Blender V4.3
COM_DisplaceOperation.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
6
7namespace blender::compositor {
8
18
20{
22
23 width_x4_ = this->get_width() * 4;
24 height_x4_ = this->get_height() * 4;
25 input_vector_width_ = vector->get_width();
26 input_vector_height_ = vector->get_height();
27}
28
29bool DisplaceOperation::read_displacement(
30 float x, float y, float xscale, float yscale, const float origin[2], float &r_u, float &r_v)
31{
32 float width = input_vector_width_;
33 float height = input_vector_height_;
34 if (x < 0.0f || x >= width || y < 0.0f || y >= height) {
35 r_u = 0.0f;
36 r_v = 0.0f;
37 return false;
38 }
39
40 float col[4];
41 vector_read_fn_(x, y, col);
42 r_u = origin[0] - col[0] * xscale;
43 r_v = origin[1] - col[1] * yscale;
44 return true;
45}
46
47void DisplaceOperation::pixel_transform(const float xy[2], float r_uv[2], float r_deriv[2][2])
48{
49 float col[4];
50 float uv[2]; /* temporary variables for derivative estimation */
51 int num;
52
53 scale_x_read_fn_(xy[0], xy[1], col);
54 float xs = col[0];
55 scale_y_read_fn_(xy[0], xy[1], col);
56 float ys = col[0];
57 /* clamp x and y displacement to triple image resolution -
58 * to prevent hangs from huge values mistakenly plugged in eg. z buffers */
59 CLAMP(xs, -width_x4_, width_x4_);
60 CLAMP(ys, -height_x4_, height_x4_);
61
62 /* displaced pixel in uv coords, for image sampling */
63 read_displacement(xy[0], xy[1], xs, ys, xy, r_uv[0], r_uv[1]);
64
65 /* Estimate partial derivatives using 1-pixel offsets */
66 const float epsilon[2] = {1.0f, 1.0f};
67
68 zero_v2(r_deriv[0]);
69 zero_v2(r_deriv[1]);
70
71 num = 0;
72 if (read_displacement(xy[0] + epsilon[0], xy[1], xs, ys, xy, uv[0], uv[1])) {
73 r_deriv[0][0] += uv[0] - r_uv[0];
74 r_deriv[1][0] += uv[1] - r_uv[1];
75 num++;
76 }
77 if (read_displacement(xy[0] - epsilon[0], xy[1], xs, ys, xy, uv[0], uv[1])) {
78 r_deriv[0][0] += r_uv[0] - uv[0];
79 r_deriv[1][0] += r_uv[1] - uv[1];
80 num++;
81 }
82 if (num > 0) {
83 float numinv = 1.0f / float(num);
84 r_deriv[0][0] *= numinv;
85 r_deriv[1][0] *= numinv;
86 }
87
88 num = 0;
89 if (read_displacement(xy[0], xy[1] + epsilon[1], xs, ys, xy, uv[0], uv[1])) {
90 r_deriv[0][1] += uv[0] - r_uv[0];
91 r_deriv[1][1] += uv[1] - r_uv[1];
92 num++;
93 }
94 if (read_displacement(xy[0], xy[1] - epsilon[1], xs, ys, xy, uv[0], uv[1])) {
95 r_deriv[0][1] += r_uv[0] - uv[0];
96 r_deriv[1][1] += r_uv[1] - uv[1];
97 num++;
98 }
99 if (num > 0) {
100 float numinv = 1.0f / float(num);
101 r_deriv[0][1] *= numinv;
102 r_deriv[1][1] *= numinv;
103 }
104}
105
107 const rcti &output_area,
108 rcti &r_input_area)
109{
110 switch (input_idx) {
111 case 0: {
112 r_input_area = get_input_operation(input_idx)->get_canvas();
113 break;
114 }
115 case 1: {
116 r_input_area = output_area;
118 break;
119 }
120 default: {
121 r_input_area = output_area;
122 break;
123 }
124 }
125}
126
128 const rcti & /*area*/,
130{
131 MemoryBuffer *vector = inputs[1];
132 MemoryBuffer *scale_x = inputs[2];
133 MemoryBuffer *scale_y = inputs[3];
134 vector_read_fn_ = [=](float x, float y, float *out) { vector->read_elem_bilinear(x, y, out); };
135 scale_x_read_fn_ = [=](float x, float y, float *out) { scale_x->read_elem_checked(x, y, out); };
136 scale_y_read_fn_ = [=](float x, float y, float *out) { scale_y->read_elem_checked(x, y, out); };
137}
138
140 const rcti &area,
142{
143 const MemoryBuffer *input_color = inputs[0];
144 for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) {
145 const float xy[2] = {float(it.x), float(it.y)};
146 float uv[2];
147 float deriv[2][2];
148
149 pixel_transform(xy, uv, deriv);
150 if (is_zero_v2(deriv[0]) && is_zero_v2(deriv[1])) {
151 input_color->read_elem_bilinear(uv[0], uv[1], it.out);
152 }
153 else {
154 /* EWA filtering (without nearest it gets blurry with NO distortion). */
155 input_color->read_elem_filtered(uv[0], uv[1], deriv[0], deriv[1], false, it.out);
156 }
157 }
158}
159
160} // namespace blender::compositor
MINLINE bool is_zero_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void zero_v2(float r[2])
#define CLAMP(a, b, c)
void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override
Get input operation area being read by this operation on rendering given output area.
void pixel_transform(const float xy[2], float r_uv[2], float r_deriv[2][2])
void update_memory_buffer_partial(MemoryBuffer *output, const rcti &area, Span< MemoryBuffer * > inputs) override
void update_memory_buffer_started(MemoryBuffer *output, const rcti &area, Span< MemoryBuffer * > inputs) override
a MemoryBuffer contains access to the data
void read_elem_checked(int x, int y, float *out) const
void read_elem_bilinear(float x, float y, float *out) const
void read_elem_filtered(float x, float y, float dx[2], float dy[2], bool extend_boundary, float *out) const
NodeOperation contains calculation logic.
void add_output_socket(DataType datatype)
SocketReader * get_input_socket_reader(unsigned int index)
NodeOperation * get_input_operation(int index)
void add_input_socket(DataType datatype, ResizeMode resize_mode=ResizeMode::Center)
draw_view in_light_buf[] float
uint col
@ Vector
Vector data type.
void expand_area_for_sampler(rcti &area, PixelSampler sampler)
Definition COM_Enums.cc:9
typename BuffersIteratorBuilder< T >::Iterator BuffersIterator
int xy[2]
Definition wm_draw.cc:170