I’m currently working on Shadow casting by referring to NeHe’s example.
Problem I have are
- No shadow is drawn at all
- Every time I add a new object, screen gets darker and darker
so I would like to get your help to fix the issue I have.
Below is part of source codes…
void DrawRoom() {
glBegin(GL_QUADS); // Begin Drawing Quads
// Floor
glNormal3f(0.0f, 1.0f, 0.0f); // Normal Pointing Up
glVertex3f(-10.0f, -10.0f, -20.0f); // Back Left
glVertex3f(-10.0f, -10.0f, 20.0f); // Front Left
glVertex3f(10.0f, -10.0f, 20.0f); // Front Right
glVertex3f(10.0f, -10.0f, -20.0f); // Back Right
// Ceiling
glNormal3f(0.0f, -1.0f, 0.0f); // Normal Point Down
glVertex3f(-10.0f, 10.0f, 20.0f); // Front Left
glVertex3f(-10.0f, 10.0f, -20.0f); // Back Left
glVertex3f(10.0f, 10.0f, -20.0f); // Back Right
glVertex3f(10.0f, 10.0f, 20.0f); // Front Right
// Front Wall
glNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Away From Viewer
glVertex3f(-10.0f, 10.0f, -20.0f); // Top Left
glVertex3f(-10.0f, -10.0f, -20.0f); // Bottom Left
glVertex3f(10.0f, -10.0f, -20.0f); // Bottom Right
glVertex3f(10.0f, 10.0f, -20.0f); // Top Right
// Back Wall
glNormal3f(0.0f, 0.0f, -1.0f); // Normal Pointing Towards Viewer
glVertex3f(10.0f, 10.0f, 20.0f); // Top Right
glVertex3f(10.0f, -10.0f, 20.0f); // Bottom Right
glVertex3f(-10.0f, -10.0f, 20.0f); // Bottom Left
glVertex3f(-10.0f, 10.0f, 20.0f); // Top Left
// Left Wall
glNormal3f(1.0f, 0.0f, 0.0f); // Normal Pointing Right
glVertex3f(-10.0f, 10.0f, 20.0f); // Top Front
glVertex3f(-10.0f, -10.0f, 20.0f); // Bottom Front
glVertex3f(-10.0f, -10.0f, -20.0f); // Bottom Back
glVertex3f(-10.0f, 10.0f, -20.0f); // Top Back
// Right Wall
glNormal3f(-1.0f, 0.0f, 0.0f); // Normal Pointing Left
glVertex3f(10.0f, 10.0f, -20.0f); // Top Back
glVertex3f(10.0f, -10.0f, -20.0f); // Bottom Back
glVertex3f(10.0f, -10.0f, 20.0f); // Bottom Front
glVertex3f(10.0f, 10.0f, 20.0f); // Top Front
glEnd(); // Done Drawing Quads
}
void DrawScene(Object3D &object, Light &light, GL_Window &glView) {
GLmatrix16f mvMatrix;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// Enable Light and Lighting
glEnable(GL_LIGHT1);
glEnable(GL_LIGHTING);
// Reset the current viewport
glViewport(0, 0, glView.Width, glView.Height);
// Select and reset the Projection Matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Calculate the aspect ratio of the window
gluPerspective(45.0f, (GLfloat)glView.Width / (GLfloat)glView.Height, 0.001f, 100.0f);
// Select and reset the Modelview Matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Position Light and zoom into screen 20 units
glLightfv(GL_LIGHT1, GL_POSITION, LightPos);
glTranslatef(0.0f, 0.0f, -20.0f);
// Set color to an Orange and position the sphere then draw sphere
glColor4f(1.0f, 0.2f, 0.0f, 1.0f);
glTranslatef(SpherePos[0], SpherePos[1], SpherePos[2]);
gluSphere(light.quadric, 1.5f, 32, 16);
// Reset Matrix
glLoadIdentity();
// Retrieve ModelView Matrix
glGetFloatv(GL_MODELVIEW_MATRIX, mvMatrix);
// Store Light vector
light.data[0].VMatMult(mvMatrix, light.position);
// Retrieve ModelView Matrix
glGetFloatv(GL_MODELVIEW_MATRIX, mvMatrix);
// World Local Coord X, Y, Z to 0
light.worldCoordinate[0] = 0.0f;
light.worldCoordinate[1] = 0.0f;
light.worldCoordinate[2] = 0.0f;
light.worldCoordinate[3] = 1.0f;
// Store the position of world relative to the local Coordinate system
light.data[0].VMatMult(mvMatrix, light.worldCoordinate);
// Retrieve position of Light relative to the local coordinate system
light.position[0] += light.worldCoordinate[0];
light.position[1] += light.worldCoordinate[1];
light.position[2] += light.worldCoordinate[2];
// Reset Modelview Matrix andd zoom into the screen 20 units
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -20.0f);
// Draw Room
DrawRoom();
// Zoom into screen 20 units
glTranslatef(0.0f, 0.0f, -20.0f);
// Draw object
glBegin(GL_TRIANGLES);
for (int i = 0; i < object.vSurfaceCount; i++) {
glNormal3f(object.vSurfaces[i].normal.x, object.vSurfaces[i].normal.y, object.vSurfaces[i].normal.z);
glVertex3f(object.vPoints[object.vSurfaces[i].p1].position.x, object.vPoints[object.vSurfaces[i].p1].position.y, object.vPoints[object.vSurfaces[i].p1].position.z);
glVertex3f(object.vPoints[object.vSurfaces[i].p2].position.x, object.vPoints[object.vSurfaces[i].p2].position.y, object.vPoints[object.vSurfaces[i].p2].position.z);
glVertex3f(object.vPoints[object.vSurfaces[i].p3].position.x, object.vPoints[object.vSurfaces[i].p3].position.y, object.vPoints[object.vSurfaces[i].p3].position.z);
}
glEnd();
// Cast Shadow
CastShadow(light, 0, object);
// Set Color To Purplish Blue
glColor4f(0.7f, 0.4f, 0.0f, 1.0f);
// Disable Lighting and Depth Mask
glDisable(GL_LIGHTING);
glDepthMask(GL_FALSE);
// Translate to Light's position, we're still in local coordinate system
glTranslatef(light.position[0], light.position[1], light.position[2]);
// Draw a little yellow sphere (Represents Light)
gluSphere(light.quadric, 0.2f, 16, 8);
glLoadIdentity();
// Enable Lighting and Depth mask
glEnable(GL_LIGHTING);
glDepthMask(GL_TRUE);
// Flush the OpenGL pipeline
glFlush();
// Swap buffers (Double buffering)
SwapBuffers(glView.hDC);
}
void CalculatePlane(Surface3D &vSurface, Point3D *vPoints) {
Coordinate3D v1 = vPoints[vSurface.p1].position;
Coordinate3D v2 = vPoints[vSurface.p2].position;
Coordinate3D v3 = vPoints[vSurface.p3].position;
vSurface.pEquation.a = v1.y * (v2.z - v3.z) + v2.y * (v3.z - v1.z) + v3.y * (v1.z - v2.z);
vSurface.pEquation.b = v1.z * (v2.x - v3.x) + v2.z * (v3.x - v1.x) + v3.z * (v1.x - v2.x);
vSurface.pEquation.c = v1.x * (v2.y - v3.y) + v2.x * (v3.y - v1.y) + v3.x * (v1.y - v2.y);
vSurface.pEquation.d = -(v1.x * (v2.y * v3.z - v3.y * v2.z) + v2.x * (v3.y * v1.z - v1.y * v3.z) + v3.x * (v1.y * v2.z - v2.y * v1.z));
}
void Normalize(Surface3D &vSurface, Point3D *vPoints) {
GLdouble Ux = vPoints[vSurface.p2].position.x - vPoints[vSurface.p1].position.x;
GLdouble Uy = vPoints[vSurface.p2].position.y - vPoints[vSurface.p1].position.y;
GLdouble Uz = vPoints[vSurface.p2].position.z - vPoints[vSurface.p1].position.z;
GLdouble Vx = vPoints[vSurface.p3].position.x - vPoints[vSurface.p1].position.x;
GLdouble Vy = vPoints[vSurface.p3].position.y - vPoints[vSurface.p1].position.y;
GLdouble Vz = vPoints[vSurface.p3].position.z - vPoints[vSurface.p1].position.z;
vSurface.normal.y = (Uz * Vx) - (Ux * Vz);
vSurface.normal.z = (Ux * Vy) - (Uy * Vx);
vSurface.normal.x = (Uy * Vz) - (Uz * Vy);
}
// Cast shadow
void CastShadow(Light &light, Object3D &object, int objectIndex) {
int i, j, k, jj;
int p1, p2;
Coordinate3D v1, v2;
float side;
// Set visual parameter
for (i = 0; i < object.vSurfaceCount; i++) {
// Check to see if light is in front or behind the plane (face plane)
side = object.vSurfaces[i].pEquation.a * light.position[0] +
object.vSurfaces[i].pEquation.b * light.position[1] +
object.vSurfaces[i].pEquation.c * light.position[2] +
object.vSurfaces[i].pEquation.d * light.position[3];
if (side > 0)
object.vSurfaces[i].IsShadowed = false;
else
object.vSurfaces[i].IsShadowed = true;
}
glDisable(GL_LIGHTING);
glDepthMask(GL_FALSE);
glDepthFunc(GL_LEQUAL);
glEnable(GL_STENCIL_TEST);
glColorMask(0, 0, 0, 0);
glStencilFunc(GL_ALWAYS, 1, 0xffffffff);
// First pass, stencil operation decreases stencil value
glFrontFace(GL_CCW);
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
for (i = 0; i < object.vSurfaceCount; i++) {
if (!object.vSurfaces[i].IsShadowed) {
for (j = 0; j < 3; j++) {
k = object.vSurfaces[i].neighbor[j];
if ((k == -1) || (object.vSurfaces[k - 1].IsShadowed)) {
// Here we have an edge, we must draw a polygon
p1 = object.vSurfaces[i].index[j];
jj = (j + 1) % 3;
p2 = object.vSurfaces[i].index[jj];
// Calculate the length of the vector
v1.x = (object.vPoints[p1].position.x - light.position[0]) * 100;
v1.y = (object.vPoints[p1].position.y - light.position[1]) * 100;
v1.z = (object.vPoints[p1].position.z - light.position[2]) * 100;
v2.x = (object.vPoints[p2].position.x - light.position[0]) * 100;
v2.y = (object.vPoints[p2].position.y - light.position[1]) * 100;
v2.z = (object.vPoints[p2].position.z - light.position[2]) * 100;
// Draw the polygon
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(object.vPoints[p1].position.x, object.vPoints[p1].position.y, object.vPoints[p1].position.z);
glVertex3f(object.vPoints[p1].position.x + v1.x, object.vPoints[p1].position.y + v1.y, object.vPoints[p1].position.z + v1.z);
glVertex3f(object.vPoints[p2].position.x, object.vPoints[p2].position.y, object.vPoints[p2].position.z);
glVertex3f(object.vPoints[p2].position.x + v2.x, object.vPoints[p2].position.y + v2.y, object.vPoints[p2].position.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 < object.vSurfaceCount; i++) {
if (!object.vSurfaces[i].IsShadowed) {
for (j = 0; j < 3; j++) {
k = object.vSurfaces[i].neighbor[j];
if ((k == -1) || (object.vSurfaces[k - 1].IsShadowed)) {
// Here we have an edge, we must draw a polygon
p1 = object.vSurfaces[i].index[j];
jj = (j + 1) % 3;
p2 = object.vSurfaces[i].index[jj];
// Calculate the length of the vector
v1.x = (object.vPoints[p1].position.x - light.position[0]) * 100;
v1.y = (object.vPoints[p1].position.y - light.position[1]) * 100;
v1.z = (object.vPoints[p1].position.z - light.position[2]) * 100;
v2.x = (object.vPoints[p2].position.x - light.position[0]) * 100;
v2.y = (object.vPoints[p2].position.y - light.position[1]) * 100;
v2.z = (object.vPoints[p2].position.z - light.position[2]) * 100;
// Draw the polygon
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(object.vPoints[p1].position.x, object.vPoints[p1].position.y, object.vPoints[p1].position.z);
glVertex3f(object.vPoints[p1].position.x + v1.x, object.vPoints[p1].position.y + v1.y, object.vPoints[p1].position.z + v1.z);
glVertex3f(object.vPoints[p2].position.x, object.vPoints[p2].position.y, object.vPoints[p2].position.z);
glVertex3f(object.vPoints[p2].position.x + v2.x, object.vPoints[p2].position.y + v2.y, object.vPoints[p2].position.z + v2.z);
glEnd();
}
}
}
}
glFrontFace(GL_CCW);
glColorMask(1, 1, 1, 1);
// Draw a shadowing rectangle covering the entire screen
glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glStencilFunc(GL_NOTEQUAL, 0, 0xffffffff);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
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();
glDisable(GL_BLEND);
glDepthFunc(GL_LEQUAL);
glDepthMask(GL_TRUE);
glEnable(GL_LIGHTING);
glDisable(GL_STENCIL_TEST);
glShadeModel(GL_SMOOTH);
}
Below is what I can see when I compile it, so no shadow is drawn…and the screen gets darker
Thanks in advance