Little Lighting issue

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

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.

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?

Did you check your normals ? If they are not continuous, you will see discontinuities like that.

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.

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.

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

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

That’s not what I meant for you to do. Disable lighting only. Keep the texturing on (like Photon said).

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

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

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

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.

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.

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

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

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("
 nx : %f ny %f nz %f",normal[0], normal[1],normal[2]);
 }

Thanks for the help,

Dale

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