Shading: Refactor Math node and use dynamic inputs.
authorOmarSquircleArt <omar.squircleart@gmail.com>
Sun, 18 Aug 2019 09:16:04 +0000 (11:16 +0200)
committerOmarSquircleArt <omar.squircleart@gmail.com>
Sun, 18 Aug 2019 09:16:04 +0000 (11:16 +0200)
- Implement dynamic inputs. The second input is now unavailable in single
operand math operators.
- Reimplemenet the clamp option using graph expansion for Cycles.
- Clean up code and unify naming between Blender and Cycles.
- Remove unused code.

Reviewers: brecht

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

19 files changed:
intern/cycles/blender/blender_shader.cpp
intern/cycles/kernel/shaders/node_math.osl
intern/cycles/kernel/svm/svm_math.h
intern/cycles/kernel/svm/svm_math_util.h
intern/cycles/kernel/svm/svm_types.h
intern/cycles/render/constant_fold.cpp
intern/cycles/render/constant_fold.h
intern/cycles/render/nodes.cpp
intern/cycles/render/nodes.h
intern/cycles/test/render_graph_finalize_test.cpp
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/intern/node.c
source/blender/blenloader/intern/versioning_cycles.c
source/blender/compositor/nodes/COM_MathNode.cpp
source/blender/gpu/shaders/gpu_shader_material.glsl
source/blender/makesdna/DNA_node_types.h
source/blender/makesrna/intern/rna_nodetree.c
source/blender/nodes/shader/nodes/node_shader_math.c
source/blender/nodes/texture/nodes/node_texture_math.c

