Skip to content
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

[Feature] 🌫️ Gaussian Blur #1952

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

bungoboingo
Copy link
Contributor

@bungoboingo bungoboingo commented Jul 11, 2023

🌫️ This PR aims to bring blur capabilities to Iced

blur_example.mov

This PR also introduces very basic sub-surface compositing support for the iced_wgpu backend. Note that tiny-skia appears to have no support for blurring, so the plan is to not support it at this time.

NOTE: The internals of this PR are very likely to change with upcoming layering changes. This PR mostly aims to get feedback on a) the blur widget API, and b) sub-surface compositing in Iced in general.

Implementation details

A few changes were needed in our rendering backend, as it was mostly set up with only the viewport's texture as a render attachment in mind!

The blur widget

A Blur widget can be used to wrap any Element, like so:

let blurred_content = blur(10, content);

Where 10 here represents the blur "radius". I chose to implement it as its own widget vs an appearance attribute (like how it's done on web) to allow for the most flexibility. Feedback welcome!

A new iced_wgpu::layer::Kind **

This could be done any number of ways; first I tried just adding a blur option to the existing layer which worked fine, but thought this approach was more readable.

I've adjusted iced_wgpu::Layer to have a kind field, Immediate or Deferred (naming suggestions welcome :P). A layer::Kind::Immediate is rendered to the viewport's surface immediately. A layer::Kind::Deferred must first render everything within the layer to its own Surface, and that will be composited onto the viewport's surface later.

** This is very likely to be completely reworked after layering changes!

The Composite pipeline (name TBD)

This is just a general purpose pipeline which can be used to composite any sub-surface onto the viewport's texture. The general idea is that if we want to do any sort of layer Effect we first must render it to a composite::Surface, and that will be used to sample from in the Composite pipeline. In terms of blur, this is necessary as it is much faster to do each blur pass (horizontal & vertical) on a downsampled texture and then upsample it back up to the proper size.

I abstracted it out into its own pipeline as it's more general purpose than just for blur, but originally had it as just part of the blur pipeline. If we don't think this is useful could move it back again! 🤷

That's about it in terms of details. Max blur time for large images caps out at around ~150µs on my various rigs which I believe should be fast enough for its use case in Iced 😉

iced_wgpu::Backend changes

Mostly just needed to change things to be able to be relative to any texture size vs just the viewport, nothing too crazy here. Made an abstraction over wgpu::RenderPass that we might be unnecessary.

Outstanding TODOS

  • tiny-skia gaussian blur
  • Test changes I had to make to Glyphon to see if there's a better way to get accurate final quad vertex positions w/ different texture sizes.
  • Revisit transformation math to avoid some unnecessary multiplication, of which I'm sure there's a few.
  • Add a mesh example to the blur package to make sure that meshes are blurring properly.
  • Speaking of meshes, probably ignore MSAA if we're doing a blur pass since that seems unnecessary.

Outstanding Questions

  • Does it make sense for content which is blurred beyond a certain amount to be interactable? If I blur a button by like 100 radius for example, and then try to click the vaguely blurred outline of it, is sort of a weird experience.
  • Should the blur radius expand the actual bounds of the content by +/- blur radius? I don't think it makes sense but maybe others have different opinions. Right now blur will be cut off at the content bounds, and if you don't want any hard edge would need to add padding.

Let me know what you think! Note again that the internals of this implementation will probably change quite a bit after upcoming layering changes to Iced.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
2 participants