渐变着色器 Z 仅在场景视图中战斗
Gradient shader Z fighting in Scene view only
我创建了以下渐变,它采用图像组件源图像并对其应用两种颜色的渐变。使用切换可以将其切换为使用源图像的 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 fighting 问题仅在场景视图中 基于场景相机与层次结构中下一个对象(在本例中为绿色方块)的角度。在游戏视图和构建中,不会发生 Z 战斗。
我正在使用默认的 LessEqual
ZTest 选项,将反向剔除和渲染队列设置为 3000(这与其前后图像的渲染队列相同)。根据 Unity's documentation 将其设置为 LessEqual
应该可以使前面的对象绘制在顶部,后面的对象隐藏:
How should depth testing be performed. Default is LEqual (draw objects in from or at the distance as existing objects; hide objects behind them).
将 ZTest 设置为任何其他选项(关闭、始终、greaterEqual 等)不会产生更好的结果。
如果我将渲染队列设置得更高 (3001),它将始终在场景视图中绘制渐变(在游戏视图中没有变化),而将其设置为 2999 仍会使其与它的前面(绿色方块),同时使它后面的蓝色方块透明。
当我在渐变前面只有绿色方块时,它会在某些地方打架,而在源图像没有任何像素的其他地方切掉绿色方块。
使用源图像的 alpha 或使用两种单独颜色的 alpha 也没有区别。
(gyazo) Example gif 战斗的变化取决于摄像机角度。
是什么导致了这种 z 冲突,为什么它只发生在场景视图中?
使用 Unity 2019.3.13f1,在 Windows 上的 2019.2、2019.1m 2018.4 LTS、2017 LTS 中结果相同。
尝试添加 ZWrite Off
。对于着色器,开始(或至少查看)Unity's built-in shaders that is close to what you want.
In your case that would be UI-Default.shader.
之一可能会很有用
我创建了以下渐变,它采用图像组件源图像并对其应用两种颜色的渐变。使用切换可以将其切换为使用源图像的 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 fighting 问题仅在场景视图中 基于场景相机与层次结构中下一个对象(在本例中为绿色方块)的角度。在游戏视图和构建中,不会发生 Z 战斗。
我正在使用默认的 LessEqual
ZTest 选项,将反向剔除和渲染队列设置为 3000(这与其前后图像的渲染队列相同)。根据 Unity's documentation 将其设置为 LessEqual
应该可以使前面的对象绘制在顶部,后面的对象隐藏:
How should depth testing be performed. Default is LEqual (draw objects in from or at the distance as existing objects; hide objects behind them).
将 ZTest 设置为任何其他选项(关闭、始终、greaterEqual 等)不会产生更好的结果。
如果我将渲染队列设置得更高 (3001),它将始终在场景视图中绘制渐变(在游戏视图中没有变化),而将其设置为 2999 仍会使其与它的前面(绿色方块),同时使它后面的蓝色方块透明。
当我在渐变前面只有绿色方块时,它会在某些地方打架,而在源图像没有任何像素的其他地方切掉绿色方块。
使用源图像的 alpha 或使用两种单独颜色的 alpha 也没有区别。
(gyazo) Example gif 战斗的变化取决于摄像机角度。
是什么导致了这种 z 冲突,为什么它只发生在场景视图中?
使用 Unity 2019.3.13f1,在 Windows 上的 2019.2、2019.1m 2018.4 LTS、2017 LTS 中结果相同。
尝试添加 ZWrite Off
。对于着色器,开始(或至少查看)Unity's built-in shaders that is close to what you want.
In your case that would be UI-Default.shader.