白泽图

  • 文章
    • Unity渲染
    • Unity项目开发
    • 工具
    • 数学
    • 算法
    • 网站搭建
    • 网络&操作系统
蒋程个人博客
互联网技术经验总结&分享
  1. 首页
  2. Unity渲染
  3. 正文

Unity渲染顺序(Queue,ZWrite,ZTest)

2020-12-31 3303点热度 2人点赞 0条评论

用实例说明Queue,ZWrite ,ZTest对渲染循序的影响

新建两个一样的Shader(Test1.shader与Test2.shader) 并分别创建材质球,然后赋值给两个Cube, shader代码如下:

Shader "Custom/Test1"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                return col;
            }
            ENDCG
        }
    }
}

这个shader非常简单,就是采样一张贴图,我们分别给它们一张绿色和一张紫色的图,注意此时我们没有写任何关于Queue,ZWrite ,ZTest的代码,但事实上Unity帮我们默认设置这三个属性,首先是渲染队列默认设置(缺省代码如下)

Tags { "Queue"="Geometry" }

我们可以通过Inspector面板来观察它


渲染队列(RenderQueue)

Unity允许我们通过一个叫渲染队列的值来决定物体渲染的先后顺序(可以忽略物体的摆放顺序),它规定渲染队列值越小的物体优越被渲染

(特别注意 越小越优先被渲染说明后渲染的物体有可能会挡住先渲染的物体)

渲染队列的值

Unity将不同类型的物体渲染顺序划分了一个区间,比如不透明物体(Geometry)默认值是2000,透明度测试的物体(AlphaTest)默认值是2450。(代码 Tags { "Queue"="Geometry-1" } 对应 1999,同理Tags { "Queue"="Geometry+1" }对应2001,其他以此类推)

实际验证

我们将两个cube放到距离相机一样远的位置,并让它们有一部分重叠,然后分别调整它们的渲染队列值进行观察

首先我们将cube2的RenderQueue调整到2001,发现Cube2显示到前面


然后我们将cube1的RenderQueue调整到2002,发现Cube1显示到前面

看来RenderQueue确实可以改变物体的渲染顺序,越小的值越先被渲染,所以RenderQueue大的物体会挡住RenderQueue小的物体

继续实验

我们将Cube1往后移一米继续观察


Cube1跑到后面了,此时出现了一个问题,明明Cube1的RenderQueue大于Cube2的,为什么会跑后面去了?说好的可以忽略物体摆放位置呢?

这个问题涉及到Unity的另外两个缺省设置,深度测试与深度缓冲区


ZTest&ZWrite

缺省代码如下

ZTest LEqual
ZWrite On

ZTest:深度测试   LEqual 是 测试标准

ZTest LEqual 表示 当一个颜色的深度(代表距离相机的远近的值)小于等于  时才有资格写入深度缓存  (除了LEqual之外还有Less (<) 、 Greater (>)  、 GEqual  (>=)、 Equal (==) 、 NotEqual (!=) 、 Always (全部通过)  、Never(全部不通过)、On(开启深度测试 等同于ZTest LEqual)、Off (关闭深度测度 等同于ZTest Always) )

ZWrite: 是否允许写入深度缓存(Depth-Buffer)  On (开启) 、 Off (关闭)

先说结论: ZTest与Zwrite的作用就是用来保证物体之间的遮挡顺序可以正确的显示,也就是离我们近的物体会挡住离我们远的物体,这符合自然规律

现在我们来将这两个默认设置都关闭

ZTest Off
ZWrite Off

再看一下效果:

现在渲染的顺序以渲染队列为准了

继续回过头来看ZTest与ZWrite的原理,这里需要提两个概念,一个是颜色缓冲区,另一个是深度缓冲区

颜色缓冲区(COLOR_BUFFER)就是帧缓冲区(FRAME_BUFFER),摄像机需要渲染的场景最终每一个像素都要写入该缓冲区,然后由它在渲染到屏幕上显示

深度缓冲区(DEPTH_BUFFER)与帧缓冲区对应,用于记录上面每个像素的深度值,通过深度缓冲区,我们可以进行深度测试,从而确定像素的遮挡关系,保证渲染正确.

逻辑执行顺序:

1.当ZTest开启时,以深度缓冲为判断基准,来判断是否满足通过条件,如果不满足则直接丢弃,如果满足执行2

2. 更新颜色缓存,同时判断是否可以更新 深度缓冲,(也就是 ZWrite 是On还是 Off),如果Off,不更新深度缓冲(之后如果有同位置的颜色要深度测试,用的还是之前深度缓冲里对应颜色的深度),如果满足执行3

3.更新深度缓冲

(深度缓冲创建时,默认里面的值都是无穷大,设置ZTest Greater(>=)时会发现一个有趣的现象:Cube1消失了,因为它无法通过深度测试)


ZTest与ZWrite的所有组合关系如下

1.深度测试通过,深度写入开启:更新颜色缓冲区,更新深度缓冲区;

2.深度测试通过,深度写入关闭:更新颜色缓冲区,不更新深度缓冲区;

3.深度测试失败,深度写入开启:不更新颜色缓冲区,不更新深度缓冲区;

4.深度测试失败,深度写入关闭:不更新颜色缓冲区,不更新深度缓冲区。

标签: 暂无
最后更新:2021-01-15

蒋程

这个人很懒,什么都没留下

点赞
< 上一篇
下一篇 >

文章评论

您需要 登录 之后才可以评论

COPYRIGHT © 2023 白泽图. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

登录
注册|忘记密码?