nVidia GlSlang gl_FragDepth

Started by
2 comments, last by vincoof 19 years, 9 months ago
I've been messing around with GlSlang these last couple of days, since the new drivers came out. Thus far I've done infinite shadow volumes using the vertex shader, normal mapping and parallax mapping. I've been trying to extend my parallax mapping shader to offset the fragment depth values, but I'm getting strange behaviour from the shader. To test it out properly I wrote a simple program which simply renders a green quad with one shader and a red quad with another shader at exactly the same position. The red quad is rendered second using a GL_EQUAL depth test and the green quad is rendered with shaders which change the depth of the fragments. If I run them with the following shaders:
green quad shader:
void main()
{
	gl_FragColor = gl_Color;
}
red quad shader:
void main()
{
	gl_FragColor = gl_Color;
}
I get the expected result - the red quad is rendered. If I use:
green quad shader:
void main()
{
	gl_FragColor = gl_Color;
	gl_FragDepth = gl_FragCoord.z;
}
red quad shader:
void main()
{
	gl_FragColor = gl_Color;
}
Again, as expected, the red quad is rendered. If I use:
green quad shader:
void main()
{
	gl_FragColor = gl_Color;
	gl_FragDepth = 0;
}
red quad shader:
void main()
{
	gl_FragColor = gl_Color;
}
As expected the red quad is not rendered because the depths no longer match. But if I use:
green quad shader:
void main()
{
	gl_FragColor = gl_Color;
	gl_FragDepth = gl_FragCoord.z + 1;
}
red quad shader:
void main()
{
	gl_FragColor = gl_Color;
}
Then the red quad is rendered, despite the fact it should have a different depth value. It doesn't even matter what constant I use. I tried +/- 0.00001, 0.01, 1, 100 and 100000 and the result was always the same. I've written depth values from ARB_ and NV_ fragment_programs before and don't remember encountering any problems like this. Is this a possible driver bug or am I just completely forgetting how to use depth values? Enigma
Advertisement
I'm impressed that the following shader works :
green quad shader:void main(){	gl_FragColor = gl_Color;	gl_FragDepth = gl_FragCoord.z;}red quad shader:void main(){	gl_FragColor = gl_Color;}

Either you are lucky, or the GLslang compiler detects you're not changing the depth fragment and ignores the "gl_FragDepth = gl_FragCoord.z;" line.
Why am I talking about luck ? Simply because the fragment programs and fragment shader specs clearly state that rasterized fragments are not guaranteed to produce exactly the same depth values when depth output is written in the shader compared to "default" depth output. This is due to floating-point precision errors.
So I rather think that the compiler is clever enough and ignores the line of code that writes depth, thus it behaves like the following shader :
green quad shader:void main(){	gl_FragColor = gl_Color;}red quad shader:void main(){	gl_FragColor = gl_Color;}


Then, if you really modify the depth output (like adding +0.001) the compiler really has to modify the depth, and it's possible that this case is not working very well in first GLslang implementations. So, to cut a long story short, yes I think there is some kind of bug. I'm not really surprised though.
Thanks for the reassurance that I'm not just going crazy.

Regarding the 'gl_FragDepth = gl_FragCoord.z;' - I was under the impression from the spec that gl_FragCoord.z holds the fixed-function z-depth of the fragment (assuming the polygons are transformed by the fixed function pipe and not by a vertex program):

Quote:GlSlang Spec:
The variable gl_FragCoord is available as a read-only variable from within fragment shaders and it holds the window relative coordinates x, y, z, and 1/w values for the fragment. This value is the result of the fixed functionality that interpolates primitives after vertex processing to generate fragments. The z component is the depth value that would be used for the fragment’s depth if a shader contained no writes to gl_FragDepth. This is useful for invariance if a shader conditionally computes gl_FragDepth but otherwise wants the fixed functionality fragment depth.


My emphasis on the last sentance.

Enigma
Ok, could you try :
gl_FragDepth = gl_FragCoord.z + 0;
or :
gl_FragDepth = gl_FragCoord.z * 1;
Unless the compiler is clever enough, my guess is that both won't behave like :
gl_FragDepth = gl_FragCoord.z;

This topic is closed to new replies.

Advertisement