初步介绍

新年假期结束了,想不想掌握一个新技能迎接全新的一年呢?不妨来阅读一下Unity预计算实时GI系列文章。本文是该系列的第一篇。

在Unity中有两种区别很大的技术被用于计算全局光照GI或光源反射,它们就是烘焙全局光照(Baked GI)和预计算实时全局光照(Precomputed Realtime GI)。本文主要介绍预计算实时全局光照(PRGI),学习如何使用Unity全局光照计算系统 — Enlighten系统来优化一个场景,让预计算只需要几分钟而非几小时。

为什么要使用PRGI
当启用PRGI时, 光照预计算指的是计算静态几何对象周围光的反射,并存成数据给Runtime执行使用的过程 。这个过程减少了原本必须在Runtime执行时的光照计算量,可以让项目在保持FPS稳定的同时,还允许使用实时反射光照。

当启用烘焙GI(Baked GI)时,预计算的过程会计算并产生传统的光照贴图(Lightmap),这些贴图会以资源(Assets)的形式存在项目中,但是无法在Runtime执行时被更改。而PRGI则是使用不同的方法生成光照贴图, PRGI计算的结果会被存成光照数据文件(Lighting Data Asset),这些数据可以在Runtime执行时实时产生和更新一组低分辨率的光照图。

不过,除非场景已经为PRGI计算优化过,否则完成这些计算所需的时间可能会很长。下面我们一起来看一下如何针对Enlighten系统来做场景优化,从而把预计算时间从几小时缩小到几分钟。我们将会涵盖以下几个要点:

如何定义适合当前场景的光照分辨率
了解什么是光照图(Charts),以及它是如何影响计算时间的
如何开始预计算
使用光照探针来降低光照方案的复杂度
改进由Unity PRGI自动拆解出的UV
了解何谓集群(Clusters),以及如何用它来产生GI照明
了解如何使用光照贴图参数来微调单个游戏对象上的光照

一旦我们学习并了解了这些技术,我们就可以充分利用PRGI的优点: 快速的光照迭代,以及在打光过程中和在游戏过程中对实时反射光照进行快速试验的能力 。

PRGI优化演示
在下图所示的场景里,用没有优化过的默认设置,在我们的测试机上预计算光照大约花了7.5个小时。显然这是无法接受的!

无优化场景(上图) :预计算7.5小时,有优化场景(下图):预计算2.25分钟

使用本教学所介绍的技术进行大约30分钟的场景准备后,这个场景的预计算仅仅花了2.25分钟就得到了产品等级的效果。这个技术的好处是显而易见的,因为我们可以在游戏过程中快速迭代场景照明而不需要重新计算GI和改变GI照明。

学习前准备
您可以在 Asset Store资源商店上下载官方光照优化素材包 ,跟着我们进一步学习。本教学所用的是Scenes/Article目录下的范例场景:

LightingTutorialOptimal:展示PRGI如何设定能用最短的时间呈现出产品等级的结果。
LightingTutorialNonOptimal:呈现了我们在项目中常看到的问题,要么造成无法烘焙,要么花费无法接受的时间烘焙,这是一个很好的错误示范。
LightingTutorialStart:我们在教学过程中用到的场景,我们会按照步骤一步一步将它变成一个产品等级的结果。

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


我们已经在《Unity预计算实时GI (一)介绍》中聊到Unity预计算实时GI的必要性和学习准备,并且了解到实现这个过程需要考虑的问题。本文我们对如何定义一个适合场景的光照分辨率进行了相关介绍,一起来学习一下吧!

如何调整实时分辨率?
当使用PRGI来计算场景照明时,首先要做出的决定之一是确定场景的实时分辨率(Realtime Resolution),因为它决定每个世界单位所使用即时光照的贴图像素数量。Realtime Resolution设定可以在Lighting窗口中找到并调整,方法如下:

Unity的Lighting窗口:主要显示整个场景会用到的光照设定。
  • 通过Window > Lighting菜单,开启Lighting窗口,并选择Scene标签页。
  • 确保Precomputed Realtime GI选项打上勾,在它下面找到Realtime Resolution属性,即可设置它的值。

但这个分辨率应该如何设置呢?

