Fix for last commit, forgot changes in Cycles itself.
[blender.git] / intern / cycles / blender / blender_shader.cpp
index d915d51dfd8e5d4d1bea967e645447ba96cc31ea..51d8a4da744b1ef0b19ad663e4a6132440d9dc55 100644 (file)
@@ -147,7 +147,7 @@ static void get_tex_mapping(TextureMapping *mapping, BL::TexMapping b_mapping)
        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.type();
+       mapping->type = (TextureMapping::Type)b_mapping.vector_type();
 
        mapping->x_mapping = (TextureMapping::Mapping)b_mapping.mapping_x();
        mapping->y_mapping = (TextureMapping::Mapping)b_mapping.mapping_y();
@@ -162,7 +162,7 @@ static void get_tex_mapping(TextureMapping *mapping, BL::ShaderNodeMapping b_map
        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.type();
+       mapping->type = (TextureMapping::Type)b_mapping.vector_type();
 
        mapping->use_minmax = b_mapping.use_min() || b_mapping.use_max();
 
@@ -172,6 +172,13 @@ static void get_tex_mapping(TextureMapping *mapping, BL::ShaderNodeMapping b_map
                mapping->max = get_float3(b_mapping.max());
 }
 
+static bool is_output_node(BL::Node b_node)
+{
+       return (b_node.is_a(&RNA_ShaderNodeOutputMaterial)
+                   || b_node.is_a(&RNA_ShaderNodeOutputWorld)
+                   || b_node.is_a(&RNA_ShaderNodeOutputLamp));
+}
+
 static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, BL::ShaderNode b_node)
 {
        ShaderNode *node = NULL;
@@ -237,6 +244,12 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
        else if (b_node.is_a(&RNA_ShaderNodeCombineHSV)) {
                node = new CombineHSVNode();
        }
+       else if (b_node.is_a(&RNA_ShaderNodeSeparateXYZ)) {
+               node = new SeparateXYZNode();
+       }
+       else if (b_node.is_a(&RNA_ShaderNodeCombineXYZ)) {
+               node = new CombineXYZNode();
+       }
        else if (b_node.is_a(&RNA_ShaderNodeHueSaturation)) {
                node = new HSVNode();
        }
@@ -280,12 +293,6 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
                
                node = mapping;
        }
-       /* new nodes */
-       else if (b_node.is_a(&RNA_ShaderNodeOutputMaterial)
-             || b_node.is_a(&RNA_ShaderNodeOutputWorld)
-             || b_node.is_a(&RNA_ShaderNodeOutputLamp)) {
-               node = graph->output();
-       }
        else if (b_node.is_a(&RNA_ShaderNodeFresnel)) {
                node = new FresnelNode();
        }
@@ -311,7 +318,23 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
                node = new HoldoutNode();
        }
        else if (b_node.is_a(&RNA_ShaderNodeBsdfAnisotropic)) {
-               node = new WardBsdfNode();
+               BL::ShaderNodeBsdfAnisotropic b_aniso_node(b_node);
+               AnisotropicBsdfNode *aniso = new AnisotropicBsdfNode();
+
+               switch (b_aniso_node.distribution())
+               {
+               case BL::ShaderNodeBsdfAnisotropic::distribution_BECKMANN:
+                       aniso->distribution = ustring("Beckmann");
+                       break;
+               case BL::ShaderNodeBsdfAnisotropic::distribution_GGX:
+                       aniso->distribution = ustring("GGX");
+                       break;
+               case BL::ShaderNodeBsdfAnisotropic::distribution_ASHIKHMIN_SHIRLEY:
+                       aniso->distribution = ustring("Ashikhmin-Shirley");
+                       break;
+               }
+
+               node = aniso;
        }
        else if (b_node.is_a(&RNA_ShaderNodeBsdfDiffuse)) {
                node = new DiffuseBsdfNode();
@@ -322,9 +345,6 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
                SubsurfaceScatteringNode *subsurface = new SubsurfaceScatteringNode();
 
                switch(b_subsurface_node.falloff()) {
-               case BL::ShaderNodeSubsurfaceScattering::falloff_COMPATIBLE:
-                       subsurface->closure = CLOSURE_BSSRDF_COMPATIBLE_ID;
-                       break;
                case BL::ShaderNodeSubsurfaceScattering::falloff_CUBIC:
                        subsurface->closure = CLOSURE_BSSRDF_CUBIC_ID;
                        break;
@@ -349,6 +369,9 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
                case BL::ShaderNodeBsdfGlossy::distribution_GGX:
                        glossy->distribution = ustring("GGX");
                        break;
+               case BL::ShaderNodeBsdfGlossy::distribution_ASHIKHMIN_SHIRLEY:
+                       glossy->distribution = ustring("Ashikhmin-Shirley");
+                       break;
                }
                node = glossy;
        }
