Iray Programmer's Manual

A first image

This topic introduces:

  1. Core concepts about rendering images with Iray:
  2. example_rendering.cpp, which demonstrates how to render an image with Iray


To render a first image, you need to follow the steps explained in Starting and shutting down the Iray API to obtain the neuray object. Before actually starting the Iray API, you configure it -- in this example you provide the material search path and load plugins -- and after starting the Iray API you load the scene from a file into the database, render the image, and write the result into an image file.


The minimal configuration needed for this example is the search path setting and the plugin loading.

When loading assets like textures or materials, Iray uses search paths to locate those assets, This example imports .mi files, which reference MDL materials, written in the NVIDIA Material Definition Language (MDL). The search path to find those materials is set here. For this example, the search path is actually provided as one of the input parameters to the example program.

Iray makes itself use of plugins to provide different functionality. This example needs to load the FreeImage plugin to support various image formats, the .mi importer plugin to load the scene in this file format, and the libiray plugin to render with the Iray Photoreal render mode.

Accessing the database

The mi::neuraylib::IDatabase interface is one of the central interface classes that become available once neuray has been started. Using this interface, you can access the scene database. In particular, you can either access the global scope or create your own scope. The mi::neuraylib::IScope interface allows you to create transactions, which are required for all operations that access the database.

This example uses the database interface to access the global scope and creates a transaction in the global scope. All transactions need either to get committed or aborted. By committing a transaction, all changes (if any) will become visible for subsequently started transactions. Aborting a transaction discards any changes made in that transaction.

Importing a scene file

The import of files is handled by the API component mi::neuraylib::IImport_api. The actual import is done by the method mi::neuraylib::IImport_api::import_elements(). The result of the import operation is described by the interface mi::neuraylib::IImport_result. This interface provides among other things the method mi::neuraylib::IImport_result::get_error_number() to retrieve the resulting error number. This error number is 0 in case of success, all other numbers indicate failures.

The example also creates an instance of the mi::neuraylib::IScene interface, which is later used for rendering. To this end, the name of the root group, the camera, and the options are set in the scene. These names are available from the import result.

Rendering a scene

Rendering a scene requires a render mode, which might require the loading of a corresponding plugin, a render target and a render context.

A list of render modes with their plugin names and string value name, for the use with the render context below, is shown here. For the example program below, the chosen render mode is Iray Photoreal with the required libiray plugin and the string value name "iray".

To render a scene, you have to provide a render target with space for the rendered images. In principle, a single render call can render several images at once, each stored in a canvas. Canvases have names and these names determine the actual images render, e.g., the final beauty pass result, alpha channel, depth or normal pass. The relevant API interfaces are mi::neuraylib::IRender_target, mi::neuraylib::ICanvas, and mi::neuraylib::ITile. However, the Iray API provides a default canvas class implementation, which is used in the example below. Furthermore, the implementation of a render target has been factored into a separate header file, example_render_target_simple.h, which is used across several examples. More details about customizing a render target of canvas class can be found here.

The render context can be obtained from mi::neuraylib::IScene::create_render_context(). Here, the actual render mode is selected with its string value name, which is "iray" in the example program below.

Example for rendering an image from a scene file

This example program expands the example_start_shutdown.cpp example program and adds a configuration() and a rendering() function. The configuration() function sets the MDL search path and loads the required plugin libraries. The rendering() function goes through all the other steps described above; it imports a scene file, renders the scene and writes the resulting image to disk.

This example program expects two command line arguments; the search path for the MDL materials and the file name for the scene file.


