Integer socket support in Cycles. Int values are already supported natively in OSL...
[blender.git] / intern / cycles / kernel / svm / svm_closure.h
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 CCL_NAMESPACE_BEGIN
20
21 /* Closure Nodes */
22
23 __device void svm_node_glossy_setup(ShaderData *sd, ShaderClosure *sc, int type, float eta, float roughness, bool refract)
24 {
25         if(type == CLOSURE_BSDF_REFRACTION_ID) {
26                 if(refract) {
27                         sc->data0 = eta;
28                         sd->flag |= bsdf_refraction_setup(sc);
29                 }
30                 else
31                         sd->flag |= bsdf_reflection_setup(sc);
32         }
33         else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) {
34                 sc->data0 = roughness;
35                 sc->data1 = eta;
36
37                 if(refract)
38                         sd->flag |= bsdf_microfacet_beckmann_refraction_setup(sc);
39                 else
40                         sd->flag |= bsdf_microfacet_beckmann_setup(sc);
41         }
42         else {
43                 sc->data0 = roughness;
44                 sc->data1 = eta;
45
46                 if(refract)
47                         sd->flag |= bsdf_microfacet_ggx_refraction_setup(sc);
48                 else
49                         sd->flag |= bsdf_microfacet_ggx_setup(sc);
50         }
51 }
52
53 __device_inline ShaderClosure *svm_node_closure_get(ShaderData *sd)
54 {
55 #ifdef __MULTI_CLOSURE__
56         ShaderClosure *sc = &sd->closure[sd->num_closure];
57
58         if(sd->num_closure < MAX_CLOSURE)
59                 sd->num_closure++;
60
61         return sc;
62 #else
63         return &sd->closure;
64 #endif
65 }
66
67 __device_inline void svm_node_closure_set_mix_weight(ShaderClosure *sc, float mix_weight)
68 {
69 #ifdef __MULTI_CLOSURE__
70         sc->weight *= mix_weight;
71         sc->sample_weight = fabsf(average(sc->weight));
72 #endif
73 }
74
75 __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, float randb, int path_flag, int *offset)
76 {
77         uint type, param1_offset, param2_offset;
78
79 #ifdef __MULTI_CLOSURE__
80         uint mix_weight_offset;
81         decode_node_uchar4(node.y, &type, &param1_offset, &param2_offset, &mix_weight_offset);
82         float mix_weight = (stack_valid(mix_weight_offset)? stack_load_float(stack, mix_weight_offset): 1.0f);
83
84         /* note we read this extra node before weight check, so offset is added */
85         uint4 data_node = read_node(kg, offset);
86
87         if(mix_weight == 0.0f)
88                 return;
89
90         float3 N = stack_valid(data_node.y)? stack_load_float3(stack, data_node.y): sd->N; 
91 #else
92         decode_node_uchar4(node.y, &type, &param1_offset, &param2_offset, NULL);
93         float mix_weight = 1.0f;
94
95         uint4 data_node = read_node(kg, offset);
96         float3 N = stack_valid(data_node.y)? stack_load_float3(stack, data_node.y): sd->N; 
97 #endif
98
99         float param1 = (stack_valid(param1_offset))? stack_load_float(stack, param1_offset): __int_as_float(node.z);
100         float param2 = (stack_valid(param2_offset))? stack_load_float(stack, param2_offset): __int_as_float(node.w);
101
102         switch(type) {
103                 case CLOSURE_BSDF_DIFFUSE_ID: {
104                         ShaderClosure *sc = svm_node_closure_get(sd);
105                         sc->N = N;
106                         svm_node_closure_set_mix_weight(sc, mix_weight);
107
108                         float roughness = param1;
109
110                         if(roughness == 0.0f) {
111                                 sd->flag |= bsdf_diffuse_setup(sc);
112                         }
113                         else {
114                                 sc->data0 = roughness;
115                                 sd->flag |= bsdf_oren_nayar_setup(sc);
116                         }
117                         break;
118                 }
119                 case CLOSURE_BSDF_TRANSLUCENT_ID: {
120                         ShaderClosure *sc = svm_node_closure_get(sd);
121                         sc->N = N;
122                         svm_node_closure_set_mix_weight(sc, mix_weight);
123                         sd->flag |= bsdf_translucent_setup(sc);
124                         break;
125                 }
126                 case CLOSURE_BSDF_TRANSPARENT_ID: {
127                         ShaderClosure *sc = svm_node_closure_get(sd);
128                         sc->N = N;
129                         svm_node_closure_set_mix_weight(sc, mix_weight);
130                         sd->flag |= bsdf_transparent_setup(sc);
131                         break;
132                 }
133                 case CLOSURE_BSDF_REFLECTION_ID:
134                 case CLOSURE_BSDF_MICROFACET_GGX_ID:
135                 case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: {
136 #ifdef __CAUSTICS_TRICKS__
137                         if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
138                                 break;
139 #endif
140                         ShaderClosure *sc = svm_node_closure_get(sd);
141                         sc->N = N;
142                         sc->data0 = param1;
143                         svm_node_closure_set_mix_weight(sc, mix_weight);
144
145                         /* setup bsdf */
146                         if(type == CLOSURE_BSDF_REFLECTION_ID)
147                                 sd->flag |= bsdf_reflection_setup(sc);
148                         else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID)
149                                 sd->flag |= bsdf_microfacet_beckmann_setup(sc);
150                         else
151                                 sd->flag |= bsdf_microfacet_ggx_setup(sc);
152
153                         break;
154                 }
155                 case CLOSURE_BSDF_REFRACTION_ID:
156                 case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
157                 case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: {
158 #ifdef __CAUSTICS_TRICKS__
159                         if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
160                                 break;
161 #endif
162                         /* index of refraction */
163                         float eta = fmaxf(param2, 1.0f + 1e-5f);
164                         eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
165
166                         /* fresnel */
167                         float cosNO = dot(N, sd->I);
168                         float fresnel = fresnel_dielectric_cos(cosNO, eta);
169                         float roughness = param1;
170
171 #ifdef __MULTI_CLOSURE__
172                         /* reflection */
173                         ShaderClosure *sc = svm_node_closure_get(sd);
174                         sc->N = N;
175
176                         float3 weight = sc->weight;
177                         float sample_weight = sc->sample_weight;
178
179                         svm_node_closure_set_mix_weight(sc, mix_weight*fresnel);
180                         svm_node_glossy_setup(sd, sc, type, eta, roughness, false);
181
182                         /* refraction */
183                         sc = svm_node_closure_get(sd);
184                         sc->N = N;
185
186                         sc->weight = weight;
187                         sc->sample_weight = sample_weight;
188
189                         svm_node_closure_set_mix_weight(sc, mix_weight*(1.0f - fresnel));
190                         svm_node_glossy_setup(sd, sc, type, eta, roughness, true);
191 #else
192                         ShaderClosure *sc = svm_node_closure_get(sd);
193                         sc->N = N;
194
195                         bool refract = (randb > fresnel);
196
197                         svm_node_closure_set_mix_weight(sc, mix_weight);
198                         svm_node_glossy_setup(sd, sc, type, eta, roughness, refract);
199 #endif
200
201                         break;
202                 }
203 #ifdef __DPDU__
204                 case CLOSURE_BSDF_WARD_ID: {
205 #ifdef __CAUSTICS_TRICKS__
206                         if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
207                                 break;
208 #endif
209                         ShaderClosure *sc = svm_node_closure_get(sd);
210                         sc->N = N;
211                         sc->T = stack_load_float3(stack, data_node.z);
212                         svm_node_closure_set_mix_weight(sc, mix_weight);
213
214                         sc->data0 = param1;
215                         sc->data1 = param2;
216
217                         sd->flag |= bsdf_ward_setup(sc);
218                         break;
219                 }
220 #endif
221                 case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: {
222                         ShaderClosure *sc = svm_node_closure_get(sd);
223                         sc->N = N;
224                         svm_node_closure_set_mix_weight(sc, mix_weight);
225
226                         /* sigma */
227                         sc->data0 = clamp(param1, 0.0f, 1.0f);
228                         sd->flag |= bsdf_ashikhmin_velvet_setup(sc);
229                         break;
230                 }
231                 default:
232                         break;
233         }
234 }
235
236 __device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int path_flag)
237 {
238         uint type, param1_offset, param2_offset;
239
240 #ifdef __MULTI_CLOSURE__
241         uint mix_weight_offset;
242         decode_node_uchar4(node.y, &type, &param1_offset, &param2_offset, &mix_weight_offset);
243         float mix_weight = (stack_valid(mix_weight_offset)? stack_load_float(stack, mix_weight_offset): 1.0f);
244
245         if(mix_weight == 0.0f)
246                 return;
247 #else
248         decode_node_uchar4(node.y, &type, &param1_offset, &param2_offset, NULL);
249         float mix_weight = 1.0f;
250 #endif
251
252         float param1 = (stack_valid(param1_offset))? stack_load_float(stack, param1_offset): __int_as_float(node.z);
253         //float param2 = (stack_valid(param2_offset))? stack_load_float(stack, param2_offset): __int_as_float(node.w);
254
255         switch(type) {
256                 case CLOSURE_VOLUME_TRANSPARENT_ID: {
257                         ShaderClosure *sc = svm_node_closure_get(sd);
258                         svm_node_closure_set_mix_weight(sc, mix_weight);
259
260                         float density = param1;
261                         sd->flag |= volume_transparent_setup(sc, density);
262                         break;
263                 }
264                 case CLOSURE_VOLUME_ISOTROPIC_ID: {
265                         ShaderClosure *sc = svm_node_closure_get(sd);
266                         svm_node_closure_set_mix_weight(sc, mix_weight);
267
268                         float density = param1;
269                         sd->flag |= volume_isotropic_setup(sc, density);
270                         break;
271                 }
272                 default:
273                         break;
274         }
275 }
276
277 __device void svm_node_closure_emission(ShaderData *sd, float *stack, uint4 node)
278 {
279 #ifdef __MULTI_CLOSURE__
280         uint mix_weight_offset = node.y;
281
282         if(stack_valid(mix_weight_offset)) {
283                 float mix_weight = stack_load_float(stack, mix_weight_offset);
284
285                 if(mix_weight == 0.0f)
286                         return;
287
288                 ShaderClosure *sc = svm_node_closure_get(sd);
289                 sc->weight *= mix_weight;
290                 sc->type = CLOSURE_EMISSION_ID;
291         }
292         else {
293                 ShaderClosure *sc = svm_node_closure_get(sd);
294                 sc->type = CLOSURE_EMISSION_ID;
295         }
296
297 #else
298         ShaderClosure *sc = &sd->closure;
299         sc->type = CLOSURE_EMISSION_ID;
300 #endif
301
302         sd->flag |= SD_EMISSION;
303 }
304
305 __device void svm_node_closure_background(ShaderData *sd, float *stack, uint4 node)
306 {
307 #ifdef __MULTI_CLOSURE__
308         uint mix_weight_offset = node.y;
309
310         if(stack_valid(mix_weight_offset)) {
311                 float mix_weight = stack_load_float(stack, mix_weight_offset);
312
313                 if(mix_weight == 0.0f)
314                         return;
315
316                 ShaderClosure *sc = svm_node_closure_get(sd);
317                 sc->weight *= mix_weight;
318                 sc->type = CLOSURE_BACKGROUND_ID;
319         }
320         else {
321                 ShaderClosure *sc = svm_node_closure_get(sd);
322                 sc->type = CLOSURE_BACKGROUND_ID;
323         }
324
325 #else
326         ShaderClosure *sc = &sd->closure;
327         sc->type = CLOSURE_BACKGROUND_ID;
328 #endif
329 }
330
331 __device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 node)
332 {
333 #ifdef __MULTI_CLOSURE__
334         uint mix_weight_offset = node.y;
335
336         if(stack_valid(mix_weight_offset)) {
337                 float mix_weight = stack_load_float(stack, mix_weight_offset);
338
339                 if(mix_weight == 0.0f)
340                         return;
341
342                 ShaderClosure *sc = svm_node_closure_get(sd);
343                 sc->weight = make_float3(mix_weight, mix_weight, mix_weight);
344                 sc->type = CLOSURE_HOLDOUT_ID;
345         }
346         else {
347                 ShaderClosure *sc = svm_node_closure_get(sd);
348                 sc->weight = make_float3(1.0f, 1.0f, 1.0f);
349                 sc->type = CLOSURE_HOLDOUT_ID;
350         }
351 #else
352         ShaderClosure *sc = &sd->closure;
353         sc->type = CLOSURE_HOLDOUT_ID;
354 #endif
355
356         sd->flag |= SD_HOLDOUT;
357 }
358
359 /* Closure Nodes */
360
361 __device_inline void svm_node_closure_store_weight(ShaderData *sd, float3 weight)
362 {
363 #ifdef __MULTI_CLOSURE__
364         sd->closure[sd->num_closure].weight = weight;
365 #else
366         sd->closure.weight = weight;
367 #endif
368 }
369
370 __device void svm_node_closure_set_weight(ShaderData *sd, uint r, uint g, uint b)
371 {
372         float3 weight = make_float3(__int_as_float(r), __int_as_float(g), __int_as_float(b));
373         svm_node_closure_store_weight(sd, weight);
374 }
375
376 __device void svm_node_emission_set_weight_total(KernelGlobals *kg, ShaderData *sd, uint r, uint g, uint b)
377 {
378         float3 weight = make_float3(__int_as_float(r), __int_as_float(g), __int_as_float(b));
379
380         if(sd->object != ~0)
381                 weight /= object_surface_area(kg, sd->object);
382
383         svm_node_closure_store_weight(sd, weight);
384 }
385
386 __device void svm_node_closure_weight(ShaderData *sd, float *stack, uint weight_offset)
387 {
388         float3 weight = stack_load_float3(stack, weight_offset);
389
390         svm_node_closure_store_weight(sd, weight);
391 }
392
393 __device void svm_node_emission_weight(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
394 {
395         uint color_offset = node.y;
396         uint strength_offset = node.z;
397         uint total_power = node.w;
398
399         float strength = stack_load_float(stack, strength_offset);
400         float3 weight = stack_load_float3(stack, color_offset)*strength;
401
402         if(total_power && sd->object != ~0)
403                 weight /= object_surface_area(kg, sd->object);
404
405         svm_node_closure_store_weight(sd, weight);
406 }
407
408 __device void svm_node_mix_closure(ShaderData *sd, float *stack,
409         uint4 node, int *offset, float *randb)
410 {
411 #ifdef __MULTI_CLOSURE__
412         /* fetch weight from blend input, previous mix closures,
413          * and write to stack to be used by closure nodes later */
414         uint weight_offset, in_weight_offset, weight1_offset, weight2_offset;
415         decode_node_uchar4(node.y, &weight_offset, &in_weight_offset, &weight1_offset, &weight2_offset);
416
417         float weight = stack_load_float(stack, weight_offset);
418         float in_weight = (stack_valid(in_weight_offset))? stack_load_float(stack, in_weight_offset): 1.0f;
419
420         if(stack_valid(weight1_offset))
421                 stack_store_float(stack, weight1_offset, in_weight*(1.0f - weight));
422         if(stack_valid(weight2_offset))
423                 stack_store_float(stack, weight2_offset, in_weight*weight);
424 #else
425         /* pick a closure and make the random number uniform over 0..1 again.
426          * closure 1 starts on the next node, for closure 2 the start is at an
427          * offset from the current node, so we jump */
428         uint weight_offset = node.y;
429         uint node_jump = node.z;
430         float weight = stack_load_float(stack, weight_offset);
431         weight = clamp(weight, 0.0f, 1.0f);
432
433         if(*randb < weight) {
434                 *offset += node_jump;
435                 *randb = *randb/weight;
436         }
437         else
438                 *randb = (*randb - weight)/(1.0f - weight);
439 #endif
440 }
441
442 __device void svm_node_add_closure(ShaderData *sd, float *stack, uint unused,
443         uint node_jump, int *offset, float *randb, float *closure_weight)
444 {
445 #ifdef __MULTI_CLOSURE__
446         /* nothing to do, handled in compiler */
447 #else
448         /* pick one of the two closures with probability 0.5. sampling quality
449          * is not going to be great, for that we'd need to evaluate the weights
450          * of the two closures being added */
451         float weight = 0.5f;
452
453         if(*randb < weight) {
454                 *offset += node_jump;
455                 *randb = *randb/weight;
456         }
457         else
458                 *randb = (*randb - weight)/(1.0f - weight);
459         
460         *closure_weight *= 2.0f;
461 #endif
462 }
463
464 /* (Bump) normal */
465
466 __device void svm_node_set_normal(KernelGlobals *kg, ShaderData *sd, float *stack, uint in_direction, uint out_normal)
467 {
468         float3 normal = stack_load_float3(stack, in_direction);
469         sd->N = normal;
470         stack_store_float3(stack, out_normal, normal);
471 }
472
473 CCL_NAMESPACE_END
474