~ubuntu-branches/ubuntu/trusty/blender/trusty

« back to all changes in this revision

Viewing changes to intern/cycles/render/graph.cpp

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2013-03-06 12:08:47 UTC
  • mfrom: (1.5.1) (14.1.8 experimental)
  • Revision ID: package-import@ubuntu.com-20130306120847-frjfaryb2zrotwcg
Tags: 2.66a-1ubuntu1
* Resynchronize with Debian (LP: #1076930, #1089256, #1052743, #999024,
  #1122888, #1147084)
* debian/control:
  - Lower build-depends on libavcodec-dev since we're not
    doing the libav9 transition in Ubuntu yet

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
        value = make_float3(0, 0, 0);
38
38
        stack_offset = SVM_STACK_INVALID;
39
39
        default_value = NONE;
40
 
        osl_only = false;
 
40
        usage = USE_ALL;
41
41
}
42
42
 
43
43
ShaderOutput::ShaderOutput(ShaderNode *parent_, const char *name_, ShaderSocketType type_)
55
55
        name = name_;
56
56
        id = -1;
57
57
        bump = SHADER_BUMP_NONE;
 
58
        special_type = SHADER_SPECIAL_TYPE_NONE;
58
59
}
59
60
 
60
61
ShaderNode::~ShaderNode()
84
85
        return NULL;
85
86
}
86
87
 
87
 
ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float value)
 
88
ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float value, int usage)
88
89
{
89
90
        ShaderInput *input = new ShaderInput(this, name, type);
90
91
        input->value.x = value;
 
92
        input->usage = usage;
91
93
        inputs.push_back(input);
92
94
        return input;
93
95
}
94
96
 
95
 
ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float3 value)
 
97
ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float3 value, int usage)
96
98
{
97
99
        ShaderInput *input = new ShaderInput(this, name, type);
98
100
        input->value = value;
 
101
        input->usage = usage;
99
102
        inputs.push_back(input);
100
103
        return input;
101
104
}
102
105
 
103
 
ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, ShaderInput::DefaultValue value, bool osl_only)
 
106
ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, ShaderInput::DefaultValue value, int usage)
104
107
{
105
108
        ShaderInput *input = add_input(name, type);
106
109
        input->default_value = value;
107
 
        input->osl_only = osl_only;
 
110
        input->usage = usage;
108
111
        return input;
109
112
}
110
113
 
120
123
        foreach(ShaderInput *input, inputs) {
121
124
                if(!input->link) {
122
125
                        if(input->default_value == ShaderInput::TEXTURE_GENERATED)
123
 
                                attributes->add(Attribute::STD_GENERATED);
 
126
                                attributes->add(ATTR_STD_GENERATED);
124
127
                        else if(input->default_value == ShaderInput::TEXTURE_UV)
125
 
                                attributes->add(Attribute::STD_UV);
 
128
                                attributes->add(ATTR_STD_UV);
126
129
                }
127
130
        }
128
131
}
180
183
        assert(from && to);
181
184
 
182
185
        if(to->link) {
183
 
                fprintf(stderr, "ShaderGraph connect: input already connected.\n");
 
186
                fprintf(stderr, "Cycles shader graph connect: input already connected.\n");
184
187
                return;
185
188
        }
186
189
 
187
190
        if(from->type != to->type) {
188
191
                /* for closures we can't do automatic conversion */
189
192
                if(from->type == SHADER_SOCKET_CLOSURE || to->type == SHADER_SOCKET_CLOSURE) {
190
 
                        fprintf(stderr, "ShaderGraph connect: can only connect closure to closure.\n");
 
193
                        fprintf(stderr, "Cycles shader graph connect: can only connect closure to closure "
 
194
                                "(ShaderNode:%s, ShaderOutput:%s , type:%d -> to ShaderNode:%s, ShaderInput:%s, type:%d).\n",
 
195
                                from->parent->name.c_str(), from->name, (int)from->type,
 
196
                                to->parent->name.c_str(),   to->name,   (int)to->type);
191
197
                        return;
192
198
                }
193
199
 
215
221
        from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end());
