• Advertisement
Sign in to follow this  

Lighting problem

This topic is 4585 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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!

Share this post


Link to post
Share on other sites
Advertisement
Light sources are transformed by the modelview matrix. Are you placing the light after a glLoadIdentity call and before the glTranslate call?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement