• 9
• 9
• 11
• 12
• 9

# higher precision depth buffering?

This topic is 4212 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I'm making an app with outdoor scenes. My intention was to get good details close up as well as a long view distance, but with the standard depth buffering that is out of the question - I get z fighting even for quite sparse heightmap grids and must set the near plane so far away that it isn't really possible to move up as close to the things as I had intended. Judging from some books like GPU Gems and ShaderX series there should be some way of setting depth buffers to higher precision. I've also heard some source claiming that w buffering should be avoided but it was an old source so I'm not sure whether this is good advice or not. In either case, I'd like to find the syntax for getting better depth buffer precision, and also if possible some information about the hardware compatibility issues related to increasing depth buffer precision.

##### Share on other sites
Are you using IDirect3D9::CheckDepthStencilMatch() to enumerate support for different formats? You'll pretty much be guaranteed a 16bit ZB, most have a 24bit one and some have a 32bit ZB. That's one simple way of getting higher-precision. Not even D3D10 goes beyond a 32bit depth buffer.

However, most improvements can be achieved by playing with the projection matrix set up. Learning how the mathematics behind it works (refer to a good classic graphics textbook) should allow you to pick the best values. Typically avoiding very high ratio's of Znear and Zfar values does the trick.

I've not tried it, but I've read about doing multiple-passes and tweaking the projection matrix to get absolute maximum Z accuracy. For example, if you want 0..10000 range you could divide it into 4 sections (0-2500, 2500-5000, 5000-7500, 7500-10000) and use clipping planes to split it into 4 passes, each with a projection matrix set to precisely that range. I'd imagine it won't be amazingly fast, but it might be worth considering.

hth
Jack

##### Share on other sites
Remember that the ratio of distribution of precision of the z-buffer (16 or 24 bit) is zfar / znear. You should have a ratio between these of about 500 (iirc, someone please correct me if I'm wrong). This also means that you need to be careful when setting znear to a small value. An example:

zfar = 500.0f, znear = 1.0f -> OK!

zfar = 500.0f, znear = 0.1f -> doesn't seem like a big change distance-wise (and may seem tempting if you want a near plane that's really close, but will leave you with only a tenth of the precision!

Hope this helps!

//Simon

EDIT: jollyjeffers beat me to it while i was writing this reply ;)

##### Share on other sites
Thank you for the fast replies!

@jollyjeffers: I think I've now found one possible procedure for solving the problem:
- step1: IDirect3D9::CheckDepthStencilMatch()
- step2: device->CreateRenderTarget(...) using for example format D3DFMT_D24FS8
- step3: device->SetDepthStencilSurface(...)
- step4: render the stuff

@simonjacoby: 500 sounds a bit too low to at all be possible for my application :| My plan was to be able to zoom in to about 1-10 meters from units but at the same time be able to see all the way to the horizon, which is approximately 20,000 meters away when the camera is around 50 meters above sea level - which means 20,000 or 2,000 for the quotient! But looking at many professional games with large outdoor scenes I think I've seen plenty of z fighting artifacts so it might be acceptable - at least with high depth buffer precision and the 2,000 quotient... I'll have to experiment more with it and perhaps give up on either of the demands high range or close zoom!

##### Share on other sites
this is my first time dealing with changing buffer formats etc, so of course I ran into problems when trying to implement the format change stuff... I'd like to use a floating point back buffer together with the high precision depth format is possible, but I have so far not found a single floating point format that my hardware has said is compatible (which I know is true, because I've tried an HDR sample which used floating point render targets).

Here's an example
	if(FAILED(g_pD3D->CheckDepthStencilMatch(			D3DADAPTER_DEFAULT,			D3DDEVTYPE_HAL,			D3DFMT_X8R8G8B8, //adapter format			D3DFMT_A32B32G32R32F, //render target			D3DFMT_D15S1) //depth stencil format			)) {		//error: not supported!	}

...is anyone familiar with any format which uses a floating point render target that should work on a Nvidia 7600 GS GPU?

##### Share on other sites
Just a very quick reply (lunchtime and I wanna watch the GP [wink]). Look up the "Graphics Card Capabilities" entry in the SampleBrowser (or search for "cardcaps.xls" in your install directory). It's not exhaustive, but it does list most of the common GPU's and what they support.

The 7800 (close enough to the 7600) only supports three - D16, D24S8 and D24X8. Only some really old and obscure hardware seems to handle D15S1.

hth
Jack