Archived

This topic is now archived and is closed to further replies.

JonW

Pixelated lighting on heightmapped terrain

Recommended Posts

Hi, I have some randomly generated islands and I would like to use OpenGL's lighting to give shape to the hills. It turned out as I planned, but the tiles become severely "pixelated": Screenshot - 72kb Here is the code for terrain rendering:
        
	glBegin( GL_QUADS );					// Render Quads

	CVector3 vQuad[4];

	for ( X = 0; X < NUM_TILES; X++ )
	{
		for ( Y = 0; Y < NUM_TILES; Y++ )
		{
			// Get the (X, Y, Z) value for the bottom left vertex		

			vQuad[0].x = X;
			vQuad[0].y = GetVertex(X, Y)->nHeight;
			vQuad[0].z = Y;

			// Get the (X, Y, Z) value for the top right vertex		

			vQuad[1].x = X + 1; 
			vQuad[1].y = GetVertex(X + 1, Y + 1)->nHeight; 
			vQuad[1].z = Y + 1;

			// Get the (X, Y, Z) value for the top left vertex		

			vQuad[2].x = X;										
			vQuad[2].y = GetVertex(X, Y + 1)->nHeight; 
			vQuad[2].z = Y + 1;

			// Get the (X, Y, Z) value for the bottom right vertex		

			vQuad[3].x = X + 1;
			vQuad[3].y = GetVertex(X + 1, Y)->nHeight; 
			vQuad[3].z = Y;

			// Set the normal for this quad

			CVector3 vNormal = Normal(vQuad);
			glNormal3f(vNormal.x, vNormal.y, vNormal.z);

			// Render the vertices


			SetVertexColor(pVertices, vQuad[0].x, vQuad[0].z);
			glVertex3i(vQuad[0].x * TILE_SIZE, vQuad[0].y,
				vQuad[0].z * TILE_SIZE);

			SetVertexColor(pVertices, vQuad[2].x, vQuad[2].z);
			glVertex3i(vQuad[2].x * TILE_SIZE, vQuad[2].y,
				vQuad[2].z * TILE_SIZE);

			SetVertexColor(pVertices, vQuad[1].x, vQuad[1].z);
			glVertex3i(vQuad[1].x * TILE_SIZE, vQuad[1].y,
				vQuad[1].z * TILE_SIZE);

			SetVertexColor(pVertices, vQuad[3].x, vQuad[3].z);
			glVertex3i(vQuad[3].x * TILE_SIZE, vQuad[3].y,
				vQuad[3].z * TILE_SIZE);
		}
	}

	glEnd();

	// Reset the color

	glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
  
The light setup:
  
	float ambience[4] = {0.3f, 0.3f, 0.3f, 1.0};		// The color of the default light in the world

	float diffuse[4] = {0.5f, 0.5f, 0.5f, 1.0};			// The color of the positioned light


	glLightfv( GL_LIGHT0, GL_AMBIENT,  ambience );
	glLightfv( GL_LIGHT0, GL_DIFFUSE,  diffuse );
	glLightfv( GL_LIGHT0, GL_POSITION, g_LightPosition );

	glEnable(  GL_LIGHT0   );								// Turn this light on

	glEnable(  GL_LIGHTING );								// This turns on lighting


	// Allow us to use colors on our polygons during lighting

	glEnable(GL_COLOR_MATERIAL);
  
And finally the normal function:
  
CVector3 Normal(CVector3 vTriangle[])
{
	CVector3 vVector1 = Vector(vTriangle[2], vTriangle[0]);
	CVector3 vVector2 = Vector(vTriangle[1], vTriangle[0]);

	// Calculate normal

	CVector3 vNormal = Cross(vVector1, vVector2);

	// Normalize it to 1

	vNormal = Normalize(vNormal);

	return vNormal;
}
  
I think this is because each 16x16 quad has its own normal, so each one has slightly different lighting. Any suggestions on how I can correct it? The quads are not textured, just colored. Would texturing them help? Thanks in advance! [edited by - JonWoyame on May 28, 2003 3:42:10 PM]

Share this post


Link to post
Share on other sites
Looks like you need to specify a different normal for each vertex in each quad. This can be done by inserting glNormal calls before each vertex in the rendering loop. These normals need to be calculated as an average between adjacent quads to get a smoothing effect.

I should probably be working now...

Share this post


Link to post
Share on other sites
I never thought about using a different normal for each vert, but that probably would work! I''ll try that out tomarrow and share the results.

Thanks!

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
You might try looking up the command glShadeModel(). Using
glShadeModel(GL_SMOOTH) in your display function will cause the lighting to determine the normal for a particular spot on a surface by interpolating the normals at each vertex.

Consequently, you must calculate the normal at each vertex (this doesn''t make sense, formally), but it is what is needed.
The vertex normal is the weighted average of polygon normals that share the vertex.

n = n1 + n2 + n3 + n4 / | n1 + n2 + n3 + n4 |

(if there were 4 polys at the vertex)

Share this post


Link to post
Share on other sites
Thanks, the scene looks great now. I didn''t have to enable smooth shading (according to MSDN it is the default value). I got caught up for a while because for some reason I mistakenly calculated the normalized sum of the surrounding vertices'' normals, rather than the sum of the faces sharing the vertex. Doh!

Share this post


Link to post
Share on other sites