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 renderer_display(). The routine requires the bind(c) attribute to be interoperable with GLUT.

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

    public :: renderer_display
    public :: renderer_init
contains
    subroutine renderer_display() bind(c)
        call glClear(ior(GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT))

        ! Render display list.
        call glCallList(1)
        call glutSwapBuffers()
    end subroutine renderer_display

    subroutine renderer_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 renderer_init
end module renderer

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

    flags = ior(GLUT_DOUBLE, ior(GLUT_RGB, GLUT_DEPTH))

    call glutInit()
    call glutInitDisplayMode(flags)

    rc = glutCreateWindow('Fortran GLUT sphere')

    call renderer_init()
    call glutDisplayFunc(renderer_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:

.POSIX:

FC      = gfortran13
CC      = gcc13
CFLAGS  = -Wall
FFLAGS  = -Wall
LDFLAGS = -I/usr/local/include -L/usr/local/lib
LDLIBS  = -lGLU -lglut -lGL -lX11 -lXext
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