本页面将介绍 Unity 内置渲染管线中的前向渲染路径。
前向渲染根据影响对象的光源在一个或多个通道中渲染每个对象。光源本身也可以通过前向渲染进行不同的处理,具体取决于它们的设置和强度。
在前向渲染中,影响每个对象的一些最亮的光源以完全逐像素光照模式渲染。然后,最多 4 个点光源采用每顶点计算方式。其他光源以球谐函数 (SH) 计算,这种计算方式会快得多,但仅得到近似值。光源是否为每像素光源根据以下原则而定:
每个对象的渲染按如下方式进行:
例如,如果某个对象受到许多光源的影响(下图中的圆形受光源 A 到 H 的影响):
让我们假设光源 A 到 H 具有相同的颜色和强度,并且所有光源都具有自动渲染模式,因此它们将严格按照此对象的以下顺序排序。最亮的光源将以每像素光照模式渲染(A 到 D),然后最多 4 个光源以每顶点光照模式渲染(D 到 G),最后其余光源以 SH 进行渲染(G 到 H):
请注意,光源组会重叠;例如,最后一个每像素光源混合到每顶点光照模式,因此当对象和光源移动时,“光射量”(light popping) 较少。
基础通道使用一个每像素方向光和所有 SH/每顶点光源来渲染对象。此通道还会添加着色器中的所有光照贴图、环境光照和发射光照。在此通道中渲染的方向光可以具有阴影。请注意,光照贴图的对象不会从 SH 光源获得光照。
请注意,在着色器中使用“OnlyDirectional”通道标志时,前向基础通道仅渲染主方向光、环境光/光照探针和光照贴图(SH 和顶点光源不包括在通道数据中)。
对于影响此对象的每个额外的每像素光源,需要额外的渲染通道。默认情况下,这些通道中的光源没有阴影(因此在结果中,前向渲染支持一个带阴影的方向光),除非使用 multi_compile_fwdadd_fullshadows 变体快捷方式。
对于所有像素,动态光照会为每个受影响的像素增加渲染工作,可能导致对象在多个 pass 中被渲染。避免在性能较弱的设备(如移动端或低端 PC GPU)上使用多个__像素光照__来照射单个对象,应使用光照贴图实现静态对象的光照,而不是每帧计算其光照。每顶点动态光照可能会为顶点变换增加显著的工作量,因此尽量避免多个光源照射单个对象的情况。
避免组合距离足够远而需要受到不同像素光照影响的网格。使用像素光照时,每个网格必须渲染多次,因为只要发生像素光照就要进行渲染。如果组合两个相距很远的网格,则会增加组合对象的有效大小。照射该组合对象任何部分的所有像素光照在渲染期间都要考虑在内,因此需要创建的渲染 pass 的数量可能增加。通常情况下,为渲染组合对象而必须创建的 pass 数为每个单独对象的 pass 数之和,因此进行网格组合并不会获得任何好处。
在渲染过程中,Unity 会查找网格周围的所有光源,并计算出哪些光源对网格的影响最大。使用 Quality 窗口上的设置可修改多少个光源用于像素光照以及多少个用于顶点光照。每个光源根据它与网格的距离以及它的光照强度来计算其重要性;纯粹从游戏背景而言,有些光源比另一些光源更重要。鉴于此原因,每个光源都有 Render Mode 设置,可设置为 Important 或 Not Important__;标记为 Not Important__ 的光源具有较低的渲染开销。
示例:假设有一个驾驶游戏,玩家的汽车在黑暗中行驶,前照灯已打开。前照灯可能是游戏中视觉上最重要的光源,因此它们的 Render Mode 应设置为 Important。游戏中可能还有其他不太重要的光源,比如其他汽车的尾灯或远处的灯柱,这些光源不能通过像素光照来大幅改善视觉效果。这种情况下,可放心地将这些光源的 Render Mode 设置为 __Not Important__,从而避免将渲染能力浪费在无用之处。
通过优化每像素光照可以节省 CPU 和 GPU 工作量:CPU 的绘制调用将减少,而 GPU 要处理的顶点将减少,同时为所有其他对象渲染栅格化的像素也将减少。
球谐函数光源的渲染速度_很_快。这些光源的 CPU 成本很低,并且使用 GPU 的_成本基本为零_(也就是说,基础通道始终会计算 SH 光照;但由于 SH 光源工作方式的原因,无论 SH 光源有多少,成本都完全相同)。
SH 光源的缺点:
总的来说,SH 光源通常足以达到小型动态对象的光照要求。
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.