Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Light path expressions #2868

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
487 changes: 487 additions & 0 deletions sandbox/tests/test scenes/aovs/06 - LPE aov.appleseed

Large diffs are not rendered by default.

12,106 changes: 12,106 additions & 0 deletions sandbox/tests/test scenes/aovs/glass_sphere.obj

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/appleseed.bench/mainwindow/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -837,7 +837,7 @@ void MainWindow::slot_open_project_complete(const QString& filepath, const bool
ParamArray frame_params = frame->get_parameters();
frame_params.insert("resolution", "128 128");
frame_params.insert("tile_size", "16 16");
project->set_frame(FrameFactory::create(frame->get_name(), frame_params, frame->aovs()));
project->set_frame(FrameFactory::create(frame->get_name(), frame_params, frame->aovs(), frame->lpe_aovs()));
#endif

m_rendering_time_display->set_rendering_timer(&m_project_manager.get_project()->get_rendering_timer());
Expand Down
3 changes: 2 additions & 1 deletion src/appleseed.cli/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,8 @@ namespace
FrameFactory::create(
frame->get_name(),
new_params,
frame->aovs());
frame->aovs(),
frame->lpe_aovs());

// Recreate post-processing stages.
for (PostProcessingStage& stage : frame->post_processing_stages())
Expand Down
5 changes: 3 additions & 2 deletions src/appleseed.python/bindframe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,10 @@ namespace
auto_release_ptr<Frame> create_frame_with_aovs(
const std::string& name,
const bpy::dict& params,
const AOVContainer& aovs)
const AOVContainer& aovs,
const AOVContainer& lpe_aovs)
{
return FrameFactory::create(name.c_str(), bpy_dict_to_param_array(params), aovs);
return FrameFactory::create(name.c_str(), bpy_dict_to_param_array(params), aovs, lpe_aovs);
}

bpy::object archive_frame(const Frame* frame, const char* directory)
Expand Down
2 changes: 1 addition & 1 deletion src/appleseed.studio/mainwindow/project/projectbuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ Frame* ProjectBuilder::edit_frame(
const size_t old_canvas_width = old_frame->image().properties().m_canvas_width;
const size_t old_canvas_height = old_frame->image().properties().m_canvas_height;

auto_release_ptr<Frame> new_frame = FrameFactory::create(name.c_str(), clean_values, old_frame->aovs());
auto_release_ptr<Frame> new_frame = FrameFactory::create(name.c_str(), clean_values, old_frame->aovs(), old_frame->lpe_aovs());
new_frame->post_processing_stages().swap(old_frame->post_processing_stages());
const size_t new_canvas_width = new_frame->image().properties().m_canvas_width;
const size_t new_canvas_height = new_frame->image().properties().m_canvas_height;
Expand Down
2 changes: 2 additions & 0 deletions src/appleseed/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1565,6 +1565,8 @@ set (renderer_modeling_aov_sources
renderer/modeling/aov/iaovfactory.h
renderer/modeling/aov/invalidsamplesaov.cpp
renderer/modeling/aov/invalidsamplesaov.h
renderer/modeling/aov/lpeaov.cpp
renderer/modeling/aov/lpeaov.h
renderer/modeling/aov/normalaov.cpp
renderer/modeling/aov/normalaov.h
renderer/modeling/aov/npraovs.cpp
Expand Down
1 change: 1 addition & 0 deletions src/appleseed/foundation/platform/path.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "boost/filesystem/exception.hpp"
#include "boost/filesystem/operations.hpp"
#include "boost/filesystem/path.hpp"
#include "boost/filesystem/exception.hpp"

// Standard headers.
#include <cassert>
Expand Down
73 changes: 73 additions & 0 deletions src/appleseed/renderer/kernel/aov/aovaccumulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,27 @@

// appleseed.renderer headers.
#include "renderer/global/globaltypes.h"
#include "renderer/kernel/aov/aovcomponents.h"
#include "renderer/kernel/shading/shadingcomponents.h"
#include "renderer/modeling/aov/aov.h"
#include "renderer/modeling/aov/lpeaov.h"
#include "renderer/modeling/frame/frame.h"
#include "renderer/modeling/color/colorspace.h"

// appleseed.foundation headers.
#include "foundation/image/canvasproperties.h"
#include "foundation/image/image.h"
#include "foundation/image/tile.h"

// OSL headers.
#include "OSL/oslclosure.h"

// Standard headers.
#include <cassert>
#include <cstring>

#include <iostream>

using namespace foundation;

namespace renderer
Expand Down Expand Up @@ -149,6 +158,18 @@ void UnfilteredAOVAccumulator::on_tile_end(
}


//
// PixelInfo structure to pass pixel information to LPE AOV.
//

struct PixelInfo
{
size_t px;
size_t py;
size_t sample_count;
};


//
// AOVAccumulatorContainer class implementation.
//
Expand All @@ -175,6 +196,27 @@ AOVAccumulatorContainer::AOVAccumulatorContainer(const Frame& frame)
const AOV* aov = frame.internal_aovs().get_by_index(i);
insert(aov->create_accumulator());
}

// Add custom LPE events and scattering types.
m_automata.addEventType(OSL::ustring("X"));

// Create accumulators for LPE AOVs if there is any.
if (frame.lpe_aovs().size() > 0)
{
for (size_t i = 0, e = frame.lpe_aovs().size(); i < e; ++i)
{
const LPEAOV* aov = static_cast<LPEAOV*>(frame.lpe_aovs().get_by_index(i));
m_automata.addRule(aov->get_rule_string(), i);
}
m_automata.compile();

m_accum_ptr = std::unique_ptr<OSL::Accumulator>(new OSL::Accumulator(&m_automata));
for (size_t i = 0, e = frame.lpe_aovs().size(); i < e; ++i)
{
const LPEAOV* aov = static_cast<LPEAOV*>(frame.lpe_aovs().get_by_index(i));
m_accum_ptr->setAov(i, aov->get_wrapped_aov(), false, false);
}
}
}

