Bug in culling when GL_LIGHT_MODEL_TWO_SIDE is active

Bug definiton:
Back facing polygons are CULLED away, --in contradiction-- upon
activation of GL_LIGHT_MODEL_TWO_SIDE, no matter glDisable(GL_CULL_FACE)
is called or not.

Possible suggestion for workaround: “Flip the normals” does not
work if there are open surfaces in the scene of which front and
back sides cannot be defined mathematically.
That is possible only for closed surfaces tough with some overhead.

Below is a code sample to reproduce this error.

On the output window:
1st row-> two-side OFF, SAME material for front&back
2nd row-> two-side ON, SAME material for front&back
3rd row-> two-side ON, DIFFERENT material for front&back

Note that in 3rd row, magenta is the back-face (interior) material of
the objects which should NOT be seen.

If you set glFrontFace(GL_CW) Sphere shows the bug,
elseif you set glFrontFace(GL_CCW) it is the Teapot.

Code to reproduce the bug:
(modified from the distributed sample code TEA.C)


#include <GL/glut.h>

void init();
void reshape(int w, int h);
void display();

int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(600, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow(“Tea in the Sahara”);
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();

return 0;

}

void init()
{
GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };

glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);

glFrontFace (GL_CW); /** THIS LINE SWITCHES BUGGY OBJECTS **/
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_NORMALIZE);
glDisable(GL_CULL_FACE); /** HAS NO AFFECT **/
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);

}

void reshape(int w, int h)
{
if (!h) return;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho (-4.0, 4.0, -4.0*(GLfloat)h/(GLfloat)w,
4.0*(GLfloat)h/(GLfloat)w, -10.0, 10.0);
else
glOrtho (-4.0*(GLfloat)w/(GLfloat)h,
4.0*(GLfloat)w/(GLfloat)h, -4.0, 4.0, -10.0, 10.0);

glMatrixMode(GL_MODELVIEW);

}

void drawScene()
{
glPushMatrix();
glTranslatef(2.0, 0.0, 0.0);
glutSolidTeapot(1.0);
glPopMatrix();

glPushMatrix();
glTranslatef(-2.0, 0.0, 0.0);
glutSolidSphere(1.0, 16.0, 16.0);
glPopMatrix();

}

void display()
{
GLfloat mat_diffuse[] = { 0.8, 0.8, 0.8, 1.0 };
GLfloat back_diffuse[] = { 0.8, 0.2, 0.8, 1.0 };

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glPushMatrix ();

/* one-sided lighting */
glLightModelf (GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
glPushMatrix ();
glTranslatef (0.0, 2.0, 0.0);
drawScene();
glPopMatrix ();

/* two-sided lighting, but same material */
glLightModelf (GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
glPushMatrix ();
glTranslatef (0.0, 0.0, 0.0);
drawScene();
glPopMatrix ();

/* two-sided lighting, two different materials */
glMaterialfv (GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv (GL_BACK, GL_DIFFUSE, back_diffuse);
glPushMatrix ();
glTranslatef (0.0, -2.0, 0.0);
drawScene();
glPopMatrix ();

glLightModelf (GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
glPopMatrix ();
glFlush();

}

[This message has been edited by Suha Aktan (edited 12-12-2000).]

Two-sided lighting just controls lighting.

Culling is controlled with glCullFace() and
the GL_CULL_FACE state.
Add a call to glDisable(GL_CULL_FACE); to
your setup code and back-faces won’t be
culled anymore.

Culling is controlled with glCullFace() and
the GL_CULL_FACE state.
Add a call to glDisable(GL_CULL_FACE); to
your setup code and back-faces won’t be
culled anymore.

Actually, Suha Aktan said that this behavior existed even when he called glDisable(GL_CULL_FACE).

Which driver are you using? Because if it actually is a bug, then it’s probably driver specific, not something that affects OpenGL.

My guess is that the “bug” is something to do with the fact that front and back material properties are separate. But I really don’t know what actually is going wrong.

j

You are right; I missed that. I must have
spelled it wrong when searching the article
to make sure :frowning:

Try a different machine with a different
card and see if it still happens. Also try
putting a breakpoint in glEnable (if you
have a systems-level debugger) and make sure
it doesn’t accidentally get re-enabled after
you disable it.

Often, the best way to confirm bugs like this is to use the Microsoft software OpenGL driver.

The easiest way to force this is to rename your OpenGL driver so the OS can’t load it. In our case, rename nvopengl.dll to, say, nvopengl.dll.bak on Win9x systems and nvoglnt.dll to nvoglnt.dll.bak on WinNT/Win2K systems. Make sure to rename it back when you’re done.

  • Matt

Is there anybody who ran the code and DID NOT see the magenta?

Besides, any suggestions for workaround?
I just want to see all the polygons facing both front and back.
(Please don’t say just “use GL_LIGHT_MODEL_TWO_SIDE” without reading the 1st post)