From ee0cef6162e43d258aa06f4745039e4c92d49543 Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Fri, 13 Jan 2023 05:28:08 +0800 Subject: [PATCH] Improve bloom --- src/game/context.hpp | 2 - src/game/graphics.cpp | 26 +-- src/game/state/boot.cpp | 11 +- src/game/state/nest-selection.cpp | 4 +- src/render/passes/bloom-pass.cpp | 279 +++++++++++++++++++++--------- src/render/passes/bloom-pass.hpp | 95 +++++++--- src/render/passes/final-pass.cpp | 13 +- src/render/passes/final-pass.hpp | 5 +- src/render/passes/sky-pass.cpp | 2 +- 9 files changed, 299 insertions(+), 138 deletions(-) diff --git a/src/game/context.hpp b/src/game/context.hpp index 4a0ebc9..8b488ac 100644 --- a/src/game/context.hpp +++ b/src/game/context.hpp @@ -185,8 +185,6 @@ struct context gl::texture_2d* hdr_color_texture; gl::texture_2d* hdr_depth_texture; gl::framebuffer* hdr_framebuffer; - gl::texture_2d* bloom_color_texture; - gl::framebuffer* bloom_framebuffer; gl::texture_2d* shadow_map_depth_texture; gl::framebuffer* shadow_map_framebuffer; diff --git a/src/game/graphics.cpp b/src/game/graphics.cpp index d80c06f..b725e98 100644 --- a/src/game/graphics.cpp +++ b/src/game/graphics.cpp @@ -18,6 +18,7 @@ */ #include "game/graphics.hpp" +#include "render/passes/bloom-pass.hpp" #include "gl/framebuffer.hpp" #include "gl/texture-2d.hpp" #include "gl/texture-wrapping.hpp" @@ -61,17 +62,6 @@ void create_framebuffers(game::context& ctx) ctx.hdr_framebuffer->attach(gl::framebuffer_attachment_type::depth, ctx.hdr_depth_texture); ctx.hdr_framebuffer->attach(gl::framebuffer_attachment_type::stencil, ctx.hdr_depth_texture); - // Calculate bloom resolution - int2 bloom_resolution = ctx.render_resolution / 2; - - // Create bloom framebuffer (16F color, no depth) - ctx.bloom_color_texture = new gl::texture_2d(bloom_resolution.x(), bloom_resolution.y(), gl::pixel_type::float_16, gl::pixel_format::rgb); - ctx.bloom_color_texture->set_wrapping(gl::texture_wrapping::extend, gl::texture_wrapping::extend); - ctx.bloom_color_texture->set_filters(gl::texture_min_filter::linear, gl::texture_mag_filter::linear); - ctx.bloom_color_texture->set_max_anisotropy(0.0f); - ctx.bloom_framebuffer = new gl::framebuffer(bloom_resolution.x(), bloom_resolution.y()); - ctx.bloom_framebuffer->attach(gl::framebuffer_attachment_type::color, ctx.bloom_color_texture); - // Load shadow map resolution from config int shadow_map_resolution = 4096; if (ctx.config->contains("shadow_map_resolution")) @@ -100,12 +90,6 @@ void destroy_framebuffers(game::context& ctx) delete ctx.hdr_depth_texture; ctx.hdr_depth_texture = nullptr; - // Delete bloom framebuffer and its attachments - delete ctx.bloom_framebuffer; - ctx.bloom_framebuffer = nullptr; - delete ctx.bloom_color_texture; - ctx.bloom_color_texture = nullptr; - // Delete shadow map framebuffer and its attachments delete ctx.shadow_map_framebuffer; ctx.shadow_map_framebuffer = nullptr; @@ -131,12 +115,8 @@ void change_render_resolution(game::context& ctx, float scale) resize_framebuffer_attachment(*ctx.hdr_color_texture, ctx.render_resolution); resize_framebuffer_attachment(*ctx.hdr_depth_texture, ctx.render_resolution); - // Recalculate bloom resolution - int2 bloom_resolution = ctx.render_resolution / 2; - - // Resize bloom framebuffer and attachments - ctx.bloom_framebuffer->resize({bloom_resolution.x(), bloom_resolution.y()}); - resize_framebuffer_attachment(*ctx.bloom_color_texture, bloom_resolution); + // Resize bloom render pass + ctx.common_bloom_pass->resize(); ctx.logger->pop_task(EXIT_SUCCESS); } diff --git a/src/game/state/boot.cpp b/src/game/state/boot.cpp index 2f34e4e..eddb850 100644 --- a/src/game/state/boot.cpp +++ b/src/game/state/boot.cpp @@ -447,14 +447,15 @@ void boot::setup_rendering() // Setup common render passes { - ctx.common_bloom_pass = new render::bloom_pass(ctx.rasterizer, ctx.bloom_framebuffer, ctx.resource_manager); + ctx.common_bloom_pass = new render::bloom_pass(ctx.rasterizer, ctx.resource_manager); ctx.common_bloom_pass->set_source_texture(ctx.hdr_color_texture); - ctx.common_bloom_pass->set_brightness_threshold(1.0f); - ctx.common_bloom_pass->set_blur_iterations(5); + ctx.common_bloom_pass->set_mip_chain_length(6); + ctx.common_bloom_pass->set_filter_radius(0.005f); ctx.common_final_pass = new render::final_pass(ctx.rasterizer, &ctx.rasterizer->get_default_framebuffer(), ctx.resource_manager); ctx.common_final_pass->set_color_texture(ctx.hdr_color_texture); - ctx.common_final_pass->set_bloom_texture(ctx.bloom_color_texture); + ctx.common_final_pass->set_bloom_texture(ctx.common_bloom_pass->get_bloom_texture()); + ctx.common_final_pass->set_bloom_weight(0.04f); ctx.common_final_pass->set_blue_noise_texture(blue_noise_map); } @@ -526,7 +527,7 @@ void boot::setup_rendering() ctx.surface_compositor->add_pass(ctx.ground_pass); ctx.surface_compositor->add_pass(ctx.surface_material_pass); //ctx.surface_compositor->add_pass(ctx.surface_outline_pass); - //ctx.surface_compositor->add_pass(ctx.common_bloom_pass); + ctx.surface_compositor->add_pass(ctx.common_bloom_pass); ctx.surface_compositor->add_pass(ctx.common_final_pass); } diff --git a/src/game/state/nest-selection.cpp b/src/game/state/nest-selection.cpp index 84cca8c..89c4289 100644 --- a/src/game/state/nest-selection.cpp +++ b/src/game/state/nest-selection.cpp @@ -714,7 +714,7 @@ void nest_selection::enable_controls() [&ctx = this->ctx](float) { //ctx.astronomy_system->set_exposure_offset(ctx.astronomy_system->get_exposure_offset() - 1.0f); - ctx.surface_camera->set_exposure(ctx.surface_camera->get_exposure() + 0.5f * static_cast(ctx.loop.get_update_period())); + ctx.surface_camera->set_exposure(ctx.surface_camera->get_exposure() + 2.0f * static_cast(ctx.loop.get_update_period())); ctx.logger->log("EV100: " + std::to_string(ctx.surface_camera->get_exposure())); } ); @@ -724,7 +724,7 @@ void nest_selection::enable_controls() [&ctx = this->ctx](float) { //ctx.astronomy_system->set_exposure_offset(ctx.astronomy_system->get_exposure_offset() + 1.0f); - ctx.surface_camera->set_exposure(ctx.surface_camera->get_exposure() - 0.5f * static_cast(ctx.loop.get_update_period())); + ctx.surface_camera->set_exposure(ctx.surface_camera->get_exposure() - 2.0f * static_cast(ctx.loop.get_update_period())); ctx.logger->log("EV100: " + std::to_string(ctx.surface_camera->get_exposure())); } ); diff --git a/src/render/passes/bloom-pass.cpp b/src/render/passes/bloom-pass.cpp index cc45638..354d463 100644 --- a/src/render/passes/bloom-pass.cpp +++ b/src/render/passes/bloom-pass.cpp @@ -32,63 +32,47 @@ #include "gl/texture-filter.hpp" #include "render/vertex-attribute.hpp" #include "render/context.hpp" +#include #include #include +#include namespace render { -bloom_pass::bloom_pass(gl::rasterizer* rasterizer, const gl::framebuffer* framebuffer, resource_manager* resource_manager): - pass(rasterizer, framebuffer), +bloom_pass::bloom_pass(gl::rasterizer* rasterizer, resource_manager* resource_manager): + pass(rasterizer, nullptr), source_texture(nullptr), - brightness_threshold(1.0f), - blur_iterations(1) + source_texel_size{1.0f, 1.0f}, + mip_chain_length(0), + filter_radius(0.005f), + corrected_filter_radius{filter_radius, filter_radius} { - // Create clone of framebuffer texture - const gl::texture_2d* framebuffer_texture = framebuffer->get_color_attachment(); - auto dimensions = framebuffer_texture->get_dimensions(); - auto pixel_type = framebuffer_texture->get_pixel_type(); - auto pixel_format = framebuffer_texture->get_pixel_format(); - auto wrapping = framebuffer_texture->get_wrapping(); - auto filters = framebuffer_texture->get_filters(); - float max_anisotropy = framebuffer_texture->get_max_anisotropy(); - cloned_framebuffer_texture = new gl::texture_2d(std::get<0>(dimensions), std::get<1>(dimensions), pixel_type, pixel_format); - cloned_framebuffer_texture->set_wrapping(std::get<0>(wrapping), std::get<1>(wrapping)); - cloned_framebuffer_texture->set_filters(std::get<0>(filters), std::get<1>(filters)); - cloned_framebuffer_texture->set_max_anisotropy(max_anisotropy); + // Load downsample with Karis average shader + downsample_karis_shader = resource_manager->load("bloom-downsample-karis.glsl"); + downsample_karis_source_texture_input = downsample_karis_shader->get_input("source_texture"); + downsample_karis_texel_size_input = downsample_karis_shader->get_input("texel_size"); - // Create clone of framebuffer - cloned_framebuffer = new gl::framebuffer(std::get<0>(dimensions), std::get<1>(dimensions)); - cloned_framebuffer->attach(gl::framebuffer_attachment_type::color, cloned_framebuffer_texture); + // Load downsample shader + downsample_shader = resource_manager->load("bloom-downsample.glsl"); + downsample_source_texture_input = downsample_shader->get_input("source_texture"); + downsample_texel_size_input = downsample_shader->get_input("texel_size"); - // Setup pingponging - pingpong_textures[0] = framebuffer_texture; - pingpong_textures[1] = cloned_framebuffer_texture; - pingpong_framebuffers[0] = framebuffer; - pingpong_framebuffers[1] = cloned_framebuffer; - - // Load brightness threshold shader - threshold_shader = resource_manager->load("brightness-threshold.glsl"); - threshold_shader_image_input = threshold_shader->get_input("image"); - threshold_shader_resolution_input = threshold_shader->get_input("resolution"); - threshold_shader_threshold_input = threshold_shader->get_input("threshold"); - - // Load blur shader - blur_shader = resource_manager->load("blur.glsl"); - blur_shader_image_input = blur_shader->get_input("image"); - blur_shader_resolution_input = blur_shader->get_input("resolution"); - blur_shader_direction_input = blur_shader->get_input("direction"); + // Load upsample shader + upsample_shader = resource_manager->load("bloom-upsample.glsl"); + upsample_source_texture_input = upsample_shader->get_input("source_texture"); + upsample_filter_radius_input = upsample_shader->get_input("filter_radius"); const float vertex_data[] = { - -1.0f, 1.0f, 0.0f, - -1.0f, -1.0f, 0.0f, - 1.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 0.0f, - -1.0f, -1.0f, 0.0f, - 1.0f, -1.0f, 0.0f + -1.0f, 1.0f, + -1.0f, -1.0f, + 1.0f, 1.0f, + 1.0f, 1.0f, + -1.0f, -1.0f, + 1.0f, -1.0f }; - - std::size_t vertex_size = 3; + + std::size_t vertex_size = 2; std::size_t vertex_stride = sizeof(float) * vertex_size; std::size_t vertex_count = 6; @@ -101,7 +85,7 @@ bloom_pass::bloom_pass(gl::rasterizer* rasterizer, const gl::framebuffer* frameb position_attribute.offset = 0; position_attribute.stride = vertex_stride; position_attribute.type = gl::vertex_attribute_type::float_32; - position_attribute.components = 3; + position_attribute.components = 2; // Bind vertex attributes to VAO quad_vao->bind(render::vertex_attribute::position, position_attribute); @@ -109,67 +93,198 @@ bloom_pass::bloom_pass(gl::rasterizer* rasterizer, const gl::framebuffer* frameb bloom_pass::~bloom_pass() { - delete cloned_framebuffer; - delete cloned_framebuffer_texture; - delete quad_vao; - delete quad_vbo; + set_mip_chain_length(0); } void bloom_pass::render(const render::context& ctx, render::queue& queue) const -{ - glDisable(GL_BLEND); +{ + if (!source_texture || !mip_chain_length) + return; + + // Disable depth testing glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); + + // Enable back-face culling glEnable(GL_CULL_FACE); glCullFace(GL_BACK); - - // Determine viewport based on framebuffer resolution - auto viewport = framebuffer->get_dimensions(); - rasterizer->set_viewport(0, 0, std::get<0>(viewport), std::get<1>(viewport)); - float2 resolution = {std::get<0>(viewport), std::get<1>(viewport)}; - // Perform brightness threshold subpass, rendering to the first pingpong fbo - rasterizer->use_framebuffer(*pingpong_framebuffers[0]); - rasterizer->use_program(*threshold_shader); - threshold_shader_image_input->upload(source_texture); - threshold_shader_resolution_input->upload(resolution); - threshold_shader_threshold_input->upload(brightness_threshold); - rasterizer->draw_arrays(*quad_vao, gl::drawing_mode::triangles, 0, 6); + // Disable blending + glDisable(GL_BLEND); - // Perform iterative blur subpass - const float2 direction_horizontal = {1, 0}; - const float2 direction_vertical = {0, 1}; - rasterizer->use_program(*blur_shader); - blur_shader_resolution_input->upload(resolution); - for (int i = 0; i < blur_iterations; ++i) + // Downsample first mip with Karis average { - // Perform horizontal blur - rasterizer->use_framebuffer(*pingpong_framebuffers[1]); - blur_shader_image_input->upload(pingpong_textures[0]); - blur_shader_direction_input->upload(direction_horizontal); + rasterizer->use_program(*downsample_karis_shader); + downsample_karis_source_texture_input->upload(source_texture); + downsample_karis_texel_size_input->upload(source_texel_size); + + rasterizer->use_framebuffer(*framebuffers[0]); + rasterizer->set_viewport(0, 0, textures[0]->get_width(), textures[0]->get_height()); + rasterizer->draw_arrays(*quad_vao, gl::drawing_mode::triangles, 0, 6); + } + + // Downsample remaining mips + rasterizer->use_program(*downsample_shader); + for (int i = 1; i < static_cast(mip_chain_length); ++i) + { + rasterizer->use_framebuffer(*framebuffers[i]); + rasterizer->set_viewport(0, 0, textures[i]->get_width(), textures[i]->get_height()); + + // Use previous downsample texture as downsample source + downsample_source_texture_input->upload(textures[i - 1]); + downsample_texel_size_input->upload(texel_sizes[i - 1]); + + rasterizer->draw_arrays(*quad_vao, gl::drawing_mode::triangles, 0, 6); + } + + // Enable additive blending + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + glBlendEquation(GL_FUNC_ADD); + + // Upsample + rasterizer->use_program(*upsample_shader); + upsample_filter_radius_input->upload(corrected_filter_radius); + for (int i = static_cast(mip_chain_length) - 1; i > 0; --i) + { + const int j = i - 1; + rasterizer->use_framebuffer(*framebuffers[j]); + rasterizer->set_viewport(0, 0, textures[j]->get_width(), textures[j]->get_height()); + + upsample_source_texture_input->upload(textures[i]); - // Perform vertical blur - rasterizer->use_framebuffer(*pingpong_framebuffers[0]); - blur_shader_image_input->upload(pingpong_textures[1]); - blur_shader_direction_input->upload(direction_vertical); rasterizer->draw_arrays(*quad_vao, gl::drawing_mode::triangles, 0, 6); } } +void bloom_pass::resize() +{ + unsigned int source_width = 0; + unsigned int source_height = 0; + source_texel_size = {0.0f, 0.0f}; + if (source_texture) + { + // Get source texture dimensions + source_width = source_texture->get_width(); + source_height = source_texture->get_height(); + + // Update source texel size + source_texel_size.x() = 1.0f / static_cast(source_texture->get_width()); + source_texel_size.y() = 1.0f / static_cast(source_texture->get_height()); + + // Correct filter radius according to source texture aspect ratio + corrected_filter_radius = {filter_radius * (source_texel_size.x() / source_texel_size.y()), filter_radius}; + } + + // Resize mip chain + for (unsigned int i = 0; i < mip_chain_length; ++i) + { + // Calculate mip dimensions + unsigned int mip_width = std::max(1, source_width >> (i + 1)); + unsigned int mip_height = std::max(1, source_height >> (i + 1)); + + // Resize mip texture + textures[i]->resize(mip_width, mip_height, nullptr); + + // Resize mip framebuffer + framebuffers[i]->resize({(int)mip_width, (int)mip_height}); + + // Update mip texel size + texel_sizes[i] = 1.0f / float2{static_cast(mip_width), static_cast(mip_height)}; + } +} + void bloom_pass::set_source_texture(const gl::texture_2d* texture) { - this->source_texture = texture; + if (texture != source_texture) + { + if (texture) + { + if (source_texture) + { + if (texture->get_width() != source_texture->get_width() || texture->get_height() != source_texture->get_height()) + { + source_texture = texture; + resize(); + } + else + { + source_texture = texture; + } + } + else + { + source_texture = texture; + resize(); + } + } + else + { + source_texture = texture; + } + } } -void bloom_pass::set_brightness_threshold(float threshold) +void bloom_pass::set_mip_chain_length(unsigned int length) { - this->brightness_threshold = threshold; + unsigned int source_width = 0; + unsigned int source_height = 0; + if (source_texture) + { + // Get source texture dimensions + source_width = source_texture->get_width(); + source_height = source_texture->get_height(); + } + + if (length > mip_chain_length) + { + // Generate additional framebuffers + for (unsigned int i = mip_chain_length; i < length; ++i) + { + // Calculate mip resolution + unsigned int mip_width = std::max(1, source_width >> (i + 1)); + unsigned int mip_height = std::max(1, source_height >> (i + 1)); + + // Generate mip texture + gl::texture_2d* texture = new gl::texture_2d(mip_width, mip_height, gl::pixel_type::float_16, gl::pixel_format::rgb); + texture->set_wrapping(gl::texture_wrapping::extend, gl::texture_wrapping::extend); + texture->set_filters(gl::texture_min_filter::linear, gl::texture_mag_filter::linear); + texture->set_max_anisotropy(0.0f); + textures.push_back(texture); + + // Generate mip framebuffer + gl::framebuffer* framebuffer = new gl::framebuffer(mip_width, mip_height); + framebuffer->attach(gl::framebuffer_attachment_type::color, texture); + framebuffers.push_back(framebuffer); + + // Calculate mip texel size + texel_sizes.push_back(1.0f / float2{static_cast(mip_width), static_cast(mip_height)}); + } + } + else if (length < mip_chain_length) + { + // Free excess framebuffers + while (framebuffers.size() > length) + { + delete framebuffers.back(); + framebuffers.pop_back(); + + delete textures.back(); + textures.pop_back(); + + texel_sizes.pop_back(); + } + } + + // Update mip chain length + mip_chain_length = length; } -void bloom_pass::set_blur_iterations(int iterations) +void bloom_pass::set_filter_radius(float radius) noexcept { - this->blur_iterations = iterations; + filter_radius = radius; + corrected_filter_radius = {filter_radius * (source_texel_size.x() / source_texel_size.y()), filter_radius}; } } // namespace render diff --git a/src/render/passes/bloom-pass.hpp b/src/render/passes/bloom-pass.hpp index 4c1bab4..d30c1f7 100644 --- a/src/render/passes/bloom-pass.hpp +++ b/src/render/passes/bloom-pass.hpp @@ -32,43 +32,98 @@ class resource_manager; namespace render { /** + * Physically-based bloom render pass. * + * @see Jimenez, J. (2014). Next generation post processing in call of duty advanced warfare. SIGGRAPH Advances in Real-Time Rendering. + * @see https://learnopengl.com/Guest-Articles/2022/Phys.-Based-Bloom */ class bloom_pass: public pass { public: - bloom_pass(gl::rasterizer* rasterizer, const gl::framebuffer* framebuffer, resource_manager* resource_manager); + /** + * Constructs a bloom pass. + * + * @param rasterizer Rasterizer. + * @param resource_manager Resource manager. + */ + bloom_pass(gl::rasterizer* rasterizer, resource_manager* resource_manager); + + /** + * Destructs a bloom pass. + */ virtual ~bloom_pass(); + + /** + * Renders a bloom texture. + * + * @param ctx Render context. + * @param queue Render queue. + */ virtual void render(const render::context& ctx, render::queue& queue) const final; + /** + * Resizes the mip chain resolution according to the resolution of the source texture. + */ + void resize(); + + /** + * Sets the bloom source texture. + * + * @param texture Bloom source texture. + */ void set_source_texture(const gl::texture_2d* texture); - void set_brightness_threshold(float threshold); - void set_blur_iterations(int iterations); + + /** + * Sets the mip chain length. A length of `1` indicates a single stage bloom. + * + * @param length Mip chain length. + */ + void set_mip_chain_length(unsigned int length); + + /** + * Sets the upsample filter radius. + * + * @param radius Upsample filter radius, in texture coordinates. + */ + void set_filter_radius(float radius) noexcept; + + /** + * Returns the texture containing the bloom result. + */ + const gl::texture_2d* get_bloom_texture() const; private: - gl::vertex_buffer* quad_vbo; - gl::vertex_array* quad_vao; + const gl::texture_2d* source_texture; + float2 source_texel_size; - const gl::framebuffer* pingpong_framebuffers[2]; - const gl::texture_2d* pingpong_textures[2]; - gl::texture_2d* cloned_framebuffer_texture; - gl::framebuffer* cloned_framebuffer; + gl::shader_program* downsample_karis_shader; + const gl::shader_input* downsample_karis_source_texture_input; + const gl::shader_input* downsample_karis_texel_size_input; - gl::shader_program* threshold_shader; - const gl::shader_input* threshold_shader_image_input; - const gl::shader_input* threshold_shader_resolution_input; - const gl::shader_input* threshold_shader_threshold_input; + gl::shader_program* downsample_shader; + const gl::shader_input* downsample_source_texture_input; + const gl::shader_input* downsample_texel_size_input; - gl::shader_program* blur_shader; - const gl::shader_input* blur_shader_image_input; - const gl::shader_input* blur_shader_resolution_input; - const gl::shader_input* blur_shader_direction_input; + gl::shader_program* upsample_shader; + const gl::shader_input* upsample_source_texture_input; + const gl::shader_input* upsample_filter_radius_input; - const gl::texture_2d* source_texture; - float brightness_threshold; - int blur_iterations; + gl::vertex_buffer* quad_vbo; + gl::vertex_array* quad_vao; + + unsigned int mip_chain_length; + std::vector framebuffers; + std::vector textures; + std::vector texel_sizes; + float filter_radius; + float2 corrected_filter_radius; }; +inline const gl::texture_2d* bloom_pass::get_bloom_texture() const +{ + return textures.empty() ? nullptr : textures.front(); +} + } // namespace render #endif // ANTKEEPER_RENDER_BLOOM_PASS_HPP diff --git a/src/render/passes/final-pass.cpp b/src/render/passes/final-pass.cpp index 73f4e7d..e4e822c 100644 --- a/src/render/passes/final-pass.cpp +++ b/src/render/passes/final-pass.cpp @@ -41,12 +41,14 @@ final_pass::final_pass(gl::rasterizer* rasterizer, const gl::framebuffer* frameb pass(rasterizer, framebuffer), color_texture(nullptr), bloom_texture(nullptr), + bloom_weight(0.04f), blue_noise_texture(nullptr), - blue_noise_scale(1.0) + blue_noise_scale(1.0f) { shader_program = resource_manager->load("final.glsl"); color_texture_input = shader_program->get_input("color_texture"); bloom_texture_input = shader_program->get_input("bloom_texture"); + bloom_weight_input = shader_program->get_input("bloom_weight"); blue_noise_texture_input = shader_program->get_input("blue_noise_texture"); blue_noise_scale_input = shader_program->get_input("blue_noise_scale"); resolution_input = shader_program->get_input("resolution"); @@ -109,6 +111,8 @@ void final_pass::render(const render::context& ctx, render::queue& queue) const color_texture_input->upload(color_texture); if (bloom_texture && bloom_texture_input) bloom_texture_input->upload(bloom_texture); + if (bloom_weight_input) + bloom_weight_input->upload(bloom_weight); if (blue_noise_texture && blue_noise_texture_input) blue_noise_texture_input->upload(blue_noise_texture); if (blue_noise_scale_input) @@ -127,11 +131,16 @@ void final_pass::set_color_texture(const gl::texture_2d* texture) this->color_texture = texture; } -void final_pass::set_bloom_texture(const gl::texture_2d* texture) +void final_pass::set_bloom_texture(const gl::texture_2d* texture) noexcept { this->bloom_texture = texture; } +void final_pass::set_bloom_weight(float weight) noexcept +{ + this->bloom_weight = weight; +} + void final_pass::set_blue_noise_texture(const gl::texture_2d* texture) { this->blue_noise_texture = texture; diff --git a/src/render/passes/final-pass.hpp b/src/render/passes/final-pass.hpp index 04fe846..b5dc2f4 100644 --- a/src/render/passes/final-pass.hpp +++ b/src/render/passes/final-pass.hpp @@ -42,13 +42,15 @@ public: virtual void render(const render::context& ctx, render::queue& queue) const final; void set_color_texture(const gl::texture_2d* texture); - void set_bloom_texture(const gl::texture_2d* texture); + void set_bloom_texture(const gl::texture_2d* texture) noexcept; + void set_bloom_weight(float weight) noexcept; void set_blue_noise_texture(const gl::texture_2d* texture); private: gl::shader_program* shader_program; const gl::shader_input* color_texture_input; const gl::shader_input* bloom_texture_input; + const gl::shader_input* bloom_weight_input; const gl::shader_input* blue_noise_texture_input; const gl::shader_input* blue_noise_scale_input; const gl::shader_input* resolution_input; @@ -58,6 +60,7 @@ private: const gl::texture_2d* color_texture; const gl::texture_2d* bloom_texture; + float bloom_weight; const gl::texture_2d* blue_noise_texture; float blue_noise_scale; }; diff --git a/src/render/passes/sky-pass.cpp b/src/render/passes/sky-pass.cpp index dca08d8..6ba5119 100644 --- a/src/render/passes/sky-pass.cpp +++ b/src/render/passes/sky-pass.cpp @@ -215,8 +215,8 @@ void sky_pass::render(const render::context& ctx, render::queue& queue) const float3 sun_direction = math::normalize(sun_position); // Interpolate and expose sun luminance and illuminance - float3 sun_luminance = sun_luminance_tween.interpolate(ctx.alpha) * ctx.exposure; float3 sun_illuminance = sun_illuminance_tween.interpolate(ctx.alpha) * ctx.exposure; + float3 sun_luminance = sun_luminance_tween.interpolate(ctx.alpha) * ctx.exposure; float3 moon_position = moon_position_tween.interpolate(ctx.alpha); float3 moon_direction = math::normalize(moon_position);