SPH

@three-blocks/coreWebGPU
new SPH()

Smoothed Particle Hydrodynamics (SPH) fluid simulation with spatial grid acceleration.

Features

  • Pressure, viscosity, and gravity forces with configurable SPH kernels (Poly6, Spiky, Viscosity)
  • Spatial grid acceleration (default) or naive O(N²) neighbor search
  • 2D and 3D modes with appropriate kernel functions
  • Domain attachment to Three.js objects for dynamic boundary transforms
  • Pointer-based interaction for user-driven forces
  • Optional direction storage for oriented particle rendering

Architecture

  • Compute passes: density → pressure → forces (pressure + viscosity) → interaction → integration
  • Spatial grid reduces neighbor search from O(N²) to O(N) via cell hashing
  • Domain matrix transforms allow particles to follow moving/rotating objects
  • Kernel radius auto-scales with domain transformations when scaleKernelWithDomain is enabled
See also
  • SpatialGrid
Example
import { SPH } from '@three-blocks/core';
import { SphereGeometry, InstancedMesh, MeshStandardNodeMaterial } from 'three/webgpu';
import { storage, instanceIndex } from 'three/tsl';

const sph = new SPH({
  count: 2000,
  is3D: true,
  domainDimensions: new THREE.Vector3(20, 20, 20),
  h: 1.2,
  viscosityMu: 0.15,
  useMatrices: true
});

// Create instanced mesh for rendering particles
const geometry = new SphereGeometry(0.3, 8, 8);
const material = new MeshStandardNodeMaterial();
const positionNode = storage(sph.buffers.positions, 'vec3', sph.particleCount);
material.positionNode = positionNode.element(instanceIndex);
const mesh = new InstancedMesh(geometry, material, sph.particleCount);
// When useMatrices is enabled, you can feed instance matrices directly
mesh.instanceMatrix = sph.buffers.instanceMatrices.value;
scene.add(mesh);

// Simulation loop
async function animate() {
  await sph.step(renderer);
  renderer.render(scene, camera);
  requestAnimationFrame(animate);
}

Properties

.sdfVolumeConstraint : SDFVolumeConstraint|null

Methods

setDomainDimensions#

setDomainDimensions(dimensions : THREE.Vector3) : this

Manually set the simulation domain dimensions. Updates UBOs and synchronizes the spatial grid.

Parameters
dimensionsTHREE.Vector3
New domain dimensions.
Returns
this

setDomainFromObject#

setDomainFromObject(object : THREE.Object3D, options : Object) : this

Bind simulation domain to a Three.js object's world-space bounds. Particles will be constrained to the object's local space and follow its transforms.

Parameters
objectTHREE.Object3D
Target object (mesh or group).
optionsoptionalObject
Configuration options.
Default is {}.
  • paddingoptionalnumber | THREE.Vector3
    Extend domain bounds by padding.
    Default is 0.
  • autoUpdateoptionalboolean
    Update domain matrices every frame.
    Default is true.
  • simulationScaleoptionalnumber | THREE.Vector3
    Override domain scale for visualization.
    Default is null.
Returns
this

attachSpatialGrid#

attachSpatialGrid(grid : SpatialGrid) : this

Attach an external SpatialGrid instance for neighbor acceleration. Rebuilds compute passes to use grid-accelerated lookups.

Parameters
gridSpatialGrid
External SpatialGrid instance.
Returns
this

setSmoothingRadius#

setSmoothingRadius(radius : number) : this

Update the SPH smoothing kernel radius (h parameter). Recomputes kernel coefficients and syncs spatial grid cell size.

Parameters
radiusnumber
New smoothing radius (h).
Returns
this

setRestDensity#

setRestDensity(value : number|null|undefined) : this

Set rest density manually. Passing null/undefined re-enables auto rest density.

Parameters
valuenumber | null | undefined
Returns
this

setMass#

setMass(value : number) : this

Set particle mass. Recomputes auto rest density when enabled.

Parameters
valuenumber
Returns
this

setKernelScaleEnabled#

setKernelScaleEnabled(enabled : boolean) : this

Enable/disable automatic kernel radius scaling with domain transformations.

Parameters
enabledboolean
Whether to scale h with domain scale.
Returns
this

enableSpatialGrid#

enableSpatialGrid(options : Object) : this

Create and attach an internal spatial grid for neighbor acceleration. Automatically configures grid based on current domain and kernel radius.

Parameters
optionsoptionalObject
Options forwarded to SpatialGrid constructor.
Default is {}.
Returns
this

setSpatialGridEnabled#

setSpatialGridEnabled(enabled : boolean, options : Object) : this

Toggle spatial grid acceleration.

Parameters
enabledboolean
Enable (true) or disable (false) spatial grid.
optionsoptionalObject
Options passed to enableSpatialGrid() if enabling.
Returns
this

detachSpatialGrid#

detachSpatialGrid() : this

Detach and dispose of the spatial grid, reverting to naive O(N²) neighbor search.

Returns
this

syncSpatialGrid#

syncSpatialGrid() : this

Synchronize spatial grid configuration with current domain and kernel radius. Automatically called when domain or kernel changes.

