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