Merge branch 'master' into blender2.8
[blender.git] / source / blender / nodes / shader / node_shader_tree.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
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  * The Original Code is Copyright (C) 2007 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s):
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/nodes/shader/node_shader_tree.c
29  *  \ingroup nodes
30  */
31
32
33 #include <string.h>
34
35 #include "DNA_lamp_types.h"
36 #include "DNA_material_types.h"
37 #include "DNA_node_types.h"
38 #include "DNA_scene_types.h"
39 #include "DNA_space_types.h"
40 #include "DNA_world_types.h"
41 #include "DNA_linestyle_types.h"
42
43 #include "BLI_listbase.h"
44 #include "BLI_threads.h"
45 #include "BLI_utildefines.h"
46
47 #include "BLT_translation.h"
48
49 #include "BKE_context.h"
50 #include "BKE_linestyle.h"
51 #include "BKE_node.h"
52 #include "BKE_scene.h"
53
54 #include "RNA_access.h"
55
56 #include "GPU_material.h"
57
58 #include "RE_shader_ext.h"
59
60 #include "NOD_common.h"
61
62 #include "node_common.h"
63 #include "node_exec.h"
64 #include "node_util.h"
65 #include "node_shader_util.h"
66
67 static int shader_tree_poll(const bContext *C, bNodeTreeType *UNUSED(treetype))
68 {
69         Scene *scene = CTX_data_scene(C);
70         /* allow empty engine string too, this is from older versions that didn't have registerable engines yet */
71         return (scene->r.engine[0] == '\0' ||
72                 STREQ(scene->r.engine, RE_engine_id_BLENDER_RENDER) ||
73                 STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME) ||
74                 STREQ(scene->r.engine, RE_engine_id_CYCLES) ||
75                 !BKE_scene_use_shading_nodes_custom(scene));
76 }
77
78 static void shader_get_from_context(const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from)
79 {
80         SpaceNode *snode = CTX_wm_space_node(C);
81         Scene *scene = CTX_data_scene(C);
82         SceneLayer *sl = CTX_data_scene_layer(C);
83         Object *ob = OBACT_NEW(sl);
84         
85         if ((snode->shaderfrom == SNODE_SHADER_OBJECT) ||
86             (BKE_scene_use_new_shading_nodes(scene) == false))
87         {
88                 if (ob) {
89                         *r_from = &ob->id;
90                         if (ob->type == OB_LAMP) {
91                                 *r_id = ob->data;
92                                 *r_ntree = ((Lamp *)ob->data)->nodetree;
93                         }
94                         else {
95                                 Material *ma = give_current_material(ob, ob->actcol);
96                                 if (ma) {
97                                         *r_id = &ma->id;
98                                         *r_ntree = ma->nodetree;
99                                 }
100                         }
101                 }
102         }
103 #ifdef WITH_FREESTYLE
104         else if (snode->shaderfrom == SNODE_SHADER_LINESTYLE) {
105                 FreestyleLineStyle *linestyle = BKE_linestyle_active_from_scene(scene);
106                 if (linestyle) {
107                         *r_from = NULL;
108                         *r_id = &linestyle->id;
109                         *r_ntree = linestyle->nodetree;
110                 }
111         }
112 #endif
113         else { /* SNODE_SHADER_WORLD */
114                 if (scene->world) {
115                         *r_from = NULL;
116                         *r_id = &scene->world->id;
117                         *r_ntree = scene->world->nodetree;
118                 }
119         }
120 }
121
122 static void foreach_nodeclass(Scene *scene, void *calldata, bNodeClassCallback func)
123 {
124         func(calldata, NODE_CLASS_INPUT, N_("Input"));
125         func(calldata, NODE_CLASS_OUTPUT, N_("Output"));
126
127         if (BKE_scene_use_new_shading_nodes(scene)) {
128                 func(calldata, NODE_CLASS_SHADER, N_("Shader"));
129                 func(calldata, NODE_CLASS_TEXTURE, N_("Texture"));
130         }
131         
132         func(calldata, NODE_CLASS_OP_COLOR, N_("Color"));
133         func(calldata, NODE_CLASS_OP_VECTOR, N_("Vector"));
134         func(calldata, NODE_CLASS_CONVERTOR, N_("Convertor"));
135         func(calldata, NODE_CLASS_SCRIPT, N_("Script"));
136         func(calldata, NODE_CLASS_GROUP, N_("Group"));
137         func(calldata, NODE_CLASS_INTERFACE, N_("Interface"));
138         func(calldata, NODE_CLASS_LAYOUT, N_("Layout"));
139 }
140
141 static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree))
142 {
143         bNode *node, *node_next;
144         
145         /* replace muted nodes and reroute nodes by internal links */
146         for (node = localtree->nodes.first; node; node = node_next) {
147                 node_next = node->next;
148                 
149                 if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) {
150                         nodeInternalRelink(localtree, node);
151                         nodeFreeNode(localtree, node);
152                 }
153         }
154 }
155
156 static void local_sync(bNodeTree *localtree, bNodeTree *ntree)
157 {
158         BKE_node_preview_sync_tree(ntree, localtree);
159 }
160
161 static void local_merge(bNodeTree *localtree, bNodeTree *ntree)
162 {
163         BKE_node_preview_merge_tree(ntree, localtree, true);
164 }
165
166 static void update(bNodeTree *ntree)
167 {
168         ntreeSetOutput(ntree);
169         
170         ntree_update_reroute_nodes(ntree);
171         
172         if (ntree->update & NTREE_UPDATE_NODES) {
173                 /* clean up preview cache, in case nodes have been removed */
174                 BKE_node_preview_remove_unused(ntree);
175         }
176 }
177
178 bNodeTreeType *ntreeType_Shader;
179
180 void register_node_tree_type_sh(void)
181 {
182         bNodeTreeType *tt = ntreeType_Shader = MEM_callocN(sizeof(bNodeTreeType), "shader node tree type");
183         
184         tt->type = NTREE_SHADER;
185         strcpy(tt->idname, "ShaderNodeTree");
186         strcpy(tt->ui_name, "Shader");
187         tt->ui_icon = 0;    /* defined in drawnode.c */
188         strcpy(tt->ui_description, "Shader nodes");
189         
190         tt->foreach_nodeclass = foreach_nodeclass;
191         tt->localize = localize;
192         tt->local_sync = local_sync;
193         tt->local_merge = local_merge;
194         tt->update = update;
195         tt->poll = shader_tree_poll;
196         tt->get_from_context = shader_get_from_context;
197         
198         tt->ext.srna = &RNA_ShaderNodeTree;
199         
200         ntreeTypeAdd(tt);
201 }
202
203 /* GPU material from shader nodes */
204
205 static void ntree_shader_link_builtin_normal(bNodeTree *ntree,
206                                              bNode *node_from,
207                                              bNodeSocket *socket_from,
208                                              bNode *displacement_node,
209                                              bNodeSocket *displacement_socket);
210
211 /* Find an output node of the shader tree.
212  *
213  * NOTE: it will only return output which is NOT in the group, which isn't how
214  * render engines works but it's how the GPU shader compilation works. This we
215  * can change in the future and make it a generic function, but for now it stays
216  * private here.
217  *
218  * It also does not yet take into account render engine specific output nodes,
219  * it should give priority to e.g. the Eevee material output node for Eevee.
220  */
221 static bNode *ntree_shader_output_node(bNodeTree *ntree)
222 {
223         /* Make sure we only have single node tagged as output. */
224         ntreeSetOutput(ntree);
225         for (bNode *node = ntree->nodes.first; node != NULL; node = node->next) {
226                 if (node->flag & NODE_DO_OUTPUT) {
227                         return node;
228                 }
229         }
230         return NULL;
231 }
232
233 /* Find socket with a specified identifier. */
234 static bNodeSocket *ntree_shader_node_find_socket(ListBase *sockets,
235                                                   const char *identifier)
236 {
237         for (bNodeSocket *sock = sockets->first; sock != NULL; sock = sock->next) {
238                 if (STREQ(sock->identifier, identifier)) {
239                         return sock;
240                 }
241         }
242         return NULL;
243 }
244
245 /* Find input socket with a specified identifier. */
246 static bNodeSocket *ntree_shader_node_find_input(bNode *node,
247                                                  const char *identifier)
248 {
249         return ntree_shader_node_find_socket(&node->inputs, identifier);
250 }
251
252 /* Find output socket with a specified identifier. */
253 static bNodeSocket *ntree_shader_node_find_output(bNode *node,
254                                                   const char *identifier)
255 {
256         return ntree_shader_node_find_socket(&node->outputs, identifier);
257 }
258
259 /* Check whether shader has a displacement.
260  *
261  * Will also return a node and it's socket which is connected to a displacement
262  * output. Additionally, link which is attached to the displacement output is
263  * also returned.
264  */
265 static bool ntree_shader_has_displacement(bNodeTree *ntree,
266                                           bNode **r_node,
267                                           bNodeSocket **r_socket,
268                                           bNodeLink **r_link)
269 {
270         bNode *output_node = ntree_shader_output_node(ntree);
271         if (output_node == NULL) {
272                 /* We can't have displacement without output node, apparently. */
273                 return false;
274         }
275         /* Make sure sockets links pointers are correct. */
276         ntreeUpdateTree(G.main, ntree);
277         bNodeSocket *displacement = ntree_shader_node_find_input(output_node,
278                                                                  "Displacement");
279
280         if (displacement == NULL) {
281                 /* Non-cycles node is used as an output. */
282                 return false;
283         }
284         if (displacement->link != NULL) {
285                 *r_node = displacement->link->fromnode;
286                 *r_socket = displacement->link->fromsock;
287                 *r_link = displacement->link;
288         }
289         return displacement->link != NULL;
290 }
291
292 static bool ntree_shader_relink_node_normal(bNodeTree *ntree,
293                                             bNode *node,
294                                             bNode *node_from,
295                                             bNodeSocket *socket_from)
296 {
297         bNodeSocket *sock = ntree_shader_node_find_input(node, "Normal");
298         /* TODO(sergey): Can we do something smarter here than just a name-based
299          * matching?
300          */
301         if (sock == NULL) {
302                 /* There's no Normal input, nothing to link. */
303                 return false;
304         }
305         if (sock->link != NULL) {
306                 /* Something is linked to the normal input already. can't
307                  * use other input for that.
308                  */
309                 return false;
310         }
311         /* Create connection between specified node and the normal input. */
312         nodeAddLink(ntree, node_from, socket_from, node, sock);
313         return true;
314 }
315
316 static void ntree_shader_link_builtin_group_normal(
317         bNodeTree *ntree,
318         bNode *group_node,
319         bNode *node_from,
320         bNodeSocket *socket_from,
321         bNode *displacement_node,
322         bNodeSocket *displacement_socket)
323 {
324         bNodeTree *group_ntree = (bNodeTree *)group_node->id;
325         /* Create input socket to plug displacement connection to. */
326         bNodeSocket *group_normal_socket =
327                 ntreeAddSocketInterface(group_ntree,
328                                         SOCK_IN,
329                                         "NodeSocketVector",
330                                         "Normal");
331         /* Need to update tree so all node instances nodes gets proper sockets. */
332         bNode *group_input_node = ntreeFindType(group_ntree, NODE_GROUP_INPUT);
333         node_group_verify(ntree, group_node, &group_ntree->id);
334         if (group_input_node)
335                 node_group_input_verify(group_ntree, group_input_node, &group_ntree->id);
336         ntreeUpdateTree(G.main, group_ntree);
337         /* Assumes sockets are always added at the end. */
338         bNodeSocket *group_node_normal_socket = group_node->inputs.last;
339         if (displacement_node == group_node) {
340                 /* If displacement is coming from this node group we need to perform
341                  * some internal re-linking in order to avoid cycles.
342                  */
343                 bNode *group_output_node = ntreeFindType(group_ntree, NODE_GROUP_OUTPUT);
344                 BLI_assert(group_output_node != NULL);
345                 bNodeSocket *group_output_node_displacement_socket =
346                         nodeFindSocket(group_output_node,
347                                        SOCK_IN,
348                                        displacement_socket->identifier);
349                 bNodeLink *group_displacement_link = group_output_node_displacement_socket->link;
350                 if (group_displacement_link == NULL) {
351                         /* Displacement output is not connected to anything, can just stop
352                          * right away.
353                          */
354                         return;
355                 }
356                 /* This code is similar to ntree_shader_relink_displacement() */
357                 bNode *group_displacement_node = group_displacement_link->fromnode;
358                 bNodeSocket *group_displacement_socket = group_displacement_link->fromsock;
359                 /* Create and link bump node.
360                  * Can't re-use bump node from parent tree because it'll cause cycle.
361                  */
362                 bNode *bump_node = nodeAddStaticNode(NULL, group_ntree, SH_NODE_BUMP);
363                 bNodeSocket *bump_input_socket = ntree_shader_node_find_input(bump_node, "Height");
364                 bNodeSocket *bump_output_socket = ntree_shader_node_find_output(bump_node, "Normal");
365                 BLI_assert(bump_input_socket != NULL);
366                 BLI_assert(bump_output_socket != NULL);
367                 nodeAddLink(group_ntree,
368                             group_displacement_node, group_displacement_socket,
369                             bump_node, bump_input_socket);
370                 /* Relink normals inside of the instanced tree. */
371                 ntree_shader_link_builtin_normal(group_ntree,
372                                                  bump_node,
373                                                  bump_output_socket,
374                                                  group_displacement_node,
375                                                  group_displacement_socket);
376                 ntreeUpdateTree(G.main, group_ntree);
377         }
378         else if (group_input_node) {
379                 /* Connect group node normal input. */
380                 nodeAddLink(ntree,
381                             node_from, socket_from,
382                             group_node, group_node_normal_socket);
383                 BLI_assert(group_input_node != NULL);
384                 bNodeSocket *group_input_node_normal_socket =
385                         nodeFindSocket(group_input_node,
386                                        SOCK_OUT,
387                                        group_normal_socket->identifier);
388                 BLI_assert(group_input_node_normal_socket != NULL);
389                 /* Relink normals inside of the instanced tree. */
390                 ntree_shader_link_builtin_normal(group_ntree,
391                                                  group_input_node,
392                                                  group_input_node_normal_socket,
393                                                  displacement_node,
394                                                  displacement_socket);
395                 ntreeUpdateTree(G.main, group_ntree);
396         }
397 }
398
399 /* Use specified node and socket as an input for unconnected normal sockets. */
400 static void ntree_shader_link_builtin_normal(bNodeTree *ntree,
401                                              bNode *node_from,
402                                              bNodeSocket *socket_from,
403                                              bNode *displacement_node,
404                                              bNodeSocket *displacement_socket)
405 {
406         for (bNode *node = ntree->nodes.first; node != NULL; node = node->next) {
407                 if (node == node_from) {
408                         /* Don't connect node itself! */
409                         continue;
410                 }
411                 if (node->type == NODE_GROUP && node->id) {
412                         /* Special re-linking for group nodes. */
413                         ntree_shader_link_builtin_group_normal(ntree,
414                                                                node,
415                                                                node_from,
416                                                                socket_from,
417                                                                displacement_node,
418                                                                displacement_socket);
419                         continue;
420                 }
421                 if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) {
422                         /* Group inputs and outputs needs nothing special. */
423                         continue;
424                 }
425                 ntree_shader_relink_node_normal(ntree, node, node_from, socket_from);
426         }
427 }
428
429 /* Re-link displacement output to unconnected normal sockets via bump node.
430  * This way material with have proper displacement in the viewport.
431  */
432 static void ntree_shader_relink_displacement(bNodeTree *ntree,
433                                              short compatibility)
434 {
435         if (compatibility != NODE_NEW_SHADING) {
436                 /* We can only deal with new shading system here. */
437                 return;
438         }
439         bNode *displacement_node;
440         bNodeSocket *displacement_socket;
441         bNodeLink *displacement_link;
442         if (!ntree_shader_has_displacement(ntree,
443                                            &displacement_node,
444                                            &displacement_socket,
445                                            &displacement_link))
446         {
447                 /* There is no displacement output connected, nothing to re-link. */
448                 return;
449         }
450         /* We have to disconnect displacement output socket, otherwise we'll have
451          * cycles in the Cycles material :)
452          */
453         nodeRemLink(ntree, displacement_link);
454         /* We can't connect displacement to normal directly, use bump node for that
455          * and hope that it gives good enough approximation.
456          */
457         bNode *bump_node = nodeAddStaticNode(NULL, ntree, SH_NODE_BUMP);
458         bNodeSocket *bump_input_socket = ntree_shader_node_find_input(bump_node, "Height");
459         bNodeSocket *bump_output_socket = ntree_shader_node_find_output(bump_node, "Normal");
460         BLI_assert(bump_input_socket != NULL);
461         BLI_assert(bump_output_socket != NULL);
462         /* Connect bump node to where displacement output was originally
463          * connected to.
464          */
465         nodeAddLink(ntree,
466                     displacement_node, displacement_socket,
467                     bump_node, bump_input_socket);
468         /* Connect all free-standing Normal inputs. */
469         ntree_shader_link_builtin_normal(ntree,
470                                          bump_node,
471                                          bump_output_socket,
472                                          displacement_node,
473                                          displacement_socket);
474         /* TODO(sergey): Reconnect Geometry Info->Normal sockets to the new
475          * bump node.
476          */
477         /* We modified the tree, it needs to be updated now. */
478         ntreeUpdateTree(G.main, ntree);
479 }
480
481 static bool ntree_tag_ssr_bsdf_cb(bNode *fromnode, bNode *UNUSED(tonode), void *userdata, const bool UNUSED(reversed))
482 {
483         switch (fromnode->type) {
484                 case SH_NODE_BSDF_ANISOTROPIC:
485                 case SH_NODE_EEVEE_SPECULAR:
486                 case SH_NODE_BSDF_PRINCIPLED:
487                 case SH_NODE_BSDF_GLOSSY:
488                 case SH_NODE_BSDF_GLASS:
489                         fromnode->ssr_id = (*(float *)userdata);
490                         (*(float *)userdata) += 1;
491                         break;
492                 default:
493                         /* We could return false here but since we (will)
494                          * allow the use of Closure as RGBA, we can have
495                          * Bsdf nodes linked to other Bsdf nodes. */
496                         break;
497         }
498
499         return true;
500 }
501
502 /* EEVEE: Scan the ntree to set the Screen Space Reflection
503  * layer id of every specular node.
504  */
505 static void ntree_shader_tag_ssr_node(bNodeTree *ntree, short compatibility)
506 {
507         if (compatibility != NODE_NEWER_SHADING) {
508                 /* We can only deal with new shading system here. */
509                 return;
510         }
511
512         bNode *output_node = ntree_shader_output_node(ntree);
513         if (output_node == NULL) {
514                 return;
515         }
516         /* Make sure sockets links pointers are correct. */
517         ntreeUpdateTree(G.main, ntree);
518
519         int lobe_count = 0;
520         nodeChainIter(ntree, output_node, ntree_tag_ssr_bsdf_cb, &lobe_count, true);
521 }
522
523 void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat, short compatibility)
524 {
525         /* localize tree to create links for reroute and mute */
526         bNodeTree *localtree = ntreeLocalize(ntree);
527         bNodeTreeExec *exec;
528
529         /* Perform all needed modifications on the tree in order to support
530          * displacement/bump mapping.
531          */
532         ntree_shader_relink_displacement(localtree, compatibility);
533
534         ntree_shader_tag_ssr_node(localtree, compatibility);
535
536         exec = ntreeShaderBeginExecTree(localtree);
537         ntreeExecGPUNodes(exec, mat, 1, compatibility);
538         ntreeShaderEndExecTree(exec);
539
540         ntreeFreeTree(localtree);
541         MEM_freeN(localtree);
542 }
543
544 /* **************** call to switch lamploop for material node ************ */
545
546 void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *);
547
548 void set_node_shader_lamp_loop(void (*lamp_loop_func)(ShadeInput *, ShadeResult *))
549 {
550         node_shader_lamp_loop = lamp_loop_func;
551 }
552
553
554 bNodeTreeExec *ntreeShaderBeginExecTree_internal(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key)
555 {
556         bNodeTreeExec *exec;
557         bNode *node;
558         
559         /* ensures only a single output node is enabled */
560         ntreeSetOutput(ntree);
561         
562         /* common base initialization */
563         exec = ntree_exec_begin(context, ntree, parent_key);
564         
565         /* allocate the thread stack listbase array */
566         exec->threadstack = MEM_callocN(BLENDER_MAX_THREADS * sizeof(ListBase), "thread stack array");
567         
568         for (node = exec->nodetree->nodes.first; node; node = node->next)
569                 node->need_exec = 1;
570         
571         return exec;
572 }
573
574 bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree)
575 {
576         bNodeExecContext context;
577         bNodeTreeExec *exec;
578         
579         /* XXX hack: prevent exec data from being generated twice.
580          * this should be handled by the renderer!
581          */
582         if (ntree->execdata)
583                 return ntree->execdata;
584         
585         context.previews = ntree->previews;
586         
587         exec = ntreeShaderBeginExecTree_internal(&context, ntree, NODE_INSTANCE_KEY_BASE);
588         
589         /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
590          * which only store the ntree pointer. Should be fixed at some point!
591          */
592         ntree->execdata = exec;
593         
594         return exec;
595 }
596
597 void ntreeShaderEndExecTree_internal(bNodeTreeExec *exec)
598 {
599         bNodeThreadStack *nts;
600         int a;
601         
602         if (exec->threadstack) {
603                 for (a = 0; a < BLENDER_MAX_THREADS; a++) {
604                         for (nts = exec->threadstack[a].first; nts; nts = nts->next)
605                                 if (nts->stack) MEM_freeN(nts->stack);
606                         BLI_freelistN(&exec->threadstack[a]);
607                 }
608                 
609                 MEM_freeN(exec->threadstack);
610                 exec->threadstack = NULL;
611         }
612         
613         ntree_exec_end(exec);
614 }
615
616 void ntreeShaderEndExecTree(bNodeTreeExec *exec)
617 {
618         if (exec) {
619                 /* exec may get freed, so assign ntree */
620                 bNodeTree *ntree = exec->nodetree;
621                 ntreeShaderEndExecTree_internal(exec);
622                 
623                 /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
624                 ntree->execdata = NULL;
625         }
626 }
627
628 /* only for Blender internal */
629 bool ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr)
630 {
631         ShaderCallData scd;
632         /**
633          * \note: preserve material from ShadeInput for material id, nodetree execs change it
634          * fix for bug "[#28012] Mat ID messy with shader nodes"
635          */
636         Material *mat = shi->mat;
637         bNodeThreadStack *nts = NULL;
638         bNodeTreeExec *exec = ntree->execdata;
639         int compat;
640         
641         /* convert caller data to struct */
642         scd.shi = shi;
643         scd.shr = shr;
644         
645         /* each material node has own local shaderesult, with optional copying */
646         memset(shr, 0, sizeof(ShadeResult));
647         
648         /* ensure execdata is only initialized once */
649         if (!exec) {
650                 BLI_lock_thread(LOCK_NODES);
651                 if (!ntree->execdata)
652                         ntree->execdata = ntreeShaderBeginExecTree(ntree);
653                 BLI_unlock_thread(LOCK_NODES);
654
655                 exec = ntree->execdata;
656         }
657         
658         nts = ntreeGetThreadStack(exec, shi->thread);
659         compat = ntreeExecThreadNodes(exec, nts, &scd, shi->thread);
660         ntreeReleaseThreadStack(nts);
661         
662         // \note: set material back to preserved material
663         shi->mat = mat;
664                 
665         /* better not allow negative for now */
666         if (shr->combined[0] < 0.0f) shr->combined[0] = 0.0f;
667         if (shr->combined[1] < 0.0f) shr->combined[1] = 0.0f;
668         if (shr->combined[2] < 0.0f) shr->combined[2] = 0.0f;
669         
670         /* if compat is zero, it has been using non-compatible nodes */
671         return compat;
672 }