A first image
This topic introduces:
- Core concepts about rendering images with Iray:
- 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::IImport_result. This interface provides among other things the method mi::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 c-"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 c-"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, 2014 NVIDIA Corporation. 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, which is the root for all transactions, 053 // and create a transaction 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::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 }