Search Unity

Edge seam issue when sampling 4-in-one texture

Discussion in 'Shaders' started by aldrickbanks, Dec 19, 2019.

  1. aldrickbanks

    aldrickbanks

    Joined:
    Jul 18, 2019
    Posts:
    9
    I am using 2 4-in-one texture and 2 RGBA weight maps to realize the effect which usually needs 8 textures to save some semantics and a second draw call in Unity's default terrain engine.

    When I test it in terrain shader and in regular scene architecture shader, the basic mechanism works, but the edge of each texture shows a weird dotted seam line :
    seam.jpg
    The UV tweak codes are like this. I only show sampling the first 4-in-one texture cuz it is the same for the second one:

    Code (CSharp):
    1.         void MP_SplatmapMix(Input IN, out fixed4 mixedDiffuse)
    2.         {
    3.  
    4.         //////////////////////////////////////////////
    5.         /////////first 4-in-one texture/////
    6.         //////////////////////////////////////////////
    7.             mixedDiffuse = 0.0;
    8.             fixed4 c1 = tex2D(_MainTex, (IN.uv_MainTex  - floor(IN.uv_MainTex))/ 2.0);
    9.             float2 uvnew  = float2((IN.uv_MainTex.x  + 1.0 - floor(IN.uv_MainTex.x))/ 2.0,(IN.uv_MainTex.y  - floor(IN.uv_MainTex.y))/ 2.0);
    10.             fixed4 c2 = tex2D(_MainTex,uvnew);
    11.             uvnew = float2((IN.uv_MainTex.x  - floor(IN.uv_MainTex.x))/ 2.0,(IN.uv_MainTex.y  + 1.0 - floor(IN.uv_MainTex.y))/ 2.0);
    12.             fixed4 c3 = tex2D(_MainTex, uvnew);
    13.             fixed4 c4 = tex2D(_MainTex, (IN.uv_MainTex  + 1.0 - floor(IN.uv_MainTex))/ 2.0);
    14.  
    15.         ////////////////////////////////////////////////////////////////////////
    16.         /////////composite with a RGBA weight texture//
    17.         ////////////////////////////////////////////////////////////////////////
    18.             fixed4 alpha = tex2D(_AlphaTex1, IN.uv_AlphaTex1);
    19.             half alpha3 =  max(alpha.g - alpha.r - alpha.b,0.0);
    20.             half alpha2 = max(alpha.r - alpha.b,0.0);
    21.             half alpha4 = alpha.b;
    22.             half alpha1 = 1.0 - saturate(alpha2 + alpha3 + alpha4);
    23.             mixedDiffuse.rgb = c1.rgb * alpha1 + c2.rgb * alpha2 + c3.rgb * alpha3 + c4.rgb * alpha4;
    24.             mixedDiffuse.a = 1.0;
    25.         }
    The textures look like this:
    seam2.png

    Does anyone have an idea of why is this dotted edge line appearing?
     

    Attached Files:

  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    I just wrote a bunch about the same kind of issue here:
    https://forum.unity.com/threads/str...lines-along-quad-borders.795870/#post-5296011

    You're not directly using the
    frac()
    function in your shader, but you are still doing the same thing since this is how that function is implemented:
    float frac(float x) { return x - floor(x); }

    Look familiar?

    You'll want to use the tex2Dgrad solution I mention in the above post. You'll also want to add some gutters between the 4 textures so the UVs you're wrapping at aren't right on the edge, otherwise you'll always have some amount of bleed. And you may want to limit the mip levels allowed, either by limiting the derivatives passed to tex2Dgrad, or by using the recently added mip count limits.
     
  3. aldrickbanks

    aldrickbanks

    Joined:
    Jul 18, 2019
    Posts:
    9
    bgolus, thank you. The first two suggestions from you both work. I keep the uv 0.002 away from the border(tried 0.001, which seemed not enough to end the seam):
    Code (CSharp):
    1.         float2 copyUV = IN.uv_MainTex;
    2.         if( frac(copyUV.x ) > 0.998 && frac(copyUV.x) <= 1.0)
    3.         {copyUV.x = floor(copyUV.x) + 0.998; }
    4.  
    5.         if( frac(copyUV.y ) > 0.998 && frac(copyUV.y) <= 1.0)
    6.         {copyUV.y = floor(copyUV.y) + 0.998;}
    7.  
    8.         if( frac(copyUV.x ) >= 0.0 && frac(copyUV.x) <= 0.002)
    9.         {copyUV.x = floor(copyUV.x) + 0.002; }
    10.  
    11.         if( frac(copyUV.y ) >= 0.0 && frac(copyUV.y) <= 0.002)
    12.         {copyUV.y = floor(copyUV.y) + 0.002; }
    13.  
    14.         IN.uv_MainTex = copyUV;
    Then the UV change rate calculation:
    Code (CSharp):
    1.         float2 dx = ddx(frac(IN.uv_MainTex / uvscale));
    2.         float2 dy = ddy(frac(IN.uv_MainTex / uvscale));
    3.         float2 uvnew = (IN.uv_MainTex - floor(IN.uv_MainTex))/ 2.0;
    4.         float4 c1 = tex2Dgrad(_MainTex, uvnew, dx, dy); //choose lod based on UV's change rate
    5.         //float4 c1 = tex2D(_MainTex, uvnew);
    6.  
    Result(dark area is lightmapped,not an issue):
    8tex.jpg

    So far no problem occurs,so I haven't tried limiting mipmap level yet.

    Found in the forum for a while that you have in-depth knowledge of computer graphics,do you major in computer graphics in college:)?

    cheers
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    Nope. Was working on a degree in fine arts and dropped out before I finished. My graphics programming knowledge is self taught and from working with others who I could learn from.
     
    aldrickbanks likes this.