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;
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}
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a color
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)
#define vector3
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
float3 color
Definition voronoi.h:42
float max
ccl_device_inline int abs(int x)
Definition util/math.h:120