Code refactor: improve attribute handling for optional volume attributes.
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Sun, 18 Feb 2018 02:20:39 +0000 (03:20 +0100)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Fri, 23 Feb 2018 17:57:58 +0000 (18:57 +0100)
A volume shader should be able to request attributes, and still be rendered
as homogeneous if no volume attributes are available for the object.

14 files changed:
intern/cycles/kernel/kernel_types.h
intern/cycles/kernel/kernel_volume.h
intern/cycles/render/attribute.cpp
intern/cycles/render/attribute.h
intern/cycles/render/graph.h
intern/cycles/render/nodes.cpp
intern/cycles/render/nodes.h
intern/cycles/render/object.cpp
intern/cycles/render/osl.cpp
intern/cycles/render/osl.h
intern/cycles/render/shader.cpp
intern/cycles/render/shader.h
intern/cycles/render/svm.cpp
intern/cycles/render/svm.h

index 26b5a27807ce107d91638b7d015d588a9182ce52..d967edca75dcc7ec549e75cb3c73e4ffd739d420 100644 (file)
@@ -925,19 +925,22 @@ enum ShaderDataFlag {
        SD_HAS_DISPLACEMENT       = (1 << 26),
        /* Has constant emission (value stored in __shader_flag) */
        SD_HAS_CONSTANT_EMISSION  = (1 << 27),
+       /* Needs to access attributes */
+       SD_NEED_ATTRIBUTES        = (1 << 28),
 
        SD_SHADER_FLAGS = (SD_USE_MIS |
                           SD_HAS_TRANSPARENT_SHADOW |
                           SD_HAS_VOLUME |
                           SD_HAS_ONLY_VOLUME |
-                          SD_HETEROGENEOUS_VOLUME|
+                          SD_HETEROGENEOUS_VOLUME |
                           SD_HAS_BSSRDF_BUMP |
                           SD_VOLUME_EQUIANGULAR |
                           SD_VOLUME_MIS |
                           SD_VOLUME_CUBIC |
                           SD_HAS_BUMP |
                           SD_HAS_DISPLACEMENT |
-                          SD_HAS_CONSTANT_EMISSION)
+                          SD_HAS_CONSTANT_EMISSION |
+                          SD_NEED_ATTRIBUTES)
 };
 
        /* Object flags. */
@@ -958,6 +961,8 @@ enum ShaderDataObjectFlag {
        SD_OBJECT_HAS_VERTEX_MOTION      = (1 << 6),
        /* object is used to catch shadows */
        SD_OBJECT_SHADOW_CATCHER         = (1 << 7),
+       /* object has volume attributes */
+       SD_OBJECT_HAS_VOLUME_ATTRIBUTES  = (1 << 8),
 
        SD_OBJECT_FLAGS = (SD_OBJECT_HOLDOUT_MASK |
                           SD_OBJECT_MOTION |
@@ -965,7 +970,8 @@ enum ShaderDataObjectFlag {
                           SD_OBJECT_NEGATIVE_SCALE_APPLIED |
                           SD_OBJECT_HAS_VOLUME |
                           SD_OBJECT_INTERSECTS_VOLUME |
-                          SD_OBJECT_SHADOW_CATCHER)
+                          SD_OBJECT_SHADOW_CATCHER |
+                          SD_OBJECT_HAS_VOLUME_ATTRIBUTES)
 };
 
 typedef ccl_addr_space struct ShaderData {
index 3274e05f98e0b33b3ebc634bcaf13a37a777f2f6..058e7dccafdb0251a5f27b4da6b9b1e0bba0566e 100644 (file)
@@ -106,8 +106,21 @@ ccl_device bool volume_stack_is_heterogeneous(KernelGlobals *kg, ccl_addr_space
        for(int i = 0; stack[i].shader != SHADER_NONE; i++) {
                int shader_flag = kernel_tex_fetch(__shader_flag, (stack[i].shader & SHADER_MASK)*SHADER_SIZE);
 
-               if(shader_flag & SD_HETEROGENEOUS_VOLUME)
+               if(shader_flag & SD_HETEROGENEOUS_VOLUME) {
                        return true;
+               }
+               else if(shader_flag & SD_NEED_ATTRIBUTES) {
+                       /* We want to render world or objects without any volume grids
+                        * as homogenous, but can only verify this at runtime since other
+                        * heterogenous volume objects may be using the same shader. */
+                       int object = stack[i].object;
+                       if(object != OBJECT_NONE) {
+                               int object_flag = kernel_tex_fetch(__object_flag, object);
+                               if(object_flag & SD_OBJECT_HAS_VOLUME_ATTRIBUTES) {
+                                       return true;
+                               }
+                       }
+               }
        }
 
        return false;
index f959b1fef8b165cce1b23b9c7ef74636ac4da28d..6816f8ca3f347f2648573e0e8663406b959acf29 100644 (file)
@@ -298,9 +298,13 @@ const char *Attribute::standard_name(AttributeStandard std)
 
 AttributeStandard Attribute::name_standard(const char *name)
 {
-       for(int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++)
-               if(strcmp(name, Attribute::standard_name((AttributeStandard)std)) == 0)
-                       return (AttributeStandard)std;
+       if(name) {
+               for(int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++) {
+                       if(strcmp(name, Attribute::standard_name((AttributeStandard)std)) == 0) {
+                               return (AttributeStandard)std;
+                       }
+               }
+       }
 
        return ATTR_STD_NONE;
 }
@@ -615,9 +619,11 @@ bool AttributeRequestSet::modified(const AttributeRequestSet& other)
 
 void AttributeRequestSet::add(ustring name)
 {
-       foreach(AttributeRequest& req, requests)
-               if(req.name == name)
+       foreach(AttributeRequest& req, requests) {
+               if(req.name == name) {
                        return;
+               }
+       }
 
        requests.push_back(AttributeRequest(name));
 }
@@ -641,6 +647,22 @@ void AttributeRequestSet::add(AttributeRequestSet& reqs)
        }
 }
 
