bvle-voxels/src/voxel/TopingSystem.h
Samuel Bouchet cd9814e494 Phase 5.2-5.3: CPU perf optimizations + GPU compute Surface Nets
CPU smooth mesher optimizations (560ms → 17ms):
- VoxelData grid cache eliminates redundant readVoxel calls
- Pre-cached 27 neighbor chunk pointers (readVoxelFast)
- smoothNear dilation (8 lookups/cell instead of 56)
- Early exit via containsSmooth flag on chunks
- Thread-local scratch buffers (SmoothScratch ~600KB)
- wi::jobsystem parallelization across all cores
- Persistent staging vectors for upload

TopingSystem optimizations (58ms → 6ms):
- collectInstancesParallel() with per-chunk local vectors
- Neighbor chunk pointer caching

GPU compute Surface Nets (Phase 5.3):
- Two-pass compute shader: centroid grid + emit with smooth normals
- Pass 1 (voxelSmoothCentroidCS): computes centroids + solid flags
  for cells [-1..32], cross-chunk neighbor voxel reading
- Pass 2 (voxelSmoothCS): reads ONLY from centroid grid, computes
  area-weighted smooth normals from 12 incident edges per vertex
- Batched dispatch: all centroid passes then all emit passes with
  single UAV→SRV barrier (instead of 2 barriers per chunk)
- Smooth chunk filtering: only dispatches chunks with containsSmooth
- Centroid grid buffer dynamically sized per smooth chunk count
- 1-frame readback delay with auto-redispatch on first frame
2026-03-27 22:30:43 +01:00

85 lines
3.7 KiB
C++

#pragma once
#include "VoxelTypes.h"
#include <vector>
#include <cstdint>
namespace voxel {
class VoxelWorld;
// ── Toping mesh vertex (position + normal) ──────────────────────
struct TopingVertex {
float px, py, pz; // position in voxel-local space [0,1]³
float nx, ny, nz; // normal
};
// ── Reference to a slice of vertices in the shared pool ─────────
struct MeshSlice {
uint32_t offset; // first vertex index in TopingSystem::vertices_
uint32_t count; // number of vertices (multiple of 3)
};
// ── Toping definition (one per decorative type) ─────────────────
// Each def targets a specific material + face, and provides 16
// mesh variants indexed by a 4-bit adjacency bitmask.
//
// Adjacency bitmask (for FACE_POS_Y):
// bit 0 = +X neighbor has same material AND exposed +Y face
// bit 1 = -X neighbor has same material AND exposed +Y face
// bit 2 = +Z neighbor has same material AND exposed +Y face
// bit 3 = -Z neighbor has same material AND exposed +Y face
//
// A SET bit means the neighbor IS present → no bevel on that edge.
// An UNSET bit means the edge is "open" → bevel strip generated.
struct TopingDef {
uint8_t materialID; // voxel material that triggers this toping
uint8_t face; // Face enum (FACE_POS_Y, etc.)
uint8_t priority; // higher priority topings generate bevels over lower ones at boundaries
float height; // bevel peak height (voxel units)
float width; // bevel inward extent (voxel units)
int segments; // subdivisions per edge strip (1=smooth, 3+=bumpy)
MeshSlice variants[16]; // indexed by adjacency bitmask
};
// ── Placed toping instance ──────────────────────────────────────
struct TopingInstance {
float wx, wy, wz; // world position of the source voxel (integer coords)
uint16_t topingType; // index into TopingSystem::defs_
uint16_t variant; // adjacency bitmask (0-15)
};
// ── Toping System ───────────────────────────────────────────────
// Manages toping definitions, procedural mesh generation, and
// instance collection from the voxel world.
//
// Phase 4.1: data structures + mesh gen + collection (no rendering).
// Phase 4.2 will upload vertices_ to a GPU vertex buffer and
// instances_ to an instance buffer for instanced drawing.
class TopingSystem {
public:
void initialize();
void collectInstances(const VoxelWorld& world);
void collectInstancesParallel(const VoxelWorld& world);
// Accessors for Phase 4.2 GPU upload
const std::vector<TopingVertex>& getVertices() const { return vertices_; }
const std::vector<TopingInstance>& getInstances() const { return instances_; }
const std::vector<TopingDef>& getDefs() const { return defs_; }
size_t getDefCount() const { return defs_.size(); }
size_t getInstanceCount() const { return instances_.size(); }
size_t getVertexCount() const { return vertices_.size(); }
private:
void registerDefs();
void generateMeshes();
void generateVariant(TopingDef& def, uint8_t bitmask);
void generateStoneVariant(TopingDef& def, uint8_t bitmask);
void generateGrassVariant(TopingDef& def, uint8_t bitmask);
std::vector<TopingDef> defs_;
std::vector<TopingVertex> vertices_; // shared vertex pool for all types/variants
std::vector<TopingInstance> instances_; // collected per frame/update
};
} // namespace voxel