Own canvas class
This topic introduces:
- example_render_target_advanced.h, which demonstrates how to set up a custom rendering infrastructure when the default rendering infrastructure is not sufficient for your needs
Customized rendering infrastructure
To render a scene, you have to provide some rendering infrastructure for the Iray API. Basically, you have to provide buffers where the rendered image is written to. These buffers are defined by the interfaces mi::neuraylib::IRender_target, mi::neuraylib::ICanvas, and mi::neuraylib::ITile.
Most of the example programs shipped with Iray use internal default implementations. However, the example for progressive rendering demonstrates an advanced way of providing the required rendering infrastructure by using custom implementations of the interfaces mi::neuraylib::ICanvas and mi::neuraylib::ITile and the corresponding classes Canvas and Tile. Those implementations are in their own include file shown below. For simplicity, the only supported pixel type is Color, that is, one float per channel.
You can see the cancas class in use in:
example_render_target_advanced.h
001 /****************************************************************************** 002 * © 1986, 2014 NVIDIA Corporation. All rights reserved. 003 *****************************************************************************/ 004 005 // examples/example_render_target_advanced.h 006 // 007 // Code shared by some rendering examples 008 009 #ifndef EXAMPLE_RENDER_TARGET_ADVANCED_H 010 #define EXAMPLE_RENDER_TARGET_ADVANCED_H 011 012 #include <mi/neuraylib.h> 013 014 // A simple implementation of the ITile interface with pixel type "Color". 015 // 016 // This implementation is for educational purposes. Being able to supply your own implementation 017 // of the ICanvas and ITile interfaces might be advantageous depending on the context. If you do 018 // not have any special needs you can simply use the default implementation available via 019 // mi::neuraylib::IImage_api::create_tile(). 020 class Tile : public mi::base::Interface_implement<mi::neuraylib::ITile> 021 { 022 public: 023 // Constructor. 024 // 025 // Creates a tile of the given width and height with pixel type "Color". 026 Tile( mi::Uint32 width, mi::Uint32 height) 027 { 028 m_width = width; 029 m_height = height; 030 m_data = new mi::Float32[m_width * m_height * 4]; 031 } 032 033 // Destructor 034 ~Tile() { delete[] m_data; } 035 036 // Implement the interface of mi::neuraylib::ITile 037 void set_pixel( mi::Uint32 x_offset, mi::Uint32 y_offset, const mi::Float32* floats) 038 { 039 mi::Float32* position = &m_data[(x_offset + y_offset * m_width) * 4]; 040 position[0] = floats[0]; 041 position[1] = floats[1]; 042 position[2] = floats[2]; 043 position[3] = floats[3]; 044 } 045 void get_pixel( mi::Uint32 x_offset, mi::Uint32 y_offset, mi::Float32* floats) const 046 { 047 mi::Float32* position = &m_data[(x_offset + y_offset * m_width) * 4]; 048 floats[0] = position[0]; 049 floats[1] = position[1]; 050 floats[2] = position[2]; 051 floats[3] = position[3]; 052 } 053 const char* get_type() const { return "Color"; } 054 mi::Uint32 get_resolution_x() const { return m_width; } 055 mi::Uint32 get_resolution_y() const { return m_height; } 056 const void* get_data() const { return m_data; } 057 void* get_data() { return m_data; } 058 059 private: 060 // Width of the tile 061 mi::Uint32 m_width; 062 // Height of the tile 063 mi::Uint32 m_height; 064 // The data of this tile, 32 bytes per pixel 065 mi::Float32* m_data; 066 }; 067 068 // A simple implementation of the ICanvas interface with a single tile with pixel type "Color". 069 // 070 // This implementation is for educational purposes. Being able to supply your own implementation 071 // of the ICanvas and ITile interfaces might be advantageous depending on the context. If you do 072 // not have any special needs you can simply use the default implementation available via 073 // mi::neuraylib::IImage_api::create_canvas(). 074 class Canvas : public mi::base::Interface_implement<mi::neuraylib::ICanvas> 075 { 076 public: 077 // Constructor. 078 // 079 // Creates a canvas with a single tile of the given width and height. 080 Canvas( mi::Uint32 width, mi::Uint32 height) 081 { 082 m_width = width; 083 m_height = height; 084 m_gamma = 1.0f; 085 m_tile = new Tile( width, height); 086 } 087 088 // Implement the interface of mi::neuraylib::ICanvas 089 mi::Uint32 get_resolution_x() const { return m_width; } 090 mi::Uint32 get_resolution_y() const { return m_height; } 091 mi::Uint32 get_tile_resolution_x() const { return m_width; } 092 mi::Uint32 get_tile_resolution_y() const { return m_height; } 093 mi::Uint32 get_tiles_size_x() const { return 1; } 094 mi::Uint32 get_tiles_size_y() const { return 1; } 095 mi::Uint32 get_layers_size() const { return 1; } 096 const mi::neuraylib::ITile* get_tile( 097 mi::Uint32 pixel_x, mi::Uint32 pixel_y, mi::Uint32 layer = 0) const 098 { 099 if( pixel_x >= m_width || pixel_y >= m_height || layer > 0) 100 return 0; 101 m_tile->retain(); 102 return m_tile.get(); 103 } 104 mi::neuraylib::ITile* get_tile( 105 mi::Uint32 pixel_x, mi::Uint32 pixel_y, mi::Uint32 layer = 0) 106 { 107 if( pixel_x >= m_width || pixel_y >= m_height || layer > 0) 108 return 0; 109 m_tile->retain(); 110 return m_tile.get(); 111 } 112 const char* get_type( mi::Uint32 layer) const { return layer == 0 ? "Color" : 0; } 113 mi::Float32 get_gamma() const { return m_gamma; } 114 void set_gamma( mi::Float32 gamma) { m_gamma = gamma; } 115 116 private: 117 // Width of the canvas 118 mi::Uint32 m_width; 119 // Height of the canvas 120 mi::Uint32 m_height; 121 // Gamma value of the canvas 122 mi::Float32 m_gamma; 123 // The only tile of this canvas 124 mi::base::Handle<mi::neuraylib::ITile> m_tile; 125 }; 126 127 // An advanced implementation of the IRender_target interface using the custom implementations 128 // of the abstract ICanvas and ITile interfaces above. 129 class Render_target : public mi::base::Interface_implement<mi::neuraylib::IRender_target> 130 { 131 public: 132 // Constructor. 133 // 134 // Creates a render target with a single canvas of the given width and height. 135 // This variant uses custom implementations for canvases and tiles that are defined above 136 // by the classes Tile and Canvas. In these implementations the pixel type is fixed to "Color" 137 // for simplicity. 138 Render_target( mi::Uint32 width, mi::Uint32 height) 139 { 140 m_canvas = new Canvas( width, height); 141 } 142 143 // Implement the interface of mi::neuraylib::IRender_target 144 mi::Uint32 get_canvas_count() const { return 1; } 145 const char* get_canvas_name( mi::Uint32 index) const { return index == 0 ? "result" : 0; } 146 const mi::neuraylib::ICanvas* get_canvas( mi::Uint32 index) const 147 { 148 if( index > 0) 149 return 0; 150 m_canvas->retain(); 151 return m_canvas.get(); 152 } 153 mi::neuraylib::ICanvas* get_canvas( mi::Uint32 index) 154 { 155 if( index > 0) 156 return 0; 157 m_canvas->retain(); 158 return m_canvas.get(); 159 } 160 161 private: 162 // The only canvas of this render target 163 mi::base::Handle<mi::neuraylib::ICanvas> m_canvas; 164 }; 165 166 #endif // MI_EXAMPLE_RENDER_TARGET_ADVANED_H