New version of Ab3d.DXEngine comes with DirectX command list caching and many new features

by abenedik 1. June 2020 11:48

I am proud to inform you that a new major release of the Ab3d.DXEngine has been released. There is also a new minor version of Ab3d.PowerToys.

Let's start with a question: what makes a rendering engine faster? The answer is simple: a faster rendering engine will render the 3D scene quicker and achieve higher frames per second. This can be achieved in two ways. The first option is to provide special rendering techniques to the end-user that can optimize the rendering (for example, object instancing). The second option is to organize the data for the 3D scene so that it can be sent to the graphics card as quickly as possible and in a way that allows the graphics card to render the scene the most optimally.

This part of the job is done internally by the DXEngine. This process was already highly optimized for CPU, memory access and can be executed using multiple threads. Still, a 3D scene with a few thousand objects may require a few milliseconds of CPU time to render. In this case, a rendering engine written in C++ or another low-level language may be faster because its code can be better optimized.

But with the introduction of DirectX commands caching in the new version of Ab3d.DXEngine, this advantage of low-level languages is significantly reduced. In case when only camera or lights are changed (the majority of cases in a typical business or scientific 3D application), then the new version of Ab3d.DXEngine can render the new frame with only updating the camera and lights data and then "instructing" the graphics card to re-render the new frame with using the DirectX commands that were recorded in one of the previous frames. This requires so little code to be executed on the CPU, that even if the engine were written in C++, the performance difference would not be noticeable.

Therefore I would like to conclude the first part of this post with a statement that in cases when DirectX commands caching can be used (in a typical business 3D application this is most of the cases) the Ab3d.DXEngine is as fast as if it would be written in C++. 

Let me show you that in action:

Ab3d.DXEngine with DirectX command list caching

As seen from this screenshot, in case of rendering 160.000 individual 3D objects, the time required to send all that data to the graphics card is only 0.14 ms (see DrawRenderTime which shows time to execute 160.000 draw calls with all required state changes). This way, it would be possible to achieve almost 3000 FPS. When the command list caching would be disabled, then the DrawRenderTime would be around 16 ms. This is still a fantastic result and can be achieved using multi-threading and many other optimizations.

Another area that received some great new features is rendering transparent objects. Rendering transparent objects can be hard in 3D graphics. The reason for that is that when a transparent object is rendered, the colors of the already rendered objects are blended with the color of the transparent object. This means that if we want to see the objects through transparent objects, they need to be rendered before the transparent object. Usually (when the objects are not self-intersecting), this can be solved with sorting the objects so that the objects that are farther away from the camera are rendered first. To help you with sorting, you can use the TransparencySorter class from the Ab3d.PowerToys library. But this class work only for WPF 3D objects. What is more, sorting WPF 3D objects can be a very slow process and in case of complex hierarchy, it may not be possible to sort all the objects correctly.

The new version of Ab3d.DXEngine provides a better way of sorting transparent objects. With setting the DXScene.IsTransparencySortingEnabled property to true (by default it is set to false to make the engine work as in the previous version), the engine automatically sorts all the objects in the TransparentRenderingQueue. Because the objects there are defined in a flat queue, there is no problem with the hierarchical organization of objects. Also, sorting is highly optimized and uses multi-threading, so it is much faster than TransparencySorter. And finally, the DXEngine's SceneNodes can also be sorted in this way.

Another new feature regarding transparent objects is the added support for alpha-clipping and alpha-to-coverage. Those two techniques can be used to render textures that have opaque and also transparent pixels (for example, text with a transparent background or threes). An advantage of those two techniques is that they do not require the objects to be sorted by camera distance. But they can produce some artifacts on the areas where the transparent part of the texture is transitioned to the opaque part. If this transition is small, then the results can be very good. In the case of using alpha-clipping, the user can select an alpha clip threshold - this is a value that specifies at which alpha value the pixels are clipped. When using alpha-to-coverage, it is possible to use MSAA (multi-sample anti-aliasing) to provide a more accurate level of transparency with making some sub-pixel samples transparent and some opaque. See the comments in the new sample for more information.

There are also improvements in how textures are loaded. First, all textures that are created from WPF BitmapImage objects are checked if they actually contain transparent pixels. In the previous version, only the file format was checked and if it supported transparency, then the texture was considered transparent. In this case, the object that used that texture was put into the TransparentRenderingQueue - requiring alpha blending (more GPU memory transfer), transparency sorting and having no rendering optimizations. In the version, the DXEngine "knows" if the texture does not have any transparent pixels so its object can be put into the StandardGeometryRenderingQueue. This way, it gets support for multi-threaded rendering and DirectX commands caching.

