using System; using System.IO; using UnityEditor; using UnityEditor.SceneManagement; using UnityEngine; namespace Thousandto.Editor.Test { public static class LightMapUtil { public static void CalcLightmapInfo(Renderer render) { } //如果不存在uv2,则使用uv代替 public static Vector2[] GetMeshUV2(Mesh m) { var uv2 = m.uv2; if (uv2 == null || uv2.Length == 0) uv2 = m.uv; return uv2; } /// /// 计算该renderer在lightmap贴图中的包围范围 /// /// uv2光照uv /// /// (minx, miny, maxX, maxY) public static Vector4 GetBounds(Vector2[] uv, Renderer r) { if (uv != null) { var __uv = new Vector2[uv.Length]; Array.Copy(uv, __uv, uv.Length); uv = __uv; var minx = float.MaxValue; var miny = float.MaxValue; var maxx = float.MinValue; var maxy = float.MinValue; for (var _j = 0; _j < uv.Length; ++_j) { var _uv = uv[_j]; if (_uv.x < minx) { minx = _uv.x; } if (_uv.y < miny) { miny = _uv.y; } if (_uv.x > maxx) { maxx = _uv.x; } if (_uv.y > maxy) { maxy = _uv.y; } } var bounds = new Vector4(minx, miny, maxx, maxy); return bounds; } return Vector4.zero; } public static float GetScaleInLightmap(Renderer rd) { UnityEditor.SerializedObject so = new UnityEditor.SerializedObject(rd); var sp = so.FindProperty("m_ScaleInLightmap"); return sp.floatValue; } //烘焙场景时,可以指定GameObject的bake tag,相同tag的物件的光照信息会生成到同以一张贴图中 public static void SetRenderLightmapParameters(Renderer renderer, string giparamsFile = "Assets/GameAssets/Resources/Scene/AAA.giparams") { SerializedObject so = new SerializedObject(renderer); var sp = so.FindProperty("m_LightmapParameters"); sp.objectReferenceValue = AssetDatabase.LoadAssetAtPath(giparamsFile, typeof(LightmapParameters)); so.ApplyModifiedProperties(); } //创建LightmapParameters资源文件 public static void CreateLightmapParameterFile(string path, int bakeTag) { LightmapParameters lp = new LightmapParameters(); lp.bakedLightmapTag = bakeTag; AssetDatabase.CreateAsset(lp, path); AssetDatabase.ImportAsset(path); } //从整lightmap贴图中扣指定物件的光照贴图 public static Texture2D PickLightmap(GameObject go, out Vector4 sourceBounds, out Vector4 scaleBounds, out Rect pickRect) { pickRect = new Rect(); sourceBounds = Vector4.zero; scaleBounds = Vector4.zero; if (go == null) return null; var meshFilter = go.GetComponent(); var renderer = go.GetComponent(); if (meshFilter == null || renderer == null) return null; var tex = GetFullLightmap(renderer); if (tex == null) return null; var uv2s = GetMeshUV2(meshFilter.sharedMesh); //var bounds = GetBounds(uv2s, renderer); sourceBounds = LightMapUtil.GetBounds(uv2s, renderer); scaleBounds = CalcBoundWithLightmapScaleOffset(sourceBounds, renderer.lightmapScaleOffset); return PickTexture(tex, scaleBounds, out pickRect); } public static Vector4 CalcBoundWithLightmapScaleOffset(Vector4 sourceBounds, Vector4 lightmapScaleOffset) { var scaleBounds = new Vector4(sourceBounds.x * lightmapScaleOffset.x + lightmapScaleOffset.z, sourceBounds.y * lightmapScaleOffset.y + lightmapScaleOffset.w, sourceBounds.z * lightmapScaleOffset.x + lightmapScaleOffset.z, sourceBounds.w * lightmapScaleOffset.y + lightmapScaleOffset.w); return scaleBounds; } public static Texture2D PickTexture(Texture2D sourceTex, Vector4 bounds, out Rect pickRect) { pickRect = new Rect(); var blockW = ((bounds.z - bounds.x) * sourceTex.width); var blockH = ((bounds.w - bounds.y) * sourceTex.height); var startX = Mathf.RoundToInt(bounds.x * sourceTex.width); var startY = Mathf.RoundToInt(bounds.y * sourceTex.height); if(blockW - (int)blockW > 0.11f) { blockW += 1; } if(blockH - (int)blockH > 0.11f) { blockH += 1; } int w = (int)blockW; int h = (int)blockH; //startY = (tex.height - startY - blockH); if (blockH == 0 || blockW == 0) return null; if (startX + w > sourceTex.width) w--; if (startY + h > sourceTex.height) h--; pickRect.x = startX; pickRect.y = startY; pickRect.width = w; pickRect.height = h; var colors = sourceTex.GetPixels(startX, startY, w, h); Texture2D tex2d = new Texture2D(w, h); tex2d.SetPixels(colors); tex2d.Apply(); return tex2d; } //从整lightmap贴图中扣指定物件的光照贴图 public static Texture2D PickLightmap(Renderer renderer, out Vector4 bound, out Vector4 scaleBound, out Rect pickRect) { GameObject go = renderer.gameObject; return PickLightmap(go, out bound, out scaleBound, out pickRect); } public static Texture2D GetFullLightmap(Renderer rd) { int lightmapIndex = rd.lightmapIndex; var lightmaps = LightmapSettings.lightmaps; if(lightmaps.Length == 0) { UnityEngine.Debug.LogError("No lightmap in current scene: " + EditorSceneManager.GetActiveScene().name); return null; } if(lightmapIndex == -1) { UnityEngine.Debug.LogError("lightmapIndex is -1 : " + rd.name); return null; } if(lightmapIndex >= lightmaps.Length) { UnityEngine.Debug.LogError("Renderer index out of range: " + lightmapIndex + " name: " + rd.name); return null; } var tex = lightmaps[lightmapIndex].lightmapColor; var path = AssetDatabase.GetAssetPath(tex); if(File.Exists(path)) { TextureImporter ti = AssetImporter.GetAtPath(path) as TextureImporter; if (!ti.isReadable) { ti.isReadable = true; ti.SaveAndReimport(); } } return tex; } public static Texture2D CreateEmptyTexture(int width, int height, TextureFormat format) { Texture2D tex = new Texture2D(width, height, TextureFormat.RGBA32, false); Color[] color = new Color[width * height]; for (int i = 0; i < color.Length; ++i) { color[i] = new Color(0, 0, 0, 0); } tex.SetPixels(color); return tex; } [MenuItem("Test/Create/LightmapParameters")] static void TestCreate() { CreateLightmapParameterFile("Assets/GameAssets/Resources/Scene/1.giparams", 1); } } }