How to imitate OuterGlowBitmapEffect using WPF effects?
Asked Answered
C

1

8

I tried using DropShadowEffect but it's "glow" strength weakens when you increase BlurRadius. I want to have strong outer glow like the image below.

enter image description here

If I stack the same effect a dozen times I am able to get this, but the performance tanks after this. Is this possible to do using WPF with a single effect?

Clotildecloture answered 16/9, 2021 at 9:14 Comment(3)
If you have very specific requirement like this then there are two alternatives I would suggest. 1) Write your own effect. It'll do whatever you want then. 2) Use a imagebrush - if you can build it once, capture and re-use as a picture then it doesn't matter how expensive that building process was.Burr
One way to build such an image programmatically would be to use writeablebitmap. This is pretty fast. I build one 1155 x 805 for map backgrounds in our game and it takes 20 odd milliseconds. You'd want a faster simper algorithm than gaussian to work out the strength of colour for each px. That needn't be too precise if you then blur the image.Burr
One simple solution is to surround the targeted control with an Image control that points to a shadow .PNG file with transparency (something like this i.imgur.com/T7uNORE.png) that you can stretch to the control size. The benefit is you can finely craft the image you want.Ysabel
C
4

Depending on how large you want the radius of the blur to be and how smooth the result needs to be, you could stack different effects like gradient stops instead of repeatedly stacking the same effect.


Like you pointed out, the DropShadowEffect strength gets weaker as the BlurRadius increases.

Example of a WPF control

<TextBox Text="DropShadowEffect">
    <TextBox.Effect>
        <DropShadowEffect BlurRadius="50"
                          ShadowDepth="0" 
                          Color="Blue" 
                          Opacity="1"/>
    </TextBox.Effect>
</TextBox>

Additionally, applying effects directly to the TextBox impacts the rendering quality of the text. The proposed solution to the linked question (setting TextOptions.TextFormattingMode="Display" on the Window) also has layout implications. Instead, you can draw a Rectangle with a BlurEffect behind your element.

Example of a WPF control

<Rectangle Fill="Blue"
           Height={Binding ElementName=MyTextBox, Path=ActualHeight}"
           Width={Binding ElementName=MyTextBox, Path=ActualWidth}">
    <Rectangle.Effect>
        <BlurEffect Radius="50"/>
    </Rectangle.Effect>
</Rectangle>
<TextBox x:Name="MyTextBox" Text="Rectangle with BlurEffect"/>

You can then add an additional Rectangle for each gradient stop. Here there are two: one at 50 to define the overall size of the blur, and one at 30 to strengthen the glow around the control.

Example of a WPF control

<Rectangle Fill="Blue"
           Height={Binding ElementName=MyTextBox, Path=ActualHeight}"
           Width={Binding ElementName=MyTextBox, Path=ActualWidth}">
    <Rectangle.Effect>
        <BlurEffect Radius="50"/>
    </Rectangle.Effect>
</Rectangle>
<Rectangle Fill="Blue"
           Height={Binding ElementName=MyTextBox, Path=ActualHeight}"
           Width={Binding ElementName=MyTextBox, Path=ActualWidth}">
    <Rectangle.Effect>
        <BlurEffect Radius="30"/>
    </Rectangle.Effect>
</Rectangle>
<TextBox x:Name="MyTextBox" Text="Two Rectangles with BlurEffect"/>

You asked about the perceived sharpness around the corners of the TextBox and I must admit I don't have a good solution. I initially considered rounding the corners of the blurred elements behind your control by using a Border instead of a Rectangle, but I honestly don't see much of a difference.

Example of a WPF control

<!-- Remove the CornerRadius property for square corners. -->
<Border CornerRadius="10" Background="Blue">
    <Border.Effect>
        <BlurEffect Radius="50"/>
    </Border.Effect>
</Border>
<Border CornerRadius="10" Background="Blue">
    <Border.Effect>
        <BlurEffect Radius="30"/>
    </Border.Effect>
</Border>

Of course, you could always make the background objects larger than your control. Here they are in the same cell of a Grid but there is extra space for the Border to grow because the TextBox has a Margin. A smaller top/bottom margin and larger left/right margin means the glow will be more uniform around the control.

Example of a WPF control

<!-- These items should be in the same cell of a Grid -->
<Border CornerRadius="10" Background="Blue">
    <Border.Effect>
        <BlurEffect Radius="50"/>
    </Border.Effect>
</Border>
<Border CornerRadius="10" Background="Blue">
    <Border.Effect>
        <BlurEffect Radius="30"/>
    </Border.Effect>
</Border>
<TextBox Text="TextBox has an 8px, 4px margin" Margin="8 4"/>
Codfish answered 20/9, 2021 at 18:1 Comment(2)
Thanks a lot. One thing with rectangle is you can notice the corners look sharp, not as round as the glow effect in OP. Is there a way to fix that? Basically to have a rounder glow that's uniform around the control.Clotildecloture
I don't think there's a good solution since the BlurEffect will approximate an ellipse unless your control is close to square. I added a section about using a different size for the background object that might suit your needs.Codfish

© 2022 - 2024 — McMap. All rights reserved.