1321 lines
40 KiB
C
1321 lines
40 KiB
C
/* 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_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) \
|
|
} \
|
|
;
|
|
#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 = 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 = 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 = 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_specular_reflection(sd->Ng, sd->wi, 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_specular_reflection(sd->Ng, sd->wi, 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);
|
|
}
|
|
|
|
/* MaterialX closures */
|
|
ccl_device void osl_closure_dielectric_bsdf_setup(KernelGlobals kg,
|
|
ccl_private ShaderData *sd,
|
|
uint32_t path_flag,
|
|
float3 weight,
|
|
ccl_private const DielectricBSDFClosure *closure)
|
|
{
|
|
const bool has_reflection = !is_zero(closure->reflection_tint);
|
|
const bool has_transmission = !is_zero(closure->transmission_tint);
|
|
|
|
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 FresnelDielectricTint *fresnel = (ccl_private FresnelDielectricTint *)
|
|
closure_alloc_extra(sd, sizeof(FresnelDielectricTint));
|
|
if (!fresnel) {
|
|
return;
|
|
}
|
|
|
|
bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N);
|
|
bsdf->alpha_x = closure->alpha_x;
|
|
bsdf->alpha_y = closure->alpha_y;
|
|
bsdf->ior = closure->ior;
|
|
if (sd->flag & SD_BACKFACING) {
|
|
bsdf->ior = 1.0f / bsdf->ior;
|
|
}
|
|
bsdf->T = closure->T;
|
|
|
|
/* GGX */
|
|
if (closure->distribution == make_string("ggx", 11253504724482777663ull) ||
|
|
closure->distribution == make_string("default", 4430693559278735917ull))
|
|
{
|
|
if (has_reflection && has_transmission) {
|
|
sd->flag |= bsdf_microfacet_ggx_glass_setup(bsdf);
|
|
}
|
|
else if (has_transmission) {
|
|
sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
|
|
}
|
|
else {
|
|
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
|
|
}
|
|
}
|
|
/* Beckmann */
|
|
else {
|
|
if (has_reflection && has_transmission) {
|
|
sd->flag |= bsdf_microfacet_beckmann_glass_setup(bsdf);
|
|
}
|
|
else if (has_transmission) {
|
|
sd->flag |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
|
|
}
|
|
else {
|
|
sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
|
|
}
|
|
}
|
|
|
|
fresnel->reflection_tint = rgb_to_spectrum(closure->reflection_tint);
|
|
fresnel->transmission_tint = rgb_to_spectrum(closure->transmission_tint);
|
|
bsdf_microfacet_setup_fresnel_dielectric_tint(bsdf, sd, fresnel);
|
|
}
|
|
|
|
ccl_device void osl_closure_conductor_bsdf_setup(KernelGlobals kg,
|
|
ccl_private ShaderData *sd,
|
|
uint32_t path_flag,
|
|
float3 weight,
|
|
ccl_private const ConductorBSDFClosure *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 FresnelConductor *fresnel = (ccl_private FresnelConductor *)closure_alloc_extra(
|
|
sd, sizeof(FresnelConductor));
|
|
if (!fresnel) {
|
|
return;
|
|
}
|
|
|
|
bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N);
|
|
bsdf->alpha_x = closure->alpha_x;
|
|
bsdf->alpha_y = closure->alpha_y;
|
|
bsdf->ior = 0.0f;
|
|
bsdf->T = closure->T;
|
|
|
|
/* GGX */
|
|
if (closure->distribution == make_string("ggx", 11253504724482777663ull) ||
|
|
closure->distribution == make_string("default", 4430693559278735917ull))
|
|
{
|
|
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
|
|
}
|
|
/* Beckmann */
|
|
else {
|
|
sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
|
|
}
|
|
|
|
fresnel->n = rgb_to_spectrum(closure->ior);
|
|
fresnel->k = rgb_to_spectrum(closure->extinction);
|
|
bsdf_microfacet_setup_fresnel_conductor(bsdf, sd, fresnel);
|
|
}
|
|
|
|
ccl_device void osl_closure_generalized_schlick_bsdf_setup(
|
|
KernelGlobals kg,
|
|
ccl_private ShaderData *sd,
|
|
uint32_t path_flag,
|
|
float3 weight,
|
|
ccl_private const GeneralizedSchlickBSDFClosure *closure)
|
|
{
|
|
const bool has_reflection = !is_zero(closure->reflection_tint);
|
|
const bool has_transmission = !is_zero(closure->transmission_tint);
|
|
|
|
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 FresnelGeneralizedSchlick *fresnel = (ccl_private FresnelGeneralizedSchlick *)
|
|
closure_alloc_extra(sd, sizeof(FresnelGeneralizedSchlick));
|
|
if (!fresnel) {
|
|
return;
|
|
}
|
|
|
|
bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N);
|
|
bsdf->alpha_x = closure->alpha_x;
|
|
bsdf->alpha_y = closure->alpha_y;
|
|
bsdf->ior = ior_from_F0(closure->f0);
|
|
if (sd->flag & SD_BACKFACING) {
|
|
bsdf->ior = 1.0f / bsdf->ior;
|
|
}
|
|
bsdf->T = closure->T;
|
|
|
|
/* GGX */
|
|
if (closure->distribution == make_string("ggx", 11253504724482777663ull) ||
|
|
closure->distribution == make_string("default", 4430693559278735917ull))
|
|
{
|
|
if (has_reflection && has_transmission) {
|
|
sd->flag |= bsdf_microfacet_ggx_glass_setup(bsdf);
|
|
}
|
|
else if (has_transmission) {
|
|
sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
|
|
}
|
|
else {
|
|
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
|
|
}
|
|
}
|
|
/* Beckmann */
|
|
else {
|
|
if (has_reflection && has_transmission) {
|
|
sd->flag |= bsdf_microfacet_beckmann_glass_setup(bsdf);
|
|
}
|
|
else if (has_transmission) {
|
|
sd->flag |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
|
|
}
|
|
else {
|
|
sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
|
|
}
|
|
}
|
|
|
|
fresnel->reflection_tint = rgb_to_spectrum(closure->reflection_tint);
|
|
fresnel->transmission_tint = rgb_to_spectrum(closure->transmission_tint);
|
|
fresnel->f0 = rgb_to_spectrum(closure->f0);
|
|
fresnel->f90 = rgb_to_spectrum(closure->f90);
|
|
fresnel->exponent = closure->exponent;
|
|
bsdf_microfacet_setup_fresnel_generalized_schlick(bsdf, sd, fresnel);
|
|
}
|
|
|
|
/* 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_specular_reflection(sd->Ng, sd->wi, closure->N);
|
|
bsdf->alpha_x = closure->alpha_x;
|
|
bsdf->alpha_y = closure->alpha_y;
|
|
bsdf->ior = closure->ior;
|
|
bsdf->T = closure->T;
|
|
|
|
/* Beckmann */
|
|
if (closure->distribution == make_string("beckmann", 14712237670914973463ull)) {
|
|
if (closure->refract == 1) {
|
|
sd->flag |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
|
|
}
|
|
else if (closure->refract == 2) {
|
|
sd->flag |= bsdf_microfacet_beckmann_glass_setup(bsdf);
|
|
}
|
|
else {
|
|
sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
|
|
}
|
|
}
|
|
/* Sharp */
|
|
else if (closure->distribution == make_string("sharp", 1870681295563127462ull)) {
|
|
if (closure->refract == 1) {
|
|
sd->flag |= bsdf_refraction_setup(bsdf);
|
|
}
|
|
else if (closure->refract == 2) {
|
|
sd->flag |= bsdf_sharp_glass_setup(bsdf);
|
|
}
|
|
else {
|
|
sd->flag |= bsdf_reflection_setup(bsdf);
|
|
}
|
|
}
|
|
/* Ashikhmin-Shirley */
|
|
else if (closure->distribution == make_string("ashikhmin_shirley", 11318482998918370922ull)) {
|
|
sd->flag |= bsdf_ashikhmin_shirley_setup(bsdf);
|
|
}
|
|
/* GGX */
|
|
else {
|
|
if (closure->refract == 1) {
|
|
sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
|
|
}
|
|
else if (closure->refract == 2) {
|
|
sd->flag |= bsdf_microfacet_ggx_glass_setup(bsdf);
|
|
}
|
|
else {
|
|
sd->flag |= bsdf_microfacet_ggx_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_specular_reflection(sd->Ng, sd->wi, closure->N);
|
|
bsdf->alpha_x = bsdf->alpha_y = closure->alpha_x;
|
|
|
|
sd->flag |= bsdf_microfacet_ggx_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_specular_reflection(sd->Ng, sd->wi, 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_specular_reflection(sd->Ng, sd->wi, 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 FresnelPrincipledV1 *fresnel = (ccl_private FresnelPrincipledV1 *)
|
|
closure_alloc_extra(sd, sizeof(FresnelPrincipledV1));
|
|
if (!fresnel) {
|
|
return;
|
|
}
|
|
|
|
bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N);
|
|
bsdf->alpha_x = closure->alpha_x;
|
|
bsdf->alpha_y = bsdf->alpha_x;
|
|
bsdf->ior = closure->ior;
|
|
bsdf->T = zero_float3();
|
|
|
|
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
|
|
|
|
fresnel->color = rgb_to_spectrum(closure->color);
|
|
fresnel->cspec0 = rgb_to_spectrum(closure->cspec0);
|
|
bsdf_microfacet_setup_fresnel_principledv1(bsdf, sd, fresnel);
|
|
}
|
|
|
|
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 FresnelPrincipledV1 *fresnel = (ccl_private FresnelPrincipledV1 *)
|
|
closure_alloc_extra(sd, sizeof(FresnelPrincipledV1));
|
|
if (!fresnel) {
|
|
return;
|
|
}
|
|
|
|
bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N);
|
|
bsdf->alpha_x = closure->alpha_x;
|
|
bsdf->alpha_y = closure->alpha_y;
|
|
bsdf->ior = closure->ior;
|
|
bsdf->T = closure->T;
|
|
|
|
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
|
|
|
|
fresnel->color = rgb_to_spectrum(closure->color);
|
|
fresnel->cspec0 = rgb_to_spectrum(closure->cspec0);
|
|
bsdf_microfacet_setup_fresnel_principledv1(bsdf, sd, fresnel);
|
|
}
|
|
|
|
/* 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 FresnelConstant *fresnel = (ccl_private FresnelConstant *)closure_alloc_extra(
|
|
sd, sizeof(FresnelConstant));
|
|
if (!fresnel) {
|
|
return;
|
|
}
|
|
|
|
bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N);
|
|
bsdf->alpha_x = closure->alpha_x;
|
|
bsdf->alpha_y = bsdf->alpha_x;
|
|
bsdf->ior = 1.0f;
|
|
|
|
bsdf->fresnel = fresnel;
|
|
fresnel->color = rgb_to_spectrum(closure->color);
|
|
|
|
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 FresnelConstant *fresnel = (ccl_private FresnelConstant *)closure_alloc_extra(
|
|
sd, sizeof(FresnelConstant));
|
|
if (!fresnel) {
|
|
return;
|
|
}
|
|
|
|
bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N);
|
|
bsdf->alpha_x = closure->alpha_x;
|
|
bsdf->alpha_y = bsdf->alpha_x;
|
|
bsdf->ior = closure->ior;
|
|
|
|
bsdf->fresnel = fresnel;
|
|
fresnel->color = rgb_to_spectrum(closure->color);
|
|
|
|
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 FresnelConstant *fresnel = (ccl_private FresnelConstant *)closure_alloc_extra(
|
|
sd, sizeof(FresnelConstant));
|
|
if (!fresnel) {
|
|
return;
|
|
}
|
|
|
|
bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N);
|
|
bsdf->alpha_x = closure->alpha_x;
|
|
bsdf->alpha_y = closure->alpha_y;
|
|
bsdf->ior = 1.0f;
|
|
|
|
bsdf->fresnel = fresnel;
|
|
fresnel->color = rgb_to_spectrum(closure->color);
|
|
|
|
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 FresnelPrincipledV1 *fresnel = (ccl_private FresnelPrincipledV1 *)
|
|
closure_alloc_extra(sd, sizeof(FresnelPrincipledV1));
|
|
if (!fresnel) {
|
|
return;
|
|
}
|
|
|
|
bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N);
|
|
bsdf->alpha_x = closure->alpha_x;
|
|
bsdf->alpha_y = bsdf->alpha_x;
|
|
bsdf->ior = closure->ior;
|
|
|
|
bsdf->fresnel = fresnel;
|
|
fresnel->color = rgb_to_spectrum(closure->color);
|
|
fresnel->cspec0 = rgb_to_spectrum(closure->cspec0);
|
|
|
|
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 FresnelPrincipledV1 *fresnel = (ccl_private FresnelPrincipledV1 *)
|
|
closure_alloc_extra(sd, sizeof(FresnelPrincipledV1));
|
|
if (!fresnel) {
|
|
return;
|
|
}
|
|
|
|
bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N);
|
|
bsdf->alpha_x = closure->alpha_x;
|
|
bsdf->alpha_y = bsdf->alpha_x;
|
|
bsdf->ior = closure->ior;
|
|
|
|
bsdf->fresnel = fresnel;
|
|
fresnel->color = rgb_to_spectrum(closure->color);
|
|
fresnel->cspec0 = rgb_to_spectrum(closure->cspec0);
|
|
|
|
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 FresnelPrincipledV1 *fresnel = (ccl_private FresnelPrincipledV1 *)
|
|
closure_alloc_extra(sd, sizeof(FresnelPrincipledV1));
|
|
if (!fresnel) {
|
|
return;
|
|
}
|
|
|
|
bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N);
|
|
bsdf->alpha_x = closure->alpha_x;
|
|
bsdf->alpha_y = closure->alpha_y;
|
|
bsdf->ior = closure->ior;
|
|
|
|
bsdf->fresnel = fresnel;
|
|
fresnel->color = rgb_to_spectrum(closure->color);
|
|
fresnel->cspec0 = rgb_to_spectrum(closure->cspec0);
|
|
|
|
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_specular_reflection(sd->Ng, sd->wi, closure->N);
|
|
bsdf->alpha_x = bsdf->alpha_y = closure->alpha_x;
|
|
|
|
sd->flag |= bsdf_microfacet_beckmann_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_specular_reflection(sd->Ng, sd->wi, 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_specular_reflection(sd->Ng, sd->wi, 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_specular_reflection(sd->Ng, sd->wi, 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_specular_reflection(sd->Ng, sd->wi, 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_specular_reflection(sd->Ng, sd->wi, 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_specular_reflection(sd->Ng, sd->wi, 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 = 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 = 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)
|
|
{
|
|
weight *= 0.25f * closure->clearcoat;
|
|
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
|
|
sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight));
|
|
if (!bsdf) {
|
|
return;
|
|
}
|
|
|
|
bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N);
|
|
bsdf->alpha_x = closure->clearcoat_roughness;
|
|
bsdf->alpha_y = closure->clearcoat_roughness;
|
|
bsdf->ior = 1.5f;
|
|
|
|
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 = 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_specular_reflection(sd->Ng, sd->wi, 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)
|
|
{
|
|
ClosureType type;
|
|
if (closure->method == make_string("burley", 186330084368958868ull)) {
|
|
type = CLOSURE_BSSRDF_BURLEY_ID;
|
|
}
|
|
else if (closure->method == make_string("random_walk_fixed_radius", 5695810351010063150ull)) {
|
|
type = CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID;
|
|
}
|
|
else if (closure->method == make_string("random_walk", 11360609267673527222ull)) {
|
|
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 = 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_specular_reflection(sd->Ng, sd->wi, 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_specular_reflection(sd->Ng, sd->wi, 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_specular_reflection(sd->Ng, sd->wi, 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
|