001 /******************************************************************************
002  * © 1986, 2016 NVIDIA Corporation. All rights reserved.
003  *****************************************************************************/
005 // examples/example_rendering.cpp
006 //
007 // Imports a scene file, renders the scene, and writes the image to disk.
008 //
009 // The example expects the following command line arguments:
010 //
011 //   example_rendering <scene_file> <mdl_path>
012 //
013 // scene_file       some scene file, e.g., main.mi
014 // mdl_path         path to the MDL modules, e.g., iray-<version>/mdl
015 //
016 // The rendered image is written to a file named "example_rendering.png".
018 #include <iostream>
020 #include <mi/neuraylib.h>
022 // Include code shared by all examples.
023 #include "example_shared.h"
024 // Include an implementation of IRender_target.
025 #include "example_render_target_simple.h"
027 void configuration( mi::base::Handle<mi::neuraylib::INeuray> neuray, const char* mdl_path)
028 {
029     // Configure the neuray library. Here we set the search path for .mdl files.
030     mi::base::Handle<mi::neuraylib::IRendering_configuration> rendering_configuration(
031         neuray->get_api_component<mi::neuraylib::IRendering_configuration>());
032     check_success( rendering_configuration.is_valid_interface());
033     check_success( rendering_configuration->add_mdl_path( mdl_path) == 0);
035     // Load the FreeImage, Iray Photoreal, and .mi importer plugins.
036     mi::base::Handle<mi::neuraylib::IPlugin_configuration> plugin_configuration(
037         neuray->get_api_component<mi::neuraylib::IPlugin_configuration>());
039     check_success( plugin_configuration->load_plugin_library( "") == 0);
040     check_success( plugin_configuration->load_plugin_library( "") == 0);
041     check_success( plugin_configuration->load_plugin_library( "") == 0);
042 #else
043     check_success( plugin_configuration->load_plugin_library( "freeimage.dll") == 0);
044     check_success( plugin_configuration->load_plugin_library( "libiray.dll") == 0);
045     check_success( plugin_configuration->load_plugin_library( "mi_importer.dll") == 0);
046 #endif
047 }
049 void rendering( mi::base::Handle<mi::neuraylib::INeuray> neuray,
050                 const char* scene_file)
051 {
052     // Get the database, the global scope of the database, and create a transaction in the global
053     // scope for importing the scene file and storing the scene.
054     mi::base::Handle<mi::neuraylib::IDatabase> database(
055         neuray->get_api_component<mi::neuraylib::IDatabase>());
056     check_success( database.is_valid_interface());
057     mi::base::Handle<mi::neuraylib::IScope> scope(
058         database->get_global_scope());
059     mi::base::Handle<mi::neuraylib::ITransaction> transaction(
060         scope->create_transaction());
061     check_success( transaction.is_valid_interface());
063     // Import the scene file
064     mi::base::Handle<mi::neuraylib::IImport_api> import_api(
065         neuray->get_api_component<mi::neuraylib::IImport_api>());
066     check_success( import_api.is_valid_interface());
067     mi::base::Handle<const mi::IString> uri( import_api->convert_filename_to_uri( scene_file));
068     mi::base::Handle<const mi::neuraylib::IImport_result> import_result(
069         import_api->import_elements( transaction.get(), uri->get_c_str()));
070     check_success( import_result->get_error_number() == 0);
072     // Create the scene object
073     mi::base::Handle<mi::neuraylib::IScene> scene(
074         transaction->create<mi::neuraylib::IScene>( "Scene"));
075     scene->set_rootgroup(       import_result->get_rootgroup());
076     scene->set_options(         import_result->get_options());
077     scene->set_camera_instance( import_result->get_camera_inst());
078     transaction->store( scene.get(), "the_scene");
080     // Create the render context using the Iray Photoreal render mode
081     scene = transaction->edit<mi::neuraylib::IScene>( "the_scene");
082     mi::base::Handle<mi::neuraylib::IRender_context> render_context(
083         scene->create_render_context( transaction.get(), "iray"));
084     check_success( render_context.is_valid_interface());
085     mi::base::Handle<mi::IString> scheduler_mode( transaction->create<mi::IString>());
086     scheduler_mode->set_c_str( "batch");
087     render_context->set_option( "scheduler_mode", scheduler_mode.get());
088     scene = 0;
090     // Create the render target and render the scene
091     mi::base::Handle<mi::neuraylib::IImage_api> image_api(
092         neuray->get_api_component<mi::neuraylib::IImage_api>());
093     mi::base::Handle<mi::neuraylib::IRender_target> render_target(
094         new Render_target( image_api.get(), "Color", 512, 384));
095     check_success( render_context->render( transaction.get(), render_target.get(), 0) >= 0);
097     // Write the image to disk
098     mi::base::Handle<mi::neuraylib::IExport_api> export_api(
099         neuray->get_api_component<mi::neuraylib::IExport_api>());
100     check_success( export_api.is_valid_interface());
101     mi::base::Handle<mi::neuraylib::ICanvas> canvas( render_target->get_canvas( 0));
102     export_api->export_canvas( "file:example_rendering.png", canvas.get());
104     // All transactions need to get committed or aborted.
105     transaction->commit();
106 }
108 int main( int argc, char* argv[])
109 {
110     // Collect command line parameters
111     if( argc != 3) {
112         std::cerr << "Usage: example_rendering <scene_file> <mdl_path>" << std::endl;
113         keep_console_open();
114         return EXIT_FAILURE;
115     }
116     const char* scene_file  = argv[1];
117     const char* mdl_path = argv[2];
119     // Access the neuray library
120     mi::base::Handle<mi::neuraylib::INeuray> neuray( load_and_get_ineuray());
121     check_success( neuray.is_valid_interface());
123     // Configure the neuray library
124     configuration( neuray, mdl_path);
126     // Start the neuray library
127     mi::Sint32 result = neuray->start();
128     check_start_success( result);
130     // Do the actual rendering
131     rendering( neuray, scene_file);
133     // Shut down the neuray library
134     check_success( neuray->shutdown() == 0);
135     neuray = 0;
137     // Unload the neuray library
138     check_success( unload());
140     keep_console_open();
141     return EXIT_SUCCESS;
142 }