不透明物体的渲染顺序

在Unity中为避免被遮挡看不见的部分重复Overdraw浪费性能,需要进行深度测试来剔除隐藏面(消隐)。为此不透明物体采用由近到远的绘制顺序 一边写入更新深度缓存一边做深度测试 (近的物体深度缓存中的值小),在绘制较远物体时,如果某个片段比已有深度缓存中的值大,说明前面有物体遮挡,需要丢弃这个被遮挡的片段。

半透明物体的渲染顺序

如果同样采用不透明物体的渲染方式会产生第一个问题: 半透明和不透明物体的渲染顺序 。
  • 半透明物体在不透明物体前,不透明物体的重叠区域会被当作是被遮挡的无效区域进行剔除,正常应该保留进行混合。
  • 不透明物体在半透明物体前,不透明物体后的透明物体会被剔除,正常。
第一种情况的本质原因是不透明物体的重叠区域因为深度测试到前方有透明物体于是把自己剔除了,解决错误剔除有几种可能的办法可以解决:
  • 可以关闭不透明物体B的深度测试或者让其深度测试总为通过,但这种方式仅适用于B前面没有别的不透明物体,否则B会遮盖住前方的物体,不可取,那么是否可以让B检测前面的物体是不透明就不关闭深度测试呢,实际上不可以,只有在渲染的最后Blending阶段才能知道一个物体是不是半透明的,在深度测试阶段无法知道。
  • 正确的方式应该是从半透明物体A入手,不将半透明物体B的深度值写入深度缓存,这样B也就不会知道自己前方存在A,而并不干扰B对其他不透明物体的正常深度测试。
这里需要注意,半透明物体 关闭了深度写入但并没有关闭深度测试 ,当其被不透明物体遮住时还是要正常剔除。
  • 现在关闭了半透明物体A的深度写入,B的重叠部分不会被剔除了,但如果还是从近到远的绘制顺序一起绘制不透明和半透明物体,如图不透明物体B会把A盖住(B不知道自己前面有A),这时如果 由远到近进行绘制 ,就可以解决半透明物体在不透明物体前面的情况。
到这里透明物体A在前,不透明B在后的情况已经正确,但回过头来看不透明B在前的情况:
在对A进行深度测试的时候,B还没有写入深度缓存,所以A不知道自己前面有B,自己不会被剔除,虽然最后效果是正确的,但本该剔除的片元错误的保留会造成浪费。所以还是应该从近到远进行绘制,但这就造成了没有一个统一的绘制顺序。
实际上是可以归为一种顺序的, Unity指定所有不透明物体绘制完毕后,再绘制半透明物体 (。这样就确保了透明物体A在不透明物体B之前时,由远到近正常叠加,相反时由近到远正常剔除。
另一方面,对于多个半透明物体重叠绘制时,先近后远会导致近处的不透明物体被远处的盖在上面叠加。因此对于半透明物体的渲染顺序还是要指定由远到近进行渲染。
有关不透明之间和半透明物体之间绘制顺序相反可以理解为: 不透明物体相当于剔除,要从近到远扣除重叠部分,而透明物体是叠加,要从远到近进行一层一层的叠加,符合正常画画的逻辑。
总结来说,半透明物体之间渲染从远往近,不透明物体之间从近往远,半透明和不透明物体之间先不透明后透明。具体流程如下:
1、先由近到远渲染所有不透明物体,并开启它们的深度测试和写入。
2、把半透明物体按它们离摄像机远近排序,然后按照从后往前的顺序渲染,开启深度测试,关闭深度写入。
Logo

分享前沿Unity技术干货和开发经验,精彩的Unity活动和社区相关信息

更多推荐