From 885e7abed13b204a701466a203f6d96773de902a Mon Sep 17 00:00:00 2001 From: Omar Emara Date: Thu, 18 Aug 2022 17:14:29 +0200 Subject: Realtime Compositor: Implement bilateral blur node This patch implements the bilateral blur node for the realtime compositor. Differential Revision: https://developer.blender.org/D15674 Reviewed By: Clement Foucault --- source/blender/gpu/CMakeLists.txt | 2 + .../compositor/compositor_bilateral_blur.glsl | 31 +++++++++++++ .../infos/compositor_bilateral_blur_info.hh | 13 ++++++ .../nodes/node_composite_bilateralblur.cc | 51 +++++++++++++++++++++- 4 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 source/blender/gpu/shaders/compositor/compositor_bilateral_blur.glsl create mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_bilateral_blur_info.hh (limited to 'source/blender') diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 40ede29eab6..9469db1d842 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -315,6 +315,7 @@ set(GLSL_SRC shaders/common/gpu_shader_common_mix_rgb.glsl shaders/compositor/compositor_alpha_crop.glsl + shaders/compositor/compositor_bilateral_blur.glsl shaders/compositor/compositor_bokeh_image.glsl shaders/compositor/compositor_box_mask.glsl shaders/compositor/compositor_convert.glsl @@ -566,6 +567,7 @@ set(SRC_SHADER_CREATE_INFOS shaders/infos/gpu_srgb_to_framebuffer_space_info.hh shaders/compositor/infos/compositor_alpha_crop_info.hh + shaders/compositor/infos/compositor_bilateral_blur_info.hh shaders/compositor/infos/compositor_bokeh_image_info.hh shaders/compositor/infos/compositor_box_mask_info.hh shaders/compositor/infos/compositor_convert_info.hh diff --git a/source/blender/gpu/shaders/compositor/compositor_bilateral_blur.glsl b/source/blender/gpu/shaders/compositor/compositor_bilateral_blur.glsl new file mode 100644 index 00000000000..c7c5ada7a9f --- /dev/null +++ b/source/blender/gpu/shaders/compositor/compositor_bilateral_blur.glsl @@ -0,0 +1,31 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + vec4 center_determinator = texture_load(determinator_tx, texel); + + /* Go over the pixels in the blur window of the specified radius around the center pixel, and for + * pixels whose determinator is close enough to the determinator of the center pixel, accumulate + * their color as well as their weights. */ + float accumulated_weight = 0.0; + vec4 accumulated_color = vec4(0.0); + for (int y = -radius; y <= radius; y++) { + for (int x = -radius; x <= radius; x++) { + vec4 determinator = texture_load(determinator_tx, texel + ivec2(x, y)); + float difference = dot(abs(center_determinator - determinator).rgb, vec3(1.0)); + + if (difference < threshold) { + accumulated_weight += 1.0; + accumulated_color += texture_load(input_tx, texel + ivec2(x, y)); + } + } + } + + /* Write the accumulated color divided by the accumulated weight if any pixel in the window was + * accumulated, otherwise, write a fallback black color. */ + vec4 fallback = vec4(vec3(0.0), 1.0); + vec4 color = (accumulated_weight != 0.0) ? (accumulated_color / accumulated_weight) : fallback; + imageStore(output_img, texel, color); +} diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_bilateral_blur_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_bilateral_blur_info.hh new file mode 100644 index 00000000000..301cd6acd9e --- /dev/null +++ b/source/blender/gpu/shaders/compositor/infos/compositor_bilateral_blur_info.hh @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_bilateral_blur) + .local_group_size(16, 16) + .push_constant(Type::INT, "radius") + .push_constant(Type::FLOAT, "threshold") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .sampler(1, ImageType::FLOAT_2D, "determinator_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_bilateral_blur.glsl") + .do_static_compilation(true); diff --git a/source/blender/nodes/composite/nodes/node_composite_bilateralblur.cc b/source/blender/nodes/composite/nodes/node_composite_bilateralblur.cc index 66a321eb088..355ec42f221 100644 --- a/source/blender/nodes/composite/nodes/node_composite_bilateralblur.cc +++ b/source/blender/nodes/composite/nodes/node_composite_bilateralblur.cc @@ -5,10 +5,15 @@ * \ingroup cmpnodes */ +#include "BLI_math_base.hh" + #include "UI_interface.h" #include "UI_resources.h" +#include "GPU_shader.h" + #include "COM_node_operation.hh" +#include "COM_utilities.hh" #include "node_composite_util.hh" @@ -52,7 +57,51 @@ class BilateralBlurOperation : public NodeOperation { void execute() override { - get_input("Image").pass_through(get_result("Image")); + const Result &input_image = get_input("Image"); + /* Single value inputs can't be blurred and are returned as is. */ + if (input_image.is_single_value()) { + get_input("Image").pass_through(get_result("Image")); + return; + } + + GPUShader *shader = shader_manager().get("compositor_bilateral_blur"); + GPU_shader_bind(shader); + + GPU_shader_uniform_1i(shader, "radius", get_blur_radius()); + GPU_shader_uniform_1f(shader, "threshold", get_threshold()); + + input_image.bind_as_texture(shader, "input_tx"); + + const Result &determinator_image = get_input("Determinator"); + determinator_image.bind_as_texture(shader, "determinator_tx"); + + const Domain domain = compute_domain(); + Result &output_image = get_result("Image"); + output_image.allocate_texture(domain); + output_image.bind_as_image(shader, "output_img"); + + compute_dispatch_threads_at_least(shader, domain.size); + + GPU_shader_unbind(); + output_image.unbind_as_image(); + input_image.unbind_as_texture(); + determinator_image.unbind_as_texture(); + } + + int get_blur_radius() + { + return math::ceil(get_node_bilateral_blur_data().iter + + get_node_bilateral_blur_data().sigma_space); + } + + float get_threshold() + { + return get_node_bilateral_blur_data().sigma_color; + } + + NodeBilateralBlurData &get_node_bilateral_blur_data() + { + return *static_cast(bnode().storage); } }; -- cgit v1.2.3