我正在开发一款类似游戏的应用程序,它有多达千种形状(椭圆和线条),不断变换为60fps。阅读excellent article on rendering many moving shapes后,我使用自定义Canvas后代实现了这一点,该后代覆盖OnRender
以通过DrawingContext
进行绘制。虽然CPU使用率很高,但性能非常合理。
然而,文章建议不断移动形状的最有效方法是使用大量DrawingVisual
个实例而不是OnRender
。不幸的是,虽然它没有解释为什么在这种情况下应该更快。
以这种方式改变实现并不是一件小事,所以我想在决定进行切换之前了解原因以及它们是否适用于我。为什么DrawingVisual
方法会导致CPU使用率低于此方案中的OnRender
方法?
答案 0 :(得分:15)
来自C#2008中的Pro WPF:
这些问题引起的问题 应用程序并不复杂 艺术,但纯粹的数量 个别图形元素。即使 你用你的Path元素替换 重量较轻的几何物体, 开销仍将阻碍 应用程序的性能。 WPF 这种情况的解决方案是 使用较低级别的可视图层 模型。基本的想法就是你 将每个图形元素定义为 视觉对象,这是一个非常 轻量化成分少 开销比Geometry对象或 路径对象。
它归结为你正在创建的那些省略号和行中的每一个都是单独的FrameworkElement
;这意味着它不仅支持命中测试,还支持布局,输入,焦点,事件,样式,数据绑定,资源和动画。对于你想要做的事情来说,这是一个非常重量级的对象! Visual
对象会跳过所有内容并直接从DependencyObject
继承。它仍然支持命中测试,坐标转换和边界框计算,但没有形状支持的其他东西。它的重量更轻,可能会极大地提高你的性能。
修改强>
好的,我第一次误读了你的问题。
如果您使用OnRender
,则实际上取决于您创建视觉效果并显示它们的方式。如果您使用DrawingContext
并将所有视觉效果添加到单个元素,则这与使用DrawingVisual
方法没有什么不同。如果您为创建的每个Visual
创建单独的元素,那么这将是一个问题。在我看来,你正在以正确的方式做事。
答案 1 :(得分:8)
答案中的每个人都错了。问题是在绘图上下文中直接渲染形状是否比创建DrawingVisual更快。答案显然是'是'。 DrawLine,DrawEllipse,DrawRectangle等函数不会创建任何UI元素。 DrawingVisual要慢得多,因为它确实创建了一个UI元素,尽管它是一个轻量级元素。答案中的混淆是因为人们只是复制/粘贴DrawingVisual比MSDN中的不同UIElement形状语句表现更好。
答案 2 :(得分:7)
我认为Petzold在这一段中解释过;
ScatterPlotVisual类的工作原理 为...创建DrawingVisual对象 每个DataPoint。什么时候的属性 一个DataPoint对象更改,该类 只需要改变DrawingVisual 与该DataPoint相关联。
构建于之前的解释;
每当ItemsSource属性 更改,或集合更改,或 DataPoint对象的属性 集合改变了, ScatterPlotRender调用 InvalidateVisual。这会产生一个 打电话给OnRender 整个散点图。
这是你的要求吗?
顺便说一句,this是一个相当新的高性能WPF教程,在该绘图中有数万个点,它也是3D渲染和动画(甚至使用鼠标输入来驱动一些变换)。
答案 3 :(得分:2)
在我的测试中(平移动画),我注意到速度没有差异。我会说使用主机元素进行许多绘制视觉效果要快一些。这种使用许多视觉效果构建可视树的方法可以让您获得更多控制权。此外,当您想要进行复杂的命中测试时,过滤过程会更快,因为您可以跳过视觉效果的整个“分支”