void AOVAccumulatorContainer::init()
Expand Down Expand Up @@ -220,20 +262,37 @@ void AOVAccumulatorContainer::on_pixel_end(
{
for (size_t i = 0, e = m_size; i < e; ++i)
m_accumulators[i]->on_pixel_end(pi);

if (m_accum_ptr)
{
PixelInfo pixel_info{static_cast<size_t>(pi.x), static_cast<size_t>(pi.y), 0};
m_accum_ptr->end(&pixel_info);
}
}

void AOVAccumulatorContainer::on_sample_begin(
const PixelContext& pixel_context)
{
for (size_t i = 0, e = m_size; i < e; ++i)
m_accumulators[i]->on_sample_begin(pixel_context);

if (m_accum_ptr)
{
m_accum_ptr->begin();
m_accum_ptr->pushState();
}
}

void AOVAccumulatorContainer::on_sample_end(
const PixelContext& pixel_context)
{
for (size_t i = 0, e = m_size; i < e; ++i)
m_accumulators[i]->on_sample_end(pixel_context);

if (m_accum_ptr)
{
m_accum_ptr->popState();
}
}

void AOVAccumulatorContainer::write(
Expand All @@ -252,6 +311,20 @@ void AOVAccumulatorContainer::write(
aov_components,
shading_result);
}

if (m_accum_ptr)
{
for (const auto& event : aov_components.m_lpe_events)
{
for (const auto c : event) {
m_accum_ptr->move(OSL::ustring(&c, 1));
}
m_accum_ptr->move(OSL::Labels::STOP);
}

Color3f color = shading_components.m_beauty.illuminance_to_rgb(g_std_lighting_conditions);
m_accum_ptr->accum(OSL::Color3(color.r, color.g, color.b));
}
}

bool AOVAccumulatorContainer::insert(auto_release_ptr<AOVAccumulator> aov_accum)
Expand Down
6 changes: 6 additions & 0 deletions src/appleseed/renderer/kernel/aov/aovaccumulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
#include "foundation/math/vector.h"
#include "foundation/memory/autoreleaseptr.h"

// OSL headers.
#include "OSL/accum.h"

// Standard headers.
#include <cstddef>

Expand Down Expand Up @@ -200,6 +203,9 @@ class AOVAccumulatorContainer

size_t m_size;
AOVAccumulator* m_accumulators[MaxAOVAccumulatorCount];

OSL::AccumAutomata m_automata;
std::unique_ptr<OSL::Accumulator> m_accum_ptr;
};

} // namespace renderer
13 changes: 10 additions & 3 deletions src/appleseed/renderer/kernel/aov/aovcomponents.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,22 @@
// appleseed.foundation headers.
#include "foundation/image/color.h"

// OSL headers.
#include "OSL/accum.h"

