OpenGL Programming/Intermediate/Normals

From Wikibooks, open books for an open world
Jump to navigation Jump to search

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 | edit source]

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 | edit source]

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