PDA

View Full Version : Little Lighting issue



dalemac
01-21-2011, 11:50 AM
First of all, i want to thank everyone for the wealth of info that is on this site, it has helped me get over other issues which i have come across. The current issue however, i cant seem to find an explaination for!

I have been working on a small game for my computer science uni course, but have ran into a little issue with lighting. Basically, the lights aren't working as i would expect to, i must be setting something wrong, but i cant figure out what!

The image attached probably explains this better than i can in words, butbasically i am drawing two rectangles (track start, and then the length), texturing them, creating the normals etc. but as you can see, the lighting stops on the first rectangle, and then restarts on the second rectangle.

What i am trying to implement is a light in the middle of the track, but i cant figure out how to do this.


My lighting function is as follows:


void initLighting()
{
// set up light colours (ambient, diffuse, specular)
GLfloat lightLa[] = {1.0, 0.0, 0.0, 1.0}; // ambient
GLfloat lightLd[] = {1.0, 1.0, 1.0, 1.0}; // diffuse
GLfloat lightLs[] = {1.0, 1.0, 1.0, 1.0}; // specular
float lightPs[4] = {20, 20, -200, 1}; // position of light

glLightfv(GL_LIGHT0, GL_AMBIENT, lightLa);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightLd);
glLightfv(GL_LIGHT0, GL_SPECULAR, lightLs);
glLightfv(GL_LIGHT0, GL_POSITION, lightPs);

GLfloat materialMs[] = {1.0f, 1.0f, 1.0f, 1.0f}; // specular
GLfloat materialMe[] = {1.0f, 1.0f, 1.0f, 1.0f}; // emission
glLightfv(GL_LIGHT0, GL_AMBIENT, materialMs);
glLightfv(GL_LIGHT0, GL_DIFFUSE, materialMe);

//glLightfv(GL_LIGHT0, GL_CONSTANT_ATTENUATION, lightPos);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
}


Any help would be greatly appreciated.

Thanks,
Dale

Dark Photon
01-21-2011, 04:47 PM
...basically i am drawing two rectangles (track start, and then the length), texturing them, creating the normals etc. but as you can see, the lighting stops on the first rectangle, and then restarts on the second rectangle.

What i am trying to implement is a light in the middle of the track, but i cant figure out how to do this.
Ok, there may be other problems but here is your main problem.

With the fixed function pipeline (which you are using with these legacy lighting calls), lighting is performed "per vertex" and the color resulting from lighting is then interpolated across the polygon (and your texturing is applied on top of that interpolated color).

So when you're drawing the entire track with only 6 vertices (effectively), you're only evaluating the lighting environment at those 6 points in space, and you shouldn't expect to get a nice radial lighting effect on the track right above your light source.

Now to do better, you can use shaders, interpolate the normals across the polygon, and evaluate lighting at every pixel. Then you'll get the nice radial lighting effect on the track even when you have a very low number of verts like this.

Another approach which would let you keep using the fixed-function lighting functionality and still get a nice radial lighting effect is to use a bunch more vertices to draw your track. This gets expensive, but it's nevertheless possible.

Note that there's another issue with the lighting results in your picture: Because there's a hard lighting "seam" between your two rectangles, I suspect the shared vertices in the middle are being sent down the pipe with different normals depending on which quad they are in. You should use the same normal (and same position and color) when sending those verts down so that the pipeline computes the same lighting value for them in both triangles. Then, assuming you have smooth shading on (see glShadeModel), you'll at least get rid of the hard seam your lighting has there, even if you won't get an awesome radial falloff to your light.

MaxH
01-21-2011, 05:14 PM
This doesn't really look like a lighting problem because of that hard seam. Are you sure you have matching colors and textures on the two polys? What happens if you turn lighting off entirely and render the same scene with simple coloring? Does the seam go away?

ZbuffeR
01-22-2011, 02:21 AM
Did you check your normals ? If they are not continuous, you will see discontinuities like that.

dalemac
01-22-2011, 02:29 AM
Hey Dark Photon, thankyou for your insight and suggestions.

How would i go about implementing your first suggestion?

Your second suggestion i understand, but i dont really want to be adding too many vertices.

i spent most of yesterday playing around with my normals but i couldnt get it right. I am only calculating one normal per face, because when i calculated one per vertices, it was the same for each anyway. is this correct?

also, i am feeding the co-ordinates into my normal function for both rectangles as so:

calcNormals(tl_x, tl_y, tl_z, bl_x, bl_y, bl_z, br_x, br_y, br_z)

where tl = top left, bl = bottom left, and br = bottom right. This is the same order in which they are being drawn in, and yes i am culling the faces.

So should i be feeding the co-ordinates into the second calcNormals call (i.e. the second rectangle) in a different order?


