diff --git a/examples_tests b/examples_tests index 2fd21fd891..21334ead5d 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 2fd21fd8917660d2a559b97d80afa95dd6b591d5 +Subproject commit 21334ead5dcc4c1cf3fbc3a1c815166ad9874bee diff --git a/include/nbl/builtin/hlsl/bxdf/base/cook_torrance_base.hlsl b/include/nbl/builtin/hlsl/bxdf/base/cook_torrance_base.hlsl index 30639d6b7c..f5a4fbf5c6 100644 --- a/include/nbl/builtin/hlsl/bxdf/base/cook_torrance_base.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/base/cook_torrance_base.hlsl @@ -20,27 +20,6 @@ namespace bxdf namespace impl { -template -struct __implicit_promote; - -template -struct __implicit_promote -{ - static T __call(const T v) - { - return v; - } -}; - -template -struct __implicit_promote::scalar_type, 1> > -{ - static T __call(const vector::scalar_type, 1> v) - { - return hlsl::promote(v[0]); - } -}; - template struct quant_query_helper; @@ -83,7 +62,19 @@ struct SCookTorrance NBL_CONSTEXPR_STATIC_INLINE bool IsAnisotropic = ndf_type::IsAnisotropic; NBL_CONSTEXPR_STATIC_INLINE bool IsBSDF = ndf_type::SupportedPaths != ndf::MTT_REFLECT; + using random_type = conditional_t; NBL_HLSL_BXDF_ANISOTROPIC_COND_DECLS(IsAnisotropic); + using cache_type = conditional_t; + + struct PdfQuery + { + scalar_type pdf; + fresnel_type orientedFresnel; + typename ndf_type::quant_query_type quantQuery; + + spectral_type reflectance; + scalar_type scaled_reflectance; + }; // utility functions template, @@ -143,7 +134,9 @@ struct SCookTorrance static scalar_type __getScaledReflectance(NBL_CONST_REF_ARG(fresnel_type) orientedFresnel, NBL_CONST_REF_ARG(Interaction) interaction, scalar_type clampedVdotH, bool transmitted, NBL_REF_ARG(spectral_type) outFresnelVal) { scalar_type reflectance = orientedFresnel(clampedVdotH)[0]; - return hlsl::mix(reflectance, scalar_type(1.0)-reflectance, transmitted); + reflectance = hlsl::mix(reflectance, scalar_type(1.0)-reflectance, transmitted); + outFresnelVal = hlsl::promote(reflectance); + return reflectance; } bool __dotIsValue(const vector3_type a, const vector3_type b, const scalar_type value) NBL_CONST_MEMBER_FUNC @@ -152,18 +145,35 @@ struct SCookTorrance return hlsl::max(ab, value / ab) <= scalar_type(value + 1e-3); } + template, + typename C=bool_constant NBL_FUNC_REQUIRES(C::value && !fresnel_type::ReturnsMonochrome) + static scalar_type __getMonochromeEta(NBL_CONST_REF_ARG(fresnel_type) fresnel, NBL_CONST_REF_ARG(Interaction) interaction) + { + spectral_type throughputWeights = interaction.getLuminosityContributionHint(); + return hlsl::dot(fresnel.eta, throughputWeights) / (throughputWeights.r + throughputWeights.g + throughputWeights.b); + } + template, + typename C=bool_constant NBL_FUNC_REQUIRES(C::value && fresnel_type::ReturnsMonochrome) + static scalar_type __getMonochromeEta(NBL_CONST_REF_ARG(fresnel_type) fresnel, NBL_CONST_REF_ARG(Interaction) interaction) + { + return fresnel.getRefractionOrientedEta(); + } + // bxdf stuff template, class MicrofacetCache=conditional_t NBL_FUNC_REQUIRES(RequiredInteraction && RequiredMicrofacetCache) - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) NBL_CONST_MEMBER_FUNC + value_weight_type evalAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) NBL_CONST_MEMBER_FUNC { - fresnel_type _f = __getOrientedFresnel(fresnel, interaction.getNdotV()); - if (!__checkValid(_f, _sample, interaction, cache)) - return hlsl::promote(0.0); + PdfQuery pdfQuery = __forwardPdf(_sample, interaction, cache); + scalar_type _pdf = pdfQuery.pdf; + if (_pdf == scalar_type(0.0) || hlsl::isinf(_pdf)) + return value_weight_type::create(scalar_type(0.0), scalar_type(0.0)); + + fresnel_type _f = pdfQuery.orientedFresnel; using quant_query_type = typename ndf_type::quant_query_type; - quant_query_type qq = impl::quant_query_helper::template __call(ndf, _f, interaction, cache); + quant_query_type qq = pdfQuery.quantQuery; using g2g1_query_type = typename ndf_type::g2g1_query_type; g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); @@ -179,19 +189,27 @@ struct SCookTorrance // immediately return only after all calls setting DG // allows compiler to throw away calls to ndf.D if using __overwriteDG, before that we only avoid computation for G2(correlated) if (isInfinity) - return hlsl::promote(0.0); - - scalar_type clampedVdotH = cache.getVdotH(); - NBL_IF_CONSTEXPR(IsBSDF) - clampedVdotH = hlsl::abs(clampedVdotH); + return value_weight_type::create(scalar_type(0.0), scalar_type(0.0)); + spectral_type eval; NBL_IF_CONSTEXPR(IsBSDF) - { - const spectral_type reflectance = impl::__implicit_promote::__call(_f(clampedVdotH)); - return hlsl::mix(reflectance, hlsl::promote(1.0) - reflectance, cache.isTransmission()) * DG; - } + eval = pdfQuery.reflectance; else - return impl::__implicit_promote::__call(_f(clampedVdotH)) * DG; + eval = _f(cache.getVdotH()); + eval *= DG; + + return value_weight_type::create(eval, _pdf); + } + + template, + class MicrofacetCache=conditional_t + NBL_FUNC_REQUIRES(RequiredInteraction && RequiredMicrofacetCache) + value_weight_type evalAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(Interaction) interaction) NBL_CONST_MEMBER_FUNC + { + const scalar_type eta = __getMonochromeEta(fresnel, interaction); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.getNdotV(), hlsl::promote(eta)); + MicrofacetCache cache = MicrofacetCache::template create(interaction, _sample, orientedEta); + return evalAndWeight(_sample, interaction, cache); } sample_type __generate_common(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type localH, @@ -245,7 +263,7 @@ struct SCookTorrance return sample_type::create(L, T, B, NdotL); } template NBL_FUNC_REQUIRES(C::value && !IsBSDF) - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache) NBL_CONST_MEMBER_FUNC + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const random_type u, NBL_REF_ARG(anisocache_type) cache) NBL_CONST_MEMBER_FUNC { const scalar_type NdotV = interaction.getNdotV(); if (NdotV < numeric_limits::min) @@ -275,7 +293,7 @@ struct SCookTorrance return s; } template NBL_FUNC_REQUIRES(C::value && IsBSDF) - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(anisocache_type) cache) NBL_CONST_MEMBER_FUNC + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const random_type u, NBL_REF_ARG(anisocache_type) cache) NBL_CONST_MEMBER_FUNC { const vector3_type localV = interaction.getTangentSpaceV(); const scalar_type NdotV = localV.z; @@ -332,7 +350,7 @@ struct SCookTorrance return s; } template NBL_FUNC_REQUIRES(C::value && !IsAnisotropic) - sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const conditional_t u, NBL_REF_ARG(isocache_type) cache) NBL_CONST_MEMBER_FUNC + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const random_type u, NBL_REF_ARG(isocache_type) cache) NBL_CONST_MEMBER_FUNC { anisocache_type aniso_cache; sample_type s = generate(anisotropic_interaction_type::create(interaction), u, aniso_cache); @@ -340,60 +358,66 @@ struct SCookTorrance return s; } - template - scalar_type __pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache, NBL_REF_ARG(bool) isInfinity) NBL_CONST_MEMBER_FUNC + template + PdfQuery __forwardPdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) NBL_CONST_MEMBER_FUNC { - using quant_query_type = typename ndf_type::quant_query_type; - using dg1_query_type = typename ndf_type::dg1_query_type; + // MicrofacetCache cache = _cache; + // cache.VdotH = 0.5; + PdfQuery query; + query.pdf = scalar_type(0.0); + query.orientedFresnel = __getOrientedFresnel(fresnel, interaction.getNdotV()); + const bool cacheIsValid = __checkValid(query.orientedFresnel, _sample, interaction, cache); + assert(!FromGenerator || cacheIsValid); + const bool isValid = FromGenerator ? _sample.isValid() : cacheIsValid; // when from generator, expect the generated sample to always be valid, different checks for brdf and btdf + + if (isValid) + { + using dg1_query_type = typename ndf_type::dg1_query_type; + dg1_query_type dq = ndf.template createDG1Query(interaction, cache); - dg1_query_type dq = ndf.template createDG1Query(interaction, cache); + bool isInfinity; + query.quantQuery = impl::quant_query_helper::template __call(ndf, query.orientedFresnel, interaction, cache); + quant_type DG1 = ndf.template DG1(dq, query.quantQuery, _sample, interaction, isInfinity); - fresnel_type _f = __getOrientedFresnel(fresnel, interaction.getNdotV()); - quant_query_type qq = impl::quant_query_helper::template __call(ndf, _f, interaction, cache); - quant_type DG1 = ndf.template DG1(dq, qq, _sample, interaction, isInfinity); + if (isInfinity) + { + query.pdf = bit_cast(numeric_limits::infinity); + return query; + } - NBL_IF_CONSTEXPR(IsBSDF) - { - spectral_type dummy; - const scalar_type reflectance = __getScaledReflectance(_f, interaction, hlsl::abs(cache.getVdotH()), cache.isTransmission(), dummy); - return reflectance * DG1.projectedLightMeasure; - } - else - { - return DG1.projectedLightMeasure; + query.pdf = DG1.projectedLightMeasure; + NBL_IF_CONSTEXPR(IsBSDF) + { + query.scaled_reflectance = __getScaledReflectance(query.orientedFresnel, interaction, hlsl::abs(cache.getVdotH()), cache.isTransmission(), query.reflectance); + query.pdf *= query.scaled_reflectance; + } } + + return query; } template, class MicrofacetCache=conditional_t NBL_FUNC_REQUIRES(RequiredInteraction && RequiredMicrofacetCache) - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) NBL_CONST_MEMBER_FUNC + scalar_type forwardPdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) NBL_CONST_MEMBER_FUNC { - fresnel_type _f = __getOrientedFresnel(fresnel, interaction.getNdotV()); - if (!__checkValid(_f, _sample, interaction, cache)) - return scalar_type(0.0); - - bool isInfinity; - scalar_type _pdf = __pdf(_sample, interaction, cache, isInfinity); - return hlsl::mix(_pdf, scalar_type(0.0), isInfinity); + PdfQuery query = __forwardPdf(_sample, interaction, cache); + return query.pdf; } template, class MicrofacetCache=conditional_t NBL_FUNC_REQUIRES(RequiredInteraction && RequiredMicrofacetCache) - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) NBL_CONST_MEMBER_FUNC + quotient_weight_type quotientAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) NBL_CONST_MEMBER_FUNC { - if (!_sample.isValid()) - return quotient_pdf_type::create(scalar_type(0.0), scalar_type(0.0)); // set pdf=0 when quo=0 because we don't want to give high weight to sampling strategy that yields 0 contribution - - bool isInfinity; - scalar_type _pdf = __pdf(_sample, interaction, cache, isInfinity); - fresnel_type _f = __getOrientedFresnel(fresnel, interaction.getNdotV()); + PdfQuery pdfQuery = __forwardPdf(_sample, interaction, cache); + scalar_type _pdf = pdfQuery.pdf; + if (_pdf == scalar_type(0.0)) + return quotient_weight_type::create(scalar_type(0.0), scalar_type(0.0)); - const bool valid = __checkValid(_f, _sample, interaction, cache); - assert(valid); // expect the generated sample to always be valid, different checks for brdf and btdf + fresnel_type _f = pdfQuery.orientedFresnel; scalar_type G2_over_G1 = scalar_type(1.0); - if (!isInfinity) + if (!hlsl::isinf(_pdf)) { using g2g1_query_type = typename N::g2g1_query_type; g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); @@ -406,11 +430,7 @@ struct SCookTorrance NBL_IF_CONSTEXPR(fresnel_type::ReturnsMonochrome) quo = hlsl::promote(G2_over_G1); else - { - spectral_type reflectance; - const scalar_type scaled_reflectance = __getScaledReflectance(_f, interaction, hlsl::abs(cache.getVdotH()), cache.isTransmission(), reflectance); - quo = reflectance / scaled_reflectance * G2_over_G1; - } + quo = pdfQuery.reflectance / pdfQuery.scaled_reflectance * G2_over_G1; } else { @@ -419,7 +439,7 @@ struct SCookTorrance quo = _f(VdotH) * G2_over_G1; } - return quotient_pdf_type::create(quo, _pdf); + return quotient_weight_type::create(quo, _pdf); } ndf_type ndf; @@ -436,6 +456,7 @@ struct traits > NBL_CONSTEXPR_STATIC_INLINE bool IsMicrofacet = true; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = !__type::IsBSDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = !__type::IsBSDF; + NBL_CONSTEXPR_STATIC_INLINE bool TractablePdf = true; }; } diff --git a/include/nbl/builtin/hlsl/bxdf/base/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/base/lambertian.hlsl index 24f7b49dd2..08c3f967b6 100644 --- a/include/nbl/builtin/hlsl/bxdf/base/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/base/lambertian.hlsl @@ -23,19 +23,25 @@ struct SLambertianBase using this_t = SLambertianBase; BXDF_CONFIG_TYPE_ALIASES(Config); + using random_type = conditional_t; + struct Cache {}; + using isocache_type = Cache; + using anisocache_type = Cache; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = conditional_value::value; - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + value_weight_type evalAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { - return hlsl::promote(_sample.getNdotL(_clamp) * numbers::inv_pi * hlsl::mix(1.0, 0.5, IsBSDF)); + const spectral_type quo = hlsl::promote(_sample.getNdotL(_clamp) * numbers::inv_pi * hlsl::mix(1.0, 0.5, IsBSDF)); + return value_weight_type::create(quo, forwardPdf(_sample, interaction)); } - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + value_weight_type evalAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { - return eval(_sample, interaction.isotropic); + return evalAndWeight(_sample, interaction.isotropic); } template > - enable_if_t generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u) NBL_CONST_MEMBER_FUNC + enable_if_t generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const random_type u, NBL_CONST_REF_ARG(anisocache_type) _cache) NBL_CONST_MEMBER_FUNC { typename sampling::ProjectedHemisphere::cache_type cache; ray_dir_info_type L; @@ -43,7 +49,7 @@ struct SLambertianBase return sample_type::createFromTangentSpace(L, interaction.getFromTangentSpace()); } template > - enable_if_t generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u) NBL_CONST_MEMBER_FUNC + enable_if_t generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const random_type u, NBL_REF_ARG(anisocache_type) _cache) NBL_CONST_MEMBER_FUNC { typename sampling::ProjectedSphere::cache_type cache; vector3_type _u = u; @@ -51,44 +57,35 @@ struct SLambertianBase L.setDirection(sampling::ProjectedSphere::generate(_u, cache)); return sample_type::createFromTangentSpace(L, interaction.getFromTangentSpace()); } - template > - enable_if_t generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u) NBL_CONST_MEMBER_FUNC - { - return generate(anisotropic_interaction_type::create(interaction), u); - } - template > - enable_if_t generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector3_type u) NBL_CONST_MEMBER_FUNC + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const random_type u, NBL_REF_ARG(isocache_type) _cache) NBL_CONST_MEMBER_FUNC { - return generate(anisotropic_interaction_type::create(interaction), u); + return generate(anisotropic_interaction_type::create(interaction), u, _cache); } - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + scalar_type forwardPdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { NBL_IF_CONSTEXPR (IsBSDF) return sampling::ProjectedSphere::backwardPdf(vector(0, 0, _sample.getNdotL(_clamp))); else return sampling::ProjectedHemisphere::backwardPdf(vector(0, 0, _sample.getNdotL(_clamp))); } - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + scalar_type forwardPdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { - return pdf(_sample, interaction.isotropic); + return forwardPdf(_sample, interaction.isotropic); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + quotient_weight_type quotientAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) _cache) NBL_CONST_MEMBER_FUNC { - // only z component matters: ProjectedHemisphere::forwardPdf reads v.z - const vector3_type L = vector3_type(0, 0, _sample.getNdotL(_clamp)); - typename sampling::ProjectedHemisphere::cache_type cache; scalar_type p; NBL_IF_CONSTEXPR (IsBSDF) - p = sampling::ProjectedSphere::forwardPdf(L, cache); + p = sampling::ProjectedSphere::backwardPdf(vector(0, 0, _sample.getNdotL(_clamp))); else - p = sampling::ProjectedHemisphere::forwardPdf(L, cache); - return quotient_pdf_type::create(scalar_type(1.0), p); + p = sampling::ProjectedHemisphere::backwardPdf(vector(0, 0, _sample.getNdotL(_clamp))); + return quotient_weight_type::create(scalar_type(1.0), p); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + quotient_weight_type quotientAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) _cache) NBL_CONST_MEMBER_FUNC { - return quotient_and_pdf(_sample, interaction.isotropic); + return quotientAndWeight(_sample, interaction.isotropic, _cache); } }; diff --git a/include/nbl/builtin/hlsl/bxdf/base/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/base/oren_nayar.hlsl index 6412dc0fca..b250c7ed4a 100644 --- a/include/nbl/builtin/hlsl/bxdf/base/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/base/oren_nayar.hlsl @@ -23,6 +23,11 @@ struct SOrenNayarBase using this_t = SOrenNayarBase; BXDF_CONFIG_TYPE_ALIASES(Config); + using random_type = conditional_t; + struct Cache {}; + using isocache_type = Cache; + using anisocache_type = Cache; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = conditional_value::value; struct SCreationParams @@ -58,19 +63,19 @@ struct SOrenNayarBase return hlsl::promote(NdotL * numbers::inv_pi * hlsl::mix(1.0, 0.5, IsBSDF) * __rec_pi_factored_out_wo_clamps(query.getVdotL(), NdotL, interaction.getNdotV(_clamp))); } - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + value_weight_type evalAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { SQuery query; query.VdotL = hlsl::dot(interaction.getV().getDirection(), _sample.getL().getDirection()); - return __eval(query, _sample, interaction); + return value_weight_type::create(__eval(query, _sample, interaction), forwardPdf(_sample, interaction)); } - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + value_weight_type evalAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { - return eval(_sample, interaction.isotropic); + return evalAndWeight(_sample, interaction.isotropic); } template > - enable_if_t generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u) NBL_CONST_MEMBER_FUNC + enable_if_t generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const random_type u, NBL_REF_ARG(anisocache_type) _cache) NBL_CONST_MEMBER_FUNC { typename sampling::ProjectedHemisphere::cache_type cache; ray_dir_info_type L; @@ -78,7 +83,7 @@ struct SOrenNayarBase return sample_type::createFromTangentSpace(L, interaction.getFromTangentSpace()); } template > - enable_if_t generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u) NBL_CONST_MEMBER_FUNC + enable_if_t generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const random_type u, NBL_REF_ARG(anisocache_type) _cache) NBL_CONST_MEMBER_FUNC { typename sampling::ProjectedSphere::cache_type cache; vector3_type _u = u; @@ -86,45 +91,39 @@ struct SOrenNayarBase L.setDirection(sampling::ProjectedSphere::generate(_u, cache)); return sample_type::createFromTangentSpace(L, interaction.getFromTangentSpace()); } - template > - enable_if_t generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u) NBL_CONST_MEMBER_FUNC - { - return generate(anisotropic_interaction_type::create(interaction), u); - } - template > - enable_if_t generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector3_type u) NBL_CONST_MEMBER_FUNC + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const random_type u, NBL_REF_ARG(isocache_type) _cache) NBL_CONST_MEMBER_FUNC { - return generate(anisotropic_interaction_type::create(interaction), u); + return generate(anisotropic_interaction_type::create(interaction), u, _cache); } - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + scalar_type forwardPdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { if (IsBSDF) return sampling::ProjectedSphere::backwardPdf(vector(0, 0, _sample.getNdotL(_clamp))); else return sampling::ProjectedHemisphere::backwardPdf(vector(0, 0, _sample.getNdotL(_clamp))); } - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + scalar_type forwardPdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { - return pdf(_sample, interaction.isotropic); + return forwardPdf(_sample, interaction.isotropic); } template - quotient_pdf_type __quotient_and_pdf(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + quotient_weight_type __quotientAndWeight(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { - scalar_type _pdf = pdf(_sample, interaction); + scalar_type _pdf = forwardPdf(_sample, interaction); scalar_type q = __rec_pi_factored_out_wo_clamps(query.getVdotL(), _sample.getNdotL(_clamp), interaction.getNdotV(_clamp)); - return quotient_pdf_type::create(q, _pdf); + return quotient_weight_type::create(q, _pdf); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + quotient_weight_type quotientAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) _cache) NBL_CONST_MEMBER_FUNC { SQuery query; query.VdotL = hlsl::dot(interaction.getV().getDirection(), _sample.getL().getDirection()); - return __quotient_and_pdf(query, _sample, interaction); + return __quotientAndWeight(query, _sample, interaction); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + quotient_weight_type quotientAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) _cache) NBL_CONST_MEMBER_FUNC { - return quotient_and_pdf(_sample, interaction.isotropic); + return quotientAndWeight(_sample, interaction.isotropic, _cache); } scalar_type A2; diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index c114222c7c..54e4a1b145 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -15,6 +15,7 @@ #include "nbl/builtin/hlsl/cpp_compat/promote.hlsl" #include "nbl/builtin/hlsl/bxdf/fresnel.hlsl" #include "nbl/builtin/hlsl/sampling/quotient_and_pdf.hlsl" +#include "nbl/builtin/hlsl/sampling/value_and_weight.hlsl" #include "nbl/builtin/hlsl/vector_utils/vector_traits.hlsl" namespace nbl @@ -889,7 +890,6 @@ namespace bxdf_concepts { namespace impl { - #define NBL_CONCEPT_NAME bxdf_common_typdefs #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) #define NBL_CONCEPT_TPLT_PRM_NAMES (T) @@ -900,31 +900,41 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::anisotropic_interaction_type)) ((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::anisocache_type)) ((NBL_CONCEPT_REQ_TYPE)(T::spectral_type)) - ((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::quotient_weight_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::value_weight_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::random_type)) ); #undef bxdf #include +template +NBL_BOOL_CONCEPT VecDim2OrMore = vector_traits::Dimension >= 2; +template +NBL_BOOL_CONCEPT VecDim3OrMore = vector_traits::Dimension >= 3; + #define NBL_CONCEPT_NAME bxdf_common #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) #define NBL_CONCEPT_TPLT_PRM_NAMES (T) #define NBL_CONCEPT_PARAM_0 (bxdf, T) #define NBL_CONCEPT_PARAM_1 (_sample, typename T::sample_type) #define NBL_CONCEPT_PARAM_2 (aniso, typename T::anisotropic_interaction_type) -NBL_CONCEPT_BEGIN(3) +#define NBL_CONCEPT_PARAM_3 (anisocache, typename T::anisocache_type) +NBL_CONCEPT_BEGIN(4) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +#define anisocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(bxdf_common_typdefs, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.eval(_sample, aniso)), ::nbl::hlsl::is_same_v, typename T::spectral_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.pdf(_sample, aniso)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(_sample, aniso)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.evalAndWeight(_sample, aniso)), ::nbl::hlsl::is_same_v, typename T::value_weight_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotientAndWeight(_sample, aniso, anisocache)), ::nbl::hlsl::is_same_v, typename T::quotient_weight_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(LightSample, typename T::sample_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(concepts::FloatingPointLikeVectorial, typename T::spectral_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Anisotropic, typename T::anisotropic_interaction_type)) ); +#undef anisocache #undef aniso #undef _sample #undef bxdf @@ -936,19 +946,79 @@ NBL_CONCEPT_END( #define NBL_CONCEPT_PARAM_0 (bxdf, T) #define NBL_CONCEPT_PARAM_1 (_sample, typename T::sample_type) #define NBL_CONCEPT_PARAM_2 (iso, typename T::isotropic_interaction_type) -NBL_CONCEPT_BEGIN(3) +#define NBL_CONCEPT_PARAM_3 (isocache, typename T::isocache_type) +NBL_CONCEPT_BEGIN(4) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +#define isocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(bxdf_common, T)) ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_interaction_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.eval(_sample, iso)), ::nbl::hlsl::is_same_v, typename T::spectral_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.pdf(_sample, iso)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(_sample, iso)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(concepts::FloatingPointLikeVectorial, typename T::spectral_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::isocache_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.evalAndWeight(_sample, iso)), ::nbl::hlsl::is_same_v, typename T::value_weight_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotientAndWeight(_sample, iso, isocache)), ::nbl::hlsl::is_same_v, typename T::quotient_weight_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Isotropic, typename T::isotropic_interaction_type)) ); +#undef isocache +#undef iso +#undef _sample +#undef bxdf +#include + +#define NBL_CONCEPT_NAME microfacet_bxdf_common +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (bxdf, T) +#define NBL_CONCEPT_PARAM_1 (_sample, typename T::sample_type) +#define NBL_CONCEPT_PARAM_2 (aniso, typename T::anisotropic_interaction_type) +#define NBL_CONCEPT_PARAM_3 (microfacetCache, typename T::cache_type) +#define NBL_CONCEPT_PARAM_4 (anisocache, typename T::anisocache_type) +NBL_CONCEPT_BEGIN(5) +#define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +#define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 +#define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +#define microfacetCache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 +#define anisocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_TYPE)(T::cache_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(bxdf_common, T)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(AnisotropicMicrofacetCache, typename T::anisocache_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.evalAndWeight(_sample, aniso, anisocache)), ::nbl::hlsl::is_same_v, typename T::value_weight_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.evalAndWeight(_sample, aniso, microfacetCache)), ::nbl::hlsl::is_same_v, typename T::value_weight_type)) +); +#undef anisocache +#undef microfacetCache +#undef aniso +#undef _sample +#undef bxdf +#include + +#define NBL_CONCEPT_NAME microfacet_iso_bxdf_common +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (bxdf, T) +#define NBL_CONCEPT_PARAM_1 (_sample, typename T::sample_type) +#define NBL_CONCEPT_PARAM_2 (iso, typename T::isotropic_interaction_type) +#define NBL_CONCEPT_PARAM_3 (microfacetCache, typename T::cache_type) +#define NBL_CONCEPT_PARAM_4 (isocache, typename T::isocache_type) +NBL_CONCEPT_BEGIN(5) +#define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +#define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 +#define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +#define microfacetCache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 +#define isocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_TYPE)(T::cache_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(iso_bxdf_common, T)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(microfacet_bxdf_common, T)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(AnisotropicMicrofacetCache, typename T::anisocache_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(CreatableIsotropicMicrofacetCache, typename T::isocache_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.evalAndWeight(_sample, iso, isocache)), ::nbl::hlsl::is_same_v, typename T::value_weight_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.evalAndWeight(_sample, iso, microfacetCache)), ::nbl::hlsl::is_same_v, typename T::value_weight_type)) +); +#undef isocache +#undef microfacetCache #undef iso #undef _sample #undef bxdf @@ -960,15 +1030,19 @@ NBL_CONCEPT_END( #define NBL_CONCEPT_TPLT_PRM_NAMES (T) #define NBL_CONCEPT_PARAM_0 (bxdf, T) #define NBL_CONCEPT_PARAM_1 (aniso, typename T::anisotropic_interaction_type) -#define NBL_CONCEPT_PARAM_2 (u, vector) -NBL_CONCEPT_BEGIN(3) +#define NBL_CONCEPT_PARAM_2 (u, typename T::random_type) +#define NBL_CONCEPT_PARAM_3 (anisocache, typename T::anisocache_type) +NBL_CONCEPT_BEGIN(4) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define u NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +#define anisocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(impl::bxdf_common, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(aniso,u)), ::nbl::hlsl::is_same_v, typename T::sample_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(impl::VecDim2OrMore, typename T::random_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(aniso,u,anisocache)), ::nbl::hlsl::is_same_v, typename T::sample_type)) ); +#undef anisocache #undef u #undef aniso #undef bxdf @@ -979,15 +1053,19 @@ NBL_CONCEPT_END( #define NBL_CONCEPT_TPLT_PRM_NAMES (T) #define NBL_CONCEPT_PARAM_0 (bxdf, T) #define NBL_CONCEPT_PARAM_1 (aniso, typename T::anisotropic_interaction_type) -#define NBL_CONCEPT_PARAM_2 (u, vector) -NBL_CONCEPT_BEGIN(3) +#define NBL_CONCEPT_PARAM_2 (u, typename T::random_type) +#define NBL_CONCEPT_PARAM_3 (anisocache, typename T::anisocache_type) +NBL_CONCEPT_BEGIN(4) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define u NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +#define anisocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(impl::bxdf_common, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(aniso,u)), ::nbl::hlsl::is_same_v, typename T::sample_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(impl::VecDim3OrMore, typename T::random_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(aniso,u,anisocache)), ::nbl::hlsl::is_same_v, typename T::sample_type)) ); +#undef anisocache #undef u #undef aniso #undef bxdf @@ -998,15 +1076,19 @@ NBL_CONCEPT_END( #define NBL_CONCEPT_TPLT_PRM_NAMES (T) #define NBL_CONCEPT_PARAM_0 (bxdf, T) #define NBL_CONCEPT_PARAM_1 (iso, typename T::isotropic_interaction_type) -#define NBL_CONCEPT_PARAM_2 (u, vector) -NBL_CONCEPT_BEGIN(3) +#define NBL_CONCEPT_PARAM_2 (u, typename T::random_type) +#define NBL_CONCEPT_PARAM_3 (isocache, typename T::isocache_type) +NBL_CONCEPT_BEGIN(4) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define u NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +#define isocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(impl::iso_bxdf_common, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(iso,u)), ::nbl::hlsl::is_same_v, typename T::sample_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(impl::VecDim2OrMore, typename T::random_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(iso,u,isocache)), ::nbl::hlsl::is_same_v, typename T::sample_type)) ); +#undef isocache #undef u #undef iso #undef bxdf @@ -1017,15 +1099,19 @@ NBL_CONCEPT_END( #define NBL_CONCEPT_TPLT_PRM_NAMES (T) #define NBL_CONCEPT_PARAM_0 (bxdf, T) #define NBL_CONCEPT_PARAM_1 (iso, typename T::isotropic_interaction_type) -#define NBL_CONCEPT_PARAM_2 (u, vector) -NBL_CONCEPT_BEGIN(3) +#define NBL_CONCEPT_PARAM_2 (u, typename T::random_type) +#define NBL_CONCEPT_PARAM_3 (isocache, typename T::isocache_type) +NBL_CONCEPT_BEGIN(4) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define u NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +#define isocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(impl::iso_bxdf_common, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(iso,u)), ::nbl::hlsl::is_same_v, typename T::sample_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(impl::VecDim3OrMore, typename T::random_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(iso,u,isocache)), ::nbl::hlsl::is_same_v, typename T::sample_type)) ); +#undef isocache #undef u #undef iso #undef bxdf @@ -1036,73 +1122,12 @@ NBL_BOOL_CONCEPT BxDF = BRDF || BSDF; template NBL_BOOL_CONCEPT IsotropicBxDF = IsotropicBRDF || IsotropicBSDF; - -namespace impl -{ -#define NBL_CONCEPT_NAME microfacet_bxdf_common -#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) -#define NBL_CONCEPT_TPLT_PRM_NAMES (T) -#define NBL_CONCEPT_PARAM_0 (bxdf, T) -#define NBL_CONCEPT_PARAM_1 (_sample, typename T::sample_type) -#define NBL_CONCEPT_PARAM_2 (aniso, typename T::anisotropic_interaction_type) -#define NBL_CONCEPT_PARAM_3 (anisocache, typename T::anisocache_type) -NBL_CONCEPT_BEGIN(4) -#define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 -#define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 -#define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 -#define anisocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 -NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(bxdf_common_typdefs, T)) - ((NBL_CONCEPT_REQ_TYPE)(T::anisocache_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.eval(_sample, aniso, anisocache)), ::nbl::hlsl::is_same_v, typename T::spectral_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.pdf(_sample, aniso, anisocache)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(_sample, aniso, anisocache)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(LightSample, typename T::sample_type)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(concepts::FloatingPointLikeVectorial, typename T::spectral_type)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Anisotropic, typename T::anisotropic_interaction_type)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(AnisotropicMicrofacetCache, typename T::anisocache_type)) -); -#undef anisocache -#undef aniso -#undef _sample -#undef bxdf -#include - -#define NBL_CONCEPT_NAME iso_microfacet_bxdf_common -#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) -#define NBL_CONCEPT_TPLT_PRM_NAMES (T) -#define NBL_CONCEPT_PARAM_0 (bxdf, T) -#define NBL_CONCEPT_PARAM_1 (_sample, typename T::sample_type) -#define NBL_CONCEPT_PARAM_2 (iso, typename T::isotropic_interaction_type) -#define NBL_CONCEPT_PARAM_3 (isocache, typename T::isocache_type) -NBL_CONCEPT_BEGIN(4) -#define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 -#define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 -#define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 -#define isocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 -NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(microfacet_bxdf_common, T)) - ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_interaction_type)) - ((NBL_CONCEPT_REQ_TYPE)(T::isocache_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.eval(_sample, iso, isocache)), ::nbl::hlsl::is_same_v, typename T::spectral_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.pdf(_sample, iso, isocache)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(_sample, iso, isocache)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Isotropic, typename T::isotropic_interaction_type)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(CreatableIsotropicMicrofacetCache, typename T::isocache_type)) -); -#undef isocache -#undef iso -#undef _sample -#undef bxdf -#include -} - #define NBL_CONCEPT_NAME MicrofacetBRDF #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) #define NBL_CONCEPT_TPLT_PRM_NAMES (T) #define NBL_CONCEPT_PARAM_0 (bxdf, T) #define NBL_CONCEPT_PARAM_1 (aniso, typename T::anisotropic_interaction_type) -#define NBL_CONCEPT_PARAM_2 (u, vector) +#define NBL_CONCEPT_PARAM_2 (u, typename T::random_type) #define NBL_CONCEPT_PARAM_3 (anisocache, typename T::anisocache_type) NBL_CONCEPT_BEGIN(4) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 @@ -1111,6 +1136,7 @@ NBL_CONCEPT_BEGIN(4) #define anisocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(impl::microfacet_bxdf_common, T)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(impl::VecDim2OrMore, typename T::random_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(aniso,u,anisocache)), ::nbl::hlsl::is_same_v, typename T::sample_type)) ); #undef anisocache @@ -1124,7 +1150,7 @@ NBL_CONCEPT_END( #define NBL_CONCEPT_TPLT_PRM_NAMES (T) #define NBL_CONCEPT_PARAM_0 (bxdf, T) #define NBL_CONCEPT_PARAM_1 (aniso, typename T::anisotropic_interaction_type) -#define NBL_CONCEPT_PARAM_2 (u, vector) +#define NBL_CONCEPT_PARAM_2 (u, typename T::random_type) #define NBL_CONCEPT_PARAM_3 (anisocache, typename T::anisocache_type) NBL_CONCEPT_BEGIN(4) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 @@ -1133,6 +1159,7 @@ NBL_CONCEPT_BEGIN(4) #define anisocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(impl::microfacet_bxdf_common, T)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(impl::VecDim3OrMore, typename T::random_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(aniso,u,anisocache)), ::nbl::hlsl::is_same_v, typename T::sample_type)) ); #undef anisocache @@ -1146,7 +1173,7 @@ NBL_CONCEPT_END( #define NBL_CONCEPT_TPLT_PRM_NAMES (T) #define NBL_CONCEPT_PARAM_0 (bxdf, T) #define NBL_CONCEPT_PARAM_1 (iso, typename T::isotropic_interaction_type) -#define NBL_CONCEPT_PARAM_2 (u, vector) +#define NBL_CONCEPT_PARAM_2 (u, typename T::random_type) #define NBL_CONCEPT_PARAM_3 (isocache, typename T::isocache_type) NBL_CONCEPT_BEGIN(4) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 @@ -1154,7 +1181,8 @@ NBL_CONCEPT_BEGIN(4) #define u NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 #define isocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(impl::iso_microfacet_bxdf_common, T)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(impl::microfacet_iso_bxdf_common, T)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(impl::VecDim2OrMore, typename T::random_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(iso,u,isocache)), ::nbl::hlsl::is_same_v, typename T::sample_type)) ); #undef isocache @@ -1168,7 +1196,7 @@ NBL_CONCEPT_END( #define NBL_CONCEPT_TPLT_PRM_NAMES (T) #define NBL_CONCEPT_PARAM_0 (bxdf, T) #define NBL_CONCEPT_PARAM_1 (iso, typename T::isotropic_interaction_type) -#define NBL_CONCEPT_PARAM_2 (u, vector) +#define NBL_CONCEPT_PARAM_2 (u, typename T::random_type) #define NBL_CONCEPT_PARAM_3 (isocache, typename T::isocache_type) NBL_CONCEPT_BEGIN(4) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 @@ -1176,7 +1204,8 @@ NBL_CONCEPT_BEGIN(4) #define u NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 #define isocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(impl::iso_microfacet_bxdf_common, T)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(impl::microfacet_iso_bxdf_common, T)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(impl::VecDim3OrMore, typename T::random_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(iso,u,isocache)), ::nbl::hlsl::is_same_v, typename T::sample_type)) ); #undef isocache diff --git a/include/nbl/builtin/hlsl/bxdf/config.hlsl b/include/nbl/builtin/hlsl/bxdf/config.hlsl index 0d49d45b3f..25ddf20881 100644 --- a/include/nbl/builtin/hlsl/bxdf/config.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/config.hlsl @@ -31,7 +31,8 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::anisotropic_interaction_type)) ((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) ((NBL_CONCEPT_REQ_TYPE)(T::spectral_type)) - ((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::quotient_weight_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::value_weight_type)) ); #undef conf #include @@ -75,7 +76,8 @@ struct SConfiguration using anisotropic_interaction_type = surface_interactions::SAnisotropic; using sample_type = LS; using spectral_type = Spectrum; - using quotient_pdf_type = sampling::quotient_and_pdf; + using quotient_weight_type = sampling::quotient_and_pdf; + using value_weight_type = sampling::value_and_weight; }; #define CONF_ANISO LightSample && surface_interactions::Anisotropic && concepts::FloatingPointLikeVectorial @@ -97,7 +99,8 @@ struct SConfiguration using anisotropic_interaction_type = Interaction; using sample_type = LS; using spectral_type = Spectrum; - using quotient_pdf_type = sampling::quotient_and_pdf; + using quotient_weight_type = sampling::quotient_and_pdf; + using value_weight_type = sampling::value_and_weight; }; template @@ -149,7 +152,8 @@ NBL_BXDF_CONFIG_ALIAS(isotropic_interaction_type, Config);\ NBL_BXDF_CONFIG_ALIAS(anisotropic_interaction_type, Config);\ NBL_BXDF_CONFIG_ALIAS(sample_type, Config);\ NBL_BXDF_CONFIG_ALIAS(spectral_type, Config);\ -NBL_BXDF_CONFIG_ALIAS(quotient_pdf_type, Config);\ +NBL_BXDF_CONFIG_ALIAS(quotient_weight_type, Config);\ +NBL_BXDF_CONFIG_ALIAS(value_weight_type, Config);\ #define MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config) BXDF_CONFIG_TYPE_ALIASES(Config);\ NBL_BXDF_CONFIG_ALIAS(matrix3x3_type, Config);\ diff --git a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl index dcac34188c..bcd39a759e 100644 --- a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl @@ -667,7 +667,7 @@ struct iridescent_base template T __call(const vector_type _iork3, const vector_type etak23, const scalar_type clampedCosTheta) NBL_CONST_MEMBER_FUNC { - return impl::iridescent_helper::template __call(D, ior1, ior2, ior3, _iork3, + return impl::iridescent_helper::template __call(D, ior1, ior2, ior3, iork3, eta12, eta23, etak23, clampedCosTheta); } diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index 2c5f0c819c..a79eb65f55 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -226,8 +226,10 @@ struct GGX enable_if_t createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) NBL_CONST_MEMBER_FUNC { dg1_query_type dg1_query; - bool dummy; - dg1_query.ndf = __ndf_base.template D(cache, dummy); + bool isInfinity; + dg1_query.ndf = __ndf_base.template D(cache, isInfinity); + if (isInfinity) + return dg1_query; scalar_type clampedNdotV = interaction.getNdotV(BxDFClampMode::BCM_ABS); dg1_query.G1_over_2NdotV = G1_wo_numerator(clampedNdotV, __ndf_base.devsh_part(interaction.getNdotV2())); return dg1_query; @@ -244,8 +246,10 @@ struct GGX enable_if_t createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) NBL_CONST_MEMBER_FUNC { dg1_query_type dg1_query; - bool dummy; - dg1_query.ndf = __ndf_base.template D(cache, dummy); + bool isInfinity; + dg1_query.ndf = __ndf_base.template D(cache, isInfinity); + if (isInfinity) + return dg1_query; scalar_type clampedNdotV = interaction.getNdotV(BxDFClampMode::BCM_ABS); dg1_query.G1_over_2NdotV = G1_wo_numerator(clampedNdotV, __ndf_base.devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2())); return dg1_query; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/delta_distribution.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/delta_distribution.hlsl index 9bf9e16aa9..3ca10587d3 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/delta_distribution.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/delta_distribution.hlsl @@ -23,18 +23,23 @@ struct SDeltaDistribution using this_t = SDeltaDistribution; BXDF_CONFIG_TYPE_ALIASES(Config); + using random_type = vector2_type; + struct Cache {}; + using isocache_type = Cache; + using anisocache_type = Cache; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_MAX; - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + value_weight_type evalAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { - return hlsl::promote(0); + return value_weight_type::create(0.0, 0.0); } - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + value_weight_type evalAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { - return hlsl::promote(0); + return value_weight_type::create(0.0, 0.0); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u) NBL_CONST_MEMBER_FUNC + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const random_type u, NBL_REF_ARG(anisocache_type) _cache) NBL_CONST_MEMBER_FUNC { vector3_type V = interaction.getV().getDirection(); bxdf::Reflect r = bxdf::Reflect::create(V, interaction.getN()); @@ -47,28 +52,28 @@ struct SDeltaDistribution return s; } - sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u) NBL_CONST_MEMBER_FUNC + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const random_type u, NBL_REF_ARG(isocache_type) _cache) NBL_CONST_MEMBER_FUNC { - return generate(anisotropic_interaction_type::create(interaction), u); + return generate(anisotropic_interaction_type::create(interaction), u, _cache); } - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + scalar_type forwardPdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { return 0; } - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + scalar_type forwardPdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { return 0; } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + quotient_weight_type quotientAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) _cache) NBL_CONST_MEMBER_FUNC { const scalar_type _pdf = bit_cast(numeric_limits::infinity); - return quotient_pdf_type::create(1.0, _pdf); + return quotient_weight_type::create(1.0, _pdf); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + quotient_weight_type quotientAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) _cache) NBL_CONST_MEMBER_FUNC { - return quotient_and_pdf(_sample, interaction.isotropic); + return quotientAndWeight(_sample, interaction.isotropic, _cache); } }; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl index 0e0e6bebb0..da0411eb4d 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl @@ -28,6 +28,7 @@ struct traits > NBL_CONSTEXPR_STATIC_INLINE bool IsMicrofacet = false; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = false; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; + NBL_CONSTEXPR_STATIC_INLINE bool TractablePdf = true; }; } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl index df0e6ebc19..4ea6000419 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl @@ -28,6 +28,7 @@ struct traits > NBL_CONSTEXPR_STATIC_INLINE bool IsMicrofacet = false; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; + NBL_CONSTEXPR_STATIC_INLINE bool TractablePdf = true; }; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/delta_distribution.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/delta_distribution.hlsl index 7ec41aeed5..59b58bfedf 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/delta_distribution.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/delta_distribution.hlsl @@ -23,18 +23,23 @@ struct SDeltaDistribution using this_t = SDeltaDistribution; BXDF_CONFIG_TYPE_ALIASES(Config); + using random_type = vector2_type; + struct Cache {}; + using isocache_type = Cache; + using anisocache_type = Cache; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + value_weight_type evalAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { - return hlsl::promote(0); + return value_weight_type::create(0.0, 0.0); } - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + value_weight_type evalAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { - return hlsl::promote(0); + return value_weight_type::create(0.0, 0.0); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u) NBL_CONST_MEMBER_FUNC + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const random_type u, NBL_REF_ARG(anisocache_type) _cache) NBL_CONST_MEMBER_FUNC { ray_dir_info_type L = interaction.getV().transmit(); sample_type s = sample_type::create(L, interaction.getN()); @@ -44,28 +49,28 @@ struct SDeltaDistribution s.NdotL2 = interaction.getNdotV2(); return s; } - sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u) NBL_CONST_MEMBER_FUNC + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const random_type u, NBL_REF_ARG(isocache_type) _cache) NBL_CONST_MEMBER_FUNC { - return generate(anisotropic_interaction_type::create(interaction), u); + return generate(anisotropic_interaction_type::create(interaction), u, _cache); } - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + scalar_type forwardPdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { return 0; } - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + scalar_type forwardPdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { return 0; } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + quotient_weight_type quotientAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) _cache) NBL_CONST_MEMBER_FUNC { const scalar_type _pdf = bit_cast(numeric_limits::infinity); - return quotient_pdf_type::create(1.0, _pdf); + return quotient_weight_type::create(1.0, _pdf); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + quotient_weight_type quotientAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) _cache) NBL_CONST_MEMBER_FUNC { - return quotient_and_pdf(_sample, interaction.isotropic); + return quotientAndWeight(_sample, interaction.isotropic); } }; @@ -78,6 +83,7 @@ struct traits > NBL_CONSTEXPR_STATIC_INLINE bool IsMicrofacet = false; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = false; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; + NBL_CONSTEXPR_STATIC_INLINE bool TractablePdf = true; }; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl index 6ea67a65fd..0751ead92f 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl @@ -28,6 +28,7 @@ struct traits > NBL_CONSTEXPR_STATIC_INLINE bool IsMicrofacet = false; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = false; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; + NBL_CONSTEXPR_STATIC_INLINE bool TractablePdf = true; }; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/oren_nayar.hlsl index b39d48d2bf..1b224b34e1 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/oren_nayar.hlsl @@ -28,6 +28,7 @@ struct traits > NBL_CONSTEXPR_STATIC_INLINE bool IsMicrofacet = false; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; + NBL_CONSTEXPR_STATIC_INLINE bool TractablePdf = true; }; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index bee202dc8d..bb70e46805 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -24,18 +24,24 @@ struct SSmoothDielectric using this_t = SSmoothDielectric; BXDF_CONFIG_TYPE_ALIASES(Config); + using random_type = vector3_type; + struct Cache {}; + using isocache_type = Cache; + using anisocache_type = Cache; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + // eval and weight return 0 because smooth dielectric/conductor BxDFs are dirac delta distributions, model perfectly specular objects that scatter light to only one outgoing direction + value_weight_type evalAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { - return hlsl::promote(0); + return value_weight_type::create(0.0, 0.0); } - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + value_weight_type evalAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { - return hlsl::promote(0); + return value_weight_type::create(0.0, 0.0); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u) NBL_CONST_MEMBER_FUNC + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(random_type) u, NBL_REF_ARG(anisocache_type) _cache) NBL_CONST_MEMBER_FUNC { const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta.value*orientedEta.value, interaction.getNdotV(_clamp))[0]; @@ -51,29 +57,28 @@ struct SSmoothDielectric ray_dir_info_type L = V.reflectRefract(rr, transmitted, orientedEta.rcp[0]); return sample_type::create(L, interaction.getT(), interaction.getB(), interaction.getN()); } - sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u) NBL_CONST_MEMBER_FUNC + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(random_type) u, NBL_REF_ARG(isocache_type) _cache) NBL_CONST_MEMBER_FUNC { - return generate(anisotropic_interaction_type::create(interaction), u); + return generate(anisotropic_interaction_type::create(interaction), u, _cache); } - // eval and pdf return 0 because smooth dielectric/conductor BxDFs are dirac delta distributions, model perfectly specular objects that scatter light to only one outgoing direction - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + scalar_type forwardPdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { return 0; } - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + scalar_type forwardPdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { return 0; } // smooth BxDFs are isotropic by definition - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + quotient_weight_type quotientAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) _cache) NBL_CONST_MEMBER_FUNC { - return quotient_pdf_type::create(1.0, bit_cast(numeric_limits::infinity)); + return quotient_weight_type::create(1.0, bit_cast(numeric_limits::infinity)); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + quotient_weight_type quotientAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) _cache) NBL_CONST_MEMBER_FUNC { - return quotient_and_pdf(_sample, interaction.isotropic); + return quotientAndWeight(_sample, interaction.isotropic, _cache); } fresnel::OrientedEtas orientedEta; @@ -83,16 +88,12 @@ template; - NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); - NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); - NBL_BXDF_CONFIG_ALIAS(vector3_type, Config); - NBL_BXDF_CONFIG_ALIAS(monochrome_type, Config); - NBL_BXDF_CONFIG_ALIAS(ray_dir_info_type, Config); - NBL_BXDF_CONFIG_ALIAS(isotropic_interaction_type, Config); - NBL_BXDF_CONFIG_ALIAS(anisotropic_interaction_type, Config); - NBL_BXDF_CONFIG_ALIAS(sample_type, Config); - NBL_BXDF_CONFIG_ALIAS(spectral_type, Config); - NBL_BXDF_CONFIG_ALIAS(quotient_pdf_type, Config); + BXDF_CONFIG_TYPE_ALIASES(Config); + + using random_type = vector3_type; + struct Cache {}; + using isocache_type = Cache; + using anisocache_type = Cache; NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; @@ -105,20 +106,20 @@ struct SThinSmoothDielectric return retval; } - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + value_weight_type evalAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { - return hlsl::promote(0); + return value_weight_type::create(0.0, 0.0); } - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + value_weight_type evalAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { - return hlsl::promote(0); + return value_weight_type::create(0.0, 0.0); } // usually `luminosityContributionHint` would be the Rec.709 luma coefficients (the Y row of the RGB to CIE XYZ matrix) // its basically a set of weights that determine // assert(1.0==luminosityContributionHint.r+luminosityContributionHint.g+luminosityContributionHint.b); - // `remainderMetadata` is a variable which the generator function returns byproducts of sample generation that would otherwise have to be redundantly calculated `quotient_and_pdf` - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(spectral_type) remainderMetadata) NBL_CONST_MEMBER_FUNC + // `remainderMetadata` is a variable which the generator function returns byproducts of sample generation that would otherwise have to be redundantly calculated `quotient_and_weight` + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const random_type u, NBL_REF_ARG(spectral_type) remainderMetadata) NBL_CONST_MEMBER_FUNC { // we will only ever intersect from the outside const spectral_type reflectance = fresnel::thinDielectricInfiniteScatter(fresnel(interaction.getNdotV(_clamp))); @@ -140,27 +141,27 @@ struct SThinSmoothDielectric return sample_type::create(L, interaction.getT(), interaction.getB(), N); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u) NBL_CONST_MEMBER_FUNC + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const random_type u, NBL_REF_ARG(anisocache_type) _cache) NBL_CONST_MEMBER_FUNC { vector3_type dummy; return generate(interaction, u, dummy); } - sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector3_type u) NBL_CONST_MEMBER_FUNC + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const random_type u, NBL_REF_ARG(isocache_type) _cache) NBL_CONST_MEMBER_FUNC { - return generate(anisotropic_interaction_type::create(interaction), u); + return generate(anisotropic_interaction_type::create(interaction), u, _cache); } - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + scalar_type forwardPdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { return 0; } - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + scalar_type forwardPdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC { return 0; } // smooth BxDFs are isotropic by definition - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + quotient_weight_type quotientAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) _cache) NBL_CONST_MEMBER_FUNC { const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(interaction.getNdotV(), _sample.getNdotL()); const spectral_type reflectance = fresnel::thinDielectricInfiniteScatter(fresnel(interaction.getNdotV(_clamp))); @@ -169,11 +170,11 @@ struct SThinSmoothDielectric const scalar_type sampleProb = nbl::hlsl::dot(sampleValue,interaction.getLuminosityContributionHint()); const scalar_type _pdf = bit_cast(numeric_limits::infinity); - return quotient_pdf_type::create(sampleValue / sampleProb, _pdf); + return quotient_weight_type::create(sampleValue / sampleProb, _pdf); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) NBL_CONST_MEMBER_FUNC + quotient_weight_type quotientAndWeight(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) _cache) NBL_CONST_MEMBER_FUNC { - return quotient_and_pdf(_sample, interaction.isotropic); + return quotientAndWeight(_sample, interaction.isotropic, _cache); } fresnel::Dielectric fresnel; @@ -188,6 +189,7 @@ struct traits > NBL_CONSTEXPR_STATIC_INLINE bool IsMicrofacet = false; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; + NBL_CONSTEXPR_STATIC_INLINE bool TractablePdf = true; }; template @@ -197,6 +199,7 @@ struct traits > NBL_CONSTEXPR_STATIC_INLINE bool IsMicrofacet = false; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; + NBL_CONSTEXPR_STATIC_INLINE bool TractablePdf = true; }; } diff --git a/include/nbl/builtin/hlsl/path_tracing/concepts.hlsl b/include/nbl/builtin/hlsl/path_tracing/concepts.hlsl index 140a800c81..f0a47efc8f 100644 --- a/include/nbl/builtin/hlsl/path_tracing/concepts.hlsl +++ b/include/nbl/builtin/hlsl/path_tracing/concepts.hlsl @@ -206,17 +206,17 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) ((NBL_CONCEPT_REQ_TYPE)(T::material_id_type)) ((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) - ((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::quotient_weight_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::value_weight_type)) ((NBL_CONCEPT_REQ_TYPE)(T::measure_type)) ((NBL_CONCEPT_REQ_TYPE)(T::anisotropic_interaction_type)) ((NBL_CONCEPT_REQ_TYPE)(T::cache_type)) ((NBL_CONCEPT_REQ_TYPE)(T::bxdfnode_type)) ((NBL_CONCEPT_REQ_TYPE)(T::create_params_t)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(BxdfNode, typename T::bxdfnode_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((matsys.eval(matid, _sample, aniso_inter)), ::nbl::hlsl::is_same_v, typename T::measure_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((matsys.evalAndWeight(matid, _sample, aniso_inter)), ::nbl::hlsl::is_same_v, typename T::value_weight_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((matsys.generate(matid, aniso_inter, u, cache_)), ::nbl::hlsl::is_same_v, typename T::sample_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((matsys.pdf(matid, _sample, aniso_inter)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((matsys.quotient_and_pdf(matid, _sample, aniso_inter, cache_)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((matsys.quotientAndWeight(matid, _sample, aniso_inter, cache_)), ::nbl::hlsl::is_same_v, typename T::quotient_weight_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((matsys.getBxDFNode(matid, aniso_inter)), ::nbl::hlsl::is_same_v, typename T::bxdfnode_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((matsys.hasEmission(matid)), ::nbl::hlsl::is_same_v, bool)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((matsys.setMonochromeEta(matid, cie_y)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) @@ -247,10 +247,10 @@ NBL_CONCEPT_BEGIN(1) NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) - ((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::quotient_weight_type)) ((NBL_CONCEPT_REQ_TYPE)(T::object_handle_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((sqr.getSample()), ::nbl::hlsl::is_same_v, typename T::sample_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((sqr.getQuotientPdf()), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((sqr.getQuotientWeight()), ::nbl::hlsl::is_same_v, typename T::quotient_weight_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((sqr.getT()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((sqr.getLightObjectID()), ::nbl::hlsl::is_same_v, typename T::object_handle_type)) ); @@ -266,17 +266,15 @@ NBL_CONCEPT_END( #define NBL_CONCEPT_PARAM_3 (v, typename T::vector3_type) #define NBL_CONCEPT_PARAM_4 (matSys, impl::DummyMaterialSystem) #define NBL_CONCEPT_PARAM_5 (interaction, typename T::interaction_type) -#define NBL_CONCEPT_PARAM_6 (depth, uint16_t) -#define NBL_CONCEPT_PARAM_7 (scene, typename T::scene_type) -NBL_CONCEPT_BEGIN(8) +#define NBL_CONCEPT_PARAM_6 (scene, typename T::scene_type) +NBL_CONCEPT_BEGIN(7) #define nee NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define ray NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define id NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 #define v NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 #define matSys NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 #define interaction NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 -#define depth NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 -#define scene NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_7 +#define scene NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) @@ -286,19 +284,18 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::ray_type)) ((NBL_CONCEPT_REQ_TYPE)(T::spectral_type)) ((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) - ((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::quotient_weight_type)) ((NBL_CONCEPT_REQ_TYPE)(T::interaction_type)) ((NBL_CONCEPT_REQ_TYPE)(T::sample_quotient_return_type)) ((NBL_CONCEPT_REQ_TYPE)(T::tolerance_method_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(NextEventEstimatorSampleQuotientReturn, typename T::sample_quotient_return_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(Ray, typename T::ray_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((nee.deferred_pdf(scene, id, ray)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((nee.template generate_and_quotient_and_pdf(scene, matSys, v/*origin*/, interaction, v/*xi*/, depth)), ::nbl::hlsl::is_same_v, typename T::sample_quotient_return_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((nee.get_env_light_id()), ::nbl::hlsl::is_same_v, typename T::light_id_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((nee.get_environment_radiance(ray)), ::nbl::hlsl::is_same_v, typename T::spectral_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((nee.deferredWeight(scene, id, ray)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((nee.template generateAndQuotientAndWeight(scene, matSys, v/*origin*/, interaction, v/*xi*/, ray)), ::nbl::hlsl::is_same_v, typename T::sample_quotient_return_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((nee.getEnvLightId()), ::nbl::hlsl::is_same_v, typename T::light_id_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((nee.getEnvRadiance(ray)), ::nbl::hlsl::is_same_v, typename T::spectral_type)) ); #undef scene -#undef depth #undef interaction #undef matSys #undef v diff --git a/include/nbl/builtin/hlsl/path_tracing/unidirectional.hlsl b/include/nbl/builtin/hlsl/path_tracing/unidirectional.hlsl index 3c05b8e52d..3b3bacd05d 100644 --- a/include/nbl/builtin/hlsl/path_tracing/unidirectional.hlsl +++ b/include/nbl/builtin/hlsl/path_tracing/unidirectional.hlsl @@ -44,7 +44,8 @@ struct Unidirectional using bxdfnode_type = typename MaterialSystem::bxdfnode_type; using anisotropic_interaction_type = typename MaterialSystem::anisotropic_interaction_type; using cache_type = typename MaterialSystem::cache_type; - using quotient_pdf_type = typename NextEventEstimator::quotient_pdf_type; + using quotient_weight_type = typename MaterialSystem::quotient_weight_type; + using value_weight_type = typename MaterialSystem::value_weight_type; using tolerance_method_type = typename NextEventEstimator::tolerance_method_type; scalar_type getLuma(NBL_CONST_REF_ARG(vector3_type) col) @@ -67,9 +68,9 @@ struct Unidirectional if (ray.shouldDoMIS() && matLightID.isLight()) { emissive *= ray.getPayloadThroughput(); - const scalar_type pdf = nee.deferred_pdf(scene, lightID, ray); - assert(!hlsl::isinf(pdf)); - emissive *= ray.foundEmissiveMIS(pdf * pdf); + const scalar_type weight = nee.deferredWeight(scene, lightID, ray); + assert(!hlsl::isinf(weight)); + emissive *= ray.foundEmissiveMIS(weight * weight); } ray.addPayloadContribution(emissive); } @@ -92,13 +93,13 @@ struct Unidirectional assert(neeProbability >= 0.0 && neeProbability <= 1.0); if (!partitionRandVariable(eps0.z, rcpChoiceProb)) { - typename nee_type::sample_quotient_return_type ret = nee.template generate_and_quotient_and_pdf( - scene, materialSystem, intersectP, interaction, - eps0, depth + typename nee_type::sample_quotient_return_type ret = nee.template generateAndQuotientAndWeight( + scene, materialSystem, intersectP, + interaction, eps0, ray ); scalar_type t = ret.getT(); sample_type nee_sample = ret.getSample(); - quotient_pdf_type neeContrib = ret.getQuotientPdf(); + quotient_weight_type neeContrib = ret.getQuotientWeight(); // While NEE or other generators are not supposed to pick up Delta lobes by accident, we need the MIS weights to add up to 1 for the non-delta lobes. // So we need to weigh the Delta lobes as if the MIS weight is always 1, but other areas regularly. @@ -106,12 +107,11 @@ struct Unidirectional // This stops a discrepancy in MIS weights and NEE mistakenly trying to add non-delta lobe contributions with a MIS weight > 0 and creating energy from thin air. if (neeContrib.pdf() > scalar_type(0.0)) { - // TODO: we'll need an `eval_and_mis_weight` and `quotient_and_mis_weight` - const scalar_type bsdf_pdf = materialSystem.pdf(matID, nee_sample, interaction); - neeContrib._quotient *= materialSystem.eval(matID, nee_sample, interaction) * rcpChoiceProb; + value_weight_type bsdfContrib = materialSystem.evalAndWeight(matID, nee_sample, interaction); + neeContrib._quotient *= bsdfContrib.value() * rcpChoiceProb; if (neeContrib.pdf() < bit_cast(numeric_limits::infinity)) { - const scalar_type otherGenOverLightAndChoice = bsdf_pdf * rcpChoiceProb / neeContrib.pdf(); + const scalar_type otherGenOverLightAndChoice = bsdfContrib.weight() * rcpChoiceProb / neeContrib.pdf(); neeContrib._quotient /= 1.f + otherGenOverLightAndChoice * otherGenOverLightAndChoice; // balance heuristic } @@ -139,9 +139,9 @@ struct Unidirectional return false; // the value of the bsdf divided by the probability of the sample being generated - quotient_pdf_type bsdf_quotient_pdf = materialSystem.quotient_and_pdf(matID, bsdf_sample, interaction, _cache); - throughput *= bsdf_quotient_pdf.quotient(); - bxdfPdf = bsdf_quotient_pdf.pdf(); + quotient_weight_type bsdf_quotient_weight = materialSystem.quotientAndWeight(matID, bsdf_sample, interaction, _cache); + throughput *= bsdf_quotient_weight.quotient(); + bxdfPdf = bsdf_quotient_weight.pdf(); bxdfSample = bsdf_sample.getL().getDirection(); } @@ -168,12 +168,12 @@ struct Unidirectional void missProgram(NBL_REF_ARG(ray_type) ray) { - measure_type finalContribution = nee.get_environment_radiance(ray); - typename nee_type::light_id_type env_light_id = nee.get_env_light_id(); - const scalar_type pdf = nee.deferred_pdf(scene, env_light_id, ray); + measure_type finalContribution = nee.getEnvRadiance(ray); + typename nee_type::light_id_type env_light_id = nee.getEnvLightId(); + const scalar_type weight = nee.deferredWeight(scene, env_light_id, ray); finalContribution *= ray.getPayloadThroughput(); - if (pdf > scalar_type(0.0)) - finalContribution *= ray.foundEmissiveMIS(pdf * pdf); + if (weight > scalar_type(0.0)) + finalContribution *= ray.foundEmissiveMIS(weight * weight); ray.addPayloadContribution(finalContribution); } @@ -187,6 +187,7 @@ struct Unidirectional for (uint16_t d = 1; (d <= maxDepth) && continuePath; d++) { ray.setT(numeric_limits::max); + ray.setDepth(d); closest_hit_type intersection = intersector_type::traceClosestHit(scene, ray); notMissed = intersection.foundHit(); diff --git a/include/nbl/builtin/hlsl/sampling/value_and_pdf.hlsl b/include/nbl/builtin/hlsl/sampling/value_and_pdf.hlsl index 8c54d34c5e..ac7e448295 100644 --- a/include/nbl/builtin/hlsl/sampling/value_and_pdf.hlsl +++ b/include/nbl/builtin/hlsl/sampling/value_and_pdf.hlsl @@ -5,6 +5,8 @@ #ifndef _NBL_BUILTIN_HLSL_SAMPLING_VALUE_AND_PDF_INCLUDED_ #define _NBL_BUILTIN_HLSL_SAMPLING_VALUE_AND_PDF_INCLUDED_ +#include "nbl/builtin/hlsl/sampling/value_and_weight.hlsl" + namespace nbl { namespace hlsl @@ -16,40 +18,40 @@ template struct value_and_rcpPdf { using this_t = value_and_rcpPdf; + using base_t = value_and_rcpWeight; static this_t create(const V _value, const P _rcpPdf) { this_t retval; - retval._value = _value; - retval._rcpPdf = _rcpPdf; + retval._base._value = _value; + retval._base._rcpWeight = _rcpPdf; return retval; } - V value() NBL_CONST_MEMBER_FUNC { return _value; } - P rcpPdf() NBL_CONST_MEMBER_FUNC { return _rcpPdf; } + V value() { return _base._value; } + P rcpPdf() { return _base._rcpWeight; } - V _value; - P _rcpPdf; + base_t _base; }; template struct value_and_pdf { using this_t = value_and_pdf; + using base_t = value_and_weight; static this_t create(const V _value, const P _pdf) { this_t retval; - retval._value = _value; - retval._pdf = _pdf; + retval._base._value = _value; + retval._base._weight = _pdf; return retval; } - V value() NBL_CONST_MEMBER_FUNC { return _value; } - P pdf() NBL_CONST_MEMBER_FUNC { return _pdf; } + V value() { return _base._value; } + P pdf() { return _base._weight; } - V _value; - P _pdf; + base_t _base; }; // Returned by TractableSampler::generate, codomain sample bundled with its rcpPdf diff --git a/include/nbl/builtin/hlsl/sampling/value_and_weight.hlsl b/include/nbl/builtin/hlsl/sampling/value_and_weight.hlsl new file mode 100644 index 0000000000..19711174c5 --- /dev/null +++ b/include/nbl/builtin/hlsl/sampling/value_and_weight.hlsl @@ -0,0 +1,89 @@ +// Copyright (C) 2018-2026 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h + +#ifndef _NBL_BUILTIN_HLSL_SAMPLING_VALUE_AND_WEIGHT_INCLUDED_ +#define _NBL_BUILTIN_HLSL_SAMPLING_VALUE_AND_WEIGHT_INCLUDED_ + +namespace nbl +{ +namespace hlsl +{ +namespace sampling +{ + +template +struct value_and_rcpWeight +{ + using this_t = value_and_rcpWeight; + using scalar_v = typename vector_traits::scalar_type; + + static this_t create(const V _value, const W _rcpWeight) + { + this_t retval; + retval._value = _value; + retval._rcpWeight = _rcpWeight; + return retval; + } + + static this_t create(const scalar_v _value, const W _rcpWeight) + { + this_t retval; + retval._value = hlsl::promote(_value); + retval._rcpWeight = _rcpWeight; + return retval; + } + + V value() { return _value; } + W rcpWeight() { return _rcpWeight; } + + V _value; + W _rcpWeight; +}; + +template +struct value_and_weight +{ + using this_t = value_and_weight; + using scalar_v = typename vector_traits::scalar_type; + + static this_t create(const V _value, const W _weight) + { + this_t retval; + retval._value = _value; + retval._weight = _weight; + return retval; + } + + static this_t create(const scalar_v _value, const W _weight) + { + this_t retval; + retval._value = hlsl::promote(_value); + retval._weight = _weight; + return retval; + } + + V value() { return _value; } + W weight() { return _weight; } + + V _value; + W _weight; +}; + +template +using codomain_and_rcpWeight = value_and_rcpWeight; + +template +using codomain_and_weight = value_and_weight; + +template +using domain_and_rcpWeight = value_and_rcpWeight; + +template +using domain_and_weight = value_and_weight; + +} // namespace sampling +} // namespace hlsl +} // namespace nbl + +#endif diff --git a/src/nbl/builtin/CMakeLists.txt b/src/nbl/builtin/CMakeLists.txt index 9e6dcaa2f9..d35f50b2d4 100644 --- a/src/nbl/builtin/CMakeLists.txt +++ b/src/nbl/builtin/CMakeLists.txt @@ -284,6 +284,7 @@ LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/sampling/projected_spherical_ LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/sampling/cos_weighted_spheres.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/sampling/quotient_and_pdf.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/sampling/value_and_pdf.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/sampling/value_and_weight.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/sampling/concepts.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/sampling/uniform_spheres.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/sampling/alias_table.hlsl")