diff options
24 files changed, 467 insertions, 240 deletions
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index e81336cd692..f5a76002eb6 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -208,24 +208,6 @@ static void get_tex_mapping(TextureMapping *mapping, BL::TexMapping &b_mapping) mapping->z_mapping = (TextureMapping::Mapping)b_mapping.mapping_z(); } -static void get_tex_mapping(TextureMapping *mapping, BL::ShaderNodeMapping &b_mapping) -{ - if (!b_mapping) - return; - - mapping->translation = get_float3(b_mapping.translation()); - mapping->rotation = get_float3(b_mapping.rotation()); - mapping->scale = get_float3(b_mapping.scale()); - mapping->type = (TextureMapping::Type)b_mapping.vector_type(); - - mapping->use_minmax = b_mapping.use_min() || b_mapping.use_max(); - - if (b_mapping.use_min()) - mapping->min = get_float3(b_mapping.min()); - if (b_mapping.use_max()) - mapping->max = get_float3(b_mapping.max()); -} - static ShaderNode *add_node(Scene *scene, BL::RenderEngine &b_engine, BL::BlendData &b_data, @@ -357,9 +339,7 @@ static ShaderNode *add_node(Scene *scene, else if (b_node.is_a(&RNA_ShaderNodeMapping)) { BL::ShaderNodeMapping b_mapping_node(b_node); MappingNode *mapping = new MappingNode(); - - get_tex_mapping(&mapping->tex_mapping, b_mapping_node); - + mapping->type = (NodeMappingType)b_mapping_node.vector_type(); node = mapping; } else if (b_node.is_a(&RNA_ShaderNodeFresnel)) { diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 89ecdc6b7ac..04df49aa058 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -201,6 +201,7 @@ set(SRC_SVM_HEADERS svm/svm_magic.h svm/svm_map_range.h svm/svm_mapping.h + svm/svm_mapping_util.h svm/svm_math.h svm/svm_math_util.h svm/svm_mix.h diff --git a/intern/cycles/kernel/shaders/node_mapping.osl b/intern/cycles/kernel/shaders/node_mapping.osl index f5cc2d1c5dd..8eed0ae9c48 100644 --- a/intern/cycles/kernel/shaders/node_mapping.osl +++ b/intern/cycles/kernel/shaders/node_mapping.osl @@ -16,17 +16,58 @@ #include "stdosl.h" -shader node_mapping(matrix Matrix = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - point mapping_min = point(0.0, 0.0, 0.0), - point mapping_max = point(0.0, 0.0, 0.0), - int use_minmax = 0, - point VectorIn = point(0.0, 0.0, 0.0), - output point VectorOut = point(0.0, 0.0, 0.0)) +point safe_divide(point a, point b) +{ + return point((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); +} + +matrix euler_to_mat(point euler) { - point p = transform(Matrix, VectorIn); + float cx = cos(euler[0]); + float cy = cos(euler[1]); + float cz = cos(euler[2]); + float sx = sin(euler[0]); + float sy = sin(euler[1]); + float sz = sin(euler[2]); + + matrix mat = matrix(1.0); + mat[0][0] = cy * cz; + mat[0][1] = cy * sz; + mat[0][2] = -sy; - if (use_minmax) - p = min(max(mapping_min, p), mapping_max); + mat[1][0] = sy * sx * cz - cx * sz; + mat[1][1] = sy * sx * sz + cx * cz; + mat[1][2] = cy * sx; - VectorOut = p; + mat[2][0] = sy * cx * cz + sx * sz; + mat[2][1] = sy * cx * sz - sx * cz; + mat[2][2] = cy * cx; + return mat; +} + +shader node_mapping(string type = "point", + point VectorIn = point(0.0, 0.0, 0.0), + point Location = point(0.0, 0.0, 0.0), + point Rotation = point(0.0, 0.0, 0.0), + point Scale = point(1.0, 1.0, 1.0), + output point VectorOut = point(0.0, 0.0, 0.0)) +{ + if (type == "point") { + VectorOut = transform(euler_to_mat(Rotation), (VectorIn * Scale)) + Location; + } + else if (type == "texture") { + VectorOut = safe_divide(transform(transpose(euler_to_mat(Rotation)), (VectorIn - Location)), + Scale); + } + else if (type == "vector") { + VectorOut = transform(euler_to_mat(Rotation), (VectorIn * Scale)); + } + else if (type == "normal") { + VectorOut = normalize(transform(euler_to_mat(Rotation), safe_divide(VectorIn, Scale))); + } + else { + warning("%s", "Unknown Mapping vector type!"); + } } diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index 95954aaf99e..ce651a1b5ff 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -162,6 +162,7 @@ CCL_NAMESPACE_END #include "kernel/svm/svm_color_util.h" #include "kernel/svm/svm_math_util.h" +#include "kernel/svm/svm_mapping_util.h" #include "kernel/svm/svm_attribute.h" #include "kernel/svm/svm_gradient.h" @@ -405,8 +406,11 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, #endif /* NODES_GROUP(NODE_GROUP_LEVEL_1) */ #if NODES_GROUP(NODE_GROUP_LEVEL_2) + case NODE_TEXTURE_MAPPING: + svm_node_texture_mapping(kg, sd, stack, node.y, node.z, &offset); + break; case NODE_MAPPING: - svm_node_mapping(kg, sd, stack, node.y, node.z, &offset); + svm_node_mapping(kg, sd, stack, node.y, node.z, node.w, &offset); break; case NODE_MIN_MAX: svm_node_min_max(kg, sd, stack, node.y, node.z, &offset); diff --git a/intern/cycles/kernel/svm/svm_mapping.h b/intern/cycles/kernel/svm/svm_mapping.h index 998a29912d4..6e19c859e19 100644 --- a/intern/cycles/kernel/svm/svm_mapping.h +++ b/intern/cycles/kernel/svm/svm_mapping.h @@ -18,7 +18,33 @@ CCL_NAMESPACE_BEGIN /* Mapping Node */ -ccl_device void svm_node_mapping( +ccl_device void svm_node_mapping(KernelGlobals *kg, + ShaderData *sd, + float *stack, + uint type, + uint inputs_stack_offsets, + uint result_stack_offset, + int *offset) +{ + uint vector_stack_offset, location_stack_offset, rotation_stack_offset, scale_stack_offset; + svm_unpack_node_uchar4(inputs_stack_offsets, + &vector_stack_offset, + &location_stack_offset, + &rotation_stack_offset, + &scale_stack_offset); + + float3 vector = stack_load_float3(stack, vector_stack_offset); + float3 location = stack_load_float3(stack, location_stack_offset); + float3 rotation = stack_load_float3(stack, rotation_stack_offset); + float3 scale = stack_load_float3(stack, scale_stack_offset); + + float3 result = svm_mapping((NodeMappingType)type, vector, location, rotation, scale); + stack_store_float3(stack, result_stack_offset, result); +} + +/* Texture Mapping */ + +ccl_device void svm_node_texture_mapping( KernelGlobals *kg, ShaderData *sd, float *stack, uint vec_offset, uint out_offset, int *offset) { float3 v = stack_load_float3(stack, vec_offset); diff --git a/intern/cycles/kernel/svm/svm_mapping_util.h b/intern/cycles/kernel/svm/svm_mapping_util.h new file mode 100644 index 00000000000..ec2c84e0791 --- /dev/null +++ b/intern/cycles/kernel/svm/svm_mapping_util.h @@ -0,0 +1,39 @@ +/* + * Copyright 2011-2014 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +CCL_NAMESPACE_BEGIN + +ccl_device float3 +svm_mapping(NodeMappingType type, float3 vector, float3 location, float3 rotation, float3 scale) +{ + Transform rotationTransform = euler_to_transform(rotation); + switch (type) { + case NODE_MAPPING_TYPE_POINT: + return transform_direction(&rotationTransform, (vector * scale)) + location; + case NODE_MAPPING_TYPE_TEXTURE: + return safe_divide_float3_float3( + transform_direction_transposed(&rotationTransform, (vector - location)), scale); + case NODE_MAPPING_TYPE_VECTOR: + return transform_direction(&rotationTransform, (vector * scale)); + case NODE_MAPPING_TYPE_NORMAL: + return safe_normalize( + transform_direction(&rotationTransform, safe_divide_float3_float3(vector, scale))); + default: + return make_float3(0.0f, 0.0f, 0.0f); + } +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index a3caa1ab68d..de7114566b3 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -140,6 +140,7 @@ typedef enum ShaderNodeType { NODE_IES, NODE_MAP_RANGE, NODE_CLAMP, + NODE_TEXTURE_MAPPING, NODE_TEX_WHITE_NOISE, } ShaderNodeType; @@ -299,6 +300,13 @@ typedef enum NodeVectorMathType { NODE_VECTOR_MATH_MAXIMUM, } NodeVectorMathType; +typedef enum NodeMappingType { + NODE_MAPPING_TYPE_POINT, + NODE_MAPPING_TYPE_TEXTURE, + NODE_MAPPING_TYPE_VECTOR, + NODE_MAPPING_TYPE_NORMAL +} NodeMappingType; + typedef enum NodeVectorTransformType { NODE_VECTOR_TRANSFORM_TYPE_VECTOR, NODE_VECTOR_TRANSFORM_TYPE_POINT, diff --git a/intern/cycles/render/constant_fold.cpp b/intern/cycles/render/constant_fold.cpp index 851d4b71df8..f3809ee8d80 100644 --- a/intern/cycles/render/constant_fold.cpp +++ b/intern/cycles/render/constant_fold.cpp @@ -429,4 +429,21 @@ void ConstantFolder::fold_vector_math(NodeVectorMathType type) const } } +void ConstantFolder::fold_mapping(NodeMappingType type) const +{ + ShaderInput *vector_in = node->input("Vector"); + ShaderInput *location_in = node->input("Location"); + ShaderInput *rotation_in = node->input("Rotation"); + ShaderInput *scale_in = node->input("Scale"); + + if (is_zero(scale_in)) { + make_zero(); + } + else if ((is_zero(location_in) || type == NODE_MAPPING_TYPE_VECTOR || + type == NODE_MAPPING_TYPE_NORMAL) && + is_zero(rotation_in) && is_one(scale_in)) { + try_bypass_or_make_constant(vector_in); + } +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/constant_fold.h b/intern/cycles/render/constant_fold.h index 881636a9fe1..7f622488a88 100644 --- a/intern/cycles/render/constant_fold.h +++ b/intern/cycles/render/constant_fold.h @@ -66,6 +66,7 @@ class ConstantFolder { void fold_mix(NodeMix type, bool clamp) const; void fold_math(NodeMathType type) const; void fold_vector_math(NodeVectorMathType type) const; + void fold_mapping(NodeMappingType type) const; }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 24aa9589220..31dc986a4d1 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -25,6 +25,7 @@ #include "kernel/svm/svm_color_util.h" #include "kernel/svm/svm_ramp_util.h" #include "kernel/svm/svm_math_util.h" +#include "kernel/svm/svm_mapping_util.h" #include "render/osl.h" #include "render/constant_fold.h" @@ -149,7 +150,7 @@ bool TextureMapping::skip() void TextureMapping::compile(SVMCompiler &compiler, int offset_in, int offset_out) { - compiler.add_node(NODE_MAPPING, offset_in, offset_out); + compiler.add_node(NODE_TEXTURE_MAPPING, offset_in, offset_out); Transform tfm = compute_transform(); compiler.add_node(tfm.x); @@ -1727,9 +1728,18 @@ NODE_DEFINE(MappingNode) { NodeType *type = NodeType::add("mapping", create, NodeType::SHADER); - TEXTURE_MAPPING_DEFINE(MappingNode); + static NodeEnum type_enum; + type_enum.insert("point", NODE_MAPPING_TYPE_POINT); + type_enum.insert("texture", NODE_MAPPING_TYPE_TEXTURE); + type_enum.insert("vector", NODE_MAPPING_TYPE_VECTOR); + type_enum.insert("normal", NODE_MAPPING_TYPE_NORMAL); + SOCKET_ENUM(type, "Type", type_enum, NODE_MAPPING_TYPE_POINT); SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f)); + SOCKET_IN_POINT(location, "Location", make_float3(0.0f, 0.0f, 0.0f)); + SOCKET_IN_POINT(rotation, "Rotation", make_float3(0.0f, 0.0f, 0.0f)); + SOCKET_IN_POINT(scale, "Scale", make_float3(1.0f, 1.0f, 1.0f)); + SOCKET_OUT_POINT(vector, "Vector"); return type; @@ -1739,22 +1749,42 @@ MappingNode::MappingNode() : ShaderNode(node_type) { } +void MappingNode::constant_fold(const ConstantFolder &folder) +{ + if (folder.all_inputs_constant()) { + float3 result = svm_mapping((NodeMappingType)type, vector, location, rotation, scale); + folder.make_constant(result); + } + else { + folder.fold_mapping((NodeMappingType)type); + } +} + void MappingNode::compile(SVMCompiler &compiler) { ShaderInput *vector_in = input("Vector"); + ShaderInput *location_in = input("Location"); + ShaderInput *rotation_in = input("Rotation"); + ShaderInput *scale_in = input("Scale"); ShaderOutput *vector_out = output("Vector"); - tex_mapping.compile( - compiler, compiler.stack_assign(vector_in), compiler.stack_assign(vector_out)); + int vector_stack_offset = compiler.stack_assign(vector_in); + int location_stack_offset = compiler.stack_assign(location_in); + int rotation_stack_offset = compiler.stack_assign(rotation_in); + int scale_stack_offset = compiler.stack_assign(scale_in); + int result_stack_offset = compiler.stack_assign(vector_out); + + compiler.add_node( + NODE_MAPPING, + type, + compiler.encode_uchar4( + vector_stack_offset, location_stack_offset, rotation_stack_offset, scale_stack_offset), + result_stack_offset); } void MappingNode::compile(OSLCompiler &compiler) { - compiler.parameter("Matrix", tex_mapping.compute_transform()); - compiler.parameter_point("mapping_min", tex_mapping.min); - compiler.parameter_point("mapping_max", tex_mapping.max); - compiler.parameter("use_minmax", tex_mapping.use_minmax); - + compiler.parameter(this, "type"); compiler.add(this, "node_mapping"); } diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 271d60d16b7..769687f1f19 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -391,9 +391,10 @@ class MappingNode : public ShaderNode { { return NODE_GROUP_LEVEL_2; } + void constant_fold(const ConstantFolder &folder); - float3 vector; - TextureMapping tex_mapping; + float3 vector, location, rotation, scale; + NodeMappingType type; }; class RGBToBWNode : public ShaderNode { diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h index cfe71d696ed..407654245cb 100644 --- a/intern/cycles/util/util_transform.h +++ b/intern/cycles/util/util_transform.h @@ -148,6 +148,32 @@ ccl_device_inline Transform make_transform(float a, return t; } +ccl_device_inline Transform euler_to_transform(const float3 euler) +{ + float cx = cosf(euler.x); + float cy = cosf(euler.y); + float cz = cosf(euler.z); + float sx = sinf(euler.x); + float sy = sinf(euler.y); + float sz = sinf(euler.z); + + Transform t; + t.x.x = cy * cz; + t.y.x = cy * sz; + t.z.x = -sy; + + t.x.y = sy * sx * cz - cx * sz; + t.y.y = sy * sx * sz + cx * cz; + t.z.y = cy * sx; + + t.x.z = sy * cx * cz + sx * sz; + t.y.z = sy * cx * sz - sx * cz; + t.z.z = cy * cx; + + t.x.w = t.y.w = t.z.w = 0.0f; + return t; +} + /* Constructs a coordinate frame from a normalized normal. */ ccl_device_inline Transform make_transform_frame(float3 N) { diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 30df5abebc0..e68989dd9ef 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -27,7 +27,7 @@ * \note Use #STRINGIFY() rather than defining with quotes. */ #define BLENDER_VERSION 281 -#define BLENDER_SUBVERSION 7 +#define BLENDER_SUBVERSION 8 /** Several breakages with 280, e.g. collections vs layers. */ #define BLENDER_MINVERSION 280 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenloader/intern/versioning_cycles.c b/source/blender/blenloader/intern/versioning_cycles.c index f12a544a9cc..52be5b2ce74 100644 --- a/source/blender/blenloader/intern/versioning_cycles.c +++ b/source/blender/blenloader/intern/versioning_cycles.c @@ -34,12 +34,16 @@ #include "DNA_node_types.h" #include "DNA_particle_types.h" #include "DNA_camera_types.h" +#include "DNA_anim_types.h" #include "BKE_colortools.h" +#include "BKE_animsys.h" #include "BKE_idprop.h" #include "BKE_main.h" #include "BKE_node.h" +#include "MEM_guardedalloc.h" + #include "IMB_colormanagement.h" #include "BLO_readfile.h" @@ -769,6 +773,141 @@ static void update_noise_node_dimensions(bNodeTree *ntree) } } +/* The Mapping node has been rewritten to support dynamic inputs. Previously, + * the transformation information was stored in a TexMapping struct in the + * node->storage member of bNode. Currently, the transformation information + * is stored in input sockets. To correct this, we transfer the information + * from the TexMapping struct to the input sockets. + * + * Additionally, the Minimum and Maximum properties are no longer available + * in the node. To correct this, a Vector Minimum and/or a Vector Maximum + * nodes are added if needed. + * + * Finally, the TexMapping struct is freed and node->storage is set to NULL. + * + * Since the RNA paths of the properties changed, we also have to update the + * rna_path of the FCurves if they exist. To do that, we loop over FCurves + * and check if they control a property of the node, if they do, we update + * the path to be that of the corrsponding socket in the node or the added + * minimum/maximum node. + * + */ +static void update_mapping_node_inputs_and_properties(bNodeTree *ntree) +{ + bool need_update = false; + + for (bNode *node = ntree->nodes.first; node; node = node->next) { + if (node->type == SH_NODE_MAPPING) { + TexMapping *mapping = (TexMapping *)node->storage; + node->custom1 = mapping->type; + node->width = 140.0f; + + bNodeSocket *sockLocation = nodeFindSocket(node, SOCK_IN, "Location"); + copy_v3_v3(cycles_node_socket_vector_value(sockLocation), mapping->loc); + bNodeSocket *sockRotation = nodeFindSocket(node, SOCK_IN, "Rotation"); + copy_v3_v3(cycles_node_socket_vector_value(sockRotation), mapping->rot); + bNodeSocket *sockScale = nodeFindSocket(node, SOCK_IN, "Scale"); + copy_v3_v3(cycles_node_socket_vector_value(sockScale), mapping->size); + + bNode *maximumNode = NULL; + if (mapping->flag & TEXMAP_CLIP_MAX) { + maximumNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH); + maximumNode->custom1 = NODE_VECTOR_MATH_MAXIMUM; + if (mapping->flag & TEXMAP_CLIP_MIN) { + maximumNode->locx = node->locx + (node->width + 20.0f) * 2.0f; + } + else { + maximumNode->locx = node->locx + node->width + 20.0f; + } + maximumNode->locy = node->locy; + bNodeSocket *sockMaximumB = BLI_findlink(&maximumNode->inputs, 1); + copy_v3_v3(cycles_node_socket_vector_value(sockMaximumB), mapping->max); + bNodeSocket *sockMappingResult = nodeFindSocket(node, SOCK_OUT, "Vector"); + + LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) { + if (link->fromsock == sockMappingResult) { + bNodeSocket *sockMaximumResult = nodeFindSocket(maximumNode, SOCK_OUT, "Vector"); + nodeAddLink(ntree, maximumNode, sockMaximumResult, link->tonode, link->tosock); + nodeRemLink(ntree, link); + } + } + if (!(mapping->flag & TEXMAP_CLIP_MIN)) { + bNodeSocket *sockMaximumA = BLI_findlink(&maximumNode->inputs, 0); + nodeAddLink(ntree, node, sockMappingResult, maximumNode, sockMaximumA); + } + + need_update = true; + } + + bNode *minimumNode = NULL; + if (mapping->flag & TEXMAP_CLIP_MIN) { + minimumNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH); + minimumNode->custom1 = NODE_VECTOR_MATH_MINIMUM; + minimumNode->locx = node->locx + node->width + 20.0f; + minimumNode->locy = node->locy; + bNodeSocket *sockMinimumB = BLI_findlink(&minimumNode->inputs, 1); + copy_v3_v3(cycles_node_socket_vector_value(sockMinimumB), mapping->min); + + bNodeSocket *sockMinimumResult = nodeFindSocket(minimumNode, SOCK_OUT, "Vector"); + bNodeSocket *sockMappingResult = nodeFindSocket(node, SOCK_OUT, "Vector"); + + if (maximumNode) { + bNodeSocket *sockMaximumA = BLI_findlink(&maximumNode->inputs, 0); + nodeAddLink(ntree, minimumNode, sockMinimumResult, maximumNode, sockMaximumA); + } + else { + LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) { + if (link->fromsock == sockMappingResult) { + nodeAddLink(ntree, minimumNode, sockMinimumResult, link->tonode, link->tosock); + nodeRemLink(ntree, link); + } + } + } + bNodeSocket *sockMinimumA = BLI_findlink(&minimumNode->inputs, 0); + nodeAddLink(ntree, node, sockMappingResult, minimumNode, sockMinimumA); + + need_update = true; + } + + MEM_freeN(node->storage); + node->storage = NULL; + + AnimData *animData = BKE_animdata_from_id(&ntree->id); + if (animData && animData->action) { + const char *nodePath = BLI_sprintfN("nodes[\"%s\"]", node->name); + for (FCurve *fcu = animData->action->curves.first; fcu; fcu = fcu->next) { + if (STRPREFIX(fcu->rna_path, nodePath) && + !BLI_str_endswith(fcu->rna_path, "default_value")) { + + MEM_freeN(fcu->rna_path); + if (BLI_str_endswith(fcu->rna_path, "translation")) { + fcu->rna_path = BLI_sprintfN("%s.%s", nodePath, "inputs[1].default_value"); + } + else if (BLI_str_endswith(fcu->rna_path, "rotation")) { + fcu->rna_path = BLI_sprintfN("%s.%s", nodePath, "inputs[2].default_value"); + } + else if (BLI_str_endswith(fcu->rna_path, "scale")) { + fcu->rna_path = BLI_sprintfN("%s.%s", nodePath, "inputs[3].default_value"); + } + else if (minimumNode && BLI_str_endswith(fcu->rna_path, "min")) { + fcu->rna_path = BLI_sprintfN( + "nodes[\"%s\"].%s", minimumNode->name, "inputs[1].default_value"); + } + else if (maximumNode && BLI_str_endswith(fcu->rna_path, "max")) { + fcu->rna_path = BLI_sprintfN( + "nodes[\"%s\"].%s", maximumNode->name, "inputs[1].default_value"); + } + } + } + } + } + } + + if (need_update) { + ntreeUpdateTree(NULL, ntree); + } +} + void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bmain) { /* Particle shape shared with Eevee. */ @@ -950,4 +1089,13 @@ void do_versions_after_linking_cycles(Main *bmain) } FOREACH_NODETREE_END; } + + if (!MAIN_VERSION_ATLEAST(bmain, 281, 8)) { + FOREACH_NODETREE_BEGIN (bmain, ntree, id) { + if (ntree->type == NTREE_SHADER) { + update_mapping_node_inputs_and_properties(ntree); + } + } + FOREACH_NODETREE_END; + } } diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 47433693e7b..8e6b09be2c7 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -731,37 +731,7 @@ static void node_buts_image_user(uiLayout *layout, static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiLayout *row, *col, *sub; - - uiItemR(layout, ptr, "vector_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); - - row = uiLayoutRow(layout, false); - - col = uiLayoutColumn(row, true); - uiItemL(col, IFACE_("Location:"), ICON_NONE); - uiItemR(col, ptr, "translation", 0, "", ICON_NONE); - - col = uiLayoutColumn(row, true); - uiItemL(col, IFACE_("Rotation:"), ICON_NONE); - uiItemR(col, ptr, "rotation", 0, "", ICON_NONE); - - col = uiLayoutColumn(row, true); - uiItemL(col, IFACE_("Scale:"), ICON_NONE); - uiItemR(col, ptr, "scale", 0, "", ICON_NONE); - - row = uiLayoutRow(layout, false); - - col = uiLayoutColumn(row, true); - uiItemR(col, ptr, "use_min", 0, IFACE_("Min"), ICON_NONE); - sub = uiLayoutColumn(col, true); - uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_min")); - uiItemR(sub, ptr, "min", 0, "", ICON_NONE); - - col = uiLayoutColumn(row, true); - uiItemR(col, ptr, "use_max", 0, IFACE_("Max"), ICON_NONE); - sub = uiLayoutColumn(col, true); - uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_max")); - uiItemR(sub, ptr, "max", 0, "", ICON_NONE); + uiItemR(layout, ptr, "vector_type", 0, NULL, ICON_NONE); } static void node_shader_buts_vect_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) diff --git a/source/blender/gpu/intern/gpu_material_library.h b/source/blender/gpu/intern/gpu_material_library.h index 99a71094753..9c0cf3e6bea 100644 --- a/source/blender/gpu/intern/gpu_material_library.h +++ b/source/blender/gpu/intern/gpu_material_library.h @@ -318,7 +318,7 @@ static GPUMaterialLibrary gpu_shader_material_light_path_library = { static GPUMaterialLibrary gpu_shader_material_mapping_library = { .code = datatoc_gpu_shader_material_mapping_glsl, - .dependencies = {NULL}, + .dependencies = {&gpu_shader_material_math_util_library, NULL}, }; static GPUMaterialLibrary gpu_shader_material_map_range_library = { diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_mapping.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_mapping.glsl index ef47ac2be98..07f152439fe 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_mapping.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_mapping.glsl @@ -1,7 +1,27 @@ -void mapping( +void mapping_mat4( vec3 vec, vec4 m0, vec4 m1, vec4 m2, vec4 m3, vec3 minvec, vec3 maxvec, out vec3 outvec) { mat4 mat = mat4(m0, m1, m2, m3); outvec = (mat * vec4(vec, 1.0)).xyz; outvec = clamp(outvec, minvec, maxvec); } + +void mapping_point(vec3 vector, vec3 location, vec3 rotation, vec3 scale, out vec3 result) +{ + result = (euler_to_mat3(rotation) * (vector * scale)) + location; +} + +void mapping_texture(vec3 vector, vec3 location, vec3 rotation, vec3 scale, out vec3 result) +{ + result = safe_divide(transpose(euler_to_mat3(rotation)) * (vector - location), scale); +} + +void mapping_vector(vec3 vector, vec3 location, vec3 rotation, vec3 scale, out vec3 result) +{ + result = euler_to_mat3(rotation) * (vector * scale); +} + +void mapping_normal(vec3 vector, vec3 location, vec3 rotation, vec3 scale, out vec3 result) +{ + result = normalize(euler_to_mat3(rotation) * safe_divide(vector, scale)); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_math_util.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_math_util.glsl index 0be7da0cc4c..fd9aaf4ae86 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_math_util.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_math_util.glsl @@ -85,6 +85,30 @@ void vector_normalize(vec3 normal, out vec3 outnormal) /* Matirx Math */ +mat3 euler_to_mat3(vec3 euler) +{ + float cx = cos(euler.x); + float cy = cos(euler.y); + float cz = cos(euler.z); + float sx = sin(euler.x); + float sy = sin(euler.y); + float sz = sin(euler.z); + + mat3 mat; + mat[0][0] = cy * cz; + mat[0][1] = cy * sz; + mat[0][2] = -sy; + + mat[1][0] = sy * sx * cz - cx * sz; + mat[1][1] = sy * sx * sz + cx * cz; + mat[1][2] = cy * sx; + + mat[2][0] = sy * cx * cz + sx * sz; + mat[2][1] = sy * cx * sz - sx * cz; + mat[2][2] = cy * cx; + return mat; +} + void direction_transform_m4v3(vec3 vin, mat4 mat, out vec3 vout) { vout = (mat * vec4(vin, 0.0)).xyz; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 0787f41b810..ee5e9a13f66 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1169,6 +1169,14 @@ typedef struct NodeDenoise { #define SHD_AO_INSIDE 1 #define SHD_AO_LOCAL 2 +/* Mapping node vector types */ +enum { + NODE_MAPPING_TYPE_POINT = 0, + NODE_MAPPING_TYPE_TEXTURE = 1, + NODE_MAPPING_TYPE_VECTOR = 2, + NODE_MAPPING_TYPE_NORMAL = 3, +}; + /* math node clamp */ #define SHD_MATH_CLAMP 1 diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h index b3e1f22f413..e72a55b5a9e 100644 --- a/source/blender/makesrna/RNA_enum_types.h +++ b/source/blender/makesrna/RNA_enum_types.h @@ -184,6 +184,7 @@ extern const EnumPropertyItem rna_enum_file_sort_items[]; extern const EnumPropertyItem rna_enum_node_socket_in_out_items[]; extern const EnumPropertyItem rna_enum_node_math_items[]; +extern const EnumPropertyItem rna_enum_mapping_type_items[]; extern const EnumPropertyItem rna_enum_node_vec_math_items[]; extern const EnumPropertyItem rna_enum_node_filter_items[]; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 988533e0f0e..6a4d59bd883 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -102,6 +102,26 @@ static const EnumPropertyItem node_chunksize_items[] = { }; #endif +const EnumPropertyItem rna_enum_mapping_type_items[] = { + {NODE_MAPPING_TYPE_POINT, "POINT", 0, "Point", "Transform a point"}, + {NODE_MAPPING_TYPE_TEXTURE, + "TEXTURE", + 0, + "Texture", + "Transform a texture by inverse mapping the texture coordinate"}, + {NODE_MAPPING_TYPE_VECTOR, + "VECTOR", + 0, + "Vector", + "Transform a direction vector. Location is ignored"}, + {NODE_MAPPING_TYPE_NORMAL, + "NORMAL", + 0, + "Normal", + "Transform a unit normal vector. Location is ignored"}, + {0, NULL, 0, NULL, NULL}, +}; + const EnumPropertyItem rna_enum_node_math_items[] = { {NODE_MATH_ADD, "ADD", 0, "Add", "A + B"}, {NODE_MATH_SUBTRACT, "SUBTRACT", 0, "Subtract", "A - B"}, @@ -3213,13 +3233,6 @@ static void rna_Image_Node_update_id(Main *UNUSED(bmain), Scene *UNUSED(scene), nodeUpdate(ntree, node); /* to update image node sockets */ } -static void rna_Mapping_Node_update(Main *bmain, Scene *scene, PointerRNA *ptr) -{ - bNode *node = ptr->data; - BKE_texture_mapping_init(node->storage); - rna_Node_update(bmain, scene, ptr); -} - static void rna_NodeOutputFile_slots_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { bNode *node = ptr->data; @@ -4034,68 +4047,13 @@ static void def_sh_output_linestyle(StructRNA *srna) static void def_sh_mapping(StructRNA *srna) { - static const EnumPropertyItem prop_vect_type_items[] = { - {TEXMAP_TYPE_TEXTURE, - "TEXTURE", - 0, - "Texture", - "Transform a texture by inverse mapping the texture coordinate"}, - {TEXMAP_TYPE_POINT, "POINT", 0, "Point", "Transform a point"}, - {TEXMAP_TYPE_VECTOR, "VECTOR", 0, "Vector", "Transform a direction vector"}, - {TEXMAP_TYPE_NORMAL, "NORMAL", 0, "Normal", "Transform a normal vector with unit length"}, - {0, NULL, 0, NULL, NULL}, - }; - - static float default_1[3] = {1.f, 1.f, 1.f}; - PropertyRNA *prop; - RNA_def_struct_sdna_from(srna, "TexMapping", "storage"); - prop = RNA_def_property(srna, "vector_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "type"); - RNA_def_property_enum_items(prop, prop_vect_type_items); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, rna_enum_mapping_type_items); RNA_def_property_ui_text(prop, "Type", "Type of vector that the mapping transforms"); - RNA_def_property_update(prop, 0, "rna_Mapping_Node_update"); - - prop = RNA_def_property(srna, "translation", PROP_FLOAT, PROP_TRANSLATION); - RNA_def_property_float_sdna(prop, NULL, "loc"); - RNA_def_property_ui_text(prop, "Location", ""); - RNA_def_property_update(prop, 0, "rna_Mapping_Node_update"); - - /* Not PROP_XYZ, this is now in radians, no more degrees */ - prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_EULER); - RNA_def_property_float_sdna(prop, NULL, "rot"); - RNA_def_property_ui_text(prop, "Rotation", ""); - RNA_def_property_update(prop, 0, "rna_Mapping_Node_update"); - - prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ); - RNA_def_property_float_sdna(prop, NULL, "size"); - RNA_def_property_float_array_default(prop, default_1); - RNA_def_property_flag(prop, PROP_PROPORTIONAL); - RNA_def_property_ui_text(prop, "Scale", ""); - RNA_def_property_update(prop, 0, "rna_Mapping_Node_update"); - - prop = RNA_def_property(srna, "min", PROP_FLOAT, PROP_XYZ); - RNA_def_property_float_sdna(prop, NULL, "min"); - RNA_def_property_ui_text(prop, "Minimum", "Minimum value for clipping"); - RNA_def_property_update(prop, 0, "rna_Mapping_Node_update"); - - prop = RNA_def_property(srna, "max", PROP_FLOAT, PROP_XYZ); - RNA_def_property_float_sdna(prop, NULL, "max"); - RNA_def_property_float_array_default(prop, default_1); - RNA_def_property_ui_text(prop, "Maximum", "Maximum value for clipping"); - RNA_def_property_update(prop, 0, "rna_Mapping_Node_update"); - - prop = RNA_def_property(srna, "use_min", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", TEXMAP_CLIP_MIN); - RNA_def_property_ui_text(prop, "Has Minimum", "Whether to use minimum clipping value"); - RNA_def_property_update(prop, 0, "rna_Mapping_Node_update"); - - prop = RNA_def_property(srna, "use_max", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", TEXMAP_CLIP_MAX); - RNA_def_property_ui_text(prop, "Has Maximum", "Whether to use maximum clipping value"); - RNA_def_property_update(prop, 0, "rna_Mapping_Node_update"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update"); } static void def_sh_attribute(StructRNA *srna) diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c index 2015356d071..2fc0e2bdf2d 100644 --- a/source/blender/makesrna/intern/rna_texture.c +++ b/source/blender/makesrna/intern/rna_texture.c @@ -465,18 +465,6 @@ static void rna_def_texmapping(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}, }; - static const EnumPropertyItem prop_vect_type_items[] = { - {TEXMAP_TYPE_TEXTURE, - "TEXTURE", - 0, - "Texture", - "Transform a texture by inverse mapping the texture coordinate"}, - {TEXMAP_TYPE_POINT, "POINT", 0, "Point", "Transform a point"}, - {TEXMAP_TYPE_VECTOR, "VECTOR", 0, "Vector", "Transform a direction vector"}, - {TEXMAP_TYPE_NORMAL, "NORMAL", 0, "Normal", "Transform a normal vector with unit length"}, - {0, NULL, 0, NULL, NULL}, - }; - static const EnumPropertyItem prop_xyz_mapping_items[] = { {0, "NONE", 0, "None", ""}, {1, "X", 0, "X", ""}, @@ -493,7 +481,7 @@ static void rna_def_texmapping(BlenderRNA *brna) prop = RNA_def_property(srna, "vector_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type"); - RNA_def_property_enum_items(prop, prop_vect_type_items); + RNA_def_property_enum_items(prop, rna_enum_mapping_type_items); RNA_def_property_ui_text(prop, "Type", "Type of vector that the mapping transforms"); RNA_def_property_update(prop, 0, "rna_Texture_mapping_update"); diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c index 65676a5ea91..a2b18b61480 100644 --- a/source/blender/nodes/shader/node_shader_util.c +++ b/source/blender/nodes/shader/node_shader_util.c @@ -280,7 +280,7 @@ void node_shader_gpu_tex_mapping(GPUMaterial *mat, tmat2 = GPU_uniform((float *)texmap->mat[2]); tmat3 = GPU_uniform((float *)texmap->mat[3]); - GPU_link(mat, "mapping", in[0].link, tmat0, tmat1, tmat2, tmat3, tmin, tmax, &in[0].link); + GPU_link(mat, "mapping_mat4", in[0].link, tmat0, tmat1, tmat2, tmat3, tmin, tmax, &in[0].link); if (texmap->type == TEXMAP_TYPE_NORMAL) { GPU_link(mat, "vector_normalize", in[0].link, &in[0].link); diff --git a/source/blender/nodes/shader/nodes/node_shader_mapping.c b/source/blender/nodes/shader/nodes/node_shader_mapping.c index e58a5d72f28..d607fcdc7a1 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mapping.c +++ b/source/blender/nodes/shader/nodes/node_shader_mapping.c @@ -25,7 +25,10 @@ /* **************** MAPPING ******************** */ static bNodeSocketTemplate sh_node_mapping_in[] = { - {SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE}, + {SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 1.0f, -FLT_MAX, FLT_MAX, PROP_NONE}, + {SOCK_VECTOR, 1, N_("Location"), 0.0f, 0.0f, 0.0f, 1.0f, -FLT_MAX, FLT_MAX, PROP_TRANSLATION}, + {SOCK_VECTOR, 1, N_("Rotation"), 0.0f, 0.0f, 0.0f, 1.0f, -FLT_MAX, FLT_MAX, PROP_EULER}, + {SOCK_VECTOR, 1, N_("Scale"), 1.0f, 1.0f, 1.0f, 1.0f, -FLT_MAX, FLT_MAX, PROP_XYZ}, {-1, 0, ""}, }; @@ -34,91 +37,27 @@ static bNodeSocketTemplate sh_node_mapping_out[] = { {-1, 0, ""}, }; -static void *node_shader_initexec_mapping(bNodeExecContext *UNUSED(context), - bNode *node, - bNodeInstanceKey UNUSED(key)) -{ - TexMapping *texmap = node->storage; - BKE_texture_mapping_init(texmap); - return NULL; -} - -/* do the regular mapping options for blender textures */ -static void node_shader_exec_mapping(void *UNUSED(data), - int UNUSED(thread), - bNode *node, - bNodeExecData *UNUSED(execdata), - bNodeStack **in, - bNodeStack **out) -{ - TexMapping *texmap = node->storage; - float *vec = out[0]->vec; - - /* stack order input: vector */ - /* stack order output: vector */ - nodestack_get_vec(vec, SOCK_VECTOR, in[0]); - mul_m4_v3(texmap->mat, vec); - - if (texmap->flag & TEXMAP_CLIP_MIN) { - if (vec[0] < texmap->min[0]) { - vec[0] = texmap->min[0]; - } - if (vec[1] < texmap->min[1]) { - vec[1] = texmap->min[1]; - } - if (vec[2] < texmap->min[2]) { - vec[2] = texmap->min[2]; - } - } - if (texmap->flag & TEXMAP_CLIP_MAX) { - if (vec[0] > texmap->max[0]) { - vec[0] = texmap->max[0]; - } - if (vec[1] > texmap->max[1]) { - vec[1] = texmap->max[1]; - } - if (vec[2] > texmap->max[2]) { - vec[2] = texmap->max[2]; - } - } - - if (texmap->type == TEXMAP_TYPE_NORMAL) { - normalize_v3(vec); - } -} - -static void node_shader_init_mapping(bNodeTree *UNUSED(ntree), bNode *node) -{ - node->storage = BKE_texture_mapping_add(TEXMAP_TYPE_POINT); -} - static int gpu_shader_mapping(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { - TexMapping *texmap = node->storage; - float domin = (texmap->flag & TEXMAP_CLIP_MIN) != 0; - float domax = (texmap->flag & TEXMAP_CLIP_MAX) != 0; - static float max[3] = {FLT_MAX, FLT_MAX, FLT_MAX}; - static float min[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX}; - GPUNodeLink *tmin, *tmax, *tmat0, *tmat1, *tmat2, *tmat3; - - tmin = GPU_uniform((domin) ? texmap->min : min); - tmax = GPU_uniform((domax) ? texmap->max : max); - tmat0 = GPU_uniform((float *)texmap->mat[0]); - tmat1 = GPU_uniform((float *)texmap->mat[1]); - tmat2 = GPU_uniform((float *)texmap->mat[2]); - tmat3 = GPU_uniform((float *)texmap->mat[3]); - - GPU_stack_link(mat, node, "mapping", in, out, tmat0, tmat1, tmat2, tmat3, tmin, tmax); - - if (texmap->type == TEXMAP_TYPE_NORMAL) { - GPU_link(mat, "vector_normalize", out[0].link, &out[0].link); - } + static const char *names[] = { + [NODE_MAPPING_TYPE_POINT] = "mapping_point", + [NODE_MAPPING_TYPE_TEXTURE] = "mapping_texture", + [NODE_MAPPING_TYPE_VECTOR] = "mapping_vector", + [NODE_MAPPING_TYPE_NORMAL] = "mapping_normal", + }; + + return GPU_stack_link(mat, node, names[node->custom1], in, out); +} - return true; +static void node_shader_update_mapping(bNodeTree *UNUSED(ntree), bNode *node) +{ + bNodeSocket *sock = nodeFindSocket(node, SOCK_IN, "Location"); + nodeSetSocketAvailability( + sock, ELEM(node->custom1, NODE_MAPPING_TYPE_POINT, NODE_MAPPING_TYPE_TEXTURE)); } void register_node_type_sh_mapping(void) @@ -127,11 +66,8 @@ void register_node_type_sh_mapping(void) sh_node_type_base(&ntype, SH_NODE_MAPPING, "Mapping", NODE_CLASS_OP_VECTOR, 0); node_type_socket_templates(&ntype, sh_node_mapping_in, sh_node_mapping_out); - node_type_size(&ntype, 320, 160, 360); - node_type_init(&ntype, node_shader_init_mapping); - node_type_storage(&ntype, "TexMapping", node_free_standard_storage, node_copy_standard_storage); - node_type_exec(&ntype, node_shader_initexec_mapping, NULL, node_shader_exec_mapping); node_type_gpu(&ntype, gpu_shader_mapping); + node_type_update(&ntype, node_shader_update_mapping); nodeRegisterType(&ntype); } |