PDA

View Full Version : Problem With Location of Specular Highlights



Carmine
06-20-2012, 05:33 PM
I have a small application which opens 4 windows and displays the same set of spheres in each window. This is traditional GL. I look at the spheres from a different direction in each window. There's only one light source in the scene. I am trying to show ambient, diffuse, and specular lighting on the spheres from this light source. Should be easy, right? The ambient and diffuse lighting looks correct in all 4 windows (relative to my light source). But in 2 of the windows the specular highlights are misplaced. It looks like they are being generated from a different light source than what is generating the diffuse lighting. Been looking at this for a day and a half and can not figure out what's going on. Before I resort to posting source code or screen grabs, I was wondering if anyone has run into this problem before and can give me a hint about how to fix it. Thanks.

thokra
06-21-2012, 12:13 AM
Care to share some code and screenshots?

Carmine
06-21-2012, 03:41 PM
Care to share some code and screenshots? Didn't want to bother you guys with my code. But here goes. I'm still stuck on this problem. I'm drawing the same set of objects in different windows, illuminated by the same light source, but I can't get the specular highlights to work correctly in any window where I use gluLookAt. Diffuse lighting seems to be o.k. It doesn't seem right to ask the forum to debug my entire program, so I just posted the code which generates the two windows in the screen grabs below. Any ideas?


//---+----4----+----3----+----2----+----1----+---/\---+----1----+----2----+----3----+----4----+---\\
//--------------------------------------- Cam_Vu::draw -----------------------------------------

void Cam_Vu::draw (void)
{
float cam[3], asp = w() / h(), nlit[4];

static float nospec[4] = {0,0,0,0};

cam[0] = cameraPosition[0];
cam[1] = cameraPosition[1];
cam[2] = cameraPosition[2];

glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective (40.0f, asp, 2.0f, 8.0f);
gluLookAt (cam[0],cam[1],cam[2], 0,0,0, 0,1,0);
glViewport (0, 0, w(), h());
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();

glClearColor (0.05, 0.20, 0.05, 1.0);

glEnable (GL_DEPTH_TEST);
glEnable (GL_NORMALIZE );
glEnable (GL_CULL_FACE );

glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

Show_Light ();

if (lighting) {
Light_Source ();

glEnable (GL_LIGHT1);
glEnable (GL_LIGHTING);
glEnable (GL_COLOR_MATERIAL);
glMaterialfv (GL_FRONT, GL_SPECULAR, wyte_spc);
glMaterialf (GL_FRONT, GL_SHININESS, 40.0f);
glColorMaterial (GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

nlit[0] = lightPosition[0];
nlit[1] = lightPosition[1];
nlit[2] = lightPosition[2];
nlit[3] = 1.0;

glLightfv (GL_LIGHT1, GL_POSITION, nlit);
}

Draw_Objects ();

Window_Title (1.0, 97.0, linen, "From Camera");
}


//---+----4----+----3----+----2----+----1----+---/\---+----1----+----2----+----3----+----4----+---\\
//---------------------------------------- God_Vu::draw -----------------------------------------

void God_Vu::draw (void)
{
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective (40.0, (w()/h()), 2.0, 8.0);
glViewport (0, 0, w(),h());
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();

glEnable (GL_DEPTH_TEST);
glEnable (GL_NORMALIZE );
glEnable (GL_CULL_FACE );

glClearColor (0.05, 0.05, 0.20, 1.0);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glPushMatrix();

glTranslatef (vu_hor, vu_ver, -5.0);
glRotatef (vu_tip, 1,0,0);
glRotatef (vu_trn, 0,1,0);
glScalef (vu_scl, vu_scl, vu_scl);

Show_Light ();
Show_Camera ();
Light_Source();

glEnable (GL_COLOR_MATERIAL);
glMaterialfv (GL_FRONT , GL_SPECULAR, wyte_spc);
glMaterialf (GL_FRONT , GL_SHININESS, 40.0f);
glColorMaterial(GL_FRONT , GL_AMBIENT_AND_DIFFUSE);
glLightfv (GL_LIGHT1, GL_POSITION, lyte_pos);

Draw_Objects ();

glPopMatrix();

Window_Title (1.0, 97.0, linen, "God's Eye");
}

http://www.mfwerner.addr.com/OpenGL/Forum_A_Dfs.jpg

http://www.mfwerner.addr.com/OpenGL/Forum_A_Spc.jpg

thokra
06-22-2012, 12:57 AM
Didn't want to bother you guys with my code.

You'd have to ask yourself: How could we help you with your OpenGL code if we don't see your OpenGL code? :) There are times where a full function snippet isn't necessary but in general a bit of code is very much appreciated.

