Iray SDK API nvidia_logo_transpbg.gif Up
Example for Progressive rendering
[Previous] [Next] [Up]

This example renders a scene progressively.

New Topics

  • Providing the rendering infrastructure (advanced)
  • Progressive rendering of a scene

Detailed Description

Providing the rendering infrastructure (advanced)


This example demonstrates an advanced way of providing the required rendering infrastructure: custom implementations of the interfaces mi::neuraylib::ICanvas and mi::neuraylib::ITile; the previous example (and most other examples) use internal default implementations.

The classes Canvas and Tile show an example implementation of the corresponding interfaces. For simplicity, the only supported pixel type is "Color", i.e., one float per channel.

Progressive rendering of a scene


Progressive rendering is a rendering mode that provide fast feedback to the user. Typically, the first frame has a lower quality than usual, but it is available very fast. Subsequent render calls then improve the result obtained so far more and more.

This example is a modification of the previous example. The scheduling mode is not changed to "batch", but left at "interactive" (which is the default). The render() method is called repeatedly from a loop, but otherwise identical to the previous example.

Each frame is exported to a file. Displaying all files in sequence shows the progression. On Linux you can view the progression using the animate command from the ImageMagick software as follows

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

See [IPM] for further attributes related to progressive rendering, in particular see interactive_update_interval.

Picking


Finally the example shows how to pick objects that are behind a given point in screen space. For each hit object the following pieces of information are available: the name of the object, the coordinates of the hit point, and the path in the scene graph from the object to the root group. Note that if there are multiple instances of this object that path identifies the particular instance that was hit by the pick operation.

Note that while the API is designed to report all hit objects many render modes have the limitation to report only the first hit.

Example Source

Source Code Location: examples/example_render_target_advanced.h

/******************************************************************************
* Copyright 2023 NVIDIA Corporation. All rights reserved.
*****************************************************************************/
// examples/example_render_target_advanced.h
//
// Code shared by some rendering examples
#ifndef EXAMPLE_RENDER_TARGET_ADVANCED_H
#define EXAMPLE_RENDER_TARGET_ADVANCED_H
#include <mi/neuraylib.h>
// A simple implementation of the ITile interface with pixel type "Color".
//
// This implementation is for educational purposes. Being able to supply your own implementation
// of the ICanvas and ITile interfaces might be advantageous depending on the context. If you do
// not have any special needs you can simply use the default implementation available via
// mi::neuraylib::IImage_api::create_tile().
class Tile : public mi::base::Interface_implement<mi::neuraylib::ITile>
{
public:
// Constructor.
//
// Creates a tile of the given width and height with pixel type "Color".
Tile( mi::Uint32 width, mi::Uint32 height)
{
m_width = width;
m_height = height;
m_data = new mi::Float32[m_width * m_height * 4];
}
// Destructor
~Tile() { delete[] m_data; }
// Implement the interface of mi::neuraylib::ITile
void set_pixel( mi::Uint32 x_offset, mi::Uint32 y_offset, const mi::Float32* floats)
{
mi::Float32* position = &m_data[(x_offset + y_offset * m_width) * 4];
position[0] = floats[0];
position[1] = floats[1];
position[2] = floats[2];
position[3] = floats[3];
}
void get_pixel( mi::Uint32 x_offset, mi::Uint32 y_offset, mi::Float32* floats) const
{
mi::Float32* position = &m_data[(x_offset + y_offset * m_width) * 4];
floats[0] = position[0];
floats[1] = position[1];
floats[2] = position[2];
floats[3] = position[3];
}
const char* get_type() const { return "Color"; }
mi::Uint32 get_resolution_x() const { return m_width; }
mi::Uint32 get_resolution_y() const { return m_height; }
const void* get_data() const { return m_data; }
void* get_data() { return m_data; }
private:
// Width of the tile
mi::Uint32 m_width;
// Height of the tile
mi::Uint32 m_height;
// The data of this tile, 32 bytes per pixel
mi::Float32* m_data;
};
// A simple implementation of the ICanvas interface with a single tile with pixel type "Color".
//
// This implementation is for educational purposes. Being able to supply your own implementation
// of the ICanvas and ITile interfaces might be advantageous depending on the context. If you do
// not have any special needs you can simply use the default implementation available via
// mi::neuraylib::IImage_api::create_canvas().
class Canvas : public mi::base::Interface_implement<mi::neuraylib::ICanvas>
{
public:
// Constructor.
//
// Creates a canvas with a single tile of the given width and height.
Canvas( mi::Uint32 width, mi::Uint32 height)
{
m_width = width;
m_height = height;
m_gamma = 1.0f;
m_tile = new Tile( width, height);
}
// Implement the interface of mi::neuraylib::ICanvas
mi::Uint32 get_resolution_x() const { return m_width; }
mi::Uint32 get_resolution_y() const { return m_height; }
mi::Uint32 get_layers_size() const { return 1; }
const mi::neuraylib::ITile* get_tile(mi::Uint32 = 0) const
{
m_tile->retain();
return m_tile.get();
}
{
m_tile->retain();
return m_tile.get();
}
const char* get_type() const { return "Color"; }
mi::Float32 get_gamma() const { return m_gamma; }
void set_gamma( mi::Float32 gamma) { m_gamma = gamma; }
private:
// Width of the canvas
mi::Uint32 m_width;
// Height of the canvas
mi::Uint32 m_height;
// Gamma value of the canvas
mi::Float32 m_gamma;
// The only tile of this canvas
};
// An advanced implementation of the IRender_target interface using the custom implementations
// of the abstract ICanvas and ITile interfaces above.
class Render_target : public mi::base::Interface_implement<mi::neuraylib::IRender_target>
{
public:
// Constructor.
//
// Creates a render target with a single canvas of the given width and height.
// This variant uses custom implementations for canvases and tiles that are defined above
// by the classes Tile and Canvas. In these implementations the pixel type is fixed to "Color"
// for simplicity.
Render_target( mi::Uint32 width, mi::Uint32 height)
{
m_canvas = new Canvas( width, height);
}
// Implement the interface of mi::neuraylib::IRender_target
mi::Uint32 get_canvas_count() const { return 1; }
mi::neuraylib::Canvas_type get_canvas_type( mi::Uint32 index) const
const mi::neuraylib::ICanvas_parameters* get_canvas_parameters( mi::Uint32) const
{ return 0; }
const mi::neuraylib::ICanvas* get_canvas( mi::Uint32 index) const
{
if( index > 0)
return 0;
m_canvas->retain();
return m_canvas.get();
}
mi::neuraylib::ICanvas* get_canvas( mi::Uint32 index)
{
if( index > 0)
return 0;
m_canvas->retain();
return m_canvas.get();
}
private:
// The only canvas of this render target
};
#endif // MI_EXAMPLE_RENDER_TARGET_ADVANCED_H
Handle class template for interfaces, automatizing the lifetime control via reference counting.
Definition: handle.h:113
Mixin class template for deriving interface implementations.
Definition: interface_implement.h:41
Abstract interface for render target canvas parameters.
Definition: irender_target.h:106
Abstract interface for a canvas represented by a rectangular array of tiles.
Definition: icanvas.h:85
Abstract interface for a tile.
Definition: itile.h:36
virtual Uint32 retain() const =0
Increments the reference count.
unsigned int Uint32
32-bit unsigned integer.
Definition: types.h:49
float Float32
32-bit float.
Definition: types.h:51
Canvas_type
The type of a canvas in an mi::neuraylib::IRender_target_base.
Definition: irender_target.h:32
@ TYPE_UNDEFINED
not a valid canvas type
Definition: irender_target.h:62
@ TYPE_RESULT
"Color" (includes alpha) or "Rgb_fp" result
Definition: irender_target.h:33
Iray SDK API.

