Unity引擎中的前向渲染路径和延迟渲染路径的比较

Unity最重要的功能之一是可以让用户选择具体的渲染路径。对于那些不是很熟悉Unity的用户来说,(通常情况下)在前向渲染路径和延迟渲染路径做一个宣发就好比在“一个正常的渲染方法”和“某个看起来就很奇怪的方法”之间做选择一样。为了更好的理解为什么这里要有多个渲染路径进行选择,首先你需要理解这些设置背后的动机。

所有的渲染路径的核心都是光照的处理

光照的计算是非常昂贵的,主要是因为当物体被光照到的时候有大量的计算工作要做才能找出像素的有效颜色。在Unity中,光照可以按照逐顶点、逐像素、球谐光照。在这篇文章里面,我将主要谈论的是前两种。

Unity引擎中的前向渲染路径和延迟渲染路径的比较

在逐像素光照中,每个像素的颜色被单独计算(如左图所示)。在这个例子中,你可以看到即使我使用的是一个低精度的用多边形表示的球体,光照仍然让它看起来是圆的。如果不是因为有边缘的存在(边缘的地方就是明暗变化的地方),真的很难发现那些顶点都在哪里。右边的图是说明逐顶点的光照,它只在每个顶点上做一次光照。除了顶点以外的所有其他像素都是使用常规的颜色混合算法(就是简单的插值,不会再做进一步的光照计算)评估颜色。这是光照计算最节省的方法而且。。。。它的效果也看起来非常廉价(如果你想知道在哪里切换逐像素光照和逐顶点光照,它隐藏在渲染模式选项下面的光照组件里面。那里面比较重要的选项是强制每个光照为逐像素光照,不那么重要的选项是逐顶点光照,如果选择自动选项,那么Unity会选出强度最强的光源进行逐像素光照)。

相比较逐顶点光照,游戏开发者更喜欢逐像素光照,这不是一个秘密。但是逐像素光照有一个显著的缺点。每个光源会让每个在它光照范围的物体增加一个渲染批次。所以才会有一个物体最多受4个光源影响的限制。更重要的是,这里还涉及了对阴影的限制,根据Unity文档,只有一个光源可以产生阴影(出于某种原因,我已经成功地在Unity 5.3.4中得到了两个黑影,所以我真的不确定是否有这个限制。)

延迟渲染是光照问题的救星!

这是一种可以按照你的需求在场景中使用任意数目的光源的方法,而且这个方法还能同时保证性能仍然保持在一个合理的范围。它也不限制阴影的数量,如果场景中的对象是在光照范围之内的话,也不会增加额外的渲染批次(如果对象投射阴影的话则是例外)。这就是所谓的延迟着色渲染路径。

Unity引擎中的前向渲染路径和延迟渲染路径的比较

在游戏中的实时光照,一般有三种常用的办法,

1) 一遍渲染多个光源

在一遍渲染多个光源光照方法中,所有光照运算都在一个着色器中进行。但一个着色器有指令数量的限制,所以这个技术只适用于光源数量较少的情况。在某些游戏中,只需要少量光源,例如室外白天场景,这就是个较好的选择。这个技术的缺点是不能支持光源数量较多的情况.

2) 多遍渲染多光源

这种方法物体光照的计算只在当前光源着色器中进行。这会导致非常高的batch数量(调用Draw的次数),最坏的情况会达到光源数量乘以物体数量。某些操作会重复多次,例如顶点的转换。

3) 延迟渲染

首先,所有物体在不进行光照运算的情况下被绘制,然后对每个像素生成一组数据,这些数据包括位置、法线、高光颜色等,统一称之为G-buffer。之后,将每个光源以一个2D后期处理的方式(渲染屏幕大小的一个四边形)施加到最终图像上,这个过程使用的数据是在上一个批次中生成的G-buffer。

为什么延迟渲染是如此的不同?这主要是因为大部分模型在渲染的时候并不需要光照计算,而在渲染场景已经接近完成的时候,才会使用光照信息就好像在渲染一个二维图像一样。在这个阶段所做的改变通常被称为在屏幕空间进行了一些计算。知道这一点以后,我们可以说延迟渲染的光照是发生在屏幕空间

的。为了更好地理解延迟渲染的光照,最好看下帧调试器到底发生了什么。

场景渲染的最开始,渲染所有几何体:

Unity引擎中的前向渲染路径和延迟渲染路径的比较

这是一个平面图像,所以显卡怎么会知道如何运用灯光和阴影?这就要感谢深度缓冲区了!你可以把深度缓冲区理解成另一个图像,只是你看不到它而已,它存储的是每个像素所在的位置到底离相机有多远的信息。当作为图像表现出来的话,它看上去可能是这样的:

Unity引擎中的前向渲染路径和延迟渲染路径的比较

只有深度信息是不足以弄清楚光照如何在表面上进行计算的。我们至少需要另外一个东西-方向。三维空间的方向通常是用法线来表示的。延迟渲染的光照与其他光照方法不同的是除了具有颜色缓冲区和深度缓冲区,延迟渲染的光照还弄了一个缓冲区专门存储法线数据!

Unity引擎中的前向渲染路径和延迟渲染路径的比较

