An interface to OpenGL is provided by the F03GL library (mirror). It allows to create 3D graphics with Fortran in a conservative way, i. e., without GLSL and vertex shaders. Additional libraries, like the OpenGL Utility Library (GLU) or the OpenGL Utility Toolkit (GLUT), can be accessed as well.


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

The example OpenGL application renders a red light sphere (fig. 1):

! sphere.f90
! Fortran GLUT program to draw a red light sphere.
subroutine display() bind(c)
    use :: opengl_gl
    use :: opengl_glut
    implicit none

    call glcalllist(1)
    call glutswapbuffers
end subroutine display

subroutine gfxinit()
    use :: opengl_gl
    use :: opengl_glu
    use :: opengl_glut
    implicit none

    real(kind=glfloat) :: diffuse(4) = [ 1.0, 0.0, 0.0, 1.0 ]
    real(kind=glfloat) :: pos(4)     = [ 1.0, 1.0, 1.0, 0.0 ]

    call glnewlist(1, GL_COMPILE)
    call glutsolidsphere(1.0_gldouble, 20, 20)
    call glendlist

    call gllightfv(GL_LIGHT0, GL_DIFFUSE, diffuse)
    call gllightfv(GL_LIGHT0, GL_POSITION, pos)
    call glenable(GL_LIGHTING)
    call glenable(GL_LIGHT0)
    call glenable(GL_DEPTH_TEST)
    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 gfxinit

program main
    use :: opengl_glut
    external :: display
    external :: gfxinit
    implicit none
    integer :: rc

        subroutine display() bind(c)
        end subroutine display
    end interface

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

    rc = glutcreatewindow('Fortran GLUT sphere')

    call gfxinit
    call glutdisplayfunc(display)
    call glutmainloop
end program main

The compilation process can be simplified by writing a Makefile. The following verbose example uses Clang and Flang:

CC      = clang
FC      = flang
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)


GLUT_fonts.o: GLUT_fonts.c
	$(CC) $(CFLAGS) -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

	rm *.o *.mod $(TARGET)

Run the Makefile with BSD make (bmake on Linux):

$ make

Execute the demo with:

$ ./sphere