Fix: Cycles: wrong refractive index in path guiding

should be the relative IOR of the outgoing media to the incoming media,
depending on `bsdf->ior` and whether the interaction is refraction.
Reference paper: [Robust Fitting of Parallax-Aware Mixtures for Path Guiding](https://uni-tuebingen.de/fakultaeten/mathematisch-naturwissenschaftliche-fakultaet/fachbereiche/informatik/lehrstuehle/computergrafik/lehrstuhl/veroeffentlichungen/robust-fitting-of-parallax-aware-mixtures-for-path-guiding/) Eq (35)

Pull Request: https://projects.blender.org/blender/blender/pulls/112157
This commit is contained in:
Weizhen Huang 2023-09-18 16:20:48 +02:00 committed by Weizhen Huang
parent c951464b8a
commit e894e6a411
6 changed files with 23 additions and 28 deletions

View File

@ -196,10 +196,12 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
*eta = 1.0f;
break;
case CLOSURE_BSDF_HAIR_CHIANG_ID:
label = bsdf_hair_chiang_sample(kg, sc, sd, rand, eval, wo, pdf, sampled_roughness, eta);
label = bsdf_hair_chiang_sample(kg, sc, sd, rand, eval, wo, pdf, sampled_roughness);
*eta = 1.0f;
break;
case CLOSURE_BSDF_HAIR_HUANG_ID:
label = bsdf_hair_huang_sample(kg, sc, sd, rand, eval, wo, pdf, sampled_roughness, eta);
label = bsdf_hair_huang_sample(kg, sc, sd, rand, eval, wo, pdf, sampled_roughness);
*eta = 1.0f;
break;
case CLOSURE_BSDF_SHEEN_ID:
label = bsdf_sheen_sample(sc, Ng, sd->wi, rand_xy, eval, wo, pdf);
@ -247,6 +249,7 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
ccl_device_inline void bsdf_roughness_eta(const KernelGlobals kg,
ccl_private const ShaderClosure *sc,
const float3 wo,
ccl_private float2 *roughness,
ccl_private float *eta)
{
@ -290,12 +293,7 @@ ccl_device_inline void bsdf_roughness_eta(const KernelGlobals kg,
case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID: {
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
*roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y);
if (CLOSURE_IS_REFRACTION(bsdf->type) || CLOSURE_IS_GLASS(bsdf->type)) {
*eta = 1.0f / bsdf->ior;
}
else {
*eta = bsdf->ior;
}
*eta = (bsdf_is_transmission(sc, wo)) ? bsdf->ior : 1.0f;
break;
}
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: {
@ -330,12 +328,12 @@ ccl_device_inline void bsdf_roughness_eta(const KernelGlobals kg,
case CLOSURE_BSDF_HAIR_CHIANG_ID:
alpha = ((ccl_private ChiangHairBSDF *)sc)->m0_roughness;
*roughness = make_float2(alpha, alpha);
*eta = ((ccl_private ChiangHairBSDF *)sc)->eta;
*eta = 1.0f;
break;
case CLOSURE_BSDF_HAIR_HUANG_ID:
alpha = ((ccl_private HuangHairBSDF *)sc)->roughness;
*roughness = make_float2(alpha, alpha);
*eta = ((ccl_private HuangHairBSDF *)sc)->eta;
*eta = 1.0f;
break;
case CLOSURE_BSDF_SHEEN_ID:
alpha = ((ccl_private SheenBsdf *)sc)->roughness;

View File

@ -683,7 +683,7 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc,
}
*sampled_roughness = make_float2(alpha_x, alpha_y);
*eta = do_refract ? m_inv_eta : m_eta;
*eta = do_refract ? m_eta : 1.0f;
return (do_refract ? LABEL_TRANSMIT : LABEL_REFLECT) |
(m_singular ? LABEL_SINGULAR : LABEL_GLOSSY);

View File

@ -335,13 +335,11 @@ ccl_device int bsdf_hair_chiang_sample(KernelGlobals kg,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf,
ccl_private float2 *sampled_roughness,
ccl_private float *eta)
ccl_private float2 *sampled_roughness)
{
ccl_private ChiangHairBSDF *bsdf = (ccl_private ChiangHairBSDF *)sc;
*sampled_roughness = make_float2(bsdf->m0_roughness, bsdf->m0_roughness);
*eta = bsdf->eta;
const float3 Y = bsdf->N;

View File

@ -614,14 +614,12 @@ ccl_device int bsdf_hair_huang_sample(const KernelGlobals kg,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf,
ccl_private float2 *sampled_roughness,
ccl_private float *eta)
ccl_private float2 *sampled_roughness)
{
ccl_private HuangHairBSDF *bsdf = (ccl_private HuangHairBSDF *)sc;
const float roughness = bsdf->roughness;
*sampled_roughness = make_float2(roughness, roughness);
*eta = bsdf->eta;
kernel_assert(fabsf(bsdf->h) < bsdf->extra->radius);
@ -680,7 +678,7 @@ ccl_device int bsdf_hair_huang_sample(const KernelGlobals kg,
}
float cos_theta_t1;
const float R1 = fresnel_dielectric(dot(wi, wh1), *eta, &cos_theta_t1);
const float R1 = fresnel_dielectric(dot(wi, wh1), bsdf->eta, &cos_theta_t1);
const float scale1 = bsdf_hair_huang_energy_scale(kg, cos_mi1, sqrt_roughness, bsdf->eta);
const float R = bsdf->extra->R * R1 * scale1 * microfacet_visible(wr, wmi_, wh1) *
bsdf_Go(roughness2, cos_mi1, dot(wmi, wr));
@ -717,7 +715,7 @@ ccl_device int bsdf_hair_huang_sample(const KernelGlobals kg,
const float T2 = 1.0f - R2;
const float scale2 = bsdf_hair_huang_energy_scale(kg, cos_mi2, sqrt_roughness, inv_eta);
wtt = refract_angle(-wt, wh2, cos_theta_t2, *eta);
wtt = refract_angle(-wt, wh2, cos_theta_t2, bsdf->eta);
if (dot(wmt, -wtt) > 0.0f && cos_theta_t2 != 0.0f && microfacet_visible(-wtt, wmt_, wh2)) {
TT = bsdf->extra->TT * T1 * A_t * T2 * scale2 * bsdf_Go(roughness2, cos_mi2, dot(wmt, -wtt));
@ -733,7 +731,7 @@ ccl_device int bsdf_hair_huang_sample(const KernelGlobals kg,
float cos_theta_t3;
const float R3 = fresnel_dielectric(dot(wtr, wh3), inv_eta, &cos_theta_t3);
wtrt = refract_angle(wtr, wh3, cos_theta_t3, *eta);
wtrt = refract_angle(wtr, wh3, cos_theta_t3, bsdf->eta);
const float cos_mi3 = dot(wmtr, wtr);
if (cos_mi3 > 0.0f) {

View File

@ -15,6 +15,7 @@ CCL_NAMESPACE_BEGIN
struct GuidingRISSample {
float3 rand;
float2 sampled_roughness;
/* The relative ior of the outgoing media and the incoming media. */
float eta{1.0f};
int label;
float3 wo;

View File

@ -209,7 +209,7 @@ ccl_device_inline void surface_shader_prepare_closures(KernelGlobals kg,
}
/* BSDF */
#if 0
#ifdef WITH_CYCLES_DEBUG
ccl_device_inline void surface_shader_validate_bsdf_sample(const KernelGlobals kg,
const ShaderClosure *sc,
const float3 wo,
@ -224,7 +224,7 @@ ccl_device_inline void surface_shader_validate_bsdf_sample(const KernelGlobals k
float2 comp_roughness;
float comp_eta;
bsdf_roughness_eta(kg, sc, &comp_roughness, &comp_eta);
bsdf_roughness_eta(kg, sc, wo, &comp_roughness, &comp_eta);
kernel_assert(org_eta == comp_eta);
kernel_assert(org_roughness.x == comp_roughness.x);
kernel_assert(org_roughness.y == comp_roughness.y);
@ -550,10 +550,10 @@ ccl_device int surface_shader_bsdf_guided_sample_closure_mis(KernelGlobals kg,
unguided_bsdf_pdf,
sampled_roughness,
eta);
# if 0
// Code path to validate the estimation of the label, sampled roughness and eta
// This should be activated from time to time when the BSDFs change to check if everything
// is still working correctly.
# ifdef WITH_CYCLES_DEBUG
/* Code path to validate the estimation of the label, sampled roughness and eta. This should be
* activated from time to time when the BSDFs change to check if everything is still working
* correctly. */
if (*unguided_bsdf_pdf > 0.0f) {
surface_shader_validate_bsdf_sample(kg, sc, *wo, label, *sampled_roughness, *eta);
}
@ -773,7 +773,7 @@ ccl_device int surface_shader_bsdf_guided_sample_closure_ris(KernelGlobals kg,
idx = (rnd > sum_pdfs) ? sd->num_closure - 1 : idx;
label = bsdf_label(kg, &sd->closure[idx], *wo);
bsdf_roughness_eta(kg, &sd->closure[idx], sampled_roughness, eta);
bsdf_roughness_eta(kg, &sd->closure[idx], *wo, sampled_roughness, eta);
}
kernel_assert(isfinite_safe(*bsdf_pdf));
@ -793,7 +793,7 @@ ccl_device int surface_shader_bsdf_guided_sample_closure_ris(KernelGlobals kg,
unguided_bsdf_pdf,
sampled_roughness,
eta);
# if 0
# ifdef WITH_CYCLES_DEBUG
// Code path to validate the estimation of the label, sampled roughness and eta
// This should be activated from time to time when the BSDFs change to check if everything
// is still working correctly.