Search Unity

Correct way to recover world space position from depth value

Discussion in 'Shaders' started by jmargaris2, Aug 19, 2016.

  1. jmargaris2

    jmargaris2

    Joined:
    Mar 20, 2015
    Posts:
    34
    Everything I can find says that this is the correct way to do this:

    half4 pos = half4(uv.xy * 2.0 - 1.0,depth, 1);
    half4 ray = mul(_InverseViewProject, pos);
    return ray.xyz / ray.w;

    Where depth is read from the built-in depth buffer and _InverseViewProject comes from:

    Shader.SetGlobalMatrix("_InverseViewProject", (_camera.projectionMatrix * _camera.worldToCameraMatrix).inverse);


    I have been using this, and I am using SSAO pro that also uses this formula. However I recently noticed that it doesn't seem correct. I changed my image effect to draw height using the scaled world y value. What I would expect is that the floor, which is at 0, is black, then mountains that rise up gradient towards white.

    However what actually happens is that the color of the floor is dependent on the camera distance. If I zoom in and out while looking down the gradient moves - as I pull away from the floor more of the ground is black.

    If I change "depth" above to "depth*2-1" it works. However I have no idea why this works, and I'm not 100% sure that it's correct, though it does appear to be at least more correct in that the colors don't shift around as I move the camera, and the origin stays at the right place.

    I've also tried transforming the point into camera space and then again into world space as two separate steps and have the same issue - if I use "depth*2-1" things seem to work, if I just use depth things are wrong.

    So...what is the correct way to recover world position based on a screen UV and depth value?

    Please note that I can't use the trick of interpolating linear depth over a full screen quad because I'm not using a full-screen effect for what I'm doing - I have the projected position of an object in world space. (That doesn't write to the z buffer)

    Given a UV value and a z value how do I reconstruct world space? Again, doing "depth*2-1" seems to work but I have no real confidence in it - it seems like it should be wrong.
     
  2. michal_gjk

    michal_gjk

    Joined:
    Aug 13, 2016
    Posts:
    69
    Watch this carefully.



    I think you may find it interesting.
     
    a_p_u_r_o and mj321 like this.
  3. mj321

    mj321

    Joined:
    Aug 23, 2016
    Posts:
    21
    Thanks for the link, that guy made some excellent videos.
     
  4. michal_gjk

    michal_gjk

    Joined:
    Aug 13, 2016
    Posts:
    69
    He sure did.
     
  5. jmargaris2

    jmargaris2

    Joined:
    Mar 20, 2015
    Posts:
    34
    "Please note that I can't use the trick of interpolating linear depth over a full screen quad because I'm not using a full-screen effect for what I'm doing - I have the projected position of an object in world space."