Merge branch 'master' into blender2.8
[blender.git] / intern / cycles / kernel / osl / osl_closures.cpp
1 /*
2  * Adapted from Open Shading Language with this license:
3  *
4  * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
5  * All Rights Reserved.
6  *
7  * Modifications Copyright 2011, Blender Foundation.
8  * 
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are
11  * met:
12  * * Redistributions of source code must retain the above copyright
13  *   notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above copyright
15  *   notice, this list of conditions and the following disclaimer in the
16  *   documentation and/or other materials provided with the distribution.
17  * * Neither the name of Sony Pictures Imageworks nor the names of its
18  *   contributors may be used to endorse or promote products derived from
19  *   this software without specific prior written permission.
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include <OSL/genclosure.h>
34 #include <OSL/oslclosure.h>
35
36 #include "kernel/osl/osl_closures.h"
37 #include "kernel/osl/osl_shader.h"
38
39 #include "util/util_math.h"
40 #include "util/util_param.h"
41
42 #include "kernel/kernel_types.h"
43 #include "kernel/kernel_compat_cpu.h"
44 #include "kernel/split/kernel_split_data_types.h"
45 #include "kernel/kernel_globals.h"
46 #include "kernel/kernel_montecarlo.h"
47 #include "kernel/kernel_random.h"
48
49 #include "kernel/closure/alloc.h"
50 #include "kernel/closure/bsdf_util.h"
51 #include "kernel/closure/bsdf_ashikhmin_velvet.h"
52 #include "kernel/closure/bsdf_diffuse.h"
53 #include "kernel/closure/bsdf_microfacet.h"
54 #include "kernel/closure/bsdf_microfacet_multi.h"
55 #include "kernel/closure/bsdf_oren_nayar.h"
56 #include "kernel/closure/bsdf_reflection.h"
57 #include "kernel/closure/bsdf_refraction.h"
58 #include "kernel/closure/bsdf_transparent.h"
59 #include "kernel/closure/bsdf_ashikhmin_shirley.h"
60 #include "kernel/closure/bsdf_toon.h"
61 #include "kernel/closure/bsdf_hair.h"
62 #include "kernel/closure/bsdf_principled_diffuse.h"
63 #include "kernel/closure/bsdf_principled_sheen.h"
64 #include "kernel/closure/volume.h"
65
66 CCL_NAMESPACE_BEGIN
67
68 using namespace OSL;
69
70 /* BSDF class definitions */
71
72 BSDF_CLOSURE_CLASS_BEGIN(Diffuse, diffuse, DiffuseBsdf, LABEL_DIFFUSE)
73         CLOSURE_FLOAT3_PARAM(DiffuseClosure, params.N),
74 BSDF_CLOSURE_CLASS_END(Diffuse, diffuse)
75
76 BSDF_CLOSURE_CLASS_BEGIN(Translucent, translucent, DiffuseBsdf, LABEL_DIFFUSE)
77         CLOSURE_FLOAT3_PARAM(TranslucentClosure, params.N),
78 BSDF_CLOSURE_CLASS_END(Translucent, translucent)
79
80 BSDF_CLOSURE_CLASS_BEGIN(OrenNayar, oren_nayar, OrenNayarBsdf, LABEL_DIFFUSE)
81         CLOSURE_FLOAT3_PARAM(OrenNayarClosure, params.N),
82         CLOSURE_FLOAT_PARAM(OrenNayarClosure, params.roughness),
83 BSDF_CLOSURE_CLASS_END(OrenNayar, oren_nayar)
84
85 BSDF_CLOSURE_CLASS_BEGIN(Reflection, reflection, MicrofacetBsdf, LABEL_SINGULAR)
86         CLOSURE_FLOAT3_PARAM(ReflectionClosure, params.N),
87 BSDF_CLOSURE_CLASS_END(Reflection, reflection)
88
89 BSDF_CLOSURE_CLASS_BEGIN(Refraction, refraction, MicrofacetBsdf, LABEL_SINGULAR)
90         CLOSURE_FLOAT3_PARAM(RefractionClosure, params.N),
91         CLOSURE_FLOAT_PARAM(RefractionClosure, params.ior),
92 BSDF_CLOSURE_CLASS_END(Refraction, refraction)
93
94 BSDF_CLOSURE_CLASS_BEGIN(AshikhminVelvet, ashikhmin_velvet, VelvetBsdf, LABEL_DIFFUSE)
95         CLOSURE_FLOAT3_PARAM(AshikhminVelvetClosure, params.N),
96         CLOSURE_FLOAT_PARAM(AshikhminVelvetClosure, params.sigma),
97 BSDF_CLOSURE_CLASS_END(AshikhminVelvet, ashikhmin_velvet)
98
99 BSDF_CLOSURE_CLASS_BEGIN(AshikhminShirley, ashikhmin_shirley_aniso, MicrofacetBsdf, LABEL_GLOSSY|LABEL_REFLECT)
100         CLOSURE_FLOAT3_PARAM(AshikhminShirleyClosure, params.N),
101         CLOSURE_FLOAT3_PARAM(AshikhminShirleyClosure, params.T),
102         CLOSURE_FLOAT_PARAM(AshikhminShirleyClosure, params.alpha_x),
103         CLOSURE_FLOAT_PARAM(AshikhminShirleyClosure, params.alpha_y),
104 BSDF_CLOSURE_CLASS_END(AshikhminShirley, ashikhmin_shirley_aniso)
105
106 BSDF_CLOSURE_CLASS_BEGIN(DiffuseToon, diffuse_toon, ToonBsdf, LABEL_DIFFUSE)
107         CLOSURE_FLOAT3_PARAM(DiffuseToonClosure, params.N),
108         CLOSURE_FLOAT_PARAM(DiffuseToonClosure, params.size),
109         CLOSURE_FLOAT_PARAM(DiffuseToonClosure, params.smooth),
110 BSDF_CLOSURE_CLASS_END(DiffuseToon, diffuse_toon)
111
112 BSDF_CLOSURE_CLASS_BEGIN(GlossyToon, glossy_toon, ToonBsdf, LABEL_GLOSSY)
113         CLOSURE_FLOAT3_PARAM(GlossyToonClosure, params.N),
114         CLOSURE_FLOAT_PARAM(GlossyToonClosure, params.size),
115         CLOSURE_FLOAT_PARAM(GlossyToonClosure, params.smooth),
116 BSDF_CLOSURE_CLASS_END(GlossyToon, glossy_toon)
117
118 BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGX, microfacet_ggx, MicrofacetBsdf, LABEL_GLOSSY|LABEL_REFLECT)
119         CLOSURE_FLOAT3_PARAM(MicrofacetGGXClosure, params.N),
120         CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure, params.alpha_x),
121 BSDF_CLOSURE_CLASS_END(MicrofacetGGX, microfacet_ggx)
122
123 BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXAniso, microfacet_ggx_aniso, MicrofacetBsdf, LABEL_GLOSSY|LABEL_REFLECT)
124         CLOSURE_FLOAT3_PARAM(MicrofacetGGXAnisoClosure, params.N),
125         CLOSURE_FLOAT3_PARAM(MicrofacetGGXAnisoClosure, params.T),
126         CLOSURE_FLOAT_PARAM(MicrofacetGGXAnisoClosure, params.alpha_x),
127         CLOSURE_FLOAT_PARAM(MicrofacetGGXAnisoClosure, params.alpha_y),
128 BSDF_CLOSURE_CLASS_END(MicrofacetGGXAniso, microfacet_ggx_aniso)
129
130 BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmann, microfacet_beckmann, MicrofacetBsdf, LABEL_GLOSSY|LABEL_REFLECT)
131         CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannClosure, params.N),
132         CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure, params.alpha_x),
133 BSDF_CLOSURE_CLASS_END(MicrofacetBeckmann, microfacet_beckmann)
134
135 BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannAniso, microfacet_beckmann_aniso, MicrofacetBsdf, LABEL_GLOSSY|LABEL_REFLECT)
136         CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannAnisoClosure, params.N),
137         CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannAnisoClosure, params.T),
138         CLOSURE_FLOAT_PARAM(MicrofacetBeckmannAnisoClosure, params.alpha_x),
139         CLOSURE_FLOAT_PARAM(MicrofacetBeckmannAnisoClosure, params.alpha_y),
140 BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannAniso, microfacet_beckmann_aniso)
141
142 BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXRefraction, microfacet_ggx_refraction, MicrofacetBsdf, LABEL_GLOSSY|LABEL_TRANSMIT)
143         CLOSURE_FLOAT3_PARAM(MicrofacetGGXRefractionClosure, params.N),
144         CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, params.alpha_x),
145         CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, params.ior),
146 BSDF_CLOSURE_CLASS_END(MicrofacetGGXRefraction, microfacet_ggx_refraction)
147
148 BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction, MicrofacetBsdf, LABEL_GLOSSY|LABEL_TRANSMIT)
149         CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannRefractionClosure, params.N),
150         CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, params.alpha_x),
151         CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, params.ior),
152 BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction)
153
154 BSDF_CLOSURE_CLASS_BEGIN(HairReflection, hair_reflection, HairBsdf, LABEL_GLOSSY)
155         CLOSURE_FLOAT3_PARAM(HairReflectionClosure, params.N),
156         CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.roughness1),
157         CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.roughness2),
158         CLOSURE_FLOAT3_PARAM(HairReflectionClosure, params.T),
159         CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.offset),
160 BSDF_CLOSURE_CLASS_END(HairReflection, hair_reflection)
161
162 BSDF_CLOSURE_CLASS_BEGIN(HairTransmission, hair_transmission, HairBsdf, LABEL_GLOSSY)
163         CLOSURE_FLOAT3_PARAM(HairTransmissionClosure, params.N),
164         CLOSURE_FLOAT_PARAM(HairTransmissionClosure, params.roughness1),
165         CLOSURE_FLOAT_PARAM(HairTransmissionClosure, params.roughness2),
166         CLOSURE_FLOAT3_PARAM(HairReflectionClosure, params.T),
167         CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.offset),
168 BSDF_CLOSURE_CLASS_END(HairTransmission, hair_transmission)
169
170 BSDF_CLOSURE_CLASS_BEGIN(PrincipledDiffuse, principled_diffuse, PrincipledDiffuseBsdf, LABEL_DIFFUSE)
171         CLOSURE_FLOAT3_PARAM(PrincipledDiffuseClosure, params.N),
172         CLOSURE_FLOAT_PARAM(PrincipledDiffuseClosure, params.roughness),
173 BSDF_CLOSURE_CLASS_END(PrincipledDiffuse, principled_diffuse)
174
175 BSDF_CLOSURE_CLASS_BEGIN(PrincipledSheen, principled_sheen, PrincipledSheenBsdf, LABEL_DIFFUSE)
176         CLOSURE_FLOAT3_PARAM(PrincipledSheenClosure, params.N),
177 BSDF_CLOSURE_CLASS_END(PrincipledSheen, principled_sheen)
178
179 /* DISNEY PRINCIPLED CLEARCOAT */
180 class PrincipledClearcoatClosure : public CBSDFClosure {
181 public:
182         MicrofacetBsdf params;
183         float clearcoat, clearcoat_roughness;
184
185         MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
186         {
187                 MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc_osl(sd, sizeof(MicrofacetBsdf), weight, &params);
188                 if(!bsdf) {
189                         return NULL;
190                 }
191
192                 MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
193                 if(!extra) {
194                         return NULL;
195                 }
196
197                 bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
198                 bsdf->extra = extra;
199                 bsdf->ior = 1.5f;
200                 bsdf->alpha_x = clearcoat_roughness;
201                 bsdf->alpha_y = clearcoat_roughness;
202                 bsdf->extra->color = make_float3(0.0f, 0.0f, 0.0f);
203                 bsdf->extra->cspec0 = make_float3(0.04f, 0.04f, 0.04f);
204                 bsdf->extra->clearcoat = clearcoat;
205                 return bsdf;
206         }
207
208         void setup(ShaderData *sd, int path_flag, float3 weight)
209         {
210                 MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
211                 if(!bsdf) {
212                         return;
213                 }
214
215                 sd->flag |= bsdf_microfacet_ggx_clearcoat_setup(bsdf, sd);
216         }
217 };
218
219 ClosureParam *closure_bsdf_principled_clearcoat_params()
220 {
221         static ClosureParam params[] = {
222                 CLOSURE_FLOAT3_PARAM(PrincipledClearcoatClosure, params.N),
223                 CLOSURE_FLOAT_PARAM(PrincipledClearcoatClosure, clearcoat),
224                 CLOSURE_FLOAT_PARAM(PrincipledClearcoatClosure, clearcoat_roughness),
225                 CLOSURE_STRING_KEYPARAM(PrincipledClearcoatClosure, label, "label"),
226                 CLOSURE_FINISH_PARAM(PrincipledClearcoatClosure)
227         };
228         return params;
229 }
230 CCLOSURE_PREPARE(closure_bsdf_principled_clearcoat_prepare, PrincipledClearcoatClosure)
231
232
233 /* Registration */
234
235 static void register_closure(OSL::ShadingSystem *ss, const char *name, int id, OSL::ClosureParam *params, OSL::PrepareClosureFunc prepare)
236 {
237         /* optimization: it's possible to not use a prepare function at all and
238          * only initialize the actual class when accessing the closure component
239          * data, but then we need to map the id to the class somehow */
240 #if OSL_LIBRARY_VERSION_CODE >= 10900
241         ss->register_closure(name, id, params, prepare, NULL);
242 #else
243         ss->register_closure(name, id, params, prepare, NULL, 16);
244 #endif
245 }
246
247 void OSLShader::register_closures(OSLShadingSystem *ss_)
248 {
249         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)ss_;
250         int id = 0;
251
252         register_closure(ss, "diffuse", id++,
253                 bsdf_diffuse_params(), bsdf_diffuse_prepare);
254         register_closure(ss, "oren_nayar", id++,
255                 bsdf_oren_nayar_params(), bsdf_oren_nayar_prepare);
256         register_closure(ss, "translucent", id++,
257                 bsdf_translucent_params(), bsdf_translucent_prepare);
258         register_closure(ss, "reflection", id++,
259                 bsdf_reflection_params(), bsdf_reflection_prepare);
260         register_closure(ss, "refraction", id++,
261                 bsdf_refraction_params(), bsdf_refraction_prepare);
262         register_closure(ss, "transparent", id++,
263                 closure_bsdf_transparent_params(), closure_bsdf_transparent_prepare);
264         register_closure(ss, "microfacet_ggx", id++,
265                 bsdf_microfacet_ggx_params(), bsdf_microfacet_ggx_prepare);
266         register_closure(ss, "microfacet_ggx_aniso", id++,
267                 bsdf_microfacet_ggx_aniso_params(), bsdf_microfacet_ggx_aniso_prepare);
268         register_closure(ss, "microfacet_ggx_refraction", id++,
269                 bsdf_microfacet_ggx_refraction_params(), bsdf_microfacet_ggx_refraction_prepare);
270         register_closure(ss, "microfacet_multi_ggx", id++,
271                 closure_bsdf_microfacet_multi_ggx_params(), closure_bsdf_microfacet_multi_ggx_prepare);
272         register_closure(ss, "microfacet_multi_ggx_glass", id++,
273                 closure_bsdf_microfacet_multi_ggx_glass_params(), closure_bsdf_microfacet_multi_ggx_glass_prepare);
274         register_closure(ss, "microfacet_multi_ggx_aniso", id++,
275                 closure_bsdf_microfacet_multi_ggx_aniso_params(), closure_bsdf_microfacet_multi_ggx_aniso_prepare);
276         register_closure(ss, "microfacet_ggx_fresnel", id++,
277                 closure_bsdf_microfacet_ggx_fresnel_params(), closure_bsdf_microfacet_ggx_fresnel_prepare);
278         register_closure(ss, "microfacet_ggx_aniso_fresnel", id++,
279                 closure_bsdf_microfacet_ggx_aniso_fresnel_params(), closure_bsdf_microfacet_ggx_aniso_fresnel_prepare);
280         register_closure(ss, "microfacet_multi_ggx_fresnel", id++,
281                 closure_bsdf_microfacet_multi_ggx_fresnel_params(), closure_bsdf_microfacet_multi_ggx_fresnel_prepare);
282         register_closure(ss, "microfacet_multi_ggx_glass_fresnel", id++,
283                 closure_bsdf_microfacet_multi_ggx_glass_fresnel_params(), closure_bsdf_microfacet_multi_ggx_glass_fresnel_prepare);
284         register_closure(ss, "microfacet_multi_ggx_aniso_fresnel", id++,
285                 closure_bsdf_microfacet_multi_ggx_aniso_fresnel_params(), closure_bsdf_microfacet_multi_ggx_aniso_fresnel_prepare);
286         register_closure(ss, "microfacet_beckmann", id++,
287                 bsdf_microfacet_beckmann_params(), bsdf_microfacet_beckmann_prepare);
288         register_closure(ss, "microfacet_beckmann_aniso", id++,
289                 bsdf_microfacet_beckmann_aniso_params(), bsdf_microfacet_beckmann_aniso_prepare);
290         register_closure(ss, "microfacet_beckmann_refraction", id++,
291                 bsdf_microfacet_beckmann_refraction_params(), bsdf_microfacet_beckmann_refraction_prepare);
292         register_closure(ss, "ashikhmin_shirley", id++,
293                 bsdf_ashikhmin_shirley_aniso_params(), bsdf_ashikhmin_shirley_aniso_prepare);
294         register_closure(ss, "ashikhmin_velvet", id++,
295                 bsdf_ashikhmin_velvet_params(), bsdf_ashikhmin_velvet_prepare);
296         register_closure(ss, "diffuse_toon", id++,
297                 bsdf_diffuse_toon_params(), bsdf_diffuse_toon_prepare);
298         register_closure(ss, "glossy_toon", id++,
299                 bsdf_glossy_toon_params(), bsdf_glossy_toon_prepare);
300         register_closure(ss, "principled_diffuse", id++,
301                 bsdf_principled_diffuse_params(), bsdf_principled_diffuse_prepare);
302         register_closure(ss, "principled_sheen", id++,
303                 bsdf_principled_sheen_params(), bsdf_principled_sheen_prepare);
304         register_closure(ss, "principled_clearcoat", id++,
305                 closure_bsdf_principled_clearcoat_params(), closure_bsdf_principled_clearcoat_prepare);
306
307         register_closure(ss, "emission", id++,
308                 closure_emission_params(), closure_emission_prepare);
309         register_closure(ss, "background", id++,
310                 closure_background_params(), closure_background_prepare);
311         register_closure(ss, "holdout", id++,
312                 closure_holdout_params(), closure_holdout_prepare);
313         register_closure(ss, "ambient_occlusion", id++,
314                 closure_ambient_occlusion_params(), closure_ambient_occlusion_prepare);
315         register_closure(ss, "diffuse_ramp", id++,
316                 closure_bsdf_diffuse_ramp_params(), closure_bsdf_diffuse_ramp_prepare);
317         register_closure(ss, "phong_ramp", id++,
318                 closure_bsdf_phong_ramp_params(), closure_bsdf_phong_ramp_prepare);
319         register_closure(ss, "bssrdf", id++,
320                 closure_bssrdf_params(), closure_bssrdf_prepare);
321
322         register_closure(ss, "hair_reflection", id++,
323                 bsdf_hair_reflection_params(), bsdf_hair_reflection_prepare);
324         register_closure(ss, "hair_transmission", id++,
325                 bsdf_hair_transmission_params(), bsdf_hair_transmission_prepare);
326
327         register_closure(ss, "henyey_greenstein", id++,
328                 closure_henyey_greenstein_params(), closure_henyey_greenstein_prepare);
329         register_closure(ss, "absorption", id++,
330                 closure_absorption_params(), closure_absorption_prepare);
331 }
332
333 /* BSDF Closure */
334
335 bool CBSDFClosure::skip(const ShaderData *sd, int path_flag, int scattering)
336 {
337         /* caustic options */
338         if((scattering & LABEL_GLOSSY) && (path_flag & PATH_RAY_DIFFUSE)) {
339                 KernelGlobals *kg = sd->osl_globals;
340
341                 if((!kernel_data.integrator.caustics_reflective && (scattering & LABEL_REFLECT)) ||
342                    (!kernel_data.integrator.caustics_refractive && (scattering & LABEL_TRANSMIT)))
343                 {
344                         return true;
345                 }
346         }
347
348         return false;
349 }
350
351
352 /* GGX closures with Fresnel */
353
354 class MicrofacetFresnelClosure : public CBSDFClosure {
355 public:
356         MicrofacetBsdf params;
357         float3 color;
358         float3 cspec0;
359
360         MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
361         {
362                 /* Technically, the MultiGGX Glass closure may also transmit. However,
363                 * since this is set statically and only used for caustic flags, this
364                 * is probably as good as it gets. */
365                 if(skip(sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
366                         return NULL;
367                 }
368
369                 MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc_osl(sd, sizeof(MicrofacetBsdf), weight, &params);
370                 if(!bsdf) {
371                         return NULL;
372                 }
373
374                 MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
375                 if(!extra) {
376                         return NULL;
377                 }
378
379                 bsdf->extra = extra;
380                 bsdf->extra->color = color;
381                 bsdf->extra->cspec0 = cspec0;
382                 bsdf->extra->clearcoat = 0.0f;
383                 return bsdf;
384         }
385 };
386
387 class MicrofacetGGXFresnelClosure : public MicrofacetFresnelClosure {
388 public:
389         void setup(ShaderData *sd, int path_flag, float3 weight)
390         {
391                 MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
392                 if(!bsdf) {
393                         return;
394                 }
395
396                 bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
397                 bsdf->alpha_y = bsdf->alpha_x;
398                 sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd);
399         }
400 };
401
402 ClosureParam *closure_bsdf_microfacet_ggx_fresnel_params()
403 {
404         static ClosureParam params[] = {
405                 CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, params.N),
406                 CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.alpha_x),
407                 CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.ior),
408                 CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, color),
409                 CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, cspec0),
410                 CLOSURE_STRING_KEYPARAM(MicrofacetGGXFresnelClosure, label, "label"),
411                 CLOSURE_FINISH_PARAM(MicrofacetGGXFresnelClosure)
412         };
413         return params;
414 }
415 CCLOSURE_PREPARE(closure_bsdf_microfacet_ggx_fresnel_prepare, MicrofacetGGXFresnelClosure);
416
417 class MicrofacetGGXAnisoFresnelClosure : public MicrofacetFresnelClosure {
418 public:
419         void setup(ShaderData *sd, int path_flag, float3 weight)
420         {
421                 MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
422                 if(!bsdf) {
423                         return;
424                 }
425
426                 sd->flag |= bsdf_microfacet_ggx_aniso_fresnel_setup(bsdf, sd);
427         }
428 };
429
430 ClosureParam *closure_bsdf_microfacet_ggx_aniso_fresnel_params()
431 {
432         static ClosureParam params[] = {
433                 CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, params.N),
434                 CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, params.T),
435                 CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.alpha_x),
436                 CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.alpha_y),
437                 CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.ior),
438                 CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, color),
439                 CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, cspec0),
440                 CLOSURE_STRING_KEYPARAM(MicrofacetGGXFresnelClosure, label, "label"),
441                 CLOSURE_FINISH_PARAM(MicrofacetGGXFresnelClosure)
442         };
443         return params;
444 }
445 CCLOSURE_PREPARE(closure_bsdf_microfacet_ggx_aniso_fresnel_prepare, MicrofacetGGXAnisoFresnelClosure);
446
447
448 /* Multiscattering GGX closures */
449
450 class MicrofacetMultiClosure : public CBSDFClosure {
451 public:
452         MicrofacetBsdf params;
453         float3 color;
454
455         MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
456         {
457                 /* Technically, the MultiGGX closure may also transmit. However,
458                  * since this is set statically and only used for caustic flags, this
459                  * is probably as good as it gets. */
460             if(skip(sd, path_flag, LABEL_GLOSSY|LABEL_REFLECT)) {
461                         return NULL;
462                 }
463
464                 MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc_osl(sd, sizeof(MicrofacetBsdf), weight, &params);
465                 if(!bsdf) {
466                         return NULL;
467                 }
468
469                 MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
470                 if(!extra) {
471                         return NULL;
472                 }
473
474                 bsdf->extra = extra;
475                 bsdf->extra->color = color;
476                 bsdf->extra->cspec0 = make_float3(0.0f, 0.0f, 0.0f);
477                 bsdf->extra->clearcoat = 0.0f;
478                 return bsdf;
479         }
480 };
481
482 class MicrofacetMultiGGXClosure : public MicrofacetMultiClosure {
483 public:
484         void setup(ShaderData *sd, int path_flag, float3 weight)
485         {
486                 MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
487                 if(!bsdf) {
488                         return;
489                 }
490
491                 bsdf->ior = 0.0f;
492                 bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
493                 bsdf->alpha_y = bsdf->alpha_x;
494                 sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf);
495         }
496 };
497
498 ClosureParam *closure_bsdf_microfacet_multi_ggx_params()
499 {
500         static ClosureParam params[] = {
501                 CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, params.N),
502                 CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.alpha_x),
503                 CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, color),
504                 CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXClosure, label, "label"),
505                 CLOSURE_FINISH_PARAM(MicrofacetMultiGGXClosure)
506         };
507         return params;
508 }
509 CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_prepare, MicrofacetMultiGGXClosure);
510
511 class MicrofacetMultiGGXAnisoClosure : public MicrofacetMultiClosure {
512 public:
513         void setup(ShaderData *sd, int path_flag, float3 weight)
514         {
515                 MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
516                 if(!bsdf) {
517                         return;
518                 }
519
520                 bsdf->ior = 0.0f;
521                 sd->flag |= bsdf_microfacet_multi_ggx_aniso_setup(bsdf);
522         }
523 };
524
525 ClosureParam *closure_bsdf_microfacet_multi_ggx_aniso_params()
526 {
527         static ClosureParam params[] = {
528                 CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, params.N),
529                 CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, params.T),
530                 CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.alpha_x),
531                 CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.alpha_y),
532                 CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, color),
533                 CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXClosure, label, "label"),
534                 CLOSURE_FINISH_PARAM(MicrofacetMultiGGXClosure)
535         };
536         return params;
537 }
538 CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_aniso_prepare, MicrofacetMultiGGXAnisoClosure);
539
540 class MicrofacetMultiGGXGlassClosure : public MicrofacetMultiClosure {
541 public:
542         MicrofacetMultiGGXGlassClosure() : MicrofacetMultiClosure() {}
543
544         void setup(ShaderData *sd, int path_flag, float3 weight)
545         {
546                 MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
547                 if(!bsdf) {
548                         return;
549                 }
550
551                 bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
552                 bsdf->alpha_y = bsdf->alpha_x;
553                 sd->flag |= bsdf_microfacet_multi_ggx_glass_setup(bsdf);
554         }
555 };
556
557 ClosureParam *closure_bsdf_microfacet_multi_ggx_glass_params()
558 {
559         static ClosureParam params[] = {
560                 CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, params.N),
561                 CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.alpha_x),
562                 CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.ior),
563                 CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, color),
564                 CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXClosure, label, "label"),
565                 CLOSURE_FINISH_PARAM(MicrofacetMultiGGXClosure)
566         };
567         return params;
568 }
569 CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_glass_prepare, MicrofacetMultiGGXGlassClosure);
570
571
572 /* Multiscattering GGX closures with Fresnel */
573
574 class MicrofacetMultiFresnelClosure : public CBSDFClosure {
575 public:
576         MicrofacetBsdf params;
577         float3 color;
578         float3 cspec0;
579
580         MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
581         {
582                 /* Technically, the MultiGGX closure may also transmit. However,
583                 * since this is set statically and only used for caustic flags, this
584                 * is probably as good as it gets. */
585                 if(skip(sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
586                         return NULL;
587                 }
588
589                 MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc_osl(sd, sizeof(MicrofacetBsdf), weight, &params);
590                 if(!bsdf) {
591                         return NULL;
592                 }
593
594                 MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
595                 if(!extra) {
596                         return NULL;
597                 }
598
599                 bsdf->extra = extra;
600                 bsdf->extra->color = color;
601                 bsdf->extra->cspec0 = cspec0;
602                 bsdf->extra->clearcoat = 0.0f;
603                 return bsdf;
604         }
605 };
606
607 class MicrofacetMultiGGXFresnelClosure : public MicrofacetMultiFresnelClosure {
608 public:
609         void setup(ShaderData *sd, int path_flag, float3 weight)
610         {
611                 MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
612                 if(!bsdf) {
613                         return;
614                 }
615
616                 bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
617                 bsdf->alpha_y = bsdf->alpha_x;
618                 sd->flag |= bsdf_microfacet_multi_ggx_fresnel_setup(bsdf, sd);
619         }
620 };
621
622 ClosureParam *closure_bsdf_microfacet_multi_ggx_fresnel_params()
623 {
624         static ClosureParam params[] = {
625                 CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.N),
626                 CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_x),
627                 CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.ior),
628                 CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, color),
629                 CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, cspec0),
630                 CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXFresnelClosure, label, "label"),
631                 CLOSURE_FINISH_PARAM(MicrofacetMultiGGXFresnelClosure)
632         };
633         return params;
634 }
635 CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_fresnel_prepare, MicrofacetMultiGGXFresnelClosure);
636
637 class MicrofacetMultiGGXAnisoFresnelClosure : public MicrofacetMultiFresnelClosure {
638 public:
639         void setup(ShaderData *sd, int path_flag, float3 weight)
640         {
641                 MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
642                 if(!bsdf) {
643                         return;
644                 }
645
646                 sd->flag |= bsdf_microfacet_multi_ggx_aniso_fresnel_setup(bsdf, sd);
647         }
648 };
649
650 ClosureParam *closure_bsdf_microfacet_multi_ggx_aniso_fresnel_params()
651 {
652         static ClosureParam params[] = {
653                 CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.N),
654                 CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.T),
655                 CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_x),
656                 CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_y),
657                 CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.ior),
658                 CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, color),
659                 CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, cspec0),
660                 CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXFresnelClosure, label, "label"),
661                 CLOSURE_FINISH_PARAM(MicrofacetMultiGGXFresnelClosure)
662         };
663         return params;
664 }
665 CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_aniso_fresnel_prepare, MicrofacetMultiGGXAnisoFresnelClosure);
666
667 class MicrofacetMultiGGXGlassFresnelClosure : public MicrofacetMultiFresnelClosure {
668 public:
669         MicrofacetMultiGGXGlassFresnelClosure() : MicrofacetMultiFresnelClosure() {}
670
671         void setup(ShaderData *sd, int path_flag, float3 weight)
672         {
673                 MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
674                 if(!bsdf) {
675                         return;
676                 }
677
678                 bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
679                 bsdf->alpha_y = bsdf->alpha_x;
680                 sd->flag |= bsdf_microfacet_multi_ggx_glass_fresnel_setup(bsdf, sd);
681         }
682 };
683
684 ClosureParam *closure_bsdf_microfacet_multi_ggx_glass_fresnel_params()
685 {
686         static ClosureParam params[] = {
687                 CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.N),
688                 CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_x),
689                 CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.ior),
690                 CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, color),
691                 CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, cspec0),
692                 CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXFresnelClosure, label, "label"),
693                 CLOSURE_FINISH_PARAM(MicrofacetMultiGGXFresnelClosure)
694         };
695         return params;
696 }
697 CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_glass_fresnel_prepare, MicrofacetMultiGGXGlassFresnelClosure);
698
699 /* Transparent */
700
701 class TransparentClosure : public CBSDFClosure {
702 public:
703         ShaderClosure params;
704         float3 unused;
705
706         void setup(ShaderData *sd, int path_flag, float3 weight)
707         {
708                 bsdf_transparent_setup(sd, weight);
709         }
710 };
711
712 ClosureParam *closure_bsdf_transparent_params()
713 {
714         static ClosureParam params[] = {
715                 CLOSURE_STRING_KEYPARAM(TransparentClosure, label, "label"),
716                 CLOSURE_FINISH_PARAM(TransparentClosure)
717         };
718         return params;
719 }
720
721 CCLOSURE_PREPARE(closure_bsdf_transparent_prepare, TransparentClosure)
722
723 /* Volume */
724
725 class VolumeAbsorptionClosure : public CBSDFClosure {
726 public:
727         void setup(ShaderData *sd, int path_flag, float3 weight)
728         {
729                 volume_extinction_setup(sd, weight);
730         }
731 };
732
733 ClosureParam *closure_absorption_params()
734 {
735         static ClosureParam params[] = {
736                 CLOSURE_STRING_KEYPARAM(VolumeAbsorptionClosure, label, "label"),
737                 CLOSURE_FINISH_PARAM(VolumeAbsorptionClosure)
738         };
739         return params;
740 }
741
742 CCLOSURE_PREPARE(closure_absorption_prepare, VolumeAbsorptionClosure)
743
744 class VolumeHenyeyGreensteinClosure : public CBSDFClosure {
745 public:
746         HenyeyGreensteinVolume params;
747
748         void setup(ShaderData *sd, int path_flag, float3 weight)
749         {
750                 volume_extinction_setup(sd, weight);
751
752             HenyeyGreensteinVolume *volume = (HenyeyGreensteinVolume*)bsdf_alloc_osl(sd, sizeof(HenyeyGreensteinVolume), weight, &params);
753                 if(!volume) {
754                         return;
755                 }
756
757                 sd->flag |= volume_henyey_greenstein_setup(volume);
758         }
759 };
760
761 ClosureParam *closure_henyey_greenstein_params()
762 {
763         static ClosureParam params[] = {
764                 CLOSURE_FLOAT_PARAM(VolumeHenyeyGreensteinClosure, params.g),
765                 CLOSURE_STRING_KEYPARAM(VolumeHenyeyGreensteinClosure, label, "label"),
766                 CLOSURE_FINISH_PARAM(VolumeHenyeyGreensteinClosure)
767         };
768         return params;
769 }
770
771 CCLOSURE_PREPARE(closure_henyey_greenstein_prepare, VolumeHenyeyGreensteinClosure)
772
773
774 CCL_NAMESPACE_END
775