untiy 为预制体动态加载光照贴图

unity版本为2021.8
预制体不能携带光照贴图信息,只能我们自己准备了
多方查找加自己摸索终于找到了适合新版本的解决方案,直接贴代码

将这个脚本挂到预制体的最上级

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

[System.Serializable]
public struct RendererInfo
{
    public Renderer renderer;//网格物体  网格和地形的光照信息是分开的
    public Terrain terrain;//地形
    public int lightmapIndex;
    public Vector4 lightmapScaleScaleOffset;
}
//记录光照贴图的信息
public class PrefabLightmapData : MonoBehaviour
{
    public RendererInfo[] m_RendererInfo;
    public Texture2D[] m_Lightmaps_light;//颜色贴图
    public Texture2D[] m_Lightmaps_dir;//方向贴图
    public Texture2D[] m_Lightmaps_shadowmask;//阴影贴图

    private void Awake() 
    {
        RebuildLight();
    }
    public void RebuildLight()
    {
        if (m_RendererInfo == null || m_RendererInfo.Length == 0) return;

        LightmapData[] lightmapDataArray = new LightmapData[m_Lightmaps_light.Length];
        for (int i = 0; i < m_Lightmaps_light.Length; i++)
        {
            LightmapData lightmapData = new LightmapData();
            if (i < m_Lightmaps_light.Length) lightmapData.lightmapColor = m_Lightmaps_light[i];
            if (i < m_Lightmaps_dir.Length) lightmapData.lightmapDir = m_Lightmaps_dir[i];
            if (i < m_Lightmaps_shadowmask.Length) lightmapData.shadowMask = m_Lightmaps_shadowmask[i];
            lightmapDataArray[i] = lightmapData;
        }
        //为预制体的物体应用光照贴图
        ApplyRendererInfo(m_RendererInfo);
        LightmapSettings.lightmaps = lightmapDataArray;//将光照贴图应用到Untiy
    }
    //应用光照贴图信息到重建的预制体
    private void ApplyRendererInfo(RendererInfo[] rendererInfoArray)
    {
        for (int i = 0; i < rendererInfoArray.Length; i++)
        {
            RendererInfo rendererInfo = rendererInfoArray[i];
            if (rendererInfo.renderer != null)
            {
                rendererInfo.renderer.lightmapIndex = rendererInfo.lightmapIndex;
                rendererInfo.renderer.lightmapScaleOffset = rendererInfo.lightmapScaleScaleOffset;
            }
            else if (rendererInfo.terrain != null)
            {
                rendererInfo.terrain.lightmapIndex = rendererInfo.lightmapIndex;
                rendererInfo.terrain.lightmapScaleOffset = rendererInfo.lightmapScaleScaleOffset;
            }
        }
    }
}
//自定义inspector面板
[CustomEditor(typeof(PrefabLightmapData))]
public class PrefabLightmapData_Inspector : Editor
{
    //重写OnInspectorGUI类(刷新Inspector面板)
    public override void OnInspectorGUI()
    {
        //继承基类方法
        base.OnInspectorGUI();
        PrefabLightmapData myScript = (PrefabLightmapData)target;
        //绘制Button
        Rect rect = new Rect(0, 0,100,50);
        if (GUILayout.Button("重新构建烘焙光照"))
        {
            myScript.RebuildLight();
        }
    }
}

在使用下方的脚本完成烘焙后,脚本将自动记录所有模型和地形的烘焙信息,并在运行后自动重建光照贴图,如果我们需要在不运行时查看光照贴图效果,可以手动点击“重新构建烘焙光照”的按钮
在这里插入图片描述

