Extending on the previous tutorial's spinning cube code, this tutorial will explain how to calculate your cube's face normals and add OpenGL lighting to your program.

When you've completed this tutorial, you should have a good enough understanding of the of OpenGL lighting to be able to use it in your own code.

We'll be using the same code as we used in the previous tutorial, so load it up and we'll begin.

[size="5"]The Code

The first thing we'll do is add normals to our cube quad struct. Normals are vectors of length 1 which indicate the angle of facing of a polygon. The cube struct should now look like this:

`struct `

{

struct

{

float pos[3];

float col[3];

}ver[8];

struct

{

unsigned int ver[6];

float norm[3];

}quad[6];

}cube;

`typedef struct`

{

float pos[4];

float diffuse[4];

float specular[4];

float ambient[4];

}light_t;

`light_t light={`

{6,10,15,1}, //position (the final 1 means the light is positional)

{1,1,1,1}, //diffuse

{0,0,0,1}, //specular

{0,0,0,1} //ambient

};

`glEnable(GL_LIGHTING); //enables lighting`

glEnable(GL_LIGHT0); //enables a light

glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,0); //sets lighting to one-sided

`glEnable(GL_COLOR_MATERIAL);`

`glColorMaterial(GL_FRONT,GL_DIFFUSE);`

`float black[4]={0,0,0,0};`

glMaterialfv(GL_FRONT,GL_AMBIENT,black);

glMaterialfv(GL_FRONT,GL_SPECULAR,black);

`void crossProduct(float *c,float a[3], float b[3]);`

void normalize(float *vect);

void getFaceNormal(float *norm,float pointa[3],float pointb[3],float pointc[3]);

The first thing it'll do is copy the points pointa, pointb and pointc into a 2-dimensional array, point[ ] [ ].

`void `

getFaceNormal(float *norm,float pointa[3],float pointb[3],float pointc[3])

{

float vect[2][3];

int a,b;

float point[3][3];

for (a=0;a<3;++a)

{

point[0][a]=pointa[a]; //copies points into point[][]

point[1][a]=pointb[a];

point[2][a]=pointc[a];

}

` for (a=0;a<2;++a) //calculates vectors from point[0] to point[1]`

{ //and point[0] to point[2]

for (b=0;b<3;++b)

{

vect[a]=point[2-a]-point[0];

}

}

` crossProduct(norm,vect[0],vect[1]); //calculates vector at 90? to to 2 vectors`

normalize(norm); //makes the vector length 1

}

`void crossProduct(float *c,float a[3], float b[3]) //finds the cross product of two vectors`

{

c[0]=a[1]*b[2] - b[1]*a[2];

c[1]=a[2]*b[0] - b[2]*a[0];

c[2]=a[0]*b[1] - b[0]*a[1];

}

`length=sqrt( //A^2 + B^2 + C^2 = length^2`

pow(vect[0],2)+

pow(vect[1],2)+

pow(vect[2],2)

);

`for (a=0;a<3;++a) `

{

vect[a]/=length;

}

`for (a=0;a<6;++a)`

{

getFaceNormal(cube.quad[a].norm, cube.ver[ cube.quad[a].ver[2] ].pos,

cube.ver[ cube.quad[a].ver[1] ].pos,

cube.ver[ cube.quad[a].ver[0] ].pos);

}

`glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);`

glLightfv(GL_LIGHT0,GL_POSITION,light.pos); //updates the light's position

glLightfv(GL_LIGHT0,GL_DIFFUSE,light.diffuse); //updates the light's diffuse colour

glLightfv(GL_LIGHT0,GL_SPECULAR,light.specular); //updates the light's specular colour

glLightfv(GL_LIGHT0,GL_AMBIENT,light.ambient); //updates the light's ambient colour

glPushMatrix();

`for (a=0;a<6;++a)`

{

glNormal3fv(cube.quad[ a ].norm); //sets the current normal to this quad's normal

for (b=0;b<4;++b)

{

currentVer=cube.quad[a].ver;

This tutorial is Copyright (C) 2001 Ben Woodhouse