查看原文
其他

预计算实时GI (完)集群和微调光照贴图参数

2017-02-26 Unity官方 Unity官方平台

目前为止我们已经围绕预计算实时GI的光照图讨论了多方面内容,例如缝合或打包技巧等关于优化及简化光照图的流程,这对减少预计算所生成的信息大小以及改善运行时性能有很大的帮助。您可以点击下面的链接回顾之前的内容:


(一)介绍

(二)实时分辨率

(三)了解光照图

(四)光照探测

(五)UV展开与减少光照图数量


本文是预计算实时GI系列的最后一篇文章,我们一起来学习如何微调影响场景物体的光照贴图分辨率及精确度,以便对视觉效果影响较小的物体适当降低其预计算的消耗。

集群的概念


在学习之前,我们先来了解一下集群的定义与用法,以及它对全局光照的影响,以便后续更好地理解。


修改集群(Cluster)是减少Unity预计算流程所需执行的工作数量的好方法。与此同时,降低集群数量也能提高运行时的性能。当采用PRGI来计算场景光照时,Unity对生成静态场景立体像素化结构的计算进行简化,这些体素叫做集群。集群实际上是映射到用于照明的静态几何体表面的小贴片,以一种层级关联的结构存储,用来预处理漫反射全局光照的复杂辐射度计算。虽然集群和光照图的映射方式很像,但两者是各自独立的。



场景视图的Clustering绘制模式下可以查看预计算实时GI所计算出的集群大小。集群会对其被映射到的静态物体的反射率(Albedo)进行采样,然后在预计算的Light Transport阶段计算这些集群间的关联,以便让光照在整个集群网络之间进行传送。Unity生成静态场景近似的低分辨率环境,以便简化在运行时需要更新的光照数据量,从而在保证帧率的情况下传送全局光照。

集群X的光照值与附近的集群值之间的关联(本图由Geomerics提供)

 

一旦预计算完成后,就可以修改环境光(Skybox)及光照位置、强度和颜色,不需要再重新进行预计算。更新后的光照会通过集群网络,将场景的反射率和自发光材质一并考虑进来以计算最终的光照反射结果。

 

第一次反弹之后的光照结果会被应用到集群里,在每次迭代后集群会被采样到相应的光照贴图纹理,最后供场景中的Shader使用。

 

由于这个过程在CPU上异步执行,每次更新全局光照所花的时间取决于可用的工作线程。如果需要,可以通过Lighting视图的“CPU Usage”来设定工作线程的数量。 



场景视图的Lit Clustering绘制模式下显示出当光线通过集群网络反弹到集群中的样子。可以通过场景视图的Clustering或Lit Clustering绘制模式来查看集群的分布,在Clustering模式下,场景会覆盖一层由许多彩色方块组成的诊断图,每个方块大小表示映射到静态几何体的集群大小,每种颜色代表场景中不同的集群;Lit Clustering模式也类似,它显示当光照通过集群网络反弹到集群并将光照反射结果反映到集群里的样子。

 

降低集群的数量在很大程度上决定了更新的速度,也因此决定了Unity预计算实时GI在目标平台的最终效果。我们发现,减少集群数量将会加速预计算光照,而且就结果来看,设置场景光照的迭代速度也会提升,所以减少集群数量是十分有意义的。


光照贴图参数


Unity通过光照贴图参数(Lightmap Parameters)提供了许多高级的光照贴图控制方法,这些设置被存储在一个光照贴图参数(Lightmap Parameters)资源里,以便不同场景或团队协作环境下可以通过版本控制共享光照设置。您可以通过以下三种方法建立光照贴图参数(Lightmap Parameters)资源:

  • 方法一:打开Project视图,从Project视图左上方的Create下拉列表中点击Create > Lightmap Parameters。

  • 方法二:在Project视图中按右键弹出菜单,选择Create > Lightmap Parameters。

  • 方法三:依次点击编辑器顶部菜单(Asset > Create > Lightmap Parameters)。


光照贴图参数可以针对烘焙GI或预计算实时GI进行高级设置

 

