笔者使用的是 Unity 2018.2.0f2 + VS2017,建议读者使用与 Unity 2018 相近的版本,避免一些因为版本不一致而出现的问题。
目录
前言
相信读者对透明效果都不陌生,因为透明效果是游戏中经常使用的一种效果。要实现透明效果,通常会在渲染模型时控制它的透明通道。而其透明度则控制是其是否会显示,0 表示完全不显示,1 表示完全显示。
Unity 中通常使用两种方法来实现透明效果:透明度测试(Alpha Test)和 透明度混合(Alpha Blending)。
- 透明度测试。透明度测试是一种十分 “简单粗暴” 的机制,当有一个片元的透明度不符合条件时,就直接舍弃,不再任何处理(不会对颜色缓冲有影响);如果符合,就进行正常的处理(深度测试,深度写入等);所以这带来的效果也是两极分化的,要么完全透明,要么完全不透明。
- 透明度混合。透明度混合可以得到真正的半透明效果。它会使用当前片元的透明度作为混合因子,与颜色缓冲中的值进行混合,得到新的颜色。需要注意的是,此方法需要关闭深度写入,而因此带来的问题就是要 十分十分十分 地注意渲染顺序。
为了方便读者理解,先解释一下深度缓冲,深度测试和深度写入
- 深度缓冲。用于解决可见性问题的强大存在。决定了哪个物体的哪些部分会被渲染,哪些部分会被遮挡
- 深度测试。开启后,当渲染一个片元时,根据它的深度值判断该片元距离摄像机的距离,然后将它的深度值和深度缓冲中的值进行比较
- 深度写入。开启后,当一个片元进行了深度测试后,如果它的值距离更远,则说明有物体挡在了它前面,那么它就不会被渲染,如果更近,那么这个片元就应该覆盖掉颜色缓冲中的值,并把它的深度值更新到深度缓冲中。
可能会有读者会问:为什么透明度混合需要关闭深度写入呢?我们可以同过一张图来解释
平面 1 和 平面 2 都是在摄像机视线上,平面 1 是透明的而平面 2 是不透明的且平面 1 挡住了平面 2。理论上我们应该可以透过平面 1 来看到平面 2。事实上,如果没有关闭深度写入,平面 1 和 平面 2在渲染时进行深度测试,测试结果为平面 2更远,所以平面 2不会被渲染到屏幕上,即我们看不到平面 2。这很显然是不符合我们所要的。所以透明度混合需要关闭深度写入。
一. 渲染顺序
1.1 渲染顺序的重要性
前文说过,关闭了深度写入后,渲染顺序就变得十分重要,为什么这么说呢
如图,A 和 B渲染顺序不一样。有两种情况
- 先渲染 B 再 渲染 A。此时深度缓冲中没有数据,B 直接写入它的颜色缓冲和深度缓冲;然后渲染 A,A进行深度测试,结果为 A 更近,所以此时会用 A 的透明度与颜色缓冲中值进行混合,得到正确的半透明效果。
- 先渲染 A 再 渲染 B。此时深度缓冲中并没有数据,A 会写入颜色缓冲,但不会写入深度缓冲(因为关闭了深度写入);然后渲染 B ,B 进行深度测试,而此时深度缓冲中并没有数据,所以 B 会直接写进颜色缓冲和深度缓冲,就会覆盖掉颜色缓冲中 A 的颜色,所以最终渲染出来,从视觉上是 B 在 A 的前面
所以说,渲染顺序十分重要,就算 A 和 B 同为半透明物体也是一样的情况。所以,我们一般是先渲染不透明物体,再渲染透明物体。
1.2 渲染队列
Unity 中提供了 渲染队列,并用整数索引表示渲染队列,索引越小,越早渲染
![]()
也可以使用 SubShader 中的 Queue 标签来决定该模型属于哪个渲染队列
名称 队列索引号 描述 Background 1000 这个队列会在任何队列 之前被渲染,通常用来渲染绘制在背景的物体 Geometry 2000 默认的队列,非透明物体使用此队列 Alpha Test 2450 进行透明度测试的物体使用的队列 Transparent 3000 按后往前顺序渲染,使用透明度混合的物体应该使用此队列 Overlay 4000 在最后渲染的物体使用此队列
二. 透明度测试
新建一个工程,去掉天空盒;新建一个Material 和 shader ,命名为 Alpha Test;新建一个 cube
需要提前了解的是:
- ZWrite Off 用于关闭深度写入,可以写在 Pass里面,也可以写在 SubShader 里,如果是后者,那么就会对所有的 Pass 产生效果,即所有的 Pass 都会关闭深度写入。
- 我们在后面的代码将会使用 clip 函数进行透明度测试。参数为裁剪时使用的标量或矢量,如果参数的任一分量为负数,就舍弃当前像素的输出颜色。我们同样可以在MSDN上找到它的定义
I. 创建一个场景,去掉天空盒;新建一个 Material 和 shader ,命名为 Alpha Test;创建一个 Cube;准备一张不同区域透明度不同的透明纹理(读者可以在本文最下方下载);
II. 定义 Propreties 语义块
Properites 语义块并没有什么特别的属性,_Cutoff 属性用来控制透明度,范围为【0,1】,因为纹理像素的透明度范围就在此范围。
III. 指定渲染队列






最低0.47元/天 解锁文章
7077

被折叠的 条评论
为什么被折叠?



