# BVLE Voxels - Prototype de Moteur Voxel Hybride ## Vue d'ensemble 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. 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) │ │ ├── VoxelMesher.h/.cpp # Binary Greedy Mesher CPU + SmoothMesher (Naive Surface Nets) │ │ ├── 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 │ │ └── TopingSystem.h/.cpp # Système de topings (biseaux décoratifs sur faces +Y) │ └── app/ │ └── main.cpp # Point d'entrée Win32 + crash handler SEH ├── shaders/ # Sources HLSL des shaders voxel (copiés dans engine/ au build) │ ├── 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) │ ├── voxelMeshCS.hlsl # Compute shader GPU mesher 1×1 (Phase 2.4-2.5) │ ├── voxelTopingVS.hlsl # Vertex shader topings (instanced vertex pulling, t4/t5) │ ├── voxelTopingPS.hlsl # Pixel shader topings (triplanar + directional lighting) │ ├── voxelSmoothVS.hlsl # Vertex shader smooth Surface Nets (vertex pulling, t6) │ ├── voxelSmoothPS.hlsl # Pixel shader smooth (triplanar + material blending) │ ├── voxelBLASExtractCS.hlsl # Compute shader BLAS position extraction (Phase 6.1) │ ├── 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) │ └── voxelAOApplyCS.hlsl # Compute shader AO apply + tone mapping + saturation (Phase 6.3 + 7) ├── CLAUDE.md └── TROUBLESHOOTING.md # Pièges techniques, debugging, APIs Wicked ``` ## 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 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. ### Point d'entrée et architecture de rendu `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()`. **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. ``` 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`. > See `TROUBLESHOOTING.md` for the detailed Wicked API reference table, shader binding pitfalls, DX12 resource state management, and debugging guides. ## 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) ``` [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) ``` ### Binary Greedy Mesher (CPU, `VoxelMesher.cpp`) Masques binaires par axe, face culling par shift/XOR, greedy merge rectangulaire par tranche de profondeur. ### Génération procédurale (`VoxelWorld.cpp`) 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`. ### Renderer (`VoxelRenderer.cpp`) - **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` (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) - **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` ## Phases de développement ### Phase 1 - Setup et meshing de base [FAIT] Fork Wicked Engine, VoxelWorld procédural, Binary Greedy Mesher CPU (~300K quads), rendu vertex pulling, caméra libre, crash handler SEH. ### Phase 2 - Performance GPU [FAIT] - **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 ### Phase 3 - Texture blending [FAIT] PS-based heightmap blending, winner-takes-all, corner attenuation subtractive. GPU mesh path uniquement. ### Phase 4 - Toping [EN COURS] - **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 ### Phase 5 - Rendu smooth [EN COURS] - **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 ### Phase 6 - Ray tracing hybride [EN COURS] - **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 ## Métriques cibles et résultats | Métrique | Cible | Résultat (Ryzen 7 9800X3D + RX 9070 XT) | |----------|-------|---------------------------------------| | 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) | ## 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 - Matériaux : palette de 256, index 0 = air (vide), 1=grass, 2=dirt, 3=stone (blocky), 4=sand, 5=snow (smooth), 6=smoothstone (smooth) - Faces : 0=+X, 1=-X, 2=+Y, 3=-Y, 4=+Z, 5=-Z - Smooth flag : `FLAG_SMOOTH = 0x1` dans VoxelData flags — active Surface Nets au lieu du rendu blocky