The last new feature related to transparency is that the TextureLoader.LoadShaderResourceView method has been significantly improved. The method loads a texture into a DirectX resource and now also sets a new TextureInfo class that describes the loaded texture: image size, dpi, format, has transparent pixels. That information can help you correctly set the properties in the StandardMaterial or any other material that is showing the texture.

There are also some other great new features. Let me quickly mention some of them.

Object instancing also received a few improvements. The first improvement is that it is now possible to quickly hide (discard) some instances when setting their alpha color to 0. In the previous version, such instances were still rendered - they were not visible because of alpha value 0, but their depth values were still written and therefore this prevented rendering of all objects behind them. So in the previous version, you needed to re-create the InstancesData array with removing some items from the array.

The next new feature is that now you can render instanced objects with a single color without any light shading. Another instancing improvement is that it is now possible to specify the size of each instance in screen-space units. This means that even when you zoom in or out, the size of the instances on the screen will remain the same (the size calculations are done on the graphics card).

Another performance-related improvement is that now multi-threaded rendering is also supported for 3D lines. Before, it was supported only for standard and opaque 3D objects. It is still better to combine many 3D lines into a single 3D line object (for example, MultiLineVisual3D or even better ScreenSpaceLineNode), but if you happen to have many individual 3D line objects, then the new version could now render at more then 4-times the speed.

If you are an advanced DXEngine user, you will be interested in that the GeometryRenderingQueue has been split into 4 different rendering queues: 

  • ComplexGeometryRenderingQueue - used for instanced objects and very complex meshes (with more than 100.000 triangle indices or 20.000 lines) - the idea is to send such objects to GPU as soon as possible,
  • StandardGeometryRenderingQueue - highly optimized for rendering standard 3D objects - supports multi-threading and command list caching,
  • OtherGeometryRenderingQueue - used for other 3D objects with non-standard effects,
  • LineGeometryRenderingQueue - used for opaque and solid color 3D lines - support multi-threading),

The old GeometryRenderingQueue is still defined in the DXScene class. But it is marked as obsolete and points to the OtherGeometryRenderingQueue. If you are using the GeometryRenderingQueue, please change that to any of the 4 new rendering queues instead.

Advanced users will be also happy to hear that there are some interesting improvements in the Diagnostics project that is also used in the DXEngineSnoop tool (see also Diagnostics Guide). Now you can render an object-id bitmap of the 3D scene - there the colors in the bitmap represent the ids of the rendered objects. You can also disable and enable rendering of some RenderingQueues and RenderingSteps. With those new features, you can diagnose some low-level rendering problems and get some additional understanding of how the rendering engine works.


As always, there are many other new features, improvements and bug fixes. This is also true for Ab3d.PowerToys. To get the full list of changes see Ab3d.DXEngine versions history and Ab3d.PowerToys versions history.

From the number of support requests, I have seen that the corona crises have significantly slowed down the development worldwide. This lasted for around a month and a half. Then suddenly, there was a burst of activity that highly exceeded the time before the pandemic. So it looks like during the quarantine, you had time to gather many great new ideas. So, when the development started again, you wanted to try them right away. I was pleased to see that. I hope that the newly published versions will allow you to realize your ideas even more quickly and have better results.

Tags: , , , ,

Ab3d.PowerToys | DXEngine

New version of Ab2d.ReaderSvg supports .Net CORE 3.1

by abenedik 23. December 2019 15:43

I am happy to inform you that a new version of Ab2d.ReaderSvg library is available.

As you can see from the title of this blog post, the Ab2d.ReaderSvg got the .Net CORE 3.1 support and has joined the 3D libraries that also support that.

What is more, this version of Ab2d.ReaderSvg got a new distribution method - it can be installed as a NuGet package from the standard NuGet repository.

The new version is still available as a windows installer (evaluation version can be downloaded from Downloads web page; commercial version can be downloaded from the Users Account web page). The version that is installed with windows installer uses the same licensing mechanism as before – using license.licx files or application license key.

But because the licensing with license.licx files does not work anymore for .Net CORE applications and also because this licensing was not very intuitive to use, the distribution that comes with NuGet uses a new, so called “universal”, licensing mechanism. There a single dll file is used for both evaluation and commercial usage. If the commercial license is not activated, then on first use of the library the user gets a dialog where he can start a 60-day evaluation. But if the user has a commercial license, he can activate it with calling SetLicense method – for example:

Ab2d.Licensing.ReaderSvg.LicenseHelper.SetLicense(licenseOwner: "[CompanyName]", 
                                                  licenseType: "[LicenseType]", 
                                                  license: "[LicenseText]");

This should be easier to setup. The parameters for the SetLicense call will be available from the User Account web page. Currently this is not yet implemented on the web site, but you can contact support and you will get the required code snippet by email.

