1
votes

I'm having trouble with OpenGL lighting. My issue is this: When the object has 0 rotation, the lighting is fine- otherwise the lighting works, but rotates with the object, instead of staying fixed in regards to the scene.

Sounds simple, right? The OpenGL FAQ has some simple advice on this: coordinates passed to glLightfv(GL_LIGHT0, GL_POSITION...) are multiplied by the current MODELVIEW matrix. So I must be calling this at the wrong place... except I'm not. I've copied the MODELVIEW matrix into a variable to debug, and it stays the same regardless of how my object is rotated. So it has to be something else, but I'm at a loss as to what.

I draw the model using glDrawArrays, and position my model within the world using glMatrixMult on a matrix built from a rotation quaternion and a translation. All of this takes place within glPushMatrix/glPopMatrix, so shouldn't have any side effect on the light.

A cut down version of my rendering process looks like this:

//Setup our camera
glMatrixMode(GL_MODELVIEW);             
glLoadIdentity();
cameraMatrix = translate(Vector3D(Pos.mX,Pos.mY,Pos.mZ)) * camRot.QuatToMatrix();
glMultMatrixf((GLfloat*)&cameraMatrix);

//Position the light now
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
GLfloat lp[4] = {lightPos.mX, lightPos.mY, lightPos.mZ, 1.0f};
glLightfv(GL_LIGHT0, GL_POSITION,(GLfloat*)  lp);

//Loop, doing this for each model: (mRot, mPos, and mi are model member variables)
matrix = translate(Vector3D(mPos.mX,mPos.mY,mPos.mZ)) * mRot.QuatToMatrix();
glPushMatrix();
glMultMatrixf((GLfloat*)&matrix);
glBindBuffer(GL_ARRAY_BUFFER, mi->mVertexBufHandle);  //Bind the model VBO.
glDrawArrays(GL_TRIANGLES, 0, mi->verts); //Draw the object
glPopMatrix();

I thought the normals might be messed up, but when I render them out they look fine. Is there anything else that might effect openGL lighting? The FAQ mentions:

If your light source is part of a light fixture, you also may need to specify a modeling transform, so the light position is in the same location as the surrounding fixture geometry.

I took this to mean that you'd need to translate the light into the scene, kind of a no-brainer... but does it mean something else?

3
This is really getting weird. The light even rotates when I set the light position to 0,0,0 under the identity transform, using glPushMatrix(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glLightfv(GL_LIGHT0,GL_POSITION, Vector4D(0,0,0,1)); glPopMatrix(); - Ian Nafiri
I'm fairly sure I'm doing something wrong when I render the object- the last step is to give the object a local rotation, but it seems like this rotation also applies to the light. My first thought was to multiply the light position by the new rotation, but I'm either doing that wrong or it doesn't help... - Ian Nafiri
how do you tell that the light is rotating? try drawing a GL_POINT in its position, and try commenting glDrawArrays (to avoid any confusion); is the point moving, even when cameraMatrix is fixed? - UncleZeiv
When I don't change cameraMatrix, the light does not move. When I do, the light orbits around the rotating model like a planet around the sun. Am I rotating my model wrong? - Ian Nafiri

3 Answers

1
votes

It might be minor, but in this line:

glLightfv(GL_LIGHT0, GL_POSITION,(GLfloat*)  &lp);

remove the & (address operator). lp will already give you the array-address.

1
votes

This was awhile back, but I did eventually figure out the problem. The issue I thought I was having was that the light's position got translated wrong. Picture this: the light was located at 0,0,0, but then I translated and rotated my mesh. If this had been the case, I'd have to do as suggested in the other answers and make certain I was placing my glLightfv calls in the right place.

The actual problem turned out to be much simpler, yet much more insidious. It turns out I wasn't setting the glNormalPointer correctly, and so it was being fed garbage data. While debugging, I'd render the normals to check that they were correct, but when doing so I'd manually draw them based on the positions I'd calculated. A recommendation to future debuggers: when drawing your debug info normal rays, make sure you feed the debug function /the same data/ as openGL gets. In my case, this would mean pointing my normal ray draw function's glVertexPointer to the same place as the model's glNormalPointer.

0
votes

Basically an OpenGL light behaves like a vertex. So in your code it's transformed by cameraMatrix, while your meshes are transformed by cameraMatrix * matrix. Now, it looks like both cameraMatrix and matrix contain mrot.QuatToMatrix(), that is: there is a single rotation matrix there, and the light gets rotated once, while the objects get rotated twice. It doesn't look right to me, unless your actual code is different; the mRot matrix you use for each mesh should be its own, e.g. mRot[meshIndex].