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
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,
192 int indices[PATCH_MAX_CONTROL_VERTS])
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,
251 int indices[PATCH_MAX_CONTROL_VERTS],
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{
277 int indices[PATCH_MAX_CONTROL_VERTS];
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{
318 int indices[PATCH_MAX_CONTROL_VERTS];
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{
357 int indices[PATCH_MAX_CONTROL_VERTS];
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,
395 ccl_private float4 *du,
396 ccl_private float4 *dv)
397{
398 int indices[PATCH_MAX_CONTROL_VERTS];
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,
434 ccl_private float4 *du,
435 ccl_private float4 *dv)
436{
437 int indices[PATCH_MAX_CONTROL_VERTS];
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++) {
452 float4 v = color_srgb_to_linear_v4(
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
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
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
#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
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