Search Unity

Simple Shader does not work on Android device

Discussion in 'Shaders' started by RainbowLab, Aug 21, 2019.

  1. RainbowLab

    RainbowLab

    Joined:
    May 20, 2019
    Posts:
    5
    I wrote this simple shader that allows me to change two specific colors of a sprite:
    Code (CSharp):
    1. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    2.  
    3. Shader "Unlit/PixelColorSwap"
    4. {
    5.     Properties
    6.     {
    7.         [PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}
    8.         _Color1in("Color 1 In", Color) = (1,1,1,1)
    9.         _Color1out("Color 1 Out", Color) = (1,1,1,1)
    10.         _Color2in("Color 2 In", Color) = (1,1,1,1)
    11.         _Color2out("Color 2 Out", Color) = (1,1,1,1)
    12.     }
    13.  
    14.         SubShader
    15.         {
    16.             Tags
    17.             {
    18.                 "Queue" = "Transparent"
    19.                 "IgnoreProjector" = "True"
    20.                 "RenderType" = "Transparent"
    21.                 "PreviewType" = "Plane"
    22.                 "CanUseSpriteAtlas" = "True"
    23.             }
    24.  
    25.             Cull Off
    26.             Lighting Off
    27.             ZWrite Off
    28.             ZTest[unity_GUIZTestMode]
    29.             Blend SrcAlpha OneMinusSrcAlpha
    30.  
    31.             Pass
    32.             {
    33.             CGPROGRAM
    34.                 #pragma vertex vert
    35.                 #pragma fragment frag      
    36.  
    37.                 #include "UnityCG.cginc"
    38.                 #include "UnityUI.cginc"
    39.  
    40.                 struct appdata_t
    41.                 {
    42.                     float4 vertex   : POSITION;
    43.                     float4 color    : COLOR;
    44.                     float2 texcoord : TEXCOORD0;
    45.                 };
    46.  
    47.                 struct v2f
    48.                 {
    49.                     float4 vertex   : SV_POSITION;
    50.                     fixed4 color : COLOR;
    51.                     half2 texcoord  : TEXCOORD0;
    52.                     float4 texposition : TEXCOORD1;
    53.                 };
    54.  
    55.                 fixed4 _Color1in;
    56.                 fixed4 _Color1out;
    57.                 fixed4 _Color2in;
    58.                 fixed4 _Color2out;
    59.  
    60.                 bool _UseClipRect;
    61.                 bool _UseAlphaClip;
    62.                 float4 _ClipRect;
    63.  
    64.                 v2f vert(appdata_t IN)
    65.                 {
    66.                     v2f OUT;
    67.                     OUT.texposition = IN.vertex;
    68.                     OUT.vertex = UnityObjectToClipPos(OUT.texposition);
    69.                     OUT.texcoord = IN.texcoord;
    70.  
    71.                     #ifdef UNITY_HALF_TEXEL_OFFSET
    72.                     OUT.vertex.xy += (_ScreenParams.zw - 1.0) * float2(-1, 1);
    73.                     #endif
    74.  
    75.                     OUT.color = IN.color;
    76.  
    77.                     return OUT;
    78.                 }
    79.  
    80.                 sampler2D _MainTex;
    81.  
    82.                 fixed4 frag(v2f IN) : Color
    83.                 {
    84.                     float4 texColor = tex2D(_MainTex, IN.texcoord) * IN.color;
    85.                     texColor = all(texColor == _Color1in) ? _Color1out : texColor;
    86.                     texColor = all(texColor == _Color2in) ? _Color2out : texColor;
    87.  
    88.                     if (_UseClipRect)
    89.                         texColor *= UnityGet2DClipping(IN.texposition.xy, _ClipRect);
    90.  
    91.                     if (_UseAlphaClip)
    92.                         clip(texColor.a);
    93.  
    94.                     return texColor * IN.color;
    95.                 }
    96.             ENDCG
    97.             }
    98.         }
    99. }
    Testing it with the Unity editor works perfectly.
    Creating a .apk and testing it on a PC (unig emulator) works perfectly.
    If instead I install the .apk on an Android device (so far I have tested 4 different ones), the shader does not work at all, and the colors of the sprite are not changed.
    Can anyone tell me why? Unfortunately I haven't been able to find a solution for weeks, and I can't continue to develop my project. :(
     
  2. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    911
    Hi!
    (Not on topic)
    Code (CSharp):
    1. half2 texcoord  : TEXCOORD0;
    needs to be float2, otherwise you can have precision issues on larger textures.

    (On topic)
    When you're comparing floating-point values, you can't just use "==". You need to provide some tolerance for rounding that happens after operations, e.g.
    Code (CSharp):
    1. abs(texColor - _Color1in) < 0.005
    . See https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems, for example for a detailed explanation.
     
    RainbowLab likes this.
  3. RainbowLab

    RainbowLab

    Joined:
    May 20, 2019
    Posts:
    5
    Thank you so much!
    I made the corrections and now also seems to work on Android devices!
    Thank you!
     
    aleksandrk likes this.