首页 > 解决方案 > 渐变着色器 Z 仅在场景视图中战斗

问题描述

我创建了以下渐变,它采用图像组件源图像并对其应用两种颜色的渐变。使用切换可以切换到使用源图像的 alpha 作为渐变 alpha,或设置每个渐变颜色的 alpha。

 Properties
{
    [PerRendererData] _MainTex ("Texture", 2D) = "white" {}
    [Header(Colours)]
    _Color1("Color 1", Color) = (0,0,0,1)
    _Color2("Color 2", Color) = (1,1,1,1)

    [Toggle]_UseImageAlpha("Use Image alpha", float) = 0
    [Header(Cull mode)]
    [Enum(UnityEngine.Rendering.CullMode)] _CullMode("Cull mode", float) = 2
    [Header(ZTest)]
    [Enum(UnityEngine.Rendering.CompareFunction)] _ZTest("ZTest", float) = 4
    [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip("Use Alpha Clip", Float) = 1

}
SubShader
{
    Tags {"Queue" = "Transparent" "RenderType"="Transparent"}
    LOD 100
    Blend SrcAlpha OneMinusSrcAlpha
    ZTest [_ZTest]
    Cull [_CullMode]
    Pass
    {
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        #pragma multi_compile_local _ UNITY_UI_ALPHACLIP
        #include "UnityCG.cginc"
        struct appdata
        {
            float4 vertex : POSITION;
            float2 uv : TEXCOORD0;
            fixed4 col : COLOR;
        };
        struct v2f
        {
            float2 uv : TEXCOORD0;
            float4 vertex : SV_POSITION;
            fixed4 col : COLOR;
        };
        sampler2D _MainTex;
        float4 _MainTex_ST;
        fixed4 _Color1;
        fixed4 _Color2;
        bool _UseImageAlpha;
        v2f vert (appdata v)
        {
            v2f o;
            o.vertex = UnityObjectToClipPos(v.vertex);
            o.uv = TRANSFORM_TEX(v.uv, _MainTex);
            o.col = v.col;
            return o;
        }
        fixed4 frag (v2f i) : SV_Target
        {
            if (_UseImageAlpha) {
                _Color1.a = i.col.a;
                _Color2.a = i.col.a;
            }

            fixed4 col = tex2D(_MainTex, i.uv);
            col *= lerp(_Color1, _Color2, i.uv.y);
            col.a = clamp(col.a, 0, 1);

#ifdef UNITY_UI_ALPHACLIP
            clip(col.a - .001);
#endif

            return col;
        }
        ENDCG
    }
}

此着色器工作正常并按预期显示渐变,但是一旦我开始添加多层图像(例如它后面的蓝色正方形和前面的绿色正方形),它就会开始在场景视图中出现 Z 战斗问题基于场景相机与层次结构中下一个对象的角度(在本例中为绿色方块)。在游戏视图和构建中不会发生 Z 战斗。渐变圆 z 与前面的绿色方块战斗

我使用默认的LessEqualZTest 选项,将反向剔除和渲染队列设置为 3000(这与图像前后的渲染队列相同)。根据Unity 的文档,将其设置为LessEqual应该使前面的对象被绘制在顶部,而后面的对象被隐藏:

应该如何进行深度测试。默认为 LEqual(从或远处绘制对象作为现有对象;将对象隐藏在它们后面)。

将 ZTest 设置为任何其他选项(off、always、greaterEqual 等)都不会产生更好的结果。

如果我将渲染队列设置得更高(3001),它将始终在场景视图的顶部绘制渐变(游戏视图中没有变化),而将其设置为 2999 仍会使其与前面的对象发生冲突(绿色正方形),同时使其后面的蓝色正方形透明。渐变圆 z 与前面的绿色方块战斗,用较低的渲染队列将蓝色方块隐藏在后面

当我在渐变前面只有绿色方块时,它会在某些地方进行 z 战斗,而在源图像没有任何像素的其他地方切掉绿色方块。渐变圆 z 与前面的绿色方块以相等的渲染队列战斗

使用源图像的 alpha 或使用两种单独颜色的 alpha 也没有区别。

(gyazo)战斗根据相机角度变化的示例 gif。

是什么导致了这个 z 战斗,为什么它只发生在场景视图中?

使用 Unity 2019.3.13f1,Windows 上的 2019.2、2019.1m 2018.4 LTS、2017 LTS 的结果相同。

标签: unity3dshaderhlsl

解决方案


尝试添加ZWrite Off. 对于着色器,从Unity 内置着色器之一开始(或至少查看)可能会很有用,它与您想要的很接近。
在您的情况下,这将是UI-Default.shader


推荐阅读