Cycles: add some volume nodes, they don't actually do anything, this is just
[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         ShaderClosure *sc = svm_node_closure_get(sd);
240         uint mix_weight_offset = node.y;
241
242         if(stack_valid(mix_weight_offset)) {
243                 float mix_weight = stack_load_float(stack, mix_weight_offset);
244
245                 if(mix_weight == 0.0f)
246                         return;
247
248                 sc->weight *= mix_weight;
249         }
250 #else
251         ShaderClosure *sc = &sd->closure;
252 #endif
253
254         sc->type = CLOSURE_EMISSION_ID;
255         sd->flag |= SD_EMISSION;
256 }
257
258 __device void svm_node_closure_background(ShaderData *sd, uint4 node)
259 {
260 #ifdef __MULTI_CLOSURE__
261         ShaderClosure *sc = svm_node_closure_get(sd);
262 #else
263         ShaderClosure *sc = &sd->closure;
264 #endif
265
266         sc->type = CLOSURE_BACKGROUND_ID;
267 }
268
269 __device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 node)
270 {
271 #ifdef __MULTI_CLOSURE__
272         ShaderClosure *sc = svm_node_closure_get(sd);
273         uint mix_weight_offset = node.y;
274
275         if(stack_valid(mix_weight_offset)) {
276                 float mix_weight = stack_load_float(stack, mix_weight_offset);
277
278                 if(mix_weight == 0.0f)
279                         return;
280
281                 sc->weight = make_float3(mix_weight, mix_weight, mix_weight);
282         }
283         else
284                 sc->weight = make_float3(1.0f, 1.0f, 1.0f);
285
286         sc->sample_weight = 0.0f;
287 #else
288         ShaderClosure *sc = &sd->closure;
289 #endif
290
291         sc->type = CLOSURE_HOLDOUT_ID;
292         sd->flag |= SD_HOLDOUT;
293 }
294
295 /* Closure Nodes */
296
297 __device_inline void svm_node_closure_store_weight(ShaderData *sd, float3 weight)
298 {
299 #ifdef __MULTI_CLOSURE__
300         sd->closure[sd->num_closure].weight = weight;
301 #else
302         sd->closure.weight = weight;
303 #endif
304 }
305
306 __device void svm_node_closure_set_weight(ShaderData *sd, uint r, uint g, uint b)
307 {
308         float3 weight = make_float3(__int_as_float(r), __int_as_float(g), __int_as_float(b));
309         svm_node_closure_store_weight(sd, weight);
310 }
311
312 __device void svm_node_emission_set_weight_total(KernelGlobals *kg, ShaderData *sd, uint r, uint g, uint b)
313 {
314         float3 weight = make_float3(__int_as_float(r), __int_as_float(g), __int_as_float(b));
315
316         if(sd->object != ~0)
317                 weight /= object_surface_area(kg, sd->object);
318
319         svm_node_closure_store_weight(sd, weight);
320 }
321
322 __device void svm_node_closure_weight(ShaderData *sd, float *stack, uint weight_offset)
323 {
324         float3 weight = stack_load_float3(stack, weight_offset);
325
326         svm_node_closure_store_weight(sd, weight);
327 }
328
329 __device void svm_node_emission_weight(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
330 {
331         uint color_offset = node.y;
332         uint strength_offset = node.z;
333         uint total_power = node.w;
334
335         float strength = stack_load_float(stack, strength_offset);
336         float3 weight = stack_load_float3(stack, color_offset)*strength;
337
338         if(total_power && sd->object != ~0)
339                 weight /= object_surface_area(kg, sd->object);
340
341         svm_node_closure_store_weight(sd, weight);
342 }
343
344 __device void svm_node_mix_closure(ShaderData *sd, float *stack,
345         uint4 node, int *offset, float *randb)
346 {
347 #ifdef __MULTI_CLOSURE__
348         /* fetch weight from blend input, previous mix closures,
349            and write to stack to be used by closure nodes later */
350         uint weight_offset, in_weight_offset, weight1_offset, weight2_offset;
351         decode_node_uchar4(node.y, &weight_offset, &in_weight_offset, &weight1_offset, &weight2_offset);
352
353         float weight = stack_load_float(stack, weight_offset);
354         float in_weight = (stack_valid(in_weight_offset))? stack_load_float(stack, in_weight_offset): 1.0f;
355
356         if(stack_valid(weight1_offset))
357                 stack_store_float(stack, weight1_offset, in_weight*(1.0f - weight));
358         if(stack_valid(weight2_offset))
359                 stack_store_float(stack, weight2_offset, in_weight*weight);
360 #else
361         /* pick a closure and make the random number uniform over 0..1 again.
362            closure 1 starts on the next node, for closure 2 the start is at an
363            offset from the current node, so we jump */
364         uint weight_offset = node.y;
365         uint node_jump = node.z;
366         float weight = stack_load_float(stack, weight_offset);
367         weight = clamp(weight, 0.0f, 1.0f);
368
369         if(*randb < weight) {
370                 *offset += node_jump;
371                 *randb = *randb/weight;
372         }
373         else
374                 *randb = (*randb - weight)/(1.0f - weight);
375 #endif
376 }
377
378 __device void svm_node_add_closure(ShaderData *sd, float *stack, uint unused,
379         uint node_jump, int *offset, float *randb, float *closure_weight)
380 {
381 #ifdef __MULTI_CLOSURE__
382         /* nothing to do, handled in compiler */
383 #else
384         /* pick one of the two closures with probability 0.5. sampling quality
385            is not going to be great, for that we'd need to evaluate the weights
386            of the two closures being added */
387         float weight = 0.5f;
388
389         if(*randb < weight) {
390                 *offset += node_jump;
391                 *randb = *randb/weight;
392         }
393         else
394                 *randb = (*randb - weight)/(1.0f - weight);
395         
396         *closure_weight *= 2.0f;
397 #endif
398 }
399
400 CCL_NAMESPACE_END
401