Fix #114780: Cycles: Principled Chiang Hair importance sampling correction
Principled Chiang hair longitudinal importance sampling correction, according to the new pbrt fix here : https://github.com/mmp/pbrt-v3/pull/256 Pull Request: https://projects.blender.org/blender/blender/pulls/115241
This commit is contained in:
parent
7911e2614f
commit
4708e9ec6d
@ -142,11 +142,13 @@ ccl_device_inline float longitudinal_scattering(
|
|||||||
if (v <= 0.1f) {
|
if (v <= 0.1f) {
|
||||||
float i0 = log_bessel_I0(cos_arg);
|
float i0 = log_bessel_I0(cos_arg);
|
||||||
float val = expf(i0 - sin_arg - inv_v + 0.6931f + logf(0.5f * inv_v));
|
float val = expf(i0 - sin_arg - inv_v + 0.6931f + logf(0.5f * inv_v));
|
||||||
|
kernel_assert(isfinite_safe(val));
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
float i0 = bessel_I0(cos_arg);
|
float i0 = bessel_I0(cos_arg);
|
||||||
float val = (expf(-sin_arg) * i0) / (sinhf(inv_v) * 2.0f * v);
|
float val = (expf(-sin_arg) * i0) / (sinhf(inv_v) * 2.0f * v);
|
||||||
|
kernel_assert(isfinite_safe(val));
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -185,7 +187,7 @@ ccl_device int bsdf_hair_chiang_setup(ccl_private ShaderData *sd, ccl_private Ch
|
|||||||
kernel_assert(isfinite_safe(bsdf->h));
|
kernel_assert(isfinite_safe(bsdf->h));
|
||||||
|
|
||||||
bsdf->N = Y;
|
bsdf->N = Y;
|
||||||
|
bsdf->alpha = -bsdf->alpha;
|
||||||
return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_HAS_TRANSMISSION;
|
return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_HAS_TRANSMISSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,9 +226,9 @@ ccl_device_inline void hair_attenuation(
|
|||||||
Ap_energy[3] *= fac;
|
Ap_energy[3] *= fac;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Given the tilt angle, generate the rotated theta_i for the different bounces. */
|
/* Update sin_theta_o and cos_theta_o to account for scale tilt for each bounce. */
|
||||||
ccl_device_inline void hair_alpha_angles(float sin_theta_i,
|
ccl_device_inline void hair_alpha_angles(float sin_theta_o,
|
||||||
float cos_theta_i,
|
float cos_theta_o,
|
||||||
float alpha,
|
float alpha,
|
||||||
ccl_private float *angles)
|
ccl_private float *angles)
|
||||||
{
|
{
|
||||||
@ -237,12 +239,12 @@ ccl_device_inline void hair_alpha_angles(float sin_theta_i,
|
|||||||
float sin_4alpha = 2.0f * sin_2alpha * cos_2alpha;
|
float sin_4alpha = 2.0f * sin_2alpha * cos_2alpha;
|
||||||
float cos_4alpha = sqr(cos_2alpha) - sqr(sin_2alpha);
|
float cos_4alpha = sqr(cos_2alpha) - sqr(sin_2alpha);
|
||||||
|
|
||||||
angles[0] = sin_theta_i * cos_2alpha + cos_theta_i * sin_2alpha;
|
angles[0] = sin_theta_o * cos_2alpha - cos_theta_o * sin_2alpha;
|
||||||
angles[1] = fabsf(cos_theta_i * cos_2alpha - sin_theta_i * sin_2alpha);
|
angles[1] = fabsf(cos_theta_o * cos_2alpha + sin_theta_o * sin_2alpha);
|
||||||
angles[2] = sin_theta_i * cos_1alpha - cos_theta_i * sin_1alpha;
|
angles[2] = sin_theta_o * cos_1alpha + cos_theta_o * sin_1alpha;
|
||||||
angles[3] = fabsf(cos_theta_i * cos_1alpha + sin_theta_i * sin_1alpha);
|
angles[3] = fabsf(cos_theta_o * cos_1alpha - sin_theta_o * sin_1alpha);
|
||||||
angles[4] = sin_theta_i * cos_4alpha - cos_theta_i * sin_4alpha;
|
angles[4] = sin_theta_o * cos_4alpha + cos_theta_o * sin_4alpha;
|
||||||
angles[5] = fabsf(cos_theta_i * cos_4alpha + sin_theta_i * sin_4alpha);
|
angles[5] = fabsf(cos_theta_o * cos_4alpha - sin_theta_o * sin_4alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Evaluation function for our shader. */
|
/* Evaluation function for our shader. */
|
||||||
@ -293,17 +295,17 @@ ccl_device Spectrum bsdf_hair_chiang_eval(KernelGlobals kg,
|
|||||||
const float phi = phi_i - phi_o;
|
const float phi = phi_i - phi_o;
|
||||||
|
|
||||||
float angles[6];
|
float angles[6];
|
||||||
hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
|
hair_alpha_angles(sin_theta_o, cos_theta_o, bsdf->alpha, angles);
|
||||||
|
|
||||||
Spectrum F = zero_spectrum();
|
Spectrum F = zero_spectrum();
|
||||||
float F_energy = 0.0f;
|
float F_energy = 0.0f;
|
||||||
|
|
||||||
/* Primary specular (R), Transmission (TT) and Secondary Specular (TRT). */
|
/* Primary specular (R), Transmission (TT) and Secondary Specular (TRT). */
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
const float Mp = longitudinal_scattering(angles[2 * i],
|
const float Mp = longitudinal_scattering(sin_theta_i,
|
||||||
|
cos_theta_i,
|
||||||
|
angles[2 * i],
|
||||||
angles[2 * i + 1],
|
angles[2 * i + 1],
|
||||||
sin_theta_o,
|
|
||||||
cos_theta_o,
|
|
||||||
(i == 0) ? bsdf->m0_roughness :
|
(i == 0) ? bsdf->m0_roughness :
|
||||||
(i == 1) ? 0.25f * bsdf->v :
|
(i == 1) ? 0.25f * bsdf->v :
|
||||||
4.0f * bsdf->v);
|
4.0f * bsdf->v);
|
||||||
@ -347,6 +349,7 @@ ccl_device int bsdf_hair_chiang_sample(KernelGlobals kg,
|
|||||||
kernel_assert(fabsf(dot(X, Y)) < 1e-3f);
|
kernel_assert(fabsf(dot(X, Y)) < 1e-3f);
|
||||||
const float3 Z = safe_normalize(cross(X, Y));
|
const float3 Z = safe_normalize(cross(X, Y));
|
||||||
|
|
||||||
|
/* wo in pbrt. */
|
||||||
const float3 local_O = make_float3(dot(sd->wi, X), dot(sd->wi, Y), dot(sd->wi, Z));
|
const float3 local_O = make_float3(dot(sd->wi, X), dot(sd->wi, Y), dot(sd->wi, Z));
|
||||||
|
|
||||||
const float sin_theta_o = local_O.x;
|
const float sin_theta_o = local_O.x;
|
||||||
@ -387,19 +390,20 @@ ccl_device int bsdf_hair_chiang_sample(KernelGlobals kg,
|
|||||||
v *= 4.0f;
|
v *= 4.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float angles[6];
|
||||||
|
hair_alpha_angles(sin_theta_o, cos_theta_o, bsdf->alpha, angles);
|
||||||
|
float sin_theta_o_tilted = sin_theta_o;
|
||||||
|
float cos_theta_o_tilted = cos_theta_o;
|
||||||
|
if (p < 3) {
|
||||||
|
sin_theta_o_tilted = angles[2 * p];
|
||||||
|
cos_theta_o_tilted = angles[2 * p + 1];
|
||||||
|
}
|
||||||
rand.z = max(rand.z, 1e-5f);
|
rand.z = max(rand.z, 1e-5f);
|
||||||
const float fac = 1.0f + v * logf(rand.z + (1.0f - rand.z) * expf(-2.0f / v));
|
const float fac = 1.0f + v * logf(rand.z + (1.0f - rand.z) * expf(-2.0f / v));
|
||||||
float sin_theta_i = -fac * sin_theta_o +
|
float sin_theta_i = -fac * sin_theta_o_tilted +
|
||||||
cos_from_sin(fac) * cosf(M_2PI_F * rand.y) * cos_theta_o;
|
sin_from_cos(fac) * cosf(M_2PI_F * rand.y) * cos_theta_o_tilted;
|
||||||
float cos_theta_i = cos_from_sin(sin_theta_i);
|
float cos_theta_i = cos_from_sin(sin_theta_i);
|
||||||
|
|
||||||
float angles[6];
|
|
||||||
if (p < 3) {
|
|
||||||
hair_alpha_angles(sin_theta_i, cos_theta_i, -bsdf->alpha, angles);
|
|
||||||
sin_theta_i = angles[2 * p];
|
|
||||||
cos_theta_i = angles[2 * p + 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
float phi;
|
float phi;
|
||||||
if (p < 3) {
|
if (p < 3) {
|
||||||
phi = delta_phi(p, gamma_o, gamma_t) + sample_trimmed_logistic(rand.x, bsdf->s);
|
phi = delta_phi(p, gamma_o, gamma_t) + sample_trimmed_logistic(rand.x, bsdf->s);
|
||||||
@ -409,17 +413,15 @@ ccl_device int bsdf_hair_chiang_sample(KernelGlobals kg,
|
|||||||
}
|
}
|
||||||
const float phi_i = phi_o + phi;
|
const float phi_i = phi_o + phi;
|
||||||
|
|
||||||
hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
|
|
||||||
|
|
||||||
Spectrum F = zero_spectrum();
|
Spectrum F = zero_spectrum();
|
||||||
float F_energy = 0.0f;
|
float F_energy = 0.0f;
|
||||||
|
|
||||||
/* Primary specular (R), Transmission (TT) and Secondary Specular (TRT). */
|
/* Primary specular (R), Transmission (TT) and Secondary Specular (TRT). */
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
const float Mp = longitudinal_scattering(angles[2 * i],
|
const float Mp = longitudinal_scattering(sin_theta_i,
|
||||||
|
cos_theta_i,
|
||||||
|
angles[2 * i],
|
||||||
angles[2 * i + 1],
|
angles[2 * i + 1],
|
||||||
sin_theta_o,
|
|
||||||
cos_theta_o,
|
|
||||||
(i == 0) ? bsdf->m0_roughness :
|
(i == 0) ? bsdf->m0_roughness :
|
||||||
(i == 1) ? 0.25f * bsdf->v :
|
(i == 1) ? 0.25f * bsdf->v :
|
||||||
4.0f * bsdf->v);
|
4.0f * bsdf->v);
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 9c778e4642436b603d51923213483cccef1d08a1
|
Subproject commit 753727081d73e1469f45fb9b36ad081c12cfcfab
|
Loading…
Reference in New Issue
Block a user