2026-03-25 14:24:05 +01:00
# BVLE Voxels - Prototype de Moteur Voxel Hybride
## Vue d'ensemble
2026-03-25 22:07:22 +01:00
Prototype de moteur voxel basé sur **Wicked Engine** (MIT, C++17, DX12/Vulkan) pour valider les performances de rendu sur GPU moderne (AMD RDNA 2+ / Nvidia RTX 3060+). Le document de spécification complet est dans `voxel_engine_spec.md` à la racine du projet.
2026-03-25 14:24:05 +01:00
Cible : 60+ fps en 1440p, monde de 512x512x256 voxels visibles.
## Architecture
```
bvle-voxels/
├── CMakeLists.txt # Build CMake racine
├── engine/ # Wicked Engine (clone --depth 1, branche main)
│ └── WickedEngine/shaders/voxel/ # Nos shaders copiés ici pour compilation DXC
├── src/
│ ├── voxel/ # Bibliothèque VoxelEngine (static lib)
│ │ ├── VoxelTypes.h # Types fondamentaux (VoxelData, PackedQuad, MaterialDesc, ChunkPos)
│ │ ├── VoxelWorld.h/.cpp # Monde voxel (hashmap de chunks, génération procédurale)
Phase 5.1: Naive Surface Nets smooth rendering
Implement CPU-side Naive Surface Nets for smooth voxel surfaces (SmoothStone,
Snow) coexisting with blocky voxels (Grass, Dirt, Stone, Sand).
Key features:
- SmoothMesher with binary SDF, centroid vertex placement, per-axis boundary
clamping to align with blocky grid at smooth↔blocky transitions
- Cross-chunk connectivity: PAD=2 SDF grid, vertex range [-1, CHUNK_SIZE),
canonical edge ownership (no duplicate triangles, no z-fighting)
- Face normals oriented by edge axis+sign (robust with binary SDF, unlike
SDF gradient dot or centroid sampling approaches)
- Y-axis winding fix: sharing cells have different spatial arrangement,
requiring opposite winding from X and Z axes
- GPU mesher treats smooth neighbors as solid (no blocky faces toward smooth)
- Material blending: primary (smooth-only) + secondary (all counts) per vertex
- Dedicated shaders: voxelSmoothVS (vertex pulling t6) + voxelSmoothPS
(triplanar + lerp blending between two materials)
- Separate render pass with LoadOp::LOAD after voxels+topings
- New materials: SmoothStone (mat 6), blocky Stone (mat 3) and Dirt patches
added to world generation for boundary testing
2026-03-27 13:03:55 +01:00
│ │ ├── VoxelMesher.h/.cpp # Binary Greedy Mesher CPU + SmoothMesher (Naive Surface Nets)
2026-03-31 13:46:35 +02:00
│ │ ├── VoxelRenderer.h/.cpp# Renderer + VoxelRenderPath (CameraController, AnimationState, VoxelProfiler)
│ │ ├── VoxelRTManager.h/.cpp # Ray tracing: BLAS/TLAS lifecycle, shadows+AO dispatches
│ │ ├── DeferredGPUBuffer.h # Utilitaire staging→dirty→capacity GPU buffer upload
2026-03-26 17:47:08 +01:00
│ │ └── TopingSystem.h/.cpp # Système de topings (biseaux décoratifs sur faces +Y)
2026-03-25 14:24:05 +01:00
│ └── app/
│ └── main.cpp # Point d'entrée Win32 + crash handler SEH
├── shaders/ # Sources HLSL des shaders voxel (copiés dans engine/ au build)
2026-03-26 09:05:52 +01:00
│ ├── voxelCommon.hlsli # Root signature et CB partagés (inclus par tous les shaders)
│ ├── voxelVS.hlsl # Vertex shader (vertex pulling, triple-mode: CPU/MDI/GPU mesh)
│ ├── voxelPS.hlsl # Pixel shader (triplanar + lighting)
│ ├── voxelCullCS.hlsl # Compute shader frustum+backface cull (Phase 2.3)
2026-03-26 17:47:08 +01:00
│ ├── voxelMeshCS.hlsl # Compute shader GPU mesher 1× 1 (Phase 2.4-2.5)
│ ├── voxelTopingVS.hlsl # Vertex shader topings (instanced vertex pulling, t4/t5)
Phase 5.1: Naive Surface Nets smooth rendering
Implement CPU-side Naive Surface Nets for smooth voxel surfaces (SmoothStone,
Snow) coexisting with blocky voxels (Grass, Dirt, Stone, Sand).
Key features:
- SmoothMesher with binary SDF, centroid vertex placement, per-axis boundary
clamping to align with blocky grid at smooth↔blocky transitions
- Cross-chunk connectivity: PAD=2 SDF grid, vertex range [-1, CHUNK_SIZE),
canonical edge ownership (no duplicate triangles, no z-fighting)
- Face normals oriented by edge axis+sign (robust with binary SDF, unlike
SDF gradient dot or centroid sampling approaches)
- Y-axis winding fix: sharing cells have different spatial arrangement,
requiring opposite winding from X and Z axes
- GPU mesher treats smooth neighbors as solid (no blocky faces toward smooth)
- Material blending: primary (smooth-only) + secondary (all counts) per vertex
- Dedicated shaders: voxelSmoothVS (vertex pulling t6) + voxelSmoothPS
(triplanar + lerp blending between two materials)
- Separate render pass with LoadOp::LOAD after voxels+topings
- New materials: SmoothStone (mat 6), blocky Stone (mat 3) and Dirt patches
added to world generation for boundary testing
2026-03-27 13:03:55 +01:00
│ ├── voxelTopingPS.hlsl # Pixel shader topings (triplanar + directional lighting)
│ ├── voxelSmoothVS.hlsl # Vertex shader smooth Surface Nets (vertex pulling, t6)
2026-03-28 14:48:11 +01:00
│ ├── voxelSmoothPS.hlsl # Pixel shader smooth (triplanar + material blending)
2026-03-28 20:01:18 +01:00
│ ├── voxelBLASExtractCS.hlsl # Compute shader BLAS position extraction (Phase 6.1)
2026-03-29 09:31:19 +02:00
│ ├── voxelShadowCS.hlsl # Compute shader RT shadows + raw AO (inline ray queries, Phase 6.2+6.3)
│ ├── voxelAOBlurCS.hlsl # Compute shader bilateral AO blur (separable H/V, Phase 6.3)
2026-03-29 15:00:12 +02:00
│ └── voxelAOApplyCS.hlsl # Compute shader AO apply + tone mapping + saturation (Phase 6.3 + 7)
2026-03-30 21:37:39 +02:00
├── CLAUDE.md
└── TROUBLESHOOTING.md # Pièges techniques, debugging, APIs Wicked
2026-03-25 14:24:05 +01:00
```
## Build
### Prérequis
- CMake 3.19+ (`winget install Kitware.CMake` )
- Visual Studio 2022 Build Tools (`winget install Microsoft.VisualStudio.2022.BuildTools` )
- Windows SDK 10.0.26100+ (`winget install Microsoft.WindowsSDK.10.0.26100` )
### Commandes
```bash
# Configurer (depuis la racine du projet)
cmake -B build -G "Visual Studio 17 2022" -A x64 -DCMAKE_SYSTEM_VERSION=10.0.26100.0
# Compiler
cmake --build build --config Release --target BVLEVoxels --parallel
# Exécutable produit dans build/Release/BVLEVoxels.exe
```
Le SDK 10.0.26100 est requis car les headers DX12 (`d3dx12_check_feature_support.h` ) fournis par Wicked Engine ne sont pas compatibles avec le SDK 22621.
### Post-build automatique (CMakeLists.txt)
Le build copie automatiquement :
1. `dxcompiler.dll` → à côté de l'exe (requis pour la compilation runtime des shaders)
2. `shaders/*.hlsl` → `engine/WickedEngine/shaders/voxel/` (pour que `LoadShader` les trouve via `SHADERSOURCEPATH` )
3. `engine/Content/` → à côté de l'exe (assets Wicked Engine)
## Intégration Wicked Engine
### Backend graphique
2026-03-30 21:37:39 +02:00
Wicked Engine utilise **DX12 par défaut sur Windows** , Vulkan sur Linux. Les shaders sont écrits en **HLSL** et compilés via DXC. Pour forcer Vulkan sur Windows, passer `"vulkan"` en argument de ligne de commande.
2026-03-25 14:24:05 +01:00
### Point d'entrée et architecture de rendu
2026-03-30 21:37:39 +02:00
`VoxelRenderPath` hérite de `wi::RenderPath3D` . Le rendu voxel utilise ses propres render targets (`voxelRT_` , `voxelDepth_` ) et est exécuté dans `Render()` sur un **command list dédié** . Le résultat est composité dans `Compose()` via `wi::image::Draw()` .
2026-03-25 14:24:05 +01:00
2026-03-30 21:37:39 +02:00
**NE JAMAIS créer un render pass dans `Compose()` ** : cette méthode est appelée à l'intérieur du render pass du swapchain. Imbriquer des render passes est interdit en D3D12.
2026-03-25 14:24:05 +01:00
```
Render() → RenderPath3D::Render() // Wicked rend sa scène
→ device->BeginCommandList() // Nouveau cmd list
→ renderer.render(cmd, ...) // Notre render pass (clear + draw voxels → voxelRT_)
Compose() → RenderPath3D::Compose() // Wicked affiche son résultat
→ wi::image::Draw(voxelRT_) // On overlay nos voxels par-dessus
```
La caméra est gérée manuellement dans `Update()` en écrivant directement `camera->Eye` , `camera->At` (direction LookTo), `camera->Up` .
2026-03-30 21:37:39 +02:00
> See `TROUBLESHOOTING.md` for the detailed Wicked API reference table, shader binding pitfalls, DX12 resource state management, and debugging guides.
2026-03-25 14:24:05 +01:00
## Détails d'implémentation
### VoxelData (16 bits)
```
[15:8] material ID (256 matériaux)
[7:4] flags (smooth, transparent, emissive, custom)
[3:0] metadata (orientation, variant)
```
### PackedQuad (64 bits = 8 octets par quad)
```
2026-03-30 21:37:39 +02:00
[5:0] position X (0-63) [23:18] width (1-32)
[11:6] position Y (0-63) [29:24] height (1-32)
[17:12] position Z (0-63) [32:30] face (0-5)
[40:33] material ID [48:41] blendMatID
[59:49] chunkIndex (11 bits) [63:60] blendEdges (4 bits)
2026-03-25 14:24:05 +01:00
```
### Binary Greedy Mesher (CPU, `VoxelMesher.cpp`)
2026-03-30 21:37:39 +02:00
Masques binaires par axe, face culling par shift/XOR, greedy merge rectangulaire par tranche de profondeur.
2026-03-25 14:24:05 +01:00
### Génération procédurale (`VoxelWorld.cpp`)
2026-03-30 21:37:39 +02:00
Perlin noise 3D, fBm 5 octaves (2 en animation), caves 3D, matériaux par altitude. Chunks Y=0..7. Animation 60 Hz via `regenerateAnimated()` parallélisé avec `wi::jobsystem` .
2026-03-25 14:24:05 +01:00
### Renderer (`VoxelRenderer.cpp`)
2026-03-30 21:37:39 +02:00
- **Triple-mode VS** : CPU path, MDI path, GPU mesh path (défaut)
- **GPU mesh** : compute shader `voxelMeshCS` → barrier UAV→SRV → `DrawInstanced` (readback 1-frame-delay)
- **Vertex pulling** via `SV_VertexID` , pas de vertex buffer classique
- **Per-chunk info** : `StructuredBuffer<GPUChunkInfo>` (80 bytes/chunk)
- **Height-based blending** (Phase 3) : PS lit `voxelDataBuffer` (t3), winner-takes-all heightmap, corner attenuation
- **Render targets propres** : `voxelRT_` (R8G8B8A8) + `voxelDepth_` (D32_FLOAT)
2026-03-31 13:46:35 +02:00
- **CPU profiling** : `VoxelProfiler` (21 `ProfileAccum` , moyennes toutes les 5s)
- **DeferredGPUBuffer** : utilitaire pour buffers GPU avec staging CPU, dirty flag, capacity-based growth (25% headroom)
- **VoxelRTManager** (`VoxelRTManager.h/.cpp` ) : gère BLAS/TLAS, dispatches RT shadows+AO, isolé du renderer
- **VoxelRenderPath** décomposé en : `CameraController` (mouvement/souris), `AnimationState` (tick terrain), `VoxelProfiler`
- **Toping sort** : counting sort O(n) par (type, variant) au lieu de `std::sort`
2026-03-30 21:37:39 +02:00
## Phases de développement
2026-03-25 14:24:05 +01:00
### Phase 1 - Setup et meshing de base [FAIT]
2026-03-30 21:37:39 +02:00
Fork Wicked Engine, VoxelWorld procédural, Binary Greedy Mesher CPU (~300K quads), rendu vertex pulling, caméra libre, crash handler SEH.
2026-03-25 14:24:05 +01:00
2026-03-26 09:05:52 +01:00
### Phase 2 - Performance GPU [FAIT]
2026-03-25 22:07:22 +01:00
2026-03-30 21:37:39 +02:00
- **2.1** : Mega-buffer + CPU frustum/backface cull + per-face DrawInstanced
- **2.2** : CPU-filled indirect args + DrawInstancedIndirectCount (MDI)
- **2.3** : GPU compute culling (0.006 ms / 168 chunks)
- **2.4** : GPU compute mesher benchmark (CPU 277ms vs GPU 5.3ms)
- **2.5** : GPU meshing production + CPU optimisations (fused regen+pack, memcpy, dirty cache)
- **Résultat** : 80-110 FPS avec animation 60 Hz, 700+ FPS statique
2026-03-26 09:05:52 +01:00
2026-03-26 12:14:08 +01:00
### Phase 3 - Texture blending [FAIT]
2026-03-30 21:37:39 +02:00
PS-based heightmap blending, winner-takes-all, corner attenuation subtractive. GPU mesh path uniquement.
2026-03-25 14:24:05 +01:00
2026-03-26 17:47:08 +01:00
### Phase 4 - Toping [EN COURS]
2026-03-25 14:24:05 +01:00
2026-03-30 21:37:39 +02:00
- **4.1** [FAIT] : TopingSystem infrastructure, 4-bit adjacency, priority-based, stone wedges + grass tufts
- **4.2** [FAIT] : Shaders dédiés, vertex pulling instancié, half-Lambert + translucency vegetation
- **4.3** [A FAIRE] : Plus de types, LOD, animation vent, compute shader instances
2026-03-25 14:24:05 +01:00
Phase 5.1: Naive Surface Nets smooth rendering
Implement CPU-side Naive Surface Nets for smooth voxel surfaces (SmoothStone,
Snow) coexisting with blocky voxels (Grass, Dirt, Stone, Sand).
Key features:
- SmoothMesher with binary SDF, centroid vertex placement, per-axis boundary
clamping to align with blocky grid at smooth↔blocky transitions
- Cross-chunk connectivity: PAD=2 SDF grid, vertex range [-1, CHUNK_SIZE),
canonical edge ownership (no duplicate triangles, no z-fighting)
- Face normals oriented by edge axis+sign (robust with binary SDF, unlike
SDF gradient dot or centroid sampling approaches)
- Y-axis winding fix: sharing cells have different spatial arrangement,
requiring opposite winding from X and Z axes
- GPU mesher treats smooth neighbors as solid (no blocky faces toward smooth)
- Material blending: primary (smooth-only) + secondary (all counts) per vertex
- Dedicated shaders: voxelSmoothVS (vertex pulling t6) + voxelSmoothPS
(triplanar + lerp blending between two materials)
- Separate render pass with LoadOp::LOAD after voxels+topings
- New materials: SmoothStone (mat 6), blocky Stone (mat 3) and Dirt patches
added to world generation for boundary testing
2026-03-27 13:03:55 +01:00
### Phase 5 - Rendu smooth [EN COURS]
2026-03-25 14:24:05 +01:00
2026-03-30 21:37:39 +02:00
- **5.1** [FAIT] : Naive Surface Nets CPU, SDF binaire, cross-chunk connectivity, smooth/blocky boundary
- **5.2** [FAIT] : Smooth vertex normals, geometric normals triplanar, optimisations CPU (560ms → 17ms)
- **5.3** [A FAIRE] : GPU compute Surface Nets
- **5.4** [A FAIRE] : SDF lissé, LOD, pipeline asynchrone
2026-03-25 14:24:05 +01:00
2026-03-28 14:48:11 +01:00
### Phase 6 - Ray tracing hybride [EN COURS]
2026-03-30 21:37:39 +02:00
- **6.1** [FAIT] : Normal RT (MRT), BLAS extraction CS, 3 BLAS (blocky+smooth+topings), TLAS
- **6.2** [FAIT] : RT shadows (3 jittered rays, TMin adaptatif, colored shadows)
- **6.3** [FAIT] : RT AO (4 cosine-weighted rays, IGN + Cranley-Patterson, temporal accumulation, bilateral blur)
- **6.4** [A FAIRE] : Fallback shadow maps + SSAO
### Phase 7 - Stylized Lighting [EN COURS]
- **7.1** [FAIT] : Hemisphere ambient, colored shadows, rim light, tone mapping + saturation, screenshot mode
2026-03-29 15:00:12 +02:00
2026-03-26 09:05:52 +01:00
## Métriques cibles et résultats
2026-03-25 14:24:05 +01:00
2026-03-28 14:48:11 +01:00
| Métrique | Cible | Résultat (Ryzen 7 9800X3D + RX 9070 XT) |
2026-03-26 09:05:52 +01:00
|----------|-------|---------------------------------------|
2026-03-30 21:37:39 +02:00
| FPS 1440p | > 60 fps | 80-110 FPS (anim blocky), 700+ FPS (statique) |
| FPS anim smooth+topings | > 15 fps | 17 FPS (smooth+topings+blocky anim 60Hz) |
| Meshing GPU (blocky) | < 200 us / chunk | ~ 0 . 6 us / chunk ( 0 . 1ms / 171 chunks ) |
| Meshing CPU (smooth) | < 30ms | 17ms ( parallele , 648 chunks ) |
| Memoire GPU | < 500 Mo | ~ 30 Mo |
| Draw calls | < 100 | 1 ( GPU mesh ) ou 1 ( MDI ) |
2026-03-25 14:24:05 +01:00
## Conventions
- Namespaces : tout le code voxel est dans `namespace voxel`
- Chunks : 32x32x32, configurable via `CHUNK_SIZE`
- Coordonnées : Y = haut, monde infini en X/Z, hashmap sparse
Phase 5.1: Naive Surface Nets smooth rendering
Implement CPU-side Naive Surface Nets for smooth voxel surfaces (SmoothStone,
Snow) coexisting with blocky voxels (Grass, Dirt, Stone, Sand).
Key features:
- SmoothMesher with binary SDF, centroid vertex placement, per-axis boundary
clamping to align with blocky grid at smooth↔blocky transitions
- Cross-chunk connectivity: PAD=2 SDF grid, vertex range [-1, CHUNK_SIZE),
canonical edge ownership (no duplicate triangles, no z-fighting)
- Face normals oriented by edge axis+sign (robust with binary SDF, unlike
SDF gradient dot or centroid sampling approaches)
- Y-axis winding fix: sharing cells have different spatial arrangement,
requiring opposite winding from X and Z axes
- GPU mesher treats smooth neighbors as solid (no blocky faces toward smooth)
- Material blending: primary (smooth-only) + secondary (all counts) per vertex
- Dedicated shaders: voxelSmoothVS (vertex pulling t6) + voxelSmoothPS
(triplanar + lerp blending between two materials)
- Separate render pass with LoadOp::LOAD after voxels+topings
- New materials: SmoothStone (mat 6), blocky Stone (mat 3) and Dirt patches
added to world generation for boundary testing
2026-03-27 13:03:55 +01:00
- Matériaux : palette de 256, index 0 = air (vide), 1=grass, 2=dirt, 3=stone (blocky), 4=sand, 5=snow (smooth), 6=smoothstone (smooth)
2026-03-25 14:24:05 +01:00
- Faces : 0=+X, 1=-X, 2=+Y, 3=-Y, 4=+Z, 5=-Z
Phase 5.1: Naive Surface Nets smooth rendering
Implement CPU-side Naive Surface Nets for smooth voxel surfaces (SmoothStone,
Snow) coexisting with blocky voxels (Grass, Dirt, Stone, Sand).
Key features:
- SmoothMesher with binary SDF, centroid vertex placement, per-axis boundary
clamping to align with blocky grid at smooth↔blocky transitions
- Cross-chunk connectivity: PAD=2 SDF grid, vertex range [-1, CHUNK_SIZE),
canonical edge ownership (no duplicate triangles, no z-fighting)
- Face normals oriented by edge axis+sign (robust with binary SDF, unlike
SDF gradient dot or centroid sampling approaches)
- Y-axis winding fix: sharing cells have different spatial arrangement,
requiring opposite winding from X and Z axes
- GPU mesher treats smooth neighbors as solid (no blocky faces toward smooth)
- Material blending: primary (smooth-only) + secondary (all counts) per vertex
- Dedicated shaders: voxelSmoothVS (vertex pulling t6) + voxelSmoothPS
(triplanar + lerp blending between two materials)
- Separate render pass with LoadOp::LOAD after voxels+topings
- New materials: SmoothStone (mat 6), blocky Stone (mat 3) and Dirt patches
added to world generation for boundary testing
2026-03-27 13:03:55 +01:00
- Smooth flag : `FLAG_SMOOTH = 0x1` dans VoxelData flags — active Surface Nets au lieu du rendu blocky