Nodes: Add Multiply Add to Vector Math nodes

Cycles, Eevee, OSL, Geo, Attribute

This operator provides consistency with the standard math node. Allows users to use a single node instead of two nodes for this common operation.

Reviewed By: HooglyBoogly, brecht

Differential Revision: https://developer.blender.org/D10808
This commit is contained in:
Charlie Jolly 2021-06-04 16:53:50 +01:00 committed by Charlie Jolly
parent eb030204f1
commit 00073651d4
13 changed files with 43 additions and 7 deletions

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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 {

View File

@ -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(

@ -1 +1 @@
Subproject commit 5ab29b1331d2103dae634b987f121c4599459d7f
Subproject commit 2cef4877edc40875978c4e95322bb5193f5815bf

View File

@ -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;
}

View File

@ -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. */

View File

@ -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"},

View File

@ -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));

View File

@ -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<float3>(),
attribute_b->typed<float3>(),
attribute_c->typed<float3>(),

View File

@ -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

View File

@ -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");