Returns
this

step#

step(renderer : THREE.WebGPURenderer) : Promise<void>

Advance the simulation by one frame using GPU compute passes. Executes: grid update → density → pressure → forces → interaction → integration.

Parameters
rendererTHREE.WebGPURenderer
WebGPU renderer instance.
Returns
Promise<void>

attachGUI#

attachGUI(gui : Object, options : Object) : Object

Attach SPH parameters to a GUI for interactive tuning. Compatible with lil-gui, dat.gui, and Three.js Inspector.

Parameters
guiObject
GUI instance (e.g., new GUI() from lil-gui or renderer.inspector.createParameters()).
optionsoptionalObject
Configuration options.
Default is {}.
  • folderNameoptionalstring
    Name for the main folder.
    Default is 'SPH'.
  • openoptionalboolean
    Whether folders start open.
    Default is false.
Returns
Object — Object containing created GUI folders: { main, physics, simulation, domain, pointer }.

Type Definitions

SPHOptions#

count:number, is3D:boolean, domainDimensions:THREE.Vector3, mass:number, +19 more
Properties
countoptionalnumber
Number of particles to simulate.
Default is 5000.
is3Doptionalboolean
Enable 3D mode; false uses 2D kernels with single z-layer.
Default is true.
domainDimensionsoptionalTHREE.Vector3
Simulation domain size.
Default is new THREE.Vector3(32, 32, 32).
massoptionalnumber
Particle mass.
Default is 0.4.
hoptionalnumber
Smoothing kernel radius (SPH h parameter).
Default is 1.0.
restDensityoptionalnumber | null
Target rest density for the fluid. If null/undefined, it is auto-computed from mass, h, and kernel dimensionality (2D/3D).
Default is null.
pressureStiffnessoptionalnumber
Pressure force multiplier (stiffness constant).
Default is 100.0.
viscosityMuoptionalnumber
Viscosity coefficient for inter-particle friction.
Default is 0.12.
restitutionoptionalnumber
Coefficient of restitution for domain boundary collisions (0 = inelastic, 1 = elastic).
Default is 0.1.
maxSpeedoptionalnumber
Maximum allowed particle velocity magnitude (clamps velocity during integration to avoid runaway speeds).
Default is 15.0.
gravityoptionalTHREE.Vector3
Constant acceleration applied during integration.
Default is new THREE.Vector3(0, -9.81, 0).
fixedTimeStepoptionalnumber | null
Fixed timestep (in seconds). Set to null to use variable dt based on the render loop.
Default is 1/60.
maxSubstepsoptionalnumber
Maximum number of fixed timesteps processed per frame (prevents spiraling after long pauses).
Default is 5.
maxFrameDeltaoptionalnumber
Maximum frame delta (in seconds) added to the accumulator to avoid huge jumps after tab switches.
Default is 0.1.
debugoptionalboolean
Enable debug buffers and logging.
Default is false.
useDirectionoptionalboolean
Allocate buffers for smoothed particle directions (useful for oriented rendering).
Default is false.
scaleKernelWithDomainoptionalboolean
Scale smoothing radius proportionally with domain scale changes.
Default is true.
useSpatialGridoptionalboolean
Enable internal spatial grid acceleration (O(N) vs O(N²)).
Default is true.
useMatricesoptionalboolean
When true, writes per-instance transformation matrices to a storage buffer. Enables GPU culling with custom instanceMatrix on InstancedMesh (requires Three.js r182+).
Default is false.
spatialGridOptionsoptionalObject
Options passed to the internal SpatialGrid instance.
Default is {}.
spatialGridoptionalSpatialGrid
Attach a preconfigured SpatialGrid instance.
Default is null.
initialPositionsoptionalTHREE.StorageInstancedBufferAttribute
Optional external positions buffer to initialize particle positions from (e.g., from ComputeBVHSampler). Positions can be vec3 or vec4. Invalid positions (zero vectors) are automatically scattered to prevent spatial clustering.
Default is null.
sdfVolumeConstraintoptionalSDFVolumeConstraint
Optional SDF volume boundary constraint for complex boundaries.
Default is null.

SPHBuffers#

positions:THREE.InstancedBufferAttribute, velocities:THREE.InstancedBufferAttribute, densities:THREE.InstancedBufferAttribute, pressures:THREE.InstancedBufferAttribute, +4 more
Properties
positionsTHREE.InstancedBufferAttribute
Particle world positions (vec3).
velocitiesTHREE.InstancedBufferAttribute
Particle velocities (vec3).
densitiesTHREE.InstancedBufferAttribute
Computed particle densities (float).
pressuresTHREE.InstancedBufferAttribute
Computed particle pressures (float).
pressureForcesTHREE.InstancedBufferAttribute
Pressure gradient forces (vec3).
viscosityForcesTHREE.InstancedBufferAttribute
Viscosity forces (vec3).
prevVelocitiesoptionalTHREE.InstancedBufferAttribute
Previous frame velocities (optional, if useDirection enabled).
directionsoptionalTHREE.InstancedBufferAttribute
Smoothed directions (optional, if useDirection enabled).