Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SPILL

SPILL — the fluid block collapses, settles into a pool, and splashes when stirred with the pointer

Real-time MLS-MPM fluid simulation, running entirely on the GPU via Three.js WebGPURenderer and TSL compute shaders.

Built by Aung Pyae Soe (Bill) · billcreates.tech

Run

npm install && npm run dev

Needs a WebGPU-capable browser — Chrome or Edge on desktop. Other browsers get a styled fallback message instead of a crash.

npm run build     # tsc --noEmit + vite build
npm run preview   # serve the production build

Interact

Move the pointer across the fluid to stir it — motion near the cursor pushes particles and flares them bright.

Press h (or append #debug to the URL) to open a hidden tweak panel over the sim and render parameters.

How it works

The fluid is simulated with MLS-MPM (Moving Least Squares Material Point Method) on a fixed 64³ grid, advecting ~131k particles. Each substep runs five TSL compute passes: clearGrid zeroes the grid's fixed-point accumulators, p2g1 scatters particle mass and APIC momentum onto the grid, p2g2 derives density and an equation-of-state pressure per particle and scatters the resulting stress, gridUpdate decodes momentum into velocity, applies gravity, and enforces box boundaries, and g2p gathers grid velocity back onto particles, applies the pointer force, and advects positions. Because WebGPU atomics only exist for i32/u32, all grid scatter uses fixed-point integers via atomicAdd/atomicLoad. Rendering is a single instanced SpriteNodeMaterial pass — additive, soft-round monochrome sprites whose brightness is driven by particle speed — reading positions and velocities straight off the sim's storage buffers with no CPU readback.

Key params

Name Where Default Effect
gravity sim.uniforms.gravity -0.3 Downward acceleration per substep
stiffness sim.uniforms.stiffness 3.0 EOS pressure response to compression — higher resists compression more
restDensity sim.uniforms.restDensity 4.0 Density at which pressure is zero
dynamicViscosity sim.uniforms.dynamicViscosity 0.1 Damps velocity gradients — higher reads as thicker fluid
dt sim.uniforms.dt 0.15 Substep timestep; larger is faster but less stable
substeps MPMParams.substeps (constructor only) 2 Substeps run per rendered frame
particleCount MPMParams.particleCount (constructor only) 131072 Particle count, fixed at sim creation
mouseRadius sim.uniforms.mouseRadius 6.0 Falloff radius of the pointer's influence, in sim units
mouseStrength sim.uniforms.mouseStrength 1.0 Pointer force multiplier
tint look.uniforms.tint ice blue #8ec8e8-ish Base particle color
baseGlow look.uniforms.baseGlow 0.16 Brightness at rest
speedGlow look.uniforms.speedGlow 0.85 Extra brightness added by motion
speedMax look.uniforms.speedMax 1.6 Speed at which glow reaches full extra brightness
particleScale look.uniforms.particleScale 0.32 Sprite world size

Structure

index.html          Black page, #app canvas mount, footer credit, #nogpu fallback
src/main.ts          Boot: WebGPU check, module wiring, frame loop
src/stage.ts          WebGPURenderer + scene + camera + resize
src/sim/mpm.ts        MLSMPMSim: buffers, 5 compute passes, update(), uniforms
src/pointer.ts        PointerForce: pointer → raycast → sim-space pos/vel uniforms
src/material.ts        Particle render: additive soft-round sprites, speed-driven glow
src/gui.ts             Hidden lil-gui tweak panel (`h` key / #debug)

The sim is self-contained with no runtime network assets, and every module besides main.ts is import-isolated from the others — main.ts is the only file that reaches across modules — so src/ can be lifted whole into an Astro island later.

About

Real-time MLS-MPM fluid simulation — Three.js WebGPU + TSL compute, 131k particles

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages