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
This commit is contained in:
parent
d8be33333f
commit
885e7abed1
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
|
@ -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<NodeBilateralBlurData *>(bnode().storage);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue