This version keeps the integration small so the moving parts are visible. It uses the WebGL / GLSL path from `three-fluid-fx`, where the effect is built with EffectComposer passes, ShaderMaterial uniforms, and WebGL render targets.
Live demo
What this demo teaches
The fluid is a 2D screen-space field. A 3D particle first projects itself onto the screen to sample the field, then converts screen flow into world-space acceleration. In this variant, the relevant fluid output is Texture objects: velocityTexture, densityTexture, and dyeTexture when dye is enabled.
- Understand why camera matrices are required.
- Map 2D fluid motion into cameraRight and cameraUp world directions.
- Tune depth lift and side variation without losing the particle volume.
Implementation path
- Project world position to fluid UV
The update uses viewMatrix and projectionMatrix to find which fluid pixel sits behind each particle.
- Convert screen flow to world axes
flow.x maps to cameraRight and flow.y maps to cameraUp. That is why camera vectors are passed every frame.
- Add depth behavior separately
Depth lift and attenuation are art-direction controls. They should not be mixed with the basic screen-flow conversion.
- Minimal scope
It avoids GUI state and preset switching. Read it first when you need the smallest reliable version of the technique.
fluid.step(dt)
particles.step({
dt,
velocityField: fluid.velocityTexture,
viewMatrix: camera.matrixWorldInverse,
projectionMatrix: camera.projectionMatrix,
cameraRight,
cameraUp,
spring,
zeta,
flowStrength,
maxFlowSpeed,
}) Parameters to tune
| Parameter | What it controls | How to tune it |
|---|---|---|
viewMatrix + projectionMatrix | Project particle positions into screen space for fluid sampling. | Update them after camera resize and before the particle step. |
cameraRight + cameraUp | World directions that correspond to screen X and screen Y. | Read them from camera.matrixWorld each frame. |
depthLift | Extra motion along the camera depth or object depth direction. | Use lightly. It adds dimensionality but can flatten the volume if too strong. |
sideVariation | Per-particle variation for lateral response. | Raise for a more organic cloud. Lower for clean spherical motion. |
Source landmarks
Start from examples/glsl/minimal/particles-3d/main.ts. These are the parts worth reading first:
- Camera matrix and camera axis extraction.
- Projection from 3D position to fluid UV.
- World-space acceleration from screen-space flow.
- Depth lift, rotation, and attenuation controls.
Production notes
- Always update camera projection after resize before stepping the particles.
- If particles react in the wrong direction, check cameraRight and cameraUp first.
- Keep flowThreshold above background noise to prevent constant low-level buzzing.