在 WPF 中绘制到 DrawingContext 时如何应用投影效果?

Posted

技术标签:

【中文标题】在 WPF 中绘制到 DrawingContext 时如何应用投影效果?【英文标题】:How to apply a drop shadow effect when drawing to a DrawingContext in WPF? 【发布时间】:2012-01-29 03:45:28 【问题描述】:

我正在向DrawingContext 绘图,我想对绘图的一部分应用投影效果。目前我在DrawingGroup 中创建相关部分并应用BitmapEffect,但这没有效果:

var layer = new DrawingGroup();
using (var lcontext = layer.Open())

    // draw stuff in lcontext

layer.BitmapEffect = new DropShadowBitmapEffect  Color = Colors.Black, ShadowDepth = 3, Opacity = 0.5 ;
context.DrawDrawing(layer);

这会正确地绘制layer 内的所有内容,但没有投影效果。

我做错了什么/我还能如何将阴影应用到 DrawingContext 中的一堆图元?

【问题讨论】:

【参考方案1】:

BitmapEffect 是 .NET 3.5 之前的旧属性(他们使用 CPU 渲染效果)。 4.0 中的属性has no effect。

在 4.0 中,您应该使用 Effect 属性,它使用像素着色器。

DrawingGroup 但是似乎没有效果属性 - 听起来您可能需要set the effect on the parent UI element instead。

【讨论】:

嗯...我没有父 UI 元素;这个DrawingGroup 直接呈现为RenderTargetBitmap。奇怪的是,我必须使用 UI 元素进行纯渲染,嗯?... 我不认为这很奇怪 - 在内存中创建位图时,它还没有发送到 GPU,因此 GPU 无法运行像素着色器。旧的BitmapEffects 没有使用像素着色器,它们在 CPU 上运行,这就是它们在这种情况下工作的原因。不过大多数时候 BitmapEffects 太慢了,这就是它们被淘汰的原因。 在这种情况下,您可能可以使用绘图组填充一个 Rectangle,然后将 Rectangle 渲染到 RenderTargetBitmap(不要忘记先调整元素的大小)——这应该(我认为)调用 GPU调用你的着色器。【参考方案2】:

如果您在 .NET Framework 3.5 SP1 或更高版本上运行,则应使用 UIElement.Effect 或 Visual.VisualEffect(这是受保护的,因此您需要从它派生),并使用 System.Windows.Media.Effects.DropShadowEffect 的实例.

【讨论】:

A DrawingGroup 既不是Visual 也不是UIElement,那么我应该在哪里应用这个效果呢? 我将图像和图元之类的东西绘制到我的DrawingGroup 中(使用我在问题中引用的代码)。然后我使用DrawDrawing 渲染它。我也想做同样的事情,但要让 DrawingGroup 中的所有内容都投下阴影。 根据我的经验,DrawingContext 是 GDI API 的完美替代品。似乎没有现成的阴影效果,这是可以理解的。您想更新或删除您的答案吗?就目前而言,它不适用/具有误导性。 让我给你我的角度 - 我从 FrameworkElement 继承了 SomeControl,并覆盖了 OnRender。 UIElement.Effect 还不够好——它把效果放在整个元素上,而贬低的 PushEffect 只能把效果放在几行 drawingContext.DrawXXX 上,让我不能一次把效果放在整个元素上。 WPF4 => 控制比 WPF3 少? @SimonMourier 感谢您的帮助。 FWIW,我认为删除答案不需要任何费用。

以上是关于在 WPF 中绘制到 DrawingContext 时如何应用投影效果?的主要内容,如果未能解决你的问题,请参考以下文章

WPF 使用 DrawingContext 绘制温度计

WPF中如何使用图像API进行绘制

如何使用 WPF 中的 TextShape 类绘制自定义形状?

WPF之几何图形Geometry

WPF DrawingContext Pen

WPF的二维绘图——几何图形Geometry