index b95e88573fa9a026b5f434f99b7bdedf290846b6..626a1dad7db3415b119f01ad3f05a365b94a945e 100644 (file)
@@ -326,10 +326,10 @@ static ShaderNode *add_node(Scene *scene,
   }
   else if (b_node.is_a(&RNA_ShaderNodeMath)) {
     BL::ShaderNodeMath b_math_node(b_node);
-    MathNode *math = new MathNode();
-    math->type = (NodeMath)b_math_node.operation();
-    math->use_clamp = b_math_node.use_clamp();
-    node = math;
+    MathNode *math_node = new MathNode();
+    math_node->type = (NodeMathType)b_math_node.operation();
+    math_node->use_clamp = b_math_node.use_clamp();
+    node = math_node;
   }
   else if (b_node.is_a(&RNA_ShaderNodeVectorMath)) {
     BL::ShaderNodeVectorMath b_vector_math_node(b_node);
index 8830339e05f9d7a4e521e6f555fdba60e6145b10..fb59c783770d3995f4521654149a25b781ac8a0e 100644 (file)
 #include "stdosl.h"
 
 float safe_divide(float a, float b)
-{
-  float result;
-
-  if (b == 0.0)
-    result = 0.0;
-  else
-    result = a / b;
-
-  return result;
+{ 
+  return (b != 0.0) ? a / b : 0.0;
 }
 
 float safe_modulo(float a, float b)
 {
-  float result;
-
-  if (b == 0.0)
-    result = 0.0;
-  else
-    result = fmod(a, b);
-
-  return result;
+  return (b != 0.0) ? fmod(a, b) : 0.0;
 }
 
 float safe_sqrt(float a)
 {
-  float result;
-
-  if (a > 0.0)
-    result = sqrt(a);
-  else
-    result = 0.0;
-
-  return result;
+  return (a > 0.0) ? sqrt(a) : 0.0;
 }
 
 float safe_log(float a, float b)
 {
-  if (a < 0.0 || b < 0.0)
-    return 0.0;
-
-  return log(a) / log(b);
+  return (a > 0.0 && b > 0.0) ? log(a) / log(b) : 0.0;
 }
 
+/* OSL asin, acos, and pow functions are safe by default. */
 shader node_math(string type = "add",
-                 int use_clamp = 0,
-                 float Value1 = 0.0,
-                 float Value2 = 0.0,
+                 float Value1 = 0.5,
+                 float Value2 = 0.5,
                  output float Value = 0.0)
 {
-  /* OSL asin, acos, pow check for values that could give rise to nan */
-
   if (type == "add")
     Value = Value1 + Value2;
   else if (type == "subtract")
@@ -76,47 +50,46 @@ shader node_math(string type = "add",
     Value = Value1 * Value2;
   else if (type == "divide")
     Value = safe_divide(Value1, Value2);
-  else if (type == "sine")
-    Value = sin(Value1);
-  else if (type == "cosine")
-    Value = cos(Value1);
-  else if (type == "tangent")
-    Value = tan(Value1);
-  else if (type == "arcsine")
-    Value = asin(Value1);
-  else if (type == "arccosine")
-    Value = acos(Value1);
-  else if (type == "arctangent")
-    Value = atan(Value1);
   else if (type == "power")
     Value = pow(Value1, Value2);
   else if (type == "logarithm")
     Value = safe_log(Value1, Value2);
+  else if (type == "sqrt")
+    Value = safe_sqrt(Value1);
+  else if (type == "absolute")
+    Value = fabs(Value1);
   else if (type == "minimum")
     Value = min(Value1, Value2);
   else if (type == "maximum")
     Value = max(Value1, Value2);
-  else if (type == "round")
-    Value = floor(Value1 + 0.5);
   else if (type == "less_than")
     Value = Value1 < Value2;
   else if (type == "greater_than")
     Value = Value1 > Value2;
-  else if (type == "modulo")
-    Value = safe_modulo(Value1, Value2);
-  else if (type == "absolute")
-    Value = fabs(Value1);
-  else if (type == "arctan2")
-    Value = atan2(Value1, Value2);
+  else if (type == "round")
+    Value = floor(Value1 + 0.5);
   else if (type == "floor")
     Value = floor(Value1);
   else if (type == "ceil")
     Value = ceil(Value1);
-  else if (type == "fract")
+  else if (type == "fraction")
     Value = Value1 - floor(Value1);
-  else if (type == "sqrt")
-    Value = safe_sqrt(Value1);
-
-  if (use_clamp)
-    Value = clamp(Value, 0.0, 1.0);
+  else if (type == "modulo")
+    Value = safe_modulo(Value1, Value2);
+  else if (type == "sine")
+    Value = sin(Value1);
+  else if (type == "cosine")
+    Value = cos(Value1);
+  else if (type == "tangent")
+    Value = tan(Value1);
+  else if (type == "arcsine")
+    Value = asin(Value1);
+  else if (type == "arccosine")
+    Value = acos(Value1);
+  else if (type == "arctangent")
+    Value = atan(Value1);
+  else if (type == "arctan2")
+    Value = atan2(Value1, Value2);
+  else
+    warning("%s", "Unknown math operator!");
 }
index 5920913825be52604c647b2bcf69669ba5d44326..402290d72188fa803f777bf2997ef9a535557726 100644 (file)
 
 CCL_NAMESPACE_BEGIN
 
-/* Nodes */
-
 ccl_device void svm_node_math(KernelGlobals *kg,
                               ShaderData *sd,
                               float *stack,
-                              uint itype,
-                              uint f1_offset,
-                              uint f2_offset,
+                              uint type,
+                              uint inputs_stack_offsets,
+                              uint result_stack_offset,
                               int *offset)
 {
-  NodeMath type = (NodeMath)itype;
-  float f1 = stack_load_float(stack, f1_offset);
-  float f2 = stack_load_float(stack, f2_offset);
-  float f = svm_math(type, f1, f2);
+  uint a_stack_offset, b_stack_offset;
+  decode_node_uchar4(inputs_stack_offsets, &a_stack_offset, &b_stack_offset, NULL, NULL);
 
-  uint4 node1 = read_node(kg, offset);
+  float a = stack_load_float(stack, a_stack_offset);
+  float b = stack_load_float(stack, b_stack_offset);
+  float result = svm_math((NodeMathType)type, a, b);
 
-  stack_store_float(stack, node1.y, f);
+  stack_store_float(stack, result_stack_offset, result);
 }
 
 ccl_device void svm_node_vector_math(KernelGlobals *kg,
index e3544515f1b867dc0707aa61cf827a103f7ca88d..d880422648705486a1bcc70de692086e89f838ed 100644 (file)
@@ -51,64 +51,60 @@ ccl_device void svm_vector_math(
   }
 }
 
-ccl_device float svm_math(NodeMath type, float Fac1, float Fac2)
+ccl_device float svm_math(NodeMathType type, float a, float b)
 {
-  float Fac;
-
-  if (type == NODE_MATH_ADD)
-    Fac = Fac1 + Fac2;
-  else if (type == NODE_MATH_SUBTRACT)
-    Fac = Fac1 - Fac2;
-  else if (type == NODE_MATH_MULTIPLY)
-    Fac = Fac1 * Fac2;
-  else if (type == NODE_MATH_DIVIDE)
-    Fac = safe_divide(Fac1, Fac2);
-  else if (type == NODE_MATH_SINE)
-    Fac = sinf(Fac1);
-  else if (type == NODE_MATH_COSINE)
-    Fac = cosf(Fac1);
-  else if (type == NODE_MATH_TANGENT)
-    Fac = tanf(Fac1);
-  else if (type == NODE_MATH_ARCSINE)
-    Fac = safe_asinf(Fac1);
-  else if (type == NODE_MATH_ARCCOSINE)
-    Fac = safe_acosf(Fac1);
-  else if (type == NODE_MATH_ARCTANGENT)
-    Fac = atanf(Fac1);
-  else if (type == NODE_MATH_POWER)
-    Fac = safe_powf(Fac1, Fac2);
-  else if (type == NODE_MATH_LOGARITHM)
-    Fac = safe_logf(Fac1, Fac2);
-  else if (type == NODE_MATH_MINIMUM)
-    Fac = fminf(Fac1, Fac2);
-  else if (type == NODE_MATH_MAXIMUM)
-    Fac = fmaxf(Fac1, Fac2);
-  else if (type == NODE_MATH_ROUND)
-    Fac = floorf(Fac1 + 0.5f);
-  else if (type == NODE_MATH_LESS_THAN)
-    Fac = Fac1 < Fac2;
-  else if (type == NODE_MATH_GREATER_THAN)
-    Fac = Fac1 > Fac2;
-  else if (type == NODE_MATH_MODULO)
-    Fac = safe_modulo(Fac1, Fac2);
-  else if (type == NODE_MATH_ABSOLUTE)
-    Fac = fabsf(Fac1);
-  else if (type == NODE_MATH_ARCTAN2)
-    Fac = atan2f(Fac1, Fac2);
-  else if (type == NODE_MATH_FLOOR)
-    Fac = floorf(Fac1);
-  else if (type == NODE_MATH_CEIL)
-    Fac = ceilf(Fac1);
-  else if (type == NODE_MATH_FRACT)
-    Fac = Fac1 - floorf(Fac1);
-  else if (type == NODE_MATH_SQRT)
-    Fac = safe_sqrtf(Fac1);
-  else if (type == NODE_MATH_CLAMP)
-    Fac = saturate(Fac1);
-  else
-    Fac = 0.0f;
-
-  return Fac;
+  switch (type) {
+    case NODE_MATH_ADD:
+      return a + b;
+    case NODE_MATH_SUBTRACT:
+      return a - b;
+    case NODE_MATH_MULTIPLY:
+      return a * b;
+    case NODE_MATH_DIVIDE:
+      return safe_divide(a, b);
+    case NODE_MATH_POWER:
+      return safe_powf(a, b);
+    case NODE_MATH_LOGARITHM:
+      return safe_logf(a, b);
+    case NODE_MATH_SQRT:
+      return safe_sqrtf(a);
+    case NODE_MATH_ABSOLUTE:
+      return fabsf(a);
+    case NODE_MATH_MINIMUM:
+      return fminf(a, b);
+    case NODE_MATH_MAXIMUM:
+      return fmaxf(a, b);
+    case NODE_MATH_LESS_THAN:
+      return a < b;
+    case NODE_MATH_GREATER_THAN:
+      return a > b;
+    case NODE_MATH_ROUND:
+      return floorf(a + 0.5f);
+    case NODE_MATH_FLOOR:
+      return floorf(a);
+    case NODE_MATH_CEIL:
+      return ceilf(a);
+    case NODE_MATH_FRACTION:
+      return a - floorf(a);
+    case NODE_MATH_MODULO:
+      return safe_modulo(a, b);
+    case NODE_MATH_SINE:
+      return sinf(a);
+    case NODE_MATH_COSINE:
+      return cosf(a);
+    case NODE_MATH_TANGENT:
+      return tanf(a);
+    case NODE_MATH_ARCSINE:
+      return safe_asinf(a);
+    case NODE_MATH_ARCCOSINE:
+      return safe_acosf(a);
+    case NODE_MATH_ARCTANGENT:
+      return atanf(a);
+    case NODE_MATH_ARCTAN2:
+      return atan2f(a, b);
+    default:
+      return 0.0f;
+  }
 }
 
 /* Calculate color in range 800..12000 using an approximation
index 9a8a5401297b12654d34cbac6b6c282b612cdd8f..6b0d10adc74ee98e931542ee3b94f2f464d71d0f 100644 (file)
@@ -244,7 +244,7 @@ typedef enum NodeMix {
   NODE_MIX_CLAMP /* used for the clamp UI option */
 } NodeMix;
 
-typedef enum NodeMath {
+typedef enum NodeMathType {
   NODE_MATH_ADD,
   NODE_MATH_SUBTRACT,
   NODE_MATH_MULTIPLY,
@@ -267,10 +267,9 @@ typedef enum NodeMath {
   NODE_MATH_ARCTAN2,
   NODE_MATH_FLOOR,
   NODE_MATH_CEIL,
-  NODE_MATH_FRACT,
+  NODE_MATH_FRACTION,
   NODE_MATH_SQRT,
-  NODE_MATH_CLAMP /* used for the clamp UI option */
-} NodeMath;
+} NodeMathType;
 
 typedef enum NodeVectorMath {
   NODE_VECTOR_MATH_ADD,
index e475ff60eefbc8b0cdc7674083498d941420b907..d6fdc49434ee8338697bbc5faee1e1a678b36a7b 100644 (file)
@@ -301,7 +301,7 @@ void ConstantFolder::fold_mix(NodeMix type, bool clamp) const
   }
 }
 
-void ConstantFolder::fold_math(NodeMath type, bool clamp) const
+void ConstantFolder::fold_math(NodeMathType type) const
 {
   ShaderInput *value1_in = node->input("Value1");
   ShaderInput *value2_in = node->input("Value2");
@@ -310,25 +310,25 @@ void ConstantFolder::fold_math(NodeMath type, bool clamp) const
     case NODE_MATH_ADD:
       /* X + 0 == 0 + X == X */
       if (is_zero(value1_in)) {
-        try_bypass_or_make_constant(value2_in, clamp);
+        try_bypass_or_make_constant(value2_in);
       }
       else if (is_zero(value2_in)) {
-        try_bypass_or_make_constant(value1_in, clamp);
+        try_bypass_or_make_constant(value1_in);
       }
       break;
     case NODE_MATH_SUBTRACT:
       /* X - 0 == X */
       if (is_zero(value2_in)) {
-        try_bypass_or_make_constant(value1_in, clamp);
+        try_bypass_or_make_constant(value1_in);
       }
       break;
     case NODE_MATH_MULTIPLY:
       /* X * 1 == 1 * X == X */
       if (is_one(value1_in)) {
-        try_bypass_or_make_constant(value2_in, clamp);
+        try_bypass_or_make_constant(value2_in);
       }
       else if (is_one(value2_in)) {
-        try_bypass_or_make_constant(value1_in, clamp);
+        try_bypass_or_make_constant(value1_in);
       }
       /* X * 0 == 0 * X == 0 */
       else if (is_zero(value1_in) || is_zero(value2_in)) {
@@ -338,7 +338,7 @@ void ConstantFolder::fold_math(NodeMath type, bool clamp) const
     case NODE_MATH_DIVIDE:
       /* X / 1 == X */
       if (is_one(value2_in)) {
-        try_bypass_or_make_constant(value1_in, clamp);
+        try_bypass_or_make_constant(value1_in);
       }
       /* 0 / X == 0 */
       else if (is_zero(value1_in)) {
@@ -352,7 +352,7 @@ void ConstantFolder::fold_math(NodeMath type, bool clamp) const
       }
       /* X ^ 1 == X */
       else if (is_one(value2_in)) {
-        try_bypass_or_make_constant(value1_in, clamp);
+        try_bypass_or_make_constant(value1_in);
       }
     default:
       break;
index c14b94868dc810eabdb8efefe06486522c91fc95..d223fd861973c09b5635239baea9bd027df4fc16 100644 (file)
@@ -64,7 +64,7 @@ class ConstantFolder {
 
   /* Specific nodes. */
   void fold_mix(NodeMix type, bool clamp) const;
-  void fold_math(NodeMath type, bool clamp) const;
+  void fold_math(NodeMathType type) const;
   void fold_vector_math(NodeVectorMath type) const;
 };
 
index 9255181b4210d807c6f24540fde0dad19ba60805..7d4fcba9f3b299b3377427167e58d34853abd0b4 100644 (file)
@@ -5422,14 +5422,12 @@ NODE_DEFINE(MathNode)
   type_enum.insert("arctan2", NODE_MATH_ARCTAN2);
   type_enum.insert("floor", NODE_MATH_FLOOR);
   type_enum.insert("ceil", NODE_MATH_CEIL);
-  type_enum.insert("fract", NODE_MATH_FRACT);
+  type_enum.insert("fraction", NODE_MATH_FRACTION);
   type_enum.insert("sqrt", NODE_MATH_SQRT);
   SOCKET_ENUM(type, "Type", type_enum, NODE_MATH_ADD);
 
-  SOCKET_BOOLEAN(use_clamp, "Use Clamp", false);
-
-  SOCKET_IN_FLOAT(value1, "Value1", 0.0f);
-  SOCKET_IN_FLOAT(value2, "Value2", 0.0f);
+  SOCKET_IN_FLOAT(value1, "Value1", 0.5f);
+  SOCKET_IN_FLOAT(value2, "Value2", 0.5f);
 
   SOCKET_OUT_FLOAT(value, "Value");
 
@@ -5440,13 +5438,28 @@ MathNode::MathNode() : ShaderNode(node_type)
 {
 }
 
+void MathNode::expand(ShaderGraph *graph)
+{
+  if (use_clamp) {
+    ShaderOutput *result_out = output("Value");
+    if (!result_out->links.empty()) {
+      ClampNode *clamp_node = new ClampNode();
+      clamp_node->min = 0.0f;
+      clamp_node->max = 1.0f;
+      graph->add(clamp_node);
+      graph->relink(result_out, clamp_node->output("Result"));
+      graph->connect(result_out, clamp_node->input("Value"));
+    }
+  }
+}
+
 void MathNode::constant_fold(const ConstantFolder &folder)
 {
   if (folder.all_inputs_constant()) {
-    folder.make_constant_clamp(svm_math(type, value1, value2), use_clamp);
+    folder.make_constant(svm_math(type, value1, value2));
   }
   else {
-    folder.fold_math(type, use_clamp);
+    folder.fold_math(type);
   }
 }
 
@@ -5456,20 +5469,19 @@ void MathNode::compile(SVMCompiler &compiler)
   ShaderInput *value2_in = input("Value2");
   ShaderOutput *value_out = output("Value");
 
-  compiler.add_node(
-      NODE_MATH, type, compiler.stack_assign(value1_in), compiler.stack_assign(value2_in));
-  compiler.add_node(NODE_MATH, compiler.stack_assign(value_out));
+  int value1_stack_offset = compiler.stack_assign(value1_in);
+  int value2_stack_offset = compiler.stack_assign(value2_in);
+  int value_stack_offset = compiler.stack_assign(value_out);
 
-  if (use_clamp) {
-    compiler.add_node(NODE_MATH, NODE_MATH_CLAMP, compiler.stack_assign(value_out));
-    compiler.add_node(NODE_MATH, compiler.stack_assign(value_out));
-  }
+  compiler.add_node(NODE_MATH,
+                    type,
+                    compiler.encode_uchar4(value1_stack_offset, value2_stack_offset),
+                    value_stack_offset);
 }
 
 void MathNode::compile(OSLCompiler &compiler)
 {
   compiler.parameter(this, "type");
-  compiler.parameter(this, "use_clamp");
   compiler.add(this, "node_math");
 }
 
index d4708adf9afb361f64dc001bd64d8163a9b38458..514ab3db8eb268a97581fde96d1e6513d9b591dc 100644 (file)
@@ -1260,11 +1260,12 @@ class MathNode : public ShaderNode {
   {
     return NODE_GROUP_LEVEL_1;
   }
+  void expand(ShaderGraph *graph);
   void constant_fold(const ConstantFolder &folder);
 
   float value1;
   float value2;
-  NodeMath type;
+  NodeMathType type;
   bool use_clamp;
 };
 
index 7fb92bfb8625a91c57920904b4fc0e0f6b67dd46..11c758c93895cfdf8c3b3946d0586de42bde4a4c 100644 (file)
@@ -1003,7 +1003,7 @@ TEST_F(RenderGraph, constant_fold_math_clamp)
  * Includes 2 tests: constant on each side.
  */
 static void build_math_partial_test_graph(ShaderGraphBuilder &builder,
-                                          NodeMath type,
+                                          NodeMathType type,
                                           float constval)
 {
   builder
index 9b2db5acd3b411c8cfa5119a75d8f3a565d62862..7d427cb7799749258766ee740a2ae6aaf26c7271 100644 (file)
@@ -615,6 +615,7 @@ void nodeUpdateInternalLinks(struct bNodeTree *ntree, struct bNode *node);
 
 int nodeSocketIsHidden(struct bNodeSocket *sock);
 void ntreeTagUsedSockets(struct bNodeTree *ntree);
+void nodeSetSocketAvailability(struct bNodeSocket *sock, bool is_available);
 
 /* Node Clipboard */
 void BKE_node_clipboard_init(struct bNodeTree *ntree);
index 986571e34bdd08907a5f4397b2927a10aa0447c6..d64a5a33ef13d4ce782c076882a1bb74e438f967 100644 (file)
@@ -2799,6 +2799,16 @@ int nodeSocketIsHidden(bNodeSocket *sock)
   return ((sock->flag & (SOCK_HIDDEN | SOCK_UNAVAIL)) != 0);
 }
 
+void nodeSetSocketAvailability(bNodeSocket *sock, bool is_available)
+{
+  if (is_available) {
+    sock->flag &= ~SOCK_UNAVAIL;
+  }
+  else {
+    sock->flag |= SOCK_UNAVAIL;
+  }
+}
+
 /* ************** Node Clipboard *********** */
 
 #define USE_NODE_CB_VALIDATE
index cebe15e2719572f044b66037347c147e3df80f0b..10f24cff61b0ce3b2b50b5da65e598d9c4495dd1 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "BLI_math.h"
 #include "BLI_string.h"
+#include "BLI_listbase.h"
 #include "BLI_utildefines.h"
 
 #include "DNA_color_types.h"
@@ -185,7 +186,7 @@ static void square_roughness_node_insert(bNodeTree *ntree)
 
     /* Add sqrt node. */
     bNode *node = nodeAddStaticNode(NULL, ntree, SH_NODE_MATH);
-    node->custom1 = NODE_MATH_POW;
+    node->custom1 = NODE_MATH_POWER;
     node->locx = 0.5f * (fromnode->locx + tonode->locx);
     node->locy = 0.5f * (fromnode->locy + tonode->locy);
 
@@ -385,6 +386,46 @@ static void light_emission_unify(Light *light, const char *engine)
   }
 }
 
+/* The B input of the Math node is no longer used for single-operand operators.
+ * Previously, if the B input was linked and the A input was not, the B input
+ * was used as the input of the operator. To correct this, we move the link
+ * from B to A if B is linked and A is not.
+ */
+static void update_math_node_single_operand_operators(bNodeTree *ntree)
+{
+  bool need_update = false;
+
+  for (bNode *node = ntree->nodes.first; node; node = node->next) {
+    if (node->type == SH_NODE_MATH) {
+      if (ELEM(node->custom1,
+               NODE_MATH_SQRT,
+               NODE_MATH_CEIL,
+               NODE_MATH_SINE,
+               NODE_MATH_ROUND,
+               NODE_MATH_FLOOR,
+               NODE_MATH_COSINE,
+               NODE_MATH_ARCSINE,
+               NODE_MATH_TANGENT,
+               NODE_MATH_ABSOLUTE,
+               NODE_MATH_FRACTION,
+               NODE_MATH_ARCCOSINE,
+               NODE_MATH_ARCTANGENT)) {
+        bNodeSocket *sockA = BLI_findlink(&node->inputs, 0);
+        bNodeSocket *sockB = BLI_findlink(&node->inputs, 1);
+        if (!sockA->link && sockB->link) {
+          nodeAddLink(ntree, sockB->link->fromnode, sockB->link->fromsock, node, sockA);
+          nodeRemLink(ntree, sockB->link);
+          need_update = true;
+        }
+      }
+    }
+  }
+
+  if (need_update) {
+    ntreeUpdateTree(NULL, ntree);
+  }
+}
+
 void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bmain)
 {
   /* Particle shape shared with Eevee. */
@@ -526,4 +567,13 @@ void do_versions_after_linking_cycles(Main *bmain)
       }
     }
   }