选择适当的分辨率
在设定场景时,首先要要了解你的项目使用的单位比例,可能在你的项目里一个单位等于现实世界的1米、一英尺或一公分。Unity没有默认真实世界的单位,所以要由开发者自行决定。

在这个范例里我们采用1 unit(单位) = 1 meter(米)。因为这和Unity的物理概念不谋而合。举例来说Unity的重力预设就是以每秒多少单位来计算的,因此设定1单位 = 1米对于一个真实世界的场景来说是恰当的。

Realtime Resolution的值通常可以由游戏世界的规模来制定。例如,你的场景是一个拥有丰富光照变化的室内环境。在这种情况下,高一点的值比如2 - 3,可以捕捉到更详细或"高频"的光照。

如果你的场景是一个规模较大的户外环境,可能覆盖了几百甚至上千单位(平方米)的表面,而这些表面并不会剧烈地改变反射光的颜色。在这样的情况下,把适合计算复杂室内场景的设定用在有大量相同特征的室外环境是很浪费的。我们会浪费宝贵的CPU时间和内存去更新那些对整体外观贡献不大的光照贴图。为了教学目的,我们会提高PRGI计算期间必须考虑的光照贴图的像素数量,这会对预计算的时间造成很大的影响。针对室外环境,可以为场景中尺寸较大的游戏对象设置0.5 - 1的texel,针对地形可以设置0.1- 0.5的texel。

Unity PRGI所需要的Realtime Resolution值比传统光照贴图密度要小好几个等级,这是因为我们只从这些光照图里获取间接光数据,且这些数据通常分辨率都很低。所以使用PRGI时,清晰的阴影通常都是通过实时运算而非高分辨率的光照图来提供的。

在这里使用传统光照惯用的值,例如:30 texels,可能会导致预计算失败或无法计算。室内场景比较适合的值是2 - 3,室外场景则是0.5 - 1。这是我们在使用1单位 = 1米的前提下,如果单位大小不同这些值就需要调整。

具体可以参考以下的场景与Realtime Resolution值对照表(1单位代表1米):

室内:2-3 像素/单位
户外:0.5-1 像素/单位
地形:0.1-0.5 像素/单位

当设定场景实时分辨率时,Unity会指定给场景内的静态对象。新建的带有Mesh Renderer且标记为静态光照(Lightmap Static)的对象,会使用这个值一直到它被其他设置修改。

除了帮场景加上分辨率设定外,我们还能针对每个对象调整光照贴图的分辨率,在需要高分辨率来提供更高真实感的情况下,我们可以选择性的提高这个值。通常是将场景里最多的对象分辨率设为默认值,然后手动调高需要更多照明细节对象的值。

练习一下
如果你想跟着做,打开教学素材包里的LightingTutorialStart场景。

在范例场景里,我们有一个户外环境,具有中等大小的地形与相当一致的色调。所以我们设定Realtime Resolution为0.5像素/单位就足以处理从场景其他对象来的光照反射。然而,场景里也有些贴图细腻的木屋。由于场景里有比地形对象还多的房子,我们应该把默认的分辨率设定为适合房子的数值。然后我们可以单独修改地形对象的分辨率,这样可以降低场景准备的工作量。考虑到这点,我们用1作为我们的默认分辨率,操作步骤如下:

  • 开启Lighting窗口(Window > Lighting) 然后选择Scene页签
  • 设定Realtime Resolution值为1

由于我们的世界单位设定为1单位 = 1米,这表示由PRGI所产生的光照图将会是1x1米的大小,或许你看起来很低,那是因为我们只抓取间接光照。还会从场景里的直接光源计算清晰的阴影和反光。

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


我们曾经为大家介绍了预计算实时GI的必要性,以及在实现预计算实时GI时,如何定义一个适合场景的光照分辨率。本文我们一起来看看光照图,了解一下它是如何影响计算时间的。

光照图是什么?
在Unity PRGI里,一个光照图(Chart)是表示一个光照贴图(Lightmap)的区域,用来映射场景对象的光照贴图UV。你可以认为它是能影响对象的一张瓦片图。一张光照图由两部分组成:辐照度(光照)和方向性(主要光线方向编码)。

当产生PRGI数据时,图表里的每个texel都会被计算光照。换句话说,场景里面有大量的光照图可能会增加PRGI耗时的主要原因之一,因此理解光照图的运作原理以及如何管理它们来优化光照计算的时间是很重要的。

