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:
authorOmarSquircleArt <omar.squircleart@gmail.com>2019-08-18 12:16:04 +0300
committerOmarSquircleArt <omar.squircleart@gmail.com>2019-08-18 12:16:04 +0300
commite5618725fd1ebdf558e963d959eb3950b5a9874c (patch)
treed1e02f93f36aefa5bf6a87ca75b91558a34ae5d1
parente12c17b3054b9a3d9636268c2a2904ecb9df632b (diff)
Shading: Refactor Math node and use dynamic inputs.
- 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
-rw-r--r--intern/cycles/blender/blender_shader.cpp8
-rw-r--r--intern/cycles/kernel/shaders/node_math.osl93
-rw-r--r--intern/cycles/kernel/svm/svm_math.h20
-rw-r--r--intern/cycles/kernel/svm/svm_math_util.h110
-rw-r--r--intern/cycles/kernel/svm/svm_types.h7
-rw-r--r--intern/cycles/render/constant_fold.cpp16
-rw-r--r--intern/cycles/render/constant_fold.h2
-rw-r--r--intern/cycles/render/nodes.cpp42
-rw-r--r--intern/cycles/render/nodes.h3
-rw-r--r--intern/cycles/test/render_graph_finalize_test.cpp2
-rw-r--r--source/blender/blenkernel/BKE_node.h1
-rw-r--r--source/blender/blenkernel/intern/node.c10
-rw-r--r--source/blender/blenloader/intern/versioning_cycles.c52
-rw-r--r--source/blender/compositor/nodes/COM_MathNode.cpp36
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl164
-rw-r--r--source/blender/makesdna/DNA_node_types.h38
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c54
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_math.c368
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_math.c36
19 files changed, 398 insertions, 664 deletions
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index b95e88573fa..626a1dad7db 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -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);
diff --git a/intern/cycles/kernel/shaders/node_math.osl b/intern/cycles/kernel/shaders/node_math.osl
index 8830339e05f..fb59c783770 100644
--- a/intern/cycles/kernel/shaders/node_math.osl
+++ b/intern/cycles/kernel/shaders/node_math.osl
@@ -17,57 +17,31 @@
#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!");
}
diff --git a/intern/cycles/kernel/svm/svm_math.h b/intern/cycles/kernel/svm/svm_math.h
index 5920913825b..402290d7218 100644
--- a/intern/cycles/kernel/svm/svm_math.h
+++ b/intern/cycles/kernel/svm/svm_math.h
@@ -16,24 +16,22 @@
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,
diff --git a/intern/cycles/kernel/svm/svm_math_util.h b/intern/cycles/kernel/svm/svm_math_util.h
index e3544515f1b..d8804226487 100644
--- a/intern/cycles/kernel/svm/svm_math_util.h
+++ b/intern/cycles/kernel/svm/svm_math_util.h
@@ -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
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index 9a8a5401297..6b0d10adc74 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -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,
diff --git a/intern/cycles/render/constant_fold.cpp b/intern/cycles/render/constant_fold.cpp
index e475ff60eef..d6fdc49434e 100644
--- a/intern/cycles/render/constant_fold.cpp
+++ b/intern/cycles/render/constant_fold.cpp
@@ -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;
diff --git a/intern/cycles/render/constant_fold.h b/intern/cycles/render/constant_fold.h
index c14b94868dc..d223fd86197 100644
--- a/intern/cycles/render/constant_fold.h
+++ b/intern/cycles/render/constant_fold.h
@@ -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;
};
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 9255181b421..7d4fcba9f3b 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -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");
}
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index d4708adf9af..514ab3db8eb 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -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;
};
diff --git a/intern/cycles/test/render_graph_finalize_test.cpp b/intern/cycles/test/render_graph_finalize_test.cpp
index 7fb92bfb862..11c758c9389 100644
--- a/intern/cycles/test/render_graph_finalize_test.cpp
+++ b/intern/cycles/test/render_graph_finalize_test.cpp
@@ -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
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 9b2db5acd3b..7d427cb7799 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -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);
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 986571e34bd..d64a5a33ef1 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -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
diff --git a/source/blender/blenloader/intern/versioning_cycles.c b/source/blender/blenloader/intern/versioning_cycles.c
index cebe15e2719..10f24cff61b 100644
--- a/source/blender/blenloader/intern/versioning_cycles.c
+++ b/source/blender/blenloader/intern/versioning_cycles.c
@@ -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;
+ }
}
diff --git a/source/blender/compositor/nodes/COM_MathNode.cpp b/source/blender/compositor/nodes/COM_MathNode.cpp
index 5a2f934f37f..d13b34bb6b5 100644
--- a/source/blender/compositor/nodes/COM_MathNode.cpp
+++ b/source/blender/compositor/nodes/COM_MathNode.cpp
@@ -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:
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index f077ae55d8f..1529279ca03 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -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)
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 3ad857ac7b7..81b93ce6541 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -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,
};
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index c9815a6cc37..a0c00db1a1e 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -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);
diff --git a/source/blender/nodes/shader/nodes/node_shader_math.c b/source/blender/nodes/shader/nodes/node_shader_math.c
index 29c6d855eae..aaedc4aa1b7 100644
--- a/source/blender/nodes/shader/nodes/node_shader_math.c
+++ b/source/blender/nodes/shader/nodes/node_shader_math.c
@@ -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);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_math.c b/source/blender/nodes/texture/nodes/node_texture_math.c
index 2eb32e0addc..b1d67a5a953 100644
--- a/source/blender/nodes/texture/nodes/node_texture_math.c
+++ b/source/blender/nodes/texture/nodes/node_texture_math.c
@@ -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;
}