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, 2014 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 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, which is the root for all transactions, 055 // and create a transaction 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::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 // All transactions need to get committed or aborted. 114 transaction->commit(); 115 } 116 117 int main( int argc, char* argv[]) 118 { 119 // Collect command line parameters 120 if( argc != 3) { 121 std::cerr << "Usage: example_progressive_rendering <scene_file> <mdl_path>" << std::endl; 122 keep_console_open(); 123 return EXIT_FAILURE; 124 } 125 const char* scene_file = argv[1]; 126 const char* mdl_path = argv[2]; 127 128 // Access the neuray library 129 mi::base::Handle<mi::neuraylib::INeuray> neuray( load_and_get_ineuray()); 130 check_success( neuray.is_valid_interface()); 131 132 // Configure the neuray library 133 configuration( neuray, mdl_path); 134 135 // Start the neuray library 136 check_success( neuray->start() == 0); 137 138 // Do the actual rendering 139 rendering( neuray, scene_file); 140 141 // Shut down the neuray library 142 check_success( neuray->shutdown() == 0); 143 neuray = 0; 144 145 // Unload the neuray library 146 check_success( unload()); 147 148 keep_console_open(); 149 return EXIT_SUCCESS; 150 }