Home > Blockchain >  Unity shader glitches according to the Dark Mode on iOS 15
Unity shader glitches according to the Dark Mode on iOS 15

Time:12-07

I'm using a shader (code below) which allows me to turn an image color into a grayscale (with transparency if needed).

Everything was perfect until I updated my device to iOS 15. Since that update, my shaders glitch as soon as the scene is rendered. After a lot of days searching for a solution, I noticed that this is related to the iPhone Dark Mode.

I provided here some "concept" example in order to show you what currently happens:

enter image description here

The Grayscale shader is applied onto a red cube.

  • The cube A runs on an iPhone with Dark Mode activated (which is the result I get in Unity, the correct one).
  • The cube B represents the same object with Dark Mode disabled.

The problem is that I've been using these shaders for a lot of items inside my application and this gives me an inconsistency and ugly UI according to the User's Dark Mode preferences.

Note: I don't think that the problem is the shader itself, because on the < iOS 15 version it works fine. I think is something about how iOS 15 handles shaders with transparency effects, but It's just a supposition 'cause I still don't know how to work with shaders (I'm a student).

This is the shader I'm using:

Shader "Unlit/NewUnlitShader"
{
    Properties
    {
        _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
        _EffectAmount ("Effect Amount", Range (0, 1)) = 1.0
    }

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

        LOD 200
        Blend SrcAlpha OneMinusSrcAlpha
    
        Pass
        {

        CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata_t
            {
                float4 vertex : POSITION;
                float2 texcoord : TEXCOORD0;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                half2 texcoord : TEXCOORD0;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            uniform float _EffectAmount;
            
            v2f vert (appdata_t v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 c = tex2D(_MainTex, i.texcoord);
                c.rgb = lerp(c.rgb, dot(c.rgb, float3(0.3, 0.59, 0.11)), _EffectAmount);
                return c;
            }

        ENDCG
        }
    }
    Fallback "Standard"
}

Is this a bug or am I missing something?

UPDATE - SOLVE

It's a bug, Unity devs have been notified about this.

CodePudding user response:

"shader works < iOS 15" doesn't mean the shader itself is always correct.

Some simple shader variable types like float, half, and fixed can give you total different result in different devices and OS.

"half" and "fixed" variables for better performance, while "float" for less bug.

It happens mostly on mobile, due to different CPU/GPU specs and also your Graphic APIs option.

Another key word will be "Color Space", please check Linear & Gamma option in your Unity Build Player settings.

A broken shader will return pink color. If it's not pink, it must be some math issue in your shader for wrong result. The shader code works very straight forwarding. If the rendering result changes after a while, it seems likely some variables are changed in runtime too. And obviously the plugin which you are using, is also included lots of math calculation between C# and Shader.

You can imagine this: When the C# code is trying to get variable from Shader, but shader return a wrong variable for your calculation in C#. Then, C# assign the wrong calculation result again to the Shader. This will become infinite loop for wrong result.

Unity UI Effects(with shader) are not reliable: Sometimes, they are just not updated... You have to force them update via script. Below commands may help sometimes, but not always...

Canvas.ForceUpdateCanvases();
ScrollRect.GraphicUpdateComplete();

Thus, you should contact the developer who maintain this plugin instead. As they know the best of how their plugin works

Otherwise, you should begin writing your own shader scripts instead. Grayscale shader is just extremely easy to write..

  • Related