Removing clustering. Replaced by separation of axes

This commit is contained in:
2025-10-21 22:50:36 +02:00
parent 16ffd2cb57
commit 7031d8ad5e
5 changed files with 209 additions and 676 deletions

View File

@ -1,81 +1,91 @@
// VoxelBatchCluster.compute
#pragma kernel AccumulateHits
#pragma kernel ComputeMeans
// SpatialGridCluster.compute
#pragma kernel Accumulate
#pragma kernel Reduce
// ---- Structures ----
struct BatchData
{
float3 position;
float3 origin;
float maxDistance;
};
// ---- Constantes ----
#define GRID_SIZE 8192 // nombre total de cellules max
#define GRID_PRIME1 73856093 // pour hash
#define GRID_PRIME2 19349663
#define GRID_PRIME3 83492791
#define SCALE 1000.0
StructuredBuffer<BatchData> batchDatas;
RWStructuredBuffer<uint> cellCount;
RWStructuredBuffer<uint> cellDistanceSum;
AppendStructuredBuffer<BatchData> clusteredBatches;
// ---- Buffers ----
StructuredBuffer<BatchData> inputHits;
float3 gridMin;
float3 gridMax;
int3 gridResolution;
float3 cellSize;
int startIndex;
RWStructuredBuffer<int4> cellSums; // xyz = somme positions, w = somme maxDistance
RWStructuredBuffer<uint> cellCounts; // nombre d'éléments par cellule
AppendStructuredBuffer<BatchData> clusteredHits;
#define DIST_SCALE 100.0
#define THREADS 64
// ---- Params ----
float cellSize; // taille d'une cellule (distance seuil)
uint inputCount; // nombre d'éléments d'entrée
float3 gridOrigin; // origine du monde pour le hash
// ----------------------
// === KERNEL 1 : ACCUMULATION OPTIMISÉE ===
// ----------------------
groupshared uint localCellCount[THREADS];
groupshared uint localCellSum[THREADS];
// ---- Utilitaires ----
uint HashCell(int3 cell)
[numthreads(THREADS, 1, 1)]
void Accumulate(uint3 id : SV_DispatchThreadID, uint3 groupId : SV_GroupID, uint3 localId : SV_GroupThreadID)
{
uint h = (uint)((cell.x * GRID_PRIME1) ^ (cell.y * GRID_PRIME2) ^ (cell.z * GRID_PRIME3));
return h % GRID_SIZE;
uint index = id.x + startIndex;
if (index >= batchDatas.Length) return;
BatchData b = batchDatas[index];
// Position relative dans la grille
float3 rel = (b.origin - gridMin) / (gridMax - gridMin);
int3 cell = clamp(int3(rel * gridResolution), 0, gridResolution - 1);
// Index 1D de la cellule
uint cellIndex = cell.x + cell.y * gridResolution.x + cell.z * gridResolution.x * gridResolution.y;
// Initialiser le groupe partagé pour ce thread
localCellCount[localId.x] = 0;
localCellSum[localId.x] = 0;
GroupMemoryBarrierWithGroupSync();
// Accumulation locale
localCellCount[localId.x] += 1;
localCellSum[localId.x] += (uint)(b.maxDistance * DIST_SCALE + 0.5);
GroupMemoryBarrierWithGroupSync();
// Écriture atomique unique par thread vers le buffer global
InterlockedAdd(cellCount[cellIndex], localCellCount[localId.x]);
InterlockedAdd(cellDistanceSum[cellIndex], localCellSum[localId.x]);
}
// ---- Kernel 1 : Accumulation ----
// Constante déchelle
[numthreads(64,1,1)]
void AccumulateHits(uint3 id : SV_DispatchThreadID)
// ----------------------
// === KERNEL 2 : REDUCTION ===
// ----------------------
[numthreads(THREADS, 1, 1)]
void Reduce(uint3 id : SV_DispatchThreadID)
{
uint i = id.x;
if (i >= inputCount) return;
uint index = id.x;
uint totalCells = gridResolution.x * gridResolution.y * gridResolution.z;
BatchData b = inputHits[i];
if (index >= totalCells) return;
int3 cell = int3(floor((b.position - gridOrigin) / cellSize));
uint hash = HashCell(cell);
// Conversion float -> int
int3 posInt = int3(b.position * SCALE);
int maxDistInt = (int)(b.maxDistance * SCALE);
// Ajout atomique
InterlockedAdd(cellSums[hash].x, posInt.x);
InterlockedAdd(cellSums[hash].y, posInt.y);
InterlockedAdd(cellSums[hash].z, posInt.z);
InterlockedAdd(cellSums[hash].w, maxDistInt);
InterlockedAdd(cellCounts[hash], 1);
}
// ---- Kernel 2 : Calcul des moyennes ----
[numthreads(64,1,1)]
void ComputeMeans(uint3 id : SV_DispatchThreadID)
{
uint i = id.x;
if (i >= GRID_SIZE) return;
uint count = cellCounts[i];
uint count = cellCount[index];
if (count == 0) return;
int4 sum = cellSums[i];
uint sumScaled = cellDistanceSum[index];
float avgDistance = (float(sumScaled) / float(count)) / DIST_SCALE;
BatchData outB;
outB.position = (float3(sum.xyz) / SCALE) / count;
outB.maxDistance = (float(sum.w) / SCALE) / count;
uint3 coord;
coord.x = index % gridResolution.x;
coord.y = (index / gridResolution.x) % gridResolution.y;
coord.z = index / (gridResolution.x * gridResolution.y);
clusteredHits.Append(outB);
float3 center = gridMin + (float3(coord) + 0.5) * cellSize;
BatchData b;
b.origin = center;
b.maxDistance = avgDistance;
clusteredBatches.Append(b);
}

