- TopingSystem with TopingDef registry, procedural mesh gen, instance collection - 2 toping types: stone bevel (h=0.06, smooth) + grass edge (h=0.12, bumpy) - 16 mesh variants per type indexed by 4-bit adjacency bitmask (~6 unique with symmetry) - Wedge cross-section: outer wall + sloped top, grass has sinusoidal height profile - Instance collection scans exposed +Y faces, checks same-material neighbors - Cross-chunk adjacency via VoxelWorld::getVoxel() - Integrated into VoxelRenderPath: init at Start(), stats in HUD - ~191K instances, 1920 mesh vertices for 170 chunks (validated) - Research doc (research_connected_meshes.md) + plan (plan_phase4.md)
3.7 KiB
Plan Phase 4 — Toping (meshes décoratifs adaptatifs)
Le toping consiste à placer automatiquement des meshes 3D procéduraux sur les faces exposées de certains voxels, qui s'adaptent à leur voisinage via un bitmask 4 bits (16 variantes). C'est fondamentalement différent des phases précédentes : on passe du rendu de quads au rendu de triangles instanciés avec géométrie 3D.
Phase 4.1 — Infrastructure TopingSystem + génération de meshes procéduraux
Objectif : Créer le système de données (TopingDef, TopingInstance) et générer des meshes de test procéduralement (pas d'import d'assets).
-
TopingSystemclass (src/voxel/TopingSystem.h/.cpp) :TopingDef: définit un type de toping (ID matériau source, face(s) applicables, 16 mesh variants indexées par bitmask d'adjacence)TopingInstance: position monde (float3) + rotation/face + variant index + toping type ID- Registry de
TopingDef(tableau fixe, 2-3 types de test) - Collecte des instances : itérer sur les voxels exposés d'un chunk, vérifier le matériau, calculer le bitmask 4 bits des voisins cardinaux dans le plan de la face, émettre un
TopingInstance
-
Meshes procéduraux de test (pas d'assets externes) :
- Type 1 — Rebord de pierre : sur les faces +Y de la stone, petit biseau/corniche qui longe le bord supérieur
- Type 2 — Bordure d'herbe : sur les faces +Y du grass, petites touffes/relief organique sur les bords
- Chaque type a 16 variants (straight, corner, T-junction, cross, isolé, etc.) générées par code
-
Livrables : TopingSystem peut scanner un chunk et produire une liste de TopingInstance. Pas de rendu encore.
Phase 4.2 — GPU buffers + pipeline de rendu instancié
Objectif : Rendre les toping instances sur le même render target que les voxels.
-
Vertex buffer partagé pour les mesh variants :
- Toutes les variantes de tous les TopingDef dans un seul vertex buffer (position + normal + UV)
- Index table :
meshOffset[topingType][variant]→ offset + vertex count dans le VB
-
Instance buffer (
StructuredBuffer<TopingInstance>) :- Rempli par le CPU après collecte (comme le mega quad buffer)
- Contient : world position, face rotation matrix (ou quaternion), mesh variant offset
-
PSO toping :
- Nouveau VS (
voxelTopingVS.hlsl) : lit instance data + vertex data, transforme en world space - Réutilise le PS existant (ou PS simplifié avec UVs classiques au lieu de triplanar)
- Même root signature, même depth buffer, même render target
DrawInstancedouDrawInstancedIndirectgroupé par type de mesh
- Nouveau VS (
-
Intégration dans
VoxelRenderer::render(): après le draw des voxels, draw des topings dans le même render pass
Phase 4.3 — Adjacence dynamique + optimisation
Objectif : Le bitmask s'adapte quand le monde change, et le pipeline est performant.
- Recalcul incrémental : quand un chunk est dirty, recalculer uniquement les toping instances de ce chunk + les chunks voisins (bords)
- Frustum culling : skip les instances hors frustum (par chunk, comme les voxels)
- Benchmark : mesurer le coût GPU pour 50K instances (cible < 2ms)
- Mode debug (F5 ?) : visualiser les bitmasks d'adjacence en couleur
- Cross-chunk adjacency : voisins aux frontières de chunks (comme le mesher fait déjà)
Complexité estimée
Phase 4.1 est la plus lourde (design des structures + génération procédurale des 16 variants × 2 types). Phase 4.2 est mécanique (pipeline GPU classique). Phase 4.3 est de l'optimisation.
Prérequis
Avant d'implémenter, une étude des systèmes de meshes connectés contextuels est nécessaire (WFC, dual grid, marching squares variants, etc.) — voir research_connected_meshes.md.