// Given a brick index, find and accumulate probes in nearby bricks private static void CullDilationProbes(int brickIdx, List <Brick> bricks, float[] validity, ProbeDilationSettings dilationSettings, List <DilationProbe> outProbeIndices) { outProbeIndices.Clear(); for (int otherBrickIdx = 0; otherBrickIdx < bricks.Count; otherBrickIdx++) { var currentBrick = bricks[brickIdx]; var otherBrick = bricks[otherBrickIdx]; float currentBrickSize = Mathf.Pow(3f, currentBrick.size); float otherBrickSize = Mathf.Pow(3f, otherBrick.size); // TODO: This should probably be revisited. float sqrt2 = 1.41421356237f; float maxDistance = sqrt2 * currentBrickSize + sqrt2 * otherBrickSize; float interval = dilationSettings.maxDilationSampleDistance / dilationSettings.brickSize; maxDistance = interval * Mathf.Ceil(maxDistance / interval); Vector3 currentBrickCenter = currentBrick.position + Vector3.one * currentBrickSize / 2f; Vector3 otherBrickCenter = otherBrick.position + Vector3.one * otherBrickSize / 2f; if (Vector3.Distance(currentBrickCenter, otherBrickCenter) <= maxDistance) { for (int probeOffset = 0; probeOffset < 64; probeOffset++) { int otherProbeIdx = otherBrickIdx * 64 + probeOffset; if (validity[otherProbeIdx] <= dilationSettings.dilationValidityThreshold) { outProbeIndices.Add(new DilationProbe(otherProbeIdx, 0)); } } } } }
internal void SetBakeSettingsForScene(Scene scene, ProbeDilationSettings dilationSettings, VirtualOffsetSettings virtualOffsetSettings) { if (sceneBakingSettings == null) { sceneBakingSettings = new Dictionary <string, ProbeVolumeBakingProcessSettings>(); } var sceneGUID = GetSceneGUID(scene); sceneBakingSettings[sceneGUID] = new ProbeVolumeBakingProcessSettings(dilationSettings, virtualOffsetSettings); }
// Given a probe index, find nearby probes weighted by inverse distance private static void FindNearProbes(int probeIdx, Vector3[] probePositions, ProbeDilationSettings dilationSettings, List <DilationProbe> culledProbes, List <DilationProbe> outNearProbes, out float invDistSum) { outNearProbes.Clear(); invDistSum = 0; // Sort probes by distance to prioritize closer ones for (int culledProbeIdx = 0; culledProbeIdx < culledProbes.Count; culledProbeIdx++) { float dist = Vector3.Distance(probePositions[culledProbes[culledProbeIdx].idx], probePositions[probeIdx]); culledProbes[culledProbeIdx] = new DilationProbe(culledProbes[culledProbeIdx].idx, dist); } if (!dilationSettings.greedyDilation) { culledProbes.Sort(); } // Return specified amount of probes under given max distance int numSamples = 0; for (int sortedProbeIdx = 0; sortedProbeIdx < culledProbes.Count; sortedProbeIdx++) { if (numSamples >= dilationSettings.maxDilationSamples) { return; } var current = culledProbes[sortedProbeIdx]; if (current.dist <= dilationSettings.maxDilationSampleDistance) { var invDist = 1f / (current.dist * current.dist); invDistSum += invDist; outNearProbes.Add(new DilationProbe(current.idx, invDist)); numSamples++; } } }
private static void DilateInvalidProbes(Vector3[] probePositions, List <Brick> bricks, SphericalHarmonicsL2[] sh, float[] validity, ProbeDilationSettings dilationSettings) { // For each brick List <DilationProbe> culledProbes = new List <DilationProbe>(); List <DilationProbe> nearProbes = new List <DilationProbe>(dilationSettings.maxDilationSamples); for (int brickIdx = 0; brickIdx < bricks.Count; brickIdx++) { // Find probes that are in bricks nearby CullDilationProbes(brickIdx, bricks, validity, dilationSettings, culledProbes); // Iterate probes in current brick for (int probeOffset = 0; probeOffset < 64; probeOffset++) { int probeIdx = brickIdx * 64 + probeOffset; // Skip valid probes if (validity[probeIdx] <= dilationSettings.dilationValidityThreshold) { continue; } // Find distance weighted probes nearest to current probe FindNearProbes(probeIdx, probePositions, dilationSettings, culledProbes, nearProbes, out float invDistSum); // Set invalid probe to weighted average of found neighboring probes var shAverage = new SphericalHarmonicsL2(); for (int nearProbeIdx = 0; nearProbeIdx < nearProbes.Count; nearProbeIdx++) { var nearProbe = nearProbes[nearProbeIdx]; float weight = nearProbe.dist / invDistSum; var target = sh[nearProbe.idx]; for (int c = 0; c < 9; ++c) { shAverage[0, c] += target[0, c] * weight; shAverage[1, c] += target[1, c] * weight; shAverage[2, c] += target[2, c] * weight; } } sh[probeIdx] = shAverage; validity[probeIdx] = validity[probeIdx]; } } }
static void PerformDilation(ProbeReferenceVolume.Cell cell, ProbeDilationSettings settings) { InitDilationShaders(); DataForDilation data = new DataForDilation(cell, settings.dilationValidityThreshold); var cmd = CommandBufferPool.Get("Cell Dilation"); cmd.SetComputeBufferParam(dilationShader, dilationKernel, _ProbePositionsBuffer, data.positionBuffer); cmd.SetComputeBufferParam(dilationShader, dilationKernel, _OutputProbes, data.outputProbes); cmd.SetComputeBufferParam(dilationShader, dilationKernel, _NeedDilating, data.needDilatingBuffer); int probeCount = cell.probePositions.Length; cmd.SetComputeVectorParam(dilationShader, _DilationParameters, new Vector4(probeCount, settings.dilationValidityThreshold, settings.dilationDistance, ProbeReferenceVolume.instance.MinBrickSize())); cmd.SetComputeVectorParam(dilationShader, _DilationParameters2, new Vector4(settings.squaredDistWeighting ? 1 : 0, 0, 0, 0)); var refVolume = ProbeReferenceVolume.instance; ProbeReferenceVolume.RuntimeResources rr = refVolume.GetRuntimeResources(); bool validResources = rr.index != null && rr.L0_L1rx != null && rr.L1_G_ry != null && rr.L1_B_rz != null; if (validResources) { cmd.SetGlobalBuffer(_APVResIndex, rr.index); cmd.SetGlobalBuffer(_APVResCellIndices, rr.cellIndices); cmd.SetGlobalTexture(_APVResL0_L1Rx, rr.L0_L1rx); cmd.SetGlobalTexture(_APVResL1G_L1Ry, rr.L1_G_ry); cmd.SetGlobalTexture(_APVResL1B_L1Rz, rr.L1_B_rz); cmd.SetGlobalTexture(_APVResL2_0, rr.L2_0); cmd.SetGlobalTexture(_APVResL2_1, rr.L2_1); cmd.SetGlobalTexture(_APVResL2_2, rr.L2_2); cmd.SetGlobalTexture(_APVResL2_3, rr.L2_3); } ProbeVolumeShadingParameters parameters; parameters.normalBias = 0; parameters.viewBias = 0; parameters.scaleBiasByMinDistanceBetweenProbes = false; parameters.samplingNoise = 0; parameters.weight = 1f; parameters.leakReductionMode = APVLeakReductionMode.None; parameters.occlusionWeightContribution = 0.0f; parameters.minValidNormalWeight = 0.0f; parameters.frameIndexForNoise = 0; parameters.reflNormalizationLowerClamp = 0.1f; parameters.reflNormalizationUpperClamp = 1.0f; ProbeReferenceVolume.instance.UpdateConstantBuffer(cmd, parameters); int groupCount = (probeCount + 63) / 64; cmd.DispatchCompute(dilationShader, dilationKernel, groupCount, 1, 1); cmd.WaitAllAsyncReadbackRequests(); Graphics.ExecuteCommandBuffer(cmd); data.ExtractDilatedProbes(); data.Dispose(); }