Blurs are essential to modern design. Layered drop shadows, frosted glass effects, blurred backgrounds — you won’t see a nice looking app in the 2020s without them.

Designers tend to work in vector based tools such as Figma. Shadows are a big part of their workflow. It’s how they bring depth and life to 2D interfaces. Melatonin Blur lets you take a designer’s work in CSS/Figma and quickly translate it. No need to export image strips and so on like it’s the 1990s!

For example, I have a slider that look like this:

Every single part of this slider is a vector path with shadows. The background track (2 inner), to the level indicator (3 inner, 2 drop) to the knob (3 drop shadow). They all need to be rendered fast enough that many of these can be happily animated at 60fps without freezing up the UI on older machines.

Stack Blur makes it possible

Stack Blur via the Gin implementation first made this feel technically possible for me. Thanks Roland!

However, performance is death by 1000 cuts. I was still finding myself building little caching helpers. Sometimes these shadows add up, and I didn’t feel “safe”, in particular on Windows.

On larger images (above 500px in a dimension) Stack Blur can takes milliseconds of CPU time (which is unacceptable for responsive UI targeting 60fps). I was also seeing some sluggishness in Debug mode, which drives me crazy!

So I started to get curious about the Stack Blur algorithm. I kept thinking I could make it:

  • Faster. The original stack blur algorithm was made for an environment without access to SIMD or intel/apple vendor libs, in 2004. For larger images, I was seeing images take ms. I wanted to see them in the µs. In Debug, Stack Blur is sluggish and can’t always provide 60fps, even on a fast machine.
  • Cleaner. The Gin Stack Blur implementation comes from a long line of ports originating with Mario’s js implementation. There’s no templates, no code reuse, there’s multiplication and left shift tables to avoid division, and all kinds of trickery that I felt was unneeded with modern C++ and modern compilers.
  • Understandable. The concept of the “stack” in Stack Blur — what is it? I had a hard time finding resources that made it easy to understand. The original notes on the algorithm don’t align with how implementations worked in
    practice. So I was interested in understanding how the algorithm works.
  • Fully Tested. This is critical when iteratively re-implementing algorithms, and I felt like it was a must-have.
  • Benchmarked. The only way to effectively compare implementations was to test on Windows and MacOS.
  • Batteries included. Let me design in code, please! Nice syntax, etc.

Thanks to being arrogant and setting a somewhat ridiculously high bar, I implemented Stack Blur probably 25+ times over the course of a few weeks. Enough where I can do it in my sleep.

There are 15 reference implementations in this repo that pass the tests, but most didn’t bring the performance improvements I was looking for.

I still have a few more implementations that I’d like to try, but already invested ridiculous amounts of time, so I’m calling it for now!


Leave a Reply

Your email address will not be published. Required fields are marked *