Merge branch 'master' into blender2.8
[blender.git] / source / blender / nodes / shader / node_shader_util.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) 2005 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/nodes/shader/node_shader_util.c
29  *  \ingroup nodes
30  */
31
32
33 #include "DNA_node_types.h"
34
35 #include "node_shader_util.h"
36
37 #include "node_exec.h"
38
39
40 int sh_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree)
41 {
42         return STREQ(ntree->idname, "ShaderNodeTree");
43 }
44
45 void sh_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass, short flag)
46 {
47         node_type_base(ntype, type, name, nclass, flag);
48         
49         ntype->poll = sh_node_poll_default;
50         ntype->insert_link = node_insert_link_default;
51         ntype->update_internal_links = node_update_internal_links_default;
52 }
53
54 /* ****** */
55
56 void nodestack_get_vec(float *in, short type_in, bNodeStack *ns)
57 {
58         const float *from = ns->vec;
59                 
60         if (type_in == SOCK_FLOAT) {
61                 if (ns->sockettype == SOCK_FLOAT)
62                         *in = *from;
63                 else 
64                         *in = (from[0] + from[1] + from[2]) / 3.0f;
65         }
66         else if (type_in == SOCK_VECTOR) {
67                 if (ns->sockettype == SOCK_FLOAT) {
68                         in[0] = from[0];
69                         in[1] = from[0];
70                         in[2] = from[0];
71                 }
72                 else {
73                         copy_v3_v3(in, from);
74                 }
75         }
76         else { /* type_in==SOCK_RGBA */
77                 if (ns->sockettype == SOCK_RGBA) {
78                         copy_v4_v4(in, from);
79                 }
80                 else if (ns->sockettype == SOCK_FLOAT) {
81                         in[0] = from[0];
82                         in[1] = from[0];
83                         in[2] = from[0];
84                         in[3] = 1.0f;
85                 }
86                 else {
87                         copy_v3_v3(in, from);
88                         in[3] = 1.0f;
89                 }
90         }
91 }
92
93
94 /* go over all used Geometry and Texture nodes, and return a texco flag */
95 /* no group inside needed, this function is called for groups too */
96 void ntreeShaderGetTexcoMode(bNodeTree *ntree, int r_mode, short *texco, int *mode)
97 {
98         bNode *node;
99         bNodeSocket *sock;
100         int a;
101         
102         for (node = ntree->nodes.first; node; node = node->next) {
103                 if (node->type == SH_NODE_TEXTURE) {
104                         if ((r_mode & R_OSA) && node->id) {
105                                 Tex *tex = (Tex *)node->id;
106                                 if (ELEM(tex->type, TEX_IMAGE, TEX_ENVMAP)) {
107                                         *texco |= TEXCO_OSA | NEED_UV;
108                                 }
109                         }
110                         /* usability exception... without input we still give the node orcos */
111                         sock = node->inputs.first;
112                         if (sock == NULL || sock->link == NULL)
113                                 *texco |= TEXCO_ORCO | NEED_UV;
114                 }
115                 else if (node->type == SH_NODE_GEOMETRY) {
116                         /* note; sockets always exist for the given type! */
117                         for (a = 0, sock = node->outputs.first; sock; sock = sock->next, a++) {
118                                 if (sock->flag & SOCK_IN_USE) {
119                                         switch (a) {
120                                                 case GEOM_OUT_GLOB: 
121                                                         *texco |= TEXCO_GLOB | NEED_UV; break;
122                                                 case GEOM_OUT_VIEW: 
123                                                         *texco |= TEXCO_VIEW | NEED_UV; break;
124                                                 case GEOM_OUT_ORCO: 
125                                                         *texco |= TEXCO_ORCO | NEED_UV; break;
126                                                 case GEOM_OUT_UV: 
127                                                         *texco |= TEXCO_UV | NEED_UV; break;
128                                                 case GEOM_OUT_NORMAL: 
129                                                         *texco |= TEXCO_NORM | NEED_UV; break;
130                                                 case GEOM_OUT_VCOL:
131                                                         *texco |= NEED_UV; *mode |= MA_VERTEXCOL; break;
132                                                 case GEOM_OUT_VCOL_ALPHA:
133                                                         *texco |= NEED_UV; *mode |= MA_VERTEXCOL; break;
134                                         }
135                                 }
136                         }
137                 }
138         }
139 }
140
141 void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, bNodeStack *ns)
142 {
143         memset(gs, 0, sizeof(*gs));
144         
145         if (ns == NULL) {
146                 /* node_get_stack() will generate NULL bNodeStack pointers for unknown/unsuported types of sockets... */
147                 zero_v4(gs->vec);
148                 gs->link = NULL;
149                 gs->type = GPU_NONE;
150                 gs->name = "";
151                 gs->hasinput = false;
152                 gs->hasoutput = false;
153                 gs->sockettype = type;
154         }
155         else {
156                 nodestack_get_vec(gs->vec, type, ns);
157                 gs->link = ns->data;
158         
159                 if (type == SOCK_FLOAT)
160                         gs->type = GPU_FLOAT;
161                 else if (type == SOCK_VECTOR)
162                         gs->type = GPU_VEC3;
163                 else if (type == SOCK_RGBA)
164                         gs->type = GPU_VEC4;
165                 else if (type == SOCK_SHADER)
166                         gs->type = GPU_CLOSURE;
167                 else
168                         gs->type = GPU_NONE;
169
170                 gs->name = "";
171                 gs->hasinput = ns->hasinput && ns->data;
172                 /* XXX Commented out the ns->data check here, as it seems it's not always set,
173                  *     even though there *is* a valid connection/output... But that might need
174                  *     further investigation.
175                  */
176                 gs->hasoutput = ns->hasoutput /*&& ns->data*/;
177                 gs->sockettype = ns->sockettype;
178         }
179 }
180
181 void node_data_from_gpu_stack(bNodeStack *ns, GPUNodeStack *gs)
182 {
183         copy_v4_v4(ns->vec, gs->vec);
184         ns->data = gs->link;
185         ns->sockettype = gs->sockettype;
186 }
187
188 static void gpu_stack_from_data_list(GPUNodeStack *gs, ListBase *sockets, bNodeStack **ns)
189 {
190         bNodeSocket *sock;
191         int i;
192         
193         for (sock = sockets->first, i = 0; sock; sock = sock->next, i++)
194                 node_gpu_stack_from_data(&gs[i], sock->type, ns[i]);
195         
196         gs[i].type = GPU_NONE;
197 }
198
199 static void data_from_gpu_stack_list(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs)
200 {
201         bNodeSocket *sock;
202         int i;
203
204         for (sock = sockets->first, i = 0; sock; sock = sock->next, i++)
205                 node_data_from_gpu_stack(ns[i], &gs[i]);
206 }
207
208 bNode *nodeGetActiveTexture(bNodeTree *ntree)
209 {
210         /* this is the node we texture paint and draw in textured draw */
211         bNode *node, *tnode, *inactivenode = NULL, *activetexnode = NULL, *activegroup = NULL;
212         bool hasgroup = false;
213
214         if (!ntree)
215                 return NULL;
216
217         for (node = ntree->nodes.first; node; node = node->next) {
218                 if (node->flag & NODE_ACTIVE_TEXTURE) {
219                         activetexnode = node;
220                         /* if active we can return immediately */
221                         if (node->flag & NODE_ACTIVE)
222                                 return node;
223                 }
224                 else if (!inactivenode && node->typeinfo->nclass == NODE_CLASS_TEXTURE)
225                         inactivenode = node;
226                 else if (node->type == NODE_GROUP) {
227                         if (node->flag & NODE_ACTIVE)
228                                 activegroup = node;
229                         else
230                                 hasgroup = true;
231                 }
232         }
233
234         /* first, check active group for textures */
235         if (activegroup) {
236                 tnode = nodeGetActiveTexture((bNodeTree *)activegroup->id);
237                 /* active node takes priority, so ignore any other possible nodes here */
238                 if (tnode)
239                         return tnode;
240         }
241
242         if (activetexnode)
243                 return activetexnode;
244         
245         if (hasgroup) {
246                 /* node active texture node in this tree, look inside groups */
247                 for (node = ntree->nodes.first; node; node = node->next) {
248                         if (node->type == NODE_GROUP) {
249                                 tnode = nodeGetActiveTexture((bNodeTree *)node->id);
250                                 if (tnode && ((tnode->flag & NODE_ACTIVE_TEXTURE) || !inactivenode))
251                                         return tnode;
252                         }
253                 }
254         }
255         
256         return inactivenode;
257 }
258
259 void ntreeExecGPUNodes(bNodeTreeExec *exec, GPUMaterial *mat, int do_outputs, short compatibility)
260 {
261         bNodeExec *nodeexec;
262         bNode *node;
263         int n;
264         bNodeStack *stack;
265         bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
266         bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
267         GPUNodeStack gpuin[MAX_SOCKET + 1], gpuout[MAX_SOCKET + 1];
268         bool do_it;
269
270         stack = exec->stack;
271
272         for (n = 0, nodeexec = exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
273                 node = nodeexec->node;
274                 
275                 do_it = false;
276                 /* for groups, only execute outputs for edited group */
277                 if (node->typeinfo->nclass == NODE_CLASS_OUTPUT) {
278                         if (node->typeinfo->compatibility & compatibility)
279                                 if (do_outputs && (node->flag & NODE_DO_OUTPUT))
280                                         do_it = true;
281                 }
282                 else {
283                         do_it = true;
284                 }
285
286                 if (do_it) {
287                         if (node->typeinfo->gpufunc) {
288                                 node_get_stack(node, stack, nsin, nsout);
289                                 gpu_stack_from_data_list(gpuin, &node->inputs, nsin);
290                                 gpu_stack_from_data_list(gpuout, &node->outputs, nsout);
291                                 if (node->typeinfo->gpufunc(mat, node, &nodeexec->data, gpuin, gpuout))
292                                         data_from_gpu_stack_list(&node->outputs, nsout, gpuout);
293                         }
294                 }
295         }
296 }
297
298 void node_shader_gpu_tex_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *UNUSED(out))
299 {
300         NodeTexBase *base = node->storage;
301         TexMapping *texmap = &base->tex_mapping;
302         float domin = (texmap->flag & TEXMAP_CLIP_MIN) != 0;
303         float domax = (texmap->flag & TEXMAP_CLIP_MAX) != 0;
304
305         if (domin || domax || !(texmap->flag & TEXMAP_UNIT_MATRIX)) {
306                 GPUNodeLink *tmat = GPU_uniform((float *)texmap->mat);
307                 GPUNodeLink *tmin = GPU_uniform(texmap->min);
308                 GPUNodeLink *tmax = GPU_uniform(texmap->max);
309                 GPUNodeLink *tdomin = GPU_uniform(&domin);
310                 GPUNodeLink *tdomax = GPU_uniform(&domax);
311
312                 GPU_link(mat, "mapping", in[0].link, tmat, tmin, tmax, tdomin, tdomax, &in[0].link);
313
314                 if (texmap->type == TEXMAP_TYPE_NORMAL)
315                         GPU_link(mat, "texco_norm", in[0].link, &in[0].link);
316         }
317 }
318