Fortran and OpenGL (F03GL)

Fortran and OpenGL (F03GL)

1. Introduction

Stuff needed:

Install and build f03gl on a GNU/Linux system. The programms presented here were created, compiled and run on an Ubuntu 10.04 Lucid Lynx x86_64 system using ifort. 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:

A typical compilation command could be
$ ifort -o binary source.f90 \
GLUT_fonts.o OpenGL_freeglut.o OpenGL_glut.o OpenGL_glu.o OpenGL_gl.o \
-L/usr/lib -lglut -lGL -lGLU

Compilers already incorporate many Fortran2003 features. Some are really needed in order to compile f03gl successfully:

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 typeF95/F03 typekindvalueC type
GLbyte C_SIGNED_CHARinteger1signed char
GLshort C_SHORT integer2short
GLint C_INT integer4int
GLsizei C_INT integer4int
GLbooleanC_SIGNED_CHARinteger1unsigned char
GLenum C_INT integer4unsigned int
GLbitfieldC_INT integer4unsigned int
GLcint C_INT integer4signed char
GLubyte C_SIGNED_CHARinteger1unsigned char
GLushortC_SHORT integer2unsigned short
GLuint C_INT integer4unsigned int
GLfloat C_FLOAT real 4float
GLdoubleC_DOUBLE real 8double
GLclampfC_FLOAT real 4float
GLclampdC_DOUBLE real 8double

Finally some very important ISO_C_BINDING constants:

Step by step instructions:

2. NIST f90gl

icon trivial. Simple white square.
Glutinit call simplified to call glutinit().
icon blender. Antialiased text.
icon checker. Location of image changed to c_loc(checkImage).
icon fscene. Minor changes.
icon
icon
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))
icon 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)
...

icon 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)
...
icon molehill. Change the declaration of nurb into
type(c_ptr) :: nurb
icon
icon
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.
icon scube.
icon sphere.
icon stars.
icon torus. Glutinit call simplified to call glutinit().
icon fbitfont.
icon 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.
icon 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)
icon polyoff. Glutinit call simplified to call glutinit().
icon plotfunc. Avoided name overlap for "menu_handler".

3. OpenGL Green Book

The next examples are based on Computer Graphics with OpenGL. GreenBook

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.

icon 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()
...
icon 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
...
icon 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
...
icon 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
...
icon 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()
...
icon 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)
...
icon 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
...
icon 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. RedBook

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.

icon 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.)
...
icon 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)
...
icon fgl12. Transformed cube (fig. 3-3)
icon 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)
...
icon 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()
...
icon 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
...
icon 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)
...
icon 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
icon fgl18. Clicking. Relates to fgl17.
...
hits = glRendermode(GL_RENDER)
call processhits(hits, selectBuf)
call glutPostRedisplay
...
icon 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
...
icon fgl20.
icon fgl21.

5. OpenGL Blue Book

The next examples are based on the Blue Book. BlueBook

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(len=*), 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

icon
icon
icon
icon
icon
icon
block. Display changes everytime the spacebar is hit.
icon 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
...
icon 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)
...
icon 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)
...
icon scissor.
...
! Now set scissor to smaller red sub region
call glClearColor(1.0, 0.0, 0.0, 0.0 )
call glScissor(100, 100, 600, 400)
call glEnable(GL_SCISSOR_TEST)
call glClear(GL_COLOR_BUFFER_BIT)
! Finally, an even smaller green rectangle
call glClearColor(0.0, 1.0, 0.0, 0.0)
call glScissor(200, 200, 400, 200)
call glClear(GL_COLOR_BUFFER_BIT)
! Turn scissor back off for next render
call glDisable(GL_SCISSOR_TEST)
...
icon 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)
...
icon 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)
...
icon transform.
...
! Build a rotation matrix
yRotrad = m3dDegToRad(yRot)
call m3dRotationMatrix44(transformationMatrix, yRotrad, 0., 1.,0.)

transformationMatrix(13) = 0.0
transformationMatrix(14) = 0.0
transformationMatrix(15) = -2.5

call DrawTorus(transformationMatrix)
...
icon transformgl.
...
call glLoadMatrixf(transformationMatrix)

call gltDrawTorus(0.35, 0.15, 40, 20)
...
icon 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
...
icon ambient.
icon litjet.
icon shinyjet.
icon spot.
icon shadow.
icon sphereworld2.
icon reflection.
icon
icon
smoother.
icon sphereworld3.
icon fogged.
icon motionblur.
icon pyramid. Note the use of a texture.
icon sphereworld4.
icon tunnel. More textures.
icon toon.
icon texgen.
icon cubemap.
icon snowman.
icon bezier.
...
! Set up bezier. This actually only needs
! to be called once and could go in
! the setup function

call glMap1f(GL_MAP1_VERTEX_3, & ! Type of data generated
    0.0 , & ! Lower u range
  100.0 , & ! Upper u range
     3  , & ! Distance between points in the data
NumPoints, & ! number of control points
tmp ) ! array of control points
! Enable the evaluator
call glEnable(GL_MAP1_VERTEX_3)
! Use a line strip to "connect-the-dots"
call glBegin(GL_LINE_STRIP)
do i=0,100
call glEvalCoord1f(float(i))
end do
call glEnd
...
icon bez3d.
icon bezlit.
icon nurbs.
icon nurbt.
icon
icon
icon
florida. The polygon tesselation!
icon sphereworld5.
icon
icon
icon
starrynight.
icon cubedx.
icon thunderbird.
icon 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
...
icon 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)
...
icon planets.
icon moons.
icon planets2.
icon 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
...
icon 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 fortran and f03gl!



Cyclone www.dolfyn.net