Reconstructing position from Z buffer problem

I have been making a little demo program to try out the various ways of getting the screen/view space position back from the depth buffer, but i have run into some troubles with the method specified in the Leadwerks paper on deferred rendering.

I render to a depth and position buffer FBO in the first pass, with red and black dot representing the position I am trying to reconstruct in the second pass (the first pass is shown on the small windows on the left hand side of this picture)

In this first picture I am using a position buffer to reconstruct the position and as you can see it aligns perfectly, with the blue dot on the main image covering the red dot from the first pass completely.

this is the 2nd pass fragment shader:


vec4 depth = texture2D(tex_depth, vryTexCoord.st);
	vec4 position = texture2D(tex_position, vryTexCoord.st);
	vec4 diffuse = texture2D(tex_diffuse, vryTexCoord.st);
	gl_FragColor = diffuse;	//debug colour so we can see if they align.
	vec3 vs_v_pos;	
	vs_v_pos = position.xyz;	
	
	vec3 VL = vs_light_pos - vs_v_pos;
	float d = length(VL);
	if(d < 10.0f)
		gl_FragColor = vec4(0, 0, 1.0, 1.0);

vs_light_pos is a uniform of the viewspace position of the dot from the first render.

If I replace the Z value of the position buffer in the second pass with a reconstructed z taken from the depth buffer and using the function:

float DepthToZPosition(in float depth) 
{ 
	return cameraRange.x / (cameraRange.y - depth * (cameraRange.y - cameraRange.x)) * cameraRange.y; 
}

where cameraRange contains the near and far values of the frustum used in the first rendering pass. It also works with no problems.

these are the changes:


vec3 vs_v_pos;
	vs_v_pos.xy = position.xy;	
	vs_v_pos.z = -DepthToZPosition( depth.x );	

but when i start to replace the x and y values of vs_v_pos to use the function:

vec3 vs_v_pos;
	
	vs_v_pos = vec3(	((gl_FragCoord.x/screenSize.x)-0.5) * 2.0,
						((-gl_FragCoord.y/screenSize.y)+0.5) * 2.0 / (screenSize.x/screenSize.y),
						-DepthToZPosition( depth.x ));

	vs_v_pos.x *= -vs_v_pos.z;
	vs_v_pos.y *= vs_v_pos.z;

(screenSize is passed in as 640 by 480 the final resolution i am rendering to.)

the blue dot starts to deviate slightly depending on the angle. (it does centre properly when looking straight down the z, albeit the ratio of the circle is slightly incorrect)

Can anyone tell me what I am doing wrong? or at least point me in the right direction? i’m sure DepthToZPosition is ok.

I think I know what i am doing wrong.

This original function assumes you are initially using a frustum with left and right at -1.0 and 1.0, and proportional values for top and bottom.

to adjust for this I just pass in the frustum right and top values as a vec2 frustumRange (here I am assuming that the left is just -right and bottom is just -top) and multiply at the end.

also, the divide by (screenSize.x/screenSize.y) when calculating vs_v_pos.y is nto needed


vec3 vs_v_pos;
	vs_v_pos = vec3(((gl_FragCoord.x/screenSize.x)-0.5) * 2.0,
                       ((-gl_FragCoord.y/screenSize.y)+0.5) * 2.0,
                       DepthToZPosition( depth.x ));

	vs_v_pos.x *= -vs_v_pos.z * frustumRange.x;
	vs_v_pos.y *= vs_v_pos.z * frustumRange.y;

Thanks for listening :wink: