This topic is 5416 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

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:
/* Here is some relevant information regarding my rendering code:

Functions:

- DrawShadowPlane1(): draws the floor plane
- DrawShadowPlane2(): draws the wall plane

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 the plane that the shadow will project onto

glEnable(GL_STENCIL_TEST);

// Draw the shadow plane into the stencil buffer
glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);

// Restrict drawing to the shadow plane
glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

// 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);
glPopMatrix();
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);

// Draw the plane that the shadow will project onto

glEnable(GL_STENCIL_TEST);

// Draw the shadow plane into the stencil buffer
glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);

// Restrict drawing to the shadow plane
glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

// 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);
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);


And here are some screenshots I took of my problem: Clicky Any help is appreciated.

• 21
• 16
• 9
• 17
• 13