Blender V4.3
node_shader_tex_voronoi.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2005 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "node_shader_util.hh"
6#include "node_util.hh"
7
8#include "BKE_texture.h"
9
10#include "BLI_noise.hh"
11
12#include "NOD_multi_function.hh"
13
14#include "RNA_access.hh"
15
16#include "UI_interface.hh"
17#include "UI_resources.hh"
18
20
22
24{
25 b.is_function_node();
26 b.add_input<decl::Vector>("Vector").hide_value().implicit_field(implicit_field_inputs::position);
27 b.add_input<decl::Float>("W").min(-1000.0f).max(1000.0f).make_available([](bNode &node) {
28 /* Default to 1 instead of 4, because it is much faster. */
29 node_storage(node).dimensions = 1;
30 });
31 b.add_input<decl::Float>("Scale").min(-1000.0f).max(1000.0f).default_value(5.0f);
32 b.add_input<decl::Float>("Detail")
33 .min(0.0f)
34 .max(15.0f)
35 .default_value(0.0f)
36 .make_available([](bNode &node) { node_storage(node).feature = SHD_VORONOI_F1; })
37 .description("The number of Voronoi layers to sum");
38 b.add_input<decl::Float>("Roughness")
39 .min(0.0f)
40 .max(1.0f)
41 .default_value(0.5f)
42 .subtype(PROP_FACTOR)
43 .make_available([](bNode &node) { node_storage(node).feature = SHD_VORONOI_F1; })
44 .description("The influence of a Voronoi layer relative to that of the previous layer");
45 b.add_input<decl::Float>("Lacunarity")
46 .min(0.0f)
47 .max(1000.0f)
48 .default_value(2.0f)
49 .make_available([](bNode &node) { node_storage(node).feature = SHD_VORONOI_F1; })
50 .description("The scale of a Voronoi layer relative to that of the previous layer");
51 b.add_input<decl::Float>("Smoothness")
52 .min(0.0f)
53 .max(1.0f)
54 .default_value(1.0f)
55 .subtype(PROP_FACTOR)
56 .make_available([](bNode &node) { node_storage(node).feature = SHD_VORONOI_SMOOTH_F1; });
57 b.add_input<decl::Float>("Exponent")
58 .min(0.0f)
59 .max(32.0f)
60 .default_value(0.5f)
61 .make_available([](bNode &node) { node_storage(node).distance = SHD_VORONOI_MINKOWSKI; });
62 b.add_input<decl::Float>("Randomness")
63 .min(0.0f)
64 .max(1.0f)
65 .default_value(1.0f)
66 .subtype(PROP_FACTOR);
67 b.add_output<decl::Float>("Distance").no_muted_links();
68 b.add_output<decl::Color>("Color").no_muted_links();
69 b.add_output<decl::Vector>("Position").no_muted_links();
70 b.add_output<decl::Float>("W").no_muted_links().make_available([](bNode &node) {
71 /* Default to 1 instead of 4, because it is much faster. */
72 node_storage(node).dimensions = 1;
73 });
74 b.add_output<decl::Float>("Radius").no_muted_links().make_available(
75 [](bNode &node) { node_storage(node).feature = SHD_VORONOI_N_SPHERE_RADIUS; });
76}
77
79{
80 uiItemR(layout, ptr, "voronoi_dimensions", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
81 uiItemR(layout, ptr, "feature", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
82 int feature = RNA_enum_get(ptr, "feature");
84 RNA_enum_get(ptr, "voronoi_dimensions") != 1)
85 {
86 uiItemR(layout, ptr, "distance", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
87 }
88 if (!ELEM(feature, SHD_VORONOI_N_SPHERE_RADIUS)) {
89 uiItemR(layout, ptr, "normalize", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
90 }
91}
92
93static void node_shader_init_tex_voronoi(bNodeTree * /*ntree*/, bNode *node)
94{
95 NodeTexVoronoi *tex = MEM_cnew<NodeTexVoronoi>(__func__);
97 BKE_texture_colormapping_default(&tex->base.color_mapping);
98 tex->dimensions = 3;
99 tex->distance = SHD_VORONOI_EUCLIDEAN;
100 tex->feature = SHD_VORONOI_F1;
101 tex->normalize = false;
102
103 node->storage = tex;
104}
105
106static const char *gpu_shader_get_name(const int feature, const int dimensions)
107{
108 BLI_assert(feature >= 0 && feature < 5);
109 BLI_assert(dimensions > 0 && dimensions < 5);
110
111 switch (feature) {
112 case SHD_VORONOI_F1:
113 return std::array{
114 "node_tex_voronoi_f1_1d",
115 "node_tex_voronoi_f1_2d",
116 "node_tex_voronoi_f1_3d",
117 "node_tex_voronoi_f1_4d",
118 }[dimensions - 1];
119 case SHD_VORONOI_F2:
120 return std::array{
121 "node_tex_voronoi_f2_1d",
122 "node_tex_voronoi_f2_2d",
123 "node_tex_voronoi_f2_3d",
124 "node_tex_voronoi_f2_4d",
125 }[dimensions - 1];
127 return std::array{
128 "node_tex_voronoi_smooth_f1_1d",
129 "node_tex_voronoi_smooth_f1_2d",
130 "node_tex_voronoi_smooth_f1_3d",
131 "node_tex_voronoi_smooth_f1_4d",
132 }[dimensions - 1];
134 return std::array{
135 "node_tex_voronoi_distance_to_edge_1d",
136 "node_tex_voronoi_distance_to_edge_2d",
137 "node_tex_voronoi_distance_to_edge_3d",
138 "node_tex_voronoi_distance_to_edge_4d",
139 }[dimensions - 1];
141 return std::array{
142 "node_tex_voronoi_n_sphere_radius_1d",
143 "node_tex_voronoi_n_sphere_radius_2d",
144 "node_tex_voronoi_n_sphere_radius_3d",
145 "node_tex_voronoi_n_sphere_radius_4d",
146 }[dimensions - 1];
147 }
148 return nullptr;
149}
150
152 bNode *node,
153 bNodeExecData * /*execdata*/,
154 GPUNodeStack *in,
155 GPUNodeStack *out)
156{
157 node_shader_gpu_default_tex_coord(mat, node, &in[0].link);
158 node_shader_gpu_tex_mapping(mat, node, in, out);
159
160 NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
161 float metric = tex->distance;
162 float normalize = tex->normalize;
163
164 const char *name = gpu_shader_get_name(tex->feature, tex->dimensions);
165
166 return GPU_stack_link(mat, node, name, in, out, GPU_constant(&metric), GPU_constant(&normalize));
167}
168
170{
171 bNodeSocket *inVectorSock = bke::node_find_socket(node, SOCK_IN, "Vector");
172 bNodeSocket *inWSock = bke::node_find_socket(node, SOCK_IN, "W");
173 bNodeSocket *inDetailSock = bke::node_find_socket(node, SOCK_IN, "Detail");
174 bNodeSocket *inRoughnessSock = bke::node_find_socket(node, SOCK_IN, "Roughness");
175 bNodeSocket *inLacunaritySock = bke::node_find_socket(node, SOCK_IN, "Lacunarity");
176 bNodeSocket *inSmoothnessSock = bke::node_find_socket(node, SOCK_IN, "Smoothness");
177 bNodeSocket *inExponentSock = bke::node_find_socket(node, SOCK_IN, "Exponent");
178
179 bNodeSocket *outDistanceSock = bke::node_find_socket(node, SOCK_OUT, "Distance");
180 bNodeSocket *outColorSock = bke::node_find_socket(node, SOCK_OUT, "Color");
181 bNodeSocket *outPositionSock = bke::node_find_socket(node, SOCK_OUT, "Position");
182 bNodeSocket *outWSock = bke::node_find_socket(node, SOCK_OUT, "W");
183 bNodeSocket *outRadiusSock = bke::node_find_socket(node, SOCK_OUT, "Radius");
184
185 const NodeTexVoronoi &storage = node_storage(*node);
186
188 ntree, inWSock, storage.dimensions == 1 || storage.dimensions == 4);
189 bke::node_set_socket_availability(ntree, inVectorSock, storage.dimensions != 1);
191 ntree,
192 inExponentSock,
193 storage.distance == SHD_VORONOI_MINKOWSKI && storage.dimensions != 1 &&
196 ntree, inDetailSock, storage.feature != SHD_VORONOI_N_SPHERE_RADIUS);
198 ntree, inRoughnessSock, storage.feature != SHD_VORONOI_N_SPHERE_RADIUS);
200 ntree, inLacunaritySock, storage.feature != SHD_VORONOI_N_SPHERE_RADIUS);
202 ntree, inSmoothnessSock, storage.feature == SHD_VORONOI_SMOOTH_F1);
203
205 ntree, outDistanceSock, storage.feature != SHD_VORONOI_N_SPHERE_RADIUS);
207 outColorSock,
211 outPositionSock,
214 storage.dimensions != 1);
216 outWSock,
219 ELEM(storage.dimensions, 1, 4));
221 ntree, outRadiusSock, storage.feature == SHD_VORONOI_N_SPHERE_RADIUS);
222}
223
224static mf::MultiFunction::ExecutionHints voronoi_execution_hints{50, false};
225
227 private:
228 int dimensions_;
229 int feature_;
230 int metric_;
231 bool normalize_;
232
233 public:
234 VoronoiMetricFunction(int dimensions, int feature, int metric, bool normalize)
235 : dimensions_(dimensions), feature_(feature), metric_(metric), normalize_(normalize)
236 {
237 BLI_assert(dimensions >= 1 && dimensions <= 4);
238 BLI_assert(feature >= 0 && feature <= 4);
239 if (ELEM(metric_, SHD_VORONOI_MINKOWSKI)) {
240 static std::array<mf::Signature, 12> signatures{
245
250
255 };
256 this->set_signature(&signatures[dimensions + feature * 4 - 1]);
257 }
258 else {
259 static std::array<mf::Signature, 12> signatures{
264
269
274 };
275 this->set_signature(&signatures[dimensions + feature * 4 - 1]);
276 }
277 }
278
279 static mf::Signature create_signature(int dimensions, int feature, int metric)
280 {
282 mf::SignatureBuilder builder{"voronoi_metric", signature};
283
284 if (ELEM(dimensions, 2, 3, 4)) {
285 builder.single_input<float3>("Vector");
286 }
287 if (ELEM(dimensions, 1, 4)) {
288 builder.single_input<float>("W");
289 }
290 builder.single_input<float>("Scale");
291 builder.single_input<float>("Detail");
292 builder.single_input<float>("Roughness");
293 builder.single_input<float>("Lacunarity");
294 if (feature == SHD_VORONOI_SMOOTH_F1) {
295 builder.single_input<float>("Smoothness");
296 }
297 if ((dimensions != 1) && (metric == SHD_VORONOI_MINKOWSKI)) {
298 builder.single_input<float>("Exponent");
299 }
300 builder.single_input<float>("Randomness");
301
302 builder.single_output<float>("Distance", mf::ParamFlag::SupportsUnusedOutput);
303 builder.single_output<ColorGeometry4f>("Color", mf::ParamFlag::SupportsUnusedOutput);
304 if (dimensions != 1) {
305 builder.single_output<float3>("Position", mf::ParamFlag::SupportsUnusedOutput);
306 }
307 if (ELEM(dimensions, 1, 4)) {
308 builder.single_output<float>("W", mf::ParamFlag::SupportsUnusedOutput);
309 }
310
311 return signature;
312 }
313
314 void call(const IndexMask &mask, mf::Params mf_params, mf::Context /*context*/) const override
315 {
316 auto get_vector = [&](int param_index) -> VArray<float3> {
317 return mf_params.readonly_single_input<float3>(param_index, "Vector");
318 };
319 auto get_w = [&](int param_index) -> VArray<float> {
320 return mf_params.readonly_single_input<float>(param_index, "W");
321 };
322 auto get_scale = [&](int param_index) -> VArray<float> {
323 return mf_params.readonly_single_input<float>(param_index, "Scale");
324 };
325 auto get_detail = [&](int param_index) -> VArray<float> {
326 return mf_params.readonly_single_input<float>(param_index, "Detail");
327 };
328 auto get_roughness = [&](int param_index) -> VArray<float> {
329 return mf_params.readonly_single_input<float>(param_index, "Roughness");
330 };
331 auto get_lacunarity = [&](int param_index) -> VArray<float> {
332 return mf_params.readonly_single_input<float>(param_index, "Lacunarity");
333 };
334 auto get_smoothness = [&](int param_index) -> VArray<float> {
335 return mf_params.readonly_single_input<float>(param_index, "Smoothness");
336 };
337 auto get_exponent = [&](int param_index) -> VArray<float> {
338 return mf_params.readonly_single_input<float>(param_index, "Exponent");
339 };
340 auto get_randomness = [&](int param_index) -> VArray<float> {
341 return mf_params.readonly_single_input<float>(param_index, "Randomness");
342 };
343 auto get_r_distance = [&](int param_index) -> MutableSpan<float> {
344 return mf_params.uninitialized_single_output_if_required<float>(param_index, "Distance");
345 };
346 auto get_r_color = [&](int param_index) -> MutableSpan<ColorGeometry4f> {
347 return mf_params.uninitialized_single_output_if_required<ColorGeometry4f>(param_index,
348 "Color");
349 };
350 auto get_r_position = [&](int param_index) -> MutableSpan<float3> {
351 return mf_params.uninitialized_single_output_if_required<float3>(param_index, "Position");
352 };
353 auto get_r_w = [&](int param_index) -> MutableSpan<float> {
354 return mf_params.uninitialized_single_output_if_required<float>(param_index, "W");
355 };
356
357 int param = 0;
358
359 const VArray<float3> &vector = !ELEM(dimensions_, 1) ? get_vector(param++) : VArray<float3>{};
360 const VArray<float> &w = ELEM(dimensions_, 1, 4) ? get_w(param++) : VArray<float>{};
361 const VArray<float> &scale = get_scale(param++);
362 const VArray<float> &detail = get_detail(param++);
363 const VArray<float> &roughness = get_roughness(param++);
364 const VArray<float> &lacunarity = get_lacunarity(param++);
365 const VArray<float> &smoothness = ELEM(feature_, SHD_VORONOI_SMOOTH_F1) ?
366 get_smoothness(param++) :
368 const VArray<float> &exponent = ELEM(metric_, SHD_VORONOI_MINKOWSKI) && !ELEM(dimensions_, 1) ?
369 get_exponent(param++) :
371 const VArray<float> &randomness = get_randomness(param++);
372 MutableSpan<float> r_distance = get_r_distance(param++);
373 MutableSpan<ColorGeometry4f> r_color = get_r_color(param++);
374 MutableSpan<float3> r_position = !ELEM(dimensions_, 1) ? get_r_position(param++) :
376 MutableSpan<float> r_w = ELEM(dimensions_, 1, 4) ? get_r_w(param++) : MutableSpan<float>{};
377 const bool calc_distance = !r_distance.is_empty();
378 const bool calc_color = !r_color.is_empty();
379 const bool calc_position = !r_position.is_empty();
380 const bool calc_w = !r_w.is_empty();
381
383 params.feature = feature_;
384 params.metric = metric_;
385 params.normalize = normalize_;
386
388 switch (dimensions_) {
389 case 1: {
390 mask.foreach_index([&](const int64_t i) {
391 params.scale = scale[i];
392 params.detail = detail[i];
393 params.roughness = roughness[i];
394 params.lacunarity = lacunarity[i];
395 params.smoothness = ELEM(feature_, SHD_VORONOI_SMOOTH_F1) ?
396 std::min(std::max(smoothness[i] / 2.0f, 0.0f), 0.5f) :
397 0.0f;
398 params.exponent = 0.0f;
399 params.randomness = std::min(std::max(randomness[i], 0.0f), 1.0f);
400 params.max_distance = (0.5f + 0.5f * params.randomness) *
401 ((params.feature == SHD_VORONOI_F2) ? 2.0f : 1.0f);
402
403 output = noise::fractal_voronoi_x_fx<float>(params, w[i] * params.scale, calc_color);
404 if (calc_distance) {
405 r_distance[i] = output.distance;
406 }
407 if (calc_color) {
408 r_color[i] = ColorGeometry4f(output.color.x, output.color.y, output.color.z, 1.0f);
409 }
410 if (calc_w) {
411 r_w[i] = output.position.w;
412 }
413 });
414 break;
415 }
416 case 2: {
417 mask.foreach_index([&](const int64_t i) {
418 params.scale = scale[i];
419 params.detail = detail[i];
420 params.roughness = roughness[i];
421 params.lacunarity = lacunarity[i];
422 params.smoothness = ELEM(feature_, SHD_VORONOI_SMOOTH_F1) ?
423 std::min(std::max(smoothness[i] / 2.0f, 0.0f), 0.5f) :
424 0.0f;
425 params.exponent = ELEM(metric_, SHD_VORONOI_MINKOWSKI) && !ELEM(dimensions_, 1) ?
426 exponent[i] :
427 0.0f;
428 params.randomness = std::min(std::max(randomness[i], 0.0f), 1.0f);
429 params.max_distance = noise::voronoi_distance(float2{0.0f, 0.0f},
430 float2(0.5f + 0.5f * params.randomness,
431 0.5f + 0.5f * params.randomness),
432 params) *
433 ((params.feature == SHD_VORONOI_F2) ? 2.0f : 1.0f);
434
436 params, float2{vector[i].x, vector[i].y} * params.scale, calc_color);
437 if (calc_distance) {
438 r_distance[i] = output.distance;
439 }
440 if (calc_color) {
441 r_color[i] = ColorGeometry4f(output.color.x, output.color.y, output.color.z, 1.0f);
442 }
443 if (calc_position) {
444 r_position[i] = float3{output.position.x, output.position.y, 0.0f};
445 }
446 });
447 break;
448 }
449 case 3: {
450 mask.foreach_index([&](const int64_t i) {
451 params.scale = scale[i];
452 params.detail = detail[i];
453 params.roughness = roughness[i];
454 params.lacunarity = lacunarity[i];
455 params.smoothness = ELEM(feature_, SHD_VORONOI_SMOOTH_F1) ?
456 std::min(std::max(smoothness[i] / 2.0f, 0.0f), 0.5f) :
457 0.0f;
458 params.exponent = ELEM(metric_, SHD_VORONOI_MINKOWSKI) && !ELEM(dimensions_, 1) ?
459 exponent[i] :
460 0.0f;
461 params.randomness = std::min(std::max(randomness[i], 0.0f), 1.0f);
462 params.max_distance = noise::voronoi_distance(float3{0.0f, 0.0f, 0.0f},
463 float3(0.5f + 0.5f * params.randomness,
464 0.5f + 0.5f * params.randomness,
465 0.5f + 0.5f * params.randomness),
466 params) *
467 ((params.feature == SHD_VORONOI_F2) ? 2.0f : 1.0f);
468
470 params, vector[i] * params.scale, calc_color);
471 if (calc_distance) {
472 r_distance[i] = output.distance;
473 }
474 if (calc_color) {
475 r_color[i] = ColorGeometry4f(output.color.x, output.color.y, output.color.z, 1.0f);
476 }
477 if (calc_position) {
478 r_position[i] = float3{output.position.x, output.position.y, output.position.z};
479 }
480 });
481 break;
482 }
483 case 4: {
484 mask.foreach_index([&](const int64_t i) {
485 params.scale = scale[i];
486 params.detail = detail[i];
487 params.roughness = roughness[i];
488 params.lacunarity = lacunarity[i];
489 params.smoothness = ELEM(feature_, SHD_VORONOI_SMOOTH_F1) ?
490 std::min(std::max(smoothness[i] / 2.0f, 0.0f), 0.5f) :
491 0.0f;
492 params.exponent = ELEM(metric_, SHD_VORONOI_MINKOWSKI) && !ELEM(dimensions_, 1) ?
493 exponent[i] :
494 0.0f;
495 params.randomness = std::min(std::max(randomness[i], 0.0f), 1.0f);
496 params.max_distance = noise::voronoi_distance(float4{0.0f, 0.0f, 0.0f, 0.0f},
497 float4(0.5f + 0.5f * params.randomness,
498 0.5f + 0.5f * params.randomness,
499 0.5f + 0.5f * params.randomness,
500 0.5f + 0.5f * params.randomness),
501 params) *
502 ((params.feature == SHD_VORONOI_F2) ? 2.0f : 1.0f);
503
505 params,
506 float4{vector[i].x, vector[i].y, vector[i].z, w[i]} * params.scale,
507 calc_color);
508 if (calc_distance) {
509 r_distance[i] = output.distance;
510 }
511 if (calc_color) {
512 r_color[i] = ColorGeometry4f(output.color.x, output.color.y, output.color.z, 1.0f);
513 }
514 if (calc_position) {
515 r_position[i] = float3{output.position.x, output.position.y, output.position.z};
516 }
517 if (calc_w) {
518 r_w[i] = output.position.w;
519 }
520 });
521 break;
522 }
523 }
524 }
525
527 {
529 }
530};
531
533 private:
534 int dimensions_;
535 bool normalize_;
536
537 public:
539 : dimensions_(dimensions), normalize_(normalize)
540 {
541 BLI_assert(dimensions >= 1 && dimensions <= 4);
542 static std::array<mf::Signature, 4> signatures{
547 };
548 this->set_signature(&signatures[dimensions - 1]);
549 }
550
551 static mf::Signature create_signature(int dimensions)
552 {
554 mf::SignatureBuilder builder{"voronoi_dist_to_edge", signature};
555
556 if (ELEM(dimensions, 2, 3, 4)) {
557 builder.single_input<float3>("Vector");
558 }
559 if (ELEM(dimensions, 1, 4)) {
560 builder.single_input<float>("W");
561 }
562 builder.single_input<float>("Scale");
563 builder.single_input<float>("Detail");
564 builder.single_input<float>("Roughness");
565 builder.single_input<float>("Lacunarity");
566 builder.single_input<float>("Randomness");
567
568 builder.single_output<float>("Distance");
569
570 return signature;
571 }
572
573 void call(const IndexMask &mask, mf::Params mf_params, mf::Context /*context*/) const override
574 {
575 auto get_vector = [&](int param_index) -> VArray<float3> {
576 return mf_params.readonly_single_input<float3>(param_index, "Vector");
577 };
578 auto get_w = [&](int param_index) -> VArray<float> {
579 return mf_params.readonly_single_input<float>(param_index, "W");
580 };
581 auto get_scale = [&](int param_index) -> VArray<float> {
582 return mf_params.readonly_single_input<float>(param_index, "Scale");
583 };
584 auto get_detail = [&](int param_index) -> VArray<float> {
585 return mf_params.readonly_single_input<float>(param_index, "Detail");
586 };
587 auto get_roughness = [&](int param_index) -> VArray<float> {
588 return mf_params.readonly_single_input<float>(param_index, "Roughness");
589 };
590 auto get_lacunarity = [&](int param_index) -> VArray<float> {
591 return mf_params.readonly_single_input<float>(param_index, "Lacunarity");
592 };
593 auto get_randomness = [&](int param_index) -> VArray<float> {
594 return mf_params.readonly_single_input<float>(param_index, "Randomness");
595 };
596 auto get_r_distance = [&](int param_index) -> MutableSpan<float> {
597 return mf_params.uninitialized_single_output<float>(param_index, "Distance");
598 };
599
600 int param = 0;
601
602 const VArray<float3> &vector = !ELEM(dimensions_, 1) ? get_vector(param++) : VArray<float3>{};
603 const VArray<float> &w = ELEM(dimensions_, 1, 4) ? get_w(param++) : VArray<float>{};
604 const VArray<float> &scale = get_scale(param++);
605 const VArray<float> &detail = get_detail(param++);
606 const VArray<float> &roughness = get_roughness(param++);
607 const VArray<float> &lacunarity = get_lacunarity(param++);
608 const VArray<float> &randomness = get_randomness(param++);
609 MutableSpan<float> r_distance = get_r_distance(param++);
610
612 params.normalize = normalize_;
613
614 switch (dimensions_) {
615 case 1: {
616 mask.foreach_index([&](const int64_t i) {
617 params.scale = scale[i];
618 params.detail = detail[i];
619 params.roughness = roughness[i];
620 params.lacunarity = lacunarity[i];
621 params.randomness = std::min(std::max(randomness[i], 0.0f), 1.0f);
622 params.max_distance = 0.5f + 0.5f * params.randomness;
623
625 w[i] * params.scale);
626 });
627 break;
628 }
629 case 2: {
630 mask.foreach_index([&](const int64_t i) {
631 params.scale = scale[i];
632 params.detail = detail[i];
633 params.roughness = roughness[i];
634 params.lacunarity = lacunarity[i];
635 params.randomness = std::min(std::max(randomness[i], 0.0f), 1.0f);
636 params.max_distance = 0.5f + 0.5f * params.randomness;
637
639 params, float2{vector[i].x, vector[i].y} * params.scale);
640 });
641 break;
642 }
643 case 3: {
644 mask.foreach_index([&](const int64_t i) {
645 params.scale = scale[i];
646 params.detail = detail[i];
647 params.roughness = roughness[i];
648 params.lacunarity = lacunarity[i];
649 params.randomness = std::min(std::max(randomness[i], 0.0f), 1.0f);
650 params.max_distance = 0.5f + 0.5f * params.randomness;
651
653 params, vector[i] * params.scale);
654 });
655 break;
656 }
657 case 4: {
658 mask.foreach_index([&](const int64_t i) {
659 params.scale = scale[i];
660 params.detail = detail[i];
661 params.roughness = roughness[i];
662 params.lacunarity = lacunarity[i];
663 params.randomness = std::min(std::max(randomness[i], 0.0f), 1.0f);
664 params.max_distance = 0.5f + 0.5f * params.randomness;
665
667 params, float4{vector[i].x, vector[i].y, vector[i].z, w[i]} * params.scale);
668 });
669 break;
670 }
671 }
672 }
673
675 {
677 }
678};
679
681 private:
682 int dimensions_;
683
684 public:
685 VoronoiNSphereFunction(int dimensions) : dimensions_(dimensions)
686 {
687 BLI_assert(dimensions >= 1 && dimensions <= 4);
688 static std::array<mf::Signature, 4> signatures{
693 };
694 this->set_signature(&signatures[dimensions - 1]);
695 }
696
697 static mf::Signature create_signature(int dimensions)
698 {
700 mf::SignatureBuilder builder{"voronoi_n_sphere", signature};
701
702 if (ELEM(dimensions, 2, 3, 4)) {
703 builder.single_input<float3>("Vector");
704 }
705 if (ELEM(dimensions, 1, 4)) {
706 builder.single_input<float>("W");
707 }
708 builder.single_input<float>("Scale");
709 builder.single_input<float>("Randomness");
710
711 builder.single_output<float>("Radius");
712
713 return signature;
714 }
715
716 void call(const IndexMask &mask, mf::Params mf_params, mf::Context /*context*/) const override
717 {
718 auto get_vector = [&](int param_index) -> VArray<float3> {
719 return mf_params.readonly_single_input<float3>(param_index, "Vector");
720 };
721 auto get_w = [&](int param_index) -> VArray<float> {
722 return mf_params.readonly_single_input<float>(param_index, "W");
723 };
724 auto get_scale = [&](int param_index) -> VArray<float> {
725 return mf_params.readonly_single_input<float>(param_index, "Scale");
726 };
727 auto get_randomness = [&](int param_index) -> VArray<float> {
728 return mf_params.readonly_single_input<float>(param_index, "Randomness");
729 };
730 auto get_r_radius = [&](int param_index) -> MutableSpan<float> {
731 return mf_params.uninitialized_single_output<float>(param_index, "Radius");
732 };
733
734 int param = 0;
735
736 const VArray<float3> &vector = !ELEM(dimensions_, 1) ? get_vector(param++) : VArray<float3>{};
737 const VArray<float> &w = ELEM(dimensions_, 1, 4) ? get_w(param++) : VArray<float>{};
738 const VArray<float> &scale = get_scale(param++);
739 const VArray<float> &randomness = get_randomness(param++);
740 MutableSpan<float> r_radius = get_r_radius(param++);
741
743
744 switch (dimensions_) {
745 case 1: {
746 mask.foreach_index([&](const int64_t i) {
747 params.scale = scale[i];
748 params.randomness = std::min(std::max(randomness[i], 0.0f), 1.0f);
749
750 r_radius[i] = noise::voronoi_n_sphere_radius(params, w[i] * params.scale);
751 });
752 break;
753 }
754 case 2: {
755 mask.foreach_index([&](const int64_t i) {
756 params.scale = scale[i];
757 params.randomness = std::min(std::max(randomness[i], 0.0f), 1.0f);
758
759 r_radius[i] = noise::voronoi_n_sphere_radius(
760 params, float2{vector[i].x, vector[i].y} * params.scale);
761 });
762 break;
763 }
764 case 3: {
765 mask.foreach_index([&](const int64_t i) {
766 params.scale = scale[i];
767 params.randomness = std::min(std::max(randomness[i], 0.0f), 1.0f);
768
769 r_radius[i] = noise::voronoi_n_sphere_radius(params, vector[i] * params.scale);
770 });
771 break;
772 }
773 case 4: {
774 mask.foreach_index([&](const int64_t i) {
775 params.scale = scale[i];
776 params.randomness = std::min(std::max(randomness[i], 0.0f), 1.0f);
777
778 r_radius[i] = noise::voronoi_n_sphere_radius(
779 params, float4{vector[i].x, vector[i].y, vector[i].z, w[i]} * params.scale);
780 });
781 break;
782 }
783 }
784 }
785
787 {
789 }
790};
791
793{
794 const NodeTexVoronoi &storage = node_storage(builder.node());
795 switch (storage.feature) {
798 storage.normalize);
799 break;
800 }
803 break;
804 }
805 default: {
807 storage.dimensions, storage.feature, storage.distance, storage.normalize);
808 break;
809 }
810 }
811}
812
813} // namespace blender::nodes::node_shader_tex_voronoi_cc
814
816{
818
819 static blender::bke::bNodeType ntype;
820
822 ntype.declare = file_ns::sh_node_tex_voronoi_declare;
823 ntype.draw_buttons = file_ns::node_shader_buts_tex_voronoi;
824 ntype.initfunc = file_ns::node_shader_init_tex_voronoi;
826 &ntype, "NodeTexVoronoi", node_free_standard_storage, node_copy_standard_storage);
827 ntype.gpu_fn = file_ns::node_shader_gpu_tex_voronoi;
828 ntype.updatefunc = file_ns::node_shader_update_tex_voronoi;
829 ntype.build_multi_function = file_ns::sh_node_voronoi_build_multi_function;
830
832}
#define NODE_STORAGE_FUNCS(StorageT)
Definition BKE_node.hh:1799
#define SH_NODE_TEX_VORONOI
Definition BKE_node.hh:933
#define NODE_CLASS_TEXTURE
Definition BKE_node.hh:414
void BKE_texture_mapping_default(struct TexMapping *texmap, int type)
Definition texture.cc:247
void BKE_texture_colormapping_default(struct ColorMapping *colormap)
Definition texture.cc:350
#define BLI_assert(a)
Definition BLI_assert.h:50
#define ELEM(...)
@ SHD_VORONOI_EUCLIDEAN
@ SHD_VORONOI_MINKOWSKI
@ SOCK_OUT
@ SOCK_IN
@ SHD_VORONOI_F2
@ SHD_VORONOI_SMOOTH_F1
@ SHD_VORONOI_DISTANCE_TO_EDGE
@ SHD_VORONOI_F1
@ SHD_VORONOI_N_SPHERE_RADIUS
@ TEXMAP_TYPE_POINT
bool GPU_stack_link(GPUMaterial *mat, const bNode *node, const char *name, GPUNodeStack *in, GPUNodeStack *out,...)
GPUNodeLink * GPU_constant(const float *num)
@ PROP_FACTOR
Definition RNA_types.hh:154
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
@ UI_ITEM_R_SPLIT_EMPTY_NAME
#define output
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition btVector3.h:303
constexpr bool is_empty() const
Definition BLI_span.hh:510
void set_signature(const Signature *signature)
MutableSpan< T > uninitialized_single_output_if_required(int param_index, StringRef name="")
MutableSpan< T > uninitialized_single_output(int param_index, StringRef name="")
VArray< T > readonly_single_input(int param_index, StringRef name="")
void make_available(bNode &node) const
void call(const IndexMask &mask, mf::Params mf_params, mf::Context) const override
void call(const IndexMask &mask, mf::Params mf_params, mf::Context) const override
static mf::Signature create_signature(int dimensions, int feature, int metric)
VoronoiMetricFunction(int dimensions, int feature, int metric, bool normalize)
void call(const IndexMask &mask, mf::Params mf_params, mf::Context) const override
local_group_size(16, 16) .push_constant(Type b
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void node_set_socket_availability(bNodeTree *ntree, bNodeSocket *sock, bool is_available)
Definition node.cc:3911
void node_type_storage(bNodeType *ntype, const char *storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
Definition node.cc:4632
void node_register_type(bNodeType *ntype)
Definition node.cc:1708
bNodeSocket * node_find_socket(bNode *node, eNodeSocketInOut in_out, StringRef identifier)
Definition node.cc:1829
void position(const bNode &, void *r_value)
static const char * gpu_shader_get_name(const int feature, const int dimensions)
static void sh_node_tex_voronoi_declare(NodeDeclarationBuilder &b)
static mf::MultiFunction::ExecutionHints voronoi_execution_hints
static void sh_node_voronoi_build_multi_function(NodeMultiFunctionBuilder &builder)
static void node_shader_update_tex_voronoi(bNodeTree *ntree, bNode *node)
static int node_shader_gpu_tex_voronoi(GPUMaterial *mat, bNode *node, bNodeExecData *, GPUNodeStack *in, GPUNodeStack *out)
static void node_shader_init_tex_voronoi(bNodeTree *, bNode *node)
static void node_shader_buts_tex_voronoi(uiLayout *layout, bContext *, PointerRNA *ptr)
template VoronoiOutput fractal_voronoi_x_fx< float4 >(const VoronoiParams &params, const float4 coord, const bool calc_color)
template float fractal_voronoi_distance_to_edge< float >(const VoronoiParams &params, const float coord)
float voronoi_n_sphere_radius(const VoronoiParams &params, const float coord)
Definition noise.cc:1245
template VoronoiOutput fractal_voronoi_x_fx< float3 >(const VoronoiParams &params, const float3 coord, const bool calc_color)
float voronoi_distance(const float a, const float b)
Definition noise.cc:1051
template VoronoiOutput fractal_voronoi_x_fx< float >(const VoronoiParams &params, const float coord, const bool calc_color)
template float fractal_voronoi_distance_to_edge< float3 >(const VoronoiParams &params, const float3 coord)
template VoronoiOutput fractal_voronoi_x_fx< float2 >(const VoronoiParams &params, const float2 coord, const bool calc_color)
template float fractal_voronoi_distance_to_edge< float4 >(const VoronoiParams &params, const float4 coord)
template float fractal_voronoi_distance_to_edge< float2 >(const VoronoiParams &params, const float2 coord)
VecBase< float, 4 > float4
VecBase< float, 2 > float2
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
Definition BLI_color.hh:337
VecBase< float, 3 > float3
void register_node_type_sh_tex_voronoi()
void node_shader_gpu_tex_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *)
void node_shader_gpu_default_tex_coord(GPUMaterial *mat, bNode *node, GPUNodeLink **link)
void sh_fn_node_type_base(blender::bke::bNodeType *ntype, int type, const char *name, short nclass)
void node_free_standard_storage(bNode *node)
Definition node_util.cc:46
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
Definition node_util.cc:58
int RNA_enum_get(PointerRNA *ptr, const char *name)
#define min(a, b)
Definition sort.c:32
__int64 int64_t
Definition stdint.h:89
Defines a node type.
Definition BKE_node.hh:218
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:267
NodeGPUExecFunction gpu_fn
Definition BKE_node.hh:318
NodeMultiFunctionBuildFunction build_multi_function
Definition BKE_node.hh:336
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:238
NodeDeclareFunction declare
Definition BKE_node.hh:347
void(* updatefunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:257
PointerRNA * ptr
Definition wm_files.cc:4126