Because all users will have access to all future library version form NuGet web site, the license parameters also contain information about the updates subscription expiration date. So if you will not have a valid subscription when a new version will be available, you will not be able to use it. This also means that when updates subscription is renewed, then new license parameters will need to be entered to the SetLicense call. If will not want to update to new version, then you will need to limit the version to the last version that you still have access to. If you will want to the new version before renewing the license, you will simply need to comment the SetLicense call and start the library in an evaluation mode.

So to summarize: the new licensing mechanism is much simpler to use and understand, the library requires only one dll for both evaluation and commercial version and therefore it can be distributed as a NuGet package. And this licensing mechanism is supported in .Net CORE 3.1. 

This also means that the .Net CORE version is not available with windows installer. It can be get only from NuGet.

With windows installer you also get samples projects and Users Reference help file. This is not available with NuGet. But there are now more standard ways to get them:

- Samples can get downloaded from GitHub -

- Help is available online -


Support for .Net CORE 3.1 is not the only new feature of this release. If you are using ReaderSvg to read large svg files, you will be happy to know that the new version got some significant performance optimizations – some svg files can be read a few times faster.

There is also an improved support for reading svg patterns – the new versions now support linked patterns (patterns that have xlink:href set to another pattern).

There are also a few other improvements and fixes. See a full list here:


Though most of the development time in the company is spent for 3D libraries, you can see that the 2D libraries are still fully supported and will continue to get new updates in the future. For example, in early 2020 I plan to update ZoomPanel control so that it will also support .Net CORE 3.1 version and be available with NuGet.



.NET Core 3.1 support and many other new features for the 3D libraries available

by abenedik 12. December 2019 10:30

I am happy to inform you that new versions of Ab3d.PowerToys and Ab3d.DXEngine libraries have been published.

The new libraries bring many new features and improvements. But probably the most important is that both libraries now support .NET Core 3.1 (released on 3rd December) - see more: This version of .Net is a long-term supported (LTS) release. Therefore it is recommended to use that version instead of .NET Core 3.0.


Let's go back to the new features.

Probably the most interesting new feature is support for planar shadows. Shadows are very important to give the viewer a real sense of depth and distances between objects. Consider the following two images that show the differences.

Ducks lake sample showing difference between rendering shadows or not

Planar shadows sample showing difference between rendering shadows or not

The first image is showing a Ducks lake sample - there a VarianceShadowRenderingProvider is used to provide nice soft shadows that add a much more realistic feeling where it is very clearly seen that the ducks are actually swimming in the lake. In the right part of the image the ducks might also be floating in the air.

The image below is showing a new sample that uses a new PlanarShadowRenderingProvider. Again, in the part with shadows it is very easy to see the distance between the spheres and the plane. But in the right side without shadows this information is totally lost.

What are the differences between those two shadow rendering techniques?

The VarianceShadowRenderingProvider uses a variance shadow mapping algorithm that can render nice soft shadows with minimal artifacts (compared to some other shadow rendering techniques). The shadows can be rendered to all 3D objects.

In this algorithm, the whole 3D scene is rendered from the light's position into a special texture - a shadow map. The values in this texture do not represent object colors but float values that describe distances from the light. Because the shadow information for the whole 3D scene (not only for visible part) is written into one texture, the resolution of the shadow depends on the size of the shadow texture and the size of the 3D scene. Sometimes it is desirable to have a more blurry shadow. But other times, especially in technical applications, users want to have more precise shadows. To increase the shadow resolution, the shadow texture size needs to be increased (with ShadowMapSize property), or the size of the whole 3D scene needs to be decreased. Increasing the shadow map size can significantly reduce performance. Also, decreasing the size of the 3D scene is not always possible. So this shadow rendering is not ideal for all the cases (there is actually no such technique except ray tracing).

On the other hand, the planar shadow rendering always renders perfectly sharp shadows without any loss of details. But as its name suggests, the shadows can be rendered only to a 3D plane. This techinque is also faster to render. There the shadows are rendered with applying a shadow matrix transformation to all objects. This matrix flattens all the objects so that they have no height and become only 2D shapes that represent the shadows. Those shapes are then rendered as 3D objects on top of the 3D plane.

Disadvantages of planar shadows are that they can be rendered only to 3D planes, they cannot have soft edges, shadows are also rendered for objects behind the plane or point light, some objects that lie on the plane or are very close to the plane may get invalid shadow (too wide). But still, they are an excellent choice for many scenarios.

Anyway, you as a user now have more choice regarding the shadow rendering. What is more, the planar shadows can be also rendered with WPF 3D rendering and do not require Ab3d.DXEngine.

