/// <summary> /// Initialize the reference volume. /// </summary> /// <param name ="allocationSize"> Size used for the chunk allocator that handles bricks.</param> /// <param name ="memoryBudget">Probe reference volume memory budget.</param> /// <param name ="indexDimensions">Dimensions of the index data structure.</param> public void InitProbeReferenceVolume(int allocationSize, ProbeVolumeTextureMemoryBudget memoryBudget, Vector3Int indexDimensions) { if (!m_ProbeReferenceVolumeInit) { Profiler.BeginSample("Initialize Reference Volume"); m_Pool = new ProbeBrickPool(allocationSize, memoryBudget); if ((indexDimensions.x * (indexDimensions.y + 1) * indexDimensions.z) == 0) { // Give a momentarily dummy size to allow the system to function with no asset assigned. indexDimensions = new Vector3Int(1, 1, 1); } m_Index = new ProbeBrickIndex(indexDimensions); m_TmpBricks[0] = new List <Brick>(); m_TmpBricks[1] = new List <Brick>(); m_TmpBricks[0].Capacity = m_TmpBricks[1].Capacity = 1024; // initialize offsets m_PositionOffsets[0] = 0.0f; float probeDelta = 1.0f / ProbeBrickPool.kBrickCellCount; 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; } m_NeedLoadAsset = true; }
private void LoadAsset(ProbeVolumeAsset asset) { var path = asset.GetSerializedFullPath(); m_AssetPathToBricks[path] = new List <RegId>(); foreach (var cell in asset.cells) { // Push data to HDRP bool compressed = false; var dataLocation = ProbeBrickPool.CreateDataLocation(cell.sh.Length, compressed, ProbeVolumeSHBands.SphericalHarmonicsL2); ProbeBrickPool.FillDataLocation(ref dataLocation, cell.sh, ProbeVolumeSHBands.SphericalHarmonicsL2); // TODO register ID of brick list List <ProbeBrickIndex.Brick> brickList = new List <ProbeBrickIndex.Brick>(); brickList.AddRange(cell.bricks); var regId = AddBricks(brickList, dataLocation); cells[cell.index] = cell; m_AssetPathToBricks[path].Add(regId); dataLocation.Cleanup(); } }
// This is very much modeled to be as close as possible to the way bricks are loaded in the texture pool. // Not necessarily a good thing. static void ComputeValidityMasks(BakingCell bakingCell) { var bricks = bakingCell.bricks; var cell = bakingCell; int chunkSize = ProbeBrickPool.GetChunkSize(); int brickChunksCount = (bricks.Length + chunkSize - 1) / chunkSize; var probeHasEmptySpaceInGrid = new NativeArray <bool>(bakingCell.probePositions.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); int chunkIndex = 0; while (chunkIndex < brickChunksCount) { int chunkToProcess = Math.Min(ProbeReferenceVolume.kTemporaryDataLocChunkCount, brickChunksCount - chunkIndex); Vector3Int locSize = ProbeBrickPool.ProbeCountToDataLocSize(ProbeReferenceVolume.kTemporaryDataLocChunkCount * ProbeBrickPool.GetChunkSizeInProbeCount()); int size = locSize.x * locSize.y * locSize.z; int startIndex = chunkIndex * ProbeBrickPool.GetChunkSizeInProbeCount(); int count = chunkToProcess * ProbeBrickPool.GetChunkSizeInProbeCount(); int shidx = startIndex; int bx = 0, by = 0, bz = 0; s_Validity_locData.Resize(size); s_ProbeIndices.Resize(size); Dictionary <Vector3Int, (float, Vector3, Bounds)> probesToRestoreInfo = new Dictionary <Vector3Int, (float, Vector3, Bounds)>(); HashSet <Vector3Int> probesToRestore = new HashSet <Vector3Int>(); for (int brickIdx = startIndex; brickIdx < (startIndex + count); brickIdx += ProbeBrickPool.kBrickProbeCountTotal) { for (int z = 0; z < ProbeBrickPool.kBrickProbeCountPerDim; z++) { for (int y = 0; y < ProbeBrickPool.kBrickProbeCountPerDim; y++) { for (int x = 0; x < ProbeBrickPool.kBrickProbeCountPerDim; x++) { int ix = bx + x; int iy = by + y; int iz = bz + z; if (shidx >= cell.validity.Length) { StoreScratchData(ix, iy, iz, locSize.x, locSize.y, 1.0f, shidx); } else { StoreScratchData(ix, iy, iz, locSize.x, locSize.y, ProbeReferenceVolume.Cell.GetValidityFromPacked(cell.validity[shidx]), shidx); // Check if we need to do some extra check on this probe. bool hasFreeNeighbourhood = false; Bounds invalidatingTouchupBound; if (s_ForceInvalidatedProbesAndTouchupVols.TryGetValue(cell.probePositions[shidx], out invalidatingTouchupBound)) { int actualBrickIdx = brickIdx / ProbeBrickPool.kBrickProbeCountTotal; float brickSize = ProbeReferenceVolume.CellSize(cell.bricks[actualBrickIdx].subdivisionLevel); Vector3 position = cell.probePositions[shidx]; probesToRestore.Add(new Vector3Int(ix, iy, iz)); var searchDistance = (brickSize * m_BakingProfile.minBrickSize) / ProbeBrickPool.kBrickCellCount; hasFreeNeighbourhood = NeighbourhoodIsEmptySpace(position, searchDistance, invalidatingTouchupBound); } probeHasEmptySpaceInGrid[shidx] = hasFreeNeighbourhood; } shidx++; } } } // update the pool index bx += ProbeBrickPool.kBrickProbeCountPerDim; if (bx >= locSize.x) { bx = 0; by += ProbeBrickPool.kBrickProbeCountPerDim; if (by >= locSize.y) { by = 0; bz += ProbeBrickPool.kBrickProbeCountPerDim; } } } for (int x = 0; x < locSize.x; ++x) { for (int y = 0; y < locSize.y; ++y) { for (int z = 0; z < locSize.z; ++z) { int outIdx = ReadProbeIndex(x, y, z, locSize.x, locSize.y); float probeValidity = ReadValidity(x, y, z, locSize.x, locSize.y); if (outIdx < cell.validity.Length) { float[] validities = new float[8]; bool forceAllValid = false; for (int o = 0; o < 8; ++o) { Vector3Int off = GetSampleOffset(o); Vector3Int samplePos = new Vector3Int(Mathf.Clamp(x + off.x, 0, locSize.x - 1), Mathf.Clamp(y + off.y, 0, locSize.y - 1), Mathf.Clamp(z + off.z, 0, ProbeBrickPool.kBrickProbeCountPerDim - 1)); if (probesToRestore.Contains(samplePos)) { if (probeHasEmptySpaceInGrid[outIdx]) { forceAllValid = true; } } validities[o] = ReadValidity(samplePos.x, samplePos.y, samplePos.z, locSize.x, locSize.y); } byte mask = forceAllValid ? (byte)255 : Convert.ToByte(PackValidity(validities)); float validity = probeValidity; cell.validity[outIdx] = ProbeReferenceVolume.Cell.PackValidityAndMask(validity, mask); } } } } chunkIndex += ProbeReferenceVolume.kTemporaryDataLocChunkCount; } probeHasEmptySpaceInGrid.Dispose(); }