Blender V4.3
kernel/geom/patch.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2013 Pixar
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
8
9#pragma once
10
11#include "util/color.h"
12
14
18
20 ccl_private float *u,
21 ccl_private float *v)
22{
23 int quadrant = -1;
24
25 if (*u < median) {
26 if (*v < median) {
27 quadrant = 0;
28 }
29 else {
30 quadrant = 1;
31 *v -= median;
32 }
33 }
34 else {
35 if (*v < median) {
36 quadrant = 3;
37 }
38 else {
39 quadrant = 2;
40 *v -= median;
41 }
42 *u -= median;
43 }
44
45 return quadrant;
46}
47
48/* retrieve PatchHandle from patch coords */
49
51patch_map_find_patch(KernelGlobals kg, int object, int patch, float u, float v)
52{
53 PatchHandle handle;
54
55 // TODO: temporarily disabled due to slight inaccuracies on ARM.
56 // kernel_assert((u >= 0.0f) && (u <= 1.0f) && (v >= 0.0f) && (v <= 1.0f));
57
58 int node = (object_patch_map_offset(kg, object) + patch) / 2;
59 float median = 0.5f;
60
61 for (int depth = 0; depth < 0xff; depth++) {
62 float delta = median * 0.5f;
63
64 int quadrant = patch_map_resolve_quadrant(median, &u, &v);
65 kernel_assert(quadrant >= 0);
66
67 uint child = kernel_data_fetch(patches, node + quadrant);
68
69 /* is the quadrant a hole? */
70 if (!(child & PATCH_MAP_NODE_IS_SET)) {
71 handle.array_index = -1;
72 return handle;
73 }
74
75 uint index = child & PATCH_MAP_NODE_INDEX_MASK;
76
77 if (child & PATCH_MAP_NODE_IS_LEAF) {
78 handle.array_index = kernel_data_fetch(patches, index + 0);
79 handle.patch_index = kernel_data_fetch(patches, index + 1);
80 handle.vert_index = kernel_data_fetch(patches, index + 2);
81
82 return handle;
83 }
84 else {
85 node = index;
86 }
87
88 median = delta;
89 }
90
91 /* no leaf found */
93
94 handle.array_index = -1;
95 return handle;
96}
97
99 ccl_private float *point,
100 ccl_private float *deriv)
101{
102 /* The four uniform cubic B-Spline basis functions evaluated at t */
103 float inv_6 = 1.0f / 6.0f;
104
105 float t2 = t * t;
106 float t3 = t * t2;
107
108 point[0] = inv_6 * (1.0f - 3.0f * (t - t2) - t3);
109 point[1] = inv_6 * (4.0f - 6.0f * t2 + 3.0f * t3);
110 point[2] = inv_6 * (1.0f + 3.0f * (t + t2 - t3));
111 point[3] = inv_6 * t3;
112
113 /* Derivatives of the above four basis functions at t */
114 deriv[0] = -0.5f * t2 + t - 0.5f;
115 deriv[1] = 1.5f * t2 - 2.0f * t;
116 deriv[2] = -1.5f * t2 + t + 0.5f;
117 deriv[3] = 0.5f * t2;
118}
119
121 ccl_private float *s,
122 ccl_private float *t)
123{
124 int boundary = ((bits >> 8) & 0xf);
125
126 if (boundary & 1) {
127 t[2] -= t[0];
128 t[1] += 2 * t[0];
129 t[0] = 0;
130 }
131
132 if (boundary & 2) {
133 s[1] -= s[3];
134 s[2] += 2 * s[3];
135 s[3] = 0;
136 }
137
138 if (boundary & 4) {
139 t[1] -= t[3];
140 t[2] += 2 * t[3];
141 t[3] = 0;
142 }
143
144 if (boundary & 8) {
145 s[2] -= s[0];
146 s[1] += 2 * s[0];
147 s[0] = 0;
148 }
149}
150
152{
153 return (patch_bits & 0xf);
154}
155
157{
158 bool non_quad_root = (patch_bits >> 4) & 0x1;
159 int depth = patch_eval_depth(patch_bits);
160
161 if (non_quad_root) {
162 return 1.0f / (float)(1 << (depth - 1));
163 }
164 else {
165 return 1.0f / (float)(1 << depth);
166 }
167}
168
170 ccl_private float *u,
171 ccl_private float *v)
172{
173 float frac = patch_eval_param_fraction(patch_bits);
174
175 int iu = (patch_bits >> 22) & 0x3ff;
176 int iv = (patch_bits >> 12) & 0x3ff;
177
178 /* top left corner */
179 float pu = (float)iu * frac;
180 float pv = (float)iv * frac;
181
182 /* normalize uv coordinates */
183 *u = (*u - pu) / frac;
184 *v = (*v - pv) / frac;
185}
186
187/* retrieve patch control indices */
188
190 ccl_private const PatchHandle *handle,
191 int channel,
193{
194 int index_base = kernel_data_fetch(patches, handle->array_index + 2) + handle->vert_index;
195
196 /* XXX: regular patches only */
197 for (int i = 0; i < 16; i++) {
198 indices[i] = kernel_data_fetch(patches, index_base + i);
199 }
200
201 return 16;
202}
203
204/* evaluate patch basis functions */
205
207 ccl_private const PatchHandle *handle,
208 float u,
209 float v,
210 float weights[PATCH_MAX_CONTROL_VERTS],
211 float weights_du[PATCH_MAX_CONTROL_VERTS],
212 float weights_dv[PATCH_MAX_CONTROL_VERTS])
213{
214 uint patch_bits = kernel_data_fetch(patches, handle->patch_index + 1); /* read patch param */
215 float d_scale = 1 << patch_eval_depth(patch_bits);
216
217 bool non_quad_root = (patch_bits >> 4) & 0x1;
218 if (non_quad_root) {
219 d_scale *= 0.5f;
220 }
221
222 patch_eval_normalize_coords(patch_bits, &u, &v);
223
224 /* XXX: regular patches only for now. */
225
226 float s[4], t[4], ds[4], dt[4];
227
230
231 patch_eval_adjust_boundary_weights(patch_bits, s, t);
232 patch_eval_adjust_boundary_weights(patch_bits, ds, dt);
233
234 for (int k = 0; k < 4; k++) {
235 for (int l = 0; l < 4; l++) {
236 weights[4 * k + l] = s[l] * t[k];
237 weights_du[4 * k + l] = ds[l] * t[k] * d_scale;
238 weights_dv[4 * k + l] = s[l] * dt[k] * d_scale;
239 }
240 }
241}
242
243/* generic function for evaluating indices and weights from patch coords */
244
246 int object,
247 int patch,
248 float u,
249 float v,
250 int channel,
252 float weights[PATCH_MAX_CONTROL_VERTS],
253 float weights_du[PATCH_MAX_CONTROL_VERTS],
254 float weights_dv[PATCH_MAX_CONTROL_VERTS])
255{
256 PatchHandle handle = patch_map_find_patch(kg, object, patch, u, v);
257 kernel_assert(handle.array_index >= 0);
258
259 int num_control = patch_eval_indices(kg, &handle, channel, indices);
260 patch_eval_basis(kg, &handle, u, v, weights, weights_du, weights_dv);
261
262 return num_control;
263}
264
265/* functions for evaluating attributes on patches */
266
268 ccl_private const ShaderData *sd,
269 int offset,
270 int patch,
271 float u,
272 float v,
273 int channel,
274 ccl_private float *du,
275 ccl_private float *dv)
276{
278 float weights[PATCH_MAX_CONTROL_VERTS];
279 float weights_du[PATCH_MAX_CONTROL_VERTS];
280 float weights_dv[PATCH_MAX_CONTROL_VERTS];
281
282 int num_control = patch_eval_control_verts(
283 kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
284
285 float val = 0.0f;
286 if (du) {
287 *du = 0.0f;
288 }
289 if (dv) {
290 *dv = 0.0f;
291 }
292
293 for (int i = 0; i < num_control; i++) {
294 float v = kernel_data_fetch(attributes_float, offset + indices[i]);
295
296 val += v * weights[i];
297 if (du) {
298 *du += v * weights_du[i];
299 }
300 if (dv) {
301 *dv += v * weights_dv[i];
302 }
303 }
304
305 return val;
306}
307
309 ccl_private const ShaderData *sd,
310 int offset,
311 int patch,
312 float u,
313 float v,
314 int channel,
317{
319 float weights[PATCH_MAX_CONTROL_VERTS];
320 float weights_du[PATCH_MAX_CONTROL_VERTS];
321 float weights_dv[PATCH_MAX_CONTROL_VERTS];
322
323 int num_control = patch_eval_control_verts(
324 kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
325
326 float2 val = make_float2(0.0f, 0.0f);
327 if (du)
328 *du = make_float2(0.0f, 0.0f);
329 if (dv)
330 *dv = make_float2(0.0f, 0.0f);
331
332 for (int i = 0; i < num_control; i++) {
333 float2 v = kernel_data_fetch(attributes_float2, offset + indices[i]);
334
335 val += v * weights[i];
336 if (du) {
337 *du += v * weights_du[i];
338 }
339 if (dv) {
340 *dv += v * weights_dv[i];
341 }
342 }
343
344 return val;
345}
346
348 ccl_private const ShaderData *sd,
349 int offset,
350 int patch,
351 float u,
352 float v,
353 int channel,
356{
358 float weights[PATCH_MAX_CONTROL_VERTS];
359 float weights_du[PATCH_MAX_CONTROL_VERTS];
360 float weights_dv[PATCH_MAX_CONTROL_VERTS];
361
362 int num_control = patch_eval_control_verts(
363 kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
364
365 float3 val = make_float3(0.0f, 0.0f, 0.0f);
366 if (du) {
367 *du = make_float3(0.0f, 0.0f, 0.0f);
368 }
369 if (dv) {
370 *dv = make_float3(0.0f, 0.0f, 0.0f);
371 }
372
373 for (int i = 0; i < num_control; i++) {
374 float3 v = kernel_data_fetch(attributes_float3, offset + indices[i]);
375
376 val += v * weights[i];
377 if (du) {
378 *du += v * weights_du[i];
379 }
380 if (dv) {
381 *dv += v * weights_dv[i];
382 }
383 }
384
385 return val;
386}
387
389 ccl_private const ShaderData *sd,
390 int offset,
391 int patch,
392 float u,
393 float v,
394 int channel,
397{
399 float weights[PATCH_MAX_CONTROL_VERTS];
400 float weights_du[PATCH_MAX_CONTROL_VERTS];
401 float weights_dv[PATCH_MAX_CONTROL_VERTS];
402
403 int num_control = patch_eval_control_verts(
404 kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
405
406 float4 val = zero_float4();
407 if (du)
408 *du = zero_float4();
409 if (dv)
410 *dv = zero_float4();
411
412 for (int i = 0; i < num_control; i++) {
413 float4 v = kernel_data_fetch(attributes_float4, offset + indices[i]);
414
415 val += v * weights[i];
416 if (du) {
417 *du += v * weights_du[i];
418 }
419 if (dv) {
420 *dv += v * weights_dv[i];
421 }
422 }
423
424 return val;
425}
426
428 ccl_private const ShaderData *sd,
429 int offset,
430 int patch,
431 float u,
432 float v,
433 int channel,
436{
438 float weights[PATCH_MAX_CONTROL_VERTS];
439 float weights_du[PATCH_MAX_CONTROL_VERTS];
440 float weights_dv[PATCH_MAX_CONTROL_VERTS];
441
442 int num_control = patch_eval_control_verts(
443 kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
444
445 float4 val = zero_float4();
446 if (du)
447 *du = zero_float4();
448 if (dv)
449 *dv = zero_float4();
450
451 for (int i = 0; i < num_control; i++) {
453 color_uchar4_to_float4(kernel_data_fetch(attributes_uchar4, offset + indices[i])));
454
455 val += v * weights[i];
456 if (du) {
457 *du += v * weights_du[i];
458 }
459 if (dv) {
460 *dv += v * weights_dv[i];
461 }
462 }
463
464 return val;
465}
466
unsigned int uint
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 Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture 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
CCL_NAMESPACE_BEGIN ccl_device_inline float frac(float x, ccl_private int *ix)
#define kernel_assert(cond)
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define kernel_data_fetch(name, index)
#define ccl_device
#define ccl_private
#define ccl_device_inline
#define CCL_NAMESPACE_END
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
ccl_device_forceinline float2 make_float2(const float x, const float y)
draw_view in_light_buf[] float
static ushort 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_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
#define PATCH_MAP_NODE_IS_LEAF
#define PATCH_MAP_NODE_INDEX_MASK
CCL_NAMESPACE_BEGIN ccl_device_inline float4 zero_float4()
Definition math_float4.h:15
VecBase< float, 4 > float4
ccl_device_inline float4 color_uchar4_to_float4(uchar4 c)
Definition util/color.h:56
ccl_device float4 color_srgb_to_linear_v4(float4 c)
Definition util/color.h:327