OpenGL

The F03GL library provides Fortran 2003 interface bindings to OpenGL, the OpenGL Utility Library (GLU), and the legacy OpenGL Utility Toolkit (GLUT). The library covers only the fixed-function rendering pipeline of OpenGL (immediate mode), i. e., neither GLSL nor vertex shaders are available. The SDL 2.0 Fortran bindings include interfaces to selected OpenGL and GLU routines as well.

Additionally, the F03GL contains various soure code examples from the OpenGL Green Book, Red Book, and Blue Book in Fortran.

Fortran GLUT Sphere
Fig. 1: Rendering a sphere with Fortran and F03GL

Example

The example OpenGL application renders a red light sphere (fig. 1) by creating a display list first. The display list is called in subroutine opengl_display(). The routine requires the bind(c) attribute to be interoperable with GLUT.

! sphere.f90
! Fortran GLUT/GLU program to draw a red light sphere.
module renderer
    use, intrinsic :: iso_c_binding
    use :: opengl_gl
    use :: opengl_glu
    use :: opengl_glut
    implicit none

    public :: opengl_display
    public :: opengl_init
contains
    subroutine opengl_display() bind(c)
        call glclear(GL_COLOR_BUFFER_BIT + GL_DEPTH_BUFFER_BIT)
        ! Render display list.
        call glcalllist(1)
        call glutswapbuffers()
    end subroutine opengl_display

    subroutine opengl_init()
        real(kind=GLfloat), parameter :: diffuse(4)  = [ 1.0, 0.0, 0.0, 1.0 ]
        real(kind=GLfloat), parameter :: position(4) = [ 1.0, 1.0, 1.0, 0.0 ]

        ! Create new OpenGL display list.
        call glnewlist(1, GL_COMPILE)
        call glutsolidsphere(1.0_GLdouble, 20, 20)
        call glendlist()

        ! Set lighting.
        call gllightfv(GL_LIGHT0, GL_DIFFUSE, diffuse)
        call gllightfv(GL_LIGHT0, GL_POSITION, position)
        call glenable(GL_LIGHTING)
        call glenable(GL_LIGHT0)
        call glenable(GL_DEPTH_TEST)

        ! Set projection.
        call glmatrixmode(GL_PROJECTION)
        call gluperspective(40.0_GLdouble,  1.0_GLdouble, &
                             1.0_GLdouble, 10.0_GLdouble)

        call glmatrixmode(GL_MODELVIEW)
        call glulookat(0.0_GLdouble, 0.0_GLdouble, 5.0_GLdouble, &
                       0.0_GLdouble, 0.0_GLdouble, 0.0_GLdouble, &
                       0.0_GLdouble, 1.0_GLdouble, 1.0_GLdouble)
        call gltranslatef(0.0, 0.0, -1.0)
    end subroutine opengl_init
end module renderer

program main
    use :: opengl_glut
    use :: renderer
    implicit none
    integer :: rc

    call glutinit()
    call glutinitdisplaymode(GLUT_DOUBLE + GLUT_RGB + GLUT_DEPTH)

    rc = glutcreatewindow('Fortran GLUT sphere')

    call opengl_init()
    call glutdisplayfunc(opengl_display)
    call glutmainloop()
end program main

The build process can be simplified by writing a Makefile. The following verbose example uses GNU Fortran as the default compiler:

FC      = gfortran10
CC      = gcc10
CFLAGS  = -Wall
FFLAGS  = -Wall
LDFLAGS = -I/usr/local/include/ -L/usr/local/lib/
LDLIBS  = -lX11 -lXext -lGL -lGLU -lglut
OBJ     = GLUT_fonts.o OpenGL_gl.o OpenGL_glu.o OpenGL_glut.o
SRC     = sphere.f90
TARGET  = sphere

.PHONY: all clean

all: $(TARGET)

$(TARGET): $(OBJ)
	$(FC) $(FFLAGS) $(LDFLAGS) -o $(TARGET) $(SRC) $(OBJ) $(LDLIBS)

GLUT_fonts.o: GLUT_fonts.c
	$(CC) $(CFLAGS) $(LDFLAGS) -c GLUT_fonts.c

OpenGL_gl.o: OpenGL_gl.f90
	$(FC) $(FFLAGS) -c OpenGL_gl.f90

OpenGL_glu.o: OpenGL_glu.f90
	$(FC) $(FFLAGS) -c OpenGL_glu.f90

OpenGL_glut.o: OpenGL_glut.f90
	$(FC) $(FFLAGS) -c OpenGL_glut.f90

clean:
	rm *.o *.mod $(TARGET)

Copy the files OpenGL_gl.f90, OpenGL_glu.f90, OpenGL_glut.f90, and GLUT_fonts.f90 from the F03GL archive (mirror) into the current workspace directory. Run the Makefile with make:

$ make

Execute the demo with:

$ ./sphere

Fortran Libraries

References