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:
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.
2
Answers
"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…
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..
Edit 2021-12-07:
From your shader, I can’t see any relationship between greyscale and alpha channel.
I think this would be a proper way to achieve what you needed.
Meanwhile, removing the line "Fallback…" should help debugging. As sometimes the fallback shader will override your current shader scripts.
There is also a mis-matching variable type in your original code, it should be float2 instead of half2.
I experienced something similar, where materials (and presumably shades…) looked different in an IOS build with dark mode off compared to the editor or an IOS build with dark mode on.
From here a dirty hack until this bug is solved is to add this key to the info.plist:
info.plist
This basically forces the app to use dark mode. It works the same for