Sign in to follow this  
eigers

Reading from a depth texture in a pixel shader in DX9

Recommended Posts

eigers    122
Hi everyone, Is there a way in DX9 to read values from a depth texture (D24S8 format) in a pixel shader? From reading in forums I understand that generally it's not possible, but is there a hack around it? I know that if I write the depth values into a R32F render target I can read it later, but unfortunately this is not an option for me. I also know that in DX10 this is not a problem anymore, but unfortunately this is not an option for me as well. I'd appreciate any asistance. Shai.

Share this post


Link to post
Share on other sites
jollyjeffers    1570
Yes, this sort of functionality is IHV-specific from what I remember.

Off the top of my head Nvidia GPU's support readback from the proper depth format textures subject to some constraints, but ATI/AMD GPU's require a custom format - something like FOURCC('D','F','2','4') I think.

Probably best to have a look around the respective IHV SDK's for details. It'll usually pop-up in the context of shadow mapping with PCF/Fetch-4 type filtering...


hth
Jack

Share this post


Link to post
Share on other sites
eigers    122
Thanks Jack,

From the NVIDIA docs it seems that the value returned by tex2dproj on the depth texture is shadow-map specific - 1 if the object is in the shadow, 0 otherwise. Do you know if it's possible to get the actual depth value as well?

Thanks,
Shai.

Share this post


Link to post
Share on other sites
deathkrush    350
The hack for NVIDIA is to lie to DX and provide an BGRA texture when it really is D24S8 texture under the hood. When you sample this BGRA texture in the shader you will get 4 values which you can use to reconstruct the depth. Stencil value will be in the B component and depth values will be in GRA components. The formula for reconstruction is:

float z = dot(tex2D(DepthSampler, uv).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5));

The BGRA format you need to provide is undocumented and varies from card to card. See this post for more details:

http://forum.beyond3d.com/showthread.php?t=43182

Share this post


Link to post
Share on other sites
eigers    122
Thanks deathkrush, you're a life saver.
Still, something seems odd here: the numbers used for conversion from the 3 eight bit values - they have far more precision than a single precision float can accommodate. So what actually happens here?

Share this post


Link to post
Share on other sites
deathkrush    350
What happens is that the compiler will truncate those numbers to float precision and you will get somewhat imprecise results. That said, precision is mostly fine and usable for effects such as soft particles and water fog even though the values you'll get are different from values in the depth buffer. If you are using this technique for something crazy, like resizing the depth buffer for mixed resolution rendering, then the formula might need some fudging.

Share this post


Link to post
Share on other sites
eigers    122
Nothing crazy, just computing object space coords from screen space. I guess the precision should be enough.
RAWZ is not supported on my 8800 GTS, only INTZ is. Do you happen to know if INTZ contains stencil bits as well as depth? Is it the same as RAWZ just with easier depth access or is it like a D32F?

Share this post


Link to post
Share on other sites
deathkrush    350
I haven't used INTZ format, but I think it just returns the correct depth value so you don't have to calculate it using crazy formulas. This means that INTZ doesn't give access to stencil bits.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this