Merge branch 'master' into blender2.8
[blender.git] / source / blender / nodes / shader / nodes / node_shader_math.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/nodes/node_shader_math.c
29  *  \ingroup shdnodes
30  */
31
32
33 #include "node_shader_util.h"
34
35
36 /* **************** SCALAR MATH ******************** */
37 static bNodeSocketTemplate sh_node_math_in[] = {
38         { SOCK_FLOAT, 1, N_("Value"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE},
39         { SOCK_FLOAT, 1, N_("Value"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE},
40         { -1, 0, "" }
41 };
42
43 static bNodeSocketTemplate sh_node_math_out[] = {
44         { SOCK_FLOAT, 0, N_("Value")},
45         { -1, 0, "" }
46 };
47
48 static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
49 {
50         float a, b, r = 0.0f;
51
52         nodestack_get_vec(&a, SOCK_FLOAT, in[0]);
53         nodestack_get_vec(&b, SOCK_FLOAT, in[1]);
54
55         switch (node->custom1) {
56
57                 case NODE_MATH_ADD:
58                         r = a + b;
59                         break;
60                 case NODE_MATH_SUB:
61                         r = a - b;
62                         break;
63                 case NODE_MATH_MUL:
64                         r = a * b;
65                         break;
66                 case NODE_MATH_DIVIDE:
67                 {
68                         if (b == 0) /* We don't want to divide by zero. */
69                                 r = 0.0;
70                         else
71                                 r = a / b;
72                         break;
73                 }
74                 case NODE_MATH_SIN:
75                 {
76                         if (in[0]->hasinput || !in[1]->hasinput)  /* This one only takes one input, so we've got to choose. */
77                                 r = sinf(a);
78                         else
79                                 r = sinf(b);
80                         break;
81                 }
82                 case NODE_MATH_COS:
83                 {
84                         if (in[0]->hasinput || !in[1]->hasinput)  /* This one only takes one input, so we've got to choose. */
85                                 r = cosf(a);
86                         else
87                                 r = cosf(b);
88                         break;
89                 }
90                 case NODE_MATH_TAN:
91                 {
92                         if (in[0]->hasinput || !in[1]->hasinput)  /* This one only takes one input, so we've got to choose. */
93                                 r = tanf(a);
94                         else
95                                 r = tanf(b);
96                         break;
97                 }
98                 case NODE_MATH_ASIN:
99                 {
100                         if (in[0]->hasinput || !in[1]->hasinput) { /* This one only takes one input, so we've got to choose. */
101                                 /* Can't do the impossible... */
102                                 if (a <= 1 && a >= -1)
103                                         r = asinf(a);
104                                 else
105                                         r = 0.0;
106                         }
107                         else {
108                                 /* Can't do the impossible... */
109                                 if (b <= 1 && b >= -1)
110                                         r = asinf(b);
111                                 else
112                                         r = 0.0;
113                         }
114                         break;
115                 }
116                 case NODE_MATH_ACOS:
117                 {
118                         if (in[0]->hasinput || !in[1]->hasinput) { /* This one only takes one input, so we've got to choose. */
119                                 /* Can't do the impossible... */
120                                 if (a <= 1 && a >= -1)
121                                         r = acosf(a);
122                                 else
123                                         r = 0.0;
124                         }
125                         else {
126                                 /* Can't do the impossible... */
127                                 if (b <= 1 && b >= -1)
128                                         r = acosf(b);
129                                 else
130                                         r = 0.0;
131                         }
132                         break;
133                 }
134                 case NODE_MATH_ATAN:
135                 {
136                         if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
137                                 r = atan(a);
138                         else
139                                 r = atan(b);
140                         break;
141                 }
142                 case NODE_MATH_POW:
143                 {
144                         /* Only raise negative numbers by full integers */
145                         if (a >= 0) {
146                                 r = pow(a, b);
147                         }
148                         else {
149                                 float y_mod_1 = fabsf(fmodf(b, 1.0f));
150
151                                 /* if input value is not nearly an integer, fall back to zero, nicer than straight rounding */
152                                 if (y_mod_1 > 0.999f || y_mod_1 < 0.001f) {
153                                         r = powf(a, floorf(b + 0.5f));
154                                 }
155                                 else {
156                                         r = 0.0f;
157                                 }
158                         }
159
160                         break;
161                 }
162                 case NODE_MATH_LOG:
163                 {
164                         /* Don't want any imaginary numbers... */
165                         if (a > 0  && b > 0)
166                                 r = log(a) / log(b);
167                         else
168                                 r = 0.0;
169                         break;
170                 }
171                 case NODE_MATH_MIN:
172                 {
173                         if (a < b)
174                                 r = a;
175                         else
176                                 r = b;
177                         break;
178                 }
179                 case NODE_MATH_MAX:
180                 {
181                         if (a > b)
182                                 r = a;
183                         else
184                                 r = b;
185                         break;
186                 }
187                 case NODE_MATH_ROUND:
188                 {
189                         if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
190                                 r = (a < 0) ? (int)(a - 0.5f) : (int)(a + 0.5f);
191                         else
192                                 r = (b < 0) ? (int)(b - 0.5f) : (int)(b + 0.5f);
193                         break;
194                 }
195                 case NODE_MATH_LESS:
196                 {
197                         if (a < b)
198                                 r = 1.0f;
199                         else
200                                 r = 0.0f;
201                         break;
202                 }
203                 case NODE_MATH_GREATER:
204                 {
205                         if (a > b)
206                                 r = 1.0f;
207                         else
208                                 r = 0.0f;
209                         break;
210                 }
211                 case NODE_MATH_MOD:
212                 {
213                         if (b == 0.0f)
214                                 r = 0.0f;
215                         else
216                                 r = fmod(a, b);
217                         break;
218                 }
219                 case NODE_MATH_ABS:
220                 {
221                         r = fabsf(a);
222                         break;
223                 }
224                 case NODE_MATH_ATAN2:
225                 {
226                         r = atan2(a, b);
227                         break;
228                 }
229                 case NODE_MATH_FLOOR:
230                 {
231                         if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
232                                 r = floorf(a);
233                         else
234                                 r = floorf(b);
235                         break;
236                 }
237                 case NODE_MATH_CEIL:
238                 {
239                         if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
240                                 r = ceilf(a);
241                         else
242                                 r = ceilf(b);
243                         break;
244                 }
245                 case NODE_MATH_FRACT:
246                 {
247                         if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
248                                 r = a - floorf(a);
249                         else
250                                 r = b - floorf(b);
251                         break;
252                 }
253                 case NODE_MATH_SQRT:
254                 {
255                         if (in[0]->hasinput || !in[1]->hasinput) { /* This one only takes one input, so we've got to choose. */
256                                 if (a > 0)
257                                         r = sqrt(a);
258                                 else
259                                         r = 0.0;
260                         }
261                         else {
262                                 if (b > 0)
263                                         r = sqrt(b);
264                                 else
265                                         r = 0.0;
266                         }
267                         break;
268                 }
269         }
270         if (node->custom2 & SHD_MATH_CLAMP) {
271                 CLAMP(r, 0.0f, 1.0f);
272         }
273         out[0]->vec[0] = r;
274 }
275
276 static int gpu_shader_math(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
277 {
278         static const char *names[] = {
279             "math_add", "math_subtract", "math_multiply",
280             "math_divide", "math_sine", "math_cosine", "math_tangent", "math_asin",
281             "math_acos", "math_atan", "math_pow", "math_log", "math_min", "math_max",
282             "math_round", "math_less_than", "math_greater_than", "math_modulo", "math_abs",
283             "math_atan2", "math_floor", "math_ceil", "math_fract", "math_sqrt"
284         };
285
286         switch (node->custom1) {
287                 case NODE_MATH_ADD:
288                 case NODE_MATH_SUB:
289                 case NODE_MATH_MUL:
290                 case NODE_MATH_DIVIDE:
291                 case NODE_MATH_POW:
292                 case NODE_MATH_LOG:
293                 case NODE_MATH_MIN:
294                 case NODE_MATH_MAX:
295                 case NODE_MATH_LESS:
296                 case NODE_MATH_GREATER:
297                 case NODE_MATH_MOD:
298                 case NODE_MATH_ATAN2:
299                         GPU_stack_link(mat, node, names[node->custom1], in, out);
300                         break;
301                 case NODE_MATH_SIN:
302                 case NODE_MATH_COS:
303                 case NODE_MATH_TAN:
304                 case NODE_MATH_ASIN:
305                 case NODE_MATH_ACOS:
306                 case NODE_MATH_ATAN:
307                 case NODE_MATH_ROUND:
308                 case NODE_MATH_ABS:
309                 case NODE_MATH_FLOOR:
310                 case NODE_MATH_FRACT:
311                 case NODE_MATH_CEIL:
312                 case NODE_MATH_SQRT:
313                         if (in[0].hasinput || !in[1].hasinput) {
314                                 /* use only first item and terminator */
315                                 GPUNodeStack tmp_in[2];
316                                 memcpy(&tmp_in[0], &in[0], sizeof(GPUNodeStack));
317                                 memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack));
318                                 GPU_stack_link(mat, node, names[node->custom1], tmp_in, out);
319                         }
320                         else {
321                                 /* use only second item and terminator */
322                                 GPUNodeStack tmp_in[2];
323                                 memcpy(&tmp_in[0], &in[1], sizeof(GPUNodeStack));
324                                 memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack));
325                                 GPU_stack_link(mat, node, names[node->custom1], tmp_in, out);
326                         }
327                         break;
328                 default:
329                         return 0;
330         }
331
332         if (node->custom2 & SHD_MATH_CLAMP) {
333                 float min[3] = {0.0f, 0.0f, 0.0f};
334                 float max[3] = {1.0f, 1.0f, 1.0f};
335                 GPU_link(mat, "clamp_val", out[0].link, GPU_uniform(min), GPU_uniform(max), &out[0].link);
336         }
337
338         return 1;
339 }
340
341 void register_node_type_sh_math(void)
342 {
343         static bNodeType ntype;
344
345         sh_node_type_base(&ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, 0);
346         node_type_socket_templates(&ntype, sh_node_math_in, sh_node_math_out);
347         node_type_label(&ntype, node_math_label);
348         node_type_storage(&ntype, "", NULL, NULL);
349         node_type_exec(&ntype, NULL, NULL, node_shader_exec_math);
350         node_type_gpu(&ntype, gpu_shader_math);
351
352         nodeRegisterType(&ntype);
353 }