The logic here is not ideal but was unintentionally changed in refactoring for path guiding, now restore it back to 3.3 behavior again.
686 lines
24 KiB
C
686 lines
24 KiB
C
/* SPDX-License-Identifier: Apache-2.0
|
|
* Copyright 2011-2022 Blender Foundation */
|
|
|
|
#pragma once
|
|
|
|
// clang-format off
|
|
#include "kernel/closure/bsdf_ashikhmin_velvet.h"
|
|
#include "kernel/closure/bsdf_diffuse.h"
|
|
#include "kernel/closure/bsdf_oren_nayar.h"
|
|
#include "kernel/closure/bsdf_phong_ramp.h"
|
|
#include "kernel/closure/bsdf_diffuse_ramp.h"
|
|
#include "kernel/closure/bsdf_microfacet.h"
|
|
#include "kernel/closure/bsdf_microfacet_multi.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/bssrdf.h"
|
|
#include "kernel/closure/volume.h"
|
|
// clang-format on
|
|
|
|
CCL_NAMESPACE_BEGIN
|
|
|
|
/* Returns the square of the roughness of the closure if it has roughness,
|
|
* 0 for singular closures and 1 otherwise. */
|
|
ccl_device_inline float bsdf_get_specular_roughness_squared(ccl_private const ShaderClosure *sc)
|
|
{
|
|
if (CLOSURE_IS_BSDF_SINGULAR(sc->type)) {
|
|
return 0.0f;
|
|
}
|
|
|
|
if (CLOSURE_IS_BSDF_MICROFACET(sc->type)) {
|
|
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)sc;
|
|
return bsdf->alpha_x * bsdf->alpha_y;
|
|
}
|
|
|
|
return 1.0f;
|
|
}
|
|
|
|
ccl_device_inline float bsdf_get_roughness_squared(ccl_private const ShaderClosure *sc)
|
|
{
|
|
/* This version includes diffuse, mainly for baking Principled BSDF
|
|
* where specular and metallic zero otherwise does not bake the
|
|
* specified roughness parameter. */
|
|
if (sc->type == CLOSURE_BSDF_OREN_NAYAR_ID) {
|
|
ccl_private OrenNayarBsdf *bsdf = (ccl_private OrenNayarBsdf *)sc;
|
|
return sqr(sqr(bsdf->roughness));
|
|
}
|
|
|
|
if (sc->type == CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID) {
|
|
ccl_private PrincipledDiffuseBsdf *bsdf = (ccl_private PrincipledDiffuseBsdf *)sc;
|
|
return sqr(sqr(bsdf->roughness));
|
|
}
|
|
|
|
if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
|
|
return 0.0f;
|
|
}
|
|
|
|
return bsdf_get_specular_roughness_squared(sc);
|
|
}
|
|
|
|
/* An additional term to smooth illumination on grazing angles when using bump mapping.
|
|
* Based on "Taming the Shadow Terminator" by Matt Jen-Yuan Chiang,
|
|
* Yining Karl Li and Brent Burley. */
|
|
ccl_device_inline float bump_shadowing_term(float3 Ng, float3 N, float3 I)
|
|
{
|
|
const float cosNI = dot(N, I);
|
|
if (cosNI < 0.0f) {
|
|
Ng = -Ng;
|
|
}
|
|
float g = safe_divide(dot(Ng, I), cosNI * dot(Ng, N));
|
|
|
|
/* If the incoming light is on the unshadowed side, return full brightness. */
|
|
if (g >= 1.0f) {
|
|
return 1.0f;
|
|
}
|
|
|
|
/* If the incoming light points away from the surface, return black. */
|
|
if (g < 0.0f) {
|
|
return 0.0f;
|
|
}
|
|
|
|
/* Return smoothed value to avoid discontinuity at perpendicular angle. */
|
|
float g2 = sqr(g);
|
|
return -g2 * g + g2 + g;
|
|
}
|
|
|
|
ccl_device_inline float shift_cos_in(float cos_in, const float frequency_multiplier)
|
|
{
|
|
/* Shadow terminator workaround, taken from Appleseed.
|
|
* SPDX-License-Identifier: MIT
|
|
* Copyright (c) 2019 Francois Beaune, The appleseedhq Organization */
|
|
cos_in = min(cos_in, 1.0f);
|
|
|
|
const float angle = fast_acosf(cos_in);
|
|
const float val = max(cosf(angle * frequency_multiplier), 0.0f) / cos_in;
|
|
return val;
|
|
}
|
|
|
|
ccl_device_inline bool bsdf_is_transmission(ccl_private const ShaderClosure *sc,
|
|
const float3 omega_in)
|
|
{
|
|
return dot(sc->N, omega_in) < 0.0f;
|
|
}
|
|
|
|
ccl_device_inline int bsdf_sample(KernelGlobals kg,
|
|
ccl_private ShaderData *sd,
|
|
ccl_private const ShaderClosure *sc,
|
|
float randu,
|
|
float randv,
|
|
ccl_private Spectrum *eval,
|
|
ccl_private float3 *omega_in,
|
|
ccl_private float *pdf,
|
|
ccl_private float2 *sampled_roughness,
|
|
ccl_private float *eta)
|
|
{
|
|
/* For curves use the smooth normal, particularly for ribbons the geometric
|
|
* normal gives too much darkening otherwise. */
|
|
int label;
|
|
const float3 Ng = (sd->type & PRIMITIVE_CURVE) ? sc->N : sd->Ng;
|
|
|
|
switch (sc->type) {
|
|
case CLOSURE_BSDF_DIFFUSE_ID:
|
|
label = bsdf_diffuse_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
|
*sampled_roughness = one_float2();
|
|
*eta = 1.0f;
|
|
break;
|
|
#if defined(__SVM__) || defined(__OSL__)
|
|
case CLOSURE_BSDF_OREN_NAYAR_ID:
|
|
label = bsdf_oren_nayar_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
|
*sampled_roughness = one_float2();
|
|
*eta = 1.0f;
|
|
break;
|
|
# ifdef __OSL__
|
|
case CLOSURE_BSDF_PHONG_RAMP_ID:
|
|
label = bsdf_phong_ramp_sample(
|
|
sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, sampled_roughness);
|
|
*eta = 1.0f;
|
|
break;
|
|
case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
|
|
label = bsdf_diffuse_ramp_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
|
*sampled_roughness = one_float2();
|
|
*eta = 1.0f;
|
|
break;
|
|
# endif
|
|
case CLOSURE_BSDF_TRANSLUCENT_ID:
|
|
label = bsdf_translucent_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
|
*sampled_roughness = one_float2();
|
|
*eta = 1.0f;
|
|
break;
|
|
case CLOSURE_BSDF_REFLECTION_ID:
|
|
label = bsdf_reflection_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, eta);
|
|
*sampled_roughness = zero_float2();
|
|
break;
|
|
case CLOSURE_BSDF_REFRACTION_ID:
|
|
label = bsdf_refraction_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, eta);
|
|
*sampled_roughness = zero_float2();
|
|
break;
|
|
case CLOSURE_BSDF_TRANSPARENT_ID:
|
|
label = bsdf_transparent_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
|
*sampled_roughness = zero_float2();
|
|
*eta = 1.0f;
|
|
break;
|
|
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
|
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
|
|
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
|
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
|
label = bsdf_microfacet_ggx_sample(
|
|
kg, sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, sampled_roughness, eta);
|
|
break;
|
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
|
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
|
|
label = bsdf_microfacet_multi_ggx_sample(kg,
|
|
sc,
|
|
Ng,
|
|
sd->I,
|
|
randu,
|
|
randv,
|
|
eval,
|
|
omega_in,
|
|
pdf,
|
|
&sd->lcg_state,
|
|
sampled_roughness,
|
|
eta);
|
|
break;
|
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
|
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
|
|
label = bsdf_microfacet_multi_ggx_glass_sample(kg,
|
|
sc,
|
|
Ng,
|
|
sd->I,
|
|
randu,
|
|
randv,
|
|
eval,
|
|
omega_in,
|
|
pdf,
|
|
&sd->lcg_state,
|
|
sampled_roughness,
|
|
eta);
|
|
break;
|
|
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
|
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
|
|
label = bsdf_microfacet_beckmann_sample(
|
|
kg, sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, sampled_roughness, eta);
|
|
break;
|
|
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
|
|
label = bsdf_ashikhmin_shirley_sample(
|
|
sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, sampled_roughness);
|
|
*eta = 1.0f;
|
|
break;
|
|
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
|
|
label = bsdf_ashikhmin_velvet_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
|
*sampled_roughness = one_float2();
|
|
*eta = 1.0f;
|
|
break;
|
|
case CLOSURE_BSDF_DIFFUSE_TOON_ID:
|
|
label = bsdf_diffuse_toon_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
|
*sampled_roughness = one_float2();
|
|
*eta = 1.0f;
|
|
break;
|
|
case CLOSURE_BSDF_GLOSSY_TOON_ID:
|
|
label = bsdf_glossy_toon_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
|
// double check if this is valid
|
|
*sampled_roughness = one_float2();
|
|
*eta = 1.0f;
|
|
break;
|
|
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
|
|
label = bsdf_hair_reflection_sample(
|
|
sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, sampled_roughness);
|
|
*eta = 1.0f;
|
|
break;
|
|
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
|
|
label = bsdf_hair_transmission_sample(
|
|
sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, sampled_roughness);
|
|
*eta = 1.0f;
|
|
break;
|
|
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
|
|
label = bsdf_principled_hair_sample(
|
|
kg, sc, sd, randu, randv, eval, omega_in, pdf, sampled_roughness, eta);
|
|
break;
|
|
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
|
|
label = bsdf_principled_diffuse_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
|
*sampled_roughness = one_float2();
|
|
*eta = 1.0f;
|
|
break;
|
|
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
|
|
label = bsdf_principled_sheen_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
|
*sampled_roughness = one_float2();
|
|
*eta = 1.0f;
|
|
break;
|
|
#endif
|
|
default:
|
|
label = LABEL_NONE;
|
|
break;
|
|
}
|
|
|
|
/* Test if BSDF sample should be treated as transparent for background. */
|
|
if (label & LABEL_TRANSMIT) {
|
|
float threshold_squared = kernel_data.background.transparent_roughness_squared_threshold;
|
|
|
|
if (threshold_squared >= 0.0f && !(label & LABEL_DIFFUSE)) {
|
|
if (bsdf_get_specular_roughness_squared(sc) <= threshold_squared) {
|
|
label |= LABEL_TRANSMIT_TRANSPARENT;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
/* Shadow terminator offset. */
|
|
const float frequency_multiplier =
|
|
kernel_data_fetch(objects, sd->object).shadow_terminator_shading_offset;
|
|
if (frequency_multiplier > 1.0f) {
|
|
const float cosNI = dot(*omega_in, sc->N);
|
|
*eval *= shift_cos_in(cosNI, frequency_multiplier);
|
|
}
|
|
if (label & LABEL_DIFFUSE) {
|
|
if (!isequal(sc->N, sd->N)) {
|
|
*eval *= bump_shadowing_term(sd->N, sc->N, *omega_in);
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef WITH_CYCLES_DEBUG
|
|
kernel_assert(*pdf >= 0.0f);
|
|
kernel_assert(eval->x >= 0.0f && eval->y >= 0.0f && eval->z >= 0.0f);
|
|
#endif
|
|
|
|
return label;
|
|
}
|
|
|
|
ccl_device_inline void bsdf_roughness_eta(const KernelGlobals kg,
|
|
ccl_private const ShaderClosure *sc,
|
|
ccl_private float2 *roughness,
|
|
ccl_private float *eta)
|
|
{
|
|
#ifdef __SVM__
|
|
bool refractive = false;
|
|
float alpha = 1.0f;
|
|
#endif
|
|
switch (sc->type) {
|
|
case CLOSURE_BSDF_DIFFUSE_ID:
|
|
*roughness = one_float2();
|
|
*eta = 1.0f;
|
|
break;
|
|
#ifdef __SVM__
|
|
case CLOSURE_BSDF_OREN_NAYAR_ID:
|
|
*roughness = one_float2();
|
|
*eta = 1.0f;
|
|
break;
|
|
# ifdef __OSL__
|
|
case CLOSURE_BSDF_PHONG_RAMP_ID:
|
|
alpha = phong_ramp_exponent_to_roughness(((ccl_private const PhongRampBsdf *)sc)->exponent);
|
|
*roughness = make_float2(alpha, alpha);
|
|
*eta = 1.0f;
|
|
break;
|
|
case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
|
|
*roughness = one_float2();
|
|
*eta = 1.0f;
|
|
break;
|
|
# endif
|
|
case CLOSURE_BSDF_TRANSLUCENT_ID:
|
|
*roughness = one_float2();
|
|
*eta = 1.0f;
|
|
break;
|
|
case CLOSURE_BSDF_REFLECTION_ID: {
|
|
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
|
*roughness = zero_float2();
|
|
*eta = bsdf->ior;
|
|
break;
|
|
}
|
|
case CLOSURE_BSDF_REFRACTION_ID: {
|
|
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
|
*roughness = zero_float2();
|
|
// do we need to inverse eta??
|
|
*eta = bsdf->ior;
|
|
break;
|
|
}
|
|
case CLOSURE_BSDF_TRANSPARENT_ID:
|
|
*roughness = zero_float2();
|
|
*eta = 1.0f;
|
|
break;
|
|
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
|
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
|
|
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
|
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: {
|
|
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
|
*roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y);
|
|
refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
|
|
*eta = refractive ? 1.0f / bsdf->ior : bsdf->ior;
|
|
break;
|
|
}
|
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
|
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID: {
|
|
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
|
*roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y);
|
|
*eta = bsdf->ior;
|
|
break;
|
|
}
|
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
|
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID: {
|
|
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
|
*roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y);
|
|
*eta = bsdf->ior;
|
|
break;
|
|
}
|
|
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
|
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: {
|
|
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
|
*roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y);
|
|
refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
|
|
*eta = refractive ? 1.0f / bsdf->ior : bsdf->ior;
|
|
} break;
|
|
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: {
|
|
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
|
*roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y);
|
|
*eta = 1.0f;
|
|
break;
|
|
}
|
|
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
|
|
*roughness = one_float2();
|
|
*eta = 1.0f;
|
|
break;
|
|
case CLOSURE_BSDF_DIFFUSE_TOON_ID:
|
|
*roughness = one_float2();
|
|
*eta = 1.0f;
|
|
break;
|
|
case CLOSURE_BSDF_GLOSSY_TOON_ID:
|
|
// double check if this is valid
|
|
*roughness = one_float2();
|
|
*eta = 1.0f;
|
|
break;
|
|
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
|
|
*roughness = make_float2(((ccl_private HairBsdf *)sc)->roughness1,
|
|
((ccl_private HairBsdf *)sc)->roughness2);
|
|
*eta = 1.0f;
|
|
break;
|
|
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
|
|
*roughness = make_float2(((ccl_private HairBsdf *)sc)->roughness1,
|
|
((ccl_private HairBsdf *)sc)->roughness2);
|
|
*eta = 1.0f;
|
|
break;
|
|
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
|
|
alpha = ((ccl_private PrincipledHairBSDF *)sc)->m0_roughness;
|
|
*roughness = make_float2(alpha, alpha);
|
|
*eta = ((ccl_private PrincipledHairBSDF *)sc)->eta;
|
|
break;
|
|
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
|
|
*roughness = one_float2();
|
|
*eta = 1.0f;
|
|
break;
|
|
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
|
|
*roughness = one_float2();
|
|
*eta = 1.0f;
|
|
break;
|
|
#endif
|
|
default:
|
|
*roughness = one_float2();
|
|
*eta = 1.0f;
|
|
break;
|
|
}
|
|
}
|
|
|
|
ccl_device_inline int bsdf_label(const KernelGlobals kg,
|
|
ccl_private const ShaderClosure *sc,
|
|
const float3 omega_in)
|
|
{
|
|
/* For curves use the smooth normal, particularly for ribbons the geometric
|
|
* normal gives too much darkening otherwise. */
|
|
int label;
|
|
switch (sc->type) {
|
|
case CLOSURE_BSDF_DIFFUSE_ID:
|
|
case CLOSURE_BSSRDF_BURLEY_ID:
|
|
case CLOSURE_BSSRDF_RANDOM_WALK_ID:
|
|
case CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID:
|
|
label = LABEL_REFLECT | LABEL_DIFFUSE;
|
|
break;
|
|
#ifdef __SVM__
|
|
case CLOSURE_BSDF_OREN_NAYAR_ID:
|
|
label = LABEL_REFLECT | LABEL_DIFFUSE;
|
|
break;
|
|
# ifdef __OSL__
|
|
case CLOSURE_BSDF_PHONG_RAMP_ID:
|
|
label = LABEL_REFLECT | LABEL_GLOSSY;
|
|
break;
|
|
case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
|
|
label = LABEL_REFLECT | LABEL_DIFFUSE;
|
|
break;
|
|
# endif
|
|
case CLOSURE_BSDF_TRANSLUCENT_ID:
|
|
label = LABEL_TRANSMIT | LABEL_DIFFUSE;
|
|
break;
|
|
case CLOSURE_BSDF_REFLECTION_ID:
|
|
label = LABEL_REFLECT | LABEL_SINGULAR;
|
|
break;
|
|
case CLOSURE_BSDF_REFRACTION_ID:
|
|
label = LABEL_TRANSMIT | LABEL_SINGULAR;
|
|
break;
|
|
case CLOSURE_BSDF_TRANSPARENT_ID:
|
|
label = LABEL_TRANSMIT | LABEL_TRANSPARENT;
|
|
break;
|
|
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
|
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
|
|
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
|
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
|
|
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: {
|
|
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
|
label = (bsdf->alpha_x * bsdf->alpha_y <= 1e-7f) ? LABEL_REFLECT | LABEL_SINGULAR :
|
|
LABEL_REFLECT | LABEL_GLOSSY;
|
|
break;
|
|
}
|
|
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
|
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: {
|
|
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
|
label = (bsdf->alpha_x * bsdf->alpha_y <= 1e-7f) ? LABEL_TRANSMIT | LABEL_SINGULAR :
|
|
LABEL_TRANSMIT | LABEL_GLOSSY;
|
|
break;
|
|
}
|
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
|
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
|
|
label = (bsdf_is_transmission(sc, omega_in)) ? LABEL_TRANSMIT | LABEL_GLOSSY :
|
|
LABEL_REFLECT | LABEL_GLOSSY;
|
|
break;
|
|
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
|
|
label = LABEL_REFLECT | LABEL_GLOSSY;
|
|
break;
|
|
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
|
|
label = LABEL_REFLECT | LABEL_DIFFUSE;
|
|
break;
|
|
case CLOSURE_BSDF_DIFFUSE_TOON_ID:
|
|
label = LABEL_REFLECT | LABEL_DIFFUSE;
|
|
break;
|
|
case CLOSURE_BSDF_GLOSSY_TOON_ID:
|
|
label = LABEL_REFLECT | LABEL_GLOSSY;
|
|
break;
|
|
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
|
|
label = LABEL_REFLECT | LABEL_GLOSSY;
|
|
break;
|
|
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
|
|
label = LABEL_TRANSMIT | LABEL_GLOSSY;
|
|
break;
|
|
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
|
|
if (bsdf_is_transmission(sc, omega_in))
|
|
label = LABEL_TRANSMIT | LABEL_GLOSSY;
|
|
else
|
|
label = LABEL_REFLECT | LABEL_GLOSSY;
|
|
break;
|
|
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
|
|
label = LABEL_REFLECT | LABEL_DIFFUSE;
|
|
break;
|
|
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
|
|
label = LABEL_REFLECT | LABEL_DIFFUSE;
|
|
break;
|
|
#endif
|
|
default:
|
|
label = LABEL_NONE;
|
|
break;
|
|
}
|
|
|
|
/* Test if BSDF sample should be treated as transparent for background. */
|
|
if (label & LABEL_TRANSMIT) {
|
|
float threshold_squared = kernel_data.background.transparent_roughness_squared_threshold;
|
|
|
|
if (threshold_squared >= 0.0f) {
|
|
if (bsdf_get_specular_roughness_squared(sc) <= threshold_squared) {
|
|
label |= LABEL_TRANSMIT_TRANSPARENT;
|
|
}
|
|
}
|
|
}
|
|
return label;
|
|
}
|
|
|
|
#ifndef __KERNEL_CUDA__
|
|
ccl_device
|
|
#else
|
|
ccl_device_inline
|
|
#endif
|
|
Spectrum
|
|
bsdf_eval(KernelGlobals kg,
|
|
ccl_private ShaderData *sd,
|
|
ccl_private const ShaderClosure *sc,
|
|
const float3 omega_in,
|
|
ccl_private float *pdf)
|
|
{
|
|
Spectrum eval = zero_spectrum();
|
|
|
|
switch (sc->type) {
|
|
case CLOSURE_BSDF_DIFFUSE_ID:
|
|
eval = bsdf_diffuse_eval(sc, sd->I, omega_in, pdf);
|
|
break;
|
|
#if defined(__SVM__) || defined(__OSL__)
|
|
case CLOSURE_BSDF_OREN_NAYAR_ID:
|
|
eval = bsdf_oren_nayar_eval(sc, sd->I, omega_in, pdf);
|
|
break;
|
|
# ifdef __OSL__
|
|
case CLOSURE_BSDF_PHONG_RAMP_ID:
|
|
eval = bsdf_phong_ramp_eval(sc, sd->I, omega_in, pdf);
|
|
break;
|
|
case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
|
|
eval = bsdf_diffuse_ramp_eval(sc, sd->I, omega_in, pdf);
|
|
break;
|
|
# endif
|
|
case CLOSURE_BSDF_TRANSLUCENT_ID:
|
|
eval = bsdf_translucent_eval(sc, sd->I, omega_in, pdf);
|
|
break;
|
|
case CLOSURE_BSDF_REFLECTION_ID:
|
|
eval = bsdf_reflection_eval(sc, sd->I, omega_in, pdf);
|
|
break;
|
|
case CLOSURE_BSDF_REFRACTION_ID:
|
|
eval = bsdf_refraction_eval(sc, sd->I, omega_in, pdf);
|
|
break;
|
|
case CLOSURE_BSDF_TRANSPARENT_ID:
|
|
eval = bsdf_transparent_eval(sc, sd->I, omega_in, pdf);
|
|
break;
|
|
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
|
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
|
|
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
|
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
|
eval = bsdf_microfacet_ggx_eval(sc, sd->N, sd->I, omega_in, pdf);
|
|
break;
|
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
|
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
|
|
eval = bsdf_microfacet_multi_ggx_eval(sc, sd->N, sd->I, omega_in, pdf, &sd->lcg_state);
|
|
break;
|
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
|
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
|
|
eval = bsdf_microfacet_multi_ggx_glass_eval(sc, sd->I, omega_in, pdf, &sd->lcg_state);
|
|
break;
|
|
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
|
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
|
|
eval = bsdf_microfacet_beckmann_eval(sc, sd->N, sd->I, omega_in, pdf);
|
|
break;
|
|
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
|
|
eval = bsdf_ashikhmin_shirley_eval(sc, sd->N, sd->I, omega_in, pdf);
|
|
break;
|
|
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
|
|
eval = bsdf_ashikhmin_velvet_eval(sc, sd->I, omega_in, pdf);
|
|
break;
|
|
case CLOSURE_BSDF_DIFFUSE_TOON_ID:
|
|
eval = bsdf_diffuse_toon_eval(sc, sd->I, omega_in, pdf);
|
|
break;
|
|
case CLOSURE_BSDF_GLOSSY_TOON_ID:
|
|
eval = bsdf_glossy_toon_eval(sc, sd->I, omega_in, pdf);
|
|
break;
|
|
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
|
|
eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf);
|
|
break;
|
|
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
|
|
eval = bsdf_hair_reflection_eval(sc, sd->I, omega_in, pdf);
|
|
break;
|
|
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
|
|
eval = bsdf_hair_transmission_eval(sc, sd->I, omega_in, pdf);
|
|
break;
|
|
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
|
|
eval = bsdf_principled_diffuse_eval(sc, sd->I, omega_in, pdf);
|
|
break;
|
|
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
|
|
eval = bsdf_principled_sheen_eval(sc, sd->I, omega_in, pdf);
|
|
break;
|
|
#endif
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
|
|
if (!isequal(sc->N, sd->N)) {
|
|
eval *= bump_shadowing_term(sd->N, sc->N, omega_in);
|
|
}
|
|
}
|
|
|
|
/* Shadow terminator offset. */
|
|
const float frequency_multiplier =
|
|
kernel_data_fetch(objects, sd->object).shadow_terminator_shading_offset;
|
|
if (frequency_multiplier > 1.0f) {
|
|
const float cosNI = dot(omega_in, sc->N);
|
|
if (cosNI >= 0.0f) {
|
|
eval *= shift_cos_in(cosNI, frequency_multiplier);
|
|
}
|
|
}
|
|
|
|
#ifdef WITH_CYCLES_DEBUG
|
|
kernel_assert(*pdf >= 0.0f);
|
|
kernel_assert(eval.x >= 0.0f && eval.y >= 0.0f && eval.z >= 0.0f);
|
|
#endif
|
|
return eval;
|
|
}
|
|
|
|
ccl_device void bsdf_blur(KernelGlobals kg, ccl_private ShaderClosure *sc, float roughness)
|
|
{
|
|
/* TODO: do we want to blur volume closures? */
|
|
#if defined(__SVM__) || defined(__OSL__)
|
|
switch (sc->type) {
|
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
|
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
|
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
|
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
|
|
bsdf_microfacet_multi_ggx_blur(sc, roughness);
|
|
break;
|
|
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
|
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
|
|
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
|
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
|
bsdf_microfacet_ggx_blur(sc, roughness);
|
|
break;
|
|
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
|
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
|
|
bsdf_microfacet_beckmann_blur(sc, roughness);
|
|
break;
|
|
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
|
|
bsdf_ashikhmin_shirley_blur(sc, roughness);
|
|
break;
|
|
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
|
|
bsdf_principled_hair_blur(sc, roughness);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
CCL_NAMESPACE_END
|