低配机下的多套lightmap烘焙切换方案研究
-
开门见山的说,最近一直在研究四季变换在低配机上的方案。高配机就不说了,直接通过Mixed光源然后根据季节控制平行光即可。但低配机上就得关掉Mixed光源,只使用Bake光源烘焙出的lightmap贴图来做差值切换。
-
那么关于这方面,目前研究出两种方案。
-
1、 vfshader中有unity为我们封装好的调用lightmap的函数,我们可以通过这个获取对应的lightmap,他内部是自动获取lightmap索引采样的。
-
那么我们就可以在C#代码里编写脚本改变烘焙出的lightmap。首先烘焙出四种季节不同的lightmap,分别放入春夏秋冬的文件夹。然后通过C#代码或者compute shader,读取他们并对他们做差值。读取可以用GexPix那些函数进行赋值。
-
差值完毕后,在把得到的结果贴图写入场景保存的lightmap中。把每一个索引得到的结果分别赋给对应的场景lightmap即可
-
但此方案对CPU消耗较大,直接在代码中做差值会非常影响效率,使用compute shader又会在传送数据,转换格式时消耗大量资源,得做好取舍。
-
2、把lightmap当做Texture来直接赋值给shader,由shader进行差值。首先烘焙出不同季节的lightmap保存至春夏秋冬文件夹。
-
这个方案要清楚的一点是,如果烘焙设置后场景烘焙出了6张lightmap,那么就相当于整个大场景被6张lightmap分成了6份。我们得通过render.sharedMaterial.lightmapIndex来获取模型自身存储的index信息,然后遍历一遍场景模型,根据索引分配贴图才行。
-
此时shader将会动态采样两张lightmap,动态变换则在代码里切换。
private void SetLightMap(int season)
{
for (int i = 0; i < _materials.Count; i++)
{
int index = _materials[i].lightmapIndex;
_materials[i].sharedMaterial.SetTexture("_FirstLightMap", _lightMaps[season, index]);
_materials[i].sharedMaterial.SetTexture("_LastLightMap", _lightMaps[(season + 1)%4, index]);
}
}
但这个方案需要注意一点就是,当你烘焙出6张lightmap,并完成动态赋值操作之后,你会发现只有采样lightmap0的模型特别亮,其他5个都很正常。在我多次对比测试后猜测可能是两个原因:1.第一张lightmap会储存场景的bake光烘焙信息。2:unity会在场景中保存第一张lightmap信息,故会叠加。解决方法:烘焙完所有场景后,将场景中所有bake光关闭再烘焙一次,得出的lightmap替换掉原来的第一张就行,亲测有效,效果也很正常。
这个方案的优点就是不需要再cpu,gpu间来回传2048贴图,也不需要逐像素处理贴图转换格式,一切由shader的lerp函数就能完成,但需要在内存中动态采样两张lightmap。
有什么意见欢迎大家提出