129 float sin_gamma, cos_gamma;
131 return atan2f(
b * sin_gamma, cos_gamma);
156 float sin_gamma, cos_gamma;
169 if (
b == 1.0f ||
fabsf(cos_gamma) < 1e-6f) {
174 float tan_gamma = sin_gamma / cos_gamma;
175 float tan_phi =
b * tan_gamma;
184 return e2 == 0 ? 1.0f :
sqrtf(1.0f - e2 *
sqr(
sinf(gamma)));
189 return bsdf->extra->radius > bsdf->extra->pixel_coverage;
202 bsdf->roughness =
clamp(bsdf->roughness, 0.001f, 1.0f);
205 bsdf->tilt = -bsdf->tilt;
224 if (bsdf->aspect_ratio > 1.0f) {
226 bsdf->aspect_ratio = 1.0f / bsdf->aspect_ratio;
247 dot(sd->wi, bsdf->N),
dot(sd->wi, bsdf->extra->Y),
dot(sd->wi, bsdf->extra->Z));
249 bsdf->extra->e2 = 1.0f -
sqr(bsdf->aspect_ratio);
250 bsdf->extra->radius = bsdf->extra->e2 == 0 ?
255 if (
fabsf(bsdf->h) >= bsdf->extra->radius) {
258 sd->num_closure_left += 2;
275 const bool inv_table = (ior < 1.0f);
277 const float z =
sqrtf(
fabsf((ior - 1.0f) / (ior + 1.0f)));
293 const float3 wh = wh_wm.
x * s + wh_wm.
y * t + wh_wm.
z * wm;
300 return (
dot(
v, h) > 0.0f &&
dot(
v, m) > 0.0f);
317 return (1.0f + lambdaI) / (1.0f + lambdaI + lambdaO);
327 if (bsdf->extra->R <= 0.0f) {
332 const float b = bsdf->aspect_ratio;
336 const float roughness = bsdf->roughness;
337 const float roughness2 =
sqr(roughness);
340 float res = roughness * 0.7f;
342 const float gamma_m_range = bsdf->extra->gamma_m_max - bsdf->extra->gamma_m_min;
345 const size_t intervals = 2 * (size_t)
ceilf(gamma_m_range / res * 0.5f);
348 res = gamma_m_range /
float(intervals);
351 float integral = 0.0f;
352 for (
size_t i = 0; i <= intervals; i++) {
353 const float gamma_m = bsdf->extra->gamma_m_min + i * res;
357 const float weight = (i == 0 || i == intervals) ? 0.5f : (i % 2 + 1);
358 const float cos_mi =
dot(wm, wi);
367 integral *= (2.0f / 3.0f * res);
379 const float T_avg =
max(1.0f -
R, 1e-5f);
381 return TRRT_avg / (
one_spectrum() - A * (1.0f - T_avg));
394 if (bsdf->extra->TT <= 0.0f && bsdf->extra->TRT <= 0.0f) {
399 const float b = bsdf->aspect_ratio;
400 const bool is_circular = (
b == 1.0f);
403 const float eta = bsdf->eta;
404 const float inv_eta = 1.0f / eta;
406 const float roughness = bsdf->roughness;
407 const float roughness2 =
sqr(roughness);
408 const float sqrt_roughness =
sqrtf(roughness);
410 float res = roughness * 0.8f;
411 const float gamma_m_range = bsdf->extra->gamma_m_max - bsdf->extra->gamma_m_min;
412 const size_t intervals = 2 * (size_t)
ceilf(gamma_m_range / res * 0.5f);
413 res = gamma_m_range / intervals;
418 for (
size_t i = 0; i <= intervals; i++) {
420 const float gamma_mi = bsdf->extra->gamma_m_min + i * res;
430 const float cos_hi1 =
dot(wi, wh1);
431 if (!(cos_hi1 > 0.0f)) {
435 const float cos_mi1 =
dot(wi, wmi);
442 const float phi_t =
dir_phi(wt);
443 const float gamma_mt = 2.0f *
to_phi(phi_t,
b) - gamma_mi;
447 const float cos_mo1 =
dot(-wt, wmi);
448 const float cos_mi2 =
dot(-wt, wmt);
449 const float G1o =
bsdf_Go(roughness2, cos_mi1, cos_mo1);
454 const float weight = (i == 0 || i == intervals) ? 0.5f : (i % 2 + 1);
458 2.0f *
cosf(gamma_mi - phi_t) :
464 if (bsdf->extra->TT > 0.0f) {
465 if (
dot(wo, wt) >= inv_eta - 1e-5f) {
466 float3 wh2 = -wt + inv_eta * wo;
467 const float rcp_norm_wh2 = 1.0f /
len(wh2);
469 const float cos_mh2 =
dot(wmt, wh2);
470 if (cos_mh2 >= 0.0f) {
471 const float cos_hi2 =
dot(-wt, wh2);
472 const float cos_ho2 =
dot(-wo, wh2);
473 const float cos_mo2 =
dot(-wo, wmt);
479 const Spectrum result = weight *
T1 * scale1 *
T2 * D2 * G1o * G2 * A_t / cos_mo1 *
480 cos_mi1 * cos_hi2 * cos_ho2 *
sqr(rcp_norm_wh2);
483 S_tt += bsdf->extra->TT * result *
arc_length(bsdf->extra->e2, gamma_mt);
490 if (bsdf->extra->TRT > 0.0f) {
495 const float cos_hi2 =
dot(-wt, wh2);
496 if (!(cos_hi2 > 0.0f)) {
502 if (
dot(-wtr, wo) < inv_eta - 1e-5f) {
512 const float phi_tr =
dir_phi(wtr);
517 float3 wh3 = wtr + inv_eta * wo;
518 const float rcp_norm_wh3 = 1.0f /
len(wh3);
520 const float cos_mh3 =
dot(wmtr, wh3);
528 const float cos_hi3 =
dot(wh3, wtr);
529 const float cos_ho3 =
dot(wh3, -wo);
530 const float cos_mi3 =
dot(wmtr, wtr);
541 const float cos_mo2 =
dot(wmt, -wtr);
542 const float G2o =
bsdf_Go(roughness2, cos_mi2, cos_mo2);
545 const Spectrum result = weight *
T1 * scale1 * R2 * scale2 *
T3 * D3 * G1o * G2o * G3 * A_t *
546 A_tr / (cos_mo1 * cos_mo2) * cos_mi1 * cos_mi2 * cos_hi3 * cos_ho3 *
550 S_trt += bsdf->extra->TRT * result *
arc_length(bsdf->extra->e2, gamma_mtr);
562 const float N = M_1_2PI_F;
564 const float simpson_coeff = 2.0f / 3.0f * res;
566 return ((S_tt + S_trt) *
sqr(inv_eta) + S_trrt *
M *
N * M_2_PI_F) * simpson_coeff;
581 *sampled_roughness =
make_float2(roughness, roughness);
586 float sample_lobe = rand.
x;
587 const float sample_h = rand.
y;
595 const float3 wi = bsdf->extra->wi;
598 const float b = bsdf->aspect_ratio;
599 const bool is_circular = (
b == 1.0f);
602 const float h_div_r =
is_nearfield(bsdf) ? bsdf->h / bsdf->extra->radius :
603 (sample_h * 2.0f - 1.0f);
613 const float cos_mi1 =
dot(wmi, wi);
615 if (cos_mi1 < 0.0f ||
dot(wmi_, wi) < 0.0f) {
622 const float roughness2 =
sqr(roughness);
623 const float sqrt_roughness =
sqrtf(roughness);
640 const float inv_eta = 1.0f / bsdf->eta;
642 const float phi_t =
dir_phi(wt);
644 const float gamma_mt = 2.0f *
to_phi(phi_t,
b) - gamma_mi;
652 float3 wh3, wtt, wtrt, wmtr, wtrrt;
656 const float cos_mi2 =
dot(-wt, wmt);
662 2.0f *
cosf(phi_t - gamma_mi) :
667 const float T1 = (1.0f - R1) * scale1 *
bsdf_Go(roughness2, cos_mi1,
dot(wmi, -wt));
668 const float T2 = 1.0f - R2;
674 TT = bsdf->extra->TT *
T1 * A_t *
T2 * scale2 *
bsdf_Go(roughness2, cos_mi2,
dot(wmt, -wtt));
678 const float phi_tr =
dir_phi(wtr);
680 wmtr =
sphg_dir(-bsdf->tilt, gamma_mtr,
b);
682 wh3 =
sample_wh(kg, roughness, wtr, wmtr, sample_h3);
689 const float cos_mi3 =
dot(wmtr, wtr);
690 if (cos_mi3 > 0.0f) {
700 const float T3 = 1.0f - R3;
704 bsdf_Go(roughness2, cos_mi3,
dot(wmtr, -wtrt));
713 const float fac = 1.0f +
714 4.0f * bsdf->roughness *
715 logf(rand_theta + (1.0f - rand_theta) *
expf(-0.5f / bsdf->roughness));
716 const float sin_theta_o = -fac *
sin_theta(wi) +
723 float sin_phi_o, cos_phi_o;
727 wtrrt =
make_float3(sin_phi_o * cos_theta_o, sin_theta_o, cos_phi_o * cos_theta_o);
733 const float T_avg =
max(0.5f * (
T2 +
T3), 1e-5f);
743 const float trt =
average(TRT);
744 const float trrt =
average(TRRT);
745 const float total_energy = r + tt + trt + trrt;
747 if (total_energy == 0.0f) {
754 sample_lobe *= total_energy;
755 if (sample_lobe < r) {
759 else if (sample_lobe < (r + tt)) {
761 *eval = TT / tt * total_energy;
763 else if (sample_lobe < (r + tt + trt)) {
765 *eval = TRT / trt * total_energy;
774 const float3 Y = bsdf->extra->Y;
775 const float3 Z = bsdf->extra->Z;
778 *wo = local_O.
x *
X + local_O.
y *
Y + local_O.
z *
Z;
799 const float3 Y = bsdf->extra->Y;
800 const float3 Z = bsdf->extra->Z;
803 const float3 local_I = bsdf->extra->wi;
810 const float tan_tilt =
tanf(bsdf->tilt);
811 if (tan_tilt *
tan_theta(local_O) < -1.0f) {
821 const float r = bsdf->extra->radius;
822 const float b = bsdf->aspect_ratio;
823 const float phi_i = (
b == 1.0f) ? 0.0f :
dir_phi(local_I);
824 float gamma_m_min =
to_gamma(phi_i - half_span,
b);
825 float gamma_m_max =
to_gamma(phi_i + half_span,
b);
826 if (gamma_m_max < gamma_m_min) {
831 gamma_m_min += 1e-3f;
832 gamma_m_max -= 1e-3f;
842 const float h_max =
min(bsdf->h + bsdf->extra->pixel_coverage, r);
843 const float h_min =
max(bsdf->h - bsdf->extra->pixel_coverage, -r);
848 float nearfield_gamma_min =
h_to_gamma(h_max / r, bsdf->aspect_ratio, local_I);
849 float nearfield_gamma_max =
h_to_gamma(h_min / r, bsdf->aspect_ratio, local_I);
851 if (nearfield_gamma_max < nearfield_gamma_min) {
852 nearfield_gamma_max +=
M_2PI_F;
856 if ((gamma_m_max - nearfield_gamma_min) >
M_2PI_F) {
860 else if ((nearfield_gamma_max - gamma_m_min) >
M_2PI_F) {
861 nearfield_gamma_min -=
M_2PI_F;
862 nearfield_gamma_max -=
M_2PI_F;
865 gamma_m_min =
fmaxf(gamma_m_min, nearfield_gamma_min);
866 gamma_m_max =
fminf(gamma_m_max, nearfield_gamma_max);
869 bsdf->extra->gamma_m_min = gamma_m_min;
870 bsdf->extra->gamma_m_max = gamma_m_max;
872 const float projected_area =
cos_theta(local_I) * dh;
898 const Spectrum A =
exp(2.0f * bsdf->sigma * cos_t / (1.0f -
sqr(wt.
y)));
MINLINE float signf(float f)
MINLINE float safe_sqrtf(float a)
MINLINE float safe_divide(float a, float b)
ATTR_WARN_UNUSED_RESULT const BMVert * v
ccl_device_inline float bsdf_lambda(float alpha2, float cos_N)
ccl_device_forceinline float3 microfacet_ggx_sample_vndf(const float3 wi, const float alpha_x, const float alpha_y, const float2 rand)
ccl_device_inline float bsdf_D(float alpha2, float cos_NH)
ccl_device_inline float bsdf_G(float alpha2, float cos_N)
ccl_device_inline float longitudinal_scattering(float sin_theta_i, float cos_theta_i, float sin_theta_o, float cos_theta_o, float v)
ccl_device float2 sincos_phi(const float3 w)
ccl_device_inline float cos_theta(const float3 w)
ccl_device int bsdf_hair_huang_sample(const KernelGlobals kg, ccl_private const ShaderClosure *sc, ccl_private ShaderData *sd, float3 rand, ccl_private Spectrum *eval, ccl_private float3 *wo, ccl_private float *pdf, ccl_private float2 *sampled_roughness)
ccl_device Spectrum bsdf_hair_huang_albedo(ccl_private const ShaderData *sd, ccl_private const ShaderClosure *sc)
CCL_NAMESPACE_BEGIN struct HuangHairExtra HuangHairExtra
ccl_device_forceinline float bsdf_hair_huang_energy_scale(KernelGlobals kg, float mu, float rough, float ior)
ccl_device Spectrum bsdf_hair_huang_eval(KernelGlobals kg, ccl_private const ShaderData *sd, ccl_private const ShaderClosure *sc, const float3 wo, ccl_private float *pdf)
ccl_device Spectrum bsdf_hair_huang_eval_trrt(const float T, const float R, const Spectrum A)
ccl_device_inline float arc_length(float e2, float gamma)
ccl_device_inline float2 to_point(float gamma, float b)
ccl_device_inline bool microfacet_visible(const float3 v, const float3 m, const float3 h)
ccl_device_inline float2 dir_sph(const float3 w)
ccl_device_inline float tan_theta(const float3 w)
ccl_device_inline float bsdf_Go(float alpha2, float cos_NI, float cos_NO)
ccl_device Spectrum bsdf_hair_huang_eval_residual(KernelGlobals kg, ccl_private const ShaderClosure *sc, const float3 wi, const float3 wo, uint rng_quadrature)
ccl_device_inline float3 sphg_dir(float theta, float gamma, float b)
ccl_device Spectrum bsdf_hair_huang_eval_r(KernelGlobals kg, ccl_private const ShaderClosure *sc, const float3 wi, const float3 wo)
ccl_device_inline bool is_nearfield(ccl_private const HuangHairBSDF *bsdf)
ccl_device_inline float to_gamma(float phi, float b)
ccl_device float sin_phi(const float3 w)
ccl_device_inline float dir_phi(const float3 w)
ccl_device_inline float3 sample_wh(KernelGlobals kg, const float roughness, const float3 wi, const float3 wm, const float2 rand)
struct HuangHairBSDF HuangHairBSDF
ccl_device_inline float to_phi(float gamma, float b)
ccl_device_inline float sin_theta(const float3 w)
ccl_device void bsdf_hair_huang_blur(ccl_private ShaderClosure *sc, float roughness)
ccl_device_inline float dir_theta(const float3 w)
ccl_device_inline float h_to_gamma(const float h_div_r, const float b, const float3 wi)
CCL_NAMESPACE_BEGIN ccl_device void bsdf_transparent_setup(ccl_private ShaderData *sd, const Spectrum weight, uint32_t path_flag)
ccl_device float fresnel_dielectric_cos(float cosi, float eta)
ccl_device_forceinline float fresnel_dielectric(float cos_theta_i, 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)
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
local_group_size(16, 16) .push_constant(Type b
additional_info("compositor_sum_squared_difference_float_shared") .push_constant(Type output_img float dot(value.rgb, luminance_coefficients)") .define("LOAD(value)"
#define kernel_assert(cond)
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define ccl_device_forceinline
#define ccl_device_inline
#define CCL_NAMESPACE_END
draw_view in_light_buf[] float
@ CLOSURE_BSDF_HAIR_HUANG_ID
@ SD_BSDF_HAS_TRANSMISSION
ccl_device float lcg_step_float(T rng)
ccl_device float lookup_table_read_3D(KernelGlobals kg, float x, float y, float z, int offset, int xsize, int ysize, int zsize)
ccl_device void fast_sincosf(float x, ccl_private float *sine, ccl_private float *cosine)
ccl_device_inline bool is_zero(const float2 a)
ccl_device_inline float average(const float2 a)
ccl_device_inline float2 safe_normalize(const float2 a)
ccl_device_inline float cross(const float2 a, const float2 b)
ccl_device_inline float3 reflect(const float3 incident, const float3 unit_normal)
ccl_device_inline float3 exp(float3 v)
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
ccl_private HuangHairExtra * extra
SPECTRUM_DATA_TYPE Spectrum
ccl_device_inline float sqr(float a)
ccl_device_inline float inversesqrtf(float f)
ccl_device_inline bool isfinite_safe(float f)
ccl_device_inline bool isnan_safe(float f)
ccl_device_inline void make_orthonormals(const float3 N, ccl_private float3 *a, ccl_private float3 *b)
ccl_device_inline float cos_from_sin(const float s)
ccl_device_inline int clamp(int a, int mn, int mx)