View File

@ -69,6 +69,8 @@ float3 rootCenter;
float rootHalfSize;
int rootIndex;
int startIndexY;
float3 ClosestPointOnAABB(float3 hitPos, float3 boxCenter, float halfSize)
{
float3 minB = boxCenter - halfSize;
@ -139,7 +141,7 @@ inline bool IntersectAABB_fast(
void CSMain(uint3 id : SV_DispatchThreadID)
{
uint rayIndex = id.x;
uint batchIndex = id.y;
uint batchIndex = id.y + startIndexY;
if (rayIndex >= rays.Length || batchIndex >= batchDatas.Length) return;
RayData r = rays[rayIndex];

View File

@ -244,228 +244,6 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::AudioObject
audioMaterialSettings: {fileID: 11400000, guid: 58ebbfa597f7b56499162cc5660da3ba, type: 2}
--- !u!1 &428183757
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 428183761}
- component: {fileID: 428183760}
- component: {fileID: 428183759}
- component: {fileID: 428183758}
m_Layer: 0
m_Name: Cube (2)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!65 &428183758
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 428183757}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Size: {x: 1, y: 1, z: 1}
m_Center: {x: 0, y: 0, z: 0}
--- !u!23 &428183759
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 428183757}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!33 &428183760
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 428183757}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!4 &428183761
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 428183757}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 19.35913, y: 9.19515, z: 43.9}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &450236051
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 450236055}
- component: {fileID: 450236054}
- component: {fileID: 450236053}
- component: {fileID: 450236052}
m_Layer: 0
m_Name: Cube (5)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!65 &450236052
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 450236051}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Size: {x: 1, y: 1, z: 1}
m_Center: {x: 0, y: 0, z: 0}
--- !u!23 &450236053
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 450236051}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!33 &450236054
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 450236051}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!4 &450236055
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 450236051}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 20.352, y: 9.19515, z: 44.904}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &464574962
GameObject:
m_ObjectHideFlags: 0
@ -560,117 +338,6 @@ MonoBehaviour:
emptyColor: {r: 0, g: 0.5, b: 1, a: 0.2}
solidColor: {r: 1, g: 0, b: 0, a: 0.5}
mixedColor: {r: 1, g: 1, b: 0, a: 0.4}
--- !u!1 &612412859
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 612412863}
- component: {fileID: 612412862}
- component: {fileID: 612412861}
- component: {fileID: 612412860}
m_Layer: 0
m_Name: Cube (6)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!65 &612412860
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 612412859}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Size: {x: 1, y: 1, z: 1}
m_Center: {x: 0, y: 0, z: 0}
--- !u!23 &612412861
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 612412859}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!33 &612412862
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 612412859}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!4 &612412863
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 612412859}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 18.363, y: 9.19515, z: 41.884}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &705507993
GameObject:
m_ObjectHideFlags: 0
@ -768,7 +435,7 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
--- !u!1 &864920249
--- !u!1 &711765669
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
@ -776,104 +443,24 @@ GameObject:
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 864920253}
- component: {fileID: 864920252}
- component: {fileID: 864920251}
- component: {fileID: 864920250}
- component: {fileID: 711765670}
m_Layer: 0
m_Name: Cube (3)
m_Name: GameObject
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!65 &864920250
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 864920249}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Size: {x: 1, y: 1, z: 1}
m_Center: {x: 0, y: 0, z: 0}
--- !u!23 &864920251
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 864920249}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!33 &864920252
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 864920249}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!4 &864920253
--- !u!4 &711765670
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 864920249}
m_GameObject: {fileID: 711765669}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 18.363, y: 9.19515, z: 42.918}
m_LocalPosition: {x: 50, y: 50, z: 50}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
@ -1349,117 +936,6 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: -53.013, z: 0}
--- !u!1 &2077705879
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2077705883}
- component: {fileID: 2077705882}
- component: {fileID: 2077705881}
- component: {fileID: 2077705880}
m_Layer: 0
m_Name: Cube (4)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!65 &2077705880
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2077705879}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Size: {x: 1, y: 1, z: 1}
m_Center: {x: 0, y: 0, z: 0}
--- !u!23 &2077705881
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2077705879}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!33 &2077705882
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2077705879}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!4 &2077705883
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2077705879}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 21.35913, y: 9.19515, z: 45.902}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1660057539 &9223372036854775807
SceneRoots:
m_ObjectHideFlags: 0
@ -1470,9 +946,5 @@ SceneRoots:
- {fileID: 1376698039}
- {fileID: 1629958729}
- {fileID: 464574964}
- {fileID: 428183761}
- {fileID: 864920253}
- {fileID: 612412863}
- {fileID: 2077705883}
- {fileID: 450236055}
- {fileID: 1273284507}
- {fileID: 711765670}

