Blender V4.5
voronoi.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#pragma once
6
7#include "kernel/svm/util.h"
8#include "util/hash.h"
9
11
12/*
13 * SPDX-License-Identifier: MIT
14 * Original code is copyright (c) 2013 Inigo Quilez.
15 *
16 * Smooth Voronoi:
17 *
18 * - https://wiki.blender.org/wiki/User:OmarSquircleArt/GSoC2019/Documentation/Smooth_Voronoi
19 *
20 * Distance To Edge based on:
21 *
22 * - https://www.iquilezles.org/www/articles/voronoilines/voronoilines.htm
23 * - https://www.shadertoy.com/view/ldl3W8
24 *
25 * With optimization to change -2..2 scan window to -1..1 for better performance,
26 * as explained in https://www.shadertoy.com/view/llG3zy.
27 */
28
29struct VoronoiParams {
30 float scale;
31 float detail;
32 float roughness;
33 float lacunarity;
34 float smoothness;
35 float exponent;
36 float randomness;
37 float max_distance;
41};
42
43struct VoronoiOutput {
44 float distance = 0.0f;
47};
48
49/* ***** Distances ***** */
50
51ccl_device float voronoi_distance(const float a, const float b)
52{
53 return fabsf(b - a);
54}
55
56template<typename T>
58{
59 if (params.metric == NODE_VORONOI_EUCLIDEAN) {
60 return distance(a, b);
61 }
62 if (params.metric == NODE_VORONOI_MANHATTAN) {
63 return reduce_add(fabs(a - b));
64 }
65 if (params.metric == NODE_VORONOI_CHEBYCHEV) {
66 return reduce_max(fabs(a - b));
67 }
68 if (params.metric == NODE_VORONOI_MINKOWSKI) {
69 return powf(reduce_add(power(fabs(a - b), params.exponent)), 1.0f / params.exponent);
70 }
71 return 0.0f;
72}
73
74/* Possibly cheaper/faster version of Voronoi distance, in a way that does not change
75 * logic of "which distance is the closest?". */
76template<typename T>
78 const T b,
80{
81 if (params.metric == NODE_VORONOI_EUCLIDEAN) {
82 return len_squared(a - b);
83 }
84 if (params.metric == NODE_VORONOI_MANHATTAN) {
85 return reduce_add(fabs(a - b));
86 }
87 if (params.metric == NODE_VORONOI_CHEBYCHEV) {
88 return reduce_max(fabs(a - b));
89 }
90 if (params.metric == NODE_VORONOI_MINKOWSKI) {
91 return reduce_add(power(fabs(a - b), params.exponent));
92 }
93 return 0.0f;
94}
95
96/* **** 1D Voronoi **** */
97
99{
100 return make_float4(0.0f, 0.0f, 0.0f, coord);
101}
102
104{
105 const float cellPosition = floorf(coord);
106 const float localPosition = coord - cellPosition;
107
108 float minDistance = FLT_MAX;
109 float targetOffset = 0.0f;
110 float targetPosition = 0.0f;
111 for (int i = -1; i <= 1; i++) {
112 const float cellOffset = i;
113 const float pointPosition = cellOffset +
114 hash_float_to_float(cellPosition + cellOffset) * params.randomness;
115 const float distanceToPoint = voronoi_distance(pointPosition, localPosition);
116 if (distanceToPoint < minDistance) {
117 targetOffset = cellOffset;
118 minDistance = distanceToPoint;
119 targetPosition = pointPosition;
120 }
121 }
122
123 VoronoiOutput octave;
124 octave.distance = minDistance;
125 octave.color = hash_float_to_float3(cellPosition + targetOffset);
126 octave.position = voronoi_position(targetPosition + cellPosition);
127 return octave;
128}
129
131 const float coord)
132{
133 const float cellPosition = floorf(coord);
134 const float localPosition = coord - cellPosition;
135
136 float smoothDistance = 0.0f;
137 float smoothPosition = 0.0f;
138 float3 smoothColor = make_float3(0.0f, 0.0f, 0.0f);
139 float h = -1.0f;
140 for (int i = -2; i <= 2; i++) {
141 const float cellOffset = i;
142 const float pointPosition = cellOffset +
143 hash_float_to_float(cellPosition + cellOffset) * params.randomness;
144 const float distanceToPoint = voronoi_distance(pointPosition, localPosition);
145 h = h == -1.0f ?
146 1.0f :
148 0.0f, 1.0f, 0.5f + 0.5f * (smoothDistance - distanceToPoint) / params.smoothness);
149 float correctionFactor = params.smoothness * h * (1.0f - h);
150 smoothDistance = mix(smoothDistance, distanceToPoint, h) - correctionFactor;
151 correctionFactor /= 1.0f + 3.0f * params.smoothness;
152 const float3 cellColor = hash_float_to_float3(cellPosition + cellOffset);
153 smoothColor = mix(smoothColor, cellColor, h) - correctionFactor;
154 smoothPosition = mix(smoothPosition, pointPosition, h) - correctionFactor;
155 }
156
157 VoronoiOutput octave;
158 octave.distance = smoothDistance;
159 octave.color = smoothColor;
160 octave.position = voronoi_position(cellPosition + smoothPosition);
161 return octave;
162}
163
165{
166 const float cellPosition = floorf(coord);
167 const float localPosition = coord - cellPosition;
168
169 float distanceF1 = FLT_MAX;
170 float distanceF2 = FLT_MAX;
171 float offsetF1 = 0.0f;
172 float positionF1 = 0.0f;
173 float offsetF2 = 0.0f;
174 float positionF2 = 0.0f;
175 for (int i = -1; i <= 1; i++) {
176 const float cellOffset = i;
177 const float pointPosition = cellOffset +
178 hash_float_to_float(cellPosition + cellOffset) * params.randomness;
179 const float distanceToPoint = voronoi_distance(pointPosition, localPosition);
180 if (distanceToPoint < distanceF1) {
181 distanceF2 = distanceF1;
182 distanceF1 = distanceToPoint;
183 offsetF2 = offsetF1;
184 offsetF1 = cellOffset;
185 positionF2 = positionF1;
186 positionF1 = pointPosition;
187 }
188 else if (distanceToPoint < distanceF2) {
189 distanceF2 = distanceToPoint;
190 offsetF2 = cellOffset;
191 positionF2 = pointPosition;
192 }
193 }
194
195 VoronoiOutput octave;
196 octave.distance = distanceF2;
197 octave.color = hash_float_to_float3(cellPosition + offsetF2);
198 octave.position = voronoi_position(positionF2 + cellPosition);
199 return octave;
200}
201
203 const float coord)
204{
205 const float cellPosition = floorf(coord);
206 const float localPosition = coord - cellPosition;
207
208 const float midPointPosition = hash_float_to_float(cellPosition) * params.randomness;
209 const float leftPointPosition = -1.0f +
210 hash_float_to_float(cellPosition - 1.0f) * params.randomness;
211 const float rightPointPosition = 1.0f +
212 hash_float_to_float(cellPosition + 1.0f) * params.randomness;
213 const float distanceToMidLeft = fabsf((midPointPosition + leftPointPosition) / 2.0f -
214 localPosition);
215 const float distanceToMidRight = fabsf((midPointPosition + rightPointPosition) / 2.0f -
216 localPosition);
217
218 return min(distanceToMidLeft, distanceToMidRight);
219}
220
222 const float coord)
223{
224 const float cellPosition = floorf(coord);
225 const float localPosition = coord - cellPosition;
226
227 float closestPoint = 0.0f;
228 float closestPointOffset = 0.0f;
229 float minDistance = FLT_MAX;
230 for (int i = -1; i <= 1; i++) {
231 const float cellOffset = i;
232 const float pointPosition = cellOffset +
233 hash_float_to_float(cellPosition + cellOffset) * params.randomness;
234 const float distanceToPoint = fabsf(pointPosition - localPosition);
235 if (distanceToPoint < minDistance) {
236 minDistance = distanceToPoint;
237 closestPoint = pointPosition;
238 closestPointOffset = cellOffset;
239 }
240 }
241
242 minDistance = FLT_MAX;
243 float closestPointToClosestPoint = 0.0f;
244 for (int i = -1; i <= 1; i++) {
245 if (i == 0) {
246 continue;
247 }
248 const float cellOffset = i + closestPointOffset;
249 const float pointPosition = cellOffset +
250 hash_float_to_float(cellPosition + cellOffset) * params.randomness;
251 const float distanceToPoint = fabsf(closestPoint - pointPosition);
252 if (distanceToPoint < minDistance) {
253 minDistance = distanceToPoint;
254 closestPointToClosestPoint = pointPosition;
255 }
256 }
257
258 return fabsf(closestPointToClosestPoint - closestPoint) / 2.0f;
259}
260
261/* **** 2D Voronoi **** */
262
264{
265 return make_float4(coord.x, coord.y, 0.0f, 0.0f);
266}
267
269{
270 const float2 cellPosition = floor(coord);
271 const float2 localPosition = coord - cellPosition;
272
273 float minDistance = FLT_MAX;
274 float2 targetOffset = make_float2(0.0f, 0.0f);
275 float2 targetPosition = make_float2(0.0f, 0.0f);
276 for (int j = -1; j <= 1; j++) {
277 for (int i = -1; i <= 1; i++) {
278 const float2 cellOffset = make_float2(i, j);
279 const float2 pointPosition = cellOffset + hash_float2_to_float2(cellPosition + cellOffset) *
280 params.randomness;
281 const float distanceToPoint = voronoi_distance_bound(pointPosition, localPosition, params);
282 if (distanceToPoint < minDistance) {
283 targetOffset = cellOffset;
284 minDistance = distanceToPoint;
285 targetPosition = pointPosition;
286 }
287 }
288 }
289
290 VoronoiOutput octave;
291 octave.distance = voronoi_distance(targetPosition, localPosition, params);
292 octave.color = hash_float2_to_float3(cellPosition + targetOffset);
293 octave.position = voronoi_position(targetPosition + cellPosition);
294 return octave;
295}
296
298 const float2 coord)
299{
300 const float2 cellPosition = floor(coord);
301 const float2 localPosition = coord - cellPosition;
302
303 float smoothDistance = 0.0f;
304 float3 smoothColor = make_float3(0.0f, 0.0f, 0.0f);
305 float2 smoothPosition = make_float2(0.0f, 0.0f);
306 float h = -1.0f;
307 for (int j = -2; j <= 2; j++) {
308 for (int i = -2; i <= 2; i++) {
309 const float2 cellOffset = make_float2(i, j);
310 const float2 pointPosition = cellOffset + hash_float2_to_float2(cellPosition + cellOffset) *
311 params.randomness;
312 const float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
313 h = h == -1.0f ?
314 1.0f :
315 smoothstep(0.0f,
316 1.0f,
317 0.5f + 0.5f * (smoothDistance - distanceToPoint) / params.smoothness);
318 float correctionFactor = params.smoothness * h * (1.0f - h);
319 smoothDistance = mix(smoothDistance, distanceToPoint, h) - correctionFactor;
320 correctionFactor /= 1.0f + 3.0f * params.smoothness;
321 const float3 cellColor = hash_float2_to_float3(cellPosition + cellOffset);
322 smoothColor = mix(smoothColor, cellColor, h) - correctionFactor;
323 smoothPosition = mix(smoothPosition, pointPosition, h) - correctionFactor;
324 }
325 }
326
327 VoronoiOutput octave;
328 octave.distance = smoothDistance;
329 octave.color = smoothColor;
330 octave.position = voronoi_position(cellPosition + smoothPosition);
331 return octave;
332}
333
335{
336 const float2 cellPosition = floor(coord);
337 const float2 localPosition = coord - cellPosition;
338
339 float distanceF1 = FLT_MAX;
340 float distanceF2 = FLT_MAX;
341 float2 offsetF1 = make_float2(0.0f, 0.0f);
342 float2 positionF1 = make_float2(0.0f, 0.0f);
343 float2 offsetF2 = make_float2(0.0f, 0.0f);
344 float2 positionF2 = make_float2(0.0f, 0.0f);
345 for (int j = -1; j <= 1; j++) {
346 for (int i = -1; i <= 1; i++) {
347 const float2 cellOffset = make_float2(i, j);
348 const float2 pointPosition = cellOffset + hash_float2_to_float2(cellPosition + cellOffset) *
349 params.randomness;
350 const float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
351 if (distanceToPoint < distanceF1) {
352 distanceF2 = distanceF1;
353 distanceF1 = distanceToPoint;
354 offsetF2 = offsetF1;
355 offsetF1 = cellOffset;
356 positionF2 = positionF1;
357 positionF1 = pointPosition;
358 }
359 else if (distanceToPoint < distanceF2) {
360 distanceF2 = distanceToPoint;
361 offsetF2 = cellOffset;
362 positionF2 = pointPosition;
363 }
364 }
365 }
366
367 VoronoiOutput octave;
368 octave.distance = distanceF2;
369 octave.color = hash_float2_to_float3(cellPosition + offsetF2);
370 octave.position = voronoi_position(positionF2 + cellPosition);
371 return octave;
372}
373
375 const float2 coord)
376{
377 const float2 cellPosition = floor(coord);
378 const float2 localPosition = coord - cellPosition;
379
380 float2 vectorToClosest = make_float2(0.0f, 0.0f);
381 float minDistance = FLT_MAX;
382 for (int j = -1; j <= 1; j++) {
383 for (int i = -1; i <= 1; i++) {
384 const float2 cellOffset = make_float2(i, j);
385 const float2 vectorToPoint = cellOffset +
386 hash_float2_to_float2(cellPosition + cellOffset) *
387 params.randomness -
388 localPosition;
389 const float distanceToPoint = dot(vectorToPoint, vectorToPoint);
390 if (distanceToPoint < minDistance) {
391 minDistance = distanceToPoint;
392 vectorToClosest = vectorToPoint;
393 }
394 }
395 }
396
397 minDistance = FLT_MAX;
398 for (int j = -1; j <= 1; j++) {
399 for (int i = -1; i <= 1; i++) {
400 const float2 cellOffset = make_float2(i, j);
401 const float2 vectorToPoint = cellOffset +
402 hash_float2_to_float2(cellPosition + cellOffset) *
403 params.randomness -
404 localPosition;
405 const float2 perpendicularToEdge = vectorToPoint - vectorToClosest;
406 if (dot(perpendicularToEdge, perpendicularToEdge) > 0.0001f) {
407 const float distanceToEdge = dot((vectorToClosest + vectorToPoint) / 2.0f,
408 normalize(perpendicularToEdge));
409 minDistance = min(minDistance, distanceToEdge);
410 }
411 }
412 }
413
414 return minDistance;
415}
416
418 const float2 coord)
419{
420 const float2 cellPosition = floor(coord);
421 const float2 localPosition = coord - cellPosition;
422
423 float2 closestPoint = make_float2(0.0f, 0.0f);
424 float2 closestPointOffset = make_float2(0.0f, 0.0f);
425 float minDistanceSq = FLT_MAX;
426 for (int j = -1; j <= 1; j++) {
427 for (int i = -1; i <= 1; i++) {
428 const float2 cellOffset = make_float2(i, j);
429 const float2 pointPosition = cellOffset + hash_float2_to_float2(cellPosition + cellOffset) *
430 params.randomness;
431 const float distanceToPointSq = len_squared(pointPosition - localPosition);
432 if (distanceToPointSq < minDistanceSq) {
433 minDistanceSq = distanceToPointSq;
434 closestPoint = pointPosition;
435 closestPointOffset = cellOffset;
436 }
437 }
438 }
439
440 minDistanceSq = FLT_MAX;
441 float2 closestPointToClosestPoint = make_float2(0.0f, 0.0f);
442 for (int j = -1; j <= 1; j++) {
443 for (int i = -1; i <= 1; i++) {
444 if (i == 0 && j == 0) {
445 continue;
446 }
447 const float2 cellOffset = make_float2(i, j) + closestPointOffset;
448 const float2 pointPosition = cellOffset + hash_float2_to_float2(cellPosition + cellOffset) *
449 params.randomness;
450 const float distanceToPointSq = len_squared(closestPoint - pointPosition);
451 if (distanceToPointSq < minDistanceSq) {
452 minDistanceSq = distanceToPointSq;
453 closestPointToClosestPoint = pointPosition;
454 }
455 }
456 }
457
458 return distance(closestPointToClosestPoint, closestPoint) / 2.0f;
459}
460
461/* **** 3D Voronoi **** */
462
464{
465 return make_float4(coord);
466}
467
469{
470 const float3 cellPosition = floor(coord);
471 const float3 localPosition = coord - cellPosition;
472
473 float minDistance = FLT_MAX;
474 float3 targetOffset = make_float3(0.0f, 0.0f, 0.0f);
475 float3 targetPosition = make_float3(0.0f, 0.0f, 0.0f);
476 for (int k = -1; k <= 1; k++) {
477 for (int j = -1; j <= 1; j++) {
478 for (int i = -1; i <= 1; i++) {
479 const float3 cellOffset = make_float3(i, j, k);
480 const float3 pointPosition = cellOffset +
481 hash_float3_to_float3(cellPosition + cellOffset) *
482 params.randomness;
483 const float distanceToPoint = voronoi_distance_bound(pointPosition, localPosition, params);
484 if (distanceToPoint < minDistance) {
485 targetOffset = cellOffset;
486 minDistance = distanceToPoint;
487 targetPosition = pointPosition;
488 }
489 }
490 }
491 }
492
493 VoronoiOutput octave;
494 octave.distance = voronoi_distance(targetPosition, localPosition, params);
495 octave.color = hash_float3_to_float3(cellPosition + targetOffset);
496 octave.position = voronoi_position(targetPosition + cellPosition);
497 return octave;
498}
499
501 const float3 coord)
502{
503 const float3 cellPosition = floor(coord);
504 const float3 localPosition = coord - cellPosition;
505
506 float smoothDistance = 0.0f;
507 float3 smoothColor = make_float3(0.0f, 0.0f, 0.0f);
508 float3 smoothPosition = make_float3(0.0f, 0.0f, 0.0f);
509 float h = -1.0f;
510 for (int k = -2; k <= 2; k++) {
511 for (int j = -2; j <= 2; j++) {
512 for (int i = -2; i <= 2; i++) {
513 const float3 cellOffset = make_float3(i, j, k);
514 const float3 pointPosition = cellOffset +
515 hash_float3_to_float3(cellPosition + cellOffset) *
516 params.randomness;
517 const float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
518 h = h == -1.0f ?
519 1.0f :
520 smoothstep(0.0f,
521 1.0f,
522 0.5f + 0.5f * (smoothDistance - distanceToPoint) / params.smoothness);
523 float correctionFactor = params.smoothness * h * (1.0f - h);
524 smoothDistance = mix(smoothDistance, distanceToPoint, h) - correctionFactor;
525 correctionFactor /= 1.0f + 3.0f * params.smoothness;
526 const float3 cellColor = hash_float3_to_float3(cellPosition + cellOffset);
527 smoothColor = mix(smoothColor, cellColor, h) - correctionFactor;
528 smoothPosition = mix(smoothPosition, pointPosition, h) - correctionFactor;
529 }
530 }
531 }
532
533 VoronoiOutput octave;
534 octave.distance = smoothDistance;
535 octave.color = smoothColor;
536 octave.position = voronoi_position(cellPosition + smoothPosition);
537 return octave;
538}
539
541{
542 const float3 cellPosition = floor(coord);
543 const float3 localPosition = coord - cellPosition;
544
545 float distanceF1 = FLT_MAX;
546 float distanceF2 = FLT_MAX;
547 float3 offsetF1 = make_float3(0.0f, 0.0f, 0.0f);
548 float3 positionF1 = make_float3(0.0f, 0.0f, 0.0f);
549 float3 offsetF2 = make_float3(0.0f, 0.0f, 0.0f);
550 float3 positionF2 = make_float3(0.0f, 0.0f, 0.0f);
551 for (int k = -1; k <= 1; k++) {
552 for (int j = -1; j <= 1; j++) {
553 for (int i = -1; i <= 1; i++) {
554 const float3 cellOffset = make_float3(i, j, k);
555 const float3 pointPosition = cellOffset +
556 hash_float3_to_float3(cellPosition + cellOffset) *
557 params.randomness;
558 const float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
559 if (distanceToPoint < distanceF1) {
560 distanceF2 = distanceF1;
561 distanceF1 = distanceToPoint;
562 offsetF2 = offsetF1;
563 offsetF1 = cellOffset;
564 positionF2 = positionF1;
565 positionF1 = pointPosition;
566 }
567 else if (distanceToPoint < distanceF2) {
568 distanceF2 = distanceToPoint;
569 offsetF2 = cellOffset;
570 positionF2 = pointPosition;
571 }
572 }
573 }
574 }
575
576 VoronoiOutput octave;
577 octave.distance = distanceF2;
578 octave.color = hash_float3_to_float3(cellPosition + offsetF2);
579 octave.position = voronoi_position(positionF2 + cellPosition);
580 return octave;
581}
582
584 const float3 coord)
585{
586 const float3 cellPosition = floor(coord);
587 const float3 localPosition = coord - cellPosition;
588
589 float3 vectorToClosest = make_float3(0.0f, 0.0f, 0.0f);
590 float minDistance = FLT_MAX;
591 for (int k = -1; k <= 1; k++) {
592 for (int j = -1; j <= 1; j++) {
593 for (int i = -1; i <= 1; i++) {
594 const float3 cellOffset = make_float3(i, j, k);
595 const float3 vectorToPoint = cellOffset +
596 hash_float3_to_float3(cellPosition + cellOffset) *
597 params.randomness -
598 localPosition;
599 const float distanceToPoint = dot(vectorToPoint, vectorToPoint);
600 if (distanceToPoint < minDistance) {
601 minDistance = distanceToPoint;
602 vectorToClosest = vectorToPoint;
603 }
604 }
605 }
606 }
607
608 minDistance = FLT_MAX;
609 for (int k = -1; k <= 1; k++) {
610 for (int j = -1; j <= 1; j++) {
611 for (int i = -1; i <= 1; i++) {
612 const float3 cellOffset = make_float3(i, j, k);
613 const float3 vectorToPoint = cellOffset +
614 hash_float3_to_float3(cellPosition + cellOffset) *
615 params.randomness -
616 localPosition;
617 const float3 perpendicularToEdge = vectorToPoint - vectorToClosest;
618 if (dot(perpendicularToEdge, perpendicularToEdge) > 0.0001f) {
619 const float distanceToEdge = dot((vectorToClosest + vectorToPoint) / 2.0f,
620 normalize(perpendicularToEdge));
621 minDistance = min(minDistance, distanceToEdge);
622 }
623 }
624 }
625 }
626
627 return minDistance;
628}
629
631 const float3 coord)
632{
633 const float3 cellPosition = floor(coord);
634 const float3 localPosition = coord - cellPosition;
635
636 float3 closestPoint = make_float3(0.0f, 0.0f, 0.0f);
637 float3 closestPointOffset = make_float3(0.0f, 0.0f, 0.0f);
638 float minDistanceSq = FLT_MAX;
639 for (int k = -1; k <= 1; k++) {
640 for (int j = -1; j <= 1; j++) {
641 for (int i = -1; i <= 1; i++) {
642 const float3 cellOffset = make_float3(i, j, k);
643 const float3 pointPosition = cellOffset +
644 hash_float3_to_float3(cellPosition + cellOffset) *
645 params.randomness;
646 const float distanceToPointSq = len_squared(pointPosition - localPosition);
647 if (distanceToPointSq < minDistanceSq) {
648 minDistanceSq = distanceToPointSq;
649 closestPoint = pointPosition;
650 closestPointOffset = cellOffset;
651 }
652 }
653 }
654 }
655
656 minDistanceSq = FLT_MAX;
657 float3 closestPointToClosestPoint = make_float3(0.0f, 0.0f, 0.0f);
658 for (int k = -1; k <= 1; k++) {
659 for (int j = -1; j <= 1; j++) {
660 for (int i = -1; i <= 1; i++) {
661 if (i == 0 && j == 0 && k == 0) {
662 continue;
663 }
664 const float3 cellOffset = make_float3(i, j, k) + closestPointOffset;
665 const float3 pointPosition = cellOffset +
666 hash_float3_to_float3(cellPosition + cellOffset) *
667 params.randomness;
668 const float distanceToPointSq = len_squared(closestPoint - pointPosition);
669 if (distanceToPointSq < minDistanceSq) {
670 minDistanceSq = distanceToPointSq;
671 closestPointToClosestPoint = pointPosition;
672 }
673 }
674 }
675 }
676
677 return distance(closestPointToClosestPoint, closestPoint) / 2.0f;
678}
679
680/* **** 4D Voronoi **** */
681
683{
684 return coord;
685}
686
688{
689 const float4 cellPosition = floor(coord);
690 const float4 localPosition = coord - cellPosition;
691
692 float minDistance = FLT_MAX;
693 float4 targetOffset = zero_float4();
694 float4 targetPosition = zero_float4();
695 for (int u = -1; u <= 1; u++) {
696 for (int k = -1; k <= 1; k++) {
697 for (int j = -1; j <= 1; j++) {
698 for (int i = -1; i <= 1; i++) {
699 const float4 cellOffset = make_float4(i, j, k, u);
700 const float4 pointPosition = cellOffset +
701 hash_float4_to_float4(cellPosition + cellOffset) *
702 params.randomness;
703 const float distanceToPoint = voronoi_distance_bound(
704 pointPosition, localPosition, params);
705 if (distanceToPoint < minDistance) {
706 targetOffset = cellOffset;
707 minDistance = distanceToPoint;
708 targetPosition = pointPosition;
709 }
710 }
711 }
712 }
713 }
714
715 VoronoiOutput octave;
716 octave.distance = voronoi_distance(targetPosition, localPosition, params);
717 octave.color = hash_float4_to_float3(cellPosition + targetOffset);
718 octave.position = voronoi_position(targetPosition + cellPosition);
719 return octave;
720}
721
723 const float4 coord)
724{
725 const float4 cellPosition = floor(coord);
726 const float4 localPosition = coord - cellPosition;
727
728 float smoothDistance = 0.0f;
729 float3 smoothColor = make_float3(0.0f, 0.0f, 0.0f);
730 float4 smoothPosition = zero_float4();
731 float h = -1.0f;
732 for (int u = -2; u <= 2; u++) {
733 for (int k = -2; k <= 2; k++) {
734 for (int j = -2; j <= 2; j++) {
735 for (int i = -2; i <= 2; i++) {
736 const float4 cellOffset = make_float4(i, j, k, u);
737 const float4 pointPosition = cellOffset +
738 hash_float4_to_float4(cellPosition + cellOffset) *
739 params.randomness;
740 const float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
741 h = h == -1.0f ?
742 1.0f :
743 smoothstep(0.0f,
744 1.0f,
745 0.5f + 0.5f * (smoothDistance - distanceToPoint) / params.smoothness);
746 float correctionFactor = params.smoothness * h * (1.0f - h);
747 smoothDistance = mix(smoothDistance, distanceToPoint, h) - correctionFactor;
748 correctionFactor /= 1.0f + 3.0f * params.smoothness;
749 const float3 cellColor = hash_float4_to_float3(cellPosition + cellOffset);
750 smoothColor = mix(smoothColor, cellColor, h) - correctionFactor;
751 smoothPosition = mix(smoothPosition, pointPosition, h) - correctionFactor;
752 }
753 }
754 }
755 }
756
757 VoronoiOutput octave;
758 octave.distance = smoothDistance;
759 octave.color = smoothColor;
760 octave.position = voronoi_position(cellPosition + smoothPosition);
761 return octave;
762}
763
765{
766 const float4 cellPosition = floor(coord);
767 const float4 localPosition = coord - cellPosition;
768
769 float distanceF1 = FLT_MAX;
770 float distanceF2 = FLT_MAX;
771 float4 offsetF1 = zero_float4();
772 float4 positionF1 = zero_float4();
773 float4 offsetF2 = zero_float4();
774 float4 positionF2 = zero_float4();
775 for (int u = -1; u <= 1; u++) {
776 for (int k = -1; k <= 1; k++) {
777 for (int j = -1; j <= 1; j++) {
778 for (int i = -1; i <= 1; i++) {
779 const float4 cellOffset = make_float4(i, j, k, u);
780 const float4 pointPosition = cellOffset +
781 hash_float4_to_float4(cellPosition + cellOffset) *
782 params.randomness;
783 const float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
784 if (distanceToPoint < distanceF1) {
785 distanceF2 = distanceF1;
786 distanceF1 = distanceToPoint;
787 offsetF2 = offsetF1;
788 offsetF1 = cellOffset;
789 positionF2 = positionF1;
790 positionF1 = pointPosition;
791 }
792 else if (distanceToPoint < distanceF2) {
793 distanceF2 = distanceToPoint;
794 offsetF2 = cellOffset;
795 positionF2 = pointPosition;
796 }
797 }
798 }
799 }
800 }
801
802 VoronoiOutput octave;
803 octave.distance = distanceF2;
804 octave.color = hash_float4_to_float3(cellPosition + offsetF2);
805 octave.position = voronoi_position(positionF2 + cellPosition);
806 return octave;
807}
808
810 const float4 coord)
811{
812 const float4 cellPosition = floor(coord);
813 const float4 localPosition = coord - cellPosition;
814
815 float4 vectorToClosest = zero_float4();
816 float minDistance = FLT_MAX;
817 for (int u = -1; u <= 1; u++) {
818 for (int k = -1; k <= 1; k++) {
819 for (int j = -1; j <= 1; j++) {
820 for (int i = -1; i <= 1; i++) {
821 const float4 cellOffset = make_float4(i, j, k, u);
822 const float4 vectorToPoint = cellOffset +
823 hash_float4_to_float4(cellPosition + cellOffset) *
824 params.randomness -
825 localPosition;
826 const float distanceToPoint = dot(vectorToPoint, vectorToPoint);
827 if (distanceToPoint < minDistance) {
828 minDistance = distanceToPoint;
829 vectorToClosest = vectorToPoint;
830 }
831 }
832 }
833 }
834 }
835
836 minDistance = FLT_MAX;
837 for (int u = -1; u <= 1; u++) {
838 for (int k = -1; k <= 1; k++) {
839 for (int j = -1; j <= 1; j++) {
840 for (int i = -1; i <= 1; i++) {
841 const float4 cellOffset = make_float4(i, j, k, u);
842 const float4 vectorToPoint = cellOffset +
843 hash_float4_to_float4(cellPosition + cellOffset) *
844 params.randomness -
845 localPosition;
846 const float4 perpendicularToEdge = vectorToPoint - vectorToClosest;
847 if (dot(perpendicularToEdge, perpendicularToEdge) > 0.0001f) {
848 const float distanceToEdge = dot((vectorToClosest + vectorToPoint) / 2.0f,
849 normalize(perpendicularToEdge));
850 minDistance = min(minDistance, distanceToEdge);
851 }
852 }
853 }
854 }
855 }
856
857 return minDistance;
858}
859
861 const float4 coord)
862{
863 const float4 cellPosition = floor(coord);
864 const float4 localPosition = coord - cellPosition;
865
866 float4 closestPoint = zero_float4();
867 float4 closestPointOffset = zero_float4();
868 float minDistanceSq = FLT_MAX;
869 for (int u = -1; u <= 1; u++) {
870 for (int k = -1; k <= 1; k++) {
871 for (int j = -1; j <= 1; j++) {
872 for (int i = -1; i <= 1; i++) {
873 const float4 cellOffset = make_float4(i, j, k, u);
874 const float4 pointPosition = cellOffset +
875 hash_float4_to_float4(cellPosition + cellOffset) *
876 params.randomness;
877 const float distanceToPointSq = len_squared(pointPosition - localPosition);
878 if (distanceToPointSq < minDistanceSq) {
879 minDistanceSq = distanceToPointSq;
880 closestPoint = pointPosition;
881 closestPointOffset = cellOffset;
882 }
883 }
884 }
885 }
886 }
887
888 minDistanceSq = FLT_MAX;
889 float4 closestPointToClosestPoint = zero_float4();
890 for (int u = -1; u <= 1; u++) {
891 for (int k = -1; k <= 1; k++) {
892 for (int j = -1; j <= 1; j++) {
893 for (int i = -1; i <= 1; i++) {
894 if (i == 0 && j == 0 && k == 0 && u == 0) {
895 continue;
896 }
897 const float4 cellOffset = make_float4(i, j, k, u) + closestPointOffset;
898 const float4 pointPosition = cellOffset +
899 hash_float4_to_float4(cellPosition + cellOffset) *
900 params.randomness;
901 const float distanceToPointSq = len_squared(closestPoint - pointPosition);
902 if (distanceToPointSq < minDistanceSq) {
903 minDistanceSq = distanceToPointSq;
904 closestPointToClosestPoint = pointPosition;
905 }
906 }
907 }
908 }
909 }
910
911 return distance(closestPointToClosestPoint, closestPoint) / 2.0f;
912}
913
914/* **** Fractal Voronoi **** */
915
916/* The fractalization logic is the same as for fBM Noise, except that some additions are replaced
917 * by lerps. */
918template<typename T>
920 const T coord)
921{
922 float amplitude = 1.0f;
923 float max_amplitude = 0.0f;
924 float scale = 1.0f;
925
927 const bool zero_input = params.detail == 0.0f || params.roughness == 0.0f;
928
929 for (int i = 0; i <= ceilf(params.detail); ++i) {
930 VoronoiOutput octave = (params.feature == NODE_VORONOI_F2) ?
931 voronoi_f2(params, coord * scale) :
932 (params.feature == NODE_VORONOI_SMOOTH_F1 &&
933 params.smoothness != 0.0f) ?
934 voronoi_smooth_f1(params, coord * scale) :
935 voronoi_f1(params, coord * scale);
936
937 if (zero_input) {
938 max_amplitude = 1.0f;
939 output = octave;
940 break;
941 }
942 if (i <= params.detail) {
943 max_amplitude += amplitude;
944 output.distance += octave.distance * amplitude;
945 output.color += octave.color * amplitude;
946 output.position = mix(output.position, octave.position / scale, amplitude);
947 scale *= params.lacunarity;
948 amplitude *= params.roughness;
949 }
950 else {
951 const float remainder = params.detail - floorf(params.detail);
952 if (remainder != 0.0f) {
953 max_amplitude = mix(max_amplitude, max_amplitude + amplitude, remainder);
954 output.distance = mix(
955 output.distance, output.distance + octave.distance * amplitude, remainder);
956 output.color = mix(output.color, output.color + octave.color * amplitude, remainder);
957 output.position = mix(
958 output.position, mix(output.position, octave.position / scale, amplitude), remainder);
959 }
960 }
961 }
962
963 if (params.normalize) {
964 output.distance /= max_amplitude * params.max_distance;
965 output.color /= max_amplitude;
966 }
967
968 output.position = safe_divide(output.position, params.scale);
969
970 return output;
971}
972
973/* The fractalization logic is the same as for fBM Noise, except that some additions are replaced
974 * by lerps. */
975template<typename T>
977 const T coord)
978{
979 float amplitude = 1.0f;
980 float max_amplitude = params.max_distance;
981 float scale = 1.0f;
982 float distance = 8.0f;
983
984 const bool zero_input = params.detail == 0.0f || params.roughness == 0.0f;
985
986 for (int i = 0; i <= ceilf(params.detail); ++i) {
987 const float octave_distance = voronoi_distance_to_edge(params, coord * scale);
988
989 if (zero_input) {
990 distance = octave_distance;
991 break;
992 }
993 if (i <= params.detail) {
994 max_amplitude = mix(max_amplitude, params.max_distance / scale, amplitude);
995 distance = mix(distance, min(distance, octave_distance / scale), amplitude);
996 scale *= params.lacunarity;
997 amplitude *= params.roughness;
998 }
999 else {
1000 const float remainder = params.detail - floorf(params.detail);
1001 if (remainder != 0.0f) {
1002 const float lerp_amplitude = mix(max_amplitude, params.max_distance / scale, amplitude);
1003 max_amplitude = mix(max_amplitude, lerp_amplitude, remainder);
1004 const float lerp_distance = mix(
1005 distance, min(distance, octave_distance / scale), amplitude);
1006 distance = mix(distance, min(distance, lerp_distance), remainder);
1007 }
1008 }
1009 }
1010
1011 if (params.normalize) {
1012 distance /= max_amplitude;
1013 }
1014
1015 return distance;
1016}
1017
1018ccl_device void svm_voronoi_output(const uint4 stack_offsets,
1019 ccl_private float *stack,
1020 const float distance,
1021 const float3 color,
1022 const float3 position,
1023 const float w,
1024 const float radius)
1025{
1026 uint distance_stack_offset;
1027 uint color_stack_offset;
1028 uint position_stack_offset;
1029 uint w_out_stack_offset;
1030 uint radius_stack_offset;
1031 uint unused;
1032
1034 stack_offsets.z, &unused, &unused, &distance_stack_offset, &color_stack_offset);
1036 stack_offsets.w, &position_stack_offset, &w_out_stack_offset, &radius_stack_offset);
1037
1038 if (stack_valid(distance_stack_offset)) {
1039 stack_store_float(stack, distance_stack_offset, distance);
1040 }
1041 if (stack_valid(color_stack_offset)) {
1042 stack_store_float3(stack, color_stack_offset, color);
1043 }
1044 if (stack_valid(position_stack_offset)) {
1045 stack_store_float3(stack, position_stack_offset, position);
1046 }
1047 if (stack_valid(w_out_stack_offset)) {
1048 stack_store_float(stack, w_out_stack_offset, w);
1049 }
1050 if (stack_valid(radius_stack_offset)) {
1051 stack_store_float(stack, radius_stack_offset, radius);
1052 }
1053}
1054
1055template<uint node_feature_mask>
1057 ccl_private ShaderData *sd,
1058 ccl_private float *stack,
1059 const uint dimensions,
1060 const uint feature,
1061 const uint metric,
1062 int offset)
1063{
1064 /* Read node defaults and stack offsets. */
1065 const uint4 stack_offsets = read_node(kg, &offset);
1066 const uint4 defaults1 = read_node(kg, &offset);
1067 const uint4 defaults2 = read_node(kg, &offset);
1068
1069 uint coord_stack_offset;
1070 uint w_stack_offset;
1071 uint scale_stack_offset;
1072 uint detail_stack_offset;
1073 uint roughness_stack_offset;
1074 uint lacunarity_stack_offset;
1075 uint smoothness_stack_offset;
1076 uint exponent_stack_offset;
1077 uint randomness_stack_offset;
1079
1080 svm_unpack_node_uchar4(stack_offsets.x,
1081 &coord_stack_offset,
1082 &w_stack_offset,
1083 &scale_stack_offset,
1084 &detail_stack_offset);
1085 svm_unpack_node_uchar4(stack_offsets.y,
1086 &roughness_stack_offset,
1087 &lacunarity_stack_offset,
1088 &smoothness_stack_offset,
1089 &exponent_stack_offset);
1090 svm_unpack_node_uchar2(stack_offsets.z, &randomness_stack_offset, &normalize);
1091
1092 /* Read from stack. */
1093 float3 coord = stack_load_float3(stack, coord_stack_offset);
1094 float w = stack_load_float_default(stack, w_stack_offset, defaults1.x);
1095
1097 params.feature = (NodeVoronoiFeature)feature;
1098 params.metric = (NodeVoronoiDistanceMetric)metric;
1099 params.scale = stack_load_float_default(stack, scale_stack_offset, defaults1.y);
1100 params.detail = stack_load_float_default(stack, detail_stack_offset, defaults1.z);
1101 params.roughness = stack_load_float_default(stack, roughness_stack_offset, defaults1.w);
1102 params.lacunarity = stack_load_float_default(stack, lacunarity_stack_offset, defaults2.x);
1103 params.smoothness = stack_load_float_default(stack, smoothness_stack_offset, defaults2.y);
1104 params.exponent = stack_load_float_default(stack, exponent_stack_offset, defaults2.z);
1105 params.randomness = stack_load_float_default(stack, randomness_stack_offset, defaults2.w);
1106 params.max_distance = 0.0f;
1107 params.normalize = normalize;
1108
1109 params.detail = clamp(params.detail, 0.0f, 15.0f);
1110 params.roughness = clamp(params.roughness, 0.0f, 1.0f);
1111 params.randomness = clamp(params.randomness, 0.0f, 1.0f);
1112 params.smoothness = clamp(params.smoothness / 2.0f, 0.0f, 0.5f);
1113
1114 coord *= params.scale;
1115 w *= params.scale;
1116
1117 /* Compute output, specialized for each dimension. */
1118 switch (params.feature) {
1120 float distance = 0.0f;
1121 params.max_distance = 0.5f + 0.5f * params.randomness;
1122 switch (dimensions) {
1123 case 1:
1125 break;
1126 case 2:
1128 break;
1129 case 3:
1131 break;
1132 case 4:
1134 break;
1135 default:
1136 kernel_assert(0);
1137 break;
1138 }
1139
1140 svm_voronoi_output(stack_offsets, stack, distance, zero_float3(), zero_float3(), 0.0f, 0.0f);
1141 break;
1142 }
1144 float radius = 0.0f;
1145 switch (dimensions) {
1146 case 1:
1147 radius = voronoi_n_sphere_radius(params, w);
1148 break;
1149 case 2:
1150 radius = voronoi_n_sphere_radius(params, make_float2(coord));
1151 break;
1152 case 3:
1153 radius = voronoi_n_sphere_radius(params, coord);
1154 break;
1155 case 4:
1156 radius = voronoi_n_sphere_radius(params, make_float4(coord, w));
1157 break;
1158 default:
1159 kernel_assert(0);
1160 break;
1161 }
1162
1163 svm_voronoi_output(stack_offsets, stack, 0.0f, zero_float3(), zero_float3(), 0.0f, radius);
1164 break;
1165 }
1166 default: {
1168 switch (dimensions) {
1169 case 1:
1170 params.max_distance = (0.5f + 0.5f * params.randomness) *
1171 ((params.feature == NODE_VORONOI_F2) ? 2.0f : 1.0f);
1173 break;
1174 case 2:
1175 IF_KERNEL_NODES_FEATURE(VORONOI_EXTRA)
1176 {
1177 params.max_distance = voronoi_distance(zero_float2(),
1178 make_float2(0.5f + 0.5f * params.randomness,
1179 0.5f + 0.5f * params.randomness),
1180 params) *
1181 ((params.feature == NODE_VORONOI_F2) ? 2.0f : 1.0f);
1183 }
1184 break;
1185 case 3:
1186 IF_KERNEL_NODES_FEATURE(VORONOI_EXTRA)
1187 {
1188 params.max_distance = voronoi_distance(zero_float3(),
1189 make_float3(0.5f + 0.5f * params.randomness,
1190 0.5f + 0.5f * params.randomness,
1191 0.5f + 0.5f * params.randomness),
1192 params) *
1193 ((params.feature == NODE_VORONOI_F2) ? 2.0f : 1.0f);
1195 }
1196 break;
1197 case 4:
1198 IF_KERNEL_NODES_FEATURE(VORONOI_EXTRA)
1199 {
1200 params.max_distance = voronoi_distance(zero_float4(),
1201 make_float4(0.5f + 0.5f * params.randomness,
1202 0.5f + 0.5f * params.randomness,
1203 0.5f + 0.5f * params.randomness,
1204 0.5f + 0.5f * params.randomness),
1205 params) *
1206 ((params.feature == NODE_VORONOI_F2) ? 2.0f : 1.0f);
1208 }
1209 break;
1210 default:
1211 kernel_assert(0);
1212 break;
1213 }
1214
1215 svm_voronoi_output(stack_offsets,
1216 stack,
1217 output.distance,
1218 output.color,
1219 make_float3(output.position),
1220 output.position.w,
1221 0.0f);
1222 break;
1223 }
1224 }
1225
1226 return offset;
1227}
1228
MINLINE float safe_divide(float a, float b)
unsigned int uint
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
reduce_max(value.rgb)") DEFINE_VALUE("REDUCE(lhs
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
ccl_device_inline void stack_store_float(ccl_private float *stack, const uint a, const float f)
ccl_device_inline uint4 read_node(KernelGlobals kg, ccl_private int *const offset)
ccl_device_inline void stack_store_float3(ccl_private float *stack, const uint a, const float3 f)
ccl_device_inline float stack_load_float_default(const ccl_private float *stack, const uint a, const uint value)
ccl_device_forceinline void svm_unpack_node_uchar2(const uint i, ccl_private uint *x, ccl_private uint *y)
ccl_device_forceinline void svm_unpack_node_uchar3(const uint i, ccl_private uint *x, ccl_private uint *y, ccl_private uint *z)
ccl_device_forceinline void svm_unpack_node_uchar4(const uint i, ccl_private uint *x, ccl_private uint *y, ccl_private uint *z, ccl_private uint *w)
ccl_device_inline bool stack_valid(const uint a)
CCL_NAMESPACE_BEGIN ccl_device_inline float3 stack_load_float3(const ccl_private float *stack, const uint a)
#define kernel_assert(cond)
#define IF_KERNEL_NODES_FEATURE(feature)
#define ccl_device
#define ccl_private
const ThreadKernelGlobalsCPU * KernelGlobals
#define ccl_device_noinline
#define powf(x, y)
#define CCL_NAMESPACE_END
ccl_device_forceinline float4 make_float4(const float x, const float y, const float z, const float w)
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define ceilf(x)
#define floorf(x)
ccl_device_forceinline float2 make_float2(const float x, const float y)
#define fabsf(x)
VecBase< float, 4 > float4
VecBase< float, D > normalize(VecOp< float, D >) RET
#define floor
#define output
constexpr T clamp(T, U, U) RET
float distance(VecOp< float, D >, VecOp< float, D >) RET
ccl_device_inline float3 hash_float_to_float3(const float k)
Definition hash.h:213
ccl_device_inline float2 hash_float2_to_float2(const float2 k)
Definition hash.h:191
ccl_device_inline float3 hash_float2_to_float3(const float2 k)
Definition hash.h:220
ccl_device_inline float4 hash_float4_to_float4(const float4 k)
Definition hash.h:203
ccl_device_inline float3 hash_float4_to_float3(const float4 k)
Definition hash.h:227
ccl_device_inline float3 hash_float3_to_float3(const float3 k)
Definition hash.h:196
#define mix(a, b, c)
Definition hash.h:35
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
NodeVoronoiFeature
@ NODE_VORONOI_SMOOTH_F1
@ NODE_VORONOI_N_SPHERE_RADIUS
@ NODE_VORONOI_F2
@ NODE_VORONOI_DISTANCE_TO_EDGE
NodeVoronoiDistanceMetric
@ NODE_VORONOI_EUCLIDEAN
@ NODE_VORONOI_MANHATTAN
@ NODE_VORONOI_CHEBYCHEV
@ NODE_VORONOI_MINKOWSKI
MINLINE float smoothstep(float edge0, float edge1, float x)
ccl_device_inline float2 power(const float2 v, const float e)
CCL_NAMESPACE_BEGIN ccl_device_inline float2 zero_float2()
Definition math_float2.h:13
ccl_device_inline float len_squared(const float2 a)
ccl_device_inline float reduce_add(const float2 a)
ccl_device_inline float2 fabs(const float2 a)
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
Definition math_float3.h:15
CCL_NAMESPACE_BEGIN ccl_device_inline float4 zero_float4()
Definition math_float4.h:13
#define T
float hash_float_to_float(float k)
Definition node_hash.h:13
#define min(a, b)
Definition sort.cc:36
#define FLT_MAX
Definition stdcycles.h:14
float3 color
Definition voronoi.h:45
float4 position
Definition voronoi.h:46
float distance
Definition voronoi.h:44
float x
float y
uint x
Definition types_uint4.h:13
uint y
Definition types_uint4.h:13
uint z
Definition types_uint4.h:13
uint w
Definition types_uint4.h:13
i
Definition text_draw.cc:230
ccl_device VoronoiOutput voronoi_f1(const ccl_private VoronoiParams &params, const float coord)
Definition voronoi.h:103
ccl_device float voronoi_distance_bound(const T a, const T b, const ccl_private VoronoiParams &params)
Definition voronoi.h:77
ccl_device float voronoi_distance(const float a, const float b)
Definition voronoi.h:51
ccl_device VoronoiOutput voronoi_smooth_f1(const ccl_private VoronoiParams &params, const float coord)
Definition voronoi.h:130
ccl_device float voronoi_n_sphere_radius(const ccl_private VoronoiParams &params, const float coord)
Definition voronoi.h:221
ccl_device VoronoiOutput fractal_voronoi_x_fx(const ccl_private VoronoiParams &params, const T coord)
Definition voronoi.h:919
ccl_device float4 voronoi_position(const float coord)
Definition voronoi.h:98
ccl_device void svm_voronoi_output(const uint4 stack_offsets, ccl_private float *stack, const float distance, const float3 color, const float3 position, const float w, const float radius)
Definition voronoi.h:1018
ccl_device float fractal_voronoi_distance_to_edge(const ccl_private VoronoiParams &params, const T coord)
Definition voronoi.h:976
ccl_device_noinline int svm_node_tex_voronoi(KernelGlobals kg, ccl_private ShaderData *sd, ccl_private float *stack, const uint dimensions, const uint feature, const uint metric, int offset)
Definition voronoi.h:1056
ccl_device float voronoi_distance_to_edge(const ccl_private VoronoiParams &params, const float coord)
Definition voronoi.h:202
ccl_device VoronoiOutput voronoi_f2(const ccl_private VoronoiParams &params, const float coord)
Definition voronoi.h:164