68f91408f1f1392d9cd930a6c0bf9d0eb23770ba
[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_emission(ShaderData *sd, float *stack, uint4 node)
196 {
197 #ifdef __MULTI_CLOSURE__
198         ShaderClosure *sc = svm_node_closure_get(sd);
199         uint mix_weight_offset = node.y;
200
201         if(stack_valid(mix_weight_offset)) {
202                 float mix_weight = stack_load_float(stack, mix_weight_offset);
203
204                 if(mix_weight == 0.0f)
205                         return;
206
207                 sc->weight *= mix_weight;
208         }
209 #else
210         ShaderClosure *sc = &sd->closure;
211 #endif
212
213         sc->type = CLOSURE_EMISSION_ID;
214         sd->flag |= SD_EMISSION;
215 }
216
217 __device void svm_node_closure_background(ShaderData *sd, uint4 node)
218 {
219 #ifdef __MULTI_CLOSURE__
220         ShaderClosure *sc = svm_node_closure_get(sd);
221 #else
222         ShaderClosure *sc = &sd->closure;
223 #endif
224
225         sc->type = CLOSURE_BACKGROUND_ID;
226 }
227
228 __device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 node)
229 {
230 #ifdef __MULTI_CLOSURE__
231         ShaderClosure *sc = svm_node_closure_get(sd);
232         uint mix_weight_offset = node.y;
233
234         if(stack_valid(mix_weight_offset)) {
235                 float mix_weight = stack_load_float(stack, mix_weight_offset);
236
237                 if(mix_weight == 0.0f)
238                         return;
239
240                 sc->weight = make_float3(mix_weight, mix_weight, mix_weight);
241         }
242         else
243                 sc->weight = make_float3(1.0f, 1.0f, 1.0f);
244
245         sc->sample_weight = 0.0f;
246 #else
247         ShaderClosure *sc = &sd->closure;
248 #endif
249
250         sc->type = CLOSURE_HOLDOUT_ID;
251         sd->flag |= SD_HOLDOUT;
252 }
253
254 /* Closure Nodes */
255
256 __device_inline void svm_node_closure_store_weight(ShaderData *sd, float3 weight)
257 {
258 #ifdef __MULTI_CLOSURE__
259         sd->closure[sd->num_closure].weight = weight;
260 #else
261         sd->closure.weight = weight;
262 #endif
263 }
264
265 __device void svm_node_closure_set_weight(ShaderData *sd, uint r, uint g, uint b)
266 {
267         float3 weight = make_float3(__int_as_float(r), __int_as_float(g), __int_as_float(b));
268         svm_node_closure_store_weight(sd, weight);
269 }
270
271 __device void svm_node_emission_set_weight_total(KernelGlobals *kg, ShaderData *sd, uint r, uint g, uint b)
272 {
273         float3 weight = make_float3(__int_as_float(r), __int_as_float(g), __int_as_float(b));
274
275         if(sd->object != ~0)
276                 weight /= object_surface_area(kg, sd->object);
277
278         svm_node_closure_store_weight(sd, weight);
279 }
280
281 __device void svm_node_closure_weight(ShaderData *sd, float *stack, uint weight_offset)
282 {
283         float3 weight = stack_load_float3(stack, weight_offset);
284
285         svm_node_closure_store_weight(sd, weight);
286 }
287
288 __device void svm_node_emission_weight(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
289 {
290         uint color_offset = node.y;
291         uint strength_offset = node.z;
292         uint total_power = node.w;
293
294         float strength = stack_load_float(stack, strength_offset);
295         float3 weight = stack_load_float3(stack, color_offset)*strength;
296
297         if(total_power && sd->object != ~0)
298                 weight /= object_surface_area(kg, sd->object);
299
300         svm_node_closure_store_weight(sd, weight);
301 }
302
303 __device void svm_node_mix_closure(ShaderData *sd, float *stack,
304         uint4 node, int *offset, float *randb)
305 {
306 #ifdef __MULTI_CLOSURE__
307         /* fetch weight from blend input, previous mix closures,
308            and write to stack to be used by closure nodes later */
309         uint weight_offset, in_weight_offset, weight1_offset, weight2_offset;
310         decode_node_uchar4(node.y, &weight_offset, &in_weight_offset, &weight1_offset, &weight2_offset);
311
312         float weight = stack_load_float(stack, weight_offset);
313         float in_weight = (stack_valid(in_weight_offset))? stack_load_float(stack, in_weight_offset): 1.0f;
314
315         if(stack_valid(weight1_offset))
316                 stack_store_float(stack, weight1_offset, in_weight*(1.0f - weight));
317         if(stack_valid(weight2_offset))
318                 stack_store_float(stack, weight2_offset, in_weight*weight);
319 #else
320         /* pick a closure and make the random number uniform over 0..1 again.
321            closure 1 starts on the next node, for closure 2 the start is at an
322            offset from the current node, so we jump */
323         uint weight_offset = node.y;
324         uint node_jump = node.z;
325         float weight = stack_load_float(stack, weight_offset);
326         weight = clamp(weight, 0.0f, 1.0f);
327
328         if(*randb < weight) {
329                 *offset += node_jump;
330                 *randb = *randb/weight;
331         }
332         else
333                 *randb = (*randb - weight)/(1.0f - weight);
334 #endif
335 }
336
337 __device void svm_node_add_closure(ShaderData *sd, float *stack, uint unused,
338         uint node_jump, int *offset, float *randb, float *closure_weight)
339 {
340 #ifdef __MULTI_CLOSURE__
341         /* nothing to do, handled in compiler */
342 #else
343         /* pick one of the two closures with probability 0.5. sampling quality
344            is not going to be great, for that we'd need to evaluate the weights
345            of the two closures being added */
346         float weight = 0.5f;
347
348         if(*randb < weight) {
349                 *offset += node_jump;
350                 *randb = *randb/weight;
351         }
352         else
353                 *randb = (*randb - weight)/(1.0f - weight);
354         
355         *closure_weight *= 2.0f;
356 #endif
357 }
358
359 CCL_NAMESPACE_END
360