View File

@ -29,18 +29,18 @@ public class Player : MonoBehaviour
void Cast( ref VoxelRaycastGPU.BatchData[] batchData, int batchCount, int iIteration )
{
ComputeBuffer hitBuffer = new ComputeBuffer(rayCount * batchCount, Marshal.SizeOf(typeof(VoxelRaycastGPU.Hit)), ComputeBufferType.Append);
Stopwatch sw = Stopwatch.StartNew();
totalCastDone += batchCount * rayCount;
VoxelRaycastGPU.BatchData[] hits = voxelManager.CastGpuRay(in batchData, batchCount);
/*for( int i = 0; i < hits.Length; i++ )
/**
for( int i = 0; i < hits.Length; i++ )
{
GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
sphere.transform.position = hits[i].origin;
sphere.transform.localScale = Vector3.one * 0.5f;
}*/
}
*/
sw.Stop();
}

View File

@ -15,10 +15,11 @@ public class VoxelRaycastGpuManager
//--------------- RayCasts ------------------------------------------------------
int kernel;
ComputeBuffer datasBuffer;
ComputeBuffer datasBuffer = null;
ComputeBuffer hitCounterBuffer = null;
ComputeBuffer rayBuffer = null;
ComputeBuffer hitBuffer;
ComputeBuffer hitBuffer = null;
ComputeBuffer countBuffer = null;
int raysPerBatch;
@ -28,11 +29,15 @@ public class VoxelRaycastGpuManager
int maxRaycastPerIteration;
int threadsY = 8;
int maxGroupsY = 65535;
//--------------- Clustering ------------------------------------------------------
ComputeShader clusteringShader;
int accumulationKernel;
int reductionKernel;
int gridSize;
int threadCount = 64;
int groupCountHits;
@ -54,8 +59,6 @@ public class VoxelRaycastGpuManager
public VoxelRaycastGPU.BatchData[] Raycast(in VoxelRaycastGPU.BatchData[] batchData, int datasLenght)
{
ComputeBuffer countBuffer = new ComputeBuffer(1, sizeof(int), ComputeBufferType.Raw);
int iteration = 0;
int currentCount = datasLenght;
int previousCount = datasLenght;
@ -71,27 +74,52 @@ public class VoxelRaycastGpuManager
raycastShader.SetBuffer(kernel, "batchDatas", datasBuffer );
raycastShader.SetBuffer(kernel, "hits", hitBuffer);
int threadsY = 8;
int groupsY = Mathf.CeilToInt((float)currentCount / threadsY);
/**
Stopwatch sw = Stopwatch.StartNew();
raycastShader.Dispatch(kernel, groupsX, groupsY, 1);
*/
for (int y = 0; y < currentCount; y += threadsY * maxGroupsY)
{
int remaining = currentCount - y;
int dispatchGroupsY = Mathf.CeilToInt(Mathf.Min(remaining / (float)threadsY, maxGroupsY));
raycastShader.SetInt("startIndexY", y);
raycastShader.Dispatch(kernel, groupsX, dispatchGroupsY, 1);
}
ComputeBuffer.CopyCount(hitBuffer, countBuffer, 0);
int[] countArr = new int[1];
countBuffer.GetData(countArr);
currentCount = countArr[0];
/**
VoxelRaycastGPU.BatchData[] hits = new VoxelRaycastGPU.BatchData[currentCount];
hitBuffer.GetData(hits, 0, 0, currentCount);
for( int i = 0; i < hits.Length; i++ )
{
GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
sphere.transform.position = hits[i].origin;
sphere.transform.localScale = Vector3.one * 0.5f;
}
*/
/**
sw.Stop();
UnityEngine.Debug.Log($"Dispatch done in {sw.Elapsed.TotalMilliseconds}ms for {previousCount*raysPerBatch} casts retrieving {currentCount} hits");
*/
if (currentCount > 0)
iteration++;
if (currentCount > 0 && iteration < 5)
{
datasBuffer = hitBuffer;
/**
if (currentCount * raysPerBatch > maxRaycastPerIteration && iteration < 5)
{
sw = Stopwatch.StartNew();
currentCount = Clustering(currentCount);
currentCount = Clustering( maxRaycastPerIteration / raysPerBatch);
sw.Stop();
UnityEngine.Debug.Log($"Clustering done in {sw.Elapsed.TotalMilliseconds}ms for {currentCount} casts");
@ -105,27 +133,15 @@ public class VoxelRaycastGpuManager
sphere.transform.position = hits[i].origin;
sphere.transform.localScale = Vector3.one * 0.5f;
}
}
else
{
datasBuffer = hitBuffer;
}
*/
}
iteration++;
}
VoxelRaycastGPU.BatchData[] result = new VoxelRaycastGPU.BatchData[previousCount];
if (currentCount == 0)
datasBuffer.GetData(result, 0, 0, previousCount);
else
hitBuffer.GetData(result, 0, 0, previousCount);
countBuffer.Release();
return result;
}
@ -134,6 +150,8 @@ public class VoxelRaycastGpuManager
maxRaycastPerIteration = 1000000;
raysPerBatch = nbRaysPerBatch;
countBuffer = new ComputeBuffer(1, sizeof(int), ComputeBufferType.Raw);
// Flatten octree
linearTree = OctreeGpuHelpers.FlattenOctree(root);
int nodeStride = Marshal.SizeOf(typeof(LinearNode)); // should be 64
@ -152,7 +170,6 @@ public class VoxelRaycastGpuManager
uint[] counterInit = { 0 };
counterInit[0] = 0;
hitCounterBuffer.SetData(counterInit);
kernel = raycastShader.FindKernel("CSMain");
raycastShader.SetBuffer(kernel, "nodes", nodeBuffer);
@ -174,46 +191,72 @@ public class VoxelRaycastGpuManager
cellClusteringSums = new ComputeBuffer(gridSize, sizeof(float) * 4);
cellClusteringCounts = new ComputeBuffer(gridSize, sizeof(uint));
clustered = new ComputeBuffer(gridSize, Marshal.SizeOf(typeof(VoxelRaycastGPU.BatchData)), ComputeBufferType.Append);
accumulationKernel = clusteringShader.FindKernel("Accumulate");
reductionKernel = clusteringShader.FindKernel("Reduce");
}
public int Clustering( int inputCount )
public int Clustering( int targetGroupCount )
{
groupCountHits = Mathf.CeilToInt((float)inputCount / threadCount);
int count = datasBuffer.count;
clustered.SetCounterValue(0);
float[] zero4 = new float[gridSize * 4];
uint[] zeroU = new uint[gridSize];
cellClusteringSums.SetData(zero4);
cellClusteringCounts.SetData(zeroU);
// 1⃣ Définir la résolution de la grille
int cellsPerAxis = Mathf.CeilToInt(Mathf.Pow(targetGroupCount, 1f / 3f));
Vector3 gridMin = new Vector3(-50, -50, -50);
Vector3 gridMax = new Vector3(50, 50, 50);
Vector3 cellSize = (gridMax - gridMin) / cellsPerAxis;
// Shader
int kernelAcc = clusteringShader.FindKernel("AccumulateHits");
int kernelMean = clusteringShader.FindKernel("ComputeMeans");
int totalCells = cellsPerAxis * cellsPerAxis * cellsPerAxis;
clusteringShader.SetInt("inputCount", inputCount);
clusteringShader.SetFloat("cellSize", 1.0f); // taille des cellules
clusteringShader.SetVector("gridOrigin", Vector3.zero);
// 2⃣ Créer les buffers
ComputeBuffer cellCount = new ComputeBuffer(totalCells, sizeof(uint));
ComputeBuffer cellDistanceSum = new ComputeBuffer(totalCells, sizeof(float));
ComputeBuffer resultBuffer = new ComputeBuffer(totalCells, sizeof(float) * 4, ComputeBufferType.Append);
resultBuffer.SetCounterValue(0);
clusteringShader.SetBuffer(kernelAcc, "inputHits", hitBuffer);
clusteringShader.SetBuffer(kernelAcc, "cellSums", cellClusteringSums);
clusteringShader.SetBuffer(kernelAcc, "cellCounts", cellClusteringCounts);
clusteringShader.Dispatch(kernelAcc, groupCountHits, 1, 1);
clusteringShader.SetBuffer(accumulationKernel, "batchDatas", datasBuffer);
clusteringShader.SetBuffer(accumulationKernel, "cellCount", cellCount);
clusteringShader.SetBuffer(accumulationKernel, "cellDistanceSum", cellDistanceSum);
clusteringShader.SetBuffer(kernelMean, "cellSums", cellClusteringSums);
clusteringShader.SetBuffer(kernelMean, "cellCounts", cellClusteringCounts);
clusteringShader.SetBuffer(kernelMean, "clusteredHits", clustered);
clusteringShader.Dispatch(kernelMean, groupCountGrid, 1, 1);
clusteringShader.SetVector("gridMin", gridMin);
clusteringShader.SetVector("gridMax", gridMax);
clusteringShader.SetInts("gridResolution", cellsPerAxis, cellsPerAxis, cellsPerAxis);
clusteringShader.SetVector("cellSize", cellSize);
// Lecture du résultat
ComputeBuffer countBuffer = new ComputeBuffer(1, sizeof(int), ComputeBufferType.Raw);
ComputeBuffer.CopyCount(clustered, countBuffer, 0);
int[] countArr = new int[1];
countBuffer.GetData(countArr);
int clusterCount = countArr[0];
int threadsPerGroup = 64;
int maxThreadGroups = 65535;
datasBuffer = clustered;
for (int i = 0; i < count; i += threadsPerGroup * maxThreadGroups)
{
int remaining = count - i;
int groups = Mathf.CeilToInt(Mathf.Min(remaining / (float)threadsPerGroup, maxThreadGroups));
clusteringShader.SetInt("startIndex", i);
clusteringShader.Dispatch(accumulationKernel, groups, 1, 1);
}
return clusterCount;
// 4⃣ Dispatch reduce
clusteringShader.SetBuffer(reductionKernel, "cellCount", cellCount);
clusteringShader.SetBuffer(reductionKernel, "cellDistanceSum", cellDistanceSum);
clusteringShader.SetBuffer(reductionKernel, "clusteredBatches", resultBuffer);
int reduceGroups = Mathf.CeilToInt(totalCells / 64);
clusteringShader.Dispatch(reductionKernel, reduceGroups, 1, 1);
// 5⃣ Lire le résultat
ComputeBuffer.CopyCount(resultBuffer, countBuffer, 0);
int[] countArray = new int[1];
countBuffer.GetData(countArray);
int outputCount = countArray[0];
VoxelRaycastGPU.BatchData[] finalBatches = new VoxelRaycastGPU.BatchData[outputCount];
resultBuffer.GetData(finalBatches, 0, 0, outputCount);
// 🔚 Cleanup
cellCount.Release();
cellDistanceSum.Release();
resultBuffer.Release();
return outputCount;
}
~VoxelRaycastGpuManager()
@ -224,8 +267,14 @@ public class VoxelRaycastGpuManager
if (rayBuffer != null)
rayBuffer.Release();
if (hitBuffer != null)
hitBuffer.Release();
if (datasBuffer != null)
datasBuffer.Release();
if( countBuffer != null )
countBuffer.Release();
}
}