
讯享网
深度测试在模板测试之后,透明度混合之前,如果开启了深度测试,GPU会把该片元的深度值和已经存在于深度缓冲区(Depth Buffer 或者叫 Z-Buffer)中的深度值进行比较,这个比较函数可由开发者设置的,例如片元的深度值大于缓冲区深度值时舍弃该片元
从逻辑上理解
if(ZWrite On && (currentDepthValue ComparisonFunction DepthBufferValue)) 写入深度 else 丢弃像素
讯享网
讯享网if(currentDepthValue ComparisonFunction DepthBufferValue) 写入颜色缓冲 else 不写入颜色缓冲
深度缓冲中,对于每一个像素都存储一个深度值,注意这个深度值是非线性的,近处的精度高,远处的精度低。ZTest分为通过和不通过两种情况,ZWrite分为开启和关闭两种情况,一共四种情况
- 深度测试通过,深度写入开启,写入深度缓冲区,写入颜色缓冲区
- 深度测试通过,深度写入关闭,不写深度缓冲区,写入颜色缓冲区
- 深度测试失败,深度写入开启,不写深度缓冲区,不写颜色缓冲区
- 深度测试失败,深度写入关闭,不写深度缓冲区,不写颜色缓冲区
深度测试的比较方法 ComparisonFunction ,和模板测试差不多
| 比较方法 | 描述 |
|---|---|
| Greater | 深度大于当前缓冲则通过 |
| GEqual | 深度大于等于当前缓存则通过 |
| Less | 深度小于当前缓存则通过 |
| LEqual | 深度小于等于当前缓存则通过 |
| Equal | 深度等于当前缓存则通过 |
| NotEqual | 深度不等于当前缓存则通过 |
| Always | 深度不论如何都通过 |
| Never | 深度不论如何都不通过 |
默认是ZWrite On和ZTest LEqual

- 不透明物体的渲染顺序:从前往后
- 透明物体的渲染顺序:从后往前
下面几种情况显示,ZTest,ZWrite和渲染队列如何影响渲染,蓝色立方体离摄像机最近,红色离的最远

这是默认设置,从近到远,先渲染蓝色,深度缓冲区默认是无穷大,蓝色深度小于无穷大,深度测试通过,写入深度,写入颜色缓冲,再渲染绿色,在蓝色和绿色相交的部分,绿色的深度大于蓝色,深度测试不通过,其他部分正常写入深度,最后渲染红色同理

渲染蓝色,深度测试通过,但是它关闭的深度写入,不写入深度值,写入颜色缓冲,渲染绿色,深度测试通过,写入深度值和颜色,替换掉之前的蓝色

渲染蓝色,和第一张图情况一样,绿色的ZTest设置为Always,不管深度值如何都通过深度测试,写入深度和颜色,重叠部分覆盖蓝色深度值

红色ZTest也改成Always,原理和绿色覆盖蓝色是一样的

绿色的渲染队列调整为Geometry+1,越大越后渲染,渲染顺序是:蓝,红,绿,先按照渲染队列排序,同一个队列,不透明物体按照从近到远排列

绿色ZTest选择Greater,表示当前深度大于深度缓冲区深度才能通过,蓝绿重叠部分,绿色深度大于蓝色深度,深度测试通过,其他部分绿色深度小于无穷大,深度测试不通过
可以使用下面的Shader验证
Shader "MyCustom/ZTestZWrite" {
Properties {
_Color ("_Color", Color) = (1, 0, 0, 1) //自定义枚举 [Enum(Off, 0, On, 1)]_ZWriteMode ("ZWriteMode", Float) = 1 [Enum(UnityEngine.Rendering.CompareFunction)]_ZTestComp ("ZTestComp", Int) = 4 } SubShader {
Tags {
"RenderType"="Opaque" "Queue"="Geometry" } ZWrite [_ZWriteMode] ZTest [_ZTestComp] Pass {
CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata {
float4 vertex : POSITION; }; struct v2f {
float4 vertex : SV_POSITION; }; float4 _Color; v2f vert (appdata v) {
v2f o; o.vertex = UnityObjectToClipPos(v.vertex); return o; } fixed4 frag (v2f i) : SV_Target {
return _Color; } ENDCG } } }
XRay效果

使用深度测试,实现角色在墙后显示描边的效果,这里用2个Pass实现
第一个Pass渲染描边,角色的深度大于墙的深度,为了让角色通过深度测试需要设置 ZTest Greater,并且需要保持正常的遮挡关系,所以渲染描边时不能写入深度,实现这种半透明效果还要设置混合因子
第二个Pass就是正常的渲染
讯享网Shader "MyCustom/XRay" {
Properties {
_MainTex("Base 2D", 2D) = "white" {
} _XRayColor ("XRay Color", Color) = (1, 0, 0, 1) } SubShader {
CGINCLUDE #include "UnityCG.cginc" float4 _XRayColor; struct v2f {
float4 pos : SV_POSITION; float3 normal : NORMAL; float3 viewDir : TEXCOORD0; fixed4 color : COLOR; }; v2f vertXRay(appdata_base v) {
v2f o; o.pos = UnityObjectToClipPos(v.vertex); //模型顶点到相机方向(模型空间) o.viewDir = ObjSpaceViewDir(v.vertex); o.normal = v.normal; float3 normal = normalize(v.normal); float3 viewDir = normalize(o.viewDir); float rim = 1 - dot(normal, viewDir); o.color = _XRayColor * rim; return o; } fixed4 fragXRay(v2f i) : SV_Target {
return i.color; } sampler2D _MainTex; float4 _MainTex_ST; struct v2f2 {
float4 pos : SV_POSITION; float2 uv : TEXCOORD0; }; v2f2 vertNormal(appdata_base v) {
v2f2 o; o.pos = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); return o; } fixed4 fragNormal(v2f2 i) : SV_Target {
return tex2D(_MainTex, i.uv); } ENDCG //XRay Pass {
Tags {
"RenderType"="Transparent" "Queue"="Transparent" } ZWrite Off ZTest Greater Blend SrcAlpha One CGPROGRAM #pragma vertex vertXRay #pragma fragment fragXRay ENDCG } //正常绘制 Pass {
Tags {
"RenderType"="Opaque" "Queue"="Geometry" } ZWrite On ZTest LEqual CGPROGRAM #pragma vertex vertNormal #pragma fragment fragNormal ENDCG } } }

对于多Pass渲染,Unity会从多个Pass里选择渲染队列最靠前的,把物体放在这个队列渲染,这里第一个Pass是Transparent,第二个Pass是Geometry,Geometry靠前渲染就放在了Geometry队列,然后会根据Pass顺序执行
参考
【技术美术百人计划】图形 3.1 深度与模板测试 传送门效果示例
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/59742.html