Sunday, August 11, 2019

shaders - Disable depth testing for only some faces


I have some meshes and I need to be able to draw some part of them without depth test. Is it possible to turn off depth testing from within shader, wo that some parts will be rendered no matter what depth is in z-buffer ?


Or transform Z, W somehow to fake this ?



Answer



The most robust way to do this is probably to split your geometry into two separate draw calls, one with depth testing and one without.



That said, if you want to do it in one batch...


1) If the depth override is set on a per-vertex level, you can do something like this in your vertex shader:


output.position = mul(worldViewProjectionMatrix, vertex.position);
if(vertex.forceDraw)
{
output.position /= output.position.w;
output.position.z = 0.0f;
// might need to be -1.0f? I can't recall where the near plane maps to...
}


This should take the vertices that are supposed to render in front of everything and snap them to the near plane, without affecting their projected position on-screen. You'll still benefit from early depth testing this way. If you have polygons that include some always-drawn vertices and some regular ones, then that polygon may get cut partway along by other geometry.


2) If the depth-overriding is decided per-fragment, you can set the fragment depth in the fragment shader. Something like...


(Disclaimer: It's been a while since I messed with fragment depth, so think of this as a rough guide, not a copy-and-paste-ready sample. Always check what's appropriate for your language/environment of choice)


void frag(vertOutput input, out float4 color : COLOR, out float depth : DEPTH)
{
fragOutput output;
color = input.color;
if(shouldIOverrideDepth(input))
{
depth = 0.0f;

// might need to be -1.0f?
}
else
{
depth = input.position.z/input.position.w;
// You may need to convert this to a different range.
}
}

This will pass-through the expected depth for regular fragments, but replace it with the nearest depth for selected fragments.



This will disable early-z testing on everything drawn with this shader, which is bad for performance. So, consider splitting your geometry so that this shader is only used where absolutely necessary.




Note that both of these approaches will write super-near depths into the depth buffer for the affected fragments, if depth writes are enabled. If this is undesirable, you can disable depth writes for this shader, at the risk of later draw calls drawing over this content incorrectly.


(Both these approaches can work branch-free, but I've shown them with branches so it's clearer what's happening)


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...