Material Definition Language API nvidia_logo_transpbg.gif Up
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Example for MDL Modules
[Previous] [Up] [Next]

This example loads an MDL module and inspects it contents.

New Topics

  • Configuration of the MDL API
  • Loading of MDL modules
  • Enumerating the contents of MDL modules
  • Inspecting the parameters of material and function definitions

Detailed Description

Configuration of the MDL API

In order to allow the the MDL API to locate MDL modules and its resources in the file system it is necessary to configure the MDL module search path. This is done by calling mi::neuraylib::IMdl_configuration::add_mdl_path().

Our example module ::nvidia::sdk_examples::tutorials makes use of textures. The support for image formats in the the MDL API is provided by image plugins, which have to be loaded explicitly via mi::neuraylib::IPlugin_configuration::load_plugin_library().

In this and most other examples the configuration is done within the utility function configure(). Here, we set the module search path to the MDL directory shipped wit the examples. We also load the FreeImage plugin which comes with the the MDL API and is capable of handling .png files.

Loading of MDL modules

MDL modules are loaded with the method mi::neuraylib::IMdl_impexp_api::load_module(). Note that this method expects the module name, not the name of the file containing the module. To find the corresponding file it is necessary to configure the module search path as described above.

Enumerating the contents of MDL modules

The mi::neuraylib::IModule interface offers various methods related to metadata, like the name of the module, or the name of the file it was loaded from. Furthermore, it offers methods to enumerate the material and function definitions contained in the module. It also allows to enumerate all modules that have been (directly) imported by that module. Imported modules will be automatically loaded (if not already loaded before).

Inspecting the parameters of material and function definitions

MDL materials and functions (as found in a .mdl file) are represented in the MDL API by the interfaces mi::neuraylib::IMaterial_definition and mi::neuraylib::IFunction_definition. Similar to the module interface these interfaces offer various methods related to metadata, like the name of the definition, or the name of the containing module. Important methods are those that provide details about the parameters, like their names, types, and the values of defaults (if present).

In this example we simply dump the parameter information for the first material and function definition. The textual representation of the default values is generated by the method mi::neuraylib::IExpression_factory::dump().

Enumerating resources required by a module

The example also demonstrates the iteration of required resources. After reading the number of resources, we can iterate them and get the database name, the mdl file path, and the resource type. Based on the latter, it is possible to fetch the resolved resource path that points to the file on the current system. In case the resource could not be resolved, the database name will be NULL. However, the mdl file path will still point to the missing resource.

Example Source

Source Code Location: examples/mdl_sdk/modules/example_modules.cpp