@@ -425,11 +448,11 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
        else if (b_node.is_a(&RNA_ShaderNodeAmbientOcclusion)) {
                node = new AmbientOcclusionNode();
        }
-       else if (b_node.is_a(&RNA_ShaderNodeVolumeIsotropic)) {
-               node = new IsotropicVolumeNode();
+       else if (b_node.is_a(&RNA_ShaderNodeVolumeScatter)) {
+               node = new ScatterVolumeNode();
        }
-       else if (b_node.is_a(&RNA_ShaderNodeVolumeTransparent)) {
-               node = new TransparentVolumeNode();
+       else if (b_node.is_a(&RNA_ShaderNodeVolumeAbsorption)) {
+               node = new AbsorptionVolumeNode();
        }
        else if (b_node.is_a(&RNA_ShaderNodeNewGeometry)) {
                node = new GeometryNode();
@@ -548,9 +571,11 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
                        }
 
                        image->animated = b_image_node.image_user().use_auto_refresh();
+                       image->use_alpha = b_image.use_alpha();
                }
                image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()];
                image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()];
+               image->interpolation = (InterpolationType)b_image_node.interpolation();
                image->projection_blend = b_image_node.projection_blend();
                get_tex_mapping(&image->tex_mapping, b_image_node.texture_mapping());
                node = image;
@@ -575,6 +600,8 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
                                env->animated = b_env_node.image_user().use_auto_refresh();
                                env->builtin_data = NULL;
                        }
+
+                       env->use_alpha = b_image.use_alpha();
                }
                env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()];
                env->projection = EnvironmentTextureNode::projection_enum[(int)b_env_node.projection()];
@@ -648,7 +675,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
                BL::ShaderNodeTexSky b_sky_node(b_node);
                SkyTextureNode *sky = new SkyTextureNode();
                sky->type = SkyTextureNode::type_enum[(int)b_sky_node.sky_type()];
-               sky->sun_direction = get_float3(b_sky_node.sun_direction());
+               sky->sun_direction = normalize(get_float3(b_sky_node.sun_direction()));
                sky->turbidity = b_sky_node.turbidity();
                sky->ground_albedo = b_sky_node.ground_albedo();
                get_tex_mapping(&sky->tex_mapping, b_sky_node.texture_mapping());
@@ -669,66 +696,87 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
                tangent->attribute = b_tangent_node.uv_map();
                node = tangent;
        }
+       else if (b_node.is_a(&RNA_ShaderNodeUVMap)) {
+               BL::ShaderNodeUVMap b_uvmap_node(b_node);
+               UVMapNode *uvm = new UVMapNode();
+               uvm->attribute = b_uvmap_node.uv_map();
+               uvm->from_dupli = b_uvmap_node.from_dupli();
+               node = uvm;
+       }
 
-       if(node && node != graph->output())
+       if(node)
                graph->add(node);
 
        return node;
 }
 
