Blender V4.3
node_shader_mix.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
9#include <algorithm>
10
11#include "BKE_material.h"
12
14#include "BLI_math_vector.h"
15#include "BLI_string_utf8.h"
16
17#include "DNA_material_types.h"
18
19#include "UI_interface.hh"
20#include "UI_resources.hh"
21
22#include "node_shader_util.hh"
23#include "node_util.hh"
24
26
27#include "NOD_multi_function.hh"
29
30#include "RNA_access.hh"
31#include "RNA_enum_types.hh"
32
34
36
38{
39 b.is_function_node();
40 /* WARNING:
41 * Input socket indices must be kept in sync with ntree_shader_disconnect_inactive_mix_branches
42 */
43 b.add_input<decl::Float>("Factor", "Factor_Float")
44 .default_value(0.5f)
45 .min(0.0f)
46 .max(1.0f)
48 .no_muted_links()
49 .description("Amount of mixing between the A and B inputs");
50 b.add_input<decl::Vector>("Factor", "Factor_Vector")
51 .default_value(float3(0.5f))
52 .subtype(PROP_FACTOR)
53 .no_muted_links()
54 .description("Amount of mixing between the A and B vector inputs");
55
56 b.add_input<decl::Float>("A", "A_Float")
57 .min(-10000.0f)
58 .max(10000.0f)
60 .translation_context(BLT_I18NCONTEXT_ID_NODETREE)
61 .description("Value of the first floating number input");
62 b.add_input<decl::Float>("B", "B_Float")
63 .min(-10000.0f)
64 .max(10000.0f)
66 .description("Value of the second floating number input");
67
68 b.add_input<decl::Vector>("A", "A_Vector")
69 .is_default_link_socket()
71 .description("Value of the first vector input");
72 b.add_input<decl::Vector>("B", "B_Vector")
73 .translation_context(BLT_I18NCONTEXT_ID_NODETREE)
74 .description("Value of the second vector input");
75
76 b.add_input<decl::Color>("A", "A_Color")
77 .default_value({0.5f, 0.5f, 0.5f, 1.0f})
78 .is_default_link_socket()
80 .description("Value of the first color input");
81 b.add_input<decl::Color>("B", "B_Color")
82 .default_value({0.5f, 0.5f, 0.5f, 1.0f})
83 .translation_context(BLT_I18NCONTEXT_ID_NODETREE)
84 .description("Value of the second color input");
85
86 b.add_input<decl::Rotation>("A", "A_Rotation")
87 .is_default_link_socket()
89 b.add_input<decl::Rotation>("B", "B_Rotation").translation_context(BLT_I18NCONTEXT_ID_NODETREE);
90
91 b.add_output<decl::Float>("Result", "Result_Float");
92 b.add_output<decl::Vector>("Result", "Result_Vector");
93 b.add_output<decl::Color>("Result", "Result_Color");
94 b.add_output<decl::Rotation>("Result", "Result_Rotation");
95};
96
97static void sh_node_mix_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
98{
99 const NodeShaderMix &data = node_storage(*static_cast<const bNode *>(ptr->data));
100 uiItemR(layout, ptr, "data_type", UI_ITEM_NONE, "", ICON_NONE);
101 switch (data.data_type) {
102 case SOCK_FLOAT:
103 break;
104 case SOCK_VECTOR:
105 uiItemR(layout, ptr, "factor_mode", UI_ITEM_NONE, "", ICON_NONE);
106 break;
107 case SOCK_RGBA:
108 uiItemR(layout, ptr, "blend_type", UI_ITEM_NONE, "", ICON_NONE);
109 uiItemR(layout, ptr, "clamp_result", UI_ITEM_NONE, nullptr, ICON_NONE);
110 break;
111 case SOCK_ROTATION:
112 break;
113 default:
115 }
116 uiItemR(layout, ptr, "clamp_factor", UI_ITEM_NONE, nullptr, ICON_NONE);
117}
118
119static void sh_node_mix_label(const bNodeTree * /*ntree*/,
120 const bNode *node,
121 char *label,
122 int label_maxncpy)
123{
124 const NodeShaderMix &storage = node_storage(*node);
125 if (storage.data_type == SOCK_RGBA) {
126 const char *name;
127 bool enum_label = RNA_enum_name(rna_enum_ramp_blend_items, storage.blend_type, &name);
128 if (!enum_label) {
129 name = "Unknown";
130 }
131 BLI_strncpy_utf8(label, IFACE_(name), label_maxncpy);
132 }
133}
134
135static int sh_node_mix_ui_class(const bNode *node)
136{
137 const NodeShaderMix &storage = node_storage(*node);
138 const eNodeSocketDatatype data_type = static_cast<eNodeSocketDatatype>(storage.data_type);
139
140 switch (data_type) {
141 case SOCK_VECTOR:
143 case SOCK_RGBA:
144 return NODE_CLASS_OP_COLOR;
145 default:
147 }
148}
149
150static void sh_node_mix_update(bNodeTree *ntree, bNode *node)
151{
152 const NodeShaderMix &storage = node_storage(*node);
153 const eNodeSocketDatatype data_type = static_cast<eNodeSocketDatatype>(storage.data_type);
154
155 bNodeSocket *sock_factor = static_cast<bNodeSocket *>(node->inputs.first);
156 bNodeSocket *sock_factor_vec = static_cast<bNodeSocket *>(sock_factor->next);
157
158 bool use_vector_factor = data_type == SOCK_VECTOR &&
160
161 bke::node_set_socket_availability(ntree, sock_factor, !use_vector_factor);
162
163 bke::node_set_socket_availability(ntree, sock_factor_vec, use_vector_factor);
164
165 for (bNodeSocket *socket = sock_factor_vec->next; socket != nullptr; socket = socket->next) {
166 bke::node_set_socket_availability(ntree, socket, socket->type == data_type);
167 }
168
169 LISTBASE_FOREACH (bNodeSocket *, socket, &node->outputs) {
170 bke::node_set_socket_availability(ntree, socket, socket->type == data_type);
171 }
172}
173
175 public:
176 std::string socket_name;
177 int type = MA_RAMP_BLEND;
179 {
180 bNode &node = params.add_node("ShaderNodeMix");
181 node_storage(node).data_type = SOCK_RGBA;
182 node_storage(node).blend_type = type;
183 params.update_and_connect_available_socket(node, socket_name);
184 }
185};
186
188{
190 switch (eNodeSocketDatatype(params.other_socket().type)) {
191 case SOCK_BOOLEAN:
192 case SOCK_INT:
193 case SOCK_FLOAT:
194 type = SOCK_FLOAT;
195 break;
196 case SOCK_VECTOR:
197 type = SOCK_VECTOR;
198 break;
199 case SOCK_RGBA:
200 type = SOCK_RGBA;
201 break;
202 case SOCK_ROTATION:
203 type = SOCK_ROTATION;
204 break;
205 default:
206 return;
207 }
208
209 int weight = 0;
210 if (params.in_out() == SOCK_OUT) {
211 params.add_item(IFACE_("Result"), [type](LinkSearchOpParams &params) {
212 bNode &node = params.add_node("ShaderNodeMix");
213 node_storage(node).data_type = type;
214 params.update_and_connect_available_socket(node, "Result");
215 });
216 }
217 else {
218 params.add_item(
220 [type](LinkSearchOpParams &params) {
221 bNode &node = params.add_node("ShaderNodeMix");
222 node_storage(node).data_type = type;
223 params.update_and_connect_available_socket(node, "A");
224 },
225 weight);
226 weight--;
227 params.add_item(
229 [type](LinkSearchOpParams &params) {
230 bNode &node = params.add_node("ShaderNodeMix");
231 node_storage(node).data_type = type;
232 params.update_and_connect_available_socket(node, "B");
233 },
234 weight);
235 weight--;
236 if (ELEM(type, SOCK_VECTOR, SOCK_RGBA)) {
237 params.add_item(
238 IFACE_("Factor (Non-Uniform)"),
240 bNode &node = params.add_node("ShaderNodeMix");
241 node_storage(node).data_type = SOCK_VECTOR;
242 node_storage(node).factor_mode = NODE_MIX_MODE_NON_UNIFORM;
243 params.update_and_connect_available_socket(node, "Factor");
244 },
245 weight);
246 weight--;
247 }
248 if (type != SOCK_ROTATION) {
249 params.add_item(
250 IFACE_("Factor"),
251 [type](LinkSearchOpParams &params) {
252 bNode &node = params.add_node("ShaderNodeMix");
253 node_storage(node).data_type = type;
254 params.update_and_connect_available_socket(node, "Factor");
255 },
256 weight);
257 weight--;
258 }
259 }
260
261 if (type == SOCK_ROTATION) {
262 return;
263 }
264
265 if (type != SOCK_RGBA) {
266 weight--;
267 }
268 const std::string socket_name = params.in_out() == SOCK_IN ? "A" : "Result";
269 for (const EnumPropertyItem *item = rna_enum_ramp_blend_items; item->identifier != nullptr;
270 item++)
271 {
272 if (item->name != nullptr && item->identifier[0] != '\0') {
273 params.add_item(IFACE_(item->name), SocketSearchOp{socket_name, item->value}, weight);
274 }
275 }
276}
277
278static void node_mix_init(bNodeTree * /*tree*/, bNode *node)
279{
280 NodeShaderMix *data = MEM_cnew<NodeShaderMix>(__func__);
281 data->data_type = SOCK_FLOAT;
282 data->factor_mode = NODE_MIX_MODE_UNIFORM;
283 data->clamp_factor = 1;
284 data->clamp_result = 0;
285 data->blend_type = MA_RAMP_BLEND;
286 node->storage = data;
287}
288
289static const char *gpu_shader_get_name(eNodeSocketDatatype data_type,
290 const bool non_uniform,
291 const int blend_type)
292{
293 switch (data_type) {
294 case SOCK_FLOAT:
295 return "node_mix_float";
296 case SOCK_VECTOR:
297 return (non_uniform) ? "node_mix_vector_non_uniform" : "node_mix_vector";
298 case SOCK_RGBA:
299 switch (blend_type) {
300 case MA_RAMP_BLEND:
301 return "node_mix_blend";
302 case MA_RAMP_ADD:
303 return "node_mix_add";
304 case MA_RAMP_MULT:
305 return "node_mix_mult";
306 case MA_RAMP_SUB:
307 return "node_mix_sub";
308 case MA_RAMP_SCREEN:
309 return "node_mix_screen";
310 case MA_RAMP_DIV:
311 return "node_mix_div_fallback";
312 case MA_RAMP_DIFF:
313 return "node_mix_diff";
315 return "node_mix_exclusion";
316 case MA_RAMP_DARK:
317 return "node_mix_dark";
318 case MA_RAMP_LIGHT:
319 return "node_mix_light";
320 case MA_RAMP_OVERLAY:
321 return "node_mix_overlay";
322 case MA_RAMP_DODGE:
323 return "node_mix_dodge";
324 case MA_RAMP_BURN:
325 return "node_mix_burn";
326 case MA_RAMP_HUE:
327 return "node_mix_hue";
328 case MA_RAMP_SAT:
329 return "node_mix_sat";
330 case MA_RAMP_VAL:
331 return "node_mix_val";
332 case MA_RAMP_COLOR:
333 return "node_mix_color";
334 case MA_RAMP_SOFT:
335 return "node_mix_soft";
336 case MA_RAMP_LINEAR:
337 return "node_mix_linear";
338 default:
340 return nullptr;
341 }
342 case SOCK_ROTATION:
343 return nullptr;
344 default:
346 return nullptr;
347 }
348}
349
351 bNode *node,
352 bNodeExecData * /*execdata*/,
353 GPUNodeStack *in,
354 GPUNodeStack *out)
355{
356 const NodeShaderMix &storage = node_storage(*node);
357 const bool is_non_uniform = storage.factor_mode == NODE_MIX_MODE_NON_UNIFORM;
358 const bool is_color_mode = storage.data_type == SOCK_RGBA;
359 const bool is_vector_mode = storage.data_type == SOCK_VECTOR;
360 const int blend_type = storage.blend_type;
361 const char *name = gpu_shader_get_name(
362 (eNodeSocketDatatype)storage.data_type, is_non_uniform, blend_type);
363
364 if (name == nullptr) {
365 return 0;
366 }
367
368 if (storage.clamp_factor) {
369 if (is_non_uniform && is_vector_mode) {
370 const float min[3] = {0.0f, 0.0f, 0.0f};
371 const float max[3] = {1.0f, 1.0f, 1.0f};
372 const GPUNodeLink *factor_link = in[1].link ? in[1].link : GPU_uniform(in[1].vec);
373 GPU_link(mat,
374 "node_mix_clamp_vector",
375 factor_link,
377 GPU_constant(max),
378 &in[1].link);
379 }
380 else {
381 const float min = 0.0f;
382 const float max = 1.0f;
383 const GPUNodeLink *factor_link = in[0].link ? in[0].link : GPU_uniform(in[0].vec);
384 GPU_link(mat,
385 "node_mix_clamp_value",
386 factor_link,
388 GPU_constant(&max),
389 &in[0].link);
390 }
391 }
392
393 int ret = GPU_stack_link(mat, node, name, in, out);
394
395 if (ret && is_color_mode && storage.clamp_result) {
396 const float min[3] = {0.0f, 0.0f, 0.0f};
397 const float max[3] = {1.0f, 1.0f, 1.0f};
398 GPU_link(mat,
399 "node_mix_clamp_vector",
400 out[2].link,
402 GPU_constant(max),
403 &out[2].link);
404 }
405 return ret;
406}
407
409 private:
410 const bool clamp_factor_;
411 const bool clamp_result_;
412 const int blend_type_;
413
414 public:
415 MixColorFunction(const bool clamp_factor, const bool clamp_result, const int blend_type)
416 : clamp_factor_(clamp_factor), clamp_result_(clamp_result), blend_type_(blend_type)
417 {
418 static const mf::Signature signature = []() {
420 mf::SignatureBuilder builder{"MixColor", signature};
421 builder.single_input<float>("Factor");
422 builder.single_input<ColorGeometry4f>("A");
423 builder.single_input<ColorGeometry4f>("B");
424 builder.single_output<ColorGeometry4f>("Result");
425 return signature;
426 }();
427 this->set_signature(&signature);
428 }
429
430 void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override
431 {
432 const VArray<float> &fac = params.readonly_single_input<float>(0, "Factor");
433 const VArray<ColorGeometry4f> &col1 = params.readonly_single_input<ColorGeometry4f>(1, "A");
434 const VArray<ColorGeometry4f> &col2 = params.readonly_single_input<ColorGeometry4f>(2, "B");
435 MutableSpan<ColorGeometry4f> results = params.uninitialized_single_output<ColorGeometry4f>(
436 3, "Result");
437
438 if (clamp_factor_) {
439 mask.foreach_index_optimized<int64_t>([&](const int64_t i) {
440 results[i] = col1[i];
441 ramp_blend(blend_type_, results[i], std::clamp(fac[i], 0.0f, 1.0f), col2[i]);
442 });
443 }
444 else {
445 mask.foreach_index_optimized<int64_t>([&](const int64_t i) {
446 results[i] = col1[i];
447 ramp_blend(blend_type_, results[i], fac[i], col2[i]);
448 });
449 }
450
451 if (clamp_result_) {
452 mask.foreach_index_optimized<int64_t>(
453 [&](const int64_t i) { clamp_v3(results[i], 0.0f, 1.0f); });
454 }
455 }
456};
457
459{
460 const NodeShaderMix *data = (NodeShaderMix *)node.storage;
461 bool uniform_factor = data->factor_mode == NODE_MIX_MODE_UNIFORM;
462 const bool clamp_factor = data->clamp_factor;
463 switch (data->data_type) {
464 case SOCK_FLOAT: {
465 if (clamp_factor) {
466 static auto fn = mf::build::SI3_SO<float, float, float, float>(
467 "Clamp Mix Float", [](float t, const float a, const float b) {
468 return math::interpolate(a, b, std::clamp(t, 0.0f, 1.0f));
469 });
470 return &fn;
471 }
472 else {
473 static auto fn = mf::build::SI3_SO<float, float, float, float>(
474 "Mix Float", [](const float t, const float a, const float b) {
475 return math::interpolate(a, b, t);
476 });
477 return &fn;
478 }
479 }
480 case SOCK_VECTOR: {
481 if (clamp_factor) {
482 if (uniform_factor) {
483 static auto fn = mf::build::SI3_SO<float, float3, float3, float3>(
484 "Clamp Mix Vector", [](const float t, const float3 a, const float3 b) {
485 return math::interpolate(a, b, std::clamp(t, 0.0f, 1.0f));
486 });
487 return &fn;
488 }
489 else {
490 static auto fn = mf::build::SI3_SO<float3, float3, float3, float3>(
491 "Clamp Mix Vector Non Uniform", [](float3 t, const float3 a, const float3 b) {
492 t = math::clamp(t, 0.0f, 1.0f);
493 return a * (float3(1.0f) - t) + b * t;
494 });
495 return &fn;
496 }
497 }
498 else {
499 if (uniform_factor) {
500 static auto fn = mf::build::SI3_SO<float, float3, float3, float3>(
501 "Mix Vector", [](const float t, const float3 a, const float3 b) {
502 return math::interpolate(a, b, t);
503 });
504 return &fn;
505 }
506 else {
507 static auto fn = mf::build::SI3_SO<float3, float3, float3, float3>(
508 "Mix Vector Non Uniform", [](const float3 t, const float3 a, const float3 b) {
509 return a * (float3(1.0f) - t) + b * t;
510 });
511 return &fn;
512 }
513 }
514 }
515 case SOCK_ROTATION: {
516 if (clamp_factor) {
517 static auto fn =
518 mf::build::SI3_SO<float, math::Quaternion, math::Quaternion, math::Quaternion>(
519 "Clamp Mix Rotation",
520 [](const float t, const math::Quaternion &a, const math::Quaternion &b) {
521 return math::interpolate(a, b, math::clamp(t, 0.0f, 1.0f));
522 });
523 return &fn;
524 }
525 else {
526 static auto fn =
527 mf::build::SI3_SO<float, math::Quaternion, math::Quaternion, math::Quaternion>(
528 "Mix Rotation",
529 [](const float t, const math::Quaternion &a, const math::Quaternion &b) {
530 return math::interpolate(a, b, t);
531 });
532 return &fn;
533 }
534 }
535 }
537 return nullptr;
538}
539
541{
542 const NodeShaderMix &storage = node_storage(builder.node());
543
544 if (storage.data_type == SOCK_RGBA) {
546 storage.clamp_factor, storage.clamp_result, storage.blend_type);
547 }
548 else {
549 const mf::MultiFunction *fn = get_multi_function(builder.node());
550 builder.set_matching_fn(fn);
551 }
552}
553
555#ifdef WITH_MATERIALX
556{
557 const NodeShaderMix *data = (NodeShaderMix *)node_->storage;
558
559 NodeItem factor = empty();
560 NodeItem value1 = empty();
561 NodeItem value2 = empty();
562 switch (data->data_type) {
563 case SOCK_FLOAT:
564 factor = get_input_value(0, NodeItem::Type::Float);
565 value1 = get_input_value(2, NodeItem::Type::Float);
566 value2 = get_input_value(3, NodeItem::Type::Float);
567 break;
568
569 case SOCK_VECTOR:
570 if (data->factor_mode == NODE_MIX_MODE_UNIFORM) {
571 factor = get_input_value(0, NodeItem::Type::Float);
572 }
573 else {
574 factor = get_input_value(1, NodeItem::Type::Vector3);
575 }
576 value1 = get_input_value(4, NodeItem::Type::Vector3);
577 value2 = get_input_value(5, NodeItem::Type::Vector3);
578 break;
579
580 case SOCK_RGBA:
581 factor = get_input_value(0, NodeItem::Type::Float);
582 value1 = get_input_value(6, NodeItem::Type::Color4);
583 value2 = get_input_value(7, NodeItem::Type::Color4);
584 break;
585
586 default:
588 }
589
590 if (data->clamp_factor) {
591 factor = factor.clamp();
592 }
593 NodeItem res = factor.mix(value1, value2);
594 if (data->data_type == SOCK_RGBA) {
595 /* TODO: Apply data->blend_type */
596
597 if (data->clamp_result) {
598 res = res.clamp();
599 }
600 }
601 return res;
602}
603#endif
605
606} // namespace blender::nodes::node_sh_mix_cc
607
609{
610 namespace file_ns = blender::nodes::node_sh_mix_cc;
611
612 static blender::bke::bNodeType ntype;
613 sh_fn_node_type_base(&ntype, SH_NODE_MIX, "Mix", NODE_CLASS_CONVERTER);
614 ntype.declare = file_ns::sh_node_mix_declare;
615 ntype.ui_class = file_ns::sh_node_mix_ui_class;
616 ntype.gpu_fn = file_ns::gpu_shader_mix;
617 ntype.updatefunc = file_ns::sh_node_mix_update;
618 ntype.initfunc = file_ns::node_mix_init;
621 ntype.build_multi_function = file_ns::sh_node_mix_build_multi_function;
622 ntype.draw_buttons = file_ns::sh_node_mix_layout;
623 ntype.labelfunc = file_ns::sh_node_mix_label;
624 ntype.gather_link_search_ops = file_ns::node_mix_gather_link_searches;
625 ntype.materialx_fn = file_ns::node_shader_materialx;
626
628}
General operations, lookup, etc. for materials.
void ramp_blend(int type, float r_col[3], float fac, const float col[3])
#define NODE_CLASS_CONVERTER
Definition BKE_node.hh:410
#define NODE_STORAGE_FUNCS(StorageT)
Definition BKE_node.hh:1799
#define NODE_CLASS_OP_VECTOR
Definition BKE_node.hh:407
#define NODE_CLASS_OP_COLOR
Definition BKE_node.hh:406
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define LISTBASE_FOREACH(type, var, list)
MINLINE void clamp_v3(float vec[3], float min, float max)
char * BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define ELEM(...)
#define BLT_I18NCONTEXT_ID_NODETREE
#define CTX_IFACE_(context, msgid)
#define IFACE_(msgid)
@ MA_RAMP_LIGHT
@ MA_RAMP_COLOR
@ MA_RAMP_SAT
@ MA_RAMP_HUE
@ MA_RAMP_LINEAR
@ MA_RAMP_DIV
@ MA_RAMP_EXCLUSION
@ MA_RAMP_ADD
@ MA_RAMP_DODGE
@ MA_RAMP_SUB
@ MA_RAMP_SCREEN
@ MA_RAMP_SOFT
@ MA_RAMP_DARK
@ MA_RAMP_BURN
@ MA_RAMP_BLEND
@ MA_RAMP_VAL
@ MA_RAMP_OVERLAY
@ MA_RAMP_MULT
@ MA_RAMP_DIFF
@ SOCK_OUT
@ SOCK_IN
@ NODE_MIX_MODE_UNIFORM
@ NODE_MIX_MODE_NON_UNIFORM
eNodeSocketDatatype
@ SOCK_INT
@ SOCK_VECTOR
@ SOCK_BOOLEAN
@ SOCK_FLOAT
@ SOCK_ROTATION
@ SOCK_RGBA
bool GPU_stack_link(GPUMaterial *mat, const bNode *node, const char *name, GPUNodeStack *in, GPUNodeStack *out,...)
GPUNodeLink * GPU_constant(const float *num)
bool GPU_link(GPUMaterial *mat, const char *name,...)
GPUNodeLink * GPU_uniform(const float *num)
@ PROP_FACTOR
Definition RNA_types.hh:154
#define UI_ITEM_NONE
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
void set_signature(const Signature *signature)
void set_matching_fn(const mf::MultiFunction *fn)
void call(const IndexMask &mask, mf::Params params, mf::Context) const override
MixColorFunction(const bool clamp_factor, const bool clamp_result, const int blend_type)
void operator()(LinkSearchOpParams &params)
local_group_size(16, 16) .push_constant(Type b
const char * label
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
T clamp(const T &a, const T &min, const T &max)
T interpolate(const T &a, const T &b, const FactorT &t)
static const char * gpu_shader_get_name(eNodeSocketDatatype data_type, const bool non_uniform, const int blend_type)
static void node_mix_init(bNodeTree *, bNode *node)
static int sh_node_mix_ui_class(const bNode *node)
static void node_mix_gather_link_searches(GatherLinkSearchOpParams &params)
static void sh_node_mix_build_multi_function(NodeMultiFunctionBuilder &builder)
static void sh_node_mix_layout(uiLayout *layout, bContext *, PointerRNA *ptr)
static const mf::MultiFunction * get_multi_function(const bNode &node)
static int gpu_shader_mix(GPUMaterial *mat, bNode *node, bNodeExecData *, GPUNodeStack *in, GPUNodeStack *out)
static void sh_node_mix_declare(NodeDeclarationBuilder &b)
static void sh_node_mix_update(bNodeTree *ntree, bNode *node)
static void sh_node_mix_label(const bNodeTree *, const bNode *node, char *label, int label_maxncpy)
VecBase< float, 3 > float3
#define NODE_SHADER_MATERIALX_BEGIN
#define NODE_SHADER_MATERIALX_END
void register_node_type_sh_mix()
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
return ret
bool RNA_enum_name(const EnumPropertyItem *item, const int value, const char **r_name)
const EnumPropertyItem rna_enum_ramp_blend_items[]
#define min(a, b)
Definition sort.c:32
__int64 int64_t
Definition stdint.h:89
const char * identifier
Definition RNA_types.hh:506
void * data
Definition RNA_types.hh:42
struct bNodeSocket * next
Defines a node type.
Definition BKE_node.hh:218
NodeMaterialXFunction materialx_fn
Definition BKE_node.hh:320
int(* ui_class)(const bNode *node)
Definition BKE_node.hh:252
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:267
void(* labelfunc)(const bNodeTree *ntree, const bNode *node, char *label, int label_maxncpy)
Definition BKE_node.hh:249
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
NodeGatherSocketLinkOperationsFunction gather_link_search_ops
Definition BKE_node.hh:363
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