最大程度地提高 WPF 三维性能

使用 Windows Presentation Foundation (WPF) 生成 3D 控件并在应用程序中包含 3D 场景时,请务必考虑性能优化。 本主题提供对应用程序具有性能影响的 3D 类和属性的列表,以及在使用它们时优化性能的建议。

本主题假定你对 Windows Presentation Foundation (WPF) 3D 功能具有深入理解。 本文档中的建议适用于“呈现层 2” - 大致定义为支持像素着色器版本 2.0 和顶点着色器版本 2.0 的硬件。 有关详细信息,请参阅图形呈现层

性能影响:高

properties 建议
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 内容是在软件中完成的,并且对于大型网格可能很慢。 在 Viewport3D 上默认启用 IsHitTestVisible(慢速)。
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

性能影响:中

properties 建议
MeshGeometry3D 如果将网格定义为带有共享顶点的邻接三角形,并且这些顶点具有相同的位置、法线和纹理坐标,则仅需定义每个共享顶点一次,然后通过索引 TriangleIndices 定义三角形。
ImageBrush 对纹理大小有显示控制时(使用 RenderTargetBitmap 和/或 ImageBrush 时),尝试最小化纹理大小。 请注意,低分辨率的纹理会降低视觉质量,因此请尝试在质量和性能之间找到合适的平衡。
不透明度 呈现半透明 3D 内容(如反射)时,请使用画笔或材料的不透明度属性(通过 OpacityColor),而不是通过将 Viewport3D.Opacity 设置为小于 1 的值来创建一个单独的半透明 Viewport3D
Viewport3D 尽量减少在场景中使用的 Viewport3D 对象的数量。 将许多 3D 模型放在同一个 Viewport3D 中,而不是为每个模型创建单独的 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 材料的数量。

性能影响:低

properties 建议
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 的 PositionsNormalsTextureCoordinatesTriangleIndices)的构造时间,应在填充值之前预先调整集合的大小。 如果可能,请向集合的构造函数传递预填充的数据结构,例如数组或列表。

另请参阅