diff --git a/sandbox/tests/unit tests/inputs/test_projectfilereader_configurationblocks.appleseed b/sandbox/tests/unit tests/inputs/test_projectfilereader_configurationblocks.appleseed index f44b5fed22..93c8b93523 100644 --- a/sandbox/tests/unit tests/inputs/test_projectfilereader_configurationblocks.appleseed +++ b/sandbox/tests/unit tests/inputs/test_projectfilereader_configurationblocks.appleseed @@ -1,5 +1,5 @@ - + diff --git a/src/appleseed.studio/mainwindow/renderingsettingswindow.cpp b/src/appleseed.studio/mainwindow/renderingsettingswindow.cpp index 102a5dc526..bd5ae9c34e 100644 --- a/src/appleseed.studio/mainwindow/renderingsettingswindow.cpp +++ b/src/appleseed.studio/mainwindow/renderingsettingswindow.cpp @@ -467,12 +467,10 @@ namespace create_direct_link("uniform_sampler.samples", "uniform_pixel_renderer.samples"); create_direct_link("uniform_sampler.force_antialiasing", "uniform_pixel_renderer.force_antialiasing"); create_direct_link("uniform_sampler.decorrelate_pixels", "uniform_pixel_renderer.decorrelate_pixels"); - create_direct_link("uniform_sampler.enable_diagnostics", "uniform_pixel_renderer.enable_diagnostics"); create_direct_link("adaptive_sampler.min_samples", "adaptive_pixel_renderer.min_samples"); create_direct_link("adaptive_sampler.max_samples", "adaptive_pixel_renderer.max_samples"); create_direct_link("adaptive_sampler.quality", "adaptive_pixel_renderer.quality"); - create_direct_link("adaptive_sampler.enable_diagnostics", "adaptive_pixel_renderer.enable_diagnostics"); load_directly_linked_values(config); } @@ -555,10 +553,6 @@ namespace m_uniform_sampler_decorrelate_pixels->setToolTip(m_params_metadata.get_path("uniform_pixel_renderer.decorrelate_pixels.help")); layout->addWidget(m_uniform_sampler_decorrelate_pixels); - QCheckBox* enable_diagnostics = create_checkbox("uniform_sampler.enable_diagnostics", "Enable Diagnostic AOVs"); - enable_diagnostics->setToolTip(m_params_metadata.get_path("uniform_pixel_renderer.enable_diagnostics.help")); - layout->addWidget(enable_diagnostics); - connect( m_image_plane_sampler_passes, SIGNAL(valueChanged(const int)), SLOT(slot_changed_image_plane_sampler_passes(const int))); @@ -586,10 +580,6 @@ namespace QDoubleSpinBox* quality = create_double_input("adaptive_sampler.quality", -20.0, +20.0, 2, 0.5); quality->setToolTip(m_params_metadata.get_path("adaptive_pixel_renderer.quality.help")); sublayout->addRow("Quality:", quality); - - QCheckBox* enable_diagnostics = create_checkbox("adaptive_sampler.enable_diagnostics", "Enable Diagnostic AOVs"); - enable_diagnostics->setToolTip(m_params_metadata.get_path("adaptive_pixel_renderer.enable_diagnostics.help")); - layout->addWidget(enable_diagnostics); } private slots: diff --git a/src/appleseed/CMakeLists.txt b/src/appleseed/CMakeLists.txt index 9367474a92..22ada19440 100644 --- a/src/appleseed/CMakeLists.txt +++ b/src/appleseed/CMakeLists.txt @@ -1399,6 +1399,8 @@ set (renderer_modeling_aov_sources renderer/modeling/aov/denoiseraov.h renderer/modeling/aov/depthaov.cpp renderer/modeling/aov/depthaov.h + renderer/modeling/aov/diagnosticaov.cpp + renderer/modeling/aov/diagnosticaov.h renderer/modeling/aov/diffuseaov.cpp renderer/modeling/aov/diffuseaov.h renderer/modeling/aov/emissionaov.cpp diff --git a/src/appleseed/renderer/api/aov.h b/src/appleseed/renderer/api/aov.h index 2e7edf966a..adabecd688 100644 --- a/src/appleseed/renderer/api/aov.h +++ b/src/appleseed/renderer/api/aov.h @@ -37,6 +37,7 @@ #include "renderer/modeling/aov/aovfactoryregistrar.h" #include "renderer/modeling/aov/aovtraits.h" #include "renderer/modeling/aov/depthaov.h" +#include "renderer/modeling/aov/diagnosticaov.h" #include "renderer/modeling/aov/diffuseaov.h" #include "renderer/modeling/aov/emissionaov.h" #include "renderer/modeling/aov/glossyaov.h" diff --git a/src/appleseed/renderer/kernel/aov/tilestack.h b/src/appleseed/renderer/kernel/aov/tilestack.h index 8638a547e2..4525653051 100644 --- a/src/appleseed/renderer/kernel/aov/tilestack.h +++ b/src/appleseed/renderer/kernel/aov/tilestack.h @@ -62,6 +62,12 @@ class TileStack const size_t i, const foundation::Color4f& color) const; + foundation::Tile& get_tile( + const size_t index); + + const foundation::Tile& get_tile( + const size_t index) const; + private: foundation::Tile* m_tiles[MaxAOVCount]; size_t m_size; @@ -99,6 +105,20 @@ inline void TileStack::set_pixel( m_tiles[i]->set_pixel(x, y, color); } +inline foundation::Tile& TileStack::get_tile( + const size_t index) +{ + assert(index < m_size); + return *m_tiles[index]; +} + +inline const foundation::Tile& TileStack::get_tile( + const size_t index) const +{ + assert(index < m_size); + return *m_tiles[index]; +} + } // namespace renderer #endif // !APPLESEED_RENDERER_KERNEL_AOV_TILESTACK_H diff --git a/src/appleseed/renderer/kernel/rendering/final/adaptivepixelrenderer.cpp b/src/appleseed/renderer/kernel/rendering/final/adaptivepixelrenderer.cpp index 1e25d670dc..01822cbd14 100644 --- a/src/appleseed/renderer/kernel/rendering/final/adaptivepixelrenderer.cpp +++ b/src/appleseed/renderer/kernel/rendering/final/adaptivepixelrenderer.cpp @@ -42,6 +42,7 @@ #include "renderer/kernel/rendering/pixelrendererbase.h" #include "renderer/kernel/rendering/shadingresultframebuffer.h" #include "renderer/kernel/shading/shadingresult.h" +#include "renderer/modeling/aov/aov.h" #include "renderer/modeling/frame/frame.h" #include "renderer/utility/settingsparsing.h" @@ -86,22 +87,14 @@ namespace ISampleRendererFactory* factory, const ParamArray& params, const size_t thread_index) - : PixelRendererBase(frame, thread_index, params) + : PixelRendererBase() , m_params(params) , m_sample_renderer(factory->create(thread_index)) + , m_sample_aov_tile(nullptr) + , m_variation_aov_tile(nullptr) { - if (are_diagnostics_enabled()) - { - m_variation_aov_index = frame.create_extra_aov_image("variation"); - m_samples_aov_index = frame.create_extra_aov_image("samples"); - - if ((thread_index == 0) && (m_variation_aov_index == ~size_t(0) || m_samples_aov_index == ~size_t(0))) - { - RENDERER_LOG_WARNING( - "could not create some of the diagnostic aovs, maximum number of aovs (" FMT_SIZE_T ") reached.", - MaxAOVCount); - } - } + m_variation_aov_index = frame.aovs().get_index("pixel_variation"); + m_sample_aov_index = frame.aovs().get_index("pixel_sample"); } void release() override @@ -115,22 +108,27 @@ namespace "adaptive pixel renderer settings:\n" " min samples %s\n" " max samples %s\n" - " max variation %f\n" - " diagnostics %s", + " max variation %f", pretty_uint(m_params.m_min_samples).c_str(), pretty_uint(m_params.m_max_samples).c_str(), - m_params.m_max_variation, - are_diagnostics_enabled() ? "on" : "off"); + m_params.m_max_variation); m_sample_renderer->print_settings(); } void on_tile_begin( const Frame& frame, + const size_t tile_x, + const size_t tile_y, Tile& tile, TileStack& aov_tiles) override { - PixelRendererBase::on_tile_begin(frame, tile, aov_tiles); + PixelRendererBase::on_tile_begin( + frame, + tile_x, + tile_y, + tile, + aov_tiles); m_scratch_fb_half_width = truncate(ceil(frame.get_filter().get_xradius())); m_scratch_fb_half_height = truncate(ceil(frame.get_filter().get_yradius())); @@ -142,40 +140,29 @@ namespace frame.aov_images().size(), frame.get_filter())); - if (are_diagnostics_enabled()) - { - m_diagnostics.reset(new Tile( - tile.get_width(), tile.get_height(), 2, PixelFormatFloat)); - } + if (m_sample_aov_index != ~size_t(0)) + m_sample_aov_tile = &frame.aovs().get_by_index(m_sample_aov_index)->get_image().tile(tile_x, tile_y); + + if (m_variation_aov_index != ~size_t(0)) + m_variation_aov_tile = &frame.aovs().get_by_index(m_variation_aov_index)->get_image().tile(tile_x, tile_y); } void on_tile_end( const Frame& frame, + const size_t tile_x, + const size_t tile_y, Tile& tile, TileStack& aov_tiles) override { - PixelRendererBase::on_tile_end(frame, tile, aov_tiles); - - if (are_diagnostics_enabled()) - { - const size_t width = tile.get_width(); - const size_t height = tile.get_height(); - - for (size_t y = 0; y < height; ++y) - { - for (size_t x = 0; x < width; ++x) - { - Color values; - m_diagnostics->get_pixel(x, y, values); - - if (m_variation_aov_index != ~size_t(0)) - aov_tiles.set_pixel(x, y, m_variation_aov_index, scalar_to_color(values[0])); - - if (m_samples_aov_index != ~size_t(0)) - aov_tiles.set_pixel(x, y, m_samples_aov_index, scalar_to_color(values[1])); - } - } - } + PixelRendererBase::on_tile_end( + frame, + tile_x, + tile_y, + tile, + aov_tiles); + + m_sample_aov_tile = nullptr; + m_variation_aov_tile = nullptr; } void render_pixel( @@ -293,28 +280,29 @@ namespace } // Store diagnostics values in the diagnostics tile. - if (are_diagnostics_enabled() && tile_bbox.contains(pt)) + if ((m_sample_aov_tile || m_variation_aov_tile) && tile_bbox.contains(pt)) { - Color values; - - values[0] = - saturate( - max( - trackers[0].get_variation(), - trackers[1].get_variation(), - trackers[2].get_variation()) - / m_params.m_max_variation); - - values[1] = - m_params.m_min_samples == m_params.m_max_samples - ? 1.0f - : fit( - static_cast(trackers[0].get_size()), - static_cast(m_params.m_min_samples), - static_cast(m_params.m_max_samples), - 0.0f, 1.0f); - - m_diagnostics->set_pixel(pt.x, pt.y, values); + Color3f value(0.0f, 0.0f, 0.0f); + + if (m_sample_aov_tile) + { + value[0] = trackers[0].get_size(); + + m_sample_aov_tile->set_pixel(pt.x, pt.y, value); + } + + if (m_variation_aov_tile) + { + value[0] = + saturate( + max( + trackers[0].get_variation(), + trackers[1].get_variation(), + trackers[2].get_variation()) + / m_params.m_max_variation); + + m_variation_aov_tile->set_pixel(pt.x, pt.y, value); + } } on_pixel_end(pi, pt, tile_bbox, aov_accumulators); @@ -350,18 +338,12 @@ namespace const Parameters m_params; auto_release_ptr m_sample_renderer; size_t m_variation_aov_index; - size_t m_samples_aov_index; + size_t m_sample_aov_index; int m_scratch_fb_half_width; int m_scratch_fb_half_height; unique_ptr m_scratch_fb; - unique_ptr m_diagnostics; - - static Color4f scalar_to_color(const float value) - { - static const Color4f Blue(0.0f, 0.0f, 1.0f, 1.0f); - static const Color4f Red(1.0f, 0.0f, 0.0f, 1.0f); - return lerp(Blue, Red, saturate(value)); - } + Tile* m_sample_aov_tile; + Tile* m_variation_aov_tile; }; } @@ -397,7 +379,7 @@ IPixelRenderer* AdaptivePixelRendererFactory::create( Dictionary AdaptivePixelRendererFactory::get_params_metadata() { - Dictionary metadata = PixelRendererBaseFactory::get_params_metadata(); + Dictionary metadata; metadata.dictionaries().insert( "min_samples", diff --git a/src/appleseed/renderer/kernel/rendering/final/adaptivepixelrenderer.h b/src/appleseed/renderer/kernel/rendering/final/adaptivepixelrenderer.h index 1029e4f50b..0df01b178d 100644 --- a/src/appleseed/renderer/kernel/rendering/final/adaptivepixelrenderer.h +++ b/src/appleseed/renderer/kernel/rendering/final/adaptivepixelrenderer.h @@ -31,7 +31,7 @@ #define APPLESEED_RENDERER_KERNEL_RENDERING_FINAL_ADAPTIVEPIXELRENDERER_H // appleseed.renderer headers. -#include "renderer/kernel/rendering/pixelrendererbase.h" +#include "renderer/kernel/rendering/ipixelrenderer.h" #include "renderer/utility/paramarray.h" // appleseed.foundation headers. @@ -53,7 +53,7 @@ namespace renderer // class AdaptivePixelRendererFactory - : public PixelRendererBaseFactory + : public IPixelRendererFactory { public: // Constructor. diff --git a/src/appleseed/renderer/kernel/rendering/final/uniformpixelrenderer.cpp b/src/appleseed/renderer/kernel/rendering/final/uniformpixelrenderer.cpp index 794c23ee5e..17186bf6e2 100644 --- a/src/appleseed/renderer/kernel/rendering/final/uniformpixelrenderer.cpp +++ b/src/appleseed/renderer/kernel/rendering/final/uniformpixelrenderer.cpp @@ -79,7 +79,7 @@ namespace ISampleRendererFactory* factory, const ParamArray& params, const size_t thread_index) - : PixelRendererBase(frame, thread_index, params) + : PixelRendererBase() , m_params(params) , m_sample_renderer(factory->create(thread_index)) , m_sample_count(m_params.m_samples) @@ -113,12 +113,10 @@ namespace "uniform pixel renderer settings:\n" " samples %s\n" " force antialiasing %s\n" - " decorrelate pixels %s\n" - " diagnostics %s", + " decorrelate pixels %s", pretty_uint(m_params.m_samples).c_str(), m_params.m_force_aa ? "on" : "off", - m_params.m_decorrelate ? "on" : "off", - are_diagnostics_enabled() ? "on" : "off"); + m_params.m_decorrelate ? "on" : "off"); m_sample_renderer->print_settings(); } @@ -324,7 +322,7 @@ IPixelRenderer* UniformPixelRendererFactory::create( Dictionary UniformPixelRendererFactory::get_params_metadata() { - Dictionary metadata = PixelRendererBaseFactory::get_params_metadata(); + Dictionary metadata; metadata.dictionaries().insert( "samples", diff --git a/src/appleseed/renderer/kernel/rendering/final/uniformpixelrenderer.h b/src/appleseed/renderer/kernel/rendering/final/uniformpixelrenderer.h index f33b1c1b5b..b2e143f1a8 100644 --- a/src/appleseed/renderer/kernel/rendering/final/uniformpixelrenderer.h +++ b/src/appleseed/renderer/kernel/rendering/final/uniformpixelrenderer.h @@ -31,7 +31,7 @@ #define APPLESEED_RENDERER_KERNEL_RENDERING_FINAL_UNIFORMPIXELRENDERER_H // appleseed.renderer headers. -#include "renderer/kernel/rendering/pixelrendererbase.h" +#include "renderer/kernel/rendering/ipixelrenderer.h" #include "renderer/utility/paramarray.h" // appleseed.foundation headers. @@ -53,7 +53,7 @@ namespace renderer // class UniformPixelRendererFactory - : public PixelRendererBaseFactory + : public IPixelRendererFactory { public: // Constructor. diff --git a/src/appleseed/renderer/kernel/rendering/generic/generictilerenderer.cpp b/src/appleseed/renderer/kernel/rendering/generic/generictilerenderer.cpp index f3a66cbc40..c5ae676c94 100644 --- a/src/appleseed/renderer/kernel/rendering/generic/generictilerenderer.cpp +++ b/src/appleseed/renderer/kernel/rendering/generic/generictilerenderer.cpp @@ -157,9 +157,6 @@ namespace padded_tile_bbox.max.x = tile_bbox.max.x + m_margin_width; padded_tile_bbox.max.y = tile_bbox.max.y + m_margin_height; - // Inform the pixel renderer that we are about to render a tile. - m_pixel_renderer->on_tile_begin(frame, tile, aov_tiles); - // Inform the AOV accumulators that we are about to render a tile. m_aov_accumulators.on_tile_begin( frame, @@ -167,6 +164,14 @@ namespace tile_y, m_pixel_renderer->get_max_samples_per_pixel()); + // Inform the pixel renderer that we are about to render a tile. + m_pixel_renderer->on_tile_begin( + frame, + tile_x, + tile_y, + tile, + aov_tiles); + // Create the framebuffer into which we will accumulate the samples. ShadingResultFrameBuffer* framebuffer = m_framebuffer_factory->create( @@ -219,11 +224,16 @@ namespace // Release the framebuffer. m_framebuffer_factory->destroy(framebuffer); + // Inform the pixel renderer that we are done rendering the tile. + m_pixel_renderer->on_tile_end( + frame, + tile_x, + tile_y, + tile, + aov_tiles); + // Inform the AOV accumulators that we are done rendering a tile. m_aov_accumulators.on_tile_end(frame, tile_x, tile_y); - - // Inform the pixel renderer that we are done rendering the tile. - m_pixel_renderer->on_tile_end(frame, tile, aov_tiles); } StatisticsVector get_statistics() const override diff --git a/src/appleseed/renderer/kernel/rendering/ipixelrenderer.h b/src/appleseed/renderer/kernel/rendering/ipixelrenderer.h index b9b206710a..787b7a7903 100644 --- a/src/appleseed/renderer/kernel/rendering/ipixelrenderer.h +++ b/src/appleseed/renderer/kernel/rendering/ipixelrenderer.h @@ -63,12 +63,16 @@ class IPixelRenderer // This method is called before a tile gets rendered. virtual void on_tile_begin( const Frame& frame, + const size_t tile_x, + const size_t tile_y, foundation::Tile& tile, TileStack& aov_tiles) = 0; // This method is called after a tile has been rendered. virtual void on_tile_end( const Frame& frame, + const size_t tile_x, + const size_t tile_y, foundation::Tile& tile, TileStack& aov_tiles) = 0; diff --git a/src/appleseed/renderer/kernel/rendering/pixelrendererbase.cpp b/src/appleseed/renderer/kernel/rendering/pixelrendererbase.cpp index 9a64963768..c13cade4f8 100644 --- a/src/appleseed/renderer/kernel/rendering/pixelrendererbase.cpp +++ b/src/appleseed/renderer/kernel/rendering/pixelrendererbase.cpp @@ -52,90 +52,28 @@ namespace renderer // PixelRendererBase class implementation. // -const uint8 NoState = 0; -const uint8 InvalidSample = 1; -const uint8 CorrectSample = 2; - -PixelRendererBase::PixelRendererBase( - const Frame& frame, - const size_t thread_index, - const ParamArray& params) - : m_params(params) - , m_invalid_pixel_count(0) - , m_invalid_sample_aov_index(~size_t(0)) +PixelRendererBase::PixelRendererBase() + : m_invalid_pixel_count(0) + , m_invalid_sample_count(0) { - if (m_params.m_diagnostics) - { - m_invalid_sample_aov_index = frame.create_extra_aov_image("invalid_samples"); - - if (m_invalid_sample_aov_index == ~size_t(0) && thread_index == 0) - { - RENDERER_LOG_WARNING( - "could not create invalid samples aov, maximum number of aovs (" FMT_SIZE_T ") reached.", - MaxAOVCount); - } - } -} - -bool PixelRendererBase::are_diagnostics_enabled() const -{ - return m_params.m_diagnostics; } void PixelRendererBase::on_tile_begin( const Frame& frame, + const size_t tile_x, + const size_t tile_y, Tile& tile, TileStack& aov_tiles) { - if (m_invalid_sample_aov_index != ~size_t(0)) - { - m_invalid_sample_diagnostic.reset( - new Tile(tile.get_width(), tile.get_height(), 1, PixelFormatUInt8)); - } } void PixelRendererBase::on_tile_end( const Frame& frame, + const size_t tile_x, + const size_t tile_y, Tile& tile, TileStack& aov_tiles) { - if (m_invalid_sample_aov_index != ~size_t(0)) - { - const size_t width = tile.get_width(); - const size_t height = tile.get_height(); - - for (size_t y = 0; y < height; ++y) - { - for (size_t x = 0; x < width; ++x) - { - Color sample_state; - m_invalid_sample_diagnostic->get_pixel(x, y, sample_state); - - Color4f color; - - switch (sample_state[0]) - { - case NoState: - color = Color4f(1.0f, 0.0f, 0.0f, 1.0f); - break; - - case InvalidSample: - color = Color4f(1.0f, 0.0f, 1.0f, 1.0f); - break; - - case CorrectSample: - tile.get_pixel(x, y, color); - color.rgb().set(0.2f * luminance(color.rgb())); // 20% of luminance - color.a = 1.0f; - break; - - assert_otherwise; - } - - aov_tiles.set_pixel(x, y, m_invalid_sample_aov_index, color); - } - } - } } void PixelRendererBase::on_pixel_begin( @@ -154,21 +92,20 @@ void PixelRendererBase::on_pixel_end( const AABB2i& tile_bbox, AOVAccumulatorContainer& aov_accumulators) { - aov_accumulators.on_pixel_end(pi); + static const size_t MaxWarningsPerThread = 5; - // todo: mark pixel as faulty in the diagnostic map. + aov_accumulators.on_pixel_end(pi); + // Warns the user for bad pixels. if (m_invalid_sample_count > 0) { - ++m_invalid_pixel_count; - - const size_t MaxWarningsPerThread = 5; + m_invalid_pixel_count++; if (m_invalid_pixel_count <= MaxWarningsPerThread) { RENDERER_LOG_WARNING( - FMT_SIZE_T " sample%s at pixel (%d, %d) had nan, negative or infinite components and %s ignored.", - m_invalid_sample_count, + "%s sample%s at pixel (%d, %d) had nan, negative or infinite components and %s ignored.", + pretty_uint(m_invalid_sample_count).c_str(), m_invalid_sample_count > 1 ? "s" : "", pi.x, pi.y, m_invalid_sample_count > 1 ? "were" : "was"); @@ -178,12 +115,6 @@ void PixelRendererBase::on_pixel_end( RENDERER_LOG_WARNING("more invalid samples found, omitting warning messages for brevity."); } } - - if (m_params.m_diagnostics && tile_bbox.contains(pt)) - { - m_invalid_sample_diagnostic->set_pixel(pt.x, pt.y, - m_invalid_sample_count > 0 ? &InvalidSample : &CorrectSample); - } } void PixelRendererBase::signal_invalid_sample() @@ -191,24 +122,4 @@ void PixelRendererBase::signal_invalid_sample() ++m_invalid_sample_count; } - -// -// PixelRendererBaseFactory class implementation. -// - -Dictionary PixelRendererBaseFactory::get_params_metadata() -{ - Dictionary metadata; - - metadata.dictionaries().insert( - "enable_diagnostics", - Dictionary() - .insert("type", "bool") - .insert("default", "false") - .insert("label", "Enable Diagnostics") - .insert("help", "Enable pixel renderer diagnostics")); - - return metadata; -} - } // namespace renderer diff --git a/src/appleseed/renderer/kernel/rendering/pixelrendererbase.h b/src/appleseed/renderer/kernel/rendering/pixelrendererbase.h index 65e096a4d9..a6b03f4328 100644 --- a/src/appleseed/renderer/kernel/rendering/pixelrendererbase.h +++ b/src/appleseed/renderer/kernel/rendering/pixelrendererbase.h @@ -62,22 +62,21 @@ class PixelRendererBase { public: // Constructor. - PixelRendererBase( - const Frame& frame, - const size_t thread_index, - const ParamArray& params); - - bool are_diagnostics_enabled() const; + PixelRendererBase(); // This method is called before a tile gets rendered. void on_tile_begin( const Frame& frame, + const size_t tile_x, + const size_t tile_y, foundation::Tile& tile, TileStack& aov_tiles) override; // This method is called after a tile has been rendered. void on_tile_end( const Frame& frame, + const size_t tile_x, + const size_t tile_y, foundation::Tile& tile, TileStack& aov_tiles) override; @@ -97,33 +96,8 @@ class PixelRendererBase void signal_invalid_sample(); private: - struct Parameters - { - const bool m_diagnostics; - - explicit Parameters(const ParamArray& params) - : m_diagnostics(params.get_optional("enable_diagnostics", false)) - { - } - }; - - size_t m_invalid_sample_count; - size_t m_invalid_pixel_count; - size_t m_invalid_sample_aov_index; - std::unique_ptr m_invalid_sample_diagnostic; - const Parameters m_params; -}; - - -// -// Pixel renderer base factory. -// - -class PixelRendererBaseFactory - : public IPixelRendererFactory -{ - public: - static foundation::Dictionary get_params_metadata(); + size_t m_invalid_pixel_count; + size_t m_invalid_sample_count; }; } // namespace renderer diff --git a/src/appleseed/renderer/modeling/aov/aov.cpp b/src/appleseed/renderer/modeling/aov/aov.cpp index d345f25f5e..44c7fd53aa 100644 --- a/src/appleseed/renderer/modeling/aov/aov.cpp +++ b/src/appleseed/renderer/modeling/aov/aov.cpp @@ -94,7 +94,7 @@ void AOV::clear_image() m_image->clear(Color4f(0.0f)); } -void AOV::post_process_image() +void AOV::post_process_image(const AABB2u& bbox) { } diff --git a/src/appleseed/renderer/modeling/aov/aov.h b/src/appleseed/renderer/modeling/aov/aov.h index f7cf34cb5a..f67d94762e 100644 --- a/src/appleseed/renderer/modeling/aov/aov.h +++ b/src/appleseed/renderer/modeling/aov/aov.h @@ -33,6 +33,7 @@ #include "renderer/modeling/entity/entity.h" // appleseed.foundation headers. +#include "foundation/math/aabb.h" #include "foundation/platform/compiler.h" #include "foundation/utility/autoreleaseptr.h" #include "foundation/utility/uid.h" @@ -90,7 +91,7 @@ class APPLESEED_DLLSYMBOL AOV virtual void clear_image(); // Apply any post processing needed to the AOV image. - virtual void post_process_image(); + virtual void post_process_image(const foundation::AABB2u& bbox); protected: friend class AOVAccumulatorContainer; diff --git a/src/appleseed/renderer/modeling/aov/aovfactoryregistrar.cpp b/src/appleseed/renderer/modeling/aov/aovfactoryregistrar.cpp index 5e5078223c..480db9378d 100644 --- a/src/appleseed/renderer/modeling/aov/aovfactoryregistrar.cpp +++ b/src/appleseed/renderer/modeling/aov/aovfactoryregistrar.cpp @@ -33,6 +33,7 @@ #include "renderer/modeling/aov/aovtraits.h" #include "renderer/modeling/aov/albedoaov.h" #include "renderer/modeling/aov/depthaov.h" +#include "renderer/modeling/aov/diagnosticaov.h" #include "renderer/modeling/aov/diffuseaov.h" #include "renderer/modeling/aov/emissionaov.h" #include "renderer/modeling/aov/glossyaov.h" @@ -89,8 +90,11 @@ void AOVFactoryRegistrar::reinitialize(const SearchPaths& search_paths) register_factory(auto_release_ptr(new GlossyAOVFactory())); register_factory(auto_release_ptr(new IndirectDiffuseAOVFactory())); register_factory(auto_release_ptr(new IndirectGlossyAOVFactory())); + register_factory(auto_release_ptr(new InvalidSampleAOVFactory())); register_factory(auto_release_ptr(new NormalAOVFactory())); + register_factory(auto_release_ptr(new PixelSampleAOVFactory())); register_factory(auto_release_ptr(new PixelTimeAOVFactory())); + register_factory(auto_release_ptr(new PixelVariationAOVFactory())); register_factory(auto_release_ptr(new UVAOVFactory())); register_factory(auto_release_ptr(new AlbedoAOVFactory())); diff --git a/src/appleseed/renderer/modeling/aov/diagnosticaov.cpp b/src/appleseed/renderer/modeling/aov/diagnosticaov.cpp new file mode 100644 index 0000000000..e16aeeadae --- /dev/null +++ b/src/appleseed/renderer/modeling/aov/diagnosticaov.cpp @@ -0,0 +1,501 @@ + +// +// This source file is part of appleseed. +// Visit https://appleseedhq.net/ for additional information and resources. +// +// This software is released under the MIT license. +// +// Copyright (c) 2018 Kevin Masson, The appleseedhq Organization +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +// Interface header. +#include "diagnosticaov.h" + +// appleseed.renderer headers. +#include "renderer/kernel/aov/aovaccumulator.h" +#include "renderer/kernel/aov/imagestack.h" +#include "renderer/kernel/rendering/pixelcontext.h" +#include "renderer/kernel/shading/shadingpoint.h" +#include "renderer/kernel/shading/shadingresult.h" +#include "renderer/modeling/aov/aov.h" +#include "renderer/modeling/frame/frame.h" + +// appleseed.foundation headers. +#include "foundation/image/color.h" +#include "foundation/image/image.h" +#include "foundation/image/tile.h" +#include "foundation/utility/api/apistring.h" +#include "foundation/utility/api/specializedapiarrays.h" +#include "foundation/utility/containers/dictionary.h" + +// Standard headers. +#include +#include + +using namespace foundation; +using namespace std; + +namespace renderer +{ + +namespace +{ + // + // Diagnostic AOV accumulator. + // + + class DiagnosticAOVAccumulator + : public AOVAccumulator + { + public: + DiagnosticAOVAccumulator() + { + } + }; + + // + // Invalid Sample AOV accumulator. + // + // + + const uint8 NoState = 0; + const uint8 InvalidSample = 1; + const uint8 CorrectSample = 2; + + class InvalidSampleAOVAccumulator + : public AOVAccumulator + { + public: + explicit InvalidSampleAOVAccumulator( + Image& image) + : m_image(image) + , m_invalid_sample_count(0) + { + } + + void on_tile_begin( + const Frame& frame, + const size_t tile_x, + const size_t tile_y, + const size_t max_spp) override + { + // Create a tile that stores samples hint. + const Tile& tile = frame.image().tile(tile_x, tile_y); + + m_invalid_sample_tile.reset( + new Tile(tile.get_width(), tile.get_height(), 1, PixelFormatUInt8)); + m_invalid_sample_tile->clear(Color(0)); + + const CanvasProperties& props = frame.image().properties(); + + m_tile_origin_x = static_cast(tile_x * props.m_tile_width); + m_tile_origin_y = static_cast(tile_y * props.m_tile_height); + m_tile_end_x = static_cast(m_tile_origin_x + m_invalid_sample_tile->get_width() - 1); + m_tile_end_y = static_cast(m_tile_origin_y + m_invalid_sample_tile->get_height() - 1); + } + + void on_tile_end( + const Frame& frame, + const size_t tile_x, + const size_t tile_y) override + { + // Fill the tile according to samples state. + const Tile& tile = frame.image().tile(tile_x, tile_y); + Tile& aov_tile = m_image.tile(tile_x, tile_y); + + const size_t width = tile.get_width(); + const size_t height = tile.get_height(); + + for (size_t y = 0; y < height; ++y) + { + for (size_t x = 0; x < width; ++x) + { + Color sample_state; + m_invalid_sample_tile->get_pixel(x, y, sample_state); + + Color3f color; + Color4f beauty_color; + + switch (sample_state[0]) + { + case NoState: + color = Color3f(1.0f, 0.0f, 0.0f); + break; + + case InvalidSample: + color = Color3f(1.0f, 0.0f, 1.0f); + break; + + case CorrectSample: + tile.get_pixel(x, y, beauty_color); + color.set(0.2f * luminance(beauty_color.rgb())); // 20% of luminance + break; + + assert_otherwise; + } + + aov_tile.set_pixel(x, y, color); + } + } + } + + void on_pixel_begin(const Vector2i& pi) override + { + m_invalid_sample_count = 0; + } + + void on_pixel_end(const Vector2i& pi) override + { + // Store a hint corresping to the sample state in the tile. + if (pi.x >= m_tile_origin_x && + pi.y >= m_tile_origin_y && + pi.x <= m_tile_end_x && + pi.y <= m_tile_end_y) + { + const Vector2i pt(pi.x - m_tile_origin_x, pi.y - m_tile_origin_y); + m_invalid_sample_tile->set_pixel(pt.x, pt.y, + m_invalid_sample_count > 0 ? &InvalidSample : &CorrectSample); + } + } + + void write( + const PixelContext& pixel_context, + const ShadingPoint& shading_point, + const ShadingComponents& shading_components, + const AOVComponents& aov_components, + ShadingResult& shading_result) override + { + // Detect invalid samples. + if (!shading_result.is_valid()) + m_invalid_sample_count++; + } + + private: + Image& m_image; + size_t m_invalid_sample_count; + std::unique_ptr m_invalid_sample_tile; + int m_tile_origin_x; + int m_tile_origin_y; + int m_tile_end_x; + int m_tile_end_y; + }; + + // + // Diagnostic AOV. + // + + class DiagnosticAOV + : public AOV + { + public: + explicit DiagnosticAOV(const char* name, const ParamArray& params) + : AOV(name, params) + { + } + + void release() override + { + delete this; + } + + size_t get_channel_count() const override + { + return 3; + } + + const char** get_channel_names() const override + { + static const char* ChannelNames[] = {"R", "G", "B"}; + return ChannelNames; + } + + bool has_color_data() const override + { + return false; + } + + void create_image( + const size_t canvas_width, + const size_t canvas_height, + const size_t tile_width, + const size_t tile_height, + ImageStack& aov_images) override + { + m_image = + new Image( + canvas_width, + canvas_height, + tile_width, + tile_height, + get_channel_count(), + PixelFormatFloat); + } + + void clear_image() override + { + m_image->clear(Color3f(0.0f, 0.0f, 0.0f)); + } + + auto_release_ptr create_accumulator() const override + { + return auto_release_ptr( + new DiagnosticAOVAccumulator()); + } + }; + + // + // Invalid Sample AOV. + // + + const char* Invalid_Sample_Model = "invalid_sample_aov"; + + class InvalidSampleAOV + : public DiagnosticAOV + { + public: + explicit InvalidSampleAOV(const ParamArray& params) + : DiagnosticAOV("invalid_sample", params) + { + } + + void release() override + { + delete this; + } + + const char* get_model() const override + { + return Invalid_Sample_Model; + } + + auto_release_ptr create_accumulator() const override + { + return auto_release_ptr( + new InvalidSampleAOVAccumulator(get_image())); + } + }; + + // + // Pixel Sample AOV. + // + + const char* Pixel_Sample_Model = "pixel_sample_aov"; + + class PixelSampleAOV + : public DiagnosticAOV + { + public: + explicit PixelSampleAOV(const ParamArray& params) + : DiagnosticAOV("pixel_sample", params) + { + } + + const char* get_model() const override + { + return Pixel_Sample_Model; + } + + void post_process_image(const AABB2u& bbox) override + { + static const Color3f Blue(0.0f, 0.0f, 1.0f); + static const Color3f Red(1.0f, 0.0f, 0.0f); + + // Find the maximum and minimum samples count. + float max_samples = std::numeric_limits::lowest(); + float min_samples = std::numeric_limits::max(); + + Color3f color; + + for (size_t j = bbox.min.y; j <= bbox.max.y; ++j) + { + for (size_t i = bbox.min.x; i < bbox.max.x; ++i) + { + m_image->get_pixel(i, j, color); + max_samples = max(color[0], max_samples); + min_samples = min(color[0], min_samples); + } + } + + if (max_samples < min_samples) + return; + + // Normalize. + for (size_t j = bbox.min.y; j <= bbox.max.y; ++j) + { + for (size_t i = bbox.min.x; i < bbox.max.x; ++i) + { + m_image->get_pixel(i, j, color); + + float c = fit(color[0], min_samples, max_samples, 0.0f, 1.0f); + + color = lerp(Blue, Red, saturate(c)); + m_image->set_pixel(i, j, color); + } + } + } + }; + + // + // Pixel Variation AOV. + // + + const char* Pixel_Variation_Model = "pixel_variation_aov"; + + class PixelVariationAOV + : public DiagnosticAOV + { + public: + explicit PixelVariationAOV(const ParamArray& params) + : DiagnosticAOV("pixel_variation", params) + { + } + + void post_process_image(const AABB2u& bbox) override + { + static const Color3f Blue(0.0f, 0.0f, 1.0f); + static const Color3f Red(1.0f, 0.0f, 0.0f); + + Color3f color; + + for (size_t j = bbox.min.y; j <= bbox.max.y; ++j) + { + for (size_t i = bbox.min.x; i < bbox.max.x; ++i) + { + m_image->get_pixel(i, j, color); + color = lerp(Blue, Red, saturate(color[0])); + m_image->set_pixel(i, j, color); + } + } + } + + const char* get_model() const override + { + return Pixel_Variation_Model; + } + }; +} + + +// +// InvalidSampleAOVFactory class implementation. +// + +void InvalidSampleAOVFactory::release() +{ + delete this; +} + +const char* InvalidSampleAOVFactory::get_model() const +{ + return Invalid_Sample_Model; +} + +Dictionary InvalidSampleAOVFactory::get_model_metadata() const +{ + return + Dictionary() + .insert("name", Invalid_Sample_Model) + .insert("label", "Invalid Sample"); +} + +DictionaryArray InvalidSampleAOVFactory::get_input_metadata() const +{ + DictionaryArray metadata; + return metadata; +} + +auto_release_ptr InvalidSampleAOVFactory::create( + const ParamArray& params) const +{ + return auto_release_ptr(new InvalidSampleAOV(params)); +} + + +// +// PixelSampleAOVFactory class implementation. +// + +void PixelSampleAOVFactory::release() +{ + delete this; +} + +const char* PixelSampleAOVFactory::get_model() const +{ + return Pixel_Sample_Model; +} + +Dictionary PixelSampleAOVFactory::get_model_metadata() const +{ + return + Dictionary() + .insert("name", Pixel_Sample_Model) + .insert("label", "Pixel Sample"); +} + +DictionaryArray PixelSampleAOVFactory::get_input_metadata() const +{ + DictionaryArray metadata; + return metadata; +} + +auto_release_ptr PixelSampleAOVFactory::create( + const ParamArray& params) const +{ + return auto_release_ptr(new PixelSampleAOV(params)); +} + + +// +// PixelVariationAOVFactory class implementation. +// + +void PixelVariationAOVFactory::release() +{ + delete this; +} + +const char* PixelVariationAOVFactory::get_model() const +{ + return Pixel_Variation_Model; +} + +Dictionary PixelVariationAOVFactory::get_model_metadata() const +{ + return + Dictionary() + .insert("name", Pixel_Variation_Model) + .insert("label", "Pixel Variation"); +} + +DictionaryArray PixelVariationAOVFactory::get_input_metadata() const +{ + DictionaryArray metadata; + return metadata; +} + +auto_release_ptr PixelVariationAOVFactory::create( + const ParamArray& params) const +{ + return auto_release_ptr(new PixelVariationAOV(params)); +} + +} // namespace renderer diff --git a/src/appleseed/renderer/modeling/aov/diagnosticaov.h b/src/appleseed/renderer/modeling/aov/diagnosticaov.h new file mode 100644 index 0000000000..ceaf0fbfe5 --- /dev/null +++ b/src/appleseed/renderer/modeling/aov/diagnosticaov.h @@ -0,0 +1,129 @@ + +// +// This source file is part of appleseed. +// Visit https://appleseedhq.net/ for additional information and resources. +// +// This software is released under the MIT license. +// +// Copyright (c) 2018 Kevin Masson, The appleseedhq Organization +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#ifndef APPLESEED_RENDERER_MODELING_AOV_DIAGNOSTICAOV_H +#define APPLESEED_RENDERER_MODELING_AOV_DIAGNOSTICAOV_H + +// appleseed.renderer headers. +#include "renderer/modeling/aov/iaovfactory.h" + +// appleseed.foundation headers. +#include "foundation/utility/autoreleaseptr.h" + +// appleseed.main headers. +#include "main/dllsymbol.h" + +// Forward declarations. +namespace foundation { class Dictionary; } +namespace foundation { class DictionaryArray; } +namespace renderer { class AOV; } +namespace renderer { class ParamArray; } + +namespace renderer +{ + +// +// A factory for invalid sample AOVs. +// + +class APPLESEED_DLLSYMBOL InvalidSampleAOVFactory + : public IAOVFactory +{ + public: + // Delete this instance. + void release() override; + + // Return a string identifying this AOV model. + const char* get_model() const override; + + // Return metadata for this AOV model. + foundation::Dictionary get_model_metadata() const override; + + // Return metadata for the inputs of this AOV model. + foundation::DictionaryArray get_input_metadata() const override; + + // Create a new AOV instance. + foundation::auto_release_ptr create( + const ParamArray& params) const override; +}; + + +// +// A factory for pixel sample AOVs. +// + +class APPLESEED_DLLSYMBOL PixelSampleAOVFactory + : public IAOVFactory +{ + public: + // Delete this instance. + void release() override; + + // Return a string identifying this AOV model. + const char* get_model() const override; + + // Return metadata for this AOV model. + foundation::Dictionary get_model_metadata() const override; + + // Return metadata for the inputs of this AOV model. + foundation::DictionaryArray get_input_metadata() const override; + + // Create a new AOV instance. + foundation::auto_release_ptr create( + const ParamArray& params) const override; +}; + + +// +// A factory for pixel variation AOVs. +// + +class APPLESEED_DLLSYMBOL PixelVariationAOVFactory + : public IAOVFactory +{ + public: + // Delete this instance. + void release() override; + + // Return a string identifying this AOV model. + const char* get_model() const override; + + // Return metadata for this AOV model. + foundation::Dictionary get_model_metadata() const override; + + // Return metadata for the inputs of this AOV model. + foundation::DictionaryArray get_input_metadata() const override; + + // Create a new AOV instance. + foundation::auto_release_ptr create( + const ParamArray& params) const override; +}; + +} // namespace renderer + +#endif // !APPLESEED_RENDERER_MODELING_AOV_DIAGNOSTICAOV_H diff --git a/src/appleseed/renderer/modeling/aov/pixeltimeaov.cpp b/src/appleseed/renderer/modeling/aov/pixeltimeaov.cpp index 4c19de03d9..d2a10b7f4e 100644 --- a/src/appleseed/renderer/modeling/aov/pixeltimeaov.cpp +++ b/src/appleseed/renderer/modeling/aov/pixeltimeaov.cpp @@ -218,16 +218,14 @@ namespace m_image->clear(Color(0.0f)); } - void post_process_image() override + void post_process_image(const AABB2u& bbox) override { - const CanvasProperties& src_props = m_image->properties(); - // Find the maximum value. float max_time = 0.0f; - for (size_t j = 0; j < src_props.m_canvas_height; ++j) + for (size_t j = bbox.min.y; j <= bbox.max.y; ++j) { - for (size_t i = 0; i < src_props.m_canvas_width; ++i) + for (size_t i = bbox.min.x; i < bbox.max.x; ++i) { float val; m_image->get_pixel(i, j, &val); @@ -241,9 +239,9 @@ namespace const float rcp_max_time = 1.0f / max_time; // Normalize. - for (size_t j = 0; j < src_props.m_canvas_height; ++j) + for (size_t j = bbox.min.y; j <= bbox.max.y; ++j) { - for (size_t i = 0; i < src_props.m_canvas_width; ++i) + for (size_t i = bbox.min.x; i < bbox.max.x; ++i) { float c; m_image->get_pixel(i, j, &c); diff --git a/src/appleseed/renderer/modeling/frame/frame.cpp b/src/appleseed/renderer/modeling/frame/frame.cpp index d19404dc59..732ea5a707 100644 --- a/src/appleseed/renderer/modeling/frame/frame.cpp +++ b/src/appleseed/renderer/modeling/frame/frame.cpp @@ -105,7 +105,6 @@ struct Frame::Impl AABB2u m_crop_window; ParamArray m_render_info; DenoisingMode m_denoising_mode; - bool m_save_extra_aovs; // Child entities. AOVContainer m_aovs; @@ -116,7 +115,6 @@ struct Frame::Impl unique_ptr m_image; unique_ptr m_aov_images; DenoiserAOV* m_denoiser_aov; - vector m_extra_aovs; }; Frame::Frame( @@ -217,8 +215,7 @@ void Frame::print_settings() " filter %s\n" " filter size %f\n" " crop window (%s, %s)-(%s, %s)\n" - " denoising mode %s\n" - " save extra aovs %s", + " denoising mode %s", get_path().c_str(), camera_name ? camera_name : "none", pretty_uint(impl->m_frame_width).c_str(), @@ -232,8 +229,7 @@ void Frame::print_settings() pretty_uint(impl->m_crop_window.max[0]).c_str(), pretty_uint(impl->m_crop_window.max[1]).c_str(), impl->m_denoising_mode == DenoisingMode::Off ? "off" : - impl->m_denoising_mode == DenoisingMode::WriteOutputs ? "write outputs" : "denoise", - impl->m_save_extra_aovs ? "on" : "off"); + impl->m_denoising_mode == DenoisingMode::WriteOutputs ? "write outputs" : "denoise"); } AOVContainer& Frame::aovs() const @@ -280,20 +276,6 @@ const AOVContainer& Frame::internal_aovs() const return impl->m_internal_aovs; } -size_t Frame::create_extra_aov_image(const char* name) const -{ - const size_t index = aov_images().get_index(name); - - if (index == ~size_t(0) && aov_images().size() < MaxAOVCount) - { - const size_t add_index = aov_images().append(name, 4, PixelFormatFloat); - impl->m_extra_aovs.push_back(add_index); - return add_index; - } - - return index; -} - const Filter2f& Frame::get_filter() const { return *impl->m_filter.get(); @@ -378,10 +360,10 @@ bool Frame::on_frame_begin( void Frame::post_process_aov_images() const { for (size_t i = 0, e = aovs().size(); i < e; ++i) - aovs().get_by_index(i)->post_process_image(); + aovs().get_by_index(i)->post_process_image(get_crop_window()); for (size_t i = 0, e = internal_aovs().size(); i < e; ++i) - internal_aovs().get_by_index(i)->post_process_image(); + internal_aovs().get_by_index(i)->post_process_image(get_crop_window()); } ParamArray& Frame::render_info() @@ -738,25 +720,6 @@ bool Frame::write_aov_images(const char* file_path) const success = false; } - if (impl->m_save_extra_aovs) - { - for (size_t i = 0, e = impl->m_extra_aovs.size(); i < e; ++i) - { - const size_t image_index = impl->m_extra_aovs[i]; - const Image& image = aov_images().get_image(image_index); - - // Compute AOV image file path. - const string aov_name = aov_images().get_name(image_index); - const string safe_aov_name = make_safe_filename(aov_name); - const string aov_file_name = base_file_name + "." + safe_aov_name + ".exr"; - const string aov_file_path = (directory / aov_file_name).string(); - - // Write AOV image. - if (!write_image(aov_file_path.c_str(), image)) - success = false; - } - } - return success; } @@ -850,21 +813,6 @@ void Frame::write_main_and_aov_images_to_multipart_exr(const char* file_path) co writer.append_part(aov_name.c_str(), image, image_attributes, aov->get_channel_count(), aov->get_channel_names()); } - if (impl->m_save_extra_aovs) - { - for (size_t i = 0, e = impl->m_extra_aovs.size(); i < e; ++i) - { - const size_t image_index = impl->m_extra_aovs[i]; - assert(image_index < aov_images().size()); - - const Image& image = aov_images().get_image(image_index); - const CanvasProperties& props = image.properties(); - const string aov_name = aov_images().get_name(image_index); - assert(props.m_channel_count == 4); - writer.append_part(aov_name.c_str(), image, image_attributes, props.m_channel_count, ChannelNames); - } - } - create_parent_directories(file_path); writer.write_multipart_exr(file_path); @@ -995,9 +943,6 @@ void Frame::extract_parameters() impl->m_denoising_mode = DenoisingMode::Off; } } - - // Retrieve save extra AOVs parameter - impl->m_save_extra_aovs = m_params.get_optional("save_extra_aovs", false); } @@ -1188,14 +1133,6 @@ DictionaryArray FrameFactory::get_input_metadata() Dictionary() .insert("denoiser", "on"))); - metadata.push_back( - Dictionary() - .insert("name", "save_extra_aovs") - .insert("label", "Save Extra AOVs") - .insert("type", "boolean") - .insert("use", "optional") - .insert("default", "false")); - return metadata; } diff --git a/src/appleseed/renderer/modeling/frame/frame.h b/src/appleseed/renderer/modeling/frame/frame.h index 9cbf9271a1..1ec62fa87f 100644 --- a/src/appleseed/renderer/modeling/frame/frame.h +++ b/src/appleseed/renderer/modeling/frame/frame.h @@ -107,9 +107,6 @@ class APPLESEED_DLLSYMBOL Frame // Access the AOV images. ImageStack& aov_images() const; - // Create an extra AOV image if it does not exist. - size_t create_extra_aov_image(const char* name) const; - // Return the reconstruction filter used by the main image and the AOV images. const foundation::Filter2f& get_filter() const; diff --git a/src/appleseed/renderer/modeling/project/projectfileupdater.cpp b/src/appleseed/renderer/modeling/project/projectfileupdater.cpp index 9fc24c01f8..c6eb5c4aae 100644 --- a/src/appleseed/renderer/modeling/project/projectfileupdater.cpp +++ b/src/appleseed/renderer/modeling/project/projectfileupdater.cpp @@ -1786,6 +1786,55 @@ namespace params.remove_path("render_stamp_format"); } }; + + // + // Update from revision 26 to revision 27. + // + + class UpdateFromRevision_26 + : public Updater + { + public: + explicit UpdateFromRevision_26(Project& project) + : Updater(project, 26) + { + } + + void update() override + { + remove_diagnostic_option(); + } + + private: + // Remove pixel_renderer::enable_diagnostics and frame::save_extra_aovs. + void remove_diagnostic_option() + { + for (each i = m_project.configurations(); i; ++i) + { + Dictionary& root = i->get_parameters(); + + if (root.dictionaries().exist("uniform_pixel_renderer")) + { + Dictionary& upr = root.dictionary("uniform_pixel_renderer"); + upr.strings().remove("enable_diagnostics"); + } + + if (root.dictionaries().exist("adaptive_pixel_renderer")) + { + Dictionary& apr = root.dictionary("adaptive_pixel_renderer"); + apr.strings().remove("enable_diagnostics"); + } + } + + Frame* frame = m_project.get_frame(); + + if (frame == nullptr) + return; + + ParamArray& frame_params = frame->get_parameters(); + frame_params.strings().remove("save_extra_aovs"); + } + }; } bool ProjectFileUpdater::update( @@ -1844,6 +1893,7 @@ void ProjectFileUpdater::update( CASE_UPDATE_FROM_REVISION(23); CASE_UPDATE_FROM_REVISION(24); CASE_UPDATE_FROM_REVISION(25); + CASE_UPDATE_FROM_REVISION(26); case ProjectFormatRevision: // Project is up-to-date. diff --git a/src/appleseed/renderer/modeling/project/projectformatrevision.h b/src/appleseed/renderer/modeling/project/projectformatrevision.h index d230c2bbb5..698f2433bd 100644 --- a/src/appleseed/renderer/modeling/project/projectformatrevision.h +++ b/src/appleseed/renderer/modeling/project/projectformatrevision.h @@ -39,7 +39,7 @@ namespace renderer // when you increment this value. // -const size_t ProjectFormatRevision = 26; +const size_t ProjectFormatRevision = 27; } // namespace renderer