Shadow map artifact

Started by
7 comments, last by TwistedPix 15 years, 3 months ago
Hello Everyone I'm new to shadow mapping so i've created a shadow mapping demo to learn more and it seems it works well except when i move the light near objects in the scene. I'm using one 1024*1024 shadow map and using

D3DXMatrixLookAtLH( &ViewMat, &mSunPos, &D3DXVECTOR3(0.0f, 0.0f, 0.0f), 
						&D3DXVECTOR3(0.0f, 1.0f, 0.0f) );

D3DXMatrixPerspectiveFovLH( &ProjMat, D3DX_PI / 2.0f, 1.0f, 1.0f, 200.0f );

to get the light View Projection matrix. Here is the screen shot when light is not near the object: Free Image Hosting at www.ImageShack.us And when it's near the statue: Free Image Hosting at www.ImageShack.us Am i missing something? Thanks.
[Blog]
Advertisement
I think maybe it's because of using one depth texture instead of cube map but from what i got from the theory it should work with the scene in the demo.

Anyone?

Thanks in advance for your replies.
[Blog]
Not too much to go on here, but it looks like your light frustum is too small (not big enough to cover the entire visible scene when you move it close up to the scene). Effectively it means the part of the scene that is wrongly fully shadowed is outside of the area of your projected SM.

Ideally for best results you need to recompute your light matrices every frame to make sure the light frustum is large enough to cover everything in your view frustum you want shadowed in your scene.

(if all you want to do is hide the issue asap your can add some code to your pixel shader that just sets the fragment to be fully unshadowed when the projected shadow map texture coords are out of range)
Seems logical but i can't set the frustum wider than PI/2 ( the scene goes completely shadowed )

How can i compute the lights projection matrix based on scene information?

Anyway Thanks. :)
[Blog]
Lookup how the perspective matrix is defined component wise

you can create your own one with simple trigonemetry

here is a good link discussing the map behind the opengl perspective projection matrix

look for something similar for d3d I guess the coordinate systems are slightly different

basically you do the opposite of "frustrum extraction"

http://www.songho.ca/opengl/gl_projectionmatrix.html


http://www.8ung.at/basiror/theironcross.html
Well are you trying to work with a spot light, or a directional(infinite) light? For a spot light, your can just give your perspective projection the same field of view as the cone width of your spot light, and you're good to go.

For a directional light things are quite a bit different. First of all, an orthographic projection is typically used since this gives the proper impression of the light source being infinitely far away. Second, this orthographic projection has to be sized so that it properly encloses the entire view frustum. If this is what you're trying to accomplish, I can give you some more detailed instructions and point you toward some resources.
@Basiror:
Thanks for the link. But what i meant was: how could i set proper field of view for given position of light and the scene info but i think as MJP pointed i should use either directional light shadows or setting spot light cone width ( for spot lights )

@MJP:
Well, I'm trying to do dynamic shadows for terrains so i think i need directional light shadows. I would appreciate any directions.

Thanks.
[Blog]
-The first thing you need to do for a directional light is you need to find the 8 corners of your view frustum. This page (and the one following) give some instructions on how you can do this using your projection parameters. When you first find your corners, they will be in view-space (relative to your camera). You need them in world-space, so you just need to transform them by camera's world matrix (a camera's world matrix is the inverse of its view matrix).

-Once you have your 8 frustum corners in world-space, you can start fitting an orthographic projection to it. The first step is to find the centroid of the frustum, by adding the corner positions together and dividing by 8 (the centroid is the exact center of your view frustum).

-You now need to pick a temporary working position for your light, by taking the centroid and "backing up" in the opposite direction of the light. How far you back up depends on your scene...backing up really far allows you to have objects cast shadows that aren't visible by the main camera. Keeping the camera close gives better precision, but you could miss geometry that should be casting shadows in the scene. You might want to start out with something like the distance between your camera's near and far clipping planes, and then add a constant value:
float distFromCentroid = mainCamera.FarClip - mainCamera.NearClip + 50.0f;

Then once you have this distance, you can back up from the centroid to create position for the light as well as a view matrix:
D3DXMatrixLookAtLH(&lightViewMatrix, &(frustumCentroid - (lightDirection * distFromCentroid)), &frustumCentroid, &D3DXVECTOR3(0,1,0));


-Now that we have a view matrix, we can find the positions of the frustum corners with respect to the temporary position of our light source. To do that we just transform the world-space corners by the lightViewMatrix we came up with.

-Figure out the minimum and maximum x, y, and z values of the frustum corners in light-space.

-Create an orthographic projection using these min and max values. Use D3DXMatrixOrthoOffCenterLH and use min x as l, max x as right, min y as b, max y as t, min z as zn, and max z as zf.

-Perform shadow mapping as you did before, using your lightView and lightProjection matrices.
Thanks for the detailed explanation. I'll try to implement it. :)
[Blog]

This topic is closed to new replies.

Advertisement