Material Definition Language API nvidia_logo_transpbg.gif Up
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Example for a Microsoft DXR-based MDL-enabled Path Tracer
[Previous] [Up] [Next]

This example demonstrates how to integrate MDL into a real-time path tracer that is able to render scenes provided in the glTF format. The rendering framework is based on Microsoft DirectX Raytracing (DXR) and utilizes the MDL HLSL backend to generate HLSL code for evaluating expressions and distribution functions directly inside shaders.

New Topics

  • Integration of MDL in a real-time renderer
  • Using the glTF metallic-roughness support material, as well as other MDL materials and MDLE

Detailed Description

The Examples Rendering Framework


In order to illustrate the use of MDL in the context of real-time rendering and in scenes consisting of multiple objects with different materials, at least a small rendering framework that handles scene loading and the main application loop is required. To concentrate on the MDL features, most parts of the low-level Direct3D API have been hidden behind classes that provide a more abstract view, which in turn makes it easier to communicate how MDL fits into the bigger picture. To get started with DXR and for more detailed information on the Direct3D API it is recommended to look into other resources such as the NVIDIA DX12 Raytracing tutorial and the Microsoft DirectX-Graphics-Samples.

The parts of the framework that are important for the MDL integration can be found in a few source files: mdl_d3d12/mdl_material.h, mdl_d3d12/mdl_material.cpp, and example_dxr.cpp. While the latter contains the main application that triggers the scene loading, the pipeline setup as well as the update and rendering loop, the first two files define classes for the MDL SDK interface, the MDL target code with a link unit and most importantly the Mdl_material class which handles the loading and parameterization of the scenes materials.

The essential parts of the renderer are implemented in HLSL. In the hit shaders (content/mdl_hit_programs.hlsl), the material is evaluated for the current intersection of the ray with the surface. Afterwards, the direction for the next segment of the ray path is computed. The interface for the evaluation corresponds to the one in the [df_cuda example]. The required glue-code and the runtime functions for HLSL can be found in the content/mdl_target_code_types.hlsl and content/mdl_renderer_runtime.hlsl.

The actual renderer will not have to call the contained functions directly, they are referenced by the generated code. Instead, the entry points into the generated code have to be invoked by the renderer. For instance:

mdl_bsdf_evaluate( // defined in the generated target code
scattering_function_index, // returned by link_unit::add_material(...)
// and passed to shader in constant buffer
eval_data, // local in/output struct prepared by the renderer
mdl_state); // contains information about the hit point and the material

The generated code is written to the binary directory for debugging and inspection purposes: link_unit_source.hlsl

Material parameters are mapped to a dear imgui user interface, just like in the [df_cuda example], so they can be changed at runtime. See mdl_d3d12/mdl_material_info.h, gui.h, and gui.cpp for more details.

Specifying MDL Materials in glTF scenes


At this point, the glTF scene format contains no explicit support for MDL. However, it provides a set of parameters that are intended to be used in physically-based rendering (PBR) and is therefore compatible with MDL. Here is an example for an glTF material node:

{
"name": "ShaderBall",
"doubleSided": true,
"emissiveFactor": [ 0.0, 0.0, 0.0 ],
"normalTexture": {
"index": 1,
"scale": 1,
"texCoord": 0
},
"pbrMetallicRoughness": {
"baseColorFactor": [ 1.0, 1.0, 1.0, 1.0 ],
"baseColorTexture": {
"index": 2,
"texCoord": 0
},
"metallicFactor": 1.0,
"roughnessFactor": 1.0,
"metallicRoughnessTexture": {
"index": 0,
"texCoord": 0
}
}
}

Note, that textures are defined separately. They are referenced by the index property. While loading the scene, these parameters are parsed, the texture file paths are resolved and the support material defined in the provided gltf_support.mdl is parameterized accordingly.

To avoid the creation of redundant HLSL code class-compilation is used, which allows to change parameters at runtime. For each scene material that uses the glTF_support material the same HLSL code is executed, but the individual parameter sets, the argument blocks, are bound as buffers to the graphics pipeline.

The possibilities of this standard material are limited. Glass for instance can not be described properly without an index of refraction (IOR). To overcome this limitation without introducing an MDL extension to glFT, an arbitrary MDL material can be assigned by setting the name property of the glTF material node to a fully qualified absolute MDL material identifier like this:

{
"name": "::nvidia::sdk_examples::tutorials::dxr_sphere_mat"
}

All other material properties are ignored in that case. This means that the selected MDL material must provide default values for all its parameters.

The Example also supports the MDL encapsulated format. In this case, the file path of the MDLE has to be specified in the name property of the glTF material node. This file path can either be absolute or relative to the .glft scene file:

{
"name": "glass.mdle"
}

Running the example


When running the DXR example, a simple sphere with an MDL material is rendered. Moving the mouse while pressing the left or the middle mouse button allows to rotate or pan the camera, while scrolling allows to move forward and back. Pressing space reveals the user interface that allows to change parameters of the material, the camera and the renderer. Pressing print writes a screenshot into the current working directory.

To load a different scene, the DXR example is started from the command line with an glTF file to load:

dxr.exe some_folder/my_scene.gltf

Various interesting scenes can be found online, for instance on sketchfab.com, so give it a try.

There are further options that can be used with the DXR example. Here are a few commonly used ones:

  • -h | --help
    Shows all options with a short explanation.
  • --mdl_path <value>
    By default, the example uses three default search paths. On the Windows platform this is the admin-space search path, e.g., C:\ProgramData\NVIDIA Corporation\mdl and the user-space search path %USERPROFILE%\Documents\mdl as well as scene folder that contains the loaded glTF. By passing the command line option --mdl_path <value>, this default behavior can be changed. The option can appear multiple times.
  • --hdr <filename>
    Path of an .hdr environment map that is used for image-based lighting and as background. The path can be absolute or relative to the scene file.
  • --mat <qualified_name>
    Override all materials in the scene using a qualified material name or an MDLE path.

Restrictions

The DXR example is a prototype renderer with certain limitations:
  • The encoding of MDL material qualifiers into the name property has obviously limitations. All names starting with :: literal are interpreted as MDL names and all names ending with .mdle are interpreted as file paths, which both are unlikely but not impossible to appear by accident.
  • From an MDL perspective, the lack of specifying MDL material parameters in glTF is also a limitation.
  • Many existing glTF scenes make use of extensions like KHR_materials_pbrSpecularGlossiness. There are no support material for such extensions yet.
  • The example is based on a very simple path tracer. Multiple importance sampling (MIS) is only used to sample the BSDFs and the environment light. Emissive surfaces however are only hit by chance and the progressive rendering requires more time to converge.
  • The example does not include support for measured BSDFs and light profiles.
[Previous] [Up] [Next]