Custom Metallic shader is broken on iPad

I wrote a metallic glitter shader and it’s working fine on most devices except Ipad 5th gen as far as I know. The gold pattern shows up as black with overlay glitter texture still in tact. I suspect that the issue comes from the metal calculation part.

Does anyone know what I might be doing wrong? Here’s my shader. Any help would be greatly appreciated! :smile:

Shader "Unlit/MetallicGlitter" {
    Properties {
        [Header(Texture properties)]
        [Space(10)]
        _Color ("Main Color", Color) = (1,1,1,1)
        _MainTex ("Base (RGB)", 2D) = "white" {}
        [HDR]_PatternColorR ("Pattern Color R", Color) = (1,1,1,1)
        [HDR]_PatternColorG ("Pattern Color G", Color) = (1,1,1,1)
        [HDR]_PatternColorB ("Pattern Color B", Color) = (1,1,1,1)
        _PatternTex ("Pattern", 2D) = "white" {}
        _Cutoff("Alpha Cutoff", Range(0.000000,1.000000)) = 0.500000
        [Header(Pattern properties)]
        [Space(10)]
        [Toggle] _IsMetal("Enable Metallic", Float) = 0
        _Shiny ("Shininess", Range(0.1,6)) = 0.0
        _Roughness ("Roughness", Range(0,2)) = 0.0
        [Header(Lighting properties)]
        [Space(10)]
        [Toggle] _RimLight("Enable Rim Light", Float) = 0
        _RimColor ("Rim Color", Color) = (1,1,1,1)
        _RimPower("Rim Power", Range(0,10)) = 2.0

        [Header(Glitter properties)]
        [Space(10)]
        [Toggle] _IsGlitter("Enable Glitter", Float) = 0
        _GlitterTex ("Glitter", 2D) = "white" {}
        _SparkPower("Spark Power", Range(-5,5)) = 2.0
        _GlitterScale("Glitter Scale", Range(0,100)) = 2.0
        [HDR]_GlitterColor ("Glitter Color", Color) = (1,1,1,1)
        _Contrast ("Contrast Strength", Float) = 1
    }

    SubShader {
        Tags { "RenderType"="TransparentCutout" "CanUseSpriteAtlas"="True"}
        LOD 43
        AlphaToMask On
        Zwrite On
        Blend SrcAlpha OneMinusSrcAlpha
        Cull Off
        ZTest On

        Pass{
            Name "HDFILL"
            Lighting Off
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma fragmentoption ARB_precision_hint_fastest
            #pragma shader_feature _ISGLITTER_ON
            #pragma shader_feature _RIMLIGHT_ON
            #pragma shader_feature _ISMETAL_ON
            #include "UnityCG.cginc"
            struct vertIn {
            float4 vertex : POSITION;
            float3 normal : NORMAL;
            float4 texcoord : TEXCOORD0;
        };

        struct v2f {
            float2 uv : TEXCOORD0;
            float3 nrml : TEXCOORD1;
            float3 pos : TEXCOORD2;
            float4 vertex : SV_POSITION;
            float3 viewDir : TEXCOORD3;
            float3 normal_world : TEXCOORD4;
            float4 worldPos : TEXCOORD5;
        };

        uniform sampler2D _MainTex, _PatternTex, _ShineTex, _GlitterTex;
        uniform float4 _Color, _PatternColorR, _PatternColorG, _PatternColorB, _RimColor, _GlitterColor;
        uniform float _Shiny, _Cutoff, _RimPower, _Roughness, _ShineSpeed, _SparkPower, _GlitterScale, _Contrast;
        uniform fixed4 _MainTex_ST, _PatternTex_ST, _ShineTex_ST, _GlitterTex_ST, _ShineRot;

        v2f vert (vertIn v)
        {
            v2f o;
            o.vertex = UnityObjectToClipPos(v.vertex);
            o.uv = v.texcoord;
            o.normal_world = normalize(mul(unity_ObjectToWorld, float4(v.normal, 0))).xyz;
            o.pos = (mul(unity_ObjectToWorld, v.vertex)).xyz;
            o.nrml = UnityObjectToClipPos(float4(v.normal, 0.0)).xyz;
            o.worldPos = mul(unity_ObjectToWorld, v.vertex);
            o.viewDir = normalize(UnityWorldSpaceViewDir(o.worldPos));
            return o;
        }

        float4 frag (v2f i) : COLOR
        {
                float4 mainTex = tex2D(_MainTex, i.uv);
                float4 maskTex = tex2D(_PatternTex, i.uv);
                clip(mainTex.w - _Cutoff);
                mainTex *= _Color;

                float4 maskBW = maskTex.r + maskTex.g + maskTex.b;
                float4 maskCol = maskTex.r * _PatternColorR;
                maskCol += maskTex.g * _PatternColorG;
                maskCol += maskTex.b * _PatternColorB;
                mainTex = lerp(mainTex, maskCol, maskBW);


                #if _ISMETAL_ON
                    half3 nrml = normalize(i.nrml);
                    half3 camDir = _WorldSpaceCameraPos.xyz - i.pos;
                    camDir = normalize(camDir);
                    camDir *= float3(1.6,1.6,0.95);
                    half rim = saturate(dot(camDir, nrml));
                    float rim2 = pow(1.25 - rim*rim + 1.5*(pow(rim*rim,_Shiny)), _Roughness);
                    float4 colorOut = rim2 * maskCol;
                    mainTex += (colorOut * maskBW);
                #endif
             
                #if _ISGLITTER_ON
                    float3 glitterTex = tex2D(_GlitterTex, i.uv * _GlitterScale).xyz-0.5;
                    glitterTex = normalize(normalize(-glitterTex)) * maskBW;
                    float glitter = pow(dot(i.viewDir, glitterTex), _SparkPower);
                    glitter = saturate(lerp(1, glitter, _Contrast));
                    fixed4 maskedGlitter = lerp(mainTex, half4(glitter, glitter, glitter, 1), maskBW);
                    maskedGlitter = saturate(maskedGlitter);
                    maskedGlitter *= _GlitterColor;
                    mainTex += (maskedGlitter * maskBW);
                #endif

                # if _RIMLIGHT_ON
                    float3 normal = i.normal_world;
                    float fresnel = dot(normal, i.viewDir);
                    fresnel = saturate(1 - fresnel) * _RimPower;
                    float3 fresnelColor = fresnel * _RimColor;
                    float4 rimLight =  float4(fresnelColor, mainTex.w);
                    mainTex += rimLight;
                #endif

                return mainTex;
        }

        ENDCG

        }
    }
}

Try changing all half calculations to float and see if it fixes the issue.

Thank you so much for you reply @aleksandrk ! I tried changing all the half calculations, but it’s not working still. Is there anything else I could try?

It may also be a problem specific to this device. You can file a bug report and see what the devs would say.

The pow calculation on minus value will output 0 on some platform and NaN on some platform.
1.25 - rimrim + 1.5(pow(rim*rim,_Shiny)) can be minus value. The result color + 0 is your supposed to look, but color + NaN = NaN is what happening on iPad, I think.