In this case the new PlanarShadowMeshCreator class from Ab3d.PowerToys can generate the 3D mesh that can be rendered as a planar shadow. This class can even clip the shadow to the edges of the 3D plane. But the mesh generation is 100% done on the CPU. And each time the light or the objects are changed, the whole shadow mesh needs to be regenerated. When the 3D scene is complex, this shadow mesh generation can present a performance problem. What is more, WPF 3D cannot render semi-transparent shadows correctly. The problem is that the shadow is darker and less transparent in the areas where multiple parts of the 3D objects are rendered. This means that with WPF 3D only opaque shadows can be correctly rendered. But still, it is possible to significantly improve the visual appearance of some 3D scenes by adding planar shadows without any transparency.

To correctly render the semi-transparent shadows and to avoid the slow 3D mesh generation on the CPU, it is possible to use the PlanarShadowRenderingProvider from Ab3d.DXEngine library. It provides full hardware acceleration for rendering planar shadows and uses the stencil buffer to clip the shadow to the edges of the plane and to prevent semi-transparent shadow artifacts (it ensures that each shadow pixel is rendered only once).


Another great new feature of the Ab3d.DXEngine library that was requested from some users is the ability to render 3D lines with different start and end colors. In this case, the line color is interpolated from the start to the end color. It is also possible to specify color's alpha values so that the line slowly fades away (its alpha value goes from 1 to 0). This is very useful for showing trails of moving 3D objects (for example orbits of planets). The following image shows a screenshot from a simple sample that demonstrates that new feature:

Rendering 3D lines with different start and end color

Ab3d.DXEngine can already render huge point clouds with hundreds of millions of points. To optimize rendering in such extreme cases, a OptimizedPointMesh can be used. This object can significantly reduce the number of points that need to be rendered. But until now all the points need to be in the same color. With the new version of Ab3d.DXEngine it is possible to specify a different color for each point.

The new version also improves the mouse rotation and movement when showing point clouds. This is done with new methods that return the 3D position that is closest to the mouse position. This way it is possible to use camera rotation around mouse position when showing point cloud data. Also, because the distance from the camera to the position under the mouse can be correctly calculated, the mouse movement is more precise.

The last new feature in Ab3d.DXEngine that I would like to mention here is that with the new version of the library it is possible to recover from rare cases when the DirectX device is removed or reset by the OS. This happens when the graphics driver is updated while the application is running. This can also happen in case when there is some problem with the driver (very rare). Note that this does not happen when the operating system is restored from sleep or hibernation or when the window is minimized and then opened again.

To handle the DirectX device removal, there is a new DeviceRemoved event in the DXScene class. In the event handler the application can save the current state of the 3D scene, then dispose the current DXViewportView and other 3D objects and finally create a new DXViewportView and recreate the 3D scene from the saved data. There is a simple sample that demonstrates that.


Regarding the new Ab3d.PowerToys library I would like to mention that now it works with a new Assimp library v5.0. This provides improved support for importing 3D models from many file formats. What is more, the Ab3d.PowerToys has improved skeletal (skinned) animation that can animate 3D objects with a more complex hierarchy of bones.

Another nice new feature is that the ViewCubeCameraController can now show different bitmaps for selected planes. This gives users a nice indication that they can click on the plane to rotate the camera to see the 3D scene from the selected angle.


And finally, I would like to mention two new samples that come with Ab3d.PowerToys.

The first one is called "Basic WPF 3D objects tutorial". I have seen many users that wanted to create an application with 3D graphics and just jumped in and started using the Ab3d.PowerToys library. They may be able to do some complicated things because some powerful features of the library are very easy to be used. But sometimes, when it comes to some relatively simple tasks, they are stuck because they do not know the basics of the WPF 3D objects. This new sample should help such users to be quickly back on track.

Another new sample is called "Standard WPF hit testing". The reasons why I wrote this sample are very similar to the reasons mentioned before. When it comes to 3D hit testing, many users thought that the only way to do that is to use the EventManager3D. The reason for that was that the samples that come with Ab3d.PowerToys were only showing the features of the library and therefore only the usage of EventManager3D was mentioned. So many users were not aware that there is also a low-level way to do the 3D hit testing. In this way, the user can get the closest or all the 3D objects that are behind some specified 2D position (for example mouse position). This approach is actually more useful and can be used in more cases, especially in situations when there are many possible hit objects and when the objects are dynamically added and removed. EventManger3D is more suited for simple 3D scenes where the number of 3D objects is low and does not change a lot.

As always, there are many other new features and improvements. For the full list of changes see the and


At this point, I would also like to tell you something about an exciting new feature that is already in development and is planned for the next version. It is called "reused DirectX command lists". With technical 3D applications it is very usual that the 3D scene is mostly static and many times only the camera is changing. With DirectX 11 it is possible to render such 3D scenes extremely fast with almost no CPU overhead. This is done with recording a command list that contains all the DirectX commands that are required to render one 3D scene. After the command list is generated, we can reuse it for other frames. So if only the camera is changed, then we just send new camera information to the graphics card and then instruct it to render the same command list as before. This can be done with almost no CPU time spent. The results are stunning. See the following screenshot:

