Jump to content
  • Advertisement
Sign in to follow this  
Chacha

OpenGL Projective Shadows Problem

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

If you intended to correct an error in the post then please contact us.

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


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

Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!