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
This commit is contained in:
Omar Emara 2022-09-09 13:15:01 +02:00
parent 77a4bb02cc
commit ac66a819c1
5 changed files with 69 additions and 0 deletions

View File

@ -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);

View File

@ -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]);

View File

@ -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]);

View File

@ -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

View File

@ -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)