neuray API Programmer's Manual

Example for Progressive rendering

[Previous] [Next] [Up]

This example renders a scene progressively.

New Topics

  • Progressive rendering of a scene

Detailed Description

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. First, after the scene has been imported, progressive rendering is enabled via the progressive_rendering attribute on the options. In this example the rt_bsp renderer is explicitly selected, since not all renderers support progressive rendering. Since we use separate transactions later, the current transaction is committed.

The rendering of the single frames happens in a loop. Each iteration uses a distinct transaction. The rendering itself is 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 5 `\ls -1 *.png | sort -n` 

See INVALID_DOXYREFmi::IOptions for further attributes related to progressive rendering, in particular see sample_sequence_offset. Since the rt_bsp and iray renderers internally maintain such a counter the creation of this attribute and its modification in each iterations has been omitted from this example.

Source Code Location: examples/example_progressive_rendering.cpp

‎/******************************************************************************
 * Copyright 1986, 2011 NVIDIA Corporation. All rights reserved.
 *****************************************************************************/

// examples/example_progressive_rendering.cpp
//
// Renders a scene in progressive rendering mode.

#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.h"

void configuration( mi::base::Handle< mi::neuraylib::INeuray> neuray, const char* shader_path)
{
    // Configure the neuray library. Here we set some paths needed by the renderer.
    mi::base::Handle< mi::neuraylib::IRendering_configuration> rendering_configuration(
        neuray->get_api_component<mi::neuraylib::IRendering_configuration>());
    check_success( rendering_configuration.is_valid_interface());
    check_success( rendering_configuration->add_shader_path( shader_path) == 0);

    // Load the FreeImage image plugin and the LLVM backend for MetaSL.
    mi::base::Handle< mi::neuraylib::IPlugin_configuration> plugin_configuration(
        neuray->get_api_component<mi::neuraylib::IPlugin_configuration>());
#ifndef MI_PLATFORM_WINDOWS
    check_success( plugin_configuration->load_plugin_library( "freeimage.so") == 0);
    check_success( plugin_configuration->load_plugin_library( "gen_llvm.so") == 0);
#else
    check_success( plugin_configuration->load_plugin_library( "freeimage.dll") == 0);
    check_success( plugin_configuration->load_plugin_library( "gen_llvm.dll") == 0);
#endif
}

void rendering( mi::base::Handle< mi::neuraylib::INeuray> neuray,
                const char* scene_file)
{
    // Get the database, the global scope, which is the root for all transactions,
    // and create a transaction for importing the scene file and storing the scene.
    mi::base::Handle< mi::neuraylib::IDatabase> database(
        neuray->get_api_component<mi::neuraylib::IDatabase>());
    check_success( database.is_valid_interface());
    mi::base::Handle< mi::neuraylib::IScope> scope(
        database->get_global_scope());
    mi::base::Handle< mi::neuraylib::ITransaction> transaction(
        scope->create_transaction());
    check_success( transaction.is_valid_interface());

    // Import the scene file
    mi::base::Handle< mi::neuraylib::IImport_api> import_api(
        neuray->get_api_component<mi::neuraylib::IImport_api>());
    check_success( import_api.is_valid_interface());
    mi::base::Handle< const mi::IImport_result> import_result(
        import_api->import_elements( transaction.get(), scene_file));
    check_success( import_result->get_error_number() == 0);

    // Enable progressive rendering on the global options
    mi::base::Handle< mi::IOptions> options( transaction->edit<INVALID_DOXYREFmi::IOptions>(
        import_result->get_options()));
    mi::base::Handle< mi::IBoolean> progressive_rendering(
        options->create_attribute<mi::IBoolean>( "progressive_rendering", "Boolean"));
    progressive_rendering->set_value( true);
    progressive_rendering = 0;
    options = 0;

    // Create the scene object
    mi::base::Handle< mi::neuraylib::IScene> scene(
        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 rt_bsp renderer
    scene = transaction->edit<mi::neuraylib::IScene>( "the_scene");
    mi::base::Handle< mi::neuraylib::IRender_context> render_context(
        scene->get_render_context( transaction.get(), "rt_bsp"));
    scene = 0;
    transaction->commit();

    // Render progressively 50 frames
    for( mi::Size i = 0; i < 50; ++i) {
        
        transaction = scope->create_transaction();

        // Create the render target and render the i-th frame of the scene
        Render_target render_target( 512, 384);
        check_success( render_context->render( transaction.get(), &render_target, NULL) == 0);

        // Write the image to disk
        mi::base::Handle< mi::neuraylib::IExport_api> export_api(
            neuray->get_api_component<mi::neuraylib::IExport_api>());
        check_success( export_api.is_valid_interface());
        mi::base::Handle< mi::neuraylib::ICanvas> canvas( render_target.get_canvas( 0));
        std::ostringstream str;
        str << i << ".png";
        export_api->export_canvas( str.str().c_str(), canvas.get(), 100);

        transaction->commit();
    }
}

// The example takes the following command line arguments:
//
//   example_progressive_rendering <scene_file> <shader_path>
//
// scene_file       some scene file
// shader_path      path to the shaders, e.g., neuray-<version>/shaders
//
// The rendered images are written to files named "0.png", "1.png", etc.
//
int main( int argc, char* argv[])
{
    // Collect command line parameters
    if( argc != 3) {
        std::cerr << "Usage: example_progressive_rendering <scene_file> <shader_path>" << std::endl;
        return EXIT_FAILURE;
    }
    const char* scene_file  = argv[1];
    const char* shader_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, shader_path);

    // Start the neuray library
    check_success( neuray->start( true) == 0);

    // Do the actual rendering
    rendering( neuray, scene_file);

    // Shut down the neuray library
    check_success( neuray->shutdown() == 0);
    neuray = 0;

    // Unload the neuray library
    check_success( unload());

    return EXIT_SUCCESS;
}

[Previous] [Next] [Up]