Reading from a depth texture in a pixel shader in DX9

Started by
7 comments, last by eigers 16 years ago
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.
Advertisement
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

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

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.
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
deathkrushPS3/Xbox360 Graphics Programmer, Mass Media.Completed Projects: Stuntman Ignition (PS3), Saints Row 2 (PS3), Darksiders(PS3, 360)
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?
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.
deathkrushPS3/Xbox360 Graphics Programmer, Mass Media.Completed Projects: Stuntman Ignition (PS3), Saints Row 2 (PS3), Darksiders(PS3, 360)
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?
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.
deathkrushPS3/Xbox360 Graphics Programmer, Mass Media.Completed Projects: Stuntman Ignition (PS3), Saints Row 2 (PS3), Darksiders(PS3, 360)
Thanks a lot for your help.

This topic is closed to new replies.

Advertisement