这篇文章是基于最近听的Unity官方的一个名叫《Unity 2018 Progressive Lightmapper功能介绍》的直播:直播地址录播地址。不过说实话,关于progressive lightmapper暂时没有给我太大惊喜,目前看到最大的进步就是2018之后可以使用N卡利用GPU烘焙 lightmapper,其他的都是一些小的改动。具体如下:

Shader中的计算默认不考虑间接光(PBR会使用的是假的间接光),所以想有间接光,要么就使用Baked GI,要么就使用Realtime GI,Realtime GI效果比较好(因为随着光照的变化可以实时变换,但是对性能影响很大),所以手机中基本都使用Baked GI。所以为了使得场景中能有间接光的效果,让场景更加真实的表现,那么需要使用lightmap。特别是场景中光照比较多的情况,多盏实时光会导致严重的性能问题。

Unity 5.6推出了Progressive Lightmapper渐进光照贴图,然后在2018中正式投入使用。(2018中还会推出GPU 渐进光照贴图 烘焙,可以提升烘焙速度)

下面,就通过对三种全局光照模式( Realtime GIBaked GIMix GI)的介绍,对GI的基本概念进行梳理,重点还是将介绍烘焙的全局光照模式。

在介绍烘焙的全局光照模式中,主要介绍progressive lightmapper、light probe以及reflection probe的基本概念。

最后再聊Mix的光照模式,包含Baked Indirect,ShadowMask,Subtractive三种。

RealTimeGI

当Light为realtime,且LightSetting中RealtimeGI没有打开的时候(Mix Lighting中的Baked GI也关闭),然后把之前Bake的数据clear掉,这个时候就没有GI,没有间接光了,场景会比较暗。如果打开LightSetting中的RealtimeGI,然后再选择Generate Lighting(这个时候会预计算实时GI所需要的信息,预计算的方法如下图,是预先计算了表面到表面之间间接光照的路径,这样的话效果最好,因为随着光照亮度的调节,甚至通过Indirect Multiplier属性的调节(可以通过SceneView的Realtime GI模块的Indirect选项,可以看到间接光照的效果),可以控制间接光照的影响程度,效果可以立即反应出来。但是会有一个问题,因为它的这个预计算是通过分帧计算的,所以不适合快速变化的光源),就可以得到实时光照的效果,也就是有了间接光照(包括人物身上)。实时光照的全局GI虽然效果最好,但是计算量太大了,所以适合中高端的平台,比如PC或者Console。Engliten最擅长的就是实时GI。

lightmap

BakedGI

通过LightExplorer可以设置当前打开的light的选项,比如切换realtime/baked/mixed。BakedGI的开关在light setting的Mix Lighting中的Baked GI。然后在lightmappingsetting中设置lightmapper,可以选择engliten或者progressive,engliten擅长实时GI,progressive的优势在于优先烘焙sceneview中可见部分的lightmap,并可以实时看到,这是progressive在工作流上的一个改进。选择progressive的时候就可以看到可以勾选proritize view,勾选上后就会优先烘焙SceneView中看到的场景区域。

在Unity2018中,可以在sceneview中选择Baked GI中模块的UV Charts,然后可以看到每个物件的UV Charts,然后对应Lightsetting中的Object Map中的Baked UV Chart模块,就可以看到每个物件在lightmap中所占的大小,在Sceneview中UV Chart上的棋盘格一样的小方块,也就对应了lightmap中的一个像素(通过修改),通过sceneview的这个UV chart视图,就可以看出该物件对应lightmap的分辨率是否合适。

看下Lightmap Settings中的其他参数Direct Samples和Indirect Samples,因为progressive lightmapper是基于光线追踪的光照系统,所以这两个sample是用于指定每个纹理像素中会发射出光线的数量,数量少了就会产生噪音,数量多了噪音就少了。通过sceneview的Baked Lightmap可以看到当前lightmap(也就可以看到噪点)。

下面看Lightmap Settings中的参数lightmap resolution,这个选项代表着每个单元物件所对应的lightmap的纹理像素数量,这个数值越大,lightmap计算的越慢,计算出来的lightmap质量越好。这个属性是全局光照贴图属性设置。其实可以针对每个物件设置不同的~通过MeshRenderer的LightMap Setting中的Scale In Lightmap设置。实时GI也有lightmap,它的分辨率是通过Indirect Resolution设置的。

下面看Lightmap Settings中的参数filtering,类似纹理的filter,是用于进行平滑处理的,可以控制边缘模糊或者尖锐。filter有三种模式:none、auto、advance(高斯、a-trous)。其中 高斯是用于做边缘模糊的,比如阴影就可以显得柔和,而A-trous会让阴影边缘比较尖锐。如下图,但是并非所有的情况都适合高斯模糊,比如下下图,A-trous更适合一些。

