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:
-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);
+}