Stunning performance with reusing DirectX commands list

The arrow is pointing to the area that is showing the CPU time to render the scene. In this case, the CPU time to render 160.000 individual boxes (without using instancing but with creating one draw call for each object) is only 0.10 ms. Now compare that with what is possible to achieve with standard rendering process and with full multi-threading - see the screenshot from

There you can see that the CPU time to render the scene is almost 15 ms. This is still an incredible achievement, but compared to 0.10 ms it is a lot.

There are some complex challenges that need to be solved before reused command lists can be used in a generic purpose rendering engine as Ab3d.DXEngine is. As you can see, a special demo version is already running. A more generic version will be ready for the next release, so stay tuned.


As it was already announced in the previous blog post, the new versions of Ab3d.PowerToys and Ab3d.DXEngine are available through multiple sources:

  • NuGet packages ( and This distribution includes assemblies for .NET Framework 4.0 and 4.5+ and for .NET Core 3.1. The same dll (assembly) is used for both evaluation and commercial usage. By default, the evaluation license is started. The commercial license can be activated with calling the SetLicense method and providing the license information. In the near future, it will be possible to get the license parameters from the Users Account web page. Until then, please contact us for the parameters.
  • The commercial version installer can be downloaded from the User Account web page. Because the old licensing system that uses license.licx files cannot be used in .NET Core, this distribution contains only assemblies for .NET Framework 4.0 and 4.5+.
  • The evaluation installer can be downloaded from Downloads web page - Also contains only assemblies for .NET Framework 4.0 and 4.5+.

Tags: , , , , , , ,

Ab3d.PowerToys | DXEngine

New .NET Core 3, NuGet and GitHub support

by abenedik 22. October 2019 16:17

I am pleased to inform you that some significant changes to our libraries have happened.

Everything started with the announcement that .NET Core 3 will support WPF and WinForms application. That meant that Microsoft would finally upgrade its frameworks that are used to create most of the desktop applications.

My first port to the beta version of the .NET Core 3 was very promising and it looked like that it will be easy to provide day-zero support for the new framework. But when the release day approached and when some additional tests were done, then some problems begin to emerge. Though the main functionality of the Ab3d.PowerToys and Ab3d.DXEngine libraries was ported without any problems, the existing licensing mechanism did not work with the new compiler. 

Our libraries use the standard .Net licensing mechanism that use license.licx files - in case when this file is present, the .Net compiler calls the licensing code inside the library during the compilation of the project. The licensing code can generate a run-time license key that is embedded into the project. This then allows to run the project on cumputers where the library is not installed. The problem was that the compiler for .NET Core 3 did not call the licensing code. This meant that it was not possible to use the existing licensing mechanism to provide commercial licenses. What is more, some tools (obfuscator) also did not fully support .NET Core 3 assemblies at the time of the release.

Therefore a new licensing mechanism was needed. Besides the support for .NET Core 3, one of the main goals of the new licensing was also to allow distribution with NuGet (without private repositories). This required that a single dll should be used for the evaluation and for the commercial version.

If you have checked our web site recently, you may have noticed that it was already possible to download beta and release candidate versions of the Ab3d.PowerToys and Abd3.DXEngine. The new libraries support .NET Core 3 and have a new licensing mechanism. And today I am announcing that final versions of both libraries were released on NuGet.

Let me quickly describe the new licensing mechanism. It is super easy to use. When the library is used for the first time, a "Start evaluation" dialog is shown. This allows the user to start a 60-day evaluation of the library. In evaluation mode, all the features of the library can be used. The differences between running in evaluation and commercial mode are that in evaluation mode sometimes an evaluation watermark is shown and a dialog to show remaining evaluation days is shown once per day.

To activate a commercial version of the library, you do not need to change the dll, but you simply need to call a SetLicense method and pass a company name, license type and license text as parameters. For example, to activate Ab3d.PowerToys library, you need to add the following line to your project (it should be called before any Ab3d.PowerToys code is used):

Ab3d.Licensing.PowerToys.LicenseHelper.SetLicense(licenseOwner: "[CompanyName]",
                                                  licenseType: "[LicenseType]",
                                                  license: "[LicenseText]");


The same method can also be used to extend the evaluation period.

Note that the license text is not the same as the license key that was used until now. The difference is that the license text also need to include information until when the updates for the library are available. This is needed because everybody has access to the latest version of the libraries. So the licensing code needs to prevent using a commercial version that was released after the updates subscription has expired. Unfortunately, this will require the change of the license text after each license renewal. But on the other hand, the licensing code is cleaner and the distribution of the dlls is much simpler and done in a much more common way for the .Net ecosystem.

Of course, the current way of distributing evaluation and commercial versions with windows installer will still be available and fully supported in the future.

One of the advantages of using windows installer was that with the dlls it was also possible to install the sample projects for the libraries. This is not possible with NuGet distribution.

Again, there is a more conventional way in the .Net ecosystem to distribute sample projects. It is GitHub. So, when a NuGet package is installed with the Nuget Package Manager, a readme file is displayed. And the readme file shows the user a link to GitHub repositories with sample projects.

Currently, the following two repositories are available (contain solutions for standard .NET framework and for Core 3):


I am planning to add more repositories in the future.

I am also planning to add NuGet support for Ab2d.ReaderSvg, Ab2d.ReaderWmf and Ab3d.Reader3ds libraries.


Now each version of the library comes with many different variants - commercial, NuGet, core 3, etc. How do you know which one is which? This can be read from the revision number. If it is below 1000, then it is an evaluation version that was installed with windows installer; if it is between 1000 and 2000 then it is a commercial version that was installed with windows installer; if it is above 2000 then it has universal licensing and is distributed through NuGet. Also, the framework version is encoded into the revision - the last 3 digits tell you: if they are 35, then the library is compiled with .Net 3.5; 40 means it is compiled with .Net 4.0; 45 means .Net 4.5 and 300 means .NET Core 3.


Let me finish with the following question: should a WPF project be ported to .NET Core 3?

Here I would agree with Microsoft's recommendation: if your project is already completed and require only minimal maintenance, then leave it on a standard .Net framework. If the project is still heavily under development, then it is worth considering to migrate to .NET Core 3 for one of the next releases of your project. If you are starting a new WPF project, then it is recommended to use .NET Core 3.

Tags: , , , , , , ,

Ab3d.PowerToys | DXEngine

New major version of Ab3d.PowerToys released

by abenedik 26. June 2019 11:20

A new major version of the Ab3d.PowerToys library has been released!

The new version brings many new features, significantly improves performance in some cases and also fixes a few issues.

I am sure that most of you will find your own favorite feature or improvement in this version. For me, the most important addition is a new ModelScalarVisual3D class.

The ModelScalarVisual3D is a control that provides a simple way for the user to scale a selected 3D model - it is a usual control in almost all 3D modeling applications. This way the Ab3d.PowerToys library provides all three standard transformation controls: translation (with ModelMoverVisual3D), rotation (with ModelRotatorVisual3D) and scale (with ModelScalarVisual3D). There is also a new "Ducks lake" sample that demonstrates the usage of all three:

Ducks lake sample with translate, rotate and scale transformation controls

Another very nice new feature that I really like is support for rendering 3D streamlines. 3D streamlines are 3D lines that represent a flow of water or air with different colors. Streamlines are used many times to show simulation results or show sensor data. With Ab3d.PowerToys library they can be shown with an updated TubePathMesh3D class. The class is created with a collection of 3D positions that define the tube positions. With the new version, it is now possible to also specify texture coordinates for each tube path position. This way it is possible to assign a texture with a color gradient to the TubePath and use the texture coordinates to specify which color should be shown for each tube path position.

3D streamlines samples created with textured tube lines

TubePath always shows a cylindrical tube along the specified path. But if you want to show some other shape along a path, then you can use an updated CreateExtrudedMeshGeometry method (in Ab3d.Meshes.Mesh3DFactory namespace). Previously it was possible to extrude a 2D shape into a 3D object only by providing a single 3D vector. Now you can provide a list of 3D positions and the new method will extrude the 2D shape along the provided positions.

Extrude a custom 2D shape along a 3D path

Many of you have already tried to create a custom 3D mesh with defining custom positions, triangle indices and texture coordinates. The "best friend" for this task is a piece of paper and a pencil. This way you can draw the 3D object schema to a paper and then number the positions. This makes it much easier to see the position indexes that will form the object triangles. For those users, the new version of Ab3d.PowerToys is introducing a new "best friend": MeshInspectorOverlay control. It is a control that is derived from Canvas and can show position indexes, triangle indexes and orientation of positions in each triangle. You just add the MeshInspectorOverlay control to your visual tree (it should be added after the Viewport3D control and should occupy the same space), then assign MeshGeometry3D and Camera properties and after that the mesh details will be written on top of the 3D object. 

If you are interested in MeshInspectorOverlay then I would like to remind you about the Ab3d.Utilities.Dumper class. This class defines many methods that can be used at design time in Visual Studio Immediate window to show many details about objects used in 3D scene. For example, its Dump method can show many details about a MeshGeometry3D, Model3D or Matrix3D. That method is also defined as an extension method on those classes. There is also a DumpHierarchy extension method that can be used on Model3D, Visual3D or even Viewport3D. Try them.

Most of the samples under "Objects 3D" have been updated and can now show 3D model details with using the MeshInspectorOverlay. Here is a screenshot of MeshInspectorOverlay sample that also shows many of its properties:

MeshInspectorOverlay shows position indexes, triangle indexes and orienations of triangles

There are also some other nice new features. But let me now describe some of the performance improvements.

If you are using Boolean operations, then you will be happy to learn that this part of the library has been significantly improved. Boolean operations require a generation of Constructive solid geometry (CSG) objects where polygons in one CSG object are split based on the polygons in another CSG object. This process can create an insane amount of objects. Optimizing the creation of objects in the latest version has significantly improved the performance. What is more, if you are doing multiple Boolean operations on a single 3D object, you can now preserve the internal CSG object between all the operations (before new CGS was created each time). This can provide an even bigger speed-up. But, please do not be too excited, Boolean operations are still very complex and slow operations.

Another significant performance improvement has been done to improve getting the 3D line that is the closest to the mouse position. If you are using only Ab3d.PowerToys and WPF to render 3D lines, then this is not very relevant because showing many 3D lines in such a scenario is much more limiting that getting the closest line. But when using Ab3d.DXEngine, it is possible to show hundreds of thousands of 3D lines and in such extreme scenarios, it is essential that the code that gets the closest 3D line is fully optimized. This was achieved with heavy inlining and reordering of the code in the critical path. What is more, the methods in the LineSelectorData class have been updated in such a way that now it is possible to call them in multiple threads (for example with using Parallel.For). This way you can achieve massive performance gains.

The code in LineSelectorData was also updated to correctly handle the cases when 3D lines cross the camera's near plane (line goes behind the camera). In this case, the closest line was not always correctly calculated. Because this requires special handling of the 3D line, there is also a new Line3DTo2D method on the camera class (besides the Point3DTo2D and Rect3DTo2D methods).

There are also some other fixes available. To get the full list of new features and changes see the Ab3d.PowerToys versions history.



New version of Ab3d.PowerToys and Ab3d.DXEngine with multi-threaded rendering

by abenedik 20. February 2019 16:10

I am very happy to inform you that new versions of our 3D libraries have been published.

The greatest new feature of this release is that the Ab3d.DXEngine now supports multi-threaded rendering. This can provide an amazing performance boost - in some cases, the time required to render one frame has been reduced by more than 4 times = 400% improvement.

This version also adds support for showing object outlines and provides a few improvements and additional options for rendering instanced objects. It also fixes a few bugs, especially with some hit testing use cases.

The main focus of the new Ab3d.PowerToys library version is on improved camera controller. This should prevent problems with mouse rotation and movement when using custom rotation or zoom position. There is also a new QuickZoom zooming mode that provides a very fast and precise zooming option for the user.

Let me first provide some additional details about the new multi-threading capabilities. The following graph shows the total time that is needed to render one frame where the number of used background threads is shown on the x axis:

Ab3d.DXEngine multi-threading performance improvements graph

The data was created by the new benchmark test that is now part of the Ab3d.DXEngine samples. It shows the rendering 160.000 (!!!) boxes without using instancing (each is defined by its own SceneNode object). The test was executed on Intel i7 6700K CPU (4 cores with hyperthreading) and NVIDIA 1080 GTX graphics card. As you can see the new multi-threading capabilities can provide 4 times the performance of a single threaded rendering. It is also incredible that now it is possible to render so many individual objects with almost 60 FPS (55 FPS in this test).

When describing the results I need to tell that those results were achieved with using DirectXOverlay PresentationType. This means that the 3D scene is rendered on top of the WPF content - in this case the graphics card can render the scene in the background and when the rendering is completed it can show the rendered image. This means that the Ab3d.DXEngine does not need to wait for the graphics card to finish rendering. On the other hand, when DirectXImage is used as a PresentationType, the 3D scene is composed with other WPF objects (other WPF objects can be seen through the scene and other WPF objects can be shown on top of the 3D scene). But for this to work, the Ab3d.DXEngine needs to wait until the graphics card finishes rendering the scene and this significantly increases the total rendering time. In case of using multi-threading this means that Ab3d.DXEngine can issue all the DirectX state changes and draw calls much faster compared to a single threaded rendering. But this also means that the time to wait for the graphics card to finish rendering increases significantly. Therefore the performance improvements are not as great as with DirectXOverlay, but still, the scene with 160.000 boxes can be rendered almost 3 times faster - see graph:

Ab3d.DXEngine multi-threading performance improvements graph

So, if you are rendering complex 3D scenes with many objects, you can expect great performance gains just with upgrading to a new Ab3d.DXEngine version. What is more, when rendering many 3D objects the CPU is usually the bottleneck of the whole process. But with greatly increasing throughput of the CPU, the graphics card can become the bottleneck. And because the performance of the graphics cards increases significantly with each new graphics card version, it is possible to further improve the performance with upgrading the graphics card (upgrading CPU to a new version usually do not provide such benefits).

Note that multi-threading only helps when the scene contains many 3D objects - in this case many DirectX commands needs to be executed. When you are rendering only a smaller number of objects but that objects are very complex with a lot of triangles or when you are using object instancing to render many 3D objects, then the new multi-threading will not have any significant effect.

It is also worth mentioning that increasing the number of used CPU cores does not improve performance indefinitely. The tests have shown that for most use cases it is not worth using more the 8 cores. Therefore the Ab3d.DXEngine initially uses all the cores but not more than 8. This value is defined by DXScene.MaxBackgroundThreadsCount property (note that it counts only the background threads so value 7 means that 8 cores will be used: 1 main thread + 7 background threads).

To get more information about multi-threading in Ab3D.DXEngine you can read the online help for MaxBackgroundThreadsCount.


This new version also provides some improvements and additional options for rendering instanced objects. The most useful new option is to render the same instance data (same DirectX instance buffer) with using different InstancedMeshGeometry3DNode objects and providing different StartInstanceIndex and InstancesCount values for each InstancedMeshGeometry3DNode object. This way it is possible to hide multiple parts of the instanced objects without changing the instance buffer (which is a costly operation). A new sample that demonstrates that also shows how to override the color of the shown instances - this can be useful for showing selected objects with different color again without changing the instances data.

Let me also provide a few additional details about the new possibility to show object outlines. The following screenshot will illustrate what this means:

Ab3d.DXEngine with object oulines

As you see the new outlines can be used to provide great visual feedback to the user about the selected objects. The trick is that the outlines are visible through other 3D objects. To provide support for that, the Ab3d.DXEngine comes with a new ExpandPostProcess and a new sample that demonstrates how to alter the rendering process to render the object outlines.

The new version of Ab3d.DXEngine also adds support for showing object edges with using a sobel algorithm ( The following screenshot shows an example of that:

Ab3d.DXEngine with sobel edge detection post process


There are also some other very important improvements and fixes. For a full list of changes see the history web page:

Ab3d.DXEngine versions history

Ab3d.PowerToys versions history


In this version of Ab3d.PowerToys I also wanted to update the version of the third-party Assimp importer (imports 3D objects from many file formats). Because the official release is from December 2017 I went to GitHub and get the latest source. I compiled the source into native libraries. But after doing some tests I have found out that some of the 3D files were not imported correctly. Therefore I did not publish the new version. So this release comes with the official version (from December 2017) and also with a newer version that was published with the previous version with Ab3d.PowerToys (from May 2018).

Finally, I would like to say that I am following the .Net framework development news with great interest. Especially the part that with .Net Core 3 it will be possible to build WPF and WinForms apps. I have already tried to compile the Ab3d.PowerToys and Ab3d.DXEngine libraries with the preview version of the .Net Core 3 and they have both compiled fine and also run very well. This means that when an official version of .Net Core 3 will be released it will be also possible to get both Ab3d.PowerToys and Ab3d.DXEngine libraries compiled for that framework.

Tags: , , , ,

Ab3d.PowerToys | DXEngine

Major update of Ab2d.ReaderSvg brings better support for css styles and more

by abenedik 6. November 2018 17:00

I am happy to inform you that a new major version of Ab2d.ReaderSvg was just published.

The new version has a significantly better support for reading css styles. The new version of the Ab2d.ReaderSvg can now correctly read a css text with multiple class name definitions in one line. Also adding additional properties to already defined class names is now supported. Those two features are required to correctly read the following css definition:

.A, .B { fill: green; } 

.A { stroke: green; }

This update should greatly improve reading css styles from svg files. But because css styles can be incredibly complex, there are still cases that are not supported. Luckily, the main tools that can save to svg files usually do not use such complex css styles and therefore Ab2d.ReaderSvg should be able to read almost all the files.


An important new feature is also that ReaderSvg class now has two new delegates: BeforeWpfObjectCreatedCallback and AfterWpfObjectCreatedCallback. The first delegate is called before ReaderSvg creates a WPF object from the svg element. The delegate gets the xml text that is used to define the element. It can be used to create your own WPF object from the xml and pass that back to ReaderSvg. The other delegate is called after the WPF object is created by ReaderSvg. It gets the created WPF object and the xml text. This delegate can be used to read some additional properties from the xml and decorate or change the already created WPF object.

There are also some other improvements and fixes. The whole list can be seen on ReaderSvg versions history web page.


This shows that though the main focus of the AB4D company is on developing components for 3D visualization, the 2D tools and importers are still fully supported - most of the updates are based on the great feedback from the customers. So, if you get a svg file that is not correctly imported or you have a good feature request, please send me the svg file or a feature request.