接下来可以将创建完成的光照贴图参数集指定给Static MeshRenderer组件,具体操作步骤如下:

  • 从Hierarchy视图选择要指定光照贴图参数资源的对象,请注意,该对象必须带有Mesh Renderer组件且标记为静态。

  • 打开Lighting界面(Window > Lighting)并选择Object标签页。

  • 从Advance Parameters下拉列表赋值光照贴图参数集给组件,点击右边的”Edit"按钮可以快速开始编辑光照贴图参数。



如上图所示,我们可以从Lighting界面Object标签页中Advanced Parameters字段的下拉列表指定光照贴图参数集。同一个光照参数集可以赋值给多个不同的组件,只需从Hierarchy视图一次选定所有需要赋值的Object,执行上面说明的步骤将资源赋值到Advanced Parameters字段即可。

 

那么光照贴图参数集应该赋值给实例(per-Instance)还是预制件(per-Prefab)?UV展开设置类似,光照贴图参数集可以赋值给预制件(Prefab)或场景中的独立对象,一旦光照贴图参数集被赋给场景中的预制件实例就会覆盖掉预制件原有的设置。这个方法的好处是可以将正常情况下会用到的光照设置放在预制件中,然后依照不同需求修改并覆盖场景里实例对象上的光照贴图参数设置。

 

下面我们以实例对象来示范一下如何应用光照贴图参数集,这样就可以根据对象所在的不同环境来选择不同的光照贴图参数集。


默认参数集


配置场景通用的默认光照贴图参数集将被赋给场景中所有带有Mesh Renderer组件但还未指定Lightmap Parameters的对象。场景中任意新建的带有Mesh Renderer组件的对象都将被赋予该默认参数集,这样可以省下手动赋值的时间。具体操作步骤如下:

  • 打开Lighting界面(Window > Lighting)并选择Object标签页。

  • 找到General GI区域下的Default Parameter,选择刚才创建的光照贴图参数集。

 

虽然新建的对象会应用这个默认设置,但仍可以从Advanced Parameter参数中单独设置。


默认设置会应用到所有新建的带有Static Mesh Render组件的对象

 

Unity提供了几组默认的光照贴图参数集:

  • Default - HighResolution

  • Default - Medium

  • Default - LowResolution

  • Default - VeryLowResolution

 

这些不同的默认参数集中配置了会影响到选定对象整体光照开销的设置,包括光照贴图分辨率、全局光照参数、集群分辨率以及其他一些高级设置选项。这些设置对平衡整个场景的光照性能来说至关重要。


光照贴图集参数说明


Unity的默认参数集已经覆盖了大多数常见用例,并且对大多数光照场景都适用。但更好地掌握预计算实时GI系统可以帮助我们创建自己的参数集,进行更多控制。Unity手册上有提供关于光照贴图参数集所有默认设置的说明,下面会重点说明几个对光照优化最有用的设置。


分辨率

分辨率(Resolution)的值决定了使用该光照贴图参数集的对象所需的光照贴图分辨率,这个值会与Lighting界面里场景全局的分辨率相乘。例如,如果场景实时分辨率设为2,这里的Resolution属性设为0.5,那所有带有这个参数集的对象都会采用1 texel/unit来计算光照贴图纹理。

 

由于PRGI(预计算实时GI)只会呈现场景里的漫反射(Diffuse)和间接照明,所以我们不需要用到像传统烘焙贴图那么高(20-30)的采样值,PRGI通常设定为2-3就已经很好了。大多数情况下,尤其是户外场景如地形等,甚至可以缩小很多倍。如下图所示的光照贴图分辨率就是0.1 texel/unit,已经可以提供足够多的细节。 



分辨率很大的光照贴图所产生的影子斑点可以通过调高Irradiance Budget这个参数来缓解。需要注意,使用高分辨率光照贴图时,可能会出现使用低分辨率时不能发现的缺陷。这些阴影在最终的光照贴图纹理中可能看起来像是斑点或污迹。如果出现这种情况,可以试着调高Irradiance Budget参数进行改善。


集群分辨率

集群分辨率用来决定1个像素里能有多少集群数量。假如这个值设为1,代表光照图里面每个像素都会有一个集群,0.5代表一个像素会有2个集群,换句话说集群会是一个光照图的两倍大小。

 

