Skip to main content
gamedev.net
🔒 Locked

Lighting problem

Started by Mantear Jul 31, 2005 at 4:15 PM 11 replies 950+ views
Original Post
Mantear
Mantear
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!
trippytarka
trippytarka
Light sources are transformed by the modelview matrix. Are you placing the light after a glLoadIdentity call and before the glTranslate call?
Mantear
Mantear
Here's the order I do things in:
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 GUI

Any ideas? Thanks.
dimebolt
dimebolt
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:
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
deavik
deavik
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.
Mantear
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.
dimebolt
dimebolt
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
Mantear
Mantear
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.
dimebolt
dimebolt
It does seem you still apply some transformations before the lighting:
   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
dimebolt
dimebolt
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:
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
Kalidor
Kalidor
Quote:
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.
That sounds like you're using a directional light. When you do this...
...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?
Mantear
Mantear
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.
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.
Mantear
Mantear
Kalidor,

Your hunch was right. I wasn't setting the 'w' value correctly. I had some issues with my derived Light object which had the addition of the W parameter, accessing the position values, etc. I'm still a bit unsure of why what I had didn't work as I expected.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.