85static_assert(
sizeof(ShaderClosure) >=
sizeof(
MicrofacetBsdf),
"MicrofacetBsdf is too large!");
103 float cos_phi_i = 1.0f;
104 float sin_phi_i = 0.0f;
106 if (wi_.
z >= 0.99999f) {
114 const float cos_theta_i = wi_.
z;
116 const float tan_theta_i = sin_theta_i / cos_theta_i;
117 const float cot_theta_i = 1.0f / tan_theta_i;
118 const float erf_a =
fast_erff(cot_theta_i);
119 const float exp_a2 =
expf(-cot_theta_i * cot_theta_i);
120 const float SQRT_PI_INV = 0.56418958354f;
122 const float invlen = 1.0f / sin_theta_i;
123 cos_phi_i = wi_.
x * invlen;
124 sin_phi_i = wi_.
y * invlen;
141 const float K = tan_theta_i * SQRT_PI_INV;
142 const float y_approx = rand.
x * (1.0f + erf_a +
K * (1 - erf_a * erf_a));
143 const float y_exact = rand.
x * (1.0f + erf_a +
K * exp_a2);
144 const float b =
K > 0 ? (0.5f -
sqrtf(
K * (
K - y_approx + 1.0f) + 0.25f)) /
K :
155 const float precision = 1e-6f;
156 const int max_iter = 3;
158 while (
fabsf(current.
y) > precision && iter++ < max_iter) {
166 const float newton_x = current.
x - current.
y / (1.0f - inv_erf * tan_theta_i);
167 current.
x = (newton_x >=
begin.x && newton_x <= end.
x) ? newton_x : 0.5f * (
begin.x + end.
x);
169 current.
y = 1.0f + current.
x +
K *
expf(-
sqr(inv_erf)) - y_exact;
177 slope =
make_float2(cos_phi_i * slope.
x - sin_phi_i * slope.
y,
178 sin_phi_i * slope.
x + cos_phi_i * slope.
y);
200 const float lensq =
sqr(wi_.
x) +
sqr(wi_.
y);
230 const float cos_theta_i,
237 const bool has_transmission =
CLOSURE_IS_GLASS(bsdf->type) || !has_reflection;
248 *r_reflectance =
F * fresnel->reflection_tint;
249 *r_transmittance = (1.0f -
F) * fresnel->transmission_tint;
261 const float mu =
saturatef(1.0f - cos_theta_i);
262 const float mu5 =
sqr(
sqr(mu)) * mu;
264 *r_reflectance =
saturate(F_schlick - fresnel->b * cos_theta_i * mu5 * mu);
271 if (fresnel->thin_film.thickness > 0.1f) {
278 fresnel->thin_film.ior,
281 fresnel->thin_film.thickness,
298 else if (fresnel->exponent < 0.0f) {
304 F =
mix(fresnel->f0, fresnel->f90, s);
308 const float cos_theta_t_sq = 1.0f - (1.0f -
sqr(cos_theta_i)) /
sqr(bsdf->ior);
309 if (cos_theta_t_sq <= 0.0f) {
311 *r_reflectance = fresnel->reflection_tint * (float)has_reflection;
315 const float cos_theta_t =
sqrtf(cos_theta_t_sq);
317 *r_cos_theta_t = cos_theta_t;
322 const float fresnel_angle = ((bsdf->ior < 1.0f) ? cos_theta_t : cos_theta_i);
323 const float s =
powf(1.0f - fresnel_angle, fresnel->exponent);
324 F =
mix(fresnel->f0, fresnel->f90, s);
326 *r_reflectance =
F * fresnel->reflection_tint;
327 *r_transmittance = (
one_spectrum() -
F) * fresnel->transmission_tint;
335 if (has_transmission &&
fresnel_dielectric(cos_theta_i, bsdf->ior, r_cos_theta_t) == 1.0f) {
340 *r_reflectance *= (float)has_reflection;
341 *r_transmittance *= (float)has_transmission;
349 const float mu =
dot(sd->wi, bsdf->N);
350 const float rough =
sqrtf(
sqrtf(bsdf->alpha_x * bsdf->alpha_y));
361 float ior = bsdf->ior;
368 const float z =
sqrtf(
fabsf((ior - 1.0f) / (ior + 1.0f)));
378 const float missing_factor = ((1.0f - E) / E);
379 bsdf->energy_scale = 1.0f + missing_factor;
392 bsdf->weight *= darkening;
393 bsdf->sample_weight *=
average(darkening);
411 const bool eval_reflection,
412 const bool eval_transmission)
414 const float cos_NI =
dot(sd->wi, bsdf->N);
419 reflectance *= (float)eval_reflection;
420 transmittance *= (float)eval_transmission;
430 if (fresnel->thin_film.thickness > 0.1f) {
435 const float rough =
sqrtf(
sqrtf(bsdf->alpha_x * bsdf->alpha_y));
437 if (fresnel->exponent < 0.0f) {
438 const float z =
sqrtf(
fabsf((bsdf->ior - 1.0f) / (bsdf->ior + 1.0f)));
440 kg, rough, cos_NI,
z,
kernel_data.tables.ggx_gen_schlick_ior_s, 16, 16, 16);
443 const float z = 1.0f / (0.2f * fresnel->exponent + 1.0f);
445 kg, rough, cos_NI,
z,
kernel_data.tables.ggx_gen_schlick_s, 16, 16, 16);
447 reflectance =
mix(fresnel->f0, fresnel->f90, s) * fresnel->reflection_tint;
452 const float rough =
sqrtf(
sqrtf(bsdf->alpha_x * bsdf->alpha_y));
454 kg, rough, cos_NI, 0.5f,
kernel_data.tables.ggx_gen_schlick_s, 16, 16, 16);
464 const float rough =
sqrtf(
sqrtf(bsdf->alpha_x * bsdf->alpha_y));
465 const float z =
sqrtf(
fabsf((bsdf->ior - 1.0f) / (bsdf->ior + 1.0f)));
467 kg, rough, cos_NI,
z,
kernel_data.tables.ggx_gen_schlick_ior_s, 16, 16, 16);
472 reflectance *= fresnel->reflection_tint;
476 return reflectance + transmittance;
484template<MicrofacetType m_type>
489 return 0.5f * (
sqrtf(1.0f + sqr_alpha_tan_n) - 1.0f);
493 if (sqr_alpha_tan_n < 0.39f) {
499 return ((0.396f * a - 1.259f) * a + 1.0f) / ((2.181f * a + 3.535f) * a);
502template<MicrofacetType m_type>
508template<MicrofacetType m_type>
511 const float sqr_alpha_tan_n = (
sqr(alpha_x *
V.x) +
sqr(alpha_y *
V.y)) /
sqr(
V.z);
516template<MicrofacetType m_type>
523template<MicrofacetType m_type>
530template<MicrofacetType m_type>
533 const float cos_NH2 =
min(
sqr(cos_NH), 1.0f);
534 const float one_minus_cos_NH2 = 1.0f - cos_NH2;
537 return 1.0f / (
expf(one_minus_cos_NH2 / (cos_NH2 * alpha2)) *
M_PI_F * alpha2 *
sqr(cos_NH2));
540 return alpha2 / (
M_PI_F *
sqr(one_minus_cos_NH2 + alpha2 * cos_NH2));
543template<MicrofacetType m_type>
548 const float cos_NH2 =
sqr(
H.z);
549 const float alpha2 = alpha_x * alpha_y;
564template<MicrofacetType m_type>
576 const bool has_transmission =
CLOSURE_IS_GLASS(bsdf->type) || !has_reflection;
579 const float cos_NI =
dot(
N, wi);
580 const float cos_NO =
dot(
N, wo);
581 const float cos_NgO =
dot(Ng, wo);
583 const float alpha_x = bsdf->alpha_x;
584 const float alpha_y = bsdf->alpha_y;
586 const bool is_transmission = (cos_NO < 0.0f);
596 (is_transmission && !has_transmission) || (!is_transmission && !has_reflection))
605 float3 H = is_transmission ? -(bsdf->ior * wo + wi) : (wi + wo);
610 const float cos_HI =
dot(
H, wi);
619 const float cos_NH =
dot(
N,
H);
626 if (alpha_x == alpha_y || is_transmission) {
627 const float alpha2 = alpha_x * alpha_y;
647 const float common =
D / cos_NI *
648 (is_transmission ?
sqr(bsdf->ior * inv_len_H) *
fabsf(cos_HI *
dot(
H, wo)) :
651 const float pdf_reflect =
average(reflectance) /
average(reflectance + transmittance);
652 const float lobe_pdf = is_transmission ? 1.0f - pdf_reflect : pdf_reflect;
654 *pdf =
common * lobe_pdf / (1.0f + lambdaI);
655 return (is_transmission ? transmittance : reflectance) *
common / (1.0f + lambdaO + lambdaI);
658template<MicrofacetType m_type>
673 const float cos_NI =
dot(
N, wi);
679 const float m_eta = bsdf->ior;
680 const float m_inv_eta =
safe_divide(1.0f, bsdf->ior);
681 const float alpha_x = bsdf->alpha_x;
682 const float alpha_y = bsdf->alpha_y;
696 if (alpha_x == alpha_y) {
716 const float cos_HI =
dot(
H, wi);
730 const float pdf_reflect =
average(reflectance) /
average(reflectance + transmittance);
731 const bool do_refract = (rand.
z >= pdf_reflect);
734 *wo = do_refract ?
refract_angle(wi,
H, cos_HO, m_inv_eta) : 2.0f * cos_HI *
H - wi;
735 if ((
dot(Ng, *wo) < 0) != do_refract) {
740 *eval = transmittance;
741 *pdf = 1.0f - pdf_reflect;
743 m_singular = m_singular || (
fabsf(m_eta - 1.0f) < 1e-4f);
761 if (alpha_x == alpha_y || do_refract) {
762 const float alpha2 = alpha_x * alpha_y;
763 const float cos_NH = local_H.
z;
764 const float cos_NO =
dot(
N, *wo);
771 const float3 local_O = 2.0f * cos_HI * local_H - local_I;
779 const float common =
D / cos_NI *
780 (do_refract ?
fabsf(cos_HI * cos_HO) /
sqr(cos_HO + cos_HI * m_inv_eta) :
783 *pdf *=
common / (1.0f + lambdaI);
784 *eval *=
common / (1.0f + lambdaI + lambdaO);
787 *sampled_roughness =
make_float2(alpha_x, alpha_y);
788 *eta = do_refract ? m_eta : 1.0f;
801 const bool preserve_energy)
804 bsdf->fresnel = fresnel;
807 if (preserve_energy) {
817 const bool preserve_energy)
820 bsdf->fresnel = fresnel;
823 if (preserve_energy) {
825 Spectrum Fss = fresnel->transmission_tint;
826 if (
is_zero(fresnel->transmission_tint)) {
839 const bool preserve_energy)
841 fresnel->f0 =
saturate(fresnel->f0);
843 bsdf->fresnel = fresnel;
846 if (preserve_energy) {
849 if (
is_zero(fresnel->transmission_tint)) {
851 if (fresnel->exponent < 0.0f) {
858 s = 2.0f / ((fresnel->exponent + 3.0f) * fresnel->exponent + 2.0f);
861 Fss = fresnel->reflection_tint *
mix(fresnel->f0, fresnel->f90, s);
866 Fss = fresnel->transmission_tint;
878 const bool preserve_energy)
888 bsdf->fresnel = fresnel;
891 if (preserve_energy) {
935 bsdf->alpha_x =
saturatef(bsdf->alpha_x);
936 bsdf->alpha_y =
saturatef(bsdf->alpha_y);
939 bsdf->energy_scale = 1.0f;
947 bsdf->alpha_x =
saturatef(bsdf->alpha_x);
948 bsdf->alpha_y = bsdf->alpha_x;
951 bsdf->energy_scale = 1.0f;
959 bsdf->alpha_x =
saturatef(bsdf->alpha_x);
960 bsdf->alpha_y = bsdf->alpha_x;
963 bsdf->energy_scale = 1.0f;
974 bsdf->alpha_y =
fmaxf(roughness, bsdf->alpha_y);
1001 kg, sc, Ng, wi, rand, eval, wo, pdf, sampled_roughness, eta);
1013 bsdf->alpha_x =
saturatef(bsdf->alpha_x);
1014 bsdf->alpha_y =
saturatef(bsdf->alpha_y);
1024 bsdf->alpha_x =
saturatef(bsdf->alpha_x);
1025 bsdf->alpha_y = bsdf->alpha_x;
1035 bsdf->alpha_x =
saturatef(bsdf->alpha_x);
1036 bsdf->alpha_y = bsdf->alpha_x;
1066 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 Spectrum bsdf_microfacet_ggx_eval(KernelGlobals kg, const ccl_private ShaderClosure *sc, const float3 Ng, const float3 wi, const float3 wo, ccl_private float *pdf)
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_eval(KernelGlobals kg, const ccl_private ShaderClosure *sc, const float3 Ng, 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_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 Spectrum bsdf_microfacet_beckmann_eval(KernelGlobals kg, const ccl_private ShaderClosure *sc, const float3 Ng, const float3 wi, const float3 wo, ccl_private float *pdf)
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 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 float F0_from_ior(const float ior)
ccl_device Spectrum fresnel_conductor(const float cosi, const Spectrum eta, const Spectrum k)
ccl_device Spectrum fresnel_iridescence(KernelGlobals kg, float eta1, float eta2, float eta3, float cos_theta_1, const float thickness, ccl_private float *r_cos_theta_3)
ccl_device_inline Spectrum fresnel_f82_Fss(const Spectrum F0, const Spectrum B)
ccl_device_inline Spectrum fresnel_conductor_Fss(const Spectrum eta, const Spectrum k)
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_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 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 sqr(const float a)
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 float average(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)
Spectrum transmission_tint
FresnelThinFilm thin_film
Spectrum transmission_tint
FresnelThinFilm thin_film
ccl_private void * fresnel
CCL_NAMESPACE_BEGIN struct Window V