Skip to content

Commit

Permalink
gh-55: impl auto exposition effect
Browse files Browse the repository at this point in the history
  • Loading branch information
EgorOrachyov committed Nov 1, 2023
1 parent c115d31 commit ce75ddd
Show file tree
Hide file tree
Showing 78 changed files with 1,860 additions and 205 deletions.
2 changes: 2 additions & 0 deletions engine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,8 @@ add_library(wmoge STATIC
render/visibility.hpp
render/geometry/pass_gbuffer.cpp
render/geometry/pass_gbuffer.hpp
render/post_process/pass_autoexposure.cpp
render/post_process/pass_autoexposure.hpp
render/post_process/pass_bloom.cpp
render/post_process/pass_bloom.hpp
render/post_process/pass_composition.cpp
Expand Down
2 changes: 1 addition & 1 deletion engine/core/ref.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ namespace wmoge {
return Ref<G>(dynamic_cast<G*>(m_ptr));
}

private:
protected:
T* m_ptr = nullptr;
};

Expand Down
15 changes: 11 additions & 4 deletions engine/render/deferred_pipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "debug/profiler.hpp"
#include "geometry/pass_gbuffer.hpp"
#include "platform/window_manager.hpp"
#include "post_process/pass_autoexposure.hpp"
#include "post_process/pass_bloom.hpp"
#include "post_process/pass_composition.hpp"
#include "post_process/pass_tonemap.hpp"
Expand All @@ -43,20 +44,23 @@ namespace wmoge {
void DeferredPipeline::init() {
WG_AUTO_PROFILE_RENDER("DeferredPipeline::init");

m_pass_gbuffer = std::make_unique<PassGBuffer>();
m_pass_bloom = std::make_unique<PassBloom>();
m_pass_tonemap = std::make_unique<PassToneMap>();
m_pass_composition = std::make_unique<PassComposition>();
m_pass_gbuffer = std::make_unique<PassGBuffer>();
m_pass_bloom = std::make_unique<PassBloom>();
m_pass_autoexposure = std::make_unique<PassAutoExposure>();
m_pass_tonemap = std::make_unique<PassToneMap>();
m_pass_composition = std::make_unique<PassComposition>();

m_stages.push_back(m_pass_gbuffer.get());
m_stages.push_back(m_pass_bloom.get());
m_stages.push_back(m_pass_autoexposure.get());
m_stages.push_back(m_pass_tonemap.get());
m_stages.push_back(m_pass_composition.get());

for (GraphicsPipelineStage* stage : m_stages) {
stage->set_pipeline(this);
}

m_shared.allocate();
m_textures.resize(m_target_resolution);
m_textures.update_viewport(m_resolution);
}
Expand All @@ -75,6 +79,8 @@ namespace wmoge {
WG_GFX_LABEL(gfx_ctx, SID("DeferredPipeline::exectute"));

for (int i = view_count - 1; i >= 0; i--) {
WG_AUTO_PROFILE_RENDER("Render view=" + StringUtils::from_int(i));

const int view_idx = i;
const RenderCameraData& camera = m_cameras->data_at(view_idx);

Expand All @@ -85,6 +91,7 @@ namespace wmoge {

m_pass_gbuffer->execute(view_idx);
m_pass_bloom->execute(view_idx);
m_pass_autoexposure->execute(view_idx);
m_pass_tonemap->execute(view_idx);
m_pass_composition->execute(0, engine->window_manager()->primary_window());
}
Expand Down
11 changes: 6 additions & 5 deletions engine/render/deferred_pipeline.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ namespace wmoge {

/**
* @class DeferredPipeline
* @brief Deferred HDR pipeline for scene rendering
* @brief Deferred high-quality HDR pipeline for scene rendering
*/
class DeferredPipeline : public GraphicsPipeline {
public:
Expand All @@ -51,10 +51,11 @@ namespace wmoge {
std::string get_name() override;

private:
std::unique_ptr<class PassGBuffer> m_pass_gbuffer;
std::unique_ptr<class PassBloom> m_pass_bloom;
std::unique_ptr<class PassToneMap> m_pass_tonemap;
std::unique_ptr<class PassComposition> m_pass_composition;
std::unique_ptr<class PassGBuffer> m_pass_gbuffer;
std::unique_ptr<class PassBloom> m_pass_bloom;
std::unique_ptr<class PassAutoExposure> m_pass_autoexposure;
std::unique_ptr<class PassToneMap> m_pass_tonemap;
std::unique_ptr<class PassComposition> m_pass_composition;
// std::unique_ptr<class PassForward> m_pass_forward;
// std::unique_ptr<class PassDeferredLighting> m_pass_deferred_lighting;

Expand Down
45 changes: 45 additions & 0 deletions engine/render/graphics_pipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
#include "graphics_pipeline.hpp"

#include "core/engine.hpp"
#include "shaders/generated/auto_luminance_avg_reflection.hpp"
#include "shaders/generated/auto_luminance_histogram_reflection.hpp"

#include <cstring>

namespace wmoge {

Expand Down Expand Up @@ -55,6 +59,28 @@ namespace wmoge {
return StatusCode::Ok;
}

Status yaml_read(const YamlConstNodeRef& node, AutoExposureSettings& settings) {
WG_YAML_READ_AS_OPT(node, "enable", settings.enable);
WG_YAML_READ_AS_OPT(node, "mode", settings.mode);
WG_YAML_READ_AS_OPT(node, "histogram_log_min", settings.histogram_log_min);
WG_YAML_READ_AS_OPT(node, "histogram_log_max", settings.histogram_log_max);
WG_YAML_READ_AS_OPT(node, "speed_up", settings.speed_up);
WG_YAML_READ_AS_OPT(node, "speed_down", settings.speed_down);
WG_YAML_READ_AS_OPT(node, "exposure_compensation", settings.exposure_compensation);
return StatusCode::Ok;
}
Status yaml_write(YamlNodeRef node, const AutoExposureSettings& settings) {
WG_YAML_MAP(node);
WG_YAML_WRITE_AS(node, "enable", settings.enable);
WG_YAML_WRITE_AS(node, "mode", settings.mode);
WG_YAML_WRITE_AS(node, "histogram_log_min", settings.histogram_log_min);
WG_YAML_WRITE_AS(node, "histogram_log_max", settings.histogram_log_max);
WG_YAML_WRITE_AS(node, "speed_up", settings.speed_up);
WG_YAML_WRITE_AS(node, "speed_down", settings.speed_down);
WG_YAML_WRITE_AS(node, "exposure_compensation", settings.exposure_compensation);
return StatusCode::Ok;
}

Status yaml_read(const YamlConstNodeRef& node, TonemapSettings& settings) {
WG_YAML_READ_AS_OPT(node, "exposure", settings.exposure);
WG_YAML_READ_AS_OPT(node, "white_point", settings.white_point);
Expand Down Expand Up @@ -121,6 +147,25 @@ namespace wmoge {
size = Vec2u(new_resoulution.x(), new_resoulution.y());
}

void GraphicsPipelineShared::allocate() {
Engine* engine = Engine::instance();
GfxDriver* gfx_driver = engine->gfx_driver();
GfxCtx* gfx_ctx = engine->gfx_ctx();

ShaderLuminanceHistogram::Histogram histogram;
std::memset(histogram.Bins, 0, sizeof(histogram.Bins));

ShaderLuminanceHistogram::Luminance luminance;
luminance.LumTemporal = 1.0f;
luminance.AutoExposure = 1.0f;

lum_histogram = gfx_driver->make_storage_buffer(int(sizeof(histogram)), GfxMemUsage::GpuLocal, SID("lum_histogram"));
lum_luminance = gfx_driver->make_storage_buffer(int(sizeof(luminance)), GfxMemUsage::GpuLocal, SID("lum_luminance"));

gfx_ctx->update_storage_buffer(lum_histogram, 0, lum_histogram->size(), make_ref<Data>(&histogram, sizeof(histogram)));
gfx_ctx->update_storage_buffer(lum_luminance, 0, lum_luminance->size(), make_ref<Data>(&luminance, sizeof(luminance)));
}

GraphicsPipelineStage::GraphicsPipelineStage() {
Engine* engine = Engine::instance();

Expand Down
67 changes: 53 additions & 14 deletions engine/render/graphics_pipeline.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#define WMOGE_GRAPHICS_PIPELINE_HPP

#include "core/array_view.hpp"
#include "gfx/gfx_buffers.hpp"
#include "gfx/gfx_ctx.hpp"
#include "gfx/gfx_driver.hpp"
#include "gfx/gfx_texture.hpp"
Expand All @@ -52,19 +53,43 @@ namespace wmoge {
* @brief Bloom effect settings
*/
struct BloomSettings {
bool enable = true;
float intensity = 1.0f;
float threshold = 1.0f;
float knee = 0.5f;
float radius = 4.0f;
float uspample_weight = 0.4f;
float dirt_mask_intensity = 3.0f;
std::optional<ResourceRefHard<Texture2d>> dirt_mask;
bool enable = true;
float intensity = 1.0f;
float threshold = 1.0f;
float knee = 0.5f;
float radius = 4.0f;
float uspample_weight = 0.4f;
float dirt_mask_intensity = 3.0f;
std::optional<ResRef<Texture2d>> dirt_mask;

friend Status yaml_read(const YamlConstNodeRef& node, BloomSettings& settings);
friend Status yaml_write(YamlNodeRef node, const BloomSettings& settings);
};

/**
* @class AutoExposureSettings
* @brief Automatic exposition or eye adaptation settings
*/
struct AutoExposureSettings {

/** @brief Mode to select algo */
enum class Mode {
Adaptive = 0,
Instant = 1
};

bool enable = true;
Mode mode = Mode::Adaptive;
float histogram_log_min = -10.0f;
float histogram_log_max = 5.0f;
float speed_up = 4.0f;
float speed_down = 0.5f;
float exposure_compensation = 1.0f;

friend Status yaml_read(const YamlConstNodeRef& node, AutoExposureSettings& settings);
friend Status yaml_write(YamlNodeRef node, const AutoExposureSettings& settings);
};

/**
* @class TonemapSettings
* @brief Final HDR image tonemapping settings for composition
Expand All @@ -80,9 +105,9 @@ namespace wmoge {
Uncharted2 = 4
};

float exposure = 0.8f;
float white_point = 1.0f;
Mode mode = Mode::Exponential;
float exposure = 1.0f;
float white_point = 1.0f;

friend Status yaml_read(const YamlConstNodeRef& node, TonemapSettings& settings);
friend Status yaml_write(YamlNodeRef node, const TonemapSettings& settings);
Expand All @@ -93,8 +118,9 @@ namespace wmoge {
* @brief Graphics pipeline settings for rendering scene
*/
struct GraphicsPipelineSettings {
BloomSettings bloom;
TonemapSettings tonemap;
BloomSettings bloom;
AutoExposureSettings auto_exposure;
TonemapSettings tonemap;

friend Status yaml_read(const YamlConstNodeRef& node, GraphicsPipelineSettings& settings);
friend Status yaml_write(YamlNodeRef node, const GraphicsPipelineSettings& settings);
Expand Down Expand Up @@ -140,10 +166,21 @@ namespace wmoge {
void update_viewport(Size2i new_resoulution);
};

/**
* @class GraphicsPipelineShared
* @brief Shared state of pipeline required for rendering
*/
struct GraphicsPipelineShared {
Ref<GfxStorageBuffer> lum_histogram;//< Luminance histogram of the hdr color buffer
Ref<GfxStorageBuffer> lum_luminance;//< Luminance avg and exposure correction

void allocate();
};

/**
* @class GraphicsPipelineStage
* @brief
*/
*/
class GraphicsPipelineStage {
public:
GraphicsPipelineStage();
Expand Down Expand Up @@ -173,7 +210,7 @@ namespace wmoge {
/**
* @class GraphicsPipeline
* @brief Pipeline capable of rendering scene cameras draw cmds into series of pass to get final image
*/
*/
class GraphicsPipeline {
public:
virtual ~GraphicsPipeline() = default;
Expand All @@ -193,6 +230,7 @@ namespace wmoge {

[[nodiscard]] const GraphicsPipelineSettings& get_settings() { return m_settings; }
[[nodiscard]] const GraphicsPipelineTextures& get_textures() { return m_textures; }
[[nodiscard]] const GraphicsPipelineShared& get_shared() { return m_shared; }
[[nodiscard]] ArrayView<struct RenderView> get_views() const { return m_views; }
[[nodiscard]] RenderCameras* get_cameras() const { return m_cameras; }
[[nodiscard]] RenderScene* get_scene() const { return m_scene; }
Expand All @@ -202,6 +240,7 @@ namespace wmoge {
protected:
GraphicsPipelineSettings m_settings;
GraphicsPipelineTextures m_textures;
GraphicsPipelineShared m_shared;
ArrayView<struct RenderView> m_views;
RenderCameras* m_cameras;
RenderScene* m_scene;
Expand Down
Loading

0 comments on commit ce75ddd

Please sign in to comment.