Blender  V2.93
COM_MapUVOperation.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_MapUVOperation.h"
20 #include "BLI_math.h"
21 
22 namespace blender::compositor {
23 
25 {
29  this->m_alpha = 0.0f;
30  this->flags.complex = true;
32 
33  this->m_inputUVProgram = nullptr;
34  this->m_inputColorProgram = nullptr;
35 }
36 
38 {
39  this->m_inputColorProgram = this->getInputSocketReader(0);
40  this->m_inputUVProgram = this->getInputSocketReader(1);
41 }
42 
44  float x,
45  float y,
46  PixelSampler /*sampler*/)
47 {
48  float xy[2] = {x, y};
49  float uv[2], deriv[2][2], alpha;
50 
51  pixelTransform(xy, uv, deriv, alpha);
52  if (alpha == 0.0f) {
53  zero_v4(output);
54  return;
55  }
56 
57  /* EWA filtering */
58  this->m_inputColorProgram->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1]);
59 
60  /* UV to alpha threshold */
61  const float threshold = this->m_alpha * 0.05f;
62  /* XXX alpha threshold is used to fade out pixels on boundaries with invalid derivatives.
63  * this calculation is not very well defined, should be looked into if it becomes a problem ...
64  */
65  float du = len_v2(deriv[0]);
66  float dv = len_v2(deriv[1]);
67  float factor = 1.0f - threshold * (du / m_inputColorProgram->getWidth() +
68  dv / m_inputColorProgram->getHeight());
69  if (factor < 0.0f) {
70  alpha = 0.0f;
71  }
72  else {
73  alpha *= factor;
74  }
75 
76  /* "premul" */
77  if (alpha < 1.0f) {
79  }
80 }
81 
82 bool MapUVOperation::read_uv(float x, float y, float &r_u, float &r_v, float &r_alpha)
83 {
84  float width = m_inputUVProgram->getWidth();
85  float height = m_inputUVProgram->getHeight();
86  if (x < 0.0f || x >= width || y < 0.0f || y >= height) {
87  r_u = 0.0f;
88  r_v = 0.0f;
89  r_alpha = 0.0f;
90  return false;
91  }
92 
93  float vector[3];
94  m_inputUVProgram->readSampled(vector, x, y, PixelSampler::Bilinear);
95  r_u = vector[0] * m_inputColorProgram->getWidth();
96  r_v = vector[1] * m_inputColorProgram->getHeight();
97  r_alpha = vector[2];
98  return true;
99 }
100 
101 void MapUVOperation::pixelTransform(const float xy[2],
102  float r_uv[2],
103  float r_deriv[2][2],
104  float &r_alpha)
105 {
106  float uv[2], alpha; /* temporary variables for derivative estimation */
107  int num;
108 
109  read_uv(xy[0], xy[1], r_uv[0], r_uv[1], r_alpha);
110 
111  /* Estimate partial derivatives using 1-pixel offsets */
112  const float epsilon[2] = {1.0f, 1.0f};
113 
114  zero_v2(r_deriv[0]);
115  zero_v2(r_deriv[1]);
116 
117  num = 0;
118  if (read_uv(xy[0] + epsilon[0], xy[1], uv[0], uv[1], alpha)) {
119  r_deriv[0][0] += uv[0] - r_uv[0];
120  r_deriv[1][0] += uv[1] - r_uv[1];
121  num++;
122  }
123  if (read_uv(xy[0] - epsilon[0], xy[1], uv[0], uv[1], alpha)) {
124  r_deriv[0][0] += r_uv[0] - uv[0];
125  r_deriv[1][0] += r_uv[1] - uv[1];
126  num++;
127  }
128  if (num > 0) {
129  float numinv = 1.0f / (float)num;
130  r_deriv[0][0] *= numinv;
131  r_deriv[1][0] *= numinv;
132  }
133 
134  num = 0;
135  if (read_uv(xy[0], xy[1] + epsilon[1], uv[0], uv[1], alpha)) {
136  r_deriv[0][1] += uv[0] - r_uv[0];
137  r_deriv[1][1] += uv[1] - r_uv[1];
138  num++;
139  }
140  if (read_uv(xy[0], xy[1] - epsilon[1], uv[0], uv[1], alpha)) {
141  r_deriv[0][1] += r_uv[0] - uv[0];
142  r_deriv[1][1] += r_uv[1] - uv[1];
143  num++;
144  }
145  if (num > 0) {
146  float numinv = 1.0f / (float)num;
147  r_deriv[0][1] *= numinv;
148  r_deriv[1][1] *= numinv;
149  }
150 }
151 
153 {
154  this->m_inputUVProgram = nullptr;
155  this->m_inputColorProgram = nullptr;
156 }
157 
159  ReadBufferOperation *readOperation,
160  rcti *output)
161 {
162  rcti colorInput;
163  rcti uvInput;
164  NodeOperation *operation = nullptr;
165 
166  /* the uv buffer only needs a 3x3 buffer. The image needs whole buffer */
167 
168  operation = getInputOperation(0);
169  colorInput.xmax = operation->getWidth();
170  colorInput.xmin = 0;
171  colorInput.ymax = operation->getHeight();
172  colorInput.ymin = 0;
173  if (operation->determineDependingAreaOfInterest(&colorInput, readOperation, output)) {
174  return true;
175  }
176 
177  operation = getInputOperation(1);
178  uvInput.xmax = input->xmax + 1;
179  uvInput.xmin = input->xmin - 1;
180  uvInput.ymax = input->ymax + 1;
181  uvInput.ymin = input->ymin - 1;
182  if (operation->determineDependingAreaOfInterest(&uvInput, readOperation, output)) {
183  return true;
184  }
185 
186  return false;
187 }
188 
189 } // namespace blender::compositor
typedef float(TangentPoint)[2]
MINLINE void mul_v4_fl(float r[4], float f)
MINLINE void zero_v4(float r[4])
MINLINE void zero_v2(float r[2])
MINLINE float len_v2(const float a[2]) 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
#define output
void pixelTransform(const float xy[2], float r_uv[2], float r_deriv[2][2], float &r_alpha)
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
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 setResolutionInputSocketIndex(unsigned int index)
set the index of the input socket that will determine the resolution of this operation
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)
static CCL_NAMESPACE_BEGIN const double alpha
@ Vector
Vector data type.
@ None
The bottom left of the input image is the bottom left of the working area of the node,...
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