US2S2L5-2——States-渲染状态

回顾:

知识必备——片元

SubShader的基本构成:SubShader语句块中主要由3部分构成:渲染标签,渲染状态,n个渲染通道

1
2
3
4
5
            |--------Tags(渲染标签)
|--------States(渲染状态)
SubShader---|--------Pass(渲染通道1)
|--------Pass(渲染通道2)
|--------....(渲染通道n)

本章代码关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//设置剔除状态
Cull Back //背面剔除
Cull Front //正面剔除
Cull Off //不剔除
//是否写入深度缓冲
ZWrite On //写入深度缓冲
ZWrite Off //不写入深度缓冲
//设置深度测试通过条件
ZTest Less //小于当前深度缓冲中的值,就通过测试,写入到深度缓冲中
ZTest Greater //大于当前深度缓冲中的值,就通过测试,写入到深度缓冲中
ZTest LEqual //小于等于当前深度缓冲中的值,就通过测试,写入到深度缓冲中
ZTest GEqual //大于等于当前深度缓冲中的值,就通过测试,写入到深度缓冲中
ZTest Equal //等于当前深度缓冲中的值,就通过测试,写入到深度缓冲中
ZTest NotEqual //不等于当前深度缓冲中的值,就通过测试,写入到深度缓冲中
ZTest Always //始终通过深度测试写入深度缓冲中
//设置混合方式
Blend One One //线性减淡
Blend SrcAlpha OneMinusSrcAlpha //正常透明混合
Blend OneMinusDstColor One //滤色
Blend DstColor Zero //正片叠底
Blend DstColor SrcColor //X光片效果
Blend One OneMinusSrcAlpha //透明度混合
//其他
LOD 数值 //控制SubShader的LOD级别,Unity引擎会根据不同的LOD值在使用不同的SubShader
ColorMask RGBA //设置颜色通道的写入蒙版,默认蒙版为RGBA

渲染状态

渲染状态对于我们来说很重要,它可以影响最终我们看到的渲染效果

其中:

  • 剔除方式决定了 模型正面背面是否能够被渲染
  • 深度缓冲和深度测试 决定了景深关系的确定以及透明效果的正确表达等
  • 混合方式 决定了透明半透明颜色的正确表现,以及一些特殊颜色效果的表现

渲染状态的语法结构

1
2
3
4
SubShader
{
渲染状态 状态类型
}

例如:

1
2
3
4
SubShader
{
LOD 100
}

渲染状态是通过 渲染状态关键词+空格+状态类型​ 决定的
如果存在多个渲染状态,可以通过换行隔开

渲染状态的注意事项

以下些状态不仅可以在 SubShader​ 语句块中声明
之后讲解的Pass渲染通道语句块中也可以声明渲染标签
如果在 SubShader​ 语句块中使用,会影响之后的所有渲染通道Pass
如果在 Pass​ 语句块中使用只会影响当前 Pass​ 渲染通道,不会影响其他的Pass

剔除方式

主要作用:设置多边形的剔除方式,有背面剔除、正面剔除、不剔除

所谓的剔除,就是不渲染,背面剔除就是背面不渲染,正面剔除就是正面不渲染,不剔除就是都渲染

1
2
3
Cull Back     //背面剔除
Cull Front //正面剔除
Cull Off //不剔除

不设置的话,默认为背面剔除,如果是背面剔除,当摄像机处于模型内部时,我们是看不到模型的贴图的,也就是其模型内部的面看不到

image

一般情况下,我们需要两面渲染时,会设置为不剔除

1
2
3
4
SubShader
{
Cull Off
}

image

深度缓冲

主要作用:是否写入深度缓冲,也就是是否开启深度写入

深度缓冲(Depth Buffer):
深度缓冲是一个与屏幕像素对应的缓冲区,用于存储每个像素的深度值(距离相机的距离)。
在渲染场景之前,深度缓冲被初始化为最大深度值,表示所有像素都在相机之外。最后留在深度缓冲中的信息会被渲染