216
222
}
217
223
 
218
 
void ShaderGraph::finalize(bool do_bump, bool do_osl)
 
224
void ShaderGraph::finalize(bool do_bump, bool do_osl, bool do_multi_transform)
219
225
{
220
226
        /* before compiling, the shader graph may undergo a number of modifications.
221
227
         * currently we set default geometry shader inputs, and create automatic bump
225
231
        if(!finalized) {
226
232
                clean();
227
233
                default_inputs(do_osl);
 
234
                refine_bump_nodes();
 
235
 
228
236
                if(do_bump)
229
237
                        bump_from_displacement();
230
238
 
 
239
                if(do_multi_transform) {
 
240
                        ShaderInput *surface_in = output()->input("Surface");
 
241
                        ShaderInput *volume_in = output()->input("Volume");
 
242
 
 
243
                        /* todo: make this work when surface and volume closures are tangled up */
 
244
 
 
245
                        if(surface_in->link)
 
246
                                transform_multi_closure(surface_in->link->parent, NULL, false);
 
247
                        if(volume_in->link)
 
248
                                transform_multi_closure(volume_in->link->parent, NULL, true);
 
249
                }
 
250
 
231
251
                finalized = true;
232
252
        }
233
253
}
295
315
void ShaderGraph::remove_proxy_nodes(vector<bool>& removed)
296
316
{
297
317
        foreach(ShaderNode *node, nodes) {
298
 
                ProxyNode *proxy = dynamic_cast<ProxyNode*>(node);
299
 
                if (proxy) {
 
318
                if (node->special_type == SHADER_SPECIAL_TYPE_PROXY) {
 
319
                        ProxyNode *proxy = static_cast<ProxyNode*>(node);
300
320
                        ShaderInput *input = proxy->inputs[0];
301
321
                        ShaderOutput *output = proxy->outputs[0];
302
322
                        
320
340
                                        
321
341
                                        /* transfer the default input value to the target socket */
322
342
                                        to->set(input->value);
 
343
                                        to->set(input->value_string);
323
344
                                }
324
345
                        }
325
346
                        
326
347
                        removed[proxy->id] = true;
327
348
                }
 
349
 
 
350
                /* remove useless mix closures nodes */
 
351
                if(node->special_type == SHADER_SPECIAL_TYPE_MIX_CLOSURE) {
 
352
                        MixClosureNode *mix = static_cast<MixClosureNode*>(node);
 
353
                        if(mix->outputs[0]->links.size() && mix->inputs[1]->link == mix->inputs[2]->link) {
 
354
                                ShaderOutput *output = mix->inputs[1]->link;
 
355
                                vector<ShaderInput*> inputs = mix->outputs[0]->links;
 
356
 
 
357
                                foreach(ShaderInput *sock, mix->inputs)
 
358
                                        if(sock->link)
 
359
                                                disconnect(sock);
 
360
 
 
361
                                foreach(ShaderInput *input, inputs) {
 
362
                                        disconnect(input);
 
363
                                        if (output)
 
364
                                                connect(output, input);
 
365
                                }
 
366
                        }
 
367
                }
328
368
        }
329
369
}
330
370
 
340
380
                        if(on_stack[depnode->id]) {
341
381
                                /* break cycle */
342
382
                                disconnect(input);
343
 
                                fprintf(stderr, "ShaderGraph: detected cycle in graph, connection removed.\n");
 
383
                                fprintf(stderr, "Cycles shader graph: detected cycle in graph, connection removed.\n");
344
384
                        }