Before talking about lighting, I have other objections to make:



float asp = w() / h();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective (40.0f, asp, 2.0f, 8.0f);
glViewport(0, 0, w(),h());


You recalculate the projection matrix every time you draw a view - either god or cam view. This is fine if the projection is actually different but in your current case it's simply a performance waste. Furthermore, it's simply code duplication which should be factored into a function. The same goes for some pretty constant state:



glEnable (GL_DEPTH_TEST);
glEnable (GL_NORMALIZE );
glEnable (GL_CULL_FACE );


Not necessary to set it again and again. Do it at init time and keep the settings until a change, is really needed - if ever.

Then there's this code:



glMatrixMode(GL_PROJECTION);
glLoadIdentity ();
gluPerspective (40.0f, asp, 2.0f, 8.0f);
gluLookAt(cam[0],cam[1],cam[2], 0,0,0, 0,1,0);


Although legal, you alter the projection Matrix when calling gluLookAt() before resetting to the MODELVIEW matrix stack (i.e. glMatrixMode(GL_MODELVIEW)). Since you don't do that in the god view, the result may and probably will vary in some way. Remember, gluLookAt() computes a view matrix! Only use it on the MODELVIEW stack.

What perplexes me about you lighting routine is that in god mode, the light seems to have a different world-space position than in cam view:




nlit[0] = lightPosition[0];
nlit[1] = lightPosition[1];
nlit[2] = lightPosition[2];
nlit[3] = 1.0;
glLightfv (GL_LIGHT1, GL_POSITION, nlit);



and



glLightfv(GL_LIGHT1, GL_POSITION, lyte_pos);


When doing lighting calculations, programmable or fixed, you need to make sure that all data is consistent. Furthermore, you don't need to enable and set the diffuse, ambient and specular components every frame. Do it at init time and change if necessary. In general I'd advise you to make your view functions as consistent as possible, with the exception of the view matrix. Incidentally, you don't need to manually do the view matrix setup in god mode like:


glTranslatef(vu_hor, vu_ver, -5.0);
glRotatef(vu_tip, 1,0,0);
glRotatef(vu_trn, 0,1,0);
glScalef(vu_scl, vu_scl, vu_scl);


And why the uniform scaling? You can use gluLookAt() here just the same. BTW, pushing and popping the matrix isn't necessary in your case.

Carmine
06-22-2012, 10:13 AM
.
First of all, thanks for the feedback. It was very helpful.


Then there's this code:


glMatrixMode(GL_PROJECTION);
glLoadIdentity ();
gluPerspective (40.0f, asp, 2.0f, 8.0f);
gluLookAt(cam[0],cam[1],cam[2], 0,0,0, 0,1,0);


Although legal, you alter the projection Matrix when calling gluLookAt() before resetting to the MODELVIEW matrix stack (i.e. glMatrixMode(GL_MODELVIEW)). Since you don't do that in the god view, the result may and probably will vary in some way. Remember, gluLookAt() computes a view matrix! Only use it on the MODELVIEW stack.
This is where my problem was. The lighting works correctly now that I've moved the gluLookAt command further down in the code after I go into MODELVIEW mode. Not sure why this problem only messed up the specular highlights and not the diffuse lighting?

You're comments on the inefficient coding are correct. This code is a little test program I wrote to experiment with lighting. I'm not too worried about it being optimized for speed. I try to implement the efficiencies you talk about in my larger simulations.

Thanks again for the feedback. I was losing my mind over this one :)