Skip to content

Commit 1c20019

Browse files
committed
mix child bxdf in microfacet normals quotient properly
1 parent a1d9577 commit 1c20019

2 files changed

Lines changed: 42 additions & 6 deletions

File tree

include/nbl/builtin/hlsl/bxdf/reflection/microfacet_normals.hlsl

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ struct SMicrofacetNormals<Config, BRDF, ndf::PNS_SCHUSSLER, 2 NBL_PARTIAL_REQ_BO
7676
return bxdf_type::anisocache_type::template createForReflection<anisotropic_interaction_type, sample_type>(interaction, _sample);
7777
}
7878

79+
static spectral_type __calculateQuotient(const spectral_type quo, const spectral_type quo_other, const scalar_type choiceProb, const scalar_type pdf, const scalar_type pdf_other)
80+
{
81+
const scalar_type weight = pdf / (pdf + pdf_other); // balance heuristic
82+
return (quo * weight / choiceProb) / (scalar_type(1.0) + pdf_other * (scalar_type(1.0) - choiceProb) / (pdf * choiceProb)) +
83+
(quo_other * (scalar_type(1.0) - weight)) / (pdf_other * (scalar_type(1.0) - choiceProb) + (pdf * choiceProb));
84+
}
85+
7986
value_weight_type evalAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC
8087
{
8188
return evalAndWeight(_sample, anisotropic_interaction_type::create(interaction));
@@ -311,6 +318,9 @@ struct SMicrofacetNormals<Config, BRDF, ndf::PNS_SCHUSSLER, 2 NBL_PARTIAL_REQ_BO
311318
}
312319

313320
const vector3_type Nt = shadowing_method_type::computeNt(Np, shadingBasis);
321+
const scalar_type NpdotV = interaction.getNdotV();
322+
const scalar_type NtdotV = hlsl::dot(Nt, V.getDirection());
323+
const scalar_type lambda_p = shadowing_method_type::lambdaP(NdotNp, hlsl::max(scalar_type(0.0), NpdotV), hlsl::max(scalar_type(0.0), NtdotV));
314324
spectral_type quo = hlsl::promote<spectral_type>(1.0);
315325

316326
if (_cache.sampleFromNt)
@@ -325,12 +335,14 @@ struct SMicrofacetNormals<Config, BRDF, ndf::PNS_SCHUSSLER, 2 NBL_PARTIAL_REQ_BO
325335
typename bxdf_type::anisotropic_interaction_type interaction_negreflected = bxdf_type::anisotropic_interaction_type::create(iso_negreflected);
326336

327337
quotient_weight_type qw = nested_brdf.quotientAndWeight(_sample, interaction_negreflected, __createChildCache(_sample, interaction_negreflected));
328-
quo *= qw.quotient();
338+
value_weight_type vw_other = nested_brdf.evalAndWeight(_sample, interaction_negreflected);
339+
quo *= __calculateQuotient(qw.quotient(), vw_other.value(), scalar_type(1.0) - lambda_p, qw.weight(), vw_other.weight());
329340
}
330341
else
331342
{
332343
quotient_weight_type qw = nested_brdf.quotientAndWeight(_sample, interaction, _cache.aniso_cache);
333-
quo *= qw.quotient();
344+
value_weight_type vw_other = nested_brdf.evalAndWeight(_sample, interaction);
345+
quo *= __calculateQuotient(qw.quotient(), vw_other.value(), lambda_p, qw.weight(), vw_other.weight());
334346
}
335347

336348
if (_cache.sampleIsShadowed)
@@ -403,6 +415,13 @@ struct SMicrofacetNormals<Config, BRDF, P, 1 NBL_PARTIAL_REQ_BOT(config_concepts
403415
return bxdf_type::anisocache_type::template createForReflection<anisotropic_interaction_type, sample_type>(interaction, _sample);
404416
}
405417

