Blender V4.3
compositor/realtime_compositor/algorithms/intern/transform.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
6#include "BLI_math_matrix.hh"
9
10#include "GPU_capabilities.hh"
11#include "GPU_shader.hh"
12#include "GPU_texture.hh"
13
15#include "COM_context.hh"
16#include "COM_domain.hh"
17#include "COM_result.hh"
18
20
22
23/* Given a potentially transformed domain, compute a domain such that its rotation and scale become
24 * identity and the size of the domain is increased/reduced to adapt to the new transformation. For
25 * instance, if the domain is rotated, the returned domain will have zero rotation but expanded
26 * size to account for the bounding box of the domain after rotation. The size of the returned
27 * domain is bound and clipped by the maximum possible GPU texture size to avoid allocations that
28 * surpass hardware limits, which is typically 16k. */
30{
31 math::AngleRadian rotation;
32 float2 translation, scale;
33 float2 size = float2(domain.size);
34 math::to_loc_rot_scale(domain.transformation, translation, rotation, scale);
35
36 /* Set the rotation to zero and expand the domain size to fit the bounding box of the rotated
37 * result. */
38 const float sine = math::abs(math::sin(rotation));
39 const float cosine = math::abs(math::cos(rotation));
40 size = float2(size.x * cosine + size.y * sine, size.x * sine + size.y * cosine);
41 rotation = 0.0f;
42
43 /* Set the scale to 1 and scale the domain size to adapt to the new domain. */
44 size *= scale;
45 scale = float2(1.0f);
46
47 const float3x3 transformation = math::from_loc_rot_scale<float3x3>(translation, rotation, scale);
48
49 const int2 domain_size = math::clamp(
51
52 return Domain(domain_size, transformation);
53}
54
55void transform(Context &context,
56 Result &input,
57 Result &output,
58 const float3x3 &transformation,
59 RealizationOptions realization_options)
60{
61 /* If we are wrapping, the input is translated but the target domain remains fixed, which results
62 * in the input clipping on one side and wrapping on the opposite side. This mask vector can be
63 * multiplied to the translation component of the transformation to remove it. */
64 const float2 wrap_mask = float2(realization_options.wrap_x ? 0.0f : 1.0f,
65 realization_options.wrap_y ? 0.0f : 1.0f);
66
67 /* Compute a transformed input domain, excluding translations of wrapped axes. */
68 Domain input_domain = input.domain();
69 float3x3 domain_transformation = transformation;
70 domain_transformation.location() *= wrap_mask;
71 input_domain.transform(domain_transformation);
72
73 /* Realize the input on the target domain using the full transformation. */
74 const Domain target_domain = compute_realized_transformation_domain(input_domain);
75 realize_on_domain(context,
76 input,
77 output,
78 target_domain,
79 transformation * input.domain().transformation,
80 realization_options);
81
82 output.get_realization_options().interpolation = realization_options.interpolation;
83}
84
85} // namespace blender::realtime_compositor
int GPU_max_texture_size()
T cos(const AngleRadianBase< T > &a)
T clamp(const T &a, const T &min, const T &max)
T sin(const AngleRadianBase< T > &a)
T abs(const T &a)
void to_loc_rot_scale(const MatBase< T, 3, 3 > &mat, VecBase< T, 2 > &r_location, AngleRadianBase< T > &r_rotation, VecBase< T, 2 > &r_scale)
T round(const T &a)
MatT from_loc_rot_scale(const typename MatT::loc_type &location, const RotationT &rotation, const VecBase< typename MatT::base_type, ScaleDim > &scale)
void transform(Context &context, Result &input, Result &output, const float3x3 &transformation, RealizationOptions realization_options)
void realize_on_domain(Context &context, Result &input, Result &output, const Domain &domain, const float3x3 &input_transformation, const RealizationOptions &realization_options)
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2