Configuration
Full prop reference for FluidConfig. Every field is optional — the engine fills in
defaults at construction time. Pass these as props to <Fluid>. Presets expose only their documented common and scene-specific props; their physics recipes are fixed.
Simulation
Core physics parameters that control grid resolution, dissipation, and solver behavior.
| Prop | Type | Default | Description |
|---|---|---|---|
simResolution | number | 128 | Velocity grid resolution. |
dyeResolution | number | 1024 | Dye grid resolution. Clamped to 512 if linear filtering is unsupported. |
densityDissipation | number | 1 | How fast dye fades. |
initialDensityDissipation | number | same as densityDissipation | Starting dissipation value, ramped to densityDissipation over the duration. No ramp by default. |
initialDensityDissipationDuration | number | 0 | Seconds over which to ramp from initial to steady dissipation. 0 disables the ramp. |
velocityDissipation | number | 0.2 | How fast velocity fades. |
advectionScheme | 'semilagrangian' | 'maccormack' | 'semilagrangian' | Velocity advection scheme. 'maccormack' can keep flow/structured
scenes crisper, but can look angular or cubey on diffuse decorative dye. Dye and
scalars stay semi-Lagrangian, and devices without linear filtering fall back to 'semilagrangian'. Construct-only. |
maxTimeStep | number | 1 / 60 | Maximum simulated seconds per solver substep. Lower values help fast, narrow flows stay stable. |
substeps | number | 1 | Minimum solver substeps per animation frame, independent of presentation cadence. Higher values improve stability at extra GPU cost. |
viscosity | number | 0 | Dimensionless implicit velocity diffusion. Use small values for smoother browser-GPU CFD scenes. |
viscosityIterations | number | 8 | Jacobi iterations for the viscosity solve. |
wallFriction | number | 0 | Velocity damping near interior obstruction masks. Approximates wall shear/no-slip drag. |
wallFrictionWidth | number | 1 | Width of the obstruction-adjacent wall-friction band in simulation cells. |
pressure | number | 0.8 | Pressure solver weight. |
pressureIterations | number | 20 | Pressure solver iterations per frame. |
autoPerformance | boolean | false | Opt-in frame-time governor. Under sustained load it lowers Bucket-A quality only: pressure iterations first, then substeps. It never auto-restores quality, and deterministic advance() runs ignore it. |
autoPerformanceTargetFrameMs | number | 1000 / 60 | Average live-frame budget used by autoPerformance. Use approximately 33.33, 16.67, or 8.33 for 30, 60, or 120 Hz targets. Bucket A. |
autoPerformanceMinPressureIterations | number | 8 | Lower bound for autoPerformance pressure-iteration shedding. |
autoPerformanceMinSubsteps | number | 1 | Lower bound for autoPerformance substep shedding. |
curl | number | 30 | Vorticity confinement strength. |
vorticityAdaptive | number | 0 | Adaptive vorticity confinement blend. 0 disables adaptive gating (legacy
magnitude); 1 enables full local adaptive scaling by vorticity magnitude.
Confinement is separately attenuated next to solid boundaries (a bugfix), so output
near obstructions differs from prior versions regardless of this value. |
Splats
Control how pointer-driven splats are created.
| Prop | Type | Default | Description |
|---|---|---|---|
splatRadius | number | 0.25 | Splat radius in NDC units. |
splatForce | number | 6000 | Splat impulse force multiplier. |
splatOnHover | boolean | false | Create splats on mouse or pen move without requiring a press (never for touch). No effect when pointerInput is false. |
pointerInput | boolean | true | Enable mouse, touch and pen input (Pointer Events). Drags that leave the canvas keep splatting until release; pen pressure scales force 0.5x-1.5x. While true on a canvas target the canvas gets touch-action: none; when false it does not block touch scrolling. |
pointerTarget | 'canvas' | 'window' | 'canvas' | Where to attach pointer listeners. 'window' drives the sim from pointer activity anywhere on the page and never blocks touch scrolling. |
Visuals
Shading, pointer color cycling, pause, and background.
| Prop | Type | Default | Description |
|---|---|---|---|
shading | boolean | true | Diffuse relief from independently deposited thickness, not pigment brightness. Equal splats, including black pigment, have equal geometry. This passive thin layer is not a calibrated free-surface solve; shading intentionally differs from 0.8.0. Recompiles the display program. |
specular | number | 0 | Opt-in 0–1. Glossy studio-light highlight on the same surface (Blinn-Phong
with Schlick Fresnel). Independent of shading. Turning it on or off
recompiles the display program; other values are hot. |
refraction | number | 0 | Opt-in 0–1. Refracts the image under the dye: the distortion image, or the
fluid seen through glass. No effect on plain fluid, reveal, or page
content behind a transparent canvas. No extra textures; values above 0 are hot. |
colorful | boolean | true | Rotate pointer/touch splat colors over time. Does not change hand-authored presetSplats. |
colorUpdateSpeed | number | 10 | Pointer/touch color rotation rate (1/seconds). Only matters when colorful is true. |
maxFps | number | null | 0 | Opt-in maximum presented frames per second (for example 60 on 120 Hz displays presents half as many frames, which also halves presented motion cadence there). Simulation, input, and automatic splats still run every animation frame; only bloom, sunrays, display, glass, and presentation are capped. 0/null presents every frame. Paused invalidations, resize/resume, explicit renders and the final settle frame bypass the cap. Negative/nonfinite values are ignored; undefined preserves the resolved hot value. Bucket A; no texture allocation or shader compilation. |
paused | boolean | false | Pause simulation stepping. RAF stays live; dirty invalidations render immediately, stable images submit no rendering. |
backColor | RGB | { r: 0, g: 0, b: 0 } | Background color in 0-255 RGB (CSS-style). Normalized internally before reaching the shader. |
transparent | boolean | false | Render with a transparent background. |
minContrast | number | 0 (off) | WCAG contrast floor (1-21) the display pass enforces against contrastColor: failing pixels are lightened or darkened with hue kept; pixels already passing against the reference are untouched. Glass reflections are excluded. FluidText defaults to 4.5 with an outline halo, not a fill correction; 3 is an opt-in for large text. Toggling on/off recompiles the display shader; changing the value is hot. |
contrastColor | RGB | null | null (backColor) | Reference colour (0-255) for minContrast: the page behind transparent canvases, the text colour over opaque ones. No default: without it the correction is off (a guessed page colour would paint the canvas grey). |
contrastMode | 'floor' | 'outline' | 'floor' | Outline draws a 1.5 CSS px halo around svgPath masks, preserving interior dye (SDF on WebGL2, coverage mask on WebGL1). FluidText uses outline. Other shapes use floor. |
Tone mapping
| Prop | Type | Default | Description |
|---|---|---|---|
toneMapping | 'neutral' | 'agx' | 'none' | 'none' | How bright dye and bloom are brought into display range. 'none' (default) clips each channel exactly as 0.8.0 did, so every preset keeps its
authored look and saturated HDR dye (fire, lava) stays vivid. Opt-in 'neutral' (Khronos PBR Neutral shoulder) leaves in-range colours
unchanged and rolls highlights off smoothly instead of clipping to white.
Opt-in 'agx' is a softer, filmic curve that desaturates highlights
more. Hot-updatable: recompiles only the display program, no framebuffer
allocation. |
Authored colours (splat and preset dye, backColor, obstructionColor)
are display-referred sRGB. Bloom is encoded and added to the dye as in 0.8.0. With 'neutral' or 'agx' the combined colour is decoded to linear
light, tone-mapped and encoded to sRGB once. Every mode is then composited over backColor and blue-noise dithered to reduce 8-bit banding.
Bloom
Post-processing glow effect.
| Prop | Type | Default | Description |
|---|---|---|---|
bloom | boolean | true | Enable bloom effect. |
bloomIterations | number | 8 | Bloom blur iterations. |
bloomResolution | number | 256 | Bloom framebuffer resolution. |
bloomIntensity | number | 0.8 | Bloom intensity multiplier. |
bloomThreshold | number | 0.6 | Brightness (max channel) threshold for bloom. |
bloomSoftKnee | number | 0.7 | Bloom soft-knee curve. |
Sunrays
Volumetric light ray effect.
| Prop | Type | Default | Description |
|---|---|---|---|
sunrays | boolean | true | Enable sunrays effect. |
sunraysResolution | number | 196 | Sunrays framebuffer resolution. |
sunraysWeight | number | 1 | Sunrays intensity weight. |
Initial Splats
Splats created once at engine construction. These are construct-only (Bucket D) — changing them at runtime has no effect. initialSplatCount, initialSplatCountMin, and initialSplatCountMax are clamped to 0–64.
| Prop | Type | Default | Description |
|---|---|---|---|
initialSplatCountMin | number | 5 | Minimum number of initial random splats. |
initialSplatCountMax | number | 25 | Maximum number of initial random splats. |
initialSplatCount | number | undefined | — | Exact initial splat count. Overrides min/max when set. |
seed | number | auto-generated | 32-bit unsigned integer seed for the deterministic PRNG. Reused across resizes for consistent patterns. |
presetSplats | PresetSplat[] | — | Hand-crafted splats applied after the random initial splats. Combine with initialSplatCount: 0 to suppress random splats. |
requireHardwareAcceleration | boolean | false | Reject a software/SwiftShader rendering path (failIfMajorPerformanceCaveat). When true and only a software renderer exists, the component shows its WebGL fallback instead of animating on a slow CPU path. Construct-only. See ADR-0041. |
maxPixelRatio | number | null | null | Component drawing-buffer DPR cap. The default, null, uses the native device pixel ratio; pass a number such as 2 to cap physical pixels on DPR 3+ screens. Texture allocation caps use physical pixels, while small-canvas quality tiers use CSS pixels, so DPR alone does not disable or enable effects. Construct-only. |
Automatic Splats
Automatic splat generation for ambient motion without pointer input. Think of it as a timer that injects small bursts of dye and velocity.
| Prop | Type | Default | Description |
|---|---|---|---|
autoSplatRate | number | 0 | Automatic burst rate in splats per second. 0 = disabled. |
autoSplatCount | number | 1 | Number of splats emitted each automatic burst. Clamped to 0–16. |
autoSplatColor | RGB | null | null | Fixed color for automatic splats (0-1 linear range). null = fresh random color per splat. |
autoSplatVelocityX | number | 0 | X velocity for automatic splats (raw, not scaled by splatForce). Ignored when autoSplatSwirl is nonzero. |
autoSplatVelocityY | number | 0 | Y velocity for automatic splats (raw). Negative = downward in DOM. Ignored when autoSplatSwirl is nonzero. |
autoSplatCenterX | number | 0.5 | Horizontal center of the spawn band: 0 = left, 0.5 = center, 1 = right. |
autoSplatCenterY | number | 0.5 | Vertical center of the spawn band: 0 = bottom, 0.5 = center, 1 = top. |
autoSplatEvenX | boolean | false | Within each burst, use equal x positions such as 25%, 50%, 75% instead of random x positions. |
autoSplatSwirl | number | 0 | Orbital velocity around the container/canvas center. Positive = counter-clockwise; negative = clockwise. |
autoSplatBandHeight | number | 0.1 | Height of the spawn band. 0 = one horizontal line, 0.1 = ±5%, 2.0 = full canvas. |
autoSplatBandWidth | number | 1.0 | Width of the spawn band. 0 = one vertical line, 1.0 = full canvas width. Ignored when autoSplatEvenX is true. |
Container
Confine the simulation to a geometric shape. The boundary is physically enforced, not just a visual clip.
| Prop | Type | Default | Description |
|---|---|---|---|
containerShape | ContainerShape | null | null | Shape constraint for the fluid. Supports circle, frame, roundedRect, annulus, and svgPath. null = full rectangle. |
openBoundary | boolean | false | When true, fluid flows freely at boundaries instead of bouncing back. Shape becomes a visual crop, not a physical wall. |
Glass
Simulates a glass vessel effect with refraction and specular highlights. Requires a containerShape.
| Prop | Type | Default | Description |
|---|---|---|---|
glass | boolean | false | Enable glass vessel post-processing. Ignored when containerShape is null. |
glassThickness | number | 0.04 | Wall thickness in UV units. Controls how wide the refraction band is at the boundary. |
glassRefraction | number | 0.4 | Refraction strength, 0-1. Mapped internally to IOR 1.0-2.0. |
glassReflectivity | number | 0.12 | Specular reflectivity (Fresnel F0), 0-1. 0 = matte, 1 = mirror. |
glassChromatic | number | 0.15 | Chromatic aberration strength, 0-1. Splits refraction into R/G/B for prismatic fringes. |
Reveal
Dye acts as an opacity mask — scratch to reveal content behind. Colors are in 0-1 linear range.
| Prop | Type | Default | Description |
|---|---|---|---|
reveal | boolean | false | Enable reveal mode. Dye becomes a transparency mask with iridescent fringes. |
revealSensitivity | number | 0.1 | Multiplier on dye intensity before the power curve. Higher = easier reveal. |
revealCurve | number | 0.5 | Power exponent for reveal alpha. Higher = crisper edge, lower = softer gradient. |
revealCoverColor | RGB | { r: 1, g: 1, b: 1 } | Cover layer color (0-1 linear). Visible before scratching. |
revealAccentColor | RGB | { r: 0.05, g: 0.16, b: 0.32 } | Fringe accent color (0-1 linear). Shown between cover and revealed content. |
revealFringeColor | RGB | { r: 0.6, g: 0.7, b: 0.85 } | Outer fringe color (0-1 linear). Creates a two-tone fringe: cover → fringe → accent → transparent. |
Distortion
Velocity field warps an underlying image like liquid glass. Mutually exclusive with reveal.
| Prop | Type | Default | Description |
|---|---|---|---|
distortion | boolean | false | Enable distortion mode. Cursor movement ripples and warps the image. |
distortionPower | number | 0.4 | How strongly velocity warps UV coordinates, 0-1. |
distortionImageUrl | string | — | URL of the image to distort. Required when distortion is true. Loaded asynchronously. |
distortionFit | 'cover' | 'contain' | 'cover' | How the image fits the canvas. 'cover' fills and crops, 'contain' fits within. |
distortionScale | number | 1.0 | Image scale factor. Values > 1 zoom out, < 1 zoom in. |
distortionBleedX | number | 0 | Horizontal bleed fraction (0-0.5). Canvas extends invisibly beyond visible area to prevent edge bounce. |
distortionBleedY | number | 0 | Vertical bleed fraction (0-0.5). See distortionBleedX. |
Sticky
Dye clings to a mask region by modulating physics. Composable with container shapes, bloom, sunrays, and glass. Mutually exclusive with reveal and distortion.
| Prop | Type | Default | Description |
|---|---|---|---|
sticky | boolean | false | Enable sticky mode. Triggers mask texture rebuild. |
stickyMask | StickyMask | — | Mask shape that dye sticks to. Supports text, SVG paths, or both. Required when sticky is true. |
stickyStrength | number | 0.9 | How strongly dissipation is reduced on the mask, 0-1. 1 = dye never fades on mask. |
stickyPressure | number | 0.15 | Artificial pressure on the mask to push fluid around the shape. |
stickyAmplify | number | 0.3 | Splat intensity multiplier on the mask region. Higher = more dye deposited. |
Obstructions
Interior obstacles the fluid flows around — the inverse of containerShape, and orthogonal to it. See the Container Shapes page for the Obstruction descriptor and behavior.
| Prop | Type | Default | Description |
|---|---|---|---|
obstructions | ReadonlyArray<Obstruction> | undefined | Interior obstacles the fluid flows around. Union into one combined mask; allowed region is container × (1 − obstruction). Changing it rebuilds the obstruction mask texture (Bucket C) and recompiles the display shader. Mutually exclusive with distortion. |
obstructionColor | RGB | null | null | Fill color painted over obstruction footprints in the display pass, in 0–255 RGB (same convention as backColor). Makes solid bodies read as visible objects instead of background-colored silhouettes (e.g. the Karman cylinder). Anti-aliased edges from the rasterized mask. null keeps the silhouette. Presence toggles a display keyword (Bucket B); the value itself is a per-frame uniform. |
Flow scene
flow is the higher-level API for believable fixed or semi-fixed scenes. It keeps
legacy splats available, but lets presets describe persistent inlets, edge-drain outlets, scalar fields,
body forces, prescribed fields, and field-aware visualization directly.
| Prop | Type | Default | Description |
|---|---|---|---|
flow | FlowConfig | null | undefined | Additive flow-scene controls. mode may be 'live', 'prescribed', or 'hybrid'. Supports sources, edge-drain outlets, scalarFields, forces, prescribed, and visualization. flow.boundary overrides individual edges; openBoundary is the fallback. reveal and distortion remain authoritative display modes. |
Use sources for steady inlet lines/points/rects, outlets for edge sponge/drain zones, scalarFields for temperature/ink-like quantities, and forces for gravity,
pressure-gradient body forces, or scalar-coupled buoyancy. prescribed.kind: 'grid' allows custom uploaded
flow fields. In mode: 'prescribed', velocity remains prescribed and ignores
source velocity and forces; use 'hybrid' to add live velocity before projection.
Uploaded grid fields should be immutable or carry a bumped version when reused.
Hot-update buckets
Non-finite top-level numeric config values (NaN, ±Infinity) are ignored and the
previous value is kept.
When props change at runtime, setConfig() classifies each field into one of four buckets
that determine how the change takes effect:
Bucket A — Hot scalars
Written directly to the internal config object and picked up on the next simulation frame.
Zero overhead. Most numeric props live here: densityDissipation, velocityDissipation, maxTimeStep, substeps, viscosity, viscosityIterations, wallFriction, wallFrictionWidth, pressure, curl, vorticityAdaptive, autoPerformance, autoPerformanceTargetFrameMs, autoPerformanceMinPressureIterations, autoPerformanceMinSubsteps, splatRadius, splatForce, colorUpdateSpeed, bloomIntensity, sunraysWeight, all autoSplat* props,
all glass* scalars, all reveal* scalars, all distortion* scalars, stickyStrength, stickyPressure, stickyAmplify, pointerTarget, openBoundary, and most flow source/force
scalars.
Bucket B — Keyword recompile
Triggers a display shader recompile (~1 ms). Applies to feature toggles that change which
GLSL code paths are active: shading, bloom, sunrays, reveal, distortion, toneMapping, specular or refraction crossing 0, and field visualization inside flow. Positive specular/refraction changes are hot scalars.
Bucket C — FBO rebuild
Triggers framebuffer reallocation. Applies to resolution fields: simResolution, dyeResolution, bloomResolution, bloomIterations,
and sunraysResolution. Also triggered by containerShape changes
(mask texture rebuild), obstructions changes (obstruction mask rebuild +
display keyword recompile), scalar-field allocation inside flow, and glass toggle (scene FBO alloc/dispose).
Bucket D — Construct-only
Ignored by setConfig() after construction. These values are consumed once when the
engine is created: seed, initialSplatCountMin, initialSplatCountMax, initialSplatCount, presetSplats, and requireHardwareAcceleration, maxPixelRatio, and advectionScheme.