1. Introduction
Stuff needed:
Install g95 and build f03gl on a GNU/Linux system. The programms presented here
were created, compiled and run on openSuSE 10.3 and Debian etch systems. They have
not been tested on other platforms. Note that the OpenGL (or Mesa) development
libraries (incl. GLUT) have to be installed prior to compiling f03gl and the
examples.
More Fortran OpenGL information can be found
at math.nist.gov/f90gl. In the examples
symbolic links have been made to:
- GLUT_fonts.o (needed for bitfonts).
- opengl_gl.mod (GL module name is in lower case)
- OpenGL_gl.o
- opengl_glu.mod (GLu module name is in lower case)
- OpenGL_glu.o
- opengl_glut.mod (GLut module name is in lower case)
- OpenGL_glut.o
A typical compilation command could be
$ g95 -o binary source.f90 \
OpenGL_glut.o OpenGL_glu.o OpenGL_gl.o -L/usr/lib -lglut -lGL -lGLU
G95 already incorporates many Fortran2003 features. Some are needed for f03gl:
- Value type declaration value.
- The BIND(C) construct.
- ISO_C_BINDING.
- ENUMERATION support.
- Fortran 2003 BOZ in INT, REAL etc.
- Stream I/O has been used for reading in the textures (see below).
- Note that character strings need to be terminated with char(0) when
passed on to a C function.
Note that OpenGL relies on constants (Fortran does not know about the concept of unsigned
variables, so they have to be casted to the base form and converted by hand):
| GL type | F95/F03 type | kind | value | C type |
| GLbyte | C_SIGNED_CHAR | integer | 1 | signed char |
| GLshort | C_SHORT | integer | 2 | short |
| GLint | C_INT | integer | 4 | int |
| GLsizei | C_INT | integer | 4 | int |
| GLboolean | C_SIGNED_CHAR | integer | 1 | unsigned char |
| GLenum | C_INT | integer | 4 | unsigned int |
| GLbitfield | C_INT | integer | 4 | unsigned int |
| GLcint | C_INT | integer | 4 | signed char |
| GLubyte | C_SIGNED_CHAR | integer | 1 | unsigned char |
| GLushort | C_SHORT | integer | 2 | unsigned short |
| GLuint | C_INT | integer | 4 | unsigned int |
| GLfloat | C_FLOAT | real | 4 | float |
| GLdouble | C_DOUBLE | real | 8 | double |
| GLclampf | C_FLOAT | real | 4 | float |
| GLclampd | C_DOUBLE | real | 8 | double |
Finally some very important ISO_C_BINDING constants:
- C_NULL_CHAR for the C null character '\0' (or char(0)).
- C_PTR is interoperable with any C data pointer type.
- C_NULL_PTR is of type C_PTR; it has the value of a C null data pointer.
- C_FUNPTR is interoperable with any C function pointer type.
- C_NULL_FUNPTR is of type C_FUNPTR; it has the value of a C null function pointer.
- C_F_POINTER(CPTR, FPTR [,SHAPE]), associates a data pointer with the
target of a C pointer and specifies its shape.
- C_FUNLOC(X), returns the C address of a function pointer.
- C_LOC(X), returns the C address of the argument.
Step by step instructions:
- Create a directory (eg. 'tmpdir').
- Download the files and save them in there:
- 'cd' into the directory and unpack the tar-balls:
- tar xvzof f03gl.tgz
- tar xvzof cc.tgz
- tar xvzof rb.tgz
- tar xvzof sb.tgz
- 'cd' into the f03gl directory and hit 'make'.
- 'cd' into the other directories and hit 'make'.
2. NIST f90gl
Modifications of the original tarball and the NIST examples are available
here.
 |
trivial. Simple white square.
Glutinit call simplified to
call glutinit(). |
 |
blender. Antialiased text. |
 |
checker. Location of image changed to
c_loc(checkImage). |
 |
fscene. Minor changes. |
 |
