🔒 Locked
Lighting problem
Advertisement
Original Post
I've re-worked the rendering section of my program and somehow broke the lighting. I've compared my different versions of the code and can't figure out what's different. What happens is all objects are lit as if they were positioned at the origin. I can move the light source arround, and the lighting is updated as expected. I can rotate the object around, and the lighting is updated as expected. But when I translate the object, it is drawn in the new, expected position, but lit as if it were still at the origin. Anyone have any ideas? I can post code if needed. Thanks!
Light sources are transformed by the modelview matrix. Are you placing the light after a glLoadIdentity call and before the glTranslate call?
Here's the order I do things in:
Any ideas? Thanks.
glClearColor()glClear()glMatrixMode(GL_PROJECTION)glLoadIdentity()gluPerspective()glMatrixMode(GL_MODELVIEW)glLoadIdentity()glPushMatrix() // according to camera view... glRotate() & glTranslatef() //apply lighting glEnable(GL_LIGHTING) glLightfv(GL_LIGHT0, GL_POSITION, pLight0Position) glEnable(GL_LIGHT0) // Draw the objects glPushMatrix() // according to object... glRotate() & glTranslatef() // Draw VBOs glPopMatrix()glPopMatrix()glMatrixMode(GL_PROJECTION)glLoadIdentity()gluOrtho()// Draw my GUIAny ideas? Thanks.
What trippytarka predicted is actually true in your case. Your lights are transformed by the camera matrix. So they are actually positioned w.r.t. the camera. If the light position you contain in pLight0Position is supposed to be a coordinate in world space, swap your code as follows:
Tom
glPushMatrix() // first apply lighting glEnable(GL_LIGHTING) glLightfv(GL_LIGHT0, GL_POSITION, pLight0Position) glEnable(GL_LIGHT0) // then transform according to camera view... glRotate() & glTranslatef() // rest of code here...Tom
I find this a simple workaround:
Say you are doing a
glTranslatef (x, y, z);
// draw code
// lighting code
Just add before lighting code,
glTranslatef (-x, -y, -z);
That was the way my code was set up and so this is the way I fixed it. Your's may be different, but anyway I hope this helped.
Say you are doing a
glTranslatef (x, y, z);
// draw code
// lighting code
Just add before lighting code,
glTranslatef (-x, -y, -z);
That was the way my code was set up and so this is the way I fixed it. Your's may be different, but anyway I hope this helped.
dimebolt, I tried what you suggested, but I ended up with the same result. I can move the camera around, I can move the light around, I can move the object around. Everything works as expected, except that the object remains lit as if its position is located at the origin. Rotating the object works fine, moving the light around works fine, moving the camera around, etc... But I move the object -10 on the Z axis, with the point light located at -5, and the object still remains lit on the -Z side.
This is really stumping me.
This is really stumping me.
Quote:
Original post by Mantear
dimebolt, I tried what you suggested, but I ended up with the same result. I can move the camera around, I can move the light around, I can move the object around. Everything works as expected, except that the object remains lit as if its position is located at the origin. Rotating the object works fine, moving the light around works fine, moving the camera around, etc... But I move the object -10 on the Z axis, with the point light located at -5, and the object still remains lit on the -Z side.
This is really stumping me.
It's stumping me too :) Could you post the real code? Clearly something fishy is going on...
Tom
void RenderEngine::RenderScene(int width, int height){ // Set the Background color glClearColor(BGColor[0], BGColor[1], BGColor[2], BGColor[3]); // Clear the screen and the depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Select and initialize the Projection Matrix glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective( Camera.GetViewAngle(), (float)width/(float)height, Camera.GetNearClip(), Camera.GetFarClip()); // Select and reset the ModelView Maxtrix glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // Set up the scene glPushMatrix(); { // Translate and rotate according to the current viewing object glRotatef(*CurrentViewObject.GetMirrorDataPtr()->pRotationX, -1.0f, 0.0f, 0.0f); glRotatef(*CurrentViewObject.GetMirrorDataPtr()->pRotationY, 0.0f, -1.0f, 0.0f); glRotatef(*CurrentViewObject.GetMirrorDataPtr()->pRotationZ, 0.0f, 0.0f, -1.0f); glTranslatef( -*CurrentViewObject.GetMirrorDataPtr()->pPositionX, -*CurrentViewObject.GetMirrorDataPtr()->pPositionY, -*CurrentViewObject.GetMirrorDataPtr()->pPositionZ); // Draw the scene DrawScene(); } glPopMatrix(); // Switch to the Projection Matrix, reset it, // and load some nice coordinates for doing the GUI glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, width, 0, height); // Don't allow lighting to affect the GUI and make sure textures are enabled glDisable(GL_LIGHTING); glEnable(GL_TEXTURE_2D); // Display the GUI pGUI->DisplayGUI();}void RenderEngine::DrawScene(void){ // Apply the lighting for the objects ApplyLighting(); // Draw each object for (int i = 0; i < ObjectsCurrentSize; i++) { // Only draw if it is not hidden if (!pObjects.IsHidden()) { pObjects.DrawObject(); } } // Anything drawn past here won't have textures or lighting applied glDisable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); // Draw things like normals, bounding boxes, camera and light models, etc}void RenderEngine::ApplyLighting(void){ // Is overall lighting enabled? if (LightingEnabled) { // Yes, so enable lighting glEnable(GL_LIGHTING); glEnable(GL_COLOR_MATERIAL); for (int i = 0; i < 8; i++) { // Is this light enabled? if (Lights.IsEnabled()) { // Apply light properties glLightfv(GL_LIGHT0 + i, GL_AMBIENT, Lights.GetAmbient()); glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, Lights.GetDiffuse()); glLightfv(GL_LIGHT0 + i, GL_SPECULAR, Lights.GetSpecular()); // Distant, Point, or Spot light switch(Lights.GetLightType()) { case DistantLight: case PointLight: glLightfv(GL_LIGHT0 + i, GL_POSITION, Lights.GetPosition()); break; case SpotLight: glLightfv(GL_LIGHT0 + i, GL_POSITION, Lights.GetPosition()); // TO DO: Get this part working! glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, Lights.GetSpotDirection()); glLightf(GL_LIGHT0 + i, GL_SPOT_CUTOFF, Lights.GetSpotCutoff()); glLightf(GL_LIGHT0 + i, GL_SPOT_EXPONENT, Lights.GetSpotExponent()); break; default: // Invalid light type break; } // Apply Attenuation glLightf(GL_LIGHT0 + i, Lights.GetAttenuationType(), Lights.GetAttenuation()); // Enable the light glEnable(GL_LIGHT0 + i); } else { // Disable the light glDisable(GL_LIGHT0 + i); } } } else { // No, disanbel lighting glDisable(GL_LIGHTING); glDisable(GL_COLOR_MATERIAL); }}void Objects::DrawObject(void){ glPushMatrix(); { // Translate glTranslatef(*MirrorData.pPositionX, *MirrorData.pPositionY, *MirrorData.pPositionZ); // Then rotate glRotatef(*MirrorData.pRotationZ, 0.0f, 0.0f, 1.0f); glRotatef(*MirrorData.pRotationY, 0.0f, 1.0f, 0.0f); glRotatef(*MirrorData.pRotationX, 1.0f, 0.0f, 0.0f); // Bind the vertex data glBindBufferARB(GL_ARRAY_BUFFER, *MirrorData.pVertexName); glVertexPointer(3, GL_FLOAT, 0, 0); // Bind the color data glBindBufferARB(GL_ARRAY_BUFFER, *MirrorData.pColorName); glColorPointer(4, GL_UNSIGNED_BYTE, 0, 0); // Bind the normal data glBindBufferARB(GL_ARRAY_BUFFER, *MirrorData.pNormalName); glNormalPointer(GL_FLOAT, 0, 0); // Bind the texture data glBindBufferARB(GL_ARRAY_BUFFER, *MirrorData.pTexCoordName); glTexCoordPointer(2, GL_FLOAT, 0, 0); // Draw the Points if (MirrorData.pPoints->IndexCurrentSize > 0) { glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, MirrorData.pPoints->VBOName); glDrawRangeElements(GL_POINTS, 0, MirrorData.pPoints->IndexCurrentSize, MirrorData.pPoints->IndexCurrentSize, GL_UNSIGNED_INT, NULL); } // Draw the Lines if (Lines.IndexCurrentSize > 0) { glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, Lines.VBOName); glDrawRangeElements(GL_LINES, 0, MirrorData.pLines->IndexCurrentSize, MirrorData.pLines->IndexCurrentSize, GL_UNSIGNED_INT, NULL); } // Draw the Triangles if (Triangles.IndexCurrentSize > 0) { glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, Triangles.VBOName); glDrawRangeElements(GL_TRIANGLES, 0, MirrorData.pTriangles->IndexCurrentSize, MirrorData.pTriangles->IndexCurrentSize, GL_UNSIGNED_INT, NULL); } // Draw the Quads if (Quads.IndexCurrentSize > 0) { glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, Quads.VBOName); glDrawRangeElements(GL_QUADS, 0, MirrorData.pQuads->IndexCurrentSize, MirrorData.pQuads->IndexCurrentSize, GL_UNSIGNED_INT, NULL); } } glPopMatrix();}Here's my source code, nearly un-altered (removed commented out sections, drawing of camera/light objects, a background grid, etc). MirrorData is a structure of pointers that points to the data within the object, or can be set to point to another object (in this way I'm going to see if I can't 'mirror' an object without having to duplicte all the data). For now, they always 'mirror' themselves, pointing to their own data.
Thanks for your help, this is a very frustrating problem and I'm running out of ideas.
It does seem you still apply some transformations before the lighting:
Could you try pulling the lighting out of the DrawScene and run like this:
That may solve your problem.
Tom
glPushMatrix(); { // some transformations: glRotatef(*CurrentViewObject.GetMirrorDataPtr()->pRotationX, -1.0f, 0.0f, 0.0f); glRotatef(*CurrentViewObject.GetMirrorDataPtr()->pRotationY, 0.0f, -1.0f, 0.0f); glRotatef(*CurrentViewObject.GetMirrorDataPtr()->pRotationZ, 0.0f, 0.0f, -1.0f); glTranslatef( -*CurrentViewObject.GetMirrorDataPtr()->pPositionX, -*CurrentViewObject.GetMirrorDataPtr()->pPositionY, -*CurrentViewObject.GetMirrorDataPtr()->pPositionZ); // Draw the scene with lighting first: DrawScene(); } glPopMatrix(); Could you try pulling the lighting out of the DrawScene and run like this:
glPushMatrix(); { // light: ApplyLighting(); // transformsations: glRotatef(*CurrentViewObject.GetMirrorDataPtr()->pRotationX, -1.0f, 0.0f, 0.0f); glRotatef(*CurrentViewObject.GetMirrorDataPtr()->pRotationY, 0.0f, -1.0f, 0.0f); glRotatef(*CurrentViewObject.GetMirrorDataPtr()->pRotationZ, 0.0f, 0.0f, -1.0f); glTranslatef( -*CurrentViewObject.GetMirrorDataPtr()->pPositionX, -*CurrentViewObject.GetMirrorDataPtr()->pPositionY, -*CurrentViewObject.GetMirrorDataPtr()->pPositionZ); // Draw the scene without lighting first: DrawScene(); } glPopMatrix(); That may solve your problem.
Tom
I'm beginning to use my brains now and started looking into my own code.
Forget my post on the camera code, that was nonsense.
This is a simplified, mono-scopic version of what I do in my SG:
As you can see, I do load the viewmatrix before the lighting as you had in your initial code. I messed up, you were right there. The problem is probably what I stated in the previous post. Try to rewrite your code to do:
Sorry about the confusion...
Tom
Forget my post on the camera code, that was nonsense.
This is a simplified, mono-scopic version of what I do in my SG:
void caOpenGLProcessor::Process(caSequence *seq){ if (!Setup()) return; Render(seq);}bool caOpenGLProcessor::Setup(){ if (!SetupViewport()) return false; if (!ClearFrameBuffer()) return false; if (!SetupProjectionAndView()) return false; return true;}bool caOpenGLProcessor::SetupProjectionAndView(){ caCamera *camera = viewport->Camera(); afrustum frust; amatrix proj, view; frust = camera->Frustum(); proj.make_perspective(frust); view = camera->InverseViewMatrix(); glMatrixMode(GL_PROJECTION); glLoadMatrixf(proj.m); glMatrixMode(GL_MODELVIEW); glLoadMatrixf(view.m);}void caOpenGLProcessor::Render(caSequence *seq){ // emit lights EmitLights(seq->lights); // continue with appearances and shapes EmitGeometries(seq->geometries); // continue with transparent appearances and shapes glDepthMask(GL_FALSE); EmitGeometries(s->transparents); glDepthMask(GL_TRUE); glFlush();}As you can see, I do load the viewmatrix before the lighting as you had in your initial code. I messed up, you were right there. The problem is probably what I stated in the previous post. Try to rewrite your code to do:
glMatrixMode(GL_PROJECTION);LoadProjectionMatrix();glMatrixMode(GL_MODELVIEW);LoadViewMatrix();glPushMatrix();{ ApplyLighting(); DoMirroringTransforms(); // I'm not sure what they do, bu I assume you need them DrawScene();}glPopMatrix(); Sorry about the confusion...
Tom
Quote:That sounds like you're using a directional light. When you do this...
Original post by Mantear
But I move the object -10 on the Z axis, with the point light located at -5, and the object still remains lit on the -Z side.
...case DistantLight:case PointLight: glLightfv(GL_LIGHT0 + i, GL_POSITION, Lights.GetPosition()); break;case SpotLight: glLightfv(GL_LIGHT0 + i, GL_POSITION, Lights.GetPosition());......are you sure that the w-value of the light's position is not 0?
Kalidor,
When I initialize my lights, the w-value is determined by the type of light it is (distant, point, or spot). I will re-check it and make sure it is being done correctly. The reason I said that is to show that even when the object moves to the other side of the light, the object remains lit on the side that would be lit if it were at the origin. Going from my previous example, if I then move the light to +5 on the Z axis, the object is lit on the other side, regardless of where I put the object. I also don't think I'm accidentally setting up a directional light, as rotating the light has no affect, only its position (relative to the origin).
dimebolt,
I figured that MirrorData part was going to be confusing... you can treat the MirrorData as the objects own data. Position, Rotation, etc. When I create the object, I have the MirrorData structure (which is mostly pointers) point to the objects own data. I then reference the object's Position, Rotation, etc, via the MirrorData pointers, instead of directly. My intent here is I want to be able to have one object "mirror" another. Instead of pointing at its own data, it could point at another objects data. That way, I could have two copies of the same object without copying all the data.
I hope that makes sense. (*CurrentViewObject.GetMirrorDataPtr()->pRotationX simply returns the X rotation value of the current view/camera object.
This simply translates and rotates the object according to its own position and rotation values.
I'll try your suggestions when I get a chance.
When I initialize my lights, the w-value is determined by the type of light it is (distant, point, or spot). I will re-check it and make sure it is being done correctly. The reason I said that is to show that even when the object moves to the other side of the light, the object remains lit on the side that would be lit if it were at the origin. Going from my previous example, if I then move the light to +5 on the Z axis, the object is lit on the other side, regardless of where I put the object. I also don't think I'm accidentally setting up a directional light, as rotating the light has no affect, only its position (relative to the origin).
dimebolt,
I figured that MirrorData part was going to be confusing... you can treat the MirrorData as the objects own data. Position, Rotation, etc. When I create the object, I have the MirrorData structure (which is mostly pointers) point to the objects own data. I then reference the object's Position, Rotation, etc, via the MirrorData pointers, instead of directly. My intent here is I want to be able to have one object "mirror" another. Instead of pointing at its own data, it could point at another objects data. That way, I could have two copies of the same object without copying all the data.
I hope that makes sense. (*CurrentViewObject.GetMirrorDataPtr()->pRotationX simply returns the X rotation value of the current view/camera object.
void Objects::DrawObject(void){ glPushMatrix(); { // Translate glTranslatef(*MirrorData.pPositionX, *MirrorData.pPositionY, *MirrorData.pPositionZ); // Then rotate glRotatef(*MirrorData.pRotationZ, 0.0f, 0.0f, 1.0f); glRotatef(*MirrorData.pRotationY, 0.0f, 1.0f, 0.0f); glRotatef(*MirrorData.pRotationX, 1.0f, 0.0f, 0.0f);This simply translates and rotates the object according to its own position and rotation values.
I'll try your suggestions when I get a chance.
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement