Blender  V3.3
kernel/geom/patch.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2013 Pixar. */
3 
8 #pragma once
9 
10 #include "util/color.h"
11 
13 
14 typedef struct PatchHandle {
17 
19  ccl_private float *u,
20  ccl_private float *v)
21 {
22  int quadrant = -1;
23 
24  if (*u < median) {
25  if (*v < median) {
26  quadrant = 0;
27  }
28  else {
29  quadrant = 1;
30  *v -= median;
31  }
32  }
33  else {
34  if (*v < median) {
35  quadrant = 3;
36  }
37  else {
38  quadrant = 2;
39  *v -= median;
40  }
41  *u -= median;
42  }
43 
44  return quadrant;
45 }
46 
47 /* retrieve PatchHandle from patch coords */
48 
50 patch_map_find_patch(KernelGlobals kg, int object, int patch, float u, float v)
51 {
52  PatchHandle handle;
53 
54  kernel_assert((u >= 0.0f) && (u <= 1.0f) && (v >= 0.0f) && (v <= 1.0f));
55 
56  int node = (object_patch_map_offset(kg, object) + patch) / 2;
57  float median = 0.5f;
58 
59  for (int depth = 0; depth < 0xff; depth++) {
60  float delta = median * 0.5f;
61 
62  int quadrant = patch_map_resolve_quadrant(median, &u, &v);
63  kernel_assert(quadrant >= 0);
64 
65  uint child = kernel_data_fetch(patches, node + quadrant);
66 
67  /* is the quadrant a hole? */
68  if (!(child & PATCH_MAP_NODE_IS_SET)) {
69  handle.array_index = -1;
70  return handle;
71  }
72 
73  uint index = child & PATCH_MAP_NODE_INDEX_MASK;
74 
75  if (child & PATCH_MAP_NODE_IS_LEAF) {
76  handle.array_index = kernel_data_fetch(patches, index + 0);
77  handle.patch_index = kernel_data_fetch(patches, index + 1);
78  handle.vert_index = kernel_data_fetch(patches, index + 2);
79 
80  return handle;
81  }
82  else {
83  node = index;
84  }
85 
86  median = delta;
87  }
88 
89  /* no leaf found */
90  kernel_assert(0);
91 
92  handle.array_index = -1;
93  return handle;
94 }
95 
97  ccl_private float *point,
98  ccl_private float *deriv)
99 {
100  /* The four uniform cubic B-Spline basis functions evaluated at t */
101  float inv_6 = 1.0f / 6.0f;
102 
103  float t2 = t * t;
104  float t3 = t * t2;
105 
106  point[0] = inv_6 * (1.0f - 3.0f * (t - t2) - t3);
107  point[1] = inv_6 * (4.0f - 6.0f * t2 + 3.0f * t3);
108  point[2] = inv_6 * (1.0f + 3.0f * (t + t2 - t3));
109  point[3] = inv_6 * t3;
110 
111  /* Derivatives of the above four basis functions at t */
112  deriv[0] = -0.5f * t2 + t - 0.5f;
113  deriv[1] = 1.5f * t2 - 2.0f * t;
114  deriv[2] = -1.5f * t2 + t + 0.5f;
115  deriv[3] = 0.5f * t2;
116 }
117 
119  ccl_private float *s,
120  ccl_private float *t)
121 {
122  int boundary = ((bits >> 8) & 0xf);
123 
124  if (boundary & 1) {
125  t[2] -= t[0];
126  t[1] += 2 * t[0];
127  t[0] = 0;
128  }
129 
130  if (boundary & 2) {
131  s[1] -= s[3];
132  s[2] += 2 * s[3];
133  s[3] = 0;
134  }
135 
136  if (boundary & 4) {
137  t[1] -= t[3];
138  t[2] += 2 * t[3];
139  t[3] = 0;
140  }
141 
142  if (boundary & 8) {
143  s[2] -= s[0];
144  s[1] += 2 * s[0];
145  s[0] = 0;
146  }
147 }
148 
150 {
151  return (patch_bits & 0xf);
152 }
153 
155 {
156  bool non_quad_root = (patch_bits >> 4) & 0x1;
157  int depth = patch_eval_depth(patch_bits);
158 
159  if (non_quad_root) {
160  return 1.0f / (float)(1 << (depth - 1));
161  }
162  else {
163  return 1.0f / (float)(1 << depth);
164  }
165 }
166 
168  ccl_private float *u,
169  ccl_private float *v)
170 {
171  float frac = patch_eval_param_fraction(patch_bits);
172 
173  int iu = (patch_bits >> 22) & 0x3ff;
174  int iv = (patch_bits >> 12) & 0x3ff;
175 
176  /* top left corner */
177  float pu = (float)iu * frac;
178  float pv = (float)iv * frac;
179 
180  /* normalize uv coordinates */
181  *u = (*u - pu) / frac;
182  *v = (*v - pv) / frac;
183 }
184 
185 /* retrieve patch control indices */
186 
188  ccl_private const PatchHandle *handle,
189  int channel,
191 {
192  int index_base = kernel_data_fetch(patches, handle->array_index + 2) + handle->vert_index;
193 
194  /* XXX: regular patches only */
195  for (int i = 0; i < 16; i++) {
196  indices[i] = kernel_data_fetch(patches, index_base + i);
197  }
198 
199  return 16;
200 }
201 
202 /* evaluate patch basis functions */
203 
205  ccl_private const PatchHandle *handle,
206  float u,
207  float v,
208  float weights[PATCH_MAX_CONTROL_VERTS],
209  float weights_du[PATCH_MAX_CONTROL_VERTS],
210  float weights_dv[PATCH_MAX_CONTROL_VERTS])
211 {
212  uint patch_bits = kernel_data_fetch(patches, handle->patch_index + 1); /* read patch param */
213  float d_scale = 1 << patch_eval_depth(patch_bits);
214 
215  bool non_quad_root = (patch_bits >> 4) & 0x1;
216  if (non_quad_root) {
217  d_scale *= 0.5f;
218  }
219 
220  patch_eval_normalize_coords(patch_bits, &u, &v);
221 
222  /* XXX: regular patches only for now. */
223 
224  float s[4], t[4], ds[4], dt[4];
225 
226  patch_eval_bspline_weights(u, s, ds);
228 
229  patch_eval_adjust_boundary_weights(patch_bits, s, t);
230  patch_eval_adjust_boundary_weights(patch_bits, ds, dt);
231 
232  for (int k = 0; k < 4; k++) {
233  for (int l = 0; l < 4; l++) {
234  weights[4 * k + l] = s[l] * t[k];
235  weights_du[4 * k + l] = ds[l] * t[k] * d_scale;
236  weights_dv[4 * k + l] = s[l] * dt[k] * d_scale;
237  }
238  }
239 }
240 
241 /* generic function for evaluating indices and weights from patch coords */
242 
244  int object,
245  int patch,
246  float u,
247  float v,
248  int channel,
250  float weights[PATCH_MAX_CONTROL_VERTS],
251  float weights_du[PATCH_MAX_CONTROL_VERTS],
252  float weights_dv[PATCH_MAX_CONTROL_VERTS])
253 {
254  PatchHandle handle = patch_map_find_patch(kg, object, patch, u, v);
255  kernel_assert(handle.array_index >= 0);
256 
257  int num_control = patch_eval_indices(kg, &handle, channel, indices);
258  patch_eval_basis(kg, &handle, u, v, weights, weights_du, weights_dv);
259 
260  return num_control;
261 }
262 
263 /* functions for evaluating attributes on patches */
264 
266  ccl_private const ShaderData *sd,
267  int offset,
268  int patch,
269  float u,
270  float v,
271  int channel,
272  ccl_private float *du,
273  ccl_private float *dv)
274 {
276  float weights[PATCH_MAX_CONTROL_VERTS];
277  float weights_du[PATCH_MAX_CONTROL_VERTS];
278  float weights_dv[PATCH_MAX_CONTROL_VERTS];
279 
280  int num_control = patch_eval_control_verts(
281  kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
282 
283  float val = 0.0f;
284  if (du)
285  *du = 0.0f;
286  if (dv)
287  *dv = 0.0f;
288 
289  for (int i = 0; i < num_control; i++) {
290  float v = kernel_data_fetch(attributes_float, offset + indices[i]);
291 
292  val += v * weights[i];
293  if (du)
294  *du += v * weights_du[i];
295  if (dv)
296  *dv += v * weights_dv[i];
297  }
298 
299  return val;
300 }
301 
303  ccl_private const ShaderData *sd,
304  int offset,
305  int patch,
306  float u,
307  float v,
308  int channel,
309  ccl_private float2 *du,
310  ccl_private float2 *dv)
311 {
313  float weights[PATCH_MAX_CONTROL_VERTS];
314  float weights_du[PATCH_MAX_CONTROL_VERTS];
315  float weights_dv[PATCH_MAX_CONTROL_VERTS];
316 
317  int num_control = patch_eval_control_verts(
318  kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
319 
320  float2 val = make_float2(0.0f, 0.0f);
321  if (du)
322  *du = make_float2(0.0f, 0.0f);
323  if (dv)
324  *dv = make_float2(0.0f, 0.0f);
325 
326  for (int i = 0; i < num_control; i++) {
327  float2 v = kernel_data_fetch(attributes_float2, offset + indices[i]);
328 
329  val += v * weights[i];
330  if (du)
331  *du += v * weights_du[i];
332  if (dv)
333  *dv += v * weights_dv[i];
334  }
335 
336  return val;
337 }
338 
340  ccl_private const ShaderData *sd,
341  int offset,
342  int patch,
343  float u,
344  float v,
345  int channel,
346  ccl_private float3 *du,
347  ccl_private float3 *dv)
348 {
350  float weights[PATCH_MAX_CONTROL_VERTS];
351  float weights_du[PATCH_MAX_CONTROL_VERTS];
352  float weights_dv[PATCH_MAX_CONTROL_VERTS];
353 
354  int num_control = patch_eval_control_verts(
355  kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
356 
357  float3 val = make_float3(0.0f, 0.0f, 0.0f);
358  if (du)
359  *du = make_float3(0.0f, 0.0f, 0.0f);
360  if (dv)
361  *dv = make_float3(0.0f, 0.0f, 0.0f);
362 
363  for (int i = 0; i < num_control; i++) {
364  float3 v = kernel_data_fetch(attributes_float3, offset + indices[i]);
365 
366  val += v * weights[i];
367  if (du)
368  *du += v * weights_du[i];
369  if (dv)
370  *dv += v * weights_dv[i];
371  }
372 
373  return val;
374 }
375 
377  ccl_private const ShaderData *sd,
378  int offset,
379  int patch,
380  float u,
381  float v,
382  int channel,
383  ccl_private float4 *du,
384  ccl_private float4 *dv)
385 {
387  float weights[PATCH_MAX_CONTROL_VERTS];
388  float weights_du[PATCH_MAX_CONTROL_VERTS];
389  float weights_dv[PATCH_MAX_CONTROL_VERTS];
390 
391  int num_control = patch_eval_control_verts(
392  kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
393 
394  float4 val = zero_float4();
395  if (du)
396  *du = zero_float4();
397  if (dv)
398  *dv = zero_float4();
399 
400  for (int i = 0; i < num_control; i++) {
401  float4 v = kernel_data_fetch(attributes_float4, offset + indices[i]);
402 
403  val += v * weights[i];
404  if (du)
405  *du += v * weights_du[i];
406  if (dv)
407  *dv += v * weights_dv[i];
408  }
409 
410  return val;
411 }
412 
414  ccl_private const ShaderData *sd,
415  int offset,
416  int patch,
417  float u,
418  float v,
419  int channel,
420  ccl_private float4 *du,
421  ccl_private float4 *dv)
422 {
424  float weights[PATCH_MAX_CONTROL_VERTS];
425  float weights_du[PATCH_MAX_CONTROL_VERTS];
426  float weights_dv[PATCH_MAX_CONTROL_VERTS];
427 
428  int num_control = patch_eval_control_verts(
429  kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
430 
431  float4 val = zero_float4();
432  if (du)
433  *du = zero_float4();
434  if (dv)
435  *dv = zero_float4();
436 
437  for (int i = 0; i < num_control; i++) {
439  color_uchar4_to_float4(kernel_data_fetch(attributes_uchar4, offset + indices[i])));
440 
441  val += v * weights[i];
442  if (du)
443  *du += v * weights_du[i];
444  if (dv)
445  *dv += v * weights_dv[i];
446  }
447 
448  return val;
449 }
450 
typedef float(TangentPoint)[2]
unsigned int uint
Definition: BLI_sys_types.h:67
_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
float float4[4]
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define kernel_assert(cond)
Definition: cpu/compat.h:34
#define ccl_device
Definition: cuda/compat.h:32
#define ccl_private
Definition: cuda/compat.h:48
#define ccl_device_inline
Definition: cuda/compat.h:34
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
OperationNode * node
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define kernel_data_fetch(name, index)
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
ccl_gpu_kernel_postfix int ccl_global int * indices
ccl_device_inline uint object_patch_map_offset(KernelGlobals kg, int object)
ccl_device_inline void patch_eval_bspline_weights(float t, ccl_private float *point, ccl_private float *deriv)
ccl_device float patch_eval_float(KernelGlobals kg, ccl_private const ShaderData *sd, int offset, int patch, float u, float v, int channel, ccl_private float *du, ccl_private float *dv)
ccl_device_inline int patch_map_resolve_quadrant(float median, ccl_private float *u, ccl_private float *v)
ccl_device_inline int patch_eval_indices(KernelGlobals kg, ccl_private const PatchHandle *handle, int channel, int indices[PATCH_MAX_CONTROL_VERTS])
ccl_device float2 patch_eval_float2(KernelGlobals kg, ccl_private const ShaderData *sd, int offset, int patch, float u, float v, int channel, ccl_private float2 *du, ccl_private float2 *dv)
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])
ccl_device float3 patch_eval_float3(KernelGlobals kg, ccl_private const ShaderData *sd, int offset, int patch, float u, float v, int channel, ccl_private float3 *du, ccl_private float3 *dv)
ccl_device float4 patch_eval_float4(KernelGlobals kg, ccl_private const ShaderData *sd, int offset, int patch, float u, float v, int channel, ccl_private float4 *du, ccl_private float4 *dv)
ccl_device_inline void patch_eval_normalize_coords(uint patch_bits, ccl_private float *u, ccl_private float *v)
ccl_device float4 patch_eval_uchar4(KernelGlobals kg, ccl_private const ShaderData *sd, int offset, int patch, float u, float v, int channel, ccl_private float4 *du, ccl_private float4 *dv)
ccl_device_inline void patch_eval_adjust_boundary_weights(uint bits, ccl_private float *s, ccl_private float *t)
ccl_device_inline float patch_eval_param_fraction(uint patch_bits)
ccl_device_inline PatchHandle patch_map_find_patch(KernelGlobals kg, int object, int patch, float u, float v)
CCL_NAMESPACE_BEGIN struct PatchHandle PatchHandle
ccl_device_inline void patch_eval_basis(KernelGlobals kg, ccl_private 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])
ccl_device_inline int patch_eval_depth(uint patch_bits)
#define PATCH_MAP_NODE_IS_SET
#define PATCH_MAX_CONTROL_VERTS
ShaderData
Definition: kernel/types.h:925
#define PATCH_MAP_NODE_IS_LEAF
#define PATCH_MAP_NODE_INDEX_MASK
ccl_device_inline float4 zero_float4()
Definition: math_float4.h:92
#define make_float2(x, y)
Definition: metal/compat.h:203
#define make_float3(x, y, z)
Definition: metal/compat.h:204
ccl_device_inline float frac(float x, int *ix)
ccl_device_inline float4 color_uchar4_to_float4(uchar4 c)
Definition: util/color.h:50
ccl_device float4 color_srgb_to_linear_v4(float4 c)
Definition: util/color.h:302