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.

PropTypeDefaultDescription
simResolutionnumber128Velocity grid resolution.
dyeResolutionnumber1024Dye grid resolution. Clamped to 512 if linear filtering is unsupported.
densityDissipationnumber1How fast dye fades.
initialDensityDissipationnumbersame as densityDissipationStarting dissipation value, ramped to densityDissipation over the duration. No ramp by default.
initialDensityDissipationDurationnumber0Seconds over which to ramp from initial to steady dissipation. 0 disables the ramp.
velocityDissipationnumber0.2How 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.
maxTimeStepnumber1 / 60Maximum simulated seconds per solver substep. Lower values help fast, narrow flows stay stable.
substepsnumber1Minimum solver substeps per animation frame, independent of presentation cadence. Higher values improve stability at extra GPU cost.
viscositynumber0Dimensionless implicit velocity diffusion. Use small values for smoother browser-GPU CFD scenes.
viscosityIterationsnumber8Jacobi iterations for the viscosity solve.
wallFrictionnumber0Velocity damping near interior obstruction masks. Approximates wall shear/no-slip drag.
wallFrictionWidthnumber1Width of the obstruction-adjacent wall-friction band in simulation cells.
pressurenumber0.8Pressure solver weight.
pressureIterationsnumber20Pressure solver iterations per frame.
autoPerformancebooleanfalseOpt-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.
autoPerformanceTargetFrameMsnumber1000 / 60Average live-frame budget used by autoPerformance. Use approximately 33.33, 16.67, or 8.33 for 30, 60, or 120 Hz targets. Bucket A.
autoPerformanceMinPressureIterationsnumber8Lower bound for autoPerformance pressure-iteration shedding.
autoPerformanceMinSubstepsnumber1Lower bound for autoPerformance substep shedding.
curlnumber30Vorticity confinement strength.
vorticityAdaptivenumber0Adaptive 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.

PropTypeDefaultDescription
splatRadiusnumber0.25Splat radius in NDC units.
splatForcenumber6000Splat impulse force multiplier.
splatOnHoverbooleanfalseCreate splats on mouse or pen move without requiring a press (never for touch). No effect when pointerInput is false.
pointerInputbooleantrueEnable 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.

