实现透明效果的两种方式:
- 透明度测试(Alpha Test),这种方法无法得到真正的半透明效果。
- 透明度混合(Alpha Blending)
深度缓冲用于解决可见性(Visibility)问题,它决定那个物体那些部分会被渲染在前面,那些部分会被遮挡。其思想是:根据深度缓冲中的值来判断该片元距摄像机的距离,当渲染一个片元时,需要把它的深度值和已经存在于深度缓冲中的值进行比较(开启了深度测试),如果它的值距离摄像机远,那么说明这个片元不应该被渲染到屏幕上(有物体挡住了它);否则,这个片元应该覆盖掉此时深度缓冲中的像素值,并把他的深度值更新到深度缓冲中(如果开启了深度写入)。
当我们想要实现透明效果时,需要关闭深度写入(ZWrite),那么之前的自动判断机制就失效了。
透明度测试和透明度混合的基本原理:
- 透明度测试,其效果是完全透明或完全不透明,因为只要有一个片元不满足条件,那么它就会被舍弃。
- 透明度混合,需要关闭深入写入,它使用当前的透明度作为混合因子,与已经存在颜色缓冲中的颜色值进行混合,得到新的颜色,其可以得到真正的透明度效果。
要想得到真正的透明度效果,需要使用透明度混合技术,其需要关闭深度写入,此时就必须要注意渲染顺序。如果不关闭深度写入,一个半透明表面背后表面本可以被看到的,但是因为深度测试结果较远导致后面的表面会被剔除,这样就无法看到了。这就导致渲染顺序非常重要。
一般渲染引擎会先对物体进行排序,再渲染:
- 先渲染所有不透明读题 ,并开启他们的深入测试与写入
- 把半透明物体按照远近排序,再按照从后向前的顺序渲染这些透明物体,并开启深度测试,并关闭深度写入。
Unity为了解决渲染顺序的问题提供了渲染队列(Render Queue)这一解决方案。
通过使用Queue标签(Tag)来决定我们的模型归于那个渲染队列。使用整数索引表示渲染队列,索引号越小表示越早被渲染。
名称 | 队列索引号 | 描述 |
---|---|---|
Background | 1000 | 这个渲染队列会在任何其他队列之前被渲染,通常使用该队列来渲染那些需要绘制在背景上的物体 |
Geometry | 2000 | 默认的渲染队列,大多数物体都使用这个渲染队列,不透明物体使用这个渲染队列。 |
AlphaTest | 2450 | 需要透明度测试的物体。 |
Transparent | 3000 | 这个队列的物体会在Geometry和AlphaTest物体渲染后,再按照从后往前的顺序进行渲染,任何使用了透明度混合的物体都应该使用这个队列 |
Overly | 4000 | 该队列用于实现一些叠加效果,任何需要在最后渲染的物体都应该使用这个队列 |
通过透明度测试实现透明度效果:
SubShader{
Tags { "Queue"="AlphaTest" }
Pass {}
}
通过透明度混合来实现透明效果:
SubShader {
Tags {"Queue" = "Transparent"}
Pass {
ZWrite Off
}
}