Cycles: Code cleanup, spaces around keywords
[blender-staging.git] / intern / cycles / kernel / svm / svm_closure.h
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 CCL_NAMESPACE_BEGIN
18
19 /* Closure Nodes */
20
21 ccl_device void svm_node_glass_setup(ShaderData *sd, ShaderClosure *sc, int type, float eta, float roughness, bool refract)
22 {
23         if(type == CLOSURE_BSDF_SHARP_GLASS_ID) {
24                 if(refract) {
25                         sc->data0 = eta;
26                         sc->data1 = 0.0f;
27                         sc->data2 = 0.0f;
28                         sd->flag |= bsdf_refraction_setup(sc);
29                 }
30                 else {
31                         sc->data0 = 0.0f;
32                         sc->data1 = 0.0f;
33                         sd->flag |= bsdf_reflection_setup(sc);
34                 }
35         }
36         else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID) {
37                 sc->data0 = roughness;
38                 sc->data1 = roughness;
39                 sc->data2 = eta;
40
41                 if(refract)
42                         sd->flag |= bsdf_microfacet_beckmann_refraction_setup(sc);
43                 else
44                         sd->flag |= bsdf_microfacet_beckmann_setup(sc);
45         }
46         else {
47                 sc->data0 = roughness;
48                 sc->data1 = roughness;
49                 sc->data2 = eta;
50
51                 if(refract)
52                         sd->flag |= bsdf_microfacet_ggx_refraction_setup(sc);
53                 else
54                         sd->flag |= bsdf_microfacet_ggx_setup(sc);
55         }
56 }
57
58 ccl_device_inline ShaderClosure *svm_node_closure_get_non_bsdf(ShaderData *sd, ClosureType type, float mix_weight)
59 {
60         ShaderClosure *sc = &sd->closure[sd->num_closure];
61
62         if(sd->num_closure < MAX_CLOSURE) {
63                 sc->weight *= mix_weight;
64                 sc->type = type;
65 #ifdef __OSL__
66                 sc->prim = NULL;
67 #endif
68                 sd->num_closure++;
69                 return sc;
70         }
71
72         return NULL;
73 }
74
75 ccl_device_inline ShaderClosure *svm_node_closure_get_bsdf(ShaderData *sd, float mix_weight)
76 {
77         ShaderClosure *sc = &sd->closure[sd->num_closure];
78         float3 weight = sc->weight * mix_weight;
79         float sample_weight = fabsf(average(weight));
80
81         if(sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure < MAX_CLOSURE) {
82                 sc->weight = weight;
83                 sc->sample_weight = sample_weight;
84                 sd->num_closure++;
85 #ifdef __OSL__
86                 sc->prim = NULL;
87 #endif
88                 return sc;
89         }
90
91         return NULL;
92 }
93
94 ccl_device_inline ShaderClosure *svm_node_closure_get_absorption(ShaderData *sd, float mix_weight)
95 {
96         ShaderClosure *sc = &sd->closure[sd->num_closure];
97         float3 weight = (make_float3(1.0f, 1.0f, 1.0f) - sc->weight) * mix_weight;
98         float sample_weight = fabsf(average(weight));
99
100         if(sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure < MAX_CLOSURE) {
101                 sc->weight = weight;
102                 sc->sample_weight = sample_weight;
103                 sd->num_closure++;
104 #ifdef __OSL__
105                 sc->prim = NULL;
106 #endif
107                 return sc;
108         }
109
110         return NULL;
111 }
112
113 ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int path_flag, int *offset)
114 {
115         uint type, param1_offset, param2_offset;
116
117         uint mix_weight_offset;
118         decode_node_uchar4(node.y, &type, &param1_offset, &param2_offset, &mix_weight_offset);
119         float mix_weight = (stack_valid(mix_weight_offset)? stack_load_float(stack, mix_weight_offset): 1.0f);
120
121         /* note we read this extra node before weight check, so offset is added */
122         uint4 data_node = read_node(kg, offset);
123
124         if(mix_weight == 0.0f)
125                 return;
126
127         float3 N = stack_valid(data_node.x)? stack_load_float3(stack, data_node.x): sd->N; 
128
129         float param1 = (stack_valid(param1_offset))? stack_load_float(stack, param1_offset): __uint_as_float(node.z);
130         float param2 = (stack_valid(param2_offset))? stack_load_float(stack, param2_offset): __uint_as_float(node.w);
131
132         switch(type) {
133                 case CLOSURE_BSDF_DIFFUSE_ID: {
134                         ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
135
136                         if(sc) {
137                                 sc->N = N;
138
139                                 float roughness = param1;
140
141                                 if(roughness == 0.0f) {
142                                         sc->data0 = 0.0f;
143                                         sc->data1 = 0.0f;
144                                         sc->data2 = 0.0f;
145                                         sd->flag |= bsdf_diffuse_setup(sc);
146                                 }
147                                 else {
148                                         sc->data0 = roughness;
149                                         sc->data1 = 0.0f;
150                                         sc->data2 = 0.0f;
151                                         sd->flag |= bsdf_oren_nayar_setup(sc);
152                                 }
153                         }
154                         break;
155                 }
156                 case CLOSURE_BSDF_TRANSLUCENT_ID: {
157                         ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
158
159                         if(sc) {
160                                 sc->data0 = 0.0f;
161                                 sc->data1 = 0.0f;
162                                 sc->data2 = 0.0f;
163                                 sc->N = N;
164                                 sd->flag |= bsdf_translucent_setup(sc);
165                         }
166                         break;
167                 }
168                 case CLOSURE_BSDF_TRANSPARENT_ID: {
169                         ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
170
171                         if(sc) {
172                                 sc->data0 = 0.0f;
173                                 sc->data1 = 0.0f;
174                                 sc->data2 = 0.0f;
175                                 sc->N = N;
176                                 sd->flag |= bsdf_transparent_setup(sc);
177                         }
178                         break;
179                 }
180                 case CLOSURE_BSDF_REFLECTION_ID:
181                 case CLOSURE_BSDF_MICROFACET_GGX_ID:
182                 case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
183                 case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: {
184 #ifdef __CAUSTICS_TRICKS__
185                         if(!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
186                                 break;
187 #endif
188                         ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
189
190                         if(sc) {
191                                 sc->N = N;
192                                 sc->data0 = param1;
193                                 sc->data1 = param1;
194                                 sc->data2 = 0.0f;
195
196                                 /* setup bsdf */
197                                 if(type == CLOSURE_BSDF_REFLECTION_ID)
198                                         sd->flag |= bsdf_reflection_setup(sc);
199                                 else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID)
200                                         sd->flag |= bsdf_microfacet_beckmann_setup(sc);
201                                 else if(type == CLOSURE_BSDF_MICROFACET_GGX_ID)
202                                         sd->flag |= bsdf_microfacet_ggx_setup(sc);
203                                 else
204                                         sd->flag |= bsdf_ashikhmin_shirley_setup(sc);
205                         }
206
207                         break;
208                 }
209                 case CLOSURE_BSDF_REFRACTION_ID:
210                 case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
211                 case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: {
212 #ifdef __CAUSTICS_TRICKS__
213                         if(!kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
214                                 break;
215 #endif
216                         ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
217
218                         if(sc) {
219                                 sc->N = N;
220
221                                 float eta = fmaxf(param2, 1e-5f);
222                                 eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
223
224                                 /* setup bsdf */
225                                 if(type == CLOSURE_BSDF_REFRACTION_ID) {
226                                         sc->data0 = eta;
227                                         sc->data1 = 0.0f;
228                                         sc->data2 = 0.0f;
229
230                                         sd->flag |= bsdf_refraction_setup(sc);
231                                 }
232                                 else {
233                                         sc->data0 = param1;
234                                         sc->data1 = param1;
235                                         sc->data2 = eta;
236
237                                         if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID)
238                                                 sd->flag |= bsdf_microfacet_beckmann_refraction_setup(sc);
239                                         else
240                                                 sd->flag |= bsdf_microfacet_ggx_refraction_setup(sc);
241                                 }
242                         }
243
244                         break;
245                 }
246                 case CLOSURE_BSDF_SHARP_GLASS_ID:
247                 case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID:
248                 case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID: {
249 #ifdef __CAUSTICS_TRICKS__
250                         if(!kernel_data.integrator.caustics_reflective &&
251                            !kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE)) {
252                                 break;
253                         }
254 #endif
255                         /* index of refraction */
256                         float eta = fmaxf(param2, 1e-5f);
257                         eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
258
259                         /* fresnel */
260                         float cosNO = dot(N, sd->I);
261                         float fresnel = fresnel_dielectric_cos(cosNO, eta);
262                         float roughness = param1;
263
264                         /* reflection */
265                         ShaderClosure *sc = &sd->closure[sd->num_closure];
266                         float3 weight = sc->weight;
267                         float sample_weight = sc->sample_weight;
268
269                         sc = svm_node_closure_get_bsdf(sd, mix_weight*fresnel);
270 #ifdef __CAUSTICS_TRICKS__
271                         if(kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0)
272 #endif
273                         {
274                                 if(sc) {
275                                         sc->N = N;
276                                         svm_node_glass_setup(sd, sc, type, eta, roughness, false);
277                                 }
278                         }
279
280 #ifdef __CAUSTICS_TRICKS__
281                         if(!kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
282                                 break;
283 #endif
284
285                         /* refraction */
286                         sc = &sd->closure[sd->num_closure];
287                         sc->weight = weight;
288                         sc->sample_weight = sample_weight;
289
290                         sc = svm_node_closure_get_bsdf(sd, mix_weight*(1.0f - fresnel));
291
292                         if(sc) {
293                                 sc->N = N;
294                                 svm_node_glass_setup(sd, sc, type, eta, roughness, true);
295                         }
296
297                         break;
298                 }
299                 case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
300                 case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
301                 case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID: {
302 #ifdef __CAUSTICS_TRICKS__
303                         if(!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
304                                 break;
305 #endif
306                         ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
307
308                         if(sc) {
309                                 sc->N = N;
310
311                                 sc->T = stack_load_float3(stack, data_node.y);
312
313                                 /* rotate tangent */
314                                 float rotation = stack_load_float(stack, data_node.z);
315
316                                 if(rotation != 0.0f)
317                                         sc->T = rotate_around_axis(sc->T, sc->N, rotation * M_2PI_F);
318
319                                 /* compute roughness */
320                                 float roughness = param1;
321                                 float anisotropy = clamp(param2, -0.99f, 0.99f);
322
323                                 if(anisotropy < 0.0f) {
324                                         sc->data0 = roughness/(1.0f + anisotropy);
325                                         sc->data1 = roughness*(1.0f + anisotropy);
326                                 }
327                                 else {
328                                         sc->data0 = roughness*(1.0f - anisotropy);
329                                         sc->data1 = roughness/(1.0f - anisotropy);
330                                 }
331
332                                 sc->data2 = 0.0f;
333
334                                 if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID)
335                                         sd->flag |= bsdf_microfacet_beckmann_aniso_setup(sc);
336                                 else if(type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID)
337                                         sd->flag |= bsdf_microfacet_ggx_aniso_setup(sc);
338                                 else
339                                         sd->flag |= bsdf_ashikhmin_shirley_aniso_setup(sc);
340                         }
341                         break;
342                 }
343                 case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: {
344                         ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
345
346                         if(sc) {
347                                 sc->N = N;
348
349                                 /* sigma */
350                                 sc->data0 = clamp(param1, 0.0f, 1.0f);
351                                 sc->data1 = 0.0f;
352                                 sc->data2 = 0.0f;
353                                 sd->flag |= bsdf_ashikhmin_velvet_setup(sc);
354                         }
355                         break;
356                 }
357                 case CLOSURE_BSDF_DIFFUSE_TOON_ID:
358                 case CLOSURE_BSDF_GLOSSY_TOON_ID: {
359                         ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
360
361                         if(sc) {
362                                 /* Normal, Size and Smooth */
363                                 sc->N = N;
364                                 sc->data0 = param1;
365                                 sc->data1 = param2;
366                                 sc->data2 = 0.0f;
367                                 
368                                 if(type == CLOSURE_BSDF_DIFFUSE_TOON_ID)
369                                         sd->flag |= bsdf_diffuse_toon_setup(sc);
370                                 else
371                                         sd->flag |= bsdf_glossy_toon_setup(sc);
372                         }
373                         break;
374                 }
375 #ifdef __HAIR__
376                 case CLOSURE_BSDF_HAIR_REFLECTION_ID:
377                 case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: {
378                         
379                         if(sd->flag & SD_BACKFACING && sd->type & PRIMITIVE_ALL_CURVE) {
380                                 ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
381
382                                 if(sc) {
383                                         /* todo: giving a fixed weight here will cause issues when
384                                          * mixing multiple BSDFS. energy will not be conserved and
385                                          * the throughput can blow up after multiple bounces. we
386                                          * better figure out a way to skip backfaces from rays
387                                          * spawned by transmission from the front */
388                                         sc->weight = make_float3(1.0f, 1.0f, 1.0f);
389                                         sc->N = N;
390                                         sc->data0 = 0.0f;
391                                         sc->data1 = 0.0f;
392                                         sd->flag |= bsdf_transparent_setup(sc);
393                                 }
394                         }
395                         else {
396                                 ShaderClosure *sc = &sd->closure[sd->num_closure];
397                                 sc = svm_node_closure_get_bsdf(sd, mix_weight);
398
399                                 if(sc) {
400                                         sc->N = N;
401                                         sc->data0 = param1;
402                                         sc->data1 = param2;
403                                         sc->data2 = -stack_load_float(stack, data_node.z);
404
405                                         if(!(sd->type & PRIMITIVE_ALL_CURVE)) {
406                                                 sc->T = normalize(sd->dPdv);
407                                                 sc->data2 = 0.0f;
408                                         }
409                                         else
410                                                 sc->T = normalize(sd->dPdu);
411
412                                         if(type == CLOSURE_BSDF_HAIR_REFLECTION_ID) {
413                                                 sd->flag |= bsdf_hair_reflection_setup(sc);
414                                         }
415                                         else {
416                                                 sd->flag |= bsdf_hair_transmission_setup(sc);
417                                         }
418                                 }
419                         }
420
421                         break;
422                 }
423 #endif
424
425 #ifdef __SUBSURFACE__
426                 case CLOSURE_BSSRDF_CUBIC_ID:
427                 case CLOSURE_BSSRDF_GAUSSIAN_ID: {
428                         ShaderClosure *sc = &sd->closure[sd->num_closure];
429                         float3 weight = sc->weight * mix_weight;
430                         float sample_weight = fabsf(average(weight));
431                         
432                         /* disable in case of diffuse ancestor, can't see it well then and
433                          * adds considerably noise due to probabilities of continuing path
434                          * getting lower and lower */
435                         if(path_flag & PATH_RAY_DIFFUSE_ANCESTOR)
436                                 param1 = 0.0f;
437
438                         if(sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure+2 < MAX_CLOSURE) {
439                                 /* radius * scale */
440                                 float3 radius = stack_load_float3(stack, data_node.z)*param1;
441                                 /* sharpness */
442                                 float sharpness = stack_load_float(stack, data_node.w);
443                                 /* texture color blur */
444                                 float texture_blur = param2;
445
446                                 /* create one closure per color channel */
447                                 if(fabsf(weight.x) > 0.0f) {
448                                         sc->weight = make_float3(weight.x, 0.0f, 0.0f);
449                                         sc->sample_weight = sample_weight;
450                                         sc->data0 = radius.x;
451                                         sc->data1 = texture_blur;
452                                         sc->data2 = 0.0f;
453                                         sc->T.x = sharpness;
454 #ifdef __OSL__
455                                         sc->prim = NULL;
456 #endif
457                                         sc->N = N;
458                                         sd->flag |= bssrdf_setup(sc, (ClosureType)type);
459
460                                         sd->num_closure++;
461                                         sc++;
462                                 }
463
464                                 if(fabsf(weight.y) > 0.0f) {
465                                         sc->weight = make_float3(0.0f, weight.y, 0.0f);
466                                         sc->sample_weight = sample_weight;
467                                         sc->data0 = radius.y;
468                                         sc->data1 = texture_blur;
469                                         sc->data2 = 0.0f;
470                                         sc->T.x = sharpness;
471 #ifdef __OSL__
472                                         sc->prim = NULL;
473 #endif
474                                         sc->N = N;
475                                         sd->flag |= bssrdf_setup(sc, (ClosureType)type);
476
477                                         sd->num_closure++;
478                                         sc++;
479                                 }
480
481                                 if(fabsf(weight.z) > 0.0f) {
482                                         sc->weight = make_float3(0.0f, 0.0f, weight.z);
483                                         sc->sample_weight = sample_weight;
484                                         sc->data0 = radius.z;
485                                         sc->data1 = texture_blur;
486                                         sc->data2 = 0.0f;
487                                         sc->T.x = sharpness;
488 #ifdef __OSL__
489                                         sc->prim = NULL;
490 #endif
491                                         sc->N = N;
492                                         sd->flag |= bssrdf_setup(sc, (ClosureType)type);
493
494                                         sd->num_closure++;
495                                         sc++;
496                                 }
497                         }
498
499                         break;
500                 }
501 #endif
502                 default:
503                         break;
504         }
505 }
506
507 ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int path_flag)
508 {
509 #ifdef __VOLUME__
510         uint type, param1_offset, param2_offset;
511
512         uint mix_weight_offset;
513         decode_node_uchar4(node.y, &type, &param1_offset, &param2_offset, &mix_weight_offset);
514         float mix_weight = (stack_valid(mix_weight_offset)? stack_load_float(stack, mix_weight_offset): 1.0f);
515
516         if(mix_weight == 0.0f)
517                 return;
518
519         float param1 = (stack_valid(param1_offset))? stack_load_float(stack, param1_offset): __uint_as_float(node.z);
520         float param2 = (stack_valid(param2_offset))? stack_load_float(stack, param2_offset): __uint_as_float(node.w);
521         float density = fmaxf(param1, 0.0f);
522
523         switch(type) {
524                 case CLOSURE_VOLUME_ABSORPTION_ID: {
525                         ShaderClosure *sc = svm_node_closure_get_absorption(sd, mix_weight * density);
526
527                         if(sc) {
528                                 sd->flag |= volume_absorption_setup(sc);
529                         }
530                         break;
531                 }
532                 case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID: {
533                         ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight * density);
534
535                         if(sc) {
536                                 sc->data0 = param2; /* g */
537                                 sc->data1 = 0.0f;
538                                 sd->flag |= volume_henyey_greenstein_setup(sc);
539                         }
540                         break;
541                 }
542                 default:
543                         break;
544         }
545 #endif
546 }
547
548 ccl_device void svm_node_closure_emission(ShaderData *sd, float *stack, uint4 node)
549 {
550         uint mix_weight_offset = node.y;
551
552         if(stack_valid(mix_weight_offset)) {
553                 float mix_weight = stack_load_float(stack, mix_weight_offset);
554
555                 if(mix_weight == 0.0f)
556                         return;
557
558                 svm_node_closure_get_non_bsdf(sd, CLOSURE_EMISSION_ID, mix_weight);
559         }
560         else
561                 svm_node_closure_get_non_bsdf(sd, CLOSURE_EMISSION_ID, 1.0f);
562
563         sd->flag |= SD_EMISSION;
564 }
565
566 ccl_device void svm_node_closure_background(ShaderData *sd, float *stack, uint4 node)
567 {
568         uint mix_weight_offset = node.y;
569
570         if(stack_valid(mix_weight_offset)) {
571                 float mix_weight = stack_load_float(stack, mix_weight_offset);
572
573                 if(mix_weight == 0.0f)
574                         return;
575
576                 svm_node_closure_get_non_bsdf(sd, CLOSURE_BACKGROUND_ID, mix_weight);
577         }
578         else
579                 svm_node_closure_get_non_bsdf(sd, CLOSURE_BACKGROUND_ID, 1.0f);
580 }
581
582 ccl_device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 node)
583 {
584         uint mix_weight_offset = node.y;
585
586         if(stack_valid(mix_weight_offset)) {
587                 float mix_weight = stack_load_float(stack, mix_weight_offset);
588
589                 if(mix_weight == 0.0f)
590                         return;
591
592                 svm_node_closure_get_non_bsdf(sd, CLOSURE_HOLDOUT_ID, mix_weight);
593         }
594         else
595                 svm_node_closure_get_non_bsdf(sd, CLOSURE_HOLDOUT_ID, 1.0f);
596
597         sd->flag |= SD_HOLDOUT;
598 }
599
600 ccl_device void svm_node_closure_ambient_occlusion(ShaderData *sd, float *stack, uint4 node)
601 {
602         uint mix_weight_offset = node.y;
603
604         if(stack_valid(mix_weight_offset)) {
605                 float mix_weight = stack_load_float(stack, mix_weight_offset);
606
607                 if(mix_weight == 0.0f)
608                         return;
609
610                 svm_node_closure_get_non_bsdf(sd, CLOSURE_AMBIENT_OCCLUSION_ID, mix_weight);
611         }
612         else
613                 svm_node_closure_get_non_bsdf(sd, CLOSURE_AMBIENT_OCCLUSION_ID, 1.0f);
614
615         sd->flag |= SD_AO;
616 }
617
618 /* Closure Nodes */
619
620 ccl_device_inline void svm_node_closure_store_weight(ShaderData *sd, float3 weight)
621 {
622         if(sd->num_closure < MAX_CLOSURE)
623                 sd->closure[sd->num_closure].weight = weight;
624 }
625
626 ccl_device void svm_node_closure_set_weight(ShaderData *sd, uint r, uint g, uint b)
627 {
628         float3 weight = make_float3(__uint_as_float(r), __uint_as_float(g), __uint_as_float(b));
629         svm_node_closure_store_weight(sd, weight);
630 }
631
632 ccl_device void svm_node_closure_weight(ShaderData *sd, float *stack, uint weight_offset)
633 {
634         float3 weight = stack_load_float3(stack, weight_offset);
635
636         svm_node_closure_store_weight(sd, weight);
637 }
638
639 ccl_device void svm_node_emission_weight(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
640 {
641         uint color_offset = node.y;
642         uint strength_offset = node.z;
643
644         float strength = stack_load_float(stack, strength_offset);
645         float3 weight = stack_load_float3(stack, color_offset)*strength;
646
647         svm_node_closure_store_weight(sd, weight);
648 }
649
650 ccl_device void svm_node_mix_closure(ShaderData *sd, float *stack, uint4 node)
651 {
652         /* fetch weight from blend input, previous mix closures,
653          * and write to stack to be used by closure nodes later */
654         uint weight_offset, in_weight_offset, weight1_offset, weight2_offset;
655         decode_node_uchar4(node.y, &weight_offset, &in_weight_offset, &weight1_offset, &weight2_offset);
656
657         float weight = stack_load_float(stack, weight_offset);
658         weight = clamp(weight, 0.0f, 1.0f);
659
660         float in_weight = (stack_valid(in_weight_offset))? stack_load_float(stack, in_weight_offset): 1.0f;
661
662         if(stack_valid(weight1_offset))
663                 stack_store_float(stack, weight1_offset, in_weight*(1.0f - weight));
664         if(stack_valid(weight2_offset))
665                 stack_store_float(stack, weight2_offset, in_weight*weight);
666 }
667
668 /* (Bump) normal */
669
670 ccl_device void svm_node_set_normal(KernelGlobals *kg, ShaderData *sd, float *stack, uint in_direction, uint out_normal)
671 {
672         float3 normal = stack_load_float3(stack, in_direction);
673         sd->N = normal;
674         stack_store_float3(stack, out_normal, normal);
675 }
676
677 CCL_NAMESPACE_END
678