Blender  V3.3
COM_DisplaceOperation.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2011 Blender Foundation. */
3 
5 
6 namespace blender::compositor {
7 
9 {
15  flags_.complex = true;
16 
17  input_color_program_ = nullptr;
18 }
19 
21 {
22  input_color_program_ = this->get_input_socket_reader(0);
24  NodeOperation *scale_x = this->get_input_socket_reader(2);
25  NodeOperation *scale_y = this->get_input_socket_reader(3);
27  vector_read_fn_ = [=](float x, float y, float *out) {
28  vector->read_sampled(out, x, y, PixelSampler::Bilinear);
29  };
30  scale_x_read_fn_ = [=](float x, float y, float *out) {
32  };
33  scale_y_read_fn_ = [=](float x, float y, float *out) {
35  };
36  }
37 
38  width_x4_ = this->get_width() * 4;
39  height_x4_ = this->get_height() * 4;
40  input_vector_width_ = vector->get_width();
41  input_vector_height_ = vector->get_height();
42 }
43 
45  float x,
46  float y,
47  PixelSampler /*sampler*/)
48 {
49  float xy[2] = {x, y};
50  float uv[2], deriv[2][2];
51 
52  pixel_transform(xy, uv, deriv);
53  if (is_zero_v2(deriv[0]) && is_zero_v2(deriv[1])) {
54  input_color_program_->read_sampled(output, uv[0], uv[1], PixelSampler::Bilinear);
55  }
56  else {
57  /* EWA filtering (without nearest it gets blurry with NO distortion) */
58  input_color_program_->read_filtered(output, uv[0], uv[1], deriv[0], deriv[1]);
59  }
60 }
61 
62 bool DisplaceOperation::read_displacement(
63  float x, float y, float xscale, float yscale, const float origin[2], float &r_u, float &r_v)
64 {
65  float width = input_vector_width_;
66  float height = input_vector_height_;
67  if (x < 0.0f || x >= width || y < 0.0f || y >= height) {
68  r_u = 0.0f;
69  r_v = 0.0f;
70  return false;
71  }
72 
73  float col[4];
74  vector_read_fn_(x, y, col);
75  r_u = origin[0] - col[0] * xscale;
76  r_v = origin[1] - col[1] * yscale;
77  return true;
78 }
79 
80 void DisplaceOperation::pixel_transform(const float xy[2], float r_uv[2], float r_deriv[2][2])
81 {
82  float col[4];
83  float uv[2]; /* temporary variables for derivative estimation */
84  int num;
85 
86  scale_x_read_fn_(xy[0], xy[1], col);
87  float xs = col[0];
88  scale_y_read_fn_(xy[0], xy[1], col);
89  float ys = col[0];
90  /* clamp x and y displacement to triple image resolution -
91  * to prevent hangs from huge values mistakenly plugged in eg. z buffers */
92  CLAMP(xs, -width_x4_, width_x4_);
93  CLAMP(ys, -height_x4_, height_x4_);
94 
95  /* displaced pixel in uv coords, for image sampling */
96  read_displacement(xy[0], xy[1], xs, ys, xy, r_uv[0], r_uv[1]);
97 
98  /* Estimate partial derivatives using 1-pixel offsets */
99  const float epsilon[2] = {1.0f, 1.0f};
100 
101  zero_v2(r_deriv[0]);
102  zero_v2(r_deriv[1]);
103 
104  num = 0;
105  if (read_displacement(xy[0] + epsilon[0], xy[1], xs, ys, xy, uv[0], uv[1])) {
106  r_deriv[0][0] += uv[0] - r_uv[0];
107  r_deriv[1][0] += uv[1] - r_uv[1];
108  num++;
109  }
110  if (read_displacement(xy[0] - epsilon[0], xy[1], xs, ys, xy, uv[0], uv[1])) {
111  r_deriv[0][0] += r_uv[0] - uv[0];
112  r_deriv[1][0] += r_uv[1] - uv[1];
113  num++;
114  }
115  if (num > 0) {
116  float numinv = 1.0f / (float)num;
117  r_deriv[0][0] *= numinv;
118  r_deriv[1][0] *= numinv;
119  }
120 
121  num = 0;
122  if (read_displacement(xy[0], xy[1] + epsilon[1], xs, ys, xy, uv[0], uv[1])) {
123  r_deriv[0][1] += uv[0] - r_uv[0];
124  r_deriv[1][1] += uv[1] - r_uv[1];
125  num++;
126  }
127  if (read_displacement(xy[0], xy[1] - epsilon[1], xs, ys, xy, uv[0], uv[1])) {
128  r_deriv[0][1] += r_uv[0] - uv[0];
129  r_deriv[1][1] += r_uv[1] - uv[1];
130  num++;
131  }
132  if (num > 0) {
133  float numinv = 1.0f / (float)num;
134  r_deriv[0][1] *= numinv;
135  r_deriv[1][1] *= numinv;
136  }
137 }
138 
140 {
141  input_color_program_ = nullptr;
142  vector_read_fn_ = nullptr;
143  scale_x_read_fn_ = nullptr;
144  scale_y_read_fn_ = nullptr;
145 }
146 
148  ReadBufferOperation *read_operation,
149  rcti *output)
150 {
151  rcti color_input;
152  rcti vector_input;
153  NodeOperation *operation = nullptr;
154 
155  /* the vector buffer only needs a 2x2 buffer. The image needs whole buffer */
156  /* image */
157  operation = get_input_operation(0);
158  color_input.xmax = operation->get_width();
159  color_input.xmin = 0;
160  color_input.ymax = operation->get_height();
161  color_input.ymin = 0;
162  if (operation->determine_depending_area_of_interest(&color_input, read_operation, output)) {
163  return true;
164  }
165 
166  /* vector */
167  operation = get_input_operation(1);
168  vector_input.xmax = input->xmax + 1;
169  vector_input.xmin = input->xmin - 1;
170  vector_input.ymax = input->ymax + 1;
171  vector_input.ymin = input->ymin - 1;
172  if (operation->determine_depending_area_of_interest(&vector_input, read_operation, output)) {
173  return true;
174  }
175 
176  /* scale x */
177  operation = get_input_operation(2);
178  if (operation->determine_depending_area_of_interest(input, read_operation, output)) {
179  return true;
180  }
181 
182  /* scale y */
183  operation = get_input_operation(3);
184  if (operation->determine_depending_area_of_interest(input, read_operation, output)) {
185  return true;
186  }
187 
188  return false;
189 }
190 
192  const rcti &output_area,
193  rcti &r_input_area)
194 {
195  switch (input_idx) {
196  case 0: {
197  r_input_area = get_input_operation(input_idx)->get_canvas();
198  break;
199  }
200  case 1: {
201  r_input_area = output_area;
203  break;
204  }
205  default: {
206  r_input_area = output_area;
207  break;
208  }
209  }
210 }
211 
213  const rcti &UNUSED(area),
215 {
216  MemoryBuffer *vector = inputs[1];
217  MemoryBuffer *scale_x = inputs[2];
218  MemoryBuffer *scale_y = inputs[3];
219  vector_read_fn_ = [=](float x, float y, float *out) { vector->read_elem_bilinear(x, y, out); };
220  scale_x_read_fn_ = [=](float x, float y, float *out) { scale_x->read_elem_checked(x, y, out); };
221  scale_y_read_fn_ = [=](float x, float y, float *out) { scale_y->read_elem_checked(x, y, out); };
222 }
223 
225  const rcti &area,
227 {
228  const MemoryBuffer *input_color = inputs[0];
229  for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) {
230  const float xy[2] = {(float)it.x, (float)it.y};
231  float uv[2];
232  float deriv[2][2];
233 
234  pixel_transform(xy, uv, deriv);
235  if (is_zero_v2(deriv[0]) && is_zero_v2(deriv[1])) {
236  input_color->read_elem_bilinear(uv[0], uv[1], it.out);
237  }
238  else {
239  /* EWA filtering (without nearest it gets blurry with NO distortion). */
240  input_color->read_elem_filtered(uv[0], uv[1], deriv[0], deriv[1], it.out);
241  }
242  }
243 }
244 
245 } // namespace blender::compositor
typedef float(TangentPoint)[2]
MINLINE void zero_v2(float r[2])
MINLINE bool is_zero_v2(const float a[2]) ATTR_WARN_UNUSED_RESULT
#define UNUSED(x)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
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 execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
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
bool determine_depending_area_of_interest(rcti *input, ReadBufferOperation *read_operation, rcti *output) override
void update_memory_buffer_started(MemoryBuffer *output, const rcti &area, Span< MemoryBuffer * > inputs) override
a MemoryBuffer contains access to the data of a chunk
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], float *out) const
NodeOperation contains calculation logic.
void add_output_socket(DataType datatype)
void read_filtered(float result[4], float x, float y, float dx[2], float dy[2])
SocketReader * get_input_socket_reader(unsigned int index)
NodeOperation * get_input_operation(int index)
virtual bool determine_depending_area_of_interest(rcti *input, ReadBufferOperation *read_operation, rcti *output)
void read_sampled(float result[4], float x, float y, PixelSampler sampler)
void add_input_socket(DataType datatype, ResizeMode resize_mode=ResizeMode::Center)
uint col
@ Vector
Vector data type.
ccl_global KernelShaderEvalInput ccl_global float * output
ccl_global KernelShaderEvalInput * input
static void area(int d1, int d2, int e1, int e2, float weights[2])
void expand_area_for_sampler(rcti &area, PixelSampler sampler)
Definition: COM_Enums.cc:8
typename BuffersIteratorBuilder< T >::Iterator BuffersIterator
static double epsilon
static const pxr::TfToken out("out", pxr::TfToken::Immortal)
static bNodeSocketTemplate inputs[]
int ymin
Definition: DNA_vec_types.h:64
int ymax
Definition: DNA_vec_types.h:64
int xmin
Definition: DNA_vec_types.h:63
int xmax
Definition: DNA_vec_types.h:63
int xy[2]
Definition: wm_draw.c:135