+
+  if (!MAIN_VERSION_ATLEAST(bmain, 281, 2)) {
+    FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+      if (ntree->type == NTREE_SHADER) {
+        update_math_node_single_operand_operators(ntree);
+      }
+    }
+    FOREACH_NODETREE_END;
+  }
 }
index 5a2f934f37f997d4aff536f1067daceb0f8f5eeb..d13b34bb6b5d516fb7f96301472e1f27876593d0 100644 (file)
@@ -29,61 +29,61 @@ void MathNode::convertToOperations(NodeConverter &converter,
     case NODE_MATH_ADD:
       operation = new MathAddOperation();
       break;
-    case NODE_MATH_SUB:
+    case NODE_MATH_SUBTRACT:
       operation = new MathSubtractOperation();
       break;
-    case NODE_MATH_MUL:
+    case NODE_MATH_MULTIPLY:
       operation = new MathMultiplyOperation();
       break;
     case NODE_MATH_DIVIDE:
       operation = new MathDivideOperation();
       break;
-    case NODE_MATH_SIN:
+    case NODE_MATH_SINE:
       operation = new MathSineOperation();
       break;
-    case NODE_MATH_COS:
+    case NODE_MATH_COSINE:
       operation = new MathCosineOperation();
       break;
-    case NODE_MATH_TAN:
+    case NODE_MATH_TANGENT:
       operation = new MathTangentOperation();
       break;
-    case NODE_MATH_ASIN:
+    case NODE_MATH_ARCSINE:
       operation = new MathArcSineOperation();
       break;
-    case NODE_MATH_ACOS:
+    case NODE_MATH_ARCCOSINE:
       operation = new MathArcCosineOperation();
       break;
-    case NODE_MATH_ATAN:
+    case NODE_MATH_ARCTANGENT:
       operation = new MathArcTangentOperation();
       break;
-    case NODE_MATH_POW:
+    case NODE_MATH_POWER:
       operation = new MathPowerOperation();
       break;
-    case NODE_MATH_LOG:
+    case NODE_MATH_LOGARITHM:
       operation = new MathLogarithmOperation();
       break;
-    case NODE_MATH_MIN:
+    case NODE_MATH_MINIMUM:
       operation = new MathMinimumOperation();
       break;
-    case NODE_MATH_MAX:
+    case NODE_MATH_MAXIMUM:
       operation = new MathMaximumOperation();
       break;
     case NODE_MATH_ROUND:
       operation = new MathRoundOperation();
       break;
-    case NODE_MATH_LESS:
+    case NODE_MATH_LESS_THAN:
       operation = new MathLessThanOperation();
       break;
-    case NODE_MATH_GREATER:
+    case NODE_MATH_GREATER_THAN:
       operation = new MathGreaterThanOperation();
       break;
-    case NODE_MATH_MOD:
+    case NODE_MATH_MODULO:
       operation = new MathModuloOperation();
       break;
-    case NODE_MATH_ABS:
+    case NODE_MATH_ABSOLUTE:
       operation = new MathAbsoluteOperation();
       break;
-    case NODE_MATH_ATAN2:
+    case NODE_MATH_ARCTAN2:
       operation = new MathArcTan2Operation();
       break;
     case NODE_MATH_FLOOR:
@@ -92,7 +92,7 @@ void MathNode::convertToOperations(NodeConverter &converter,
     case NODE_MATH_CEIL:
       operation = new MathCeilOperation();
       break;
-    case NODE_MATH_FRACT:
+    case NODE_MATH_FRACTION:
       operation = new MathFractOperation();
       break;
     case NODE_MATH_SQRT:
index f077ae55d8fc6c57b1e5c95159004b20d4df6bb6..1529279ca0346c64e6857d222e9c6c882ac6dece 100644 (file)
@@ -250,178 +250,138 @@ void camera(vec3 co, out vec3 outview, out float outdepth, out float outdist)
   outview = normalize(co);
 }
 
-void math_add(float val1, float val2, out float outval)
+void math_add(float a, float b, out float result)
 {
-  outval = val1 + val2;
+  result = a + b;
 }
 
-void math_subtract(float val1, float val2, out float outval)
+void math_subtract(float a, float b, out float result)
 {
-  outval = val1 - val2;
+  result = a - b;
 }
 
-void math_multiply(float val1, float val2, out float outval)
+void math_multiply(float a, float b, out float result)
 {
-  outval = val1 * val2;
+  result = a * b;
 }
 
-void math_divide(float val1, float val2, out float outval)
+void math_divide(float a, float b, out float result)
 {
-  if (val2 == 0.0) {
-    outval = 0.0;
+  result = (b != 0.0) ? a / b : 0.0;
+}
+
+void math_power(float a, float b, out float result)
+{
+  if (a >= 0.0) {
+    result = compatible_pow(a, b);
   }
   else {
-    outval = val1 / val2;
+    float fraction = mod(abs(b), 1.0);
+    if (fraction > 0.999 || fraction < 0.001) {
+      result = compatible_pow(a, floor(b + 0.5));
+    }
+    else {
+      result = 0.0;
+    }
   }
 }
 
-void math_sine(float val, out float outval)
+void math_logarithm(float a, float b, out float result)
 {
-  outval = sin(val);
+  result = (a > 0.0 && b > 0.0) ? log2(a) / log2(b) : 0.0;
 }
 
-void math_cosine(float val, out float outval)
+void math_sqrt(float a, float b, out float result)
 {
-  outval = cos(val);
+  result = (a > 0.0) ? sqrt(a) : 0.0;
 }
 
-void math_tangent(float val, out float outval)
+void math_absolute(float a, float b, out float result)
 {
-  outval = tan(val);
+  result = abs(a);
 }
 
-void math_asin(float val, out float outval)
+void math_minimum(float a, float b, out float result)
 {
-  if (val <= 1.0 && val >= -1.0) {
-    outval = asin(val);
-  }
-  else {
-    outval = 0.0;
-  }
+  result = min(a, b);
 }
 
-void math_acos(float val, out float outval)
+void math_maximum(float a, float b, out float result)
 {
-  if (val <= 1.0 && val >= -1.0) {
-    outval = acos(val);
-  }
-  else {
-    outval = 0.0;
-  }
-}
-
-void math_atan(float val, out float outval)
-{
-  outval = atan(val);
+  result = max(a, b);
 }
 
-void math_pow(float val1, float val2, out float outval)
+void math_less_than(float a, float b, out float result)
 {
-  if (val1 >= 0.0) {
-    outval = compatible_pow(val1, val2);
-  }
-  else {
-    float val2_mod_1 = mod(abs(val2), 1.0);
-
-    if (val2_mod_1 > 0.999 || val2_mod_1 < 0.001) {
-      outval = compatible_pow(val1, floor(val2 + 0.5));
-    }
-    else {
-      outval = 0.0;
-    }
-  }
+  result = (a < b) ? 1.0 : 0.0;
 }
 
-void math_log(float val1, float val2, out float outval)
+void math_greater_than(float a, float b, out float result)
 {
-  if (val1 > 0.0 && val2 > 0.0) {
-    outval = log2(val1) / log2(val2);
-  }
-  else {
-    outval = 0.0;
-  }
+  result = (a > b) ? 1.0 : 0.0;
 }
 
-void math_max(float val1, float val2, out float outval)
+void math_round(float a, float b, out float result)
 {
-  outval = max(val1, val2);
+  result = floor(a + 0.5);
 }
 
-void math_min(float val1, float val2, out float outval)
+void math_floor(float a, float b, out float result)
 {
-  outval = min(val1, val2);
+  result = floor(a);
 }
 
-void math_round(float val, out float outval)
+void math_ceil(float a, float b, out float result)
 {
-  outval = floor(val + 0.5);
+  result = ceil(a);
 }
 
-void math_less_than(float val1, float val2, out float outval)
+void math_fraction(float a, float b, out float result)
 {
-  if (val1 < val2) {
-    outval = 1.0;
-  }
-  else {
-    outval = 0.0;
-  }
+  result = a - floor(a);
 }
 
-void math_greater_than(float val1, float val2, out float outval)
+/* Change sign to match C convention. mod in GLSL will take absolute for negative numbers.
+ * See https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/mod.xhtml
+ */
+void math_modulo(float a, float b, out float result)
 {
-  if (val1 > val2) {
-    outval = 1.0;
-  }
-  else {
-    outval = 0.0;
-  }
+  result = (b != 0.0) ? sign(a) * mod(abs(a), b) : 0.0;
 }
 
-void math_modulo(float val1, float val2, out float outval)
+void math_sine(float a, float b, out float result)
 {
-  if (val2 == 0.0 || val1 == val2) {
-    outval = 0.0;
-  }
-  else {
-    /* change sign to match C convention, mod in GLSL will take absolute for negative numbers,
-     * see https://www.opengl.org/sdk/docs/man/html/mod.xhtml */
-    outval = sign(val1) * mod(abs(val1), val2);
-  }
+  result = sin(a);
 }
 
-void math_abs(float val1, out float outval)
+void math_cosine(float a, float b, out float result)
 {
-  outval = abs(val1);
+  result = cos(a);
 }
 
-void math_atan2(float val1, float val2, out float outval)
+void math_tangent(float a, float b, out float result)
 {
-  outval = atan(val1, val2);
+  result = tan(a);
 }
 
-void math_floor(float val, out float outval)
+void math_arcsine(float a, float b, out float result)
 {
-  outval = floor(val);
+  result = (a <= 1.0 && a >= -1.0) ? asin(a) : 0.0;
 }
 
-void math_ceil(float val, out float outval)
+void math_arccosine(float a, float b, out float result)
 {
-  outval = ceil(val);
+  result = (a <= 1.0 && a >= -1.0) ? acos(a) : 0.0;
 }
 
-void math_fract(float val, out float outval)
+void math_arctangent(float a, float b, out float result)
 {
-  outval = val - floor(val);
+  result = atan(a);
 }
 
-void math_sqrt(float val, out float outval)
+void math_arctan2(float a, float b, out float result)
 {
-  if (val > 0.0) {
-    outval = sqrt(val);
-  }
-  else {
-    outval = 0.0;
-  }
+  result = atan(a, b);
 }
 
 void squeeze(float val, float width, float center, out float outval)
index 3ad857ac7b7dcbe4de43159f18ffdb346889054d..81b93ce654126739eb6b365b810f607a8dc6bfa8 100644 (file)
@@ -1167,31 +1167,31 @@ typedef struct NodeDenoise {
 /* math node clamp */
 #define SHD_MATH_CLAMP 1
 
-/* Math node operation/ */
+/* Math node operations. */
 enum {
   NODE_MATH_ADD = 0,
-  NODE_MATH_SUB = 1,
-  NODE_MATH_MUL = 2,
+  NODE_MATH_SUBTRACT = 1,
+  NODE_MATH_MULTIPLY = 2,
   NODE_MATH_DIVIDE = 3,
-  NODE_MATH_SIN = 4,
-  NODE_MATH_COS = 5,
-  NODE_MATH_TAN = 6,
-  NODE_MATH_ASIN = 7,
-  NODE_MATH_ACOS = 8,
-  NODE_MATH_ATAN = 9,
-  NODE_MATH_POW = 10,
-  NODE_MATH_LOG = 11,
-  NODE_MATH_MIN = 12,
-  NODE_MATH_MAX = 13,
+  NODE_MATH_SINE = 4,
+  NODE_MATH_COSINE = 5,
+  NODE_MATH_TANGENT = 6,
+  NODE_MATH_ARCSINE = 7,
+  NODE_MATH_ARCCOSINE = 8,
+  NODE_MATH_ARCTANGENT = 9,
+  NODE_MATH_POWER = 10,
+  NODE_MATH_LOGARITHM = 11,
+  NODE_MATH_MINIMUM = 12,
+  NODE_MATH_MAXIMUM = 13,
   NODE_MATH_ROUND = 14,
-  NODE_MATH_LESS = 15,
-  NODE_MATH_GREATER = 16,
-  NODE_MATH_MOD = 17,
-  NODE_MATH_ABS = 18,
-  NODE_MATH_ATAN2 = 19,
+  NODE_MATH_LESS_THAN = 15,
+  NODE_MATH_GREATER_THAN = 16,
+  NODE_MATH_MODULO = 17,
+  NODE_MATH_ABSOLUTE = 18,
+  NODE_MATH_ARCTAN2 = 19,
   NODE_MATH_FLOOR = 20,
   NODE_MATH_CEIL = 21,
-  NODE_MATH_FRACT = 22,
+  NODE_MATH_FRACTION = 22,
   NODE_MATH_SQRT = 23,
 };
 
index c9815a6cc3724978fe9d8063876474636dd1a7ce..a0c00db1a1e16f55c803f37967cba299a4bcb71c 100644 (file)
@@ -100,34 +100,38 @@ static const EnumPropertyItem node_chunksize_items[] = {
 #endif
 
 const EnumPropertyItem rna_enum_node_math_items[] = {
-    {NODE_MATH_ADD, "ADD", 0, "Add", ""},
-    {NODE_MATH_SUB, "SUBTRACT", 0, "Subtract", ""},
-    {NODE_MATH_MUL, "MULTIPLY", 0, "Multiply", ""},
-    {NODE_MATH_DIVIDE, "DIVIDE", 0, "Divide", ""},
+    {NODE_MATH_ADD, "ADD", 0, "Add", "A + B"},
+    {NODE_MATH_SUBTRACT, "SUBTRACT", 0, "Subtract", "A - B"},
+    {NODE_MATH_MULTIPLY, "MULTIPLY", 0, "Multiply", "A * B"},
+    {NODE_MATH_DIVIDE, "DIVIDE", 0, "Divide", "A / B"},
     {0, "", ICON_NONE, NULL, NULL},
-    {NODE_MATH_POW, "POWER", 0, "Power", ""},
-    {NODE_MATH_LOG, "LOGARITHM", 0, "Logarithm", ""},
-    {NODE_MATH_SQRT, "SQRT", 0, "Square Root", ""},
-    {NODE_MATH_ABS, "ABSOLUTE", 0, "Absolute", ""},
+    {NODE_MATH_POWER, "POWER", 0, "Power", "A power B"},
+    {NODE_MATH_LOGARITHM, "LOGARITHM", 0, "Logarithm", "Logarithm A base B"},
+    {NODE_MATH_SQRT, "SQRT", 0, "Square Root", "Square root of A"},
+    {NODE_MATH_ABSOLUTE, "ABSOLUTE", 0, "Absolute", "Magnitude of A"},
     {0, "", ICON_NONE, NULL, NULL},
-    {NODE_MATH_MIN, "MINIMUM", 0, "Minimum", ""},
-    {NODE_MATH_MAX, "MAXIMUM", 0, "Maximum", ""},
-    {NODE_MATH_LESS, "LESS_THAN", 0, "Less Than", ""},
-    {NODE_MATH_GREATER, "GREATER_THAN", 0, "Greater Than", ""},
+    {NODE_MATH_MINIMUM, "MINIMUM", 0, "Minimum", "The minimum from A and B"},
+    {NODE_MATH_MAXIMUM, "MAXIMUM", 0, "Maximum", "The maximum from A and B"},
+    {NODE_MATH_LESS_THAN, "LESS_THAN", 0, "Less Than", "1 if A < B else 0"},
+    {NODE_MATH_GREATER_THAN, "GREATER_THAN", 0, "Greater Than", "1 if A > B else 0"},
     {0, "", ICON_NONE, NULL, NULL},
-    {NODE_MATH_ROUND, "ROUND", 0, "Round", ""},
-    {NODE_MATH_FLOOR, "FLOOR", 0, "Floor", ""},
-    {NODE_MATH_CEIL, "CEIL", 0, "Ceil", ""},
-    {NODE_MATH_FRACT, "FRACT", 0, "Fract", ""},
-    {NODE_MATH_MOD, "MODULO", 0, "Modulo", ""},
+    {NODE_MATH_ROUND,
+     "ROUND",
+     0,
+     "Round",
+     "Round A to the nearest integer. Round upward if the fraction part is 0.5"},
+    {NODE_MATH_FLOOR, "FLOOR", 0, "Floor", "The largest integer smaller than or equal A"},
+    {NODE_MATH_CEIL, "CEIL", 0, "Ceil", "The smallest integer greater than or equal A"},
+    {NODE_MATH_FRACTION, "FRACT", 0, "Fraction", "The fraction part of A"},
+    {NODE_MATH_MODULO, "MODULO", 0, "Modulo", "A mod B"},
     {0, "", ICON_NONE, NULL, NULL},
-    {NODE_MATH_SIN, "SINE", 0, "Sine", ""},
-    {NODE_MATH_COS, "COSINE", 0, "Cosine", ""},
-    {NODE_MATH_TAN, "TANGENT", 0, "Tangent", ""},
-    {NODE_MATH_ASIN, "ARCSINE", 0, "Arcsine", ""},
-    {NODE_MATH_ACOS, "ARCCOSINE", 0, "Arccosine", ""},
-    {NODE_MATH_ATAN, "ARCTANGENT", 0, "Arctangent", ""},
-    {NODE_MATH_ATAN2, "ARCTAN2", 0, "Arctan2", ""},
+    {NODE_MATH_SINE, "SINE", 0, "Sine", "sin(A)"},
+    {NODE_MATH_COSINE, "COSINE", 0, "Cosine", "cos(A)"},
+    {NODE_MATH_TANGENT, "TANGENT", 0, "Tangent", "tan(A)"},
+    {NODE_MATH_ARCSINE, "ARCSINE", 0, "Arcsine", "arcsin(A)"},
+    {NODE_MATH_ARCCOSINE, "ARCCOSINE", 0, "Arccosine", "arccos(A)"},
+    {NODE_MATH_ARCTANGENT, "ARCTANGENT", 0, "Arctangent", "arctan(A)"},
+    {NODE_MATH_ARCTAN2, "ARCTAN2", 0, "Arctan2", "The signed angle arctan(A / B)"},
     {0, NULL, 0, NULL, NULL},
 };
 
@@ -3852,7 +3856,7 @@ static void def_math(StructRNA *srna)
   RNA_def_property_enum_sdna(prop, NULL, "custom1");
   RNA_def_property_enum_items(prop, rna_enum_node_math_items);
   RNA_def_property_ui_text(prop, "Operation", "");
-  RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+  RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update");
 
   prop = RNA_def_property(srna, "use_clamp", PROP_BOOLEAN, PROP_NONE);
   RNA_def_property_boolean_sdna(prop, NULL, "custom2", SHD_MATH_CLAMP);
index 29c6d855eaebbcdf71b9630b0c5abdeefadcf0f0..aaedc4aa1b7545f84f414722bc02e8f646791d86 100644 (file)
@@ -31,272 +31,6 @@ static bNodeSocketTemplate sh_node_math_in[] = {
 
 static bNodeSocketTemplate sh_node_math_out[] = {{SOCK_FLOAT, 0, N_("Value")}, {-1, 0, ""}};
 
-static void node_shader_exec_math(void *UNUSED(data),
-                                  int UNUSED(thread),
-                                  bNode *node,
-                                  bNodeExecData *UNUSED(execdata),
-                                  bNodeStack **in,
-                                  bNodeStack **out)
-{
-  float a, b, r = 0.0f;
-
-  nodestack_get_vec(&a, SOCK_FLOAT, in[0]);
-  nodestack_get_vec(&b, SOCK_FLOAT, in[1]);
-
-  switch (node->custom1) {
-
-    case NODE_MATH_ADD:
-      r = a + b;
-      break;
-    case NODE_MATH_SUB:
-      r = a - b;
-      break;
-    case NODE_MATH_MUL:
-      r = a * b;
-      break;
-    case NODE_MATH_DIVIDE: {
-      if (b == 0) { /* We don't want to divide by zero. */
-        r = 0.0;
-      }
-      else {
-        r = a / b;
-      }
-      break;
-    }
-    case NODE_MATH_SIN: {
-      /* This one only takes one input, so we've got to choose. */
-      if (in[0]->hasinput || !in[1]->hasinput) {
-        r = sinf(a);
-      }
-      else {
-        r = sinf(b);
-      }
-      break;
-    }
-    case NODE_MATH_COS: {
-      /* This one only takes one input, so we've got to choose. */
-      if (in[0]->hasinput || !in[1]->hasinput) {
-        r = cosf(a);
-      }
-      else {
-        r = cosf(b);
-      }
-      break;
-    }
-    case NODE_MATH_TAN: {
-      /* This one only takes one input, so we've got to choose. */
-      if (in[0]->hasinput || !in[1]->hasinput) {
-        r = tanf(a);
-      }
-      else {
-        r = tanf(b);
-      }
-      break;
-    }
-    case NODE_MATH_ASIN: {
-      /* This one only takes one input, so we've got to choose. */
-      if (in[0]->hasinput || !in[1]->hasinput) {
-        /* Can't do the impossible... */
-        if (a <= 1 && a >= -1) {
-          r = asinf(a);
-        }
-        else {
-          r = 0.0;
-        }
-      }
-      else {
-        /* Can't do the impossible... */
-        if (b <= 1 && b >= -1) {
-          r = asinf(b);
-        }
-        else {
-          r = 0.0;
-        }
-      }
-      break;
-    }
-    case NODE_MATH_ACOS: {
-      /* This one only takes one input, so we've got to choose. */
-      if (in[0]->hasinput || !in[1]->hasinput) {
-        /* Can't do the impossible... */
-        if (a <= 1 && a >= -1) {
-          r = acosf(a);
-        }
-        else {
-          r = 0.0;
-        }
-      }
-      else {
-        /* Can't do the impossible... */
-        if (b <= 1 && b >= -1) {
-          r = acosf(b);
-        }
-        else {
-          r = 0.0;
-        }
-      }
-      break;
-    }
-    case NODE_MATH_ATAN: {
-      /* This one only takes one input, so we've got to choose. */
-      if (in[0]->hasinput || !in[1]->hasinput) {
-        r = atan(a);
-      }
-      else {
-        r = atan(b);
-      }
-      break;
-    }
-    case NODE_MATH_POW: {
-      /* Only raise negative numbers by full integers */
-      if (a >= 0) {
-        r = pow(a, b);
-      }
-      else {
-        float y_mod_1 = fabsf(fmodf(b, 1.0f));
-
-        /* if input value is not nearly an integer,
-         * fall back to zero, nicer than straight rounding. */
-        if (y_mod_1 > 0.999f || y_mod_1 < 0.001f) {
-          r = powf(a, floorf(b + 0.5f));
-        }
-        else {
-          r = 0.0f;
-        }
-      }
-
-      break;
-    }
-    case NODE_MATH_LOG: {
-      /* Don't want any imaginary numbers... */
-      if (a > 0 && b > 0) {
-        r = log(a) / log(b);
-      }
-      else {
-        r = 0.0;
-      }
-      break;
-    }
-    case NODE_MATH_MIN: {
-      if (a < b) {
-        r = a;
-      }
-      else {
-        r = b;
-      }
-      break;
-    }
-    case NODE_MATH_MAX: {
-      if (a > b) {
-        r = a;
-      }
-      else {
-        r = b;
-      }
-      break;
-    }
-    case NODE_MATH_ROUND: {
-      /* This one only takes one input, so we've got to choose. */
-      if (in[0]->hasinput || !in[1]->hasinput) {
-        r = (a < 0) ? (int)(a - 0.5f) : (int)(a + 0.5f);
-      }
-      else {
-        r = (b < 0) ? (int)(b - 0.5f) : (int)(b + 0.5f);
-      }
-      break;
-    }
-    case NODE_MATH_LESS: {
-      if (a < b) {
-        r = 1.0f;
-      }
-      else {
-        r = 0.0f;
-      }
-      break;
-    }
-    case NODE_MATH_GREATER: {
-      if (a > b) {
-        r = 1.0f;
-      }
-      else {
-        r = 0.0f;
-      }
-      break;
-    }
-    case NODE_MATH_MOD: {
-      if (b == 0.0f) {
-        r = 0.0f;
-      }
-      else {
-        r = fmod(a, b);
-      }
-      break;
-    }
-    case NODE_MATH_ABS: {
-      r = fabsf(a);
-      break;
-    }
-    case NODE_MATH_ATAN2: {
-      r = atan2(a, b);
-      break;
-    }
-    case NODE_MATH_FLOOR: {
-      /* This one only takes one input, so we've got to choose. */
-      if (in[0]->hasinput || !in[1]->hasinput) {
-        r = floorf(a);
-      }
-      else {
-        r = floorf(b);
-      }
-      break;
-    }
-    case NODE_MATH_CEIL: {
-      /* This one only takes one input, so we've got to choose. */
-      if (in[0]->hasinput || !in[1]->hasinput) {
-        r = ceilf(a);
-      }
-      else {
-        r = ceilf(b);
-      }
-      break;
-    }
-    case NODE_MATH_FRACT: {
-      /* This one only takes one input, so we've got to choose. */
-      if (in[0]->hasinput || !in[1]->hasinput) {
-        r = a - floorf(a);
-      }
-      else {
-        r = b - floorf(b);
-      }
-      break;
-    }
-    case NODE_MATH_SQRT: {
-      /* This one only takes one input, so we've got to choose. */
-      if (in[0]->hasinput || !in[1]->hasinput) {
-        if (a > 0) {
-          r = sqrt(a);
-        }
-        else {
-          r = 0.0;
-        }
-      }
-      else {
-        if (b > 0) {
-          r = sqrt(b);
-        }
-        else {
-          r = 0.0;
-        }
-      }
-      break;
-    }
-  }
-  if (node->custom2 & SHD_MATH_CLAMP) {
-    CLAMP(r, 0.0f, 1.0f);
-  }
-  out[0]->vec[0] = r;
-}
-
 static int gpu_shader_math(GPUMaterial *mat,
                            bNode *node,
                            bNodeExecData *UNUSED(execdata),
@@ -304,68 +38,65 @@ static int gpu_shader_math(GPUMaterial *mat,
                            GPUNodeStack *out)
 {
   static const char *names[] = {
-      "math_add",       "math_subtract",     "math_multiply", "math_divide", "math_sine",
-      "math_cosine",    "math_tangent",      "math_asin",     "math_acos",   "math_atan",
-      "math_pow",       "math_log",          "math_min",      "math_max",    "math_round",
-      "math_less_than", "math_greater_than", "math_modulo",   "math_abs",    "math_atan2",
-      "math_floor",     "math_ceil",         "math_fract",    "math_sqrt",
+      [NODE_MATH_ADD] = "math_add",
+      [NODE_MATH_SUBTRACT] = "math_subtract",
+      [NODE_MATH_MULTIPLY] = "math_multiply",
+      [NODE_MATH_DIVIDE] = "math_divide",
+
+      [NODE_MATH_POWER] = "math_power",
+      [NODE_MATH_LOGARITHM] = "math_logarithm",
+      [NODE_MATH_SQRT] = "math_sqrt",
+      [NODE_MATH_ABSOLUTE] = "math_absolute",
+
+      [NODE_MATH_MINIMUM] = "math_minimum",
+      [NODE_MATH_MAXIMUM] = "math_maximum",
+      [NODE_MATH_LESS_THAN] = "math_less_than",
+      [NODE_MATH_GREATER_THAN] = "math_greater_than",
+
+      [NODE_MATH_ROUND] = "math_round",
+      [NODE_MATH_FLOOR] = "math_floor",
+      [NODE_MATH_CEIL] = "math_ceil",
+      [NODE_MATH_FRACTION] = "math_fraction",
+      [NODE_MATH_MODULO] = "math_modulo",
+
+      [NODE_MATH_SINE] = "math_sine",
+      [NODE_MATH_COSINE] = "math_cosine",
+      [NODE_MATH_TANGENT] = "math_tangent",
+      [NODE_MATH_ARCSINE] = "math_arcsine",
+      [NODE_MATH_ARCCOSINE] = "math_arccosine",
+      [NODE_MATH_ARCTANGENT] = "math_arctangent",
+      [NODE_MATH_ARCTAN2] = "math_arctan2",
   };
 
-  switch (node->custom1) {
-    case NODE_MATH_ADD:
-    case NODE_MATH_SUB:
-    case NODE_MATH_MUL:
-    case NODE_MATH_DIVIDE:
-    case NODE_MATH_POW:
-    case NODE_MATH_LOG:
-    case NODE_MATH_MIN:
-    case NODE_MATH_MAX:
-    case NODE_MATH_LESS:
-    case NODE_MATH_GREATER:
-    case NODE_MATH_MOD:
-    case NODE_MATH_ATAN2:
-      GPU_stack_link(mat, node, names[node->custom1], in, out);
-      break;
-    case NODE_MATH_SIN:
-    case NODE_MATH_COS:
-    case NODE_MATH_TAN:
-    case NODE_MATH_ASIN:
-    case NODE_MATH_ACOS:
-    case NODE_MATH_ATAN:
-    case NODE_MATH_ROUND:
-    case NODE_MATH_ABS:
-    case NODE_MATH_FLOOR:
-    case NODE_MATH_FRACT:
-    case NODE_MATH_CEIL:
-    case NODE_MATH_SQRT:
-      if (in[0].hasinput || !in[1].hasinput) {
-        /* use only first item and terminator */
-        GPUNodeStack tmp_in[2];
-        memcpy(&tmp_in[0], &in[0], sizeof(GPUNodeStack));
-        memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack));
-        GPU_stack_link(mat, node, names[node->custom1], tmp_in, out);
-      }
-      else {
-        /* use only second item and terminator */
-        GPUNodeStack tmp_in[2];
-        memcpy(&tmp_in[0], &in[1], sizeof(GPUNodeStack));
-        memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack));
-        GPU_stack_link(mat, node, names[node->custom1], tmp_in, out);
-      }
-      break;
-    default:
-      return 0;
-  }
+  GPU_stack_link(mat, node, names[node->custom1], in, out);
 
   if (node->custom2 & SHD_MATH_CLAMP) {
     float min[3] = {0.0f, 0.0f, 0.0f};
     float max[3] = {1.0f, 1.0f, 1.0f};
     GPU_link(mat, "clamp_value", out[0].link, GPU_constant(min), GPU_constant(max), &out[0].link);
   }
-
   return 1;
 }
 
+static void node_shader_update_math(bNodeTree *UNUSED(ntree), bNode *node)
+{
+  bNodeSocket *sock = BLI_findlink(&node->inputs, 1);
+  nodeSetSocketAvailability(sock,
+                            !ELEM(node->custom1,
+                                  NODE_MATH_SQRT,
+                                  NODE_MATH_CEIL,
+                                  NODE_MATH_SINE,
+                                  NODE_MATH_ROUND,
+                                  NODE_MATH_FLOOR,
+                                  NODE_MATH_COSINE,
+                                  NODE_MATH_ARCSINE,
+                                  NODE_MATH_TANGENT,
+                                  NODE_MATH_ABSOLUTE,
+                                  NODE_MATH_FRACTION,
+                                  NODE_MATH_ARCCOSINE,
+                                  NODE_MATH_ARCTANGENT));
+}
+
 void register_node_type_sh_math(void)
 {
   static bNodeType ntype;
@@ -373,9 +104,8 @@ void register_node_type_sh_math(void)
   sh_node_type_base(&ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, 0);
   node_type_socket_templates(&ntype, sh_node_math_in, sh_node_math_out);
   node_type_label(&ntype, node_math_label);
-  node_type_storage(&ntype, "", NULL, NULL);
-  node_type_exec(&ntype, NULL, NULL, node_shader_exec_math);
   node_type_gpu(&ntype, gpu_shader_math);
+  node_type_update(&ntype, node_shader_update_math);
 
   nodeRegisterType(&ntype);
 }
index 2eb32e0addc2a98c09536f7cc277ca7775bbe5c0..b1d67a5a953e9a4fbf06650fbc390c9e5cb7f9c9 100644 (file)
@@ -46,10 +46,10 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
     case NODE_MATH_ADD:
       *out = in0 + in1;
       break;
-    case NODE_MATH_SUB:
+    case NODE_MATH_SUBTRACT:
       *out = in0 - in1;
       break;
-    case NODE_MATH_MUL:
+    case NODE_MATH_MULTIPLY:
       *out = in0 * in1;
       break;
     case NODE_MATH_DIVIDE: {
@@ -62,19 +62,19 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
       }
       break;
     }
-    case NODE_MATH_SIN: {
+    case NODE_MATH_SINE: {
       *out = sinf(in0);
       break;
     }
-    case NODE_MATH_COS: {
+    case NODE_MATH_COSINE: {
       *out = cosf(in0);
       break;
     }
-    case NODE_MATH_TAN: {
+    case NODE_MATH_TANGENT: {
       *out = tanf(in0);
       break;
     }
-    case NODE_MATH_ASIN: {
+    case NODE_MATH_ARCSINE: {
       /* Can't do the impossible... */
       if (in0 <= 1 && in0 >= -1) {
         *out = asinf(in0);
@@ -84,7 +84,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
       }
       break;
     }
-    case NODE_MATH_ACOS: {
+    case NODE_MATH_ARCCOSINE: {
       /* Can't do the impossible... */
       if (in0 <= 1 && in0 >= -1) {
         *out = acosf(in0);
@@ -94,11 +94,11 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
       }
       break;
     }
-    case NODE_MATH_ATAN: {
+    case NODE_MATH_ARCTANGENT: {
       *out = atan(in0);
       break;
     }
-    case NODE_MATH_POW: {
+    case NODE_MATH_POWER: {
       /* Only raise negative numbers by full integers */
       if (in0 >= 0) {
         out[0] = pow(in0, in1);
@@ -114,7 +114,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
       }
       break;
     }
-    case NODE_MATH_LOG: {
+    case NODE_MATH_LOGARITHM: {
       /* Don't want any imaginary numbers... */
       if (in0 > 0 && in1 > 0) {
         *out = log(in0) / log(in1);
@@ -124,7 +124,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
       }
       break;
     }
-    case NODE_MATH_MIN: {
+    case NODE_MATH_MINIMUM: {
       if (in0 < in1) {
         *out = in0;
       }
@@ -133,7 +133,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
       }
       break;
     }
-    case NODE_MATH_MAX: {
+    case NODE_MATH_MAXIMUM: {
       if (in0 > in1) {
         *out = in0;
       }
@@ -147,7 +147,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
       break;
     }
 
-    case NODE_MATH_LESS: {
+    case NODE_MATH_LESS_THAN: {
       if (in0 < in1) {
         *out = 1.0f;
       }
@@ -157,7 +157,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
       break;
     }
 
-    case NODE_MATH_GREATER: {
+    case NODE_MATH_GREATER_THAN: {
       if (in0 > in1) {
         *out = 1.0f;
       }
@@ -167,7 +167,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
       break;
     }
 
-    case NODE_MATH_MOD: {
+    case NODE_MATH_MODULO: {
       if (in1 == 0.0f) {
         *out = 0.0f;
       }
@@ -177,12 +177,12 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
       break;
     }
 
-    case NODE_MATH_ABS: {
+    case NODE_MATH_ABSOLUTE: {
       *out = fabsf(in0);
       break;
     }
 
-    case NODE_MATH_ATAN2: {
+    case NODE_MATH_ARCTAN2: {
       *out = atan2(in0, in1);
       break;
     }
@@ -197,7 +197,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
       break;
     }
 
-    case NODE_MATH_FRACT: {
+    case NODE_MATH_FRACTION: {
       *out = in0 - floorf(in0);
       break;
     }