diff options
author | Omar Emara <mail@OmarEmara.dev> | 2022-10-11 14:22:52 +0300 |
---|---|---|
committer | Omar Emara <mail@OmarEmara.dev> | 2022-10-11 14:22:52 +0300 |
commit | 0037411f55ec3da4cfad79575d5531869ae5dc38 (patch) | |
tree | 92070a51c4ee039729fe2192649602b76b3af244 /source/blender/nodes | |
parent | f6a69920313255277ad1c21fcb813ee6ac774db7 (diff) |
Realtime Compositor: Implement parallel reduction
This patch implements generic parallel reduction for the realtime
compositor and implements the Levels operation as an example. This patch
also introduces the notion of a "Compositor Algorithm", which is a
reusable operation that can be used to construct other operations.
Differential Revision: https://developer.blender.org/D16184
Reviewed By: Clement Foucault
Diffstat (limited to 'source/blender/nodes')
-rw-r--r-- | source/blender/nodes/composite/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/nodes/composite/nodes/node_composite_levels.cc | 144 |
2 files changed, 142 insertions, 3 deletions
diff --git a/source/blender/nodes/composite/CMakeLists.txt b/source/blender/nodes/composite/CMakeLists.txt index 2537e8e93cc..4255a2dde21 100644 --- a/source/blender/nodes/composite/CMakeLists.txt +++ b/source/blender/nodes/composite/CMakeLists.txt @@ -18,6 +18,7 @@ set(INC ../../render ../../windowmanager ../../compositor/realtime_compositor + ../../compositor/realtime_compositor/algorithms ../../../../intern/guardedalloc # dna_type_offsets.h diff --git a/source/blender/nodes/composite/nodes/node_composite_levels.cc b/source/blender/nodes/composite/nodes/node_composite_levels.cc index a4fe1f33813..4c901372b9f 100644 --- a/source/blender/nodes/composite/nodes/node_composite_levels.cc +++ b/source/blender/nodes/composite/nodes/node_composite_levels.cc @@ -5,9 +5,18 @@ * \ingroup cmpnodes */ +#include <cmath> + +#include "BLI_assert.h" +#include "BLI_math_vec_types.hh" +#include "BLI_math_vector.hh" + #include "UI_interface.h" #include "UI_resources.h" +#include "IMB_colormanagement.h" + +#include "COM_algorithm_parallel_reduction.hh" #include "COM_node_operation.hh" #include "node_composite_util.hh" @@ -18,7 +27,9 @@ namespace blender::nodes::node_composite_levels_cc { static void cmp_node_levels_declare(NodeDeclarationBuilder &b) { - b.add_input<decl::Color>(N_("Image")).default_value({0.0f, 0.0f, 0.0f, 1.0f}); + b.add_input<decl::Color>(N_("Image")) + .default_value({0.0f, 0.0f, 0.0f, 1.0f}) + .compositor_domain_priority(0); b.add_output<decl::Float>(N_("Mean")); b.add_output<decl::Float>(N_("Std Dev")); } @@ -36,13 +47,140 @@ static void node_composit_buts_view_levels(uiLayout *layout, bContext * /*C*/, P using namespace blender::realtime_compositor; class LevelsOperation : public NodeOperation { + private: + constexpr static float luminance_coefficients_bt709_[3] = {0.2126f, 0.7152f, 0.0722f}; + public: using NodeOperation::NodeOperation; void execute() override { - get_result("Mean").allocate_invalid(); - get_result("Std Dev").allocate_invalid(); + if (get_input("Image").is_single_value()) { + execute_single_value(); + return; + } + + const float mean = compute_mean(); + + Result &mean_result = get_result("Mean"); + if (mean_result.should_compute()) { + mean_result.allocate_single_value(); + mean_result.set_float_value(mean); + } + + Result &standard_deviation_result = get_result("Std Dev"); + if (standard_deviation_result.should_compute()) { + const float standard_deviation = compute_standard_deviation(mean); + standard_deviation_result.allocate_single_value(); + standard_deviation_result.set_float_value(standard_deviation); + } + } + + void execute_single_value() + { + Result &standard_deviation_result = get_result("Std Dev"); + if (standard_deviation_result.should_compute()) { + standard_deviation_result.allocate_single_value(); + standard_deviation_result.set_float_value(0.0f); + } + + Result &mean_result = get_result("Mean"); + if (!mean_result.should_compute()) { + return; + } + + mean_result.allocate_single_value(); + const float3 input = float3(get_input("Image").get_color_value()); + + switch (get_channel()) { + case CMP_NODE_LEVLES_RED: + mean_result.set_float_value(input.x); + break; + case CMP_NODE_LEVLES_GREEN: + mean_result.set_float_value(input.y); + break; + case CMP_NODE_LEVLES_BLUE: + mean_result.set_float_value(input.z); + break; + case CMP_NODE_LEVLES_LUMINANCE_BT709: + mean_result.set_float_value(math::dot(input, float3(luminance_coefficients_bt709_))); + break; + case CMP_NODE_LEVLES_LUMINANCE: { + float luminance_coefficients[3]; + IMB_colormanagement_get_luminance_coefficients(luminance_coefficients); + mean_result.set_float_value(math::dot(input, float3(luminance_coefficients))); + break; + } + default: + BLI_assert_unreachable(); + break; + } + } + + float compute_mean() + { + const Result &input = get_input("Image"); + return compute_sum() / (input.domain().size.x * input.domain().size.y); + } + + float compute_sum() + { + const Result &input = get_input("Image"); + switch (get_channel()) { + case CMP_NODE_LEVLES_RED: + return sum_red(context(), input.texture()); + case CMP_NODE_LEVLES_GREEN: + return sum_green(context(), input.texture()); + case CMP_NODE_LEVLES_BLUE: + return sum_blue(context(), input.texture()); + case CMP_NODE_LEVLES_LUMINANCE_BT709: + return sum_luminance(context(), input.texture(), float3(luminance_coefficients_bt709_)); + case CMP_NODE_LEVLES_LUMINANCE: { + float luminance_coefficients[3]; + IMB_colormanagement_get_luminance_coefficients(luminance_coefficients); + return sum_luminance(context(), input.texture(), float3(luminance_coefficients)); + } + default: + BLI_assert_unreachable(); + return 0.0f; + } + } + + float compute_standard_deviation(float mean) + { + const Result &input = get_input("Image"); + const float sum = compute_sum_squared_difference(mean); + return std::sqrt(sum / (input.domain().size.x * input.domain().size.y)); + } + + float compute_sum_squared_difference(float subtrahend) + { + const Result &input = get_input("Image"); + switch (get_channel()) { + case CMP_NODE_LEVLES_RED: + return sum_red_squared_difference(context(), input.texture(), subtrahend); + case CMP_NODE_LEVLES_GREEN: + return sum_green_squared_difference(context(), input.texture(), subtrahend); + case CMP_NODE_LEVLES_BLUE: + return sum_blue_squared_difference(context(), input.texture(), subtrahend); + case CMP_NODE_LEVLES_LUMINANCE_BT709: + return sum_luminance_squared_difference( + context(), input.texture(), float3(luminance_coefficients_bt709_), subtrahend); + case CMP_NODE_LEVLES_LUMINANCE: { + float luminance_coefficients[3]; + IMB_colormanagement_get_luminance_coefficients(luminance_coefficients); + return sum_luminance_squared_difference( + context(), input.texture(), float3(luminance_coefficients), subtrahend); + } + default: + BLI_assert_unreachable(); + return 0.0f; + } + } + + CMPNodeLevelsChannel get_channel() + { + return static_cast<CMPNodeLevelsChannel>(bnode().custom1); } }; |