进一步来说,可以想像如果将场景的分辨率设为1,并建立一个1x1x1的立方,然后将这个光照参数集赋给立方,那么立方的每一面都会有1个集群。如果将分辨率改为2,结果立方每一边的集群数量就会变为2倍,每面的集群会变成4个。



上图表示实时分辨率设为1的1x1x1方块,光照参数设定集群分辨率(Cluster Resolution)为1 Cluster/texel和光照贴图分辨率为2 texel/unit时,方块每一面都会有4个集群。在大多数的情况下,集群分辨率(Cluster Resolution)只需要设为低于光照贴图像素(lightmap texels)大小即可,例如Unity默认的光照贴图设置Default - HighResolution,就将Cluster Resolution设为0.6。

 

如本文第一节所述,一个场景中集群太多的话会加长预计算时间,还会影响到运行时的场景全局光照。因此必须要确保增加的集群数量可以显著提高光照贴图的品质,如果减少集群数量对光照贴图并没有太大影响,那就尽可能地减少集群数量。

 

让光照贴图分辨率和集群分辨率成比例,这样就可以和场景整体的实时分辨率建立一个相关关系。我们可以将Lighting界面中定义的分辨率作为场景整体的高级分辨率,然后针对个别对象或对象组对各自的光照贴图参数集进行微调。Unity采用这种分层法可以为开发者提供更方便的全局控制,不然对每个对象都手动设置光照贴图参数的值会很麻烦。


Irradiance Budget

本文开始的时候有介绍过Unity如何利用集群来生成近似的场景静态几何体以计算预计算实时GI。在预计算过程中已计算好集群之间的关系,以便光照可以在分层网络内快速传递。


本质上,光照贴图的像素值取决于从该像素的位置能“看到”场景集群的数量,这样可以很快计算出光照在集群之间的反弹以生成全局光照的效果,这些集群就能在最终渲染之前被适当进行采样。

 

Irradiance Budget决定每个光照贴图像素采样集群网格时所使用的内存量,这会决定光照结果的精度。Irradiance Budget数值越低表示每个贴图像素在记录场景信息时使用的内存越少。减少内存的同时也降低了运行时的CPU开销,但代价就是损失光照精确度,数值越低光照结果会越模糊。反之,Irradiance Budget数值越高则GI结果越精确,但相应的内存用量和CPU消耗都会提升。

 

如果预计算实时GI在运行时更新较慢或者有延迟,可能减小Irradiance Budget值会得到改善,这个设置比较适用于不太注意到的对象,如很大、模糊或遥远的几何体。


Irradiance Quality 

当计算PRGI时,每个光照贴图像素会开始对场景投出射线,以收集附近集群的可视信息。然后计算出贴图像素可以看到的每个集群的百分比,这个值用来定义光照贴图里每个像素从集群所分到的可视数据,而Irradiance Quality就是用来指定每个像素能对场景投射的射线数量

 

如果场景里的物体和周围环境光照不合的情况下可以适当加大这个值,有时本该较暗的光照结果却意想不到得亮,有可能是因为投射到场景的射线不足或被遮挡,导致漏计算了集群信息。同样本该亮的地方如果射线没有被检查到,可能会造成过暗的结果。

 

增加射线的投射量就能解决类似的问题,其代价是增加预计算的时间。想要优化这个时间,就应该找出最适合的值来达到理想的照明效果。请注意,这个值不会影响到运行时的性能。


Backface Tolerance 

当射线从光照贴图像素投射出时,从场景的集群搜集光照信息时偶尔会打到几何的背面,当计算全局光照时仅关注投射到物体表面的光照,从背面来的光照信息通常都会被忽视,这些从背面来的光照信息会破坏光照结果,因此调整这个值能防止出现这类情况。



这里的地板上的阴影就是Unity在计算辐射度时,射线投射到物体无效的背面所生成的,增加Backface Tolerance的值能改善这个问题。Backface Tolerance指定必须从物体前方来的光照百分比,以便正面的贴图像素被判定为有效。假如贴图像素未通过测试,Unity会采用邻近的像素值来估算正确的光照结果。

 

