OpenGL

A Fortran interface to OpenGL is implemented in the F03GL library (mirror). Even if OpenGL has been replaced by Vulkan, F03GL can still be used to create 3D graphics in the old and conservative way (that means, without GLSL and vertex shaders).

Fortran GLUT Sphere on FreeBSD
Fig. 1: The example OpenGL program on FreeBSD

An example OpenGL application that draws 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 glclear(GL_COLOR_BUFFER_BIT + GL_DEPTH_BUFFER_BIT)
    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

    interface
        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 -I/usr/local/include/ -L/usr/local/lib/
LDFLAGS = -lX11 -lXext -lGL -lGLU -lGLU -lglut
OBJ     = GLUT_fonts.o OpenGL_gl.o OpenGL_glu.o OpenGL_glut.o
SRC     = sphere.f90
BIN     = sphere

.PHONY: all clean

all: $(BIN)

$(BIN): $(OBJ)
	$(FC) -o $(BIN) $(SRC) $(OBJ) $(LDFLAGS)

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

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

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

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

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

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

$ make

Run the demo with:

$ ./sphere

References