C# 使UIElement仅在聚光灯下可见

C# 使UIElement仅在聚光灯下可见,c#,xaml,uwp,win2d,xaml-composition,C#,Xaml,Uwp,Win2d,Xaml Composition,我有一个矩形: <Border x:Name="Elem1" BorderThickness="2" Height="100" Width="200" BorderBrush="Red" /> 当rectagle上没有灯光时,它将保持黑色: 我希望矩形的其余部分是透明的,因此只有被照亮的部分才可见 我尝试添加透明AmblentLight,但忽略了aplha通道 我想这可以通过场景照明效果来实现,但如何实现呢?:) 特别为你准备的:D public MainPage()

我有一个矩形:

<Border x:Name="Elem1" BorderThickness="2" Height="100" Width="200" BorderBrush="Red" />
当rectagle上没有灯光时,它将保持黑色:

我希望矩形的其余部分是透明的,因此只有被照亮的部分才可见

我尝试添加透明AmblentLight,但忽略了aplha通道

我想这可以通过
场景照明效果来实现,但如何实现呢?:)

特别为你准备的: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);
    }

比以往任何时候都好

如果适合你的情况,你可以用面具代替聚光灯。我也试过,但没有成功。不是因为这不可能,而是因为我对uwp的知识有限,我不知道如何创建径向梯度掩模并移动它
    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);
    }