Maximizing WPF 3D Performance on Tier-2 Hardware

As people use the Windows Presentation Foundation to build more 3D controls and include 3D scenes in their applications, they’ve been asking questions about how to optimize performance.  Several members of the WPF 3D team have provided a list of 3D classes and properties that have performance implications, along with recommendations for optimizing performance when you use them.

This post assumes an advanced understanding of the WPF 3D API.  Users unfamiliar with the API should consult the WPF SDK before making use of these suggestions.  The advice in this post only applies to “Tier-2” video hardware—roughly defined as hardware that supports pixel shader version 2.0 and vertex shader version 2.0.  In the interest of brevity, this post makes some generalizations—your mileage may vary.

Performance Impact: High




Brush speed (fastest to slowest):




DrawingBrush (cached)

VisualBrush (cached)


DrawingBrush (uncached)

VisualBrush (uncached)


Set Viewport3D.ClipToBounds to false whenever you do not need to have WPF explicitly clip the content of a Viewport3D to the Viewport3D’s rectangle.  WPF’s antialiased clipping can be very slow, and ClipToBounds is enabled (slow) by default on Viewport3D.


Set Viewport3D.IsHitTestVisible to false whenever you do not need WPF to consider the content of a Viewport3D when performing mouse hit testing.  Hit testing 3D content is done in software and can be very slow with large meshes, and IsHitTestVisible is enabled (slow) by default on Viewport3D.


Only make different models when they require different Materials or Transforms.  Otherwise try to coalesce many GeometryModel3D instances with the same Materials and Transforms into a few large GeometryModel3D and MeshGeometry3D instances.


Mesh animation—changing the individual vertices of a mesh on a per-frame basis—is not very efficient in WPF.  To minimize the performance impact of change-notifications when each vertex is modified, detach the mesh from the visual tree before performing per-vertex modification.  Once the mesh has been modified, reattach it to the visual tree.  Also, try to minimize the size of meshes which will be animated in this way.

3D Antialiasing

To potentially increase rendering speed, disable multisampling on a Viewport3D by setting the attached property RenderOptions.EdgeMode to Aliased.  By default, 3D antialiasing is disabled on Windows XP and enabled on Vista with 4 samples per pixel.


Live text in a 3D scene (live because it’s in a DrawingBrush or VisualBrush) is often super slow. Try to use images of the text instead (via RenderTargetBitmap) unless the text will be changing.


If you absolutely must use a VisualBrush or a DrawingBrush in a 3D scene (since the brush’s content is not static), try caching the brush (setting the attached property RenderOptions.CachingHint to Cache).  Set the min and max scale invalidation thresholds (with the attached properties CacheInvalidationThresholdMinimum and CacheInvalidationThresholdMaximum) so that the cached brushes won’t be regenerated too frequently (or ever) given your scene, while still maintaining your desired level of quality.  By default, DrawingBrushes and VisualBrushes are not cached, meaning that every time something painted with the brush has to be re-rendered, the entire content of the brush must first be re-rendered to an intermediate surface.


BitmapEffects force all affected content to be rendered without hardware acceleration.  For best performance, do not use BitmapEffects.


Performance Impact: Medium




When a mesh is defined as abutting triangles with shared vertices and those vertices have the same position, normal, and texture coordinates, define each shared vertex only once and then define your triangles by index with MeshGeometry3D.TriangleIndices.


Try to minimize WPF’s texture sizes when you have explicit control over the size (as when you’re using a RenderTargetBitmap and/or an ImageBrush).  Note that lower resolution textures can decrease visual quality, so try to find the right balance between quality and performance.


When rendering translucent 3D content (such as reflections), use the opacity properties on Brushes or Materials (via Brush.Opacity or Material.Color) instead of creating a separate translucent Viewport3D (with Viewport3D.Opacity < 1).


Minimize the number of Viewport3D objects you’re using in a scene.  Put many 3D models in the same Viewport3D rather than creating separate Viewport3D instances for each model.


