From 42aec3b355b7692f60369c0d5333f54b029bfcad Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sat, 7 May 2016 19:48:28 +0200 Subject: Cycles: nodify shader nodes Differential Revision: https://developer.blender.org/D2038 --- intern/cycles/app/cycles_xml.cpp | 511 +----- intern/cycles/blender/blender_shader.cpp | 49 +- intern/cycles/render/graph.cpp | 196 +-- intern/cycles/render/graph.h | 62 +- intern/cycles/render/nodes.cpp | 2519 ++++++++++++++++++------------ intern/cycles/render/nodes.h | 474 +++--- intern/cycles/render/osl.cpp | 203 ++- intern/cycles/render/osl.h | 2 + intern/cycles/render/shader.cpp | 20 +- intern/cycles/render/svm.cpp | 10 +- 10 files changed, 2117 insertions(+), 1929 deletions(-) diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp index 9f967a4bde9..48a2b12b23a 100644 --- a/intern/cycles/app/cycles_xml.cpp +++ b/intern/cycles/app/cycles_xml.cpp @@ -73,18 +73,6 @@ struct XMLReadState : public XMLReader { /* Attribute Reading */ -static bool xml_read_bool(bool *value, pugi::xml_node node, const char *name) -{ - pugi::xml_attribute attr = node.attribute(name); - - if(attr) { - *value = (string_iequals(attr.value(), "true")) || (atoi(attr.value()) != 0); - return true; - } - - return false; -} - static bool xml_read_int(int *value, pugi::xml_node node, const char *name) { pugi::xml_attribute attr = node.attribute(name); @@ -193,18 +181,6 @@ static bool xml_read_string(string *str, pugi::xml_node node, const char *name) return false; } -static bool xml_read_ustring(ustring *str, pugi::xml_node node, const char *name) -{ - pugi::xml_attribute attr = node.attribute(name); - - if(attr) { - *str = ustring(attr.value()); - return true; - } - - return false; -} - static bool xml_equal_string(pugi::xml_node node, const char *name, const char *value) { pugi::xml_attribute attr = node.attribute(name); @@ -215,24 +191,6 @@ static bool xml_equal_string(pugi::xml_node node, const char *name, const char * return false; } -static bool xml_read_enum_value(int *value, NodeEnum& enm, pugi::xml_node node, const char *name) -{ - pugi::xml_attribute attr = node.attribute(name); - - if(attr) { - ustring ustr(attr.value()); - - if(enm.exists(ustr)) { - *value = enm[ustr]; - return true; - } - else - fprintf(stderr, "Unknown value \"%s\" for attribute \"%s\".\n", ustr.c_str(), name); - } - - return false; -} - /* Camera */ static void xml_read_camera(XMLReadState& state, pugi::xml_node node) @@ -267,47 +225,74 @@ static void xml_read_shader_graph(XMLReadState& state, Shader *shader, pugi::xml { xml_read_node(state, shader, graph_node); - ShaderManager *manager = state.scene->shader_manager; ShaderGraph *graph = new ShaderGraph(); - map nodemap; - - nodemap["output"] = graph->output(); + /* local state, shader nodes can't link to nodes outside the shader graph */ + XMLReader graph_reader; + graph_reader.node_map[ustring("output")] = graph->output(); for(pugi::xml_node node = graph_node.first_child(); node; node = node.next_sibling()) { - ShaderNode *snode = NULL; + ustring node_name(node.name()); - /* ToDo: Add missing nodes - * RGBCurvesNode, VectorCurvesNode, RGBRampNode and ConvertNode (RGB -> BW). - */ + if(node_name == "connect") { + /* connect nodes */ + vector from_tokens, to_tokens; - if(string_iequals(node.name(), "image_texture")) { - ImageTextureNode *img = new ImageTextureNode(); + string_split(from_tokens, node.attribute("from").value()); + string_split(to_tokens, node.attribute("to").value()); - xml_read_string(&img->filename, node, "src"); - img->filename = path_join(state.base, img->filename); - - xml_read_enum_value((int*)&img->color_space, ImageTextureNode::color_space_enum, node, "color_space"); - xml_read_enum_value((int*)&img->projection, ImageTextureNode::projection_enum, node, "projection"); - xml_read_float(&img->projection_blend, node, "projection_blend"); + if(from_tokens.size() == 2 && to_tokens.size() == 2) { + ustring from_node_name(from_tokens[0]); + ustring from_socket_name(from_tokens[1]); + ustring to_node_name(to_tokens[0]); + ustring to_socket_name(to_tokens[1]); - /* ToDo: Interpolation */ + /* find nodes and sockets */ + ShaderOutput *output = NULL; + ShaderInput *input = NULL; - snode = img; - } - else if(string_iequals(node.name(), "environment_texture")) { - EnvironmentTextureNode *env = new EnvironmentTextureNode(); + if(graph_reader.node_map.find(from_node_name) != graph_reader.node_map.end()) { + ShaderNode *fromnode = (ShaderNode*)graph_reader.node_map[from_node_name]; - xml_read_string(&env->filename, node, "src"); - env->filename = path_join(state.base, env->filename); - - xml_read_enum_value((int*)&env->color_space, EnvironmentTextureNode::color_space_enum, node, "color_space"); - xml_read_enum_value((int*)&env->projection, EnvironmentTextureNode::projection_enum, node, "projection"); + foreach(ShaderOutput *out, fromnode->outputs) + if(string_iequals(xml_socket_name(out->name().c_str()), from_socket_name.c_str())) + output = out; + + if(!output) + fprintf(stderr, "Unknown output socket name \"%s\" on \"%s\".\n", from_node_name.c_str(), from_socket_name.c_str()); + } + else + fprintf(stderr, "Unknown shader node name \"%s\".\n", from_node_name.c_str()); + + if(graph_reader.node_map.find(to_node_name) != graph_reader.node_map.end()) { + ShaderNode *tonode = (ShaderNode*)graph_reader.node_map[to_node_name]; + + foreach(ShaderInput *in, tonode->inputs) + if(string_iequals(xml_socket_name(in->name().c_str()), to_socket_name.c_str())) + input = in; + + if(!input) + fprintf(stderr, "Unknown input socket name \"%s\" on \"%s\".\n", to_socket_name.c_str(), to_node_name.c_str()); + } + else + fprintf(stderr, "Unknown shader node name \"%s\".\n", to_node_name.c_str()); + + /* connect */ + if(output && input) + graph->connect(output, input); + } + else + fprintf(stderr, "Invalid from or to value for connect node.\n"); - snode = env; + continue; } + + ShaderNode *snode = NULL; + #ifdef WITH_OSL - else if(string_iequals(node.name(), "osl_shader")) { + if(node_name == "osl_shader") { + ShaderManager *manager = state.scene->shader_manager; + if(manager->use_osl()) { std::string filepath; @@ -320,390 +305,54 @@ static void xml_read_shader_graph(XMLReadState& state, Shader *shader, pugi::xml if(!snode) { fprintf(stderr, "Failed to create OSL node from \"%s\".\n", filepath.c_str()); + continue; } } else { fprintf(stderr, "OSL node missing \"src\" attribute.\n"); + continue; } } else { fprintf(stderr, "OSL node without using --shadingsys osl.\n"); + continue; } } + else #endif - else if(string_iequals(node.name(), "sky_texture")) { - SkyTextureNode *sky = new SkyTextureNode(); - - xml_read_enum_value((int*)&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(); + { + /* exception for name collision */ + if(node_name == "background") + node_name = "background_shader"; - 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"); + const NodeType *node_type = NodeType::find(node_name); - snode = brick; - } - else if(string_iequals(node.name(), "gradient_texture")) { - GradientTextureNode *blend = new GradientTextureNode(); - xml_read_enum_value((int*)&blend->type, GradientTextureNode::type_enum, node, "type"); - snode = blend; - } - else if(string_iequals(node.name(), "voronoi_texture")) { - VoronoiTextureNode *voronoi = new VoronoiTextureNode(); - xml_read_enum_value((int*)&voronoi->coloring, VoronoiTextureNode::coloring_enum, node, "coloring"); - snode = voronoi; - } - else if(string_iequals(node.name(), "musgrave_texture")) { - MusgraveTextureNode *musgrave = new MusgraveTextureNode(); - xml_read_enum_value((int*)&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(), "wave_texture")) { - WaveTextureNode *wave = new WaveTextureNode(); - xml_read_enum_value((int*)&wave->type, WaveTextureNode::type_enum, node, "type"); - xml_read_enum_value((int*)&wave->profile, WaveTextureNode::profile_enum, node, "profile"); - 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(), "bump")) { - BumpNode *bump = new BumpNode(); - xml_read_bool(&bump->invert, node, "invert"); - snode = bump; - } - else if(string_iequals(node.name(), "mapping")) { - MappingNode *map = new MappingNode(); - - TextureMapping *texmap = &map->tex_mapping; - xml_read_enum_value((int*) &texmap->type, TextureMapping::type_enum, node, "type"); - xml_read_enum_value((int*) &texmap->projection, TextureMapping::projection_enum, node, "projection"); - xml_read_enum_value((int*) &texmap->x_mapping, TextureMapping::mapping_enum, node, "x_mapping"); - xml_read_enum_value((int*) &texmap->y_mapping, TextureMapping::mapping_enum, node, "y_mapping"); - xml_read_enum_value((int*) &texmap->z_mapping, TextureMapping::mapping_enum, node, "z_mapping"); - xml_read_bool(&texmap->use_minmax, node, "use_minmax"); - if(texmap->use_minmax) { - xml_read_float3(&texmap->min, node, "min"); - xml_read_float3(&texmap->max, node, "max"); + if(!node_type) { + fprintf(stderr, "Unknown shader node \"%s\".\n", node.name()); + continue; + } + else if(node_type->type != NodeType::SHADER) { + fprintf(stderr, "Node type \"%s\" is not a shader node.\n", node_type->name.c_str()); + continue; } - xml_read_float3(&texmap->translation, node, "translation"); - xml_read_float3(&texmap->rotation, node, "rotation"); - xml_read_float3(&texmap->scale, node, "scale"); - snode = map; - } - else if(string_iequals(node.name(), "anisotropic_bsdf")) { - AnisotropicBsdfNode *aniso = new AnisotropicBsdfNode(); - xml_read_enum_value((int*)&aniso->distribution, AnisotropicBsdfNode::distribution_enum, node, "distribution"); - snode = aniso; - } - 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(); + snode = (ShaderNode*) node_type->create(node_type); } - else if(string_iequals(node.name(), "toon_bsdf")) { - ToonBsdfNode *toon = new ToonBsdfNode(); - xml_read_enum_value((int*)&toon->component, ToonBsdfNode::component_enum, node, "component"); - snode = toon; - } - else if(string_iequals(node.name(), "glossy_bsdf")) { - GlossyBsdfNode *glossy = new GlossyBsdfNode(); - xml_read_enum_value((int*)&glossy->distribution, GlossyBsdfNode::distribution_enum, node, "distribution"); - snode = glossy; - } - else if(string_iequals(node.name(), "glass_bsdf")) { - GlassBsdfNode *diel = new GlassBsdfNode(); - xml_read_enum_value((int*)&diel->distribution, GlassBsdfNode::distribution_enum, node, "distribution"); - snode = diel; - } - else if(string_iequals(node.name(), "refraction_bsdf")) { - RefractionBsdfNode *diel = new RefractionBsdfNode(); - xml_read_enum_value((int*)&diel->distribution, RefractionBsdfNode::distribution_enum, node, "distribution"); - snode = diel; - } - else if(string_iequals(node.name(), "hair_bsdf")) { - HairBsdfNode *hair = new HairBsdfNode(); - xml_read_enum_value((int*)&hair->component, HairBsdfNode::component_enum, node, "component"); - snode = hair; - } - else if(string_iequals(node.name(), "emission")) { - snode = new EmissionNode(); - } - 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(), "holdout")) { - snode = new HoldoutNode(); - } - 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(); - - string falloff; - xml_read_string(&falloff, node, "falloff"); - if(falloff == "cubic") - sss->closure = CLOSURE_BSSRDF_CUBIC_ID; - else if(falloff == "gaussian") - sss->closure = CLOSURE_BSSRDF_GAUSSIAN_ID; - else /*if(falloff == "burley")*/ - sss->closure = CLOSURE_BSSRDF_BURLEY_ID; - - 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")) { - /* ToDo: Tag Mix case for optimization */ - MixNode *mix = new MixNode(); - xml_read_enum_value((int*)&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(), "combine_xyz")) { - snode = new CombineXYZNode(); - } - else if(string_iequals(node.name(), "separate_xyz")) { - snode = new SeparateXYZNode(); - } - 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(), "uv_map")) { - UVMapNode *uvm = new UVMapNode(); - xml_read_ustring(&uvm->attribute, node, "uv_map"); - snode = uvm; - } - 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_value((int*)&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_value((int*)&tangent->direction_type, TangentNode::direction_type_enum, node, "direction_type"); - xml_read_enum_value((int*)&tangent->axis, TangentNode::axis_enum, node, "axis"); - snode = tangent; - } - else if(string_iequals(node.name(), "math")) { - MathNode *math = new MathNode(); - xml_read_enum_value((int*)&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_value((int*)&vmath->type, VectorMathNode::type_enum, node, "type"); - snode = vmath; - } - else if(string_iequals(node.name(), "vector_transform")) { - VectorTransformNode *vtransform = new VectorTransformNode(); - xml_read_enum_value((int*)&vtransform->type, VectorTransformNode::type_enum, node, "type"); - xml_read_enum_value((int*)&vtransform->convert_from, VectorTransformNode::convert_space_enum, node, "convert_from"); - xml_read_enum_value((int*)&vtransform->convert_to, VectorTransformNode::convert_space_enum, node, "convert_to"); - snode = vtransform; - } - else if(string_iequals(node.name(), "connect")) { - /* connect nodes */ - vector 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().c_str()), 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 - fprintf(stderr, "Unknown shader node name \"%s\".\n", from_tokens[0].c_str()); - - if(nodemap.find(to_tokens[0]) != nodemap.end()) { - ShaderNode *tonode = nodemap[to_tokens[0]]; - foreach(ShaderInput *in, tonode->inputs) - if(string_iequals(xml_socket_name(in->name().c_str()), to_tokens[1])) - input = in; + xml_read_node(graph_reader, snode, node); - if(!input) - fprintf(stderr, "Unknown input socket name \"%s\" on \"%s\".\n", to_tokens[1].c_str(), to_tokens[0].c_str()); - } - else - fprintf(stderr, "Unknown shader node name \"%s\".\n", to_tokens[0].c_str()); - - /* connect */ - if(output && input) - graph->connect(output, input); - } - else - fprintf(stderr, "Invalid from or to value for connect node.\n"); + if(node_name == "image_texture") { + ImageTextureNode *img = (ImageTextureNode*) snode; + img->filename = path_join(state.base, img->filename); + } + else if(node_name == "environment_texture") { + EnvironmentTextureNode *env = (EnvironmentTextureNode*) snode; + env->filename = path_join(state.base, env->filename); } - else - fprintf(stderr, "Unknown shader node \"%s\".\n", node.name()); if(snode) { /* add to graph */ graph->add(snode); - - /* add to map for name lookups */ - string name = ""; - xml_read_string(&name, node, "name"); - - nodemap[name] = snode; - - /* read input values */ - for(pugi::xml_attribute attr = node.first_attribute(); attr; attr = attr.next_attribute()) { - foreach(ShaderInput *in, snode->inputs) { - if(string_iequals(in->name().c_str(), attr.name())) { - switch(in->type()) { - case SocketType::FLOAT: - case SocketType::INT: - xml_read_float(&in->value_float(), node, attr.name()); - break; - case SocketType::COLOR: - case SocketType::VECTOR: - case SocketType::POINT: - case SocketType::NORMAL: - xml_read_float3(&in->value(), node, attr.name()); - break; - case SocketType::STRING: - xml_read_ustring( &in->value_string(), node, attr.name() ); - break; - default: - break; - } - } - } - } } } diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 7a13641a312..0b61cbb0f62 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -153,28 +153,31 @@ static void set_default_value(ShaderInput *input, BL::BlendData& b_data, BL::ID& b_id) { + Node *node = input->parent; + const SocketType& socket = input->socket_type; + /* copy values for non linked inputs */ switch(input->type()) { case SocketType::FLOAT: { - input->set(get_float(b_sock.ptr, "default_value")); + node->set(socket, get_float(b_sock.ptr, "default_value")); break; } case SocketType::INT: { - input->set(get_int(b_sock.ptr, "default_value")); + node->set(socket, get_int(b_sock.ptr, "default_value")); break; } case SocketType::COLOR: { - input->set(float4_to_float3(get_float4(b_sock.ptr, "default_value"))); + node->set(socket, float4_to_float3(get_float4(b_sock.ptr, "default_value"))); break; } case SocketType::NORMAL: case SocketType::POINT: case SocketType::VECTOR: { - input->set(get_float3(b_sock.ptr, "default_value")); + node->set(socket, get_float3(b_sock.ptr, "default_value")); break; } case SocketType::STRING: { - input->set((ustring)blender_absolute_path(b_data, b_id, get_string(b_sock.ptr, "default_value"))); + node->set(socket, (ustring)blender_absolute_path(b_data, b_id, get_string(b_sock.ptr, "default_value"))); break; } default: @@ -799,7 +802,7 @@ static ShaderNode *add_node(Scene *scene, if(true) { b_point_density_node.cache_point_density(b_scene, settings); scene->image_manager->tag_reload_image( - point_density->filename, + point_density->filename.string(), point_density->builtin_data, point_density->interpolation, EXTENSION_CLIP); @@ -1153,13 +1156,12 @@ void BlenderSync::sync_materials(bool update_all) 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")->set(get_float3(b_mat->diffuse_color())); - out = graph->output(); + DiffuseBsdfNode *diffuse = new DiffuseBsdfNode(); + diffuse->color = get_float3(b_mat->diffuse_color()); + graph->add(diffuse); - graph->connect(closure->output("BSDF"), out->input("Surface")); + ShaderNode *out = graph->output(); + graph->connect(diffuse->output("BSDF"), out->input("Surface")); } /* settings */ @@ -1202,13 +1204,12 @@ void BlenderSync::sync_world(bool update_all) shader->volume_interpolation_method = get_volume_interpolation(cworld); } else if(b_world) { - ShaderNode *closure, *out; - - closure = graph->add(new BackgroundNode()); - closure->input("Color")->set(get_float3(b_world.horizon_color())); - out = graph->output(); + BackgroundNode *background = new BackgroundNode(); + background->color = get_float3(b_world.horizon_color()); + graph->add(background); - graph->connect(closure->output("Background"), out->input("Surface")); + ShaderNode *out = graph->output(); + graph->connect(background->output("Background"), out->input("Surface")); } if(b_world) { @@ -1287,7 +1288,6 @@ void BlenderSync::sync_lamps(bool update_all) add_nodes(scene, b_engine, b_data, b_scene, !preview, graph, b_ntree); } else { - ShaderNode *closure, *out; float strength = 1.0f; if(b_lamp->type() == BL::Lamp::type_POINT || @@ -1297,12 +1297,13 @@ void BlenderSync::sync_lamps(bool update_all) strength = 100.0f; } - closure = graph->add(new EmissionNode()); - closure->input("Color")->set(get_float3(b_lamp->color())); - closure->input("Strength")->set(strength); - out = graph->output(); + EmissionNode *emission = new EmissionNode(); + emission->color = get_float3(b_lamp->color()); + emission->strength = strength; + graph->add(emission); - graph->connect(closure->output("Emission"), out->input("Surface")); + ShaderNode *out = graph->output(); + graph->connect(emission->output("Emission"), out->input("Surface")); } shader->set_graph(graph); diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index 29c0eec9b97..9210221a261 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -51,72 +51,19 @@ bool check_node_inputs_traversed(const ShaderNode *node, return true; } -bool check_node_inputs_equals(const ShaderNode *node_a, - const ShaderNode *node_b) -{ - if(node_a->inputs.size() != node_b->inputs.size()) { - /* Happens with BSDF closure nodes which are currently sharing the same - * name for all the BSDF types, making it impossible to filter out - * incompatible nodes. - */ - return false; - } - for(int i = 0; i < node_a->inputs.size(); ++i) { - ShaderInput *input_a = node_a->inputs[i], - *input_b = node_b->inputs[i]; - if(input_a->link == NULL && input_b->link == NULL) { - /* Unconnected inputs are expected to have the same value. */ - if(input_a->value() != input_b->value()) { - return false; - } - } - else if(input_a->link != NULL && input_b->link != NULL) { - /* Expect links are to come from the same exact socket. */ - if(input_a->link != input_b->link) { - return false; - } - } - else { - /* One socket has a link and another has not, inputs can't be - * considered equal. - */ - return false; - } - } - return true; -} - } /* namespace */ -/* Input and Output */ - -ShaderInput::ShaderInput(ShaderNode *parent_, const char *name, SocketType::Type type) -{ - parent = parent_; - name_ = name; - type_ = type; - link = NULL; - value_ = make_float3(0.0f, 0.0f, 0.0f); - stack_offset = SVM_STACK_INVALID; - flags_ = 0; -} - -ShaderOutput::ShaderOutput(ShaderNode *parent_, const char *name, SocketType::Type type) -{ - parent = parent_; - name_ = name; - type_ = type; - stack_offset = SVM_STACK_INVALID; -} - /* Node */ -ShaderNode::ShaderNode(const char *name_) +ShaderNode::ShaderNode(const NodeType *type) +: Node(type) { - name = name_; + name = type->name; id = -1; bump = SHADER_BUMP_NONE; special_type = SHADER_SPECIAL_TYPE_NONE; + + create_inputs_outputs(type); } ShaderNode::~ShaderNode() @@ -128,6 +75,19 @@ ShaderNode::~ShaderNode() delete socket; } +void ShaderNode::create_inputs_outputs(const NodeType *type) +{ + foreach(const SocketType& socket, type->inputs) { + if(socket.flags & SocketType::LINKABLE) { + inputs.push_back(new ShaderInput(socket, this)); + } + } + + foreach(const SocketType& socket, type->outputs) { + outputs.push_back(new ShaderOutput(socket, this)); + } +} + ShaderInput *ShaderNode::input(const char *name) { foreach(ShaderInput *socket, inputs) { @@ -166,31 +126,6 @@ ShaderOutput *ShaderNode::output(ustring name) return NULL; } -ShaderInput *ShaderNode::add_input(const char *name, SocketType::Type type, float value, int flags) -{ - ShaderInput *input = new ShaderInput(this, name, type); - input->value_.x = value; - input->flags_ = flags; - inputs.push_back(input); - return input; -} - -ShaderInput *ShaderNode::add_input(const char *name, SocketType::Type type, float3 value, int flags) -{ - ShaderInput *input = new ShaderInput(this, name, type); - input->value_ = value; - input->flags_ = flags; - inputs.push_back(input); - return input; -} - -ShaderOutput *ShaderNode::add_output(const char *name, SocketType::Type type) -{ - ShaderOutput *output = new ShaderOutput(this, name, type); - outputs.push_back(output); - return output; -} - void ShaderNode::attributes(Shader *shader, AttributeRequestSet *attributes) { foreach(ShaderInput *input, inputs) { @@ -209,6 +144,49 @@ void ShaderNode::attributes(Shader *shader, AttributeRequestSet *attributes) } } +bool ShaderNode::equals(const ShaderNode& other) +{ + if (type != other.type || bump != other.bump) + return false; + + assert(inputs.size() == other.inputs.size()); + + /* Compare unlinkable sockets */ + foreach(const SocketType& socket, type->inputs) { + if(!(socket.flags & SocketType::LINKABLE)) { + if(!Node::equals_value(other, socket)) { + return false; + } + } + } + + /* Compare linkable input sockets */ + for(int i = 0; i < inputs.size(); ++i) { + ShaderInput *input_a = inputs[i], + *input_b = other.inputs[i]; + if(input_a->link == NULL && input_b->link == NULL) { + /* Unconnected inputs are expected to have the same value. */ + if(!Node::equals_value(other, input_a->socket_type)) { + return false; + } + } + else if(input_a->link != NULL && input_b->link != NULL) { + /* Expect links are to come from the same exact socket. */ + if(input_a->link != input_b->link) { + return false; + } + } + else { + /* One socket has a link and another has not, inputs can't be + * considered equal. + */ + return false; + } + } + + return true; +} + /* Graph */ ShaderGraph::ShaderGraph() @@ -470,8 +448,7 @@ void ShaderGraph::remove_proxy_nodes() disconnect(to); /* transfer the default input value to the target socket */ - to->set(input->value()); - to->set(input->value_string()); + tonode->copy_value(to->socket_type, *proxy, input->socket_type); } } @@ -542,7 +519,7 @@ void ShaderGraph::constant_fold() vector links(output->links); for(size_t i = 0; i < links.size(); i++) { if(i > 0) - links[i]->set(links[0]->value()); + links[i]->parent->copy_value(links[i]->socket_type, *links[0]->parent, links[0]->socket_type); disconnect(links[i]); } } @@ -604,25 +581,11 @@ void ShaderGraph::deduplicate_nodes() } /* Try to merge this node with another one. */ foreach(ShaderNode *other_node, done[node->name]) { - if(node == other_node) { - /* Don't merge with self. */ - continue; - } - if(node->name != other_node->name) { - /* Can only de-duplicate nodes of the same type. */ - continue; - } - if(!check_node_inputs_equals(node, other_node)) { - /* Node inputs are different, can't merge them, */ - continue; - } - if(!node->equals(other_node)) { - /* Node settings are different. */ - continue; - } - /* TODO(sergey): Consider making it an utility function. */ - for(int i = 0; i < node->outputs.size(); ++i) { - relink(node, node->outputs[i], other_node->outputs[i]); + if (node != other_node && node->equals(*other_node)) { + /* TODO(sergey): Consider making it an utility function. */ + for(int i = 0; i < node->outputs.size(); ++i) { + relink(node, node->outputs[i], other_node->outputs[i]); + } } break; } @@ -927,14 +890,15 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight if(fin) { /* mix closure: add node to mix closure weights */ - ShaderNode *mix_node = add(new MixClosureWeightNode()); + MixClosureWeightNode *mix_node = new MixClosureWeightNode(); + add(mix_node); ShaderInput *fac_in = mix_node->input("Fac"); ShaderInput *weight_in = mix_node->input("Weight"); if(fin->link) connect(fin->link, fac_in); else - fac_in->set(fin->value_float()); + mix_node->fac = node->get_float(fin->socket_type); if(weight_out) connect(weight_out, weight_in); @@ -961,20 +925,20 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight return; /* already has a weight connected to it? add weights */ - if(weight_in->link || weight_in->value_float() != 0.0f) { - ShaderNode *math_node = add(new MathNode()); - ShaderInput *value1_in = math_node->input("Value1"); - ShaderInput *value2_in = math_node->input("Value2"); + float weight_value = node->get_float(weight_in->socket_type); + if(weight_in->link || weight_value != 0.0f) { + MathNode *math_node = new MathNode(); + add(math_node); if(weight_in->link) - connect(weight_in->link, value1_in); + connect(weight_in->link, math_node->input("Value1")); else - value1_in->set(weight_in->value_float()); + math_node->value1 = weight_value; if(weight_out) - connect(weight_out, value2_in); + connect(weight_out, math_node->input("Value2")); else - value2_in->set(1.0f); + math_node->value2 = 1.0f; weight_out = math_node->output("Value"); if(weight_in->link) @@ -985,7 +949,7 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight if(weight_out) connect(weight_out, weight_in); else - weight_in->set(weight_in->value_float() + 1.0f); + node->set(weight_in->socket_type, weight_value + 1.0f); } } diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h index 882e495df20..dccd8c27b2f 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -18,6 +18,7 @@ #define __GRAPH_H__ #include "node.h" +#include "node_type.h" #include "kernel_types.h" @@ -79,32 +80,21 @@ enum ShaderNodeSpecialType { class ShaderInput { public: - ShaderInput(ShaderNode *parent, const char *name, SocketType::Type type); + ShaderInput(const SocketType& socket_type_, ShaderNode* parent_) + : socket_type(socket_type_), parent(parent_), link(NULL), stack_offset(SVM_STACK_INVALID) + {} - ustring name() { return name_; } - int flags() { return flags_; } - SocketType::Type type() { return type_; } + ustring name() { return socket_type.ui_name; } + int flags() { return socket_type.flags; } + SocketType::Type type() { return socket_type.type; } - void set(float f) { value_.x = f; } - void set(float3 f) { value_ = f; } - void set(int i) { value_.x = (float)i; } - void set(ustring s) { value_string_ = s; } - - float3& value() { return value_; } - float& value_float() { return value_.x; } - ustring& value_string() { return value_string_; } - - ustring name_; - SocketType::Type type_; + void set(float f) { ((Node*)parent)->set(socket_type, f); } + void set(float3 f) { ((Node*)parent)->set(socket_type, f); } + const SocketType& socket_type; ShaderNode *parent; ShaderOutput *link; - - float3 value_; - ustring value_string_; - int stack_offset; /* for SVM compiler */ - int flags_; }; /* Output @@ -113,17 +103,16 @@ public: class ShaderOutput { public: - ShaderOutput(ShaderNode *parent, const char *name, SocketType::Type type); - - ustring name() { return name_; } - SocketType::Type type() { return type_; } + ShaderOutput(const SocketType& socket_type_, ShaderNode* parent_) + : socket_type(socket_type_), parent(parent_), stack_offset(SVM_STACK_INVALID) + {} - ustring name_; - SocketType::Type type_; + ustring name() { return socket_type.ui_name; } + SocketType::Type type() { return socket_type.type; } + const SocketType& socket_type; ShaderNode *parent; vector links; - int stack_offset; /* for SVM compiler */ }; @@ -132,20 +121,18 @@ public: * Shader node in graph, with input and output sockets. This is the virtual * base class for all node types. */ -class ShaderNode { +class ShaderNode : public Node { public: - explicit ShaderNode(const char *name); + explicit ShaderNode(const NodeType *type); virtual ~ShaderNode(); + void create_inputs_outputs(const NodeType *type); + ShaderInput *input(const char *name); ShaderOutput *output(const char *name); ShaderInput *input(ustring name); ShaderOutput *output(ustring name); - ShaderInput *add_input(const char *name, SocketType::Type type, float value=0.0f, int flags=0); - ShaderInput *add_input(const char *name, SocketType::Type type, float3 value, int flags=0); - ShaderOutput *add_output(const char *name, SocketType::Type type); - virtual ShaderNode *clone() const = 0; virtual void attributes(Shader *shader, AttributeRequestSet *attributes); virtual void compile(SVMCompiler& compiler) = 0; @@ -171,7 +158,6 @@ public: vector inputs; vector outputs; - ustring name; /* name, not required to be unique */ int id; /* index in graph node array */ ShaderBump bump; /* for bump mapping utility */ @@ -207,23 +193,21 @@ public: * NOTE: If some node can't be de-duplicated for whatever reason it * is to be handled in the subclass. */ - virtual bool equals(const ShaderNode *other) - { - return name == other->name && - bump == other->bump; - } + virtual bool equals(const ShaderNode& other); }; /* Node definition utility macros */ #define SHADER_NODE_CLASS(type) \ + NODE_DECLARE; \ type(); \ virtual ShaderNode *clone() const { return new type(*this); } \ virtual void compile(SVMCompiler& compiler); \ virtual void compile(OSLCompiler& compiler); \ #define SHADER_NODE_NO_CLONE_CLASS(type) \ + NODE_DECLARE; \ type(); \ virtual void compile(SVMCompiler& compiler); \ virtual void compile(OSLCompiler& compiler); \ diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index df0fee63113..e0b2f377a00 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -30,64 +30,40 @@ CCL_NAMESPACE_BEGIN /* Texture Mapping */ -static NodeEnum texture_mapping_type_init() -{ - NodeEnum enm; - - enm.insert("Point", TextureMapping::POINT); - enm.insert("Texture", TextureMapping::TEXTURE); - enm.insert("Vector", TextureMapping::VECTOR); - enm.insert("Normal", TextureMapping::NORMAL); - - return enm; -} - -static NodeEnum texture_mapping_mapping_init() -{ - NodeEnum enm; - - enm.insert("None", TextureMapping::NONE); - enm.insert("X", TextureMapping::X); - enm.insert("Y", TextureMapping::Y); - enm.insert("Z", TextureMapping::Z); - - return enm; -} - -static NodeEnum texture_mapping_projection_init() -{ - NodeEnum enm; - - enm.insert("Flat", TextureMapping::FLAT); - enm.insert("Cube", TextureMapping::CUBE); - enm.insert("Tube", TextureMapping::TUBE); - enm.insert("Sphere", TextureMapping::SPHERE); - - return enm; -} - -NodeEnum TextureMapping::type_enum = texture_mapping_type_init(); -NodeEnum TextureMapping::mapping_enum = texture_mapping_mapping_init(); -NodeEnum TextureMapping::projection_enum = texture_mapping_projection_init(); +#define TEXTURE_MAPPING_DEFINE(TextureNode) \ + SOCKET_POINT(tex_mapping.translation, "Translation", make_float3(0.0f, 0.0f, 0.0f)); \ + SOCKET_VECTOR(tex_mapping.rotation, "Rotation", make_float3(0.0f, 0.0f, 0.0f)); \ + SOCKET_VECTOR(tex_mapping.scale, "Scale", make_float3(1.0f, 1.0f, 1.0f)); \ + \ + SOCKET_VECTOR(tex_mapping.min, "Min", make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX)); \ + SOCKET_VECTOR(tex_mapping.max, "Max", make_float3(FLT_MAX, FLT_MAX, FLT_MAX)); \ + SOCKET_BOOLEAN(tex_mapping.use_minmax, "Use Min Max", false); \ + \ + static NodeEnum mapping_axis_enum; \ + mapping_axis_enum.insert("none", TextureMapping::NONE); \ + mapping_axis_enum.insert("X", TextureMapping::X); \ + mapping_axis_enum.insert("Y", TextureMapping::Y); \ + mapping_axis_enum.insert("Z", TextureMapping::Z); \ + SOCKET_ENUM(tex_mapping.x_mapping, "X Mapping", mapping_axis_enum, TextureMapping::X); \ + SOCKET_ENUM(tex_mapping.y_mapping, "Y Mapping", mapping_axis_enum, TextureMapping::Y); \ + SOCKET_ENUM(tex_mapping.z_mapping, "z mapping", mapping_axis_enum, TextureMapping::Z); \ + \ + static NodeEnum mapping_type_enum; \ + mapping_type_enum.insert("point", TextureMapping::POINT); \ + mapping_type_enum.insert("texture", TextureMapping::TEXTURE); \ + mapping_type_enum.insert("vector", TextureMapping::VECTOR); \ + mapping_type_enum.insert("normal", TextureMapping::NORMAL); \ + SOCKET_ENUM(tex_mapping.type, "Type", mapping_type_enum, TextureMapping::TEXTURE); \ + \ + static NodeEnum mapping_projection_enum; \ + mapping_projection_enum.insert("flat", TextureMapping::FLAT); \ + mapping_projection_enum.insert("cube", TextureMapping::CUBE); \ + mapping_projection_enum.insert("tube", TextureMapping::TUBE); \ + mapping_projection_enum.insert("sphere", TextureMapping::SPHERE); \ + SOCKET_ENUM(tex_mapping.projection, "Projection", mapping_projection_enum, TextureMapping::FLAT); TextureMapping::TextureMapping() { - translation = make_float3(0.0f, 0.0f, 0.0f); - rotation = make_float3(0.0f, 0.0f, 0.0f); - scale = make_float3(1.0f, 1.0f, 1.0f); - - min = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX); - max = make_float3(FLT_MAX, FLT_MAX, FLT_MAX); - - use_minmax = false; - - x_mapping = X; - y_mapping = Y; - z_mapping = Z; - - type = TEXTURE; - - projection = FLAT; } Transform TextureMapping::compute_transform() @@ -222,66 +198,60 @@ void TextureMapping::compile(OSLCompiler &compiler) /* Image Texture */ -static NodeEnum color_space_init() +NODE_DEFINE(ImageTextureNode) { - NodeEnum enm; + NodeType* type = NodeType::add("image_texture", create, NodeType::SHADER); - enm.insert("None", 0); - enm.insert("Color", 1); + TEXTURE_MAPPING_DEFINE(ImageTextureNode); - return enm; -} + SOCKET_STRING(filename, "Filename", ustring("")); -static NodeEnum image_projection_init() -{ - NodeEnum enm; + static NodeEnum color_space_enum; + color_space_enum.insert("None", NODE_COLOR_SPACE_NONE); + color_space_enum.insert("Color", NODE_COLOR_SPACE_COLOR); + SOCKET_ENUM(color_space, "Color Space", color_space_enum, NODE_COLOR_SPACE_COLOR); - enm.insert("Flat", NODE_IMAGE_PROJ_FLAT); - enm.insert("Box", NODE_IMAGE_PROJ_BOX); - enm.insert("Sphere", NODE_IMAGE_PROJ_SPHERE); - enm.insert("Tube", NODE_IMAGE_PROJ_TUBE); + SOCKET_BOOLEAN(use_alpha, "Use Alpha", true); - return enm; -} + static NodeEnum interpolation_enum; + interpolation_enum.insert("closest", INTERPOLATION_CLOSEST); + interpolation_enum.insert("linear", INTERPOLATION_LINEAR); + interpolation_enum.insert("cubic", INTERPOLATION_CUBIC); + interpolation_enum.insert("smart", INTERPOLATION_SMART); + SOCKET_ENUM(interpolation, "Interpolation", interpolation_enum, INTERPOLATION_LINEAR); -static const char* get_osl_interpolation_parameter(InterpolationType interpolation) -{ - switch(interpolation) { - case INTERPOLATION_CLOSEST: - return "closest"; - case INTERPOLATION_CUBIC: - return "cubic"; - case INTERPOLATION_SMART: - return "smart"; - case INTERPOLATION_LINEAR: - default: - return "linear"; - } -} + static NodeEnum extension_enum; + extension_enum.insert("periodic", EXTENSION_REPEAT); + extension_enum.insert("clamp", EXTENSION_EXTEND); + extension_enum.insert("black", EXTENSION_CLIP); + SOCKET_ENUM(extension, "Extension", extension_enum, EXTENSION_REPEAT); + + static NodeEnum projection_enum; + projection_enum.insert("Flat", NODE_IMAGE_PROJ_FLAT); + projection_enum.insert("Box", NODE_IMAGE_PROJ_BOX); + projection_enum.insert("Sphere", NODE_IMAGE_PROJ_SPHERE); + projection_enum.insert("Tube", NODE_IMAGE_PROJ_TUBE); + SOCKET_ENUM(projection, "Projection", projection_enum, NODE_IMAGE_PROJ_FLAT); + + SOCKET_FLOAT(projection_blend, "Projection Blend", 0.0f); -NodeEnum ImageTextureNode::color_space_enum = color_space_init(); -NodeEnum ImageTextureNode::projection_enum = image_projection_init(); + SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_UV); + + SOCKET_OUT_COLOR(color, "Color"); + SOCKET_OUT_FLOAT(alpha, "Alpha"); + + return type; +} ImageTextureNode::ImageTextureNode() -: ImageSlotTextureNode("image_texture") +: ImageSlotTextureNode(node_type) { image_manager = NULL; slot = -1; is_float = -1; is_linear = false; - use_alpha = true; - filename = ""; builtin_data = NULL; - color_space = NODE_COLOR_SPACE_COLOR; - projection = NODE_IMAGE_PROJ_FLAT; - interpolation = INTERPOLATION_LINEAR; - extension = EXTENSION_REPEAT; - projection_blend = 0.0f; animated = false; - - add_input("Vector", SocketType::POINT, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_UV); - add_output("Color", SocketType::COLOR); - add_output("Alpha", SocketType::FLOAT); } ImageTextureNode::~ImageTextureNode() @@ -410,7 +380,7 @@ void ImageTextureNode::compile(OSLCompiler& compiler) } if(slot == -1) { - compiler.parameter("filename", filename.c_str()); + compiler.parameter(this, "filename"); } else { /* TODO(sergey): It's not so simple to pass custom attribute @@ -425,61 +395,62 @@ void ImageTextureNode::compile(OSLCompiler& compiler) compiler.parameter("color_space", "Linear"); else compiler.parameter("color_space", "sRGB"); - compiler.parameter("projection", projection); - compiler.parameter("projection_blend", projection_blend); - compiler.parameter("is_float", is_float); + compiler.parameter(this, "projection"); + compiler.parameter(this, "projection_blend"); + compiler.parameter(this, "is_float"); compiler.parameter("use_alpha", !alpha_out->links.empty()); - compiler.parameter("interpolation", get_osl_interpolation_parameter(interpolation)); - - switch(extension) { - case EXTENSION_EXTEND: - compiler.parameter("extension", "clamp"); - break; - case EXTENSION_CLIP: - compiler.parameter("extension", "black"); - break; - case EXTENSION_REPEAT: - default: - compiler.parameter("extension", "periodic"); - break; - } + compiler.parameter(this, "interpolation"); + compiler.parameter(this, "extension"); compiler.add(this, "node_image_texture"); } /* Environment Texture */ -static NodeEnum env_projection_init() +NODE_DEFINE(EnvironmentTextureNode) { - NodeEnum enm; + NodeType* type = NodeType::add("environment_texture", create, NodeType::SHADER); - enm.insert("Equirectangular", 0); - enm.insert("Mirror Ball", 1); + TEXTURE_MAPPING_DEFINE(EnvironmentTextureNode); - return enm; -} + SOCKET_STRING(filename, "Filename", ustring("")); + + static NodeEnum color_space_enum; + color_space_enum.insert("None", NODE_COLOR_SPACE_NONE); + color_space_enum.insert("Color", NODE_COLOR_SPACE_COLOR); + SOCKET_ENUM(color_space, "Color Space", color_space_enum, NODE_COLOR_SPACE_COLOR); + + SOCKET_BOOLEAN(use_alpha, "Use Alpha", true); -NodeEnum EnvironmentTextureNode::color_space_enum = color_space_init(); -NodeEnum EnvironmentTextureNode::projection_enum = env_projection_init(); + static NodeEnum interpolation_enum; + interpolation_enum.insert("closest", INTERPOLATION_CLOSEST); + interpolation_enum.insert("linear", INTERPOLATION_LINEAR); + interpolation_enum.insert("cubic", INTERPOLATION_CUBIC); + interpolation_enum.insert("smart", INTERPOLATION_SMART); + SOCKET_ENUM(interpolation, "Interpolation", interpolation_enum, INTERPOLATION_LINEAR); + + static NodeEnum projection_enum; + projection_enum.insert("Equirectangular", NODE_ENVIRONMENT_EQUIRECTANGULAR); + projection_enum.insert("Mirror Ball", NODE_ENVIRONMENT_MIRROR_BALL); + SOCKET_ENUM(projection, "Projection", projection_enum, NODE_ENVIRONMENT_EQUIRECTANGULAR); + + SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_POSITION); + + SOCKET_OUT_COLOR(color, "Color"); + SOCKET_OUT_FLOAT(alpha, "Alpha"); + + return type; +} EnvironmentTextureNode::EnvironmentTextureNode() -: ImageSlotTextureNode("environment_texture") +: ImageSlotTextureNode(node_type) { image_manager = NULL; slot = -1; is_float = -1; is_linear = false; - use_alpha = true; - filename = ""; builtin_data = NULL; - color_space = NODE_COLOR_SPACE_COLOR; - interpolation = INTERPOLATION_LINEAR; - projection = NODE_ENVIRONMENT_EQUIRECTANGULAR; animated = false; - - add_input("Vector", SocketType::VECTOR, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_POSITION); - add_output("Color", SocketType::COLOR); - add_output("Alpha", SocketType::FLOAT); } EnvironmentTextureNode::~EnvironmentTextureNode() @@ -597,20 +568,19 @@ void EnvironmentTextureNode::compile(OSLCompiler& compiler) } if(slot == -1) { - compiler.parameter("filename", filename.c_str()); + compiler.parameter(this, "filename"); } else { compiler.parameter("filename", string_printf("@%d", slot).c_str()); } - compiler.parameter("projection", projection_enum[projection]); + compiler.parameter(this, "projection"); if(is_linear || color_space != NODE_COLOR_SPACE_COLOR) compiler.parameter("color_space", "Linear"); else compiler.parameter("color_space", "sRGB"); - compiler.parameter("interpolation", get_osl_interpolation_parameter(interpolation)); - - compiler.parameter("is_float", is_float); + compiler.parameter(this, "interpolation"); + compiler.parameter(this, "is_float"); compiler.parameter("use_alpha", !alpha_out->links.empty()); compiler.add(this, "node_environment_texture"); } @@ -738,29 +708,31 @@ static void sky_texture_precompute_new(SunSky *sunsky, float3 dir, float turbidi arhosekskymodelstate_free(sky_state); } -static NodeEnum sky_type_init() +NODE_DEFINE(SkyTextureNode) { - NodeEnum enm; + NodeType* type = NodeType::add("sky_texture", create, NodeType::SHADER); - enm.insert("Preetham", NODE_SKY_OLD); - enm.insert("Hosek / Wilkie", NODE_SKY_NEW); + TEXTURE_MAPPING_DEFINE(SkyTextureNode); - return enm; -} + static NodeEnum type_enum; + type_enum.insert("Preetham", NODE_SKY_OLD); + type_enum.insert("Hosek / Wilkie", NODE_SKY_NEW); + SOCKET_ENUM(type, "Type", type_enum, NODE_SKY_NEW); -NodeEnum SkyTextureNode::type_enum = sky_type_init(); + SOCKET_VECTOR(sun_direction, "Sun Direction", make_float3(0.0f, 0.0f, 1.0f)); + SOCKET_FLOAT(turbidity, "Turbidity", 2.2f); + SOCKET_FLOAT(ground_albedo, "Ground Albedo", 0.3f); + + SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED); + + SOCKET_OUT_COLOR(color, "Color"); + + return type; +} SkyTextureNode::SkyTextureNode() -: TextureNode("sky_texture") +: TextureNode(node_type) { - type = NODE_SKY_NEW; - - sun_direction = make_float3(0.0f, 0.0f, 1.0f); - turbidity = 2.2f; - ground_albedo = 0.3f; - - add_input("Vector", SocketType::VECTOR, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_POSITION); - add_output("Color", SocketType::COLOR); } void SkyTextureNode::compile(SVMCompiler& compiler) @@ -806,7 +778,7 @@ void SkyTextureNode::compile(OSLCompiler& compiler) else assert(false); - compiler.parameter("sky_model", type_enum[type]); + compiler.parameter("sky_model", type); compiler.parameter("theta", sunsky.theta); compiler.parameter("phi", sunsky.phi); compiler.parameter_color("radiance", make_float3(sunsky.radiance_x, sunsky.radiance_y, sunsky.radiance_z)); @@ -818,31 +790,35 @@ void SkyTextureNode::compile(OSLCompiler& compiler) /* Gradient Texture */ -static NodeEnum gradient_type_init() +NODE_DEFINE(GradientTextureNode) { - NodeEnum enm; + NodeType* type = NodeType::add("gradient_texture", create, NodeType::SHADER); - enm.insert("Linear", NODE_BLEND_LINEAR); - enm.insert("Quadratic", NODE_BLEND_QUADRATIC); - enm.insert("Easing", NODE_BLEND_EASING); - enm.insert("Diagonal", NODE_BLEND_DIAGONAL); - enm.insert("Radial", NODE_BLEND_RADIAL); - enm.insert("Quadratic Sphere", NODE_BLEND_QUADRATIC_SPHERE); - enm.insert("Spherical", NODE_BLEND_SPHERICAL); + TEXTURE_MAPPING_DEFINE(GradientTextureNode); - return enm; -} + static NodeEnum type_enum; + type_enum.insert("Linear", NODE_BLEND_LINEAR); + type_enum.insert("Quadratic", NODE_BLEND_QUADRATIC); + type_enum.insert("Easing", NODE_BLEND_EASING); + type_enum.insert("Diagonal", NODE_BLEND_DIAGONAL); + type_enum.insert("Radial", NODE_BLEND_RADIAL); + type_enum.insert("Quadratic Sphere", NODE_BLEND_QUADRATIC_SPHERE); + type_enum.insert("Spherical", NODE_BLEND_SPHERICAL); + type_enum.insert("Bands", NODE_WAVE_BANDS); + type_enum.insert("Rings", NODE_WAVE_RINGS); + SOCKET_ENUM(type, "Type", type_enum, NODE_BLEND_LINEAR); + + SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED); -NodeEnum GradientTextureNode::type_enum = gradient_type_init(); + SOCKET_OUT_COLOR(color, "Color"); + SOCKET_OUT_FLOAT(fac, "Fac"); + + return type; +} GradientTextureNode::GradientTextureNode() -: TextureNode("gradient_texture") +: TextureNode(node_type) { - type = NODE_BLEND_LINEAR; - - add_input("Vector", SocketType::POINT, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED); - add_output("Color", SocketType::COLOR); - add_output("Fac", SocketType::FLOAT); } void GradientTextureNode::compile(SVMCompiler& compiler) @@ -867,22 +843,32 @@ void GradientTextureNode::compile(OSLCompiler& compiler) { tex_mapping.compile(compiler); - compiler.parameter("type", type_enum[type]); + compiler.parameter(this, "type"); compiler.add(this, "node_gradient_texture"); } /* Noise Texture */ -NoiseTextureNode::NoiseTextureNode() -: TextureNode("noise_texture") +NODE_DEFINE(NoiseTextureNode) { - add_input("Vector", SocketType::POINT, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED); - add_input("Scale", SocketType::FLOAT, 1.0f); - add_input("Detail", SocketType::FLOAT, 2.0f); - add_input("Distortion", SocketType::FLOAT, 0.0f); + NodeType* type = NodeType::add("noise_texture", create, NodeType::SHADER); + + TEXTURE_MAPPING_DEFINE(NoiseTextureNode); + + SOCKET_IN_FLOAT(scale, "Scale", 1.0f); + SOCKET_IN_FLOAT(detail, "Detail", 2.0f); + SOCKET_IN_FLOAT(distortion, "Distortion", 0.0f); + SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED); + + SOCKET_OUT_COLOR(color, "Color"); + SOCKET_OUT_FLOAT(fac, "Fac"); + + return type; +} - add_output("Color", SocketType::COLOR); - add_output("Fac", SocketType::FLOAT); +NoiseTextureNode::NoiseTextureNode() +: TextureNode(node_type) +{ } void NoiseTextureNode::compile(SVMCompiler& compiler) @@ -906,9 +892,9 @@ void NoiseTextureNode::compile(SVMCompiler& compiler) compiler.stack_assign_if_linked(color_out), compiler.stack_assign_if_linked(fac_out))); compiler.add_node( - __float_as_int(scale_in->value_float()), - __float_as_int(detail_in->value_float()), - __float_as_int(distortion_in->value_float())); + __float_as_int(scale), + __float_as_int(detail), + __float_as_int(distortion)); tex_mapping.compile_end(compiler, vector_in, vector_offset); } @@ -922,28 +908,29 @@ void NoiseTextureNode::compile(OSLCompiler& compiler) /* Voronoi Texture */ -static NodeEnum voronoi_coloring_init() +NODE_DEFINE(VoronoiTextureNode) { - NodeEnum enm; + NodeType* type = NodeType::add("voronoi_texture", create, NodeType::SHADER); - enm.insert("Intensity", NODE_VORONOI_INTENSITY); - enm.insert("Cells", NODE_VORONOI_CELLS); + TEXTURE_MAPPING_DEFINE(VoronoiTextureNode); - return enm; -} + static NodeEnum coloring_enum; + coloring_enum.insert("Intensity", NODE_VORONOI_INTENSITY); + coloring_enum.insert("Cells", NODE_VORONOI_CELLS); + SOCKET_ENUM(coloring, "Coloring", coloring_enum, NODE_VORONOI_INTENSITY); -NodeEnum VoronoiTextureNode::coloring_enum = voronoi_coloring_init(); + SOCKET_IN_FLOAT(scale, "Scale", 1.0f); + SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED); -VoronoiTextureNode::VoronoiTextureNode() -: TextureNode("voronoi_texture") -{ - coloring = NODE_VORONOI_INTENSITY; + SOCKET_OUT_COLOR(color, "Color"); + SOCKET_OUT_FLOAT(fac, "Fac"); - add_input("Scale", SocketType::FLOAT, 1.0f); - add_input("Vector", SocketType::POINT, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED); + return type; +} - add_output("Color", SocketType::COLOR); - add_output("Fac", SocketType::FLOAT); +VoronoiTextureNode::VoronoiTextureNode() +: TextureNode(node_type) +{ } void VoronoiTextureNode::compile(SVMCompiler& compiler) @@ -962,7 +949,7 @@ void VoronoiTextureNode::compile(SVMCompiler& compiler) vector_offset, compiler.stack_assign(fac_out), compiler.stack_assign(color_out)), - __float_as_int(scale_in->value_float())); + __float_as_int(scale)); tex_mapping.compile_end(compiler, vector_in, vector_offset); } @@ -971,42 +958,43 @@ void VoronoiTextureNode::compile(OSLCompiler& compiler) { tex_mapping.compile(compiler); - compiler.parameter("coloring", coloring_enum[coloring]); + compiler.parameter(this, "coloring"); compiler.add(this, "node_voronoi_texture"); } /* Musgrave Texture */ -static NodeEnum musgrave_type_init() +NODE_DEFINE(MusgraveTextureNode) { - NodeEnum enm; + NodeType* type = NodeType::add("musgrave_texture", create, NodeType::SHADER); - enm.insert("Multifractal", NODE_MUSGRAVE_MULTIFRACTAL); - enm.insert("fBM", NODE_MUSGRAVE_FBM); - enm.insert("Hybrid Multifractal", NODE_MUSGRAVE_HYBRID_MULTIFRACTAL); - enm.insert("Ridged Multifractal", NODE_MUSGRAVE_RIDGED_MULTIFRACTAL); - enm.insert("Hetero Terrain", NODE_MUSGRAVE_HETERO_TERRAIN); + TEXTURE_MAPPING_DEFINE(MusgraveTextureNode); - return enm; -} + static NodeEnum type_enum; + type_enum.insert("Multifractal", NODE_MUSGRAVE_MULTIFRACTAL); + type_enum.insert("fBM", NODE_MUSGRAVE_FBM); + type_enum.insert("Hybrid Multifractal", NODE_MUSGRAVE_HYBRID_MULTIFRACTAL); + type_enum.insert("Ridged Multifractal", NODE_MUSGRAVE_RIDGED_MULTIFRACTAL); + type_enum.insert("Hetero Terrain", NODE_MUSGRAVE_HETERO_TERRAIN); + SOCKET_ENUM(type, "Type", type_enum, NODE_MUSGRAVE_FBM); -NodeEnum MusgraveTextureNode::type_enum = musgrave_type_init(); + SOCKET_IN_FLOAT(scale, "Scale", 1.0f); + SOCKET_IN_FLOAT(detail, "Detail", 2.0f); + SOCKET_IN_FLOAT(dimension, "Dimension", 2.0f); + SOCKET_IN_FLOAT(lacunarity, "Lacunarity", 1.0f); + SOCKET_IN_FLOAT(offset, "Offset", 0.0f); + SOCKET_IN_FLOAT(gain, "Gain", 1.0f); + SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED); -MusgraveTextureNode::MusgraveTextureNode() -: TextureNode("musgrave_texture") -{ - type = NODE_MUSGRAVE_FBM; + SOCKET_OUT_COLOR(color, "Color"); + SOCKET_OUT_FLOAT(fac, "Fac"); - add_input("Scale", SocketType::FLOAT, 1.0f); - add_input("Detail", SocketType::FLOAT, 2.0f); - add_input("Vector", SocketType::POINT, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED); - add_input("Dimension", SocketType::FLOAT, 2.0f); - add_input("Lacunarity", SocketType::FLOAT, 1.0f); - add_input("Offset", SocketType::FLOAT, 0.0f); - add_input("Gain", SocketType::FLOAT, 1.0f); + return type; +} - add_output("Fac", SocketType::FLOAT); - add_output("Color", SocketType::COLOR); +MusgraveTextureNode::MusgraveTextureNode() +: TextureNode(node_type) +{ } void MusgraveTextureNode::compile(SVMCompiler& compiler) @@ -1037,12 +1025,12 @@ void MusgraveTextureNode::compile(SVMCompiler& compiler) compiler.encode_uchar4( compiler.stack_assign_if_linked(gain_in), compiler.stack_assign_if_linked(scale_in))); - compiler.add_node(__float_as_int(dimension_in->value_float()), - __float_as_int(lacunarity_in->value_float()), - __float_as_int(detail_in->value_float()), - __float_as_int(offset_in->value_float())); - compiler.add_node(__float_as_int(gain_in->value_float()), - __float_as_int(scale_in->value_float())); + compiler.add_node(__float_as_int(dimension), + __float_as_int(lacunarity), + __float_as_int(detail), + __float_as_int(offset)); + compiler.add_node(__float_as_int(gain), + __float_as_int(scale)); tex_mapping.compile_end(compiler, vector_in, vector_offset); } @@ -1051,50 +1039,43 @@ void MusgraveTextureNode::compile(OSLCompiler& compiler) { tex_mapping.compile(compiler); - compiler.parameter("type", type_enum[type]); - + compiler.parameter(this, "type"); compiler.add(this, "node_musgrave_texture"); } /* Wave Texture */ -static NodeEnum wave_type_init() +NODE_DEFINE(WaveTextureNode) { - NodeEnum enm; + NodeType* type = NodeType::add("wave_texture", create, NodeType::SHADER); - enm.insert("Bands", NODE_WAVE_BANDS); - enm.insert("Rings", NODE_WAVE_RINGS); + TEXTURE_MAPPING_DEFINE(WaveTextureNode); - return enm; -} + static NodeEnum type_enum; + type_enum.insert("Bands", NODE_WAVE_BANDS); + type_enum.insert("Rings", NODE_WAVE_RINGS); + SOCKET_ENUM(type, "Type", type_enum, NODE_WAVE_BANDS); -static NodeEnum wave_profile_init() -{ - NodeEnum enm; + static NodeEnum profile_enum; + profile_enum.insert("Sine", NODE_WAVE_PROFILE_SIN); + profile_enum.insert("Saw", NODE_WAVE_PROFILE_SAW); + SOCKET_ENUM(profile, "Profile", profile_enum, NODE_WAVE_PROFILE_SIN); - enm.insert("Sine", NODE_WAVE_PROFILE_SIN); - enm.insert("Saw", NODE_WAVE_PROFILE_SAW); + SOCKET_IN_FLOAT(scale, "Scale", 1.0f); + SOCKET_IN_FLOAT(distortion, "Distortion", 0.0f); + SOCKET_IN_FLOAT(detail, "Detail", 2.0f); + SOCKET_IN_FLOAT(detail_scale, "Detail Scale", 0.0f); + SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED); - return enm; -} + SOCKET_OUT_COLOR(color, "Color"); + SOCKET_OUT_FLOAT(fac, "Fac"); -NodeEnum WaveTextureNode::type_enum = wave_type_init(); -NodeEnum WaveTextureNode::profile_enum = wave_profile_init(); + return type; +} WaveTextureNode::WaveTextureNode() -: TextureNode("wave_texture") +: TextureNode(node_type) { - type = NODE_WAVE_BANDS; - profile = NODE_WAVE_PROFILE_SIN; - - add_input("Scale", SocketType::FLOAT, 1.0f); - add_input("Distortion", SocketType::FLOAT, 0.0f); - add_input("Detail", SocketType::FLOAT, 2.0f); - add_input("Detail Scale", SocketType::FLOAT, 1.0f); - add_input("Vector", SocketType::POINT, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED); - - add_output("Color", SocketType::COLOR); - add_output("Fac", SocketType::FLOAT); } void WaveTextureNode::compile(SVMCompiler& compiler) @@ -1123,10 +1104,10 @@ void WaveTextureNode::compile(SVMCompiler& compiler) profile); compiler.add_node( - __float_as_int(scale_in->value_float()), - __float_as_int(detail_in->value_float()), - __float_as_int(distortion_in->value_float()), - __float_as_int(dscale_in->value_float())); + __float_as_int(scale), + __float_as_int(detail), + __float_as_int(distortion), + __float_as_int(detail_scale)); tex_mapping.compile_end(compiler, vector_in, vector_offset); } @@ -1135,25 +1116,35 @@ void WaveTextureNode::compile(OSLCompiler& compiler) { tex_mapping.compile(compiler); - compiler.parameter("type", type_enum[type]); - compiler.parameter("profile", profile_enum[profile]); + compiler.parameter(this, "type"); + compiler.parameter(this, "profile"); compiler.add(this, "node_wave_texture"); } /* Magic Texture */ -MagicTextureNode::MagicTextureNode() -: TextureNode("magic_texture") +NODE_DEFINE(MagicTextureNode) { - depth = 2; + NodeType* type = NodeType::add("magic_texture", create, NodeType::SHADER); + + TEXTURE_MAPPING_DEFINE(MagicTextureNode); - add_input("Vector", SocketType::POINT, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED); - add_input("Scale", SocketType::FLOAT, 5.0f); - add_input("Distortion", SocketType::FLOAT, 1.0f); + SOCKET_INT(depth, "Depth", 2); - add_output("Color", SocketType::COLOR); - add_output("Fac", SocketType::FLOAT); + SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED); + SOCKET_IN_FLOAT(scale, "Scale", 5.0f); + SOCKET_IN_FLOAT(distortion, "Distortion", 1.0f); + + SOCKET_OUT_COLOR(color, "Color"); + SOCKET_OUT_FLOAT(fac, "Fac"); + + return type; +} + +MagicTextureNode::MagicTextureNode() +: TextureNode(node_type) +{ } void MagicTextureNode::compile(SVMCompiler& compiler) @@ -1176,8 +1167,8 @@ void MagicTextureNode::compile(SVMCompiler& compiler) compiler.stack_assign_if_linked(scale_in), compiler.stack_assign_if_linked(distortion_in))); compiler.add_node( - __float_as_int(scale_in->value_float()), - __float_as_int(distortion_in->value_float())); + __float_as_int(scale), + __float_as_int(distortion)); tex_mapping.compile_end(compiler, vector_in, vector_offset); } @@ -1186,22 +1177,32 @@ void MagicTextureNode::compile(OSLCompiler& compiler) { tex_mapping.compile(compiler); - compiler.parameter("depth", depth); + compiler.parameter(this, "depth"); compiler.add(this, "node_magic_texture"); } /* Checker Texture */ -CheckerTextureNode::CheckerTextureNode() -: TextureNode("checker_texture") +NODE_DEFINE(CheckerTextureNode) { - add_input("Vector", SocketType::POINT, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED); - add_input("Color1", SocketType::COLOR); - add_input("Color2", SocketType::COLOR); - add_input("Scale", SocketType::FLOAT, 1.0f); + NodeType* type = NodeType::add("checker_texture", create, NodeType::SHADER); + + TEXTURE_MAPPING_DEFINE(CheckerTextureNode); - add_output("Color", SocketType::COLOR); - add_output("Fac", SocketType::FLOAT); + SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED); + SOCKET_IN_COLOR(color1, "Color1", make_float3(0.0f, 0.0f, 0.0f)); + SOCKET_IN_COLOR(color2, "Color2", make_float3(0.0f, 0.0f, 0.0f)); + SOCKET_IN_FLOAT(scale, "Scale", 1.0f); + + SOCKET_OUT_COLOR(color, "Color"); + SOCKET_OUT_FLOAT(fac, "Fac"); + + return type; +} + +CheckerTextureNode::CheckerTextureNode() +: TextureNode(node_type) +{ } void CheckerTextureNode::compile(SVMCompiler& compiler) @@ -1225,7 +1226,7 @@ void CheckerTextureNode::compile(SVMCompiler& compiler) compiler.encode_uchar4( compiler.stack_assign_if_linked(color_out), compiler.stack_assign_if_linked(fac_out)), - __float_as_int(scale_in->value_float())); + __float_as_int(scale)); tex_mapping.compile_end(compiler, vector_in, vector_offset); } @@ -1239,26 +1240,37 @@ void CheckerTextureNode::compile(OSLCompiler& compiler) /* Brick Texture */ -BrickTextureNode::BrickTextureNode() -: TextureNode("brick_texture") +NODE_DEFINE(BrickTextureNode) { - offset = 0.5f; - offset_frequency = 2; - squash = 1.0f; - squash_frequency = 2; - - add_input("Vector", SocketType::POINT, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED); - add_input("Color1", SocketType::COLOR); - add_input("Color2", SocketType::COLOR); - add_input("Mortar", SocketType::COLOR); - add_input("Scale", SocketType::FLOAT, 5.0f); - add_input("Mortar Size", SocketType::FLOAT, 0.02f); - add_input("Bias", SocketType::FLOAT, 0.0f); - add_input("Brick Width", SocketType::FLOAT, 0.5f); - add_input("Row Height", SocketType::FLOAT, 0.25f); + NodeType* type = NodeType::add("brick_texture", create, NodeType::SHADER); - add_output("Color", SocketType::COLOR); - add_output("Fac", SocketType::FLOAT); + TEXTURE_MAPPING_DEFINE(BrickTextureNode); + + SOCKET_FLOAT(offset, "Offset", 0.5f); + SOCKET_INT(offset_frequency, "Offset Frequency", 2); + SOCKET_FLOAT(squash, "Squash", 1.0f); + SOCKET_INT(squash_frequency, "Squash Frequency", 2); + + SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED); + + SOCKET_IN_COLOR(color1, "Color1", make_float3(0.0f, 0.0f, 0.0f)); + SOCKET_IN_COLOR(color2, "Color2", make_float3(0.0f, 0.0f, 0.0f)); + SOCKET_IN_COLOR(mortar, "Mortar", make_float3(0.0f, 0.0f, 0.0f)); + SOCKET_IN_FLOAT(scale, "Scale", 5.0f); + SOCKET_IN_FLOAT(mortar_size, "Mortar Size", 0.02f); + SOCKET_IN_FLOAT(bias, "Bias", 0.0f); + SOCKET_IN_FLOAT(brick_width, "Brick Width", 0.5f); + SOCKET_IN_FLOAT(row_height, "Row Height", 0.25f); + + SOCKET_OUT_COLOR(color, "Color"); + SOCKET_OUT_FLOAT(fac, "Fac"); + + return type; +} + +BrickTextureNode::BrickTextureNode() +: TextureNode(node_type) +{ } void BrickTextureNode::compile(SVMCompiler& compiler) @@ -1295,12 +1307,12 @@ void BrickTextureNode::compile(SVMCompiler& compiler) compiler.stack_assign_if_linked(fac_out))); compiler.add_node(compiler.encode_uchar4(offset_frequency, squash_frequency), - __float_as_int(scale_in->value_float()), - __float_as_int(mortar_size_in->value_float()), - __float_as_int(bias_in->value_float())); + __float_as_int(scale), + __float_as_int(mortar_size), + __float_as_int(bias)); - compiler.add_node(__float_as_int(brick_width_in->value_float()), - __float_as_int(row_height_in->value_float()), + compiler.add_node(__float_as_int(brick_width), + __float_as_int(row_height), __float_as_int(offset), __float_as_int(squash)); @@ -1311,48 +1323,55 @@ void BrickTextureNode::compile(OSLCompiler& compiler) { tex_mapping.compile(compiler); - compiler.parameter("offset", offset); - compiler.parameter("offset_frequency", offset_frequency); - compiler.parameter("squash", squash); - compiler.parameter("squash_frequency", squash_frequency); + compiler.parameter(this, "offset"); + compiler.parameter(this, "offset_frequency"); + compiler.parameter(this, "squash"); + compiler.parameter(this, "squash_frequency"); compiler.add(this, "node_brick_texture"); } /* Point Density Texture */ -static NodeEnum point_density_space_init() +NODE_DEFINE(PointDensityTextureNode) { - NodeEnum enm; + NodeType* type = NodeType::add("point_density_texture", create, NodeType::SHADER); - enm.insert("Object", NODE_TEX_VOXEL_SPACE_OBJECT); - enm.insert("World", NODE_TEX_VOXEL_SPACE_WORLD); + SOCKET_STRING(filename, "Filename", ustring("")); - return enm; -} + static NodeEnum space_enum; + space_enum.insert("Object", NODE_TEX_VOXEL_SPACE_OBJECT); + space_enum.insert("World", NODE_TEX_VOXEL_SPACE_WORLD); + SOCKET_ENUM(space, "Space", space_enum, NODE_TEX_VOXEL_SPACE_OBJECT); + + static NodeEnum interpolation_enum; + interpolation_enum.insert("closest", INTERPOLATION_CLOSEST); + interpolation_enum.insert("linear", INTERPOLATION_LINEAR); + interpolation_enum.insert("cubic", INTERPOLATION_CUBIC); + interpolation_enum.insert("smart", INTERPOLATION_SMART); + SOCKET_ENUM(interpolation, "Interpolation", interpolation_enum, INTERPOLATION_LINEAR); + + SOCKET_TRANSFORM(tfm, "Transform", transform_identity()); -NodeEnum PointDensityTextureNode::space_enum = point_density_space_init(); + SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_POSITION); + + SOCKET_OUT_FLOAT(density, "Density"); + SOCKET_OUT_COLOR(color, "Color"); + + return type; +} PointDensityTextureNode::PointDensityTextureNode() -: ShaderNode("point_density") +: ShaderNode(node_type) { image_manager = NULL; slot = -1; - filename = ""; - space = NODE_TEX_VOXEL_SPACE_OBJECT; builtin_data = NULL; - interpolation = INTERPOLATION_LINEAR; - - tfm = transform_identity(); - - add_input("Vector", SocketType::POINT, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_POSITION); - add_output("Density", SocketType::FLOAT); - add_output("Color", SocketType::COLOR); } PointDensityTextureNode::~PointDensityTextureNode() { if(image_manager) { - image_manager->remove_image(filename, + image_manager->remove_image(filename.string(), builtin_data, interpolation, EXTENSION_CLIP); @@ -1390,7 +1409,7 @@ void PointDensityTextureNode::compile(SVMCompiler& compiler) if(use_density || use_color) { if(slot == -1) { bool is_float, is_linear; - slot = image_manager->add_image(filename, builtin_data, + slot = image_manager->add_image(filename.string(), builtin_data, false, 0, is_float, is_linear, interpolation, @@ -1442,7 +1461,7 @@ void PointDensityTextureNode::compile(OSLCompiler& compiler) if(use_density || use_color) { if(slot == -1) { bool is_float, is_linear; - slot = image_manager->add_image(filename, builtin_data, + slot = image_manager->add_image(filename.string(), builtin_data, false, 0, is_float, is_linear, interpolation, @@ -1457,33 +1476,30 @@ void PointDensityTextureNode::compile(OSLCompiler& compiler) compiler.parameter("mapping", transform_transpose(tfm)); compiler.parameter("use_mapping", 1); } - switch(interpolation) { - case INTERPOLATION_CLOSEST: - compiler.parameter("interpolation", "closest"); - break; - case INTERPOLATION_CUBIC: - compiler.parameter("interpolation", "cubic"); - break; - case INTERPOLATION_LINEAR: - default: - compiler.parameter("interpolation", "linear"); - break; - } - + compiler.parameter(this, "interpolation"); compiler.add(this, "node_voxel_texture"); } } /* Normal */ -NormalNode::NormalNode() -: ShaderNode("normal") +NODE_DEFINE(NormalNode) { - direction = make_float3(0.0f, 0.0f, 1.0f); + NodeType* type = NodeType::add("normal", create, NodeType::SHADER); + + SOCKET_VECTOR(direction, "direction", make_float3(0.0f, 0.0f, 0.0f)); + + SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f)); + + SOCKET_OUT_NORMAL(normal, "Normal"); + SOCKET_OUT_FLOAT(dot, "Dot"); - add_input("Normal", SocketType::NORMAL); - add_output("Normal", SocketType::NORMAL); - add_output("Dot", SocketType::FLOAT); + return type; +} + +NormalNode::NormalNode() +: ShaderNode(node_type) +{ } void NormalNode::compile(SVMCompiler& compiler) @@ -1504,17 +1520,27 @@ void NormalNode::compile(SVMCompiler& compiler) void NormalNode::compile(OSLCompiler& compiler) { - compiler.parameter_normal("direction", direction); + compiler.parameter(this, "direction"); compiler.add(this, "node_normal"); } /* Mapping */ +NODE_DEFINE(MappingNode) +{ + NodeType* type = NodeType::add("mapping", create, NodeType::SHADER); + + TEXTURE_MAPPING_DEFINE(MappingNode); + + SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f)); + SOCKET_OUT_POINT(vector, "Vector"); + + return type; +} + MappingNode::MappingNode() -: ShaderNode("mapping") +: ShaderNode(node_type) { - add_input("Vector", SocketType::POINT); - add_output("Vector", SocketType::POINT); } void MappingNode::compile(SVMCompiler& compiler) @@ -1538,17 +1564,25 @@ void MappingNode::compile(OSLCompiler& compiler) /* RGBToBW */ +NODE_DEFINE(RGBToBWNode) +{ + NodeType* type = NodeType::add("rgb_to_bw", create, NodeType::SHADER); + + SOCKET_IN_POINT(color, "Color", make_float3(0.0f, 0.0f, 0.0f)); + SOCKET_OUT_POINT(val, "Val"); + + return type; +} + RGBToBWNode::RGBToBWNode() -: ShaderNode("rgb_to_bw") +: ShaderNode(node_type) { - add_input("Color", SocketType::COLOR); - add_output("Val", SocketType::FLOAT); } bool RGBToBWNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) { if(inputs[0]->link == NULL) { - optimized->set(linear_rgb_to_gray(inputs[0]->value())); + optimized->set(linear_rgb_to_gray(color)); return true; } @@ -1570,82 +1604,94 @@ void RGBToBWNode::compile(OSLCompiler& compiler) /* Convert */ -ConvertNode::ConvertNode(SocketType::Type from_, SocketType::Type to_, bool autoconvert) -: ShaderNode("convert") +const NodeType* ConvertNode::node_types[ConvertNode::MAX_TYPE][ConvertNode::MAX_TYPE]; +bool ConvertNode::initialized = ConvertNode::register_types(); + +Node* ConvertNode::create(const NodeType *type) { - from = from_; - to = to_; + return new ConvertNode(type->inputs[0].type, type->outputs[0].type); +} - if(autoconvert) { - if(from == to) - special_type = SHADER_SPECIAL_TYPE_PROXY; - else - special_type = SHADER_SPECIAL_TYPE_AUTOCONVERT; +bool ConvertNode::register_types() +{ + const int num_types = 8; + SocketType::Type types[num_types] = {SocketType::FLOAT, + SocketType::INT, + SocketType::COLOR, + SocketType::VECTOR, + SocketType::POINT, + SocketType::NORMAL, + SocketType::STRING, + SocketType::CLOSURE}; + + for(size_t i = 0; i < num_types; i++) { + SocketType::Type from = types[i]; + ustring from_name(SocketType::type_name(from)); + ustring from_value_name("value_" + from_name.string()); + + for(size_t j = 0; j < num_types; j++) { + SocketType::Type to = types[j]; + ustring to_name(SocketType::type_name(to)); + ustring to_value_name("value_" + to_name.string()); + + string node_name = "convert_" + from_name.string() + "_to_" + to_name.string(); + NodeType* type = NodeType::add(node_name.c_str(), create, NodeType::SHADER); + + type->register_input(from_value_name, from_value_name, from, + SOCKET_OFFSETOF(ConvertNode, value_float), SocketType::zero_default_value(), + NULL, NULL, SocketType::LINKABLE); + type->register_output(to_value_name, to_value_name, to); + + assert(from < MAX_TYPE); + assert(to < MAX_TYPE); + + node_types[from][to] = type; + } } - if(from == SocketType::FLOAT) - add_input("value_float", SocketType::FLOAT); - else if(from == SocketType::INT) - add_input("value_int", SocketType::INT); - else if(from == SocketType::COLOR) - add_input("value_color", SocketType::COLOR); - else if(from == SocketType::VECTOR) - add_input("value_vector", SocketType::VECTOR); - else if(from == SocketType::POINT) - add_input("value_point", SocketType::POINT); - else if(from == SocketType::NORMAL) - add_input("value_normal", SocketType::NORMAL); - else if(from == SocketType::STRING) - add_input("value_string", SocketType::STRING); - else if(from == SocketType::CLOSURE) - add_input("value_closure", SocketType::CLOSURE); - else - assert(0); + return true; +} - if(to == SocketType::FLOAT) - add_output("value_float", SocketType::FLOAT); - else if(to == SocketType::INT) - add_output("value_int", SocketType::INT); - else if(to == SocketType::COLOR) - add_output("value_color", SocketType::COLOR); - else if(to == SocketType::VECTOR) - add_output("value_vector", SocketType::VECTOR); - else if(to == SocketType::POINT) - add_output("value_point", SocketType::POINT); - else if(to == SocketType::NORMAL) - add_output("value_normal", SocketType::NORMAL); - else if(to == SocketType::STRING) - add_output("value_string", SocketType::STRING); - else if(to == SocketType::CLOSURE) - add_output("value_closure", SocketType::CLOSURE); - else - assert(0); +ConvertNode::ConvertNode(SocketType::Type from_, SocketType::Type to_, bool autoconvert) +: ShaderNode(node_types[from_][to_]) +{ + from = from_; + to = to_; + + if(from == to) + special_type = SHADER_SPECIAL_TYPE_PROXY; + else if(autoconvert) + special_type = SHADER_SPECIAL_TYPE_AUTOCONVERT; } bool ConvertNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) { + /* proxy nodes should have been removed at this point */ + assert(special_type != SHADER_SPECIAL_TYPE_PROXY); + ShaderInput *in = inputs[0]; - float3 value = in->value(); /* TODO(DingTo): conversion from/to int is not supported yet, don't fold in that case */ if(in->link == NULL) { if(from == SocketType::FLOAT) { if(SocketType::is_float3(to)) { - optimized->set(make_float3(value.x, value.x, value.x)); + optimized->set(make_float3(value_float, value_float, value_float)); return true; } } else if(SocketType::is_float3(from)) { if(to == SocketType::FLOAT) { if(from == SocketType::COLOR) - optimized->set(linear_rgb_to_gray(value)); + /* color to float */ + optimized->set(linear_rgb_to_gray(value_color)); else - optimized->set(average(value)); + /* vector/point/normal to float */ + optimized->set(average(value_vector)); return true; } else if(SocketType::is_float3(to)) { - optimized->set(value); + optimized->set(value_color); return true; } } @@ -1656,8 +1702,8 @@ bool ConvertNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *opti void ConvertNode::compile(SVMCompiler& compiler) { - /* constant folding should eliminate proxy nodes */ - assert(from != to); + /* proxy nodes should have been removed at this point */ + assert(special_type != SHADER_SPECIAL_TYPE_PROXY); ShaderInput *in = inputs[0]; ShaderOutput *out = outputs[0]; @@ -1703,15 +1749,15 @@ void ConvertNode::compile(SVMCompiler& compiler) else { /* set 0,0,0 value */ compiler.add_node(NODE_VALUE_V, compiler.stack_assign(out)); - compiler.add_node(NODE_VALUE_V, in->value()); + compiler.add_node(NODE_VALUE_V, value_color); } } } void ConvertNode::compile(OSLCompiler& compiler) { - /* constant folding should eliminate proxy nodes */ - assert(from != to); + /* proxy nodes should have been removed at this point */ + assert(special_type != SHADER_SPECIAL_TYPE_PROXY); if(from == SocketType::FLOAT) compiler.add(this, "node_convert_from_float"); @@ -1731,23 +1777,10 @@ void ConvertNode::compile(OSLCompiler& compiler) /* BSDF Closure */ -BsdfNode::BsdfNode(bool scattering_) -: ShaderNode("bsdf"), scattering(scattering_) +BsdfNode::BsdfNode(const NodeType *node_type) +: ShaderNode(node_type) { special_type = SHADER_SPECIAL_TYPE_CLOSURE; - - add_input("Color", SocketType::COLOR, make_float3(0.8f, 0.8f, 0.8f)); - add_input("Normal", SocketType::NORMAL, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL); - add_input("SurfaceMixWeight", SocketType::FLOAT, 0.0f, SocketType::SVM_INTERNAL); - - if(scattering) { - closure = CLOSURE_BSSRDF_CUBIC_ID; - add_output("BSSRDF", SocketType::CLOSURE); - } - else { - closure = CLOSURE_BSDF_DIFFUSE_ID; - add_output("BSDF", SocketType::CLOSURE); - } } void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3, ShaderInput *param4) @@ -1759,9 +1792,9 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput * if(color_in->link) compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in)); else - compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value()); + compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color); - int normal_offset = compiler.stack_assign_if_linked(normal_in); + int normal_offset = (normal_in) ? compiler.stack_assign_if_linked(normal_in) : SVM_STACK_INVALID; int tangent_offset = (tangent_in) ? compiler.stack_assign_if_linked(tangent_in) : SVM_STACK_INVALID; int param3_offset = (param3) ? compiler.stack_assign(param3) : SVM_STACK_INVALID; int param4_offset = (param4) ? compiler.stack_assign(param4) : SVM_STACK_INVALID; @@ -1771,8 +1804,8 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput * (param1)? compiler.stack_assign(param1): SVM_STACK_INVALID, (param2)? compiler.stack_assign(param2): SVM_STACK_INVALID, compiler.closure_mix_weight_offset()), - __float_as_int((param1)? param1->value_float(): 0.0f), - __float_as_int((param2)? param2->value_float(): 0.0f)); + __float_as_int((param1)? get_float(param1->socket_type): 0.0f), + __float_as_int((param2)? get_float(param2->socket_type): 0.0f)); compiler.add_node(normal_offset, tangent_offset, param3_offset, param4_offset); } @@ -1789,29 +1822,35 @@ void BsdfNode::compile(OSLCompiler& /*compiler*/) /* Anisotropic BSDF Closure */ -static NodeEnum aniso_distribution_init() +NODE_DEFINE(AnisotropicBsdfNode) { - NodeEnum enm; + NodeType* type = NodeType::add("anisotropic_bsdf", create, NodeType::SHADER); - enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID); - enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID); - enm.insert("Ashikhmin-Shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID); + SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f)); + SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL); + SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL); - return enm; -} + static NodeEnum distribution_enum; + distribution_enum.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID); + distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID); + distribution_enum.insert("Ashikhmin-Shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID); + SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID); + + SOCKET_IN_VECTOR(tangent, "Tangent", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TANGENT); + + SOCKET_IN_FLOAT(roughness, "Roughness", 0.2f); + SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.5f); + SOCKET_IN_FLOAT(rotation, "Rotation", 0.0f); + + SOCKET_OUT_CLOSURE(BSDF, "BSDF"); -NodeEnum AnisotropicBsdfNode::distribution_enum = aniso_distribution_init(); + return type; +} AnisotropicBsdfNode::AnisotropicBsdfNode() +: BsdfNode(node_type) { closure = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID; - distribution = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID; - - add_input("Tangent", SocketType::VECTOR, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TANGENT); - - add_input("Roughness", SocketType::FLOAT, 0.2f); - add_input("Anisotropy", SocketType::FLOAT, 0.5f); - add_input("Rotation", SocketType::FLOAT, 0.0f); } void AnisotropicBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes) @@ -1835,33 +1874,38 @@ void AnisotropicBsdfNode::compile(SVMCompiler& compiler) void AnisotropicBsdfNode::compile(OSLCompiler& compiler) { - compiler.parameter("distribution", distribution_enum[distribution]); + compiler.parameter(this, "distribution"); compiler.add(this, "node_anisotropic_bsdf"); } /* Glossy BSDF Closure */ -static NodeEnum glossy_distribution_init() +NODE_DEFINE(GlossyBsdfNode) { - NodeEnum enm; + NodeType* type = NodeType::add("glossy_bsdf", create, NodeType::SHADER); - enm.insert("Sharp", CLOSURE_BSDF_REFLECTION_ID); - enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ID); - enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ID); - enm.insert("Ashikhmin-Shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID); + SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f)); + SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL); + SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL); - return enm; -} + static NodeEnum distribution_enum; + distribution_enum.insert("Sharp", CLOSURE_BSDF_REFLECTION_ID); + distribution_enum.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ID); + distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ID); + distribution_enum.insert("Ashikhmin-Shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID); + SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_ID); + SOCKET_IN_FLOAT(roughness, "Roughness", 0.2f); -NodeEnum GlossyBsdfNode::distribution_enum = glossy_distribution_init(); + SOCKET_OUT_CLOSURE(BSDF, "BSDF"); + + return type; +} GlossyBsdfNode::GlossyBsdfNode() +: BsdfNode(node_type) { closure = CLOSURE_BSDF_MICROFACET_GGX_ID; - distribution = CLOSURE_BSDF_MICROFACET_GGX_ID; distribution_orig = NBUILTIN_CLOSURES; - - add_input("Roughness", SocketType::FLOAT, 0.2f); } void GlossyBsdfNode::simplify_settings(Scene *scene) @@ -1875,7 +1919,7 @@ void GlossyBsdfNode::simplify_settings(Scene *scene) * Note: Keep the epsilon in sync with kernel! */ ShaderInput *roughness_input = input("Roughness"); - if(!roughness_input->link && roughness_input->value_float() <= 1e-4f) { + if(!roughness_input->link && roughness <= 1e-4f) { distribution = CLOSURE_BSDF_REFLECTION_ID; } } @@ -1889,7 +1933,7 @@ void GlossyBsdfNode::simplify_settings(Scene *scene) bool GlossyBsdfNode::has_integrator_dependency() { ShaderInput *roughness_input = input("Roughness"); - return !roughness_input->link && roughness_input->value_float() <= 1e-4f; + return !roughness_input->link && roughness <= 1e-4f; } void GlossyBsdfNode::compile(SVMCompiler& compiler) @@ -1904,33 +1948,38 @@ void GlossyBsdfNode::compile(SVMCompiler& compiler) void GlossyBsdfNode::compile(OSLCompiler& compiler) { - compiler.parameter("distribution", distribution_enum[distribution]); + compiler.parameter(this, "distribution"); compiler.add(this, "node_glossy_bsdf"); } /* Glass BSDF Closure */ -static NodeEnum glass_distribution_init() +NODE_DEFINE(GlassBsdfNode) { - NodeEnum enm; + NodeType* type = NodeType::add("glass_bsdf", create, NodeType::SHADER); - enm.insert("Sharp", CLOSURE_BSDF_SHARP_GLASS_ID); - enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID); - enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID); + SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f)); + SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL); + SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL); - return enm; -} + static NodeEnum distribution_enum; + distribution_enum.insert("Sharp", CLOSURE_BSDF_SHARP_GLASS_ID); + distribution_enum.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID); + distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID); + SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID); + SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f); + SOCKET_IN_FLOAT(IOR, "IOR", 0.3f); -NodeEnum GlassBsdfNode::distribution_enum = glass_distribution_init(); + SOCKET_OUT_CLOSURE(BSDF, "BSDF"); + + return type; +} GlassBsdfNode::GlassBsdfNode() +: BsdfNode(node_type) { closure = CLOSURE_BSDF_SHARP_GLASS_ID; - distribution = CLOSURE_BSDF_SHARP_GLASS_ID; distribution_orig = NBUILTIN_CLOSURES; - - add_input("Roughness", SocketType::FLOAT, 0.0f); - add_input("IOR", SocketType::FLOAT, 0.3f); } void GlassBsdfNode::simplify_settings(Scene *scene) @@ -1944,7 +1993,7 @@ void GlassBsdfNode::simplify_settings(Scene *scene) * Note: Keep the epsilon in sync with kernel! */ ShaderInput *roughness_input = input("Roughness"); - if(!roughness_input->link && roughness_input->value_float() <= 1e-4f) { + if(!roughness_input->link && roughness <= 1e-4f) { distribution = CLOSURE_BSDF_SHARP_GLASS_ID; } } @@ -1958,7 +2007,7 @@ void GlassBsdfNode::simplify_settings(Scene *scene) bool GlassBsdfNode::has_integrator_dependency() { ShaderInput *roughness_input = input("Roughness"); - return !roughness_input->link && roughness_input->value_float() <= 1e-4f; + return !roughness_input->link && roughness <= 1e-4f; } void GlassBsdfNode::compile(SVMCompiler& compiler) @@ -1973,33 +2022,39 @@ void GlassBsdfNode::compile(SVMCompiler& compiler) void GlassBsdfNode::compile(OSLCompiler& compiler) { - compiler.parameter("distribution", distribution_enum[distribution]); + compiler.parameter(this, "distribution"); compiler.add(this, "node_glass_bsdf"); } /* Refraction BSDF Closure */ -static NodeEnum refraction_distribution_init() +NODE_DEFINE(RefractionBsdfNode) { - NodeEnum enm; + NodeType* type = NodeType::add("refraction_bsdf", create, NodeType::SHADER); - enm.insert("Sharp", CLOSURE_BSDF_REFRACTION_ID); - enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID); - enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID); + SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f)); + SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL); + SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL); - return enm; -} + static NodeEnum distribution_enum; + distribution_enum.insert("Sharp", CLOSURE_BSDF_REFRACTION_ID); + distribution_enum.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID); + distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID); + SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID); -NodeEnum RefractionBsdfNode::distribution_enum = refraction_distribution_init(); + SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f); + SOCKET_IN_FLOAT(IOR, "IOR", 0.3f); + + SOCKET_OUT_CLOSURE(BSDF, "BSDF"); + + return type; +} RefractionBsdfNode::RefractionBsdfNode() +: BsdfNode(node_type) { closure = CLOSURE_BSDF_REFRACTION_ID; - distribution = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; distribution_orig = NBUILTIN_CLOSURES; - - add_input("Roughness", SocketType::FLOAT, 0.0f); - add_input("IOR", SocketType::FLOAT, 0.3f); } void RefractionBsdfNode::simplify_settings(Scene *scene) @@ -2013,7 +2068,7 @@ void RefractionBsdfNode::simplify_settings(Scene *scene) * Note: Keep the epsilon in sync with kernel! */ ShaderInput *roughness_input = input("Roughness"); - if(!roughness_input->link && roughness_input->value_float() <= 1e-4f) { + if(!roughness_input->link && roughness <= 1e-4f) { distribution = CLOSURE_BSDF_REFRACTION_ID; } } @@ -2027,7 +2082,7 @@ void RefractionBsdfNode::simplify_settings(Scene *scene) bool RefractionBsdfNode::has_integrator_dependency() { ShaderInput *roughness_input = input("Roughness"); - return !roughness_input->link && roughness_input->value_float() <= 1e-4f; + return !roughness_input->link && roughness <= 1e-4f; } void RefractionBsdfNode::compile(SVMCompiler& compiler) @@ -2042,31 +2097,36 @@ void RefractionBsdfNode::compile(SVMCompiler& compiler) void RefractionBsdfNode::compile(OSLCompiler& compiler) { - compiler.parameter("distribution", distribution_enum[distribution]); + compiler.parameter(this, "distribution"); compiler.add(this, "node_refraction_bsdf"); } /* Toon BSDF Closure */ -static NodeEnum toon_component_init() +NODE_DEFINE(ToonBsdfNode) { - NodeEnum enm; + NodeType* type = NodeType::add("toon_bsdf", create, NodeType::SHADER); - enm.insert("Diffuse", CLOSURE_BSDF_DIFFUSE_TOON_ID); - enm.insert("Glossy", CLOSURE_BSDF_GLOSSY_TOON_ID); + SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f)); + SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL); + SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL); - return enm; -} + static NodeEnum component_enum; + component_enum.insert("Diffuse", CLOSURE_BSDF_DIFFUSE_TOON_ID); + component_enum.insert("Glossy", CLOSURE_BSDF_GLOSSY_TOON_ID); + SOCKET_ENUM(component, "Component", component_enum, CLOSURE_BSDF_DIFFUSE_TOON_ID); + SOCKET_IN_FLOAT(size, "Size", 0.5f); + SOCKET_IN_FLOAT(smooth, "Smooth", 0.0f); + + SOCKET_OUT_CLOSURE(BSDF, "BSDF"); -NodeEnum ToonBsdfNode::component_enum = toon_component_init(); + return type; +} ToonBsdfNode::ToonBsdfNode() +: BsdfNode(node_type) { closure = CLOSURE_BSDF_DIFFUSE_TOON_ID; - component = CLOSURE_BSDF_DIFFUSE_TOON_ID; - - add_input("Size", SocketType::FLOAT, 0.5f); - add_input("Smooth", SocketType::FLOAT, 0.0f); } void ToonBsdfNode::compile(SVMCompiler& compiler) @@ -2078,17 +2138,30 @@ void ToonBsdfNode::compile(SVMCompiler& compiler) void ToonBsdfNode::compile(OSLCompiler& compiler) { - compiler.parameter("component", component_enum[component]); + compiler.parameter(this, "component"); compiler.add(this, "node_toon_bsdf"); } /* Velvet BSDF Closure */ +NODE_DEFINE(VelvetBsdfNode) +{ + NodeType* type = NodeType::add("velvet_bsdf", create, NodeType::SHADER); + + SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f)); + SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL); + SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL); + SOCKET_IN_FLOAT(sigma, "Sigma", 1.0f); + + SOCKET_OUT_CLOSURE(BSDF, "BSDF"); + + return type; +} + VelvetBsdfNode::VelvetBsdfNode() +: BsdfNode(node_type) { closure = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID; - - add_input("Sigma", SocketType::FLOAT, 1.0f); } void VelvetBsdfNode::compile(SVMCompiler& compiler) @@ -2103,10 +2176,24 @@ void VelvetBsdfNode::compile(OSLCompiler& compiler) /* Diffuse BSDF Closure */ +NODE_DEFINE(DiffuseBsdfNode) +{ + NodeType* type = NodeType::add("diffuse_bsdf", create, NodeType::SHADER); + + SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f)); + SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL); + SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL); + SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f); + + SOCKET_OUT_CLOSURE(BSDF, "BSDF"); + + return type; +} + DiffuseBsdfNode::DiffuseBsdfNode() +: BsdfNode(node_type) { closure = CLOSURE_BSDF_DIFFUSE_ID; - add_input("Roughness", SocketType::FLOAT, 0.0f); } void DiffuseBsdfNode::compile(SVMCompiler& compiler) @@ -2121,7 +2208,21 @@ void DiffuseBsdfNode::compile(OSLCompiler& compiler) /* Translucent BSDF Closure */ +NODE_DEFINE(TranslucentBsdfNode) +{ + NodeType* type = NodeType::add("translucent_bsdf", create, NodeType::SHADER); + + SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f)); + SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL); + SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL); + + SOCKET_OUT_CLOSURE(BSDF, "BSDF"); + + return type; +} + TranslucentBsdfNode::TranslucentBsdfNode() +: BsdfNode(node_type) { closure = CLOSURE_BSDF_TRANSLUCENT_ID; } @@ -2138,9 +2239,21 @@ void TranslucentBsdfNode::compile(OSLCompiler& compiler) /* Transparent BSDF Closure */ +NODE_DEFINE(TransparentBsdfNode) +{ + NodeType* type = NodeType::add("transparent_bsdf", create, NodeType::SHADER); + + SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f)); + SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL); + + SOCKET_OUT_CLOSURE(BSDF, "BSDF"); + + return type; +} + TransparentBsdfNode::TransparentBsdfNode() +: BsdfNode(node_type) { - name = "transparent"; closure = CLOSURE_BSDF_TRANSPARENT_ID; } @@ -2156,29 +2269,32 @@ void TransparentBsdfNode::compile(OSLCompiler& compiler) /* Subsurface Scattering Closure */ -static NodeEnum subsurface_falloff_init() +NODE_DEFINE(SubsurfaceScatteringNode) { - NodeEnum enm; + NodeType* type = NodeType::add("subsurface_scattering", create, NodeType::SHADER); - enm.insert("Cubic", CLOSURE_BSSRDF_CUBIC_ID); - enm.insert("Gaussian", CLOSURE_BSSRDF_GAUSSIAN_ID); - enm.insert("Burley", CLOSURE_BSSRDF_BURLEY_ID); + SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f)); + SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL); + SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL); - return enm; -} + static NodeEnum falloff_enum; + falloff_enum.insert("Cubic", CLOSURE_BSSRDF_CUBIC_ID); + falloff_enum.insert("Gaussian", CLOSURE_BSSRDF_GAUSSIAN_ID); + falloff_enum.insert("Burley", CLOSURE_BSSRDF_BURLEY_ID); + SOCKET_ENUM(falloff, "Falloff", falloff_enum, CLOSURE_BSSRDF_BURLEY_ID); + SOCKET_IN_FLOAT(scale, "Scale", 0.01f); + SOCKET_IN_VECTOR(radius, "Radius", make_float3(0.1f, 0.1f, 0.1f)); + SOCKET_IN_FLOAT(sharpness, "Sharpness", 0.0f); + SOCKET_IN_FLOAT(texture_blur, "Texture Blur", 1.0f); -NodeEnum SubsurfaceScatteringNode::falloff_enum = subsurface_falloff_init(); + SOCKET_OUT_CLOSURE(BSSRDF, "BSSRDF"); + + return type; +} SubsurfaceScatteringNode::SubsurfaceScatteringNode() -: BsdfNode(true) +: BsdfNode(node_type) { - name = "subsurface_scattering"; - falloff = CLOSURE_BSSRDF_CUBIC_ID; - - add_input("Scale", SocketType::FLOAT, 0.01f); - add_input("Radius", SocketType::VECTOR, make_float3(0.1f, 0.1f, 0.1f)); - add_input("Sharpness", SocketType::FLOAT, 0.0f); - add_input("Texture Blur", SocketType::FLOAT, 1.0f); } void SubsurfaceScatteringNode::compile(SVMCompiler& compiler) @@ -2189,7 +2305,7 @@ void SubsurfaceScatteringNode::compile(SVMCompiler& compiler) void SubsurfaceScatteringNode::compile(OSLCompiler& compiler) { - compiler.parameter("falloff", falloff_enum[closure]); + compiler.parameter(this, "falloff"); compiler.add(this, "node_subsurface_scattering"); } @@ -2202,14 +2318,22 @@ bool SubsurfaceScatteringNode::has_bssrdf_bump() /* Emissive Closure */ -EmissionNode::EmissionNode() -: ShaderNode("emission") +NODE_DEFINE(EmissionNode) { - add_input("Color", SocketType::COLOR, make_float3(0.8f, 0.8f, 0.8f)); - add_input("Strength", SocketType::FLOAT, 10.0f); - add_input("SurfaceMixWeight", SocketType::FLOAT, 0.0f, SocketType::SVM_INTERNAL); + NodeType* type = NodeType::add("emission", create, NodeType::SHADER); + + SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f)); + SOCKET_IN_FLOAT(strength, "Strength", 1.0f); + SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL); + + SOCKET_OUT_CLOSURE(emission, "Emission"); - add_output("Emission", SocketType::CLOSURE); + return type; +} + +EmissionNode::EmissionNode() +: ShaderNode(node_type) +{ } void EmissionNode::compile(SVMCompiler& compiler) @@ -2223,7 +2347,7 @@ void EmissionNode::compile(SVMCompiler& compiler) compiler.stack_assign(strength_in)); } else - compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value() * strength_in->value_float()); + compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color * strength); compiler.add_node(NODE_CLOSURE_EMISSION, compiler.closure_mix_weight_offset()); } @@ -2238,20 +2362,28 @@ bool EmissionNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *) ShaderInput *color_in = input("Color"); ShaderInput *strength_in = input("Strength"); - return ((!color_in->link && color_in->value() == make_float3(0.0f, 0.0f, 0.0f)) || - (!strength_in->link && strength_in->value_float() == 0.0f)); + return ((!color_in->link && color == make_float3(0.0f, 0.0f, 0.0f)) || + (!strength_in->link && strength == 0.0f)); } /* Background Closure */ -BackgroundNode::BackgroundNode() -: ShaderNode("background") +NODE_DEFINE(BackgroundNode) { - add_input("Color", SocketType::COLOR, make_float3(0.8f, 0.8f, 0.8f)); - add_input("Strength", SocketType::FLOAT, 1.0f); - add_input("SurfaceMixWeight", SocketType::FLOAT, 0.0f, SocketType::SVM_INTERNAL); + NodeType* type = NodeType::add("background_shader", create, NodeType::SHADER); + + SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f)); + SOCKET_IN_FLOAT(strength, "Strength", 1.0f); + SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL); + + SOCKET_OUT_CLOSURE(background, "Background"); + + return type; +} - add_output("Background", SocketType::CLOSURE); +BackgroundNode::BackgroundNode() +: ShaderNode(node_type) +{ } void BackgroundNode::compile(SVMCompiler& compiler) @@ -2265,7 +2397,7 @@ void BackgroundNode::compile(SVMCompiler& compiler) compiler.stack_assign(strength_in)); } else - compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value()*strength_in->value_float()); + compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color*strength); compiler.add_node(NODE_CLOSURE_BACKGROUND, compiler.closure_mix_weight_offset()); } @@ -2280,19 +2412,27 @@ bool BackgroundNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *) ShaderInput *color_in = input("Color"); ShaderInput *strength_in = input("Strength"); - return ((!color_in->link && color_in->value() == make_float3(0.0f, 0.0f, 0.0f)) || - (!strength_in->link && strength_in->value_float() == 0.0f)); + return ((!color_in->link && color == make_float3(0.0f, 0.0f, 0.0f)) || + (!strength_in->link && strength == 0.0f)); } /* Holdout Closure */ -HoldoutNode::HoldoutNode() -: ShaderNode("holdout") +NODE_DEFINE(HoldoutNode) { - add_input("SurfaceMixWeight", SocketType::FLOAT, 0.0f, SocketType::SVM_INTERNAL); - add_input("VolumeMixWeight", SocketType::FLOAT, 0.0f, SocketType::SVM_INTERNAL); + NodeType* type = NodeType::add("holdout", create, NodeType::SHADER); - add_output("Holdout", SocketType::CLOSURE); + SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL); + SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL); + + SOCKET_OUT_CLOSURE(holdout, "Holdout"); + + return type; +} + +HoldoutNode::HoldoutNode() +: ShaderNode(node_type) +{ } void HoldoutNode::compile(SVMCompiler& compiler) @@ -2310,15 +2450,23 @@ void HoldoutNode::compile(OSLCompiler& compiler) /* Ambient Occlusion */ -AmbientOcclusionNode::AmbientOcclusionNode() -: ShaderNode("ambient_occlusion") +NODE_DEFINE(AmbientOcclusionNode) { - add_input("NormalIn", SocketType::NORMAL, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL); - add_input("Color", SocketType::COLOR, make_float3(0.8f, 0.8f, 0.8f)); - add_input("SurfaceMixWeight", SocketType::FLOAT, 0.0f, SocketType::SVM_INTERNAL); + NodeType* type = NodeType::add("ambient_occlusion", create, NodeType::SHADER); - add_output("AO", SocketType::CLOSURE); -} + SOCKET_IN_NORMAL(normal_osl, "NormalIn", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL); + SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f)); + SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL); + + SOCKET_OUT_CLOSURE(AO, "AO"); + + return type; +} + +AmbientOcclusionNode::AmbientOcclusionNode() +: ShaderNode(node_type) +{ +} void AmbientOcclusionNode::compile(SVMCompiler& compiler) { @@ -2327,7 +2475,7 @@ void AmbientOcclusionNode::compile(SVMCompiler& compiler) if(color_in->link) compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in)); else - compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value()); + compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color); compiler.add_node(NODE_CLOSURE_AMBIENT_OCCLUSION, compiler.closure_mix_weight_offset()); } @@ -2339,16 +2487,10 @@ void AmbientOcclusionNode::compile(OSLCompiler& compiler) /* Volume Closure */ -VolumeNode::VolumeNode() -: ShaderNode("volume") +VolumeNode::VolumeNode(const NodeType *node_type) +: ShaderNode(node_type) { closure = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID; - - add_input("Color", SocketType::COLOR, make_float3(0.8f, 0.8f, 0.8f)); - add_input("Density", SocketType::FLOAT, 1.0f); - add_input("VolumeMixWeight", SocketType::FLOAT, 0.0f, SocketType::SVM_INTERNAL); - - add_output("Volume", SocketType::CLOSURE); } void VolumeNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2) @@ -2358,15 +2500,15 @@ void VolumeNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput if(color_in->link) compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in)); else - compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value()); + compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color); compiler.add_node(NODE_CLOSURE_VOLUME, compiler.encode_uchar4(closure, (param1)? compiler.stack_assign(param1): SVM_STACK_INVALID, (param2)? compiler.stack_assign(param2): SVM_STACK_INVALID, compiler.closure_mix_weight_offset()), - __float_as_int((param1)? param1->value_float(): 0.0f), - __float_as_int((param2)? param2->value_float(): 0.0f)); + __float_as_int((param1)? get_float(param1->socket_type): 0.0f), + __float_as_int((param2)? get_float(param2->socket_type): 0.0f)); } void VolumeNode::compile(SVMCompiler& compiler) @@ -2381,7 +2523,21 @@ void VolumeNode::compile(OSLCompiler& /*compiler*/) /* Absorption Volume Closure */ +NODE_DEFINE(AbsorptionVolumeNode) +{ + NodeType* type = NodeType::add("absorption_volume", create, NodeType::SHADER); + + SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f)); + SOCKET_IN_FLOAT(density, "Density", 1.0f); + SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL); + + SOCKET_OUT_CLOSURE(volume, "Volume"); + + return type; +} + AbsorptionVolumeNode::AbsorptionVolumeNode() +: VolumeNode(node_type) { closure = CLOSURE_VOLUME_ABSORPTION_ID; } @@ -2398,11 +2554,24 @@ void AbsorptionVolumeNode::compile(OSLCompiler& compiler) /* Scatter Volume Closure */ +NODE_DEFINE(ScatterVolumeNode) +{ + NodeType* type = NodeType::add("scatter_volume", create, NodeType::SHADER); + + SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f)); + SOCKET_IN_FLOAT(density, "Density", 1.0f); + SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.0f); + SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL); + + SOCKET_OUT_CLOSURE(volume, "Volume"); + + return type; +} + ScatterVolumeNode::ScatterVolumeNode() +: VolumeNode(node_type) { closure = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID; - - add_input("Anisotropy", SocketType::FLOAT, 0.0f); } void ScatterVolumeNode::compile(SVMCompiler& compiler) @@ -2417,27 +2586,32 @@ void ScatterVolumeNode::compile(OSLCompiler& compiler) /* Hair BSDF Closure */ -static NodeEnum hair_component_init() +NODE_DEFINE(HairBsdfNode) { - NodeEnum enm; + NodeType* type = NodeType::add("hair_bsdf", create, NodeType::SHADER); - enm.insert("Reflection", CLOSURE_BSDF_HAIR_REFLECTION_ID); - enm.insert("Transmission", CLOSURE_BSDF_HAIR_TRANSMISSION_ID); + SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f)); + SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL); + SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL); - return enm; -} + static NodeEnum component_enum; + component_enum.insert("Reflection", CLOSURE_BSDF_HAIR_REFLECTION_ID); + component_enum.insert("Transmission", CLOSURE_BSDF_HAIR_TRANSMISSION_ID); + SOCKET_ENUM(component, "Component", component_enum, CLOSURE_BSDF_HAIR_REFLECTION_ID); + SOCKET_IN_FLOAT(offset, "Offset", 0.0f); + SOCKET_IN_FLOAT(roughness_u, "RoughnessU", 0.2f); + SOCKET_IN_FLOAT(roughness_v, "RoughnessV", 0.2f); + SOCKET_IN_VECTOR(tangent, "Tangent", make_float3(0.0f, 0.0f, 0.0f)); -NodeEnum HairBsdfNode::component_enum = hair_component_init(); + SOCKET_OUT_CLOSURE(BSDF, "BSDF"); + + return type; +} HairBsdfNode::HairBsdfNode() +: BsdfNode(node_type) { closure = CLOSURE_BSDF_HAIR_REFLECTION_ID; - component = CLOSURE_BSDF_HAIR_REFLECTION_ID; - - add_input("Offset", SocketType::FLOAT); - add_input("RoughnessU", SocketType::FLOAT); - add_input("RoughnessV", SocketType::FLOAT); - add_input("Tangent", SocketType::VECTOR); } void HairBsdfNode::compile(SVMCompiler& compiler) @@ -2449,27 +2623,34 @@ void HairBsdfNode::compile(SVMCompiler& compiler) void HairBsdfNode::compile(OSLCompiler& compiler) { - compiler.parameter("component", component_enum[component]); - + compiler.parameter(this, "component"); compiler.add(this, "node_hair_bsdf"); } /* Geometry */ +NODE_DEFINE(GeometryNode) +{ + NodeType* type = NodeType::add("geometry", create, NodeType::SHADER); + + SOCKET_IN_NORMAL(normal_osl, "NormalIn", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL); + + SOCKET_OUT_POINT(position, "Position"); + SOCKET_OUT_NORMAL(normal, "Normal"); + SOCKET_OUT_NORMAL(tangent, "Tangent"); + SOCKET_OUT_NORMAL(true_normal, "True Normal"); + SOCKET_OUT_VECTOR(incoming, "Incoming"); + SOCKET_OUT_POINT(parametric, "Parametric"); + SOCKET_OUT_FLOAT(backfacing, "Backfacing"); + SOCKET_OUT_FLOAT(pointiness, "Pointiness"); + + return type; +} + GeometryNode::GeometryNode() -: ShaderNode("geometry") +: ShaderNode(node_type) { special_type = SHADER_SPECIAL_TYPE_GEOMETRY; - - add_input("NormalIn", SocketType::NORMAL, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL); - add_output("Position", SocketType::POINT); - add_output("Normal", SocketType::NORMAL); - add_output("Tangent", SocketType::NORMAL); - add_output("True Normal", SocketType::NORMAL); - add_output("Incoming", SocketType::VECTOR); - add_output("Parametric", SocketType::POINT); - add_output("Backfacing", SocketType::FLOAT); - add_output("Pointiness", SocketType::FLOAT); } void GeometryNode::attributes(Shader *shader, AttributeRequestSet *attributes) @@ -2564,21 +2745,30 @@ void GeometryNode::compile(OSLCompiler& compiler) /* TextureCoordinate */ -TextureCoordinateNode::TextureCoordinateNode() -: ShaderNode("texture_coordinate") +NODE_DEFINE(TextureCoordinateNode) { - add_input("NormalIn", SocketType::NORMAL, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL); - add_output("Generated", SocketType::POINT); - add_output("Normal", SocketType::NORMAL); - add_output("UV", SocketType::POINT); - add_output("Object", SocketType::POINT); - add_output("Camera", SocketType::POINT); - add_output("Window", SocketType::POINT); - add_output("Reflection", SocketType::NORMAL); + NodeType* type = NodeType::add("texture_coordinate", create, NodeType::SHADER); + + SOCKET_BOOLEAN(from_dupli, "From Dupli", false); + SOCKET_BOOLEAN(use_transform, "Use Transform", false); + SOCKET_TRANSFORM(ob_tfm, "Object Transform", transform_identity()); - from_dupli = false; - use_transform = false; - ob_tfm = transform_identity(); + SOCKET_IN_NORMAL(normal_osl, "NormalIn", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL); + + SOCKET_OUT_POINT(generated, "Generated"); + SOCKET_OUT_NORMAL(normal, "Normal"); + SOCKET_OUT_POINT(UV, "UV"); + SOCKET_OUT_POINT(object, "Object"); + SOCKET_OUT_POINT(camera, "Camera"); + SOCKET_OUT_POINT(window, "Window"); + SOCKET_OUT_NORMAL(reflection, "Reflection"); + + return type; +} + +TextureCoordinateNode::TextureCoordinateNode() +: ShaderNode(node_type) +{ } void TextureCoordinateNode::attributes(Shader *shader, AttributeRequestSet *attributes) @@ -2702,22 +2892,32 @@ void TextureCoordinateNode::compile(OSLCompiler& compiler) compiler.parameter("is_background", true); if(compiler.output_type() == SHADER_TYPE_VOLUME) compiler.parameter("is_volume", true); - compiler.parameter("use_transform", use_transform); + compiler.parameter(this, "use_transform"); Transform ob_itfm = transform_transpose(transform_inverse(ob_tfm)); compiler.parameter("object_itfm", ob_itfm); - compiler.parameter("from_dupli", from_dupli); + compiler.parameter(this, "from_dupli"); compiler.add(this, "node_texture_coordinate"); } -UVMapNode::UVMapNode() -: ShaderNode("uvmap") +/* UV Map */ + +NODE_DEFINE(UVMapNode) { - attribute = ""; - from_dupli = false; + NodeType* type = NodeType::add("uvmap", create, NodeType::SHADER); + + SOCKET_IN_STRING(attribute, "attribute", ustring("")); + SOCKET_IN_BOOLEAN(from_dupli, "from dupli", false); + + SOCKET_OUT_POINT(UV, "UV"); - add_output("UV", SocketType::POINT); + return type; +} + +UVMapNode::UVMapNode() +: ShaderNode(node_type) +{ } void UVMapNode::attributes(Shader *shader, AttributeRequestSet *attributes) @@ -2776,28 +2976,36 @@ void UVMapNode::compile(OSLCompiler& compiler) else compiler.parameter("bump_offset", "center"); - compiler.parameter("from_dupli", from_dupli); + compiler.parameter(this, "from_dupli"); compiler.parameter("name", attribute.c_str()); compiler.add(this, "node_uv_map"); } /* Light Path */ +NODE_DEFINE(LightPathNode) +{ + NodeType* type = NodeType::add("light_path", create, NodeType::SHADER); + + SOCKET_OUT_FLOAT(is_camera_ray, "Is Camera Ray"); + SOCKET_OUT_FLOAT(is_shadow_ray, "Is Shadow Ray"); + SOCKET_OUT_FLOAT(is_diffus_ray, "Is Diffus Ray"); + SOCKET_OUT_FLOAT(is_glossy_ray, "Is Glossy Ray"); + SOCKET_OUT_FLOAT(is_singular_ray, "Is Singular Ray"); + SOCKET_OUT_FLOAT(is_reflection_ray, "Is Reflection Ray"); + SOCKET_OUT_FLOAT(is_transmission_ray, "Is Transmission Ray"); + SOCKET_OUT_FLOAT(is_volume_scatter_ray, "Is Volume Scatter Ray"); + SOCKET_OUT_FLOAT(ray_length, "Ray Length"); + SOCKET_OUT_FLOAT(ray_depth, "Ray Depth"); + SOCKET_OUT_FLOAT(transparent_depth, "Transparent Depth"); + SOCKET_OUT_FLOAT(transmission_depth, "Transmission Depth"); + + return type; +} + LightPathNode::LightPathNode() -: ShaderNode("light_path") -{ - add_output("Is Camera Ray", SocketType::FLOAT); - add_output("Is Shadow Ray", SocketType::FLOAT); - add_output("Is Diffuse Ray", SocketType::FLOAT); - add_output("Is Glossy Ray", SocketType::FLOAT); - add_output("Is Singular Ray", SocketType::FLOAT); - add_output("Is Reflection Ray", SocketType::FLOAT); - add_output("Is Transmission Ray", SocketType::FLOAT); - add_output("Is Volume Scatter Ray", SocketType::FLOAT); - add_output("Ray Length", SocketType::FLOAT); - add_output("Ray Depth", SocketType::FLOAT); - add_output("Transparent Depth", SocketType::FLOAT); - add_output("Transmission Depth", SocketType::FLOAT); +: ShaderNode(node_type) +{ } void LightPathNode::compile(SVMCompiler& compiler) @@ -2873,14 +3081,23 @@ void LightPathNode::compile(OSLCompiler& compiler) /* Light Falloff */ +NODE_DEFINE(LightFalloffNode) +{ + NodeType* type = NodeType::add("light_fallof", create, NodeType::SHADER); + + SOCKET_IN_FLOAT(strength, "Strength", 100.0f); + SOCKET_IN_FLOAT(smooth, "Smooth", 0.0f); + + SOCKET_OUT_FLOAT(quadratic, "Quadratic"); + SOCKET_OUT_FLOAT(linear, "Linear"); + SOCKET_OUT_FLOAT(constant, "Constant"); + + return type; +} + LightFalloffNode::LightFalloffNode() -: ShaderNode("light_fallof") +: ShaderNode(node_type) { - add_input("Strength", SocketType::FLOAT, 100.0f); - add_input("Smooth", SocketType::FLOAT, 0.0f); - add_output("Quadratic", SocketType::FLOAT); - add_output("Linear", SocketType::FLOAT); - add_output("Constant", SocketType::FLOAT); } void LightFalloffNode::compile(SVMCompiler& compiler) @@ -2923,13 +3140,21 @@ void LightFalloffNode::compile(OSLCompiler& compiler) /* Object Info */ +NODE_DEFINE(ObjectInfoNode) +{ + NodeType* type = NodeType::add("object_info", create, NodeType::SHADER); + + SOCKET_OUT_VECTOR(location, "Location"); + SOCKET_OUT_FLOAT(object_index, "Object Index"); + SOCKET_OUT_FLOAT(material_index, "Material Index"); + SOCKET_OUT_FLOAT(random, "Random"); + + return type; +} + ObjectInfoNode::ObjectInfoNode() -: ShaderNode("object_info") +: ShaderNode(node_type) { - add_output("Location", SocketType::VECTOR); - add_output("Object Index", SocketType::FLOAT); - add_output("Material Index", SocketType::FLOAT); - add_output("Random", SocketType::FLOAT); } void ObjectInfoNode::compile(SVMCompiler& compiler) @@ -2962,19 +3187,27 @@ void ObjectInfoNode::compile(OSLCompiler& compiler) /* Particle Info */ -ParticleInfoNode::ParticleInfoNode() -: ShaderNode("particle_info") +NODE_DEFINE(ParticleInfoNode) { - add_output("Index", SocketType::FLOAT); - add_output("Age", SocketType::FLOAT); - add_output("Lifetime", SocketType::FLOAT); - add_output("Location", SocketType::POINT); + NodeType* type = NodeType::add("particle_info", create, NodeType::SHADER); + + SOCKET_OUT_FLOAT(index, "Index"); + SOCKET_OUT_FLOAT(age, "Age"); + SOCKET_OUT_FLOAT(lifetime, "Lifetime"); + SOCKET_OUT_POINT(location, "Location"); #if 0 /* not yet supported */ - add_output("Rotation", SHADER_SOCKET_QUATERNION); + SOCKET_OUT_QUATERNION(rotation, "Rotation"); #endif - add_output("Size", SocketType::FLOAT); - add_output("Velocity", SocketType::VECTOR); - add_output("Angular Velocity", SocketType::VECTOR); + SOCKET_OUT_FLOAT(size, "Size"); + SOCKET_OUT_VECTOR(velocity, "Velocity"); + SOCKET_OUT_VECTOR(angular_velocity, "Angular Velocity"); + + return type; +} + +ParticleInfoNode::ParticleInfoNode() +: ShaderNode(node_type) +{ } void ParticleInfoNode::attributes(Shader *shader, AttributeRequestSet *attributes) @@ -3056,15 +3289,24 @@ void ParticleInfoNode::compile(OSLCompiler& compiler) /* Hair Info */ +NODE_DEFINE(HairInfoNode) +{ + NodeType* type = NodeType::add("hair_info", create, NodeType::SHADER); + + SOCKET_OUT_FLOAT(is_strand, "Is Strand"); + SOCKET_OUT_FLOAT(intercept, "Intercept"); + SOCKET_OUT_FLOAT(thickness, "Thickness"); + SOCKET_OUT_NORMAL(tangent Normal, "Tangent Normal"); +#if 0 /*output for minimum hair width transparency - deactivated */ + SOCKET_OUT_FLOAT(fade, "Fade"); +#endif + + return type; +} + HairInfoNode::HairInfoNode() -: ShaderNode("hair_info") +: ShaderNode(node_type) { - add_output("Is Strand", SocketType::FLOAT); - add_output("Intercept", SocketType::FLOAT); - add_output("Thickness", SocketType::FLOAT); - add_output("Tangent Normal", SocketType::NORMAL); - /*output for minimum hair width transparency - deactivated*/ - /*add_output("Fade", SocketType::FLOAT);*/ } void HairInfoNode::attributes(Shader *shader, AttributeRequestSet *attributes) @@ -3118,12 +3360,19 @@ void HairInfoNode::compile(OSLCompiler& compiler) /* Value */ -ValueNode::ValueNode() -: ShaderNode("value") +NODE_DEFINE(ValueNode) { - value = 0.0f; + NodeType* type = NodeType::add("value", create, NodeType::SHADER); - add_output("Value", SocketType::FLOAT); + SOCKET_FLOAT(value, "Value", 0.0f); + SOCKET_OUT_FLOAT(value, "Value"); + + return type; +} + +ValueNode::ValueNode() +: ShaderNode(node_type) +{ } bool ValueNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) @@ -3147,12 +3396,19 @@ void ValueNode::compile(OSLCompiler& compiler) /* Color */ -ColorNode::ColorNode() -: ShaderNode("color") +NODE_DEFINE(ColorNode) { - value = make_float3(0.0f, 0.0f, 0.0f); + NodeType* type = NodeType::add("color", create, NodeType::SHADER); + + SOCKET_COLOR(value, "Value", make_float3(0.0f, 0.0f, 0.0f)); + SOCKET_OUT_COLOR(color, "Color"); - add_output("Color", SocketType::COLOR); + return type; +} + +ColorNode::ColorNode() +: ShaderNode(node_type) +{ } bool ColorNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) @@ -3180,14 +3436,21 @@ void ColorNode::compile(OSLCompiler& compiler) /* Add Closure */ +NODE_DEFINE(AddClosureNode) +{ + NodeType* type = NodeType::add("add_closure", create, NodeType::SHADER); + + SOCKET_IN_CLOSURE(closure1, "Closure1"); + SOCKET_IN_CLOSURE(closure2, "Closure2"); + SOCKET_OUT_CLOSURE(closure, "Closure"); + + return type; +} + AddClosureNode::AddClosureNode() -: ShaderNode("add_closure") +: ShaderNode(node_type) { special_type = SHADER_SPECIAL_TYPE_COMBINE_CLOSURE; - - add_input("Closure1", SocketType::CLOSURE); - add_input("Closure2", SocketType::CLOSURE); - add_output("Closure", SocketType::CLOSURE); } void AddClosureNode::compile(SVMCompiler& /*compiler*/) @@ -3202,15 +3465,23 @@ void AddClosureNode::compile(OSLCompiler& compiler) /* Mix Closure */ +NODE_DEFINE(MixClosureNode) +{ + NodeType* type = NodeType::add("mix_closure", create, NodeType::SHADER); + + SOCKET_IN_FLOAT(fac, "Fac", 0.5f); + SOCKET_IN_CLOSURE(closure1, "Closure1"); + SOCKET_IN_CLOSURE(closure2, "Closure2"); + + SOCKET_OUT_CLOSURE(closure, "Closure"); + + return type; +} + MixClosureNode::MixClosureNode() -: ShaderNode("mix_closure") +: ShaderNode(node_type) { special_type = SHADER_SPECIAL_TYPE_COMBINE_CLOSURE; - - add_input("Fac", SocketType::FLOAT, 0.5f); - add_input("Closure1", SocketType::CLOSURE); - add_input("Closure2", SocketType::CLOSURE); - add_output("Closure", SocketType::CLOSURE); } void MixClosureNode::compile(SVMCompiler& /*compiler*/) @@ -3240,12 +3511,12 @@ bool MixClosureNode::constant_fold(ShaderGraph *graph, ShaderOutput *, ShaderInp /* check for closure links and make sure factor link is disconnected */ if(closure1_in->link && closure2_in->link && !fac_in->link) { /* factor 0.0 */ - if(fac_in->value_float() == 0.0f) { + if(fac == 0.0f) { graph->relink(this, closure_out, closure1_in->link); return true; } /* factor 1.0 */ - else if(fac_in->value_float() == 1.0f) { + else if(fac == 1.0f) { graph->relink(this, closure_out, closure2_in->link); return true; } @@ -3256,13 +3527,22 @@ bool MixClosureNode::constant_fold(ShaderGraph *graph, ShaderOutput *, ShaderInp /* Mix Closure */ +NODE_DEFINE(MixClosureWeightNode) +{ + NodeType* type = NodeType::add("mix_closure_weight", create, NodeType::SHADER); + + SOCKET_IN_FLOAT(weight, "Weight", 1.0f); + SOCKET_IN_FLOAT(fac, "Fac", 1.0f); + + SOCKET_OUT_FLOAT(weight1, "Weight1"); + SOCKET_OUT_FLOAT(weight2, "Weight2"); + + return type; +} + MixClosureWeightNode::MixClosureWeightNode() -: ShaderNode("mix_closure_weight") +: ShaderNode(node_type) { - add_input("Weight", SocketType::FLOAT, 1.0f); - add_input("Fac", SocketType::FLOAT, 1.0f); - add_output("Weight1", SocketType::FLOAT); - add_output("Weight2", SocketType::FLOAT); } void MixClosureWeightNode::compile(SVMCompiler& compiler) @@ -3287,12 +3567,21 @@ void MixClosureWeightNode::compile(OSLCompiler& /*compiler*/) /* Invert */ +NODE_DEFINE(InvertNode) +{ + NodeType* type = NodeType::add("invert", create, NodeType::SHADER); + + SOCKET_IN_FLOAT(fac, "Fac", 1.0f); + SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f)); + + SOCKET_OUT_COLOR(color, "Color"); + + return type; +} + InvertNode::InvertNode() -: ShaderNode("invert") +: ShaderNode(node_type) { - add_input("Fac", SocketType::FLOAT, 1.0f); - add_input("Color", SocketType::COLOR); - add_output("Color", SocketType::COLOR); } void InvertNode::compile(SVMCompiler& compiler) @@ -3314,46 +3603,46 @@ void InvertNode::compile(OSLCompiler& compiler) /* Mix */ -MixNode::MixNode() -: ShaderNode("mix") +NODE_DEFINE(MixNode) { - type = NODE_MIX_BLEND; + NodeType* type = NodeType::add("mix", create, NodeType::SHADER); - use_clamp = false; + static NodeEnum type_enum; + type_enum.insert("Mix", NODE_MIX_BLEND); + type_enum.insert("Add", NODE_MIX_ADD); + type_enum.insert("Multiply", NODE_MIX_MUL); + type_enum.insert("Screen", NODE_MIX_SCREEN); + type_enum.insert("Overlay", NODE_MIX_OVERLAY); + type_enum.insert("Subtract", NODE_MIX_SUB); + type_enum.insert("Divide", NODE_MIX_DIV); + type_enum.insert("Difference", NODE_MIX_DIFF); + type_enum.insert("Darken", NODE_MIX_DARK); + type_enum.insert("Lighten", NODE_MIX_LIGHT); + type_enum.insert("Dodge", NODE_MIX_DODGE); + type_enum.insert("Burn", NODE_MIX_BURN); + type_enum.insert("Hue", NODE_MIX_HUE); + type_enum.insert("Saturation", NODE_MIX_SAT); + type_enum.insert("Value", NODE_MIX_VAL); + type_enum.insert("Color", NODE_MIX_COLOR); + type_enum.insert("Soft Light", NODE_MIX_SOFT); + type_enum.insert("Linear Light", NODE_MIX_LINEAR); + SOCKET_ENUM(type, "Type", type_enum, NODE_MIX_BLEND); - add_input("Fac", SocketType::FLOAT, 0.5f); - add_input("Color1", SocketType::COLOR); - add_input("Color2", SocketType::COLOR); - add_output("Color", SocketType::COLOR); -} + SOCKET_BOOLEAN(use_clamp, "Use Clamp", false); -static NodeEnum mix_type_init() -{ - NodeEnum enm; + SOCKET_IN_FLOAT(fac, "Fac", 0.5f); + SOCKET_IN_COLOR(color1, "Color1", make_float3(0.0f, 0.0f, 0.0f)); + SOCKET_IN_COLOR(color2, "Color2", make_float3(0.0f, 0.0f, 0.0f)); - enm.insert("Mix", NODE_MIX_BLEND); - enm.insert("Add", NODE_MIX_ADD); - enm.insert("Multiply", NODE_MIX_MUL); - enm.insert("Screen", NODE_MIX_SCREEN); - enm.insert("Overlay", NODE_MIX_OVERLAY); - enm.insert("Subtract", NODE_MIX_SUB); - enm.insert("Divide", NODE_MIX_DIV); - enm.insert("Difference", NODE_MIX_DIFF); - enm.insert("Darken", NODE_MIX_DARK); - enm.insert("Lighten", NODE_MIX_LIGHT); - enm.insert("Dodge", NODE_MIX_DODGE); - enm.insert("Burn", NODE_MIX_BURN); - enm.insert("Hue", NODE_MIX_HUE); - enm.insert("Saturation", NODE_MIX_SAT); - enm.insert("Value", NODE_MIX_VAL); - enm.insert("Color", NODE_MIX_COLOR); - enm.insert("Soft Light", NODE_MIX_SOFT); - enm.insert("Linear Light", NODE_MIX_LINEAR); + SOCKET_OUT_COLOR(color, "Color"); - return enm; + return type; } -NodeEnum MixNode::type_enum = mix_type_init(); +MixNode::MixNode() +: ShaderNode(node_type) +{ +} void MixNode::compile(SVMCompiler& compiler) { @@ -3376,8 +3665,8 @@ void MixNode::compile(SVMCompiler& compiler) void MixNode::compile(OSLCompiler& compiler) { - compiler.parameter("type", type_enum[type]); - compiler.parameter("use_clamp", use_clamp); + compiler.parameter(this, "type"); + compiler.parameter(this, "use_clamp"); compiler.add(this, "node_mix"); } @@ -3401,19 +3690,19 @@ bool MixNode::constant_fold(ShaderGraph *graph, ShaderOutput *, ShaderInput *opt /* remove unused mix color input when factor is 0.0 or 1.0 */ if(!fac_in->link) { /* factor 0.0 */ - if(fac_in->value_float() == 0.0f) { + if(fac == 0.0f) { if(color1_in->link) graph->relink(this, color_out, color1_in->link); else - optimized->set(color1_in->value()); + optimized->set(color1); return true; } /* factor 1.0 */ - else if(fac_in->value_float() == 1.0f) { + else if(fac == 1.0f) { if(color2_in->link) graph->relink(this, color_out, color2_in->link); else - optimized->set(color2_in->value()); + optimized->set(color2); return true; } } @@ -3422,13 +3711,23 @@ bool MixNode::constant_fold(ShaderGraph *graph, ShaderOutput *, ShaderInput *opt } /* Combine RGB */ + +NODE_DEFINE(CombineRGBNode) +{ + NodeType* type = NodeType::add("combine_rgb", create, NodeType::SHADER); + + SOCKET_IN_FLOAT(r, "R", 0.0f); + SOCKET_IN_FLOAT(g, "G", 0.0f); + SOCKET_IN_FLOAT(b, "B", 0.0f); + + SOCKET_OUT_COLOR(image, "Image"); + + return type; +} + CombineRGBNode::CombineRGBNode() -: ShaderNode("combine_rgb") +: ShaderNode(node_type) { - add_input("R", SocketType::FLOAT); - add_input("G", SocketType::FLOAT); - add_input("B", SocketType::FLOAT); - add_output("Image", SocketType::COLOR); } void CombineRGBNode::compile(SVMCompiler& compiler) @@ -3457,13 +3756,23 @@ void CombineRGBNode::compile(OSLCompiler& compiler) } /* Combine XYZ */ + +NODE_DEFINE(CombineXYZNode) +{ + NodeType* type = NodeType::add("combine_xyz", create, NodeType::SHADER); + + SOCKET_IN_FLOAT(x, "X", 0.0f); + SOCKET_IN_FLOAT(y, "Y", 0.0f); + SOCKET_IN_FLOAT(z, "Z", 0.0f); + + SOCKET_OUT_COLOR(color, "Image"); + + return type; +} + CombineXYZNode::CombineXYZNode() -: ShaderNode("combine_xyz") +: ShaderNode(node_type) { - add_input("X", SocketType::FLOAT); - add_input("Y", SocketType::FLOAT); - add_input("Z", SocketType::FLOAT); - add_output("Vector", SocketType::VECTOR); } void CombineXYZNode::compile(SVMCompiler& compiler) @@ -3492,13 +3801,23 @@ void CombineXYZNode::compile(OSLCompiler& compiler) } /* Combine HSV */ + +NODE_DEFINE(CombineHSVNode) +{ + NodeType* type = NodeType::add("combine_hsv", create, NodeType::SHADER); + + SOCKET_IN_FLOAT(h, "H", 0.0f); + SOCKET_IN_FLOAT(s, "S", 0.0f); + SOCKET_IN_FLOAT(v, "V", 0.0f); + + SOCKET_OUT_COLOR(color, "Color"); + + return type; +} + CombineHSVNode::CombineHSVNode() -: ShaderNode("combine_hsv") +: ShaderNode(node_type) { - add_input("H", SocketType::FLOAT); - add_input("S", SocketType::FLOAT); - add_input("V", SocketType::FLOAT); - add_output("Color", SocketType::COLOR); } void CombineHSVNode::compile(SVMCompiler& compiler) @@ -3522,12 +3841,21 @@ void CombineHSVNode::compile(OSLCompiler& compiler) } /* Gamma */ + +NODE_DEFINE(GammaNode) +{ + NodeType* type = NodeType::add("gamma", create, NodeType::SHADER); + + SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f)); + SOCKET_IN_FLOAT(gamma, "Gamma", 1.0f); + SOCKET_OUT_COLOR(color, "Color"); + + return type; +} + GammaNode::GammaNode() -: ShaderNode("gamma") +: ShaderNode(node_type) { - add_input("Color", SocketType::COLOR); - add_input("Gamma", SocketType::FLOAT); - add_output("Color", SocketType::COLOR); } bool GammaNode::constant_fold(ShaderGraph *, ShaderOutput *socket, ShaderInput *optimized) @@ -3535,12 +3863,9 @@ bool GammaNode::constant_fold(ShaderGraph *, ShaderOutput *socket, ShaderInput * ShaderInput *color_in = input("Color"); ShaderInput *gamma_in = input("Gamma"); - if(socket == output("Color")) { - if(color_in->link == NULL && gamma_in->link == NULL) { - optimized->set(svm_math_gamma_color(color_in->value(), - gamma_in->value_float())); - return true; - } + if(color_in->link == NULL && gamma_in->link == NULL) { + optimized->set(svm_math_gamma_color(color, gamma)); + return true; } return false; @@ -3564,13 +3889,23 @@ void GammaNode::compile(OSLCompiler& compiler) } /* Bright Contrast */ + +NODE_DEFINE(BrightContrastNode) +{ + NodeType* type = NodeType::add("brightness_contrast", create, NodeType::SHADER); + + SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f)); + SOCKET_IN_FLOAT(bright, "Bright", 0.0f); + SOCKET_IN_FLOAT(contrast, "Contrast", 0.0f); + + SOCKET_OUT_COLOR(color, "Color"); + + return type; +} + BrightContrastNode::BrightContrastNode() -: ShaderNode("brightness") +: ShaderNode(node_type) { - add_input("Color", SocketType::COLOR); - add_input("Bright", SocketType::FLOAT); - add_input("Contrast", SocketType::FLOAT); - add_output("Color", SocketType::COLOR); } void BrightContrastNode::compile(SVMCompiler& compiler) @@ -3594,13 +3929,23 @@ void BrightContrastNode::compile(OSLCompiler& compiler) } /* Separate RGB */ + +NODE_DEFINE(SeparateRGBNode) +{ + NodeType* type = NodeType::add("separate_rgb", create, NodeType::SHADER); + + SOCKET_IN_COLOR(color, "Image", make_float3(0.0f, 0.0f, 0.0f)); + + SOCKET_OUT_FLOAT(g, "R"); + SOCKET_OUT_FLOAT(g, "G"); + SOCKET_OUT_FLOAT(b, "B"); + + return type; +} + SeparateRGBNode::SeparateRGBNode() -: ShaderNode("separate_rgb") +: ShaderNode(node_type) { - add_input("Image", SocketType::COLOR); - add_output("R", SocketType::FLOAT); - add_output("G", SocketType::FLOAT); - add_output("B", SocketType::FLOAT); } void SeparateRGBNode::compile(SVMCompiler& compiler) @@ -3629,13 +3974,23 @@ void SeparateRGBNode::compile(OSLCompiler& compiler) } /* Separate XYZ */ + +NODE_DEFINE(SeparateXYZNode) +{ + NodeType* type = NodeType::add("separate_xyz", create, NodeType::SHADER); + + SOCKET_IN_COLOR(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f)); + + SOCKET_OUT_FLOAT(x, "X"); + SOCKET_OUT_FLOAT(y, "Y"); + SOCKET_OUT_FLOAT(z, "Z"); + + return type; +} + SeparateXYZNode::SeparateXYZNode() -: ShaderNode("separate_xyz") +: ShaderNode(node_type) { - add_input("Vector", SocketType::VECTOR); - add_output("X", SocketType::FLOAT); - add_output("Y", SocketType::FLOAT); - add_output("Z", SocketType::FLOAT); } void SeparateXYZNode::compile(SVMCompiler& compiler) @@ -3664,13 +4019,23 @@ void SeparateXYZNode::compile(OSLCompiler& compiler) } /* Separate HSV */ + +NODE_DEFINE(SeparateHSVNode) +{ + NodeType* type = NodeType::add("separate_hsv", create, NodeType::SHADER); + + SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f)); + + SOCKET_OUT_FLOAT(h, "H"); + SOCKET_OUT_FLOAT(s, "S"); + SOCKET_OUT_FLOAT(v, "V"); + + return type; +} + SeparateHSVNode::SeparateHSVNode() -: ShaderNode("separate_hsv") +: ShaderNode(node_type) { - add_input("Color", SocketType::COLOR); - add_output("H", SocketType::FLOAT); - add_output("S", SocketType::FLOAT); - add_output("V", SocketType::FLOAT); } void SeparateHSVNode::compile(SVMCompiler& compiler) @@ -3694,15 +4059,25 @@ void SeparateHSVNode::compile(OSLCompiler& compiler) } /* Hue Saturation Value */ + +NODE_DEFINE(HSVNode) +{ + NodeType* type = NodeType::add("hsv", create, NodeType::SHADER); + + SOCKET_IN_FLOAT(hue, "Hue", 0.5f); + SOCKET_IN_FLOAT(saturation, "Saturation", 1.0f); + SOCKET_IN_FLOAT(value, "Value", 1.0f); + SOCKET_IN_FLOAT(fac, "Fac", 1.0f); + SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f)); + + SOCKET_OUT_COLOR(color, "Color"); + + return type; +} + HSVNode::HSVNode() -: ShaderNode("hsv") +: ShaderNode(node_type) { - add_input("Hue", SocketType::FLOAT); - add_input("Saturation", SocketType::FLOAT); - add_input("Value", SocketType::FLOAT); - add_input("Fac", SocketType::FLOAT); - add_input("Color", SocketType::COLOR); - add_output("Color", SocketType::COLOR); } void HSVNode::compile(SVMCompiler& compiler) @@ -3732,14 +4107,22 @@ void HSVNode::compile(OSLCompiler& compiler) /* Attribute */ -AttributeNode::AttributeNode() -: ShaderNode("attribute") +NODE_DEFINE(AttributeNode) { - attribute = ""; + NodeType* type = NodeType::add("attribute", create, NodeType::SHADER); + + SOCKET_STRING(attribute, "Attribute", ustring("")); + + SOCKET_OUT_COLOR(color, "Color"); + SOCKET_OUT_VECTOR(vector, "Vector"); + SOCKET_OUT_FLOAT(fac, "Fac"); + + return type; +} - add_output("Color", SocketType::COLOR); - add_output("Vector", SocketType::VECTOR); - add_output("Fac", SocketType::FLOAT); +AttributeNode::AttributeNode() +: ShaderNode(node_type) +{ } void AttributeNode::attributes(Shader *shader, AttributeRequestSet *attributes) @@ -3815,12 +4198,20 @@ void AttributeNode::compile(OSLCompiler& compiler) /* Camera */ +NODE_DEFINE(CameraNode) +{ + NodeType* type = NodeType::add("camera_info", create, NodeType::SHADER); + + SOCKET_OUT_VECTOR(view_vector, "View Vector"); + SOCKET_OUT_FLOAT(view_z_depth, "View Z Depth"); + SOCKET_OUT_FLOAT(view_distance, "View Distance"); + + return type; +} + CameraNode::CameraNode() -: ShaderNode("camera") +: ShaderNode(node_type) { - add_output("View Vector", SocketType::VECTOR); - add_output("View Z Depth", SocketType::FLOAT); - add_output("View Distance", SocketType::FLOAT); } void CameraNode::compile(SVMCompiler& compiler) @@ -3842,12 +4233,21 @@ void CameraNode::compile(OSLCompiler& compiler) /* Fresnel */ +NODE_DEFINE(FresnelNode) +{ + NodeType* type = NodeType::add("fresnel", create, NodeType::SHADER); + + SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL); + SOCKET_IN_FLOAT(IOR, "IOR", 1.45f); + + SOCKET_OUT_FLOAT(fac, "Fac"); + + return type; +} + FresnelNode::FresnelNode() -: ShaderNode("fresnel") +: ShaderNode(node_type) { - add_input("Normal", SocketType::NORMAL, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL); - add_input("IOR", SocketType::FLOAT, 1.45f); - add_output("Fac", SocketType::FLOAT); } void FresnelNode::compile(SVMCompiler& compiler) @@ -3858,7 +4258,7 @@ void FresnelNode::compile(SVMCompiler& compiler) compiler.add_node(NODE_FRESNEL, compiler.stack_assign(IOR_in), - __float_as_int(IOR_in->value_float()), + __float_as_int(IOR), compiler.encode_uchar4( compiler.stack_assign_if_linked(normal_in), compiler.stack_assign(fac_out))); @@ -3871,14 +4271,22 @@ void FresnelNode::compile(OSLCompiler& compiler) /* Layer Weight */ -LayerWeightNode::LayerWeightNode() -: ShaderNode("layer_weight") +NODE_DEFINE(LayerWeightNode) { - add_input("Normal", SocketType::NORMAL, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL); - add_input("Blend", SocketType::FLOAT, 0.5f); + NodeType* type = NodeType::add("layer_weight", create, NodeType::SHADER); - add_output("Fresnel", SocketType::FLOAT); - add_output("Facing", SocketType::FLOAT); + SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL); + SOCKET_IN_FLOAT(blend, "Blend", 0.5f); + + SOCKET_OUT_FLOAT(fresnel, "Fresnel"); + SOCKET_OUT_FLOAT(facing, "Facing"); + + return type; +} + +LayerWeightNode::LayerWeightNode() +: ShaderNode(node_type) +{ } void LayerWeightNode::compile(SVMCompiler& compiler) @@ -3891,7 +4299,7 @@ void LayerWeightNode::compile(SVMCompiler& compiler) if(!fresnel_out->links.empty()) { compiler.add_node(NODE_LAYER_WEIGHT, compiler.stack_assign_if_linked(blend_in), - __float_as_int(blend_in->value_float()), + __float_as_int(blend), compiler.encode_uchar4(NODE_LAYER_WEIGHT_FRESNEL, compiler.stack_assign_if_linked(normal_in), compiler.stack_assign(fresnel_out))); @@ -3900,7 +4308,7 @@ void LayerWeightNode::compile(SVMCompiler& compiler) if(!facing_out->links.empty()) { compiler.add_node(NODE_LAYER_WEIGHT, compiler.stack_assign_if_linked(blend_in), - __float_as_int(blend_in->value_float()), + __float_as_int(blend), compiler.encode_uchar4(NODE_LAYER_WEIGHT_FACING, compiler.stack_assign_if_linked(normal_in), compiler.stack_assign(facing_out))); @@ -3914,13 +4322,20 @@ void LayerWeightNode::compile(OSLCompiler& compiler) /* Wireframe */ +NODE_DEFINE(WireframeNode) +{ + NodeType* type = NodeType::add("wireframe", create, NodeType::SHADER); + + SOCKET_BOOLEAN(use_pixel_size, "Use Pixel Size", false); + SOCKET_IN_FLOAT(size, "Size", 0.01f); + SOCKET_OUT_FLOAT(fac, "Fac"); + + return type; +} + WireframeNode::WireframeNode() -: ShaderNode("wireframe") +: ShaderNode(node_type) { - add_input("Size", SocketType::FLOAT, 0.01f); - add_output("Fac", SocketType::FLOAT); - - use_pixel_size = false; } void WireframeNode::compile(SVMCompiler& compiler) @@ -3953,17 +4368,25 @@ void WireframeNode::compile(OSLCompiler& compiler) else { compiler.parameter("bump_offset", "center"); } - compiler.parameter("use_pixel_size", use_pixel_size); + compiler.parameter(this, "use_pixel_size"); compiler.add(this, "node_wireframe"); } /* Wavelength */ +NODE_DEFINE(WavelengthNode) +{ + NodeType* type = NodeType::add("wavelength", create, NodeType::SHADER); + + SOCKET_IN_FLOAT(wavelength, "Wavelength", 500.0f); + SOCKET_OUT_COLOR(color, "Color"); + + return type; +} + WavelengthNode::WavelengthNode() -: ShaderNode("wavelength") +: ShaderNode(node_type) { - add_input("Wavelength", SocketType::FLOAT, 500.0f); - add_output("Color", SocketType::COLOR); } void WavelengthNode::compile(SVMCompiler& compiler) @@ -3983,22 +4406,28 @@ void WavelengthNode::compile(OSLCompiler& compiler) /* Blackbody */ +NODE_DEFINE(BlackbodyNode) +{ + NodeType* type = NodeType::add("blackbody", create, NodeType::SHADER); + + SOCKET_IN_FLOAT(temperature, "Temperature", 1200.0f); + SOCKET_OUT_COLOR(color, "Color"); + + return type; +} + BlackbodyNode::BlackbodyNode() -: ShaderNode("blackbody") +: ShaderNode(node_type) { - add_input("Temperature", SocketType::FLOAT, 1200.0f); - add_output("Color", SocketType::COLOR); } bool BlackbodyNode::constant_fold(ShaderGraph *, ShaderOutput *socket, ShaderInput *optimized) { ShaderInput *temperature_in = input("Temperature"); - if(socket == output("Color")) { - if(temperature_in->link == NULL) { - optimized->set(svm_math_blackbody_color(temperature_in->value_float())); - return true; - } + if(temperature_in->link == NULL) { + optimized->set(svm_math_blackbody_color(temperature)); + return true; } return false; @@ -4021,15 +4450,22 @@ void BlackbodyNode::compile(OSLCompiler& compiler) /* Output */ +NODE_DEFINE(OutputNode) +{ + NodeType* type = NodeType::add("output", create, NodeType::SHADER); + + SOCKET_IN_CLOSURE(surface, "Surface"); + SOCKET_IN_CLOSURE(volume, "Volume"); + SOCKET_IN_FLOAT(displacement, "Displacement", 0.0f); + SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f)); + + return type; +} + OutputNode::OutputNode() -: ShaderNode("output") +: ShaderNode(node_type) { special_type = SHADER_SPECIAL_TYPE_OUTPUT; - - add_input("Surface", SocketType::CLOSURE); - add_input("Volume", SocketType::CLOSURE); - add_input("Displacement", SocketType::FLOAT); - add_input("Normal", SocketType::NORMAL); } void OutputNode::compile(SVMCompiler& compiler) @@ -4055,66 +4491,62 @@ void OutputNode::compile(OSLCompiler& compiler) /* Math */ -MathNode::MathNode() -: ShaderNode("math") +NODE_DEFINE(MathNode) { - type = NODE_MATH_ADD; + NodeType* type = NodeType::add("math", create, NodeType::SHADER); - use_clamp = false; + static NodeEnum type_enum; + type_enum.insert("Add", NODE_MATH_ADD); + type_enum.insert("Subtract", NODE_MATH_SUBTRACT); + type_enum.insert("Multiply", NODE_MATH_MULTIPLY); + type_enum.insert("Divide", NODE_MATH_DIVIDE); + type_enum.insert("Sine", NODE_MATH_SINE); + type_enum.insert("Cosine", NODE_MATH_COSINE); + type_enum.insert("Tangent", NODE_MATH_TANGENT); + type_enum.insert("Arcsine", NODE_MATH_ARCSINE); + type_enum.insert("Arccosine", NODE_MATH_ARCCOSINE); + type_enum.insert("Arctangent", NODE_MATH_ARCTANGENT); + type_enum.insert("Power", NODE_MATH_POWER); + type_enum.insert("Logarithm", NODE_MATH_LOGARITHM); + type_enum.insert("Minimum", NODE_MATH_MINIMUM); + type_enum.insert("Maximum", NODE_MATH_MAXIMUM); + type_enum.insert("Round", NODE_MATH_ROUND); + type_enum.insert("Less Than", NODE_MATH_LESS_THAN); + type_enum.insert("Greater Than", NODE_MATH_GREATER_THAN); + type_enum.insert("Modulo", NODE_MATH_MODULO); + type_enum.insert("Absolute", NODE_MATH_ABSOLUTE); + SOCKET_ENUM(type, "Type", type_enum, NODE_MATH_ADD); - add_input("Value1", SocketType::FLOAT); - add_input("Value2", SocketType::FLOAT); - add_output("Value", SocketType::FLOAT); -} + SOCKET_BOOLEAN(use_clamp, "Use Clamp", false); -static NodeEnum math_type_init() -{ - NodeEnum enm; + SOCKET_IN_FLOAT(value1, "Value1", 0.0f); + SOCKET_IN_FLOAT(value2, "Value2", 0.0f); - enm.insert("Add", NODE_MATH_ADD); - enm.insert("Subtract", NODE_MATH_SUBTRACT); - enm.insert("Multiply", NODE_MATH_MULTIPLY); - enm.insert("Divide", NODE_MATH_DIVIDE); - enm.insert("Sine", NODE_MATH_SINE); - enm.insert("Cosine", NODE_MATH_COSINE); - enm.insert("Tangent", NODE_MATH_TANGENT); - enm.insert("Arcsine", NODE_MATH_ARCSINE); - enm.insert("Arccosine", NODE_MATH_ARCCOSINE); - enm.insert("Arctangent", NODE_MATH_ARCTANGENT); - enm.insert("Power", NODE_MATH_POWER); - enm.insert("Logarithm", NODE_MATH_LOGARITHM); - enm.insert("Minimum", NODE_MATH_MINIMUM); - enm.insert("Maximum", NODE_MATH_MAXIMUM); - enm.insert("Round", NODE_MATH_ROUND); - enm.insert("Less Than", NODE_MATH_LESS_THAN); - enm.insert("Greater Than", NODE_MATH_GREATER_THAN); - enm.insert("Modulo", NODE_MATH_MODULO); - enm.insert("Absolute", NODE_MATH_ABSOLUTE); + SOCKET_OUT_FLOAT(value, "Value"); - return enm; + return type; } -NodeEnum MathNode::type_enum = math_type_init(); +MathNode::MathNode() +: ShaderNode(node_type) +{ +} bool MathNode::constant_fold(ShaderGraph *, ShaderOutput *socket, ShaderInput *optimized) { ShaderInput *value1_in = input("Value1"); ShaderInput *value2_in = input("Value2"); - if(socket == output("Value")) { - if(value1_in->link == NULL && value2_in->link == NULL) { - float value = svm_math(type, - value1_in->value_float(), - value2_in->value_float()); + if(value1_in->link == NULL && value2_in->link == NULL) { + float value = svm_math(type, value1, value2); - if(use_clamp) { - value = saturate(value); - } + if(use_clamp) { + value = saturate(value); + } - optimized->set(value); + optimized->set(value); - return true; - } + return true; } return false; @@ -4137,39 +4569,39 @@ void MathNode::compile(SVMCompiler& compiler) void MathNode::compile(OSLCompiler& compiler) { - compiler.parameter("type", type_enum[type]); - compiler.parameter("use_clamp", use_clamp); + compiler.parameter(this, "type"); + compiler.parameter(this, "use_clamp"); compiler.add(this, "node_math"); } /* VectorMath */ -VectorMathNode::VectorMathNode() -: ShaderNode("vector_math") +NODE_DEFINE(VectorMathNode) { - type = NODE_VECTOR_MATH_ADD; + NodeType* type = NodeType::add("vector_math", create, NodeType::SHADER); - add_input("Vector1", SocketType::VECTOR); - add_input("Vector2", SocketType::VECTOR); - add_output("Value", SocketType::FLOAT); - add_output("Vector", SocketType::VECTOR); -} + static NodeEnum type_enum; + type_enum.insert("Add", NODE_VECTOR_MATH_ADD); + type_enum.insert("Subtract", NODE_VECTOR_MATH_SUBTRACT); + type_enum.insert("Average", NODE_VECTOR_MATH_AVERAGE); + type_enum.insert("Dot Product", NODE_VECTOR_MATH_DOT_PRODUCT); + type_enum.insert("Cross Product", NODE_VECTOR_MATH_CROSS_PRODUCT); + type_enum.insert("Normalize", NODE_VECTOR_MATH_NORMALIZE); + SOCKET_ENUM(type, "Type", type_enum, NODE_VECTOR_MATH_ADD); -static NodeEnum vector_math_type_init() -{ - NodeEnum enm; + SOCKET_IN_VECTOR(vector1, "Vector1", make_float3(0.0f, 0.0f, 0.0f)); + SOCKET_IN_VECTOR(vector2, "Vector2", make_float3(0.0f, 0.0f, 0.0f)); - enm.insert("Add", NODE_VECTOR_MATH_ADD); - enm.insert("Subtract", NODE_VECTOR_MATH_SUBTRACT); - enm.insert("Average", NODE_VECTOR_MATH_AVERAGE); - enm.insert("Dot Product", NODE_VECTOR_MATH_DOT_PRODUCT); - enm.insert("Cross Product", NODE_VECTOR_MATH_CROSS_PRODUCT); - enm.insert("Normalize", NODE_VECTOR_MATH_NORMALIZE); + SOCKET_OUT_FLOAT(value, "Value"); + SOCKET_OUT_VECTOR(vector, "Vector"); - return enm; + return type; } -NodeEnum VectorMathNode::type_enum = vector_math_type_init(); +VectorMathNode::VectorMathNode() +: ShaderNode(node_type) +{ +} bool VectorMathNode::constant_fold(ShaderGraph *, ShaderOutput *socket, ShaderInput *optimized) { @@ -4183,8 +4615,8 @@ bool VectorMathNode::constant_fold(ShaderGraph *, ShaderOutput *socket, ShaderIn svm_vector_math(&value, &vector, type, - vector1_in->value(), - vector2_in->value()); + vector1, + vector2); if(socket == output("Value")) { optimized->set(value); @@ -4217,48 +4649,40 @@ void VectorMathNode::compile(SVMCompiler& compiler) void VectorMathNode::compile(OSLCompiler& compiler) { - compiler.parameter("type", type_enum[type]); + compiler.parameter(this, "type"); compiler.add(this, "node_vector_math"); } /* VectorTransform */ -VectorTransformNode::VectorTransformNode() -: ShaderNode("vector_transform") +NODE_DEFINE(VectorTransformNode) { - type = NODE_VECTOR_TRANSFORM_TYPE_VECTOR; - convert_from = NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD; - convert_to = NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT; + NodeType* type = NodeType::add("vector_transform", create, NodeType::SHADER); - add_input("Vector", SocketType::VECTOR); - add_output("Vector", SocketType::VECTOR); -} + static NodeEnum type_enum; + type_enum.insert("Vector", NODE_VECTOR_TRANSFORM_TYPE_VECTOR); + type_enum.insert("Point", NODE_VECTOR_TRANSFORM_TYPE_POINT); + type_enum.insert("Normal", NODE_VECTOR_TRANSFORM_TYPE_NORMAL); + SOCKET_ENUM(type, "Type", type_enum, NODE_VECTOR_TRANSFORM_TYPE_VECTOR); -static NodeEnum vector_transform_type_init() -{ - NodeEnum enm; + static NodeEnum space_enum; + space_enum.insert("world", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD); + space_enum.insert("object", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT); + space_enum.insert("camera", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_CAMERA); + SOCKET_ENUM(convert_from, "Convert From", space_enum, NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD); + SOCKET_ENUM(convert_to, "Convert To", space_enum, NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT); - enm.insert("Vector", NODE_VECTOR_TRANSFORM_TYPE_VECTOR); - enm.insert("Point", NODE_VECTOR_TRANSFORM_TYPE_POINT); - enm.insert("Normal", NODE_VECTOR_TRANSFORM_TYPE_NORMAL); + SOCKET_IN_VECTOR(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f)); + SOCKET_OUT_VECTOR(vector, "Vector"); - return enm; + return type; } -static NodeEnum vector_transform_convert_space_init() +VectorTransformNode::VectorTransformNode() +: ShaderNode(node_type) { - NodeEnum enm; - - enm.insert("world", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD); - enm.insert("object", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT); - enm.insert("camera", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_CAMERA); - - return enm; } -NodeEnum VectorTransformNode::type_enum = vector_transform_type_init(); -NodeEnum VectorTransformNode::convert_space_enum = vector_transform_convert_space_init(); - void VectorTransformNode::compile(SVMCompiler& compiler) { ShaderInput *vector_in = input("Vector"); @@ -4272,33 +4696,40 @@ void VectorTransformNode::compile(SVMCompiler& compiler) void VectorTransformNode::compile(OSLCompiler& compiler) { - compiler.parameter("type", type_enum[type]); - compiler.parameter("convert_from", convert_space_enum[convert_from]); - compiler.parameter("convert_to", convert_space_enum[convert_to]); + compiler.parameter(this, "type"); + compiler.parameter(this, "convert_from"); + compiler.parameter(this, "convert_to"); compiler.add(this, "node_vector_transform"); } /* BumpNode */ -BumpNode::BumpNode() -: ShaderNode("bump") +NODE_DEFINE(BumpNode) { - invert = false; + NodeType* type = NodeType::add("bump", create, NodeType::SHADER); - special_type = SHADER_SPECIAL_TYPE_BUMP; + SOCKET_BOOLEAN(invert, "Invert", false); /* this input is used by the user, but after graph transform it is no longer * used and moved to sampler center/x/y instead */ - add_input("Height", SocketType::FLOAT); + SOCKET_IN_FLOAT(height, "Height", 1.0f); + + SOCKET_IN_FLOAT(sample_center, "SampleCenter", 0.0f); + SOCKET_IN_FLOAT(sample_x, "SampleX", 0.0f); + SOCKET_IN_FLOAT(sample_y, "SampleY", 0.0f); + SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL); + SOCKET_IN_FLOAT(strength, "Strength", 1.0f); + SOCKET_IN_FLOAT(distance, "Distance", 0.1f); + + SOCKET_OUT_NORMAL(normal, "Normal"); - add_input("SampleCenter", SocketType::FLOAT); - add_input("SampleX", SocketType::FLOAT); - add_input("SampleY", SocketType::FLOAT); - add_input("Normal", SocketType::NORMAL, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL); - add_input("Strength", SocketType::FLOAT, 1.0f); - add_input("Distance", SocketType::FLOAT, 0.1f); + return type; +} - add_output("Normal", SocketType::NORMAL); +BumpNode::BumpNode() +: ShaderNode(node_type) +{ + special_type = SHADER_SPECIAL_TYPE_BUMP; } void BumpNode::compile(SVMCompiler& compiler) @@ -4327,7 +4758,7 @@ void BumpNode::compile(SVMCompiler& compiler) void BumpNode::compile(OSLCompiler& compiler) { - compiler.parameter("invert", invert); + compiler.parameter(this, "invert"); compiler.add(this, "node_bump"); } @@ -4355,15 +4786,25 @@ bool BumpNode::constant_fold(ShaderGraph *graph, ShaderOutput *, ShaderInput *) /* RGBCurvesNode */ -RGBCurvesNode::RGBCurvesNode() -: ShaderNode("rgb_curves") +NODE_DEFINE(RGBCurvesNode) { - add_input("Fac", SocketType::FLOAT); - add_input("Color", SocketType::COLOR); - add_output("Color", SocketType::COLOR); + NodeType* type = NodeType::add("rgb_curves", create, NodeType::SHADER); - min_x = 0.0f; - max_x = 1.0f; + SOCKET_COLOR_ARRAY(curves, "Curves", array()); + SOCKET_FLOAT(min_x, "Min X", 0.0f); + SOCKET_FLOAT(max_x, "Max X", 1.0f); + + SOCKET_IN_FLOAT(fac, "Fac", 0.0f); + SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f)); + + SOCKET_OUT_COLOR(color, "Color"); + + return type; +} + +RGBCurvesNode::RGBCurvesNode() +: ShaderNode(node_type) +{ } void RGBCurvesNode::compile(SVMCompiler& compiler) @@ -4393,22 +4834,32 @@ void RGBCurvesNode::compile(OSLCompiler& compiler) return; compiler.parameter_color_array("ramp", curves); - compiler.parameter("min_x", min_x); - compiler.parameter("max_x", max_x); + compiler.parameter(this, "min_x"); + compiler.parameter(this, "max_x"); compiler.add(this, "node_rgb_curves"); } /* VectorCurvesNode */ -VectorCurvesNode::VectorCurvesNode() -: ShaderNode("vector_curves") +NODE_DEFINE(VectorCurvesNode) { - add_input("Fac", SocketType::FLOAT); - add_input("Vector", SocketType::VECTOR); - add_output("Vector", SocketType::VECTOR); + NodeType* type = NodeType::add("vector_curves", create, NodeType::SHADER); + + SOCKET_VECTOR_ARRAY(curves, "Curves", array()); + SOCKET_FLOAT(min_x, "Min X", 0.0f); + SOCKET_FLOAT(max_x, "Max X", 1.0f); + + SOCKET_IN_FLOAT(fac, "Fac", 0.0f); + SOCKET_IN_VECTOR(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f)); - min_x = 0.0f; - max_x = 1.0f; + SOCKET_OUT_VECTOR(vector, "Vector"); + + return type; +} + +VectorCurvesNode::VectorCurvesNode() +: ShaderNode(node_type) +{ } void VectorCurvesNode::compile(SVMCompiler& compiler) @@ -4438,21 +4889,32 @@ void VectorCurvesNode::compile(OSLCompiler& compiler) return; compiler.parameter_color_array("ramp", curves); - compiler.parameter("min_x", min_x); - compiler.parameter("max_x", max_x); + compiler.parameter(this, "min_x"); + compiler.parameter(this, "max_x"); compiler.add(this, "node_vector_curves"); } /* RGBRampNode */ -RGBRampNode::RGBRampNode() -: ShaderNode("rgb_ramp") +NODE_DEFINE(RGBRampNode) { - add_input("Fac", SocketType::FLOAT); - add_output("Color", SocketType::COLOR); - add_output("Alpha", SocketType::FLOAT); + NodeType* type = NodeType::add("rgb_ramp", create, NodeType::SHADER); + + SOCKET_COLOR_ARRAY(ramp, "Ramp", array()); + SOCKET_FLOAT_ARRAY(ramp_alpha, "Ramp Alpha", array()); + SOCKET_BOOLEAN(interpolate, "Interpolate", true); + + SOCKET_IN_FLOAT(fac, "Fac", 0.0f); + + SOCKET_OUT_COLOR(color, "Color"); + SOCKET_OUT_FLOAT(alpha, "Alpha"); + + return type; +} - interpolate = true; +RGBRampNode::RGBRampNode() +: ShaderNode(node_type) +{ } void RGBRampNode::compile(SVMCompiler& compiler) @@ -4483,18 +4945,26 @@ void RGBRampNode::compile(OSLCompiler& compiler) compiler.parameter_color_array("ramp_color", ramp); compiler.parameter_array("ramp_alpha", ramp_alpha.data(), ramp_alpha.size()); - compiler.parameter("interpolate", interpolate); + compiler.parameter(this, "interpolate"); compiler.add(this, "node_rgb_ramp"); } /* Set Normal Node */ +NODE_DEFINE(SetNormalNode) +{ + NodeType* type = NodeType::add("set_normal", create, NodeType::SHADER); + + SOCKET_IN_VECTOR(direction, "Direction", make_float3(0.0f, 0.0f, 0.0f)); + SOCKET_OUT_NORMAL(normal, "Normal"); + + return type; +} + SetNormalNode::SetNormalNode() -: ShaderNode("set_normal") +: ShaderNode(node_type) { - add_input("Direction", SocketType::VECTOR); - add_output("Normal", SocketType::NORMAL); } void SetNormalNode::compile(SVMCompiler& compiler) @@ -4515,18 +4985,47 @@ void SetNormalNode::compile(OSLCompiler& compiler) /* OSLNode */ OSLNode::OSLNode() -: ShaderNode("osl_shader") +: ShaderNode(new NodeType(NodeType::SHADER)) { special_type = SHADER_SPECIAL_TYPE_SCRIPT; } OSLNode::~OSLNode() { + delete type; +} + +OSLNode* OSLNode::create(size_t num_inputs) +{ + /* allocate space for the node itself and parameters, aligned to 16 bytes + * assuming that's the most parameter types need */ + size_t node_size = align_up(sizeof(OSLNode), 16); + size_t inputs_size = align_up(SocketType::max_size(), 16) * num_inputs; + + char *node_memory = (char*) operator new(node_size + inputs_size); + memset(node_memory, 0, node_size + inputs_size); + + return new(node_memory) OSLNode(); +} + +char* OSLNode::input_default_value() +{ + /* pointer to default value storage, which is the same as our actual value */ + size_t num_inputs = type->inputs.size(); + size_t inputs_size = align_up(SocketType::max_size(), 16) * num_inputs; + return (char*)this + align_up(sizeof(OSLNode), 16) + inputs_size; } -OSLNode* OSLNode::create(size_t) +void OSLNode::add_input(ustring name, SocketType::Type socket_type) { - return new OSLNode(); + char *memory = input_default_value(); + size_t offset = memory - (char*)this; + const_cast(type)->register_input(name, name, socket_type, offset, memory, NULL, NULL, SocketType::LINKABLE); +} + +void OSLNode::add_output(ustring name, SocketType::Type socket_type) +{ + const_cast(type)->register_output(name, name, socket_type); } void OSLNode::compile(SVMCompiler&) @@ -4544,32 +5043,32 @@ void OSLNode::compile(OSLCompiler& compiler) /* Normal Map */ -static NodeEnum normal_map_space_init() +NODE_DEFINE(NormalMapNode) { - NodeEnum enm; + NodeType* type = NodeType::add("normal_map", create, NodeType::SHADER); - enm.insert("Tangent", NODE_NORMAL_MAP_TANGENT); - enm.insert("Object", NODE_NORMAL_MAP_OBJECT); - enm.insert("World", NODE_NORMAL_MAP_WORLD); - enm.insert("Blender Object", NODE_NORMAL_MAP_BLENDER_OBJECT); - enm.insert("Blender World", NODE_NORMAL_MAP_BLENDER_WORLD); + static NodeEnum space_enum; + space_enum.insert("Tangent", NODE_NORMAL_MAP_TANGENT); + space_enum.insert("Object", NODE_NORMAL_MAP_OBJECT); + space_enum.insert("World", NODE_NORMAL_MAP_WORLD); + space_enum.insert("Blender Object", NODE_NORMAL_MAP_BLENDER_OBJECT); + space_enum.insert("Blender World", NODE_NORMAL_MAP_BLENDER_WORLD); + SOCKET_ENUM(space, "Space", space_enum, NODE_TANGENT_RADIAL); - return enm; -} + SOCKET_STRING(attribute, "Attribute", ustring("")); -NodeEnum NormalMapNode::space_enum = normal_map_space_init(); + 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); + SOCKET_IN_COLOR(color, "Color", make_float3(0.5f, 0.5f, 1.0f)); -NormalMapNode::NormalMapNode() -: ShaderNode("normal_map") -{ - space = NODE_NORMAL_MAP_TANGENT; - attribute = ustring(""); + SOCKET_OUT_NORMAL(normal, "Normal"); - add_input("NormalIn", SocketType::NORMAL, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL); - add_input("Strength", SocketType::FLOAT, 1.0f); - add_input("Color", SocketType::COLOR); + return type; +} - add_output("Normal", SocketType::NORMAL); +NormalMapNode::NormalMapNode() +: ShaderNode(node_type) +{ } void NormalMapNode::attributes(Shader *shader, AttributeRequestSet *attributes) @@ -4630,46 +5129,38 @@ void NormalMapNode::compile(OSLCompiler& compiler) } } - compiler.parameter("space", space_enum[space]); - + compiler.parameter(this, "space"); compiler.add(this, "node_normal_map"); } /* Tangent */ -static NodeEnum tangent_direction_type_init() +NODE_DEFINE(TangentNode) { - NodeEnum enm; + NodeType* type = NodeType::add("tangent", create, NodeType::SHADER); - enm.insert("Radial", NODE_TANGENT_RADIAL); - enm.insert("UV Map", NODE_TANGENT_UVMAP); + static NodeEnum direction_type_enum; + direction_type_enum.insert("Radial", NODE_TANGENT_RADIAL); + direction_type_enum.insert("UV Map", NODE_TANGENT_UVMAP); + SOCKET_ENUM(direction_type, "Direction Type", direction_type_enum, NODE_TANGENT_RADIAL); - return enm; -} + static NodeEnum axis_enum; + axis_enum.insert("X", NODE_TANGENT_AXIS_X); + axis_enum.insert("Y", NODE_TANGENT_AXIS_Y); + axis_enum.insert("Z", NODE_TANGENT_AXIS_Z); + SOCKET_ENUM(axis, "Axis", axis_enum, NODE_TANGENT_AXIS_X); -static NodeEnum tangent_axis_init() -{ - NodeEnum enm; + SOCKET_STRING(attribute, "Attribute", ustring("")); - enm.insert("X", NODE_TANGENT_AXIS_X); - enm.insert("Y", NODE_TANGENT_AXIS_Y); - enm.insert("Z", NODE_TANGENT_AXIS_Z); + 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"); - return enm; + return type; } -NodeEnum TangentNode::direction_type_enum = tangent_direction_type_init(); -NodeEnum TangentNode::axis_enum = tangent_axis_init(); - TangentNode::TangentNode() -: ShaderNode("tangent") +: ShaderNode(node_type) { - direction_type = NODE_TANGENT_RADIAL; - axis = NODE_TANGENT_AXIS_X; - attribute = ustring(""); - - add_input("NormalIn", SocketType::NORMAL, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL); - add_output("Tangent", SocketType::NORMAL); } void TangentNode::attributes(Shader *shader, AttributeRequestSet *attributes) @@ -4718,8 +5209,8 @@ void TangentNode::compile(OSLCompiler& compiler) compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str())); } - compiler.parameter("direction_type", direction_type_enum[direction_type]); - compiler.parameter("axis", axis_enum[axis]); + compiler.parameter(this, "direction_type"); + compiler.parameter(this, "axis"); compiler.add(this, "node_tangent"); } diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 8b17e455f7a..a0c09f0807a 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -18,6 +18,7 @@ #define __NODES_H__ #include "graph.h" +#include "node.h" #include "util_string.h" @@ -35,6 +36,7 @@ public: Transform compute_transform(); bool skip(); void compile(SVMCompiler& compiler, int offset_in, int offset_out); + int compile(SVMCompiler& compiler, ShaderInput *vector_in); void compile(OSLCompiler &compiler); int compile_begin(SVMCompiler& compiler, ShaderInput *vector_in); @@ -49,48 +51,26 @@ public: enum Type { POINT = 0, TEXTURE = 1, VECTOR = 2, NORMAL = 3 }; Type type; - static NodeEnum type_enum; enum Mapping { NONE = 0, X = 1, Y = 2, Z = 3 }; Mapping x_mapping, y_mapping, z_mapping; - static NodeEnum mapping_enum; enum Projection { FLAT, CUBE, TUBE, SPHERE }; Projection projection; - static NodeEnum projection_enum; - - bool equals(const TextureMapping& other) { - return translation == other.translation && - rotation == other.rotation && - scale == other.scale && - use_minmax == other.use_minmax && - min == other.min && - max == other.max && - type == other.type && - x_mapping == other.x_mapping && - y_mapping == other.y_mapping && - z_mapping == other.z_mapping && - projection == other.projection; - } }; /* Nodes */ class TextureNode : public ShaderNode { public: - explicit TextureNode(const char *name_) : ShaderNode(name_) {} + explicit TextureNode(const NodeType *node_type) : ShaderNode(node_type) {} TextureMapping tex_mapping; - - virtual bool equals(const ShaderNode *other) { - return ShaderNode::equals(other) && - tex_mapping.equals(((const TextureNode*)other)->tex_mapping); - } }; /* Any node which uses image manager's slot should be a subclass of this one. */ class ImageSlotTextureNode : public TextureNode { public: - explicit ImageSlotTextureNode(const char *name_) : TextureNode(name_) { + explicit ImageSlotTextureNode(const NodeType *node_type) : TextureNode(node_type) { special_type = SHADER_SPECIAL_TYPE_IMAGE_SLOT; } int slot; @@ -115,22 +95,14 @@ public: ExtensionType extension; float projection_blend; bool animated; + float3 vector; - static NodeEnum color_space_enum; - static NodeEnum projection_enum; - - virtual bool equals(const ShaderNode *other) { - const ImageTextureNode *image_node = (const ImageTextureNode*)other; + virtual bool equals(const ShaderNode& other) + { + const ImageTextureNode& image_node = (const ImageTextureNode&)other; return ImageSlotTextureNode::equals(other) && - use_alpha == image_node->use_alpha && - filename == image_node->filename && - builtin_data == image_node->builtin_data && - color_space == image_node->color_space && - projection == image_node->projection && - interpolation == image_node->interpolation && - extension == image_node->extension && - projection_blend == image_node->projection_blend && - animated == image_node->animated; + builtin_data == image_node.builtin_data && + animated == image_node.animated; } }; @@ -152,20 +124,14 @@ public: NodeEnvironmentProjection projection; InterpolationType interpolation; bool animated; + float3 vector; - static NodeEnum color_space_enum; - static NodeEnum projection_enum; - - virtual bool equals(const ShaderNode *other) { - const EnvironmentTextureNode *env_node = (const EnvironmentTextureNode*)other; + virtual bool equals(const ShaderNode& other) + { + const EnvironmentTextureNode& env_node = (const EnvironmentTextureNode&)other; return ImageSlotTextureNode::equals(other) && - use_alpha == env_node->use_alpha && - filename == env_node->filename && - builtin_data == env_node->builtin_data && - color_space == env_node->color_space && - projection == env_node->projection && - interpolation == env_node->interpolation && - animated == env_node->animated; + builtin_data == env_node.builtin_data && + animated == env_node.animated; } }; @@ -179,25 +145,20 @@ public: float3 sun_direction; float turbidity; float ground_albedo; - - static NodeEnum type_enum; - - virtual bool equals(const ShaderNode *other) { - const SkyTextureNode *sky_node = (const SkyTextureNode*)other; - return TextureNode::equals(other) && - sun_direction == sky_node->sun_direction && - turbidity == sky_node->turbidity && - ground_albedo == sky_node->ground_albedo && - type == sky_node->type; - } + float3 vector; }; class OutputNode : public ShaderNode { public: SHADER_NODE_CLASS(OutputNode) + void* surface; + void* volume; + float displacement; + float3 normal; + /* Don't allow output node de-duplication. */ - virtual bool equals(const ShaderNode * /*other*/) { return false; } + virtual bool equals(const ShaderNode& /*other*/) { return false; } }; class GradientTextureNode : public TextureNode { @@ -207,18 +168,15 @@ public: virtual int get_group() { return NODE_GROUP_LEVEL_2; } NodeGradientType type; - static NodeEnum type_enum; - - virtual bool equals(const ShaderNode *other) { - const GradientTextureNode *gradient_node = (const GradientTextureNode*)other; - return TextureNode::equals(other) && - type == gradient_node->type; - } + float3 vector; }; class NoiseTextureNode : public TextureNode { public: SHADER_NODE_CLASS(NoiseTextureNode) + + float scale, detail, distortion; + float3 vector; }; class VoronoiTextureNode : public TextureNode { @@ -228,13 +186,8 @@ public: virtual int get_group() { return NODE_GROUP_LEVEL_2; } NodeVoronoiColoring coloring; - static NodeEnum coloring_enum; - - virtual bool equals(const ShaderNode *other) { - const VoronoiTextureNode *voronoi_node = (const VoronoiTextureNode*)other; - return TextureNode::equals(other) && - coloring == voronoi_node->coloring; - } + float scale; + float3 vector; }; class MusgraveTextureNode : public TextureNode { @@ -244,13 +197,8 @@ public: virtual int get_group() { return NODE_GROUP_LEVEL_2; } NodeMusgraveType type; - static NodeEnum type_enum; - - virtual bool equals(const ShaderNode *other) { - const MusgraveTextureNode *musgrave_node = (const MusgraveTextureNode*)other; - return TextureNode::equals(other) && - type == musgrave_node->type; - } + float scale, detail, dimension, lacunarity, offset, gain; + float3 vector; }; class WaveTextureNode : public TextureNode { @@ -261,15 +209,9 @@ public: NodeWaveType type; NodeWaveProfile profile; - static NodeEnum type_enum; - static NodeEnum profile_enum; - - virtual bool equals(const ShaderNode *other) { - const WaveTextureNode *wave_node = (const WaveTextureNode*)other; - return TextureNode::equals(other) && - type == wave_node->type && - profile == wave_node->profile; - } + + float scale, distortion, detail, detail_scale; + float3 vector; }; class MagicTextureNode : public TextureNode { @@ -279,18 +221,17 @@ public: virtual int get_group() { return NODE_GROUP_LEVEL_2; } int depth; - - virtual bool equals(const ShaderNode *other) { - const MagicTextureNode *magic_node = (const MagicTextureNode*)other; - return TextureNode::equals(other) && - depth == magic_node->depth; - } + float3 vector; + float scale, distortion; }; class CheckerTextureNode : public TextureNode { public: SHADER_NODE_CLASS(CheckerTextureNode) + float3 vector, color1, color2; + float scale; + virtual int get_group() { return NODE_GROUP_LEVEL_2; } }; @@ -301,16 +242,11 @@ public: float offset, squash; int offset_frequency, squash_frequency; - virtual int get_group() { return NODE_GROUP_LEVEL_2; } + float3 color1, color2, mortar; + float scale, mortar_size, bias, brick_width, row_height; + float3 vector; - virtual bool equals(const ShaderNode *other) { - const BrickTextureNode *brick_node = (const BrickTextureNode*)other; - return TextureNode::equals(other) && - offset == brick_node->offset && - squash == brick_node->squash && - offset_frequency == brick_node->offset_frequency && - squash_frequency == brick_node->squash_frequency; - } + virtual int get_group() { return NODE_GROUP_LEVEL_2; } }; class PointDensityTextureNode : public ShaderNode { @@ -324,25 +260,20 @@ public: bool has_spatial_varying() { return true; } bool has_object_dependency() { return true; } - ImageManager *image_manager; - int slot; - string filename; + ustring filename; NodeTexVoxelSpace space; - void *builtin_data; InterpolationType interpolation; - Transform tfm; + float3 vector; - static NodeEnum space_enum; + ImageManager *image_manager; + int slot; + void *builtin_data; - virtual bool equals(const ShaderNode *other) { - const PointDensityTextureNode *point_dendity_node = (const PointDensityTextureNode*)other; + virtual bool equals(const ShaderNode& other) { + const PointDensityTextureNode& point_dendity_node = (const PointDensityTextureNode&)other; return ShaderNode::equals(other) && - filename == point_dendity_node->filename && - space == point_dendity_node->space && - builtin_data == point_dendity_node->builtin_data && - interpolation == point_dendity_node->interpolation && - tfm == point_dendity_node->tfm; + builtin_data == point_dendity_node.builtin_data; } }; @@ -351,20 +282,16 @@ public: SHADER_NODE_CLASS(MappingNode) virtual int get_group() { return NODE_GROUP_LEVEL_2; } + float3 vector; TextureMapping tex_mapping; - - virtual bool equals(const ShaderNode *other) { - const MappingNode *mapping_node = (const MappingNode*)other; - return ShaderNode::equals(other) && - tex_mapping.equals(mapping_node->tex_mapping); - } }; class RGBToBWNode : public ShaderNode { public: SHADER_NODE_CLASS(RGBToBWNode) - bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized); + + float3 color; }; class ConvertNode : public ShaderNode { @@ -376,28 +303,39 @@ public: SocketType::Type from, to; - virtual bool equals(const ShaderNode *other) - { - const ConvertNode *convert_node = (const ConvertNode*)other; - return ShaderNode::equals(other) && - from == convert_node->from && - to == convert_node->to; - } + union { + float value_float; + int value_int; + float3 value_color; + float3 value_vector; + float3 value_point; + float3 value_normal; + }; + ustring value_string; + +private: + static const int MAX_TYPE = 12; + static bool register_types(); + static Node* create(const NodeType *type); + static const NodeType *node_types[MAX_TYPE][MAX_TYPE]; + static bool initialized; }; class BsdfNode : public ShaderNode { public: - explicit BsdfNode(bool scattering = false); + explicit BsdfNode(const NodeType *node_type); SHADER_NODE_BASE_CLASS(BsdfNode); bool has_spatial_varying() { return true; } void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3 = NULL, ShaderInput *param4 = NULL); virtual ClosureType get_closure_type() { return closure; } + float3 color; + float3 normal; + float surface_mix_weight; ClosureType closure; - bool scattering; - virtual bool equals(const ShaderNode * /*other*/) + virtual bool equals(const ShaderNode& /*other*/) { /* TODO(sergey): With some care BSDF nodes can be de-duplicated. */ return false; @@ -408,8 +346,9 @@ class AnisotropicBsdfNode : public BsdfNode { public: SHADER_NODE_CLASS(AnisotropicBsdfNode) + float3 tangent; + float roughness, anisotropy, rotation; ClosureType distribution; - static NodeEnum distribution_enum; void attributes(Shader *shader, AttributeRequestSet *attributes); }; @@ -417,6 +356,8 @@ public: class DiffuseBsdfNode : public BsdfNode { public: SHADER_NODE_CLASS(DiffuseBsdfNode) + + float roughness; }; class TranslucentBsdfNode : public BsdfNode { @@ -434,6 +375,8 @@ public: class VelvetBsdfNode : public BsdfNode { public: SHADER_NODE_CLASS(VelvetBsdfNode) + + float sigma; }; class GlossyBsdfNode : public BsdfNode { @@ -443,8 +386,8 @@ public: void simplify_settings(Scene *scene); bool has_integrator_dependency(); + float roughness; ClosureType distribution, distribution_orig; - static NodeEnum distribution_enum; }; class GlassBsdfNode : public BsdfNode { @@ -454,8 +397,8 @@ public: void simplify_settings(Scene *scene); bool has_integrator_dependency(); + float roughness, IOR; ClosureType distribution, distribution_orig; - static NodeEnum distribution_enum; }; class RefractionBsdfNode : public BsdfNode { @@ -465,16 +408,16 @@ public: void simplify_settings(Scene *scene); bool has_integrator_dependency(); + float roughness, IOR; ClosureType distribution, distribution_orig; - static NodeEnum distribution_enum; }; class ToonBsdfNode : public BsdfNode { public: SHADER_NODE_CLASS(ToonBsdfNode) + float smooth, size; ClosureType component; - static NodeEnum component_enum; }; class SubsurfaceScatteringNode : public BsdfNode { @@ -483,8 +426,11 @@ public: bool has_surface_bssrdf() { return true; } bool has_bssrdf_bump(); + float scale; + float3 radius; + float sharpness; + float texture_blur; ClosureType falloff; - static NodeEnum falloff_enum; }; class EmissionNode : public ShaderNode { @@ -494,6 +440,10 @@ public: virtual ClosureType get_closure_type() { return CLOSURE_EMISSION_ID; } bool has_surface_emission() { return true; } + + float3 color; + float strength; + float surface_mix_weight; }; class BackgroundNode : public ShaderNode { @@ -501,6 +451,10 @@ public: SHADER_NODE_CLASS(BackgroundNode) bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized); virtual ClosureType get_closure_type() { return CLOSURE_BACKGROUND_ID; } + + float3 color; + float strength; + float surface_mix_weight; }; class HoldoutNode : public ShaderNode { @@ -508,6 +462,9 @@ public: SHADER_NODE_CLASS(HoldoutNode) virtual int get_group() { return NODE_GROUP_LEVEL_1; } virtual ClosureType get_closure_type() { return CLOSURE_HOLDOUT_ID; } + + float surface_mix_weight; + float volume_mix_weight; }; class AmbientOcclusionNode : public ShaderNode { @@ -517,11 +474,16 @@ public: bool has_spatial_varying() { return true; } virtual int get_group() { return NODE_GROUP_LEVEL_1; } virtual ClosureType get_closure_type() { return CLOSURE_AMBIENT_OCCLUSION_ID; } + + float3 normal_osl; + float3 color; + float surface_mix_weight; }; class VolumeNode : public ShaderNode { public: - SHADER_NODE_CLASS(VolumeNode) + VolumeNode(const NodeType *node_type); + SHADER_NODE_BASE_CLASS(VolumeNode) void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2); virtual int get_group() { return NODE_GROUP_LEVEL_1; } @@ -530,9 +492,12 @@ public: } virtual ClosureType get_closure_type() { return closure; } + float3 color; + float density; + float volume_mix_weight; ClosureType closure; - virtual bool equals(const ShaderNode * /*other*/) + virtual bool equals(const ShaderNode& /*other*/) { /* TODO(sergey): With some care Volume nodes can be de-duplicated. */ return false; @@ -547,6 +512,8 @@ public: class ScatterVolumeNode : public VolumeNode { public: SHADER_NODE_CLASS(ScatterVolumeNode) + + float anisotropy; }; class HairBsdfNode : public BsdfNode { @@ -554,8 +521,10 @@ public: SHADER_NODE_CLASS(HairBsdfNode) ClosureType component; - static NodeEnum component_enum; - + float offset; + float roughness_u; + float roughness_v; + float3 tangent; }; class GeometryNode : public ShaderNode { @@ -563,6 +532,8 @@ public: SHADER_NODE_CLASS(GeometryNode) void attributes(Shader *shader, AttributeRequestSet *attributes); bool has_spatial_varying() { return true; } + + float3 normal_osl; }; class TextureCoordinateNode : public ShaderNode { @@ -572,17 +543,10 @@ public: bool has_spatial_varying() { return true; } bool has_object_dependency() { return use_transform; } + float3 normal_osl; bool from_dupli; bool use_transform; Transform ob_tfm; - - virtual bool equals(const ShaderNode *other) { - const TextureCoordinateNode *texco_node = (const TextureCoordinateNode*)other; - return ShaderNode::equals(other) && - from_dupli == texco_node->from_dupli && - use_transform == texco_node->use_transform && - ob_tfm == texco_node->ob_tfm; - } }; class UVMapNode : public ShaderNode { @@ -594,13 +558,6 @@ public: ustring attribute; bool from_dupli; - - virtual bool equals(const ShaderNode *other) { - const UVMapNode *uv_map_node = (const UVMapNode*)other; - return ShaderNode::equals(other) && - attribute == uv_map_node->attribute && - from_dupli == uv_map_node->from_dupli; - } }; class LightPathNode : public ShaderNode { @@ -614,6 +571,9 @@ public: SHADER_NODE_CLASS(LightFalloffNode) bool has_spatial_varying() { return true; } virtual int get_group() { return NODE_GROUP_LEVEL_2; } + + float strength; + float smooth; }; class ObjectInfoNode : public ShaderNode { @@ -648,12 +608,6 @@ public: bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized); float value; - - virtual bool equals(const ShaderNode *other) { - const ValueNode *value_node = (const ValueNode*)other; - return ShaderNode::equals(other) && - value == value_node->value; - } }; class ColorNode : public ShaderNode { @@ -663,12 +617,6 @@ public: bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized); float3 value; - - virtual bool equals(const ShaderNode *other) { - const ColorNode *color_node = (const ColorNode*)other; - return ShaderNode::equals(other) && - value == color_node->value; - } }; class AddClosureNode : public ShaderNode { @@ -680,11 +628,16 @@ class MixClosureNode : public ShaderNode { public: SHADER_NODE_CLASS(MixClosureNode) bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized); + + float fac; }; class MixClosureWeightNode : public ShaderNode { public: SHADER_NODE_CLASS(MixClosureWeightNode); + + float weight; + float fac; }; class InvertNode : public ShaderNode { @@ -692,6 +645,9 @@ public: SHADER_NODE_CLASS(InvertNode) virtual int get_group() { return NODE_GROUP_LEVEL_3; } + + float fac; + float3 color; }; class MixNode : public ShaderNode { @@ -701,80 +657,90 @@ public: virtual int get_group() { return NODE_GROUP_LEVEL_3; } - bool use_clamp; - NodeMix type; - static NodeEnum type_enum; - - virtual bool equals(const ShaderNode *other) - { - const MixNode *mix_node = (const MixNode*)other; - return ShaderNode::equals(other) && - use_clamp == mix_node->use_clamp && - type == mix_node->type; - } + bool use_clamp; + float3 color1; + float3 color2; + float fac; }; class CombineRGBNode : public ShaderNode { public: SHADER_NODE_CLASS(CombineRGBNode) - virtual int get_group() { return NODE_GROUP_LEVEL_3; } + + float r, g, b; }; class CombineHSVNode : public ShaderNode { public: SHADER_NODE_CLASS(CombineHSVNode) - virtual int get_group() { return NODE_GROUP_LEVEL_3; } + + float h, s, v; }; class CombineXYZNode : public ShaderNode { public: SHADER_NODE_CLASS(CombineXYZNode) - virtual int get_group() { return NODE_GROUP_LEVEL_3; } + + float x, y, z; }; class GammaNode : public ShaderNode { public: SHADER_NODE_CLASS(GammaNode) - bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized); - virtual int get_group() { return NODE_GROUP_LEVEL_1; } + + float3 color; + float gamma; }; class BrightContrastNode : public ShaderNode { public: SHADER_NODE_CLASS(BrightContrastNode) virtual int get_group() { return NODE_GROUP_LEVEL_1; } + + float3 color; + float bright; + float contrast; }; class SeparateRGBNode : public ShaderNode { public: SHADER_NODE_CLASS(SeparateRGBNode) - virtual int get_group() { return NODE_GROUP_LEVEL_3; } + + float3 color; }; class SeparateHSVNode : public ShaderNode { public: SHADER_NODE_CLASS(SeparateHSVNode) - virtual int get_group() { return NODE_GROUP_LEVEL_3; } + + float3 color; }; class SeparateXYZNode : public ShaderNode { public: SHADER_NODE_CLASS(SeparateXYZNode) - virtual int get_group() { return NODE_GROUP_LEVEL_3; } + + float3 vector; }; class HSVNode : public ShaderNode { public: SHADER_NODE_CLASS(HSVNode) + + float hue; + float saturation; + float value; + float fac; + float3 color; }; class AttributeNode : public ShaderNode { @@ -784,12 +750,6 @@ public: bool has_spatial_varying() { return true; } ustring attribute; - - virtual bool equals(const ShaderNode *other) { - const AttributeNode *color_node = (const AttributeNode*)other; - return ShaderNode::equals(other) && - attribute == color_node->attribute; - } }; class CameraNode : public ShaderNode { @@ -803,6 +763,9 @@ public: SHADER_NODE_CLASS(FresnelNode) bool has_spatial_varying() { return true; } virtual int get_group() { return NODE_GROUP_LEVEL_1; } + + float3 normal; + float IOR; }; class LayerWeightNode : public ShaderNode { @@ -810,6 +773,9 @@ public: SHADER_NODE_CLASS(LayerWeightNode) bool has_spatial_varying() { return true; } virtual int get_group() { return NODE_GROUP_LEVEL_1; } + + float3 normal; + float blend; }; class WireframeNode : public ShaderNode { @@ -818,22 +784,25 @@ public: bool has_spatial_varying() { return true; } virtual int get_group() { return NODE_GROUP_LEVEL_3; } + float size; bool use_pixel_size; }; class WavelengthNode : public ShaderNode { public: SHADER_NODE_CLASS(WavelengthNode) - virtual int get_group() { return NODE_GROUP_LEVEL_3; } + + float wavelength; }; class BlackbodyNode : public ShaderNode { public: SHADER_NODE_CLASS(BlackbodyNode) bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized); - virtual int get_group() { return NODE_GROUP_LEVEL_3; } + + float temperature; }; class MathNode : public ShaderNode { @@ -842,18 +811,10 @@ public: virtual int get_group() { return NODE_GROUP_LEVEL_1; } bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized); - bool use_clamp; - + float value1; + float value2; NodeMath type; - static NodeEnum type_enum; - - virtual bool equals(const ShaderNode *other) - { - const MathNode *math_node = (const MathNode*)other; - return ShaderNode::equals(other) && - use_clamp == math_node->use_clamp && - type == math_node->type; - } + bool use_clamp; }; class NormalNode : public ShaderNode { @@ -862,13 +823,7 @@ public: virtual int get_group() { return NODE_GROUP_LEVEL_2; } float3 direction; - - virtual bool equals(const ShaderNode *other) - { - const NormalNode *normal_node = (const NormalNode*)other; - return ShaderNode::equals(other) && - direction == normal_node->direction; - } + float3 normal; }; class VectorMathNode : public ShaderNode { @@ -877,15 +832,9 @@ public: virtual int get_group() { return NODE_GROUP_LEVEL_1; } bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized); + float3 vector1; + float3 vector2; NodeVectorMath type; - static NodeEnum type_enum; - - virtual bool equals(const ShaderNode *other) - { - const VectorMathNode *math_node = (const VectorMathNode*)other; - return ShaderNode::equals(other) && - type == math_node->type; - } }; class VectorTransformNode : public ShaderNode { @@ -897,17 +846,7 @@ public: NodeVectorTransformType type; NodeVectorTransformConvertSpace convert_from; NodeVectorTransformConvertSpace convert_to; - - static NodeEnum type_enum; - static NodeEnum convert_space_enum; - - virtual bool equals(const ShaderNode *other) { - const VectorTransformNode *vector_transform_node = (const VectorTransformNode*)other; - return ShaderNode::equals(other) && - type == vector_transform_node->type && - convert_from == vector_transform_node->convert_from && - convert_to == vector_transform_node->convert_to; - } + float3 vector; }; class BumpNode : public ShaderNode { @@ -920,12 +859,13 @@ public: } bool invert; - - virtual bool equals(const ShaderNode *other) { - const BumpNode *bump_node = (const BumpNode*)other; - return ShaderNode::equals(other) && - invert == bump_node->invert; - } + float height; + float sample_center; + float sample_x; + float sample_y; + float3 normal; + float strength; + float distance; }; class RGBCurvesNode : public ShaderNode { @@ -933,10 +873,10 @@ public: SHADER_NODE_CLASS(RGBCurvesNode) virtual int get_group() { return NODE_GROUP_LEVEL_3; } - virtual bool equals(const ShaderNode * /*other*/) { return false; } array curves; - float min_x, max_x; + float min_x, max_x, fac; + float3 color; }; class VectorCurvesNode : public ShaderNode { @@ -944,25 +884,27 @@ public: SHADER_NODE_CLASS(VectorCurvesNode) virtual int get_group() { return NODE_GROUP_LEVEL_3; } - virtual bool equals(const ShaderNode * /*other*/) { return false; } array curves; - float min_x, max_x; + float min_x, max_x, fac; + float3 vector; }; class RGBRampNode : public ShaderNode { public: SHADER_NODE_CLASS(RGBRampNode) + virtual int get_group() { return NODE_GROUP_LEVEL_1; } + array ramp; array ramp_alpha; + float fac; bool interpolate; - virtual int get_group() { return NODE_GROUP_LEVEL_1; } - virtual bool equals(const ShaderNode * /*other*/) { return false; } }; class SetNormalNode : public ShaderNode { public: SHADER_NODE_CLASS(SetNormalNode) + float3 direction; }; class OSLNode : public ShaderNode { @@ -970,11 +912,15 @@ public: static OSLNode *create(size_t num_inputs); ~OSLNode(); + char* input_default_value(); + void add_input(ustring name, SocketType::Type type); + void add_output(ustring name, SocketType::Type type); + SHADER_NODE_BASE_CLASS(OSLNode) /* ideally we could beter detect this, but we can't query this now */ bool has_spatial_varying() { return true; } - virtual bool equals(const ShaderNode * /*other*/) { return false; } + virtual bool equals(const ShaderNode& /*other*/) { return false; } string filepath; string bytecode_hash; @@ -991,17 +937,10 @@ public: virtual int get_group() { return NODE_GROUP_LEVEL_3; } NodeNormalMapSpace space; - static NodeEnum space_enum; - ustring attribute; - - virtual bool equals(const ShaderNode *other) - { - const NormalMapNode *normal_map_node = (const NormalMapNode*)other; - return ShaderNode::equals(other) && - space == normal_map_node->space && - attribute == normal_map_node->attribute; - } + float strength; + float3 color; + float3 normal_osl; }; class TangentNode : public ShaderNode { @@ -1013,19 +952,8 @@ public: NodeTangentDirectionType direction_type; NodeTangentAxis axis; - static NodeEnum direction_type_enum; - static NodeEnum axis_enum; - ustring attribute; - - virtual bool equals(const ShaderNode *other) - { - const TangentNode *tangent_node = (const TangentNode*)other; - return ShaderNode::equals(other) && - direction_type == tangent_node->direction_type && - axis == tangent_node->axis && - attribute == tangent_node->attribute; - } + float3 normal_osl; }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index 1cfe3fb38e2..cf94df5f98f 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -477,8 +477,10 @@ OSLNode *OSLShaderManager::osl_node(const std::string& filepath, continue; if(!param->isoutput && param->validdefault) { - node->add_input(param->name.c_str(), socket_type, make_float3(param->fdefault[0], param->fdefault[1], param->fdefault[2])); - continue; + float3 *default_value = (float3*)node->input_default_value(); + default_value->x = param->fdefault[0]; + default_value->y = param->fdefault[1]; + default_value->z = param->fdefault[2]; } } else if(param->type.aggregate == TypeDesc::SCALAR) { @@ -486,24 +488,21 @@ OSLNode *OSLShaderManager::osl_node(const std::string& filepath, socket_type = SocketType::INT; if(!param->isoutput && param->validdefault) { - node->add_input(param->name.c_str(), socket_type, (float)param->idefault[0]); - continue; + *(int*)node->input_default_value() = param->idefault[0]; } } else if(param->type.basetype == TypeDesc::FLOAT) { socket_type = SocketType::FLOAT; if(!param->isoutput && param->validdefault) { - node->add_input(param->name.c_str(), socket_type, param->fdefault[0]); - continue; + *(float*)node->input_default_value() = param->fdefault[0]; } } else if(param->type.basetype == TypeDesc::STRING) { socket_type = SocketType::STRING; if(!param->isoutput && param->validdefault) { - node->add_input(param->name.c_str(), socket_type); - continue; + *(ustring*)node->input_default_value() = param->sdefault[0]; } } else @@ -513,10 +512,10 @@ OSLNode *OSLShaderManager::osl_node(const std::string& filepath, continue; if(param->isoutput) { - node->add_output(param->name.c_str(), socket_type); + node->add_output(param->name, socket_type); } else { - node->add_input(param->name.c_str(), socket_type); + node->add_input(param->name, socket_type); } } @@ -528,6 +527,9 @@ OSLNode *OSLShaderManager::osl_node(const std::string& filepath, node->filepath = filepath; } + /* Generate inputs and outputs */ + node->create_inputs_outputs(node->type); + return node; } @@ -643,27 +645,28 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath) continue; string param_name = compatible_name(node, input); + const SocketType& socket = input->socket_type; switch(input->type()) { case SocketType::COLOR: - parameter_color(param_name.c_str(), input->value()); + parameter_color(param_name.c_str(), node->get_float3(socket)); break; case SocketType::POINT: - parameter_point(param_name.c_str(), input->value()); + parameter_point(param_name.c_str(), node->get_float3(socket)); break; case SocketType::VECTOR: - parameter_vector(param_name.c_str(), input->value()); + parameter_vector(param_name.c_str(), node->get_float3(socket)); break; case SocketType::NORMAL: - parameter_normal(param_name.c_str(), input->value()); + parameter_normal(param_name.c_str(), node->get_float3(socket)); break; case SocketType::FLOAT: - parameter(param_name.c_str(), input->value_float()); + parameter(param_name.c_str(), node->get_float(socket)); break; case SocketType::INT: - parameter(param_name.c_str(), (int)input->value_float()); + parameter(param_name.c_str(), node->get_int(socket)); break; case SocketType::STRING: - parameter(param_name.c_str(), input->value_string()); + parameter(param_name.c_str(), node->get_string(socket)); break; case SocketType::CLOSURE: case SocketType::UNDEFINED: @@ -733,6 +736,168 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath) } } +static TypeDesc array_typedesc(TypeDesc typedesc, int arraylength) +{ + return TypeDesc((TypeDesc::BASETYPE)typedesc.basetype, + (TypeDesc::AGGREGATE)typedesc.aggregate, + (TypeDesc::VECSEMANTICS)typedesc.vecsemantics, + arraylength); +} + +void OSLCompiler::parameter(ShaderNode* node, const char *name) +{ + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; + ustring uname = ustring(name); + const SocketType& socket = *(node->type->find_input(uname)); + + switch(socket.type) + { + case SocketType::BOOLEAN: + { + int value = node->get_bool(socket); + ss->Parameter(name, TypeDesc::TypeInt, &value); + break; + } + case SocketType::FLOAT: + { + float value = node->get_float(socket); + ss->Parameter(uname, TypeDesc::TypeFloat, &value); + break; + } + case SocketType::INT: + { + int value = node->get_int(socket); + ss->Parameter(uname, TypeDesc::TypeInt, &value); + break; + } + case SocketType::COLOR: + { + float3 value = node->get_float3(socket); + ss->Parameter(uname, TypeDesc::TypeColor, &value); + break; + } + case SocketType::VECTOR: + { + float3 value = node->get_float3(socket); + ss->Parameter(uname, TypeDesc::TypeVector, &value); + break; + } + case SocketType::POINT: + { + float3 value = node->get_float3(socket); + ss->Parameter(uname, TypeDesc::TypePoint, &value); + break; + } + case SocketType::NORMAL: + { + float3 value = node->get_float3(socket); + ss->Parameter(uname, TypeDesc::TypeNormal, &value); + break; + } + case SocketType::POINT2: + { + float2 value = node->get_float2(socket); + ss->Parameter(uname, TypeDesc(TypeDesc::FLOAT, TypeDesc::VEC2, TypeDesc::POINT), &value); + break; + } + case SocketType::STRING: + { + ustring value = node->get_string(socket); + ss->Parameter(uname, TypeDesc::TypeString, &value); + break; + } + case SocketType::ENUM: + { + ustring value = node->get_string(socket); + ss->Parameter(uname, TypeDesc::TypeString, &value); + break; + } + case SocketType::TRANSFORM: + { + Transform value = node->get_transform(socket); + ss->Parameter(uname, TypeDesc::TypeMatrix, &value); + break; + } + case SocketType::BOOLEAN_ARRAY: + { + // OSL does not support booleans, so convert to int + const array& value = node->get_bool_array(socket); + array intvalue(value.size()); + for (size_t i = 0; i < value.size(); i++) + intvalue[i] = value[i]; + ss->Parameter(uname, array_typedesc(TypeDesc::TypeInt, value.size()), intvalue.data()); + break; + } + case SocketType::FLOAT_ARRAY: + { + const array& value = node->get_float_array(socket); + ss->Parameter(uname, array_typedesc(TypeDesc::TypeFloat, value.size()), value.data()); + break; + } + case SocketType::INT_ARRAY: + { + const array& value = node->get_int_array(socket); + ss->Parameter(uname, array_typedesc(TypeDesc::TypeInt, value.size()), value.data()); + break; + } + case SocketType::COLOR_ARRAY: + case SocketType::VECTOR_ARRAY: + case SocketType::POINT_ARRAY: + case SocketType::NORMAL_ARRAY: + { + TypeDesc typedesc; + + switch(socket.type) + { + case SocketType::COLOR_ARRAY: typedesc = TypeDesc::TypeColor; break; + case SocketType::VECTOR_ARRAY: typedesc = TypeDesc::TypeVector; break; + case SocketType::POINT_ARRAY: typedesc = TypeDesc::TypePoint; break; + case SocketType::NORMAL_ARRAY: typedesc = TypeDesc::TypeNormal; break; + default: assert(0); break; + } + + // convert to tightly packed array since float3 has padding + const array& value = node->get_float3_array(socket); + array fvalue(value.size() * 3); + for (size_t i = 0, j = 0; i < value.size(); i++) + { + fvalue[j++] = value[i].x; + fvalue[j++] = value[i].y; + fvalue[j++] = value[i].z; + } + + ss->Parameter(uname, array_typedesc(typedesc, value.size()), fvalue.data()); + break; + } + case SocketType::POINT2_ARRAY: + { + const array& value = node->get_float2_array(socket); + ss->Parameter(uname, array_typedesc(TypeDesc(TypeDesc::FLOAT, TypeDesc::VEC2, TypeDesc::POINT), value.size()), value.data()); + break; + } + case SocketType::STRING_ARRAY: + { + const array& value = node->get_string_array(socket); + ss->Parameter(uname, array_typedesc(TypeDesc::TypeString, value.size()), value.data()); + break; + } + case SocketType::TRANSFORM_ARRAY: + { + const array& value = node->get_transform_array(socket); + ss->Parameter(uname, array_typedesc(TypeDesc::TypeMatrix, value.size()), value.data()); + break; + } + case SocketType::CLOSURE: + case SocketType::NODE: + case SocketType::NODE_ARRAY: + case SocketType::UNDEFINED: + { + assert(0); + break; + } + } +} + void OSLCompiler::parameter(const char *name, float f) { OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; @@ -996,6 +1161,10 @@ void OSLCompiler::add(ShaderNode * /*node*/, const char * /*name*/, bool /*isfil { } +void OSLCompiler::parameter(ShaderNode * /*node*/, const char * /*name*/) +{ +} + void OSLCompiler::parameter(const char * /*name*/, float /*f*/) { } diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h index 13b9d6307f9..b131b672b8c 100644 --- a/intern/cycles/render/osl.h +++ b/intern/cycles/render/osl.h @@ -125,6 +125,8 @@ public: void add(ShaderNode *node, const char *name, bool isfilepath = false); + void parameter(ShaderNode *node, const char *name); + void parameter(const char *name, float f); void parameter_color(const char *name, float3 f); void parameter_vector(const char *name, float3 f); diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index 708eeef3b50..4cdb878df45 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -449,17 +449,15 @@ void ShaderManager::device_free_common(Device *device, DeviceScene *dscene, Scen void ShaderManager::add_default(Scene *scene) { - ShaderNode *closure, *out; - /* default surface */ { ShaderGraph *graph = new ShaderGraph(); - closure = graph->add(new DiffuseBsdfNode()); - closure->input("Color")->set(make_float3(0.8f, 0.8f, 0.8f)); - out = graph->output(); + DiffuseBsdfNode *diffuse = new DiffuseBsdfNode(); + diffuse->color = make_float3(0.8f, 0.8f, 0.8f); + graph->add(diffuse); - graph->connect(closure->output("BSDF"), out->input("Surface")); + graph->connect(diffuse->output("BSDF"), graph->output()->input("Surface")); Shader *shader = new Shader(); shader->name = "default_surface"; @@ -472,12 +470,12 @@ void ShaderManager::add_default(Scene *scene) { ShaderGraph *graph = new ShaderGraph(); - closure = graph->add(new EmissionNode()); - closure->input("Color")->set(make_float3(0.8f, 0.8f, 0.8f)); - closure->input("Strength")->set(0.0f); - out = graph->output(); + EmissionNode *emission = new EmissionNode(); + emission->color = make_float3(0.8f, 0.8f, 0.8f); + emission->strength = 0.0f; + graph->add(emission); - graph->connect(closure->output("Emission"), out->input("Surface")); + graph->connect(emission->output("Emission"), graph->output()->input("Surface")); Shader *shader = new Shader(); shader->name = "default_light"; diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index d54afd1ba6f..f0e7ee2bd49 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -192,14 +192,16 @@ int SVMCompiler::stack_assign(ShaderInput *input) input->stack_offset = input->link->stack_offset; } else { + Node *node = input->parent; + /* not linked to output -> add nodes to load default value */ input->stack_offset = stack_find_offset(input->type()); if(input->type() == SocketType::FLOAT) { - add_node(NODE_VALUE_F, __float_as_int(input->value_float()), input->stack_offset); + add_node(NODE_VALUE_F, __float_as_int(node->get_float(input->socket_type)), input->stack_offset); } else if(input->type() == SocketType::INT) { - add_node(NODE_VALUE_F, (int)input->value_float(), input->stack_offset); + add_node(NODE_VALUE_F, node->get_int(input->socket_type), input->stack_offset); } else if(input->type() == SocketType::VECTOR || input->type() == SocketType::NORMAL || @@ -208,7 +210,7 @@ int SVMCompiler::stack_assign(ShaderInput *input) { add_node(NODE_VALUE_V, input->stack_offset); - add_node(NODE_VALUE_V, input->value()); + add_node(NODE_VALUE_V, node->get_float3(input->socket_type)); } else /* should not get called for closure */ assert(0); @@ -446,7 +448,7 @@ void SVMCompiler::generate_closure_node(ShaderNode *node, const char *weight_name = (current_type == SHADER_TYPE_VOLUME)? "VolumeMixWeight": "SurfaceMixWeight"; ShaderInput *weight_in = node->input(weight_name); - if(weight_in && (weight_in->link || weight_in->value_float() != 1.0f)) + if(weight_in && (weight_in->link || node->get_float(weight_in->socket_type) != 1.0f)) mix_weight_offset = stack_assign(weight_in); else mix_weight_offset = SVM_STACK_INVALID; -- cgit v1.2.3