根据 iOS 15 上的暗模式,Unity 着色器出现故障
Posted
技术标签:
【中文标题】根据 iOS 15 上的暗模式,Unity 着色器出现故障【英文标题】:Unity shader glitches according to the Dark Mode on iOS 15 【发布时间】:2021-12-05 23:50:36 【问题描述】:我正在使用着色器(下面的代码),它允许我将图像颜色转换为灰度(如果需要,可以使用透明度)。
在我将设备更新到 ios 15 之前,一切都很完美。自从更新后,我的着色器在场景渲染后立即出现故障。 在寻找解决方案很多天后,我注意到这与 iPhone 暗模式有关。
我在这里提供了一些“概念”示例,以便向您展示当前发生的情况:
灰度着色器应用于红色立方体。
立方体 A 在启用了深色模式的 iPhone 上运行(这是我在 Unity 中得到的结果,正确)。 立方体 B 表示禁用深色模式的同一对象。问题是我一直在为我的应用程序中的许多项目使用这些着色器,根据用户的暗模式偏好,这给我带来了不一致和丑陋的 UI。
注意:我不认为问题出在着色器本身,因为在
这是我正在使用的着色器:
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"
这是一个错误还是我遗漏了什么?
更新 - 解决
这是一个错误,已通知 Unity 开发人员。
【问题讨论】:
我在 iOS 14.8.1 上对透明对象有类似的错误。统一 2020.3。 【参考方案1】:我遇到过类似的情况,与编辑器或启用暗模式的 IOS 版本相比,关闭暗模式的 IOS 版本中的材质(可能还有阴影......)看起来不同。
从here 开始,直到解决此错误为止,都是将这个密钥添加到 info.plist:
UIUserInterfaceStyle = Dark
info.plist
这基本上会强制应用使用暗模式。它的工作原理相同
UIUserInterfaceStyle = Light
【讨论】:
【参考方案2】:“着色器工作
一些简单的着色器变量类型,如 float、half 和 fixed 可以在不同的设备和操作系统中为您提供完全不同的结果。
“half”和“fixed”变量可以获得更好的性能,而“float”可以减少错误。
由于不同的 CPU/GPU 规格以及您的图形 API 选项,它主要发生在移动设备上。
另一个关键词是“色彩空间”,请在 Unity Build Player 设置中检查线性和伽玛选项。
损坏的着色器将返回粉红色。如果它不是粉红色,则一定是着色器中的一些数学问题导致错误结果。 着色器代码非常直接。如果渲染结果在一段时间后发生变化,似乎一些变量在运行时也发生了变化。很明显,您正在使用的插件还包含大量 C# 和 Shader 之间的数学计算。
你可以想象: 当 C# 代码试图从 Shader 获取变量时,但 Shader 返回了错误的变量以供您在 C# 中进行计算。然后,C#再次将错误的计算结果分配给Shader。 这将成为错误结果的无限循环。
Unity UI 效果(带着色器)不可靠: 有时,它们只是没有更新......您必须通过脚本强制它们更新。下面的命令有时可能会有所帮助,但并非总是如此......
Canvas.ForceUpdateCanvases();
ScrollRect.GraphicUpdateComplete();
因此,您应该联系维护此插件的开发人员。因为他们最了解他们的插件的工作原理
否则,您应该开始编写自己的着色器脚本。 灰度着色器非常容易编写..
编辑 2021-12-07:
从您的着色器中,我看不出灰度和 Alpha 通道之间有任何关系。
c.rgb = lerp(c.rgb, dot(c.rgb, float3(0.3, 0.59, 0.11)), _EffectAmount);
我认为这将是实现您所需要的正确方法。
fixed3 greyColor = dot(c.rgb, float3(0.3, 0.59, 0.11));
c.rgb = lerp(c.rgb, greyColor, _EffectAmount);
c.a = greyColor.a;
同时,删除“Fallback...”行应该有助于调试。因为有时后备着色器会覆盖您当前的着色器脚本。
Fallback "Standard"//remove it<---
您的原始代码中还有一个不匹配的变量类型,它应该是 float2 而不是 half2。
struct v2f
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
;
【讨论】:
你是对的。我尝试在UIEffects
框架中使用其他着色器和脚本。除了 alpha,每个人都按预期工作。每个使用 UIEffects
的对象如果具有一定的透明度就会出现故障,可能是因为 iOS 15 改变了一些东西(只是假设)。我要看看着色器,也许我能弄清楚一些事情。谢谢你回复我,你让我很开心
在 Shader 中,您还可以查看“RenderType”、“Blend”..等。和 alpha..etc 的“剪辑”。 UI Shader with Alpha 与 iOS 15 兼容。但是,为“Many Devices”编写通用着色器并不容易。例如,当您使用网络摄像头过滤器时,您需要找到一种技巧,以使高端和低端设备之间的结果尽可能相似。
这里的事情变得更加奇怪了!我决定创建自己的基本灰度+透明度着色器(由于我从未研究过着色器,因此主要从论坛复制)。你猜怎么着?它给了我关于 iOS 15+ 的确切问题。现在我认为问题不再是 UIEffect 了,而是更普遍的问题。
我终于找到了发生的事情,只是运气好。基本上它是关于以某种方式干扰着色器的暗模式。我更新了整个问题以使其清楚。我真的不知道这是怎么回事
这是一个众所周知的Bug,已经提交。感谢您的帮助和耐心@thelghome以上是关于根据 iOS 15 上的暗模式,Unity 着色器出现故障的主要内容,如果未能解决你的问题,请参考以下文章