最大化 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 内容是在软件中完成的,并且对于大型网格可能很慢。 默认情况下,IsHitTestVisibleViewport3D上被启用(慢)。
GeometryModel3D 仅当它们需要不同的材料或转换时,才创建不同的模型。 否则,请尝试将许多具有相同材料和转换的 GeometryModel3D 实例合并为几个更大的 GeometryModel3DMeshGeometry3D 实例。
MeshGeometry3D 在 Windows Presentation Foundation(WPF)中,网格动画(每帧更改网格的各个顶点)并不总是高效的。 要在修改每个顶点时尽量减少更改通知的性能影响,请在执行每顶点修改之前将网格从可视树中分离出来。 修改网格后,将其重新附加到可视化树。 此外,尽量减小以这种方式进行动画处理的网格大小。
3D 抗锯齿 为了提高渲染速度,可通过将附加属性 EdgeMode 设置为 Aliased来禁用 Viewport3D 上的多重采样。 默认情况下,3D 抗锯齿功能在 Windows 上启用,每个像素有 4 个样本。
文本 在 3D 场景中的实时文本(实时是因为它在 DrawingBrushVisualBrush 中)可能会很慢。 尝试使用文本的图像(通过 RenderTargetBitmap),除非文本将更改。
TileBrush 如果必须在 3D 场景中使用 VisualBrushDrawingBrush,因为画笔的内容不是静态的,请尝试缓存画笔(将附加属性 CachingHint 设置为 Cache)。 设置最小和最大缩放无效阈值(使用附加属性 CacheInvalidationThresholdMinimumCacheInvalidationThresholdMaximum),以便缓存的画笔不会太频繁地重新生成,同时仍然保持所需的质量级别。 默认情况下,不会缓存 DrawingBrushVisualBrush,这意味着每次使用画笔绘制的内容都必须重新呈现时,必须首先将画笔的全部内容重新呈现到中间图面。
BitmapEffect BitmapEffect 强制呈现所有受影响的内容,而无需硬件加速。 为了获得最佳性能,请勿使用 BitmapEffect

性能影响:中等

财产 建议
MeshGeometry3D 如果将网格定义为共享顶点且相邻的三角形,并且这些顶点具有相同的位置、法线和纹理坐标,则每个共享顶点仅需定义一次,然后使用TriangleIndices索引来指定三角形。
ImageBrush 当你对大小有显式控制时(使用 RenderTargetBitmap 和/或 ImageBrush时),请尝试最小化纹理大小。 请注意,分辨率较低的纹理可以降低视觉质量,因此请尝试在质量和性能之间找到适当的平衡。
不透明度 呈现半透明 3D 内容(如反射)时,在画笔或材料(通过 OpacityColor)上使用不透明度属性,而不是通过将 Viewport3D.Opacity 设置为小于 1 的值来创建单独的半透明 Viewport3D
Viewport3D 最大程度地减少你在场景中使用的 Viewport3D 对象数。 在同一 Viewport3D 中放置许多 3D 模型,而不是为每个模型创建单独的 Viewport3D 实例。
Freezable 通常,重复使用 MeshGeometry3DGeometryModel3D、画笔和材料是有益的。 它们都是多父的,因为它们派生自 Freezable
Freezable 当“可冻结”的属性在应用程序中保持不变时,对其调用 Freeze 方法。 冻结可以减少工作集,提高速度。
Brush 在画笔内容不会更改时,请使用 ImageBrush 而不是 VisualBrushDrawingBrush。 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 的 PositionsNormalsTextureCoordinatesTriangleIndices,在值填充之前预先调整集合的大小。 如果可能,请向集合的构造函数传递预填充的数据结构,例如数组或列表。

另请参阅