Stencil Shaders not working on Android device, Image sprite missing

Recently after exporting to Android, the shaders that used to work on Image components stopped working. Everything looks perfectly fine in the Editor but when tested on an Android device, all images with stencil shaders would disappear. One time, it managed to work like before on a Xiaomi Redmi note 4 but not on an Oppo Reno, both phones did not show any error on Android Monitor, no compile error either. Feels a lot like a bug.

I tried deleting the shader cache in the project library folder, re-importing all the assets, reinstalled Unity, used OpenGLES2 only on Player Settings. Nothing works.

Any ideas?

My shaders:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Particles/Multiply (Double)" {
Properties {
    _MainTex ("Particle Texture", 2D) = "white" {}
    _InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
  
             // required for UI.Mask
         _StencilComp ("Stencil Comparison", Float) = 8
         _Stencil ("Stencil ID", Float) = 0
         _StencilOp ("Stencil Operation", Float) = 0
         _StencilWriteMask ("Stencil Write Mask", Float) = 255
         _StencilReadMask ("Stencil Read Mask", Float) = 255
         _ColorMask ("Color Mask", Float) = 15
}

Category {
    Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
    Blend DstColor SrcColor
    ColorMask RGB
    Cull Off Lighting Off ZWrite Off
  
    SubShader {
  
             // required for UI.Mask
         Stencil
         {
             Ref [_Stencil]
             Comp [_StencilComp]
             Pass [_StencilOp]
             ReadMask [_StencilReadMask]
             WriteMask [_StencilWriteMask]
         }
       
        Pass {
      
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_particles
            #pragma multi_compile_fog
            
            #include "UnityCG.cginc"
            #pragma multi_compile_fwdbase
            #pragma target 3.0
           

            sampler2D _MainTex;
            fixed4 _TintColor;
          
            struct appdata_t {
                float4 vertex : POSITION;
                fixed4 color : COLOR;
                float2 texcoord : TEXCOORD0;
            };

            struct v2f {
                float4 vertex : SV_POSITION;
                fixed4 color : COLOR;
                float2 texcoord : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                #ifdef SOFTPARTICLES_ON
                float4 projPos : TEXCOORD2;
                #endif
            };
          
            float4 _MainTex_ST;

            v2f vert (appdata_t v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                #ifdef SOFTPARTICLES_ON
                o.projPos = ComputeScreenPos (o.vertex);
                COMPUTE_EYEDEPTH(o.projPos.z);
                #endif
                o.color = v.color;
                o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            sampler2D_float _CameraDepthTexture;
            float _InvFade;
          
            fixed4 frag (v2f i) : SV_Target
            {
                #ifdef SOFTPARTICLES_ON
                float sceneZ = LinearEyeDepth (SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)));
                float partZ = i.projPos.z;
                float fade = saturate (_InvFade * (sceneZ-partZ * 2));
                i.color.a *= fade;
                #endif
              
                fixed4 col;
                fixed4 tex = tex2D(_MainTex, i.texcoord);
                col.rgb = tex.rgb * i.color.rgb * 3;
                col.a = i.color.a * tex.a * 3;
                col = lerp(fixed4(0.5f,0.5f,0.5f,0.5f), col, col.a);
                UNITY_APPLY_FOG_COLOR(i.fogCoord, col, fixed4(0.5,0.5,0.5,0.5)); // fog towards gray due to our blend mode
                return col;
            }
            ENDCG
        }
    }
}
}
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Particles/AdditiveImage"
{
    Properties
    {
        _TintColor("Tint Color", Color) = (0.5, 0.5, 0.5, 0.5)
        _MainTex("Particle Texture", 2D) = "white" {}
      

    //Copied from MultiplyDouble
        _InvFade("Soft Particles Factor", Range(0.01,3.0)) = 1.0

        // required for UI.Mask
        _StencilComp("Stencil Comparison", Float) = 8
        _Stencil("Stencil ID", Float) = 0
        _StencilOp("Stencil Operation", Float) = 0
        _StencilWriteMask("Stencil Write Mask", Float) = 255
        _StencilReadMask("Stencil Read Mask", Float) = 255
        _ColorMask("Color Mask", Float) = 15
    }

      

        CGINCLUDE

#include "UnityCG.cginc"

        sampler2D _MainTex;
    float4 _MainTex_ST;
    fixed4 _TintColor;


    struct appdata_t
    {
        float4 position : POSITION;
        float4 texcoord : TEXCOORD0;
        fixed4 color : COLOR;
    };

    struct v2f
    {
        float4 position : SV_POSITION;
        float2 texcoord : TEXCOORD0;
        fixed4 color : COLOR;
        UNITY_FOG_COORDS(1)
    };

    v2f vert(appdata_t v)
    {
        v2f o;
        o.position = UnityObjectToClipPos(v.position);
        o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
        o.color = v.color;
        UNITY_TRANSFER_FOG(o, o.vertex);
        return o;
    }

    fixed4 frag(v2f i) : SV_Target
    {
        fixed4 col = 2.0f * i.color * _TintColor * tex2D(_MainTex, i.texcoord);
        UNITY_APPLY_FOG_COLOR(i.fogCoord, col, (fixed4)0);
        return col;
    }

        ENDCG

        SubShader
    {
        Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }

            Blend SrcAlpha One
            Cull Off Lighting Off ZWrite Off Fog{ Mode Off }

            // required for UI.Mask
            Stencil
        {
            Ref[_Stencil]
            Comp[_StencilComp]
            Pass[_StencilOp]
            ReadMask[_StencilReadMask]
            WriteMask[_StencilWriteMask]
        }


            Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_particles
            #pragma multi_compile_fog
            ENDCG
        }
    }
}

