Share one toolbox: power functions, particles, shaders — and presets - #62
Merged
Conversation
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.
Effects used to hand-roll their own drawing, math and motion: each one carried its own line
walker, its own sine, its own fade, its own idea of how fast a frame is. This branch replaces
that with one shared toolbox, and migrates the existing effects onto it.
Two things fall out. Effects get shorter and more capable — anti-aliasing, sub-pixel
positioning and signed distance fields arrive everywhere at once rather than per effect. And
motion becomes a property of time rather than of hardware: the same settings look the same on
a 30 fps wall and a 5,000 fps desktop, with the faster device drawing it more smoothly.
What landed
Presets and a control surface.
ControlModulesaves and restores any part of the moduletree as a named JSON file. A
Layers-only preset is hardware-portable; addingDriversmakesit a device snapshot carrying pin maps. Presets publish to Home Assistant as a select.
The power-function library (
docs/moonmodules/light/power-functions.mdlists everyfunction with its callers):
Canvas, lines, bars, rects, circles, scroll, splat, anti-aliased linessin16/cos16,atan16,dist16,map32, easings,BeatPhase,hashIntfbm,turbulence,warp, blobssmin, and free anti-aliasing fromcoverage()collisions, emitters
Twelve new effects (40 → 52), each a showcase for one part of the toolbox: SdfShapes,
PolarNoise, WaterRipple, Tunnel, Echo, Dissolve, Spectrum, Fireworks, Ballpit, Truchet,
Raymarch, VectorBalls.
Framerate independence as a system rule (
architecture.md). Everything that changes overtime is driven by elapsed time, never by frame count. Quantising to a fixed 60 Hz and skipping
frames is explicitly the wrong fix, since it discards the smoothness the extra frames buy.
unit_Effects_framerate.cppaudits all 52 effects at 60 vs 1200 fps.Bugs this found and fixed
Several were live before the branch, and none were visible from reading the code:
sin16/cos16returned unsigned where FastLED master and WLED main both return signed. Aported effect that writes
sin16(x) + 32768is offset by half scale with no error anywhere.isqrt64returned 0 forUINT64_MAX— its first Newton step overflowed. Oncecollide()used it, that would have read as zero separation.
lerp16overflowed int32 on roughly a quarter of samples (undefined behaviour), andfbm16shifted each octave down by 8 before summing, making its output 8-bit in a 16-bit type: 195
distinct values over 20,000 samples, now 15,118.
speedon a fast device, where the per-frame steptruncated to zero.
Performance
Desktop tick measured three runs each, side by side against a
mainworktree: the rangesoverlap and there is no regression. The repo-health "+13 µs ⚠" marker compares two single
samples of a noisy metric. Flash grows by the new effects and the library.
Raymarching measures 96 cycles/pixel on an S3 — below the 292 budgeted for a full 128×128
wall — which is why it is gated on
SOC_CPU_HAS_FPUrather than restricted to desktop.Known and deferred
currently cancel: frame-counted launches, and a
fadeToBlackByfloor that erases the trailfaster on a fast device. Fixing one exposes the other, and fixing both changes how the
effect looks, so it gets its own commit.
which is a rework rather than a migration.
fbm16,warp16/turbulence16) are backlogged, each to land with the first effect thatneeds it.
Review
CodeRabbit and two Reviewer passes. Findings fixed, except: the two grid guards in effects
(
Layer::tickalready gates onhasGrid, so a guard there is dead code and an orchestrationviolation),
map32's split numerator (needs both spans near 2^32; no call site does), andmoving
FrameTimeto core / abstracting raymarch behind a platform interface — both real,both refactors across every caller rather than review fixes.
Summary by CodeRabbit
New Features
Bug Fixes