Search Unity

Bug Faulty Property Value

Discussion in 'Shaders' started by MediumSolid, Sep 25, 2022.

  1. MediumSolid

    MediumSolid

    Joined:
    Apr 24, 2016
    Posts:
    45
    Hi everyone, I'm writing a really simple shader that is supposed to blend colors between each gradient segment on a cylinder including the start and the end segment, in other words the gradient should be seamless. However, despite that, there seams to be a visible seem on the cylinder when certain int values are typed into _Count property field, such as 30, in other words the blending at start and end UV points breaks for some reason. The strange thing is that if you substitute the property field with a local variable or an r-value the problem disappears and the shader displays the results as expected. I need to point out that cylinder's base UV's overlay over the whole UV map.
    Is this Unity's internal issue or am I doing something wrong?

    Application: Unity 2021.3.9f1
    OS : Windows 10
    GPU: AMD Radeon R9-270x
    CPU: AMD FX8300


    Cylinder FBX:

    Code (CSharp):
    1.  
    2. Shader "CgProgramming/Custom/Wraper"
    3. {
    4.     Properties
    5.     {
    6.         _MainTex("Main Tex", 2D) = "white"
    7.         _Count("Count", Integer) = 1
    8.     }
    9.     SubShader
    10.     {
    11.         Tags { "RenderType"="Opaque" }
    12.         LOD 100
    13.  
    14.         Pass
    15.         {
    16.             Cull Off
    17.             CGPROGRAM
    18.             #pragma vertex vert
    19.             #pragma fragment frag
    20.  
    21.             #include "UnityCG.cginc"
    22.  
    23.             sampler2D _MainTex;
    24.             float4 _MainTex_ST;
    25.             uniform half _Count;
    26.  
    27.             struct appdata
    28.             {
    29.                 float4 vertex : POSITION;
    30.                 float2 uv : TEXCOORD0;
    31.             };
    32.  
    33.             struct v2f
    34.             {
    35.                 float2 uv : TEXCOORD0;
    36.                 float4 vertex : SV_POSITION;
    37.             };
    38.  
    39.  
    40.             v2f vert (appdata v)
    41.             {
    42.                 v2f o;
    43.                 o.vertex = UnityObjectToClipPos(v.vertex);
    44.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    45.  
    46.                 return o;
    47.             }
    48.  
    49.             fixed4 frag (v2f i) : SV_Target
    50.             {
    51.                 int n = _Count; // doesn't work properly with some values (e.g. 30)
    52.                 // int n = 30; // works fine with any value
    53.                 float x_i = floor(i.uv.x*n);
    54.                 float x_f = frac(i.uv.x*n);
    55.                 float cell1 = x_i/n;
    56.                 float cell2 = fmod((x_i+1.0), n)/n;
    57.                 float val = lerp(cell1, cell2, x_f*x_f*(3.0-2.0*x_f));
    58.  
    59.                 return fixed4(val.xxx, 1.0);
    60.             }
    61.             ENDCG
    62.         }
    63.     }
    64. }
    65.  
     

    Attached Files:

    Last edited: Sep 26, 2022
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    Have you tried:
    int n = _Count + 0.5;
     
  3. MediumSolid

    MediumSolid

    Joined:
    Apr 24, 2016
    Posts:
    45
    I have, it doesn't work. So far this issue really seems to be more like an internal bug than a feature to me.
     
    Last edited: Sep 26, 2022
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    Tried with 2021.3.0f1 on an Nvidia RTX 3080 and I don't see any issues, so the bug might be caused by AMD rather than Unity?

    Here's a version of the shader that'll print the number the shader is getting on top of the gradient:
    Code (csharp):
    1. Shader "MediumSolid/Custom/Wraper"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex("Main Tex", 2D) = "white"
    6.         _Count("Count", Integer) = 1
    7.     }
    8.     SubShader
    9.     {
    10.         Tags { "RenderType"="Opaque" }
    11.         LOD 100
    12.  
    13.         Pass
    14.         {
    15.             Cull Off
    16.             CGPROGRAM
    17.             #pragma vertex vert
    18.             #pragma fragment frag
    19.  
    20.             #include "UnityCG.cginc"
    21.  
    22.             sampler2D _MainTex;
    23.             float4 _MainTex_ST;
    24.             uniform half _Count;
    25.  
    26.             struct appdata
    27.             {
    28.                 float4 vertex : POSITION;
    29.                 float2 uv : TEXCOORD0;
    30.             };
    31.  
    32.             struct v2f
    33.             {
    34.                 float2 uv : TEXCOORD0;
    35.                 float4 vertex : SV_POSITION;
    36.             };
    37.  
    38.  
    39.             v2f vert (appdata v)
    40.             {
    41.                 v2f o;
    42.                 o.vertex = UnityObjectToClipPos(v.vertex);
    43.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    44.  
    45.                 return o;
    46.             }
    47.  
    48.             // digit rendering from https://www.shadertoy.com/view/4sBSWW
    49.             float DigitBin( const int x )
    50.             {
    51.                 return x==0?480599.0:x==1?139810.0:x==2?476951.0:x==3?476999.0:x==4?350020.0:x==5?464711.0:x==6?464727.0:x==7?476228.0:x==8?481111.0:x==9?481095.0:0.0;
    52.             }
    53.  
    54.             float PrintValue( float2 vStringCoords, float fValue, float fMaxDigits, float fDecimalPlaces )
    55.             {      
    56.                 if ((vStringCoords.y < 0.0) || (vStringCoords.y >= 1.0)) return 0.0;
    57.                
    58.                 bool bNeg = ( fValue < 0.0 );
    59.                 fValue = abs(fValue);
    60.                
    61.                 float fLog10Value = log2(abs(fValue)) / log2(10.0);
    62.                 float fBiggestIndex = max(floor(fLog10Value), 0.0);
    63.                 float fDigitIndex = fMaxDigits - floor(vStringCoords.x);
    64.                 float fCharBin = 0.0;
    65.                 if(fDigitIndex > (-fDecimalPlaces - 1.01)) {
    66.                     if(fDigitIndex > fBiggestIndex) {
    67.                         if((bNeg) && (fDigitIndex < (fBiggestIndex+1.5))) fCharBin = 1792.0;
    68.                     } else {      
    69.                         if(fDigitIndex == -1.0) {
    70.                             if(fDecimalPlaces > 0.0) fCharBin = 2.0;
    71.                         } else {
    72.                             float fReducedRangeValue = fValue;
    73.                             if(fDigitIndex < 0.0) { fReducedRangeValue = frac( fValue ); fDigitIndex += 1.0; }
    74.                             float fDigitValue = (abs(fReducedRangeValue / (pow(10.0, fDigitIndex))));
    75.                             fCharBin = DigitBin(int(floor(fmod(fDigitValue, 10.0))));
    76.                         }
    77.                     }
    78.                 }
    79.                 return floor(fmod((fCharBin / pow(2.0, floor(frac(vStringCoords.x) * 4.0) + (floor(vStringCoords.y * 5.0) * 4.0))), 2.0));
    80.             }
    81.              
    82.             fixed4 frag (v2f i) : SV_Target
    83.             {
    84.                 int n = _Count; // doesn't work properly with some values (e.g. 30)
    85.                 // int n = 30; // works fine with any value
    86.                 float x_i = floor(i.uv.x*n);
    87.                 float x_f = frac(i.uv.x*n);
    88.                 float cell1 = x_i/n;
    89.                 float cell2 = fmod((x_i+1.0), n)/n;
    90.                 float val = lerp(cell1, cell2, x_f*x_f*(3.0-2.0*x_f));
    91.  
    92.                 float num = PrintValue(i.uv * float2(15.0, 5.0) + float2(8.0,-2.0), _Count, 10, 10);
    93.                 val = lerp(val, 0.0, num);
    94.  
    95.                 return fixed4(val.xxx, 1.0);
    96.             }
    97.             ENDCG
    98.         }
    99.     }
    100. }
    upload_2022-9-26_10-39-22.png
     
    MediumSolid likes this.
  5. MediumSolid

    MediumSolid

    Joined:
    Apr 24, 2016
    Posts:
    45
    Thank you for going out of your way to help me and point out where the problem most likely is.
    I consider this thread solved.

    UPDATE:
    I just tried the code and it spits out the following numbers:

    Input_____Output

    14 -------> 13
    23 -------> 22
    28 -------> 27
    33 -------> 32
    38 -------> 37
    41 -------> 40
    46 -------> 45

    51 -------> 50
     
    Last edited: Sep 26, 2022
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    I'd try changing this line:
    uniform half _Count;

    to:
    int _Count;
    or
    float _Count;


    (Note
    uniform
    isn't needed as any variable defined outside of a function is by default a uniform.)
     
    MediumSolid likes this.
  7. MediumSolid

    MediumSolid

    Joined:
    Apr 24, 2016
    Posts:
    45
    I've implemented the changes you've suggested and so far no dice. But thank you for the help once more, much appreciated.
     
  8. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    I would report this as a bug using the in-editor reporting tool. If there is an issue with specific hardware / drivers as I suspect is the case, this is something they'll need to handle.

    Until then I might suggest changing:
    _Count("Count", Integer) = 1

    to
    _Count("Count", Float) = 1

    and use
    float _Count;
    for the uniform and
    int n = _Count + 0.5;
    in the function.
     
  9. MediumSolid

    MediumSolid

    Joined:
    Apr 24, 2016
    Posts:
    45
    It was already set up like that and unfortunately it didn't change anything.