unity ShaderLab 基础之【深度测试DepthTest】ZWrite、ZTest详解

一 名词解释

1 Z深度

Z 就是深度轴,在一般3d软件中,x是横轴,y是纵轴,z是深度轴。离摄像机越近值越小,反之则越大。深度决定渲染的先后顺序。值大的像素会被值小的像素覆盖。

2 缓冲区

【颜色缓冲区】:也叫帧缓冲区,场景中的物体的像素都要写入该缓冲区,然后再渲染到屏幕上显示
【深度缓冲区】:用于记录颜色缓冲区中每个像素的深度值,通过深度缓冲区,我们可以通过深度测试来确定像素的遮挡关系
【模版缓冲区】:与深度缓冲类似,但这个值是可以自己设定的。,通过设置每个像素的模板缓冲值,就可以指定只渲染某些像素,用于实现类似遮罩之类的效果。

3 深度测试

深度测试开启时,当同一像素position位置有多个像素需要渲染的时候,可以按照某个规则,对比新的像素与已有像素的深度值,来决定最终输出哪个像素信息。默认情况深度值越小,优先权越高。
简单来说,深度测试,就是像素重合时的像素替换
规则。

4 透明测试

透明测试开启时,当前像素根据设定条件决定是否输出颜色

5 深度测试ZTest、透明测试AlphaTest、混合模式Blend的关系

总的来说深度测试ZTest决定遮挡关系,是否用当前像素替换缓存像素
透明测试alphatest决定是否显示透明度达标的像素
颜色混合blend决定通过测试的像素如果重合如何显示

深度写入

1 ZWrite(深度写入)

ZWrite的作用是决定是否要将像素的深度写入深度缓存中(同时还要看ZTest是否通过)
如果设置 ZWrite Off,则任何覆盖的像素都没有

//Zwrite 的默认值为On, 允许像素写入
ZWrite On
//不允许像素写入  如果一个物体就算没有遮挡 设置zwrite off 也不会显示
ZWrite Off

2 ZTest(深度测试)

【当前像素】 当前像素就是指当前shader脚本所属的模型像素
【缓存限速】 准备输出到屏幕上的像素,被称为缓存像素
【深度测试】 实际上就是描述如何确定缓存像素的规则
【启用深度测试的必要条件】ZWrite、ZTest同时不为Off

深度测试指令:

//启用深度测试,如果当前像素深度值大于缓存像素深度值就进行替换
ZTest Greater
指令 说明 实例
Greater 当前像素深度值 > 缓存像素深度值,就进行替换 ZTest Greater//类似于抠图
Less 当前像素深度值 < 缓存像素深度值,就进行替换 ZTest Less类似于反向抠图
GEqual 大于等于
LEqual 小于等于
Equal 等于
NotEqual 不等于
Always 总是
Never 永不
Off 关闭

3 实例

【准备工作】:
首先创建三个方块分A、B、C,再分别创建两个材质命名A、B。再为每个材质用下面的shader代码创建一个shader。将材质A赋给方块A、B,将材质B赋给C。然后将B的透明度修改为0.5,并添加Blend SrcAlpha OneMinusSrcAlpha做普通透明度混合。
【两个shader的代码】:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Custom/A"
{
	Properties
	{
        _MainTex ("贴图", 2D) = "white" {}
		_BackgroundColor ("背景颜色", Color) = (1, 1, 1, 1)
	}
	SubShader
	{
		Pass
		{
			///这段代码是B中独有的
			Tags {"Queue" = "Transparent"}
            Blend SrcAlpha OneMinusSrcAlpha
            ZWrite On
            ZTest Less
			///
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
            //从程序传染顶点渲染器的数据
			struct a2v
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};
            //从顶点渲染器传入片元渲染器的数据
			struct v2f
			{			
				float4 position : SV_POSITION;
				float2 uv : TEXCOORD0;
			};
 
			//格子背景
            sampler2D _MainTex;
			fixed4 _BackgroundColor;
            
            //顶点着色器
			v2f vert (a2v v)
			{
				v2f o;
                //将像素空间从模型转为裁剪空间
				o.position = UnityObjectToClipPos(v.vertex);
				o.uv = v.uv;
				return o;

			}
			//片段着色器
			fixed4 frag (v2f o) : COLOR
			{
				fixed4 renderTex = tex2D(_MainTex, o.uv);
                //合成贴图、遮罩、线的像素
                return renderTex * _BackgroundColor;
			}
			ENDCG
		}
	}
}

【原图】
在这里插入图片描述

1. ZTest Greater

在这里插入图片描述

//shader写法
ZTest Greater

【通过测试条件】:当前像素深度值 > 缓存像素深度值。 当前像素与缓存像素重合时,如果当前像素离摄像机更远就会替换掉缓存像素,否则就算作失效像素不做处理。
【本例解释】:由于B有一部分被A、C遮挡,所以被遮挡的地方显示。没有遮挡和被遮挡的像素之所以不显示,是因为那些像素和背景做了比较背景色更远。

2. ZTest Less

在这里插入图片描述

//shader写法
ZTest Less

【通过测试条件】:当前像素深度值 < 缓存像素深度值。当前像素与缓存像素重合时,如果当前像素离摄像机较近就替换掉缓存像素
【本例解释】:由于B有一部分被A、C遮挡,所以被遮挡的地方没有显示,因为对比之下B的像素离相机更远。B的中间部分可以看到A与C的轮廓,是因为B的透明度是0.5,由于我们设置了透明度正常融合,所以看到了下面的A、C的像素

3. ZTest GEqual

【效果图参照Greater】

//shader写法
ZWrite On
ZTest GEqual

【通过测试条件】:当前像素深度值 >= 缓存像素深度值。当像素与缓存像素重合时,如果当前像素离摄像机较远的或是与缓存像素深度值同等就会替换掉缓存像素,否则就算作失效像素不做处理。
【本例解释】:与 ZTest Greater 一样

4. ZTest LEqual

【效果图参照Greater】

//shader写法
ZWrite On
ZTest LEqual

【通过测试条件】:当前像素深度值 <= 缓存像素深度值。当像素与缓存像素重合时,如果当前像素离相机更近或与缓存像素的深度值相等就会替换掉缓存像素,否则就算作失效像素不做处理。
【本例解释】:与 ZTest Less 一样

5. ZTest Equal
//shader写法
ZWrite On
ZTest Equal 

【通过测试条件】:当前像素深度值 == 缓存像素深度值。当像素与缓存像素重合时,如果当前像素与缓存像素离摄像机同等距离就会替换掉缓存像素,否则就算作失效像素不做处理。

6. ZTest NotEqual
//shader写法
ZWrite On
ZTest NotEqual  

【通过测试条件】:当前像素深度值 != 缓存像素深度值。当像素与缓存像素重合时,如果当前像素与缓存像素深度值不同就会替换掉缓存像素,否则就算作失效像素不做处理。

7. ZTest Always
//shader写法
ZWrite On
ZTest Always

【通过测试条件】:当前像素与缓存像素重合时,永远直接替换缓存像素。与ZTest Off 效果相同

发布了138 篇原创文章 · 获赞 37 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/lengyoumo/article/details/104191053