Skip to main content
GameDev.net gamedev.net
🔒 Locked

Optimization: Depth Only Rendering Pass

Started by blaze02 Jan 29, 2007 at 1:05 PM 19 replies 11.1k views
Original Post
blaze02
blaze02
I'm working on a shader graphics engine. First, it disables the color channels and renders the scene to the z-buffer. Then, it turns the color writing back on, and renders the final scene. This works great in that it only has to pixel shade the pixels that are not rejected by the final z-buffer. I get a little z fighting because the pixel shaders are not outputting the same z-value as the fixed pipeline. Has anybody else had this happen? This happens to all my geometry in the scene, even the quads that are rendered using the world matrix set as the identity matrix. It can easily be fixed by adding a small offset to the z value in the vertex shader, but that solution doesn't seem ideal. I've heard messing with the z-bias render state is not a good solution either. Anything I'm missing? Thanks for the help.
Gagyi
Gagyi
Simply use D3DCMP_LESSOREQUAL
-----------------------------------"After you finish the first 90% of a project, you have to finish the other 90%." - Michael Abrashstickman.hu <=my game (please tell me your opinion about it)
Drazgal
Drazgal
The trouble with Z Bias is that theres no real standard way of implementing it on the graphics cards so the units are fairly meaningless and so you can't reply on getting the same result every time. It's far safe to diddle the mvp matrix instead :)
Schrompf
Schrompf
Been there, done that. Even LESSEQUAL gives you patterns of misplaces z-rejects over all surfaces. We solved it by multiplying projectedPos.z with 0.001f. We tried other formulas, viewPos.xyz * 0.001f being the only other method that does not produce heavy artifacts. But this version has problems with parts close to the far clipping plane. There's a seem at the far clipping plane only covered by the PreZ pass but not by the actuall renderings. And you get Z-fighting on distant scene parts with a certain angle to the camera. Better head for the projectedPos.z * 0.001f.

Another question while we're at it: Does the PreZ pass actually gain you anything performance-wise? My test system is Athlon 64 3200+, Geforce7800GT. Although the average pixel shader is 100 instructions in size, we lost roughly 30% framerate by adding that PreZ pass. Only simple test scenes and small indoor scenes do profit a bit by PreZ. From my present experience, I'd drop out PreZ happily if I could. The problem is that we also render out the depth into a texture at the PreZ pass. And there are a couple of post processing filters now that rely on accessing that depth. Bad luck, I guess.

Bye, Thomas
----------
Gonna try that "Indie" stuff I keep hearing about. Let's start with Splatter.
osmanb
osmanb
Ummm, how about using the same geometry transformation during both passes. This is a solved problem, eh? Just because you're not writing color doesn't mean you have to turn off shaders, just write a very simple 'prepass' shader that only does transformation, and no color/lighting work. You should be able to use ZEQUAL and get EXACTLY the same rasterization on the lighting passes as you do during your z-prepass. Doom III worked this way. And yes, it is very often a performance win (assuming that your pixel shaders are expensive and/or you have a non-trivial amount of overdraw).
Schrompf
Schrompf
Quote:

Ummm, how about using the same geometry transformation during both passes. This is a solved problem, eh? Just because you're not writing color doesn't mean you have to turn off shaders, just write a very simple 'prepass' shader that only does transformation, and no color/lighting work. You should be able to use ZEQUAL and get EXACTLY the same rasterization on the lighting passes as you do during your z-prepass.


No. As I said: I tried it. It doesn't transform exactly the same. Same matrices, same viewport, yet I got sparkling ZFail patterns everywhere. Happened both on a ATI Radeon 9800 Pro and a NVidia Geforce 7800 GT. I've read this claims in some docs as well, but theory doesn't match reality here.

Bye, Thomas

----------
Gonna try that "Indie" stuff I keep hearing about. Let's start with Splatter.
zedzeek
zedzeek
u should never see zfighting by drawing the same geometry, ive been doing it for years + never an issue ( in fact in the gl spec IIRC its guarantted to work) . the only cases where it can fail is if the vertices are not the same
(eg clipplanes are enabled)
Zipster
Zipster
This sounds to me a lot like deferred shading - is there a reason why you're not not using that instead? Or are you trying to support older hardware?
PfhorSlayer
PfhorSlayer
Assuming you're using the same geometry for the depth only pass and the rest of the passes, the ONLY way you should be getting ANY sort of z-fighting artifact is, as others have mentioned, if you're using a different transform.

