Skybox shader - iOS vs Windows mismatch

Hi!

I’m having the following issue where my shader looks correct on Windows, but totally borked on iOS:

Shader "Custom/ProceduralSky" {
    Properties {
        _StarsTexture ("Stars Texture", 2D) = "white" {}
        _StarPosition ("Star Position", Float ) = 0.45
        _StarIntensity ("Star Intensity", Float ) = 350
        _Night ("Night", Color) = (0.28, 0.466, 0.8156, 1.0)
        _GroundColor ("Ground Color", Color) = (0.051, 0.11, 1.0, 1.0)
        _GroundSmoothness ("Ground Smoothness", Range(0.01, 2)) = 0.5
    }
    SubShader {
        Tags {
            "RenderType"="Opaque"
            //"PreviewType"="Skybox"
        }
        LOD 200
        Pass {
            Name "FORWARD"
            Tags {
                "LightMode"="ForwardBase"
            }
         
         
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #define UNITY_PASS_FORWARDBASE
            #include "UnityCG.cginc"
            #pragma multi_compile_fwdbase_fullshadows

            #pragma target 2.0
            uniform fixed _StarPosition;
            uniform sampler2D _StarsTexture; uniform fixed4 _StarsTexture_ST;
            uniform fixed4 _Night;
            uniform fixed _StarIntensity;
            uniform fixed4 _GroundColor;
            uniform fixed _GroundSmoothness;
         
            struct VertexInput {
                fixed4 vertex : POSITION;
            };

            struct VertexOutput {
                fixed4 pos : SV_POSITION;
                fixed4 uv0 : TEXCOORD0;
            };

            VertexOutput vert (VertexInput v) {
                VertexOutput o;
                o.uv0 = mul(_Object2World, v.vertex);
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex );
             
                return o;
            }
         
            fixed3 frag(VertexOutput i) : COLOR {

                fixed3 normalizedRGB = normalize(i.uv0.rgb);
             
                fixed saturatedGreen = saturate(normalizedRGB.g);

                fixed2 normalizedRB = normalizedRGB.rb;
                fixed2 invertedSaturatedGreen = (normalizedRB+(normalizedRB*(1.0f - saturatedGreen)));
                fixed4 _StarsTexture_var = tex2D(_StarsTexture,TRANSFORM_TEX(invertedSaturatedGreen, _StarsTexture));

                fixed3 lerped = lerp(_Night.rgb, pow(_Night.rgb,_Night.a), (1.0f - normalizedRGB));
                fixed3 finalColor = lerp(_GroundColor.rgb,(((_StarsTexture_var.g*pow(saturatedGreen,_StarPosition))*_StarIntensity*lerped)+lerped),saturate((((0.1f*_GroundSmoothness)+normalizedRGB.g)/_GroundSmoothness)));
                return fixed3(finalColor);
            }

            ENDCG
        }
    }
}

Does anyone have a clue why iOS is not able to handle this seemingly simple shader correctly? I’m trying to run this on an iPhone 6 and iPad Air 2 building with Unity 5.3.3f1. Any help would be greatly appreciated.

Thanks!

I suspect the issue is your use of “fixed” precision numbers through out the shader. Try replacing them all with “half” just to see if that fixes it.

The three main float types, float, half, and fixed, have specific meanings:
fixed : Low precision and range, minimum range of -2 to +2, minimum precision of 1/256. Usually
half : Medium precision and range, minimum 16bit float (-65535 to +65536)
float : High precision and range, minimum 32bit float (though some very, very old hardware cheated with 24bit)

However those are all minimum requirements, and desktop GPUs just don’t bother to do fixed at all, and instead use at least half precision. In fact it’s quite likely they don’t even do half and do everything as 32bit floats!

Mobile GPUs are different, and many do actually use only the minimum required precision for the various floating point number formats. All do half, and some do real fixed precision math. This is good for power savings, which hasn’t been a big concern for desktop hence its exclusion (though some people have guessed Nvidia might be using selective 16bit precision for the last two generations as for one of the ways they use so little power). That means you using “fixed value = 350.0” on desktop works totally fine, but on mobile it gets clamped to 2!