根据 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 着色器出现故障的主要内容,如果未能解决你的问题,请参考以下文章

Unity学习——纹理材质&着色器

初步了解3D着色器的概念

Unity shader - 如何根据纹理贴图生成法线贴图

为啥我在 Unity RayMarching 着色器中出现 for-loop 错误?

Unity-SRP之DrawCall

unity2019着色器编辑器出问题打不开