unity可否将多张地图载入到同一个场景中,同时保留lightmap信息

 我来答
点点通软件公司
2016-12-02 · TA获得超过922个赞
知道小有建树答主
回答量:650
采纳率:89%
帮助的人:137万
展开全部
为什么要动态更新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;
}
}
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式