MaxH:
if i disable texturing and lighting, there is no seam

ZbuffeR:
see above about my confusion with normals.

ZbuffeR
01-22-2011, 03:47 AM
You can force road normals to have only vertical component at 1.0, the two others at 0.0 : is it better ?

Anyway, fixed path lighting is very poor, you need to have highly tesselated geometry to get anything passable.
http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/
http://www.opengl.org/resources/faq/technical/lights.htm

These links are all about deprecated OpenGL, and totally superseded by shaders.

dalemac
01-22-2011, 06:42 AM
hi ZbuffeR,

i forced the normals to 0.0,1.0,0.0, but this made no diffence. when i checked the output from the normals function, the values above were the same. (for both rectangles).

Like i said, i am calculating one normal per face, is that correct?

I have read the first link, and i understand the tesselation effect now. but my question is, if i were to split the track length into say 10 seperate rectangles, wouldnt i just be reproducing the split another 10 times?

Im going to read the second article now.

Thanks,

Dale

Dark Photon
01-22-2011, 06:06 PM
I am only calculating one normal per face, because when i calculated one per vertices, it was the same for each anyway. is this correct?
...
if i disable texturing and lighting, there is no seam
What about if you disable texturing but keep lighting. Is there a seam?

If so, then your problem is likely that the normals at the shared vertices don't match between the quads.

If not, then it's a fair bet that the textures don't match. Enable texturing but disable lighting to be sure.


How would i go about implementing your first suggestion?
Before we do that, we should get to the bottom of your problem here first. If the above doesn't nail down your problem, could you post a short GLUT test program that illustrates it? This will also provide a framework to plug in your "per pixel" lighting.

If you want to read ahead on that, here's a good lighting tutorial that describes how to take lighting to the pixel level:

http://www.lighthouse3d.com/opengl/glsl/index.php?lights

MaxH
01-22-2011, 10:31 PM
MaxH:
if i disable texturing and lighting, there is no seam That's not what I meant for you to do. Disable lighting only. Keep the texturing on (like Photon said).

dalemac
01-23-2011, 01:28 PM
Hey guys, thanks for your continued input.

I didnt notice at first, but there does seem to be a small gap in the textures, take a look at the image. (see the red box in the bottom right corner)

how can i get rid of this seam?

Thanks,

Dale

dalemac
01-24-2011, 06:06 AM
I have been doing some research, and this little gap i saw doesnt seem to be causing the problem.

I think the textures "dont match" but im not sure what to do about this!

how can i resolve this issue?

Thanks,

Dale

MaxH
01-24-2011, 01:08 PM
float lightPs[4] = {20, 20, -200, 1}; What happens if you change the 4th element of lightPs from 1 to 0?

dalemac
01-24-2011, 02:48 PM
What happens if you change the 4th element of lightPs from 1 to 0?

Hey MaxH,

If i change the values from 1 to 0, it doesnt make any noticable difference, and the lighting is as it was in the first attachment.

Dale

MaxH
01-24-2011, 03:10 PM
I think the textures "dont match" but im not sure what to do about this! You are using 2 different images for your textures, correct?
If you display them as images side by side with Photoshop or something similar,
do they match up along the shared edge?
Might be time to post your code, or just the parts where the road is defined and displayed.

