Blender  V2.93
COM_DisplaceOperation.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Copyright 2011, Blender Foundation.
17  */
18 
19 #include "COM_DisplaceOperation.h"
20 #include "BLI_math.h"
21 #include "BLI_utildefines.h"
22 
23 namespace blender::compositor {
24 
26 {
32  this->flags.complex = true;
33 
34  this->m_inputColorProgram = nullptr;
35  this->m_inputVectorProgram = nullptr;
36  this->m_inputScaleXProgram = nullptr;
37  this->m_inputScaleYProgram = nullptr;
38 }
39 
41 {
42  this->m_inputColorProgram = this->getInputSocketReader(0);
43  this->m_inputVectorProgram = this->getInputSocketReader(1);
44  this->m_inputScaleXProgram = this->getInputSocketReader(2);
45  this->m_inputScaleYProgram = this->getInputSocketReader(3);
46 
47  this->m_width_x4 = this->getWidth() * 4;
48  this->m_height_x4 = this->getHeight() * 4;
49 }
50 
52  float x,
53  float y,
54  PixelSampler /*sampler*/)
55 {
56  float xy[2] = {x, y};
57  float uv[2], deriv[2][2];
58 
59  pixelTransform(xy, uv, deriv);
60  if (is_zero_v2(deriv[0]) && is_zero_v2(deriv[1])) {
61  this->m_inputColorProgram->readSampled(output, uv[0], uv[1], PixelSampler::Bilinear);
62  }
63  else {
64  /* EWA filtering (without nearest it gets blurry with NO distortion) */
65  this->m_inputColorProgram->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1]);
66  }
67 }
68 
69 bool DisplaceOperation::read_displacement(
70  float x, float y, float xscale, float yscale, const float origin[2], float &r_u, float &r_v)
71 {
72  float width = m_inputVectorProgram->getWidth();
73  float height = m_inputVectorProgram->getHeight();
74  if (x < 0.0f || x >= width || y < 0.0f || y >= height) {
75  r_u = 0.0f;
76  r_v = 0.0f;
77  return false;
78  }
79 
80  float col[4];
81  m_inputVectorProgram->readSampled(col, x, y, PixelSampler::Bilinear);
82  r_u = origin[0] - col[0] * xscale;
83  r_v = origin[1] - col[1] * yscale;
84  return true;
85 }
86 
87 void DisplaceOperation::pixelTransform(const float xy[2], float r_uv[2], float r_deriv[2][2])
88 {
89  float col[4];
90  float uv[2]; /* temporary variables for derivative estimation */
91  int num;
92 
93  m_inputScaleXProgram->readSampled(col, xy[0], xy[1], PixelSampler::Nearest);
94  float xs = col[0];
95  m_inputScaleYProgram->readSampled(col, xy[0], xy[1], PixelSampler::Nearest);
96  float ys = col[0];
97  /* clamp x and y displacement to triple image resolution -
98  * to prevent hangs from huge values mistakenly plugged in eg. z buffers */
99  CLAMP(xs, -m_width_x4, m_width_x4);
100  CLAMP(ys, -m_height_x4, m_height_x4);
101 
102  /* displaced pixel in uv coords, for image sampling */
103  read_displacement(xy[0], xy[1], xs, ys, xy, r_uv[0], r_uv[1]);
104 
105  /* Estimate partial derivatives using 1-pixel offsets */
106  const float epsilon[2] = {1.0f, 1.0f};
107 
108  zero_v2(r_deriv[0]);
109  zero_v2(r_deriv[1]);
110 
111  num = 0;
112  if (read_displacement(xy[0] + epsilon[0], xy[1], xs, ys, xy, uv[0], uv[1])) {
113  r_deriv[0][0] += uv[0] - r_uv[0];
114  r_deriv[1][0] += uv[1] - r_uv[1];
115  num++;
116  }
117  if (read_displacement(xy[0] - epsilon[0], xy[1], xs, ys, xy, uv[0], uv[1])) {
118  r_deriv[0][0] += r_uv[0] - uv[0];
119  r_deriv[1][0] += r_uv[1] - uv[1];
120  num++;
121  }
122  if (num > 0) {
123  float numinv = 1.0f / (float)num;
124  r_deriv[0][0] *= numinv;
125  r_deriv[1][0] *= numinv;
126  }
127 
128  num = 0;
129  if (read_displacement(xy[0], xy[1] + epsilon[1], xs, ys, xy, uv[0], uv[1])) {
130  r_deriv[0][1] += uv[0] - r_uv[0];
131  r_deriv[1][1] += uv[1] - r_uv[1];
132  num++;
133  }
134  if (read_displacement(xy[0], xy[1] - epsilon[1], xs, ys, xy, uv[0], uv[1])) {
135  r_deriv[0][1] += r_uv[0] - uv[0];
136  r_deriv[1][1] += r_uv[1] - uv[1];
137  num++;
138  }
139  if (num > 0) {
140  float numinv = 1.0f / (float)num;
141  r_deriv[0][1] *= numinv;
142  r_deriv[1][1] *= numinv;
143  }
144 }
145 
147 {
148  this->m_inputColorProgram = nullptr;
149  this->m_inputVectorProgram = nullptr;
150  this->m_inputScaleXProgram = nullptr;
151  this->m_inputScaleYProgram = nullptr;
152 }
153 
155  ReadBufferOperation *readOperation,
156  rcti *output)
157 {
158  rcti colorInput;
159  rcti vectorInput;
160  NodeOperation *operation = nullptr;
161 
162  /* the vector buffer only needs a 2x2 buffer. The image needs whole buffer */
163  /* image */
164  operation = getInputOperation(0);
165  colorInput.xmax = operation->getWidth();
166  colorInput.xmin = 0;
167  colorInput.ymax = operation->getHeight();
168  colorInput.ymin = 0;
169  if (operation->determineDependingAreaOfInterest(&colorInput, readOperation, output)) {
170  return true;
171  }
172 
173  /* vector */
174  operation = getInputOperation(1);
175  vectorInput.xmax = input->xmax + 1;
176  vectorInput.xmin = input->xmin - 1;
177  vectorInput.ymax = input->ymax + 1;
178  vectorInput.ymin = input->ymin - 1;
179  if (operation->determineDependingAreaOfInterest(&vectorInput, readOperation, output)) {
180  return true;
181  }
182 
183  /* scale x */
184  operation = getInputOperation(2);
185  if (operation->determineDependingAreaOfInterest(input, readOperation, output)) {
186  return true;
187  }
188 
189  /* scale y */
190  operation = getInputOperation(3);
191  if (operation->determineDependingAreaOfInterest(input, readOperation, output)) {
192  return true;
193  }
194 
195  return false;
196 }
197 
198 } // namespace blender::compositor
typedef float(TangentPoint)[2]
MINLINE void zero_v2(float r[2])
MINLINE bool is_zero_v2(const float a[3]) ATTR_WARN_UNUSED_RESULT
_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
_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
Group RGB to Bright Vector Camera CLAMP
#define output
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
void pixelTransform(const float xy[2], float r_uv[2], float r_deriv[2][2])
bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) override
NodeOperation contains calculation logic.
void readSampled(float result[4], float x, float y, PixelSampler sampler)
void addInputSocket(DataType datatype, ResizeMode resize_mode=ResizeMode::Center)
NodeOperation * getInputOperation(unsigned int inputSocketindex)
void addOutputSocket(DataType datatype)
void readFiltered(float result[4], float x, float y, float dx[2], float dy[2])
SocketReader * getInputSocketReader(unsigned int inputSocketindex)
virtual bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
uint col
@ Vector
Vector data type.
static double epsilon
int ymin
Definition: DNA_vec_types.h:80
int ymax
Definition: DNA_vec_types.h:80
int xmin
Definition: DNA_vec_types.h:79
int xmax
Definition: DNA_vec_types.h:79