Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UWP App realtime blur background using DX Compositor

So the UWP Composition support has been out for a while I am looking for a way to do real-time blurring of elements (live blur as they move or load, not static snapshot). So far I have been looking at some answers on stackoverflow, and google which lead me to use Lumia Imaging SDK Sample and Win2D. None of them are good enough for realtime blur support. I know doing blur in realtime is possible in composition because I have seen demos of blurred videos and there is an obsolete project XAMLFx that allows you to blur almost anything using DX on 8.1 Apps.

I don't want to use RenderTargetBitmap (want to keep my UI thread free). How can I do so by only using composition API:

ContainerVisual rootVisual = GetVisual(this.Content);
Compositor compositor = rootVisual.Compositor;

// what next?

Any help is greatly appreciated :)

like image 987
MaX Avatar asked Mar 29 '16 06:03

MaX


1 Answers

Note: These features (blur and the Backdrop brush) require the Anniversary Update to Windows 10. You currently can get a preview of the SDK through the Windows Insider Program

Prerequisites

  1. Targeting the Windows 10 Anniversary Update
  2. A basic understanding of the Visual Layer and how the Visual Tree works. You can find out more here.

Additionally you can look to a gist I wrote here, which is a quick way to get up and running using the Composition API within a XAML app. It demos using an effect as well. Not only that, but it also covers loading an image using the Composition API (with a package I wrote).

Getting Started

There are two ways you can consume a blur effect in the Composition APIs. One is as a normal effect that applies to a single surface. The other is to use it as a "Backdrop" brush which takes all content behind it and blurs it.

To use a blur effect you need to use a GaussianBlurEffect definition from Win2D. That goes something like this:

GaussianBlurEffect blurEffect = new GaussianBlurEffect() 
{
    Name = "Blur",
    BlurAmount = 0.0f, // You can place your blur amount here.
    BorderMode = EffectBorderMode.Hard,
    Optimization = EffectOptimization.Balanced,
    Source = new CompositionEffectSourceParameter("source")
};

The next step is to create an effect factory:

var effectFactory = compositor.CreateEffectFactory(blurEffect, new[] {"Blur.BlurAmount"});

The second parameter is not required, but providing it allows you to animate or change the named property after the effect is compiled. In this case we can now change or animate the BlurAmount. This is usefull if you want to reuse your blur effect factory to create multiple blur effect brushes but have them all use a different BlurAmount.

The next step varies depending on how you want the effect to work.

Single Surface

If you want it to only apply to a single surface, you would do the following:

var effectBrush = effectFactory.CreateBrush();
effectBrush.SetSourceParameter("source", someOtherSurfaceBrush);
visual.Brush = effectBrush;

Backdrop

However, if you want to blur lots of content dynamically that is behind a given visual, you would do the following:

var effectBrush = effectFactory.CreateBrush();
effectBrush.SetSourceParameter("source", compositor.CreateBackdropBrush());
visual.Brush = effectBrush;

Notice that this looks very similar to the first method, but instead of giving it a surface brush you give it a BackdropBrush. This will take the content behind the visual in real time and feed it into the source of your effect. In this case anything "behind" the visual will be blurred.

Performance

If you're only blurring a single image, it's better to blur the single surface. You should try to only use the BackdropBrush when you really need it.

Show me more!

To see more, head over to our GitHub page! We've created a custom XAML control that should help you out here, and you can see it in action here. You can also see the //build talk here.

like image 82
robmikh Avatar answered Sep 20 '22 13:09

robmikh