Unity Lightmap之动态加载单个物件和其对应的Lightmap

下一篇: Lightmap之Terrain和Lightmap切割      

 接上一篇,LightMap之动态切换LightMap模拟白天夜晚 ,介绍了最基本的动态切换。现在问题来了,当场景比较大的时候,我们通常不是一次性把所有的物件都加载,哪怕这个物件是静态的,比如场景中不动的建筑。如果我们仅仅是烘焙后场景物件保存成prefab,那么我们在加载后,prefab是没有烘焙信息的。最后出现的效果如下,显然不是预期。Cube 1 和 Plane 1是之前烘焙完后保存的prafab。Unity Lightmap之动态加载单个物件和其对应的Lightmap_第1张图片

       好在有解决方案:在每个需要烘焙的场景物件上挂一个脚本,当场景烘培结束后,把每个物件的烘焙信息记录在脚本上,然后把整个物件连同脚本一起保存成prefab。运行时直接把prefab加载就完成了。下图就是正确的预期结果。

Unity Lightmap之动态加载单个物件和其对应的Lightmap_第2张图片

        那这个脚本上记录什么东西呢?有两个很重要的数据就是index和offsetScale,这些信息都能从MeshRenderer中取到

lightmapIndex 和 lightmapScaleOffset。除了这两者之外,还有具体的Lightmap烘焙贴图,lightmaps 和lightmaps2。因为这些是带在场景信息中的,因此需要单独拉出来保存。就是Lightmap-0_comp_light和Lightmap-0_comp_dir,再下面的小图是把他们保存到Resource中的截图。相当于index和offsetScale记录的是物件在具体的Lightmap烘焙贴图的信息。换句话说,Lightmap烘焙贴图是整个场景的,每个物件的烘焙信息肯定在这之中,至于在这中的位置就是index和offsetScale记录的。

Unity Lightmap之动态加载单个物件和其对应的Lightmap_第3张图片

当然,保存这些信息需要脚本的支持。完整代码下载   两个核心的函数如下:

 

static void GenerateLightmapInfo(string scenePath, string resourcePath, GameObject root, List rendererInfos, List lightmaps, List lightmaps2)
    {
        var renderers = root.GetComponentsInChildren();
        foreach (MeshRenderer renderer in renderers)
        {
            if (renderer.lightmapIndex != -1)
            {
                RendererInfo info = new RendererInfo();
                info.renderer = renderer;
                info.lightmapOffsetScale = renderer.lightmapScaleOffset;

                Texture2D lightmap = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapColor;
                Texture2D lightmap2 = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapDir;
                int sceneLightmapIndex = AddLightmap(scenePath, resourcePath, renderer.lightmapIndex, lightmap, lightmap2);

                info.lightmapIndex = lightmaps.IndexOf(sceneLightmaps[sceneLightmapIndex].lightmap0);
                if (info.lightmapIndex == -1)
                {
                    info.lightmapIndex = lightmaps.Count;
                    lightmaps.Add(sceneLightmaps[sceneLightmapIndex].lightmap0);
                    lightmaps2.Add(sceneLightmaps[sceneLightmapIndex].lightmap1);
                }

                rendererInfos.Add(info);
            }
        }
    }

    static int AddLightmap(string scenePath, string resourcePath, int originalLightmapIndex, Texture2D lightmap, Texture2D lightmap2)
    {
        int newIndex = -1;

        for (int i = 0; i < sceneLightmaps.Count; i++)
        {
            if (sceneLightmaps[i].originalLightmapIndex == originalLightmapIndex)
            {
                return i;
            }
        }

        if (newIndex == -1)
        {
            var lightmap_Remap = new Texture2D_Remap();
            lightmap_Remap.originalLightmapIndex = originalLightmapIndex;
            lightmap_Remap.originalLightmap = lightmap;

            var filename = scenePath + "Lightmap-" + originalLightmapIndex;

            lightmap_Remap.lightmap0 = GetLightmapAsset(filename + "_comp_light.exr", resourcePath + "_light", originalLightmapIndex, lightmap);
            if (lightmap2 != null)
            {
                //lightmap_Remap.lightmap1 = GetLightmapAsset(filename + "_comp_dir.exr", resourcePath + "_dir", originalLightmapIndex, lightmap2);
                lightmap_Remap.lightmap1 = GetLightmapAsset(filename + "_comp_dir.png", resourcePath + "_dir", originalLightmapIndex, lightmap2);
            }

            sceneLightmaps.Add(lightmap_Remap);
            newIndex = sceneLightmaps.Count - 1;
        }

        return newIndex;
    }

 

你可能感兴趣的:(Unity3D.杂项,Unity,Lightmap)