Commit 3cb5164e authored by Johannes Braun's avatar Johannes Braun
Browse files

Optimized color templates, Pathtracer method structure and began a new texture class.

parent f645ffaf
......@@ -486,16 +486,12 @@ void drawSettingsWindow()
break;
case 1:
{
ImGui::Checkbox("Print render times", &pathtracer->debug.print_render_times);
ImGui::Spacing();
ImGui::BeginNamedGroup("Ray Generator");
{
int raygenstate = static_cast<int>(pathtracer->getGenerator());
int raygenstate = static_cast<int>(pathtracer->getRayGenerator());
ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth());
if (ImGui::Combo("", &raygenstate, { "Trace [default]", "OpenGL GBuffer" })) {
pathtracer->setGenerator(static_cast<raytrace::RayGeneratorType>(raygenstate));
pathtracer->setRayGenerator(static_cast<raytrace::RayGenType>(raygenstate));
}
ImGui::PopItemWidth();
}
......@@ -506,14 +502,14 @@ void drawSettingsWindow()
ImGui::BeginNamedGroup("Samples");
{
ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth());
ImGui::ProgressBar(pathtracer->currentSample() / static_cast<float>(pathtracer->getMaxSamples()), ImVec2(-1, 0),
("Current: " + std::to_string(pathtracer->currentSample()) + " of " + std::to_string(pathtracer->getMaxSamples())).c_str());
ImGui::ProgressBar(pathtracer->getSamplesCurrent() / static_cast<float>(pathtracer->getSamplesMax()), ImVec2(-1, 0),
("Current: " + std::to_string(pathtracer->getSamplesCurrent()) + " of " + std::to_string(pathtracer->getSamplesMax())).c_str());
ImGui::PopItemWidth();
ImGui::Spacing();
int max_samples = pathtracer->getMaxSamples();
int max_samples = pathtracer->getSamplesMax();
if (ImGui::DragInt("Maximum", &max_samples, 10, 1, 100000))
pathtracer->setMaxSamples(max_samples);
pathtracer->setSamplesMax(max_samples);
int spfr = pathtracer->getSamplesPerFrame();
if (ImGui::DragInt("per frame", &spfr, 0.1f, 1, 10))
......@@ -526,26 +522,26 @@ void drawSettingsWindow()
ImGui::BeginNamedGroup("Bounces");
ImGui::TextWrapped("The global bounce limit clamps down all effect-dependant bounce limits to a unified maximum value.");
{
int bounces = pathtracer->getBounces();
int bounces = pathtracer->getBounceCount();
if (ImGui::DragInt("Global Limit", &bounces, 0.1f, 0, 255))
pathtracer->setBounces(bounces);
pathtracer->setBounceCount(bounces);
ImGui::Spacing();
if (ImGui::TreeNode("Bounce Thresholds"))
{
// Let's keep this function locally near to the only place it's being used.
static auto effectBounces = [](const std::string &label, raytrace::EffectType effect)
static auto effectBounces = [](const std::string &label, raytrace::Effect effect)
{
int val = pathtracer->getEffectBounces(effect);
int val = pathtracer->getBounceThreshold(effect);
if (ImGui::DragInt(label.c_str(), &val, 0.1f, 0, 255))
pathtracer->setEffectBounces(effect, static_cast<uint8_t>(val));
pathtracer->setBounceThreshold(effect, static_cast<uint8_t>(val));
};
effectBounces("Diffusion", raytrace::EffectType::eDiffusion);
effectBounces("Reflection", raytrace::EffectType::eReflection);
effectBounces("Transmission", raytrace::EffectType::eTransmission);
effectBounces("Emission", raytrace::EffectType::eEmission);
effectBounces("Diffusion", raytrace::Effect::eDiffusion);
effectBounces("Reflection", raytrace::Effect::eReflection);
effectBounces("Transmission", raytrace::Effect::eTransmission);
effectBounces("Emission", raytrace::Effect::eEmission);
ImGui::TreePop();
}
}
......@@ -568,38 +564,38 @@ void drawSettingsWindow()
ImGui::Title("PDF Thresholds");
ImGui::TextWrapped("The following threshold values will determine as of which accumulated PDF value the Line Space should be used instead of the BVH.");
{
float acc = pathtracer->getAccuracyThreshold();
float acc = pathtracer->getLinespaceAccuracy();
if (ImGui::DragFloat("Direct", &acc, 0.001f, 0.0f, 1.f))
pathtracer->setAccuracyThreshold(acc);
pathtracer->setLinespaceAccuracy(acc);
float shd = pathtracer->getShadowThreshold();
float shd = pathtracer->getLinespaceShadow();
if (ImGui::DragFloat("Shadow", &shd, 0.001f, 0.0f, 1.f))
pathtracer->setShadowThreshold(shd);
pathtracer->setLinespaceShadow(shd);
}
ImGui::Title("Distance Threshold");
ImGui::TextWrapped("Works like a level of detail slider. This is the maximum path length with which the BVH should be used.");
{
float dt = pathtracer->getDistanceThreshold();
float dt = pathtracer->getLinespaceDistance();
if (ImGui::DragFloat("Distance", &dt, 0.1f, 0.0f, 10000.f))
pathtracer->setDistanceThreshold(dt);
pathtracer->setLinespaceDistance(dt);
}
ImGui::Title("Bounce Thresholds");
ImGui::TextWrapped("The following threshold values will determine as of which bounce the Line Space should be used instead of the BVH. This can vary for every kind of effect.");
{
// Let's keep this function locally near to the only place it's being used.
static auto bounceControl = [](const std::string &label, raytrace::EffectType effect)
static auto bounceControl = [](const std::string &label, raytrace::Effect effect)
{
int val = pathtracer->getLinespaceBounceThreshold(effect);
if (ImGui::DragInt(label.c_str(), &val, 0.1f, 0, pathtracer->getEffectBounces(effect)))
pathtracer->setLinespaceBounceThresholds(effect, static_cast<uint8_t>(val));
int val = pathtracer->getLinespaceBounces(effect);
if (ImGui::DragInt(label.c_str(), &val, 0.1f, 0, pathtracer->getLinespaceBounces(effect)))
pathtracer->setLinespaceBounces(effect, static_cast<uint8_t>(val));
};
bounceControl("Diffusion", raytrace::EffectType::eDiffusion);
bounceControl("Reflection", raytrace::EffectType::eReflection);
bounceControl("Transmission", raytrace::EffectType::eTransmission);
bounceControl("Emission", raytrace::EffectType::eEmission);
bounceControl("Diffusion", raytrace::Effect::eDiffusion);
bounceControl("Reflection", raytrace::Effect::eReflection);
bounceControl("Transmission", raytrace::Effect::eTransmission);
bounceControl("Emission", raytrace::Effect::eEmission);
}
}
break;
......
......@@ -3,27 +3,15 @@
#include <cassert>
#include <functional>
#include <util/property.h>
#include <util/color.h>
class P
{
public:
void blub(unsigned bla)
{
}
unsigned blubber()
{
}
};
#include <core/res/texture.h>
int main()
{
P p;
glare::core::Texture texture;
//auto prop = make_property<int, P, unsigned>(&p, &P::blub, &P::blubber);
texture.resize<color::rgba32f>(1024, 1024);
system("pause");
return 0;
......
......@@ -40,7 +40,7 @@ namespace glare::core
{
// Restore modified GL state
gl::useProgram(m_last_program);
gl::bindTexture(gl::TextureTarget::e2D, m_last_texture);
gl::bindTexture(gl::TextureType::e2D, m_last_texture);
gl::bindBuffer(gl::BufferType::eArray, m_last_array_buffer);
gl::bindBuffer(gl::BufferType::eElementArray, m_last_element_array_buffer);
gl::bindVertexArray(m_last_vertex_array);
......
......@@ -11,7 +11,7 @@ namespace glare::core
{
Skybox::Skybox()
: SceneComponent("Skybox"), m_handle(std::move(gl::TextureTarget::eCubeMap))
: SceneComponent("Skybox"), m_handle(std::move(gl::TextureType::eCubeMap))
{
}
......
#ifndef INCLUDE_TEXTURE_H
#define INCLUDE_TEXTURE_H
#include <filesystem>
#include <memory>
#include <vector>
#include <GL/glew.h>
#include <util/color.h>
#include <util/log.h>
#include <util/opengl.h>
#include <util/images.h>
#include "freetype/internal/ftvalid.h"
namespace glm {namespace io {
struct width;
}
}
namespace glare::core
{
template<typename T, int Components> struct Formats;
template<> struct Formats<float, 4>
{
constexpr static gl::TextureFormat format = gl::TextureFormat::eRGBA;
constexpr static gl::TextureInternalFormat internal_format = gl::TextureInternalFormat::eRGBA32Float;
};
template<> struct Formats<float, 3>
{
constexpr static gl::TextureFormat format = gl::TextureFormat::eRGB;
constexpr static gl::TextureInternalFormat internal_format = gl::TextureInternalFormat::eRGB32Float;
};
template<> struct Formats<float, 1>
{
constexpr static gl::TextureFormat format = gl::TextureFormat::eRed;
constexpr static gl::TextureInternalFormat internal_format = gl::TextureInternalFormat::eR32Float;
};
template<> struct Formats<uint8_t, 4>
{
constexpr static gl::TextureFormat format = gl::TextureFormat::eRGBA;
constexpr static gl::TextureInternalFormat internal_format = gl::TextureInternalFormat::eRGBA8;
};
template<> struct Formats<uint8_t, 3>
{
constexpr static gl::TextureFormat format = gl::TextureFormat::eRGB;
constexpr static gl::TextureInternalFormat internal_format = gl::TextureInternalFormat::eRGB;
};
template<> struct Formats<uint8_t, 1>
{
constexpr static gl::TextureFormat format = gl::TextureFormat::eRed;
constexpr static gl::TextureInternalFormat internal_format = gl::TextureInternalFormat::eRed;
};
template<typename T>
struct TypeConvert;
template<> struct TypeConvert<float>
{
constexpr static gl::Type gl_type = gl::Type::eFloat;
};
template<> struct TypeConvert<uint8_t>
{
constexpr static gl::Type gl_type = gl::Type::eUByte;
};
class Texture
{
public:
using address_t = uint64_t;
Texture() {};
template<typename T>
void upload(T* data, gl::TextureImageTarget2D target, int level, int width, int height)
{
upload2dimpl(data, target, level, width, height);
}
template<typename T>
void upload(T* data, int width, int height)
{
upload(data, gl::TextureImageTarget2D::e2D, 0, width, height);
}
template<typename T>
void upload(T* data, int width, int height, int samples)
{
upload2d(data, gl::TextureImageTarget2D::e2D, 0, width, height);
}
template<typename TColor>
void resize(gl::TextureImageTarget2D target, int level, int width, int height)
{
upload<TColor>(nullptr, target, level, width, height);
}
template<typename TColor>
void resize(gl::TextureImageTargetMultisample2D target, int width, int height, int samples)
{
resize2dMSimpl<TColor>(target, width, height, samples);
}
template<typename TColor>
void resize(int width, int height, int samples = -1)
{
if (samples == -1)
samples = m_samples;
if (samples == 1)
resize<TColor>(m_target2d, 0, width, height);
else
resize<TColor>(m_target2d, 0, width, height, samples);
}
bool textureResident() const
{
return m_resident_texture_address != 0 && gl::isTextureHandleResident(m_resident_texture_address);
}
bool imageResident() const
{
return m_resident_image_address != 0 && gl::isImageHandleResident(m_resident_image_address);
}
uint64_t residentTextureAddress() const
{
if (!textureResident())
{
m_resident_texture_address = gl::getTextureHandle(m_handle);
gl::makeTextureHandleResident(m_resident_texture_address);
}
assert(textureResident());
return residentTextureAddress();
}
uint64_t makeImageResident(gl::Access access) const
{
if (!imageResident())
{
m_resident_image_address = gl::getImageHandle(m_handle, 0, false, 0, m_image_format);
gl::makeImageHandleResident(m_resident_image_address, access);
}
assert(imageResident());
return m_resident_image_address;
}
void makeTextureNonResident() const
{
if (textureResident())
{
gl::makeTextureHandleNonResident(m_resident_texture_address);
}
assert(!textureResident());
}
void makeImageNonResident() const
{
if (imageResident())
{
gl::makeImageHandleNonResident(m_resident_image_address);
}
assert(!imageResident());
}
private:
template<typename T>
void upload2dimpl(T* data, gl::TextureImageTarget2D target, int level, int width, int height)
{
// A method implementation for f32 vec(n) data
using type = typename T::value_type;
using formats = Formats<type, color::components<T>::length>;
m_target2d = target;
bool changed = false;
switch(target)
{
case gl::TextureImageTarget2D::e2D:
case gl::TextureImageTarget2D::e2DProxy:
changed = m_type != gl::TextureType::e2D;
m_type = gl::TextureType::e2D;
break;
case gl::TextureImageTarget2D::e1DArray:
case gl::TextureImageTarget2D::e1DArrayProxy:
changed = m_type != gl::TextureType::eArray1D;
m_type = gl::TextureType::eArray1D;
break;
case gl::TextureImageTarget2D::eRectangle:
case gl::TextureImageTarget2D::eRectangleProxy:
changed = m_type != gl::TextureType::eRectangle;
m_type = gl::TextureType::eRectangle;
break;
case gl::TextureImageTarget2D::eCubeMapPosX:
case gl::TextureImageTarget2D::eCubeMapNegX:
case gl::TextureImageTarget2D::eCubeMapPosY:
case gl::TextureImageTarget2D::eCubeMapNegY:
case gl::TextureImageTarget2D::eCubeMapPosZ:
case gl::TextureImageTarget2D::eCubeMapNegZ:
changed = m_type != gl::TextureType::eCubeMap;
m_type = gl::TextureType::eCubeMap;
break;
default: break;
}
if (changed)
{
m_handle.regenerate(gl::TextureType{ m_type });
}
m_image_format = gl::ImageUnitFormat(formats::internal_format);
gl::pixelStorei(gl::PixelStoreAlignment::eUnpack, 1);
gl::textureImage2D(m_handle, target, level, formats::internal_format, width, height, 0, formats::format, TypeConvert<type>::gl_type, data);
}
template<typename T>
void resize2dMSimpl(gl::TextureImageTargetMultisample2D target, int width, int height, int samples)
{
using type = typename T::value_type;
using formats = Formats<type, color::components<T>::length>;
if (m_type != gl::TextureType::e2DMultisample)
{
m_type = gl::TextureType::e2DMultisample;
m_handle.regenerate(gl::TextureType{ m_type });
}
m_image_format = gl::ImageUnitFormat(formats::internal_format);
gl::pixelStorei(gl::PixelStoreAlignment::eUnpack, 1);
gl::textureImage2DMS(m_handle, target, samples, formats::internal_format, width, height, false);
}
gl::handle::texture m_handle {gl::TextureType::e2D};
gl::TextureType m_type = gl::TextureType::e2D;
gl::TextureImageTarget2D m_target2d = gl::TextureImageTarget2D::e2D;
gl::TextureImageTargetMultisample2D m_target2dMS = gl::TextureImageTargetMultisample2D::e2DMultisample;
gl::ImageUnitFormat m_image_format = gl::ImageUnitFormat::eRGBA32Float;
unsigned m_samples = 1;
mutable address_t m_resident_texture_address = 0;
mutable address_t m_resident_image_address = 0;
};
}
#endif //!INCLUDE_TEXTURE_H
\ No newline at end of file
......@@ -231,6 +231,7 @@ namespace glare::core
template<gl::TextureFormat Format, gl::TextureInternalFormat InternalFormat> using TextureData_UByte = TextureData<Format, InternalFormat, gl::Type::eUByte>;
template<gl::TextureFormat Format, gl::TextureInternalFormat InternalFormat> using TextureData_Float = TextureData<Format, InternalFormat, gl::Type::eFloat>;
//Float textures
using TextureRGBA_32F = Texture_Float<gl::TextureFormat::eRGBA, gl::TextureInternalFormat::eRGBA32Float>;
using TextureRGBA_UB = Texture_UByte<gl::TextureFormat::eRGBA, gl::TextureInternalFormat::eRGBA8>;
......@@ -373,7 +374,7 @@ namespace glare::core
template<gl::TextureFormat Format, gl::TextureInternalFormat InternalFormat, gl::Type T>
Texture<Format, InternalFormat, T>::Texture(uint32_t width, uint32_t height, tex_type* data, gl::TextureFilterMin min, gl::TextureFilterMag mag)
: m_handle(std::move(gl::TextureTarget::e2D))
: m_handle(std::move(gl::TextureType::e2D))
{
m_filter_min = min;
m_filter_mag = mag;
......
......@@ -70,7 +70,7 @@ namespace glare::core
template<gl::TextureFormat Format, gl::TextureInternalFormat InternalFormat, gl::Type T>
TextureMultisampled<Format, InternalFormat, T>::TextureMultisampled(unsigned width, unsigned height, unsigned samples)
: m_handle(std::move(gl::TextureTarget::e2DMultisample))
: m_handle(std::move(gl::TextureType::e2DMultisample))
{
resize(width, height, samples);
}
......
......@@ -78,7 +78,7 @@ namespace glare::core
template<gl::TextureFormat Format, gl::TextureInternalFormat InternalFormat, gl::Type T>
Texture3D<Format, InternalFormat, T>::Texture3D(unsigned width, unsigned height, unsigned depth, tex_type* data, gl::TextureFilterMin min, gl::TextureFilterMag mag)
: m_handle(std::move(gl::TextureTarget::e3D))
: m_handle(std::move(gl::TextureType::e3D))
{
m_filter_min = min;
m_filter_mag = mag;
......
......@@ -107,7 +107,7 @@ namespace ImGui {
}
else
{
gl::bindTexture(gl::TextureTarget::e2D, unsigned(reinterpret_cast<intptr_t>(pcmd.TextureId)));
gl::bindTexture(gl::TextureType::e2D, unsigned(reinterpret_cast<intptr_t>(pcmd.TextureId)));
gl::scissor(static_cast<int>(pcmd.ClipRect.x), static_cast<int>(fb_height - pcmd.ClipRect.w), static_cast<unsigned>(pcmd.ClipRect.z - pcmd.ClipRect.x), static_cast<unsigned>(pcmd.ClipRect.w - pcmd.ClipRect.y));
gl::drawElements(gl::PrimitiveType::eTriangles, static_cast<unsigned>(pcmd.ElemCount), gl::Type::eUShort, idx_buffer_offset);
}
......@@ -241,7 +241,7 @@ namespace ImGui {
createFontsTexture();
// Restore modified GL state
gl::bindTexture(gl::TextureTarget::e2D, last_texture);
gl::bindTexture(gl::TextureType::e2D, last_texture);
gl::bindBuffer(gl::BufferType::eArray, last_array_buffer);
gl::bindVertexArray(last_vertex_array);
......
......@@ -6,53 +6,22 @@
namespace glare::raytrace
{
std::unique_ptr<core::Program> Pathtracer::m_render_shader = nullptr;
Pathtracer::Pathtracer()
: Pathtracer(RayGeneratorType::eTrace)
{
}
Pathtracer::Pathtracer(std::shared_ptr<core::SceneNode> graph_root)
: Pathtracer(std::make_shared<SceneCollector>(graph_root))
{
}
Pathtracer::Pathtracer(std::shared_ptr<core::SceneNode> graph_root, RayGeneratorType ray_generator)
Pathtracer::Pathtracer(std::shared_ptr<core::SceneNode> graph_root, RayGenType ray_generator)
: Pathtracer(std::make_shared<SceneCollector>(graph_root), ray_generator)
{
}
Pathtracer::Pathtracer(RayGeneratorType ray_generator)
Pathtracer::Pathtracer(RayGenType ray_generator)
: Pathtracer(std::shared_ptr<SceneCollector>(nullptr), ray_generator)
{
}
Pathtracer::Pathtracer(std::shared_ptr<SceneCollector> collector)
: Pathtracer(collector, RayGeneratorType::eTrace)
{
}
Pathtracer::Pathtracer(std::shared_ptr<SceneCollector> collector, RayGeneratorType ray_generator)
Pathtracer::Pathtracer(std::shared_ptr<SceneCollector> collector, RayGenType ray_generator)
{
m_bounce_count_thresholds[static_cast<unsigned>(EffectType::eDiffusion)] = 4;
m_bounce_count_thresholds[static_cast<unsigned>(EffectType::eReflection)] = 6;
m_bounce_count_thresholds[static_cast<unsigned>(EffectType::eTransmission)] = 12;
m_bounce_count_thresholds[static_cast<unsigned>(EffectType::eEmission)] = 1;
m_ls_bounce_count_thresholds[static_cast<unsigned>(EffectType::eDiffusion)] = 1;
m_ls_bounce_count_thresholds[static_cast<unsigned>(EffectType::eReflection)] = 3;
m_ls_bounce_count_thresholds[static_cast<unsigned>(EffectType::eTransmission)] = 3;
m_ls_bounce_count_thresholds[static_cast<unsigned>(EffectType::eEmission)] = 6;
m_linespace_config.distance_threshold = 8.f;
m_render_config.bounces = 16;
Log_Hint << "Pathtracing Shader will now be compiled. This might take a couple of seconds.";
if(!m_render_shader) m_render_shader = std::make_unique<core::Program>(files::shader("/pathtracer/pathtracer.comp"));
m_generator_type = ray_generator;
m_ray_generator = ray_generator;
core::Context::current().messages()->addObserver(this, tags::scene);
......@@ -76,53 +45,41 @@ namespace glare::raytrace
//bounces
const auto bounces_child = pt_child.find_child_by_attribute("group", "name", "bounces");
dynamic_config.bounces.thresholds[static_cast<unsigned>(EffectType::eDiffusion)] = static_cast<uint8_t>(bounces_child.find_child_by_attribute("item", "name", "diffusion").attribute("value").as_uint(2));
dynamic_config.bounces.thresholds[static_cast<unsigned>(EffectType::eReflection)] = static_cast<uint8_t>(bounces_child.find_child_by_attribute("item", "name", "reflection").attribute("value").as_uint(4));
dynamic_config.bounces.thresholds[static_cast<unsigned>(EffectType::eTransmission)] = static_cast<uint8_t>(bounces_child.find_child_by_attribute("item", "name", "transmission").attribute("value").as_uint(4));
dynamic_config.bounces.thresholds[static_cast<unsigned>(EffectType::eEmission)] = static_cast<uint8_t>(bounces_child.find_child_by_attribute("item", "name", "emission").attribute("value").as_uint(8));
m_bounce_thresholds[Effect::eDiffusion] = static_cast<uint8_t>(bounces_child.find_child_by_attribute("item", "name", "diffusion").attribute("value").as_uint(2));
m_bounce_thresholds[Effect::eReflection] = static_cast<uint8_t>(bounces_child.find_child_by_attribute("item", "name", "reflection").attribute("value").as_uint(4));
m_bounce_thresholds[Effect::eTransmission] = static_cast<uint8_t>(bounces_child.find_child_by_attribute("item", "name", "transmission").attribute("value").as_uint(4));
m_bounce_thresholds[Effect::eEmission] = static_cast<uint8_t>(bounces_child.find_child_by_attribute("item", "name", "emission").attribute("value").as_uint(8));
//ls thresholds
const auto ls_thresholds_child = pt_child.find_child_by_attribute("group", "name", "ls-thresholds");
dynamic_config.linespace.thresholds.bounces[static_cast<unsigned>(EffectType::eDiffusion)] = static_cast<uint8_t>(ls_thresholds_child.find_child_by_attribute("item", "name", "diffusion").attribute("value").as_uint(2));
dynamic_config.linespace.thresholds.bounces[static_cast<unsigned>(EffectType::eReflection)] = static_cast<uint8_t>(ls_thresholds_child.find_child_by_attribute("item", "name", "reflection").attribute("value").as_uint(4));
dynamic_config.linespace.thresholds.bounces[static_cast<unsigned>(EffectType::eTransmission)] = static_cast<uint8_t>(ls_thresholds_child.find_child_by_attribute("item", "name", "transmission").attribute("value").as_uint(4));
dynamic_config.linespace.thresholds.bounces[static_cast<unsigned>(EffectType::eEmission)] = static_cast<uint8_t>(ls_thresholds_child.find_child_by_attribute("item", "name", "emission").attribute("value").as_uint(8));
dynamic_config.linespace.thresholds.distance = ls_thresholds_child.find_child_by_attribute("item", "name", "distance").attribute("value").as_float(10.f);
m_linespace_bounces[Effect::eDiffusion] = static_cast<uint8_t>(ls_thresholds_child.find_child_by_attribute("item", "name", "diffusion").attribute("value").as_uint(2));
m_linespace_bounces[Effect::eReflection] = static_cast<uint8_t>(ls_thresholds_child.find_child_by_attribute("item", "name", "reflection").attribute("value").as_uint(4));
m_linespace_bounces[Effect::eTransmission] = static_cast<uint8_t>(ls_thresholds_child.find_child_by_attribute("item", "name", "transmission").attribute("value").as_uint(4));
m_linespace_bounces[Effect::eEmission] = static_cast<uint8_t>(ls_thresholds_child.find_child_by_attribute("item", "name", "emission").attribute("value").as_uint(8));
m_linespace_distance = ls_thresholds_child.find_child_by_attribute("item", "name", "distance").attribute("value").as_float(10.f);
dynamic_config.linespace.quality.accuracy = ls_thresholds_child.find_child_by_attribute("item", "name", "accuracy").attribute("value").as_float(0.5f);
dynamic_config.linespace.quality.shadow = ls_thresholds_child.find_child_by_attribute("item", "name", "shadow").attribute("value").as_float(0.5f);
m_linespace_accuracy = ls_thresholds_child.find_child_by_attribute("item", "name", "accuracy").attribute("value").as_float(0.5f);
m_linespace_shadow = ls_thresholds_child.find_child_by_attribute("item", "name", "shadow").attribute("value").as_float(0.5f);
dynamic_config.clamp.direct = pt_child.find_child_by_attribute("item", "name", "clamp-direct").attribute("value").as_float(8);
dynamic_config.clamp.indirect = pt_child.find_child_by_attribute("item", "name", "clamp-indirect").attribute("value").as_float(8);
m_clamp_direct = pt_child.find_child_by_attribute("item", "name", "clamp-direct").attribute("value").as_float(8);
m_clamp_indirect = pt_child.find_child_by_attribute("item", "name", "clamp-indirect").attribute("value").as_float(8);
}
void Pathtracer::reset()