Here is the code of the shadow rendering.
void CastShadow(glObject *o, float *lp){
unsigned int i, j, k, jj;
unsigned int p1, p2;
sPoint v1, v2;
float side;
//set visual parameter
for (i=0;i<o->nPlanes;i++){
// chech to see if light is in front or behind the plane (face plane)
side = o->planes[i].PlaneEq.a*lp[0]+
o->planes[i].PlaneEq.b*lp[1]+
o->planes[i].PlaneEq.c*lp[2]+
o->planes[i].PlaneEq.d*lp[3];
if (side >0) o->planes[i].visible = TRUE;
else o->planes[i].visible = FALSE;
}
glPushAttrib( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | GL_POLYGON_BIT | GL_STENCIL_BUFFER_BIT );
glDisable(GL_LIGHTING);
glDepthMask(GL_FALSE);
glDepthFunc(GL_LEQUAL);
glEnable(GL_STENCIL_TEST);
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
glStencilFunc( GL_ALWAYS, 1, 0xFFFFFFFFL );
// first pass, stencil operation decreases stencil value
glFrontFace(GL_CCW);
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
for (i=0; i<o->nPlanes;i++){
if (o->planes[i].visible)
for (j=0;j<3;j++){
k = o->planes[i].neigh[j];
if ((!k) || (!o->planes[k-1].visible)){
// here we have an edge, we must draw a polygon
p1 = o->planes[i].p[j];
jj = (j+1)%3;
p2 = o->planes[i].p[jj];
//calculate the length of the vector
v1.x = (o->points[p1].x - lp[0])*100;
v1.y = (o->points[p1].y - lp[1])*100;
v1.z = (o->points[p1].z - lp[2])*100;
v2.x = (o->points[p2].x - lp[0])*100;
v2.y = (o->points[p2].y - lp[1])*100;
v2.z = (o->points[p2].z - lp[2])*100;
//draw the polygon
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(o->points[p1].x,
o->points[p1].y,
o->points[p1].z);
glVertex3f(o->points[p1].x + v1.x,
o->points[p1].y + v1.y,
o->points[p1].z + v1.z);
glVertex3f(o->points[p2].x,
o->points[p2].y,
o->points[p2].z);
glVertex3f(o->points[p2].x + v2.x,
o->points[p2].y + v2.y,
o->points[p2].z + v2.z);
glEnd();
}
}
}
// second pass, stencil operation increases stencil value
glFrontFace(GL_CW);
glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
for (i=0; i<o->nPlanes;i++){
if (o->planes[i].visible)
for (j=0;j<3;j++){
k = o->planes[i].neigh[j];
if ((!k) || (!o->planes[k-1].visible)){
// here we have an edge, we must draw a polygon
p1 = o->planes[i].p[j];
jj = (j+1)%3;
p2 = o->planes[i].p[jj];
//calculate the length of the vector
v1.x = (o->points[p1].x - lp[0])*100;
v1.y = (o->points[p1].y - lp[1])*100;
v1.z = (o->points[p1].z - lp[2])*100;
v2.x = (o->points[p2].x - lp[0])*100;
v2.y = (o->points[p2].y - lp[1])*100;
v2.z = (o->points[p2].z - lp[2])*100;
//draw the polygon
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(o->points[p1].x,
o->points[p1].y,
o->points[p1].z);
glVertex3f(o->points[p1].x + v1.x,
o->points[p1].y + v1.y,
o->points[p1].z + v1.z);
glVertex3f(o->points[p2].x,
o->points[p2].y,
o->points[p2].z);
glVertex3f(o->points[p2].x + v2.x,
o->points[p2].y + v2.y,
o->points[p2].z + v2.z);
glEnd();
}
}
}
glFrontFace(GL_CCW);
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
//draw a shadowing rectangle covering the entire screen
glColor4f(0.0f, 0.0f, 0.0f, 0.6f);
glStencilFunc( GL_NOTEQUAL, 0, 0xFFFFFFFFL );
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
glPushMatrix();
glLoadIdentity();
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(-0.1f, 0.1f,-0.1f);
glVertex3f(-0.1f,-0.1f,-0.1f);
glVertex3f( 0.1f, 0.1f,-0.1f);
glVertex3f( 0.1f,-0.1f,-0.1f);
glEnd();
glPopMatrix();
glDepthFunc(GL_LEQUAL);
glDepthMask(GL_TRUE);
glEnable(GL_LIGHTING);
glDisable(GL_STENCIL_TEST);
glShadeModel(GL_SMOOTH);
glPopAttrib();
}