渐变着色器 Z 仅在场景视图中战斗

Posted

技术标签:

【中文标题】渐变着色器 Z 仅在场景视图中战斗【英文标题】:Gradient shader Z fighting in Scene view only 【发布时间】:2020-06-08 07:53:36 【问题描述】:

我创建了以下渐变,它采用图像组件源图像并对其应用两种颜色的渐变。使用切换开关可以切换到使用源图像的 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 战斗。

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

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

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

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

当我只有在渐变前面的绿色方块时,它会在某些地方打架,而在源图像没有任何像素的其他地方切掉绿色方块。

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

(gyazo) Example gif的战斗根据摄像机角度而变化。

是什么导致了这个z打架,为什么它只出现在场景视图中?

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

【问题讨论】:

尝试添加ZWrite Off。查看 Unity 的内置 UI-Default.shader 可能会有所帮助 @Pluto 厉害,确实是ZWrite加UNITY_UI_ALPHACLIP造成的!如果您将评论转换为完整答案,我会接受它:) 【参考方案1】:

尝试添加ZWrite Off。对于着色器,从Unity's built-in shaders 之一开始(或至少查看)与您想要的很接近可能会很有用。 你的情况是UI-Default.shader。

【讨论】:

以上是关于渐变着色器 Z 仅在场景视图中战斗的主要内容,如果未能解决你的问题,请参考以下文章

maya渐变着色器怎么用

为啥金属着色器渐变作为 SCNProgram 应用于 SceneKit 节点比作为 MTKView 更轻?

ShaderLab学习小结在标准表面shader中加入顶点着色器函数

Android UIPaint Gradient 渐变渲染 ③ ( RadialGradient 环形渐变渲染 | 在给定中心和半径的情况下绘制径向渐变的着色器 | 水波纹效果 )

Android UIPaint Gradient 渐变渲染 ② ( SweepGradient 梯度渐变渲染 | 围绕中心点绘制扫描渐变的着色器 | 多渐变色构造函数 | 雷达扫描效果 )

统一按钮在着色器中丢弃像素