void BlenderSync::sync_world(bool update_all) { Background *background = scene->background; Background prevbackground = *background; BL::World b_world = b_scene.world(); if(world_recalc || update_all || 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()) { BL::ShaderNodeTree b_ntree(b_world.node_tree()); add_nodes(scene, b_data, b_scene, graph, b_ntree); } 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")); } /* AO */ if(b_world) { BL::WorldLighting b_light = b_world.light_settings(); if(b_light.use_ambient_occlusion()) background->ao_factor = b_light.ao_factor(); else background->ao_factor = 0.0f; background->ao_distance = b_light.distance(); } shader->set_graph(graph); shader->tag_update(scene); } PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); /* when doing preview render check for BI's transparency settings, * this is so because bledner's preview render routines are not able * to tweak all cycles's settings depending on different circumstances */ if(b_engine.is_preview() == false) background->transparent = get_boolean(cscene, "film_transparent"); else background->transparent = b_scene.render().alpha_mode() == BL::RenderSettings::alpha_mode_TRANSPARENT; background->use = render_layer.use_background; if(background->modified(prevbackground)) background->tag_update(scene); }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Add default shaders to scene, to use as default for things that don't have any shader assigned explicitly ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ShaderManager::add_default(Scene *scene) { // Add default surface material ShaderGraph *graph = new ShaderGraph(); graph->add(new ShaderNode(new ::OctaneEngine::OctaneDiffuseMaterial())); Shader *shader = new Shader(); shader->name = "default_surface"; shader->graph = graph; scene->shaders.push_back(shader); scene->default_surface = scene->shaders.size() - 1; } //add_default()
void BlenderSync::sync_world(bool update_all) { Background *background = scene->background; Background prevbackground = *background; BL::World b_world = b_scene.world(); if(world_recalc || update_all || 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(scene, b_data, b_scene, graph, b_ntree, 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")); } /* AO */ if(b_world) { BL::WorldLighting b_light = b_world.light_settings(); if(b_light.use_ambient_occlusion()) background->ao_factor = b_light.ao_factor(); else background->ao_factor = 0.0f; background->ao_distance = b_light.distance(); } shader->set_graph(graph); shader->tag_update(scene); } PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); background->transparent = get_boolean(cscene, "film_transparent"); background->use = render_layer.use_background; if(background->modified(prevbackground)) background->tag_update(scene); }
void BlenderSync::sync_lamps(bool update_all) { 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) || update_all) { 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(scene, b_data, b_scene, graph, b_ntree, 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_materials(bool update_all) { 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) || update_all) { ShaderGraph *graph = new ShaderGraph(); shader->name = b_mat->name().c_str(); shader->pass_id = b_mat->pass_index(); /* create nodes */ if(b_mat->use_nodes() && b_mat->node_tree()) { BL::ShaderNodeTree b_ntree(b_mat->node_tree()); add_nodes(scene, b_engine, b_data, b_scene, !preview, graph, b_ntree); } 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->use_mis = get_boolean(cmat, "sample_as_light"); shader->use_transparent_shadow = get_boolean(cmat, "use_transparent_shadow"); shader->heterogeneous_volume = !get_boolean(cmat, "homogeneous_volume"); shader->volume_sampling_method = (VolumeSampling)RNA_enum_get(&cmat, "volume_sampling"); shader->volume_interpolation_method = (VolumeInterpolation)RNA_enum_get(&cmat, "volume_interpolation"); shader->set_graph(graph); shader->tag_update(scene); } } }
void BlenderSync::sync_lamps(bool update_all) { shader_map.set_default(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) || update_all) { ShaderGraph *graph = new ShaderGraph(); /* create nodes */ if(b_lamp->use_nodes() && b_lamp->node_tree()) { shader->name = b_lamp->name().c_str(); BL::ShaderNodeTree b_ntree(b_lamp->node_tree()); add_nodes(scene, b_engine, b_data, b_scene, !preview, graph, b_ntree); } else { 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; } EmissionNode *emission = new EmissionNode(); emission->color = get_float3(b_lamp->color()); emission->strength = strength; graph->add(emission); ShaderNode *out = graph->output(); graph->connect(emission->output("Emission"), out->input("Surface")); } shader->set_graph(graph); shader->tag_update(scene); } } }
static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pugi::xml_node graph_node) { ShaderGraph *graph = new ShaderGraph(); map<string, ShaderNode*> nodemap; nodemap["output"] = graph->output(); for(pugi::xml_node node = graph_node.first_child(); node; node = node.next_sibling()) { ShaderNode *snode = NULL; if(string_iequals(node.name(), "image_texture")) { ImageTextureNode *img = new ImageTextureNode(); xml_read_string(&img->filename, node, "src"); img->filename = path_join(state.base, img->filename); xml_read_enum(&img->color_space, ImageTextureNode::color_space_enum, node, "color_space"); xml_read_enum(&img->projection, ImageTextureNode::projection_enum, node, "projection"); xml_read_float(&img->projection_blend, node, "projection_blend"); snode = img; } else if(string_iequals(node.name(), "environment_texture")) { EnvironmentTextureNode *env = new EnvironmentTextureNode(); xml_read_string(&env->filename, node, "src"); env->filename = path_join(state.base, env->filename); xml_read_enum(&env->color_space, EnvironmentTextureNode::color_space_enum, node, "color_space"); xml_read_enum(&env->projection, EnvironmentTextureNode::projection_enum, node, "projection"); snode = env; } else if(string_iequals(node.name(), "osl_shader")) { OSLScriptNode *osl = new OSLScriptNode(); /* Source */ xml_read_string(&osl->filepath, node, "src"); if(path_is_relative(osl->filepath)) { osl->filepath = path_join(state.base, osl->filepath); } /* Generate inputs/outputs from node sockets * * Note: ShaderInput/ShaderOutput store shallow string copies only! * Socket names must be stored in the extra lists instead. */ /* read input values */ for(pugi::xml_node param = node.first_child(); param; param = param.next_sibling()) { if (string_iequals(param.name(), "input")) { string name; if (!xml_read_string(&name, param, "name")) continue; ShaderSocketType type = xml_read_socket_type(param, "type"); if (type == SHADER_SOCKET_UNDEFINED) continue; osl->input_names.push_back(ustring(name)); osl->add_input(osl->input_names.back().c_str(), type); } else if (string_iequals(param.name(), "output")) { string name; if (!xml_read_string(&name, param, "name")) continue; ShaderSocketType type = xml_read_socket_type(param, "type"); if (type == SHADER_SOCKET_UNDEFINED) continue; osl->output_names.push_back(ustring(name)); osl->add_output(osl->output_names.back().c_str(), type); } } snode = osl; } else if(string_iequals(node.name(), "sky_texture")) { SkyTextureNode *sky = new SkyTextureNode(); xml_read_enum(&sky->type, SkyTextureNode::type_enum, node, "type"); xml_read_float3(&sky->sun_direction, node, "sun_direction"); xml_read_float(&sky->turbidity, node, "turbidity"); xml_read_float(&sky->ground_albedo, node, "ground_albedo"); snode = sky; } else if(string_iequals(node.name(), "noise_texture")) { snode = new NoiseTextureNode(); } else if(string_iequals(node.name(), "checker_texture")) { snode = new CheckerTextureNode(); } else if(string_iequals(node.name(), "brick_texture")) { BrickTextureNode *brick = new BrickTextureNode(); xml_read_float(&brick->offset, node, "offset"); xml_read_int(&brick->offset_frequency, node, "offset_frequency"); xml_read_float(&brick->squash, node, "squash"); xml_read_int(&brick->squash_frequency, node, "squash_frequency"); snode = brick; } else if(string_iequals(node.name(), "gradient_texture")) { GradientTextureNode *blend = new GradientTextureNode(); xml_read_enum(&blend->type, GradientTextureNode::type_enum, node, "type"); snode = blend; } else if(string_iequals(node.name(), "voronoi_texture")) { VoronoiTextureNode *voronoi = new VoronoiTextureNode(); xml_read_enum(&voronoi->coloring, VoronoiTextureNode::coloring_enum, node, "coloring"); snode = voronoi; } else if(string_iequals(node.name(), "musgrave_texture")) { MusgraveTextureNode *musgrave = new MusgraveTextureNode(); xml_read_enum(&musgrave->type, MusgraveTextureNode::type_enum, node, "type"); snode = musgrave; } else if(string_iequals(node.name(), "magic_texture")) { MagicTextureNode *magic = new MagicTextureNode(); xml_read_int(&magic->depth, node, "depth"); snode = magic; } else if(string_iequals(node.name(), "noise_texture")) { NoiseTextureNode *dist = new NoiseTextureNode(); snode = dist; } else if(string_iequals(node.name(), "wave_texture")) { WaveTextureNode *wave = new WaveTextureNode(); xml_read_enum(&wave->type, WaveTextureNode::type_enum, node, "type"); snode = wave; } else if(string_iequals(node.name(), "normal")) { NormalNode *normal = new NormalNode(); xml_read_float3(&normal->direction, node, "direction"); snode = normal; } else if(string_iequals(node.name(), "mapping")) { snode = new MappingNode(); } else if(string_iequals(node.name(), "ward_bsdf")) { snode = new WardBsdfNode(); } else if(string_iequals(node.name(), "diffuse_bsdf")) { snode = new DiffuseBsdfNode(); } else if(string_iequals(node.name(), "translucent_bsdf")) { snode = new TranslucentBsdfNode(); } else if(string_iequals(node.name(), "transparent_bsdf")) { snode = new TransparentBsdfNode(); } else if(string_iequals(node.name(), "velvet_bsdf")) { snode = new VelvetBsdfNode(); } else if(string_iequals(node.name(), "toon_bsdf")) { ToonBsdfNode *toon = new ToonBsdfNode(); xml_read_enum(&toon->component, ToonBsdfNode::component_enum, node, "component"); snode = toon; } else if(string_iequals(node.name(), "glossy_bsdf")) { GlossyBsdfNode *glossy = new GlossyBsdfNode(); xml_read_enum(&glossy->distribution, GlossyBsdfNode::distribution_enum, node, "distribution"); snode = glossy; } else if(string_iequals(node.name(), "glass_bsdf")) { GlassBsdfNode *diel = new GlassBsdfNode(); xml_read_enum(&diel->distribution, GlassBsdfNode::distribution_enum, node, "distribution"); snode = diel; } else if(string_iequals(node.name(), "refraction_bsdf")) { RefractionBsdfNode *diel = new RefractionBsdfNode(); xml_read_enum(&diel->distribution, RefractionBsdfNode::distribution_enum, node, "distribution"); snode = diel; } else if(string_iequals(node.name(), "hair_bsdf")) { HairBsdfNode *hair = new HairBsdfNode(); xml_read_enum(&hair->component, HairBsdfNode::component_enum, node, "component"); snode = hair; } else if(string_iequals(node.name(), "emission")) { EmissionNode *emission = new EmissionNode(); xml_read_bool(&emission->total_power, node, "total_power"); snode = emission; } else if(string_iequals(node.name(), "ambient_occlusion")) { snode = new AmbientOcclusionNode(); } else if(string_iequals(node.name(), "background")) { snode = new BackgroundNode(); } else if(string_iequals(node.name(), "absorption_volume")) { snode = new AbsorptionVolumeNode(); } else if(string_iequals(node.name(), "scatter_volume")) { snode = new ScatterVolumeNode(); } else if(string_iequals(node.name(), "subsurface_scattering")) { SubsurfaceScatteringNode *sss = new SubsurfaceScatteringNode(); //xml_read_enum(&sss->falloff, SubsurfaceScatteringNode::falloff_enum, node, "falloff"); snode = sss; } else if(string_iequals(node.name(), "geometry")) { snode = new GeometryNode(); } else if(string_iequals(node.name(), "texture_coordinate")) { snode = new TextureCoordinateNode(); } else if(string_iequals(node.name(), "light_path")) { snode = new LightPathNode(); } else if(string_iequals(node.name(), "light_falloff")) { snode = new LightFalloffNode(); } else if(string_iequals(node.name(), "object_info")) { snode = new ObjectInfoNode(); } else if(string_iequals(node.name(), "particle_info")) { snode = new ParticleInfoNode(); } else if(string_iequals(node.name(), "hair_info")) { snode = new HairInfoNode(); } else if(string_iequals(node.name(), "value")) { ValueNode *value = new ValueNode(); xml_read_float(&value->value, node, "value"); snode = value; } else if(string_iequals(node.name(), "color")) { ColorNode *color = new ColorNode(); xml_read_float3(&color->value, node, "value"); snode = color; } else if(string_iequals(node.name(), "mix_closure")) { snode = new MixClosureNode(); } else if(string_iequals(node.name(), "add_closure")) { snode = new AddClosureNode(); } else if(string_iequals(node.name(), "invert")) { snode = new InvertNode(); } else if(string_iequals(node.name(), "mix")) { MixNode *mix = new MixNode(); xml_read_enum(&mix->type, MixNode::type_enum, node, "type"); xml_read_bool(&mix->use_clamp, node, "use_clamp"); snode = mix; } else if(string_iequals(node.name(), "gamma")) { snode = new GammaNode(); } else if(string_iequals(node.name(), "brightness")) { snode = new BrightContrastNode(); } else if(string_iequals(node.name(), "combine_rgb")) { snode = new CombineRGBNode(); } else if(string_iequals(node.name(), "separate_rgb")) { snode = new SeparateRGBNode(); } else if(string_iequals(node.name(), "combine_hsv")) { snode = new CombineHSVNode(); } else if(string_iequals(node.name(), "separate_hsv")) { snode = new SeparateHSVNode(); } else if(string_iequals(node.name(), "hsv")) { snode = new HSVNode(); } else if(string_iequals(node.name(), "wavelength")) { snode = new WavelengthNode(); } else if(string_iequals(node.name(), "blackbody")) { snode = new BlackbodyNode(); } else if(string_iequals(node.name(), "attribute")) { AttributeNode *attr = new AttributeNode(); xml_read_ustring(&attr->attribute, node, "attribute"); snode = attr; } else if(string_iequals(node.name(), "camera")) { snode = new CameraNode(); } else if(string_iequals(node.name(), "fresnel")) { snode = new FresnelNode(); } else if(string_iequals(node.name(), "layer_weight")) { snode = new LayerWeightNode(); } else if(string_iequals(node.name(), "wireframe")) { WireframeNode *wire = new WireframeNode; xml_read_bool(&wire->use_pixel_size, node, "use_pixel_size"); snode = wire; } else if(string_iequals(node.name(), "normal_map")) { NormalMapNode *nmap = new NormalMapNode; xml_read_ustring(&nmap->attribute, node, "attribute"); xml_read_enum(&nmap->space, NormalMapNode::space_enum, node, "space"); snode = nmap; } else if(string_iequals(node.name(), "tangent")) { TangentNode *tangent = new TangentNode; xml_read_ustring(&tangent->attribute, node, "attribute"); xml_read_enum(&tangent->direction_type, TangentNode::direction_type_enum, node, "direction_type"); xml_read_enum(&tangent->axis, TangentNode::axis_enum, node, "axis"); snode = tangent; } else if(string_iequals(node.name(), "math")) { MathNode *math = new MathNode(); xml_read_enum(&math->type, MathNode::type_enum, node, "type"); xml_read_bool(&math->use_clamp, node, "use_clamp"); snode = math; } else if(string_iequals(node.name(), "vector_math")) { VectorMathNode *vmath = new VectorMathNode(); xml_read_enum(&vmath->type, VectorMathNode::type_enum, node, "type"); snode = vmath; } else if(string_iequals(node.name(), "vector_transform")) { VectorTransformNode *vtransform = new VectorTransformNode(); xml_read_enum(&vtransform->type, VectorTransformNode::type_enum, node, "type"); xml_read_enum(&vtransform->convert_from, VectorTransformNode::convert_space_enum, node, "convert_from"); xml_read_enum(&vtransform->convert_to, VectorTransformNode::convert_space_enum, node, "convert_to"); snode = vtransform; } else if(string_iequals(node.name(), "connect")) { /* connect nodes */ vector<string> from_tokens, to_tokens; string_split(from_tokens, node.attribute("from").value()); string_split(to_tokens, node.attribute("to").value()); if(from_tokens.size() == 2 && to_tokens.size() == 2) { /* find nodes and sockets */ ShaderOutput *output = NULL; ShaderInput *input = NULL; if(nodemap.find(from_tokens[0]) != nodemap.end()) { ShaderNode *fromnode = nodemap[from_tokens[0]]; foreach(ShaderOutput *out, fromnode->outputs) if(string_iequals(xml_socket_name(out->name), from_tokens[1])) output = out; if(!output) fprintf(stderr, "Unknown output socket name \"%s\" on \"%s\".\n", from_tokens[1].c_str(), from_tokens[0].c_str()); } else
void BlenderSync::sync_world(bool update_all) { Background *background = scene->background; Background prevbackground = *background; BL::World b_world = b_scene.world(); if(world_recalc || update_all || 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()) { BL::ShaderNodeTree b_ntree(b_world.node_tree()); add_nodes(scene, b_engine, b_data, b_scene, !preview, 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 = (VolumeSampling)RNA_enum_get(&cworld, "volume_sampling"); shader->volume_interpolation_method = (VolumeInterpolation)RNA_enum_get(&cworld, "volume_interpolation"); } 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")); } if(b_world) { /* AO */ BL::WorldLighting b_light = b_world.light_settings(); if(b_light.use_ambient_occlusion()) background->ao_factor = b_light.ao_factor(); else background->ao_factor = 0.0f; background->ao_distance = b_light.distance(); /* visibility */ PointerRNA cvisibility = RNA_pointer_get(&b_world.ptr, "cycles_visibility"); uint visibility = 0; visibility |= get_boolean(cvisibility, "camera")? PATH_RAY_CAMERA: 0; visibility |= get_boolean(cvisibility, "diffuse")? PATH_RAY_DIFFUSE: 0; visibility |= get_boolean(cvisibility, "glossy")? PATH_RAY_GLOSSY: 0; visibility |= get_boolean(cvisibility, "transmission")? PATH_RAY_TRANSMIT: 0; visibility |= get_boolean(cvisibility, "scatter")? PATH_RAY_VOLUME_SCATTER: 0; background->visibility = visibility; } else { background->ao_factor = 0.0f; background->ao_distance = FLT_MAX; } shader->set_graph(graph); shader->tag_update(scene); background->tag_update(scene); } PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); /* when doing preview render check for BI's transparency settings, * this is so because Blender's preview render routines are not able * to tweak all cycles's settings depending on different circumstances */ if(b_engine.is_preview() == false) background->transparent = get_boolean(cscene, "film_transparent"); else background->transparent = b_scene.render().alpha_mode() == BL::RenderSettings::alpha_mode_TRANSPARENT; background->use_shader = render_layer.use_background_shader; background->use_ao = render_layer.use_background_ao; if(background->modified(prevbackground)) background->tag_update(scene); }
static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pugi::xml_node graph_node) { ShaderGraph *graph = new ShaderGraph(); map<string, ShaderNode*> nodemap; nodemap["output"] = graph->output(); for(pugi::xml_node node = graph_node.first_child(); node; node = node.next_sibling()) { ShaderNode *snode = NULL; if(string_iequals(node.name(), "image_texture")) { ImageTextureNode *img = new ImageTextureNode(); xml_read_string(&img->filename, node, "src"); img->filename = path_join(state.base, img->filename); snode = img; } else if(string_iequals(node.name(), "environment_texture")) { EnvironmentTextureNode *env = new EnvironmentTextureNode(); xml_read_string(&env->filename, node, "src"); env->filename = path_join(state.base, env->filename); snode = env; } else if(string_iequals(node.name(), "sky_texture")) { SkyTextureNode *sky = new SkyTextureNode(); xml_read_float3(&sky->sun_direction, node, "sun_direction"); xml_read_float(&sky->turbidity, node, "turbidity"); snode = sky; } else if(string_iequals(node.name(), "noise_texture")) { snode = new NoiseTextureNode(); } else if(string_iequals(node.name(), "checker_texture")) { snode = new CheckerTextureNode(); } else if(string_iequals(node.name(), "gradient_texture")) { GradientTextureNode *blend = new GradientTextureNode(); xml_read_enum(&blend->type, GradientTextureNode::type_enum, node, "type"); snode = blend; } else if(string_iequals(node.name(), "voronoi_texture")) { VoronoiTextureNode *voronoi = new VoronoiTextureNode(); xml_read_enum(&voronoi->coloring, VoronoiTextureNode::coloring_enum, node, "coloring"); snode = voronoi; } else if(string_iequals(node.name(), "musgrave_texture")) { MusgraveTextureNode *musgrave = new MusgraveTextureNode(); xml_read_enum(&musgrave->type, MusgraveTextureNode::type_enum, node, "type"); snode = musgrave; } else if(string_iequals(node.name(), "magic_texture")) { MagicTextureNode *magic = new MagicTextureNode(); xml_read_int(&magic->depth, node, "depth"); snode = magic; } else if(string_iequals(node.name(), "noise_texture")) { NoiseTextureNode *dist = new NoiseTextureNode(); snode = dist; } else if(string_iequals(node.name(), "wave_texture")) { WaveTextureNode *wood = new WaveTextureNode(); xml_read_enum(&wood->type, WaveTextureNode::type_enum, node, "type"); snode = wood; } else if(string_iequals(node.name(), "normal")) { snode = new NormalNode(); } else if(string_iequals(node.name(), "mapping")) { snode = new MappingNode(); } else if(string_iequals(node.name(), "ward_bsdf")) { snode = new WardBsdfNode(); } else if(string_iequals(node.name(), "diffuse_bsdf")) { snode = new DiffuseBsdfNode(); } else if(string_iequals(node.name(), "translucent_bsdf")) { snode = new TranslucentBsdfNode(); } else if(string_iequals(node.name(), "transparent_bsdf")) { snode = new TransparentBsdfNode(); } else if(string_iequals(node.name(), "velvet_bsdf")) { snode = new VelvetBsdfNode(); } else if(string_iequals(node.name(), "glossy_bsdf")) { GlossyBsdfNode *glossy = new GlossyBsdfNode(); xml_read_enum(&glossy->distribution, GlossyBsdfNode::distribution_enum, node, "distribution"); snode = glossy; } else if(string_iequals(node.name(), "glass_bsdf")) { GlassBsdfNode *diel = new GlassBsdfNode(); xml_read_enum(&diel->distribution, GlassBsdfNode::distribution_enum, node, "distribution"); snode = diel; } else if(string_iequals(node.name(), "emission")) { EmissionNode *emission = new EmissionNode(); xml_read_bool(&emission->total_power, node, "total_power"); snode = emission; } else if(string_iequals(node.name(), "background")) { snode = new BackgroundNode(); } else if(string_iequals(node.name(), "transparent_volume")) { snode = new TransparentVolumeNode(); } else if(string_iequals(node.name(), "isotropic_volume")) { snode = new IsotropicVolumeNode(); } else if(string_iequals(node.name(), "geometry")) { snode = new GeometryNode(); } else if(string_iequals(node.name(), "texture_coordinate")) { snode = new TextureCoordinateNode(); } else if(string_iequals(node.name(), "lightPath")) { snode = new LightPathNode(); } else if(string_iequals(node.name(), "value")) { ValueNode *value = new ValueNode(); xml_read_float(&value->value, node, "value"); snode = value; } else if(string_iequals(node.name(), "color")) { ColorNode *color = new ColorNode(); xml_read_float3(&color->value, node, "value"); snode = color; } else if(string_iequals(node.name(), "mix_closure")) { snode = new MixClosureNode(); } else if(string_iequals(node.name(), "add_closure")) { snode = new AddClosureNode(); } else if(string_iequals(node.name(), "invert")) { snode = new InvertNode(); } else if(string_iequals(node.name(), "mix")) { MixNode *mix = new MixNode(); xml_read_enum(&mix->type, MixNode::type_enum, node, "type"); snode = mix; } else if(string_iequals(node.name(), "gamma")) { snode = new GammaNode(); } else if(string_iequals(node.name(), "brightness")) { snode = new BrightContrastNode(); } else if(string_iequals(node.name(), "combine_rgb")) { snode = new CombineRGBNode(); } else if(string_iequals(node.name(), "separate_rgb")) { snode = new SeparateRGBNode(); } else if(string_iequals(node.name(), "hsv")) { snode = new HSVNode(); } else if(string_iequals(node.name(), "attribute")) { AttributeNode *attr = new AttributeNode(); xml_read_ustring(&attr->attribute, node, "attribute"); snode = attr; } else if(string_iequals(node.name(), "camera")) { snode = new CameraNode(); } else if(string_iequals(node.name(), "fresnel")) { snode = new FresnelNode(); } else if(string_iequals(node.name(), "math")) { MathNode *math = new MathNode(); xml_read_enum(&math->type, MathNode::type_enum, node, "type"); snode = math; } else if(string_iequals(node.name(), "vector_math")) { VectorMathNode *vmath = new VectorMathNode(); xml_read_enum(&vmath->type, VectorMathNode::type_enum, node, "type"); snode = vmath; } else if(string_iequals(node.name(), "connect")) { /* connect nodes */ vector<string> from_tokens, to_tokens; string_split(from_tokens, node.attribute("from").value()); string_split(to_tokens, node.attribute("to").value()); if(from_tokens.size() == 2 && to_tokens.size() == 2) { /* find nodes and sockets */ ShaderOutput *output = NULL; ShaderInput *input = NULL; if(nodemap.find(from_tokens[0]) != nodemap.end()) { ShaderNode *fromnode = nodemap[from_tokens[0]]; foreach(ShaderOutput *out, fromnode->outputs) if(string_iequals(xml_socket_name(out->name), from_tokens[1])) output = out; if(!output) fprintf(stderr, "Unknown output socket name \"%s\" on \"%s\".\n", from_tokens[1].c_str(), from_tokens[0].c_str()); } else