ComputeMeshSurfaceSampler

@three-blocks/coreWebGPU
new ComputeMeshSurfaceSampler(mesh : THREE.Mesh, renderer : THREE.WebGPURenderer, count : number, options : MeshSurfaceSamplerOptions)

GPU mesh surface sampler using TSL.

Overview This class implements a high-performance surface sampling algorithm that runs entirely on the GPU. It is designed to generate thousands or millions of instances distributed on the surface of a mesh.

Algorithm

  1. CPU Pre-processing: Builds a weighted distribution (CDF) and Alias Table based on triangle areas.
  2. GPU Sampling: Uses the Alias Method (O(1)) to select triangles and Blue Noise to pick barycentric coordinates.
  3. Output: Writes transformation matrices to a storage buffer, ready for InstancedMesh.

Features

  • Blue Noise: Ensures samples are well-distributed (low discrepancy) and temporally stable.
  • Alias Method: Efficient O(1) selection of weighted triangles.
  • Normal Alignment: Aligns instance Y-axis to the surface normal.

Example: Grass distribution on terrain

Example: Resampling specific instances

// Resample only instance 42 (e.g., for respawning)
await sampler.compute({ resampleIndex: 42 });

// Measure GPU performance
const timestamp = await sampler.compute({ trackTimestamp: true });
console.log(`Sampling took ${timestamp}ms`);
Constructor Parameters
meshTHREE.Mesh
Source mesh to sample from.
rendererTHREE.WebGPURenderer
WebGPU renderer instance.
countnumber
Number of samples/instances to generate.
optionsoptionalMeshSurfaceSamplerOptions
Configuration options.
Example
import { ComputeMeshSurfaceSampler } from '@three-blocks/core';
import * as THREE from 'three/webgpu';

// Load terrain mesh
const terrain = await loadTerrain();

// Create sampler for 100,000 grass blades
const sampler = new ComputeMeshSurfaceSampler(terrain, renderer, 100000, {
  seed: 42,
  useVertexNormals: true
});

// Run sampling on GPU
await sampler.compute();

// Create instanced grass using the sampled transforms
const grassGeometry = new THREE.PlaneGeometry(0.1, 0.5);
const grassMaterial = new THREE.MeshStandardNodeMaterial({ color: 0x3d9140 });
const grass = new THREE.InstancedMesh(grassGeometry, grassMaterial, 100000);

// Assign the GPU-generated transforms directly
grass.instanceMatrix = sampler.output;
scene.add(grass);

Properties

.renderer : THREE.WebGPURenderer

.count : number

.output :

Returns the GPU storage buffer containing instance transformation matrices. Can be directly assigned to InstancedMesh.instanceMatrix.

.outputNormal :

Returns the GPU storage buffer containing world-space surface normals per instance.

Methods

compute#

compute(options : Object) : Promise<(number|undefined)>

Recompute on GPU. Pass {resampleIndex} to update just one instance.

Parameters
optionsoptionalObject
Options
  • resampleIndexoptionalnumber
    If provided, updates only this instance index; otherwise all instances are recomputed.
  • trackTimestampoptionalboolean
    If true, returns the GPU timestamp.
Returns
Promise<(number|undefined)> — GPU timestamp if {trackTimestamp} is true, otherwise null.

readback#

readback() : Promise<Float32Array>

(optional) Read back transformation matrices to CPU

Returns
Promise<Float32Array> — Array of mat4 matrices (16 floats per instance)