Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ public static List<Brick> SubdivideCell(ProbeReferenceVolume.Volume cellVolume,
// In case there is at least one brick in the sub-cell, we need to spawn the parent brick.
if (brickCount != brickSet.Count)
{
float minBrickSize = subdivisionCtx.refVolume.profile.minBrickSize;
float minBrickSize = subdivisionCtx.profile.minBrickSize;
Vector3 cellID = (cellAABB.center - cellAABB.extents) / minBrickSize;
float parentSubdivLevel = 3.0f;
for (int i = k_MaxSubdivisionInSubCell; i < ctx.maxSubdivisionLevel; i++)
Expand Down Expand Up @@ -350,7 +350,7 @@ static void SubdivideSubCell(ProbeReferenceVolume.Volume cellVolume, ProbeSubdiv
List<(Terrain terrain, ProbeReferenceVolume.Volume volume)> terrains, HashSet<Brick> brickSet)
{
var cellAABB = cellVolume.CalculateAABB();
float minBrickSize = subdivisionCtx.refVolume.profile.minBrickSize;
float minBrickSize = subdivisionCtx.profile.minBrickSize;

cellVolume.CalculateCenterAndSize(out var center, out var _);
var cmd = CommandBufferPool.Get($"Subdivide (Sub)Cell {center}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,132 +12,18 @@ namespace UnityEngine.Experimental.Rendering
[CustomEditor(typeof(ProbeReferenceVolumeAuthoring))]
internal class ProbeReferenceVolumeAuthoringEditor : Editor
{
[InitializeOnLoad]
class RealtimeProbeSubdivisionDebug
{
static double s_LastSubdivisionTime;
static double s_LastRefreshTime;
static IEnumerator s_CurrentSubdivision;

static RealtimeProbeSubdivisionDebug()
{
EditorApplication.update -= UpdateRealtimeSubdivisionDebug;
EditorApplication.update += UpdateRealtimeSubdivisionDebug;
}

static void UpdateRealtimeSubdivisionDebug()
{
var debugDisplay = ProbeReferenceVolume.instance.debugDisplay;
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 probeVolumeAuthoring = FindObjectOfType<ProbeReferenceVolumeAuthoring>();
if (probeVolumeAuthoring == null || !probeVolumeAuthoring.isActiveAndEnabled)
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 (probeVolumeAuthoring.profile.simplificationLevels > 4)
updatePerFrame = (int)Mathf.Max(1, updatePerFrame / Mathf.Pow(9, probeVolumeAuthoring.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(probeVolumeAuthoring);

// Cull all the cells that are not visible (we don't need them for realtime debug)
ctx.cells.RemoveAll(c =>
{
return probeVolumeAuthoring.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 ctx.refVolume.realtimeSubdivisionInfo.Keys.ToList())
{
if (!cells.Any(c => c.volume.Equals(cellVolume)))
ctx.refVolume.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);
ctx.refVolume.realtimeSubdivisionInfo[cell.volume] = result.bricksPerCells[cell.position];

yield return null;
}

yield break;
}
}
}
}

private SerializedProperty m_Dilate;
private SerializedProperty m_MaxDilationSampleDistance;
private SerializedProperty m_DilationValidityThreshold;
private SerializedProperty m_DilationIterations;
private SerializedProperty m_DilationInvSquaredWeight;
private SerializedProperty m_VolumeAsset;

private SerializedProperty m_EnableVirtualOffset;
private SerializedProperty m_VirtualOffsetGeometrySearchMultiplier;
private SerializedProperty m_VirtualOffsetBiasOutOfGeometry;

private SerializedProperty m_Profile;

internal static readonly GUIContent s_DataAssetLabel = new GUIContent("Data asset", "The asset which serializes all probe related data in this volume.");
internal static readonly GUIContent s_ProfileAssetLabel = new GUIContent("Profile", "The asset which determines the characteristics of the probe reference volume.");

private static bool DilationGroupEnabled;
Expand All @@ -155,7 +41,6 @@ private void OnEnable()
m_DilationInvSquaredWeight = serializedObject.FindProperty("m_DilationInvSquaredWeight");
m_MaxDilationSampleDistance = serializedObject.FindProperty("m_MaxDilationSampleDistance");
m_DilationValidityThreshold = serializedObject.FindProperty("m_DilationValidityThreshold");
m_VolumeAsset = serializedObject.FindProperty("volumeAsset");
m_EnableVirtualOffset = serializedObject.FindProperty("m_EnableVirtualOffset");
m_VirtualOffsetGeometrySearchMultiplier = serializedObject.FindProperty("m_VirtualOffsetGeometrySearchMultiplier");
m_VirtualOffsetBiasOutOfGeometry = serializedObject.FindProperty("m_VirtualOffsetBiasOutOfGeometry");
Expand Down Expand Up @@ -231,8 +116,6 @@ public override void OnInspectorGUI()
m_Profile.objectReferenceValue = asset;
}

m_VolumeAsset.objectReferenceValue = EditorGUILayout.ObjectField(s_DataAssetLabel, m_VolumeAsset.objectReferenceValue, typeof(ProbeVolumeAsset), false);

DilationGroupEnabled = EditorGUILayout.BeginFoldoutHeaderGroup(DilationGroupEnabled, "Dilation");
if (DilationGroupEnabled)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using Unity.Collections;
using System;
using System.Collections;
using System.Linq;
using UnityEditor;

Expand All @@ -12,16 +13,132 @@ namespace UnityEngine.Experimental.Rendering
{
class ProbeSubdivisionContext
{
[InitializeOnLoad]
class RealtimeProbeSubdivisionDebug
{
static double s_LastSubdivisionTime;
static double s_LastRefreshTime;
static IEnumerator s_CurrentSubdivision;

static RealtimeProbeSubdivisionDebug()
{
EditorApplication.update -= UpdateRealtimeSubdivisionDebug;
EditorApplication.update += UpdateRealtimeSubdivisionDebug;
}

static void UpdateRealtimeSubdivisionDebug()
{
var debugDisplay = ProbeReferenceVolume.instance.debugDisplay;
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);
ProbeReferenceVolume.instance.realtimeSubdivisionInfo[cell.volume] = result.bricksPerCells[cell.position];

yield return null;
}

yield break;
}
}
}
}

public List<(ProbeVolume component, ProbeReferenceVolume.Volume volume)> probeVolumes = new List<(ProbeVolume, ProbeReferenceVolume.Volume)>();
public List<(Renderer component, ProbeReferenceVolume.Volume volume)> renderers = new List<(Renderer, ProbeReferenceVolume.Volume)>();
public List<(Vector3Int position, ProbeReferenceVolume.Volume volume)> cells = new List<(Vector3Int, ProbeReferenceVolume.Volume)>();
public List<(Terrain, ProbeReferenceVolume.Volume volume)> terrains = new List<(Terrain, ProbeReferenceVolume.Volume)>();
public ProbeReferenceVolumeAuthoring refVolume;
public ProbeReferenceVolumeProfile profile;

public void Initialize(ProbeReferenceVolumeAuthoring refVolume, Vector3 refVolOrigin)
public void Initialize(ProbeReferenceVolumeProfile profile, Vector3 refVolOrigin)
{
this.refVolume = refVolume;
float cellSize = refVolume.cellSizeInMeters;
this.profile = profile;
float cellSize = profile.cellSizeInMeters;

foreach (var pv in UnityEngine.Object.FindObjectsOfType<ProbeVolume>())
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class CellInstancedDebugProbes

internal float dilationValidtyThreshold = 0.25f; // We ned to store this here to access it

// Field used for the realtime subdivision preview
internal Dictionary<ProbeReferenceVolume.Volume, List<ProbeBrickIndex.Brick>> realtimeSubdivisionInfo = new Dictionary<ProbeReferenceVolume.Volume, List<ProbeBrickIndex.Brick>>();

/// <summary>
/// Render Probe Volume related debug
Expand Down Expand Up @@ -238,6 +240,7 @@ void DrawProbeDebug(Camera camera)
void ClearDebugData()
{
m_CellDebugData.Clear();
realtimeSubdivisionInfo.Clear();
}

void CreateInstancedProbes()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ public struct ProbeVolumeSystemParameters
/// </summary>
public Shader probeDebugShader;

public ProbeVolumeSceneBounds sceneBounds;
public ProbeVolumeSceneData sceneData;
public ProbeVolumeSHBands shBands;
}

Expand Down Expand Up @@ -515,7 +515,7 @@ public override bool Equals(object obj)
internal Dictionary<int, Cell> cells = new Dictionary<int, Cell>();
Dictionary<int, CellChunkInfo> m_ChunkInfo = new Dictionary<int, CellChunkInfo>();

internal ProbeVolumeSceneBounds sceneBounds;
internal ProbeVolumeSceneData sceneData;


/// <summary>
Expand Down Expand Up @@ -620,11 +620,11 @@ public void Initialize(in ProbeVolumeSystemParameters parameters)
InitProbeReferenceVolume(kProbeIndexPoolAllocationSize, m_MemoryBudget, m_SHBands);
m_IsInitialized = true;
m_NeedsIndexRebuild = true;
sceneBounds = parameters.sceneBounds;
sceneData = parameters.sceneData;
#if UNITY_EDITOR
if (sceneBounds != null)
if (sceneData != null)
{
UnityEditor.SceneManagement.EditorSceneManager.sceneSaved += sceneBounds.UpdateSceneBounds;
UnityEditor.SceneManagement.EditorSceneManager.sceneSaved += sceneData.OnSceneSaved;
}
#endif
}
Expand Down Expand Up @@ -813,6 +813,11 @@ void LoadAsset(ProbeVolumeAsset asset)

var path = asset.GetSerializedFullPath();

// Load info coming originally from profile
SetTRS(Vector3.zero, Quaternion.identity, asset.minBrickSize);
SetMaxSubdivision(asset.maxSubdivision);


for (int i = 0; i < asset.cells.Count; ++i)
{
var cell = asset.cells[i];
Expand Down
Loading