Read the ZBuffer?

Started by
6 comments, last by jollyjeffers 17 years ago
Hello! How can i read the values from the ZBuffer? Is it possible to save for each pixel in the zbuffer for which object the pixel stands for? I needed this because i wanted to make a fast collission detection in 2d by first drawing one object then a second one and testing the zbuffer if the second object has overdrawn the first object or not. Thanks a lot!!
Gaudeamus igitur, iuvenes dum sumus!
Advertisement
If you want to find out how many pixels of an object are actually visible you can use D3D’s occlusion query feature. You can draw the second object under the first one and see if all pixels pass the depth test; this way you do not need to access the z-buffer.
http://www.codesampler.com/dx9src/dx9src_7.htm#dx9_occlusion_query
http://www.gamedev.net/reference/articles/article2128.asp
Oh thanks a very good hint! But how can i directly access the zbuffer?
Gaudeamus igitur, iuvenes dum sumus!
Note that the sort of algorithm you're attempting will need to tolerate a couple of frames latency if you want really high performance. Issuing draw commands and expecting to immediately read the values back will force lock-step with CPU and GPU and kill the parallelism that helps makes GPU's so fast [smile]

Quote:Original post by dali
Oh thanks a very good hint!
Make sure you understand the performance implications of occlusion queries; they're a nice tool but they can be painful...
Quote:Original post by dali
But how can i directly access the zbuffer?
You don't.

There are a couple of lockable formats in the enumeration, but I'm not aware of there being much hardware support for these.

A typical approach would be to use a pixel shader and possibly MRT's to output the Z value and/or an Object ID value.

hth
Jack

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

Quote:Original post by dali
Oh thanks a very good hint! But how can i directly access the zbuffer?


1. Use the D3DFMT_D16_LOCKABLE or D3DFMT_D32F_LOCKABLE format for yout depth buffer (depending on which your graphics hardware/device driver supports - some don't support any lockable formats).

2. IDirect3DDevice9::GetDepthStencilSurface gets you an IDirect3DSurface9 interface representing the depth and stencil surface. NOTE: the IDirect3DSurface9 interface is reference counted so you need to call ->Release() on it when you're done with the pointer.

3. finally IDirect3DSurface9::LockRect gets you direct access to the data in the depth buffer.


Generally though, I'd advise against trying to read back from the Z buffer using the CPU: the lock will cause a serialisation waiting for the GPU to finish rendering up to the point where you called LockRect; there's a very good chance you'll be reading back from uncached memory (slooooww for the CPU); you might not get the optimisation of proper hierarchical-Z (depending on the card).

There is usually always a better alternative to reading the Z buffer directly these days, for lens flare visibility tests occlusion queries are where it's at; for Z buffer based shadow techniques, use a render target texture and a shader to output the depth to a colour channel of that texture - use the texture where you would usually use the ZB, etc...

[edit]Bah, the lateness! That's what happens when I don't refresh enough[wink][/edit]

Simon O'Connor | Technical Director (Newcastle) Lockwood Publishing | LinkedIn | Personal site

Ok thanks! Good to know that these locks need time but i hope this approach is faster as testing two objects manually against each other by comparing pixels.
Gaudeamus igitur, iuvenes dum sumus!
Oh thanks again :)

Quote:Original post by S1CA
Generally though, I'd advise against trying to read back from the Z buffer using the CPU...


I just have to write to the buffer once so this shouldnt be that big problem.
Gaudeamus igitur, iuvenes dum sumus!
Quote:Original post by dali
Quote:Original post by S1CA
Generally though, I'd advise against trying to read back from the Z buffer using the CPU...


I just have to write to the buffer once so this shouldnt be that big problem.
Just because you're writing depth doesn't mean you should read it - conceptually you are just talking about a block of video memory, but it's such an integral core part of GPU-based graphics that it's a focus of some serious optimizations by the IHV's.

In general the depth information doesn't need to be accessed by the application and is optimized accordingly. By breaking that rule you'll effectively cancel out any of their optimizations and destroy the performance advantages (Hierarchical-Z and early-rejection can be huge performance gains), combine this with your proposed instant read-back of depth and you're forcing a sub-optimal rendering in lock-step with the CPU. Bottom line is you'll be wasting such a huge amount of potential performance it brings into question whether you'll see much advantage by offloading this GPGPU style...

hth
Jack

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

This topic is closed to new replies.

Advertisement