[Bf-blender-cvs] [ac66a819c14] master: Realtime Compositor: Implement pixelate node

Omar Emara noreply at git.blender.org
Fri Sep 9 13:16:10 CEST 2022


Commit: ac66a819c14265ee3e0f48e4cb54b6c10b7fb064
Author: Omar Emara
Date:   Fri Sep 9 13:15:01 2022 +0200
Branches: master
https://developer.blender.org/rBac66a819c14265ee3e0f48e4cb54b6c10b7fb064

Realtime Compositor: Implement pixelate node

This patch implements the pixelate node for the realtime compositor.

Differential Revision: https://developer.blender.org/D15662

Reviewed By: Clement Foucault

===================================================================

M	source/blender/blenlib/BLI_float3x3.hh
M	source/blender/blenlib/BLI_math_matrix.h
M	source/blender/blenlib/intern/math_matrix.c
M	source/blender/blenlib/tests/BLI_float3x3_test.cc
M	source/blender/nodes/composite/nodes/node_composite_pixelate.cc

===================================================================

diff --git a/source/blender/blenlib/BLI_float3x3.hh b/source/blender/blenlib/BLI_float3x3.hh
index 6a9e7dd04f0..178973c155d 100644
--- a/source/blender/blenlib/BLI_float3x3.hh
+++ b/source/blender/blenlib/BLI_float3x3.hh
@@ -63,6 +63,15 @@ struct float3x3 {
     return result;
   }
 
+  static float3x3 from_scale(const float2 scale)
+  {
+    float3x3 result = zero();
+    result.values[0][0] = scale.x;
+    result.values[1][1] = scale.y;
+    result.values[2][2] = 1.0f;
+    return result;
+  }
+
   static float3x3 from_translation_rotation_scale(const float2 translation,
                                                   float rotation,
                                                   const float2 scale)
@@ -190,6 +199,13 @@ struct float3x3 {
     return result;
   }
 
+  float2 scale_2d() const
+  {
+    float2 scale;
+    mat3_to_size_2d(scale, values);
+    return scale;
+  }
+
   friend bool operator==(const float3x3 &a, const float3x3 &b)
   {
     return equals_m3m3(a.values, b.values);
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index 467e6db4805..19943614881 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -410,6 +410,8 @@ float mat4_to_xy_scale(const float mat[4][4]);
 void size_to_mat3(float R[3][3], const float size[3]);
 void size_to_mat4(float R[4][4], const float size[3]);
 
+/** Return 2D size assuming the given matrix is a 2D affine matrix. */
+void mat3_to_size_2d(float size[2], const float M[3][3]);
 void mat3_to_size(float size[3], const float M[3][3]);
 void mat4_to_size(float size[3], const float M[4][4]);
 
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index e96b12033a9..221ae84e74d 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -2127,6 +2127,12 @@ void size_to_mat4(float R[4][4], const float size[3])
   R[3][3] = 1.0f;
 }
 
+void mat3_to_size_2d(float size[2], const float M[3][3])
+{
+  size[0] = len_v2(M[0]);
+  size[1] = len_v2(M[1]);
+}
+
 void mat3_to_size(float size[3], const float M[3][3])
 {
   size[0] = len_v3(M[0]);
diff --git a/source/blender/blenlib/tests/BLI_float3x3_test.cc b/source/blender/blenlib/tests/BLI_float3x3_test.cc
index d22993ee69e..cd823b6e368 100644
--- a/source/blender/blenlib/tests/BLI_float3x3_test.cc
+++ b/source/blender/blenlib/tests/BLI_float3x3_test.cc
@@ -34,6 +34,15 @@ TEST(float3x3, Rotation)
   EXPECT_FLOAT_EQ(result[1], 1.0f);
 }
 
+TEST(float3x3, Scale)
+{
+  float2 point(1.0f, 2.0f);
+  float3x3 transformation = float3x3::from_scale(float2(2.0f, 3.0f));
+  float2 result = transformation * point;
+  EXPECT_FLOAT_EQ(result[0], 2.0f);
+  EXPECT_FLOAT_EQ(result[1], 6.0f);
+}
+
 TEST(float3x3, TranslationRotationScale)
 {
   float2 point(1.0f, 2.0f);
@@ -116,4 +125,11 @@ TEST(float3x3, Origin)
   EXPECT_FLOAT_EQ(result[1], 3.0f);
 }
 
+TEST(float3x3, GetScale2D)
+{
+  float2 scale(2.0f, 3.0f);
+  float3x3 transformation = float3x3::from_scale(scale);
+  EXPECT_EQ(scale, transformation.scale_2d());
+}
+
 }  // namespace blender::tests
diff --git a/source/blender/nodes/composite/nodes/node_composite_pixelate.cc b/source/blender/nodes/composite/nodes/node_composite_pixelate.cc
index 4567464a547..c4e42f8247d 100644
--- a/source/blender/nodes/composite/nodes/node_composite_pixelate.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_pixelate.cc
@@ -5,6 +5,9 @@
  * \ingroup cmpnodes
  */
 
+#include "BLI_math_vec_types.hh"
+#include "BLI_math_vector.hh"
+
 #include "COM_node_operation.hh"
 
 #include "node_composite_util.hh"
@@ -27,8 +30,34 @@ class PixelateOperation : public 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. */
     get_input("Color").pass_through(get_result("Color"));
   }
+
+  /* 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)



More information about the Bf-blender-cvs mailing list