Unity 透明混合为什么要关闭深度写入

如果半透明物体开启了深度写入的话,就无法看到在该fragment处后面渲染的fragment,这个主要是为了在半透明物体互相交叉、无法得到正确渲染效果时,我们折中的一种方式。

举个例子,我们来创造一个半透明物体互相交叉的例子:

请添加图片描述

这两个方块使用的Shader是一样的,但使用了两个各自的材质。为了让效果明显我故意把它们材质的透明度调成不同的值,摄像机靠后的方块透明度较低,靠前的较高。

在不采用其他方法的前提下,如果我们使用书里这种传统的透明混合的方式(指关闭深度写入进行混合)会得到下面的效果:

请添加图片描述

实际上,这种效果是有问题的。错误的地方在于中间两个方块互相重叠的地方,这个混合效果有问题。我们可以在脑海里重现这个渲染过程:首先Unity会基于物体中心对两个方块进行排序,来实现半透明物体的从后往前渲染的目的。所以,Unity会先渲染方块B、再渲染方块A(参见第一张图里面两个方块在摄像机空间下的位置)。然而在重叠区域,正确的渲染顺序应该是先渲染方块A,因为在这部分区域内,它被方块B覆盖住了,它位于后面。出现错误的本质原因是因为我们的排序都是基于object level的,而不是基于pixel level的排序。

如果此时我们把深度打开,则会得到下面的效果:

请添加图片描述

你可以一眼就看出来这里面的错误,那就是方块A的重叠部分别完全剔除掉了,这部分完全没有渲染!它被剔除掉的 原因就是因为Unity会先渲染方块B,由于方块B进行了深度写入,所以等到方块A渲染的时候,重叠部分A的像素根本无法通过depth test,会直接被剔除掉。

除了半透明物体之间的问题,尽管理论上来说,理想情况下半透明物体应该在所有不透明物体渲染完之后再渲染,但如果一个不透明物体因为某些原因在某个半透明物体后面被渲染了,也可能会因为半透明物体开启了深度写入而出现非常明显的渲染错误(不透明物体被半透明物体完全遮挡掉没有渲染)。

我觉得看到这里你应该知道我们为什么要关闭深度写入。总结一下的话,可以参考知乎上Milo Yip的回答:

对于不透明(opaque)的 fragment,最后只需要看到最接近视点的 fragment。在实时渲染一般是通过深度缓冲来取得这个最近的 fragment。

但对于半透明的 fragment,每一个都会影响最终的结果,需要从远至近地渲染。由于深度缓冲不能用于排序多个 fragment,所以只能用于保存最接近视点的不透明 fragment 深度,远于该深度的透明 fragment 不用渲染,所以仍需要深度测试(depth test)。

由于需要手动排序半透明的物体,写入深度已没有意义。如果能完美地手工排序不透明 fragment,写入深度也没有影响;但若物体在深度方向有重叠,有些 fragment 的顺序会有误,如果开启深度写入,会令到渲染错误很明显,而关掉的话影响较小一点。

当然理想的话,应该用顺序无关透明(order independent transparency, OIT)技术,例如用逐像素链表存储多个 fragment,以像素为单位排序渲染。
简而言之,就是因为,传统的半透明混合总是会在物体交叉、渲染重叠的情况下,出现错误的混合效果。如果开启深度写入,会令到渲染错误很明显,而关掉的话影响较小一点。

回到你的图里,由于你的两个方块摆放规则不存在相互重叠,所以Unity对于两个物体的排序在pixel level也是正确的排序,即每个像素也都是满足从后往前渲染的,所以你不会发现问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值