Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Simulating Kinect/Primesense depth view -- how do I map camera distance values?

Discussion in 'Shaders' started by ikelaiah, Aug 22, 2013.

  1. ikelaiah

    ikelaiah

    Joined:
    Apr 15, 2013
    Posts:
    154
    I'd like to simulate kinect/primesense depth camera view. I follow a simple code given in the documentation as follows to produce a reasonably good looking depth when combined with camera.

    Shader code:
    Code (csharp):
    1. Shader "Render Depth" {
    2. SubShader {
    3.     Tags { "RenderType"="Opaque" }
    4.     Pass {
    5.         Fog { Mode Off }
    6. CGPROGRAM
    7. #pragma vertex vert
    8. #pragma fragment frag
    9. #include "UnityCG.cginc"
    10.  
    11. struct v2f {
    12.     float4 pos : SV_POSITION;
    13.     float2 depth : TEXCOORD0;
    14. };
    15.  
    16. v2f vert (appdata_base v) {
    17.     v2f o;
    18.     o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
    19.     UNITY_TRANSFER_DEPTH(o.depth);
    20.     return o;
    21. }
    22.  
    23. half4 frag(v2f i) : COLOR {
    24.     UNITY_OUTPUT_DEPTH(i.depth);
    25. }
    26. ENDCG
    27.     }
    28. }
    29. }
    I used the image effect camera script as supplied by JoeyK.

    I perceived that the closer to the camera you get black and further white. How do I reverse this effect? I
    d like to have object in the distance to appear black, and closer as white.

    Thanks for suggestions.
     
    Last edited: Aug 22, 2013
  2. ikelaiah

    ikelaiah

    Joined:
    Apr 15, 2013
    Posts:
    154
    Never mind. Solved. Hint: Get the depth values of each pixel and manipulate the value with simple arithmetic to get the effect that you want in frag.
     
  3. Dolkar

    Dolkar

    Joined:
    Jun 8, 2013
    Posts:
    576
    Also, note that this value does not represent the accurate distance from the vertex to the camera, but rather to it's projection plane. This might cause problems depending on what you want to do with it. The actual distance to the camera would be length(mul(UNITY_MATRIX_MV, v.vertex));
     
  4. ikelaiah

    ikelaiah

    Joined:
    Apr 15, 2013
    Posts:
    154
    Hi Dolkar,

    Thanks for the correction. Greatly appreciated.

    -ikel
     
  5. Dolkar

    Dolkar

    Joined:
    Jun 8, 2013
    Posts:
    576
    Oh, one more thing... if you're using that, don't transfer the distance... transfer the view-space vertex instead and compute its length in the fragment shader or else you might get incorrect results.
     
  6. ikelaiah

    ikelaiah

    Joined:
    Apr 15, 2013
    Posts:
    154
    I lost you there "...don't transfer the distance...transfer view-space instead..." why view space?
     
  7. Dolkar

    Dolkar

    Joined:
    Jun 8, 2013
    Posts:
    576
    Well, the view-space position of the vertex is basically the vector from the camera to the vertex. Which means that if you compute the length of this vector, you get the distance to the camera. The reason why you can't transfer this distance directly is because it's not linear, so you get incorrect results when you try to linearly interpolate it. Imagine these two vectors that define a line: (-1, 0, 0) and (1, 0, 0) Now, imagine there's a pixel right in the middle of this line, so the interpolated position would be (0, 0, 0). It's length is obviously 0, which is the correct result. If you, however, computed the length directly in the vertex shader, you would get a length of 1 for both of these positions and when you interpolate between two 1s, you get a 1! Which is the incorrect result, because the pixel's position is (0, 0, 0)!
    I guess the fault is on my side... I'm not all that good at explaining stuff.