原文:最优化WPF 3D性能(基于“Tier-2”硬件)

原文地址:Maximizing WPF 3D Performance on Tier-2 Hardware

开发人员在应用程序中使用Windows Presentation Foundation来构建大量的3D控件、包含3D场景时,常常会遇到如何优化其性能的问题。WPF 3D组的几个成员提供了一个影响应用程序性能的3D类和属性的列表。当我们使用她们来优化应用程序性能时应该遵从这些建议。

本随笔假定你深刻的理解了WPF 3D API。不熟悉这些API的用户在使用这些建议之前应该首先阅读WPF SDK文档。本随笔中提出的建议只适用于“Tier-2”的视频硬件(通常是指支持象素Shader 2.0和顶点Shader 2.0的硬件)。为了简洁,本随笔进行适当的总结,因此真正理解掌握她们并不简单。

性能影响级:高

属性

建议

Brush

Brush速度(从快到慢):

SolidColorBrush

LinearGradientBrush

ImageBrush

DrawingBrush(缓存的)

VisualBrush(缓存的)

RadialGradientBrush

DrawingBrush(未缓存的)

VisualBrush(未缓存的)

Viewport3D.ClipToBounds

在明确不需要把Viewport3D的内容剪切到Viewport3D的矩形范围内时,应该把Viewport3D.ClipToBounds设置为false。WPF的反走样剪切非常慢,而且ClipToBounds默认是为true的。

Viewport3D.IsHitTestVisible

如果鼠标点击时不需要考虑Viewport3D的内容,Viewport3D.IsHitTestVisible应该设置为false。3D内容的点击测试是由软件实现的,在大的网格中非常慢。Viewport3D的IsHitTestVisible默认是为true的。

GeometryModel3D

只有在需要不同的Materials或者Transforms时,才建立不同的模型。否则应该把多个GeometryModel3D实例用相同的Materials和Transforms组合到一个更大的GeometryModel3D和MeshGeometry3D实例之中。

MeshGeometry3D

基于每帧来改变网格的不同顶点形成的网格动画在WPF不是很高效。在修改顶点时,为了减少对性能的影响,在执行每个顶点的修改之前应该从Visual树中Detach网格。在修改完成后,重新Attach到Visual树。同样,构建这样的动画时应该减小网格的大小。

3D反走样

为了尽可能增加提交速度,可通过设置Attached属性RenderOptions.EdgeMode为Aliased来禁用Multisampling。默认时,3D反走样在Windows XP被禁用,而在Windows Vista被启用,每个象素4个Samples。

Text

3D场景中的实时文本(比较在DrawingBrush或者VisualBrush中的文本就是实时的)通常非常缓慢。尝试使用文本的图像(通过RenderTargetBitmap)来代替她,除非你需要修改文本。

TileBrush

如果你必须要在3D场景中使用VisualBrush或者DrawingBrush(因为这种Brush的内容不是静态的),应该尝试缓存Brush(通过设置Attached属性RenderOptions.CachingHint为Cache实现)。

用CacheInvalidationThresholdMinimum、CacheInvalidationThresholdMaximum设置无效放缩的最大、最小阀值。她能在场景中减小Brush重新生成的次数(甚至是避免),同时保持我们需要的质量。默认时,DrawingBrush和VisualBrush都没有缓存,表示每次重画都必须重新生成画刷,而且整个内容是被画到一个临时的Surface,最后再复制到目标Surface。

BitmapEffect

BitmapEffect强制其影响的所有内容都不能使用硬件加速来提交。如果需要最好的性能,请不要使用BitmapEffect。

性能影响级别:中

属性

建议

MeshGeometry3D

如果网格是通过共享顶点(而且这些顶点的位置、向量和纹理映射都相同),以邻接三角形的形式定义网格的,共享的顶点应该只定义一次,然后用索引MeshGeometry3D.TriangleIndices来定义三角形。

ImageBrush

当我们需要直接控制纹理大小时(比如在使用RenderTargetBitmap和/或者ImageBrush时),应该尽可能减小WPF纹理大小。注意低分辨率的纹理会降低显示质量。因此在质量和性能之间应该进行合理的选择。