Solved, the problem might be caused by Unity not detecting the #endif tags.

Shaders with pragma target 3.0 are not guaranteed to work with GLES2.0.

Hmm… I have been using these shaders for the game since 2018. The error is only happening now in my latest build, if I install the older apks to the phones, the error does not occur.

I solved the problem by removing certain lines in my shader.

The problem itself is very strange given that I have not modified the shaders lately, I suspect the culprit to be “if/endif” statements, which is a Unity bug that happened to me before.

Example:

//In the past, I wrote some codes within UnityEditor tag...
//...and when released on Android, somehow Unity ignored the #endif tag ...
//...which caused the rest of the code after #if UNITY_EDITOR to be removed.

#if UNITY_EDITOR
//Do something
#endif

However, that is my guess, It would be great if anyone could identify the real issue. Please refer to the working shaders below:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Particles/MultiplyTest2"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)
     
        _StencilComp ("Stencil Comparison", Float) = 8
        _Stencil ("Stencil ID", Float) = 0
        _StencilOp ("Stencil Operation", Float) = 0
        _StencilWriteMask ("Stencil Write Mask", Float) = 255
        _StencilReadMask ("Stencil Read Mask", Float) = 255
 
        _ColorMask ("Color Mask", Float) = 15
    }

 

    SubShader
    {
        Tags
        {
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }

 
        // required for UI.Mask
        Stencil
        {
            Ref [_Stencil]
            Comp [_StencilComp]
            Pass [_StencilOp]
            ReadMask [_StencilReadMask]
            WriteMask [_StencilWriteMask]
        }

        Cull Off
        Lighting Off
        ZWrite Off
        ZTest [unity_GUIZTestMode]
        Fog { Mode Off }

        Blend DstColor SrcColor // Blend SrcAlpha OneMinusSrcAlpha
   
        ColorMask [_ColorMask]
    
        Pass
        {
  
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
        
            #include "UnityCG.cginc"
        
            sampler2D _MainTex;
            //fixed4 _TintColor;
      
            struct appdata_t {
                float4 vertex : POSITION;
                fixed4 color : COLOR;
                float2 texcoord : TEXCOORD0;
            };

            struct v2f {
                float4 vertex : SV_POSITION;
                fixed4 color : COLOR;
                float2 texcoord : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                //#ifdef SOFTPARTICLES_ON
                //float4 projPos : TEXCOORD2;
                //#endif
            };
      
            float4 _MainTex_ST;

            v2f vert (appdata_t v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                //#ifdef SOFTPARTICLES_ON
                //o.projPos = ComputeScreenPos (o.vertex);
                //COMPUTE_EYEDEPTH(o.projPos.z);
                //#endif
                o.color = v.color;
                o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            //sampler2D _CameraDepthTexture;
            //float _InvFade;
      
            fixed4 frag (v2f i) : SV_Target
            {
                //#ifdef SOFTPARTICLES_ON
                //float sceneZ = LinearEyeDepth (SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)));
                //float partZ = i.projPos.z;
                //float fade = saturate (_InvFade * (sceneZ-partZ * 2));
                //i.color.a *= fade;
                //#endif
          
                fixed4 col;
                fixed4 tex = tex2D(_MainTex, i.texcoord);
                col.rgb = tex.rgb * i.color.rgb * 3;
                col.a = i.color.a * tex.a * 3;
                col = lerp(fixed4(0.5f,0.5f,0.5f,0.5f), col, col.a);
                UNITY_APPLY_FOG_COLOR(i.fogCoord, col, fixed4(0.5,0.5,0.5,0.5)); // fog towards gray due to our blend mode
                return col;
            }

            ENDCG
        }
    }
}
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Particles/AdditiveImageTest"
{
    Properties
    {
         [PerRendererData] _MainTex("Particle Texture", 2D) = "white" {}
        _Color("Tint", Color) = (0.5, 0.5, 0.5, 0.5)
         //_TintColor("Tint Color", Color) = (0.5, 0.5, 0.5, 0.5)
   
        //Copied from MultiplyDouble
        //_InvFade("Soft Particles Factor", Range(0.01,3.0)) = 1.0

        // required for UI.Mask
        _StencilComp("Stencil Comparison", Float) = 8
        _Stencil("Stencil ID", Float) = 0
        _StencilOp("Stencil Operation", Float) = 0
        _StencilWriteMask("Stencil Write Mask", Float) = 255
        _StencilReadMask("Stencil Read Mask", Float) = 255
  
        _ColorMask("Color Mask", Float) = 15
    }

    SubShader
    {
        Tags
        {
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }

        // required for UI.Mask
        Stencil
        {
            Ref[_Stencil]
            Comp[_StencilComp]
            Pass[_StencilOp]
            ReadMask[_StencilReadMask]
            WriteMask[_StencilWriteMask]
        }
  
        Cull Off
        Lighting Off
        ZWrite Off
        ZTest [unity_GUIZTestMode]
        Fog{ Mode Off }
  
        Blend SrcAlpha One
  
        ColorMask [_ColorMask]
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            //#pragma multi_compile_particles
            //#pragma multi_compile_fog
       
            #include "UnityCG.cginc"

            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed4 _Color;
 
            struct appdata_t
            {
                float4 position : POSITION;
                fixed4 color : COLOR;
                float4 texcoord : TEXCOORD0;
            };

            struct v2f
            {
                float4 position : SV_POSITION;
                float2 texcoord : TEXCOORD0;
                fixed4 color : COLOR;
                UNITY_FOG_COORDS(1)
            };
       
            v2f vert(appdata_t v)
            {
                v2f o;
                o.position = UnityObjectToClipPos(v.position);
                o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
          
                o.color = v.color;
                UNITY_TRANSFER_FOG(o, o.vertex);
                return o;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                fixed4 col = 1.0f * i.color * _Color * tex2D(_MainTex, i.texcoord);
                UNITY_APPLY_FOG_COLOR(i.fogCoord, col, (fixed4)0);
                return col;
            }

            ENDCG
        }
    }
}

Oh, yeah, I’ve had that too, I think. Where changing the order of some lines or doing some misc changes fixed some issues I had when it shouldn’t change anything. Not sure what the issue is exactly.

Which Unity version do you use?
It’s very unlikely for the problem to be in the preprocessor, though.

2021.2 / .3 now. It has been a few months since I first noticed this.

I’d love to see a bug report with a repro for this :slight_smile:

I will make a bug report if I stumble upon it naturally again, but for the time being I’m not willing to dig into the shaders unless I see a problem in builds.

Thank you :slight_smile: