add BLI_strcpy_rlen, replace strcat, which was used in misleading way.
[blender.git] / intern / cycles / render / graph.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 #include "attribute.h"
20 #include "graph.h"
21 #include "nodes.h"
22
23 #include "util_algorithm.h"
24 #include "util_debug.h"
25 #include "util_foreach.h"
26
27 CCL_NAMESPACE_BEGIN
28
29 /* Input and Output */
30
31 ShaderInput::ShaderInput(ShaderNode *parent_, const char *name_, ShaderSocketType type_)
32 {
33         parent = parent_;
34         name = name_;
35         type = type_;
36         link = NULL;
37         value = make_float3(0, 0, 0);
38         stack_offset = SVM_STACK_INVALID;
39         default_value = NONE;
40         usage = USE_ALL;
41 }
42
43 ShaderOutput::ShaderOutput(ShaderNode *parent_, const char *name_, ShaderSocketType type_)
44 {
45         parent = parent_;
46         name = name_;
47         type = type_;
48         stack_offset = SVM_STACK_INVALID;
49 }
50
51 /* Node */
52
53 ShaderNode::ShaderNode(const char *name_)
54 {
55         name = name_;
56         id = -1;
57         bump = SHADER_BUMP_NONE;
58         special_type = SHADER_SPECIAL_TYPE_NONE;
59 }
60
61 ShaderNode::~ShaderNode()
62 {
63         foreach(ShaderInput *socket, inputs)
64                 delete socket;
65
66         foreach(ShaderOutput *socket, outputs)
67                 delete socket;
68 }
69
70 ShaderInput *ShaderNode::input(const char *name)
71 {
72         foreach(ShaderInput *socket, inputs)
73                 if(strcmp(socket->name, name) == 0)
74                         return socket;
75
76         return NULL;
77 }
78
79 ShaderOutput *ShaderNode::output(const char *name)
80 {
81         foreach(ShaderOutput *socket, outputs)
82                 if(strcmp(socket->name, name) == 0)
83                         return socket;
84
85         return NULL;
86 }
87
88 ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float value, int usage)
89 {
90         ShaderInput *input = new ShaderInput(this, name, type);
91         input->value.x = value;
92         input->usage = usage;
93         inputs.push_back(input);
94         return input;
95 }
96
97 ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float3 value, int usage)
98 {
99         ShaderInput *input = new ShaderInput(this, name, type);
100         input->value = value;
101         input->usage = usage;
102         inputs.push_back(input);
103         return input;
104 }
105
106 ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, ShaderInput::DefaultValue value, int usage)
107 {
108         ShaderInput *input = add_input(name, type);
109         input->default_value = value;
110         input->usage = usage;
111         return input;
112 }
113
114 ShaderOutput *ShaderNode::add_output(const char *name, ShaderSocketType type)
115 {
116         ShaderOutput *output = new ShaderOutput(this, name, type);
117         outputs.push_back(output);
118         return output;
119 }
120
121 void ShaderNode::attributes(AttributeRequestSet *attributes)
122 {
123         foreach(ShaderInput *input, inputs) {
124                 if(!input->link) {
125                         if(input->default_value == ShaderInput::TEXTURE_GENERATED)
126                                 attributes->add(ATTR_STD_GENERATED);
127                         else if(input->default_value == ShaderInput::TEXTURE_UV)
128                                 attributes->add(ATTR_STD_UV);
129                 }
130         }
131 }
132
133 /* Graph */
134
135 ShaderGraph::ShaderGraph()
136 {
137         finalized = false;
138         num_node_ids = 0;
139         add(new OutputNode());
140 }
141
142 ShaderGraph::~ShaderGraph()
143 {
144         foreach(ShaderNode *node, nodes)
145                 delete node;
146 }
147
148 ShaderNode *ShaderGraph::add(ShaderNode *node)
149 {
150         assert(!finalized);
151         node->id = num_node_ids++;
152         nodes.push_back(node);
153         return node;
154 }
155
156 ShaderNode *ShaderGraph::output()
157 {
158         return nodes.front();
159 }
160
161 ShaderGraph *ShaderGraph::copy()
162 {
163         ShaderGraph *newgraph = new ShaderGraph();
164
165         /* copy nodes */
166         set<ShaderNode*> nodes_all;
167         foreach(ShaderNode *node, nodes)
168                 nodes_all.insert(node);
169
170         map<ShaderNode*, ShaderNode*> nodes_copy;
171         copy_nodes(nodes_all, nodes_copy);
172
173         /* add nodes (in same order, so output is still first) */
174         newgraph->nodes.clear();
175         foreach(ShaderNode *node, nodes)
176                 newgraph->add(nodes_copy[node]);
177
178         return newgraph;
179 }
180
181 void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to)
182 {
183         assert(!finalized);
184         assert(from && to);
185
186         if(to->link) {
187                 fprintf(stderr, "Cycles shader graph connect: input already connected.\n");
188                 return;
189         }
190
191         if(from->type != to->type) {
192                 /* for closures we can't do automatic conversion */
193                 if(from->type == SHADER_SOCKET_CLOSURE || to->type == SHADER_SOCKET_CLOSURE) {
194                         fprintf(stderr, "Cycles shader graph connect: can only connect closure to closure "
195                                 "(%s.%s to %s.%s).\n",
196                                 from->parent->name.c_str(), from->name,
197                                 to->parent->name.c_str(), to->name);
198                         return;
199                 }
200
201                 /* add automatic conversion node in case of type mismatch */
202                 ShaderNode *convert = add(new ConvertNode(from->type, to->type));
203
204                 connect(from, convert->inputs[0]);
205                 connect(convert->outputs[0], to);
206         }
207         else {
208                 /* types match, just connect */
209                 to->link = from;
210                 from->links.push_back(to);
211         }
212 }
213
214 void ShaderGraph::disconnect(ShaderInput *to)
215 {
216         assert(!finalized);
217         assert(to->link);
218
219         ShaderOutput *from = to->link;
220
221         to->link = NULL;
222         from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end());
223 }
224
225 void ShaderGraph::finalize(bool do_bump, bool do_osl, bool do_multi_transform)
226 {
227         /* before compiling, the shader graph may undergo a number of modifications.
228          * currently we set default geometry shader inputs, and create automatic bump
229          * from displacement. a graph can be finalized only once, and should not be
230          * modified afterwards. */
231
232         if(!finalized) {
233                 clean();
234                 default_inputs(do_osl);
235                 refine_bump_nodes();
236
237                 if(do_bump)
238                         bump_from_displacement();
239
240                 if(do_multi_transform) {
241                         ShaderInput *surface_in = output()->input("Surface");
242                         ShaderInput *volume_in = output()->input("Volume");
243
244                         /* todo: make this work when surface and volume closures are tangled up */
245
246                         if(surface_in->link)
247                                 transform_multi_closure(surface_in->link->parent, NULL, false);
248                         if(volume_in->link)
249                                 transform_multi_closure(volume_in->link->parent, NULL, true);
250                 }
251
252                 finalized = true;
253         }
254 }
255
256 void ShaderGraph::find_dependencies(set<ShaderNode*>& dependencies, ShaderInput *input)
257 {
258         /* find all nodes that this input dependes on directly and indirectly */
259         ShaderNode *node = (input->link)? input->link->parent: NULL;
260
261         if(node) {
262                 foreach(ShaderInput *in, node->inputs)
263                         find_dependencies(dependencies, in);
264
265                 dependencies.insert(node);
266         }
267 }
268
269 void ShaderGraph::copy_nodes(set<ShaderNode*>& nodes, map<ShaderNode*, ShaderNode*>& nnodemap)
270 {
271         /* copy a set of nodes, and the links between them. the assumption is
272          * made that all nodes that inputs are linked to are in the set too. */
273
274         /* copy nodes */
275         foreach(ShaderNode *node, nodes) {
276                 ShaderNode *nnode = node->clone();
277                 nnodemap[node] = nnode;
278
279                 nnode->inputs.clear();
280                 nnode->outputs.clear();
281
282                 foreach(ShaderInput *input, node->inputs) {
283                         ShaderInput *ninput = new ShaderInput(*input);
284                         nnode->inputs.push_back(ninput);
285
286                         ninput->parent = nnode;
287                         ninput->link = NULL;
288                 }
289
290                 foreach(ShaderOutput *output, node->outputs) {
291                         ShaderOutput *noutput = new ShaderOutput(*output);
292                         nnode->outputs.push_back(noutput);
293
294                         noutput->parent = nnode;
295                         noutput->links.clear();
296                 }
297         }
298
299         /* recreate links */
300         foreach(ShaderNode *node, nodes) {
301                 foreach(ShaderInput *input, node->inputs) {
302                         if(input->link) {
303                                 /* find new input and output */
304                                 ShaderNode *nfrom = nnodemap[input->link->parent];
305                                 ShaderNode *nto = nnodemap[input->parent];
306                                 ShaderOutput *noutput = nfrom->output(input->link->name);
307                                 ShaderInput *ninput = nto->input(input->name);
308
309                                 /* connect */
310                                 connect(noutput, ninput);
311                         }
312                 }
313         }
314 }
315
316 void ShaderGraph::remove_unneeded_nodes()
317 {
318         vector<bool> removed(num_node_ids, false);
319         bool any_node_removed = false;
320         
321         /* find and unlink proxy nodes */
322         foreach(ShaderNode *node, nodes) {
323                 if(node->special_type == SHADER_SPECIAL_TYPE_PROXY) {
324                         ProxyNode *proxy = static_cast<ProxyNode*>(node);
325                         ShaderInput *input = proxy->inputs[0];
326                         ShaderOutput *output = proxy->outputs[0];
327                         
328                         /* temp. copy of the output links list.
329                          * output->links is modified when we disconnect!
330                          */
331                         vector<ShaderInput*> links(output->links);
332                         ShaderOutput *from = input->link;
333                         
334                         /* bypass the proxy node */
335                         if(from) {
336                                 disconnect(input);
337                                 foreach(ShaderInput *to, links) {
338                                         disconnect(to);
339                                         connect(from, to);
340                                 }
341                         }
342                         else {
343                                 foreach(ShaderInput *to, links) {
344                                         disconnect(to);
345                                         
346                                         /* transfer the default input value to the target socket */
347                                         to->set(input->value);
348                                         to->set(input->value_string);
349                                 }
350                         }
351                         
352                         removed[proxy->id] = true;
353                         any_node_removed = true;
354                 }
355
356                 /* remove useless mix closures nodes */
357                 if(node->special_type == SHADER_SPECIAL_TYPE_MIX_CLOSURE) {
358                         MixClosureNode *mix = static_cast<MixClosureNode*>(node);
359                         if(mix->outputs[0]->links.size() && mix->inputs[1]->link == mix->inputs[2]->link) {
360                                 ShaderOutput *output = mix->inputs[1]->link;
361                                 vector<ShaderInput*> inputs = mix->outputs[0]->links;
362
363                                 foreach(ShaderInput *sock, mix->inputs)
364                                         if(sock->link)
365                                                 disconnect(sock);
366
367                                 foreach(ShaderInput *input, inputs) {
368                                         disconnect(input);
369                                         if(output)
370                                                 connect(output, input);
371                                 }
372                         }
373                 }
374                 
375                 /* remove unused mix closure input when factor is 0.0 or 1.0 */
376                 if(node->special_type == SHADER_SPECIAL_TYPE_MIX_CLOSURE) {
377                         MixClosureNode *mix = static_cast<MixClosureNode*>(node);
378                         /* Check for closure links and make sure factor link is disconnected */
379                         if(mix->outputs[0]->links.size() && mix->inputs[1]->link && mix->inputs[2]->link && !mix->inputs[0]->link) {
380                         
381                                 /* Factor 0.0 */
382                                 if(mix->inputs[0]->value.x == 0.0f) {
383                                         ShaderOutput *output = mix->inputs[1]->link;
384                                         vector<ShaderInput*> inputs = mix->outputs[0]->links;
385                                         
386                                         foreach(ShaderInput *sock, mix->inputs)
387                                                 if(sock->link)
388                                                         disconnect(sock);
389
390                                         foreach(ShaderInput *input, inputs) {
391                                                 disconnect(input);
392                                                 if(output)
393                                                         connect(output, input);
394                                         }
395                                 }
396                                 /* Factor 1.0 */
397                                 else if(mix->inputs[0]->value.x == 1.0f) {
398                                         ShaderOutput *output = mix->inputs[2]->link;
399                                         vector<ShaderInput*> inputs = mix->outputs[0]->links;
400                                         
401                                         foreach(ShaderInput *sock, mix->inputs)
402                                                 if(sock->link)
403                                                         disconnect(sock);
404
405                                         foreach(ShaderInput *input, inputs) {
406                                                 disconnect(input);
407                                                 if(output)
408                                                         connect(output, input);
409                                         }
410                                 }
411                         }
412                 }
413         }
414
415         /* remove nodes */
416         if (any_node_removed) {
417                 list<ShaderNode*> newnodes;
418
419                 foreach(ShaderNode *node, nodes) {
420                         if(!removed[node->id])
421                                 newnodes.push_back(node);
422                         else
423                                 delete node;
424                 }
425
426                 nodes = newnodes;
427         }
428 }
429
430 void ShaderGraph::break_cycles(ShaderNode *node, vector<bool>& visited, vector<bool>& on_stack)
431 {
432         visited[node->id] = true;
433         on_stack[node->id] = true;
434
435         foreach(ShaderInput *input, node->inputs) {
436                 if(input->link) {
437                         ShaderNode *depnode = input->link->parent;
438
439                         if(on_stack[depnode->id]) {
440                                 /* break cycle */
441                                 disconnect(input);
442                                 fprintf(stderr, "Cycles shader graph: detected cycle in graph, connection removed.\n");
443                         }
444                         else if(!visited[depnode->id]) {
445                                 /* visit dependencies */
446                                 break_cycles(depnode, visited, on_stack);
447                         }
448                 }
449         }
450
451         on_stack[node->id] = false;
452 }
453
454 void ShaderGraph::clean()
455 {
456         /* remove proxy and unnecessary mix nodes */
457         remove_unneeded_nodes();
458
459         /* we do two things here: find cycles and break them, and remove unused
460          * nodes that don't feed into the output. how cycles are broken is
461          * undefined, they are invalid input, the important thing is to not crash */
462
463         vector<bool> visited(num_node_ids, false);
464         vector<bool> on_stack(num_node_ids, false);
465         
466         /* break cycles */
467         break_cycles(output(), visited, on_stack);
468
469         /* disconnect unused nodes */
470         foreach(ShaderNode *node, nodes) {
471                 if(!visited[node->id]) {
472                         foreach(ShaderInput *to, node->inputs) {
473                                 ShaderOutput *from = to->link;
474
475                                 if(from) {
476                                         to->link = NULL;
477                                         from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end());
478                                 }
479                         }
480                 }
481         }
482
483         /* remove unused nodes */
484         list<ShaderNode*> newnodes;
485
486         foreach(ShaderNode *node, nodes) {
487                 if(visited[node->id])
488                         newnodes.push_back(node);
489                 else
490                         delete node;
491         }
492         
493         nodes = newnodes;
494 }
495
496 void ShaderGraph::default_inputs(bool do_osl)
497 {
498         /* nodes can specify default texture coordinates, for now we give
499          * everything the position by default, except for the sky texture */
500
501         ShaderNode *geom = NULL;
502         ShaderNode *texco = NULL;
503
504         foreach(ShaderNode *node, nodes) {
505                 foreach(ShaderInput *input, node->inputs) {
506                         if(!input->link && ((input->usage & ShaderInput::USE_SVM) || do_osl)) {
507                                 if(input->default_value == ShaderInput::TEXTURE_GENERATED) {
508                                         if(!texco)
509                                                 texco = new TextureCoordinateNode();
510
511                                         connect(texco->output("Generated"), input);
512                                 }
513                                 else if(input->default_value == ShaderInput::TEXTURE_UV) {
514                                         if(!texco)
515                                                 texco = new TextureCoordinateNode();
516
517                                         connect(texco->output("UV"), input);
518                                 }
519                                 else if(input->default_value == ShaderInput::INCOMING) {
520                                         if(!geom)
521                                                 geom = new GeometryNode();
522
523                                         connect(geom->output("Incoming"), input);
524                                 }
525                                 else if(input->default_value == ShaderInput::NORMAL) {
526                                         if(!geom)
527                                                 geom = new GeometryNode();
528
529                                         connect(geom->output("Normal"), input);
530                                 }
531                                 else if(input->default_value == ShaderInput::POSITION) {
532                                         if(!geom)
533                                                 geom = new GeometryNode();
534
535                                         connect(geom->output("Position"), input);
536                                 }
537                                 else if(input->default_value == ShaderInput::TANGENT) {
538                                         if(!geom)
539                                                 geom = new GeometryNode();
540
541                                         connect(geom->output("Tangent"), input);
542                                 }
543                         }
544                 }
545         }
546
547         if(geom)
548                 add(geom);
549         if(texco)
550                 add(texco);
551 }
552
553 void ShaderGraph::refine_bump_nodes()
554 {
555         /* we transverse the node graph looking for bump nodes, when we find them,
556          * like in bump_from_displacement(), we copy the sub-graph defined from "bump"
557          * input to the inputs "center","dx" and "dy" What is in "bump" input is moved
558          * to "center" input. */
559
560         foreach(ShaderNode *node, nodes) {
561                 if(node->name == ustring("bump") && node->input("Height")->link) {
562                         ShaderInput *bump_input = node->input("Height");
563                         set<ShaderNode*> nodes_bump;
564
565                         /* make 2 extra copies of the subgraph defined in Bump input */
566                         map<ShaderNode*, ShaderNode*> nodes_dx;
567                         map<ShaderNode*, ShaderNode*> nodes_dy;
568
569                         /* find dependencies for the given input */
570                         find_dependencies(nodes_bump, bump_input );
571
572                         copy_nodes(nodes_bump, nodes_dx);
573                         copy_nodes(nodes_bump, nodes_dy);
574         
575                         /* mark nodes to indicate they are use for bump computation, so
576                            that any texture coordinates are shifted by dx/dy when sampling */
577                         foreach(ShaderNode *node, nodes_bump)
578                                 node->bump = SHADER_BUMP_CENTER;
579                         foreach(NodePair& pair, nodes_dx)
580                                 pair.second->bump = SHADER_BUMP_DX;
581                         foreach(NodePair& pair, nodes_dy)
582                                 pair.second->bump = SHADER_BUMP_DY;
583
584                         ShaderOutput *out = bump_input->link;
585                         ShaderOutput *out_dx = nodes_dx[out->parent]->output(out->name);
586                         ShaderOutput *out_dy = nodes_dy[out->parent]->output(out->name);
587
588                         connect(out_dx, node->input("SampleX"));
589                         connect(out_dy, node->input("SampleY"));
590                         
591                         /* add generated nodes */
592                         foreach(NodePair& pair, nodes_dx)
593                                 add(pair.second);
594                         foreach(NodePair& pair, nodes_dy)
595                                 add(pair.second);
596                         
597                         /* connect what is conected is bump to samplecenter input*/
598                         connect(out , node->input("SampleCenter"));
599
600                         /* bump input is just for connectivity purpose for the graph input,
601                          * we reconected this input to samplecenter, so lets disconnect it
602                          * from bump input */
603                         disconnect(bump_input);
604                 }
605         }
606 }
607
608 void ShaderGraph::bump_from_displacement()
609 {
610         /* generate bump mapping automatically from displacement. bump mapping is
611          * done using a 3-tap filter, computing the displacement at the center,
612          * and two other positions shifted by ray differentials.
613          *
614          * since the input to displacement is a node graph, we need to ensure that
615          * all texture coordinates use are shift by the ray differentials. for this
616          * reason we make 3 copies of the node subgraph defining the displacement,
617          * with each different geometry and texture coordinate nodes that generate
618          * different shifted coordinates.
619          *
620          * these 3 displacement values are then fed into the bump node, which will
621          * output the the perturbed normal. */
622
623         ShaderInput *displacement_in = output()->input("Displacement");
624
625         if(!displacement_in->link)
626                 return;
627         
628         /* find dependencies for the given input */
629         set<ShaderNode*> nodes_displace;
630         find_dependencies(nodes_displace, displacement_in);
631
632         /* copy nodes for 3 bump samples */
633         map<ShaderNode*, ShaderNode*> nodes_center;
634         map<ShaderNode*, ShaderNode*> nodes_dx;
635         map<ShaderNode*, ShaderNode*> nodes_dy;
636
637         copy_nodes(nodes_displace, nodes_center);
638         copy_nodes(nodes_displace, nodes_dx);
639         copy_nodes(nodes_displace, nodes_dy);
640
641         /* mark nodes to indicate they are use for bump computation, so
642          * that any texture coordinates are shifted by dx/dy when sampling */
643         foreach(NodePair& pair, nodes_center)
644                 pair.second->bump = SHADER_BUMP_CENTER;
645         foreach(NodePair& pair, nodes_dx)
646                 pair.second->bump = SHADER_BUMP_DX;
647         foreach(NodePair& pair, nodes_dy)
648                 pair.second->bump = SHADER_BUMP_DY;
649
650         /* add set normal node and connect the bump normal ouput to the set normal
651          * output, so it can finally set the shader normal, note we are only doing
652          * this for bump from displacement, this will be the only bump allowed to
653          * overwrite the shader normal */
654         ShaderNode *set_normal = add(new SetNormalNode());
655         
656         /* add bump node and connect copied graphs to it */
657         ShaderNode *bump = add(new BumpNode());
658
659         ShaderOutput *out = displacement_in->link;
660         ShaderOutput *out_center = nodes_center[out->parent]->output(out->name);
661         ShaderOutput *out_dx = nodes_dx[out->parent]->output(out->name);
662         ShaderOutput *out_dy = nodes_dy[out->parent]->output(out->name);
663
664         connect(out_center, bump->input("SampleCenter"));
665         connect(out_dx, bump->input("SampleX"));
666         connect(out_dy, bump->input("SampleY"));
667         
668         /* connect the bump out to the set normal in: */
669         connect(bump->output("Normal"), set_normal->input("Direction"));
670
671         /* connect bump output to normal input nodes that aren't set yet. actually
672          * this will only set the normal input to the geometry node that we created
673          * and connected to all other normal inputs already. */
674         foreach(ShaderNode *node, nodes)
675                 foreach(ShaderInput *input, node->inputs)
676                         if(!input->link && input->default_value == ShaderInput::NORMAL)
677                                 connect(set_normal->output("Normal"), input);
678
679         /* for displacement bump, clear the normal input in case the above loop
680          * connected the setnormal out to the bump normalin */
681         ShaderInput *bump_normal_in = bump->input("Normal");
682         if(bump_normal_in)
683                 bump_normal_in->link = NULL;
684
685         /* finally, add the copied nodes to the graph. we can't do this earlier
686          * because we would create dependency cycles in the above loop */
687         foreach(NodePair& pair, nodes_center)
688                 add(pair.second);
689         foreach(NodePair& pair, nodes_dx)
690                 add(pair.second);
691         foreach(NodePair& pair, nodes_dy)
692                 add(pair.second);
693 }
694
695 void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume)
696 {
697         /* for SVM in multi closure mode, this transforms the shader mix/add part of
698          * the graph into nodes that feed weights into closure nodes. this is too
699          * avoid building a closure tree and then flattening it, and instead write it
700          * directly to an array */
701         
702         if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) {
703                 ShaderInput *fin = node->input("Fac");
704                 ShaderInput *cl1in = node->input("Closure1");
705                 ShaderInput *cl2in = node->input("Closure2");
706                 ShaderOutput *weight1_out, *weight2_out;
707
708                 if(fin) {
709                         /* mix closure: add node to mix closure weights */
710                         ShaderNode *mix_node = add(new MixClosureWeightNode());
711                         ShaderInput *fac_in = mix_node->input("Fac"); 
712                         ShaderInput *weight_in = mix_node->input("Weight"); 
713
714                         if(fin->link)
715                                 connect(fin->link, fac_in);
716                         else
717                                 fac_in->value = fin->value;
718
719                         if(weight_out)
720                                 connect(weight_out, weight_in);
721
722                         weight1_out = mix_node->output("Weight1");
723                         weight2_out = mix_node->output("Weight2");
724                 }
725                 else {
726                         /* add closure: just pass on any weights */
727                         weight1_out = weight_out;
728                         weight2_out = weight_out;
729                 }
730
731                 if(cl1in->link)
732                         transform_multi_closure(cl1in->link->parent, weight1_out, volume);
733                 if(cl2in->link)
734                         transform_multi_closure(cl2in->link->parent, weight2_out, volume);
735         }
736         else {
737                 ShaderInput *weight_in = node->input((volume)? "VolumeMixWeight": "SurfaceMixWeight");
738
739                 /* not a closure node? */
740                 if(!weight_in)
741                         return;
742
743                 /* already has a weight connected to it? add weights */
744                 if(weight_in->link || weight_in->value.x != 0.0f) {
745                         ShaderNode *math_node = add(new MathNode());
746                         ShaderInput *value1_in = math_node->input("Value1");
747                         ShaderInput *value2_in = math_node->input("Value2");
748
749                         if(weight_in->link)
750                                 connect(weight_in->link, value1_in);
751                         else
752                                 value1_in->value = weight_in->value;
753
754                         if(weight_out)
755                                 connect(weight_out, value2_in);
756                         else
757                                 value2_in->value.x = 1.0f;
758
759                         weight_out = math_node->output("Value");
760                         if(weight_in->link)
761                                 disconnect(weight_in);
762                 }
763
764                 /* connected to closure mix weight */
765                 if(weight_out)
766                         connect(weight_out, weight_in);
767                 else
768                         weight_in->value.x += 1.0f;
769         }
770 }
771
772 CCL_NAMESPACE_END
773