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 的预制体烘焙光照
在这里插入图片描述

使用方法,先给预制体挂脚本,然后点Tools里的烘焙光照,然后删掉场景的预制体,然后拖一个新的预制体出来,然后运行场景即可

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/623718.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

花趣短视频源码淘宝客系统全开源版带直播带货带自营商城流量主小游戏功能介绍

1、首页仿抖音短视频 &#xff0c;关注 &#xff0c;我的 本地 直播 可发布短视频 可录制上传 2、商城页面 广告位、淘口令识别、微信登录、淘宝登录、淘宝返佣、拼多多返佣、京东返佣、唯品会返佣、热销榜、聚划算、天猫超市、9.9包邮、品牌特卖、新人攻略 、小米有品、优惠加…

便签字号怎么改 便签字体大小调节方法

在日常工作和生活中&#xff0c;便签是我形影不离的助手。每当灵感闪现或是有待办事项时&#xff0c;我都会随手记录在便签上&#xff0c;它就像我生活中的记事本&#xff0c;帮助我安排生活和工作。 然而&#xff0c;每个人都有不同的视觉需求和阅读习惯&#xff0c;对于便签…

【Jenkins】Pipeline流水线语法解析全集 -- 声明式流水线

&#x1f468;‍&#x1f393;博主简介 &#x1f3c5;CSDN博客专家   &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01…

Centos7网卡启动失败(Failed to start LSB: Bring up/down)

好雨知时节 当春乃发生 随风潜入夜 润物细无声 报错内容 启动虚拟机时&#xff0c;Ceotos的虚拟网卡没有一起启动&#xff0c;导致服务无法正常使用 查询网络启动状态 systemctl status network.service报Failed to start LSB: Bring up/down 查看网络启动日志 journalctl…

pypi发布.whl文件

Profile of liguandong PyPIThe Python Package Index (PyPI) is a repository of software for the Python programming language.https://pypi.org/user/liguandong/2024年&#xff0c;将Python项目发布到PyPI保姆级教程 - 知乎前几天我准备上传自己开发的项目到PyPI上的时候…

Spring MVC(五) 文件上传

1 单文件上传 在程序开发中&#xff0c;有时候需要上传一些文件。我们在学习Servlet的时候&#xff0c;也做过文件上传的操作&#xff0c;只不过基于Servlet的文件上传操作起来过于复杂&#xff0c;因此所有的MVC框架都提供了自己的文件上传操作&#xff0c;基本上都是基于File…

从零开始学习Linux(6)----进程控制

1.环境变量 环境变量一般是指在操作系统中用来指定操作系统运行环境的一些参数&#xff0c;我们在编写C/C代码时&#xff0c;链接时我们不知道我们链接的动态静态库在哪里&#xff0c;但可以连接成功&#xff0c;原因是环境变量帮助编译器进行查找&#xff0c;环境变量通常具有…

简单粗暴的翻译英文pdf

背景&#xff1a;看书的时候经常遇到英文pdf&#xff0c;没有合适的翻译软件可以快速翻译全书。这里提供一个解决方案。 Step 1 打开英文pdfCTRLA全选文字CTRLC复制打开记事本CTRLV复制保存为data.txt Step 2 写一个C脚本 // ToolPdf2Html.cpp : 此文件包含 "main&quo…

【HMGD】GD32/STM32 DMA接收不定长串口数据

单片机型号&#xff1a;GD32F303系列 CubeMX配置 配置串口参数 开启DMA 开启中断 示例代码 使用到的变量 uint8_t RX_Buff_FLAG 0; uint8_t RX_Buff[300] {0}; uint8_t TX_Buff[300] {0};串口接收空闲函数 // 串口接收空闲函数 void HAL_UARTEx_RxEventCallback(UART_H…

Redisson中分布式锁的实现原理

redisson版本&#xff1a;3.27.2 简介 锁归根结底就是对同一资源的竞争抢夺&#xff0c;不管是在单体的应用亦或者集群的服务中&#xff0c;上锁都是对同一资源进行修改的操作。至于分布式锁&#xff0c;那就是多个服务器或资源&#xff0c;同时抢占某一单体应用的同个资源了。…

基于Springboot+Vue的Java项目-农产品直卖平台系统开发实战(附演示视频+源码+LW)

大家好&#xff01;我是程序员一帆&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &am…

AD软件针对分散的元器件归一排列

先框选 然后快捷键TOL 绿色的十字箭头选框选位置 完成

将excel表中的数据导入到navicat中

1.将excel中的表头改成英文 2.在navicat中右键表&#xff0c;选择【导入向导】 3.在弹出的导入向导中选择Excel文件&#xff0c;然后点击【下一步】 4.选择需要导入的excel&#xff0c;选中后&#xff0c;在下方会罗列出excel中的sheet&#xff0c;勾选需要导入的sheet&#xf…

Chromium 调试指南2024 Windows11篇-使用日志来辅助调试(八)

1. 日志&#xff1a;你的第一个调试工具 日志是开发者最简单也是最常用的调试工具之一&#xff0c;它能够提供程序运行时的详细记录。通过合理的日志记录策略&#xff0c;开发者可以快速定位问题发生的上下文&#xff0c;理解程序的运行流程和状态。 2. 如何在Chromium中使用…

QMT如何写代码获取基金数据?方法总结!

此函数被设计为只支持单一基金查询&#xff0c;用于获取详细的股票信息。该函数可以让您接收关于特定基金的深度信息&#xff0c;包括但不限于其涨跌停价格、上市日期、退市日期以及期权到期日等重要数据。这将为您提供详尽的信息&#xff0c;以便更好地理解并分析股票的历史和…

【vue2项目经验总结:a标签干扰路由】

当我们点击页面中的a标签实现跳转时&#xff0c;会发现网页上方的路由也切换成了a标签的id值&#xff1a; 刷新后页面也会变成空白&#xff1a; 解决方法&#xff1a; 添加Click方法&#xff0c;传入的参数与id值保持一致 scrollIntoView() 方法&#xff0c;将该元素滚动到…

pycharm连接远程服务器,解决终端出现乱码问题

在终端输入命令时会有乱码问题&#xff0c;是字体编码设置错误。 根据上述步骤&#xff0c;设置完成后重启就可以了。

C#语言进阶

一、简单数据结构类 1. ArrayList ArrayList是一个 C# 为我们封装好的类&#xff0c;它的本质是一个 object 类型的数组。ArrayList类帮助我们实现了很多方法&#xff0c;比如数组的增删查改 1.1 声明 using System.Collections;ArrayList array new ArrayList(); 1.2 增…

MyBatis的创建和测试

创建项目点击Spring Initializr然后点击next 点击SQL 选择里面的Mybatis Framework和Mysql Driver 按如下图片创建项目 user表中的数据 #下面这些内容是为了让MyBatis映射 #指定Mybatis的Mapper文件 mybatis.mapper-locationsclasspath:mappers/*xml #指定Mybatis的实体目录 my…

亿级流量系统架构设计与实战

&#x1f482; 个人网站:【 摸鱼游戏】【神级代码资源网站】【工具大全】&#x1f91f; 一站式轻松构建小程序、Web网站、移动应用&#xff1a;&#x1f449;注册地址&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交…