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-2018, 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 // clang-format off
43 #include "kernel/kernel_types.h"
44 #include "kernel/kernel_compat_cpu.h"
45 #include "kernel/split/kernel_split_data_types.h"
46 #include "kernel/kernel_globals.h"
47 #include "kernel/kernel_montecarlo.h"
48 #include "kernel/kernel_random.h"
49 
50 #include "kernel/closure/alloc.h"
51 #include "kernel/closure/bsdf_util.h"
52 #include "kernel/closure/bsdf_ashikhmin_velvet.h"
53 #include "kernel/closure/bsdf_diffuse.h"
54 #include "kernel/closure/bsdf_microfacet.h"
55 #include "kernel/closure/bsdf_microfacet_multi.h"
56 #include "kernel/closure/bsdf_oren_nayar.h"
57 #include "kernel/closure/bsdf_reflection.h"
58 #include "kernel/closure/bsdf_refraction.h"
59 #include "kernel/closure/bsdf_transparent.h"
60 #include "kernel/closure/bsdf_ashikhmin_shirley.h"
61 #include "kernel/closure/bsdf_toon.h"
62 #include "kernel/closure/bsdf_hair.h"
63 #include "kernel/closure/bsdf_hair_principled.h"
64 #include "kernel/closure/bsdf_principled_diffuse.h"
65 #include "kernel/closure/bsdf_principled_sheen.h"
66 #include "kernel/closure/volume.h"
67 // clang-format on
68 
69 CCL_NAMESPACE_BEGIN
70 
71 using namespace OSL;
72 
73 /* BSDF class definitions */
74 
75 BSDF_CLOSURE_CLASS_BEGIN(Diffuse, diffuse, DiffuseBsdf, LABEL_DIFFUSE)
76 CLOSURE_FLOAT3_PARAM(DiffuseClosure, params.N),
77     BSDF_CLOSURE_CLASS_END(Diffuse, diffuse)
78 
79         BSDF_CLOSURE_CLASS_BEGIN(Translucent, translucent, DiffuseBsdf, LABEL_DIFFUSE)
80             CLOSURE_FLOAT3_PARAM(TranslucentClosure, params.N),
81     BSDF_CLOSURE_CLASS_END(Translucent, translucent)
82 
83         BSDF_CLOSURE_CLASS_BEGIN(OrenNayar, oren_nayar, OrenNayarBsdf, LABEL_DIFFUSE)
84             CLOSURE_FLOAT3_PARAM(OrenNayarClosure, params.N),
85     CLOSURE_FLOAT_PARAM(OrenNayarClosure, params.roughness),
86     BSDF_CLOSURE_CLASS_END(OrenNayar, oren_nayar)
87 
88         BSDF_CLOSURE_CLASS_BEGIN(Reflection, reflection, MicrofacetBsdf, LABEL_SINGULAR)
89             CLOSURE_FLOAT3_PARAM(ReflectionClosure, params.N),
90     BSDF_CLOSURE_CLASS_END(Reflection, reflection)
91 
92         BSDF_CLOSURE_CLASS_BEGIN(Refraction, refraction, MicrofacetBsdf, LABEL_SINGULAR)
93             CLOSURE_FLOAT3_PARAM(RefractionClosure, params.N),
94     CLOSURE_FLOAT_PARAM(RefractionClosure, params.ior),
95     BSDF_CLOSURE_CLASS_END(Refraction, refraction)
96 
97         BSDF_CLOSURE_CLASS_BEGIN(AshikhminVelvet, ashikhmin_velvet, VelvetBsdf, LABEL_DIFFUSE)
98             CLOSURE_FLOAT3_PARAM(AshikhminVelvetClosure, params.N),
99     CLOSURE_FLOAT_PARAM(AshikhminVelvetClosure, params.sigma),
100     BSDF_CLOSURE_CLASS_END(AshikhminVelvet, ashikhmin_velvet)
101 
102         BSDF_CLOSURE_CLASS_BEGIN(AshikhminShirley,
103                                  ashikhmin_shirley,
104                                  MicrofacetBsdf,
105                                  LABEL_GLOSSY | LABEL_REFLECT)
106             CLOSURE_FLOAT3_PARAM(AshikhminShirleyClosure, params.N),
107     CLOSURE_FLOAT3_PARAM(AshikhminShirleyClosure, params.T),
108     CLOSURE_FLOAT_PARAM(AshikhminShirleyClosure, params.alpha_x),
109     CLOSURE_FLOAT_PARAM(AshikhminShirleyClosure, params.alpha_y),
110     BSDF_CLOSURE_CLASS_END(AshikhminShirley, ashikhmin_shirley)
111 
112         BSDF_CLOSURE_CLASS_BEGIN(DiffuseToon, diffuse_toon, ToonBsdf, LABEL_DIFFUSE)
113             CLOSURE_FLOAT3_PARAM(DiffuseToonClosure, params.N),
114     CLOSURE_FLOAT_PARAM(DiffuseToonClosure, params.size),
115     CLOSURE_FLOAT_PARAM(DiffuseToonClosure, params.smooth),
116     BSDF_CLOSURE_CLASS_END(DiffuseToon, diffuse_toon)
117 
118         BSDF_CLOSURE_CLASS_BEGIN(GlossyToon, glossy_toon, ToonBsdf, LABEL_GLOSSY)
119             CLOSURE_FLOAT3_PARAM(GlossyToonClosure, params.N),
120     CLOSURE_FLOAT_PARAM(GlossyToonClosure, params.size),
121     CLOSURE_FLOAT_PARAM(GlossyToonClosure, params.smooth),
122     BSDF_CLOSURE_CLASS_END(GlossyToon, glossy_toon)
123 
124         BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXIsotropic,
125                                  microfacet_ggx_isotropic,
126                                  MicrofacetBsdf,
127                                  LABEL_GLOSSY | LABEL_REFLECT)
128             CLOSURE_FLOAT3_PARAM(MicrofacetGGXIsotropicClosure, params.N),
129     CLOSURE_FLOAT_PARAM(MicrofacetGGXIsotropicClosure, params.alpha_x),
130     BSDF_CLOSURE_CLASS_END(MicrofacetGGXIsotropic, microfacet_ggx_isotropic)
131 
132         BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGX,
133                                  microfacet_ggx,
134                                  MicrofacetBsdf,
135                                  LABEL_GLOSSY | LABEL_REFLECT)
136             CLOSURE_FLOAT3_PARAM(MicrofacetGGXClosure, params.N),
137     CLOSURE_FLOAT3_PARAM(MicrofacetGGXClosure, params.T),
138     CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure, params.alpha_x),
139     CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure, params.alpha_y),
140     BSDF_CLOSURE_CLASS_END(MicrofacetGGX, microfacet_ggx)
141 
142         BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannIsotropic,
143                                  microfacet_beckmann_isotropic,
144                                  MicrofacetBsdf,
145                                  LABEL_GLOSSY | LABEL_REFLECT)
146             CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannIsotropicClosure, params.N),
147     CLOSURE_FLOAT_PARAM(MicrofacetBeckmannIsotropicClosure, params.alpha_x),
148     BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannIsotropic, microfacet_beckmann_isotropic)
149 
150         BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmann,
151                                  microfacet_beckmann,
152                                  MicrofacetBsdf,
153                                  LABEL_GLOSSY | LABEL_REFLECT)
154             CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannClosure, params.N),
155     CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannClosure, params.T),
156     CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure, params.alpha_x),
157     CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure, params.alpha_y),
158     BSDF_CLOSURE_CLASS_END(MicrofacetBeckmann, microfacet_beckmann)
159 
160         BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXRefraction,
161                                  microfacet_ggx_refraction,
162                                  MicrofacetBsdf,
163                                  LABEL_GLOSSY | LABEL_TRANSMIT)
164             CLOSURE_FLOAT3_PARAM(MicrofacetGGXRefractionClosure, params.N),
165     CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, params.alpha_x),
166     CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, params.ior),
167     BSDF_CLOSURE_CLASS_END(MicrofacetGGXRefraction, microfacet_ggx_refraction)
168 
169         BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannRefraction,
170                                  microfacet_beckmann_refraction,
171                                  MicrofacetBsdf,
172                                  LABEL_GLOSSY | LABEL_TRANSMIT)
173             CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannRefractionClosure, params.N),
174     CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, params.alpha_x),
175     CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, params.ior),
176     BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction)
177 
178         BSDF_CLOSURE_CLASS_BEGIN(HairReflection, hair_reflection, HairBsdf, LABEL_GLOSSY)
179             CLOSURE_FLOAT3_PARAM(HairReflectionClosure, params.N),
180     CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.roughness1),
181     CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.roughness2),
182     CLOSURE_FLOAT3_PARAM(HairReflectionClosure, params.T),
183     CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.offset),
184     BSDF_CLOSURE_CLASS_END(HairReflection, hair_reflection)
185 
186         BSDF_CLOSURE_CLASS_BEGIN(HairTransmission, hair_transmission, HairBsdf, LABEL_GLOSSY)
187             CLOSURE_FLOAT3_PARAM(HairTransmissionClosure, params.N),
188     CLOSURE_FLOAT_PARAM(HairTransmissionClosure, params.roughness1),
189     CLOSURE_FLOAT_PARAM(HairTransmissionClosure, params.roughness2),
190     CLOSURE_FLOAT3_PARAM(HairReflectionClosure, params.T),
191     CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.offset),
192     BSDF_CLOSURE_CLASS_END(HairTransmission, hair_transmission)
193 
194         BSDF_CLOSURE_CLASS_BEGIN(PrincipledDiffuse,
195                                  principled_diffuse,
196                                  PrincipledDiffuseBsdf,
197                                  LABEL_DIFFUSE)
198             CLOSURE_FLOAT3_PARAM(PrincipledDiffuseClosure, params.N),
199     CLOSURE_FLOAT_PARAM(PrincipledDiffuseClosure, params.roughness),
200     BSDF_CLOSURE_CLASS_END(PrincipledDiffuse, principled_diffuse)
201 
202         class PrincipledSheenClosure : public CBSDFClosure {
203  public:
204   PrincipledSheenBsdf params;
205 
setup(ShaderData * sd,int path_flag,float3 weight)206   void setup(ShaderData *sd, int path_flag, float3 weight)
207   {
208     if (!skip(sd, path_flag, LABEL_DIFFUSE)) {
209       PrincipledSheenBsdf *bsdf = (PrincipledSheenBsdf *)bsdf_alloc_osl(
210           sd, sizeof(PrincipledSheenBsdf), weight, &params);
211       sd->flag |= (bsdf) ? bsdf_principled_sheen_setup(sd, bsdf) : 0;
212     }
213   }
214 };
215 
bsdf_principled_sheen_params()216 static ClosureParam *bsdf_principled_sheen_params()
217 {
218   static ClosureParam params[] = {CLOSURE_FLOAT3_PARAM(PrincipledSheenClosure, params.N),
219                                   CLOSURE_STRING_KEYPARAM(PrincipledSheenClosure, label, "label"),
220                                   CLOSURE_FINISH_PARAM(PrincipledSheenClosure)};
221   return params;
222 }
223 
224 CCLOSURE_PREPARE_STATIC(closure_bsdf_principled_sheen_prepare, PrincipledSheenClosure)
225 
226 /* PRINCIPLED HAIR BSDF */
227 class PrincipledHairClosure : public CBSDFClosure {
228  public:
229   PrincipledHairBSDF params;
230 
alloc(ShaderData * sd,int path_flag,float3 weight)231   PrincipledHairBSDF *alloc(ShaderData *sd, int path_flag, float3 weight)
232   {
233     PrincipledHairBSDF *bsdf = (PrincipledHairBSDF *)bsdf_alloc_osl(
234         sd, sizeof(PrincipledHairBSDF), weight, &params);
235     if (!bsdf) {
236       return NULL;
237     }
238 
239     PrincipledHairExtra *extra = (PrincipledHairExtra *)closure_alloc_extra(
240         sd, sizeof(PrincipledHairExtra));
241     if (!extra) {
242       return NULL;
243     }
244 
245     bsdf->extra = extra;
246     return bsdf;
247   }
248 
setup(ShaderData * sd,int path_flag,float3 weight)249   void setup(ShaderData *sd, int path_flag, float3 weight)
250   {
251     if (!skip(sd, path_flag, LABEL_GLOSSY)) {
252       PrincipledHairBSDF *bsdf = (PrincipledHairBSDF *)alloc(sd, path_flag, weight);
253       if (!bsdf) {
254         return;
255       }
256 
257       sd->flag |= (bsdf) ? bsdf_principled_hair_setup(sd, bsdf) : 0;
258     }
259   }
260 };
261 
closure_bsdf_principled_hair_params()262 static ClosureParam *closure_bsdf_principled_hair_params()
263 {
264   static ClosureParam params[] = {CLOSURE_FLOAT3_PARAM(PrincipledHairClosure, params.N),
265                                   CLOSURE_FLOAT3_PARAM(PrincipledHairClosure, params.sigma),
266                                   CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.v),
267                                   CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.s),
268                                   CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.m0_roughness),
269                                   CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.alpha),
270                                   CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.eta),
271                                   CLOSURE_STRING_KEYPARAM(PrincipledHairClosure, label, "label"),
272                                   CLOSURE_FINISH_PARAM(PrincipledHairClosure)};
273 
274   return params;
275 }
276 
277 CCLOSURE_PREPARE(closure_bsdf_principled_hair_prepare, PrincipledHairClosure)
278 
279 /* DISNEY PRINCIPLED CLEARCOAT */
280 class PrincipledClearcoatClosure : public CBSDFClosure {
281  public:
282   MicrofacetBsdf params;
283   float clearcoat, clearcoat_roughness;
284 
alloc(ShaderData * sd,int path_flag,float3 weight)285   MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
286   {
287     MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl(
288         sd, sizeof(MicrofacetBsdf), weight, &params);
289     if (!bsdf) {
290       return NULL;
291     }
292 
293     MicrofacetExtra *extra = (MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
294     if (!extra) {
295       return NULL;
296     }
297 
298     bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
299     bsdf->extra = extra;
300     bsdf->ior = 1.5f;
301     bsdf->alpha_x = clearcoat_roughness;
302     bsdf->alpha_y = clearcoat_roughness;
303     bsdf->extra->color = make_float3(0.0f, 0.0f, 0.0f);
304     bsdf->extra->cspec0 = make_float3(0.04f, 0.04f, 0.04f);
305     bsdf->extra->clearcoat = clearcoat;
306     return bsdf;
307   }
308 
setup(ShaderData * sd,int path_flag,float3 weight)309   void setup(ShaderData *sd, int path_flag, float3 weight)
310   {
311     MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
312     if (!bsdf) {
313       return;
314     }
315 
316     sd->flag |= bsdf_microfacet_ggx_clearcoat_setup(bsdf, sd);
317   }
318 };
319 
closure_bsdf_principled_clearcoat_params()320 ClosureParam *closure_bsdf_principled_clearcoat_params()
321 {
322   static ClosureParam params[] = {
323       CLOSURE_FLOAT3_PARAM(PrincipledClearcoatClosure, params.N),
324       CLOSURE_FLOAT_PARAM(PrincipledClearcoatClosure, clearcoat),
325       CLOSURE_FLOAT_PARAM(PrincipledClearcoatClosure, clearcoat_roughness),
326       CLOSURE_STRING_KEYPARAM(PrincipledClearcoatClosure, label, "label"),
327       CLOSURE_FINISH_PARAM(PrincipledClearcoatClosure)};
328   return params;
329 }
CCLOSURE_PREPARE(closure_bsdf_principled_clearcoat_prepare,PrincipledClearcoatClosure)330 CCLOSURE_PREPARE(closure_bsdf_principled_clearcoat_prepare, PrincipledClearcoatClosure)
331 
332 /* Registration */
333 
334 static void register_closure(OSL::ShadingSystem *ss,
335                              const char *name,
336                              int id,
337                              OSL::ClosureParam *params,
338                              OSL::PrepareClosureFunc prepare)
339 {
340   /* optimization: it's possible to not use a prepare function at all and
341    * only initialize the actual class when accessing the closure component
342    * data, but then we need to map the id to the class somehow */
343 #if OSL_LIBRARY_VERSION_CODE >= 10900
344   ss->register_closure(name, id, params, prepare, NULL);
345 #else
346   ss->register_closure(name, id, params, prepare, NULL, 16);
347 #endif
348 }
349 
register_closures(OSLShadingSystem * ss_)350 void OSLShader::register_closures(OSLShadingSystem *ss_)
351 {
352   OSL::ShadingSystem *ss = (OSL::ShadingSystem *)ss_;
353   int id = 0;
354 
355   register_closure(ss, "diffuse", id++, bsdf_diffuse_params(), bsdf_diffuse_prepare);
356   register_closure(ss, "oren_nayar", id++, bsdf_oren_nayar_params(), bsdf_oren_nayar_prepare);
357   register_closure(ss, "translucent", id++, bsdf_translucent_params(), bsdf_translucent_prepare);
358   register_closure(ss, "reflection", id++, bsdf_reflection_params(), bsdf_reflection_prepare);
359   register_closure(ss, "refraction", id++, bsdf_refraction_params(), bsdf_refraction_prepare);
360   register_closure(ss,
361                    "transparent",
362                    id++,
363                    closure_bsdf_transparent_params(),
364                    closure_bsdf_transparent_prepare);
365 
366   register_closure(
367       ss, "microfacet", id++, closure_bsdf_microfacet_params(), closure_bsdf_microfacet_prepare);
368   register_closure(ss,
369                    "microfacet_ggx",
370                    id++,
371                    bsdf_microfacet_ggx_isotropic_params(),
372                    bsdf_microfacet_ggx_isotropic_prepare);
373   register_closure(
374       ss, "microfacet_ggx_aniso", id++, bsdf_microfacet_ggx_params(), bsdf_microfacet_ggx_prepare);
375   register_closure(ss,
376                    "microfacet_ggx_refraction",
377                    id++,
378                    bsdf_microfacet_ggx_refraction_params(),
379                    bsdf_microfacet_ggx_refraction_prepare);
380   register_closure(ss,
381                    "microfacet_multi_ggx",
382                    id++,
383                    closure_bsdf_microfacet_multi_ggx_params(),
384                    closure_bsdf_microfacet_multi_ggx_prepare);
385   register_closure(ss,
386                    "microfacet_multi_ggx_glass",
387                    id++,
388                    closure_bsdf_microfacet_multi_ggx_glass_params(),
389                    closure_bsdf_microfacet_multi_ggx_glass_prepare);
390   register_closure(ss,
391                    "microfacet_multi_ggx_aniso",
392                    id++,
393                    closure_bsdf_microfacet_multi_ggx_aniso_params(),
394                    closure_bsdf_microfacet_multi_ggx_aniso_prepare);
395   register_closure(ss,
396                    "microfacet_ggx_fresnel",
397                    id++,
398                    closure_bsdf_microfacet_ggx_fresnel_params(),
399                    closure_bsdf_microfacet_ggx_fresnel_prepare);
400   register_closure(ss,
401                    "microfacet_ggx_aniso_fresnel",
402                    id++,
403                    closure_bsdf_microfacet_ggx_aniso_fresnel_params(),
404                    closure_bsdf_microfacet_ggx_aniso_fresnel_prepare);
405   register_closure(ss,
406                    "microfacet_multi_ggx_fresnel",
407                    id++,
408                    closure_bsdf_microfacet_multi_ggx_fresnel_params(),
409                    closure_bsdf_microfacet_multi_ggx_fresnel_prepare);
410   register_closure(ss,
411                    "microfacet_multi_ggx_glass_fresnel",
412                    id++,
413                    closure_bsdf_microfacet_multi_ggx_glass_fresnel_params(),
414                    closure_bsdf_microfacet_multi_ggx_glass_fresnel_prepare);
415   register_closure(ss,
416                    "microfacet_multi_ggx_aniso_fresnel",
417                    id++,
418                    closure_bsdf_microfacet_multi_ggx_aniso_fresnel_params(),
419                    closure_bsdf_microfacet_multi_ggx_aniso_fresnel_prepare);
420   register_closure(ss,
421                    "microfacet_beckmann",
422                    id++,
423                    bsdf_microfacet_beckmann_isotropic_params(),
424                    bsdf_microfacet_beckmann_isotropic_prepare);
425   register_closure(ss,
426                    "microfacet_beckmann_aniso",
427                    id++,
428                    bsdf_microfacet_beckmann_params(),
429                    bsdf_microfacet_beckmann_prepare);
430   register_closure(ss,
431                    "microfacet_beckmann_refraction",
432                    id++,
433                    bsdf_microfacet_beckmann_refraction_params(),
434                    bsdf_microfacet_beckmann_refraction_prepare);
435   register_closure(ss,
436                    "ashikhmin_shirley",
437                    id++,
438                    bsdf_ashikhmin_shirley_params(),
439                    bsdf_ashikhmin_shirley_prepare);
440   register_closure(
441       ss, "ashikhmin_velvet", id++, bsdf_ashikhmin_velvet_params(), bsdf_ashikhmin_velvet_prepare);
442   register_closure(
443       ss, "diffuse_toon", id++, bsdf_diffuse_toon_params(), bsdf_diffuse_toon_prepare);
444   register_closure(ss, "glossy_toon", id++, bsdf_glossy_toon_params(), bsdf_glossy_toon_prepare);
445   register_closure(ss,
446                    "principled_diffuse",
447                    id++,
448                    bsdf_principled_diffuse_params(),
449                    bsdf_principled_diffuse_prepare);
450   register_closure(ss,
451                    "principled_sheen",
452                    id++,
453                    bsdf_principled_sheen_params(),
454                    closure_bsdf_principled_sheen_prepare);
455   register_closure(ss,
456                    "principled_clearcoat",
457                    id++,
458                    closure_bsdf_principled_clearcoat_params(),
459                    closure_bsdf_principled_clearcoat_prepare);
460 
461   register_closure(ss, "emission", id++, closure_emission_params(), closure_emission_prepare);
462   register_closure(
463       ss, "background", id++, closure_background_params(), closure_background_prepare);
464   register_closure(ss, "holdout", id++, closure_holdout_params(), closure_holdout_prepare);
465   register_closure(ss,
466                    "diffuse_ramp",
467                    id++,
468                    closure_bsdf_diffuse_ramp_params(),
469                    closure_bsdf_diffuse_ramp_prepare);
470   register_closure(
471       ss, "phong_ramp", id++, closure_bsdf_phong_ramp_params(), closure_bsdf_phong_ramp_prepare);
472   register_closure(ss, "bssrdf", id++, closure_bssrdf_params(), closure_bssrdf_prepare);
473 
474   register_closure(
475       ss, "hair_reflection", id++, bsdf_hair_reflection_params(), bsdf_hair_reflection_prepare);
476   register_closure(ss,
477                    "hair_transmission",
478                    id++,
479                    bsdf_hair_transmission_params(),
480                    bsdf_hair_transmission_prepare);
481 
482   register_closure(ss,
483                    "principled_hair",
484                    id++,
485                    closure_bsdf_principled_hair_params(),
486                    closure_bsdf_principled_hair_prepare);
487 
488   register_closure(ss,
489                    "henyey_greenstein",
490                    id++,
491                    closure_henyey_greenstein_params(),
492                    closure_henyey_greenstein_prepare);
493   register_closure(
494       ss, "absorption", id++, closure_absorption_params(), closure_absorption_prepare);
495 }
496 
497 /* BSDF Closure */
498 
skip(const ShaderData * sd,int path_flag,int scattering)499 bool CBSDFClosure::skip(const ShaderData *sd, int path_flag, int scattering)
500 {
501   /* caustic options */
502   if ((scattering & LABEL_GLOSSY) && (path_flag & PATH_RAY_DIFFUSE)) {
503     KernelGlobals *kg = sd->osl_globals;
504 
505     if ((!kernel_data.integrator.caustics_reflective && (scattering & LABEL_REFLECT)) ||
506         (!kernel_data.integrator.caustics_refractive && (scattering & LABEL_TRANSMIT))) {
507       return true;
508     }
509   }
510 
511   return false;
512 }
513 
514 /* Standard Microfacet Closure */
515 
516 class MicrofacetClosure : public CBSDFClosure {
517  public:
518   MicrofacetBsdf params;
519   ustring distribution;
520   int refract;
521 
setup(ShaderData * sd,int path_flag,float3 weight)522   void setup(ShaderData *sd, int path_flag, float3 weight)
523   {
524     static ustring u_ggx("ggx");
525     static ustring u_default("default");
526 
527     const int label = (refract) ? LABEL_TRANSMIT : LABEL_REFLECT;
528     if (skip(sd, path_flag, LABEL_GLOSSY | label)) {
529       return;
530     }
531 
532     MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl(
533         sd, sizeof(MicrofacetBsdf), weight, &params);
534 
535     if (!bsdf) {
536       return;
537     }
538 
539     /* GGX */
540     if (distribution == u_ggx || distribution == u_default) {
541       if (!refract) {
542         if (params.alpha_x == params.alpha_y) {
543           /* Isotropic */
544           sd->flag |= bsdf_microfacet_ggx_isotropic_setup(bsdf);
545         }
546         else {
547           /* Anisotropic */
548           sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
549         }
550       }
551       else {
552         sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
553       }
554     }
555     /* Beckmann */
556     else {
557       if (!refract) {
558         if (params.alpha_x == params.alpha_y) {
559           /* Isotropic */
560           sd->flag |= bsdf_microfacet_beckmann_isotropic_setup(bsdf);
561         }
562         else {
563           /* Anisotropic */
564           sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
565         }
566       }
567       else {
568         sd->flag |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
569       }
570     }
571   }
572 };
573 
closure_bsdf_microfacet_params()574 ClosureParam *closure_bsdf_microfacet_params()
575 {
576   static ClosureParam params[] = {CLOSURE_STRING_PARAM(MicrofacetClosure, distribution),
577                                   CLOSURE_FLOAT3_PARAM(MicrofacetClosure, params.N),
578                                   CLOSURE_FLOAT3_PARAM(MicrofacetClosure, params.T),
579                                   CLOSURE_FLOAT_PARAM(MicrofacetClosure, params.alpha_x),
580                                   CLOSURE_FLOAT_PARAM(MicrofacetClosure, params.alpha_y),
581                                   CLOSURE_FLOAT_PARAM(MicrofacetClosure, params.ior),
582                                   CLOSURE_INT_PARAM(MicrofacetClosure, refract),
583                                   CLOSURE_STRING_KEYPARAM(MicrofacetClosure, label, "label"),
584                                   CLOSURE_FINISH_PARAM(MicrofacetClosure)};
585 
586   return params;
587 }
588 CCLOSURE_PREPARE(closure_bsdf_microfacet_prepare, MicrofacetClosure)
589 
590 /* GGX closures with Fresnel */
591 
592 class MicrofacetFresnelClosure : public CBSDFClosure {
593  public:
594   MicrofacetBsdf params;
595   float3 color;
596   float3 cspec0;
597 
alloc(ShaderData * sd,int path_flag,float3 weight)598   MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
599   {
600     /* Technically, the MultiGGX Glass closure may also transmit. However,
601      * since this is set statically and only used for caustic flags, this
602      * is probably as good as it gets. */
603     if (skip(sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
604       return NULL;
605     }
606 
607     MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl(
608         sd, sizeof(MicrofacetBsdf), weight, &params);
609     if (!bsdf) {
610       return NULL;
611     }
612 
613     MicrofacetExtra *extra = (MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
614     if (!extra) {
615       return NULL;
616     }
617 
618     bsdf->extra = extra;
619     bsdf->extra->color = color;
620     bsdf->extra->cspec0 = cspec0;
621     bsdf->extra->clearcoat = 0.0f;
622     return bsdf;
623   }
624 };
625 
626 class MicrofacetGGXFresnelClosure : public MicrofacetFresnelClosure {
627  public:
setup(ShaderData * sd,int path_flag,float3 weight)628   void setup(ShaderData *sd, int path_flag, float3 weight)
629   {
630     MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
631     if (!bsdf) {
632       return;
633     }
634 
635     bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
636     bsdf->alpha_y = bsdf->alpha_x;
637     sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd);
638   }
639 };
640 
closure_bsdf_microfacet_ggx_fresnel_params()641 ClosureParam *closure_bsdf_microfacet_ggx_fresnel_params()
642 {
643   static ClosureParam params[] = {
644       CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, params.N),
645       CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.alpha_x),
646       CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.ior),
647       CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, color),
648       CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, cspec0),
649       CLOSURE_STRING_KEYPARAM(MicrofacetGGXFresnelClosure, label, "label"),
650       CLOSURE_FINISH_PARAM(MicrofacetGGXFresnelClosure)};
651   return params;
652 }
653 CCLOSURE_PREPARE(closure_bsdf_microfacet_ggx_fresnel_prepare, MicrofacetGGXFresnelClosure);
654 
655 class MicrofacetGGXAnisoFresnelClosure : public MicrofacetFresnelClosure {
656  public:
setup(ShaderData * sd,int path_flag,float3 weight)657   void setup(ShaderData *sd, int path_flag, float3 weight)
658   {
659     MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
660     if (!bsdf) {
661       return;
662     }
663 
664     sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd);
665   }
666 };
667 
closure_bsdf_microfacet_ggx_aniso_fresnel_params()668 ClosureParam *closure_bsdf_microfacet_ggx_aniso_fresnel_params()
669 {
670   static ClosureParam params[] = {
671       CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, params.N),
672       CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, params.T),
673       CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.alpha_x),
674       CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.alpha_y),
675       CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.ior),
676       CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, color),
677       CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, cspec0),
678       CLOSURE_STRING_KEYPARAM(MicrofacetGGXFresnelClosure, label, "label"),
679       CLOSURE_FINISH_PARAM(MicrofacetGGXFresnelClosure)};
680   return params;
681 }
682 CCLOSURE_PREPARE(closure_bsdf_microfacet_ggx_aniso_fresnel_prepare,
683                  MicrofacetGGXAnisoFresnelClosure);
684 
685 /* Multiscattering GGX closures */
686 
687 class MicrofacetMultiClosure : public CBSDFClosure {
688  public:
689   MicrofacetBsdf params;
690   float3 color;
691 
alloc(ShaderData * sd,int path_flag,float3 weight)692   MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
693   {
694     /* Technically, the MultiGGX closure may also transmit. However,
695      * since this is set statically and only used for caustic flags, this
696      * is probably as good as it gets. */
697     if (skip(sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
698       return NULL;
699     }
700 
701     MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl(
702         sd, sizeof(MicrofacetBsdf), weight, &params);
703     if (!bsdf) {
704       return NULL;
705     }
706 
707     MicrofacetExtra *extra = (MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
708     if (!extra) {
709       return NULL;
710     }
711 
712     bsdf->extra = extra;
713     bsdf->extra->color = color;
714     bsdf->extra->cspec0 = make_float3(0.0f, 0.0f, 0.0f);
715     bsdf->extra->clearcoat = 0.0f;
716     return bsdf;
717   }
718 };
719 
720 class MicrofacetMultiGGXClosure : public MicrofacetMultiClosure {
721  public:
setup(ShaderData * sd,int path_flag,float3 weight)722   void setup(ShaderData *sd, int path_flag, float3 weight)
723   {
724     MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
725     if (!bsdf) {
726       return;
727     }
728 
729     bsdf->ior = 0.0f;
730     bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
731     bsdf->alpha_y = bsdf->alpha_x;
732     sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf);
733   }
734 };
735 
closure_bsdf_microfacet_multi_ggx_params()736 ClosureParam *closure_bsdf_microfacet_multi_ggx_params()
737 {
738   static ClosureParam params[] = {
739       CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, params.N),
740       CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.alpha_x),
741       CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, color),
742       CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXClosure, label, "label"),
743       CLOSURE_FINISH_PARAM(MicrofacetMultiGGXClosure)};
744   return params;
745 }
746 CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_prepare, MicrofacetMultiGGXClosure);
747 
748 class MicrofacetMultiGGXAnisoClosure : public MicrofacetMultiClosure {
749  public:
setup(ShaderData * sd,int path_flag,float3 weight)750   void setup(ShaderData *sd, int path_flag, float3 weight)
751   {
752     MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
753     if (!bsdf) {
754       return;
755     }
756 
757     bsdf->ior = 0.0f;
758     sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf);
759   }
760 };
761 
closure_bsdf_microfacet_multi_ggx_aniso_params()762 ClosureParam *closure_bsdf_microfacet_multi_ggx_aniso_params()
763 {
764   static ClosureParam params[] = {
765       CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, params.N),
766       CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, params.T),
767       CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.alpha_x),
768       CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.alpha_y),
769       CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, color),
770       CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXClosure, label, "label"),
771       CLOSURE_FINISH_PARAM(MicrofacetMultiGGXClosure)};
772   return params;
773 }
774 CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_aniso_prepare, MicrofacetMultiGGXAnisoClosure);
775 
776 class MicrofacetMultiGGXGlassClosure : public MicrofacetMultiClosure {
777  public:
MicrofacetMultiGGXGlassClosure()778   MicrofacetMultiGGXGlassClosure() : MicrofacetMultiClosure()
779   {
780   }
781 
setup(ShaderData * sd,int path_flag,float3 weight)782   void setup(ShaderData *sd, int path_flag, float3 weight)
783   {
784     MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
785     if (!bsdf) {
786       return;
787     }
788 
789     bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
790     bsdf->alpha_y = bsdf->alpha_x;
791     sd->flag |= bsdf_microfacet_multi_ggx_glass_setup(bsdf);
792   }
793 };
794 
closure_bsdf_microfacet_multi_ggx_glass_params()795 ClosureParam *closure_bsdf_microfacet_multi_ggx_glass_params()
796 {
797   static ClosureParam params[] = {
798       CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, params.N),
799       CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.alpha_x),
800       CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.ior),
801       CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, color),
802       CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXClosure, label, "label"),
803       CLOSURE_FINISH_PARAM(MicrofacetMultiGGXClosure)};
804   return params;
805 }
806 CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_glass_prepare, MicrofacetMultiGGXGlassClosure);
807 
808 /* Multiscattering GGX closures with Fresnel */
809 
810 class MicrofacetMultiFresnelClosure : public CBSDFClosure {
811  public:
812   MicrofacetBsdf params;
813   float3 color;
814   float3 cspec0;
815 
alloc(ShaderData * sd,int path_flag,float3 weight)816   MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
817   {
818     /* Technically, the MultiGGX closure may also transmit. However,
819      * since this is set statically and only used for caustic flags, this
820      * is probably as good as it gets. */
821     if (skip(sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
822       return NULL;
823     }
824 
825     MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl(
826         sd, sizeof(MicrofacetBsdf), weight, &params);
827     if (!bsdf) {
828       return NULL;
829     }
830 
831     MicrofacetExtra *extra = (MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
832     if (!extra) {
833       return NULL;
834     }
835 
836     bsdf->extra = extra;
837     bsdf->extra->color = color;
838     bsdf->extra->cspec0 = cspec0;
839     bsdf->extra->clearcoat = 0.0f;
840     return bsdf;
841   }
842 };
843 
844 class MicrofacetMultiGGXFresnelClosure : public MicrofacetMultiFresnelClosure {
845  public:
setup(ShaderData * sd,int path_flag,float3 weight)846   void setup(ShaderData *sd, int path_flag, float3 weight)
847   {
848     MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
849     if (!bsdf) {
850       return;
851     }
852 
853     bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
854     bsdf->alpha_y = bsdf->alpha_x;
855     sd->flag |= bsdf_microfacet_multi_ggx_fresnel_setup(bsdf, sd);
856   }
857 };
858 
closure_bsdf_microfacet_multi_ggx_fresnel_params()859 ClosureParam *closure_bsdf_microfacet_multi_ggx_fresnel_params()
860 {
861   static ClosureParam params[] = {
862       CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.N),
863       CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_x),
864       CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.ior),
865       CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, color),
866       CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, cspec0),
867       CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXFresnelClosure, label, "label"),
868       CLOSURE_FINISH_PARAM(MicrofacetMultiGGXFresnelClosure)};
869   return params;
870 }
871 CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_fresnel_prepare,
872                  MicrofacetMultiGGXFresnelClosure);
873 
874 class MicrofacetMultiGGXAnisoFresnelClosure : public MicrofacetMultiFresnelClosure {
875  public:
setup(ShaderData * sd,int path_flag,float3 weight)876   void setup(ShaderData *sd, int path_flag, float3 weight)
877   {
878     MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
879     if (!bsdf) {
880       return;
881     }
882 
883     sd->flag |= bsdf_microfacet_multi_ggx_fresnel_setup(bsdf, sd);
884   }
885 };
886 
closure_bsdf_microfacet_multi_ggx_aniso_fresnel_params()887 ClosureParam *closure_bsdf_microfacet_multi_ggx_aniso_fresnel_params()
888 {
889   static ClosureParam params[] = {
890       CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.N),
891       CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.T),
892       CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_x),
893       CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_y),
894       CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.ior),
895       CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, color),
896       CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, cspec0),
897       CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXFresnelClosure, label, "label"),
898       CLOSURE_FINISH_PARAM(MicrofacetMultiGGXFresnelClosure)};
899   return params;
900 }
901 CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_aniso_fresnel_prepare,
902                  MicrofacetMultiGGXAnisoFresnelClosure);
903 
904 class MicrofacetMultiGGXGlassFresnelClosure : public MicrofacetMultiFresnelClosure {
905  public:
MicrofacetMultiGGXGlassFresnelClosure()906   MicrofacetMultiGGXGlassFresnelClosure() : MicrofacetMultiFresnelClosure()
907   {
908   }
909 
setup(ShaderData * sd,int path_flag,float3 weight)910   void setup(ShaderData *sd, int path_flag, float3 weight)
911   {
912     MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
913     if (!bsdf) {
914       return;
915     }
916 
917     bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
918     bsdf->alpha_y = bsdf->alpha_x;
919     sd->flag |= bsdf_microfacet_multi_ggx_glass_fresnel_setup(bsdf, sd);
920   }
921 };
922 
closure_bsdf_microfacet_multi_ggx_glass_fresnel_params()923 ClosureParam *closure_bsdf_microfacet_multi_ggx_glass_fresnel_params()
924 {
925   static ClosureParam params[] = {
926       CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.N),
927       CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_x),
928       CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.ior),
929       CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, color),
930       CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, cspec0),
931       CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXFresnelClosure, label, "label"),
932       CLOSURE_FINISH_PARAM(MicrofacetMultiGGXFresnelClosure)};
933   return params;
934 }
935 CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_glass_fresnel_prepare,
936                  MicrofacetMultiGGXGlassFresnelClosure);
937 
938 /* Transparent */
939 
940 class TransparentClosure : public CBSDFClosure {
941  public:
942   ShaderClosure params;
943   float3 unused;
944 
setup(ShaderData * sd,int path_flag,float3 weight)945   void setup(ShaderData *sd, int path_flag, float3 weight)
946   {
947     bsdf_transparent_setup(sd, weight, path_flag);
948   }
949 };
950 
closure_bsdf_transparent_params()951 ClosureParam *closure_bsdf_transparent_params()
952 {
953   static ClosureParam params[] = {CLOSURE_STRING_KEYPARAM(TransparentClosure, label, "label"),
954                                   CLOSURE_FINISH_PARAM(TransparentClosure)};
955   return params;
956 }
957 
958 CCLOSURE_PREPARE(closure_bsdf_transparent_prepare, TransparentClosure)
959 
960 /* Volume */
961 
962 class VolumeAbsorptionClosure : public CBSDFClosure {
963  public:
setup(ShaderData * sd,int path_flag,float3 weight)964   void setup(ShaderData *sd, int path_flag, float3 weight)
965   {
966     volume_extinction_setup(sd, weight);
967   }
968 };
969 
closure_absorption_params()970 ClosureParam *closure_absorption_params()
971 {
972   static ClosureParam params[] = {CLOSURE_STRING_KEYPARAM(VolumeAbsorptionClosure, label, "label"),
973                                   CLOSURE_FINISH_PARAM(VolumeAbsorptionClosure)};
974   return params;
975 }
976 
977 CCLOSURE_PREPARE(closure_absorption_prepare, VolumeAbsorptionClosure)
978 
979 class VolumeHenyeyGreensteinClosure : public CBSDFClosure {
980  public:
981   HenyeyGreensteinVolume params;
982 
setup(ShaderData * sd,int path_flag,float3 weight)983   void setup(ShaderData *sd, int path_flag, float3 weight)
984   {
985     volume_extinction_setup(sd, weight);
986 
987     HenyeyGreensteinVolume *volume = (HenyeyGreensteinVolume *)bsdf_alloc_osl(
988         sd, sizeof(HenyeyGreensteinVolume), weight, &params);
989     if (!volume) {
990       return;
991     }
992 
993     sd->flag |= volume_henyey_greenstein_setup(volume);
994   }
995 };
996 
closure_henyey_greenstein_params()997 ClosureParam *closure_henyey_greenstein_params()
998 {
999   static ClosureParam params[] = {
1000       CLOSURE_FLOAT_PARAM(VolumeHenyeyGreensteinClosure, params.g),
1001       CLOSURE_STRING_KEYPARAM(VolumeHenyeyGreensteinClosure, label, "label"),
1002       CLOSURE_FINISH_PARAM(VolumeHenyeyGreensteinClosure)};
1003   return params;
1004 }
1005 
1006 CCLOSURE_PREPARE(closure_henyey_greenstein_prepare, VolumeHenyeyGreensteinClosure)
1007 
1008 CCL_NAMESPACE_END
1009