Search Unity

tex2dLod on a Texture_R8

Discussion in 'Shaders' started by GameDude31415, Jun 24, 2019.

  1. GameDude31415

    GameDude31415

    Joined:
    Feb 11, 2017
    Posts:
    9
    I am having difficulty with making a shader that renders a depth image as a heightmap. I have traced the problem to the value coming from my vertex shader that calls tex2dLod. The depth image is in floats with a maximum depth of 10m. So the depth is quantized to 8 bit by multiplying it by 255.0f/10.f. The bytes are passed into a Texture2D

    Code (CSharp):
    1.  
    2. depth = new Texture2D(depthWidth, depthHeight, TextureFormat.R8, false);
    3.  
    When the camera sends an IntPtr with the new depth it is updated with

    Code (CSharp):
    1.  
    2.       lock (lockme)
    3.             {
    4.                 fixed (byte* p = this.depthPacket)
    5.                 {
    6.                     IntPtr ptr = (IntPtr)(p + sizeof(int) * 2 + sizeof(float));
    7.                     depth.LoadRawTextureData(ptr, depthWidth * depthHeight);
    8.                 }
    9.                 depth.Apply(false);
    10.             }
    11.  
    Finally in my vertex shader, the 8 bit texture is sampled and the value is multiplied by 10.0/255.0. This results in depths that are not the right value in meters. What would help tremendously is understanding exactly what the expected range of values is for tex2Dlod on an 8 bit texture. The vertex shader calls getHeight():

    Code (shader):
    1.  
    2.             float getHeight(float textureCoordinateX, float textureCoordinateY)
    3.             {
    4.                 float4 s;
    5.                 s.x = tx;
    6.                 s.y = 1.0 - textureCoordinateY;
    7.                 s.z = 0.0f;
    8.                 s.w = 0.0f;
    9.                 float scaledDepth = tex2Dlod(_DepthTex, s);  // <-- I assumed this would be 1..255
    10.                 float depthMeters = scaledDepth * 10.0/255.0;
    11.                 return depthMeters;
    12.             }
    13.  
    When hardcoded test depth images set to a depth of 1.5 meters are used, the shader actually renders at about 2.1 meters. I put a plane in Unity and move it back and forth in the editor to measure the rendered depth.

    So hopefully someone can see what I'm doing wrong for what should be a simple situation. I think I'm being careful about not accidentally creating unwanted mip levels that would affect the returned value.

    Scott
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    Multiply by 10, not 10/255. Shaders read 8bpc texture formats as a 0.0 to 1.0 float range rather than their original integer byte per channel.

    Also when you create your Texture2D you need one more ", true" at the end to make sure it's in linear rather than the default sRGB mode, otherwise the shader gets a gamma corrected value when sampling the texture which you don't want.
     
    lclemens and GameDude31415 like this.