Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/kernel/osl/closures_setup.h')
-rw-r--r--intern/cycles/kernel/osl/closures_setup.h1166
1 files changed, 1166 insertions, 0 deletions
diff --git a/intern/cycles/kernel/osl/closures_setup.h b/intern/cycles/kernel/osl/closures_setup.h
new file mode 100644
index 00000000000..f8d68444f90
--- /dev/null
+++ b/intern/cycles/kernel/osl/closures_setup.h
@@ -0,0 +1,1166 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Adapted from Open Shading Language
+ * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
+ * All Rights Reserved.
+ *
+ * Modifications Copyright 2011-2022 Blender Foundation. */
+
+#pragma once
+
+// clang-format off
+#include "kernel/closure/alloc.h"
+#include "kernel/closure/bsdf_util.h"
+#include "kernel/closure/bsdf_ashikhmin_velvet.h"
+#include "kernel/closure/bsdf_diffuse.h"
+#include "kernel/closure/bsdf_microfacet.h"
+#include "kernel/closure/bsdf_microfacet_multi.h"
+#include "kernel/closure/bsdf_oren_nayar.h"
+#include "kernel/closure/bsdf_reflection.h"
+#include "kernel/closure/bsdf_refraction.h"
+#include "kernel/closure/bsdf_transparent.h"
+#include "kernel/closure/bsdf_ashikhmin_shirley.h"
+#include "kernel/closure/bsdf_toon.h"
+#include "kernel/closure/bsdf_hair.h"
+#include "kernel/closure/bsdf_hair_principled.h"
+#include "kernel/closure/bsdf_principled_diffuse.h"
+#include "kernel/closure/bsdf_principled_sheen.h"
+#include "kernel/closure/volume.h"
+#include "kernel/closure/bsdf_diffuse_ramp.h"
+#include "kernel/closure/bsdf_phong_ramp.h"
+#include "kernel/closure/bssrdf.h"
+#include "kernel/closure/emissive.h"
+// clang-format on
+
+CCL_NAMESPACE_BEGIN
+
+#define OSL_CLOSURE_STRUCT_BEGIN(Upper, lower) \
+ struct ccl_align(8) Upper##Closure \
+ { \
+ const char *label;
+#define OSL_CLOSURE_STRUCT_END(Upper, lower) \
+ } \
+ ; \
+ ccl_device void osl_closure_##lower##_setup(KernelGlobals kg, \
+ ccl_private ShaderData *sd, \
+ uint32_t path_flag, \
+ float3 weight, \
+ ccl_private Upper##Closure *closure);
+#define OSL_CLOSURE_STRUCT_MEMBER(Upper, TYPE, type, name, key) type name;
+#define OSL_CLOSURE_STRUCT_ARRAY_MEMBER(Upper, TYPE, type, name, key, size) type name[size];
+
+#include "closures_template.h"
+
+ccl_device_forceinline bool osl_closure_skip(KernelGlobals kg,
+ ccl_private const ShaderData *sd,
+ uint32_t path_flag,
+ int scattering)
+{
+ /* caustic options */
+ if ((scattering & LABEL_GLOSSY) && (path_flag & PATH_RAY_DIFFUSE)) {
+ if ((!kernel_data.integrator.caustics_reflective && (scattering & LABEL_REFLECT)) ||
+ (!kernel_data.integrator.caustics_refractive && (scattering & LABEL_TRANSMIT))) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* Diffuse */
+
+ccl_device void osl_closure_diffuse_setup(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const DiffuseClosure *closure)
+{
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_DIFFUSE)) {
+ return;
+ }
+
+ ccl_private DiffuseBsdf *bsdf = (ccl_private DiffuseBsdf *)bsdf_alloc(
+ sd, sizeof(DiffuseBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+
+ sd->flag |= bsdf_diffuse_setup(bsdf);
+}
+
+ccl_device void osl_closure_oren_nayar_setup(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const OrenNayarClosure *closure)
+{
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_DIFFUSE)) {
+ return;
+ }
+
+ ccl_private OrenNayarBsdf *bsdf = (ccl_private OrenNayarBsdf *)bsdf_alloc(
+ sd, sizeof(OrenNayarBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->roughness = closure->roughness;
+
+ sd->flag |= bsdf_oren_nayar_setup(bsdf);
+}
+
+ccl_device void osl_closure_translucent_setup(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const TranslucentClosure *closure)
+{
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_DIFFUSE)) {
+ return;
+ }
+
+ ccl_private DiffuseBsdf *bsdf = (ccl_private DiffuseBsdf *)bsdf_alloc(
+ sd, sizeof(DiffuseBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+
+ sd->flag |= bsdf_translucent_setup(bsdf);
+}
+
+ccl_device void osl_closure_reflection_setup(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const ReflectionClosure *closure)
+{
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_SINGULAR)) {
+ return;
+ }
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+
+ sd->flag |= bsdf_reflection_setup(bsdf);
+}
+
+ccl_device void osl_closure_refraction_setup(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const RefractionClosure *closure)
+{
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_SINGULAR)) {
+ return;
+ }
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->ior = closure->ior;
+
+ sd->flag |= bsdf_refraction_setup(bsdf);
+}
+
+ccl_device void osl_closure_transparent_setup(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const TransparentClosure *closure)
+{
+ bsdf_transparent_setup(sd, rgb_to_spectrum(weight), path_flag);
+}
+
+/* Standard microfacet closures */
+
+ccl_device void osl_closure_microfacet_setup(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const MicrofacetClosure *closure)
+{
+ const int label = (closure->refract) ? LABEL_TRANSMIT : LABEL_REFLECT;
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | label)) {
+ return;
+ }
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->alpha_x = closure->alpha_x;
+ bsdf->alpha_y = closure->alpha_y;
+ bsdf->ior = closure->ior;
+ bsdf->T = closure->T;
+
+ static OSL::ustring u_ggx("ggx");
+ static OSL::ustring u_default("default");
+
+ /* GGX */
+ if (closure->distribution == u_ggx || closure->distribution == u_default) {
+ if (!closure->refract) {
+ if (closure->alpha_x == closure->alpha_y) {
+ /* Isotropic */
+ sd->flag |= bsdf_microfacet_ggx_isotropic_setup(bsdf);
+ }
+ else {
+ /* Anisotropic */
+ sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
+ }
+ }
+ else {
+ sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
+ }
+ }
+ /* Beckmann */
+ else {
+ if (!closure->refract) {
+ if (closure->alpha_x == closure->alpha_y) {
+ /* Isotropic */
+ sd->flag |= bsdf_microfacet_beckmann_isotropic_setup(bsdf);
+ }
+ else {
+ /* Anisotropic */
+ sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
+ }
+ }
+ else {
+ sd->flag |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
+ }
+ }
+}
+
+ccl_device void osl_closure_microfacet_ggx_setup(
+ KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const MicrofacetGGXIsotropicClosure *closure)
+{
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
+ return;
+ }
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->alpha_x = closure->alpha_x;
+
+ sd->flag |= bsdf_microfacet_ggx_isotropic_setup(bsdf);
+}
+
+ccl_device void osl_closure_microfacet_ggx_aniso_setup(
+ KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const MicrofacetGGXClosure *closure)
+{
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
+ return;
+ }
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->alpha_x = closure->alpha_x;
+ bsdf->alpha_y = closure->alpha_y;
+ bsdf->T = closure->T;
+
+ sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
+}
+
+ccl_device void osl_closure_microfacet_ggx_refraction_setup(
+ KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const MicrofacetGGXRefractionClosure *closure)
+{
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_TRANSMIT)) {
+ return;
+ }
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->alpha_x = closure->alpha_x;
+ bsdf->ior = closure->ior;
+
+ sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
+}
+
+/* GGX closures with Fresnel */
+
+ccl_device void osl_closure_microfacet_ggx_fresnel_setup(
+ KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const MicrofacetGGXFresnelClosure *closure)
+{
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
+ return;
+ }
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ ccl_private MicrofacetExtra *extra = (ccl_private MicrofacetExtra *)closure_alloc_extra(
+ sd, sizeof(MicrofacetExtra));
+ if (!extra) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->alpha_x = closure->alpha_x;
+ bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->ior = closure->ior;
+
+ bsdf->extra = extra;
+ bsdf->extra->color = rgb_to_spectrum(closure->color);
+ bsdf->extra->cspec0 = rgb_to_spectrum(closure->cspec0);
+ bsdf->extra->clearcoat = 0.0f;
+
+ bsdf->T = zero_float3();
+
+ sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd);
+}
+
+ccl_device void osl_closure_microfacet_ggx_aniso_fresnel_setup(
+ KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const MicrofacetGGXAnisoFresnelClosure *closure)
+{
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
+ return;
+ }
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ ccl_private MicrofacetExtra *extra = (ccl_private MicrofacetExtra *)closure_alloc_extra(
+ sd, sizeof(MicrofacetExtra));
+ if (!extra) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->alpha_x = closure->alpha_x;
+ bsdf->alpha_y = closure->alpha_y;
+ bsdf->ior = closure->ior;
+
+ bsdf->extra = extra;
+ bsdf->extra->color = rgb_to_spectrum(closure->color);
+ bsdf->extra->cspec0 = rgb_to_spectrum(closure->cspec0);
+ bsdf->extra->clearcoat = 0.0f;
+
+ bsdf->T = closure->T;
+
+ sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd);
+}
+
+/* Multi-scattering GGX closures */
+
+ccl_device void osl_closure_microfacet_multi_ggx_setup(
+ KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const MicrofacetMultiGGXClosure *closure)
+{
+ /* Technically, the MultiGGX closure may also transmit. However,
+ * since this is set statically and only used for caustic flags, this
+ * is probably as good as it gets. */
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
+ return;
+ }
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ ccl_private MicrofacetExtra *extra = (ccl_private MicrofacetExtra *)closure_alloc_extra(
+ sd, sizeof(MicrofacetExtra));
+ if (!extra) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->alpha_x = closure->alpha_x;
+ bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->ior = 0.0f;
+
+ bsdf->extra = extra;
+ bsdf->extra->color = rgb_to_spectrum(closure->color);
+ bsdf->extra->cspec0 = zero_spectrum();
+ bsdf->extra->clearcoat = 0.0f;
+
+ bsdf->T = zero_float3();
+
+ sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf);
+}
+
+ccl_device void osl_closure_microfacet_multi_ggx_glass_setup(
+ KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const MicrofacetMultiGGXGlassClosure *closure)
+{
+ /* Technically, the MultiGGX closure may also transmit. However,
+ * since this is set statically and only used for caustic flags, this
+ * is probably as good as it gets. */
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
+ return;
+ }
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ ccl_private MicrofacetExtra *extra = (ccl_private MicrofacetExtra *)closure_alloc_extra(
+ sd, sizeof(MicrofacetExtra));
+ if (!extra) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->alpha_x = closure->alpha_x;
+ bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->ior = closure->ior;
+
+ bsdf->extra = extra;
+ bsdf->extra->color = rgb_to_spectrum(closure->color);
+ bsdf->extra->cspec0 = zero_spectrum();
+ bsdf->extra->clearcoat = 0.0f;
+
+ bsdf->T = zero_float3();
+
+ sd->flag |= bsdf_microfacet_multi_ggx_glass_setup(bsdf);
+}
+
+ccl_device void osl_closure_microfacet_multi_ggx_aniso_setup(
+ KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const MicrofacetMultiGGXAnisoClosure *closure)
+{
+ /* Technically, the MultiGGX closure may also transmit. However,
+ * since this is set statically and only used for caustic flags, this
+ * is probably as good as it gets. */
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
+ return;
+ }
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ ccl_private MicrofacetExtra *extra = (ccl_private MicrofacetExtra *)closure_alloc_extra(
+ sd, sizeof(MicrofacetExtra));
+ if (!extra) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->alpha_x = closure->alpha_x;
+ bsdf->alpha_y = closure->alpha_y;
+ bsdf->ior = 0.0f;
+
+ bsdf->extra = extra;
+ bsdf->extra->color = rgb_to_spectrum(closure->color);
+ bsdf->extra->cspec0 = zero_spectrum();
+ bsdf->extra->clearcoat = 0.0f;
+
+ bsdf->T = closure->T;
+
+ sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf);
+}
+
+/* Multi-scattering GGX closures with Fresnel */
+
+ccl_device void osl_closure_microfacet_multi_ggx_fresnel_setup(
+ KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const MicrofacetMultiGGXFresnelClosure *closure)
+{
+ /* Technically, the MultiGGX closure may also transmit. However,
+ * since this is set statically and only used for caustic flags, this
+ * is probably as good as it gets. */
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
+ return;
+ }
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ ccl_private MicrofacetExtra *extra = (ccl_private MicrofacetExtra *)closure_alloc_extra(
+ sd, sizeof(MicrofacetExtra));
+ if (!extra) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->alpha_x = closure->alpha_x;
+ bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->ior = closure->ior;
+
+ bsdf->extra = extra;
+ bsdf->extra->color = rgb_to_spectrum(closure->color);
+ bsdf->extra->cspec0 = rgb_to_spectrum(closure->cspec0);
+ bsdf->extra->clearcoat = 0.0f;
+
+ bsdf->T = zero_float3();
+
+ sd->flag |= bsdf_microfacet_multi_ggx_fresnel_setup(bsdf, sd);
+}
+
+ccl_device void osl_closure_microfacet_multi_ggx_glass_fresnel_setup(
+ KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const MicrofacetMultiGGXGlassFresnelClosure *closure)
+{
+ /* Technically, the MultiGGX closure may also transmit. However,
+ * since this is set statically and only used for caustic flags, this
+ * is probably as good as it gets. */
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
+ return;
+ }
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ ccl_private MicrofacetExtra *extra = (ccl_private MicrofacetExtra *)closure_alloc_extra(
+ sd, sizeof(MicrofacetExtra));
+ if (!extra) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->alpha_x = closure->alpha_x;
+ bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->ior = closure->ior;
+
+ bsdf->extra = extra;
+ bsdf->extra->color = rgb_to_spectrum(closure->color);
+ bsdf->extra->cspec0 = rgb_to_spectrum(closure->cspec0);
+ bsdf->extra->clearcoat = 0.0f;
+
+ bsdf->T = zero_float3();
+
+ sd->flag |= bsdf_microfacet_multi_ggx_glass_fresnel_setup(bsdf, sd);
+}
+
+ccl_device void osl_closure_microfacet_multi_ggx_aniso_fresnel_setup(
+ KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const MicrofacetMultiGGXAnisoFresnelClosure *closure)
+{
+ /* Technically, the MultiGGX closure may also transmit. However,
+ * since this is set statically and only used for caustic flags, this
+ * is probably as good as it gets. */
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
+ return;
+ }
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ ccl_private MicrofacetExtra *extra = (ccl_private MicrofacetExtra *)closure_alloc_extra(
+ sd, sizeof(MicrofacetExtra));
+ if (!extra) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->alpha_x = closure->alpha_x;
+ bsdf->alpha_y = closure->alpha_y;
+ bsdf->ior = closure->ior;
+
+ bsdf->extra = extra;
+ bsdf->extra->color = rgb_to_spectrum(closure->color);
+ bsdf->extra->cspec0 = rgb_to_spectrum(closure->cspec0);
+ bsdf->extra->clearcoat = 0.0f;
+
+ bsdf->T = closure->T;
+
+ sd->flag |= bsdf_microfacet_multi_ggx_fresnel_setup(bsdf, sd);
+}
+
+/* Beckmann closures */
+
+ccl_device void osl_closure_microfacet_beckmann_setup(
+ KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const MicrofacetBeckmannIsotropicClosure *closure)
+{
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
+ return;
+ }
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->alpha_x = closure->alpha_x;
+
+ sd->flag |= bsdf_microfacet_beckmann_isotropic_setup(bsdf);
+}
+
+ccl_device void osl_closure_microfacet_beckmann_aniso_setup(
+ KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const MicrofacetBeckmannClosure *closure)
+{
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
+ return;
+ }
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->alpha_x = closure->alpha_x;
+ bsdf->alpha_y = closure->alpha_y;
+ bsdf->T = closure->T;
+
+ sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
+}
+
+ccl_device void osl_closure_microfacet_beckmann_refraction_setup(
+ KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const MicrofacetBeckmannRefractionClosure *closure)
+{
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_TRANSMIT)) {
+ return;
+ }
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->alpha_x = closure->alpha_x;
+ bsdf->ior = closure->ior;
+
+ sd->flag |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
+}
+
+/* Ashikhmin closures */
+
+ccl_device void osl_closure_ashikhmin_velvet_setup(
+ KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const AshikhminVelvetClosure *closure)
+{
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_DIFFUSE)) {
+ return;
+ }
+
+ ccl_private VelvetBsdf *bsdf = (ccl_private VelvetBsdf *)bsdf_alloc(
+ sd, sizeof(VelvetBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->sigma = closure->sigma;
+
+ sd->flag |= bsdf_ashikhmin_velvet_setup(bsdf);
+}
+
+ccl_device void osl_closure_ashikhmin_shirley_setup(
+ KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const AshikhminShirleyClosure *closure)
+{
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
+ return;
+ }
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->alpha_x = closure->alpha_x;
+ bsdf->alpha_y = closure->alpha_y;
+ bsdf->T = closure->T;
+
+ sd->flag |= bsdf_ashikhmin_shirley_setup(bsdf);
+}
+
+ccl_device void osl_closure_diffuse_toon_setup(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const DiffuseToonClosure *closure)
+{
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_DIFFUSE)) {
+ return;
+ }
+
+ ccl_private ToonBsdf *bsdf = (ccl_private ToonBsdf *)bsdf_alloc(
+ sd, sizeof(ToonBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->size = closure->size;
+ bsdf->smooth = closure->smooth;
+
+ sd->flag |= bsdf_diffuse_toon_setup(bsdf);
+}
+
+ccl_device void osl_closure_glossy_toon_setup(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const GlossyToonClosure *closure)
+{
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY)) {
+ return;
+ }
+
+ ccl_private ToonBsdf *bsdf = (ccl_private ToonBsdf *)bsdf_alloc(
+ sd, sizeof(ToonBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->size = closure->size;
+ bsdf->smooth = closure->smooth;
+
+ sd->flag |= bsdf_glossy_toon_setup(bsdf);
+}
+
+/* Disney principled closures */
+
+ccl_device void osl_closure_principled_diffuse_setup(
+ KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const PrincipledDiffuseClosure *closure)
+{
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_DIFFUSE)) {
+ return;
+ }
+
+ ccl_private PrincipledDiffuseBsdf *bsdf = (ccl_private PrincipledDiffuseBsdf *)bsdf_alloc(
+ sd, sizeof(PrincipledDiffuseBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->roughness = closure->roughness;
+
+ sd->flag |= bsdf_principled_diffuse_setup(bsdf);
+}
+
+ccl_device void osl_closure_principled_sheen_setup(
+ KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const PrincipledSheenClosure *closure)
+{
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_DIFFUSE)) {
+ return;
+ }
+
+ ccl_private PrincipledSheenBsdf *bsdf = (ccl_private PrincipledSheenBsdf *)bsdf_alloc(
+ sd, sizeof(PrincipledSheenBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->avg_value = 0.0f;
+
+ sd->flag |= bsdf_principled_sheen_setup(sd, bsdf);
+}
+
+ccl_device void osl_closure_principled_clearcoat_setup(
+ KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const PrincipledClearcoatClosure *closure)
+{
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ MicrofacetExtra *extra = (MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
+ if (!extra) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->alpha_x = closure->clearcoat_roughness;
+ bsdf->alpha_y = closure->clearcoat_roughness;
+ bsdf->ior = 1.5f;
+
+ bsdf->extra = extra;
+ bsdf->extra->color = zero_spectrum();
+ bsdf->extra->cspec0 = make_spectrum(0.04f);
+ bsdf->extra->clearcoat = closure->clearcoat;
+
+ bsdf->T = zero_float3();
+
+ sd->flag |= bsdf_microfacet_ggx_clearcoat_setup(bsdf, sd);
+}
+
+/* Variable cone emissive closure
+ *
+ * This primitive emits in a cone having a configurable penumbra area where the light decays to 0
+ * reaching the outer_angle limit. It can also behave as a lambertian emitter if the provided
+ * angles are PI/2, which is the default
+ */
+ccl_device void osl_closure_emission_setup(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t /* path_flag */,
+ float3 weight,
+ ccl_private const GenericEmissiveClosure *closure)
+{
+ emission_setup(sd, rgb_to_spectrum(weight));
+}
+
+/* Generic background closure
+ *
+ * We only have a background closure for the shaders to return a color in background shaders. No
+ * methods, only the weight is taking into account
+ */
+ccl_device void osl_closure_background_setup(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t /* path_flag */,
+ float3 weight,
+ ccl_private const GenericBackgroundClosure *closure)
+{
+ background_setup(sd, rgb_to_spectrum(weight));
+}
+
+/* Holdout closure
+ *
+ * This will be used by the shader to mark the amount of holdout for the current shading point. No
+ * parameters, only the weight will be used
+ */
+ccl_device void osl_closure_holdout_setup(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t /* path_flag */,
+ float3 weight,
+ ccl_private const HoldoutClosure *closure)
+{
+ closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, rgb_to_spectrum(weight));
+ sd->flag |= SD_HOLDOUT;
+}
+
+ccl_device void osl_closure_diffuse_ramp_setup(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t /* path_flag */,
+ float3 weight,
+ ccl_private const DiffuseRampClosure *closure)
+{
+ ccl_private DiffuseRampBsdf *bsdf = (ccl_private DiffuseRampBsdf *)bsdf_alloc(
+ sd, sizeof(DiffuseRampBsdf), rgb_to_spectrum(weight));
+
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+
+ bsdf->colors = (float3 *)closure_alloc_extra(sd, sizeof(float3) * 8);
+ if (!bsdf->colors) {
+ return;
+ }
+
+ for (int i = 0; i < 8; i++)
+ bsdf->colors[i] = closure->colors[i];
+
+ sd->flag |= bsdf_diffuse_ramp_setup(bsdf);
+}
+
+ccl_device void osl_closure_phong_ramp_setup(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t /* path_flag */,
+ float3 weight,
+ ccl_private const PhongRampClosure *closure)
+{
+ ccl_private PhongRampBsdf *bsdf = (ccl_private PhongRampBsdf *)bsdf_alloc(
+ sd, sizeof(PhongRampBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->exponent = closure->exponent;
+
+ bsdf->colors = (float3 *)closure_alloc_extra(sd, sizeof(float3) * 8);
+ if (!bsdf->colors) {
+ return;
+ }
+
+ for (int i = 0; i < 8; i++)
+ bsdf->colors[i] = closure->colors[i];
+
+ sd->flag |= bsdf_phong_ramp_setup(bsdf);
+}
+
+ccl_device void osl_closure_bssrdf_setup(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const BSSRDFClosure *closure)
+{
+ static ustring u_burley("burley");
+ static ustring u_random_walk_fixed_radius("random_walk_fixed_radius");
+ static ustring u_random_walk("random_walk");
+
+ ClosureType type;
+ if (closure->method == u_burley) {
+ type = CLOSURE_BSSRDF_BURLEY_ID;
+ }
+ else if (closure->method == u_random_walk_fixed_radius) {
+ type = CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID;
+ }
+ else if (closure->method == u_random_walk) {
+ type = CLOSURE_BSSRDF_RANDOM_WALK_ID;
+ }
+ else {
+ return;
+ }
+
+ ccl_private Bssrdf *bssrdf = bssrdf_alloc(sd, rgb_to_spectrum(weight));
+ if (!bssrdf) {
+ return;
+ }
+
+ /* disable in case of diffuse ancestor, can't see it well then and
+ * adds considerably noise due to probabilities of continuing path
+ * getting lower and lower */
+ if (path_flag & PATH_RAY_DIFFUSE_ANCESTOR) {
+ bssrdf->radius = zero_spectrum();
+ }
+ else {
+ bssrdf->radius = closure->radius;
+ }
+
+ /* create one closure per color channel */
+ bssrdf->albedo = closure->albedo;
+ bssrdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bssrdf->roughness = closure->roughness;
+ bssrdf->anisotropy = clamp(closure->anisotropy, 0.0f, 0.9f);
+
+ sd->flag |= bssrdf_setup(sd, bssrdf, type, clamp(closure->ior, 1.01f, 3.8f));
+}
+
+/* Hair */
+
+ccl_device void osl_closure_hair_reflection_setup(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const HairReflectionClosure *closure)
+{
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY)) {
+ return;
+ }
+
+ ccl_private HairBsdf *bsdf = (ccl_private HairBsdf *)bsdf_alloc(
+ sd, sizeof(HairBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->T = closure->T;
+ bsdf->roughness1 = closure->roughness1;
+ bsdf->roughness2 = closure->roughness2;
+ bsdf->offset = closure->offset;
+
+ sd->flag |= bsdf_hair_reflection_setup(bsdf);
+}
+
+ccl_device void osl_closure_hair_transmission_setup(
+ KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const HairTransmissionClosure *closure)
+{
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY)) {
+ return;
+ }
+
+ ccl_private HairBsdf *bsdf = (ccl_private HairBsdf *)bsdf_alloc(
+ sd, sizeof(HairBsdf), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->T = closure->T;
+ bsdf->roughness1 = closure->roughness1;
+ bsdf->roughness2 = closure->roughness2;
+ bsdf->offset = closure->offset;
+
+ sd->flag |= bsdf_hair_transmission_setup(bsdf);
+}
+
+ccl_device void osl_closure_principled_hair_setup(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const PrincipledHairClosure *closure)
+{
+#ifdef __HAIR__
+ if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY)) {
+ return;
+ }
+
+ ccl_private PrincipledHairBSDF *bsdf = (ccl_private PrincipledHairBSDF *)bsdf_alloc(
+ sd, sizeof(PrincipledHairBSDF), rgb_to_spectrum(weight));
+ if (!bsdf) {
+ return;
+ }
+
+ ccl_private PrincipledHairExtra *extra = (ccl_private PrincipledHairExtra *)closure_alloc_extra(
+ sd, sizeof(PrincipledHairExtra));
+ if (!extra) {
+ return;
+ }
+
+ bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
+ bsdf->sigma = closure->sigma;
+ bsdf->v = closure->v;
+ bsdf->s = closure->s;
+ bsdf->alpha = closure->alpha;
+ bsdf->eta = closure->eta;
+ bsdf->m0_roughness = closure->m0_roughness;
+
+ bsdf->extra = extra;
+
+ sd->flag |= bsdf_principled_hair_setup(sd, bsdf);
+#endif
+}
+
+/* Volume */
+
+ccl_device void osl_closure_absorption_setup(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const VolumeAbsorptionClosure *closure)
+{
+ volume_extinction_setup(sd, rgb_to_spectrum(weight));
+}
+
+ccl_device void osl_closure_henyey_greenstein_setup(
+ KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ uint32_t path_flag,
+ float3 weight,
+ ccl_private const VolumeHenyeyGreensteinClosure *closure)
+{
+ volume_extinction_setup(sd, rgb_to_spectrum(weight));
+
+ ccl_private HenyeyGreensteinVolume *volume = (ccl_private HenyeyGreensteinVolume *)bsdf_alloc(
+ sd, sizeof(HenyeyGreensteinVolume), rgb_to_spectrum(weight));
+ if (!volume) {
+ return;
+ }
+
+ volume->g = closure->g;
+
+ sd->flag |= volume_henyey_greenstein_setup(volume);
+}
+
+CCL_NAMESPACE_END