Skip to content

Commit

Permalink
Replace Max Samples by Max Average SPP in interactive mode
Browse files Browse the repository at this point in the history
Intended to be a first step towards exposing samples, samples per pixel, and time-based rendering constraints: appleseedhq#1508.
  • Loading branch information
wilimitis authored and dictoon committed Mar 25, 2019
1 parent d001eba commit 43a48f9
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 32 deletions.
97 changes: 82 additions & 15 deletions src/appleseed.studio/mainwindow/renderingsettingswindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ class RenderSettingsPanel
: public FoldablePanelWidget
{
public:
RenderSettingsPanel(const QString& title, QWidget* parent = nullptr)
explicit RenderSettingsPanel(const QString& title, QWidget* parent = nullptr)
: FoldablePanelWidget(title, parent)
, m_params_metadata(Configuration::get_metadata())
{
Expand Down Expand Up @@ -420,7 +420,7 @@ namespace
Q_OBJECT

public:
GeneralSettingsPanel(const Configuration& config, QWidget* parent = nullptr)
explicit GeneralSettingsPanel(const Configuration& config, QWidget* parent = nullptr)
: RenderSettingsPanel("General Settings", parent)
{
QFormLayout* layout = create_form_layout();
Expand All @@ -444,17 +444,27 @@ namespace
};

//
// Image Plane Sampling panel.
// Image Plane Sampling panels.
//

class ImagePlaneSamplingPanel
: public RenderSettingsPanel
{
public:
explicit ImagePlaneSamplingPanel(QWidget* parent = nullptr)
: RenderSettingsPanel("Image Plane Sampling", parent)
{
}
};

class FinalImagePlaneSamplingPanel
: public ImagePlaneSamplingPanel
{
Q_OBJECT

public:
ImagePlaneSamplingPanel(const Configuration& config, QWidget* parent = nullptr)
: RenderSettingsPanel("Image Plane Sampling", parent)
explicit FinalImagePlaneSamplingPanel(const Configuration& config, QWidget* parent = nullptr)
: ImagePlaneSamplingPanel(parent)
{
QVBoxLayout* layout = new QVBoxLayout();
container()->setLayout(layout);
Expand Down Expand Up @@ -652,6 +662,59 @@ namespace
}
};

class InteractiveImagePlaneSamplingPanel
: public ImagePlaneSamplingPanel
{
Q_OBJECT

public:
explicit InteractiveImagePlaneSamplingPanel(const Configuration& config, QWidget* parent = nullptr)
: ImagePlaneSamplingPanel(parent)
{
QVBoxLayout* layout = new QVBoxLayout();
container()->setLayout(layout);

create_image_plane_sampling_general_settings(layout);

load_general_sampler(config);
}

void save_config(Configuration& config) const override
{
if (get_widget<bool>("general.unlimited_samples"))
config.get_parameters().remove_path("progressive_frame_renderer.max_average_spp");
else set_config(config, "progressive_frame_renderer.max_average_spp", get_widget<int>("general.max_average_spp"));
}

private:
void create_image_plane_sampling_general_settings(QVBoxLayout* parent)
{
QGroupBox* groupbox = new QGroupBox("General");
parent->addWidget(groupbox);

QVBoxLayout* layout = new QVBoxLayout();
groupbox->setLayout(layout);

QFormLayout* sublayout = create_form_layout();
layout->addLayout(sublayout);

QSpinBox* max_average_spp = create_integer_input("general.max_average_spp", 1, 1000000, 10);
QCheckBox* unlimited_samples = create_checkbox("general.unlimited_samples", "Unlimited");
sublayout->addRow("Max Average Samples Per Pixel:", create_horizontal_group(max_average_spp, unlimited_samples));
connect(unlimited_samples, SIGNAL(toggled(bool)), max_average_spp, SLOT(setDisabled(bool)));
}

void load_general_sampler(const Configuration& config)
{
const int DefaultMaxSamples = 64;

const int max_average_spp = get_config<int>(config, "progressive_frame_renderer.max_average_spp", -1);

set_widget("general.unlimited_samples", max_average_spp == -1);
set_widget("general.max_average_spp", max_average_spp == -1 ? DefaultMaxSamples : max_average_spp);
}
};

//
// Lighting panels.
//
Expand All @@ -660,7 +723,7 @@ namespace
: public RenderSettingsPanel
{
public:
LightingPanel(const Configuration& config, QWidget* parent = nullptr)
explicit LightingPanel(const Configuration& config, QWidget* parent = nullptr)
: RenderSettingsPanel("Lighting", parent)
{
}
Expand Down Expand Up @@ -688,7 +751,7 @@ namespace
: public LightingPanel
{
public:
FinalConfigurationLightingPanel(const Configuration& config, QWidget* parent = nullptr)
explicit FinalConfigurationLightingPanel(const Configuration& config, QWidget* parent = nullptr)
: LightingPanel(config, parent)
{
QComboBox* combobox = create_combobox("engine");
Expand All @@ -704,7 +767,7 @@ namespace
: public LightingPanel
{
public:
InteractiveConfigurationLightingPanel(const Configuration& config, QWidget* parent = nullptr)
explicit InteractiveConfigurationLightingPanel(const Configuration& config, QWidget* parent = nullptr)
: LightingPanel(config, parent)
{
QComboBox* combobox = create_combobox("engine");
Expand All @@ -722,7 +785,7 @@ namespace
: public RenderSettingsPanel
{
public:
LightingEnginePanel(const QString& title, QWidget* parent = nullptr)
explicit LightingEnginePanel(const QString& title, QWidget* parent = nullptr)
: RenderSettingsPanel(title, parent)
{
}
Expand Down Expand Up @@ -880,7 +943,7 @@ namespace
: public LightingEnginePanel
{
public:
UnidirectionalPathTracerPanel(const Configuration& config, QWidget* parent = nullptr)
explicit UnidirectionalPathTracerPanel(const Configuration& config, QWidget* parent = nullptr)
: LightingEnginePanel("Unidirectional Path Tracer", parent)
{
fold();
Expand Down Expand Up @@ -1098,7 +1161,7 @@ namespace
: public LightingEnginePanel
{
public:
SPPMPanel(const Configuration& config, QWidget* parent = nullptr)
explicit SPPMPanel(const Configuration& config, QWidget* parent = nullptr)
: LightingEnginePanel("Stochastic Progressive Photon Mapping", parent)
{
fold();
Expand Down Expand Up @@ -1522,12 +1585,16 @@ void RenderingSettingsWindow::create_panels(const Configuration& config)

m_panels.push_back(new GeneralSettingsPanel(config));

if (!interactive)
m_panels.push_back(new ImagePlaneSamplingPanel(config));

if (interactive)
{
m_panels.push_back(new InteractiveImagePlaneSamplingPanel(config));
m_panels.push_back(new InteractiveConfigurationLightingPanel(config));
else m_panels.push_back(new FinalConfigurationLightingPanel(config));
}
else
{
m_panels.push_back(new FinalImagePlaneSamplingPanel(config));
m_panels.push_back(new FinalConfigurationLightingPanel(config));
}

m_panels.push_back(new UnidirectionalPathTracerPanel(config));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,10 @@ namespace
const ParamArray& params)
: m_project(project)
, m_params(params)
, m_sample_counter(m_params.m_max_sample_count)
, m_sample_counter(
m_params.m_max_average_spp < numeric_limits<uint64>::max()
? m_params.m_max_average_spp * project.get_frame()->get_crop_window().volume()
: m_params.m_max_average_spp)
, m_ref_image_avg_lum(0.0)
{
// We must have a generator factory, but it's OK not to have a callback factory.
Expand Down Expand Up @@ -193,16 +196,16 @@ namespace
" spectrum mode %s\n"
" sampling mode %s\n"
" rendering threads %s\n"
" max samples %s\n"
" max average samples per pixel %s\n"
" max fps %f\n"
" collect performance stats %s\n"
" collect luminance stats %s",
get_spectrum_mode_name(m_params.m_spectrum_mode).c_str(),
get_sampling_context_mode_name(m_params.m_sampling_mode).c_str(),
pretty_uint(m_params.m_thread_count).c_str(),
m_params.m_max_sample_count == numeric_limits<uint64>::max()
m_params.m_max_average_spp == numeric_limits<uint64>::max()
? "unlimited"
: pretty_uint(m_params.m_max_sample_count).c_str(),
: pretty_uint(m_params.m_max_average_spp).c_str(),
m_params.m_max_fps,
m_params.m_perf_stats ? "on" : "off",
m_params.m_luminance_stats ? "on" : "off");
Expand Down Expand Up @@ -268,7 +271,6 @@ namespace
*m_project.get_frame(),
*m_buffer.get(),
m_tile_callback.get(),
m_params.m_max_sample_count,
m_params.m_max_fps,
m_display_thread_abort_switch));
m_display_thread.reset(
Expand Down Expand Up @@ -362,17 +364,17 @@ namespace
{
const Spectrum::Mode m_spectrum_mode;
const SamplingContext::Mode m_sampling_mode;
const size_t m_thread_count; // number of rendering threads
const uint64 m_max_sample_count; // maximum total number of samples to compute
const double m_max_fps; // maximum display frequency in frames/second
const bool m_perf_stats; // collect and print performance statistics?
const bool m_luminance_stats; // collect and print luminance statistics?
const size_t m_thread_count; // number of rendering threads
const uint64 m_max_average_spp; // maximum average number of samples to compute per pixel
const double m_max_fps; // maximum display frequency in frames/second
const bool m_perf_stats; // collect and print performance statistics?
const bool m_luminance_stats; // collect and print luminance statistics?

explicit Parameters(const ParamArray& params)
: m_spectrum_mode(get_spectrum_mode(params))
, m_sampling_mode(get_sampling_context_mode(params))
, m_thread_count(get_rendering_thread_count(params))
, m_max_sample_count(params.get_optional<uint64>("max_samples", numeric_limits<uint64>::max()))
, m_max_average_spp(params.get_optional<uint64>("max_average_spp", numeric_limits<uint64>::max()))
, m_max_fps(params.get_optional<double>("max_fps", 30.0))
, m_perf_stats(params.get_optional<bool>("performance_statistics", false))
, m_luminance_stats(params.get_optional<bool>("luminance_statistics", false))
Expand All @@ -392,13 +394,12 @@ namespace
Frame& frame,
SampleAccumulationBuffer& buffer,
ITileCallback* tile_callback,
const uint64 max_sample_count,
const double max_fps,
IAbortSwitch& abort_switch)
: m_frame(frame)
, m_buffer(buffer)
, m_tile_callback(tile_callback)
, m_min_sample_count(min<uint64>(max_sample_count, 32 * 32 * 2))
, m_min_sample_count(min<uint64>(frame.get_crop_window().volume(), 32 * 32 * 2))
, m_target_elapsed(1.0 / max_fps)
, m_abort_switch(abort_switch)
{
Expand Down Expand Up @@ -734,11 +735,13 @@ Dictionary ProgressiveFrameRendererFactory::get_params_metadata()
.insert("help", "Maximum progressive rendering update rate in frames per second"));

metadata.dictionaries().insert(
"max_samples",
"max_average_spp",
Dictionary()
.insert("type", "int")
.insert("label", "Max Samples")
.insert("help", "Maximum number of samples per pixel"));
.insert("default", "64")
.insert("unlimited", "true")
.insert("label", "Max Average Samples Per Pixel")
.insert("help", "Maximum number of average samples per pixel"));

return metadata;
}
Expand Down
50 changes: 50 additions & 0 deletions src/appleseed/renderer/modeling/project/projectfileupdater.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
// Standard headers.
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
Expand Down Expand Up @@ -2017,6 +2018,54 @@ namespace
}
}
};


//
// Update from revision 30 to revision 31.
//

class UpdateFromRevision_30
: public Updater
{
public:
explicit UpdateFromRevision_30(Project& project)
: Updater(project, 30)
{
}

void update() override
{
replace_max_samples_interactive_renderer_setting();
}

private:
void replace_max_samples_interactive_renderer_setting()
{
for (Configuration& config : m_project.configurations())
{
Dictionary& root = config.get_parameters();

if (root.dictionaries().exist("progressive_frame_renderer"))
{
Dictionary& pfr = root.dictionaries().get("progressive_frame_renderer");

if (pfr.strings().exist("max_samples"))
{
const uint64 max_samples = pfr.strings().get<uint64>("max_samples");
pfr.strings().remove("max_samples");

Frame* frame = m_project.get_frame();
if (frame)
{
// If max samples was previously set then preserve the nearest max average spp count.
pfr.strings().insert(
"max_average_spp", static_cast<uint64>(ceil(max_samples / frame->get_crop_window().volume())));
}
}
}
}
}
};
}

bool ProjectFileUpdater::update(
Expand Down Expand Up @@ -2079,6 +2128,7 @@ void ProjectFileUpdater::update(
CASE_UPDATE_FROM_REVISION(27);
CASE_UPDATE_FROM_REVISION(28);
CASE_UPDATE_FROM_REVISION(29);
CASE_UPDATE_FROM_REVISION(30);

case ProjectFormatRevision:
// Project is up-to-date.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,6 @@ namespace renderer
// when you increment this value.
//

const size_t ProjectFormatRevision = 30;
const size_t ProjectFormatRevision = 31;

} // namespace renderer

0 comments on commit 43a48f9

Please sign in to comment.