Typically it’s beneficial to reuse MeshGeometry3D, GeometryModel3D, Brushes, and Materials.  All are multiparentable since they’re derived from Freezable.


Call the Freeze method on Freezables when their properties will remain unchanged in your application.  Freezing can decrease working set and increase speed.


Use ImageBrushes instead of VisualBrush or DrawingBrush when the content of the brush will not change.  2D content can be converted to an Image via RenderTargetBitmap and then used in an ImageBrush.


Don’t use GeometryModel3D.BackMaterial unless you actually have a use for seeing the back faces of your GeometryModel3D.


Light speed (fastest to slowest):






Try to keep mesh sizes under these limits:

MeshGeometry3D.Positions: 20,001 Point3D instances

MeshGeometry3D.TriangleIndices: 60,003 Int32 instances


Material speed (fastest to slowest):





WPF 3D doesn’t opt out of invisible brushes (black ambient brushes, clear brushes, etc…) in a consistent way.  Don’t put these in your scene.


Each Material in a MaterialGroup causes another rendering pass, so many including materials, even simple materials, can dramatically increase the fill demands on your GPU.  Minimize the number of materials in your MaterialGroup.


Performance Impact: Low




When you don’t need animation or databinding, instead of using a transform group containing multiple transforms, use a single MatrixTransform3D, setting it to be the product of all the transforms that would otherwise exist independently in the transform group.


Minimize the number of lights in your scene. Too many lights in a scene will force WPF to fall back to software rendering.  The limits are roughly ~110 DirectionalLights, ~70 PointLights, or ~40 SpotLights.


Separate moving objects from static objects by putting them in separate ModelVisual3D instances.  ModelVisual3D is “heavier” than GeometryModel3D because it caches transformed bounds.  GeometryModel3Ds are optimized to be models.  ModelVisual3Ds are optimized to be scene nodes.  You want to use ModelVisual3Ds to put instances of (hopefully shared) GeometryModel3Ds into the scene.


Minimize the number of times you change the number of lights in the scene.  Each change of light count forces a shader regeneration and recompilation unless that configuration has already existed previously (and thus had its shader cached).


Black lights won’t be visible, but they will still add to render time, so don’t use them.


To minimize the construction time of large collections  in WPF, such as a MeshGeometry3D’s Positions, Normals, TextureCoordinates, and TriangleIndices, pre-size the collections before value population, and if possible, pass the the collections’ constructors pre-populated data structures such as arrays or Lists.


By David Teitlebaum, with contributions from Chris Raubacher, Anthony Hodsdon, Jordan Parker, and Daniel Lehenbauer.


About Us

We are the Windows Presentation Foundation SDK writers and editors.

Comments (9)

  1. David Teitlebaum has put together a set of perf guidelines which should help you get the most out of

  2. Celà va plaire a certains afficionadosde WPF de la communauté, l’équipe du SDK de WPF à publié un billet

  3. Members of the WPF 3D team have provided a list of 3D classes and properties with performance implications,

  4. Yiling Lai says:

    开发人员在应用程序中使用Windows Presentation Foundation来构建大量的3D控件、包含3D场景时,常常会遇到如何优化其性能的问题。WPF 3D组的几个成员提供了一个影响应用程序性能的3D类和属性的列表。当我们使用她们来优化应用程序性能时应该遵从这些建议。本随笔假定你深刻的理解了WPF 3D API。不熟悉这些API的用户在使用这些建议之前应该首先阅读WPF SDK文档。本随笔中提出的建议只适用于“Tier-2”的视频硬件(通常是指支持象素Shader 2.0和顶点Shader

  5. We gave a lecture on 3D yesterday at a "WPF Bootcamp" event and I’ve attached the slides. Here’s the

  6. I just discovered this great post by the WPF 3D team: Maximizing WPF 3D Performance on Tier-2 Hardware

  7. I just found this very nice blog entry with hints for WPF 3D Summary of the hints that I found more interesting/not

  8. WPF 3D Reflections Brush Optimisation

  9. Ho trovato un link utile a chi si diletta nello sviluppo di applicazioni WPF. Sono riportati tutti gli