Opacity

提交半透明的3D内容时(比如反射),应该在Brush或者Materials上使用Opacity属性(通过Brush.Opacity或者Materials.Opacity)而不是另外建立一个半透明的Viewport3D(使Viewport3D.Opacity < 1)。

Viewport3D

减少在场景中使用的Viewport3D的数量。把多个3D模型放在同一个Viewport3D之中,而不是为每个模型建立不同的Viewport3D。

Freezable

通常,重用MeshGeometry3D、GeometryModel3D、Brush和Materials很有好处。由于她们都从Freezable继承,都可以拥有多个父元素。

Brush

当Brush内容不改变时,用ImageBrush来代替VisualBrush和DrawingBrush。2D内容可以通过RenderTargetBitmap转换为Image,然后在ImageBursh中使用。

Light

光源速度(从快到慢):

Ambient

Directional

Point

Spot

MeshGeometry3D

尽量让网格大小满足这些条件:

MeshGeometry3D.Positions: 20,001个Point3D实例

MeshGeometry3D.TriangleIndices: 60,003个Int32实例

Materials

Materials速度(从快到慢):

EmissiveMaterials

DiffuseMaterials

SpecularMaterials

Brush

WPF 3D没有以相同的方式来选择忽略不可见的画刷(黑色的环境Brush、光亮画刷等等)。不要在我们的场景中使用她们。

MaterialsGroup

在MaterialsGroup中的每个Materials都引起另一个提交通道,因此包含多个Materials,即使是简单的Materials也会严重地增加GPU的填充指令。应该在MaterialsGroup尽可能减少Materials的数量。

性能影响级别:低

属性

建议

Transform3DGroup

当我们不需要动画或者数据绑定时,不要使用Transform组包含多个Transform。而是使用一个单独的MatrixTransform3D。

Light

在场景中减少光源的数量。太多的光源会强制WPF回退到软件提交实现。粗略的限制是110个DirectionalLights、70个PointLights或者40个SpotLights。

ModelVisual3D

应该把静态对象单独放入一个ModelVisual3D实例。ModelVisual3D比GeometryModel3D更庞大,因为她缓存了变换的边界。GeometryModel3D适合于模型。而ModelVisual3D适合于场景点。我们需要使用ModelVisual3D来把GeometryModel3D实例(希望共享)放入场景之中。

Light

在场景中减少改变光源的次数。每次改变光源都强制重新生成Shader、重新编译。除非原来的配置已经存在(也就是Shader被缓存)。

MeshGeometry3D

为了减少在WPF构造大量集合的时间,比如MeshGeometry3D的Position、Normals、TextureCoordinates和TrangleIndices。应该在值写入前就改变集合的大小。如果可能,直接向集合的构造函数传入一个Array或者List。

作者:David Teitlebaum。感谢Chris Raubacher、Anthony Hodsdon、Jordan Parker和Daniel Lehenbauer。

