Jump to content
  • Advertisement
Sign in to follow this  
howie_007

higher precision shadow maps

This topic is 2435 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 got my shadow maps working (yaaaaaa) but I'm a little confused by some of the results (boooooooo).

I'm using D3DFMT_R32F to create the texture to make the shadow map buffer. Am I getting a 32-bit float back when I sample the texture's red channel? The enum suggests just a red 32-bit channel but you still set it as float4 in the shader and read it as a float4.

I noticed these other enums.
D3DFMT_G32R32F
D3DFMT_A32B32G32R32F

Not sure what to think.

What I'm confused about is that I need to subtract from my depth value to get more of the shadow to show itself. Is what I'm getting an 8-bit float?


//-----------------------------------------------------------------------------
// pixel shader to compair Z depth based on shadow map buffer to
// color or shade the pixel
//-----------------------------------------------------------------------------
float4 p_shaderShadowed( PS_INPUT_SHADOW IN ) : COLOR0
{
float4 finalColor = IN.color;

// Test to see if the light is facing the pixel
if( IN.dotProd < 0.f )
{
finalColor = ambient;

float2 projTexCoords;
projTexCoords[0] = IN.lPos.x/IN.lPos.w/2.0f + 0.5f;
projTexCoords[1] = -IN.lPos.y/IN.lPos.w/2.0f + 0.5f;

float2 projTexCoordsSat = saturate(projTexCoords);

// Get the shadow map depth value for this pixel
float shadowdepth = tex2D(shadowMapBufTextSampler, projTexCoords).r;

// Check our value against the depth value
float ourdepth = IN.lPos.z / IN.lPos.w;

// Check if the projected x and y coordinates are within the [0, 1] range
// If not, then they are not in view of the light
if( (projTexCoordsSat.x == projTexCoords.x) &&
(projTexCoordsSat.y == projTexCoords.y) &&
(IN.vPos.z > 0) )
{
// Check the shadowdepth against the depth of this pixel

// ***** Have to subtract from the "ourdepth" value to get more of the shadow to show ******
// ***** Could this be the result of a 8-bit float ?! *********
if( (ourdepth - 0.003f) <= shadowdepth)
{
finalColor = IN.color;
}
}
else
finalColor = IN.color;
}

return tex2D( diffuseTextSampler, IN.uv0 ) * finalColor;
}

Share this post


Link to post
Share on other sites
Advertisement
To the best of my knowledge, what you're doing is exactly correct. The subtraction is what is called shadow bias and you need to do it to get the shadows to show up correctly, it's part of how shadow mapping works. It does not, in any way, shape or form, mean you're dealing with any kind of buffer in particular. And R32F definitely means 32-bit floating point when you read the buffer.r variable - even though HLSL requires you to treat it as a float4. At least that's the way I do it and it works fine.

Share this post


Link to post
Share on other sites

The subtraction is what is called shadow bias and you need to do it to get the shadows to show up correctly...

It's good to know this is the expected result. It's weird to think that depending on the scene, I need to fiddle with the "shadow bias" to get the correct results. May need to add a setting so this value can be unique per object. Is it possible to have an object that doesn't shadow correctly? It's seems like I need to fiddle with this number based on how close or far the light source is.

It was this shadow map example that made me wonder what I was seeing was the result of a 8-bit float
Riemers XNA Tutorial > Real shadow

This is the text from that page that talks about an 8-bit float.

if ((realDistance - 1.0f/100.0f) <= depthStoredInShadowMap)
{
}
/*
You see we subtracted a little bias of 1/100. Let me show you why. We store depth information as a color in our Shadow Map.
One color component of this map is stored in only 8 bits, so the smallest difference is 1/256. Now say the maximal distance
in our scene is 40.0f, so the smallest difference is 40/256 = 0.156f. This means that in even the best case, all points with
distances 0.156f to 0.234f will be stored as 0.156f.

Take for example a point at real distance 2.0f (which is stored as 0.156f in our shadow map!). You would like to check whether
the real and stored distances are the same: if (2.0f == 0.156f) so this would FAIL, and you would think the point is in the shadow
of another object. For this, we need to subtract a small value of our real distance while comparing
*/

Share this post


Link to post
Share on other sites
The author seems to confuse bit-per-channel and bit depth overall (assuming he's also working with an R32F shadow map). R32G32B32A32F is not 32-bit overall (ie. 8-bit per channel), it is 32-bit for each channel. He seems to assume the former and, apparently, because of that, believes the R32F format to also only be 8-bit deep?

One color component of this map is stored in only 8 bits[/quote]

is not correct for an R32F render target (to the best of my knowledge - and this link to the MSDN for example agrees):


D3DFMT_R32F 32-bit float format using 32 bits for the red channel.[/quote]

I wasn't able to find out on a whim what kind of render target format the author of these tutorials (of which I have previously heard bad things) uses but if he's indeed talking about R32F he's mistaken.

Share this post


Link to post
Share on other sites
Based on the code towards the bottom of the page it would appear the author of that article is using a RGBA8 render target which would explain why he is talking about the 8bit issues. Last time I used a standard RGBA8 texture for a shadow buffer the accepted method was to do some maths to use all 32bit (you basically extract sections of the final float into 8bit values to write and reverse the operation on read) and don't try to shove everything into 8 bits as it will fall over :)

Of course these days you are better off using an R32 format or the depth buffer render target directly instead of messing about :)

Share this post


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

  • Advertisement
×

Important Information

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

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!