I can’t get my terrain to be properly lit, and my problem resides of course in the normals.
I generate the terrain with triangle strips, with the code:
for (int z = 0; z < tsize-1; z++)
{
glBegin(GL_TRIANGLE_STRIP);
for (int x=0; x < tsize-1; x++)
{
v_height = hmap.GetValue(x,z);
scaledHeight = v_height * h_scale;
glNormal3fv (normals[x*tsize+z]);
glVertex3f ((GLfloat) x, scaledHeight, (GLfloat) z);
v_height = hmap.GetValue(x,z+1);
scaledHeight = v_height * h_scale;
glNormal3fv (normals[(x*tsize)+z+1]);
glVertex3f ((GLfloat)x, scaledHeight, (GLfloat)z+1);
}
glEnd();
}
As you see, triangles are generated like this:
B\---D\---
| \ | \
| \ | \
| \| \
A----C---E-
Tris are ABC, CDE…etc.
This triangles of course are generating a terrain geometry… and I need to calculate normals for it.
The method which I think should work is:
- For every vertex A choose neighbour vertices B and C that share the same triangle as A.
- Take vectors B-A and C-A, do cross product (B-A)x(C-A)
- Normalize cross product.
- We have our normal for the vertex.
But of course this generates very sharp lighting, so for I need to average more vectors in case of vertices that share more than one triangle.
M\---N\---O\---P
| \ | \ | \ |
| \ | \| \ |
I\--\J----k\--\L
| \ | \ | \ |
| \ | \| \ |
E\--\F\---G---\H
| \ | \ | \ |
| \ | \ | \ |
A----B----C----D
Well, let's go for a little pseudocode:
IF VTX=A
N=NORM((E-A)x(B-A))
// this shares two triangles BEF and BFC
IF VTX=B
V1=(E-B)
V2=(F-B)
V3=(C-B)
VP=(V1xV2+V2xV3)/2
N=NORM(VP)
// a inner vertex like F shares triangles FIJ, FJG, BEF, BFC
and so on...
Should this work or can I use another methods for smooth lighting?
At last, should my normals be 1 at Y (height) or must be multiplied by the height-scale of my terrain vertices?
thank you!