This version is the production tuning surface for the same idea. It uses the WebGPU / TSL path from `three-fluid-fx/tsl`, where the effect is built with RenderPipeline output nodes, TSL factories, and WGSL compute helpers.
Live demo
What this demo teaches
Mega is the hero scene without page typography: a centered particle sculpture morphs through geometric and text targets while the same fluid field drives both particle motion and post-processing. In this variant, the relevant fluid output is TextureNode fields: velocityNode, densityNode, and dyeNode when dye is enabled.
- See how one morphing GPGPU particle system can reuse the 3D particle fluid response.
- Understand why the particle model matrix must be passed when the sculpture is scaled.
- Tune hero defaults such as Art Ink overlay, simple distortion, morph timing, and spring physics.
Implementation path
- Generate morph destinations
The particle helper builds sphere, tetrahedron, trefoil, TSL, and GL/SL target buffers, then uploads an interpolated destination texture every frame.
- Keep particles centered in world space
Resize maps the visible camera height to a stable particle scale, so the sculpture stays centered instead of following a DOM text column.
- Compose like the hero
The scene pass is distorted first and then receives the Art Ink overlay, matching the hero defaults while still exposing the Combined-style controls.
- Full scope
It keeps the core render path but adds controls, style choices, background handling, and parameters that matter when shipping the effect.
const particles = new MorphFlowParticles(renderer, {
size: 64,
holdSeconds: 6.5,
morphSeconds: 4.8,
})
pipeline.outputNode = fluidOverlay(
'artInk',
simpleDistortion(scenePass, fluid.densityNode, 0.45),
fluid.densityNode,
fluid.dyeNode,
fluid.velocityNode,
{ opacity: 0.5, vibrance: 0.5 },
)
renderer.setAnimationLoop(() => {
fluid.step(dt)
particles.step({ ...particleForces, modelMatrix: particles.mesh.matrixWorld }, morphTime)
pipeline.render()
}) Parameters to tune
| Parameter | What it controls | How to tune it |
|---|---|---|
holdSeconds + morphSeconds | Controls how long each target shape rests and how long the transition takes. | Use longer holds for documentation capture. Shorten morph duration only after the spring response feels stable. |
modelMatrix | Projects scaled particle positions into the correct screen-space fluid UVs. | Pass it every frame after position, scale, and rotation are updated. |
spring + zeta | Keeps particles readable while the morph target and fluid forces compete. | Start from the 3D particle defaults. Lower spring only when you intentionally want loose drift. |
overlay + distortion | Adds the hero post-processing layer around the particle scene. | Art Ink opacity and vibrance are the first controls to adjust before changing solver strength. |
Source landmarks
Start from examples/tsl/full/mega/main.ts. These are the parts worth reading first:
- MorphFlowParticles target generation and setDestinationData().
- The resize path that derives particle scale from camera viewport height.
- The per-frame order: sync params, update mesh transform, step fluid, step particles, render pipeline.
- The pipeline output: simpleDistortion followed by fluidOverlay.
Production notes
- Use this page for hero tuning without DOM text masking layout bugs.
- Keep reflect walls disabled when matching the landing-page feel.
- If fluid influence appears offset, inspect modelMatrix before changing force parameters.