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

news2024/11/17 23:38:29

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【半夜学习MySQL】库的操作(含库的创建、删除、修改、备份操作/查看mysql连接情况/字符集和校验规则详谈)

&#x1f3e0;关于专栏&#xff1a;半夜学习MySQL专栏用于记录MySQL数据相关内容。 &#x1f3af;每天努力一点点&#xff0c;技术变化看得见 文章目录 创建数据库字符集和校验规则查看字符集合校验规则校验规则对数据库的影响 操纵数据库数据备份和恢复查看连接情况 创建数据库…

SDXL-ControlNet模型MistoLine:引领高精度图像生成的革新高质量图像模型

在数字艺术的浩瀚星空中&#xff0c;MistoLine犹如一颗璀璨的新星&#xff0c;以其对SDXL-ControlNet技术的深度整合&#xff0c;展示了对多种线稿类型的非凡适应能力&#xff0c;并在高精度图像生成领域树立了新的标杆。 GitHub&#xff1a;https://github.com/TheMistoAI/Mi…

Spring Framework-简介

Spring Framework Java Spring是一个开源的Java应用框架&#xff0c;它的主要目的是简化企业级应用开发的复杂性。Spring框架为开发者提供了许多基础功能&#xff0c;使得开发者能够更专注于业务逻辑的实现&#xff0c;而不是底层的细节。 主要特点和功能&#xff1a; 控制反…

Redis-新数据类型-Hyperloglog

