diff --git a/intern/cycles/kernel/shaders/node_vector_math.osl b/intern/cycles/kernel/shaders/node_vector_math.osl index 3963c23ea9c..c08d75b99ef 100644 --- a/intern/cycles/kernel/shaders/node_vector_math.osl +++ b/intern/cycles/kernel/shaders/node_vector_math.osl @@ -52,6 +52,9 @@ shader node_vector_math(string math_type = "add", else if (math_type == "faceforward") { Vector = compatible_faceforward(Vector1, Vector2, Vector3); } + else if (math_type == "multiply_add") { + Vector = Vector1 * Vector2 + Vector3; + } else if (math_type == "dot_product") { Value = dot(Vector1, Vector2); } diff --git a/intern/cycles/kernel/svm/svm_math.h b/intern/cycles/kernel/svm/svm_math.h index dda2e50f916..733ea28f9e5 100644 --- a/intern/cycles/kernel/svm/svm_math.h +++ b/intern/cycles/kernel/svm/svm_math.h @@ -58,7 +58,8 @@ ccl_device void svm_node_vector_math(KernelGlobals *kg, float3 vector; /* 3 Vector Operators */ - if (type == NODE_VECTOR_MATH_WRAP || type == NODE_VECTOR_MATH_FACEFORWARD) { + if (type == NODE_VECTOR_MATH_WRAP || type == NODE_VECTOR_MATH_FACEFORWARD || + type == NODE_VECTOR_MATH_MULTIPLY_ADD) { uint4 extra_node = read_node(kg, offset); c = stack_load_float3(stack, extra_node.x); } diff --git a/intern/cycles/kernel/svm/svm_math_util.h b/intern/cycles/kernel/svm/svm_math_util.h index 19fb1da5a1f..9e654f2247f 100644 --- a/intern/cycles/kernel/svm/svm_math_util.h +++ b/intern/cycles/kernel/svm/svm_math_util.h @@ -52,6 +52,9 @@ ccl_device void svm_vector_math(float *value, case NODE_VECTOR_MATH_FACEFORWARD: *vector = faceforward(a, b, c); break; + case NODE_VECTOR_MATH_MULTIPLY_ADD: + *vector = a * b + c; + break; case NODE_VECTOR_MATH_DOT_PRODUCT: *value = dot(a, b); break; diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 64a8f82a094..062afcfa5ac 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -341,6 +341,7 @@ typedef enum NodeVectorMathType { NODE_VECTOR_MATH_TANGENT, NODE_VECTOR_MATH_REFRACT, NODE_VECTOR_MATH_FACEFORWARD, + NODE_VECTOR_MATH_MULTIPLY_ADD, } NodeVectorMathType; typedef enum NodeClampType { diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index f3d420c6fcb..5792d2458d1 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -6093,6 +6093,7 @@ NODE_DEFINE(VectorMathNode) type_enum.insert("reflect", NODE_VECTOR_MATH_REFLECT); type_enum.insert("refract", NODE_VECTOR_MATH_REFRACT); type_enum.insert("faceforward", NODE_VECTOR_MATH_FACEFORWARD); + type_enum.insert("multiply_add", NODE_VECTOR_MATH_MULTIPLY_ADD); type_enum.insert("dot_product", NODE_VECTOR_MATH_DOT_PRODUCT); @@ -6165,7 +6166,8 @@ void VectorMathNode::compile(SVMCompiler &compiler) int vector_stack_offset = compiler.stack_assign_if_linked(vector_out); /* 3 Vector Operators */ - if (math_type == NODE_VECTOR_MATH_WRAP || math_type == NODE_VECTOR_MATH_FACEFORWARD) { + if (math_type == NODE_VECTOR_MATH_WRAP || math_type == NODE_VECTOR_MATH_FACEFORWARD || + math_type == NODE_VECTOR_MATH_MULTIPLY_ADD) { ShaderInput *vector3_in = input("Vector3"); int vector3_stack_offset = compiler.stack_assign(vector3_in); compiler.add_node( diff --git a/release/datafiles/locale b/release/datafiles/locale index 5ab29b1331d..2cef4877edc 160000 --- a/release/datafiles/locale +++ b/release/datafiles/locale @@ -1 +1 @@ -Subproject commit 5ab29b1331d2103dae634b987f121c4599459d7f +Subproject commit 2cef4877edc40875978c4e95322bb5193f5815bf diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_vector_math.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_vector_math.glsl index 60ed098beb3..4ad5d4232de 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_vector_math.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_vector_math.glsl @@ -150,3 +150,9 @@ void vector_math_faceforward( { outVector = faceforward(a, b, c); } + +void vector_math_multiply_add( + vec3 a, vec3 b, vec3 c, float scale, out vec3 outVector, out float outValue) +{ + outVector = a * b + c; +} diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 0fa1d1a74ac..1ab6c5e52a6 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1633,6 +1633,7 @@ typedef enum NodeVectorMathOperation { NODE_VECTOR_MATH_TANGENT = 23, NODE_VECTOR_MATH_REFRACT = 24, NODE_VECTOR_MATH_FACEFORWARD = 25, + NODE_VECTOR_MATH_MULTIPLY_ADD = 26, } NodeVectorMathOperation; /* Boolean math node operations. */ diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index f5cbb694554..2bafbd57e11 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -248,6 +248,7 @@ const EnumPropertyItem rna_enum_node_vec_math_items[] = { {NODE_VECTOR_MATH_SUBTRACT, "SUBTRACT", 0, "Subtract", "A - B"}, {NODE_VECTOR_MATH_MULTIPLY, "MULTIPLY", 0, "Multiply", "Entry-wise multiply"}, {NODE_VECTOR_MATH_DIVIDE, "DIVIDE", 0, "Divide", "Entry-wise divide"}, + {NODE_VECTOR_MATH_MULTIPLY_ADD, "MULTIPLY_ADD", 0, "Multiply Add", "A * B + C"}, {0, "", ICON_NONE, NULL, NULL}, {NODE_VECTOR_MATH_CROSS_PRODUCT, "CROSS_PRODUCT", 0, "Cross Product", "A cross B"}, {NODE_VECTOR_MATH_PROJECT, "PROJECT", 0, "Project", "Project A onto B"}, diff --git a/source/blender/nodes/NOD_math_functions.hh b/source/blender/nodes/NOD_math_functions.hh index 45de1816549..f3eb1c24087 100644 --- a/source/blender/nodes/NOD_math_functions.hh +++ b/source/blender/nodes/NOD_math_functions.hh @@ -347,6 +347,8 @@ inline bool try_dispatch_float_math_fl3_fl3_fl3_to_fl3(const NodeVectorMathOpera }; switch (operation) { + case NODE_VECTOR_MATH_MULTIPLY_ADD: + return dispatch([](float3 a, float3 b, float3 c) { return a * b + c; }); case NODE_VECTOR_MATH_WRAP: return dispatch([](float3 a, float3 b, float3 c) { return float3(wrapf(a.x, b.x, c.x), wrapf(a.y, b.y, c.y), wrapf(a.z, b.z, c.z)); diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_vector_math.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_vector_math.cc index 8877af445f9..b04e04d1cb7 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_vector_math.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_vector_math.cc @@ -59,8 +59,11 @@ static bool operation_use_input_b(const NodeVectorMathOperation operation) static bool operation_use_input_c(const NodeVectorMathOperation operation) { - return ELEM( - operation, NODE_VECTOR_MATH_WRAP, NODE_VECTOR_MATH_REFRACT, NODE_VECTOR_MATH_FACEFORWARD); + return ELEM(operation, + NODE_VECTOR_MATH_WRAP, + NODE_VECTOR_MATH_REFRACT, + NODE_VECTOR_MATH_FACEFORWARD, + NODE_VECTOR_MATH_MULTIPLY_ADD); } static void geo_node_attribute_vector_math_layout(uiLayout *layout, @@ -137,6 +140,7 @@ static CustomDataType operation_get_result_type(const NodeVectorMathOperation op case NODE_VECTOR_MATH_TANGENT: case NODE_VECTOR_MATH_REFRACT: case NODE_VECTOR_MATH_FACEFORWARD: + case NODE_VECTOR_MATH_MULTIPLY_ADD: return CD_PROP_FLOAT3; case NODE_VECTOR_MATH_DOT_PRODUCT: case NODE_VECTOR_MATH_DISTANCE: @@ -495,6 +499,7 @@ static void attribute_vector_math_calc(GeometryComponent &component, break; case NODE_VECTOR_MATH_WRAP: case NODE_VECTOR_MATH_FACEFORWARD: + case NODE_VECTOR_MATH_MULTIPLY_ADD: do_math_operation_fl3_fl3_fl3_to_fl3(attribute_a->typed(), attribute_b->typed(), attribute_c->typed(), diff --git a/source/blender/nodes/intern/math_functions.cc b/source/blender/nodes/intern/math_functions.cc index fb34144abf6..aa23777b664 100644 --- a/source/blender/nodes/intern/math_functions.cc +++ b/source/blender/nodes/intern/math_functions.cc @@ -209,6 +209,8 @@ const FloatMathOperationInfo *get_float3_math_operation_info(const int operation RETURN_OPERATION_INFO("Refract", "vector_math_refract"); case NODE_VECTOR_MATH_FACEFORWARD: RETURN_OPERATION_INFO("Faceforward", "vector_math_faceforward"); + case NODE_VECTOR_MATH_MULTIPLY_ADD: + RETURN_OPERATION_INFO("Multiply Add", "vector_math_multiply_add"); } #undef RETURN_OPERATION_INFO diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_math.cc b/source/blender/nodes/shader/nodes/node_shader_vector_math.cc index 472f903e1a5..419a11201aa 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vector_math.cc +++ b/source/blender/nodes/shader/nodes/node_shader_vector_math.cc @@ -94,6 +94,8 @@ static const char *gpu_shader_get_name(int mode) return "vector_math_refract"; case NODE_VECTOR_MATH_FACEFORWARD: return "vector_math_faceforward"; + case NODE_VECTOR_MATH_MULTIPLY_ADD: + return "vector_math_multiply_add"; } return nullptr; @@ -134,8 +136,11 @@ static void node_shader_update_vector_math(bNodeTree *UNUSED(ntree), bNode *node NODE_VECTOR_MATH_ABSOLUTE, NODE_VECTOR_MATH_FRACTION, NODE_VECTOR_MATH_NORMALIZE)); - nodeSetSocketAvailability( - sockC, ELEM(node->custom1, NODE_VECTOR_MATH_WRAP, NODE_VECTOR_MATH_FACEFORWARD)); + nodeSetSocketAvailability(sockC, + ELEM(node->custom1, + NODE_VECTOR_MATH_WRAP, + NODE_VECTOR_MATH_FACEFORWARD, + NODE_VECTOR_MATH_MULTIPLY_ADD)); nodeSetSocketAvailability(sockScale, ELEM(node->custom1, NODE_VECTOR_MATH_SCALE, NODE_VECTOR_MATH_REFRACT)); nodeSetSocketAvailability(sockVector, @@ -154,6 +159,10 @@ static void node_shader_update_vector_math(bNodeTree *UNUSED(ntree), bNode *node node_sock_label_clear(sockC); node_sock_label_clear(sockScale); switch (node->custom1) { + case NODE_VECTOR_MATH_MULTIPLY_ADD: + node_sock_label(sockB, "Multiplier"); + node_sock_label(sockC, "Addend"); + break; case NODE_VECTOR_MATH_FACEFORWARD: node_sock_label(sockB, "Incident"); node_sock_label(sockC, "Reference");