Search Unity

Question Precise distance reading from Depth Texture

Discussion in 'Shaders' started by ScetticoBlu, Jan 31, 2023.

  1. ScetticoBlu

    ScetticoBlu

    Joined:
    Nov 26, 2020
    Posts:
    21
    Hi guys, I know it's a well discussed topic but I still miss something. My goal it's easy:
    Draw a Render Texture with depth informations of the scene, as precise as possible.
    I'll use this texture to simulate a LiDAR raycast without using physics raycast, but that's not the point since I'm having troubles in the first step, getting precise reading from the render texture.

    I'm in Unity 2022 with URP. Here my setup.
    A MainCamera used just for rendering the scene, with default high fidelity renderer.
    A Camera (child of MainCamera) with Near Plane = 0.1, Far Plane = 100. This camera uses a custom renderer where a feature with an override material is applied. Also, this camera renders into my Render Texture target.
    The override material is a simple Shader Graph where a Scene Depth (Linear01) node is plugged to the color output.

    To test this setup, I placed a cube in front on the Camera so that the central pixel of the Render Texture always contains the center of the front front face of the cube. Then, I use a script to print the distance read from Render Texture:
    Code (CSharp):
    1.   private void Update()
    2.     {
    3.        Texture2D t = new Texture2D(m_RenderTexture.width,m_RenderTexture.height,TextureFormat.RGBAFloat, false);
    4.         RenderTexture.active = m_RenderTexture;
    5.         t.ReadPixels(new Rect(0, 0, m_RenderTexture.width, m_RenderTexture.height), 0, 0);
    6.         var colors = t.GetPixels(m_RenderTexture.width / 2, m_RenderTexture.height / 2, 1, 1);
    7.         DISTANCE = colors[0].r * (m_FarPlane - m_NearPlane) + m_NearPlane;
    8.         print(DISTANCE);
    9. }

    The distance doesn't seem correct (look the gif). It has this snappy behaviour. What am I missing?
    Something wrong with the red value-distance conversion (line 7)?
    If I place the cube at (FarPlane - NearPlane)/2 + 0.5 (cube size), the pixel value from the depth texture is not precisely 0.5 but something close (0.498). The error can be up to 0.20 units from the actual cube position, is way too high than I though, is it a limit of this approach?
    Thank you!
     

    Attached Files:

  2. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,924
    There's something definitely wrong: precision should be much, much higher. Keep in mind that the depth buffer is used during rendering, it can't afford to have huge precision issues.

    Your Texture2D is RGBAFloat, but what's your RenderTexture format?
     
  3. ScetticoBlu

    ScetticoBlu

    Joined:
    Nov 26, 2020
    Posts:
    21
    @arkano22 ty for the answer, indeed it seems correlated to the RenderTexture format.
    I used these settings.
    upload_2023-2-1_9-44-52.png
    Changing the color format to something like R32_SFLOAT is better, but still there's an error 0.1 units:
    upload_2023-2-1_9-50-12.png
    The error seems to converge to 0 as the distance increases, at least it doesn't snap but it's continuous.
    Different formats have different errors, but I can't find which one is better. Probably there's still something going on..

    EDIT:
    Ok I used the term DISTANCE improperly in the script. I mean, If i want the distance from the camera I have to subtract also the NeaPlane value. It ended up being much more precise now.
    As the distance increase also the error increase but i think that's normal, right? For example, at 80 units it mesures 79.91.
     
    Last edited: Feb 1, 2023
  4. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,924
    You mention your shader is getting the linear depth and then writing it into the RenderTexture's color. Your RenderTexture color format is R8G8B8A8_UNORM, that's only 8 bits per color channel so your depth value is getting quantized to just 256 possible values (and wasting 24 bits per pixel on all other 3 unused channels).

    Try using R32_SFloat for the RenderTexture's color format (not the depth/stencil format!), that should solve the problem.
     
    ScetticoBlu likes this.