如何进行U3D三维图形渲染

今天我们来了解一下游戏中的三维图形渲染技术。

三维图形要显示在屏幕上,需要CPU向GPU发送绘制调用(DrawCall)指令,然后GPU按照CPU下达的指令,完成一系列的脏活累活,将模型的顶点坐标变换到屏幕空间的像素坐标,再根据纹理和光照信息给每个像素涂上颜色,这是三维图形显示的大致流程。一般将三维图形呈现在屏幕上的这个过程叫做“渲染”。

性能瓶颈

渲染过程中,性能瓶颈可能存在于CPU或者GPU。如果CPU跑得慢,GPU已经把上一个DrawCall吩咐的工作全部做完了,CPU还发不出下一条DrawCall,那么GPU就可以打酱油了,这时候性能瓶颈在CPU。如果GPU手脚慢,CPU已经发来新的一条DrawCall,GPU还没做完上一条DrawCall吩咐的工作,那新的工作就只能等到GPU完成手头上的工作才能开始,这时候性能瓶颈在GPU。GPU的性能瓶颈在硬件指标上体现为像素填充率和显存带宽。在制定性能优化策略时,要搞清楚瓶颈到底在哪边。对于CPU性能较低的移动设备,一般重点在DrawCall优化。

渲染路径

在渲染中,根据渲染的方法不同,得到的显示效果也不同。每种渲染方法都是一个严密的流水线过程,图形硬件按照既定的格式接收图形数据输入,对数据进行规定的运算,最终得到显示数据。对渲染方法的流水线过程的定义,叫做渲染路径(Rendering Path)。

渲染路径的各个阶段中,图形硬件对数据具体执行哪些操作,是通过着色器(Shader)代码定义的。就是在渲染路径的每步里面的具体操作了。

Unity提供了四种渲染路径:前向渲染、延迟着色、延迟光照、顶点光照。它们的特征大致归纳起来是:

前向渲染(Forward):适用于光源较少、物体较少的场景,支持透明效果,支持绝大多数显卡

延迟着色(Deferred):适用于光源较多的场景,物体较多的场景,效果最好,不支持透明,显存带宽要求高,老显卡不支持

延迟光照(Legacy Deferred):延迟着色的变种,节约显存带宽,但增加DrawCall

顶点光照(Vertex Lit):最简单,兼容性最好,不支持阴影和凹凸贴图


其中,前向渲染和延迟着色是主流的选择。项目的渲染路径在Build Settings - Player Settings - Other Settings - Rendering -Rendering Path选项中设置。另外,每个摄像机都可以单独设置渲染路径。

前向渲染和延迟着色的性能比较

我们用一个例子说明前向渲染和延迟着色的性能差异。下图的场景里面有1个方向光,8个点光源,9个不透明物体(4个方块,4个球,1个平面)。所有光源都是实时的,没有使用全局照明。图1是前向渲染,图2是延迟着色,可以看出图2的方块的凹凸感更加鲜明,而DrawCall开销更少。


在所有光源都被指定为重要光源的情况下,两种渲染路径的DrawCall数分别为:

前向渲染:120

延迟着色:50

两者的DrawCall数相差如此之大,原因在于两种渲染路径中在光照计算上需要耗费的DrawCall数的差异。

前向渲染中,物体的灯光计算总共需要的DrawCall数DCF是:

DCF = 照射在单个物体的灯光数 * 物体总数

而延迟着色中,物体的灯光计算总共需要的DrawCall数DCD是:

DCD= 物体总数 + 灯光总数

在这个例子中,物体总数是9个,灯光数也是9个,每个灯光能够照射每个物体,根据上面的公式,可以得到:

DCF = 9 * 9 = 81

DCD = 9 + 9 = 18

可见光照计算方式的差异,是造成两者DrawCall性能差异的主要原因。

那么前向渲染是不是就没救了呢?也不是。如果把所有点光源的RenderMode设置为Not Important,那么所有点光源的计算会被简化合并到一个DrawCall中,尽管画面效果要再打折扣,如下图,点光源合并之后就无法在球体上显示高光了。但DrawCall就可以大大减少到46,甚至低于延迟着色。


通过这个例子,我们可以知道,在动态光源较多的场景,使用延迟着色不仅可以得到更好的画面,而且还可以节约DrawCall。下一次,我们会进一步了解延迟着色和前向渲染的光照性能差异,并学习结合使用两种渲染路径来优化带有透明物体的场景的方法。


来源:游戏机迷GamFuns ,转载此文目的在于传递更多信息,版权归原作者所有。如不支持转载,请联系小编demi@eetrend.com删除。

最新文章