TSL / WebGPU Full

Mega Demo: WebGPU / TSL Full walkthrough

Hero-style morphing particle sculpture with art ink overlay, fluid distortion, and full tuning controls. This walkthrough explains what the demo is doing, which library outputs it uses, and which parameters matter.
Hero demo

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

Full TSL Examples: Mega Demo Open example

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

  1. Generate morph destinations

    The particle helper builds sphere, tetrahedron, trefoil, TSL, and GL/SL target buffers, then uploads an interpolated destination texture every frame.

  2. 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.

  3. 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.

  4. 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.