Sign in to follow this  

From Z buffer to world coordinate

Recommended Posts

Giving the zbuffer filled with values from 0 to 1, I'm trying to get back the source world coordinate. What I'm doing right now is this: - IN.texSrc is 0,0 in the top left corner and 1,1 in the bottom right (a fullscreen quad). - invCamMatrix is the inverse of view*prj matrix - sampler2 is the texture filled with zvalue (R32F)
float3  screenCoord;
screenCoord.x = (IN.texSrc.x*2.0f) -1.0f;    // range from -1 to 1
screenCoord.y = 1.0f - (IN.texSrc.y*2.0f);   // range from 1 to -1
screenCoord.z = tex2D(sampler2,IN.texSrc).r; // z value 0 to 1

float4 worldCoord = mul (float4(screenCoord,1.0f),invCamMatrix); /= worldCoord.w;

I think this should work (and it seems to works...sometimes) but I believe i'm getting wrong world coordinate when the zbuffer value are close to 0 (maybe due to precision errors). I know that in the "deferred shading" way of rendering you've to get back the world position from the zbuffer just like I need to and so, I'd like hear if you have some tips to give me to improve the quality.

Share this post

Link to post
Share on other sites
If you are using a 32 bit floating point format you should have enough precision right up to the near clipping plane. Are you doing any filtering on your texture sampler? Make sure you are using point sampling (you probably are, but just checking) and not linear or aniso.

What type of values are you getting when the z values are very small?

Share this post

Link to post
Share on other sites
Mmm after a lot of investigation, I think the problem is not with the inverse transformation but with the z value.

To calculate the z value, I'm doing like this:

float3 f3WorldPos= mul (IN.pos,matW).xyz;
OUT.pos = mul (float4(f3WorldPos,1.0f),matVP);
OUT.f1Depth = OUT.pos.z/OUT.pos.w;
return OUT;

where matW is the world matrix, matVP is the View*Projection matrix.
f1Depth is the z value I'm storing in the R32F texture.

I'm not sure this is the right value to store.

Any tips ?

Share this post

Link to post
Share on other sites
Try doing the transform in one multiplication instead of two. I think setting the w coordinate to 1 after the first mul may cause trouble.

Share this post

Link to post
Share on other sites
Well, I've found a solution.
After all, there was nothing wrong with my shaders. The problem was the interpolation.

I was filling the texture with z value calculated in the vertex shader like this : z=OUT.pos.z/OUT.pos.w
The pixel shader was as simple as writing the z value from the vertex shader
OUT.col.rgba = float4(IN.z,0,0,0)

This was not working due to interploation error (I guess)

What I do now, is this:
in vertex shader:
f2Depth.xy =
in pixel shader
OUT.col.rgba = float4(IN.f2Depth.x/IN.f2Depth.y,0,0,0)

I'm calculating the z value (POS.z/POS.w) in the pixel shader (ie: for every texel) instead of calculating it in the vertex shader and let the pipeline to interploate it for me.
This is working :-)

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this