From b882f89fe36614b4ed15b2f1e7915c538f371dd2 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 16 Jul 2020 13:41:47 +0200 Subject: Particles: support for most math node operations --- source/blender/nodes/shader/node_shader_util.h | 1 + .../blender/nodes/shader/nodes/node_shader_math.cc | 215 +++++++++++++++++++-- 2 files changed, 204 insertions(+), 12 deletions(-) diff --git a/source/blender/nodes/shader/node_shader_util.h b/source/blender/nodes/shader/node_shader_util.h index fc262544b4f..9ea3974679a 100644 --- a/source/blender/nodes/shader/node_shader_util.h +++ b/source/blender/nodes/shader/node_shader_util.h @@ -42,6 +42,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLI_math_base_safe.h" #include "BLI_rand.h" #include "BLI_threads.h" #include "BLI_utildefines.h" diff --git a/source/blender/nodes/shader/nodes/node_shader_math.cc b/source/blender/nodes/shader/nodes/node_shader_math.cc index a0eb5099f9d..c6762f17919 100644 --- a/source/blender/nodes/shader/nodes/node_shader_math.cc +++ b/source/blender/nodes/shader/nodes/node_shader_math.cc @@ -146,38 +146,229 @@ static int gpu_shader_math(GPUMaterial *mat, } } -static void sh_node_math_expand_in_mf_network(blender::bke::NodeMFNetworkBuilder &builder) +static const blender::fn::MultiFunction &get_base_multi_function( + blender::bke::NodeMFNetworkBuilder &builder) { - /* TODO: Implement clamp and other operations. */ const int mode = builder.bnode().custom1; switch (mode) { case NODE_MATH_ADD: { static blender::fn::CustomMF_SI_SI_SO fn{ "Add", [](float a, float b) { return a + b; }}; - builder.set_matching_fn(fn); - break; + return fn; } case NODE_MATH_SUBTRACT: { static blender::fn::CustomMF_SI_SI_SO fn{ "Subtract", [](float a, float b) { return a - b; }}; - builder.set_matching_fn(fn); - break; + return fn; } case NODE_MATH_MULTIPLY: { static blender::fn::CustomMF_SI_SI_SO fn{ "Multiply", [](float a, float b) { return a * b; }}; - builder.set_matching_fn(fn); - break; + return fn; } case NODE_MATH_DIVIDE: { + static blender::fn::CustomMF_SI_SI_SO fn{"Divide", safe_divide}; + return fn; + } + case NODE_MATH_MULTIPLY_ADD: { + static blender::fn::CustomMF_SI_SI_SI_SO fn{ + "Multiply Add", [](float a, float b, float c) { return a * b + c; }}; + return fn; + } + + case NODE_MATH_POWER: { + static blender::fn::CustomMF_SI_SI_SO fn{"Power", safe_powf}; + return fn; + } + case NODE_MATH_LOGARITHM: { + static blender::fn::CustomMF_SI_SI_SO fn{"Logarithm", safe_logf}; + return fn; + } + case NODE_MATH_EXPONENT: { + static blender::fn::CustomMF_SI_SO fn{"Exponent", expf}; + return fn; + } + case NODE_MATH_SQRT: { + static blender::fn::CustomMF_SI_SO fn{"Sqrt", safe_sqrtf}; + return fn; + } + case NODE_MATH_INV_SQRT: { + static blender::fn::CustomMF_SI_SO fn{"Inverse Sqrt", safe_inverse_sqrtf}; + return fn; + }; + case NODE_MATH_ABSOLUTE: { + static blender::fn::CustomMF_SI_SO fn{"Absolute", + [](float a) { return fabs(a); }}; + return fn; + } + case NODE_MATH_RADIANS: { + static blender::fn::CustomMF_SI_SO fn{"Radians", + [](float a) { return DEG2RAD(a); }}; + return fn; + } + case NODE_MATH_DEGREES: { + static blender::fn::CustomMF_SI_SO fn{"Degrees", + [](float a) { return RAD2DEG(a); }}; + return fn; + } + + case NODE_MATH_MINIMUM: { + static blender::fn::CustomMF_SI_SI_SO fn{ + "Minimum", [](float a, float b) { return std::min(a, b); }}; + return fn; + } + case NODE_MATH_MAXIMUM: { + static blender::fn::CustomMF_SI_SI_SO fn{ + "Maximum", [](float a, float b) { return std::max(a, b); }}; + return fn; + } + case NODE_MATH_LESS_THAN: { + static blender::fn::CustomMF_SI_SI_SO fn{ + "Less Than", [](float a, float b) { return (float)(a < b); }}; + return fn; + } + case NODE_MATH_GREATER_THAN: { + static blender::fn::CustomMF_SI_SI_SO fn{ + "Greater Than", [](float a, float b) { return (float)(a > b); }}; + return fn; + } + case NODE_MATH_SIGN: { + static blender::fn::CustomMF_SI_SO fn{ + "Sign", [](float a) { return compatible_signf(a); }}; + return fn; + } + case NODE_MATH_COMPARE: { + static blender::fn::CustomMF_SI_SI_SI_SO fn{ + "Compare", [](float a, float b, float c) -> float { + return ((a == b) || (fabsf(a - b) <= fmaxf(c, FLT_EPSILON))) ? 1.0f : 0.0f; + }}; + return fn; + } + case NODE_MATH_SMOOTH_MIN: { + return builder.get_not_implemented_fn(); + } + case NODE_MATH_SMOOTH_MAX: { + return builder.get_not_implemented_fn(); + } + + case NODE_MATH_ROUND: { + static blender::fn::CustomMF_SI_SO fn{ + "Round", [](float a) { return floorf(a + 0.5f); }}; + return fn; + } + case NODE_MATH_FLOOR: { + static blender::fn::CustomMF_SI_SO fn{"Floor", + [](float a) { return floorf(a); }}; + return fn; + } + case NODE_MATH_CEIL: { + static blender::fn::CustomMF_SI_SO fn{"Ceil", + [](float a) { return ceilf(a); }}; + return fn; + } + case NODE_MATH_FRACTION: { + static blender::fn::CustomMF_SI_SO fn{"Fraction", + [](float a) { return a - floorf(a); }}; + return fn; + } + case NODE_MATH_MODULO: { static blender::fn::CustomMF_SI_SI_SO fn{ - "Divide", [](float a, float b) { return (b != 0.0f) ? a / b : 0.0f; }}; - builder.set_matching_fn(fn); - break; + "Modulo", [](float a, float b) { return safe_modf(a, b); }}; + return fn; } + case NODE_MATH_TRUNC: { + static blender::fn::CustomMF_SI_SO fn{ + "Trunc", [](float a) { return a >= 0.0f ? floorf(a) : ceilf(a); }}; + return fn; + } + case NODE_MATH_SNAP: { + static blender::fn::CustomMF_SI_SI_SO fn{ + "Snap", [](float a, float b) { return floorf(safe_divide(a, b)) * b; }}; + return fn; + } + case NODE_MATH_WRAP: { + return builder.get_not_implemented_fn(); + } + case NODE_MATH_PINGPONG: { + return builder.get_not_implemented_fn(); + } + + case NODE_MATH_SINE: { + static blender::fn::CustomMF_SI_SO fn{"Sine", [](float a) { return sinf(a); }}; + return fn; + } + case NODE_MATH_COSINE: { + static blender::fn::CustomMF_SI_SO fn{"Cosine", + [](float a) { return cosf(a); }}; + return fn; + } + case NODE_MATH_TANGENT: { + static blender::fn::CustomMF_SI_SO fn{"Tangent", + [](float a) { return tanf(a); }}; + return fn; + } + case NODE_MATH_SINH: { + static blender::fn::CustomMF_SI_SO fn{"Hyperbolic Sine", + [](float a) { return sinhf(a); }}; + return fn; + } + case NODE_MATH_COSH: { + static blender::fn::CustomMF_SI_SO fn{"Hyperbolic Cosine", + [](float a) { return coshf(a); }}; + return fn; + } + case NODE_MATH_TANH: { + static blender::fn::CustomMF_SI_SO fn{"Hyperbolic Tangent", + [](float a) { return tanhf(a); }}; + return fn; + } + case NODE_MATH_ARCSINE: { + static blender::fn::CustomMF_SI_SO fn{"Arc Sine", safe_asinf}; + return fn; + } + case NODE_MATH_ARCCOSINE: { + static blender::fn::CustomMF_SI_SO fn{"Arc Cosine", safe_acosf}; + return fn; + } + case NODE_MATH_ARCTANGENT: { + static blender::fn::CustomMF_SI_SO fn{"Arc Tangent", + [](float a) { return atanf(a); }}; + return fn; + } + case NODE_MATH_ARCTAN2: { + static blender::fn::CustomMF_SI_SI_SO fn{ + "Arc Tangent 2", [](float a, float b) { return atan2f(a, b); }}; + return fn; + } + default: BLI_assert(false); - break; + return builder.get_not_implemented_fn(); + } +} + +static void sh_node_math_expand_in_mf_network(blender::bke::NodeMFNetworkBuilder &builder) +{ + const blender::fn::MultiFunction &base_function = get_base_multi_function(builder); + + const blender::bke::DNode &dnode = builder.dnode(); + blender::fn::MFNetwork &network = builder.network(); + blender::fn::MFFunctionNode &base_node = network.add_function(base_function); + + builder.network_map().add_try_match(dnode.inputs(), base_node.inputs()); + + const bool clamp_output = builder.bnode().custom2 != 0; + if (clamp_output) { + static blender::fn::CustomMF_SI_SO clamp_fn{"Clamp", [](float value) { + CLAMP(value, 0.0f, 1.0f); + return value; + }}; + blender::fn::MFFunctionNode &clamp_node = network.add_function(clamp_fn); + network.add_link(base_node.output(0), clamp_node.input(0)); + builder.network_map().add(dnode.output(0), clamp_node.output(0)); + } + else { + builder.network_map().add(dnode.output(0), base_node.output(0)); } } -- cgit v1.2.3