ComputeBatchCulling
new ComputeBatchCulling(options : ComputeBatchCullingOptions)GPU-driven culling for IndirectBatchedMesh with matrix-based reference positions.
Architecture
- Optimized for
IndirectBatchedMeshwith per-instance matrices - Two-pass block compaction algorithm for efficient parallel writes
- Supports both ref-position and matrix-based culling
- Per-geometry bounding sphere tests (reads from mesh geometry info)
- Writes survivor IDs for indirect instanced draw
Limitations
- Transparency is not supported: IndirectBatchedMesh does not support transparent materials. Use opaque materials only. Depth sorting is not available.
Block Compaction Algorithm
- Count Pass: Each instance atomically increments its block counter if visible
- Prefix Sum: CPU computes block offsets (serial over blocks, parallel within)
- Scatter Pass: Each visible instance writes to its block's allocated slot
Matrix vs Position Mode
- Position Mode (default): Uses
refPosition/refNormalarrays - Matrix Mode (via
bindMatricesAsReference()): Extracts position from matrices- Enables per-geometry bounding sphere culling
- Ideal for
IndirectBatchedMeshintegration
LOD System
- Purpose: Reduce draw density smoothly with distance by keeping each instance with probability
pKeep. - Near/Far:
lodNeardefines where LOD begins.lodFardefines where range mode reaches full falloff. - Modes (
lodMode):- Disabled (
LOD_MODE_DISABLED): LOD sampling is off. - Range (
LOD_MODE_RANGE): Smoothstep falloff betweenlodNearandlodFar.pKeep = 1 - smoothstep( lodNear, lodFar, d ) - Exp (
LOD_MODE_EXP): Exponential density falloff starting atlodNear.pKeep = exp( -density^2 * (d - lodNear)^2 )Note:lodNearshifts the start of the exp curve; increasing it delays the falloff.
- Disabled (
- Density Parameter:
lodDensityacts as exp density (smaller = slower decay). - Sampling: Each instance is kept if
hash(instanceId) < pKeep, giving stable stochastic thinning. - Compatibility: Internally computes
stepF = sqrt(1 / max(pKeep, eps))for legacy outputs.
Integration with IndirectBatchedMesh
Constructor Parameters
optionsComputeBatchCullingOptionsSee also
Example
import { IndirectBatchedMesh, ComputeBatchCulling, indirectBatch } from '@three-blocks/core';
// Create batched mesh
const count = 10000;
const mesh = new IndirectBatchedMesh(count, 50000, 150000, material);
mesh.frustumCulled = false; // Disable CPU culling
// Add geometries and instances
const sphereId = mesh.addGeometry(new SphereGeometry(1, 16, 16));
for (let i = 0; i < count; i++) {
const id = mesh.addInstance(sphereId);
const matrix = new Matrix4();
matrix.makeTranslation(
Math.random() * 100 - 50,
Math.random() * 100 - 50,
Math.random() * 100 - 50
);
mesh.setMatrixAt(id, matrix);
}
// Setup material with indirect batch node
material.positionNode = Fn(() => {
indirectBatch(mesh).toStack();
return positionLocal;
})();
// Create culler
const culler = new ComputeBatchCulling({
renderer,
count,
indexCount: sphereGeometry.index.count,
enabled: true
});
// Bind mesh matrices as culling reference
culler.bindMatricesAsReference(mesh);
culler.attachGeometry(mesh.geometry);
culler.attachMesh(mesh);
// Render loop
function animate() {
culler.setCameraUniforms(camera);
culler.update(); // GPU culling
renderer.render(scene, camera);
}
Properties
# .indirect : THREE.IndirectStorageBufferAttribute
Get indirect draw buffer.
# .outIdSSBO : THREE.StorageBufferAttribute
Get survivor ID buffer.
# .outIdNode : StorageNode
Get survivor ID storage node (TSL).
Methods
setCameraUniforms#
setCameraUniforms(camera : THREE.Camera)Update camera uniforms for frustum culling.
Call before update() each frame.
Parameters
cameraTHREE.CameraattachGUI#
attachGUI(folder : Object)Attach culling controls to a GUI folder. Compatible with lil-gui, dat.gui, and Three.js Inspector.
Parameters
folderObjectdisposeGUI#
disposeGUI()Detach and destroy the GUI folder.
update#
update()Execute GPU culling with two-pass block compaction. Must be called every frame before rendering.
attachGeometry#
attachGeometry(geometry : THREE.BufferGeometry)Attach geometry to receive indirect draw args.
Parameters
geometryTHREE.BufferGeometryattachMesh#
attachMesh(mesh : THREE.Mesh)Attach mesh and configure survivor buffer.
Parameters
meshTHREE.MeshsetReferenceMatrixNode#
setReferenceMatrixNode(resolverFn : function|null) : thisOverride the matrix used for culling (e.g., animation texture).
Parameters
resolverFnfunction | nullReturns
thisbindMatricesAsReference#
bindMatricesAsReference(mesh : IndirectBatchedMesh)Bind mesh matrices as culling reference (enables matrix mode).
Extracts positions from instance matrices and enables per-geometry sphere tests.
Automatically called by IndirectBatchedMesh when culling is enabled.
Parameters
matricesSB storage buffer.readIndirectArgs#
readIndirectArgs() : Promise<Uint32Array>Read back indirect draw arguments from GPU (debug/stats).
Returns
Promise<Uint32Array> — Array of [indexCount, instanceCount, firstIndex, baseVertex, firstInstance].readSurvivorIndicesAsync#
readSurvivorIndicesAsync() : Promise<Uint32Array>Read back surviving instance IDs from GPU (debug/analysis).
Returns
Promise<Uint32Array> — Array of survivor instance indices.dispose#
dispose()Dispose of GPU resources.