Skip to main content
GameDev.net gamedev.net
🔒 Locked 🎮 Unity

XNA - Deferred Shadow Maps Sample

Started by - hAk - Apr 6, 2011 at 9:57 AM 3 replies 3.6k views
Original Post
- hAk -
- hAk -
Hey folks!

Currently I'm working on a shadow mapping implementation for my litte XNA game. Following the tutorial by Matt (aka MJP), I was able to convert his sourcecode to XNA 4.0 - but obviously I'm making some mistakes :-S

Although my depthMap and shadowMap are looking good, the occlusionMap does not. It's a bit hard to describe, so let the pictures speak ;-)
sample.jpg

Matt is using CCW culling in his shaders (sample homepage), which gives the results from above. For me it would be a little more logical, if the depthMap and shadowMap would also show the plane beneath the cube. This could be achived by using CW culling order but still does not solve the issue.

I think there might be some kind of error in the occlusion shader, but the understanding of that is way beyond my knowledge.

My light view projection matrix is calculated as:

protected void CalculateFrustum(NiceLightDirectional light, NiceCameraAbstract camera)
{
// Shorten the view frustum according to the shadow view distance
Matrix cameraMatrix = camera.WorldMatrix;

// Find the centroid
Vector3 frustumCentroid = new Vector3(0, 0, 0);
for (int i = 0; i < 8; i++)
frustumCentroid += frustumCornersWS;
frustumCentroid /= 8;

// Position the shadow-caster camera so that it's looking at the centroid,
// and backed up in the direction of the sunlight
float distFromCentroid = MathHelper.Max((camera.FarPlane - camera.NearPlane), Vector3.Distance(frustumCornersVS[4], frustumCornersVS[5])) + 50.0f;
Matrix viewMatrix = Matrix.CreateLookAt(frustumCentroid - (light.Direction * distFromCentroid), frustumCentroid, new Vector3(0, 1, 0));

// Determine the position of the frustum corners in light space
Vector3.Transform(frustumCornersWS, ref viewMatrix, frustumCornersLS);

// Calculate an orthographic projection by sizing a bounding box
// to the frustum coordinates in light space
Vector3 mins = frustumCornersLS[0];
Vector3 maxes = frustumCornersLS[0];
for (int i = 0; i < 8; i++)
{
if (frustumCornersLS.X > maxes.X)
maxes.X = frustumCornersLS.X;
else if (frustumCornersLS.X < mins.X)
mins.X = frustumCornersLS.X;
if (frustumCornersLS.Y > maxes.Y)
maxes.Y = frustumCornersLS.Y;
else if (frustumCornersLS.Y < mins.Y)
mins.Y = frustumCornersLS.Y;
if (frustumCornersLS.Z > maxes.Z)
maxes.Z = frustumCornersLS.Z;
else if (frustumCornersLS.Z < mins.Z)
mins.Z = frustumCornersLS.Z;
}

// Create an orthographic camera for use as a shadow caster
const float nearClipOffset = 100.0f;

Matrix c_ProjectionMatrix;
Matrix.CreateOrthographicOffCenter(mins.X, maxes.X, mins.Y, maxes.Y, -maxes.Z - nearClipOffset, -mins.Z, out c_ProjectionMatrix);
Matrix.Multiply(ref viewMatrix, ref c_ProjectionMatrix, out lightCameraViewProjection);
}


Any ideas?

Thanks a lot!
MJP
MJP
It's been a while since I wrote that, or even since I used XNA at all, so I don't quite remember the exact combinations of culling order and winding order specified in the model processor. Either way, you'll want to make sure that you use standard back-face culling when rendering to the depth map and shadow map.
- hAk -
- hAk -
Hey Matt,

if I get you right, I should change the culling to CW - which gives me the result below. It look a little bit more logic to me, since the plane is visible in the depth and shadowmap as stated above.

The occlusion map stays completely white without the strage "artifacts" from the pic above.

Do you have any clue what's still wrong in my implementation? Can you at least confirm, that my two depth maps now look correct to you? Also I'm wondering, whether it is normal for the ShadowMap in this example to move as the camera moves. The camera is orbiting the scene on a circular path.

Thank you anyway for your reply :-)


sample_CW.jpg
MJP
MJP
Yes the depth map and shadow map look correct. They should be darker for geometry closer to the camera, and brighter for geometry further from the camera.

And yeah, the shadow-casting "camera" set up for the directional light in the sample follows the main camera based on its position and the direction it's looking. So the view rendered to the shadow map should change as the camera moves around.
- hAk -
- hAk -
Thank you for your reply, Matt!

Knowing that me depth buffers are issue free I focused on the occlusion shader - again.

I found that I simply mixed the camera-view-inverse matrix with the camera-world-inverse - d'oh! Time to blush now ...

Anyway I wonder how to combine multiple lights and shadows now. My first idea is the following:


render GBuffer

foreach light
render occlusionMap
render lightMap and remove lit pieces using occlusionMap

combine GBuffer output and alpha blended lighting pass


Combining each single lightMap and it occlusionMap should give me the ability to remove shadows, when an other light is lighting it (i.e. light inside the "shadow volume"). I should also be able make overlapping shadows darker than other ones this way.

Any thoughts about this approach?

Best regards!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.