using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine.Experimental.Rendering.RenderGraphModule;
using UnityEditor;
namespace UnityEngine.Rendering
{
///
/// Modes for Debugging Probes
///
[GenerateHLSL]
public enum DebugProbeShadingMode
{
///
/// Based on Spherical Harmonics
///
SH,
///
/// Based on Spherical Harmonics first band only (ambient)
///
SHL0,
///
/// Based on Spherical Harmonics band zero and one only
///
SHL0L1,
///
/// Based on validity
///
Validity,
///
/// Based on validity over a dilation threshold
///
ValidityOverDilationThreshold,
///
/// Show in red probes that have been made invalid by touchup volumes. Important to note that this debug view will only show result for volumes still present in the scene.
///
InvalidatedByTouchupVolumes,
///
/// Based on size
///
Size
}
class ProbeVolumeDebug : IDebugData
{
public bool drawProbes;
public bool drawBricks;
public bool drawCells;
public bool realtimeSubdivision;
public int subdivisionCellUpdatePerFrame = 4;
public float subdivisionDelayInSeconds = 1;
public DebugProbeShadingMode probeShading;
public float probeSize = 0.3f;
public float subdivisionViewCullingDistance = 500.0f;
public float probeCullingDistance = 200.0f;
public int maxSubdivToVisualize = ProbeBrickIndex.kMaxSubdivisionLevels;
public int minSubdivToVisualize = 0;
public float exposureCompensation;
public bool drawVirtualOffsetPush;
public float offsetSize = 0.025f;
public bool freezeStreaming;
public int otherStateIndex = 0;
public ProbeVolumeDebug()
{
Init();
}
void Init()
{
drawProbes = false;
drawBricks = false;
drawCells = false;
realtimeSubdivision = false;
subdivisionCellUpdatePerFrame = 4;
subdivisionDelayInSeconds = 1;
probeShading = DebugProbeShadingMode.SH;
probeSize = 0.3f;
subdivisionViewCullingDistance = 500.0f;
probeCullingDistance = 200.0f;
maxSubdivToVisualize = ProbeBrickIndex.kMaxSubdivisionLevels;
minSubdivToVisualize = 0;
exposureCompensation = 0.0f;
drawVirtualOffsetPush = false;
offsetSize = 0.025f;
freezeStreaming = false;
otherStateIndex = 0;
}
public Action GetReset() => () => Init();
}
public partial class ProbeReferenceVolume
{
internal class CellInstancedDebugProbes
{
public List probeBuffers;
public List offsetBuffers;
public List props;
}
const int kProbesPerBatch = 511;
/// Name of debug panel for Probe Volume
public static readonly string k_DebugPanelName = "Probe Volume";
internal ProbeVolumeDebug probeVolumeDebug { get; } = new ProbeVolumeDebug();
/// Colors that can be used for debug visualization of the brick structure subdivision.
public Color[] subdivisionDebugColors { get; } = new Color[ProbeBrickIndex.kMaxSubdivisionLevels];
DebugUI.Widget[] m_DebugItems;
Mesh m_DebugMesh;
Material m_DebugMaterial;
Mesh m_DebugOffsetMesh;
Material m_DebugOffsetMaterial;
Plane[] m_DebugFrustumPlanes = new Plane[6];
// Scenario blending debug data
GUIContent[] m_DebugScenarioNames = new GUIContent[0];
int[] m_DebugScenarioValues = new int[0];
string m_DebugActiveSceneGUID, m_DebugActiveScenario;
DebugUI.EnumField m_DebugScenarioField;
internal ProbeVolumeBakingProcessSettings bakingProcessSettings; /* DEFAULTS would be better but is implemented in PR#6174 = ProbeVolumeBakingProcessSettings.Defaults; */
// Field used for the realtime subdivision preview
internal Dictionary realtimeSubdivisionInfo = new ();
bool m_MaxSubdivVisualizedIsMaxAvailable = false;
///
/// Render Probe Volume related debug
///
/// The
public void RenderDebug(Camera camera)
{
if (camera.cameraType != CameraType.Reflection && camera.cameraType != CameraType.Preview)
{
DrawProbeDebug(camera);
}
}
void InitializeDebug(in ProbeVolumeSystemParameters parameters)
{
if (parameters.supportsRuntimeDebug)
{
m_DebugMesh = parameters.probeDebugMesh;
m_DebugMaterial = CoreUtils.CreateEngineMaterial(parameters.probeDebugShader);
m_DebugMaterial.enableInstancing = true;
m_DebugOffsetMesh = parameters.offsetDebugMesh;
m_DebugOffsetMaterial = CoreUtils.CreateEngineMaterial(parameters.offsetDebugShader);
m_DebugOffsetMaterial.enableInstancing = true;
// Hard-coded colors for now.
Debug.Assert(ProbeBrickIndex.kMaxSubdivisionLevels == 7); // Update list if this changes.
subdivisionDebugColors[0] = new Color(1.0f, 0.0f, 0.0f);
subdivisionDebugColors[1] = new Color(0.0f, 1.0f, 0.0f);
subdivisionDebugColors[2] = new Color(0.0f, 0.0f, 1.0f);
subdivisionDebugColors[3] = new Color(1.0f, 1.0f, 0.0f);
subdivisionDebugColors[4] = new Color(1.0f, 0.0f, 1.0f);
subdivisionDebugColors[5] = new Color(0.0f, 1.0f, 1.0f);
subdivisionDebugColors[6] = new Color(0.5f, 0.5f, 0.5f);
}
RegisterDebug(parameters);
#if UNITY_EDITOR
UnityEditor.Lightmapping.lightingDataCleared += OnClearLightingdata;
#endif
}
void CleanupDebug()
{
UnregisterDebug(true);
CoreUtils.Destroy(m_DebugMaterial);
CoreUtils.Destroy(m_DebugOffsetMaterial);
#if UNITY_EDITOR
UnityEditor.Lightmapping.lightingDataCleared -= OnClearLightingdata;
#endif
}
void DebugCellIndexChanged(DebugUI.Field field, T value)
{
ClearDebugData();
}
void RegisterDebug(ProbeVolumeSystemParameters parameters)
{
void RefreshDebug(DebugUI.Field field, T value)
{
UnregisterDebug(false);
RegisterDebug(parameters);
}
const float kProbeSizeMin = 0.05f, kProbeSizeMax = 10.0f;
const float kOffsetSizeMin = 0.001f, kOffsetSizeMax = 0.1f;
var widgetList = new List();
var subdivContainer = new DebugUI.Container() { displayName = "Subdivision Visualization" };
subdivContainer.children.Add(new DebugUI.BoolField { displayName = "Display Cells", getter = () => probeVolumeDebug.drawCells, setter = value => probeVolumeDebug.drawCells = value, onValueChanged = RefreshDebug });
subdivContainer.children.Add(new DebugUI.BoolField { displayName = "Display Bricks", getter = () => probeVolumeDebug.drawBricks, setter = value => probeVolumeDebug.drawBricks = value, onValueChanged = RefreshDebug });
#if UNITY_EDITOR
subdivContainer.children.Add(new DebugUI.BoolField { displayName = "Realtime Update", getter = () => probeVolumeDebug.realtimeSubdivision, setter = value => probeVolumeDebug.realtimeSubdivision = value, onValueChanged = RefreshDebug });
if (probeVolumeDebug.realtimeSubdivision)
{
var cellUpdatePerFrame = new DebugUI.IntField { displayName = "Number Of Cell Update Per Frame", getter = () => probeVolumeDebug.subdivisionCellUpdatePerFrame, setter = value => probeVolumeDebug.subdivisionCellUpdatePerFrame = value, min = () => 1, max = () => 100 };
var delayBetweenUpdates = new DebugUI.FloatField { displayName = "Delay Between Two Updates In Seconds", getter = () => probeVolumeDebug.subdivisionDelayInSeconds, setter = value => probeVolumeDebug.subdivisionDelayInSeconds = value, min = () => 0.1f, max = () => 10 };
subdivContainer.children.Add(new DebugUI.Container { children = { cellUpdatePerFrame, delayBetweenUpdates } });
}
#endif
subdivContainer.children.Add(new DebugUI.FloatField { displayName = "Culling Distance", getter = () => probeVolumeDebug.subdivisionViewCullingDistance, setter = value => probeVolumeDebug.subdivisionViewCullingDistance = value, min = () => 0.0f });
var probeContainer = new DebugUI.Container() { displayName = "Probe Visualization" };
probeContainer.children.Add(new DebugUI.BoolField { displayName = "Display Probes", getter = () => probeVolumeDebug.drawProbes, setter = value => probeVolumeDebug.drawProbes = value, onValueChanged = RefreshDebug });
if (probeVolumeDebug.drawProbes)
{
var probeContainerChildren = new DebugUI.Container();
probeContainerChildren.children.Add(new DebugUI.EnumField
{
displayName = "Probe Shading Mode",
getter = () => (int)probeVolumeDebug.probeShading,
setter = value => probeVolumeDebug.probeShading = (DebugProbeShadingMode)value,
autoEnum = typeof(DebugProbeShadingMode),
getIndex = () => (int)probeVolumeDebug.probeShading,
setIndex = value => probeVolumeDebug.probeShading = (DebugProbeShadingMode)value,
onValueChanged = RefreshDebug
});
probeContainerChildren.children.Add(new DebugUI.FloatField { displayName = "Probe Size", getter = () => probeVolumeDebug.probeSize, setter = value => probeVolumeDebug.probeSize = value, min = () => kProbeSizeMin, max = () => kProbeSizeMax });
if (probeVolumeDebug.probeShading == DebugProbeShadingMode.SH || probeVolumeDebug.probeShading == DebugProbeShadingMode.SHL0 || probeVolumeDebug.probeShading == DebugProbeShadingMode.SHL0L1)
probeContainerChildren.children.Add(new DebugUI.FloatField { displayName = "Probe Exposure Compensation", getter = () => probeVolumeDebug.exposureCompensation, setter = value => probeVolumeDebug.exposureCompensation = value });
probeContainerChildren.children.Add(new DebugUI.IntField
{
displayName = "Max subdivision displayed",
getter = () => probeVolumeDebug.maxSubdivToVisualize,
setter = (v) => probeVolumeDebug.maxSubdivToVisualize = Mathf.Min(v, ProbeReferenceVolume.instance.GetMaxSubdivision() - 1),
min = () => 0,
max = () => ProbeReferenceVolume.instance.GetMaxSubdivision()-1,
});
probeContainerChildren.children.Add(new DebugUI.IntField
{
displayName = "Min subdivision displayed",
getter = () => probeVolumeDebug.minSubdivToVisualize,
setter = (v) => probeVolumeDebug.minSubdivToVisualize = Mathf.Max(v, 0),
min = () => 0,
max = () => ProbeReferenceVolume.instance.GetMaxSubdivision()-1,
});
probeContainer.children.Add(probeContainerChildren);
}
probeContainer.children.Add(new DebugUI.BoolField
{
displayName = "Virtual Offset",
getter = () => probeVolumeDebug.drawVirtualOffsetPush,
setter = value =>
{
probeVolumeDebug.drawVirtualOffsetPush = value;
if (probeVolumeDebug.drawVirtualOffsetPush && probeVolumeDebug.drawProbes)
{
// If probes are being drawn when enabling offset, automatically scale them down to a reasonable size so the arrows aren't obscured by the probes.
var searchDistance = CellSize(0) * MinBrickSize() / ProbeBrickPool.kBrickCellCount * bakingProcessSettings.virtualOffsetSettings.searchMultiplier + bakingProcessSettings.virtualOffsetSettings.outOfGeoOffset;
probeVolumeDebug.probeSize = Mathf.Min(probeVolumeDebug.probeSize, Mathf.Clamp(searchDistance, kProbeSizeMin, kProbeSizeMax));
}
},
onValueChanged = RefreshDebug
});
if (probeVolumeDebug.drawVirtualOffsetPush)
{
var voOffset = new DebugUI.FloatField { displayName = "Offset Size", getter = () => probeVolumeDebug.offsetSize, setter = value => probeVolumeDebug.offsetSize = value, min = () => kOffsetSizeMin, max = () => kOffsetSizeMax };
probeContainer.children.Add(new DebugUI.Container { children = { voOffset } });
}
probeContainer.children.Add(new DebugUI.FloatField { displayName = "Culling Distance", getter = () => probeVolumeDebug.probeCullingDistance, setter = value => probeVolumeDebug.probeCullingDistance = value, min = () => 0.0f });
var streamingContainer = new DebugUI.Container() { displayName = "Streaming" };
streamingContainer.children.Add(new DebugUI.BoolField { displayName = "Freeze Streaming", getter = () => probeVolumeDebug.freezeStreaming, setter = value => probeVolumeDebug.freezeStreaming = value });
streamingContainer.children.Add(new DebugUI.IntField { displayName = "Number Of Cells Loaded Per Frame", getter = () => instance.numberOfCellsLoadedPerFrame, setter = value => instance.SetNumberOfCellsLoadedPerFrame(value), min = () => 0 });
if (parameters.supportsRuntimeDebug)
{
// Cells / Bricks visualization is not implemented in a runtime compatible way atm.
if (Application.isEditor)
widgetList.Add(subdivContainer);
widgetList.Add(probeContainer);
}
if (parameters.supportStreaming)
{
widgetList.Add(streamingContainer);
}
if (parameters.scenarioBlendingShader != null && parameters.blendingMemoryBudget != 0)
{
var blendingContainer = new DebugUI.Container() { displayName = "Scenario Blending" };
blendingContainer.children.Add(new DebugUI.IntField { displayName = "Number Of Cells Blended Per Frame", getter = () => instance.numberOfCellsBlendedPerFrame, setter = value => instance.numberOfCellsBlendedPerFrame = value, min = () => 0 });
blendingContainer.children.Add(new DebugUI.FloatField { displayName = "Turnover Rate", getter = () => instance.turnoverRate, setter = value => instance.turnoverRate = value, min = () => 0, max = () => 1 });
void RefreshScenarioNames(string guid)
{
HashSet allScenarios = new();
foreach (var set in parameters.sceneData.bakingSets)
{
if (!set.sceneGUIDs.Contains(guid))
continue;
foreach (var scenario in set.lightingScenarios)
allScenarios.Add(scenario);
}
allScenarios.Remove(sceneData.lightingScenario);
if (m_DebugActiveSceneGUID == guid && allScenarios.Count + 1 == m_DebugScenarioNames.Length && m_DebugActiveScenario == sceneData.lightingScenario)
return;
int i = 0;
ArrayExtensions.ResizeArray(ref m_DebugScenarioNames, allScenarios.Count + 1);
ArrayExtensions.ResizeArray(ref m_DebugScenarioValues, allScenarios.Count + 1);
m_DebugScenarioNames[0] = new GUIContent("None");
m_DebugScenarioValues[0] = 0;
foreach (var scenario in allScenarios)
{
i++;
m_DebugScenarioNames[i] = new GUIContent(scenario);
m_DebugScenarioValues[i] = i;
}
m_DebugActiveSceneGUID = guid;
m_DebugActiveScenario = sceneData.lightingScenario;
m_DebugScenarioField.enumNames = m_DebugScenarioNames;
m_DebugScenarioField.enumValues = m_DebugScenarioValues;
if (probeVolumeDebug.otherStateIndex >= m_DebugScenarioNames.Length)
probeVolumeDebug.otherStateIndex = 0;
}
m_DebugScenarioField = new DebugUI.EnumField
{
displayName = "Scenario To Blend With",
enumNames = m_DebugScenarioNames,
enumValues = m_DebugScenarioValues,
getIndex = () =>
{
RefreshScenarioNames(ProbeVolumeSceneData.GetSceneGUID(SceneManagement.SceneManager.GetActiveScene()));
probeVolumeDebug.otherStateIndex = 0;
if (!string.IsNullOrEmpty(sceneData.otherScenario))
{
for (int i = 1; i < m_DebugScenarioNames.Length; i++)
{
if (m_DebugScenarioNames[i].text == sceneData.otherScenario)
{
probeVolumeDebug.otherStateIndex = i;
break;
}
}
}
return probeVolumeDebug.otherStateIndex;
},
setIndex = value =>
{
string other = value == 0 ? null : m_DebugScenarioNames[value].text;
sceneData.BlendLightingScenario(other, sceneData.scenarioBlendingFactor);
probeVolumeDebug.otherStateIndex = value;
},
getter = () => probeVolumeDebug.otherStateIndex,
setter = (value) => probeVolumeDebug.otherStateIndex = value,
};
blendingContainer.children.Add(m_DebugScenarioField);
blendingContainer.children.Add(new DebugUI.FloatField { displayName = "Scenario Blending Factor", getter = () => instance.scenarioBlendingFactor, setter = value => instance.scenarioBlendingFactor = value, min = () => 0.0f, max = () => 1.0f });
widgetList.Add(blendingContainer);
}
if (widgetList.Count > 0)
{
m_DebugItems = widgetList.ToArray();
var panel = DebugManager.instance.GetPanel(k_DebugPanelName, true);
panel.children.Add(m_DebugItems);
}
DebugManager debugManager = DebugManager.instance;
debugManager.RegisterData(probeVolumeDebug);
}
void UnregisterDebug(bool destroyPanel)
{
if (destroyPanel)
DebugManager.instance.RemovePanel(k_DebugPanelName);
else
DebugManager.instance.GetPanel(k_DebugPanelName, false).children.Remove(m_DebugItems);
}
bool ShouldCullCell(Vector3 cellPosition, Transform cameraTransform, Plane[] frustumPlanes)
{
var cellSize = MaxBrickSize();
var originWS = GetTransform().posWS;
Vector3 cellCenterWS = cellPosition * cellSize + originWS + Vector3.one * (cellSize / 2.0f);
// We do coarse culling with cell, finer culling later.
float distanceRoundedUpWithCellSize = Mathf.CeilToInt(probeVolumeDebug.probeCullingDistance / cellSize) * cellSize;
if (Vector3.Distance(cameraTransform.position, cellCenterWS) > distanceRoundedUpWithCellSize)
return true;
var volumeAABB = new Bounds(cellCenterWS, cellSize * Vector3.one);
return !GeometryUtility.TestPlanesAABB(frustumPlanes, volumeAABB);
}
void DrawProbeDebug(Camera camera)
{
if (!enabledBySRP || !isInitialized)
return;
if (!probeVolumeDebug.drawProbes && !probeVolumeDebug.drawVirtualOffsetPush)
return;
GeometryUtility.CalculateFrustumPlanes(camera, m_DebugFrustumPlanes);
m_DebugMaterial.shaderKeywords = null;
if (m_SHBands == ProbeVolumeSHBands.SphericalHarmonicsL1)
m_DebugMaterial.EnableKeyword("PROBE_VOLUMES_L1");
else if (m_SHBands == ProbeVolumeSHBands.SphericalHarmonicsL2)
m_DebugMaterial.EnableKeyword("PROBE_VOLUMES_L2");
// This is to force the rendering not to draw to the depth pre pass and still behave.
// They are going to be rendered opaque anyhow, just using the transparent render queue to make sure
// they properly behave w.r.t fog.
m_DebugMaterial.renderQueue = (int)RenderQueue.Transparent;
m_DebugOffsetMaterial.renderQueue = (int)RenderQueue.Transparent;
// Sanitize the min max subdiv levels with what is available
int minAvailableSubdiv = ProbeReferenceVolume.instance.cells.Count > 0 ? ProbeReferenceVolume.instance.GetMaxSubdivision()-1 : 0;
foreach (var cellInfo in ProbeReferenceVolume.instance.cells.Values)
{
minAvailableSubdiv = Mathf.Min(minAvailableSubdiv, cellInfo.cell.minSubdiv);
}
probeVolumeDebug.maxSubdivToVisualize = Mathf.Min(probeVolumeDebug.maxSubdivToVisualize, ProbeReferenceVolume.instance.GetMaxSubdivision() - 1);
m_MaxSubdivVisualizedIsMaxAvailable = probeVolumeDebug.maxSubdivToVisualize == ProbeReferenceVolume.instance.GetMaxSubdivision() - 1;
probeVolumeDebug.minSubdivToVisualize = Mathf.Clamp(probeVolumeDebug.minSubdivToVisualize, minAvailableSubdiv, probeVolumeDebug.maxSubdivToVisualize);
foreach (var cellInfo in ProbeReferenceVolume.instance.cells.Values)
{
if (ShouldCullCell(cellInfo.cell.position, camera.transform, m_DebugFrustumPlanes))
continue;
var debug = CreateInstancedProbes(cellInfo);
if (debug == null)
continue;
for (int i = 0; i < debug.probeBuffers.Count; ++i)
{
var props = debug.props[i];
props.SetInt("_ShadingMode", (int)probeVolumeDebug.probeShading);
props.SetFloat("_ExposureCompensation", probeVolumeDebug.exposureCompensation);
props.SetFloat("_ProbeSize", probeVolumeDebug.probeSize);
props.SetFloat("_CullDistance", probeVolumeDebug.probeCullingDistance);
props.SetInt("_MaxAllowedSubdiv", probeVolumeDebug.maxSubdivToVisualize);
props.SetInt("_MinAllowedSubdiv", probeVolumeDebug.minSubdivToVisualize);
props.SetFloat("_ValidityThreshold", bakingProcessSettings.dilationSettings.dilationValidityThreshold);
props.SetFloat("_OffsetSize", probeVolumeDebug.offsetSize);
if (probeVolumeDebug.drawProbes)
{
var probeBuffer = debug.probeBuffers[i];
Graphics.DrawMeshInstanced(m_DebugMesh, 0, m_DebugMaterial, probeBuffer, probeBuffer.Length, props, ShadowCastingMode.Off, false, 0, camera, LightProbeUsage.Off, null);
}
if (probeVolumeDebug.drawVirtualOffsetPush)
{
var offsetBuffer = debug.offsetBuffers[i];
Graphics.DrawMeshInstanced(m_DebugOffsetMesh, 0, m_DebugOffsetMaterial, offsetBuffer, offsetBuffer.Length, props, ShadowCastingMode.Off, false, 0, camera, LightProbeUsage.Off, null);
}
}
}
}
internal void ResetDebugViewToMaxSubdiv()
{
if (m_MaxSubdivVisualizedIsMaxAvailable)
probeVolumeDebug.maxSubdivToVisualize = ProbeReferenceVolume.instance.GetMaxSubdivision() - 1;
}
void ClearDebugData()
{
realtimeSubdivisionInfo.Clear();
}
CellInstancedDebugProbes CreateInstancedProbes(CellInfo cellInfo)
{
if (cellInfo.debugProbes != null)
return cellInfo.debugProbes;
int maxSubdiv = ProbeReferenceVolume.instance.GetMaxSubdivision() - 1;
var cell = cellInfo.cell;
if (!cell.bricks.IsCreated || cell.bricks.Length == 0 || !cellInfo.loaded)
return null;
List probeBuffers = new List();
List offsetBuffers = new List();
List props = new List();
var chunks = cellInfo.chunkList;
Vector4[] texels = new Vector4[kProbesPerBatch];
float[] validity = new float[kProbesPerBatch];
float[] relativeSize = new float[kProbesPerBatch];
float[] touchupUpVolumeAction = cell.touchupVolumeInteraction.Length > 0 ? new float[kProbesPerBatch] : null;
Vector4[] offsets = cell.offsetVectors.Length > 0 ? new Vector4[kProbesPerBatch] : null;
List probeBuffer = new List();
List offsetBuffer = new List();
var debugData = new CellInstancedDebugProbes();
debugData.probeBuffers = probeBuffers;
debugData.offsetBuffers = offsetBuffers;
debugData.props = props;
var chunkSizeInProbes = m_CurrentProbeVolumeChunkSizeInBricks * ProbeBrickPool.kBrickProbeCountTotal;
var loc = ProbeBrickPool.ProbeCountToDataLocSize(chunkSizeInProbes);
int idxInBatch = 0;
int globalIndex = 0;
int brickCount = cell.probeCount / ProbeBrickPool.kBrickProbeCountTotal;
int bx = 0, by = 0, bz = 0;
for (int brickIndex = 0; brickIndex < brickCount; ++brickIndex)
{
Debug.Assert(bz < loc.z);
int brickSize = cell.bricks[brickIndex].subdivisionLevel;
int chunkIndex = brickIndex / m_CurrentProbeVolumeChunkSizeInBricks;
var chunk = chunks[chunkIndex];
Vector3Int brickStart = new Vector3Int(chunk.x + bx, chunk.y + by, chunk.z + bz);
for (int z = 0; z < ProbeBrickPool.kBrickProbeCountPerDim; ++z)
{
for (int y = 0; y < ProbeBrickPool.kBrickProbeCountPerDim; ++y)
{
for (int x = 0; x < ProbeBrickPool.kBrickProbeCountPerDim; ++x)
{
Vector3Int texelLoc = new Vector3Int(brickStart.x + x, brickStart.y + y, brickStart.z + z);
int probeFlatIndex = chunkIndex * chunkSizeInProbes + (bx + x) + loc.x * ((by + y) + loc.y * (bz + z));
probeBuffer.Add(Matrix4x4.TRS(cell.probePositions[probeFlatIndex], Quaternion.identity, Vector3.one * (0.3f * (brickSize + 1))));
validity[idxInBatch] = cell.validity[probeFlatIndex];
texels[idxInBatch] = new Vector4(texelLoc.x, texelLoc.y, texelLoc.z, brickSize);
relativeSize[idxInBatch] = (float)brickSize / (float)maxSubdiv;
if (touchupUpVolumeAction != null)
{
touchupUpVolumeAction[idxInBatch] = cell.touchupVolumeInteraction[probeFlatIndex];
}
if (offsets != null)
{
const float kOffsetThresholdSqr = 1e-6f;
var offset = cell.offsetVectors[probeFlatIndex];
offsets[idxInBatch] = offset;
if (offset.sqrMagnitude < kOffsetThresholdSqr)
{
offsetBuffer.Add(Matrix4x4.identity);
}
else
{
var position = cell.probePositions[probeFlatIndex] + offset;
var orientation = Quaternion.LookRotation(-offset);
var scale = new Vector3(0.5f, 0.5f, offset.magnitude);
offsetBuffer.Add(Matrix4x4.TRS(position, orientation, scale));
}
}
idxInBatch++;
if (probeBuffer.Count >= kProbesPerBatch || globalIndex == cell.probeCount - 1)
{
idxInBatch = 0;
MaterialPropertyBlock prop = new MaterialPropertyBlock();
prop.SetFloatArray("_Validity", validity);
prop.SetFloatArray("_TouchupedByVolume", touchupUpVolumeAction);
prop.SetFloatArray("_RelativeSize", relativeSize);
prop.SetVectorArray("_IndexInAtlas", texels);
if (offsets != null)
prop.SetVectorArray("_Offset", offsets);
props.Add(prop);
probeBuffers.Add(probeBuffer.ToArray());
probeBuffer = new List();
probeBuffer.Clear();
offsetBuffers.Add(offsetBuffer.ToArray());
offsetBuffer.Clear();
}
globalIndex++;
}
}
}
bx += ProbeBrickPool.kBrickProbeCountPerDim;
if (bx >= loc.x)
{
bx = 0;
by += ProbeBrickPool.kBrickProbeCountPerDim;
if (by >= loc.y)
{
by = 0;
bz += ProbeBrickPool.kBrickProbeCountPerDim;
if (bz >= loc.z)
{
bx = 0;
by = 0;
bz = 0;
}
}
}
}
cellInfo.debugProbes = debugData;
return debugData;
}
void OnClearLightingdata()
{
ClearDebugData();
}
}
}