最大化 WPF 3D 性能
使用 Windows Presentation Foundation (WPF) 生成 3D 控件并在应用程序中包括 3D 场景时,请务必考虑性能优化。 本主题提供 3D 类和属性的列表,这些类和属性对应用程序具有性能影响,并提供了在使用这些类时优化性能的建议。
本主题假定你对 Windows Presentation Foundation (WPF) 3D 功能有高级了解。 本文档中的建议适用于“呈现层 2”,大致定义为支持像素着色器版本 2.0 和顶点着色器版本 2.0 的硬件。 有关详细信息,请参阅 图形呈现层。
性能影响:高
财产 | 建议 |
---|---|
Brush | 画笔速度(最快至慢): SolidColorBrush LinearGradientBrush ImageBrush DrawingBrush (缓存) VisualBrush (缓存) RadialGradientBrush DrawingBrush (未缓存) VisualBrush (未缓存) |
ClipToBoundsProperty | 如果不需要使 Windows Presentation Foundation (WPF) 显式地将 Viewport3D 的内容剪裁到 Viewport3D 的矩形,请将 Viewport3D.ClipToBounds 设置为 false。 Windows Presentation Foundation (WPF) 的抗锯齿剪裁可能非常慢,并且在 Viewport3D 上默认启用ClipToBounds (慢速)。 |
IsHitTestVisible | 如果在执行鼠标点击测试时不需要 Windows Presentation Foundation (WPF) 考虑 Viewport3D 的内容,请将 Viewport3D.IsHitTestVisible 设置为 false。 点击测试 3D 内容是在软件中完成的,并且对于大型网格可能很慢。 默认情况下,IsHitTestVisible 在 Viewport3D上被启用(慢)。 |
GeometryModel3D | 仅当它们需要不同的材料或转换时,才创建不同的模型。 否则,请尝试将许多具有相同材料和转换的 GeometryModel3D 实例合并为几个更大的 GeometryModel3D 和 MeshGeometry3D 实例。 |
MeshGeometry3D | 在 Windows Presentation Foundation(WPF)中,网格动画(每帧更改网格的各个顶点)并不总是高效的。 要在修改每个顶点时尽量减少更改通知的性能影响,请在执行每顶点修改之前将网格从可视树中分离出来。 修改网格后,将其重新附加到可视化树。 此外,尽量减小以这种方式进行动画处理的网格大小。 |
3D 抗锯齿 | 为了提高渲染速度,可通过将附加属性 EdgeMode 设置为 Aliased 来禁用 Viewport3D 上的多重采样。 默认情况下,3D 抗锯齿功能在 Windows 上启用,每个像素有 4 个样本。 |
文本 | 在 3D 场景中的实时文本(实时是因为它在 DrawingBrush 或 VisualBrush 中)可能会很慢。 尝试使用文本的图像(通过 RenderTargetBitmap),除非文本将更改。 |
TileBrush | 如果必须在 3D 场景中使用 VisualBrush 或 DrawingBrush,因为画笔的内容不是静态的,请尝试缓存画笔(将附加属性 CachingHint 设置为 Cache )。 设置最小和最大缩放无效阈值(使用附加属性 CacheInvalidationThresholdMinimum 和 CacheInvalidationThresholdMaximum),以便缓存的画笔不会太频繁地重新生成,同时仍然保持所需的质量级别。 默认情况下,不会缓存 DrawingBrush 和 VisualBrush,这意味着每次使用画笔绘制的内容都必须重新呈现时,必须首先将画笔的全部内容重新呈现到中间图面。 |
BitmapEffect | BitmapEffect 强制呈现所有受影响的内容,而无需硬件加速。 为了获得最佳性能,请勿使用 BitmapEffect。 |
性能影响:中等
财产 | 建议 |
---|---|
MeshGeometry3D | 如果将网格定义为共享顶点且相邻的三角形,并且这些顶点具有相同的位置、法线和纹理坐标,则每个共享顶点仅需定义一次,然后使用TriangleIndices索引来指定三角形。 |
ImageBrush | 当你对大小有显式控制时(使用 RenderTargetBitmap 和/或 ImageBrush时),请尝试最小化纹理大小。 请注意,分辨率较低的纹理可以降低视觉质量,因此请尝试在质量和性能之间找到适当的平衡。 |
不透明度 | 呈现半透明 3D 内容(如反射)时,在画笔或材料(通过 Opacity 或 Color)上使用不透明度属性,而不是通过将 Viewport3D.Opacity 设置为小于 1 的值来创建单独的半透明 Viewport3D。 |
Viewport3D | 最大程度地减少你在场景中使用的 Viewport3D 对象数。 在同一 Viewport3D 中放置许多 3D 模型,而不是为每个模型创建单独的 Viewport3D 实例。 |
Freezable | 通常,重复使用 MeshGeometry3D、GeometryModel3D、画笔和材料是有益的。 它们都是多父的,因为它们派生自 Freezable 。 |
Freezable | 当“可冻结”的属性在应用程序中保持不变时,对其调用 Freeze 方法。 冻结可以减少工作集,提高速度。 |
Brush | 在画笔内容不会更改时,请使用 ImageBrush 而不是 VisualBrush 或 DrawingBrush。 2D 内容可以通过 RenderTargetBitmap 转换为 Image,然后在 ImageBrush 中使用。 |
BackMaterial | 除非你实际上需要看到 GeometryModel3D 的背面,否则不要使用 BackMaterial。 |
Light | 光速(最快至最慢): AmbientLight DirectionalLight PointLight SpotLight |
MeshGeometry3D | 尝试将网格大小保持在以下限制之下: Positions:20,001 个 Point3D 实例 TriangleIndices:60,003 个 Int32 实例 |
Material | 材料速度(最快至慢): EmissiveMaterial DiffuseMaterial SpecularMaterial |
Brush | Windows Presentation Foundation (WPF) 3D 不会以一致的方式选择退出不可见的画笔(黑色环境画笔和清除画笔等)。 请考虑从场景中省略这些内容。 |
MaterialGroup | MaterialGroup 中的每一个 Material 都会导致另一个呈现传递,因此包括许多材料,甚至是简单的材料,都可以显著增加 GPU 上的填充需求。 尽量减少 MaterialGroup 材料的数量。 |
性能影响:低
财产 | 建议 |
---|---|
Transform3DGroup | 如果不需要动画或数据绑定,与其使用包含多个转换的转换组,不如使用单个 MatrixTransform3D,将其设置为转换组中独立存在的所有转换的乘积。 |
Light | 最大程度地减少场景中的灯光数量。 场景中的灯光过多将迫使 Windows Presentation Foundation (WPF) 回退到软件渲染。 限制约为 110 个 DirectionalLight 对象、70 个 PointLight 对象或 40 个 SpotLight 对象。 |
ModelVisual3D | 通过将移动对象与静态对象置于不同的 ModelVisual3D 实例中,将它们分开。 ModelVisual3D 比 GeometryModel3D 更“负担重”,因为它缓存了转换后的边界。 GeometryModel3D 已优化为模型;ModelVisual3D 已优化为场景节点。 使用 ModelVisual3D 将 GeometryModel3D 的共享实例放入场景中。 |
Light | 最大程度地减少更改场景中的灯数的次数。 光计数的每个更改都强制着色器重新生成和重新编译,除非以前存在该配置(因此缓存了着色器)。 |
Light | 黑光灯不可见,但它们会增加渲染时间,可以考虑省略。 |
MeshGeometry3D | 若要最大程度地减少 Windows Presentation Foundation(WPF)中大型集合的构造时间,例如 MeshGeometry3D 的 Positions、Normals、TextureCoordinates和 TriangleIndices,在值填充之前预先调整集合的大小。 如果可能,请向集合的构造函数传递预填充的数据结构,例如数组或列表。 |