光照图的尺寸

最小的4x4 texel的UV光照图
如上图所示,这是最小的4x4单位的UV光照图,为了防止贴图过滤造成的渗色,UV贴图始终被光照图包住并空出一半texel的宽度。

在预设的情况下,每张光照图最少要有4x4 texel的大小,所以说不管世界中的物体或对应的UV有多大,一张图表至少需要16个texel。因此如果有一个1x1米的对象并带有一个图表,间接分辨率是1,那这个对象就会需要16个texel来表现。最后Unity会将这些图表缝合在一起,作为模型边缘的光线取样参考。Unity需要每张图表的边缘至少有4个texel,方便在缝合不同光照图时有对照的依据。

要注意的是使用实时GI时不需要自己去填这些UV的边,因为Unity在处理网格汇入的流程时,会自动将光照UV图向内挤出一个边框的空间。这样就能让相邻的图表无需做渗色处理,也能保持双线性插值(Bilinearly Interpolated),能节省宝贵的光照贴图空间。


光照图如何影响计算时间?
要弄清楚这个问题,我们可以试想一下: 1x1对象如果带有50张光照图,Unity会为它创建800个texel。尽管这个数字看上去不是很大,但说明了当图表的量一大就会快速拉高texel的量。越多的贴图像素意味着更为繁重的光照运算要处理,更多的光照数据要计算、压缩和储存,这些因素都会提高场景的复杂度,并导致运行时长时间的计算和较低的效率。

不合理的光照图规划一般是导致计算耗时过长或无法完成的主因。也因为如此,我们许多减少计算时间的方向大多都是思考如何降低场景内光照图的数量。


Unity预计算实时GI (四)开始预计算


我们在先前已经为大家介绍了预计算实时GI有关的内容,从初步的介绍,到实时分辨率计算,再到光照图的认识,已经为预计算的实现打下了基础,下面就一起看看如何开始预计算吧!

计算全局光照需要启动PRGI流程,在开始预计算之前,我们必须确保场景里面至少必须有一个对象被标为静态(Lightmap Static)。

可以通过层级视图(Hierarchy)的功能,您可以轻松管理并选择哪些对象要用于计算光照。 管理这些对象有非常多的方法,但这不是今天教学讨论的目的。但这里需要,重点指出的就是:好的对象管理流程可以大大提升对象利用率。

在本文示例中,我们会将所有对象放在一个名为"Environment"的父对象下方进行管理,这个群组会放所有可见的,并且带有MeshRenderer组件,用来组成场景环境的静态对象。 在它下方还会有一些放有各种场景对象的子群组。

对场景中的对象进行分类有助于频繁重复选择对象的操作 

最好的做法是先从Lighting设置中确定初步大方向,然后边做边调整细节设置:
        •        选择场景里的"Environment"对象
        •        勾选检视面板(Inspector)右上方的Static
        •        如果系统跳出对话框,提示是否要将该对象下的子对象也一起标记为静态对象,请选择”Yes, change children"。 这样就能确保所有在Environment里的对象都变为静态对象并纳入光照计算。

现在场景内有了一些静态对象之后,我们就可以开始计算GI了,步骤如下:
        •        打开Lighting界面(Window > Lighting)然后选择Scene标签页
        •        确认勾选界面最下方的Auto(最下方Build按钮旁,如果打勾Build按钮会灰掉)
        •        然后系统就会开始计算光照。 画面的右下角会出现一个蓝色的进度条,显示目前的工作(几分之几)以及需要计算的工作量。
        •        如果未勾选Auto,也可以手动点击Build进行计算,系统会先询问是否要存档后开始计算光照。 本次教学建议直接勾选Auto即可。

 
进度条显示目前进度,并提示等待计算的工作量 

Unity预计算实时GI (五)光照探测


预计算实时全局光照(PRGI)是优化场景的一种手段,我们曾经详细介绍过它的必要性,定义适合当前场景的光照分辨率,以及影响计算时间的光照图的概念。本文我们聊聊如何使用光照探针(Probe Lighting)来降低光照方案的复杂度,这种方法非常适用于场景中的小物体,一起来一探究竟吧!

何谓光照探测
光照探测是一种快速计算实时渲染应用中的光照技术,通常会用于处理游戏世界的人物角色或是动态物体的光照,它的优点在于运行时有不错的处理性能而且预计算也相当快速。

