渲染顺序
深度缓冲
在实时渲染中,深度缓冲(depth-buffer,也被称为z-buffer)是用于解决可见性的(visibilty)问题的,它可以决定哪个物体哪些部分会被渲染在前面,而哪些部分会被其他物体遮挡住。它的基本思想就是:根据深度缓冲中的值来判断该片元距离摄像机的距离,当渲染一个片元时,需要把它的深度值和已经存在于深度缓冲中的值进行比较(默认会开启深度测试),如果它的值距离摄像机更远,那么说明这个片元不应该被渲染到屏幕上(说明有物体遮挡),否则这个片元应该覆盖掉此时颜色缓冲中的像素值,并把它的深度信息更新到深度缓冲中(默认开始深度写入)。
对于不透明的物体我们不需要关系它们的渲染顺序,因为使用了深度缓冲,无论是谁先被画都会有正确的效果。
但是如果想要实现透明效果,如透明度混合,渲染顺序就会很重要,因为对于透明度混合,我们关闭了深度写入(ZWrite)。注意深度测试没有关闭!!
引擎对于透明与不透明物体的渲染顺序的处理
引擎一般会先对物体进行排序,在渲染。常用的方法是:
(1)渲染所有不透明物体,并开启它们的深度测试和深度写入
(2)把半透明物体按它们距离摄像机的远近进行排序,然后按照从后往前的顺序渲染这些半透明物体,并开启他们的深度测试,关闭深度写入。
但是这并没有解决所有问题,第2步中的“摄像机的远近”如何定义,将会直接决定,那个透明物体在前,哪个透明物体在后,注意这个地方是对整个物体的排序,而不是比较深度缓冲区中的深度值(深度缓冲区中的值是像素级别的,是每个像素对于摄像机的远近)。当透明物体循环折叠时就会出现问题,因为是对整个物体序列进行排序,所以对于两个透明物体A,B,要么A全在B前面,要么A全在B后面。
上述出现的问题,我们可以使用开启了深度写入的半透明效果来近似模拟物体半透明的效果。
Unity Shader的渲染顺序
Unity为了解决渲染顺序的问题提供了渲染队列(render queue),这一解决方案。可以使用SubShader的Queue标签来决定我们的模型将归于哪个渲染队列。Unity在内部使用一系列整数索引来表示每个渲染队列,且索引号越小表示越早被渲染。
SubShader
{
Tags{"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
Pass
{
Tags{"LightModel"="ForwardBase"}
Cull Front
ZWrite Off //用于关闭深度写入
Blend SrcAlpha OneMinusSrcAlpha
}
}
其中ZWrite Off用于关闭深度写入,就可以写在Pass中也可以写在SubShader中,如果写在SubShader中则所有Pass都会关闭深度写入。