// standard headers.
#include <vector>

namespace renderer
{

class AOVComponents
{
public:
Spectrum m_albedo;
foundation::Color3f m_npr_shading;
foundation::Color4f m_npr_contour;
Spectrum m_albedo;
foundation::Color3f m_npr_shading;
foundation::Color4f m_npr_contour;
std::vector<OIIO::ustring> m_lpe_events;

// Constructor. Clears all components to 0.
AOVComponents();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,12 @@ namespace
void on_scatter(PathVertex& vertex)
{
}

// This function is added for consistence with pt engine interface and it will
// be called in the path tracer, do nothing here.
void on_terminate(const TerminateType& terminate_type)
{
}
};

struct VolumeVisitor
Expand Down
127 changes: 127 additions & 0 deletions src/appleseed/renderer/kernel/lighting/lightpathstream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ void LightPathStream::hit_reflector(const PathVertex& vertex)
data.m_object_instance = &vertex.m_shading_point->get_object_instance();
data.m_vertex_position = Vector3f(vertex.get_point());
data.m_path_throughput = vertex.m_throughput.illuminance_to_rgb(g_std_lighting_conditions);
data.m_crossing_interface = vertex.m_crossing_interface;
data.m_scattering_type = vertex.m_prev_mode;
m_hit_reflector_data.push_back(data);
}

Expand Down Expand Up @@ -190,6 +192,37 @@ void LightPathStream::sampled_environment(
m_sampled_env_data.push_back(data);
}

void LightPathStream::sampled_volume(const bool is_homogeneous)
{
Event event;
event.m_type = EventType::SampledVolume;
event.m_data_index = static_cast<std::uint8_t>(m_sampled_volume_data.size());
m_events.push_back(event);

SampledVolumeData data;
data.m_is_homogeneous = is_homogeneous;
m_sampled_volume_data.push_back(data);
}

void LightPathStream::terminate(const TerminateType& terminate_type)
{
Event event;
event.m_type = EventType::Terminate;
event.m_data_index = static_cast<std::uint8_t>(m_cut_off_data.size());
m_events.push_back(event);

TerminateData data;
data.type = terminate_type;
m_cut_off_data.push_back(data);
}

void LightPathStream::hit_background()
{
Event event;
event.m_type = EventType::HitBackground;
m_events.push_back(event);
}

void LightPathStream::end_path()
{
// Ignore paths that fall outside of the supported range.
Expand Down Expand Up @@ -229,6 +262,100 @@ void LightPathStream::end_path()
clear_keep_memory(m_sampled_env_data);
}

std::vector<OIIO::ustring> LightPathStream::build_lpe_events()
{
std::vector<OIIO::ustring> lpe_events;

assert(m_camera != nullptr);
lpe_events.emplace_back("C_");

for (auto& event : m_events)
{
switch (event.m_type)
{
case EventType::HitReflector:
{
auto& reflector_data = m_hit_reflector_data[event.m_data_index];

std::string event_type, scattering_type;
// Determine event type.
// Volumn is not considered now.
if (reflector_data.m_crossing_interface)
event_type = "T";
else
event_type = "R";

// Determine scattering type.
switch (reflector_data.m_scattering_type)
{
case ScatteringMode::Diffuse:
{
scattering_type = "D";
break;
}
case ScatteringMode::Glossy:
{
scattering_type = "G";
break;
}
case ScatteringMode::Specular:
{
scattering_type = "S";
break;
}

// Ignore the "s" type for now.

assert_otherwise;
}

lpe_events.emplace_back(OIIO::ustring(event_type + scattering_type, 0));
break;
}

case EventType::HitEmitter:
{
lpe_events.emplace_back("O_");
break;
}

case EventType::SampledEmitter:
{
lpe_events.emplace_back("O_");
break;
}

case EventType::SampledEnvironment:
{
lpe_events.emplace_back("B_");
break;
}

case EventType::SampledVolume:
{
lpe_events.emplace_back("V_");
break;
}

case EventType::HitBackground:
{
lpe_events.emplace_back("B_");
break;
}

case EventType::Terminate:
{
lpe_events.emplace_back("X_");
break;
}

assert_otherwise;
}
}

return lpe_events;
}

void LightPathStream::create_path_from_hit_emitter(const size_t emitter_event_index)
{
const auto& hit_emitter_event = m_events[emitter_event_index];
Expand Down
Loading