使用 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.ClipToBounds 的内容剪裁到 Viewport3D 的矩形,请将 Viewport3D 设置为 false。 Windows Presentation Foundation (WPF) 的抗锯齿剪裁可能非常慢,并且在 ClipToBounds 上默认启用Viewport3D(慢速)。 |
IsHitTestVisible | 如果在执行鼠标点击测试时不需要 Windows Presentation Foundation (WPF) 考虑 Viewport3D.IsHitTestVisible 的内容,请将 Viewport3D 设置为 false。 点击测试 3D 内容是在软件中完成的,并且对于大型网格可能很慢。 默认情况下,IsHitTestVisible 在 Viewport3D上被启用(慢)。 |
GeometryModel3D | 仅当它们需要不同的材料或转换时,才创建不同的模型。 否则,请尝试将许多具有相同材料和转换的 GeometryModel3D 实例合并为几个更大的 GeometryModel3D 和 MeshGeometry3D 实例。 |
MeshGeometry3D | 在 Windows Presentation Foundation(WPF)中,网格动画(每帧更改网格的各个顶点)并不总是高效的。 要在修改每个顶点时尽量减少更改通知的性能影响,请在执行每顶点修改之前将网格从可视树中分离出来。 修改网格后,将其重新附加到可视化树。 此外,尽量减小以这种方式进行动画处理的网格大小。 |
3D 抗锯齿 | 为了提高渲染速度,可通过将附加属性 Viewport3D 设置为 EdgeMode来禁用 Aliased 上的多重采样。 默认情况下,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 设置为小于 1 的值来创建单独的半透明 Viewport3D.Opacity 。 |
Viewport3D | 最大程度地减少你在场景中使用的 Viewport3D 对象数。 在同一 Viewport3D 中放置许多 3D 模型,而不是为每个模型创建单独的 Viewport3D 实例。 |
Freezable | 通常,重复使用 MeshGeometry3D、GeometryModel3D、画笔和材料是有益的。 它们都是多父的,因为它们派生自 Freezable 。 |
Freezable | 当“可冻结”的属性在应用程序中保持不变时,对其调用 Freeze 方法。 冻结可以减少工作集,提高速度。 |
Brush | 在画笔内容不会更改时,请使用 ImageBrush 而不是 VisualBrush 或 DrawingBrush。 2D 内容可以通过 Image 转换为 RenderTargetBitmap,然后在 ImageBrush 中使用。 |
BackMaterial | 除非你实际上需要看到 BackMaterial 的背面,否则不要使用 GeometryModel3D。 |
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 | Material 中的每一个 MaterialGroup 都会导致另一个呈现传递,因此包括许多材料,甚至是简单的材料,都可以显著增加 GPU 上的填充需求。 尽量减少 MaterialGroup 材料的数量。 |
性能影响:低
资产 | 建议 |
---|---|
Transform3DGroup | 如果不需要动画或数据绑定,与其使用包含多个转换的转换组,不如使用单个 MatrixTransform3D,将其设置为转换组中独立存在的所有转换的乘积。 |
Light | 最大程度地减少场景中的灯光数量。 场景中的灯光过多将迫使 Windows Presentation Foundation (WPF) 回退到软件渲染。 限制约为 110 个 DirectionalLight 对象、70 个 PointLight 对象或 40 个 SpotLight 对象。 |
ModelVisual3D | 通过将移动对象与静态对象置于不同的 ModelVisual3D 实例中,将它们分开。 ModelVisual3D 比 GeometryModel3D 更“负担重”,因为它缓存了转换后的边界。 GeometryModel3D 已优化为模型;ModelVisual3D 已优化为场景节点。 使用 ModelVisual3D 将 GeometryModel3D 的共享实例放入场景中。 |
Light | 最大程度地减少更改场景中的灯数的次数。 光计数的每个更改都强制着色器重新生成和重新编译,除非以前存在该配置(因此缓存了着色器)。 |
轻度 | 黑光灯不可见,但它们会增加渲染时间,可以考虑省略。 |
MeshGeometry3D | 若要最大程度地减少 Windows Presentation Foundation(WPF)中大型集合的构造时间,例如 MeshGeometry3D 的 Positions、Normals、TextureCoordinates和 TriangleIndices,在值填充之前预先调整集合的大小。 如果可能,请向集合的构造函数传递预填充的数据结构,例如数组或列表。 |