lightmap lightmap

下面说2个Lightmap中经常会出现的问题。

第一个是由于一个物件的两个Chart重叠,导致可能会出现的UV Overlap,导致显示不正确。可以通过Sceneview的UV Overlap选项可以清晰的看出Overlap的部位,也可以在Lightsetting的Object map中选择Baked UV Overlap看到lightmap中overlap的部位。避免办法也很简单,需要选择物件对应的FBX的importsetting,勾选generate lightmap uvs,在advanced中设置pack margin,在贴图打包atlas的时候对这个都会比较属性,这个可以增加同一个模型不同chart之间的margin间距,需要注意的是,这里设置的单位并非像素,而是百分比,区别于ligmapsetting中的lightmap padding。设置完毕后需要重新烘焙lightmap。然后在Sceneview的UV Overlap选项中就看不到overlap了,在Lightsetting的Object map中选择Baked UV Overlap就可以看到该物件的不同chart有了间隙。当然这样也增加了lightmap的大小,所以需要合理设置。

第二个纹理是出现裂纹,非方形物件的不同chart之间容易出现裂纹/缝隙,如果出现这种问题,就需要打开该物件Mesh renderer的lightmap setting的stitch seams用于修复裂纹。

以上内容说的都是静态物体的lightmap,而动态物件其实是没有baked的光照信息的,所以需要使用lightprobe。可以在动态物件四周布上 lightprobe,然后点击物件,可以看到对其产生影响的lightprobe,并且在probe上可以看到probe接收到的照明信息(包括直接光和间接光)。

Unity还提供了reflection probe,是把该点当做一个视点,然后看到周围世界的样子,并烘焙到一个cubemap上,并可以用到接收reflection probe的物件上。

这种方案是性能最佳的方案。

Mixed GI

Mixed模式指的是:间接光采用烘焙的方式(可以衬托场景的氛围),直接光实时计算以增加材质的真实感,比如表面高光的显示。Mixed模式氛围三种:Baked Indriect、Shadowmask、Subtractive

Baked Indriect只烘焙间接光照,直接光和阴影使用实时计算(不区分静态还是动态)。

lightmap

ShadowMask:静态对象通过shadowmask从其他静态对象接收阴影,不必考虑阴影距离。来自动态对象的阴影仅能通过阴影距离内的阴影贴图获得。动态对象通过阴影距离内的阴影贴图接受来自其他动态对象的阴影。来自静态对象的阴影仅能通过光照探针获得。对于静态物体,会把直接光照产生的阴影会烘焙到ShadowMask贴图中,但是这个ShadowMask贴图分辨率没有实时影子的ShadowMap的分辨率高。现在,当你同时在动态对象和光照贴图静态对象上使用Shadowmask模式时,你首先可能会发现问题就是,动态对象的阴影(阴影贴图)和来自光照贴图静态对象的烘焙阴影之间的不一致。当前(针对5.6),Unity在运行时仅支持简易版本的PCF阴影,这种阴影很简陋,走近时还可能会出现阴影瑕疵。因此,动态对象是不可能获得软阴影的。与之相比,静态对象则相对较容易获得软阴影。实际上,你通常需要增加分辨率以渲染更多静态对象的阴影,因为你需要更多的纹理像素来定义一张光照贴图上的阴影。只有这样,你才能渲染出与来自动态对象的阴影贴图相近的阴影。动态对象仅会在阴影距离内投射阴影贴图。而静态对象,无论阴影距离为何,仅会投射烘焙阴影。Shadowmask 和Distance Shadowmask两者均可提供实时镜面高光。更详细信息见:

lightmap

Subtractive:对于静态物体,直接光和间接光以及直接光照产生的阴影都烘焙到光照贴图中,对于动态物体,混合灯光还会为场景中的非静态(动态)游戏对象提供直接光(实时),直接光需要实时计算,可以在静态物件上投射主方向光的阴影,但是仅有单个定向Mix光时它才能正常工作,混合点光源和聚光灯不会在对象上投射任何阴影。缺点:1.与其他模式不同,Subtractive模式的直接光也是烘焙的,因此在这种光照模式中,没有镜面反射。2.没有光照探针,动态对象无法对用于静态对象的光照进行采样,而且更重要的是,它们无法使用遮蔽数据。因此,为了能接收阴影,动态对象需要将来自光照探针的光照进行混合。为了达成更精确的遮蔽,可以为你场景中重要的对象(例如,主要角色)指定光照探针代理体(LPPV)。但是注意,这会带来额外的性能消耗。3.不适用于延迟渲染路径和Linear色彩空间。

lightmap

虽然并非全部原创,但还是希望转载请注明出处:电子设备中的画家|王烁 于 2018 年 6 月 4 日发表,原文链接(http://geekfaner.com/unity/blog12_LightMap.html)