Skip to content

Commit fde63d2

Browse files
Fix APV seams between cells. (#4429)
* Properly clear debug data when clearing baked lighting data. * All probes are now baked together for a baking batch * Fixed probe remapping per cell * Removed hard coded baking batch index.
1 parent 6e65f23 commit fde63d2

File tree

2 files changed

+89
-49
lines changed

2 files changed

+89
-49
lines changed

com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs

Lines changed: 71 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,39 @@ struct BakingCell
3333
{
3434
public ProbeReferenceVolume.Cell cell;
3535
public int[] probeIndices;
36-
public int numUniqueProbes;
36+
}
37+
38+
class BakingBatch
39+
{
40+
public int index;
41+
public Dictionary<int, List<Scene>> cellIndex2SceneReferences = new Dictionary<int, List<Scene>>();
42+
public List<BakingCell> cells = new List<BakingCell>();
43+
public Dictionary<Vector3, int> uniquePositions = new Dictionary<Vector3, int>();
44+
45+
private BakingBatch() {}
46+
47+
public BakingBatch(int index)
48+
{
49+
this.index = index;
50+
}
51+
52+
public void Clear()
53+
{
54+
UnityEditor.Experimental.Lightmapping.SetAdditionalBakedProbes(index, null);
55+
cells.Clear();
56+
cellIndex2SceneReferences.Clear();
57+
}
58+
59+
public int uniqueProbeCount => uniquePositions.Keys.Count;
3760
}
3861

3962
[InitializeOnLoad]
40-
internal class ProbeGIBaking
63+
class ProbeGIBaking
4164
{
42-
private static bool init = false;
43-
private static Dictionary<int, List<Scene>> cellIndex2SceneReferences = new Dictionary<int, List<Scene>>();
44-
private static List<BakingCell> bakingCells = new List<BakingCell>();
45-
private static ProbeReferenceVolumeAuthoring bakingReferenceVolumeAuthoring = null;
65+
static bool m_IsInit = false;
66+
static BakingBatch m_BakingBatch;
67+
static ProbeReferenceVolumeAuthoring m_BakingReferenceVolumeAuthoring = null;
68+
static int m_BakingBatchIndex = 0;
4669

4770
static ProbeGIBaking()
4871
{
@@ -51,9 +74,9 @@ static ProbeGIBaking()
5174

5275
public static void Init()
5376
{
54-
if (!init)
77+
if (!m_IsInit)
5578
{
56-
init = true;
79+
m_IsInit = true;
5780
Lightmapping.lightingDataCleared += OnLightingDataCleared;
5881
Lightmapping.bakeStarted += OnBakeStarted;
5982
}
@@ -76,14 +99,10 @@ static public void Clear()
7699
refVol.SetMaxSubdivision(refVolAuthoring.maxSubdivision);
77100
}
78101

79-
cellIndex2SceneReferences.Clear();
102+
if (m_BakingBatch != null)
103+
m_BakingBatch.Clear();
80104

81-
foreach (var bakingCell in bakingCells)
82-
{
83-
UnityEditor.Experimental.Lightmapping.SetAdditionalBakedProbes(bakingCell.cell.index, null);
84-
}
85-
86-
bakingCells.Clear();
105+
m_BakingBatchIndex = 0;
87106
}
88107

89108
private static ProbeReferenceVolumeAuthoring GetCardinalAuthoringComponent(ProbeReferenceVolumeAuthoring[] refVolAuthList)
@@ -129,9 +148,9 @@ private static void OnBakeStarted()
129148
if (refVolAuthList.Length == 0)
130149
return;
131150

132-
bakingReferenceVolumeAuthoring = GetCardinalAuthoringComponent(refVolAuthList);
151+
m_BakingReferenceVolumeAuthoring = GetCardinalAuthoringComponent(refVolAuthList);
133152

134-
if (bakingReferenceVolumeAuthoring == null)
153+
if (m_BakingReferenceVolumeAuthoring == null)
135154
{
136155
Debug.Log("Scene(s) have multiple inconsistent ProbeReferenceVolumeAuthoring components. Please ensure they use identical profiles and transforms before baking.");
137156
return;
@@ -144,8 +163,17 @@ private static void OnAdditionalProbesBakeCompleted()
144163
{
145164
UnityEditor.Experimental.Lightmapping.additionalBakedProbesCompleted -= OnAdditionalProbesBakeCompleted;
146165

166+
var bakingCells = m_BakingBatch.cells;
147167
var numCells = bakingCells.Count;
148168

169+
int numUniqueProbes = m_BakingBatch.uniqueProbeCount;
170+
171+
var sh = new NativeArray<SphericalHarmonicsL2>(numUniqueProbes, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
172+
var validity = new NativeArray<float>(numUniqueProbes, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
173+
var bakedProbeOctahedralDepth = new NativeArray<float>(numUniqueProbes * 64, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
174+
175+
UnityEditor.Experimental.Lightmapping.GetAdditionalBakedProbes(m_BakingBatch.index, sh, validity, bakedProbeOctahedralDepth);
176+
149177
// Fetch results of all cells
150178
for (int c = 0; c < numCells; ++c)
151179
{
@@ -157,14 +185,6 @@ private static void OnAdditionalProbesBakeCompleted()
157185
int numProbes = cell.probePositions.Length;
158186
Debug.Assert(numProbes > 0);
159187

160-
int numUniqueProbes = bakingCells[c].numUniqueProbes;
161-
162-
var sh = new NativeArray<SphericalHarmonicsL2>(numUniqueProbes, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
163-
var validity = new NativeArray<float>(numUniqueProbes, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
164-
var bakedProbeOctahedralDepth = new NativeArray<float>(numUniqueProbes * 64, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
165-
166-
UnityEditor.Experimental.Lightmapping.GetAdditionalBakedProbes(cell.index, sh, validity, bakedProbeOctahedralDepth);
167-
168188
cell.sh = new SphericalHarmonicsL2[numProbes];
169189
cell.validity = new float[numProbes];
170190

@@ -218,14 +238,16 @@ private static void OnAdditionalProbesBakeCompleted()
218238
cell.validity[i] = validity[j];
219239
}
220240

221-
// Reset index
222-
UnityEditor.Experimental.Lightmapping.SetAdditionalBakedProbes(cell.index, null);
223-
224-
DilateInvalidProbes(cell.probePositions, cell.bricks, cell.sh, cell.validity, bakingReferenceVolumeAuthoring.GetDilationSettings());
241+
DilateInvalidProbes(cell.probePositions, cell.bricks, cell.sh, cell.validity, m_BakingReferenceVolumeAuthoring.GetDilationSettings());
225242

226243
ProbeReferenceVolume.instance.cells[cell.index] = cell;
227244
}
228245

246+
m_BakingBatchIndex = 0;
247+
248+
// Reset index
249+
UnityEditor.Experimental.Lightmapping.SetAdditionalBakedProbes(m_BakingBatch.index, null);
250+
229251
// Map from each scene to an existing reference volume
230252
var scene2RefVol = new Dictionary<Scene, ProbeReferenceVolumeAuthoring>();
231253
foreach (var refVol in GameObject.FindObjectsOfType<ProbeReferenceVolumeAuthoring>())
@@ -242,7 +264,7 @@ private static void OnAdditionalProbesBakeCompleted()
242264
// Put cells into the respective assets
243265
foreach (var cell in ProbeReferenceVolume.instance.cells.Values)
244266
{
245-
foreach (var scene in cellIndex2SceneReferences[cell.index])
267+
foreach (var scene in m_BakingBatch.cellIndex2SceneReferences[cell.index])
246268
{
247269
// This scene has a reference volume authoring component in it?
248270
ProbeReferenceVolumeAuthoring refVol = null;
@@ -437,12 +459,11 @@ private static void FindNearProbes(int probeIdx, Vector3[] probePositions,
437459
}
438460
}
439461

440-
private static void DeduplicateProbePositions(in Vector3[] probePositions, out Vector3[] deduplicatedProbePositions, out int[] indices)
462+
private static void DeduplicateProbePositions(in Vector3[] probePositions, Dictionary<Vector3, int> uniquePositions, out int[] indices)
441463
{
442-
var uniquePositions = new Dictionary<Vector3, int>();
443464
indices = new int[probePositions.Length];
465+
int uniqueIndex = uniquePositions.Count;
444466

445-
int uniqueIndex = 0;
446467
for (int i = 0; i < probePositions.Length; i++)
447468
{
448469
var pos = probePositions[i];
@@ -458,8 +479,6 @@ private static void DeduplicateProbePositions(in Vector3[] probePositions, out V
458479
uniqueIndex++;
459480
}
460481
}
461-
462-
deduplicatedProbePositions = uniquePositions.Keys.ToArray();
463482
}
464483

465484
public static void RunPlacement()
@@ -470,8 +489,8 @@ public static void RunPlacement()
470489

471490
UnityEditor.Experimental.Lightmapping.additionalBakedProbesCompleted += OnAdditionalProbesBakeCompleted;
472491

473-
var volumeScale = bakingReferenceVolumeAuthoring.transform.localScale;
474-
var CellSize = bakingReferenceVolumeAuthoring.cellSize;
492+
var volumeScale = m_BakingReferenceVolumeAuthoring.transform.localScale;
493+
var CellSize = m_BakingReferenceVolumeAuthoring.cellSize;
475494
var xCells = (int)Mathf.Ceil(volumeScale.x / CellSize);
476495
var yCells = (int)Mathf.Ceil(volumeScale.y / CellSize);
477496
var zCells = (int)Mathf.Ceil(volumeScale.z / CellSize);
@@ -486,6 +505,10 @@ public static void RunPlacement()
486505
cellPositions.Add(new Vector3Int(x, y, z));
487506

488507
int index = 0;
508+
// For now we just have one baking batch. Later we'll have more than one for a set of scenes.
509+
// All probes need to be baked only once for the whole batch and not once per cell
510+
// The reason is that the baker is not deterministic so the same probe position baked in two different cells may have different values causing seams artefacts.
511+
m_BakingBatch = new BakingBatch(m_BakingBatchIndex++);
489512

490513
// subdivide and create positions and add them to the bake queue
491514
foreach (var cellPos in cellPositions)
@@ -498,15 +521,15 @@ public static void RunPlacement()
498521
var cellTrans = Matrix4x4.TRS(refVolTransform.posWS, refVolTransform.rot, Vector3.one);
499522

500523
//BakeMesh[] bakeMeshes = GetEntityQuery(typeof(BakeMesh)).ToComponentDataArray<BakeMesh>();
501-
Renderer[] renderers = UnityEngine.Object.FindObjectsOfType<Renderer>();
502-
ProbeVolume[] probeVolumes = UnityEngine.Object.FindObjectsOfType<ProbeVolume>();
524+
Renderer[] renderers = Object.FindObjectsOfType<Renderer>();
525+
ProbeVolume[] probeVolumes = Object.FindObjectsOfType<ProbeVolume>();
503526

504527
// Calculate the cell volume:
505528
ProbeReferenceVolume.Volume cellVolume = new ProbeReferenceVolume.Volume();
506-
cellVolume.corner = new Vector3(cellPos.x * bakingReferenceVolumeAuthoring.cellSize, cellPos.y * bakingReferenceVolumeAuthoring.cellSize, cellPos.z * bakingReferenceVolumeAuthoring.cellSize);
507-
cellVolume.X = new Vector3(bakingReferenceVolumeAuthoring.cellSize, 0, 0);
508-
cellVolume.Y = new Vector3(0, bakingReferenceVolumeAuthoring.cellSize, 0);
509-
cellVolume.Z = new Vector3(0, 0, bakingReferenceVolumeAuthoring.cellSize);
529+
cellVolume.corner = new Vector3(cellPos.x * m_BakingReferenceVolumeAuthoring.cellSize, cellPos.y * m_BakingReferenceVolumeAuthoring.cellSize, cellPos.z * m_BakingReferenceVolumeAuthoring.cellSize);
530+
cellVolume.X = new Vector3(m_BakingReferenceVolumeAuthoring.cellSize, 0, 0);
531+
cellVolume.Y = new Vector3(0, m_BakingReferenceVolumeAuthoring.cellSize, 0);
532+
cellVolume.Z = new Vector3(0, 0, m_BakingReferenceVolumeAuthoring.cellSize);
510533
cellVolume.Transform(cellTrans);
511534

512535
// In this max subdiv field, we store the minimum subdivision possible for the cell, then, locally we can subdivide more based on the probe volumes subdiv multiplier
@@ -530,22 +553,21 @@ public static void RunPlacement()
530553
if (probePositionsArr.Length > 0 && bricks.Count > 0)
531554
{
532555
int[] indices = null;
533-
Vector3[] deduplicatedProbePositions = null;
534-
DeduplicateProbePositions(in probePositionsArr, out deduplicatedProbePositions, out indices);
556+
DeduplicateProbePositions(in probePositionsArr, m_BakingBatch.uniquePositions, out indices);
535557

536-
UnityEditor.Experimental.Lightmapping.SetAdditionalBakedProbes(cell.index, deduplicatedProbePositions);
537558
cell.probePositions = probePositionsArr;
538559
cell.bricks = bricks;
539560

540561
BakingCell bakingCell = new BakingCell();
541562
bakingCell.cell = cell;
542563
bakingCell.probeIndices = indices;
543-
bakingCell.numUniqueProbes = deduplicatedProbePositions.Length;
544564

545-
bakingCells.Add(bakingCell);
546-
cellIndex2SceneReferences[cell.index] = new List<Scene>(sortedRefs.Values);
565+
m_BakingBatch.cells.Add(bakingCell);
566+
m_BakingBatch.cellIndex2SceneReferences[cell.index] = new List<Scene>(sortedRefs.Values);
547567
}
548568
}
569+
570+
UnityEditor.Experimental.Lightmapping.SetAdditionalBakedProbes(m_BakingBatch.index, m_BakingBatch.uniquePositions.Keys.ToArray());
549571
}
550572
}
551573
}

com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.Debug.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,20 @@ void InitializeDebug(Mesh debugProbeMesh, Shader debugProbeShader)
7777
subdivisionDebugColors[6] = new Color(0.5f, 0.5f, 0.5f);
7878

7979
RegisterDebug();
80+
81+
#if UNITY_EDITOR
82+
UnityEditor.Lightmapping.lightingDataCleared += OnClearLightingdata;
83+
#endif
8084
}
8185

8286
void CleanupDebug()
8387
{
8488
UnregisterDebug(true);
8589
CoreUtils.Destroy(m_DebugMaterial);
90+
91+
#if UNITY_EDITOR
92+
UnityEditor.Lightmapping.lightingDataCleared -= OnClearLightingdata;
93+
#endif
8694
}
8795

8896
void RefreshDebug<T>(DebugUI.Field<T> field, T value)
@@ -91,6 +99,11 @@ void RefreshDebug<T>(DebugUI.Field<T> field, T value)
9199
RegisterDebug();
92100
}
93101

102+
void DebugCellIndexChanged<T>(DebugUI.Field<T> field, T value)
103+
{
104+
ClearDebugData();
105+
}
106+
94107
void RegisterDebug()
95108
{
96109
var widgetList = new List<DebugUI.Widget>();
@@ -250,5 +263,10 @@ void CreateInstancedProbes()
250263
m_CellDebugData.Add(debugData);
251264
}
252265
}
266+
267+
void OnClearLightingdata()
268+
{
269+
ClearDebugData();
270+
}
253271
}
254272
}

0 commit comments

Comments
 (0)