重写烘焙,烘焙完成后自动准备重建光照贴图所需要的信息

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public static class BackeLightMap
{
    [UnityEditor.MenuItem("Tools/光照/烘焙光照贴图")]
    private static void GenerateLightmapInfo()
    {
        //必须不能是自动烘焙
        if (UnityEditor.Lightmapping.giWorkflowMode != UnityEditor.Lightmapping.GIWorkflowMode.OnDemand)
        {
            Debug.LogError("ExtractLightmapData requires that you have baked you lightmaps and Auto mode is disabled.");
            return;
        }
        //烘焙贴图
        UnityEditor.Lightmapping.Bake();
        //找到有这个脚本的物体
        PrefabLightmapData[] prefabs = Object.FindObjectsOfType<PrefabLightmapData>();

        foreach (var prefabInScene in prefabs)
        {
            GameObject scenePrefab = prefabInScene.gameObject;
            List<RendererInfo> rendererInfos = new List<RendererInfo>();//重建光照贴图时需要的信息
            List<Texture2D> lightmaps_light = new List<Texture2D>();//所有的光照贴图
            List<Texture2D> lightmaps_dir = new List<Texture2D>();//所有的光照贴图
            List<Texture2D> lightmaps_shadowmask = new List<Texture2D>();//所有的光照贴图

            GenerateLightmapInfo(scenePrefab, rendererInfos, lightmaps_light, lightmaps_dir, lightmaps_shadowmask);//获取当前物体的光照贴图信息和光照贴图
            //为光照贴图信息和光照贴图赋值
            prefabInScene.m_RendererInfo = rendererInfos.ToArray();
            prefabInScene.m_Lightmaps_light = lightmaps_light.ToArray();
            prefabInScene.m_Lightmaps_dir = lightmaps_dir.ToArray();
            prefabInScene.m_Lightmaps_shadowmask = lightmaps_shadowmask.ToArray();
            //替换掉已经保存的预制体
            GameObject sourcePrefab = UnityEditor.PrefabUtility.GetPrefabParent(prefabInScene) as GameObject;
            //GameObject sourcePrefab = UnityEditor.PrefabUtility.GetCorrespondingObjectFromSource(scenePrefab);
            if (sourcePrefab != null)
            {
                UnityEditor.PrefabUtility.ReplacePrefab(scenePrefab, sourcePrefab);
            }
        }
    }
    //点击按钮生成光照贴图信息
    private static void GenerateLightmapInfo(GameObject root, List<RendererInfo> rendererInfoList, List<Texture2D> lightmaps_light, List<Texture2D> lightmaps_dir, List<Texture2D> lightmaps_shadowmask)
    {
        //找到这个物体的所有网格
        MeshRenderer[] renderers = root.GetComponentsInChildren<MeshRenderer>();
        //遍历网格
        foreach (MeshRenderer meshRenderer in renderers)
        {
            if (meshRenderer.lightmapIndex != -1)
            {
                //收集光照贴图信息
                RendererInfo rendererInfo = new RendererInfo();
                rendererInfo.renderer = meshRenderer;
                rendererInfo.lightmapIndex = meshRenderer.lightmapIndex;
                rendererInfo.lightmapScaleScaleOffset = meshRenderer.lightmapScaleOffset;
                //收集光照贴图
                //颜色贴图
                Texture2D lightmap_light = LightmapSettings.lightmaps[meshRenderer.lightmapIndex].lightmapColor;
                AddLightMapToCheach(lightmaps_light, lightmap_light);
                //方向贴图
                Texture2D lightmap_dir = LightmapSettings.lightmaps[meshRenderer.lightmapIndex].lightmapDir;
                AddLightMapToCheach(lightmaps_dir, lightmap_dir);
                //shadowmask
                Texture2D lightmap_shadowmask = LightmapSettings.lightmaps[meshRenderer.lightmapIndex].shadowMask;
                AddLightMapToCheach(lightmaps_shadowmask,lightmap_shadowmask);
                //光照信息
                rendererInfoList.Add(rendererInfo);
            }
        }
        //找到这个物体的所有网格
        Terrain[] terrains = root.GetComponentsInChildren<Terrain>();
        //遍历网格
        foreach (Terrain terrain in terrains)
        {
            if (terrain.lightmapIndex != -1)
            {
                //收集光照贴图信息
                RendererInfo rendererInfo = new RendererInfo();
                rendererInfo.terrain = terrain;
                rendererInfo.lightmapIndex = terrain.lightmapIndex;
                rendererInfo.lightmapScaleScaleOffset = terrain.lightmapScaleOffset;
                //收集光照贴图
                //颜色贴图
                Texture2D lightmap_light = LightmapSettings.lightmaps[terrain.lightmapIndex].lightmapColor;
                AddLightMapToCheach(lightmaps_light, lightmap_light);
                //方向贴图
                Texture2D lightmap_dir = LightmapSettings.lightmaps[terrain.lightmapIndex].lightmapDir;
                AddLightMapToCheach(lightmaps_dir, lightmap_dir);
                //shadowmask
                Texture2D lightmap_shadowmask = LightmapSettings.lightmaps[terrain.lightmapIndex].shadowMask;
                AddLightMapToCheach(lightmaps_shadowmask, lightmap_shadowmask);
                //光照信息
                rendererInfoList.Add(rendererInfo);
            }
        }
    }
    //将一个光照贴图添加进缓存
    private static void AddLightMapToCheach(List<Texture2D> list,Texture2D texture)
    {
        if (texture == null) return;
        int index = list.IndexOf(texture);//查找已有的集合里有没有这个元素,如果没有,返回-1
        if (index == -1)
        {
            list.Add(texture);
        }
    }
}

工具栏里会出现烘焙按钮,点击烘焙光照贴图,不要再用Unity自己的烘焙了,为场景中所有挂载了PrefabLightmapData 的预制体烘焙光照
在这里插入图片描述

相关推荐

  1. three.js使用环境或者hdr

    2024-05-11 10:10:06       11 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-05-11 10:10:06       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-05-11 10:10:06       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-05-11 10:10:06       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-05-11 10:10:06       20 阅读

热门阅读

  1. 三生随记——耳机里的诅咒

    2024-05-11 10:10:06       8 阅读
  2. 2.mysql--备份恢复

    2024-05-11 10:10:06       10 阅读
  3. Spring Cloud LoadBalancer 4.1.2

    2024-05-11 10:10:06       9 阅读
  4. Acwing2024蓝桥杯并查集

    2024-05-11 10:10:06       15 阅读
  5. 什么是中间件

    2024-05-11 10:10:06       9 阅读
  6. 关于SpringBoot MVC接口超时时间的分析

    2024-05-11 10:10:06       12 阅读
  7. C#爬虫爬取某东商品信息

    2024-05-11 10:10:06       9 阅读
  8. TVM简介

    TVM简介

    2024-05-11 10:10:06      11 阅读
  9. Lua(0)环境搭建与基础代码

    2024-05-11 10:10:06       14 阅读