Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOmarSquircleArt <omar.squircleart@gmail.com>2019-08-21 20:36:33 +0300
committerOmarSquircleArt <omar.squircleart@gmail.com>2019-08-21 20:36:33 +0300
commit7f4a2fc437cf9a6decbda152bd7d36ce7a08929f (patch)
treea0643b42154c44abf8999192e0c640b4c02615ae
parent6785da095d66c341ca14eeec5c02ab6e4ad2454f (diff)
Shading: Add more operators to Vector Math node.
Add Multiply, Divide, Project, Reflect, Distance, Length, Scale, Snap, Floor, Ceil, Modulo, Fraction, Absolute, Minimum, and Maximum operators to the Vector Math node. The Value output has been removed from operators whose output is a vector, and the other way around. All of those removals has been handled properly in versioning code. The patch doesn't include tests for the new operators. Tests will be added in a later patch. Reviewers: brecht, JacquesLucke Differential Revision: https://developer.blender.org/D5523
-rw-r--r--.clang-format2
-rw-r--r--intern/cycles/blender/blender_session.cpp4
-rw-r--r--intern/cycles/blender/blender_shader.cpp6
-rw-r--r--intern/cycles/kernel/shaders/node_vector_math.osl83
-rw-r--r--intern/cycles/kernel/svm/svm_math.h32
-rw-r--r--intern/cycles/kernel/svm/svm_math_util.h95
-rw-r--r--intern/cycles/kernel/svm/svm_types.h27
-rw-r--r--intern/cycles/render/bake.cpp2
-rw-r--r--intern/cycles/render/constant_fold.cpp39
-rw-r--r--intern/cycles/render/constant_fold.h2
-rw-r--r--intern/cycles/render/nodes.cpp47
-rw-r--r--intern/cycles/render/nodes.h3
-rw-r--r--intern/cycles/subd/subd_dice.cpp4
-rw-r--r--intern/cycles/subd/subd_split.cpp8
-rw-r--r--intern/cycles/test/render_graph_finalize_test.cpp27
-rw-r--r--intern/cycles/util/util_math_float3.h62
-rw-r--r--source/blender/blenkernel/BKE_node.h2
-rw-r--r--source/blender/blenkernel/intern/node.c5
-rw-r--r--source/blender/blenlib/BLI_listbase.h9
-rw-r--r--source/blender/blenloader/intern/versioning_cycles.c352
-rw-r--r--source/blender/editors/space_node/drawnode.c2
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl116
-rw-r--r--source/blender/makesdna/DNA_node_types.h27
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c39
-rw-r--r--source/blender/nodes/CMakeLists.txt2
-rw-r--r--source/blender/nodes/NOD_static_types.h2
-rw-r--r--source/blender/nodes/intern/node_util.c2
-rw-r--r--source/blender/nodes/intern/node_util.h2
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_normal_map.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vectMath.c155
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vector_math.c113
32 files changed, 968 insertions, 307 deletions
diff --git a/.clang-format b/.clang-format
index bbbe3f1bac4..b81403c46ce 100644
--- a/.clang-format
+++ b/.clang-format
@@ -224,7 +224,9 @@ ForEachMacros:
- LISTBASE_CIRCULAR_BACKWARD_BEGIN
- LISTBASE_CIRCULAR_FORWARD_BEGIN
- LISTBASE_FOREACH
+ - LISTBASE_FOREACH_BACKWARD
- LISTBASE_FOREACH_MUTABLE
+ - LISTBASE_FOREACH_BACKWARD_MUTABLE
- MAN2D_ITER_AXES_BEGIN
- MAN_ITER_AXES_BEGIN
- NODE_INSTANCE_HASH_ITER
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index d38a97dc4ea..047cc82dbfc 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -1481,8 +1481,8 @@ void BlenderSession::update_resumable_tile_manager(int num_samples)
/* Round after doing the multiplications with num_chunks and num_samples_per_chunk
* to allow for many small chunks. */
- int rounded_range_start_sample = (int)floor(range_start_sample + 0.5f);
- int rounded_range_num_samples = max((int)floor(range_num_samples + 0.5f), 1);
+ int rounded_range_start_sample = (int)floorf(range_start_sample + 0.5f);
+ int rounded_range_num_samples = max((int)floorf(range_num_samples + 0.5f), 1);
/* Make sure we don't overshoot. */
if (rounded_range_start_sample + rounded_range_num_samples > num_samples) {
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 626a1dad7db..322a1771786 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -333,9 +333,9 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeVectorMath)) {
BL::ShaderNodeVectorMath b_vector_math_node(b_node);
- VectorMathNode *vmath = new VectorMathNode();
- vmath->type = (NodeVectorMath)b_vector_math_node.operation();
- node = vmath;
+ VectorMathNode *vector_math_node = new VectorMathNode();
+ vector_math_node->type = (NodeVectorMathType)b_vector_math_node.operation();
+ node = vector_math_node;
}
else if (b_node.is_a(&RNA_ShaderNodeVectorTransform)) {
BL::ShaderNodeVectorTransform b_vector_transform_node(b_node);
diff --git a/intern/cycles/kernel/shaders/node_vector_math.osl b/intern/cycles/kernel/shaders/node_vector_math.osl
index 10bb0c7283c..fd5e27aa144 100644
--- a/intern/cycles/kernel/shaders/node_vector_math.osl
+++ b/intern/cycles/kernel/shaders/node_vector_math.osl
@@ -16,34 +16,97 @@
#include "stdosl.h"
+float safe_divide(float a, float b)
+{
+ return (b != 0.0) ? a / b : 0.0;
+}
+
+vector safe_divide(vector a, vector b)
+{
+ return vector((b[0] != 0.0) ? a[0] / b[0] : 0.0,
+ (b[1] != 0.0) ? a[1] / b[1] : 0.0,
+ (b[2] != 0.0) ? a[2] / b[2] : 0.0);
+}
+
+vector project(vector v, vector v_proj)
+{
+ float lenSquared = dot(v_proj, v_proj);
+ return (lenSquared != 0.0) ? (dot(v, v_proj) / lenSquared) * v_proj : vector(0.0);
+}
+
+vector snap(vector a, vector b)
+{
+ return floor(safe_divide(a, b)) * b;
+}
+
shader node_vector_math(string type = "add",
vector Vector1 = vector(0.0, 0.0, 0.0),
vector Vector2 = vector(0.0, 0.0, 0.0),
+ float Scale = 1.0,
output float Value = 0.0,
output vector Vector = vector(0.0, 0.0, 0.0))
{
if (type == "add") {
Vector = Vector1 + Vector2;
- Value = (abs(Vector[0]) + abs(Vector[1]) + abs(Vector[2])) / 3.0;
}
else if (type == "subtract") {
Vector = Vector1 - Vector2;
- Value = (abs(Vector[0]) + abs(Vector[1]) + abs(Vector[2])) / 3.0;
}
- else if (type == "average") {
- Value = length(Vector1 + Vector2);
- Vector = normalize(Vector1 + Vector2);
+ else if (type == "multiply") {
+ Vector = Vector1 * Vector2;
+ }
+ else if (type == "divide") {
+ Vector = safe_divide(Vector1, Vector2);
+ }
+ else if (type == "cross_product") {
+ Vector = cross(Vector1, Vector2);
+ }
+ else if (type == "project") {
+ Vector = project(Vector1, Vector2);
+ }
+ else if (type == "reflect") {
+ Vector = reflect(Vector1, normalize(Vector2));
}
else if (type == "dot_product") {
Value = dot(Vector1, Vector2);
}
- else if (type == "cross_product") {
- vector c = cross(Vector1, Vector2);
- Value = length(c);
- Vector = normalize(c);
+ else if (type == "distance") {
+ Value = distance(Vector1, Vector2);
}
- else if (type == "normalize") {
+ else if (type == "length") {
Value = length(Vector1);
+ }
+ else if (type == "scale") {
+ Vector = Vector1 * Scale;
+ }
+ else if (type == "normalize") {
Vector = normalize(Vector1);
}
+ else if (type == "snap") {
+ Vector = snap(Vector1, Vector2);
+ }
+ else if (type == "floor") {
+ Vector = floor(Vector1);
+ }
+ else if (type == "ceil") {
+ Vector = ceil(Vector1);
+ }
+ else if (type == "modulo") {
+ Vector = mod(Vector1, Vector2);
+ }
+ else if (type == "fraction") {
+ Vector = Vector1 - floor(Vector1);
+ }
+ else if (type == "absolute") {
+ Vector = abs(Vector1);
+ }
+ else if (type == "minimum") {
+ Vector = min(Vector1, Vector2);
+ }
+ else if (type == "maximum") {
+ Vector = max(Vector1, Vector2);
+ }
+ else {
+ warning("%s", "Unknown vector math operator!");
+ }
}
diff --git a/intern/cycles/kernel/svm/svm_math.h b/intern/cycles/kernel/svm/svm_math.h
index 402290d7218..c577a7f13c7 100644
--- a/intern/cycles/kernel/svm/svm_math.h
+++ b/intern/cycles/kernel/svm/svm_math.h
@@ -37,25 +37,29 @@ ccl_device void svm_node_math(KernelGlobals *kg,
ccl_device void svm_node_vector_math(KernelGlobals *kg,
ShaderData *sd,
float *stack,
- uint itype,
- uint v1_offset,
- uint v2_offset,
+ uint type,
+ uint inputs_stack_offsets,
+ uint outputs_stack_offsets,
int *offset)
{
- NodeVectorMath type = (NodeVectorMath)itype;
- float3 v1 = stack_load_float3(stack, v1_offset);
- float3 v2 = stack_load_float3(stack, v2_offset);
- float f;
- float3 v;
+ uint value_stack_offset, vector_stack_offset;
+ uint a_stack_offset, b_stack_offset, scale_stack_offset;
+ decode_node_uchar4(
+ inputs_stack_offsets, &a_stack_offset, &b_stack_offset, &scale_stack_offset, NULL);
+ decode_node_uchar4(outputs_stack_offsets, &value_stack_offset, &vector_stack_offset, NULL, NULL);
- svm_vector_math(&f, &v, type, v1, v2);
+ float3 a = stack_load_float3(stack, a_stack_offset);
+ float3 b = stack_load_float3(stack, b_stack_offset);
+ float scale = stack_load_float(stack, scale_stack_offset);
- uint4 node1 = read_node(kg, offset);
+ float value;
+ float3 vector;
+ svm_vector_math(&value, &vector, (NodeVectorMathType)type, a, b, scale);
- if (stack_valid(node1.y))
- stack_store_float(stack, node1.y, f);
- if (stack_valid(node1.z))
- stack_store_float3(stack, node1.z, v);
+ if (stack_valid(value_stack_offset))
+ stack_store_float(stack, value_stack_offset, value);
+ if (stack_valid(vector_stack_offset))
+ stack_store_float3(stack, vector_stack_offset, vector);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_math_util.h b/intern/cycles/kernel/svm/svm_math_util.h
index d8804226487..c87ca0defa7 100644
--- a/intern/cycles/kernel/svm/svm_math_util.h
+++ b/intern/cycles/kernel/svm/svm_math_util.h
@@ -16,38 +16,73 @@
CCL_NAMESPACE_BEGIN
-ccl_device float average_fac(float3 v)
-{
- return (fabsf(v.x) + fabsf(v.y) + fabsf(v.z)) / 3.0f;
-}
-
ccl_device void svm_vector_math(
- float *Fac, float3 *Vector, NodeVectorMath type, float3 Vector1, float3 Vector2)
+ float *value, float3 *vector, NodeVectorMathType type, float3 a, float3 b, float scale)
{
- if (type == NODE_VECTOR_MATH_ADD) {
- *Vector = Vector1 + Vector2;
- *Fac = average_fac(*Vector);
- }
- else if (type == NODE_VECTOR_MATH_SUBTRACT) {
- *Vector = Vector1 - Vector2;
- *Fac = average_fac(*Vector);
- }
- else if (type == NODE_VECTOR_MATH_AVERAGE) {
- *Vector = safe_normalize_len(Vector1 + Vector2, Fac);
- }
- else if (type == NODE_VECTOR_MATH_DOT_PRODUCT) {
- *Fac = dot(Vector1, Vector2);
- *Vector = make_float3(0.0f, 0.0f, 0.0f);
- }
- else if (type == NODE_VECTOR_MATH_CROSS_PRODUCT) {
- *Vector = safe_normalize_len(cross(Vector1, Vector2), Fac);
- }
- else if (type == NODE_VECTOR_MATH_NORMALIZE) {
- *Vector = safe_normalize_len(Vector1, Fac);
- }
- else {
- *Fac = 0.0f;
- *Vector = make_float3(0.0f, 0.0f, 0.0f);
+ switch (type) {
+ case NODE_VECTOR_MATH_ADD:
+ *vector = a + b;
+ break;
+ case NODE_VECTOR_MATH_SUBTRACT:
+ *vector = a - b;
+ break;
+ case NODE_VECTOR_MATH_MULTIPLY:
+ *vector = a * b;
+ break;
+ case NODE_VECTOR_MATH_DIVIDE:
+ *vector = safe_divide_float3_float3(a, b);
+ break;
+ case NODE_VECTOR_MATH_CROSS_PRODUCT:
+ *vector = cross(a, b);
+ break;
+ case NODE_VECTOR_MATH_PROJECT:
+ *vector = project(a, b);
+ break;
+ case NODE_VECTOR_MATH_REFLECT:
+ *vector = reflect(a, b);
+ break;
+ case NODE_VECTOR_MATH_DOT_PRODUCT:
+ *value = dot(a, b);
+ break;
+ case NODE_VECTOR_MATH_DISTANCE:
+ *value = distance(a, b);
+ break;
+ case NODE_VECTOR_MATH_LENGTH:
+ *value = len(a);
+ break;
+ case NODE_VECTOR_MATH_SCALE:
+ *vector = a * scale;
+ break;
+ case NODE_VECTOR_MATH_NORMALIZE:
+ *vector = safe_normalize(a);
+ break;
+ case NODE_VECTOR_MATH_SNAP:
+ *vector = floor(safe_divide_float3_float3(a, b)) * b;
+ break;
+ case NODE_VECTOR_MATH_FLOOR:
+ *vector = floor(a);
+ break;
+ case NODE_VECTOR_MATH_CEIL:
+ *vector = ceil(a);
+ break;
+ case NODE_VECTOR_MATH_MODULO:
+ *vector = make_float3(safe_modulo(a.x, b.x), safe_modulo(a.y, b.y), safe_modulo(a.z, b.z));
+ break;
+ case NODE_VECTOR_MATH_FRACTION:
+ *vector = fract(a);
+ break;
+ case NODE_VECTOR_MATH_ABSOLUTE:
+ *vector = fabs(a);
+ break;
+ case NODE_VECTOR_MATH_MINIMUM:
+ *vector = min(a, b);
+ break;
+ case NODE_VECTOR_MATH_MAXIMUM:
+ *vector = max(a, b);
+ break;
+ default:
+ *vector = make_float3(0.0f, 0.0f, 0.0f);
+ *value = 0.0f;
}
}
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index 6b0d10adc74..884ad76a9b7 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -271,14 +271,31 @@ typedef enum NodeMathType {
NODE_MATH_SQRT,
} NodeMathType;
-typedef enum NodeVectorMath {
+typedef enum NodeVectorMathType {
NODE_VECTOR_MATH_ADD,
NODE_VECTOR_MATH_SUBTRACT,
- NODE_VECTOR_MATH_AVERAGE,
- NODE_VECTOR_MATH_DOT_PRODUCT,
+ NODE_VECTOR_MATH_MULTIPLY,
+ NODE_VECTOR_MATH_DIVIDE,
+
NODE_VECTOR_MATH_CROSS_PRODUCT,
- NODE_VECTOR_MATH_NORMALIZE
-} NodeVectorMath;
+ NODE_VECTOR_MATH_PROJECT,
+ NODE_VECTOR_MATH_REFLECT,
+ NODE_VECTOR_MATH_DOT_PRODUCT,
+
+ NODE_VECTOR_MATH_DISTANCE,
+ NODE_VECTOR_MATH_LENGTH,
+ NODE_VECTOR_MATH_SCALE,
+ NODE_VECTOR_MATH_NORMALIZE,
+
+ NODE_VECTOR_MATH_SNAP,
+ NODE_VECTOR_MATH_FLOOR,
+ NODE_VECTOR_MATH_CEIL,
+ NODE_VECTOR_MATH_MODULO,
+ NODE_VECTOR_MATH_FRACTION,
+ NODE_VECTOR_MATH_ABSOLUTE,
+ NODE_VECTOR_MATH_MINIMUM,
+ NODE_VECTOR_MATH_MAXIMUM,
+} NodeVectorMathType;
typedef enum NodeVectorTransformType {
NODE_VECTOR_TRANSFORM_TYPE_VECTOR,
diff --git a/intern/cycles/render/bake.cpp b/intern/cycles/render/bake.cpp
index 73893921500..b906357b7b5 100644
--- a/intern/cycles/render/bake.cpp
+++ b/intern/cycles/render/bake.cpp
@@ -124,7 +124,7 @@ BakeData *BakeManager::init(const int object, const size_t tri_offset, const siz
void BakeManager::set_shader_limit(const size_t x, const size_t y)
{
m_shader_limit = x * y;
- m_shader_limit = (size_t)pow(2, ceil(log(m_shader_limit) / log(2)));
+ m_shader_limit = (size_t)pow(2, std::ceil(log(m_shader_limit) / log(2)));
}
bool BakeManager::bake(Device *device,
diff --git a/intern/cycles/render/constant_fold.cpp b/intern/cycles/render/constant_fold.cpp
index d6fdc49434e..851d4b71df8 100644
--- a/intern/cycles/render/constant_fold.cpp
+++ b/intern/cycles/render/constant_fold.cpp
@@ -359,10 +359,11 @@ void ConstantFolder::fold_math(NodeMathType type) const
}
}
-void ConstantFolder::fold_vector_math(NodeVectorMath type) const
+void ConstantFolder::fold_vector_math(NodeVectorMathType type) const
{
ShaderInput *vector1_in = node->input("Vector1");
ShaderInput *vector2_in = node->input("Vector2");
+ ShaderInput *scale_in = node->input("Scale");
switch (type) {
case NODE_VECTOR_MATH_ADD:
@@ -380,6 +381,27 @@ void ConstantFolder::fold_vector_math(NodeVectorMath type) const
try_bypass_or_make_constant(vector1_in);
}
break;
+ case NODE_VECTOR_MATH_MULTIPLY:
+ /* X * 0 == 0 * X == 0 */
+ if (is_zero(vector1_in) || is_zero(vector2_in)) {
+ make_zero();
+ } /* X * 1 == 1 * X == X */
+ else if (is_one(vector1_in)) {
+ try_bypass_or_make_constant(vector2_in);
+ }
+ else if (is_one(vector2_in)) {
+ try_bypass_or_make_constant(vector1_in);
+ }
+ break;
+ case NODE_VECTOR_MATH_DIVIDE:
+ /* X / 0 == 0 / X == 0 */
+ if (is_zero(vector1_in) || is_zero(vector2_in)) {
+ make_zero();
+ } /* X / 1 == X */
+ else if (is_one(vector2_in)) {
+ try_bypass_or_make_constant(vector1_in);
+ }
+ break;
case NODE_VECTOR_MATH_DOT_PRODUCT:
case NODE_VECTOR_MATH_CROSS_PRODUCT:
/* X * 0 == 0 * X == 0 */
@@ -387,6 +409,21 @@ void ConstantFolder::fold_vector_math(NodeVectorMath type) const
make_zero();
}
break;
+ case NODE_VECTOR_MATH_LENGTH:
+ case NODE_VECTOR_MATH_ABSOLUTE:
+ if (is_zero(vector1_in)) {
+ make_zero();
+ }
+ break;
+ case NODE_VECTOR_MATH_SCALE:
+ /* X * 0 == 0 * X == 0 */
+ if (is_zero(vector1_in) || is_zero(scale_in)) {
+ make_zero();
+ } /* X * 1 == X */
+ else if (is_one(scale_in)) {
+ try_bypass_or_make_constant(vector1_in);
+ }
+ break;
default:
break;
}
diff --git a/intern/cycles/render/constant_fold.h b/intern/cycles/render/constant_fold.h
index d223fd86197..881636a9fe1 100644
--- a/intern/cycles/render/constant_fold.h
+++ b/intern/cycles/render/constant_fold.h
@@ -65,7 +65,7 @@ class ConstantFolder {
/* Specific nodes. */
void fold_mix(NodeMix type, bool clamp) const;
void fold_math(NodeMathType type) const;
- void fold_vector_math(NodeVectorMath type) const;
+ void fold_vector_math(NodeVectorMathType type) const;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 642f7beaf3c..8c8bb559c30 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -163,8 +163,10 @@ void TextureMapping::compile(SVMCompiler &compiler, int offset_in, int offset_ou
}
if (type == NORMAL) {
- compiler.add_node(NODE_VECTOR_MATH, NODE_VECTOR_MATH_NORMALIZE, offset_out, offset_out);
- compiler.add_node(NODE_VECTOR_MATH, SVM_STACK_INVALID, offset_out);
+ compiler.add_node(NODE_VECTOR_MATH,
+ NODE_VECTOR_MATH_NORMALIZE,
+ compiler.encode_uchar4(offset_out, offset_out, offset_out),
+ compiler.encode_uchar4(SVM_STACK_INVALID, offset_out));
}
}
@@ -5496,14 +5498,32 @@ NODE_DEFINE(VectorMathNode)
static NodeEnum type_enum;
type_enum.insert("add", NODE_VECTOR_MATH_ADD);
type_enum.insert("subtract", NODE_VECTOR_MATH_SUBTRACT);
- type_enum.insert("average", NODE_VECTOR_MATH_AVERAGE);
- type_enum.insert("dot_product", NODE_VECTOR_MATH_DOT_PRODUCT);
+ type_enum.insert("multiply", NODE_VECTOR_MATH_MULTIPLY);
+ type_enum.insert("divide", NODE_VECTOR_MATH_DIVIDE);
+
type_enum.insert("cross_product", NODE_VECTOR_MATH_CROSS_PRODUCT);
+ type_enum.insert("project", NODE_VECTOR_MATH_PROJECT);
+ type_enum.insert("reflect", NODE_VECTOR_MATH_REFLECT);
+ type_enum.insert("dot_product", NODE_VECTOR_MATH_DOT_PRODUCT);
+
+ type_enum.insert("distance", NODE_VECTOR_MATH_DISTANCE);
+ type_enum.insert("length", NODE_VECTOR_MATH_LENGTH);
+ type_enum.insert("scale", NODE_VECTOR_MATH_SCALE);
type_enum.insert("normalize", NODE_VECTOR_MATH_NORMALIZE);
+
+ type_enum.insert("snap", NODE_VECTOR_MATH_SNAP);
+ type_enum.insert("floor", NODE_VECTOR_MATH_FLOOR);
+ type_enum.insert("ceil", NODE_VECTOR_MATH_CEIL);
+ type_enum.insert("modulo", NODE_VECTOR_MATH_MODULO);
+ type_enum.insert("fraction", NODE_VECTOR_MATH_FRACTION);
+ type_enum.insert("absolute", NODE_VECTOR_MATH_ABSOLUTE);
+ type_enum.insert("minimum", NODE_VECTOR_MATH_MINIMUM);
+ type_enum.insert("maximum", NODE_VECTOR_MATH_MAXIMUM);
SOCKET_ENUM(type, "Type", type_enum, NODE_VECTOR_MATH_ADD);
SOCKET_IN_VECTOR(vector1, "Vector1", make_float3(0.0f, 0.0f, 0.0f));
SOCKET_IN_VECTOR(vector2, "Vector2", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
SOCKET_OUT_FLOAT(value, "Value");
SOCKET_OUT_VECTOR(vector, "Vector");
@@ -5521,8 +5541,7 @@ void VectorMathNode::constant_fold(const ConstantFolder &folder)
float3 vector;
if (folder.all_inputs_constant()) {
- svm_vector_math(&value, &vector, type, vector1, vector2);
-
+ svm_vector_math(&value, &vector, type, vector1, vector2, scale);
if (folder.output == output("Value")) {
folder.make_constant(value);
}
@@ -5539,15 +5558,21 @@ void VectorMathNode::compile(SVMCompiler &compiler)
{
ShaderInput *vector1_in = input("Vector1");
ShaderInput *vector2_in = input("Vector2");
+ ShaderInput *scale_in = input("Scale");
ShaderOutput *value_out = output("Value");
ShaderOutput *vector_out = output("Vector");
- compiler.add_node(NODE_VECTOR_MATH,
- type,
- compiler.stack_assign(vector1_in),
- compiler.stack_assign(vector2_in));
+ int vector1_stack_offset = compiler.stack_assign(vector1_in);
+ int vector2_stack_offset = compiler.stack_assign(vector2_in);
+ int scale_stack_offset = compiler.stack_assign(scale_in);
+ int value_stack_offset = compiler.stack_assign_if_linked(value_out);
+ int vector_stack_offset = compiler.stack_assign_if_linked(vector_out);
+
compiler.add_node(
- NODE_VECTOR_MATH, compiler.stack_assign(value_out), compiler.stack_assign(vector_out));
+ NODE_VECTOR_MATH,
+ type,
+ compiler.encode_uchar4(vector1_stack_offset, vector2_stack_offset, scale_stack_offset),
+ compiler.encode_uchar4(value_stack_offset, vector_stack_offset));
}
void VectorMathNode::compile(OSLCompiler &compiler)
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 514ab3db8eb..417623c7562 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -1292,7 +1292,8 @@ class VectorMathNode : public ShaderNode {
float3 vector1;
float3 vector2;
- NodeVectorMath type;
+ float scale;
+ NodeVectorMathType type;
};
class VectorTransformNode : public ShaderNode {
diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp
index fb96be5065b..914b408911e 100644
--- a/intern/cycles/subd/subd_dice.cpp
+++ b/intern/cycles/subd/subd_dice.cpp
@@ -323,8 +323,8 @@ void QuadDice::dice(SubPatch &sub, EdgeFactors &ef)
float S = 1.0f;
#endif
- Mu = max((int)ceil(S * Mu), 2); // XXX handle 0 & 1?
- Mv = max((int)ceil(S * Mv), 2); // XXX handle 0 & 1?
+ Mu = max((int)ceilf(S * Mu), 2); // XXX handle 0 & 1?
+ Mv = max((int)ceilf(S * Mv), 2); // XXX handle 0 & 1?
/* reserve space for new verts */
int offset = params.mesh->verts.size();
diff --git a/intern/cycles/subd/subd_split.cpp b/intern/cycles/subd/subd_split.cpp
index e6603632ba7..e5b85fcfd60 100644
--- a/intern/cycles/subd/subd_split.cpp
+++ b/intern/cycles/subd/subd_split.cpp
@@ -80,9 +80,9 @@ int DiagSplit::T(Patch *patch, float2 Pstart, float2 Pend)
Plast = P;
}
- int tmin = (int)ceil(Lsum / params.dicing_rate);
- int tmax = (int)ceil((params.test_steps - 1) * Lmax /
- params.dicing_rate); // XXX paper says N instead of N-1, seems wrong?
+ int tmin = (int)ceilf(Lsum / params.dicing_rate);
+ int tmax = (int)ceilf((params.test_steps - 1) * Lmax /
+ params.dicing_rate); // XXX paper says N instead of N-1, seems wrong?
if (tmax - tmin > params.split_threshold)
return DSPLIT_NON_UNIFORM;
@@ -99,7 +99,7 @@ void DiagSplit::partition_edge(
*t1 = T(patch, *P, Pend);
}
else {
- int I = (int)floor((float)t * 0.5f);
+ int I = (int)floorf((float)t * 0.5f);
*P = interp(Pstart, Pend, (t == 0) ? 0 : I / (float)t); /* XXX is t faces or verts */
*t0 = I;
*t1 = t - I;
diff --git a/intern/cycles/test/render_graph_finalize_test.cpp b/intern/cycles/test/render_graph_finalize_test.cpp
index 7d4b600350b..ca93f8b02d0 100644
--- a/intern/cycles/test/render_graph_finalize_test.cpp
+++ b/intern/cycles/test/render_graph_finalize_test.cpp
@@ -1163,21 +1163,14 @@ TEST_F(RenderGraph, constant_fold_part_math_pow_1)
TEST_F(RenderGraph, constant_fold_vector_math)
{
EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding VectorMath::Value to constant (1).");
CORRECT_INFO_MESSAGE(log, "Folding VectorMath::Vector to constant (3, 0, 0).");
- CORRECT_INFO_MESSAGE(log, "Folding convert_vector_to_float::value_float to constant (1).");
- CORRECT_INFO_MESSAGE(log, "Folding Math::Value to constant (2).");
- CORRECT_INFO_MESSAGE(log, "Folding convert_float_to_color::value_color to constant (2, 2, 2).");
builder
.add_node(ShaderNodeBuilder<VectorMathNode>("VectorMath")
.set(&VectorMathNode::type, NODE_VECTOR_MATH_SUBTRACT)
.set("Vector1", make_float3(1.3f, 0.5f, 0.7f))
.set("Vector2", make_float3(-1.7f, 0.5f, 0.7f)))
- .add_node(ShaderNodeBuilder<MathNode>("Math").set(&MathNode::type, NODE_MATH_ADD))
- .add_connection("VectorMath::Vector", "Math::Value1")
- .add_connection("VectorMath::Value", "Math::Value2")
- .output_color("Math::Value");
+ .output_color("VectorMath::Vector");
graph.finalize(scene);
}
@@ -1187,7 +1180,7 @@ TEST_F(RenderGraph, constant_fold_vector_math)
* Includes 2 tests: constant on each side.
*/
static void build_vecmath_partial_test_graph(ShaderGraphBuilder &builder,
- NodeVectorMath type,
+ NodeVectorMathType type,
float3 constval)
{
builder
@@ -1241,22 +1234,6 @@ TEST_F(RenderGraph, constant_fold_part_vecmath_sub_0)
}
/*
- * Tests: partial folding for Vector Math Dot Product with known 0.
- */
-TEST_F(RenderGraph, constant_fold_part_vecmath_dot_0)
-{
- EXPECT_ANY_MESSAGE(log);
- /* X * 0 == 0 * X == X */
- CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Vector to constant (0, 0, 0).");
- CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Vector to constant (0, 0, 0).");
- CORRECT_INFO_MESSAGE(log, "Folding Out::Vector to constant (0, 0, 0).");
- CORRECT_INFO_MESSAGE(log, "Discarding closure EmissionNode.");
-
- build_vecmath_partial_test_graph(builder, NODE_VECTOR_MATH_DOT_PRODUCT, make_float3(0, 0, 0));
- graph.finalize(scene);
-}
-
-/*
* Tests: partial folding for Vector Math Cross Product with known 0.
*/
TEST_F(RenderGraph, constant_fold_part_vecmath_cross_0)
diff --git a/intern/cycles/util/util_math_float3.h b/intern/cycles/util/util_math_float3.h
index 554b7408148..0d7588da690 100644
--- a/intern/cycles/util/util_math_float3.h
+++ b/intern/cycles/util/util_math_float3.h
@@ -47,6 +47,7 @@ ccl_device_inline float3 operator/=(float3 &a, float f);
ccl_device_inline bool operator==(const float3 &a, const float3 &b);
ccl_device_inline bool operator!=(const float3 &a, const float3 &b);
+ccl_device_inline float distance(const float3 &a, const float3 &b);
ccl_device_inline float dot(const float3 &a, const float3 &b);
ccl_device_inline float dot_xy(const float3 &a, const float3 &b);
ccl_device_inline float3 cross(const float3 &a, const float3 &b);
@@ -58,6 +59,9 @@ ccl_device_inline float3 fabs(const float3 &a);
ccl_device_inline float3 mix(const float3 &a, const float3 &b, float t);
ccl_device_inline float3 rcp(const float3 &a);
ccl_device_inline float3 sqrt(const float3 &a);
+ccl_device_inline float3 floor(const float3 &a);
+ccl_device_inline float3 ceil(const float3 &a);
+ccl_device_inline float3 fract(const float3 &a);
#endif /* !__KERNEL_OPENCL__ */
ccl_device_inline float min3(float3 a);
@@ -65,10 +69,15 @@ ccl_device_inline float max3(float3 a);
ccl_device_inline float len(const float3 a);
ccl_device_inline float len_squared(const float3 a);
+ccl_device_inline float3 reflect(const float3 incident, const float3 normal);
+ccl_device_inline float3 project(const float3 v, const float3 v_proj);
+
ccl_device_inline float3 saturate3(float3 a);
ccl_device_inline float3 safe_normalize(const float3 a);
ccl_device_inline float3 normalize_len(const float3 a, float *t);
ccl_device_inline float3 safe_normalize_len(const float3 a, float *t);
+ccl_device_inline float3 safe_divide_float3_float3(const float3 a, const float3 b);
+ccl_device_inline float3 safe_divide_float3_float(const float3 a, const float b);
ccl_device_inline float3 interp(float3 a, float3 b, float t);
ccl_device_inline float3 sqr3(float3 a);
@@ -205,6 +214,11 @@ ccl_device_inline bool operator!=(const float3 &a, const float3 &b)
return !(a == b);
}
+ccl_device_inline float distance(const float3 &a, const float3 &b)
+{
+ return len(a - b);
+}
+
ccl_device_inline float dot(const float3 &a, const float3 &b)
{
# if defined(__KERNEL_SSE41__) && defined(__KERNEL_SSE__)
@@ -281,6 +295,29 @@ ccl_device_inline float3 sqrt(const float3 &a)
# endif
}
+ccl_device_inline float3 floor(const float3 &a)
+{
+# ifdef __KERNEL_SSE__
+ return float3(_mm_floor_ps(a));
+# else
+ return make_float3(floorf(a.x), floorf(a.y), floorf(a.z));
+# endif
+}
+
+ccl_device_inline float3 ceil(const float3 &a)
+{
+# ifdef __KERNEL_SSE__
+ return float3(_mm_ceil_ps(a));
+# else
+ return make_float3(ceilf(a.x), ceilf(a.y), ceilf(a.z));
+# endif
+}
+
+ccl_device_inline float3 fract(const float3 &a)
+{
+ return a - floor(a);
+}
+
ccl_device_inline float3 mix(const float3 &a, const float3 &b, float t)
{
return a + t * (b - a);
@@ -321,6 +358,19 @@ ccl_device_inline float len_squared(const float3 a)
return dot(a, a);
}
+ccl_device_inline float3 reflect(const float3 incident, const float3 normal)
+{
+ float3 unit_normal = normalize(normal);
+ return incident - 2.0f * unit_normal * dot(incident, unit_normal);
+}
+
+ccl_device_inline float3 project(const float3 v, const float3 v_proj)
+{
+ float len_squared = dot(v_proj, v_proj);
+ return (len_squared != 0.0f) ? (dot(v, v_proj) / len_squared) * v_proj :
+ make_float3(0.0f, 0.0f, 0.0f);
+}
+
ccl_device_inline float3 saturate3(float3 a)
{
return make_float3(saturate(a.x), saturate(a.y), saturate(a.z));
@@ -345,6 +395,18 @@ ccl_device_inline float3 safe_normalize_len(const float3 a, float *t)
return (*t != 0.0f) ? a / (*t) : a;
}
+ccl_device_inline float3 safe_divide_float3_float3(const float3 a, const float3 b)
+{
+ return make_float3((b.x != 0.0f) ? a.x / b.x : 0.0f,
+ (b.y != 0.0f) ? a.y / b.y : 0.0f,
+ (b.z != 0.0f) ? a.z / b.z : 0.0f);
+}
+
+ccl_device_inline float3 safe_divide_float3_float(const float3 a, const float b)
+{
+ return (b != 0.0f) ? a / b : make_float3(0.0f, 0.0f, 0.0f);
+}
+
ccl_device_inline float3 interp(float3 a, float3 b, float t)
{
return a + t * (b - a);
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 7d427cb7799..1b7debe4496 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -895,7 +895,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree,
#define SH_NODE_CURVE_RGB 111
#define SH_NODE_CAMERA 114
#define SH_NODE_MATH 115
-#define SH_NODE_VECT_MATH 116
+#define SH_NODE_VECTOR_MATH 116
#define SH_NODE_SQUEEZE 117
//#define SH_NODE_MATERIAL_EXT 118
#define SH_NODE_INVERT 119
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index d64a5a33ef1..7e455ba742a 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -3232,11 +3232,6 @@ void ntreeTagUsedSockets(bNodeTree *ntree)
}
for (link = ntree->links.first; link; link = link->next) {
- /* link is unused if either side is disabled */
- if ((link->fromsock->flag & SOCK_UNAVAIL) || (link->tosock->flag & SOCK_UNAVAIL)) {
- continue;
- }
-
link->fromsock->flag |= SOCK_IN_USE;
link->tosock->flag |= SOCK_IN_USE;
}
diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h
index c235a72e7e4..b8b62dd3451 100644
--- a/source/blender/blenlib/BLI_listbase.h
+++ b/source/blender/blenlib/BLI_listbase.h
@@ -171,12 +171,21 @@ struct LinkData *BLI_genericNodeN(void *data);
#define LISTBASE_FOREACH(type, var, list) \
for (type var = (type)((list)->first); var != NULL; var = (type)(((Link *)(var))->next))
+#define LISTBASE_FOREACH_BACKWARD(type, var, list) \
+ for (type var = (type)((list)->last); var != NULL; var = (type)(((Link *)(var))->prev))
+
/** A version of #LISTBASE_FOREACH that supports removing the item we're looping over. */
#define LISTBASE_FOREACH_MUTABLE(type, var, list) \
for (type var = (type)((list)->first), *var##_iter_next; \
((var != NULL) ? ((void)(var##_iter_next = (type)(((Link *)(var))->next)), 1) : 0); \
var = var##_iter_next)
+/** A version of #LISTBASE_FOREACH_BACKWARD that supports removing the item we're looping over. */
+#define LISTBASE_FOREACH_BACKWARD_MUTABLE(type, var, list) \
+ for (type var = (type)((list)->last), *var##_iter_prev; \
+ ((var != NULL) ? ((void)(var##_iter_prev = (type)(((Link *)(var))->prev)), 1) : 0); \
+ var = var##_iter_prev)
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenloader/intern/versioning_cycles.c b/source/blender/blenloader/intern/versioning_cycles.c
index 10f24cff61b..a3e9b8dc206 100644
--- a/source/blender/blenloader/intern/versioning_cycles.c
+++ b/source/blender/blenloader/intern/versioning_cycles.c
@@ -45,6 +45,11 @@
#include "BLO_readfile.h"
#include "readfile.h"
+static bool socket_is_used(bNodeSocket *sock)
+{
+ return sock->flag & SOCK_IN_USE;
+}
+
static float *cycles_node_socket_float_value(bNodeSocket *socket)
{
bNodeSocketValueFloat *socket_data = socket->default_value;
@@ -57,6 +62,12 @@ static float *cycles_node_socket_rgba_value(bNodeSocket *socket)
return socket_data->value;
}
+static float *cycles_node_socket_vector_value(bNodeSocket *socket)
+{
+ bNodeSocketValueVector *socket_data = socket->default_value;
+ return socket_data->value;
+}
+
static IDProperty *cycles_properties_from_ID(ID *id)
{
IDProperty *idprop = IDP_GetProperties(id, false);
@@ -426,6 +437,325 @@ static void update_math_node_single_operand_operators(bNodeTree *ntree)
}
}
+/* The Value output of the Vector Math node is no longer available in the Add
+ * and Subtract operators. Previously, this Value output was computed from the
+ * Vector output V as follows:
+ *
+ * Value = (abs(V.x) + abs(V.y) + abs(V.z)) / 3
+ *
+ * Or more compactly using vector operators:
+ *
+ * Value = dot(abs(V), (1 / 3, 1 / 3, 1 / 3))
+ *
+ * To correct this, if the Value output was used, we are going to compute
+ * it using the second equation by adding an absolute and a dot node, and
+ * then connect them appropriately.
+ */
+static void update_vector_math_node_add_and_subtract_operators(bNodeTree *ntree)
+{
+ bool need_update = false;
+
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_VECTOR_MATH) {
+ bNodeSocket *sockOutValue = nodeFindSocket(node, SOCK_OUT, "Value");
+ if (socket_is_used(sockOutValue) &&
+ ELEM(node->custom1, NODE_VECTOR_MATH_ADD, NODE_VECTOR_MATH_SUBTRACT)) {
+
+ bNode *absNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH);
+ absNode->custom1 = NODE_VECTOR_MATH_ABSOLUTE;
+ absNode->locx = node->locx + node->width + 20.0f;
+ absNode->locy = node->locy;
+
+ bNode *dotNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH);
+ dotNode->custom1 = NODE_VECTOR_MATH_DOT_PRODUCT;
+ dotNode->locx = absNode->locx + absNode->width + 20.0f;
+ dotNode->locy = absNode->locy;
+ bNodeSocket *sockDotB = BLI_findlink(&dotNode->inputs, 1);
+ bNodeSocket *sockDotOutValue = nodeFindSocket(dotNode, SOCK_OUT, "Value");
+ copy_v3_fl(cycles_node_socket_vector_value(sockDotB), 1 / 3.0f);
+
+ LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) {
+ if (link->fromsock == sockOutValue) {
+ nodeAddLink(ntree, dotNode, sockDotOutValue, link->tonode, link->tosock);
+ nodeRemLink(ntree, link);
+ }
+ }
+
+ bNodeSocket *sockAbsA = BLI_findlink(&absNode->inputs, 0);
+ bNodeSocket *sockDotA = BLI_findlink(&dotNode->inputs, 0);
+ bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector");
+ bNodeSocket *sockAbsOutVector = nodeFindSocket(absNode, SOCK_OUT, "Vector");
+
+ nodeAddLink(ntree, node, sockOutVector, absNode, sockAbsA);
+ nodeAddLink(ntree, absNode, sockAbsOutVector, dotNode, sockDotA);
+
+ need_update = true;
+ }
+ }
+ }
+
+ if (need_update) {
+ ntreeUpdateTree(NULL, ntree);
+ }
+}
+
+/* The Vector output of the Vector Math node is no longer available in the Dot
+ * Product operator. Previously, this Vector was always zero initialized. To
+ * correct this, we zero out any socket the Vector Output was connected to.
+ */
+static void update_vector_math_node_dot_product_operator(bNodeTree *ntree)
+{
+ bool need_update = false;
+
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_VECTOR_MATH) {
+ bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector");
+ if (socket_is_used(sockOutVector) && node->custom1 == NODE_VECTOR_MATH_DOT_PRODUCT) {
+ LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
+ if (link->fromsock == sockOutVector) {
+ switch (link->tosock->type) {
+ case SOCK_FLOAT:
+ *cycles_node_socket_float_value(link->tosock) = 0.0f;
+ break;
+ case SOCK_VECTOR:
+ copy_v3_fl(cycles_node_socket_vector_value(link->tosock), 0.0f);
+ break;
+ case SOCK_RGBA:
+ copy_v4_fl(cycles_node_socket_rgba_value(link->tosock), 0.0f);
+ break;
+ }
+ nodeRemLink(ntree, link);
+ }
+ }
+ need_update = true;
+ }
+ }
+ }
+
+ if (need_update) {
+ ntreeUpdateTree(NULL, ntree);
+ }
+}
+
+/* Previously, the Vector output of the cross product operator was normalized.
+ * To correct this, a Normalize node is added to normalize the output if used.
+ * Moreover, the Value output was removed. This Value was equal to the length
+ * of the cross product. To correct this, a Length node is added if needed.
+ */
+static void update_vector_math_node_cross_product_operator(bNodeTree *ntree)
+{
+ bool need_update = false;
+
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_VECTOR_MATH) {
+ if (node->custom1 == NODE_VECTOR_MATH_CROSS_PRODUCT) {
+ bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector");
+ if (socket_is_used(sockOutVector)) {
+ bNode *normalizeNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH);
+ normalizeNode->custom1 = NODE_VECTOR_MATH_NORMALIZE;
+ normalizeNode->locx = node->locx + node->width + 20.0f;
+ normalizeNode->locy = node->locy;
+ bNodeSocket *sockNormalizeOut = nodeFindSocket(normalizeNode, SOCK_OUT, "Vector");
+
+ LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) {
+ if (link->fromsock == sockOutVector) {
+ nodeAddLink(ntree, normalizeNode, sockNormalizeOut, link->tonode, link->tosock);
+ nodeRemLink(ntree, link);
+ }
+ }
+ bNodeSocket *sockNormalizeA = BLI_findlink(&normalizeNode->inputs, 0);
+ nodeAddLink(ntree, node, sockOutVector, normalizeNode, sockNormalizeA);
+
+ need_update = true;
+ }
+
+ bNodeSocket *sockOutValue = nodeFindSocket(node, SOCK_OUT, "Value");
+ if (socket_is_used(sockOutValue)) {
+ bNode *lengthNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH);
+ lengthNode->custom1 = NODE_VECTOR_MATH_LENGTH;
+ lengthNode->locx = node->locx + node->width + 20.0f;
+ if (socket_is_used(sockOutVector)) {
+ lengthNode->locy = node->locy - lengthNode->height - 20.0f;
+ }
+ else {
+ lengthNode->locy = node->locy;
+ }
+ bNodeSocket *sockLengthOut = nodeFindSocket(lengthNode, SOCK_OUT, "Value");
+
+ LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) {
+ if (link->fromsock == sockOutValue) {
+ nodeAddLink(ntree, lengthNode, sockLengthOut, link->tonode, link->tosock);
+ nodeRemLink(ntree, link);
+ }
+ }
+ bNodeSocket *sockLengthA = BLI_findlink(&lengthNode->inputs, 0);
+ nodeAddLink(ntree, node, sockOutVector, lengthNode, sockLengthA);
+
+ need_update = true;
+ }
+ }
+ }
+ }
+
+ if (need_update) {
+ ntreeUpdateTree(NULL, ntree);
+ }
+}
+
+/* The Value output of the Vector Math node is no longer available in the
+ * Normalize operator. This Value output was equal to the length of the
+ * the input vector A. To correct this, we either add a Length node or
+ * convert the Normalize node into a Length node, depending on if the
+ * Vector output is needed.
+ */
+static void update_vector_math_node_normalize_operator(bNodeTree *ntree)
+{
+ bool need_update = false;
+
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_VECTOR_MATH) {
+ bNodeSocket *sockOutValue = nodeFindSocket(node, SOCK_OUT, "Value");
+ if (node->custom1 == NODE_VECTOR_MATH_NORMALIZE && socket_is_used(sockOutValue)) {
+ bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector");
+ if (socket_is_used(sockOutVector)) {
+ bNode *lengthNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH);
+ lengthNode->custom1 = NODE_VECTOR_MATH_LENGTH;
+ lengthNode->locx = node->locx + node->width + 20.0f;
+ lengthNode->locy = node->locy;
+ bNodeSocket *sockLengthValue = nodeFindSocket(lengthNode, SOCK_OUT, "Value");
+
+ LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) {
+ if (link->fromsock == sockOutValue) {
+ nodeAddLink(ntree, lengthNode, sockLengthValue, link->tonode, link->tosock);
+ nodeRemLink(ntree, link);
+ }
+ }
+ bNodeSocket *sockA = BLI_findlink(&node->inputs, 0);
+ bNodeSocket *sockLengthA = BLI_findlink(&lengthNode->inputs, 0);
+ if (sockA->link) {
+ bNodeLink *link = sockA->link;
+ nodeAddLink(ntree, link->fromnode, link->fromsock, lengthNode, sockLengthA);
+ }
+ else {
+ copy_v3_v3(cycles_node_socket_vector_value(sockLengthA),
+ cycles_node_socket_vector_value(sockA));
+ }
+
+ need_update = true;
+ }
+ else {
+ node->custom1 = NODE_VECTOR_MATH_LENGTH;
+ }
+ }
+ }
+ }
+ if (need_update) {
+ ntreeUpdateTree(NULL, ntree);
+ }
+}
+
+/* The Vector Math operator types didn't have an enum, but rather, their
+ * values were hard coded into the code. After the enum was created and
+ * after more vector operators were added, the hard coded values needs
+ * to be remapped to their correct enum values. To fix this, we remap
+ * the values according to the following rules:
+ *
+ * Dot Product Operator : 3 -> 7
+ * Normalize Operator : 5 -> 11
+ *
+ * Additionally, since the Average operator was removed, it is assigned
+ * a value of -1 just to be identified later in the versioning code:
+ *
+ * Average Operator : 2 -> -1
+ *
+ */
+static void update_vector_math_node_operators_enum_mapping(bNodeTree *ntree)
+{
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_VECTOR_MATH) {
+ switch (node->custom1) {
+ case 2:
+ node->custom1 = -1;
+ break;
+ case 3:
+ node->custom1 = 7;
+ break;
+ case 5:
+ node->custom1 = 11;
+ break;
+ }
+ }
+ }
+}
+
+/* The Average operator is no longer available in the Vector Math node.
+ * The Vector output was equal to the normalized sum of input vectors while
+ * the Value output was equal to the length of the sum of input vectors.
+ * To correct this, we convert the node into an Add node and add a length
+ * node or a normalize node if needed.
+ */
+static void update_vector_math_node_average_operator(bNodeTree *ntree)
+{
+ bool need_update = false;
+
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_VECTOR_MATH) {
+ /* See update_vector_math_node_operators_enum_mapping. */
+ if (node->custom1 == -1) {
+ node->custom1 = NODE_VECTOR_MATH_ADD;
+ bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector");
+ if (socket_is_used(sockOutVector)) {
+ bNode *normalizeNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH);
+ normalizeNode->custom1 = NODE_VECTOR_MATH_NORMALIZE;
+ normalizeNode->locx = node->locx + node->width + 20.0f;
+ normalizeNode->locy = node->locy;
+ bNodeSocket *sockNormalizeOut = nodeFindSocket(normalizeNode, SOCK_OUT, "Vector");
+
+ LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) {
+ if (link->fromsock == sockOutVector) {
+ nodeAddLink(ntree, normalizeNode, sockNormalizeOut, link->tonode, link->tosock);
+ nodeRemLink(ntree, link);
+ }
+ }
+ bNodeSocket *sockNormalizeA = BLI_findlink(&normalizeNode->inputs, 0);
+ nodeAddLink(ntree, node, sockOutVector, normalizeNode, sockNormalizeA);
+
+ need_update = true;
+ }
+
+ bNodeSocket *sockOutValue = nodeFindSocket(node, SOCK_OUT, "Value");
+ if (socket_is_used(sockOutValue)) {
+ bNode *lengthNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH);
+ lengthNode->custom1 = NODE_VECTOR_MATH_LENGTH;
+ lengthNode->locx = node->locx + node->width + 20.0f;
+ if (socket_is_used(sockOutVector)) {
+ lengthNode->locy = node->locy - lengthNode->height - 20.0f;
+ }
+ else {
+ lengthNode->locy = node->locy;
+ }
+ bNodeSocket *sockLengthOut = nodeFindSocket(lengthNode, SOCK_OUT, "Value");
+
+ LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) {
+ if (link->fromsock == sockOutValue) {
+ nodeAddLink(ntree, lengthNode, sockLengthOut, link->tonode, link->tosock);
+ nodeRemLink(ntree, link);
+ }
+ }
+ bNodeSocket *sockLengthA = BLI_findlink(&lengthNode->inputs, 0);
+ nodeAddLink(ntree, node, sockOutVector, lengthNode, sockLengthA);
+
+ 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. */
@@ -458,6 +788,15 @@ void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bm
}
}
}
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 281, 3)) {
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ update_vector_math_node_operators_enum_mapping(ntree);
+ }
+ }
+ FOREACH_NODETREE_END;
+ }
}
void do_versions_after_linking_cycles(Main *bmain)
@@ -576,4 +915,17 @@ void do_versions_after_linking_cycles(Main *bmain)
}
FOREACH_NODETREE_END;
}
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 281, 3)) {
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ update_vector_math_node_add_and_subtract_operators(ntree);
+ update_vector_math_node_dot_product_operator(ntree);
+ update_vector_math_node_cross_product_operator(ntree);
+ update_vector_math_node_normalize_operator(ntree);
+ update_vector_math_node_average_operator(ntree);
+ }
+ }
+ FOREACH_NODETREE_END;
+ }
}
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index c3ecc34aaf4..4201fe7c289 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -1220,7 +1220,7 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_MATH:
ntype->draw_buttons = node_buts_math;
break;
- case SH_NODE_VECT_MATH:
+ case SH_NODE_VECTOR_MATH:
ntype->draw_buttons = node_shader_buts_vect_math;
break;
case SH_NODE_VECT_TRANSFORM:
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 1529279ca03..1817efd35d2 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -400,46 +400,118 @@ void map_range(
}
}
-void vec_math_add(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
+vec3 safe_divide(vec3 a, vec3 b) {
+ return vec3((b.x != 0.0) ? a.x / b.x : 0.0,
+ (b.y != 0.0) ? a.y / b.y : 0.0,
+ (b.z != 0.0) ? a.z / b.z : 0.0);
+}
+
+void vector_math_add(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = a + b;
+}
+
+void vector_math_subtract(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = a - b;
+}
+
+void vector_math_multiply(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = a * b;
+}
+
+void vector_math_divide(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = safe_divide(a, b);
+}
+
+void vector_math_cross(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = cross(a, b);
+}
+
+void vector_math_project(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ float lenSquared = dot(b, b);
+ outVector = (lenSquared != 0.0) ? (dot(a, b) / lenSquared) * b : vec3(0.0);
+}
+
+void vector_math_reflect(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = reflect(a, normalize(b));
+}
+
+void vector_math_dot(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
{
- outvec = v1 + v2;
- outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2])) * 0.333333;
+ outValue = dot(a, b);
}
-void vec_math_sub(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
+void vector_math_distance(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
{
- outvec = v1 - v2;
- outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2])) * 0.333333;
+ outValue = distance(a, b);
}
-void vec_math_average(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
+void vector_math_length(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
{
- outvec = v1 + v2;
- outval = length(outvec);
- outvec = normalize(outvec);
+ outValue = length(a);
}
-void vec_math_mix(float strength, vec3 v1, vec3 v2, out vec3 outvec)
+
+void vector_math_scale(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = a * scale;
+}
+
+void vector_math_normalize(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = normalize(a);
+}
+
+void vector_math_snap(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = floor(safe_divide(a, b)) * b;
+}
+
+void vector_math_floor(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = floor(a);
+}
+
+void vector_math_ceil(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = ceil(a);
+}
+
+void vector_math_modulo(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ math_modulo(a.x, b.x, outVector.x);
+ math_modulo(a.y, b.y, outVector.y);
+ math_modulo(a.z, b.z, outVector.z);
+}
+
+void vector_math_fraction(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = fract(a);
+}
+
+void vector_math_absolute(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
{
- outvec = strength * v1 + (1 - strength) * v2;
+ outVector = abs(a);
}
-void vec_math_dot(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
+void vector_math_minimum(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
{
- outvec = vec3(0);
- outval = dot(v1, v2);
+ outVector = min(a, b);
}
-void vec_math_cross(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
+void vector_math_maximum(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
{
- outvec = cross(v1, v2);
- outval = length(outvec);
- outvec /= outval;
+ outVector = max(a, b);
}
-void vec_math_normalize(vec3 v, out vec3 outvec, out float outval)
+void vector_math_mix(float strength, vec3 a, vec3 b, out vec3 outVector)
{
- outval = length(v);
- outvec = normalize(v);
+ outVector = strength * a + (1 - strength) * b;
}
void vec_math_negate(vec3 v, out vec3 outv)
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 81b93ce6541..385a5bd4428 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -1195,6 +1195,33 @@ enum {
NODE_MATH_SQRT = 23,
};
+/* Vector Math node operations. */
+enum {
+ NODE_VECTOR_MATH_ADD = 0,
+ NODE_VECTOR_MATH_SUBTRACT = 1,
+ NODE_VECTOR_MATH_MULTIPLY = 2,
+ NODE_VECTOR_MATH_DIVIDE = 3,
+
+ NODE_VECTOR_MATH_CROSS_PRODUCT = 4,
+ NODE_VECTOR_MATH_PROJECT = 5,
+ NODE_VECTOR_MATH_REFLECT = 6,
+ NODE_VECTOR_MATH_DOT_PRODUCT = 7,
+
+ NODE_VECTOR_MATH_DISTANCE = 8,
+ NODE_VECTOR_MATH_LENGTH = 9,
+ NODE_VECTOR_MATH_SCALE = 10,
+ NODE_VECTOR_MATH_NORMALIZE = 11,
+
+ NODE_VECTOR_MATH_SNAP = 12,
+ NODE_VECTOR_MATH_FLOOR = 13,
+ NODE_VECTOR_MATH_CEIL = 14,
+ NODE_VECTOR_MATH_MODULO = 15,
+ NODE_VECTOR_MATH_FRACTION = 16,
+ NODE_VECTOR_MATH_ABSOLUTE = 17,
+ NODE_VECTOR_MATH_MINIMUM = 18,
+ NODE_VECTOR_MATH_MAXIMUM = 19,
+};
+
/* mix rgb node flags */
#define SHD_MIXRGB_USE_ALPHA 1
#define SHD_MIXRGB_CLAMP 2
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 020f4296ddd..f377ae9a84f 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -136,12 +136,37 @@ const EnumPropertyItem rna_enum_node_math_items[] = {
};
const EnumPropertyItem rna_enum_node_vec_math_items[] = {
- {0, "ADD", 0, "Add", ""},
- {1, "SUBTRACT", 0, "Subtract", ""},
- {2, "AVERAGE", 0, "Average", ""},
- {3, "DOT_PRODUCT", 0, "Dot Product", ""},
- {4, "CROSS_PRODUCT", 0, "Cross Product", ""},
- {5, "NORMALIZE", 0, "Normalize", ""},
+ {NODE_VECTOR_MATH_ADD, "ADD", 0, "Add", "A + B"},
+ {NODE_VECTOR_MATH_SUBTRACT, "SUBTRACT", 0, "Subtract", "A - B"},
+ {NODE_VECTOR_MATH_MULTIPLY, "MULTIPLY", 0, "Multiply", "Entrywise multiply"},
+ {NODE_VECTOR_MATH_DIVIDE, "DIVIDE", 0, "Divide", "Entrywise divide"},
+ {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"},
+ {NODE_VECTOR_MATH_REFLECT,
+ "REFLECT",
+ 0,
+ "Reflect",
+ "Reflect A around the normal B. B needn't be normalized"},
+ {NODE_VECTOR_MATH_DOT_PRODUCT, "DOT_PRODUCT", 0, "Dot Product", "A dot B"},
+ {0, "", ICON_NONE, NULL, NULL},
+ {NODE_VECTOR_MATH_DISTANCE, "DISTANCE", 0, "Distance", "Distance between A and B"},
+ {NODE_VECTOR_MATH_LENGTH, "LENGTH", 0, "Length", "Length of A"},
+ {NODE_VECTOR_MATH_SCALE, "SCALE", 0, "Scale", "A multiplied by Scale"},
+ {NODE_VECTOR_MATH_NORMALIZE, "NORMALIZE", 0, "Normalize", "Normalize A"},
+ {0, "", ICON_NONE, NULL, NULL},
+ {NODE_VECTOR_MATH_SNAP,
+ "SNAP",
+ 0,
+ "Snap",
+ "Round A to the largest integer multiple of B less than or equal A"},
+ {NODE_VECTOR_MATH_FLOOR, "FLOOR", 0, "Floor", "Entrywise floor"},
+ {NODE_VECTOR_MATH_CEIL, "CEIL", 0, "Ceil", "Entrywise ceil"},
+ {NODE_VECTOR_MATH_MODULO, "MODULO", 0, "Modulo", "Entrywise modulo"},
+ {NODE_VECTOR_MATH_FRACTION, "FRACTION", 0, "Fraction", "The fraction part of A entrywise"},
+ {NODE_VECTOR_MATH_ABSOLUTE, "ABSOLUTE", 0, "Absolute", "Entrywise absolute"},
+ {NODE_VECTOR_MATH_MINIMUM, "MINIMUM", 0, "Minimum", "Entrywise minimum"},
+ {NODE_VECTOR_MATH_MAXIMUM, "MAXIMUM", 0, "Maximum", "Entrywise maximum"},
{0, NULL, 0, NULL, NULL},
};
@@ -3873,7 +3898,7 @@ static void def_vector_math(StructRNA *srna)
RNA_def_property_enum_sdna(prop, NULL, "custom1");
RNA_def_property_enum_items(prop, rna_enum_node_vec_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");
}
static void def_rgb_curve(StructRNA *srna)
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 284eaa8b70b..3c97bdae929 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -204,7 +204,7 @@ set(SRC
shader/nodes/node_shader_uvmap.c
shader/nodes/node_shader_valToRgb.c
shader/nodes/node_shader_value.c
- shader/nodes/node_shader_vectMath.c
+ shader/nodes/node_shader_vector_math.c
shader/nodes/node_shader_vectTransform.c
shader/nodes/node_shader_vector_displacement.c
shader/nodes/node_shader_volume_absorption.c
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index c72e97642a2..c08911c1db8 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -53,7 +53,7 @@ DefNode(ShaderNode, SH_NODE_CAMERA, 0, "CAMERA
DefNode(ShaderNode, SH_NODE_MAP_RANGE, def_map_range, "MAP_RANGE", MapRange, "Map Range", "" )
DefNode(ShaderNode, SH_NODE_CLAMP, 0, "CLAMP", Clamp, "Clamp", "" )
DefNode(ShaderNode, SH_NODE_MATH, def_math, "MATH", Math, "Math", "" )
-DefNode(ShaderNode, SH_NODE_VECT_MATH, def_vector_math, "VECT_MATH", VectorMath, "Vector Math", "" )
+DefNode(ShaderNode, SH_NODE_VECTOR_MATH, def_vector_math, "VECT_MATH", VectorMath, "Vector Math", "" )
DefNode(ShaderNode, SH_NODE_SQUEEZE, 0, "SQUEEZE", Squeeze, "Squeeze Value", "" )
DefNode(ShaderNode, SH_NODE_INVERT, 0, "INVERT", Invert, "Invert", "" )
DefNode(ShaderNode, SH_NODE_SEPRGB, 0, "SEPRGB", SeparateRGB, "Separate RGB", "" )
diff --git a/source/blender/nodes/intern/node_util.c b/source/blender/nodes/intern/node_util.c
index e9a825b5b3f..0d7f19fb67a 100644
--- a/source/blender/nodes/intern/node_util.c
+++ b/source/blender/nodes/intern/node_util.c
@@ -100,7 +100,7 @@ void node_math_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int max
BLI_strncpy(label, IFACE_(name), maxlen);
}
-void node_vect_math_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int maxlen)
+void node_vector_math_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int maxlen)
{
const char *name;
RNA_enum_name(rna_enum_node_vec_math_items, node->custom1, &name);
diff --git a/source/blender/nodes/intern/node_util.h b/source/blender/nodes/intern/node_util.h
index 7eef70db498..49117b38aba 100644
--- a/source/blender/nodes/intern/node_util.h
+++ b/source/blender/nodes/intern/node_util.h
@@ -71,7 +71,7 @@ extern void *node_initexec_curves(struct bNodeExecContext *context,
void node_blend_label(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen);
void node_image_label(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen);
void node_math_label(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen);
-void node_vect_math_label(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen);
+void node_vector_math_label(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen);
void node_filter_label(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen);
/*** Link Handling */
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index 4891fb323ad..60a6cc91630 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -799,7 +799,7 @@ static void ntree_shader_relink_displacement(bNodeTree *ntree, bNode *output_nod
nodeRemLink(ntree, displacement_link);
/* Convert displacement vector to bump height. */
- bNode *dot_node = nodeAddStaticNode(NULL, ntree, SH_NODE_VECT_MATH);
+ bNode *dot_node = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH);
bNode *geo_node = nodeAddStaticNode(NULL, ntree, SH_NODE_NEW_GEOMETRY);
bNodeSocket *normal_socket = ntree_shader_node_find_output(geo_node, "Normal");
dot_node->custom1 = 3; /* dot product */
diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.c b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
index 3d034372300..712c64084cc 100644
--- a/source/blender/nodes/shader/nodes/node_shader_normal_map.c
+++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
@@ -114,7 +114,7 @@ static int gpu_shader_normal_map(GPUMaterial *mat,
break;
}
- GPU_link(mat, "vec_math_mix", strength, realnorm, negnorm, &out[0].link);
+ GPU_link(mat, "vector_math_mix", strength, realnorm, negnorm, &out[0].link);
GPU_link(mat, "vect_normalize", out[0].link, &out[0].link);
return true;
diff --git a/source/blender/nodes/shader/nodes/node_shader_vectMath.c b/source/blender/nodes/shader/nodes/node_shader_vectMath.c
deleted file mode 100644
index 41273a6dc1d..00000000000
--- a/source/blender/nodes/shader/nodes/node_shader_vectMath.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2005 Blender Foundation.
- * All rights reserved.
- */
-
-/** \file
- * \ingroup shdnodes
- */
-
-#include "node_shader_util.h"
-
-/* **************** VECTOR MATH ******************** */
-static bNodeSocketTemplate sh_node_vect_math_in[] = {
- {SOCK_VECTOR, 1, N_("Vector"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE},
- {SOCK_VECTOR, 1, N_("Vector"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE},
- {-1, 0, ""}};
-
-static bNodeSocketTemplate sh_node_vect_math_out[] = {
- {SOCK_VECTOR, 0, N_("Vector")}, {SOCK_FLOAT, 0, N_("Value")}, {-1, 0, ""}};
-
-static void node_shader_exec_vect_math(void *UNUSED(data),
- int UNUSED(thread),
- bNode *node,
- bNodeExecData *UNUSED(execdata),
- bNodeStack **in,
- bNodeStack **out)
-{
- float vec1[3], vec2[3];
-
- nodestack_get_vec(vec1, SOCK_VECTOR, in[0]);
- nodestack_get_vec(vec2, SOCK_VECTOR, in[1]);
-
- if (node->custom1 == 0) { /* Add */
- out[0]->vec[0] = vec1[0] + vec2[0];
- out[0]->vec[1] = vec1[1] + vec2[1];
- out[0]->vec[2] = vec1[2] + vec2[2];
-
- out[1]->vec[0] = (fabsf(out[0]->vec[0]) + fabsf(out[0]->vec[1]) + fabsf(out[0]->vec[2])) /
- 3.0f;
- }
- else if (node->custom1 == 1) { /* Subtract */
- out[0]->vec[0] = vec1[0] - vec2[0];
- out[0]->vec[1] = vec1[1] - vec2[1];
- out[0]->vec[2] = vec1[2] - vec2[2];
-
- out[1]->vec[0] = (fabsf(out[0]->vec[0]) + fabsf(out[0]->vec[1]) + fabsf(out[0]->vec[2])) /
- 3.0f;
- }
- else if (node->custom1 == 2) { /* Average */
- out[0]->vec[0] = vec1[0] + vec2[0];
- out[0]->vec[1] = vec1[1] + vec2[1];
- out[0]->vec[2] = vec1[2] + vec2[2];
-
- out[1]->vec[0] = normalize_v3(out[0]->vec);
- }
- else if (node->custom1 == 3) { /* Dot product */
- out[1]->vec[0] = (vec1[0] * vec2[0]) + (vec1[1] * vec2[1]) + (vec1[2] * vec2[2]);
- }
- else if (node->custom1 == 4) { /* Cross product */
- out[0]->vec[0] = (vec1[1] * vec2[2]) - (vec1[2] * vec2[1]);
- out[0]->vec[1] = (vec1[2] * vec2[0]) - (vec1[0] * vec2[2]);
- out[0]->vec[2] = (vec1[0] * vec2[1]) - (vec1[1] * vec2[0]);
-
- out[1]->vec[0] = normalize_v3(out[0]->vec);
- }
- else if (node->custom1 == 5) { /* Normalize */
- /* This one only takes one input, so we've got to choose. */
- if (in[0]->hasinput || !in[1]->hasinput) {
- out[0]->vec[0] = vec1[0];
- out[0]->vec[1] = vec1[1];
- out[0]->vec[2] = vec1[2];
- }
- else {
- out[0]->vec[0] = vec2[0];
- out[0]->vec[1] = vec2[1];
- out[0]->vec[2] = vec2[2];
- }
-
- out[1]->vec[0] = normalize_v3(out[0]->vec);
- }
-}
-
-static int gpu_shader_vect_math(GPUMaterial *mat,
- bNode *node,
- bNodeExecData *UNUSED(execdata),
- GPUNodeStack *in,
- GPUNodeStack *out)
-{
- static const char *names[] = {
- "vec_math_add",
- "vec_math_sub",
- "vec_math_average",
- "vec_math_dot",
- "vec_math_cross",
- "vec_math_normalize",
- };
-
- switch (node->custom1) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- GPU_stack_link(mat, node, names[node->custom1], in, out);
- break;
- case 5:
- 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 false;
- }
-
- return true;
-}
-
-void register_node_type_sh_vect_math(void)
-{
- static bNodeType ntype;
-
- sh_node_type_base(&ntype, SH_NODE_VECT_MATH, "Vector Math", NODE_CLASS_CONVERTOR, 0);
- node_type_socket_templates(&ntype, sh_node_vect_math_in, sh_node_vect_math_out);
- node_type_label(&ntype, node_vect_math_label);
- node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL, NULL, node_shader_exec_vect_math);
- node_type_gpu(&ntype, gpu_shader_vect_math);
-
- nodeRegisterType(&ntype);
-}
diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_math.c b/source/blender/nodes/shader/nodes/node_shader_vector_math.c
new file mode 100644
index 00000000000..03de83655b5
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_vector_math.c
@@ -0,0 +1,113 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup shdnodes
+ */
+
+#include "node_shader_util.h"
+
+/* **************** VECTOR MATH ******************** */
+static bNodeSocketTemplate sh_node_vector_math_in[] = {
+ {SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE},
+ {SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE},
+ {SOCK_FLOAT, 1, N_("Scale"), 1.0f, 1.0f, 1.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE},
+ {-1, 0, ""}};
+
+static bNodeSocketTemplate sh_node_vector_math_out[] = {
+ {SOCK_VECTOR, 0, N_("Vector")}, {SOCK_FLOAT, 0, N_("Value")}, {-1, 0, ""}};
+
+static int gpu_shader_vector_math(GPUMaterial *mat,
+ bNode *node,
+ bNodeExecData *UNUSED(execdata),
+ GPUNodeStack *in,
+ GPUNodeStack *out)
+{
+ static const char *names[] = {
+ [NODE_VECTOR_MATH_ADD] = "vector_math_add",
+ [NODE_VECTOR_MATH_SUBTRACT] = "vector_math_subtract",
+ [NODE_VECTOR_MATH_MULTIPLY] = "vector_math_multiply",
+ [NODE_VECTOR_MATH_DIVIDE] = "vector_math_divide",
+
+ [NODE_VECTOR_MATH_CROSS_PRODUCT] = "vector_math_cross",
+ [NODE_VECTOR_MATH_PROJECT] = "vector_math_project",
+ [NODE_VECTOR_MATH_REFLECT] = "vector_math_reflect",
+ [NODE_VECTOR_MATH_DOT_PRODUCT] = "vector_math_dot",
+
+ [NODE_VECTOR_MATH_DISTANCE] = "vector_math_distance",
+ [NODE_VECTOR_MATH_LENGTH] = "vector_math_length",
+ [NODE_VECTOR_MATH_SCALE] = "vector_math_scale",
+ [NODE_VECTOR_MATH_NORMALIZE] = "vector_math_normalize",
+
+ [NODE_VECTOR_MATH_SNAP] = "vector_math_snap",
+ [NODE_VECTOR_MATH_FLOOR] = "vector_math_floor",
+ [NODE_VECTOR_MATH_CEIL] = "vector_math_ceil",
+ [NODE_VECTOR_MATH_MODULO] = "vector_math_modulo",
+ [NODE_VECTOR_MATH_FRACTION] = "vector_math_fraction",
+ [NODE_VECTOR_MATH_ABSOLUTE] = "vector_math_absolute",
+ [NODE_VECTOR_MATH_MINIMUM] = "vector_math_minimum",
+ [NODE_VECTOR_MATH_MAXIMUM] = "vector_math_maximum",
+ };
+
+ GPU_stack_link(mat, node, names[node->custom1], in, out);
+ return true;
+}
+
+static void node_shader_update_vector_math(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ bNodeSocket *sockB = BLI_findlink(&node->inputs, 1);
+ bNodeSocket *sockScale = nodeFindSocket(node, SOCK_IN, "Scale");
+
+ bNodeSocket *sockVector = nodeFindSocket(node, SOCK_OUT, "Vector");
+ bNodeSocket *sockValue = nodeFindSocket(node, SOCK_OUT, "Value");
+
+ nodeSetSocketAvailability(sockB,
+ !ELEM(node->custom1,
+ NODE_VECTOR_MATH_CEIL,
+ NODE_VECTOR_MATH_SCALE,
+ NODE_VECTOR_MATH_FLOOR,
+ NODE_VECTOR_MATH_LENGTH,
+ NODE_VECTOR_MATH_ABSOLUTE,
+ NODE_VECTOR_MATH_FRACTION,
+ NODE_VECTOR_MATH_NORMALIZE));
+ nodeSetSocketAvailability(sockScale, node->custom1 == NODE_VECTOR_MATH_SCALE);
+ nodeSetSocketAvailability(sockVector,
+ !ELEM(node->custom1,
+ NODE_VECTOR_MATH_LENGTH,
+ NODE_VECTOR_MATH_DISTANCE,
+ NODE_VECTOR_MATH_DOT_PRODUCT));
+ nodeSetSocketAvailability(sockValue,
+ ELEM(node->custom1,
+ NODE_VECTOR_MATH_LENGTH,
+ NODE_VECTOR_MATH_DISTANCE,
+ NODE_VECTOR_MATH_DOT_PRODUCT));
+}
+
+void register_node_type_sh_vect_math(void)
+{
+ static bNodeType ntype;
+
+ sh_node_type_base(&ntype, SH_NODE_VECTOR_MATH, "Vector Math", NODE_CLASS_CONVERTOR, 0);
+ node_type_socket_templates(&ntype, sh_node_vector_math_in, sh_node_vector_math_out);
+ node_type_label(&ntype, node_vector_math_label);
+ node_type_gpu(&ntype, gpu_shader_vector_math);
+ node_type_update(&ntype, node_shader_update_vector_math);
+
+ nodeRegisterType(&ntype);
+}