diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 806eae72b23..baf79a78987 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -687,6 +687,10 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen BL::ShaderNodeTexCoord b_tex_coord_node(b_node); TextureCoordinateNode *tex_coord = new TextureCoordinateNode(); tex_coord->from_dupli = b_tex_coord_node.from_dupli(); + if(b_tex_coord_node.object()) { + tex_coord->use_transform = true; + tex_coord->ob_tfm = get_transform(b_tex_coord_node.object().matrix_world()); + } node = tex_coord; } else if (b_node.is_a(&RNA_ShaderNodeTexSky)) { diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 97ceae7237b..79ee6d51196 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -70,10 +70,18 @@ bool BlenderSync::sync_recalc() * so we can do it later on if doing it immediate is not suitable */ BL::BlendData::materials_iterator b_mat; - - for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat) - if(b_mat->is_updated() || (b_mat->node_tree() && b_mat->node_tree().is_updated())) + bool has_updated_objects = b_data.objects.is_updated(); + for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat) { + if(b_mat->is_updated() || (b_mat->node_tree() && b_mat->node_tree().is_updated())) { shader_map.set_recalc(*b_mat); + } + else { + Shader *shader = shader_map.find(*b_mat); + if(has_updated_objects && shader != NULL && shader->has_object_dependency) { + shader_map.set_recalc(*b_mat); + } + } + } BL::BlendData::lamps_iterator b_lamp; diff --git a/intern/cycles/kernel/shaders/node_texture_coordinate.osl b/intern/cycles/kernel/shaders/node_texture_coordinate.osl index f8a6f787288..9e2109fa082 100644 --- a/intern/cycles/kernel/shaders/node_texture_coordinate.osl +++ b/intern/cycles/kernel/shaders/node_texture_coordinate.osl @@ -21,7 +21,9 @@ shader node_texture_coordinate( int is_background = 0, int is_volume = 0, int from_dupli = 0, + int use_transform = 0, string bump_offset = "center", + matrix object_itfm = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), output point Generated = point(0.0, 0.0, 0.0), output point UV = point(0.0, 0.0, 0.0), @@ -60,7 +62,12 @@ shader node_texture_coordinate( getattribute("geom:uv", UV); } - Object = transform("object", P); + if (use_transform) { + Object = transform(object_itfm, P); + } + else { + Object = transform("object", P); + } Camera = transform("camera", P); Window = transform("NDC", P); Normal = transform("world", "object", NormalIn); diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index 3465a743c3f..f1dfeb45265 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -395,7 +395,7 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade svm_node_min_max(kg, sd, stack, node.y, node.z, &offset); break; case NODE_TEX_COORD: - svm_node_tex_coord(kg, sd, path_flag, stack, node.y, node.z); + svm_node_tex_coord(kg, sd, path_flag, stack, node, &offset); break; #ifdef __EXTRA_NODES__ case NODE_TEX_COORD_BUMP_DX: diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h index b69f0d1c1c8..dcaa488ed31 100644 --- a/intern/cycles/kernel/svm/svm_tex_coord.h +++ b/intern/cycles/kernel/svm/svm_tex_coord.h @@ -18,15 +18,33 @@ CCL_NAMESPACE_BEGIN /* Texture Coordinate Node */ -ccl_device void svm_node_tex_coord(KernelGlobals *kg, ShaderData *sd, int path_flag, float *stack, uint type, uint out_offset) +ccl_device void svm_node_tex_coord(KernelGlobals *kg, + ShaderData *sd, + int path_flag, + float *stack, + uint4 node, + int *offset) { float3 data; + uint type = node.y; + uint out_offset = node.z; switch(type) { case NODE_TEXCO_OBJECT: { data = sd->P; - if(sd->object != OBJECT_NONE) - object_inverse_position_transform(kg, sd, &data); + if(node.w == 0) { + if(sd->object != OBJECT_NONE) { + object_inverse_position_transform(kg, sd, &data); + } + } + else { + Transform tfm; + tfm.x = read_node_float(kg, offset); + tfm.y = read_node_float(kg, offset); + tfm.z = read_node_float(kg, offset); + tfm.w = read_node_float(kg, offset); + data = transform_point(&tfm, data); + } break; } case NODE_TEXCO_NORMAL: { diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h index 6821d012166..b39b3dae324 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -196,6 +196,7 @@ public: virtual bool has_converter_blackbody() { return false; } virtual bool has_bssrdf_bump() { return false; } virtual bool has_spatial_varying() { return false; } + virtual bool has_object_dependency() { return false; } vector inputs; vector outputs; diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index ed0be4d7b41..3448209f101 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -2263,6 +2263,8 @@ TextureCoordinateNode::TextureCoordinateNode() add_output("Reflection", SHADER_SOCKET_NORMAL); from_dupli = false; + use_transform = false; + ob_tfm = transform_identity(); } void TextureCoordinateNode::attributes(Shader *shader, AttributeRequestSet *attributes) @@ -2350,7 +2352,14 @@ void TextureCoordinateNode::compile(SVMCompiler& compiler) out = output("Object"); if(!out->links.empty()) { compiler.stack_assign(out); - compiler.add_node(texco_node, NODE_TEXCO_OBJECT, out->stack_offset); + compiler.add_node(texco_node, NODE_TEXCO_OBJECT, out->stack_offset, use_transform); + if(use_transform) { + Transform ob_itfm = transform_inverse(ob_tfm); + compiler.add_node(ob_itfm.x); + compiler.add_node(ob_itfm.y); + compiler.add_node(ob_itfm.z); + compiler.add_node(ob_itfm.w); + } } out = output("Camera"); @@ -2391,7 +2400,10 @@ void TextureCoordinateNode::compile(OSLCompiler& compiler) compiler.parameter("is_background", true); if(compiler.output_type() == SHADER_TYPE_VOLUME) compiler.parameter("is_volume", true); - + compiler.parameter("use_transform", use_transform); + Transform ob_itfm = transform_transpose(transform_inverse(ob_tfm)); + compiler.parameter("object_itfm", ob_itfm); + compiler.parameter("from_dupli", from_dupli); compiler.add(this, "node_texture_coordinate"); diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 3140ec939bb..0ec0fce512f 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -357,8 +357,11 @@ public: SHADER_NODE_CLASS(TextureCoordinateNode) void attributes(Shader *shader, AttributeRequestSet *attributes); bool has_spatial_varying() { return true; } - + bool has_object_dependency() { return use_transform; } + bool from_dupli; + bool use_transform; + Transform ob_tfm; }; class UVMapNode : public ShaderNode { diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index 7ddfdaf6cc2..7b22d200a9e 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -567,6 +567,10 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath) if(node->has_spatial_varying()) current_shader->has_heterogeneous_volume = true; } + + if(node->has_object_dependency()) { + current_shader->has_object_dependency = true; + } } void OSLCompiler::parameter(const char *name, float f) @@ -808,6 +812,7 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader) shader->has_volume = false; shader->has_displacement = false; shader->has_heterogeneous_volume = false; + shader->has_object_dependency = false; /* generate surface shader */ if(shader->used && graph && output->input("Surface")->link) { diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index dbf5c5ed7ff..5899c562f72 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -151,6 +151,7 @@ Shader::Shader() has_displacement = false; has_bssrdf_bump = false; has_heterogeneous_volume = false; + has_object_dependency = false; used = false; diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index 1d903ee3a13..1dee47c7731 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -106,6 +106,7 @@ public: bool has_converter_blackbody; bool has_bssrdf_bump; bool has_heterogeneous_volume; + bool has_object_dependency; /* requested mesh attributes */ AttributeRequestSet attributes; diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index 8216669a1ec..2e3abfcffb9 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -393,6 +393,10 @@ void SVMCompiler::generate_node(ShaderNode *node, set& done) /* detect if we have a blackbody converter, to prepare lookup table */ if(node->has_converter_blackbody()) current_shader->has_converter_blackbody = true; + + if(node->has_object_dependency()) { + current_shader->has_object_dependency = true; + } } void SVMCompiler::generate_svm_nodes(const set& nodes, set& done) @@ -713,6 +717,7 @@ void SVMCompiler::compile(Shader *shader, vector& global_svm_nodes, int in shader->has_volume = false; shader->has_displacement = false; shader->has_heterogeneous_volume = false; + shader->has_object_dependency = false; /* generate surface shader */ compile_type(shader, shader->graph, SHADER_TYPE_SURFACE); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 870b4637f4b..f1dfa4f1e8f 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -861,6 +861,7 @@ static void node_shader_buts_tex_voronoi(uiLayout *layout, bContext *UNUSED(C), static void node_shader_buts_tex_coord(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { + uiItemR(layout, ptr, "object", 0, NULL, 0); uiItemR(layout, ptr, "from_dupli", 0, NULL, 0); } diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index ed3896b050d..413531798f2 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -3647,7 +3647,14 @@ static void def_sh_tex_wave(StructRNA *srna) static void def_sh_tex_coord(StructRNA *srna) { PropertyRNA *prop; - + + prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "id"); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Object", "Use coordinates from this object (for object texture coordinates output, currently only for SVM shading)"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + prop = RNA_def_property(srna, "from_dupli", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom1", 1); RNA_def_property_ui_text(prop, "From Dupli", "Use the parent of the dupli object if possible");