void DrawDilationSettings(SerializedProperty dilationSettings) { var enableDilation = dilationSettings.FindPropertyRelative("enableDilation"); var maxDilationSampleDistance = dilationSettings.FindPropertyRelative("dilationDistance"); var dilationValidityThreshold = dilationSettings.FindPropertyRelative("dilationValidityThreshold"); float dilationValidityThresholdInverted = 1f - dilationValidityThreshold.floatValue; var dilationIterations = dilationSettings.FindPropertyRelative("dilationIterations"); var dilationInvSquaredWeight = dilationSettings.FindPropertyRelative("squaredDistWeighting"); EditorGUI.indentLevel++; enableDilation.boolValue = EditorGUILayout.Toggle(Styles.enableDilation, enableDilation.boolValue); EditorGUI.BeginDisabledGroup(!enableDilation.boolValue); maxDilationSampleDistance.floatValue = Mathf.Max(EditorGUILayout.FloatField(Styles.dilationDistance, maxDilationSampleDistance.floatValue), 0); dilationValidityThresholdInverted = EditorGUILayout.Slider(Styles.dilationValidity, dilationValidityThresholdInverted, 0f, 0.95f); dilationValidityThreshold.floatValue = Mathf.Max(0.05f, 1.0f - dilationValidityThresholdInverted); dilationIterations.intValue = EditorGUILayout.IntSlider(Styles.dilationIterationCount, dilationIterations.intValue, 1, 5); dilationInvSquaredWeight.boolValue = EditorGUILayout.Toggle(Styles.dilationSquaredDistanceWeighting, dilationInvSquaredWeight.boolValue); EditorGUI.EndDisabledGroup(); EditorGUI.indentLevel--; if (Unsupported.IsDeveloperMode()) { if (GUILayout.Button(EditorGUIUtility.TrTextContent("Refresh dilation"), EditorStyles.miniButton)) { ProbeGIBaking.RevertDilation(); ProbeGIBaking.PerformDilation(); } } }
static void UpdateRealtimeSubdivisionDebug() { var debugDisplay = ProbeReferenceVolume.instance.probeVolumeDebug; if (!debugDisplay.realtimeSubdivision) { return; } // Avoid killing the GPU when Unity is in background and runInBackground is disabled if (!Application.runInBackground && !UnityEditorInternal.InternalEditorUtility.isApplicationActive) { return; } // update is called 200 times per second so we bring down the update rate to 60hz to avoid overloading the GPU if (Time.realtimeSinceStartupAsDouble - s_LastRefreshTime < 1.0f / 60.0f) { return; } s_LastRefreshTime = Time.realtimeSinceStartupAsDouble; if (Time.realtimeSinceStartupAsDouble - s_LastSubdivisionTime > debugDisplay.subdivisionDelayInSeconds) { var probeVolume = GameObject.FindObjectOfType <ProbeVolume>(); if (probeVolume == null || !probeVolume.isActiveAndEnabled || ProbeReferenceVolume.instance.sceneData == null) { return; } var profile = ProbeReferenceVolume.instance.sceneData.GetProfileForScene(probeVolume.gameObject.scene); if (profile == null) { return; } if (s_CurrentSubdivision == null) { // Start a new Subdivision s_CurrentSubdivision = Subdivide(); } // Step the subdivision with the amount of cell per frame in debug menu int updatePerFrame = debugDisplay.subdivisionCellUpdatePerFrame; // From simplification level 5 and higher, the cost of calculating one cell is very high, so we adjust that number. if (profile.simplificationLevels > 4) { updatePerFrame = (int)Mathf.Max(1, updatePerFrame / Mathf.Pow(9, profile.simplificationLevels - 4)); } for (int i = 0; i < debugDisplay.subdivisionCellUpdatePerFrame; i++) { if (!s_CurrentSubdivision.MoveNext()) { s_LastSubdivisionTime = Time.realtimeSinceStartupAsDouble; s_CurrentSubdivision = null; break; } } IEnumerator Subdivide() { var ctx = ProbeGIBaking.PrepareProbeSubdivisionContext(); // Cull all the cells that are not visible (we don't need them for realtime debug) ctx.cells.RemoveAll(c => { return(probeVolume.ShouldCullCell(c.position)); }); Camera activeCamera = Camera.current ?? SceneView.lastActiveSceneView.camera; // Sort cells by camera distance to compute the closest cells first if (activeCamera != null) { var cameraPos = activeCamera.transform.position; ctx.cells.Sort((c1, c2) => { c1.volume.CalculateCenterAndSize(out var c1Center, out var _); float c1Distance = Vector3.Distance(cameraPos, c1Center); c2.volume.CalculateCenterAndSize(out var c2Center, out var _); float c2Distance = Vector3.Distance(cameraPos, c2Center); return(c1Distance.CompareTo(c2Distance)); }); } // Progressively update cells: var cells = ctx.cells.ToList(); // Remove all the cells that was not updated to prevent ghosting foreach (var cellVolume in ProbeReferenceVolume.instance.realtimeSubdivisionInfo.Keys.ToList()) { if (!cells.Any(c => c.volume.Equals(cellVolume))) { ProbeReferenceVolume.instance.realtimeSubdivisionInfo.Remove(cellVolume); } } // Subdivide visible cells foreach (var cell in cells) { // Override the cell list to only compute one cell ctx.cells.Clear(); ctx.cells.Add(cell); var result = ProbeGIBaking.BakeBricks(ctx); if (result.bricksPerCells.TryGetValue(cell.position, out var bricks)) { ProbeReferenceVolume.instance.realtimeSubdivisionInfo[cell.volume] = bricks; } else { ProbeReferenceVolume.instance.realtimeSubdivisionInfo.Remove(cell.volume); } yield return(null); } yield break; } } }