83static_assert(
sizeof(ShaderClosure) >=
sizeof(
MicrofacetBsdf),
"MicrofacetBsdf is too large!");
101 float cos_phi_i = 1.0f;
102 float sin_phi_i = 0.0f;
104 if (wi_.
z >= 0.99999f) {
112 const float cos_theta_i = wi_.
z;
114 const float tan_theta_i = sin_theta_i / cos_theta_i;
115 const float cot_theta_i = 1.0f / tan_theta_i;
116 const float erf_a =
fast_erff(cot_theta_i);
117 const float exp_a2 =
expf(-cot_theta_i * cot_theta_i);
118 const float SQRT_PI_INV = 0.56418958354f;
120 const float invlen = 1.0f / sin_theta_i;
121 cos_phi_i = wi_.
x * invlen;
122 sin_phi_i = wi_.
y * invlen;
139 const float K = tan_theta_i * SQRT_PI_INV;
140 const float y_approx = rand.
x * (1.0f + erf_a +
K * (1 - erf_a * erf_a));
141 const float y_exact = rand.
x * (1.0f + erf_a +
K * exp_a2);
142 const float b =
K > 0 ? (0.5f -
sqrtf(
K * (
K - y_approx + 1.0f) + 0.25f)) /
K :
153 const float precision = 1e-6f;
154 const int max_iter = 3;
156 while (
fabsf(current.
y) > precision && iter++ < max_iter) {
164 const float newton_x = current.
x - current.
y / (1.0f - inv_erf * tan_theta_i);
165 current.
x = (newton_x >=
begin.x && newton_x <= end.
x) ? newton_x : 0.5f * (
begin.x + end.
x);
167 current.
y = 1.0f + current.
x +
K *
expf(-
sqr(inv_erf)) - y_exact;
175 slope =
make_float2(cos_phi_i * slope.
x - sin_phi_i * slope.
y,
176 sin_phi_i * slope.
x + cos_phi_i * slope.
y);
198 const float lensq =
sqr(wi_.
x) +
sqr(wi_.
y);
228 const float cos_theta_i,
235 const bool has_transmission =
CLOSURE_IS_GLASS(bsdf->type) || !has_reflection;
246 *r_reflectance =
F * fresnel->reflection_tint;
247 *r_transmittance = (1.0f -
F) * fresnel->transmission_tint;
254 kg, 1.0f, fresnel->thin_film, fresnel->ior,
nullptr, cos_theta_i, r_cos_theta_t);
275 const Spectrum n =
mix((1.0f + sqrt_r) / (1.0f - sqrt_r), (1.0f - r) / (1.0f + r), g);
279 kg, 1.0f, fresnel->thin_film, {n, k}, &g, cos_theta_i, r_cos_theta_t);
282 *r_reflectance =
fresnel_f82(cos_theta_i, fresnel->f0, fresnel->b);
297 kg, 1.0f, fresnel->thin_film, {bsdf->ior, 0.0f},
nullptr, cos_theta_i, r_cos_theta_t);
313 else if (fresnel->exponent < 0.0f) {
319 F =
mix(fresnel->f0, fresnel->f90, s);
323 const float cos_theta_t_sq = 1.0f - (1.0f -
sqr(cos_theta_i)) /
sqr(bsdf->ior);
324 if (cos_theta_t_sq <= 0.0f) {
326 *r_reflectance = fresnel->reflection_tint * (
float)has_reflection;
330 const float cos_theta_t =
sqrtf(cos_theta_t_sq);
332 *r_cos_theta_t = cos_theta_t;
337 const float fresnel_angle = ((bsdf->ior < 1.0f) ? cos_theta_t : cos_theta_i);
338 const float s =
powf(1.0f - fresnel_angle, fresnel->exponent);
339 F =
mix(fresnel->f0, fresnel->f90, s);
341 *r_reflectance =
F * fresnel->reflection_tint;
342 *r_transmittance = (
one_spectrum() -
F) * fresnel->transmission_tint;
350 if (has_transmission &&
fresnel_dielectric(cos_theta_i, bsdf->ior, r_cos_theta_t) == 1.0f) {
355 *r_reflectance *= (
float)has_reflection;
356 *r_transmittance *= (
float)has_transmission;
364 const float mu =
dot(sd->wi, bsdf->N);
365 const float rough =
sqrtf(
sqrtf(bsdf->alpha_x * bsdf->alpha_y));
376 float ior = bsdf->ior;
383 const float z =
sqrtf(
fabsf((ior - 1.0f) / (ior + 1.0f)));
393 const float missing_factor = ((1.0f - E) / E);
394 bsdf->energy_scale = 1.0f + missing_factor;
407 bsdf->weight *= darkening;
408 bsdf->sample_weight *=
average(darkening);
426 const bool eval_reflection,
427 const bool eval_transmission)
429 const float cos_NI =
dot(sd->wi, bsdf->N);
434 reflectance *= (
float)eval_reflection;
435 transmittance *= (
float)eval_transmission;
450 const float rough =
sqrtf(
sqrtf(bsdf->alpha_x * bsdf->alpha_y));
452 if (fresnel->exponent < 0.0f) {
453 const float z =
sqrtf(
fabsf((bsdf->ior - 1.0f) / (bsdf->ior + 1.0f)));
455 kg, rough, cos_NI,
z,
kernel_data.tables.ggx_gen_schlick_ior_s, 16, 16, 16);
458 const float z = 1.0f / (0.2f * fresnel->exponent + 1.0f);
460 kg, rough, cos_NI,
z,
kernel_data.tables.ggx_gen_schlick_s, 16, 16, 16);
462 reflectance =
mix(fresnel->f0, fresnel->f90, s) * fresnel->reflection_tint;
473 const float rough =
sqrtf(
sqrtf(bsdf->alpha_x * bsdf->alpha_y));
475 kg, rough, cos_NI, 0.5f,
kernel_data.tables.ggx_gen_schlick_s, 16, 16, 16);
486 const float rough =
sqrtf(
sqrtf(bsdf->alpha_x * bsdf->alpha_y));
487 const float z =
sqrtf(
fabsf((bsdf->ior - 1.0f) / (bsdf->ior + 1.0f)));
489 kg, rough, cos_NI,
z,
kernel_data.tables.ggx_gen_schlick_ior_s, 16, 16, 16);
494 reflectance *= fresnel->reflection_tint;
498 return reflectance + transmittance;
506template<MicrofacetType m_type>
511 return 0.5f * (
sqrtf(1.0f + sqr_alpha_tan_n) - 1.0f);
515 if (sqr_alpha_tan_n < 0.39f) {
521 return ((0.396f * a - 1.259f) * a + 1.0f) / ((2.181f * a + 3.535f) * a);
524template<MicrofacetType m_type>
530template<MicrofacetType m_type>
533 const float sqr_alpha_tan_n = (
sqr(alpha_x *
V.x) +
sqr(alpha_y *
V.y)) /
sqr(
V.z);
538template<MicrofacetType m_type>
545template<MicrofacetType m_type>
552template<MicrofacetType m_type>
555 const float cos_NH2 =
min(
sqr(cos_NH), 1.0f);
556 const float one_minus_cos_NH2 = 1.0f - cos_NH2;
559 return 1.0f / (
expf(one_minus_cos_NH2 / (cos_NH2 * alpha2)) *
M_PI_F * alpha2 *
sqr(cos_NH2));
562 return alpha2 / (
M_PI_F *
sqr(one_minus_cos_NH2 + alpha2 * cos_NH2));
565template<MicrofacetType m_type>
570 const float cos_NH2 =
sqr(
H.z);
571 const float alpha2 = alpha_x * alpha_y;
586template<MicrofacetType m_type>
597 const bool has_transmission =
CLOSURE_IS_GLASS(bsdf->type) || !has_reflection;
600 const float cos_NI =
dot(
N, wi);
601 const float cos_NO =
dot(
N, wo);
603 const float alpha_x = bsdf->alpha_x;
604 const float alpha_y = bsdf->alpha_y;
606 const bool is_transmission = (cos_NO < 0.0f);
615 (is_transmission && !has_transmission) || (!is_transmission && !has_reflection))
624 float3 H = is_transmission ? -(bsdf->ior * wo + wi) : (wi + wo);
629 const float cos_HI =
dot(
H, wi);
638 const float cos_NH =
dot(
N,
H);
645 if (alpha_x == alpha_y || is_transmission) {
646 const float alpha2 = alpha_x * alpha_y;
666 const float common =
D / cos_NI *
667 (is_transmission ?
sqr(bsdf->ior * inv_len_H) *
fabsf(cos_HI *
dot(
H, wo)) :
670 const float pdf_reflect =
average(reflectance) /
average(reflectance + transmittance);
671 const float lobe_pdf = is_transmission ? 1.0f - pdf_reflect : pdf_reflect;
673 *pdf =
common * lobe_pdf / (1.0f + lambdaI);
674 return (is_transmission ? transmittance : reflectance) *
common / (1.0f + lambdaO + lambdaI);
677template<MicrofacetType m_type>
692 const float cos_NI =
dot(
N, wi);
698 const float m_eta = bsdf->ior;
699 const float m_inv_eta =
safe_divide(1.0f, bsdf->ior);
700 const float alpha_x = bsdf->alpha_x;
701 const float alpha_y = bsdf->alpha_y;
715 if (alpha_x == alpha_y) {
735 const float cos_HI =
dot(
H, wi);
749 const float pdf_reflect =
average(reflectance) /
average(reflectance + transmittance);
750 const bool do_refract = (rand.
z >= pdf_reflect);
753 *wo = do_refract ?
refract_angle(wi,
H, cos_HO, m_inv_eta) : 2.0f * cos_HI *
H - wi;
761 const float cos_NO =
dot(
N, *wo);
762 const float cos_NgO =
dot(Ng, *wo);
763 if ((cos_NgO < 0) != do_refract || (cos_NO < 0) != do_refract) {
768 *eval = transmittance;
769 *pdf = 1.0f - pdf_reflect;
771 m_singular = m_singular || (
fabsf(m_eta - 1.0f) < 1e-4f);
789 if (alpha_x == alpha_y || do_refract) {
790 const float alpha2 = alpha_x * alpha_y;
791 const float cos_NH = local_H.
z;
792 const float cos_NO =
dot(
N, *wo);
799 const float3 local_O = 2.0f * cos_HI * local_H - local_I;
807 const float common =
D / cos_NI *
808 (do_refract ?
fabsf(cos_HI * cos_HO) /
sqr(cos_HO + cos_HI * m_inv_eta) :
811 *pdf *=
common / (1.0f + lambdaI);
812 *eval *=
common / (1.0f + lambdaI + lambdaO);
815 *sampled_roughness =
make_float2(alpha_x, alpha_y);
816 *eta = do_refract ? m_eta : 1.0f;
829 const bool preserve_energy)
832 bsdf->fresnel = fresnel;
835 if (preserve_energy) {
845 const bool preserve_energy)
848 bsdf->fresnel = fresnel;
851 if (preserve_energy) {
853 Spectrum Fss = fresnel->transmission_tint;
854 if (
is_zero(fresnel->transmission_tint)) {
867 const bool preserve_energy)
869 fresnel->f0 =
saturate(fresnel->f0);
871 bsdf->fresnel = fresnel;
874 if (preserve_energy) {
877 if (
is_zero(fresnel->transmission_tint)) {
879 if (fresnel->exponent < 0.0f) {
886 s = 2.0f / ((fresnel->exponent + 3.0f) * fresnel->exponent + 2.0f);
889 Fss = fresnel->reflection_tint *
mix(fresnel->f0, fresnel->f90, s);
894 Fss = fresnel->transmission_tint;
906 const bool preserve_energy)
916 bsdf->fresnel = fresnel;
919 if (preserve_energy) {
963 bsdf->alpha_x =
saturatef(bsdf->alpha_x);
964 bsdf->alpha_y =
saturatef(bsdf->alpha_y);
967 bsdf->energy_scale = 1.0f;
975 bsdf->alpha_x =
saturatef(bsdf->alpha_x);
976 bsdf->alpha_y = bsdf->alpha_x;
979 bsdf->energy_scale = 1.0f;
987 bsdf->alpha_x =
saturatef(bsdf->alpha_x);
988 bsdf->alpha_y = bsdf->alpha_x;
991 bsdf->energy_scale = 1.0f;
1002 bsdf->alpha_y =
fmaxf(roughness, bsdf->alpha_y);
1028 kg, sc, Ng, wi, rand, eval, wo, pdf, sampled_roughness, eta);
1040 bsdf->alpha_x =
saturatef(bsdf->alpha_x);
1041 bsdf->alpha_y =
saturatef(bsdf->alpha_y);
1051 bsdf->alpha_x =
saturatef(bsdf->alpha_x);
1052 bsdf->alpha_y = bsdf->alpha_x;
1062 bsdf->alpha_x =
saturatef(bsdf->alpha_x);
1063 bsdf->alpha_y = bsdf->alpha_x;
1092 kg, sc, Ng, wi, rand, eval, wo, pdf, sampled_roughness, eta);
MINLINE float signf(float f)
MINLINE float safe_sqrtf(float a)
MINLINE float safe_divide(float a, float b)
ccl_device_forceinline float3 microfacet_beckmann_sample_vndf(const float3 wi, const float alpha_x, const float alpha_y, const float2 rand)
ccl_device void bsdf_microfacet_setup_fresnel_f82_tint(KernelGlobals kg, ccl_private MicrofacetBsdf *bsdf, const ccl_private ShaderData *sd, ccl_private FresnelF82Tint *fresnel, const Spectrum f82_tint, const bool preserve_energy)
ccl_device Spectrum bsdf_microfacet_ggx_eval(KernelGlobals kg, const ccl_private ShaderClosure *sc, const float3 wi, const float3 wo, ccl_private float *pdf)
ccl_device_inline float bsdf_lambda_from_sqr_alpha_tan_n(const float sqr_alpha_tan_n)
ccl_device int bsdf_microfacet_sample(KernelGlobals kg, const ccl_private ShaderClosure *sc, const float3 Ng, const float3 wi, const float3 rand, ccl_private Spectrum *eval, ccl_private float3 *wo, ccl_private float *pdf, ccl_private float2 *sampled_roughness, ccl_private float *eta)
ccl_device_forceinline float3 microfacet_ggx_sample_vndf(const float3 wi, const float alpha_x, const float alpha_y, const float2 rand)
ccl_device Spectrum bsdf_microfacet_eval(KernelGlobals kg, const ccl_private ShaderClosure *sc, const float3 wi, const float3 wo, ccl_private float *pdf)
ccl_device Spectrum bsdf_microfacet_estimate_albedo(KernelGlobals kg, const ccl_private ShaderData *sd, const ccl_private MicrofacetBsdf *bsdf, const bool eval_reflection, const bool eval_transmission)
ccl_device int bsdf_microfacet_beckmann_glass_setup(ccl_private MicrofacetBsdf *bsdf)
ccl_device int bsdf_microfacet_beckmann_setup(ccl_private MicrofacetBsdf *bsdf)
ccl_device_forceinline int bsdf_microfacet_eval_flag(const ccl_private MicrofacetBsdf *bsdf)
ccl_device void bsdf_microfacet_setup_fresnel_constant(KernelGlobals kg, ccl_private MicrofacetBsdf *bsdf, const ccl_private ShaderData *sd, const Spectrum color)
ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg, const ccl_private ShaderClosure *sc, const float3 Ng, const float3 wi, const float3 rand, ccl_private Spectrum *eval, ccl_private float3 *wo, ccl_private float *pdf, ccl_private float2 *sampled_roughness, ccl_private float *eta)
ccl_device void bsdf_microfacet_setup_fresnel_generalized_schlick(KernelGlobals kg, ccl_private MicrofacetBsdf *bsdf, const ccl_private ShaderData *sd, ccl_private FresnelGeneralizedSchlick *fresnel, const bool preserve_energy)
ccl_device_inline float bsdf_D(const float alpha2, const float cos_NH)
ccl_device_inline float bsdf_lambda(const float alpha2, const float cos_N)
ccl_device Spectrum bsdf_microfacet_beckmann_eval(KernelGlobals kg, const ccl_private ShaderClosure *sc, const float3 wi, const float3 wo, ccl_private float *pdf)
ccl_device void bsdf_microfacet_setup_fresnel_dielectric(KernelGlobals kg, ccl_private MicrofacetBsdf *bsdf, const ccl_private ShaderData *sd)
ccl_device_inline float bsdf_G(const float alpha2, const float cos_N)
ccl_device void bsdf_microfacet_setup_fresnel_conductor(KernelGlobals kg, ccl_private MicrofacetBsdf *bsdf, const ccl_private ShaderData *sd, ccl_private FresnelConductor *fresnel, const bool preserve_energy)
ccl_device_inline void microfacet_ggx_preserve_energy(KernelGlobals kg, ccl_private MicrofacetBsdf *bsdf, const ccl_private ShaderData *sd, const Spectrum Fss)
ccl_device void bsdf_microfacet_setup_fresnel_dielectric_tint(KernelGlobals kg, ccl_private MicrofacetBsdf *bsdf, const ccl_private ShaderData *sd, ccl_private FresnelDielectricTint *fresnel, const bool preserve_energy)
ccl_device_inline float bsdf_aniso_D(const float alpha_x, const float alpha_y, float3 H)
ccl_device_inline float bsdf_aniso_lambda(const float alpha_x, const float alpha_y, const float3 V)
ccl_device int bsdf_microfacet_beckmann_refraction_setup(ccl_private MicrofacetBsdf *bsdf)
ccl_device int bsdf_microfacet_ggx_glass_setup(ccl_private MicrofacetBsdf *bsdf)
ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg, const ccl_private ShaderClosure *sc, const float3 Ng, const float3 wi, const float3 rand, ccl_private Spectrum *eval, ccl_private float3 *wo, ccl_private float *pdf, ccl_private float2 *sampled_roughness, ccl_private float *eta)
ccl_device int bsdf_microfacet_ggx_setup(ccl_private MicrofacetBsdf *bsdf)
ccl_device_forceinline void microfacet_fresnel(KernelGlobals kg, const ccl_private MicrofacetBsdf *bsdf, const float cos_theta_i, ccl_private float *r_cos_theta_t, ccl_private Spectrum *r_reflectance, ccl_private Spectrum *r_transmittance)
ccl_device void bsdf_microfacet_blur(ccl_private ShaderClosure *sc, const float roughness)
ccl_device int bsdf_microfacet_ggx_refraction_setup(ccl_private MicrofacetBsdf *bsdf)
ccl_device Spectrum fresnel_conductor(const float cosi, const complex< Spectrum > ior)
ccl_device Spectrum fresnel_iridescence(KernelGlobals kg, const float ambient_ior, const FresnelThinFilm thin_film, const complex< SpectrumOrFloat > substrate_ior, ccl_private const Spectrum *F82, const float cos_theta_1, ccl_private float *r_cos_theta_3)
ccl_device_inline Spectrum fresnel_conductor_Fss(const complex< Spectrum > ior)
ccl_device float F0_from_ior(const float ior)
ccl_device_inline Spectrum fresnel_f82_Fss(const Spectrum F0, const Spectrum B)
ccl_device_inline float fresnel_dielectric_Fss(const float eta)
ccl_device_forceinline float fresnel_dielectric(const float cos_theta_i, const float eta, ccl_private float *r_cos_theta_t)
ccl_device_inline float3 refract_angle(const float3 incident, const float3 normal, const float cos_theta_t, const float inv_eta)
ccl_device_inline Spectrum fresnel_f82(const float cosi, const Spectrum F0, const Spectrum B)
ccl_device_inline Spectrum fresnel_f82tint_B(const Spectrum F0, const Spectrum tint)
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
ccl_device_inline float3 disk_to_hemisphere(const float2 p)
ccl_device_inline T to_global(const float2 p, const T X, const T Y)
ccl_device_inline float2 polar_to_cartesian(const float r, const float phi)
#define kernel_assert(cond)
#define CLOSURE_IS_GLASS(type)
#define THINFILM_THICKNESS_CUTOFF
#define ccl_device_forceinline
const ThreadKernelGlobalsCPU * KernelGlobals
#define ccl_device_inline
#define FOREACH_SPECTRUM_CHANNEL(counter)
#define CLOSURE_IS_REFRACTION(type)
#define GET_SPECTRUM_CHANNEL(v, i)
#define BSDF_ROUGHNESS_SQ_THRESH
#define CCL_NAMESPACE_END
VecBase< float, D > normalize(VecOp< float, D >) RET
VecBase< float, 3 > cross(VecOp< float, 3 >, VecOp< float, 3 >) RET
@ CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID
@ CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID
@ CLOSURE_BSDF_MICROFACET_GGX_ID
@ CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID
@ CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID
@ CLOSURE_BSDF_MICROFACET_BECKMANN_ID
@ SD_BSDF_HAS_TRANSMISSION
ccl_device float lookup_table_read_2D(KernelGlobals kg, const float x, float y, const int offset, const int xsize, const int ysize)
ccl_device float lookup_table_read_3D(KernelGlobals kg, const float x, float y, float z, const int offset, const int xsize, const int ysize, const int zsize)
CCL_NAMESPACE_BEGIN ccl_device float lookup_table_read(KernelGlobals kg, float x, const int offset, const int size)
ccl_device_inline float inversesqrtf(const float f)
ccl_device_inline float sin_from_cos(const float c)
ccl_device_inline float inverse_lerp(const float a, const float b, const float x)
ccl_device_inline float fast_erff(const float x)
ccl_device_inline float fast_ierff(const float x)
ccl_device_inline float len_squared(const float2 a)
ccl_device_inline bool is_zero(const float2 a)
ccl_device_inline bool isequal(const float2 a, const float2 b)
ccl_device_inline void make_orthonormals(const float3 N, ccl_private float3 *a, ccl_private float3 *b)
CCL_NAMESPACE_BEGIN ccl_device float2 sample_uniform_disk(const float2 rand)
ccl_device void make_orthonormals_tangent(const float3 N, const float3 T, ccl_private float3 *a, ccl_private float3 *b)
FresnelThinFilm thin_film
Spectrum transmission_tint
FresnelThinFilm thin_film
FresnelThinFilm thin_film
Spectrum transmission_tint
FresnelThinFilm thin_film
ccl_private void * fresnel
CCL_NAMESPACE_BEGIN struct Window V