* Copyright 2020 NVIDIA Corporation. All rights reserved.
// examples/mdl_sdk/modules/example_modules.cpp
// Loads an MDL module and inspects it contents.
#include <iostream>
#include <string>
#include "example_shared.h"
const char* material_definition_name = "mdl::nvidia::sdk_examples::tutorials::example_material";
const char* function_definition_name =
// Utility function to dump the parameters of a material or function definition.
template <class T>
void dump_definition(
const T* definition,
mi::Size depth,
std::ostream& s)
mdl_factory->create_type_factory( transaction));
mdl_factory->create_expression_factory( transaction));
mi::Size count = definition->get_parameter_count();
mi::base::Handle<const mi::neuraylib::IType_list> types( definition->get_parameter_types());
mi::base::Handle<const mi::neuraylib::IExpression_list> defaults( definition->get_defaults());
for( mi::Size index = 0; index < count; index++) {
mi::base::Handle<const mi::neuraylib::IType> type( types->get_type( index));
mi::base::Handle<const mi::IString> type_text( type_factory->dump( type.get(), depth+1));
std::string name = definition->get_parameter_name( index);
s << " parameter " << type_text->get_c_str() << " " << name;
defaults->get_expression( name.c_str()));
if( default_.is_valid_interface()) {
expression_factory->dump( default_.get(), 0, depth+1));
s << ", default = " << default_text->get_c_str() << std::endl;
} else {
s << " (no default)" << std::endl;
mi::Size temporary_count = definition->get_temporary_count();
for( mi::Size i = 0; i < temporary_count; ++i) {
mi::base::Handle<const mi::neuraylib::IExpression> temporary( definition->get_temporary( i));
std::stringstream name;
name << i;
expression_factory->dump( temporary.get(), name.str().c_str(), 1));
s << " temporary " << result->get_c_str() << std::endl;
mi::base::Handle<const mi::IString> result( expression_factory->dump( body.get(), 0, 1));
if( result)
s << " body " << result->get_c_str() << std::endl;
s << " body not available for this function" << std::endl;
s << std::endl;
// Loads an MDL module and inspects it contents.
void load_module( mi::neuraylib::INeuray* neuray)
// Access the database and create a transaction.
mi::base::Handle<mi::neuraylib::IScope> scope( database->get_global_scope());
mi::base::Handle<mi::neuraylib::ITransaction> transaction( scope->create_transaction());
// Load the module "tutorials".
transaction.get(), "::nvidia::sdk_examples::tutorials", context.get()) >= 0);
print_messages( context.get());
// Access the module by its name. The name to be used here is the MDL name of the module
// ("example") plus the "mdl::" prefix.
transaction->access<mi::neuraylib::IModule>( "mdl::nvidia::sdk_examples::tutorials"));
check_success( module.is_valid_interface());
// Print the module name and the file name it was loaded from.
std::cout << "Loaded file " << module->get_filename() << std::endl;
std::cout << "Found module " << module->get_mdl_name() << std::endl;
std::cout << std::endl;
// Dump imported modules.
mi::Size module_count = module->get_import_count();
std::cout << "The module imports the following modules:" << std::endl;
for( mi::Size i = 0; i < module_count; i++)
std::cout << " " << module->get_import( i) << std::endl;
std::cout << std::endl;
// Dump exported types.
mdl_factory->create_type_factory( transaction.get()));
std::cout << "The module contains the following types: " << std::endl;
for( mi::Size i = 0; i < types->get_size(); ++i) {
mi::base::Handle<const mi::IString> result( type_factory->dump( type.get(), 1));
std::cout << " " << result->get_c_str() << std::endl;
std::cout << std::endl;
// Dump exported constants.
mdl_factory->create_value_factory( transaction.get()));
mi::base::Handle<const mi::neuraylib::IValue_list> constants( module->get_constants());
std::cout << "The module contains the following constants: " << std::endl;
for( mi::Size i = 0; i < constants->get_size(); ++i) {
const char* name = constants->get_name( i);
mi::base::Handle<const mi::neuraylib::IValue> constant( constants->get_value( i));
mi::base::Handle<const mi::IString> result( value_factory->dump( constant.get(), 0, 1));
std::cout << " " << name << " = " << result->get_c_str() << std::endl;
std::cout << std::endl;
// Dump function definitions of the module.
mi::Size function_count = module->get_function_count();
std::cout << "The module contains the following function definitions:" << std::endl;
for( mi::Size i = 0; i < function_count; i++)
std::cout << " " << module->get_function( i) << std::endl;
std::cout << std::endl;
// Dump material definitions of the module.
mi::Size material_count = module->get_material_count();
std::cout << "The module contains the following material definitions:" << std::endl;
for( mi::Size i = 0; i < material_count; i++)
std::cout << " " << module->get_material( i) << std::endl;
std::cout << std::endl;
// Dump a function definition from the module.
std::cout << "Dumping function definition \"" << function_definition_name << "\":"
<< std::endl;
transaction->access<mi::neuraylib::IFunction_definition>( function_definition_name));
transaction.get(), mdl_factory.get(), function_definition.get(), 1, std::cout);
// Dump a material definition from the module.
std::cout << "Dumping material definition \"" << material_definition_name << "\":"
<< std::endl;
transaction->access<mi::neuraylib::IMaterial_definition>( material_definition_name));
transaction.get(), mdl_factory.get(), material_definition.get(), 1, std::cout);
// Dump the resources referenced by this module
std::cout << "Dumping resources of this module: \n";
for( mi::Size r = 0, rn = module->get_resources_count(); r < rn; ++r)
const char* db_name = module->get_resource_name( r);
const char* mdl_file_path = module->get_resource_mdl_file_path( r);
if( db_name == nullptr)
// resource is either not used and therefore has not been loaded or
// could not be found.
std::cout << " db_name: none" << std::endl;
std::cout << " mdl_file_path: " << mdl_file_path << std::endl
<< std::endl;
std::cout << " db_name: " << db_name << std::endl;
std::cout << " mdl_file_path: " << mdl_file_path << std::endl;
module->get_resource_type( r));
switch( type->get_kind())
transaction->access<mi::neuraylib::ITexture>( db_name));
if( texture)
transaction->access<mi::neuraylib::IImage>( texture->get_image()));
for( mi::Size t = 0, tn = image->get_uvtile_length(); t < tn; ++t)
const char* system_file_path = image->get_filename(
static_cast<mi::Uint32>( t));
std::cout << " resolved_file_path[" << t << "]: "
<< system_file_path << std::endl;
transaction->access<mi::neuraylib::ILightprofile>( db_name));
if( light_profile)
const char* system_file_path = light_profile->get_filename();
std::cout << " resolved_file_path: " << system_file_path << std::endl;
transaction->access<mi::neuraylib::IBsdf_measurement>( db_name));
if( mbsdf)
const char* system_file_path = mbsdf->get_filename();
std::cout << " resolved_file_path: " << system_file_path << std::endl;
std::cout << std::endl;
// All transactions need to get committed.
int MAIN_UTF8( int /*argc*/, char* /*argv*/[])
// Access the MDL SDK
mi::base::Handle<mi::neuraylib::INeuray> neuray(mi::examples::mdl::load_and_get_ineuray());
if (!neuray.is_valid_interface())
exit_failure("Failed to load the SDK.");
// Configure the MDL SDK
if (!mi::examples::mdl::configure(neuray.get()))
exit_failure("Failed to initialize the SDK.");
// Start the MDL SDK
mi::Sint32 ret = neuray->start();
if (ret != 0)
exit_failure("Failed to initialize the SDK. Result code: %d", ret);
// Load an MDL module and dump its contents
load_module( neuray.get());
// Shut down the MDL SDK
if (neuray->shutdown() != 0)
exit_failure("Failed to shutdown the SDK.");
// Unload the MDL SDK
neuray = nullptr;
if (!mi::examples::mdl::unload())
exit_failure("Failed to unload the SDK.");
// Convert command line arguments to UTF8 on Windows
[Previous] [Up] [Next]