I feel like an idiot. What im trying to do is light a terrain using per-surface shading. Ive looked in MANY other posts and sites but none of them clear up my confusion, maybe you can help.

To draw my terrain I use triangle strips but only declare 2 verticies, to be honest I dont know how you get a triangle from 2 vertices but its on most sites and it works so I use it.

Ive read to get normals to get a 2 vectors from 3 different verticies on a triangle, but im confused. You’re supposed to do v[0] = v1 - v2 and so on. But I thought a vertice consisted of 3 variables - a x, y, and z coord. So how would you subtract 2 vertices consisting of 3 coords each?!?! or is it supposed to be v[0] = x - y: like that?

Ill do whatever it takes; if you think posting my code up here would help let me know!


v = v1 - v2 means, that v, v1 and v2 are vectors. So v, v1 and v2 each consist of x, y and z. Using C++ you could define e.g. a vector class and do operations on it (like v = v1 - v2).
Otherwise, do this for each component (x, y and z).

Having those two vectors you calculate the cross product and get the vector standing perpendicular on those two… maybe thats the normal vector you wanted. But if you want a smoothed terrain, you have to average the vector between all triangles using that point.


A vector in 3d is an ordered triple of components (x, y, z). You add or subtract two vectors by adding or subtracting their respective components. A vertex in OpenGL is represented by a vector from the origin (0, 0, 0) to a point in space (x, y, z). To get a normal to a triangle face defined by 3 vertices let’s say a = (x1, y1, z1), b = (x2, y2, z2) and c (x3, y3, z3), you have to calculate vectors that form the edges of the triangle. You do that by subtracting a from b and c. The two vectors you get are d = b - a = (x2 - x1, y2 - y1, z2 - z1) and e = c - a = (x3 - x1, y3 - y1, z3 - z1). To calculate a surface normal, you have to take a cross product of vectors d and e, which is a vector perpendicular to both of them.

You have a question that I have the answer for, to be blunt this is my normal generation function for my terrain engine:

void GenerateNormals(void){
float vec1_x, vec1_y, vec1_z, vec2_x, vec2_y, vec2_z;
float bigx, bigy, bigz;
float x1, x2, x3, y1, y2, y3, z1, z2, z3;

for(mapx=0; mapx<TERRAIN_WIDTH; mapx++){
for(mapz=0; mapz<TERRAIN_LENGTH; mapz++){
x1 = mapx/DETAIL;
y1 = map[mapx][mapz];
z1 = mapz/DETAIL;
x2 = mapx/DETAIL;
y2 = map[mapx][mapz+1];
z2 = (mapz+1)/DETAIL;
x3 = (mapx+1)/DETAIL;
y3 = map[mapx+1][mapz];
z3 = mapz/DETAIL;

  vec1_x = x2 - x1;
  vec1_y = y2 - y1;
  vec1_z = z2 - z1;
  vec2_x = x3 - x1;
  vec2_y = y3 - y1;
  vec2_z = z3 - z1;

  bigx = (vec1_y*vec2_z) - (vec1_z*vec2_y);
  bigy = (vec1_z*vec2_x) - (vec1_x*vec2_z);
  bigz = (vec1_x*vec2_y) - (vec1_y*vec2_x);

  normal[mapx][mapz].x = bigx/sqrt(bigx*bigx + bigy*bigy + bigz*bigz);
  normal[mapx][mapz].y = bigy/sqrt(bigx*bigx + bigy*bigy + bigz*bigz);
  normal[mapz][mapz].z = bigz/sqrt(bigx*bigx + bigy*bigy + bigz*bigz);

for(mapx=0; mapx<TERRAIN_WIDTH; mapx++){
for(mapz=0; mapz<TERRAIN_LENGTH; mapz++){
normal[mapx][mapz].x = normal[mapx][mapz].x+normal[mapx+1][mapz].x+normal[mapx][mapz+1].x+normal[mapx+1][mapz+1].x;
normal[mapx][mapz].y = normal[mapx][mapz].y+normal[mapx+1][mapz].y+normal[mapx][mapz+1].y+normal[mapx+1][mapz+1].y;
normal[mapx][mapz].z = normal[mapx][mapz].z+normal[mapx+1][mapz].z+normal[mapx][mapz+1].z+normal[mapx+1][mapz+1].z;

  normal[mapx][mapz].x = normal[mapx][mapz].x * 1/4.0;
  normal[mapx][mapz].y = normal[mapx][mapz].y * 1/4.0;
  normal[mapx][mapz].z = normal[mapx][mapz].z * 1/4.0;


hmmm, tell me if you need more help.
Also, this may not be the most efficient way of doing things but hey…

[This message has been edited by MrShoe (edited 07-20-2001).]