仅在SpotLight下显示UIElement

时间:2022-09-25 21:18:32

I have an rectangle:

我有一个矩形:

<Border x:Name="Elem1" BorderThickness="2" Height="100" Width="200" BorderBrush="Red" />

And a Windows.UI.Composition.SpotLight moving togehter with pointer:

并且Windows.UI.Composition.SpotLight使用指针移动togehter:

const float LightDistance = 20;
_compositor = Window.Current.Compositor;
_pointLight = _compositor.CreatePointLight();
_pointLight.Color = Colors.White;
_pointLight.Targets.Add(ElementCompositionPreview.GetElementVisual(Elem1)); 

PointerMoved += (o, e) => {
    var point = e.GetCurrentPoint(this).Position;
    _pointLight.Offset = new Vector3((float)point.X, (float)point.Y, LightDistance);
};

When there is no light over rectagle, it remain black:

当直肠上没有光线时,它仍然是黑色的:

仅在SpotLight下显示UIElement

I would like the rest of the rectangle to be transparent, so only enlightened part will be visible

我希望矩形的其余部分是透明的,所以只有开明的部分才会可见

I've tried to add transparent AmblientLight, but the aplha channel is ignored.

我试图添加透明的AmblientLight,但忽略了aplha通道。

I guess it could be achieved by SceneLightingEffect, but how? :)

我想这可以通过SceneLightingEffect来实现,但是怎么样? :)

1 个解决方案

#1


0  

Special for you :D

特别适合你:D

    public MainPage()
    {
        InitializeComponent();
        Loaded += MainPage_Loaded;
    }

    private CompositionSurfaceBrush _maskSurfaceBrush;
    private readonly float _size = 512;

    private async void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        PointerMoved += MainPage_PointerMoved;

        var compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
        var canvasDevice = CanvasDevice.GetSharedDevice();
        var graphicsDevice = CanvasComposition.CreateCompositionGraphicsDevice(compositor, canvasDevice);

        var canvasBitmap = await CanvasBitmap.LoadAsync(canvasDevice, new Uri("ms-appx:///Assets/44578.jpg"));

        var sourceDrawingSurface = graphicsDevice.CreateDrawingSurface(new Size(_size, _size), DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied);
        using (var ds = CanvasComposition.CreateDrawingSession(sourceDrawingSurface))
        {
            ds.Clear(Colors.Transparent);
            ds.DrawImage(canvasBitmap);
        }

        var sourceSurfaceBrush = compositor.CreateSurfaceBrush(sourceDrawingSurface);

        var maskRenderTarget = new CanvasRenderTarget(canvasDevice, _size, _size, 96);
        using (var ds = maskRenderTarget.CreateDrawingSession())
        {
            ds.Clear(Colors.Transparent);
            ds.FillCircle(_size / 2, _size / 2, _size / 8, Colors.Black);
        }

        var blur = new GaussianBlurEffect
        {
            BlurAmount = 16,
            Source = maskRenderTarget
        };

        var blurredMaskDrawingSurface = graphicsDevice.CreateDrawingSurface(new Size(_size, _size), DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied);
        using (var ds = CanvasComposition.CreateDrawingSession(blurredMaskDrawingSurface))
        {
            ds.Clear(Colors.Transparent);
            ds.DrawImage(blur);
        }

        _maskSurfaceBrush = compositor.CreateSurfaceBrush(blurredMaskDrawingSurface);

        var composite = new CompositeEffect
        {
            Sources = { new CompositionEffectSourceParameter("source"), new CompositionEffectSourceParameter("mask") },
            Mode = CanvasComposite.DestinationAtop
        };

        var effectFactory = compositor.CreateEffectFactory(composite);
        var fxBrush = effectFactory.CreateBrush();
        fxBrush.SetSourceParameter("source", sourceSurfaceBrush);
        fxBrush.SetSourceParameter("mask", _maskSurfaceBrush);

        var sprite = compositor.CreateSpriteVisual();
        sprite.Size = new Vector2(_size, _size);
        sprite.Brush = fxBrush;

        ElementCompositionPreview.SetElementChildVisual(this, sprite);
    }

    private void MainPage_PointerMoved(object sender, PointerRoutedEventArgs e)
    {
        var position = e.GetCurrentPoint(this).Position.ToVector2();

        _maskSurfaceBrush.Offset = position - new Vector2(_size / 2, _size / 2);
    }

Works better than ever!

效果比以往更好!

#1


0  

Special for you :D

特别适合你:D

    public MainPage()
    {
        InitializeComponent();
        Loaded += MainPage_Loaded;
    }

    private CompositionSurfaceBrush _maskSurfaceBrush;
    private readonly float _size = 512;

    private async void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        PointerMoved += MainPage_PointerMoved;

        var compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
        var canvasDevice = CanvasDevice.GetSharedDevice();
        var graphicsDevice = CanvasComposition.CreateCompositionGraphicsDevice(compositor, canvasDevice);

        var canvasBitmap = await CanvasBitmap.LoadAsync(canvasDevice, new Uri("ms-appx:///Assets/44578.jpg"));

        var sourceDrawingSurface = graphicsDevice.CreateDrawingSurface(new Size(_size, _size), DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied);
        using (var ds = CanvasComposition.CreateDrawingSession(sourceDrawingSurface))
        {
            ds.Clear(Colors.Transparent);
            ds.DrawImage(canvasBitmap);
        }

        var sourceSurfaceBrush = compositor.CreateSurfaceBrush(sourceDrawingSurface);

        var maskRenderTarget = new CanvasRenderTarget(canvasDevice, _size, _size, 96);
        using (var ds = maskRenderTarget.CreateDrawingSession())
        {
            ds.Clear(Colors.Transparent);
            ds.FillCircle(_size / 2, _size / 2, _size / 8, Colors.Black);
        }

        var blur = new GaussianBlurEffect
        {
            BlurAmount = 16,
            Source = maskRenderTarget
        };

        var blurredMaskDrawingSurface = graphicsDevice.CreateDrawingSurface(new Size(_size, _size), DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied);
        using (var ds = CanvasComposition.CreateDrawingSession(blurredMaskDrawingSurface))
        {
            ds.Clear(Colors.Transparent);
            ds.DrawImage(blur);
        }

        _maskSurfaceBrush = compositor.CreateSurfaceBrush(blurredMaskDrawingSurface);

        var composite = new CompositeEffect
        {
            Sources = { new CompositionEffectSourceParameter("source"), new CompositionEffectSourceParameter("mask") },
            Mode = CanvasComposite.DestinationAtop
        };

        var effectFactory = compositor.CreateEffectFactory(composite);
        var fxBrush = effectFactory.CreateBrush();
        fxBrush.SetSourceParameter("source", sourceSurfaceBrush);
        fxBrush.SetSourceParameter("mask", _maskSurfaceBrush);

        var sprite = compositor.CreateSpriteVisual();
        sprite.Size = new Vector2(_size, _size);
        sprite.Brush = fxBrush;

        ElementCompositionPreview.SetElementChildVisual(this, sprite);
    }

    private void MainPage_PointerMoved(object sender, PointerRoutedEventArgs e)
    {
        var position = e.GetCurrentPoint(this).Position.ToVector2();

        _maskSurfaceBrush.Offset = position - new Vector2(_size / 2, _size / 2);
    }

Works better than ever!

效果比以往更好!