OpenGL Programming/Intermediate/Normals

You can specify normals for faces you create. This is a vector that's perpendicular to the face. Specifying normals is important if you plan to use lighting. They tell OpenGL how the light is to be reflected. Although OpenGL is not a raytracer, it still influences how bright you see the face. OpenGL will not calculate the normals itself, you have to do it manually.

Specifying Normals

edit

Normals are specified using the function glNormal3f and used before you make the vertices that belong to the face. Example:

// Create a square on the XY axis. The normal vector is then (0, 0, 1)
glBegin(GL_QUADS);
    glNormal3f(0.0, 0.0, 1.0);
    glVertex3f(0.0, 0.0, 0.0);
    glVertex3f(0.0, 1.0, 0.0);
    glVertex3f(1.0, 1.0, 0.0);
    glVertex3f(1.0, 0.0, 0.0);
glEnd();

Calculating Normals

edit

There is a quite simple approach for calculating the normal vector for a triangle. Given p1, p2 and p3, the normal vector can be expressed as the cross product of (p2 - p1) and (p3 - p1), divided by the length of the result. In C code, using a struct type for the vectors:

struct vector a, b, n;
double l;

a.x = p2.x - p1.x;
a.y = p2.y - p1.y;
a.z = p2.z - p1.z;

b.x = p3.x - p1.x;
b.y = p3.y - p1.y;
b.z = p3.z - p1.z;

n.x = (a.y * b.z) - (a.z * b.y);
n.y = (a.z * b.x) - (a.x * b.z);
n.z = (a.x * b.y) - (a.y * b.x);

// Normalize (divide by root of dot product)
l = sqrt(n.x * n.x + n.y * n.y + n.z * n.z);
n.x /= l;
n.y /= l;
n.z /= l;

// Now pass n.x, n.y, n.z to glNormal3f