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:
-rw-r--r--intern/cycles/blender/shader.cpp12
-rw-r--r--intern/cycles/kernel/CMakeLists.txt1
-rw-r--r--intern/cycles/kernel/osl/shaders/CMakeLists.txt2
-rw-r--r--intern/cycles/kernel/osl/shaders/node_color.h50
-rw-r--r--intern/cycles/kernel/osl/shaders/node_combine_color.osl12
-rw-r--r--intern/cycles/kernel/osl/shaders/node_separate_color.osl26
-rw-r--r--intern/cycles/kernel/svm/color_util.h26
-rw-r--r--intern/cycles/kernel/svm/sepcomb_color.h53
-rw-r--r--intern/cycles/kernel/svm/svm.h7
-rw-r--r--intern/cycles/kernel/svm/types.h8
-rw-r--r--intern/cycles/scene/shader_nodes.cpp121
-rw-r--r--intern/cycles/scene/shader_nodes.h20
-rw-r--r--intern/cycles/util/color.h49
-rw-r--r--release/scripts/startup/nodeitems_builtins.py24
-rw-r--r--source/blender/blenkernel/BKE_node.h36
-rw-r--r--source/blender/blenkernel/intern/node.cc8
-rw-r--r--source/blender/blenlib/intern/math_color.c2
-rw-r--r--source/blender/blenloader/intern/versioning_300.c245
-rw-r--r--source/blender/compositor/CMakeLists.txt4
-rw-r--r--source/blender/compositor/intern/COM_Converter.cc24
-rw-r--r--source/blender/compositor/nodes/COM_CombineColorNode.cc57
-rw-r--r--source/blender/compositor/nodes/COM_CombineColorNode.h39
-rw-r--r--source/blender/compositor/nodes/COM_CombineColorNodeLegacy.cc78
-rw-r--r--source/blender/compositor/nodes/COM_CombineColorNodeLegacy.h56
-rw-r--r--source/blender/compositor/nodes/COM_SeparateColorNode.cc57
-rw-r--r--source/blender/compositor/nodes/COM_SeparateColorNode.h39
-rw-r--r--source/blender/compositor/nodes/COM_SeparateColorNodeLegacy.cc110
-rw-r--r--source/blender/compositor/nodes/COM_SeparateColorNodeLegacy.h56
-rw-r--r--source/blender/compositor/operations/COM_ConvertOperation.cc62
-rw-r--r--source/blender/compositor/operations/COM_ConvertOperation.h20
-rw-r--r--source/blender/editors/space_node/drawnode.cc40
-rw-r--r--source/blender/gpu/CMakeLists.txt2
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_color_util.glsl50
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_combine_color.glsl16
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_separate_color.glsl28
-rw-r--r--source/blender/makesdna/DNA_node_types.h27
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c75
-rw-r--r--source/blender/nodes/NOD_composite.h2
-rw-r--r--source/blender/nodes/NOD_function.h2
-rw-r--r--source/blender/nodes/NOD_shader.h2
-rw-r--r--source/blender/nodes/NOD_static_types.h38
-rw-r--r--source/blender/nodes/NOD_texture.h2
-rw-r--r--source/blender/nodes/composite/CMakeLists.txt1
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_sepcomb_color.cc139
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_sepcomb_hsva.cc4
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_sepcomb_rgba.cc4
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_sepcomb_ycca.cc4
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_sepcomb_yuva.cc4
-rw-r--r--source/blender/nodes/function/CMakeLists.txt2
-rw-r--r--source/blender/nodes/function/nodes/node_fn_combine_color.cc108
-rw-r--r--source/blender/nodes/function/nodes/node_fn_separate_color.cc205
-rw-r--r--source/blender/nodes/intern/node_util.c33
-rw-r--r--source/blender/nodes/intern/node_util.h1
-rw-r--r--source/blender/nodes/shader/CMakeLists.txt1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_sepcomb_color.cc162
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_sepcomb_hsv.cc4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_sepcomb_rgb.cc4
-rw-r--r--source/blender/nodes/texture/CMakeLists.txt2
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_combine_color.c76
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_compose.c2
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_decompose.c2
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_separate_color.c102
62 files changed, 2252 insertions, 196 deletions
diff --git a/intern/cycles/blender/shader.cpp b/intern/cycles/blender/shader.cpp
index d3527567b96..35c98a71558 100644
--- a/intern/cycles/blender/shader.cpp
+++ b/intern/cycles/blender/shader.cpp
@@ -355,6 +355,18 @@ static ShaderNode *add_node(Scene *scene,
else if (b_node.is_a(&RNA_ShaderNodeCombineHSV)) {
node = graph->create_node<CombineHSVNode>();
}
+ else if (b_node.is_a(&RNA_ShaderNodeSeparateColor)) {
+ BL::ShaderNodeSeparateColor b_separate_node(b_node);
+ SeparateColorNode *separate_node = graph->create_node<SeparateColorNode>();
+ separate_node->set_color_type((NodeCombSepColorType)b_separate_node.mode());
+ node = separate_node;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeCombineColor)) {
+ BL::ShaderNodeCombineColor b_combine_node(b_node);
+ CombineColorNode *combine_node = graph->create_node<CombineColorNode>();
+ combine_node->set_color_type((NodeCombSepColorType)b_combine_node.mode());
+ node = combine_node;
+ }
else if (b_node.is_a(&RNA_ShaderNodeSeparateXYZ)) {
node = graph->create_node<SeparateXYZNode>();
}
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index d97854a52d0..473bdb67920 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -145,6 +145,7 @@ set(SRC_KERNEL_SVM_HEADERS
svm/normal.h
svm/ramp.h
svm/ramp_util.h
+ svm/sepcomb_color.h
svm/sepcomb_hsv.h
svm/sepcomb_vector.h
svm/sky.h
diff --git a/intern/cycles/kernel/osl/shaders/CMakeLists.txt b/intern/cycles/kernel/osl/shaders/CMakeLists.txt
index 7ced21c5670..741bce7c399 100644
--- a/intern/cycles/kernel/osl/shaders/CMakeLists.txt
+++ b/intern/cycles/kernel/osl/shaders/CMakeLists.txt
@@ -16,6 +16,7 @@ set(SRC_OSL
node_camera.osl
node_checker_texture.osl
node_clamp.osl
+ node_combine_color.osl
node_combine_rgb.osl
node_combine_hsv.osl
node_combine_xyz.osl
@@ -68,6 +69,7 @@ set(SRC_OSL
node_refraction_bsdf.osl
node_rgb_curves.osl
node_rgb_ramp.osl
+ node_separate_color.osl
node_separate_rgb.osl
node_separate_hsv.osl
node_separate_xyz.osl
diff --git a/intern/cycles/kernel/osl/shaders/node_color.h b/intern/cycles/kernel/osl/shaders/node_color.h
index 388dd114e9a..06735f5b03d 100644
--- a/intern/cycles/kernel/osl/shaders/node_color.h
+++ b/intern/cycles/kernel/osl/shaders/node_color.h
@@ -148,3 +148,53 @@ color hsv_to_rgb(color hsv)
return rgb;
}
+
+color rgb_to_hsl(color rgb)
+{
+ float cmax, cmin, h, s, l;
+
+ cmax = max(rgb[0], max(rgb[1], rgb[2]));
+ cmin = min(rgb[0], min(rgb[1], rgb[2]));
+ l = min(1.0, (cmax + cmin) / 2.0);
+
+ if (cmax == cmin) {
+ h = s = 0.0; /* achromatic */
+ }
+ else {
+ float cdelta = cmax - cmin;
+ s = l > 0.5 ? cdelta / (2.0 - cmax - cmin) : cdelta / (cmax + cmin);
+ if (cmax == rgb[0]) {
+ h = (rgb[1] - rgb[2]) / cdelta + (rgb[1] < rgb[2] ? 6.0 : 0.0);
+ }
+ else if (cmax == rgb[1]) {
+ h = (rgb[2] - rgb[0]) / cdelta + 2.0;
+ }
+ else {
+ h = (rgb[0] - rgb[1]) / cdelta + 4.0;
+ }
+ }
+ h /= 6.0;
+
+ return color(h, s, l);
+}
+
+color hsl_to_rgb(color hsl)
+{
+ float nr, ng, nb, chroma, h, s, l;
+
+ h = hsl[0];
+ s = hsl[1];
+ l = hsl[2];
+
+ nr = abs(h * 6.0 - 3.0) - 1.0;
+ ng = 2.0 - abs(h * 6.0 - 2.0);
+ nb = 2.0 - abs(h * 6.0 - 4.0);
+
+ nr = clamp(nr, 0.0, 1.0);
+ nb = clamp(nb, 0.0, 1.0);
+ ng = clamp(ng, 0.0, 1.0);
+
+ chroma = (1.0 - abs(2.0 * l - 1.0)) * s;
+
+ return color((nr - 0.5) * chroma + l, (ng - 0.5) * chroma + l, (nb - 0.5) * chroma + l);
+}
diff --git a/intern/cycles/kernel/osl/shaders/node_combine_color.osl b/intern/cycles/kernel/osl/shaders/node_combine_color.osl
new file mode 100644
index 00000000000..94d624d82ad
--- /dev/null
+++ b/intern/cycles/kernel/osl/shaders/node_combine_color.osl
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright 2011-2022 Blender Foundation */
+
+#include "stdcycles.h"
+
+shader node_combine_color(string color_type = "rgb", float Red = 0.0, float Green = 0.0, float Blue = 0.0, output color Color = 0.8)
+{
+ if (color_type == "rgb" || color_type == "hsv" || color_type == "hsl")
+ Color = color(color_type, Red, Green, Blue);
+ else
+ warning("%s", "Unknown color space!");
+}
diff --git a/intern/cycles/kernel/osl/shaders/node_separate_color.osl b/intern/cycles/kernel/osl/shaders/node_separate_color.osl
new file mode 100644
index 00000000000..cba2d85da05
--- /dev/null
+++ b/intern/cycles/kernel/osl/shaders/node_separate_color.osl
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright 2011-2022 Blender Foundation */
+
+#include "node_color.h"
+#include "stdcycles.h"
+
+shader node_separate_color(string color_type = "rgb",
+ color Color = 0.8,
+ output float Red = 0.0,
+ output float Green = 0.0,
+ output float Blue = 0.0)
+{
+ color col;
+ if (color_type == "rgb")
+ col = Color;
+ else if (color_type == "hsv")
+ col = rgb_to_hsv(Color);
+ else if (color_type == "hsl")
+ col = rgb_to_hsl(Color);
+ else
+ warning("%s", "Unknown color space!");
+
+ Red = col[0];
+ Green = col[1];
+ Blue = col[2];
+}
diff --git a/intern/cycles/kernel/svm/color_util.h b/intern/cycles/kernel/svm/color_util.h
index b439721383c..fa22d4bc8c2 100644
--- a/intern/cycles/kernel/svm/color_util.h
+++ b/intern/cycles/kernel/svm/color_util.h
@@ -307,4 +307,30 @@ ccl_device_inline float3 svm_brightness_contrast(float3 color, float brightness,
return color;
}
+ccl_device float3 svm_combine_color(NodeCombSepColorType type, float3 color)
+{
+ switch (type) {
+ case NODE_COMBSEP_COLOR_HSV:
+ return hsv_to_rgb(color);
+ case NODE_COMBSEP_COLOR_HSL:
+ return hsl_to_rgb(color);
+ case NODE_COMBSEP_COLOR_RGB:
+ default:
+ return color;
+ }
+}
+
+ccl_device float3 svm_separate_color(NodeCombSepColorType type, float3 color)
+{
+ switch (type) {
+ case NODE_COMBSEP_COLOR_HSV:
+ return rgb_to_hsv(color);
+ case NODE_COMBSEP_COLOR_HSL:
+ return rgb_to_hsl(color);
+ case NODE_COMBSEP_COLOR_RGB:
+ default:
+ return color;
+ }
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/sepcomb_color.h b/intern/cycles/kernel/svm/sepcomb_color.h
new file mode 100644
index 00000000000..a1a8cdfd9b0
--- /dev/null
+++ b/intern/cycles/kernel/svm/sepcomb_color.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright 2011-2022 Blender Foundation */
+
+#pragma once
+
+CCL_NAMESPACE_BEGIN
+
+ccl_device_noinline void svm_node_combine_color(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ ccl_private float *stack,
+ uint color_type,
+ uint inputs_stack_offsets,
+ uint result_stack_offset)
+{
+ uint red_stack_offset, green_stack_offset, blue_stack_offset;
+ svm_unpack_node_uchar3(inputs_stack_offsets, &red_stack_offset, &green_stack_offset, &blue_stack_offset);
+
+ float r = stack_load_float(stack, red_stack_offset);
+ float g = stack_load_float(stack, green_stack_offset);
+ float b = stack_load_float(stack, blue_stack_offset);
+
+ /* Combine, and convert back to RGB */
+ float3 color = svm_combine_color((NodeCombSepColorType)color_type, make_float3(r, g, b));
+
+ if (stack_valid(result_stack_offset))
+ stack_store_float3(stack, result_stack_offset, color);
+}
+
+ccl_device_noinline void svm_node_separate_color(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ ccl_private float *stack,
+ uint color_type,
+ uint input_stack_offset,
+ uint results_stack_offsets)
+{
+ float3 color = stack_load_float3(stack, input_stack_offset);
+
+ /* Convert color space */
+ color = svm_separate_color((NodeCombSepColorType)color_type, color);
+
+ uint red_stack_offset, green_stack_offset, blue_stack_offset;
+ svm_unpack_node_uchar3(
+ results_stack_offsets, &red_stack_offset, &green_stack_offset, &blue_stack_offset);
+
+ if (stack_valid(red_stack_offset))
+ stack_store_float(stack, red_stack_offset, color.x);
+ if (stack_valid(green_stack_offset))
+ stack_store_float(stack, green_stack_offset, color.y);
+ if (stack_valid(blue_stack_offset))
+ stack_store_float(stack, blue_stack_offset, color.z);
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h
index 6b969da7e52..293501946c4 100644
--- a/intern/cycles/kernel/svm/svm.h
+++ b/intern/cycles/kernel/svm/svm.h
@@ -181,6 +181,7 @@ CCL_NAMESPACE_END
#include "kernel/svm/noisetex.h"
#include "kernel/svm/normal.h"
#include "kernel/svm/ramp.h"
+#include "kernel/svm/sepcomb_color.h"
#include "kernel/svm/sepcomb_hsv.h"
#include "kernel/svm/sepcomb_vector.h"
#include "kernel/svm/sky.h"
@@ -520,6 +521,12 @@ ccl_device void svm_eval_nodes(KernelGlobals kg,
case NODE_MIX:
offset = svm_node_mix(kg, sd, stack, node.y, node.z, node.w, offset);
break;
+ case NODE_SEPARATE_COLOR:
+ svm_node_separate_color(kg, sd, stack, node.y, node.z, node.w);
+ break;
+ case NODE_COMBINE_COLOR:
+ svm_node_combine_color(kg, sd, stack, node.y, node.z, node.w);
+ break;
case NODE_SEPARATE_VECTOR:
svm_node_separate_vector(sd, stack, node.y, node.z, node.w);
break;
diff --git a/intern/cycles/kernel/svm/types.h b/intern/cycles/kernel/svm/types.h
index bede58f7a54..82109ec4c4f 100644
--- a/intern/cycles/kernel/svm/types.h
+++ b/intern/cycles/kernel/svm/types.h
@@ -92,6 +92,8 @@ typedef enum ShaderNodeType {
NODE_NORMAL_MAP,
NODE_INVERT,
NODE_MIX,
+ NODE_SEPARATE_COLOR,
+ NODE_COMBINE_COLOR,
NODE_SEPARATE_VECTOR,
NODE_COMBINE_VECTOR,
NODE_SEPARATE_HSV,
@@ -487,6 +489,12 @@ typedef enum NodePrincipledHairParametrization {
NODE_PRINCIPLED_HAIR_NUM,
} NodePrincipledHairParametrization;
+typedef enum NodeCombSepColorType {
+ NODE_COMBSEP_COLOR_RGB,
+ NODE_COMBSEP_COLOR_HSV,
+ NODE_COMBSEP_COLOR_HSL,
+} NodeCombSepColorType;
+
/* Closure */
typedef enum ClosureType {
diff --git a/intern/cycles/scene/shader_nodes.cpp b/intern/cycles/scene/shader_nodes.cpp
index 95fccf725f3..06a2052d4cb 100644
--- a/intern/cycles/scene/shader_nodes.cpp
+++ b/intern/cycles/scene/shader_nodes.cpp
@@ -5010,6 +5010,63 @@ void MixNode::constant_fold(const ConstantFolder &folder)
}
}
+/* Combine Color */
+
+NODE_DEFINE(CombineColorNode)
+{
+ NodeType *type = NodeType::add("combine_color", create, NodeType::SHADER);
+
+ static NodeEnum type_enum;
+ type_enum.insert("rgb", NODE_COMBSEP_COLOR_RGB);
+ type_enum.insert("hsv", NODE_COMBSEP_COLOR_HSV);
+ type_enum.insert("hsl", NODE_COMBSEP_COLOR_HSL);
+ SOCKET_ENUM(color_type, "Type", type_enum, NODE_COMBSEP_COLOR_RGB);
+
+ SOCKET_IN_FLOAT(r, "Red", 0.0f);
+ SOCKET_IN_FLOAT(g, "Green", 0.0f);
+ SOCKET_IN_FLOAT(b, "Blue", 0.0f);
+
+ SOCKET_OUT_COLOR(color, "Color");
+
+ return type;
+}
+
+CombineColorNode::CombineColorNode() : ShaderNode(get_node_type())
+{
+}
+
+void CombineColorNode::constant_fold(const ConstantFolder &folder)
+{
+ if (folder.all_inputs_constant()) {
+ folder.make_constant(svm_combine_color(color_type, make_float3(r, g, b)));
+ }
+}
+
+void CombineColorNode::compile(SVMCompiler &compiler)
+{
+ ShaderInput *red_in = input("Red");
+ ShaderInput *green_in = input("Green");
+ ShaderInput *blue_in = input("Blue");
+ ShaderOutput *color_out = output("Color");
+
+ int red_stack_offset = compiler.stack_assign(red_in);
+ int green_stack_offset = compiler.stack_assign(green_in);
+ int blue_stack_offset = compiler.stack_assign(blue_in);
+ int color_stack_offset = compiler.stack_assign(color_out);
+
+ compiler.add_node(
+ NODE_COMBINE_COLOR,
+ color_type,
+ compiler.encode_uchar4(red_stack_offset, green_stack_offset, blue_stack_offset),
+ color_stack_offset);
+}
+
+void CombineColorNode::compile(OSLCompiler &compiler)
+{
+ compiler.parameter(this, "color_type");
+ compiler.add(this, "node_combine_color");
+}
+
/* Combine RGB */
NODE_DEFINE(CombineRGBNode)
@@ -5250,6 +5307,70 @@ void BrightContrastNode::compile(OSLCompiler &compiler)
compiler.add(this, "node_brightness");
}
+/* Separate Color */
+
+NODE_DEFINE(SeparateColorNode)
+{
+ NodeType *type = NodeType::add("separate_color", create, NodeType::SHADER);
+
+ static NodeEnum type_enum;
+ type_enum.insert("rgb", NODE_COMBSEP_COLOR_RGB);
+ type_enum.insert("hsv", NODE_COMBSEP_COLOR_HSV);
+ type_enum.insert("hsl", NODE_COMBSEP_COLOR_HSL);
+ SOCKET_ENUM(color_type, "Type", type_enum, NODE_COMBSEP_COLOR_RGB);
+
+ SOCKET_IN_COLOR(color, "Color", zero_float3());
+
+ SOCKET_OUT_FLOAT(r, "Red");
+ SOCKET_OUT_FLOAT(g, "Green");
+ SOCKET_OUT_FLOAT(b, "Blue");
+
+ return type;
+}
+
+SeparateColorNode::SeparateColorNode() : ShaderNode(get_node_type())
+{
+}
+
+void SeparateColorNode::constant_fold(const ConstantFolder &folder)
+{
+ if (folder.all_inputs_constant()) {
+ float3 col = svm_separate_color(color_type, color);
+
+ for (int channel = 0; channel < 3; channel++) {
+ if (outputs[channel] == folder.output) {
+ folder.make_constant(col[channel]);
+ return;
+ }
+ }
+ }
+}
+
+void SeparateColorNode::compile(SVMCompiler &compiler)
+{
+ ShaderInput *color_in = input("Color");
+ ShaderOutput *red_out = output("Red");
+ ShaderOutput *green_out = output("Green");
+ ShaderOutput *blue_out = output("Blue");
+
+ int color_stack_offset = compiler.stack_assign(color_in);
+ int red_stack_offset = compiler.stack_assign(red_out);
+ int green_stack_offset = compiler.stack_assign(green_out);
+ int blue_stack_offset = compiler.stack_assign(blue_out);
+
+ compiler.add_node(
+ NODE_SEPARATE_COLOR,
+ color_type,
+ color_stack_offset,
+ compiler.encode_uchar4(red_stack_offset, green_stack_offset, blue_stack_offset));
+}
+
+void SeparateColorNode::compile(OSLCompiler &compiler)
+{
+ compiler.parameter(this, "color_type");
+ compiler.add(this, "node_separate_color");
+}
+
/* Separate RGB */
NODE_DEFINE(SeparateRGBNode)
diff --git a/intern/cycles/scene/shader_nodes.h b/intern/cycles/scene/shader_nodes.h
index 9aef5d3151f..ac40a397c1e 100644
--- a/intern/cycles/scene/shader_nodes.h
+++ b/intern/cycles/scene/shader_nodes.h
@@ -1101,6 +1101,17 @@ class MixNode : public ShaderNode {
NODE_SOCKET_API(float, fac)
};
+class CombineColorNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(CombineColorNode)
+ void constant_fold(const ConstantFolder &folder);
+
+ NODE_SOCKET_API(NodeCombSepColorType, color_type)
+ NODE_SOCKET_API(float, r)
+ NODE_SOCKET_API(float, g)
+ NODE_SOCKET_API(float, b)
+};
+
class CombineRGBNode : public ShaderNode {
public:
SHADER_NODE_CLASS(CombineRGBNode)
@@ -1150,6 +1161,15 @@ class BrightContrastNode : public ShaderNode {
NODE_SOCKET_API(float, contrast)
};
+class SeparateColorNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(SeparateColorNode)
+ void constant_fold(const ConstantFolder &folder);
+
+ NODE_SOCKET_API(NodeCombSepColorType, color_type)
+ NODE_SOCKET_API(float3, color)
+};
+
class SeparateRGBNode : public ShaderNode {
public:
SHADER_NODE_CLASS(SeparateRGBNode)
diff --git a/intern/cycles/util/color.h b/intern/cycles/util/color.h
index cccccde3ba6..a390b49cf7b 100644
--- a/intern/cycles/util/color.h
+++ b/intern/cycles/util/color.h
@@ -152,6 +152,55 @@ ccl_device float3 hsv_to_rgb(float3 hsv)
return rgb;
}
+ccl_device float3 rgb_to_hsl(float3 rgb)
+{
+ float cmax, cmin, h, s, l;
+
+ cmax = fmaxf(rgb.x, fmaxf(rgb.y, rgb.z));
+ cmin = min(rgb.x, min(rgb.y, rgb.z));
+ l = min(1.0f, (cmax + cmin) / 2.0f);
+
+ if (cmax == cmin) {
+ h = s = 0.0f; /* achromatic */
+ } else {
+ float cdelta = cmax - cmin;
+ s = l > 0.5f ? cdelta / (2.0f - cmax - cmin) : cdelta / (cmax + cmin);
+ if (cmax == rgb.x) {
+ h = (rgb.y - rgb.z) / cdelta + (rgb.y < rgb.z ? 6.0f : 0.0f);
+ }
+ else if (cmax == rgb.y) {
+ h = (rgb.z - rgb.x) / cdelta + 2.0f;
+ }
+ else {
+ h = (rgb.x - rgb.y) / cdelta + 4.0f;
+ }
+ }
+ h /= 6.0f;
+
+ return make_float3(h, s, l);
+}
+
+ccl_device float3 hsl_to_rgb(float3 hsl)
+{
+ float nr, ng, nb, chroma, h, s, l;
+
+ h = hsl.x;
+ s = hsl.y;
+ l = hsl.z;
+
+ nr = fabsf(h * 6.0f - 3.0f) - 1.0f;
+ ng = 2.0f - fabsf(h * 6.0f - 2.0f);
+ nb = 2.0f - fabsf(h * 6.0f - 4.0f);
+
+ nr = clamp(nr, 0.0f, 1.0f);
+ nb = clamp(nb, 0.0f, 1.0f);
+ ng = clamp(ng, 0.0f, 1.0f);
+
+ chroma = (1.0f - fabsf(2.0f * l - 1.0f)) * s;
+
+ return make_float3((nr - 0.5f) * chroma + l, (ng - 0.5f) * chroma + l, (nb - 0.5f) * chroma + l);
+}
+
ccl_device float3 xyY_to_xyz(float x, float y, float Y)
{
float X, Z;
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index 4f94184f006..817c53cca62 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -419,12 +419,10 @@ shader_node_categories = [
NodeItem("ShaderNodeRGBToBW"),
NodeItem("ShaderNodeShaderToRGB", poll=object_eevee_shader_nodes_poll),
NodeItem("ShaderNodeVectorMath"),
- NodeItem("ShaderNodeSeparateRGB"),
- NodeItem("ShaderNodeCombineRGB"),
+ NodeItem("ShaderNodeSeparateColor"),
+ NodeItem("ShaderNodeCombineColor"),
NodeItem("ShaderNodeSeparateXYZ"),
NodeItem("ShaderNodeCombineXYZ"),
- NodeItem("ShaderNodeSeparateHSV"),
- NodeItem("ShaderNodeCombineHSV"),
NodeItem("ShaderNodeWavelength"),
NodeItem("ShaderNodeBlackbody"),
]),
@@ -483,14 +481,8 @@ compositor_node_categories = [
NodeItem("CompositorNodePremulKey"),
NodeItem("CompositorNodeIDMask"),
NodeItem("CompositorNodeRGBToBW"),
- NodeItem("CompositorNodeSepRGBA"),
- NodeItem("CompositorNodeCombRGBA"),
- NodeItem("CompositorNodeSepHSVA"),
- NodeItem("CompositorNodeCombHSVA"),
- NodeItem("CompositorNodeSepYUVA"),
- NodeItem("CompositorNodeCombYUVA"),
- NodeItem("CompositorNodeSepYCCA"),
- NodeItem("CompositorNodeCombYCCA"),
+ NodeItem("CompositorNodeSeparateColor"),
+ NodeItem("CompositorNodeCombineColor"),
NodeItem("CompositorNodeSeparateXYZ"),
NodeItem("CompositorNodeCombineXYZ"),
NodeItem("CompositorNodeSwitchView"),
@@ -576,8 +568,8 @@ texture_node_categories = [
NodeItem("TextureNodeCurveRGB"),
NodeItem("TextureNodeInvert"),
NodeItem("TextureNodeHueSaturation"),
- NodeItem("TextureNodeCompose"),
- NodeItem("TextureNodeDecompose"),
+ NodeItem("TextureNodeCombineColor"),
+ NodeItem("TextureNodeSeparateColor"),
]),
TextureNodeCategory("TEX_PATTERN", "Pattern", items=[
NodeItem("TextureNodeChecker"),
@@ -629,8 +621,8 @@ geometry_node_categories = [
NodeItem("ShaderNodeMixRGB"),
NodeItem("ShaderNodeRGBCurve"),
NodeItem("ShaderNodeValToRGB"),
- NodeItem("ShaderNodeSeparateRGB"),
- NodeItem("ShaderNodeCombineRGB"),
+ NodeItem("FunctionNodeSeparateColor"),
+ NodeItem("FunctionNodeCombineColor"),
]),
GeometryNodeCategory("GEO_CURVE", "Curve", items=curve_node_items),
GeometryNodeCategory("GEO_PRIMITIVES_CURVE", "Curve Primitives", items=[
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index c9228db9ecc..1ff10d06b00 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -1090,8 +1090,8 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
#define SH_NODE_SQUEEZE 117
//#define SH_NODE_MATERIAL_EXT 118
#define SH_NODE_INVERT 119
-#define SH_NODE_SEPRGB 120
-#define SH_NODE_COMBRGB 121
+#define SH_NODE_SEPRGB_LEGACY 120
+#define SH_NODE_COMBRGB_LEGACY 121
#define SH_NODE_HUE_SAT 122
#define SH_NODE_OUTPUT_MATERIAL 124
@@ -1147,8 +1147,8 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
#define SH_NODE_WAVELENGTH 180
#define SH_NODE_BLACKBODY 181
#define SH_NODE_VECT_TRANSFORM 182
-#define SH_NODE_SEPHSV 183
-#define SH_NODE_COMBHSV 184
+#define SH_NODE_SEPHSV_LEGACY 183
+#define SH_NODE_COMBHSV_LEGACY 184
#define SH_NODE_BSDF_HAIR 185
// #define SH_NODE_LAMP 186
#define SH_NODE_UVMAP 187
@@ -1175,6 +1175,8 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
#define SH_NODE_VECTOR_ROTATE 708
#define SH_NODE_CURVE_FLOAT 709
#define SH_NODE_POINT_INFO 710
+#define SH_NODE_COMBINE_COLOR 711
+#define SH_NODE_SEPARATE_COLOR 712
/** \} */
@@ -1202,8 +1204,8 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
#define CMP_NODE_MAP_VALUE 213
#define CMP_NODE_TIME 214
#define CMP_NODE_VECBLUR 215
-#define CMP_NODE_SEPRGBA 216
-#define CMP_NODE_SEPHSVA 217
+#define CMP_NODE_SEPRGBA_LEGACY 216
+#define CMP_NODE_SEPHSVA_LEGACY 217
#define CMP_NODE_SETALPHA 218
#define CMP_NODE_HUE_SAT 219
#define CMP_NODE_IMAGE 220
@@ -1213,14 +1215,14 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
#define CMP_NODE_TEXTURE 224
#define CMP_NODE_TRANSLATE 225
#define CMP_NODE_ZCOMBINE 226
-#define CMP_NODE_COMBRGBA 227
+#define CMP_NODE_COMBRGBA_LEGACY 227
#define CMP_NODE_DILATEERODE 228
#define CMP_NODE_ROTATE 229
#define CMP_NODE_SCALE 230
-#define CMP_NODE_SEPYCCA 231
-#define CMP_NODE_COMBYCCA 232
-#define CMP_NODE_SEPYUVA 233
-#define CMP_NODE_COMBYUVA 234
+#define CMP_NODE_SEPYCCA_LEGACY 231
+#define CMP_NODE_COMBYCCA_LEGACY 232
+#define CMP_NODE_SEPYUVA_LEGACY 233
+#define CMP_NODE_COMBYUVA_LEGACY 234
#define CMP_NODE_DIFF_MATTE 235
#define CMP_NODE_COLOR_SPILL 236
#define CMP_NODE_CHROMA_MATTE 237
@@ -1232,7 +1234,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
#define CMP_NODE_ID_MASK 243
#define CMP_NODE_DEFOCUS 244
#define CMP_NODE_DISPLACE 245
-#define CMP_NODE_COMBHSVA 246
+#define CMP_NODE_COMBHSVA_LEGACY 246
#define CMP_NODE_MATH 247
#define CMP_NODE_LUMA_MATTE 248
#define CMP_NODE_BRIGHTCONTRAST 249
@@ -1289,6 +1291,8 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
#define CMP_NODE_SCENE_TIME 329
#define CMP_NODE_SEPARATE_XYZ 330
#define CMP_NODE_COMBINE_XYZ 331
+#define CMP_NODE_COMBINE_COLOR 332
+#define CMP_NODE_SEPARATE_COLOR 333
/* channel toggles */
#define CMP_CHAN_RGB 1
@@ -1354,11 +1358,13 @@ struct TexResult;
#define TEX_NODE_TRANSLATE 416
#define TEX_NODE_COORD 417
#define TEX_NODE_DISTANCE 418
-#define TEX_NODE_COMPOSE 419
-#define TEX_NODE_DECOMPOSE 420
+#define TEX_NODE_COMPOSE_LEGACY 419
+#define TEX_NODE_DECOMPOSE_LEGACY 420
#define TEX_NODE_VALTONOR 421
#define TEX_NODE_SCALE 422
#define TEX_NODE_AT 423
+#define TEX_NODE_COMBINE_COLOR 424
+#define TEX_NODE_SEPARATE_COLOR 425
/* 501-599 reserved. Use like this: TEX_NODE_PROC + TEX_CLOUDS, etc */
#define TEX_NODE_PROC 500
@@ -1511,6 +1517,8 @@ struct TexResult;
#define FN_NODE_REPLACE_STRING 1218
#define FN_NODE_INPUT_BOOL 1219
#define FN_NODE_INPUT_INT 1220
+#define FN_NODE_SEPARATE_COLOR 1221
+#define FN_NODE_COMBINE_COLOR 1222
/** \} */
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index 200eefb73ec..ffa39f79e7c 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -4502,6 +4502,8 @@ static void registerCompositNodes()
register_node_type_cmp_premulkey();
register_node_type_cmp_separate_xyz();
register_node_type_cmp_combine_xyz();
+ register_node_type_cmp_separate_color();
+ register_node_type_cmp_combine_color();
register_node_type_cmp_diff_matte();
register_node_type_cmp_distance_matte();
@@ -4574,6 +4576,8 @@ static void registerShaderNodes()
register_node_type_sh_vect_transform();
register_node_type_sh_squeeze();
register_node_type_sh_invert();
+ register_node_type_sh_sepcolor();
+ register_node_type_sh_combcolor();
register_node_type_sh_seprgb();
register_node_type_sh_combrgb();
register_node_type_sh_sephsv();
@@ -4660,6 +4664,8 @@ static void registerTextureNodes()
register_node_type_tex_distance();
register_node_type_tex_compose();
register_node_type_tex_decompose();
+ register_node_type_tex_combine_color();
+ register_node_type_tex_separate_color();
register_node_type_tex_output();
register_node_type_tex_viewer();
@@ -4821,6 +4827,7 @@ static void registerFunctionNodes()
{
register_node_type_fn_align_euler_to_vector();
register_node_type_fn_boolean_math();
+ register_node_type_fn_combine_color();
register_node_type_fn_compare();
register_node_type_fn_float_to_int();
register_node_type_fn_input_bool();
@@ -4832,6 +4839,7 @@ static void registerFunctionNodes()
register_node_type_fn_random_value();
register_node_type_fn_replace_string();
register_node_type_fn_rotate_euler();
+ register_node_type_fn_separate_color();
register_node_type_fn_slice_string();
register_node_type_fn_string_length();
register_node_type_fn_value_to_string();
diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c
index aeeaf47d813..07e9eaf0f42 100644
--- a/source/blender/blenlib/intern/math_color.c
+++ b/source/blender/blenlib/intern/math_color.c
@@ -238,7 +238,7 @@ void rgb_to_hsl(float r, float g, float b, float *r_h, float *r_s, float *r_l)
{
const float cmax = max_fff(r, g, b);
const float cmin = min_fff(r, g, b);
- float h, s, l = min_ff(1.0, (cmax + cmin) / 2.0f);
+ float h, s, l = min_ff(1.0f, (cmax + cmin) / 2.0f);
if (cmax == cmin) {
h = s = 0.0f; /* achromatic */
diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c
index e6a214452fe..0a69ef5f7cd 100644
--- a/source/blender/blenloader/intern/versioning_300.c
+++ b/source/blender/blenloader/intern/versioning_300.c
@@ -2772,5 +2772,250 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
*/
{
/* Keep this block, even when empty. */
+
+ /* Replace legacy combine/separate color nodes */
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ /* In geometry nodes, replace shader combine/separate color nodes with function nodes */
+ if (ntree->type == NTREE_GEOMETRY) {
+ version_node_input_socket_name(ntree, SH_NODE_COMBRGB_LEGACY, "R", "Red");
+ version_node_input_socket_name(ntree, SH_NODE_COMBRGB_LEGACY, "G", "Green");
+ version_node_input_socket_name(ntree, SH_NODE_COMBRGB_LEGACY, "B", "Blue");
+ version_node_output_socket_name(ntree, SH_NODE_COMBRGB_LEGACY, "Image", "Color");
+
+ version_node_output_socket_name(ntree, SH_NODE_SEPRGB_LEGACY, "R", "Red");
+ version_node_output_socket_name(ntree, SH_NODE_SEPRGB_LEGACY, "G", "Green");
+ version_node_output_socket_name(ntree, SH_NODE_SEPRGB_LEGACY, "B", "Blue");
+ version_node_input_socket_name(ntree, SH_NODE_SEPRGB_LEGACY, "Image", "Color");
+
+ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
+ switch (node->type) {
+ case SH_NODE_COMBRGB_LEGACY: {
+ node->type = FN_NODE_COMBINE_COLOR;
+ NodeCombSepColor *storage = (NodeCombSepColor *)MEM_callocN(sizeof(NodeCombSepColor),
+ __func__);
+ storage->mode = NODE_COMBSEP_COLOR_RGB;
+ strcpy(node->idname, "FunctionNodeCombineColor");
+ node->storage = storage;
+ break;
+ }
+ case SH_NODE_SEPRGB_LEGACY: {
+ node->type = FN_NODE_SEPARATE_COLOR;
+ NodeCombSepColor *storage = (NodeCombSepColor *)MEM_callocN(sizeof(NodeCombSepColor),
+ __func__);
+ storage->mode = NODE_COMBSEP_COLOR_RGB;
+ strcpy(node->idname, "FunctionNodeSeparateColor");
+ node->storage = storage;
+ break;
+ }
+ }
+ }
+ }
+
+ /* In compositing nodes, replace combine/separate RGBA/HSVA/YCbCrA/YCCA nodes with
+ * combine/separate color */
+ if (ntree->type == NTREE_COMPOSIT) {
+ version_node_input_socket_name(ntree, CMP_NODE_COMBRGBA_LEGACY, "R", "Red");
+ version_node_input_socket_name(ntree, CMP_NODE_COMBRGBA_LEGACY, "G", "Green");
+ version_node_input_socket_name(ntree, CMP_NODE_COMBRGBA_LEGACY, "B", "Blue");
+ version_node_input_socket_name(ntree, CMP_NODE_COMBRGBA_LEGACY, "A", "Alpha");
+
+ version_node_input_socket_name(ntree, CMP_NODE_COMBHSVA_LEGACY, "H", "Red");
+ version_node_input_socket_name(ntree, CMP_NODE_COMBHSVA_LEGACY, "S", "Green");
+ version_node_input_socket_name(ntree, CMP_NODE_COMBHSVA_LEGACY, "V", "Blue");
+ version_node_input_socket_name(ntree, CMP_NODE_COMBHSVA_LEGACY, "A", "Alpha");
+
+ version_node_input_socket_name(ntree, CMP_NODE_COMBYCCA_LEGACY, "Y", "Red");
+ version_node_input_socket_name(ntree, CMP_NODE_COMBYCCA_LEGACY, "Cb", "Green");
+ version_node_input_socket_name(ntree, CMP_NODE_COMBYCCA_LEGACY, "Cr", "Blue");
+ version_node_input_socket_name(ntree, CMP_NODE_COMBYCCA_LEGACY, "A", "Alpha");
+
+ version_node_input_socket_name(ntree, CMP_NODE_COMBYUVA_LEGACY, "Y", "Red");
+ version_node_input_socket_name(ntree, CMP_NODE_COMBYUVA_LEGACY, "U", "Green");
+ version_node_input_socket_name(ntree, CMP_NODE_COMBYUVA_LEGACY, "V", "Blue");
+ version_node_input_socket_name(ntree, CMP_NODE_COMBYUVA_LEGACY, "A", "Alpha");
+
+ version_node_output_socket_name(ntree, CMP_NODE_SEPRGBA_LEGACY, "R", "Red");
+ version_node_output_socket_name(ntree, CMP_NODE_SEPRGBA_LEGACY, "G", "Green");
+ version_node_output_socket_name(ntree, CMP_NODE_SEPRGBA_LEGACY, "B", "Blue");
+ version_node_output_socket_name(ntree, CMP_NODE_SEPRGBA_LEGACY, "A", "Alpha");
+
+ version_node_output_socket_name(ntree, CMP_NODE_SEPHSVA_LEGACY, "H", "Red");
+ version_node_output_socket_name(ntree, CMP_NODE_SEPHSVA_LEGACY, "S", "Green");
+ version_node_output_socket_name(ntree, CMP_NODE_SEPHSVA_LEGACY, "V", "Blue");
+ version_node_output_socket_name(ntree, CMP_NODE_SEPHSVA_LEGACY, "A", "Alpha");
+
+ version_node_output_socket_name(ntree, CMP_NODE_SEPYCCA_LEGACY, "Y", "Red");
+ version_node_output_socket_name(ntree, CMP_NODE_SEPYCCA_LEGACY, "Cb", "Green");
+ version_node_output_socket_name(ntree, CMP_NODE_SEPYCCA_LEGACY, "Cr", "Blue");
+ version_node_output_socket_name(ntree, CMP_NODE_SEPYCCA_LEGACY, "A", "Alpha");
+
+ version_node_output_socket_name(ntree, CMP_NODE_SEPYUVA_LEGACY, "Y", "Red");
+ version_node_output_socket_name(ntree, CMP_NODE_SEPYUVA_LEGACY, "U", "Green");
+ version_node_output_socket_name(ntree, CMP_NODE_SEPYUVA_LEGACY, "V", "Blue");
+ version_node_output_socket_name(ntree, CMP_NODE_SEPYUVA_LEGACY, "A", "Alpha");
+
+ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
+ switch (node->type) {
+ case CMP_NODE_COMBRGBA_LEGACY: {
+ node->type = CMP_NODE_COMBINE_COLOR;
+ NodeCMPCombSepColor *storage = (NodeCMPCombSepColor *)MEM_callocN(
+ sizeof(NodeCMPCombSepColor), __func__);
+ storage->mode = CMP_NODE_COMBSEP_COLOR_RGB;
+ strcpy(node->idname, "CompositorNodeCombineColor");
+ node->storage = storage;
+ break;
+ }
+ case CMP_NODE_COMBHSVA_LEGACY: {
+ node->type = CMP_NODE_COMBINE_COLOR;
+ NodeCMPCombSepColor *storage = (NodeCMPCombSepColor *)MEM_callocN(
+ sizeof(NodeCMPCombSepColor), __func__);
+ storage->mode = CMP_NODE_COMBSEP_COLOR_HSV;
+ strcpy(node->idname, "CompositorNodeCombineColor");
+ node->storage = storage;
+ break;
+ }
+ case CMP_NODE_COMBYCCA_LEGACY: {
+ node->type = CMP_NODE_COMBINE_COLOR;
+ NodeCMPCombSepColor *storage = (NodeCMPCombSepColor *)MEM_callocN(
+ sizeof(NodeCMPCombSepColor), __func__);
+ storage->mode = CMP_NODE_COMBSEP_COLOR_YCC;
+ storage->ycc_mode = node->custom1;
+ strcpy(node->idname, "CompositorNodeCombineColor");
+ node->storage = storage;
+ break;
+ }
+ case CMP_NODE_COMBYUVA_LEGACY: {
+ node->type = CMP_NODE_COMBINE_COLOR;
+ NodeCMPCombSepColor *storage = (NodeCMPCombSepColor *)MEM_callocN(
+ sizeof(NodeCMPCombSepColor), __func__);
+ storage->mode = CMP_NODE_COMBSEP_COLOR_YUV;
+ strcpy(node->idname, "CompositorNodeCombineColor");
+ node->storage = storage;
+ break;
+ }
+ case CMP_NODE_SEPRGBA_LEGACY: {
+ node->type = CMP_NODE_SEPARATE_COLOR;
+ NodeCMPCombSepColor *storage = (NodeCMPCombSepColor *)MEM_callocN(
+ sizeof(NodeCMPCombSepColor), __func__);
+ storage->mode = CMP_NODE_COMBSEP_COLOR_RGB;
+ strcpy(node->idname, "CompositorNodeSeparateColor");
+ node->storage = storage;
+ break;
+ }
+ case CMP_NODE_SEPHSVA_LEGACY: {
+ node->type = CMP_NODE_SEPARATE_COLOR;
+ NodeCMPCombSepColor *storage = (NodeCMPCombSepColor *)MEM_callocN(
+ sizeof(NodeCMPCombSepColor), __func__);
+ storage->mode = CMP_NODE_COMBSEP_COLOR_HSV;
+ strcpy(node->idname, "CompositorNodeSeparateColor");
+ node->storage = storage;
+ break;
+ }
+ case CMP_NODE_SEPYCCA_LEGACY: {
+ node->type = CMP_NODE_SEPARATE_COLOR;
+ NodeCMPCombSepColor *storage = (NodeCMPCombSepColor *)MEM_callocN(
+ sizeof(NodeCMPCombSepColor), __func__);
+ storage->mode = CMP_NODE_COMBSEP_COLOR_YCC;
+ storage->ycc_mode = node->custom1;
+ strcpy(node->idname, "CompositorNodeSeparateColor");
+ node->storage = storage;
+ break;
+ }
+ case CMP_NODE_SEPYUVA_LEGACY: {
+ node->type = CMP_NODE_SEPARATE_COLOR;
+ NodeCMPCombSepColor *storage = (NodeCMPCombSepColor *)MEM_callocN(
+ sizeof(NodeCMPCombSepColor), __func__);
+ storage->mode = CMP_NODE_COMBSEP_COLOR_YUV;
+ strcpy(node->idname, "CompositorNodeSeparateColor");
+ node->storage = storage;
+ break;
+ }
+ }
+ }
+ }
+
+ /* In texture nodes, replace combine/separate RGBA with combine/separate color */
+ if (ntree->type == NTREE_TEXTURE) {
+ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
+ switch (node->type) {
+ case TEX_NODE_COMPOSE_LEGACY: {
+ node->type = TEX_NODE_COMBINE_COLOR;
+ node->custom1 = NODE_COMBSEP_COLOR_RGB;
+ strcpy(node->idname, "TextureNodeCombineColor");
+ break;
+ }
+ case TEX_NODE_DECOMPOSE_LEGACY: {
+ node->type = TEX_NODE_SEPARATE_COLOR;
+ node->custom1 = NODE_COMBSEP_COLOR_RGB;
+ strcpy(node->idname, "TextureNodeSeparateColor");
+ break;
+ }
+ }
+ }
+ }
+
+ /* In shader nodes, replace combine/separate RGB/HSV with combine/separate color */
+ if (ntree->type == NTREE_SHADER) {
+ version_node_input_socket_name(ntree, SH_NODE_COMBRGB_LEGACY, "R", "Red");
+ version_node_input_socket_name(ntree, SH_NODE_COMBRGB_LEGACY, "G", "Green");
+ version_node_input_socket_name(ntree, SH_NODE_COMBRGB_LEGACY, "B", "Blue");
+ version_node_output_socket_name(ntree, SH_NODE_COMBRGB_LEGACY, "Image", "Color");
+
+ version_node_input_socket_name(ntree, SH_NODE_COMBHSV_LEGACY, "H", "Red");
+ version_node_input_socket_name(ntree, SH_NODE_COMBHSV_LEGACY, "S", "Green");
+ version_node_input_socket_name(ntree, SH_NODE_COMBHSV_LEGACY, "V", "Blue");
+
+ version_node_output_socket_name(ntree, SH_NODE_SEPRGB_LEGACY, "R", "Red");
+ version_node_output_socket_name(ntree, SH_NODE_SEPRGB_LEGACY, "G", "Green");
+ version_node_output_socket_name(ntree, SH_NODE_SEPRGB_LEGACY, "B", "Blue");
+ version_node_input_socket_name(ntree, SH_NODE_SEPRGB_LEGACY, "Image", "Color");
+
+ version_node_output_socket_name(ntree, SH_NODE_SEPHSV_LEGACY, "H", "Red");
+ version_node_output_socket_name(ntree, SH_NODE_SEPHSV_LEGACY, "S", "Green");
+ version_node_output_socket_name(ntree, SH_NODE_SEPHSV_LEGACY, "V", "Blue");
+
+ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
+ switch (node->type) {
+ case SH_NODE_COMBRGB_LEGACY: {
+ node->type = SH_NODE_COMBINE_COLOR;
+ NodeCombSepColor *storage = (NodeCombSepColor *)MEM_callocN(sizeof(NodeCombSepColor),
+ __func__);
+ storage->mode = NODE_COMBSEP_COLOR_RGB;
+ strcpy(node->idname, "ShaderNodeCombineColor");
+ node->storage = storage;
+ break;
+ }
+ case SH_NODE_COMBHSV_LEGACY: {
+ node->type = SH_NODE_COMBINE_COLOR;
+ NodeCombSepColor *storage = (NodeCombSepColor *)MEM_callocN(sizeof(NodeCombSepColor),
+ __func__);
+ storage->mode = NODE_COMBSEP_COLOR_HSV;
+ strcpy(node->idname, "ShaderNodeCombineColor");
+ node->storage = storage;
+ break;
+ }
+ case SH_NODE_SEPRGB_LEGACY: {
+ node->type = SH_NODE_SEPARATE_COLOR;
+ NodeCombSepColor *storage = (NodeCombSepColor *)MEM_callocN(sizeof(NodeCombSepColor),
+ __func__);
+ storage->mode = NODE_COMBSEP_COLOR_RGB;
+ strcpy(node->idname, "ShaderNodeSeparateColor");
+ node->storage = storage;
+ break;
+ }
+ case SH_NODE_SEPHSV_LEGACY: {
+ node->type = SH_NODE_SEPARATE_COLOR;
+ NodeCombSepColor *storage = (NodeCombSepColor *)MEM_callocN(sizeof(NodeCombSepColor),
+ __func__);
+ storage->mode = NODE_COMBSEP_COLOR_HSV;
+ strcpy(node->idname, "ShaderNodeSeparateColor");
+ node->storage = storage;
+ break;
+ }
+ }
+ }
+ }
+ }
+ FOREACH_NODETREE_END;
}
}
diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt
index 66f813e02b2..55e349423bb 100644
--- a/source/blender/compositor/CMakeLists.txt
+++ b/source/blender/compositor/CMakeLists.txt
@@ -259,12 +259,16 @@ set(SRC
# converter nodes
nodes/COM_CombineColorNode.cc
nodes/COM_CombineColorNode.h
+ nodes/COM_CombineColorNodeLegacy.cc
+ nodes/COM_CombineColorNodeLegacy.h
nodes/COM_CombineXYZNode.cc
nodes/COM_CombineXYZNode.h
nodes/COM_IDMaskNode.cc
nodes/COM_IDMaskNode.h
nodes/COM_SeparateColorNode.cc
nodes/COM_SeparateColorNode.h
+ nodes/COM_SeparateColorNodeLegacy.cc
+ nodes/COM_SeparateColorNodeLegacy.h
nodes/COM_SeparateXYZNode.cc
nodes/COM_SeparateXYZNode.h
diff --git a/source/blender/compositor/intern/COM_Converter.cc b/source/blender/compositor/intern/COM_Converter.cc
index 13d412a338b..6d7341376e9 100644
--- a/source/blender/compositor/intern/COM_Converter.cc
+++ b/source/blender/compositor/intern/COM_Converter.cc
@@ -29,6 +29,7 @@
#include "COM_ColorSpillNode.h"
#include "COM_ColorToBWNode.h"
#include "COM_CombineColorNode.h"
+#include "COM_CombineColorNodeLegacy.h"
#include "COM_CombineXYZNode.h"
#include "COM_CompositorNode.h"
#include "COM_ConvertAlphaNode.h"
@@ -82,6 +83,7 @@
#include "COM_ScaleOperation.h"
#include "COM_SceneTimeNode.h"
#include "COM_SeparateColorNode.h"
+#include "COM_SeparateColorNodeLegacy.h"
#include "COM_SeparateXYZNode.h"
#include "COM_SetAlphaNode.h"
#include "COM_SetValueOperation.h"
@@ -169,28 +171,34 @@ Node *COM_convert_bnode(bNode *b_node)
case CMP_NODE_BRIGHTCONTRAST:
node = new BrightnessNode(b_node);
break;
- case CMP_NODE_SEPRGBA:
+ case CMP_NODE_SEPARATE_COLOR:
+ node = new SeparateColorNode(b_node);
+ break;
+ case CMP_NODE_COMBINE_COLOR:
+ node = new CombineColorNode(b_node);
+ break;
+ case CMP_NODE_SEPRGBA_LEGACY:
node = new SeparateRGBANode(b_node);
break;
- case CMP_NODE_COMBRGBA:
+ case CMP_NODE_COMBRGBA_LEGACY:
node = new CombineRGBANode(b_node);
break;
- case CMP_NODE_SEPHSVA:
+ case CMP_NODE_SEPHSVA_LEGACY:
node = new SeparateHSVANode(b_node);
break;
- case CMP_NODE_COMBHSVA:
+ case CMP_NODE_COMBHSVA_LEGACY:
node = new CombineHSVANode(b_node);
break;
- case CMP_NODE_SEPYUVA:
+ case CMP_NODE_SEPYUVA_LEGACY:
node = new SeparateYUVANode(b_node);
break;
- case CMP_NODE_COMBYUVA:
+ case CMP_NODE_COMBYUVA_LEGACY:
node = new CombineYUVANode(b_node);
break;
- case CMP_NODE_SEPYCCA:
+ case CMP_NODE_SEPYCCA_LEGACY:
node = new SeparateYCCANode(b_node);
break;
- case CMP_NODE_COMBYCCA:
+ case CMP_NODE_COMBYCCA_LEGACY:
node = new CombineYCCANode(b_node);
break;
case CMP_NODE_ALPHAOVER:
diff --git a/source/blender/compositor/nodes/COM_CombineColorNode.cc b/source/blender/compositor/nodes/COM_CombineColorNode.cc
index 0c8748fd2d6..c766a359d63 100644
--- a/source/blender/compositor/nodes/COM_CombineColorNode.cc
+++ b/source/blender/compositor/nodes/COM_CombineColorNode.cc
@@ -40,7 +40,39 @@ void CombineColorNode::convert_to_operations(NodeConverter &converter,
converter.map_input_socket(input_bsocket, operation->get_input_socket(2));
converter.map_input_socket(input_asocket, operation->get_input_socket(3));
- NodeOperation *color_conv = get_color_converter(context);
+ bNode *editor_node = this->get_bnode();
+ NodeCMPCombSepColor *storage = (NodeCMPCombSepColor *)editor_node->storage;
+
+ NodeOperation *color_conv = nullptr;
+ switch (storage->mode) {
+ case CMP_NODE_COMBSEP_COLOR_RGB: {
+ /* Pass */
+ break;
+ }
+ case CMP_NODE_COMBSEP_COLOR_HSV: {
+ color_conv = new ConvertHSVToRGBOperation();
+ break;
+ }
+ case CMP_NODE_COMBSEP_COLOR_HSL: {
+ color_conv = new ConvertHSLToRGBOperation();
+ break;
+ }
+ case CMP_NODE_COMBSEP_COLOR_YCC: {
+ ConvertYCCToRGBOperation *operation = new ConvertYCCToRGBOperation();
+ operation->set_mode(storage->ycc_mode);
+ color_conv = operation;
+ break;
+ }
+ case CMP_NODE_COMBSEP_COLOR_YUV: {
+ color_conv = new ConvertYUVToRGBOperation();
+ break;
+ }
+ default: {
+ BLI_assert_unreachable();
+ break;
+ }
+ }
+
if (color_conv) {
converter.add_operation(color_conv);
@@ -52,27 +84,4 @@ void CombineColorNode::convert_to_operations(NodeConverter &converter,
}
}
-NodeOperation *CombineRGBANode::get_color_converter(const CompositorContext & /*context*/) const
-{
- return nullptr; /* no conversion needed */
-}
-
-NodeOperation *CombineHSVANode::get_color_converter(const CompositorContext & /*context*/) const
-{
- return new ConvertHSVToRGBOperation();
-}
-
-NodeOperation *CombineYCCANode::get_color_converter(const CompositorContext & /*context*/) const
-{
- ConvertYCCToRGBOperation *operation = new ConvertYCCToRGBOperation();
- bNode *editor_node = this->get_bnode();
- operation->set_mode(editor_node->custom1);
- return operation;
-}
-
-NodeOperation *CombineYUVANode::get_color_converter(const CompositorContext & /*context*/) const
-{
- return new ConvertYUVToRGBOperation();
-}
-
} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_CombineColorNode.h b/source/blender/compositor/nodes/COM_CombineColorNode.h
index 2bead24cb02..7576cc9eb2d 100644
--- a/source/blender/compositor/nodes/COM_CombineColorNode.h
+++ b/source/blender/compositor/nodes/COM_CombineColorNode.h
@@ -12,45 +12,6 @@ class CombineColorNode : public Node {
CombineColorNode(bNode *editor_node);
void convert_to_operations(NodeConverter &converter,
const CompositorContext &context) const override;
-
- protected:
- virtual NodeOperation *get_color_converter(const CompositorContext &context) const = 0;
-};
-
-class CombineRGBANode : public CombineColorNode {
- public:
- CombineRGBANode(bNode *editor_node) : CombineColorNode(editor_node)
- {
- }
-
- NodeOperation *get_color_converter(const CompositorContext &context) const override;
-};
-
-class CombineHSVANode : public CombineColorNode {
- public:
- CombineHSVANode(bNode *editor_node) : CombineColorNode(editor_node)
- {
- }
-
- NodeOperation *get_color_converter(const CompositorContext &context) const override;
-};
-
-class CombineYCCANode : public CombineColorNode {
- public:
- CombineYCCANode(bNode *editor_node) : CombineColorNode(editor_node)
- {
- }
-
- NodeOperation *get_color_converter(const CompositorContext &context) const override;
-};
-
-class CombineYUVANode : public CombineColorNode {
- public:
- CombineYUVANode(bNode *editor_node) : CombineColorNode(editor_node)
- {
- }
-
- NodeOperation *get_color_converter(const CompositorContext &context) const override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_CombineColorNodeLegacy.cc b/source/blender/compositor/nodes/COM_CombineColorNodeLegacy.cc
new file mode 100644
index 00000000000..d5ba379bfc2
--- /dev/null
+++ b/source/blender/compositor/nodes/COM_CombineColorNodeLegacy.cc
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2011 Blender Foundation. */
+
+#include "COM_CombineColorNodeLegacy.h"
+
+#include "COM_ConvertOperation.h"
+
+namespace blender::compositor {
+
+CombineColorNodeLegacy::CombineColorNodeLegacy(bNode *editor_node) : Node(editor_node)
+{
+}
+
+void CombineColorNodeLegacy::convert_to_operations(NodeConverter &converter,
+ const CompositorContext &context) const
+{
+ NodeInput *input_rsocket = this->get_input_socket(0);
+ NodeInput *input_gsocket = this->get_input_socket(1);
+ NodeInput *input_bsocket = this->get_input_socket(2);
+ NodeInput *input_asocket = this->get_input_socket(3);
+ NodeOutput *output_socket = this->get_output_socket(0);
+
+ CombineChannelsOperation *operation = new CombineChannelsOperation();
+ if (input_rsocket->is_linked()) {
+ operation->set_canvas_input_index(0);
+ }
+ else if (input_gsocket->is_linked()) {
+ operation->set_canvas_input_index(1);
+ }
+ else if (input_bsocket->is_linked()) {
+ operation->set_canvas_input_index(2);
+ }
+ else {
+ operation->set_canvas_input_index(3);
+ }
+ converter.add_operation(operation);
+
+ converter.map_input_socket(input_rsocket, operation->get_input_socket(0));
+ converter.map_input_socket(input_gsocket, operation->get_input_socket(1));
+ converter.map_input_socket(input_bsocket, operation->get_input_socket(2));
+ converter.map_input_socket(input_asocket, operation->get_input_socket(3));
+
+ NodeOperation *color_conv = get_color_converter(context);
+ if (color_conv) {
+ converter.add_operation(color_conv);
+
+ converter.add_link(operation->get_output_socket(), color_conv->get_input_socket(0));
+ converter.map_output_socket(output_socket, color_conv->get_output_socket());
+ }
+ else {
+ converter.map_output_socket(output_socket, operation->get_output_socket());
+ }
+}
+
+NodeOperation *CombineRGBANode::get_color_converter(const CompositorContext & /*context*/) const
+{
+ return nullptr; /* no conversion needed */
+}
+
+NodeOperation *CombineHSVANode::get_color_converter(const CompositorContext & /*context*/) const
+{
+ return new ConvertHSVToRGBOperation();
+}
+
+NodeOperation *CombineYCCANode::get_color_converter(const CompositorContext & /*context*/) const
+{
+ ConvertYCCToRGBOperation *operation = new ConvertYCCToRGBOperation();
+ bNode *editor_node = this->get_bnode();
+ operation->set_mode(editor_node->custom1);
+ return operation;
+}
+
+NodeOperation *CombineYUVANode::get_color_converter(const CompositorContext & /*context*/) const
+{
+ return new ConvertYUVToRGBOperation();
+}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_CombineColorNodeLegacy.h b/source/blender/compositor/nodes/COM_CombineColorNodeLegacy.h
new file mode 100644
index 00000000000..edc66c8932f
--- /dev/null
+++ b/source/blender/compositor/nodes/COM_CombineColorNodeLegacy.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2011 Blender Foundation. */
+
+#pragma once
+
+#include "COM_Node.h"
+
+namespace blender::compositor {
+
+class CombineColorNodeLegacy : public Node {
+ public:
+ CombineColorNodeLegacy(bNode *editor_node);
+ void convert_to_operations(NodeConverter &converter,
+ const CompositorContext &context) const override;
+
+ protected:
+ virtual NodeOperation *get_color_converter(const CompositorContext &context) const = 0;
+};
+
+class CombineRGBANode : public CombineColorNodeLegacy {
+ public:
+ CombineRGBANode(bNode *editor_node) : CombineColorNodeLegacy(editor_node)
+ {
+ }
+
+ NodeOperation *get_color_converter(const CompositorContext &context) const override;
+};
+
+class CombineHSVANode : public CombineColorNodeLegacy {
+ public:
+ CombineHSVANode(bNode *editor_node) : CombineColorNodeLegacy(editor_node)
+ {
+ }
+
+ NodeOperation *get_color_converter(const CompositorContext &context) const override;
+};
+
+class CombineYCCANode : public CombineColorNodeLegacy {
+ public:
+ CombineYCCANode(bNode *editor_node) : CombineColorNodeLegacy(editor_node)
+ {
+ }
+
+ NodeOperation *get_color_converter(const CompositorContext &context) const override;
+};
+
+class CombineYUVANode : public CombineColorNodeLegacy {
+ public:
+ CombineYUVANode(bNode *editor_node) : CombineColorNodeLegacy(editor_node)
+ {
+ }
+
+ NodeOperation *get_color_converter(const CompositorContext &context) const override;
+};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_SeparateColorNode.cc b/source/blender/compositor/nodes/COM_SeparateColorNode.cc
index 221d80e67f2..6e69bd097a1 100644
--- a/source/blender/compositor/nodes/COM_SeparateColorNode.cc
+++ b/source/blender/compositor/nodes/COM_SeparateColorNode.cc
@@ -20,7 +20,39 @@ void SeparateColorNode::convert_to_operations(NodeConverter &converter,
NodeOutput *output_bsocket = this->get_output_socket(2);
NodeOutput *output_asocket = this->get_output_socket(3);
- NodeOperation *color_conv = get_color_converter(context);
+ bNode *editor_node = this->get_bnode();
+ NodeCMPCombSepColor *storage = (NodeCMPCombSepColor *)editor_node->storage;
+
+ NodeOperation *color_conv = nullptr;
+ switch (storage->mode) {
+ case CMP_NODE_COMBSEP_COLOR_RGB: {
+ /* Pass */
+ break;
+ }
+ case CMP_NODE_COMBSEP_COLOR_HSV: {
+ color_conv = new ConvertRGBToHSVOperation();
+ break;
+ }
+ case CMP_NODE_COMBSEP_COLOR_HSL: {
+ color_conv = new ConvertRGBToHSLOperation();
+ break;
+ }
+ case CMP_NODE_COMBSEP_COLOR_YCC: {
+ ConvertRGBToYCCOperation *operation = new ConvertRGBToYCCOperation();
+ operation->set_mode(storage->ycc_mode);
+ color_conv = operation;
+ break;
+ }
+ case CMP_NODE_COMBSEP_COLOR_YUV: {
+ color_conv = new ConvertRGBToYUVOperation();
+ break;
+ }
+ default: {
+ BLI_assert_unreachable();
+ break;
+ }
+ }
+
if (color_conv) {
converter.add_operation(color_conv);
@@ -84,27 +116,4 @@ void SeparateColorNode::convert_to_operations(NodeConverter &converter,
}
}
-NodeOperation *SeparateRGBANode::get_color_converter(const CompositorContext & /*context*/) const
-{
- return nullptr; /* no conversion needed */
-}
-
-NodeOperation *SeparateHSVANode::get_color_converter(const CompositorContext & /*context*/) const
-{
- return new ConvertRGBToHSVOperation();
-}
-
-NodeOperation *SeparateYCCANode::get_color_converter(const CompositorContext & /*context*/) const
-{
- ConvertRGBToYCCOperation *operation = new ConvertRGBToYCCOperation();
- bNode *editor_node = this->get_bnode();
- operation->set_mode(editor_node->custom1);
- return operation;
-}
-
-NodeOperation *SeparateYUVANode::get_color_converter(const CompositorContext & /*context*/) const
-{
- return new ConvertRGBToYUVOperation();
-}
-
} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_SeparateColorNode.h b/source/blender/compositor/nodes/COM_SeparateColorNode.h
index 78ab0959f43..6adb2d0bb22 100644
--- a/source/blender/compositor/nodes/COM_SeparateColorNode.h
+++ b/source/blender/compositor/nodes/COM_SeparateColorNode.h
@@ -12,45 +12,6 @@ class SeparateColorNode : public Node {
SeparateColorNode(bNode *editor_node);
void convert_to_operations(NodeConverter &converter,
const CompositorContext &context) const override;
-
- protected:
- virtual NodeOperation *get_color_converter(const CompositorContext &context) const = 0;
-};
-
-class SeparateRGBANode : public SeparateColorNode {
- public:
- SeparateRGBANode(bNode *editor_node) : SeparateColorNode(editor_node)
- {
- }
-
- NodeOperation *get_color_converter(const CompositorContext &context) const override;
-};
-
-class SeparateHSVANode : public SeparateColorNode {
- public:
- SeparateHSVANode(bNode *editor_node) : SeparateColorNode(editor_node)
- {
- }
-
- NodeOperation *get_color_converter(const CompositorContext &context) const override;
-};
-
-class SeparateYCCANode : public SeparateColorNode {
- public:
- SeparateYCCANode(bNode *editor_node) : SeparateColorNode(editor_node)
- {
- }
-
- NodeOperation *get_color_converter(const CompositorContext &context) const override;
-};
-
-class SeparateYUVANode : public SeparateColorNode {
- public:
- SeparateYUVANode(bNode *editor_node) : SeparateColorNode(editor_node)
- {
- }
-
- NodeOperation *get_color_converter(const CompositorContext &context) const override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_SeparateColorNodeLegacy.cc b/source/blender/compositor/nodes/COM_SeparateColorNodeLegacy.cc
new file mode 100644
index 00000000000..c3728bc152f
--- /dev/null
+++ b/source/blender/compositor/nodes/COM_SeparateColorNodeLegacy.cc
@@ -0,0 +1,110 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2011 Blender Foundation. */
+
+#include "COM_SeparateColorNodeLegacy.h"
+
+#include "COM_ConvertOperation.h"
+
+namespace blender::compositor {
+
+SeparateColorNodeLegacy::SeparateColorNodeLegacy(bNode *editor_node) : Node(editor_node)
+{
+}
+
+void SeparateColorNodeLegacy::convert_to_operations(NodeConverter &converter,
+ const CompositorContext &context) const
+{
+ NodeInput *image_socket = this->get_input_socket(0);
+ NodeOutput *output_rsocket = this->get_output_socket(0);
+ NodeOutput *output_gsocket = this->get_output_socket(1);
+ NodeOutput *output_bsocket = this->get_output_socket(2);
+ NodeOutput *output_asocket = this->get_output_socket(3);
+
+ NodeOperation *color_conv = get_color_converter(context);
+ if (color_conv) {
+ converter.add_operation(color_conv);
+
+ converter.map_input_socket(image_socket, color_conv->get_input_socket(0));
+ }
+
+ {
+ SeparateChannelOperation *operation = new SeparateChannelOperation();
+ operation->set_channel(0);
+ converter.add_operation(operation);
+
+ if (color_conv) {
+ converter.add_link(color_conv->get_output_socket(), operation->get_input_socket(0));
+ }
+ else {
+ converter.map_input_socket(image_socket, operation->get_input_socket(0));
+ }
+ converter.map_output_socket(output_rsocket, operation->get_output_socket(0));
+ }
+
+ {
+ SeparateChannelOperation *operation = new SeparateChannelOperation();
+ operation->set_channel(1);
+ converter.add_operation(operation);
+
+ if (color_conv) {
+ converter.add_link(color_conv->get_output_socket(), operation->get_input_socket(0));
+ }
+ else {
+ converter.map_input_socket(image_socket, operation->get_input_socket(0));
+ }
+ converter.map_output_socket(output_gsocket, operation->get_output_socket(0));
+ }
+
+ {
+ SeparateChannelOperation *operation = new SeparateChannelOperation();
+ operation->set_channel(2);
+ converter.add_operation(operation);
+
+ if (color_conv) {
+ converter.add_link(color_conv->get_output_socket(), operation->get_input_socket(0));
+ }
+ else {
+ converter.map_input_socket(image_socket, operation->get_input_socket(0));
+ }
+ converter.map_output_socket(output_bsocket, operation->get_output_socket(0));
+ }
+
+ {
+ SeparateChannelOperation *operation = new SeparateChannelOperation();
+ operation->set_channel(3);
+ converter.add_operation(operation);
+
+ if (color_conv) {
+ converter.add_link(color_conv->get_output_socket(), operation->get_input_socket(0));
+ }
+ else {
+ converter.map_input_socket(image_socket, operation->get_input_socket(0));
+ }
+ converter.map_output_socket(output_asocket, operation->get_output_socket(0));
+ }
+}
+
+NodeOperation *SeparateRGBANode::get_color_converter(const CompositorContext & /*context*/) const
+{
+ return nullptr; /* no conversion needed */
+}
+
+NodeOperation *SeparateHSVANode::get_color_converter(const CompositorContext & /*context*/) const
+{
+ return new ConvertRGBToHSVOperation();
+}
+
+NodeOperation *SeparateYCCANode::get_color_converter(const CompositorContext & /*context*/) const
+{
+ ConvertRGBToYCCOperation *operation = new ConvertRGBToYCCOperation();
+ bNode *editor_node = this->get_bnode();
+ operation->set_mode(editor_node->custom1);
+ return operation;
+}
+
+NodeOperation *SeparateYUVANode::get_color_converter(const CompositorContext & /*context*/) const
+{
+ return new ConvertRGBToYUVOperation();
+}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_SeparateColorNodeLegacy.h b/source/blender/compositor/nodes/COM_SeparateColorNodeLegacy.h
new file mode 100644
index 00000000000..10b33039c86
--- /dev/null
+++ b/source/blender/compositor/nodes/COM_SeparateColorNodeLegacy.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2011 Blender Foundation. */
+
+#pragma once
+
+#include "COM_Node.h"
+
+namespace blender::compositor {
+
+class SeparateColorNodeLegacy : public Node {
+ public:
+ SeparateColorNodeLegacy(bNode *editor_node);
+ void convert_to_operations(NodeConverter &converter,
+ const CompositorContext &context) const override;
+
+ protected:
+ virtual NodeOperation *get_color_converter(const CompositorContext &context) const = 0;
+};
+
+class SeparateRGBANode : public SeparateColorNodeLegacy {
+ public:
+ SeparateRGBANode(bNode *editor_node) : SeparateColorNodeLegacy(editor_node)
+ {
+ }
+
+ NodeOperation *get_color_converter(const CompositorContext &context) const override;
+};
+
+class SeparateHSVANode : public SeparateColorNodeLegacy {
+ public:
+ SeparateHSVANode(bNode *editor_node) : SeparateColorNodeLegacy(editor_node)
+ {
+ }
+
+ NodeOperation *get_color_converter(const CompositorContext &context) const override;
+};
+
+class SeparateYCCANode : public SeparateColorNodeLegacy {
+ public:
+ SeparateYCCANode(bNode *editor_node) : SeparateColorNodeLegacy(editor_node)
+ {
+ }
+
+ NodeOperation *get_color_converter(const CompositorContext &context) const override;
+};
+
+class SeparateYUVANode : public SeparateColorNodeLegacy {
+ public:
+ SeparateYUVANode(bNode *editor_node) : SeparateColorNodeLegacy(editor_node)
+ {
+ }
+
+ NodeOperation *get_color_converter(const CompositorContext &context) const override;
+};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ConvertOperation.cc b/source/blender/compositor/operations/COM_ConvertOperation.cc
index 7579abf792a..24c0c577ac7 100644
--- a/source/blender/compositor/operations/COM_ConvertOperation.cc
+++ b/source/blender/compositor/operations/COM_ConvertOperation.cc
@@ -464,6 +464,68 @@ void ConvertHSVToRGBOperation::update_memory_buffer_partial(BuffersIterator<floa
}
}
+/* ******** RGB to HSL ******** */
+
+ConvertRGBToHSLOperation::ConvertRGBToHSLOperation() : ConvertBaseOperation()
+{
+ this->add_input_socket(DataType::Color);
+ this->add_output_socket(DataType::Color);
+}
+
+void ConvertRGBToHSLOperation::execute_pixel_sampled(float output[4],
+ float x,
+ float y,
+ PixelSampler sampler)
+{
+ float input_color[4];
+ input_operation_->read_sampled(input_color, x, y, sampler);
+ rgb_to_hsl_v(input_color, output);
+ output[3] = input_color[3];
+}
+
+void ConvertRGBToHSLOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ const float *in = it.in(0);
+ rgb_to_hsl_v(in, it.out);
+ it.out[3] = in[3];
+ }
+}
+
+/* ******** HSL to RGB ******** */
+
+ConvertHSLToRGBOperation::ConvertHSLToRGBOperation() : ConvertBaseOperation()
+{
+ this->add_input_socket(DataType::Color);
+ this->add_output_socket(DataType::Color);
+}
+
+void ConvertHSLToRGBOperation::execute_pixel_sampled(float output[4],
+ float x,
+ float y,
+ PixelSampler sampler)
+{
+ float input_color[4];
+ input_operation_->read_sampled(input_color, x, y, sampler);
+ hsl_to_rgb_v(input_color, output);
+ output[0] = max_ff(output[0], 0.0f);
+ output[1] = max_ff(output[1], 0.0f);
+ output[2] = max_ff(output[2], 0.0f);
+ output[3] = input_color[3];
+}
+
+void ConvertHSLToRGBOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
+{
+ for (; !it.is_end(); ++it) {
+ const float *in = it.in(0);
+ hsl_to_rgb_v(in, it.out);
+ it.out[0] = max_ff(it.out[0], 0.0f);
+ it.out[1] = max_ff(it.out[1], 0.0f);
+ it.out[2] = max_ff(it.out[2], 0.0f);
+ it.out[3] = in[3];
+ }
+}
+
/* ******** Premul to Straight ******** */
ConvertPremulToStraightOperation::ConvertPremulToStraightOperation() : ConvertBaseOperation()
diff --git a/source/blender/compositor/operations/COM_ConvertOperation.h b/source/blender/compositor/operations/COM_ConvertOperation.h
index e1904d61d46..16d1e2e6bb5 100644
--- a/source/blender/compositor/operations/COM_ConvertOperation.h
+++ b/source/blender/compositor/operations/COM_ConvertOperation.h
@@ -172,6 +172,26 @@ class ConvertHSVToRGBOperation : public ConvertBaseOperation {
void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
+class ConvertRGBToHSLOperation : public ConvertBaseOperation {
+ public:
+ ConvertRGBToHSLOperation();
+
+ void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
+};
+
+class ConvertHSLToRGBOperation : public ConvertBaseOperation {
+ public:
+ ConvertHSLToRGBOperation();
+
+ void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+ void update_memory_buffer_partial(BuffersIterator<float> &it) override;
+};
+
class ConvertPremulToStraightOperation : public ConvertBaseOperation {
public:
ConvertPremulToStraightOperation();
diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc
index 958a9fdfc60..d5507619e0d 100644
--- a/source/blender/editors/space_node/drawnode.cc
+++ b/source/blender/editors/space_node/drawnode.cc
@@ -213,6 +213,11 @@ static void node_buts_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *pt
uiItemR(layout, ptr, "use_clamp", DEFAULT_FLAGS, nullptr, ICON_NONE);
}
+static void node_buts_combsep_color(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE);
+}
+
NodeResizeDirection node_get_resize_direction(const bNode *node, const int x, const int y)
{
if (node->type == NODE_FRAME) {
@@ -480,6 +485,10 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_MATH:
ntype->draw_buttons = node_buts_math;
break;
+ case SH_NODE_COMBINE_COLOR:
+ case SH_NODE_SEPARATE_COLOR:
+ ntype->draw_buttons = node_buts_combsep_color;
+ break;
case SH_NODE_TEX_IMAGE:
ntype->draw_buttons = node_shader_buts_tex_image;
ntype->draw_buttons_ex = node_shader_buts_tex_image_ex;
@@ -589,6 +598,19 @@ static void node_composit_buts_ycc(uiLayout *layout, bContext *UNUSED(C), Pointe
uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE);
}
+static void node_composit_buts_combsep_color(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ bNode *node = (bNode *)ptr->data;
+ NodeCMPCombSepColor *storage = (NodeCMPCombSepColor *)node->storage;
+
+ uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE);
+ if (storage->mode == CMP_NODE_COMBSEP_COLOR_YCC) {
+ uiItemR(layout, ptr, "ycc_mode", DEFAULT_FLAGS, "", ICON_NONE);
+ }
+}
+
static void node_composit_backdrop_viewer(
SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y)
{
@@ -821,8 +843,12 @@ static void node_composit_set_butfunc(bNodeType *ntype)
case CMP_NODE_HUECORRECT:
ntype->draw_buttons = node_composit_buts_huecorrect;
break;
- case CMP_NODE_COMBYCCA:
- case CMP_NODE_SEPYCCA:
+ case CMP_NODE_COMBINE_COLOR:
+ case CMP_NODE_SEPARATE_COLOR:
+ ntype->draw_buttons = node_composit_buts_combsep_color;
+ break;
+ case CMP_NODE_COMBYCCA_LEGACY:
+ case CMP_NODE_SEPYCCA_LEGACY:
ntype->draw_buttons = node_composit_buts_ycc;
break;
case CMP_NODE_MASK_BOX:
@@ -975,6 +1001,11 @@ static void node_texture_buts_output(uiLayout *layout, bContext *UNUSED(C), Poin
uiItemR(layout, ptr, "filepath", DEFAULT_FLAGS, "", ICON_NONE);
}
+static void node_texture_buts_combsep_color(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE);
+}
+
/* only once called */
static void node_texture_set_butfunc(bNodeType *ntype)
{
@@ -1020,6 +1051,11 @@ static void node_texture_set_butfunc(bNodeType *ntype)
case TEX_NODE_OUTPUT:
ntype->draw_buttons = node_texture_buts_output;
break;
+
+ case TEX_NODE_COMBINE_COLOR:
+ case TEX_NODE_SEPARATE_COLOR:
+ ntype->draw_buttons = node_texture_buts_combsep_color;
+ break;
}
}
}
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 7c6390971dd..1e54d5fb7ee 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -317,6 +317,7 @@ set(GLSL_SRC
shaders/material/gpu_shader_material_clamp.glsl
shaders/material/gpu_shader_material_color_ramp.glsl
shaders/material/gpu_shader_material_color_util.glsl
+ shaders/material/gpu_shader_material_combine_color.glsl
shaders/material/gpu_shader_material_combine_hsv.glsl
shaders/material/gpu_shader_material_combine_rgb.glsl
shaders/material/gpu_shader_material_combine_xyz.glsl
@@ -359,6 +360,7 @@ set(GLSL_SRC
shaders/material/gpu_shader_material_refraction.glsl
shaders/material/gpu_shader_material_rgb_curves.glsl
shaders/material/gpu_shader_material_rgb_to_bw.glsl
+ shaders/material/gpu_shader_material_separate_color.glsl
shaders/material/gpu_shader_material_separate_hsv.glsl
shaders/material/gpu_shader_material_separate_rgb.glsl
shaders/material/gpu_shader_material_separate_xyz.glsl
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_color_util.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_color_util.glsl
index a5c3a990d90..fe89985ae7f 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_color_util.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_color_util.glsl
@@ -90,6 +90,56 @@ void hsv_to_rgb(vec4 hsv, out vec4 outcol)
outcol = vec4(rgb, hsv.w);
}
+void rgb_to_hsl(vec4 rgb, out vec4 outcol)
+{
+ float cmax, cmin, h, s, l;
+
+ cmax = max(rgb[0], max(rgb[1], rgb[2]));
+ cmin = min(rgb[0], min(rgb[1], rgb[2]));
+ l = min(1.0, (cmax + cmin) / 2.0);
+
+ if (cmax == cmin) {
+ h = s = 0.0; /* achromatic */
+ }
+ else {
+ float cdelta = cmax - cmin;
+ s = l > 0.5 ? cdelta / (2.0 - cmax - cmin) : cdelta / (cmax + cmin);
+ if (cmax == rgb[0]) {
+ h = (rgb[1] - rgb[2]) / cdelta + (rgb[1] < rgb[2] ? 6.0 : 0.0);
+ }
+ else if (cmax == rgb[1]) {
+ h = (rgb[2] - rgb[0]) / cdelta + 2.0;
+ }
+ else {
+ h = (rgb[0] - rgb[1]) / cdelta + 4.0;
+ }
+ }
+ h /= 6.0;
+
+ outcol = vec4(h, s, l, rgb.w);
+}
+
+void hsl_to_rgb(vec4 hsl, out vec4 outcol)
+{
+ float nr, ng, nb, chroma, h, s, l;
+
+ h = hsl[0];
+ s = hsl[1];
+ l = hsl[2];
+
+ nr = abs(h * 6.0 - 3.0) - 1.0;
+ ng = 2.0 - abs(h * 6.0 - 2.0);
+ nb = 2.0 - abs(h * 6.0 - 4.0);
+
+ nr = clamp(nr, 0.0, 1.0);
+ nb = clamp(nb, 0.0, 1.0);
+ ng = clamp(ng, 0.0, 1.0);
+
+ chroma = (1.0 - abs(2.0 * l - 1.0)) * s;
+
+ outcol = vec4((nr - 0.5) * chroma + l, (ng - 0.5) * chroma + l, (nb - 0.5) * chroma + l, hsl.w);
+}
+
void color_alpha_clear(vec4 color, out vec4 result)
{
result = vec4(color.rgb, 1.0);
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_combine_color.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_combine_color.glsl
new file mode 100644
index 00000000000..3a250fcae8b
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_combine_color.glsl
@@ -0,0 +1,16 @@
+#pragma BLENDER_REQUIRE(gpu_shader_material_color_util.glsl)
+
+void combine_color_rgb(float r, float g, float b, out vec4 col)
+{
+ col = vec4(r, g, b, 1.0);
+}
+
+void combine_color_hsv(float h, float s, float v, out vec4 col)
+{
+ hsv_to_rgb(vec4(h, s, v, 1.0), col);
+}
+
+void combine_color_hsl(float h, float s, float l, out vec4 col)
+{
+ hsl_to_rgb(vec4(h, s, l, 1.0), col);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_separate_color.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_separate_color.glsl
new file mode 100644
index 00000000000..7425e53ce7b
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_separate_color.glsl
@@ -0,0 +1,28 @@
+#pragma BLENDER_REQUIRE(gpu_shader_material_color_util.glsl)
+
+void separate_color_rgb(vec4 col, out float r, out float g, out float b)
+{
+ r = col.r;
+ g = col.g;
+ b = col.b;
+}
+
+void separate_color_hsv(vec4 col, out float r, out float g, out float b)
+{
+ vec4 hsv;
+
+ rgb_to_hsv(col, hsv);
+ r = hsv[0];
+ g = hsv[1];
+ b = hsv[2];
+}
+
+void separate_color_hsl(vec4 col, out float r, out float g, out float b)
+{
+ vec4 hsl;
+
+ rgb_to_hsl(col, hsl);
+ r = hsl[0];
+ g = hsl[1];
+ b = hsl[2];
+}
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index d18fe1b81dd..92c4d8fe938 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -855,6 +855,12 @@ typedef struct NodeVertexCol {
char name[64];
} NodeVertexCol;
+typedef struct NodeCMPCombSepColor {
+ /* CMPNodeCombSepColorMode */
+ uint8_t mode;
+ uint8_t ycc_mode;
+} NodeCMPCombSepColor;
+
/** Defocus blur node. */
typedef struct NodeDefocus {
char bktype, _pad0, preview, gamco;
@@ -1485,6 +1491,11 @@ typedef struct NodeFunctionCompare {
char _pad[1];
} NodeFunctionCompare;
+typedef struct NodeCombSepColor {
+ /* NodeCombSepColorMode */
+ int8_t mode;
+} NodeCombSepColor;
+
/* script node mode */
#define NODE_SCRIPT_INTERNAL 0
#define NODE_SCRIPT_EXTERNAL 1
@@ -1877,6 +1888,16 @@ typedef enum CMPNodeDenoisePrefilter {
CMP_NODE_DENOISE_PREFILTER_ACCURATE = 2
} CMPNodeDenoisePrefilter;
+/* Color combine/separate modes */
+
+typedef enum CMPNodeCombSepColorMode {
+ CMP_NODE_COMBSEP_COLOR_RGB = 0,
+ CMP_NODE_COMBSEP_COLOR_HSV = 1,
+ CMP_NODE_COMBSEP_COLOR_HSL = 2,
+ CMP_NODE_COMBSEP_COLOR_YCC = 3,
+ CMP_NODE_COMBSEP_COLOR_YUV = 4,
+} CMPNodeCombSepColorMode;
+
#define CMP_NODE_PLANETRACKDEFORM_MBLUR_SAMPLES_MAX 64
/* Point Density shader node */
@@ -2135,6 +2156,12 @@ typedef enum GeometryNodeScaleElementsMode {
GEO_NODE_SCALE_ELEMENTS_SINGLE_AXIS = 1,
} GeometryNodeScaleElementsMode;
+typedef enum NodeCombSepColorMode {
+ NODE_COMBSEP_COLOR_RGB = 0,
+ NODE_COMBSEP_COLOR_HSV = 1,
+ NODE_COMBSEP_COLOR_HSL = 2,
+} NodeCombSepColorMode;
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index eaf2142495e..4cd12acd038 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -489,6 +489,13 @@ static const EnumPropertyItem rna_node_geometry_curve_handle_side_items[] = {
{GEO_NODE_CURVE_HANDLE_RIGHT, "RIGHT", ICON_NONE, "Right", "Use the right handles"},
{0, NULL, 0, NULL, NULL}};
+static const EnumPropertyItem rna_node_combsep_color_items[] = {
+ {NODE_COMBSEP_COLOR_RGB, "RGB", ICON_NONE, "RGB", "Use RGB color processing"},
+ {NODE_COMBSEP_COLOR_HSV, "HSV", ICON_NONE, "HSV", "Use HSV color processing"},
+ {NODE_COMBSEP_COLOR_HSL, "HSL", ICON_NONE, "HSL", "Use HSL color processing"},
+ {0, NULL, 0, NULL, NULL},
+};
+
#ifndef RNA_RUNTIME
static const EnumPropertyItem node_sampler_type_items[] = {
{0, "NEAREST", 0, "Nearest", ""},
@@ -5050,6 +5057,18 @@ static void def_fn_input_string(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
+static void def_fn_combsep_color(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ RNA_def_struct_sdna_from(srna, "NodeCombSepColor", "storage");
+
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, rna_node_combsep_color_items);
+ RNA_def_property_ui_text(prop, "Mode", "Mode of color processing");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
+}
+
/* -- Shader Nodes ---------------------------------------------------------- */
static void def_sh_output(StructRNA *srna)
@@ -5401,6 +5420,17 @@ static void def_sh_tex_image(StructRNA *srna)
RNA_def_property_update(prop, 0, "rna_Node_update");
}
+static void def_tex_combsep_color(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "custom1");
+ RNA_def_property_enum_items(prop, rna_node_combsep_color_items);
+ RNA_def_property_ui_text(prop, "Mode", "Mode of color processing");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
+}
+
static void def_geo_image_texture(StructRNA *srna)
{
static const EnumPropertyItem fn_tex_prop_interpolation_items[] = {
@@ -6308,6 +6338,25 @@ static void def_sh_output_aov(StructRNA *srna)
RNA_def_struct_sdna_from(srna, "bNode", NULL);
}
+static void def_sh_combsep_color(StructRNA *srna)
+{
+ static const EnumPropertyItem type_items[] = {
+ {NODE_COMBSEP_COLOR_RGB, "RGB", ICON_NONE, "RGB", "Use RGB color processing"},
+ {NODE_COMBSEP_COLOR_HSV, "HSV", ICON_NONE, "HSV", "Use HSV color processing"},
+ {NODE_COMBSEP_COLOR_HSL, "HSL", ICON_NONE, "HSL", "Use HSL color processing"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ PropertyRNA *prop;
+
+ RNA_def_struct_sdna_from(srna, "NodeCombSepColor", "storage");
+
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, type_items);
+ RNA_def_property_ui_text(prop, "Mode", "Mode of color processing");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
+}
+
static void def_sh_script(StructRNA *srna)
{
PropertyRNA *prop;
@@ -8071,6 +8120,32 @@ static void def_cmp_ycc(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
+static void def_cmp_combsep_color(StructRNA *srna)
+{
+ static const EnumPropertyItem mode_items[] = {
+ {CMP_NODE_COMBSEP_COLOR_RGB, "RGB", ICON_NONE, "RGB", "Use RGB color processing"},
+ {CMP_NODE_COMBSEP_COLOR_HSV, "HSV", ICON_NONE, "HSV", "Use HSV color processing"},
+ {CMP_NODE_COMBSEP_COLOR_HSL, "HSL", ICON_NONE, "HSL", "Use HSL color processing"},
+ {CMP_NODE_COMBSEP_COLOR_YCC, "YCC", ICON_NONE, "YCbCr", "Use YCbCr color processing"},
+ {CMP_NODE_COMBSEP_COLOR_YUV, "YUV", ICON_NONE, "YUV", "Use YUV color processing"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ PropertyRNA *prop;
+
+ RNA_def_struct_sdna_from(srna, "NodeCMPCombSepColor", "storage");
+
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, mode_items);
+ RNA_def_property_ui_text(prop, "Mode", "Mode of color processing");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
+
+ prop = RNA_def_property(srna, "ycc_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, node_ycc_items);
+ RNA_def_property_ui_text(prop, "Color Space", "Color space used for YCbCrA processing");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+}
+
static void def_cmp_movieclip(StructRNA *srna)
{
PropertyRNA *prop;
diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h
index 3d3450d9252..5d782674f16 100644
--- a/source/blender/nodes/NOD_composite.h
+++ b/source/blender/nodes/NOD_composite.h
@@ -126,6 +126,8 @@ void register_node_type_cmp_planetrackdeform(void);
void register_node_type_cmp_cornerpin(void);
void register_node_type_cmp_separate_xyz(void);
void register_node_type_cmp_combine_xyz(void);
+void register_node_type_cmp_separate_color(void);
+void register_node_type_cmp_combine_color(void);
void node_cmp_rlayers_outputs(struct bNodeTree *ntree, struct bNode *node);
void node_cmp_rlayers_register_pass(struct bNodeTree *ntree,
diff --git a/source/blender/nodes/NOD_function.h b/source/blender/nodes/NOD_function.h
index cde4b67e120..ad96fba1929 100644
--- a/source/blender/nodes/NOD_function.h
+++ b/source/blender/nodes/NOD_function.h
@@ -8,6 +8,7 @@ extern "C" {
void register_node_type_fn_align_euler_to_vector(void);
void register_node_type_fn_boolean_math(void);
+void register_node_type_fn_combine_color(void);
void register_node_type_fn_compare(void);
void register_node_type_fn_float_to_int(void);
void register_node_type_fn_input_bool(void);
@@ -19,6 +20,7 @@ void register_node_type_fn_input_vector(void);
void register_node_type_fn_random_value(void);
void register_node_type_fn_replace_string(void);
void register_node_type_fn_rotate_euler(void);
+void register_node_type_fn_separate_color(void);
void register_node_type_fn_slice_string(void);
void register_node_type_fn_string_length(void);
void register_node_type_fn_value_to_string(void);
diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h
index 4996f12e27d..1d1310360b8 100644
--- a/source/blender/nodes/NOD_shader.h
+++ b/source/blender/nodes/NOD_shader.h
@@ -43,6 +43,8 @@ void register_node_type_sh_vect_math(void);
void register_node_type_sh_squeeze(void);
void register_node_type_sh_dynamic(void);
void register_node_type_sh_invert(void);
+void register_node_type_sh_sepcolor(void);
+void register_node_type_sh_combcolor(void);
void register_node_type_sh_seprgb(void);
void register_node_type_sh_combrgb(void);
void register_node_type_sh_sephsv(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 5818fa631e7..7dd732e7fad 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -42,8 +42,8 @@ DefNode(ShaderNode, SH_NODE_MATH, def_math, "MATH",
DefNode(ShaderNode, SH_NODE_VECTOR_MATH, def_vector_math, "VECT_MATH", VectorMath, "Vector Math", "" )
DefNode(ShaderNode, SH_NODE_SQUEEZE, 0, "SQUEEZE", Squeeze, "Squeeze Value", "" )
DefNode(ShaderNode, SH_NODE_INVERT, 0, "INVERT", Invert, "Invert", "" )
-DefNode(ShaderNode, SH_NODE_SEPRGB, 0, "SEPRGB", SeparateRGB, "Separate RGB", "" )
-DefNode(ShaderNode, SH_NODE_COMBRGB, 0, "COMBRGB", CombineRGB, "Combine RGB", "" )
+DefNode(ShaderNode, SH_NODE_SEPRGB_LEGACY, 0, "SEPRGB", SeparateRGB, "Separate RGB", "" )
+DefNode(ShaderNode, SH_NODE_COMBRGB_LEGACY, 0, "COMBRGB", CombineRGB, "Combine RGB", "" )
DefNode(ShaderNode, SH_NODE_HUE_SAT, 0, "HUE_SAT", HueSaturation, "Hue/Saturation", "" )
DefNode(ShaderNode, SH_NODE_OUTPUT_MATERIAL, def_sh_output, "OUTPUT_MATERIAL", OutputMaterial, "Material Output", "" )
@@ -106,8 +106,8 @@ DefNode(ShaderNode, SH_NODE_TEX_POINTDENSITY, def_sh_tex_pointdensity,"TEX
DefNode(ShaderNode, SH_NODE_TEX_COORD, def_sh_tex_coord, "TEX_COORD", TexCoord, "Texture Coordinate","" )
DefNode(ShaderNode, SH_NODE_VECTOR_ROTATE, def_sh_vector_rotate, "VECTOR_ROTATE", VectorRotate, "Vector Rotate", "" )
DefNode(ShaderNode, SH_NODE_VECT_TRANSFORM, def_sh_vect_transform, "VECT_TRANSFORM", VectorTransform, "Vector Transform", "" )
-DefNode(ShaderNode, SH_NODE_SEPHSV, 0, "SEPHSV", SeparateHSV, "Separate HSV", "" )
-DefNode(ShaderNode, SH_NODE_COMBHSV, 0, "COMBHSV", CombineHSV, "Combine HSV", "" )
+DefNode(ShaderNode, SH_NODE_SEPHSV_LEGACY, 0, "SEPHSV", SeparateHSV, "Separate HSV", "" )
+DefNode(ShaderNode, SH_NODE_COMBHSV_LEGACY, 0, "COMBHSV", CombineHSV, "Combine HSV", "" )
DefNode(ShaderNode, SH_NODE_UVMAP, def_sh_uvmap, "UVMAP", UVMap, "UV Map", "" )
DefNode(ShaderNode, SH_NODE_VERTEX_COLOR, def_sh_vertex_color, "VERTEX_COLOR", VertexColor, "Color Attribute", "" )
DefNode(ShaderNode, SH_NODE_UVALONGSTROKE, def_sh_uvalongstroke, "UVALONGSTROKE", UVAlongStroke, "UV Along Stroke", "" )
@@ -120,6 +120,8 @@ DefNode(ShaderNode, SH_NODE_TEX_IES, def_sh_tex_ies, "TEX
DefNode(ShaderNode, SH_NODE_TEX_WHITE_NOISE, def_sh_tex_white_noise, "TEX_WHITE_NOISE", TexWhiteNoise, "White Noise", "" )
DefNode(ShaderNode, SH_NODE_OUTPUT_AOV, def_sh_output_aov, "OUTPUT_AOV", OutputAOV, "AOV Output", "" )
DefNode(ShaderNode, SH_NODE_CURVE_FLOAT, def_float_curve, "CURVE_FLOAT", FloatCurve, "Float Curve", "" )
+DefNode(ShaderNode, SH_NODE_COMBINE_COLOR, def_sh_combsep_color, "COMBINE_COLOR", CombineColor, "Combine Color", "" )
+DefNode(ShaderNode, SH_NODE_SEPARATE_COLOR, def_sh_combsep_color, "SEPARATE_COLOR", SeparateColor, "Separate Color", "" )
DefNode(CompositorNode, CMP_NODE_VIEWER, def_cmp_viewer, "VIEWER", Viewer, "Viewer", "" )
DefNode(CompositorNode, CMP_NODE_RGB, 0, "RGB", RGB, "RGB", "" )
@@ -137,8 +139,8 @@ DefNode(CompositorNode, CMP_NODE_MAP_VALUE, def_cmp_map_value, "MAP_VA
DefNode(CompositorNode, CMP_NODE_MAP_RANGE, def_cmp_map_range, "MAP_RANGE", MapRange, "Map Range", "" )
DefNode(CompositorNode, CMP_NODE_TIME, def_time, "TIME", Time, "Time Curve", "" )
DefNode(CompositorNode, CMP_NODE_VECBLUR, def_cmp_vector_blur, "VECBLUR", VecBlur, "Vector Blur", "" )
-DefNode(CompositorNode, CMP_NODE_SEPRGBA, 0, "SEPRGBA", SepRGBA, "Separate RGBA", "" )
-DefNode(CompositorNode, CMP_NODE_SEPHSVA, 0, "SEPHSVA", SepHSVA, "Separate HSVA", "" )
+DefNode(CompositorNode, CMP_NODE_SEPRGBA_LEGACY, 0, "SEPRGBA", SepRGBA, "Separate RGBA", "" )
+DefNode(CompositorNode, CMP_NODE_SEPHSVA_LEGACY, 0, "SEPHSVA", SepHSVA, "Separate HSVA", "" )
DefNode(CompositorNode, CMP_NODE_SETALPHA, def_cmp_set_alpha, "SETALPHA", SetAlpha, "Set Alpha", "" )
DefNode(CompositorNode, CMP_NODE_HUE_SAT, 0, "HUE_SAT", HueSat, "Hue Saturation Value","" )
DefNode(CompositorNode, CMP_NODE_IMAGE, def_cmp_image, "IMAGE", Image, "Image", "" )
@@ -149,16 +151,16 @@ DefNode(CompositorNode, CMP_NODE_OUTPUT_FILE, 0, "OUTPUT
DefNode(CompositorNode, CMP_NODE_TEXTURE, def_texture, "TEXTURE", Texture, "Texture", "" )
DefNode(CompositorNode, CMP_NODE_TRANSLATE, def_cmp_translate, "TRANSLATE", Translate, "Translate", "" )
DefNode(CompositorNode, CMP_NODE_ZCOMBINE, def_cmp_zcombine, "ZCOMBINE", Zcombine, "Z Combine", "" )
-DefNode(CompositorNode, CMP_NODE_COMBRGBA, 0, "COMBRGBA", CombRGBA, "Combine RGBA", "" )
+DefNode(CompositorNode, CMP_NODE_COMBRGBA_LEGACY,0, "COMBRGBA", CombRGBA, "Combine RGBA", "" )
DefNode(CompositorNode, CMP_NODE_DILATEERODE, def_cmp_dilate_erode, "DILATEERODE", DilateErode, "Dilate/Erode", "" )
DefNode(CompositorNode, CMP_NODE_INPAINT, def_cmp_inpaint, "INPAINT", Inpaint, "Inpaint", "" )
DefNode(CompositorNode, CMP_NODE_DESPECKLE, def_cmp_despeckle, "DESPECKLE", Despeckle, "Despeckle", "" )
DefNode(CompositorNode, CMP_NODE_ROTATE, def_cmp_rotate, "ROTATE", Rotate, "Rotate", "" )
DefNode(CompositorNode, CMP_NODE_SCALE, def_cmp_scale, "SCALE", Scale, "Scale", "" )
-DefNode(CompositorNode, CMP_NODE_SEPYCCA, def_cmp_ycc, "SEPYCCA", SepYCCA, "Separate YCbCrA", "" )
-DefNode(CompositorNode, CMP_NODE_COMBYCCA, def_cmp_ycc, "COMBYCCA", CombYCCA, "Combine YCbCrA", "" )
-DefNode(CompositorNode, CMP_NODE_SEPYUVA, 0, "SEPYUVA", SepYUVA, "Separate YUVA", "" )
-DefNode(CompositorNode, CMP_NODE_COMBYUVA, 0, "COMBYUVA", CombYUVA, "Combine YUVA", "" )
+DefNode(CompositorNode, CMP_NODE_SEPYCCA_LEGACY, def_cmp_ycc, "SEPYCCA", SepYCCA, "Separate YCbCrA", "" )
+DefNode(CompositorNode, CMP_NODE_COMBYCCA_LEGACY,def_cmp_ycc, "COMBYCCA", CombYCCA, "Combine YCbCrA", "" )
+DefNode(CompositorNode, CMP_NODE_SEPYUVA_LEGACY, 0, "SEPYUVA", SepYUVA, "Separate YUVA", "" )
+DefNode(CompositorNode, CMP_NODE_COMBYUVA_LEGACY,0, "COMBYUVA", CombYUVA, "Combine YUVA", "" )
DefNode(CompositorNode, CMP_NODE_DIFF_MATTE, def_cmp_diff_matte, "DIFF_MATTE", DiffMatte, "Difference Key", "" )
DefNode(CompositorNode, CMP_NODE_COLOR_SPILL, def_cmp_color_spill, "COLOR_SPILL", ColorSpill, "Color Spill", "" )
DefNode(CompositorNode, CMP_NODE_CHROMA_MATTE, def_cmp_chroma_matte, "CHROMA_MATTE", ChromaMatte, "Chroma Key", "" )
@@ -170,7 +172,7 @@ DefNode(CompositorNode, CMP_NODE_ID_MASK, def_cmp_id_mask, "ID_MAS
DefNode(CompositorNode, CMP_NODE_DOUBLEEDGEMASK, def_cmp_double_edge_mask,"DOUBLEEDGEMASK", DoubleEdgeMask, "Double Edge Mask", "" )
DefNode(CompositorNode, CMP_NODE_DEFOCUS, def_cmp_defocus, "DEFOCUS", Defocus, "Defocus", "" )
DefNode(CompositorNode, CMP_NODE_DISPLACE, 0, "DISPLACE", Displace, "Displace", "" )
-DefNode(CompositorNode, CMP_NODE_COMBHSVA, 0, "COMBHSVA", CombHSVA, "Combine HSVA", "" )
+DefNode(CompositorNode, CMP_NODE_COMBHSVA_LEGACY,0, "COMBHSVA", CombHSVA, "Combine HSVA", "" )
DefNode(CompositorNode, CMP_NODE_MATH, def_math, "MATH", Math, "Math", "" )
DefNode(CompositorNode, CMP_NODE_LUMA_MATTE, def_cmp_luma_matte, "LUMA_MATTE", LumaMatte, "Luminance Key", "" )
DefNode(CompositorNode, CMP_NODE_BRIGHTCONTRAST, def_cmp_brightcontrast, "BRIGHTCONTRAST", BrightContrast, "Bright/Contrast", "" )
@@ -215,9 +217,11 @@ DefNode(CompositorNode, CMP_NODE_EXPOSURE, 0, "EXPOSU
DefNode(CompositorNode, CMP_NODE_ANTIALIASING, def_cmp_antialiasing, "ANTIALIASING", AntiAliasing, "Anti-Aliasing", "" )
DefNode(CompositorNode, CMP_NODE_POSTERIZE, 0, "POSTERIZE", Posterize, "Posterize", "" )
DefNode(CompositorNode, CMP_NODE_CONVERT_COLOR_SPACE,def_cmp_convert_color_space, "CONVERT_COLORSPACE", ConvertColorSpace, "Color Space","" )
-DefNode(CompositorNode, CMP_NODE_SCENE_TIME, 0, "SCENE_TIME", SceneTime, "Scene Time", "" )
+DefNode(CompositorNode, CMP_NODE_SCENE_TIME, 0, "SCENE_TIME", SceneTime, "Scene Time", "" )
DefNode(CompositorNode, CMP_NODE_COMBINE_XYZ, 0, "COMBINE_XYZ", CombineXYZ, "Combine XYZ", "" )
DefNode(CompositorNode, CMP_NODE_SEPARATE_XYZ, 0, "SEPARATE_XYZ", SeparateXYZ, "Separate XYZ", "" )
+DefNode(CompositorNode, CMP_NODE_SEPARATE_COLOR, def_cmp_combsep_color, "SEPARATE_COLOR", SeparateColor, "Separate Color", "" )
+DefNode(CompositorNode, CMP_NODE_COMBINE_COLOR, def_cmp_combsep_color, "COMBINE_COLOR", CombineColor, "Combine Color", "" )
DefNode(TextureNode, TEX_NODE_OUTPUT, def_tex_output, "OUTPUT", Output, "Output", "" )
DefNode(TextureNode, TEX_NODE_CHECKER, 0, "CHECKER", Checker, "Checker", "" )
@@ -237,11 +241,13 @@ DefNode(TextureNode, TEX_NODE_VIEWER, 0, "VIEWER
DefNode(TextureNode, TEX_NODE_TRANSLATE, 0, "TRANSLATE", Translate, "Translate", "" )
DefNode(TextureNode, TEX_NODE_COORD, 0, "COORD", Coordinates, "Coordinates", "" )
DefNode(TextureNode, TEX_NODE_DISTANCE, 0, "DISTANCE", Distance, "Distance", "" )
-DefNode(TextureNode, TEX_NODE_COMPOSE, 0, "COMPOSE", Compose, "Combine RGBA", "" )
-DefNode(TextureNode, TEX_NODE_DECOMPOSE, 0, "DECOMPOSE", Decompose, "Separate RGBA", "" )
+DefNode(TextureNode, TEX_NODE_COMPOSE_LEGACY, 0, "COMPOSE", Compose, "Combine RGBA", "" )
+DefNode(TextureNode, TEX_NODE_DECOMPOSE_LEGACY,0, "DECOMPOSE", Decompose, "Separate RGBA", "" )
DefNode(TextureNode, TEX_NODE_VALTONOR, 0, "VALTONOR", ValToNor, "Value to Normal", "" )
DefNode(TextureNode, TEX_NODE_SCALE, 0, "SCALE", Scale, "Scale", "" )
DefNode(TextureNode, TEX_NODE_AT, 0, "AT", At, "At", "" )
+DefNode(TextureNode, TEX_NODE_COMBINE_COLOR, def_tex_combsep_color, "COMBINE_COLOR", CombineColor, "Combine Color", "" )
+DefNode(TextureNode, TEX_NODE_SEPARATE_COLOR, def_tex_combsep_color, "SEPARATE_COLOR", SeparateColor, "Separate Color", "" )
/* procedural textures */
DefNode(TextureNode, TEX_NODE_PROC+TEX_VORONOI, 0, "TEX_VORONOI", TexVoronoi, "Voronoi", "" )
DefNode(TextureNode, TEX_NODE_PROC+TEX_BLEND, 0, "TEX_BLEND", TexBlend, "Blend", "" )
@@ -256,6 +262,7 @@ DefNode(TextureNode, TEX_NODE_PROC+TEX_DISTNOISE, 0, "TEX_DI
DefNode(FunctionNode, FN_NODE_ALIGN_EULER_TO_VECTOR, def_fn_align_euler_to_vector, "ALIGN_EULER_TO_VECTOR", AlignEulerToVector, "Align Euler To Vector", "")
DefNode(FunctionNode, FN_NODE_BOOLEAN_MATH, def_boolean_math, "BOOLEAN_MATH", BooleanMath, "Boolean Math", "")
+DefNode(FunctionNode, FN_NODE_COMBINE_COLOR, def_fn_combsep_color, "COMBINE_COLOR", CombineColor, "Combine Color", "")
DefNode(FunctionNode, FN_NODE_COMPARE, def_compare, "COMPARE", Compare, "Compare", "")
DefNode(FunctionNode, FN_NODE_FLOAT_TO_INT, def_float_to_int, "FLOAT_TO_INT", FloatToInt, "Float to Integer", "")
DefNode(FunctionNode, FN_NODE_INPUT_BOOL, def_fn_input_bool, "INPUT_BOOL", InputBool, "Boolean", "")
@@ -267,6 +274,7 @@ DefNode(FunctionNode, FN_NODE_INPUT_VECTOR, def_fn_input_vector, "INPUT_VECTOR",
DefNode(FunctionNode, FN_NODE_RANDOM_VALUE, def_fn_random_value, "RANDOM_VALUE", RandomValue, "Random Value", "")
DefNode(FunctionNode, FN_NODE_REPLACE_STRING, 0, "REPLACE_STRING", ReplaceString, "Replace String", "")
DefNode(FunctionNode, FN_NODE_ROTATE_EULER, def_fn_rotate_euler, "ROTATE_EULER", RotateEuler, "Rotate Euler", "")
+DefNode(FunctionNode, FN_NODE_SEPARATE_COLOR, def_fn_combsep_color, "SEPARATE_COLOR", SeparateColor, "Separate Color", "")
DefNode(FunctionNode, FN_NODE_SLICE_STRING, 0, "SLICE_STRING", SliceString, "Slice String", "")
DefNode(FunctionNode, FN_NODE_STRING_LENGTH, 0, "STRING_LENGTH", StringLength, "String Length", "")
DefNode(FunctionNode, FN_NODE_VALUE_TO_STRING, 0, "VALUE_TO_STRING", ValueToString, "Value to String", "")
diff --git a/source/blender/nodes/NOD_texture.h b/source/blender/nodes/NOD_texture.h
index 0f07b17f165..9a2dc705c0d 100644
--- a/source/blender/nodes/NOD_texture.h
+++ b/source/blender/nodes/NOD_texture.h
@@ -46,6 +46,8 @@ void register_node_type_tex_at(void);
void register_node_type_tex_compose(void);
void register_node_type_tex_decompose(void);
+void register_node_type_tex_combine_color(void);
+void register_node_type_tex_separate_color(void);
void register_node_type_tex_proc_voronoi(void);
void register_node_type_tex_proc_blend(void);
diff --git a/source/blender/nodes/composite/CMakeLists.txt b/source/blender/nodes/composite/CMakeLists.txt
index 57f76f20ac6..c0100d77889 100644
--- a/source/blender/nodes/composite/CMakeLists.txt
+++ b/source/blender/nodes/composite/CMakeLists.txt
@@ -91,6 +91,7 @@ set(SRC
nodes/node_composite_rotate.cc
nodes/node_composite_scale.cc
nodes/node_composite_scene_time.cc
+ nodes/node_composite_sepcomb_color.cc
nodes/node_composite_sepcomb_hsva.cc
nodes/node_composite_sepcomb_rgba.cc
nodes/node_composite_sepcomb_xyz.cc
diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcomb_color.cc b/source/blender/nodes/composite/nodes/node_composite_sepcomb_color.cc
new file mode 100644
index 00000000000..689c069c50f
--- /dev/null
+++ b/source/blender/nodes/composite/nodes/node_composite_sepcomb_color.cc
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "node_composite_util.hh"
+
+static void node_cmp_combsep_color_init(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ NodeCMPCombSepColor *data = MEM_cnew<NodeCMPCombSepColor>(__func__);
+ data->mode = CMP_NODE_COMBSEP_COLOR_RGB;
+ data->ycc_mode = BLI_YCC_ITU_BT709;
+ node->storage = data;
+}
+
+static void node_cmp_combsep_color_label(const ListBase *sockets, CMPNodeCombSepColorMode mode)
+{
+ bNodeSocket *sock1 = (bNodeSocket *)sockets->first;
+ bNodeSocket *sock2 = sock1->next;
+ bNodeSocket *sock3 = sock2->next;
+
+ node_sock_label_clear(sock1);
+ node_sock_label_clear(sock2);
+ node_sock_label_clear(sock3);
+
+ switch (mode) {
+ case CMP_NODE_COMBSEP_COLOR_RGB:
+ node_sock_label(sock1, "Red");
+ node_sock_label(sock2, "Green");
+ node_sock_label(sock3, "Blue");
+ break;
+ case CMP_NODE_COMBSEP_COLOR_HSV:
+ node_sock_label(sock1, "Hue");
+ node_sock_label(sock2, "Saturation");
+ node_sock_label(sock3, "Value");
+ break;
+ case CMP_NODE_COMBSEP_COLOR_HSL:
+ node_sock_label(sock1, "Hue");
+ node_sock_label(sock2, "Saturation");
+ node_sock_label(sock3, "Lightness");
+ break;
+ case CMP_NODE_COMBSEP_COLOR_YCC:
+ node_sock_label(sock1, "Y");
+ node_sock_label(sock2, "Cb");
+ node_sock_label(sock3, "Cr");
+ break;
+ case CMP_NODE_COMBSEP_COLOR_YUV:
+ node_sock_label(sock1, "Y");
+ node_sock_label(sock2, "U");
+ node_sock_label(sock3, "V");
+ break;
+ default:
+ BLI_assert_unreachable();
+ break;
+ }
+}
+
+/* **************** SEPARATE COLOR ******************** */
+
+namespace blender::nodes::node_composite_separate_color_cc {
+
+static void cmp_node_separate_color_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Color>(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f});
+ b.add_output<decl::Float>(N_("Red"));
+ b.add_output<decl::Float>(N_("Green"));
+ b.add_output<decl::Float>(N_("Blue"));
+ b.add_output<decl::Float>(N_("Alpha"));
+}
+
+static void cmp_node_separate_color_update(bNodeTree *ntree, bNode *node)
+{
+ const NodeCMPCombSepColor *storage = (NodeCMPCombSepColor *)node->storage;
+ node_cmp_combsep_color_label(&node->outputs, (CMPNodeCombSepColorMode)storage->mode);
+}
+
+} // namespace blender::nodes::node_composite_separate_color_cc
+
+void register_node_type_cmp_separate_color()
+{
+ namespace file_ns = blender::nodes::node_composite_separate_color_cc;
+
+ static bNodeType ntype;
+
+ cmp_node_type_base(&ntype, CMP_NODE_SEPARATE_COLOR, "Separate Color", NODE_CLASS_CONVERTER);
+ ntype.declare = file_ns::cmp_node_separate_color_declare;
+ node_type_init(&ntype, node_cmp_combsep_color_init);
+ node_type_storage(
+ &ntype, "NodeCMPCombSepColor", node_free_standard_storage, node_copy_standard_storage);
+ node_type_update(&ntype, file_ns::cmp_node_separate_color_update);
+
+ nodeRegisterType(&ntype);
+}
+
+/* **************** COMBINE COLOR ******************** */
+
+namespace blender::nodes::node_composite_combine_color_cc {
+
+static void cmp_node_combine_color_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Float>(N_("Red")).default_value(0.0f).min(0.0f).max(1.0f).subtype(PROP_FACTOR);
+ b.add_input<decl::Float>(N_("Green"))
+ .default_value(0.0f)
+ .min(0.0f)
+ .max(1.0f)
+ .subtype(PROP_FACTOR);
+ b.add_input<decl::Float>(N_("Blue"))
+ .default_value(0.0f)
+ .min(0.0f)
+ .max(1.0f)
+ .subtype(PROP_FACTOR);
+ b.add_input<decl::Float>(N_("Alpha"))
+ .default_value(1.0f)
+ .min(0.0f)
+ .max(1.0f)
+ .subtype(PROP_FACTOR);
+ b.add_output<decl::Color>(N_("Image"));
+}
+
+static void cmp_node_combine_color_update(bNodeTree *ntree, bNode *node)
+{
+ const NodeCMPCombSepColor *storage = (NodeCMPCombSepColor *)node->storage;
+ node_cmp_combsep_color_label(&node->inputs, (CMPNodeCombSepColorMode)storage->mode);
+}
+
+} // namespace blender::nodes::node_composite_combine_color_cc
+
+void register_node_type_cmp_combine_color()
+{
+ namespace file_ns = blender::nodes::node_composite_combine_color_cc;
+
+ static bNodeType ntype;
+
+ cmp_node_type_base(&ntype, CMP_NODE_COMBINE_COLOR, "Combine Color", NODE_CLASS_CONVERTER);
+ ntype.declare = file_ns::cmp_node_combine_color_declare;
+ node_type_init(&ntype, node_cmp_combsep_color_init);
+ node_type_storage(
+ &ntype, "NodeCMPCombSepColor", node_free_standard_storage, node_copy_standard_storage);
+ node_type_update(&ntype, file_ns::cmp_node_combine_color_update);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcomb_hsva.cc b/source/blender/nodes/composite/nodes/node_composite_sepcomb_hsva.cc
index 349c27d876d..a0d2485ea5a 100644
--- a/source/blender/nodes/composite/nodes/node_composite_sepcomb_hsva.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_sepcomb_hsva.cc
@@ -28,7 +28,7 @@ void register_node_type_cmp_sephsva()
static bNodeType ntype;
- cmp_node_type_base(&ntype, CMP_NODE_SEPHSVA, "Separate HSVA", NODE_CLASS_CONVERTER);
+ cmp_node_type_base(&ntype, CMP_NODE_SEPHSVA_LEGACY, "Separate HSVA", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::cmp_node_sephsva_declare;
nodeRegisterType(&ntype);
}
@@ -54,7 +54,7 @@ void register_node_type_cmp_combhsva()
static bNodeType ntype;
- cmp_node_type_base(&ntype, CMP_NODE_COMBHSVA, "Combine HSVA", NODE_CLASS_CONVERTER);
+ cmp_node_type_base(&ntype, CMP_NODE_COMBHSVA_LEGACY, "Combine HSVA", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::cmp_node_combhsva_declare;
nodeRegisterType(&ntype);
diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcomb_rgba.cc b/source/blender/nodes/composite/nodes/node_composite_sepcomb_rgba.cc
index c46603be847..ae46681b0f4 100644
--- a/source/blender/nodes/composite/nodes/node_composite_sepcomb_rgba.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_sepcomb_rgba.cc
@@ -27,7 +27,7 @@ void register_node_type_cmp_seprgba()
static bNodeType ntype;
- cmp_node_type_base(&ntype, CMP_NODE_SEPRGBA, "Separate RGBA", NODE_CLASS_CONVERTER);
+ cmp_node_type_base(&ntype, CMP_NODE_SEPRGBA_LEGACY, "Separate RGBA", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::cmp_node_seprgba_declare;
nodeRegisterType(&ntype);
@@ -54,7 +54,7 @@ void register_node_type_cmp_combrgba()
static bNodeType ntype;
- cmp_node_type_base(&ntype, CMP_NODE_COMBRGBA, "Combine RGBA", NODE_CLASS_CONVERTER);
+ cmp_node_type_base(&ntype, CMP_NODE_COMBRGBA_LEGACY, "Combine RGBA", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::cmp_node_combrgba_declare;
nodeRegisterType(&ntype);
diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcomb_ycca.cc b/source/blender/nodes/composite/nodes/node_composite_sepcomb_ycca.cc
index 9b5c153fddf..a3c40b61e64 100644
--- a/source/blender/nodes/composite/nodes/node_composite_sepcomb_ycca.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_sepcomb_ycca.cc
@@ -33,7 +33,7 @@ void register_node_type_cmp_sepycca()
static bNodeType ntype;
- cmp_node_type_base(&ntype, CMP_NODE_SEPYCCA, "Separate YCbCrA", NODE_CLASS_CONVERTER);
+ cmp_node_type_base(&ntype, CMP_NODE_SEPYCCA_LEGACY, "Separate YCbCrA", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::cmp_node_sepycca_declare;
node_type_init(&ntype, file_ns::node_composit_init_mode_sepycca);
@@ -66,7 +66,7 @@ void register_node_type_cmp_combycca()
static bNodeType ntype;
- cmp_node_type_base(&ntype, CMP_NODE_COMBYCCA, "Combine YCbCrA", NODE_CLASS_CONVERTER);
+ cmp_node_type_base(&ntype, CMP_NODE_COMBYCCA_LEGACY, "Combine YCbCrA", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::cmp_node_combycca_declare;
node_type_init(&ntype, file_ns::node_composit_init_mode_combycca);
diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcomb_yuva.cc b/source/blender/nodes/composite/nodes/node_composite_sepcomb_yuva.cc
index e458c9cfb7e..7fdece5904d 100644
--- a/source/blender/nodes/composite/nodes/node_composite_sepcomb_yuva.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_sepcomb_yuva.cc
@@ -28,7 +28,7 @@ void register_node_type_cmp_sepyuva()
static bNodeType ntype;
- cmp_node_type_base(&ntype, CMP_NODE_SEPYUVA, "Separate YUVA", NODE_CLASS_CONVERTER);
+ cmp_node_type_base(&ntype, CMP_NODE_SEPYUVA_LEGACY, "Separate YUVA", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::cmp_node_sepyuva_declare;
nodeRegisterType(&ntype);
@@ -55,7 +55,7 @@ void register_node_type_cmp_combyuva()
static bNodeType ntype;
- cmp_node_type_base(&ntype, CMP_NODE_COMBYUVA, "Combine YUVA", NODE_CLASS_CONVERTER);
+ cmp_node_type_base(&ntype, CMP_NODE_COMBYUVA_LEGACY, "Combine YUVA", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::cmp_node_combyuva_declare;
nodeRegisterType(&ntype);
diff --git a/source/blender/nodes/function/CMakeLists.txt b/source/blender/nodes/function/CMakeLists.txt
index 6ccc4c7bf5c..d03f1cb63ff 100644
--- a/source/blender/nodes/function/CMakeLists.txt
+++ b/source/blender/nodes/function/CMakeLists.txt
@@ -20,6 +20,7 @@ set(INC
set(SRC
nodes/node_fn_align_euler_to_vector.cc
nodes/node_fn_boolean_math.cc
+ nodes/node_fn_combine_color.cc
nodes/node_fn_compare.cc
nodes/node_fn_float_to_int.cc
nodes/node_fn_input_bool.cc
@@ -31,6 +32,7 @@ set(SRC
nodes/node_fn_random_value.cc
nodes/node_fn_replace_string.cc
nodes/node_fn_rotate_euler.cc
+ nodes/node_fn_separate_color.cc
nodes/node_fn_slice_string.cc
nodes/node_fn_string_length.cc
nodes/node_fn_value_to_string.cc
diff --git a/source/blender/nodes/function/nodes/node_fn_combine_color.cc b/source/blender/nodes/function/nodes/node_fn_combine_color.cc
new file mode 100644
index 00000000000..8167cf55028
--- /dev/null
+++ b/source/blender/nodes/function/nodes/node_fn_combine_color.cc
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "node_function_util.hh"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+namespace blender::nodes {
+
+NODE_STORAGE_FUNCS(NodeCombSepColor)
+
+static void fn_node_combine_color_declare(NodeDeclarationBuilder &b)
+{
+ b.is_function_node();
+ b.add_input<decl::Float>(N_("Red")).default_value(0.0f).min(0.0f).max(1.0f).subtype(PROP_FACTOR);
+ b.add_input<decl::Float>(N_("Green"))
+ .default_value(0.0f)
+ .min(0.0f)
+ .max(1.0f)
+ .subtype(PROP_FACTOR);
+ b.add_input<decl::Float>(N_("Blue"))
+ .default_value(0.0f)
+ .min(0.0f)
+ .max(1.0f)
+ .subtype(PROP_FACTOR);
+ b.add_input<decl::Float>(N_("Alpha"))
+ .default_value(1.0f)
+ .min(0.0f)
+ .max(1.0f)
+ .subtype(PROP_FACTOR);
+ b.add_output<decl::Color>(N_("Color"));
+};
+
+static void fn_node_combine_color_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
+}
+
+static void fn_node_combine_color_update(bNodeTree *ntree, bNode *node)
+{
+ const NodeCombSepColor &storage = node_storage(*node);
+ node_combsep_color_label(&node->inputs, (NodeCombSepColorMode)storage.mode);
+}
+
+static void fn_node_combine_color_init(bNodeTree *UNUSED(tree), bNode *node)
+{
+ NodeCombSepColor *data = MEM_cnew<NodeCombSepColor>(__func__);
+ data->mode = NODE_COMBSEP_COLOR_RGB;
+ node->storage = data;
+}
+
+static const fn::MultiFunction *get_multi_function(bNode &bnode)
+{
+ const NodeCombSepColor &storage = node_storage(bnode);
+
+ static fn::CustomMF_SI_SI_SI_SI_SO<float, float, float, float, ColorGeometry4f> rgba_fn{
+ "RGB", [](float r, float g, float b, float a) { return ColorGeometry4f(r, g, b, a); }};
+ static fn::CustomMF_SI_SI_SI_SI_SO<float, float, float, float, ColorGeometry4f> hsva_fn{
+ "HSV", [](float h, float s, float v, float a) {
+ ColorGeometry4f r_color;
+ hsv_to_rgb(h, s, v, &r_color.r, &r_color.g, &r_color.b);
+ r_color.a = a;
+ return r_color;
+ }};
+ static fn::CustomMF_SI_SI_SI_SI_SO<float, float, float, float, ColorGeometry4f> hsla_fn{
+ "HSL", [](float h, float s, float l, float a) {
+ ColorGeometry4f color;
+ hsl_to_rgb(h, s, l, &color.r, &color.g, &color.b);
+ color.a = a;
+ return color;
+ }};
+
+ switch (storage.mode) {
+ case NODE_COMBSEP_COLOR_RGB:
+ return &rgba_fn;
+ case NODE_COMBSEP_COLOR_HSV:
+ return &hsva_fn;
+ case NODE_COMBSEP_COLOR_HSL:
+ return &hsla_fn;
+ }
+
+ BLI_assert_unreachable();
+ return nullptr;
+}
+
+static void fn_node_combine_color_build_multi_function(NodeMultiFunctionBuilder &builder)
+{
+ const fn::MultiFunction *fn = get_multi_function(builder.node());
+ builder.set_matching_fn(fn);
+}
+
+} // namespace blender::nodes
+
+void register_node_type_fn_combine_color(void)
+{
+ static bNodeType ntype;
+
+ fn_node_type_base(&ntype, FN_NODE_COMBINE_COLOR, "Combine Color", NODE_CLASS_CONVERTER);
+ ntype.declare = blender::nodes::fn_node_combine_color_declare;
+ node_type_update(&ntype, blender::nodes::fn_node_combine_color_update);
+ node_type_init(&ntype, blender::nodes::fn_node_combine_color_init);
+ node_type_storage(
+ &ntype, "NodeCombSepColor", node_free_standard_storage, node_copy_standard_storage);
+ ntype.build_multi_function = blender::nodes::fn_node_combine_color_build_multi_function;
+ ntype.draw_buttons = blender::nodes::fn_node_combine_color_layout;
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/function/nodes/node_fn_separate_color.cc b/source/blender/nodes/function/nodes/node_fn_separate_color.cc
new file mode 100644
index 00000000000..3fea4c4c040
--- /dev/null
+++ b/source/blender/nodes/function/nodes/node_fn_separate_color.cc
@@ -0,0 +1,205 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "node_function_util.hh"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+namespace blender::nodes {
+
+NODE_STORAGE_FUNCS(NodeCombSepColor)
+
+static void fn_node_separate_color_declare(NodeDeclarationBuilder &b)
+{
+ b.is_function_node();
+ b.add_input<decl::Color>(N_("Color")).default_value({1.0f, 1.0f, 1.0f, 1.0f});
+ b.add_output<decl::Float>(N_("Red"));
+ b.add_output<decl::Float>(N_("Green"));
+ b.add_output<decl::Float>(N_("Blue"));
+ b.add_output<decl::Float>(N_("Alpha"));
+};
+
+static void fn_node_separate_color_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
+}
+
+static void fn_node_separate_color_update(bNodeTree *ntree, bNode *node)
+{
+ const NodeCombSepColor &storage = node_storage(*node);
+ node_combsep_color_label(&node->outputs, (NodeCombSepColorMode)storage.mode);
+}
+
+static void fn_node_separate_color_init(bNodeTree *UNUSED(tree), bNode *node)
+{
+ NodeCombSepColor *data = MEM_cnew<NodeCombSepColor>(__func__);
+ data->mode = NODE_COMBSEP_COLOR_RGB;
+ node->storage = data;
+}
+
+class SeparateRGBAFunction : public fn::MultiFunction {
+ public:
+ SeparateRGBAFunction()
+ {
+ static fn::MFSignature signature = create_signature();
+ this->set_signature(&signature);
+ }
+
+ static fn::MFSignature create_signature()
+ {
+ fn::MFSignatureBuilder signature{"Separate Color"};
+ signature.single_input<ColorGeometry4f>("Color");
+ signature.single_output<float>("Red");
+ signature.single_output<float>("Green");
+ signature.single_output<float>("Blue");
+ signature.single_output<float>("Alpha");
+ return signature.build();
+ }
+
+ void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
+ {
+ const VArray<ColorGeometry4f> &colors = params.readonly_single_input<ColorGeometry4f>(0,
+ "Color");
+ MutableSpan<float> red = params.uninitialized_single_output<float>(1, "Red");
+ MutableSpan<float> green = params.uninitialized_single_output<float>(2, "Green");
+ MutableSpan<float> blue = params.uninitialized_single_output<float>(3, "Blue");
+ MutableSpan<float> alpha = params.uninitialized_single_output_if_required<float>(4, "Alpha");
+
+ for (int64_t i : mask) {
+ red[i] = colors[i].r;
+ green[i] = colors[i].g;
+ blue[i] = colors[i].b;
+ }
+
+ if (!alpha.is_empty()) {
+ for (int64_t i : mask) {
+ alpha[i] = colors[i].a;
+ }
+ }
+ }
+};
+
+class SeparateHSVAFunction : public fn::MultiFunction {
+ public:
+ SeparateHSVAFunction()
+ {
+ static fn::MFSignature signature = create_signature();
+ this->set_signature(&signature);
+ }
+
+ static fn::MFSignature create_signature()
+ {
+ fn::MFSignatureBuilder signature{"Separate Color"};
+ signature.single_input<ColorGeometry4f>("Color");
+ signature.single_output<float>("Hue");
+ signature.single_output<float>("Saturation");
+ signature.single_output<float>("Value");
+ signature.single_output<float>("Alpha");
+ return signature.build();
+ }
+
+ void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
+ {
+ const VArray<ColorGeometry4f> &colors = params.readonly_single_input<ColorGeometry4f>(0,
+ "Color");
+ MutableSpan<float> hue = params.uninitialized_single_output<float>(1, "Hue");
+ MutableSpan<float> saturation = params.uninitialized_single_output<float>(2, "Saturation");
+ MutableSpan<float> value = params.uninitialized_single_output<float>(3, "Value");
+ MutableSpan<float> alpha = params.uninitialized_single_output_if_required<float>(4, "Alpha");
+
+ for (int64_t i : mask) {
+ rgb_to_hsv(colors[i].r, colors[i].g, colors[i].b, &hue[i], &saturation[i], &value[i]);
+ }
+
+ if (!alpha.is_empty()) {
+ for (int64_t i : mask) {
+ alpha[i] = colors[i].a;
+ }
+ }
+ }
+};
+
+class SeparateHSLAFunction : public fn::MultiFunction {
+ public:
+ SeparateHSLAFunction()
+ {
+ static fn::MFSignature signature = create_signature();
+ this->set_signature(&signature);
+ }
+
+ static fn::MFSignature create_signature()
+ {
+ fn::MFSignatureBuilder signature{"Separate Color"};
+ signature.single_input<ColorGeometry4f>("Color");
+ signature.single_output<float>("Hue");
+ signature.single_output<float>("Saturation");
+ signature.single_output<float>("Lightness");
+ signature.single_output<float>("Alpha");
+ return signature.build();
+ }
+
+ void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
+ {
+ const VArray<ColorGeometry4f> &colors = params.readonly_single_input<ColorGeometry4f>(0,
+ "Color");
+ MutableSpan<float> hue = params.uninitialized_single_output<float>(1, "Hue");
+ MutableSpan<float> saturation = params.uninitialized_single_output<float>(2, "Saturation");
+ MutableSpan<float> lightness = params.uninitialized_single_output<float>(3, "Lightness");
+ MutableSpan<float> alpha = params.uninitialized_single_output_if_required<float>(4, "Alpha");
+
+ for (int64_t i : mask) {
+ rgb_to_hsl(colors[i].r, colors[i].g, colors[i].b, &hue[i], &saturation[i], &lightness[i]);
+ }
+
+ if (!alpha.is_empty()) {
+ for (int64_t i : mask) {
+ alpha[i] = colors[i].a;
+ }
+ }
+ }
+};
+
+static void fn_node_separate_color_build_multi_function(NodeMultiFunctionBuilder &builder)
+{
+ const NodeCombSepColor &storage = node_storage(builder.node());
+
+ switch (storage.mode) {
+ case NODE_COMBSEP_COLOR_RGB: {
+ static SeparateRGBAFunction fn;
+ builder.set_matching_fn(fn);
+ break;
+ }
+ case NODE_COMBSEP_COLOR_HSV: {
+ static SeparateHSVAFunction fn;
+ builder.set_matching_fn(fn);
+ break;
+ }
+ case NODE_COMBSEP_COLOR_HSL: {
+ static SeparateHSLAFunction fn;
+ builder.set_matching_fn(fn);
+ break;
+ }
+ default: {
+ BLI_assert_unreachable();
+ break;
+ }
+ }
+}
+
+} // namespace blender::nodes
+
+void register_node_type_fn_separate_color(void)
+{
+ static bNodeType ntype;
+
+ fn_node_type_base(&ntype, FN_NODE_SEPARATE_COLOR, "Separate Color", NODE_CLASS_CONVERTER);
+ ntype.declare = blender::nodes::fn_node_separate_color_declare;
+ node_type_update(&ntype, blender::nodes::fn_node_separate_color_update);
+ node_type_init(&ntype, blender::nodes::fn_node_separate_color_init);
+ node_type_storage(
+ &ntype, "NodeCombSepColor", node_free_standard_storage, node_copy_standard_storage);
+ ntype.build_multi_function = blender::nodes::fn_node_separate_color_build_multi_function;
+ ntype.draw_buttons = blender::nodes::fn_node_separate_color_layout;
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/intern/node_util.c b/source/blender/nodes/intern/node_util.c
index 5d2e1663ae3..e8be093c606 100644
--- a/source/blender/nodes/intern/node_util.c
+++ b/source/blender/nodes/intern/node_util.c
@@ -226,6 +226,39 @@ void node_filter_label(const bNodeTree *UNUSED(ntree), const bNode *node, char *
BLI_strncpy(label, IFACE_(name), maxlen);
}
+void node_combsep_color_label(const ListBase *sockets, NodeCombSepColorMode mode)
+{
+ bNodeSocket *sock1 = (bNodeSocket *)sockets->first;
+ bNodeSocket *sock2 = sock1->next;
+ bNodeSocket *sock3 = sock2->next;
+
+ node_sock_label_clear(sock1);
+ node_sock_label_clear(sock2);
+ node_sock_label_clear(sock3);
+
+ switch (mode) {
+ case NODE_COMBSEP_COLOR_RGB:
+ node_sock_label(sock1, "Red");
+ node_sock_label(sock2, "Green");
+ node_sock_label(sock3, "Blue");
+ break;
+ case NODE_COMBSEP_COLOR_HSL:
+ node_sock_label(sock1, "Hue");
+ node_sock_label(sock2, "Saturation");
+ node_sock_label(sock3, "Lightness");
+ break;
+ case NODE_COMBSEP_COLOR_HSV:
+ node_sock_label(sock1, "Hue");
+ node_sock_label(sock2, "Saturation");
+ node_sock_label(sock3, "Value");
+ break;
+ default: {
+ BLI_assert_unreachable();
+ break;
+ }
+ }
+}
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/nodes/intern/node_util.h b/source/blender/nodes/intern/node_util.h
index de03a176c0c..0a2a7a70091 100644
--- a/source/blender/nodes/intern/node_util.h
+++ b/source/blender/nodes/intern/node_util.h
@@ -65,6 +65,7 @@ void node_filter_label(const struct bNodeTree *ntree,
const struct bNode *node,
char *label,
int maxlen);
+void node_combsep_color_label(const ListBase *sockets, NodeCombSepColorMode mode);
/*** Link Handling */
diff --git a/source/blender/nodes/shader/CMakeLists.txt b/source/blender/nodes/shader/CMakeLists.txt
index 9b4ea0e0db6..3e90f185168 100644
--- a/source/blender/nodes/shader/CMakeLists.txt
+++ b/source/blender/nodes/shader/CMakeLists.txt
@@ -82,6 +82,7 @@ set(SRC
nodes/node_shader_rgb.cc
nodes/node_shader_rgb_to_bw.cc
nodes/node_shader_script.cc
+ nodes/node_shader_sepcomb_color.cc
nodes/node_shader_sepcomb_hsv.cc
nodes/node_shader_sepcomb_rgb.cc
nodes/node_shader_sepcomb_xyz.cc
diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcomb_color.cc b/source/blender/nodes/shader/nodes/node_shader_sepcomb_color.cc
new file mode 100644
index 00000000000..a80b4ed0444
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_sepcomb_color.cc
@@ -0,0 +1,162 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup shdnodes
+ */
+
+#include "node_shader_util.hh"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+static void node_combsep_color_init(bNodeTree *UNUSED(tree), bNode *node)
+{
+ NodeCombSepColor *data = MEM_cnew<NodeCombSepColor>(__func__);
+ data->mode = NODE_COMBSEP_COLOR_RGB;
+ node->storage = data;
+}
+
+/* **************** SEPARATE COLOR ******************** */
+
+namespace blender::nodes::node_shader_separate_color_cc {
+
+NODE_STORAGE_FUNCS(NodeCombSepColor)
+
+static void sh_node_sepcolor_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Color>(N_("Color")).default_value({0.8f, 0.8f, 0.8f, 1.0f});
+ b.add_output<decl::Float>(N_("Red"));
+ b.add_output<decl::Float>(N_("Green"));
+ b.add_output<decl::Float>(N_("Blue"));
+}
+
+static void node_sepcolor_update(bNodeTree *ntree, bNode *node)
+{
+ const NodeCombSepColor &storage = node_storage(*node);
+ node_combsep_color_label(&node->outputs, (NodeCombSepColorMode)storage.mode);
+}
+
+static const char *gpu_shader_get_name(int mode)
+{
+ switch (mode) {
+ case NODE_COMBSEP_COLOR_RGB:
+ return "separate_color_rgb";
+ case NODE_COMBSEP_COLOR_HSV:
+ return "separate_color_hsv";
+ case NODE_COMBSEP_COLOR_HSL:
+ return "separate_color_hsl";
+ }
+
+ return nullptr;
+}
+
+static int gpu_shader_sepcolor(GPUMaterial *mat,
+ bNode *node,
+ bNodeExecData *UNUSED(execdata),
+ GPUNodeStack *in,
+ GPUNodeStack *out)
+{
+ const NodeCombSepColor &storage = node_storage(*node);
+ const char *name = gpu_shader_get_name(storage.mode);
+ if (name != nullptr) {
+ return GPU_stack_link(mat, node, name, in, out);
+ }
+
+ return 0;
+}
+
+} // namespace blender::nodes::node_shader_separate_color_cc
+
+void register_node_type_sh_sepcolor()
+{
+ namespace file_ns = blender::nodes::node_shader_separate_color_cc;
+
+ static bNodeType ntype;
+
+ sh_node_type_base(&ntype, SH_NODE_SEPARATE_COLOR, "Separate Color", NODE_CLASS_CONVERTER);
+ ntype.declare = file_ns::sh_node_sepcolor_declare;
+ node_type_update(&ntype, file_ns::node_sepcolor_update);
+ node_type_init(&ntype, node_combsep_color_init);
+ node_type_storage(
+ &ntype, "NodeCombSepColor", node_free_standard_storage, node_copy_standard_storage);
+ node_type_gpu(&ntype, file_ns::gpu_shader_sepcolor);
+
+ nodeRegisterType(&ntype);
+}
+
+/* **************** COMBINE COLOR ******************** */
+
+namespace blender::nodes::node_shader_combine_color_cc {
+
+NODE_STORAGE_FUNCS(NodeCombSepColor)
+
+static void sh_node_combcolor_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Float>(N_("Red")).default_value(0.0f).min(0.0f).max(1.0f).subtype(PROP_FACTOR);
+ b.add_input<decl::Float>(N_("Green"))
+ .default_value(0.0f)
+ .min(0.0f)
+ .max(1.0f)
+ .subtype(PROP_FACTOR);
+ b.add_input<decl::Float>(N_("Blue"))
+ .default_value(0.0f)
+ .min(0.0f)
+ .max(1.0f)
+ .subtype(PROP_FACTOR);
+ b.add_output<decl::Color>(N_("Color"));
+}
+
+static void node_combcolor_update(bNodeTree *ntree, bNode *node)
+{
+ const NodeCombSepColor &storage = node_storage(*node);
+ node_combsep_color_label(&node->inputs, (NodeCombSepColorMode)storage.mode);
+}
+
+static const char *gpu_shader_get_name(int mode)
+{
+ switch (mode) {
+ case NODE_COMBSEP_COLOR_RGB:
+ return "combine_color_rgb";
+ case NODE_COMBSEP_COLOR_HSV:
+ return "combine_color_hsv";
+ case NODE_COMBSEP_COLOR_HSL:
+ return "combine_color_hsl";
+ }
+
+ return nullptr;
+}
+
+static int gpu_shader_combcolor(GPUMaterial *mat,
+ bNode *node,
+ bNodeExecData *UNUSED(execdata),
+ GPUNodeStack *in,
+ GPUNodeStack *out)
+{
+ const NodeCombSepColor &storage = node_storage(*node);
+ const char *name = gpu_shader_get_name(storage.mode);
+ if (name != nullptr) {
+ return GPU_stack_link(mat, node, name, in, out);
+ }
+
+ return 0;
+}
+
+} // namespace blender::nodes::node_shader_combine_color_cc
+
+void register_node_type_sh_combcolor()
+{
+ namespace file_ns = blender::nodes::node_shader_combine_color_cc;
+
+ static bNodeType ntype;
+
+ sh_node_type_base(&ntype, SH_NODE_COMBINE_COLOR, "Combine Color", NODE_CLASS_CONVERTER);
+ ntype.declare = file_ns::sh_node_combcolor_declare;
+ node_type_update(&ntype, file_ns::node_combcolor_update);
+ node_type_init(&ntype, node_combsep_color_init);
+ node_type_storage(
+ &ntype, "NodeCombSepColor", node_free_standard_storage, node_copy_standard_storage);
+ node_type_gpu(&ntype, file_ns::gpu_shader_combcolor);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcomb_hsv.cc b/source/blender/nodes/shader/nodes/node_shader_sepcomb_hsv.cc
index 129c8cf4b97..6dfabe48292 100644
--- a/source/blender/nodes/shader/nodes/node_shader_sepcomb_hsv.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_sepcomb_hsv.cc
@@ -36,7 +36,7 @@ void register_node_type_sh_sephsv()
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_SEPHSV, "Separate HSV", NODE_CLASS_CONVERTER);
+ sh_node_type_base(&ntype, SH_NODE_SEPHSV_LEGACY, "Separate HSV", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::node_declare_sephsv;
node_type_gpu(&ntype, file_ns::gpu_shader_sephsv);
@@ -72,7 +72,7 @@ void register_node_type_sh_combhsv()
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_COMBHSV, "Combine HSV", NODE_CLASS_CONVERTER);
+ sh_node_type_base(&ntype, SH_NODE_COMBHSV_LEGACY, "Combine HSV", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::node_declare_combhsv;
node_type_gpu(&ntype, file_ns::gpu_shader_combhsv);
diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcomb_rgb.cc b/source/blender/nodes/shader/nodes/node_shader_sepcomb_rgb.cc
index 657f591a50c..28b55047633 100644
--- a/source/blender/nodes/shader/nodes/node_shader_sepcomb_rgb.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_sepcomb_rgb.cc
@@ -76,7 +76,7 @@ void register_node_type_sh_seprgb()
static bNodeType ntype;
- sh_fn_node_type_base(&ntype, SH_NODE_SEPRGB, "Separate RGB", NODE_CLASS_CONVERTER);
+ sh_fn_node_type_base(&ntype, SH_NODE_SEPRGB_LEGACY, "Separate RGB", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::sh_node_seprgb_declare;
node_type_gpu(&ntype, file_ns::gpu_shader_seprgb);
ntype.build_multi_function = file_ns::sh_node_seprgb_build_multi_function;
@@ -119,7 +119,7 @@ void register_node_type_sh_combrgb()
static bNodeType ntype;
- sh_fn_node_type_base(&ntype, SH_NODE_COMBRGB, "Combine RGB", NODE_CLASS_CONVERTER);
+ sh_fn_node_type_base(&ntype, SH_NODE_COMBRGB_LEGACY, "Combine RGB", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::sh_node_combrgb_declare;
node_type_gpu(&ntype, file_ns::gpu_shader_combrgb);
ntype.build_multi_function = file_ns::sh_node_combrgb_build_multi_function;
diff --git a/source/blender/nodes/texture/CMakeLists.txt b/source/blender/nodes/texture/CMakeLists.txt
index 7706f118507..8eb4d2bfacd 100644
--- a/source/blender/nodes/texture/CMakeLists.txt
+++ b/source/blender/nodes/texture/CMakeLists.txt
@@ -25,6 +25,7 @@ set(SRC
nodes/node_texture_bricks.c
nodes/node_texture_checker.c
nodes/node_texture_common.c
+ nodes/node_texture_combine_color.c
nodes/node_texture_compose.c
nodes/node_texture_coord.c
nodes/node_texture_curves.c
@@ -38,6 +39,7 @@ set(SRC
nodes/node_texture_output.c
nodes/node_texture_proc.c
nodes/node_texture_rotate.c
+ nodes/node_texture_separate_color.c
nodes/node_texture_scale.c
nodes/node_texture_texture.c
nodes/node_texture_translate.c
diff --git a/source/blender/nodes/texture/nodes/node_texture_combine_color.c b/source/blender/nodes/texture/nodes/node_texture_combine_color.c
new file mode 100644
index 00000000000..3ba6755e7c6
--- /dev/null
+++ b/source/blender/nodes/texture/nodes/node_texture_combine_color.c
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup texnodes
+ */
+
+#include "BLI_listbase.h"
+#include "NOD_texture.h"
+#include "node_texture_util.h"
+
+static bNodeSocketTemplate inputs[] = {
+ {SOCK_FLOAT, N_("Red"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ {SOCK_FLOAT, N_("Green"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ {SOCK_FLOAT, N_("Blue"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ {SOCK_FLOAT, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ {-1, ""},
+};
+static bNodeSocketTemplate outputs[] = {
+ {SOCK_RGBA, N_("Color")},
+ {-1, ""},
+};
+
+static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
+{
+ int i;
+ for (i = 0; i < 4; i++) {
+ out[i] = tex_input_value(in[i], p, thread);
+ }
+ /* Apply color space if required. */
+ switch (node->custom1) {
+ case NODE_COMBSEP_COLOR_RGB: {
+ /* Pass */
+ break;
+ }
+ case NODE_COMBSEP_COLOR_HSV: {
+ hsv_to_rgb_v(out, out);
+ break;
+ }
+ case NODE_COMBSEP_COLOR_HSL: {
+ hsl_to_rgb_v(out, out);
+ break;
+ }
+ default: {
+ BLI_assert_unreachable();
+ break;
+ }
+ }
+}
+
+static void update(bNodeTree *ntree, bNode *node)
+{
+ node_combsep_color_label(&node->inputs, (NodeCombSepColorMode)node->custom1);
+}
+
+static void exec(void *data,
+ int UNUSED(thread),
+ bNode *node,
+ bNodeExecData *execdata,
+ bNodeStack **in,
+ bNodeStack **out)
+{
+ tex_output(node, execdata, in, out[0], &colorfn, data);
+}
+
+void register_node_type_tex_combine_color(void)
+{
+ static bNodeType ntype;
+
+ tex_node_type_base(&ntype, TEX_NODE_COMBINE_COLOR, "Combine Color", NODE_CLASS_OP_COLOR);
+ node_type_socket_templates(&ntype, inputs, outputs);
+ node_type_exec(&ntype, NULL, NULL, exec);
+ node_type_update(&ntype, update);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/texture/nodes/node_texture_compose.c b/source/blender/nodes/texture/nodes/node_texture_compose.c
index e341b65ac97..ef14062c72d 100644
--- a/source/blender/nodes/texture/nodes/node_texture_compose.c
+++ b/source/blender/nodes/texture/nodes/node_texture_compose.c
@@ -42,7 +42,7 @@ void register_node_type_tex_compose(void)
{
static bNodeType ntype;
- tex_node_type_base(&ntype, TEX_NODE_COMPOSE, "Combine RGBA", NODE_CLASS_OP_COLOR);
+ tex_node_type_base(&ntype, TEX_NODE_COMPOSE_LEGACY, "Combine RGBA", NODE_CLASS_OP_COLOR);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_exec(&ntype, NULL, NULL, exec);
diff --git a/source/blender/nodes/texture/nodes/node_texture_decompose.c b/source/blender/nodes/texture/nodes/node_texture_decompose.c
index 21c3944e255..2d42fa4602e 100644
--- a/source/blender/nodes/texture/nodes/node_texture_decompose.c
+++ b/source/blender/nodes/texture/nodes/node_texture_decompose.c
@@ -62,7 +62,7 @@ void register_node_type_tex_decompose(void)
{
static bNodeType ntype;
- tex_node_type_base(&ntype, TEX_NODE_DECOMPOSE, "Separate RGBA", NODE_CLASS_OP_COLOR);
+ tex_node_type_base(&ntype, TEX_NODE_DECOMPOSE_LEGACY, "Separate RGBA", NODE_CLASS_OP_COLOR);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_exec(&ntype, NULL, NULL, exec);
diff --git a/source/blender/nodes/texture/nodes/node_texture_separate_color.c b/source/blender/nodes/texture/nodes/node_texture_separate_color.c
new file mode 100644
index 00000000000..94f9fafe838
--- /dev/null
+++ b/source/blender/nodes/texture/nodes/node_texture_separate_color.c
@@ -0,0 +1,102 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup texnodes
+ */
+
+#include "BLI_listbase.h"
+#include "NOD_texture.h"
+#include "node_texture_util.h"
+#include <math.h>
+
+static bNodeSocketTemplate inputs[] = {
+ {SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f},
+ {-1, ""},
+};
+static bNodeSocketTemplate outputs[] = {
+ {SOCK_FLOAT, N_("Red")},
+ {SOCK_FLOAT, N_("Green")},
+ {SOCK_FLOAT, N_("Blue")},
+ {SOCK_FLOAT, N_("Alpha")},
+ {-1, ""},
+};
+
+static void apply_color_space(float *out, NodeCombSepColorMode type)
+{
+ switch (type) {
+ case NODE_COMBSEP_COLOR_RGB: {
+ /* Pass */
+ break;
+ }
+ case NODE_COMBSEP_COLOR_HSV: {
+ rgb_to_hsv_v(out, out);
+ break;
+ }
+ case NODE_COMBSEP_COLOR_HSL: {
+ rgb_to_hsl_v(out, out);
+ break;
+ }
+ default: {
+ BLI_assert_unreachable();
+ break;
+ }
+ }
+}
+
+static void valuefn_r(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
+{
+ tex_input_rgba(out, in[0], p, thread);
+ apply_color_space(out, (NodeCombSepColorMode)node->custom1);
+ *out = out[0];
+}
+
+static void valuefn_g(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
+{
+ tex_input_rgba(out, in[0], p, thread);
+ apply_color_space(out, (NodeCombSepColorMode)node->custom1);
+ *out = out[1];
+}
+
+static void valuefn_b(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)
+{
+ tex_input_rgba(out, in[0], p, thread);
+ apply_color_space(out, (NodeCombSepColorMode)node->custom1);
+ *out = out[2];
+}
+
+static void valuefn_a(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack **in, short thread)
+{
+ tex_input_rgba(out, in[0], p, thread);
+ *out = out[3];
+}
+
+static void update(bNodeTree *ntree, bNode *node)
+{
+ node_combsep_color_label(&node->outputs, (NodeCombSepColorMode)node->custom1);
+}
+
+static void exec(void *data,
+ int UNUSED(thread),
+ bNode *node,
+ bNodeExecData *execdata,
+ bNodeStack **in,
+ bNodeStack **out)
+{
+ tex_output(node, execdata, in, out[0], &valuefn_r, data);
+ tex_output(node, execdata, in, out[1], &valuefn_g, data);
+ tex_output(node, execdata, in, out[2], &valuefn_b, data);
+ tex_output(node, execdata, in, out[3], &valuefn_a, data);
+}
+
+void register_node_type_tex_separate_color(void)
+{
+ static bNodeType ntype;
+
+ tex_node_type_base(&ntype, TEX_NODE_SEPARATE_COLOR, "Separate Color", NODE_CLASS_OP_COLOR);
+ node_type_socket_templates(&ntype, inputs, outputs);
+ node_type_exec(&ntype, NULL, NULL, exec);
+ node_type_update(&ntype, update);
+
+ nodeRegisterType(&ntype);
+}