/* Here is some relevant information regarding my rendering code:
Functions:
- DrawShadowPlane1(): draws the floor plane
- DrawShadowPlane2(): draws the wall plane
- DrawShadowedObjects(): draws the object/s that will cast shadows
Planes:
- Plane plane1; (a = 0, b = 1, c = 0, d = 0) --> this is the floor plane
- Plane plane2; (a = 1, b = 0, c = 0, d = 20) --> this is the wall plane
Projection matrices:
- float projectionMatrix1[16];
- float projectionMatrix2[16];
And I have a single point light source:
- float lightPos[4] = { ... };
*/
////////////////////////////////////////////////////////////////
// Firstly, I create the projection matrices:
// Create the first projection matrix (for projection onto the floor plane)
Vector3 normal = plane.GetNormal();
float distance = plane.GetDistance();
float dot = (lightPos[0] * normal.x) + (lightPos[1] * normal.y) + (lightPos[2] * normal.z) + (lightPos[3] * distance);
projectionMatrix[0] = dot - lightPos[0] * normal.x;
projectionMatrix[1] = -lightPos[1] * normal.x;
projectionMatrix[2] = -lightPos[2] * normal.x;
projectionMatrix[3] = -lightPos[3] * normal.x;
projectionMatrix[4] = -lightPos[0] * normal.y;
projectionMatrix[5] = dot -lightPos[1] * normal.y;
projectionMatrix[6] = -lightPos[2] * normal.y;
projectionMatrix[7] = -lightPos[3] * normal.y;
projectionMatrix[8] = -lightPos[0] * normal.z;
projectionMatrix[9] = -lightPos[1] * normal.z;
projectionMatrix[10] = dot -lightPos[2] * normal.z;
projectionMatrix[11] = -lightPos[3] * normal.z;
projectionMatrix[12] = -lightPos[0] * distance;
projectionMatrix[13] = -lightPos[1] * distance;
projectionMatrix[14] = -lightPos[2] * distance;
// Create the second projection matrix (for projection onto the wall plane)
normal = plane2.GetNormal();
distance = plane2.GetDistance();
dot = (lightPos[0] * normal.x) + (lightPos[1] * normal.y) + (lightPos[2] * normal.z) + (lightPos[3] * distance);
projectionMatrix2[0] = dot - lightPos[0] * normal.x;
projectionMatrix2[1] = -lightPos[1] * normal.x;
projectionMatrix2[2] = -lightPos[2] * normal.x;
projectionMatrix2[3] = -lightPos[3] * normal.x;
projectionMatrix2[4] = -lightPos[0] * normal.y;
projectionMatrix2[5] = dot -lightPos[1] * normal.y;
projectionMatrix2[6] = -lightPos[2] * normal.y;
projectionMatrix2[7] = -lightPos[3] * normal.y;
projectionMatrix2[8] = -lightPos[0] * normal.z;
projectionMatrix2[9] = -lightPos[1] * normal.z;
projectionMatrix2[10] = dot -lightPos[2] * normal.z;
projectionMatrix2[11] = -lightPos[3] * normal.z;
projectionMatrix2[12] = -lightPos[0] * distance;
projectionMatrix2[13] = -lightPos[1] * distance;
projectionMatrix2[14] = -lightPos[2] * distance;
projectionMatrix2[15] = dot -lightPos[3] * distance;
// DRAW SHADOW 1 ///////////////////////////////////////////////
// Draw the plane that the shadow will project onto
DrawShadowPlane1();
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthMask(GL_FALSE);
glEnable(GL_STENCIL_TEST);
// Draw the shadow plane into the stencil buffer
glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
DrawShadowPlane1();
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_TRUE);
// Restrict drawing to the shadow plane
glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
// Draw the shadow (blended with the shadow plane)
// The depth buffer is disabled to prevent z-fighting
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
glPushMatrix();
glMultMatrixf(projectionMatrix1);
DrawShadowedObjects();
glPopMatrix();
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
// DRAW SHADOW 2 ///////////////////////////////////////////////
// Draw the plane that the shadow will project onto
DrawShadowPlane2();
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthMask(GL_FALSE);
glEnable(GL_STENCIL_TEST);
// Draw the shadow plane into the stencil buffer
glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
DrawShadowPlane2();
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_TRUE);
// Restrict drawing to the shadow plane
glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
// Draw the shadow (blended with the shadow plane)
// The depth buffer is disabled to prevent z-fighting
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
glPushMatrix();
glMultMatrixf(projectionMatrix2);
DrawShadowedObjects();
glPopMatrix();
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
////////////////////////////////////////////////////////////////
// And lastly I draw the objects that cast the shadows
glColor3f(1.0f, 1.0f, 1.0f);
DrawShadowedObjects();
Projective Shadows Problem
I have implemented simple projective shadows using OpenGL (described in 'OpenGL Game Programming', and also described here), but I'm having problems with projecting shadows onto more than one plane. Projecting one shadow is no problem, but if I have more than one shadow, the shadows appear incorrectly (they appear infront of the shadow plane). I know that I need to use the depth buffer to correctly draw multiple shadows, but I don't know how. In what order should I draw the objects/shadows so that it looks right? And how do I use the depth buffer correctly to achieve this?
Here is my rendering code, just in case:
And here are some screenshots I took of my problem:
Clicky
Any help is appreciated.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement