Repository navigation
feat(shaders): add LiquidGradient - #244
Merged
hunterbecton merged 6 commits intoOct 12, 2026
Merged
Conversation
Name what an Effect's base-pass UV transform does, since SwirlGradient is a Source that CursorDisplacement bends that way. "Warp" on its own moves to Avoid, because Paper's Warp is a Source, not a UV warp.
Phase 1 of SHA-223. Each pixel traces 24 steps backward along the curl
of a periodic gradient noise and reads LinearGradient's repeating bands
where it lands, so swirl={0} draws LinearGradient's image exactly.
The flow pass draws the velocity into a half-float texture each frame,
because computing the noise inline at every step read 3.6 ms in the
Reactive card's window at 2x. With the texture it reads 0.35 ms there and
1.9 ms at 1440 by 900. Renderers that can't draw half floats compute it
inline instead.
Adds the docs page, a temporary tuning rig for the step count, step
length, and smaller eddies, and a dev benchmark route.
Phase 2 of SHA-223. speed turns each lattice arrow at its own rate (Perlin and Neyret's flow noise), so the eddies form, merge, and dissolve in place. A literal speed of 0 votes idle, so the scene parks. One hash word per corner supplies both the start angle and the spin, because a second hash per corner pushed the Reactive card's window past 0.4 ms at 2x. A temporary slide knob in the tuning rig moves the whole flow, for comparison.
Phase 3 and the liquid rework of SHA-223. Each pixel now averages the colors along its backward trace, which streaks the bands and a fractal paint field along the current, closer to the liquid look the author picked than folded marbling. A cached ramp texture colors each sample, and midpoint integration keeps traces on tight eddies. softness eases each stop in with smoothstep, fwidth keeps every edge one pixel wide, and streaks thinner than a pixel fade to the bands' average color. Mirrored band ends replace seams by default. The flow repeats every 8 eddies, and the average, ramp, and paint passes redraw only when their inputs change.
…faults
The defaults gate of SHA-223. The look is a liquid gradient now, so the
component, slug, and benchmark route take that name. The tuning rig is
gone. Mirrored band ends and the full path average are fixed, and each
feel constant lives in the module that uses it.
Each trace takes 8 steps of one flow read at the reach of the author's
12 midpoint steps. That looked the same and brought the Reactive card's
window at 2x from 0.57-0.63 ms to 0.34-0.38 ms, under its 0.4 ms
budget. The paint fades in as swirl rises to 0.2, so swirl={0} draws
straight bands.
Adds the catalog copy, the poster and thumbnail, and the visual spec
with its baselines. The benchmark keeps a LinearGradient baseline that
shows when another tab is sharing the GPU.
Contributor
|
React Doctor found no new issues. 🎉 Reviewed by React Doctor for commit |
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The required release changeset and focused pre-pass lifecycle coverage are missing.
2 open findings
What changed in this PR
Adds LiquidGradient, a streaked gradient Source optimized through cached GPU pre-passes, with public exports and docs integration.
Changes:
- Implements flow tracing, paint noise, band interpolation, and texture caching.
- Adds the interactive docs page, benchmark route, posters, and visual baselines.
- Defines “UV warp” in the glossary.
| File | Description |
|---|---|
scripts/build-posters.sh |
Registers the poster build. |
packages/shaders/src/components/liquid-gradient/shader.tsx |
Composes the shader and pre-passes. |
packages/shaders/src/components/liquid-gradient/paint.ts |
Implements cached fractal paint. |
packages/shaders/src/components/liquid-gradient/liquid-gradient.tsx |
Defines the public component API. |
packages/shaders/src/components/liquid-gradient/flow.ts |
Implements curl flow and tracing. |
packages/shaders/src/components/liquid-gradient/bands.ts |
Implements cached band coloring. |
packages/shaders/src/components/index.ts |
Exports LiquidGradient. |
GLOSSARY.md |
Defines UV warp terminology. |
apps/docs/src/content/components.ts |
Adds the catalog entry. |
apps/docs/src/app/dev/liquid-gradient-benchmark/page.dev.tsx |
Adds the client-only benchmark route. |
apps/docs/src/app/dev/liquid-gradient-benchmark/benchmark-scene.tsx |
Implements benchmark controls and comparison. |
apps/docs/src/app/components/liquid-gradient/scene.tsx |
Connects parameters to the component. |
apps/docs/src/app/components/liquid-gradient/params.ts |
Defines demo defaults and parameters. |
apps/docs/src/app/components/liquid-gradient/demo.tsx |
Adds the interactive demo. |
apps/docs/src/app/components/demo-registry.tsx |
Registers the generated docs page. |
apps/docs-tests/visual/liquid-gradient.spec.ts |
Adds default visual regression coverage. |
apps/docs/public/posters/liquid-gradient.jpg |
Provides the demo poster. |
apps/docs/public/posters/liquid-gradient.thumb.webp |
Provides the catalog thumbnail. |
apps/docs-tests/visual/liquid-gradient.spec.ts-snapshots/liquid-gradient-default-chromium-darwin.png |
Adds the macOS baseline. |
apps/docs-tests/visual/liquid-gradient.spec.ts-snapshots/liquid-gradient-default-chromium-linux.png |
Adds the Linux baseline. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…ngeset The visual spec can't tell a texture drawn once from one drawn every frame. The new tests count each pre-pass's draws across seed, softness, and phase changes, and check that Strict Mode leaves four registered. The changeset adds LiquidGradient to the next minor release.
hunterbecton
deleted the
hunter/sha-223-build-the-liquidgradient-source
branch
October 12, 2026 10:47
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Why
The Reactive feature card (SHA-216) needs a Source under the CursorDisplacement cursor effect. SHA-223 asked for SwirlGradient, bands folded along a noise flow. Partway through the gated build, the author moved the look to a streaked liquid gradient, so it ships as LiquidGradient.
What changes
A liquid gradient with no simulation state
Each pixel traces 8 steps backward along a curl-noise flow and averages the colors it passes. The average streaks LinearGradient's bands and a field of fractal paint along the current, like a long-exposure photo of moving water. The noise's arrows spin at their own rates while the flow slides, so eddies form and dissolve as they drift. A literal
speed={0}parks the scene.Textures that redraw only when their inputs change
Computing the noise at every step read 3.6 ms in the Reactive card's window at 2x. Four pre-passes now draw the flow, the paint, the palette, and the bands' average color into textures, and each redraws only when its inputs change. The card's window now reads 0.27 to 0.29 ms with the flow still and 0.34 to 0.38 ms with it moving, under the 0.4 ms budget. The readings and the step count are documented in
shader.tsx.Edges
softnesseases each stop in with smoothstep, andfwidthkeeps every edge at least a pixel wide. Streaks thinner than a pixel fade to the bands' average color. Every other pass of the stops runs backward, so no seams form.Docs site and glossary
The component page, catalog entry, poster, thumbnail, and visual baselines, plus a dev-only benchmark route with a LinearGradient baseline for spotting GPU contention.
GLOSSARY.mdgains UV warp, the term CursorDisplacement will use.Known limitations
scale={4}on a wide canvas. The prop's docs say so, and the demo slider stops at 4.swirl={2}, streaks break into separate copies around tight curls.