Ab3d.DXEngine Users Guide
Initialization
DXEngine can run on a variety of computers: from high end gaming computers to servers running in virtual machines.
Obviously we cannot use the same rendering technique on all of the devices.
On high end computer we can use powerful graphics card and use all possible effects.
But when running on low end computer or in virtual machine we usually do not have a good graphics card and need to use WPF 3D or DirectX 11 software rendering (also called WARP - it is high speed software rendering that produces the same results as hardware rendering).
GraphicsProfile
To allow DXEngine to adapt to specific hardware, it is possible to use different GraphicsProfiles.
GraphicsProfile can be described as a collection of settings that define what type of rendering will be used (hardware accelerated, software, WPF 3D), which graphics adapter (graphics card) and what quality settings will be used (amount of antialiasing, texture sampling quality, shaders quality, etc).
When DXViewportView is being initialized, it uses the GraphicsProfiles array and tries to initialize the DXScene with the specified GraphicsProfiles.
If the first GraphicsProfile in the array cannot be used, then the next one is tried. If this one also fails, DXSceneView tries to use the next one. And so on.
Once the DXScene is initialized, the used GraphicsProfile is set to the UsedGraphicsProfile property.
By default the GraphicsProfiles array has the following values:
- GraphicsProfile.NormalQualityHardwareRendering
- GraphicsProfile.NormalQualitySoftwareRendering
- GraphicsProfile.Wpf3D
This means that by default, DXSceneView first tries to initialize DXScene with hardware graphics card (the first GraphicsProfile in the array).
If there is no graphics card available or it does not support the
required feature level (FeatureLevel 10 or higher), than DirectX 11 software rendering is used (the next GraphicsProfile in the array).
Software rendering can provide the same quality as hardware rendering (all the effects work the same) but its performance is much worse (but on a modest CPU it is surprisingly good - on CPU with many cores it can outperform hardware accelerated WPF 3D).
If software rendering also cannot be used (when DirectX 11 is not supported on the system - for example on Windows XP), than WPF 3D is used as last fallback.
GraphicsProfile class defines the following properties:
- DriverType - one of: DirectXHardware, DirectXSoftware or Wpf3D
- DefaultAdapter - can be set to specific adapter (graphic card) or left at null to use the default system adapter>
- ShaderQuality - one of: Low (per vertex lighting), Normal (per pixel lighting), High (currently the same as Normal)
- PreferedMultisampleCount - define anti-aliasing level
- TextureFiltering - define quality of textures
More details about each property can be read it the GraphicsProfile class reference.
The GraphicsProfile class already defines some of the most common GraphicProfiles: three for hardware rendering (high, normal and low quality settings), three for software rendering and one for WPF 3D.
It is possible to defined custom GraphicsProfile. Also, you can specify GraphicsProfile for specific adapter (graphics card) - for example:
var nVidiaCardProfile = new GraphicsProfile(GraphicsProfile.HighQualityHardwareRendering, nVidiaAdapter);
This uses setting from the HighQualityHardwareRendering GraphicsProfile, but forces using the specified nVidiaAdapter.
Initializing DXViewportView
You can customize the GraphicsProfiles array and fill it with your own list of GraphicsProfiles.
But you need to do that before the DXViewportView is initialized.
If you do not initialize DXViewportView manually, then you need to do that before the DXViewportView is loaded.
For example the following code forces using DirectX software rendering (DXViewportView is defined in XAML):
public Window1()
{
InitializeComponent();
MainViewportView.GraphicsProfiles = new GraphicsProfile[] { GraphicsProfile.NormalQualitySoftwareRendering };
}
The following can force WPF 3D rendering - useful to compare the same scene once rendered with DXEngine and the other time with WPF 3D:
MainViewportView.GraphicsProfiles = new GraphicsProfile[] { GraphicsProfile.Wpf3D };
When DXViewportView tries to initialize a GraphicsProfile and the initialization fails, the DXViewportView.GraphicsProfileRejected event is triggered.
User can subscribe to this event to get additional information why GraphicsProfile is rejected.
This can be used to inform user that for example software rendering will be used instead of hardware rendering because he does not have a required graphics card.
Another way to achieve the same result is to subscribe to DXSceneDeviceCreated event.
This event is triggered after the DirectX device has been initialized (or when WPF 3D rendering was initialized).
In the event handler the user can check the value of GraphicsProfile property to see which GraphicsProfile is being used.
Using Ab3d.DirectX.Client.Settings project
Ab3d.DirectX.Client.Settings project, that is available with full source code, can help you to work with GraphicsProfiles. The project supports the following features:
- SystemCapabilities class can help you check the graphic capabilities of the current system. You can also call the GetRecommendedGraphicsProfiles method that returns an array of the recommended GraphicProfiles for the current system.
- GraphicsProfileSerializer can be used to serialize and deserialize GraphicsProfile setting to and from string. This can be used to save GraphicsProfile data to application settings and read the saved data on application start.
- DXEngineSettingsPanel and DXEngineSettingsWindow can be used to show graphics settings in your application. This allows user to configure the graphic settings - define his own GraphicsProfile.
The samples that come with Ab3d.DXEngine utilize the Ab3d.DirectX.Client.Settings project extensively.
In main window's Loaded event handler, the code first checks if the current system support DirectX 11.
If not than a warning message is displayed informing the user that WPF 3D will be used (or that the user should install "Platform update" if on Windows Vista or Server 2008.
Then the code calls the InitializeGraphicProfiles method. This method first checks if the DXEngineGraphicProfile key is set in the application config file.
In this case the DXEngineGraphicProfile value is used to create the GraphicsProfile that is used to initialize the DXEngine.
This can be very useful if user would have any problems with initializing the DXEngine because of faulty drivers or some other problems - with changing the application config we can force to use software rendering, some other graphics card or WPF 3D rendering.
If DXEngineGraphicProfile is not set in application config file, then application checks if the DXEngineGraphicProfile is set in the application user settings (right click on project, select "Properties" and then "Settings").
If the settings is saved there, this means that user has manually changed the GraphicProfile with using DXEngineSettingsWindow.
We deserialize the setting into a GraphicProfile and use it to initialize the DXEngine. This way the user settings are preserved between application sessions.
If no setting is saved, then the application calls the GetRecommendedGraphicsProfiles method. This checks the current system and build an array of GraphicsProfile that are recommended for the current system.
The application also allows user to manually change the GraphicProfile with using DXEngineSettingsWindow. The following screenshot shows the settings window on a laptop with two graphics card:
You do not need to use the same initialization process in your application. You can simply preserve the default value of GraphicsProfiles array and it should work in almost all the cased.
If your application is running on a controlled number of computers with proven hardware and drivers, this is probably good enough.
But if your application can be used by many users on any possible computer system, then it is wise to at least add a checking application config file for DXEngineGraphicProfile setting.
This would allow you to simply force software or WPF 3D rendering in case user would have some problems with his graphics card.
It is also recommended to add the DXEngineSettingsPanel or DXEngineSettingsWindow to your application to allow user to change the GraphicsProfile setting at runtime (for the user this is easier then changing application config files).
Also note that all modern 3D game allows setting graphics adapter and some other graphics settings - if this is used in modern 3D games, than it should be also recommended for applications that use Ab3d.DXEngine.
To use DXEngine with an application that is running in remote desktop and you want to use DirectXImage for DXViewportView.PresentationType,
you need to use .Net 4.5 or newer and the .Net 4.5 build of DXEngine (revision number should be 1045 or 45 and not 1040 or 40).
When using DirectXOverlay you can use both .Net 4.0 or .Net 4.5.
Usage notes:
You can use the Ab3d.DirectX.Client.Settings project freely and also change its source as you wish. You can add the library as reference to your project or copy the files that you need to your own project.
In the next section you will learn how to use DXEngine with Ab3d.PowerToys library.