Large performence improvements to Plasma background - #1007
Conversation
|
Just a few notes. Would it help to transfer the control of the Also, you wrote how cutting the loop iterations from 60 to 45 alters the ray distance Instead of fixed steps, you can scale the step size inversely with iteration count. Fragment precision can be set to |
|
Thanks for the feedback and tips! OffscreenCanvas: Agreed this is the right direction, but it's quite a big Step scaling: I made an attempt at fixing this but I was unable to resolve a fix, mostly due to the fact that I am not very extremely familiar with WebGL. Instead, I changed the "Quality" prop to "Iterations", as this is a much more accurate description of it and "Quality" could very easily confuse anyone. I'd be happy to see someone else implementing this if felt like necessary - but for the moment I'm keeping it as "Iterations", allowing for more customization instead. Precision : I tried Early exit: I held off on this one. This shader accumulates color on |
|
Got it. I love how this component looks but I avoid even clicking on it because it freezes my system as well, so thank you so much for this. Once your PR gets approved, I'll try and build upon it to see if I can find ways to make it more efficient. |
|
Thanks for the hard work! Merging. |
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.