I wrote an ssao algorithm with compute shaders and view-position-reconstruction from the depth buffer. It works great for objects near by but results in strip or banding artifacts for large planes further away:enter image description here

This does not happen if i use an explicit position buffer. I don't think this is because of floating point accuracy. My methods to reconstruct the position for the original pixel and the z coordinate for the pixels in its hemisphere:

vec3 calcViewPos(vec2 texCoords, float depth){
    vec3 clipPos = vec3(texCoords, depth) * 2.0 - vec3(1.0);
    vec4 viewPos = vec4(vec2(invProj[0][0], invProj[1][1]) * clipPos.xy, -1,
                                   invProj[2][3] * clipPos.z + invProj[3][3]);
    return(viewPos.xyz / viewPos.w);

I use a GL_DEPTH_COMPONENT32 depth texture. I could solve the problem by a little hack: Comparing the normal of the original pixel and the normal of the neighbourhood pixels and skipping those which have a too similar normal solves this problem (since this only occurs on those large plains), but causes an additional texture lookup in a for loop, which costs too much (and would make using a position buffer again more efficient).

Did any of you experience a simillar problem or have ideas of how to solve this smarter? Thank you very much :)

  • $\begingroup$ Are you offsetting the depth positions with a bias value? And are you using any depth clamping? And what is your depth slope factor? $\endgroup$
    – pmw1234
    Dec 3, 2021 at 12:05
  • $\begingroup$ @pmw1234 yes i tried to increase the bias already, but that just shifts the banding along the view-z-axis and of course lowers the quality of the remaining ao. No i don't use depth clamping. If you mean the fov, its 70 degree $\endgroup$ Dec 3, 2021 at 21:51

1 Answer 1


For anyone having the same problem: I calculated the normalized texture coordinates by

vec2 imgSize = imageSize(img_output);
vec2 normtc = vec2(gl_GlobalInvocationID.xy) / imgSize;

this is of course wrong, the last line should be:

vec2 normtc = (vec2(gl_GlobalInvocationID.xy) + vec2(0.5)) / imgSize;

since we want to sample the center of the pixel. This solved the problem for me.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.