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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2012-11-27 01:59:41 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2012-11-27 01:59:41 +0400
commitceed3ef640bb40e1232feeb409220fe19011bc43 (patch)
tree48ad960f483ad185718b14bbc605b6182732f56c /intern/cycles/render/graph.cpp
parenteab58bf994323a53311543d7d706b0be87ffe197 (diff)
Fix #32907: failure rendering a complex node setup, hitting fixed max number
of closures limit. Optimized the code now so it can handle more. Change SVM mix/add closure handling, now we transform the node graph so that the mix weights are fed into the closure nodes directly.
Diffstat (limited to 'intern/cycles/render/graph.cpp')
-rw-r--r--intern/cycles/render/graph.cpp104
1 files changed, 97 insertions, 7 deletions
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index f71675dbda3..14b219383d0 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -37,7 +37,7 @@ ShaderInput::ShaderInput(ShaderNode *parent_, const char *name_, ShaderSocketTyp
value = make_float3(0, 0, 0);
stack_offset = SVM_STACK_INVALID;
default_value = NONE;
- osl_only = false;
+ usage = USE_ALL;
}
ShaderOutput::ShaderOutput(ShaderNode *parent_, const char *name_, ShaderSocketType type_)
@@ -85,27 +85,29 @@ ShaderOutput *ShaderNode::output(const char *name)
return NULL;
}
-ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float value)
+ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float value, int usage)
{
ShaderInput *input = new ShaderInput(this, name, type);
input->value.x = value;
+ input->usage = usage;
inputs.push_back(input);
return input;
}
-ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float3 value)
+ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float3 value, int usage)
{
ShaderInput *input = new ShaderInput(this, name, type);
input->value = value;
+ input->usage = usage;
inputs.push_back(input);
return input;
}
-ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, ShaderInput::DefaultValue value, bool osl_only)
+ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, ShaderInput::DefaultValue value, int usage)
{
ShaderInput *input = add_input(name, type);
input->default_value = value;
- input->osl_only = osl_only;
+ input->usage = usage;
return input;
}
@@ -219,7 +221,7 @@ void ShaderGraph::disconnect(ShaderInput *to)
from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end());
}
-void ShaderGraph::finalize(bool do_bump, bool do_osl)
+void ShaderGraph::finalize(bool do_bump, bool do_osl, bool do_multi_transform)
{
/* before compiling, the shader graph may undergo a number of modifications.
* currently we set default geometry shader inputs, and create automatic bump
@@ -234,6 +236,18 @@ void ShaderGraph::finalize(bool do_bump, bool do_osl)
if(do_bump)
bump_from_displacement();
+ if(do_multi_transform) {
+ ShaderInput *surface_in = output()->input("Surface");
+ ShaderInput *volume_in = output()->input("Volume");
+
+ /* todo: make this work when surface and volume closures are tangled up */
+
+ if(surface_in->link)
+ transform_multi_closure(surface_in->link->parent, NULL, false);
+ if(volume_in->link)
+ transform_multi_closure(volume_in->link->parent, NULL, true);
+ }
+
finalized = true;
}
}
@@ -440,7 +454,7 @@ void ShaderGraph::default_inputs(bool do_osl)
foreach(ShaderNode *node, nodes) {
foreach(ShaderInput *input, node->inputs) {
- if(!input->link && !(input->osl_only && !do_osl)) {
+ if(!input->link && ((input->usage & ShaderInput::USE_SVM) || do_osl)) {
if(input->default_value == ShaderInput::TEXTURE_GENERATED) {
if(!texco)
texco = new TextureCoordinateNode();
@@ -629,5 +643,81 @@ void ShaderGraph::bump_from_displacement()
add(pair.second);
}
+void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume)
+{
+ /* for SVM in multi closure mode, this transforms the shader mix/add part of
+ * the graph into nodes that feed weights into closure nodes. this is too
+ * avoid building a closure tree and then flattening it, and instead write it
+ * directly to an array */
+
+ if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) {
+ ShaderInput *fin = node->input("Fac");
+ ShaderInput *cl1in = node->input("Closure1");
+ ShaderInput *cl2in = node->input("Closure2");
+ ShaderOutput *weight1_out, *weight2_out;
+
+ if(fin) {
+ /* mix closure: add node to mix closure weights */
+ ShaderNode *mix_node = add(new MixClosureWeightNode());
+ 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->value = fin->value;
+
+ if(weight_out)
+ connect(weight_out, weight_in);
+
+ weight1_out = mix_node->output("Weight1");
+ weight2_out = mix_node->output("Weight2");
+ }
+ else {
+ /* add closure: just pass on any weights */
+ weight1_out = weight_out;
+ weight2_out = weight_out;
+ }
+
+ if(cl1in->link)
+ transform_multi_closure(cl1in->link->parent, weight1_out, volume);
+ if(cl2in->link)
+ transform_multi_closure(cl2in->link->parent, weight2_out, volume);
+ }
+ else {
+ ShaderInput *weight_in = node->input((volume)? "VolumeMixWeight": "SurfaceMixWeight");
+
+ /* not a closure node? */
+ if(!weight_in)
+ return;
+
+ /* already has a weight connected to it? add weights */
+ if(weight_in->link || weight_in->value.x != 0.0f) {
+ ShaderNode *math_node = add(new MathNode());
+ ShaderInput *value1_in = math_node->input("Value1");
+ ShaderInput *value2_in = math_node->input("Value2");
+
+ if(weight_in->link)
+ connect(weight_in->link, value1_in);
+ else
+ value1_in->value = weight_in->value;
+
+ if(weight_out)
+ connect(weight_out, value2_in);
+ else
+ value2_in->value.x = 1.0f;
+
+ weight_out = math_node->output("Value");
+ disconnect(weight_in);
+ }
+
+ /* connected to closure mix weight */
+ if(weight_out)
+ connect(weight_out, weight_in);
+ else
+ weight_in->value.x += 1.0f;
+ }
+}
+
CCL_NAMESPACE_END