From 079f35572b1dc74427509476c413fb2becdafa14 Mon Sep 17 00:00:00 2001 From: Manuel Castilla Date: Tue, 10 Aug 2021 15:24:05 +0200 Subject: Compositor: Full frame Bilateral Blur node Adds full frame implementation to this node operation. No functional changes. Reviewed By: jbakker Differential Revision: https://developer.blender.org/D11634 --- source/blender/compositor/COM_defines.h | 1 + .../operations/COM_BilateralBlurOperation.cc | 86 +++++++++++++++++++++- .../operations/COM_BilateralBlurOperation.h | 13 +++- 3 files changed, 97 insertions(+), 3 deletions(-) (limited to 'source/blender/compositor') diff --git a/source/blender/compositor/COM_defines.h b/source/blender/compositor/COM_defines.h index 900f29db44c..5b826d8fc08 100644 --- a/source/blender/compositor/COM_defines.h +++ b/source/blender/compositor/COM_defines.h @@ -68,6 +68,7 @@ constexpr int COM_DATA_TYPE_COLOR_CHANNELS = COM_data_type_num_channels(DataType constexpr float COM_COLOR_TRANSPARENT[4] = {0.0f, 0.0f, 0.0f, 0.0f}; constexpr float COM_VECTOR_ZERO[3] = {0.0f, 0.0f, 0.0f}; +constexpr float COM_COLOR_BLACK[4] = {0.0f, 0.0f, 0.0f, 1.0f}; constexpr float COM_VALUE_ZERO[1] = {0.0f}; constexpr float COM_VALUE_ONE[1] = {1.0f}; diff --git a/source/blender/compositor/operations/COM_BilateralBlurOperation.cc b/source/blender/compositor/operations/COM_BilateralBlurOperation.cc index 64448e2ae95..0c1bb688d4e 100644 --- a/source/blender/compositor/operations/COM_BilateralBlurOperation.cc +++ b/source/blender/compositor/operations/COM_BilateralBlurOperation.cc @@ -38,7 +38,6 @@ void BilateralBlurOperation::initExecution() { this->m_inputColorProgram = getInputSocketReader(0); this->m_inputDeterminatorProgram = getInputSocketReader(1); - this->m_space = this->m_data->sigma_space + this->m_data->iter; QualityStepHelper::initExecution(COM_QH_INCREASE); } @@ -115,4 +114,89 @@ bool BilateralBlurOperation::determineDependingAreaOfInterest(rcti *input, return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } +void BilateralBlurOperation::get_area_of_interest(const int UNUSED(input_idx), + const rcti &output_area, + rcti &r_input_area) +{ + const int add = ceil(this->m_space) + 1; + + r_input_area.xmax = output_area.xmax + (add); + r_input_area.xmin = output_area.xmin - (add); + r_input_area.ymax = output_area.ymax + (add); + r_input_area.ymin = output_area.ymin - (add); +} + +struct PixelCursor { + MemoryBuffer *input_determinator; + MemoryBuffer *input_color; + int step; + float sigma_color; + const float *determ_reference_color; + float temp_color[4]; + float *out; + int min_x, max_x; + int min_y, max_y; +}; + +static void blur_pixel(PixelCursor &p) +{ + float blur_divider = 0.0f; + zero_v4(p.out); + + /* TODO(sergey): This isn't really good bilateral filter, it should be + * using gaussian bell for weights. Also sigma_color doesn't seem to be + * used correct at all. + */ + for (int yi = p.min_y; yi < p.max_y; yi += p.step) { + for (int xi = p.min_x; xi < p.max_x; xi += p.step) { + p.input_determinator->read(p.temp_color, xi, yi); + /* Do not take the alpha channel into account. */ + const float delta_color = (fabsf(p.determ_reference_color[0] - p.temp_color[0]) + + fabsf(p.determ_reference_color[1] - p.temp_color[1]) + + fabsf(p.determ_reference_color[2] - p.temp_color[2])); + if (delta_color < p.sigma_color) { + /* Add this to the blur. */ + p.input_color->read(p.temp_color, xi, yi); + add_v4_v4(p.out, p.temp_color); + blur_divider += 1.0f; + } + } + } + + if (blur_divider > 0.0f) { + mul_v4_fl(p.out, 1.0f / blur_divider); + } + else { + copy_v4_v4(p.out, COM_COLOR_BLACK); + } +} + +void BilateralBlurOperation::update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span inputs) +{ + PixelCursor p = {}; + p.step = QualityStepHelper::getStep(); + p.sigma_color = this->m_data->sigma_color; + p.input_color = inputs[0]; + p.input_determinator = inputs[1]; + const float space = this->m_space; + for (int y = area.ymin; y < area.ymax; y++) { + p.out = output->get_elem(area.xmin, y); + /* This will be used as the reference color for the determinator. */ + p.determ_reference_color = p.input_determinator->get_elem(area.xmin, y); + p.min_y = floor(y - space); + p.max_y = ceil(y + space); + for (int x = area.xmin; x < area.xmax; x++) { + p.min_x = floor(x - space); + p.max_x = ceil(x + space); + + blur_pixel(p); + + p.determ_reference_color += p.input_determinator->elem_stride; + p.out += output->elem_stride; + } + } +} + } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_BilateralBlurOperation.h b/source/blender/compositor/operations/COM_BilateralBlurOperation.h index c56cef35050..4819715deb0 100644 --- a/source/blender/compositor/operations/COM_BilateralBlurOperation.h +++ b/source/blender/compositor/operations/COM_BilateralBlurOperation.h @@ -18,12 +18,12 @@ #pragma once -#include "COM_NodeOperation.h" +#include "COM_MultiThreadedOperation.h" #include "COM_QualityStepHelper.h" namespace blender::compositor { -class BilateralBlurOperation : public NodeOperation, public QualityStepHelper { +class BilateralBlurOperation : public MultiThreadedOperation, public QualityStepHelper { private: SocketReader *m_inputColorProgram; SocketReader *m_inputDeterminatorProgram; @@ -55,7 +55,16 @@ class BilateralBlurOperation : public NodeOperation, public QualityStepHelper { void setData(NodeBilateralBlurData *data) { this->m_data = data; + this->m_space = data->sigma_space + data->iter; } + + void get_area_of_interest(int input_idx, + const rcti &output_area, + rcti &r_input_area) override; + + void update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span inputs) override; }; } // namespace blender::compositor -- cgit v1.2.3