418+
static spectral_type __calculateQuotient(const spectral_type quo, const spectral_type quo_other, const scalar_type choiceProb, const scalar_type pdf, const scalar_type pdf_other)
419+
{
420+
const scalar_type weight = pdf / (pdf + pdf_other); // balance heuristic
421+
return (quo * weight / choiceProb) / (scalar_type(1.0) + pdf_other * (scalar_type(1.0) - choiceProb) / (pdf * choiceProb)) +
422+
(quo_other * (scalar_type(1.0) - weight)) / (pdf_other * (scalar_type(1.0) - choiceProb) + (pdf * choiceProb));
423+
}
424+
406425
value_weight_type evalAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC
407426
{
408427
return evalAndWeight(_sample, anisotropic_interaction_type::create(interaction));
@@ -580,6 +599,9 @@ struct SMicrofacetNormals<Config, BRDF, P, 1 NBL_PARTIAL_REQ_BOT(config_concepts
580599
}
581600

582601
const vector3_type Nt = shadowing_method_type::computeNt(Np, shadingBasis);
602+
const scalar_type NpdotV = interaction.getNdotV();
603+
const scalar_type NtdotV = hlsl::dot(Nt, V.getDirection());
604+
const scalar_type lambda_p = shadowing_method_type::lambdaP(NdotNp, hlsl::max(scalar_type(0.0), NpdotV), hlsl::max(scalar_type(0.0), NtdotV));
583605
spectral_type quo = hlsl::promote<spectral_type>(1.0);
584606

585607
if (_cache.sampleFromNt)
@@ -589,12 +611,14 @@ struct SMicrofacetNormals<Config, BRDF, P, 1 NBL_PARTIAL_REQ_BOT(config_concepts
589611
typename bxdf_type::anisotropic_interaction_type interaction_t = bxdf_type::anisotropic_interaction_type::create(iso_t);
590612

591613
quotient_weight_type qw = nested_brdf.quotientAndWeight(_sample, interaction_t, __createChildCache(_sample, interaction_t));
592-
quo *= qw.quotient();
614+
value_weight_type vw_other = nested_brdf.evalAndWeight(_sample, interaction_t);
615+
quo *= __calculateQuotient(qw.quotient(), vw_other.value(), scalar_type(1.0) - lambda_p, qw.weight(), vw_other.weight());
593616
}
594617
else
595618
{
596619
quotient_weight_type qw = nested_brdf.quotientAndWeight(_sample, interaction, _cache.aniso_cache);
597-
quo *= qw.quotient();
620+
value_weight_type vw_other = nested_brdf.evalAndWeight(_sample, interaction);
621+
quo *= __calculateQuotient(qw.quotient(), vw_other.value(), lambda_p, qw.weight(), vw_other.weight());
598622
}
599623

600624
if (_cache.sampleIsShadowed)

include/nbl/builtin/hlsl/bxdf/transmission/microfacet_normals.hlsl

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ struct SMicrofacetNormals<Config, BRDF, P, 1 NBL_PARTIAL_REQ_BOT(config_concepts
7979
return bxdf_type::anisocache_type::template create<anisotropic_interaction_type, sample_type>(interaction, _sample, orientedEta);
8080
}
8181

82+
static spectral_type __calculateQuotient(const spectral_type quo, const spectral_type quo_other, const scalar_type choiceProb, const scalar_type pdf, const scalar_type pdf_other)
83+
{
84+
const scalar_type weight = pdf / (pdf + pdf_other); // balance heuristic
85+
return (quo * weight / choiceProb) / (scalar_type(1.0) + pdf_other * (scalar_type(1.0) - choiceProb) / (pdf * choiceProb)) +
86+
(quo_other * (scalar_type(1.0) - weight)) / (pdf_other * (scalar_type(1.0) - choiceProb) + (pdf * choiceProb));
87+
}
88+
8289
value_weight_type evalAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC
8390
{
8491
return evalAndWeight(_sample, anisotropic_interaction_type::create(interaction));
@@ -258,6 +265,9 @@ struct SMicrofacetNormals<Config, BRDF, P, 1 NBL_PARTIAL_REQ_BOT(config_concepts
258265
}
259266

260267
const vector3_type Nt = shadowing_method_type::computeNt(Np, shadingBasis);
268+
const scalar_type NpdotV = interaction.getNdotV();
269+
const scalar_type NtdotV = hlsl::dot(Nt, V.getDirection());
270+
const scalar_type lambda_p = shadowing_method_type::lambdaP(NdotNp, hlsl::abs(NpdotV), hlsl::abs(NtdotV));
261271
spectral_type quo = hlsl::promote<spectral_type>(1.0);
262272

263273
if (_cache.sampleFromNt)
@@ -267,12 +277,14 @@ struct SMicrofacetNormals<Config, BRDF, P, 1 NBL_PARTIAL_REQ_BOT(config_concepts
267277
typename bxdf_type::anisotropic_interaction_type interaction_t = bxdf_type::anisotropic_interaction_type::create(iso_t);
268278

269279
quotient_weight_type qw = nested_bsdf.quotientAndWeight(_sample, interaction_t, __createChildCache(_sample, interaction_t));
270-
quo *= qw.quotient();
280+
value_weight_type vw_other = nested_bsdf.evalAndWeight(_sample, interaction_t);
281+
quo *= __calculateQuotient(qw.quotient(), vw_other.value(), scalar_type(1.0) - lambda_p, qw.weight(), vw_other.weight());
271282
}
272283
else
273284
{
274285
quotient_weight_type qw = nested_bsdf.quotientAndWeight(_sample, interaction, _cache.aniso_cache);
275-
quo *= qw.quotient();
286+
value_weight_type vw_other = nested_bsdf.evalAndWeight(_sample, interaction);
287+
quo *= __calculateQuotient(qw.quotient(), vw_other.value(), lambda_p, qw.weight(), vw_other.weight());
276288
}
277289

278290
if (_cache.sampleIsShadowed)

0 commit comments

Comments
 (0)