Search Unity

What Color Function Tex2d() Return When The Uv Coordinate Is 0 0 (empty Uv)?

Discussion in 'Shaders' started by NathanJSmith, Apr 15, 2019.

  1. NathanJSmith

    NathanJSmith

    Joined:
    May 11, 2018
    Posts:
    57
    I'm trying to calculate the color when there is no UV. I have this code (which modified from Unity's example)

    Code (CSharp):
    1. fixed4 frag(v2f i) : SV_Target
    2. {
    3.     fixed4 col;
    4.     float2 testUV;
    5.     float time = int(_Time.x * 100);
    6.  
    7.     if(time % 2 == 0)
    8.         testUV.xy = 0;
    9.     else
    10.         testUV.xy = i.uv;
    11.  
    12.     col = tex2D(_MainTex, testUV);
    13.    
    14.     return col;
    15. }
    16.  
    So when the UV coordinate is (0, 0), the funcion tex2D() return the empty UV color. My question is how can I calculate this color? I know this color is formed by 4 corners of the texture, I have tried to calculate it like this:
    Code (CSharp):
    1. Vector2Int lastIdx = new Vector2Int(
    2.             myTexture2D.width - 1,
    3.             myTexture2D.height - 1);
    4.  
    5. color = (myTexture2D.GetPixel(0, 0) +
    6.                 myTexture2D.GetPixel(lastIdx.x, 0) +
    7.                 myTexture2D.GetPixel(lastIdx.x, lastIdx.y) +
    8.                 myTexture2D.GetPixel(0, lastIdx.y) +
    9.                 Color.white) / 5.0f;
    But the color I get isn't exactly like the empty UV color. I also checked the document of tex2D() but I still can't find my answer.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    wat ...

    You're on the right track. Sampling the UV coordinate (0,0) is sampling the point at the corner of the texture, which is between all 4 corner pixels. If your texture has bilinear or trilinear filter enabled, this will be a blend of those 4 corner pixels. If it's point filtered, then it's just the bottom left pixel's color, but obviously that's not what you're going for.

    If you just want the bilinear filtered value for a specific UV coordinate, you may be able to use the built in GetPixelBilinear() function.
    https://docs.unity3d.com/ScriptReference/Texture2D.GetPixelBilinear.html
    The documentation for that function makes me worried though.
    If that's correct, then GetPixelBilinear() does not have the same behaviour as tex2D() on a bilinear texture.

    So then, you're kind of on the right path, but the value is just the 4 colors added together divided by 4. I'm not sure why the code you found was adding white and dividing by 5 (probably some color space issues).
    Code (csharp):
    1. color = (myTexture2D.GetPixel(0, 0) +
    2. myTexture2D.GetPixel(lastIdx.x, 0) +
    3. myTexture2D.GetPixel(lastIdx.x, lastIdx.y) +
    4. myTexture2D.GetPixel(0, lastIdx.y)) / 4.0f;
    If this color isn't looking correct still, then you'll likely need to do some color space correction. I can go over that if it's an issue, but I'm going to skip it for now.

    You can also look at this code for an implementation that handles arbitrary UV coordinates.
    http://wiki.unity3d.com/index.php/TextureSampler
     
    NathanJSmith likes this.
  3. NathanJSmith

    NathanJSmith

    Joined:
    May 11, 2018
    Posts:
    57
    Thank bgolus :)
    I think add white to make the color brighter, because if not add white like the code below:
    Code (CSharp):
    1.     color = (myTexture2D.GetPixel(0, 0) +
    2.     myTexture2D.GetPixel(lastIdx.x, 0) +
    3.     myTexture2D.GetPixel(lastIdx.x, lastIdx.y) +
    4.     myTexture2D.GetPixel(0, lastIdx.y)) / 4.0f;
    5.  
    Then the color is darker than the empty UV color, thus add white.
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Then there's a gamma issue. Don't arbitrarily add white, that won't fix it.

    The question I have is how & where are you using the resulting color value?
     
    NathanJSmith likes this.
  5. NathanJSmith

    NathanJSmith

    Joined:
    May 11, 2018
    Posts:
    57
    I work on a case where you can cut open the mesh, the color inside the mesh is the empty UV color, I need to get this color to add some more effect to the cut open mesh process :D