Reputation: 4501
I have a two pass rendering. in the first pass i render some opaque geometry using an FBO into several textures.
In the second pass I render the same geometry again and based on different geometry properties (like object, normal etc.) i'm writing the calculated colorvalues from pass 1 into specific texels of some textures using imageStore() (image_load_and_store)
I want this to happen only for visible fragments however (only those corresponding to the final fragmentcolors of pass 1)
so what i try now is to take the GL_DEPTH_ATTACHMENT texture from pass 1 and attach it to the fbo from pass 2 (also as GL_DEPTH_ATTACHMENT) and then before rendering pass 2 i set
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT);
glDepthMask(false);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
...render my scene...
And i'd expect the fragment shader (which uses imageStore()) to execute only for those fragments that were visible in pass 1 (and since it's the same scene i render, also in pass 2).
But it doesn't seem to work - hidden fragments are processed too and execute imageStore() (and since they use colors calculated in pass1 for the visible fragments, they do the wrong thing)
Any idea why? does imageStore or something else force the fragmentshader to execute? can I control this somehow? does it have to do something with early-z?
Upvotes: 2
Views: 1943
Reputation: 473322
The OpenGL specification defines that the fragment shader executes before the depth test. If some hardware executes the depth test first, then it would only be in circumstances when no behavioral changes would be noticed by the switch.
Well, unless you just tell the fragment shader to execute after the depth test, by putting this line in your fragment shader:
layout(early_fragment_tests) in;
This is part of shader_image_load_store, for obvious reasons.
Upvotes: 3
Reputation: 45948
Since early-z is only an optimization facility that doesn't need to be done, I guess this is perfectly valid behaviour.
As said, early-z is a mere optimization that is not allowed to alter the behaviour in any way. It doesn't alter the output when the fragment get's depth rejected anyway, but with the advent of image load store, the fragment is not the only output any more, and a shader invocation for a fragment that fails the depth test could still have written into an image. Therefore early-z has to be disabled in this case, to guarantee consistent behaviour. Your compiler doesn't magically know, that you don't want to write into the image when the depth test fails, since it only sees a shader that writes something into an image and early-z is not specified anywhere.
You won't get around performing your own depth test, by not using the depth texture as depth attachment, but as texture input:
uniform sampler2D depth;
void main()
{
if(gl_FragCoord.z > texture(depth, gl_FragCoord.xy / textureSize(depth))
discard;
...
}
Upvotes: 1