Visual FX catalog
The ftui-extras visual_fx module ships a collection of effects that
render at sub-character resolution via the VFX rasterizer.
Each effect is a plain struct you construct, tick, and render into a
Frame. All of them respect the FxQuality
degradation tier and consume only ThemeInputs.
This page documents every effect that has a concrete implementation in
the tree. Items marked with {/* TODO */} are referenced in design docs
but not yet in source.
All effects are exported from
visual_fx/effects/mod.rs.
How to view effects
Most demo harnesses check the FTUI_HARNESS_VIEW environment variable to
switch screens. To see the visual FX showcase:
FTUI_HARNESS_VIEW=visual_effects cargo run -p ftui-demo-showcaseThe concrete screen (Metaballs, Plasma, etc.) is usually selected by a
second env var or a keybinding inside the showcase. See
screen catalog for the full set of
FTUI_HARNESS_VIEW values.
Metaballs
What it draws. Smooth blobs that merge as they approach each other — the classic iso-surface of a sum of inverse-squared fields.
Key equation. Each ball at position with radius contributes a field:
The rendered iso-surface is the set where for some threshold .
Source: effects/metaballs.rs (55 KB).
Public API: MetaballsFx, MetaballsParams, MetaballsPalette,
Metaball.
How to view: FTUI_HARNESS_VIEW=visual_effects then pick the
metaballs screen.
Plasma
What it draws. Animated interference patterns — coloured waves that blend, reminiscent of 1990s demoscene intros.
Key equation. The standard plasma wave is a sum of sinusoids:
This is mapped through a palette to produce per-cell RGB. A low-quality
variant (plasma_wave_low) uses one or two sine ops only; the full
variant mixes four or more frequencies.
Source: effects/plasma.rs (126 KB).
Public API: PlasmaFx, PlasmaPalette, plasma_wave,
plasma_wave_low.
How to view: FTUI_HARNESS_VIEW=visual_effects then pick the plasma
screen.
Doom Fire
What it draws. Animated fire rising from the bottom of the viewport — the classic PSX Doom fire effect.
Key equation. A cellular automaton on a heat grid. Each frame, for each cell :
where is heat, is the next frame’s heat, and is a small random decay plus horizontal drift. Heat is mapped to a red → yellow → white palette.
Source: effects/doom_fire.rs (24 KB).
Public API: DoomFireFx.
Feature flag: always available (no gate), since the effect is tiny.
How to view: FTUI_HARNESS_VIEW=visual_effects and select doom fire.
Screen Melt
What it draws. The “screen dripping downward like melting wax” effect used as a transition in classic DOOM between levels.
Key equation. Each column has an offset that increases monotonically with randomised speed. Displayed pixel reads from source pixel until exceeds the viewport height.
Source: effects/screen_melt.rs (32 KB).
Public API: ScreenMeltFx.
How to view: FTUI_HARNESS_VIEW=visual_effects and trigger the melt
transition.
Underwater Warp
What it draws. A wavy distortion of the scene, as if viewed through moving water.
Key equation. A displacement field samples source pixels with an offset given by two orthogonal sine waves:
The final pixel is read from .
Source: effects/underwater_warp.rs (35 KB).
Public API: UnderwaterWarpFx.
How to view: FTUI_HARNESS_VIEW=visual_effects and select the warp
screen.
Doom Melt (feature-gated)
What it draws. A combined Doom Fire + Screen Melt: the fire rises while the old frame melts away.
Source: effects/doom_melt/.
Public API: DoomMeltFx.
Feature flag: doom (implies visual-fx).
How to view: build with --features doom then
FTUI_HARNESS_VIEW=visual_effects.
Quake Console (feature-gated)
What it draws. A sliding drop-down console overlay styled after Quake’s dev console. Not strictly a visual effect in the field-math sense — it is a scripted animation of a pane entering from the top.
Key behaviour. Linear interpolation of height from 0 to target with configurable easing:
Source: effects/quake_console/.
Public API: QuakeConsoleFx.
Feature flag: quake (implies visual-fx).
How to view: build with --features quake then
FTUI_HARNESS_VIEW=visual_effects.
Samplers and field-building blocks
Not effects in themselves, but the primitives every effect uses:
Source: effects/sampling.rs.
| Item | Purpose |
|---|---|
Sampler trait | Compute a field value at normalised |
FnSampler | Wrap a closure as a sampler |
MetaballFieldSampler | Sum of inverse-square contributions from multiple balls |
PlasmaSampler | Wraps plasma_wave as a sampler |
BallState | Position / velocity physics for metaballs |
CoordCache | Cache normalised coordinates for repeated sampling |
cell_to_normalized | Map cell coords to |
fill_normalized_coords | Iterate over cells emitting normalised coordinates |
You can build your own effect by providing a new Sampler implementation
and a canvas adapter.
Canvas adapters
Source: effects/canvas_adapters.rs.
| Adapter | Mode | For |
|---|---|---|
MetaballsCanvasAdapter | Braille / half-block (auto) | MetaballsFx |
PlasmaCanvasAdapter | Half-block | PlasmaFx |
Both are feature-gated behind canvas.
Additional effects referenced in design docs
These effects appear in the research notes but have no concrete implementation yet. Treat them as planned, not shipped.
| Effect | Status |
|---|---|
| Gray–Scott reaction–diffusion | {/* TODO: not in source */} |
| Clifford attractor | {/* TODO: possibly a sampler variant */} |
| Mandelbrot / Julia sets with deep zoom | {/* TODO: no dedicated module yet */} |
| Lissajous / Harmonograph | {/* TODO: planned */} |
| Flow field (curl / Perlin) | {/* TODO: can be built on FnSampler */} |
| Wave interference (slit diffraction) | {/* TODO: close to Plasma */} |
| Spiral galaxy (N-body) | {/* TODO: planned */} |
| Spin lattice (LLG dynamics) | {/* TODO: planned */} |
The scaffolding in sampling.rs is general enough to add most of these
as Sampler implementations plus a canvas adapter.
Common pitfalls
- Skipping
tick()beforerender. Every stateful effect exposes atick()method that advances its internal clock. Rendering without ticking gives a frozen image. - Re-creating the effect each frame. Effects carry internal state (ball positions, plasma phase, particle arrays). Construct once, store on your model, tick per frame.
- Running at
Fullquality on a huge viewport. The area clamp drops toReducedautomatically past ~16K cells; bypassing it manually makes you exceed the frame budget. - Feeding the effect a global theme. Effects only read
ThemeInputs. Derive aThemeInputsonce per theme change and cache it.
Where next
Why extras is its own crate, feature-flag matrix, ThemeInputs
contract.
Sub-character density in depth — Braille, half-blocks, quadrants.
VFX rasterizerThe full list of FTUI_HARNESS_VIEW screens including every visual
effect.
Per-feature gate matrix across the workspace.
Feature flags