关于深度缓冲和深度写入,详见:逐片元操作中的深度测试流程

1
2
ZWrite On     //写入深度缓冲
ZWrite Off //不写入深度缓冲

不设置的话,默认为写入,一般情况下,我们在做透明等特殊效果时,会设置为不写入

关于天空盒Shader

天空盒的Shader通常是关闭了深度写入的。这意味着天空盒不会对深度缓冲区进行任何写入操作。
这样做的原因是,天空盒本质上是渲染在场景的背景中,不需要参与深度测试。

即使我们不知道这点,也不太影响我们对最终渲染结果的理解,在此特别说明。

深度测试

主要作用:设置深度测试的对比方式

深度测试的主要目的是确保在渲染时,像素按照正确的深度(距离相机的距离)顺序进行绘制,从而创建正确的遮挡关系和透视效果
在渲染场景之前,深度缓冲被初始化为最大深度值,表示所有像素都在相机之外。
在渲染过程中,对于每个像素,深度测试会将当前像素的深度值与深度缓冲中对应位置的值进行比较。

一般情况下:

  1. 如果当前像素的深度值小于深度缓冲中的值,说明当前像素在其他物体之前,它会被绘制,并更新深度缓冲。
  2. 如果当前像素的深度值大于等于深度缓冲中的值,说明当前像素在其他物体之后,它会被丢弃,不会被绘制,并保持深度缓冲不变。

关于深度测试的流程,详见:逐片元操作中的深度测试流程

Shader内可以修改通过深度测试的条件:

1
2
3
4
5
6
7
ZTest Less        //小于当前深度缓冲中的值,就通过测试,写入到深度缓冲中
ZTest Greater //大于当前深度缓冲中的值,就通过测试,写入到深度缓冲中
ZTest LEqual //小于等于当前深度缓冲中的值,就通过测试,写入到深度缓冲中
ZTest GEqual //大于等于当前深度缓冲中的值,就通过测试,写入到深度缓冲中
ZTest Equal //等于当前深度缓冲中的值,就通过测试,写入到深度缓冲中
ZTest NotEqual //不等于当前深度缓冲中的值,就通过测试,写入到深度缓冲中
ZTest Always //始终通过深度测试写入深度缓冲中

不设置的话,默认为 LEqual​ ,即当小于等于当前深度缓冲中的值,就通过测试,写入到深度缓冲中

一般情况下,我们只有在实现一些特殊效果时才会区修改深度测试方式,比如​**透明物体渲染会修改为Less,描边效果会修改为Greater等**

示例(将深度测试通过条件改为大于当前深度缓冲中的值)

1
2
3
4
SubShader
{
ZTest Greater
}

修改前效果:image修改后:image

混合方式

主要作用:设置渲染图像的混合方式(多种颜色叠加混合,比如透明、半透明效果和遮挡的物体进行颜色混合)

混合流程详见:逐片元操作中的混合流程

1
2
3
4
5
6
Blend One One                         //线性减淡
Blend SrcAlpha OneMinusSrcAlpha //正常透明混合
Blend OneMinusDstColor One //滤色
Blend DstColor Zero //正片叠底
Blend DstColor SrcColor //X光片效果
Blend One OneMinusSrcAlpha //透明度混合

等等,不设置的话,默认不会进行混合

一般情况下,我们需要多种颜色叠加渲染时,就需要设置混合方式,具体情况具体处理

其他渲染状态

  1. LOD(Level Of Detail)- 细节层次

    Unity引擎会根据不同的LOD值在使用不同的SubShader

    控制LOD级别,我们可以在Pass语句块里使用它,用于控制模型在不同距离下的渲染方式,一般越远的模型渲染细节越少

    1
    LOD 100
  2. ColorMask - 颜色蒙版

    设置颜色通道的写入蒙版,默认蒙版为RGBA

    1
    ColorMask RGBA

等等,我们目前主要掌握剔除方式、深度缓冲、深度测试、混合方式即可