Source Code Location: examples/example_progressive_rendering.cpp

/******************************************************************************
* Copyright 2023 NVIDIA Corporation. All rights reserved.
*****************************************************************************/
// examples/example_progressive_rendering.cpp
//
// Renders a scene in progressive rendering mode.
//
// The example expects the following command line arguments:
//
// example_progressive_rendering <scene_file> <mdl_path>
//
// scene_file some scene file, e.g., main.mi
// mdl_path path to the MDL modules, e.g., iray-<version>/mdl
//
// The rendered images are written to files named "example_progressive_rendering_00.png", etc.
#include <iomanip>
#include <iostream>
#include <sstream>
#include <mi/neuraylib.h>
// Include code shared by all examples.
#include "example_shared.h"
// Include an implementation of ITile, ICanvas, and IRender_target.
#include "example_render_target_advanced.h"
void configuration( mi::neuraylib::INeuray* neuray, const char* mdl_path)
{
// Configure the neuray library. Here we set the search path for .mdl files.
check_success( rc->add_mdl_path( mdl_path) == 0);
check_success( rc->add_mdl_path( ".") == 0);
// Load the OpenImageIO, Iray Photoreal, and .mi importer plugins.
check_success( pc->load_plugin_library( "nv_openimageio" MI_BASE_DLL_FILE_EXT) == 0);
check_success( pc->load_plugin_library( "libiray" MI_BASE_DLL_FILE_EXT) == 0);
check_success( pc->load_plugin_library( "mi_importer" MI_BASE_DLL_FILE_EXT) == 0);
}
void rendering( mi::neuraylib::INeuray* neuray, const char* scene_file)
{
// Get the database, the global scope of the database, and create a transaction in the global
// scope for importing the scene file and storing the scene.
check_success( database.is_valid_interface());
database->get_global_scope());
scope->create_transaction());
check_success( transaction.is_valid_interface());
// Import the scene file
check_success( import_api.is_valid_interface());
mi::base::Handle<const mi::IString> uri( import_api->convert_filename_to_uri( scene_file));
import_api->import_elements( transaction.get(), uri->get_c_str()));
check_success( import_result->get_error_number() == 0);
// Create the scene object
transaction->create<mi::neuraylib::IScene>( "Scene"));
scene->set_rootgroup( import_result->get_rootgroup());
scene->set_options( import_result->get_options());
scene->set_camera_instance( import_result->get_camera_inst());
transaction->store( scene.get(), "the_scene");
// Create the render context using the Iray Photoreal render mode
scene = transaction->edit<mi::neuraylib::IScene>( "the_scene");
scene->create_render_context( transaction.get(), "iray"));
check_success( render_context.is_valid_interface());
scene = 0;
// Render progressively at most 10 frames
for( mi::Size i = 0; i < 10; ++i) {
// Create the render target and render the i-th frame of the scene
new Render_target( 512, 384));
mi::Sint32 result = render_context->render( transaction.get(), render_target.get(), 0);
check_success( result >= 0);
// Write the image to disk
check_success( export_api.is_valid_interface());
mi::base::Handle<mi::neuraylib::ICanvas> canvas( render_target->get_canvas( 0));
std::ostringstream str;
str << "example_progressive_rendering_" << std::setw( 2) << std::setfill( '0') << i
<< ".png";
export_api->export_canvas( str.str().c_str(), canvas.get());
// Leave render loop if the termination criteria have been met
if( result > 0)
break;
}
// Pick the cube.
render_context->pick( transaction.get(), mi::Float32_2( 128, 192)));
std::cerr << "Picked objects:" << std::endl;
for( mi::Uint32 i = 0; i < pick_array->get_length(); ++i) {
mi::base::Handle<mi::neuraylib::IPick_result> pick_result( pick_array->get_pick_result( i));
mi::Float64_3 hit_point = pick_result->get_world_point();
std::cerr << "Object " << i << ": \"" << pick_result->get_picked_object_name() << "\", "
<< "hit point (" << hit_point.x << ", " << hit_point.y << ", " << hit_point.z << "), "
<< "path \"" << pick_result->get_path( 0) << "\"";
mi::Uint32 path_length = pick_result->get_path_length();
for( mi::Uint32 j = 1; j < path_length; ++j)
std::cerr << ", \"" << pick_result->get_path( j) << "\"";
std::cerr << std::endl;
}
transaction->commit();
}
int main( int argc, char* argv[])
{
// Collect command line parameters
if( argc != 3) {
std::cerr << "Usage: example_progressive_rendering <scene_file> <mdl_path>" << std::endl;
keep_console_open();
return EXIT_FAILURE;
}
const char* scene_file = argv[1];
const char* mdl_path = argv[2];
// Access the neuray library
mi::base::Handle<mi::neuraylib::INeuray> neuray( load_and_get_ineuray());
check_success( neuray.is_valid_interface());
// Configure the neuray library
configuration( neuray.get(), mdl_path);
// Start the neuray library
mi::Sint32 result = neuray->start();
check_start_success( result);
// Do the actual rendering
rendering( neuray.get(), scene_file);
// Shut down the neuray library
check_success( neuray->shutdown() == 0);
neuray = 0;
// Unload the neuray library
check_success( unload());
keep_console_open();
return EXIT_SUCCESS;
}
Fixed-size math vector class template with generic operations.
Definition: vector.h:286
This interface is used to interact with the distributed database.
Definition: idatabase.h:293
This interface is used to export files.
Definition: iexport_api.h:38
This interface is used to import files.
Definition: iimport_api.h:100
This is an object representing the Iray library.
Definition: ineuray.h:44
virtual Sint32 shutdown(bool blocking=true)=0
Shuts down the library.
virtual base::IInterface * get_api_component(const base::Uuid &uuid) const =0
Returns an API component from the Iray SDK API.
virtual Sint32 start(bool blocking=true)=0
Starts the operation of the Iray library.
This interface is used to load plugins and to query information about loaded plugins.
Definition: iplugin_configuration.h:24
This interface is used to query and change the rendering configuration.
Definition: irendering_configuration.h:109
The scene is the top-level element describing a subset of DB elements to be rendered.
Definition: iscene.h:44
#define MI_BASE_DLL_FILE_EXT
The operating system specific default filename extension for shared libraries (DLLs)
Definition: config.h:340
Uint64 Size
Unsigned integral type that is large enough to hold the size of all types.
Definition: types.h:112
signed int Sint32
32-bit signed integer.
Definition: types.h:46
[Previous] [Next] [Up]