Search Unity

Getting world position from depth buffer...

Discussion in 'Image Effects' started by stu_pidd_cow, Feb 17, 2017.

  1. stu_pidd_cow

    stu_pidd_cow

    Joined:
    Aug 4, 2014
    Posts:
    233
    I'm trying to get the world position from the depth buffer for an image effect. I have actually got it working for standalone builds using the following code snippet:

    Code (CSharp):
    1.  
    2.     // for fast world space reconstruction
    3.     uniform float4x4 _FrustumCornersWS;
    4.     uniform float3 _CameraWS; // camera's world space position (ie camera's Transform.position)
    5.     uniform float4 _CameraDir; // xyz = camera forward direction, w = near plane distance
    6.    
    7.     struct v2f
    8.     {
    9.         float4 pos : SV_POSITION;
    10.         float2 uv : TEXCOORD0;
    11.         float2 uv_depth : TEXCOORD1;
    12.         float4 interpolatedRay : TEXCOORD2;
    13.     };
    14.    
    15.     v2f vert (appdata_img v)
    16.     {
    17.         v2f o;
    18.         half index = v.vertex.z;
    19.         v.vertex.z = 0.1;
    20.         o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    21.         o.uv = v.texcoord.xy;
    22.         o.uv_depth = v.texcoord.xy;
    23.        
    24.         #if UNITY_UV_STARTS_AT_TOP
    25.         if (_MainTex_TexelSize.y < 0)
    26.             o.uv.y = 1-o.uv.y;
    27.         #endif              
    28.        
    29.         o.interpolatedRay = _FrustumCornersWS[(int)index];
    30.         o.interpolatedRay.w = index;
    31.        
    32.         return o;
    33.     }
    34.    
    35.     half4 frag (v2f i) : SV_Target
    36.     {
    37.         // Reconstruct world space position and direction
    38.         float rawdpth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, -i.uv_depth);
    39.         #ifdef CAMERA_ORTHOGRAPHIC
    40.             float3 nearPlaneDist = _CameraDir.w; // from camera
    41.             float3 camDir = _CameraDir.xyz;
    42.             float3 nearPlaneOffset = camDir * nearPlaneDist; // relative to camera pos
    43.             float3 camPos = _CameraWS + nearPlaneOffset; // pretend the camera pos is at the near plane
    44.             float3 rayFar = i.interpolatedRay - nearPlaneOffset; // relative to camera near plane
    45.        
    46.             float3 rayVec = camDir * dot(rayFar, camDir); // relative to rayOrigin
    47.             float3 rayOrigin = rayFar - rayVec; // relative to camera
    48.             // apparently unity inverted the Z buffer when not using Linear01Depth: https://docs.unity3d.com/Manual/UpgradeGuide55.html
    49.             #if UNITY_VERSION >= 550
    50.                 rawdpth = 1 - rawdpth;
    51.             #endif
    52.             float3 rayCast = (rayFar - rayOrigin) * rawdpth; // just use the raw depth texture for ortho
    53.             float3 wsPos = camPos + rayOrigin + rayCast;
    54.        
    55.         #else
    56.             float3 wsDir = i.interpolatedRay * Linear01Depth(rawdpth); // for PERSPECTIVE
    57.             float3 wsPos = _CameraWS + wsDir;
    58.         #endif
    59.        
    60.         // other stuff is here...
    61.     }
    62.  
    So this appears to work fine for windows, but doesn't work for android. On android, the positions are all skewed. I don't know if my solution is best (it seems quite convoluted for orthographic).
    I have looked at the source for Unity's global fog, and it appears that it doesn't support orthographic cameras. I'm not sure where to look next.

    Has anyone got experience with reconstructing positions in image effects?

    Cheers.
     
  2. stu_pidd_cow

    stu_pidd_cow

    Joined:
    Aug 4, 2014
    Posts:
    233
    It appears that my depth buffer is black, as though it's not rendering the depth buffer at all. I have tried disabling the 32-bit depth and it didn't make a difference.

    This thread suggests that it's a bug in unity, but I'm not sure why other's aren't talking about it more since the lack of a depth buffer would seem to be a major issue in my mind. So the suggested solution is to render your own depth buffer, which sounds quite sucky.

    Has anyone else come across this?
     
  3. jamius19

    jamius19

    Joined:
    Mar 30, 2015
    Posts:
    96
    Try lowering your upper clipping distance for the camera.