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

Overview

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.

Configuration

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.

example_rendering.cpp

001 /******************************************************************************
002  * © 1986, 2015 NVIDIA ARC GmbH. All rights reserved.
003  *****************************************************************************/
004 
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
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".
017 
018 #include <iostream>
019 
020 #include <mi/neuraylib.h>
021 
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"
026 
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);
034 
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>());
038 #ifndef MI_PLATFORM_WINDOWS
039     check_success( plugin_configuration->load_plugin_library( "freeimage.so") == 0);
040     check_success( plugin_configuration->load_plugin_library( "libiray.so") == 0);
041     check_success( plugin_configuration->load_plugin_library( "mi_importer.so") == 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 }
048 
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());
062 
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);
071 
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");
079 
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;
089 
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);
096 
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());
103 
104     // All transactions need to get committed or aborted.
105     transaction->commit();
106 }
107 
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];
118 
119     // Access the neuray library
120     mi::base::Handle<mi::neuraylib::INeuray> neuray( load_and_get_ineuray());
121     check_success( neuray.is_valid_interface());
122 
123     // Configure the neuray library
124     configuration( neuray, mdl_path);
125 
126     // Start the neuray library
127     check_success( neuray->start() == 0);
128 
129     // Do the actual rendering
130     rendering( neuray, scene_file);
131 
132     // Shut down the neuray library
133     check_success( neuray->shutdown() == 0);
134     neuray = 0;
135 
136     // Unload the neuray library
137     check_success( unload());
138 
139     keep_console_open();
140     return EXIT_SUCCESS;
141 }