231 lines
8.1 KiB
C#
231 lines
8.1 KiB
C#
|
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;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 计算该renderer在lightmap贴图中的包围范围
|
|||
|
/// </summary>
|
|||
|
/// <param name="uv">uv2光照uv</param>
|
|||
|
/// <param name="r"></param>
|
|||
|
/// <returns>(minx, miny, maxX, maxY)</returns>
|
|||
|
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<MeshFilter>();
|
|||
|
var renderer = go.GetComponent<Renderer>();
|
|||
|
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);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|