Blender V5.0
morphological_blur.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_assert.h"
6#include "BLI_math_base.hh"
8
9#include "GPU_shader.hh"
10
11#include "COM_context.hh"
12#include "COM_result.hh"
13#include "COM_utilities.hh"
14
17
18namespace blender::compositor {
19
20static const char *get_shader(MorphologicalBlurOperation operation)
21{
22 switch (operation) {
24 return "compositor_morphological_blur_dilate";
26 return "compositor_morphological_blur_erode";
27 }
28
30 return nullptr;
31}
32
34 const Result &input,
35 Result &blurred_input,
36 const MorphologicalBlurOperation operation)
37{
38 gpu::Shader *shader = context.get_shader(get_shader(operation));
39 GPU_shader_bind(shader);
40
41 input.bind_as_texture(shader, "input_tx");
42
43 blurred_input.bind_as_image(shader, "blurred_input_img", true);
44
45 Domain domain = input.domain();
47
49 input.unbind_as_texture();
50 blurred_input.unbind_as_image();
51}
52
54 Result &blurred_input,
55 const MorphologicalBlurOperation operation)
56{
57 Domain domain = input.domain();
58 switch (operation) {
60 parallel_for(domain.size, [&](const int2 texel) {
61 float input_value = input.load_pixel<float>(texel);
62 float blurred_value = blurred_input.load_pixel<float>(texel);
63 blurred_input.store_pixel(texel, math::max(input_value, blurred_value));
64 });
65 break;
67 parallel_for(domain.size, [&](const int2 texel) {
68 float input_value = input.load_pixel<float>(texel);
69 float blurred_value = blurred_input.load_pixel<float>(texel);
70 blurred_input.store_pixel(texel, math::min(input_value, blurred_value));
71 });
72 break;
73 }
74}
75
76/* Apply the morphological operator (minimum or maximum) on the input and the blurred input. The
77 * output is written to the blurred_input in-place. */
79 const Result &input,
80 Result &blurred_input,
81 const MorphologicalBlurOperation operation)
82{
83 if (context.use_gpu()) {
84 apply_morphological_operator_gpu(context, input, blurred_input, operation);
85 }
86 else {
87 apply_morphological_operator_cpu(input, blurred_input, operation);
88 }
89}
90
92 const Result &input,
94 const float2 &radius,
95 const MorphologicalBlurOperation operation,
96 const int filter_type)
97{
99
100 symmetric_separable_blur(context, input, output, radius, filter_type);
101 apply_morphological_operator(context, input, output, operation);
102}
103
104} // namespace blender::compositor
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
void GPU_shader_bind(blender::gpu::Shader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
void GPU_shader_unbind()
void unbind_as_image() const
Definition result.cc:517
void bind_as_image(gpu::Shader *shader, const char *image_name, bool read=false) const
Definition result.cc:498
#define input
#define output
void symmetric_separable_blur(Context &context, const Result &input, Result &output, const float2 &radius, const int filter_type=R_FILTER_GAUSS)
void compute_dispatch_threads_at_least(gpu::Shader *shader, int2 threads_range, int2 local_size=int2(16))
Definition utilities.cc:196
static void apply_morphological_operator_gpu(Context &context, const Result &input, Result &blurred_input, const MorphologicalBlurOperation operation)
static void apply_morphological_operator(Context &context, const Result &input, Result &blurred_input, const MorphologicalBlurOperation operation)
void morphological_blur(Context &context, const Result &input, Result &output, const float2 &radius, const MorphologicalBlurOperation operation=MorphologicalBlurOperation::Erode, const int filter_type=R_FILTER_GAUSS)
static const char * get_shader(MorphologicalBlurOperation operation)
static void apply_morphological_operator_cpu(const Result &input, Result &blurred_input, const MorphologicalBlurOperation operation)
void parallel_for(const int2 range, const Function &function)
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2