光照探测的原理是通过放置在3D空间里的探针来接收光照信息,然后用类似球谐函数(spherical harmonics)的数学方法将信息编码在一个球体上。这些系数占用空间很小,在游戏运行时能快速”解包",以便Shader可以存取并计算表面光照,在Unity中这个功能叫做光照探针(Light Probes)。它是一种让对象接收场景间接照明的好方法,虽然被光照探针指定的对象无法计算场景的光照反射,但通常影响不大。

使用光照探测是有些限制的,其中一个限制:在不提高探针数量的前提下很难在球形范围上表现出高频或斑驳的光照,并且其精度和消耗成本成正比。也就是说,在考虑性能的前提下,必须限制使用较低阶的球谐函数。

实际上,一个3D坐标只能用一个球体来记录光照信息,所以光照探测不适合用于有大量光照投射在大物体表面的情况,所以不得不提到另外一个限制:当用球谐函数在一个球体上进行编码时,通常不擅于处理拥有特大平面的物体或是带有很深的凹洞的物体。如果想要将光照探测技术用于大型物体,可以参考Unity手册中Unity提供的另一个光照探测代理体(Light Probe Proxy Volumes, LPPV)技术做进一步了解。

尽管有这些限制,光照探测还是很适用于和符合条件的小物体一起搭配使用,以较低的成本消耗发挥出卓越效果。 我们后续将深入探讨如何设置及摆放光照探针(Light Probes),现在只了解适当使用光照探测功能可以降低光照贴图的数量。

为对象设置光照探针
尽管我们一般将环境里的对象都设置为静态后再做光照计算,但其实整个环境里有很多对象都适合用光照探测技术进行处理。减少场景里光照图的数量是加快预计算时间的关键,将对象的静态标签清除之后,它们不再受到PRGI计算的影响的同时,光照贴图的数量也会降低。

 
使用光照探测的最佳物体就是像这种凸起的小碎石

从Unity编辑器的层级视图(Hierarchy)看Environment下的子对象,会发现Props下的对象几乎都是点缀场景用的小物体,例如:石头、水桶或木板。 这些物体非常多,而且很多小物体的UV可能不太好展开。获取不失真的光照贴图UV可能会产生很多UV Shell,一旦UV Shell过多就会需要额外的光照图,更多的光照图代表将产生更多的贴图像素。

假设这些物体很小,不太可能对场景的间接照明产生什么影响,而且它们表面能显示的光照细节也有限,所以这样的物体非常适合用光照探测技术来计算,不但可以加速预计算时间,同时要存到内存中的光照图和Shader解码的数量也变少了,在运行时的性能也会因此提升。具体操作如下:

  • 从层级视图(Hierarchy)选择Props对象
  • 在检视面板(Inspector)中取消勾选最右上角的Static
  • 在弹出的提示框中,选择"Yes, change children"
这时等待计算完成,就能看到场景最终的光照计算结果,你会发现被探测光影响的非静态物体(non-Static objects)和周围的物体有些格格不入,和场景的光照也不匹配。 这是因为我们还未设置光照探针(Light Probes),导致这些物体被纳入环境探针(Ambient Probe)的光照计算。 环境探针本质上是一个在场景里无法看到的隐形探测器,只对Lighting视图中的Ambient Source所指定的来源进行采样。

 
在没有光照探针影响下,非静态物体的位置可能看起来有些异样

为了让非静态物体的摆放位置更为合理,我们需要花点时间来将光照探针放置在场景的周围,方便对世界中的间接照明进行采样。

放置光照探针
非静态物体会通过附近的光照探针接收光照信息,光照探针会基于探针之间的空间划分四面体,然后检查物体属于哪个四面体来决定物体"读取"哪个探针。 为了正确地产生这些四面体,探针之间的位置关系在3D空间里就必须要放得有体积感。


 
画面中那些白色的球体就是光照探针在场景里的样子

光照探测技术执行的消耗非常低,预计算也非常快。然而考虑到性能,也有些需要注意的地方:尽管设置简单,但密度太高的探针可能会浪费资源,因为太接近的探针在特定光照条件下的采样结果没什么差异。 最好的做法是在光照变化明显的区域放置密度较高的探针,例如由亮转暗的区域,或是强光反射的区域。设置光照探针的具体方法如下:

  • 从GameObject菜单新建一个光照探针群组(GameObject > Light > Light Probe Group)
  • 开始放置光照探针,从层级视图(Hierarchy)选择刚才新建的光照探针群组对象
  • 在检视面板(Inspector)中找到Light Probe Group组件,选择Edit Light Probes开始编辑
  • 可以从场景直接点选那些探针,留下角落的一个光照探针,其他可以全部删除
  • 将剩下的一个光照探针移到地形上方,然后按住Ctrl + D( Mac是按Cmd + D)键复制
  • 用移动工具(按W键)将复制的二号光照探针沿着Y轴往上约2米(2 meters)
  • 再复制一次光照探针,并将新光照探针的Y轴上移更高,约5米

 
Light Probe Group组件的Edit Light Probes按钮位置
这样的垂直光照探针分布为的是可以同时采样到地面、头部高度和天空的间接光照(Indirect Light)。 当我们开始将这组光照探针大量复制到场景其它位置来产生光照探测区域时,要确保可玩区域都会被探针所产生的四面体覆盖到,可以看到光照探针之间会以品红色的线串联表示这些区域。

 
光照探针的位置和它们之间所产生的四角面
  • 全选刚刚建立好的三个光照探针(按住Shift并点选每个光照探针或是拖拽进行框选)
  • 复制整个光照探针组并移到场景其它需要采样的地方
需要采样的地方不外乎是有阴影的区域或是地形材质色调会变化的地方。请记住,我们的目的是对场景里的间接或反射光照进行采样。 为了让每个光照探针的性能都用在刀刃上,尽量确保它们对一些光照变化明显的地方进行采样,如果光照探针放在一致性很高的光照区域,那光照探针反映给动态物体的结果不会太明显。 如同游戏优化的各方面技巧一样,尽量确保每个光照探针都有其存在的必要。

继续重复上述操作,在照明区域大密度地放置光照探针直到产生一个像笼子般的区域,涵盖所有的可玩区域。 布置这些光照探针时,请记得每一次都要检查最底部的光照探针要和地面保持一定的距离。

在我们的示例LightingTutorialOptimal场景中带有两组光照探针,VillageLightProbeGroup比较密集、用于村庄区域,ExtentsLightProbeGroup比较稀疏、用于村庄外无法到达的区域。 第二个光照探针组涵盖了整个游戏世界以防止任何非静态物体离开可玩区域,这一组不需要像村庄那组探针那么密集,垂直轴方向只要两个探针就够了。

将光照探针拆成两组,方便定义光照探针的用途,每个光照探针组都可以独立开启或关闭,方便适应场景的各种需求,这些光照探针在运行时会自动组合并执行重叠检查(de-duplication pass)以删除所有重叠的探针。

想看到光照探针的照明结果,必须等到预计算完成,如果勾选Lighting视图(Window > Lighting)下的Auto就会自动进行计算,如果未勾选,则需要按下旁边的Build按钮来手动计算。

一旦计算完成后,你会发现场景里面的非静态物体会开始接收光照探针的信息,看起来和场景光源会更匹配。如果要查看照明状态下的光照探针,可以从层级视图(Hierarchy)选择光照探针组。

现在场景里有了光照探针组,我们就能为场景中的小物体取得间接光照信息,而不需要从PRGI的流程中为这些物体生成额外的光照图。

总结
本文我们通过对光照探针的定义、设置方法和放置技巧进行阐述,希望能为您带来处理光照的新思路。想要了解预计算的操作步骤,以及更多详情,请关注Unity官方平台。

默认标题--设计创建于创客贴 (2).png(192.75 KB, 下载次数: 0)

下载附件

5 天前 上传

转载请注明来源:Unity官方中文社区 (forum.china.unity3d.com)。请勿私自更改任何版权说明信息。


