Another Position From Depth Thread

Started by
5 comments, last by Haptic 13 years, 7 months ago
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.
Photobucket

And my result using the deferred method.
Photobucket

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}


If you need any more info let me know.

Thanks alot

[Edited by - Haptic on August 26, 2010 10:30:54 PM]
- Haptic
Advertisement
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
Photobucket
- Haptic
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.
- Haptic
Haptic, where do you add the camera position to the ray? Your reconstruction should be: pos= cameraPos + direction*z;
Thanks for the reply jcabeleira.

I fixed a couple of errors including adding the camera position and it now works perfectly!
Thanks for the tip.
- Haptic
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.

Photobucket

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

Thanks again
- Haptic
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]
- Haptic

This topic is closed to new replies.

Advertisement