[Bf-blender-cvs] [bea5fe65055] master: Nodes: Add Exclusion color mix mode

Charlie Jolly noreply at git.blender.org
Fri Dec 16 16:42:54 CET 2022


Commit: bea5fe65055e32a0a95232450b014c0d84e21e68
Author: Charlie Jolly
Date:   Fri Nov 18 12:52:14 2022 +0000
Branches: master
https://developer.blender.org/rBbea5fe65055e32a0a95232450b014c0d84e21e68

Nodes: Add Exclusion color mix mode

Expands Color Mix nodes with new Exclusion mode.

Similar to Difference but produces less contrast.

Requested by Pierre Schiller @3D_director and
@OmarSquircleArt on twitter.

Differential Revision: https://developer.blender.org/D16543

===================================================================

M	intern/cycles/kernel/osl/shaders/node_color_blend.h
M	intern/cycles/kernel/osl/shaders/node_mix.osl
M	intern/cycles/kernel/osl/shaders/node_mix_color.osl
M	intern/cycles/kernel/svm/color_util.h
M	intern/cycles/kernel/svm/types.h
M	intern/cycles/scene/shader_nodes.cpp
M	source/blender/blenkernel/intern/material.cc
M	source/blender/compositor/nodes/COM_MixNode.cc
M	source/blender/compositor/operations/COM_MixOperation.cc
M	source/blender/compositor/operations/COM_MixOperation.h
M	source/blender/freestyle/intern/python/BPy_Freestyle.cpp
M	source/blender/gpu/shaders/common/gpu_shader_common_mix_rgb.glsl
M	source/blender/gpu/shaders/material/gpu_shader_material_mix_color.glsl
M	source/blender/makesdna/DNA_material_types.h
M	source/blender/makesrna/intern/rna_material.c
M	source/blender/nodes/composite/nodes/node_composite_mixrgb.cc
M	source/blender/nodes/shader/nodes/node_shader_mix.cc
M	source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc

===================================================================

diff --git a/intern/cycles/kernel/osl/shaders/node_color_blend.h b/intern/cycles/kernel/osl/shaders/node_color_blend.h
index ab4b4809a97..205784c0cda 100644
--- a/intern/cycles/kernel/osl/shaders/node_color_blend.h
+++ b/intern/cycles/kernel/osl/shaders/node_color_blend.h
@@ -73,6 +73,11 @@ color node_mix_diff(float t, color col1, color col2)
   return mix(col1, abs(col1 - col2), t);
 }
 
+color node_mix_exclusion(float t, color col1, color col2)
+{
+  return max(mix(col1, col1 + col2 - 2.0 * col1 * col2, t), 0.0);
+}
+
 color node_mix_dark(float t, color col1, color col2)
 {
   return mix(col1, min(col1, col2), t);
diff --git a/intern/cycles/kernel/osl/shaders/node_mix.osl b/intern/cycles/kernel/osl/shaders/node_mix.osl
index 1bf3abc7f08..6b6806dd05f 100644
--- a/intern/cycles/kernel/osl/shaders/node_mix.osl
+++ b/intern/cycles/kernel/osl/shaders/node_mix.osl
@@ -76,6 +76,11 @@ color node_mix_diff(float t, color col1, color col2)
   return mix(col1, abs(col1 - col2), t);
 }
 