glutdino (same result as gltdino2). Alter tobj definition to:
type(c_ptr) :: tobj
and the calls to the C functions
...
call glutesscallback(tobj, GLU_TESS_BEGIN, &
c_funloc(glbegin))
call glutesscallback(tobj, GLU_TESS_VERTEX, &
c_funloc(glvertex2fv))
call glutesscallback(tobj, GLU_TESS_END, &
c_funloc(glend))
...
and the call to the data into:
call glutessvertex(tobj, vertex, &
c_loc(data(i)%val))
|
 |
logo. Set target for:
real(GLfloat), dimension(90), target :: cva(3,30000)
and then
...
call glNormalPointer(GL_FLOAT,12,c_loc(cva(1,n0)))
call glVertexPointer(3,GL_FLOAT,12, &
c_loc(cva(1,n0+1)) )
...
Next glIsList returns an integer... so
...
if(glIsList(thelist)==1) &
call gldeletelists(thelist,1_glsizei)
...
|
 |
modview. Add //char(0) and create the menu with:
...
button_left = glutCreateMenu(set_left_button)
call glutAddMenuEntry('rotate'//char(0),ROTATE)
call glutAddMenuEntry('zoom'//char(0),ZOOM)
...
|
 |
molehill. Change the declaration of nurb into
type(c_ptr) :: nurb
|
 |
olympic (same result as olympic3).
Mismatch of interface for Key:
subroutine Key(%VAL(ikey), %VAL(x), %VAL(y))
use olympic_mod
integer(GLubyte), intent(inout):: ikey
integer(glInt), intent(inout):: x, y
end subroutine key
Finally ikey is GLubyte and not glInt.
|
 |
scube. |
 |
sphere. |
 |
stars. |
 |
torus. Glutinit call simplified to
call glutinit(). |
 |
fbitfont. |
 |
eps. In select constructs as in:
case (int(GL_PASS_THROUGH_TOKEN)) the
GL_PASS_THROUGH_TOKEN should be an integer... and not a real.
In OpenGL_gl.f90 however they were defined as floats.
Finally glIsList returns an integer.
|
 |
array. Introduce
type(c_ptr), pointer :: cstr
and change the pointer to the string into:
cstr=glGetString(GL_VENDOR)
call c_f_pointer(cptr=cstr, fptr=str)
|
 |
polyoff. Glutinit call simplified to
call glutinit(). |
 |
plotfunc. Avoided name overlap for "menu_handler". |
3. OpenGL Green Book
The next examples are based on Computer Graphics with OpenGL.
This new edition is a complete revision, bringing the text up to date with
current advances in computer graphics technology and applications. Assuming
readers have no prior familiarity with computer graphics, the authors' both
authorities in their field's present basic principles for design, use, and
understanding of computer graphics systems using their well-known, and
accessible writing style. It includes an exploration of GL, PHIGS, PHIGS+, GKS
and other graphics libraries and covers topics such as distributed ray tracing,
radiosity, physically based modeling, particle systems, and visualization
techniques. For professionals in any area of computer graphics: CAD, Animation,
Software Design, etc.
The g95 files are available
here.
 |
fgl01. Open a window and draw a red line.
...
call glClear(GL_COLOR_BUFFER_BIT)
call glColor3f(1.0,0.0,0.0)
call glBegin(GL_LINES)
call glVertex2i(180,20)
call glVertex2i( 20,80)
call glEnd()
...
|
 |
fgl03. Using display lists.
...
integer(kind=GLuint) :: Hexagon
...
Hexagon = glGenLists(1)
call glNewList( Hexagon, GL_COMPILE)
call glColor3f( 1.0, 0.0, 0.0 )
call glBegin(GL_POLYGON)
do i=1,7
...
call glVertex2i( ix, iy)
end do
call glEnd
call glEndList
...
|
 |
fgl04. A bar chart with characters.
...
call glColor3f(0.0,0.0,0.0)
xRaster = 20
do i=1,12
call glRasterPos2i(xraster,yraster)
do j=3*(i-1)+1,3*(i-1)+3
call glutBitmapCharacter( &
GLUT_BITMAP_HELVETICA_12, &
iachar(label(j)))
end do
xraster=xraster+50
end do
...
|
 |
fgl05. Three dimensional viewing example.
...
call glColor3f(0.0,1.0,0.0)
call glPolygonMode(GL_FRONT,GL_FILL)
call glPolygonMode(GL_BACK,GL_LINE)
call glBegin(GL_QUADS)
call glVertex3f( 0.0, 0.0, 0.0)
call glVertex3f(100.0, 0.0, 0.0)
call glVertex3f(100.0, 100.0, 0.0)
call glVertex3f( 0.0, 100.0, 0.0)
call glEnd
...
|
 |
fgl06. A perspective view of the five GLUT polyhedra, scaled and positioned
within the display window.
...
call glutWirecube(1.0_gldouble)
...
call glutWireDodecahedron()
...
call glutWireTetrahedron()
...
call glutWireOctahedron()
...
call glutWireIcosahedron()
...
|
 |
fgl07. Display of the GLUT sphere, GLUT cone and GLUT cylinder
(using quadrics).
...
type(c_ptr) :: ptr = c_null_ptr
...
ptr = gluNewQuadric()
call gluQuadricDrawStyle(ptr,GLU_LINE)
call gluCylinder(ptr,s1,s2,s3,6,4)
...
|
 |
fgl08. Mouse droppings.
subroutine mouse(ibutton,iaction,ix,iy)
...
integer(GLint), intent(in), value :: &
ibutton, iaction, ix, iy
...
if( ibutton == GLUT_LEFT_BUTTON .and. &
iaction == GLUT_DOWN )then
call plotpoint(ix,winHeight-iy)
call glFlush()
endif
...
|
 |
fgl09. Example of an interactive mouse procedure.
subroutine drawline(p1,p2)
...
type(Point), intent(in) :: p1, p2
...
call glBegin(GL_LINES)
call glVertex2i(p1%x,p1%y)
call glVertex2i(p2%x,p2%y)
call glEnd()
...
|
4. OpenGL Red Book
These examples are based on the Red Book.

The OpenGL Programming Guide, Fifth Edition, provides definitive and
comprehensive information on OpenGL and the OpenGL Utility Library. This fifth edition of the
'red book' describes the latest features of OpenGL Versions 1.5 and
2.0, including the introduction of the OpenGL Shading Language. You will find
clear explanations of OpenGL functionality and many basic computer graphics
techniques, such as building and rendering 3D models; interactively viewing
objects from different perspective points; and using shading, lighting, and
texturing effects for greater realism. In addition, this book provides in-depth
coverage of advanced techniques, including texture mapping, antialiasing, fog
and atmospheric effects, NURBS, image processing, and more.
The g95 files are available
here.
 |
fgl10. Wide stippled lines (fig. 2-9).
...
call glLineWidth(5.0)
! dotted
call glLineStipple(1,z'0101'_Glushort)
call drawline( 50.,100.,150.,100.)
! dashed
call glLineStipple(1,z'00FF'_Glushort)
call drawline(150.,100.,250.,100.)
! dash dot dash
call glLineStipple(1,z'1C47'_Glushort)
call drawline(250.,100.,350.,100.)
...
|
 |
fgl11. Polygon stipple patterns (fig. 2-11).
...
call glenable(GL_POLYGON_STIPPLE)
call glpolygonstipple(fly)
call glrectf(125.0,25.0,225.,125.)
call glpolygonstipple(halftone)
call glrectf(225.0,25.0,325.,125.)
call gldisable(GL_POLYGON_STIPPLE)
...
|
 |
fgl12. Transformed cube (fig. 3-3) |
 |
fgl13. Clipped wireframe sphere (fig. 3-23).
...
! clip lower half
call glClipPlane(GL_CLIP_PLANE0, eqn1)
call glEnable(GL_CLIP_PLANE0)
! clip left half
call glClipPlane(GL_CLIP_PLANE1, eqn2)
call glEnable(GL_CLIP_PLANE1)
call glRotatef(90.0, 1.0, 0.0, 0.0)
call glutWireSphere(radius, 20,16)
...
|
 |
fgl14. Planetary system.
...
! zon
call glutWireSphere(radzon,20,16)
! planeet
call glRotatef(Year, 0.0,1.0,0.0)
call glTranslatef(2.8,0.0,0.0)
call axis(0.4)
call glRotatef(Day, 0.0,1.0,0.0)
call glColor3f(1.0,1.0,1.0)
call glPushMatrix()
call glRotatef(20.0, 0.0,0.0,1.0)
call glutWireSphere(radplan,10,8)
call glPopMatrix()
...
|
 |
fgl15. Plate 11. A smooth shaded triangle.
...
call glBegin(GL_TRIANGLES)
call glColor3f(1.0,0.0,0.0)
call glVertex2f(5.0,5.0)
call glColor3f(0.0,1.0,0.0)
call glVertex2f(25.0,5.0)
call glColor3f(0.0,0.0,1.0)
call glVertex2f(5.0,25.0)
call glEnd
...
|
 |
fgl16. A lit sphere.
...
call glShadeModel(GL_SMOOTH)
call glMaterialfv(GL_FRONT, GL_SPECULAR, spec)
call glMaterialfv(GL_FRONT, GL_SHININESS, shine)
call glLightfv(GL_LIGHT0, GL_POSITION, pos)
call glLightfv(GL_LIGHT0, GL_DIFFUSE, white)
call glLightfv(GL_LIGHT0, GL_SPECULAR, white)
call glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb)
call glEnable(GL_LIGHTING)
call glEnable(GL_LIGHT0)
call glEnable(GL_DEPTH_TEST)
...
call glutSolidSphere(radius,32,32)
...
|
 |
fgl17. Triangle selection example.
Depth values (which are in the range [0,1]) are multiplied
by 2^32 - 1, before being placed in the hit record
as an
unsigned integer. So this needs to be converted
into something usable:
double precision function &
convert_uint_to_double( uint )
...
! check highest bit
if( btest(uint,31) )then
big = 4294967295.0
else
big = 0.0
endif
! clear highest bit
iconv = ibclr(uint,31)
! simple type conversion:
convert_uint_to_double = dble(iconv) + big
end function convert_uint_to_double
|
 |
fgl18. Clicking. Relates to fgl17.
...
hits = glRendermode(GL_RENDER)
call processhits(hits, selectBuf)
call glutPostRedisplay
...
|
 |
fgl19. Shows the use of 'PassThrough tokens'.
...
if( mode == GL_FEEDBACK ) call glPassThrough(2.0)
call glBegin(GL_POINTS)
call glNormal3f( 0.0, 0.0, 1.0)
call glVertex3f( 50.0, 50.0, 0.0)
call glEnd
...
|
 |
fgl20. |
 |
fgl21. |
5. OpenGL Blue Book
The next examples are based on the Blue Book.

OpenGL SuperBible, Fourth Edition, begins by illuminating the core techniques
of 'classic' OpenGL graphics programming, from drawing in space to geometric
transformations, from lighting to texture mapping. The authors cover newer
OpenGL capabilities, including OpenGL 2.1's powerful programmable pipeline,
vertex and fragment shaders, and advanced buffers. They also present thorough,
up-to-date introductions to OpenGL implementations on multiple platforms,
including Windows, Mac OS X, GNU/Linux, UNIX, and embedded systems. The
reference pages for all of the OpenGL 2.1 commands are included!
These examples rely on textures. The function interface is:
interface
function fgltLoadTGA(FileName,width,height,components,eform,image)
use, intrinsic :: iso_c_binding
type(c_ptr), target :: fgltloadTGA
character, dimension(*), intent(IN) :: FileName
integer(c_int), intent(out) :: width, height
integer(c_int), intent(out) :: components, eform
integer(c_char), dimension(:), allocatable, &
intent(out), target :: image
end function
end interface
The g95 files are available
here.






|
block. Display changes everytime the spacebar is hit. |
 |
pointsz. Loop around in a circle three times. Set the point size and draw
the point.
...
! Specify the point size
call glPointSize(curSize)
! Draw the point
call glBegin(GL_POINTS)
call glVertex3f(x, y, z)
call glEnd
...
|
 |
triangle. Explores depths and culling.
...
! Create the Menu
im = glutCreateMenu(ProcessMenu)
call glutAddMenuEntry &
('Toggle depth test'//char(0),1)
call glutAddMenuEntry &
('Toggle cull backface'//char(0),2)
call glutAddMenuEntry &
('Toggle outline back'//char(0),3)
call glutAttachMenu(GLUT_RIGHT_BUTTON)
...
|
 |
pstipple.
...
! Black background
call glClearColor(0.0, 0.0, 0.0, 1.0 )
! Set drawing color to red
call glColor3f(1.0, 0.0, 0.0)
! Enable polygon stippling
call glEnable(GL_POLYGON_STIPPLE)
! Specify a specific stipple pattern
call glPolygonStipple(fire)
...
|
 |
scissor. |
 |
stencil.
...
! Now draw except where the stencil pattern is 0x1
! dont make any further changes to the stencil buffer
call glStencilFunc(GL_NOTEQUAL, z'01', z'01')
call glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP)
! Now draw red bouncing square
! (x and y) are modified by a timer function
call glColor3f(1.0, 0.0, 0.0)
call glRectf(x, y, x + rsize, y - rsize)
...
|
 |
solar.
...
! Move the light after we draw the sun!
call glLightfv(GL_LIGHT0,GL_POSITION,lightPos)
! Rotate coordinate system
call glRotatef(fEarthRot, 0.0, 1.0, 0.0)
! Draw the Earth
call glColor3f(0.0,0.0,1.0)
call glTranslatef(105.0,0.0,0.0)
call glutSolidSphere(dble(15.), 30, 17)
...
|
 |
transform. |
 |
transformgl. |
 |
sphereworld1. Introduces OOP-style GLframes class:
...
! Default. At the origin, looking
! down the positive Z axis.
type :: GLFrame
sequence
real,dimension(3) :: Org = (/0.0,0.0, 0.0/)
real,dimension(3) :: Up = (/0.0,1.0, 0.0/)
real,dimension(3) :: Frw = (/0.0,0.0,-1.0/)
end type GLFrame
...
|
 |
ambient. |
 |
litjet. |
 |
shinyjet. |




|
spot. |
 |
shadow. |
 |
sphereworld2. |
 |
reflection. |
 |
smoother. |
 |
sphereworld3. |
 |
fogged. |
 |
motionblur. |
 |
pyramid. |
 |
sphereworld4. |
 |
tunnel. |
 |
toon. |
 |
texgen. |
 |
cubemap. |
 |
snowman. |
 |
bezier. |
 |
bez3d. |
 |
bezlit. |
 |
nurbs. |
 |
nurbt. |
 |
florida. The polygon tesselation fails! This
is the only case of this large set which failed.
|
 |
sphereworld5. |
 |
starrynight. |
 |
cubedx. |
 |
thunderbird. |
 |
thunderbirdgl. Introduces OOP-style CTriangleMeshes:
...
type :: CTriangleMesh
integer(GLuint), dimension(:), allocatable :: Indexes
real(GLfloat), dimension(:), allocatable :: Verts
real(GLfloat), dimension(:), allocatable :: Norms
real(GLfloat), dimension(:), allocatable :: TexCoords
integer(GLint) :: nMaxIndexes = 0
integer(GLint) :: nNumIndexes = 0
integer(GLint) :: nNumVerts = 0
end type CTriangleMesh
...
|
 |
thunderbirdvbo. Same idea but now with Vertex Buffer Objects:
...
! Texture coordinates
call glBindBuffer(GL_ARRAY_BUFFER, &
self%bufferObjects(TEXTURE_DATA))
call glTexCoordPointer(2, GL_FLOAT, 0, c_null_ptr)
! Indexes
call glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, &
self%bufferObjects(INDEX_DATA))
call glDrawElements(GL_TRIANGLES, self%nNumIndexes, &
GL_UNSIGNED_INT, c_null_ptr)
...
|
 |
planets. |
 |
moons. |
 |
planets2. |
 |
oocquery. Chapter 13, demonstrates occlusion queries.
...
if( occlusionDetection == GL_TRUE )then
! Check if this sphere would be occluded
call glGetQueryObjectiv(queryIDs(i),&
GL_QUERY_RESULT, passingSamples(i))
if( passingSamples(i) == 0 ) occluded = GL_TRUE
endif
...
|
 |
shadowmap. |
6. Warning
You need to know what to do. The codes and files are 'as is'. The
software and files are there to give you an impression only without any guarantee
whatsoever.
Enjoy g95 and f03gl!