Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commit9eb3c4fc65

README.md

gpu

GPU greedy mesher. Dispatches a WGSL compute shader that emits vertices and indices directly into GPU-resident storage buffers; the caller wraps those buffers with renderer.mesh.create for a zero-copy renderable mesh. Mirrors the CPU mesher's public API surface so the top-level backend selector (Mesher.setBackend / Mesher.build) can swap CPU ↔ GPU without the caller caring which one produced the mesh descriptor.

The mesher runs the package's greedy_mesh.computeShader, which declares the six buffers it binds and takes the engine's vertex stride as a param. It is resolved and compiled on first use of M.build; later calls reuse it.

Exports

  • M.isAvailable() -> boolean — probe whether the engine exposes the compute + mesh-from-buffer globals.
  • M.build(opts: BuildOpts) -> MeshDescriptor — dispatch the greedy mesher shader. Output's gpuBuffers is what you pass to renderer.mesh.create.
  • M.releaseBuffers(desc: MeshDescriptor?) — destroy the GPU buffers owned by a descriptor. Must be called when the mesh is no longer needed.

Types:

  • Vec3 = { x: number, y: number, z: number }
  • Submesh = { material: string, indexStart: number, indexCount: number }
  • GpuBuffers = { vertex: string, index: string, counters?: string, vertexCount: number, indexCount: number }
  • Aabb = { min: Vec3, max: Vec3 }
  • MeshDescriptor = { positions, indices, normals, uvs, colors, submeshes, vertexCount, gpuBuffers?, aabb }
  • BuildOpts = { size, blockSize?, origin?, isSolid, getColor, getMaterial? }

Usage

local Gpu = require("@builtin::systems.voxelEngine.voxelEngine.mesher.gpu")

if Gpu.isAvailable() then
    local desc = Gpu.build({
        size      = { x = 32, y = 32, z = 32 },
        blockSize = 1.0,
        isSolid   = function(x, y, z) return ... end,
        getColor  = function(x, y, z) return r, g, b end,
    })

    -- Pass desc.gpuBuffers.vertex / .index into renderer.mesh.create.
    -- When the mesh is no longer needed:
    Gpu.releaseBuffers(desc)
end

Notes

  • Grid dimensions are capped at 64 per axis (matches the shader's MAX_SIZE workgroup-memory layout — MAX_SIZE * MAX_SIZE * 4 u32 mask bytes fit the WebGPU baseline maxComputeWorkgroupStorageSize of 16 KiB). Larger grids must be split into chunks before meshing.
  • Face emission order differs from the CPU mesher (+Y, -Y, +X, -X, +Z, -Z vs CPU's +X, -X, +Y, -Y, +Z, -Z); vertex indexing is internally consistent within each mesh.
  • vertexCount and the index count reported in gpuBuffers.indexCount are conservative upper bounds — unused slots collapse to degenerate triangles. This matches how renderer.mesh.create wraps the buffers.
  • Multi-material parity with the CPU mesher is approximate; see the in-file TODO for the planned shader extension.
  • releaseBuffers is mandatory on completion. Forgetting it leaks GPU memory because the buffers stay alive for the lifetime of the mesh.