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:
parent
77a4bb02cc
commit
ac66a819c1
|
@ -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);
|
||||
|
|
|
@ -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]);
|
||||
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue