! Example showing how to use OpenGL's feedback mode to capture
! transformed vertices and output them as Encapsulated PostScript.
! Handles limited hidden surface removal by sorting and does
! smooth shading (albeit limited due to PostScript).
! Modified for use with PHAML graphics, William F. Mitchell, 5/15/97
! Translated to Fortran by William F. Mitchell, 6/16/00
! Extended to an example for f90gl by William F. Mitchell, 1/3/03
! Translated to F by William F. Mitchell, 1/23/04
! This is a translation of a C program written by Mark J. Kilgard. The
! original C program had the following notice:
! /* Copyright (c) Mark J. Kilgard, 1997. */
!
! /* This program is freely distributable without licensing fees
! and is provided without guarantee or warrantee expressed or
! implied. This program is -not- in the public domain. */
! (end of Mark's notice)
! The Fortran version is a contribution of NIST, not subject to copyright.
! The OpenGL image must be drawn in display list number 1, since this
! routine uses "call glCallList(1_GLint)" to render the image.
! The interface for the public routine is:
! subroutine outputEPS(bsize, doSort, filename)
! integer, intent(in) :: bsize
! logical, intent(in) :: doSort
! character(len=*), intent(in), optional :: filename
! bsize is the amount of space (in words) to allocate for the feedback buffer.
! doSort indicates whether or not to sort the rendered objects, back to front.
! With F, doSort is ignored (because my sort routine is an old FORTRAN 77
! routine from Netlib and I don't want to translate it).
! filename is the name of the file to which to write the postscript. If it
! is not present, the feedback buffer is printed (for debugging)
module rendereps
use opengl_gl
implicit none
private
public :: outputEPS
real(kind=GLfloat), private, dimension(1) :: pointSize
character(len=74), private, dimension(25) :: gouraudtriangleEPS = (/ &
"/bd{bind def}bind def /triangle { aload pop setrgbcolor aload pop 5 3 ",&
"roll 4 2 roll 3 2 roll exch moveto lineto lineto closepath fill } bd ",&
"/computediff1 { 2 copy sub abs threshold ge {pop pop pop true} { exch 2 ",&
"index sub abs threshold ge { pop pop true} { sub abs threshold ge } ifelse",&
"} ifelse } bd /computediff3 { 3 copy 0 get 3 1 roll 0 get 3 1 roll 0 get ",&
"computediff1 {true} { 3 copy 1 get 3 1 roll 1 get 3 1 roll 1 get ",&
"computediff1 {true} { 3 copy 2 get 3 1 roll 2 get 3 1 roll 2 get ",&
"computediff1 } ifelse } ifelse } bd /middlecolor { aload pop 4 -1 roll ",&
"aload pop 4 -1 roll add 2 div 5 1 roll 3 -1 roll add 2 div 3 1 roll add 2 ",&
"div 3 1 roll exch 3 array astore } bd /gouraudtriangle { computediff3 { 4 ",&
"-1 roll aload 7 1 roll 6 -1 roll pop 3 -1 roll pop add 2 div 3 1 roll add ",&
"2 div exch 3 -1 roll aload 7 1 roll exch pop 4 -1 roll pop add 2 div 3 1 ",&
"roll add 2 div exch 3 -1 roll aload 7 1 roll pop 3 -1 roll pop add 2 div 3",&
"1 roll add 2 div exch 7 3 roll 10 -3 roll dup 3 index middlecolor 4 1 roll",&
"2 copy middlecolor 4 1 roll 3 copy pop middlecolor 4 1 roll 13 -1 roll ",&
"aload pop 17 index 6 index 15 index 19 index 6 index 17 index 6 array ",&
"astore 10 index 10 index 14 index gouraudtriangle 17 index 5 index 17 ",&
"index 19 index 5 index 19 index 6 array astore 10 index 9 index 13 index ",&
"gouraudtriangle 13 index 16 index 5 index 15 index 18 index 5 index 6 ",&
"array astore 12 index 12 index 9 index gouraudtriangle 17 index 16 index ",&
"15 index 19 index 18 index 17 index 6 array astore 10 index 12 index 14 ",&
"index gouraudtriangle 18 {pop} repeat } { aload pop 5 3 roll aload pop 7 3",&
"roll aload pop 9 3 roll 4 index 6 index 4 index add add 3 div 10 1 roll 7 ",&
"index 5 index 3 index add add 3 div 10 1 roll 6 index 4 index 2 index add ",&
"add 3 div 10 1 roll 9 {pop} repeat 3 array astore triangle } ifelse } bd " &
/)
! OpenGL's GL_3D_COLOR feedback vertex format. Use as offsets from base entry.
integer, private, parameter :: X=0, Y=1, Z=2, CRED=3, CGREEN=4, CBLUE=5, ALPHA=6
!type DepthIndex
! integer(kind=GLint) :: ptr
! real(kind=GLfloat) :: depth
!end type DepthIndex
private :: print3DcolorVertex, spewPrimitiveEPS, printBuffer, &
spewUnsortedFeedback, spewWireFrameEPS
contains
! ------------------
subroutine print3DcolorVertex(count, buffer)
! ------------------
integer(kind=GLint), intent(inout) :: count
real(kind=GLfloat), intent(in), dimension(:) :: buffer
! Write contents of one vertex to stdout.
!write(unit=*,fmt="(' ',7(f4.2,' '))") buffer(count:count+6)
write(unit=*,fmt="(a2,7(f4.2))") " ",buffer(count:count+6)
count = count + 7
end subroutine print3DcolorVertex
! -----------
subroutine printBuffer(bsize, buffer)
! -----------
integer, intent(in) :: bsize
real(kind=GLfloat),intent(in),dimension(:) :: buffer
integer(kind=GLint) :: count
integer(kind=GLint) :: token
integer :: nvertices, i
count = 1
do
if (count >= bsize) exit
token = buffer(count)
count = count + 1
select case (token)
case (GL_PASS_THROUGH_TOKEN)
write(unit=*,fmt=*) "GL_PASS_THROUGH_TOKEN"
write(unit=*,fmt="(a2,f4.2)") " ",buffer(count)
count = count + 1
case (GL_POINT_TOKEN)
write(unit=*,fmt=*) "GL_POINT_TOKEN"
call print3DcolorVertex(count, buffer)
case (GL_LINE_TOKEN)
write(unit=*,fmt=*) "GL_LINE_TOKEN"
call print3DcolorVertex(count, buffer)
call print3DcolorVertex(count, buffer)
case (GL_LINE_RESET_TOKEN)
write(unit=*,fmt=*) "GL_LINE_RESET_TOKEN"
call print3DcolorVertex(count, buffer)
call print3DcolorVertex(count, buffer)
case (GL_POLYGON_TOKEN)
write(unit=*,fmt=*) "GL_POLYGON_TOKEN"
nvertices = buffer(count)
count = count + 1
do i=1,nvertices
call print3DcolorVertex(count, buffer)
end do
case default
write(unit=*,fmt=*) "Incomplete implementation. Unexpected token ",token
end select
end do
end subroutine printBuffer
! ----------------
subroutine spewPrimitiveEPS(file, loc, buffer)
! ----------------
integer, intent(in) :: file
integer, intent(inout) :: loc
real(kind=GLfloat), intent(in),dimension(:) :: buffer
integer(kind=GLint) :: token
integer :: nvertices, i
real(kind=GLfloat) :: red, green, blue
logical :: smooth
real(kind=GLfloat) :: dx, dy, dr, dg, db, absR, absG, absB, colormax
integer :: steps
real(kind=GLfloat) :: xstep, ystep, rstep, gstep, bstep
real(kind=GLfloat) :: xnext, ynext, rnext, gnext, bnext, distance
! Lower for better smooth lines.
real(kind=GLfloat), parameter :: EPS_SMOOTH_LINE_FACTOR = 0.06
token = buffer(loc)
loc = loc + 1
select case (token)
case (GL_LINE_RESET_TOKEN, GL_LINE_TOKEN)
dr = buffer(loc+7+CRED) - buffer(loc+CRED)
dg = buffer(loc+7+CGREEN) - buffer(loc+CGREEN)
db = buffer(loc+7+CBLUE) - buffer(loc+CBLUE)
if (dr /= 0 .or. dg /= 0 .or. db /= 0) then
! Smooth shaded line.
dx = buffer(loc+7+X) - buffer(loc+X)
dy = buffer(loc+7+Y) - buffer(loc+Y)
distance = sqrt(dx * dx + dy * dy)
absR = abs(dr)
absG = abs(dg)
absB = abs(db)
colormax = max(absR, absG, absB)
steps = max(1.0_GLfloat, colormax * distance * EPS_SMOOTH_LINE_FACTOR)
xstep = dx / steps
ystep = dy / steps
rstep = dr / steps
gstep = dg / steps
bstep = db / steps
xnext = buffer(loc+X)
ynext = buffer(loc+Y)
rnext = buffer(loc+CRED)
gnext = buffer(loc+CGREEN)
bnext = buffer(loc+CBLUE)
! Back up half a step; we want the end points to be
! exactly the their endpoint colors.
xnext = xnext - xstep / 2.0_GLfloat
ynext = ynext - ystep / 2.0_GLfloat
rnext = rnext - rstep / 2.0_GLfloat
gnext = gnext - gstep / 2.0_GLfloat
bnext = bnext - bstep / 2.0_GLfloat
else
! Single color line.
steps = 0
endif
write(unit=file,fmt=*) buffer(loc+CRED),buffer(loc+CGREEN),buffer(loc+CBLUE),&
" setrgbcolor"
write(unit=file,fmt=*) buffer(loc+X),buffer(loc+Y)," moveto"
do i=1,steps
xnext = xnext + xstep
ynext = ynext + ystep
rnext = rnext + rstep
gnext = gnext + gstep
bnext = bnext + bstep
write(unit=file,fmt=*) xnext, ynext, " lineto stroke"
write(unit=file,fmt=*) rnext, gnext, bnext, " setrgbcolor"
write(unit=file,fmt=*) xnext, ynext, " moveto"
end do
write(unit=file,fmt=*) buffer(loc+7+X), buffer(loc+7+Y), " lineto stroke"
loc = loc + 14 ! Each vertex element in the feedback buffer is 7 GLfloats.
case (GL_POLYGON_TOKEN)
nvertices = buffer(loc)
loc = loc + 1
if (nvertices > 0) then
red = buffer(loc+CRED)
green = buffer(loc+CGREEN)
blue = buffer(loc+CBLUE)
smooth = .false.
do i=1,nvertices-1
if (red /= buffer(loc+7*i+CRED) .or. green /= buffer(loc+7*i+CGREEN) &
.or. blue /= buffer(loc+7*i+CBLUE)) then
smooth = .true.
exit
endif
end do
if (smooth) then
! Smooth shaded polygon; varying colors at vetices.
! Break polygon into "nvertices-2" triangle fans.
do i=1,nvertices-2
write(unit=file,fmt=*) "[",buffer(loc+X),buffer(loc+7*i+X), &
buffer(loc+7*(i+1)+X),buffer(loc+Y),buffer(loc+7*i+Y), &
buffer(loc+7*(i+1)+Y),"] [",buffer(loc+CRED),buffer(loc+CGREEN), &
buffer(loc+CBLUE),"] [",buffer(loc+7*i+CRED),buffer(loc+7*i+CGREEN), &
buffer(loc+7*i+CBLUE),"] [",buffer(loc+7*(i+1)+CRED), &
buffer(loc+7*(i+1)+CGREEN),buffer(loc+7*(i+1)+CBLUE), &
"] gouraudtriangle"
end do
else
! Flat shaded polygon; all vertex colors the same.
write(unit=file,fmt=*) "newpath"
write(unit=file,fmt=*) red, green, blue, " setrgbcolor"
! Draw a filled triangle.
write(unit=file,fmt=*) buffer(loc+X),buffer(loc+Y)," moveto"
do i=1,nvertices-1
write(unit=file,fmt=*) buffer(loc+7*i+X),buffer(loc+7*i+Y)," lineto"
end do
write(unit=file,fmt=*) "closepath fill"
write(unit=file,fmt=*) ""
endif
endif
loc = loc + nvertices * 7 ! Each vertex element in the
! feedback buffer is 7 GLfloats.
case (GL_POINT_TOKEN)
write(unit=file,fmt=*) buffer(loc+CRED),buffer(loc+CGREEN),buffer(loc+CBLUE), &
" setrgbcolor"
write(unit=file,fmt=*) buffer(loc+X),buffer(loc+Y),pointSize(1)/2.0,0, &
360," arc fill"
write(unit=file,fmt=*) ""
loc = loc + 7 ! Each vertex element in the feedback buffer is 7 GLfloats.
case default
write(unit=*,fmt=*) "Incomplete implementation. Unexpected token ",token
end select
end subroutine spewPrimitiveEPS
! --------------------
subroutine spewUnsortedFeedback(file, bsize, buffer)
! --------------------
integer, intent(in) :: file, bsize
real(kind=GLfloat), intent(in), dimension(:) :: buffer
integer :: loc
loc = 1
do
if (loc >= bsize) exit
call spewPrimitiveEPS(file, loc, buffer)
end do
end subroutine spewUnsortedFeedback
!! ------------------
!subroutine spewSortedFeedback(file, bsize, buffer)
!! ------------------
!integer, intent(in) :: file, bsize
!real(GLfloat), intent(in) :: buffer(:)
!
! integer(GLint) :: token
! integer :: loc
! real(GLfloat) :: depthSum
! integer :: nprimitives, item
! type(DepthIndex), allocatable :: prims(:)
! integer :: nvertices, i
! real :: ydum(1)
!
!! Count how many primitives there are.
! nprimitives = 0
! loc = 1
! do while (loc < bsize)
! token = buffer(loc)
! loc = loc + 1
! select case (token)
! case (GL_LINE_TOKEN, GL_LINE_RESET_TOKEN)
! loc = loc + 14
! nprimitives = nprimitives + 1
! case (GL_POLYGON_TOKEN)
! nvertices = buffer(loc)
! loc = loc + 1
! loc = loc + 7*nvertices
! nprimitives = nprimitives + 1
! case (GL_POINT_TOKEN)
! loc = loc + 7
! nprimitives = nprimitives + 1
! case default
! write(unit=*,fmt=*) "Incomplete implementation. Unexpected token ",token
! end select
! end do
!
!! Allocate an array of pointers that will point back at
!! primitives in the feedback buffer. There will be one
!! entry per primitive. This array is also where we keep the
!! primitive's average depth. There is one entry per
!! primitive in the feedback buffer.
! allocate(prims(nprimitives))
!
! item = 1
! loc = 1
! do while (loc < bsize)
! prims(item)%ptr = loc ! Save this primitive's location.
! token = buffer(loc)
! loc = loc + 1
! select case (token)
! case (GL_LINE_TOKEN, GL_LINE_RESET_TOKEN)
! depthSum = buffer(loc+Z) + buffer(loc+7+Z)
! prims(item)%depth = depthSum / 2.0
!! WFM to force triangle edges on top of filled triangle
!! prims(item)%depth = prims(item)%depth - .0001
! loc = loc + 14
! case (GL_POLYGON_TOKEN)
! nvertices = buffer(loc)
! loc = loc + 1
! depthSum = buffer(loc+Z)
! do i=1,nvertices-1
! depthSum = depthSum + buffer(loc+7*i+Z)
! end do
! prims(item)%depth = depthSum / nvertices
! loc = loc + 7*nvertices
! case (GL_POINT_TOKEN)
! prims(item)%depth = buffer(loc+Z)
! loc = loc + 7
! case default
! write(unit=*,fmt=*) "Incomplete implementation. Unexpected token ",token
! end select
! item = item + 1
! end do
!
!! Sort the primitives back to front.
!! call ssort(prims, ydum, nprimitives, -1)
!
!! XXX Understand that sorting by a primitives average depth
!! doesn't allow us to disambiguate some cases like self
!! intersecting polygons. Handling these cases would require
!! breaking up the primitives. That's too involved for this
!! example. Sorting by depth is good enough for lots of
!! applications.
!
!! Emit the Encapsulated PostScript for the primitives in
!! back to front order.
! do item=1,nprimitives
! call spewPrimitiveEPS(file, prims(item)%ptr, buffer)
! end do
!
! deallocate(prims)
!end subroutine spewSortedFeedback
! ----------------
subroutine spewWireFrameEPS(file, doSort, bsize, buffer, creator)
! ----------------
integer, intent(in) :: file, bsize
logical, intent(in) :: doSort
real(kind=GLfloat), intent(in), dimension(:) :: buffer
character(len=*), intent(in) :: creator
real(kind=GLfloat), dimension(4) :: clearColor, viewport
real(kind=GLfloat), dimension(1) :: lineWidth
integer :: i
! Lower for better (slower) smooth shading.
real(kind=GLfloat), parameter :: EPS_GOURAUD_THRESHOLD=0.1
! Read back a bunch of OpenGL state to help make the EPS
! consistent with the OpenGL clear color, line width, point
! bsize, and viewport.
call glGetFloatv(GL_VIEWPORT, viewport)
call glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColor)
call glGetFloatv(GL_LINE_WIDTH, lineWidth)
call glGetFloatv(GL_POINT_SIZE, pointSize)
! Emit EPS header. */
write(unit=file,fmt="(a)") "%!PS-Adobe-2.0 EPSF-2.0"
write(unit=file,fmt="(a)") "%%Creator: eps.f90 (using OpenGL feedback)"
write(unit=file,fmt="(a,4i10)") "%%BoundingBox: ", int(viewport)
write(unit=file,fmt="(a)") "%%EndComments"
write(unit=file,fmt=*) ""
write(unit=file,fmt=*) "gsave"
write(unit=file,fmt=*) ""
! Output Frederic Delhoume's "gouraudtriangle" PostScript fragment.
write(unit=file,fmt=*) "% the gouraudtriangle PostScript fragement below is free"
write(unit=file,fmt=*) "% written by Frederic Delhoume ([email protected])"
write(unit=file,fmt=*) "/threshold ",EPS_GOURAUD_THRESHOLD," def"
do i=1,size(gouraudtriangleEPS)
write(unit=file,fmt=*) gouraudtriangleEPS(i)
end do
write(unit=file,fmt=*) ""
write(unit=file,fmt=*) lineWidth(1)," setlinewidth"
! Clear the background like OpenGL had it.
write(unit=file,fmt=*) clearColor(1:3)," setrgbcolor"
write(unit=file,fmt=*) viewport," rectfill"
write(unit=file,fmt=*) ""
! if (doSort) then
! call spewSortedFeedback(file, bsize, buffer)
! else
call spewUnsortedFeedback(file, bsize, buffer)
! endif
! Emit EPS trailer.
write(unit=file,fmt=*) "grestore"
write(unit=file,fmt=*) ""
! WFM I don't know why Mark put this comment instead of showpage, unless some
! apps that take eps input don't like it (ghostview is fine with it)
! write(unit=file,fmt=*) "%Add `showpage' to the end of this file to be able to print to a printer."
write(unit=file,fmt=*) "% 'showpage' is needed to print to a printer, but there"
write(unit=file,fmt=*) "% may be some apps for which it must be removed"
write(unit=file,fmt=*) "showpage"
close(file)
end subroutine spewWireFrameEPS
subroutine outputEPS(bsize, doSort, filename)
integer, intent(in) :: bsize
logical, intent(in) :: doSort
character(len=*), intent(in), optional :: filename
real(kind=GLfloat), allocatable, dimension(:) :: feedbackBuffer
integer(kind=GLint) :: returned, idum
integer :: file, iostat
logical :: opened
allocate(feedbackBuffer(bsize))
call glFeedbackBuffer(bsize, GL_3D_COLOR, feedbackBuffer)
idum = glRenderMode(GL_FEEDBACK)
call glCallList(1_GLint)
returned = glRenderMode(GL_RENDER)
if (present(filename)) then
file = 11
do
inquire(unit=file,opened=opened)
if (.not. opened) exit
file = file + 1
end do
open(unit=file,file=filename,iostat=iostat,status="NEW",action="WRITE")
if (iostat==0) then
call spewWireFrameEPS(file, doSort, returned, feedbackBuffer, "rendereps")
else
write(unit=*,fmt=*) "Could not open ", filename
endif
else
! Helps debugging to be able to see the decode feedback buffer as text.
call printBuffer(returned, feedbackBuffer)
endif
deallocate(feedbackBuffer)
end subroutine outputEPS
end module rendereps
!-----------------------------------------------------------
!
! Use the fscene.f90 program to illustrate use of rendereps. Contrast the
! remainder of this file to the file fscene.f90.
! GLUT Fortran program to render simple red scene.
! In a risky move, this program assumes that the default kind of
! integer is the same as glint and glsizei and also that the
! default real is the same kind as glfloat
module callbacks
private
public :: mainmenu, display, myinit, submenu
contains
subroutine display()
use opengl_gl
use opengl_glu
use opengl_glut
call gldeletelists(1_gluint, 1_glsizei)
! put the display in list 1 for rendereps
call glnewlist(1_gluint, gl_compile_and_execute)
call glclear(GL_COLOR_BUFFER_BIT + GL_DEPTH_BUFFER_BIT)
call glpushmatrix()
call glscalef(1.3, 1.3, 1.3)
call glrotatef(20.0, 1.0, 0.0, 0.0)
call glpushmatrix()
call gltranslatef(-0.75, 0.5, 0.0)
call glrotatef(90.0, 1.0, 0.0, 0.0)
call glutsolidtorus(0.275_gldouble, 0.85_gldouble, 10, 15)
call glpopmatrix()
call glpushmatrix()
call gltranslatef(-0.75, -0.5, 0.0)
call glrotatef(270.0, 1.0, 0.0, 0.0)
call glutsolidtetrahedron()
call glpopmatrix()
call glpushmatrix()
call gltranslatef(0.75, 0.0, -1.0)
call glutsolidicosahedron()
call glpopmatrix()
call glpopmatrix()
call glendlist()
call glflush()
end subroutine display
subroutine reshape(w,h)
use opengl_gl
use opengl_glu
use opengl_glut
integer, intent(in out) :: w,h
real(kind=gldouble) :: wr,hr,d
call glviewport(0, 0, w, h)
call glmatrixmode(GL_PROJECTION)
call glloadidentity()
wr = w
hr = h
d = 1.0_gldouble
if ( w <= h ) then
call glortho(-2.5_gldouble, 2.5_gldouble, &
-2.5_gldouble * hr/wr, 2.5_gldouble * hr/wr, &
-10.0_gldouble, 10.0_gldouble)
else
call glortho(-2.5_gldouble * hr/wr, &
2.5_gldouble * hr/wr, &
-2.5_gldouble, 2.5_gldouble, -10.0_gldouble, &
10.0_gldouble)
end if
call glmatrixmode(GL_MODELVIEW)
end subroutine reshape
subroutine submenu(value)
use opengl_gl
use opengl_glu
use opengl_glut
integer, intent(in out) :: value
if ( value == 1 ) then
call glenable(GL_DEPTH_TEST)
call glenable(GL_LIGHTING)
call gldisable(GL_BLEND)
call glpolygonmode(GL_FRONT_AND_BACK, GL_FILL)
else
call gldisable(GL_DEPTH_TEST)
call gldisable(GL_LIGHTING)
call glcolor3f(1.0, 1.0, 1.0)
call glpolygonmode(GL_FRONT_AND_BACK, GL_LINE)
call glenable(GL_LINE_SMOOTH)
call glenable(GL_BLEND)
call glblendfunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
end if
call glutpostredisplay()
end subroutine submenu
subroutine mainmenu(value)
use rendereps
use opengl_glut
integer, intent(in out) :: value
if (value == 10) then
call glutsetcursor(glut_cursor_wait)
call outputeps(100000,.true.,"epsout.eps")
call glutsetcursor(glut_cursor_inherit)
endif
if (value == 666) stop
end subroutine mainmenu
subroutine myinit()
use opengl_gl
use opengl_glu
use opengl_glut
real, dimension(4) :: lambient = (/ 0.0, 0.0, 0.0, 1.0 /), &
ldiffuse = (/ 1.0, 0.0, 0.0, 1.0 /), &
lspecular= (/ 1.0, 1.0, 1.0, 1.0 /), &
lposition= (/ 1.0, 1.0, 1.0, 0.0 /)
call gllightfv(GL_LIGHT0, GL_AMBIENT, lambient)
call gllightfv(GL_LIGHT0, GL_DIFFUSE, ldiffuse)
call gllightfv(GL_LIGHT0, GL_SPECULAR, lspecular)
call gllightfv(GL_LIGHT0, GL_POSITION, lposition)
call glenable(GL_LIGHT0)
call gldepthfunc(GL_LESS)
call glenable(GL_DEPTH_TEST)
call glenable(GL_LIGHTING)
end subroutine myinit
end module callbacks
program main
use opengl_gl
use opengl_glu
use opengl_glut
use callbacks
integer :: i,j
call glutinitwindowposition(500,500)
call glutinitwindowsize(500,500)
call glutinit()
i = glutcreatewindow("Fortran GLUT program")
call myinit()
call glutdisplayfunc(display)
call glutreshapefunc(reshape)
call glutcreatemenu(submenu,i)
call glutaddmenuentry("Filled", 1)
call glutaddmenuentry("Outline", 2)
call glutcreatemenu(mainmenu,j)
call glutaddsubmenu("Polygon mode", i)
call glutaddmenuentry("Save postscript",10)
call glutaddmenuentry("Quit", 666)
call glutattachmenu(GLUT_RIGHT_BUTTON)
call glutmainloop()
end program main
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet)
¤
|
Haftungshinweis
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.
|