Files
JJBB/Assets/Project/Script/Common/Utilities/Editor/LightmapSeperate.cs

165 lines
6.5 KiB
C#
Raw Normal View History

2024-08-23 15:49:34 +08:00
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.SceneManagement;
using Object = UnityEngine.Object;
public class LightmapSeperate
{
public const string lightmapFormat = "Assets/Res_newMS/LightmapParameters/Lightmap{0}.giparams";
public const int textureSize = 1024;
public const float atlasFillRatio = 1f;
[MenuItem("Scene/Bake Scene 烘培当前场景", false, 1)]
public static void SeperateLightmaps()
{
var resolution = LightmapEditorSettings.bakeResolution;
var allMaterials = new List<LightmapSizeData>();
var meshRenderers = Object.FindObjectsOfType<MeshRenderer>();
for (var i = 0; i < meshRenderers.Length; i++)
{
var meshRenderer = meshRenderers[i];
if (meshRenderer.gameObject.isStatic)
{
var serialized = new SerializedObject(meshRenderer);
var property = serialized.FindProperty("m_ScaleInLightmap");
if (property != null && property.floatValue > 0.5f)
{
property.floatValue = 0.5f;
serialized.ApplyModifiedProperties();
}
var mainMaterial = meshRenderer.sharedMaterial;
if (mainMaterial == null)
Debug.LogError("物体没有材质 " + meshRenderer.transform.GetHierarchyName());
else
{
var lightmapSize = allMaterials.GetItem(mainMaterial, ListGetMode.create);
lightmapSize.AddMeshRenderer(meshRenderer, resolution);
}
}
}
for (var i = allMaterials.Count - 1; i >= 0; i--)
if (!allMaterials[i].IsBakable())
{
allMaterials[i].SetLightmapParameters(null);
allMaterials.RemoveAt(i);
}
// 试图合并光照贴图
allMaterials.Sort((a, b) => -a.totalSize.CompareTo(b.totalSize));
for (var i = allMaterials.Count - 1; i >= 0; i--)
{
var material = allMaterials[i];
if (material.rendererList.Count < 1)
{
allMaterials.RemoveAt(i);
material.SetLightmapParameters(null);
}
}
var lightmapList = new List<LightmapParamData>();
while (allMaterials.Count > 0)
{
var lightmapData = new LightmapParamData();
lightmapList.Add(lightmapData);
lightmapData.AddLightmap(allMaterials, 0);
var index = allMaterials.FindIndex(a => a.totalSize + lightmapData.totalSize < textureSize * textureSize * atlasFillRatio);
while (index >= 0)
{
lightmapData.AddLightmap(allMaterials, index);
index = allMaterials.FindIndex(a => a.totalSize + lightmapData.totalSize < textureSize * textureSize * atlasFillRatio);
}
}
var source = AssetDatabase.LoadAssetAtPath<LightmapParameters>(string.Format(lightmapFormat, 0));
for (var i = 0; i < lightmapList.Count; i++)
{
LightmapParameters target;
if (i == 0)
target = source;
else
{
var path = string.Format(lightmapFormat, i);
target = AssetDatabase.LoadAssetAtPath<LightmapParameters>(path);
if (target == null)
{
target = Object.Instantiate(source);
target.bakedLightmapTag = i;
EditorUtility.SetDirty(target);
AssetDatabase.CreateAsset(target, path);
}
}
var lightmap = lightmapList[i];
lightmap.SetLightmapParameters(target);
}
EditorSceneManager.MarkAllScenesDirty();
AssetDatabase.Refresh();
// 配置标准化烘培参数
LightmapEditorSettings.maxAtlasHeight = textureSize;
#if UNITY_2018
LightmapEditorSettings.maxAtlasSize = textureSize;
#endif
Lightmapping.BakeAsync();
}
public class LightmapParamData
{
public readonly List<LightmapSizeData> lightmapSizeList = new List<LightmapSizeData>();
public float totalSize { get; private set; }
public void AddLightmap(List<LightmapSizeData> list, int index)
{
var item = list[index];
list.RemoveAt(index);
totalSize += item.totalSize;
lightmapSizeList.Add(item);
}
public void SetLightmapParameters(LightmapParameters lightmapParameters)
{
for (var i = 0; i < lightmapSizeList.Count; i++)
{
var lightmap = lightmapSizeList[i];
lightmap.SetLightmapParameters(lightmapParameters);
}
}
}
public class LightmapSizeData : ListItemBase<Material>
{
public readonly List<MeshRenderer> rendererList = new List<MeshRenderer>();
public float totalSize { get; private set; }
public void AddMeshRenderer(MeshRenderer meshRenderer, float resolution)
{
var serializedObject = new SerializedObject(meshRenderer);
var serializedProperty = serializedObject.FindProperty("m_ScaleInLightmap");
if (serializedProperty != null)
{
var bounds = meshRenderer.bounds;
var size = bounds.size.x * bounds.size.y + bounds.size.y * bounds.size.z +
bounds.size.z * bounds.size.x;
rendererList.Add(meshRenderer);
var scale = resolution * serializedProperty.floatValue;
totalSize += size * scale * scale;
}
}
public bool IsBakable()
{
// Unity当前版本无法有效拿到Fallback里面继承的通道
// 当前条件下使用Forward通道的都会参加烘培所以暂时用这个流程替代
return id.FindPass("META") > -1 || id.FindPass("FORWARD") > -1;
}
public void SetLightmapParameters(LightmapParameters lightmapParameters)
{
for (var i = 0; i < rendererList.Count; i++)
{
var meshRenderer = rendererList[i];
var serializedObject = new SerializedObject(meshRenderer);
var serializedProperty = serializedObject.FindProperty("m_LightmapParameters");
serializedProperty.objectReferenceValue = lightmapParameters;
serializedObject.ApplyModifiedProperties();
}
}
}
}