Iray Programmer's Manual

Progressive rendering of a scene

This topic introduces:

  1. Progressive rendering, which explains what progressive rendering is and when to use it
  2. example_progressive_rendering.cpp, which demonstrates how to set up progressive rendering for a render context

Progressive rendering

Progressive rendering is intended to provide users with fast feedback. The initial render call generates a somewhat low quality frame. Subsequent render calls refine the image incrementally.

Each frame generated by a progressive rendering operation is exported to a file. Displaying all files in sequence shows the incremental refinement of the image. On Linux, you can view this progression using the animate command from ImageMagick software:

animate -delay 10 `\ls -1 example_progressive_rendering_*.png`

There are a number of termination criteria used to determine when a progressive rendering operation is considered finished. The progressive rendering operation is restarted, for example, when the camera position changes or changes are made to the scene that would be visible in the rendered image. On the other hand, progressive rendering operation is ended when the image resolution of the last rendered frame satisfies the image resolution criterion.

See Progressive rendering in Iray Photoreal and Progressive rendering in Iray Interactive for detailed information about progressive rendering options supported by the respective rendering modes.

Example for progressive rendering

The example for progressive rendering is a modification of the example program used in A first image, Accessing the database, and Importing a scene file.

Note the following:

  • The interactive scheduling mode (default mode) is used.
  • The rendering logic has one modification: A loop is used to repeatedly call the render() method.
  • A custom canvas class is used, whose implementation you can see in Own canvas class.

example_progressive_rendering.cpp

