title: GLSL - SSAO: Getting undesired results when fetching depth position
body: <p>I am trying to implement SSAO based on this tutorial: <a href="http://john-chapman-graphics.blogspot.com/2013/01/ssao-tutorial.html" rel="nofollow noreferrer">http://john-chapman-graphics.blogspot.com/2013/01/ssao-tutorial.html</a>. I don't seem to understand how to achieve this and I keep getting undesired results in my fragment shader.</p>
  
  <p>First I setup my shader to pass in the depth buffer, camera's projection matrix and 4x4 noise texture. The ssao kernel has already been initialized and passed into the shader as well. I also sample the normal from the depth buffer.</p>
  
  <p><strong>EDIT:</strong> At first I thought I was getting the depth position incorrectly so I added a new function called positionFromDepth, but it still doesn't seem to work...</p>
  
  <p>My fragment shader:</p>
  
  <pre><code>uniform sampler2D uDepthBuffer;
  uniform sampler2D uNoiseTexture;
  
  uniform mat4 uProjection; // camera's projection matrix
  uniform mat4 uInverseMatrix; // inverse of projection matrix
  uniform vec2 uNoiseScale; // vec2(1024.0 / 4.0, 768.0 / 4.0)
  
  const int MAX_KERNEL_SIZE = 128;
  
  uniform int uSampleKernelSize;
  uniform vec3 uSampleKernel[MAX_KERNEL_SIZE];
  
  uniform float uRadius;
  
  const float zNear = 0.1;
  const float zFar = 2579.5671;
  
  float linearizeDepth(float near, float far, float depth) {
      return 2.0 * near / (far + near - depth * (far - near));
  }
  
  vec3 positionFromDepth(vec2 texcoords) {
      float d = linearizeDepth(zNear, zFar, texture2D(uDepthBuffer, texcoords).r);
      vec4 pos = uInverseMatrix * vec4(texcoords.x * 2.0 - 1.0,
                                       texcoords.y * 2.0 - 1.0,
                                       d * 2.0 - 1.0, 1.0);
  
      pos.xyz /= pos.w;
  
      return pos.xyz;
  }
  
  vec3 normal_from_depth(float depth, vec2 texcoords) {
    const vec2 offset1 = vec2(0.0, 0.001);
    const vec2 offset2 = vec2(0.001, 0.0);
  
    float depth1 = linearizeDepth(zNear, zFar, texture2D(uDepthBuffer, texcoords + offset1).r);
    float depth2 = linearizeDepth(zNear, zFar, texture2D(uDepthBuffer, texcoords + offset2).r);
  
    vec3 p1 = vec3(offset1, depth1 - depth);
    vec3 p2 = vec3(offset2, depth2 - depth);
  
    vec3 normal = cross(p1, p2);
    normal.z = -normal.z;
  
    return normalize(normal);
  }
  
  void main() {
      vec2 texcoord = gl_TexCoord[0].st;
  
      vec3 origin = positionFromDepth(texcoord);
  
      float d = texture2D(uDepthBuffer, texcoord).r;
      vec3 normal = normal_from_depth(linearizeDepth(zNear, zFar, d), texcoord) * 2.0 - 1.0;
      normal = normalize(normal);
  
      vec3 rvec = texture2D(uNoiseTexture, texcoord * uNoiseScale).rgb * 2.0 - 1.0;
      vec3 tangent = normalize(rvec - normal * dot(rvec, normal));
      vec3 bitangent = cross(normal, tangent);
      mat3 tbn = mat3(tangent, bitangent, normal);
  
      float occlusion = 0.0;
  
      for(int i = 0; i &lt; uSampleKernelSize; i++) {
          vec3 sample = tbn * uSampleKernel[i];
          sample = sample * uRadius + origin.xyz;
  
          vec4 offset = vec4(sample, 1.0);
          offset = uProjection * offset;
          offset.xy /= offset.w;
          offset.xy = offset.xy * 0.5 + 0.5;
  
          float sampleDepth = positionFromDepth(offset.xy).z;
          occlusion += (sampleDepth &lt;= sample.z ? 1.0 : 0.0);
      }
  
      occlusion = 1.0 - (occlusion / float(uSampleKernelSize));
      gl_FragColor = vec4(pow(occlusion, 4.0));
  }
  </code></pre>
  
  <p>The occluded samples changes when I move my camera around. The result looks something like this:</p>
  
  <p><img src="https://i.stack.imgur.com/mCsis.jpg" alt="Result from SSAO shader"></p>
  
  <p>I am assuming I am doing something wrong when sampling the depth position, but maybe I am doing something wrong with the projection matrix as well. Should the uProjection matrix be transposed or inverted? Can anyone identity the issue?</p>
  
  <p>Also ignore the fact that I haven't done a blur pass yet.</p>