调整Backface Tolerance并不会影响PRGI的性能,也不会对预计算时长有太大影响。如果调整Irradiance Budget也无法解决场景贴图太亮或太暗的问题时,Backface Tolerance会是很有用的解决办法。


Modelling Tolerance

有时在场景静态物体中存在小间隙的区域会产生黑色的光晕或预期外的残像,这种情况会出现在旁边有相反几何体的区域,像是地板上的组件,如下图所示。


物品的黑暗边缘通常可以通过加大Modelling Tolerance来改善

 

通常在这种情况下,物体之间存在较小的缝隙,因为没有太多光线可以进入,导致产生非常暗的光照图。当光照贴图分辨率较低时,这些黑暗像素的大小可能会导致它们超出遮挡物的边界并产生不协调的黑色块。

 

Modelling Tolerance用于忽略比Threshold值还小的细节,提高Modelling Tolerance值可以确保Unity在计算GI时忽略掉非常靠近其它物体表面的几何面,Modelling Tolerance值越高代表预计算的Light Transport阶段将忽视这些小于光照贴图纹理像素百分比的间隙,调低Modelling Tolerance可以确保小物体不被GI计算遗漏。

 

Modelling Tolerance不会影响PRGI的优化,对预计算时间和运行时性能也没什么负面影响,它能用在一些除错流程上,解决连调整Irradiance Budget或Irradiance Quality都无法改善的残影问题。


开始建立光照贴图参数资源


您现在已经了解光照贴图参数能做什么了,接下来一起看一下建立光照贴图资源、微调光照贴图资源参数和为其他物体指定光照贴图参数集的方法。


创建资源

下面我们可以开始尝试创建这些资源,具体步骤如下:

  • 打开LightingTutorialStart场景。

  • 从Project视图中找到Assets > LightmapParameters目录。

  • 在Project视图上方依次点击Create > Lightmap Parameters新建一个光照贴图参数集。

  • 将新建的Lightmap Parameters命名为"TutorialTerrainLow"。



本例中我们考虑上图中的山型物体,从相机镜头看起来大且远,比较适合设置光照贴图参数集而非使用场景默认的设置。

 

下面将刚才新建的光照贴图参数集指定给该物体:

  • 在场景视图选择最接近主场景的两座山,这些山都已经被命为"MountainPeak"。注意,我们将忽略最远的山。

  • 在检视面板(Inspector)中确保将两个物体都设为静态。

  • 打开Lighting视图(Window > Lighting)并选择Scene标签页。

  • 确保勾选最下方的Auto。

  • 选择Object标签页。

  • 在Advanced Parameters下拉列表中选择刚创建的TutorialTerrainLow。

  • 点击右边的Edit按钮,准备开始调整设置。


默认的光照贴图参数集设置

 

参数调整 — Resolution

第一个参数是分辨率(Resolution),降低这个值可以减少预计算时长同时提升运行时性能,所以应该在不影响画质的前提下采用较低的分辨率。对于离相机镜头很近的物体可以设置比较高的分辨率,但这里两座山距离镜头都非常远,因此本例中将该值设低一点更合适。 这些大物体表面材质的反射率相当一致,从镜头的角度来看,接收到光的颜色变化也不大,由于不需要获取更多光照细节,所以降低这个值并不会影响光照结果的品质。


像山或地形这样的大场景,光照贴图分辨率采用默认值反而很浪费


使用较低的分辨率会稍稍牺牲一点品质,但可以大大节省预计算时长并提高运行时性能


  • 尝试缓慢调低TutorialTerrainLow光照贴图参数集里面的Resolution参数并观察结果的变化。


请记住,这里的分辨率和Lighting视图中的场景分辨率是会相乘的,目前场景分辨率是1,代表如果这里分辨率小于1,输出的光照贴图每个单元也会小于1纹理像素(texel)。两座山和其它物体距离非常远,所以它们不可能接受很细节或是频率很高的光照,也就是说如果采用较低的分辨率也不会牺牲太多品质。我们发现在示例场景中使用0.05就足以获取。


  • 在Project视图中选中TutorialTerrainLow资源。

  • 在检视面板中将Resolution设为0.05。

 