+static bool node_use_modified_socket_name(ShaderNode *node)
+{
+       if (node->special_type == SHADER_SPECIAL_TYPE_SCRIPT)
+               return false;
+       
+       return true;
+}
+
 static ShaderInput *node_find_input_by_name(ShaderNode *node, BL::Node b_node, BL::NodeSocket b_socket)
 {
-       BL::Node::inputs_iterator b_input;
        string name = b_socket.name();
-       bool found = false;
-       int counter = 0, total = 0;
        
-       for (b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) {
-               if (b_input->name() == name) {
-                       if (!found)
-                               counter++;
-                       total++;
+       if (node_use_modified_socket_name(node)) {
+               BL::Node::inputs_iterator b_input;
+               bool found = false;
+               int counter = 0, total = 0;
+               
+               for (b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) {
+                       if (b_input->name() == name) {
+                               if (!found)
+                                       counter++;
+                               total++;
+                       }
+                       
+                       if(b_input->ptr.data == b_socket.ptr.data)
+                               found = true;
                }
-
-               if(b_input->ptr.data == b_socket.ptr.data)
-                       found = true;
+               
+               /* rename if needed */
+               if (name == "Shader")
+                       name = "Closure";
+               
+               if (total > 1)
+                       name = string_printf("%s%d", name.c_str(), counter);
        }
        
-       /* rename if needed */
-       if (name == "Shader")
-               name = "Closure";
-       
-       if (total > 1)
-               name = string_printf("%s%d", name.c_str(), counter);
-       
        return node->input(name.c_str());
 }
 
 static ShaderOutput *node_find_output_by_name(ShaderNode *node, BL::Node b_node, BL::NodeSocket b_socket)
 {
-       BL::Node::outputs_iterator b_output;
        string name = b_socket.name();
-       bool found = false;
-       int counter = 0, total = 0;
        
-       for (b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) {
-               if (b_output->name() == name) {
-                       if (!found)
-                               counter++;
-                       total++;
+       if (node_use_modified_socket_name(node)) {
+               BL::Node::outputs_iterator b_output;
+               bool found = false;
+               int counter = 0, total = 0;
+               
+               for (b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) {
+                       if (b_output->name() == name) {
+                               if (!found)
+                                       counter++;
+                               total++;
+                       }
+                       
+                       if(b_output->ptr.data == b_socket.ptr.data)
+                               found = true;
                }
-
-               if(b_output->ptr.data == b_socket.ptr.data)
-                       found = true;
+               
+               /* rename if needed */
+               if (name == "Shader")
+                       name = "Closure";
+               
+               if (total > 1)
+                       name = string_printf("%s%d", name.c_str(), counter);
        }
        
-       /* rename if needed */
-       if (name == "Shader")
-               name = "Closure";
-       
-       if (total > 1)
-               name = string_printf("%s%d", name.c_str(), counter);
-       
        return node->output(name.c_str());
 }
 
@@ -743,6 +791,26 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha
        BL::Node::inputs_iterator b_input;
        BL::Node::outputs_iterator b_output;
 
+       /* find the node to use for output if there are multiple */
+       bool found_active_output = false;
+       BL::ShaderNode output_node(PointerRNA_NULL);
+
+       for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
+               if (is_output_node(*b_node)) {
+                       BL::ShaderNodeOutputMaterial b_output_node(*b_node);
+
+                       if(b_output_node.is_active_output()) {
+                               output_node = b_output_node;
+                               found_active_output = true;
+                               break;
+                       }
+                       else if(!output_node.ptr.data && !found_active_output) {
+                               output_node = b_output_node;
+                       }
+               }
+       }
+
+       /* add nodes */
        for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
                if (b_node->mute() || b_node->is_a(&RNA_NodeReroute)) {
                        /* replace muted node with internal links */
@@ -822,18 +890,35 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha
                        }
                }
                else {
-                       ShaderNode *node = add_node(scene, b_data, b_scene, graph, b_ntree, BL::ShaderNode(*b_node));
+                       ShaderNode *node = NULL;
+
+                       if (is_output_node(*b_node)) {
+                               if (b_node->ptr.data == output_node.ptr.data) {
+                                       node = graph->output();
+                               }
+                       }
+                       else {
+                               node = add_node(scene, b_data, b_scene, graph, b_ntree, BL::ShaderNode(*b_node));
+                       }
                        
                        if(node) {
                                /* map node sockets for linking */
                                for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
                                        ShaderInput *input = node_find_input_by_name(node, *b_node, *b_input);
+                                       if (!input) {
+                                               /* XXX should not happen, report error? */
+                                               continue;
+                                       }
                                        input_map[b_input->ptr.data] = input;
                                        
                                        set_default_value(input, *b_node, *b_input, b_data, b_ntree);
                                }
                                for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
                                        ShaderOutput *output = node_find_output_by_name(node, *b_node, *b_output);
+                                       if (!output) {
+                                               /* XXX should not happen, report error? */
+                                               continue;
+                                       }
                                        output_map[b_output->ptr.data] = output;
                                }
                        }
@@ -910,7 +995,8 @@ void BlenderSync::sync_materials(bool update_all)
                        PointerRNA cmat = RNA_pointer_get(&b_mat->ptr, "cycles");
                        shader->use_mis = get_boolean(cmat, "sample_as_light");
                        shader->use_transparent_shadow = get_boolean(cmat, "use_transparent_shadow");
-                       shader->homogeneous_volume = get_boolean(cmat, "homogeneous_volume");
+                       shader->heterogeneous_volume = !get_boolean(cmat, "homogeneous_volume");
+                       shader->volume_sampling_method = RNA_enum_get(&cmat, "volume_sampling");
 
                        shader->set_graph(graph);
                        shader->tag_update(scene);
@@ -936,6 +1022,11 @@ void BlenderSync::sync_world(bool update_all)
                        BL::ShaderNodeTree b_ntree(b_world.node_tree());
 
                        add_nodes(scene, b_data, b_scene, graph, b_ntree);
+                       
+                       /* volume */
+                       PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles");
+                       shader->heterogeneous_volume = !get_boolean(cworld, "homogeneous_volume");
+                       shader->volume_sampling_method = RNA_enum_get(&cworld, "volume_sampling");
                }
                else if(b_world) {
                        ShaderNode *closure, *out;
@@ -972,6 +1063,7 @@ void BlenderSync::sync_world(bool update_all)
 
                shader->set_graph(graph);
                shader->tag_update(scene);
+               background->tag_update(scene);
        }
 
        PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");