165 lines
6.5 KiB
C#
165 lines
6.5 KiB
C#
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();
|
||
}
|
||
}
|
||
}
|
||
} |