Unity Shader (三)深度测试(depth test)

前言:
第二篇我说了在片段程序处理之前除了裁剪,还有一个比较重要的概念就是深度测试。深度测试的作用其实是对裁剪的弥补,裁剪讨论的范围是局部坐标的模型本身的优化,而深度测试是在世界空间的对渲染的优化,想象一下,在世界空间中有很多出现在视野中,但是有互相遮挡的情况,其实我们是不需要去处理他的着色的。而要完成这个过程就必须用到两个术语(缺一不可):深度缓存(zwrite) + 颜色缓存(ztest)

zwrite 分类

zwrite on / off : 开启深度缓冲/关闭深度缓冲(其实就是记录Z值,把最小的Z存放在缓冲中),一般情况不透明的物体都会使用zwrite on 而 半透明的物体都会使用 zwrite off 这样半透明的物体就直接比较ztest了

ztest 分类

less / greater / lequal /gequal / equal / notequal /always(其实就是拿着当前的像素来对深度缓冲中的z值进行比较的条件)

那么他们的情况就有如下几种

1.当ZWrite为On时,ZTest通过时,该像素的深度才能成功写入深度缓存,同时因为ZTest通过了,该像素的颜色值也会写入颜色缓存。
2.当ZWrite为On时,ZTest不通过时,该像素的深度不能成功写入深度缓存,同时因为ZTest不通过,该像素的颜色值不会写入颜色缓存。
3.当ZWrite为Off时,ZTest通过时,该像素的深度不能成功写入深度缓存,同时因为ZTest通过了,该像素的颜色值会写入颜色缓存。
4.当ZWrite为Off时,ZTest不通过时,该像素的深度不能成功写入深度缓存,同时因为ZTest不通过,该像素的颜色值不会写入颜色缓存。

总结:zwrite只是处理深度值,ztest才是决定采用谁的颜色值,zwrite只是为ztest服务的。默认情况下unity采用的是zwrite为on,ztest为lqeual 也就是越靠近相机的显示优先级越高。

例子1:两个不透明的物体我需要后面的物体不被挡住。比如游戏里面的轮廓显示主角(要实现这种情况其实有很多方式,具体可以自己尝试)

这里写图片描述这里写图片描述

代码:

Shader "Custom/Depth Test" {
    Properties {
        //定义一个贴图
        _MainTex ("Base (RGB)", 2D) = "white" {} 
    }
    SubShader 
    {       
      Pass
        {
            zwrite on //打开深度缓存
            ztest greater  //打开深度测试,颜色通过
        }

        Pass
        {
            SetTexture [_MainTex] 
            {
                Combine texture * primary  //正面赋予贴图
            }
        }
    } 
    FallBack "Diffuse"
}

渲染队列

前面我们说的zwrite 和 ztest 可以理解为在同一个队列里面进行的,我们知道在Tag 里面可以设置queue这个参数来表明物体所在的队列。也许你看到的不透明不同越靠近相机,半透明物体远离相机,但是由于他们的queue不同也就是基础深度不同,所以他们渲染的渲染顺序也是不同的。

例子二:使用渲染队列决定z值

这里写图片描述这里写图片描述

cube的代码

Shader "Custom/Depth Transparent" {

    SubShader 
    {       
        Tags { "Queue"="Transparent-1000"} //这里可以自己试着修改,比如修改为-999的时候你会发现角色被挡住了
         pass{

         }
    } 
    FallBack "Diffuse"
}

这里列举下unity 内部的渲染队列: Background = 1000, Geometry = 2000, AlphaTest = 2450
Transparent = 3000, Overlay = 4000 所以知道为什么上面的 -1000 和 -999 的区别了吧 (越大的值越后渲染)

### 如何在 Unity测试 Shader 模板 #### 使用 `Stencil` 关键字配置模板测试 为了启用并自定义模板测试,在着色器中需加入特定的 `Stencil` 代码块。此部分允许开发者指定一系列参数来控制哪些像素应当被绘制以及如何更新模板缓冲区中的数据[^3]。 ```cg Shader "Custom/StencilTest" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } Pass { Stencil { Ref [_RefVal] ReadMask [_ReadMaskVal] WriteMask [_WriteMaskVal] Comp Always // Comparison function Pass Replace // Action on pass Fail Keep // Action on fail ZFail Keep // Depth buffer fail action } CGPROGRAM #pragma vertex vert #pragma fragment frag sampler2D _MainTex; struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 pos : SV_POSITION; }; v2f vert (appdata v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; } fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv); return col; } ENDCG } } } ``` 这段代码展示了怎样创建一个带有基本纹理映射功能的同时也启用了模板测试的着色器。其中,`Comp`, `Pass`, `Fail`, 和 `ZFail` 定义了当执行模板测试时不同情况下的行为;而 `Ref`, `ReadMask`, 及 `WriteMask` 则用于设置参考值及其掩码操作[^5]。 #### 配置材质属性以调整模板测试逻辑 除了编写合适的着色器外,还需要通过脚本或Inspector面板动态修改这些属性以便灵活地改变模板测试的行为模式: - `_RefVal`: 设置参考数值。 - `_ReadMaskVal`: 设定读取遮罩位。 - `_WriteMaskVal`: 控制写入遮罩位。 这使得可以在运行期间轻松切换不同的模板测试条件而不必重新编译着色器程序[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值