PropTypeDefaultDescription
shadingbooleantrueDiffuse 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.
specularnumber0Opt-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.
refractionnumber0Opt-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.
colorfulbooleantrueRotate pointer/touch splat colors over time. Does not change hand-authored presetSplats.
colorUpdateSpeednumber10Pointer/touch color rotation rate (1/seconds). Only matters when colorful is true.
maxFpsnumber | null0Opt-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.
pausedbooleanfalsePause simulation stepping. RAF stays live; dirty invalidations render immediately, stable images submit no rendering.
backColorRGB{ r: 0, g: 0, b: 0 }Background color in 0-255 RGB (CSS-style). Normalized internally before reaching the shader.
transparentbooleanfalseRender with a transparent background.
minContrastnumber0 (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.
contrastColorRGB | nullnull (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

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

PropTypeDefaultDescription
bloombooleantrueEnable bloom effect.
bloomIterationsnumber8Bloom blur iterations.
bloomResolutionnumber256Bloom framebuffer resolution.
bloomIntensitynumber0.8Bloom intensity multiplier.
bloomThresholdnumber0.6Brightness (max channel) threshold for bloom.
bloomSoftKneenumber0.7Bloom soft-knee curve.

Sunrays

Volumetric light ray effect.

PropTypeDefaultDescription
sunraysbooleantrueEnable sunrays effect.
sunraysResolutionnumber196Sunrays framebuffer resolution.
sunraysWeightnumber1Sunrays 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.

PropTypeDefaultDescription
initialSplatCountMinnumber5Minimum number of initial random splats.
initialSplatCountMaxnumber25Maximum number of initial random splats.
initialSplatCountnumber | undefined—Exact initial splat count. Overrides min/max when set.
seednumberauto-generated32-bit unsigned integer seed for the deterministic PRNG. Reused across resizes for consistent patterns.
presetSplatsPresetSplat[]—Hand-crafted splats applied after the random initial splats. Combine with initialSplatCount: 0 to suppress random splats.
requireHardwareAccelerationbooleanfalseReject 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.
maxPixelRationumber | nullnullComponent 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.

PropTypeDefaultDescription
autoSplatRatenumber0Automatic burst rate in splats per second. 0 = disabled.
autoSplatCountnumber1Number of splats emitted each automatic burst. Clamped to 0–16.
autoSplatColorRGB | nullnullFixed color for automatic splats (0-1 linear range). null = fresh random color per splat.
autoSplatVelocityXnumber0X velocity for automatic splats (raw, not scaled by splatForce). Ignored when autoSplatSwirl is nonzero.
autoSplatVelocityYnumber0Y velocity for automatic splats (raw). Negative = downward in DOM. Ignored when autoSplatSwirl is nonzero.
autoSplatCenterXnumber0.5Horizontal center of the spawn band: 0 = left, 0.5 = center, 1 = right.
autoSplatCenterYnumber0.5Vertical center of the spawn band: 0 = bottom, 0.5 = center, 1 = top.
autoSplatEvenXbooleanfalseWithin each burst, use equal x positions such as 25%, 50%, 75% instead of random x positions.
autoSplatSwirlnumber0Orbital velocity around the container/canvas center. Positive = counter-clockwise; negative = clockwise.
autoSplatBandHeightnumber0.1Height of the spawn band. 0 = one horizontal line, 0.1 = ±5%, 2.0 = full canvas.
autoSplatBandWidthnumber1.0Width 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.

PropTypeDefaultDescription
containerShapeContainerShape | nullnullShape constraint for the fluid. Supports circle, frame, roundedRect, annulus, and svgPath. null = full rectangle.
openBoundarybooleanfalseWhen 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.

PropTypeDefaultDescription
glassbooleanfalseEnable glass vessel post-processing. Ignored when containerShape is null.
glassThicknessnumber0.04Wall thickness in UV units. Controls how wide the refraction band is at the boundary.
glassRefractionnumber0.4Refraction strength, 0-1. Mapped internally to IOR 1.0-2.0.
glassReflectivitynumber0.12Specular reflectivity (Fresnel F0), 0-1. 0 = matte, 1 = mirror.
glassChromaticnumber0.15Chromatic 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.

PropTypeDefaultDescription
revealbooleanfalseEnable reveal mode. Dye becomes a transparency mask with iridescent fringes.
revealSensitivitynumber0.1Multiplier on dye intensity before the power curve. Higher = easier reveal.
revealCurvenumber0.5Power exponent for reveal alpha. Higher = crisper edge, lower = softer gradient.
revealCoverColorRGB{ r: 1, g: 1, b: 1 }Cover layer color (0-1 linear). Visible before scratching.
revealAccentColorRGB{ r: 0.05, g: 0.16, b: 0.32 }Fringe accent color (0-1 linear). Shown between cover and revealed content.
revealFringeColorRGB{ 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.

PropTypeDefaultDescription
distortionbooleanfalseEnable distortion mode. Cursor movement ripples and warps the image.
distortionPowernumber0.4How strongly velocity warps UV coordinates, 0-1.
distortionImageUrlstring—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.
distortionScalenumber1.0Image scale factor. Values > 1 zoom out, < 1 zoom in.
distortionBleedXnumber0Horizontal bleed fraction (0-0.5). Canvas extends invisibly beyond visible area to prevent edge bounce.
distortionBleedYnumber0Vertical 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.

PropTypeDefaultDescription
stickybooleanfalseEnable sticky mode. Triggers mask texture rebuild.
stickyMaskStickyMask—Mask shape that dye sticks to. Supports text, SVG paths, or both. Required when sticky is true.
stickyStrengthnumber0.9How strongly dissipation is reduced on the mask, 0-1. 1 = dye never fades on mask.
stickyPressurenumber0.15Artificial pressure on the mask to push fluid around the shape.
stickyAmplifynumber0.3Splat 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.

PropTypeDefaultDescription
obstructionsReadonlyArray<Obstruction>undefinedInterior 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.
obstructionColorRGB | nullnullFill 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.

PropTypeDefaultDescription
flowFlowConfig | nullundefinedAdditive 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.