diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 6709e90c3d3..732c4b0da96 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -327,6 +327,7 @@ static ShaderNode *add_node(Scene *scene, BL::ShaderNodeVectorRotate b_vector_rotate_node(b_node); VectorRotateNode *vector_rotate_node = new VectorRotateNode(); vector_rotate_node->type = (NodeVectorRotateType)b_vector_rotate_node.rotation_type(); + vector_rotate_node->invert = b_vector_rotate_node.invert(); node = vector_rotate_node; } else if (b_node.is_a(&RNA_ShaderNodeVectorTransform)) { diff --git a/intern/cycles/kernel/shaders/node_vector_rotate.osl b/intern/cycles/kernel/shaders/node_vector_rotate.osl index 533aa7bbe13..d32733b0966 100644 --- a/intern/cycles/kernel/shaders/node_vector_rotate.osl +++ b/intern/cycles/kernel/shaders/node_vector_rotate.osl @@ -17,7 +17,8 @@ #include "stdcycles.h" #include "node_math.h" -shader node_vector_rotate(string type = "axis", +shader node_vector_rotate(int invert = 0, + string type = "axis", vector VectorIn = vector(0.0, 0.0, 0.0), point Center = point(0.0, 0.0, 0.0), point Rotation = point(0.0, 0.0, 0.0), @@ -26,20 +27,23 @@ shader node_vector_rotate(string type = "axis", output vector VectorOut = vector(0.0, 0.0, 0.0)) { if (type == "euler_xyz") { - VectorOut = transform(euler_to_mat(Rotation), VectorIn - Center) + Center; + matrix rmat = (invert) ? transpose(euler_to_mat(Rotation)) : euler_to_mat(Rotation); + VectorOut = transform(rmat, VectorIn - Center) + Center; } - else if (type == "x_axis") { - VectorOut = rotate(VectorIn - Center, Angle, point(0.0), vector(1.0, 0.0, 0.0)) + Center; - } - else if (type == "y_axis") { - VectorOut = rotate(VectorIn - Center, Angle, point(0.0), vector(0.0, 1.0, 0.0)) + Center; - } - else if (type == "z_axis") { - VectorOut = rotate(VectorIn - Center, Angle, point(0.0), vector(0.0, 0.0, 1.0)) + Center; - } - else { // axis - VectorOut = (length(Axis) != 0.0) ? - rotate(VectorIn - Center, Angle, point(0.0), Axis) + Center : - VectorIn; + else { + float a = (invert) ? -Angle : Angle; + if (type == "x_axis") { + VectorOut = rotate(VectorIn - Center, a, point(0.0), vector(1.0, 0.0, 0.0)) + Center; + } + else if (type == "y_axis") { + VectorOut = rotate(VectorIn - Center, a, point(0.0), vector(0.0, 1.0, 0.0)) + Center; + } + else if (type == "z_axis") { + VectorOut = rotate(VectorIn - Center, a, point(0.0), vector(0.0, 0.0, 1.0)) + Center; + } + else { // axis + VectorOut = (length(Axis) != 0.0) ? rotate(VectorIn - Center, a, point(0.0), Axis) + Center : + VectorIn; + } } } diff --git a/intern/cycles/kernel/svm/svm_vector_rotate.h b/intern/cycles/kernel/svm/svm_vector_rotate.h index 0dc0e223f41..79a4ec2c40e 100644 --- a/intern/cycles/kernel/svm/svm_vector_rotate.h +++ b/intern/cycles/kernel/svm/svm_vector_rotate.h @@ -25,45 +25,52 @@ ccl_device void svm_node_vector_rotate(ShaderData *sd, uint result_stack_offset) { uint type, vector_stack_offset, rotation_stack_offset, center_stack_offset, axis_stack_offset, - angle_stack_offset; + angle_stack_offset, invert; - svm_unpack_node_uchar3(input_stack_offsets, &type, &vector_stack_offset, &rotation_stack_offset); + svm_unpack_node_uchar4( + input_stack_offsets, &type, &vector_stack_offset, &rotation_stack_offset, &invert); svm_unpack_node_uchar3( axis_stack_offsets, ¢er_stack_offset, &axis_stack_offset, &angle_stack_offset); - float3 vector = stack_load_float3(stack, vector_stack_offset); - float3 center = stack_load_float3(stack, center_stack_offset); - float3 result = make_float3(0.0f, 0.0f, 0.0f); - - if (type == NODE_VECTOR_ROTATE_TYPE_EULER_XYZ) { - float3 rotation = stack_load_float3(stack, rotation_stack_offset); // Default XYZ. - Transform rotationTransform = euler_to_transform(rotation); - result = transform_direction(&rotationTransform, vector - center) + center; - } - else { - float3 axis; - switch (type) { - case NODE_VECTOR_ROTATE_TYPE_AXIS_X: - axis = make_float3(1.0f, 0.0f, 0.0f); - break; - case NODE_VECTOR_ROTATE_TYPE_AXIS_Y: - axis = make_float3(0.0f, 1.0f, 0.0f); - break; - case NODE_VECTOR_ROTATE_TYPE_AXIS_Z: - axis = make_float3(0.0f, 0.0f, 1.0f); - break; - default: - axis = normalize(stack_load_float3(stack, axis_stack_offset)); - break; - } - float angle = stack_load_float(stack, angle_stack_offset); - result = (len_squared(axis) != 0.0f) ? - rotate_around_axis(vector - center, axis, angle) + center : - vector; - } - - /* Output */ if (stack_valid(result_stack_offset)) { + + float3 vector = stack_load_float3(stack, vector_stack_offset); + float3 center = stack_load_float3(stack, center_stack_offset); + float3 result = make_float3(0.0f, 0.0f, 0.0f); + + if (type == NODE_VECTOR_ROTATE_TYPE_EULER_XYZ) { + float3 rotation = stack_load_float3(stack, rotation_stack_offset); // Default XYZ. + Transform rotationTransform = euler_to_transform(rotation); + if (invert) { + result = transform_direction_transposed(&rotationTransform, vector - center) + center; + } + else { + result = transform_direction(&rotationTransform, vector - center) + center; + } + } + else { + float3 axis; + switch (type) { + case NODE_VECTOR_ROTATE_TYPE_AXIS_X: + axis = make_float3(1.0f, 0.0f, 0.0f); + break; + case NODE_VECTOR_ROTATE_TYPE_AXIS_Y: + axis = make_float3(0.0f, 1.0f, 0.0f); + break; + case NODE_VECTOR_ROTATE_TYPE_AXIS_Z: + axis = make_float3(0.0f, 0.0f, 1.0f); + break; + default: + axis = normalize(stack_load_float3(stack, axis_stack_offset)); + break; + } + float angle = stack_load_float(stack, angle_stack_offset); + angle = invert ? -angle : angle; + result = (len_squared(axis) != 0.0f) ? + rotate_around_axis(vector - center, axis, angle) + center : + vector; + } + stack_store_float3(stack, result_stack_offset, result); } } diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 4ff03d28330..a52b7f0ea00 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -6157,6 +6157,8 @@ NODE_DEFINE(VectorRotateNode) type_enum.insert("euler_xyz", NODE_VECTOR_ROTATE_TYPE_EULER_XYZ); SOCKET_ENUM(type, "Type", type_enum, NODE_VECTOR_ROTATE_TYPE_AXIS); + SOCKET_BOOLEAN(invert, "Invert", false); + SOCKET_IN_VECTOR(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f)); SOCKET_IN_POINT(rotation, "Rotation", make_float3(0.0f, 0.0f, 0.0f)); SOCKET_IN_POINT(center, "Center", make_float3(0.0f, 0.0f, 0.0f)); @@ -6180,19 +6182,20 @@ void VectorRotateNode::compile(SVMCompiler &compiler) ShaderInput *angle_in = input("Angle"); ShaderOutput *vector_out = output("Vector"); - compiler.add_node(NODE_VECTOR_ROTATE, - compiler.encode_uchar4(type, - compiler.stack_assign(vector_in), - compiler.stack_assign(rotation_in)), - compiler.encode_uchar4(compiler.stack_assign(center_in), - compiler.stack_assign(axis_in), - compiler.stack_assign(angle_in)), - compiler.stack_assign(vector_out)); + compiler.add_node( + NODE_VECTOR_ROTATE, + compiler.encode_uchar4( + type, compiler.stack_assign(vector_in), compiler.stack_assign(rotation_in), invert), + compiler.encode_uchar4(compiler.stack_assign(center_in), + compiler.stack_assign(axis_in), + compiler.stack_assign(angle_in)), + compiler.stack_assign(vector_out)); } void VectorRotateNode::compile(OSLCompiler &compiler) { compiler.parameter(this, "type"); + compiler.parameter(this, "invert"); compiler.add(this, "node_vector_rotate"); } diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 38b6b7554c0..1d76cb5e828 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -1400,6 +1400,7 @@ class VectorRotateNode : public ShaderNode { return NODE_GROUP_LEVEL_3; } NodeVectorRotateType type; + bool invert; float3 vector; float3 center; float3 axis; diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 8633ebca8d6..7ba033432c0 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -748,6 +748,7 @@ static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), Poin static void node_shader_buts_vector_rotate(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiItemR(layout, ptr, "rotation_type", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "invert", 0, NULL, 0); } static void node_shader_buts_vect_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_vector_rotate.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_vector_rotate.glsl index 405821e01e3..41ad16cce0b 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_vector_rotate.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_vector_rotate.glsl @@ -20,33 +20,34 @@ vec3 rotate_around_axis(vec3 p, vec3 axis, float angle) } void node_vector_rotate_axis_angle( - vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, out vec3 vec) + vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, float invert, out vec3 vec) { vec = (length(axis) != 0.0) ? - rotate_around_axis(vector_in - center, normalize(axis), angle) + center : + rotate_around_axis(vector_in - center, normalize(axis), angle * invert) + center : vector_in; } void node_vector_rotate_axis_x( - vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, out vec3 vec) + vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, float invert, out vec3 vec) { - vec = rotate_around_axis(vector_in - center, vec3(1.0, 0.0, 0.0), angle) + center; + vec = rotate_around_axis(vector_in - center, vec3(1.0, 0.0, 0.0), angle * invert) + center; } void node_vector_rotate_axis_y( - vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, out vec3 vec) + vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, float invert, out vec3 vec) { - vec = rotate_around_axis(vector_in - center, vec3(0.0, 1.0, 0.0), angle) + center; + vec = rotate_around_axis(vector_in - center, vec3(0.0, 1.0, 0.0), angle * invert) + center; } void node_vector_rotate_axis_z( - vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, out vec3 vec) + vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, float invert, out vec3 vec) { - vec = rotate_around_axis(vector_in - center, vec3(0.0, 0.0, 1.0), angle) + center; + vec = rotate_around_axis(vector_in - center, vec3(0.0, 0.0, 1.0), angle * invert) + center; } void node_vector_rotate_euler_xyz( - vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, out vec3 vec) + vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, float invert, out vec3 vec) { - vec = euler_to_mat3(rotation) * (vector_in - center) + center; + mat3 rmat = (invert < 0.0) ? transpose(euler_to_mat3(rotation)) : euler_to_mat3(rotation); + vec = rmat * (vector_in - center) + center; } diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index a0f7f9b585e..e5445546491 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -4166,6 +4166,11 @@ static void def_sh_vector_rotate(StructRNA *srna) RNA_def_property_enum_items(prop, rna_enum_vector_rotate_type_items); RNA_def_property_ui_text(prop, "Type", "Type of rotation"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update"); + + prop = RNA_def_property(srna, "invert", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "custom2", 0); + RNA_def_property_ui_text(prop, "Invert", "Invert angle"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } static void def_sh_attribute(StructRNA *srna) diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_rotate.c b/source/blender/nodes/shader/nodes/node_shader_vector_rotate.c index bee5377c438..c94cb903bf3 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vector_rotate.c +++ b/source/blender/nodes/shader/nodes/node_shader_vector_rotate.c @@ -51,7 +51,8 @@ static int gpu_shader_vector_rotate(GPUMaterial *mat, }; if (node->custom1 < ARRAY_SIZE(names) && names[node->custom1]) { - return GPU_stack_link(mat, node, names[node->custom1], in, out); + float invert = (node->custom2) ? -1.0 : 1.0; + return GPU_stack_link(mat, node, names[node->custom1], in, out, GPU_constant(&invert)); } else { return 0;