Notifications
Article
光照探针
Published a month ago
237
0
通过光照探针可以捕获并使用穿过场景空白空间的光线的相关信息。
与光照贴图类似,光照探针存储了有关场景中的光照的“烘焙”信息。不同之处在于,光照贴图存储的是有关光线照射到场景中的表面的光照信息,而光照探针存储的是有关光线穿过场景中的空白空间的信息。
光照探针有两个主要用途:
  • 光照探针的主要用途是为场景中的移动对象提供高质量的光照(包括间接反射光)。
  • 光照探针的次要用途是在静态景物使用 Unity 的 LOD(细节级别)系统时提供该景物的光照信息。
将光照探针用于这两个不同目的时,需要使用的许多技术都是相同的。了解光照探针的工作原理非常重要,这样才能正确选择将探针放置在场景中的位置。

放置光照探针

要将光照探针置于场景中,必须使用已附加光照探针组 (Light Probe Group) 组件的游戏对象。可从菜单 Component > Rendering > Light Probe Group 添加“光照探针组”组件。
可将“光照探针组”组件添加到场景中的任何对象,但最好将其添加到新的空游戏对象。
光照探针组有自己的编辑模式 (Edit Mode),可开启或关闭此模式。要添加、移动或删除光照探针,必须按 Edit Light Probes 按钮来开启光照探针组的编辑模式:
使用编辑光照探针 (Edit Light Probes) 模式时,可按照与游戏对象类似的方式来操作单个光照探针,但是单个探针不是游戏对象,它们作为一组点存储在“光照探针组”组件中。
开始编辑新的光照探针组时,将从一个立方体中排列的八个探针的默认编队开始,如下所示:
现在可以使用光照探针组 (Light Probe Group) 检视面板中的控件向该组添加新的探针位置。探针在场景中显示为黄色球体,这些球体可按照与游戏对象相同的方式定位。还可以使用常规的“复制”键盘快捷键 (ctrl+d/cmd+d) 来选择和复制单个探针或按组进行这些操作。完成探针的编辑后,关闭光照探针组编辑模式,否则无法移动或操作常规对象。

选择光照探针位置

与通常在对象表面具有连续分辨率的光照贴图不同,光照探针信息的分辨率完全由放置探针的紧密程度决定。
为了优化光照探针存储的数据量以及游戏在进行时完成的计算量,通常应尝试尽可能少量放置光照探针。但是,在可以接受的范围内,建议放置足够多的探针记录一个空间到另一空间的光线变化。这意味着,在具有复杂或高对比度光线的区域周围可提高光照探针的放置密度,而在光线没有显著变化的区域可降低它们的放置密度。
在以上示例中,建筑物附近和之间的对比度和颜色变化较大,因此探针放置得较密集,而沿着道路的光照没有显著变化,因此放置密度较小。
定位探针的最简单方法是将它们排列成常规 3D 网格图案。虽然此设置简单有效,但可能会消耗不必要的内存,并可能有大量冗余的探针。例如,在以上场景中,如果沿着道路放置大量探针,将会浪费资源。光照沿着道路的长度不会发生太大变化,因此许多探针将大多数相同的光照数据存储到相邻探针中。在此类情况下,通过在稀疏探针之间插入此光照数据,效率会高得多。
光照探针不会单独存储大量信息。从技术角度来看,每个探针都是来自采样点的球形全景 HDR 图像,使用存储为 27 个浮点值的球谐函数 L2 进行编码。然而,在具有数百个探针的大型场景中,这些探针可以累加,而设置密集度过高的探针可能导致游戏中大量内存浪费。
即使游戏位于 2D 平面上(例如,在路面上行驶的汽车),光照探针也必须形成 3D 体积。这意味着探针组中至少应有两个垂直“层”的点。
在以下示例中,在左侧看到探针仅排列在地面上。因为光照探针系统无法从探针计算明显的四面体体积,所以这种排列方式不会产生良好光照。在右侧,探针排列为两层,一些低至地面,另一些高于地面,因此它们一起形成由大量单个四面体组成的一个 3D 体积。这是一种良好的布局。

放置光照探针以实现动态 GI

Unity 的实时 GI 允许移动光源针对静态景物投射动态反射光。但是,使用光照探针时,还可从移动游戏对象上的移动光源接收动态反射光。
因此,光照探针执行两个非常相似但不同的功能:它们存储静态烘焙光源,并在运行时代表动态实时全局光照(GI 或反射光)的采样点来影响移动对象上的光照。
所以,如果要使用动态移动光源,并希望移动游戏对象上有实时反射光,这可能会影响放置光照探针的位置以及将它们分组的密集程度。
在这种情况下要考虑的要点是,对于大面积范围内相对不变的静态光源,因为光照不会在大面积范围内变化,只需放置少数几个探针。但是,如果计划在此区域内使用移动光源,并且希望移动对象用来接收反射光,则需要在该区域内建立更密集的光照探针网络,以便有足够高的准确度来匹配光源的范围和样式。
放置探针需要的密集程度因光源的大小和范围、其移动速度以及希望接收反射光的移动对象的大小而异。

光照探针放置问题