最优化WPF 3D性能(基于“Tier-2”硬件)的更多相关文章

  1. 优化WPF 3D性能

    Maximize WPF 3D Performance .NET Framework 4.5   As you use the Windows Presentation Foundation (WPF ...

  2. WPF 3D 知识点大全以及实例

    引言 现在物联网概念这么火,如果监控的信息能够实时在手机的客服端中以3D形式展示给我们,那种体验大家可以发挥自己的想象. 那生活中我们还有很多地方用到这些,如上图所示的Kinect 在医疗上的应用,当 ...

  3. WPF 3D 小小小小引擎 - ·WPF 3D变换应用

    原文:WPF 3D 小小小小引擎 - ·WPF 3D变换应用 WPF可以提供的3D模型使我们可以轻松地创建3D实体,虽然目前来看还很有一些性能上的问题,不过对于一些简单的3D应用应该是可取的,毕竟其开 ...

  4. WPF 3D: MeshGeometry3D纹理坐标的正确定义

    原文 WPF 3D: MeshGeometry3D纹理坐标的正确定义 为了使基于2D的纹理显示在3D对象中,我们必须定义3D Mesh对象的纹理贴图坐标.在WPF中,此项功能则通过MeshGeomet ...

  5. WPF 3D变换应用

    WPF可以提供的3D模型使我们可以轻松地创建3D实体,虽然目前来看还很有一些性能上的问题,不过对于一些简单的3D应用应该是可取的,毕竟其开发效率高,而且也容易上手. 下面给大家演示的是使用在WPF 3 ...

  6. WPF 3D编程介绍

    原文:WPF 3D编程介绍 上一篇文章简单的介绍了WPF编程的相关的内容,也推荐了本书.今天要来讲一下在WPF如何开展3D编程. 使用的xmal 和C#开发的时候:需要使用如下的关键要素: 1:摄像机 ...

  7. WPF 3D 获取鼠标在场景的3d坐标

    原文:WPF 3D 获取鼠标在场景的3d坐标 上一篇中我们谈到了WPF 3d做图的一些简单原理,这里我们简单介绍一下怎样获得鼠标在场景中的3d坐标,知道了3d坐标就可以进行很多操作了: 首先介绍一下3 ...

  8. WPF 3D 模型旋转

    原文:WPF 3D 模型旋转 WPF 是 Microsoft 在 Framework3.0 中支持的一种技术,它能作出很绚丽的界面,同时它也支持3D的操作.在3D操作主要包括平移(Translate) ...

  9. WPF 3D 常用类(1)

    原文:WPF 3D 常用类(1) 几何数据相关类 Geometry3D 抽象类, 用于定义物体的几何数据, 可用于计算HitTest和BoundingBox MeshGeometry3D Geomet ...

随机推荐

  1. Redis源码解析:24sentinel(五)TLIT模式、执行脚本

    十一:TILT模式 根据之前的介绍可知,哨兵的运行,非常依赖于系统时间,但是当系统时间被调整,或者哨兵中的流程因为某种原因(比如负载较高.IO发生阻塞.进程被信号停止等)而被阻塞时,哨兵的行为就会变得 ...

  2. Spring配置xml自动提示——转载https://blog.csdn.net/sinat_18474835/article/details/79370629

    以Spring2.0为例: 下载地址: Csdn: http://download.csdn.net/download/hh775313602/9812757 没积分的可以去百度网盘下载,我已共享: ...

  3. MAC+iTerm定制目录显示颜色和提示符

    知道该如何定制ls时各种类型文件(unix下所有的都是file..)的颜色了. 很简单,就是在.bash_profile下加了三行. export CLICOLOR=1 export LSCOLORS ...

  4. 如何获取Expression Design 4工具与Expression Blend 4工具

    在VS2010+C#+WPF 开发项目过程中涉及到界面的布局与设计,网上有人讲采用Expression Design 4与Expression Blend 4工具相当方便, 于是决定试看看,下面将这个 ...

  5. jnhs[未解决]无法使用选定的hibernate配置文件建立数据库连接.请验证hibernate.cfg.xml中的数据库连接详情信息

    工程可以正常的使用读写数据库,当然model和model.hbm.xml文件是自己写的. 解决中

  6. 学习JDK1.8集合源码之--PriorityQueue

    1. PriorityQueue简介 PriorityQueue是一种优先队列,不同于普通队列的先进先出原则,优先队列是按照元素的优先级出列,每次出列都是优先级最高的元素.优先队列的应用很多,最典型的 ...

  7. 解决git的the remote end hung up问题_百度经验

    使用git更新或提交中途有时出现The remote end hung up unexpectedly的异常,特别是资源库在国外的情况下.此问题可能由网络原因引起. 工具/原料   git 方法/步骤 ...

  8. Django独有报错的原因和解决

    RuntimeError at /login You called this URL via POST, but the URL doesn't end in a slash and you have ...

  9. QT_获取运行进程所在目录路径_2

    QString getProcessFullPath(const quint64 &processId) { #ifdef Q_OS_WIN // access process path WC ...

  10. 你真的了解HTML吗

    有这么一段HTML,请挑毛病: <P> 哥写的不是HTML,是寂寞.<br><br> 我说: <br>不要迷恋哥,哥只是一个传说 这是原来雅虎一道笔试题 ...