我们创建了 Fontainebleau 演示来说明摄影photogrammetry流程和 LayeredLit 着色器的使用。
您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

383 行
14 KiB

using UnityEngine;
using UnityEngine.SceneManagement;
using System;
using System.Collections.Generic;
using UnityEngine.Rendering;
using System.Collections;
#if UNITY_EDITOR
using UnityEditor;
#endif
[ExecuteInEditMode]
public class LevelLightmapData : MonoBehaviour
{
[System.Serializable]
public class SphericalHarmonics
{
public float[] coefficients = new float[27];
}
[System.Serializable]
public class RendererInfo
{
public Renderer renderer;
public int lightmapIndex;
public Vector4 lightmapOffsetScale;
}
[System.Serializable]
public class LightingScenarioData {
public RendererInfo[] rendererInfos;
public Texture2D[] lightmaps;
public Texture2D[] lightmapsDir;
public Texture2D[] shadowMasks;
public LightmapsMode lightmapsMode;
public SphericalHarmonics[] lightProbes;
public bool hasRealtimeLights;
}
public bool latestBuildHasReltimeLights;
public bool allowLoadingLightingScenes = true;
[SerializeField]
List<LightingScenarioData> lightingScenariosData;
#if UNITY_EDITOR
[SerializeField]
public List<SceneAsset> lightingScenariosScenes;
#endif
[SerializeField]
public String[] lightingScenesNames = new string[1];
public int currentLightingScenario = -1;
public int previousLightingScenario = -1;
private Coroutine m_SwitchSceneCoroutine;
[SerializeField]
public int lightingScenariosCount;
//TODO : enable logs only when verbose enabled
public bool verbose = false;
private List<SphericalHarmonicsL2[]> lightProbesRuntime = new List<SphericalHarmonicsL2[]>();
public void LoadLightingScenario(int index)
{
if(index != currentLightingScenario)
{
previousLightingScenario = currentLightingScenario == -1 ? index : currentLightingScenario;
currentLightingScenario = index;
LightmapSettings.lightmapsMode = lightingScenariosData[index].lightmapsMode;
if(allowLoadingLightingScenes)
m_SwitchSceneCoroutine = StartCoroutine(SwitchSceneCoroutine(lightingScenesNames[previousLightingScenario], lightingScenesNames[currentLightingScenario]));
var newLightmaps = LoadLightmaps(index);
ApplyRendererInfo(lightingScenariosData[index].rendererInfos);
LightmapSettings.lightmaps = newLightmaps;
LoadLightProbes(currentLightingScenario);
}
}
private void Start()
{
PrepareLightProbeArrays();
}
private void PrepareLightProbeArrays()
{
for (int x = 0; x < lightingScenariosCount; x++)
{
lightProbesRuntime.Add(DeserializeLightProbes(x));
}
}
private SphericalHarmonicsL2[] DeserializeLightProbes(int index)
{
var sphericalHarmonicsArray = new SphericalHarmonicsL2[lightingScenariosData[index].lightProbes.Length];
for (int i = 0; i < lightingScenariosData[index].lightProbes.Length; i++)
{
var sphericalHarmonics = new SphericalHarmonicsL2();
// j is coefficient
for (int j = 0; j < 3; j++)
{
//k is channel ( r g b )
for (int k = 0; k < 9; k++)
{
sphericalHarmonics[j, k] = lightingScenariosData[index].lightProbes[i].coefficients[j * 9 + k];
}
}
sphericalHarmonicsArray[i] = sphericalHarmonics;
}
return sphericalHarmonicsArray;
}
IEnumerator SwitchSceneCoroutine(string sceneToUnload, string sceneToLoad)
{
AsyncOperation unloadop = null;
AsyncOperation loadop = null;
if (sceneToUnload != null && sceneToUnload != string.Empty && sceneToUnload != sceneToLoad)
{
unloadop = SceneManager.UnloadSceneAsync(sceneToUnload);
while (!unloadop.isDone)
{
yield return new WaitForEndOfFrame();
}
}
if(sceneToLoad != null && sceneToLoad != string.Empty && sceneToLoad != "")
{
loadop = SceneManager.LoadSceneAsync(sceneToLoad, LoadSceneMode.Additive);
while ((!loadop.isDone || loadop == null))
{
yield return new WaitForEndOfFrame();
}
SceneManager.SetActiveScene(SceneManager.GetSceneByName(sceneToLoad));
}
LoadLightProbes(currentLightingScenario);
}
LightmapData[] LoadLightmaps(int index)
{
if (lightingScenariosData[index].lightmaps == null
|| lightingScenariosData[index].lightmaps.Length == 0)
{
Debug.LogWarning("No lightmaps stored in scenario " + index);
return null;
}
var newLightmaps = new LightmapData[lightingScenariosData[index].lightmaps.Length];
for (int i = 0; i < newLightmaps.Length; i++)
{
newLightmaps[i] = new LightmapData();
newLightmaps[i].lightmapColor = lightingScenariosData[index].lightmaps[i];
if (lightingScenariosData[index].lightmapsMode != LightmapsMode.NonDirectional)
{
newLightmaps[i].lightmapDir = lightingScenariosData[index].lightmapsDir[i];
}
if (lightingScenariosData[index].shadowMasks.Length > 0)
{
newLightmaps[i].shadowMask = lightingScenariosData[index].shadowMasks[i];
}
}
return newLightmaps;
}
public void ApplyRendererInfo(RendererInfo[] infos)
{
try
{
Terrain terrain = FindObjectOfType<Terrain>();
int i = 0;
if (terrain != null)
{
terrain.lightmapIndex = infos[i].lightmapIndex;
terrain.lightmapScaleOffset = infos[i].lightmapOffsetScale;
i++;
}
for (int j = i; j < infos.Length; j++)
{
RendererInfo info = infos[j];
//if (info.renderer == null)
//continue;
info.renderer.lightmapIndex = infos[j].lightmapIndex;
if (!info.renderer.isPartOfStaticBatch)
{
info.renderer.lightmapScaleOffset = infos[j].lightmapOffsetScale;
}
if (info.renderer.isPartOfStaticBatch && verbose == true && Application.isEditor)
{
Debug.Log("Object " + info.renderer.gameObject.name + " is part of static batch, skipping lightmap offset and scale.");
}
}
}
catch (Exception e)
{
Debug.LogError("Error in ApplyRendererInfo:" + e.GetType().ToString());
}
}
public void LoadLightProbes(int index)
{
if (Application.isEditor && !Application.isPlaying)
{
PrepareLightProbeArrays();
}
try
{
LightmapSettings.lightProbes.bakedProbes = lightProbesRuntime[index];
}
catch { Debug.LogWarning("Warning, error when trying to load lightprobes for scenario " + index); }
}
public void StoreLightmapInfos(int index)
{
var newLightingScenarioData = new LightingScenarioData ();
var newRendererInfos = new List<RendererInfo>();
var newLightmapsTextures = new List<Texture2D>();
var newLightmapsTexturesDir = new List<Texture2D>();
var newLightmapsMode = new LightmapsMode();
var newSphericalHarmonicsList = new List<SphericalHarmonics>();
var newLightmapsShadowMasks = new List<Texture2D>();
newLightmapsMode = LightmapSettings.lightmapsMode;
GenerateLightmapInfo(gameObject, newRendererInfos, newLightmapsTextures, newLightmapsTexturesDir, newLightmapsShadowMasks, newLightmapsMode);
newLightingScenarioData.lightmapsMode = newLightmapsMode;
newLightingScenarioData.lightmaps = newLightmapsTextures.ToArray();
if (newLightmapsMode != LightmapsMode.NonDirectional)
{
newLightingScenarioData.lightmapsDir = newLightmapsTexturesDir.ToArray();
}
//Mixed or realtime support
newLightingScenarioData.hasRealtimeLights = latestBuildHasReltimeLights;
newLightingScenarioData.shadowMasks = newLightmapsShadowMasks.ToArray();
newLightingScenarioData.rendererInfos = newRendererInfos.ToArray();
var scene_LightProbes = new SphericalHarmonicsL2[LightmapSettings.lightProbes.bakedProbes.Length];
scene_LightProbes = LightmapSettings.lightProbes.bakedProbes;
for (int i = 0; i < scene_LightProbes.Length; i++)
{
var SHCoeff = new SphericalHarmonics();
// j is coefficient
for (int j = 0; j < 3; j++)
{
//k is channel ( r g b )
for (int k = 0; k < 9; k++)
{
SHCoeff.coefficients[j*9+k] = scene_LightProbes[i][j, k];
}
}
newSphericalHarmonicsList.Add(SHCoeff);
}
newLightingScenarioData.lightProbes = newSphericalHarmonicsList.ToArray ();
if (lightingScenariosData.Count < index + 1)
{
lightingScenariosData.Insert(index, newLightingScenarioData);
}
else
{
lightingScenariosData[index] = newLightingScenarioData;
}
lightingScenariosCount = lightingScenariosData.Count;
if (lightingScenesNames == null || lightingScenesNames.Length< lightingScenariosCount)
{
lightingScenesNames = new string[lightingScenariosCount];
}
}
static void GenerateLightmapInfo(GameObject root, List<RendererInfo> newRendererInfos, List<Texture2D> newLightmapsLight, List<Texture2D> newLightmapsDir, List<Texture2D> newLightmapsShadow, LightmapsMode newLightmapsMode)
{
Terrain terrain = FindObjectOfType<Terrain>();
if (terrain != null && terrain.lightmapIndex != -1 && terrain.lightmapIndex != 65534)
{
RendererInfo terrainRendererInfo = new RendererInfo();
terrainRendererInfo.lightmapOffsetScale = terrain.lightmapScaleOffset;
Texture2D lightmaplight = LightmapSettings.lightmaps[terrain.lightmapIndex].lightmapColor;
terrainRendererInfo.lightmapIndex = newLightmapsLight.IndexOf(lightmaplight);
if (terrainRendererInfo.lightmapIndex == -1)
{
terrainRendererInfo.lightmapIndex = newLightmapsLight.Count;
newLightmapsLight.Add(lightmaplight);
}
if (newLightmapsMode != LightmapsMode.NonDirectional)
{
Texture2D lightmapdir = LightmapSettings.lightmaps[terrain.lightmapIndex].lightmapDir;
terrainRendererInfo.lightmapIndex = newLightmapsDir.IndexOf(lightmapdir);
if (terrainRendererInfo.lightmapIndex == -1)
{
terrainRendererInfo.lightmapIndex = newLightmapsDir.Count;
newLightmapsDir.Add(lightmapdir);
}
}
if (LightmapSettings.lightmaps[terrain.lightmapIndex].shadowMask != null)
{
Texture2D lightmapShadow = LightmapSettings.lightmaps[terrain.lightmapIndex].shadowMask;
terrainRendererInfo.lightmapIndex = newLightmapsShadow.IndexOf(lightmapShadow);
if (terrainRendererInfo.lightmapIndex == -1)
{
terrainRendererInfo.lightmapIndex = newLightmapsShadow.Count;
newLightmapsShadow.Add(lightmapShadow);
}
}
newRendererInfos.Add(terrainRendererInfo);
if (Application.isEditor)
Debug.Log("Terrain lightmap stored in" + terrainRendererInfo.lightmapIndex.ToString());
}
var renderers = FindObjectsOfType(typeof(Renderer));
if (Application.isEditor)
Debug.Log("stored info for " + renderers.Length + " meshrenderers");
foreach (Renderer renderer in renderers)
{
if (renderer.lightmapIndex != -1 && renderer.lightmapIndex != 65534)
{
RendererInfo info = new RendererInfo();
info.renderer = renderer;
info.lightmapOffsetScale = renderer.lightmapScaleOffset;
Texture2D lightmaplight = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapColor;
info.lightmapIndex = newLightmapsLight.IndexOf(lightmaplight);
if (info.lightmapIndex == -1)
{
info.lightmapIndex = newLightmapsLight.Count;
newLightmapsLight.Add(lightmaplight);
}
if (newLightmapsMode != LightmapsMode.NonDirectional)
{
Texture2D lightmapdir = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapDir;
info.lightmapIndex = newLightmapsDir.IndexOf(lightmapdir);
if (info.lightmapIndex == -1)
{
info.lightmapIndex = newLightmapsDir.Count;
newLightmapsDir.Add(lightmapdir);
}
}
if (LightmapSettings.lightmaps[renderer.lightmapIndex].shadowMask != null)
{
Texture2D lightmapShadow = LightmapSettings.lightmaps[renderer.lightmapIndex].shadowMask;
info.lightmapIndex = newLightmapsShadow.IndexOf(lightmapShadow);
if (info.lightmapIndex == -1)
{
info.lightmapIndex = newLightmapsShadow.Count;
newLightmapsShadow.Add(lightmapShadow);
}
}
newRendererInfos.Add(info);
}
}
}
}