.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: https://devblogs.microsoft.com/dotnet/announcing-net-core-3-1/. 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 https://www.ab4d.com/DXEngine-history.aspx and https://www.ab4d.com/PowerToys-history.aspx.

 

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 https://www.ab4d.com/images/DXEngineGallery/DXEngine-Multi-threaded-rendering.png

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 (https://www.nuget.org/packages/Ab3d.PowerToys/ and https://www.nuget.org/packages/Ab3d.DXEngine/). 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 - https://www.ab4d.com/Downloads.aspx. 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):

https://github.com/ab4d/Ab3d.PowerToys.Wpf.Samples

https://github.com/ab4d/Ab3d.DXEngine.Wpf.Samples

 

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 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 (https://en.wikipedia.org/wiki/Sobel_operator). 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

A critical update for Ab3d.DXEngine and a minor hotfix for Ab3d.PowerToys published

by abenedik 17. October 2018 17:07

I would like to inform you that a critical update for Ab3d.DXEngine and a minor hotfix for Ab3d.PowerToys has been published.

The critical problem that occurred in the previous version was that on high DPI settings the new hit testing did not work in all use cases. If a user was using the new hit testing it may appear that the mouse was offset by some amount. This is now fixed. If you were using the previous version 3.0., then please update the library to the version 3.1.

The Ab3d.DXEngine also comes with a few other improvements and new features. One of them allows using a texture when rendering instanced objects. When using textures with transparency, do not forget to set the UseAlphaBlend property on the InstancedMeshGeometryVisual3D to true. Also, in the case of rendering semi-transparent instances, they need to be sorted so that those farther away from the camera are rendered first (are defined first in the InstancesData array).

The other new feature is that MeshObjectNode can now render meshes with multiple SubMeshes defined. This means that you can create one giant vertex buffer and one index buffer and then use SubMeshes to define which triangles in those two buffers will be rendered with which material. This provides an optimal way for the graphics card to render objects. What is more, it is very easy and super fast (almost at no cost) to change which triangles use which material or to change a material.

This was already used by the DXEngine when a frozen Model3DGroup was rendered - in this case DXEngine combined all the meshes into one single vertex and index buffer and then defined SubMeshes for each used material. Now, this can be also achieved manually with using MeshObjectNode and SubMeshes. 

There are two new samples that demonstrate that. One shows a simple animation that changes SubMesh properties. The other new sample shows an efficient way of selecting a part of a mesh with changing its color. Usually, this is done with moving the selected triangles from the original mesh into a new mesh. The new mesh is then shown with the selected material. For complex meshes this is very inefficient. When using SubMeshes the same effect can be achieved with almost no performance cost. 

Efficient material animation with using SubMeshes

 

There is also a new sample that shows how to efficiently create huge height maps. The easiest way to show height maps is to use HeightMapVisual3D object from Ab3d.PowerToys library. But when creating huge height maps, this approach is very inefficient because it requires a lot of memory and takes long time to initialize (first MeshGeometry3D is created for WPF 3D objects and then this is converted into DirectX buffers). The new sample shows how to directly create DirectX buffers and then show the height map with created buffers.

This shows that Ab3d.DXEngine is build to provide great support for the most demanding and complex DirectX use cases. And all that power can be used from the .Net application.

The full list of changes can be found in DXEngine versions history page.

 

As mentioned before, the Ab3d.PowerToys also got a minor hotfix. This fixes two issues. The first one was that in case of using OrthographicCamera and negative NearPlaneDistance value, then some 3D lines may not be rendered. Another fix improves the FitIntoView method when there are no WPF 3D objects in the scene (there are only DXEngine SceneNodes objects).

What is more, the new version of Ab3d.PowerToys comes with an improved SceneEditor sample. The new version of the sample shows how to create a simple 3D scene editor where the user can create 3D boxes and spheres, move them around and edit their positions. The following image shows a screenshot from that sample:

SceneEditor sample

If you are using OrthographicCamera and are manually setting the NearPlaneDistance, then it is recommended to update to the latest version v8.2.6863.

Tags: , , , ,

Ab3d.PowerToys | DXEngine

PBR support and many other new features in new versions of Ab3d.DXEngine and Ab3d.PowerToys

by abenedik 29. August 2018 22:48

I am very excited to finally release a new major version of the Ab3d.DXEngine library and a new big release of the Ab3d.PowerToys library.

The list of major new features includes support for Physically Based Rendering (PBR), significantly improved hit-testing, better shadow rendering and many other performance and usability improvements. The new version also uses the latest version of SharpDX (v4.2).

The following image is showing the new Physically Based Rendering in action:

Pistol model rendered with PBR material with Ab3d.DXEngine

Standard materials define diffuse color, specular color and specular power.   In most cases this allows rendering quite realistic 3D scenes. But because this lighting model is using many simplifications it cannot provide a very realistic rendering. To solve that, some bright minds dug into the lighting physics and based on what is really going on a Physically Based Rendering (PBR) was "born". In this lighting model the major two properties that define how material is shown are metalness and roughness. Metalness distinguishes between metallic and non-metallic objects. This has the major effect on how much light is reflected and how much is absorbed and returned as diffuse light. Roughness defines how clearly the environment is reflected and how big and bright the specular shiness is.

In PBR it is possible to use textures to define different metalness and roughness values for different parts of the model. This can be nicely seen in the image above where the wooden parts or the pistol are rendered differently from the metallic parts because they have different metalness values.

The following image shows sample models with different metalness and roughness values:

models with different metalness and roughness values

Besides metalness and roughness, the PhysicallyBasedMaterial in Ab3d.DXEngine also supports base color (diffuse color), emissive map, ambient occlusion map and normal map (also called bump map).

Another great new feature of the new version of Ab3d.DXEngine is much better support for hit testing. Hit testing is used for all the interactions of the mouse or touch with the 3D objects. In hit testing, a ray is created from the mouse or touch position and then the ray is checked against the 3D scene and the hit objects are returned. In previous versions of the library all the hit testing was done by using hit testing build into WPF. This worked well in most cases. But it was not able to use it for optimized SceneNode objects that were not created from WPF objects because those objects were not "visible" from WPF. Also, hit testing on instanced objects required that WPF 3D objects were created for each instance. This greatly increased initialization time and memory usage.

The new version of Ab3d.DXEngine how includes its own hit testing code that supports all types of SceneNode objects. What is more, the new code works much faster than the hit testing code in WPF. It can do hit testing on instanced objects without creating 3D objects for each instance. When hit testing a mesh, each triangle in the mesh needs to be tested against the 3D ray. Because some meshes can have hundreds of thousands of triangles, this can take some time. But the new Ab3d.DXEngine can also very efficiently hit test such meshes. In that case an oct-tree structure (https://en.wikipedia.org/wiki/Octree) is used to group the triangles in the mesh into small nodes. This way only a fraction of the total number of triangles needs to be checked. This provides enormous performance benefits. The following screenshot shows how oct-tree is used to divide a teapot object:

Teapot divided by oct-tree structure

Another significant performance improvement is related to the use of the IsVisible property. This property is defined by all the objects that are derived from the BaseVisual3D objects from Ab3d.PowerToys library. This includes most of the Visual3D objects (BoxVisual3D, SphereVisual3D, ect.), all 3D line Visual3D and some other objects.

When you want to hide an object, it is very convenient to just set IsVisible to false. To show the object again, you can just set IsVisible back to true. What happened behind the scenes was that the object that was hidden was removed from the 3D scene. When IsVisible was set back to true, the object was added back to the 3D scene. This meant that when complex objects were hidden and shown, all the DirectX resources were disposed and then created again. So this quite common operation was not as fluent as it should be.

The new version of Ab3d.DXEngine greatly improves that because now setting the IsVisible property to false does not change the 3D scene but just marks the object to be skipped when rendered. This way hiding and showing an object is now an instantaneous action.

To provide advanced IsVisible processing to any Model3D object and not only objects derived from BaseVisual3D, the new Ab3d.PowerToys library provides a new ContentVisual3D object. For example, ContentVisual3D can be used to show or hide a 3D object that is read from a file (usually defined with a Model3DGroup).

The new IsVisible processing also has a disadvantage that I need to mention here. Because the 3D scene is not changed when IsVisible is set to false, this means that DXEngine will not render the object, but it will be still present in the WPF 3D objects tree. Therefore, if you are using WPF hit testing, you might get a hit result on an object that is actually not shown. The easiest way to solve that is to use hit testing from DXEngine. You can also filter the hit objects by checking if they are derived from BaseVisual3D and then checking the value of IsVisible property. It is also possible to disable the new IsVisible processing.

If you are using PixelsVisual3D to render many pixels, you will be happy to hear that now it is possible to specify a different color and a different size for each of the pixels. Also, pixels can be quickly hidden with setting pixel's alpha color value to 0 or size to 0.

Another bigger change with DXEngine is that the SharpDX library that is used as a managed DirectX wrapper has been updated from v4.0.1 to v4.2. This means that you will need to update this library. You can get the new version from NuGet or from the same folder as the DXEngine library.

Among other new things there are also a few new very interesting samples. One of them is demonstrating how to very efficiently use object instancing to animate many objects. The following screenshot is showing a real-time animation of one million (!) 3D arrows that runs at 60 fps:

Animating 1 million 3D arrows with instancing in Ab3d.DXEngine

Another screenshot shows the same sample with less arrow and a different camera angle:

Animating 3D arrows with instancing in Ab3d.DXEngine

The trick to doing such an animation is to construct the correct transformation matrix (instance's world matrix) that transforms the 3D arrow mesh so that it points in the correct direction.  Because this may not be very easy to understand, there is another new sample that teaches you step by step how to create such matrices - here is a screenshot from that sample:

Instancing matrices guide

This knowledge is very important for performance because it teaches you how to use instancing for scenarios that you may not think of. And using instancing instead of many simple objects is in many cases the most beneficial performance improvement that you can do.

Because there are many WinForms users of Ab3d.DXEngine, I have updated the WinForms samples project and added code that shows new efficient ways to use the rendering engine. The samples also got new code comments.

 

So far I have been mostly wringing about Ab3d.DXEngine. But also the Ab3d.PowerToys library got tons of new features and capabilities.

One of the most important new one is that the library now comes with the new version of Assimp importer (http://www.assimp.org or https://github.com/assimp/assimp). This means that many new file formats are supported - the new list of supported file formats that can be imported is really long: .3d, .3ds, .3mf, .ac, .ac3d, .acc, .amf, .ase, .ask, .assbin, .b3d, .blend, .bvh, .cob, .csm, .dae, .dxf, .enff, .fbx, .glb, .gltf, .hmp, .ifc, .ifczip, .irr, .irrmesh, .lwo, .lws, .lxo, .md2, .md3, .md5anim, .md5camera, .md5mesh, .mdc, .mdl, .mesh, .mesh.xml, .mot, .ms3d, .ndo, .nff, .obj, .off, .ogex, .pk3, .ply, .pmx, .prj, .q3o, .q3s, .raw, .scn, .sib, .smd, .stl, .stp, .ter, .uc, .vta, .x, .x3d, .x3db, .xgl, .xml, .zgl.

Also, the list of file formats you can export to has been extended significantly. You can now export to the following file formats: dae, x, stp, obj, obj, stl, stl, ply, ply, 3ds, gltf, glb, gltf, glb, assbin, assxml, x3d, fbx, fbx, 3mf.

If you were already using Assimp importer and would like to switch to a new version, note that the new version has different native libraries requirements. See the comments in the samples or the Ab3d.PowerToys.Assimp.chm help file for more info.

There are also many other features or improvements. For example, if you were using WireGridVisual3D to show a wire grid, you will be happy to hear that now it is possible to define different major and minor grid lines. This makes the grid much nicer and required a minimal change in the code.

 

To get a full list of changes, see the Ab3d.PowerToys versions history web page.

Also, check the Ab3d.DXEngine versions history.

Commercial users can get the new version from their User Account web page. Others can download the new evaluation version. The best way to know more about the new features is to check the new samples projects. As always, the new samples are marked with NEW icon and the samples that are significantly updated with UP icon.

 

Let me finish with a few words about my future plans. 

One of the things that I would like to implement as soon as possible is to create a special version of the dll that could be distributed through NuGet and would provide evaluation and commercial version. This would also allow me to move the samples to the GitHub.

I also have a few ideas on how to provide some solutions to improve performance in some commonly used scenarios. I also want to update the support for Oculus Rift (also with help from some customer provide support for Avatars) and add support for OpenVR. And there are many other great new things waiting on my todo list.

 

So stay tuned...

Tags: , , , ,

Ab3d.PowerToys | DXEngine

Ab3d.DXEngine hotfix published

by abenedik 22. December 2017 11:02

I would like to inform you that a hotfix for Ab3d.DXEngine has been published.

This hotfix fixes a few issues that are mostly related to the DPI scale. This is the list of fixes:

  1. Fixed using actual system DPI scale in DXViewportView.
  2. Fixed using DPI scale when rendering hardware accelerated PolyLines.
  3. Improved using dpi values in RenderToBitmap method.
  4. Fixed using Attenuation values when using PointLight.

 

1)

The first issue is that the DXViewportView did not use the actual system scale factor (used for high DPI monitors).

For example, when a user set system scale factor to 200% (192 DPI), then WPF scales all its elements accordingly. This means that a Rectangle with size 800 x 600 is actually rendered to 1600 x 1200 pixels. The Ab3d.DXEngine did not automatically set the dpi scale so by default the 3D scene was rendered to 800 x 600 pixels and then WPF scaled the rendered scene to 1600 x 1200 pixels.

It was possible to solve this with manually set the DpiScaleX and DpiScaleY properties on DXViewportView.

The new version improves that so that the DpiScaleX and DpiScaleY properties are automatically set from the actual system dpi values.

 

2)

The second issue is also related to DPI scale settings. The problem was that the thickness of the hardware accelerated 3D polylines (introduced in the Ab3d.DXEngine 2.3) was not increased when the DPI scale was bigger than 1.

This means that on high DPI monitors the polylines (also 3D text lines) appear too thin. What is more, when simple disconnected lines and connected polylines are rendered on the same 3D scene, the thickness of the disconnected lines will be correctly increased, but the thickness of the polylines will not be increased by the dpi scale.

 

This problem is solved in this hotfix.

 

3)

The third issue that is solved is that dpi values in RenderToBitmap method are now correctly used.

 

4)

The last issue that is solved in this hotfix is that PointLight Attenuation values are now correctly used in the shader. The Attenuation values can be used to specify how the light strength is decreased with the distance from the light.

 

Those fixes should make the engine run well on high DPI monitors.

To conclude, I would really like to wish you a Merry Christmas, all the best in the new year and that you will create amazing applications with great 3D graphics.

Tags: , , ,

DXEngine

New version of Ab3d.DXEngine and Ab3d.PowerToys bring support for normal mapping and many other great new features

by abenedik 6. December 2017 23:26

I am happy to inform you that a great new update of main 3D libraries is available.

This time most work was done to improve the Ab3d.DXEngine - DirectX rendering engine.

 

The highlights of the new version are:

  • Added support for normal mapping (also called bump mapping).
  • Added rendering 3D lines with patterns (enables rendering of dashed and dotted 3D lines).
  • Improved texture loading with support for loading DDS files.
  • Improved Assimp importer that can now also read and play keyframe and skinned animations from many 3D file formats (including fbx and dae).

 

DirectX 11 normal or bump mapping with DXEngine

Normal mapping is now supported with a new MultiMapMaterial class. This material defines a list of maps or textures where for each map its usage type is defined. This way it is possible to define a material with diffuse, normal, specular and also environment map. A drawback of the current version is that shadow rendering is not yet supported where rendering objects with MultiMapMaterial .

 

Dashed and dotted 3D lines with Abd3.DXEngine

3D lines rendering is greatly improved in this version of Ab3d.DXEngine. There is now a new ILinePattern interface that defines LinePattern, LinePatternScale and LinePatternOffset properties. This not only allows rendering dashed and dotted lines but with changing LinePatternOffset it also provides an option to animate the dashed lines - for example, to show a way or direction. Also, this version now supports full hardware acceleration of rendering connected 3D lines (polylines). This means that you do not need to use special properties to render connected 3D lines as disconnected 3D lines anymore.

 

What is more, both Ab3d.DXEngine and also Ab3d.PowerToys now have a new MitterLimit property that defines when a sharp line connection is turned into beveled (cut) line connection.

 

Skeletal animation with Ab3d.PowerToys

3D models can be read into your application with using Assimp importer library that can read data from almost any 3D file format. But until now only static models can be imported. The only way to play animations was to use Ab3d.Reader3ds library and play animations stored with 3ds files. But the new version of Ab3d.PowerToys.Assimp library supports reading keyframe and also skinned animations. There is also a new AssimpAnimationController that can play both keyframe and skinned animations. This way it is possible to read animations from almost any 3D file format that support storing animation data.

 

Optimized point cloud DirectX rendering with Ab3d.DXEngine

A lot of work was also dedicated to providing an efficient way of rendering many millions of pixels - the so-called point clouds. The new OptimizedPointMesh class can optimize rendering of huge point clouds in two ways. First, it can determine which parts of point cloud are visible to the camera. Second, on the visible parts it can check the following positions and if they would be rendered so close together that the distance on the screen would be less then one pixel, they are rendered only once as only one pixel. Those two optimizations can in most of the cases provide huge performance improvements (but still, investing in a high-end graphics card is the most efficient way to deliver substantial performance gains).

 

When 3D models with very detailed textures (for example 4096 x 4096) are loaded, the texture initialization can take quite a lot of time and memory. Most of the time and memory is used to create mipmaps of the texture. Those are required to get efficient color sampling on the graphics card. To improve this, modern 3D games use DDS texture formats. This file format is optimized for the graphic card and also alredy include mipmaps.

 

The new version of Ab3d.DXEngine provide a few easy ways to load DDS textures instead of standard png or other files. This can significantly improve load time.

 

There are also many other improvements and fixes. The following is the full list of changes:

Ab3d.DXEngine v2.3:

  • Implemented rendering materials with diffuse, normal (bump) and specular texture. Note: does not work yet with shadow rendering.
  • Added MultiMapMaterial that can be used to render material with diffuse, normal, specular and environment reflection texture.
  • Added DXAttributeType.MeshTangentArray that can be set to the MeshGeometry3D with SetDXAttribute extension method and allows attaching tangent array to MeshGeometry3D
  • Added Ab3d.DirectX.Utilities.MeshUtils.CalculateTangentVectors method (can be used calculate tangents on the CPU for objects that are rendered with normal / bump map)
  • Added support for rendering 3D lines with custom pattern. This allows rendering dashed and dotted lines (only for disconnected 3D lines; not for poly-lines):
  • Added ILinePattern interface with properties that define line pattern: LinePattern, LinePatternScale and LinePatternOffset.
  • Implemented ILinePattern with LineMaterial object.
  • Added LinePattern, LinePatternScale and LinePatternOffset to DXAttributeType. This way it is possible to specify line pattern parameters on LineVisual3D objects with using SetDXAttribute extension method.
  • Added support for rendering connected 3D lines (PolyLineVisual3D, etc.) with full hardware acceleration. Note that lines with arrows are not rendered with full hardware acceleration.
  • Changed default value of DXScene.RenderConnectedLinesAsDisconnectedLinesThicknessLimit from 3 to 0 - so connected lines that are thinner than 3 are not rendered as disconnected lines by default.
  • Added IPolyLine interface with IsPolyLine and MiterLimit properties.
  • Updated LineMaterial to implement IPolyLine interface.
  • Improved time and memory consumption when reading textures.
  • Added Ab3d.DirectX.TextureLoader.LoadShaderResourceView method that can be used to load textures from standard image files (png, jpg, tiff, gif, bmp) and from DDS files.
  • Added Ab3d.DirectX.TextureLoader.CreateShaderResourceView method that can create ShaderResourceView from texture stored in byte array (for cases when bitmap is read from a stream).
  • Added static bool LoadDdsIfAvailable field to WpfMaterial. When LoadDdsIfAvailable us true, then the texture loader will check if there is a DDS file with the same name but dds file extension. In this case the DDS file will be loaded. Using dds files can greatly improve required load time and memory usage.
  • Added static CreateTexture2D method to WpfMaterial that creates a ShaderResourceView from the specified WPF BitmapSource.
  • Created OptimizedPointMesh class that can be used to show point cloud and can dynamically reduce the number of rendered positions to improve rendering performance.
  • Make CalculateCameraPlanes on DXScene public. The method calcualates zNear and zFar values for the specified camera.
  • Added ParentNodeChanged and ResourcesInitialized events to SceneNode.
  • Added ForegroundRenderingQueue to DXScene. This is a new rendering queue that is rendered after GeometryRenderingQueue but before TransparentRenderingQueue.
  • Set default values of ReadZBuffer and WriteZBuffer properties on PixelMaterial to true.
  • Removed ScreenSpaceLineNode constructors that takes both isPolyLine and LineMaterial as parameters - IsPolyLine values is now provided only by LineMaterial parameter (when it implements the IPolyLine interface).
  • Added CustomRenderableNode and CustomRenderablePrimitive. Those two SceneNode classes simplify using custom rendering logic to render 3D objects with providing a callback method that is called to render the 3D object (used can call Draw calls on DirectX device in the callback method).
  • Added DXAttribute OnSceneNodeCreatedAction. Its value can be set to a callback method defined by an Action<SceneNode>. The callback method is called after a SceneNode is created from the WPF object.
  • Added DXAttribute OnDXResourcesInitializedAction. Its value can be set to a callback method defined by an Action<object>. The callback method is called after the specified DXEngine's resource is initialized and DirectX resource objects are created.
  • Fixed problems when color from PixelEffect is used to render 3D lines instead of the color defined in the LineColor property (and vice-versa).
  • Added dpiX and dpiY parameters to DXView.RenderToBitmap method (they default to 96 but can be changed by the user).

Breaking changes:

  • Renamed Ab3d.DirectX.ContexStatesManager class to Ab3d.DirectX.ContextStatesManager to fix spelling of the class.

Apart from samples that demonstrate new functionality the following samples are also added or improved:

  • Added BackgroundObjectsCreation sample that shows how it is possible to initialize 3D objects on the background thread so that when they are shown the UI thread is not blocked for a longer time.
  • Added Frustum culling sample. The sample shows how to determine which 3D objects are visible in the camera view. 
  • Improved WinForms sample to show how to use DXViewportView in WinForms with SharpDX.RenderForm. Using DXViewportView in WinForms application allows easy conversion of samples from Ab3d.DXEngine and Ab3d.PowerToys to WinForms application.

 

Ab3d.PowerToys v8.1

  • Added MiterLimit property to PolyLineVisual3D, MultiPolyLineVisual3D, RectangleVisual3D and LineArcVisual3D (all lines derived from BasePolyLineVisual3D). The MiterLimit value specifies when the mitered line joint is changed into beveled line joint.
  • Added support to read 3D lines from obj files with ReaderObj. Before lines can be read, the ReaderObj.ParentModelVisual3D property must be set. Lines color is get from material's diffuse color (or ReaderObj.DefaultMaterial). Line thickness is always set to 1.
  • Improved XInputCameraController when to continuously move up or down when the DPad buttons are pressed and when MoveVerticallyWithDPadButtons is true  (before user needed to release the button and press again)
  • Added support for ModelUIElement3D objects when calling ModelUtils.GetBounds and ModelIterator.IterateGeometryModel3DObjects methods
  • Added CurrentFrameNumber property to AnimationController
  • Changed type used for FrameNumber in animation classes from int to double.
  • Fixed Ab3d.Utilities.Dumper.GetMatrix3DText to correctly use the specified indentText and newlineText
  • Added static FormatMatricesHorizontally method to Ab3d.Utilities.Dumper class
  • Fixed Camera.GetMousePositionOnPlane method when using OrthographicCamera and when camera's Offset is not zero (Offset is changed when camera is moved).
  • Added a new constructor to Ab3d.Utilities.Plane class that takes a position on a plane and plane's normal.
  • Added GetClosestPointOnPlane method to Ab3d.Utilities.Plane class
  • Added GetPerspectiveScreenSize, GetOrthographicScreenSize, GetPerspectiveWorldSize and GetOrthographicWorldSize to Ab3d.Utilities.CameraUtils
  • Added GetWorldSize and GetScreenSize to BaseCamera
  • Added static bool ImmediatelyLoadTextureFiles field to MaterialTypeConverter to control how the BitmapImages are created (can prevent locking the read file because file is in use). See comments for the field for more info.
  • Line3DFactory.CreatePolyLine3D method was renamed into Line3DFactory.CreateMultiPolyLine3D for those overrides that takes a List of Point3DCollection objects
  • Added protected OnMouseMove, OnMouseButtonUp, OnMouseButtonDown and OnMouseWheel to MouseCameraController. This make it possible to use MouseCameraController in WinForms application (with SharpDX.RenderForm).
  • Improved performance of calling AlignWithCamera on TextBlockVisual3D

Breaking changes:

  • Changed Ab3d.Utilities.Plane class to use a more standard a*x + b*y + c*z + d = 0 equation instead of a*x + b*y + c*z = d. If you are creating Plane object with a, b, c and d parameters, then you will need to flip the sign of the d parameter.

Assimp:

  • Added support to read bones and skeleton information.
  • Added support to play keyframe and skeletal animation (use Ab3d.Assimp.AssimpAnimationController that is defined in Assimp folder in main Ab3d.PowerToys samples project).
  • Set name of the created WPF materials from names defined in the file. The material's name can be read with material.GetName extension method (defined in Ab3d namespace).
  • Added GetAssimpMeshForGeometryModel3D, GetWpfMaterialForAssimpMaterial and GetAssimpMaterialForWpfMaterial to AssimpWpfConverter.

Tags: , , , ,

Ab3d.PowerToys | DXEngine