参考链接:http://www.xuanyusong.com/archives/3807
其它关于Unity5的光照系统神马的,网上很多资源,这几个文章良大本人觉得是很有价值的:
Unity 5 中的全局光照技术详解
http://www.gameres.com/forum.php?mod=viewthread&tid=446301
详解Unity 5 全局光照系统Enlighten问题
http://forum.china.unity3d.com/thread-14559-1-1.html
http://forum.china.unity3d.com/thread-14700-1-1.html
为什么要动态更新Lightmap
项目内需要对项目进行动态更新或者制作如白天黑夜等,同一场景不同光照渲染的情况。
将场景(.unity)文件转换成(.prefab)文件,能够更加*的操作场景资源的更换。
修改功能支持
- 添加多张光照贴图烘焙
具体代码如下:
using UnityEngine;
using System.Collections.Generic;
using System.IO;
using GOE.Scene;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine.SceneManagement;
using SceneManager = UnityEngine.SceneManagement.SceneManager;
/// <summary>
/// 描述:动态烘焙场景光照模型,并产生对应的Prefab文件
/// <para>创建时间:2016-06-15</para>
/// </summary>
public sealed class LightMapEditor
{
private const string LightMapsDir = "Resources/Lightmaps/";
private static List<RemapTexture2D> sceneLightmaps = new List<RemapTexture2D>();
public static void UpdateLightmaps()
{
PrefabLightmapData pld = GameObject.FindObjectOfType<PrefabLightmapData>();
if (pld == null) return;
LightmapSettings.lightmaps = null;
PrefabLightmapData.ApplyLightmaps(pld.mRendererInfos , pld.mLightmapFars , pld.mLightmapNears);
Debug.Log("Prefab Lightmap updated");
}
public static void GenLightmap()
{
genBakeLightmapAndPrefab(false);
EditorSceneManager.SaveOpenScenes();
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Debug.Log("----------------Update to Prefab Lightmap Finish -------------------------");
}
/// <summary>
/// 生成lightmap和prefab资源
/// </summary>
private static void genBakeLightmapAndPrefab()
{
if (Lightmapping.giWorkflowMode != Lightmapping.GIWorkflowMode.OnDemand)
{
Debug.LogError("ExtractLightmapData requires that you have baked you lightmaps and Auto mode is disabled.");
return;
}
Debug.ClearDeveloperConsole();
PrefabLightmapData[] pldArr = GameObject.FindObjectsOfType<PrefabLightmapData>();
if (pldArr == null || pldArr.Length <= 0)
{
EditorUtility.DisplayDialog("提示", "没有找到必要的脚本PrefabLightmapData,请检查场景", "OK");
return;
}
Lightmapping.Bake();
sceneLightmaps.Clear();
string path = Path.Combine(Application.dataPath, LightMapsDir);
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
Scene curScene = EditorSceneManager.GetActiveScene();
string sceneName = Path.GetFileNameWithoutExtension(curScene.name);
string scenePath = Path.GetDirectoryName(curScene.path) + "/" + sceneName + "/";
string resourcesPath = Path.GetDirectoryName(curScene.path) + "/" + sceneName + "_lightmap/" + sceneName;
foreach (PrefabLightmapData pld in pldArr)
{
GameObject gObj = pld.gameObject;
List<RendererInfo> renderers = new List<RendererInfo>();
List<Texture2D> lightmapFars = new List<Texture2D>();
List<Texture2D> lightmapNears = new List<Texture2D>();
genLightmapInfo(scenePath, resourcesPath, gObj, renderers, lightmapFars, lightmapNears);
pld.mRendererInfos = renderers.ToArray();
pld.mLightmapFars = lightmapFars.ToArray();
pld.mLightmapNears = lightmapNears.ToArray();
GameObject targetPrefab = PrefabUtility.GetPrefabParent(gObj) as GameObject;
if (targetPrefab != null)
{
//自定义存放的路径
PrefabUtility.ReplacePrefab(gObj, targetPrefab);
}
else
{
//默认路径
string prefabPath = Path.GetDirectoryName(curScene.path) + "/" + sceneName + ".prefab";
PrefabUtility.CreatePrefab(prefabPath, gObj, ReplacePrefabOptions.ConnectToPrefab);
}
//改变当前场景中的光照贴图信息
PrefabLightmapData.ApplyLightmaps(pld.mRendererInfos, pld.mLightmapFars, pld.mLightmapNears);
}
}
private static void genLightmapInfo(string scenePath , string resourcePath , GameObject root,
List<RendererInfo> renderers, List<Texture2D> lightmapFars,
List<Texture2D> lightmapNears)
{
MeshRenderer[] subRenderers = root.GetComponentsInChildren<MeshRenderer>();
LightmapData[] srcLightData = LightmapSettings.lightmaps;
foreach (MeshRenderer meshRenderer in subRenderers)
{
if(meshRenderer.lightmapIndex == -1) continue;
RendererInfo renderInfo = new RendererInfo();
renderInfo.renderer = meshRenderer;
renderInfo.LightmapIndex = meshRenderer.lightmapIndex;
renderInfo.LightmapOffsetScale = meshRenderer.lightmapScaleOffset;
Texture2D lightmapFar = srcLightData[meshRenderer.lightmapIndex].lightmapFar;
Texture2D lightmapNear = srcLightData[meshRenderer.lightmapIndex].lightmapNear;
int sceneCacheIndex = addLightmap(scenePath, resourcePath, renderInfo.LightmapIndex, lightmapFar,
lightmapNear);
renderInfo.LightmapIndex = lightmapFars.IndexOf(sceneLightmaps[sceneCacheIndex].LightmapFar);
if (renderInfo.LightmapIndex == -1)
{
renderInfo.LightmapIndex = lightmapFars.Count;
lightmapFars.Add(sceneLightmaps[sceneCacheIndex].LightmapFar);
lightmapNears.Add(sceneLightmaps[sceneCacheIndex].LightmapNear);
}
renderers.Add(renderInfo);
}
}
private static int addLightmap(string scenePath, string resourcePath, int originalLightmapIndex,
Texture2D lightmapFar,
Texture2D lightmapNear)
{
for (int i = 0; i < sceneLightmaps.Count; i++)
{
if (sceneLightmaps[i].OriginalLightmapIndex == originalLightmapIndex)
{
return i;
}
}
RemapTexture2D remapTex = new RemapTexture2D();
remapTex.OriginalLightmapIndex = originalLightmapIndex;
remapTex.OrginalLightmap = lightmapFar;
string fileName = scenePath + "Lightmap-" + originalLightmapIndex;
remapTex.LightmapFar = getLightmapAsset(fileName + "_comp_light.exr", resourcePath + "_light",
originalLightmapIndex);
if(lightmapNear != null)
remapTex.LightmapNear = getLightmapAsset(fileName + "_comp_dir.exr", resourcePath + "_dir",
originalLightmapIndex);
sceneLightmaps.Add(remapTex);
return sceneLightmaps.Count - 1;
}
private static Texture2D getLightmapAsset(string fileName, string resourecPath, int originalLightmapIndex)
{
TextureImporter importer = AssetImporter.GetAtPath(fileName) as TextureImporter;
if (importer == null) return null;
importer.isReadable = true;
AssetDatabase.ImportAsset(fileName , ImportAssetOptions.ForceUpdate);
Texture2D assetLightmap = AssetDatabase.LoadAssetAtPath<Texture2D>(fileName);
string assetPath = resourecPath + "_" + originalLightmapIndex + ".asset";
Texture2D newLightmap = GameObject.Instantiate<Texture2D>(assetLightmap);
string dir = Path.GetDirectoryName(assetPath);
if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
// byte[] bytes = newLightmap.EncodeToPNG();
// File.WriteAllBytes(assetPath, bytes);
AssetDatabase.CreateAsset(newLightmap , assetPath);
newLightmap = AssetDatabase.LoadAssetAtPath<Texture2D>(assetPath);
importer.isReadable = false;
AssetDatabase.ImportAsset(assetPath , ImportAssetOptions.ForceUpdate);
return newLightmap;
}
}
PrefabLightData
用于还原和记录光照数据
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace GOE.Scene
{
/// <summary>
/// 描述:光照模型预设
/// </summary>
[DisallowMultipleComponent , ExecuteInEditMode]
public class PrefabLightmapData : MonoBehaviour
{
[SerializeField]
public RendererInfo[] mRendererInfos;
[SerializeField]
public Texture2D[] mLightmapFars;
[SerializeField]
public Texture2D[] mLightmapNears;
void Awake()
{
ApplyLightmaps(mRendererInfos , mLightmapFars , mLightmapNears);
//设置原来烘焙时的光照模式,这个不设置正确,默认模式就会只显示光照贴图
LightmapSettings.lightmapsMode = LightmapsMode.NonDirectional;
}
void Start()
{
// StaticBatchingUtility.Combine(this.gameObject);
}
/// <summary>
/// 应用光照模型,根据指定的渲染信息
/// </summary>
/// <param name="rendererInfos"></param>
/// <param name="lightmapFars"></param>
/// <param name="lightmapNears"></param>
public static void ApplyLightmaps(RendererInfo[] rendererInfos, Texture2D[] lightmapFars,
Texture2D[] lightmapNears)
{
if (rendererInfos == null || rendererInfos.Length <= 0)
{
Debug.LogWarning("<<PrefabLightmapData , ApplyLightmaps>> renderer info is null !");
return;
}
LightmapData[] settingLightMaps = LightmapSettings.lightmaps;
int[] lightmapOffsetIndex = new int[lightmapFars.Length];
List<LightmapData> combinedLightmaps = new List<LightmapData>();
bool existAlready = false;
for (int i = 0; i < lightmapFars.Length; i++)
{
existAlready = false;
for (int j = 0; j < settingLightMaps.Length; j++)
{
if (lightmapFars[i] == settingLightMaps[j].lightmapFar)
{
lightmapOffsetIndex[i] = j;
existAlready = true;
break;
}
}
//如果不存在,则创建新的光照数据
if (!existAlready)
{
lightmapOffsetIndex[i] = settingLightMaps.Length + combinedLightmaps.Count;
LightmapData newLightData = new LightmapData();
newLightData.lightmapFar = lightmapFars[i];
newLightData.lightmapNear = lightmapNears[i];
combinedLightmaps.Add(newLightData);
}
}
//组合数据
LightmapData[] finalCombinedLightData = new LightmapData[combinedLightmaps.Count + settingLightMaps.Length];
settingLightMaps.CopyTo(finalCombinedLightData , 0);
combinedLightmaps.CopyTo(finalCombinedLightData , settingLightMaps.Length);
combinedLightmaps.Clear();
applyRendererInfo(rendererInfos , lightmapOffsetIndex);
//重新绑定
LightmapSettings.lightmaps = finalCombinedLightData;
}
/// <summary>
/// 应用渲染信息
/// </summary>
/// <param name="rendererInfos"></param>
/// <param name="offsetIndexs"></param>
private static void applyRendererInfo(RendererInfo[] rendererInfos, int[] offsetIndexs)
{
for (int i = 0; i < rendererInfos.Length; i++)
{
RendererInfo info = rendererInfos[i];
info.renderer.lightmapIndex = offsetIndexs[info.LightmapIndex];
info.renderer.lightmapScaleOffset = info.LightmapOffsetScale;
}
}
}
}
其它脚本
using UnityEngine;
namespace GOE.Scene
{
/// <summary>
/// 渲染信息
/// </summary>
[System.Serializable]
public struct RendererInfo
{
public Renderer renderer;
public int LightmapIndex;
public Vector4 LightmapOffsetScale; //偏移和缩放
}
/// <summary>
/// 重渲贴图
/// </summary>
[System.Serializable]
public struct RemapTexture2D
{
public int OriginalLightmapIndex;
public Texture2D OrginalLightmap;
public Texture2D LightmapFar;
public Texture2D LightmapNear;
}
}