[总结] Unity Lightmap使用总结

您所在的位置:网站首页 unity灯光贴图 [总结] Unity Lightmap使用总结

[总结] Unity Lightmap使用总结

2024-01-15 21:41| 来源: 网络整理| 查看: 265

Unity Lightmap使用总结 一 、动态加载 lightmap 给 Prefab效果操作步骤1. 烘焙光照贴图2. 记录光照信息3. 加载光照信息 遇到的问题(已解决)1. 光照贴图错位问题(已解决) 详细代码LightmapRoot.csLightmapRootEditor.cs 二 、 动态加载 lightmap 给 Scene举个栗子吧

关于“lightmap 动态加载”有两种解释:

一、动态加载 lightmap 给 Prefab : 可用于克隆出多个对象使用同一个光照贴图

二、动态加载 lightmap 给 Scene :可用于不同天气环境的动态切换

一 、动态加载 lightmap 给 Prefab 效果

xiaoguo

操作步骤 1. 烘焙光照贴图

先将预制体对象设置为 Lightmap Static 并放在场景中,如下图,具体操作就不细说了。可以在 MeshRenderer 组件上看到,该对象的 Baked Lightmap 信息:

{ LightmapIndex = 65535, LightmapScaleOffset = new Vector4 (1,1,0,0) }

然后在Lighting Settings 中勾选 Mixed Lighting ,其他设置自行选择,点击 Generate Lighting 生成光照贴图,再次查看预制体对象的光照贴图信息,与没有烘焙前不一样了,其中:

{ LightmapIndex = 使用的第几张光照贴图, LightmapScaleOffset = 在光照贴图中使用的 UV 大小和偏移 }

再次选择一个预制体,拖放进场景中,发现的并没有光照效果,查看 Baked Lightmap 信息:

{ LightmapIndex = 65535, LightmapScaleOffset = new Vector4 (1,1,0,0) }

可以得出结论:烘焙的光照贴图信息(Baked Lightmap)不会保存到预制体上。于是就有了下一步——记录烘焙的光照贴图信息。

before after

2. 记录光照信息

这一步主要是编写脚本(详细代码附在最后),用递归获取并保存此对象及所有子对象的烘焙光照贴图信息,包括:

{ LightmapIndex(int),LightmapScaleOffset(Vector4) }

考虑到运行状态下赋值时多对象 GetComponment() 耗费性能,所以在编辑器状态下记录光照信息时同时保存 MeshRenderer 的引用,所以保存的信息的数据结构可以为:

//(详细代码附在最后) [Serializable] public struct CustomLightmapData { public MeshRenderer _renderer; public int _lightmapIndex; public Vector4 _lightmapScaleOffset; } 3. 加载光照信息

这一步主要是将上一步保存的烘焙信息重新赋值给相应的 Mesh Renderer 组件(代码附在最后)

遇到的问题(已解决) 1. 光照贴图错位问题(已解决)

可以看到 Console 面板提示的警告:

warning

主要意思是:在对象静态批处理后无法再为 Baked Lightmap 赋值,解决办法就是在 Awake() 函数里进行赋值(代码附在最后)或者取消对象的静态批处理(不推荐)

详细代码 LightmapRoot.cs using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public class LightmapRoot : MonoBehaviour { public List _datas; void Start() { SetAllLightmapData(); } public void GetAllLightmapData() { _datas = new List(); GetChildData(transform); } public void SetAllLightmapData() { if (_datas == null) return; for (int i = 0; i if (parent.gameObject.isStatic) { var render = parent.GetComponent(); if (render != null) { _datas.Add(new CustomLightmapData(render, render.lightmapIndex, render.lightmapScaleOffset)); } for (int i = 0; i // if (parent.gameObject.isStatic) // { // var render = parent.GetComponent(); // if (render != null) // { // ++index; // var data = _datas[index]; // render.lightmapIndex = data._lightmapIndex; // render.lightmapScaleOffset = data._lightmapScaleOffset; // } // // for (int i = 0; i < parent.childCount; i++) // { // SetChildData(parent.GetChild(i), index); // } // } // } } [Serializable] public struct CustomLightmapData { public MeshRenderer _renderer; public int _lightmapIndex; public Vector4 _lightmapScaleOffset; public CustomLightmapData(MeshRenderer renderer, int lightmapIndex, Vector4 lightmapScaleOffset) { _renderer = renderer; _lightmapIndex = lightmapIndex; _lightmapScaleOffset = lightmapScaleOffset; } } LightmapRootEditor.cs using UnityEditor; using UnityEngine; [CustomEditor(typeof(LightmapRoot))] public class LightmapRootEditor : Editor { private LightmapRoot Root { get { return target as LightmapRoot; } } public override void OnInspectorGUI() { base.OnInspectorGUI(); GUILayout.Space(10); if (GUILayout.Button("SaveLightmapData")) { Root.GetAllLightmapData(); SavePrefab(); } GUILayout.Space(10); if (GUILayout.Button("SetLightmapData")) { Root.SetAllLightmapData(); } } private void SavePrefab() { var prefab = PrefabUtility.GetCorrespondingObjectFromSource(Root); if (prefab != null) { PrefabUtility.ReplacePrefab(Root.gameObject, prefab); } } } 二 、 动态加载 lightmap 给 Scene

相当于动态切换场景的 lightmap,实现的核心逻辑是:

[SerializeField] private Texture2D _lightmapColor; [SerializeField] private Texture2D _lightmapDir; [SerializeField] private Texture2D _shadowMask; public void ResetLightmapData() { LightmapSettings.lightmaps = new[] {new LightmapData {lightmapColor = _lightmapColor, lightmapDir = _lightmapDir, shadowMask = _shadowMask}}; } 举个栗子吧

lightmap

在王者荣耀中切换查看英雄时,要根据英雄的阵营(背景故事)切换不同的背景,此功能肯定不能通过切换场景实现,那样太慢了,所以根据上面的思路:

将不同的背景做成预制体,烘焙好光照贴图

在 LightmapRoot 中增加字段,保存对光照贴图的引用

(上面的图中两张贴图分别记录了光照信息 lightmapColor 和方向信息 lightmapDir )

切换英雄时动态加载背景预制体,设置场景的光照贴图

这个栗子同时包含了以上提到的两个 lightmap 动态加载 👍



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3