Blender  V2.93
geom_patch.h
Go to the documentation of this file.
1 /*
2  * Based on code from OpenSubdiv released under this license:
3  *
4  * Copyright 2013 Pixar
5  *
6  * Licensed under the Apache License, Version 2.0 (the "Apache License")
7  * with the following modification; you may not use this file except in
8  * compliance with the Apache License and the following modification to it:
9  * Section 6. Trademarks. is deleted and replaced with:
10  *
11  * 6. Trademarks. This License does not grant permission to use the trade
12  * names, trademarks, service marks, or product names of the Licensor
13  * and its affiliates, except as required to comply with Section 4(c) of
14  * the License and to reproduce the content of the NOTICE file.
15  *
16  * You may obtain a copy of the Apache License at
17  *
18  * http://www.apache.org/licenses/LICENSE-2.0
19  *
20  * Unless required by applicable law or agreed to in writing, software
21  * distributed under the Apache License with the above modification is
22  * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
23  * KIND, either express or implied. See the Apache License for the specific
24  * language governing permissions and limitations under the Apache License.
25  */
26 
28 
29 typedef struct PatchHandle {
32 
33 ccl_device_inline int patch_map_resolve_quadrant(float median, float *u, float *v)
34 {
35  int quadrant = -1;
36 
37  if (*u < median) {
38  if (*v < median) {
39  quadrant = 0;
40  }
41  else {
42  quadrant = 1;
43  *v -= median;
44  }
45  }
46  else {
47  if (*v < median) {
48  quadrant = 3;
49  }
50  else {
51  quadrant = 2;
52  *v -= median;
53  }
54  *u -= median;
55  }
56 
57  return quadrant;
58 }
59 
60 /* retrieve PatchHandle from patch coords */
61 
63 patch_map_find_patch(KernelGlobals *kg, int object, int patch, float u, float v)
64 {
65  PatchHandle handle;
66 
67  kernel_assert((u >= 0.0f) && (u <= 1.0f) && (v >= 0.0f) && (v <= 1.0f));
68 
69  int node = (object_patch_map_offset(kg, object) + patch) / 2;
70  float median = 0.5f;
71 
72  for (int depth = 0; depth < 0xff; depth++) {
73  float delta = median * 0.5f;
74 
75  int quadrant = patch_map_resolve_quadrant(median, &u, &v);
76  kernel_assert(quadrant >= 0);
77 
78  uint child = kernel_tex_fetch(__patches, node + quadrant);
79 
80  /* is the quadrant a hole? */
81  if (!(child & PATCH_MAP_NODE_IS_SET)) {
82  handle.array_index = -1;
83  return handle;
84  }
85 
86  uint index = child & PATCH_MAP_NODE_INDEX_MASK;
87 
88  if (child & PATCH_MAP_NODE_IS_LEAF) {
89  handle.array_index = kernel_tex_fetch(__patches, index + 0);
90  handle.patch_index = kernel_tex_fetch(__patches, index + 1);
91  handle.vert_index = kernel_tex_fetch(__patches, index + 2);
92 
93  return handle;
94  }
95  else {
96  node = index;
97  }
98 
99  median = delta;
100  }
101 
102  /* no leaf found */
103  kernel_assert(0);
104 
105  handle.array_index = -1;
106  return handle;
107 }
108 
109 ccl_device_inline void patch_eval_bspline_weights(float t, float *point, float *deriv)
110 {
111  /* The four uniform cubic B-Spline basis functions evaluated at t */
112  float inv_6 = 1.0f / 6.0f;
113 
114  float t2 = t * t;
115  float t3 = t * t2;
116 
117  point[0] = inv_6 * (1.0f - 3.0f * (t - t2) - t3);
118  point[1] = inv_6 * (4.0f - 6.0f * t2 + 3.0f * t3);
119  point[2] = inv_6 * (1.0f + 3.0f * (t + t2 - t3));
120  point[3] = inv_6 * t3;
121 
122  /* Derivatives of the above four basis functions at t */
123  deriv[0] = -0.5f * t2 + t - 0.5f;
124  deriv[1] = 1.5f * t2 - 2.0f * t;
125  deriv[2] = -1.5f * t2 + t + 0.5f;
126  deriv[3] = 0.5f * t2;
127 }
128 
130 {
131  int boundary = ((bits >> 8) & 0xf);
132 
133  if (boundary & 1) {
134  t[2] -= t[0];
135  t[1] += 2 * t[0];
136  t[0] = 0;
137  }
138 
139  if (boundary & 2) {
140  s[1] -= s[3];
141  s[2] += 2 * s[3];
142  s[3] = 0;
143  }
144 
145  if (boundary & 4) {
146  t[1] -= t[3];
147  t[2] += 2 * t[3];
148  t[3] = 0;
149  }
150 
151  if (boundary & 8) {
152  s[2] -= s[0];
153  s[1] += 2 * s[0];
154  s[0] = 0;
155  }
156 }
157 
159 {
160  return (patch_bits & 0xf);
161 }
162 
164 {
165  bool non_quad_root = (patch_bits >> 4) & 0x1;
166  int depth = patch_eval_depth(patch_bits);
167 
168  if (non_quad_root) {
169  return 1.0f / (float)(1 << (depth - 1));
170  }
171  else {
172  return 1.0f / (float)(1 << depth);
173  }
174 }
175 
176 ccl_device_inline void patch_eval_normalize_coords(uint patch_bits, float *u, float *v)
177 {
178  float frac = patch_eval_param_fraction(patch_bits);
179 
180  int iu = (patch_bits >> 22) & 0x3ff;
181  int iv = (patch_bits >> 12) & 0x3ff;
182 
183  /* top left corner */
184  float pu = (float)iu * frac;
185  float pv = (float)iv * frac;
186 
187  /* normalize uv coordinates */
188  *u = (*u - pu) / frac;
189  *v = (*v - pv) / frac;
190 }
191 
192 /* retrieve patch control indices */
193 
195  const PatchHandle *handle,
196  int channel,
198 {
199  int index_base = kernel_tex_fetch(__patches, handle->array_index + 2) + handle->vert_index;
200 
201  /* XXX: regular patches only */
202  for (int i = 0; i < 16; i++) {
203  indices[i] = kernel_tex_fetch(__patches, index_base + i);
204  }
205 
206  return 16;
207 }
208 
209 /* evaluate patch basis functions */
210 
212  const PatchHandle *handle,
213  float u,
214  float v,
215  float weights[PATCH_MAX_CONTROL_VERTS],
216  float weights_du[PATCH_MAX_CONTROL_VERTS],
217  float weights_dv[PATCH_MAX_CONTROL_VERTS])
218 {
219  uint patch_bits = kernel_tex_fetch(__patches, handle->patch_index + 1); /* read patch param */
220  float d_scale = 1 << patch_eval_depth(patch_bits);
221 
222  bool non_quad_root = (patch_bits >> 4) & 0x1;
223  if (non_quad_root) {
224  d_scale *= 0.5f;
225  }
226 
227  patch_eval_normalize_coords(patch_bits, &u, &v);
228 
229  /* XXX: regular patches only for now. */
230 
231  float s[4], t[4], ds[4], dt[4];
232 
233  patch_eval_bspline_weights(u, s, ds);
235 
236  patch_eval_adjust_boundary_weights(patch_bits, s, t);
237  patch_eval_adjust_boundary_weights(patch_bits, ds, dt);
238 
239  for (int k = 0; k < 4; k++) {
240  for (int l = 0; l < 4; l++) {
241  weights[4 * k + l] = s[l] * t[k];
242  weights_du[4 * k + l] = ds[l] * t[k] * d_scale;
243  weights_dv[4 * k + l] = s[l] * dt[k] * d_scale;
244  }
245  }
246 }
247 
248 /* generic function for evaluating indices and weights from patch coords */
249 
251  int object,
252  int patch,
253  float u,
254  float v,
255  int channel,
257  float weights[PATCH_MAX_CONTROL_VERTS],
258  float weights_du[PATCH_MAX_CONTROL_VERTS],
259  float weights_dv[PATCH_MAX_CONTROL_VERTS])
260 {
261  PatchHandle handle = patch_map_find_patch(kg, object, patch, u, v);
262  kernel_assert(handle.array_index >= 0);
263 
264  int num_control = patch_eval_indices(kg, &handle, channel, indices);
265  patch_eval_basis(kg, &handle, u, v, weights, weights_du, weights_dv);
266 
267  return num_control;
268 }
269 
270 /* functions for evaluating attributes on patches */
271 
272 ccl_device float patch_eval_float(KernelGlobals *kg,
273  const ShaderData *sd,
274  int offset,
275  int patch,
276  float u,
277  float v,
278  int channel,
279  float *du,
280  float *dv)
281 {
283  float weights[PATCH_MAX_CONTROL_VERTS];
284  float weights_du[PATCH_MAX_CONTROL_VERTS];
285  float weights_dv[PATCH_MAX_CONTROL_VERTS];
286 
287  int num_control = patch_eval_control_verts(
288  kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
289 
290  float val = 0.0f;
291  if (du)
292  *du = 0.0f;
293  if (dv)
294  *dv = 0.0f;
295 
296  for (int i = 0; i < num_control; i++) {
297  float v = kernel_tex_fetch(__attributes_float, offset + indices[i]);
298 
299  val += v * weights[i];
300  if (du)
301  *du += v * weights_du[i];
302  if (dv)
303  *dv += v * weights_dv[i];
304  }
305 
306  return val;
307 }
308 
310  const ShaderData *sd,
311  int offset,
312  int patch,
313  float u,
314  float v,
315  int channel,
316  float2 *du,
317  float2 *dv)
318 {
320  float weights[PATCH_MAX_CONTROL_VERTS];
321  float weights_du[PATCH_MAX_CONTROL_VERTS];
322  float weights_dv[PATCH_MAX_CONTROL_VERTS];
323 
324  int num_control = patch_eval_control_verts(
325  kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
326 
327  float2 val = make_float2(0.0f, 0.0f);
328  if (du)
329  *du = make_float2(0.0f, 0.0f);
330  if (dv)
331  *dv = make_float2(0.0f, 0.0f);
332 
333  for (int i = 0; i < num_control; i++) {
334  float2 v = kernel_tex_fetch(__attributes_float2, offset + indices[i]);
335 
336  val += v * weights[i];
337  if (du)
338  *du += v * weights_du[i];
339  if (dv)
340  *dv += v * weights_dv[i];
341  }
342 
343  return val;
344 }
345 
347  const ShaderData *sd,
348  int offset,
349  int patch,
350  float u,
351  float v,
352  int channel,
353  float3 *du,
354  float3 *dv)
355 {
357  float weights[PATCH_MAX_CONTROL_VERTS];
358  float weights_du[PATCH_MAX_CONTROL_VERTS];
359  float weights_dv[PATCH_MAX_CONTROL_VERTS];
360 
361  int num_control = patch_eval_control_verts(
362  kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
363 
364  float3 val = make_float3(0.0f, 0.0f, 0.0f);
365  if (du)
366  *du = make_float3(0.0f, 0.0f, 0.0f);
367  if (dv)
368  *dv = make_float3(0.0f, 0.0f, 0.0f);
369 
370  for (int i = 0; i < num_control; i++) {
371  float3 v = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + indices[i]));
372 
373  val += v * weights[i];
374  if (du)
375  *du += v * weights_du[i];
376  if (dv)
377  *dv += v * weights_dv[i];
378  }
379 
380  return val;
381 }
382 
383 ccl_device float4 patch_eval_float4(KernelGlobals *kg,
384  const ShaderData *sd,
385  int offset,
386  int patch,
387  float u,
388  float v,
389  int channel,
390  float4 *du,
391  float4 *dv)
392 {
394  float weights[PATCH_MAX_CONTROL_VERTS];
395  float weights_du[PATCH_MAX_CONTROL_VERTS];
396  float weights_dv[PATCH_MAX_CONTROL_VERTS];
397 
398  int num_control = patch_eval_control_verts(
399  kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
400 
401  float4 val = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
402  if (du)
403  *du = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
404  if (dv)
405  *dv = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
406 
407  for (int i = 0; i < num_control; i++) {
408  float4 v = kernel_tex_fetch(__attributes_float3, offset + indices[i]);
409 
410  val += v * weights[i];
411  if (du)
412  *du += v * weights_du[i];
413  if (dv)
414  *dv += v * weights_dv[i];
415  }
416 
417  return val;
418 }
419 
420 ccl_device float4 patch_eval_uchar4(KernelGlobals *kg,
421  const ShaderData *sd,
422  int offset,
423  int patch,
424  float u,
425  float v,
426  int channel,
427  float4 *du,
428  float4 *dv)
429 {
431  float weights[PATCH_MAX_CONTROL_VERTS];
432  float weights_du[PATCH_MAX_CONTROL_VERTS];
433  float weights_dv[PATCH_MAX_CONTROL_VERTS];
434 
435  int num_control = patch_eval_control_verts(
436  kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
437 
438  float4 val = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
439  if (du)
440  *du = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
441  if (dv)
442  *dv = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
443 
444  for (int i = 0; i < num_control; i++) {
445  float4 v = color_srgb_to_linear_v4(
446  color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, offset + indices[i])));
447 
448  val += v * weights[i];
449  if (du)
450  *du += v * weights_du[i];
451  if (dv)
452  *dv += v * weights_dv[i];
453  }
454 
455  return val;
456 }
457 
typedef float(TangentPoint)[2]
unsigned int uint
Definition: BLI_sys_types.h:83
_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 GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
OperationNode * node
static ushort indices[]
ccl_device_inline uint object_patch_map_offset(KernelGlobals *kg, int object)
Definition: geom_object.h:308
ccl_device float patch_eval_float(KernelGlobals *kg, const ShaderData *sd, int offset, int patch, float u, float v, int channel, float *du, float *dv)
Definition: geom_patch.h:272
ccl_device float4 patch_eval_uchar4(KernelGlobals *kg, const ShaderData *sd, int offset, int patch, float u, float v, int channel, float4 *du, float4 *dv)
Definition: geom_patch.h:420
ccl_device_inline void patch_eval_bspline_weights(float t, float *point, float *deriv)
Definition: geom_patch.h:109
ccl_device_inline void patch_eval_normalize_coords(uint patch_bits, float *u, float *v)
Definition: geom_patch.h:176
ccl_device float4 patch_eval_float4(KernelGlobals *kg, const ShaderData *sd, int offset, int patch, float u, float v, int channel, float4 *du, float4 *dv)
Definition: geom_patch.h:383
ccl_device float3 patch_eval_float3(KernelGlobals *kg, const ShaderData *sd, int offset, int patch, float u, float v, int channel, float3 *du, float3 *dv)
Definition: geom_patch.h:346
ccl_device_inline int patch_eval_control_verts(KernelGlobals *kg, int object, int patch, float u, float v, int channel, int indices[PATCH_MAX_CONTROL_VERTS], float weights[PATCH_MAX_CONTROL_VERTS], float weights_du[PATCH_MAX_CONTROL_VERTS], float weights_dv[PATCH_MAX_CONTROL_VERTS])
Definition: geom_patch.h:250
ccl_device_inline void patch_eval_basis(KernelGlobals *kg, const PatchHandle *handle, float u, float v, float weights[PATCH_MAX_CONTROL_VERTS], float weights_du[PATCH_MAX_CONTROL_VERTS], float weights_dv[PATCH_MAX_CONTROL_VERTS])
Definition: geom_patch.h:211
ccl_device float2 patch_eval_float2(KernelGlobals *kg, const ShaderData *sd, int offset, int patch, float u, float v, int channel, float2 *du, float2 *dv)
Definition: geom_patch.h:309
ccl_device_inline int patch_eval_indices(KernelGlobals *kg, const PatchHandle *handle, int channel, int indices[PATCH_MAX_CONTROL_VERTS])
Definition: geom_patch.h:194
ccl_device_inline float patch_eval_param_fraction(uint patch_bits)
Definition: geom_patch.h:163
CCL_NAMESPACE_BEGIN struct PatchHandle PatchHandle
ccl_device_inline int patch_map_resolve_quadrant(float median, float *u, float *v)
Definition: geom_patch.h:33
ccl_device_inline int patch_eval_depth(uint patch_bits)
Definition: geom_patch.h:158
ccl_device_inline void patch_eval_adjust_boundary_weights(uint bits, float *s, float *t)
Definition: geom_patch.h:129
ccl_device_inline PatchHandle patch_map_find_patch(KernelGlobals *kg, int object, int patch, float u, float v)
Definition: geom_patch.h:63
#define kernel_assert(cond)
#define kernel_tex_fetch(tex, index)
#define ccl_device
#define ccl_device_inline
#define CCL_NAMESPACE_END
#define make_float2(x, y)
#define make_float4(x, y, z, w)
#define make_float3(x, y, z)
#define PATCH_MAP_NODE_IS_SET
#define PATCH_MAX_CONTROL_VERTS
ShaderData
#define PATCH_MAP_NODE_IS_LEAF
#define PATCH_MAP_NODE_INDEX_MASK
ccl_device_inline float frac(float x, int *ix)
int patch_index
Definition: geom_patch.h:30
int vert_index
Definition: geom_patch.h:30
int array_index
Definition: geom_patch.h:30
ccl_device_inline float4 color_uchar4_to_float4(uchar4 c)
Definition: util_color.h:63
ccl_device float4 color_srgb_to_linear_v4(float4 c)
Definition: util_color.h:263
ccl_device_inline float3 float4_to_float3(const float4 a)
Definition: util_math.h:415