+void AttributeRequestSet::add_standard(ustring name)
+{
+       if(!name) {
+               return;
+       }
+
+       AttributeStandard std = Attribute::name_standard(name.c_str());
+
+       if(std) {
+               add(std);
+       }
+       else {
+               add(name);
+       }
+}
+
 bool AttributeRequestSet::find(ustring name)
 {
        foreach(AttributeRequest& req, requests)
index d15ee401a72d5cecab0362c7c70022874d2998f7..9e23345675deaef37e59147d95899c2eef49f12e 100644 (file)
@@ -159,6 +159,7 @@ public:
        void add(ustring name);
        void add(AttributeStandard std);
        void add(AttributeRequestSet& reqs);
+       void add_standard(ustring name);
 
        bool find(ustring name);
        bool find(AttributeStandard std);
index 7ed292b5b960fb963c638a10eee6bd309f75dc43..2c134932b3cbfcf72ec510cb111eb9666cfb1b79 100644 (file)
@@ -156,6 +156,7 @@ public:
        virtual bool has_bssrdf_bump() { return false; }
        virtual bool has_spatial_varying() { return false; }
        virtual bool has_object_dependency() { return false; }
+       virtual bool has_attribute_dependency() { return false; }
        virtual bool has_integrator_dependency() { return false; }
        virtual bool has_volume_support() { return false; }
        virtual bool has_raytrace() { return false; }
index 56c9e669a5ca2c8474c78d3479b9ebb504bbb250..60c536f1ec17c9cdf92353069fb45718ef46be2e 100644 (file)
@@ -208,7 +208,7 @@ NODE_DEFINE(ImageTextureNode)
 
        TEXTURE_MAPPING_DEFINE(ImageTextureNode);
 
-       SOCKET_STRING(filename, "Filename", ustring(""));
+       SOCKET_STRING(filename, "Filename", ustring());
 
        static NodeEnum color_space_enum;
        color_space_enum.insert("none", NODE_COLOR_SPACE_NONE);
@@ -419,7 +419,7 @@ NODE_DEFINE(EnvironmentTextureNode)
 
        TEXTURE_MAPPING_DEFINE(EnvironmentTextureNode);
 
-       SOCKET_STRING(filename, "Filename", ustring(""));
+       SOCKET_STRING(filename, "Filename", ustring());
 
        static NodeEnum color_space_enum;
        color_space_enum.insert("none", NODE_COLOR_SPACE_NONE);
@@ -1348,7 +1348,7 @@ NODE_DEFINE(PointDensityTextureNode)
 {
        NodeType* type = NodeType::add("point_density_texture", create, NodeType::SHADER);
 
-       SOCKET_STRING(filename, "Filename", ustring(""));
+       SOCKET_STRING(filename, "Filename", ustring());
 
        static NodeEnum space_enum;
        space_enum.insert("object", NODE_TEX_VOXEL_SPACE_OBJECT);
@@ -3167,7 +3167,7 @@ NODE_DEFINE(UVMapNode)
 {
        NodeType* type = NodeType::add("uvmap", create, NodeType::SHADER);
 
-       SOCKET_IN_STRING(attribute, "attribute", ustring(""));
+       SOCKET_STRING(attribute, "attribute", ustring());
        SOCKET_IN_BOOLEAN(from_dupli, "from dupli", false);
 
        SOCKET_OUT_POINT(UV, "UV");
@@ -4465,7 +4465,7 @@ NODE_DEFINE(AttributeNode)
 {
        NodeType* type = NodeType::add("attribute", create, NodeType::SHADER);
 
-       SOCKET_STRING(attribute, "Attribute", ustring(""));
+       SOCKET_STRING(attribute, "Attribute", ustring());
 
        SOCKET_OUT_COLOR(color, "Color");
        SOCKET_OUT_VECTOR(vector, "Vector");
@@ -4486,16 +4486,12 @@ void AttributeNode::attributes(Shader *shader, AttributeRequestSet *attributes)
        ShaderOutput *fac_out = output("Fac");
 
        if(!color_out->links.empty() || !vector_out->links.empty() || !fac_out->links.empty()) {
-               AttributeStandard std = Attribute::name_standard(attribute.c_str());
-
-               if(std != ATTR_STD_NONE)
-                       attributes->add(std);
-               else
-                       attributes->add(attribute);
+               attributes->add_standard(attribute);
        }
 
-       if(shader->has_volume)
+       if(shader->has_volume) {
                attributes->add(ATTR_STD_GENERATED_TRANSFORM);
+       }
 
        ShaderNode::attributes(shader, attributes);
 }
@@ -4506,13 +4502,7 @@ void AttributeNode::compile(SVMCompiler& compiler)
        ShaderOutput *vector_out = output("Vector");
        ShaderOutput *fac_out = output("Fac");
        ShaderNodeType attr_node = NODE_ATTR;
-       AttributeStandard std = Attribute::name_standard(attribute.c_str());
-       int attr;
-
-       if(std != ATTR_STD_NONE)
-               attr = compiler.attribute(std);
-       else
-               attr = compiler.attribute(attribute);
+       int attr = compiler.attribute_standard(attribute);;
 
        if(bump == SHADER_BUMP_DX)
                attr_node = NODE_ATTR_BUMP_DX;
@@ -5470,7 +5460,7 @@ NODE_DEFINE(NormalMapNode)
        space_enum.insert("blender_world", NODE_NORMAL_MAP_BLENDER_WORLD);
        SOCKET_ENUM(space, "Space", space_enum, NODE_TANGENT_RADIAL);
 
-       SOCKET_STRING(attribute, "Attribute", ustring(""));
+       SOCKET_STRING(attribute, "Attribute", ustring());
 
        SOCKET_IN_NORMAL(normal_osl, "NormalIn", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
        SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
@@ -5489,7 +5479,7 @@ NormalMapNode::NormalMapNode()
 void NormalMapNode::attributes(Shader *shader, AttributeRequestSet *attributes)
 {
        if(shader->has_surface && space == NODE_NORMAL_MAP_TANGENT) {
-               if(attribute == ustring("")) {
+               if(attribute.empty()) {
                        attributes->add(ATTR_STD_UV_TANGENT);
                        attributes->add(ATTR_STD_UV_TANGENT_SIGN);
                }
@@ -5512,7 +5502,7 @@ void NormalMapNode::compile(SVMCompiler& compiler)
        int attr = 0, attr_sign = 0;
 
        if(space == NODE_NORMAL_MAP_TANGENT) {
-               if(attribute == ustring("")) {
+               if(attribute.empty()) {
                        attr = compiler.attribute(ATTR_STD_UV_TANGENT);
                        attr_sign = compiler.attribute(ATTR_STD_UV_TANGENT_SIGN);
                }
@@ -5534,7 +5524,7 @@ void NormalMapNode::compile(SVMCompiler& compiler)
 void NormalMapNode::compile(OSLCompiler& compiler)
 {
        if(space == NODE_NORMAL_MAP_TANGENT) {
-               if(attribute == ustring("")) {
+               if(attribute.empty()) {
                        compiler.parameter("attr_name", ustring("geom:tangent"));
                        compiler.parameter("attr_sign_name", ustring("geom:tangent_sign"));
                }
@@ -5565,7 +5555,7 @@ NODE_DEFINE(TangentNode)
        axis_enum.insert("z", NODE_TANGENT_AXIS_Z);
        SOCKET_ENUM(axis, "Axis", axis_enum, NODE_TANGENT_AXIS_X);
 
-       SOCKET_STRING(attribute, "Attribute", ustring(""));
+       SOCKET_STRING(attribute, "Attribute", ustring());
 
        SOCKET_IN_NORMAL(normal_osl, "NormalIn", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
        SOCKET_OUT_NORMAL(tangent, "Tangent");
@@ -5582,7 +5572,7 @@ void TangentNode::attributes(Shader *shader, AttributeRequestSet *attributes)
 {
        if(shader->has_surface) {
                if(direction_type == NODE_TANGENT_UVMAP) {
-                       if(attribute == ustring(""))
+                       if(attribute.empty())
                                attributes->add(ATTR_STD_UV_TANGENT);
                        else
                                attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
@@ -5600,7 +5590,7 @@ void TangentNode::compile(SVMCompiler& compiler)
        int attr;
 
        if(direction_type == NODE_TANGENT_UVMAP) {
-               if(attribute == ustring(""))
+               if(attribute.empty())
                        attr = compiler.attribute(ATTR_STD_UV_TANGENT);
                else
                        attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str()));
@@ -5618,7 +5608,7 @@ void TangentNode::compile(SVMCompiler& compiler)
 void TangentNode::compile(OSLCompiler& compiler)
 {
        if(direction_type == NODE_TANGENT_UVMAP) {
-               if(attribute == ustring(""))
+               if(attribute.empty())
                        compiler.parameter("attr_name", ustring("geom:tangent"));
                else
                        compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
@@ -5731,7 +5721,7 @@ NODE_DEFINE(VectorDisplacementNode)
        space_enum.insert("world", NODE_NORMAL_MAP_WORLD);
 
        SOCKET_ENUM(space, "Space", space_enum, NODE_NORMAL_MAP_TANGENT);
-       SOCKET_STRING(attribute, "Attribute", ustring(""));
+       SOCKET_STRING(attribute, "Attribute", ustring());
 
        SOCKET_IN_COLOR(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f));
        SOCKET_IN_FLOAT(midlevel, "Midlevel", 0.0f);
@@ -5750,7 +5740,7 @@ VectorDisplacementNode::VectorDisplacementNode()
 void VectorDisplacementNode::attributes(Shader *shader, AttributeRequestSet *attributes)
 {
        if(shader->has_surface && space == NODE_NORMAL_MAP_TANGENT) {
-               if(attribute == ustring("")) {
+               if(attribute.empty()) {
                        attributes->add(ATTR_STD_UV_TANGENT);
                        attributes->add(ATTR_STD_UV_TANGENT_SIGN);
                }
@@ -5774,7 +5764,7 @@ void VectorDisplacementNode::compile(SVMCompiler& compiler)
        int attr = 0, attr_sign = 0;
 
        if(space == NODE_NORMAL_MAP_TANGENT) {
-               if(attribute == ustring("")) {
+               if(attribute.empty()) {
                        attr = compiler.attribute(ATTR_STD_UV_TANGENT);
                        attr_sign = compiler.attribute(ATTR_STD_UV_TANGENT_SIGN);
                }
@@ -5797,7 +5787,7 @@ void VectorDisplacementNode::compile(SVMCompiler& compiler)
 void VectorDisplacementNode::compile(OSLCompiler& compiler)
 {
        if(space == NODE_NORMAL_MAP_TANGENT) {
-               if(attribute == ustring("")) {
+               if(attribute.empty()) {
                        compiler.parameter("attr_name", ustring("geom:tangent"));
                        compiler.parameter("attr_sign_name", ustring("geom:tangent_sign"));
                }
index f664ebf545dab935b56fc2a29ef7b4ad9ae0d65c..bc516af451197b591fc62c85de5c1f1c69d82372 100644 (file)
@@ -82,6 +82,7 @@ public:
        ~ImageTextureNode();
        ShaderNode *clone() const;
        void attributes(Shader *shader, AttributeRequestSet *attributes);
+       bool has_attribute_dependency() { return true; }
 
        ImageManager *image_manager;
        int is_float;
@@ -112,6 +113,7 @@ public:
        ~EnvironmentTextureNode();
        ShaderNode *clone() const;
        void attributes(Shader *shader, AttributeRequestSet *attributes);
+       bool has_attribute_dependency() { return true; }
        virtual int get_group() { return NODE_GROUP_LEVEL_2; }
 
        ImageManager *image_manager;
@@ -257,6 +259,7 @@ public:
        ~PointDensityTextureNode();
        ShaderNode *clone() const;
        void attributes(Shader *shader, AttributeRequestSet *attributes);
+       bool has_attribute_dependency() { return true; }
 
        bool has_spatial_varying() { return true; }
        bool has_object_dependency() { return true; }
@@ -361,6 +364,7 @@ public:
 
        ClosureType get_closure_type() { return distribution; }
        void attributes(Shader *shader, AttributeRequestSet *attributes);
+       bool has_attribute_dependency() { return true; }
 };
 
 class DiffuseBsdfNode : public BsdfNode {
@@ -394,6 +398,7 @@ public:
 
        bool has_integrator_dependency();
        void attributes(Shader *shader, AttributeRequestSet *attributes);
+       bool has_attribute_dependency() { return true; }
 };
 
 class TranslucentBsdfNode : public BsdfNode {
@@ -572,6 +577,7 @@ class GeometryNode : public ShaderNode {
 public:
        SHADER_NODE_CLASS(GeometryNode)
        void attributes(Shader *shader, AttributeRequestSet *attributes);
+       bool has_attribute_dependency() { return true; }
        bool has_spatial_varying() { return true; }
 
        float3 normal_osl;
@@ -581,6 +587,7 @@ class TextureCoordinateNode : public ShaderNode {
 public:
        SHADER_NODE_CLASS(TextureCoordinateNode)
        void attributes(Shader *shader, AttributeRequestSet *attributes);
+       bool has_attribute_dependency() { return true; }
        bool has_spatial_varying() { return true; }
        bool has_object_dependency() { return use_transform; }
 
@@ -594,6 +601,7 @@ class UVMapNode : public ShaderNode {
 public:
        SHADER_NODE_CLASS(UVMapNode)
        void attributes(Shader *shader, AttributeRequestSet *attributes);
+       bool has_attribute_dependency() { return true; }
        bool has_spatial_varying() { return true; }
        virtual int get_group() { return NODE_GROUP_LEVEL_1; }
 
@@ -627,6 +635,7 @@ class ParticleInfoNode : public ShaderNode {
 public:
        SHADER_NODE_CLASS(ParticleInfoNode)
        void attributes(Shader *shader, AttributeRequestSet *attributes);
+       bool has_attribute_dependency() { return true; }
        virtual int get_group() { return NODE_GROUP_LEVEL_1; }
 };
 
@@ -635,6 +644,7 @@ public:
        SHADER_NODE_CLASS(HairInfoNode)
 
        void attributes(Shader *shader, AttributeRequestSet *attributes);
+       bool has_attribute_dependency() { return true; }
        bool has_spatial_varying() { return true; }
        virtual int get_group() { return NODE_GROUP_LEVEL_1; }
        virtual int get_feature() {
@@ -796,6 +806,7 @@ class AttributeNode : public ShaderNode {
 public:
        SHADER_NODE_CLASS(AttributeNode)
        void attributes(Shader *shader, AttributeRequestSet *attributes);
+       bool has_attribute_dependency() { return true; }
        bool has_spatial_varying() { return true; }
 
        ustring attribute;
@@ -993,6 +1004,7 @@ class NormalMapNode : public ShaderNode {
 public:
        SHADER_NODE_CLASS(NormalMapNode)
        void attributes(Shader *shader, AttributeRequestSet *attributes);
+       bool has_attribute_dependency() { return true; }
        bool has_spatial_varying() { return true; }
        virtual int get_group() { return NODE_GROUP_LEVEL_3; }
 
@@ -1007,6 +1019,7 @@ class TangentNode : public ShaderNode {
 public:
        SHADER_NODE_CLASS(TangentNode)
        void attributes(Shader *shader, AttributeRequestSet *attributes);
+       bool has_attribute_dependency() { return true; }
        bool has_spatial_varying() { return true; }
        virtual int get_group() { return NODE_GROUP_LEVEL_3; }
 
@@ -1046,6 +1059,7 @@ class VectorDisplacementNode : public ShaderNode {
 public:
        SHADER_NODE_CLASS(VectorDisplacementNode)
        void attributes(Shader *shader, AttributeRequestSet *attributes);
+       bool has_attribute_dependency() { return true; }
        virtual int get_feature() {
                return NODE_FEATURE_BUMP;
        }
index e03160954bcc084d737a64104d89dcffc30375e5..b981d2b88496682f3fc68b3cedfd61dd32f6c8a8 100644 (file)
@@ -604,9 +604,16 @@ void ObjectManager::device_update_flags(Device *,
        foreach(Object *object, scene->objects) {
                if(object->mesh->has_volume) {
                        object_flag[object_index] |= SD_OBJECT_HAS_VOLUME;
+                       object_flag[object_index] &= ~SD_OBJECT_HAS_VOLUME_ATTRIBUTES;
+
+                       foreach(Attribute& attr, object->mesh->attributes.attributes) {
+                               if(attr.element == ATTR_ELEMENT_VOXEL) {
+                                       object_flag[object_index] |= SD_OBJECT_HAS_VOLUME_ATTRIBUTES;
+                               }
+                       }
                }
                else {
-                       object_flag[object_index] &= ~SD_OBJECT_HAS_VOLUME;
+                       object_flag[object_index] &= ~(SD_OBJECT_HAS_VOLUME|SD_OBJECT_HAS_VOLUME_ATTRIBUTES);
                }
                if(object->is_shadow_catcher) {
                        object_flag[object_index] |= SD_OBJECT_SHADOW_CATCHER;
index 4d066c89b761df086a89308bbb146b0f8c6a7d37..9e931280691d79a25f19617f93b6df7bdca9d86c 100644 (file)
@@ -744,6 +744,10 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath)
                current_shader->has_object_dependency = true;
        }
 
+       if(node->has_attribute_dependency()) {
+               current_shader->has_attribute_dependency = true;
+       }
+
        if(node->has_integrator_dependency()) {
                current_shader->has_integrator_dependency = true;
        }
@@ -991,6 +995,14 @@ void OSLCompiler::parameter_color_array(const char *name, const array<float3>& f
        ss->Parameter(name, type, table.data());
 }
 
+void OSLCompiler::parameter_attribute(const char *name, ustring s)
+{
+       if(Attribute::name_standard(s.c_str()))
+               parameter(name, (string("geom:") + s.c_str()).c_str());
+       else
+               parameter(name, s.c_str());
+}
+
 void OSLCompiler::find_dependencies(ShaderNodeSet& dependencies, ShaderInput *input)
 {
        ShaderNode *node = (input->link)? input->link->parent: NULL;
@@ -1124,6 +1136,7 @@ void OSLCompiler::compile(Scene *scene, OSLGlobals *og, Shader *shader)
                shader->has_surface_spatial_varying = false;
                shader->has_volume_spatial_varying = false;
                shader->has_object_dependency = false;
+               shader->has_attribute_dependency = false;
                shader->has_integrator_dependency = false;
 
                /* generate surface shader */
index 2be1126fdd35dce22bdbec956a90e000bdfd78d2..95e35dd857ba8e9cc34ae93ad4f9c4dca69da20a 100644 (file)
@@ -140,6 +140,8 @@ public:
        void parameter_array(const char *name, const float f[], int arraylen);
        void parameter_color_array(const char *name, const array<float3>& f);
 
+       void parameter_attribute(const char *name, ustring s);
+
        ShaderType output_type() { return current_type; }
 
        bool background;
index a1ebb26eba3b75aee61bd3b778fd7c03cf64757e..578c61a3e7958f6b761e473620fd077fa7d8479d 100644 (file)
@@ -191,6 +191,7 @@ Shader::Shader()
        has_surface_spatial_varying = false;
        has_volume_spatial_varying = false;
        has_object_dependency = false;
+       has_attribute_dependency = false;
        has_integrator_dependency = false;
        has_volume_connected = false;
 
@@ -463,6 +464,8 @@ void ShaderManager::device_update_common(Device *device,
                        flag |= SD_HAS_ONLY_VOLUME;
                if(shader->heterogeneous_volume && shader->has_volume_spatial_varying)
                        flag |= SD_HETEROGENEOUS_VOLUME;
+               if(shader->has_attribute_dependency)
+                       flag |= SD_NEED_ATTRIBUTES;
                if(shader->has_bssrdf_bump)
                        flag |= SD_HAS_BSSRDF_BUMP;
                if(device->info.has_volume_decoupled) {
index 4a48c1347da9fa622b9ea0f0826de3c14b3eda1f..abd483caabc5fd9dfc330544fd90b0d58029d01e 100644 (file)
@@ -121,6 +121,7 @@ public:
        bool has_surface_spatial_varying;
        bool has_volume_spatial_varying;
        bool has_object_dependency;
+       bool has_attribute_dependency;
        bool has_integrator_dependency;
 
        /* displacement */
index b678277433b160db5c4f2fa92f76e3bf90bbf742..c5b4060d5c3c2f707809a78a085376d9eb492a9a 100644 (file)
@@ -399,6 +399,12 @@ uint SVMCompiler::attribute(AttributeStandard std)
        return shader_manager->get_attribute_id(std);
 }
 
+uint SVMCompiler::attribute_standard(ustring name)
+{
+       AttributeStandard std = Attribute::name_standard(name.c_str());
+       return (std)? attribute(std): attribute(name);
+}
+
 bool SVMCompiler::node_skip_input(ShaderNode * /*node*/, ShaderInput *input)
 {
        /* nasty exception .. */
@@ -447,6 +453,10 @@ void SVMCompiler::generate_node(ShaderNode *node, ShaderNodeSet& done)
                current_shader->has_object_dependency = true;
        }
 
+       if(node->has_attribute_dependency()) {
+               current_shader->has_attribute_dependency = true;
+       }
+
        if(node->has_integrator_dependency()) {
                current_shader->has_integrator_dependency = true;
        }
@@ -830,6 +840,7 @@ void SVMCompiler::compile(Scene *scene,
        shader->has_surface_spatial_varying = false;
        shader->has_volume_spatial_varying = false;
        shader->has_object_dependency = false;
+       shader->has_attribute_dependency = false;
        shader->has_integrator_dependency = false;
 
        /* generate bump shader */
index 0e9905957c7a54f3b1e7d816ec4d8d0b22722200..18be0fa9a223239cd2551b23b6538eac377544f4 100644 (file)
@@ -117,6 +117,7 @@ public:
        void add_node(const float4& f);
        uint attribute(ustring name);
        uint attribute(AttributeStandard std);
+       uint attribute_standard(ustring name);
        uint encode_uchar4(uint x, uint y = 0, uint z = 0, uint w = 0);
        uint closure_mix_weight_offset() { return mix_weight_offset; }