Progressive rendering of a scene
This topic introduces:
- Progressive rendering, which explains what progressive rendering is and when to use it
- 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, 2016 NVIDIA Corporation. 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, e.g., main.mi 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 mi::Sint32 result = neuray->start(); 153 check_start_success( result); 154 155 // Do the actual rendering 156 rendering( neuray, scene_file); 157 158 // Shut down the neuray library 159 check_success( neuray->shutdown() == 0); 160 neuray = 0; 161 162 // Unload the neuray library 163 check_success( unload()); 164 165 keep_console_open(); 166 return EXIT_SUCCESS; 167 }