diff options
author | OmarSquircleArt <omar.squircleart@gmail.com> | 2019-08-18 12:16:04 +0300 |
---|---|---|
committer | OmarSquircleArt <omar.squircleart@gmail.com> | 2019-08-18 12:16:04 +0300 |
commit | e5618725fd1ebdf558e963d959eb3950b5a9874c (patch) | |
tree | d1e02f93f36aefa5bf6a87ca75b91558a34ae5d1 | |
parent | e12c17b3054b9a3d9636268c2a2904ecb9df632b (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
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; } |