Blender V4.3
node_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#include "node_hash.h"
6#include "stdcycles.h"
7#include "vector2.h"
8#include "vector4.h"
9
10#define vector3 point
11
13 float scale;
14 float detail;
15 float roughness;
18 float exponent;
22 string feature;
23 string metric;
24};
25
27 float Distance;
28 color Color;
29 vector4 Position;
30};
31
32/* **** Distance Functions **** */
33
34float distance(float a, float b)
35{
36 return abs(a - b);
37}
38
39float distance(vector2 a, vector2 b)
40{
41 return length(a - b);
42}
43
44float distance(vector4 a, vector4 b)
45{
46 return length(a - b);
47}
48
49float voronoi_distance(float a, float b)
50{
51 return abs(a - b);
52}
53
54float voronoi_distance(vector2 a, vector2 b, VoronoiParams params)
55{
56 if (params.metric == "euclidean") {
57 return distance(a, b);
58 }
59 else if (params.metric == "manhattan") {
60 return abs(a.x - b.x) + abs(a.y - b.y);
61 }
62 else if (params.metric == "chebychev") {
63 return max(abs(a.x - b.x), abs(a.y - b.y));
64 }
65 else if (params.metric == "minkowski") {
66 return pow(pow(abs(a.x - b.x), params.exponent) + pow(abs(a.y - b.y), params.exponent),
67 1.0 / params.exponent);
68 }
69 else {
70 return 0.0;
71 }
72}
73
75{
76 if (params.metric == "euclidean") {
77 return distance(a, b);
78 }
79 else if (params.metric == "manhattan") {
80 return abs(a[0] - b[0]) + abs(a[1] - b[1]) + abs(a[2] - b[2]);
81 }
82 else if (params.metric == "chebychev") {
83 return max(abs(a[0] - b[0]), max(abs(a[1] - b[1]), abs(a[2] - b[2])));
84 }
85 else if (params.metric == "minkowski") {
86 return pow(pow(abs(a[0] - b[0]), params.exponent) + pow(abs(a[1] - b[1]), params.exponent) +
87 pow(abs(a[2] - b[2]), params.exponent),
88 1.0 / params.exponent);
89 }
90 else {
91 return 0.0;
92 }
93}
94
95float voronoi_distance(vector4 a, vector4 b, VoronoiParams params)
96{
97 if (params.metric == "euclidean") {
98 return distance(a, b);
99 }
100 else if (params.metric == "manhattan") {
101 return abs(a.x - b.x) + abs(a.y - b.y) + abs(a.z - b.z) + abs(a.w - b.w);
102 }
103 else if (params.metric == "chebychev") {
104 return max(abs(a.x - b.x), max(abs(a.y - b.y), max(abs(a.z - b.z), abs(a.w - b.w))));
105 }
106 else if (params.metric == "minkowski") {
107 return pow(pow(abs(a.x - b.x), params.exponent) + pow(abs(a.y - b.y), params.exponent) +
108 pow(abs(a.z - b.z), params.exponent) + pow(abs(a.w - b.w), params.exponent),
109 1.0 / params.exponent);
110 }
111 else {
112 return 0.0;
113 }
114}
115
116/* **** Safe Division **** */
117
118vector2 safe_divide(vector2 a, float b)
119{
120 return vector2((b != 0.0) ? a.x / b : 0.0, (b != 0.0) ? a.y / b : 0.0);
121}
122
123vector4 safe_divide(vector4 a, float b)
124{
125 return vector4((b != 0.0) ? a.x / b : 0.0,
126 (b != 0.0) ? a.y / b : 0.0,
127 (b != 0.0) ? a.z / b : 0.0,
128 (b != 0.0) ? a.w / b : 0.0);
129}
130
131/*
132 * SPDX-License-Identifier: MIT
133 * Original code is copyright (c) 2013 Inigo Quilez.
134 *
135 * Smooth Voronoi:
136 * - https://wiki.blender.org/wiki/User:OmarSquircleArt/GSoC2019/Documentation/Smooth_Voronoi
137 *
138 * Distance To Edge based on:
139 *
140 * - https://www.iquilezles.org/www/articles/voronoilines/voronoilines.htm
141 * - https://www.shadertoy.com/view/ldl3W8
142 *
143 * With optimization to change -2..2 scan window to -1..1 for better performance,
144 * as explained in https://www.shadertoy.com/view/llG3zy.
145 */
146
147/* **** 1D Voronoi **** */
148
149vector4 voronoi_position(float coord)
150{
151 return vector4(0.0, 0.0, 0.0, coord);
152}
153
155{
156 float cellPosition = floor(coord);
157 float localPosition = coord - cellPosition;
158
159 float minDistance = FLT_MAX;
160 float targetOffset = 0.0;
161 float targetPosition = 0.0;
162 for (int i = -1; i <= 1; i++) {
163 float cellOffset = i;
164 float pointPosition = cellOffset +
165 hash_float_to_float(cellPosition + cellOffset) * params.randomness;
166 float distanceToPoint = voronoi_distance(pointPosition, localPosition);
167 if (distanceToPoint < minDistance) {
168 targetOffset = cellOffset;
169 minDistance = distanceToPoint;
170 targetPosition = pointPosition;
171 }
172 }
173
174 VoronoiOutput octave;
175 octave.Distance = minDistance;
176 octave.Color = hash_float_to_color(cellPosition + targetOffset);
177 octave.Position = voronoi_position(targetPosition + cellPosition);
178 return octave;
179}
180
182{
183 float cellPosition = floor(coord);
184 float localPosition = coord - cellPosition;
185
186 float smoothDistance = 0.0;
187 float smoothPosition = 0.0;
188 vector3 smoothColor = vector3(0.0, 0.0, 0.0);
189 float h = -1.0;
190 for (int i = -2; i <= 2; i++) {
191 float cellOffset = i;
192 float pointPosition = cellOffset +
193 hash_float_to_float(cellPosition + cellOffset) * params.randomness;
194 float distanceToPoint = voronoi_distance(pointPosition, localPosition);
195 h = h == -1.0 ? 1.0 :
196 smoothstep(0.0,
197 1.0,
198 0.5 + 0.5 * (smoothDistance - distanceToPoint) / params.smoothness);
199 float correctionFactor = params.smoothness * h * (1.0 - h);
200 smoothDistance = mix(smoothDistance, distanceToPoint, h) - correctionFactor;
201 correctionFactor /= 1.0 + 3.0 * params.smoothness;
202 color cellColor = hash_float_to_color(cellPosition + cellOffset);
203 smoothColor = mix(smoothColor, cellColor, h) - correctionFactor;
204 smoothPosition = mix(smoothPosition, pointPosition, h) - correctionFactor;
205 }
206
207 VoronoiOutput octave;
208 octave.Distance = smoothDistance;
209 octave.Color = smoothColor;
210 octave.Position = voronoi_position(cellPosition + smoothPosition);
211 return octave;
212}
213
215{
216 float cellPosition = floor(coord);
217 float localPosition = coord - cellPosition;
218
219 float distanceF1 = FLT_MAX;
220 float distanceF2 = FLT_MAX;
221 float offsetF1 = 0.0;
222 float positionF1 = 0.0;
223 float offsetF2 = 0.0;
224 float positionF2 = 0.0;
225 for (int i = -1; i <= 1; i++) {
226 float cellOffset = i;
227 float pointPosition = cellOffset +
228 hash_float_to_float(cellPosition + cellOffset) * params.randomness;
229 float distanceToPoint = voronoi_distance(pointPosition, localPosition);
230 if (distanceToPoint < distanceF1) {
231 distanceF2 = distanceF1;
232 distanceF1 = distanceToPoint;
233 offsetF2 = offsetF1;
234 offsetF1 = cellOffset;
235 positionF2 = positionF1;
236 positionF1 = pointPosition;
237 }
238 else if (distanceToPoint < distanceF2) {
239 distanceF2 = distanceToPoint;
240 offsetF2 = cellOffset;
241 positionF2 = pointPosition;
242 }
243 }
244
245 VoronoiOutput octave;
246 octave.Distance = distanceF2;
247 octave.Color = hash_float_to_color(cellPosition + offsetF2);
248 octave.Position = voronoi_position(positionF2 + cellPosition);
249 return octave;
250}
251
253{
254 float cellPosition = floor(coord);
255 float localPosition = coord - cellPosition;
256
257 float midPointPosition = hash_float_to_float(cellPosition) * params.randomness;
258 float leftPointPosition = -1.0 + hash_float_to_float(cellPosition - 1.0) * params.randomness;
259 float rightPointPosition = 1.0 + hash_float_to_float(cellPosition + 1.0) * params.randomness;
260 float distanceToMidLeft = abs((midPointPosition + leftPointPosition) / 2.0 - localPosition);
261 float distanceToMidRight = abs((midPointPosition + rightPointPosition) / 2.0 - localPosition);
262
263 return min(distanceToMidLeft, distanceToMidRight);
264}
265
267{
268 float cellPosition = floor(coord);
269 float localPosition = coord - cellPosition;
270
271 float closestPoint = 0.0;
272 float closestPointOffset = 0.0;
273 float minDistance = FLT_MAX;
274 for (int i = -1; i <= 1; i++) {
275 float cellOffset = i;
276 float pointPosition = cellOffset +
277 hash_float_to_float(cellPosition + cellOffset) * params.randomness;
278 float distanceToPoint = abs(pointPosition - localPosition);
279 if (distanceToPoint < minDistance) {
280 minDistance = distanceToPoint;
281 closestPoint = pointPosition;
282 closestPointOffset = cellOffset;
283 }
284 }
285
286 minDistance = FLT_MAX;
287 float closestPointToClosestPoint = 0.0;
288 for (int i = -1; i <= 1; i++) {
289 if (i == 0) {
290 continue;
291 }
292 float cellOffset = i + closestPointOffset;
293 float pointPosition = cellOffset +
294 hash_float_to_float(cellPosition + cellOffset) * params.randomness;
295 float distanceToPoint = abs(closestPoint - pointPosition);
296 if (distanceToPoint < minDistance) {
297 minDistance = distanceToPoint;
298 closestPointToClosestPoint = pointPosition;
299 }
300 }
301
302 return abs(closestPointToClosestPoint - closestPoint) / 2.0;
303}
304
305/* **** 2D Voronoi **** */
306
307vector4 voronoi_position(vector2 coord)
308{
309 return vector4(coord.x, coord.y, 0.0, 0.0);
310}
311
313{
314 vector2 cellPosition = floor(coord);
315 vector2 localPosition = coord - cellPosition;
316
317 float minDistance = FLT_MAX;
318 vector2 targetOffset = vector2(0.0, 0.0);
319 vector2 targetPosition = vector2(0.0, 0.0);
320 for (int j = -1; j <= 1; j++) {
321 for (int i = -1; i <= 1; i++) {
322 vector2 cellOffset = vector2(i, j);
323 vector2 pointPosition = cellOffset + hash_vector2_to_vector2(cellPosition + cellOffset) *
324 params.randomness;
325 float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
326 if (distanceToPoint < minDistance) {
327 targetOffset = cellOffset;
328 minDistance = distanceToPoint;
329 targetPosition = pointPosition;
330 }
331 }
332 }
333
334 VoronoiOutput octave;
335 octave.Distance = minDistance;
336 octave.Color = hash_vector2_to_color(cellPosition + targetOffset);
337 octave.Position = voronoi_position(targetPosition + cellPosition);
338 return octave;
339}
340
342{
343 vector2 cellPosition = floor(coord);
344 vector2 localPosition = coord - cellPosition;
345
346 float smoothDistance = 0.0;
347 vector3 smoothColor = vector3(0.0, 0.0, 0.0);
348 vector2 smoothPosition = vector2(0.0, 0.0);
349 float h = -1.0;
350 for (int j = -2; j <= 2; j++) {
351 for (int i = -2; i <= 2; i++) {
352 vector2 cellOffset = vector2(i, j);
353 vector2 pointPosition = cellOffset + hash_vector2_to_vector2(cellPosition + cellOffset) *
354 params.randomness;
355 float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
356 h = h == -1.0 ?
357 1.0 :
359 0.0, 1.0, 0.5 + 0.5 * (smoothDistance - distanceToPoint) / params.smoothness);
360 float correctionFactor = params.smoothness * h * (1.0 - h);
361 smoothDistance = mix(smoothDistance, distanceToPoint, h) - correctionFactor;
362 correctionFactor /= 1.0 + 3.0 * params.smoothness;
363 color cellColor = hash_vector2_to_color(cellPosition + cellOffset);
364 smoothColor = mix(smoothColor, cellColor, h) - correctionFactor;
365 smoothPosition = mix(smoothPosition, pointPosition, h) - correctionFactor;
366 }
367 }
368
369 VoronoiOutput octave;
370 octave.Distance = smoothDistance;
371 octave.Color = smoothColor;
372 octave.Position = voronoi_position(cellPosition + smoothPosition);
373 return octave;
374}
375
377{
378 vector2 cellPosition = floor(coord);
379 vector2 localPosition = coord - cellPosition;
380
381 float distanceF1 = FLT_MAX;
382 float distanceF2 = FLT_MAX;
383 vector2 offsetF1 = vector2(0.0, 0.0);
384 vector2 positionF1 = vector2(0.0, 0.0);
385 vector2 offsetF2 = vector2(0.0, 0.0);
386 vector2 positionF2 = vector2(0.0, 0.0);
387 for (int j = -1; j <= 1; j++) {
388 for (int i = -1; i <= 1; i++) {
389 vector2 cellOffset = vector2(i, j);
390 vector2 pointPosition = cellOffset + hash_vector2_to_vector2(cellPosition + cellOffset) *
391 params.randomness;
392 float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
393 if (distanceToPoint < distanceF1) {
394 distanceF2 = distanceF1;
395 distanceF1 = distanceToPoint;
396 offsetF2 = offsetF1;
397 offsetF1 = cellOffset;
398 positionF2 = positionF1;
399 positionF1 = pointPosition;
400 }
401 else if (distanceToPoint < distanceF2) {
402 distanceF2 = distanceToPoint;
403 offsetF2 = cellOffset;
404 positionF2 = pointPosition;
405 }
406 }
407 }
408
409 VoronoiOutput octave;
410 octave.Distance = distanceF2;
411 octave.Color = hash_vector2_to_color(cellPosition + offsetF2);
412 octave.Position = voronoi_position(positionF2 + cellPosition);
413 return octave;
414}
415
417{
418 vector2 cellPosition = floor(coord);
419 vector2 localPosition = coord - cellPosition;
420
421 vector2 vectorToClosest = vector2(0.0, 0.0);
422 float minDistance = FLT_MAX;
423 for (int j = -1; j <= 1; j++) {
424 for (int i = -1; i <= 1; i++) {
425 vector2 cellOffset = vector2(i, j);
426 vector2 vectorToPoint = cellOffset +
427 hash_vector2_to_vector2(cellPosition + cellOffset) *
428 params.randomness -
429 localPosition;
430 float distanceToPoint = dot(vectorToPoint, vectorToPoint);
431 if (distanceToPoint < minDistance) {
432 minDistance = distanceToPoint;
433 vectorToClosest = vectorToPoint;
434 }
435 }
436 }
437
438 minDistance = FLT_MAX;
439 for (int j = -1; j <= 1; j++) {
440 for (int i = -1; i <= 1; i++) {
441 vector2 cellOffset = vector2(i, j);
442 vector2 vectorToPoint = cellOffset +
443 hash_vector2_to_vector2(cellPosition + cellOffset) *
444 params.randomness -
445 localPosition;
446 vector2 perpendicularToEdge = vectorToPoint - vectorToClosest;
447 if (dot(perpendicularToEdge, perpendicularToEdge) > 0.0001) {
448 float distanceToEdge = dot((vectorToClosest + vectorToPoint) / 2.0,
449 normalize(perpendicularToEdge));
450 minDistance = min(minDistance, distanceToEdge);
451 }
452 }
453 }
454
455 return minDistance;
456}
457
459{
460 vector2 cellPosition = floor(coord);
461 vector2 localPosition = coord - cellPosition;
462
463 vector2 closestPoint = vector2(0.0, 0.0);
464 vector2 closestPointOffset = vector2(0.0, 0.0);
465 float minDistance = FLT_MAX;
466 for (int j = -1; j <= 1; j++) {
467 for (int i = -1; i <= 1; i++) {
468 vector2 cellOffset = vector2(i, j);
469 vector2 pointPosition = cellOffset + hash_vector2_to_vector2(cellPosition + cellOffset) *
470 params.randomness;
471 float distanceToPoint = distance(pointPosition, localPosition);
472 if (distanceToPoint < minDistance) {
473 minDistance = distanceToPoint;
474 closestPoint = pointPosition;
475 closestPointOffset = cellOffset;
476 }
477 }
478 }
479
480 minDistance = FLT_MAX;
481 vector2 closestPointToClosestPoint = vector2(0.0, 0.0);
482 for (int j = -1; j <= 1; j++) {
483 for (int i = -1; i <= 1; i++) {
484 if (i == 0 && j == 0) {
485 continue;
486 }
487 vector2 cellOffset = vector2(i, j) + closestPointOffset;
488 vector2 pointPosition = cellOffset + hash_vector2_to_vector2(cellPosition + cellOffset) *
489 params.randomness;
490 float distanceToPoint = distance(closestPoint, pointPosition);
491 if (distanceToPoint < minDistance) {
492 minDistance = distanceToPoint;
493 closestPointToClosestPoint = pointPosition;
494 }
495 }
496 }
497
498 return distance(closestPointToClosestPoint, closestPoint) / 2.0;
499}
500
501/* **** 3D Voronoi **** */
502
504{
505 return vector4(coord.x, coord.y, coord.z, 0.0);
506}
507
509{
510 vector3 cellPosition = floor(coord);
511 vector3 localPosition = coord - cellPosition;
512
513 float minDistance = FLT_MAX;
514 vector3 targetOffset = vector3(0.0, 0.0, 0.0);
515 vector3 targetPosition = vector3(0.0, 0.0, 0.0);
516 for (int k = -1; k <= 1; k++) {
517 for (int j = -1; j <= 1; j++) {
518 for (int i = -1; i <= 1; i++) {
519 vector3 cellOffset = vector3(i, j, k);
520 vector3 pointPosition = cellOffset + hash_vector3_to_vector3(cellPosition + cellOffset) *
521 params.randomness;
522 float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
523 if (distanceToPoint < minDistance) {
524 targetOffset = cellOffset;
525 minDistance = distanceToPoint;
526 targetPosition = pointPosition;
527 }
528 }
529 }
530 }
531
532 VoronoiOutput octave;
533 octave.Distance = minDistance;
534 octave.Color = hash_vector3_to_color(cellPosition + targetOffset);
535 octave.Position = voronoi_position(targetPosition + cellPosition);
536 return octave;
537}
538
540{
541 vector3 cellPosition = floor(coord);
542 vector3 localPosition = coord - cellPosition;
543
544 float smoothDistance = 0.0;
545 vector3 smoothColor = vector3(0.0, 0.0, 0.0);
546 vector3 smoothPosition = vector3(0.0, 0.0, 0.0);
547 float h = -1.0;
548 for (int k = -2; k <= 2; k++) {
549 for (int j = -2; j <= 2; j++) {
550 for (int i = -2; i <= 2; i++) {
551 vector3 cellOffset = vector3(i, j, k);
552 vector3 pointPosition = cellOffset + hash_vector3_to_vector3(cellPosition + cellOffset) *
553 params.randomness;
554 float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
555 h = h == -1.0 ?
556 1.0 :
558 0.0, 1.0, 0.5 + 0.5 * (smoothDistance - distanceToPoint) / params.smoothness);
559 float correctionFactor = params.smoothness * h * (1.0 - h);
560 smoothDistance = mix(smoothDistance, distanceToPoint, h) - correctionFactor;
561 correctionFactor /= 1.0 + 3.0 * params.smoothness;
562 color cellColor = hash_vector3_to_color(cellPosition + cellOffset);
563 smoothColor = mix(smoothColor, cellColor, h) - correctionFactor;
564 smoothPosition = mix(smoothPosition, pointPosition, h) - correctionFactor;
565 }
566 }
567 }
568
569 VoronoiOutput octave;
570 octave.Distance = smoothDistance;
571 octave.Color = smoothColor;
572 octave.Position = voronoi_position(cellPosition + smoothPosition);
573 return octave;
574}
575
577{
578 vector3 cellPosition = floor(coord);
579 vector3 localPosition = coord - cellPosition;
580
581 float distanceF1 = FLT_MAX;
582 float distanceF2 = FLT_MAX;
583 vector3 offsetF1 = vector3(0.0, 0.0, 0.0);
584 vector3 positionF1 = vector3(0.0, 0.0, 0.0);
585 vector3 offsetF2 = vector3(0.0, 0.0, 0.0);
586 vector3 positionF2 = vector3(0.0, 0.0, 0.0);
587 for (int k = -1; k <= 1; k++) {
588 for (int j = -1; j <= 1; j++) {
589 for (int i = -1; i <= 1; i++) {
590 vector3 cellOffset = vector3(i, j, k);
591 vector3 pointPosition = cellOffset + hash_vector3_to_vector3(cellPosition + cellOffset) *
592 params.randomness;
593 float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
594 if (distanceToPoint < distanceF1) {
595 distanceF2 = distanceF1;
596 distanceF1 = distanceToPoint;
597 offsetF2 = offsetF1;
598 offsetF1 = cellOffset;
599 positionF2 = positionF1;
600 positionF1 = pointPosition;
601 }
602 else if (distanceToPoint < distanceF2) {
603 distanceF2 = distanceToPoint;
604 offsetF2 = cellOffset;
605 positionF2 = pointPosition;
606 }
607 }
608 }
609 }
610
611 VoronoiOutput octave;
612 octave.Distance = distanceF2;
613 octave.Color = hash_vector3_to_color(cellPosition + offsetF2);
614 octave.Position = voronoi_position(positionF2 + cellPosition);
615 return octave;
616}
617
619{
620 vector3 cellPosition = floor(coord);
621 vector3 localPosition = coord - cellPosition;
622
623 vector3 vectorToClosest = vector3(0.0, 0.0, 0.0);
624 float minDistance = FLT_MAX;
625 for (int k = -1; k <= 1; k++) {
626 for (int j = -1; j <= 1; j++) {
627 for (int i = -1; i <= 1; i++) {
628 vector3 cellOffset = vector3(i, j, k);
629 vector3 vectorToPoint = cellOffset +
630 hash_vector3_to_vector3(cellPosition + cellOffset) *
631 params.randomness -
632 localPosition;
633 float distanceToPoint = dot(vectorToPoint, vectorToPoint);
634 if (distanceToPoint < minDistance) {
635 minDistance = distanceToPoint;
636 vectorToClosest = vectorToPoint;
637 }
638 }
639 }
640 }
641
642 minDistance = FLT_MAX;
643 for (int k = -1; k <= 1; k++) {
644 for (int j = -1; j <= 1; j++) {
645 for (int i = -1; i <= 1; i++) {
646 vector3 cellOffset = vector3(i, j, k);
647 vector3 vectorToPoint = cellOffset +
648 hash_vector3_to_vector3(cellPosition + cellOffset) *
649 params.randomness -
650 localPosition;
651 vector3 perpendicularToEdge = vectorToPoint - vectorToClosest;
652 if (dot(perpendicularToEdge, perpendicularToEdge) > 0.0001) {
653 float distanceToEdge = dot((vectorToClosest + vectorToPoint) / 2.0,
654 normalize((vector)perpendicularToEdge));
655 minDistance = min(minDistance, distanceToEdge);
656 }
657 }
658 }
659 }
660
661 return minDistance;
662}
663
665{
666 vector3 cellPosition = floor(coord);
667 vector3 localPosition = coord - cellPosition;
668
669 vector3 closestPoint = vector3(0.0, 0.0, 0.0);
670 vector3 closestPointOffset = vector3(0.0, 0.0, 0.0);
671 float minDistance = FLT_MAX;
672 for (int k = -1; k <= 1; k++) {
673 for (int j = -1; j <= 1; j++) {
674 for (int i = -1; i <= 1; i++) {
675 vector3 cellOffset = vector3(i, j, k);
676 vector3 pointPosition = cellOffset + hash_vector3_to_vector3(cellPosition + cellOffset) *
677 params.randomness;
678 float distanceToPoint = distance(pointPosition, localPosition);
679 if (distanceToPoint < minDistance) {
680 minDistance = distanceToPoint;
681 closestPoint = pointPosition;
682 closestPointOffset = cellOffset;
683 }
684 }
685 }
686 }
687
688 minDistance = FLT_MAX;
689 vector3 closestPointToClosestPoint = vector3(0.0, 0.0, 0.0);
690 for (int k = -1; k <= 1; k++) {
691 for (int j = -1; j <= 1; j++) {
692 for (int i = -1; i <= 1; i++) {
693 if (i == 0 && j == 0 && k == 0) {
694 continue;
695 }
696 vector3 cellOffset = vector3(i, j, k) + closestPointOffset;
697 vector3 pointPosition = cellOffset + hash_vector3_to_vector3(cellPosition + cellOffset) *
698 params.randomness;
699 float distanceToPoint = distance(closestPoint, pointPosition);
700 if (distanceToPoint < minDistance) {
701 minDistance = distanceToPoint;
702 closestPointToClosestPoint = pointPosition;
703 }
704 }
705 }
706 }
707
708 return distance(closestPointToClosestPoint, closestPoint) / 2.0;
709}
710
711/* **** 4D Voronoi **** */
712
713vector4 voronoi_position(vector4 coord)
714{
715 return coord;
716}
717
719{
720 vector4 cellPosition = floor(coord);
721 vector4 localPosition = coord - cellPosition;
722
723 float minDistance = FLT_MAX;
724 vector4 targetOffset = vector4(0.0, 0.0, 0.0, 0.0);
725 vector4 targetPosition = vector4(0.0, 0.0, 0.0, 0.0);
726 for (int u = -1; u <= 1; u++) {
727 for (int k = -1; k <= 1; k++) {
728 for (int j = -1; j <= 1; j++) {
729 for (int i = -1; i <= 1; i++) {
730 vector4 cellOffset = vector4(i, j, k, u);
731 vector4 pointPosition = cellOffset + hash_vector4_to_vector4(cellPosition + cellOffset) *
732 params.randomness;
733 float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
734 if (distanceToPoint < minDistance) {
735 targetOffset = cellOffset;
736 minDistance = distanceToPoint;
737 targetPosition = pointPosition;
738 }
739 }
740 }
741 }
742 }
743
744 VoronoiOutput octave;
745 octave.Distance = minDistance;
746 octave.Color = hash_vector4_to_color(cellPosition + targetOffset);
747 octave.Position = voronoi_position(targetPosition + cellPosition);
748 return octave;
749}
750
752{
753 vector4 cellPosition = floor(coord);
754 vector4 localPosition = coord - cellPosition;
755
756 float smoothDistance = 0.0;
757 vector3 smoothColor = vector3(0.0, 0.0, 0.0);
758 vector4 smoothPosition = vector4(0.0, 0.0, 0.0, 0.0);
759 float h = -1.0;
760 for (int u = -2; u <= 2; u++) {
761 for (int k = -2; k <= 2; k++) {
762 for (int j = -2; j <= 2; j++) {
763 for (int i = -2; i <= 2; i++) {
764 vector4 cellOffset = vector4(i, j, k, u);
765 vector4 pointPosition = cellOffset + hash_vector4_to_vector4(cellPosition + cellOffset) *
766 params.randomness;
767 float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
768 h = h == -1.0 ?
769 1.0 :
770 smoothstep(0.0,
771 1.0,
772 0.5 + 0.5 * (smoothDistance - distanceToPoint) / params.smoothness);
773 float correctionFactor = params.smoothness * h * (1.0 - h);
774 smoothDistance = mix(smoothDistance, distanceToPoint, h) - correctionFactor;
775 correctionFactor /= 1.0 + 3.0 * params.smoothness;
776 color cellColor = hash_vector4_to_color(cellPosition + cellOffset);
777 smoothColor = mix(smoothColor, cellColor, h) - correctionFactor;
778 smoothPosition = mix(smoothPosition, pointPosition, h) - correctionFactor;
779 }
780 }
781 }
782 }
783
784 VoronoiOutput octave;
785 octave.Distance = smoothDistance;
786 octave.Color = smoothColor;
787 octave.Position = voronoi_position(cellPosition + smoothPosition);
788 return octave;
789}
790
792{
793 vector4 cellPosition = floor(coord);
794 vector4 localPosition = coord - cellPosition;
795
796 float distanceF1 = FLT_MAX;
797 float distanceF2 = FLT_MAX;
798 vector4 offsetF1 = vector4(0.0, 0.0, 0.0, 0.0);
799 vector4 positionF1 = vector4(0.0, 0.0, 0.0, 0.0);
800 vector4 offsetF2 = vector4(0.0, 0.0, 0.0, 0.0);
801 vector4 positionF2 = vector4(0.0, 0.0, 0.0, 0.0);
802 for (int u = -1; u <= 1; u++) {
803 for (int k = -1; k <= 1; k++) {
804 for (int j = -1; j <= 1; j++) {
805 for (int i = -1; i <= 1; i++) {
806 vector4 cellOffset = vector4(i, j, k, u);
807 vector4 pointPosition = cellOffset + hash_vector4_to_vector4(cellPosition + cellOffset) *
808 params.randomness;
809 float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
810 if (distanceToPoint < distanceF1) {
811 distanceF2 = distanceF1;
812 distanceF1 = distanceToPoint;
813 offsetF2 = offsetF1;
814 offsetF1 = cellOffset;
815 positionF2 = positionF1;
816 positionF1 = pointPosition;
817 }
818 else if (distanceToPoint < distanceF2) {
819 distanceF2 = distanceToPoint;
820 offsetF2 = cellOffset;
821 positionF2 = pointPosition;
822 }
823 }
824 }
825 }
826 }
827
828 VoronoiOutput octave;
829 octave.Distance = distanceF2;
830 octave.Color = hash_vector4_to_color(cellPosition + offsetF2);
831 octave.Position = voronoi_position(positionF2 + cellPosition);
832 return octave;
833}
834
836{
837 vector4 cellPosition = floor(coord);
838 vector4 localPosition = coord - cellPosition;
839
840 vector4 vectorToClosest = vector4(0.0, 0.0, 0.0, 0.0);
841 float minDistance = FLT_MAX;
842 for (int u = -1; u <= 1; u++) {
843 for (int k = -1; k <= 1; k++) {
844 for (int j = -1; j <= 1; j++) {
845 for (int i = -1; i <= 1; i++) {
846 vector4 cellOffset = vector4(i, j, k, u);
847 vector4 vectorToPoint = cellOffset +
848 hash_vector4_to_vector4(cellPosition + cellOffset) *
849 params.randomness -
850 localPosition;
851 float distanceToPoint = dot(vectorToPoint, vectorToPoint);
852 if (distanceToPoint < minDistance) {
853 minDistance = distanceToPoint;
854 vectorToClosest = vectorToPoint;
855 }
856 }
857 }
858 }
859 }
860
861 minDistance = FLT_MAX;
862 for (int u = -1; u <= 1; u++) {
863 for (int k = -1; k <= 1; k++) {
864 for (int j = -1; j <= 1; j++) {
865 for (int i = -1; i <= 1; i++) {
866 vector4 cellOffset = vector4(i, j, k, u);
867 vector4 vectorToPoint = cellOffset +
868 hash_vector4_to_vector4(cellPosition + cellOffset) *
869 params.randomness -
870 localPosition;
871 vector4 perpendicularToEdge = vectorToPoint - vectorToClosest;
872 if (dot(perpendicularToEdge, perpendicularToEdge) > 0.0001) {
873 float distanceToEdge = dot((vectorToClosest + vectorToPoint) / 2.0,
874 normalize(perpendicularToEdge));
875 minDistance = min(minDistance, distanceToEdge);
876 }
877 }
878 }
879 }
880 }
881
882 return minDistance;
883}
884
886{
887 vector4 cellPosition = floor(coord);
888 vector4 localPosition = coord - cellPosition;
889
890 vector4 closestPoint = vector4(0.0, 0.0, 0.0, 0.0);
891 vector4 closestPointOffset = vector4(0.0, 0.0, 0.0, 0.0);
892 float minDistance = FLT_MAX;
893 for (int u = -1; u <= 1; u++) {
894 for (int k = -1; k <= 1; k++) {
895 for (int j = -1; j <= 1; j++) {
896 for (int i = -1; i <= 1; i++) {
897 vector4 cellOffset = vector4(i, j, k, u);
898 vector4 pointPosition = cellOffset + hash_vector4_to_vector4(cellPosition + cellOffset) *
899 params.randomness;
900 float distanceToPoint = distance(pointPosition, localPosition);
901 if (distanceToPoint < minDistance) {
902 minDistance = distanceToPoint;
903 closestPoint = pointPosition;
904 closestPointOffset = cellOffset;
905 }
906 }
907 }
908 }
909 }
910
911 minDistance = FLT_MAX;
912 vector4 closestPointToClosestPoint = vector4(0.0, 0.0, 0.0, 0.0);
913 for (int u = -1; u <= 1; u++) {
914 for (int k = -1; k <= 1; k++) {
915 for (int j = -1; j <= 1; j++) {
916 for (int i = -1; i <= 1; i++) {
917 if (i == 0 && j == 0 && k == 0 && u == 0) {
918 continue;
919 }
920 vector4 cellOffset = vector4(i, j, k, u) + closestPointOffset;
921 vector4 pointPosition = cellOffset + hash_vector4_to_vector4(cellPosition + cellOffset) *
922 params.randomness;
923 float distanceToPoint = distance(closestPoint, pointPosition);
924 if (distanceToPoint < minDistance) {
925 minDistance = distanceToPoint;
926 closestPointToClosestPoint = pointPosition;
927 }
928 }
929 }
930 }
931 }
932
933 return distance(closestPointToClosestPoint, closestPoint) / 2.0;
934}
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition btVector3.h:303
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
Definition btVector3.h:257
local_group_size(16, 16) .push_constant(Type b
pow(value.r - subtrahend, 2.0)") .do_static_compilation(true)
additional_info("compositor_sum_squared_difference_float_shared") .push_constant(Type output_img float dot(value.rgb, luminance_coefficients)") .define("LOAD(value)"
#define mix(a, b, c)
Definition hash.h:36
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
MINLINE float smoothstep(float edge0, float edge1, float x)
ccl_device_inline float2 floor(const float2 a)
color hash_vector3_to_color(vector3 k)
Definition node_hash.h:71
color hash_float_to_color(float k)
Definition node_hash.h:57
color hash_vector4_to_color(vector4 k)
Definition node_hash.h:78
color hash_vector2_to_color(vector2 k)
Definition node_hash.h:64
vector2 hash_vector2_to_vector2(vector2 k)
Definition node_hash.h:35
vector4 hash_vector4_to_vector4(vector4 k)
Definition node_hash.h:47
float hash_float_to_float(float k)
Definition node_hash.h:13
vector3 hash_vector3_to_vector3(vector3 k)
Definition node_hash.h:40
float distance(float a, float b)
float voronoi_distance(float a, float b)
vector2 safe_divide(vector2 a, float b)
float voronoi_n_sphere_radius(VoronoiParams params, float coord)
vector4 voronoi_position(float coord)
VoronoiOutput voronoi_f1(VoronoiParams params, float coord)
VoronoiOutput voronoi_smooth_f1(VoronoiParams params, float coord)
#define vector3
VoronoiOutput voronoi_f2(VoronoiParams params, float coord)
float voronoi_distance_to_edge(VoronoiParams params, float coord)
#define min(a, b)
Definition sort.c:32
#define FLT_MAX
Definition stdcycles.h:14
vector4 Position
float max
ccl_device_inline int abs(int x)
Definition util/math.h:120