• Create Account

FREE SOFTWARE GIVEAWAY

We have 4 x Pro Licences (valued at \$59 each) for 2d modular animation software Spriter to give away in this Thursday's GDNet Direct email newsletter.

Read more in this forum topic or make sure you're signed up (from the right-hand sidebar on the homepage) and read Thursday's newsletter to get in the running!

# Batch2

Member Since 13 May 2012
Offline Last Active Oct 23 2014 08:23 AM

### 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.
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