Shadow mapping problem

Started by
22 comments, last by bushmanpaul 13 years, 6 months ago
Quote:Original post by bushmanpaul
1.The small bands of light you are seeing is the inaccuracy in float. This is totally normal.

2.This is also a problem with inaccuracy with float, try adding more bias (might make small bands of light bigger).

http://developer.nvidia.com/object/hwshadowmap_paper.html shows you how to solve this.

3.The further the light is away the higher your shadow Map resolution need to be for you to get better results.If I understand you correctly.

Hope this helps.


Cool, that helped a lot. But in HLSL, it seems pixel values are clamped to [0,1]. This means that if I store the z-values in a texture, I have to get them in this range. (z-clipNear)/(clipFar-ClipNear) doesn't work because it's non-linear, forcing all the values so close to zero that the shadow map doesnt work. Is there any way (other than 1/z) to render the shadow map?
Advertisement
you can use a 32 bit floating point texture, use view space z and then thatll work better maybe?
Quote:Original post by rouncED
you can use a 32 bit floating point texture, use view space z and then thatll work better maybe?


I already use a 32 bit texture: D3DFMT_X8R8G8B8
Also, I already use the view space z. That's why it can be any value between clipNear and clipFar, right?
Quote:Original post by xytor
Quote:Original post by rouncED
you can use a 32 bit floating point texture, use view space z and then thatll work better maybe?


I already use a 32 bit texture: D3DFMT_X8R8G8B8
Also, I already use the view space z. That's why it can be any value between clipNear and clipFar, right?


He said 32-bit floating point texture, for example D3DFMT_R32F. 8-bits is not going to have sufficient precision for a shadow map. Plus an integer format is going to be clamped to [0,1], so you can't store view-space z in it.
Quote:Original post by MJP
Quote:Original post by xytor
Quote:Original post by rouncED
you can use a 32 bit floating point texture, use view space z and then thatll work better maybe?


I already use a 32 bit texture: D3DFMT_X8R8G8B8
Also, I already use the view space z. That's why it can be any value between clipNear and clipFar, right?


He said 32-bit floating point texture, for example D3DFMT_R32F. 8-bits is not going to have sufficient precision for a shadow map. Plus an integer format is going to be clamped to [0,1], so you can't store view-space z in it.


How does that work? When a pixel shader writes to a texture like that, do I just return a single float instead of a float4? When sampling from it, does the sampler return a single float value instead of float4?
No you still return a float4 from your pixel shader. You can just return 1.0f for the BGA components. When you sample the texture you will still get a float4, but only the first component will be valid. The other 3 will either be 0 or 1, depending on the GPU and driver.
Quote:Original post by MJP
No you still return a float4 from your pixel shader. You can just return 1.0f for the BGA components. When you sample the texture you will still get a float4, but only the first component will be valid. The other 3 will either be 0 or 1, depending on the GPU and driver.


WOA, you guys are amazing, that almost completely solved my shadow mapping problem.
However, there are still a few small problems:

- There is a very thin shadowed line at the base of the spotlight lit area that corresponds to the bottom of the shadow map. Any ideas on how to get rid of that?

- The lighting fails when the light view target is exactly below the light. Why is that?

- Currently, my shadows only are feasible for spot lights. Directional lights fail because the actual shadow map is not large enough (or the fov is not large enough). So, after the borders of the shadow map, the shadows are invalid. Is there any way to make shadow mapping work for directional lights?
In general for a spotlight the projection for the shadow map should be wide enough that the entire cone-shaped area of the light fits within the borders of the shadow map. So if you're sampling past the border then your projection isn't wide enough. You should make the FOV based on the angular attenuation factor you're using for the spotlight, rather than hard-coding it. Aside from that, also make sure that you have POINT sampling enabled when sampling the shadow map.

The reason it fails when the light is vertical is because you hard-coded the up vector of your view matrix as (0,1,0). So when the light's look direction is parallel to that vector (looking straight up or straight down) the view matrix becomes invalid, since the cross product of parallel vectors is zero. A simple fix is to just test for that case and use a different up vector. Or you can use something like this to always generate an up vector that's perpendicular to your lookAt direction.

Shadows for directional lights are a broad topic, and it's not trivial to implement them properly and avoid aliasing problems. Since a directional light is global you can't just make a view and projection based on a light position and direction like you can with a spot light. Instead you have to fit an orthographic projection to the main camera's view frustum. On top of that you also need to a technique to reduce perspective aliasing caused by the non-rectangular shape of the view frustum. Cascaded shadow maps (CSM) are the most popular for this. If you do some searches on the forum or on Google you should be able to find more information about directional shadow maps in general, and CSM.
Quote:Original post by MJP
In general for a spotlight the projection for the shadow map should be wide enough that the entire cone-shaped area of the light fits within the borders of the shadow map. So if you're sampling past the border then your projection isn't wide enough. You should make the FOV based on the angular attenuation factor you're using for the spotlight, rather than hard-coding it. Aside from that, also make sure that you have POINT sampling enabled when sampling the shadow map.

The reason it fails when the light is vertical is because you hard-coded the up vector of your view matrix as (0,1,0). So when the light's look direction is parallel to that vector (looking straight up or straight down) the view matrix becomes invalid, since the cross product of parallel vectors is zero. A simple fix is to just test for that case and use a different up vector. Or you can use something like this to always generate an up vector that's perpendicular to your lookAt direction.

Shadows for directional lights are a broad topic, and it's not trivial to implement them properly and avoid aliasing problems. Since a directional light is global you can't just make a view and projection based on a light position and direction like you can with a spot light. Instead you have to fit an orthographic projection to the main camera's view frustum. On top of that you also need to a technique to reduce perspective aliasing caused by the non-rectangular shape of the view frustum. Cascaded shadow maps (CSM) are the most popular for this. If you do some searches on the forum or on Google you should be able to find more information about directional shadow maps in general, and CSM.


Ok, cool... I'll save directional shadows for later.
Thanks for the tip about point sampling and up vector, they made the shadows almost perfect!

One more problem occurs due to percentage closer filtering and possibly using back-faces for shadow map:
When two objects are touching (so without shadows, the boundary is imperceptible), there is a thin shadow along the border. What could be causing this?

[Edited by - xytor on October 17, 2010 4:36:32 PM]
The shadow you are seeing is most probably also a inaccuracy with the float. Using D3D10_CULL_BACK to create the depth map from the lights view(this only works if you are using closed meshes) would usually solve most issues with edges of shadows

Can you please include a screen shot of the problem.

This topic is closed to new replies.

Advertisement