-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add an implementation of Stack Blur as a juce::ImageEffectFilter
#1049
base: develop
Are you sure you want to change the base?
Conversation
8ae769f
to
a544085
Compare
@ImJimmi I'm pretty excited by the work you've done here. I have my own implementation of stack blur, but I never did the profiling.
I'm wondering what size image is this on? It would be nice to know if blurring X amount of pixels is possible at > 60fps... Also, do you run into any further optimization ideas? Web browsers do this very efficiently, but they are GPU based. Ran into this cool thing too tho: https://developer.chrome.com/blog/animated-blur/ |
Those benchmarks were with the new demo I added to the DemoRunner using whatever size the component is - I think about 640x480 based on the screenshot above. 60fps would be easily achievable on a smaller component, say a drop-down menu. But even with the best blurring algorithm, blurring a large image on a CPU is not going to be particularly performant.
The two biggest performance gains (other than the Stack Blur algorithm itself) came from:
The only other thing I did look at was trying to align the data so you're always accessing it in order. Reading from a container by iterating one index at a time is much quicker than stepping over large chunks. However that's exactly what you have to do to process each column of the image, you read one pixel and then jump |
Ok, great! Just wanted to confirm that the benchmarks were from that!
This is pretty interesting, wouldn't have thought of it!
Yeah, I was also wondering if there was an opportunity for matrix multiplication here. But without an ability to run that on a gpu... maybe no gainz possible. The only other thing that I've noticed is impactful on my end is providing tie-in to JUCE's components. For example, I use stack blur for drop shadows and there's all sorts of optimization techniques like having the shadow be in its own container, cached by |
Adds an implementation of the Stack Blur algorithm as described here: https://observablehq.com/@jobleonard/mario-klingemans-stackblur
Stack blur is a significantly faster blurring algorithm than the existing Gaussian blur, especially at higher blur radiuses. Here's a graph showing the render time in Milliseconds for increasing blur radiuses for Gaussian Blur, multi-threaded stack blur, and single-threaded stack blur:
Note how the Y-axis is logarithmic. Even without the use of the thread pool, Stack Blur is around 7x faster than Gaussian Blur at a blur radius of 25px. With the thread pool, Stack Blur is around 38x faster than Gaussian Blur.
To look at it another way, the maximum framerate you'd get from the Gaussian blur at 25 blur radius would be ~1.3FPS. With Stack Blur using a thread pool also with 25 blur radius you could achieve ~48FPS.
Stack Blur (top) also gives a much "smoother" blur than Gaussian (bottom), which tends to 'smudge' elements, especially noticeable at the edges of images:
This PR also adds a new Blur Demo to the Demo Runner example project. The demo shows the differences between the two available blur techniques in JUCE and their respective render times, with a slider to adjust the blur radius.
This is an extension of a previous PR made here: #934. However this version is written from scratch in a more JUCEy way.
This work was initially inspired by this thread on the forums: https://forum.juce.com/t/faster-blur-glassmorphism-ui/43086