Large performence improvements to Plasma background#1007
Open
elias4044 wants to merge 4 commits into
Open
Conversation
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.
Summary
Plasma runs a per-pixel raymarching shader with a 60-iteration loop, at full resolution and full device pixel ratio, every frame. That's expensive, on a 1440p+ display at DPR 2 it's shading roughly 15 million pixels per frame, most of which is invisible given how soft the final output is. Along side this I noticed that this background just doesn't run well on lower-end machines in general. This PR adds four opt-in props that let devs trade a bit of that invisible fidelity for a real drop in GPU cost, without changing much for people already using the component.
Changes
Added to
Plasmaacross all four variants (JS/TS × CSS/Tailwind):renderScale(default0.55) — renders the WebGL buffer at a fraction of the container size and lets CSS scale it back up. This is where most of the win comes from, since cost tracks pixel count almost linearly.maxDpr(default1.5) — caps the devicePixelRatio used for rendering. A blurred background rarely needs full DPR on high-density screens.targetFps(default60) — throttles the render loop to a target rate instead of lettingrequestAnimationFramerun flat out.quality(default60) — controls the raymarch iteration count. Unlike the three props above, this one changes the actual pattern rather than just how much of it gets rendered or how often — see note below.document.visibilitychange, on top of the existingIntersectionObserverpause for off-screen instances. Right now the component keeps rendering in a backgrounded tab.A few smaller things I found along the way:
mousemoveevent.requestAnimationFramerather than callingsetSizesynchronously on everyResizeObserverfiring.prefers-reduced-motion— it paints one static frame and stops instead of starting the loop.A note on
qualityrenderScale,maxDpr, andtargetFpsare all "free" in the sense that they only change how much gets rendered or how often, the underlying pattern at any given moment is identical either way.qualityisn't free in that sense.The loop accumulates a running distance (
z) that feeds into the next iteration's position, which is standard raymarching — each step is figuring out how far a ray has traveled based on every step before it. Cut the iteration count from 60 to 45 and the ray simply hasn't traveled as far, so it's landing on a different point of the pattern, not a lower-detail version of the same point. In testing, lower values noticeably changed how much of the bright/white area shows up in the render — not just softness or sharpness, but the actual balance of the pattern.Because of that, I'd treat
qualityas a distinct trade-off from the other three rather than something to casually lower alongside them.Testing
Tested with
renderScale={0.55},maxDpr={1.5},targetFps={60}.Before
After
Visually near-identical at normal viewing distance, roughly 2x improvement. My GPU usage went from 95% down to 45%. My laptop, which was visibly lagging and very noticeably slow on the older version, handles the new version with no problem and there is zero noticeable lag. Try it out yourself!
❤️ from Elias.