对光照探针位置的选择必须考虑到光照将在探针组之间进行插值的情况。如果探针不能充分适应场景中光照的变化,可能会出现问题。
以下示例显示了一个夜间场景,两侧有两个明亮街灯,中间有一个暗区。如果光照探针仅放置在街灯附近,而在暗区中没有放置,则街灯的光照将跨越黑暗间隙“渗透”到移动对象上。这是因为光照会从一个亮点插入到另一亮点,而没有关于暗区的信息。
如果使用实时或混合光源,此问题可能不太明显,因为只有间接光才会跨越间隙渗透。如果使用完全烘焙光源,问题会更明显,因为此情况下也会从光照探针插入移动对象上的直射光。在此示例场景中会烘焙两个街灯,因此移动对象从光照探针获得直射光。在下图中,可看到结果:一个移动对象(救护车)在穿过暗区时仍然获得明亮光照,这不是想要的效果。黄色线框四面体显示出,插值发生在街道明亮光照的一端与另一端之间。
这是不想要的效果:救护车在穿过暗区时仍然获得明亮光照,因为在暗区中没有放置光照探针。
要解决此问题,应该在暗区中放置更多探针,如下所示:
现在场景的暗区中也有了探针。因此,移动的救护车从场景的一侧移动到另一侧时,救护车上的光照更暗。
现在,救护车在场景中心时,车上的光照更暗,这符合要求。

用于移动对象的光照探针

光照贴图通过捕获逼真的反射光作为纹理(这些纹理将“烘焙”到静态对象的表面上)来显著增加场景的真实感。但是,由于光照贴图的性质,光照贴图只能应用于标记为 Lightmap Static 的非移动对象。
虽然实时和混合模式光照可在移动对象上投射直射光,但除非使用光照探针,否则移动对象不会从静态环境接受反射光。光照探针存储关于光在场景中如何反射的信息。因此,当对象在游戏环境中的空间内移动时,它们可以使用光照探针中存储的信息来显示反射光在当前位置处的近似值。
在上述场景中,当方向光照射到作为静态景物的红色和绿色建筑物时,反射光被投射到场景中。反射光在每个建筑物正前方的地面上显示为红色和绿色。由于所有这些模型都是静态的,因此所有这些光照都存储在光照贴图中。
将移动对象引入场景中时,它们不会自动接受反射光。在下图中,您可以看到救护车(动态移动对象)不受建筑物反射的红色光影响。实际上,它的侧面是单调的灰色。这是因为救护车是一种动态对象,可在游戏中四处移动,因此不能使用光照贴图(由于光照贴图本质上是静态的)。该场景需要光照探针,以便移动的救护车可接受反射光。
要使用光照探针功能将反射光投射到动态移动对象上,必须将光照探针放置在整个场景中,以便它们覆盖移动对象在游戏中可能通过的所有空间区域。
放置在场景中的探针定义了 3D 体积。然后,通过在烘焙到最近探针中的信息之间进行插值,位于该体积内任何位置处的光照将在估算后投射到移动对象上。
添加探针并在场景中烘焙光照后,动态移动对象将根据场景中最近的探针接收反射光。同样以上面的示例为例,动态对象(救护车)现在接受来自静态景物的反射光,使车辆的侧面呈现红色,因为它位于投射反射光的红色建筑物的前方。
选择动态对象后,Scene 视图将显示出正在使用的用于反射光插值的光照探针。最接近动态对象的探针用于形成四面体,而动态对象的光照便从该四面体的四个点的值进行插值。
当一个对象在场景中移动时,它从一个四面体移动到另一个四面体,并根据其在当前四面体内的位置计算出光照。

光照探针和网格渲染器

要在移动的游戏对象上使用光照探针 (Light Probes),必须正确设置该移动游戏对象上的网格渲染器 (Mesh Renderer) 组件。Mesh Renderer 组件具有 Light Probes 设置,此设置在默认情况下设为 Blend Probes。这意味着,在默认情况下,所有游戏对象都将使用光照探针,并在场景中改变位置时在最近的探针之间进行混合。
您可以将此设置更改为“关闭”或“使用代理体”。将光照探针设置切换为关闭状态将禁用光照探针对此游戏对象的影响。
光照探针代理体 (Light Probe Proxy Volumes) 是一种特殊设置;如果大型移动对象可能太大而无法通过光照探针组的单个四面体获得明显光照,而是需要在模型的整个长度上由多组光照探针进行光照,则可使用这种设置。
Mesh Renderer 检视面板中与光照探针相关的另一个设置是 Anchor Override 设置。如先前所述,当游戏对象在场景中移动时,Unity 会根据光照探针组定义的体积计算该游戏对象所在的四面体。默认情况下,这是从网格包围盒的中心点开始计算的,但是您可以通过将其他不同的游戏对象分配给 Anchor Override 字段来覆盖使用的点。
如果为此项分配了其他不同的游戏对象,则可按照网格上的光照需求自由移动该游戏对象。
当游戏对象包含两个单独的相邻网格时,锚点覆盖 (Anchor Override) 可能很有用;如果这两个网格都根据自身的包围盒位置而单独获得光照,则光照在它们的连接处将不是连续的。为防止该问题,可使用相同的变换(例如父对象或子对象)作为两个网格渲染器的插值点,或者使用光照探针代理体。该组件至少需要 Shader Model 4 图形硬件和 API 支持,包括对具有 32 位浮点格式和线性过滤的 3D 纹理的支持。要正常工作,场景需要通过光照探针组组件来包含光照探针。如果未满足要求,则渲染器或光照探针代理体组件检视面板将显示一条警告消息。
Tags:
尹煜
北京宏宇航天技术有限公司Unity工程师 - Programmer
31
Comments