[Haskell-cafe] OpenGL and GLUT in GHC

Sven Panne sven.panne at aedion.de
Sat Mar 24 11:41:09 EDT 2007

[ Small note: Library-related questions should better be directed to 
libraries at haskell.org, and for mails regardind the OpenGL/GLUT packages there 
is the hopengl at haskell.org mailing list. ]

On Saturday 24 March 2007 13:37, Ruben Zilibowitz wrote:
> [...] I've encountered a strange bug which I'm having trouble with. If I
> render a sphere and a plane, then the plane is facing the wrong way
> and is shaded on the wrong side. If however I only render the plane
> then it appears to be facing the right way and is shaded on the
> correct side. [...]

I guess the problem is a misunderstanding of what 'autoNormal $= Enabled' 
does. It enables the automatic generation of analytic normals when 2D 
evaluators are used. It doesn't affect the rendering of normal primitives 
like quads. You don't provide any normals for your plane, so the current 
normal is used for all four vertices. The value of the current normal is 
(Vector 0 0 1) initially, so this seems to work if you render the plane 
alone, *but* the GLUT object rendering functions provide normals for all 
their vertices. So the net effect is that the normals for the vertices of 
your plane are set to whichever normal GLUT has specified last. Simple fix: 
Provide normals for your quad, i.e. use

   normal (Normal3 0 0 (1 :: GLfloat))

before specifying any vertex of your quad. In general when lighting is used, 
make sure to provide the correct normals for all vertices. Unit normals 
should be preferred, otherwise you have to tell OpenGL about that and this 
leads to more work (= rescaling/normalization of all normals within OpenGL).

A few more notes:

   * There is no need in your example to use 'normalize $= Enabled' when you 
provide unit normals. GLUT does this, BTW.

   * Setting the material properties could be done only once in the 
initialization function.

   * Use postRedisplay only when something has really changed, e.g. at the end 
of 'motion'. Otherwise you get 100% CPU/GPU load for no good reason.

   * IORefs are StateVars, so you can use get and ($=) instead of readIORef 
and writeIORef, this is more consistent with the OpenGL/GLUT API.


More information about the Haskell-Cafe mailing list