Note that using the FFP transform and doing the multiply yourself in a vertex shader are NOT THE SAME! There are some options and ways you can work around this, but, like someone already said, simply write a depth-only shader that transforms the vertices exactly as is done for the rest of the shaders.
krausest
krausest
Quote:
Original post by blaze02
I get a little z fighting because the pixel shaders are not outputting the same z-value as the fixed pipeline.


In OpenGL you can say ftransform() in your vertex shader and it guarantuees that the transformation output will be identical to the fixed pipeline. Doesn't DirectX offer a similar function()?

Schrompf
Schrompf
Strange then. Both PreZ and main geometry were done by shaders. Same world matrices, same view matrix, same projection matrix. Different render targets, but of the same size. Still I got z-fighting artifacts. It has been a while since I last checked it, though. I better recheck that when I'm home again before insisting on it.

Bye, Thomas
----------
Gonna try that "Indie" stuff I keep hearing about. Let's start with Splatter.
jamessharpe
jamessharpe
Are you turning off z-writes for the color write? Since you've already drawn all the depth information you only need to do a z compare when rendering the colour buffer.
zedzeek
zedzeek
perhaps youre doing something like
A/
MultMatrix( mat )
draw mesh

B/
draw mesh
in shader -> mat * vert

whilst logically they should result in the same, in reality cause of the different storage methods it wont

superpig
superpig
Quote:
Original post by krausest
In OpenGL you can say ftransform() in your vertex shader and it guarantuees that the transformation output will be identical to the fixed pipeline. Doesn't DirectX offer a similar function()?


Nope.

(Any idea how widely supported the ftransform() function is in GLSL?)
Richard "Superpig" Fine - saving pigs from untimely fates - Microsoft DirectX MVP 2006/2007/2008/2009
"Shaders are not meant to do everything. Of course you can try to use it for everything, but it's like playing football using cabbage." - MickeyMouse
Matt Aufderheide
Matt Aufderheide
This is a normal problem when trying to combine fixed-function z pass and shader color pass. Dont do it, because it wont work on certain cards. Both pases should use shaders and there will be no problem.
JasonBlochowiak
JasonBlochowiak
I'm currently doing z-prepass in my renderer, and it's working just fine on a 7800. I am using shaders for prepass and main pass.

[edit - This is using DX9, btw.]
Jason Z
Jason Z
What is the test scene that you are using? If there is not a whole lot of movement frame to frame, and if you are not clearing the z-buffer to 1.0, I have had situations where it seems like you are getting z-fighting, but it is really that the z-buffer is never getting cleared.

Can you describe your exact sequence that you are using for rendering? Are you doing any depth surface moving around or copying? Try to be as specific as possible when you describe the problem.

Also, have you tried using PIX to step through a frame one draw call at a time and see what is happening? If you haven't ever done it - learn how, it is worth it. You could also use NVPerfHUD if you have an NV card. The solution should show itself if you start taking a closer look. Good luck!
Jason Zink :: DirectX MVP   Direct3D 11 engine on CodePlex: Hieroglyph 3 Direct3D Books: 
OrangyTang
OrangyTang
Quote:
Original post by superpig
Quote:
Original post by krausest
In OpenGL you can say ftransform() in your vertex shader and it guarantuees that the transformation output will be identical to the fixed pipeline. Doesn't DirectX offer a similar function()?


Nope.

(Any idea how widely supported the ftransform() function is in GLSL?)

It's part of the spec, you can't have a GLSL implementation without it.
superpig
superpig
Quote:
Original post by OrangyTang
Quote:
Original post by superpig
Quote:
Original post by krausest
In OpenGL you can say ftransform() in your vertex shader and it guarantuees that the transformation output will be identical to the fixed pipeline. Doesn't DirectX offer a similar function()?


Nope.

(Any idea how widely supported the ftransform() function is in GLSL?)

It's part of the spec, you can't have a GLSL implementation without it.


Hm, ok. So how widely available is standards-compliant GLSL? [grin]
Richard "Superpig" Fine - saving pigs from untimely fates - Microsoft DirectX MVP 2006/2007/2008/2009
"Shaders are not meant to do everything. Of course you can try to use it for everything, but it's like playing football using cabbage." - MickeyMouse

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.