你怎么知道这些都是法线数据?这很容易!只需要看下场景中的小物体。

Unity引擎中的前向渲染路径和延迟渲染路径的比较

你看懂里面的颜色代表什么意思了么?红锥(X)指向左侧,跟前一张图中左边的面是一致的。绿色(y)指向上方而蓝色(z)指向右下(从这个角度看)。所以所有面的颜色都和前一张的图对应的上。有了这些信息,光照和阴影就可以渲染出来了。所以你的场景中有多少物体这件事真的不重要。所有的一切会在最后一幅图中完成。

Unity引擎中的前向渲染路径和延迟渲染路径的比较

这是光照处理以后的图像效果

上面的图像是一个光照批次的结果倒置过来的版本(也就是颜色等于1-color)。在渲染结束的时候,它会与第一章不透明的图像进行混合来得到最后的结果。

前向渲染路径

前向渲染的过程如下: 基础过程 在这个过程中先渲染一遍物体,把视觉空间的法线和 specular power存在一张 ARGB32渲染纹理中,法线贴图使用agb通道,高光贴图使用a通道。 基础过程的结果就是把场景信息和一张渲染纹理填充在z buffer中。

光照过程 光照过程就是通过深度信息、法线信和specular power计算光照。光照在屏幕空间进行计算,所以消耗与需要计算的时间不取决于场景复杂程度。光照缓冲信息存在一张 ARGB32 Render Texture中,它包括漫反射光照在rgb通道,高光强度在a通道。光照值用 logarithmic encode可以有更好的动态范围。当相机的HDR选项被选择,光照缓冲信息使用ARGBHalf 格式,不使用 logarithmic encode。

最后一轮处理 所有物体再一次全部渲染,获取光照并与贴图和环境光混合计算。光照贴图也在最后一轮处理里面。 中使用。相机离得近的地方进行实时光照,只烘焙间接光照。相机离得远的地方,光全部烘

我该选择哪个渲染路径?

看完了这一切后,你可能会以饱满的热情来使用新的渲染路径,但沉住气!延迟渲染并不是万能的,它不能解决这个世界所有的问题,它有一些。。。

限制

听了前面的描述,你会不会觉得延迟渲染太伟大了以至于都让人觉得有点不太真实了?它真的这么伟大么?其实它还是有一些限制的(或者说还是有一些缺点的)。

首先,延迟渲染不允许我们渲染半透明物体。这是因为如果场景中存在半透明的物体,就没有办法记录下物体的深度和法线信息,因为半透明物体和半透明物体后面的不透明物体都是可见的,可是我们只能记录一个物体的信息。Unity处理不能渲染半透明物体的限制是通过使用在整个处理过程的结尾使用前向渲染来解决的。它工作的效果相当的不错,这些对象可以向其他物体投射一层阴影,但遗憾的是这些物体无法从其他物体接收阴影。但是不幸的是使用前向渲染的话会造成很多未预期的问题。 第二个限制是缺乏抗锯齿的支持。原因与不能渲染半透明物体的情况类似,但是Unity并不试图以任何方式来解决这个问题。相反,你可以使用屏幕空间抗锯齿算法(图像后处理效果的一种),但是表现出来的视觉效果可能并没有那么好。另一个限制是你只可以使用最多四个删除遮罩。在Unity的官方文档里面,你可以读到一下的信息:

核心的地方在于,你的剔除层遮罩必须至少包括所有的层,最少的情况下也是四层,所以32层中的28层都必须进行设置。否则,你会看到各种莫名其妙的渲染效果。

最后延迟渲染不支持关于纹理渲染器的接收阴影的标记。

硬件要求

如果这还不够的话,那么延迟渲染其实只能在有限的一组显卡上才能使用。但在个人电脑上使用延迟渲染的时候,你可以安全的假定所有不老于10年的显卡都能支持延迟渲染。但是涉及到移动设备的时候,你没有办法假设任何东西。但是这不是一个大问题,因为。。。

性能

最重要的是,在大多数情况下,移动设备上延迟渲染的性能会比前向渲染的性能要差一些。这是因为每一帧渲染的时候都需要增加一次额外的渲染。如果你的场景中只有一个光源,那么使用延迟渲染可能是不划算的。

另外一方面,增加额外的灯光带来的计算消耗也非常低。在最坏的情况下性能的下降也是与光源的数目成正比的,而且与前向渲染相比较,延迟渲染的性能是与场景中的物体数量无关的。

Unity引擎中的前向渲染路径和延迟渲染路径的比较

《城市:天际线(Cities: Skylines)》(有Unity引擎开发完成的)决定使用延迟渲染路径。所以在游戏中你能看到大量的小光源但是整体的游戏性能仍然非常的棒。

可以进一步学习的资源

我希望这篇文章能够帮助你,当你为游戏选择渲染路径的时候能让你的思路变得清楚一些。如果你对这个主题感兴趣的话,你可能对以下这些资源感兴趣:

· http://docs.unity3d.com/Manual/RenderTech-DeferredShading.html

· http://docs.unity3d.com/Manual/RenderTech-ForwardRendering.html

· http://docs.unity3d.com/Manual/RenderTech-VertexLit.html


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值