# OpenGL Another Position From Depth Thread

This topic is 3024 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hey everyone,

So I am trying to reconstruct a pixel's position in 3D space from its depth in GLSL, OpenGL and C++.

I was hoping I could run my code by you guys and see if you can spot the mistake.

I have been following the tutorials by MJP and the frustum one from Lighthouse3D, as well as the original posts MJP was responding to.

To give you an idea of what I'm after, here is the output using forward rendering.

And my result using the deferred method.

I think my problem might be the spaces I am working in, ie. View or World etc. I'm pretty average with these and have most likely made some errors I can't track down.

Frustum Corner Calculations:
        float fov = 45.0f;	float nearDist = 0.1f;        float farDist = 100.0f;        // .....	// Assuming projection is set as follows	gluPerspective(fov,(float)width/(float)height, nearDist, farDist);        // .....        // Camera is positioned using        // glTranslatef(0.0f, 0.0f, -45.0f);	float Hfar = 2 * tan(Rad(45.0f)/2.0f) * farDist;	float Wfar = Hfar * ((float)width / (float)height);	vec3  p     = vec3(0.0f, 0.0f,  45.0f);	vec3  dir   = vec3(0.0f, 0.0f,  -1.0f);	vec3  up    = vec3(0.0f, 1.0f,   0.0f);	vec3  right = vec3(1.0f, 0.0f,   0.0f);	vec3  fc    = p + dir * farDist ;			vec3  ftl = fc + (up * Hfar/2.0f) - (right * Wfar/2.0f);	vec3  ftr = fc + (up * Hfar/2.0f) + (right * Wfar/2.0f);	vec3  fbl = fc - (up * Hfar/2.0f) - (right * Wfar/2.0f);	vec3  fbr = fc - (up * Hfar/2.0f) + (right * Wfar/2.0f);

Geometry Pass
VERTEX SHADER:varying vec3 N;varying vec4 V;void main(){	N = gl_Normal;	V = gl_Vertex;	// View independent. Is this world space? 	gl_TexCoord[0] = gl_MultiTexCoord0;	gl_Position    = ftransform();}FRAGMENT SHADER:uniform sampler2D diff;uniform sampler2D norm;uniform sampler2D spec;uniform float farDist;varying vec3  N;varying vec4  V;void main(){		vec4 d = texture2D(diff, gl_TexCoord[0].st);	vec4 n = texture2D(norm, gl_TexCoord[0].st);	vec4 s = texture2D(spec, gl_TexCoord[0].st);	n = normalize(n);	gl_FragData[0] = d;		// Diffuse	gl_FragData[1] = n;		// Normal		gl_FragData[2] = s;		// Specular	//Linear normalised depth	gl_FragData[3] = vec4(-V.z / farDist, 0.0, 0.0, 1.0);}

Reconstruction Pass
VERTEX SHADER:varying   vec4 v;varying   vec3 viewDir;attribute vec3 corner;void main(){	viewDir.xyz = corner.xyz;	v = gl_Vertex;		gl_TexCoord[0] = gl_MultiTexCoord0;	gl_Position    = ftransform();}FRAGMENT SHADER:uniform sampler2D diff;uniform sampler2D norm;uniform sampler2D spec;uniform sampler2D depth;varying vec4 v;varying vec3 viewDir;void main(){	float z  = texture2D(depth, gl_TexCoord[0].st).r;	// normalisedDepth	// pos = frustumRay * normalisedDepth        // need this to be identical to gl_Vertex in geometry pass	vec4 pos = vec4(viewDir.xyz * z, 1.0);			...// Lighting Calculations}

Thanks alot

[Edited by - Haptic on August 26, 2010 10:30:54 PM]

##### Share on other sites
Ok, so my frustum corners are not in view-space.

Because it's view space, am I right in saying it will never change? It will always be a plane with z = -farDist?

So ignoring the 45.0f z-translation, my frustum calculations become
        float Hfar = 2 * tan(Rad(45.0f)/2.0f) * farDist;	float Wfar = Hfar * ((float)width / (float)height);	vec3  p     = vec3(0.0f, 0.0f,  0.0f);	vec3  dir   = vec3(0.0f, 0.0f,  -1.0f);	vec3  up    = vec3(0.0f, 1.0f,   0.0f);	vec3  right = vec3(1.0f, 0.0f,   0.0f);	vec3  fc    = p + dir * farDist ;			vec3  ftl = fc + (up * Hfar/2.0f) - (right * Wfar/2.0f);	vec3  ftr = fc + (up * Hfar/2.0f) + (right * Wfar/2.0f);	vec3  fbl = fc - (up * Hfar/2.0f) - (right * Wfar/2.0f);	vec3  fbr = fc - (up * Hfar/2.0f) + (right * Wfar/2.0f);

Also, my depth was not in view-space. I think it is now..?
varying vec3 N;varying vec4 V;void main(){	N = gl_Normal;	V = gl_ModelViewMatrix * gl_Vertex;    // multiply by modelview = View space?	gl_TexCoord[0] = gl_MultiTexCoord0;	gl_Position    = ftransform();}

This doesn't change anything much. Fiddling with the lights z-pos, the best picture I can get is

##### Share on other sites
I've found the main mistake, for those interested.

The reason half of the picture is black while the other is lit is because I was normalising the normal map in the geometry-pass shader. No idea why I did that, but anyway, the output is now looking almost exactly like the desired output in the first post.

Oddly, there's a few parameters that have to be tweaked to get it exactly the same, but I'm far less concerned about that.

##### Share on other sites
Haptic, where do you add the camera position to the ray? Your reconstruction should be: pos= cameraPos + direction*z;

##### Share on other sites

I fixed a couple of errors including adding the camera position and it now works perfectly!
Thanks for the tip.

##### Share on other sites
I still have one last problem!

When I rotate the plane that is being lit, it gets all blocky around the center of the light.

Could this be some kind of accuracy issue with my depth values or something? Any ideas?

Thanks again

##### Share on other sites
Problem solved.

It was indeed a precision error. I now create my textures using the GL_RGBA32F_ARB format instead of GL_RGBA.

Unfortunately it has halved the framerate, but I guess I'll have to live with that.

Edit: GL_RGBA16F_ARB also works. I assumed they were already 16 bit but they must have been 8. Anyway, it's running a fair bit faster now.

[Edited by - Haptic on August 31, 2010 9:05:28 PM]

1. 1
2. 2
3. 3
Rutin
15
4. 4
khawk
13
5. 5
frob
12

• 9
• 9
• 11
• 11
• 23
• ### Forum Statistics

• Total Topics
633669
• Total Posts
3013258
×