001 /******************************************************************************
002  * © 1986, 2015 NVIDIA ARC GmbH. All rights reserved.
003  *****************************************************************************/
004 
005 // examples/example_progressive_rendering.cpp
006 //
007 // Renders a scene in progressive rendering mode.
008 //
009 // The example expects the following command line arguments:
010 //
011 //   example_progressive_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 images are written to files named "example_progressive_rendering_00.png", etc.
017 
018 #include <iomanip>
019 #include <iostream>
020 #include <sstream>
021 
022 #include <mi/neuraylib.h>
023 
024 // Include code shared by all examples.
025 #include "example_shared.h"
026 // Include an implementation of ITile, ICanvas, and IRender_target.
027 #include "example_render_target_advanced.h"
028 
029 void configuration( mi::base::Handle<mi::neuraylib::INeuray> neuray, const char* mdl_path)
030 {
031     // Configure the neuray library. Here we set the search path for .mdl files.
032     mi::base::Handle<mi::neuraylib::IRendering_configuration> rendering_configuration(
033         neuray->get_api_component<mi::neuraylib::IRendering_configuration>());
034     check_success( rendering_configuration.is_valid_interface());
035     check_success( rendering_configuration->add_mdl_path( mdl_path) == 0);
036 
037     // Load the FreeImage, Iray Photoreal, and .mi importer plugins.
038     mi::base::Handle<mi::neuraylib::IPlugin_configuration> plugin_configuration(
039         neuray->get_api_component<mi::neuraylib::IPlugin_configuration>());
040 #ifndef MI_PLATFORM_WINDOWS
041     check_success( plugin_configuration->load_plugin_library( "freeimage.so") == 0);
042     check_success( plugin_configuration->load_plugin_library( "libiray.so") == 0);
043     check_success( plugin_configuration->load_plugin_library( "mi_importer.so") == 0);
044 #else
045     check_success( plugin_configuration->load_plugin_library( "freeimage.dll") == 0);
046     check_success( plugin_configuration->load_plugin_library( "libiray.dll") == 0);
047     check_success( plugin_configuration->load_plugin_library( "mi_importer.dll") == 0);
048 #endif
049 }
050 
051 void rendering( mi::base::Handle<mi::neuraylib::INeuray> neuray,
052                 const char* scene_file)
053 {
054     // Get the database, the global scope of the database, and create a transaction in the global
055     // scope for importing the scene file and storing the scene.
056     mi::base::Handle<mi::neuraylib::IDatabase> database(
057         neuray->get_api_component<mi::neuraylib::IDatabase>());
058     check_success( database.is_valid_interface());
059     mi::base::Handle<mi::neuraylib::IScope> scope(
060         database->get_global_scope());
061     mi::base::Handle<mi::neuraylib::ITransaction> transaction(
062         scope->create_transaction());
063     check_success( transaction.is_valid_interface());
064 
065     // Import the scene file
066     mi::base::Handle<mi::neuraylib::IImport_api> import_api(
067         neuray->get_api_component<mi::neuraylib::IImport_api>());
068     check_success( import_api.is_valid_interface());
069     mi::base::Handle<const mi::IString> uri( import_api->convert_filename_to_uri( scene_file));
070     mi::base::Handle<const mi::neuraylib::IImport_result> import_result(
071         import_api->import_elements( transaction.get(), uri->get_c_str()));
072     check_success( import_result->get_error_number() == 0);
073 
074     // Create the scene object
075     mi::base::Handle<mi::neuraylib::IScene> scene(
076         transaction->create<mi::neuraylib::IScene>( "Scene"));
077     scene->set_rootgroup(       import_result->get_rootgroup());
078     scene->set_options(         import_result->get_options());
079     scene->set_camera_instance( import_result->get_camera_inst());
080     transaction->store( scene.get(), "the_scene");
081 
082     // Create the render context using the Iray Photoreal render mode
083     scene = transaction->edit<mi::neuraylib::IScene>( "the_scene");
084     mi::base::Handle<mi::neuraylib::IRender_context> render_context(
085         scene->create_render_context( transaction.get(), "iray"));
086     check_success( render_context.is_valid_interface());
087     scene = 0;
088 
089     // Render progressively at most 10 frames
090     for( mi::Size i = 0; i < 10; ++i) {
091 
092         // Create the render target and render the i-th frame of the scene
093         mi::base::Handle<mi::neuraylib::IRender_target> render_target(
094             new Render_target( 512, 384));
095         mi::Sint32 result = render_context->render( transaction.get(), render_target.get(), 0);
096         check_success( result >= 0);
097 
098         // Write the image to disk
099         mi::base::Handle<mi::neuraylib::IExport_api> export_api(
100             neuray->get_api_component<mi::neuraylib::IExport_api>());
101         check_success( export_api.is_valid_interface());
102         mi::base::Handle<mi::neuraylib::ICanvas> canvas( render_target->get_canvas( 0));
103         std::ostringstream str;
104         str << "example_progressive_rendering_" << std::setw( 2) << std::setfill( '0') << i
105             << ".png";
106         export_api->export_canvas( str.str().c_str(), canvas.get());
107 
108         // Leave render loop if the termination criteria have been met
109         if( result > 0)
110             break;
111     }
112 
113     // Pick the cube.
114     mi::base::Handle<mi::neuraylib::IPick_array> pick_array(
115         render_context->pick( transaction.get(), mi::Float32_2( 128, 192)));
116     std::cerr << "Picked objects:" << std::endl;
117     for( mi::Uint32 i = 0; i < pick_array->get_length(); ++i) {
118         mi::base::Handle<mi::neuraylib::IPick_result> pick_result( pick_array->get_pick_result( i));
119         mi::Float64_3 hit_point = pick_result->get_world_point();
120         std::cerr << "Object " << i << ": \"" << pick_result->get_picked_object_name() << "\", "
121             << "hit point (" << hit_point.x << ", " << hit_point.y << ", " << hit_point.z << "), "
122             << "path \"" << pick_result->get_path( 0) << "\"";
123         mi::Uint32 path_length = pick_result->get_path_length();
124         for( mi::Uint32 j = 1; j < path_length; ++j)
125             std::cerr << ", \"" << pick_result->get_path( j) << "\"";
126         std::cerr << std::endl;
127     }
128 
129     // All transactions need to get committed or aborted.
130     transaction->commit();
131 }
132 
133 int main( int argc, char* argv[])
134 {
135     // Collect command line parameters
136     if( argc != 3) {
137         std::cerr << "Usage: example_progressive_rendering <scene_file> <mdl_path>" << std::endl;
138         keep_console_open();
139         return EXIT_FAILURE;
140     }
141     const char* scene_file  = argv[1];
142     const char* mdl_path = argv[2];
143 
144     // Access the neuray library
145     mi::base::Handle<mi::neuraylib::INeuray> neuray( load_and_get_ineuray());
146     check_success( neuray.is_valid_interface());
147 
148     // Configure the neuray library
149     configuration( neuray, mdl_path);
150 
151     // Start the neuray library
152     check_success( neuray->start() == 0);
153 
154     // Do the actual rendering
155     rendering( neuray, scene_file);
156 
157     // Shut down the neuray library
158     check_success( neuray->shutdown() == 0);
159     neuray = 0;
160 
161     // Unload the neuray library
162     check_success( unload());
163 
164     keep_console_open();
165     return EXIT_SUCCESS;
166 }