【转载收藏】Unity预计算实时GI相关推荐

  1. 使用预计算实时全局光照优化照明-微调光照贴图参数

    本文地址:https://blog.csdn.net/t163361/article/details/124107784 翻译说明: 教程翻译主要用谷歌翻译后,对特别不通顺的地方进行了微调.同时针对一 ...

  2. 使用预计算实时全局光照优化照明-教程目录

    本文地址:https://blog.csdn.net/t163361/article/details/123858265 最近准备申请新星创作者,需要2000个粉丝关注,觉得文章有用的,请点一下左侧边 ...

  3. 使用预计算实时全局光照优化照明-布置光照探针

    本文地址:https://blog.csdn.net/t163361/article/details/123909115 翻译说明: 教程翻译主要用谷歌翻译后,对特别不通顺的地方进行了微调.同时针对一 ...

  4. Unity预计算全局实时GI(六) - UV展开与减少光照图数量

    由于现在我们已经从光照预计算中排除了合适的对象物体,我们可以进行减少剩余光照图表数量的工作了. 因为生成光照图表(Charts)是为了包裹静态网格渲染器(Static Mesh Renderer)的光 ...

  5. Unity预计算全局实时GI(gi params)

    Unity提供许多进阶的光照贴图控制方法,这些设定被放在一个光照参数集(LightmapParameters)的资源里,好让设定能在不同的项目场景或是透过版本控制和团队一起共享. 要建立一个Light ...

  6. Unity预计算全局光照的学习(速度优化,LightProbe,LPPV)

    1.基本参数与使用 1.1 常规介绍 使用预计算光照需要在Window/Lighting面板下找到预计算光照选项,保持勾选预计算光照并保证场景中有一个光照静态的物体 此时在编辑器内构建后,预计算光照开 ...

  7. 鼠标控制两台台式机_台式机和控制台上的真棒实时GI

    鼠标控制两台台式机 We've teamed up with Alex Lovett again and built The Courtyard, a demo that puts the Preco ...

  8. Unity光照系统,GI,光线追踪,LightMap,Enlighten,HDR等

    GI:全局光照,指的是模拟光线是如何在场景中传播的算法.不仅会考虑直接光照的结果,还会计算光线被不同的物体表面反射产生的间接光照. Unity使用的是预计算实时全局光照 : 实时(直接光照)+ 预计算 ...

  9. 完全理解Unity中PreCompute Realtime GI及其优化(一)

       Unity作为目前最流行的游戏开发引擎,在移动端也提供了良好的光照效果,帮我们构建更加真实的游戏场景.我们知道,一个游戏场景的真实与否,效果是否出色,有一部分来自光照.逼真的光照,总能表现出令人 ...

最新文章

  1. 2022-2028年中国塑胶模具行业市场专项调研及前瞻分析报告
  2. CSS 单行溢出文本只显示部分内容
  3. keepalived 高可用日志说明及实战配置日志路径
  4. scp 将数据从一台linux服务器复制到另一台linux服务器
  5. 《Windows Communication Foundation之旅》系列之一
  6. 树莓派的九周年: 9 件事你可能不知道
  7. Nature methods | Alevin-fry, 一种高效准确的单细胞测序数据预处理工具
  8. wsdl接口调用请求消息xml_短网址生成 API 接口调用请求
  9. char与byte差异
  10. String类的编码和解码问题
  11. Arduino-定义串口
  12. c语言数字和字母运算,计算器中的字母CE、C、MR、MC、MS、M+、M-等等各是什么意思?让我来告诉你吧!...
  13. 云原生背景下的运维价值思考与实践
  14. c++中整形输入逗号_Excel 2013中单元格添加下拉列表的方法
  15. zte android截屏快捷键,中兴红牛V5手机怎么截屏 中兴红牛V5截图技巧图解
  16. 【慕课网】前端零基础入门---步骤二:页面化妆师CSS---02-CSS文本样式
  17. Java 小项目——字符界面收银台(优化版)
  18. k8s探针检测php,K8s探针
  19. 09.调色板绘制系统界面
  20. 从GMT时间转换到当地时间(北京时间)

热门文章

  1. 线性代数 --- 用条件数(condition number)来判断矩阵是否可逆
  2. 使用Java处理键盘输入(DTMF)
  3. 关系抽取调研——工业界
  4. wp8.1 java_UWP tips (与wp8.1的不同)
  5. Dell服务器如何做raid
  6. Stm32cubeIDE1.8 增加代码补齐
  7. 在线的色值转换RGB网址
  8. 最强大脑王昱珩,一个近乎完美的男人
  9. Android密码管理器app
  10. 编译php为opcode,php 中间代码opcode