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

386 行
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;
[Tooltip("Enable this if you want to use different lightmap resolutions in your different lighting scenarios. In that case you'll have to disable Static Batching in the Player Settings. When disabled, Static Batching can be used but all your lighting scenarios need to use the same lightmap resolution.")]
public bool applyLightmapScaleAndOffset = 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);
if(applyLightmapScaleAndOffset)
{
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];
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);
}
}
}
}