+color node_mix_exclusion(float t, color col1, color col2)
+{
+  return max(mix(col1, col1 + col2 - 2.0 * col1 * col2, t), 0.0);
+}
+
 color node_mix_dark(float t, color col1, color col2)
 {
   return mix(col1, min(col1, col2), t);
@@ -291,6 +296,8 @@ shader node_mix(string mix_type = "mix",
     Color = node_mix_div(t, Color1, Color2);
   if (mix_type == "difference")
     Color = node_mix_diff(t, Color1, Color2);
+  if (mix_type == "exclusion")
+    Color = node_mix_exclusion(t, Color1, Color2);
   if (mix_type == "darken")
     Color = node_mix_dark(t, Color1, Color2);
   if (mix_type == "lighten")
diff --git a/intern/cycles/kernel/osl/shaders/node_mix_color.osl b/intern/cycles/kernel/osl/shaders/node_mix_color.osl
index 3ddd89ed306..30521aa1efd 100644
--- a/intern/cycles/kernel/osl/shaders/node_mix_color.osl
+++ b/intern/cycles/kernel/osl/shaders/node_mix_color.osl
@@ -31,6 +31,8 @@ shader node_mix_color(string blend_type = "mix",
     Result = node_mix_div(t, A, B);
   if (blend_type == "difference")
     Result = node_mix_diff(t, A, B);
+  if (blend_type == "exclusion")
+    Result = node_mix_exclusion(t, A, B);
   if (blend_type == "darken")
     Result = node_mix_dark(t, A, B);
   if (blend_type == "lighten")
diff --git a/intern/cycles/kernel/svm/color_util.h b/intern/cycles/kernel/svm/color_util.h
index 96adb6fd64c..5e9e9db82af 100644
--- a/intern/cycles/kernel/svm/color_util.h
+++ b/intern/cycles/kernel/svm/color_util.h
@@ -79,6 +79,11 @@ ccl_device float3 svm_mix_diff(float t, float3 col1, float3 col2)
   return interp(col1, fabs(col1 - col2), t);
 }
 
+ccl_device float3 svm_mix_exclusion(float t, float3 col1, float3 col2)
+{
+  return max(interp(col1, col1 + col2 - 2.0f * col1 * col2, t), zero_float3());
+}
+
 ccl_device float3 svm_mix_dark(float t, float3 col1, float3 col2)
 {
   return interp(col1, min(col1, col2), t);
@@ -266,6 +271,8 @@ ccl_device_noinline_cpu float3 svm_mix(NodeMix type, float t, float3 c1, float3
       return svm_mix_div(t, c1, c2);
     case NODE_MIX_DIFF:
       return svm_mix_diff(t, c1, c2);
+    case NODE_MIX_EXCLUSION:
+      return svm_mix_exclusion(t, c1, c2);
     case NODE_MIX_DARK:
       return svm_mix_dark(t, c1, c2);
     case NODE_MIX_LIGHT:
diff --git a/intern/cycles/kernel/svm/types.h b/intern/cycles/kernel/svm/types.h
index 9dd8f196e0f..7e956505c7f 100644
--- a/intern/cycles/kernel/svm/types.h
+++ b/intern/cycles/kernel/svm/types.h
@@ -136,6 +136,7 @@ typedef enum NodeMix {
   NODE_MIX_COL,
   NODE_MIX_SOFT,
   NODE_MIX_LINEAR,
+  NODE_MIX_EXCLUSION,
   NODE_MIX_CLAMP /* used for the clamp UI option */
 } NodeMix;
 
diff --git a/intern/cycles/scene/shader_nodes.cpp b/intern/cycles/scene/shader_nodes.cpp
index e95f362793f..8cd64cd189e 100644
--- a/intern/cycles/scene/shader_nodes.cpp
+++ b/intern/cycles/scene/shader_nodes.cpp
@@ -4948,6 +4948,7 @@ NODE_DEFINE(MixNode)
   type_enum.insert("color", NODE_MIX_COL);
   type_enum.insert("soft_light", NODE_MIX_SOFT);
   type_enum.insert("linear_light", NODE_MIX_LINEAR);
+  type_enum.insert("exclusion", NODE_MIX_EXCLUSION);
   SOCKET_ENUM(mix_type, "Type", type_enum, NODE_MIX_BLEND);
 
   SOCKET_BOOLEAN(use_clamp, "Use Clamp", false);
@@ -5026,6 +5027,7 @@ NODE_DEFINE(MixColorNode)
   type_enum.insert("color", NODE_MIX_COL);
   type_enum.insert("soft_light", NODE_MIX_SOFT);
   type_enum.insert("linear_light", NODE_MIX_LINEAR);
+  type_enum.insert("exclusion", NODE_MIX_EXCLUSION);
   SOCKET_ENUM(blend_type, "Type", type_enum, NODE_MIX_BLEND);
 
   SOCKET_IN_FLOAT(fac, "Factor", 0.5f);
diff --git a/source/blender/blenkernel/intern/material.cc b/source/blender/blenkernel/intern/material.cc
index 51e61dbebad..4b0508ddf20 100644
--- a/source/blender/blenkernel/intern/material.cc
+++ b/source/blender/blenkernel/intern/material.cc
@@ -1689,6 +1689,14 @@ void ramp_blend(int type, float r_col[3], const float fac, const float col[3])
       r_col[1] = facm * (r_col[1]) + fac * fabsf(r_col[1] - col[1]);
       r_col[2] = facm * (r_col[2]) + fac * fabsf(r_col[2] - col[2]);
       break;
+    case MA_RAMP_EXCLUSION:
+      r_col[0] = max_ff(facm * (r_col[0]) + fac * (r_col[0] + col[0] - 2.0f * r_col[0] * col[0]),
+                        0.0f);
+      r_col[1] = max_ff(facm * (r_col[1]) + fac * (r_col[1] + col[1] - 2.0f * r_col[1] * col[1]),
+                        0.0f);
+      r_col[2] = max_ff(facm * (r_col[2]) + fac * (r_col[2] + col[2] - 2.0f * r_col[2] * col[2]),
+                        0.0f);
+      break;
     case MA_RAMP_DARK:
       r_col[0] = min_ff(r_col[0], col[0]) * fac + r_col[0] * facm;
       r_col[1] = min_ff(r_col[1], col[1]) * fac + r_col[1] * facm;
diff --git a/source/blender/compositor/nodes/COM_MixNode.cc b/source/blender/compositor/nodes/COM_MixNode.cc
index e9179d7063c..5fdb1cab7b1 100644
--- a/source/blender/compositor/nodes/COM_MixNode.cc
+++ b/source/blender/compositor/nodes/COM_MixNode.cc
@@ -57,6 +57,9 @@ void MixNode::convert_to_operations(NodeConverter &converter,
     case MA_RAMP_DIFF:
       convert_prog = new MixDifferenceOperation();
       break;
+    case MA_RAMP_EXCLUSION:
+      convert_prog = new MixExclusionOperation();
+      break;
     case MA_RAMP_SAT:
       convert_prog = new MixSaturationOperation();
       break;
diff --git a/source/blender/compositor/operations/COM_MixOperation.cc b/source/blender/compositor/operations/COM_MixOperation.cc
index 7a6c48b89c0..96b6cb52afe 100644
--- a/source/blender/compositor/operations/COM_MixOperation.cc
+++ b/source/blender/compositor/operations/COM_MixOperation.cc
@@ -494,7 +494,65 @@ void MixDifferenceOperation::update_memory_buffer_row(PixelCursor &p)
   }
 }
 
-/* ******** Mix Difference Operation ******** */
+/* ******** Mix Exclusion Operation ******** */
+
+void MixExclusionOperation::execute_pixel_sampled(float output[4],
+                                                  float x,
+                                                  float y,
+                                                  PixelSampler sampler)
+{
+  float input_color1[4];
+  float input_color2[4];
+  float input_value[4];
+
+  input_value_operation_->read_sampled(input_value, x, y, sampler);
+  input_color1_operation_->read_sampled(input_color1, x, y, sampler);
+  input_color2_operation_->read_sampled(input_color2, x, y, sampler);
+
+  float value = input_value[0];
+  if (this->use_value_alpha_multiply()) {
+    value *= input_color2[3];
+  }
+  float valuem = 1.0f - value;
+  output[0] = max_ff(valuem * input_color1[0] + value * (input_color1[0] + input_color2[0] -
+                                                         2.0f * input_color1[0] * input_color2[0]),
+                     0.0f);
+  output[1] = max_ff(valuem * input_color1[1] + value * (input_color1[1] + input_color2[1] -
+                                                         2.0f * input_color1[1] * input_color2[1]),
+                     0.0f);
+  output[2] = max_ff(valuem * input_color1[2] + value * (input_color1[2] + input_color2[2] -
+                                                         2.0f * input_color1[2] * input_color2[2]),
+                     0.0f);
+  output[3] = input_color1[3];
+
+  clamp_if_needed(output);
+}
+
+void MixExclusionOperation::update_memory_buffer_row(PixelCursor &p)
+{
+  while (p.out < p.row_end) {
+    float value = p.value[0];
+    if (this->use_value_alpha_multiply()) {
+      value *= p.color2[3];
+    }
+    const float value_m = 1.0f - value;
+    p.out[0] = max_ff(value_m * p.color1[0] +
+                          value * (p.color1[0] + p.color2[0] - 2.0f * p.color1[0] * p.color2[0]),
+                      0.0f);
+    p.out[1] = max_ff(value_m * p.color1[1] +
+                          value * (p.color1[1] + p.color2[1] - 2.0f * p.color1[1] * p.color2[1]),
+                      0.0f);
+    p.out[2] = max_ff(value_m * p.color1[2] +
+                          value * (p.color1[2] + p.color2[2] - 2.0f * p.color1[2] * p.color2[2]),
+                      0.0f);
+    p.out[3] = p.color1[3];
+
+    clamp_if_needed(p.out);
+    p.next();
+  }
+}
+
+/* ******** Mix Divide Operation ******** */
 
 void MixDivideOperation::execute_pixel_sampled(float output[4],
                                                float x,
diff --git a/source/blender/compositor/operations/COM_MixOperation.h b/source/blender/compositor/operations/COM_MixOperation.h
index 73c1f9fcb22..d7e5afcd9fc 100644
--- a/source/blender/compositor/operations/COM_MixOperation.h
+++ b/source/blender/compositor/operations/COM_MixOperation.h
@@ -143,6 +143,14 @@ class MixDifferenceOperation : public MixBaseOperation {
   void update_memory_buffer_row(PixelCursor &p) override;
 };
 
+class MixExclusionOperation : public MixBaseOperation {
+ public:
+  void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ protected:
+  void update_memory_buffer_row(PixelCursor &p) override;
+};
+
 class MixDivideOperation : public MixBaseOperation {
  public:
   void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override;
diff --git a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp
index f99e66c822d..402acd28602 100644
--- a/source/blender/fre

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list