Unity Lightmap&LightProbe局部动态加载
最終效果可以实现两套lightmap光照信息和light probe动态切换
背景需求
lightmap部分
[*]通常为了拥有光照效果且平衡性能,项目中常用Lightmap来模拟灯光带来的效果。
[*]但目前有些功能场景仅拥有一个scene,其中的全部资源都是以AssetBundle的形式动态加载。这时,如果需要两套光照效果,就需要开发额外的功能实现lightmap动态加载。
lightprobe部分
[*]动态物体不会受到lightmap的影响,因此当物体在场景中移动时,会因为没受光而显得很突兀。这个问题一般会使用lightprobe来解决。
[*]与lightmap面对的问题一样,当场景中的物体动态加载,且不同物体之间的光照信息并不一致时,就需要动态的替换对应的probe部分。
原理&实现
lightmap部分
[*]lightmap会在烘焙后生成一个绑定场景的lightingdata类型的asset文件,该文件和场景一一对应,默认情况下不支持一个场景对应两个data文件的情况。
[*]lightingdata文件整体替换的话难度不大,unity已经提供了接口,使用如下接口即可。
LightmapSettings.lightmaps= new LightmapData();
[*]但有时候场景的中的物体加载是独立的,例如场景中有四个房间,这四个房间均有两套独立的光照数据对应,如果继续对它们进行整体替换,则需要保存12套数据,这样实现肯定不行。目前的实现是将prefab对应的光照信息绑定在资源上,在物体被加载进来的时候,动态的修改对应的LightmapIndex和LightmapScaleOffset。
info.renderer.lightmapIndex = lightmapOffsetIndex;
info.renderer.lightmapScaleOffset = info.lightmapOffsetScale;
[*]这样实现的问题是,一个场景仅能绑定一个lightingdata,该文件的内部数据不能动态的修改,因此需要对场景进行两次烘焙,将第二次烘焙生成的lightingdata数据中需要保留的文件与第一次的数据合并,融合成为一个新的lightingdata文件,并绑定当前场景。这样实现之后,两次烘焙的有效lightmap贴图都被存储在最新的lightingdata文件内。在游戏内,加载资源实例化后,根据存储的信息重新对LightmapIndex和LightmapScaleOffset赋值,即可实现需求。
红光为第一次烘焙数据,黄光为第二次烘焙数据
[*]额外说明,这样实现时,最好让替换的prefab文件不与其他资源的lightmap贴图耦合。尽量做到合并的数据都是有效的。该功能可以通过设置下图的参数实现:
lightprobe部分
[*]unity在烘焙完成后,会生成一个存储lightprobe的asset文件,但该文件不是自动生成的,可以使用以下代码手动生成查看一下文件的存储结构。
AssetDatabase.CreateAsset(Instantiate(LightmapSettings.lightProbes), "Assets/lightProbe.asset");
[*]打印出来的文件结构如下图所示。
[*]Tetrahedralization里面保存的是LightProbe插值时需要用到的四面体数据,如果物体动态替换时,lightprobe的世界坐标不变的话,这个信息并不需要修改。
[*]Probe Sets里面存储的是关于lightprobe group的索引数据。
[*]Positions里面的是每个探针的世界坐标。
[*]Baked Coefficients里面存储的是烘焙后的球谐函数的系数,unity内部LightProbe使用的是3阶球谐函数(9个参数),因此可以看到一个探针对应"9个参数3个通道",一共27个float数据。LightProbe的原理就是对球面上的亮度信号进行编码和重建,因此该部分为lightprobe的核心数据。我们需要动态替换的就是这里面的数据。
[*]知道原理和存储结构后,我们可以根据probe的世界坐标进行索引,筛选出需要动态替换的probe索引id,并将该部分数据存储在prefab上。由于这部分是在编辑器下进行的,因此一一遍历寻找对性能没有什么影响。
[*]最后,在游戏内加载资源实例化后,根据存储的信息重新对对应的probe进行赋值,即可实现需求。
页:
[1]