I am using the ColorShadow control from the CompositionProToolkit in a WinUI/UWP project. I ported it to WinUI by replacing namespaces and Window.Current... with CompositionTarget.GetCompositionForCurrentThread. Currently, the shadow shape is rectangular.
I want the shadow to be circular, matching the circular image placed on top of it.
I can make the image circular using this code:
var imageBrush = await MakeCircularAsync(_imageSurface, _imageVisual.Size);
_imageVisual.Brush = imageBrush;
_colorShadowBrush.SetSourceParameter("source", imageBrush.Source);
private async Task<CompositionMaskBrush> MakeCircularAsync(IImageSurface imageSurface, Vector2 targetSize)
{
if (imageSurface == null)
return null;
if (_compositor == null)
{
_compositor = CompositionTarget.GetCompositorForCurrentThread();
_generator = _compositor.CreateCompositionGenerator();
}
float diameter = Math.Min(targetSize.X, targetSize.Y);
var radius = diameter / 2f;
var ellipse = CanvasGeometry.CreateCircle(
_generator.Device,
new Vector2(targetSize.X / 2f, targetSize.Y / 2f),
radius);
var maskSurface = _generator.CreateMaskSurface(targetSize.ToSize(), null);
maskSurface.Redraw(targetSize.ToSize(), ellipse);
var maskBrush = _compositor.CreateSurfaceBrush(maskSurface);
var sourceBrush = _compositor.CreateSurfaceBrush(imageSurface);
sourceBrush.Stretch = CompositionStretch.Fill;
var circularBrush = _compositor.CreateMaskBrush();
circularBrush.Source = sourceBrush;
circularBrush.Mask = maskBrush;
return circularBrush;
}
This is the result:
Now I need to make the shadow circular. I used the following code:
If I use:
_colorShadowBrush.SetSourceParameter("mask", imageBrush.Mask);
Or if I use the following, I get the same result.
UpdateColorShadowMask(_colorShadowVisual.Size);
private void UpdateColorShadowMask(Vector2 shadowSize)
{
float diameter = Math.Min(shadowSize.X, shadowSize.Y);
var radius = diameter / 2f;
var circle = CanvasGeometry.CreateCircle(
_generator.Device,
new Vector2(shadowSize.X / 2f, shadowSize.Y / 2f),
radius - 10);
if (_colorShadowMaskSurface == null)
_colorShadowMaskSurface = _generator.CreateMaskSurface(shadowSize.ToSize(), null);
_colorShadowMaskSurface.Redraw(shadowSize.ToSize(), circle);
var maskBrush = _compositor.CreateSurfaceBrush(_colorShadowMaskSurface);
_colorShadowBrush.SetSourceParameter("mask", maskBrush);
}
And this is the result:
As you can see, there is a blurred ring instead of a soft glow shadow color!
So, how can I achieve the first image but with a circular shadow?
The full source code can be found here and here. I’m fine with either UWP or WinUI code, so it doesn’t matter.
-
What you could do, though I don't remember the code is add a Radial Gradient mask to the shadow mask surface so that it starts solid but fades at the appropriate point close to the edge. From what I can tell you are just making it have a shape but if you add an extra mask with an alpha gradient you should be able to adjust it so it fades fairly smoothly. You're close, just requires an extra stepMiltonZ-TT– MiltonZ-TT2025年12月01日 19:24:32 +00:00Commented Dec 1, 2025 at 19:24
1 Answer 1
You can easily do that by using a CircularMask.png file!
private async Task<IImageSurface> LoadMaskFromFileAsync(string filePath)
{
var bitmap = await CanvasBitmap.LoadAsync(CanvasDevice.GetSharedDevice(), new Uri(filePath));
return _generator.CreateImageSurface(bitmap, bitmap.Size, ImageSurfaceOptions.Default);
}
then use it:
var _circleMaskSurface = await LoadMaskFromFileAsync("ms-appx:///Assets/CircleMask.png");
var maskBrush = _compositor.CreateMaskBrush();
maskBrush.Source = imageBrush;
maskBrush.Mask = _compositor.CreateSurfaceBrush(_circleMaskSurface);
_imageVisual.Brush = maskBrush;
and for shadow upadate this:
_imageMaskSurface = _generator.CreateImageMaskSurface(_circleMaskSurface, _colorShadowVisual.Size.ToSize(),
ColorMaskPadding, _maskOptions);