MaxH
01-24-2011, 03:28 PM
void initLighting()
{
GLfloat lightLa[ ] = {1.0, 0.0, 0.0, 1.0}; // ambient
GLfloat lightLd[ ] = {1.0, 1.0, 1.0, 1.0}; // diffuse
GLfloat lightLs[ ] = {1.0, 1.0, 1.0, 1.0}; // specular
float lightPs[4] = { 20, 20, -200, 1 }; // position

glLightfv (GL_LIGHT0, GL_AMBIENT , lightLa);
glLightfv (GL_LIGHT0, GL_DIFFUSE , lightLd);
glLightfv (GL_LIGHT0, GL_SPECULAR, lightLs);
glLightfv (GL_LIGHT0, GL_POSITION, lightPs);

GLfloat materialMs[] = {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat materialMe[] = {1.0f, 1.0f, 1.0f, 1.0f};

glLightfv (GL_LIGHT0, GL_AMBIENT, materialMs);
glLightfv (GL_LIGHT0, GL_DIFFUSE, materialMe);

glEnable (GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0);
}

Did you realize that you are defining the ambient and diffuse properties of LIGHT0 twice -
first to 'lightLa' and 'lightLd', then to 'materialMs' and 'materialMe'?
Perhaps you meant to use Material commands instead of glLight commands the second time?
Would make more sense.

dalemac
01-24-2011, 03:38 PM
Yes, you are right there, i have sorted that now.

I am indeed using two textures, one for the majority of the length, the other for the start of the track.

Just looking at my textures in photoshop now.


Dale

dalemac
01-24-2011, 03:45 PM
For the most part, the texture is a perfect match, however there is a slight issue with the lines on the track texture.

I will fix these and report back.

Thanks for the suggestion!

Dale

dalemac
01-24-2011, 04:25 PM
Ok, so to be sure, i removed the 'noise' from the texture, made all the lines solid etc.

But there is still a gap in between the two textures. which is being highlighted by the lighting. As a test, i moved the track rectangle back by 0.1, this removed the gap, but the lighting seam is still there.

Here are all code regarding the track drawing and texturing:



//track start arrays
GLfloat trackStartVertices[] = {0,0,-37, 0,0,0, 64,0,0, 64,0,-37 }; // tl-bl-br-tr
GLfloat trackStartTexcoords[] = {0.0,0.0, 0.0,1.0, 1.0,1.0, 1.0,0.0 }; // tl-bl-br-tr
GLubyte trackStartIndices[] = {0,1,2,3};

//track arrays
GLfloat trackVertices[] = {0,0,-1000, 0,0,0, 64,0,0, 64,0,-1000 }; // tl-bl-br-tr
GLfloat trackTexcoord[] = {0.0,0.0, 0.0,20.0, 1.0,20.0, 1.0,0.0 }; // tl-bl-br-tr
GLubyte trackIndices[] = {0,1,2,3};
void drawTrack()
{
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glPushMatrix();
//start of track
glBindTexture(GL_TEXTURE_2D, textureID[TRACK_START]); //bind the correct texture
glVertexPointer(3, GL_FLOAT, 0, trackStartVertices); //set the appropriate vertex array
glTexCoordPointer(2, GL_FLOAT, 0, trackStartTexcoords); //set the appropriate texture array
//calculate the normals
CalcNormal(trackStartVertices[0],trackStartVertices[1],trackStartVertices[2], //tl
trackStartVertices[3],trackStartVertices[4],trackStartVertices[5], //bl
trackStartVertices[6],trackStartVertices[7],trackStartVertices[8]); //br

GLfloat trackStartNormals[] = {normal[0],normal[1],normal[2]};
glNormalPointer(GL_FLOAT, 0, trackStartNormals); //set the appropriate normal pointer
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, trackStartIndices);

glTranslatef(0,0,-37);

//track length
glBindTexture(GL_TEXTURE_2D, textureID[TRACK_TEXTURE]); //bind the correct texture
glVertexPointer(3, GL_FLOAT, 0, trackVertices); //set the appropriate vertex array
glTexCoordPointer(2, GL_FLOAT, 0, trackTexcoord);
//set the appropriate texture array
//calculate the normals
CalcNormal(trackVertices[0],trackVertices[1],trackVertices[2], //tl
trackVertices[3],trackVertices[4],trackVertices[5], //bl
trackVertices[6],trackVertices[7],trackVertices[8]); //br
GLfloat trackNormals[] = {normal[0],normal[1],normal[2]};
glNormalPointer(GL_FLOAT, 0, trackNormals); //set the appropriate normal pointer
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, trackIndices);

glPopMatrix();

glDisableClientState(GL_NORMAL_ARRAY); //disable normal arrays
glDisableClientState(GL_VERTEX_ARRAY); // disable vertex arrays
glDisableClientState(GL_TEXTURE_COORD_ARRAY); //disable texture co-ordinate arrays

}


and the normals function, just incase:


void CalcNormal(float p1_x,float p1_y,float p1_z,float p2_x,float p2_y,float p2_z,float p3_x,float p3_y,float p3_z)
{
// Calculate vectors
float var1_x = p1_x - p2_x;
float var1_y = p1_y - p2_y;
float var1_z = p1_z - p2_z;


float var2_x = p3_x - p2_x;
float var2_y = p3_y - p2_y;
float var2_z = p3_z - p2_z;

// Get cross product of vectors
normal[0] = (var1_y * var2_z) - (var2_y * var1_z);
normal[1] = (var1_z * var2_x) - (var2_z * var1_x);
normal[2] = (var1_x * var2_y) - (var2_x * var1_y);

// Normalise final vector
float vLen = sqrt( (normal[0] * normal[0]) + (normal[1] * normal[1]) + (normal[2] * normal[2]) );

normal[0] = normal[0]/vLen;
normal[1] = normal[1]/vLen;
normal[2] = normal[2]/vLen;
//printf("\n nx : %f ny %f nz %f",normal[0], normal[1],normal[2]);
}


Thanks for the help,

Dale

MaxH
01-24-2011, 05:50 PM
I think the problem is with your normals. Where is the line of code where 'normals' is defined?

As a quick experiment - try commenting out both calls to glNormalPointer,
and instead using glNormal3f (0,1,0).