参数调整 — Cluster Resolution

然后来看看集群分辨率(Cluster Resolution)的值,这个值也是一个用于和光照贴图像素数量相乘来计算集群的乘法器,当数值为1时集群数量就等于光照贴图像素数量,因此低于1会比较好。集群本质上是为了计算PRGI所生成的类似静态场景的模拟体,所以只有在数量不足以反映物体的光照反射时才需要加大这个值。

 

这两座山的集群分辨率与光照贴图分辨率类似,也可以设为很低的值,如果将其设为场景默认的分辨率来设置集群数量,就表示可能会需要几百个小场景的集群量来覆盖这两座山。 



  • 对于很大且离相机较远的物体,集群分辨率可以设很低。

  • 将场景视图左上方的绘制模式改为Clustering

  • 从Project视图选择TutorialTerrainLow光照贴图参数集

  • 从检视面板中缓慢调低Cluster Resolution的值,会发现彩色色块慢慢变大,数量则会慢慢变少

 

另外,在Lit Clustering绘制模式下可以评估设置的分辨率是否足以采样场景的光照细节,具体方法如下:

  • 将场景视图左上方的绘制模式改为Lit Clustering

  • 从Project视图选择TutorialTerrainLow光照贴图参数集

  • 从检视面板中缓慢调低Cluster Resolution的值,观察场景的变化。

 

调整Cluster Resolution的值时,可以看看是否能接受更低的集群数值,如果继续调高对画质已经没有明显改善了,那就应该使用更少的集群数。请记住,集群数量对于预计算时长和GI的运行时性能有很大的影响,本例中使用0.4较为适合:

  • 从Project视图选择TutorialTerrainLow光照贴图参数集

  • 将Cluster Resolution设为0.4


Lit Clustering绘制模式可以用来评估场景中的集群数量是否足够

 

大多数情况下,仅需降低光照和集群的分辨率就可以提升很大的性能,但还可以利用Irradiance Budget和Irradiance Quality做进一步改善。


参数调整 — Irradiance Budget 

首先看看Irradiance Budget,如之前所说,这个值控制贴图像素在计算时所占用的内存,为了运行时性能,我们应该使用最低的值以免带来负面影响。如果预计算的结果模糊不清,可以试着调大这个值,对于场景中对比度较高却没有被精确表现出来的区域是很有用的。


Irradiance场景绘制模式可以用来评估调整Irradiance Budget或Quality的值

 

两座山接收光照的频率较低,也没有任何高对比的光照处理,这表示在不影响品质的情况下,和可以将默认值128调到更低:

  • 将场景视图左上方的绘制模式改为Irradiance

  • 从Project视图选择TutorialTerrainLow光照贴图参数集

  • 从检视面板里把Irradiance Budget的值慢慢降低

  • 当减少这里的值时,两座山上的照明会变得柔和一点

 

经过一些实验之后,本例中将Irradiance Budget设为64最合适:

  • 从Project视图中选择TutorialTerrainLow光照贴图参数集

  • 在检视面板中将Irradiance Budget的值设为64

 

参数调整 — Irradiance Quality

现在来看看另外一个Irradiance Quality,如之前所说,Irradiance Quality影响计算光照像素时从集群所投射出来的射线数量,不像Irradiance Budget那样只会影响到预计算时间,这个设置会影响到运行时性能。

 

本例中的两座山是非常大的物体,这表示它们不太容易错过邻近的集群,因此可以通过降低Irradiance Quality值来提升预计算的性能:

  • 将场景视图左上方的绘制模式改为Irradiance

  • 从Project视图中选择TutorialTerrainLow光照贴图参数集

  • 在检视面板中缓慢调低Irradiance Quality的值

  • 随着值越小,生成的光照贴图会变得越来越模糊


本例中2048是一个既能保持想要的品质又能提升计算性能的平衡点,虽然精确度会稍有损失,但整体来看是利大于弊的:

  • 从Project视图中选择TutorialTerrainLow光照贴图参数集

  • 在检视面板中将Irradiance Quality的值设为2048

 

为其它物体指定光照参数集

