diff options
Diffstat (limited to 'source/blender/nodes/composite/nodes/node_composite_pixelate.cc')
-rw-r--r-- | source/blender/nodes/composite/nodes/node_composite_pixelate.cc | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/source/blender/nodes/composite/nodes/node_composite_pixelate.cc b/source/blender/nodes/composite/nodes/node_composite_pixelate.cc index 529aa0f84de..c65bb7bb747 100644 --- a/source/blender/nodes/composite/nodes/node_composite_pixelate.cc +++ b/source/blender/nodes/composite/nodes/node_composite_pixelate.cc @@ -5,6 +5,11 @@ * \ingroup cmpnodes */ +#include "BLI_math_vec_types.hh" +#include "BLI_math_vector.hh" + +#include "COM_node_operation.hh" + #include "node_composite_util.hh" /* **************** Pixelate ******************** */ @@ -17,6 +22,52 @@ static void cmp_node_pixelate_declare(NodeDeclarationBuilder &b) b.add_output<decl::Color>(N_("Color")); } +using namespace blender::realtime_compositor; + +class PixelateOperation : public NodeOperation { + public: + using NodeOperation::NodeOperation; + + void execute() override + { + /* It might seems strange that the input is passed through without any processing, but note + * that the actual processing happens inside the domain realization input processor of the + * input. Indeed, the pixelate node merely realizes its input on a smaller-sized domain that + * matches its apparent size, that is, its size after the domain transformation. The pixelate + * node has no effect if the input is scaled-up. See the compute_domain method for more + * information. */ + Result &result = get_result("Color"); + get_input("Color").pass_through(result); + + result.get_realization_options().interpolation = Interpolation::Nearest; + } + + /* Compute a smaller-sized domain that matches the apparent size of the input while having a unit + * scale transformation, see the execute method for more information. */ + Domain compute_domain() override + { + Domain domain = get_input("Color").domain(); + + /* Get the scaling component of the domain transformation, but make sure it doesn't exceed 1, + * because pixelation should only happen if the input is scaled down. */ + const float2 scale = math::min(float2(1.0f), domain.transformation.scale_2d()); + + /* Multiply the size of the domain by its scale to match its apparent size, but make sure it is + * at least 1 pixel in both axis. */ + domain.size = math::max(int2(float2(domain.size) * scale), int2(1)); + + /* Reset the scale of the transformation by transforming it with the inverse of the scale. */ + domain.transformation *= float3x3::from_scale(math::safe_divide(float2(1.0f), scale)); + + return domain; + } +}; + +static NodeOperation *get_compositor_operation(Context &context, DNode node) +{ + return new PixelateOperation(context, node); +} + } // namespace blender::nodes::node_composite_pixelate_cc void register_node_type_cmp_pixelate() @@ -27,6 +78,7 @@ void register_node_type_cmp_pixelate() cmp_node_type_base(&ntype, CMP_NODE_PIXELATE, "Pixelate", NODE_CLASS_OP_FILTER); ntype.declare = file_ns::cmp_node_pixelate_declare; + ntype.get_compositor_operation = file_ns::get_compositor_operation; nodeRegisterType(&ntype); } |