Reconstruct normals from depth buffer

Hello,

I try to implement SSAO in our engine, but I have problems reconstructing the normals from the depth buffer (z).
First I implemented my algorithm with depth and normal buffer in Rendermonkey and everything worked very well.

Without much modifications we only have the depth Buffer in our engine.

SSAO without normals, is not good enough, so I tried to reconstruct the normals from the depth.

I read several posts about this topic:

  1. http://www.gamedev.net/community/forums/topic.asp?topic_id=497072&whichpage=1&#3242547

  2. http://forum.beyond3d.com/showpost.php?p=908753&postcount=1

Depth Buffer and depth only SSAO (no blur):


First I recreated the viewspace position like in the 2nd post above:

//w = linear depth
vec3 getViewSpacePosition(in float w) {

	vec4 pos = vec4((gl_TexCoord[0].st - depth_size.xy * 0.5) / (depth_size * 0.5), vec2(1.0))
				* w * gl_ProjectionMatrixInverse;
			
		pos.y *= -pos.z * (far - near) / near;
		pos.x *= pos.z * (far - near) / near;

	return pos.xyz;
}

This looks pretty good as you can see in the picture below.

a. Then I tried to generate my normals with following code:


vec3 normal = normalize(cross(ddx(pos.xyz),ddy(pos.xyz)))

this results in:

So no such result as they have in their posts.

b. For testing I only used this code similar as in the 2nd thread the one used, the viewposition is here interpolated over the whole screen.


vec4 pos = vec4((gl_TexCoord[0].st - depth_size.xy * 0.5) / (depth_size* 0.5), w, 1.0) * w * gl_ProjectionMatrixInverse;

vec3 n = normalize(cross(dFdx(pos.xyz), dFdy(pos.xyz))) * 0.5 + 0.5;

Without “*0.5 + 0.5” it looks similar to viewspace normals with z and y switched and z being black.
But still not as good as the ones from the first thread I mentioned.

c. For further testing purpose I directly generated them from depth derivatives.


vec3 normal = normalize(vec3(dFdx(w) * 500.0, dFdy(w) * 500.0, 1.0)) * 0.5 + 0.5;

This gives a result identical to nvidia normal map generator see the light blueish piture.


For my SSAO I currently use version b, which gives the best results from the above.

In all versions you see the gradient in the normals from certain angles.
This highly makes the use of those normals for SSAO unusable in this case, because lower angles will still turn into dark surfaces which we wanted to get rid from.

But this is unavoidable I think, because from the depth derivatives (position) the lower the angle the more depth difference is present, but at least their normals look better.

If everyone knows what I do wrong getting those normals in viewspace from viewspace position please tell me.

Isn’t a 2D projection back to 3D always followed by losses ?

regards djmj