下面可以为LightingTutorialStart场景中其它的静态物体创建并指定光照参数集。之前讨论过一种比较好的做法,就是确定某种分类或模式来组织场景中的物体。基于物体的特征(例如大小或是与镜头的距离)将其分组,以便更容易地为物体指定光照贴图参数集。

 

在处理Environment组件下方其余的子物体时,请尽量让能够共享光照贴图参数集的物体分为同一类,例如:物体是否会很接近可玩区域及相机镜头。这种情况下如果为该物体提高光照贴图分辨率对于结果会有明显改善,如果是很远的物体就不需要设置相同的值,如果物体材质的反射率没有太大的区别,也没有必要设置高分辨率。物体分组不需要太细,对于大多数情况下,几组差异性大的设置就够了,分太细也不便于管理,可能每个细节都要针对物体独立修改。

 

在已完成的场景LightingTutorialOptimal中,我们分组依据如下:

  • RockLow:距离镜头较远的光滑石头,因为距离远所以光照贴图分辨率低。

  • RockMedium:光滑石头,更接进可玩区域,所以需要设置高一点的光照贴图分辨率。

  • StructuresHigh:需要高分辨率呈现的重要建筑物,同时也需要更高的Irradiance Budget和Quality设置。

  • StructuresLow:远距离的建筑物,只需要低分辨率设置。

  • TerrainLow:大型网格且距离相机远,比如山,不需要高分辨率

  • TerrainPlayable:比较靠近镜头的大型地形,需要一个光照贴图分辨率来平衡,降低大地形的集群数量也较为合理

  • TerrainVeryLow:非常遥远且部分被遮挡的地形,分辨率和集群数量均很低,Irradiance Budget和Quality也都很低

 

除了这些自定义参数之外,在已完成的示例场景LightingTutorialOptimal中,还包含一些使用默认光照参数的结构,这里用的是默认设置Default-Medium。使用场景中大多数静态物体默认的参数集可以减少很多手动的工作,将常用值指定为默认参数设置会很有帮助,对于本例,Default-Medium和默认为1像素的分辨率搭配使用较为合适。



Irradiance绘制模式用来评估场景照明非常有用,因为它只会显示对PRGI有贡献的静态物体光照结果。

 

当决策场景光照的赋值与配置时,可以用LightingTutorialOptimal作为一个评估基础,将光照贴图参数集指定给场景的物体不会花费太久的时间。记住,当设置这些组件时,要不断的考虑调高参数值所带来的好处有多少,如果调低参数带来的负面影响不大,那就要优先选择较低的参数值。


总结


优化场景光照的用意与游戏开发的许多方面一样,就是希望在性能和视觉效果之间找到一个完美的平衡,在大多数情况下,牺牲少量的光照精确度来加快预计算时间以及改善运行时性能是很值得的。处理好整个场景的预计算之后就不需要额外计算不同时间的光照,这种效果使用传统的烘焙光照是不可能达成的。


恭喜您已经阅读完所有预计算实时GI有关内容!经过这几篇文章的学习,您已经了解到如下内容:


将所有这些技术结合再一起就能用最少的预计算时间高效实现产品级别的光照效果,再结合Unity快速迭代实时将光照更新到GI以及实时改变光照反射的能力,Unity引擎是大多数应用实现预计算实时GI解决方案的不二之选。希望您喜欢!想要了解更多技术文章,请访问Unity官方中文社区(forum.china.unity3d.com)。


更多Unity预计算实时GI相关文章

Unity预计算实时GI(一)介绍

Unity预计算实时GI (二)实时分辨率

Unity预计算实时GI (三)了解光照图

Unity预计算即时GI (四)光照探测

Unity预计算实时GI(五)UV展开与减少光照图数量


近期活动


活动一:2017 Unity技术路演 — 华南站将于3月6日开启,仅剩7天!报名从速。详情请关注2017 Unity技术路演正式启动,3月华南区报名开启


活动二:Unite 2017 Shanghai将于5月11 - 13日在上海国际会议中心举行!不到5折的超值早鸟票现已开售!详情请关注“再一次问候” - Unite 2017 Shanghai 正式开启



点击“阅读原文”访问Unity官方中文社区!

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存