Cycles: nodify shader nodes

Differential Revision: https://developer.blender.org/D2038
This commit is contained in:
Brecht Van Lommel 2016-05-07 19:48:28 +02:00
parent 4df6474f01
commit 42aec3b355
Notes: blender-bot 2023-02-14 08:45:09 +01:00
Referenced by issue #48790, Wrong render with HDRi when there Sun lamp with strength=0
Referenced by issue #48645, Regression: crash in cycles after recent commit
10 changed files with 2185 additions and 1997 deletions

View File

@ -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<string, ShaderNode*> 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()) {
ustring node_name(node.name());
if(node_name == "connect") {
/* connect nodes */
vector<string> from_tokens, to_tokens;
string_split(from_tokens, node.attribute("from").value());
string_split(to_tokens, node.attribute("to").value());
if(from_tokens.size() == 2 && to_tokens.size() == 2) {
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]);
/* find nodes and sockets */
ShaderOutput *output = NULL;
ShaderInput *input = NULL;
if(graph_reader.node_map.find(from_node_name) != graph_reader.node_map.end()) {
ShaderNode *fromnode = (ShaderNode*)graph_reader.node_map[from_node_name];
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");
continue;
}
ShaderNode *snode = NULL;
/* ToDo: Add missing nodes
* RGBCurvesNode, VectorCurvesNode, RGBRampNode and ConvertNode (RGB -> BW).
*/
if(string_iequals(node.name(), "image_texture")) {
ImageTextureNode *img = new ImageTextureNode();
xml_read_string(&img->filename, node, "src");
img->filename = path_join(state.base, img->filename);
xml_read_enum_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");
/* ToDo: Interpolation */
snode = img;
}
else if(string_iequals(node.name(), "environment_texture")) {
EnvironmentTextureNode *env = new EnvironmentTextureNode();
xml_read_string(&env->filename, node, "src");
env->filename = path_join(state.base, env->filename);
xml_read_enum_value((int*)&env->color_space, EnvironmentTextureNode::color_space_enum, node, "color_space");
xml_read_enum_value((int*)&env->projection, EnvironmentTextureNode::projection_enum, node, "projection");
snode = env;
}
#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;
}
}
#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();
xml_read_float(&brick->offset, node, "offset");
xml_read_int(&brick->offset_frequency, node, "offset_frequency");
xml_read_float(&brick->squash, node, "squash");
xml_read_int(&brick->squash_frequency, node, "squash_frequency");
snode = brick;
}
else if(string_iequals(node.name(), "gradient_texture")) {
GradientTextureNode *blend = new GradientTextureNode();
xml_read_enum_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");
}
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();
}
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<string> from_tokens, to_tokens;
string_split(from_tokens, node.attribute("from").value());
string_split(to_tokens, node.attribute("to").value());
if(from_tokens.size() == 2 && to_tokens.size() == 2) {
/* find nodes and sockets */
ShaderOutput *output = NULL;
ShaderInput *input = NULL;
if(nodemap.find(from_tokens[0]) != nodemap.end()) {
ShaderNode *fromnode = nodemap[from_tokens[0]];
foreach(ShaderOutput *out, fromnode->outputs)
if(string_iequals(xml_socket_name(out->name().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;
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");
}
else
fprintf(stderr, "Unknown shader node \"%s\".\n", node.name());
#endif
{
/* exception for name collision */
if(node_name == "background")
node_name = "background_shader";
const NodeType *node_type = NodeType::find(node_name);
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;
}
snode = (ShaderNode*) node_type->create(node_type);
}
xml_read_node(graph_reader, snode, node);
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);
}
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;
}
}
}
}
}
}

View File

@ -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;
DiffuseBsdfNode *diffuse = new DiffuseBsdfNode();
diffuse->color = get_float3(b_mat->diffuse_color());
graph->add(diffuse);
closure = graph->add(new DiffuseBsdfNode());
closure->input("Color")->set(get_float3(b_mat->diffuse_color()));
out = graph->output();
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;
BackgroundNode *background = new BackgroundNode();
background->color = get_float3(b_world.horizon_color());
graph->add(background);
closure = graph->add(new BackgroundNode());
closure->input("Color")->set(get_float3(b_world.horizon_color()));
out = graph->output();
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);

View File

@ -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<ShaderInput*> 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);
}
}

View File

@ -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);
ShaderOutput(const SocketType& socket_type_, ShaderNode* parent_)
: socket_type(socket_type_), parent(parent_), stack_offset(SVM_STACK_INVALID)
{}
ustring name() { return name_; }
SocketType::Type type() { return type_; }
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<ShaderInput*> 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<ShaderInput*> inputs;
vector<ShaderOutput*> 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); \

File diff suppressed because it is too large Load Diff

View File

@ -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; }
ustring filename;
NodeTexVoxelSpace space;
InterpolationType interpolation;
Transform tfm;
float3 vector;
ImageManager *image_manager;
int slot;
string filename;
NodeTexVoxelSpace space;
void *builtin_data;
InterpolationType interpolation;
Transform tfm;
static NodeEnum space_enum;
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<float3> 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<float3> 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<float3> ramp;
array<float> 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

View File

@ -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<bool>& value = node->get_bool_array(socket);
array<int> 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<float>& value = node->get_float_array(socket);
ss->Parameter(uname, array_typedesc(TypeDesc::TypeFloat, value.size()), value.data());
break;
}
case SocketType::INT_ARRAY:
{
const array<int>& 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<float3>& value = node->get_float3_array(socket);
array<float> 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<float2>& 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<ustring>& value = node->get_string_array(socket);
ss->Parameter(uname, array_typedesc(TypeDesc::TypeString, value.size()), value.data());
break;
}
case SocketType::TRANSFORM_ARRAY:
{
const array<Transform>& 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*/)
{
}

View File

@ -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);

View File

@ -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";

View File

@ -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;