Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/blender/blender_shader.cpp')
-rw-r--r--intern/cycles/blender/blender_shader.cpp702
1 files changed, 702 insertions, 0 deletions
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
new file mode 100644
index 00000000000..6f78fe1f0d4
--- /dev/null
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -0,0 +1,702 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "background.h"
+#include "graph.h"
+#include "light.h"
+#include "nodes.h"
+#include "scene.h"
+#include "shader.h"
+
+#include "blender_sync.h"
+#include "blender_util.h"
+
+#include "util_debug.h"
+
+CCL_NAMESPACE_BEGIN
+
+typedef map<void*, ShaderNode*> PtrNodeMap;
+typedef pair<ShaderNode*, std::string> SocketPair;
+typedef map<void*, SocketPair> PtrSockMap;
+
+/* Find */
+
+void BlenderSync::find_shader(BL::ID id, vector<uint>& used_shaders)
+{
+ Shader *shader = shader_map.find(id);
+
+ for(size_t i = 0; i < scene->shaders.size(); i++) {
+ if(scene->shaders[i] == shader) {
+ used_shaders.push_back(i);
+ break;
+ }
+ }
+}
+
+/* Graph */
+
+static BL::NodeSocket get_node_input(BL::Node *b_group_node, BL::NodeSocket b_in)
+{
+ if(b_group_node) {
+
+ BL::NodeTree b_ntree = BL::NodeGroup(*b_group_node).node_tree();
+ BL::NodeTree::links_iterator b_link;
+
+ for(b_ntree.links.begin(b_link); b_link != b_ntree.links.end(); ++b_link) {
+ if(b_link->to_socket().ptr.data == b_in.ptr.data) {
+ BL::Node::inputs_iterator b_gin;
+
+ for(b_group_node->inputs.begin(b_gin); b_gin != b_group_node->inputs.end(); ++b_gin)
+ if(b_gin->group_socket().ptr.data == b_link->from_socket().ptr.data)
+ return *b_gin;
+
+ }
+ }
+ }
+
+ return b_in;
+}
+
+static BL::NodeSocket get_node_output(BL::Node b_node, const string& name)
+{
+ BL::Node::outputs_iterator b_out;
+
+ for(b_node.outputs.begin(b_out); b_out != b_node.outputs.end(); ++b_out)
+ if(b_out->name() == name)
+ return *b_out;
+
+ assert(0);
+
+ return *b_out;
+}
+
+static float3 get_node_output_rgba(BL::Node b_node, const string& name)
+{
+ BL::NodeSocketRGBA sock(get_node_output(b_node, name));
+ return get_float3(sock.default_value());
+}
+
+static float get_node_output_value(BL::Node b_node, const string& name)
+{
+ BL::NodeSocketFloatNone sock(get_node_output(b_node, name));
+ return sock.default_value();
+}
+
+static void get_tex_mapping(TextureMapping *mapping, BL::TexMapping b_mapping)
+{
+ mapping->translation = get_float3(b_mapping.location());
+ mapping->rotation = get_float3(b_mapping.rotation())*(M_PI/180.0f); /* in degrees! */
+ mapping->scale = get_float3(b_mapping.scale());
+
+ mapping->x_mapping = (TextureMapping::Mapping)b_mapping.mapping_x();
+ mapping->y_mapping = (TextureMapping::Mapping)b_mapping.mapping_y();
+ mapping->z_mapping = (TextureMapping::Mapping)b_mapping.mapping_z();
+}
+
+static ShaderNode *add_node(BL::BlendData b_data, ShaderGraph *graph, BL::Node *b_group_node, BL::ShaderNode b_node)
+{
+ ShaderNode *node = NULL;
+
+ switch(b_node.type()) {
+ /* not supported */
+ case BL::ShaderNode::type_CAMERA: break;
+ case BL::ShaderNode::type_COMBRGB: break;
+ case BL::ShaderNode::type_CURVE_RGB: break;
+ case BL::ShaderNode::type_CURVE_VEC: break;
+ case BL::ShaderNode::type_GEOMETRY: break;
+ case BL::ShaderNode::type_HUE_SAT: break;
+ case BL::ShaderNode::type_INVERT: break;
+ case BL::ShaderNode::type_MATERIAL: break;
+ case BL::ShaderNode::type_MATERIAL_EXT: break;
+ case BL::ShaderNode::type_NORMAL: break;
+ case BL::ShaderNode::type_OUTPUT: break;
+ case BL::ShaderNode::type_SCRIPT: break;
+ case BL::ShaderNode::type_SEPRGB: break;
+ case BL::ShaderNode::type_SQUEEZE: break;
+ case BL::ShaderNode::type_TEXTURE: break;
+ case BL::ShaderNode::type_VALTORGB: break;
+ /* handled outside this function */
+ case BL::ShaderNode::type_GROUP: break;
+ /* existing blender nodes */
+ case BL::ShaderNode::type_RGB: {
+ ColorNode *color = new ColorNode();
+ color->value = get_node_output_rgba(b_node, "Color");
+ node = color;
+ break;
+ }
+ case BL::ShaderNode::type_VALUE: {
+ ValueNode *value = new ValueNode();
+ value->value = get_node_output_value(b_node, "Value");
+ node = value;
+ break;
+ }
+ case BL::ShaderNode::type_MIX_RGB: {
+ BL::ShaderNodeMixRGB b_mix_node(b_node);
+ MixNode *mix = new MixNode();
+ mix->type = MixNode::type_enum[b_mix_node.blend_type()];
+ node = mix;
+ break;
+ }
+ case BL::ShaderNode::type_RGBTOBW: {
+ node = new ConvertNode(SHADER_SOCKET_COLOR, SHADER_SOCKET_FLOAT);
+ break;
+ }
+ case BL::ShaderNode::type_MATH: {
+ BL::ShaderNodeMath b_math_node(b_node);
+ MathNode *math = new MathNode();
+ math->type = MathNode::type_enum[b_math_node.operation()];
+ node = math;
+ break;
+ }
+ case BL::ShaderNode::type_VECT_MATH: {
+ BL::ShaderNodeVectorMath b_vector_math_node(b_node);
+ VectorMathNode *vmath = new VectorMathNode();
+ vmath->type = VectorMathNode::type_enum[b_vector_math_node.operation()];
+ node = vmath;
+ break;
+ }
+ case BL::ShaderNode::type_MAPPING: {
+ BL::ShaderNodeMapping b_mapping_node(b_node);
+ MappingNode *mapping = new MappingNode();
+
+ get_tex_mapping(&mapping->tex_mapping, b_mapping_node.mapping());
+
+ node = mapping;
+ break;
+ }
+
+ /* new nodes */
+ case BL::ShaderNode::type_OUTPUT_MATERIAL:
+ case BL::ShaderNode::type_OUTPUT_WORLD:
+ case BL::ShaderNode::type_OUTPUT_LAMP: {
+ node = graph->output();
+ break;
+ }
+ case BL::ShaderNode::type_FRESNEL: {
+ node = new FresnelNode();
+ break;
+ }
+ case BL::ShaderNode::type_LAYER_WEIGHT: {
+ node = new LayerWeightNode();
+ break;
+ }
+ case BL::ShaderNode::type_ADD_SHADER: {
+ node = new AddClosureNode();
+ break;
+ }
+ case BL::ShaderNode::type_MIX_SHADER: {
+ node = new MixClosureNode();
+ break;
+ }
+ case BL::ShaderNode::type_ATTRIBUTE: {
+ BL::ShaderNodeAttribute b_attr_node(b_node);
+ AttributeNode *attr = new AttributeNode();
+ attr->attribute = b_attr_node.attribute_name();
+ node = attr;
+ break;
+ }
+ case BL::ShaderNode::type_BACKGROUND: {
+ node = new BackgroundNode();
+ break;
+ }
+ case BL::ShaderNode::type_HOLDOUT: {
+ node = new HoldoutNode();
+ break;
+ }
+ case BL::ShaderNode::type_BSDF_DIFFUSE: {
+ node = new DiffuseBsdfNode();
+ break;
+ }
+ case BL::ShaderNode::type_BSDF_GLOSSY: {
+ BL::ShaderNodeBsdfGlossy b_glossy_node(b_node);
+ GlossyBsdfNode *glossy = new GlossyBsdfNode();
+
+ switch(b_glossy_node.distribution()) {
+ case BL::ShaderNodeBsdfGlossy::distribution_SHARP:
+ glossy->distribution = ustring("Sharp");
+ break;
+ case BL::ShaderNodeBsdfGlossy::distribution_BECKMANN:
+ glossy->distribution = ustring("Beckmann");
+ break;
+ case BL::ShaderNodeBsdfGlossy::distribution_GGX:
+ glossy->distribution = ustring("GGX");
+ break;
+ }
+ node = glossy;
+ break;
+ }
+ case BL::ShaderNode::type_BSDF_GLASS: {
+ BL::ShaderNodeBsdfGlass b_glass_node(b_node);
+ GlassBsdfNode *glass = new GlassBsdfNode();
+ switch(b_glass_node.distribution()) {
+ case BL::ShaderNodeBsdfGlass::distribution_SHARP:
+ glass->distribution = ustring("Sharp");
+ break;
+ case BL::ShaderNodeBsdfGlass::distribution_BECKMANN:
+ glass->distribution = ustring("Beckmann");
+ break;
+ case BL::ShaderNodeBsdfGlass::distribution_GGX:
+ glass->distribution = ustring("GGX");
+ break;
+ }
+ node = glass;
+ break;
+ }
+ case BL::ShaderNode::type_BSDF_TRANSLUCENT: {
+ node = new TranslucentBsdfNode();
+ break;
+ }
+ case BL::ShaderNode::type_BSDF_TRANSPARENT: {
+ node = new TransparentBsdfNode();
+ break;
+ }
+ case BL::ShaderNode::type_BSDF_VELVET: {
+ node = new VelvetBsdfNode();
+ break;
+ }
+ case BL::ShaderNode::type_EMISSION: {
+ node = new EmissionNode();
+ break;
+ }
+ case BL::ShaderNode::type_VOLUME_ISOTROPIC: {
+ node = new IsotropicVolumeNode();
+ break;
+ }
+ case BL::ShaderNode::type_VOLUME_TRANSPARENT: {
+ node = new TransparentVolumeNode();
+ break;
+ }
+ case BL::ShaderNode::type_NEW_GEOMETRY: {
+ node = new GeometryNode();
+ break;
+ }
+ case BL::ShaderNode::type_LIGHT_PATH: {
+ node = new LightPathNode();
+ break;
+ }
+ case BL::ShaderNode::type_TEX_IMAGE: {
+ BL::ShaderNodeTexImage b_image_node(b_node);
+ BL::Image b_image(b_image_node.image());
+ ImageTextureNode *image = new ImageTextureNode();
+ /* todo: handle generated/builtin images */
+ if(b_image)
+ image->filename = blender_absolute_path(b_data, b_image, b_image.filepath());
+ image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()];
+ get_tex_mapping(&image->tex_mapping, b_image_node.texture_mapping());
+ node = image;
+ break;
+ }
+ case BL::ShaderNode::type_TEX_ENVIRONMENT: {
+ BL::ShaderNodeTexEnvironment b_env_node(b_node);
+ BL::Image b_image(b_env_node.image());
+ EnvironmentTextureNode *env = new EnvironmentTextureNode();
+ if(b_image)
+ env->filename = blender_absolute_path(b_data, b_image, b_image.filepath());
+ env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()];
+ get_tex_mapping(&env->tex_mapping, b_env_node.texture_mapping());
+ node = env;
+ break;
+ }
+ case BL::ShaderNode::type_TEX_GRADIENT: {
+ BL::ShaderNodeTexGradient b_gradient_node(b_node);
+ GradientTextureNode *gradient = new GradientTextureNode();
+ gradient->type = GradientTextureNode::type_enum[(int)b_gradient_node.gradient_type()];
+ get_tex_mapping(&gradient->tex_mapping, b_gradient_node.texture_mapping());
+ node = gradient;
+ break;
+ }
+ case BL::ShaderNode::type_TEX_VORONOI: {
+ BL::ShaderNodeTexVoronoi b_voronoi_node(b_node);
+ VoronoiTextureNode *voronoi = new VoronoiTextureNode();
+ voronoi->coloring = VoronoiTextureNode::coloring_enum[(int)b_voronoi_node.coloring()];
+ get_tex_mapping(&voronoi->tex_mapping, b_voronoi_node.texture_mapping());
+ node = voronoi;
+ break;
+ }
+ case BL::ShaderNode::type_TEX_MAGIC: {
+ BL::ShaderNodeTexMagic b_magic_node(b_node);
+ MagicTextureNode *magic = new MagicTextureNode();
+ magic->depth = b_magic_node.turbulence_depth();
+ get_tex_mapping(&magic->tex_mapping, b_magic_node.texture_mapping());
+ node = magic;
+ break;
+ }
+ case BL::ShaderNode::type_TEX_WAVE: {
+ BL::ShaderNodeTexWave b_wave_node(b_node);
+ WaveTextureNode *wave = new WaveTextureNode();
+ wave->type = WaveTextureNode::type_enum[(int)b_wave_node.wave_type()];
+ get_tex_mapping(&wave->tex_mapping, b_wave_node.texture_mapping());
+ node = wave;
+ break;
+ }
+ case BL::ShaderNode::type_TEX_NOISE: {
+ BL::ShaderNodeTexNoise b_noise_node(b_node);
+ NoiseTextureNode *noise = new NoiseTextureNode();
+ get_tex_mapping(&noise->tex_mapping, b_noise_node.texture_mapping());
+ node = noise;
+ break;
+ }
+ case BL::ShaderNode::type_TEX_MUSGRAVE: {
+ BL::ShaderNodeTexMusgrave b_musgrave_node(b_node);
+ MusgraveTextureNode *musgrave = new MusgraveTextureNode();
+ musgrave->type = MusgraveTextureNode::type_enum[(int)b_musgrave_node.musgrave_type()];
+ get_tex_mapping(&musgrave->tex_mapping, b_musgrave_node.texture_mapping());
+ node = musgrave;
+ break;
+ }
+ case BL::ShaderNode::type_TEX_COORD: {
+ node = new TextureCoordinateNode();;
+ break;
+ }
+ case BL::ShaderNode::type_TEX_SKY: {
+ BL::ShaderNodeTexSky b_sky_node(b_node);
+ SkyTextureNode *sky = new SkyTextureNode();
+ sky->sun_direction = get_float3(b_sky_node.sun_direction());
+ sky->turbidity = b_sky_node.turbidity();
+ get_tex_mapping(&sky->tex_mapping, b_sky_node.texture_mapping());
+ node = sky;
+ break;
+ }
+ }
+
+ if(node && node != graph->output())
+ graph->add(node);
+
+ return node;
+}
+
+static SocketPair node_socket_map_pair(PtrNodeMap& node_map, BL::Node b_node, BL::NodeSocket b_socket)
+{
+ BL::Node::inputs_iterator b_input;
+ BL::Node::outputs_iterator b_output;
+ string name = b_socket.name();
+ bool found = false;
+ int counter = 0, total = 0;
+
+ /* find in inputs */
+ 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(!found) {
+ /* find in outputs */
+ found = false;
+ 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;
+ }
+ }
+
+ /* rename if needed */
+ if(name == "Shader")
+ name = "Closure";
+
+ if(total > 1)
+ name = string_printf("%s%d", name.c_str(), counter);
+
+ return SocketPair(node_map[b_node.ptr.data], name);
+}
+
+static void add_nodes(BL::BlendData b_data, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, BL::Node *b_group_node, PtrSockMap& sockets_map)
+{
+ /* add nodes */
+ BL::ShaderNodeTree::nodes_iterator b_node;
+ PtrNodeMap node_map;
+ map<void*, PtrSockMap> node_groups;
+
+ for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
+ if(b_node->is_a(&RNA_NodeGroup)) {
+ BL::NodeGroup b_gnode(*b_node);
+ BL::ShaderNodeTree b_group_ntree(b_gnode.node_tree());
+
+ node_groups[b_node->ptr.data] = PtrSockMap();
+ add_nodes(b_data, graph, b_group_ntree, &b_gnode, node_groups[b_node->ptr.data]);
+ }
+ else {
+ ShaderNode *node = add_node(b_data, graph, b_group_node, BL::ShaderNode(*b_node));
+
+ if(node) {
+ BL::Node::inputs_iterator b_input;
+ BL::Node::outputs_iterator b_output;
+
+ node_map[b_node->ptr.data] = node;
+
+ for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
+ SocketPair pair = node_socket_map_pair(node_map, *b_node, *b_input);
+ ShaderInput *input = pair.first->input(pair.second.c_str());
+ BL::NodeSocket sock(get_node_input(b_group_node, *b_input));
+
+ assert(input);
+
+ /* copy values for non linked inputs */
+ switch(input->type) {
+ case SHADER_SOCKET_FLOAT: {
+ BL::NodeSocketFloatNone value_sock(sock);
+ input->set(value_sock.default_value());
+ break;
+ }
+ case SHADER_SOCKET_COLOR: {
+ BL::NodeSocketRGBA rgba_sock(sock);
+ input->set(get_float3(rgba_sock.default_value()));
+ break;
+ }
+ case SHADER_SOCKET_NORMAL:
+ case SHADER_SOCKET_POINT:
+ case SHADER_SOCKET_VECTOR: {
+ BL::NodeSocketVectorNone vec_sock(sock);
+ input->set(get_float3(vec_sock.default_value()));
+ break;
+ }
+ case SHADER_SOCKET_CLOSURE:
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /* connect nodes */
+ BL::NodeTree::links_iterator b_link;
+
+ for(b_ntree.links.begin(b_link); b_link != b_ntree.links.end(); ++b_link) {
+ /* get blender link data */
+ BL::Node b_from_node = b_link->from_node();
+ BL::Node b_to_node = b_link->to_node();
+
+ BL::NodeSocket b_from_sock = b_link->from_socket();
+ BL::NodeSocket b_to_sock = b_link->to_socket();
+
+ /* if link with group socket, add to map so we can connect it later */
+ if(b_group_node) {
+ if(!b_from_node) {
+ sockets_map[b_from_sock.ptr.data] =
+ node_socket_map_pair(node_map, b_to_node, b_to_sock);
+
+ continue;
+ }
+ else if(!b_to_node) {
+ sockets_map[b_to_sock.ptr.data] =
+ node_socket_map_pair(node_map, b_from_node, b_from_sock);
+
+ continue;
+ }
+ }
+
+ SocketPair from_pair, to_pair;
+
+ /* from sock */
+ if(b_from_node.is_a(&RNA_NodeGroup)) {
+ /* group node */
+ BL::NodeSocket group_sock = b_from_sock.group_socket();
+ from_pair = node_groups[b_from_node.ptr.data][group_sock.ptr.data];
+ }
+ else {
+ /* regular node */
+ from_pair = node_socket_map_pair(node_map, b_from_node, b_from_sock);
+ }
+
+ /* to sock */
+ if(b_to_node.is_a(&RNA_NodeGroup)) {
+ /* group node */
+ BL::NodeSocket group_sock = b_to_sock.group_socket();
+ to_pair = node_groups[b_to_node.ptr.data][group_sock.ptr.data];
+ }
+ else {
+ /* regular node */
+ to_pair = node_socket_map_pair(node_map, b_to_node, b_to_sock);
+ }
+
+ /* in case of groups there may not actually be a node inside the group
+ that the group socket connects to, so from_node or to_node may be NULL */
+ if(from_pair.first && to_pair.first) {
+ ShaderOutput *output = from_pair.first->output(from_pair.second.c_str());
+ ShaderInput *input = to_pair.first->input(to_pair.second.c_str());
+
+ graph->connect(output, input);
+ }
+ }
+}
+
+/* Sync Materials */
+
+void BlenderSync::sync_materials()
+{
+ shader_map.set_default(scene->shaders[scene->default_surface]);
+
+ /* material loop */
+ BL::BlendData::materials_iterator b_mat;
+
+ for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat) {
+ Shader *shader;
+
+ /* test if we need to sync */
+ if(shader_map.sync(&shader, *b_mat)) {
+ ShaderGraph *graph = new ShaderGraph();
+
+ shader->name = b_mat->name().c_str();
+
+ /* create nodes */
+ if(b_mat->use_nodes() && b_mat->node_tree()) {
+ PtrSockMap sock_to_node;
+ BL::ShaderNodeTree b_ntree(b_mat->node_tree());
+
+ add_nodes(b_data, graph, b_ntree, NULL, sock_to_node);
+ }
+ else {
+ ShaderNode *closure, *out;
+
+ closure = graph->add(new DiffuseBsdfNode());
+ closure->input("Color")->value = get_float3(b_mat->diffuse_color());
+ out = graph->output();
+
+ graph->connect(closure->output("BSDF"), out->input("Surface"));
+ }
+
+ /* settings */
+ PointerRNA cmat = RNA_pointer_get(&b_mat->ptr, "cycles");
+ shader->sample_as_light = get_boolean(cmat, "sample_as_light");
+ shader->homogeneous_volume = get_boolean(cmat, "homogeneous_volume");
+
+ shader->set_graph(graph);
+ shader->tag_update(scene);
+ }
+ }
+}
+
+/* Sync World */
+
+void BlenderSync::sync_world()
+{
+ Background *background = scene->background;
+ Background prevbackground = *background;
+
+ BL::World b_world = b_scene.world();
+
+ if(world_recalc || b_world.ptr.data != world_map) {
+ Shader *shader = scene->shaders[scene->default_background];
+ ShaderGraph *graph = new ShaderGraph();
+
+ /* create nodes */
+ if(b_world && b_world.use_nodes() && b_world.node_tree()) {
+ PtrSockMap sock_to_node;
+ BL::ShaderNodeTree b_ntree(b_world.node_tree());
+
+ add_nodes(b_data, graph, b_ntree, NULL, sock_to_node);
+ }
+ else if(b_world) {
+ ShaderNode *closure, *out;
+
+ closure = graph->add(new BackgroundNode());
+ closure->input("Color")->value = get_float3(b_world.horizon_color());
+ out = graph->output();
+
+ graph->connect(closure->output("Background"), out->input("Surface"));
+ }
+
+ shader->set_graph(graph);
+ shader->tag_update(scene);
+ }
+
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+ background->transparent = get_boolean(cscene, "film_transparent");
+
+ if(background->modified(prevbackground))
+ background->tag_update(scene);
+
+ world_map = b_world.ptr.data;
+ world_recalc = false;
+}
+
+/* Sync Lamps */
+
+void BlenderSync::sync_lamps()
+{
+ shader_map.set_default(scene->shaders[scene->default_light]);
+
+ /* lamp loop */
+ BL::BlendData::lamps_iterator b_lamp;
+
+ for(b_data.lamps.begin(b_lamp); b_lamp != b_data.lamps.end(); ++b_lamp) {
+ Shader *shader;
+
+ /* test if we need to sync */
+ if(shader_map.sync(&shader, *b_lamp)) {
+ ShaderGraph *graph = new ShaderGraph();
+
+ /* create nodes */
+ if(b_lamp->use_nodes() && b_lamp->node_tree()) {
+ shader->name = b_lamp->name().c_str();
+
+ PtrSockMap sock_to_node;
+ BL::ShaderNodeTree b_ntree(b_lamp->node_tree());
+
+ add_nodes(b_data, graph, b_ntree, NULL, sock_to_node);
+ }
+ else {
+ ShaderNode *closure, *out;
+ float strength = 1.0f;
+
+ if(b_lamp->type() == BL::Lamp::type_POINT ||
+ b_lamp->type() == BL::Lamp::type_SPOT ||
+ b_lamp->type() == BL::Lamp::type_AREA)
+ strength = 100.0f;
+
+ closure = graph->add(new EmissionNode());
+ closure->input("Color")->value = get_float3(b_lamp->color());
+ closure->input("Strength")->value.x = strength;
+ out = graph->output();
+
+ graph->connect(closure->output("Emission"), out->input("Surface"));
+ }
+
+ shader->set_graph(graph);
+ shader->tag_update(scene);
+ }
+ }
+}
+
+void BlenderSync::sync_shaders()
+{
+ shader_map.pre_sync();
+
+ sync_world();
+ sync_lamps();
+ sync_materials();
+
+ /* false = don't delete unused shaders, not supported */
+ shader_map.post_sync(false);
+}
+
+CCL_NAMESPACE_END
+