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