Jump to content

  • Log In with Google      Sign In   
  • Create Account


Batch2

Member Since 13 May 2012
Offline Last Active May 27 2012 09:21 PM
-----

Topics I've Started

Terrain lighting

13 May 2012 - 02:48 PM

Hi so I've been trying to calculate normals and lighting for randomly generated terrain. Largely the process has been sucessful however I have notice one odd effect. If you look at the picture below you will see that I get an odd checker effect on the terrain on poorly lit portions.
Attached File  Untitled.jpg   40.76KB   36 downloads
The edges appear dark but the center is bright. I believe this to be an issue with calculation of the surface normals. To test this I have disabled lighting and output the normals as color in my fragment shader. I see the same effect.
Here's the code I use to calculate the surface normals.
Vert normalizeVert(Vert old_vert) {
Vert new_vert;
float old_length;
old_length = sqrt(pow(old_vert.xcorr, 2.0f) + pow(old_vert.ycorr, 2.0f) + pow(old_vert.zcorr, 2.0f));
new_vert.xcorr = old_vert.xcorr / old_length;
new_vert.ycorr = old_vert.ycorr / old_length;
new_vert.zcorr = old_vert.zcorr / old_length;
return new_vert;
}
;
// Calculate normals for terrain.
void NSheet::calculateNormals(void) {
// First create an object to store all the surface normals
unsigned int num_surfaceNormals = pow(sheet_size - 1, 2) * 2;
Vert* surfaceNormals = new Vert[num_surfaceNormals];
Face* faces = amesh->faces;
// temporary vertices used in calculation
Vert vert1, vert2, vert3, temp_vert;
//retrieve pointer to indices
unsigned int* indices = faces->indices;
// retrieve pointer to mesh data
float* verts = faces->verts;
// compute all surface normals
for (unsigned int i = 0; i < num_surfaceNormals; i++) {
  vert1.xcorr = verts[indices[i * 3 + 0] * 4 + 0];
  vert1.ycorr = verts[indices[i * 3 + 0] * 4 + 1];
  vert1.zcorr = verts[indices[i * 3 + 0] * 4 + 2];
  vert2.xcorr = verts[indices[i * 3 + 1] * 4 + 0];
  vert2.ycorr = verts[indices[i * 3 + 1] * 4 + 1];
  vert2.zcorr = verts[indices[i * 3 + 1] * 4 + 2];
  vert3.xcorr = verts[indices[i * 3 + 2] * 4 + 0];
  vert3.ycorr = verts[indices[i * 3 + 2] * 4 + 1];
  vert3.zcorr = verts[indices[i * 3 + 2] * 4 + 2];
  // Calculate surface normal.  % overloaded to produce cross product
  surfaceNormals[i] = (vert2 - vert1) % (vert3 - vert1);
  // normalize surface normal
  surfaceNormals[i] = normalizeVert(surfaceNormals[i]);
}
// create an array to hold vertex normal data
faces->num_normals = pow(sheet_size, 2) * 3;
amesh->num_normals = faces->num_normals;
faces->normals = new float[faces->num_normals];
// This variable represents that distance in the normal array between y units in the array of surface normals
unsigned int y_step = 2 * (sheet_size - 1);
// calculate the normal values for each vertex
for (unsigned int i = 0; i < sheet_size; i++)
  for (unsigned int j = 0; j < sheet_size; j++) {
   // the current location in the surface normal array
   unsigned int displacement = i * y_step + j * 2;
   // the current location in the vertex normal array
   unsigned int vertex_displacement = (i * sheet_size + j) * 3;
   // blank the temp vertex
   temp_vert.xcorr = 0.0f;
   temp_vert.ycorr = 0.0f;
   temp_vert.zcorr = 0.0f;
   // average the vertices for the surrounding polygons
   if (i > 0 && j < sheet_size - 1) { // if has square at top right
	temp_vert = temp_vert + (surfaceNormals[displacement - y_step] * 2);
   }
   if (i > 0 && j > 0) { // if has square at top left
	temp_vert = temp_vert + surfaceNormals[displacement - y_step - 2] + surfaceNormals[displacement - y_step - 1];
   }
   if (i < sheet_size - 1 && j < sheet_size - 1) { // if has square at bottom right
	temp_vert = temp_vert + surfaceNormals[displacement] + surfaceNormals[displacement + 1];
   }
   if (i < sheet_size - 1 && j > 0) { // if square at bottom left
	temp_vert = temp_vert + (surfaceNormals[displacement - 1] * 2);
   }
   // normalize the temporary vertex
   temp_vert = normalizeVert(temp_vert);
   // set the normal data
   faces->normals[vertex_displacement] = temp_vert.xcorr;
   faces->normals[vertex_displacement + 1] = temp_vert.ycorr;
   faces->normals[vertex_displacement + 2] = temp_vert.zcorr;
  }
amesh->has_normals = true; // set to true automatically once normals are calculated
// Free memory
delete[] surfaceNormals;
}

It uses that standard method that I have seen where you calculate a surface normal for each polygon and then average those for the verts. My best guess is that my error is here somewhere but I can't figure out where...

Anyways thanks for taking the time to read this post.

PARTNERS