We looked more closely at shadows today, covering the material in
5.9 of our text. To cast a shadow of a polygon, we move the origin to
the light source (L_{x},L_{y},L_{z}), find the
coordinates of x and z when y is -L_{y}
along the ray from the light source to a given vertex, then translate
back to where we were. We calculated our own projection matrix, shown
on page 234 of our text. You can use your own 4x4 matrices in OpenGL by
creating a one-dimensional array *m* with the 4x4 array entries
listed in column-major order (ordered by columns rather than the usual
order by rows). Then *glMultMatrix(m)* will apply the
transformation.

Following is a short program which illustrates shadows by having a light source rotate around a cube. Every time the light makes a complete circle, it is raised by a short distance (thus casting shorter shadows). Here's the program:

// By Late Dr. Mark Harris#include <math.h>

#include <GL/glut.h>

typedef GLfloat point3[3];

GLfloat LightRadius=4;

GLfloat LightHeight=2;

GLfloat Lx=LightRadius,Ly=LightHeight,Lz=0;

double PI,PI2;

GLfloat m[16]={

1,0,0,0,

0,1,0,0,

0,0,1,0,

0,0,0,0};

GLfloat t=0;

// List all vertices in array and reference later by index

point3 p[8]={

{0,0,0},

{0,0,1},

{1,0,1},

{1,0,0},

{0,1,0},

{0,1,1},

{1,1,1},

{1,1,0}

};

void drawPoint(int i,int shadow){

// Draw point i in color i

if(shadow)glColor3f(0,0,0);

else glColor3fv(p[i]);

glVertex3fv(p[i]);

}

void drawFace(int i1,int i2,int i3,int i4, int shadow){

// draw a face of the cube

glBegin(GL_POLYGON);

drawPoint(i1,shadow);

drawPoint(i2,shadow);

drawPoint(i3,shadow);

drawPoint(i4,shadow);

glEnd();

}

void myinit(void)

{

PI=atan(1.0)*4;

PI2=2*PI;

m[7]=-1/Ly;

/* attributes */

glClearColor(1.0, 1.0, 1.0, 1.0); /* white background */

glColor3f(0.0, 0.0, 0.0); /* draw in black */

/* set up viewing */

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

double w=.1;

glFrustum(-w,w,-w,w,.2,10);

}

void drawCube(int shadow)

{

drawFace(0,3,2,1,shadow); //bottom

drawFace(1,2,6,5,shadow); //front

drawFace(2,3,7,6,shadow); //right side

drawFace(0,1,5,4,shadow); //left side

drawFace(3,0,4,7,shadow); //back side

drawFace(4,5,6,7,shadow); //top

}

void display( void )

{

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); /*clear the window */

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

gluLookAt(4,2,4,0,0,0,0,1,0);

drawCube(0);

glTranslatef(Lx,Ly,Lz); //translate back

glMultMatrixf(m);

glTranslatef(-Lx,-Ly,-Lz);

drawCube(1);

glFlush(); /* clear buffers */

glutSwapBuffers();

}

void idle()

{

t+=.1;

Lx=LightRadius*cos(t);

Ly=LightHeight;

Lz=LightRadius*sin(t);

m[7]=-1/Ly;

if(t>=PI2){

t-=PI2;

LightHeight+=.5;

}

glutPostRedisplay();

}

void main(int argc, char** argv)

{

/* Standard GLUT initialization */

glutInit(&argc,argv);

glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB|GLUT_DEPTH);

glutInitWindowSize(500,500); /* 500 x 500 pixel window */

glutInitWindowPosition(0,0); /* place window top left on display */

glutCreateWindow("Cube"); /* window title */

glutDisplayFunc(display); /* display callback invoked when window opened */

glutIdleFunc(idle);

myinit(); /* set attributes */

glEnable(GL_DEPTH_TEST); /* Enable hidden--surface--removal */

glEnable(GL_SMOOTH); /* Enable smooth shading and color interpolation */

glutMainLoop(); /* enter event loop */

}

Here's a sample image from the resulting animation:

We talked about lighting models.

A real light source is very complex. A light bulb emits light of various wavelengths from various points, and the cumulative effect at a target involves lots of integral calculus.

We approximate light sources using one of three types:

- point sources
- spot lights, in which a a point on the object is proportional to the angle between the surface normal and the light source. If we have both directions available as unit vectors, we can find this cosine as just the dot product of the vectors, which is a very fast operation.

Ambient lighting is a global approximation to uniform lighting. For example, if we have many fluorescent bulbs in the ceiling, the net effect might be uniform lighting. It is much faster to simply set a given light intensity at all points than to integrate over all the light sources.

Please read chapter 6 through 6.3.2.