dalemac
01-25-2011, 02:24 AM
I think the problem is with your normals. Where is the line of code where 'normals' is defined?

As a quick experiment - try commenting out both calls to glNormalPointer,
and instead using glNormal3f (0,1,0).



The normals are built in the above code segment, where calcNormals is called.



CalcNormal(trackStartVertices[0],trackStartVertices[1],trackStartVertices[2], //tl
trackStartVertices[3],trackStartVertices[4],trackStartVertices[5], //bl
trackStartVertices[6],trackStartVertices[7],trackStartVertices[8]); //br

GLfloat trackStartNormals[] = {normal[0],normal[1],normal[2]};
glNormalPointer(GL_FLOAT, 0, trackStartNormals);


I will use glNormal3f and see if it makes a difference.

Dale

dalemac
01-25-2011, 03:38 AM
i tried using glNormal3f instead, but the results are exactly the same.


This is beginning to fustrate me now!

Dale

Dan Bartlett
01-25-2011, 03:57 AM
If you use the same texture for both parts, do you still get a lighting issue? Or is it just that the road textures are different shades of grey? In which case you're unlikely to ever get them to match up.

dalemac
01-25-2011, 04:05 AM
If you use the same texture for both parts, do you still get a lighting issue? Or is it just that the road textures are different shades of grey? In which case you're unlikely to ever get them to match up.

Hi Dan, welcome to the thread!

I just bound the track texture to the start t test this, but unforunately the issue is still the same.

I think this is a normals issue, i must be doing something stupid somewhere!

I have been adding normals to my normals array per vertex now, but then there is no lighting at all!

Dale

Dark Photon
01-25-2011, 04:38 AM
The normals are built in the above code segment, where calcNormals is called.
This function just computes a face normal from three points. If you pass in 3 different points to compute the normal at the same point, you're going to get a different normal.

Here's your track:



A--B
| |
| |
C--D
| |
| |
E F


If, for the top quad, you compute the normal at C with A-C-D, and if for the bottom quad, you compute the normal at C with D-C-E, you're going to end up with a different normal at C and thus a different lighting result at C for the 2 quads (unless the two quads are coplanar).

I don't know if this is your problem, but it's at least a possibility to consider. If so, the solution is to use the same normal for C between the two quads (and for D of course). In other words, compute your normal differently.

Normals should represent the normal of the real surface you're trying to represent, not the tessellated representation. Then when you interpolate lighting (or even better, normals, with shaders), then you get a nice smooth result.

dalemac
01-25-2011, 05:09 AM
[quote=dalemac]
If, for the top quad, you compute the normal at C with A-C-D, and if for the bottom quad, you compute the normal at C with D-C-E, you're going to end up with a different normal at C and thus a different lighting result at C for the 2 quads (unless the two quads are coplanar).


currently, i am calculating the normals using the bottom left, using the top left and bottom right points to make the triangle. or as in your representation, for the first quad, computing the normal at b using a & d, and for the second quad, computing the normal at d using c & f.

So i should compute the normal at a different point for the second rectangle? i.e. f using d & e?


Or should creating the normals for the track as a whole, i.e. to get the normal of a, use b & f?

Thanks,

Dale

Dan Bartlett
01-25-2011, 05:20 AM
With your current code, you aren't providing enough normals. You need 1 normal per vertex if using glNormalPointer.

So you should have the equivalent of:
GLfloat trackStartNormals[] = {normal[0],normal[1],normal[2], normal[0],normal[1],normal[2], normal[0],normal[1],normal[2], normal[0],normal[1],normal[2]} ;

dalemac
01-25-2011, 05:25 AM
With your current code, you aren't providing enough normals. You need 1 normal per vertex if using glNormalPointer.

So you should have the equivalent of:
GLfloat trackStartNormals[] = {normal[0],normal[1],normal[2], normal[0],normal[1],normal[2], normal[0],normal[1],normal[2], normal[0],normal[1],normal[2]} ;


Yes, i have been experimenting with this all morning, and if i pass through 4 sets of normals, i get one unified lighting effect over the whole quad, but this is probably because i am not recalculating the normals again, just copying them over.

That is what im going to do next!

Dale

dalemac
01-25-2011, 05:49 AM
Ok, so have have recalculated the normals 4 times, once for each vertex, and added to the normals array as appropriate.

However, after printing all of the normals for each vertex, the are all : (0,-1,0) for each vertex. is this what you would expect to get for a flat quad?

Dale

________________

EDIT: I think i have this solved now, as there is no more seams in the scene!

This is mainly down to two things:
how i was declaring my normals with the normal pointer.

My mistake in assigning material properties to the objects - no light was being reflected.

The scene is now well lit and looking good!

Thanks to everyone who has helped me get this solved :)

Dale