1
2 //
3 // This source file is part of appleseed.
4 // Visit https://appleseedhq.net/ for additional information and resources.
5 //
6 // This software is released under the MIT license.
7 //
8 // Copyright (c) 2014-2018 Esteban Tovagliari, The appleseedhq Organization
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining a copy
11 // of this software and associated documentation files (the "Software"), to deal
12 // in the Software without restriction, including without limitation the rights
13 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 // copies of the Software, and to permit persons to whom the Software is
15 // furnished to do so, subject to the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be included in
18 // all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 // THE SOFTWARE.
27 //
28
29 // Interface header.
30 #include "closures.h"
31
32 // appleseed.renderer headers.
33 #include "renderer/global/globallogger.h"
34 #include "renderer/kernel/npr/nprclosures.h"
35 #include "renderer/kernel/shading/oslshadingsystem.h"
36 #include "renderer/modeling/bsdf/ashikhminbrdf.h"
37 #include "renderer/modeling/bsdf/blinnbrdf.h"
38 #include "renderer/modeling/bsdf/diffusebtdf.h"
39 #include "renderer/modeling/bsdf/disneybrdf.h"
40 #include "renderer/modeling/bsdf/glassbsdf.h"
41 #include "renderer/modeling/bsdf/glossybrdf.h"
42 #include "renderer/modeling/bsdf/metalbrdf.h"
43 #include "renderer/modeling/bsdf/microfacethelper.h"
44 #include "renderer/modeling/bsdf/orennayarbrdf.h"
45 #include "renderer/modeling/bsdf/plasticbrdf.h"
46 #include "renderer/modeling/bsdf/sheenbrdf.h"
47 #include "renderer/modeling/bssrdf/dipolebssrdf.h"
48 #include "renderer/modeling/bssrdf/directionaldipolebssrdf.h"
49 #include "renderer/modeling/bssrdf/gaussianbssrdf.h"
50 #include "renderer/modeling/bssrdf/normalizeddiffusionbssrdf.h"
51 #include "renderer/modeling/bssrdf/randomwalkbssrdf.h"
52 #include "renderer/modeling/color/colorspace.h"
53 #include "renderer/modeling/edf/diffuseedf.h"
54
55 // appleseed.foundation headers.
56 #include "foundation/math/cdf.h"
57 #include "foundation/math/fresnel.h"
58 #include "foundation/math/scalar.h"
59 #include "foundation/utility/arena.h"
60 #include "foundation/utility/memory.h"
61 #include "foundation/utility/otherwise.h"
62
63 // OSL headers.
64 #include "foundation/platform/_beginoslheaders.h"
65 #include "OSL/genclosure.h"
66 #include "OSL/oslclosure.h"
67 #include "OSL/oslversion.h"
68 #include "foundation/platform/_endoslheaders.h"
69
70 // Standard headers.
71 #include <algorithm>
72 #include <cmath>
73
74 using namespace foundation;
75 using namespace renderer;
76 using namespace std;
77
78 using OSL::TypeDesc;
79
80 namespace renderer
81 {
82 namespace
83 {
84
85 //
86 // Global ustrings.
87 //
88
89 const OIIO::ustring g_beckmann_str("beckmann");
90 const OIIO::ustring g_ggx_str("ggx");
91 const OIIO::ustring g_gtr1_str("gtr1");
92 const OIIO::ustring g_std_str("std");
93
94 const OIIO::ustring g_standard_dipole_profile_str("standard_dipole");
95 const OIIO::ustring g_better_dipole_profile_str("better_dipole");
96 const OIIO::ustring g_directional_dipole_profile_str("directional_dipole");
97 const OIIO::ustring g_normalized_diffusion_profile_str("normalized_diffusion");
98 const OIIO::ustring g_gaussian_profile_str("gaussian");
99 const OIIO::ustring g_randomwalk_profile_str("randomwalk");
100
101 //
102 // Closure functions.
103 //
104
105 typedef void (*convert_closure_fun)(
106 CompositeSurfaceClosure& composite_closure,
107 const Basis3f& shading_basis,
108 const void* osl_params,
109 const Color3f& weight,
110 Arena& arena);
111
112 convert_closure_fun g_closure_convert_funs[NumClosuresIDs];
113
convert_closure_nop(CompositeSurfaceClosure & composite_closure,const Basis3f & shading_basis,const void * osl_params,const Color3f & weight,Arena & arena)114 void convert_closure_nop(
115 CompositeSurfaceClosure& composite_closure,
116 const Basis3f& shading_basis,
117 const void* osl_params,
118 const Color3f& weight,
119 Arena& arena)
120 {
121 }
122
123 typedef int (*closure_get_modes)();
124
125 closure_get_modes g_closure_get_modes_funs[NumClosuresIDs];
126
closure_no_modes()127 int closure_no_modes()
128 {
129 return 0;
130 }
131
132 //
133 // Closures.
134 //
135
136 struct AshikhminShirleyClosure
137 {
138 struct Params
139 {
140 OSL::Vec3 N;
141 OSL::Vec3 T;
142 OSL::Color3 diffuse_reflectance;
143 OSL::Color3 glossy_reflectance;
144 float exponent_u;
145 float exponent_v;
146 float fresnel_multiplier;
147 };
148
namerenderer::__anon50bdf1300111::AshikhminShirleyClosure149 static const char* name()
150 {
151 return "as_ashikhmin_shirley";
152 }
153
idrenderer::__anon50bdf1300111::AshikhminShirleyClosure154 static ClosureID id()
155 {
156 return AshikhminShirleyID;
157 }
158
modesrenderer::__anon50bdf1300111::AshikhminShirleyClosure159 static int modes()
160 {
161 return ScatteringMode::Diffuse | ScatteringMode::Glossy;
162 }
163
register_closurerenderer::__anon50bdf1300111::AshikhminShirleyClosure164 static void register_closure(OSLShadingSystem& shading_system)
165 {
166 const OSL::ClosureParam params[] =
167 {
168 CLOSURE_VECTOR_PARAM(Params, N),
169 CLOSURE_VECTOR_PARAM(Params, T),
170 CLOSURE_COLOR_PARAM(Params, diffuse_reflectance),
171 CLOSURE_COLOR_PARAM(Params, glossy_reflectance),
172 CLOSURE_FLOAT_PARAM(Params, exponent_u),
173 CLOSURE_FLOAT_PARAM(Params, exponent_v),
174 CLOSURE_FLOAT_PARAM(Params, fresnel_multiplier),
175 CLOSURE_FINISH_PARAM(Params)
176 };
177
178 shading_system.register_closure(name(), id(), params, nullptr, nullptr);
179
180 g_closure_convert_funs[id()] = &convert_closure;
181 g_closure_get_modes_funs[id()] = &modes;
182 }
183
convert_closurerenderer::__anon50bdf1300111::AshikhminShirleyClosure184 static void convert_closure(
185 CompositeSurfaceClosure& composite_closure,
186 const Basis3f& shading_basis,
187 const void* osl_params,
188 const Color3f& weight,
189 Arena& arena)
190 {
191 const Params* p = static_cast<const Params*>(osl_params);
192
193 AshikhminBRDFInputValues* values =
194 composite_closure.add_closure<AshikhminBRDFInputValues>(
195 id(),
196 shading_basis,
197 weight,
198 p->N,
199 p->T,
200 arena);
201
202 values->m_rd.set(Color3f(p->diffuse_reflectance), g_std_lighting_conditions, Spectrum::Reflectance);
203 values->m_rd_multiplier = 1.0f;
204 values->m_rg.set(Color3f(p->glossy_reflectance), g_std_lighting_conditions, Spectrum::Reflectance);
205 values->m_rg_multiplier = 1.0f;
206 values->m_nu = max(p->exponent_u, 0.01f);
207 values->m_nv = max(p->exponent_v, 0.01f);
208 values->m_fr_multiplier = p->fresnel_multiplier;
209 }
210 };
211
212 struct BackgroundClosure
213 {
214 struct Params
215 {
216 };
217
namerenderer::__anon50bdf1300111::BackgroundClosure218 static const char* name()
219 {
220 return "background";
221 }
222
idrenderer::__anon50bdf1300111::BackgroundClosure223 static ClosureID id()
224 {
225 return BackgroundID;
226 }
227
register_closurerenderer::__anon50bdf1300111::BackgroundClosure228 static void register_closure(OSLShadingSystem& shading_system)
229 {
230 const OSL::ClosureParam params[] =
231 {
232 CLOSURE_FINISH_PARAM(Params)
233 };
234
235 shading_system.register_closure(name(), id(), params, nullptr, nullptr);
236 }
237 };
238
239 struct BlinnClosure
240 {
241 struct Params
242 {
243 OSL::Vec3 N;
244 float exponent;
245 float ior;
246 };
247
namerenderer::__anon50bdf1300111::BlinnClosure248 static const char* name()
249 {
250 return "as_blinn";
251 }
252
idrenderer::__anon50bdf1300111::BlinnClosure253 static ClosureID id()
254 {
255 return BlinnID;
256 }
257
modesrenderer::__anon50bdf1300111::BlinnClosure258 static int modes()
259 {
260 return ScatteringMode::Glossy;
261 }
262
register_closurerenderer::__anon50bdf1300111::BlinnClosure263 static void register_closure(OSLShadingSystem& shading_system)
264 {
265 const OSL::ClosureParam params[] =
266 {
267 CLOSURE_VECTOR_PARAM(Params, N),
268 CLOSURE_FLOAT_PARAM(Params, exponent),
269 CLOSURE_FLOAT_PARAM(Params, ior),
270 CLOSURE_FINISH_PARAM(Params)
271 };
272
273 shading_system.register_closure(name(), id(), params, nullptr, nullptr);
274
275 g_closure_convert_funs[id()] = &convert_closure;
276 g_closure_get_modes_funs[id()] = &modes;
277 }
278
convert_closurerenderer::__anon50bdf1300111::BlinnClosure279 static void convert_closure(
280 CompositeSurfaceClosure& composite_closure,
281 const Basis3f& shading_basis,
282 const void* osl_params,
283 const Color3f& weight,
284 Arena& arena)
285 {
286 const Params* p = static_cast<const Params*>(osl_params);
287
288 BlinnBRDFInputValues* values =
289 composite_closure.add_closure<BlinnBRDFInputValues>(
290 BlinnID,
291 shading_basis,
292 weight,
293 p->N,
294 arena);
295
296 values->m_exponent = max(p->exponent, 0.001f);
297 values->m_ior = max(p->ior, 0.001f);
298 }
299 };
300
301 struct DebugClosure
302 {
303 struct Params
304 {
305 OSL::ustring tag;
306 };
307
namerenderer::__anon50bdf1300111::DebugClosure308 static const char* name()
309 {
310 return "debug";
311 }
312
idrenderer::__anon50bdf1300111::DebugClosure313 static ClosureID id()
314 {
315 return DebugID;
316 }
317
register_closurerenderer::__anon50bdf1300111::DebugClosure318 static void register_closure(OSLShadingSystem& shading_system)
319 {
320 const OSL::ClosureParam params[] =
321 {
322 CLOSURE_STRING_PARAM(Params, tag),
323 CLOSURE_FINISH_PARAM(Params)
324 };
325
326 shading_system.register_closure(name(), id(), params, nullptr, nullptr);
327 }
328 };
329
330 struct DiffuseClosure
331 {
332 struct Params
333 {
334 OSL::Vec3 N;
335 };
336
namerenderer::__anon50bdf1300111::DiffuseClosure337 static const char* name()
338 {
339 return "diffuse";
340 }
341
idrenderer::__anon50bdf1300111::DiffuseClosure342 static ClosureID id()
343 {
344 return DiffuseID;
345 }
346
modesrenderer::__anon50bdf1300111::DiffuseClosure347 static int modes()
348 {
349 return ScatteringMode::Diffuse;
350 }
351
register_closurerenderer::__anon50bdf1300111::DiffuseClosure352 static void register_closure(OSLShadingSystem& shading_system)
353 {
354 const OSL::ClosureParam params[] =
355 {
356 CLOSURE_VECTOR_PARAM(Params, N),
357 CLOSURE_FINISH_PARAM(Params)
358 };
359
360 shading_system.register_closure(name(), id(), params, nullptr, nullptr);
361
362 g_closure_convert_funs[id()] = &convert_closure;
363 g_closure_get_modes_funs[id()] = &modes;
364 }
365
convert_closurerenderer::__anon50bdf1300111::DiffuseClosure366 static void convert_closure(
367 CompositeSurfaceClosure& composite_closure,
368 const Basis3f& shading_basis,
369 const void* osl_params,
370 const Color3f& weight,
371 Arena& arena)
372 {
373 const Params* p = static_cast<const Params*>(osl_params);
374
375 OrenNayarBRDFInputValues* values =
376 composite_closure.add_closure<OrenNayarBRDFInputValues>(
377 OrenNayarID,
378 shading_basis,
379 weight,
380 p->N,
381 arena);
382
383 values->m_reflectance.set(1.0f);
384 values->m_reflectance_multiplier = 1.0f;
385 values->m_roughness = 0.0f;
386 }
387 };
388
389 struct DisneyClosure
390 {
391 struct Params
392 {
393 OSL::Vec3 N;
394 OSL::Vec3 T;
395 OSL::Color3 base_color;
396 float subsurface;
397 float metallic;
398 float specular;
399 float specular_tint;
400 float anisotropic;
401 float roughness;
402 float sheen;
403 float sheen_tint;
404 float clearcoat;
405 float clearcoat_gloss;
406 };
407
namerenderer::__anon50bdf1300111::DisneyClosure408 static const char* name()
409 {
410 return "as_disney";
411 }
412
idrenderer::__anon50bdf1300111::DisneyClosure413 static ClosureID id()
414 {
415 return DisneyID;
416 }
417
modesrenderer::__anon50bdf1300111::DisneyClosure418 static int modes()
419 {
420 return ScatteringMode::Diffuse | ScatteringMode::Glossy;
421 }
422
register_closurerenderer::__anon50bdf1300111::DisneyClosure423 static void register_closure(OSLShadingSystem& shading_system)
424 {
425 const OSL::ClosureParam params[] =
426 {
427 CLOSURE_VECTOR_PARAM(Params, N),
428 CLOSURE_VECTOR_PARAM(Params, T),
429 CLOSURE_COLOR_PARAM(Params, base_color),
430 CLOSURE_FLOAT_PARAM(Params, subsurface),
431 CLOSURE_FLOAT_PARAM(Params, metallic),
432 CLOSURE_FLOAT_PARAM(Params, specular),
433 CLOSURE_FLOAT_PARAM(Params, specular_tint),
434 CLOSURE_FLOAT_PARAM(Params, anisotropic),
435 CLOSURE_FLOAT_PARAM(Params, roughness),
436 CLOSURE_FLOAT_PARAM(Params, sheen),
437 CLOSURE_FLOAT_PARAM(Params, sheen_tint),
438 CLOSURE_FLOAT_PARAM(Params, clearcoat),
439 CLOSURE_FLOAT_PARAM(Params, clearcoat_gloss),
440 CLOSURE_FINISH_PARAM(Params)
441 };
442
443 shading_system.register_closure(name(), id(), params, nullptr, nullptr);
444
445 g_closure_convert_funs[id()] = &convert_closure;
446 g_closure_get_modes_funs[id()] = &modes;
447 }
448
convert_closurerenderer::__anon50bdf1300111::DisneyClosure449 static void convert_closure(
450 CompositeSurfaceClosure& composite_closure,
451 const Basis3f& shading_basis,
452 const void* osl_params,
453 const Color3f& weight,
454 Arena& arena)
455 {
456 const Params* p = static_cast<const Params*>(osl_params);
457
458 DisneyBRDFInputValues* values =
459 composite_closure.add_closure<DisneyBRDFInputValues>(
460 id(),
461 shading_basis,
462 weight,
463 p->N,
464 p->T,
465 arena);
466
467 values->m_base_color.set(Color3f(p->base_color), g_std_lighting_conditions, Spectrum::Reflectance);
468 values->m_subsurface = saturate(p->subsurface);
469 values->m_metallic = saturate(p->metallic);
470 values->m_specular = max(p->specular, 0.0f);
471 values->m_specular_tint = saturate(p->specular_tint);
472 values->m_anisotropic = clamp(p->anisotropic, -1.0f, 1.0f);
473 values->m_roughness = clamp(p->roughness, 0.0001f, 1.0f);
474 values->m_sheen = saturate(p->sheen);
475 values->m_sheen_tint = saturate(p->sheen_tint);
476 values->m_clearcoat = max(p->clearcoat, 0.0f);
477 values->m_clearcoat_gloss = clamp(p->clearcoat_gloss, 0.0001f, 1.0f);
478 }
479 };
480
481 struct EmissionClosure
482 {
483 struct Params
484 {
485 };
486
namerenderer::__anon50bdf1300111::EmissionClosure487 static const char* name()
488 {
489 return "emission";
490 }
491
idrenderer::__anon50bdf1300111::EmissionClosure492 static ClosureID id()
493 {
494 return EmissionID;
495 }
496
register_closurerenderer::__anon50bdf1300111::EmissionClosure497 static void register_closure(OSLShadingSystem& shading_system)
498 {
499 const OSL::ClosureParam params[] =
500 {
501 CLOSURE_FINISH_PARAM(Params)
502 };
503
504 shading_system.register_closure(name(), id(), params, nullptr, nullptr);
505 }
506
convert_closurerenderer::__anon50bdf1300111::EmissionClosure507 static void convert_closure(
508 CompositeEmissionClosure& composite_closure,
509 const void* osl_params,
510 const Color3f& weight,
511 const float max_weight_component,
512 Arena& arena)
513 {
514 DiffuseEDFInputValues* values =
515 composite_closure.add_closure<DiffuseEDFInputValues>(
516 id(),
517 weight,
518 max_weight_component,
519 arena);
520
521 values->m_radiance.set(Color3f(weight / max_weight_component), g_std_lighting_conditions, Spectrum::Illuminance);
522 values->m_radiance_multiplier = max_weight_component;
523 values->m_exposure = 0.0f;
524 }
525 };
526
527 struct GlassClosure
528 {
529 struct Params
530 {
531 OSL::Vec3 N;
532 OSL::Vec3 T;
533 OSL::Color3 surface_transmittance;
534 OSL::Color3 reflection_tint;
535 OSL::Color3 refraction_tint;
536 float roughness;
537 float anisotropy;
538 float ior;
539 OSL::Color3 volume_transmittance;
540 float volume_transmittance_distance;
541 float energy_compensation;
542 };
543
namerenderer::__anon50bdf1300111::GlassClosure544 static const char* name()
545 {
546 return "as_glass";
547 }
548
idrenderer::__anon50bdf1300111::GlassClosure549 static ClosureID id()
550 {
551 return GlassID;
552 }
553
modesrenderer::__anon50bdf1300111::GlassClosure554 static int modes()
555 {
556 return ScatteringMode::Glossy | ScatteringMode::Specular;
557 }
558
prepare_closurerenderer::__anon50bdf1300111::GlassClosure559 static void prepare_closure(
560 OSL::RendererServices* render_services,
561 int id,
562 void* data)
563 {
564 // Initialize keyword parameter defaults.
565 Params* params = new (data) Params();
566 params->energy_compensation = 0.0f;
567 }
568
register_closurerenderer::__anon50bdf1300111::GlassClosure569 static void register_closure(OSLShadingSystem& shading_system)
570 {
571 const OSL::ClosureParam params[] =
572 {
573 CLOSURE_VECTOR_PARAM(Params, N),
574 CLOSURE_VECTOR_PARAM(Params, T),
575 CLOSURE_COLOR_PARAM(Params, surface_transmittance),
576 CLOSURE_COLOR_PARAM(Params, reflection_tint),
577 CLOSURE_COLOR_PARAM(Params, refraction_tint),
578 CLOSURE_FLOAT_PARAM(Params, roughness),
579 CLOSURE_FLOAT_PARAM(Params, anisotropy),
580 CLOSURE_FLOAT_PARAM(Params, ior),
581 CLOSURE_COLOR_PARAM(Params, volume_transmittance),
582 CLOSURE_FLOAT_PARAM(Params, volume_transmittance_distance),
583 CLOSURE_FLOAT_KEYPARAM(Params, energy_compensation, "energy_compensation"),
584 CLOSURE_FINISH_PARAM(Params)
585 };
586
587 shading_system.register_closure(name(), id(), params, &prepare_closure, nullptr);
588 g_closure_convert_funs[id()] = &convert_closure;
589 g_closure_get_modes_funs[id()] = &modes;
590 }
591
convert_closurerenderer::__anon50bdf1300111::GlassClosure592 static void convert_closure(
593 CompositeSurfaceClosure& composite_closure,
594 const Basis3f& shading_basis,
595 const void* osl_params,
596 const Color3f& weight,
597 Arena& arena)
598 {
599 const Params* p = static_cast<const Params*>(osl_params);
600
601 GlassBSDFInputValues* values =
602 composite_closure.add_closure<GlassBSDFInputValues>(
603 id(),
604 shading_basis,
605 weight,
606 p->N,
607 p->T,
608 arena);
609
610 values->m_surface_transmittance.set(Color3f(p->surface_transmittance), g_std_lighting_conditions, Spectrum::Reflectance);
611 values->m_surface_transmittance_multiplier = 1.0f;
612 values->m_reflection_tint.set(Color3f(p->reflection_tint), g_std_lighting_conditions, Spectrum::Reflectance);
613 values->m_refraction_tint.set(Color3f(p->refraction_tint), g_std_lighting_conditions, Spectrum::Reflectance);
614 values->m_roughness = max(p->roughness, 0.0001f);
615 values->m_anisotropy = clamp(p->anisotropy, -1.0f, 1.0f);
616 values->m_ior = max(p->ior, 0.001f);
617 values->m_volume_transmittance.set(Color3f(p->volume_transmittance), g_std_lighting_conditions, Spectrum::Reflectance);
618 values->m_volume_transmittance_distance = p->volume_transmittance_distance;
619 values->m_energy_compensation = saturate(p->energy_compensation);
620 composite_closure.add_ior(weight, values->m_ior);
621 }
622 };
623
624 struct GlossyClosure
625 {
626 struct Params
627 {
628 OSL::Vec3 N;
629 OSL::Vec3 T;
630 float roughness;
631 float anisotropy;
632 float ior;
633 float energy_compensation;
634 float fresnel_weight;
635 };
636
namerenderer::__anon50bdf1300111::GlossyClosure637 static const char* name()
638 {
639 return "as_glossy";
640 }
641
idrenderer::__anon50bdf1300111::GlossyClosure642 static ClosureID id()
643 {
644 return GlossyID;
645 }
646
modesrenderer::__anon50bdf1300111::GlossyClosure647 static int modes()
648 {
649 return ScatteringMode::Glossy | ScatteringMode::Specular;
650 }
651
prepare_closurerenderer::__anon50bdf1300111::GlossyClosure652 static void prepare_closure(
653 OSL::RendererServices* render_services,
654 int id,
655 void* data)
656 {
657 // Initialize keyword parameter defaults.
658 Params* params = new (data) Params();
659 params->energy_compensation = 0.0f;
660 params->fresnel_weight = 1.0f;
661 }
662
register_closurerenderer::__anon50bdf1300111::GlossyClosure663 static void register_closure(OSLShadingSystem& shading_system)
664 {
665 const OSL::ClosureParam params[] =
666 {
667 CLOSURE_VECTOR_PARAM(Params, N),
668 CLOSURE_VECTOR_PARAM(Params, T),
669 CLOSURE_FLOAT_PARAM(Params, roughness),
670 CLOSURE_FLOAT_PARAM(Params, anisotropy),
671 CLOSURE_FLOAT_PARAM(Params, ior),
672 CLOSURE_FLOAT_KEYPARAM(Params, energy_compensation, "energy_compensation"),
673 CLOSURE_FLOAT_KEYPARAM(Params, fresnel_weight, "fresnel_weight"),
674 CLOSURE_FINISH_PARAM(Params)
675 };
676
677 shading_system.register_closure(name(), id(), params, &prepare_closure, nullptr);
678 g_closure_convert_funs[id()] = &convert_closure;
679 g_closure_get_modes_funs[id()] = &modes;
680 }
681
convert_closurerenderer::__anon50bdf1300111::GlossyClosure682 static void convert_closure(
683 CompositeSurfaceClosure& composite_closure,
684 const Basis3f& shading_basis,
685 const void* osl_params,
686 const Color3f& weight,
687 Arena& arena)
688 {
689 const Params* p = static_cast<const Params*>(osl_params);
690
691 const float roughness = saturate(p->roughness);
692 const float fresnel_weight = saturate(p->fresnel_weight);
693
694 const float ior = max(p->ior, 0.001f);
695
696 GlossyBRDFInputValues* values =
697 composite_closure.add_closure<GlossyBRDFInputValues>(
698 id(),
699 shading_basis,
700 weight,
701 p->N,
702 p->T,
703 arena);
704
705 composite_closure.override_closure_scalar_weight(
706 luminance(weight) * sample_weight(roughness, ior, fresnel_weight));
707
708 values->m_reflectance.set(1.0f);
709 values->m_reflectance_multiplier = 1.0f;
710 values->m_roughness = roughness;
711 values->m_anisotropy = clamp(p->anisotropy, -1.0f, 1.0f);
712 values->m_ior = ior;
713 values->m_fresnel_weight = fresnel_weight;
714 values->m_energy_compensation = saturate(p->energy_compensation);
715 }
716
sample_weightrenderer::__anon50bdf1300111::GlossyClosure717 static float sample_weight(
718 const float roughness,
719 const float ior,
720 const float fresnel_weight)
721 {
722 const float eavg = get_average_albedo(roughness);
723 const float favg = lerp(
724 1.0f,
725 average_fresnel_reflectance_dielectric(ior),
726 fresnel_weight);
727 return eavg * favg;
728 }
729 };
730
731 struct HoldoutClosure
732 {
733 struct Params
734 {
735 };
736
namerenderer::__anon50bdf1300111::HoldoutClosure737 static const char* name()
738 {
739 return "holdout";
740 }
741
idrenderer::__anon50bdf1300111::HoldoutClosure742 static ClosureID id()
743 {
744 return HoldoutID;
745 }
746
register_closurerenderer::__anon50bdf1300111::HoldoutClosure747 static void register_closure(OSLShadingSystem& shading_system)
748 {
749 const OSL::ClosureParam params[] =
750 {
751 CLOSURE_FINISH_PARAM(Params)
752 };
753
754 shading_system.register_closure(name(), id(), params, nullptr, nullptr);
755 }
756 };
757
758 struct MatteClosure
759 {
760 struct Params
761 {
762 OSL::Color3 matte_color;
763 float matte_alpha;
764 };
765
namerenderer::__anon50bdf1300111::MatteClosure766 static const char* name()
767 {
768 return "as_matte";
769 }
770
idrenderer::__anon50bdf1300111::MatteClosure771 static ClosureID id()
772 {
773 return MatteID;
774 }
775
prepare_closurerenderer::__anon50bdf1300111::MatteClosure776 static void prepare_closure(
777 OSL::RendererServices* render_services,
778 int id,
779 void* data)
780 {
781 // Initialize keyword parameter defaults.
782 Params* params = new (data) Params();
783 params->matte_color = OSL::Color3(0.0f);
784 params->matte_alpha = 0.0f;
785 }
786
register_closurerenderer::__anon50bdf1300111::MatteClosure787 static void register_closure(OSLShadingSystem& shading_system)
788 {
789 const OSL::ClosureParam params[] =
790 {
791 CLOSURE_COLOR_PARAM(Params, matte_color),
792 CLOSURE_FLOAT_PARAM(Params, matte_alpha),
793 CLOSURE_FINISH_PARAM(Params)
794 };
795
796 shading_system.register_closure(name(), id(), params, nullptr, nullptr);
797 }
798 };
799
800 struct MetalClosure
801 {
802 struct Params
803 {
804 OSL::Vec3 N;
805 OSL::Vec3 T;
806 OSL::Color3 normal_reflectance;
807 OSL::Color3 edge_tint;
808 float roughness;
809 float anisotropy;
810 float energy_compensation;
811 };
812
namerenderer::__anon50bdf1300111::MetalClosure813 static const char* name()
814 {
815 return "as_metal";
816 }
817
idrenderer::__anon50bdf1300111::MetalClosure818 static ClosureID id()
819 {
820 return MetalID;
821 }
822
modesrenderer::__anon50bdf1300111::MetalClosure823 static int modes()
824 {
825 return ScatteringMode::Glossy | ScatteringMode::Specular;
826 }
827
prepare_closurerenderer::__anon50bdf1300111::MetalClosure828 static void prepare_closure(
829 OSL::RendererServices* render_services,
830 int id,
831 void* data)
832 {
833 // Initialize keyword parameter defaults.
834 Params* params = new (data) Params();
835 params->energy_compensation = 0.0f;
836 }
837
register_closurerenderer::__anon50bdf1300111::MetalClosure838 static void register_closure(OSLShadingSystem& shading_system)
839 {
840 const OSL::ClosureParam params[] =
841 {
842 CLOSURE_VECTOR_PARAM(Params, N),
843 CLOSURE_VECTOR_PARAM(Params, T),
844 CLOSURE_COLOR_PARAM(Params, normal_reflectance),
845 CLOSURE_COLOR_PARAM(Params, edge_tint),
846 CLOSURE_FLOAT_PARAM(Params, roughness),
847 CLOSURE_FLOAT_PARAM(Params, anisotropy),
848 CLOSURE_FLOAT_KEYPARAM(Params, energy_compensation, "energy_compensation"),
849 CLOSURE_FINISH_PARAM(Params)
850 };
851
852 shading_system.register_closure(name(), id(), params, &prepare_closure, nullptr);
853 g_closure_convert_funs[id()] = &convert_closure;
854 g_closure_get_modes_funs[id()] = &modes;
855 }
856
convert_closurerenderer::__anon50bdf1300111::MetalClosure857 static void convert_closure(
858 CompositeSurfaceClosure& composite_closure,
859 const Basis3f& shading_basis,
860 const void* osl_params,
861 const Color3f& weight,
862 Arena& arena)
863 {
864 const Params* p = static_cast<const Params*>(osl_params);
865
866 MetalBRDFInputValues* values =
867 composite_closure.add_closure<MetalBRDFInputValues>(
868 id(),
869 shading_basis,
870 weight,
871 p->N,
872 p->T,
873 arena);
874
875 values->m_normal_reflectance.set(Color3f(p->normal_reflectance), g_std_lighting_conditions, Spectrum::Reflectance);
876 values->m_edge_tint.set(Color3f(p->edge_tint), g_std_lighting_conditions, Spectrum::Reflectance);
877 values->m_reflectance_multiplier = 1.0f;
878 values->m_roughness = max(p->roughness, 0.0f);
879 values->m_anisotropy = clamp(p->anisotropy, -1.0f, 1.0f);
880 values->m_energy_compensation = saturate(p->energy_compensation);
881 }
882 };
883
884 struct OrenNayarClosure
885 {
886 struct Params
887 {
888 OSL::Color3 reflectance;
889 OSL::Vec3 N;
890 float roughness;
891 };
892
namerenderer::__anon50bdf1300111::OrenNayarClosure893 static const char* name()
894 {
895 return "as_oren_nayar";
896 }
897
idrenderer::__anon50bdf1300111::OrenNayarClosure898 static ClosureID id()
899 {
900 return OrenNayarID;
901 }
902
modesrenderer::__anon50bdf1300111::OrenNayarClosure903 static int modes()
904 {
905 return ScatteringMode::Diffuse;
906 }
907
register_closurerenderer::__anon50bdf1300111::OrenNayarClosure908 static void register_closure(OSLShadingSystem& shading_system)
909 {
910 const OSL::ClosureParam params[] =
911 {
912 CLOSURE_COLOR_PARAM(Params, reflectance),
913 CLOSURE_VECTOR_PARAM(Params, N),
914 CLOSURE_FLOAT_PARAM(Params, roughness),
915 CLOSURE_FINISH_PARAM(Params)
916 };
917
918 shading_system.register_closure(name(), id(), params, nullptr, nullptr);
919
920 g_closure_convert_funs[id()] = &convert_closure;
921 g_closure_get_modes_funs[id()] = &modes;
922 }
923
convert_closurerenderer::__anon50bdf1300111::OrenNayarClosure924 static void convert_closure(
925 CompositeSurfaceClosure& composite_closure,
926 const Basis3f& shading_basis,
927 const void* osl_params,
928 const Color3f& weight,
929 Arena& arena)
930 {
931 const Params* p = static_cast<const Params*>(osl_params);
932
933 OrenNayarBRDFInputValues* values =
934 composite_closure.add_closure<OrenNayarBRDFInputValues>(
935 id(),
936 shading_basis,
937 weight,
938 p->N,
939 arena);
940
941 const Color3f reflectance = Color3f(p->reflectance);
942 values->m_reflectance.set(reflectance, g_std_lighting_conditions, Spectrum::Reflectance);
943 values->m_reflectance_multiplier = 1.0f;
944 values->m_roughness = max(p->roughness, 0.0f);
945
946 const float w = luminance(weight) * luminance(reflectance);
947 composite_closure.override_closure_scalar_weight(w);
948 }
949 };
950
951 struct PhongClosure
952 {
953 struct Params
954 {
955 OSL::Vec3 N;
956 float exponent;
957 };
958
namerenderer::__anon50bdf1300111::PhongClosure959 static const char* name()
960 {
961 return "phong";
962 }
963
idrenderer::__anon50bdf1300111::PhongClosure964 static ClosureID id()
965 {
966 return PhongID;
967 }
968
modesrenderer::__anon50bdf1300111::PhongClosure969 static int modes()
970 {
971 return ScatteringMode::Glossy;
972 }
973
register_closurerenderer::__anon50bdf1300111::PhongClosure974 static void register_closure(OSLShadingSystem& shading_system)
975 {
976 const OSL::ClosureParam params[] =
977 {
978 CLOSURE_VECTOR_PARAM(Params, N),
979 CLOSURE_FLOAT_PARAM(Params, exponent),
980 CLOSURE_FINISH_PARAM(Params)
981 };
982
983 shading_system.register_closure(name(), id(), params, nullptr, nullptr);
984
985 g_closure_convert_funs[id()] = &convert_closure;
986 g_closure_get_modes_funs[id()] = &modes;
987 }
988
convert_closurerenderer::__anon50bdf1300111::PhongClosure989 static void convert_closure(
990 CompositeSurfaceClosure& composite_closure,
991 const Basis3f& shading_basis,
992 const void* osl_params,
993 const Color3f& weight,
994 Arena& arena)
995 {
996 const Params* p = static_cast<const Params*>(osl_params);
997
998 AshikhminBRDFInputValues* values =
999 composite_closure.add_closure<AshikhminBRDFInputValues>(
1000 AshikhminShirleyID,
1001 shading_basis,
1002 weight,
1003 p->N,
1004 arena);
1005
1006 values->m_rd.set(1.0f);
1007 values->m_rd_multiplier = 1.0f;
1008 values->m_rg.set(1.0f);
1009 values->m_rg_multiplier = 1.0f;
1010 values->m_nu = max(p->exponent, 0.01f);
1011 values->m_nv = max(p->exponent, 0.01f);
1012 values->m_fr_multiplier = 1.0f;
1013 }
1014 };
1015
1016 struct PlasticClosure
1017 {
1018 struct Params
1019 {
1020 OSL::Vec3 N;
1021 OSL::Color3 specular_reflectance;
1022 float specular_reflectance_multiplier;
1023 float roughness;
1024 float ior;
1025 OSL::Color3 diffuse_reflectance;
1026 float diffuse_reflectance_multiplier;
1027 float internal_scattering;
1028 };
1029
namerenderer::__anon50bdf1300111::PlasticClosure1030 static const char* name()
1031 {
1032 return "as_plastic";
1033 }
1034
idrenderer::__anon50bdf1300111::PlasticClosure1035 static ClosureID id()
1036 {
1037 return PlasticID;
1038 }
1039
modesrenderer::__anon50bdf1300111::PlasticClosure1040 static int modes()
1041 {
1042 return ScatteringMode::Diffuse | ScatteringMode::Glossy | ScatteringMode::Specular;
1043 }
1044
register_closurerenderer::__anon50bdf1300111::PlasticClosure1045 static void register_closure(OSLShadingSystem& shading_system)
1046 {
1047 const OSL::ClosureParam params[] =
1048 {
1049 CLOSURE_VECTOR_PARAM(Params, N),
1050 CLOSURE_COLOR_PARAM(Params, specular_reflectance),
1051 CLOSURE_FLOAT_PARAM(Params, specular_reflectance_multiplier),
1052 CLOSURE_FLOAT_PARAM(Params, roughness),
1053 CLOSURE_FLOAT_PARAM(Params, ior),
1054 CLOSURE_COLOR_PARAM(Params, diffuse_reflectance),
1055 CLOSURE_FLOAT_PARAM(Params, diffuse_reflectance_multiplier),
1056 CLOSURE_FLOAT_PARAM(Params, internal_scattering),
1057 CLOSURE_FINISH_PARAM(Params)
1058 };
1059
1060 shading_system.register_closure(name(), id(), params, nullptr, nullptr);
1061 g_closure_convert_funs[id()] = &convert_closure;
1062 g_closure_get_modes_funs[id()] = &modes;
1063 }
1064
convert_closurerenderer::__anon50bdf1300111::PlasticClosure1065 static void convert_closure(
1066 CompositeSurfaceClosure& composite_closure,
1067 const Basis3f& shading_basis,
1068 const void* osl_params,
1069 const Color3f& weight,
1070 Arena& arena)
1071 {
1072 const Params* p = static_cast<const Params*>(osl_params);
1073
1074 PlasticBRDFInputValues* values =
1075 composite_closure.add_closure<PlasticBRDFInputValues>(
1076 id(),
1077 shading_basis,
1078 weight,
1079 p->N,
1080 arena);
1081
1082 values->m_specular_reflectance.set(Color3f(p->specular_reflectance), g_std_lighting_conditions,
1083 Spectrum::Reflectance);
1084 values->m_specular_reflectance_multiplier = max(p->specular_reflectance_multiplier, 0.0f);
1085 values->m_roughness = clamp(p->roughness, 0.0001f, 1.0f);
1086 values->m_ior = max(p->ior, 0.001f);
1087 values->m_diffuse_reflectance.set(Color3f(p->diffuse_reflectance), g_std_lighting_conditions,
1088 Spectrum::Reflectance);
1089 values->m_diffuse_reflectance_multiplier = max(p->diffuse_reflectance_multiplier, 0.0f);
1090 values->m_internal_scattering = max(p->internal_scattering, 0.0f);
1091 }
1092 };
1093
1094 struct ReflectionClosure
1095 {
1096 struct Params
1097 {
1098 OSL::Vec3 N;
1099 float ior;
1100 };
1101
namerenderer::__anon50bdf1300111::ReflectionClosure1102 static const char* name()
1103 {
1104 return "reflection";
1105 }
1106
idrenderer::__anon50bdf1300111::ReflectionClosure1107 static ClosureID id()
1108 {
1109 return ReflectionID;
1110 }
1111
modesrenderer::__anon50bdf1300111::ReflectionClosure1112 static int modes()
1113 {
1114 return ScatteringMode::Specular;
1115 }
1116
register_closurerenderer::__anon50bdf1300111::ReflectionClosure1117 static void register_closure(OSLShadingSystem& shading_system)
1118 {
1119 const OSL::ClosureParam params[] =
1120 {
1121 CLOSURE_VECTOR_PARAM(Params, N),
1122 CLOSURE_FLOAT_PARAM(Params, ior),
1123 CLOSURE_FINISH_PARAM(Params)
1124 };
1125
1126 shading_system.register_closure(name(), id(), params, nullptr, nullptr);
1127
1128 g_closure_convert_funs[id()] = &convert_closure;
1129 g_closure_get_modes_funs[id()] = &modes;
1130 }
1131
convert_closurerenderer::__anon50bdf1300111::ReflectionClosure1132 static void convert_closure(
1133 CompositeSurfaceClosure& composite_closure,
1134 const Basis3f& shading_basis,
1135 const void* osl_params,
1136 const Color3f& weight,
1137 Arena& arena)
1138 {
1139 const Params* p = static_cast<const Params*>(osl_params);
1140
1141 GlossyBRDFInputValues* values =
1142 composite_closure.add_closure<GlossyBRDFInputValues>(
1143 GlossyID,
1144 shading_basis,
1145 weight,
1146 p->N,
1147 arena);
1148
1149 values->m_reflectance.set(1.0f);
1150 values->m_reflectance_multiplier = 1.0f;
1151 values->m_roughness = 0.0f;
1152 values->m_anisotropy = 0.0f;
1153 values->m_ior = max(p->ior, 0.001f);
1154 values->m_energy_compensation = 0.0f;
1155 }
1156 };
1157
1158 struct SheenClosure
1159 {
1160 struct Params
1161 {
1162 OSL::Vec3 N;
1163 };
1164
namerenderer::__anon50bdf1300111::SheenClosure1165 static const char* name()
1166 {
1167 return "as_sheen";
1168 }
1169
idrenderer::__anon50bdf1300111::SheenClosure1170 static ClosureID id()
1171 {
1172 return SheenID;
1173 }
1174
modesrenderer::__anon50bdf1300111::SheenClosure1175 static int modes()
1176 {
1177 return ScatteringMode::Diffuse;
1178 }
1179
register_closurerenderer::__anon50bdf1300111::SheenClosure1180 static void register_closure(OSLShadingSystem& shading_system)
1181 {
1182 const OSL::ClosureParam params[] =
1183 {
1184 CLOSURE_VECTOR_PARAM(Params, N),
1185 CLOSURE_FINISH_PARAM(Params)
1186 };
1187
1188 shading_system.register_closure(name(), id(), params, nullptr, nullptr);
1189
1190 g_closure_convert_funs[id()] = &convert_closure;
1191 g_closure_get_modes_funs[id()] = &modes;
1192 }
1193
convert_closurerenderer::__anon50bdf1300111::SheenClosure1194 static void convert_closure(
1195 CompositeSurfaceClosure& composite_closure,
1196 const Basis3f& shading_basis,
1197 const void* osl_params,
1198 const Color3f& weight,
1199 Arena& arena)
1200 {
1201 const Params* p = static_cast<const Params*>(osl_params);
1202
1203 SheenBRDFInputValues* values =
1204 composite_closure.add_closure<SheenBRDFInputValues>(
1205 id(),
1206 shading_basis,
1207 weight,
1208 p->N,
1209 arena);
1210
1211 values->m_reflectance.set(1.0f);
1212 values->m_reflectance_multiplier = 1.0f;
1213 }
1214 };
1215
1216 struct SubsurfaceClosure
1217 {
1218 struct Params
1219 {
1220 OSL::ustring profile;
1221 OSL::Vec3 N;
1222 OSL::Color3 reflectance;
1223 OSL::Color3 mean_free_path;
1224 float ior;
1225 float fresnel_weight;
1226 float volume_anisotropy;
1227 };
1228
namerenderer::__anon50bdf1300111::SubsurfaceClosure1229 static const char* name()
1230 {
1231 return "as_subsurface";
1232 }
1233
idrenderer::__anon50bdf1300111::SubsurfaceClosure1234 static ClosureID id()
1235 {
1236 return SubsurfaceID;
1237 }
1238
prepare_closurerenderer::__anon50bdf1300111::SubsurfaceClosure1239 static void prepare_closure(
1240 OSL::RendererServices* render_services,
1241 int id,
1242 void* data)
1243 {
1244 // Initialize keyword parameter defaults.
1245 Params* params = new (data) Params();
1246 params->fresnel_weight = 1.0f;
1247 params->volume_anisotropy = 0.0f;
1248 }
1249
register_closurerenderer::__anon50bdf1300111::SubsurfaceClosure1250 static void register_closure(OSLShadingSystem& shading_system)
1251 {
1252 const OSL::ClosureParam params[] =
1253 {
1254 CLOSURE_STRING_PARAM(Params, profile),
1255 CLOSURE_VECTOR_PARAM(Params, N),
1256 CLOSURE_COLOR_PARAM(Params, reflectance),
1257 CLOSURE_COLOR_PARAM(Params, mean_free_path),
1258 CLOSURE_FLOAT_PARAM(Params, ior),
1259 CLOSURE_FLOAT_KEYPARAM(Params, fresnel_weight, "fresnel_weight"),
1260 CLOSURE_FLOAT_KEYPARAM(Params, volume_anisotropy, "volume_anisotropy"),
1261 CLOSURE_FINISH_PARAM(Params)
1262 };
1263
1264 shading_system.register_closure(name(), id(), params, &prepare_closure, nullptr);
1265 }
1266
convert_closurerenderer::__anon50bdf1300111::SubsurfaceClosure1267 static void convert_closure(
1268 CompositeSubsurfaceClosure& composite_closure,
1269 const Basis3f& shading_basis,
1270 const void* osl_params,
1271 const Color3f& weight,
1272 Arena& arena)
1273 {
1274 const Params* p = static_cast<const Params*>(osl_params);
1275
1276 if (p->profile == g_standard_dipole_profile_str)
1277 {
1278 DipoleBSSRDFInputValues* values =
1279 composite_closure.add_closure<DipoleBSSRDFInputValues>(
1280 SubsurfaceStandardDipoleID,
1281 shading_basis,
1282 weight,
1283 p->N,
1284 arena);
1285
1286 copy_parameters(p, values);
1287 }
1288 else if (p->profile == g_better_dipole_profile_str)
1289 {
1290 DipoleBSSRDFInputValues* values =
1291 composite_closure.add_closure<DipoleBSSRDFInputValues>(
1292 SubsurfaceBetterDipoleID,
1293 shading_basis,
1294 weight,
1295 p->N,
1296 arena);
1297
1298 copy_parameters(p, values);
1299 }
1300 else if (p->profile == g_directional_dipole_profile_str)
1301 {
1302 DipoleBSSRDFInputValues* values =
1303 composite_closure.add_closure<DipoleBSSRDFInputValues>(
1304 SubsurfaceDirectionalDipoleID,
1305 shading_basis,
1306 weight,
1307 p->N,
1308 arena);
1309
1310 copy_parameters(p, values);
1311 }
1312 else if (p->profile == g_normalized_diffusion_profile_str)
1313 {
1314 NormalizedDiffusionBSSRDFInputValues* values =
1315 composite_closure.add_closure<NormalizedDiffusionBSSRDFInputValues>(
1316 SubsurfaceNormalizedDiffusionID,
1317 shading_basis,
1318 weight,
1319 p->N,
1320 arena);
1321
1322 copy_parameters(p, values);
1323 }
1324 else if (p->profile == g_gaussian_profile_str)
1325 {
1326 GaussianBSSRDFInputValues* values =
1327 composite_closure.add_closure<GaussianBSSRDFInputValues>(
1328 SubsurfaceGaussianID,
1329 shading_basis,
1330 weight,
1331 p->N,
1332 arena);
1333
1334 copy_parameters(p, values);
1335 }
1336 else if (p->profile == g_randomwalk_profile_str)
1337 {
1338 RandomwalkBSSRDFInputValues* values =
1339 composite_closure.add_closure<RandomwalkBSSRDFInputValues>(
1340 SubsurfaceRandomwalkID,
1341 shading_basis,
1342 weight,
1343 p->N,
1344 arena);
1345
1346 copy_parameters(p, values);
1347 values->m_volume_anisotropy = clamp(p->volume_anisotropy, -0.999f, 0.999f);
1348 }
1349 else
1350 {
1351 string msg = "unknown subsurface profile: ";
1352 msg += p->profile.c_str();
1353 throw ExceptionOSLRuntimeError(msg.c_str());
1354 }
1355 }
1356
1357 template <typename InputValues>
copy_parametersrenderer::__anon50bdf1300111::SubsurfaceClosure1358 static void copy_parameters(
1359 const Params* p,
1360 InputValues* values)
1361 {
1362 values->m_weight = 1.0f;
1363 values->m_reflectance.set(Color3f(p->reflectance), g_std_lighting_conditions, Spectrum::Reflectance);
1364 values->m_reflectance_multiplier = 1.0f;
1365 values->m_mfp.set(Color3f(p->mean_free_path), g_std_lighting_conditions, Spectrum::Reflectance);
1366 values->m_mfp_multiplier = 1.0f;
1367 values->m_ior = p->ior;
1368 values->m_fresnel_weight = saturate(p->fresnel_weight);
1369 }
1370 };
1371
1372 struct RandomwalkGlassClosure
1373 {
1374 struct Params
1375 {
1376 OSL::Vec3 N;
1377 OSL::Color3 reflectance;
1378 OSL::Color3 mean_free_path;
1379 float ior;
1380 float surface_roughness;
1381 float volume_anisotropy;
1382 };
1383
namerenderer::__anon50bdf1300111::RandomwalkGlassClosure1384 static const char* name()
1385 {
1386 return "as_randomwalk_glass";
1387 }
1388
idrenderer::__anon50bdf1300111::RandomwalkGlassClosure1389 static ClosureID id()
1390 {
1391 return RandomwalkGlassID;
1392 }
1393
prepare_closurerenderer::__anon50bdf1300111::RandomwalkGlassClosure1394 static void prepare_closure(
1395 OSL::RendererServices* render_services,
1396 int id,
1397 void* data)
1398 {
1399 // Initialize keyword parameter defaults.
1400 Params* params = new (data) Params();
1401 params->volume_anisotropy = 0.0f;
1402 }
1403
register_closurerenderer::__anon50bdf1300111::RandomwalkGlassClosure1404 static void register_closure(OSLShadingSystem& shading_system)
1405 {
1406 const OSL::ClosureParam params[] =
1407 {
1408 CLOSURE_VECTOR_PARAM(Params, N),
1409 CLOSURE_COLOR_PARAM(Params, reflectance),
1410 CLOSURE_COLOR_PARAM(Params, mean_free_path),
1411 CLOSURE_FLOAT_PARAM(Params, ior),
1412 CLOSURE_FLOAT_PARAM(Params, surface_roughness),
1413 CLOSURE_FLOAT_KEYPARAM(Params, volume_anisotropy, "volume_anisotropy"),
1414 CLOSURE_FINISH_PARAM(Params)
1415 };
1416
1417 shading_system.register_closure(name(), id(), params, &prepare_closure, nullptr);
1418 }
1419
convert_closurerenderer::__anon50bdf1300111::RandomwalkGlassClosure1420 static void convert_closure(
1421 CompositeSubsurfaceClosure& composite_closure,
1422 const Basis3f& shading_basis,
1423 const void* osl_params,
1424 const Color3f& weight,
1425 Arena& arena)
1426 {
1427 const Params* p = static_cast<const Params*>(osl_params);
1428
1429 RandomwalkBSSRDFInputValues* values =
1430 composite_closure.add_closure<RandomwalkBSSRDFInputValues>(
1431 RandomwalkGlassID,
1432 shading_basis,
1433 weight,
1434 p->N,
1435 arena);
1436
1437 copy_parameters(p, values);
1438 }
1439
copy_parametersrenderer::__anon50bdf1300111::RandomwalkGlassClosure1440 static void copy_parameters(
1441 const Params* p,
1442 RandomwalkBSSRDFInputValues* values)
1443 {
1444 values->m_weight = 1.0f;
1445 values->m_reflectance.set(Color3f(p->reflectance), g_std_lighting_conditions, Spectrum::Reflectance);
1446 values->m_reflectance_multiplier = 1.0f;
1447 values->m_mfp.set(Color3f(p->mean_free_path), g_std_lighting_conditions, Spectrum::Reflectance);
1448 values->m_mfp_multiplier = 1.0f;
1449 values->m_ior = p->ior;
1450 values->m_surface_roughness = clamp(p->surface_roughness, 0.0001f, 1.0f);
1451 values->m_fresnel_weight = 1.0f;
1452 values->m_volume_anisotropy = clamp(p->volume_anisotropy, -0.999f, 0.999f);
1453 }
1454 };
1455
1456 struct TranslucentClosure
1457 {
1458 struct Params
1459 {
1460 OSL::Vec3 N;
1461 };
1462
namerenderer::__anon50bdf1300111::TranslucentClosure1463 static const char* name()
1464 {
1465 return "translucent";
1466 }
1467
idrenderer::__anon50bdf1300111::TranslucentClosure1468 static ClosureID id()
1469 {
1470 return TranslucentID;
1471 }
1472
modesrenderer::__anon50bdf1300111::TranslucentClosure1473 static int modes()
1474 {
1475 return ScatteringMode::Diffuse;
1476 }
1477
register_closurerenderer::__anon50bdf1300111::TranslucentClosure1478 static void register_closure(OSLShadingSystem& shading_system)
1479 {
1480 const OSL::ClosureParam params[] =
1481 {
1482 CLOSURE_VECTOR_PARAM(Params, N),
1483 CLOSURE_FINISH_PARAM(Params)
1484 };
1485
1486 shading_system.register_closure(name(), id(), params, nullptr, nullptr);
1487
1488 g_closure_convert_funs[id()] = &convert_closure;
1489 g_closure_get_modes_funs[id()] = &modes;
1490 }
1491
convert_closurerenderer::__anon50bdf1300111::TranslucentClosure1492 static void convert_closure(
1493 CompositeSurfaceClosure& composite_closure,
1494 const Basis3f& shading_basis,
1495 const void* osl_params,
1496 const Color3f& weight,
1497 Arena& arena)
1498 {
1499 const Params* p = static_cast<const Params*>(osl_params);
1500
1501 DiffuseBTDFInputValues* values =
1502 composite_closure.add_closure<DiffuseBTDFInputValues>(
1503 id(),
1504 shading_basis,
1505 weight,
1506 p->N,
1507 arena);
1508
1509 values->m_transmittance.set(1.0f);
1510 values->m_transmittance_multiplier = 1.0f;
1511 }
1512 };
1513
1514 struct TransparentClosure
1515 {
1516 struct Params
1517 {
1518 };
1519
namerenderer::__anon50bdf1300111::TransparentClosure1520 static const char* name()
1521 {
1522 return "transparent";
1523 }
1524
idrenderer::__anon50bdf1300111::TransparentClosure1525 static ClosureID id()
1526 {
1527 return TransparentID;
1528 }
1529
register_closurerenderer::__anon50bdf1300111::TransparentClosure1530 static void register_closure(OSLShadingSystem& shading_system)
1531 {
1532 const OSL::ClosureParam params[] =
1533 {
1534 CLOSURE_FINISH_PARAM(Params)
1535 };
1536
1537 shading_system.register_closure(name(), id(), params, nullptr, nullptr);
1538 }
1539 };
1540
1541 //
1542 // NPR closures.
1543 //
1544
1545 struct NPRShadingClosure
1546 {
1547 struct Params
1548 {
1549 };
1550
namerenderer::__anon50bdf1300111::NPRShadingClosure1551 static const char* name()
1552 {
1553 return "as_npr_shading";
1554 }
1555
idrenderer::__anon50bdf1300111::NPRShadingClosure1556 static ClosureID id()
1557 {
1558 return NPRShadingID;
1559 }
1560
register_closurerenderer::__anon50bdf1300111::NPRShadingClosure1561 static void register_closure(OSLShadingSystem& shading_system)
1562 {
1563 const OSL::ClosureParam params[] =
1564 {
1565 CLOSURE_FINISH_PARAM(Params)
1566 };
1567
1568 shading_system.register_closure(name(), id(), params, nullptr, nullptr);
1569 }
1570
convert_closurerenderer::__anon50bdf1300111::NPRShadingClosure1571 static void convert_closure(
1572 CompositeNPRClosure& composite_closure,
1573 const void* osl_params,
1574 const Color3f& weight,
1575 Arena& arena)
1576 {
1577 composite_closure.add_closure<NPRShadingInputValues>(id(), weight, arena);
1578 }
1579 };
1580
1581 struct NPRContourClosure
1582 {
1583 struct Params
1584 {
1585 OSL::Color3 contour_color;
1586 float contour_opacity;
1587 float contour_width;
1588 int object_id;
1589 int material_id;
1590 int occlusion;
1591 float occlusion_threshold;
1592 int creases;
1593 float creases_threshold;
1594 int quality;
1595 };
1596
namerenderer::__anon50bdf1300111::NPRContourClosure1597 static const char* name()
1598 {
1599 return "as_npr_contour";
1600 }
1601
idrenderer::__anon50bdf1300111::NPRContourClosure1602 static ClosureID id()
1603 {
1604 return NPRContourID;
1605 }
1606
prepare_closurerenderer::__anon50bdf1300111::NPRContourClosure1607 static void prepare_closure(
1608 OSL::RendererServices* render_services,
1609 int id,
1610 void* data)
1611 {
1612 // Initialize keyword parameter defaults.
1613 Params* params = new (data) Params();
1614 params->quality = 1;
1615 }
1616
register_closurerenderer::__anon50bdf1300111::NPRContourClosure1617 static void register_closure(OSLShadingSystem& shading_system)
1618 {
1619 const OSL::ClosureParam params[] =
1620 {
1621 CLOSURE_COLOR_PARAM(Params, contour_color),
1622 CLOSURE_FLOAT_PARAM(Params, contour_opacity),
1623 CLOSURE_FLOAT_PARAM(Params, contour_width),
1624 CLOSURE_INT_PARAM(Params, object_id),
1625 CLOSURE_INT_PARAM(Params, material_id),
1626
1627 CLOSURE_INT_PARAM(Params, occlusion),
1628 CLOSURE_FLOAT_PARAM(Params, occlusion_threshold),
1629 CLOSURE_INT_PARAM(Params, creases),
1630 CLOSURE_FLOAT_PARAM(Params, creases_threshold),
1631
1632 CLOSURE_INT_KEYPARAM(Params, quality, "quality"),
1633 CLOSURE_FINISH_PARAM(Params)
1634 };
1635
1636 shading_system.register_closure(name(), id(), params, &prepare_closure, nullptr);
1637 }
1638
convert_closurerenderer::__anon50bdf1300111::NPRContourClosure1639 static void convert_closure(
1640 CompositeNPRClosure& composite_closure,
1641 const void* osl_params,
1642 const Color3f& weight,
1643 Arena& arena)
1644 {
1645 const Params* p = static_cast<const Params*>(osl_params);
1646
1647 unsigned int features = 0;
1648 if (p->object_id != 0) features |= static_cast<unsigned int>(NPRContourFeatures::ObjectInstanceID);
1649 if (p->material_id != 0) features |= static_cast<unsigned int>(NPRContourFeatures::MaterialID);
1650 if (p->occlusion != 0) features |= static_cast<unsigned int>(NPRContourFeatures::OcclusionEdges);
1651 if (p->creases != 0) features |= static_cast<unsigned int>(NPRContourFeatures::CreaseEdges);
1652
1653 if (features == 0 || p->contour_opacity == 0.0f || p->contour_width == 0.0f)
1654 return;
1655
1656 NPRContourInputValues* values =
1657 composite_closure.add_closure<NPRContourInputValues>(id(), weight, arena);
1658
1659 values->m_color = Color3f(p->contour_color);
1660 values->m_opacity = saturate(p->contour_opacity);
1661 values->m_width = max(p->contour_width, 0.0f);
1662
1663 values->m_occlusion_threshold = max(p->occlusion_threshold, 0.0f);
1664 values->m_cos_crease_threshold = cos(deg_to_rad(p->creases_threshold));
1665
1666 values->m_features = features;
1667 values->m_quality = static_cast<size_t>(clamp(p->quality, 1, 4));
1668 }
1669 };
1670 }
1671
1672
1673 //
1674 // CompositeClosure class implementation.
1675 //
1676
CompositeClosure()1677 CompositeClosure::CompositeClosure()
1678 : m_closure_count(0)
1679 {
1680 }
1681
compute_closure_shading_basis(const Vector3f & normal,const Basis3f & original_shading_basis)1682 void CompositeClosure::compute_closure_shading_basis(
1683 const Vector3f& normal,
1684 const Basis3f& original_shading_basis)
1685 {
1686 const float normal_square_norm = square_norm(normal);
1687 if APPLESEED_LIKELY(normal_square_norm != 0.0f)
1688 {
1689 const float rcp_normal_norm = 1.0f / sqrt(normal_square_norm);
1690 m_bases[m_closure_count] =
1691 Basis3f(
1692 normal * rcp_normal_norm,
1693 original_shading_basis.get_tangent_u());
1694 }
1695 else
1696 {
1697 // Fallback to the original shading basis if the normal is zero.
1698 m_bases[m_closure_count] = original_shading_basis;
1699 }
1700 }
1701
compute_closure_shading_basis(const Vector3f & normal,const Vector3f & tangent,const Basis3f & original_shading_basis)1702 void CompositeClosure::compute_closure_shading_basis(
1703 const Vector3f& normal,
1704 const Vector3f& tangent,
1705 const Basis3f& original_shading_basis)
1706 {
1707 const float tangent_square_norm = square_norm(tangent);
1708 if APPLESEED_LIKELY(tangent_square_norm != 0.0f)
1709 {
1710 const float normal_square_norm = square_norm(normal);
1711 if APPLESEED_LIKELY(normal_square_norm != 0.0f)
1712 {
1713 const float rcp_normal_norm = 1.0f / sqrt(normal_square_norm);
1714 const float rcp_tangent_norm = 1.0f / sqrt(tangent_square_norm);
1715 m_bases[m_closure_count] =
1716 Basis3f(
1717 normal * rcp_normal_norm,
1718 tangent * rcp_tangent_norm);
1719 }
1720 else
1721 {
1722 // Fallback to the original shading basis if the normal is zero.
1723 m_bases[m_closure_count] = original_shading_basis;
1724 }
1725 }
1726 else
1727 {
1728 // If the tangent is zero, ignore it.
1729 // This can happen when using the isotropic microfacet closure overloads, for example.
1730 compute_closure_shading_basis(normal, original_shading_basis);
1731 }
1732 }
1733
1734 template <typename InputValues>
add_closure(const ClosureID closure_type,const Basis3f & original_shading_basis,const Color3f & weight,const Vector3f & normal,Arena & arena)1735 InputValues* CompositeClosure::add_closure(
1736 const ClosureID closure_type,
1737 const Basis3f& original_shading_basis,
1738 const Color3f& weight,
1739 const Vector3f& normal,
1740 Arena& arena)
1741 {
1742 return do_add_closure<InputValues>(
1743 closure_type,
1744 original_shading_basis,
1745 weight,
1746 normal,
1747 false,
1748 Vector3f(0.0f),
1749 arena);
1750 }
1751
1752 template <typename InputValues>
add_closure(const ClosureID closure_type,const Basis3f & original_shading_basis,const Color3f & weight,const Vector3f & normal,const Vector3f & tangent,Arena & arena)1753 InputValues* CompositeClosure::add_closure(
1754 const ClosureID closure_type,
1755 const Basis3f& original_shading_basis,
1756 const Color3f& weight,
1757 const Vector3f& normal,
1758 const Vector3f& tangent,
1759 Arena& arena)
1760 {
1761 return do_add_closure<InputValues>(
1762 closure_type,
1763 original_shading_basis,
1764 weight,
1765 normal,
1766 true,
1767 tangent,
1768 arena);
1769 }
1770
1771 template <typename InputValues>
do_add_closure(const ClosureID closure_type,const Basis3f & original_shading_basis,const Color3f & weight,const Vector3f & normal,const bool has_tangent,const Vector3f & tangent,Arena & arena)1772 InputValues* CompositeClosure::do_add_closure(
1773 const ClosureID closure_type,
1774 const Basis3f& original_shading_basis,
1775 const Color3f& weight,
1776 const Vector3f& normal,
1777 const bool has_tangent,
1778 const Vector3f& tangent,
1779 Arena& arena)
1780 {
1781 // Make sure we have enough space.
1782 if APPLESEED_UNLIKELY(get_closure_count() >= MaxClosureEntries)
1783 {
1784 throw ExceptionOSLRuntimeError(
1785 "maximum number of closures in osl shader group exceeded");
1786 }
1787
1788 // We use the luminance of the weight as the BSDF weight.
1789 const float w = luminance(weight);
1790 assert(w > 0.0f);
1791
1792 m_weights[m_closure_count].set(weight, g_std_lighting_conditions, Spectrum::Reflectance);
1793 m_scalar_weights[m_closure_count] = w;
1794
1795 if (!has_tangent)
1796 compute_closure_shading_basis(normal, original_shading_basis);
1797 else compute_closure_shading_basis(normal, tangent, original_shading_basis);
1798
1799 m_closure_types[m_closure_count] = closure_type;
1800
1801 InputValues* values = arena.allocate<InputValues>();
1802 m_input_values[m_closure_count] = values;
1803
1804 ++m_closure_count;
1805
1806 return values;
1807 }
1808
compute_pdfs(float pdfs[MaxClosureEntries])1809 void CompositeClosure::compute_pdfs(float pdfs[MaxClosureEntries])
1810 {
1811 const size_t closure_count = get_closure_count();
1812
1813 float total_weight = 0.0f;
1814 for (size_t i = 0; i < closure_count; ++i)
1815 {
1816 pdfs[i] = m_scalar_weights[i];
1817 total_weight += pdfs[i];
1818 }
1819
1820 if (total_weight != 0.0f)
1821 {
1822 const float rcp_total_weight = 1.0f / total_weight;
1823
1824 for (size_t i = 0; i < closure_count; ++i)
1825 pdfs[i] *= rcp_total_weight;
1826 }
1827 }
1828
1829
1830 //
1831 // CompositeSurfaceClosure class implementation.
1832 //
1833
CompositeSurfaceClosure(const Basis3f & original_shading_basis,const OSL::ClosureColor * ci,Arena & arena)1834 CompositeSurfaceClosure::CompositeSurfaceClosure(
1835 const Basis3f& original_shading_basis,
1836 const OSL::ClosureColor* ci,
1837 Arena& arena)
1838 : m_ior_count(0)
1839 {
1840 process_closure_tree(ci, original_shading_basis, Color3f(1.0f), arena);
1841
1842 if (m_ior_count == 0)
1843 {
1844 m_ior_count = 1;
1845 m_iors[0] = 1.0f;
1846 return;
1847 }
1848
1849 // Build the IOR CDF in place if needed.
1850 if (m_ior_count > 1)
1851 {
1852 float total_weight = m_ior_cdf[0];
1853 for (size_t i = 1; i < m_ior_count; ++i)
1854 {
1855 total_weight += m_ior_cdf[i];
1856 m_ior_cdf[i] = total_weight;
1857 }
1858
1859 const float rcp_total_weight = 1.0f / total_weight;
1860
1861 for (size_t i = 0; i < m_ior_count - 1; ++i)
1862 m_ior_cdf[i] *= rcp_total_weight;
1863
1864 m_ior_cdf[m_ior_count - 1] = 1.0f;
1865 }
1866 }
1867
compute_pdfs(const int modes,float pdfs[MaxClosureEntries]) const1868 int CompositeSurfaceClosure::compute_pdfs(
1869 const int modes,
1870 float pdfs[MaxClosureEntries]) const
1871 {
1872 memset(pdfs, 0, sizeof(float) * MaxClosureEntries);
1873
1874 int num_closures = 0;
1875 float sum_weights = 0.0f;
1876
1877 for (size_t i = 0, e = get_closure_count(); i < e; ++i)
1878 {
1879 const ClosureID cid = m_closure_types[i];
1880 const int closure_modes = g_closure_get_modes_funs[cid]();
1881
1882 if (closure_modes & modes)
1883 {
1884 pdfs[i] = m_scalar_weights[i];
1885 sum_weights += m_scalar_weights[i];
1886 ++num_closures;
1887 }
1888 else
1889 pdfs[i] = 0.0f;
1890 }
1891
1892 if (sum_weights != 0.0f)
1893 {
1894 const float rcp_sum_weights = 1.0f / sum_weights;
1895 for (size_t i = 0, e = get_closure_count(); i < e; ++i)
1896 pdfs[i] *= rcp_sum_weights;
1897 }
1898
1899 return num_closures;
1900 }
1901
choose_closure(const float w,const size_t num_closures,float pdfs[MaxClosureEntries]) const1902 size_t CompositeSurfaceClosure::choose_closure(
1903 const float w,
1904 const size_t num_closures,
1905 float pdfs[MaxClosureEntries]) const
1906 {
1907 assert(num_closures > 0);
1908 assert(num_closures < MaxClosureEntries);
1909
1910 return sample_pdf_linear_search(pdfs, num_closures, w);
1911 }
1912
add_ior(const Color3f & weight,const float ior)1913 void CompositeSurfaceClosure::add_ior(
1914 const Color3f& weight,
1915 const float ior)
1916 {
1917 // We use the luminance of the weight as the IOR weight.
1918 const float w = luminance(weight);
1919 assert(w > 0.0f);
1920
1921 m_iors[m_ior_count] = ior;
1922 m_ior_cdf[m_ior_count] = w;
1923 ++m_ior_count;
1924 }
1925
choose_ior(const float w) const1926 float CompositeSurfaceClosure::choose_ior(const float w) const
1927 {
1928 assert(m_ior_count > 0);
1929
1930 if APPLESEED_LIKELY(m_ior_count == 1)
1931 return m_iors[0];
1932
1933 const size_t index = sample_cdf_linear_search(m_ior_cdf, w);
1934 return m_iors[index];
1935 }
1936
process_closure_tree(const OSL::ClosureColor * closure,const Basis3f & original_shading_basis,const Color3f & weight,Arena & arena)1937 void CompositeSurfaceClosure::process_closure_tree(
1938 const OSL::ClosureColor* closure,
1939 const Basis3f& original_shading_basis,
1940 const Color3f& weight,
1941 Arena& arena)
1942 {
1943 if (closure == nullptr)
1944 return;
1945
1946 switch (closure->id)
1947 {
1948 case OSL::ClosureColor::MUL:
1949 {
1950 const OSL::ClosureMul* c = reinterpret_cast<const OSL::ClosureMul*>(closure);
1951 const Color3f w = weight * Color3f(c->weight);
1952 process_closure_tree(c->closure, original_shading_basis, w, arena);
1953 }
1954 break;
1955
1956 case OSL::ClosureColor::ADD:
1957 {
1958 const OSL::ClosureAdd* c = reinterpret_cast<const OSL::ClosureAdd*>(closure);
1959 process_closure_tree(c->closureA, original_shading_basis, weight, arena);
1960 process_closure_tree(c->closureB, original_shading_basis, weight, arena);
1961 }
1962 break;
1963
1964 default:
1965 {
1966 const OSL::ClosureComponent* c = reinterpret_cast<const OSL::ClosureComponent*>(closure);
1967 const Color3f w = weight * Color3f(c->w);
1968
1969 if (luminance(w) > 0.0f)
1970 g_closure_convert_funs[c->id](*this, original_shading_basis, c->data(), w, arena);
1971 }
1972 break;
1973 }
1974 }
1975
1976
1977 //
1978 // CompositeSubsurfaceClosure class implementation.
1979 //
1980
CompositeSubsurfaceClosure(const Basis3f & original_shading_basis,const OSL::ClosureColor * ci,Arena & arena)1981 CompositeSubsurfaceClosure::CompositeSubsurfaceClosure(
1982 const Basis3f& original_shading_basis,
1983 const OSL::ClosureColor* ci,
1984 Arena& arena)
1985 {
1986 process_closure_tree(ci, original_shading_basis, Color3f(1.0f), arena);
1987 compute_pdfs(m_pdfs);
1988 }
1989
choose_closure(const float w) const1990 size_t CompositeSubsurfaceClosure::choose_closure(const float w) const
1991 {
1992 assert(get_closure_count() > 0);
1993 return sample_pdf_linear_search(m_pdfs, get_closure_count(), w);
1994 }
1995
process_closure_tree(const OSL::ClosureColor * closure,const Basis3f & original_shading_basis,const Color3f & weight,Arena & arena)1996 void CompositeSubsurfaceClosure::process_closure_tree(
1997 const OSL::ClosureColor* closure,
1998 const Basis3f& original_shading_basis,
1999 const Color3f& weight,
2000 Arena& arena)
2001 {
2002 if (closure == nullptr)
2003 return;
2004
2005 switch (closure->id)
2006 {
2007 case OSL::ClosureColor::MUL:
2008 {
2009 const OSL::ClosureMul* c = reinterpret_cast<const OSL::ClosureMul*>(closure);
2010 process_closure_tree(c->closure, original_shading_basis, weight * Color3f(c->weight), arena);
2011 }
2012 break;
2013
2014 case OSL::ClosureColor::ADD:
2015 {
2016 const OSL::ClosureAdd* c = reinterpret_cast<const OSL::ClosureAdd*>(closure);
2017 process_closure_tree(c->closureA, original_shading_basis, weight, arena);
2018 process_closure_tree(c->closureB, original_shading_basis, weight, arena);
2019 }
2020 break;
2021
2022 default:
2023 {
2024 const OSL::ClosureComponent* c = reinterpret_cast<const OSL::ClosureComponent*>(closure);
2025
2026 if (c->id == SubsurfaceID)
2027 {
2028 const Color3f w = weight * Color3f(c->w);
2029 if (luminance(w) > 0.0f)
2030 {
2031 SubsurfaceClosure::convert_closure(
2032 *this,
2033 original_shading_basis,
2034 c->data(),
2035 w,
2036 arena);
2037 }
2038 }
2039 else if (c->id == RandomwalkGlassID)
2040 {
2041 const Color3f w = weight * Color3f(c->w);
2042 if (luminance(w) > 0.0f)
2043 {
2044 RandomwalkGlassClosure::convert_closure(
2045 *this,
2046 original_shading_basis,
2047 c->data(),
2048 w,
2049 arena);
2050 }
2051 }
2052 }
2053 break;
2054 }
2055 }
2056
2057
2058 //
2059 // CompositeEmissionClosure class implementation.
2060 //
2061
CompositeEmissionClosure(const OSL::ClosureColor * ci,Arena & arena)2062 CompositeEmissionClosure::CompositeEmissionClosure(
2063 const OSL::ClosureColor* ci,
2064 Arena& arena)
2065 {
2066 process_closure_tree(ci, Color3f(1.0f), arena);
2067 compute_pdfs(m_pdfs);
2068 }
2069
choose_closure(const float w) const2070 size_t CompositeEmissionClosure::choose_closure(const float w) const
2071 {
2072 assert(get_closure_count() > 0);
2073 return sample_pdf_linear_search(m_pdfs, get_closure_count(), w);
2074 }
2075
2076 template <typename InputValues>
add_closure(const ClosureID closure_type,const Color3f & weight,const float max_weight_component,Arena & arena)2077 InputValues* CompositeEmissionClosure::add_closure(
2078 const ClosureID closure_type,
2079 const Color3f& weight,
2080 const float max_weight_component,
2081 Arena& arena)
2082 {
2083 // Make sure we have enough space.
2084 if APPLESEED_UNLIKELY(get_closure_count() >= MaxClosureEntries)
2085 {
2086 throw ExceptionOSLRuntimeError(
2087 "maximum number of closures in osl shader group exceeded");
2088 }
2089
2090 m_closure_types[m_closure_count] = closure_type;
2091 m_weights[m_closure_count].set(weight, g_std_lighting_conditions, Spectrum::Reflectance);
2092 m_pdfs[m_closure_count] = max_weight_component;
2093
2094 InputValues* values = arena.allocate<InputValues>();
2095 m_input_values[m_closure_count] = values;
2096
2097 ++m_closure_count;
2098
2099 return values;
2100 }
2101
process_closure_tree(const OSL::ClosureColor * closure,const Color3f & weight,Arena & arena)2102 void CompositeEmissionClosure::process_closure_tree(
2103 const OSL::ClosureColor* closure,
2104 const Color3f& weight,
2105 Arena& arena)
2106 {
2107 if (closure == nullptr)
2108 return;
2109
2110 switch (closure->id)
2111 {
2112 case OSL::ClosureColor::MUL:
2113 {
2114 const OSL::ClosureMul* c = reinterpret_cast<const OSL::ClosureMul*>(closure);
2115 process_closure_tree(c->closure, weight * Color3f(c->weight), arena);
2116 }
2117 break;
2118
2119 case OSL::ClosureColor::ADD:
2120 {
2121 const OSL::ClosureAdd* c = reinterpret_cast<const OSL::ClosureAdd*>(closure);
2122 process_closure_tree(c->closureA, weight, arena);
2123 process_closure_tree(c->closureB, weight, arena);
2124 }
2125 break;
2126
2127 default:
2128 {
2129 const OSL::ClosureComponent* c = reinterpret_cast<const OSL::ClosureComponent*>(closure);
2130
2131 const Color3f w = weight * Color3f(c->w);
2132 const float max_weight_component = max_value(w);
2133
2134 if (max_weight_component > 0.0f)
2135 {
2136 if (c->id == EmissionID)
2137 {
2138 EmissionClosure::convert_closure(
2139 *this,
2140 c->data(),
2141 w,
2142 max_weight_component,
2143 arena);
2144 }
2145 }
2146 }
2147 break;
2148 }
2149 }
2150
2151
2152 //
2153 // CompositeNPRClosure class implementation.
2154 //
2155
CompositeNPRClosure(const OSL::ClosureColor * ci,Arena & arena)2156 CompositeNPRClosure::CompositeNPRClosure(
2157 const OSL::ClosureColor* ci,
2158 Arena& arena)
2159 {
2160 process_closure_tree(ci, Color3f(1.0f), arena);
2161 }
2162
2163 template <typename InputValues>
add_closure(const ClosureID closure_type,const Color3f & weight,Arena & arena)2164 InputValues* CompositeNPRClosure::add_closure(
2165 const ClosureID closure_type,
2166 const Color3f& weight,
2167 Arena& arena)
2168 {
2169 // Make sure we have enough space.
2170 if APPLESEED_UNLIKELY(get_closure_count() >= MaxClosureEntries)
2171 {
2172 throw ExceptionOSLRuntimeError(
2173 "maximum number of closures in osl shader group exceeded");
2174 }
2175
2176 m_closure_types[m_closure_count] = closure_type;
2177 m_weights[m_closure_count].set(weight, g_std_lighting_conditions, Spectrum::Reflectance);
2178
2179 InputValues* values = arena.allocate<InputValues>();
2180 m_input_values[m_closure_count] = values;
2181
2182 ++m_closure_count;
2183
2184 return values;
2185 }
2186
get_nth_contour_closure_index(const size_t i) const2187 size_t CompositeNPRClosure::get_nth_contour_closure_index(const size_t i) const
2188 {
2189 size_t n = 0;
2190
2191 for (size_t j = 0 , e = get_closure_count(); j < e; ++j)
2192 {
2193 if (get_closure_type(j) == NPRContourID)
2194 {
2195 if (n == i)
2196 return j;
2197
2198 ++n;
2199 }
2200 }
2201
2202 return ~0;
2203 }
2204
process_closure_tree(const OSL::ClosureColor * closure,const Color3f & weight,Arena & arena)2205 void CompositeNPRClosure::process_closure_tree(
2206 const OSL::ClosureColor* closure,
2207 const Color3f& weight,
2208 Arena& arena)
2209 {
2210 if (closure == nullptr)
2211 return;
2212
2213 switch (closure->id)
2214 {
2215 case OSL::ClosureColor::MUL:
2216 {
2217 const OSL::ClosureMul* c = reinterpret_cast<const OSL::ClosureMul*>(closure);
2218 process_closure_tree(c->closure, weight * Color3f(c->weight), arena);
2219 }
2220 break;
2221
2222 case OSL::ClosureColor::ADD:
2223 {
2224 const OSL::ClosureAdd* c = reinterpret_cast<const OSL::ClosureAdd*>(closure);
2225 process_closure_tree(c->closureA, weight, arena);
2226 process_closure_tree(c->closureB, weight, arena);
2227 }
2228 break;
2229
2230 default:
2231 {
2232 const OSL::ClosureComponent* c = reinterpret_cast<const OSL::ClosureComponent*>(closure);
2233 if (c->id == NPRShadingID)
2234 {
2235 const Color3f w = weight * Color3f(c->w);
2236 NPRShadingClosure::convert_closure(
2237 *this,
2238 c->data(),
2239 w,
2240 arena);
2241 }
2242 else if (c->id == NPRContourID)
2243 {
2244 const Color3f w = weight * Color3f(c->w);
2245 NPRContourClosure::convert_closure(
2246 *this,
2247 c->data(),
2248 w,
2249 arena);
2250 }
2251 }
2252 break;
2253 }
2254 }
2255
2256
2257 //
2258 // Utility functions implementation.
2259 //
2260
2261 namespace
2262 {
do_process_closure_id_tree(const OSL::ClosureColor * closure,const int closure_id)2263 Color3f do_process_closure_id_tree(
2264 const OSL::ClosureColor* closure,
2265 const int closure_id)
2266 {
2267 if (closure)
2268 {
2269 switch (closure->id)
2270 {
2271 case OSL::ClosureColor::MUL:
2272 {
2273 const OSL::ClosureMul* c = reinterpret_cast<const OSL::ClosureMul*>(closure);
2274 return Color3f(c->weight) * do_process_closure_id_tree(c->closure, closure_id);
2275 }
2276 break;
2277
2278 case OSL::ClosureColor::ADD:
2279 {
2280 const OSL::ClosureAdd* c = reinterpret_cast<const OSL::ClosureAdd*>(closure);
2281 return do_process_closure_id_tree(c->closureA, closure_id) +
2282 do_process_closure_id_tree(c->closureB, closure_id);
2283 }
2284 break;
2285
2286 default:
2287 {
2288 const OSL::ClosureComponent* c = reinterpret_cast<const OSL::ClosureComponent*>(closure);
2289 if (c->id == closure_id)
2290 return Color3f(c->w);
2291 else return Color3f(0.0f);
2292 }
2293 break;
2294 }
2295 }
2296
2297 return Color3f(0.0f);
2298 }
2299 }
2300
process_transparency_tree(const OSL::ClosureColor * ci,Alpha & alpha)2301 void process_transparency_tree(const OSL::ClosureColor* ci, Alpha& alpha)
2302 {
2303 // Convert from transparency to opacity.
2304 const float transparency = saturate(luminance(do_process_closure_id_tree(ci, TransparentID)));
2305 alpha.set(1.0f - transparency);
2306 }
2307
process_matte_tree(const OSL::ClosureColor * closure,Color3f & matte_color,float & matte_alpha)2308 bool process_matte_tree(
2309 const OSL::ClosureColor* closure,
2310 Color3f& matte_color,
2311 float& matte_alpha)
2312 {
2313 if (closure)
2314 {
2315 switch (closure->id)
2316 {
2317 case OSL::ClosureColor::MUL:
2318 {
2319 const OSL::ClosureMul* c = reinterpret_cast<const OSL::ClosureMul*>(closure);
2320 const bool is_matte = process_matte_tree(c->closure, matte_color, matte_alpha);
2321 matte_color = Color3f(c->weight) * matte_color;
2322 matte_alpha = saturate(luminance(Color3f((c->weight) * matte_alpha)));
2323 return is_matte;
2324 }
2325
2326 case OSL::ClosureColor::ADD:
2327 {
2328 const OSL::ClosureAdd* c = reinterpret_cast<const OSL::ClosureAdd*>(closure);
2329 Color3f color_a(0.0f), color_b(0.0f);
2330 float alpha_a(0.0f), alpha_b(0.0f);
2331 const bool is_matte_a = process_matte_tree(c->closureA, color_a, alpha_a);
2332 const bool is_matte_b = process_matte_tree(c->closureB, color_b, alpha_b);
2333 matte_color = color_a + color_b;
2334 matte_alpha = alpha_a + alpha_b;
2335 return is_matte_a || is_matte_b;
2336 }
2337
2338 default:
2339 {
2340 const OSL::ClosureComponent* c = reinterpret_cast<const OSL::ClosureComponent*>(closure);
2341
2342 if (c->id == MatteID)
2343 {
2344 const MatteClosure::Params* p = static_cast<const MatteClosure::Params*>(c->data());
2345 matte_color = p->matte_color;
2346 matte_alpha = p->matte_alpha;
2347 return true;
2348 }
2349 else if (c->id == HoldoutID)
2350 {
2351 matte_color.set(0.0f);
2352 matte_alpha = 0.0f;
2353 return true;
2354 }
2355 }
2356 break;
2357 }
2358 }
2359
2360 return false;
2361 }
2362
process_background_tree(const OSL::ClosureColor * ci)2363 Color3f process_background_tree(const OSL::ClosureColor* ci)
2364 {
2365 return do_process_closure_id_tree(ci, BackgroundID);
2366 }
2367
2368 namespace
2369 {
2370 template <typename ClosureType>
register_closure(OSLShadingSystem & shading_system)2371 void register_closure(OSLShadingSystem& shading_system)
2372 {
2373 ClosureType::register_closure(shading_system);
2374 RENDERER_LOG_DEBUG("registered osl closure %s.", ClosureType::name());
2375 }
2376 }
2377
register_closures(OSLShadingSystem & shading_system)2378 void register_closures(OSLShadingSystem& shading_system)
2379 {
2380 for (size_t i = 0; i < NumClosuresIDs; ++i)
2381 {
2382 g_closure_convert_funs[i] = &convert_closure_nop;
2383 g_closure_get_modes_funs[i] = &closure_no_modes;
2384 }
2385
2386 register_closure<AshikhminShirleyClosure>(shading_system);
2387 register_closure<BackgroundClosure>(shading_system);
2388 register_closure<BlinnClosure>(shading_system);
2389 register_closure<DebugClosure>(shading_system);
2390 register_closure<DiffuseClosure>(shading_system);
2391 register_closure<DisneyClosure>(shading_system);
2392 register_closure<EmissionClosure>(shading_system);
2393 register_closure<GlassClosure>(shading_system);
2394 register_closure<GlossyClosure>(shading_system);
2395 register_closure<HoldoutClosure>(shading_system);
2396 register_closure<MatteClosure>(shading_system);
2397 register_closure<MetalClosure>(shading_system);
2398 register_closure<NPRContourClosure>(shading_system);
2399 register_closure<NPRShadingClosure>(shading_system);
2400 register_closure<OrenNayarClosure>(shading_system);
2401 register_closure<PhongClosure>(shading_system);
2402 register_closure<PlasticClosure>(shading_system);
2403 register_closure<RandomwalkGlassClosure>(shading_system);
2404 register_closure<ReflectionClosure>(shading_system);
2405 register_closure<SheenClosure>(shading_system);
2406 register_closure<SubsurfaceClosure>(shading_system);
2407 register_closure<TranslucentClosure>(shading_system);
2408 register_closure<TransparentClosure>(shading_system);
2409 }
2410
2411 } // namespace renderer
2412