Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Skybox shader - iOS vs Windows mismatch

Discussion in 'Shaders' started by GoRiLLa, Jan 31, 2017.

  1. GoRiLLa

    GoRiLLa

    Joined:
    Oct 8, 2013
    Posts:
    14
    Hi!

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

    sky-shader-bug.png

    Code (CSharp):
    1. Shader "Custom/ProceduralSky" {
    2.     Properties {
    3.         _StarsTexture ("Stars Texture", 2D) = "white" {}
    4.         _StarPosition ("Star Position", Float ) = 0.45
    5.         _StarIntensity ("Star Intensity", Float ) = 350
    6.         _Night ("Night", Color) = (0.28, 0.466, 0.8156, 1.0)
    7.         _GroundColor ("Ground Color", Color) = (0.051, 0.11, 1.0, 1.0)
    8.         _GroundSmoothness ("Ground Smoothness", Range(0.01, 2)) = 0.5
    9.     }
    10.     SubShader {
    11.         Tags {
    12.             "RenderType"="Opaque"
    13.             //"PreviewType"="Skybox"
    14.         }
    15.         LOD 200
    16.         Pass {
    17.             Name "FORWARD"
    18.             Tags {
    19.                 "LightMode"="ForwardBase"
    20.             }
    21.          
    22.          
    23.             CGPROGRAM
    24.             #pragma vertex vert
    25.             #pragma fragment frag
    26.             #define UNITY_PASS_FORWARDBASE
    27.             #include "UnityCG.cginc"
    28.             #pragma multi_compile_fwdbase_fullshadows
    29.  
    30.             #pragma target 2.0
    31.             uniform fixed _StarPosition;
    32.             uniform sampler2D _StarsTexture; uniform fixed4 _StarsTexture_ST;
    33.             uniform fixed4 _Night;
    34.             uniform fixed _StarIntensity;
    35.             uniform fixed4 _GroundColor;
    36.             uniform fixed _GroundSmoothness;
    37.          
    38.             struct VertexInput {
    39.                 fixed4 vertex : POSITION;
    40.             };
    41.  
    42.             struct VertexOutput {
    43.                 fixed4 pos : SV_POSITION;
    44.                 fixed4 uv0 : TEXCOORD0;
    45.             };
    46.  
    47.             VertexOutput vert (VertexInput v) {
    48.                 VertexOutput o;
    49.                 o.uv0 = mul(_Object2World, v.vertex);
    50.                 o.pos = mul(UNITY_MATRIX_MVP, v.vertex );
    51.              
    52.                 return o;
    53.             }
    54.          
    55.             fixed3 frag(VertexOutput i) : COLOR {
    56.  
    57.                 fixed3 normalizedRGB = normalize(i.uv0.rgb);
    58.              
    59.                 fixed saturatedGreen = saturate(normalizedRGB.g);
    60.  
    61.                 fixed2 normalizedRB = normalizedRGB.rb;
    62.                 fixed2 invertedSaturatedGreen = (normalizedRB+(normalizedRB*(1.0f - saturatedGreen)));
    63.                 fixed4 _StarsTexture_var = tex2D(_StarsTexture,TRANSFORM_TEX(invertedSaturatedGreen, _StarsTexture));
    64.  
    65.                 fixed3 lerped = lerp(_Night.rgb, pow(_Night.rgb,_Night.a), (1.0f - normalizedRGB));
    66.                 fixed3 finalColor = lerp(_GroundColor.rgb,(((_StarsTexture_var.g*pow(saturatedGreen,_StarPosition))*_StarIntensity*lerped)+lerped),saturate((((0.1f*_GroundSmoothness)+normalizedRGB.g)/_GroundSmoothness)));
    67.                 return fixed3(finalColor);
    68.             }
    69.  
    70.             ENDCG
    71.         }
    72.     }
    73. }
    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!
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    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.
    https://docs.unity3d.com/Manual/SL-DataTypesAndPrecision.html

    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!