diff --git a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.VirtualOffset.cs b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.VirtualOffset.cs index 558fb0ad1e0..3b425855d55 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.VirtualOffset.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.VirtualOffset.cs @@ -12,12 +12,54 @@ partial class ProbeGIBaking { static List addedOccluders; - private static void AddOccluders() + static void ApplyVirtualOffsets(Vector3[] positions, out Vector3[] offsets) + { + var voSettings = m_BakingSettings.virtualOffsetSettings; + if (!voSettings.useVirtualOffset) + { + offsets = null; + return; + } + + var queriesHitBackBefore = Physics.queriesHitBackfaces; + try + { + Physics.queriesHitBackfaces = true; + + AddOccluders(); + ApplyVirtualOffsetsSingleThreaded(positions, out offsets, voSettings); + } + finally + { + Physics.queriesHitBackfaces = queriesHitBackBefore; + CleanupOccluders(); + } + } + + static void ApplyVirtualOffsetsSingleThreaded(Vector3[] positions, out Vector3[] offsets, VirtualOffsetSettings voSettings) + { + offsets = new Vector3[positions.Length]; + for (int i = 0; i < positions.Length; ++i) + { + int subdivLevel = 0; + m_BakingBatch.uniqueBrickSubdiv.TryGetValue(positions[i], out subdivLevel); + float brickSize = ProbeReferenceVolume.CellSize(subdivLevel); + float searchDistance = (brickSize * m_BakingProfile.minBrickSize) / ProbeBrickPool.kBrickCellCount; + + float scaleForSearchDist = voSettings.searchMultiplier; + Vector3 pushedPosition = PushPositionOutOfGeometry(positions[i], scaleForSearchDist * searchDistance, voSettings.outOfGeoOffset); + + offsets[i] = pushedPosition - positions[i]; + positions[i] = pushedPosition; + } + } + + static void AddOccluders() { addedOccluders = new List(); - for (int sceneIndex = 0; sceneIndex < UnityEngine.SceneManagement.SceneManager.sceneCount; ++sceneIndex) + for (int sceneIndex = 0; sceneIndex < SceneManagement.SceneManager.sceneCount; ++sceneIndex) { - UnityEngine.SceneManagement.Scene scene = UnityEngine.SceneManagement.SceneManager.GetSceneAt(sceneIndex); + SceneManagement.Scene scene = SceneManagement.SceneManager.GetSceneAt(sceneIndex); if (!scene.isLoaded) continue; @@ -27,10 +69,10 @@ private static void AddOccluders() MeshRenderer[] renderComponents = gameObject.GetComponentsInChildren(); foreach (MeshRenderer mr in renderComponents) { - if (!mr.gameObject.GetComponent() && (GameObjectUtility.GetStaticEditorFlags(mr.gameObject).HasFlag(StaticEditorFlags.ContributeGI))) + if ((GameObjectUtility.GetStaticEditorFlags(mr.gameObject) & StaticEditorFlags.ContributeGI) != 0 && !mr.gameObject.TryGetComponent(out _)) { var meshCollider = mr.gameObject.AddComponent(); - meshCollider.hideFlags |= (HideFlags.DontSaveInEditor | HideFlags.DontSaveInBuild); + meshCollider.hideFlags |= HideFlags.DontSaveInEditor | HideFlags.DontSaveInBuild; addedOccluders.Add(mr); } } @@ -38,9 +80,15 @@ private static void AddOccluders() } var autoSimState = Physics.autoSimulation; - Physics.autoSimulation = false; - Physics.Simulate(0.1f); - Physics.autoSimulation = autoSimState; + try + { + Physics.autoSimulation = false; + Physics.Simulate(0.1f); + } + finally + { + Physics.autoSimulation = autoSimState; + } } private static void CleanupOccluders() 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 47ce8e5badf..84f998eb345 100644 --- a/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs +++ b/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs @@ -38,6 +38,7 @@ class BakingBatch public Dictionary> cellIndex2SceneReferences = new Dictionary>(); public List cells = new List(); public Dictionary uniquePositions = new Dictionary(); + public Vector3[] virtualOffsets; // Allow to get a mapping to subdiv level with the unique positions. It stores the minimum subdiv level found for a given position. // Can be probably done cleaner. public Dictionary uniqueBrickSubdiv = new Dictionary(); @@ -213,9 +214,6 @@ static void OnBakeStarted() SetBakingContext(perSceneDataList); - if (m_BakingSettings.virtualOffsetSettings.useVirtualOffset) - AddOccluders(); - RunPlacement(); } @@ -473,6 +471,8 @@ static void OnAdditionalProbesBakeCompleted() onAdditionalProbesBakeCompletedCalled = true; var dilationSettings = m_BakingSettings.dilationSettings; + var virtualOffsets = m_BakingBatch.virtualOffsets; + // Fetch results of all cells for (int c = 0; c < numCells; ++c) { @@ -488,12 +488,16 @@ static void OnAdditionalProbesBakeCompleted() cell.sh = new SphericalHarmonicsL2[numProbes]; cell.validity = new float[numProbes]; - cell.offsetVectors = new Vector3[0]; // pending PR #6169 + cell.offsetVectors = new Vector3[virtualOffsets != null ? numProbes : 0]; cell.minSubdiv = probeRefVolume.GetMaxSubdivision(); for (int i = 0; i < numProbes; ++i) { int j = cell.probeIndices[i]; + + if (virtualOffsets != null) + cell.offsetVectors[i] = virtualOffsets[j]; + SphericalHarmonicsL2 shv = sh[j]; int brickIdx = i / 64; @@ -1082,24 +1086,9 @@ public static void ApplySubdivisionResults(ProbeSubdivisionResult results, Matri m_BakingBatch.cellIndex2SceneReferences[cell.index] = results.scenesPerCells[cellPos].ToList(); } - - // Move positions before sending them + // Virtually offset positions before passing them to lightmapper var positions = m_BakingBatch.uniquePositions.Keys.ToArray(); - VirtualOffsetSettings voSettings = m_BakingSettings.virtualOffsetSettings; - if (voSettings.useVirtualOffset) - { - for (int i = 0; i < positions.Length; ++i) - { - int subdivLevel = 0; - m_BakingBatch.uniqueBrickSubdiv.TryGetValue(positions[i], out subdivLevel); - float brickSize = ProbeReferenceVolume.CellSize(subdivLevel); - float searchDistance = (brickSize * m_BakingProfile.minBrickSize) / ProbeBrickPool.kBrickCellCount; - - float scaleForSearchDist = voSettings.searchMultiplier; - positions[i] = PushPositionOutOfGeometry(positions[i], scaleForSearchDist * searchDistance, voSettings.outOfGeoOffset); - } - CleanupOccluders(); - } + ApplyVirtualOffsets(positions, out m_BakingBatch.virtualOffsets); UnityEditor.Experimental.Lightmapping.SetAdditionalBakedProbes(m_BakingBatch.index, positions); } 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 cd2ad260400..d3bcf6e03b4 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 @@ -14,6 +14,14 @@ public enum DebugProbeShadingMode /// SH, /// + /// Based on Spherical Harmonics first band only (ambient) + /// + SHL0, + /// + /// Based on Spherical Harmonics band zero and one only + /// + SHL0L1, + /// /// Based on validity /// Validity, @@ -41,6 +49,8 @@ class ProbeVolumeDebug public float probeCullingDistance = 200.0f; public int maxSubdivToVisualize = ProbeBrickIndex.kMaxSubdivisionLevels; public float exposureCompensation; + public bool drawVirtualOffsetPush; + public float offsetSize = 0.025f; public bool freezeStreaming; } @@ -49,12 +59,13 @@ public partial class ProbeReferenceVolume class CellInstancedDebugProbes { public List probeBuffers; + public List offsetBuffers; public List props; public Hash128 cellHash; public Vector3 cellPosition; } - const int kProbesPerBatch = 1023; + const int kProbesPerBatch = 511; public static readonly string k_DebugPanelName = "Probe Volume"; @@ -66,10 +77,12 @@ class CellInstancedDebugProbes DebugUI.Widget[] m_DebugItems; Mesh m_DebugMesh; Material m_DebugMaterial; + Mesh m_DebugOffsetMesh; + Material m_DebugOffsetMaterial; List m_CellDebugData = new List(); Plane[] m_DebugFrustumPlanes = new Plane[6]; - internal float dilationValidtyThreshold = 0.25f; // We ned to store this here to access it + internal ProbeVolumeBakingProcessSettings bakingProcessSettings; /* DEFAULTS would be better but is implemented in PR#6174 = ProbeVolumeBakingProcessSettings.Defaults; */ // Field used for the realtime subdivision preview internal Dictionary> realtimeSubdivisionInfo = new Dictionary>(); @@ -82,10 +95,7 @@ public void RenderDebug(Camera camera) { if (camera.cameraType != CameraType.Reflection && camera.cameraType != CameraType.Preview) { - if (debugDisplay.drawProbes && enabledBySRP && isInitialized) - { - DrawProbeDebug(camera); - } + DrawProbeDebug(camera); } } @@ -97,6 +107,10 @@ void InitializeDebug(in ProbeVolumeSystemParameters parameters) m_DebugMaterial = CoreUtils.CreateEngineMaterial(parameters.probeDebugShader); m_DebugMaterial.enableInstancing = true; + m_DebugOffsetMesh = parameters.offsetDebugMesh; + m_DebugOffsetMaterial = CoreUtils.CreateEngineMaterial(parameters.offsetDebugShader); + m_DebugOffsetMaterial.enableInstancing = true; + // Hard-coded colors for now. Debug.Assert(ProbeBrickIndex.kMaxSubdivisionLevels == 7); // Update list if this changes. subdivisionDebugColors[0] = new Color(1.0f, 0.0f, 0.0f); @@ -106,7 +120,7 @@ void InitializeDebug(in ProbeVolumeSystemParameters parameters) subdivisionDebugColors[4] = new Color(1.0f, 0.0f, 1.0f); subdivisionDebugColors[5] = new Color(0.0f, 1.0f, 1.0f); subdivisionDebugColors[6] = new Color(0.5f, 0.5f, 0.5f); - } + } RegisterDebug(parameters); @@ -119,6 +133,7 @@ void CleanupDebug() { UnregisterDebug(true); CoreUtils.Destroy(m_DebugMaterial); + CoreUtils.Destroy(m_DebugOffsetMaterial); #if UNITY_EDITOR UnityEditor.Lightmapping.lightingDataCleared -= OnClearLightingdata; @@ -138,6 +153,9 @@ void RefreshDebug(DebugUI.Field field, T value) RegisterDebug(parameters); } + const float kProbeSizeMin = 0.05f, kProbeSizeMax = 10.0f; + const float kOffsetSizeMin = 0.001f, kOffsetSizeMax = 0.1f; + var widgetList = new List(); var subdivContainer = new DebugUI.Container() { displayName = "Subdivision Visualization" }; @@ -153,16 +171,14 @@ void RefreshDebug(DebugUI.Field field, T value) } #endif - if (debugDisplay.drawCells || debugDisplay.drawBricks) - { - subdivContainer.children.Add(new DebugUI.FloatField { displayName = "Culling Distance", getter = () => debugDisplay.subdivisionViewCullingDistance, setter = value => debugDisplay.subdivisionViewCullingDistance = value, min = () => 0.0f }); - } + subdivContainer.children.Add(new DebugUI.FloatField { displayName = "Culling Distance", getter = () => debugDisplay.subdivisionViewCullingDistance, setter = value => debugDisplay.subdivisionViewCullingDistance = value, min = () => 0.0f }); var probeContainer = new DebugUI.Container() { displayName = "Probe Visualization" }; probeContainer.children.Add(new DebugUI.BoolField { displayName = "Display Probes", getter = () => debugDisplay.drawProbes, setter = value => debugDisplay.drawProbes = value, onValueChanged = RefreshDebug }); if (debugDisplay.drawProbes) { - probeContainer.children.Add(new DebugUI.EnumField + var probeContainerChildren = new DebugUI.Container(); + probeContainerChildren.children.Add(new DebugUI.EnumField { displayName = "Probe Shading Mode", getter = () => (int)debugDisplay.probeShading, @@ -172,13 +188,11 @@ void RefreshDebug(DebugUI.Field field, T value) setIndex = value => debugDisplay.probeShading = (DebugProbeShadingMode)value, onValueChanged = RefreshDebug }); - probeContainer.children.Add(new DebugUI.FloatField { displayName = "Probe Size", getter = () => debugDisplay.probeSize, setter = value => debugDisplay.probeSize = value, min = () => 0.1f, max = () => 10.0f }); - if (debugDisplay.probeShading == DebugProbeShadingMode.SH) - probeContainer.children.Add(new DebugUI.FloatField { displayName = "Probe Exposure Compensation", getter = () => debugDisplay.exposureCompensation, setter = value => debugDisplay.exposureCompensation = value }); - - probeContainer.children.Add(new DebugUI.FloatField { displayName = "Culling Distance", getter = () => debugDisplay.probeCullingDistance, setter = value => debugDisplay.probeCullingDistance = value, min = () => 0.0f }); + probeContainerChildren.children.Add(new DebugUI.FloatField { displayName = "Probe Size", getter = () => debugDisplay.probeSize, setter = value => debugDisplay.probeSize = value, min = () => kProbeSizeMin, max = () => kProbeSizeMax }); + if (debugDisplay.probeShading == DebugProbeShadingMode.SH || debugDisplay.probeShading == DebugProbeShadingMode.SHL0 || debugDisplay.probeShading == DebugProbeShadingMode.SHL0L1) + probeContainerChildren.children.Add(new DebugUI.FloatField { displayName = "Probe Exposure Compensation", getter = () => debugDisplay.exposureCompensation, setter = value => debugDisplay.exposureCompensation = value }); - probeContainer.children.Add(new DebugUI.IntField + probeContainerChildren.children.Add(new DebugUI.IntField { displayName = "Max subdivision displayed", getter = () => debugDisplay.maxSubdivToVisualize, @@ -186,8 +200,35 @@ void RefreshDebug(DebugUI.Field field, T value) min = () => 0, max = () => ProbeReferenceVolume.instance.GetMaxSubdivision(), }); + + probeContainer.children.Add(probeContainerChildren); } + probeContainer.children.Add(new DebugUI.BoolField + { + displayName = "Virtual Offset", + getter = () => debugDisplay.drawVirtualOffsetPush, + setter = value => + { + debugDisplay.drawVirtualOffsetPush = value; + + if (debugDisplay.drawVirtualOffsetPush && debugDisplay.drawProbes) + { + // If probes are being drawn when enabling offset, automatically scale them down to a reasonable size so the arrows aren't obscured by the probes. + var searchDistance = CellSize(0) * MinBrickSize() / ProbeBrickPool.kBrickCellCount * bakingProcessSettings.virtualOffsetSettings.searchMultiplier + bakingProcessSettings.virtualOffsetSettings.outOfGeoOffset; + debugDisplay.probeSize = Mathf.Min(debugDisplay.probeSize, Mathf.Clamp(searchDistance, kProbeSizeMin, kProbeSizeMax)); + } + }, + onValueChanged = RefreshDebug + }); + if (debugDisplay.drawVirtualOffsetPush) + { + var voOffset = new DebugUI.FloatField { displayName = "Offset Size", getter = () => debugDisplay.offsetSize, setter = value => debugDisplay.offsetSize = value, min = () => kOffsetSizeMin, max = () => kOffsetSizeMax }; + probeContainer.children.Add(new DebugUI.Container { children = { voOffset } }); + } + + probeContainer.children.Add(new DebugUI.FloatField { displayName = "Culling Distance", getter = () => debugDisplay.probeCullingDistance, setter = value => debugDisplay.probeCullingDistance = value, min = () => 0.0f }); + var streamingContainer = new DebugUI.Container() { displayName = "Streaming" }; streamingContainer.children.Add(new DebugUI.BoolField { displayName = "Freeze Streaming", getter = () => debugDisplay.freezeStreaming, setter = value => debugDisplay.freezeStreaming = value }); @@ -234,44 +275,56 @@ bool ShouldCullCell(Vector3 cellPosition, Transform cameraTransform, Plane[] fru return true; var volumeAABB = new Bounds(cellCenterWS, cellSize * Vector3.one); - return !GeometryUtility.TestPlanesAABB(frustumPlanes, volumeAABB); } void DrawProbeDebug(Camera camera) { - if (debugDisplay.drawProbes) - { - // TODO: Update data on ref vol changes - if (m_CellDebugData.Count == 0) - CreateInstancedProbes(); + if (!enabledBySRP || !isInitialized) + return; - GeometryUtility.CalculateFrustumPlanes(camera, m_DebugFrustumPlanes); + if (!debugDisplay.drawProbes && !debugDisplay.drawVirtualOffsetPush) + return; - m_DebugMaterial.shaderKeywords = null; - if (m_SHBands == ProbeVolumeSHBands.SphericalHarmonicsL1) - m_DebugMaterial.EnableKeyword("PROBE_VOLUMES_L1"); - else if (m_SHBands == ProbeVolumeSHBands.SphericalHarmonicsL2) - m_DebugMaterial.EnableKeyword("PROBE_VOLUMES_L2"); + // TODO: Update data on ref vol changes + if (m_CellDebugData.Count == 0) + CreateInstancedProbes(); - foreach (var debug in m_CellDebugData) - { - if (ShouldCullCell(debug.cellPosition, camera.transform, m_DebugFrustumPlanes)) - continue; + GeometryUtility.CalculateFrustumPlanes(camera, m_DebugFrustumPlanes); + + m_DebugMaterial.shaderKeywords = null; + if (m_SHBands == ProbeVolumeSHBands.SphericalHarmonicsL1) + m_DebugMaterial.EnableKeyword("PROBE_VOLUMES_L1"); + else if (m_SHBands == ProbeVolumeSHBands.SphericalHarmonicsL2) + m_DebugMaterial.EnableKeyword("PROBE_VOLUMES_L2"); + + foreach (var debug in m_CellDebugData) + { + if (ShouldCullCell(debug.cellPosition, camera.transform, m_DebugFrustumPlanes)) + continue; - for (int i = 0; i < debug.probeBuffers.Count; ++i) + for (int i = 0; i < debug.probeBuffers.Count; ++i) + { + var props = debug.props[i]; + props.SetInt("_ShadingMode", (int)debugDisplay.probeShading); + props.SetFloat("_ExposureCompensation", debugDisplay.exposureCompensation); + props.SetFloat("_ProbeSize", debugDisplay.probeSize); + props.SetFloat("_CullDistance", debugDisplay.probeCullingDistance); + props.SetInt("_MaxAllowedSubdiv", debugDisplay.maxSubdivToVisualize); + props.SetFloat("_ValidityThreshold", bakingProcessSettings.dilationSettings.dilationValidityThreshold); + props.SetFloat("_OffsetSize", debugDisplay.offsetSize); + + if (debugDisplay.drawProbes) { var probeBuffer = debug.probeBuffers[i]; - var props = debug.props[i]; - props.SetInt("_ShadingMode", (int)debugDisplay.probeShading); - props.SetFloat("_ExposureCompensation", debugDisplay.exposureCompensation); - props.SetFloat("_ProbeSize", debugDisplay.probeSize); - props.SetFloat("_CullDistance", debugDisplay.probeCullingDistance); - props.SetInt("_MaxAllowedSubdiv", debugDisplay.maxSubdivToVisualize); - props.SetFloat("_ValidityThreshold", dilationValidtyThreshold); - Graphics.DrawMeshInstanced(m_DebugMesh, 0, m_DebugMaterial, probeBuffer, probeBuffer.Length, props, ShadowCastingMode.Off, false, 0, camera, LightProbeUsage.Off, null); } + + if (debugDisplay.drawVirtualOffsetPush) + { + var offsetBuffer = debug.offsetBuffers[i]; + Graphics.DrawMeshInstanced(m_DebugOffsetMesh, 0, m_DebugOffsetMaterial, offsetBuffer, offsetBuffer.Length, props, ShadowCastingMode.Off, false, 0, camera, LightProbeUsage.Off, null); + } } } } @@ -293,17 +346,21 @@ void CreateInstancedProbes() continue; List probeBuffers = new List(); + List offsetBuffers = new List(); List props = new List(); var chunks = cellInfo.chunkList; Vector4[] texels = new Vector4[kProbesPerBatch]; float[] validity = new float[kProbesPerBatch]; float[] relativeSize = new float[kProbesPerBatch]; + Vector4[] offsets = cell.offsetVectors.Length > 0 ? new Vector4[kProbesPerBatch] : null; List probeBuffer = new List(); + List offsetBuffer = new List(); var debugData = new CellInstancedDebugProbes(); debugData.probeBuffers = probeBuffers; + debugData.offsetBuffers = offsetBuffers; debugData.props = props; debugData.cellPosition = cell.position; @@ -326,6 +383,25 @@ void CreateInstancedProbes() validity[idxInBatch] = cell.validity[i]; texels[idxInBatch] = new Vector4(texelLoc.x, texelLoc.y, texelLoc.z, brickSize); relativeSize[idxInBatch] = (float)brickSize / (float)maxSubdiv; + if (offsets != null) + { + const float kOffsetThresholdSqr = 1e-6f; + + var offset = cell.offsetVectors[i]; + offsets[idxInBatch] = offset; + + if (offset.sqrMagnitude < kOffsetThresholdSqr) + { + offsetBuffer.Add(Matrix4x4.identity); + } + else + { + var position = cell.probePositions[i] + offset; + var orientation = Quaternion.LookRotation(-offset); + var scale = new Vector3(0.5f, 0.5f, offset.magnitude); + offsetBuffer.Add(Matrix4x4.TRS(position, orientation, scale)); + } + } idxInBatch++; if (probeBuffer.Count >= kProbesPerBatch || i == cell.probePositions.Length - 1) @@ -337,10 +413,17 @@ void CreateInstancedProbes() prop.SetFloatArray("_RelativeSize", relativeSize); prop.SetVectorArray("_IndexInAtlas", texels); + if (offsets != null) + prop.SetVectorArray("_Offset", offsets); + props.Add(prop); probeBuffers.Add(probeBuffer.ToArray()); probeBuffer = new List(); + probeBuffer.Clear(); + + offsetBuffers.Add(offsetBuffer.ToArray()); + offsetBuffer.Clear(); } } diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.Debug.cs.hlsl b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.Debug.cs.hlsl index 9fcdecba00f..f222ba4eda8 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.Debug.cs.hlsl +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.Debug.cs.hlsl @@ -8,9 +8,11 @@ // UnityEngine.Experimental.Rendering.DebugProbeShadingMode: static fields // #define DEBUGPROBESHADINGMODE_SH (0) -#define DEBUGPROBESHADINGMODE_VALIDITY (1) -#define DEBUGPROBESHADINGMODE_VALIDITY_OVER_DILATION_THRESHOLD (2) -#define DEBUGPROBESHADINGMODE_SIZE (3) +#define DEBUGPROBESHADINGMODE_SHL0 (1) +#define DEBUGPROBESHADINGMODE_SHL0L1 (2) +#define DEBUGPROBESHADINGMODE_VALIDITY (3) +#define DEBUGPROBESHADINGMODE_VALIDITY_OVER_DILATION_THRESHOLD (4) +#define DEBUGPROBESHADINGMODE_SIZE (5) #endif 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 d7c51cd1dd6..2c172a6f0a9 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs @@ -281,6 +281,14 @@ public struct ProbeVolumeSystemParameters /// public Shader probeDebugShader; /// + /// The debug mesh used to visualize probes virtual offset in the debug view. + /// + public Mesh offsetDebugMesh; + /// + /// The shader used to visualize probes virtual offset in the debug view. + /// + public Shader offsetDebugShader; + /// /// The /// public ProbeVolumeSceneData sceneData; @@ -359,6 +367,7 @@ internal class Cell { public Vector3Int position; public int index; + public SphericalHarmonicsL2[] sh; public int minSubdiv; public int indexChunkCount; public int shChunkCount; 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 ba38ba12dca..691d6b4be27 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs @@ -101,7 +101,7 @@ internal void QueueAssetLoading() #if UNITY_EDITOR if (refVol.sceneData != null) { - refVol.dilationValidtyThreshold = refVol.sceneData.GetBakeSettingsForScene(gameObject.scene).dilationSettings.dilationValidityThreshold; + refVol.bakingProcessSettings = refVol.sceneData.GetBakeSettingsForScene(gameObject.scene); } #endif diff --git a/com.unity.render-pipelines.core/Runtime/Utilities/ResourceReloader.cs b/com.unity.render-pipelines.core/Runtime/Utilities/ResourceReloader.cs index f51f5a23511..fba907fb29c 100644 --- a/com.unity.render-pipelines.core/Runtime/Utilities/ResourceReloader.cs +++ b/com.unity.render-pipelines.core/Runtime/Utilities/ResourceReloader.cs @@ -191,9 +191,20 @@ static UnityEngine.Object Load(string path, Type type, bool builtin) // Else the path is good. Attempt loading resource if AssetDatabase available. UnityEngine.Object result; if (builtin && type == typeof(Shader)) + { result = Shader.Find(path); + } else + { result = AssetDatabase.LoadAssetAtPath(path, type); + + if (IsNull(result)) + result = Resources.GetBuiltinResource(type, path); + + if (IsNull(result)) + result = AssetDatabase.GetBuiltinExtraResource(type, path); + } + if (IsNull(result)) { var e = new Exception($"Cannot load. Path {path} is correct but AssetDatabase cannot load now."); diff --git a/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeDebug.hlsl b/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeDebug.hlsl new file mode 100644 index 00000000000..e6c99f9627a --- /dev/null +++ b/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeDebug.hlsl @@ -0,0 +1,118 @@ +#ifndef PROBEVOLUMEDEBUG_HLSL +#define PROBEVOLUMEDEBUG_HLSL + +#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" +#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/EntityLighting.hlsl" +#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonLighting.hlsl" +#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" +#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/BuiltinGIUtilities.hlsl" +#include "Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/DecodeSH.hlsl" +#include "Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolume.hlsl" +#include "Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.Debug.cs.hlsl" + +uniform int _ShadingMode; +uniform float _ExposureCompensation; +uniform float _ProbeSize; +uniform float4 _Color; +uniform int _SubdivLevel; +uniform float _CullDistance; +uniform int _MaxAllowedSubdiv; +uniform float _ValidityThreshold; +uniform float _OffsetSize; + +UNITY_INSTANCING_BUFFER_START(Props) + UNITY_DEFINE_INSTANCED_PROP(float, _Validity) + UNITY_DEFINE_INSTANCED_PROP(float4, _IndexInAtlas) + UNITY_DEFINE_INSTANCED_PROP(float4, _Offset) + UNITY_DEFINE_INSTANCED_PROP(float, _RelativeSize) +UNITY_INSTANCING_BUFFER_END(Props) + +struct appdata +{ + float4 vertex : POSITION; + float3 normal : NORMAL; + UNITY_VERTEX_INPUT_INSTANCE_ID +}; + +struct v2f +{ + float4 vertex : SV_POSITION; + float3 normal : TEXCOORD1; + UNITY_VERTEX_INPUT_INSTANCE_ID +}; + +void DoCull(inout v2f o) +{ + o.vertex = float4(0, 0, 0, 0); + o.normal = float3(0, 0, 0); +} + +// Finer culling, degenerate the vertices of the debug element if it lies over the max distance. +// Coarser culling has already happened on CPU. +bool ShouldCull(inout v2f o) +{ + float4 position = float4(UNITY_MATRIX_M._m03_m13_m23, 1); + int brickSize = UNITY_ACCESS_INSTANCED_PROP(Props, _IndexInAtlas).w; + + if(distance(position.xyz, GetCurrentViewPosition()) > _CullDistance || brickSize > _MaxAllowedSubdiv) + { + DoCull(o); + return true; + } + + return false; +} + +float3 EvalL1(float3 L0, float3 L1_R, float3 L1_G, float3 L1_B, float3 N) +{ + float3 outLighting = 0; + L1_R = DecodeSH(L0.r, L1_R); + L1_G = DecodeSH(L0.g, L1_G); + L1_B = DecodeSH(L0.b, L1_B); + outLighting += SHEvalLinearL1(N, L1_R, L1_G, L1_B); + + return outLighting; +} + +float3 EvalL2(inout float3 L0, float4 L2_R, float4 L2_G, float4 L2_B, float4 L2_C, float3 N) +{ + DecodeSH_L2(L0, L2_R, L2_G, L2_B, L2_C); + + return SHEvalLinearL2(N, L2_R, L2_G, L2_B, L2_C); +} + +float3 CalculateDiffuseLighting(v2f i) +{ + APVResources apvRes = FillAPVResources(); + int3 texLoc = UNITY_ACCESS_INSTANCED_PROP(Props, _IndexInAtlas).xyz; + float3 normal = normalize(i.normal); + + float4 L0_L1Rx = apvRes.L0_L1Rx[texLoc].rgba; + float3 L0 = L0_L1Rx.xyz; + + if (_ShadingMode == DEBUGPROBESHADINGMODE_SHL0) + return L0; + + float L1Rx = L0_L1Rx.w; + float4 L1G_L1Ry = apvRes.L1G_L1Ry[texLoc].rgba; + float4 L1B_L1Rz = apvRes.L1B_L1Rz[texLoc].rgba; + + float3 bakeDiffuseLighting = EvalL1(L0, float3(L1Rx, L1G_L1Ry.w, L1B_L1Rz.w), L1G_L1Ry.xyz, L1B_L1Rz.xyz, normal); + bakeDiffuseLighting += L0; + + if (_ShadingMode == DEBUGPROBESHADINGMODE_SHL0L1) + return bakeDiffuseLighting; + +#ifdef PROBE_VOLUMES_L2 + float4 L2_R = apvRes.L2_0[texLoc].rgba; + float4 L2_G = apvRes.L2_1[texLoc].rgba; + float4 L2_B = apvRes.L2_2[texLoc].rgba; + float4 L2_C = apvRes.L2_3[texLoc].rgba; + + bakeDiffuseLighting += EvalL2(L0, L2_R, L2_G, L2_B, L2_C, normal); +#endif + + return bakeDiffuseLighting; +} + +#endif //PROBEVOLUMEDEBUG_HLSL diff --git a/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeDebug.hlsl.meta b/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeDebug.hlsl.meta new file mode 100644 index 00000000000..dd811c03f8a --- /dev/null +++ b/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeDebug.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ccecfcbd852d8114fa00c7d48df8fb3c +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeDebug.shader b/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeDebug.shader index 0ede1ad47c9..2a3ad226f19 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeDebug.shader +++ b/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeDebug.shader @@ -1,9 +1,5 @@ Shader "Hidden/HDRP/ProbeVolumeDebug" { - Properties - { - } - SubShader { Tags{ "RenderPipeline" = "HDRenderPipeline" "RenderType" = "Opaque" } @@ -15,43 +11,7 @@ Shader "Hidden/HDRP/ProbeVolumeDebug" #pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch #pragma multi_compile_fragment PROBE_VOLUMES_OFF PROBE_VOLUMES_L1 PROBE_VOLUMES_L2 - #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" - #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/EntityLighting.hlsl" - #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonLighting.hlsl" - #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" - #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/BuiltinGIUtilities.hlsl" - #include "Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/DecodeSH.hlsl" - #include "Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolume.hlsl" - #include "Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.Debug.cs.hlsl" - - uniform int _ShadingMode; - uniform float _ExposureCompensation; - uniform float _ProbeSize; - uniform float4 _Color; - uniform int _SubdivLevel; - uniform float _CullDistance; - uniform int _MaxAllowedSubdiv; - uniform float _ValidityThreshold; - - struct appdata - { - float4 vertex : POSITION; - float3 normal : NORMAL; - UNITY_VERTEX_INPUT_INSTANCE_ID - }; - - struct v2f - { - float4 vertex : SV_POSITION; - float3 normal : TEXCOORD1; - UNITY_VERTEX_INPUT_INSTANCE_ID - }; - - UNITY_INSTANCING_BUFFER_START(Props) - UNITY_DEFINE_INSTANCED_PROP(float4, _IndexInAtlas) - UNITY_DEFINE_INSTANCED_PROP(float, _Validity) - UNITY_DEFINE_INSTANCED_PROP(float, _RelativeSize) - UNITY_INSTANCING_BUFFER_END(Props) + #include "ProbeVolumeDebug.hlsl" v2f vert(appdata v) { @@ -60,78 +20,23 @@ Shader "Hidden/HDRP/ProbeVolumeDebug" UNITY_SETUP_INSTANCE_ID(v); UNITY_TRANSFER_INSTANCE_ID(v, o); - - // Finer culling, degenerate the vertices of the sphere if it lies over the max distance. - // Coarser culling has already happened on CPU. - float4 position = float4(UNITY_MATRIX_M._m03_m13_m23, 1); - int brickSize = UNITY_ACCESS_INSTANCED_PROP(Props, _IndexInAtlas).w; - - if (distance(position.xyz, GetCurrentViewPosition()) > _CullDistance || - brickSize > _MaxAllowedSubdiv) - { - o.vertex = 0; - o.normal = 0; - } - else + if(!ShouldCull(o)) { float4 wsPos = mul(UNITY_MATRIX_M, float4(v.vertex.xyz * _ProbeSize, 1.0)); o.vertex = mul(UNITY_MATRIX_VP, wsPos); - o.normal = normalize(mul(v.normal, (float3x3)UNITY_MATRIX_M)); } return o; } - float3 EvalL1(float3 L0, float3 L1_R, float3 L1_G, float3 L1_B, float3 N) - { - float3 outLighting = 0; - L1_R = DecodeSH(L0.r, L1_R); - L1_G = DecodeSH(L0.g, L1_G); - L1_B = DecodeSH(L0.b, L1_B); - outLighting += SHEvalLinearL1(N, L1_R, L1_G, L1_B); - - return outLighting; - } - - float3 EvalL2(inout float3 L0, float4 L2_R, float4 L2_G, float4 L2_B, float4 L2_C, float3 N) - { - DecodeSH_L2(L0, L2_R, L2_G, L2_B, L2_C); - - return SHEvalLinearL2(N, L2_R, L2_G, L2_B, L2_C); - } - float4 frag(v2f i) : SV_Target { UNITY_SETUP_INSTANCE_ID(i); - if (_ShadingMode == DEBUGPROBESHADINGMODE_SH) + if (_ShadingMode >= DEBUGPROBESHADINGMODE_SH && _ShadingMode <= DEBUGPROBESHADINGMODE_SHL0L1) { - APVResources apvRes = FillAPVResources(); - int3 texLoc = UNITY_ACCESS_INSTANCED_PROP(Props, _IndexInAtlas).xyz; - float3 normal = normalize(i.normal); - - float3 bakeDiffuseLighting = float3(0.0, 0.0, 0.0); - float3 backBakeDiffuseLighting = float3(0.0, 0.0, 0.0); - - float4 L0_L1Rx = apvRes.L0_L1Rx[texLoc].rgba; - float3 L0 = L0_L1Rx.xyz; - float L1Rx = L0_L1Rx.w; - float4 L1G_L1Ry = apvRes.L1G_L1Ry[texLoc].rgba; - float4 L1B_L1Rz = apvRes.L1B_L1Rz[texLoc].rgba; - - bakeDiffuseLighting = EvalL1(L0, float3(L1Rx, L1G_L1Ry.w, L1B_L1Rz.w), L1G_L1Ry.xyz, L1B_L1Rz.xyz, normal); - - #ifdef PROBE_VOLUMES_L2 - float4 L2_R = apvRes.L2_0[texLoc].rgba; - float4 L2_G = apvRes.L2_1[texLoc].rgba; - float4 L2_B = apvRes.L2_2[texLoc].rgba; - float4 L2_C = apvRes.L2_3[texLoc].rgba; - - bakeDiffuseLighting += EvalL2(L0, L2_R, L2_G, L2_B, L2_C, normal); - #endif - bakeDiffuseLighting += L0; - return float4(bakeDiffuseLighting * exp2(_ExposureCompensation) * GetCurrentExposureMultiplier(), 1); + return float4(CalculateDiffuseLighting(i) * exp2(_ExposureCompensation) * GetCurrentExposureMultiplier(), 1); } else if (_ShadingMode == DEBUGPROBESHADINGMODE_VALIDITY) { diff --git a/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeOffsetDebug.shader b/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeOffsetDebug.shader new file mode 100644 index 00000000000..1d0e2b9723d --- /dev/null +++ b/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeOffsetDebug.shader @@ -0,0 +1,74 @@ +Shader "Hidden/HDRP/ProbeVolumeOffsetDebug" +{ + SubShader + { + Tags{ "RenderPipeline" = "HDRenderPipeline" "RenderType" = "Opaque" } + LOD 100 + + HLSLINCLUDE + #pragma editor_sync_compilation + #pragma target 4.5 + #pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch + #pragma multi_compile_fragment PROBE_VOLUMES_OFF PROBE_VOLUMES_L1 PROBE_VOLUMES_L2 + + #include "ProbeVolumeDebug.hlsl" + + v2f vert(appdata v) + { + v2f o; + + UNITY_SETUP_INSTANCE_ID(v); + UNITY_TRANSFER_INSTANCE_ID(v, o); + + float3 offset = UNITY_ACCESS_INSTANCED_PROP(Props, _Offset).xyz; + float offsetLenSqr = dot(offset, offset); + if(offsetLenSqr <= 1e-6f) + { + DoCull(o); + } + else if(!ShouldCull(o)) + { + float4 wsPos = mul(UNITY_MATRIX_M, float4(v.vertex.x * _OffsetSize, v.vertex.y * _OffsetSize, v.vertex.z, 1.f)); + o.vertex = mul(UNITY_MATRIX_VP, wsPos); + o.normal = normalize(mul(v.normal, (float3x3)UNITY_MATRIX_M)); + } + + return o; + } + + float4 frag(v2f i) : SV_Target + { + return float4(1, 0, 0, 1); + } + ENDHLSL + + Pass + { + Name "DepthForwardOnly" + Tags{ "LightMode" = "DepthForwardOnly" } + + ZWrite On + + HLSLPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma multi_compile_instancing + ENDHLSL + } + + Pass + { + Name "ForwardOnly" + Tags { "LightMode" = "ForwardOnly" } + + ZTest LEqual + ZWrite On + + HLSLPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma multi_compile_instancing + ENDHLSL + } + } +} diff --git a/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeOffsetDebug.shader.meta b/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeOffsetDebug.shader.meta new file mode 100644 index 00000000000..7aa906249f8 --- /dev/null +++ b/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeOffsetDebug.shader.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: db8bd7436dc2c5f4c92655307d198381 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + preprocessorOverride: 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 370ec4bd2be..81334196004 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs @@ -446,11 +446,13 @@ public HDRenderPipeline(HDRenderPipelineAsset asset) if (IsAPVEnabled()) { var pvr = ProbeReferenceVolume.instance; - ProbeReferenceVolume.instance.Initialize(new ProbeVolumeSystemParameters() + ProbeReferenceVolume.instance.Initialize(new ProbeVolumeSystemParameters { memoryBudget = m_Asset.currentPlatformRenderPipelineSettings.probeVolumeMemoryBudget, probeDebugMesh = defaultResources.assets.probeDebugSphere, probeDebugShader = defaultResources.shaders.probeVolumeDebugShader, + offsetDebugMesh = defaultResources.assets.pyramidMesh, + offsetDebugShader = defaultResources.shaders.probeVolumeOffsetDebugShader, sceneData = m_GlobalSettings.GetOrCreateAPVSceneData(), shBands = m_Asset.currentPlatformRenderPipelineSettings.probeVolumeSHBands, supportsRuntimeDebug = Application.isEditor || m_GlobalSettings.supportRuntimeDebugDisplay, diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipelineRuntimeResources.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipelineRuntimeResources.cs index d1373e02ee6..7005fd541ce 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipelineRuntimeResources.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipelineRuntimeResources.cs @@ -41,6 +41,8 @@ public sealed class ShaderResources public Shader materialError; [Reload("Runtime/Debug/ProbeVolumeDebug.shader")] public Shader probeVolumeDebugShader; + [Reload("Runtime/Debug/ProbeVolumeOffsetDebug.shader")] + public Shader probeVolumeOffsetDebugShader; [Reload("Runtime/Debug/ClearDebugBuffer.compute")] public ComputeShader clearDebugBufferCS; @@ -505,6 +507,8 @@ public sealed class AssetResources public Mesh sphereMesh; [Reload("Runtime/RenderPipelineResources/Mesh/ProbeDebugSphere.fbx")] public Mesh probeDebugSphere; + [Reload("pyramid.fbx", ReloadAttribute.Package.Builtin)] + public Mesh pyramidMesh; } public ShaderResources shaders; diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipelineResources/HDRenderPipelineRuntimeResources.asset b/com.unity.render-pipelines.high-definition/Runtime/RenderPipelineResources/HDRenderPipelineRuntimeResources.asset index a09c58e7dd7..72618a0e0e6 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipelineResources/HDRenderPipelineRuntimeResources.asset +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipelineResources/HDRenderPipelineRuntimeResources.asset @@ -27,6 +27,8 @@ MonoBehaviour: debugViewVirtualTexturingBlit: {fileID: 4800000, guid: 55d195396b03b804eb78c92d468e3c8e, type: 3} materialError: {fileID: 4800000, guid: 79a966a5200a456188dec0d48d805614, type: 3} probeVolumeDebugShader: {fileID: 4800000, guid: 3b21275fd12d65f49babb5286f040f2d, type: 3} + probeVolumeOffsetDebugShader: {fileID: 4800000, guid: db8bd7436dc2c5f4c92655307d198381, + type: 3} clearDebugBufferCS: {fileID: 7200000, guid: 7fc6041d5cf70004aa33bb1ac64e3c06, type: 3} deferredPS: {fileID: 4800000, guid: 00dd221e34a6ab349a1196b0f2fab693, type: 3} colorPyramidPS: {fileID: 4800000, guid: 2fcfb8d92f45e4549b3f0bad5d0654bf, type: 3} @@ -282,4 +284,5 @@ MonoBehaviour: emissiveQuadMesh: {fileID: 4300000, guid: 1d5a8595286f94f4bb54171d49f473c3, type: 3} sphereMesh: {fileID: 4300000, guid: 9e0af751bc36ea146940ba245193e28c, type: 3} probeDebugSphere: {fileID: 532591105809680800, guid: b979359990531a2489ebd7a0ef0f9f01, type: 3} + pyramidMesh: {fileID: 10213, guid: 0000000000000000e000000000000000, type: 0} m_Version: 4