1
\$\begingroup\$

I'm currently piggy backing on a mod framework (Multitheft Auto) and trying to read the depth buffer in D3DFMT_D24S8 (DirectX9). I can read it if I change the format to D3DFMT_D32F_LOCKABLE and then lock the rectange but this causes the render to be blurred like so: MTA with D3DFMT_D32F_LOCKABLE

I'm currently open to hacky methods like finding the pointer to the buffer and reading the depths without properly locking and/or using CUDA. Any advice would be greatly greatly appreciated. Thanks!

\$\endgroup\$
1
\$\begingroup\$

You can read the depth buffer in a pixel shader if you use one of the special formats described at http://aras-p.info/texts/D3D9GPUHacks.html. They are somewhat GPU vendor specific, but you can probably get away with just INTZ support.

That lets you either do what you need to do on the GPU, or to use the shader to copy it to another render target that you can read from more easily.

\$\endgroup\$
0
\$\begingroup\$

The old DirectX SDK outlines a method for being able to do this, but it does require that you use Direct3D 9 Ex rather than just plain-old Direct 3D 9. Since 9 Ex is only available on Vista+ this may not suit your requirements.

It's covered in the section titled Feature Summary (Direct3D 9 for Windows Vista) and I'll quote it in full:

Reading Depth/Stencil Buffers

Use IDirect3DDevice9::UpdateSurface to read or write depth/stencil data from surfaces obtained from IDirect3DDevice9::CreateDepthStencilSurface or IDirect3DDevice9::GetDepthStencilSurface.

First, create a lockable, depth only or stencil only surface using IDirect3DDevice9::CreateOffscreenPlainSurface. Use one of the following formats:

  • D3DFMT_D16_LOCKABLE
  • D3DFMT_D32F_LOCKABLE
  • D3DFMT_D32_LOCKABLE
  • D3DFMT_S8_LOCKABLE

Second, transfer data between the depth/stencil buffer and the newly-created lockable depth or stencil surface. The transfer is performed using IDirect3DDevice9::UpdateSurface.

UpdateSurface will fail when both surfaces are a LOCKABLE format or both are non-lockable.

Transferring non-existent data will result in an error (for example, transferring from a non-lockable depth-only surface to a D3DFMT_S8_LOCKABLE surface).

The rest of the restrictions for IDirect3DDevice9::UpdateSurface still apply.

As @Adam suggests in his answer, you really should consider whether or not you actually need to read the depth buffer back to the CPU. That's not going to be a fast operation whichever way you do it.

I'd suggest that you give more detail about why you feel you need to do this, perhaps even making it a separate question; it may well be the case that whatever you're trying to achieve can be done without such a read-back.

\$\endgroup\$
0
\$\begingroup\$

Turns out setting the resolution to 16 bit instead of 32 caused the blurring to go away. Figuring there was some pixel shader using the depth buffer that was able to deal with 16 bit color / 32 bit depth and 32 bit color / 24 bit depth, but not 32 bit color / 32 bit depth. Thanks @DarthMelkor for the Direct3D Ex suggestion. I may look more into that if there are more problems with changing the depth format. I don't have control over the initial device creation by GTA San Andreas though, so I'm not sure if I'd be able to use the UpdateSurface approach (I've def tried Direct3D 9 and get a format restriction error).

\$\endgroup\$
  • \$\begingroup\$ Have you tried getting depth map of GTA-V? \$\endgroup\$ – Muaz Usmani Sep 27 '17 at 17:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.