如何使用WPF效果模拟OuterGlowBitmapEffect外发光效果
解决方案
可以通过单个效果实现目标高强度外发光,不需要重复堆叠效果,推荐以下两种实现方式:
方案1:自定义HLSL外发光效果(性能最优,效果最好)
通过自定义HLSL着色器实现带强度控制的外发光效果,是WPF中实现该需求的标准方案,仅需单个Effect即可支持发光颜色、半径、强度独立调节,不会出现BlurRadius增大后发光衰减的问题。
- 首先编写HLSL着色器代码,保存为
OuterGlow.hlsl:
sampler2D inputSampler : register(s0); float4 glowColor : register(c0); float blurRadius : register(c1); float intensity : register(c2); float4 main(float2 uv : TEXCOORD) : SV_Target { float4 source = tex2D(inputSampler, uv); float4 glow = 0; float sampleCount = pow(2 * blurRadius + 1, 2); // 多采样计算外发光 for (float x = -blurRadius; x <= blurRadius; x++) { for (float y = -blurRadius; y <= blurRadius; y++) { float2 offset = float2(x, y) / 1024.0; glow += tex2D(inputSampler, uv + offset) * glowColor; } } glow = glow / sampleCount * intensity; // 混合原内容与发光层 return source + glow * (1 - source.a); }
使用Fxc工具将HLSL代码编译为OuterGlow.ps像素着色器文件,嵌入到WPF项目资源中。
- 封装WPF调用类:
public class OuterGlowEffect : ShaderEffect { public static readonly DependencyProperty InputProperty = RegisterPixelShaderSamplerProperty(nameof(Input), typeof(OuterGlowEffect), 0); public static readonly DependencyProperty GlowColorProperty = DependencyProperty.Register(nameof(GlowColor), typeof(Color), typeof(OuterGlowEffect), new UIPropertyMetadata(Colors.Cyan, PixelShaderConstantCallback(0))); public static readonly DependencyProperty BlurRadiusProperty = DependencyProperty.Register(nameof(BlurRadius), typeof(double), typeof(OuterGlowEffect), new UIPropertyMetadata(10.0, PixelShaderConstantCallback(1))); public static readonly DependencyProperty IntensityProperty = DependencyProperty.Register(nameof(Intensity), typeof(double), typeof(OuterGlowEffect), new UIPropertyMetadata(3.0, PixelShaderConstantCallback(2))); public OuterGlowEffect() { PixelShader = new PixelShader { // 替换为你项目中ps文件的资源路径 UriSource = new Uri("pack://application:,,,/你的程序集名称;component/Resources/OuterGlow.ps") }; UpdateShaderValue(InputProperty); UpdateShaderValue(GlowColorProperty); UpdateShaderValue(BlurRadiusProperty); UpdateShaderValue(IntensityProperty); } public Brush Input { get => (Brush)GetValue(InputProperty); set => SetValue(InputProperty, value); } public Color GlowColor { get => (Color)GetValue(GlowColorProperty); set => SetValue(GlowColorProperty, value); } public double BlurRadius { get => (double)GetValue(BlurRadiusProperty); set => SetValue(BlurRadiusProperty, value); } public double Intensity { get => (double)GetValue(IntensityProperty); set => SetValue(IntensityProperty, value); } }
- XAML中直接使用:
<Border Width="200" Height="80" Background="Transparent" BorderBrush="Cyan" BorderThickness="2"> <Border.Effect> <local:OuterGlowEffect GlowColor="Cyan" BlurRadius="15" Intensity="5"/> </Border.Effect> </Border>
调整Intensity参数即可自由控制发光强度,不受BlurRadius大小影响。
方案2:原生DropShadowEffect参数优化(无需自定义代码)
如果不想编写自定义着色器,也可以通过调整原生DropShadowEffect的参数达到接近效果,仅需单个效果即可:
<DropShadowEffect ShadowDepth="0" Color="#FF00FF00" BlurRadius="20" Opacity="1" RenderingBias="Quality"/>
如果仍然觉得强度不足,可以在原控件下层叠加1个相同内容的透明控件,仅给下层控件加Effect,性能远优于堆叠十几次效果。
内容的提问来源于stack exchange,提问作者Joan Venge
相关产品推荐
相关产品推荐

