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 /intern | |
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
Diffstat (limited to 'intern')
-rw-r--r-- | intern/cycles/blender/blender_shader.cpp | 8 | ||||
-rw-r--r-- | intern/cycles/kernel/shaders/node_math.osl | 93 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_math.h | 20 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_math_util.h | 110 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_types.h | 7 | ||||
-rw-r--r-- | intern/cycles/render/constant_fold.cpp | 16 | ||||
-rw-r--r-- | intern/cycles/render/constant_fold.h | 2 | ||||
-rw-r--r-- | intern/cycles/render/nodes.cpp | 42 | ||||
-rw-r--r-- | intern/cycles/render/nodes.h | 3 | ||||
-rw-r--r-- | intern/cycles/test/render_graph_finalize_test.cpp | 2 |
10 files changed, 141 insertions, 162 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 |