Files
JJBB/Assets/Project/Script/Common/Utilities/Editor/LightmapSeperate.cs
2024-08-23 15:49:34 +08:00

165 lines
6.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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();
}
}
}
}