You need to be careful about spaces - position and normal need to be in view space. To transform depth into view space position I used [this][1] method. So: vec3 viewPositionFromDepth(vec2 vTexCoord) { float z = texture2D(depthTexture, vTexCoord).r; // Get x/w and y/w from the viewport position float x = vTexCoord.x * 2.0 - 1.0; float y = vTexCoord.y * 2.0 - 1.0; vec4 vProjectedPos = vec4(x, y, z, 1.0f); // Transform by the inverse projection matrix vec4 vPositionVS = invProjection*vProjectedPos; // Divide by w to get the view-space position return vPositionVS.xyz / vPositionVS.w; } To transform normal into view space you need to multiply it by inverse of transpose of view matrix (should be done on CPU): vec4 n = transpose(inverse(ViewMatrix)) * normalize(texture2D(normalTexture, texCoord)*2.0 - 1.0 ); And in loop while sampling depth with offset to compare with kernel position, this depth should be in same space as position so I did it the same way: float sampleDepth = viewPositionFromDepth(offset.xy).z; This is not the most optimal way though, but it worked for me. [1]: https://mynameismjp.wordpress.com/2009/03/10/reconstructing-position-from-depth/