Blender V5.0
node_voronoi.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2025 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;
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_f = floor(coord);
315 vector2 localPosition = coord - cellPosition_f;
316 int2 cellPosition = vec2_to_int2(cellPosition_f);
317
318 float minDistance = FLT_MAX;
319 int2 targetOffset = {0, 0};
320 vector2 targetPosition = vector2(0.0, 0.0);
321 for (int j = -1; j <= 1; j++) {
322 for (int i = -1; i <= 1; i++) {
323 int2 cellOffset = {i, j};
324 vector2 pointPosition = int2_to_vec2(cellOffset) +
325 hash_int2_to_vector2(cellPosition + cellOffset) * params.randomness;
326 float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
327 if (distanceToPoint < minDistance) {
328 targetOffset = cellOffset;
329 minDistance = distanceToPoint;
330 targetPosition = pointPosition;
331 }
332 }
333 }
334
335 VoronoiOutput octave;
336 octave.Distance = minDistance;
337 octave.Color = hash_int2_to_color(cellPosition + targetOffset);
338 octave.Position = voronoi_position(targetPosition + cellPosition_f);
339 return octave;
340}
341
343{
344 vector2 cellPosition_f = floor(coord);
345 vector2 localPosition = coord - cellPosition_f;
346 int2 cellPosition = vec2_to_int2(cellPosition_f);
347
348 float smoothDistance = 0.0;
349 vector3 smoothColor = vector3(0.0, 0.0, 0.0);
350 vector2 smoothPosition = vector2(0.0, 0.0);
351 float h = -1.0;
352 for (int j = -2; j <= 2; j++) {
353 for (int i = -2; i <= 2; i++) {
354 int2 cellOffset = {i, j};
355 vector2 pointPosition = int2_to_vec2(cellOffset) +
356 hash_int2_to_vector2(cellPosition + cellOffset) * params.randomness;
357 float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
358 h = h == -1.0 ?
359 1.0 :
361 0.0, 1.0, 0.5 + 0.5 * (smoothDistance - distanceToPoint) / params.smoothness);
362 float correctionFactor = params.smoothness * h * (1.0 - h);
363 smoothDistance = mix(smoothDistance, distanceToPoint, h) - correctionFactor;
364 correctionFactor /= 1.0 + 3.0 * params.smoothness;
365 color cellColor = hash_int2_to_color(cellPosition + cellOffset);
366 smoothColor = mix(smoothColor, cellColor, h) - correctionFactor;
367 smoothPosition = mix(smoothPosition, pointPosition, h) - correctionFactor;
368 }
369 }
370
371 VoronoiOutput octave;
372 octave.Distance = smoothDistance;
373 octave.Color = smoothColor;
374 octave.Position = voronoi_position(cellPosition_f + smoothPosition);
375 return octave;
376}
377
379{
380 vector2 cellPosition_f = floor(coord);
381 vector2 localPosition = coord - cellPosition_f;
382 int2 cellPosition = vec2_to_int2(cellPosition_f);
383
384 float distanceF1 = FLT_MAX;
385 float distanceF2 = FLT_MAX;
386 int2 offsetF1 = {0, 0};
387 vector2 positionF1 = vector2(0.0, 0.0);
388 int2 offsetF2 = {0, 0};
389 vector2 positionF2 = vector2(0.0, 0.0);
390 for (int j = -1; j <= 1; j++) {
391 for (int i = -1; i <= 1; i++) {
392 int2 cellOffset = {i, j};
393 vector2 pointPosition = int2_to_vec2(cellOffset) +
394 hash_int2_to_vector2(cellPosition + cellOffset) * params.randomness;
395 float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
396 if (distanceToPoint < distanceF1) {
397 distanceF2 = distanceF1;
398 distanceF1 = distanceToPoint;
399 offsetF2 = offsetF1;
400 offsetF1 = cellOffset;
401 positionF2 = positionF1;
402 positionF1 = pointPosition;
403 }
404 else if (distanceToPoint < distanceF2) {
405 distanceF2 = distanceToPoint;
406 offsetF2 = cellOffset;
407 positionF2 = pointPosition;
408 }
409 }
410 }
411
412 VoronoiOutput octave;
413 octave.Distance = distanceF2;
414 octave.Color = hash_int2_to_color(cellPosition + offsetF2);
415 octave.Position = voronoi_position(positionF2 + cellPosition_f);
416 return octave;
417}
418
420{
421 vector2 cellPosition_f = floor(coord);
422 vector2 localPosition = coord - cellPosition_f;
423 int2 cellPosition = vec2_to_int2(cellPosition_f);
424
425 vector2 vectorToClosest = vector2(0.0, 0.0);
426 float minDistance = FLT_MAX;
427 for (int j = -1; j <= 1; j++) {
428 for (int i = -1; i <= 1; i++) {
429 int2 cellOffset = {i, j};
430 vector2 vectorToPoint = int2_to_vec2(cellOffset) +
431 hash_int2_to_vector2(cellPosition + cellOffset) * params.randomness -
432 localPosition;
433 float distanceToPoint = dot(vectorToPoint, vectorToPoint);
434 if (distanceToPoint < minDistance) {
435 minDistance = distanceToPoint;
436 vectorToClosest = vectorToPoint;
437 }
438 }
439 }
440
441 minDistance = FLT_MAX;
442 for (int j = -1; j <= 1; j++) {
443 for (int i = -1; i <= 1; i++) {
444 int2 cellOffset = {i, j};
445 vector2 vectorToPoint = int2_to_vec2(cellOffset) +
446 hash_int2_to_vector2(cellPosition + cellOffset) * params.randomness -
447 localPosition;
448 vector2 perpendicularToEdge = vectorToPoint - vectorToClosest;
449 if (dot(perpendicularToEdge, perpendicularToEdge) > 0.0001) {
450 float distanceToEdge = dot((vectorToClosest + vectorToPoint) / 2.0,
451 normalize(perpendicularToEdge));
452 minDistance = min(minDistance, distanceToEdge);
453 }
454 }
455 }
456
457 return minDistance;
458}
459
461{
462 vector2 cellPosition_f = floor(coord);
463 vector2 localPosition = coord - cellPosition_f;
464 int2 cellPosition = vec2_to_int2(cellPosition_f);
465
466 vector2 closestPoint = vector2(0.0, 0.0);
467 int2 closestPointOffset = {0, 0};
468 float minDistance = FLT_MAX;
469 for (int j = -1; j <= 1; j++) {
470 for (int i = -1; i <= 1; i++) {
471 int2 cellOffset = {i, j};
472 vector2 pointPosition = int2_to_vec2(cellOffset) +
473 hash_int2_to_vector2(cellPosition + cellOffset) * params.randomness;
474 float distanceToPoint = distance(pointPosition, localPosition);
475 if (distanceToPoint < minDistance) {
476 minDistance = distanceToPoint;
477 closestPoint = pointPosition;
478 closestPointOffset = cellOffset;
479 }
480 }
481 }
482
483 minDistance = FLT_MAX;
484 vector2 closestPointToClosestPoint = vector2(0.0, 0.0);
485 for (int j = -1; j <= 1; j++) {
486 for (int i = -1; i <= 1; i++) {
487 if (i == 0 && j == 0) {
488 continue;
489 }
490 int2 cellOffset = int2(i, j) + closestPointOffset;
491 vector2 pointPosition = int2_to_vec2(cellOffset) +
492 hash_int2_to_vector2(cellPosition + cellOffset) * params.randomness;
493 float distanceToPoint = distance(closestPoint, pointPosition);
494 if (distanceToPoint < minDistance) {
495 minDistance = distanceToPoint;
496 closestPointToClosestPoint = pointPosition;
497 }
498 }
499 }
500
501 return distance(closestPointToClosestPoint, closestPoint) / 2.0;
502}
503
504/* **** 3D Voronoi **** */
505
507{
508 return vector4(coord.x, coord.y, coord.z, 0.0);
509}
510
512{
513 vector3 cellPosition_f = floor(coord);
514 vector3 localPosition = coord - cellPosition_f;
515 int3 cellPosition = vec3_to_int3(cellPosition_f);
516
517 float minDistance = FLT_MAX;
518 int3 targetOffset = {0, 0, 0};
519 vector3 targetPosition = vector3(0.0, 0.0, 0.0);
520 for (int k = -1; k <= 1; k++) {
521 for (int j = -1; j <= 1; j++) {
522 for (int i = -1; i <= 1; i++) {
523 int3 cellOffset = {i, j, k};
524 vector3 pointPosition = int3_to_vec3(cellOffset) +
525 hash_int3_to_vector3(cellPosition + cellOffset) *
526 params.randomness;
527 float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
528 if (distanceToPoint < minDistance) {
529 targetOffset = cellOffset;
530 minDistance = distanceToPoint;
531 targetPosition = pointPosition;
532 }
533 }
534 }
535 }
536
537 VoronoiOutput octave;
538 octave.Distance = minDistance;
539 octave.Color = hash_int3_to_vector3(cellPosition + targetOffset);
540 octave.Position = voronoi_position(targetPosition + cellPosition_f);
541 return octave;
542}
543
545{
546 vector3 cellPosition_f = floor(coord);
547 vector3 localPosition = coord - cellPosition_f;
548 int3 cellPosition = vec3_to_int3(cellPosition_f);
549
550 float smoothDistance = 0.0;
551 vector3 smoothColor = vector3(0.0, 0.0, 0.0);
552 vector3 smoothPosition = vector3(0.0, 0.0, 0.0);
553 float h = -1.0;
554 for (int k = -2; k <= 2; k++) {
555 for (int j = -2; j <= 2; j++) {
556 for (int i = -2; i <= 2; i++) {
557 int3 cellOffset = {i, j, k};
558 vector3 pointPosition = int3_to_vec3(cellOffset) +
559 hash_int3_to_vector3(cellPosition + cellOffset) *
560 params.randomness;
561 float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
562 h = h == -1.0 ?
563 1.0 :
565 0.0, 1.0, 0.5 + 0.5 * (smoothDistance - distanceToPoint) / params.smoothness);
566 float correctionFactor = params.smoothness * h * (1.0 - h);
567 smoothDistance = mix(smoothDistance, distanceToPoint, h) - correctionFactor;
568 correctionFactor /= 1.0 + 3.0 * params.smoothness;
569 color cellColor = hash_int3_to_vector3(cellPosition + cellOffset);
570 smoothColor = mix(smoothColor, cellColor, h) - correctionFactor;
571 smoothPosition = mix(smoothPosition, pointPosition, h) - correctionFactor;
572 }
573 }
574 }
575
576 VoronoiOutput octave;
577 octave.Distance = smoothDistance;
578 octave.Color = smoothColor;
579 octave.Position = voronoi_position(cellPosition_f + smoothPosition);
580 return octave;
581}
582
584{
585 vector3 cellPosition_f = floor(coord);
586 vector3 localPosition = coord - cellPosition_f;
587 int3 cellPosition = vec3_to_int3(cellPosition_f);
588
589 float distanceF1 = FLT_MAX;
590 float distanceF2 = FLT_MAX;
591 int3 offsetF1 = {0, 0, 0};
592 vector3 positionF1 = vector3(0.0, 0.0, 0.0);
593 int3 offsetF2 = {0, 0, 0};
594 vector3 positionF2 = vector3(0.0, 0.0, 0.0);
595 for (int k = -1; k <= 1; k++) {
596 for (int j = -1; j <= 1; j++) {
597 for (int i = -1; i <= 1; i++) {
598 int3 cellOffset = {i, j, k};
599 vector3 pointPosition = int3_to_vec3(cellOffset) +
600 hash_int3_to_vector3(cellPosition + cellOffset) *
601 params.randomness;
602 float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
603 if (distanceToPoint < distanceF1) {
604 distanceF2 = distanceF1;
605 distanceF1 = distanceToPoint;
606 offsetF2 = offsetF1;
607 offsetF1 = cellOffset;
608 positionF2 = positionF1;
609 positionF1 = pointPosition;
610 }
611 else if (distanceToPoint < distanceF2) {
612 distanceF2 = distanceToPoint;
613 offsetF2 = cellOffset;
614 positionF2 = pointPosition;
615 }
616 }
617 }
618 }
619
620 VoronoiOutput octave;
621 octave.Distance = distanceF2;
622 octave.Color = hash_int3_to_vector3(cellPosition + offsetF2);
623 octave.Position = voronoi_position(positionF2 + cellPosition_f);
624 return octave;
625}
626
628{
629 vector3 cellPosition_f = floor(coord);
630 vector3 localPosition = coord - cellPosition_f;
631 int3 cellPosition = vec3_to_int3(cellPosition_f);
632
633 vector3 vectorToClosest = vector3(0.0, 0.0, 0.0);
634 float minDistance = FLT_MAX;
635 for (int k = -1; k <= 1; k++) {
636 for (int j = -1; j <= 1; j++) {
637 for (int i = -1; i <= 1; i++) {
638 int3 cellOffset = {i, j, k};
639 vector3 vectorToPoint = int3_to_vec3(cellOffset) +
640 hash_int3_to_vector3(cellPosition + cellOffset) *
641 params.randomness -
642 localPosition;
643 float distanceToPoint = dot(vectorToPoint, vectorToPoint);
644 if (distanceToPoint < minDistance) {
645 minDistance = distanceToPoint;
646 vectorToClosest = vectorToPoint;
647 }
648 }
649 }
650 }
651
652 minDistance = FLT_MAX;
653 for (int k = -1; k <= 1; k++) {
654 for (int j = -1; j <= 1; j++) {
655 for (int i = -1; i <= 1; i++) {
656 int3 cellOffset = {i, j, k};
657 vector3 vectorToPoint = int3_to_vec3(cellOffset) +
658 hash_int3_to_vector3(cellPosition + cellOffset) *
659 params.randomness -
660 localPosition;
661 vector3 perpendicularToEdge = vectorToPoint - vectorToClosest;
662 if (dot(perpendicularToEdge, perpendicularToEdge) > 0.0001) {
663 float distanceToEdge = dot((vectorToClosest + vectorToPoint) / 2.0,
664 normalize((vector)perpendicularToEdge));
665 minDistance = min(minDistance, distanceToEdge);
666 }
667 }
668 }
669 }
670
671 return minDistance;
672}
673
675{
676 vector3 cellPosition_f = floor(coord);
677 vector3 localPosition = coord - cellPosition_f;
678 int3 cellPosition = vec3_to_int3(cellPosition_f);
679
680 vector3 closestPoint = vector3(0.0, 0.0, 0.0);
681 int3 closestPointOffset = {0, 0, 0};
682 float minDistance = FLT_MAX;
683 for (int k = -1; k <= 1; k++) {
684 for (int j = -1; j <= 1; j++) {
685 for (int i = -1; i <= 1; i++) {
686 int3 cellOffset = {i, j, k};
687 vector3 pointPosition = int3_to_vec3(cellOffset) +
688 hash_int3_to_vector3(cellPosition + cellOffset) *
689 params.randomness;
690 float distanceToPoint = distance(pointPosition, localPosition);
691 if (distanceToPoint < minDistance) {
692 minDistance = distanceToPoint;
693 closestPoint = pointPosition;
694 closestPointOffset = cellOffset;
695 }
696 }
697 }
698 }
699
700 minDistance = FLT_MAX;
701 vector3 closestPointToClosestPoint = vector3(0.0, 0.0, 0.0);
702 for (int k = -1; k <= 1; k++) {
703 for (int j = -1; j <= 1; j++) {
704 for (int i = -1; i <= 1; i++) {
705 if (i == 0 && j == 0 && k == 0) {
706 continue;
707 }
708 int3 cellOffset = int3(i, j, k) + closestPointOffset;
709 vector3 pointPosition = int3_to_vec3(cellOffset) +
710 hash_int3_to_vector3(cellPosition + cellOffset) *
711 params.randomness;
712 float distanceToPoint = distance(closestPoint, pointPosition);
713 if (distanceToPoint < minDistance) {
714 minDistance = distanceToPoint;
715 closestPointToClosestPoint = pointPosition;
716 }
717 }
718 }
719 }
720
721 return distance(closestPointToClosestPoint, closestPoint) / 2.0;
722}
723
724/* **** 4D Voronoi **** */
725
726vector4 voronoi_position(vector4 coord)
727{
728 return coord;
729}
730
732{
733 vector4 cellPosition_f = floor(coord);
734 vector4 localPosition = coord - cellPosition_f;
735 int4 cellPosition = vec4_to_int4(cellPosition_f);
736
737 float minDistance = FLT_MAX;
738 int4 targetOffset = {0, 0, 0, 0};
739 vector4 targetPosition = vector4(0.0, 0.0, 0.0, 0.0);
740 for (int u = -1; u <= 1; u++) {
741 for (int k = -1; k <= 1; k++) {
742 for (int j = -1; j <= 1; j++) {
743 for (int i = -1; i <= 1; i++) {
744 int4 cellOffset = {i, j, k, u};
745 vector4 pointPosition = int4_to_vec4(cellOffset) +
746 hash_int4_to_vector4(cellPosition + cellOffset) *
747 params.randomness;
748 float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
749 if (distanceToPoint < minDistance) {
750 targetOffset = cellOffset;
751 minDistance = distanceToPoint;
752 targetPosition = pointPosition;
753 }
754 }
755 }
756 }
757 }
758
759 VoronoiOutput octave;
760 octave.Distance = minDistance;
761 octave.Color = hash_int4_to_color(cellPosition + targetOffset);
762 octave.Position = voronoi_position(targetPosition + cellPosition_f);
763 return octave;
764}
765
767{
768 vector4 cellPosition_f = floor(coord);
769 vector4 localPosition = coord - cellPosition_f;
770 int4 cellPosition = vec4_to_int4(cellPosition_f);
771
772 float smoothDistance = 0.0;
773 vector3 smoothColor = vector3(0.0, 0.0, 0.0);
774 vector4 smoothPosition = vector4(0.0, 0.0, 0.0, 0.0);
775 float h = -1.0;
776 for (int u = -2; u <= 2; u++) {
777 for (int k = -2; k <= 2; k++) {
778 for (int j = -2; j <= 2; j++) {
779 for (int i = -2; i <= 2; i++) {
780 int4 cellOffset = {i, j, k, u};
781 vector4 pointPosition = int4_to_vec4(cellOffset) +
782 hash_int4_to_vector4(cellPosition + cellOffset) *
783 params.randomness;
784 float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
785 h = h == -1.0 ?
786 1.0 :
787 smoothstep(0.0,
788 1.0,
789 0.5 + 0.5 * (smoothDistance - distanceToPoint) / params.smoothness);
790 float correctionFactor = params.smoothness * h * (1.0 - h);
791 smoothDistance = mix(smoothDistance, distanceToPoint, h) - correctionFactor;
792 correctionFactor /= 1.0 + 3.0 * params.smoothness;
793 color cellColor = hash_int4_to_color(cellPosition + cellOffset);
794 smoothColor = mix(smoothColor, cellColor, h) - correctionFactor;
795 smoothPosition = mix(smoothPosition, pointPosition, h) - correctionFactor;
796 }
797 }
798 }
799 }
800
801 VoronoiOutput octave;
802 octave.Distance = smoothDistance;
803 octave.Color = smoothColor;
804 octave.Position = voronoi_position(cellPosition_f + smoothPosition);
805 return octave;
806}
807
809{
810 vector4 cellPosition_f = floor(coord);
811 vector4 localPosition = coord - cellPosition_f;
812 int4 cellPosition = vec4_to_int4(cellPosition_f);
813
814 float distanceF1 = FLT_MAX;
815 float distanceF2 = FLT_MAX;
816 int4 offsetF1 = {0, 0, 0, 0};
817 vector4 positionF1 = vector4(0.0, 0.0, 0.0, 0.0);
818 int4 offsetF2 = {0, 0, 0, 0};
819 vector4 positionF2 = vector4(0.0, 0.0, 0.0, 0.0);
820 for (int u = -1; u <= 1; u++) {
821 for (int k = -1; k <= 1; k++) {
822 for (int j = -1; j <= 1; j++) {
823 for (int i = -1; i <= 1; i++) {
824 int4 cellOffset = {i, j, k, u};
825 vector4 pointPosition = int4_to_vec4(cellOffset) +
826 hash_int4_to_vector4(cellPosition + cellOffset) *
827 params.randomness;
828 float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
829 if (distanceToPoint < distanceF1) {
830 distanceF2 = distanceF1;
831 distanceF1 = distanceToPoint;
832 offsetF2 = offsetF1;
833 offsetF1 = cellOffset;
834 positionF2 = positionF1;
835 positionF1 = pointPosition;
836 }
837 else if (distanceToPoint < distanceF2) {
838 distanceF2 = distanceToPoint;
839 offsetF2 = cellOffset;
840 positionF2 = pointPosition;
841 }
842 }
843 }
844 }
845 }
846
847 VoronoiOutput octave;
848 octave.Distance = distanceF2;
849 octave.Color = hash_int4_to_color(cellPosition + offsetF2);
850 octave.Position = voronoi_position(positionF2 + cellPosition_f);
851 return octave;
852}
853
855{
856 vector4 cellPosition_f = floor(coord);
857 vector4 localPosition = coord - cellPosition_f;
858 int4 cellPosition = vec4_to_int4(cellPosition_f);
859
860 vector4 vectorToClosest = vector4(0.0, 0.0, 0.0, 0.0);
861 float 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 int4 cellOffset = {i, j, k, u};
867 vector4 vectorToPoint = int4_to_vec4(cellOffset) +
868 hash_int4_to_vector4(cellPosition + cellOffset) *
869 params.randomness -
870 localPosition;
871 float distanceToPoint = dot(vectorToPoint, vectorToPoint);
872 if (distanceToPoint < minDistance) {
873 minDistance = distanceToPoint;
874 vectorToClosest = vectorToPoint;
875 }
876 }
877 }
878 }
879 }
880
881 minDistance = FLT_MAX;
882 for (int u = -1; u <= 1; u++) {
883 for (int k = -1; k <= 1; k++) {
884 for (int j = -1; j <= 1; j++) {
885 for (int i = -1; i <= 1; i++) {
886 int4 cellOffset = {i, j, k, u};
887 vector4 vectorToPoint = int4_to_vec4(cellOffset) +
888 hash_int4_to_vector4(cellPosition + cellOffset) *
889 params.randomness -
890 localPosition;
891 vector4 perpendicularToEdge = vectorToPoint - vectorToClosest;
892 if (dot(perpendicularToEdge, perpendicularToEdge) > 0.0001) {
893 float distanceToEdge = dot((vectorToClosest + vectorToPoint) / 2.0,
894 normalize(perpendicularToEdge));
895 minDistance = min(minDistance, distanceToEdge);
896 }
897 }
898 }
899 }
900 }
901
902 return minDistance;
903}
904
906{
907 vector4 cellPosition_f = floor(coord);
908 vector4 localPosition = coord - cellPosition_f;
909 int4 cellPosition = vec4_to_int4(cellPosition_f);
910
911 vector4 closestPoint = vector4(0.0, 0.0, 0.0, 0.0);
912 int4 closestPointOffset = {0, 0, 0, 0};
913 float minDistance = FLT_MAX;
914 for (int u = -1; u <= 1; u++) {
915 for (int k = -1; k <= 1; k++) {
916 for (int j = -1; j <= 1; j++) {
917 for (int i = -1; i <= 1; i++) {
918 int4 cellOffset = {i, j, k, u};
919 vector4 pointPosition = int4_to_vec4(cellOffset) +
920 hash_int4_to_vector4(cellPosition + cellOffset) *
921 params.randomness;
922 float distanceToPoint = distance(pointPosition, localPosition);
923 if (distanceToPoint < minDistance) {
924 minDistance = distanceToPoint;
925 closestPoint = pointPosition;
926 closestPointOffset = cellOffset;
927 }
928 }
929 }
930 }
931 }
932
933 minDistance = FLT_MAX;
934 vector4 closestPointToClosestPoint = vector4(0.0, 0.0, 0.0, 0.0);
935 for (int u = -1; u <= 1; u++) {
936 for (int k = -1; k <= 1; k++) {
937 for (int j = -1; j <= 1; j++) {
938 for (int i = -1; i <= 1; i++) {
939 if (i == 0 && j == 0 && k == 0 && u == 0) {
940 continue;
941 }
942 int4 cellOffset = int4(i, j, k, u) + closestPointOffset;
943 vector4 pointPosition = int4_to_vec4(cellOffset) +
944 hash_int4_to_vector4(cellPosition + cellOffset) *
945 params.randomness;
946 float distanceToPoint = distance(closestPoint, pointPosition);
947 if (distanceToPoint < minDistance) {
948 minDistance = distanceToPoint;
949 closestPointToClosestPoint = pointPosition;
950 }
951 }
952 }
953 }
954 }
955
956 return distance(closestPointToClosestPoint, closestPoint) / 2.0;
957}
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
Definition btVector3.h:257
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
#define pow
VecBase< float, D > normalize(VecOp< float, D >) RET
#define abs
#define floor
VecBase< int, 2 > int2
VecBase< int, 3 > int3
VecBase< int, 4 > int4
vector2 int2_to_vec2(int2 k)
int4 vec4_to_int4(vector4 k)
point int3_to_vec3(int3 k)
int2 vec2_to_int2(vector2 k)
vector4 int4_to_vec4(int4 k)
int3 vec3_to_int3(point k)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
MINLINE float smoothstep(float edge0, float edge1, float x)
#define vector3
color hash_int4_to_color(int4 k)
Definition node_hash.h:62
color hash_float_to_color(float k)
Definition node_hash.h:114
vector2 hash_int2_to_vector2(int2 k)
Definition node_hash.h:15
vector3 hash_int3_to_vector3(int3 k)
Definition node_hash.h:27
color hash_int2_to_color(int2 k)
Definition node_hash.h:57
vector4 hash_int4_to_vector4(int4 k)
Definition node_hash.h:41
float hash_float_to_float(float k)
Definition node_hash.h:70
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 mix
#define min(a, b)
Definition sort.cc:36
#define FLT_MAX
Definition stdcycles.h:14
vector4 Position
float3 color
Definition voronoi.h:45
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251