新数据类型-Hyperloglog 简介 在我们做站点流量统计的时候一般会统计页面UV(独立访客:unique visitor)和PV(即页面浏览量&#xff1a;page view)。 什么是基数&#xff1f; 数据集&#xff5b;1&#xff0c;2&#xff0c;5&#xff0c;7&#xff0c;5&#xff0c;7&#xff…

Spring框架学习-详细

文章目录 1. Spring简介1.1 面向接口编程1.2 Spring简介1.3 Spring体系结构 2 Spring IoC - 基于XML2.1 Sping框架部署&#xff08;IoC&#xff09;2.2 Spring IoC使用2.3 IoC和DI2.4 DI依赖注入Spring容器通过反射方法实现属性注入有三种方式1. set方法注入2. 构造器注入 2.5 …

禁止打开浏览器时弹出 internet explorer 11 停用的通知

计算机管理&#xff08;我的电脑图标上右键&#xff09; - 管理模板 - windows 组件 - internet explorer 启用隐藏 internet explorer 11 停用通知&#xff0c;如下图所示

使用Valgrind工具套件中的Massif监测C++程序堆内存使用

Valgrind是一款用于内存调试、内存泄漏检测以及线程问题分析的套件。它由一系列的工具组成,适用于Linux、macOS等操作系统。下面简要介绍几个主要的Valgrind工具: Memcheck 这是Valgrind最常用的工具,用于检测程序中的内存错误,包括非法内存读写、使用未初始化的内存等。Cache…

【动态规划】子数组、子串系列II|等差数列划分|最长湍流子数组|单词拆分|环绕字符串中唯一的子字符串

一、等差数列划分 413. 等差数列划分 算法原理 &#x1f4a1;细节&#xff1a; 1.如果当前nums数组中i位置的数和前面两个数可以构成等差数列&#xff0c;那么当前位置所有子数组构成的等差数列个数dp[i]就等于前一个位置有子数组构成的等差数列个数1&#xff08;这个1代表增加…

基于MWORKS 2024a的MIMO-OFDM 无线通信系统设计

一、引言 在终端设备和数据流量爆发式增长的今天&#xff0c;如何提升通信系统容量、能量效率和频谱利用率成为5G通信的关键问题之一。大规模天线阵列作为5G及B5G无线通信关键技术通过把原有发送端天线数量提升一个或多个数量级&#xff0c;实现波束聚集、控制波束转向&#x…

钒回收树脂五氧化二钒净化回收工艺

钒是一种重要的工业金属&#xff0c;广泛应用于钢铁合金、化工、航空和电池材料等领域。随着资源的日益紧张和环保要求的提高&#xff0c;回收利用钒成为了一个重要的研究方向。树脂吸附技术是一种常用的从废水或废料中回收钒的方法&#xff0c;具有操作简便、效率高、成本相对…

OpenCV中的模块:点云配准

点云配准是点云相关的经典应用之一。配准的目的是估计两个点云之间位姿关系从而完成两者对应点之间的对齐/对应,因而在英文中又叫“align”、“correspondence”。笔者曾经是基于OpenCV进行三维重建的,并且从事过基于深度学习的6DoF位置估计等工作。在这些工作中,除了重建点…

Ansible的安装与配置

Ansible的安装与配置 1. 安装ansible # ansible是epel源提供的&#xff0c;所以必须安装epel&#xff1a; [rootRocky9 ~]# yum -y install epel-release Last metadata expiration check: 0:01:53 ago on Tue 26 Dec 2023 10:05:34 PM CST. Dependencies resolved. Package …

如何在 CentOS 上安装并配置 Redis

如何在 CentOS 上安装并配置 Redis 但是太阳&#xff0c;他每时每刻都是夕阳也都是旭日。当他熄灭着走下山去收尽苍凉残照之际&#xff0c;正是他在另一面燃烧着爬上山巅散烈烈朝晖之时。 ——史铁生 环境准备 本教程将在 CentOS 7 或 CentOS 8 上进行。确保你的系统已更新到最…

Java入门基础学习笔记7——Intellij IDEA开发工具概述、安装

之前的开发工具存在一些问题&#xff1a; 文本编辑工具&#xff1a;记事本、NotePad、EditPlus、Sublime...编写代码的时候没有错误提醒、没有智能代码提示、需要自己进行编译、执行、功能不够强大。 集成开发环境&#xff08;IDE&#xff1a;Integrated Development Environm…

Python 3 中zip()函数的用法

1 创作灵感 我们在阅读代码的时候&#xff0c;经常会看到zip函数&#xff0c;有的时候还和循环在一起用&#xff0c;今天举几个例子测试一下该函数的用法 2.应用举例 &#xff08;1&#xff09;定义了两个列表一个是num,一个是letter (2)使用zip可以把num列表和letter列表中…

k8s遇到的常见问题及解决

1. error: open /var/lib/kubelet/config.yaml: no such file or directory 解决&#xff1a;关键文件缺失&#xff0c;多发生于没有做 kubeadm init就运行了systemctl start kubelet。 要先成功运行kubeadm init 2. 执行初始化kubeadm init ------的时候报错 The HTTP call…

视频批量剪辑高效掌握,轻松驾驭视频制作,播放速度与帧数尽在掌控

在追求速度与激情的视频制作世界里&#xff0c;你是否曾渴望拥有一款能够轻松调整播放速度和秒数的神器&#xff1f;现在&#xff0c;这款神器已经来到了你的身边&#xff0c;让你在视频制作的道路上更加得心应手&#xff0c;效率倍增&#xff01; 首先&#xff0c;我们要进入媒…

机器学习-L1正则/L2正则

机器学习-L1正则/L2正则 目录 1.L1正则 2.L2正则 3.结合 1.L1正则 L1正则是一种用来约束模型参数的技术&#xff0c;常用于机器学习和统计建模中&#xff0c;特别是在处理特征选择问题时非常有用。 想象一下&#xff0c;你在装备行囊准备去旅行&#xff0c;但你的行囊有一…

如何用python的Turtle绘画?

目录 一、画一个圆和正方形 二、简单的方式来画一个美女 三、Turtle是一个用于绘制图形的标准库 一、画一个圆和正方形 import turtle# 创建一个图形窗口 window turtle.Screen() window.bgcolor("white")# 创建一个海龟画笔 pen turtle.Turtle() pen.shape(&q…

Maven 插件使用

1.spring-boot-maven-plugin 我们直接使用 maven package &#xff08;maven自带的package打包功能&#xff09;&#xff0c;打包Jar包的时候&#xff0c;不会将该项目所依赖的Jar包一起打进去&#xff0c;在使用java -jar命令启动项目时会报错&#xff0c;项目无法正常启动。…