diff --git a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.Invalidation.cs b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.Invalidation.cs index 22224736b52..32ade04fb0a 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.Invalidation.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.Invalidation.cs @@ -197,5 +197,139 @@ static void ComputeValidityMasks(BakingCell bakingCell) probeHasEmptySpaceInGrid.Dispose(); } + + internal static void RecomputeValidityAfterBake() + { + // We need to start from scratch, so reset this. + s_ForceInvalidatedProbesAndTouchupVols.Clear(); + var prv = ProbeReferenceVolume.instance; + + var touchupVolumes = GameObject.FindObjectsOfType(); + var touchupVolumesAndBounds = new List<(ProbeReferenceVolume.Volume obb, Bounds aabb, ProbeTouchupVolume touchupVolume)>(touchupVolumes.Length); + foreach (var touchup in touchupVolumes) + { + m_BakingProfile = prv.sceneData.GetProfileForScene(touchup.gameObject.scene); // We need to grab a profile. The last one will have to do. + if (touchup.isActiveAndEnabled) + { + touchup.GetOBBandAABB(out var obb, out var aabb); + touchupVolumesAndBounds.Add((obb, aabb, touchup)); + + } + } + + float cellSize = prv.MaxBrickSize(); + var chunkSizeInProbes = ProbeBrickPool.GetChunkSizeInProbeCount(); + Vector3Int locSize = ProbeBrickPool.ProbeCountToDataLocSize(chunkSizeInProbes); + + List bakingCells = new List(); + + // Then for each cell we need to convert to baking cell and repeat the invalidation scheme. + foreach (var cellInfo in prv.cells) + { + var cell = cellInfo.Value.cell; + var bakingCell = ConvertCellToBakingCell(cell); + var position = cell.position; + var posWS = new Vector3(position.x * cellSize, position.y * cellSize, position.z * cellSize); + + Bounds cellBounds = new Bounds(); + cellBounds.min = posWS; + cellBounds.max = posWS + (Vector3.one * cellSize); + + // Find the subset of touchup volumes that will be considered for this cell. + // Capacity of the list to cover the worst case. + var localTouchupVolumes = new List<(ProbeReferenceVolume.Volume obb, Bounds aabb, ProbeTouchupVolume touchupVolume)>(touchupVolumes.Length); + foreach (var touchup in touchupVolumesAndBounds) + { + if (touchup.aabb.Intersects(cellBounds)) + localTouchupVolumes.Add(touchup); + } + + for (int i=0; i< bakingCell.probePositions.Length; ++i) + { + var probePos = bakingCell.probePositions[i]; + // Restore validity modified by the touchup volume before going forward. + bool wasForceInvalidated = bakingCell.touchupVolumeInteraction[i] > 0.0f && bakingCell.touchupVolumeInteraction[i] <= 1; + if (wasForceInvalidated) + { + bakingCell.validity[i] = 0.0f; + } + + var probeValidity = bakingCell.validity[i]; + bakingCell.touchupVolumeInteraction[i] = 0.0f; // Reset as we don't force write it and we might have stale data from previous. + + bool invalidatedProbe = false; + foreach (var touchup in localTouchupVolumes) + { + var touchupBound = touchup.aabb; + var touchupVolume = touchup.touchupVolume; + + // We check a small box around the probe to give some leniency (a couple of centimeters). + var probeBounds = new Bounds(bakingCell.probePositions[i], new Vector3(0.02f, 0.02f, 0.02f)); + if (ProbeVolumePositioning.OBBAABBIntersect(touchup.obb, probeBounds, touchupBound)) + { + if (touchupVolume.mode == ProbeTouchupVolume.Mode.InvalidateProbes) + { + invalidatedProbe = true; + // We check as below 1 but bigger than 0 in the debug shader, so any value <1 will do to signify touched up. + bakingCell.touchupVolumeInteraction[i] = 0.5f; + + if (probeValidity < 0.05f) // We just want to add probes that were not already invalid or close to. + { + s_ForceInvalidatedProbesAndTouchupVols[bakingCell.probePositions[i]] = touchupBound; + } + break; + } + } + } + + float currValidity = invalidatedProbe ? 1.0f : probeValidity; + byte currValidityNeighbourMask = 255; + bakingCell.validity[i] = currValidity; + bakingCell.validityNeighbourMask[i] = currValidityNeighbourMask; + } + ComputeValidityMasks(bakingCell); + + bakingCells.Add(bakingCell); + } + + // Unload it all as we are gonna load back with newly written cells. + foreach (var sceneData in prv.perSceneDataList) + { + prv.AddPendingAssetRemoval(sceneData.asset); + } + + // Make sure unloading happens. + prv.PerformPendingOperations(); + + + // We now need to make sure we find for each PerSceneData + foreach (var data in prv.perSceneDataList) + { + List newCells = new List(); + // This is a bit naive now. Should be fine tho. + for (int i=0; i x.index == currCell.index); + newCells.Add(bc); + } + + // Write bake the assets. + WriteBakingCells(data, newCells); + data.ResolveCells(); + } + + + // We can now finally reload. + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + + foreach (var sceneData in prv.perSceneDataList) + { + prv.AddPendingAssetLoading(sceneData.asset); + } + + prv.PerformPendingOperations(); + } } } diff --git a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.VirtualOffset.cs b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.VirtualOffset.cs index 8f621ffbf41..f5b32fcc77d 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.VirtualOffset.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.VirtualOffset.cs @@ -13,7 +13,6 @@ #if USE_BURST using Unity.Burst; #endif -using UnityEngine.Experimental.Rendering; namespace UnityEngine.Rendering { @@ -31,6 +30,8 @@ partial class ProbeGIBaking static void ApplyVirtualOffsets(Vector3[] positions, out Vector3[] offsets) { + var cellToVolumes = GetTouchupsPerCell(out bool hasAppliers); + var voSettings = m_BakingSettings.virtualOffsetSettings; if (!voSettings.useVirtualOffset) { @@ -47,7 +48,7 @@ static void ApplyVirtualOffsets(Vector3[] positions, out Vector3[] offsets) Physics.queriesHitBackfaces = true; AddOccluders(); - DoApplyVirtualOffsets(positions, out offsets, voSettings); + DoApplyVirtualOffsets(positions, out offsets, voSettings, cellToVolumes); } finally { @@ -157,7 +158,76 @@ private static void CleanupOccluders() ms_AddedOccluders.ForEach(Object.DestroyImmediate); } - static void DoApplyVirtualOffsets(Vector3[] probePositions, out Vector3[] probeOffsets, VirtualOffsetSettings voSettings) + struct TouchupsPerCell + { + public List<(ProbeTouchupVolume touchup, ProbeReferenceVolume.Volume obb, Vector3 center, Vector3 offset)> appliers; + public List<(ProbeTouchupVolume touchup, ProbeReferenceVolume.Volume obb, Vector3 center)> overriders; + } + + static Dictionary GetTouchupsPerCell(out bool hasAppliers) + { + float cellSize = m_BakingProfile.cellSizeInMeters; + hasAppliers = false; + + Dictionary cellToVolumes = new(); + foreach (var touchup in Object.FindObjectsOfType()) + { + if (!touchup.isActiveAndEnabled || (touchup.mode != ProbeTouchupVolume.Mode.ApplyVirtualOffset && touchup.mode != ProbeTouchupVolume.Mode.OverrideVirtualOffsetSettings)) + continue; + + hasAppliers |= touchup.mode == ProbeTouchupVolume.Mode.ApplyVirtualOffset; + touchup.GetOBBandAABB(out var obb, out var aabb); + + Vector3Int min = Vector3Int.FloorToInt(aabb.min / cellSize); + Vector3Int max = Vector3Int.FloorToInt(aabb.max / cellSize); + + for (int x = min.x; x <= max.x; x++) + { + for (int y = min.y; y <= max.y; y++) + { + for (int z = min.z; z <= max.z; z++) + { + var cell = PosToIndex(new Vector3Int(x, y, z)); + if (!cellToVolumes.TryGetValue(cell, out var volumes)) + cellToVolumes[cell] = volumes = new TouchupsPerCell() { appliers = new(), overriders = new() }; + + if (touchup.mode == ProbeTouchupVolume.Mode.ApplyVirtualOffset) + volumes.appliers.Add((touchup, obb, touchup.transform.position, touchup.GetVirtualOffset())); + else + volumes.overriders.Add((touchup, obb, touchup.transform.position)); + } + + } + } + } + + return cellToVolumes; + } + + static Vector3[] DoForceVirtualOffsets(Vector3[] positions, Dictionary cellToVolumes) + { + float cellSize = m_BakingProfile.cellSizeInMeters; + var offsets = new Vector3[positions.Length]; + for (int i = 0; i < positions.Length; i++) + { + int cellIndex = PosToIndex(Vector3Int.FloorToInt(positions[i] / cellSize)); + if (cellToVolumes.TryGetValue(cellIndex, out var volumes)) + { + foreach (var (touchup, obb, center, offset) in volumes.appliers) + { + if (touchup.ContainsPoint(obb, center, positions[i])) + { + positions[i] += offset; + offsets[i] = offset; + break; + } + } + } + } + return offsets; + } + + static void DoApplyVirtualOffsets(Vector3[] probePositions, out Vector3[] probeOffsets, VirtualOffsetSettings voSettings, Dictionary cellToVolumes) { // Limit memory usage based on ray cast / hit structures (of which there are lots per position) int maxPositionsPerBatch; @@ -176,6 +246,8 @@ static void DoApplyVirtualOffsets(Vector3[] probePositions, out Vector3[] probeO var positions = new NativeArray(probePositions, Allocator.TempJob); var offsets = new NativeArray(probePositions.Length, Allocator.TempJob, NativeArrayOptions.ClearMemory); var searchDistanceForPosition = new NativeArray(positions.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); + var rayOriginBiasForPosition = new NativeArray(positions.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); + var geometryBiasForPosition = new NativeArray(positions.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var positionIndex = new NativeArray(positions.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); // Allocate ray cast/hit data @@ -207,6 +279,7 @@ static void DoApplyVirtualOffsets(Vector3[] probePositions, out Vector3[] probeO positions = positions, positionIndex = positionIndex, searchDistanceForPosition = searchDistanceForPosition, + rayOriginBiasForPosition = rayOriginBiasForPosition, queryParams = new QueryParameters(voSettings.collisionMask, true, QueryTriggerInteraction.UseGlobal, true), }; var pushOutGeometryJob = new PushOutGeometryJob @@ -214,6 +287,7 @@ static void DoApplyVirtualOffsets(Vector3[] probePositions, out Vector3[] probeO voSettings = voSettings, positions = positions, offsets = offsets, + geometryBiasForPosition = geometryBiasForPosition, positionIndex = positionIndex, }; var jobHandles = new JobHandle[2]; @@ -226,6 +300,7 @@ static void DoApplyVirtualOffsets(Vector3[] probePositions, out Vector3[] probeO int nextBatchIdx = 1; int batchPosIdx = 0; + float cellSize = m_BakingProfile.cellSizeInMeters; while (batchPosIdx < positions.Length) { // Run a quick overlap check for each search box before setting up rays for the position @@ -238,13 +313,44 @@ static void DoApplyVirtualOffsets(Vector3[] probePositions, out Vector3[] probeO var scaleForSearchDist = voSettings.searchMultiplier; var distanceSearch = scaleForSearchDist * searchDistance; + float rayOriginBias = voSettings.rayOriginBias; + float geometryBias = voSettings.outOfGeoOffset; - var positionHasCollider = Physics.CheckBox(positions[batchPosIdx], new Vector3(distanceSearch, distanceSearch, distanceSearch), Quaternion.identity, voSettings.collisionMask); + int cellIndex = PosToIndex(Vector3Int.FloorToInt(positions[batchPosIdx] / cellSize)); + bool hasTouchups = cellToVolumes.TryGetValue(cellIndex, out var volumes), adjusted = false; + if (hasTouchups) + { + foreach (var (touchup, obb, center, offset) in volumes.appliers) + { + if (touchup.ContainsPoint(obb, center, positions[batchPosIdx])) + { + positions[batchPosIdx] += offset; + offsets[batchPosIdx] = offset; + adjusted = true; + break; + } + } + } - if (positionHasCollider) + if (!adjusted && Physics.CheckBox(positions[batchPosIdx], new Vector3(distanceSearch, distanceSearch, distanceSearch), Quaternion.identity, voSettings.collisionMask)) { + if (hasTouchups) + { + foreach (var (touchup, obb, center) in volumes.overriders) + { + if (touchup.ContainsPoint(obb, center, positions[batchPosIdx])) + { + rayOriginBias = touchup.rayOriginBias; + geometryBias = touchup.geometryBias; + break; + } + } + } + positionIndex[batchPosStart + overlapCount] = batchPosIdx; searchDistanceForPosition[batchPosStart + overlapCount] = distanceSearch; + rayOriginBiasForPosition[batchPosStart + overlapCount] = rayOriginBias; + geometryBiasForPosition[batchPosStart + overlapCount] = geometryBias; ++overlapCount; } } @@ -308,6 +414,8 @@ static void DoApplyVirtualOffsets(Vector3[] probePositions, out Vector3[] probeO positions.Dispose(); offsets.Dispose(); searchDistanceForPosition.Dispose(); + rayOriginBiasForPosition.Dispose(); + geometryBiasForPosition.Dispose(); positionIndex.Dispose(); raycastCommands[0].Dispose(); @@ -332,6 +440,8 @@ struct CreateRayCastCommandsJob : IJobParallelFor [ReadOnly] public NativeArray positionIndex; [NativeDisableContainerSafetyRestriction] [ReadOnly] public NativeArray searchDistanceForPosition; + [NativeDisableContainerSafetyRestriction] + [ReadOnly] public NativeArray rayOriginBiasForPosition; [ReadOnly] public int startIdx; @@ -347,6 +457,7 @@ public void Execute(int i) int posIdx = positionIndex[i + startIdx]; var position = positions[posIdx]; var searchDistance = searchDistanceForPosition[i + startIdx]; + var rayOriginBias = rayOriginBiasForPosition[i + startIdx]; int cmdIdx = i * kRayDirectionsPerPosition; @@ -356,7 +467,7 @@ public void Execute(int i) for (var j = 0; j < kRayDirectionsPerPosition; ++j) { var direction = kRayDirections[j]; - var origin = position + direction * voSettings.rayOriginBias; + var origin = position + direction * rayOriginBias; raycastCommands[cmdIdx++] = new RaycastCommand(origin, direction, queryParams, searchDistance); } } @@ -419,11 +530,15 @@ struct PushOutGeometryJob : IJobParallelFor [NativeDisableContainerSafetyRestriction] [WriteOnly] public NativeArray offsets; + [NativeDisableContainerSafetyRestriction] + [ReadOnly] public NativeArray geometryBiasForPosition; + public void Execute(int i) { int cmdIdx = i * kRayDirectionsPerPosition; int posIdx = positionIndex[i + startIdx]; - var offset = PushOutOfGeometry(cmdIdx, voSettings.outOfGeoOffset, voSettings.maxHitsPerRay); + float geometryBias = geometryBiasForPosition[i + startIdx]; + var offset = PushOutOfGeometry(cmdIdx, geometryBias, voSettings.maxHitsPerRay); positions[posIdx] += offset; offsets[posIdx] = offset; } @@ -491,5 +606,100 @@ Vector3 PushOutOfGeometry(int cmdIdx, float biasOutGeo, int maxHitsPerRay) return Vector3.zero; } } + + static internal void RecomputeVOForDebugOnly() + { + var prv = ProbeReferenceVolume.instance; + GeneratePhysicsComponentToModList(); + if (prv.perSceneDataList.Count > 0) + { + SetBakingContext(prv.perSceneDataList); + } + else return; + + + globalBounds = prv.globalBounds; + CellCountInDirections(out minCellPosition, out maxCellPosition, prv.MaxBrickSize()); + cellCount = maxCellPosition + Vector3Int.one - minCellPosition; + + m_BakingBatch = new BakingBatch(128, cellCount); + + List bakingCells = new List(); + + foreach (var cellInfo in ProbeReferenceVolume.instance.cells.Values) + { + var cell = cellInfo.cell; + var bakingCell = ConvertCellToBakingCell(cell); + var positions = bakingCell.probePositions; + + for (int i=0; i newCells = new List(); + // This is a bit naive now. Should be fine tho. + for (int i = 0; i < data.asset.cells.Length; ++i) + { + var currCell = data.asset.cells[i]; + var bc = bakingCells.Find(x => x.index == currCell.index); + newCells.Add(bc); + } + + // Write bake the assets. + WriteBakingCells(data, newCells); + data.ResolveCells(); + } + + + // We can now finally reload. + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + + foreach (var sceneData in prv.perSceneDataList) + { + prv.AddPendingAssetLoading(sceneData.asset); + } + + prv.PerformPendingOperations(); + } } } diff --git a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs index 53e188e7184..eb184e6c6e7 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs @@ -8,6 +8,7 @@ using Brick = UnityEngine.Rendering.ProbeBrickIndex.Brick; using Cell = UnityEngine.Rendering.ProbeReferenceVolume.Cell; +using IndirectionEntryInfo = UnityEngine.Rendering.ProbeReferenceVolume.IndirectionEntryInfo; using CellInfo = UnityEngine.Rendering.ProbeReferenceVolume.CellInfo; namespace UnityEngine.Rendering @@ -28,6 +29,7 @@ struct BakingCell public int minSubdiv; public int indexChunkCount; public int shChunkCount; + public IndirectionEntryInfo[] indirectionEntryInfo; public int[] probeIndices; @@ -182,7 +184,7 @@ public enum Stages static Stages currentStage = Stages.None; public BakingSetupProfiling(Stages stage) : base(stage, ref currentStage) { } public override Stages GetLastStep() => Stages.None; - public static void GetProgressRange(out float progress0, out float progress1) { float s = 1/(float)Stages.None; progress0 = (float)currentStage*s; progress1 = progress0+s; } + public static void GetProgressRange(out float progress0, out float progress1) { float s = 1 / (float)Stages.None; progress0 = (float)currentStage * s; progress1 = progress0 + s; } public void Dispose() { OnDispose(ref currentStage); } } public class BakingCompleteProfiling : BakingProfiling, IDisposable @@ -202,7 +204,7 @@ public enum Stages static Stages currentStage = Stages.None; public BakingCompleteProfiling(Stages stage) : base(stage, ref currentStage) { } public override Stages GetLastStep() => Stages.None; - public static void GetProgressRange(out float progress0, out float progress1) { float s = 1/(float)Stages.None; progress0 = (float)currentStage*s; progress1 = progress0+s; } + public static void GetProgressRange(out float progress0, out float progress1) { float s = 1 / (float)Stages.None; progress0 = (float)currentStage * s; progress1 = progress0 + s; } public void Dispose() { OnDispose(ref currentStage); } } @@ -238,7 +240,7 @@ internal static List GetPerSceneDataList() if (!isBakingSceneSubset) return fullPerSceneDataList; - List usedPerSceneDataList = new(); + List usedPerSceneDataList = new (); foreach (var sceneData in fullPerSceneDataList) { if (partialBakeSceneList.Contains(ProbeVolumeSceneData.GetSceneGUID(sceneData.gameObject.scene))) @@ -771,7 +773,6 @@ static void OnAdditionalProbesBakeCompleted() { touchup.GetOBBandAABB(out var obb, out var aabb); touchupVolumesAndBounds.Add((obb, aabb, touchup)); - } } @@ -842,25 +843,27 @@ static void OnAdditionalProbesBakeCompleted() // We check a small box around the probe to give some leniency (a couple of centimeters). var probeBounds = new Bounds(cell.probePositions[i], new Vector3(0.02f, 0.02f, 0.02f)); - if (ProbeVolumePositioning.OBBAABBIntersect(touchup.obb, probeBounds, touchupBound)) + if (touchupVolume.IntersectsVolume(touchup.obb, touchup.aabb, probeBounds)) { - if (touchupVolume.invalidateProbes) + if (touchupVolume.mode == ProbeTouchupVolume.Mode.InvalidateProbes) { invalidatedProbe = true; - // We check as below 1 but bigger than 0 in the debug shader, so any value <1 will do to signify touched up. - cell.touchupVolumeInteraction[i] = 0.5f; if (valid < 0.05f) // We just want to add probes that were not already invalid or close to. { + // We check as below 1 but bigger than 0 in the debug shader, so any value <1 will do to signify touched up. + cell.touchupVolumeInteraction[i] = 0.5f; + s_ForceInvalidatedProbesAndTouchupVols[cell.probePositions[i]] = touchupBound; } break; } - else if (touchupVolume.overrideDilationThreshold) + else if (touchupVolume.mode == ProbeTouchupVolume.Mode.OverrideValidityThreshold) { - // The 1 + is used to determine the action (debug shader tests above 1), then we add the threshold to be able to retrieve it in debug phase. - cell.touchupVolumeInteraction[i] = 1.0f + touchupVolume.overriddenDilationThreshold; - s_CustomDilationThresh[(cell.index, i)] = touchupVolume.overriddenDilationThreshold; + float thresh = (1.0f - touchupVolume.overriddenDilationThreshold); + // The 1.0f + is used to determine the action (debug shader tests above 1), then we add the threshold to be able to retrieve it in debug phase. + cell.touchupVolumeInteraction[i] = 1.0f + thresh; + s_CustomDilationThresh[(cell.index, i)] = thresh; } intensityScale = touchupVolume.intensityScale; @@ -942,8 +945,7 @@ static void OnAdditionalProbesBakeCompleted() cell.validityNeighbourMask[i] = currValidityNeighbourMask; } - cell.indexChunkCount = probeRefVolume.GetNumberOfBricksAtSubdiv(cell.position, cell.minSubdiv, out _, out _) / ProbeBrickIndex.kIndexChunkSize; - cell.shChunkCount = ProbeBrickPool.GetChunkCount(cell.bricks.Length, ProbeBrickPool.GetChunkSizeInBrickCount()); + cell.shChunkCount = ProbeBrickPool.GetChunkCount(cell.bricks.Length); ComputeValidityMasks(cell); @@ -988,7 +990,7 @@ static void OnAdditionalProbesBakeCompleted() if (scene2Data.TryGetValue(scene, out var data)) { if (!data2BakingCells.TryGetValue(data, out var bakingCellsList)) - bakingCellsList = data2BakingCells[data] = new(); + bakingCellsList = data2BakingCells[data] = new (); bakingCellsList.Add(cell); } @@ -1013,7 +1015,7 @@ static void OnAdditionalProbesBakeCompleted() asset.bands = ProbeVolumeSHBands.SphericalHarmonicsL2; if (!data2BakingCells.TryGetValue(data, out var bakingCellsList)) - bakingCellsList = new(); // Can happen if no cell is baked for the scene + bakingCellsList = new (); // Can happen if no cell is baked for the scene WriteBakingCells(data, bakingCellsList); data.ResolveSharedCellData(); @@ -1056,6 +1058,68 @@ static void OnAdditionalProbesBakeCompleted() } + static void AnalyzeBrickForIndirectionEntries(ref BakingCell cell) + { + var prv = ProbeReferenceVolume.instance; + int cellSizeInBricks = m_BakingProfile.cellSizeInBricks; + int entrySubdivLevel = Mathf.Min(m_BakingProfile.simplificationLevels, prv.GetGlobalIndirectionEntryMaxSubdiv()); + int indirectionEntrySizeInBricks = ProbeReferenceVolume.CellSize(entrySubdivLevel); + int numOfIndirectionEntriesPerCellDim = cellSizeInBricks / indirectionEntrySizeInBricks; + + int numOfEntries = numOfIndirectionEntriesPerCellDim * numOfIndirectionEntriesPerCellDim * numOfIndirectionEntriesPerCellDim; + cell.indirectionEntryInfo = new IndirectionEntryInfo[numOfEntries]; + + // This is fairly naive now, if we need optimization this is the place to be. + + Vector3Int cellPosInEntries = cell.position * numOfIndirectionEntriesPerCellDim; + Vector3Int cellPosInBricks = cell.position * cellSizeInBricks; + + int totalIndexChunks = 0; + int i = 0; + for (int x = 0; x < numOfIndirectionEntriesPerCellDim; ++x) + { + for (int y = 0; y < numOfIndirectionEntriesPerCellDim; ++y) + { + for (int z = 0; z < numOfIndirectionEntriesPerCellDim; ++z) + { + Vector3Int entryPositionInBricks = cellPosInBricks + new Vector3Int(x, y, z) * indirectionEntrySizeInBricks; + Bounds entryBoundsInBricks = new Bounds(); + entryBoundsInBricks.min = entryPositionInBricks; + entryBoundsInBricks.max = entryPositionInBricks + new Vector3Int(indirectionEntrySizeInBricks, indirectionEntrySizeInBricks, indirectionEntrySizeInBricks); + + int minSubdiv = m_BakingProfile.maxSubdivision; + bool touchedBrick = false; + foreach (Brick b in cell.bricks) + { + if (b.subdivisionLevel < minSubdiv) + { + if (b.IntersectArea(entryBoundsInBricks)) + { + touchedBrick = true; + minSubdiv = b.subdivisionLevel; + if (minSubdiv == 0) break; + } + } + } + + cell.indirectionEntryInfo[i].minSubdiv = minSubdiv; + cell.indirectionEntryInfo[i].positionInBricks = cellPosInBricks + new Vector3Int(x, y, z) * indirectionEntrySizeInBricks; + cell.indirectionEntryInfo[i].hasOnlyBiggerBricks = minSubdiv > entrySubdivLevel && touchedBrick; + + ProbeBrickIndex.IndirectionEntryUpdateInfo unused = new ProbeBrickIndex.IndirectionEntryUpdateInfo(); + int brickCount = ProbeReferenceVolume.instance.GetNumberOfBricksAtSubdiv(cell.indirectionEntryInfo[i], ref unused); + + totalIndexChunks += Mathf.CeilToInt((float)brickCount / ProbeBrickIndex.kIndexChunkSize); + + i++; + } + } + } + + // Chunk count. + cell.indexChunkCount = totalIndexChunks; + } + static void OnLightingDataCleared() { Clear(); @@ -1152,6 +1216,7 @@ static BakingCell ConvertCellToBakingCell(Cell cell) indexChunkCount = cell.indexChunkCount, shChunkCount = cell.shChunkCount, probeIndices = null, // Not needed for this conversion. + indirectionEntryInfo = cell.indirectionEntryInfo, }; // Runtime Cell arrays may contain padding to match chunk size @@ -1256,8 +1321,9 @@ static BakingCell MergeCells(BakingCell dst, BakingCell srcCell) outCell.validityNeighbourMask = new byte[numberOfProbes]; outCell.offsetVectors = new Vector3[numberOfProbes]; outCell.touchupVolumeInteraction = new float[numberOfProbes]; - outCell.indexChunkCount = ProbeReferenceVolume.instance.GetNumberOfBricksAtSubdiv(outCell.position, outCell.minSubdiv, out _, out _) / ProbeBrickIndex.kIndexChunkSize; - outCell.shChunkCount = ProbeBrickPool.GetChunkCount(outCell.bricks.Length, ProbeBrickPool.GetChunkSizeInBrickCount()); + outCell.shChunkCount = ProbeBrickPool.GetChunkCount(outCell.bricks.Length); + // We don't need to analyse here, it will be done upon writing back. + outCell.indirectionEntryInfo = new IndirectionEntryInfo[srcCell.indirectionEntryInfo.Length]; BakingCell[] consideredCells = { dst, srcCell }; @@ -1352,6 +1418,8 @@ unsafe static void WriteBakingCells(ProbeVolumePerSceneData data, List k_ExpandedState = new ExpandedState(Expandable.Touchup); + readonly static ExpandedState k_ExpandedState = new ExpandedState(Expandable.Volume | Expandable.Touchup); readonly static AdditionalPropertiesState k_AdditionalPropertiesState = new AdditionalPropertiesState(0); public static void RegisterEditor(ProbeTouchupVolumeEditor editor) @@ -84,27 +84,86 @@ public static void SetAdditionalPropertiesVisibility(bool value) k_AdditionalPropertiesState.HideAll(); } - public static void DrawTouchupAdditionalContent(SerializedProbeTouchupVolume serialized, Editor owner) + public static void DrawVolumeContent(SerializedProbeTouchupVolume serialized, Editor owner) { - using (new EditorGUI.DisabledScope(serialized.invalidateProbes.boolValue)) + EditorGUILayout.PropertyField(serialized.shape); + EditorGUILayout.PropertyField(serialized.shape.intValue == 0 ? serialized.size : serialized.radius); + + } + + public static void DrawTouchupContent(SerializedProbeTouchupVolume serialized, Editor owner) + { + ProbeTouchupVolume ptv = (serialized.serializedObject.targetObject as ProbeTouchupVolume); + + var bakeSettings = ProbeReferenceVolume.instance.sceneData.GetBakeSettingsForScene(ptv.gameObject.scene); + + EditorGUILayout.PropertyField(serialized.mode); + + if (serialized.mode.intValue == (int)ProbeTouchupVolume.Mode.OverrideValidityThreshold) { - using (var change = new EditorGUI.ChangeCheckScope()) + EditorGUILayout.PropertyField(serialized.overriddenDilationThreshold); + } + else if (serialized.mode.intValue == (int)ProbeTouchupVolume.Mode.ApplyVirtualOffset) + { + EditorGUI.BeginDisabledGroup(!bakeSettings.virtualOffsetSettings.useVirtualOffset); + EditorGUILayout.BeginHorizontal(); + + EditorGUILayout.PropertyField(serialized.virtualOffsetRotation); + + var editMode = Styles.VirtualOffsetEditMode; + EditorGUI.BeginChangeCheck(); + GUILayout.Toggle(editMode == EditMode.editMode, Styles.s_RotateToolIcon, EditorStyles.miniButton, GUILayout.Width(28f)); + if (EditorGUI.EndChangeCheck()) { - EditorGUILayout.HelpBox("Changing the intensity of probe data is a delicate operation that can lead to inconsistencies in the lighting, hence the feature is to be used sparingly.", MessageType.Info, wide: true); - EditorGUILayout.PropertyField(serialized.intensityScale, Styles.s_IntensityScale); + EditMode.SceneViewEditMode targetMode = EditMode.editMode == editMode ? EditMode.SceneViewEditMode.None : editMode; + EditMode.ChangeEditMode(targetMode, GetBounds(serialized, owner), owner); + } + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.PropertyField(serialized.virtualOffsetDistance); + EditorGUI.EndDisabledGroup(); + + if (!bakeSettings.virtualOffsetSettings.useVirtualOffset) + { + EditorGUILayout.HelpBox("Apply Virtual Offset can be used only if Virtual Offset is enabled for the Baking Set.", MessageType.Warning); } } + else if (serialized.mode.intValue == (int)ProbeTouchupVolume.Mode.OverrideVirtualOffsetSettings) + { + EditorGUI.BeginDisabledGroup(!bakeSettings.virtualOffsetSettings.useVirtualOffset); + EditorGUILayout.PropertyField(serialized.geometryBias); + EditorGUILayout.PropertyField(serialized.rayOriginBias); + EditorGUI.EndDisabledGroup(); + + if (!bakeSettings.virtualOffsetSettings.useVirtualOffset) + { + EditorGUILayout.HelpBox("Override Virtual Offset can be used only if Virtual Offset is enabled for the Baking Set.", MessageType.Warning); + } + + } } - public static void DrawTouchupContent(SerializedProbeTouchupVolume serialized, Editor owner) + internal static Bounds GetBounds(SerializedProbeTouchupVolume serialized, Editor owner) { - EditorGUILayout.PropertyField(serialized.invalidateProbes, Styles.s_InvalidateProbes); + var position = ((Component)owner.target).transform.position; + if (serialized.shape.intValue == (int)ProbeTouchupVolume.Shape.Box) + return new Bounds(position, serialized.size.vector3Value); + if (serialized.shape.intValue == (int)ProbeTouchupVolume.Shape.Box) + return new Bounds(position, serialized.radius.floatValue * Vector3.up); + return default; + } - using (new EditorGUI.DisabledScope(serialized.invalidateProbes.boolValue)) + public static void DrawTouchupAdditionalContent(SerializedProbeTouchupVolume serialized, Editor owner) + { + if (serialized.mode.intValue == (int)ProbeTouchupVolume.Mode.InvalidateProbes) { - EditorGUILayout.PropertyField(serialized.overrideDilationThreshold, Styles.s_OverrideDilationThreshold); - using (new EditorGUI.DisabledScope(!serialized.overrideDilationThreshold.boolValue)) - EditorGUILayout.PropertyField(serialized.overriddenDilationThreshold, Styles.s_OverriddenDilationThreshold); + EditorGUILayout.HelpBox("Changing the intensity of probe data is a delicate operation that can lead to inconsistencies in the lighting, hence the feature is to be used sparingly.", MessageType.Info, wide: true); + EditorGUILayout.PropertyField(serialized.intensityScale); + + if (GUILayout.Button(EditorGUIUtility.TrTextContent("Update Probe Validity", "Update the validity of probes falling within the probe touchup volume."), EditorStyles.miniButton)) + { + ProbeGIBaking.RecomputeValidityAfterBake(); + } } } @@ -112,8 +171,11 @@ public static void DrawTouchupContent(SerializedProbeTouchupVolume serialized, E static ProbeTouchupVolumeUI() { Inspector = CED.Group( - CED.AdditionalPropertiesFoldoutGroup(Styles.s_TouchupHeader, Expandable.Touchup, k_ExpandedState, AdditionalProperties.Touchup, k_AdditionalPropertiesState, - CED.Group((serialized, owner) => DrawTouchupContent(serialized, owner)), DrawTouchupAdditionalContent)); + CED.FoldoutGroup(Styles.s_VolumeHeader, Expandable.Volume, k_ExpandedState, + (serialized, owner) => DrawVolumeContent(serialized, owner)), + CED.AdditionalPropertiesFoldoutGroup(Styles.s_TouchupHeader, Expandable.Touchup, k_ExpandedState, AdditionalProperties.Touchup, k_AdditionalPropertiesState, + CED.Group((serialized, owner) => DrawTouchupContent(serialized, owner)), DrawTouchupAdditionalContent) + ); } } @@ -132,6 +194,17 @@ static HierarchicalBox s_ShapeBox } } + static HierarchicalSphere _ShapeSphere; + static HierarchicalSphere s_ShapeSphere + { + get + { + if (_ShapeSphere == null) + _ShapeSphere = new HierarchicalSphere(Styles.k_GizmoColorBase); + return _ShapeSphere; + } + } + protected void OnEnable() { m_SerializedTouchupVolume = new SerializedProbeTouchupVolume(serializedObject); @@ -150,17 +223,6 @@ public override void OnInspectorGUI() return; } - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_SerializedTouchupVolume.size, Styles.s_Size); - if (EditorGUI.EndChangeCheck()) - { - Vector3 tmpClamp = m_SerializedTouchupVolume.size.vector3Value; - tmpClamp.x = Mathf.Max(0f, tmpClamp.x); - tmpClamp.y = Mathf.Max(0f, tmpClamp.y); - tmpClamp.z = Mathf.Max(0f, tmpClamp.z); - m_SerializedTouchupVolume.size.vector3Value = tmpClamp; - } - ProbeTouchupVolumeUI.Inspector.Draw(m_SerializedTouchupVolume, this); } else @@ -176,36 +238,98 @@ static void DrawGizmosSelected(ProbeTouchupVolume touchupVolume, GizmoType gizmo { using (new Handles.DrawingScope(Matrix4x4.TRS(touchupVolume.transform.position, touchupVolume.transform.rotation, Vector3.one))) { - // Bounding box. - s_ShapeBox.center = Vector3.zero; - s_ShapeBox.size = touchupVolume.size; - s_ShapeBox.SetBaseColor(ProbeTouchupColorPreferences.GetColorPrefProbeVolumeGizmoColor()); - s_ShapeBox.DrawHull(true); + if (touchupVolume.shape == ProbeTouchupVolume.Shape.Box) + { + s_ShapeBox.center = Vector3.zero; + s_ShapeBox.size = touchupVolume.size; + s_ShapeBox.SetBaseColor(ProbeTouchupColorPreferences.GetColorPrefProbeVolumeGizmoColor()); + s_ShapeBox.DrawHull(true); + } + else if (touchupVolume.shape == ProbeTouchupVolume.Shape.Sphere) + { + s_ShapeSphere.center = Vector3.zero; + s_ShapeSphere.radius = touchupVolume.radius; + s_ShapeSphere.DrawHull(true); + } + + if (touchupVolume.mode == ProbeTouchupVolume.Mode.ApplyVirtualOffset) + { + ArrowHandle(0, Quaternion.Euler(touchupVolume.virtualOffsetRotation), touchupVolume.virtualOffsetDistance); + } + } + } + + static void ArrowHandle(int controlID, Quaternion rotation, float distance) + { + Handles.matrix *= Matrix4x4.Rotate(rotation); + + float thickness = Handles.lineThickness; + float coneSize = .05f; + + var linePos = (distance - coneSize) * Vector3.forward; + var conePos = (distance - coneSize * 0.5f) * Vector3.forward; + + if (distance < coneSize) + { + conePos = coneSize * 0.5f * Vector3.forward; + Handles.matrix *= Matrix4x4.Scale(new Vector3(1, 1, distance / coneSize)); } + + Handles.DrawLine(Vector3.zero, linePos, thickness); + Handles.ConeHandleCap(controlID, conePos, Quaternion.identity, coneSize, EventType.Repaint); } protected void OnSceneGUI() { ProbeTouchupVolume touchupVolume = target as ProbeTouchupVolume; + var position = Quaternion.Inverse(touchupVolume.transform.rotation) * touchupVolume.transform.position; + //important: if the origin of the handle's space move along the handle, //handles displacement will appears as moving two time faster. using (new Handles.DrawingScope(Matrix4x4.TRS(Vector3.zero, touchupVolume.transform.rotation, Vector3.one))) { - //contained must be initialized in all case - s_ShapeBox.center = Quaternion.Inverse(touchupVolume.transform.rotation) * touchupVolume.transform.position; - s_ShapeBox.size = touchupVolume.size; + if (touchupVolume.shape == ProbeTouchupVolume.Shape.Box) + { + //contained must be initialized in all case + s_ShapeBox.center = position; + s_ShapeBox.size = touchupVolume.size; + + s_ShapeBox.monoHandle = false; + EditorGUI.BeginChangeCheck(); + s_ShapeBox.DrawHandle(); + if (EditorGUI.EndChangeCheck()) + { + Undo.RecordObjects(new UnityEngine.Object[] { touchupVolume, touchupVolume.transform }, "Change Adjustment Volume Bounding Box"); - s_ShapeBox.monoHandle = false; - EditorGUI.BeginChangeCheck(); - s_ShapeBox.DrawHandle(); - if (EditorGUI.EndChangeCheck()) + touchupVolume.size = s_ShapeBox.size; + Vector3 delta = touchupVolume.transform.rotation * s_ShapeBox.center - touchupVolume.transform.position; + touchupVolume.transform.position += delta; ; + } + } + else if (touchupVolume.shape == ProbeTouchupVolume.Shape.Sphere) { - Undo.RecordObjects(new UnityEngine.Object[] { touchupVolume, touchupVolume.transform }, "Change Probe Touchup Volume Bounding Box"); + s_ShapeSphere.center = position; + s_ShapeSphere.radius = touchupVolume.radius; + + EditorGUI.BeginChangeCheck(); + s_ShapeSphere.DrawHandle(); + if (EditorGUI.EndChangeCheck()) + { + Undo.RecordObject(touchupVolume, "Change Adjustment Volume Radius"); + touchupVolume.radius = s_ShapeSphere.radius; + } + } - touchupVolume.size = s_ShapeBox.size; - Vector3 delta = touchupVolume.transform.rotation * s_ShapeBox.center - touchupVolume.transform.position; - touchupVolume.transform.position += delta; ; + if (touchupVolume.mode == ProbeTouchupVolume.Mode.ApplyVirtualOffset && EditMode.editMode == Styles.VirtualOffsetEditMode) + { + EditorGUI.BeginChangeCheck(); + Quaternion rotation = Handles.RotationHandle(Quaternion.Euler(touchupVolume.virtualOffsetRotation), position); + if (EditorGUI.EndChangeCheck()) + { + Undo.RecordObject(touchupVolume, "Change Virtual Offset Direction"); + touchupVolume.virtualOffsetRotation = rotation.eulerAngles; + } } } } diff --git a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeVolumeBakingProcessSettingsDrawer.cs b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeVolumeBakingProcessSettingsDrawer.cs index 404022256f1..f8e365bb54a 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeVolumeBakingProcessSettingsDrawer.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeVolumeBakingProcessSettingsDrawer.cs @@ -8,22 +8,24 @@ class ProbeVolumeBakingProcessSettingsDrawer : PropertyDrawer { static class Styles { - public static readonly GUIContent enableDilation = new GUIContent("Enable Dilation", "Whether to enable dilation after the baking. Dilation will dilate valid probes data into invalid probes."); - public static readonly GUIContent dilationDistance = new GUIContent("Dilation Distance", "The distance used to pick neighbouring probes to dilate into the invalid probe."); - public static readonly GUIContent dilationValidity = new GUIContent("Dilation Validity Threshold", "The validity threshold used to identify invalid probes."); - public static readonly GUIContent dilationIterationCount = new GUIContent("Dilation Iteration Count", "The number of times the dilation process takes place."); - public static readonly GUIContent dilationSquaredDistanceWeighting = new GUIContent("Squared Distance Weighting", "Whether to weight neighbouring probe contribution using squared distance rather than linear distance."); - public static readonly GUIContent useVirtualOffset = EditorGUIUtility.TrTextContent("Use Virtual Offset", "Push invalid probes out of geometry. Please note, this feature is currently a proof of concept, it is fairly slow and not optimal in quality."); - public static readonly GUIContent virtualOffsetSearchMultiplier = EditorGUIUtility.TrTextContent("Search multiplier", "A multiplier to be applied on the distance between two probes to derive the search distance out of geometry."); - public static readonly GUIContent virtualOffsetBiasOutGeometry = EditorGUIUtility.TrTextContent("Bias out geometry", "Determines how much a probe is pushed out of the geometry on top of the distance to closest hit."); - public static readonly GUIContent virtualOffsetRayOriginBias = EditorGUIUtility.TrTextContent("Ray origin bias", "The distance with which to bias each ray direction away from the probe position."); - public static readonly GUIContent virtualOffsetMaxHitsPerRay = EditorGUIUtility.TrTextContent("Max hits per ray", "Determines how many colliders intersecting each ray are included in calculations."); - public static readonly GUIContent virtualOffsetCollisionMask = EditorGUIUtility.TrTextContent("Collision mask", "The collision layer mask to cast rays against."); + public static readonly GUIContent enableDilation = new GUIContent("Enable Dilation", "Replace invalid probe data with valid data from neighboring probes during baking."); + public static readonly GUIContent dilationDistance = new GUIContent("Search Radius", "How far to search from invalid probes when looking for valid neighbors. Higher values include more distant probes which may be unwanted."); + public static readonly GUIContent dilationValidity = new GUIContent("Validity Threshold", "The threshold of backfaces seen by probes before they are invalidated during baking. Higher values mean the probe is more likely to be marked invalid."); + public static readonly GUIContent dilationIterationCount = new GUIContent("Dilation Iterations", "The number of times Unity repeats the Dilation calculation. This will cause the area of dilation to grow."); + public static readonly GUIContent dilationSquaredDistanceWeighting = new GUIContent("Squared Distance Weighting", "During dilation, weight the contribution of neighbouring probes by squared distance, rather than linear distance."); + public static readonly GUIContent useVirtualOffset = EditorGUIUtility.TrTextContent("Enable Virtual Offset", "Push invalid probes outside of geometry to prevent backface hits. Produces better visual results than Dilation, but increases baking times."); + public static readonly GUIContent virtualOffsetSearchMultiplier = EditorGUIUtility.TrTextContent("Search Distance Multiplier", "Determines the length of the sampling ray Unity uses to search for valid probe positions. High values may result in unwanted results, such as pushing probes through neighboring geometry."); + public static readonly GUIContent virtualOffsetBiasOutGeometry = EditorGUIUtility.TrTextContent("Geometry Bias", "Determines how far Unity pushes a probe out of geometry after a ray hit."); + public static readonly GUIContent virtualOffsetRayOriginBias = EditorGUIUtility.TrTextContent("Ray Origin Bias", "Distance from the probe position used to determine the origin of the sampling ray."); + public static readonly GUIContent virtualOffsetMaxHitsPerRay = EditorGUIUtility.TrTextContent("Max Ray Hits", "How many collisions to allow per ray before determining the Virtual Offset probe position."); + public static readonly GUIContent virtualOffsetCollisionMask = EditorGUIUtility.TrTextContent("Layer Mask", "Layers to include in collision calculations for Virtual Offset."); public static readonly GUIContent advanced = EditorGUIUtility.TrTextContent("Advanced"); - public static readonly GUIContent dilationSettingsTitle = EditorGUIUtility.TrTextContent("Dilation Settings"); + public static readonly GUIContent dilationSettingsTitle = EditorGUIUtility.TrTextContent("Probe Dilation Settings"); public static readonly GUIContent virtualOffsetSettingsTitle = EditorGUIUtility.TrTextContent("Virtual Offset Settings"); + + public static GUIStyle voButtonStyle = new GUIStyle(EditorStyles.miniButton); } // PropertyDrawer are not made to use GUILayout, so it will try to reserve a rect before calling OnGUI @@ -110,6 +112,12 @@ void DrawVirtualOffsetSettings(SerializedProperty virtualOffsetSettings) EditorGUILayout.PropertyField(virtualOffsetCollisionMask, Styles.virtualOffsetCollisionMask); } } + + Styles.voButtonStyle.margin.left = 16 * (EditorGUI.indentLevel + 1); + if (GUILayout.Button(EditorGUIUtility.TrTextContent("Regenerate virtual offset for Debug", "Re-run the virtual offset simulation; it will be applied only for debug visualization sake and not affect baked data."), Styles.voButtonStyle)) + { + ProbeGIBaking.RecomputeVOForDebugOnly(); + } } } } diff --git a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeVolumeBakingWindow.cs b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeVolumeBakingWindow.cs index 2209a2168e1..b85cce1991d 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeVolumeBakingWindow.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeVolumeBakingWindow.cs @@ -39,20 +39,24 @@ static class Styles public static readonly Texture probeVolumeIcon = EditorGUIUtility.IconContent("LightProbeGroup Icon").image; // For now it's not the correct icon, we need to request it public static readonly Texture debugIcon = EditorGUIUtility.IconContent("DebuggerEnabled").image; - public static readonly GUIContent sceneLightingSettings = new GUIContent("Light Settings In Use", EditorGUIUtility.IconContent("LightingSettings Icon").image); - public static readonly GUIContent activeScenarioLabel = new GUIContent("Active Scenario", EditorGUIUtility.IconContent("FilterSelectedOnly").image); + public static readonly GUIContent sceneLightingSettings = new GUIContent("Active Lighting Settings", EditorGUIUtility.IconContent("LightingSettings Icon").image, "Lighting Settings used for all Scenes in this Baking Set"); + public static readonly GUIContent activeScenarioLabel = new GUIContent("Active Scenario", EditorGUIUtility.IconContent("FilterSelectedOnly").image, "The currently active lighting Scenario."); public static readonly GUIContent sceneNotFound = new GUIContent("Scene Not Found!", Styles.sceneIcon); public static readonly GUIContent bakingSetsTitle = new GUIContent("Baking Sets"); public static readonly GUIContent debugButton = new GUIContent(Styles.debugIcon); public static readonly GUIContent stats = new GUIContent("Stats"); - public static readonly GUIContent scenarioCostStat = new GUIContent("Active Scenario Size On Disk", "Size on disk used by the baked data of the currently selected lighting scenario."); - public static readonly GUIContent totalCostStat = new GUIContent("Baking Set Total Size On Disk", "Size on disk used by baked data of all lighting scenarios of the set."); + public static readonly GUIContent scenarioCostStat = new GUIContent("Scenario Size", "Size of the current Scenario's lighting data."); + public static readonly GUIContent totalCostStat = new GUIContent("Baking Set Size", "Size of the lighting data for all Scenarios in this Baking Set."); public static readonly GUIContent invalidLabel = new GUIContent("Out of Date"); public static readonly GUIContent emptyLabel = new GUIContent("Not Baked"); public static readonly GUIContent notLoadedLabel = new GUIContent("Set is not Loaded"); public static readonly GUIContent[] scenariosStatusLabel = new GUIContent[] { GUIContent.none, notLoadedLabel, invalidLabel, emptyLabel }; + + public static readonly GUIContent loadScenesButton = new GUIContent("Load All Scenes In Set", "Load all of the Scenes in this Baking Set."); + public static readonly GUIContent clearButton = new GUIContent("Clear Baked Data", "Clear baked lighting data for all loaded Scenes."); + public static readonly GUIStyle labelRed = "CN StatusError"; public static readonly GUIStyle boldFoldout = new GUIStyle(EditorStyles.foldout) { fontStyle = FontStyle.Bold }; @@ -222,10 +226,10 @@ void InitializeBakingSetList() { if (m_BakingSets.count == 1) { - EditorUtility.DisplayDialog("Can't delete baking set", "You can't delete the last Baking set. You need to have at least one.", "Ok"); + EditorUtility.DisplayDialog("Cannot delete this Baking Set", "Unable to delete. Projects must contain at least one Baking Set.", "Ok"); return; } - if (EditorUtility.DisplayDialog("Delete the selected baking set?", $"Deleting the baking set will also delete it's profile asset on disk.\nDo you really want to delete the baking set '{sceneData.bakingSets[list.index].name}'?\n\nYou cannot undo the delete assets action.", "Yes", "Cancel")) + if (EditorUtility.DisplayDialog("Delete this Baking Set and associated asset on disk?", $"Deleting the baking set will also delete it's profile asset on disk.\nDo you really want to delete the baking set '{sceneData.bakingSets[list.index].name}'?\n\nYou cannot undo the delete assets action.", "Yes", "Cancel")) { var pathToDelete = AssetDatabase.GetAssetPath(sceneData.bakingSets[list.index].profile); if (!String.IsNullOrEmpty(pathToDelete)) @@ -801,13 +805,13 @@ void DelayCreateAsset() EditorGUILayout.LabelField(Styles.totalCostStat, EditorGUIUtility.TrTextContent((sharedCost / (float)(1000 * 1000)).ToString("F1") + " MB")); } else - EditorGUILayout.HelpBox("Somes scenes of the set are not currently loaded. Stats can't be displayed", MessageType.Info); + EditorGUILayout.HelpBox("Cannot display statistics because not all Scenes in this Set are loaded.", MessageType.Info); EditorGUI.indentLevel--; } } else { - EditorGUILayout.HelpBox("You need to assign at least one scene with probe volumes to configure the baking settings", MessageType.Error, true); + EditorGUILayout.HelpBox("Add a Probe Volume to a Scene in this Baking Set to configure these settings.", MessageType.Error, true); } EditorGUILayout.EndScrollView(); @@ -868,9 +872,9 @@ void DrawBakeButton() EditorGUILayout.BeginHorizontal(); EditorGUI.BeginDisabledGroup(Lightmapping.isRunning); - if (GUILayout.Button("Load All Scenes In Set", GUILayout.ExpandWidth(true))) + if (GUILayout.Button(Styles.loadScenesButton, GUILayout.ExpandWidth(true))) LoadScenesInBakingSet(GetCurrentBakingSet()); - if (GUILayout.Button("Clear Loaded Scenes Data")) + if (GUILayout.Button(Styles.clearButton)) Lightmapping.Clear(); EditorGUI.EndDisabledGroup(); if (Lightmapping.isRunning) @@ -881,7 +885,7 @@ void DrawBakeButton() else { if (ButtonWithDropdownList(k_GenerateLighting, k_BakeOptionsText, BakeButtonCallback)) - BakeButtonCallback(0); + BakeButtonCallback(1); // By default we bake only loaded scene. } EditorGUILayout.EndHorizontal(); } diff --git a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeVolumeUI.Drawer.cs b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeVolumeUI.Drawer.cs index 28a1560e8f1..c82cd242db3 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeVolumeUI.Drawer.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeVolumeUI.Drawer.cs @@ -23,11 +23,11 @@ static void Drawer_BakeToolBar(SerializedProbeVolume serialized, Editor owner) GIContributors.ContributorFilter? filter = null; EditorGUI.BeginDisabledGroup(pv.globalVolume); - if (GUILayout.Button(EditorGUIUtility.TrTextContent("Fit to all Scenes", "Fits the Probe Volume's boundary to all open Scenes"), EditorStyles.miniButton)) + if (GUILayout.Button(EditorGUIUtility.TrTextContent("Fit to All Scenes", "Fit this Probe Volume to cover all loaded Scenes. "), EditorStyles.miniButton)) filter = GIContributors.ContributorFilter.All; - if (GUILayout.Button(EditorGUIUtility.TrTextContent("Fit to Scene", "Fits the Probe Volume's boundary to the Scene it belongs to."), EditorStyles.miniButton)) + if (GUILayout.Button(EditorGUIUtility.TrTextContent("Fit to Scene", "Fit this Probe Volume to the selected renderers in the selected Scene. Lock the Inspector to make additional selections."), EditorStyles.miniButton)) filter = GIContributors.ContributorFilter.Scene; - if (GUILayout.Button(EditorGUIUtility.TrTextContent("Fit to Selection", "Fits the Probe Volume's boundary to the selected GameObjects. Lock the Probe Volume's Inspector to allow for the selection of other GameObjects."), EditorStyles.miniButton)) + if (GUILayout.Button(EditorGUIUtility.TrTextContent("Fit to Selection", "Fits the Probe Volume to the selected renderer(s). Lock the Inspector to make additional selections."), EditorStyles.miniButton)) filter = GIContributors.ContributorFilter.Selection; EditorGUI.EndDisabledGroup(); diff --git a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeVolumeUI.Skin.cs b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeVolumeUI.Skin.cs index 3f2992f44b9..2caa25ae1cc 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeVolumeUI.Skin.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeVolumeUI.Skin.cs @@ -6,16 +6,16 @@ static partial class ProbeVolumeUI { internal static class Styles { - internal static readonly GUIContent s_Size = new GUIContent("Size", "Modify the size of this Probe Volume. This is independent of the Transform's Scale."); - internal static readonly GUIContent s_GlobalVolume = new GUIContent("Global", "If the volume is marked as global, it will be fit to the scene content every time the scene is saved or the baking starts."); + internal static readonly GUIContent s_Size = new GUIContent("Size", "Modify the size of this Probe Volume. This is unaffected by the GameObject's Transform's Scale property."); + internal static readonly GUIContent s_GlobalVolume = new GUIContent("Global", "When set to Global this Probe Volume considers all renderers with Contribute Global Illumination enabled. This list updates every time the Scene is saved or the lighting is baked."); internal static readonly GUIContent s_OverridesSubdivision = new GUIContent("Override Subdivision Levels", "Whether to override or not the subdivision levels."); internal static readonly GUIContent s_HighestSubdivLevel = new GUIContent("Highest Subdivision Level", "Overrides the highest subdivision level used by the system. This determines how finely a probe volume is subdivided, lower values means larger minimum distance between probes."); internal static readonly GUIContent s_LowestSubdivLevel = new GUIContent("Lowest Subdivision Level", "Overrides the lowest subdivision level used by the system. This determines how coarsely a probe volume is allowed to be subdivided, higher values means smaller maximum distance between probes."); - internal static readonly GUIContent s_ObjectLayerMask = new GUIContent("Layer Mask", "Control which layers will be used to select the meshes for the probe placement algorithm."); - internal static readonly GUIContent s_MinRendererVolumeSize = new GUIContent("Min Volume Size", "Specifies the minimum bounding box volume of renderers to consider placing probes around."); - internal static readonly GUIContent s_OverrideRendererFilters = new GUIContent("Override Renderer Filters", "Overrides the filters used to select renderers for the probe placement."); - internal static readonly GUIContent s_DistanceBetweenProbes = new GUIContent("Distance Between Probes", "Overrides the number of simplification levels set in the Probe Volume Settings window. Can not exceed the global maximum value."); - internal static readonly string s_ProbeVolumeChangedMessage = "The probe volume has changed since last baking or the data was never baked.\nPlease bake lighting in the lighting panel to update the lighting data."; + internal static readonly GUIContent s_ObjectLayerMask = new GUIContent("Layer Mask", "Specify Layers to consider during probe placement."); + internal static readonly GUIContent s_MinRendererVolumeSize = new GUIContent("Override Min Renderer Size", "Specify the smallest renderer size to consider during probe placement, in meters."); + internal static readonly GUIContent s_OverrideRendererFilters = new GUIContent("Override Renderer Filters", "Overrides the Renderer Filters that determine which renderers influence probe placement."); + internal static readonly GUIContent s_DistanceBetweenProbes = new GUIContent("Override Probe Spacing", "Overrides the global Probe Spacing specified in the Probe Volume Settings window. Can not exceed the maximum set there."); + internal static readonly string s_ProbeVolumeChangedMessage = "This Probe Volume has never been baked, or has changed since the last bake. Generate Lighting from the Lighting Window."; internal static readonly Color k_GizmoColorBase = new Color32(137, 222, 144, 255); diff --git a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/SerializedProbeTouchupVolume.cs b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/SerializedProbeTouchupVolume.cs index 6b2f7025267..e5049efd330 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/SerializedProbeTouchupVolume.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/SerializedProbeTouchupVolume.cs @@ -2,11 +2,17 @@ namespace UnityEditor.Rendering { internal class SerializedProbeTouchupVolume { + internal SerializedProperty shape; internal SerializedProperty size; + internal SerializedProperty radius; + + internal SerializedProperty mode; internal SerializedProperty intensityScale; - internal SerializedProperty invalidateProbes; - internal SerializedProperty overrideDilationThreshold; internal SerializedProperty overriddenDilationThreshold; + internal SerializedProperty virtualOffsetRotation; + internal SerializedProperty virtualOffsetDistance; + internal SerializedProperty geometryBias; + internal SerializedProperty rayOriginBias; internal SerializedObject serializedObject; @@ -14,11 +20,17 @@ internal SerializedProbeTouchupVolume(SerializedObject obj) { serializedObject = obj; + shape = serializedObject.FindProperty("shape"); size = serializedObject.FindProperty("size"); + radius = serializedObject.FindProperty("radius"); + + mode = serializedObject.FindProperty("mode"); intensityScale = serializedObject.FindProperty("intensityScale"); - invalidateProbes = serializedObject.FindProperty("invalidateProbes"); - overrideDilationThreshold = serializedObject.FindProperty("overrideDilationThreshold"); overriddenDilationThreshold = serializedObject.FindProperty("overriddenDilationThreshold"); + virtualOffsetRotation = serializedObject.FindProperty("virtualOffsetRotation"); + virtualOffsetDistance = serializedObject.FindProperty("virtualOffsetDistance"); + geometryBias = serializedObject.FindProperty("geometryBias"); + rayOriginBias = serializedObject.FindProperty("rayOriginBias"); } internal void Apply() diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Common/CoreProfileId.cs b/Packages/com.unity.render-pipelines.core/Runtime/Common/CoreProfileId.cs index 1275e3aad20..c6f49e7c1cf 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Common/CoreProfileId.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Common/CoreProfileId.cs @@ -5,5 +5,6 @@ internal enum CoreProfileId BlitTextureInPotAtlas, APVCellStreamingUpdate, APVScenarioBlendingUpdate, + APVIndexDefragUpdate } } diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Common/DynamicArray.cs b/Packages/com.unity.render-pipelines.core/Runtime/Common/DynamicArray.cs index 2983cb0f2b0..c0b0fcc3d8d 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Common/DynamicArray.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Common/DynamicArray.cs @@ -517,6 +517,14 @@ internal void BumpVersion() version++; #endif } + + /// + /// Delegate for custom sorting comparison. + /// + /// First object. + /// Second object. + /// -1 if x smaller than y, 1 if x bigger than y and 0 otherwise. + public delegate int SortComparer(T x, T y); } /// @@ -577,6 +585,62 @@ public static class DynamicArrayExtensions } } + // C# SUCKS + // Had to copy paste because it's apparently impossible to pass a sort delegate where T is Comparable, otherwise some boxing happens and allocates... + // So two identical versions of the function, one with delegate but no Comparable and the other with just the comparable. + static int Partition(T[] data, int left, int right, DynamicArray.SortComparer comparer) where T : new() + { + var pivot = data[left]; + + --left; + ++right; + while (true) + { + var c = 0; + var lvalue = default(T); + do + { + ++left; + lvalue = data[left]; + c = comparer(lvalue, pivot); + } + while (c < 0); + + var rvalue = default(T); + do + { + --right; + rvalue = data[right]; + c = comparer(rvalue, pivot); + } + while (c > 0); + + if (left < right) + { + data[right] = lvalue; + data[left] = rvalue; + } + else + { + return right; + } + } + } + + static void QuickSort(T[] data, int left, int right, DynamicArray.SortComparer comparer) where T : new() + { + if (left < right) + { + int pivot = Partition(data, left, right, comparer); + + if (pivot >= 1) + QuickSort(data, left, pivot, comparer); + + if (pivot + 1 < right) + QuickSort(data, pivot + 1, right, comparer); + } + } + /// /// Perform a quick sort on the DynamicArray /// @@ -587,5 +651,17 @@ public static class DynamicArrayExtensions QuickSort(array, 0, array.size - 1); array.BumpVersion(); } + + /// + /// Perform a quick sort on the DynamicArray + /// + /// Type of the array. + /// Array on which to perform the quick sort. + /// Comparer used for sorting. + public static void QuickSort(this DynamicArray array, DynamicArray.SortComparer comparer) where T : new() + { + QuickSort(array, 0, array.size - 1, comparer); + array.BumpVersion(); + } } } diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Debugging/DebugOverlay.cs b/Packages/com.unity.render-pipelines.core/Runtime/Debugging/DebugOverlay.cs new file mode 100644 index 00000000000..fabb40de704 --- /dev/null +++ b/Packages/com.unity.render-pipelines.core/Runtime/Debugging/DebugOverlay.cs @@ -0,0 +1,66 @@ +namespace UnityEngine.Rendering +{ + /// + /// Utility class for debug overlay coordinates. + /// + public class DebugOverlay + { + /// Current x coordinate. + public int x { get; private set; } + /// Current y coordinate. + public int y { get; private set; } + /// Current overlay size. + public int overlaySize { get; private set; } + + int m_InitialPositionX; + int m_ScreenWidth; + + /// + /// Start rendering overlay. + /// + /// Initial x position. + /// Initial y position. + /// Size of overlays between 0 and 1. + /// Width of the screen. + public void StartOverlay(int initialX, int initialY, int overlaySize, int screenWidth) + { + x = initialX; + y = initialY; + this.overlaySize = overlaySize; + + m_InitialPositionX = initialX; + m_ScreenWidth = screenWidth; + } + + /// + /// Increment coordinates to the next overlay and return the current overlay rect. + /// + /// Aspect of the current overlay. + /// Returns a rect of the current overlay. + public Rect Next(float aspect = 1.0f) + { + int overlayWidth = (int)(overlaySize * aspect); + + if ((x + overlayWidth) > m_ScreenWidth && x > m_InitialPositionX) + { + x = m_InitialPositionX; + y -= overlaySize; + } + + Rect rect = new Rect(x, y, overlayWidth, overlaySize); + + x += overlayWidth; + + return rect; + } + + /// + /// Setup the viewport for the current overlay. + /// + /// Command buffer used to setup viewport. + public void SetViewport(CommandBuffer cmd) + { + cmd.SetViewport(new Rect(x, y, overlaySize, overlaySize)); + } + } +} diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Debugging/DebugOverlay.cs.meta b/Packages/com.unity.render-pipelines.core/Runtime/Debugging/DebugOverlay.cs.meta new file mode 100644 index 00000000000..3670ce4e327 --- /dev/null +++ b/Packages/com.unity.render-pipelines.core/Runtime/Debugging/DebugOverlay.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 01796373c956d2c40b09d1e150c2a2bd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeBrickIndex.cs b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeBrickIndex.cs index c1130fd58de..806d818a059 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeBrickIndex.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeBrickIndex.cs @@ -17,22 +17,32 @@ internal class ProbeBrickIndex internal const int kMaxSubdivisionLevels = 7; // 3 bits internal const int kIndexChunkSize = 243; + internal const int kFailChunkIndex = -1; + internal const int kEmptyIndex = -2; // This is a tag value used to say that we have a valid entry but with no data. + + BitArray m_IndexChunks; - int m_IndexInChunks; - int m_NextFreeChunk; + BitArray m_IndexChunksCopyForChecks; + + int m_ChunksCount; int m_AvailableChunkCount; ComputeBuffer m_PhysicalIndexBuffer; int[] m_PhysicalIndexBufferData; + ComputeBuffer m_DebugFragmentationBuffer; + int[] m_DebugFragmentationData; internal int estimatedVMemCost { get; private set; } + internal ComputeBuffer GetDebugFragmentationBuffer() => m_DebugFragmentationBuffer; + internal float fragmentationRate { get; private set; } + [DebuggerDisplay("Brick [{position}, {subdivisionLevel}]")] [Serializable] public struct Brick : IEquatable { - public Vector3Int position; // refspace index, indices are cell coordinates at max resolution + public Vector3Int position; // refspace index, indices are brick coordinates at max resolution public int subdivisionLevel; // size as factor covered elementary cells internal Brick(Vector3Int position, int subdivisionLevel) @@ -42,6 +52,21 @@ internal Brick(Vector3Int position, int subdivisionLevel) } public bool Equals(Brick other) => position == other.position && subdivisionLevel == other.subdivisionLevel; + + // Important boundInBricks needs to be in min brick size so we can be agnostic of profile information. + public bool IntersectArea(Bounds boundInBricksToCheck) + { + int sizeInMinBricks = ProbeReferenceVolume.CellSize(subdivisionLevel); + Bounds brickBounds = new Bounds(); + brickBounds.min = position; + brickBounds.max = position + new Vector3Int(sizeInMinBricks, sizeInMinBricks, sizeInMinBricks); + + brickBounds.extents *= 0.99f; // Extend a bit to avoid issues. + + bool intersectionHappens = boundInBricksToCheck.Intersects(brickBounds); + + return intersectionHappens; + } } [DebuggerDisplay("Brick [{brick.position}, {brick.subdivisionLevel}], {flattenedIdx}")] @@ -104,13 +129,13 @@ int SizeOfPhysicalIndexFromBudget(ProbeVolumeTextureMemoryBudget memoryBudget) { case ProbeVolumeTextureMemoryBudget.MemoryBudgetLow: // 16 MB - 4 million of bricks worth of space. At full resolution and a distance of 1 meter between probes, this is roughly 474 * 474 * 474 meters worth of bricks. If 0.25x on Y axis, this is equivalent to 948 * 118 * 948 meters - return 16000000; + return 4000000; case ProbeVolumeTextureMemoryBudget.MemoryBudgetMedium: // 32 MB - 8 million of bricks worth of space. At full resolution and a distance of 1 meter between probes, this is roughly 600 * 600 * 600 meters worth of bricks. If 0.25x on Y axis, this is equivalent to 1200 * 150 * 1200 meters - return 32000000; + return 8000000; case ProbeVolumeTextureMemoryBudget.MemoryBudgetHigh: // 64 MB - 16 million of bricks worth of space. At full resolution and a distance of 1 meter between probes, this is roughly 756 * 756 * 756 meters worth of bricks. If 0.25x on Y axis, this is equivalent to 1512 * 184 * 1512 meters - return 64000000; + return 16000000; } return 32000000; } @@ -125,13 +150,14 @@ internal ProbeBrickIndex(ProbeVolumeTextureMemoryBudget memoryBudget) m_NeedUpdateIndexComputeBuffer = false; - m_IndexInChunks = Mathf.CeilToInt((float)SizeOfPhysicalIndexFromBudget(memoryBudget) / kIndexChunkSize); - m_AvailableChunkCount = m_IndexInChunks; - m_IndexChunks = new BitArray(Mathf.Max(1, m_IndexInChunks)); - int physicalBufferSize = m_IndexInChunks * kIndexChunkSize; + m_ChunksCount = Mathf.Max(1, Mathf.CeilToInt((float)SizeOfPhysicalIndexFromBudget(memoryBudget) / kIndexChunkSize)); + m_AvailableChunkCount = m_ChunksCount; + m_IndexChunks = new BitArray(m_ChunksCount); + m_IndexChunksCopyForChecks = new BitArray(m_ChunksCount); + + int physicalBufferSize = m_ChunksCount * kIndexChunkSize; m_PhysicalIndexBufferData = new int[physicalBufferSize]; m_PhysicalIndexBuffer = new ComputeBuffer(physicalBufferSize, sizeof(int), ComputeBufferType.Structured); - m_NextFreeChunk = 0; estimatedVMemCost = physicalBufferSize * sizeof(int); @@ -156,6 +182,23 @@ internal void UploadIndexData() m_UpdateMinIndex = int.MaxValue; } + void UpdateDebugData() + { + if (m_DebugFragmentationData == null || m_DebugFragmentationData.Length != m_IndexChunks.Length) + { + m_DebugFragmentationData = new int[m_IndexChunks.Length]; + CoreUtils.SafeRelease(m_DebugFragmentationBuffer); + m_DebugFragmentationBuffer = new ComputeBuffer(m_IndexChunks.Length, 4); + } + + for (int i = 0; i < m_IndexChunks.Length; ++i) + { + m_DebugFragmentationData[i] = m_IndexChunks[i] ? 1 : -1; + } + + m_DebugFragmentationBuffer.SetData(m_DebugFragmentationData); + } + internal void Clear() { Profiler.BeginSample("Clear Index"); @@ -167,7 +210,6 @@ internal void Clear() m_UpdateMinIndex = 0; m_UpdateMaxIndex = m_PhysicalIndexBufferData.Length - 1; - m_NextFreeChunk = 0; m_IndexChunks.SetAll(false); foreach (var value in m_VoxelToBricks.Values) @@ -182,6 +224,8 @@ internal void Clear() m_BrickMetaPool.Release(value); m_BricksToVoxels.Clear(); + m_AvailableChunkCount = m_ChunksCount; + Profiler.EndSample(); } @@ -210,20 +254,35 @@ void MapBrickToVoxels(ProbeBrickIndex.Brick brick, HashSet voxels) } } - void ClearVoxel(Vector3Int pos, CellIndexUpdateInfo cellInfo) + void ClearVoxel(Vector3Int pos, IndirectionEntryUpdateInfo entryInfo) { Vector3Int vx_min, vx_max; - ClipToIndexSpace(pos, GetVoxelSubdivLevel(), out vx_min, out vx_max, cellInfo); - UpdatePhysicalIndex(vx_min, vx_max, -1, cellInfo); + ClipToIndexSpace(pos, GetVoxelSubdivLevel(), out vx_min, out vx_max, entryInfo); + + var brickMin = vx_min - entryInfo.entryPositionInBricksAtMaxRes; + var brickMax = vx_max - entryInfo.entryPositionInBricksAtMaxRes; + brickMin /= ProbeReferenceVolume.CellSize(entryInfo.minSubdivInCell); + brickMax /= ProbeReferenceVolume.CellSize(entryInfo.minSubdivInCell); + + Debug.Assert(brickMin.x >= 0 && brickMin.y >= 0 && brickMin.z >= 0 && brickMax.x >= 0 && brickMax.y >= 0 && brickMax.z >= 0); + + UpdatePhysicalIndex(vx_min, vx_max, -1, entryInfo); } internal void GetRuntimeResources(ref ProbeReferenceVolume.RuntimeResources rr) { + bool displayFrag = ProbeReferenceVolume.instance.probeVolumeDebug.displayIndexFragmentation; // If we are pending an update of the actual compute buffer we do it here if (m_NeedUpdateIndexComputeBuffer) { UploadIndexData(); + if (displayFrag) + UpdateDebugData(); } + + if (displayFrag && m_DebugFragmentationBuffer == null) + UpdateDebugData(); + rr.index = m_PhysicalIndexBuffer; } @@ -231,10 +290,31 @@ internal void Cleanup() { CoreUtils.SafeRelease(m_PhysicalIndexBuffer); m_PhysicalIndexBuffer = null; + CoreUtils.SafeRelease(m_DebugFragmentationBuffer); + m_DebugFragmentationBuffer = null; } - public struct CellIndexUpdateInfo + internal void ComputeFragmentationRate() { + // Clearly suboptimal, will need to be profiled before trying to make it smarter. + int highestAllocatedChunk = 0; + for (int i = m_ChunksCount - 1; i >= 0; i--) + { + if (m_IndexChunks[i]) + { + highestAllocatedChunk = i + 1; + break; + } + } + + int tailFreeChunks = m_ChunksCount - highestAllocatedChunk; + int holes = m_AvailableChunkCount - tailFreeChunks; + fragmentationRate = (float)holes / highestAllocatedChunk; + } + + public struct IndirectionEntryUpdateInfo + { + public int brickCount; public int firstChunkIndex; public int numberOfChunks; public int minSubdivInCell; @@ -242,7 +322,24 @@ public struct CellIndexUpdateInfo // The map to the lower possible resolution is done after. However they are still in local space. public Vector3Int minValidBrickIndexForCellAtMaxRes; public Vector3Int maxValidBrickIndexForCellAtMaxResPlusOne; - public Vector3Int cellPositionInBricksAtMaxRes; + public Vector3Int entryPositionInBricksAtMaxRes; + + public bool hasOnlyBiggerBricks; // True if it has only bricks that are bigger than the entry itself + } + + public struct CellIndexUpdateInfo + { + public IndirectionEntryUpdateInfo[] entriesInfo; + + public int GetNumberOfChunks() + { + int chunkCount = 0; + foreach (var entry in entriesInfo) + { + chunkCount += entry.numberOfChunks; + } + return chunkCount; + } } int MergeIndex(int index, int size) @@ -252,59 +349,94 @@ int MergeIndex(int index, int size) return (index & ~(mask << shift)) | ((size & mask) << shift); } - internal bool AssignIndexChunksToCell(int bricksCount, ref CellIndexUpdateInfo cellUpdateInfo, bool ignoreErrorLog) + internal int GetNumberOfChunks(int brickCount) + { + return Mathf.CeilToInt((float)brickCount / kIndexChunkSize); + } + + internal bool FindSlotsForEntries(ref IndirectionEntryUpdateInfo[] entriesInfo) { - // We need to better handle the case where the chunks are full, this is where streaming will need to come into place swapping in/out - // Also the current way to find an empty spot might be sub-optimal, when streaming is in place it'd be nice to have this more efficient - // if it is meant to happen frequently. + int numberOfEntries = entriesInfo.Length; + for (int entry = 0; entry < numberOfEntries; ++entry) + { + entriesInfo[entry].firstChunkIndex = (entriesInfo[entry].numberOfChunks > 0) ? kFailChunkIndex : kEmptyIndex; + } - int numberOfChunks = Mathf.CeilToInt((float)bricksCount / kIndexChunkSize); + // This is not great, but the alternative is making the always in memory m_IndexChunks bigger. + // The other alternative is to temporary mark m_IndexChunks and unmark, but that is going to be slower. + // The copy here is temporary and while it is created upon loading all the time, it is going to occupy mnemory + // only when a load operation happens. - // Search for the first empty element with enough space. - int firstValidChunk = -1; - for (int i = 0; i < m_IndexInChunks; ++i) + m_IndexChunksCopyForChecks.SetAll(false); + m_IndexChunksCopyForChecks.Or(m_IndexChunks); + + for (int entry = 0; entry < numberOfEntries; ++entry) { - if (!m_IndexChunks[i] && (i + numberOfChunks) < m_IndexInChunks) + int numberOfChunksForEntry = entriesInfo[entry].numberOfChunks; + if (numberOfChunksForEntry == 0) continue; + + + for (int i = 0; i < m_ChunksCount; ++i) { - int emptySlotsStartingHere = 0; - for (int k = i; k < (i + numberOfChunks); ++k) + if (!m_IndexChunksCopyForChecks[i] && (i + numberOfChunksForEntry) < m_ChunksCount) { - if (!m_IndexChunks[k]) emptySlotsStartingHere++; - else break; + int emptySlotsStartingHere = 0; + for (int k = i; k < (i + numberOfChunksForEntry); ++k) + { + if (!m_IndexChunksCopyForChecks[k]) emptySlotsStartingHere++; + else break; + } + + if (emptySlotsStartingHere == numberOfChunksForEntry) + { + entriesInfo[entry].firstChunkIndex = i; + break; + } } + } - if (emptySlotsStartingHere == numberOfChunks) + if (entriesInfo[entry].firstChunkIndex < 0) + return false; + else // We need to markup the copy. + { + for (int i = entriesInfo[entry].firstChunkIndex; i < (entriesInfo[entry].firstChunkIndex + numberOfChunksForEntry); ++i) { - firstValidChunk = i; - break; + Debug.Assert(!m_IndexChunksCopyForChecks[i]); + m_IndexChunksCopyForChecks[i] = true; } } } - if (firstValidChunk < 0) - { - // During baking we know we can hit this when trying to do dilation of all cells at the same time. - // That can happen because we try to load all cells at the same time. If the budget is not high enough it will fail. - // In this case we'll iterate separately on each cell and their neighbors. - // If so, we don't want controlled error message spam during baking so we ignore it. - // In theory this should never happen with proper streaming/defrag but we keep the message just in case otherwise. - if (!ignoreErrorLog) - Debug.LogError("APV Index Allocation failed."); - return false; - } + return true; + } - // This assert will need to go away or do something else when streaming is allowed (we need to find holes in available chunks or stream out stuff) - cellUpdateInfo.firstChunkIndex = firstValidChunk; - cellUpdateInfo.numberOfChunks = numberOfChunks; - for (int i = firstValidChunk; i < (firstValidChunk + numberOfChunks); ++i) + internal bool ReserveChunks(IndirectionEntryUpdateInfo[] entriesInfo, bool ignoreErrorLog) + { + int entryCount = entriesInfo.Length; + // Sanity check that shouldn't be needed. + for (int entry = 0; entry < entryCount; ++entry) { - Debug.Assert(!m_IndexChunks[i]); - m_IndexChunks[i] = true; - } + int firstChunkForEntry = entriesInfo[entry].firstChunkIndex; + int numberOfChunkForEntry = entriesInfo[entry].numberOfChunks; + + if (numberOfChunkForEntry == 0) continue; - m_NextFreeChunk += Mathf.Max(0, (firstValidChunk + numberOfChunks) - m_NextFreeChunk); + if (firstChunkForEntry < 0) + { + if (!ignoreErrorLog) + Debug.LogError("APV Index Allocation failed."); - m_AvailableChunkCount -= numberOfChunks; + return false; + } + + for (int i = firstChunkForEntry; i < (firstChunkForEntry + numberOfChunkForEntry); ++i) + { + Debug.Assert(!m_IndexChunks[i]); + m_IndexChunks[i] = true; + } + + m_AvailableChunkCount -= numberOfChunkForEntry; + } return true; } @@ -318,7 +450,8 @@ public void AddBricks(Cell cell, NativeArray bricks, List allocati // create a new copy BrickMeta bm = m_BrickMetaPool.Get(); - m_BricksToVoxels.Add(cell, bm); + //if (!m_BricksToVoxels.ContainsKey(cell)) + m_BricksToVoxels.Add(cell, bm); int brick_idx = 0; // find all voxels each brick will touch @@ -371,7 +504,10 @@ public void AddBricks(Cell cell, NativeArray bricks, List allocati foreach (var voxel in bm.voxels) { - UpdateIndexForVoxel(voxel, cellInfo); + foreach (var entryInfo in cellInfo.entriesInfo) + { + UpdateIndexForVoxel(voxel, entryInfo); + } } } @@ -393,15 +529,22 @@ public void RemoveBricks(CellInfo cellInfo) { m_VoxelMetaPool.Release(vm_list[idx]); vm_list.RemoveAt(idx); - if (vm_list.Count > 0) - { - UpdateIndexForVoxel(v, cellUpdateInfo); - } - else + + // Loop through entries. + foreach (var entryInfo in cellInfo.updateInfo.entriesInfo) { - ClearVoxel(v, cellUpdateInfo); - m_VoxelMetaListPool.Release(vm_list); - m_VoxelToBricks.Remove(v); + if (entryInfo.brickCount == 0) continue; + + if (vm_list.Count > 0) + { + UpdateIndexForVoxel(v, entryInfo); + } + else + { + ClearVoxel(v, entryInfo); + m_VoxelMetaListPool.Release(vm_list); + m_VoxelToBricks.Remove(v); + } } } } @@ -409,49 +552,69 @@ public void RemoveBricks(CellInfo cellInfo) m_BricksToVoxels.Remove(cellInfo.cell); // Clear allocated chunks - for (int i = cellUpdateInfo.firstChunkIndex; i < (cellUpdateInfo.firstChunkIndex + cellUpdateInfo.numberOfChunks); ++i) + foreach (var entryInfo in cellInfo.updateInfo.entriesInfo) { - m_IndexChunks[i] = false; + for (int i = entryInfo.firstChunkIndex; i < (entryInfo.firstChunkIndex + entryInfo.numberOfChunks); ++i) + { + m_IndexChunks[i] = false; + } + m_AvailableChunkCount += entryInfo.numberOfChunks; } - m_AvailableChunkCount += cellUpdateInfo.numberOfChunks; } - void UpdateIndexForVoxel(Vector3Int voxel, CellIndexUpdateInfo cellInfo) + void UpdateIndexForVoxel(Vector3Int voxel, IndirectionEntryUpdateInfo entryInfo) { - ClearVoxel(voxel, cellInfo); + if (entryInfo.brickCount == 0) return; + + ClearVoxel(voxel, entryInfo); List vm_list = m_VoxelToBricks[voxel]; foreach (var vm in vm_list) { // get the list of bricks and indices List bricks = m_BricksToVoxels[vm.cell].bricks; List indcs = vm.brickIndices; - UpdateIndexForVoxel(voxel, bricks, indcs, cellInfo); + UpdateIndexForVoxel(voxel, bricks, indcs, entryInfo); } } - void UpdatePhysicalIndex(Vector3Int brickMin, Vector3Int brickMax, int value, CellIndexUpdateInfo cellInfo) + void UpdatePhysicalIndex(Vector3Int brickMin, Vector3Int brickMax, int value, IndirectionEntryUpdateInfo entryInfo) { + // An indirection entry might have only a single brick that is actually bigger than the entry itself. This is a bit of simpler use case + // that doesn't fit what happens otherwise in this function where the assumption is that minSubdivInCell is equal or less the size of the entry. + // In this special case, we can do things much simpler as we *know* by construction that we will always have only a single relevant brick + // and so we do the update in a simpler fashion. + if (entryInfo.hasOnlyBiggerBricks) + { + int singleEntry = entryInfo.firstChunkIndex * kIndexChunkSize; + m_UpdateMinIndex = Math.Min(m_UpdateMinIndex, singleEntry); + m_UpdateMaxIndex = Math.Max(m_UpdateMaxIndex, singleEntry); + m_PhysicalIndexBufferData[singleEntry] = value; + m_NeedUpdateIndexComputeBuffer = true; + + return; + } + // We need to do our calculations in local space to the cell, so we move the brick to local space as a first step. // Reminder that at this point we are still operating at highest resolution possible, not necessarily the one that will be // the final resolution for the chunk. - brickMin = brickMin - cellInfo.cellPositionInBricksAtMaxRes; - brickMax = brickMax - cellInfo.cellPositionInBricksAtMaxRes; + brickMin = brickMin - entryInfo.entryPositionInBricksAtMaxRes; + brickMax = brickMax - entryInfo.entryPositionInBricksAtMaxRes; // Since the index is spurious (not same resolution, but varying per cell) we need to bring to the output resolution the brick coordinates // Before finding the locations inside the Index for the current cell/chunk. - brickMin /= ProbeReferenceVolume.CellSize(cellInfo.minSubdivInCell); - brickMax /= ProbeReferenceVolume.CellSize(cellInfo.minSubdivInCell); + brickMin /= ProbeReferenceVolume.CellSize(entryInfo.minSubdivInCell); + brickMax /= ProbeReferenceVolume.CellSize(entryInfo.minSubdivInCell); // Verify we are actually in local space now. - int maxCellSizeInOutputRes = ProbeReferenceVolume.CellSize(ProbeReferenceVolume.instance.GetMaxSubdivision() - 1 - cellInfo.minSubdivInCell); + int maxCellSizeInOutputRes = ProbeReferenceVolume.CellSize(ProbeReferenceVolume.instance.GetEntrySubdivLevel() - entryInfo.minSubdivInCell); Debug.Assert(brickMin.x >= 0 && brickMin.y >= 0 && brickMin.z >= 0 && brickMax.x >= 0 && brickMax.y >= 0 && brickMax.z >= 0); - Debug.Assert(brickMin.x < maxCellSizeInOutputRes && brickMin.y < maxCellSizeInOutputRes && brickMin.z < maxCellSizeInOutputRes && brickMax.x <= maxCellSizeInOutputRes && brickMax.y <= maxCellSizeInOutputRes && brickMax.z <= maxCellSizeInOutputRes); + Debug.Assert(brickMin.x <= maxCellSizeInOutputRes && brickMin.y <= maxCellSizeInOutputRes && brickMin.z <= maxCellSizeInOutputRes && brickMax.x <= maxCellSizeInOutputRes && brickMax.y <= maxCellSizeInOutputRes && brickMax.z <= maxCellSizeInOutputRes); // We are now in the right resolution, but still not considering the valid area, so we need to still normalize against that. // To do so first let's move back the limits to the desired resolution - var cellMinIndex = cellInfo.minValidBrickIndexForCellAtMaxRes / ProbeReferenceVolume.CellSize(cellInfo.minSubdivInCell); - var cellMaxIndex = cellInfo.maxValidBrickIndexForCellAtMaxResPlusOne / ProbeReferenceVolume.CellSize(cellInfo.minSubdivInCell); + var cellMinIndex = entryInfo.minValidBrickIndexForCellAtMaxRes / ProbeReferenceVolume.CellSize(entryInfo.minSubdivInCell); + var cellMaxIndex = entryInfo.maxValidBrickIndexForCellAtMaxResPlusOne / ProbeReferenceVolume.CellSize(entryInfo.minSubdivInCell); // Then perform the rescale of the local indices for min and max. brickMin -= cellMinIndex; @@ -465,7 +628,7 @@ void UpdatePhysicalIndex(Vector3Int brickMin, Vector3Int brickMax, int value, Ce var size = (cellMaxIndex - cellMinIndex); // Analytically compute min and max because doing it in the inner loop with Math.Min/Max is costly (not inlined) - int chunkStart = cellInfo.firstChunkIndex * kIndexChunkSize; + int chunkStart = entryInfo.firstChunkIndex * kIndexChunkSize; int newMin = chunkStart + brickMin.z * (size.x * size.y) + brickMin.x * size.y + brickMin.y; int newMax = chunkStart + Math.Max(0, (brickMax.z - 1)) * (size.x * size.y) + Math.Max(0, (brickMax.x - 1)) * size.y + Math.Max(0, (brickMax.y - 1)); m_UpdateMinIndex = Math.Min(m_UpdateMinIndex, newMin); @@ -488,14 +651,14 @@ void UpdatePhysicalIndex(Vector3Int brickMin, Vector3Int brickMax, int value, Ce m_NeedUpdateIndexComputeBuffer = true; } - void ClipToIndexSpace(Vector3Int pos, int subdiv, out Vector3Int outMinpos, out Vector3Int outMaxpos, CellIndexUpdateInfo cellInfo) + void ClipToIndexSpace(Vector3Int pos, int subdiv, out Vector3Int outMinpos, out Vector3Int outMaxpos, IndirectionEntryUpdateInfo entryInfo) { // to relative coordinates int cellSize = ProbeReferenceVolume.CellSize(subdiv); // The position here is in global space, however we want to constraint this voxel update to the valid cell area - var minValidPosition = cellInfo.cellPositionInBricksAtMaxRes + cellInfo.minValidBrickIndexForCellAtMaxRes; - var maxValidPosition = cellInfo.cellPositionInBricksAtMaxRes + cellInfo.maxValidBrickIndexForCellAtMaxResPlusOne - Vector3Int.one; + var minValidPosition = entryInfo.entryPositionInBricksAtMaxRes + entryInfo.minValidBrickIndexForCellAtMaxRes; + var maxValidPosition = entryInfo.entryPositionInBricksAtMaxRes + entryInfo.maxValidBrickIndexForCellAtMaxResPlusOne - Vector3Int.one; int minpos_x = pos.x - m_CenterRS.x; int minpos_y = pos.y; @@ -504,22 +667,32 @@ void ClipToIndexSpace(Vector3Int pos, int subdiv, out Vector3Int outMinpos, out int maxpos_y = minpos_y + cellSize; int maxpos_z = minpos_z + cellSize; // clip to valid region - minpos_x = Mathf.Max(minpos_x, minValidPosition.x); - minpos_y = Mathf.Max(minpos_y, minValidPosition.y); - minpos_z = Mathf.Max(minpos_z, minValidPosition.z); - maxpos_x = Mathf.Min(maxpos_x, maxValidPosition.x); - maxpos_y = Mathf.Min(maxpos_y, maxValidPosition.y); - maxpos_z = Mathf.Min(maxpos_z, maxValidPosition.z); + minpos_x = Mathf.Clamp(minpos_x, minValidPosition.x, maxValidPosition.x); + minpos_y = Mathf.Clamp(minpos_y, minValidPosition.y, maxValidPosition.y); + minpos_z = Mathf.Clamp(minpos_z, minValidPosition.z, maxValidPosition.z); + maxpos_x = Mathf.Clamp(maxpos_x, minValidPosition.x, maxValidPosition.x); + maxpos_y = Mathf.Clamp(maxpos_y, minValidPosition.y, maxValidPosition.y); + maxpos_z = Mathf.Clamp(maxpos_z, minValidPosition.z, maxValidPosition.z); outMinpos = new Vector3Int(minpos_x, minpos_y, minpos_z); outMaxpos = new Vector3Int(maxpos_x, maxpos_y, maxpos_z); } - void UpdateIndexForVoxel(Vector3Int voxel, List bricks, List indices, CellIndexUpdateInfo cellInfo) + bool BrickOverlapEntry(Vector3Int brickMin, Vector3Int brickMax, Vector3Int entryMin, Vector3Int entryMax) + { + return brickMax.x >= entryMin.x && entryMax.x >= brickMin.x && + brickMax.y >= entryMin.y && entryMax.y >= brickMin.y && + brickMax.z >= entryMin.z && entryMax.z >= brickMin.z; + } + + void UpdateIndexForVoxel(Vector3Int voxel, List bricks, List indices, IndirectionEntryUpdateInfo entryInfo) { // clip voxel to index space Vector3Int vx_min, vx_max; - ClipToIndexSpace(voxel, GetVoxelSubdivLevel(), out vx_min, out vx_max, cellInfo); + ClipToIndexSpace(voxel, GetVoxelSubdivLevel(), out vx_min, out vx_max, entryInfo); + + var minEntryPosition = entryInfo.entryPositionInBricksAtMaxRes + entryInfo.minValidBrickIndexForCellAtMaxRes; + var maxEntryPosition = entryInfo.entryPositionInBricksAtMaxRes + entryInfo.maxValidBrickIndexForCellAtMaxResPlusOne - Vector3Int.one; foreach (var rbrick in bricks) { @@ -527,6 +700,10 @@ void UpdateIndexForVoxel(Vector3Int voxel, List bricks, List bricks, List outAllocat // In theory this should never happen with proper streaming/defrag but we keep the message just in case otherwise. if (!ignoreErrorLog) Debug.LogError("Cannot allocate more brick chunks, probe volume brick pool is full."); + + outAllocations.Clear(); return false; // failure case, pool is full } outAllocations.Add(m_NextFreeChunk); m_AvailableChunkCount--; - m_NextFreeChunk.x += kProbePoolChunkSizeInBricks * kBrickProbeCountPerDim; + m_NextFreeChunk.x += kChunkSizeInBricks * kBrickProbeCountPerDim; if (m_NextFreeChunk.x >= m_Pool.width) { m_NextFreeChunk.x = 0; @@ -204,7 +206,7 @@ internal void Update(DataLocation source, List srcLocations, Li for (int j = 0; j < kBrickProbeCountPerDim; j++) { - int width = Mathf.Min(kProbePoolChunkSizeInBricks * kBrickProbeCountPerDim, source.width - src.x); + int width = Mathf.Min(kChunkSizeInBricks * kBrickProbeCountPerDim, source.width - src.x); Graphics.CopyTexture(source.TexL0_L1rx, src.z + j, 0, src.x, src.y, width, kBrickProbeCountPerDim, m_Pool.TexL0_L1rx, dst.z + j, 0, dst.x, dst.y); Graphics.CopyTexture(source.TexL1_G_ry, src.z + j, 0, src.x, src.y, width, kBrickProbeCountPerDim, m_Pool.TexL1_G_ry, dst.z + j, 0, dst.x, dst.y); @@ -235,7 +237,7 @@ internal void UpdateValidity(DataLocation source, List srcLocat for (int j = 0; j < kBrickProbeCountPerDim; j++) { - int width = Mathf.Min(kProbePoolChunkSizeInBricks * kBrickProbeCountPerDim, source.width - src.x); + int width = Mathf.Min(kChunkSizeInBricks * kBrickProbeCountPerDim, source.width - src.x); Graphics.CopyTexture(source.TexValidity, src.z + j, 0, src.x, src.y, width, kBrickProbeCountPerDim, m_Pool.TexValidity, dst.z + j, 0, dst.x, dst.y); } } @@ -413,7 +415,6 @@ internal static void Initialize(in ProbeVolumeSystemParameters parameters) internal int GetPoolHeight() { return m_State0.m_Pool.height; } internal int GetPoolDepth() { return m_State0.m_Pool.depth; } - internal ProbeBrickBlendingPool(ProbeVolumeBlendingTextureMemoryBudget memoryBudget, ProbeVolumeSHBands shBands) { // Casting to other memory budget struct works cause it's casted to int in the end anyway diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeIndexOfIndices.cs b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeIndexOfIndices.cs index d870883affc..fa4593bde70 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeIndexOfIndices.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeIndexOfIndices.cs @@ -1,11 +1,16 @@ +using System.Collections.Generic; + namespace UnityEngine.Rendering { - internal class ProbeCellIndices + internal class ProbeGlobalIndirection { const int kUintPerEntry = 3; internal int estimatedVMemCost { get; private set; } + // IMPORTANT! IF THIS VALUE CHANGES DATA NEEDS TO BE REBAKED. + internal const int kEntryMaxSubdivLevel = 3; + internal struct IndexMetaData { static uint[] s_PackedValues = new uint[kUintPerEntry]; @@ -54,71 +59,118 @@ internal void Pack(out uint[] vals) ComputeBuffer m_IndexOfIndicesBuffer; uint[] m_IndexOfIndicesData; - Vector3Int m_CellCount; - Vector3Int m_CellMin; int m_CellSizeInMinBricks; + Vector3Int m_EntriesCount; + Vector3Int m_EntryMin; + Vector3Int m_EntryMax; + + internal void GetMinMaxEntry(out Vector3Int minEntry, out Vector3Int maxEntry) + { + minEntry = m_EntryMin; + maxEntry = m_EntryMax; + } + bool m_NeedUpdateComputeBuffer; - internal Vector3Int GetCellIndexDimension() => m_CellCount; - internal Vector3Int GetCellMinPosition() => m_CellMin; + internal Vector3Int GetGlobalIndirectionDimension() => m_EntriesCount; + internal Vector3Int GetGlobalIndirectionMinEntry() => m_EntryMin; + + int entrySizeInBricks => Mathf.Min((int)Mathf.Pow(ProbeBrickPool.kBrickCellCount, kEntryMaxSubdivLevel), m_CellSizeInMinBricks); + internal int entriesPerCellDimension => m_CellSizeInMinBricks / Mathf.Max(1, entrySizeInBricks); int GetFlatIndex(Vector3Int normalizedPos) { - return normalizedPos.z * (m_CellCount.x * m_CellCount.y) + normalizedPos.y * m_CellCount.x + normalizedPos.x; + return normalizedPos.z * (m_EntriesCount.x * m_EntriesCount.y) + normalizedPos.y * m_EntriesCount.x + normalizedPos.x; } - internal ProbeCellIndices(Vector3Int cellMin, Vector3Int cellMax, int cellSizeInMinBricks) + internal ProbeGlobalIndirection(Vector3Int cellMin, Vector3Int cellMax, int cellSizeInMinBricks) { - Vector3Int cellCount = cellMax + Vector3Int.one - cellMin; - m_CellCount = cellCount; - m_CellMin = cellMin; m_CellSizeInMinBricks = cellSizeInMinBricks; - int flatCellCount = cellCount.x * cellCount.y * cellCount.z; - int bufferSize = kUintPerEntry * flatCellCount; - m_IndexOfIndicesBuffer = new ComputeBuffer(flatCellCount, kUintPerEntry * sizeof(uint)); + + Vector3Int cellCount = cellMax + Vector3Int.one - cellMin; + m_EntriesCount = cellCount * entriesPerCellDimension; + m_EntryMin = cellMin * entriesPerCellDimension; + + m_EntryMax = (cellMax + Vector3Int.one) * entriesPerCellDimension - Vector3Int.one; + + int flatEntryCount = m_EntriesCount.x * m_EntriesCount.y * m_EntriesCount.z; + int bufferSize = kUintPerEntry * flatEntryCount; + m_IndexOfIndicesBuffer = new ComputeBuffer(flatEntryCount, kUintPerEntry * sizeof(uint)); m_IndexOfIndicesData = new uint[bufferSize]; m_NeedUpdateComputeBuffer = false; - estimatedVMemCost = flatCellCount * kUintPerEntry * sizeof(uint); + estimatedVMemCost = flatEntryCount * kUintPerEntry * sizeof(uint); } - internal int GetFlatIdxForCell(Vector3Int cellPosition) + + internal int GetFlatIdxForEntry(Vector3Int entryPosition) { - Vector3Int normalizedPos = cellPosition - m_CellMin; + Vector3Int normalizedPos = entryPosition - m_EntryMin; Debug.Assert(normalizedPos.x >= 0 && normalizedPos.y >= 0 && normalizedPos.z >= 0); return GetFlatIndex(normalizedPos); } - internal void UpdateCell(int cellFlatIdx, ProbeBrickIndex.CellIndexUpdateInfo cellUpdateInfo) + internal int[] GetFlatIndicesForCell(Vector3Int cellPosition) { - int minSubdivCellSize = ProbeReferenceVolume.CellSize(cellUpdateInfo.minSubdivInCell); - IndexMetaData metaData = new IndexMetaData(); - metaData.minSubdiv = cellUpdateInfo.minSubdivInCell; - metaData.minLocalIdx = cellUpdateInfo.minValidBrickIndexForCellAtMaxRes / minSubdivCellSize; - metaData.maxLocalIdx = cellUpdateInfo.maxValidBrickIndexForCellAtMaxResPlusOne / minSubdivCellSize; - metaData.firstChunkIndex = cellUpdateInfo.firstChunkIndex; + Vector3Int firstEntryPosition = cellPosition * entriesPerCellDimension; + int entriesPerCellDim = m_CellSizeInMinBricks / entrySizeInBricks; - metaData.Pack(out uint[] packedVals); + int[] outListOfIndices = new int[entriesPerCellDimension * entriesPerCellDimension * entriesPerCellDimension]; - for (int i = 0; i < kUintPerEntry; ++i) + int i = 0; + for (int x = 0; x < entriesPerCellDim; ++x) { - m_IndexOfIndicesData[cellFlatIdx * kUintPerEntry + i] = packedVals[i]; + for (int y = 0; y < entriesPerCellDim; ++y) + { + for (int z = 0; z < entriesPerCellDim; ++z) + { + outListOfIndices[i++] = GetFlatIdxForEntry(firstEntryPosition + new Vector3Int(x, y, z)); + } + } } - m_NeedUpdateComputeBuffer = true; + return outListOfIndices; } - internal void MarkCellAsUnloaded(int cellFlatIdx) + internal void UpdateCell(int[] cellEntriesIndices, ProbeBrickIndex.CellIndexUpdateInfo cellUpdateInfo) { - for (int i = 0; i < kUintPerEntry; ++i) + for (int entry = 0; entry < cellEntriesIndices.Length; ++entry) { - m_IndexOfIndicesData[cellFlatIdx * kUintPerEntry + i] = 0xFFFFFFFF; + int entryIndex = cellEntriesIndices[entry]; + ProbeBrickIndex.IndirectionEntryUpdateInfo entryUpdateInfo = cellUpdateInfo.entriesInfo[entry]; + + int minSubdivCellSize = ProbeReferenceVolume.CellSize(entryUpdateInfo.minSubdivInCell); + IndexMetaData metaData = new IndexMetaData(); + metaData.minSubdiv = entryUpdateInfo.minSubdivInCell; + metaData.minLocalIdx = entryUpdateInfo.hasOnlyBiggerBricks ? Vector3Int.zero : entryUpdateInfo.minValidBrickIndexForCellAtMaxRes / minSubdivCellSize; + metaData.maxLocalIdx = entryUpdateInfo.hasOnlyBiggerBricks ? Vector3Int.one : entryUpdateInfo.maxValidBrickIndexForCellAtMaxResPlusOne / minSubdivCellSize; + metaData.firstChunkIndex = entryUpdateInfo.firstChunkIndex; + + metaData.Pack(out uint[] packedVals); + + for (int i = 0; i < kUintPerEntry; ++i) + { + m_IndexOfIndicesData[entryIndex * kUintPerEntry + i] = packedVals[i]; + } } m_NeedUpdateComputeBuffer = true; } + internal void MarkEntriesAsUnloaded(int[] entriesFlatIndices) + { + for (int entry = 0; entry < entriesFlatIndices.Length; ++entry) + { + for (int i = 0; i < kUintPerEntry; ++i) + { + m_IndexOfIndicesData[entriesFlatIndices[entry] * kUintPerEntry + i] = 0xFFFFFFFF; + } + } + m_NeedUpdateComputeBuffer = true; + } + + internal void PushComputeData() { m_IndexOfIndicesBuffer.SetData(m_IndexOfIndicesData); diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.Debug.cs b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.Debug.cs index 2ddf6e69e7c..0d9f28e1fe2 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.Debug.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.Debug.cs @@ -1,4 +1,6 @@ +using System; using System.Collections.Generic; +using UnityEngine.Experimental.Rendering.RenderGraphModule; namespace UnityEngine.Rendering { @@ -29,7 +31,7 @@ public enum DebugProbeShadingMode /// ValidityOverDilationThreshold, /// - /// Show in red probes that have been made invalid by touchup volumes. Important to note that this debug view will only show result for volumes still present in the scene. + /// Show in red probes that have been made invalid by adjustment volumes. Important to note that this debug view will only show result for volumes still present in the scene. /// InvalidatedByTouchupVolumes, /// @@ -56,9 +58,44 @@ class ProbeVolumeDebug public bool drawVirtualOffsetPush; public float offsetSize = 0.025f; public bool freezeStreaming; + public bool displayCellStreamingScore; + public bool displayIndexFragmentation; public int otherStateIndex = 0; } + +#if UNITY_EDITOR + [UnityEditor.InitializeOnLoad] +#endif + internal class ProbeVolumeDebugColorPreferences + { + internal static Func GetDetailSubdivisionColor; + internal static Func GetMediumSubdivisionColor; + internal static Func GetLowSubdivisionColor; + internal static Func GetVeryLowSubdivisionColor; + internal static Func GetSparseSubdivisionColor; + internal static Func GetSparsestSubdivisionColor; + + internal static Color s_DetailSubdivision = new Color32(135, 35, 255, 255); + internal static Color s_MediumSubdivision = new Color32(54, 208, 228, 255); + internal static Color s_LowSubdivision = new Color32(255, 100, 45, 255); + internal static Color s_VeryLowSubdivision = new Color32(52, 87, 255, 255); + internal static Color s_SparseSubdivision = new Color32(255, 71, 97, 255); + internal static Color s_SparsestSubdivision = new Color32(200, 227, 39, 255); + + static ProbeVolumeDebugColorPreferences() + { +#if UNITY_EDITOR + GetDetailSubdivisionColor = CoreRenderPipelinePreferences.RegisterPreferenceColor("Adaptive Probe Volumes/Level 0 Subdivision", s_DetailSubdivision); + GetMediumSubdivisionColor = CoreRenderPipelinePreferences.RegisterPreferenceColor("Adaptive Probe Volumes/Level 1 Subdivision", s_MediumSubdivision); + GetLowSubdivisionColor = CoreRenderPipelinePreferences.RegisterPreferenceColor("Adaptive Probe Volumes/Level 2 Subdivision", s_LowSubdivision); + GetVeryLowSubdivisionColor = CoreRenderPipelinePreferences.RegisterPreferenceColor("Adaptive Probe Volumes/Level 3 Subdivision", s_VeryLowSubdivision); + GetSparseSubdivisionColor = CoreRenderPipelinePreferences.RegisterPreferenceColor("Adaptive Probe Volumes/Level 4 Subdivision", s_SparseSubdivision); + GetSparsestSubdivisionColor = CoreRenderPipelinePreferences.RegisterPreferenceColor("Adaptive Probe Volumes/Level 5 Subdivision", s_SparsestSubdivision); +#endif + } + + } public partial class ProbeReferenceVolume { internal class CellInstancedDebugProbes @@ -83,6 +120,7 @@ internal class CellInstancedDebugProbes Material m_DebugMaterial; Mesh m_DebugOffsetMesh; Material m_DebugOffsetMaterial; + Material m_DebugFragmentationMaterial; Plane[] m_DebugFrustumPlanes = new Plane[6]; // Scenario blending debug data @@ -119,16 +157,18 @@ void InitializeDebug(in ProbeVolumeSystemParameters parameters) m_DebugOffsetMesh = parameters.offsetDebugMesh; m_DebugOffsetMaterial = CoreUtils.CreateEngineMaterial(parameters.offsetDebugShader); m_DebugOffsetMaterial.enableInstancing = true; + m_DebugFragmentationMaterial = CoreUtils.CreateEngineMaterial(parameters.fragmentationDebugShader); // 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); - subdivisionDebugColors[1] = new Color(0.0f, 1.0f, 0.0f); - subdivisionDebugColors[2] = new Color(0.0f, 0.0f, 1.0f); - subdivisionDebugColors[3] = new Color(1.0f, 1.0f, 0.0f); - 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); + + subdivisionDebugColors[0] = ProbeVolumeDebugColorPreferences.s_DetailSubdivision; + subdivisionDebugColors[1] = ProbeVolumeDebugColorPreferences.s_MediumSubdivision; + subdivisionDebugColors[2] = ProbeVolumeDebugColorPreferences.s_LowSubdivision; + subdivisionDebugColors[3] = ProbeVolumeDebugColorPreferences.s_VeryLowSubdivision; + subdivisionDebugColors[4] = ProbeVolumeDebugColorPreferences.s_SparseSubdivision; + subdivisionDebugColors[5] = ProbeVolumeDebugColorPreferences.s_SparsestSubdivision; + subdivisionDebugColors[6] = ProbeVolumeDebugColorPreferences.s_DetailSubdivision; } RegisterDebug(parameters); @@ -143,6 +183,7 @@ void CleanupDebug() UnregisterDebug(true); CoreUtils.Destroy(m_DebugMaterial); CoreUtils.Destroy(m_DebugOffsetMaterial); + CoreUtils.Destroy(m_DebugFragmentationMaterial); #if UNITY_EDITOR UnityEditor.Lightmapping.lightingDataCleared -= OnClearLightingdata; @@ -168,28 +209,29 @@ void RefreshDebug(DebugUI.Field field, T value) var widgetList = new List(); var subdivContainer = new DebugUI.Container() { displayName = "Subdivision Visualization" }; - subdivContainer.children.Add(new DebugUI.BoolField { displayName = "Display Cells", getter = () => probeVolumeDebug.drawCells, setter = value => probeVolumeDebug.drawCells = value, onValueChanged = RefreshDebug }); - subdivContainer.children.Add(new DebugUI.BoolField { displayName = "Display Bricks", getter = () => probeVolumeDebug.drawBricks, setter = value => probeVolumeDebug.drawBricks = value, onValueChanged = RefreshDebug }); + subdivContainer.children.Add(new DebugUI.BoolField { displayName = "Display Cells", tooltip = "Draw Cells used for loading and streaming.", getter = () => probeVolumeDebug.drawCells, setter = value => probeVolumeDebug.drawCells = value, onValueChanged = RefreshDebug }); + subdivContainer.children.Add(new DebugUI.BoolField { displayName = "Display Bricks", tooltip = "Display Subdivision bricks.", getter = () => probeVolumeDebug.drawBricks, setter = value => probeVolumeDebug.drawBricks = value, onValueChanged = RefreshDebug }); #if UNITY_EDITOR - subdivContainer.children.Add(new DebugUI.BoolField { displayName = "Realtime Update", getter = () => probeVolumeDebug.realtimeSubdivision, setter = value => probeVolumeDebug.realtimeSubdivision = value, onValueChanged = RefreshDebug }); + subdivContainer.children.Add(new DebugUI.BoolField { displayName = "Live Subdivision Preview", tooltip = "Enable a preview of Probe Volume data in the Scene without baking. Can impact Editor performance.", getter = () => probeVolumeDebug.realtimeSubdivision, setter = value => probeVolumeDebug.realtimeSubdivision = value, onValueChanged = RefreshDebug }); if (probeVolumeDebug.realtimeSubdivision) { - var cellUpdatePerFrame = new DebugUI.IntField { displayName = "Number Of Cell Update Per Frame", getter = () => probeVolumeDebug.subdivisionCellUpdatePerFrame, setter = value => probeVolumeDebug.subdivisionCellUpdatePerFrame = value, min = () => 1, max = () => 100 }; - var delayBetweenUpdates = new DebugUI.FloatField { displayName = "Delay Between Two Updates In Seconds", getter = () => probeVolumeDebug.subdivisionDelayInSeconds, setter = value => probeVolumeDebug.subdivisionDelayInSeconds = value, min = () => 0.1f, max = () => 10 }; + var cellUpdatePerFrame = new DebugUI.IntField { displayName = "Cell Updates Per Frame", tooltip = "The number of Cells, bricks, and probe positions updated per frame. Higher numbers can impact Editor performance.", getter = () => probeVolumeDebug.subdivisionCellUpdatePerFrame, setter = value => probeVolumeDebug.subdivisionCellUpdatePerFrame = value, min = () => 1, max = () => 100 }; + var delayBetweenUpdates = new DebugUI.FloatField { displayName = "Update Frequency", tooltip = "Delay in seconds between updates to Cell, Brick, and Probe positions if Live Subdivision Preview is enabled.", getter = () => probeVolumeDebug.subdivisionDelayInSeconds, setter = value => probeVolumeDebug.subdivisionDelayInSeconds = value, min = () => 0.1f, max = () => 10 }; subdivContainer.children.Add(new DebugUI.Container { children = { cellUpdatePerFrame, delayBetweenUpdates } }); } #endif - subdivContainer.children.Add(new DebugUI.FloatField { displayName = "Culling Distance", getter = () => probeVolumeDebug.subdivisionViewCullingDistance, setter = value => probeVolumeDebug.subdivisionViewCullingDistance = value, min = () => 0.0f }); + subdivContainer.children.Add(new DebugUI.FloatField { displayName = "Debug Draw Distance", tooltip = "How far from the Scene Camera to draw debug visualization for Cells and Bricks. Large distances can impact Editor performance.", getter = () => probeVolumeDebug.subdivisionViewCullingDistance, setter = value => probeVolumeDebug.subdivisionViewCullingDistance = value, min = () => 0.0f }); var probeContainer = new DebugUI.Container() { displayName = "Probe Visualization" }; - probeContainer.children.Add(new DebugUI.BoolField { displayName = "Display Probes", getter = () => probeVolumeDebug.drawProbes, setter = value => probeVolumeDebug.drawProbes = value, onValueChanged = RefreshDebug }); + probeContainer.children.Add(new DebugUI.BoolField { displayName = "Display Probes", tooltip = "Render the debug view showing probe positions. Use the shading mode to determine which type of lighting data to visualize.", getter = () => probeVolumeDebug.drawProbes, setter = value => probeVolumeDebug.drawProbes = value, onValueChanged = RefreshDebug }); if (probeVolumeDebug.drawProbes) { var probeContainerChildren = new DebugUI.Container(); probeContainerChildren.children.Add(new DebugUI.EnumField { displayName = "Probe Shading Mode", + tooltip = "Choose which lighting data to show in the probe debug visualization.", getter = () => (int)probeVolumeDebug.probeShading, setter = value => probeVolumeDebug.probeShading = (DebugProbeShadingMode)value, autoEnum = typeof(DebugProbeShadingMode), @@ -197,13 +239,14 @@ void RefreshDebug(DebugUI.Field field, T value) setIndex = value => probeVolumeDebug.probeShading = (DebugProbeShadingMode)value, onValueChanged = RefreshDebug }); - probeContainerChildren.children.Add(new DebugUI.FloatField { displayName = "Probe Size", getter = () => probeVolumeDebug.probeSize, setter = value => probeVolumeDebug.probeSize = value, min = () => kProbeSizeMin, max = () => kProbeSizeMax }); + probeContainerChildren.children.Add(new DebugUI.FloatField { displayName = "Debug Size", tooltip = "The size of probes shown in the debug view.", getter = () => probeVolumeDebug.probeSize, setter = value => probeVolumeDebug.probeSize = value, min = () => kProbeSizeMin, max = () => kProbeSizeMax }); if (probeVolumeDebug.probeShading == DebugProbeShadingMode.SH || probeVolumeDebug.probeShading == DebugProbeShadingMode.SHL0 || probeVolumeDebug.probeShading == DebugProbeShadingMode.SHL0L1) - probeContainerChildren.children.Add(new DebugUI.FloatField { displayName = "Probe Exposure Compensation", getter = () => probeVolumeDebug.exposureCompensation, setter = value => probeVolumeDebug.exposureCompensation = value }); + probeContainerChildren.children.Add(new DebugUI.FloatField { displayName = "Exposure Compensation", tooltip = "Modify the brightness of probe visualizations. Decrease this number to make very bright probes more visible.", getter = () => probeVolumeDebug.exposureCompensation, setter = value => probeVolumeDebug.exposureCompensation = value }); probeContainerChildren.children.Add(new DebugUI.IntField { - displayName = "Max subdivision displayed", + displayName = "Max Subdivisions Displayed", + tooltip = "The highest (most dense) probe subdivision level displayed in the debug view.", getter = () => probeVolumeDebug.maxSubdivToVisualize, setter = (v) => probeVolumeDebug.maxSubdivToVisualize = Mathf.Min(v, ProbeReferenceVolume.instance.GetMaxSubdivision() - 1), min = () => 0, @@ -212,7 +255,8 @@ void RefreshDebug(DebugUI.Field field, T value) probeContainerChildren.children.Add(new DebugUI.IntField { - displayName = "Min subdivision displayed", + displayName = "Min Subdivisions Displayed", + tooltip = "The lowest (least dense) probe subdivision level displayed in the debug view.", getter = () => probeVolumeDebug.minSubdivToVisualize, setter = (v) => probeVolumeDebug.minSubdivToVisualize = Mathf.Max(v, 0), min = () => 0, @@ -225,7 +269,8 @@ void RefreshDebug(DebugUI.Field field, T value) probeContainer.children.Add(new DebugUI.BoolField { - displayName = "Virtual Offset", + displayName = "Virtual Offset Debug", + tooltip = "Enable Virtual Offset debug visualization. Indicates the offsets applied to probe positions. These are used to capture lighting when probes are considered invalid.", getter = () => probeVolumeDebug.drawVirtualOffsetPush, setter = value => { @@ -242,16 +287,19 @@ void RefreshDebug(DebugUI.Field field, T value) }); if (probeVolumeDebug.drawVirtualOffsetPush) { - var voOffset = new DebugUI.FloatField { displayName = "Offset Size", getter = () => probeVolumeDebug.offsetSize, setter = value => probeVolumeDebug.offsetSize = value, min = () => kOffsetSizeMin, max = () => kOffsetSizeMax }; + var voOffset = new DebugUI.FloatField { displayName = "Debug Size", tooltip = "Modify the size of the arrows used in the virtual offset debug visualization.", getter = () => probeVolumeDebug.offsetSize, setter = value => probeVolumeDebug.offsetSize = value, min = () => kOffsetSizeMin, max = () => kOffsetSizeMax }; probeContainer.children.Add(new DebugUI.Container { children = { voOffset } }); } - probeContainer.children.Add(new DebugUI.FloatField { displayName = "Culling Distance", getter = () => probeVolumeDebug.probeCullingDistance, setter = value => probeVolumeDebug.probeCullingDistance = value, min = () => 0.0f }); + probeContainer.children.Add(new DebugUI.FloatField { displayName = "Debug Draw Distance", tooltip = "How far from the Scene Camera to draw probe debug visualizations. Large distances can impact Editor performance.", getter = () => probeVolumeDebug.probeCullingDistance, setter = value => probeVolumeDebug.probeCullingDistance = value, min = () => 0.0f }); var streamingContainer = new DebugUI.Container() { displayName = "Streaming" }; - streamingContainer.children.Add(new DebugUI.BoolField { displayName = "Freeze Streaming", getter = () => probeVolumeDebug.freezeStreaming, setter = value => probeVolumeDebug.freezeStreaming = value }); + streamingContainer.children.Add(new DebugUI.BoolField { displayName = "Freeze Streaming", tooltip = "Stop Unity from streaming probe data in or out of GPU memory.", getter = () => probeVolumeDebug.freezeStreaming, setter = value => probeVolumeDebug.freezeStreaming = value }); + streamingContainer.children.Add(new DebugUI.Value { displayName = "Index Fragmentation Rate", getter = () => instance.indexFragmentationRate }); + streamingContainer.children.Add(new DebugUI.BoolField { displayName = "Display Streaming Score", getter = () => probeVolumeDebug.displayCellStreamingScore, setter = value => probeVolumeDebug.displayCellStreamingScore = value }); + streamingContainer.children.Add(new DebugUI.BoolField { displayName = "Display Index Fragmentation", getter = () => probeVolumeDebug.displayIndexFragmentation, setter = value => probeVolumeDebug.displayIndexFragmentation = value }); - streamingContainer.children.Add(new DebugUI.IntField { displayName = "Number Of Cells Loaded Per Frame", getter = () => instance.numberOfCellsLoadedPerFrame, setter = value => instance.SetNumberOfCellsLoadedPerFrame(value), min = () => 0 }); + streamingContainer.children.Add(new DebugUI.IntField { displayName = "Cells Per Frame", tooltip = "Determines the maximum number of Cells Unity streams per frame. Loading more Cells per frame can impact performance.", getter = () => instance.numberOfCellsLoadedPerFrame, setter = value => instance.SetNumberOfCellsLoadedPerFrame(value), min = () => 0 }); if (parameters.supportsRuntimeDebug) { @@ -310,7 +358,8 @@ void RefreshScenarioNames(string guid) m_DebugScenarioField = new DebugUI.EnumField { - displayName = "Scenario To Blend With", + displayName = "Scenario Blend Target", + tooltip = "Select another lighting scenario to blend with the active lighting scenario.", enumNames = m_DebugScenarioNames, enumValues = m_DebugScenarioValues, getIndex = () => @@ -342,7 +391,7 @@ void RefreshScenarioNames(string guid) }; blendingContainer.children.Add(m_DebugScenarioField); - blendingContainer.children.Add(new DebugUI.FloatField { displayName = "Scenario Blending Factor", getter = () => instance.scenarioBlendingFactor, setter = value => instance.scenarioBlendingFactor = value, min = () => 0.0f, max = () => 1.0f }); + blendingContainer.children.Add(new DebugUI.FloatField { displayName = "Scenario Blending Factor", tooltip = "Blend between lighting scenarios by adjusting this slider.", getter = () => instance.scenarioBlendingFactor, setter = value => instance.scenarioBlendingFactor = value, min = () => 0.0f, max = () => 1.0f }); widgetList.Add(blendingContainer); } @@ -363,6 +412,51 @@ void UnregisterDebug(bool destroyPanel) DebugManager.instance.GetPanel(k_DebugPanelName, false).children.Remove(m_DebugItems); } + class RenderFragmentationOverlayPassData + { + public Material debugFragmentationMaterial; + public Rendering.DebugOverlay debugOverlay; + public int chunkCount; + public ComputeBuffer debugFragmentationData; + public TextureHandle colorBuffer; + public TextureHandle depthBuffer; + } + + /// + /// Render a debug view showing fragmentation of the GPU memory. + /// + /// + /// + /// + /// + public void RenderFragmentationOverlay(RenderGraph renderGraph, TextureHandle colorBuffer, TextureHandle depthBuffer, DebugOverlay debugOverlay) + { + if (!probeVolumeDebug.displayIndexFragmentation) + return; + + using (var builder = renderGraph.AddRenderPass("APVFragmentationOverlay", out var passData)) + { + passData.debugOverlay = debugOverlay; + passData.debugFragmentationMaterial = m_DebugFragmentationMaterial; + passData.colorBuffer = builder.UseColorBuffer(colorBuffer, 0); + passData.depthBuffer = builder.UseDepthBuffer(depthBuffer, DepthAccess.ReadWrite); + passData.debugFragmentationData = m_Index.GetDebugFragmentationBuffer(); + passData.chunkCount = passData.debugFragmentationData.count; + + builder.SetRenderFunc( + (RenderFragmentationOverlayPassData data, RenderGraphContext ctx) => + { + var mpb = ctx.renderGraphPool.GetTempMaterialPropertyBlock(); + + data.debugOverlay.SetViewport(ctx.cmd); + mpb.SetInt("_ChunkCount", data.chunkCount); + mpb.SetBuffer("_DebugFragmentation", data.debugFragmentationData); + ctx.cmd.DrawProcedural(Matrix4x4.identity, data.debugFragmentationMaterial, 0, MeshTopology.Triangles, 3, 1, mpb); + data.debugOverlay.Next(); + }); + } + } + bool ShouldCullCell(Vector3 cellPosition, Transform cameraTransform, Plane[] frustumPlanes) { var cellSize = MaxBrickSize(); @@ -473,6 +567,7 @@ CellInstancedDebugProbes CreateInstancedProbes(CellInfo cellInfo) Vector4[] texels = new Vector4[kProbesPerBatch]; float[] validity = new float[kProbesPerBatch]; + float[] dilationThreshold = new float[kProbesPerBatch]; float[] relativeSize = new float[kProbesPerBatch]; float[] touchupUpVolumeAction = cell.touchupVolumeInteraction.Length > 0 ? new float[kProbesPerBatch] : null; Vector4[] offsets = cell.offsetVectors.Length > 0 ? new Vector4[kProbesPerBatch] : null; @@ -485,10 +580,11 @@ CellInstancedDebugProbes CreateInstancedProbes(CellInfo cellInfo) debugData.offsetBuffers = offsetBuffers; debugData.props = props; - var chunkSizeInProbes = m_CurrentProbeVolumeChunkSizeInBricks * ProbeBrickPool.kBrickProbeCountTotal; + var chunkSizeInProbes = ProbeBrickPool.GetChunkSizeInProbeCount(); var loc = ProbeBrickPool.ProbeCountToDataLocSize(chunkSizeInProbes); + float baseThreshold = bakingProcessSettings.dilationSettings.dilationValidityThreshold; int idxInBatch = 0; int globalIndex = 0; int brickCount = cell.probeCount / ProbeBrickPool.kBrickProbeCountTotal; @@ -498,7 +594,7 @@ CellInstancedDebugProbes CreateInstancedProbes(CellInfo cellInfo) Debug.Assert(bz < loc.z); int brickSize = cell.bricks[brickIndex].subdivisionLevel; - int chunkIndex = brickIndex / m_CurrentProbeVolumeChunkSizeInBricks; + int chunkIndex = brickIndex / ProbeBrickPool.GetChunkSizeInBrickCount(); var chunk = chunks[chunkIndex]; Vector3Int brickStart = new Vector3Int(chunk.x + bx, chunk.y + by, chunk.z + bz); @@ -514,12 +610,14 @@ CellInstancedDebugProbes CreateInstancedProbes(CellInfo cellInfo) probeBuffer.Add(Matrix4x4.TRS(cell.probePositions[probeFlatIndex], Quaternion.identity, Vector3.one * (0.3f * (brickSize + 1)))); validity[idxInBatch] = cell.validity[probeFlatIndex]; + dilationThreshold[idxInBatch] = baseThreshold; texels[idxInBatch] = new Vector4(texelLoc.x, texelLoc.y, texelLoc.z, brickSize); relativeSize[idxInBatch] = (float)brickSize / (float)maxSubdiv; if (touchupUpVolumeAction != null) { touchupUpVolumeAction[idxInBatch] = cell.touchupVolumeInteraction[probeFlatIndex]; + dilationThreshold[idxInBatch] = touchupUpVolumeAction[idxInBatch] > 1.0f ? touchupUpVolumeAction[idxInBatch] - 1.0f : baseThreshold; } if (offsets != null) @@ -549,6 +647,7 @@ CellInstancedDebugProbes CreateInstancedProbes(CellInfo cellInfo) MaterialPropertyBlock prop = new MaterialPropertyBlock(); prop.SetFloatArray("_Validity", validity); + prop.SetFloatArray("_DilationThreshold", dilationThreshold); prop.SetFloatArray("_TouchupedByVolume", touchupUpVolumeAction); prop.SetFloatArray("_RelativeSize", relativeSize); prop.SetVectorArray("_IndexInAtlas", texels); diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.Streaming.cs b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.Streaming.cs index 20d05ea551b..d340a174367 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.Streaming.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.Streaming.cs @@ -7,12 +7,22 @@ public partial class ProbeReferenceVolume DynamicArray m_TempCellToLoadList = new DynamicArray(); DynamicArray m_TempCellToUnloadList = new DynamicArray(); - DynamicArray m_LoadedBlendingCells = new(); - DynamicArray m_ToBeLoadedBlendingCells = new(); - DynamicArray m_TempBlendingCellToLoadList = new(); - DynamicArray m_TempBlendingCellToUnloadList = new(); + DynamicArray m_LoadedBlendingCells = new (); + DynamicArray m_ToBeLoadedBlendingCells = new (); + DynamicArray m_TempBlendingCellToLoadList = new (); + DynamicArray m_TempBlendingCellToUnloadList = new (); Vector3 m_FrozenCameraPosition; + Vector3 m_FrozenCameraDirection; + + const float kIndexFragmentationThreshold = 0.2f; + bool m_IndexDefragmentationInProgress; + ProbeBrickIndex m_DefragIndex; + ProbeGlobalIndirection m_DefragCellIndices; + DynamicArray m_IndexDefragCells = new DynamicArray(); + + internal float minStreamingScore; + internal float maxStreamingScore; bool m_HasRemainingCellsToBlend = false; internal void ScenarioBlendingChanged(bool scenarioChanged) @@ -35,13 +45,16 @@ public void SetNumberOfCellsLoadedPerFrame(int numberOfCells) m_NumberOfCellsLoadedPerFrame = Mathf.Max(1, numberOfCells); } - void ComputeCellCameraDistance(Vector3 cameraPosition, DynamicArray cells) + void ComputeStreamingScore(Vector3 cameraPosition, Vector3 cameraDirection, DynamicArray cells) { for (int i = 0; i < cells.size; ++i) { var cellInfo = cells[i]; - // For now streaming score is only distance based. + var cellPosition = cellInfo.cell.position; + var cameraToCell = (cellPosition - cameraPosition).normalized; cellInfo.streamingScore = Vector3.Distance(cameraPosition, cellInfo.cell.position); + // This should give more weight to cells in front of the camera. + cellInfo.streamingScore *= (2.0f - Vector3.Dot(cameraDirection, cameraToCell)); } } @@ -68,8 +81,7 @@ bool TryLoadCell(CellInfo cellInfo, ref int shBudget, ref int indexBudget, Dynam if (cellInfo.cell.shChunkCount <= shBudget && cellInfo.cell.indexChunkCount <= indexBudget) { // This can still fail because of fragmentation. - // TODO: Handle defrag - if (LoadCell(cellInfo)) + if (LoadCell(cellInfo, ignoreErrorLog: true)) { loadedCells.Add(cellInfo); @@ -98,6 +110,24 @@ bool TryLoadBlendingCell(BlendingCellInfo blendingCell, DynamicArray /// Updates the cell streaming for a /// @@ -113,17 +143,20 @@ public void UpdateCellStreaming(CommandBuffer cmd, Camera camera) if (!probeVolumeDebug.freezeStreaming) { m_FrozenCameraPosition = cameraPosition; + m_FrozenCameraDirection = camera.transform.forward; } // Cell position in cell space is the top left corner. So we need to shift the camera position by half a cell to make things comparable. var cameraPositionCellSpace = (m_FrozenCameraPosition - m_Transform.posWS) / MaxBrickSize() - Vector3.one * 0.5f; - ComputeCellCameraDistance(cameraPositionCellSpace, m_ToBeLoadedCells); - ComputeCellCameraDistance(cameraPositionCellSpace, m_LoadedCells); + ComputeStreamingScore(cameraPositionCellSpace, m_FrozenCameraDirection, m_ToBeLoadedCells); + ComputeStreamingScore(cameraPositionCellSpace, m_FrozenCameraDirection, m_LoadedCells); m_ToBeLoadedCells.QuickSort(); m_LoadedCells.QuickSort(); + ComputeMinMaxStreamingScore(); + // This is only a rough budget estimate at first. // It doesn't account for fragmentation. int indexChunkBudget = m_Index.GetRemainingChunkCount(); @@ -132,47 +165,66 @@ public void UpdateCellStreaming(CommandBuffer cmd, Camera camera) if (m_SupportStreaming) { - while (m_TempCellToLoadList.size < cellCountToLoad) + if (m_IndexDefragmentationInProgress) { - // Enough memory, we can safely load the cell. - var cellInfo = m_ToBeLoadedCells[m_TempCellToLoadList.size]; - if (!TryLoadCell(cellInfo, ref shChunkBudget, ref indexChunkBudget, m_TempCellToLoadList)) - break; + UpdateIndexDefragmentation(); } - - // Budget reached. We need to figure out if we can safely unload other cells to make room. - if (m_TempCellToLoadList.size != cellCountToLoad) + else { - int pendingUnloadCount = 0; + bool needComputeFragmentation = false; + while (m_TempCellToLoadList.size < cellCountToLoad) { - if (m_LoadedCells.size - pendingUnloadCount == 0) + // Enough memory, we can safely load the cell. + var cellInfo = m_ToBeLoadedCells[m_TempCellToLoadList.size]; + if (!TryLoadCell(cellInfo, ref shChunkBudget, ref indexChunkBudget, m_TempCellToLoadList)) break; + } - var furthestLoadedCell = m_LoadedCells[m_LoadedCells.size - pendingUnloadCount - 1]; - var closestUnloadedCell = m_ToBeLoadedCells[m_TempCellToLoadList.size]; - - // The most distant loaded cell is further than the closest unloaded cell, we can unload it. - if (furthestLoadedCell.streamingScore > closestUnloadedCell.streamingScore) + // Budget reached. We need to figure out if we can safely unload other cells to make room. + // If defrag was triggered by TryLoadCell we should not try to load further cells either. + if (m_TempCellToLoadList.size != cellCountToLoad && !m_IndexDefragmentationInProgress) + { + int pendingUnloadCount = 0; + while (m_TempCellToLoadList.size < cellCountToLoad) { - pendingUnloadCount++; - UnloadCell(furthestLoadedCell); - shChunkBudget += furthestLoadedCell.cell.shChunkCount; - indexChunkBudget += furthestLoadedCell.cell.indexChunkCount; + if (m_LoadedCells.size - pendingUnloadCount == 0) + break; + + var furthestLoadedCell = m_LoadedCells[m_LoadedCells.size - pendingUnloadCount - 1]; + var closestUnloadedCell = m_ToBeLoadedCells[m_TempCellToLoadList.size]; + + // The most distant loaded cell is further than the closest unloaded cell, we can unload it. + if (furthestLoadedCell.streamingScore > closestUnloadedCell.streamingScore) + { + pendingUnloadCount++; + UnloadCell(furthestLoadedCell); + shChunkBudget += furthestLoadedCell.cell.shChunkCount; + indexChunkBudget += furthestLoadedCell.cell.indexChunkCount; - m_TempCellToUnloadList.Add(furthestLoadedCell); + m_TempCellToUnloadList.Add(furthestLoadedCell); - TryLoadCell(closestUnloadedCell, ref shChunkBudget, ref indexChunkBudget, m_TempCellToLoadList); + if (!TryLoadCell(closestUnloadedCell, ref shChunkBudget, ref indexChunkBudget, m_TempCellToLoadList)) + break; // Alloc failed because of fragmentation, stop trying to load cells. + + needComputeFragmentation = true; + } + else // We are in a "stable" state, all the closest cells are loaded within the budget. + break; } - else // We are in a "stable" state, all the closest cells are loaded within the budget. - break; - } - if (pendingUnloadCount > 0) - { - m_LoadedCells.RemoveRange(m_LoadedCells.size - pendingUnloadCount, pendingUnloadCount); - RecomputeMinMaxLoadedCellPos(); + if (pendingUnloadCount > 0) + { + m_LoadedCells.RemoveRange(m_LoadedCells.size - pendingUnloadCount, pendingUnloadCount); + RecomputeMinMaxLoadedCellPos(); + } } + + if (needComputeFragmentation) + m_Index.ComputeFragmentationRate(); + + if (m_Index.fragmentationRate >= kIndexFragmentationThreshold) + StartIndexDefragmentation(); } } else @@ -186,7 +238,9 @@ public void UpdateCellStreaming(CommandBuffer cmd, Camera camera) // Remove the cells we successfully loaded. m_ToBeLoadedCells.RemoveRange(0, m_TempCellToLoadList.size); + // Move the successfully loaded cells to the "loaded cells" list. m_LoadedCells.AddRange(m_TempCellToLoadList); + // Remove the successfully loaded cells from the list of cells to be loaded. m_ToBeLoadedCells.AddRange(m_TempCellToUnloadList); m_TempCellToLoadList.Clear(); m_TempCellToUnloadList.Clear(); @@ -313,5 +367,65 @@ void UpdateBlendingCellStreaming(CommandBuffer cmd) if (m_ToBeLoadedBlendingCells.size == 0) m_HasRemainingCellsToBlend = false; } + + static int DefragComparer(CellInfo a, CellInfo b) + { + if (a.updateInfo.GetNumberOfChunks() > b.updateInfo.GetNumberOfChunks()) + return 1; + else if (a.updateInfo.GetNumberOfChunks() < b.updateInfo.GetNumberOfChunks()) + return -1; + else return 0; + } + + void StartIndexDefragmentation() + { + m_IndexDefragmentationInProgress = true; + + // Prepare the list of cells. + // We want to relocate cells with more indices first. + m_IndexDefragCells.Clear(); + m_IndexDefragCells.AddRange(m_LoadedCells); + m_IndexDefragCells.QuickSort(DefragComparer); + + m_DefragIndex.Clear(); + } + + void UpdateIndexDefragmentation() + { + using (new ProfilingScope(null, ProfilingSampler.Get(CoreProfileId.APVIndexDefragUpdate))) + { + int numberOfCellsToProcess = Mathf.Min(m_IndexDefragCells.size, m_NumberOfCellsLoadedPerFrame); + for (int i = 0; i < numberOfCellsToProcess; ++i) + { + var cellInfo = m_IndexDefragCells[m_IndexDefragCells.size - i - 1]; + + int indirectionBufferEntries = cellInfo.updateInfo.entriesInfo.Length; + bool canAllocateCell = m_DefragIndex.FindSlotsForEntries(ref cellInfo.updateInfo.entriesInfo); + bool successfulReserve = m_DefragIndex.ReserveChunks(cellInfo.updateInfo.entriesInfo, false); + + // Update index and indirection + m_DefragIndex.AddBricks(cellInfo.cell, cellInfo.cell.bricks, cellInfo.chunkList, ProbeBrickPool.GetChunkSizeInBrickCount(), m_Pool.GetPoolWidth(), m_Pool.GetPoolHeight(), cellInfo.updateInfo); + m_DefragCellIndices.UpdateCell(cellInfo.flatIndicesInGlobalIndirection, cellInfo.updateInfo); + } + + // Remove processed cells from the list. + m_IndexDefragCells.Resize(m_IndexDefragCells.size - numberOfCellsToProcess); + + if (m_IndexDefragCells.size == 0) + { + // Swap index buffers + var oldDefragIndex = m_DefragIndex; + m_DefragIndex = m_Index; + m_Index = oldDefragIndex; + + var oldDefragCellIndices = m_DefragCellIndices; + m_DefragCellIndices = m_CellIndices; + m_CellIndices = oldDefragCellIndices; + + // Resume streaming + m_IndexDefragmentationInProgress = false; + } + } + } } } diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs index 3995bc95ec9..c1a233a34af 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs @@ -45,6 +45,10 @@ public struct ProbeVolumeSystemParameters /// public Shader offsetDebugShader; /// + /// The shader used to visualize APV fragmentation. + /// + public Shader fragmentationDebugShader; + /// /// The compute shader used to interpolate between two lighting scenarios. /// Set to null if blending is not supported. /// @@ -162,6 +166,14 @@ public enum ProbeVolumeSHBands /// public partial class ProbeReferenceVolume { + [Serializable] + internal struct IndirectionEntryInfo + { + public Vector3Int positionInBricks; + public int minSubdiv; + public bool hasOnlyBiggerBricks; // True if it has only bricks that are bigger than the entry itself + } + [Serializable] [DebuggerDisplay("Index = {index} position = {position}")] internal class Cell @@ -174,6 +186,10 @@ internal class Cell public int indexChunkCount; public int shChunkCount; + // This is data that is generated at bake time to not having to re-analyzing the content of the cell + // for the indirection buffer. + public IndirectionEntryInfo[] indirectionEntryInfo; + public bool hasTwoScenarios; public ProbeVolumeSHBands shBands; @@ -210,7 +226,7 @@ internal class CellInfo : IComparable public Cell cell; public BlendingCellInfo blendingCell; public List chunkList = new List(); - public int flatIdxInCellIndices = -1; + public int[] flatIndicesInGlobalIndirection = null; public bool loaded; public ProbeBrickIndex.CellIndexUpdateInfo updateInfo; public bool indexUpdated; @@ -236,7 +252,7 @@ public void Clear() cell = null; blendingCell = null; chunkList.Clear(); - flatIdxInCellIndices = -1; + flatIndicesInGlobalIndirection = null; loaded = false; updateInfo = default(ProbeBrickIndex.CellIndexUpdateInfo); sourceAssetInstanceID = -1; @@ -453,7 +469,7 @@ public struct RuntimeResources int m_MaxSubdivision; ProbeBrickPool m_Pool; ProbeBrickIndex m_Index; - ProbeCellIndices m_CellIndices; + ProbeGlobalIndirection m_CellIndices; ProbeBrickBlendingPool m_BlendingPool; List m_TmpSrcChunks = new List(); float[] m_PositionOffsets = new float[ProbeBrickPool.kBrickProbeCountPerDim]; @@ -467,7 +483,6 @@ public struct RuntimeResources ProbeBrickPool.DataLocation m_TemporaryDataLocation; int m_TemporaryDataLocationMemCost; - int m_CurrentProbeVolumeChunkSizeInBricks = 0; internal ProbeVolumeSceneData sceneData; @@ -487,9 +502,6 @@ public struct ExtraDataActionInput /// public Action retrieveExtraDataAction; - - bool m_BricksLoaded = false; - // Information of the probe volume asset that is being loaded (if one is pending) Dictionary m_PendingAssetsToBeLoaded = new Dictionary(); // Information on probes we need to remove. @@ -606,6 +618,8 @@ internal void UnregisterPerSceneData(ProbeVolumePerSceneData data) perSceneDataList.Remove(data); } + internal float indexFragmentationRate { get => m_Index.fragmentationRate; } + /// /// Get the instance of the probe reference volume (singleton). /// @@ -633,13 +647,13 @@ public void Initialize(in ProbeVolumeSystemParameters parameters) m_BlendingMemoryBudget = parameters.blendingMemoryBudget; m_SHBands = parameters.shBands; m_ProbeVolumesWeight = 1f; + m_SupportStreaming = parameters.supportStreaming; InitializeDebug(parameters); ProbeBrickBlendingPool.Initialize(parameters); InitProbeReferenceVolume(m_MemoryBudget, m_BlendingMemoryBudget, m_SHBands); m_IsInitialized = true; m_NeedsIndexRebuild = true; sceneData = parameters.sceneData; - m_SupportStreaming = parameters.supportStreaming; #if UNITY_EDITOR if (sceneData != null) @@ -670,7 +684,8 @@ internal void ForceSHBand(ProbeVolumeSHBands shBands) if (m_ProbeReferenceVolumeInit) CleanupLoadedData(); m_SHBands = shBands; - m_ProbeReferenceVolumeInit = false; + + DeinitProbeReferenceVolume(); InitProbeReferenceVolume(m_MemoryBudget, m_BlendingMemoryBudget, shBands); } @@ -748,8 +763,8 @@ internal void UnloadCell(CellInfo cellInfo) else m_ToBeLoadedBlendingCells.Remove(cellInfo.blendingCell); - if (cellInfo.flatIdxInCellIndices >= 0) - m_CellIndices.MarkCellAsUnloaded(cellInfo.flatIdxInCellIndices); + if (cellInfo.flatIndicesInGlobalIndirection != null) + m_CellIndices.MarkEntriesAsUnloaded(cellInfo.flatIndicesInGlobalIndirection); ReleaseBricks(cellInfo); @@ -798,7 +813,7 @@ void AddCell(Cell cell, int assetInstanceID) { cellInfo = m_CellInfoPool.Get(); cellInfo.cell = cell; - cellInfo.flatIdxInCellIndices = m_CellIndices.GetFlatIdxForCell(cell.position); + cellInfo.flatIndicesInGlobalIndirection = m_CellIndices.GetFlatIndicesForCell(cell.position); cellInfo.sourceAssetInstanceID = assetInstanceID; cellInfo.referenceCount = 1; cells[cell.index] = cellInfo; @@ -807,6 +822,8 @@ void AddCell(Cell cell, int assetInstanceID) blendingCell.cellInfo = cellInfo; cellInfo.blendingCell = blendingCell; + cellInfo.tempUpdateInfo.entriesInfo = new ProbeBrickIndex.IndirectionEntryUpdateInfo[cell.indirectionEntryInfo.Length]; + m_ToBeLoadedCells.Add(cellInfo); } else @@ -819,17 +836,55 @@ void AddCell(Cell cell, int assetInstanceID) // Calling this from "outside" will not properly update Loaded/ToBeLoadedCells arrays and thus will break the state of streaming. internal bool LoadCell(CellInfo cellInfo, bool ignoreErrorLog = false) { - if (GetCellIndexUpdate(cellInfo.cell, out var cellUpdateInfo, ignoreErrorLog)) // Allocate indices - { - minLoadedCellPos = Vector3Int.Min(minLoadedCellPos, cellInfo.cell.position); - maxLoadedCellPos = Vector3Int.Max(maxLoadedCellPos, cellInfo.cell.position); + var cell = cellInfo.cell; - return AddBricks(cellInfo, cellUpdateInfo, ignoreErrorLog); - } - else + // First try to allocate pool memory. This is what is most likely to fail. + if (ReservePoolChunks(cell.bricks.Length, cellInfo.chunkList, ignoreErrorLog)) { + int indirectionBufferEntries = cell.indirectionEntryInfo.Length; + + for (int entry = 0; entry < indirectionBufferEntries; ++entry) + { + int brickCountAtResForEntry = GetNumberOfBricksAtSubdiv(cell.indirectionEntryInfo[entry], ref cellInfo.tempUpdateInfo.entriesInfo[entry]); + cellInfo.tempUpdateInfo.entriesInfo[entry].numberOfChunks = m_Index.GetNumberOfChunks(brickCountAtResForEntry); + } + + bool canAllocateCell = m_Index.FindSlotsForEntries(ref cellInfo.tempUpdateInfo.entriesInfo); + if (canAllocateCell) + { + bool successfulReserve = m_Index.ReserveChunks(cellInfo.tempUpdateInfo.entriesInfo, ignoreErrorLog); + Debug.Assert(successfulReserve); + + for (int entry = 0; entry < indirectionBufferEntries; ++entry) + { + cellInfo.tempUpdateInfo.entriesInfo[entry].entryPositionInBricksAtMaxRes = cell.indirectionEntryInfo[entry].positionInBricks; + cellInfo.tempUpdateInfo.entriesInfo[entry].minSubdivInCell = cell.indirectionEntryInfo[entry].minSubdiv; + cellInfo.tempUpdateInfo.entriesInfo[entry].hasOnlyBiggerBricks = cell.indirectionEntryInfo[entry].hasOnlyBiggerBricks; + } + cellInfo.loaded = true; + + // Copy proper data inside index buffers and pool textures. + AddBricks(cellInfo); + + minLoadedCellPos = Vector3Int.Min(minLoadedCellPos, cellInfo.cell.position); + maxLoadedCellPos = Vector3Int.Max(maxLoadedCellPos, cellInfo.cell.position); + + ClearDebugData(); + + return true; + } + else + { + // Index allocation failed, we need to release the pool chunks. + ReleasePoolChunks(cellInfo.chunkList); + // We know we should have the space (test done in TryLoadCell above) so it's because of fragmentation. + StartIndexDefragmentation(); + } + return false; } + + return false; } // May not load all cells if there is not enough space given the current budget. @@ -890,6 +945,12 @@ internal void AddPendingAssetLoading(ProbeVolumeAsset asset) m_PendingAssetsToBeLoaded.Remove(key); } + if (asset.chunkSizeInBricks != ProbeBrickPool.GetChunkSizeInBrickCount()) + { + Debug.LogError($"Trying to load Probe Volume data ({asset.name}) baked with an older incompatible version of APV. Please rebake your data."); + return; + } + if (!CheckCompatibilityWithCollection(asset, m_ActiveAssets)) { Debug.LogError($"Trying to load Probe Volume data for a scene that has been baked with different settings than currently loaded ones. " + @@ -912,12 +973,15 @@ internal void AddPendingAssetLoading(ProbeVolumeAsset asset) Vector3Int indexDimension = Vector3Int.zero; Vector3Int minCellPosition = Vector3Int.one * 10000; Vector3Int maxCellPosition = Vector3Int.one * -10000; + int maxSubdiv = -1; bool firstBound = true; foreach (var a in m_PendingAssetsToBeLoaded.Values) { minCellPosition = Vector3Int.Min(minCellPosition, a.minCellPosition); maxCellPosition = Vector3Int.Max(maxCellPosition, a.maxCellPosition); + maxSubdiv = Mathf.Max(maxSubdiv, a.maxSubdivision); + if (firstBound) { m_CurrGlobalBounds = a.globalBounds; @@ -944,7 +1008,7 @@ internal void AddPendingAssetLoading(ProbeVolumeAsset asset) } // |= because this can be called more than once before rebuild is done. - m_NeedsIndexRebuild |= m_Index == null || m_PendingInitInfo.pendingMinCellPosition != minCellPosition || m_PendingInitInfo.pendingMaxCellPosition != maxCellPosition; + m_NeedsIndexRebuild |= m_Index == null || m_PendingInitInfo.pendingMinCellPosition != minCellPosition || m_PendingInitInfo.pendingMaxCellPosition != maxCellPosition /*|| m_PendingInitInfo.pendingMaxSubdiv != maxSubdiv*/; m_PendingInitInfo.pendingMinCellPosition = minCellPosition; m_PendingInitInfo.pendingMaxCellPosition = maxCellPosition; @@ -1031,11 +1095,6 @@ void LoadAsset(ProbeVolumeAsset asset) // Load info coming originally from profile SetMinBrickAndMaxSubdiv(asset.minBrickSize, asset.maxSubdivision); - if (asset.chunkSizeInBricks != m_CurrentProbeVolumeChunkSizeInBricks) - { - m_CurrentProbeVolumeChunkSizeInBricks = asset.chunkSizeInBricks; - AllocateTemporaryDataLocation(); - } ClearDebugData(); @@ -1095,47 +1154,48 @@ void PerformPendingDeletion() m_PendingAssetsToBeUnloaded.Clear(); } - internal int GetNumberOfBricksAtSubdiv(Vector3Int position, int minSubdiv, out Vector3Int minValidLocalIdxAtMaxRes, out Vector3Int sizeOfValidIndicesAtMaxRes) + internal int GetNumberOfBricksAtSubdiv(IndirectionEntryInfo entryInfo, ref ProbeBrickIndex.IndirectionEntryUpdateInfo indirectionEntryUpdateInfo) { - minValidLocalIdxAtMaxRes = Vector3Int.zero; - sizeOfValidIndicesAtMaxRes = Vector3Int.one; + // This is a special case that can be handled manually easily. + if (entryInfo.hasOnlyBiggerBricks) + { + indirectionEntryUpdateInfo.minValidBrickIndexForCellAtMaxRes = Vector3Int.zero; + indirectionEntryUpdateInfo.maxValidBrickIndexForCellAtMaxResPlusOne = Vector3Int.one * CellSize(GetEntrySubdivLevel()) + Vector3Int.one; + indirectionEntryUpdateInfo.brickCount = 1; + return indirectionEntryUpdateInfo.brickCount; + } - var posWS = new Vector3(position.x * MaxBrickSize(), position.y * MaxBrickSize(), position.z * MaxBrickSize()); - Bounds cellBounds = new Bounds(); - cellBounds.min = posWS; - cellBounds.max = posWS + (Vector3.one * MaxBrickSize()); + indirectionEntryUpdateInfo.minValidBrickIndexForCellAtMaxRes = Vector3Int.zero; + Vector3Int sizeOfValidIndicesAtMaxRes = Vector3Int.one; + + float entrySize = GetEntrySize(); + var posWS = new Vector3(entryInfo.positionInBricks.x , entryInfo.positionInBricks.y, entryInfo.positionInBricks.z) * MinBrickSize(); + Bounds entryBounds = new Bounds(); + entryBounds.min = posWS; + entryBounds.max = posWS + (Vector3.one * entrySize); Bounds intersectBound = new Bounds(); - intersectBound.min = Vector3.Max(cellBounds.min, m_CurrGlobalBounds.min); - intersectBound.max = Vector3.Min(cellBounds.max, m_CurrGlobalBounds.max); + intersectBound.min = Vector3.Max(entryBounds.min, m_CurrGlobalBounds.min); + intersectBound.max = Vector3.Min(entryBounds.max, m_CurrGlobalBounds.max); - var toStart = intersectBound.min - cellBounds.min; - minValidLocalIdxAtMaxRes.x = Mathf.CeilToInt((toStart.x) / MinBrickSize()); - minValidLocalIdxAtMaxRes.y = Mathf.CeilToInt((toStart.y) / MinBrickSize()); - minValidLocalIdxAtMaxRes.z = Mathf.CeilToInt((toStart.z) / MinBrickSize()); + var toStart = intersectBound.min - entryBounds.min; + indirectionEntryUpdateInfo.minValidBrickIndexForCellAtMaxRes.x = Mathf.CeilToInt((toStart.x) / MinBrickSize()); + indirectionEntryUpdateInfo.minValidBrickIndexForCellAtMaxRes.y = Mathf.CeilToInt((toStart.y) / MinBrickSize()); + indirectionEntryUpdateInfo.minValidBrickIndexForCellAtMaxRes.z = Mathf.CeilToInt((toStart.z) / MinBrickSize()); - var toEnd = intersectBound.max - cellBounds.min; - sizeOfValidIndicesAtMaxRes.x = Mathf.CeilToInt((toEnd.x) / MinBrickSize()) - minValidLocalIdxAtMaxRes.x + 1; - sizeOfValidIndicesAtMaxRes.y = Mathf.CeilToInt((toEnd.y) / MinBrickSize()) - minValidLocalIdxAtMaxRes.y + 1; - sizeOfValidIndicesAtMaxRes.z = Mathf.CeilToInt((toEnd.z) / MinBrickSize()) - minValidLocalIdxAtMaxRes.z + 1; + var toEnd = intersectBound.max - entryBounds.min; + sizeOfValidIndicesAtMaxRes.x = Mathf.CeilToInt((toEnd.x) / MinBrickSize()) - indirectionEntryUpdateInfo.minValidBrickIndexForCellAtMaxRes.x + 1; + sizeOfValidIndicesAtMaxRes.y = Mathf.CeilToInt((toEnd.y) / MinBrickSize()) - indirectionEntryUpdateInfo.minValidBrickIndexForCellAtMaxRes.y + 1; + sizeOfValidIndicesAtMaxRes.z = Mathf.CeilToInt((toEnd.z) / MinBrickSize()) - indirectionEntryUpdateInfo.minValidBrickIndexForCellAtMaxRes.z + 1; - Vector3Int bricksForCell = new Vector3Int(); - bricksForCell = sizeOfValidIndicesAtMaxRes / CellSize(minSubdiv); + Vector3Int bricksForEntry = new Vector3Int(); + bricksForEntry = sizeOfValidIndicesAtMaxRes / CellSize(entryInfo.minSubdiv); - return bricksForCell.x * bricksForCell.y * bricksForCell.z; - } + indirectionEntryUpdateInfo.maxValidBrickIndexForCellAtMaxResPlusOne = indirectionEntryUpdateInfo.minValidBrickIndexForCellAtMaxRes + sizeOfValidIndicesAtMaxRes; - bool GetCellIndexUpdate(Cell cell, out ProbeBrickIndex.CellIndexUpdateInfo cellUpdateInfo, bool ignoreErrorLog) - { - cellUpdateInfo = new ProbeBrickIndex.CellIndexUpdateInfo(); - - int brickCountsAtResolution = GetNumberOfBricksAtSubdiv(cell.position, cell.minSubdiv, out var minValidLocalIdx, out var sizeOfValidIndices); - cellUpdateInfo.cellPositionInBricksAtMaxRes = cell.position * CellSize(m_MaxSubdivision - 1); - cellUpdateInfo.minSubdivInCell = cell.minSubdiv; - cellUpdateInfo.minValidBrickIndexForCellAtMaxRes = minValidLocalIdx; - cellUpdateInfo.maxValidBrickIndexForCellAtMaxResPlusOne = sizeOfValidIndices + minValidLocalIdx; + indirectionEntryUpdateInfo.brickCount = bricksForEntry.x * bricksForEntry.y * bricksForEntry.z; - return m_Index.AssignIndexChunksToCell(brickCountsAtResolution, ref cellUpdateInfo, ignoreErrorLog); + return indirectionEntryUpdateInfo.brickCount; } /// @@ -1148,6 +1208,18 @@ public void PerformPendingOperations() PerformPendingLoading(); } + internal void InitializeGlobalIndirection() + { + var minCellPosition = m_PendingInitInfo.pendingMinCellPosition; + var maxCellPosition = m_PendingInitInfo.pendingMaxCellPosition; + + m_CellIndices = new ProbeGlobalIndirection(minCellPosition, maxCellPosition, Mathf.Max(1, (int)Mathf.Pow(3, m_MaxSubdivision - 1))); + if (m_SupportStreaming) + { + m_DefragCellIndices = new ProbeGlobalIndirection(minCellPosition, maxCellPosition, Mathf.Max(1, (int)Mathf.Pow(3, m_MaxSubdivision - 1))); + } + } + /// /// Initialize the reference volume. /// @@ -1158,17 +1230,23 @@ void InitProbeReferenceVolume(ProbeVolumeTextureMemoryBudget memoryBudget, Probe { var minCellPosition = m_PendingInitInfo.pendingMinCellPosition; var maxCellPosition = m_PendingInitInfo.pendingMaxCellPosition; + if (!m_ProbeReferenceVolumeInit) { Profiler.BeginSample("Initialize Reference Volume"); - m_Pool = new ProbeBrickPool(memoryBudget, shBands); - m_BlendingPool = new ProbeBrickBlendingPool(blendingMemoryBudget, shBands); + m_Pool = new ProbeBrickPool(m_MemoryBudget, shBands); + m_BlendingPool = new ProbeBrickBlendingPool(m_BlendingMemoryBudget, shBands); m_Index = new ProbeBrickIndex(memoryBudget); - m_CellIndices = new ProbeCellIndices(minCellPosition, maxCellPosition, (int)Mathf.Pow(3, m_MaxSubdivision - 1)); - if (m_CurrentProbeVolumeChunkSizeInBricks != 0) - AllocateTemporaryDataLocation(); + if (m_SupportStreaming) + { + m_DefragIndex = new ProbeBrickIndex(memoryBudget); + } + + InitializeGlobalIndirection(); + + m_TemporaryDataLocation = ProbeBrickPool.CreateDataLocation(ProbeBrickPool.GetChunkSizeInProbeCount(), compressed: false, m_SHBands, "APV_Intermediate", false, true, out m_TemporaryDataLocationMemCost); // initialize offsets m_PositionOffsets[0] = 0.0f; @@ -1176,6 +1254,7 @@ void InitProbeReferenceVolume(ProbeVolumeTextureMemoryBudget memoryBudget, Probe for (int i = 1; i < ProbeBrickPool.kBrickProbeCountPerDim - 1; i++) m_PositionOffsets[i] = i * probeDelta; m_PositionOffsets[m_PositionOffsets.Length - 1] = 1.0f; + Profiler.EndSample(); m_ProbeReferenceVolumeInit = true; @@ -1186,12 +1265,6 @@ void InitProbeReferenceVolume(ProbeVolumeTextureMemoryBudget memoryBudget, Probe } } - void AllocateTemporaryDataLocation() - { - m_TemporaryDataLocation.Cleanup(); - m_TemporaryDataLocation = ProbeBrickPool.CreateDataLocation(m_CurrentProbeVolumeChunkSizeInBricks * ProbeBrickPool.kBrickProbeCountTotal, compressed: false, m_SHBands, "APV_Intermediate", false, true, out m_TemporaryDataLocationMemCost); - } - #if UNITY_EDITOR internal static Func _GetLightingSettingsOrDefaultsFallback; #endif @@ -1234,7 +1307,24 @@ internal void SetTRS(Vector3 position, Quaternion rotation, float minBrickSize) m_Transform.scale = minBrickSize; } - internal void SetMaxSubdivision(int maxSubdivision) => m_MaxSubdivision = System.Math.Min(maxSubdivision, ProbeBrickIndex.kMaxSubdivisionLevels); + internal void SetMaxSubdivision(int maxSubdivision) + { + int newValue = Math.Min(maxSubdivision, ProbeBrickIndex.kMaxSubdivisionLevels); + if (newValue != m_MaxSubdivision) + { + m_MaxSubdivision = System.Math.Min(maxSubdivision, ProbeBrickIndex.kMaxSubdivisionLevels); + if (m_CellIndices != null) + { + m_CellIndices.Cleanup(); + } + if (m_SupportStreaming && m_DefragCellIndices != null) + { + m_DefragCellIndices.Cleanup(); + } + InitializeGlobalIndirection(); + } + } + internal static int CellSize(int subdivisionLevel) => (int)Mathf.Pow(ProbeBrickPool.kBrickCellCount, subdivisionLevel); internal float BrickSize(int subdivisionLevel) => m_Transform.scale * CellSize(subdivisionLevel); internal float MinBrickSize() => m_Transform.scale; @@ -1245,12 +1335,16 @@ internal void SetTRS(Vector3 position, Quaternion rotation, float minBrickSize) internal float GetDistanceBetweenProbes(int subdivisionLevel) => BrickSize(subdivisionLevel) / 3.0f; internal float MinDistanceBetweenProbes() => GetDistanceBetweenProbes(0); + // IMPORTANT! IF THIS VALUE CHANGES DATA NEEDS TO BE REBAKED. + internal int GetGlobalIndirectionEntryMaxSubdiv() => ProbeGlobalIndirection.kEntryMaxSubdivLevel; + + internal int GetEntrySubdivLevel() => Mathf.Min(ProbeGlobalIndirection.kEntryMaxSubdivLevel, m_MaxSubdivision - 1); + internal float GetEntrySize() => BrickSize(GetEntrySubdivLevel()); /// /// Returns whether any brick data has been loaded. /// /// - public bool DataHasBeenLoaded() => m_BricksLoaded; - + public bool DataHasBeenLoaded() => m_LoadedCells.size != 0; internal void Clear() { @@ -1299,7 +1393,7 @@ List GetSourceLocations(int count, int chunkSize, ProbeBrickPool.DataLoca void UpdatePool(List chunkList, Cell.PerScenarioData data, NativeArray validityNeighMaskData, int chunkIndex, int poolIndex) { - var chunkSizeInProbes = m_CurrentProbeVolumeChunkSizeInBricks * ProbeBrickPool.kBrickProbeCountTotal; + var chunkSizeInProbes = ProbeBrickPool.GetChunkSizeInProbeCount(); var chunkOffsetInProbes = chunkIndex * chunkSizeInProbes; var shChunkSize = chunkSizeInProbes * 4; var shChunkOffset = chunkIndex * shChunkSize; @@ -1330,7 +1424,7 @@ void UpdatePool(List chunkList, Cell.PerScenarioData data, NativeArray chunkList, Cell.PerScenarioData data, NativeArray chunkList, Cell.PerScenarioData data, NativeArray validityNeighMaskData, int chunkIndex) { - var chunkSizeInProbes = m_CurrentProbeVolumeChunkSizeInBricks * ProbeBrickPool.kBrickProbeCountTotal; + var chunkSizeInProbes = ProbeBrickPool.GetChunkSizeInBrickCount() * ProbeBrickPool.kBrickProbeCountTotal; var chunkOffsetInProbes = chunkIndex * chunkSizeInProbes; m_TemporaryDataLocation.TexValidity.SetPixelData(validityNeighMaskData.GetSubArray(chunkOffsetInProbes, chunkSizeInProbes), 0); m_TemporaryDataLocation.TexValidity.Apply(false); - var srcChunks = GetSourceLocations(1, m_CurrentProbeVolumeChunkSizeInBricks, m_TemporaryDataLocation); + var srcChunks = GetSourceLocations(1, ProbeBrickPool.GetChunkSizeInBrickCount(), m_TemporaryDataLocation); m_Pool.UpdateValidity(m_TemporaryDataLocation, srcChunks, chunkList, chunkIndex); } @@ -1369,16 +1463,14 @@ bool AddBlendingBricks(BlendingCellInfo blendingCell) if (!bypassBlending && !m_BlendingPool.Allocate(cell.shChunkCount, blendingCell.chunkList)) return false; - var chunkList = bypassBlending ? blendingCell.cellInfo.chunkList : blendingCell.chunkList; - int chunkCount = chunkList.Count; - // Now that we are sure probe data will be uploaded, we can register the cell in the pool if (!blendingCell.cellInfo.indexUpdated) { // Update the cell index UpdateCellIndex(blendingCell.cellInfo); - // Upload validity data directly to main pool - constant per scenario, will not need blending - for (int chunkIndex = 0; chunkIndex < chunkCount; ++chunkIndex) + // Upload validity data directly to main pool - constant per scenario, will not need blending, therefore we use the cellInfo chunk list. + var chunkList = blendingCell.cellInfo.chunkList; + for (int chunkIndex = 0; chunkIndex < chunkList.Count; ++chunkIndex) UpdatePoolValidity(chunkList, cell.scenario0, cell.validityNeighMaskData, chunkIndex); } @@ -1386,7 +1478,8 @@ bool AddBlendingBricks(BlendingCellInfo blendingCell) { if (blendingCell.blendingFactor != scenarioBlendingFactor) { - for (int chunkIndex = 0; chunkIndex < chunkCount; ++chunkIndex) + var chunkList = blendingCell.cellInfo.chunkList; + for (int chunkIndex = 0; chunkIndex < chunkList.Count; ++chunkIndex) { // No blending so do the same operation as AddBricks would do. But because cell is already loaded, // no index or chunk data must change, so only probe values need to be updated @@ -1396,7 +1489,8 @@ bool AddBlendingBricks(BlendingCellInfo blendingCell) } else { - for (int chunkIndex = 0; chunkIndex < chunkCount; ++chunkIndex) + var chunkList = blendingCell.chunkList; + for (int chunkIndex = 0; chunkIndex < chunkList.Count; ++chunkIndex) { UpdatePool(chunkList, cell.scenario0, cell.validityNeighMaskData, chunkIndex, 0); UpdatePool(chunkList, cell.scenario1, cell.validityNeighMaskData, chunkIndex, 1); @@ -1408,28 +1502,31 @@ bool AddBlendingBricks(BlendingCellInfo blendingCell) return true; } - bool AddBricks(CellInfo cellInfo, ProbeBrickIndex.CellIndexUpdateInfo cellUpdateInfo, bool ignoreErrorLog) + bool ReservePoolChunks(int brickCount, List chunkList, bool ignoreErrorLog) { - using var pm = new ProfilerMarker("AddBricks").Auto(); + // calculate the number of chunks necessary + int brickChunksCount = ProbeBrickPool.GetChunkCount(brickCount); + chunkList.Clear(); - var cell = cellInfo.cell; - var bricks = cell.bricks; + // Try to allocate texture space + return m_Pool.Allocate(brickChunksCount, chunkList, ignoreErrorLog); + } - // calculate the number of chunks necessary - int brickChunksCount = ProbeBrickPool.GetChunkCount(bricks.Length, m_CurrentProbeVolumeChunkSizeInBricks); - cellInfo.chunkList.Clear(); + void ReleasePoolChunks(List chunkList) + { + m_Pool.Deallocate(chunkList); + chunkList.Clear(); + } - Debug.Assert(brickChunksCount == cell.shChunkCount); + bool AddBricks(CellInfo cellInfo) + { + using var pm = new ProfilerMarker("AddBricks").Auto(); - // Try to allocate texture space - if (!m_Pool.Allocate(brickChunksCount, cellInfo.chunkList, ignoreErrorLog)) - return false; + var cell = cellInfo.cell; if (enableScenarioBlending) // Register this cell for blending system m_ToBeLoadedBlendingCells.Add(cellInfo.blendingCell); - cellInfo.tempUpdateInfo = cellUpdateInfo; - // If blending is enabled, we rely on it to upload data already blended to avoid popping // If enabled but blending factor is 0, upload here in case blending pool is not already allocated if (!enableScenarioBlending || scenarioBlendingFactor == 0.0f || !cell.hasTwoScenarios) @@ -1458,18 +1555,17 @@ bool AddBricks(CellInfo cellInfo, ProbeBrickIndex.CellIndexUpdateInfo cellUpdate void UpdateCellIndex(CellInfo cellInfo) { cellInfo.indexUpdated = true; - m_BricksLoaded = true; // Build index var bricks = cellInfo.cell.bricks; var cellUpdateInfo = cellInfo.tempUpdateInfo; - m_Index.AddBricks(cellInfo.cell, bricks, cellInfo.chunkList, m_CurrentProbeVolumeChunkSizeInBricks, m_Pool.GetPoolWidth(), m_Pool.GetPoolHeight(), cellUpdateInfo); + m_Index.AddBricks(cellInfo.cell, bricks, cellInfo.chunkList, ProbeBrickPool.GetChunkSizeInBrickCount(), m_Pool.GetPoolWidth(), m_Pool.GetPoolHeight(), cellUpdateInfo); // Update CellInfo cellInfo.updateInfo = cellUpdateInfo; // Update indirection buffer - m_CellIndices.UpdateCell(cellInfo.flatIdxInCellIndices, cellUpdateInfo); + m_CellIndices.UpdateCell(cellInfo.flatIndicesInGlobalIndirection, cellUpdateInfo); } void ReleaseBricks(CellInfo cellInfo) @@ -1505,45 +1601,59 @@ public void UpdateConstantBuffer(CommandBuffer cmd, ProbeVolumeShadingParameters viewBias *= MinDistanceBetweenProbes(); } - var minCellPos = m_CellIndices.GetCellMinPosition(); - var indexDim = m_CellIndices.GetCellIndexDimension(); + var minCellPos = m_CellIndices.GetGlobalIndirectionMinEntry(); + var indexDim = m_CellIndices.GetGlobalIndirectionDimension(); var poolDim = m_Pool.GetPoolDimensions(); + m_CellIndices.GetMinMaxEntry(out Vector3Int minEntry, out Vector3Int maxEntry); + var entriesPerCell = m_CellIndices.entriesPerCellDimension; ShaderVariablesProbeVolumes shaderVars; shaderVars._Biases_CellInMinBrick_MinBrickSize = new Vector4(normalBias, viewBias, (int)Mathf.Pow(3, m_MaxSubdivision - 1), MinBrickSize()); shaderVars._IndicesDim_IndexChunkSize = new Vector4(indexDim.x, indexDim.y, indexDim.z, ProbeBrickIndex.kIndexChunkSize); - shaderVars._MinCellPos_Noise = new Vector4(minCellPos.x, minCellPos.y, minCellPos.z, parameters.samplingNoise); + shaderVars._MinEntryPos_Noise = new Vector4(minEntry.x, minEntry.y, minEntry.z, parameters.samplingNoise); // TODO_FCC! IMPORTANT! RENAME! shaderVars._PoolDim_CellInMeters = new Vector4(poolDim.x, poolDim.y, poolDim.z, MaxBrickSize()); - shaderVars._Weight_MinLoadedCell = new Vector4(parameters.weight, minLoadedCellPos.x, minLoadedCellPos.y, minLoadedCellPos.z); - shaderVars._MaxLoadedCell_FrameIndex = new Vector4(maxLoadedCellPos.x, maxLoadedCellPos.y, maxLoadedCellPos.z, parameters.frameIndexForNoise); - shaderVars._LeakReductionParams = new Vector4((int)parameters.leakReductionMode, parameters.occlusionWeightContribution, parameters.minValidNormalWeight, 0.0f); + shaderVars._RcpPoolDim_Padding = new Vector4(1.0f / poolDim.x, 1.0f / poolDim.y, 1.0f / poolDim.z, 0.0f); + shaderVars._Weight_MinLoadedCellInEntries = new Vector4(parameters.weight, minLoadedCellPos.x * entriesPerCell, minLoadedCellPos.y * entriesPerCell, minLoadedCellPos.z * entriesPerCell); + shaderVars._MaxLoadedCellInEntries_FrameIndex = new Vector4((maxLoadedCellPos.x + 1) * entriesPerCell - 1, (maxLoadedCellPos.y + 1) * entriesPerCell - 1, (maxLoadedCellPos.z + 1) * entriesPerCell - 1, parameters.frameIndexForNoise); shaderVars._LeakReductionParams = new Vector4((int)parameters.leakReductionMode, parameters.occlusionWeightContribution, parameters.minValidNormalWeight, 0.0f); // TODO: Expose this somewhere UX visible? To discuss. - shaderVars._NormalizationClamp_Padding12 = new Vector4(parameters.reflNormalizationLowerClamp, parameters.reflNormalizationUpperClamp, 0, 0); + shaderVars._NormalizationClamp_IndirectionEntryDim_Padding = new Vector4(parameters.reflNormalizationLowerClamp, parameters.reflNormalizationUpperClamp, GetEntrySize(), 0); ConstantBuffer.PushGlobal(cmd, shaderVars, m_CBShaderID); } - /// - /// Cleanup loaded data. - /// - void CleanupLoadedData() + void DeinitProbeReferenceVolume() { - m_BricksLoaded = false; - - UnloadAllCells(); - if (m_ProbeReferenceVolumeInit) { m_Index.Cleanup(); m_CellIndices.Cleanup(); - m_Pool.Cleanup(); - m_BlendingPool.Cleanup(); + + if (m_SupportStreaming) + { + m_DefragIndex.Cleanup(); + m_DefragCellIndices.Cleanup(); + } + + if (m_Pool != null) + { + m_Pool.Cleanup(); + m_BlendingPool.Cleanup(); + } m_TemporaryDataLocation.Cleanup(); } - m_ProbeReferenceVolumeInit = false; ClearDebugData(); + m_ProbeReferenceVolumeInit = false; + } + + /// + /// Cleanup loaded data. + /// + void CleanupLoadedData() + { + UnloadAllCells(); + DeinitProbeReferenceVolume(); } } } diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeTouchupVolume.cs b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeTouchupVolume.cs index 90ea9412bc4..044ec58c530 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeTouchupVolume.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeTouchupVolume.cs @@ -1,44 +1,83 @@ -using System.Collections.Generic; -using UnityEngine.Rendering; -using UnityEngine.SceneManagement; - -#if UNITY_EDITOR -using UnityEditor; -#endif +using System; namespace UnityEngine.Rendering { /// - /// A marker to determine what area of the scene is considered by the Probe Volumes system + /// A marker to adjust probes in an area of the scene. /// [ExecuteAlways] - [AddComponentMenu("Light/Probe Volume Touchup")] - public class ProbeTouchupVolume : MonoBehaviour + [AddComponentMenu("Light/Probe Adjustment Volume")] + public class ProbeTouchupVolume : MonoBehaviour, ISerializationCallbackReceiver { + /// The type of shape that an adjustment volume can take. + public enum Shape + { + /// A Box shape. + Box, + /// A Sphere shape. + Sphere, + }; + + /// The shape of the adjustment volume + public Shape shape = Shape.Box; + /// - /// A scale to apply to probes falling within the invalidation volume. It is really important to use this with caution as it can lead to inconsistent lighting. + /// The size for box shape. /// - [Range(0.0001f, 2.0f)] - public float intensityScale = 1.0f; + [Min(0.0f), Tooltip("Modify the size of this Probe Adjustment Volume. This is unaffected by the GameObject's Transform's Scale property.")] + public Vector3 size = new Vector3(1, 1, 1); + /// - /// Whether to invalidate all probes falling within this volume. + /// The size for sphere shape. /// - public bool invalidateProbes = false; + [Min(0.0f), Tooltip("Modify the radius of this Probe Adjustment Volume. This is unaffected by the GameObject's Transform's Scale property.")] + public float radius = 1.0f; + + + /// The mode that adjustment volume will operate in. It determines what probes falling within the volume will do. + public enum Mode + { + /// Invalidate the probes within the adjustment volume. + InvalidateProbes, + /// Override the dilation validity threshold for the probes within the adjustment volume. + OverrideValidityThreshold, + /// Apply an explicit virtual offset to the probes within the adjustment volume. + ApplyVirtualOffset, + /// Override the virtual offset settings for the probes within the adjustment volume. + OverrideVirtualOffsetSettings, + }; + + /// Choose what to do with probes falling inside this volume + [Tooltip("Choose what to do with probes falling inside this volume.")] + public Mode mode = Mode.InvalidateProbes; + /// - /// Whether to use a custom threshold for dilation for probes falling withing this volume. + /// A scale to apply to probes falling within the invalidation volume. It is really important to use this with caution as it can lead to inconsistent lighting. /// - public bool overrideDilationThreshold = false; + [Range(0.0001f, 2.0f), InspectorName("Probe Intensity Scale"), Tooltip("A scale to be applied to all probes that fall within this Probe Adjustment Volume.")] + public float intensityScale = 1.0f; /// /// The overridden dilation threshold. /// - [Range(0.0f, 0.99f)] + [Range(0.0f, 0.95f), InspectorName("Dilation Validity Threshold"), Tooltip("Override the Dilation Validity Threshold for probes covered by this Probe Adjustment Volume. Higher values increase the chance of probes being considered invalid.")] public float overriddenDilationThreshold = 0.75f; - /// - /// The size. - /// - public Vector3 size = new Vector3(1, 1, 1); + /// The rotation angles for the virtual offset direction. + [Tooltip("The rotation angles for the virtual offset direction.")] + public Vector3 virtualOffsetRotation = Vector3.zero; + + /// Determines how far probes are pushed along the specified virtual offset direction. + [Min(0.0f), Tooltip("Determines how far probes are pushed along the specified virtual offset direction.")] + public float virtualOffsetDistance = 1.0f; + + /// Determines how far Unity pushes a probe out of geometry after a ray hit. + [Range(0f, 1f), Tooltip("Determines how far Unity pushes a probe out of geometry after a ray hit.")] + public float geometryBias = 0.01f; + + /// Distance from the probe position used to determine the origin of the sampling ray. + [Range(-0.05f, 0f), Tooltip("Distance from the probe position used to determine the origin of the sampling ray.")] + public float rayOriginBias = -0.001f; #if UNITY_EDITOR /// @@ -52,9 +91,94 @@ public Vector3 GetExtents() internal void GetOBBandAABB(out ProbeReferenceVolume.Volume volume, out Bounds bounds) { - volume = new ProbeReferenceVolume.Volume(Matrix4x4.TRS(transform.position, transform.rotation, GetExtents()), 0, 0); - bounds = volume.CalculateAABB(); + if (shape == Shape.Box) + { + volume = new ProbeReferenceVolume.Volume(Matrix4x4.TRS(transform.position, transform.rotation, GetExtents()), 0, 0); + bounds = volume.CalculateAABB(); + } + else + { + volume = default; + bounds = new Bounds(transform.position, radius * Vector3.up); + } + } + + internal bool IntersectsVolume(in ProbeReferenceVolume.Volume touchupOBB, in Bounds touchupBounds, Bounds volumeBounds) + { + if (shape == Shape.Box) + return ProbeVolumePositioning.OBBAABBIntersect(touchupOBB, volumeBounds, touchupBounds); + else + return volumeBounds.SqrDistance(touchupBounds.center) < radius * radius; + } + + internal bool ContainsPoint(in ProbeReferenceVolume.Volume touchupOBB, in Vector3 touchupCenter, in Vector3 position) + { + if (shape == Shape.Box) + return ProbeVolumePositioning.OBBContains(touchupOBB, position); + else + return (touchupCenter - position).sqrMagnitude < radius * radius; + } + + internal Vector3 GetVirtualOffset() + { + if (mode != Mode.ApplyVirtualOffset) + return Vector3.zero; + return (transform.rotation * Quaternion.Euler(virtualOffsetRotation) * Vector3.forward) * virtualOffsetDistance; } #endif + + + // Migration related stuff + + enum Version + { + Initial, + Mode, + + Count + } + + [SerializeField] + Version version = Version.Count; + + /// Whether to invalidate all probes falling within this volume. + [Obsolete("Use mode")] + public bool invalidateProbes = false; + /// Whether to use a custom threshold for dilation for probes falling withing this volume. + [Obsolete("Use mode")] + public bool overrideDilationThreshold = false; + + void Awake() + { + if (version == Version.Count) + return; + + if (version == Version.Initial) + { +#pragma warning disable 618 // Type or member is obsolete + if (invalidateProbes) + mode = Mode.InvalidateProbes; + else if (overrideDilationThreshold) + mode = Mode.OverrideValidityThreshold; +#pragma warning restore 618 + + version++; + } + } + + // This piece of code is needed because some objects could have been created before existence of Version enum + /// OnBeforeSerialize needed to handle migration before the versioning system was in place. + void ISerializationCallbackReceiver.OnBeforeSerialize() + { + if (version == Version.Count) // serializing a newly created object + version = Version.Count - 1; // mark as up to date + } + + /// OnAfterDeserialize needed to handle migration before the versioning system was in place. + void ISerializationCallbackReceiver.OnAfterDeserialize() + { + if (version == Version.Count) // deserializing and object without version + version = Version.Initial; // reset to run the migration + } } -} // UnityEngine.Rendering.HDPipeline +} diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolume.cs b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolume.cs index 83b5a1a23ff..9a55120c4eb 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolume.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolume.cs @@ -67,7 +67,7 @@ public class ProbeVolume : MonoBehaviour /// Whether spaces with no renderers need to be filled with bricks at lowest subdivision level. [HideInInspector] - [Tooltip("Whether spaces with no renderers need to be filled with bricks at lowest subdivision level.")] + [Tooltip("Whether Unity should fill empty space between renderers with bricks at the lowest subdivision level.")] public bool fillEmptySpaces = false; #if UNITY_EDITOR @@ -231,6 +231,13 @@ void OnDisable() return !GeometryUtility.TestPlanesAABB(frustumPlanes, volumeAABB); } + + struct CellDebugData + { + public Vector4 center; + public Color color; + } + // TODO: We need to get rid of Handles.DrawWireCube to be able to have those at runtime as well. void OnDrawGizmos() { @@ -307,28 +314,47 @@ void OnDrawGizmos() if (debugDisplay.drawCells) { - IEnumerable GetVisibleCellCentersAndState() + IEnumerable GetVisibleCellDebugData() { + Color s_LoadedColor = new Color(0, 1, 0.5f, 0.2f); + Color s_UnloadedColor = new Color(1, 0.0f, 0.0f, 0.2f); + Color s_LowScoreColor = new Color(0, 0, 0, 0.2f); + Color s_HighScoreColor = new Color(1, 1, 0, 0.2f); + + var prv = ProbeReferenceVolume.instance; + + float minStreamingScore = prv.minStreamingScore; + float streamingScoreRange = prv.maxStreamingScore - prv.minStreamingScore; + if (debugDisplay.realtimeSubdivision) { - foreach (var kp in ProbeReferenceVolume.instance.realtimeSubdivisionInfo) + foreach (var kp in prv.realtimeSubdivisionInfo) { var center = kp.Key.center; - yield return new Vector4(center.x, center.y, center.z, 1.0f); + yield return new CellDebugData { center = center, color = s_LoadedColor }; } } else { foreach (var cellInfo in ProbeReferenceVolume.instance.cells.Values) { - if (ShouldCullCell(cellInfo.cell.position, ProbeReferenceVolume.instance.GetTransform().posWS)) + if (ShouldCullCell(cellInfo.cell.position, prv.GetTransform().posWS)) continue; var cell = cellInfo.cell; var positionF = new Vector4(cell.position.x, cell.position.y, cell.position.z, 0.0f); - var center = positionF * cellSizeInMeters + cellSizeInMeters * 0.5f * Vector4.one; - center.w = cellInfo.loaded ? 1.0f : 0.0f; - yield return center; + var output = new CellDebugData(); + output.center = positionF * cellSizeInMeters + cellSizeInMeters * 0.5f * Vector4.one; + if (debugDisplay.displayCellStreamingScore) + { + float lerpFactor = (cellInfo.streamingScore - minStreamingScore) / streamingScoreRange; + output.color = Color.Lerp(s_HighScoreColor, s_LowScoreColor, lerpFactor); + } + else + { + output.color = cellInfo.loaded ? s_LoadedColor : s_UnloadedColor; + } + yield return output; } } } @@ -339,15 +365,15 @@ IEnumerable GetVisibleCellCentersAndState() if (cellGizmo == null) cellGizmo = new MeshGizmo(); cellGizmo.Clear(); - foreach (var center in GetVisibleCellCentersAndState()) + foreach (var cell in GetVisibleCellDebugData()) { - bool loaded = center.w == 1.0f; - - Gizmos.color = loaded ? new Color(0, 1, 0.5f, 0.2f) : new Color(1, 0.0f, 0.0f, 0.2f); + Gizmos.color = cell.color; Gizmos.matrix = trs; - Gizmos.DrawCube(center, Vector3.one * cellSizeInMeters); - cellGizmo.AddWireCube(center, Vector3.one * cellSizeInMeters, loaded ? new Color(0, 1, 0.5f, 1) : new Color(1, 0.0f, 0.0f, 1)); + Gizmos.DrawCube(cell.center, Vector3.one * cellSizeInMeters); + var wireColor = cell.color; + wireColor.a = 1.0f; + cellGizmo.AddWireCube(cell.center, Vector3.one * cellSizeInMeters, wireColor); } cellGizmo.RenderWireframe(Gizmos.matrix, gizmoName: "Brick Gizmo Rendering"); Gizmos.matrix = oldGizmoMatrix; diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolume.hlsl b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolume.hlsl index 5893a64a27c..90cc164c77f 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolume.hlsl +++ b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolume.hlsl @@ -7,20 +7,22 @@ // Unpack variables #define _PoolDim _PoolDim_CellInMeters.xyz +#define _RcpPoolDim _RcpPoolDim_Padding.xyz #define _CellInMeters _PoolDim_CellInMeters.w -#define _MinCellPosition _MinCellPos_Noise.xyz -#define _PVSamplingNoise _MinCellPos_Noise.w -#define _CellIndicesDim _IndicesDim_IndexChunkSize.xyz +#define _MinEntryPosition _MinEntryPos_Noise.xyz +#define _PVSamplingNoise _MinEntryPos_Noise.w +#define _GlobalIndirectionDimension _IndicesDim_IndexChunkSize.xyz #define _IndexChunkSize _IndicesDim_IndexChunkSize.w #define _NormalBias _Biases_CellInMinBrick_MinBrickSize.x #define _ViewBias _Biases_CellInMinBrick_MinBrickSize.y #define _MinBrickSize _Biases_CellInMinBrick_MinBrickSize.w -#define _Weight _Weight_MinLoadedCell.x -#define _MinLoadedCell _Weight_MinLoadedCell.yzw -#define _MaxLoadedCell _MaxLoadedCell_FrameIndex.xyz -#define _NoiseFrameIndex _MaxLoadedCell_FrameIndex.w -#define _MinReflProbeNormalizationFactor _NormalizationClamp_Padding12.x -#define _MaxReflProbeNormalizationFactor _NormalizationClamp_Padding12.y +#define _Weight _Weight_MinLoadedCellInEntries.x +#define _MinLoadedCellInEntries _Weight_MinLoadedCellInEntries.yzw +#define _MaxLoadedCellInEntries _MaxLoadedCellInEntries_FrameIndex.xyz +#define _NoiseFrameIndex _MaxLoadedCellInEntries_FrameIndex.w +#define _MinReflProbeNormalizationFactor _NormalizationClamp_IndirectionEntryDim_Padding.x +#define _MaxReflProbeNormalizationFactor _NormalizationClamp_IndirectionEntryDim_Padding.y +#define _GlobalIndirectionEntryDim _NormalizationClamp_IndirectionEntryDim_Padding.z #ifndef DECODE_SH #include "Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/DecodeSH.hlsl" @@ -162,8 +164,8 @@ float3 GetSnappedProbePosition(float3 posWS, uint subdiv) float GetNormalWeight(int3 offset, float3 posWS, float3 sample0Pos, float3 normalWS, int subdiv) { // TODO: This can be optimized. - float3 samplePos = sample0Pos + offset * ProbeDistance(subdiv); - float3 vecToProbe = normalize((samplePos)-posWS); + float3 samplePos = (sample0Pos - posWS) + offset * ProbeDistance(subdiv); + float3 vecToProbe = normalize(samplePos); float weight = saturate(dot(vecToProbe, normalWS) - _LeakReductionParams.z); return weight; @@ -206,15 +208,15 @@ bool LoadCellIndexMetaData(int cellFlatIdx, out int chunkIndex, out int stepSize uint GetIndexData(APVResources apvRes, float3 posWS) { - int3 cellPos = floor(posWS / _CellInMeters); - float3 topLeftCellWS = cellPos * _CellInMeters; + int3 entryPos = floor(posWS / _GlobalIndirectionEntryDim); + float3 topLeftEntryWS = entryPos * _GlobalIndirectionEntryDim; - bool isALoadedCell = all(cellPos <= _MaxLoadedCell) && all(cellPos >= _MinLoadedCell); + bool isALoadedCell = all(entryPos <= _MaxLoadedCellInEntries) && all(entryPos >= _MinLoadedCellInEntries); // Make sure we start from 0 - cellPos -= (int3)_MinCellPosition; + entryPos -= (int3)_MinEntryPosition; - int flatIdx = cellPos.z * (_CellIndicesDim.x * _CellIndicesDim.y) + cellPos.y * _CellIndicesDim.x + cellPos.x; + int flatIdx = entryPos.z * (_GlobalIndirectionDimension.x * _GlobalIndirectionDimension.y) + entryPos.y * _GlobalIndirectionDimension.x + entryPos.x; int stepSize = 0; int3 minRelativeIdx, maxRelativeIdx; @@ -224,7 +226,7 @@ uint GetIndexData(APVResources apvRes, float3 posWS) if (isALoadedCell && LoadCellIndexMetaData(flatIdx, chunkIdx, stepSize, minRelativeIdx, maxRelativeIdx)) { - float3 residualPosWS = posWS - topLeftCellWS; + float3 residualPosWS = posWS - topLeftEntryWS; int3 localBrickIndex = floor(residualPosWS / (_MinBrickSize * stepSize)); // Out of bounds. @@ -273,49 +275,39 @@ APVResources FillAPVResources() } - -bool TryToGetPoolUVWAndSubdiv(APVResources apvRes, float3 posWS, float3 normalWS, float3 viewDirWS, out float3 uvw, out uint subdiv, out float3 biasedPosWS) +bool TryToGetPoolUVWAndSubdiv(APVResources apvRes, float3 posWSForSample, out float3 uvw, out uint subdiv) { - uvw = 0; - // Note: we could instead early return when we know we'll have invalid UVs, but some bade code gen on Vulkan generates shader warnings if we do. - bool hasValidUVW = true; - - float4 posWSForSample = float4(posWS + normalWS * _NormalBias - + viewDirWS * _ViewBias, 1.0); - biasedPosWS = posWSForSample.xyz; - - uint3 poolDim = (uint3)_PoolDim; - // resolve the index float3 posRS = posWSForSample.xyz / _MinBrickSize; uint packed_pool_idx = GetIndexData(apvRes, posWSForSample.xyz); - // no valid brick loaded for this index, fallback to ambient probe - if (packed_pool_idx == 0xffffffff) - { - hasValidUVW = false; - } - // unpack pool idx // size is encoded in the upper 4 bits subdiv = (packed_pool_idx >> 28) & 15; float cellSize = pow(3.0, subdiv); uint flattened_pool_idx = packed_pool_idx & ((1 << 28) - 1); uint3 pool_idx; - pool_idx.z = flattened_pool_idx / (poolDim.x * poolDim.y); + uint3 poolDim = (uint3)_PoolDim; + pool_idx.z = flattened_pool_idx * _RcpPoolDim.x * _RcpPoolDim.y; flattened_pool_idx -= pool_idx.z * (poolDim.x * poolDim.y); - pool_idx.y = flattened_pool_idx / poolDim.x; + pool_idx.y = flattened_pool_idx * _RcpPoolDim.x; pool_idx.x = flattened_pool_idx - (pool_idx.y * poolDim.x); - uvw = ((float3) pool_idx + 0.5) / _PoolDim; // calculate uv offset and scale float3 offset = frac(posRS / (float)cellSize); // [0;1] in brick space //offset = clamp( offset, 0.25, 0.75 ); // [0.25;0.75] in brick space (is this actually necessary?) - offset *= 3.0 / _PoolDim; // convert brick footprint to texels footprint in pool texel space - uvw += offset; // add the final offset + uvw = ((float3)pool_idx + 0.5 + 3.0 * offset) * _RcpPoolDim; // add offset with brick footprint converted to text footprint in pool texel space - return hasValidUVW; + // no valid brick loaded for this index, fallback to ambient probe + // Note: we could instead early return when we know we'll have invalid UVs, but some bade code gen on Vulkan generates shader warnings if we do. + return packed_pool_idx != 0xffffffff; +} + +bool TryToGetPoolUVWAndSubdiv(APVResources apvRes, float3 posWS, float3 normalWS, float3 viewDirWS, out float3 uvw, out uint subdiv, out float3 biasedPosWS) +{ + biasedPosWS = posWS + normalWS * _NormalBias + viewDirWS * _ViewBias; + return TryToGetPoolUVWAndSubdiv(apvRes, biasedPosWS, uvw, subdiv); } bool TryToGetPoolUVW(APVResources apvRes, float3 posWS, float3 normalWS, float3 viewDir, out float3 uvw) @@ -458,7 +450,7 @@ void WarpUVWLeakReduction(APVResources apvRes, float3 posWS, float3 normalWS, in float3 oneMinTexFrac = 1.0f - texFrac; uint validityMask = LOAD_TEXTURE3D(apvRes.Validity, texCoordInt).x * 255; - float3 newFrac = 0.0f; + float3 fracOffset = -texFrac; float weights[8] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; float totalW = 0.0f; int i = 0; @@ -483,10 +475,10 @@ void WarpUVWLeakReduction(APVResources apvRes, float3 posWS, float3 normalWS, in for (i = 0; i < 8; ++i) { uint3 offset = GetSampleOffset(i); - newFrac += (float3)offset * weights[i] * rcp(totalW); + fracOffset += (float3)offset * weights[i] * rcp(totalW); } - uvw = ((texCoordFloat - texFrac + newFrac + 0.5) * rcp(_PoolDim)); + uvw = uvw + fracOffset * _RcpPoolDim; } @@ -562,7 +554,7 @@ void EvaluateAdaptiveProbeVolume(APVSample apvSample, float3 normalWS, float3 ba #ifdef PROBE_VOLUMES_L1 EvaluateAPVL1(apvSample, normalWS, bakeDiffuseLighting); EvaluateAPVL1(apvSample, backNormalWS, backBakeDiffuseLighting); -#elif PROBE_VOLUMES_L2 +#elif defined(PROBE_VOLUMES_L2) EvaluateAPVL1L2(apvSample, normalWS, bakeDiffuseLighting); EvaluateAPVL1L2(apvSample, backNormalWS, backBakeDiffuseLighting); #endif @@ -603,7 +595,7 @@ void EvaluateAdaptiveProbeVolume(in float3 posWS, in float3 normalWS, in float3 EvaluateAPVL1(apvSample, normalWS, bakeDiffuseLighting); EvaluateAPVL1(apvSample, backNormalWS, backBakeDiffuseLighting); EvaluateAPVL1(apvSample, reflDir, lightingInReflDir); -#elif PROBE_VOLUMES_L2 +#elif defined(PROBE_VOLUMES_L2) EvaluateAPVL1L2(apvSample, normalWS, bakeDiffuseLighting); EvaluateAPVL1L2(apvSample, backNormalWS, backBakeDiffuseLighting); EvaluateAPVL1L2(apvSample, reflDir, lightingInReflDir); diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeAsset.cs b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeAsset.cs index 0de741c5db0..dea28038cdc 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeAsset.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeAsset.cs @@ -18,6 +18,7 @@ internal enum AssetVersion ChunkBasedIndex, BinaryRuntimeDebugSplit, BinaryTextureData, + IndirectionEntries, Max, Current = Max - 1 } diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePositioning.cs b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePositioning.cs index 0c509700add..9e99371b6bc 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePositioning.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePositioning.cs @@ -39,6 +39,19 @@ public static bool OBBIntersect(in ProbeReferenceVolume.Volume a, in ProbeRefere return true; } + public static bool OBBContains(in ProbeReferenceVolume.Volume obb, Vector3 point) + { + float lenX2 = obb.X.sqrMagnitude; + float lenY2 = obb.Y.sqrMagnitude; + float lenZ2 = obb.Z.sqrMagnitude; + + // Project in OBB space + point -= obb.corner; + point = new Vector3(Vector3.Dot(point, obb.X), Vector3.Dot(point, obb.Y), Vector3.Dot(point, obb.Z)); + + return (0.0f < point.x && point.x < lenX2) && (0.0f < point.y && point.y < lenY2) && (0.0f < point.z && point.z < lenZ2); + } + // Test between a OBB and an AABB. The AABB of the OBB is requested to avoid recalculating it public static bool OBBAABBIntersect(in ProbeReferenceVolume.Volume a, in Bounds b, in Bounds aAABB) { diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ShaderVariablesProbeVolumes.cs b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ShaderVariablesProbeVolumes.cs index a28d1567c38..b3da00f62f2 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ShaderVariablesProbeVolumes.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ShaderVariablesProbeVolumes.cs @@ -35,12 +35,13 @@ public enum APVLeakReductionMode internal unsafe struct ShaderVariablesProbeVolumes { public Vector4 _PoolDim_CellInMeters; - public Vector4 _MinCellPos_Noise; + public Vector4 _RcpPoolDim_Padding; + public Vector4 _MinEntryPos_Noise; public Vector4 _IndicesDim_IndexChunkSize; public Vector4 _Biases_CellInMinBrick_MinBrickSize; public Vector4 _LeakReductionParams; - public Vector4 _Weight_MinLoadedCell; - public Vector4 _MaxLoadedCell_FrameIndex; - public Vector4 _NormalizationClamp_Padding12; + public Vector4 _Weight_MinLoadedCellInEntries; + public Vector4 _MaxLoadedCellInEntries_FrameIndex; + public Vector4 _NormalizationClamp_IndirectionEntryDim_Padding; } } diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ShaderVariablesProbeVolumes.cs.hlsl b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ShaderVariablesProbeVolumes.cs.hlsl index acd8c020781..6bcbd41fe2a 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ShaderVariablesProbeVolumes.cs.hlsl +++ b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ShaderVariablesProbeVolumes.cs.hlsl @@ -14,13 +14,14 @@ // PackingRules = Exact GLOBAL_CBUFFER_START(ShaderVariablesProbeVolumes, b5) float4 _PoolDim_CellInMeters; - float4 _MinCellPos_Noise; + float4 _RcpPoolDim_Padding; + float4 _MinEntryPos_Noise; float4 _IndicesDim_IndexChunkSize; float4 _Biases_CellInMinBrick_MinBrickSize; float4 _LeakReductionParams; - float4 _Weight_MinLoadedCell; - float4 _MaxLoadedCell_FrameIndex; - float4 _NormalizationClamp_Padding12; + float4 _Weight_MinLoadedCellInEntries; + float4 _MaxLoadedCellInEntries_FrameIndex; + float4 _NormalizationClamp_IndirectionEntryDim_Padding; CBUFFER_END diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Volume/VolumeManager.cs b/Packages/com.unity.render-pipelines.core/Runtime/Volume/VolumeManager.cs index 8eb11f90364..44a66944597 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Volume/VolumeManager.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Volume/VolumeManager.cs @@ -564,6 +564,9 @@ static void SortByPriority(List volumes) static bool IsVolumeRenderedByCamera(Volume volume, Camera camera) { #if UNITY_2018_3_OR_NEWER && UNITY_EDITOR + // GameObject for default global volume may not belong to any scene, following check prevents it from being culled + if (!volume.gameObject.scene.IsValid()) + return true; // IsGameObjectRenderedByCamera does not behave correctly when camera is null so we have to catch it here. return camera == null ? true : UnityEditor.SceneManagement.StageUtility.IsGameObjectRenderedByCamera(volume.gameObject, camera); #else diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Decal.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Decal.md index f59ff5f173a..dcc2ff4f1a1 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Decal.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Decal.md @@ -37,21 +37,14 @@ To control the Frame Settings and set Decal Layers for a specific Camera: ### Using Decal Layers -When you enable Decal Layers, a Decal only affects a Mesh Renderer or Terrain if they both use a matching Decal Layer. You can use Decal Layers to separate Meshes from specific [Decal Projectors](Decal-Projector.md) in your Scene. To do this: +When you enable Decal Layers, a Decal only affects a Mesh Renderer or Terrain if they both use a matching Rendering Layer. You can use Decal Layers to separate Meshes from specific [Decal Projectors](Decal-Projector.md) in your Scene. To do this: 1. Click on a Decal Projector in the Hierarchy or the Scene view to view it in the Inspector. -2. Use the **Decal Layer** property drop-down to select which Decal Layers this Decal Projector affects. +2. Use the **Rendering Layer Mask** property drop-down to select which Rendering Layers this Decal Projector affects. 4. Click on a Mesh Renderer or Terrain in the Hierarchy or the Scene view to view it in the Inspector. 5. Use the **Rendering Layer Mask** drop-down (See [MeshRenderer](https://docs.unity3d.com/Manual/class-MeshRenderer.html) for GameObjects or [OtherSettings](https://docs.unity3d.com/Manual/terrain-OtherSettings.html) for Terrain) to select which Decal Layers affect this Mesh Renderer or Terrain. -### Renaming Decal Layers - -By default, in the UI for Decal Projectors, Mesh Renderers, or Terrain, Decal Layers are named **Decal Layer 1-7**. You can give each Decal Layer a specific name. To do this: - -1. Open the [HDRP Global Settings](Default-Settings-Window.md). -2. Expand the **Decal Layer Names** section. - -Here you can set the name of each Decal Layer individually. +To rename a Rendering Layer, see [Renaming rendering Layers](Rendering-Layers.md#renaming-rendering-layers). ### How Decal Layers affect performance @@ -67,7 +60,7 @@ HDRP renders Material depth in a Depth Prepass to apply decals to opaque Materia 2. Disable the **Receive Decals** property. -If you use the Decal Layer system to change the **Rendering Layer Mask** of a Mesh Renderer or Terrain to disable decal, it doesn't have an effect on your application's performance. +**Note:** When you use the **Rendering Layer Mask** of a Mesh Renderer or Terrain to disable decal on a specific Decal Layer, it doesn't affect your application's performance. ## Additive Normal Blending diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Default-Settings-Window.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Default-Settings-Window.md index 069b737a970..a7615400f3c 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Default-Settings-Window.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Default-Settings-Window.md @@ -23,12 +23,12 @@ The [Frame Settings](Frame-Settings.md) control the rendering passes that Camera Use this section to set default values for the Frame Settings that all Cameras use if you don't enable their Custom Frame Settings checkbox. For information about what each property does, see [Frame Settings](Frame-Settings.md). -## Layers Names +## Rendering Layers | **Property** | **Description** | | --------------------------| ------------------------------------------------------------ | -| Light Layer Names | The name displayed on Lights and Meshes when using [Light Layers](Light-Layers.md). | -| Decal Layer Names | The name displayed on decals and Meshes when using [Decal Layers](Decal.md). | +| Default Mesh Rendering Layer Mask | Defines the Default Rendering Layer Mask for any Terrains or Renderer you create after you set this property.
To set a Layer Mast on existing Terrains or Renderers, use [Decal Layers](Decal.md.) | +| Rendering Layer Names | Defines the number and names of the Rendering Layers in your project. | ## Custom Post Process Orders diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Frame-Settings.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Frame-Settings.md index d04f2fdb315..650afc183f6 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Frame-Settings.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Frame-Settings.md @@ -406,6 +406,14 @@ These settings control lighting features for your rendering components. Here you The custom number of samples to use for Subsurface Scattering calculations when to set the Quality Mode to Override Quality Settings. + + + Custom Downsample Level + + The number of levels to down sample the source irradiance texture, before Subsurface Scattering will sample it. This is only for samples outside of the group shared cache. + + + diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/HDRP-Asset.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/HDRP-Asset.md index 6584ac22fbd..824176cb176 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/HDRP-Asset.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/HDRP-Asset.md @@ -101,7 +101,8 @@ These settings control the draw distance and resolution of the decals atlas that | **Screen Space Ambient Occlusion** | Enable the checkbox to make HDRP support screen space ambient occlusion (SSAO). SSAO is a technique for approximating ambient occlusion efficiently in real time. | | **Screen Space Global Illumination** | Enable the checkbox to make HDRP support screen space global illumination (SSGI). SSGI is a technique for approximating global illumination efficiently in real time. | | **Volumetrics** | Enable the checkbox to make HDRP support volumetrics. This allows you to use **Volumetric Fog** for the **Fog Type** in the [Visual Environment](Override-Visual-Environment.md). | -| **Light Layers** | Enable the checkbox to make HDRP support Light Layers. You can assign a Layer to a Light which then only lights up Mesh Renderers or Terrain with a matching rendering Layer. | +| **Light Layers** | Enable the checkbox to make HDRP support Light Layers. You can assign a Layer to a Light which then only lights up Mesh Renderers or Terrains with a matching rendering Layer. | +| **Rendering Layer Mask Buffer** | Enable the checkbox to make HDRP write the Rendering Layer Mask of GameObjects in a fullscreen buffer target. This comes with a performance and memory cost.
The [HD Sample Buffer node](HD-Sample-Buffer-Node.md) in ShaderGraph can sample this target. | ### Cookies diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/HDRP-Features.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/HDRP-Features.md index 745df1f9c3f..b9e4190b5f1 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/HDRP-Features.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/HDRP-Features.md @@ -284,13 +284,13 @@ In HDRP, you set up fog, inside a [Volume](Volumes.md), so you can change fog se In addition to fog, HDRP also supports local volumetric fog. You can use this to control the density of fog in an area. For more detailed control, you can use a 3D Mask texture to control the color and the density inside the volume itself. For more information see the [Local Volumetric Fog section](Local-Volumetric-Fog.md) -### Light Layers +### Rendering Layers ![](Images/HDRPFeatures-LightLayers.png) -Light Layers are LayerMasks that you specify for Lights and Meshes. Lights only illuminate Meshes that are on Light Layers that you enable on the Light. You can also use Light Layers in the shadow map settings to decouple shadows from lighting. For more information on Light Layers, see the [Light Layers documentation](Light-Layers.md). +Rendering Layers are LayerMasks that you specify for Lights, Decals and Meshes. Lights only illuminate Meshes that are on matching Rendering Layers. You can also use Rendering Layers in the shadow map settings to decouple shadows from lighting. For more information on Rendering Layers, see the [Rendering Layers documentation](Rendering-Layers.md). -You can use Light layers in the shadow map dropdown to control which GameObject receives a shadow from which light. By default, both Light Layers and Shadow Map Light Layers are synchronized so the result is coherent. This means that when a GameObject receives light it also casts shadows. For more information on Shadow Map Light Layers, see the [Shadow Light Layer section](Light-Layers.md#ShadowLightLayers). +You can use Rendering layers in the shadow map dropdown to control which GameObject receives a shadow from which light. By default, both Light Rendering Layers and Shadow Map Rendering Layers are synchronized so the result is coherent. This means that when a GameObject receives light it also casts shadows. For more information on Shadow Map Rendering Layers, see the [Shadow Rendering Layer section](Rendering-Layers.md#ShadowLightLayers). ### Screen space ambient occlusion @@ -460,9 +460,9 @@ To help you to debug lighting in your Scene, HDRP includes various lighting debu - Reflection - Refraction -#### Light layer debug mode +#### Rendering Layer Mask debug mode -HDRP includes a [light layer](Light-Layers.md) debug mode that displays the light layers assigned to each GameObject or highlights GameObjects that match the light layers of a specific Light. +HDRP includes a [Rendering Layer](Rendering-Layers.md) debug mode that displays the Rendering Layer Mask of each GameObject or highlights GameObjects that match the Rendering Layer Mask of a specific Light. For more information, see the Lighting panel section in the [Rendering Debugger](Render-Pipeline-Debug-Window.md). diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Light-Component.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Light-Component.md index 7b483dd3819..9107aacd9b5 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Light-Component.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Light-Component.md @@ -50,13 +50,13 @@ To make the Light work with the **Animation window**, when you click on the **Ad ### General -**General** properties control the type of Light, how HDRP processes this Light, and whether this Light affects everything in the Scene or just GameObjects on a specific Light Layer. +**General** properties control the type of Light, how HDRP processes this Light, and whether this Light affects everything in the Scene or just GameObjects on a specific Rendering Layer. | **Property** | **Description** | | --------------- | ------------------------------------------------------------ | | **Type** | Defines the Light’s type. Lights of different Types behave differently, so when you change the **Type**, the properties change in the Inspector. Possible types are:
• Directional
• Point
• Spot
• Area | | **Mode** | Specify the [Light Mode](https://docs.unity3d.com/Manual/LightModes.html) that HDRP uses to determine how to bake a Light, if at all. Possible modes are:
• [Realtime](https://docs.unity3d.com/Manual/LightMode-Realtime.html): Unity performs the lighting calculations for Realtime Lights at runtime, once per frame.
• [Mixed](https://docs.unity3d.com/Manual/LightMode-Mixed.html): Mixed Lights combine elements of both realtime and baked lighting.
• [Baked](https://docs.unity3d.com/Manual/LightMode-Baked.html): Unity performs lighting calculations for Baked Lights in the Unity Editor, and saves the results to disk as lighting data. Note that soft falloff/range attenuation isn't supported for Baked Area Lights. | -| **Light Layer** | A mask that allows you to choose which Light Layers this Light affects. The affected Light only lights up Mesh Renderers or Terrain with a matching **Rendering Layer Mask**. This property only appears if:
• Your Project supports light layers. For information on how to set up light layers, see [light layers](Light-Layers.md).
• You enable [additional properties](More-Options.md) for this section. | +| **Rendering Layer Mask** | Defines which Rendering Layers this Light affects. The affected Light only lights up Mesh Renderers or Terrain with a matching **Rendering Layer Mask**. To use this property:
• Set up [light layers](Rendering-Layers.md) in your project.
• Enable [additional properties](More-Options.md) for this section. | #### Light Types guide @@ -221,8 +221,8 @@ This section is only available in Realtime or Mixed light **Mode**. | **Tint** | Specifies whether HDRP should tint the shadows this Light casts. This option affects dynamic shadows, [Contact Shadows](Override-Contact-Shadows.md), and [ShadowMask](Lighting-Mode-Shadowmask.md). It doesn't affect baked shadows. You can use this behavior to change the color and transparency of shadows.
This property only appears when you enable [additional properties](More-Options.md) for this section. | | **Penumbra Tint** | Specifies whether the tint should only affect the shadow's penumbra. If you enable this property, HDRP only applies the color tint to the shadow's penumbra. If you disable this property, HDRP applies the color tint to the entire shadow including the penumbra. To change the color HDRP tints the shadow to, see the above **Tint** property.
This property only appears when you enable [additional properties](More-Options.md) for this section. | | **Fade Distance** | The distance, in meters, between the Camera and the Light at which shadows fade out. This property is available for **Spot** and **Point** Lights.
This property only appears when you enable [additional properties](More-Options.md) for this section. | -| **Custom Shadow Layer** | Enable the checkbox to use a different [Light Layer](Light-Layers.md) for shadows than the one used for lighting. If you enable this feature, then HDRP uses the **Layer** drop-down in this section for shadowing. If you disable it, then HDRP uses the **Light Layer** drop-down in the **General** section for shadowing.
This property only appears when you enable [additional properties](More-Options.md) for this section. To access this property, enable **Light Layers** in your [HDRP Asset](HDRP-Asset.md). | -| **Layer** | Use the drop-down to set the [Light Layer](Light-Layers.md) HDRP uses for shadowing. This Light therefore only casts shadows for GameObjects that use a matching Light Layer. For more information about using Light Layers for shadowing, see [Shadow Light Layers](Light-Layers.md#ShadowLightLayers).
This property only appears when you enable [additional properties](More-Options.md) for this section. To access this property, enable the **Custom Shadow Layer** checkbox. | +| **Custom Shadow Layers** | Enable the checkbox to use a different [Rendering Layer Mask](Rendering-Layers.md) for shadows than the one used for lighting. If you enable this feature, then HDRP uses the **Shadow Layers** drop-down in this section for shadowing. If you disable it, then HDRP uses the **Rendering Layer Mask** drop-down in the **General** section for shadowing.
This property only appears when you enable [additional properties](More-Options.md) for this section. To access this property, enable **Light Layers** in your [HDRP Asset](HDRP-Asset.md). | +| **Shadow Layers** | Use the drop-down to set the [Rendering Layer Mask](Rendering-Layers.md) HDRP uses for shadowing. This Light therefore only casts shadows for GameObjects that use a matching Rendering Layer. For more information about using Rendering Layers for shadowing, see [Shadow Light Layers](Rendering-Layers.md#ShadowLightLayers).
This property only appears when you enable [additional properties](More-Options.md) for this section. To access this property, enable the **Custom Shadow Layers** checkbox. | ##### Contact Shadows diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Light-Layers.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Light-Layers.md deleted file mode 100644 index 386773c317e..00000000000 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Light-Layers.md +++ /dev/null @@ -1,64 +0,0 @@ -# Light Layers - -The High Definition Render Pipeline (HDRP) allows you to use Light Layers, which are [LayerMasks](https://docs.unity3d.com/ScriptReference/LayerMask.html), to make Lights in your Scene only light up specific Meshes. You set Light Layers for Lights and Meshes to make Lights only affect Meshes that are on corresponding Light Layers. - -![](Images/HDRPFeatures-LightLayers.png) - -## Enabling Light Layers - -To use Light Layers, you must enable them in your Project’s [HDRP Asset](HDRP-Asset.md). You can then enable Light Layers in the [Frame Settings](Frame-Settings.md) to set your Cameras to process Light Layers. - -1. Select the HDRP Asset in the Project window and, in the Inspector, go to **Lighting > Light Layers** and enable the **Enable** checkbox. -2. To enable Light Layers for all Cameras, open the [HDRP Global Settings](Default-Settings-Window.md), go to the **Frame Settings (Default Values) > Camera** section and, in the **Rendering** section, enable the **Light Layers** checkbox. -3. Go to **Edit** > **Project Settings** > **Quality** > **HDRP** > **Lighting**, and enable **Light Layers**. - -To override the Frame Settings for Cameras and set Light Layers on an individual basis: - -1. Click on a Camera in the Scene view or Hierarchy window to view its properties in the Inspector. -2. Go to the **General** section and enable the **Custom Frame Settings** checkbox. This exposes the **Frame Settings Overrides,** which you can use to customize this Camera only. -3. In the **Lighting** section, enable the **Light Layers** checkbox to make this Camera use Light Layers. - -## Using Light Layers - -After you enable Light Layers, you can then use them to decouple Meshes from certain Lights in your Scene. To do this: - -1. Click on a Light in the Hierarchy or the Scene view to view it in the Inspector. -2. Enable [additional properties](More-Options.md) in the **General** section to expose the **Light Layer** property. -3. Use the **Light Layer** property drop-down to select which Light Layers this Light affects. -4. Click on a Mesh Renderer or Terrain in the Hierarchy or the Scene view to view it in the Inspector. -5. Use the **Rendering Layer Mask** drop-down (See [MeshRenderer](https://docs.unity3d.com/Manual/class-MeshRenderer.html) for GameObjects or [OtherSettings](https://docs.unity3d.com/Manual/terrain-OtherSettings.html) for Terrain) to select which Light Layers affect this Mesh Renderer or Terrain. When you enable Light Layers, a Light only affects a Mesh Renderer or Terrain if they both use a matching Light Layer. - - - -## Shadow Light Layers - -When using Light Layers, Meshes only cast shadows for [Lights](Light-Component.md) on the same Light Layer as them. This is because HDRP synchronizes Light Layers and shadow Light Layers by default, so every Mesh that receives light, also casts shadows for it. To make a Mesh cast shadows without the Light also affecting its lighting, you must decouple the shadow Light Layers from that Light's Light Layers. - -To do this: - -1. Click on a Light in the Hierarchy or the Scene view to view it in the Inspector. -2. Go to the **Shadows** section and disable the **Link Light Layers** checkbox. - -You can now use the **Light Layers** drop-down in the **Shadows** section to set the Light Layers that the Light uses for shadowing. You can also still use the **Light Layers** drop-down in the **General** section to set the Light Layers that the Light uses for lighting. - -## Renaming Light Layers - -By default, in the UI for Lights, Mesh Renderers or Terrain, Light Layers are named **Light Layer 1-7**. To more easily differentiate between them, you can give each Light Layer a specific name. To do this, open the [HDRP Global Settings](Default-Settings-Window.md), and go to **Light Layer Names**. Here you can set the name of each Light Layer individually. - -## Example scenario for Light Layers - -Using [cookies](https://docs.unity3d.com/Manual/Cookies.html) for light fixtures can sometimes have a negative visual effect on a bulb, such as self-shadowing or transmission contribution. You can use Light Layers to make a bulb Mesh not receive any light from the Light’s cookie, and instead receive light from a separate small Point Light. - -The Light cookie incorrectly affects the transmission of this bulb’s geometry. - -![](Images/LightLayers1.png) - -Assigning the bulb’s Mesh Renderer to a specific Light Layer means that the Light cookie no longer affects the bulb’s Mesh Renderer. - -![](Images/LightLayers2.png) - -To restore the transmission effect, create a Point Light and assign it to the same Light Layer as the bulb’s Mesh Renderer . Now this Point Light only affects the bulb’s Mesh Renderer and does not contribute to the rest of the Scene Lighting. - -![](Images/LightLayers3.png) - -For more information on this process, see Pierre Donzallaz’s [expert guide](https://pydonzallaz.files.wordpress.com/2019/02/create-high-quality-light-fixtures-in-unity.pdf) on creating high quality light fixtures in Unity. diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Menu-Items.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Menu-Items.md index 5fe5d15c811..080a93e859c 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Menu-Items.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Menu-Items.md @@ -6,14 +6,14 @@ The High Definition Render Pipeline (HDRP) adds menu items to the Unity menu bar This section includes all the menu items under the **Edit > Rendering** menu fold-out. -### Decal Layers +### Rendering Layers -This section includes all the menu items under the **Edit > Rendering > Decal Layers** menu fold-out. +This section includes all the menu items under the **Edit > Rendering > Rendering Layers** menu fold-out. | **Item** | **Description** | | ------------------------------------------------------------ | ------------------------------------------------------------ | -| **Add HDRP Decal Layer Default to Loaded Mesh Renderers and Terrains** | Adds the **Decal Layer Default** item to every Mesh Renderer and Terrain in the currently open scene. This is useful when upgrading your HDRP project from Unity 2020.1 to 2020.2, if you want to use [Decal Layers](Decal.md#decal-layers). | -| **Add HDRP Decal Layer Default to Selected Mesh Renderers and Terrains** | Adds the **Decal Layer Default** item to every selected Mesh Renderer and Terrain in the currently open scene. This is useful when upgrading your HDRP project from Unity 2020.1 to 2020.2, if you want to use [Decal Layers](Decal.md#decal-layers). | +| **Add HDRP Default Layer Mask to Loaded Mesh Renderers and Terrains** | Adds the **Default Rendering Layer Mask** item to every Mesh Renderer and Terrain in the currently open scene. This is useful when upgrading your HDRP project from Unity 2020.1 to 2020.2, if you want to use [Decal Layers](Decal.md#decal-layers). | +| **Add HDRP Default Layer Mask to Selected Mesh Renderers and Terrains** | Adds the **Default Rendering Layer Mask** item to every selected Mesh Renderer and Terrain in the currently open scene. This is useful when upgrading your HDRP project from Unity 2020.1 to 2020.2, if you want to use [Decal Layers](Decal.md#decal-layers). | diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Override-Indirect-Lighting-Controller.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Override-Indirect-Lighting-Controller.md index 6259c719a8b..a09096bff30 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Override-Indirect-Lighting-Controller.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Override-Indirect-Lighting-Controller.md @@ -22,9 +22,9 @@ The **Indirect Lighting Controller** uses the [Volume](Volumes.md) framework, so | Property | Description | | ------------------------------- | ------------------------------------------------------------ | | **Indirect Diffuse Lighting Multiplier** | A multiplier for lightmaps, Light Probes, Light Probe Volumes, Screen-Space Global Illumination, and [Ray-Traced Global Illumination](Ray-Traced-Global-Illumination.md). HDRP multiplies the light data from these by this value. | -| **Indirect Diffuse Lighting Layers** | Specifies the [Light Layers](Light-Layers.md) for indirect diffuse lighting. If you enable Light Layers, you can use them to decouple Meshes in your Scene from the above multiplier. | +| **Indirect Diffuse Rendering Layer Mask** | Specifies the [Rendering Layer Mask](Rendering-Layers.md) for indirect diffuse lighting multiplier. If you enable Light Layers, you can use them to decouple Meshes in your Scene from the above multiplier. | | **Reflection Lighting Multiplier** | A multiplier for baked, realtime, custom [Reflection Probes](Reflection-Probe.md) and [Planar Probes](Planar-Reflection-Probe.md), [Screen-Space Reflection](Override-Screen-Space-Reflection.md), [Ray-Traced Reflection](Ray-Traced-Reflections.md), and Sky Reflection. HDRP multiplies the light data from these by this value. | -| **Reflection Lighting Layers** | Specifies the [Light Layers](Light-Layers.md) for reflection lighting. If you enable Light Layers, you can use them to decouple Meshes in your Scene from the above multiplier. | +| **Reflection Rendering Layer Mask** | Specifies the [Rendering Layer Mask](Rendering-Layers.md) for reflection lighting. If you enable Light Layers, you can use them to decouple Meshes in your Scene from the above multiplier. | | **Reflection/Planar Probe Intensity Multiplier** | A multiplier for baked, realtime, and custom [Reflection Probes](Reflection-Probe.md) and [Planar Probes](Planar-Reflection-Probe.md). HDRP multiplies the Reflection Probe data by this value. | ## Details diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Reflection-Probe.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Reflection-Probe.md index bb5216b43f7..a7b08c37e39 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Reflection-Probe.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Reflection-Probe.md @@ -74,7 +74,7 @@ The following properties control extra behavior options for fine-tuning the beha | **Property** | **Description** | | --------------- | ------------------------------------------------------------ | -| **Light Layer** | A mask that allows you to choose which Light Layers this Reflection Probe affects. This Reflection Probe only affects Mesh Renderers or Terrain with a matching **Rendering Layer Mask**.
Navigate to your Project’s **HDRP Asset > Render Pipeline Supported Features** and enable **Light Layers** to use this property. | +| **Rendering Layer Mask** | A mask that allows you to choose which Rendering Layers this Reflection Probe affects. This Reflection Probe only affects Mesh Renderers or Terrain with a matching **Rendering Layer Mask**.
Navigate to your Project’s **HDRP Asset > Render Pipeline Supported Features** and enable **Light Layers** to use this property. | | **Multiplier** | A multiplier for the RenderTexture the Reflection Probe captures. The Reflection Probe applies this multiplier when Reflective Materials query the RenderTexture. | | **Weight** | The overall weight of this Reflection Probe’s contribution to the reflective effect of Materials. When Reflection Probe’s blend together, the weight of each Probe determines their contribution to a reflective Material in the blend area. | | **Fade Distance** | The distance, in meters, from the camera at which reflections begin to smoothly fade out before they disappear completely. | diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Render-Pipeline-Debug-Window.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Render-Pipeline-Debug-Window.md index 75029a39746..1aeddc6177d 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Render-Pipeline-Debug-Window.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Render-Pipeline-Debug-Window.md @@ -161,6 +161,26 @@ The **Material** panel has tools that you can use to visualize different Materia Material Use the drop-down to select a Material property to visualize on every GameObject on screen using a specific Shader. The properties available depend on the HDRP Material type you select in the drop-down. + + Rendering Layer Mask + These parameters only appear when you set the Material Debug Option to Rendering Layers. + + + Filter with Light Layers from Selected Light + Enable the checkbox to visualize GameObjects that the selected light affects. + + + Use Light's Shadow Layer Mask + Enable the checkbox to visualize GameObjects that cast shadows for the selected light. + + + Filter Layers + Use the drop-down to filter layers that you want to display. GameObjects that have a matching layer appear in a specific color. Use **Layers Color** to define this color. + + + Layers Color + Use the color pickers to select the display color of each rendering layer. + Engine Use the drop-down to select a Material property to visualize on every GameObject on a screen that uses a specific Shader. The properties available are the same as Material but are in the form that the lighting engine uses them (for example, Smoothness is Perceptual Roughness). @@ -338,26 +358,6 @@ The **Lighting** panel has tools that you can use to visualize various component Hierarchy Debug Mode Use the drop-down to select a light type to display the direct lighting for or a Reflection Probe type to display the indirect lighting for. - -Light Layers Visualization -Enable the checkbox to visualize light layers of objects in your Scene. - - -Use Selected Light -Enable the checkbox to visualize objects affected by the selected light. - - -Switch to Light's Shadow Layers -Enable the checkbox to visualize objects casting shadows for the selected light. - - -Filter Layers -Use the drop-down to filter light layers that you want to visialize. Objects having a matching layer will be displayed in a specific color. - - -Layers Color -Use the color pickers to select the display color of each light layer. - diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Rendering-Layers.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Rendering-Layers.md new file mode 100644 index 00000000000..76b00604237 --- /dev/null +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Rendering-Layers.md @@ -0,0 +1,78 @@ +# Rendering Layers + +The High Definition Render Pipeline (HDRP) allows you to use Rendering Layers, which are [LayerMasks](https://docs.unity3d.com/ScriptReference/LayerMask.html) to make Lights or effects only affect specific Renderers. + +A Renderer can support up to 32 rendering layers, but all HDRP effects using Rendering Layers only support the first 16 layers. +On the image below, you can see usage of Rendering Layers with Lights to only affect some of the meshes. + +![](Images/HDRPFeatures-LightLayers.png) + +Rendering Layers are also supported on decal projectors, and can be sampled from the ShaderGraph to implement custom effects. + +## Configuring Rendering Layers + +To create and name Rendering Layers: + +- Open the [HDRP Global Settings](Default-Settings-Window.md). +- Go to the **Rendering Layers** section. +- Open the foldout **Rendering Layer Names**. + +To use Rendering Layers with Lights: +- Open the [HDRP Global Settings](Default-Settings-Window.md). +- In the **Frame Settings (Default Values)** section, open the **Lighting** dropdown. +- Enable **Light Layers**. +- Open the [HDRP Asset](HDRP-Asset.html). +- Go to the **Lighting** section. +- Enable **Light Layers**. + +To enable and use Rendering Layers with decal projectors, refer to the [Decal Layers Documentation](Decal.md#enabling-decal-layers). + +To access the Rendering Layer Mask buffer from the ShaderGraph, go to the **Lighting** section of your Project’s [HDRP Asset](HDRP-Asset.md) and enable the **Rendering Layer Mask Buffer** checkbox. +You can then use the **HD Sample Buffer** node and set **RenderingLayerMask** as the source buffer to sample the layer mask buffer per pixel. + +## Using Light's Rendering Layer Mask + +After you enable Light Layers, you can then use them to decouple Meshes from certain Lights in your Scene. To do this: + +1. Click on a Light in the Hierarchy or the Scene view to view it in the Inspector. +2. Enable [additional properties](More-Options.md) in the **General** section to expose the **Rendering Layer Mask** property. +3. Use the **Rendering Layer Mask** property drop-down to select which Light Layers this Light affects. +4. Click on a Mesh Renderer or Terrain in the Hierarchy or the Scene view to view it in the Inspector. +5. Use the **Rendering Layer Mask** drop-down (See [MeshRenderer](https://docs.unity3d.com/Manual/class-MeshRenderer.html) for GameObjects or [OtherSettings](https://docs.unity3d.com/Manual/terrain-OtherSettings.html) for Terrain) to select which Light Layers affect this Mesh Renderer or Terrain. When you enable Light Layers, a Light only affects a Mesh Renderer or Terrain if they both use a matching Light Layer. + + + +## Using Light's Shadow Layers + +When using Light Layers, Meshes only cast shadows for [Lights](Light-Component.md) on the same Rendering Layer as them. This is because HDRP synchronizes Light Rendering Layers and shadow Rendering Layers by default, so every Mesh that receives light, also casts shadows for it. To make a Mesh cast shadows without the Light also affecting its lighting, you must decouple the shadow Rendering Layers from that Light's Rendering Layers. + +To do this: + +1. Click on a Light in the Hierarchy or the Scene view to view it in the Inspector. +2. Go to the **Shadows** section and enable the **Custom Shadow Layers** checkbox. + +You can now use the **Shadow Layers** drop-down in the **Shadows** section to set the Rendering Layers that the Light uses for shadowing. You can also still use the **Rendering Layer Mask** drop-down in the **General** section to set the Rendering Layers that the Light uses for lighting. + + + +## Renaming Rendering Layers + +By default, in the UI for Lights, Decals, Mesh Renderers or Terrain, Rendering Layers are named **Layer 0-15**. To more easily differentiate between them, you can give each Layer a specific name. To do this, open the [HDRP Global Settings](Default-Settings-Window.md), and go to **Rendering Layer Names**. Here you can set the name of each Light Layer individually. + +## Example scenario for Light Layers + +Using [cookies](https://docs.unity3d.com/Manual/Cookies.html) for light fixtures can sometimes have a negative visual effect on a bulb, such as self-shadowing or transmission contribution. You can use Light Layers to make a bulb Mesh not receive any light from the Light’s cookie, and instead receive light from a separate small Point Light. + +The Light cookie incorrectly affects the transmission of this bulb’s geometry. + +![](Images/LightLayers1.png) + +Assigning the bulb’s Mesh Renderer to a specific Rendering Layer means that the Light cookie no longer affects the bulb’s Mesh Renderer. + +![](Images/LightLayers2.png) + +To restore the transmission effect, create a Point Light and assign it to the same Rendering Layer as the bulb’s Mesh Renderer. Now this Point Light only affects the bulb’s Mesh Renderer and does not contribute to the rest of the Scene Lighting. + +![](Images/LightLayers3.png) + +For more information on this process, see Pierre Donzallaz’s [expert guide](https://pydonzallaz.files.wordpress.com/2019/02/create-high-quality-light-fixtures-in-unity.pdf) on creating high quality light fixtures in Unity. diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/TableOfContents.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/TableOfContents.md index 4b4c0d2d132..fdfe60d5506 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/TableOfContents.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/TableOfContents.md @@ -143,7 +143,7 @@ * [Clouds in HDRP](clouds-in-hdrp.md) * [Atmospheric Scattering](Atmospheric-Scattering.md) * [Local Volumetric Fog](Local-Volumetric-Fog.md) - * [Light Layers](Light-Layers.md) + * [Rendering Layers](Rendering-Layers.md) * [Shadows](Shadows-in-HDRP.md) * [Shadowmasks](Lighting-Mode-Shadowmask.md) * [Volumetric Lighting](Volumetric-Lighting.md) diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/HDLightExplorerExtension.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/HDLightExplorerExtension.cs index f662c74fd4a..3efb8dd7b5e 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/HDLightExplorerExtension.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/HDLightExplorerExtension.cs @@ -118,7 +118,6 @@ public override LightingExplorerTab[] GetContentTabs() new LightingExplorerTab("Reflection Probes", GetHDReflectionProbes, GetHDReflectionProbeColumns, true), new LightingExplorerTab("Planar Reflection Probes", GetPlanarReflections, GetPlanarReflectionColumns, true), new LightingExplorerTab("Light Probes", GetLightProbes, GetLightProbeColumns, true), - new LightingExplorerTab("Probe Volumes", GetProbeVolumes, GetProbeVolumeColumns, true), new LightingExplorerTab("Emissive Materials", GetEmissives, GetEmissivesColumns, false) }; } @@ -187,11 +186,6 @@ protected virtual UnityEngine.Object[] GetVolumes() return volumes; } - protected internal virtual UnityEngine.Object[] GetProbeVolumes() - { - return Resources.FindObjectsOfTypeAll(); - } - protected virtual LightingExplorerTableColumn[] GetHDLightColumns() { return new[] @@ -1144,117 +1138,6 @@ protected virtual LightingExplorerTableColumn[] GetPlanarReflectionColumns() }; } - protected internal virtual LightingExplorerTableColumn[] GetProbeVolumeColumns() - { - return new[] - { - new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Name, HDStyles.Name, null, 200), // 0: Name - new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Checkbox, HDStyles.DrawProbes, "parameters", 35, (r, prop, dep) => // 1: Draw Probes - { - SerializedProperty drawProbes = prop.FindPropertyRelative("drawProbes"); - EditorGUI.PropertyField(r, drawProbes, GUIContent.none); - }, (lhs, rhs) => - { - return lhs.FindPropertyRelative("drawProbes").boolValue.CompareTo(rhs.FindPropertyRelative("drawProbes").boolValue); - }, (target, source) => - { - target.FindPropertyRelative("drawProbes").boolValue = source.FindPropertyRelative("drawProbes").boolValue; - }), - new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Color, HDStyles.DebugColor, "parameters", 75, (r, prop, dep) => // 2: Debug Color - { - SerializedProperty debugColor = prop.FindPropertyRelative("debugColor"); - EditorGUI.PropertyField(r, debugColor, GUIContent.none); - }, (lhs, rhs) => - { - float lh, ls, lv, rh, rs, rv; - Color.RGBToHSV(lhs.FindPropertyRelative("debugColor").colorValue, out lh, out ls, out lv); - Color.RGBToHSV(rhs.FindPropertyRelative("debugColor").colorValue, out rh, out rs, out rv); - return lh.CompareTo(rh); - }, (target, source) => - { - target.FindPropertyRelative("debugColor").colorValue = source.FindPropertyRelative("debugColor").colorValue; - }), - new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Int, HDStyles.ResolutionX, "parameters", 75, (r, prop, dep) => // 3: Resolution X - { - SerializedProperty resolutionX = prop.FindPropertyRelative("resolutionX"); - - EditorGUI.BeginChangeCheck(); - EditorGUI.PropertyField(r, resolutionX, GUIContent.none); - - if (EditorGUI.EndChangeCheck()) - { - resolutionX.intValue = Mathf.Max(1, resolutionX.intValue); - } - }, (lhs, rhs) => - { - return lhs.FindPropertyRelative("resolutionX").intValue.CompareTo(rhs.FindPropertyRelative("resolutionX").intValue); - }, (target, source) => - { - target.FindPropertyRelative("resolutionX").intValue = source.FindPropertyRelative("resolutionX").intValue; - }), - new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Int, HDStyles.ResolutionY, "parameters", 75, (r, prop, dep) => // 4: Resolution Y - { - SerializedProperty resolutionY = prop.FindPropertyRelative("resolutionY"); - - EditorGUI.BeginChangeCheck(); - EditorGUI.PropertyField(r, resolutionY, GUIContent.none); - - if (EditorGUI.EndChangeCheck()) - { - SerializedProperty resolutionX = prop.FindPropertyRelative("resolutionX"); - resolutionY.intValue = Mathf.Max(1, resolutionY.intValue); - } - }, (lhs, rhs) => - { - return lhs.FindPropertyRelative("resolutionY").intValue.CompareTo(rhs.FindPropertyRelative("resolutionY").intValue); - }, (target, source) => - { - target.FindPropertyRelative("resolutionY").intValue = source.FindPropertyRelative("resolutionY").intValue; - }), - new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Int, HDStyles.ResolutionZ, "parameters", 75, (r, prop, dep) => // 5: Resolution Z - { - SerializedProperty resolutionZ = prop.FindPropertyRelative("resolutionZ"); - - EditorGUI.BeginChangeCheck(); - EditorGUI.PropertyField(r, resolutionZ, GUIContent.none); - - if (EditorGUI.EndChangeCheck()) - { - SerializedProperty resolutionX = prop.FindPropertyRelative("resolutionX"); - resolutionZ.intValue = Mathf.Max(1, resolutionZ.intValue); - } - }, (lhs, rhs) => - { - return lhs.FindPropertyRelative("resolutionZ").intValue.CompareTo(rhs.FindPropertyRelative("resolutionZ").intValue); - }, (target, source) => - { - target.FindPropertyRelative("resolutionZ").intValue = source.FindPropertyRelative("resolutionZ").intValue; - }), - new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Float, HDStyles.FadeStart, "parameters", 65, (r, prop, dep) => // 6: Distance Fade Start - { - SerializedProperty distanceFadeStart = prop.FindPropertyRelative("distanceFadeStart"); - EditorGUI.PropertyField(r, distanceFadeStart, GUIContent.none); - }, (lhs, rhs) => - { - return lhs.FindPropertyRelative("distanceFadeStart").floatValue.CompareTo(rhs.FindPropertyRelative("distanceFadeStart").floatValue); - }, (target, source) => - { - target.FindPropertyRelative("distanceFadeStart").floatValue = source.FindPropertyRelative("distanceFadeStart").floatValue; - }), - new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Float, HDStyles.FadeEnd, "parameters", 65, (r, prop, dep) => // 7: Distance Fade End - { - SerializedProperty distanceFadeEnd = prop.FindPropertyRelative("distanceFadeEnd"); - EditorGUI.PropertyField(r, distanceFadeEnd, GUIContent.none); - }, (lhs, rhs) => - { - return lhs.FindPropertyRelative("distanceFadeEnd").floatValue.CompareTo(rhs.FindPropertyRelative("distanceFadeEnd").floatValue); - }, (target, source) => - { - target.FindPropertyRelative("distanceFadeEnd").floatValue = source.FindPropertyRelative("distanceFadeEnd").floatValue; - }) - }; - } - public override void OnDisable() { lightDataPairing.Clear(); diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/ProbeVolumeMenuItems.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/ProbeVolumeMenuItems.cs index 6503810db86..29ecb729597 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/ProbeVolumeMenuItems.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/ProbeVolumeMenuItems.cs @@ -13,11 +13,11 @@ static void CreateProbeVolumeGameObject(MenuCommand menuCommand) probeVolume.AddComponent(); } - [MenuItem("GameObject/Light/Probe Volume (Experimental)/Probe Touchup Volume", priority = CoreUtils.Sections.section8)] + [MenuItem("GameObject/Light/Probe Volume (Experimental)/Probe Adjustment Volume", priority = CoreUtils.Sections.section8)] static void CreateProbeTouchupVolumeGameObject(MenuCommand menuCommand) { var parent = menuCommand.context as GameObject; - var probeVolume = CoreEditorUtils.CreateGameObject("Probe Touchup Volume", parent); + var probeVolume = CoreEditorUtils.CreateGameObject("Probe Adjustment Volume", parent); probeVolume.AddComponent(); } } diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineMenuItems.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineMenuItems.cs index f08bd293c9c..13d8c35cfa0 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineMenuItems.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineMenuItems.cs @@ -100,7 +100,7 @@ internal static void UpgradeMaterials() MaterialReimporter.ReimportAllMaterials(); } - [MenuItem("Edit/Rendering/Decal Layers/Add HDRP Default Layer Mask to Loaded Mesh Renderers and Terrains", priority = CoreUtils.Priorities.editMenuPriority + 2)] + [MenuItem("Edit/Rendering/Rendering Layers/Add HDRP Default Layer Mask to Loaded Mesh Renderers and Terrains", priority = CoreUtils.Priorities.editMenuPriority + 2)] internal static void UpgradeDefaultRenderingLayerMask() { var meshRenderers = Resources.FindObjectsOfTypeAll(); @@ -122,7 +122,7 @@ internal static void UpgradeDefaultRenderingLayerMask() } } - [MenuItem("Edit/Rendering/Decal Layers/Add HDRP Default Layer Mask to Selected Mesh Renderers and Terrains", priority = CoreUtils.Priorities.editMenuPriority + 1)] + [MenuItem("Edit/Rendering/Rendering Layers/Add HDRP Default Layer Mask to Selected Mesh Renderers and Terrains", priority = CoreUtils.Priorities.editMenuPriority + 1)] internal static void UpgradeDefaultRenderingLayerMaskForSelection() { var selection = UnityEditor.Selection.objects; diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.Skin.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.Skin.cs index 9f9c91d9f0c..6f9c0b9e91c 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.Skin.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.Skin.cs @@ -134,6 +134,7 @@ public class Styles public static readonly GUIContent renderingLayerMaskBuffer = EditorGUIUtility.TrTextContent("Rendering Layer Mask Buffer", "When enabled, HDRP writes Rendering Layer Mask of Renderers to a buffer target that can be sampled in a shader in order to create fullscreen effects.\nThis comes with a performance and a memory cost."); public static readonly GUIContent supportedSSSContent = EditorGUIUtility.TrTextContent("Subsurface Scattering", "When enabled, HDRP allocates memory for processing subsurface scattering (SSS). This allows you to use SSS in your Unity Project."); public static readonly GUIContent sssSampleBudget = EditorGUIUtility.TrTextContent("Sample Budget", "Maximum number of samples the Subsurface Scattering algorithm is allowed to take."); + public static readonly GUIContent sssDownsampleSteps = EditorGUIUtility.TrTextContent("Downsample Level", "The number of downsample steps done to the source irradance textrure before it is used by the Subsurface Scattering algorithm. Higher value will improve performance, but might lower quality."); public static readonly GUIContent supportVolumetricFogContent = EditorGUIUtility.TrTextContent("Volumetric Fog", "When enabled, HDRP allocates Shader variants and memory for volumetric effects. This allows you to use volumetric lighting and fog in your Unity Project."); public static readonly GUIContent supportVolumetricCloudsContent = EditorGUIUtility.TrTextContent("Volumetric Clouds", "When enabled, HDRP allocates memory for processing volumetric clouds. This allows you to use volumetric clouds in your Unity Project."); public static readonly GUIContent volumetricResolutionContent = EditorGUIUtility.TrTextContent("High Quality ", "When enabled, HDRP increases the resolution of volumetric lighting buffers. Warning: There is a high performance cost, do not enable on consoles."); @@ -168,6 +169,7 @@ public class Styles public static readonly GUIContent probeVolumeBlendingMemoryBudget = EditorGUIUtility.TrTextContent("Scenario Blending Memory Budget", "Determines the width and height of the textures used to blend between lighting scenarios. Note that the textures also has a fixed depth dimension."); public static readonly GUIContent supportProbeVolumeStreaming = EditorGUIUtility.TrTextContent("Enable Streaming", "Enable cell streaming for probe volume."); public static readonly GUIContent probeVolumeSHBands = EditorGUIUtility.TrTextContent("SH Bands", "Determines up to what SH bands the Probe Volume will use. Choosing L2 will lead to better quality, but also higher memory and runtime cost."); + public static readonly GUIContent maxLocalVolumetricFogSizeStyle = EditorGUIUtility.TrTextContent("Max Local Fog Size", "Specifies the maximum size for the individual 3D Local Volumetric Fog texture that HDRP uses for Local Volumetric Fog. This settings will affect your memory consumption."); public static readonly GUIContent maxLocalVolumetricFogOnScreenStyle = EditorGUIUtility.TrTextContent("Max Local Fog On Screen", "Sets the maximum number of Local Volumetric Fog can handle on screen at once. This settings will affect your memory consumption."); public const string cacheErrorFormat = "This configuration will lead to more than 2 GB reserved for this cache at runtime! ({0} requested) Only {1} element will be reserved instead."; diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.cs index 8a4090906e4..52daa4fe81f 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.cs @@ -944,6 +944,18 @@ static void Drawer_SectionMaterialUnsorted(SerializedHDRenderPipelineAsset seria { ++EditorGUI.indentLevel; serialized.renderPipelineSettings.sssSampleBudget.ValueGUI(Styles.sssSampleBudget); + + EditorGUI.BeginChangeCheck(); + serialized.renderPipelineSettings.sssDownsampleSteps.ValueGUI(Styles.sssDownsampleSteps); + if (EditorGUI.EndChangeCheck()) + { + for (var i = 0; i < serialized.renderPipelineSettings.sssDownsampleSteps.GetSchemaLevelCount(); ++i) + { + var prop = serialized.renderPipelineSettings.sssDownsampleSteps.values.GetArrayElementAtIndex(i); + prop.SetInline(Mathf.Clamp(prop.GetInline(), 0, (int)DefaultSssDownsampleSteps.Max)); + } + } + --EditorGUI.indentLevel; } diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/FrameSettingsUI.Drawers.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/FrameSettingsUI.Drawers.cs index 4842755fd58..b8e13d4cdfe 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/FrameSettingsUI.Drawers.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/FrameSettingsUI.Drawers.cs @@ -290,6 +290,15 @@ static internal void Drawer_SectionLightingSettings(SerializedFrameSettings seri ignoreDependencies: true, hasMixedValues: serialized.sssCustomSampleBudget.hasMultipleDifferentValues ); + area.AmmendInfo(FrameSettingsField.SssCustomDownsampleSteps, + overridedDefaultValue: 0, + customGetter: () => serialized.sssDownsampleSteps.intValue, + customSetter: v => serialized.sssDownsampleSteps.intValue = Math.Max(0, Math.Min((int)v, (int)DefaultSssDownsampleSteps.Max)), + overrideable: () => (serialized.IsEnabled(FrameSettingsField.SubsurfaceScattering) ?? false) + && (serialized.sssQualityMode.GetEnumValue() != SssQualityMode.FromQualitySettings), + ignoreDependencies: true, + hasMixedValues: serialized.sssDownsampleSteps.hasMultipleDifferentValues + ); area.Draw(withOverride); GUI.enabled = isGUIenabled; diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedFrameSettings.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedFrameSettings.cs index 2a228340587..679988d5569 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedFrameSettings.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedFrameSettings.cs @@ -14,6 +14,7 @@ class SerializedFrameSettings public SerializedProperty sssQualityMode; public SerializedProperty sssQualityLevel; public SerializedProperty sssCustomSampleBudget; + public SerializedProperty sssDownsampleSteps; public SerializedProperty lodBias; public SerializedProperty lodBiasMode; public SerializedProperty lodBiasQualityLevel; @@ -86,6 +87,7 @@ public SerializedFrameSettings(SerializedProperty rootData, SerializedProperty r sssQualityMode = rootData.FindPropertyRelative("sssQualityMode"); sssQualityLevel = rootData.FindPropertyRelative("sssQualityLevel"); sssCustomSampleBudget = rootData.FindPropertyRelative("sssCustomSampleBudget"); + sssDownsampleSteps = rootData.FindPropertyRelative("sssCustomDownsampleSteps"); lodBias = rootData.FindPropertyRelative("lodBias"); lodBiasMode = rootData.FindPropertyRelative("lodBiasMode"); lodBiasQualityLevel = rootData.FindPropertyRelative("lodBiasQualityLevel"); diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedRenderPipelineSettings.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedRenderPipelineSettings.cs index 13cfde439ef..4d1880401de 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedRenderPipelineSettings.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedRenderPipelineSettings.cs @@ -25,6 +25,7 @@ class SerializedRenderPipelineSettings public SerializedProperty supportSSGI; public SerializedProperty supportSubsurfaceScattering; public SerializedScalableSetting sssSampleBudget; + public SerializedScalableSetting sssDownsampleSteps; [FormerlySerializedAs("supportVolumetric")] public SerializedProperty supportVolumetrics; public SerializedProperty supportVolumetricClouds; @@ -91,6 +92,7 @@ public SerializedRenderPipelineSettings(SerializedProperty root) supportSSGI = root.Find((RenderPipelineSettings s) => s.supportSSGI); supportSubsurfaceScattering = root.Find((RenderPipelineSettings s) => s.supportSubsurfaceScattering); sssSampleBudget = new SerializedScalableSetting(root.Find((RenderPipelineSettings s) => s.sssSampleBudget)); + sssDownsampleSteps = new SerializedScalableSetting(root.Find((RenderPipelineSettings s) => s.sssDownsampleSteps)); supportVolumetrics = root.Find((RenderPipelineSettings s) => s.supportVolumetrics); supportVolumetricClouds = root.Find((RenderPipelineSettings s) => s.supportVolumetricClouds); diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/VFXGraph/VFXHDRPBinder.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/VFXGraph/VFXHDRPBinder.cs index a6eee31ec2f..1eeae1c97ec 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/VFXGraph/VFXHDRPBinder.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/VFXGraph/VFXHDRPBinder.cs @@ -7,6 +7,7 @@ using UnityEditor.ShaderGraph.Internal; using UnityEditor.VFX; using UnityEngine; +using UnityEngine.Rendering; using UnityEngine.Rendering.HighDefinition; using BlendMode = UnityEditor.Rendering.HighDefinition.BlendMode; @@ -252,5 +253,14 @@ public override ShaderGraphBinder GetShaderGraphDescriptor(VFXContext context, V useFragInputs = true }; } + + public override IEnumerable GetSupportedGraphicDevices() + { + foreach (var device in base.GetSupportedGraphicDevices()) + { + if (HDUtils.IsSupportedGraphicDevice(device)) + yield return device; + } + } } } diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/Compositor/AlphaInjection.cs b/Packages/com.unity.render-pipelines.high-definition/Runtime/Compositor/AlphaInjection.cs index 710fceffc2a..640a9e711dc 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/Compositor/AlphaInjection.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/Compositor/AlphaInjection.cs @@ -17,8 +17,26 @@ internal class ShaderIDs } Material m_Material; + CompositionFilter m_CurrentFilter; - public bool IsActive() => m_Material != null; + public bool IsActive(HDCamera hdCamera) + { + if (m_Material == null) + return false; + + hdCamera.camera.gameObject.TryGetComponent(out var layerData); + if (layerData == null || layerData.layerFilters == null) + return false; + + int index = layerData.layerFilters.FindIndex(x => x.filterType == CompositionFilter.FilterType.ALPHA_MASK); + if (index < 0) + return false; + + // Keep the current filter for the rendering avoiding to re-fetch it later on + m_CurrentFilter = layerData.layerFilters[index]; + + return true; + } public override CustomPostProcessInjectionPoint injectionPoint => CustomPostProcessInjectionPoint.BeforePostProcess; @@ -34,24 +52,8 @@ public override void Render(CommandBuffer cmd, HDCamera camera, RTHandle source, { Debug.Assert(m_Material != null); - AdditionalCompositorData layerData = null; - camera.camera.gameObject.TryGetComponent(out layerData); - if (layerData == null || layerData.layerFilters == null) - { - HDUtils.BlitCameraTexture(cmd, source, destination); - return; - } - - int index = layerData.layerFilters.FindIndex(x => x.filterType == CompositionFilter.FilterType.ALPHA_MASK); - if (index < 0) - { - HDUtils.BlitCameraTexture(cmd, source, destination); - return; - } - - var filter = layerData.layerFilters[index]; m_Material.SetTexture(ShaderIDs.k_InputTexture, source); - m_Material.SetTexture(ShaderIDs.k_AlphaTexture, filter.alphaMask); + m_Material.SetTexture(ShaderIDs.k_AlphaTexture, m_CurrentFilter.alphaMask); HDUtils.DrawFullScreen(cmd, m_Material, destination); } diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/Compositor/ChromaKeying.cs b/Packages/com.unity.render-pipelines.high-definition/Runtime/Compositor/ChromaKeying.cs index fcd96202cc1..4614c7e5989 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/Compositor/ChromaKeying.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/Compositor/ChromaKeying.cs @@ -20,8 +20,26 @@ internal class ShaderIDs public BoolParameter activate = new BoolParameter(false); Material m_Material; + CompositionFilter m_CurrentFilter; - public bool IsActive() => m_Material != null; + public bool IsActive(HDCamera hdCamera) + { + if (m_Material == null) + return false; + + hdCamera.camera.gameObject.TryGetComponent(out var layerData); + if (activate.value == false || layerData == null || layerData.layerFilters == null) + return false; + + int index = layerData.layerFilters.FindIndex(x => x.filterType == CompositionFilter.FilterType.CHROMA_KEYING); + if (index < 0) + return false; + + // Keep the current filter for the rendering avoiding to re-fetch it later on + m_CurrentFilter = layerData.layerFilters[index]; + + return true; + } public override CustomPostProcessInjectionPoint injectionPoint => CustomPostProcessInjectionPoint.BeforePostProcess; @@ -37,30 +55,15 @@ public override void Render(CommandBuffer cmd, HDCamera camera, RTHandle source, { Debug.Assert(m_Material != null); - AdditionalCompositorData layerData = null; - camera.camera.gameObject.TryGetComponent(out layerData); - - if (activate.value == false || layerData == null || layerData.layerFilters == null) - { - HDUtils.BlitCameraTexture(cmd, source, destination); - return; - } - - int index = layerData.layerFilters.FindIndex(x => x.filterType == CompositionFilter.FilterType.CHROMA_KEYING); - if (index < 0) - { - HDUtils.BlitCameraTexture(cmd, source, destination); - return; - } + camera.camera.gameObject.TryGetComponent(out var layerData); - var filter = layerData.layerFilters[index]; Vector4 keyParams; - keyParams.x = filter.keyThreshold; - keyParams.y = filter.keyTolerance; - keyParams.z = filter.spillRemoval; + keyParams.x = m_CurrentFilter.keyThreshold; + keyParams.y = m_CurrentFilter.keyTolerance; + keyParams.z = m_CurrentFilter.spillRemoval; keyParams.w = 1.0f; - m_Material.SetVector(ShaderIDs.k_KeyColor, filter.maskColor); + m_Material.SetVector(ShaderIDs.k_KeyColor, m_CurrentFilter.maskColor); m_Material.SetVector(ShaderIDs.k_KeyParams, keyParams); m_Material.SetTexture(ShaderIDs.k_InputTexture, source); HDUtils.DrawFullScreen(cmd, m_Material, destination); diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugOverlay.cs b/Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugOverlay.cs index 15eb46caf74..1e0beeb9fd0 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugOverlay.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugOverlay.cs @@ -3,6 +3,7 @@ namespace UnityEngine.Rendering.HighDefinition /// /// Utility class for debug overlay coordinates. /// + [System.Obsolete("Please use UnityEngine.Rendering.DebugOverlay")] public class DebugOverlay { /// Current x coordinate. diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeDebug.hlsl b/Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeDebug.hlsl index b5cdec2c36e..8bf3554cf3e 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeDebug.hlsl +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeDebug.hlsl @@ -23,6 +23,7 @@ uniform float _OffsetSize; UNITY_INSTANCING_BUFFER_START(Props) UNITY_DEFINE_INSTANCED_PROP(float, _Validity) + UNITY_DEFINE_INSTANCED_PROP(float, _DilationThreshold) UNITY_DEFINE_INSTANCED_PROP(float, _TouchupedByVolume) UNITY_DEFINE_INSTANCED_PROP(float4, _IndexInAtlas) UNITY_DEFINE_INSTANCED_PROP(float4, _Offset) diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeDebug.shader b/Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeDebug.shader index 2341efc44a7..1edf827c916 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeDebug.shader +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeDebug.shader @@ -56,7 +56,8 @@ Shader "Hidden/HDRP/ProbeVolumeDebug" else if (_ShadingMode == DEBUGPROBESHADINGMODE_VALIDITY_OVER_DILATION_THRESHOLD) { float validity = UNITY_ACCESS_INSTANCED_PROP(Props, _Validity); - if (validity > _ValidityThreshold) + float threshold = UNITY_ACCESS_INSTANCED_PROP(Props, _DilationThreshold); + if (validity > threshold) { return float4(1, 0, 0, 1); } diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeFragmentationDebug.shader b/Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeFragmentationDebug.shader new file mode 100644 index 00000000000..0869171cf54 --- /dev/null +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeFragmentationDebug.shader @@ -0,0 +1,69 @@ +Shader "Hidden/HDRP/ProbeVolumeFragmentationDebug" +{ + SubShader + { + Tags{ "RenderPipeline" = "HDRenderPipeline" } + Pass + { + ZWrite On + ZTest Always + Blend Off + Cull Off + + HLSLPROGRAM + #pragma editor_sync_compilation + #pragma target 4.5 + #pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch + + #pragma vertex Vert + #pragma fragment Frag + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeDebug.hlsl" + + #pragma enable_d3d11_debug_symbols + + int _ChunkCount; + StructuredBuffer _DebugFragmentation; + + struct Attributes + { + uint vertexID : SV_VertexID; + }; + + struct Varyings + { + float4 positionCS : SV_POSITION; + float2 texcoord : TEXCOORD0; + }; + + Varyings Vert(Attributes input) + { + Varyings output; + output.positionCS = GetFullScreenTriangleVertexPosition(input.vertexID); + output.texcoord = GetFullScreenTriangleTexCoord(input.vertexID); + + return output; + } + + float4 Frag(Varyings input) : SV_Target + { + int lineSize = (int)ceil(sqrt(_ChunkCount)); + int2 coord = (int2)(input.texcoord * lineSize); + + int index = coord.y * lineSize + coord.x; + + float4 color = 0.0; + if (index < _ChunkCount && _DebugFragmentation[index] != -1) + color = float4(0.0, 1.0, 0.0, 1.0); + + return color; + } + + ENDHLSL + } + + } + Fallback Off +} diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeFragmentationDebug.shader.meta b/Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeFragmentationDebug.shader.meta new file mode 100644 index 00000000000..fe8c25d74eb --- /dev/null +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/ProbeVolumeFragmentationDebug.shader.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 3a80877c579b9144ebdcc6d923bca303 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + preprocessorOverride: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDRenderPIpeline.ScreenSpaceShadowsArea.cs b/Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDRenderPIpeline.ScreenSpaceShadowsArea.cs index 6998bf63a84..0d7938a19f2 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDRenderPIpeline.ScreenSpaceShadowsArea.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDRenderPIpeline.ScreenSpaceShadowsArea.cs @@ -139,7 +139,7 @@ static void ExecuteSSSAreaRayTrace(CommandBuffer cmd, RTShadowAreaPassData data) // Update the shadow history buffer cmd.SetComputeTextureParam(data.screenSpaceShadowsFilterCS, data.areaUpdateAnalyticHistoryKernel, HDShaderIDs._AnalyticProbBuffer, data.intermediateBufferRG0); - cmd.SetComputeTextureParam(data.screenSpaceShadowsFilterCS, data.areaUpdateAnalyticHistoryKernel, HDShaderIDs._AnalyticHistoryBuffer, data.analyticHistoryArray); + cmd.SetComputeTextureParam(data.screenSpaceShadowsFilterCS, data.areaUpdateAnalyticHistoryKernel, HDShaderIDs._AnalyticHistoryBufferRW, data.analyticHistoryArray); cmd.DispatchCompute(data.screenSpaceShadowsFilterCS, data.areaUpdateAnalyticHistoryKernel, numTilesX, numTilesY, data.viewCount); // Update the analytic history buffer @@ -268,13 +268,9 @@ void RenderAreaScreenSpaceShadow(RenderGraph renderGraph, HDCamera hdCamera passData.worldToLocalMatrix.SetColumn(2, lightData.forward); // Compensate the relative rendering if active Vector3 lightPositionWS = lightData.positionRWS; - if (ShaderConfig.s_CameraRelativeRendering != 0) - { - lightPositionWS -= hdCamera.camera.transform.position; - } passData.worldToLocalMatrix.SetColumn(3, lightPositionWS); passData.worldToLocalMatrix.m33 = 1.0f; - passData.worldToLocalMatrix = m_WorldToLocalArea.inverse; + passData.worldToLocalMatrix = passData.worldToLocalMatrix.inverse; passData.historyValidity = EvaluateHistoryValidity(hdCamera); passData.filterTracedShadow = additionalLightData.filterTracedShadow; passData.areaShadowSlot = m_GpuLightsBuilder.lights[lightIndex].screenSpaceShadowIndex; diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDRenderPipeline.ScreenSpaceShadows.cs b/Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDRenderPipeline.ScreenSpaceShadows.cs index 6decce90d1d..eaad0d017d1 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDRenderPipeline.ScreenSpaceShadows.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDRenderPipeline.ScreenSpaceShadows.cs @@ -44,8 +44,6 @@ public partial class HDRenderPipeline int m_AreaShadowNoDenoiseKernel; int m_WriteShadowTextureDebugKernel; - // Temporary variable that allows us to store the world to local matrix of the lights - Matrix4x4 m_WorldToLocalArea = new Matrix4x4(); // Temporary variables that allow us to read and write the right channels from the history buffer Vector4 m_ShadowChannelMask0 = new Vector4(1.0f, 1.0f, 1.0f, 1.0f); Vector4 m_ShadowChannelMask1 = new Vector4(1.0f, 1.0f, 1.0f, 1.0f); @@ -59,9 +57,8 @@ static RTHandle ShadowHistoryBufferAllocatorFunction(string viewName, int frameI { HDRenderPipeline hdrp = RenderPipelineManager.currentPipeline as HDRenderPipeline; HDRenderPipelineAsset hdPipelineAsset = hdrp.m_Asset; - GraphicsFormat graphicsFormat = (GraphicsFormat)hdPipelineAsset.currentPlatformRenderPipelineSettings.hdShadowInitParams.screenSpaceShadowBufferFormat; int numShadowSlices = Math.Max((int)Math.Ceiling(hdPipelineAsset.currentPlatformRenderPipelineSettings.hdShadowInitParams.maxScreenSpaceShadowSlots / 4.0f), 1); - return rtHandleSystem.Alloc(Vector2.one, slices: numShadowSlices * TextureXR.slices, dimension: TextureDimension.Tex2DArray, filterMode: FilterMode.Point, colorFormat: graphicsFormat, + return rtHandleSystem.Alloc(Vector2.one, slices: numShadowSlices * TextureXR.slices, dimension: TextureDimension.Tex2DArray, filterMode: FilterMode.Point, colorFormat: GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite: true, useDynamicScale: true, useMipMap: false, name: string.Format("{0}_ScreenSpaceShadowHistoryBuffer{1}", viewName, frameIndex)); } @@ -72,9 +69,8 @@ static RTHandle ShadowHistoryValidityBufferAllocatorFunction(string viewName, in { HDRenderPipeline hdrp = RenderPipelineManager.currentPipeline as HDRenderPipeline; HDRenderPipelineAsset hdPipelineAsset = hdrp.m_Asset; - GraphicsFormat graphicsFormat = (GraphicsFormat)hdPipelineAsset.currentPlatformRenderPipelineSettings.hdShadowInitParams.screenSpaceShadowBufferFormat; int numShadowSlices = Math.Max((int)Math.Ceiling(hdPipelineAsset.currentPlatformRenderPipelineSettings.hdShadowInitParams.maxScreenSpaceShadowSlots / 4.0f), 1); - return rtHandleSystem.Alloc(Vector2.one, slices: numShadowSlices * TextureXR.slices, dimension: TextureDimension.Tex2DArray, filterMode: FilterMode.Point, colorFormat: graphicsFormat, + return rtHandleSystem.Alloc(Vector2.one, slices: numShadowSlices * TextureXR.slices, dimension: TextureDimension.Tex2DArray, filterMode: FilterMode.Point, colorFormat: GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite: true, useDynamicScale: true, useMipMap: false, name: string.Format("{0}_ShadowHistoryValidityBuffer{1}", viewName, frameIndex)); } @@ -82,9 +78,8 @@ static RTHandle ShadowHistoryDistanceBufferAllocatorFunction(string viewName, in { HDRenderPipeline hdrp = RenderPipelineManager.currentPipeline as HDRenderPipeline; HDRenderPipelineAsset hdPipelineAsset = hdrp.m_Asset; - GraphicsFormat graphicsFormat = (GraphicsFormat)hdPipelineAsset.currentPlatformRenderPipelineSettings.hdShadowInitParams.screenSpaceShadowBufferFormat; int numShadowSlices = Math.Max((int)Math.Ceiling(hdPipelineAsset.currentPlatformRenderPipelineSettings.hdShadowInitParams.maxScreenSpaceShadowSlots / 4.0f), 1); - return rtHandleSystem.Alloc(Vector2.one, slices: numShadowSlices * TextureXR.slices, dimension: TextureDimension.Tex2DArray, filterMode: FilterMode.Point, colorFormat: graphicsFormat, + return rtHandleSystem.Alloc(Vector2.one, slices: numShadowSlices * TextureXR.slices, dimension: TextureDimension.Tex2DArray, filterMode: FilterMode.Point, colorFormat: GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite: true, useDynamicScale: true, useMipMap: false, name: string.Format("{0}_ShadowHistoryDistanceBuffer{1}", viewName, frameIndex)); } diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Decal/DecalSystem.cs b/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Decal/DecalSystem.cs index a818f608e51..62e587ff6af 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Decal/DecalSystem.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Decal/DecalSystem.cs @@ -1,11 +1,8 @@ using System; -using System.Collections; using System.Collections.Generic; using Unity.Collections; -using Unity.Mathematics; using UnityEngine.Assertions; using UnityEngine.Experimental.Rendering; -using UnityEngine.Jobs; namespace UnityEngine.Rendering.HighDefinition { @@ -1127,7 +1124,7 @@ public void Cleanup() m_Atlas = null; } - public void RenderDebugOverlay(HDCamera hdCamera, CommandBuffer cmd, int mipLevel, DebugOverlay debugOverlay) + public void RenderDebugOverlay(HDCamera hdCamera, CommandBuffer cmd, int mipLevel, Rendering.DebugOverlay debugOverlay) { cmd.SetViewport(debugOverlay.Next()); HDUtils.BlitQuad(cmd, Atlas.AtlasTexture, new Vector4(1, 1, 0, 0), new Vector4(1, 1, 0, 0), mipLevel, true); diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/DiffusionProfile/DiffusionProfile.hlsl b/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/DiffusionProfile/DiffusionProfile.hlsl index 1078eacff9b..0c91a463afa 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/DiffusionProfile/DiffusionProfile.hlsl +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/DiffusionProfile/DiffusionProfile.hlsl @@ -28,6 +28,13 @@ float3 EvalBurleyDiffusionProfile(float r, float3 S) return (S * rcp(8 * PI)) * expSum; // S / (8 * Pi) * (Exp[-S * r / 3] + Exp[-S * r]) } +float EvalBurleyDiffusionProfileCdf(float r, float S) +{ + float exp_13 = exp2(((LOG2_E * (-1.0 / 3.0)) * r) * S); // Exp[-S * r / 3] + + return 1 - 0.25 * exp_13 * exp_13 * exp_13 - 0.75 * exp_13; +} + // https://zero-radiance.github.io/post/sampling-diffusion/ // Performs sampling of a Normalized Burley diffusion profile in polar coordinates. // 'u' is the random number (the value of the CDF): [0, 1). @@ -56,3 +63,11 @@ void SampleBurleyDiffusionProfile(float u, float rcpS, out float r, out float rc r = x * rcpS; rcpPdf = (8 * PI * rcpS) * rcpExp; // (8 * Pi) / s / (Exp[-s * r / 3] + Exp[-s * r]) } + +void SampleBurleyDiffusionProfileApprox(float u, float rcpS, out float r) +{ + u = 1 - u; // Convert CDF to CCDF + + float x = ((2 - 2.5715) * u - 2) * log(1 - u); + r = x * rcpS; +} diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/DiffusionProfile/DiffusionProfileSettings.cs b/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/DiffusionProfile/DiffusionProfileSettings.cs index 6e337abc5f5..badab1054cf 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/DiffusionProfile/DiffusionProfileSettings.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/DiffusionProfile/DiffusionProfileSettings.cs @@ -19,6 +19,14 @@ enum DefaultSssSampleBudgetForQualityLevel Max = 1000 } + enum DefaultSssDownsampleSteps + { + Low = 0, + Medium = 0, + High = 0, + Max = 2 + } + [Serializable] class DiffusionProfile : IEquatable { diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/SubsurfaceScattering/RandomDownsample.compute b/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/SubsurfaceScattering/RandomDownsample.compute new file mode 100644 index 00000000000..787228ea0e5 --- /dev/null +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/SubsurfaceScattering/RandomDownsample.compute @@ -0,0 +1,41 @@ +//-------------------------------------------------------------------------------------------------- +// Definitions +//-------------------------------------------------------------------------------------------------- + +// #pragma enable_d3d11_debug_symbols +#pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch + +#pragma kernel Downsample + +//-------------------------------------------------------------------------------------------------- +// Included headers +//-------------------------------------------------------------------------------------------------- + +#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" +#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + +//-------------------------------------------------------------------------------------------------- +// Inputs & outputs +//-------------------------------------------------------------------------------------------------- +TEXTURE2D_X(_SourceTexture); +RW_TEXTURE2D_X(float4, _OutputTexture); + +int _SssDownsampleSteps; + +#define GROUP_SIZE 8 + +[numthreads(GROUP_SIZE, GROUP_SIZE, 1)] +void Downsample(uint3 dispatchThreadId : SV_DispatchThreadID) +{ + uint2 positionSS = dispatchThreadId.xy; + uint scale1d = 1u << _SssDownsampleSteps; + + // Downsample will just randomly select one of the source samples + float rand = InterleavedGradientNoise(positionSS, _FrameCount); + uint index = uint(rand * scale1d * scale1d); + + uint2 inputSS = (positionSS * scale1d) + uint2(index / scale1d, index % scale1d); + + float4 value = LOAD_TEXTURE2D_X(_SourceTexture, inputSS); + _OutputTexture[COORD_TEXTURE2D_X(positionSS)] = value; +} diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/SubsurfaceScattering/RandomDownsample.compute.meta b/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/SubsurfaceScattering/RandomDownsample.compute.meta new file mode 100644 index 00000000000..24010c60d2c --- /dev/null +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/SubsurfaceScattering/RandomDownsample.compute.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 4f8aaf0160a259e499fdfac512ca2692 +ComputeShaderImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/SubsurfaceScattering/SubsurfaceScattering.compute b/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/SubsurfaceScattering/SubsurfaceScattering.compute index 39612c666a0..54c7aaf7439 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/SubsurfaceScattering/SubsurfaceScattering.compute +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/SubsurfaceScattering/SubsurfaceScattering.compute @@ -10,6 +10,7 @@ #pragma kernel SubsurfaceScattering #pragma multi_compile _ ENABLE_MSAA +#pragma multi_compile _ USE_DOWNSAMPLE // TODO: use sharp load hoisting on PS4. @@ -21,6 +22,7 @@ #define SSS_CLAMP_ARTIFACT 0 // Reduces bleeding. Use with SSS_USE_TANGENT_PLANE. #define SSS_DEBUG_LOD 0 // Displays the sampling rate: green = no filtering, blue = 1 sample, red = _SssSampleBudget samples. #define SSS_DEBUG_NORMAL_VS 0 // Allows detection of back-facing normals. +#define SSS_DEBUG_PATTERN 0 // Shows the sample pattern of one pixel // Do not modify these. #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" @@ -55,9 +57,11 @@ //-------------------------------------------------------------------------------------------------- int _SssSampleBudget; +int _SssDownsampleSteps; TEXTURE2D_X(_DepthTexture); // Z-buffer TEXTURE2D_X(_IrradianceSource); // Includes transmitted light +TEXTURE2D_X(_IrradianceSourceDownsampled); StructuredBuffer _CoarseStencilBuffer; @@ -98,7 +102,11 @@ float4 LoadSampleFromCacheMemory(int2 cacheCoord) float4 LoadSampleFromVideoMemory(int2 pixelCoord) { +#ifndef USE_DOWNSAMPLE float3 irradiance = LOAD_TEXTURE2D_X(_IrradianceSource, pixelCoord).rgb; +#else + float3 irradiance = LOAD_TEXTURE2D_X(_IrradianceSourceDownsampled, pixelCoord >> _SssDownsampleSteps).rgb; +#endif float depth = LOAD_TEXTURE2D_X(_DepthTexture, pixelCoord).r; return float4(irradiance, depth); @@ -165,10 +173,24 @@ float3 ComputeBilateralWeight(float xy2, float z, float mmPerUnit, float3 S, flo #endif } + +// Structure for debug information regarding the sample pattern +// Note: removed for non debug builds to not affect performance +struct DebugInfo +{ +#if SSS_DEBUG_PATTERN + // Input + uint2 testCoord; + // Output + bool testCoordHit; + bool withinRadius; +#endif +}; + void EvaluateSample(uint i, uint n, int2 pixelCoord, int2 cacheOffset, float3 S, float d, float3 centerPosVS, float mmPerUnit, float pixelsPerMm, - float phase, float3 tangentX, float3 tangentY, float4x4 projMatrix, - inout float3 totalIrradiance, inout float3 totalWeight, float linearDepth) + float phase, float3 tangentX, float3 tangentY, float4x4 projMatrix, float linearDepth, inout DebugInfo debugInfo, + inout float3 totalIrradiance, inout float3 totalWeight) { // The sample count is loop-invariant. const float scale = rcp(n); @@ -233,6 +255,10 @@ void EvaluateSample(uint i, uint n, int2 pixelCoord, int2 cacheOffset, // We do not terminate the loop since we want to gather the contribution // of the remaining samples (e.g. in case of hair covering skin). } + +#if SSS_DEBUG_PATTERN + debugInfo.testCoordHit = debugInfo.testCoordHit || all(debugInfo.testCoord == position); +#endif } void StoreResult(uint2 pixelCoord, float3 irradiance) @@ -244,6 +270,142 @@ void StoreResult(uint2 pixelCoord, float3 irradiance) #endif } +struct CacheInfo +{ + uint2 cacheCoord; + int2 cacheOffset; +}; + +struct CenterInfo +{ + float3 irradiance; + float depth; +}; + +struct SssResult +{ + float3 irradiance; +}; + +void EvaluateSss(uint2 pixelCoord, CacheInfo cacheInfo, CenterInfo centerInfo, inout DebugInfo debugInfo, out SssResult result) +{ + // Initialize the result + result = (SssResult)0; + + PositionInputs posInput = GetPositionInput(pixelCoord, _ScreenSize.zw); + + // The result of the stencil test allows us to statically determine the material type (SSS). + SSSData sssData; + DECODE_FROM_SSSBUFFER(posInput.positionSS, sssData); + + int profileIndex = sssData.diffusionProfileIndex; + float distScale = sssData.subsurfaceMask; + float3 S = _ShapeParamsAndMaxScatterDists[profileIndex].rgb; + float d = _ShapeParamsAndMaxScatterDists[profileIndex].a; + float metersPerUnit = _WorldScalesAndFilterRadiiAndThicknessRemaps[profileIndex].x; + float filterRadius = _WorldScalesAndFilterRadiiAndThicknessRemaps[profileIndex].y; // In millimeters + + // Reconstruct the view-space position corresponding to the central sample. + float2 centerPosNDC = posInput.positionNDC; + float2 cornerPosNDC = centerPosNDC + 0.5 * _ScreenSize.zw; + float3 centerPosVS = ComputeViewSpacePosition(centerPosNDC, centerInfo.depth, UNITY_MATRIX_I_P); + float3 cornerPosVS = ComputeViewSpacePosition(cornerPosNDC, centerInfo.depth, UNITY_MATRIX_I_P); + + // Rescaling the filter is equivalent to inversely scaling the world. + float mmPerUnit = MILLIMETERS_PER_METER * (metersPerUnit * rcp(distScale)); + float unitsPerMm = rcp(mmPerUnit); + + // Compute the view-space dimensions of the pixel as a quad projected onto geometry. + // Assuming square pixels, both X and Y are have the same dimensions. + float unitsPerPixel = max(0.0001f, 2 * abs(cornerPosVS.x - centerPosVS.x)); + float pixelsPerMm = rcp(unitsPerPixel) * unitsPerMm; + + // Area of a disk. + float filterArea = PI * Sq(filterRadius * pixelsPerMm); + uint sampleCount = (uint)(filterArea * rcp(SSS_PIXELS_PER_SAMPLE)); + uint sampleBudget = (uint)_SssSampleBudget; + + uint texturingMode = GetSubsurfaceScatteringTexturingMode(profileIndex); + float3 albedo = ApplySubsurfaceScatteringTexturingMode(texturingMode, sssData.diffuseColor); + + if (distScale == 0 || sampleCount < 1) + { +#if SSS_DEBUG_LOD + float3 green = float3(0, 1, 0); + result.irradiance = green; +#else + result.irradiance = albedo * centerInfo.irradiance; +#endif + return; + } + +#if SSS_DEBUG_LOD + float3 red = float3(1, 0, 0); + float3 blue = float3(0, 0, 1); + result.irradiance = lerp(blue, red, saturate(sampleCount * rcp(sampleBudget))); + return; +#endif + + float4x4 viewMatrix, projMatrix; + GetLeftHandedViewSpaceMatrices(viewMatrix, projMatrix); + + // TODO: Since we have moved to forward SSS, we don't support anymore a bsdfData.normalWS. + // Once we include normal+roughness rendering during the prepass, we will have a buffer to bind here and we will be able to reuse this part of the algorithm on demand. +#if SSS_USE_TANGENT_PLANE +#error ThisWillNotCompile_SeeComment +// Compute the tangent frame in view space. + float3 normalVS = mul((float3x3)viewMatrix, bsdfData.normalWS); + float3 tangentX = GetLocalFrame(normalVS)[0] * unitsPerMm; + float3 tangentY = GetLocalFrame(normalVS)[1] * unitsPerMm; +#else + float3 normalVS = float3(0, 0, 0); + float3 tangentX = float3(0, 0, 0); + float3 tangentY = float3(0, 0, 0); +#endif + +#if SSS_DEBUG_NORMAL_VS + // We expect the normal to be front-facing. + float3 viewDirVS = normalize(centerPosVS); + if (dot(normalVS, viewDirVS) >= 0) + { + result.irradiance = float3(1, 1, 1); + return; + } +#endif + +#if SSS_RANDOM_ROTATION + // Note that GenerateHashedRandomFloat() only uses the 23 low bits, hence the 2^24 factor. + float phase = TWO_PI * GenerateHashedRandomFloat(uint3(pixelCoord, (uint)(centerInfo.depth * 16777216))); +#else + float phase = 0; +#endif + + uint n = min(sampleCount, sampleBudget); + + // Accumulate filtered irradiance and bilateral weights (for renormalization). + float3 centerWeight = 0; // Defer (* albedo) + float3 totalIrradiance = 0; + float3 totalWeight = 0; + + float linearDepth = LinearEyeDepth(centerInfo.depth, _ZBufferParams); + for (uint i = 0; i < n; i++) + { + // Integrate over the image or tangent plane in the view space. + EvaluateSample(i, n, pixelCoord, cacheInfo.cacheOffset, + S, d, centerPosVS, mmPerUnit, pixelsPerMm, + phase, tangentX, tangentY, projMatrix, linearDepth, debugInfo, + totalIrradiance, totalWeight); + } + + // Total weight is 0 for color channels without scattering. + totalWeight = max(totalWeight, FLT_MIN); + +#if SSS_DEBUG_PATTERN + debugInfo.withinRadius = length(float2(pixelCoord) - float2(debugInfo.testCoord)) * rcp(pixelsPerMm) < filterRadius; +#endif + result.irradiance = albedo * (totalIrradiance / totalWeight); +} + [numthreads(GROUP_SIZE_2D, 1, 1)] void SubsurfaceScattering(uint3 groupId : SV_GroupID, uint groupThreadId : SV_GroupThreadID, @@ -261,7 +423,10 @@ void SubsurfaceScattering(uint3 groupId : SV_GroupID, uint2 groupCoord = DecodeMorton2D(groupThreadId); uint2 groupOffset = groupId.xy * GROUP_SIZE_1D; uint2 pixelCoord = groupOffset + groupCoord; - int2 cacheOffset = (int2)groupOffset - TEXTURE_CACHE_BORDER; + + CacheInfo cacheInfo; + cacheInfo.cacheOffset = (int2)groupOffset - TEXTURE_CACHE_BORDER; + cacheInfo.cacheCoord = groupCoord + TEXTURE_CACHE_BORDER; if (groupThreadId == 0) { @@ -288,20 +453,20 @@ void SubsurfaceScattering(uint3 groupId : SV_GroupID, if (!processGroup) { return; } - float3 centerIrradiance = LOAD_TEXTURE2D_X(_IrradianceSource, pixelCoord).rgb; - float centerDepth = 0; - bool passedStencilTest = TestLightingForSSS(centerIrradiance); + CenterInfo centerInfo; + centerInfo.irradiance = LOAD_TEXTURE2D_X(_IrradianceSource, pixelCoord).rgb; + centerInfo.depth = 0; + bool passedStencilTest = TestLightingForSSS(centerInfo.irradiance); // Save some bandwidth by only loading depth values for SSS pixels. if (passedStencilTest) { - centerDepth = LOAD_TEXTURE2D_X(_DepthTexture, pixelCoord).r; + centerInfo.depth = LOAD_TEXTURE2D_X(_DepthTexture, pixelCoord).r; } #if SSS_USE_LDS_CACHE - uint2 cacheCoord = groupCoord + TEXTURE_CACHE_BORDER; // Populate the central region of the LDS cache. - StoreSampleToCacheMemory(float4(centerIrradiance, centerDepth), cacheCoord); + StoreSampleToCacheMemory(float4(centerInfo.irradiance, centerInfo.depth), cacheInfo.cacheCoord); uint numBorderQuadsPerWave = TEXTURE_CACHE_SIZE_1D / 2 - 1; uint halfCacheWidthInQuads = TEXTURE_CACHE_SIZE_1D / 4; @@ -358,113 +523,39 @@ void SubsurfaceScattering(uint3 groupId : SV_GroupID, if (!passedStencilTest) { return; } - PositionInputs posInput = GetPositionInput(pixelCoord, _ScreenSize.zw); + DebugInfo debugInfo; + debugInfo = (DebugInfo)0; - // The result of the stencil test allows us to statically determine the material type (SSS). - SSSData sssData; - DECODE_FROM_SSSBUFFER(posInput.positionSS, sssData); + SssResult result; + EvaluateSss(pixelCoord, cacheInfo, centerInfo, debugInfo, result); - int profileIndex = sssData.diffusionProfileIndex; - float distScale = sssData.subsurfaceMask; - float3 S = _ShapeParamsAndMaxScatterDists[profileIndex].rgb; - float d = _ShapeParamsAndMaxScatterDists[profileIndex].a; - float metersPerUnit = _WorldScalesAndFilterRadiiAndThicknessRemaps[profileIndex].x; - float filterRadius = _WorldScalesAndFilterRadiiAndThicknessRemaps[profileIndex].y; // In millimeters + float3 irradiance = result.irradiance; - // Reconstruct the view-space position corresponding to the central sample. - float2 centerPosNDC = posInput.positionNDC; - float2 cornerPosNDC = centerPosNDC + 0.5 * _ScreenSize.zw; - float3 centerPosVS = ComputeViewSpacePosition(centerPosNDC, centerDepth, UNITY_MATRIX_I_P); - float3 cornerPosVS = ComputeViewSpacePosition(cornerPosNDC, centerDepth, UNITY_MATRIX_I_P); +#if SSS_DEBUG_PATTERN + // Find the center of the screen + uint2 screenCenter = uint2(_ScreenSize.xy / 2); - // Rescaling the filter is equivalent to inversely scaling the world. - float mmPerUnit = MILLIMETERS_PER_METER * (metersPerUnit * rcp(distScale)); - float unitsPerMm = rcp(mmPerUnit); + // Evaluate SSS again at the pixel in the middle of the screen + // using the current pixel coordinate as the test pixel + debugInfo.testCoord = pixelCoord; + debugInfo.testCoordHit = false; + debugInfo.withinRadius = false; - // Compute the view-space dimensions of the pixel as a quad projected onto geometry. - // Assuming square pixels, both X and Y are have the same dimensions. - float unitsPerPixel = max(0.0001f, 2 * abs(cornerPosVS.x - centerPosVS.x)); - float pixelsPerMm = rcp(unitsPerPixel) * unitsPerMm; + // refresh with data from the sceen center + centerInfo.irradiance = LOAD_TEXTURE2D_X(_IrradianceSource, screenCenter).rgb; + centerInfo.depth = LOAD_TEXTURE2D_X(_DepthTexture, screenCenter).r; - // Area of a disk. - float filterArea = PI * Sq(filterRadius * pixelsPerMm); - uint sampleCount = (uint)(filterArea * rcp(SSS_PIXELS_PER_SAMPLE)); - uint sampleBudget = (uint)_SssSampleBudget; + EvaluateSss(screenCenter, cacheInfo, centerInfo, debugInfo, result); - uint texturingMode = GetSubsurfaceScatteringTexturingMode(profileIndex); - float3 albedo = ApplySubsurfaceScatteringTexturingMode(texturingMode, sssData.diffuseColor); + // Draw a lighter circle indicating profile radius + irradiance += debugInfo.withinRadius ? float3(0.1, 0.1, 0.1) : float3(0, 0, 0); - if (distScale == 0 || sampleCount < 1) - { - #if SSS_DEBUG_LOD - float3 green = float3(0, 1, 0); - StoreResult(pixelCoord, green); - #else - StoreResult(pixelCoord, albedo * centerIrradiance); - #endif - return; - } + // Draw dashed threaed group border + irradiance = any(pixelCoord % GROUP_SIZE_1D == 0) && all(pixelCoord % 2 == 0) ? float3(0, 0, 0) : irradiance; -#if SSS_DEBUG_LOD - float3 red = float3(1, 0, 0); - float3 blue = float3(0, 0, 1); - StoreResult(pixelCoord, lerp(blue, red, saturate(sampleCount * rcp(sampleBudget)))); - return; + // Draw sample positions as white pixels + irradiance = debugInfo.testCoordHit ? float3(1, 1, 1) : irradiance; #endif - float4x4 viewMatrix, projMatrix; - GetLeftHandedViewSpaceMatrices(viewMatrix, projMatrix); - - // TODO: Since we have moved to forward SSS, we don't support anymore a bsdfData.normalWS. - // Once we include normal+roughness rendering during the prepass, we will have a buffer to bind here and we will be able to reuse this part of the algorithm on demand. -#if SSS_USE_TANGENT_PLANE - #error ThisWillNotCompile_SeeComment - // Compute the tangent frame in view space. - float3 normalVS = mul((float3x3)viewMatrix, bsdfData.normalWS); - float3 tangentX = GetLocalFrame(normalVS)[0] * unitsPerMm; - float3 tangentY = GetLocalFrame(normalVS)[1] * unitsPerMm; -#else - float3 normalVS = float3(0, 0, 0); - float3 tangentX = float3(0, 0, 0); - float3 tangentY = float3(0, 0, 0); -#endif - -#if SSS_DEBUG_NORMAL_VS - // We expect the normal to be front-facing. - float3 viewDirVS = normalize(centerPosVS); - if (dot(normalVS, viewDirVS) >= 0) - { - StoreResult(pixelCoord, float3(1, 1, 1)); - return; - } -#endif - -#if SSS_RANDOM_ROTATION - // Note that GenerateHashedRandomFloat() only uses the 23 low bits, hence the 2^24 factor. - float phase = TWO_PI * GenerateHashedRandomFloat(uint3(pixelCoord, (uint)(centerDepth * 16777216))); -#else - float phase = 0; -#endif - - uint n = min(sampleCount, sampleBudget); - - // Accumulate filtered irradiance and bilateral weights (for renormalization). - float3 centerWeight = 0; // Defer (* albedo) - float3 totalIrradiance = 0; - float3 totalWeight = 0; - - float linearDepth = LinearEyeDepth(centerDepth, _ZBufferParams); - for (uint i = 0; i < n; i++) - { - // Integrate over the image or tangent plane in the view space. - EvaluateSample(i, n, pixelCoord, cacheOffset, - S, d, centerPosVS, mmPerUnit, pixelsPerMm, - phase, tangentX, tangentY, projMatrix, - totalIrradiance, totalWeight, linearDepth); - } - - // Total weight is 0 for color channels without scattering. - totalWeight = max(totalWeight, FLT_MIN); - - StoreResult(pixelCoord, albedo * (totalIrradiance / totalWeight)); + StoreResult(pixelCoord, irradiance); } diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLit.shader b/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLit.shader index f9451b66b9a..cc30a5c83e2 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLit.shader +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLit.shader @@ -379,6 +379,7 @@ Shader "HDRP/TerrainLit" #define SHADOW_LOW #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLitTemplateRayTracing.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLit_Splatmap.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassRaytracingIndirect.hlsl" ENDHLSL } @@ -408,6 +409,7 @@ Shader "HDRP/TerrainLit" #define SHADOW_LOW #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLitTemplateRayTracing.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLit_Splatmap.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassRaytracingForward.hlsl" ENDHLSL } @@ -435,6 +437,7 @@ Shader "HDRP/TerrainLit" #define SHADERPASS SHADERPASS_RAYTRACING_GBUFFER #pragma multi_compile _ MINIMAL_GBUFFER #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLitTemplateRayTracing.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLit_Splatmap.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassRaytracingGBuffer.hlsl" ENDHLSL } @@ -456,6 +459,7 @@ Shader "HDRP/TerrainLit" #define SHADERPASS SHADERPASS_RAYTRACING_VISIBILITY #pragma multi_compile _ TRANSPARENT_COLOR_SHADOW #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLitTemplateRayTracing.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLit_Splatmap.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassRaytracingVisibility.hlsl" ENDHLSL } @@ -518,6 +522,7 @@ Shader "HDRP/TerrainLit" #endif #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLitTemplateRayTracing.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLit_Splatmap.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassPathTracing.hlsl" ENDHLSL } diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLitTemplateRayTracing.hlsl b/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLitTemplateRayTracing.hlsl index fc9bca00a89..3d94a39965b 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLitTemplateRayTracing.hlsl +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLitTemplateRayTracing.hlsl @@ -37,4 +37,3 @@ #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RayTracingCommon.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLitData.hlsl" -#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLit_Splatmap.hlsl" diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLit_Basemap.shader b/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLit_Basemap.shader index 1e01f1b80ca..0a101ecbf99 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLit_Basemap.shader +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLit_Basemap.shader @@ -47,15 +47,8 @@ Shader "Hidden/HDRP/TerrainLit_Basemap" #pragma shader_feature_local _DISABLE_DECALS #pragma shader_feature_local _TERRAIN_INSTANCED_PERPIXEL_NORMAL - //enable GPU instancing support - #pragma multi_compile_instancing - #pragma instancing_options assumeuniformscaling nomatrices nolightprobe nolightmap - #pragma multi_compile _ _ALPHATEST_ON - #pragma vertex Vert - #pragma fragment Frag - #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLit_Basemap_Includes.hlsl" ENDHLSL @@ -83,6 +76,12 @@ Shader "Hidden/HDRP/TerrainLit_Basemap" } HLSLPROGRAM + //enable GPU instancing support + #pragma multi_compile_instancing + #pragma instancing_options assumeuniformscaling nomatrices nolightprobe nolightmap + + #pragma vertex Vert + #pragma fragment Frag #pragma multi_compile _ DEBUG_DISPLAY #pragma multi_compile _ LIGHTMAP_ON @@ -111,6 +110,12 @@ Shader "Hidden/HDRP/TerrainLit_Basemap" Cull Off HLSLPROGRAM + //enable GPU instancing support + #pragma multi_compile_instancing + #pragma instancing_options assumeuniformscaling nomatrices nolightprobe nolightmap + + #pragma vertex Vert + #pragma fragment Frag // Lightmap memo // DYNAMICLIGHTMAP_ON is used when we have an "enlighten lightmap" ie a lightmap updated at runtime by enlighten.This lightmap contain indirect lighting from realtime lights and realtime emissive material.Offline baked lighting(from baked material / light, @@ -137,6 +142,12 @@ Shader "Hidden/HDRP/TerrainLit_Basemap" ColorMask 0 HLSLPROGRAM + //enable GPU instancing support + #pragma multi_compile_instancing + #pragma instancing_options assumeuniformscaling nomatrices nolightprobe nolightmap + + #pragma vertex Vert + #pragma fragment Frag #define SHADERPASS SHADERPASS_SHADOWS #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLitTemplate.hlsl" @@ -164,6 +175,12 @@ Shader "Hidden/HDRP/TerrainLit_Basemap" ZWrite On HLSLPROGRAM + //enable GPU instancing support + #pragma multi_compile_instancing + #pragma instancing_options assumeuniformscaling nomatrices nolightprobe nolightmap + + #pragma vertex Vert + #pragma fragment Frag // In deferred, depth only pass don't output anything. // In forward it output the normal buffer @@ -197,6 +214,12 @@ Shader "Hidden/HDRP/TerrainLit_Basemap" Cull [_CullMode] HLSLPROGRAM + //enable GPU instancing support + #pragma multi_compile_instancing + #pragma instancing_options assumeuniformscaling nomatrices nolightprobe nolightmap + + #pragma vertex Vert + #pragma fragment Frag #pragma multi_compile _ DEBUG_DISPLAY #pragma multi_compile _ LIGHTMAP_ON @@ -224,4 +247,184 @@ Shader "Hidden/HDRP/TerrainLit_Basemap" UsePass "Hidden/Nature/Terrain/Utilities/PICKING" UsePass "HDRP/TerrainLit/SceneSelectionPass" } + + SubShader + { + Tags{ "RenderPipeline" = "HDRenderPipeline" "RenderType" = "Opaque" } + + Pass + { + Name "IndirectDXR" + Tags{ "LightMode" = "IndirectDXR" } + + HLSLPROGRAM + + #pragma only_renderers d3d11 xboxseries ps5 + #pragma raytracing surface_shader + + #pragma multi_compile _ DEBUG_DISPLAY + #pragma multi_compile _ LIGHTMAP_ON + #pragma multi_compile _ DYNAMICLIGHTMAP_ON + #pragma multi_compile PROBE_VOLUMES_OFF PROBE_VOLUMES_L1 PROBE_VOLUMES_L2 + #pragma multi_compile _ DIRLIGHTMAP_COMBINED + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" + + #define SHADERPASS SHADERPASS_RAYTRACING_INDIRECT + // multi compile that allows us to strip the recursive code + #pragma multi_compile _ MULTI_BOUNCE_INDIRECT + + #define SHADOW_LOW + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLitTemplateRayTracing.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLit_Basemap.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassRaytracingIndirect.hlsl" + ENDHLSL + } + + Pass + { + Name "ForwardDXR" + Tags{ "LightMode" = "ForwardDXR" } + + HLSLPROGRAM + #pragma only_renderers d3d11 xboxseries ps5 + #pragma raytracing surface_shader + + #pragma multi_compile _ DEBUG_DISPLAY + #pragma multi_compile _ LIGHTMAP_ON + #pragma multi_compile _ DYNAMICLIGHTMAP_ON + #pragma multi_compile PROBE_VOLUMES_OFF PROBE_VOLUMES_L1 PROBE_VOLUMES_L2 + #pragma multi_compile _ DIRLIGHTMAP_COMBINED + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" + + #define SHADERPASS SHADERPASS_RAYTRACING_FORWARD + // multi compile that allows us to strip the recursive code + + #define SHADOW_LOW + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLitTemplateRayTracing.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLit_Basemap.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassRaytracingForward.hlsl" + ENDHLSL + } + + Pass + { + Name "GBufferDXR" + Tags{ "LightMode" = "GBufferDXR" } + + HLSLPROGRAM + + #pragma only_renderers d3d11 xboxseries ps5 + #pragma raytracing surface_shader + + #pragma multi_compile _ DEBUG_DISPLAY + #pragma multi_compile _ LIGHTMAP_ON + #pragma multi_compile _ DYNAMICLIGHTMAP_ON + #pragma multi_compile PROBE_VOLUMES_OFF PROBE_VOLUMES_L1 PROBE_VOLUMES_L2 + #pragma multi_compile _ DIRLIGHTMAP_COMBINED + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" + + #define SHADERPASS SHADERPASS_RAYTRACING_GBUFFER + #pragma multi_compile _ MINIMAL_GBUFFER + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLitTemplateRayTracing.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLit_Basemap.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassRaytracingGBuffer.hlsl" + ENDHLSL + } + + Pass + { + Name "VisibilityDXR" + Tags{ "LightMode" = "VisibilityDXR" } + + HLSLPROGRAM + + #pragma only_renderers d3d11 xboxseries ps5 + #pragma raytracing surface_shader + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" + + #define SHADERPASS SHADERPASS_RAYTRACING_VISIBILITY + #pragma multi_compile _ TRANSPARENT_COLOR_SHADOW + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLitTemplateRayTracing.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLit_Basemap.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassRaytracingVisibility.hlsl" + ENDHLSL + } + + Pass + { + Name "DebugDXR" + Tags{ "LightMode" = "DebugDXR" } + + HLSLPROGRAM + #pragma only_renderers d3d11 xboxseries ps5 + #pragma raytracing surface_shader + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" + #define SHADERPASS SHADERPASS_RAYTRACING_DEBUG + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingMacros.hlsl" + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/ShaderVariablesRaytracing.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingIntersection.hlsl" + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RayTracingCommon.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassRaytracingDebug.hlsl" + + ENDHLSL + } + + Pass + { + Name "PathTracingDXR" + Tags{ "LightMode" = "PathTracingDXR" } + + HLSLPROGRAM + #pragma only_renderers d3d11 xboxseries ps5 + #pragma raytracing surface_shader + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" + #define SHADERPASS SHADERPASS_PATH_TRACING + + #pragma multi_compile _ DEBUG_DISPLAY + #pragma multi_compile _ SENSORSDK_OVERRIDE_REFLECTANCE + + #ifdef SENSORSDK_OVERRIDE_REFLECTANCE + #define SENSORSDK_ENABLE_LIDAR + #endif + + // This is just because it needs to be defined, shadow maps are not used. + #define SHADOW_LOW + + // For all single-sided, refractive materials, we want to force a thin refraction model. + #if !defined(_DOUBLESIDED_ON) && (defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE)) + #undef _REFRACTION_PLANE + #undef _REFRACTION_SPHERE + #define _REFRACTION_THIN + #endif + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLitTemplateRayTracing.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLit_Basemap.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassPathTracing.hlsl" + ENDHLSL + } + } } diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/IPostProcessComponent.cs b/Packages/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/IPostProcessComponent.cs index f8cf01376d0..85a7932797c 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/IPostProcessComponent.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/IPostProcessComponent.cs @@ -9,6 +9,13 @@ public interface IPostProcessComponent /// Tells if the post process needs to be rendered or not. /// /// true if the effect should be rendered, false otherwise. - bool IsActive(); + bool IsActive() => true; + + /// + /// Tells if the post process needs to be rendered or not. + /// + /// The current camera that renders your post processing effect. + /// true if the effect should be rendered, false otherwise. + bool IsActive(HDCamera hdCamera) => IsActive(); } } diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DebugHDRxyMapping.compute b/Packages/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DebugHDRxyMapping.compute index f821f53323e..494226483d1 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DebugHDRxyMapping.compute +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DebugHDRxyMapping.compute @@ -4,6 +4,8 @@ #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ACES.hlsl" #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/HDROutput.hlsl" +#pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch + #pragma kernel KCIExyGen #define GROUP_SIZE_X 8 #define GROUP_SIZE_Y 8 diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.Debug.cs b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.Debug.cs index 1c3d0396dd7..6f450e9b0a2 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.Debug.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.Debug.cs @@ -8,7 +8,7 @@ namespace UnityEngine.Rendering.HighDefinition public partial class HDRenderPipeline { bool m_FullScreenDebugPushed; - DebugOverlay m_DebugOverlay = new DebugOverlay(); + Rendering.DebugOverlay m_DebugOverlay = new Rendering.DebugOverlay(); TextureHandle m_DebugFullScreenTexture; ComputeBufferHandle m_DebugFullScreenComputeBuffer; ShaderVariablesDebugDisplay m_ShaderVariablesDebugDisplayCB = new ShaderVariablesDebugDisplay(); @@ -662,7 +662,7 @@ TextureHandle ResolveColorPickerDebug(RenderGraph renderGraph, TextureHandle inp class DebugOverlayPassData { - public DebugOverlay debugOverlay; + public Rendering.DebugOverlay debugOverlay; public TextureHandle colorBuffer; public TextureHandle depthBuffer; } @@ -1008,6 +1008,8 @@ void RenderDebugOverlays(RenderGraph renderGraph, RenderShadowsDebugOverlay(renderGraph, colorBuffer, depthBuffer, shadowResult); RenderDecalOverlay(renderGraph, colorBuffer, depthBuffer, hdCamera); RenderMonitorsOverlay(renderGraph, colorBuffer, hdCamera); + + ProbeReferenceVolume.instance.RenderFragmentationOverlay(renderGraph, colorBuffer, depthBuffer, m_DebugOverlay); } void RenderLightVolumes(RenderGraph renderGraph, TextureHandle destination, TextureHandle depthBuffer, CullingResults cullResults, HDCamera hdCamera) diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.PostProcess.cs b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.PostProcess.cs index f4e672e2a3a..004dc1eb99f 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.PostProcess.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.PostProcess.cs @@ -1413,7 +1413,7 @@ bool DoCustomPostProcess(RenderGraph renderGraph, HDCamera hdCamera, ref Texture { customPP.SetupIfNeeded(); - if (customPP is IPostProcessComponent pp && pp.IsActive()) + if (customPP is IPostProcessComponent pp && pp.IsActive(hdCamera)) { if (hdCamera.camera.cameraType != CameraType.SceneView || customPP.visibleInSceneView) { diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.SubsurfaceScattering.cs b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.SubsurfaceScattering.cs index cd8b755b5a1..7c72f027c06 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.SubsurfaceScattering.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.SubsurfaceScattering.cs @@ -7,14 +7,13 @@ public partial class HDRenderPipeline { // Disney SSS Model ComputeShader m_SubsurfaceScatteringCS; + ComputeShader m_SubsurfaceScatteringDownsampleCS; int m_SubsurfaceScatteringKernel; int m_SubsurfaceScatteringKernelMSAA; + int m_SubsurfaceScatteringDownsampleKernel; Material m_CombineLightingPass; // End Disney SSS Model - // This is use to be able to read stencil value in compute shader - Material m_SSSCopyStencilForSplitLighting; - // List of every diffusion profile data we need Vector4[] m_SSSShapeParamsAndMaxScatterDists; Vector4[] m_SSSTransmissionTintsAndFresnel0; @@ -36,14 +35,13 @@ void InitializeSubsurfaceScattering() string kernelName = "SubsurfaceScattering"; m_SubsurfaceScatteringCS = defaultResources.shaders.subsurfaceScatteringCS; m_SubsurfaceScatteringKernel = m_SubsurfaceScatteringCS.FindKernel(kernelName); + + m_SubsurfaceScatteringDownsampleCS = defaultResources.shaders.subsurfaceScatteringDownsampleCS; + m_SubsurfaceScatteringDownsampleKernel = m_SubsurfaceScatteringDownsampleCS.FindKernel("Downsample"); m_CombineLightingPass = CoreUtils.CreateEngineMaterial(defaultResources.shaders.combineLightingPS); m_CombineLightingPass.SetInt(HDShaderIDs._StencilRef, (int)StencilUsage.SubsurfaceScattering); m_CombineLightingPass.SetInt(HDShaderIDs._StencilMask, (int)StencilUsage.SubsurfaceScattering); - m_SSSCopyStencilForSplitLighting = CoreUtils.CreateEngineMaterial(defaultResources.shaders.copyStencilBufferPS); - m_SSSCopyStencilForSplitLighting.SetInt(HDShaderIDs._StencilRef, (int)StencilUsage.SubsurfaceScattering); - m_SSSCopyStencilForSplitLighting.SetInt(HDShaderIDs._StencilMask, (int)StencilUsage.SubsurfaceScattering); - m_SSSDefaultDiffusionProfile = defaultResources.assets.defaultDiffusionProfile; // fill the list with the max number of diffusion profile so we dont have @@ -67,7 +65,6 @@ void CleanupSubsurfaceScattering() CleanupSubsurfaceScatteringRT(); CoreUtils.Destroy(m_CombineLightingPass); - CoreUtils.Destroy(m_SSSCopyStencilForSplitLighting); } void UpdateCurrentDiffusionProfileSettings(HDCamera hdCamera) @@ -185,10 +182,12 @@ TextureHandle CreateSSSBuffer(RenderGraph renderGraph, HDCamera hdCamera, MSAASa class SubsurfaceScaterringPassData { public ComputeShader subsurfaceScatteringCS; + public ComputeShader subsurfaceScatteringDownsampleCS; public int subsurfaceScatteringCSKernel; + public int subsurfaceScatteringDownsampleCSKernel; public int sampleBudget; + public int downsampleSteps; public bool needTemporaryBuffer; - public Material copyStencilForSplitLighting; public Material combineLighting; public int numTilesX; public int numTilesY; @@ -199,6 +198,7 @@ class SubsurfaceScaterringPassData public TextureHandle depthStencilBuffer; public TextureHandle depthTexture; public TextureHandle cameraFilteringBuffer; + public TextureHandle downsampleBuffer; public TextureHandle sssBuffer; public ComputeBufferHandle coarseStencilBuffer; } @@ -216,13 +216,15 @@ TextureHandle RenderSubsurfaceScatteringScreenSpace(RenderGraph renderGraph, HDC passData.subsurfaceScatteringCS = m_SubsurfaceScatteringCS; passData.subsurfaceScatteringCSKernel = m_SubsurfaceScatteringKernel; + passData.subsurfaceScatteringDownsampleCS = m_SubsurfaceScatteringDownsampleCS; + passData.subsurfaceScatteringDownsampleCSKernel = m_SubsurfaceScatteringDownsampleKernel; passData.needTemporaryBuffer = NeedTemporarySubsurfaceBuffer() || hdCamera.msaaEnabled; - passData.copyStencilForSplitLighting = m_SSSCopyStencilForSplitLighting; passData.combineLighting = m_CombineLightingPass; passData.numTilesX = ((int)hdCamera.screenSize.x + 15) / 16; passData.numTilesY = ((int)hdCamera.screenSize.y + 15) / 16; passData.numTilesZ = hdCamera.viewCount; passData.sampleBudget = hdCamera.frameSettings.sssResolvedSampleBudget; + passData.downsampleSteps = hdCamera.frameSettings.sssResolvedDownsampleSteps; passData.colorBuffer = builder.WriteTexture(colorBuffer); passData.diffuseBuffer = builder.ReadTexture(lightingBuffers.diffuseLightingBuffer); @@ -230,6 +232,16 @@ TextureHandle RenderSubsurfaceScatteringScreenSpace(RenderGraph renderGraph, HDC passData.depthTexture = builder.ReadTexture(depthTexture); passData.sssBuffer = builder.ReadTexture(lightingBuffers.sssBuffer); passData.coarseStencilBuffer = builder.ReadComputeBuffer(prepassOutput.coarseStencilBuffer); + + if (passData.downsampleSteps > 0) + { + float scale = 1.0f / (1u << passData.downsampleSteps); + passData.downsampleBuffer = builder.CreateTransientTexture( + new TextureDesc(Vector2.one * scale, true, true) + { colorFormat = GraphicsFormat.B10G11R11_UFloatPack32, enableRandomWrite = true, clearBuffer = true, clearColor = Color.clear, name = "SSSDownsampled" }); + } + + if (passData.needTemporaryBuffer) { passData.cameraFilteringBuffer = builder.CreateTransientTexture( @@ -247,13 +259,29 @@ TextureHandle RenderSubsurfaceScatteringScreenSpace(RenderGraph renderGraph, HDC builder.SetRenderFunc( (SubsurfaceScaterringPassData data, RenderGraphContext ctx) => { + CoreUtils.SetKeyword(ctx.cmd, "USE_DOWNSAMPLE", data.downsampleSteps > 0); + + if (data.downsampleSteps > 0) + { + // The downsample workgroup size is half of the subsurface scattering main pass + int shift = data.downsampleSteps - 1; + + ctx.cmd.SetComputeIntParam(data.subsurfaceScatteringDownsampleCS, HDShaderIDs._SssDownsampleSteps, data.downsampleSteps); + ctx.cmd.SetComputeTextureParam(data.subsurfaceScatteringDownsampleCS, data.subsurfaceScatteringDownsampleCSKernel, HDShaderIDs._SourceTexture, data.diffuseBuffer); + ctx.cmd.SetComputeTextureParam(data.subsurfaceScatteringDownsampleCS, data.subsurfaceScatteringDownsampleCSKernel, HDShaderIDs._OutputTexture, data.downsampleBuffer); + ctx.cmd.DispatchCompute(data.subsurfaceScatteringDownsampleCS, data.subsurfaceScatteringDownsampleCSKernel, data.numTilesX >> shift, data.numTilesY >> shift, data.numTilesZ); + } + // Combines specular lighting and diffuse lighting with subsurface scattering. // In the case our frame is MSAA, for the moment given the fact that we do not have read/write access to the stencil buffer of the MSAA target; we need to keep this pass MSAA // However, the compute can't output and MSAA target so we blend the non-MSAA target into the MSAA one. ctx.cmd.SetComputeIntParam(data.subsurfaceScatteringCS, HDShaderIDs._SssSampleBudget, data.sampleBudget); + ctx.cmd.SetComputeIntParam(data.subsurfaceScatteringCS, HDShaderIDs._SssDownsampleSteps, data.downsampleSteps); ctx.cmd.SetComputeTextureParam(data.subsurfaceScatteringCS, data.subsurfaceScatteringCSKernel, HDShaderIDs._DepthTexture, data.depthTexture); ctx.cmd.SetComputeTextureParam(data.subsurfaceScatteringCS, data.subsurfaceScatteringCSKernel, HDShaderIDs._IrradianceSource, data.diffuseBuffer); + if (data.downsampleSteps > 0) + ctx.cmd.SetComputeTextureParam(data.subsurfaceScatteringCS, data.subsurfaceScatteringCSKernel, HDShaderIDs._IrradianceSourceDownsampled, data.downsampleBuffer); ctx.cmd.SetComputeTextureParam(data.subsurfaceScatteringCS, data.subsurfaceScatteringCSKernel, HDShaderIDs._SSSBufferTexture, data.sssBuffer); ctx.cmd.SetComputeBufferParam(data.subsurfaceScatteringCS, data.subsurfaceScatteringCSKernel, HDShaderIDs._CoarseStencilBuffer, data.coarseStencilBuffer); diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs index f5d108785d6..1d4dbc72eca 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs @@ -461,6 +461,7 @@ public HDRenderPipeline(HDRenderPipelineAsset asset) blendingMemoryBudget = m_Asset.currentPlatformRenderPipelineSettings.probeVolumeBlendingMemoryBudget, probeDebugMesh = defaultResources.assets.probeDebugSphere, probeDebugShader = defaultResources.shaders.probeVolumeDebugShader, + fragmentationDebugShader = defaultResources.shaders.probeVolumeFragmentationDebugShader, offsetDebugMesh = defaultResources.assets.pyramidMesh, offsetDebugShader = defaultResources.shaders.probeVolumeOffsetDebugShader, scenarioBlendingShader = defaultResources.shaders.probeVolumeBlendStatesCS, @@ -2342,6 +2343,7 @@ out ScriptableCullingParameters cullingParams // With the Frame Settings now properly set up, we can resolve the sample budget. currentFrameSettings.sssResolvedSampleBudget = currentFrameSettings.GetResolvedSssSampleBudget(m_Asset); + currentFrameSettings.sssResolvedDownsampleSteps = currentFrameSettings.GetResolvedSssDownsampleSteps(m_Asset); // Specific pass to simply display the content of the camera buffer if users have fill it themselves (like video player) if (additionalCameraData.fullscreenPassthrough) diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipelineAsset.Migration.cs b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipelineAsset.Migration.cs index a01847af209..87b3f614688 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipelineAsset.Migration.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipelineAsset.Migration.cs @@ -236,7 +236,7 @@ enum Version }; data.m_RenderPipelineSettings.cubeReflectionResolution = new RenderPipelineSettings.ReflectionProbeResolutionScalableSetting(cubeResolutions, ScalableSettingSchemaId.With3Levels); - int cubeReflectionAtlasArea = lightLoopSettings.reflectionProbeCacheSize * (int)lightLoopSettings.reflectionCubemapSize * (int)lightLoopSettings.reflectionCubemapSize; + int cubeReflectionAtlasArea = lightLoopSettings.reflectionProbeCacheSize * (int)lightLoopSettings.reflectionCubemapSize * (int)lightLoopSettings.reflectionCubemapSize * 6; int planarReflectionAtlasArea = (int)lightLoopSettings.planarReflectionAtlasSize * (int)lightLoopSettings.planarReflectionAtlasSize; int reflectionProbeTexCacheSize = Mathf.NextPowerOfTwo((int)Mathf.Sqrt(cubeReflectionAtlasArea + planarReflectionAtlasArea)); lightLoopSettings.reflectionProbeTexCacheSize = (ReflectionProbeTextureCacheResolution)Mathf.Clamp(reflectionProbeTexCacheSize, (int)ReflectionProbeTextureCacheResolution.Resolution512x512, (int)ReflectionProbeTextureCacheResolution.Resolution16384x16384); diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipelineGlobalSettings.cs b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipelineGlobalSettings.cs index e987a4137e1..65ed3be408b 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipelineGlobalSettings.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipelineGlobalSettings.cs @@ -702,7 +702,7 @@ internal bool AddDiffusionProfile(DiffusionProfileSettings profile) profiles[index] = profile; overrides.diffusionProfiles.value = profiles; - EditorUtility.SetDirty(this); + EditorUtility.SetDirty(overrides); return true; } diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipelineRuntimeResources.cs b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipelineRuntimeResources.cs index f400dc0c1a3..7031bb4d962 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipelineRuntimeResources.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipelineRuntimeResources.cs @@ -47,6 +47,8 @@ public sealed class ShaderResources // APV [Reload("Runtime/Debug/ProbeVolumeDebug.shader")] public Shader probeVolumeDebugShader; + [Reload("Runtime/Debug/ProbeVolumeFragmentationDebug.shader")] + public Shader probeVolumeFragmentationDebugShader; [Reload("Runtime/Debug/ProbeVolumeOffsetDebug.shader")] public Shader probeVolumeOffsetDebugShader; [Reload("Runtime/Lighting/ProbeVolume/ProbeVolumeBlendStates.compute")] @@ -116,6 +118,8 @@ public sealed class ShaderResources [Reload("Runtime/Material/SubsurfaceScattering/SubsurfaceScattering.compute")] public ComputeShader subsurfaceScatteringCS; // Disney SSS + [Reload("Runtime/Material/SubsurfaceScattering/RandomDownsample.compute")] + public ComputeShader subsurfaceScatteringDownsampleCS; [Reload("Runtime/Material/SubsurfaceScattering/CombineLighting.shader")] public Shader combineLightingPS; diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDStringConstants.cs b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDStringConstants.cs index b4c18245949..16ac04a7d6d 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDStringConstants.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDStringConstants.cs @@ -211,6 +211,7 @@ static class HDShaderIDs public static readonly int specularLightingUAV = Shader.PropertyToID("specularLightingUAV"); public static readonly int diffuseLightingUAV = Shader.PropertyToID("diffuseLightingUAV"); public static readonly int _SssSampleBudget = Shader.PropertyToID("_SssSampleBudget"); + public static readonly int _SssDownsampleSteps = Shader.PropertyToID("_SssDownsampleSteps"); public static readonly int _MaterialID = Shader.PropertyToID("_MaterialID"); public static readonly int g_TileListOffset = Shader.PropertyToID("g_TileListOffset"); @@ -310,6 +311,7 @@ static class HDShaderIDs public static readonly int _CameraSssDiffuseLightingBuffer = Shader.PropertyToID("_CameraSssDiffuseLightingTexture"); public static readonly int _CameraFilteringBuffer = Shader.PropertyToID("_CameraFilteringTexture"); public static readonly int _IrradianceSource = Shader.PropertyToID("_IrradianceSource"); + public static readonly int _IrradianceSourceDownsampled = Shader.PropertyToID("_IrradianceSourceDownsampled"); // Planar reflection filtering public static readonly int _ReflectionColorMipChain = Shader.PropertyToID("_ReflectionColorMipChain"); @@ -756,6 +758,7 @@ static class HDShaderIDs public static readonly int _AreaShadowHistoryRW = Shader.PropertyToID("_AreaShadowHistoryRW"); public static readonly int _AnalyticProbBuffer = Shader.PropertyToID("_AnalyticProbBuffer"); public static readonly int _AnalyticHistoryBuffer = Shader.PropertyToID("_AnalyticHistoryBuffer"); + public static readonly int _AnalyticHistoryBufferRW = Shader.PropertyToID("_AnalyticHistoryBufferRW"); public static readonly int _RaytracingLightRadius = Shader.PropertyToID("_RaytracingLightRadius"); public static readonly int _RaytracingSpotAngle = Shader.PropertyToID("_RaytracingSpotAngle"); public static readonly int _RaytracedShadowIntegration = Shader.PropertyToID("_RaytracedShadowIntegration"); diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingSkySamplingData.compute b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingSkySamplingData.compute index 357babdbdbb..66004b6695d 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingSkySamplingData.compute +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingSkySamplingData.compute @@ -2,6 +2,8 @@ #define COMPUTE_PATH_TRACING_SKY_SAMPLING_DATA +#pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ImageBasedLighting.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/HDRaytracingLightCluster.cs b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/HDRaytracingLightCluster.cs index 1c831a951ff..9d1a548e323 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/HDRaytracingLightCluster.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/HDRaytracingLightCluster.cs @@ -444,7 +444,7 @@ void CullLights(CommandBuffer cmd) // Inject all the parameters cmd.SetComputeVectorParam(lightClusterCS, _ClusterCenterPosition, clusterCenter); cmd.SetComputeVectorParam(lightClusterCS, _ClusterDimension, clusterDimension); - cmd.SetComputeFloatParam(lightClusterCS, _LightVolumeCount, HDShadowUtils.Asfloat(totalLightCount)); + cmd.SetComputeIntParam(lightClusterCS, _LightVolumeCount, totalLightCount); cmd.SetComputeBufferParam(lightClusterCS, lightClusterCullKernel, _LightVolumes, m_LightVolumeGPUArray); cmd.SetComputeBufferParam(lightClusterCS, lightClusterCullKernel, _RaytracingLightCullResult, m_LightCullResult); @@ -468,7 +468,7 @@ void BuildLightCluster(HDCamera hdCamera, CommandBuffer cmd) cmd.SetComputeVectorParam(lightClusterCS, _ClusterCellSize, clusterCellSize); cmd.SetComputeBufferParam(lightClusterCS, lightClusterKernel, _LightVolumes, m_LightVolumeGPUArray); - cmd.SetComputeFloatParam(lightClusterCS, _LightVolumeCount, HDShadowUtils.Asfloat(totalLightCount)); + cmd.SetComputeIntParam(lightClusterCS, _LightVolumeCount, totalLightCount); cmd.SetComputeBufferParam(lightClusterCS, lightClusterKernel, _RaytracingLightCullResult, m_LightCullResult); // Dispatch a compute diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/HDTemporalFilter.cs b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/HDTemporalFilter.cs index fbc7b64a55d..60ef91356ab 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/HDTemporalFilter.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/HDTemporalFilter.cs @@ -415,7 +415,7 @@ public TemporalDenoiserArrayOutputData DenoiseBuffer(RenderGraph renderGraph, HD // History buffers passData.outputHistoryBuffer = builder.ReadWriteTexture(renderGraph.ImportTexture(historyBuffer)); - passData.inputHistoryBuffer = ( historyValidity > 0 ) ? passData.outputHistoryBuffer : renderGraph.defaultResources.blackTextureArrayXR; + passData.inputHistoryBuffer = passData.outputHistoryBuffer; passData.validationHistoryBuffer = builder.ReadWriteTexture(renderGraph.ImportTexture(validationHistoryBuffer)); passData.distanceHistorySignal = distanceBased ? builder.ReadWriteTexture(renderGraph.ImportTexture(distanceHistorySignal)) : renderGraph.defaultResources.blackTextureXR; diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RTASDebug.raytrace b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RTASDebug.raytrace index 7cb2553b089..c12d4598b22 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RTASDebug.raytrace +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RTASDebug.raytrace @@ -53,7 +53,9 @@ void RTASDebug() // Create and init the RayIntersection structure for this RayIntersectionDebug rayIntersection; - rayIntersection.t = 0.0f; + rayIntersection.t = FLT_INF; + rayIntersection.instanceIndex = 0; + rayIntersection.primitiveIndex = 0; // Evaluate the ray intersection TraceRay(_RaytracingAccelerationStructure, RAY_FLAG_CULL_BACK_FACING_TRIANGLES, _LayerMask, 0, 1, 0, rayDescriptor, rayIntersection); diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Shadows/RaytracingMIS.hlsl b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Shadows/RaytracingMIS.hlsl index 7562c1bef29..8d7e4e973f6 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Shadows/RaytracingMIS.hlsl +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Shadows/RaytracingMIS.hlsl @@ -1,5 +1,5 @@ // Matrix used to move the samples from world space to local area light space in order to get the UV mapping values -float4x4 _RaytracingLightWorldToLocal; +float4x4 _RaytracingAreaWorldToLocal; struct MISSamplingInput { @@ -160,7 +160,7 @@ bool GenerateMISSample(inout MISSamplingInput misInput, SphQuad squad, float3 vi // The next question is: This the sample point inside the triangle? To do that for the moment we move it to the local space of the light and see if its distance to the center of the light // is coherent with the dimensions of the light - float4 lsPoint = mul(_RaytracingLightWorldToLocal, float4(misSamplingOutput.pos, 1.0)) * 2.0; + float4 lsPoint = mul(_RaytracingAreaWorldToLocal, float4(misSamplingOutput.pos, 1.0)) * 2.0; validity = abs(lsPoint.x) < misInput.rectDimension.x && abs(lsPoint.y) < misInput.rectDimension.y; if (validity) { @@ -182,7 +182,7 @@ bool GenerateMISSample(inout MISSamplingInput misInput, SphQuad squad, float3 vi // Compute the Light PDF misSamplingOutput.lightPDF = 1.0f / squad.S; // Compute the uv on the light - float4 lsPoint = mul(_RaytracingLightWorldToLocal, float4(misSamplingOutput.pos, 1.0)) * 2.0; + float4 lsPoint = mul(_RaytracingAreaWorldToLocal, float4(misSamplingOutput.pos, 1.0)) * 2.0; misSamplingOutput.sampleUV = float2((lsPoint.x + misInput.rectDimension.x) / (2.0 * misInput.rectDimension.x), (lsPoint.y + misInput.rectDimension.y) / (2.0 * misInput.rectDimension.y)); } return validity; diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Shadows/RaytracingShadow.compute b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Shadows/RaytracingShadow.compute index 77725c1be14..ef9115418d9 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Shadows/RaytracingShadow.compute +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Shadows/RaytracingShadow.compute @@ -21,8 +21,6 @@ #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" #define SHADERPASS SHADERPASS_RAYTRACING -#pragma only_renderers d3d11 xboxseries ps5 - // HDRP generic includes #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl" diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Shadows/RaytracingShadow.raytrace b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Shadows/RaytracingShadow.raytrace index 1c39f56126d..89fabcf1461 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Shadows/RaytracingShadow.raytrace +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Shadows/RaytracingShadow.raytrace @@ -48,9 +48,9 @@ uint _RaytracingTargetAreaLight; TEXTURE2D_X(_DepthTexture); // Output structure of the shadows raytrace shader -RW_TEXTURE2D_X(float2, _RaytracedAreaShadowSample); +TEXTURE2D_X(_RaytracedAreaShadowSample); +TEXTURE2D_X(_AnalyticProbBuffer); RW_TEXTURE2D_X(float2, _RaytracedAreaShadowIntegration); -RW_TEXTURE2D_X(float2, _AnalyticProbBuffer); [shader("miss")] void MissShaderShadows(inout RayIntersectionVisibility rayIntersection : SV_RayPayload) @@ -64,218 +64,6 @@ void MissShaderShadowsColor(inout RayIntersectionVisibility rayIntersection : SV // Does nothing intentionally } -// This code below is the "high quality shadow" but it is not used currently. We use the compute version which is more efficient -// and which do a good enough approximation. -[shader("raygeneration")] -void RayGenAreaShadows() -{ - // Grab the dimensions of the current raytrace shader - uint3 LaunchIndex = DispatchRaysIndex(); - uint3 LaunchDim = DispatchRaysDimensions(); - - UNITY_XR_ASSIGN_VIEW_INDEX(LaunchIndex.z); - - // Pixel coordinate of the current pixel - uint2 currentPixelCoord = uint2(LaunchIndex.x, LaunchIndex.y); - - // Initialize the output textures - _RaytracedAreaShadowIntegration[COORD_TEXTURE2D_X(currentPixelCoord)] = float2(0.0, 0.0); - _AnalyticProbBuffer[COORD_TEXTURE2D_X(currentPixelCoord)] = float2(-1.0, +1.0); - - // Read the depth value - float depthValue = LOAD_TEXTURE2D_X(_DepthTexture, currentPixelCoord).x; - ApplyRayTracingDepthOffset(depthValue); - - if (depthValue == UNITY_RAW_FAR_CLIP_VALUE) - return; - - // Compute the position input structure - PositionInputs posInput = GetPositionInput(currentPixelCoord, _ScreenSize.zw, depthValue, UNITY_MATRIX_I_VP, GetWorldToViewMatrix(), 0); - - // Decode the world space normal - NormalData normalData; - DecodeFromNormalBuffer(currentPixelCoord, normalData); - - // Convert this to a world space position - const float3 positionWS = posInput.positionWS; - - // Compute the view vector on the surface - float3 viewWS = GetWorldSpaceNormalizeViewDir(positionWS); - - // Fetch the data of the area light - LightData lightData = _LightDatas[_RaytracingTargetAreaLight]; - - // Structure that holds all the input data for the MIS - MISSamplingInput misInput; - ZERO_INITIALIZE(MISSamplingInput, misInput); - misInput.roughness = PerceptualRoughnessToRoughness(normalData.perceptualRoughness); - misInput.viewWS = viewWS; - misInput.positionWS = positionWS; - misInput.rectDimension = lightData.size.xy; - misInput.rectWSPos = lightData.positionRWS; - - // Setup and check the spherical rectangle - SphQuad squad; - if (!InitSphericalQuad(lightData, positionWS, normalData.normalWS, squad)) - { - return; - } - - // Compute the local frame that matches the normal - misInput.localToWorld = GetLocalFrame(normalData.normalWS); - - // Let's now decode the BSDF data from the gbuffer - BSDFData bsdfData; - ZERO_INITIALIZE(BSDFData, bsdfData); - BuiltinData builtinData; - ZERO_INITIALIZE(BuiltinData, builtinData); - uint featureFlags = MATERIALFEATUREFLAGS_LIT_STANDARD; - DecodeFromGBuffer(posInput.positionSS, featureFlags, bsdfData, builtinData); - - // Beyond a certain value of smoothness, we clamp due to the invalidity of the ratio BRDF / MIS. - // TODO: investigate this and find a way to by pass it - bsdfData.perceptualRoughness = ClampPerceptualRoughnessForRaytracing(bsdfData.perceptualRoughness); - bsdfData.roughnessT = ClampRoughnessForRaytracing(bsdfData.roughnessT); - bsdfData.roughnessB = ClampRoughnessForRaytracing(bsdfData.roughnessB); - - // Compute the prelight data - PreLightData preLightData = GetPreLightData(viewWS, posInput, bsdfData); - - // Compute the direct lighting of the light (used for MIS) - LightLoopContext context; - // Given that the approximation used for LTC is completely different from what we would get from a real integration, we only rely on the not textured intensity. - // To acheive that, we set cookie index to -1 so that the evaluatebsdf_rect function to not use any cookie. We also keep track of that cookie value to restore it after the evaluation. - DirectLighting lighting = EvaluateBSDF_Rect(context, viewWS, posInput, preLightData, lightData, bsdfData, builtinData); - lighting.diffuse = lighting.diffuse * bsdfData.diffuseColor; - - // Compute the non-occluded analytic luminance value - float U = Luminance(lighting.diffuse + lighting.specular); - - // NOTE: Due to a VGPR optimisation in we need to restore the previous value (position, dimmer, and other thing are overriden) - lightData = _LightDatas[_RaytracingTargetAreaLight]; - - // Here we need to evaluate the diffuseProbablity and the unshadowed lighting - if(!EvaluateMISProbabilties(lighting, bsdfData.perceptualRoughness, misInput.brdfProb)) - { - // We want this to be flagged as a proper shadow, and not a 0/0 case - _RaytracedAreaShadowIntegration[COORD_TEXTURE2D_X(currentPixelCoord)] = float2(0.0, 0.0); - _AnalyticProbBuffer[COORD_TEXTURE2D_X(currentPixelCoord)] = float2(-1.0, -1.0); - return; - } - - // Initialize Sn and Un - float3 Sn = 0.0; - float3 Un = 0.0; - - // Structure that holds all the output data from the MIS - MISSamplingOuput misOutput; - ZERO_INITIALIZE(MISSamplingOuput, misOutput); - - bool validity = false; - for (int sampleIdx = 0; sampleIdx < _RaytracingNumSamples; ++sampleIdx) - { - // Compute the current sample index - int globalSampleIndex = _RaytracingFrameIndex * _RaytracingNumSamples + sampleIdx; - - // Generate the new sample (follwing values of the sequence) - misInput.noiseValue.x = GetBNDSequenceSample(currentPixelCoord, globalSampleIndex, 0); - misInput.noiseValue.y = GetBNDSequenceSample(currentPixelCoord, globalSampleIndex, 1); - - // Pick the sampling technique - EvaluateMISTechnique(misInput); - - // Generate the right MIS Sample - validity = GenerateMISSample(misInput, squad, viewWS, misOutput); - - // If we could not sample , or the sample is not in the hemisphere or the sample is on the backface of the light - if (!validity || dot(misOutput.dir, normalData.normalWS) <= 0.0 || dot(misOutput.dir, lightData.forward) >= 0.0) - { - continue; - } - - // Make sure it is taken into account in the ray counters - if (_RayCountEnabled > 0) - { - uint3 counterIdx = uint3(currentPixelCoord, INDEX_TEXTURE2D_ARRAY_X(RAYCOUNTVALUES_SHADOW_AREA_LIGHT)); - _RayCountTexture[counterIdx] = _RayCountTexture[counterIdx] + 1; - } - - // Let's shift the origin and destination positions by a bias - #ifdef LIGHT_TO_SURFACE - // In order to match the behavior of the raster pipeline, shadow rays are cast from the light source and not the point (to mimic backface culling in shadowmaps) - float3 rayOrigin = misOutput.pos + lightData.forward * _RaytracingRayBias; - float3 rayDestination = positionWS + normalData.normalWS * _RaytracingRayBias; - float3 rayDirection = normalize(rayDestination-rayOrigin); - uint rayFlag = RAY_FLAG_CULL_BACK_FACING_TRIANGLES; - #else - float3 rayOrigin = positionWS + normalData.normalWS * _RaytracingRayBias; - float3 rayDestination = misOutput.pos + lightData.forward * _RaytracingRayBias; - float3 rayDirection = normalize(rayDestination-rayOrigin); - uint rayFlag = RAY_FLAG_CULL_FRONT_FACING_TRIANGLES; - #endif - - // Create the ray descriptor for this pixel - RayDesc rayDescriptor; - rayDescriptor.Origin = rayOrigin; - rayDescriptor.Direction = rayDirection; - rayDescriptor.TMin = 0.0; - rayDescriptor.TMax = length(rayDestination - rayOrigin); - - // Adjust world-space position to match the RAS setup with XR single-pass and camera relative - ApplyCameraRelativeXR(rayDescriptor.Origin); - - // Create and init the RayIntersectionVisibility structure for this - RayIntersectionVisibility rayIntersection; - rayIntersection.color = float3(0.0, 0.0, 0.0); - - // Evaluate the ray visibility term and PDF - TraceRay(_RaytracingAccelerationStructure, rayFlag | RAY_FLAG_SKIP_CLOSEST_HIT_SHADER | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH, RAYTRACINGRENDERERFLAG_CAST_SHADOW, 0, 1, 0, rayDescriptor, rayIntersection); - - // Evaluate the lighting - CBSDF cbsdf = EvaluateBSDF(viewWS, misOutput.dir, preLightData, bsdfData); - float3 diffuseLighting = cbsdf.diffR; - float3 specularLighting = cbsdf.specR; - - // Combine the light color with the light cookie color (if any) - float3 lightColor = lightData.color; - if (lightData.cookieMode != COOKIEMODE_NONE) - { - float cookieWidth = lightData.cookieScaleOffset.x * _CookieAtlasSize.x; - float cookieSizePOT = round(LOG2_E * log(cookieWidth)); - lightColor *= SampleCookie2D(misOutput.sampleUV, lightData.cookieScaleOffset, bsdfData.perceptualRoughness * cookieSizePOT); - } - - diffuseLighting *= bsdfData.diffuseColor * lightData.diffuseDimmer * lightColor; - specularLighting *= lightData.specularDimmer * lightColor; - - // Compute the MIS weight - float misPDF = lerp(misOutput.lightPDF, misOutput.brdfPDF, misInput.brdfProb); - float NdotL = saturate(dot(normalData.normalWS, misOutput.dir)); - float3 radiance = misPDF > 0.0 ? (diffuseLighting + specularLighting) * NdotL / misPDF : 0.0; - - // Accumulate - Sn += radiance * rayIntersection.color; - Un += radiance; - } - - float SnL = Luminance(Sn) / _RaytracingNumSamples; - float UnL = Luminance(Un) / _RaytracingNumSamples; - - // To avoid huge values on low PDFs (leading to potential precision issues), - // we clip them proportionally to the unoccluded analytic value - const float unoccludedThreshold = 10.0 * U; - if (UnL > unoccludedThreshold) - { - SnL *= unoccludedThreshold / UnL; - UnL = unoccludedThreshold; - } - - // Pass on the values to the output buffer (Sn, Un) and U - _RaytracedAreaShadowIntegration[COORD_TEXTURE2D_X(currentPixelCoord)] = float2(SnL, UnL); - _AnalyticProbBuffer[COORD_TEXTURE2D_X(currentPixelCoord)] = float2(U, misInput.brdfProb); -} - - // Texture that holds the raytracing data TEXTURE2D_X(_RaytracingDirectionBuffer); TEXTURE2D_X(_RayTracingLengthBuffer); @@ -294,14 +82,14 @@ void RayGenAreaShadowSingle() // Read the previous value of the buffer float2 previousValue = _RaytracedAreaShadowIntegration[COORD_TEXTURE2D_X(currentPixelCoord)]; - float2 currentSample = _RaytracedAreaShadowSample[COORD_TEXTURE2D_X(currentPixelCoord)]; + float2 currentSample = LOAD_TEXTURE2D_X(_RaytracedAreaShadowSample, currentPixelCoord); // Read the depth value float depthValue = LOAD_TEXTURE2D_X(_DepthTexture, currentPixelCoord).x; ApplyRayTracingDepthOffset(depthValue); // If this is the background, or UnL is null or this pixel has been flagged as invalid, no - if (depthValue == UNITY_RAW_FAR_CLIP_VALUE || currentSample.y == 0.0 || _AnalyticProbBuffer[COORD_TEXTURE2D_X(currentPixelCoord)].y < 0.0) + if (depthValue == UNITY_RAW_FAR_CLIP_VALUE || currentSample.y == 0.0 || LOAD_TEXTURE2D_X(_AnalyticProbBuffer, currentPixelCoord).y < 0.0) { _RaytracedAreaShadowIntegration[COORD_TEXTURE2D_X(currentPixelCoord)] = float2(previousValue.x, previousValue.y); return; diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Shadows/RaytracingShadowFilter.compute b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Shadows/RaytracingShadowFilter.compute index b0418ba66da..3e0d45f7535 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Shadows/RaytracingShadowFilter.compute +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Shadows/RaytracingShadowFilter.compute @@ -21,6 +21,8 @@ #pragma only_renderers d3d11 xboxseries ps5 +// #pragma enable_d3d11_debug_symbols + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/NormalBuffer.hlsl" @@ -37,7 +39,9 @@ TEXTURE2D_X(_DepthTexture); // Analytic buffer for the current frame TEXTURE2D_X(_AnalyticProbBuffer); // Analytic buffer from the previous frame (stored as array) -RW_TEXTURE2D_ARRAY(float4, _AnalyticHistoryBuffer); +TEXTURE2D_ARRAY(_AnalyticHistoryBuffer); +// Analytic buffer from the previous frame (stored as array) +RW_TEXTURE2D_ARRAY(float4, _AnalyticHistoryBufferRW); // Noisy buffer produced this frame TEXTURE2D_X(_DenoiseInputTexture); // Temporal Accumulated buffer from the previous frame @@ -63,10 +67,10 @@ void AreaAnalyticHistoryCopy(uint3 dispatchThreadId : SV_DispatchThreadID, uint2 uint2 centerCoord = groupId * AREA_BILLATERAL_TILE_SIZE + groupThreadId; // Grab the previous value stored in the buffer - float4 previousValue = _AnalyticHistoryBuffer[uint3(centerCoord, INDEX_TEXTURE2D_ARRAY_X(_DenoisingHistorySlice))]; + float4 previousValue = _AnalyticHistoryBufferRW[uint3(centerCoord, INDEX_TEXTURE2D_ARRAY_X(_DenoisingHistorySlice))]; // Only replace where the mask is 1.0 - _AnalyticHistoryBuffer[uint3(centerCoord, INDEX_TEXTURE2D_ARRAY_X(_DenoisingHistorySlice))] = (1.0 - _DenoisingHistoryMask) * previousValue + _DenoisingHistoryMask * LOAD_TEXTURE2D_X(_AnalyticProbBuffer, centerCoord).x; + _AnalyticHistoryBufferRW[uint3(centerCoord, INDEX_TEXTURE2D_ARRAY_X(_DenoisingHistorySlice))] = (1.0 - _DenoisingHistoryMask) * previousValue + _DenoisingHistoryMask * LOAD_TEXTURE2D_X(_AnalyticProbBuffer, centerCoord).x; } [numthreads(AREA_BILLATERAL_TILE_SIZE, AREA_BILLATERAL_TILE_SIZE, 1)] @@ -98,64 +102,68 @@ void AreaShadowApplyTAA(uint3 dispatchThreadId : SV_DispatchThreadID, uint2 grou float depth = LOAD_TEXTURE2D_X(_DepthTexture, centerCoord).r; PositionInputs posInputs = GetPositionInput(centerCoord, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, GetWorldToViewMatrix()); - // Get the cosest pixel - float2 closest = GetClosestFragmentCompute(posInputs.positionSS); - // Read the matching velocity float2 velocity; - DecodeMotionVector(LOAD_TEXTURE2D_X(_CameraMotionVectorsTexture, closest), velocity); - float velocityLength = length(velocity); + DecodeMotionVector(LOAD_TEXTURE2D_X(_CameraMotionVectorsTexture, (float2)centerCoord), velocity); - // UV used to read the pixels to filter - float2 uv = posInputs.positionNDC; - - // Compute the previous pixel coordinate - uint2 historyPixelCoord = centerCoord - velocity * _ScreenSize.xy; - // Ok so here, if we do not match cloesly the previous analytic value, it means either TAA has invalidated the sample or the pixel just appeared + // Read this frame's data for the current pixel + float2 currentSnUn = LOAD_TEXTURE2D_X(_DenoiseInputTexture, centerCoord).xy; float currentAnalyticValue = LOAD_TEXTURE2D_X(_AnalyticProbBuffer, centerCoord).x; - float historyAnalyticValue = dot(_DenoisingHistoryMaskSn, _AnalyticHistoryBuffer[uint3(historyPixelCoord, INDEX_TEXTURE2D_ARRAY_X(_DenoisingHistorySlice))]); - if (abs(historyAnalyticValue - currentAnalyticValue) >= 1e-1 * Max3(1.0f, abs(historyAnalyticValue), abs(currentAnalyticValue)) || historyAnalyticValue < 0.0f || _HistoryValidity == 0.0) - { - // Fetch the current value - float2 color = Fetch4(_DenoiseInputTexture, uv, 0.0, _RTHandleScale.xy).xy; + // Compute the coordinates from the previous frame + float2 historyTapCoord = (float2)((posInputs.positionNDC - velocity) * _ScreenSize.xy); + float2 historyUV = historyTapCoord * _ScreenSize.zw * _RTHandleScaleHistory.zw; + + // Read the analytic value from the previous frame + float historyAnalyticValue = dot(_DenoisingHistoryMaskSn, SAMPLE_TEXTURE2D_ARRAY_LOD(_AnalyticHistoryBuffer, s_linear_clamp_sampler, historyUV, INDEX_TEXTURE2D_ARRAY_X(_DenoisingHistorySlice), 0)); + // Ok so here, if we do not match cloesly the previous analytic value, it means either TAA has invalidated the sample or the pixel just appeared + if (abs(historyAnalyticValue - currentAnalyticValue) >= 1e-1 * Max3(1.0f, abs(historyAnalyticValue), abs(currentAnalyticValue)) + || historyAnalyticValue < 0.0 + || _HistoryValidity == 0.0 + || historyTapCoord.x < 0.0 || historyTapCoord.x >= _ScreenSize.x || historyTapCoord.y < 0.0 || historyTapCoord.y >= _ScreenSize.y + || depth == UNITY_RAW_FAR_CLIP_VALUE) + { // Set it as the output and leave the function - _DenoiseOutputTextureRW[COORD_TEXTURE2D_X(centerCoord)] = float4(color, LOAD_TEXTURE2D_X(_AnalyticProbBuffer, centerCoord).x, 1.0); + _DenoiseOutputTextureRW[COORD_TEXTURE2D_X(centerCoord)] = float4(currentSnUn, currentAnalyticValue, 1.0); return; } - float2 color = Fetch4(_DenoiseInputTexture, uv, 0.0, _RTHandleScale.xy).xy; - float4 historyArray = Fetch4Array(_AreaShadowHistory, INDEX_TEXTURE2D_ARRAY_X(_DenoisingHistorySlice), posInputs.positionNDC - velocity, 0.0, _RTHandleScaleHistory.xy); - float2 history = float2(dot(_DenoisingHistoryMaskSn, historyArray), dot(_DenoisingHistoryMaskUn, historyArray)); + // Read the history values for the current pixel + float4 historyArray = SAMPLE_TEXTURE2D_ARRAY_LOD(_AreaShadowHistory, s_linear_clamp_sampler, historyUV, INDEX_TEXTURE2D_ARRAY_X(_DenoisingHistorySlice), 0); + float2 historySnUn = float2(dot(_DenoisingHistoryMaskSn, historyArray), dot(_DenoisingHistoryMaskUn, historyArray)); + + // UV used to read the pixels to filter + float2 uv = posInputs.positionNDC; + float2 topLeft = Fetch4(_DenoiseInputTexture, uv, -RADIUS, _RTHandleScale.xy).xy; float2 bottomRight = Fetch4(_DenoiseInputTexture, uv, RADIUS, _RTHandleScale.xy).xy; - float2 corners = 4.0 * (topLeft + bottomRight) - 2.0 * color; + float2 corners = 4.0 * (topLeft + bottomRight) - 2.0 * currentSnUn; - color = clamp(color, 0.0, CLAMP_MAX); + currentSnUn = clamp(currentSnUn, 0.0, CLAMP_MAX); - float2 average = FastTonemapPerChannel((corners + color) / 7.0); + float2 average = FastTonemapPerChannel((corners + currentSnUn) / 7.0); topLeft = FastTonemapPerChannel(topLeft); bottomRight = FastTonemapPerChannel(bottomRight); - color = FastTonemapPerChannel(color); + currentSnUn = FastTonemapPerChannel(currentSnUn); - float2 colorLuma = color; + float2 colorLuma = FastTonemapPerChannel(currentSnUn); float2 averageLuma = average; - float2 nudge = lerp(4.0, 0.25, saturate(velocityLength * 100.0)) * abs(averageLuma - colorLuma); + float2 nudge = lerp(4.0, 0.25, saturate(length(velocity) * 100.0)) * abs(averageLuma - colorLuma); float2 minimum = min(bottomRight, topLeft) - nudge; float2 maximum = max(topLeft, bottomRight) + nudge; - history = FastTonemapPerChannel(history); + historySnUn = FastTonemapPerChannel(historySnUn); // Clip history samples - history = clamp(history, minimum, maximum); + historySnUn = clamp(historySnUn, minimum, maximum); // Blend color & history // Feedback weight from unbiased luminance diff (Timothy Lottes) - float2 historyLuma = history; + float2 historyLuma = historySnUn; float2 diff = abs(colorLuma - historyLuma) / Max3(colorLuma, historyLuma, float2(0.2, 0.2)); float2 weight = 1.0 - diff; weight = weight * weight; @@ -163,10 +171,10 @@ void AreaShadowApplyTAA(uint3 dispatchThreadId : SV_DispatchThreadID, uint2 grou const float feedbackMax = 0.91; float2 feedback = (1.0 - weight) * feedbackMin + weight * feedbackMax; - color = FastTonemapPerChannelInvert(lerp(color, history, feedback)); - color = clamp(color, 0.0, CLAMP_MAX); + currentSnUn = FastTonemapPerChannelInvert(lerp(currentSnUn, historySnUn, feedback)); + currentSnUn = clamp(currentSnUn, 0.0, CLAMP_MAX); - _DenoiseOutputTextureRW[COORD_TEXTURE2D_X(centerCoord)] = float4(color, LOAD_TEXTURE2D_X(_AnalyticProbBuffer, centerCoord).x, 1.0); + _DenoiseOutputTextureRW[COORD_TEXTURE2D_X(centerCoord)] = float4(currentSnUn, currentAnalyticValue, 1.0); } /* @@ -472,15 +480,15 @@ void AREA_SHADOW_DENOISE(uint3 dispatchThreadId : SV_DispatchThreadID, uint2 gro #endif } - uint2 tapCoord = centerCoord - effectiveRadius * passIncr; + int2 tapCoord = centerCoord - effectiveRadius * passIncr; for (int r = -effectiveRadius; r <= effectiveRadius; ++r, tapCoord += passIncr) { // We should not tap outside of the screen (given that its a unit, if we go below zero we wrap around) - if ((int)tapCoord.x > _ScreenSize.x || (int)tapCoord.y > _ScreenSize.y) + if (tapCoord.x >= _ScreenSize.x || tapCoord.x < 0 || tapCoord.y >= _ScreenSize.y || tapCoord.y < 0) continue; // Compute the weight (skip computation for the center) - const float w = r ? gaussian(r, sigma) * ComputeBilateralWeight(center, TapBilateralData(tapCoord)) : 1.0; + const float w = r != 0 ? gaussian(abs(r), sigma) * ComputeBilateralWeight(center, TapBilateralData(tapCoord)) : 1.0; SU += LOAD_TEXTURE2D_X(_DenoiseInputTexture, tapCoord).xy * w; wSum += w; diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Shadows/SphericalQuad.hlsl b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Shadows/SphericalQuad.hlsl index f0c73c6d9d2..a323456c505 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Shadows/SphericalQuad.hlsl +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Shadows/SphericalQuad.hlsl @@ -4,6 +4,7 @@ bool IntersectPlane(float3 ray_origin, float3 ray_dir, float3 pos, float3 normal, out float t) { + t = -1.0f; float denom = dot(normal, ray_dir); if (abs(denom) > PLANE_INTERSECTION_EPSILON) { diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/DrawRenderersCustomPass.cs b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/DrawRenderersCustomPass.cs index a1ecbfdc596..8cd766435bd 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/DrawRenderersCustomPass.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/DrawRenderersCustomPass.cs @@ -221,6 +221,8 @@ protected override void Execute(CustomPassContext ctx) var mask = overrideDepthState ? RenderStateMask.Depth : 0; mask |= overrideDepthState && !depthWrite ? RenderStateMask.Stencil : 0; + if (overrideStencil) + mask |= RenderStateMask.Stencil; var stateBlock = new RenderStateBlock(mask) { depthState = new DepthState(depthWrite, depthCompareFunction), diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Settings/FrameSettings.cs b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Settings/FrameSettings.cs index 6346e28fa1f..a9ca2c360a0 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Settings/FrameSettings.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Settings/FrameSettings.cs @@ -312,6 +312,10 @@ public enum FrameSettingsField [FrameSettingsField(1, customOrderInGroup: 49, displayedName: "Custom Sample Budget", positiveDependencies: new[] { SubsurfaceScattering }, type: FrameSettingsFieldAttribute.DisplayType.Others, tooltip: "Sets the custom sample budget of the Subsurface Scattering algorithm.")] SssCustomSampleBudget = 49, + /// Sets the custom number of downsample steps used by the Subsurface Scattering algorithm. + [FrameSettingsField(1, customOrderInGroup: 50, displayedName: "Custom Downsample Level", positiveDependencies: new[] { SubsurfaceScattering }, type: FrameSettingsFieldAttribute.DisplayType.Others, + tooltip: "Sets the custom number of downsample steps done to the source irradance textrure before it is used by the Subsurface Scattering algorithm. Higher value will improve performance, but might lower quality.")] + SssCustomDownsampleSteps = 51, /// When enabled, Cameras using these Frame Settings calculate Volumetric Clouds. [FrameSettingsField(1, autoName: VolumetricClouds, customOrderInGroup: 50, tooltip: "When enabled, Cameras using these Frame Settings calculate Volumetric Clouds.")] VolumetricClouds = 79, @@ -352,9 +356,8 @@ public enum FrameSettingsField /// When enabled, Cameras that use these Frame Settings render Direct Specular lighting. This is a useful Frame Setting to use for baked Reflection Probes to remove view dependent lighting. [FrameSettingsField(1, autoName: DirectSpecularLighting, tooltip: "When enabled, Cameras that use these Frame Settings render Direct Specular lighting. This is a useful Frame Setting to use for baked Reflection Probes to remove view dependent lighting.")] DirectSpecularLighting = 38, - /// When enabled, HDRP uses probe volumes for baked lighting. - [FrameSettingsField(1, customOrderInGroup: 3, autoName: ProbeVolume, tooltip: "Enable to debug and make HDRP process Probe Volumes. Enabling this feature causes HDRP to process Probe Volumes for this Camera/Reflection Probe.")] + [FrameSettingsField(1, customOrderInGroup: 3, displayedName: "Probe Volumes", tooltip: "Enable Probe Volumes for rendering and debug visualisations. Enabling this feature causes HDRP to process Probe Volumes for this Camera/Reflection Probe.")] ProbeVolume = 127, /// When enabled, HDRP uses probe volumes to normalize the data sampled from reflection probes so they better match the lighting at the sampling location. [FrameSettingsField(1, customOrderInGroup: 4, displayedName: "Normalize Reflection Probes", positiveDependencies: new[] { ProbeVolume })] @@ -501,6 +504,7 @@ partial struct FrameSettings sssQualityMode = SssQualityMode.FromQualitySettings, sssQualityLevel = 0, sssCustomSampleBudget = (int)DefaultSssSampleBudgetForQualityLevel.Low, + sssCustomDownsampleSteps = (int)DefaultSssDownsampleSteps.Low, msaaMode = MSAAMode.None, }; internal static FrameSettings NewDefaultRealtimeReflectionProbe() => new FrameSettings() @@ -563,6 +567,7 @@ partial struct FrameSettings sssQualityMode = SssQualityMode.FromQualitySettings, sssQualityLevel = 0, sssCustomSampleBudget = (int)DefaultSssSampleBudgetForQualityLevel.Low, + sssCustomDownsampleSteps = (int)DefaultSssDownsampleSteps.Low, msaaMode = MSAAMode.None, }; internal static FrameSettings NewDefaultCustomOrBakeReflectionProbe() => new FrameSettings() @@ -623,6 +628,7 @@ partial struct FrameSettings sssQualityMode = SssQualityMode.FromQualitySettings, sssQualityLevel = 0, sssCustomSampleBudget = (int)DefaultSssSampleBudgetForQualityLevel.Low, + sssCustomDownsampleSteps = (int)DefaultSssDownsampleSteps.Low, msaaMode = MSAAMode.None, }; @@ -667,6 +673,9 @@ partial struct FrameSettings /// Stores SssCustomSampleBudget on disk. [SerializeField] public int sssCustomSampleBudget; + /// Stores SssCustomDownsampleSteps on disk. + [SerializeField] + public int sssCustomDownsampleSteps; /// Stores MSAA Mode on disk. [SerializeField] @@ -674,6 +683,7 @@ partial struct FrameSettings /// The actual value used by the Subsurface Scattering algorithm. Updated every frame. internal int sssResolvedSampleBudget; + internal int sssResolvedDownsampleSteps; /// /// The material quality level this rendering component uses. @@ -747,6 +757,23 @@ public int GetResolvedSssSampleBudget(HDRenderPipelineAsset hdrp) } } + /// + /// Returns the number downsample steps that will be performed on the source + /// irradiance texture before the main Subsurface algorithm executes. + /// + /// The HDRP Asset to use. + /// The number downsample steps. + public int GetResolvedSssDownsampleSteps(HDRenderPipelineAsset hdrp) + { + var source = hdrp.currentPlatformRenderPipelineSettings.sssDownsampleSteps; + switch (sssQualityMode) + { + case SssQualityMode.FromQualitySettings: return source[sssQualityLevel]; + case SssQualityMode.OverrideQualitySettings: return sssCustomDownsampleSteps; + default: throw new ArgumentOutOfRangeException(nameof(sssCustomDownsampleSteps)); + } + } + /// /// Calculates the Maximum LOD level to use. /// @@ -786,6 +813,8 @@ internal static void Override(ref FrameSettings overriddenFrameSettings, FrameSe overriddenFrameSettings.sssQualityLevel = overridingFrameSettings.sssQualityLevel; if (frameSettingsOverideMask.mask[(uint)FrameSettingsField.SssCustomSampleBudget]) overriddenFrameSettings.sssCustomSampleBudget = overridingFrameSettings.sssCustomSampleBudget; + if (frameSettingsOverideMask.mask[(uint)FrameSettingsField.SssCustomDownsampleSteps]) + overriddenFrameSettings.sssCustomDownsampleSteps = overridingFrameSettings.sssCustomDownsampleSteps; if (frameSettingsOverideMask.mask[(uint)FrameSettingsField.LODBias]) overriddenFrameSettings.lodBias = overridingFrameSettings.lodBias; if (frameSettingsOverideMask.mask[(uint)FrameSettingsField.LODBiasMode]) @@ -964,6 +993,7 @@ internal static void AggregateFrameSettings(ref FrameSettings aggregatedFrameSet && a.sssQualityMode == b.sssQualityMode && a.sssQualityLevel == b.sssQualityLevel && a.sssCustomSampleBudget == b.sssCustomSampleBudget + && a.sssCustomDownsampleSteps == b.sssCustomDownsampleSteps && a.lodBias == b.lodBias && a.lodBiasMode == b.lodBiasMode && a.lodBiasQualityLevel == b.lodBiasQualityLevel @@ -992,6 +1022,7 @@ public override bool Equals(object obj) && sssQualityMode.Equals(((FrameSettings)obj).sssQualityMode) && sssQualityLevel.Equals(((FrameSettings)obj).sssQualityLevel) && sssCustomSampleBudget.Equals(((FrameSettings)obj).sssCustomSampleBudget) + && sssCustomDownsampleSteps.Equals(((FrameSettings)obj).sssCustomDownsampleSteps) && lodBias.Equals(((FrameSettings)obj).lodBias) && lodBiasMode.Equals(((FrameSettings)obj).lodBiasMode) && lodBiasQualityLevel.Equals(((FrameSettings)obj).lodBiasQualityLevel) @@ -1014,6 +1045,7 @@ public override int GetHashCode() hashCode = hashCode * -1521134295 + sssQualityMode.GetHashCode(); hashCode = hashCode * -1521134295 + sssQualityLevel.GetHashCode(); hashCode = hashCode * -1521134295 + sssCustomSampleBudget.GetHashCode(); + hashCode = hashCode * -1521134295 + sssCustomDownsampleSteps.GetHashCode(); hashCode = hashCode * -1521134295 + lodBias.GetHashCode(); hashCode = hashCode * -1521134295 + lodBiasMode.GetHashCode(); hashCode = hashCode * -1521134295 + lodBiasQualityLevel.GetHashCode(); @@ -1101,6 +1133,7 @@ public DebuggerGroup[] Keys new DebuggerEntry("sssQualityMode", m_FrameSettings.sssQualityMode), new DebuggerEntry("sssQualityLevel", m_FrameSettings.sssQualityLevel), new DebuggerEntry("sssCustomSampleBudget", m_FrameSettings.sssCustomSampleBudget), + new DebuggerEntry("sssCustomDownSampleSteps", m_FrameSettings.sssCustomDownsampleSteps), new DebuggerEntry("lodBias", m_FrameSettings.lodBias), new DebuggerEntry("lodBiasMode", m_FrameSettings.lodBiasMode), new DebuggerEntry("lodBiasQualityLevel", m_FrameSettings.lodBiasQualityLevel), diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Settings/RenderPipelineSettings.cs b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Settings/RenderPipelineSettings.cs index d8c45f60a66..8378ce646c3 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Settings/RenderPipelineSettings.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Settings/RenderPipelineSettings.cs @@ -99,6 +99,9 @@ internal static RenderPipelineSettings NewDefault() sssSampleBudget = new IntScalableSetting(new[] { (int)DefaultSssSampleBudgetForQualityLevel.Low, (int)DefaultSssSampleBudgetForQualityLevel.Medium, (int)DefaultSssSampleBudgetForQualityLevel.High }, ScalableSettingSchemaId.With3Levels), + sssDownsampleSteps = new IntScalableSetting(new[] { (int)DefaultSssDownsampleSteps.Low, + (int)DefaultSssDownsampleSteps.Medium, + (int)DefaultSssDownsampleSteps.High }, ScalableSettingSchemaId.With3Levels), supportVolumetrics = true, supportDistortion = true, supportTransparentBackface = true, @@ -215,6 +218,8 @@ public ReflectionProbeResolutionScalableSetting(CubeReflectionResolution[] value public bool supportSubsurfaceScattering; /// Sample budget for the Subsurface Scattering algorithm. public IntScalableSetting sssSampleBudget; + /// Downsample input texture for the Subsurface Scattering algorithm. + public IntScalableSetting sssDownsampleSteps; /// Support volumetric lighting. public bool supportVolumetrics; /// Support volumetric clouds. diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipelineResources/HDRenderPipelineRuntimeResources.asset b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipelineResources/HDRenderPipelineRuntimeResources.asset index 425cb5e1628..a1e44bc4c9b 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipelineResources/HDRenderPipelineRuntimeResources.asset +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipelineResources/HDRenderPipelineRuntimeResources.asset @@ -29,6 +29,7 @@ MonoBehaviour: materialLoading: {fileID: 4800000, guid: 392325671f122f540be9033ca5ae7a56, type: 3} clearDebugBufferCS: {fileID: 7200000, guid: 7fc6041d5cf70004aa33bb1ac64e3c06, type: 3} probeVolumeDebugShader: {fileID: 4800000, guid: 3b21275fd12d65f49babb5286f040f2d, type: 3} + probeVolumeFragmentationDebugShader: {fileID: 4800000, guid: 3a80877c579b9144ebdcc6d923bca303, type: 3} probeVolumeOffsetDebugShader: {fileID: 4800000, guid: db8bd7436dc2c5f4c92655307d198381, type: 3} probeVolumeBlendStatesCS: {fileID: 7200000, guid: a3f7b8c99de28a94684cb1daebeccf5d, type: 3} debugWaveformPS: {fileID: 4800000, guid: 0024f9d09a828734192f3e1cd5931745, type: 3} @@ -60,6 +61,7 @@ MonoBehaviour: deferredTilePS: {fileID: 4800000, guid: dedaf4ea0d134ca4aad1d95a558c46e5, type: 3} screenSpaceShadowPS: {fileID: 4800000, guid: bfa43a48695613b4ea19c58858ae1a61, type: 3} subsurfaceScatteringCS: {fileID: 7200000, guid: b06a7993621def248addd55d0fe931b1, type: 3} + subsurfaceScatteringDownsampleCS: {fileID: 7200000, guid: 4f8aaf0160a259e499fdfac512ca2692, type: 3} combineLightingPS: {fileID: 4800000, guid: 2e37131331fbdca449b1a2bc47a639ca, type: 3} debugLocalVolumetricFogAtlasPS: {fileID: 4800000, guid: 8371b763f09c7304889c22aa97ebdfd2, type: 3} cameraMotionVectorsPS: {fileID: 4800000, guid: 035941b63024d1943af48811c1db20d9, type: 3} diff --git a/Packages/com.unity.visualeffectgraph/Editor/Compiler/VFXCodeGenerator.cs b/Packages/com.unity.visualeffectgraph/Editor/Compiler/VFXCodeGenerator.cs index 9cb184bc8f5..dca7861aa7f 100644 --- a/Packages/com.unity.visualeffectgraph/Editor/Compiler/VFXCodeGenerator.cs +++ b/Packages/com.unity.visualeffectgraph/Editor/Compiler/VFXCodeGenerator.cs @@ -14,6 +14,7 @@ using System.Text.RegularExpressions; using System.Globalization; using UnityEngine.Profiling; +using UnityEngine.Rendering; namespace UnityEditor.VFX { @@ -750,6 +751,12 @@ static private StringBuilder Build(VFXContext context, string templatePath, VFXC var useCubeArray = contextData.uniformMapper.textures.Any(o => o.valueType == VFXValueType.TextureCubeArray); var pragmaRequire = useCubeArray ? new StringBuilder("#pragma require cubearray") : new StringBuilder(); ReplaceMultiline(stringBuilder, "${VFXPragmaRequire}", pragmaRequire); + if (VFXLibrary.currentSRPBinder != null) + { + var allowedRenderers = new StringBuilder("#pragma only_renderers "); + allowedRenderers.Append(String.Join(" ", VFXLibrary.currentSRPBinder.GetSupportedGraphicDevices().Select(d => DeviceTypeToShaderString(d)))); + ReplaceMultiline(stringBuilder, "${VFXPragmaOnlyRenderers}", allowedRenderers); + } foreach (var addionalReplacement in context.additionalReplacements) { @@ -766,6 +773,23 @@ static private StringBuilder Build(VFXContext context, string templatePath, VFXC return stringBuilder; } + static string DeviceTypeToShaderString(GraphicsDeviceType deviceType) => deviceType switch + { + GraphicsDeviceType.Direct3D11 => "d3d11", + GraphicsDeviceType.OpenGLCore => "glcore", + GraphicsDeviceType.OpenGLES2 => "gles", + GraphicsDeviceType.OpenGLES3 => "gles3", + GraphicsDeviceType.Metal => "metal", + GraphicsDeviceType.Vulkan => "vulkan", + GraphicsDeviceType.XboxOne => "xboxone", + GraphicsDeviceType.GameCoreXboxOne => "xboxone", + GraphicsDeviceType.GameCoreXboxSeries => "xboxseries", + GraphicsDeviceType.PlayStation4 => "playstation", + GraphicsDeviceType.Switch => "switch", + GraphicsDeviceType.PlayStation5 => "ps5", + _ => throw new Exception($"Graphics Device Type '{deviceType}' not supported in shader string."), + }; + private static StringBuilder TryBuildFromShaderGraph(VFXShaderGraphParticleOutput context, VFXContextCompiledData contextData) { var stringBuilder = new StringBuilder(); diff --git a/Packages/com.unity.visualeffectgraph/Editor/Core/VFXSRPBinder.cs b/Packages/com.unity.visualeffectgraph/Editor/Core/VFXSRPBinder.cs index d31d0b3c22f..7e92977f85d 100644 --- a/Packages/com.unity.visualeffectgraph/Editor/Core/VFXSRPBinder.cs +++ b/Packages/com.unity.visualeffectgraph/Editor/Core/VFXSRPBinder.cs @@ -99,5 +99,20 @@ public virtual ShaderGraphBinder GetShaderGraphDescriptor(VFXContext context, VF { return new ShaderGraphBinder(); } + + public virtual IEnumerable GetSupportedGraphicDevices() + { + yield return GraphicsDeviceType.Direct3D11; + yield return GraphicsDeviceType.OpenGLCore; + yield return GraphicsDeviceType.OpenGLES3; + yield return GraphicsDeviceType.Metal; + yield return GraphicsDeviceType.Vulkan; + yield return GraphicsDeviceType.XboxOne; + yield return GraphicsDeviceType.GameCoreXboxOne; + yield return GraphicsDeviceType.GameCoreXboxSeries; + yield return GraphicsDeviceType.PlayStation4; + yield return GraphicsDeviceType.PlayStation5; + yield return GraphicsDeviceType.Switch; + } } } diff --git a/Packages/com.unity.visualeffectgraph/Shaders/VFXGlobalSortKeys.template b/Packages/com.unity.visualeffectgraph/Shaders/VFXGlobalSortKeys.template index 88dc5c5499e..2b942acf630 100644 --- a/Packages/com.unity.visualeffectgraph/Shaders/VFXGlobalSortKeys.template +++ b/Packages/com.unity.visualeffectgraph/Shaders/VFXGlobalSortKeys.template @@ -1,5 +1,5 @@ #pragma kernel CSMain -#pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch glcore gles3 +${VFXPragmaOnlyRenderers} ${VFXPragmaRequire} ${VFXGlobalInclude} diff --git a/Packages/com.unity.visualeffectgraph/Shaders/VFXInit.template b/Packages/com.unity.visualeffectgraph/Shaders/VFXInit.template index 8d8e9a3671a..03198a1e78c 100644 --- a/Packages/com.unity.visualeffectgraph/Shaders/VFXInit.template +++ b/Packages/com.unity.visualeffectgraph/Shaders/VFXInit.template @@ -1,5 +1,5 @@ #pragma kernel CSMain -#pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch glcore gles3 +${VFXPragmaOnlyRenderers} ${VFXPragmaRequire} ${VFXGlobalInclude} diff --git a/Packages/com.unity.visualeffectgraph/Shaders/VFXOutputUpdate.template b/Packages/com.unity.visualeffectgraph/Shaders/VFXOutputUpdate.template index 978ff242502..e804a6d2046 100644 --- a/Packages/com.unity.visualeffectgraph/Shaders/VFXOutputUpdate.template +++ b/Packages/com.unity.visualeffectgraph/Shaders/VFXOutputUpdate.template @@ -1,5 +1,5 @@ #pragma kernel CSMain -#pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch glcore gles3 +${VFXPragmaOnlyRenderers} ${VFXPragmaRequire} ${VFXGlobalInclude} diff --git a/Packages/com.unity.visualeffectgraph/Shaders/VFXParticleHeader.template b/Packages/com.unity.visualeffectgraph/Shaders/VFXParticleHeader.template index 6b6712e0fba..680943bd851 100644 --- a/Packages/com.unity.visualeffectgraph/Shaders/VFXParticleHeader.template +++ b/Packages/com.unity.visualeffectgraph/Shaders/VFXParticleHeader.template @@ -4,6 +4,7 @@ ${VFXInclude("Shaders/VFXParticleCommon.template")} ${VFXOutputRenderState} HLSLINCLUDE +${VFXPragmaOnlyRenderers} ${VFXPragmaRequire} ${VFXGlobalInclude} ${VFXGlobalDeclaration} diff --git a/Packages/com.unity.visualeffectgraph/Shaders/VFXUpdate.template b/Packages/com.unity.visualeffectgraph/Shaders/VFXUpdate.template index 95e85207d25..88b75b75966 100644 --- a/Packages/com.unity.visualeffectgraph/Shaders/VFXUpdate.template +++ b/Packages/com.unity.visualeffectgraph/Shaders/VFXUpdate.template @@ -1,5 +1,5 @@ #pragma kernel CSMain -#pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch glcore gles3 +${VFXPragmaOnlyRenderers} ${VFXPragmaRequire} ${VFXGlobalInclude} diff --git a/Tests/SRPTests/Projects/HDRP_DXR_Tests/Assets/Scenes/3001_AreaShadowsDeferredTiny.meta b/Tests/SRPTests/Projects/HDRP_DXR_Tests/Assets/Scenes/3001_AreaShadowsDeferredTiny.meta new file mode 100644 index 00000000000..39f4ae2b6a1 --- /dev/null +++ b/Tests/SRPTests/Projects/HDRP_DXR_Tests/Assets/Scenes/3001_AreaShadowsDeferredTiny.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4c1f8db0b1cd4be4a9c2b5e763ada8c1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/SRPTests/Projects/HDRP_DXR_Tests/Assets/Scenes/3001_AreaShadowsDeferredTiny.unity b/Tests/SRPTests/Projects/HDRP_DXR_Tests/Assets/Scenes/3001_AreaShadowsDeferredTiny.unity new file mode 100644 index 00000000000..c25dbd4ca73 --- /dev/null +++ b/Tests/SRPTests/Projects/HDRP_DXR_Tests/Assets/Scenes/3001_AreaShadowsDeferredTiny.unity @@ -0,0 +1,856 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 4890085278179872738, guid: 23f828be21c65fa4ab4f50d91591e4ba, + type: 2} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 3 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + buildHeightMesh: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &258136885 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 258136888} + - component: {fileID: 258136887} + - component: {fileID: 258136886} + m_Layer: 0 + m_Name: Area Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &258136886 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 258136885} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7a68c43fe1f2a47cfa234b5eeaa98012, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Intensity: 200 + m_EnableSpotReflector: 1 + m_LuxAtDistance: 1 + m_InnerSpotPercent: 0 + m_SpotIESCutoffPercent: 100 + m_LightDimmer: 1 + m_VolumetricDimmer: 1 + m_LightUnit: 0 + m_FadeDistance: 10000 + m_VolumetricFadeDistance: 10000 + m_AffectDiffuse: 1 + m_AffectSpecular: 1 + m_NonLightmappedOnly: 0 + m_ShapeWidth: 0.5 + m_ShapeHeight: 0.5 + m_AspectRatio: 1 + m_ShapeRadius: 0.025 + m_SoftnessScale: 1 + m_UseCustomSpotLightShadowCone: 0 + m_CustomSpotLightShadowCone: 30 + m_MaxSmoothness: 0.99 + m_ApplyRangeAttenuation: 1 + m_DisplayAreaLightEmissiveMesh: 0 + m_AreaLightCookie: {fileID: 0} + m_IESPoint: {fileID: 0} + m_IESSpot: {fileID: 0} + m_IncludeForRayTracing: 1 + m_AreaLightShadowCone: 120 + m_UseScreenSpaceShadows: 0 + m_InteractsWithSky: 1 + m_AngularDiameter: 0.5 + m_FlareSize: 2 + m_FlareTint: {r: 1, g: 1, b: 1, a: 1} + m_FlareFalloff: 4 + m_SurfaceTexture: {fileID: 0} + m_SurfaceTint: {r: 1, g: 1, b: 1, a: 1} + m_Distance: 1.5e+11 + m_UseRayTracedShadows: 1 + m_NumRayTracingSamples: 4 + m_FilterTracedShadow: 1 + m_FilterSizeTraced: 16 + m_SunLightConeAngle: 0.5 + m_LightShadowRadius: 0.5 + m_SemiTransparentShadow: 0 + m_ColorShadow: 1 + m_DistanceBasedFiltering: 0 + m_EvsmExponent: 15 + m_EvsmLightLeakBias: 0 + m_EvsmVarianceBias: 0.00001 + m_EvsmBlurPasses: 0 + m_LightlayersMask: 1 + m_LinkShadowLayers: 1 + m_ShadowNearPlane: 0.1 + m_BlockerSampleCount: 24 + m_FilterSampleCount: 16 + m_MinFilterSize: 0.1 + m_KernelSize: 5 + m_LightAngle: 1 + m_MaxDepthBias: 0.001 + m_ShadowResolution: + m_Override: 512 + m_UseOverride: 1 + m_Level: 0 + m_ShadowDimmer: 1 + m_VolumetricShadowDimmer: 1 + m_ShadowFadeDistance: 10000 + m_UseContactShadow: + m_Override: 0 + m_UseOverride: 1 + m_Level: 0 + m_RayTracedContactShadow: 0 + m_ShadowTint: {r: 0, g: 0, b: 0, a: 1} + m_PenumbraTint: 0 + m_NormalBias: 0.75 + m_SlopeBias: 0.5 + m_ShadowUpdateMode: 0 + m_AlwaysDrawDynamicShadows: 0 + m_UpdateShadowOnLightMovement: 0 + m_CachedShadowTranslationThreshold: 0.01 + m_CachedShadowAngularThreshold: 0.5 + m_BarnDoorAngle: 90 + m_BarnDoorLength: 0.05 + m_preserveCachedShadow: 0 + m_OnDemandShadowRenderOnPlacement: 1 + m_ShadowCascadeRatios: + - 0.05 + - 0.2 + - 0.3 + m_ShadowCascadeBorders: + - 0.2 + - 0.2 + - 0.2 + - 0.2 + m_ShadowAlgorithm: 0 + m_ShadowVariant: 0 + m_ShadowPrecision: 0 + useOldInspector: 0 + useVolumetric: 1 + featuresFoldout: 1 + m_AreaLightEmissiveMeshShadowCastingMode: 0 + m_AreaLightEmissiveMeshMotionVectorGenerationMode: 0 + m_AreaLightEmissiveMeshLayer: -1 + m_Version: 11 + m_ObsoleteShadowResolutionTier: 1 + m_ObsoleteUseShadowQualitySettings: 0 + m_ObsoleteCustomShadowResolution: 512 + m_ObsoleteContactShadows: 0 + m_PointlightHDType: 1 + m_SpotLightShape: 0 + m_AreaLightShape: 0 +--- !u!108 &258136887 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 258136885} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 2 + m_Shape: 0 + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_Intensity: 254.6479 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 1 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 4 + m_LightShadowCasterMode: 2 + m_AreaSize: {x: 0.5, y: 0.5} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 1 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 10} + m_UseBoundingSphereOverride: 1 + m_UseViewFrustumForShadowCasterCull: 1 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &258136888 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 258136885} + m_LocalRotation: {x: 0.18020979, y: -0.6837576, z: 0.18020979, w: 0.6837576} + m_LocalPosition: {x: 0.62, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 29.53, y: -90, z: 0} +--- !u!1001 &846620933 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 1132393308280272, guid: c07ace9ab142ca9469fa377877c2f1e7, type: 3} + propertyPath: m_Name + value: HDRP_Test_Camera + objectReference: {fileID: 0} + - target: {fileID: 4209882255362944, guid: c07ace9ab142ca9469fa377877c2f1e7, type: 3} + propertyPath: m_RootOrder + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4209882255362944, guid: c07ace9ab142ca9469fa377877c2f1e7, type: 3} + propertyPath: m_LocalPosition.x + value: -3 + objectReference: {fileID: 0} + - target: {fileID: 4209882255362944, guid: c07ace9ab142ca9469fa377877c2f1e7, type: 3} + propertyPath: m_LocalPosition.y + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 4209882255362944, guid: c07ace9ab142ca9469fa377877c2f1e7, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4209882255362944, guid: c07ace9ab142ca9469fa377877c2f1e7, type: 3} + propertyPath: m_LocalRotation.w + value: 0.6532815 + objectReference: {fileID: 0} + - target: {fileID: 4209882255362944, guid: c07ace9ab142ca9469fa377877c2f1e7, type: 3} + propertyPath: m_LocalRotation.x + value: 0.27059805 + objectReference: {fileID: 0} + - target: {fileID: 4209882255362944, guid: c07ace9ab142ca9469fa377877c2f1e7, type: 3} + propertyPath: m_LocalRotation.y + value: 0.6532815 + objectReference: {fileID: 0} + - target: {fileID: 4209882255362944, guid: c07ace9ab142ca9469fa377877c2f1e7, type: 3} + propertyPath: m_LocalRotation.z + value: -0.27059805 + objectReference: {fileID: 0} + - target: {fileID: 4209882255362944, guid: c07ace9ab142ca9469fa377877c2f1e7, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 45 + objectReference: {fileID: 0} + - target: {fileID: 4209882255362944, guid: c07ace9ab142ca9469fa377877c2f1e7, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 90 + objectReference: {fileID: 0} + - target: {fileID: 4209882255362944, guid: c07ace9ab142ca9469fa377877c2f1e7, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 20109210616973140, guid: c07ace9ab142ca9469fa377877c2f1e7, + type: 3} + propertyPath: near clip plane + value: 0.19 + objectReference: {fileID: 0} + - target: {fileID: 114777190906822814, guid: c07ace9ab142ca9469fa377877c2f1e7, + type: 3} + propertyPath: m_Version + value: 9 + objectReference: {fileID: 0} + - target: {fileID: 114777190906822814, guid: c07ace9ab142ca9469fa377877c2f1e7, + type: 3} + propertyPath: backgroundColorHDR.b + value: 0.066037714 + objectReference: {fileID: 0} + - target: {fileID: 114777190906822814, guid: c07ace9ab142ca9469fa377877c2f1e7, + type: 3} + propertyPath: backgroundColorHDR.g + value: 0.066037714 + objectReference: {fileID: 0} + - target: {fileID: 114777190906822814, guid: c07ace9ab142ca9469fa377877c2f1e7, + type: 3} + propertyPath: backgroundColorHDR.r + value: 0.066037714 + objectReference: {fileID: 0} + - target: {fileID: 114777190906822814, guid: c07ace9ab142ca9469fa377877c2f1e7, + type: 3} + propertyPath: m_RenderingPathCustomFrameSettings.bitDatas.data1 + value: 70005818916701 + objectReference: {fileID: 0} + - target: {fileID: 114995348509370400, guid: c07ace9ab142ca9469fa377877c2f1e7, + type: 3} + propertyPath: waitFrames + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 114995348509370400, guid: c07ace9ab142ca9469fa377877c2f1e7, + type: 3} + propertyPath: renderPipelineAsset + value: + objectReference: {fileID: 11400000, guid: 14a0f3aaa5e78a3439ec76d270471ebe, + type: 2} + - target: {fileID: 114995348509370400, guid: c07ace9ab142ca9469fa377877c2f1e7, + type: 3} + propertyPath: checkMemoryAllocation + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 114995348509370400, guid: c07ace9ab142ca9469fa377877c2f1e7, + type: 3} + propertyPath: renderGraphCompatible + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 114995348509370400, guid: c07ace9ab142ca9469fa377877c2f1e7, + type: 3} + propertyPath: ImageComparisonSettings.TargetHeight + value: 480 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: c07ace9ab142ca9469fa377877c2f1e7, type: 3} +--- !u!1 &930401665 +GameObject: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 930401667} + - component: {fileID: 930401666} + m_Layer: 0 + m_Name: StaticLightingSky + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &930401666 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 930401665} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 441482e8936e35048a1dffac814e3ef8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Profile: {fileID: 11400000, guid: 919acda9bae911e4fac8930ea8b43b73, type: 2} + m_StaticLightingSkyUniqueID: 0 + m_StaticLightingCloudsUniqueID: 0 + m_StaticLightingVolumetricClouds: 0 +--- !u!4 &930401667 +Transform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 930401665} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1001 &977274794 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 6117102520564098274, guid: 0c9fcf2263b163643b5bc77eddcf9135, + type: 3} + propertyPath: m_Name + value: RayTracingFrameIndexDisplay + objectReference: {fileID: 0} + - target: {fileID: 6117102520564098278, guid: 0c9fcf2263b163643b5bc77eddcf9135, + type: 3} + propertyPath: m_RootOrder + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 6117102520564098278, guid: 0c9fcf2263b163643b5bc77eddcf9135, + type: 3} + propertyPath: m_LocalScale.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 6117102520564098278, guid: 0c9fcf2263b163643b5bc77eddcf9135, + type: 3} + propertyPath: m_LocalScale.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 6117102520564098278, guid: 0c9fcf2263b163643b5bc77eddcf9135, + type: 3} + propertyPath: m_LocalScale.z + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 6117102520564098278, guid: 0c9fcf2263b163643b5bc77eddcf9135, + type: 3} + propertyPath: m_LocalPosition.x + value: -0.318 + objectReference: {fileID: 0} + - target: {fileID: 6117102520564098278, guid: 0c9fcf2263b163643b5bc77eddcf9135, + type: 3} + propertyPath: m_LocalPosition.y + value: 0.451 + objectReference: {fileID: 0} + - target: {fileID: 6117102520564098278, guid: 0c9fcf2263b163643b5bc77eddcf9135, + type: 3} + propertyPath: m_LocalPosition.z + value: -1.219 + objectReference: {fileID: 0} + - target: {fileID: 6117102520564098278, guid: 0c9fcf2263b163643b5bc77eddcf9135, + type: 3} + propertyPath: m_LocalRotation.w + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 6117102520564098278, guid: 0c9fcf2263b163643b5bc77eddcf9135, + type: 3} + propertyPath: m_LocalRotation.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 6117102520564098278, guid: 0c9fcf2263b163643b5bc77eddcf9135, + type: 3} + propertyPath: m_LocalRotation.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 6117102520564098278, guid: 0c9fcf2263b163643b5bc77eddcf9135, + type: 3} + propertyPath: m_LocalRotation.z + value: -0.5 + objectReference: {fileID: 0} + - target: {fileID: 6117102520564098278, guid: 0c9fcf2263b163643b5bc77eddcf9135, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 90 + objectReference: {fileID: 0} + - target: {fileID: 6117102520564098278, guid: 0c9fcf2263b163643b5bc77eddcf9135, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 90 + objectReference: {fileID: 0} + - target: {fileID: 6117102520564098278, guid: 0c9fcf2263b163643b5bc77eddcf9135, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 0c9fcf2263b163643b5bc77eddcf9135, type: 3} +--- !u!1 &1215868572 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1215868576} + - component: {fileID: 1215868575} + - component: {fileID: 1215868574} + - component: {fileID: 1215868573} + m_Layer: 0 + m_Name: Plane + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!64 &1215868573 +MeshCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1215868572} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 5 + m_Convex: 0 + m_CookingOptions: 30 + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &1215868574 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1215868572} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 257 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 94719af7cfdb12445899024997aac82e, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &1215868575 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1215868572} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1215868576 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1215868572} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1338089982 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1338089984} + - component: {fileID: 1338089983} + m_Layer: 0 + m_Name: Global Volume + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1338089983 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1338089982} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 172515602e62fb746b5d573b38a5fe58, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IsGlobal: 1 + priority: 0 + blendDistance: 0 + weight: 1 + sharedProfile: {fileID: 11400000, guid: e7e1dfede0afaf14c8b86b5ccffacbc3, type: 2} +--- !u!4 &1338089984 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1338089982} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 6.9064736, y: -3.1764686, z: -1.3948785} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1638276287 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1638276291} + - component: {fileID: 1638276290} + - component: {fileID: 1638276289} + - component: {fileID: 1638276288} + m_Layer: 0 + m_Name: Cube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!65 &1638276288 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1638276287} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1638276289 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1638276287} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 257 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 73c176f402d2c2f4d929aa5da7585d17, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &1638276290 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1638276287} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1638276291 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1638276287} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 6 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Tests/SRPTests/Projects/HDRP_DXR_Tests/Assets/Scenes/3001_AreaShadowsDeferredTiny.unity.meta b/Tests/SRPTests/Projects/HDRP_DXR_Tests/Assets/Scenes/3001_AreaShadowsDeferredTiny.unity.meta new file mode 100644 index 00000000000..5ab46f572c5 --- /dev/null +++ b/Tests/SRPTests/Projects/HDRP_DXR_Tests/Assets/Scenes/3001_AreaShadowsDeferredTiny.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: bb2a3b72e71b4e64ea4683b9739d887a +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/SRPTests/Projects/HDRP_DXR_Tests/Assets/Scenes/3001_AreaShadowsDeferredTiny/Global Volume Profile.asset b/Tests/SRPTests/Projects/HDRP_DXR_Tests/Assets/Scenes/3001_AreaShadowsDeferredTiny/Global Volume Profile.asset new file mode 100644 index 00000000000..cebb26e5fa7 --- /dev/null +++ b/Tests/SRPTests/Projects/HDRP_DXR_Tests/Assets/Scenes/3001_AreaShadowsDeferredTiny/Global Volume Profile.asset @@ -0,0 +1,130 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d7fd9488000d3734a9e00ee676215985, type: 3} + m_Name: Global Volume Profile + m_EditorClassIdentifier: + components: + - {fileID: 7477922283883413941} +--- !u!114 &7477922283883413941 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 384c4d03a551c44448145f4093304119, type: 3} + m_Name: ScreenSpaceReflection + m_EditorClassIdentifier: + active: 1 + quality: + m_OverrideState: 0 + m_Value: 1 + enabled: + m_OverrideState: 1 + m_Value: 1 + enabledTransparent: + m_OverrideState: 1 + m_Value: 1 + tracing: + m_OverrideState: 0 + m_Value: 1 + m_MinSmoothness: + m_OverrideState: 0 + m_Value: 0.9 + m_SmoothnessFadeStart: + m_OverrideState: 0 + m_Value: 0.9 + reflectSky: + m_OverrideState: 0 + m_Value: 1 + usedAlgorithm: + m_OverrideState: 0 + m_Value: 0 + depthBufferThickness: + m_OverrideState: 0 + m_Value: 0.01 + screenFadeDistance: + m_OverrideState: 0 + m_Value: 0.1 + accumulationFactor: + m_OverrideState: 0 + m_Value: 0.75 + biasFactor: + m_OverrideState: 0 + m_Value: 0.5 + speedRejectionParam: + m_OverrideState: 0 + m_Value: 0.5 + speedRejectionScalerFactor: + m_OverrideState: 0 + m_Value: 0.2 + speedSmoothReject: + m_OverrideState: 0 + m_Value: 0 + speedSurfaceOnly: + m_OverrideState: 0 + m_Value: 1 + speedTargetOnly: + m_OverrideState: 0 + m_Value: 1 + enableWorldSpeedRejection: + m_OverrideState: 0 + m_Value: 0 + m_RayMaxIterations: + m_OverrideState: 0 + m_Value: 32 + rayMiss: + m_OverrideState: 0 + m_Value: 3 + lastBounceFallbackHierarchy: + m_OverrideState: 0 + m_Value: 3 + layerMask: + m_OverrideState: 0 + m_Value: + serializedVersion: 2 + m_Bits: 4294967295 + textureLodBias: + m_OverrideState: 0 + m_Value: 1 + m_RayLength: + m_OverrideState: 0 + m_Value: 50 + m_ClampValue: + m_OverrideState: 0 + m_Value: 1 + m_Denoise: + m_OverrideState: 0 + m_Value: 1 + m_DenoiserRadius: + m_OverrideState: 0 + m_Value: 8 + m_AffectSmoothSurfaces: + m_OverrideState: 0 + m_Value: 0 + mode: + m_OverrideState: 0 + m_Value: 2 + m_FullResolution: + m_OverrideState: 0 + m_Value: 0 + sampleCount: + m_OverrideState: 0 + m_Value: 1 + bounceCount: + m_OverrideState: 0 + m_Value: 1 + m_RayMaxIterationsRT: + m_OverrideState: 0 + m_Value: 48 diff --git a/Tests/SRPTests/Projects/HDRP_DXR_Tests/Assets/Scenes/3001_AreaShadowsDeferredTiny/Global Volume Profile.asset.meta b/Tests/SRPTests/Projects/HDRP_DXR_Tests/Assets/Scenes/3001_AreaShadowsDeferredTiny/Global Volume Profile.asset.meta new file mode 100644 index 00000000000..03c10801e8e --- /dev/null +++ b/Tests/SRPTests/Projects/HDRP_DXR_Tests/Assets/Scenes/3001_AreaShadowsDeferredTiny/Global Volume Profile.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e7e1dfede0afaf14c8b86b5ccffacbc3 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/SRPTests/Projects/HDRP_DXR_Tests/Assets/Scenes/3001_AreaShadowsDeferredTiny/M_DielectricRough.mat b/Tests/SRPTests/Projects/HDRP_DXR_Tests/Assets/Scenes/3001_AreaShadowsDeferredTiny/M_DielectricRough.mat new file mode 100644 index 00000000000..9f7f72cc01d --- /dev/null +++ b/Tests/SRPTests/Projects/HDRP_DXR_Tests/Assets/Scenes/3001_AreaShadowsDeferredTiny/M_DielectricRough.mat @@ -0,0 +1,276 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: M_DielectricRough + m_Shader: {fileID: 4800000, guid: 6e4ae4064600d784cac1e41a9e6f2e59, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: + - _DISABLE_SSR_TRANSPARENT + - _NORMALMAP_TANGENT_SPACE + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: 2225 + stringTagMap: {} + disabledShaderPasses: + - TransparentDepthPrepass + - TransparentDepthPostpass + - TransparentBackface + - RayTracingPrepass + - MOTIONVECTORS + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _AnisotropyMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseColorMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BentNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BentNormalMapOS: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _CoatMaskMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissiveColorMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _HeightMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _IridescenceMaskMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _IridescenceThicknessMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MaskMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _NormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _NormalMapOS: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SpecularColorMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SubsurfaceMaskMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _TangentMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _TangentMapOS: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ThicknessMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _TransmissionMaskMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _TransmittanceColorMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _AORemapMax: 1 + - _AORemapMin: 0 + - _ATDistance: 1 + - _AddPrecomputedVelocity: 0 + - _AlbedoAffectEmissive: 0 + - _AlphaCutoff: 0.5 + - _AlphaCutoffEnable: 0 + - _AlphaCutoffPostpass: 0.5 + - _AlphaCutoffPrepass: 0.5 + - _AlphaCutoffShadow: 0.5 + - _AlphaDstBlend: 0 + - _AlphaRemapMax: 1 + - _AlphaRemapMin: 0 + - _AlphaSrcBlend: 1 + - _Anisotropy: 0 + - _BlendMode: 0 + - _CoatMask: 0 + - _CullMode: 2 + - _CullModeForward: 2 + - _Cutoff: 0.5 + - _DepthOffsetEnable: 0 + - _DetailAlbedoScale: 1 + - _DetailNormalScale: 1 + - _DetailSmoothnessScale: 1 + - _DiffusionProfile: 0 + - _DiffusionProfileHash: 0 + - _DisplacementLockObjectScale: 1 + - _DisplacementLockTilingScale: 1 + - _DisplacementMode: 0 + - _DoubleSidedEnable: 0 + - _DoubleSidedGIMode: 0 + - _DoubleSidedNormalMode: 1 + - _DstBlend: 0 + - _EmissiveColorMode: 1 + - _EmissiveExposureWeight: 1 + - _EmissiveIntensity: 1 + - _EmissiveIntensityUnit: 0 + - _EnableBlendModePreserveSpecularLighting: 1 + - _EnableFogOnTransparent: 1 + - _EnableGeometricSpecularAA: 0 + - _EnergyConservingSpecularColor: 1 + - _HeightAmplitude: 0.02 + - _HeightCenter: 0.5 + - _HeightMapParametrization: 0 + - _HeightMax: 1 + - _HeightMin: -1 + - _HeightOffset: 0 + - _HeightPoMAmplitude: 2 + - _HeightTessAmplitude: 2 + - _HeightTessCenter: 0.5 + - _InvTilingScale: 1 + - _Ior: 1.5 + - _IridescenceMask: 1 + - _IridescenceThickness: 1 + - _LinkDetailsWithBase: 1 + - _MaterialID: 1 + - _Metallic: 0 + - _MetallicRemapMax: 1 + - _MetallicRemapMin: 0 + - _NormalMapSpace: 0 + - _NormalScale: 1 + - _ObjectSpaceUVMapping: 0 + - _ObjectSpaceUVMappingEmissive: 0 + - _OpaqueCullMode: 2 + - _PPDLodThreshold: 5 + - _PPDMaxSamples: 15 + - _PPDMinSamples: 5 + - _PPDPrimitiveLength: 1 + - _PPDPrimitiveWidth: 1 + - _RayTracing: 0 + - _ReceivesSSR: 1 + - _ReceivesSSRTransparent: 0 + - _RefractionModel: 0 + - _Smoothness: 0 + - _SmoothnessRemapMax: 1 + - _SmoothnessRemapMin: 0 + - _SpecularAAScreenSpaceVariance: 0.1 + - _SpecularAAThreshold: 0.2 + - _SpecularOcclusionMode: 1 + - _SrcBlend: 1 + - _StencilRef: 0 + - _StencilRefDepth: 8 + - _StencilRefGBuffer: 10 + - _StencilRefMV: 40 + - _StencilWriteMask: 6 + - _StencilWriteMaskDepth: 8 + - _StencilWriteMaskGBuffer: 14 + - _StencilWriteMaskMV: 40 + - _SubsurfaceMask: 1 + - _SupportDecals: 1 + - _SurfaceType: 0 + - _TexWorldScale: 1 + - _TexWorldScaleEmissive: 1 + - _Thickness: 1 + - _TransmissionEnable: 1 + - _TransmissionMask: 1 + - _TransparentBackfaceEnable: 0 + - _TransparentCullMode: 2 + - _TransparentDepthPostpassEnable: 0 + - _TransparentDepthPrepassEnable: 0 + - _TransparentSortPriority: 0 + - _TransparentWritingMotionVec: 0 + - _TransparentZWrite: 0 + - _UVBase: 0 + - _UVDetail: 0 + - _UVEmissive: 0 + - _UseEmissiveIntensity: 0 + - _UseShadowThreshold: 0 + - _ZTestDepthEqualForOpaque: 3 + - _ZTestGBuffer: 4 + - _ZTestTransparent: 4 + - _ZWrite: 1 + m_Colors: + - _BaseColor: {r: 1, g: 1, b: 1, a: 1} + - _BaseColorMap_MipInfo: {r: 0, g: 0, b: 0, a: 0} + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _DiffusionProfileAsset: {r: 0, g: 0, b: 0, a: 0} + - _DoubleSidedConstants: {r: 1, g: 1, b: -1, a: 0} + - _EmissionColor: {r: 1, g: 1, b: 1, a: 1} + - _EmissiveColor: {r: 0, g: 0, b: 0, a: 1} + - _EmissiveColorLDR: {r: 0, g: 0, b: 0, a: 1} + - _InvPrimScale: {r: 1, g: 1, b: 0, a: 0} + - _IridescenceThicknessRemap: {r: 0, g: 1, b: 0, a: 0} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _ThicknessRemap: {r: 0, g: 1, b: 0, a: 0} + - _TransmittanceColor: {r: 1, g: 1, b: 1, a: 1} + - _UVDetailsMappingMask: {r: 1, g: 0, b: 0, a: 0} + - _UVMappingMask: {r: 1, g: 0, b: 0, a: 0} + - _UVMappingMaskEmissive: {r: 1, g: 0, b: 0, a: 0} + m_BuildTextureStacks: [] +--- !u!114 &8769360051460969297 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: da692e001514ec24dbc4cca1949ff7e8, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 12 + hdPluginSubTargetMaterialVersions: + m_Keys: [] + m_Values: diff --git a/Tests/SRPTests/Projects/HDRP_DXR_Tests/Assets/Scenes/3001_AreaShadowsDeferredTiny/M_DielectricRough.mat.meta b/Tests/SRPTests/Projects/HDRP_DXR_Tests/Assets/Scenes/3001_AreaShadowsDeferredTiny/M_DielectricRough.mat.meta new file mode 100644 index 00000000000..8e05421a867 --- /dev/null +++ b/Tests/SRPTests/Projects/HDRP_DXR_Tests/Assets/Scenes/3001_AreaShadowsDeferredTiny/M_DielectricRough.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 94719af7cfdb12445899024997aac82e +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/SRPTests/Projects/HDRP_DXR_Tests/ProjectSettings/EditorBuildSettings.asset b/Tests/SRPTests/Projects/HDRP_DXR_Tests/ProjectSettings/EditorBuildSettings.asset index 16ee24ae4ed..59c391aff4b 100644 --- a/Tests/SRPTests/Projects/HDRP_DXR_Tests/ProjectSettings/EditorBuildSettings.asset +++ b/Tests/SRPTests/Projects/HDRP_DXR_Tests/ProjectSettings/EditorBuildSettings.asset @@ -341,6 +341,9 @@ EditorBuildSettings: - enabled: 1 path: Assets/Scenes/3001_AreaShadowsDeferred.unity guid: 490feb5a82328c647b87259fba42ec1f + - enabled: 1 + path: Assets/Scenes/3001_AreaShadowsDeferredTiny.unity + guid: bb2a3b72e71b4e64ea4683b9739d887a - enabled: 1 path: Assets/Scenes/3001_AreaShadowsForward.unity guid: 18a3a10168d8d3847abf880a745f365e diff --git a/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV.unity b/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV.unity index 0ba8e416066..1445dff1a27 100644 --- a/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV.unity +++ b/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV.unity @@ -152,9 +152,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 92247174} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 1} m_Center: {x: 0, y: 0, z: 0} --- !u!23 &92247176 @@ -466,9 +474,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 260797553} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 1} m_Center: {x: 0, y: 0, z: 0} --- !u!23 &260797555 @@ -598,9 +614,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 334101957} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 1} m_Center: {x: 0, y: 0, z: 0} --- !u!23 &334101959 @@ -756,6 +780,10 @@ MonoBehaviour: m_UseOverride: 0 m_Level: 0 resolution: 0 + cubeResolution: + m_Override: 128 + m_UseOverride: 0 + m_Level: 0 cameraSettings: customRenderingSettings: 0 renderingPathCustomFrameSettings: @@ -956,33 +984,33 @@ MonoBehaviour: m_Aspect: 0 m_HasValidSHForNormalization: 1 m_SHForNormalization: - sh[ 0]: 312.94235 - sh[ 1]: -187.60643 - sh[ 2]: 166.37894 - sh[ 3]: -33.353714 - sh[ 4]: 5.737907 - sh[ 5]: -94.603745 - sh[ 6]: -6.0550632 - sh[ 7]: -30.697018 - sh[ 8]: -27.341091 - sh[ 9]: 374.88306 - sh[10]: -167.34158 - sh[11]: 154.53041 - sh[12]: -31.58607 - sh[13]: -4.327828 - sh[14]: -87.48828 - sh[15]: -5.6446776 - sh[16]: -46.591755 - sh[17]: -19.959606 - sh[18]: 813.6431 - sh[19]: -334.9676 - sh[20]: -213.4212 - sh[21]: 123.06818 - sh[22]: -82.94431 - sh[23]: 44.769997 - sh[24]: 27.21065 - sh[25]: -202.1709 - sh[26]: -16.329988 + sh[ 0]: 294.43283 + sh[ 1]: -157.366 + sh[ 2]: 71.79524 + sh[ 3]: 3.3411484 + sh[ 4]: -28.469948 + sh[ 5]: -65.73405 + sh[ 6]: -12.597583 + sh[ 7]: 14.103926 + sh[ 8]: -9.057853 + sh[ 9]: 422.65167 + sh[10]: -215.68033 + sh[11]: -15.197263 + sh[12]: 38.74776 + sh[13]: -72.11784 + sh[14]: 40.978745 + sh[15]: -16.51425 + sh[16]: -20.724785 + sh[17]: -17.009516 + sh[18]: 595.57367 + sh[19]: -89.75712 + sh[20]: -226.80797 + sh[21]: 62.867195 + sh[22]: -57.176517 + sh[23]: 70.211075 + sh[24]: 50.295887 + sh[25]: -101.86257 + sh[26]: 30.656483 m_SHValidForCapturePosition: {x: -3.424, y: 13.12, z: 3.08} m_SHValidForSourcePosition: {x: -3.424, y: 13.12, z: 3.08} m_HDProbeVersion: 3 @@ -1164,9 +1192,17 @@ SphereCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 525690398} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Radius: 0.5 m_Center: {x: 0, y: 0, z: 0} --- !u!23 &525690400 @@ -1261,9 +1297,17 @@ SphereCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 683602977} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Radius: 0.5 m_Center: {x: 0, y: 0, z: 0} --- !u!23 &683602979 @@ -1358,9 +1402,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 766200815} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 1} m_Center: {x: 0, y: 0, z: 0} --- !u!23 &766200817 @@ -1568,11 +1620,19 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 55f90731af2ebc94fb7fdaebe2a9a409, type: 3} m_Name: m_EditorClassIdentifier: + shape: 0 + size: {x: 5.7269, y: 0.8505597, z: 4.86174} + radius: 1 + mode: 0 intensityScale: 1 + overriddenDilationThreshold: 0.75 + virtualOffsetRotation: {x: 0, y: 0, z: 0} + virtualOffsetDistance: 1 + geometryBias: 0.01 + rayOriginBias: -0.001 + version: 1 invalidateProbes: 1 overrideDilationThreshold: 0 - overriddenDilationThreshold: 0.75 - size: {x: 5.7269, y: 0.8505597, z: 4.86174} --- !u!4 &1198170532 Transform: m_ObjectHideFlags: 0 @@ -1740,7 +1800,7 @@ Light: serializedVersion: 10 m_Type: 2 m_Shape: 0 - m_Color: {r: 1, g: 0, b: 0, a: 1} + m_Color: {r: 0, g: 1, b: 0, a: 1} m_Intensity: 4774.648 m_Range: 1.9943948 m_SpotAngle: 30 @@ -1895,9 +1955,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1522498572} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 1} m_Center: {x: 0, y: 0, z: 0} --- !u!23 &1522498574 @@ -1992,9 +2060,17 @@ SphereCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1715235054} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Radius: 0.5 m_Center: {x: 0, y: 0, z: 0} --- !u!23 &1715235056 @@ -2143,11 +2219,14 @@ MonoBehaviour: stopNaNs: 0 taaSharpenStrength: 0.5 TAAQuality: 1 + taaSharpenMode: 0 + taaRingingReduction: 0 taaHistorySharpening: 0.35 taaAntiFlicker: 0.5 taaMotionVectorRejection: 0 taaAntiHistoryRinging: 0 taaBaseBlendFactor: 0.875 + taaJitterScale: 1 physicalParameters: m_Iso: 200 m_ShutterSpeed: 0.005 @@ -2167,6 +2246,8 @@ MonoBehaviour: serializedVersion: 2 m_Bits: 4294967295 hasPersistentHistory: 0 + screenSizeOverride: {x: 0, y: 0, z: 0, w: 0} + screenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} allowDeepLearningSuperSampling: 1 deepLearningSuperSamplingUseCustomQualitySettings: 0 deepLearningSuperSamplingQuality: 0 @@ -2403,13 +2484,13 @@ MonoBehaviour: serializedScenarios: - scenario: Scenario 1 data: - sceneHash: -2092273140 + sceneHash: 484293852 cellDataAsset: {fileID: 4900000, guid: ae544a6f3c1b9164abd2fab0146045c0, type: 3} cellOptionalDataAsset: {fileID: 4900000, guid: 53fac240cb0516e49bb93a839ab630fa, type: 3} - scenario: Scenario 2 data: - sceneHash: 1784705805 + sceneHash: 484293852 cellDataAsset: {fileID: 4900000, guid: 119c8614a43e778428c158c35e6ac459, type: 3} cellOptionalDataAsset: {fileID: 4900000, guid: bbdacefbfc0bb9142a400cebc6fb1060, type: 3} @@ -2455,9 +2536,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1970315737} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 1} m_Center: {x: 0, y: 0, z: 0} --- !u!23 &1970315739 @@ -2552,9 +2641,17 @@ SphereCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2072380636} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Radius: 0.5 m_Center: {x: 0, y: 0, z: 0} --- !u!23 &2072380638 @@ -2654,13 +2751,15 @@ MonoBehaviour: parameters: albedo: {r: 1, g: 1, b: 1, a: 1} meanFreePath: 1 + blendingMode: 1 + priority: 0 anisotropy: 0 volumeMask: {fileID: 0} textureScrollingSpeed: {x: 0, y: 0, z: 0} textureTiling: {x: 1, y: 1, z: 1} - positiveFade: {x: 0, y: 0, z: 0} - negativeFade: {x: 0, y: 0, z: 0} - m_EditorUniformFade: 0 + positiveFade: {x: 0.03695569, y: 0.12298492, z: 0.020658419} + negativeFade: {x: 0.03695569, y: 0.12298492, z: 0.020658419} + m_EditorUniformFade: 0.3 m_EditorPositiveFade: {x: 0, y: 0, z: 0} m_EditorNegativeFade: {x: 0, y: 0, z: 0} m_EditorAdvancedFade: 0 @@ -2670,6 +2769,8 @@ MonoBehaviour: distanceFadeEnd: 10000 textureOffset: {x: 0, y: 0, z: 0} falloffMode: 0 + maskMode: 0 + materialMask: {fileID: 0} m_Version: 2 --- !u!4 &2120413993 Transform: @@ -2713,9 +2814,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2132055074} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 1} m_Center: {x: 0, y: 0, z: 0} --- !u!23 &2132055076 diff --git a/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/AssetWithAPV.asset b/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/AssetWithAPV.asset index 497b05a34f3..304686e1b7a 100644 --- a/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/AssetWithAPV.asset +++ b/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/AssetWithAPV.asset @@ -41,6 +41,10 @@ MonoBehaviour: m_Values: 000100000004000000040000 m_SchemaId: m_Id: With3Levels + cubeReflectionResolution: + m_Values: 000100000002000000040000 + m_SchemaId: + m_Id: With3Levels supportDecals: 1 supportDecalLayers: 0 supportSurfaceGradient: 1 @@ -65,8 +69,13 @@ MonoBehaviour: planarReflectionAtlasSize: 1024 reflectionProbeCacheSize: 64 reflectionCubemapSize: 256 + maxEnvLightsOnScreen: 64 reflectionCacheCompressed: 0 reflectionProbeFormat: 74 + reflectionProbeTexCacheSize: 4096 + reflectionProbeTexLastValidCubeMip: 3 + reflectionProbeTexLastValidPlanarMip: 0 + reflectionProbeDecreaseResToFit: 1 skyReflectionSize: 256 skyLightingOverrideLayerMask: serializedVersion: 2 @@ -75,9 +84,9 @@ MonoBehaviour: maxDirectionalLightsOnScreen: 16 maxPunctualLightsOnScreen: 512 maxAreaLightsOnScreen: 64 - maxEnvLightsOnScreen: 64 - maxDecalsOnScreen: 512 + maxCubeReflectionOnScreen: 48 maxPlanarReflectionOnScreen: 16 + maxDecalsOnScreen: 512 maxLightsPerClusterCell: 8 maxLocalVolumetricFogSize: 32 maxLocalVolumetricFogOnScreen: 64 @@ -85,6 +94,7 @@ MonoBehaviour: maxShadowRequests: 128 directionalShadowsDepthBits: 32 shadowFilteringQuality: 1 + areaShadowFilteringQuality: 0 punctualLightShadowAtlas: shadowAtlasResolution: 4096 shadowAtlasDepthBits: 32 @@ -128,6 +138,7 @@ MonoBehaviour: useMipBias: 0 enableDLSS: 0 DLSSPerfQualitySetting: 0 + DLSSInjectionPoint: 0 DLSSUseOptimalSettings: 1 DLSSSharpness: 0.5 fsrOverrideSharpness: 0 @@ -286,7 +297,7 @@ MonoBehaviour: - format: 0 sizeInMegaBytes: 128 m_UseRenderGraph: 1 - m_Version: 21 + m_Version: 22 m_ObsoleteFrameSettings: overrides: 0 enableShadow: 0 diff --git a/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/Global Volume Profile.asset b/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/Global Volume Profile.asset index a0c8c6e941d..09df8f2b3c1 100644 --- a/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/Global Volume Profile.asset +++ b/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/Global Volume Profile.asset @@ -176,12 +176,18 @@ MonoBehaviour: samplingNoise: m_OverrideState: 1 m_Value: 0.078 + animateSamplingNoise: + m_OverrideState: 0 + m_Value: 1 leakReductionMode: m_OverrideState: 1 m_Value: 1 minValidDotProductValue: m_OverrideState: 0 m_Value: 0.1 + occlusionOnlyReflectionNormalization: + m_OverrideState: 0 + m_Value: 1 --- !u!114 &-4145478425724808730 MonoBehaviour: m_ObjectHideFlags: 3 @@ -440,7 +446,7 @@ MonoBehaviour: active: 1 quality: m_OverrideState: 1 - m_Value: 1 + m_Value: 3 enabled: m_OverrideState: 1 m_Value: 1 @@ -494,16 +500,16 @@ MonoBehaviour: m_Value: 0 sliceDistributionUniformity: m_OverrideState: 1 - m_Value: 0.75 + m_Value: 0.8 m_FogControlMode: m_OverrideState: 1 - m_Value: 0 + m_Value: 1 screenResolutionPercentage: m_OverrideState: 1 m_Value: 12.5 volumeSliceCount: m_OverrideState: 1 - m_Value: 64 + m_Value: 128 m_VolumetricFogBudget: m_OverrideState: 1 m_Value: 0.33 diff --git a/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/LightingData.asset b/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/LightingData.asset index 1eb1307431a..d988d7b3c78 100644 Binary files a/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/LightingData.asset and b/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/LightingData.asset differ diff --git a/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData-Scenario 1.CellData.bytes b/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData-Scenario 1.CellData.bytes index 36eca8e3a16..3f93ae68dc7 100644 --- a/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData-Scenario 1.CellData.bytes +++ b/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData-Scenario 1.CellData.bytes @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:675b299542ba687b7cdf6d4f7d4c73be8d57a102181ea124f20eca3066dbc6ba +oid sha256:e99ff174ac3c7ca2b3a85b8598d9ee4c488c0d1239de8e6f617398f2474447f6 size 1048576 diff --git a/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData-Scenario 1.CellOptionalData.bytes b/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData-Scenario 1.CellOptionalData.bytes index d82c67cf556..e8d906b1e1f 100644 --- a/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData-Scenario 1.CellOptionalData.bytes +++ b/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData-Scenario 1.CellOptionalData.bytes @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:82662d8d3ef5941be918d3da176a1ff117315dff7b8899ce3c418e0a7af44bc7 +oid sha256:570c845b4c1137b9276ca155826b60883541b8f8e9f7844b1426a7f535da4d7d size 1048576 diff --git a/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData-Scenario 2.CellData.bytes b/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData-Scenario 2.CellData.bytes index 68ba1224c56..768d03c8257 100644 --- a/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData-Scenario 2.CellData.bytes +++ b/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData-Scenario 2.CellData.bytes @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c2231d881dfe282a703b4d681c1c95931ea4dd18db3915db03f92284df6475e8 +oid sha256:f09c7bba5a30d123d903cda27fc0b56510bfce28aa895fe4d9c8fa53825ce7aa size 1048576 diff --git a/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData-Scenario 2.CellOptionalData.bytes b/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData-Scenario 2.CellOptionalData.bytes index 8dd83d3a9e7..b1a50b9a719 100644 --- a/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData-Scenario 2.CellOptionalData.bytes +++ b/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData-Scenario 2.CellOptionalData.bytes @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d2683b566d375ae46d92869d1bf924acf1231a87d23ce6c160fc47240d66fb7b +oid sha256:1c4a02badcb6d4d4b691b05ea9a3ee1b6c1a685263768a581323ec98707bcbf8 size 1048576 diff --git a/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData.CellSharedData.bytes b/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData.CellSharedData.bytes index 376a717182a..692d98b68f7 100644 --- a/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData.CellSharedData.bytes +++ b/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData.CellSharedData.bytes @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5c4886bc5d0384bc329050234207cfdf8cf9e5c3d4e833b313ba690de0bb526c -size 74368 +oid sha256:8c5df5113daeab5e4e29bb528c35d58f47197055fadbf5ea82fd25bf88f3c7cb +size 74528 diff --git a/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData.CellSupportData.bytes b/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData.CellSupportData.bytes index 63eed84a59b..3e0919520ee 100644 --- a/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData.CellSupportData.bytes +++ b/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData.CellSupportData.bytes @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6b12f628787fb07b505fcc708ff529d988ed50e682aab07f2fb79ff3335e55aa +oid sha256:352e35ae2a0f10ba9a30cb953a7a366f279a54804ef8ad9ed3bbc9a1446fc57f size 2097152 diff --git a/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData.asset b/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData.asset index 19591c73b6e..6b58cfba10b 100644 Binary files a/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData.asset and b/Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/Scenes/007-BasicAPV/ProbeVolumeData.asset differ diff --git a/Tests/SRPTests/Projects/HDRP_Tests/Assets/GraphicTests/Scenes/2x_Lighting/2120_APV_Baking.unity b/Tests/SRPTests/Projects/HDRP_Tests/Assets/GraphicTests/Scenes/2x_Lighting/2120_APV_Baking.unity index 8cb3c75b0f6..9f97b7c3e31 100644 --- a/Tests/SRPTests/Projects/HDRP_Tests/Assets/GraphicTests/Scenes/2x_Lighting/2120_APV_Baking.unity +++ b/Tests/SRPTests/Projects/HDRP_Tests/Assets/GraphicTests/Scenes/2x_Lighting/2120_APV_Baking.unity @@ -1046,11 +1046,46 @@ PrefabInstance: propertyPath: ImageComparisonSettings.TargetHeight value: 400 objectReference: {fileID: 0} + - target: {fileID: 114995348509370400, guid: c07ace9ab142ca9469fa377877c2f1e7, + type: 3} + propertyPath: doBeforeTest.m_PersistentCalls.m_Calls.Array.size + value: 1 + objectReference: {fileID: 0} - target: {fileID: 114995348509370400, guid: c07ace9ab142ca9469fa377877c2f1e7, type: 3} propertyPath: ImageComparisonSettings.AverageCorrectnessThreshold value: 0.001 objectReference: {fileID: 0} + - target: {fileID: 114995348509370400, guid: c07ace9ab142ca9469fa377877c2f1e7, + type: 3} + propertyPath: doBeforeTest.m_PersistentCalls.m_Calls.Array.data[0].m_Mode + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 114995348509370400, guid: c07ace9ab142ca9469fa377877c2f1e7, + type: 3} + propertyPath: doBeforeTest.m_PersistentCalls.m_Calls.Array.data[0].m_Target + value: + objectReference: {fileID: 1725026263} + - target: {fileID: 114995348509370400, guid: c07ace9ab142ca9469fa377877c2f1e7, + type: 3} + propertyPath: doBeforeTest.m_PersistentCalls.m_Calls.Array.data[0].m_CallState + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 114995348509370400, guid: c07ace9ab142ca9469fa377877c2f1e7, + type: 3} + propertyPath: doBeforeTest.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName + value: AddBakeLabelOnActiveScene + objectReference: {fileID: 0} + - target: {fileID: 114995348509370400, guid: c07ace9ab142ca9469fa377877c2f1e7, + type: 3} + propertyPath: doBeforeTest.m_PersistentCalls.m_Calls.Array.data[0].m_TargetAssemblyTypeName + value: AddBakeLabel, Assembly-CSharp + objectReference: {fileID: 0} + - target: {fileID: 114995348509370400, guid: c07ace9ab142ca9469fa377877c2f1e7, + type: 3} + propertyPath: doBeforeTest.m_PersistentCalls.m_Calls.Array.data[0].m_Arguments.m_ObjectArgumentAssemblyTypeName + value: UnityEngine.Object, UnityEngine + objectReference: {fileID: 0} m_RemovedComponents: [] m_AddedGameObjects: [] m_AddedComponents: [] @@ -2305,6 +2340,50 @@ Transform: m_Father: {fileID: 0} m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1725026262 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1725026264} + - component: {fileID: 1725026263} + m_Layer: 0 + m_Name: AddBakeLabel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1725026263 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1725026262} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7bfc7a40569e0a44fb0320295b3186c6, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!4 &1725026264 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1725026262} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 9 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1725355993 GameObject: m_ObjectHideFlags: 0 @@ -2520,47 +2599,3 @@ PrefabInstance: m_AddedGameObjects: [] m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 9c31666db73c94448ad9133b2aeff0e5, type: 3} ---- !u!1 &2143068754 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 2143068756} - - component: {fileID: 2143068757} - m_Layer: 0 - m_Name: ExpectAPVError - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &2143068756 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2143068754} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 1 - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 9 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &2143068757 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2143068754} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 3d7d679d253a5604aa18d11b0c912896, type: 3} - m_Name: - m_EditorClassIdentifier: diff --git a/Tests/SRPTests/Projects/HDRP_Tests/Assets/GraphicTests/Scenes/2x_Lighting/2120_APV_Baking/AddBakeLabel.cs b/Tests/SRPTests/Projects/HDRP_Tests/Assets/GraphicTests/Scenes/2x_Lighting/2120_APV_Baking/AddBakeLabel.cs new file mode 100644 index 00000000000..3d1d55c05a8 --- /dev/null +++ b/Tests/SRPTests/Projects/HDRP_Tests/Assets/GraphicTests/Scenes/2x_Lighting/2120_APV_Baking/AddBakeLabel.cs @@ -0,0 +1,14 @@ +using UnityEngine; + +public class AddBakeLabel : MonoBehaviour +{ + public void AddBakeLabelOnActiveScene() + { + #if UNITY_EDITOR + var scenePath = UnityEngine.SceneManagement.SceneManager.GetActiveScene().path; + var scene = UnityEditor.AssetDatabase.LoadMainAssetAtPath(scenePath); + UnityEditor.AssetDatabase.SetLabels(scene, new[] { "TestRunnerBake" }); + UnityEditor.AssetDatabase.SaveAssets(); + #endif + } +} diff --git a/Tests/SRPTests/Projects/HDRP_Tests/Assets/GraphicTests/Scenes/2x_Lighting/2120_APV_Baking/AddBakeLabel.cs.meta b/Tests/SRPTests/Projects/HDRP_Tests/Assets/GraphicTests/Scenes/2x_Lighting/2120_APV_Baking/AddBakeLabel.cs.meta new file mode 100644 index 00000000000..cf264f7d6aa --- /dev/null +++ b/Tests/SRPTests/Projects/HDRP_Tests/Assets/GraphicTests/Scenes/2x_Lighting/2120_APV_Baking/AddBakeLabel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7bfc7a40569e0a44fb0320295b3186c6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/SRPTests/Projects/HDRP_Tests/Assets/GraphicTests/Scenes/2x_Lighting/2120_APV_Baking/Sky and Fog Settings Profile.asset b/Tests/SRPTests/Projects/HDRP_Tests/Assets/GraphicTests/Scenes/2x_Lighting/2120_APV_Baking/Sky and Fog Settings Profile.asset index e643947be6f..8f281eee718 100644 --- a/Tests/SRPTests/Projects/HDRP_Tests/Assets/GraphicTests/Scenes/2x_Lighting/2120_APV_Baking/Sky and Fog Settings Profile.asset +++ b/Tests/SRPTests/Projects/HDRP_Tests/Assets/GraphicTests/Scenes/2x_Lighting/2120_APV_Baking/Sky and Fog Settings Profile.asset @@ -14,6 +14,44 @@ MonoBehaviour: m_EditorClassIdentifier: components: - {fileID: 9129104383184685765} + - {fileID: 546966928056812749} +--- !u!114 &546966928056812749 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 6bd486065ce11414fa40e631affc4900, type: 3} + m_Name: ProbeVolumesOptions + m_EditorClassIdentifier: + active: 1 + normalBias: + m_OverrideState: 0 + m_Value: 0.33 + viewBias: + m_OverrideState: 0 + m_Value: 0 + scaleBiasWithMinProbeDistance: + m_OverrideState: 0 + m_Value: 0 + samplingNoise: + m_OverrideState: 0 + m_Value: 0.1 + animateSamplingNoise: + m_OverrideState: 0 + m_Value: 1 + leakReductionMode: + m_OverrideState: 1 + m_Value: 0 + minValidDotProductValue: + m_OverrideState: 0 + m_Value: 0.1 + occlusionOnlyReflectionNormalization: + m_OverrideState: 0 + m_Value: 1 --- !u!114 &9129104383184685765 MonoBehaviour: m_ObjectHideFlags: 3 diff --git a/Tests/SRPTests/Projects/HDRP_Tests/ProjectSettings/EditorBuildSettings.asset b/Tests/SRPTests/Projects/HDRP_Tests/ProjectSettings/EditorBuildSettings.asset index 8893eceabcd..2e8eb80d4c0 100644 --- a/Tests/SRPTests/Projects/HDRP_Tests/ProjectSettings/EditorBuildSettings.asset +++ b/Tests/SRPTests/Projects/HDRP_Tests/ProjectSettings/EditorBuildSettings.asset @@ -299,7 +299,7 @@ EditorBuildSettings: - enabled: 1 path: Assets/GraphicTests/Scenes/2x_Lighting/2110_IndirectController.unity guid: 443ac92abc2bd6a4d94e9e673dbcc29f - - enabled: 0 + - enabled: 1 path: Assets/GraphicTests/Scenes/2x_Lighting/2120_APV_Baking.unity guid: fc784678bf952de4482e78aea61ccdc8 - enabled: 1