345
385
                        else if(!visited[depnode->id]) {
346
386
                                /* visit dependencies */
355
395
void ShaderGraph::clean()
356
396
{
357
397
        /* we do two things here: find cycles and break them, and remove unused
358
 
           nodes that don't feed into the output. how cycles are broken is
359
 
           undefined, they are invalid input, the important thing is to not crash */
 
398
         * nodes that don't feed into the output. how cycles are broken is
 
399
         * undefined, they are invalid input, the important thing is to not crash */
360
400
 
361
401
        vector<bool> removed(nodes.size(), false);
362
402
        vector<bool> visited(nodes.size(), false);
379
419
        /* break cycles */
380
420
        break_cycles(output(), visited, on_stack);
381
421
 
 
422
        /* disconnect unused nodes */
 
423
        foreach(ShaderNode *node, nodes) {
 
424
                if(!visited[node->id]) {
 
425
                        foreach(ShaderInput *to, node->inputs) {
 
426
                                ShaderOutput *from = to->link;
 
427
 
 
428
                                if (from) {
 
429
                                        to->link = NULL;
 
430
                                        from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end());
 
431
                                }
 
432
                        }
 
433
                }
 
434
        }
 
435
 
382
436
        /* remove unused nodes */
383
437
        foreach(ShaderNode *node, nodes) {
384
438
                if(visited[node->id])
400
454
 
401
455
        foreach(ShaderNode *node, nodes) {
402
456
                foreach(ShaderInput *input, node->inputs) {
403
 
                        if(!input->link && !(input->osl_only && !do_osl)) {
 
457
                        if(!input->link && ((input->usage & ShaderInput::USE_SVM) || do_osl)) {
404
458
                                if(input->default_value == ShaderInput::TEXTURE_GENERATED) {
405
459
                                        if(!texco)
406
460
                                                texco = new TextureCoordinateNode();
431
485
 
432
486
                                        connect(geom->output("Position"), input);
433
487
                                }
 
488
                                else if(input->default_value == ShaderInput::TANGENT) {
 
489
                                        if(!geom)
 
490
                                                geom = new GeometryNode();
 
491
 
 
492
                                        connect(geom->output("Tangent"), input);
 
493
                                }
434
494
                        }
435
495
                }
436
496
        }
441
501
                add(texco);
442
502
}
443
503
 
 
504
void ShaderGraph::refine_bump_nodes()
 
505
{
 
506
        /* we transverse the node graph looking for bump nodes, when we find them,
 
507
         * like in bump_from_displacement(), we copy the sub-graph defined from "bump"
 
508
         * input to the inputs "center","dx" and "dy" What is in "bump" input is moved
 
509
         * to "center" input. */
 
510
 
 
511
        foreach(ShaderNode *node, nodes) {
 
512
                if(node->name == ustring("bump") && node->input("Height")->link) {
 
513
                        ShaderInput *bump_input = node->input("Height");
 
514
                        set<ShaderNode*> nodes_bump;
 
515
 
 
516
                        /* make 2 extra copies of the subgraph defined in Bump input */
 
517
                        map<ShaderNode*, ShaderNode*> nodes_dx;
 
518
                        map<ShaderNode*, ShaderNode*> nodes_dy;
 
519
 
 
520
                        /* find dependencies for the given input */
 
521
                        find_dependencies(nodes_bump, bump_input );
 
522
 
 
523
                        copy_nodes(nodes_bump, nodes_dx);
 
524
                        copy_nodes(nodes_bump, nodes_dy);
 
525
        
 
526
                        /* mark nodes to indicate they are use for bump computation, so
 
527
                           that any texture coordinates are shifted by dx/dy when sampling */
 
528
                        foreach(ShaderNode *node, nodes_bump)
 
529
                                node->bump = SHADER_BUMP_CENTER;
 
530
                        foreach(NodePair& pair, nodes_dx)
 
531
                                pair.second->bump = SHADER_BUMP_DX;
 
532
                        foreach(NodePair& pair, nodes_dy)
 
533
                                pair.second->bump = SHADER_BUMP_DY;
 
534
 
 
535
                        ShaderOutput *out = bump_input->link;
 
536
                        ShaderOutput *out_dx = nodes_dx[out->parent]->output(out->name);
 
537
                        ShaderOutput *out_dy = nodes_dy[out->parent]->output(out->name);
 
538
 
 
539
                        connect(out_dx, node->input("SampleX"));
 
540
                        connect(out_dy, node->input("SampleY"));
 
541
                        
 
542
                        /* add generated nodes */
 
543
                        foreach(NodePair& pair, nodes_dx)
 
544
                                add(pair.second);
 
545
                        foreach(NodePair& pair, nodes_dy)
 
546
                                add(pair.second);
 
547
                        
 
548
                        /* connect what is conected is bump to samplecenter input*/
 
549
                        connect(out , node->input("SampleCenter"));
 
550
 
 
551
                        /* bump input is just for connectivity purpose for the graph input,
 
552
                         * we reconected this input to samplecenter, so lets disconnect it
 
553
                         * from bump input */
 
554
                        disconnect(bump_input);
 
555
                }
 
556
        }
 
557
}
 
558
 
444
559
void ShaderGraph::bump_from_displacement()
445
560
{
446
561
        /* generate bump mapping automatically from displacement. bump mapping is
454
569
         * different shifted coordinates.
455
570
         *
456
571
         * these 3 displacement values are then fed into the bump node, which will
457
 
         * modify the normal. */
 
572
         * output the the perturbed normal. */
458
573
 
459
574
        ShaderInput *displacement_in = output()->input("Displacement");
460
575
 
475
590
        copy_nodes(nodes_displace, nodes_dy);
476
591
 
477
592
        /* mark nodes to indicate they are use for bump computation, so
478
 
           that any texture coordinates are shifted by dx/dy when sampling */
 
593
         * that any texture coordinates are shifted by dx/dy when sampling */
479
594
        foreach(NodePair& pair, nodes_center)
480
595
                pair.second->bump = SHADER_BUMP_CENTER;
481
596
        foreach(NodePair& pair, nodes_dx)
483
598
        foreach(NodePair& pair, nodes_dy)
484
599
                pair.second->bump = SHADER_BUMP_DY;
485
600
 
 
601
        /* add set normal node and connect the bump normal ouput to the set normal
 
602
         * output, so it can finally set the shader normal, note we are only doing
 
603
         * this for bump from displacement, this will be the only bump allowed to
 
604
         * overwrite the shader normal */
 
605
        ShaderNode *set_normal = add(new SetNormalNode());
 
606
        
486
607
        /* add bump node and connect copied graphs to it */
487
608
        ShaderNode *bump = add(new BumpNode());
488
609
 
494
615
        connect(out_center, bump->input("SampleCenter"));
495
616
        connect(out_dx, bump->input("SampleX"));
496
617
        connect(out_dy, bump->input("SampleY"));
 
618
        
 
619
        /* connect the bump out to the set normal in: */
 
620
        connect(bump->output("Normal"), set_normal->input("Direction"));
497
621
 
498
622
        /* connect bump output to normal input nodes that aren't set yet. actually
499
 
           this will only set the normal input to the geometry node that we created
500
 
           and connected to all other normal inputs already. */
 
623
         * this will only set the normal input to the geometry node that we created
 
624
         * and connected to all other normal inputs already. */
501
625
        foreach(ShaderNode *node, nodes)
502
626
                foreach(ShaderInput *input, node->inputs)
503
627
                        if(!input->link && input->default_value == ShaderInput::NORMAL)
504
 
                                connect(bump->output("Normal"), input);
505
 
        
 
628
                                connect(set_normal->output("Normal"), input);
 
629
 
 
630
        /* for displacement bump, clear the normal input in case the above loop
 
631
         * connected the setnormal out to the bump normalin */
 
632
        ShaderInput *bump_normal_in = bump->input("NormalIn");
 
633
        if(bump_normal_in)
 
634
                bump_normal_in->link = NULL;
 
635
 
506
636
        /* finally, add the copied nodes to the graph. we can't do this earlier
507
 
           because we would create dependency cycles in the above loop */
 
637
         * because we would create dependency cycles in the above loop */
508
638
        foreach(NodePair& pair, nodes_center)
509
639
                add(pair.second);
510
640
        foreach(NodePair& pair, nodes_dx)
513
643
                add(pair.second);
514
644
}
515
645
 
 
646
void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume)
 
647
{
 
648
        /* for SVM in multi closure mode, this transforms the shader mix/add part of
 
649
         * the graph into nodes that feed weights into closure nodes. this is too
 
650
         * avoid building a closure tree and then flattening it, and instead write it
 
651
         * directly to an array */
 
652
        
 
653
        if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) {
 
654
                ShaderInput *fin = node->input("Fac");
 
655
                ShaderInput *cl1in = node->input("Closure1");
 
656
                ShaderInput *cl2in = node->input("Closure2");
 
657
                ShaderOutput *weight1_out, *weight2_out;
 
658
 
 
659
                if(fin) {
 
660
                        /* mix closure: add node to mix closure weights */
 
661
                        ShaderNode *mix_node = add(new MixClosureWeightNode());
 
662
                        ShaderInput *fac_in = mix_node->input("Fac"); 
 
663
                        ShaderInput *weight_in = mix_node->input("Weight"); 
 
664
 
 
665
                        if(fin->link)
 
666
                                connect(fin->link, fac_in);
 
667
                        else
 
668
                                fac_in->value = fin->value;
 
669
 
 
670
                        if(weight_out)
 
671
                                connect(weight_out, weight_in);
 
672
 
 
673
                        weight1_out = mix_node->output("Weight1");
 
674
                        weight2_out = mix_node->output("Weight2");
 
675
                }
 
676
                else {
 
677
                        /* add closure: just pass on any weights */
 
678
                        weight1_out = weight_out;
 
679
                        weight2_out = weight_out;
 
680
                }
 
681
 
 
682
                if(cl1in->link)
 
683
                        transform_multi_closure(cl1in->link->parent, weight1_out, volume);
 
684
                if(cl2in->link)
 
685
                        transform_multi_closure(cl2in->link->parent, weight2_out, volume);
 
686
        }
 
687
        else {
 
688
                ShaderInput *weight_in = node->input((volume)? "VolumeMixWeight": "SurfaceMixWeight");
 
689
 
 
690
                /* not a closure node? */
 
691
                if(!weight_in)
 
692
                        return;
 
693
 
 
694
                /* already has a weight connected to it? add weights */
 
695
                if(weight_in->link || weight_in->value.x != 0.0f) {
 
696
                        ShaderNode *math_node = add(new MathNode());
 
697
                        ShaderInput *value1_in = math_node->input("Value1");
 
698
                        ShaderInput *value2_in = math_node->input("Value2");
 
699
 
 
700
                        if(weight_in->link)
 
701
                                connect(weight_in->link, value1_in);
 
702
                        else
 
703
                                value1_in->value = weight_in->value;
 
704
 
 
705
                        if(weight_out)
 
706
                                connect(weight_out, value2_in);
 
707
                        else
 
708
                                value2_in->value.x = 1.0f;
 
709
 
 
710
                        weight_out = math_node->output("Value");
 
711
                        if(weight_in->link)
 
712
                                disconnect(weight_in);
 
713
                }
 
714
 
 
715
                /* connected to closure mix weight */
 
716
                if(weight_out)
 
717
                        connect(weight_out, weight_in);
 
718
                else
 
719
                        weight_in->value.x += 1.0f;
 
720
        }
 
721
}
 
722
 
516
723
CCL_NAMESPACE_END
517
724