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