Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_node.h3
-rw-r--r--source/blender/blenkernel/intern/node.cc1
-rw-r--r--source/blender/blenloader/intern/versioning_300.c29
-rw-r--r--source/blender/editors/space_node/drawnode.cc2
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp4
-rw-r--r--source/blender/gpu/CMakeLists.txt1
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_mix_color.glsl537
-rw-r--r--source/blender/makesdna/DNA_node_types.h16
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c54
-rw-r--r--source/blender/nodes/NOD_shader.h1
-rw-r--r--source/blender/nodes/NOD_static_types.h3
-rw-r--r--source/blender/nodes/shader/CMakeLists.txt1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mix.cc443
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc4
14 files changed, 1092 insertions, 7 deletions
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 509de0620c6..1118552b643 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -1102,7 +1102,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
//#define SH_NODE_MATERIAL 100
#define SH_NODE_RGB 101
#define SH_NODE_VALUE 102
-#define SH_NODE_MIX_RGB 103
+#define SH_NODE_MIX_RGB_LEGACY 103
#define SH_NODE_VALTORGB 104
#define SH_NODE_RGBTOBW 105
#define SH_NODE_SHADERTORGB 106
@@ -1205,6 +1205,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
#define SH_NODE_POINT_INFO 710
#define SH_NODE_COMBINE_COLOR 711
#define SH_NODE_SEPARATE_COLOR 712
+#define SH_NODE_MIX 713
/** \} */
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index 4ed2885dd90..1a40c0a18ed 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -4583,6 +4583,7 @@ static void registerShaderNodes()
register_node_type_sh_wavelength();
register_node_type_sh_blackbody();
register_node_type_sh_mix_rgb();
+ register_node_type_sh_mix();
register_node_type_sh_valtorgb();
register_node_type_sh_rgbtobw();
register_node_type_sh_shadertorgb();
diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c
index b98f8996a2c..4d604fc7eec 100644
--- a/source/blender/blenloader/intern/versioning_300.c
+++ b/source/blender/blenloader/intern/versioning_300.c
@@ -1697,6 +1697,27 @@ static void versioning_replace_legacy_combined_and_separate_color_nodes(bNodeTre
}
}
+static void versioning_replace_legacy_mix_rgb_node(bNodeTree *ntree)
+{
+ version_node_input_socket_name(ntree, SH_NODE_MIX_RGB_LEGACY, "Fac", "Factor_Float");
+ version_node_input_socket_name(ntree, SH_NODE_MIX_RGB_LEGACY, "Color1", "A_Color");
+ version_node_input_socket_name(ntree, SH_NODE_MIX_RGB_LEGACY, "Color2", "B_Color");
+ version_node_output_socket_name(ntree, SH_NODE_MIX_RGB_LEGACY, "Color", "Result_Color");
+ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
+ if (node->type == SH_NODE_MIX_RGB_LEGACY) {
+ strcpy(node->idname, "ShaderNodeMix");
+ node->type = SH_NODE_MIX;
+ NodeShaderMix *data = (NodeShaderMix *)MEM_callocN(sizeof(NodeShaderMix), __func__);
+ data->blend_type = node->custom1;
+ data->clamp_result = node->custom2;
+ data->clamp_factor = 1;
+ data->data_type = SOCK_RGBA;
+ data->factor_mode = NODE_MIX_MODE_UNIFORM;
+ node->storage = data;
+ }
+ }
+}
+
static void version_fix_image_format_copy(Main *bmain, ImageFormatData *format)
{
/* Fix bug where curves in image format were not properly copied to file output
@@ -3332,5 +3353,13 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
}
+
+ /* Convert mix rgb node to new mix node and add storage. */
+ {
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ versioning_replace_legacy_mix_rgb_node(ntree);
+ }
+ FOREACH_NODETREE_END;
+ }
}
}
diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc
index 25ab06850f5..e8325d658ca 100644
--- a/source/blender/editors/space_node/drawnode.cc
+++ b/source/blender/editors/space_node/drawnode.cc
@@ -477,7 +477,7 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_RGB:
ntype->draw_buttons = node_buts_rgb;
break;
- case SH_NODE_MIX_RGB:
+ case SH_NODE_MIX_RGB_LEGACY:
ntype->draw_buttons = node_buts_mix_rgb;
break;
case SH_NODE_VALTORGB:
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
index 87a2d1620aa..3df0d723aec 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
@@ -232,7 +232,7 @@ Material *BlenderStrokeRenderer::GetStrokeShader(Main *bmain,
storage = (NodeShaderAttribute *)input_attr_color->storage;
BLI_strncpy(storage->name, "Color", sizeof(storage->name));
- bNode *mix_rgb_color = nodeAddStaticNode(nullptr, ntree, SH_NODE_MIX_RGB);
+ bNode *mix_rgb_color = nodeAddStaticNode(nullptr, ntree, SH_NODE_MIX_RGB_LEGACY);
mix_rgb_color->custom1 = MA_RAMP_BLEND; // Mix
mix_rgb_color->locx = 200.0f;
mix_rgb_color->locy = -200.0f;
@@ -246,7 +246,7 @@ Material *BlenderStrokeRenderer::GetStrokeShader(Main *bmain,
storage = (NodeShaderAttribute *)input_attr_alpha->storage;
BLI_strncpy(storage->name, "Alpha", sizeof(storage->name));
- bNode *mix_rgb_alpha = nodeAddStaticNode(nullptr, ntree, SH_NODE_MIX_RGB);
+ bNode *mix_rgb_alpha = nodeAddStaticNode(nullptr, ntree, SH_NODE_MIX_RGB_LEGACY);
mix_rgb_alpha->custom1 = MA_RAMP_BLEND; // Mix
mix_rgb_alpha->locx = 600.0f;
mix_rgb_alpha->locy = 300.0f;
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 0c11ecb293b..c289a21421a 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -394,6 +394,7 @@ set(GLSL_SRC
shaders/material/gpu_shader_material_light_path.glsl
shaders/material/gpu_shader_material_mapping.glsl
shaders/material/gpu_shader_material_map_range.glsl
+ shaders/material/gpu_shader_material_mix_color.glsl
shaders/material/gpu_shader_material_mix_shader.glsl
shaders/material/gpu_shader_material_noise.glsl
shaders/material/gpu_shader_material_normal.glsl
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_mix_color.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_mix_color.glsl
new file mode 100644
index 00000000000..933a8de9cb7
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_mix_color.glsl
@@ -0,0 +1,537 @@
+#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl)
+
+void node_mix_blend(float fac,
+ vec3 facvec,
+ float f1,
+ float f2,
+ vec3 v1,
+ vec3 v2,
+ vec4 col1,
+ vec4 col2,
+ out float outfloat,
+ out vec3 outvec,
+ out vec4 outcol)
+{
+ outcol = mix(col1, col2, fac);
+ outcol.a = col1.a;
+}
+
+void node_mix_add(float fac,
+ vec3 facvec,
+ float f1,
+ float f2,
+ vec3 v1,
+ vec3 v2,
+ vec4 col1,
+ vec4 col2,
+ out float outfloat,
+ out vec3 outvec,
+ out vec4 outcol)
+{
+
+ outcol = mix(col1, col1 + col2, fac);
+ outcol.a = col1.a;
+}
+
+void node_mix_mult(float fac,
+ vec3 facvec,
+ float f1,
+ float f2,
+ vec3 v1,
+ vec3 v2,
+ vec4 col1,
+ vec4 col2,
+ out float outfloat,
+ out vec3 outvec,
+ out vec4 outcol)
+{
+
+ outcol = mix(col1, col1 * col2, fac);
+ outcol.a = col1.a;
+}
+
+void node_mix_screen(float fac,
+ vec3 facvec,
+ float f1,
+ float f2,
+ vec3 v1,
+ vec3 v2,
+ vec4 col1,
+ vec4 col2,
+ out float outfloat,
+ out vec3 outvec,
+ out vec4 outcol)
+{
+
+ float facm = 1.0 - fac;
+
+ outcol = vec4(1.0) - (vec4(facm) + fac * (vec4(1.0) - col2)) * (vec4(1.0) - col1);
+ outcol.a = col1.a;
+}
+
+void node_mix_overlay(float fac,
+ vec3 facvec,
+ float f1,
+ float f2,
+ vec3 v1,
+ vec3 v2,
+ vec4 col1,
+ vec4 col2,
+ out float outfloat,
+ out vec3 outvec,
+ out vec4 outcol)
+{
+
+ float facm = 1.0 - fac;
+
+ outcol = col1;
+
+ if (outcol.r < 0.5) {
+ outcol.r *= facm + 2.0 * fac * col2.r;
+ }
+ else {
+ outcol.r = 1.0 - (facm + 2.0 * fac * (1.0 - col2.r)) * (1.0 - outcol.r);
+ }
+
+ if (outcol.g < 0.5) {
+ outcol.g *= facm + 2.0 * fac * col2.g;
+ }
+ else {
+ outcol.g = 1.0 - (facm + 2.0 * fac * (1.0 - col2.g)) * (1.0 - outcol.g);
+ }
+
+ if (outcol.b < 0.5) {
+ outcol.b *= facm + 2.0 * fac * col2.b;
+ }
+ else {
+ outcol.b = 1.0 - (facm + 2.0 * fac * (1.0 - col2.b)) * (1.0 - outcol.b);
+ }
+}
+
+void node_mix_sub(float fac,
+ vec3 facvec,
+ float f1,
+ float f2,
+ vec3 v1,
+ vec3 v2,
+ vec4 col1,
+ vec4 col2,
+ out float outfloat,
+ out vec3 outvec,
+ out vec4 outcol)
+{
+
+ outcol = mix(col1, col1 - col2, fac);
+ outcol.a = col1.a;
+}
+
+/* A variant of mix_div that fallback to the first color upon zero division. */
+void node_mix_div_fallback(float fac,
+ vec3 facvec,
+ float f1,
+ float f2,
+ vec3 v1,
+ vec3 v2,
+ vec4 col1,
+ vec4 col2,
+ out float outfloat,
+ out vec3 outvec,
+ out vec4 outcol)
+{
+
+ float facm = 1.0 - fac;
+
+ outcol = col1;
+
+ if (col2.r != 0.0) {
+ outcol.r = facm * outcol.r + fac * outcol.r / col2.r;
+ }
+ if (col2.g != 0.0) {
+ outcol.g = facm * outcol.g + fac * outcol.g / col2.g;
+ }
+ if (col2.b != 0.0) {
+ outcol.b = facm * outcol.b + fac * outcol.b / col2.b;
+ }
+}
+
+void node_mix_diff(float fac,
+ vec3 facvec,
+ float f1,
+ float f2,
+ vec3 v1,
+ vec3 v2,
+ vec4 col1,
+ vec4 col2,
+ out float outfloat,
+ out vec3 outvec,
+ out vec4 outcol)
+{
+
+ outcol = mix(col1, abs(col1 - col2), fac);
+ outcol.a = col1.a;
+}
+
+void node_mix_dark(float fac,
+ vec3 facvec,
+ float f1,
+ float f2,
+ vec3 v1,
+ vec3 v2,
+ vec4 col1,
+ vec4 col2,
+ out float outfloat,
+ out vec3 outvec,
+ out vec4 outcol)
+{
+
+ outcol.rgb = mix(col1.rgb, min(col1.rgb, col2.rgb), fac);
+ outcol.a = col1.a;
+}
+
+void node_mix_light(float fac,
+ vec3 facvec,
+ float f1,
+ float f2,
+ vec3 v1,
+ vec3 v2,
+ vec4 col1,
+ vec4 col2,
+ out float outfloat,
+ out vec3 outvec,
+ out vec4 outcol)
+{
+ outcol.rgb = mix(col1.rgb, max(col1.rgb, col2.rgb), fac);
+ outcol.a = col1.a;
+}
+
+void node_mix_dodge(float fac,
+ vec3 facvec,
+ float f1,
+ float f2,
+ vec3 v1,
+ vec3 v2,
+ vec4 col1,
+ vec4 col2,
+ out float outfloat,
+ out vec3 outvec,
+ out vec4 outcol)
+{
+ outcol = col1;
+
+ if (outcol.r != 0.0) {
+ float tmp = 1.0 - fac * col2.r;
+ if (tmp <= 0.0) {
+ outcol.r = 1.0;
+ }
+ else if ((tmp = outcol.r / tmp) > 1.0) {
+ outcol.r = 1.0;
+ }
+ else {
+ outcol.r = tmp;
+ }
+ }
+ if (outcol.g != 0.0) {
+ float tmp = 1.0 - fac * col2.g;
+ if (tmp <= 0.0) {
+ outcol.g = 1.0;
+ }
+ else if ((tmp = outcol.g / tmp) > 1.0) {
+ outcol.g = 1.0;
+ }
+ else {
+ outcol.g = tmp;
+ }
+ }
+ if (outcol.b != 0.0) {
+ float tmp = 1.0 - fac * col2.b;
+ if (tmp <= 0.0) {
+ outcol.b = 1.0;
+ }
+ else if ((tmp = outcol.b / tmp) > 1.0) {
+ outcol.b = 1.0;
+ }
+ else {
+ outcol.b = tmp;
+ }
+ }
+}
+
+void node_mix_burn(float fac,
+ vec3 facvec,
+ float f1,
+ float f2,
+ vec3 v1,
+ vec3 v2,
+ vec4 col1,
+ vec4 col2,
+ out float outfloat,
+ out vec3 outvec,
+ out vec4 outcol)
+{
+
+ float tmp, facm = 1.0 - fac;
+
+ outcol = col1;
+
+ tmp = facm + fac * col2.r;
+ if (tmp <= 0.0) {
+ outcol.r = 0.0;
+ }
+ else if ((tmp = (1.0 - (1.0 - outcol.r) / tmp)) < 0.0) {
+ outcol.r = 0.0;
+ }
+ else if (tmp > 1.0) {
+ outcol.r = 1.0;
+ }
+ else {
+ outcol.r = tmp;
+ }
+
+ tmp = facm + fac * col2.g;
+ if (tmp <= 0.0) {
+ outcol.g = 0.0;
+ }
+ else if ((tmp = (1.0 - (1.0 - outcol.g) / tmp)) < 0.0) {
+ outcol.g = 0.0;
+ }
+ else if (tmp > 1.0) {
+ outcol.g = 1.0;
+ }
+ else {
+ outcol.g = tmp;
+ }
+
+ tmp = facm + fac * col2.b;
+ if (tmp <= 0.0) {
+ outcol.b = 0.0;
+ }
+ else if ((tmp = (1.0 - (1.0 - outcol.b) / tmp)) < 0.0) {
+ outcol.b = 0.0;
+ }
+ else if (tmp > 1.0) {
+ outcol.b = 1.0;
+ }
+ else {
+ outcol.b = tmp;
+ }
+}
+
+void node_mix_hue(float fac,
+ vec3 facvec,
+ float f1,
+ float f2,
+ vec3 v1,
+ vec3 v2,
+ vec4 col1,
+ vec4 col2,
+ out float outfloat,
+ out vec3 outvec,
+ out vec4 outcol)
+{
+
+ float facm = 1.0 - fac;
+
+ outcol = col1;
+
+ vec4 hsv, hsv2, tmp;
+ rgb_to_hsv(col2, hsv2);
+
+ if (hsv2.y != 0.0) {
+ rgb_to_hsv(outcol, hsv);
+ hsv.x = hsv2.x;
+ hsv_to_rgb(hsv, tmp);
+
+ outcol = mix(outcol, tmp, fac);
+ outcol.a = col1.a;
+ }
+}
+
+void node_mix_sat(float fac,
+ vec3 facvec,
+ float f1,
+ float f2,
+ vec3 v1,
+ vec3 v2,
+ vec4 col1,
+ vec4 col2,
+ out float outfloat,
+ out vec3 outvec,
+ out vec4 outcol)
+{
+
+ float facm = 1.0 - fac;
+
+ outcol = col1;
+
+ vec4 hsv, hsv2;
+ rgb_to_hsv(outcol, hsv);
+
+ if (hsv.y != 0.0) {
+ rgb_to_hsv(col2, hsv2);
+
+ hsv.y = facm * hsv.y + fac * hsv2.y;
+ hsv_to_rgb(hsv, outcol);
+ }
+}
+
+void node_mix_val(float fac,
+ vec3 facvec,
+ float f1,
+ float f2,
+ vec3 v1,
+ vec3 v2,
+ vec4 col1,
+ vec4 col2,
+ out float outfloat,
+ out vec3 outvec,
+ out vec4 outcol)
+{
+
+ float facm = 1.0 - fac;
+
+ vec4 hsv, hsv2;
+ rgb_to_hsv(col1, hsv);
+ rgb_to_hsv(col2, hsv2);
+
+ hsv.z = facm * hsv.z + fac * hsv2.z;
+ hsv_to_rgb(hsv, outcol);
+}
+
+void node_mix_color(float fac,
+ vec3 facvec,
+ float f1,
+ float f2,
+ vec3 v1,
+ vec3 v2,
+ vec4 col1,
+ vec4 col2,
+ out float outfloat,
+ out vec3 outvec,
+ out vec4 outcol)
+{
+
+ float facm = 1.0 - fac;
+
+ outcol = col1;
+
+ vec4 hsv, hsv2, tmp;
+ rgb_to_hsv(col2, hsv2);
+
+ if (hsv2.y != 0.0) {
+ rgb_to_hsv(outcol, hsv);
+ hsv.x = hsv2.x;
+ hsv.y = hsv2.y;
+ hsv_to_rgb(hsv, tmp);
+
+ outcol = mix(outcol, tmp, fac);
+ outcol.a = col1.a;
+ }
+}
+
+void node_mix_soft(float fac,
+ vec3 facvec,
+ float f1,
+ float f2,
+ vec3 v1,
+ vec3 v2,
+ vec4 col1,
+ vec4 col2,
+ out float outfloat,
+ out vec3 outvec,
+ out vec4 outcol)
+{
+
+ float facm = 1.0 - fac;
+
+ vec4 one = vec4(1.0);
+ vec4 scr = one - (one - col2) * (one - col1);
+ outcol = facm * col1 + fac * ((one - col1) * col2 * col1 + col1 * scr);
+}
+
+void node_mix_linear(float fac,
+ vec3 facvec,
+ float f1,
+ float f2,
+ vec3 v1,
+ vec3 v2,
+ vec4 col1,
+ vec4 col2,
+ out float outfloat,
+ out vec3 outvec,
+ out vec4 outcol)
+{
+
+ outcol = col1 + fac * (2.0 * (col2 - vec4(0.5)));
+}
+
+void node_mix_float(float fac,
+ vec3 facvec,
+ float f1,
+ float f2,
+ vec3 v1,
+ vec3 v2,
+ vec4 col1,
+ vec4 col2,
+ out float outfloat,
+ out vec3 outvec,
+ out vec4 outcol)
+{
+
+ outfloat = mix(f1, f2, fac);
+}
+
+void node_mix_vector(float fac,
+ vec3 facvec,
+ float f1,
+ float f2,
+ vec3 v1,
+ vec3 v2,
+ vec4 col1,
+ vec4 col2,
+ out float outfloat,
+ out vec3 outvec,
+ out vec4 outcol)
+{
+
+ outvec = mix(v1, v2, fac);
+}
+
+void node_mix_vector_non_uniform(float fac,
+ vec3 facvec,
+ float f1,
+ float f2,
+ vec3 v1,
+ vec3 v2,
+ vec4 col1,
+ vec4 col2,
+ out float outfloat,
+ out vec3 outvec,
+ out vec4 outcol)
+{
+ outvec = mix(v1, v2, facvec);
+}
+
+void node_mix_rgba(float fac,
+ vec3 facvec,
+ float f1,
+ float f2,
+ vec3 v1,
+ vec3 v2,
+ vec4 col1,
+ vec4 col2,
+ out float outfloat,
+ out vec3 outvec,
+ out vec4 outcol)
+{
+ outcol = mix(col1, col2, fac);
+}
+
+void node_mix_clamp_vector(vec3 vec, vec3 min, vec3 max, out vec3 outvec)
+{
+ outvec = clamp(vec, min, max);
+}
+
+void node_mix_clamp_value(float value, float min, float max, out float outfloat)
+{
+ outfloat = clamp(value, min, max);
+}
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 3477105f519..4ae06d0a5e4 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -1475,6 +1475,17 @@ typedef struct NodeCombSepColor {
int8_t mode;
} NodeCombSepColor;
+typedef struct NodeShaderMix {
+ /* eNodeSocketDatatype */
+ int8_t data_type;
+ /* NodeShaderMixMode */
+ int8_t factor_mode;
+ int8_t clamp_factor;
+ int8_t clamp_result;
+ int8_t blend_type;
+ char _pad[3];
+} NodeShaderMix;
+
/* script node mode */
#define NODE_SCRIPT_INTERNAL 0
#define NODE_SCRIPT_EXTERNAL 1
@@ -1762,6 +1773,11 @@ typedef enum NodeBooleanMathOperation {
NODE_BOOLEAN_MATH_NIMPLY = 8,
} NodeBooleanMathOperation;
+typedef enum NodeShaderMixMode {
+ NODE_MIX_MODE_UNIFORM = 0,
+ NODE_MIX_MODE_NON_UNIFORM = 1,
+} NodeShaderMixMode;
+
typedef enum NodeCompareMode {
NODE_COMPARE_MODE_ELEMENT = 0,
NODE_COMPARE_MODE_LENGTH = 1,
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 1573a1df002..60a57bae78a 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -4927,6 +4927,54 @@ static void def_compare(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
}
+static void def_sh_mix(StructRNA *srna)
+{
+ static const EnumPropertyItem rna_enum_mix_data_type_items[] = {
+ {SOCK_FLOAT, "FLOAT", 0, "Float", ""},
+ {SOCK_VECTOR, "VECTOR", 0, "Vector", ""},
+ {SOCK_RGBA, "RGBA", 0, "Color", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem rna_enum_mix_mode_items[] = {
+ {NODE_MIX_MODE_UNIFORM, "UNIFORM", 0, "Uniform", "Use a single factor for all components"},
+ {NODE_MIX_MODE_NON_UNIFORM, "NON_UNIFORM", 0, "Non-Uniform", "Per component factor"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ PropertyRNA *prop;
+
+ RNA_def_struct_sdna_from(srna, "NodeShaderMix", "storage");
+
+ prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, rna_enum_mix_data_type_items);
+ RNA_def_property_enum_default(prop, SOCK_FLOAT);
+ RNA_def_property_ui_text(prop, "Data Type", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
+
+ prop = RNA_def_property(srna, "factor_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, rna_enum_mix_mode_items);
+ RNA_def_property_enum_default(prop, SOCK_FLOAT);
+ RNA_def_property_ui_text(prop, "Factor Mode", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
+
+ prop = RNA_def_property(srna, "blend_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "blend_type");
+ RNA_def_property_enum_items(prop, rna_enum_ramp_blend_items);
+ RNA_def_property_ui_text(prop, "Blending Mode", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "clamp_factor", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "clamp_factor", 1);
+ RNA_def_property_ui_text(prop, "Clamp Factor", "Clamp the factor to [0,1] range");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "clamp_result", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "clamp_result", 1);
+ RNA_def_property_ui_text(prop, "Clamp Result", "Clamp the result to [0,1] range");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+}
+
static void def_float_to_int(StructRNA *srna)
{
PropertyRNA *prop;
@@ -10964,6 +11012,12 @@ static void rna_def_node_socket(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Linked", "True if the socket is connected");
+ prop = RNA_def_property(srna, "is_unavailable", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SOCK_UNAVAIL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(
+ prop, "Unavailable", "True if the socket is unavailable");
+
prop = RNA_def_property(srna, "is_multi_input", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SOCK_MULTI_INPUT);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h
index 1d1310360b8..8fe77bffaad 100644
--- a/source/blender/nodes/NOD_shader.h
+++ b/source/blender/nodes/NOD_shader.h
@@ -26,6 +26,7 @@ void register_node_type_sh_camera(void);
void register_node_type_sh_value(void);
void register_node_type_sh_rgb(void);
void register_node_type_sh_mix_rgb(void);
+void register_node_type_sh_mix(void);
void register_node_type_sh_valtorgb(void);
void register_node_type_sh_rgbtobw(void);
void register_node_type_sh_shadertorgb(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 786ce88152e..e6cdd462c66 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -25,7 +25,7 @@ DefNode(Node, NODE_REROUTE, 0, "REROUT
DefNode(ShaderNode, SH_NODE_RGB, 0, "RGB", RGB, "RGB", "A color picker")
DefNode(ShaderNode, SH_NODE_VALUE, 0, "VALUE", Value, "Value", "Used to Input numerical values to other nodes in the tree")
-DefNode(ShaderNode, SH_NODE_MIX_RGB, def_mix_rgb, "MIX_RGB", MixRGB, "MixRGB", "Mix two input colors")
+DefNode(ShaderNode, SH_NODE_MIX_RGB_LEGACY, def_mix_rgb, "MIX_RGB", MixRGB, "MixRGB", "Mix two input colors")
DefNode(ShaderNode, SH_NODE_VALTORGB, def_colorramp, "VALTORGB", ValToRGB, "ColorRamp", "Map values to colors with the use of a gradient")
DefNode(ShaderNode, SH_NODE_RGBTOBW, 0, "RGBTOBW", RGBToBW, "RGB to BW", "Convert a color's luminance to a grayscale value")
DefNode(ShaderNode, SH_NODE_SHADERTORGB, 0, "SHADERTORGB", ShaderToRGB, "Shader to RGB", "Convert rendering effect (such as light and shadow) to color. Typically used for non-photorealistic rendering, to apply additional effects on the output of BSDFs.\nNote: only supported for Eevee")
@@ -122,6 +122,7 @@ DefNode(ShaderNode, SH_NODE_OUTPUT_AOV, def_sh_output_aov, "OUT
DefNode(ShaderNode, SH_NODE_CURVE_FLOAT, def_float_curve, "CURVE_FLOAT", FloatCurve, "Float Curve", "Map an input float to a curve and outputs a float value")
DefNode(ShaderNode, SH_NODE_COMBINE_COLOR, def_sh_combsep_color, "COMBINE_COLOR", CombineColor, "Combine Color", "Create a color from individual components using multiple models")
DefNode(ShaderNode, SH_NODE_SEPARATE_COLOR, def_sh_combsep_color, "SEPARATE_COLOR", SeparateColor, "Separate Color", "Split a color into its individual components using multiple models")
+DefNode(ShaderNode, SH_NODE_MIX, def_sh_mix, "MIX", Mix, "Mix", "Mix values by a factor")
DefNode(CompositorNode, CMP_NODE_VIEWER, def_cmp_viewer, "VIEWER", Viewer, "Viewer", "" )
DefNode(CompositorNode, CMP_NODE_RGB, 0, "RGB", RGB, "RGB", "" )
diff --git a/source/blender/nodes/shader/CMakeLists.txt b/source/blender/nodes/shader/CMakeLists.txt
index 3e90f185168..d135f9a12a4 100644
--- a/source/blender/nodes/shader/CMakeLists.txt
+++ b/source/blender/nodes/shader/CMakeLists.txt
@@ -68,6 +68,7 @@ set(SRC
nodes/node_shader_mapping.cc
nodes/node_shader_math.cc
nodes/node_shader_mix_rgb.cc
+ nodes/node_shader_mix.cc
nodes/node_shader_mix_shader.cc
nodes/node_shader_normal.cc
nodes/node_shader_normal_map.cc
diff --git a/source/blender/nodes/shader/nodes/node_shader_mix.cc b/source/blender/nodes/shader/nodes/node_shader_mix.cc
new file mode 100644
index 00000000000..05aad262af8
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_mix.cc
@@ -0,0 +1,443 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2005 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup shdnodes
+ */
+
+#include <algorithm>
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "node_shader_util.hh"
+
+#include "NOD_socket_search_link.hh"
+#include "RNA_enum_types.h"
+
+namespace blender::nodes::node_sh_mix_cc {
+
+NODE_STORAGE_FUNCS(NodeShaderMix)
+
+static void sh_node_mix_declare(NodeDeclarationBuilder &b)
+{
+ b.is_function_node();
+ b.add_input<decl::Float>(N_("Factor"), "Factor_Float")
+ .default_value(0.5f)
+ .min(0.0f)
+ .max(1.0f)
+ .subtype(PROP_FACTOR);
+ b.add_input<decl::Vector>(N_("Factor"), "Factor_Vector")
+ .default_value(float3(0.5f))
+ .subtype(PROP_FACTOR);
+
+ b.add_input<decl::Float>(N_("A"), "A_Float")
+ .min(-10000.0f)
+ .max(10000.0f)
+ .is_default_link_socket();
+ b.add_input<decl::Float>(N_("B"), "B_Float").min(-10000.0f).max(10000.0f);
+
+ b.add_input<decl::Vector>(N_("A"), "A_Vector").is_default_link_socket();
+ b.add_input<decl::Vector>(N_("B"), "B_Vector");
+
+ b.add_input<decl::Color>(N_("A"), "A_Color")
+ .default_value({0.5f, 0.5f, 0.5f, 1.0f})
+ .is_default_link_socket();
+ b.add_input<decl::Color>(N_("B"), "B_Color").default_value({0.5f, 0.5f, 0.5f, 1.0f});
+
+ b.add_output<decl::Float>(N_("Result"), "Result_Float");
+ b.add_output<decl::Vector>(N_("Result"), "Result_Vector");
+ b.add_output<decl::Color>(N_("Result"), "Result_Color");
+};
+
+static void sh_node_mix_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ const NodeShaderMix &data = node_storage(*static_cast<const bNode *>(ptr->data));
+ uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
+ if (data.data_type == SOCK_VECTOR) {
+ uiItemR(layout, ptr, "factor_mode", 0, "", ICON_NONE);
+ }
+ if (data.data_type == SOCK_RGBA) {
+ uiItemR(layout, ptr, "blend_type", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "clamp_result", 0, nullptr, ICON_NONE);
+ uiItemR(layout, ptr, "clamp_factor", 0, nullptr, ICON_NONE);
+ }
+ else {
+ uiItemR(layout, ptr, "clamp_factor", 0, nullptr, ICON_NONE);
+ }
+}
+
+static void sh_node_mix_label(const bNodeTree *UNUSED(ntree),
+ const bNode *node,
+ char *label,
+ int maxlen)
+{
+ const NodeShaderMix &storage = node_storage(*node);
+ if (storage.data_type == SOCK_RGBA) {
+ const char *name;
+ bool enum_label = RNA_enum_name(rna_enum_ramp_blend_items, storage.blend_type, &name);
+ if (!enum_label) {
+ name = "Unknown";
+ }
+ BLI_strncpy(label, IFACE_(name), maxlen);
+ }
+}
+
+static int sh_node_mix_ui_class(const bNode *node)
+{
+ const NodeShaderMix &storage = node_storage(*node);
+ const eNodeSocketDatatype data_type = static_cast<eNodeSocketDatatype>(storage.data_type);
+
+ switch (data_type) {
+ case SOCK_VECTOR:
+ return NODE_CLASS_OP_VECTOR;
+ case SOCK_RGBA:
+ return NODE_CLASS_OP_COLOR;
+ default:
+ return NODE_CLASS_CONVERTER;
+ }
+}
+
+static void sh_node_mix_update(bNodeTree *ntree, bNode *node)
+{
+ const NodeShaderMix &storage = node_storage(*node);
+ const eNodeSocketDatatype data_type = static_cast<eNodeSocketDatatype>(storage.data_type);
+
+ LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
+ nodeSetSocketAvailability(ntree, socket, socket->type == data_type);
+ }
+
+ LISTBASE_FOREACH (bNodeSocket *, socket, &node->outputs) {
+ nodeSetSocketAvailability(ntree, socket, socket->type == data_type);
+ }
+
+ bool use_vector_factor = data_type == SOCK_VECTOR &&
+ storage.factor_mode != NODE_MIX_MODE_UNIFORM;
+
+ bNodeSocket *sock_factor = (bNodeSocket *)BLI_findlink(&node->inputs, 0);
+ nodeSetSocketAvailability(ntree, sock_factor, !use_vector_factor);
+
+ bNodeSocket *sock_factor_vec = (bNodeSocket *)BLI_findlink(&node->inputs, 1);
+ nodeSetSocketAvailability(ntree, sock_factor_vec, use_vector_factor);
+}
+
+static void node_mix_gather_link_searches(GatherLinkSearchOpParams &params)
+{
+ const eNodeSocketDatatype sock_type = static_cast<eNodeSocketDatatype>(
+ params.other_socket().type);
+
+ if (ELEM(sock_type, SOCK_BOOLEAN, SOCK_FLOAT, SOCK_RGBA, SOCK_VECTOR, SOCK_INT)) {
+ const eNodeSocketDatatype type = ELEM(sock_type, SOCK_BOOLEAN, SOCK_INT) ? SOCK_FLOAT :
+ sock_type;
+
+ if (params.in_out() == SOCK_OUT) {
+ params.add_item(IFACE_("Result"), [type](LinkSearchOpParams &params) {
+ bNode &node = params.add_node("ShaderNodeMix");
+ node_storage(node).data_type = type;
+ params.update_and_connect_available_socket(node, "Result");
+ });
+ }
+ else {
+ if (ELEM(sock_type, SOCK_VECTOR, SOCK_RGBA)) {
+ params.add_item(IFACE_("Factor (Non-Uniform)"), [type](LinkSearchOpParams &params) {
+ bNode &node = params.add_node("ShaderNodeMix");
+ node_storage(node).data_type = SOCK_VECTOR;
+ node_storage(node).factor_mode = NODE_MIX_MODE_NON_UNIFORM;
+ params.update_and_connect_available_socket(node, "Factor");
+ });
+ }
+ params.add_item(IFACE_("Factor"), [type](LinkSearchOpParams &params) {
+ bNode &node = params.add_node("ShaderNodeMix");
+ node_storage(node).data_type = type;
+ params.update_and_connect_available_socket(node, "Factor");
+ });
+ params.add_item(IFACE_("A"), [type](LinkSearchOpParams &params) {
+ bNode &node = params.add_node("ShaderNodeMix");
+ node_storage(node).data_type = type;
+ params.update_and_connect_available_socket(node, "A");
+ });
+ params.add_item(IFACE_("B"), [type](LinkSearchOpParams &params) {
+ bNode &node = params.add_node("ShaderNodeMix");
+ node_storage(node).data_type = type;
+ params.update_and_connect_available_socket(node, "B");
+ });
+ }
+ }
+}
+
+static void node_mix_init(bNodeTree *UNUSED(tree), bNode *node)
+{
+ NodeShaderMix *data = MEM_cnew<NodeShaderMix>(__func__);
+ data->data_type = SOCK_FLOAT;
+ data->factor_mode = NODE_MIX_MODE_UNIFORM;
+ data->clamp_factor = 1;
+ data->clamp_result = 0;
+ data->blend_type = MA_RAMP_BLEND;
+ node->storage = data;
+}
+
+static const char *gpu_shader_get_name(eNodeSocketDatatype data_type,
+ const bool non_uniform,
+ const int blend_type)
+{
+ switch (data_type) {
+ case SOCK_FLOAT:
+ return "node_mix_float";
+ case SOCK_VECTOR:
+ return (non_uniform) ? "node_mix_vector_non_uniform" : "node_mix_vector";
+ case SOCK_RGBA:
+ switch (blend_type) {
+ case MA_RAMP_BLEND:
+ return "node_mix_blend";
+ case MA_RAMP_ADD:
+ return "node_mix_add";
+ case MA_RAMP_MULT:
+ return "node_mix_mult";
+ case MA_RAMP_SUB:
+ return "node_mix_sub";
+ case MA_RAMP_SCREEN:
+ return "node_mix_screen";
+ case MA_RAMP_DIV:
+ return "node_mix_div_fallback";
+ case MA_RAMP_DIFF:
+ return "node_mix_diff";
+ case MA_RAMP_DARK:
+ return "node_mix_dark";
+ case MA_RAMP_LIGHT:
+ return "node_mix_light";
+ case MA_RAMP_OVERLAY:
+ return "node_mix_overlay";
+ case MA_RAMP_DODGE:
+ return "node_mix_dodge";
+ case MA_RAMP_BURN:
+ return "node_mix_burn";
+ case MA_RAMP_HUE:
+ return "node_mix_hue";
+ case MA_RAMP_SAT:
+ return "node_mix_sat";
+ case MA_RAMP_VAL:
+ return "node_mix_val";
+ case MA_RAMP_COLOR:
+ return "node_mix_color";
+ case MA_RAMP_SOFT:
+ return "node_mix_soft";
+ case MA_RAMP_LINEAR:
+ return "node_mix_linear";
+ default:
+ BLI_assert_unreachable();
+ return nullptr;
+ }
+ default:
+ BLI_assert_unreachable();
+ return nullptr;
+ }
+}
+
+static int gpu_shader_mix(GPUMaterial *mat,
+ bNode *node,
+ bNodeExecData *UNUSED(execdata),
+ GPUNodeStack *in,
+ GPUNodeStack *out)
+{
+ const NodeShaderMix &storage = node_storage(*node);
+ const bool is_non_uniform = storage.factor_mode == NODE_MIX_MODE_NON_UNIFORM;
+ const bool is_color_mode = storage.data_type == SOCK_RGBA;
+ const bool is_vector_mode = storage.data_type == SOCK_VECTOR;
+ const int blend_type = storage.blend_type;
+ const char *name = gpu_shader_get_name(
+ (eNodeSocketDatatype)storage.data_type, is_non_uniform, blend_type);
+
+ if (name == nullptr) {
+ return 0;
+ }
+
+ if (storage.clamp_factor) {
+ if (is_non_uniform && is_vector_mode) {
+ const float min[3] = {0.0f, 0.0f, 0.0f};
+ const float max[3] = {1.0f, 1.0f, 1.0f};
+ const GPUNodeLink *factor_link = in[1].link ? in[1].link : GPU_uniform(in[1].vec);
+ GPU_link(mat,
+ "node_mix_clamp_vector",
+ factor_link,
+ GPU_constant(min),
+ GPU_constant(max),
+ &in[1].link);
+ }
+ else {
+ const float min = 0.0f;
+ const float max = 1.0f;
+ const GPUNodeLink *factor_link = in[0].link ? in[0].link : GPU_uniform(in[0].vec);
+ GPU_link(mat,
+ "node_mix_clamp_value",
+ factor_link,
+ GPU_constant(&min),
+ GPU_constant(&max),
+ &in[0].link);
+ }
+ }
+
+ int ret = GPU_stack_link(mat, node, name, in, out);
+
+ if (ret && is_color_mode && storage.clamp_result) {
+ const float min[3] = {0.0f, 0.0f, 0.0f};
+ const float max[3] = {1.0f, 1.0f, 1.0f};
+ GPU_link(mat,
+ "node_mix_clamp_vector",
+ out[2].link,
+ GPU_constant(min),
+ GPU_constant(max),
+ &out[2].link);
+ }
+ return ret;
+}
+
+class MixColorFunction : public fn::MultiFunction {
+ private:
+ const bool clamp_factor_;
+ const bool clamp_result_;
+ const int blend_type_;
+
+ public:
+ MixColorFunction(const bool clamp_factor, const bool clamp_result, const int blend_type)
+ : clamp_factor_(clamp_factor), clamp_result_(clamp_result), blend_type_(blend_type)
+ {
+ static fn::MFSignature signature = create_signature();
+ this->set_signature(&signature);
+ }
+
+ static fn::MFSignature create_signature()
+ {
+ fn::MFSignatureBuilder signature{"MixColor"};
+ signature.single_input<float>("Factor");
+ signature.single_input<ColorGeometry4f>("A");
+ signature.single_input<ColorGeometry4f>("B");
+ signature.single_output<ColorGeometry4f>("Result");
+ return signature.build();
+ }
+
+ void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
+ {
+ const VArray<float> &fac = params.readonly_single_input<float>(0, "Factor");
+ const VArray<ColorGeometry4f> &col1 = params.readonly_single_input<ColorGeometry4f>(1, "A");
+ const VArray<ColorGeometry4f> &col2 = params.readonly_single_input<ColorGeometry4f>(2, "B");
+ MutableSpan<ColorGeometry4f> results = params.uninitialized_single_output<ColorGeometry4f>(
+ 3, "Result");
+
+ if (clamp_factor_) {
+ for (int64_t i : mask) {
+ results[i] = col1[i];
+ ramp_blend(blend_type_, results[i], std::clamp(fac[i], 0.0f, 1.0f), col2[i]);
+ }
+ }
+ else {
+ for (int64_t i : mask) {
+ results[i] = col1[i];
+ ramp_blend(blend_type_, results[i], fac[i], col2[i]);
+ }
+ }
+
+ if (clamp_result_) {
+ for (int64_t i : mask) {
+ clamp_v3(results[i], 0.0f, 1.0f);
+ }
+ }
+ }
+};
+
+static const fn::MultiFunction *get_multi_function(bNode &node)
+{
+ const NodeShaderMix *data = (NodeShaderMix *)node.storage;
+ bool uniform_factor = data->factor_mode == NODE_MIX_MODE_UNIFORM;
+ const bool clamp_factor = data->clamp_factor;
+ switch (data->data_type) {
+ case SOCK_FLOAT: {
+ if (clamp_factor) {
+ static fn::CustomMF_SI_SI_SI_SO<float, float, float, float> fn{
+ "Clamp Mix Float", [](float t, const float a, const float b) {
+ return math::interpolate(a, b, std::clamp(t, 0.0f, 1.0f));
+ }};
+ return &fn;
+ }
+ else {
+ static fn::CustomMF_SI_SI_SI_SO<float, float, float, float> fn{
+ "Mix Float", [](const float t, const float a, const float b) {
+ return math::interpolate(a, b, t);
+ }};
+ return &fn;
+ }
+ }
+ case SOCK_VECTOR: {
+ if (clamp_factor) {
+ if (uniform_factor) {
+ static fn::CustomMF_SI_SI_SI_SO<float, float3, float3, float3> fn{
+ "Clamp Mix Vector", [](const float t, const float3 a, const float3 b) {
+ return math::interpolate(a, b, std::clamp(t, 0.0f, 1.0f));
+ }};
+ return &fn;
+ }
+ else {
+ static fn::CustomMF_SI_SI_SI_SO<float3, float3, float3, float3> fn{
+ "Clamp Mix Vector Non Uniform", [](float3 t, const float3 a, const float3 b) {
+ t = math::clamp(t, 0.0f, 1.0f);
+ return a * (float3(1.0f) - t) + b * t;
+ }};
+ return &fn;
+ }
+ }
+ else {
+ if (uniform_factor) {
+ static fn::CustomMF_SI_SI_SI_SO<float, float3, float3, float3> fn{
+ "Mix Vector", [](const float t, const float3 a, const float3 b) {
+ return math::interpolate(a, b, t);
+ }};
+ return &fn;
+ }
+ else {
+ static fn::CustomMF_SI_SI_SI_SO<float3, float3, float3, float3> fn{
+ "Mix Vector Non Uniform", [](const float3 t, const float3 a, const float3 b) {
+ return a * (float3(1.0f) - t) + b * t;
+ }};
+ return &fn;
+ }
+ }
+ }
+ }
+ BLI_assert_unreachable();
+ return nullptr;
+}
+
+static void sh_node_mix_build_multi_function(NodeMultiFunctionBuilder &builder)
+{
+ const NodeShaderMix &storage = node_storage(builder.node());
+
+ if (storage.data_type == SOCK_RGBA) {
+ builder.construct_and_set_matching_fn<MixColorFunction>(
+ storage.clamp_factor, storage.clamp_result, storage.blend_type);
+ }
+ else {
+ const fn::MultiFunction *fn = get_multi_function(builder.node());
+ builder.set_matching_fn(fn);
+ }
+}
+
+} // namespace blender::nodes::node_sh_mix_cc
+
+void register_node_type_sh_mix()
+{
+ namespace file_ns = blender::nodes::node_sh_mix_cc;
+
+ static bNodeType ntype;
+ sh_fn_node_type_base(&ntype, SH_NODE_MIX, "Mix", NODE_CLASS_CONVERTER);
+ ntype.declare = file_ns::sh_node_mix_declare;
+ ntype.ui_class = file_ns::sh_node_mix_ui_class;
+ node_type_gpu(&ntype, file_ns::gpu_shader_mix);
+ node_type_update(&ntype, file_ns::sh_node_mix_update);
+ node_type_init(&ntype, file_ns::node_mix_init);
+ node_type_storage(
+ &ntype, "NodeShaderMix", node_free_standard_storage, node_copy_standard_storage);
+ ntype.build_multi_function = file_ns::sh_node_mix_build_multi_function;
+ ntype.draw_buttons = file_ns::sh_node_mix_layout;
+ ntype.labelfunc = file_ns::sh_node_mix_label;
+ ntype.gather_link_search_ops = file_ns::node_mix_gather_link_searches;
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc b/source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc
index 478a6812c36..edbded43acf 100644
--- a/source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc
@@ -150,11 +150,11 @@ void register_node_type_sh_mix_rgb()
static bNodeType ntype;
- sh_fn_node_type_base(&ntype, SH_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR);
+ sh_fn_node_type_base(&ntype, SH_NODE_MIX_RGB_LEGACY, "Mix", NODE_CLASS_OP_COLOR);
ntype.declare = file_ns::sh_node_mix_rgb_declare;
ntype.labelfunc = node_blend_label;
node_type_gpu(&ntype, file_ns::gpu_shader_mix_rgb);
ntype.build_multi_function = file_ns::sh_node_mix_rgb_build_multi_function;
-
+ ntype.gather_link_search_ops = nullptr;
nodeRegisterType(&ntype);
}