specular lighting on back face of a polygon

Hi folks,

I want to visualize thin structures (like sheet metal) where depending of camera orientation both faces might be visible. My lighting code works well (ambient, diffuse and emission) except I cannot produce specular reflections on back faces of the polygons (on front faces OK)
Tried it with two side lighting and materials for front and back side. Also tried
one side lighting with only the front material applied. I’ve never seen a specular light on the back side of those polygons.
Can not find any hint in the opengl specs.
Anyone with a solution?

Hi

You can’t expect specular highlights on backfaces because the normal vectors are in the wrong sense.
You could draw your object twice, the first time in the ordinary way, and the second time with reversed normal vectors. Note that you don’t need any blending to achieve this, and that you can enable GL_CULL_FACE, so it should run fast enough.

Hope that helps
Morglum

Hi Morglum,

thanks for your reply. I think this is
an odd behaviour of opengl, isn’t it ?
Why not letting the programmer decide
to have specular highlight’s on the back or not ? In the sense of one side lighting or
two side lighting. Anyway I checked the specs on light model.

Opengl Ref. Man states at page 48:

“Lighting may operate in two-sided mode (tbs = TRUE), in which a front
color is computed with one set of material parameters (the front material)
and a back color is computed with a second set of material parameters (the
back material). This second computation replaces n with -n. If tbs = FALSE,
then the back color and front color are both assigned the color computed
using the front material with n.”

MSDN about opengl and lightmodel:
“Otherwise, two-sided lighting is specified. In this case, vertices of back-facing polygons are lighted using the back material parameters, and have their normals reversed before the lighting equation is evaluated. Vertices of front-facing polygons are always lighted using the front material parameters, with no change to their normals. The default is 0.”

Does this make sense ?
For me it reads like: If I use two side lighting, assign a front and back material then the back face should be
lighted like the frontface.

BTW:
Doubling the polygon count is no option because I am already on the limit

Jens

Seems to be working fine for me and I’ve got some lines like this:
float mat_specular[] = { 1.0 , 1.0 , 1.0 , 1.0 };
//…
glMaterialfv( GL_FRONT_AND_BACK , GL_SPECULAR , mat_specular );
//…
glLightModeli( GL_LIGHT_MODEL_TWO_SIDE , GL_TRUE );
among others. Any luck with that?

Thanks for the reply.
That’s (except for the light intensity)
what my source code look like.
I am now sure the is a problem with
gllightmodel. When I switch from one side
lighting to two side lighting all specular
effekt are gone.
Is anybody aware of a sample program showing
specular lighting two sided
so I can check my system /hardware (web link)?

Well, here’s hoping that that A. the formatting (with tabs and all) goes through and B. that I don’t tick off too many folks with the large post.

You’ll have to guess what the MySystem object is doing (it’s pretty obvious tho (I think)).

// main.cpp

#include <glut.h>
#include “MySystem.h”

//==============================================================================
static MySystem * mySys = static_cast<MySystem *>( 0 );
static float light_pos = { 1.5 , 0.0 , 0.0 , 1.0 }; // Positional.

//==============================================================================
void init()
{
glClearColor( 0.0 , 0.0 , 0.0 , 0.0 );
glShadeModel( GL_SMOOTH );

glEnable( GL_DEPTH_TEST );

float mat_specular = { 1.0 , 1.0 , 1.0 , 1.0 };
float mat_shininess = 50.0 ;
float mat_amb_and_diffuse = { 0.0 , 0.8 , 0.2 , 1.0 };

float light_ambient = { 0.4 , 0.4 , 0.4 , 1.0 };
float white_light = { 1.0 , 1.0 , 1.0 , 1.0 };

glMaterialfv( GL_FRONT_AND_BACK , GL_SPECULAR , mat_specular );
glMaterialf( GL_FRONT_AND_BACK , GL_SHININESS , mat_shininess );
glMaterialfv( GL_FRONT_AND_BACK , GL_AMBIENT_AND_DIFFUSE , mat_amb_and_diffuse );

glLightfv( GL_LIGHT0 , GL_AMBIENT , light_ambient );
glLightfv( GL_LIGHT0 , GL_DIFFUSE , white_light ); // redundant
glLightfv( GL_LIGHT0 , GL_SPECULAR , white_light ); // redundant

glLightModeli( GL_LIGHT_MODEL_LOCAL_VIEWER , GL_TRUE );
glLightModeli( GL_LIGHT_MODEL_TWO_SIDE , GL_TRUE );

glEnable( GL_LIGHTING );
glEnable( GL_LIGHT0 );

mySys = new MySystem();
}

//==============================================================================
void display()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
mySys->draw();
glutSwapBuffers();
}

//==============================================================================
void idleFunc()
{
mySys->update();
glutPostRedisplay();
}

//==============================================================================
void reshape( int w , int h )
{
glViewport( 0 , 0 , static_cast( w ) , static_cast( h ) );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 30.0 , // fovy
static_cast( w ) / static_cast( h ) , // aspect
1.0 , // near
8.0 // far
);
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
gluLookAt( 1.0 , 1.0 , 5.0 , // eye
0.3 , 0.5 , 0.0 , // where it’s aimed
0.0 , 1.0 , 0.0 // which way is up
);
glLightfv( GL_LIGHT0 , GL_POSITION , light_pos );
}

//==============================================================================
void mouse( int button , int state , int x , int y )
{
switch ( button )
{
case GLUT_LEFT_BUTTON :
if ( state == GLUT_DOWN )
{
glutIdleFunc( idleFunc );
}
break ;
case GLUT_RIGHT_BUTTON :
if ( state == GLUT_DOWN )
{
glutIdleFunc( 0 );
}
break ;
default :
break ;
}
}

//==============================================================================
int main( int argc , char * * argv )
{
glutInit( &argc , argv );
glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA | GLUT_ALPHA | GLUT_DEPTH );
glutInitWindowSize( 250 , 250 );
glutInitWindowPosition( 100 , 100 );
glutCreateWindow( “glutSys” );
init();
glutDisplayFunc( display );
glutReshapeFunc( reshape );
glutMouseFunc( mouse );

glutMainLoop();

delete mySys ;
return 0 ;
}

//==============================================================================

[This message has been edited by jmg (edited 12-08-2001).]

You may have found a bug.

Make sure you have specular lighting on the back face. Some cards don’t do well with two sided lighting, and some companies like NVIDIA deliberately cripple it.

They like to charge the professionals more for hardware so you need a Quadro to do stuff like two sided lighting & antialiased lines well in hardware.

Basically this is down on the list of priorities, so it wouldn’t be shocking if this is a bug.

Thanks for posting your code!
I again checked my code and found the normals
not corresponding to the polygon winding.
As I have learned the front face (by
means of winding) must have a postiv normal.
If the front face has the negativ normal
(and back face positive one)
all specular light effects are gone if
two side lighting is enabled.
Huh, this one is solved
thanks alot all of you
Jens