From a584b9b833c941ca259a629ae37d519233f8a393 Mon Sep 17 00:00:00 2001 From: FrancescoC-Unity Date: Fri, 27 Aug 2021 18:52:48 +0200 Subject: [PATCH 01/18] Create hidden per scene data --- .../Lighting/ProbeVolume/ProbeGIBaking.cs | 13 +- .../ProbeVolume/ProbeReferenceVolume.cs | 10 +- .../ProbeVolume/ProbeVolumePerSceneData.cs | 111 ++++++++++++++++++ ...s.meta => ProbeVolumePerSceneData.cs.meta} | 2 +- ...SceneBounds.cs => ProbeVolumeSceneData.cs} | 54 ++++++++- .../ProbeVolume/ProbeVolumeSceneData.cs.meta | 11 ++ .../RenderPipeline/HDRenderPipeline.cs | 2 +- .../HDRenderPipelineGlobalSettings.cs | 6 +- 8 files changed, 187 insertions(+), 22 deletions(-) create mode 100644 com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs rename com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/{ProbeVolumeSceneBounds.cs.meta => ProbeVolumePerSceneData.cs.meta} (83%) rename com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/{ProbeVolumeSceneBounds.cs => ProbeVolumeSceneData.cs} (82%) create mode 100644 com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs.meta diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs index 40be8e48745..c7d969aab5e 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs @@ -111,13 +111,14 @@ public static void FindWorldBounds() ProbeReferenceVolume.instance.clearAssetsOnVolumeClear = true; - var sceneBounds = ProbeReferenceVolume.instance.sceneBounds; + var sceneData = ProbeReferenceVolume.instance.sceneData; HashSet scenesToConsider = new HashSet(); for (int i = 0; i < EditorSceneManager.sceneCount; ++i) { var scene = EditorSceneManager.GetSceneAt(i); - sceneBounds.UpdateSceneBounds(scene); + sceneData.UpdateSceneBounds(scene); + sceneData.EnsurePerSceneData(scene); // !!! IMPORTANT TODO !!! // When we will have the concept of baking set this should be reverted, if a scene is not in the bake set it should not be considered // As of now we include all open scenes as the workflow is not nice or clear. When it'll be we should *NOT* do it. @@ -139,12 +140,12 @@ public static void FindWorldBounds() foreach (var scenePath in scenesToConsider) { bool hasProbeVolumes = false; - if (sceneBounds.hasProbeVolumes.TryGetValue(scenePath, out hasProbeVolumes)) + if (sceneData.hasProbeVolumes.TryGetValue(scenePath, out hasProbeVolumes)) { if (hasProbeVolumes) { Bounds localBound; - if (sceneBounds.sceneBounds.TryGetValue(scenePath, out localBound)) + if (sceneData.sceneBounds.TryGetValue(scenePath, out localBound)) { if (hasFoundBounds) { @@ -165,8 +166,8 @@ public static void FindWorldBounds() { var scene = EditorSceneManager.OpenScene(scenePath, OpenSceneMode.Additive); openedScenes.Add(scene); - sceneBounds.UpdateSceneBounds(scene); - Bounds localBound = sceneBounds.sceneBounds[scene.path]; + sceneData.UpdateSceneBounds(scene); + Bounds localBound = sceneData.sceneBounds[scene.path]; if (hasFoundBounds) globalBounds.Encapsulate(localBound); else diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs index 4d9d800e70b..e817bcaae89 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs @@ -228,7 +228,7 @@ public struct ProbeVolumeSystemParameters /// public Shader probeDebugShader; - public ProbeVolumeSceneBounds sceneBounds; + public ProbeVolumeSceneData sceneData; public ProbeVolumeSHBands shBands; } @@ -515,7 +515,7 @@ public override bool Equals(object obj) internal Dictionary cells = new Dictionary(); Dictionary m_ChunkInfo = new Dictionary(); - internal ProbeVolumeSceneBounds sceneBounds; + internal ProbeVolumeSceneData sceneData; /// @@ -620,11 +620,11 @@ public void Initialize(in ProbeVolumeSystemParameters parameters) InitProbeReferenceVolume(kProbeIndexPoolAllocationSize, m_MemoryBudget, m_SHBands); m_IsInitialized = true; m_NeedsIndexRebuild = true; - sceneBounds = parameters.sceneBounds; + sceneData = parameters.sceneData; #if UNITY_EDITOR - if (sceneBounds != null) + if (sceneData != null) { - UnityEditor.SceneManagement.EditorSceneManager.sceneSaved += sceneBounds.UpdateSceneBounds; + UnityEditor.SceneManagement.EditorSceneManager.sceneSaved += sceneData.OnSceneSaved; } #endif } diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs new file mode 100644 index 00000000000..2747cae0866 --- /dev/null +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs @@ -0,0 +1,111 @@ +using UnityEngine.Rendering; +using UnityEngine.SceneManagement; +using System.IO; +using System; +using System.Collections.Generic; + +#if UNITY_EDITOR +using UnityEditor; +#endif + +namespace UnityEngine.Experimental.Rendering +{ + // TMP to be moved to ProbeReferenceVolume when we define the concept, here it is just to make stuff compile + enum ProbeVolumeState + { + Default = 0 + } + + [ExecuteAlways] + [AddComponentMenu("")] // Hide. + internal class ProbeVolumePerSceneData : MonoBehaviour, ISerializationCallbackReceiver + { + + [System.Serializable] + struct SerializableAssetItem + { + [SerializeField] public ProbeVolumeState state; + [SerializeField] public ProbeVolumeAsset asset; + } + + internal Dictionary assets = new Dictionary(); + + [SerializeField] List serializedAssets; + + ProbeVolumeState m_CurrentState = ProbeVolumeState.Default; + ProbeVolumeState m_PreviousState = ProbeVolumeState.Default; + + /// + /// OnAfterDeserialize implementation. + /// + public void OnAfterDeserialize() + { + if (serializedAssets == null) return; + + assets = new Dictionary(); + foreach (var assetItem in serializedAssets) + { + assets.Add(assetItem.state, assetItem.asset); + } + } + + /// + /// OnBeforeSerialize implementation. + /// + public void OnBeforeSerialize() + { + if (assets == null || serializedAssets == null) return; + + serializedAssets.Clear(); + foreach (var k in assets.Keys) + { + SerializableAssetItem item; + item.state = k; + item.asset = assets[k]; + serializedAssets.Add(item); + } + } + + internal void QueueAssetLoading() + { + if (assets.ContainsKey(m_CurrentState) && assets[m_CurrentState] != null) + ProbeReferenceVolume.instance.AddPendingAssetLoading(assets[m_CurrentState]); + } + + internal void QueueAssetRemoval() + { + if (assets.ContainsKey(m_CurrentState) && assets[m_CurrentState] != null) + ProbeReferenceVolume.instance.AddPendingAssetRemoval(assets[m_CurrentState]); + } + + void OnEnable() + { + QueueAssetLoading(); + } + + void OnDisable() + { + QueueAssetRemoval(); + } + + void OnDestroy() + { + QueueAssetRemoval(); + } + + void OnUpdate() + { + // Query state from ProbeReferenceVolume.instance. + // This is temporary here until we implement a state system. + m_CurrentState = ProbeVolumeState.Default; + if (m_PreviousState != m_CurrentState) + { + if (assets.ContainsKey(m_PreviousState) && assets[m_PreviousState] != null) + ProbeReferenceVolume.instance.AddPendingAssetRemoval(assets[m_PreviousState]); + + QueueAssetLoading(); + } + m_PreviousState = m_CurrentState; + } + } +} diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneBounds.cs.meta b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs.meta similarity index 83% rename from com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneBounds.cs.meta rename to com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs.meta index 8d499648c46..1433c28c021 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneBounds.cs.meta +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 2aadc37bd110b7a4895abe8f9fa3d776 +guid: a83d2f7ae04ab6f4f99b0d85377be998 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneBounds.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs similarity index 82% rename from com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneBounds.cs rename to com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs index 65c0d56a8db..9dc7bf194f1 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneBounds.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs @@ -5,13 +5,21 @@ #endif using UnityEngine; using UnityEngine.SceneManagement; +using System.Reflection; namespace UnityEngine.Experimental.Rendering { [System.Serializable] /// A class containing info about the bounds defined by the probe volumes in various scenes. - public class ProbeVolumeSceneBounds : ISerializationCallbackReceiver + public class ProbeVolumeSceneData : ISerializationCallbackReceiver { + static PropertyInfo s_SceneGUID = typeof(Scene).GetProperty("guid", System.Reflection.BindingFlags.NonPublic | BindingFlags.Instance); + string GetSceneGUID(Scene scene) + { + Debug.Assert(s_SceneGUID != null, "Reflection for scene GUID failed"); + return (string)s_SceneGUID.GetValue(scene); + } + [System.Serializable] struct SerializableBoundItem { @@ -34,9 +42,9 @@ struct SerializableHasPVItem public Dictionary sceneBounds; internal Dictionary hasProbeVolumes; - /// Constructor for ProbeVolumeSceneBounds. - /// The asset holding this ProbeVolumeSceneBounds, it will be dirtied every time scene bounds are updated. - public ProbeVolumeSceneBounds(Object parentAsset) + /// Constructor for ProbeVolumeSceneData. + /// The asset holding this ProbeVolumeSceneData, it will be dirtied every time scene bounds or settings are changed. + public ProbeVolumeSceneData(Object parentAsset) { m_ParentAsset = parentAsset; sceneBounds = new Dictionary(); @@ -45,8 +53,8 @@ public ProbeVolumeSceneBounds(Object parentAsset) serializedHasVolumes = new List(); } - /// Set a reference to the object holding this ProbeVolumeSceneBounds. - /// The object holding this ProbeVolumeSceneBounds, it will be dirtied every time scene bounds are updated. + /// Set a reference to the object holding this ProbeVolumeSceneData. + /// The object holding this ProbeVolumeSceneData, it will be dirtied every time scene bounds or settings are changed. public void SetParentObject(Object parent) { m_ParentAsset = parent; @@ -218,6 +226,40 @@ internal void UpdateSceneBounds(Scene scene) } } + // It is important this is called after UpdateSceneBounds is called! + internal void EnsurePerSceneData(Scene scene) + { + if (hasProbeVolumes.ContainsKey(scene.path) && hasProbeVolumes[scene.path]) + { + var perSceneData = UnityEngine.GameObject.FindObjectsOfType(); + var sceneGUID = GetSceneGUID(scene); + + bool foundPerSceneData = false; + foreach (var data in perSceneData) + { + if (GetSceneGUID(data.gameObject.scene) == sceneGUID) + { + foundPerSceneData = true; + } + } + + if (!foundPerSceneData) + { + GameObject go = new GameObject("ProbeVolumePerSceneData"); + go.hideFlags |= HideFlags.HideInHierarchy; + go.AddComponent(); + SceneManager.MoveGameObjectToScene(go, scene); + } + } + + } + + internal void OnSceneSaved(Scene scene) + { + UpdateSceneBounds(scene); + EnsurePerSceneData(scene); + } + #endif } } diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs.meta b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs.meta new file mode 100644 index 00000000000..7fcd88fff02 --- /dev/null +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 04fb4740d8c6dbc469086e13c435cd4b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs index 496a29b671e..b33b4b9e352 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs @@ -380,7 +380,7 @@ public HDRenderPipeline(HDRenderPipelineAsset asset) memoryBudget = m_Asset.currentPlatformRenderPipelineSettings.probeVolumeMemoryBudget, probeDebugMesh = defaultResources.assets.sphereMesh, probeDebugShader = defaultResources.shaders.probeVolumeDebugShader, - sceneBounds = m_GlobalSettings.GetOrCreateAPVSceneBounds(), + sceneData = m_GlobalSettings.GetOrCreateAPVSceneData(), shBands = m_Asset.currentPlatformRenderPipelineSettings.probeVolumeSHBands }); RegisterRetrieveOfProbeVolumeExtraDataAction(); diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipelineGlobalSettings.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipelineGlobalSettings.cs index d49fc6bc48b..2834df985fb 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipelineGlobalSettings.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipelineGlobalSettings.cs @@ -821,12 +821,12 @@ internal bool AddDiffusionProfile(DiffusionProfileSettings profile) #region APV // This is temporarily here until we have a core place to put it shared between pipelines. [SerializeField] - internal ProbeVolumeSceneBounds apvScenesBounds; + internal ProbeVolumeSceneData apvScenesBounds; - internal ProbeVolumeSceneBounds GetOrCreateAPVSceneBounds() + internal ProbeVolumeSceneData GetOrCreateAPVSceneData() { if (apvScenesBounds == null) - apvScenesBounds = new ProbeVolumeSceneBounds((Object)this); + apvScenesBounds = new ProbeVolumeSceneData((Object)this); apvScenesBounds.SetParentObject((Object)this); From 87fed7508c5360ee5822bb2130d0967c20f264d8 Mon Sep 17 00:00:00 2001 From: FrancescoC-Unity Date: Fri, 27 Aug 2021 20:19:33 +0200 Subject: [PATCH 02/18] Start using new mode in baking workflow (Need to fix the tmp send data) --- .../Lighting/ProbeVolume/ProbeGIBaking.cs | 100 ++++++++---------- .../ProbeReferenceVolumeAuthoring.cs | 10 ++ .../ProbeVolumeBakingProcessSettings.cs | 14 +++ .../ProbeVolumeBakingProcessSettings.cs.meta | 11 ++ .../ProbeVolume/ProbeVolumePerSceneData.cs | 22 ++++ .../ProbeVolume/ProbeVolumeSceneData.cs | 90 +++++++++++++++- 6 files changed, 187 insertions(+), 60 deletions(-) create mode 100644 com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeBakingProcessSettings.cs create mode 100644 com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeBakingProcessSettings.cs.meta diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs index c7d969aab5e..5c5c7226a78 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs @@ -84,19 +84,12 @@ static void ClearBakingBatch() static public void Clear() { - var refVolAuthList = GameObject.FindObjectsOfType(); - - foreach (var refVolAuthoring in refVolAuthList) + var perSceneData = GameObject.FindObjectsOfType(); + foreach (var data in perSceneData) { - if (!refVolAuthoring.enabled || !refVolAuthoring.gameObject.activeSelf) - continue; - - refVolAuthoring.volumeAsset = null; - + data.InvalidateAllAssets(); var refVol = ProbeReferenceVolume.instance; refVol.Clear(); - refVol.SetTRS(Vector3.zero, Quaternion.identity, refVolAuthoring.brickSize); - refVol.SetMaxSubdivision(refVolAuthoring.maxSubdivision); } var probeVolumes = GameObject.FindObjectsOfType(); @@ -279,7 +272,6 @@ internal static void RevertDilation() { var refVolAuthList = GameObject.FindObjectsOfType(); m_BakingReferenceVolumeAuthoring = GetCardinalAuthoringComponent(refVolAuthList); - m_BakingReferenceVolumeAuthoring = GetCardinalAuthoringComponent(refVolAuthList); if (m_BakingReferenceVolumeAuthoring == null) return; var dilationSettings = m_BakingReferenceVolumeAuthoring.GetDilationSettings(); @@ -306,9 +298,9 @@ internal static void RevertDilation() // proper UX. internal static void PerformDilation() { - HashSet refVols = new HashSet(); Dictionary> cell2Assets = new Dictionary>(); - var refVolAuthList = GameObject.FindObjectsOfType(); + var refVolAuthList = GameObject.FindObjectsOfType(); // TODO: Soon to be removable + var perSceneDataList = GameObject.FindObjectsOfType(); m_BakingReferenceVolumeAuthoring = GetCardinalAuthoringComponent(refVolAuthList); if (m_BakingReferenceVolumeAuthoring == null) return; @@ -317,27 +309,20 @@ internal static void PerformDilation() { if (m_BakingReferenceVolumeAuthoring == null) m_BakingReferenceVolumeAuthoring = refVol; - - if (refVol.enabled) - { - refVols.Add(refVol); - } } - foreach (var refVol in refVols) + foreach (var sceneData in perSceneDataList) { - if (refVol.volumeAsset != null) + var asset = sceneData.GetCurrentStateAsset(); + string assetPath = asset.GetSerializedFullPath(); + foreach (var cell in asset.cells) { - string assetPath = refVol.volumeAsset.GetSerializedFullPath(); - foreach (var cell in refVol.volumeAsset.cells) + if (!cell2Assets.ContainsKey(cell.index)) { - if (!cell2Assets.ContainsKey(cell.index)) - { - cell2Assets.Add(cell.index, new List()); - } - - cell2Assets[cell.index].Add(assetPath); + cell2Assets.Add(cell.index, new List()); } + + cell2Assets[cell.index].Add(assetPath); } } @@ -366,11 +351,13 @@ internal static void PerformDilation() dilatedCells.Add(cell); } - foreach (var refVol in refVols) + foreach (var sceneData in perSceneDataList) { - if (refVol != null && refVol.volumeAsset != null) + var asset = sceneData.GetCurrentStateAsset(); + string assetPath = asset.GetSerializedFullPath(); + if (asset != null) { - ProbeReferenceVolume.instance.AddPendingAssetRemoval(refVol.volumeAsset); + ProbeReferenceVolume.instance.AddPendingAssetRemoval(asset); } } @@ -381,11 +368,12 @@ internal static void PerformDilation() // Put back cells foreach (var cell in dilatedCells) { - foreach (var refVol in refVols) + foreach (var sceneData in perSceneDataList) { - if (refVol.volumeAsset == null) continue; + var asset = sceneData.GetCurrentStateAsset(); + + if (asset == null) continue; - var asset = refVol.volumeAsset; var assetPath = asset.GetSerializedFullPath(); bool valueFound = false; if (!assetCleared.TryGetValue(assetPath, out valueFound)) @@ -404,10 +392,9 @@ internal static void PerformDilation() UnityEditor.AssetDatabase.SaveAssets(); UnityEditor.AssetDatabase.Refresh(); - foreach (var refVol in refVols) + foreach (var sceneData in perSceneDataList) { - if (refVol.enabled && refVol.gameObject.activeSelf) - refVol.QueueAssetLoading(); + sceneData.QueueAssetLoading(); } } @@ -534,16 +521,15 @@ static void OnAdditionalProbesBakeCompleted() UnityEditor.Experimental.Lightmapping.SetAdditionalBakedProbes(m_BakingBatch.index, null); // Map from each scene to an existing reference volume - var scene2RefVol = new Dictionary(); - foreach (var refVol in GameObject.FindObjectsOfType()) - if (refVol.enabled) - scene2RefVol[refVol.gameObject.scene] = refVol; + var scene2Data = new Dictionary(); + foreach (var data in GameObject.FindObjectsOfType()) + scene2Data[data.gameObject.scene] = data; // Map from each reference volume to its asset - var refVol2Asset = new Dictionary(); - foreach (var refVol in scene2RefVol.Values) + var data2Asset = new Dictionary(); + foreach (var data in scene2Data.Values) { - refVol2Asset[refVol] = ProbeVolumeAsset.CreateAsset(refVol.gameObject.scene); + data2Asset[data] = ProbeVolumeAsset.CreateAsset(data.gameObject.scene); } // Put cells into the respective assets @@ -552,29 +538,32 @@ static void OnAdditionalProbesBakeCompleted() foreach (var scene in m_BakingBatch.cellIndex2SceneReferences[cell.index]) { // This scene has a reference volume authoring component in it? - ProbeReferenceVolumeAuthoring refVol = null; - if (scene2RefVol.TryGetValue(scene, out refVol)) + ProbeVolumePerSceneData data = null; + if (scene2Data.TryGetValue(scene, out data)) { - var asset = refVol2Asset[refVol]; + var asset = data2Asset[data]; asset.cells.Add(cell); - CellCountInDirections(out asset.minCellPosition, out asset.maxCellPosition, refVol.profile.cellSizeInMeters); + var profile = ProbeReferenceVolume.instance.sceneData.GetProfileForScene(scene); + Debug.Assert(profile != null); + CellCountInDirections(out asset.minCellPosition, out asset.maxCellPosition, profile.cellSizeInMeters); asset.globalBounds = globalBounds; } } } // Connect the assets to their components - foreach (var pair in refVol2Asset) + foreach (var pair in data2Asset) { - var refVol = pair.Key; + var data = pair.Key; var asset = pair.Value; - refVol.volumeAsset = asset; + // TODO: This will need to use the proper state, not default, when we have them. + data.StoreAssetForState(ProbeVolumeState.Default, asset); if (UnityEditor.Lightmapping.giWorkflowMode != UnityEditor.Lightmapping.GIWorkflowMode.Iterative) { - UnityEditor.EditorUtility.SetDirty(refVol); - UnityEditor.EditorUtility.SetDirty(refVol.volumeAsset); + UnityEditor.EditorUtility.SetDirty(data); + UnityEditor.EditorUtility.SetDirty(asset); } } @@ -588,10 +577,9 @@ static void OnAdditionalProbesBakeCompleted() UnityEditor.AssetDatabase.Refresh(); probeRefVolume.clearAssetsOnVolumeClear = false; - foreach (var refVol in refVol2Asset.Keys) + foreach (var data in data2Asset.Keys) { - if (refVol.enabled && refVol.gameObject.activeSelf) - refVol.QueueAssetLoading(); + data.QueueAssetLoading(); } // ---- Perform dilation --- diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs index 7b0516011c7..13c438f5066 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs @@ -132,6 +132,14 @@ internal void LoadProfileInformation() refVol.dilationValidtyThreshold = m_DilationValidityThreshold; } + // TEMP! THIS NEEDS TO BE REMOVED WHEN WE HAVE THE SETTINGS PANEL. + void SendSceneData() + { + if (ProbeReferenceVolume.instance.sceneData == null) return; + ProbeReferenceVolume.instance.sceneData.SetBakeSettingsForScene(gameObject.scene, GetDilationSettings(), GetVirtualOffsetSettings()); + ProbeReferenceVolume.instance.sceneData.SetProfileForScene(gameObject.scene, m_Profile); + } + internal void QueueAssetLoading() { LoadProfileInformation(); @@ -163,6 +171,7 @@ void OnEnable() if (m_Profile == null) m_Profile = CreateReferenceVolumeProfile(gameObject.scene, gameObject.name); #endif + SendSceneData(); QueueAssetLoading(); } @@ -189,6 +198,7 @@ void OnValidate() } m_PrevAsset = volumeAsset; + SendSceneData(); } void OnDisable() diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeBakingProcessSettings.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeBakingProcessSettings.cs new file mode 100644 index 00000000000..9b4c34c3d87 --- /dev/null +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeBakingProcessSettings.cs @@ -0,0 +1,14 @@ +using UnityEngine.Rendering; +#if UNITY_EDITOR +using UnityEditor; +#endif + +namespace UnityEngine.Experimental.Rendering +{ + // TODO: Use this structure in the actual authoring component rather than just a mean to group output parameters. + internal struct ProbeVolumeBakingProcessSettings + { + public ProbeDilationSettings dilationSettings; + public VirtualOffsetSettings virtualOffsetSettings; + } +} diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeBakingProcessSettings.cs.meta b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeBakingProcessSettings.cs.meta new file mode 100644 index 00000000000..bc63c960f12 --- /dev/null +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeBakingProcessSettings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2ca179cc72ecf4f4fa7d4ed3bb83ffd2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs index 2747cae0866..47f667d6497 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs @@ -66,6 +66,28 @@ public void OnBeforeSerialize() } } + internal void StoreAssetForState(ProbeVolumeState state, ProbeVolumeAsset asset) + { + assets[state] = asset; + } + + internal void InvalidateAllAssets() + { + foreach (var asset in assets.Values) + { + if (asset != null) + ProbeReferenceVolume.instance.AddPendingAssetRemoval(asset); + } + + assets.Clear(); + } + + internal ProbeVolumeAsset GetCurrentStateAsset() + { + if (assets.ContainsKey(m_CurrentState)) return assets[m_CurrentState]; + else return null; + } + internal void QueueAssetLoading() { if (assets.ContainsKey(m_CurrentState) && assets[m_CurrentState] != null) diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs index 9dc7bf194f1..fcf6215ca70 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs @@ -9,6 +9,8 @@ namespace UnityEngine.Experimental.Rendering { + // Add Profile and baking settings. + [System.Serializable] /// A class containing info about the bounds defined by the probe volumes in various scenes. public class ProbeVolumeSceneData : ISerializationCallbackReceiver @@ -34,13 +36,31 @@ struct SerializableHasPVItem [SerializeField] public bool hasProbeVolumes; } + [System.Serializable] + struct SerializablePVProfile + { + [SerializeField] public string sceneGUID; + [SerializeField] public ProbeReferenceVolumeProfile profile; + } + + [System.Serializable] + struct SerializablePVBakeSettings + { + [SerializeField] public string sceneGUID; + [SerializeField] public ProbeVolumeBakingProcessSettings settings; + } + [SerializeField] List serializedBounds; [SerializeField] List serializedHasVolumes; + [SerializeField] List serializedProfiles; + [SerializeField] List serializedBakeSettings; Object m_ParentAsset = null; /// A dictionary containing the Bounds defined by probe volumes for each scene (scene path is the key of the dictionary). public Dictionary sceneBounds; internal Dictionary hasProbeVolumes; + internal Dictionary sceneProfiles; + internal Dictionary sceneBakingSettings; /// Constructor for ProbeVolumeSceneData. /// The asset holding this ProbeVolumeSceneData, it will be dirtied every time scene bounds or settings are changed. @@ -49,8 +69,13 @@ public ProbeVolumeSceneData(Object parentAsset) m_ParentAsset = parentAsset; sceneBounds = new Dictionary(); hasProbeVolumes = new Dictionary(); + sceneProfiles = new Dictionary(); + sceneBakingSettings = new Dictionary(); + serializedBounds = new List(); serializedHasVolumes = new List(); + serializedProfiles = new List(); + serializedBakeSettings = new List(); } /// Set a reference to the object holding this ProbeVolumeSceneData. @@ -66,10 +91,14 @@ public void SetParentObject(Object parent) public void OnAfterDeserialize() { // We haven't initialized the bounds, no need to do anything here. - if (serializedBounds == null || serializedHasVolumes == null) return; + if (serializedBounds == null || serializedHasVolumes == null || + serializedProfiles == null || serializedBakeSettings == null) return; sceneBounds = new Dictionary(); hasProbeVolumes = new Dictionary(); + sceneProfiles = new Dictionary(); + sceneBakingSettings = new Dictionary(); + foreach (var boundItem in serializedBounds) { sceneBounds.Add(boundItem.scenePath, boundItem.bounds); @@ -79,6 +108,16 @@ public void OnAfterDeserialize() { hasProbeVolumes.Add(boundItem.scenePath, boundItem.hasProbeVolumes); } + + foreach (var profileItem in serializedProfiles) + { + sceneProfiles.Add(profileItem.sceneGUID, profileItem.profile); + } + + foreach (var settingsItem in serializedBakeSettings) + { + sceneBakingSettings.Add(settingsItem.sceneGUID, settingsItem.settings); + } } /// @@ -87,8 +126,8 @@ public void OnAfterDeserialize() public void OnBeforeSerialize() { // We haven't initialized the bounds, no need to do anything here. - if (sceneBounds == null || hasProbeVolumes == null || - serializedBounds == null || serializedHasVolumes == null) return; + if (sceneBounds == null || hasProbeVolumes == null || sceneBakingSettings == null || sceneProfiles == null || + serializedBounds == null || serializedHasVolumes == null || serializedBakeSettings == null || serializedProfiles == null) return; serializedBounds.Clear(); serializedHasVolumes.Clear(); @@ -107,6 +146,22 @@ public void OnBeforeSerialize() item.hasProbeVolumes = hasProbeVolumes[k]; serializedHasVolumes.Add(item); } + + foreach (var k in sceneBakingSettings.Keys) + { + SerializablePVBakeSettings item; + item.sceneGUID = k; + item.settings = sceneBakingSettings[k]; + serializedBakeSettings.Add(item); + } + + foreach (var k in sceneProfiles.Keys) + { + SerializablePVProfile item; + item.sceneGUID = k; + item.profile = sceneProfiles[k]; + serializedProfiles.Add(item); + } } #if UNITY_EDITOR @@ -251,7 +306,6 @@ internal void EnsurePerSceneData(Scene scene) SceneManager.MoveGameObjectToScene(go, scene); } } - } internal void OnSceneSaved(Scene scene) @@ -260,6 +314,34 @@ internal void OnSceneSaved(Scene scene) EnsurePerSceneData(scene); } + + internal void SetProfileForScene(Scene scene, ProbeReferenceVolumeProfile profile) + { + if (sceneProfiles == null) sceneProfiles = new Dictionary(); + + var sceneGUID = GetSceneGUID(scene); + sceneProfiles[sceneGUID] = profile; + } + + internal void SetBakeSettingsForScene(Scene scene, ProbeDilationSettings dilationSettings, VirtualOffsetSettings virtualOffsetSettings) + { + if (sceneBakingSettings == null) sceneBakingSettings = new Dictionary(); + + var sceneGUID = GetSceneGUID(scene); + ProbeVolumeBakingProcessSettings settings = new ProbeVolumeBakingProcessSettings(); + settings.dilationSettings = dilationSettings; + settings.virtualOffsetSettings = virtualOffsetSettings; + sceneBakingSettings[sceneGUID] = settings; + } + + internal ProbeReferenceVolumeProfile GetProfileForScene(Scene scene) + { + var sceneGUID = GetSceneGUID(scene); + if (sceneProfiles.ContainsKey(sceneGUID)) + return sceneProfiles[sceneGUID]; + + return null; + } #endif } } From 922f8271e611bf5e445824d979109879ee39b326 Mon Sep 17 00:00:00 2001 From: FrancescoC-Unity Date: Mon, 30 Aug 2021 10:13:16 +0200 Subject: [PATCH 03/18] Remove loading/removal from authoring --- .../Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs | 5 ----- .../Lighting/ProbeVolume/ProbeVolumePerSceneData.cs | 8 +++++--- .../Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs | 3 +++ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs index 13c438f5066..0162bb3137d 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs @@ -143,9 +143,6 @@ void SendSceneData() internal void QueueAssetLoading() { LoadProfileInformation(); - - if (volumeAsset != null) - ProbeReferenceVolume.instance.AddPendingAssetLoading(volumeAsset); } internal void QueueAssetRemoval() @@ -161,8 +158,6 @@ internal void QueueAssetRemoval() m_PrevAsset = null; #endif - - ProbeReferenceVolume.instance.AddPendingAssetRemoval(volumeAsset); } void OnEnable() diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs index 47f667d6497..35ee9c67084 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs @@ -13,7 +13,8 @@ namespace UnityEngine.Experimental.Rendering // TMP to be moved to ProbeReferenceVolume when we define the concept, here it is just to make stuff compile enum ProbeVolumeState { - Default = 0 + Default = 0, + Invalid = 999 } [ExecuteAlways] @@ -33,7 +34,7 @@ struct SerializableAssetItem [SerializeField] List serializedAssets; ProbeVolumeState m_CurrentState = ProbeVolumeState.Default; - ProbeVolumeState m_PreviousState = ProbeVolumeState.Default; + ProbeVolumeState m_PreviousState = ProbeVolumeState.Invalid; /// /// OnAfterDeserialize implementation. @@ -115,11 +116,12 @@ void OnDestroy() QueueAssetRemoval(); } - void OnUpdate() + void Update() { // Query state from ProbeReferenceVolume.instance. // This is temporary here until we implement a state system. m_CurrentState = ProbeVolumeState.Default; + if (m_PreviousState != m_CurrentState) { if (assets.ContainsKey(m_PreviousState) && assets[m_PreviousState] != null) diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs index fcf6215ca70..da46483d872 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs @@ -131,6 +131,9 @@ public void OnBeforeSerialize() serializedBounds.Clear(); serializedHasVolumes.Clear(); + serializedProfiles.Clear(); + sceneBakingSettings.Clear(); + foreach (var k in sceneBounds.Keys) { SerializableBoundItem item; From 49da9e8fb71e41bba4d7e24baf1b1aeee1f4a7b1 Mon Sep 17 00:00:00 2001 From: FrancescoC-Unity Date: Tue, 31 Aug 2021 11:23:39 +0200 Subject: [PATCH 04/18] Need to switch branch, move profile data to asset --- .../Editor/Lighting/ProbeVolume/ProbeGIBaking.cs | 2 +- .../Runtime/Lighting/ProbeVolume/ProbeVolumeAsset.cs | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs index 5c5c7226a78..acedf4d01c9 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs @@ -544,6 +544,7 @@ static void OnAdditionalProbesBakeCompleted() var asset = data2Asset[data]; asset.cells.Add(cell); var profile = ProbeReferenceVolume.instance.sceneData.GetProfileForScene(scene); + asset.StoreProfileData(profile); Debug.Assert(profile != null); CellCountInDirections(out asset.minCellPosition, out asset.maxCellPosition, profile.cellSizeInMeters); asset.globalBounds = globalBounds; @@ -646,7 +647,6 @@ public static void RunPlacement() // Compute probe positions and send them to the Lightmapper float brickSize = m_BakingReferenceVolumeAuthoring.brickSize; Matrix4x4 newRefToWS = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(brickSize, brickSize, brickSize)); - //m_BakingReferenceVolumeAuthoring; ApplySubdivisionResults(result, newRefToWS); } diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeAsset.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeAsset.cs index 77b75043f5d..3e6d62abe02 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeAsset.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeAsset.cs @@ -33,6 +33,12 @@ internal enum AssetVersion [SerializeField] string m_AssetFullPath = "UNINITIALIZED!"; + // Profile info + [SerializeField] internal int cellSizeInBricks; + [SerializeField] internal float minDistanceBetweenProbes; + [SerializeField] internal int simplificationLevels; + + public string GetSerializedFullPath() { return m_AssetFullPath; @@ -71,6 +77,12 @@ public static ProbeVolumeAsset CreateAsset(Scene scene) return asset; } + internal void StoreProfileData(ProbeReferenceVolumeProfile profile) + { + cellSizeInBricks = profile.cellSizeInBricks; + simplificationLevels = profile.simplificationLevels; + minDistanceBetweenProbes = profile.minDistanceBetweenProbes; + } #endif } From 7e86ae58638502f9ebc267f8aa33060f2f0887cb Mon Sep 17 00:00:00 2001 From: FrancescoC-Unity Date: Tue, 31 Aug 2021 15:01:10 +0200 Subject: [PATCH 05/18] Almost completely get rid of baking reference volume --- .../Lighting/ProbeVolume/ProbeGIBaking.cs | 67 ++++++++++++------- .../Lighting/ProbeVolume/ProbePlacement.cs | 4 +- .../ProbeVolume/ProbeSubdivisionContext.cs | 4 +- .../ProbeReferenceVolumeAuthoring.cs | 23 +++++-- .../ProbeVolume/ProbeVolumeSceneData.cs | 18 ++++- 5 files changed, 84 insertions(+), 32 deletions(-) diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs index acedf4d01c9..75beb48f69d 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs @@ -52,6 +52,9 @@ partial class ProbeGIBaking static bool m_IsInit = false; static BakingBatch m_BakingBatch; static ProbeReferenceVolumeAuthoring m_BakingReferenceVolumeAuthoring = null; + static ProbeReferenceVolumeProfile m_BakingProfile = null; + static ProbeVolumeBakingProcessSettings m_BakingSettings; + static int m_BakingBatchIndex = 0; static Bounds globalBounds = new Bounds(); @@ -178,6 +181,32 @@ public static void FindWorldBounds() } } + static void SetBakingContext(ProbeVolumePerSceneData[] perSceneData) + { + // We need to make sure all scenes we are baking have the same profile. The same should be done for the baking settings, but we check only profile. + // TODO: This should be ensured by the controlling panel, until we have that we need to assert. + + // To check what are the scenes that have probe volume enabled we checks the ProbeVolumePerSceneData. We are guaranteed to have only one per scene. + for (int i=0; i enabledVolumes = new List(); @@ -213,14 +242,18 @@ static void OnBakeStarted() { if (!ProbeReferenceVolume.instance.isInitialized) return; - var refVolAuthList = GameObject.FindObjectsOfType(); + var refVolAuthList = GameObject.FindObjectsOfType(); // TODO: To remove. + if (refVolAuthList.Length == 0) return; FindWorldBounds(); refVolAuthList = GameObject.FindObjectsOfType(); + var perSceneDataList = GameObject.FindObjectsOfType(); + if (perSceneDataList.Length == 0) return; m_BakingReferenceVolumeAuthoring = GetCardinalAuthoringComponent(refVolAuthList); + SetBakingContext(perSceneDataList); if (m_BakingReferenceVolumeAuthoring == null) { @@ -228,8 +261,6 @@ static void OnBakeStarted() return; } - var refVol = ProbeReferenceVolume.instance; - AddOccluders(); RunPlacement(); @@ -270,11 +301,9 @@ static void BrickCountInDirections(out Vector3Int cellsInXYZ, float brickSizeInM // It is only a first iteration of the concept that won't be as impactful on memory as other options. internal static void RevertDilation() { - var refVolAuthList = GameObject.FindObjectsOfType(); - m_BakingReferenceVolumeAuthoring = GetCardinalAuthoringComponent(refVolAuthList); - if (m_BakingReferenceVolumeAuthoring == null) return; + if (m_BakingProfile == null) return; - var dilationSettings = m_BakingReferenceVolumeAuthoring.GetDilationSettings(); + var dilationSettings = m_BakingSettings.dilationSettings; foreach (var cell in ProbeReferenceVolume.instance.cells.Values) { @@ -299,17 +328,9 @@ internal static void RevertDilation() internal static void PerformDilation() { Dictionary> cell2Assets = new Dictionary>(); - var refVolAuthList = GameObject.FindObjectsOfType(); // TODO: Soon to be removable var perSceneDataList = GameObject.FindObjectsOfType(); - m_BakingReferenceVolumeAuthoring = GetCardinalAuthoringComponent(refVolAuthList); - if (m_BakingReferenceVolumeAuthoring == null) return; - - foreach (var refVol in refVolAuthList) - { - if (m_BakingReferenceVolumeAuthoring == null) - m_BakingReferenceVolumeAuthoring = refVol; - } + if (m_BakingProfile == null) return; foreach (var sceneData in perSceneDataList) { @@ -326,7 +347,7 @@ internal static void PerformDilation() } } - var dilationSettings = m_BakingReferenceVolumeAuthoring.GetDilationSettings(); + var dilationSettings = m_BakingSettings.dilationSettings; if (dilationSettings.dilationDistance > 0.0f) @@ -432,7 +453,7 @@ static void OnAdditionalProbesBakeCompleted() onAdditionalProbesBakeCompletedCalled = true; - var dilationSettings = m_BakingReferenceVolumeAuthoring.GetDilationSettings(); + var dilationSettings = m_BakingSettings.dilationSettings; // Fetch results of all cells for (int c = 0; c < numCells; ++c) { @@ -645,7 +666,7 @@ public static void RunPlacement() var result = BakeBricks(ctx); // Compute probe positions and send them to the Lightmapper - float brickSize = m_BakingReferenceVolumeAuthoring.brickSize; + float brickSize = m_BakingProfile.minBrickSize; Matrix4x4 newRefToWS = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(brickSize, brickSize, brickSize)); ApplySubdivisionResults(result, newRefToWS); } @@ -656,7 +677,7 @@ public static ProbeSubdivisionContext PrepareProbeSubdivisionContext(ProbeRefere // Prepare all the information in the scene for baking GI. Vector3 refVolOrigin = Vector3.zero; // TODO: This will need to be center of the world bounds. - ctx.Initialize(refVolume, refVolOrigin); + ctx.Initialize(refVolume, m_BakingProfile, refVolOrigin); return ctx; } @@ -668,7 +689,7 @@ public static ProbeSubdivisionResult BakeBricks(ProbeSubdivisionContext ctx) if (ctx.probeVolumes.Count == 0) return result; - using (var gpuResources = ProbePlacement.AllocateGPUResources(ctx.probeVolumes.Count, ctx.refVolume.profile.maxSubdivision)) + using (var gpuResources = ProbePlacement.AllocateGPUResources(ctx.probeVolumes.Count, ctx.profile.maxSubdivision)) { // subdivide all the cells and generate brick positions foreach (var cell in ctx.cells) @@ -813,7 +834,7 @@ public static void ApplySubdivisionResults(ProbeSubdivisionResult results, Matri // Move positions before sending them var positions = m_BakingBatch.uniquePositions.Keys.ToArray(); - VirtualOffsetSettings voSettings = m_BakingReferenceVolumeAuthoring.GetVirtualOffsetSettings(); + VirtualOffsetSettings voSettings = m_BakingSettings.virtualOffsetSettings; if (voSettings.useVirtualOffset) { for (int i = 0; i < positions.Length; ++i) @@ -821,7 +842,7 @@ public static void ApplySubdivisionResults(ProbeSubdivisionResult results, Matri int subdivLevel = 0; m_BakingBatch.uniqueBrickSubdiv.TryGetValue(positions[i], out subdivLevel); float brickSize = ProbeReferenceVolume.CellSize(subdivLevel); - float searchDistance = (brickSize * m_BakingReferenceVolumeAuthoring.brickSize) / ProbeBrickPool.kBrickCellCount; + float searchDistance = (brickSize * m_BakingProfile.minBrickSize) / ProbeBrickPool.kBrickCellCount; float scaleForSearchDist = voSettings.searchMultiplier; positions[i] = PushPositionOutOfGeometry(positions[i], scaleForSearchDist * searchDistance, voSettings.outOfGeoOffset); diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbePlacement.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbePlacement.cs index 42f3db83972..a2e0dc1f8b6 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbePlacement.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbePlacement.cs @@ -277,7 +277,7 @@ public static List SubdivideCell(ProbeReferenceVolume.Volume cellVolume, // In case there is at least one brick in the sub-cell, we need to spawn the parent brick. if (brickCount != brickSet.Count) { - float minBrickSize = subdivisionCtx.refVolume.profile.minBrickSize; + float minBrickSize = subdivisionCtx.profile.minBrickSize; Vector3 cellID = (cellAABB.center - cellAABB.extents) / minBrickSize; float parentSubdivLevel = 3.0f; for (int i = k_MaxSubdivisionInSubCell; i < ctx.maxSubdivisionLevel; i++) @@ -350,7 +350,7 @@ static void SubdivideSubCell(ProbeReferenceVolume.Volume cellVolume, ProbeSubdiv List<(Terrain terrain, ProbeReferenceVolume.Volume volume)> terrains, HashSet brickSet) { var cellAABB = cellVolume.CalculateAABB(); - float minBrickSize = subdivisionCtx.refVolume.profile.minBrickSize; + float minBrickSize = subdivisionCtx.profile.minBrickSize; cellVolume.CalculateCenterAndSize(out var center, out var _); var cmd = CommandBufferPool.Get($"Subdivide (Sub)Cell {center}"); diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeSubdivisionContext.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeSubdivisionContext.cs index 84f260fe9d1..49fec4fe422 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeSubdivisionContext.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeSubdivisionContext.cs @@ -17,10 +17,12 @@ class ProbeSubdivisionContext public List<(Vector3Int position, ProbeReferenceVolume.Volume volume)> cells = new List<(Vector3Int, ProbeReferenceVolume.Volume)>(); public List<(Terrain, ProbeReferenceVolume.Volume volume)> terrains = new List<(Terrain, ProbeReferenceVolume.Volume)>(); public ProbeReferenceVolumeAuthoring refVolume; + public ProbeReferenceVolumeProfile profile; - public void Initialize(ProbeReferenceVolumeAuthoring refVolume, Vector3 refVolOrigin) + public void Initialize(ProbeReferenceVolumeAuthoring refVolume, ProbeReferenceVolumeProfile profile, Vector3 refVolOrigin) { this.refVolume = refVolume; + this.profile = profile; float cellSize = refVolume.cellSizeInMeters; foreach (var pv in UnityEngine.Object.FindObjectsOfType()) diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs index 0162bb3137d..d51e495a85f 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs @@ -115,6 +115,9 @@ internal static ProbeReferenceVolumeProfile CreateReferenceVolumeProfile(Scene s // The [NonSerialized] attribute allows to force the asset to be null in case a domain reload happens. [NonSerialized] ProbeVolumeAsset m_PrevAsset = null; + + [NonSerialized] + bool m_SentDataToSceneData = false; // TODO: This is temp until we don't have a setting panel. #endif [SerializeField] float m_DilationValidityThreshold = 0.25f; @@ -133,11 +136,15 @@ internal void LoadProfileInformation() } // TEMP! THIS NEEDS TO BE REMOVED WHEN WE HAVE THE SETTINGS PANEL. - void SendSceneData() + void SendSceneData(bool force = false) { if (ProbeReferenceVolume.instance.sceneData == null) return; - ProbeReferenceVolume.instance.sceneData.SetBakeSettingsForScene(gameObject.scene, GetDilationSettings(), GetVirtualOffsetSettings()); - ProbeReferenceVolume.instance.sceneData.SetProfileForScene(gameObject.scene, m_Profile); + if (!m_SentDataToSceneData || force) + { + ProbeReferenceVolume.instance.sceneData.SetBakeSettingsForScene(gameObject.scene, GetDilationSettings(), GetVirtualOffsetSettings()); + ProbeReferenceVolume.instance.sceneData.SetProfileForScene(gameObject.scene, m_Profile); + m_SentDataToSceneData = true; + } } internal void QueueAssetLoading() @@ -166,7 +173,7 @@ void OnEnable() if (m_Profile == null) m_Profile = CreateReferenceVolumeProfile(gameObject.scene, gameObject.name); #endif - SendSceneData(); + SendSceneData(force: true); QueueAssetLoading(); } @@ -193,7 +200,7 @@ void OnValidate() } m_PrevAsset = volumeAsset; - SendSceneData(); + SendSceneData(force: true); } void OnDisable() @@ -335,6 +342,12 @@ IEnumerable GetVisibleCellCenters() } } + // IMPORTANT TODO: This is to be deleted when we have the proper setting panel. + private void Update() + { + SendSceneData(); + } + public ProbeDilationSettings GetDilationSettings() { ProbeDilationSettings settings; diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs index da46483d872..1e7b606a8ea 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs @@ -132,7 +132,7 @@ public void OnBeforeSerialize() serializedBounds.Clear(); serializedHasVolumes.Clear(); serializedProfiles.Clear(); - sceneBakingSettings.Clear(); + serializedBakeSettings.Clear(); foreach (var k in sceneBounds.Keys) { @@ -331,6 +331,7 @@ internal void SetBakeSettingsForScene(Scene scene, ProbeDilationSettings dilatio if (sceneBakingSettings == null) sceneBakingSettings = new Dictionary(); var sceneGUID = GetSceneGUID(scene); + ProbeVolumeBakingProcessSettings settings = new ProbeVolumeBakingProcessSettings(); settings.dilationSettings = dilationSettings; settings.virtualOffsetSettings = virtualOffsetSettings; @@ -345,6 +346,21 @@ internal ProbeReferenceVolumeProfile GetProfileForScene(Scene scene) return null; } + + internal bool BakeSettingsDefinedForScene(Scene scene) + { + var sceneGUID = GetSceneGUID(scene); + return sceneBakingSettings.ContainsKey(sceneGUID); + } + + internal ProbeVolumeBakingProcessSettings GetBakeSettingsForScene(Scene scene) + { + var sceneGUID = GetSceneGUID(scene); + if (sceneBakingSettings.ContainsKey(sceneGUID)) + return sceneBakingSettings[sceneGUID]; + + return new ProbeVolumeBakingProcessSettings(); + } #endif } } From a92bf42828dca7176c0342ce922f5a051ab10424 Mon Sep 17 00:00:00 2001 From: FrancescoC-Unity Date: Tue, 31 Aug 2021 16:06:14 +0200 Subject: [PATCH 06/18] remove baking ref from realtime subdiv (but not working :p) --- .../Lighting/ProbeVolume/ProbeGIBaking.cs | 16 +- .../ProbeReferenceVolumeAuthoringEditor.cs | 112 ------------ .../ProbeVolume/ProbeSubdivisionContext.cs | 124 +++++++++++++- .../ProbeReferenceVolumeAuthoring.cs | 128 -------------- .../ProbeVolume/ProbeVolumePerSceneData.cs | 159 +++++++++++++++++- 5 files changed, 281 insertions(+), 258 deletions(-) diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs index 75beb48f69d..1838367fad7 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs @@ -51,7 +51,7 @@ partial class ProbeGIBaking { static bool m_IsInit = false; static BakingBatch m_BakingBatch; - static ProbeReferenceVolumeAuthoring m_BakingReferenceVolumeAuthoring = null; + static ProbeVolumePerSceneData m_BakingPerSceneData = null; static ProbeReferenceVolumeProfile m_BakingProfile = null; static ProbeVolumeBakingProcessSettings m_BakingSettings; @@ -252,15 +252,9 @@ static void OnBakeStarted() var perSceneDataList = GameObject.FindObjectsOfType(); if (perSceneDataList.Length == 0) return; - m_BakingReferenceVolumeAuthoring = GetCardinalAuthoringComponent(refVolAuthList); + m_BakingPerSceneData = perSceneDataList[0]; SetBakingContext(perSceneDataList); - if (m_BakingReferenceVolumeAuthoring == null) - { - Debug.Log("Scene(s) have multiple inconsistent ProbeReferenceVolumeAuthoring components. Please ensure they use identical profiles and transforms before baking."); - return; - } - AddOccluders(); RunPlacement(); @@ -662,7 +656,7 @@ public static void RunPlacement() ClearBakingBatch(); // Subdivide the scene and place the bricks - var ctx = PrepareProbeSubdivisionContext(m_BakingReferenceVolumeAuthoring); + var ctx = PrepareProbeSubdivisionContext(m_BakingPerSceneData); var result = BakeBricks(ctx); // Compute probe positions and send them to the Lightmapper @@ -671,13 +665,13 @@ public static void RunPlacement() ApplySubdivisionResults(result, newRefToWS); } - public static ProbeSubdivisionContext PrepareProbeSubdivisionContext(ProbeReferenceVolumeAuthoring refVolume) + public static ProbeSubdivisionContext PrepareProbeSubdivisionContext(ProbeVolumePerSceneData perSceneData) { ProbeSubdivisionContext ctx = new ProbeSubdivisionContext(); // Prepare all the information in the scene for baking GI. Vector3 refVolOrigin = Vector3.zero; // TODO: This will need to be center of the world bounds. - ctx.Initialize(refVolume, m_BakingProfile, refVolOrigin); + ctx.Initialize(perSceneData, m_BakingProfile, refVolOrigin); return ctx; } diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs index 132242ae883..608baa82be4 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs @@ -12,118 +12,6 @@ namespace UnityEngine.Experimental.Rendering [CustomEditor(typeof(ProbeReferenceVolumeAuthoring))] internal class ProbeReferenceVolumeAuthoringEditor : Editor { - [InitializeOnLoad] - class RealtimeProbeSubdivisionDebug - { - static double s_LastSubdivisionTime; - static double s_LastRefreshTime; - static IEnumerator s_CurrentSubdivision; - - static RealtimeProbeSubdivisionDebug() - { - EditorApplication.update -= UpdateRealtimeSubdivisionDebug; - EditorApplication.update += UpdateRealtimeSubdivisionDebug; - } - - static void UpdateRealtimeSubdivisionDebug() - { - var debugDisplay = ProbeReferenceVolume.instance.debugDisplay; - if (!debugDisplay.realtimeSubdivision) - return; - - // Avoid killing the GPU when Unity is in background and runInBackground is disabled - if (!Application.runInBackground && !UnityEditorInternal.InternalEditorUtility.isApplicationActive) - return; - - // update is called 200 times per second so we bring down the update rate to 60hz to avoid overloading the GPU - if (Time.realtimeSinceStartupAsDouble - s_LastRefreshTime < 1.0f / 60.0f) - return; - s_LastRefreshTime = Time.realtimeSinceStartupAsDouble; - - if (Time.realtimeSinceStartupAsDouble - s_LastSubdivisionTime > debugDisplay.subdivisionDelayInSeconds) - { - var probeVolumeAuthoring = FindObjectOfType(); - if (probeVolumeAuthoring == null || !probeVolumeAuthoring.isActiveAndEnabled) - return; - - if (s_CurrentSubdivision == null) - { - // Start a new Subdivision - s_CurrentSubdivision = Subdivide(); - } - - // Step the subdivision with the amount of cell per frame in debug menu - int updatePerFrame = debugDisplay.subdivisionCellUpdatePerFrame; - // From simplification level 5 and higher, the cost of calculating one cell is very high, so we adjust that number. - if (probeVolumeAuthoring.profile.simplificationLevels > 4) - updatePerFrame = (int)Mathf.Max(1, updatePerFrame / Mathf.Pow(9, probeVolumeAuthoring.profile.simplificationLevels - 4)); - for (int i = 0; i < debugDisplay.subdivisionCellUpdatePerFrame; i++) - { - if (!s_CurrentSubdivision.MoveNext()) - { - s_LastSubdivisionTime = Time.realtimeSinceStartupAsDouble; - s_CurrentSubdivision = null; - break; - } - } - - IEnumerator Subdivide() - { - var ctx = ProbeGIBaking.PrepareProbeSubdivisionContext(probeVolumeAuthoring); - - // Cull all the cells that are not visible (we don't need them for realtime debug) - ctx.cells.RemoveAll(c => - { - return probeVolumeAuthoring.ShouldCullCell(c.position); - }); - - Camera activeCamera = Camera.current ?? SceneView.lastActiveSceneView.camera; - - // Sort cells by camera distance to compute the closest cells first - if (activeCamera != null) - { - var cameraPos = activeCamera.transform.position; - ctx.cells.Sort((c1, c2) => - { - c1.volume.CalculateCenterAndSize(out var c1Center, out var _); - float c1Distance = Vector3.Distance(cameraPos, c1Center); - - c2.volume.CalculateCenterAndSize(out var c2Center, out var _); - float c2Distance = Vector3.Distance(cameraPos, c2Center); - - return c1Distance.CompareTo(c2Distance); - }); - } - - // Progressively update cells: - var cells = ctx.cells.ToList(); - - // Remove all the cells that was not updated to prevent ghosting - foreach (var cellVolume in ctx.refVolume.realtimeSubdivisionInfo.Keys.ToList()) - { - if (!cells.Any(c => c.volume.Equals(cellVolume))) - ctx.refVolume.realtimeSubdivisionInfo.Remove(cellVolume); - } - - // Subdivide visible cells - foreach (var cell in cells) - { - // Override the cell list to only compute one cell - ctx.cells.Clear(); - ctx.cells.Add(cell); - - var result = ProbeGIBaking.BakeBricks(ctx); - ctx.refVolume.realtimeSubdivisionInfo[cell.volume] = result.bricksPerCells[cell.position]; - - yield return null; - } - - yield break; - } - } - } - } - private SerializedProperty m_Dilate; private SerializedProperty m_MaxDilationSampleDistance; private SerializedProperty m_DilationValidityThreshold; diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeSubdivisionContext.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeSubdivisionContext.cs index 49fec4fe422..89cd93c544f 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeSubdivisionContext.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeSubdivisionContext.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Collections; using Unity.Collections; using System; using System.Linq; @@ -10,20 +11,135 @@ namespace UnityEngine.Experimental.Rendering { + [InitializeOnLoad] + class RealtimeProbeSubdivisionDebug + { + static double s_LastSubdivisionTime; + static double s_LastRefreshTime; + static IEnumerator s_CurrentSubdivision; + + static RealtimeProbeSubdivisionDebug() + { + EditorApplication.update -= UpdateRealtimeSubdivisionDebug; + EditorApplication.update += UpdateRealtimeSubdivisionDebug; + } + + static void UpdateRealtimeSubdivisionDebug() + { + var debugDisplay = ProbeReferenceVolume.instance.debugDisplay; + if (!debugDisplay.realtimeSubdivision) + return; + + // Avoid killing the GPU when Unity is in background and runInBackground is disabled + if (!Application.runInBackground && !UnityEditorInternal.InternalEditorUtility.isApplicationActive) + return; + + // update is called 200 times per second so we bring down the update rate to 60hz to avoid overloading the GPU + if (Time.realtimeSinceStartupAsDouble - s_LastRefreshTime < 1.0f / 60.0f) + return; + s_LastRefreshTime = Time.realtimeSinceStartupAsDouble; + + if (Time.realtimeSinceStartupAsDouble - s_LastSubdivisionTime > debugDisplay.subdivisionDelayInSeconds) + { + var probeVolumePerSceneData = GameObject.FindObjectOfType(); + if (probeVolumePerSceneData == null || ProbeReferenceVolume.instance.sceneData == null) return; + + var profile = ProbeReferenceVolume.instance.sceneData.GetProfileForScene(probeVolumePerSceneData.gameObject.scene); + + if (profile == null) return; + + if (s_CurrentSubdivision == null) + { + // Start a new Subdivision + s_CurrentSubdivision = Subdivide(); + } + + // Step the subdivision with the amount of cell per frame in debug menu + int updatePerFrame = debugDisplay.subdivisionCellUpdatePerFrame; + // From simplification level 5 and higher, the cost of calculating one cell is very high, so we adjust that number. + if (profile.simplificationLevels > 4) + updatePerFrame = (int)Mathf.Max(1, updatePerFrame / Mathf.Pow(9, profile.simplificationLevels - 4)); + for (int i = 0; i < debugDisplay.subdivisionCellUpdatePerFrame; i++) + { + if (!s_CurrentSubdivision.MoveNext()) + { + s_LastSubdivisionTime = Time.realtimeSinceStartupAsDouble; + s_CurrentSubdivision = null; + break; + } + } + + IEnumerator Subdivide() + { + var ctx = ProbeGIBaking.PrepareProbeSubdivisionContext(probeVolumePerSceneData); + + // Cull all the cells that are not visible (we don't need them for realtime debug) + ctx.cells.RemoveAll(c => + { + return probeVolumePerSceneData.ShouldCullCell(c.position); + }); + + Camera activeCamera = Camera.current ?? SceneView.lastActiveSceneView.camera; + + // Sort cells by camera distance to compute the closest cells first + if (activeCamera != null) + { + var cameraPos = activeCamera.transform.position; + ctx.cells.Sort((c1, c2) => + { + c1.volume.CalculateCenterAndSize(out var c1Center, out var _); + float c1Distance = Vector3.Distance(cameraPos, c1Center); + + c2.volume.CalculateCenterAndSize(out var c2Center, out var _); + float c2Distance = Vector3.Distance(cameraPos, c2Center); + + return c1Distance.CompareTo(c2Distance); + }); + } + + // Progressively update cells: + var cells = ctx.cells.ToList(); + + // Remove all the cells that was not updated to prevent ghosting + foreach (var cellVolume in ctx.perSceneData.realtimeSubdivisionInfo.Keys.ToList()) + { + if (!cells.Any(c => c.volume.Equals(cellVolume))) + ctx.perSceneData.realtimeSubdivisionInfo.Remove(cellVolume); + } + + // Subdivide visible cells + foreach (var cell in cells) + { + // Override the cell list to only compute one cell + ctx.cells.Clear(); + ctx.cells.Add(cell); + + var result = ProbeGIBaking.BakeBricks(ctx); + ctx.perSceneData.realtimeSubdivisionInfo[cell.volume] = result.bricksPerCells[cell.position]; + + yield return null; + } + + yield break; + } + } + } + } + class ProbeSubdivisionContext { public List<(ProbeVolume component, ProbeReferenceVolume.Volume volume)> probeVolumes = new List<(ProbeVolume, ProbeReferenceVolume.Volume)>(); public List<(Renderer component, ProbeReferenceVolume.Volume volume)> renderers = new List<(Renderer, ProbeReferenceVolume.Volume)>(); public List<(Vector3Int position, ProbeReferenceVolume.Volume volume)> cells = new List<(Vector3Int, ProbeReferenceVolume.Volume)>(); public List<(Terrain, ProbeReferenceVolume.Volume volume)> terrains = new List<(Terrain, ProbeReferenceVolume.Volume)>(); - public ProbeReferenceVolumeAuthoring refVolume; + public ProbeVolumePerSceneData perSceneData; public ProbeReferenceVolumeProfile profile; - public void Initialize(ProbeReferenceVolumeAuthoring refVolume, ProbeReferenceVolumeProfile profile, Vector3 refVolOrigin) + public void Initialize(ProbeVolumePerSceneData perSceneData, ProbeReferenceVolumeProfile profile, Vector3 refVolOrigin) { - this.refVolume = refVolume; + this.perSceneData = perSceneData; this.profile = profile; - float cellSize = refVolume.cellSizeInMeters; + float cellSize = profile.cellSizeInMeters; foreach (var pv in UnityEngine.Object.FindObjectsOfType()) { diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs index d51e495a85f..3443c61354a 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs @@ -213,134 +213,6 @@ void OnDestroy() QueueAssetRemoval(); } - internal bool ShouldCullCell(Vector3 cellPosition, Vector3 originWS = default(Vector3)) - { - if (m_Profile == null) - return true; - - var cameraTransform = SceneView.lastActiveSceneView.camera.transform; - - Vector3 cellCenterWS = cellPosition * m_Profile.cellSizeInMeters + originWS + Vector3.one * (m_Profile.cellSizeInMeters / 2.0f); - - // Round down to cell size distance - float roundedDownDist = Mathf.Floor(Vector3.Distance(cameraTransform.position, cellCenterWS) / m_Profile.cellSizeInMeters) * m_Profile.cellSizeInMeters; - - if (roundedDownDist > ProbeReferenceVolume.instance.debugDisplay.subdivisionViewCullingDistance) - return true; - - var frustumPlanes = GeometryUtility.CalculateFrustumPlanes(SceneView.lastActiveSceneView.camera); - var volumeAABB = new Bounds(cellCenterWS, m_Profile.cellSizeInMeters * Vector3.one); - - return !GeometryUtility.TestPlanesAABB(frustumPlanes, volumeAABB); - } - - // TODO: We need to get rid of Handles.DrawWireCube to be able to have those at runtime as well. - void OnDrawGizmos() - { - if (!enabled || !gameObject.activeSelf || !ProbeReferenceVolume.instance.isInitialized) - return; - - var debugDisplay = ProbeReferenceVolume.instance.debugDisplay; - - if (debugDisplay.drawBricks) - { - var subdivColors = ProbeReferenceVolume.instance.subdivisionDebugColors; - - IEnumerable GetVisibleBricks() - { - if (debugDisplay.realtimeSubdivision) - { - // realtime subdiv cells are already culled - foreach (var kp in realtimeSubdivisionInfo) - { - var cellVolume = kp.Key; - - foreach (var brick in kp.Value) - { - yield return brick; - } - } - } - else - { - foreach (var cell in ProbeReferenceVolume.instance.cells.Values) - { - if (ShouldCullCell(cell.position, ProbeReferenceVolume.instance.GetTransform().posWS)) - continue; - - if (cell.bricks == null) - continue; - - foreach (var brick in cell.bricks) - yield return brick; - } - } - } - - if (brickGizmos == null) - brickGizmos = new MeshGizmo((int)(Mathf.Pow(3, ProbeBrickIndex.kMaxSubdivisionLevels) * MeshGizmo.vertexCountPerCube)); - - brickGizmos.Clear(); - foreach (var brick in GetVisibleBricks()) - { - if (brick.subdivisionLevel < 0) - continue; - - Vector3 scaledSize = Vector3.one * Mathf.Pow(3, brick.subdivisionLevel); - Vector3 scaledPos = brick.position + scaledSize / 2; - brickGizmos.AddWireCube(scaledPos, scaledSize, subdivColors[brick.subdivisionLevel]); - } - - brickGizmos.RenderWireframe(ProbeReferenceVolume.instance.GetRefSpaceToWS(), gizmoName: "Brick Gizmo Rendering"); - } - - if (debugDisplay.drawCells) - { - IEnumerable GetVisibleCellCenters() - { - if (debugDisplay.realtimeSubdivision) - { - foreach (var kp in realtimeSubdivisionInfo) - { - kp.Key.CalculateCenterAndSize(out var center, out var _); - yield return center; - } - } - else - { - foreach (var cell in ProbeReferenceVolume.instance.cells.Values) - { - if (ShouldCullCell(cell.position, ProbeReferenceVolume.instance.GetTransform().posWS)) - continue; - - var positionF = new Vector3(cell.position.x, cell.position.y, cell.position.z); - var center = positionF * m_Profile.cellSizeInMeters + m_Profile.cellSizeInMeters * 0.5f * Vector3.one; - yield return center; - } - } - } - - Matrix4x4 trs = Matrix4x4.TRS(ProbeReferenceVolume.instance.GetTransform().posWS, ProbeReferenceVolume.instance.GetTransform().rot, Vector3.one); - - // For realtime subdivision, the matrix from ProbeReferenceVolume.instance can be wrong if the profile changed since the last bake - if (debugDisplay.realtimeSubdivision) - trs = Matrix4x4.TRS(transform.position, Quaternion.identity, Vector3.one); - - // Fetching this from components instead of from the reference volume allows the user to - // preview how cells will look before they commit to a bake. - Gizmos.color = new Color(0, 1, 0.5f, 0.2f); - Gizmos.matrix = trs; - if (cellGizmo == null) - cellGizmo = new MeshGizmo(); - cellGizmo.Clear(); - foreach (var center in GetVisibleCellCenters()) - { - Gizmos.DrawCube(center, Vector3.one * m_Profile.cellSizeInMeters); - cellGizmo.AddWireCube(center, Vector3.one * m_Profile.cellSizeInMeters, new Color(0, 1, 0.5f, 1)); - } - cellGizmo.RenderWireframe(Gizmos.matrix, gizmoName: "Brick Gizmo Rendering"); - } - } // IMPORTANT TODO: This is to be deleted when we have the proper setting panel. private void Update() diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs index 35ee9c67084..67efb3dd476 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs @@ -2,6 +2,7 @@ using UnityEngine.SceneManagement; using System.IO; using System; +using System.Collections; using System.Collections.Generic; #if UNITY_EDITOR @@ -21,7 +22,6 @@ enum ProbeVolumeState [AddComponentMenu("")] // Hide. internal class ProbeVolumePerSceneData : MonoBehaviour, ISerializationCallbackReceiver { - [System.Serializable] struct SerializableAssetItem { @@ -33,8 +33,23 @@ struct SerializableAssetItem [SerializeField] List serializedAssets; - ProbeVolumeState m_CurrentState = ProbeVolumeState.Default; - ProbeVolumeState m_PreviousState = ProbeVolumeState.Invalid; + [NonSerialized] ProbeVolumeState m_CurrentState = ProbeVolumeState.Default; + [NonSerialized] ProbeVolumeState m_PreviousState = ProbeVolumeState.Invalid; + + // Field used for the realtime subdivision preview + [NonSerialized] + internal Dictionary> realtimeSubdivisionInfo = new Dictionary>(); + + MeshGizmo brickGizmos; + MeshGizmo cellGizmo; + + void DisposeGizmos() + { + brickGizmos?.Dispose(); + brickGizmos = null; + cellGizmo?.Dispose(); + cellGizmo = null; + } /// /// OnAfterDeserialize implementation. @@ -109,11 +124,13 @@ void OnEnable() void OnDisable() { QueueAssetRemoval(); + DisposeGizmos(); } void OnDestroy() { QueueAssetRemoval(); + DisposeGizmos(); } void Update() @@ -131,5 +148,141 @@ void Update() } m_PreviousState = m_CurrentState; } + +#if UNITY_EDITOR + internal bool ShouldCullCell(Vector3 cellPosition, Vector3 originWS = default(Vector3)) + { + var profile = ProbeReferenceVolume.instance.sceneData.GetProfileForScene(gameObject.scene); + + if (profile == null) + return true; + + var cameraTransform = SceneView.lastActiveSceneView.camera.transform; + + Vector3 cellCenterWS = cellPosition * profile.cellSizeInMeters + originWS + Vector3.one * (profile.cellSizeInMeters / 2.0f); + + // Round down to cell size distance + float roundedDownDist = Mathf.Floor(Vector3.Distance(cameraTransform.position, cellCenterWS) / profile.cellSizeInMeters) * profile.cellSizeInMeters; + + if (roundedDownDist > ProbeReferenceVolume.instance.debugDisplay.subdivisionViewCullingDistance) + return true; + + var frustumPlanes = GeometryUtility.CalculateFrustumPlanes(SceneView.lastActiveSceneView.camera); + var volumeAABB = new Bounds(cellCenterWS, profile.cellSizeInMeters * Vector3.one); + + return !GeometryUtility.TestPlanesAABB(frustumPlanes, volumeAABB); + } + + // TODO: We need to get rid of Handles.DrawWireCube to be able to have those at runtime as well. + void OnDrawGizmos() + { + if (!enabled || !gameObject.activeSelf || !ProbeReferenceVolume.instance.isInitialized || ProbeReferenceVolume.instance.sceneData == null) + return; + + var profile = ProbeReferenceVolume.instance.sceneData.GetProfileForScene(gameObject.scene); + if (profile == null) return; + + var debugDisplay = ProbeReferenceVolume.instance.debugDisplay; + + if (debugDisplay.drawBricks) + { + var subdivColors = ProbeReferenceVolume.instance.subdivisionDebugColors; + + IEnumerable GetVisibleBricks() + { + if (debugDisplay.realtimeSubdivision) + { + // realtime subdiv cells are already culled + foreach (var kp in realtimeSubdivisionInfo) + { + var cellVolume = kp.Key; + + foreach (var brick in kp.Value) + { + yield return brick; + } + } + } + else + { + foreach (var cell in ProbeReferenceVolume.instance.cells.Values) + { + if (ShouldCullCell(cell.position, ProbeReferenceVolume.instance.GetTransform().posWS)) + continue; + + if (cell.bricks == null) + continue; + + foreach (var brick in cell.bricks) + yield return brick; + } + } + } + + if (brickGizmos == null) + brickGizmos = new MeshGizmo((int)(Mathf.Pow(3, ProbeBrickIndex.kMaxSubdivisionLevels) * MeshGizmo.vertexCountPerCube)); + + brickGizmos.Clear(); + foreach (var brick in GetVisibleBricks()) + { + if (brick.subdivisionLevel < 0) + continue; + + Vector3 scaledSize = Vector3.one * Mathf.Pow(3, brick.subdivisionLevel); + Vector3 scaledPos = brick.position + scaledSize / 2; + brickGizmos.AddWireCube(scaledPos, scaledSize, subdivColors[brick.subdivisionLevel]); + } + + brickGizmos.RenderWireframe(ProbeReferenceVolume.instance.GetRefSpaceToWS(), gizmoName: "Brick Gizmo Rendering"); + } + + if (debugDisplay.drawCells) + { + IEnumerable GetVisibleCellCenters() + { + if (debugDisplay.realtimeSubdivision) + { + foreach (var kp in realtimeSubdivisionInfo) + { + kp.Key.CalculateCenterAndSize(out var center, out var _); + yield return center; + } + } + else + { + foreach (var cell in ProbeReferenceVolume.instance.cells.Values) + { + if (ShouldCullCell(cell.position, ProbeReferenceVolume.instance.GetTransform().posWS)) + continue; + + var positionF = new Vector3(cell.position.x, cell.position.y, cell.position.z); + var center = positionF * profile.cellSizeInMeters + profile.cellSizeInMeters * 0.5f * Vector3.one; + yield return center; + } + } + } + + Matrix4x4 trs = Matrix4x4.TRS(ProbeReferenceVolume.instance.GetTransform().posWS, ProbeReferenceVolume.instance.GetTransform().rot, Vector3.one); + + // For realtime subdivision, the matrix from ProbeReferenceVolume.instance can be wrong if the profile changed since the last bake + if (debugDisplay.realtimeSubdivision) + trs = Matrix4x4.TRS(transform.position, Quaternion.identity, Vector3.one); + + // Fetching this from components instead of from the reference volume allows the user to + // preview how cells will look before they commit to a bake. + Gizmos.color = new Color(0, 1, 0.5f, 0.2f); + Gizmos.matrix = trs; + if (cellGizmo == null) + cellGizmo = new MeshGizmo(); + cellGizmo.Clear(); + foreach (var center in GetVisibleCellCenters()) + { + Gizmos.DrawCube(center, Vector3.one * profile.cellSizeInMeters); + cellGizmo.AddWireCube(center, Vector3.one * profile.cellSizeInMeters, new Color(0, 1, 0.5f, 1)); + } + cellGizmo.RenderWireframe(Gizmos.matrix, gizmoName: "Brick Gizmo Rendering"); + } + } +#endif } } From fb26eaf6ecdf70ea51d1d22febb49f4efca299cc Mon Sep 17 00:00:00 2001 From: FrancescoC-Unity Date: Tue, 31 Aug 2021 17:15:39 +0200 Subject: [PATCH 07/18] Revert "remove baking ref from realtime subdiv (but not working :p)" This reverts commit a92bf42828dca7176c0342ce922f5a051ab10424. --- .../Lighting/ProbeVolume/ProbeGIBaking.cs | 16 +- .../ProbeReferenceVolumeAuthoringEditor.cs | 112 ++++++++++++ .../ProbeVolume/ProbeSubdivisionContext.cs | 124 +------------- .../ProbeReferenceVolumeAuthoring.cs | 128 ++++++++++++++ .../ProbeVolume/ProbeVolumePerSceneData.cs | 159 +----------------- 5 files changed, 258 insertions(+), 281 deletions(-) diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs index 1838367fad7..75beb48f69d 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs @@ -51,7 +51,7 @@ partial class ProbeGIBaking { static bool m_IsInit = false; static BakingBatch m_BakingBatch; - static ProbeVolumePerSceneData m_BakingPerSceneData = null; + static ProbeReferenceVolumeAuthoring m_BakingReferenceVolumeAuthoring = null; static ProbeReferenceVolumeProfile m_BakingProfile = null; static ProbeVolumeBakingProcessSettings m_BakingSettings; @@ -252,9 +252,15 @@ static void OnBakeStarted() var perSceneDataList = GameObject.FindObjectsOfType(); if (perSceneDataList.Length == 0) return; - m_BakingPerSceneData = perSceneDataList[0]; + m_BakingReferenceVolumeAuthoring = GetCardinalAuthoringComponent(refVolAuthList); SetBakingContext(perSceneDataList); + if (m_BakingReferenceVolumeAuthoring == null) + { + Debug.Log("Scene(s) have multiple inconsistent ProbeReferenceVolumeAuthoring components. Please ensure they use identical profiles and transforms before baking."); + return; + } + AddOccluders(); RunPlacement(); @@ -656,7 +662,7 @@ public static void RunPlacement() ClearBakingBatch(); // Subdivide the scene and place the bricks - var ctx = PrepareProbeSubdivisionContext(m_BakingPerSceneData); + var ctx = PrepareProbeSubdivisionContext(m_BakingReferenceVolumeAuthoring); var result = BakeBricks(ctx); // Compute probe positions and send them to the Lightmapper @@ -665,13 +671,13 @@ public static void RunPlacement() ApplySubdivisionResults(result, newRefToWS); } - public static ProbeSubdivisionContext PrepareProbeSubdivisionContext(ProbeVolumePerSceneData perSceneData) + public static ProbeSubdivisionContext PrepareProbeSubdivisionContext(ProbeReferenceVolumeAuthoring refVolume) { ProbeSubdivisionContext ctx = new ProbeSubdivisionContext(); // Prepare all the information in the scene for baking GI. Vector3 refVolOrigin = Vector3.zero; // TODO: This will need to be center of the world bounds. - ctx.Initialize(perSceneData, m_BakingProfile, refVolOrigin); + ctx.Initialize(refVolume, m_BakingProfile, refVolOrigin); return ctx; } diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs index 608baa82be4..132242ae883 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs @@ -12,6 +12,118 @@ namespace UnityEngine.Experimental.Rendering [CustomEditor(typeof(ProbeReferenceVolumeAuthoring))] internal class ProbeReferenceVolumeAuthoringEditor : Editor { + [InitializeOnLoad] + class RealtimeProbeSubdivisionDebug + { + static double s_LastSubdivisionTime; + static double s_LastRefreshTime; + static IEnumerator s_CurrentSubdivision; + + static RealtimeProbeSubdivisionDebug() + { + EditorApplication.update -= UpdateRealtimeSubdivisionDebug; + EditorApplication.update += UpdateRealtimeSubdivisionDebug; + } + + static void UpdateRealtimeSubdivisionDebug() + { + var debugDisplay = ProbeReferenceVolume.instance.debugDisplay; + if (!debugDisplay.realtimeSubdivision) + return; + + // Avoid killing the GPU when Unity is in background and runInBackground is disabled + if (!Application.runInBackground && !UnityEditorInternal.InternalEditorUtility.isApplicationActive) + return; + + // update is called 200 times per second so we bring down the update rate to 60hz to avoid overloading the GPU + if (Time.realtimeSinceStartupAsDouble - s_LastRefreshTime < 1.0f / 60.0f) + return; + s_LastRefreshTime = Time.realtimeSinceStartupAsDouble; + + if (Time.realtimeSinceStartupAsDouble - s_LastSubdivisionTime > debugDisplay.subdivisionDelayInSeconds) + { + var probeVolumeAuthoring = FindObjectOfType(); + if (probeVolumeAuthoring == null || !probeVolumeAuthoring.isActiveAndEnabled) + return; + + if (s_CurrentSubdivision == null) + { + // Start a new Subdivision + s_CurrentSubdivision = Subdivide(); + } + + // Step the subdivision with the amount of cell per frame in debug menu + int updatePerFrame = debugDisplay.subdivisionCellUpdatePerFrame; + // From simplification level 5 and higher, the cost of calculating one cell is very high, so we adjust that number. + if (probeVolumeAuthoring.profile.simplificationLevels > 4) + updatePerFrame = (int)Mathf.Max(1, updatePerFrame / Mathf.Pow(9, probeVolumeAuthoring.profile.simplificationLevels - 4)); + for (int i = 0; i < debugDisplay.subdivisionCellUpdatePerFrame; i++) + { + if (!s_CurrentSubdivision.MoveNext()) + { + s_LastSubdivisionTime = Time.realtimeSinceStartupAsDouble; + s_CurrentSubdivision = null; + break; + } + } + + IEnumerator Subdivide() + { + var ctx = ProbeGIBaking.PrepareProbeSubdivisionContext(probeVolumeAuthoring); + + // Cull all the cells that are not visible (we don't need them for realtime debug) + ctx.cells.RemoveAll(c => + { + return probeVolumeAuthoring.ShouldCullCell(c.position); + }); + + Camera activeCamera = Camera.current ?? SceneView.lastActiveSceneView.camera; + + // Sort cells by camera distance to compute the closest cells first + if (activeCamera != null) + { + var cameraPos = activeCamera.transform.position; + ctx.cells.Sort((c1, c2) => + { + c1.volume.CalculateCenterAndSize(out var c1Center, out var _); + float c1Distance = Vector3.Distance(cameraPos, c1Center); + + c2.volume.CalculateCenterAndSize(out var c2Center, out var _); + float c2Distance = Vector3.Distance(cameraPos, c2Center); + + return c1Distance.CompareTo(c2Distance); + }); + } + + // Progressively update cells: + var cells = ctx.cells.ToList(); + + // Remove all the cells that was not updated to prevent ghosting + foreach (var cellVolume in ctx.refVolume.realtimeSubdivisionInfo.Keys.ToList()) + { + if (!cells.Any(c => c.volume.Equals(cellVolume))) + ctx.refVolume.realtimeSubdivisionInfo.Remove(cellVolume); + } + + // Subdivide visible cells + foreach (var cell in cells) + { + // Override the cell list to only compute one cell + ctx.cells.Clear(); + ctx.cells.Add(cell); + + var result = ProbeGIBaking.BakeBricks(ctx); + ctx.refVolume.realtimeSubdivisionInfo[cell.volume] = result.bricksPerCells[cell.position]; + + yield return null; + } + + yield break; + } + } + } + } + private SerializedProperty m_Dilate; private SerializedProperty m_MaxDilationSampleDistance; private SerializedProperty m_DilationValidityThreshold; diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeSubdivisionContext.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeSubdivisionContext.cs index 89cd93c544f..49fec4fe422 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeSubdivisionContext.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeSubdivisionContext.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Collections; using Unity.Collections; using System; using System.Linq; @@ -11,135 +10,20 @@ namespace UnityEngine.Experimental.Rendering { - [InitializeOnLoad] - class RealtimeProbeSubdivisionDebug - { - static double s_LastSubdivisionTime; - static double s_LastRefreshTime; - static IEnumerator s_CurrentSubdivision; - - static RealtimeProbeSubdivisionDebug() - { - EditorApplication.update -= UpdateRealtimeSubdivisionDebug; - EditorApplication.update += UpdateRealtimeSubdivisionDebug; - } - - static void UpdateRealtimeSubdivisionDebug() - { - var debugDisplay = ProbeReferenceVolume.instance.debugDisplay; - if (!debugDisplay.realtimeSubdivision) - return; - - // Avoid killing the GPU when Unity is in background and runInBackground is disabled - if (!Application.runInBackground && !UnityEditorInternal.InternalEditorUtility.isApplicationActive) - return; - - // update is called 200 times per second so we bring down the update rate to 60hz to avoid overloading the GPU - if (Time.realtimeSinceStartupAsDouble - s_LastRefreshTime < 1.0f / 60.0f) - return; - s_LastRefreshTime = Time.realtimeSinceStartupAsDouble; - - if (Time.realtimeSinceStartupAsDouble - s_LastSubdivisionTime > debugDisplay.subdivisionDelayInSeconds) - { - var probeVolumePerSceneData = GameObject.FindObjectOfType(); - if (probeVolumePerSceneData == null || ProbeReferenceVolume.instance.sceneData == null) return; - - var profile = ProbeReferenceVolume.instance.sceneData.GetProfileForScene(probeVolumePerSceneData.gameObject.scene); - - if (profile == null) return; - - if (s_CurrentSubdivision == null) - { - // Start a new Subdivision - s_CurrentSubdivision = Subdivide(); - } - - // Step the subdivision with the amount of cell per frame in debug menu - int updatePerFrame = debugDisplay.subdivisionCellUpdatePerFrame; - // From simplification level 5 and higher, the cost of calculating one cell is very high, so we adjust that number. - if (profile.simplificationLevels > 4) - updatePerFrame = (int)Mathf.Max(1, updatePerFrame / Mathf.Pow(9, profile.simplificationLevels - 4)); - for (int i = 0; i < debugDisplay.subdivisionCellUpdatePerFrame; i++) - { - if (!s_CurrentSubdivision.MoveNext()) - { - s_LastSubdivisionTime = Time.realtimeSinceStartupAsDouble; - s_CurrentSubdivision = null; - break; - } - } - - IEnumerator Subdivide() - { - var ctx = ProbeGIBaking.PrepareProbeSubdivisionContext(probeVolumePerSceneData); - - // Cull all the cells that are not visible (we don't need them for realtime debug) - ctx.cells.RemoveAll(c => - { - return probeVolumePerSceneData.ShouldCullCell(c.position); - }); - - Camera activeCamera = Camera.current ?? SceneView.lastActiveSceneView.camera; - - // Sort cells by camera distance to compute the closest cells first - if (activeCamera != null) - { - var cameraPos = activeCamera.transform.position; - ctx.cells.Sort((c1, c2) => - { - c1.volume.CalculateCenterAndSize(out var c1Center, out var _); - float c1Distance = Vector3.Distance(cameraPos, c1Center); - - c2.volume.CalculateCenterAndSize(out var c2Center, out var _); - float c2Distance = Vector3.Distance(cameraPos, c2Center); - - return c1Distance.CompareTo(c2Distance); - }); - } - - // Progressively update cells: - var cells = ctx.cells.ToList(); - - // Remove all the cells that was not updated to prevent ghosting - foreach (var cellVolume in ctx.perSceneData.realtimeSubdivisionInfo.Keys.ToList()) - { - if (!cells.Any(c => c.volume.Equals(cellVolume))) - ctx.perSceneData.realtimeSubdivisionInfo.Remove(cellVolume); - } - - // Subdivide visible cells - foreach (var cell in cells) - { - // Override the cell list to only compute one cell - ctx.cells.Clear(); - ctx.cells.Add(cell); - - var result = ProbeGIBaking.BakeBricks(ctx); - ctx.perSceneData.realtimeSubdivisionInfo[cell.volume] = result.bricksPerCells[cell.position]; - - yield return null; - } - - yield break; - } - } - } - } - class ProbeSubdivisionContext { public List<(ProbeVolume component, ProbeReferenceVolume.Volume volume)> probeVolumes = new List<(ProbeVolume, ProbeReferenceVolume.Volume)>(); public List<(Renderer component, ProbeReferenceVolume.Volume volume)> renderers = new List<(Renderer, ProbeReferenceVolume.Volume)>(); public List<(Vector3Int position, ProbeReferenceVolume.Volume volume)> cells = new List<(Vector3Int, ProbeReferenceVolume.Volume)>(); public List<(Terrain, ProbeReferenceVolume.Volume volume)> terrains = new List<(Terrain, ProbeReferenceVolume.Volume)>(); - public ProbeVolumePerSceneData perSceneData; + public ProbeReferenceVolumeAuthoring refVolume; public ProbeReferenceVolumeProfile profile; - public void Initialize(ProbeVolumePerSceneData perSceneData, ProbeReferenceVolumeProfile profile, Vector3 refVolOrigin) + public void Initialize(ProbeReferenceVolumeAuthoring refVolume, ProbeReferenceVolumeProfile profile, Vector3 refVolOrigin) { - this.perSceneData = perSceneData; + this.refVolume = refVolume; this.profile = profile; - float cellSize = profile.cellSizeInMeters; + float cellSize = refVolume.cellSizeInMeters; foreach (var pv in UnityEngine.Object.FindObjectsOfType()) { diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs index 3443c61354a..d51e495a85f 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs @@ -213,6 +213,134 @@ void OnDestroy() QueueAssetRemoval(); } + internal bool ShouldCullCell(Vector3 cellPosition, Vector3 originWS = default(Vector3)) + { + if (m_Profile == null) + return true; + + var cameraTransform = SceneView.lastActiveSceneView.camera.transform; + + Vector3 cellCenterWS = cellPosition * m_Profile.cellSizeInMeters + originWS + Vector3.one * (m_Profile.cellSizeInMeters / 2.0f); + + // Round down to cell size distance + float roundedDownDist = Mathf.Floor(Vector3.Distance(cameraTransform.position, cellCenterWS) / m_Profile.cellSizeInMeters) * m_Profile.cellSizeInMeters; + + if (roundedDownDist > ProbeReferenceVolume.instance.debugDisplay.subdivisionViewCullingDistance) + return true; + + var frustumPlanes = GeometryUtility.CalculateFrustumPlanes(SceneView.lastActiveSceneView.camera); + var volumeAABB = new Bounds(cellCenterWS, m_Profile.cellSizeInMeters * Vector3.one); + + return !GeometryUtility.TestPlanesAABB(frustumPlanes, volumeAABB); + } + + // TODO: We need to get rid of Handles.DrawWireCube to be able to have those at runtime as well. + void OnDrawGizmos() + { + if (!enabled || !gameObject.activeSelf || !ProbeReferenceVolume.instance.isInitialized) + return; + + var debugDisplay = ProbeReferenceVolume.instance.debugDisplay; + + if (debugDisplay.drawBricks) + { + var subdivColors = ProbeReferenceVolume.instance.subdivisionDebugColors; + + IEnumerable GetVisibleBricks() + { + if (debugDisplay.realtimeSubdivision) + { + // realtime subdiv cells are already culled + foreach (var kp in realtimeSubdivisionInfo) + { + var cellVolume = kp.Key; + + foreach (var brick in kp.Value) + { + yield return brick; + } + } + } + else + { + foreach (var cell in ProbeReferenceVolume.instance.cells.Values) + { + if (ShouldCullCell(cell.position, ProbeReferenceVolume.instance.GetTransform().posWS)) + continue; + + if (cell.bricks == null) + continue; + + foreach (var brick in cell.bricks) + yield return brick; + } + } + } + + if (brickGizmos == null) + brickGizmos = new MeshGizmo((int)(Mathf.Pow(3, ProbeBrickIndex.kMaxSubdivisionLevels) * MeshGizmo.vertexCountPerCube)); + + brickGizmos.Clear(); + foreach (var brick in GetVisibleBricks()) + { + if (brick.subdivisionLevel < 0) + continue; + + Vector3 scaledSize = Vector3.one * Mathf.Pow(3, brick.subdivisionLevel); + Vector3 scaledPos = brick.position + scaledSize / 2; + brickGizmos.AddWireCube(scaledPos, scaledSize, subdivColors[brick.subdivisionLevel]); + } + + brickGizmos.RenderWireframe(ProbeReferenceVolume.instance.GetRefSpaceToWS(), gizmoName: "Brick Gizmo Rendering"); + } + + if (debugDisplay.drawCells) + { + IEnumerable GetVisibleCellCenters() + { + if (debugDisplay.realtimeSubdivision) + { + foreach (var kp in realtimeSubdivisionInfo) + { + kp.Key.CalculateCenterAndSize(out var center, out var _); + yield return center; + } + } + else + { + foreach (var cell in ProbeReferenceVolume.instance.cells.Values) + { + if (ShouldCullCell(cell.position, ProbeReferenceVolume.instance.GetTransform().posWS)) + continue; + + var positionF = new Vector3(cell.position.x, cell.position.y, cell.position.z); + var center = positionF * m_Profile.cellSizeInMeters + m_Profile.cellSizeInMeters * 0.5f * Vector3.one; + yield return center; + } + } + } + + Matrix4x4 trs = Matrix4x4.TRS(ProbeReferenceVolume.instance.GetTransform().posWS, ProbeReferenceVolume.instance.GetTransform().rot, Vector3.one); + + // For realtime subdivision, the matrix from ProbeReferenceVolume.instance can be wrong if the profile changed since the last bake + if (debugDisplay.realtimeSubdivision) + trs = Matrix4x4.TRS(transform.position, Quaternion.identity, Vector3.one); + + // Fetching this from components instead of from the reference volume allows the user to + // preview how cells will look before they commit to a bake. + Gizmos.color = new Color(0, 1, 0.5f, 0.2f); + Gizmos.matrix = trs; + if (cellGizmo == null) + cellGizmo = new MeshGizmo(); + cellGizmo.Clear(); + foreach (var center in GetVisibleCellCenters()) + { + Gizmos.DrawCube(center, Vector3.one * m_Profile.cellSizeInMeters); + cellGizmo.AddWireCube(center, Vector3.one * m_Profile.cellSizeInMeters, new Color(0, 1, 0.5f, 1)); + } + cellGizmo.RenderWireframe(Gizmos.matrix, gizmoName: "Brick Gizmo Rendering"); + } + } // IMPORTANT TODO: This is to be deleted when we have the proper setting panel. private void Update() diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs index 67efb3dd476..35ee9c67084 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs @@ -2,7 +2,6 @@ using UnityEngine.SceneManagement; using System.IO; using System; -using System.Collections; using System.Collections.Generic; #if UNITY_EDITOR @@ -22,6 +21,7 @@ enum ProbeVolumeState [AddComponentMenu("")] // Hide. internal class ProbeVolumePerSceneData : MonoBehaviour, ISerializationCallbackReceiver { + [System.Serializable] struct SerializableAssetItem { @@ -33,23 +33,8 @@ struct SerializableAssetItem [SerializeField] List serializedAssets; - [NonSerialized] ProbeVolumeState m_CurrentState = ProbeVolumeState.Default; - [NonSerialized] ProbeVolumeState m_PreviousState = ProbeVolumeState.Invalid; - - // Field used for the realtime subdivision preview - [NonSerialized] - internal Dictionary> realtimeSubdivisionInfo = new Dictionary>(); - - MeshGizmo brickGizmos; - MeshGizmo cellGizmo; - - void DisposeGizmos() - { - brickGizmos?.Dispose(); - brickGizmos = null; - cellGizmo?.Dispose(); - cellGizmo = null; - } + ProbeVolumeState m_CurrentState = ProbeVolumeState.Default; + ProbeVolumeState m_PreviousState = ProbeVolumeState.Invalid; /// /// OnAfterDeserialize implementation. @@ -124,13 +109,11 @@ void OnEnable() void OnDisable() { QueueAssetRemoval(); - DisposeGizmos(); } void OnDestroy() { QueueAssetRemoval(); - DisposeGizmos(); } void Update() @@ -148,141 +131,5 @@ void Update() } m_PreviousState = m_CurrentState; } - -#if UNITY_EDITOR - internal bool ShouldCullCell(Vector3 cellPosition, Vector3 originWS = default(Vector3)) - { - var profile = ProbeReferenceVolume.instance.sceneData.GetProfileForScene(gameObject.scene); - - if (profile == null) - return true; - - var cameraTransform = SceneView.lastActiveSceneView.camera.transform; - - Vector3 cellCenterWS = cellPosition * profile.cellSizeInMeters + originWS + Vector3.one * (profile.cellSizeInMeters / 2.0f); - - // Round down to cell size distance - float roundedDownDist = Mathf.Floor(Vector3.Distance(cameraTransform.position, cellCenterWS) / profile.cellSizeInMeters) * profile.cellSizeInMeters; - - if (roundedDownDist > ProbeReferenceVolume.instance.debugDisplay.subdivisionViewCullingDistance) - return true; - - var frustumPlanes = GeometryUtility.CalculateFrustumPlanes(SceneView.lastActiveSceneView.camera); - var volumeAABB = new Bounds(cellCenterWS, profile.cellSizeInMeters * Vector3.one); - - return !GeometryUtility.TestPlanesAABB(frustumPlanes, volumeAABB); - } - - // TODO: We need to get rid of Handles.DrawWireCube to be able to have those at runtime as well. - void OnDrawGizmos() - { - if (!enabled || !gameObject.activeSelf || !ProbeReferenceVolume.instance.isInitialized || ProbeReferenceVolume.instance.sceneData == null) - return; - - var profile = ProbeReferenceVolume.instance.sceneData.GetProfileForScene(gameObject.scene); - if (profile == null) return; - - var debugDisplay = ProbeReferenceVolume.instance.debugDisplay; - - if (debugDisplay.drawBricks) - { - var subdivColors = ProbeReferenceVolume.instance.subdivisionDebugColors; - - IEnumerable GetVisibleBricks() - { - if (debugDisplay.realtimeSubdivision) - { - // realtime subdiv cells are already culled - foreach (var kp in realtimeSubdivisionInfo) - { - var cellVolume = kp.Key; - - foreach (var brick in kp.Value) - { - yield return brick; - } - } - } - else - { - foreach (var cell in ProbeReferenceVolume.instance.cells.Values) - { - if (ShouldCullCell(cell.position, ProbeReferenceVolume.instance.GetTransform().posWS)) - continue; - - if (cell.bricks == null) - continue; - - foreach (var brick in cell.bricks) - yield return brick; - } - } - } - - if (brickGizmos == null) - brickGizmos = new MeshGizmo((int)(Mathf.Pow(3, ProbeBrickIndex.kMaxSubdivisionLevels) * MeshGizmo.vertexCountPerCube)); - - brickGizmos.Clear(); - foreach (var brick in GetVisibleBricks()) - { - if (brick.subdivisionLevel < 0) - continue; - - Vector3 scaledSize = Vector3.one * Mathf.Pow(3, brick.subdivisionLevel); - Vector3 scaledPos = brick.position + scaledSize / 2; - brickGizmos.AddWireCube(scaledPos, scaledSize, subdivColors[brick.subdivisionLevel]); - } - - brickGizmos.RenderWireframe(ProbeReferenceVolume.instance.GetRefSpaceToWS(), gizmoName: "Brick Gizmo Rendering"); - } - - if (debugDisplay.drawCells) - { - IEnumerable GetVisibleCellCenters() - { - if (debugDisplay.realtimeSubdivision) - { - foreach (var kp in realtimeSubdivisionInfo) - { - kp.Key.CalculateCenterAndSize(out var center, out var _); - yield return center; - } - } - else - { - foreach (var cell in ProbeReferenceVolume.instance.cells.Values) - { - if (ShouldCullCell(cell.position, ProbeReferenceVolume.instance.GetTransform().posWS)) - continue; - - var positionF = new Vector3(cell.position.x, cell.position.y, cell.position.z); - var center = positionF * profile.cellSizeInMeters + profile.cellSizeInMeters * 0.5f * Vector3.one; - yield return center; - } - } - } - - Matrix4x4 trs = Matrix4x4.TRS(ProbeReferenceVolume.instance.GetTransform().posWS, ProbeReferenceVolume.instance.GetTransform().rot, Vector3.one); - - // For realtime subdivision, the matrix from ProbeReferenceVolume.instance can be wrong if the profile changed since the last bake - if (debugDisplay.realtimeSubdivision) - trs = Matrix4x4.TRS(transform.position, Quaternion.identity, Vector3.one); - - // Fetching this from components instead of from the reference volume allows the user to - // preview how cells will look before they commit to a bake. - Gizmos.color = new Color(0, 1, 0.5f, 0.2f); - Gizmos.matrix = trs; - if (cellGizmo == null) - cellGizmo = new MeshGizmo(); - cellGizmo.Clear(); - foreach (var center in GetVisibleCellCenters()) - { - Gizmos.DrawCube(center, Vector3.one * profile.cellSizeInMeters); - cellGizmo.AddWireCube(center, Vector3.one * profile.cellSizeInMeters, new Color(0, 1, 0.5f, 1)); - } - cellGizmo.RenderWireframe(Gizmos.matrix, gizmoName: "Brick Gizmo Rendering"); - } - } -#endif } } From 17fd32e0a97eb35778ae51e65cf2545bafd0328a Mon Sep 17 00:00:00 2001 From: FrancescoC-Unity Date: Tue, 31 Aug 2021 19:16:51 +0200 Subject: [PATCH 08/18] Remove all probe ref volume authroing from baking, yay! --- .../Editor/Lighting/ProbeVolume/ProbeGIBaking.cs | 11 ++--------- .../ProbeReferenceVolumeAuthoringEditor.cs | 6 +++--- .../Lighting/ProbeVolume/ProbeSubdivisionContext.cs | 6 ++---- .../ProbeVolume/ProbeReferenceVolume.Debug.cs | 3 +++ .../ProbeVolume/ProbeReferenceVolumeAuthoring.cs | 7 ++----- 5 files changed, 12 insertions(+), 21 deletions(-) diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs index 75beb48f69d..575bf93f061 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs @@ -252,15 +252,8 @@ static void OnBakeStarted() var perSceneDataList = GameObject.FindObjectsOfType(); if (perSceneDataList.Length == 0) return; - m_BakingReferenceVolumeAuthoring = GetCardinalAuthoringComponent(refVolAuthList); SetBakingContext(perSceneDataList); - if (m_BakingReferenceVolumeAuthoring == null) - { - Debug.Log("Scene(s) have multiple inconsistent ProbeReferenceVolumeAuthoring components. Please ensure they use identical profiles and transforms before baking."); - return; - } - AddOccluders(); RunPlacement(); @@ -662,7 +655,7 @@ public static void RunPlacement() ClearBakingBatch(); // Subdivide the scene and place the bricks - var ctx = PrepareProbeSubdivisionContext(m_BakingReferenceVolumeAuthoring); + var ctx = PrepareProbeSubdivisionContext(); var result = BakeBricks(ctx); // Compute probe positions and send them to the Lightmapper @@ -677,7 +670,7 @@ public static ProbeSubdivisionContext PrepareProbeSubdivisionContext(ProbeRefere // Prepare all the information in the scene for baking GI. Vector3 refVolOrigin = Vector3.zero; // TODO: This will need to be center of the world bounds. - ctx.Initialize(refVolume, m_BakingProfile, refVolOrigin); + ctx.Initialize(m_BakingProfile, refVolOrigin); return ctx; } diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs index 132242ae883..028aac70ca0 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs @@ -99,10 +99,10 @@ IEnumerator Subdivide() var cells = ctx.cells.ToList(); // Remove all the cells that was not updated to prevent ghosting - foreach (var cellVolume in ctx.refVolume.realtimeSubdivisionInfo.Keys.ToList()) + foreach (var cellVolume in ProbeReferenceVolume.instance.realtimeSubdivisionInfo.Keys.ToList()) { if (!cells.Any(c => c.volume.Equals(cellVolume))) - ctx.refVolume.realtimeSubdivisionInfo.Remove(cellVolume); + ProbeReferenceVolume.instance.realtimeSubdivisionInfo.Remove(cellVolume); } // Subdivide visible cells @@ -113,7 +113,7 @@ IEnumerator Subdivide() ctx.cells.Add(cell); var result = ProbeGIBaking.BakeBricks(ctx); - ctx.refVolume.realtimeSubdivisionInfo[cell.volume] = result.bricksPerCells[cell.position]; + ProbeReferenceVolume.instance.realtimeSubdivisionInfo[cell.volume] = result.bricksPerCells[cell.position]; yield return null; } diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeSubdivisionContext.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeSubdivisionContext.cs index 49fec4fe422..e736ac353b9 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeSubdivisionContext.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeSubdivisionContext.cs @@ -16,14 +16,12 @@ class ProbeSubdivisionContext public List<(Renderer component, ProbeReferenceVolume.Volume volume)> renderers = new List<(Renderer, ProbeReferenceVolume.Volume)>(); public List<(Vector3Int position, ProbeReferenceVolume.Volume volume)> cells = new List<(Vector3Int, ProbeReferenceVolume.Volume)>(); public List<(Terrain, ProbeReferenceVolume.Volume volume)> terrains = new List<(Terrain, ProbeReferenceVolume.Volume)>(); - public ProbeReferenceVolumeAuthoring refVolume; public ProbeReferenceVolumeProfile profile; - public void Initialize(ProbeReferenceVolumeAuthoring refVolume, ProbeReferenceVolumeProfile profile, Vector3 refVolOrigin) + public void Initialize(ProbeReferenceVolumeProfile profile, Vector3 refVolOrigin) { - this.refVolume = refVolume; this.profile = profile; - float cellSize = refVolume.cellSizeInMeters; + float cellSize = profile.cellSizeInMeters; foreach (var pv in UnityEngine.Object.FindObjectsOfType()) { diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.Debug.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.Debug.cs index 02b5a3c9d0c..7eaa3ea32dd 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.Debug.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.Debug.cs @@ -53,6 +53,8 @@ class CellInstancedDebugProbes internal float dilationValidtyThreshold = 0.25f; // We ned to store this here to access it + // Field used for the realtime subdivision preview + internal Dictionary> realtimeSubdivisionInfo = new Dictionary>(); /// /// Render Probe Volume related debug @@ -238,6 +240,7 @@ void DrawProbeDebug(Camera camera) void ClearDebugData() { m_CellDebugData.Clear(); + realtimeSubdivisionInfo.Clear(); } void CreateInstancedProbes() diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs index d51e495a85f..e1d42001bf4 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs @@ -104,9 +104,6 @@ internal static ProbeReferenceVolumeProfile CreateReferenceVolumeProfile(Scene s [SerializeField] float m_VirtualOffsetBiasOutOfGeometry = 0.01f; - // Field used for the realtime subdivision preview - [NonSerialized] - internal Dictionary> realtimeSubdivisionInfo = new Dictionary>(); MeshGizmo brickGizmos; MeshGizmo cellGizmo; @@ -251,7 +248,7 @@ void OnDrawGizmos() if (debugDisplay.realtimeSubdivision) { // realtime subdiv cells are already culled - foreach (var kp in realtimeSubdivisionInfo) + foreach (var kp in ProbeReferenceVolume.instance.realtimeSubdivisionInfo) { var cellVolume = kp.Key; @@ -300,7 +297,7 @@ IEnumerable GetVisibleCellCenters() { if (debugDisplay.realtimeSubdivision) { - foreach (var kp in realtimeSubdivisionInfo) + foreach (var kp in ProbeReferenceVolume.instance.realtimeSubdivisionInfo) { kp.Key.CalculateCenterAndSize(out var center, out var _); yield return center; From 809f5609532da37cb45c300d7439418e9aab9fb3 Mon Sep 17 00:00:00 2001 From: FrancescoC-Unity Date: Wed, 1 Sep 2021 10:20:30 +0200 Subject: [PATCH 09/18] Moving draw gizmo away and remove all reference of authoring from baking --- .../Lighting/ProbeVolume/ProbeGIBaking.cs | 9 +- .../ProbeReferenceVolumeAuthoringEditor.cs | 16 +- .../ProbeReferenceVolumeAuthoring.cs | 138 -------------- .../Lighting/ProbeVolume/ProbeVolume.cs | 175 +++++++++++++++++- 4 files changed, 191 insertions(+), 147 deletions(-) diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs index 575bf93f061..90b2ca6bab8 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs @@ -51,7 +51,6 @@ partial class ProbeGIBaking { static bool m_IsInit = false; static BakingBatch m_BakingBatch; - static ProbeReferenceVolumeAuthoring m_BakingReferenceVolumeAuthoring = null; static ProbeReferenceVolumeProfile m_BakingProfile = null; static ProbeVolumeBakingProcessSettings m_BakingSettings; @@ -664,12 +663,18 @@ public static void RunPlacement() ApplySubdivisionResults(result, newRefToWS); } - public static ProbeSubdivisionContext PrepareProbeSubdivisionContext(ProbeReferenceVolumeAuthoring refVolume) + public static ProbeSubdivisionContext PrepareProbeSubdivisionContext() { ProbeSubdivisionContext ctx = new ProbeSubdivisionContext(); // Prepare all the information in the scene for baking GI. Vector3 refVolOrigin = Vector3.zero; // TODO: This will need to be center of the world bounds. + if (m_BakingProfile == null) + { + var perSceneDataList = GameObject.FindObjectsOfType(); + if (perSceneDataList.Length == 0) return ctx; + SetBakingContext(perSceneDataList); + } ctx.Initialize(m_BakingProfile, refVolOrigin); return ctx; diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs index 028aac70ca0..af1603a6edb 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs @@ -42,8 +42,12 @@ static void UpdateRealtimeSubdivisionDebug() if (Time.realtimeSinceStartupAsDouble - s_LastSubdivisionTime > debugDisplay.subdivisionDelayInSeconds) { - var probeVolumeAuthoring = FindObjectOfType(); - if (probeVolumeAuthoring == null || !probeVolumeAuthoring.isActiveAndEnabled) + var probeVolume = FindObjectOfType(); + if (probeVolume == null || !probeVolume.isActiveAndEnabled || ProbeReferenceVolume.instance.sceneData == null) + return; + + var profile = ProbeReferenceVolume.instance.sceneData.GetProfileForScene(probeVolume.gameObject.scene); + if (profile == null) return; if (s_CurrentSubdivision == null) @@ -55,8 +59,8 @@ static void UpdateRealtimeSubdivisionDebug() // Step the subdivision with the amount of cell per frame in debug menu int updatePerFrame = debugDisplay.subdivisionCellUpdatePerFrame; // From simplification level 5 and higher, the cost of calculating one cell is very high, so we adjust that number. - if (probeVolumeAuthoring.profile.simplificationLevels > 4) - updatePerFrame = (int)Mathf.Max(1, updatePerFrame / Mathf.Pow(9, probeVolumeAuthoring.profile.simplificationLevels - 4)); + if (profile.simplificationLevels > 4) + updatePerFrame = (int)Mathf.Max(1, updatePerFrame / Mathf.Pow(9, profile.simplificationLevels - 4)); for (int i = 0; i < debugDisplay.subdivisionCellUpdatePerFrame; i++) { if (!s_CurrentSubdivision.MoveNext()) @@ -69,12 +73,12 @@ static void UpdateRealtimeSubdivisionDebug() IEnumerator Subdivide() { - var ctx = ProbeGIBaking.PrepareProbeSubdivisionContext(probeVolumeAuthoring); + var ctx = ProbeGIBaking.PrepareProbeSubdivisionContext(); // Cull all the cells that are not visible (we don't need them for realtime debug) ctx.cells.RemoveAll(c => { - return probeVolumeAuthoring.ShouldCullCell(c.position); + return probeVolume.ShouldCullCell(c.position); }); Camera activeCamera = Camera.current ?? SceneView.lastActiveSceneView.camera; diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs index e1d42001bf4..0016bb3e77f 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs @@ -104,10 +104,6 @@ internal static ProbeReferenceVolumeProfile CreateReferenceVolumeProfile(Scene s [SerializeField] float m_VirtualOffsetBiasOutOfGeometry = 0.01f; - - MeshGizmo brickGizmos; - MeshGizmo cellGizmo; - // In some cases Unity will magically popuplate this private field with a correct value even though it should not be serialized. // The [NonSerialized] attribute allows to force the asset to be null in case a domain reload happens. [NonSerialized] @@ -155,11 +151,6 @@ internal void QueueAssetRemoval() return; #if UNITY_EDITOR - brickGizmos?.Dispose(); - brickGizmos = null; - cellGizmo?.Dispose(); - cellGizmo = null; - m_PrevAsset = null; #endif } @@ -210,135 +201,6 @@ void OnDestroy() QueueAssetRemoval(); } - internal bool ShouldCullCell(Vector3 cellPosition, Vector3 originWS = default(Vector3)) - { - if (m_Profile == null) - return true; - - var cameraTransform = SceneView.lastActiveSceneView.camera.transform; - - Vector3 cellCenterWS = cellPosition * m_Profile.cellSizeInMeters + originWS + Vector3.one * (m_Profile.cellSizeInMeters / 2.0f); - - // Round down to cell size distance - float roundedDownDist = Mathf.Floor(Vector3.Distance(cameraTransform.position, cellCenterWS) / m_Profile.cellSizeInMeters) * m_Profile.cellSizeInMeters; - - if (roundedDownDist > ProbeReferenceVolume.instance.debugDisplay.subdivisionViewCullingDistance) - return true; - - var frustumPlanes = GeometryUtility.CalculateFrustumPlanes(SceneView.lastActiveSceneView.camera); - var volumeAABB = new Bounds(cellCenterWS, m_Profile.cellSizeInMeters * Vector3.one); - - return !GeometryUtility.TestPlanesAABB(frustumPlanes, volumeAABB); - } - - // TODO: We need to get rid of Handles.DrawWireCube to be able to have those at runtime as well. - void OnDrawGizmos() - { - if (!enabled || !gameObject.activeSelf || !ProbeReferenceVolume.instance.isInitialized) - return; - - var debugDisplay = ProbeReferenceVolume.instance.debugDisplay; - - if (debugDisplay.drawBricks) - { - var subdivColors = ProbeReferenceVolume.instance.subdivisionDebugColors; - - IEnumerable GetVisibleBricks() - { - if (debugDisplay.realtimeSubdivision) - { - // realtime subdiv cells are already culled - foreach (var kp in ProbeReferenceVolume.instance.realtimeSubdivisionInfo) - { - var cellVolume = kp.Key; - - foreach (var brick in kp.Value) - { - yield return brick; - } - } - } - else - { - foreach (var cell in ProbeReferenceVolume.instance.cells.Values) - { - if (ShouldCullCell(cell.position, ProbeReferenceVolume.instance.GetTransform().posWS)) - continue; - - if (cell.bricks == null) - continue; - - foreach (var brick in cell.bricks) - yield return brick; - } - } - } - - if (brickGizmos == null) - brickGizmos = new MeshGizmo((int)(Mathf.Pow(3, ProbeBrickIndex.kMaxSubdivisionLevels) * MeshGizmo.vertexCountPerCube)); - - brickGizmos.Clear(); - foreach (var brick in GetVisibleBricks()) - { - if (brick.subdivisionLevel < 0) - continue; - - Vector3 scaledSize = Vector3.one * Mathf.Pow(3, brick.subdivisionLevel); - Vector3 scaledPos = brick.position + scaledSize / 2; - brickGizmos.AddWireCube(scaledPos, scaledSize, subdivColors[brick.subdivisionLevel]); - } - - brickGizmos.RenderWireframe(ProbeReferenceVolume.instance.GetRefSpaceToWS(), gizmoName: "Brick Gizmo Rendering"); - } - - if (debugDisplay.drawCells) - { - IEnumerable GetVisibleCellCenters() - { - if (debugDisplay.realtimeSubdivision) - { - foreach (var kp in ProbeReferenceVolume.instance.realtimeSubdivisionInfo) - { - kp.Key.CalculateCenterAndSize(out var center, out var _); - yield return center; - } - } - else - { - foreach (var cell in ProbeReferenceVolume.instance.cells.Values) - { - if (ShouldCullCell(cell.position, ProbeReferenceVolume.instance.GetTransform().posWS)) - continue; - - var positionF = new Vector3(cell.position.x, cell.position.y, cell.position.z); - var center = positionF * m_Profile.cellSizeInMeters + m_Profile.cellSizeInMeters * 0.5f * Vector3.one; - yield return center; - } - } - } - - Matrix4x4 trs = Matrix4x4.TRS(ProbeReferenceVolume.instance.GetTransform().posWS, ProbeReferenceVolume.instance.GetTransform().rot, Vector3.one); - - // For realtime subdivision, the matrix from ProbeReferenceVolume.instance can be wrong if the profile changed since the last bake - if (debugDisplay.realtimeSubdivision) - trs = Matrix4x4.TRS(transform.position, Quaternion.identity, Vector3.one); - - // Fetching this from components instead of from the reference volume allows the user to - // preview how cells will look before they commit to a bake. - Gizmos.color = new Color(0, 1, 0.5f, 0.2f); - Gizmos.matrix = trs; - if (cellGizmo == null) - cellGizmo = new MeshGizmo(); - cellGizmo.Clear(); - foreach (var center in GetVisibleCellCenters()) - { - Gizmos.DrawCube(center, Vector3.one * m_Profile.cellSizeInMeters); - cellGizmo.AddWireCube(center, Vector3.one * m_Profile.cellSizeInMeters, new Color(0, 1, 0.5f, 1)); - } - cellGizmo.RenderWireframe(Gizmos.matrix, gizmoName: "Brick Gizmo Rendering"); - } - } - // IMPORTANT TODO: This is to be deleted when we have the proper setting panel. private void Update() { diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolume.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolume.cs index ba36ace86a8..74378765a81 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolume.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolume.cs @@ -3,8 +3,10 @@ using UnityEditor.Experimental; using Unity.Collections; using System.Collections.Generic; -#if UNITY_EDITOR +using UnityEngine.Rendering; using UnityEngine.SceneManagement; + +#if UNITY_EDITOR using UnityEditor; #endif @@ -120,5 +122,176 @@ public override int GetHashCode() } #endif + + // Momentarily moving the gizmo rendering for bricks and cells to Probe Volume itself, + // only the first probe volume in the scene will render them. The reason is that we dont have any + // other non-hidden component related to APV. + #region APVGizmo + + MeshGizmo brickGizmos; + MeshGizmo cellGizmo; + + void DisposeGizmos() + { + brickGizmos?.Dispose(); + brickGizmos = null; + cellGizmo?.Dispose(); + cellGizmo = null; + } + + void OnDestroy() + { + DisposeGizmos(); + } + + void OnDisable() + { + DisposeGizmos(); + } +#if UNITY_EDITOR + + // Only the first PV of the available ones will draw gizmos. + bool IsResponsibleToDrawGizmo() + { + var pvList = GameObject.FindObjectsOfType(); + return this == pvList[0]; + } + + internal bool ShouldCullCell(Vector3 cellPosition, Vector3 originWS = default(Vector3)) + { + var profile = ProbeReferenceVolume.instance.sceneData.GetProfileForScene(gameObject.scene); + if (profile == null) + return true; + + var cameraTransform = SceneView.lastActiveSceneView.camera.transform; + + Vector3 cellCenterWS = cellPosition * profile.cellSizeInMeters + originWS + Vector3.one * (profile.cellSizeInMeters / 2.0f); + + // Round down to cell size distance + float roundedDownDist = Mathf.Floor(Vector3.Distance(cameraTransform.position, cellCenterWS) / profile.cellSizeInMeters) * profile.cellSizeInMeters; + + if (roundedDownDist > ProbeReferenceVolume.instance.debugDisplay.subdivisionViewCullingDistance) + return true; + + var frustumPlanes = GeometryUtility.CalculateFrustumPlanes(SceneView.lastActiveSceneView.camera); + var volumeAABB = new Bounds(cellCenterWS, profile.cellSizeInMeters * Vector3.one); + + return !GeometryUtility.TestPlanesAABB(frustumPlanes, volumeAABB); + } + + // TODO: We need to get rid of Handles.DrawWireCube to be able to have those at runtime as well. + void OnDrawGizmos() + { + if (!ProbeReferenceVolume.instance.isInitialized || !IsResponsibleToDrawGizmo() || ProbeReferenceVolume.instance.sceneData == null) + return; + + var profile = ProbeReferenceVolume.instance.sceneData.GetProfileForScene(gameObject.scene); + if (profile == null) + return; + + var debugDisplay = ProbeReferenceVolume.instance.debugDisplay; + + if (debugDisplay.drawBricks) + { + var subdivColors = ProbeReferenceVolume.instance.subdivisionDebugColors; + + IEnumerable GetVisibleBricks() + { + if (debugDisplay.realtimeSubdivision) + { + // realtime subdiv cells are already culled + foreach (var kp in ProbeReferenceVolume.instance.realtimeSubdivisionInfo) + { + var cellVolume = kp.Key; + + foreach (var brick in kp.Value) + { + yield return brick; + } + } + } + else + { + foreach (var cell in ProbeReferenceVolume.instance.cells.Values) + { + if (ShouldCullCell(cell.position, ProbeReferenceVolume.instance.GetTransform().posWS)) + continue; + + if (cell.bricks == null) + continue; + + foreach (var brick in cell.bricks) + yield return brick; + } + } + } + + if (brickGizmos == null) + brickGizmos = new MeshGizmo((int)(Mathf.Pow(3, ProbeBrickIndex.kMaxSubdivisionLevels) * MeshGizmo.vertexCountPerCube)); + + brickGizmos.Clear(); + foreach (var brick in GetVisibleBricks()) + { + if (brick.subdivisionLevel < 0) + continue; + + Vector3 scaledSize = Vector3.one * Mathf.Pow(3, brick.subdivisionLevel); + Vector3 scaledPos = brick.position + scaledSize / 2; + brickGizmos.AddWireCube(scaledPos, scaledSize, subdivColors[brick.subdivisionLevel]); + } + + brickGizmos.RenderWireframe(ProbeReferenceVolume.instance.GetRefSpaceToWS(), gizmoName: "Brick Gizmo Rendering"); + } + + if (debugDisplay.drawCells) + { + IEnumerable GetVisibleCellCenters() + { + if (debugDisplay.realtimeSubdivision) + { + foreach (var kp in ProbeReferenceVolume.instance.realtimeSubdivisionInfo) + { + kp.Key.CalculateCenterAndSize(out var center, out var _); + yield return center; + } + } + else + { + foreach (var cell in ProbeReferenceVolume.instance.cells.Values) + { + if (ShouldCullCell(cell.position, ProbeReferenceVolume.instance.GetTransform().posWS)) + continue; + + var positionF = new Vector3(cell.position.x, cell.position.y, cell.position.z); + var center = positionF * profile.cellSizeInMeters + profile.cellSizeInMeters * 0.5f * Vector3.one; + yield return center; + } + } + } + + Matrix4x4 trs = Matrix4x4.TRS(ProbeReferenceVolume.instance.GetTransform().posWS, ProbeReferenceVolume.instance.GetTransform().rot, Vector3.one); + + // For realtime subdivision, the matrix from ProbeReferenceVolume.instance can be wrong if the profile changed since the last bake + if (debugDisplay.realtimeSubdivision) + trs = Matrix4x4.TRS(transform.position, Quaternion.identity, Vector3.one); + + // Fetching this from components instead of from the reference volume allows the user to + // preview how cells will look before they commit to a bake. + Gizmos.color = new Color(0, 1, 0.5f, 0.2f); + Gizmos.matrix = trs; + if (cellGizmo == null) + cellGizmo = new MeshGizmo(); + cellGizmo.Clear(); + foreach (var center in GetVisibleCellCenters()) + { + Gizmos.DrawCube(center, Vector3.one * profile.cellSizeInMeters); + cellGizmo.AddWireCube(center, Vector3.one * profile.cellSizeInMeters, new Color(0, 1, 0.5f, 1)); + } + cellGizmo.RenderWireframe(Gizmos.matrix, gizmoName: "Brick Gizmo Rendering"); + } + } + +#endif + #endregion } } // UnityEngine.Experimental.Rendering.HDPipeline From 332ec814b07e932dc8fb2320da42e7255714c372 Mon Sep 17 00:00:00 2001 From: FrancescoC-Unity Date: Wed, 1 Sep 2021 10:27:53 +0200 Subject: [PATCH 10/18] Make sure baking profile is available if required during non baking --- .../Editor/Lighting/ProbeVolume/ProbeGIBaking.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs index 90b2ca6bab8..42d72efdf96 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs @@ -293,7 +293,12 @@ static void BrickCountInDirections(out Vector3Int cellsInXYZ, float brickSizeInM // It is only a first iteration of the concept that won't be as impactful on memory as other options. internal static void RevertDilation() { - if (m_BakingProfile == null) return; + if (m_BakingProfile == null) + { + var perSceneDataList = GameObject.FindObjectsOfType(); + if (perSceneDataList.Length == 0) return; + SetBakingContext(perSceneDataList); + } var dilationSettings = m_BakingSettings.dilationSettings; @@ -321,8 +326,12 @@ internal static void PerformDilation() { Dictionary> cell2Assets = new Dictionary>(); var perSceneDataList = GameObject.FindObjectsOfType(); + if (perSceneDataList.Length == 0) return; - if (m_BakingProfile == null) return; + if (m_BakingProfile == null) + { + SetBakingContext(perSceneDataList); + } foreach (var sceneData in perSceneDataList) { From e628d771bcef59354dfe7ac4586ce9596ef81a49 Mon Sep 17 00:00:00 2001 From: FrancescoC-Unity Date: Wed, 1 Sep 2021 13:06:25 +0200 Subject: [PATCH 11/18] Load profile info from the asset --- .../ProbeVolume/ProbeReferenceVolume.cs | 5 ++ .../ProbeReferenceVolumeAuthoring.cs | 64 +------------------ .../Lighting/ProbeVolume/ProbeVolumeAsset.cs | 3 + .../ProbeVolume/ProbeVolumePerSceneData.cs | 11 +++- 4 files changed, 19 insertions(+), 64 deletions(-) diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs index e817bcaae89..e7c52ef024a 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs @@ -813,6 +813,11 @@ void LoadAsset(ProbeVolumeAsset asset) var path = asset.GetSerializedFullPath(); + // Load info coming originally from profile + SetTRS(Vector3.zero, Quaternion.identity, asset.minBrickSize); + SetMaxSubdivision(asset.maxSubdivision); + + for (int i = 0; i < asset.cells.Count; ++i) { var cell = asset.cells[i]; diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs index 0016bb3e77f..db5c09ce6ed 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs @@ -75,9 +75,6 @@ internal static ProbeReferenceVolumeProfile CreateReferenceVolumeProfile(Scene s [SerializeField] ProbeReferenceVolumeProfile m_Profile = null; -#if UNITY_EDITOR - ProbeReferenceVolumeProfile m_PrevProfile = null; -#endif internal ProbeReferenceVolumeProfile profile { get { return m_Profile; } } internal float brickSize { get { return m_Profile.minBrickSize; } } @@ -104,11 +101,6 @@ internal static ProbeReferenceVolumeProfile CreateReferenceVolumeProfile(Scene s [SerializeField] float m_VirtualOffsetBiasOutOfGeometry = 0.01f; - // In some cases Unity will magically popuplate this private field with a correct value even though it should not be serialized. - // The [NonSerialized] attribute allows to force the asset to be null in case a domain reload happens. - [NonSerialized] - ProbeVolumeAsset m_PrevAsset = null; - [NonSerialized] bool m_SentDataToSceneData = false; // TODO: This is temp until we don't have a setting panel. #endif @@ -117,16 +109,7 @@ internal static ProbeReferenceVolumeProfile CreateReferenceVolumeProfile(Scene s public ProbeVolumeAsset volumeAsset = null; - internal void LoadProfileInformation() - { - if (m_Profile == null) - return; - - var refVol = ProbeReferenceVolume.instance; - refVol.SetTRS(Vector3.zero, Quaternion.identity, m_Profile.minBrickSize); - refVol.SetMaxSubdivision(m_Profile.maxSubdivision); - refVol.dilationValidtyThreshold = m_DilationValidityThreshold; - } +#if UNITY_EDITOR // TEMP! THIS NEEDS TO BE REMOVED WHEN WE HAVE THE SETTINGS PANEL. void SendSceneData(bool force = false) @@ -140,66 +123,21 @@ void SendSceneData(bool force = false) } } - internal void QueueAssetLoading() - { - LoadProfileInformation(); - } - - internal void QueueAssetRemoval() - { - if (volumeAsset == null) - return; - -#if UNITY_EDITOR - m_PrevAsset = null; -#endif - } - void OnEnable() { -#if UNITY_EDITOR if (m_Profile == null) m_Profile = CreateReferenceVolumeProfile(gameObject.scene, gameObject.name); -#endif SendSceneData(force: true); - QueueAssetLoading(); } -#if UNITY_EDITOR - void OnValidate() { if (!enabled || !gameObject.activeSelf) return; - if (m_Profile != null) - { - m_PrevProfile = m_Profile; - } - - if (volumeAsset != m_PrevAsset && m_PrevAsset != null) - { - ProbeReferenceVolume.instance.AddPendingAssetRemoval(m_PrevAsset); - } - - if (volumeAsset != m_PrevAsset) - { - QueueAssetLoading(); - } - - m_PrevAsset = volumeAsset; SendSceneData(force: true); } - void OnDisable() - { - QueueAssetRemoval(); - } - - void OnDestroy() - { - QueueAssetRemoval(); - } // IMPORTANT TODO: This is to be deleted when we have the proper setting panel. private void Update() diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeAsset.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeAsset.cs index 3e6d62abe02..c11486336ea 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeAsset.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeAsset.cs @@ -38,6 +38,9 @@ internal enum AssetVersion [SerializeField] internal float minDistanceBetweenProbes; [SerializeField] internal int simplificationLevels; + internal int maxSubdivision => simplificationLevels + 1; // we add one for the top subdiv level which is the same size as a cell + internal float minBrickSize => Mathf.Max(0.01f, minDistanceBetweenProbes * 3.0f); + public string GetSerializedFullPath() { diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs index 35ee9c67084..00cd3f02af6 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs @@ -91,8 +91,17 @@ internal ProbeVolumeAsset GetCurrentStateAsset() internal void QueueAssetLoading() { + var refVol = ProbeReferenceVolume.instance; if (assets.ContainsKey(m_CurrentState) && assets[m_CurrentState] != null) - ProbeReferenceVolume.instance.AddPendingAssetLoading(assets[m_CurrentState]); + { + refVol.AddPendingAssetLoading(assets[m_CurrentState]); +#if UNITY_EDITOR + if (refVol.sceneData != null) + { + refVol.dilationValidtyThreshold = refVol.sceneData.GetBakeSettingsForScene(gameObject.scene).dilationSettings.dilationValidityThreshold; + } +#endif + } } internal void QueueAssetRemoval() From 802547a3fe0ba138d1b599e24da39bca22ded063 Mon Sep 17 00:00:00 2001 From: FrancescoC-Unity Date: Wed, 1 Sep 2021 15:07:33 +0200 Subject: [PATCH 12/18] Fix dilation refresh --- .../Editor/Lighting/ProbeVolume/ProbeGIBaking.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs index 42d72efdf96..eea1294ec3f 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs @@ -328,10 +328,7 @@ internal static void PerformDilation() var perSceneDataList = GameObject.FindObjectsOfType(); if (perSceneDataList.Length == 0) return; - if (m_BakingProfile == null) - { - SetBakingContext(perSceneDataList); - } + SetBakingContext(perSceneDataList); foreach (var sceneData in perSceneDataList) { @@ -346,11 +343,12 @@ internal static void PerformDilation() cell2Assets[cell.index].Add(assetPath); } + // We need to queue the asset loading to make sure all is fine when calling refresh. + sceneData.QueueAssetLoading(); } var dilationSettings = m_BakingSettings.dilationSettings; - if (dilationSettings.dilationDistance > 0.0f) { // Force maximum sh bands to perform dilation, we need to store what sh bands was selected from the settings as we need to restore From 4559ebc3c1d09b84e523ca7318926a1e4d91568b Mon Sep 17 00:00:00 2001 From: FrancescoC-Unity Date: Wed, 1 Sep 2021 18:11:53 +0200 Subject: [PATCH 13/18] remove some other things --- .../Lighting/ProbeVolume/ProbeGIBaking.cs | 37 ------ .../ProbeReferenceVolumeAuthoringEditor.cs | 119 ------------------ .../ProbeVolume/ProbeSubdivisionContext.cs | 117 +++++++++++++++++ 3 files changed, 117 insertions(+), 156 deletions(-) diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs index eea1294ec3f..0cbec6c5019 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs @@ -206,48 +206,11 @@ static void SetBakingContext(ProbeVolumePerSceneData[] perSceneData) } } - static ProbeReferenceVolumeAuthoring GetCardinalAuthoringComponent(ProbeReferenceVolumeAuthoring[] refVolAuthList) - { - List enabledVolumes = new List(); - - foreach (var refVolAuthoring in refVolAuthList) - { - if (!refVolAuthoring.enabled || !refVolAuthoring.gameObject.activeSelf) - continue; - - enabledVolumes.Add(refVolAuthoring); - } - - int numVols = enabledVolumes.Count; - - if (numVols == 0) - return null; - - if (numVols == 1) - return enabledVolumes[0]; - - var reference = enabledVolumes[0]; - for (int c = 1; c < numVols; ++c) - { - var compare = enabledVolumes[c]; - if (!reference.profile.IsEquivalent(compare.profile)) - return null; - } - - return reference; - } - static void OnBakeStarted() { if (!ProbeReferenceVolume.instance.isInitialized) return; - var refVolAuthList = GameObject.FindObjectsOfType(); // TODO: To remove. - - if (refVolAuthList.Length == 0) - return; - FindWorldBounds(); - refVolAuthList = GameObject.FindObjectsOfType(); var perSceneDataList = GameObject.FindObjectsOfType(); if (perSceneDataList.Length == 0) return; diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs index af1603a6edb..d11d093952b 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs @@ -12,122 +12,6 @@ namespace UnityEngine.Experimental.Rendering [CustomEditor(typeof(ProbeReferenceVolumeAuthoring))] internal class ProbeReferenceVolumeAuthoringEditor : Editor { - [InitializeOnLoad] - class RealtimeProbeSubdivisionDebug - { - static double s_LastSubdivisionTime; - static double s_LastRefreshTime; - static IEnumerator s_CurrentSubdivision; - - static RealtimeProbeSubdivisionDebug() - { - EditorApplication.update -= UpdateRealtimeSubdivisionDebug; - EditorApplication.update += UpdateRealtimeSubdivisionDebug; - } - - static void UpdateRealtimeSubdivisionDebug() - { - var debugDisplay = ProbeReferenceVolume.instance.debugDisplay; - if (!debugDisplay.realtimeSubdivision) - return; - - // Avoid killing the GPU when Unity is in background and runInBackground is disabled - if (!Application.runInBackground && !UnityEditorInternal.InternalEditorUtility.isApplicationActive) - return; - - // update is called 200 times per second so we bring down the update rate to 60hz to avoid overloading the GPU - if (Time.realtimeSinceStartupAsDouble - s_LastRefreshTime < 1.0f / 60.0f) - return; - s_LastRefreshTime = Time.realtimeSinceStartupAsDouble; - - if (Time.realtimeSinceStartupAsDouble - s_LastSubdivisionTime > debugDisplay.subdivisionDelayInSeconds) - { - var probeVolume = FindObjectOfType(); - if (probeVolume == null || !probeVolume.isActiveAndEnabled || ProbeReferenceVolume.instance.sceneData == null) - return; - - var profile = ProbeReferenceVolume.instance.sceneData.GetProfileForScene(probeVolume.gameObject.scene); - if (profile == null) - return; - - if (s_CurrentSubdivision == null) - { - // Start a new Subdivision - s_CurrentSubdivision = Subdivide(); - } - - // Step the subdivision with the amount of cell per frame in debug menu - int updatePerFrame = debugDisplay.subdivisionCellUpdatePerFrame; - // From simplification level 5 and higher, the cost of calculating one cell is very high, so we adjust that number. - if (profile.simplificationLevels > 4) - updatePerFrame = (int)Mathf.Max(1, updatePerFrame / Mathf.Pow(9, profile.simplificationLevels - 4)); - for (int i = 0; i < debugDisplay.subdivisionCellUpdatePerFrame; i++) - { - if (!s_CurrentSubdivision.MoveNext()) - { - s_LastSubdivisionTime = Time.realtimeSinceStartupAsDouble; - s_CurrentSubdivision = null; - break; - } - } - - IEnumerator Subdivide() - { - var ctx = ProbeGIBaking.PrepareProbeSubdivisionContext(); - - // Cull all the cells that are not visible (we don't need them for realtime debug) - ctx.cells.RemoveAll(c => - { - return probeVolume.ShouldCullCell(c.position); - }); - - Camera activeCamera = Camera.current ?? SceneView.lastActiveSceneView.camera; - - // Sort cells by camera distance to compute the closest cells first - if (activeCamera != null) - { - var cameraPos = activeCamera.transform.position; - ctx.cells.Sort((c1, c2) => - { - c1.volume.CalculateCenterAndSize(out var c1Center, out var _); - float c1Distance = Vector3.Distance(cameraPos, c1Center); - - c2.volume.CalculateCenterAndSize(out var c2Center, out var _); - float c2Distance = Vector3.Distance(cameraPos, c2Center); - - return c1Distance.CompareTo(c2Distance); - }); - } - - // Progressively update cells: - var cells = ctx.cells.ToList(); - - // Remove all the cells that was not updated to prevent ghosting - foreach (var cellVolume in ProbeReferenceVolume.instance.realtimeSubdivisionInfo.Keys.ToList()) - { - if (!cells.Any(c => c.volume.Equals(cellVolume))) - ProbeReferenceVolume.instance.realtimeSubdivisionInfo.Remove(cellVolume); - } - - // Subdivide visible cells - foreach (var cell in cells) - { - // Override the cell list to only compute one cell - ctx.cells.Clear(); - ctx.cells.Add(cell); - - var result = ProbeGIBaking.BakeBricks(ctx); - ProbeReferenceVolume.instance.realtimeSubdivisionInfo[cell.volume] = result.bricksPerCells[cell.position]; - - yield return null; - } - - yield break; - } - } - } - } - private SerializedProperty m_Dilate; private SerializedProperty m_MaxDilationSampleDistance; private SerializedProperty m_DilationValidityThreshold; @@ -141,7 +25,6 @@ IEnumerator Subdivide() private SerializedProperty m_Profile; - internal static readonly GUIContent s_DataAssetLabel = new GUIContent("Data asset", "The asset which serializes all probe related data in this volume."); internal static readonly GUIContent s_ProfileAssetLabel = new GUIContent("Profile", "The asset which determines the characteristics of the probe reference volume."); private static bool DilationGroupEnabled; @@ -235,8 +118,6 @@ public override void OnInspectorGUI() m_Profile.objectReferenceValue = asset; } - m_VolumeAsset.objectReferenceValue = EditorGUILayout.ObjectField(s_DataAssetLabel, m_VolumeAsset.objectReferenceValue, typeof(ProbeVolumeAsset), false); - DilationGroupEnabled = EditorGUILayout.BeginFoldoutHeaderGroup(DilationGroupEnabled, "Dilation"); if (DilationGroupEnabled) { diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeSubdivisionContext.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeSubdivisionContext.cs index e736ac353b9..a281f7dd9c8 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeSubdivisionContext.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeSubdivisionContext.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using Unity.Collections; using System; +using System.Collections; using System.Linq; using UnityEditor; @@ -12,6 +13,122 @@ namespace UnityEngine.Experimental.Rendering { class ProbeSubdivisionContext { + [InitializeOnLoad] + class RealtimeProbeSubdivisionDebug + { + static double s_LastSubdivisionTime; + static double s_LastRefreshTime; + static IEnumerator s_CurrentSubdivision; + + static RealtimeProbeSubdivisionDebug() + { + EditorApplication.update -= UpdateRealtimeSubdivisionDebug; + EditorApplication.update += UpdateRealtimeSubdivisionDebug; + } + + static void UpdateRealtimeSubdivisionDebug() + { + var debugDisplay = ProbeReferenceVolume.instance.debugDisplay; + if (!debugDisplay.realtimeSubdivision) + return; + + // Avoid killing the GPU when Unity is in background and runInBackground is disabled + if (!Application.runInBackground && !UnityEditorInternal.InternalEditorUtility.isApplicationActive) + return; + + // update is called 200 times per second so we bring down the update rate to 60hz to avoid overloading the GPU + if (Time.realtimeSinceStartupAsDouble - s_LastRefreshTime < 1.0f / 60.0f) + return; + s_LastRefreshTime = Time.realtimeSinceStartupAsDouble; + + if (Time.realtimeSinceStartupAsDouble - s_LastSubdivisionTime > debugDisplay.subdivisionDelayInSeconds) + { + var probeVolume = GameObject.FindObjectOfType(); + if (probeVolume == null || !probeVolume.isActiveAndEnabled || ProbeReferenceVolume.instance.sceneData == null) + return; + + var profile = ProbeReferenceVolume.instance.sceneData.GetProfileForScene(probeVolume.gameObject.scene); + if (profile == null) + return; + + if (s_CurrentSubdivision == null) + { + // Start a new Subdivision + s_CurrentSubdivision = Subdivide(); + } + + // Step the subdivision with the amount of cell per frame in debug menu + int updatePerFrame = debugDisplay.subdivisionCellUpdatePerFrame; + // From simplification level 5 and higher, the cost of calculating one cell is very high, so we adjust that number. + if (profile.simplificationLevels > 4) + updatePerFrame = (int)Mathf.Max(1, updatePerFrame / Mathf.Pow(9, profile.simplificationLevels - 4)); + for (int i = 0; i < debugDisplay.subdivisionCellUpdatePerFrame; i++) + { + if (!s_CurrentSubdivision.MoveNext()) + { + s_LastSubdivisionTime = Time.realtimeSinceStartupAsDouble; + s_CurrentSubdivision = null; + break; + } + } + + IEnumerator Subdivide() + { + var ctx = ProbeGIBaking.PrepareProbeSubdivisionContext(); + + // Cull all the cells that are not visible (we don't need them for realtime debug) + ctx.cells.RemoveAll(c => + { + return probeVolume.ShouldCullCell(c.position); + }); + + Camera activeCamera = Camera.current ?? SceneView.lastActiveSceneView.camera; + + // Sort cells by camera distance to compute the closest cells first + if (activeCamera != null) + { + var cameraPos = activeCamera.transform.position; + ctx.cells.Sort((c1, c2) => + { + c1.volume.CalculateCenterAndSize(out var c1Center, out var _); + float c1Distance = Vector3.Distance(cameraPos, c1Center); + + c2.volume.CalculateCenterAndSize(out var c2Center, out var _); + float c2Distance = Vector3.Distance(cameraPos, c2Center); + + return c1Distance.CompareTo(c2Distance); + }); + } + + // Progressively update cells: + var cells = ctx.cells.ToList(); + + // Remove all the cells that was not updated to prevent ghosting + foreach (var cellVolume in ProbeReferenceVolume.instance.realtimeSubdivisionInfo.Keys.ToList()) + { + if (!cells.Any(c => c.volume.Equals(cellVolume))) + ProbeReferenceVolume.instance.realtimeSubdivisionInfo.Remove(cellVolume); + } + + // Subdivide visible cells + foreach (var cell in cells) + { + // Override the cell list to only compute one cell + ctx.cells.Clear(); + ctx.cells.Add(cell); + + var result = ProbeGIBaking.BakeBricks(ctx); + ProbeReferenceVolume.instance.realtimeSubdivisionInfo[cell.volume] = result.bricksPerCells[cell.position]; + + yield return null; + } + + yield break; + } + } + } + } + public List<(ProbeVolume component, ProbeReferenceVolume.Volume volume)> probeVolumes = new List<(ProbeVolume, ProbeReferenceVolume.Volume)>(); public List<(Renderer component, ProbeReferenceVolume.Volume volume)> renderers = new List<(Renderer, ProbeReferenceVolume.Volume)>(); public List<(Vector3Int position, ProbeReferenceVolume.Volume volume)> cells = new List<(Vector3Int, ProbeReferenceVolume.Volume)>(); From 22d13cfcc0060b151d3063a7e12978c09b62153c Mon Sep 17 00:00:00 2001 From: FrancescoC-Unity Date: Thu, 2 Sep 2021 11:22:20 +0200 Subject: [PATCH 14/18] remove asset --- .../Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs index d11d093952b..c5873116ac1 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoringEditor.cs @@ -17,7 +17,6 @@ internal class ProbeReferenceVolumeAuthoringEditor : Editor private SerializedProperty m_DilationValidityThreshold; private SerializedProperty m_DilationIterations; private SerializedProperty m_DilationInvSquaredWeight; - private SerializedProperty m_VolumeAsset; private SerializedProperty m_EnableVirtualOffset; private SerializedProperty m_VirtualOffsetGeometrySearchMultiplier; @@ -42,7 +41,6 @@ private void OnEnable() m_DilationInvSquaredWeight = serializedObject.FindProperty("m_DilationInvSquaredWeight"); m_MaxDilationSampleDistance = serializedObject.FindProperty("m_MaxDilationSampleDistance"); m_DilationValidityThreshold = serializedObject.FindProperty("m_DilationValidityThreshold"); - m_VolumeAsset = serializedObject.FindProperty("volumeAsset"); m_EnableVirtualOffset = serializedObject.FindProperty("m_EnableVirtualOffset"); m_VirtualOffsetGeometrySearchMultiplier = serializedObject.FindProperty("m_VirtualOffsetGeometrySearchMultiplier"); m_VirtualOffsetBiasOutOfGeometry = serializedObject.FindProperty("m_VirtualOffsetBiasOutOfGeometry"); From 8f888731abff359867a44715bdc783b0d2d08548 Mon Sep 17 00:00:00 2001 From: FrancescoC-Unity Date: Thu, 2 Sep 2021 11:50:17 +0200 Subject: [PATCH 15/18] Small rename --- .../SerializedHDRenderPipelineGlobalSettings.cs | 4 ++-- .../RenderPipeline/HDRenderPipelineGlobalSettings.cs | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedHDRenderPipelineGlobalSettings.cs b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedHDRenderPipelineGlobalSettings.cs index 4999e4d1fed..92a3a394136 100644 --- a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedHDRenderPipelineGlobalSettings.cs +++ b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedHDRenderPipelineGlobalSettings.cs @@ -52,7 +52,7 @@ class SerializedHDRenderPipelineGlobalSettings public SerializedProperty DLSSProjectId; public SerializedProperty useDLSSCustomProjectId; - public SerializedProperty apvSceneBounds; + public SerializedProperty apvScenesData; internal ReorderableList uiBeforeTransparentCustomPostProcesses; internal ReorderableList uiBeforeTAACustomPostProcesses; @@ -145,7 +145,7 @@ public SerializedHDRenderPipelineGlobalSettings(SerializedObject serializedObjec DLSSProjectId = serializedObject.Find((HDRenderPipelineGlobalSettings s) => s.DLSSProjectId); useDLSSCustomProjectId = serializedObject.Find((HDRenderPipelineGlobalSettings s) => s.useDLSSCustomProjectId); - apvSceneBounds = serializedObject.Find((HDRenderPipelineGlobalSettings s) => s.apvScenesBounds); + apvScenesData = serializedObject.Find((HDRenderPipelineGlobalSettings s) => s.apvScenesData); } void InitializeCustomPostProcessesLists() diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipelineGlobalSettings.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipelineGlobalSettings.cs index 2834df985fb..03ccc7d8a31 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipelineGlobalSettings.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipelineGlobalSettings.cs @@ -821,16 +821,16 @@ internal bool AddDiffusionProfile(DiffusionProfileSettings profile) #region APV // This is temporarily here until we have a core place to put it shared between pipelines. [SerializeField] - internal ProbeVolumeSceneData apvScenesBounds; + internal ProbeVolumeSceneData apvScenesData; internal ProbeVolumeSceneData GetOrCreateAPVSceneData() { - if (apvScenesBounds == null) - apvScenesBounds = new ProbeVolumeSceneData((Object)this); + if (apvScenesData == null) + apvScenesData = new ProbeVolumeSceneData((Object)this); - apvScenesBounds.SetParentObject((Object)this); - return apvScenesBounds; + apvScenesData.SetParentObject((Object)this); + return apvScenesData; } #endregion From eb52367f6cdcdf71a640bf7b44f376e50f27cd0c Mon Sep 17 00:00:00 2001 From: FrancescoC-Unity Date: Thu, 2 Sep 2021 16:30:25 +0200 Subject: [PATCH 16/18] Move field inside EDITOR tags --- .../Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs index db5c09ce6ed..d03d6112b99 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolumeAuthoring.cs @@ -103,9 +103,10 @@ internal static ProbeReferenceVolumeProfile CreateReferenceVolumeProfile(Scene s [NonSerialized] bool m_SentDataToSceneData = false; // TODO: This is temp until we don't have a setting panel. -#endif + [SerializeField] float m_DilationValidityThreshold = 0.25f; +#endif public ProbeVolumeAsset volumeAsset = null; From 1c765d83b8486c8cbdcefa6203cd6733d9081eae Mon Sep 17 00:00:00 2001 From: FrancescoC-Unity Date: Thu, 2 Sep 2021 18:11:35 +0200 Subject: [PATCH 17/18] Fix issue when no profile is ever loaded (i.e. first time a project is loaded) --- .../Lighting/ProbeVolume/ProbeGIBaking.cs | 22 ++++++++++++------- .../ProbeVolume/ProbeVolumeSceneData.cs | 9 ++++++++ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs index 0cbec6c5019..b1391b4d6fb 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs @@ -161,12 +161,15 @@ public static void FindWorldBounds() { var scene = EditorSceneManager.OpenScene(scenePath, OpenSceneMode.Additive); openedScenes.Add(scene); - sceneData.UpdateSceneBounds(scene); - Bounds localBound = sceneData.sceneBounds[scene.path]; - if (hasFoundBounds) - globalBounds.Encapsulate(localBound); - else - globalBounds = localBound; + if (sceneData.hasProbeVolumes.TryGetValue(scenePath, out hasProbeVolumes)) + { + sceneData.UpdateSceneBounds(scene); + Bounds localBound = sceneData.sceneBounds[scene.path]; + if (hasFoundBounds) + globalBounds.Encapsulate(localBound); + else + globalBounds = localBound; + } } } } @@ -210,6 +213,9 @@ static void OnBakeStarted() { if (!ProbeReferenceVolume.instance.isInitialized) return; + var pvList = GameObject.FindObjectsOfType(); + if (pvList.Length == 0) return; // We have no probe volumes. + FindWorldBounds(); var perSceneDataList = GameObject.FindObjectsOfType(); if (perSceneDataList.Length == 0) return; @@ -306,8 +312,8 @@ internal static void PerformDilation() cell2Assets[cell.index].Add(assetPath); } - // We need to queue the asset loading to make sure all is fine when calling refresh. - sceneData.QueueAssetLoading(); + //// We need to queue the asset loading to make sure all is fine when calling refresh. + //sceneData.QueueAssetLoading(); } var dilationSettings = m_BakingSettings.dilationSettings; diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs index 1e7b606a8ea..eb762a1b297 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs @@ -225,6 +225,15 @@ private void InflateBound(ref Bounds bounds) internal void UpdateSceneBounds(Scene scene) { + // If we have not yet loaded any asset, we haven't initialized the probe reference volume with any info from the profile. + // As a result we need to prime with the profile info directly stored here. + { + var profile = GetProfileForScene(scene); + Debug.Assert(profile != null); + ProbeReferenceVolume.instance.SetTRS(Vector3.zero, Quaternion.identity, profile.minBrickSize); + ProbeReferenceVolume.instance.SetMaxSubdivision(profile.maxSubdivision); + } + var volumes = UnityEngine.GameObject.FindObjectsOfType(); bool boundFound = false; Bounds newBound = new Bounds(); From 793a30839977efad8481ef2fd2e93407d64f58a6 Mon Sep 17 00:00:00 2001 From: FrancescoC-Unity Date: Thu, 2 Sep 2021 18:33:54 +0200 Subject: [PATCH 18/18] guards --- .../Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs index eb762a1b297..05b483511d2 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeSceneData.cs @@ -350,7 +350,7 @@ internal void SetBakeSettingsForScene(Scene scene, ProbeDilationSettings dilatio internal ProbeReferenceVolumeProfile GetProfileForScene(Scene scene) { var sceneGUID = GetSceneGUID(scene); - if (sceneProfiles.ContainsKey(sceneGUID)) + if (sceneProfiles != null && sceneProfiles.ContainsKey(sceneGUID)) return sceneProfiles[sceneGUID]; return null; @@ -365,7 +365,7 @@ internal bool BakeSettingsDefinedForScene(Scene scene) internal ProbeVolumeBakingProcessSettings GetBakeSettingsForScene(Scene scene) { var sceneGUID = GetSceneGUID(scene); - if (sceneBakingSettings.ContainsKey(sceneGUID)) + if (sceneBakingSettings != null && sceneBakingSettings.ContainsKey(sceneGUID)) return sceneBakingSettings[sceneGUID]; return new ProbeVolumeBakingProcessSettings();