From 521854570647924023c715282d395f66c3314545 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 4 Sep 2025 10:46:43 +0700 Subject: [PATCH 01/38] changes to dual measure quant, old stuff commented out for now --- .../ndf/microfacet_to_light_transform.hlsl | 48 ++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl index d4118aaec4..f53fcca645 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl @@ -23,6 +23,52 @@ enum MicrofacetTransformTypes : uint16_t MTT_REFLECT_REFRACT = 0b11 }; + +template +struct SDualMeasureQuant +{ + using value_type = T; + + T microfacetMeasure; + T projectedLightMeasure; +}; + +namespace impl +{ +template +struct createDualMeasureQuantity_helper +{ + using scalar_type = vector_traits::scalar_type; + + static SDualMeasureQuant __call(const T microfacetMeasure, scalar_type clampedNdotV, scalar_type clampedNdotL, scalar_type VdotHLdotH, scalar_type VdotH_etaLdotH) + { + SDualMeasureQuant retval; + retval.microfacetMeasure = microfacetMeasure; + // do constexpr booleans first so optimizer picks up this and short circuits + const bool transmitted = reflect_refract==MTT_REFRACT || reflect_refract!=MTT_REFLECT && VdotHLdotH(0.25,VdotHLdotH,transmitted); + scalar_type denominator = clampedNdotV; + if (transmitted) // VdotHLdotH is negative under transmission, so thats denominator is negative + denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; + retval.projectedLightMeasure /= denominator; + return retval; + } +}; +} + +template +SDualMeasureQuant createDualMeasureQuantity(const T specialMeasure, vector_traits::scalar_type clampedNdotV, vector_traits::scalar_type clampedNdotL) +{ + vector_traits::scalar_type dummy; + return impl::createDualMeasureQuantity_helper::__call(specialMeasure,clampedNdotV,clampedNdotL,dummy,dummy); +} +template +SDualMeasureQuant createDualMeasureQuantity(const T specialMeasure, vector_traits::scalar_type clampedNdotV, vector_traits::scalar_type clampedNdotL, vector_traits::scalar_type VdotHLdotH, vector_traits::scalar_type VdotH_etaLdotH) +{ + return impl::createDualMeasureQuantity_helper::__call(specialMeasure,clampedNdotV,clampedNdotL,VdotHLdotH,VdotH_etaLdotH); +} + +/* template struct SDualMeasureQuant; @@ -197,7 +243,7 @@ struct SDualMeasureQuant scalar_type VdotHLdotH; scalar_type orientedEta; }; - +*/ } } From f7525af25fa385e92eb423e53c1f4eb2ad602c3d Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 5 Sep 2025 16:15:14 +0700 Subject: [PATCH 02/38] create query structs in beckmann ndf, removed query concepts, funcs return quants --- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 458 +++++++++++++++--- 1 file changed, 378 insertions(+), 80 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index 8076102d94..79528ffc08 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -16,45 +16,100 @@ namespace bxdf namespace ndf { -namespace beckmann_concepts +// namespace beckmann_concepts +// { +// #define NBL_CONCEPT_NAME DG1BrdfQuery +// #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +// #define NBL_CONCEPT_TPLT_PRM_NAMES (T) +// #define NBL_CONCEPT_PARAM_0 (query, T) +// NBL_CONCEPT_BEGIN(1) +// #define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +// NBL_CONCEPT_END( +// ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) +// ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getNdf()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) +// ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) +// ); +// #undef query +// #include + +// #define NBL_CONCEPT_NAME DG1BsdfQuery +// #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +// #define NBL_CONCEPT_TPLT_PRM_NAMES (T) +// #define NBL_CONCEPT_PARAM_0 (query, T) +// NBL_CONCEPT_BEGIN(1) +// #define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +// NBL_CONCEPT_END( +// ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) +// ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(DG1BrdfQuery, T)) +// ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getOrientedEta()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) +// ); +// #undef query +// #include + +// #define NBL_CONCEPT_NAME G2overG1Query +// #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +// #define NBL_CONCEPT_TPLT_PRM_NAMES (T) +// #define NBL_CONCEPT_PARAM_0 (query, T) +// NBL_CONCEPT_BEGIN(1) +// #define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +// NBL_CONCEPT_END( +// ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) +// ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) +// ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) +// ); +// #undef query +// #include +// } + +namespace impl { -#define NBL_CONCEPT_NAME DG1Query -#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) -#define NBL_CONCEPT_TPLT_PRM_NAMES (T) -#define NBL_CONCEPT_PARAM_0 (query, T) -NBL_CONCEPT_BEGIN(1) -#define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 -NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getNdf()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) -); -#undef query -#include - -#define NBL_CONCEPT_NAME G2overG1Query -#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) -#define NBL_CONCEPT_TPLT_PRM_NAMES (T) -#define NBL_CONCEPT_PARAM_0 (query, T) -NBL_CONCEPT_BEGIN(1) -#define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 -NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) -); -#undef query -#include -} + +template +struct SBeckmannDG1Query // TODO: need to specialize? or just ignore orientedEta if not needed +{ + using scalar_type = T; + + scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } + scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } + + scalar_type ndf; + scalar_type lambda_V; +}; + +template +struct SBeckmannG2overG1Query +{ + using scalar_type = T; + + scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } + scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } + + scalar_type lambda_L; + scalar_type lambda_V; +}; + +template +struct SQuantQuery +{ + using scalar_type = T; + + scalar_type getVdotHLdotH() NBL_CONST_MEMBER_FUNC { return VdotHLdotH; } + scalar_type getVdotH_etaLdotH() NBL_CONST_MEMBER_FUNC { return VdotH_etaLdotH; } + + scalar_type VdotHLdotH; + scalar_type VdotH_etaLdotH; +}; template -struct Beckmann; +struct BeckmannCommon; template NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) -struct Beckmann) > +struct BeckmannCommon) > { using scalar_type = T; + using dg1_query_type = SBeckmannDG1Query; + using g2g1_query_type = SBeckmannG2overG1Query; template) scalar_type D(NBL_CONST_REF_ARG(MicrofacetCache) cache) @@ -64,31 +119,17 @@ struct Beckmann) > return numbers::inv_pi * nom / denom; } - // brdf - template) - scalar_type DG1(NBL_CONST_REF_ARG(Query) query) + scalar_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query) { return query.getNdf() / (scalar_type(1.0) + query.getLambdaV()); } - // bsdf - template && ReadableIsotropicMicrofacetCache) - scalar_type DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) - { - return DG1(query); - } - - scalar_type G1(scalar_type lambda) - { - return scalar_type(1.0) / (scalar_type(1.0) + lambda); - } - - scalar_type C2(scalar_type NdotX2) + static scalar_type C2(scalar_type NdotX2) { return NdotX2 / (a2 * (scalar_type(1.0) - NdotX2)); } - scalar_type Lambda(scalar_type c2) + static scalar_type Lambda(scalar_type c2) { scalar_type c = sqrt(c2); scalar_type nom = scalar_type(1.0) - scalar_type(1.259) * c + scalar_type(0.396) * c2; @@ -96,34 +137,35 @@ struct Beckmann) > return hlsl::mix(scalar_type(0.0), nom / denom, c < scalar_type(1.6)); } - scalar_type LambdaC2(scalar_type NdotX2) + static scalar_type LambdaC2(scalar_type NdotX2) { return Lambda(C2(NdotX2)); } - template && LightSample && surface_interactions::Isotropic) - scalar_type correlated(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + template && surface_interactions::Isotropic) + scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { return scalar_type(1.0) / (scalar_type(1.0) + query.getLambdaV() + query.getLambdaL()); } - template && LightSample && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { scalar_type onePlusLambda_V = scalar_type(1.0) + query.getLambdaV(); return onePlusLambda_V * hlsl::mix(scalar_type(1.0)/(onePlusLambda_V + query.getLambdaL()), bxdf::beta(onePlusLambda_V, scalar_type(1.0) + query.getLambdaL()), cache.isTransmission()); } - vector A; + vector A; // TODO: remove? scalar_type a2; }; - template NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) -struct Beckmann) > +struct BeckmannCommon) > { using scalar_type = T; + using dg1_query_type = SBeckmannDG1Query; + using g2g1_query_type = SBeckmannG2overG1Query; template) scalar_type D(NBL_CONST_REF_ARG(MicrofacetCache) cache) @@ -133,33 +175,19 @@ struct Beckmann) > return numbers::inv_pi * nom / denom; } - template) - scalar_type DG1(NBL_CONST_REF_ARG(Query) query) + scalar_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query) { - Beckmann beckmann; - scalar_type dg = beckmann.template DG1(query); + BeckmannCommon beckmann; + scalar_type dg = beckmann.DG1(query); return dg; } - template && AnisotropicMicrofacetCache) - scalar_type DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) - { - Beckmann beckmann; - scalar_type dg = beckmann.template DG1(query, cache.iso_cache); - return dg; - } - - scalar_type G1(scalar_type lambda) - { - return scalar_type(1.0) / (scalar_type(1.0) + lambda); - } - - scalar_type C2(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2) + static scalar_type C2(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2) { return NdotX2 / (TdotX2 * ax2 + BdotX2 * ay2); } - scalar_type Lambda(scalar_type c2) + static scalar_type Lambda(scalar_type c2) { scalar_type c = sqrt(c2); scalar_type nom = scalar_type(1.0) - scalar_type(1.259) * c + scalar_type(0.396) * c2; @@ -167,19 +195,19 @@ struct Beckmann) > return hlsl::mix(scalar_type(0.0), nom / denom, c < scalar_type(1.6)); } - scalar_type LambdaC2(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2) + static scalar_type LambdaC2(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2) { return Lambda(C2(TdotX2, BdotX2, NdotX2)); } - template && LightSample && surface_interactions::Anisotropic) - scalar_type correlated(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + template && surface_interactions::Anisotropic) + scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { return scalar_type(1.0) / (scalar_type(1.0) + query.getLambdaV() + query.getLambdaL()); } - template && LightSample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { scalar_type onePlusLambda_V = scalar_type(1.0) + query.getLambdaV(); return onePlusLambda_V * hlsl::mix(scalar_type(1.0)/(onePlusLambda_V + query.getLambdaL()), bxdf::beta(onePlusLambda_V, scalar_type(1.0) + query.getLambdaL()), cache.isTransmission()); @@ -189,6 +217,276 @@ struct Beckmann) > scalar_type ax2; scalar_type ay2; }; +} + +template +struct Beckmann; + +// partial spec for brdf +template +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) +struct Beckmann) > +{ + using scalar_type = T; + using base_type = impl::BeckmannCommon; + using quant_type = SDualMeasureQuant; + + using dg1_query_type = typename base_type::dg1_query_type; + using g2g1_query_type = typename base_type::g2g1_query_type; + using quant_query_type = SQuantQuery; + + template) + quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) + { + quant_query_type dummy; // brdfs don't make use of this + return dummy; + } + template && ReadableIsotropicMicrofacetCache) + dg1_query_type createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + dg1_query_type dg1_query; + dg1_query.ndf = __base.template D(cache); + dg1_query.lambda_V = base_type::LambdaC2(interaction.getNdotV2()); + return dg1_query; + } + template && surface_interactions::Isotropic) + g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + g2g1_query_type g2_query; + g2_query.lambda_L = base_type::LambdaC2(_sample.getNdotL2()); + g2_query.lambda_V = base_type::LambdaC2(interaction.getNdotV2()); + return g2_query; + } + + template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) + quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + scalar_type d = __base.template D(cache); + return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); + } + + template && surface_interactions::Isotropic) + quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + scalar_type dg1 = __base.DG1(query); + return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); + } + + template && surface_interactions::Isotropic) + quant_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + scalar_type g = __base.template correlated(query, _sample, interaction); + return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); + } + + template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + return __base.template G2_over_G1(query, _sample, interaction, cache); + } + + base_type __base; +}; + +template +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) +struct Beckmann) > +{ + using scalar_type = T; + using base_type = impl::BeckmannCommon; + using quant_type = SDualMeasureQuant; + + using dg1_query_type = typename base_type::dg1_query_type; + using g2g1_query_type = typename base_type::g2g1_query_type; + using quant_query_type = SQuantQuery; + + template) + quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) + { + quant_query_type dummy; // brdfs don't make use of this + return dummy; + } + template && ReadableIsotropicMicrofacetCache) + dg1_query_type createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + dg1_query_type dg1_query; + dg1_query.ndf = __base.template D(cache); + dg1_query.lambda_V = base_type::LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + return dg1_query; + } + template && surface_interactions::Isotropic) + g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + g2g1_query_type g2_query; + g2_query.lambda_L = base_type::LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); + g2_query.lambda_V = base_type::LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + return g2_query; + } + + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + scalar_type d = __base.template D(cache); + return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); + } + + template && surface_interactions::Anisotropic) + quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + scalar_type dg1 = __base.DG1(query); + return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); + } + + template && surface_interactions::Anisotropic) + quant_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + scalar_type g = __base.template correlated(query, _sample, interaction); + return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); + } + + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + return __base.template G2_over_G1(query, _sample, interaction, cache); + } + + base_type __base; +}; + +// partial for bsdf +template +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) +struct Beckmann) > +{ + using scalar_type = T; + using base_type = impl::BeckmannCommon; + using quant_type = SDualMeasureQuant; + + using dg1_query_type = typename base_type::dg1_query_type; + using g2g1_query_type = typename base_type::g2g1_query_type; + using quant_query_type = SQuantQuery; + + template) + quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) + { + quant_query_type quant_query; + quant_query.VdotHLdotH = cache.getVdotHLdotH(); + quant_query.VdotH_etaLdotH = cache.getVdotH() + orientedEta * cache.getLdotH(); + return quant_query; + } + template && ReadableIsotropicMicrofacetCache) + dg1_query_type createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + dg1_query_type dg1_query; + dg1_query.ndf = __base.template D(cache); + dg1_query.lambda_V = base_type::LambdaC2(interaction.getNdotV2()); + return dg1_query; + } + template && surface_interactions::Isotropic) + g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + g2g1_query_type g2_query; + g2_query.lambda_L = base_type::LambdaC2(_sample.getNdotL2()); + g2_query.lambda_V = base_type::LambdaC2(interaction.getNdotV2()); + return g2_query; + } + + template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) + quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + scalar_type d = __base.template D(cache); + return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + } + + template && surface_interactions::Isotropic) + quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + scalar_type dg1 = __base.DG1(query); + return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + } + + template && surface_interactions::Isotropic) + quant_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + scalar_type g = __base.template correlated(query, _sample, interaction); + return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + } + + template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + return __base.template G2_over_G1(query, _sample, interaction, cache); + } + + base_type __base; +}; + +template +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) +struct Beckmann) > +{ + using scalar_type = T; + using base_type = impl::BeckmannCommon; + using quant_type = SDualMeasureQuant; + + using dg1_query_type = typename base_type::dg1_query_type; + using g2g1_query_type = typename base_type::g2g1_query_type; + using quant_query_type = SQuantQuery; + + template) + quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) + { + quant_query_type quant_query; + quant_query.VdotHLdotH = cache.getVdotHLdotH(); + quant_query.VdotH_etaLdotH = cache.getVdotH() + orientedEta * cache.getLdotH(); + return quant_query; + } + template && ReadableIsotropicMicrofacetCache) + dg1_query_type createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + dg1_query_type dg1_query; + dg1_query.ndf = __base.template D(cache); + dg1_query.lambda_V = base_type::LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + return dg1_query; + } + template && surface_interactions::Isotropic) + g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + g2g1_query_type g2_query; + g2_query.lambda_L = base_type::LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); + g2_query.lambda_V = base_type::LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + return g2_query; + } + + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + scalar_type d = __base.template D(cache); + return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + } + + template && surface_interactions::Anisotropic) + quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + scalar_type dg1 = __base.template DG1(query); + return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + } + + template && LightSample && surface_interactions::Anisotropic) + quant_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + scalar_type g = __base.template correlated(query, _sample, interaction); + return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + } + + template && LightSample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + return __base.template G2_over_G1(query, _sample, interaction, cache); + } + + base_type __base; +}; } } From c50db68adc91ea4802dedd41e7931a3809fd659c Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 5 Sep 2025 17:02:18 +0700 Subject: [PATCH 03/38] did the same for ggx ndf, some fixes to beckmann --- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 12 +- include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 491 ++++++++++++++---- 2 files changed, 406 insertions(+), 97 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index 79528ffc08..f835064453 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -300,13 +300,13 @@ struct Beckmann; - template) + template) quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) { quant_query_type dummy; // brdfs don't make use of this return dummy; } - template && ReadableIsotropicMicrofacetCache) + template && AnisotropicMicrofacetCache) dg1_query_type createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { dg1_query_type dg1_query; @@ -314,7 +314,7 @@ struct Beckmann && surface_interactions::Isotropic) + template && surface_interactions::Anisotropic) g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { g2g1_query_type g2_query; @@ -433,7 +433,7 @@ struct Beckmann; - template) + template) quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) { quant_query_type quant_query; @@ -441,7 +441,7 @@ struct Beckmann && ReadableIsotropicMicrofacetCache) + template && AnisotropicMicrofacetCache) dg1_query_type createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { dg1_query_type dg1_query; @@ -449,7 +449,7 @@ struct Beckmann && surface_interactions::Isotropic) + template && surface_interactions::Anisotropic) g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { g2g1_query_type g2_query; diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index eb49bd38f0..7f9c77ad1c 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -16,61 +16,101 @@ namespace bxdf namespace ndf { -namespace ggx_concepts +// namespace ggx_concepts +// { +// #define NBL_CONCEPT_NAME DG1BrdfQuery +// #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +// #define NBL_CONCEPT_TPLT_PRM_NAMES (T) +// #define NBL_CONCEPT_PARAM_0 (query, T) +// NBL_CONCEPT_BEGIN(1) +// #define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +// NBL_CONCEPT_END( +// ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) +// ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getNdf()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) +// ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getG1over2NdotV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) +// ); +// #undef query +// #include + +// #define NBL_CONCEPT_NAME DG1BsdfQuery +// #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +// #define NBL_CONCEPT_TPLT_PRM_NAMES (T) +// #define NBL_CONCEPT_PARAM_0 (query, T) +// NBL_CONCEPT_BEGIN(1) +// #define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +// NBL_CONCEPT_END( +// ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) +// ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(DG1BrdfQuery, T)) +// ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getOrientedEta()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) +// ); +// #undef query +// #include + +// #define NBL_CONCEPT_NAME G2XQuery +// #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +// #define NBL_CONCEPT_TPLT_PRM_NAMES (T) +// #define NBL_CONCEPT_PARAM_0 (query, T) +// NBL_CONCEPT_BEGIN(1) +// #define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +// NBL_CONCEPT_END( +// ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) +// ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getDevshV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) +// ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getDevshL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) +// ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getClampMode()), ::nbl::hlsl::is_same_v, BxDFClampMode)) +// ); +// #undef query +// #include +// } + +namespace impl { -#define NBL_CONCEPT_NAME DG1BrdfQuery -#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) -#define NBL_CONCEPT_TPLT_PRM_NAMES (T) -#define NBL_CONCEPT_PARAM_0 (query, T) -NBL_CONCEPT_BEGIN(1) -#define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 -NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getNdf()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getG1over2NdotV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) -); -#undef query -#include - -#define NBL_CONCEPT_NAME DG1BsdfQuery -#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) -#define NBL_CONCEPT_TPLT_PRM_NAMES (T) -#define NBL_CONCEPT_PARAM_0 (query, T) -NBL_CONCEPT_BEGIN(1) -#define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 -NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getNdf()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getG1over2NdotV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getOrientedEta()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) -); -#undef query -#include - -#define NBL_CONCEPT_NAME G2XQuery -#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) -#define NBL_CONCEPT_TPLT_PRM_NAMES (T) -#define NBL_CONCEPT_PARAM_0 (query, T) -NBL_CONCEPT_BEGIN(1) -#define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 -NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getDevshV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getDevshL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getClampMode()), ::nbl::hlsl::is_same_v, BxDFClampMode)) -); -#undef query -#include -} + +struct SGGXDG1Query +{ + using scalar_type = scalar_type; + + scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } + scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; } + + scalar_type ndf; + scalar_type G1_over_2NdotV; +}; + +struct SGGXG2XQuery +{ + using scalar_type = scalar_type; + + scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } + scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } + BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } + + scalar_type devsh_v; + scalar_type devsh_l; + BxDFClampMode _clamp; +}; + +template +struct SQuantQuery +{ + using scalar_type = T; + + scalar_type getVdotHLdotH() NBL_CONST_MEMBER_FUNC { return VdotHLdotH; } + scalar_type getVdotH_etaLdotH() NBL_CONST_MEMBER_FUNC { return VdotH_etaLdotH; } + + scalar_type VdotHLdotH; + scalar_type VdotH_etaLdotH; +}; template -struct GGX; +struct GGXCommon; template NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) -struct GGX) > +struct GGXCommon) > { using scalar_type = T; + using dg1_query_type = SGGXDG1Query; + using g2g1_query_type = SGGXG2XQuery; // trowbridge-reitz template) @@ -80,46 +120,31 @@ struct GGX) > return a2 * numbers::inv_pi / (denom * denom); } - template) - scalar_type DG1(NBL_CONST_REF_ARG(Query) query) + scalar_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query) { return scalar_type(0.5) * query.getNdf() * query.getG1over2NdotV(); } - template && ReadableIsotropicMicrofacetCache) - scalar_type DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) - { - scalar_type NG = query.getNdf() * query.getG1over2NdotV(); - scalar_type factor = scalar_type(0.5); - if (cache.isTransmission()) - { - const scalar_type VdotH_etaLdotH = (cache.getVdotH() + query.getOrientedEta() * cache.getLdotH()); - // VdotHLdotH is negative under transmission, so this factor is negative - factor *= -scalar_type(2.0) * cache.getVdotHLdotH() / (VdotH_etaLdotH * VdotH_etaLdotH); - } - return NG * factor; - } - - scalar_type devsh_part(scalar_type NdotX2) + static scalar_type devsh_part(scalar_type NdotX2) { assert(a2 >= numeric_limits::min); return sqrt(a2 + one_minus_a2 * NdotX2); } - scalar_type G1_wo_numerator(scalar_type absNdotX, scalar_type NdotX2) + static scalar_type G1_wo_numerator(scalar_type absNdotX, scalar_type NdotX2) { return scalar_type(1.0) / (absNdotX + devsh_part(NdotX2)); } - scalar_type G1_wo_numerator_devsh_part(scalar_type absNdotX, scalar_type devsh_part) + static scalar_type G1_wo_numerator_devsh_part(scalar_type absNdotX, scalar_type devsh_part) { // numerator is 2 * NdotX return scalar_type(1.0) / (absNdotX + devsh_part); } // without numerator, numerator is 2 * NdotV * NdotL, we factor out 4 * NdotV * NdotL, hence 0.5 - template && LightSample && surface_interactions::Isotropic) - scalar_type correlated(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + template && surface_interactions::Isotropic) + scalar_type correlated_wo_numerator(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { BxDFClampMode _clamp = query.getClampMode(); assert(_clamp != BxDFClampMode::BCM_NONE); @@ -129,8 +154,16 @@ struct GGX) > return scalar_type(0.5) / (Vterm + Lterm); } - template && LightSample && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template && surface_interactions::Isotropic) + scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + BxDFClampMode _clamp = query.getClampMode(); + assert(_clamp != BxDFClampMode::BCM_NONE); + return scalar_type(4.0) * interaction.getNdotV(_clamp) * _sample.getNdotL(_clamp) * correlated_wo_numerator(query, _sample, interaction); + } + + template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { BxDFClampMode _clamp = query.getClampMode(); assert(_clamp != BxDFClampMode::BCM_NONE); @@ -150,23 +183,25 @@ struct GGX) > } else { - G2_over_G1 = NdotL * (devsh_v + NdotV); // alternative `Vterm+NdotL*NdotV /// NdotL*NdotV could come as a parameter + G2_over_G1 = NdotL * (devsh_v + NdotV); G2_over_G1 /= NdotV * devsh_l + NdotL * devsh_v; } return G2_over_G1; } - vector A; + vector A; // TODO: remove? scalar_type a2; scalar_type one_minus_a2; }; template NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) -struct GGX) > +struct GGXCommon) > { using scalar_type = T; + using dg1_query_type = SGGXDG1Query; + using g2g1_query_type = SGGXG2XQuery; template) scalar_type D(NBL_CONST_REF_ARG(MicrofacetCache) cache) @@ -186,39 +221,31 @@ struct GGX) > return w2 * w2 * atab * numbers::inv_pi; } - template) - scalar_type DG1(NBL_CONST_REF_ARG(Query) query) + scalar_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query) { - GGX ggx; - return ggx.template DG1(query); + GGXCommon ggx; + return ggx.DG1(query); } - template && AnisotropicMicrofacetCache) - scalar_type DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) - { - GGX ggx; - return ggx.template DG1(query, cache.iso_cache); - } - - scalar_type devsh_part(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2) + static scalar_type devsh_part(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2) { assert(ax2 >= numeric_limits::min && ay2 >= numeric_limits::min); return sqrt(TdotX2 * ax2 + BdotX2 * ay2 + NdotX2); } - scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2) + static scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2) { return scalar_type(1.0) / (NdotX + devsh_part(TdotX2, BdotX2, NdotX2)); } - scalar_type G1_wo_numerator_devsh_part(scalar_type NdotX, scalar_type devsh_part) + static scalar_type G1_wo_numerator_devsh_part(scalar_type NdotX, scalar_type devsh_part) { return scalar_type(1.0) / (NdotX + devsh_part); } // without numerator - template && LightSample && surface_interactions::Anisotropic) - scalar_type correlated(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + template && surface_interactions::Anisotropic) + scalar_type correlated_wo_numerator(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { BxDFClampMode _clamp = query.getClampMode(); assert(_clamp != BxDFClampMode::BCM_NONE); @@ -228,8 +255,16 @@ struct GGX) > return scalar_type(0.5) / (Vterm + Lterm); } - template && LightSample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template && surface_interactions::Anisotropic) + scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + BxDFClampMode _clamp = query.getClampMode(); + assert(_clamp != BxDFClampMode::BCM_NONE); + return scalar_type(4.0) * interaction.getNdotV(_clamp) * _sample.getNdotL(_clamp) * correlated_wo_numerator(query, _sample, interaction); + } + + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { BxDFClampMode _clamp = query.getClampMode(); assert(_clamp != BxDFClampMode::BCM_NONE); @@ -261,6 +296,280 @@ struct GGX) > scalar_type ay2; scalar_type a2; }; +} + +template +struct GGX; + +// partial spec for brdf +template +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) +struct GGX) > +{ + using scalar_type = T; + using base_type = impl::GGXCommon; + using quant_type = SDualMeasureQuant; + + using dg1_query_type = typename base_type::dg1_query_type; + using g2g1_query_type = typename base_type::g2g1_query_type; + using quant_query_type = SQuantQuery; + + template) + quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) + { + quant_query_type dummy; // brdfs don't make use of this + return dummy; + } + template && ReadableIsotropicMicrofacetCache) + dg1_query_type createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + dg1_query_type dg1_query; + dg1_query.ndf = __base.template D(cache); + dg1_query.devsh_v = base_type::devsh_part(interaction.getNdotV2()); + return dg1_query; + } + template && surface_interactions::Isotropic) + g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + g2g1_query_type g2_query; + g2_query.devsh_l = base_type::devsh_part(_sample.getNdotL2()); + g2_query.devsh_v = base_type::devsh_part(interaction.getNdotV2()); + g2_query._clamp = BxDFClampMode::BCM_MAX; + return g2_query; + } + + template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) + quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + scalar_type d = __base.template D(cache); + return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); + } + + template && surface_interactions::Isotropic) + quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + scalar_type dg1 = __base.DG1(query); + return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); + } + + template && surface_interactions::Isotropic) + quant_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + scalar_type g = __base.template correlated(query, _sample, interaction); + return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); + } + + template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) + quant_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + return __base.template G2_over_G1(query, _sample, interaction, cache); + } + + base_type __base; +}; + +template +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) +struct GGX) > +{ + using scalar_type = T; + using base_type = impl::GGXCommon; + using quant_type = SDualMeasureQuant; + + using dg1_query_type = typename base_type::dg1_query_type; + using g2g1_query_type = typename base_type::g2g1_query_type; + using quant_query_type = SQuantQuery; + + template) + quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) + { + quant_query_type dummy; // brdfs don't make use of this + return dummy; + } + template && AnisotropicMicrofacetCache) + dg1_query_type createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + dg1_query_type dg1_query; + dg1_query.ndf = __base.template D(cache); + dg1_query.devsh_v = base_type::devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + return dg1_query; + } + template && surface_interactions::Anisotropic) + g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + g2g1_query_type g2_query; + g2_query.devsh_l = base_type::devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); + g2_query.devsh_v = base_type::devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + g2_query._clamp = BxDFClampMode::BCM_MAX; + return g2_query; + } + + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + scalar_type d = __base.template D(cache); + return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); + } + + template && surface_interactions::Anisotropic) + quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + scalar_type dg1 = __base.DG1(query); + return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); + } + + template && surface_interactions::Anisotropic) + quant_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + scalar_type g = __base.template correlated(query, _sample, interaction); + return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); + } + + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + quant_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + return __base.template G2_over_G1(query, _sample, interaction, cache); + } + + base_type __base; +}; + +// partial for bsdf +template +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) +struct GGX) > +{ + using scalar_type = T; + using base_type = impl::GGXCommon; + using quant_type = SDualMeasureQuant; + + using dg1_query_type = typename base_type::dg1_query_type; + using g2g1_query_type = typename base_type::g2g1_query_type; + using quant_query_type = SQuantQuery; + + template) + quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) + { + quant_query_type quant_query; + quant_query.VdotHLdotH = cache.getVdotHLdotH(); + quant_query.VdotH_etaLdotH = cache.getVdotH() + orientedEta * cache.getLdotH(); + return quant_query; + } + template && ReadableIsotropicMicrofacetCache) + dg1_query_type createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + dg1_query_type dg1_query; + dg1_query.ndf = __base.template D(cache); + dg1_query.devsh_v = base_type::devsh_part(interaction.getNdotV2()); + return dg1_query; + } + template && surface_interactions::Isotropic) + g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + g2g1_query_type g2_query; + g2_query.devsh_l = base_type::devsh_part(_sample.getNdotL2()); + g2_query.devsh_v = base_type::devsh_part(interaction.getNdotV2()); + g2_query._clamp = BxDFClampMode::BCM_ABS; + return g2_query; + } + + template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) + quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + scalar_type d = __base.template D(cache); + return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + } + + template && surface_interactions::Isotropic) + quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + scalar_type dg1 = __base.DG1(query); + return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + } + + template && surface_interactions::Isotropic) + quant_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + scalar_type g = __base.template correlated(query, _sample, interaction); + return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + } + + template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) + quant_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + return __base.template G2_over_G1(query, _sample, interaction, cache); + } + + base_type __base; +}; + +template +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) +struct GGX) > +{ + using scalar_type = T; + using base_type = impl::GGXCommon; + using quant_type = SDualMeasureQuant; + + using dg1_query_type = typename base_type::dg1_query_type; + using g2g1_query_type = typename base_type::g2g1_query_type; + using quant_query_type = SQuantQuery; + + template) + quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) + { + quant_query_type quant_query; + quant_query.VdotHLdotH = cache.getVdotHLdotH(); + quant_query.VdotH_etaLdotH = cache.getVdotH() + orientedEta * cache.getLdotH(); + return quant_query; + } + template && AnisotropicMicrofacetCache) + dg1_query_type createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + dg1_query_type dg1_query; + dg1_query.ndf = __base.template D(cache); + dg1_query.devsh_v = base_type::devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + return dg1_query; + } + template && surface_interactions::Anisotropic) + g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + g2g1_query_type g2_query; + g2_query.devsh_l = base_type::devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); + g2_query.devsh_v = base_type::devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + g2_query._clamp = BxDFClampMode::BCM_ABS; + return g2_query; + } + + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + scalar_type d = __base.template D(cache); + return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + } + + template && surface_interactions::Anisotropic) + quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + scalar_type dg1 = __base.template DG1(query); + return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + } + + template && surface_interactions::Anisotropic) + quant_type correlated(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + scalar_type g = __base.template correlated(query, _sample, interaction); + return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + } + + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + quant_type G2_over_G1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + return __base.template G2_over_G1(query, _sample, interaction, cache); + } + + base_type __base; +}; namespace impl From 319c954a7af805551fecadb5f0fec1c7e2aba7c7 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 8 Sep 2025 11:58:39 +0700 Subject: [PATCH 04/38] fixes to ndf concept --- include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 38 ++++++++----------- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 10 ++--- 2 files changed, 20 insertions(+), 28 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl index 9189d1baec..4fbf49433d 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -21,48 +21,40 @@ namespace dummy_impl using sample_t = SLightSample >; using interaction_t = surface_interactions::SAnisotropic > >; using cache_t = SAnisotropicMicrofacetCache >; -struct MetaQuery // nonsense struct, just put in all the functions to pass the ndf query concepts -{ - using scalar_type = float; - - scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return 0; } - scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return 0; } - scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return 0; } - - scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return 0; } - scalar_type getOrientedEta() NBL_CONST_MEMBER_FUNC { return 0; } - scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return 0; } - scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return 0; } - BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return BxDFClampMode::BCM_NONE; } -}; } #define NBL_CONCEPT_NAME NDF #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) #define NBL_CONCEPT_TPLT_PRM_NAMES (T) #define NBL_CONCEPT_PARAM_0 (ndf, T) -#define NBL_CONCEPT_PARAM_1 (query, dummy_impl::MetaQuery) +#define NBL_CONCEPT_PARAM_1 (quant_query, typename T::quant_query_type) #define NBL_CONCEPT_PARAM_2 (_sample, dummy_impl::sample_t) #define NBL_CONCEPT_PARAM_3 (interaction, dummy_impl::interaction_t) #define NBL_CONCEPT_PARAM_4 (cache, dummy_impl::cache_t) -NBL_CONCEPT_BEGIN(5) +#define NBL_CONCEPT_PARAM_5 (dg1_query, typename T::dg1_query_type) +#define NBL_CONCEPT_PARAM_6 (g2_query, typename T::g2g1_query_type) +NBL_CONCEPT_BEGIN(7) #define ndf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 -#define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 +#define quant_query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 #define interaction NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 #define cache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 +#define dg1_query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 +#define g2_query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template D(cache)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template DG1(query)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template DG1(query, cache)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template correlated(query, _sample, interaction)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template G2_over_G1(query, _sample, interaction, cache)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::quant_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template D(quant_query, _sample, interaction, cache)), ::nbl::hlsl::is_same_v, typename T::quant_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template DG1(dg1_query, quant_query, _sample, interaction)), ::nbl::hlsl::is_same_v, typename T::quant_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template correlated(g2_query, quant_query, _sample, interaction)), ::nbl::hlsl::is_same_v, typename T::quant_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template G2_over_G1(g2_query, _sample, interaction, cache)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ); +#undef g2_query +#undef dg1_query #undef cache #undef interaction #undef _sample -#undef query +#undef quant_query #undef ndf #include diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index f835064453..54a2c8ac99 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -398,14 +398,14 @@ struct Beckmann(d, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); } - template && surface_interactions::Isotropic) + template && surface_interactions::Isotropic) quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { scalar_type dg1 = __base.DG1(query); return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); } - template && surface_interactions::Isotropic) + template && surface_interactions::Isotropic) quant_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { scalar_type g = __base.template correlated(query, _sample, interaction); @@ -465,21 +465,21 @@ struct Beckmann(d, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); } - template && surface_interactions::Anisotropic) + template && surface_interactions::Anisotropic) quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { scalar_type dg1 = __base.template DG1(query); return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); } - template && LightSample && surface_interactions::Anisotropic) + template && surface_interactions::Anisotropic) quant_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { scalar_type g = __base.template correlated(query, _sample, interaction); return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); } - template && LightSample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { return __base.template G2_over_G1(query, _sample, interaction, cache); From 4eeacf1367f595f913524ed0664ede42a9f76fc1 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 9 Sep 2025 11:32:58 +0700 Subject: [PATCH 05/38] moved eval, quotient/pdf into cook torrance base --- .../builtin/hlsl/bxdf/cook_torrance_base.hlsl | 262 ++++++++++++++---- 1 file changed, 205 insertions(+), 57 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl index e95e7331c7..d163ef2ad4 100644 --- a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl @@ -17,9 +17,13 @@ namespace hlsl namespace bxdf { -// N (NDF), F (fresnel), MT (measure transform, using DualMeasureQuant) -template && ndf::NDF && fresnel::Fresnel) -struct SCookTorrance +// N (NDF), F (fresnel) +template +struct SCookTorrance; + +template +NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration && ndf::NDF && fresnel::Fresnel) +struct SCookTorrance && ndf::NDF && fresnel::Fresnel) > { NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); @@ -27,85 +31,229 @@ struct SCookTorrance 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(isocache_type, Config); NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); - scalar_type __D(NBL_CONST_REF_ARG(isocache_type) cache) + using quant_type = typename N::quant_type; + + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - return ndf.template D(cache); + if (interaction.getNdotV() > numeric_limits::min) + { + using quant_query_type = typename N::quant_query_type; + using g2g1_query_type = typename N::g2g1_query_type; + + scalar_type dummy; + quant_query_type qq = ndf.template createQuantQuery(cache, dummy); + g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); + + quant_type D = ndf.template D(qq, _sample, interaction, cache); + scalar_type DG = D.projectedLightMeasure; + if (any >(ndf.A > hlsl::promote(numeric_limits::min))) + { + quant_type G2 = ndf.template correlated(gq, qq, _sample, interaction); + DG *= G2.microfacetMeasure; + } + return __base.fresnel(cache.getVdotH()) * DG; + } + else + return hlsl::promote(0.0); } - scalar_type __D(NBL_CONST_REF_ARG(anisocache_type) cache) + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - return ndf.template D(cache); - } + if (interaction.getNdotV() > numeric_limits::min) + { + using quant_query_type = typename N::quant_query_type; + using g2g1_query_type = typename N::g2g1_query_type; - template - MT __DG1(NBL_CONST_REF_ARG(Query) query) - { - MT measure_transform; - measure_transform.pdf = ndf.template DG1(query); - return measure_transform; + scalar_type dummy; + quant_query_type qq = ndf.template createQuantQuery(cache, dummy); + g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); + + quant_type D = ndf.template D(qq, _sample, interaction, cache); + scalar_type DG = D.projectedLightMeasure; + if (any >(ndf.A > hlsl::promote(numeric_limits::min))) + { + quant_type G2 = ndf.template correlated(gq, qq, _sample, interaction); + DG *= G2.microfacetMeasure; + } + return __base.fresnel(cache.getVdotH()) * DG; + } + else + return hlsl::promote(0.0); } - template - MT __DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(isocache_type) cache) + + // TODO: generate + + scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - MT measure_transform; - measure_transform.pdf = ndf.template DG1(query, cache); - measure_transform.transmitted = cache.isTransmission(); - measure_transform.VdotH = cache.getVdotH(); - measure_transform.LdotH = cache.getLdotH(); - measure_transform.VdotHLdotH = cache.getVdotHLdotH(); - return measure_transform; + using quant_query_type = typename N::quant_query_type; + using dg1_query_type = typename N::dg1_query_type; + + scalar_type dummy; + quant_query_type qq = ndf.template createQuantQuery(cache, dummy); + dg1_query_type dq = ndf.template createDG1Query(interaction, cache); + quant_type DG1 = ndf.template DG1(dq, qq, _sample, interaction); + return DG1.projectedLightMeasure; } - template - MT __DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(anisocache_type) cache) + scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - MT measure_transform; - measure_transform.pdf = ndf.template DG1(query, cache); - measure_transform.transmitted = cache.isTransmission(); - measure_transform.VdotH = cache.getVdotH(); - measure_transform.LdotH = cache.getLdotH(); - measure_transform.VdotHLdotH = cache.getVdotHLdotH(); - return measure_transform; + using quant_query_type = typename N::quant_query_type; + using dg1_query_type = typename N::dg1_query_type; + + scalar_type dummy; + quant_query_type qq = ndf.template createQuantQuery(cache, dummy); + dg1_query_type dq = ndf.template createDG1Query(interaction, cache); + quant_type DG1 = ndf.template DG1(dq, qq, _sample, interaction); + return DG1.projectedLightMeasure; } - template - MT __DG(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - MT measure_transform; - measure_transform.pdf = ndf.template D(cache); - NBL_IF_CONSTEXPR(MT::Type == ndf::MicrofacetTransformTypes::MTT_REFLECT_REFRACT) - measure_transform.transmitted = cache.isTransmission(); - NBL_IF_CONSTEXPR(MT::Type == ndf::MicrofacetTransformTypes::MTT_REFRACT) + scalar_type _pdf = pdf(interaction, cache); + + spectral_type quo = hlsl::promote(0.0); + if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) { - measure_transform.VdotH = cache.getVdotH(); - measure_transform.LdotH = cache.getLdotH(); - measure_transform.VdotHLdotH = cache.getVdotHLdotH(); + using g2g1_query_type = typename N::g2g1_query_type; + + g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); + scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1(gq, _sample, interaction, cache); + const spectral_type reflectance = __base.fresnel(cache.getVdotH()); + quo = reflectance * G2_over_G1; } - if (any >(ndf.A > hlsl::promote(numeric_limits::min))) + + return quotient_pdf_type::create(quo, _pdf); + } + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + { + scalar_type _pdf = pdf(interaction, cache); + + spectral_type quo = hlsl::promote(0.0); + if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) { - measure_transform.pdf *= ndf.template correlated(query, _sample, interaction); + using g2g1_query_type = typename N::g2g1_query_type; + + g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); + scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1(gq, _sample, interaction, cache); + const spectral_type reflectance = __base.fresnel(cache.getVdotH()); + quo = reflectance * G2_over_G1; } - return measure_transform; + + return quotient_pdf_type::create(quo, _pdf); } - template - MT __DG(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + + N ndf; + F fresnel; +}; + +template +NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration && ndf::NDF && fresnel::Fresnel) +struct SCookTorrance && ndf::NDF && fresnel::Fresnel) > +{ + 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(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(isocache_type, Config); + NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); + + using quant_type = typename N::quant_type; + + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - MT measure_transform; - measure_transform.pdf = ndf.template D(cache); - NBL_IF_CONSTEXPR(MT::Type == ndf::MicrofacetTransformTypes::MTT_REFLECT_REFRACT) - measure_transform.transmitted = cache.isTransmission(); - NBL_IF_CONSTEXPR(MT::Type == ndf::MicrofacetTransformTypes::MTT_REFRACT) + using quant_query_type = typename N::quant_query_type; + using g2g1_query_type = typename N::g2g1_query_type; + + fresnel::OrientedEtas orientedEta = __base.fresnel.orientedEta; + quant_query_type qq = ndf.template createQuantQuery(cache, orientedEta.value[0]); + g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); + + quant_type D = ndf.template D(qq, _sample, interaction, cache); + scalar_type DG = D.projectedLightMeasure; + if (any >(ndf.A > hlsl::promote(numeric_limits::min))) { - measure_transform.VdotH = cache.getVdotH(); - measure_transform.LdotH = cache.getLdotH(); - measure_transform.VdotHLdotH = cache.getVdotHLdotH(); + quant_type G2 = ndf.template correlated(gq, qq, _sample, interaction); + DG *= G2.microfacetMeasure; } + return hlsl::promote(__base.fresnel(hlsl::abs(cache.getVdotH()))[0]) * DG; + } + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + { + using quant_query_type = typename N::quant_query_type; + using g2g1_query_type = typename N::g2g1_query_type; + + fresnel::OrientedEtas orientedEta = __base.fresnel.orientedEta; + quant_query_type qq = ndf.template createQuantQuery(cache, orientedEta.value[0]); + g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); + + quant_type D = ndf.template D(qq, _sample, interaction, cache); + scalar_type DG = D.projectedLightMeasure; if (any >(ndf.A > hlsl::promote(numeric_limits::min))) { - measure_transform.pdf *= ndf.template correlated(query, _sample, interaction); + quant_type G2 = ndf.template correlated(gq, qq, _sample, interaction); + DG *= G2.microfacetMeasure; } - return measure_transform; + return hlsl::promote(__base.fresnel(hlsl::abs(cache.getVdotH()))[0]) * DG; + } + + // TODO: generate + + scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + { + using quant_query_type = typename N::quant_query_type; + using dg1_query_type = typename N::dg1_query_type; + + fresnel::OrientedEtas orientedEta = __base.fresnel.orientedEta; + quant_query_type qq = ndf.template createQuantQuery(cache, orientedEta.value[0]); + dg1_query_type dq = ndf.template createDG1Query(interaction, cache); + quant_type DG1 = ndf.template DG1(dq, qq, _sample, interaction); + + const spectral_type reflectance = __base.fresnel(cache.getVdotH()); + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * DG1.projectedLightMeasure; + } + scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + { + using quant_query_type = typename N::quant_query_type; + using dg1_query_type = typename N::dg1_query_type; + + fresnel::OrientedEtas orientedEta = __base.fresnel.orientedEta; + quant_query_type qq = ndf.template createQuantQuery(cache, orientedEta.value[0]); + dg1_query_type dq = ndf.template createDG1Query(interaction, cache); + quant_type DG1 = ndf.template DG1(dq, qq, _sample, interaction); + + const spectral_type reflectance = __base.fresnel(cache.getVdotH()); + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * DG1.projectedLightMeasure; + } + + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + { + scalar_type _pdf = pdf(interaction, cache); + + using g2g1_query_type = typename N::g2g1_query_type; + + g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); + scalar_type quo = beckmann_ndf.template G2_over_G1(gq, _sample, interaction, cache); + + return quotient_pdf_type::create(quo, _pdf); + } + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + { + scalar_type _pdf = pdf(interaction, cache); + + using g2g1_query_type = typename N::g2g1_query_type; + + g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); + scalar_type quo = beckmann_ndf.template G2_over_G1(gq, _sample, interaction, cache); + + return quotient_pdf_type::create(quo, _pdf); } N ndf; From e7bc7845f602cad3afe13fee22c6da750ffbefc8 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 9 Sep 2025 15:58:26 +0700 Subject: [PATCH 06/38] moved generate H into ndfs, generate impl in cook torrance base --- .../builtin/hlsl/bxdf/cook_torrance_base.hlsl | 55 ++++++++++- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 96 +++++++++++++++++++ include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 50 ++++++++++ 3 files changed, 199 insertions(+), 2 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl index d163ef2ad4..0df9b13325 100644 --- a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl @@ -85,7 +85,25 @@ struct SCookTorrance(0.0); } - // TODO: generate + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache) + { + anisocache_type anisocache; + sample_type s = generate(anisotropic_interaction_type::create(interaction), u, anisocache); + cache = anisocache.iso_cache; + return s; + } + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache) + { + const vector3_type localV = interaction.getTangentSpaceV(); + const vector3_type H = ndf.generateH(localV, u); + + cache = anisocache_type::createForReflection(localV, H); + ray_dir_info_type localL; + bxdf::Reflect r = bxdf::Reflect::create(localV, H); + localL = localL.reflect(r); + + return sample_type::createFromTangentSpace(localL, interaction.getFromTangentSpace()); + } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { @@ -204,7 +222,40 @@ struct SCookTorrance(__base.fresnel(hlsl::abs(cache.getVdotH()))[0]) * DG; } - // TODO: generate + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(isocache_type) cache) + { + anisocache_type anisocache; + sample_type s = generate(anisotropic_interaction_type::create(interaction), u, anisocache); + cache = anisocache.iso_cache; + return s; + } + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(anisocache_type) cache) + { + const vector3_type localV = interaction.getTangentSpaceV(); + + fresnel::OrientedEtas orientedEta = __base.fresnel.orientedEta; + fresnel::OrientedEtaRcps rcpEta = orientedEta.getReciprocals(); + + const vector3_type upperHemisphereV = hlsl::mix(localV, -localV, interaction.getNdotV() < scalar_type(0.0)); + const vector3_type H = ndf.generateH(upperHemisphereV, u.xy); + + const scalar_type reflectance = __base.fresnel(hlsl::abs(cache.getVdotH()))[0]; + + scalar_type rcpChoiceProb; + scalar_type z = u.z; + bool transmitted = math::partitionRandVariable(reflectance, z, rcpChoiceProb); + + cache = anisocache_type::createForReflection(localV, H); + + Refract r = Refract::create(localV, H); + cache.iso_cache.LdotH = hlsl::mix(cache.getVdotH(), r.getNdotT(rcpEta.value2[0]), transmitted); + ray_dir_info_type localL; + bxdf::ReflectRefract rr; + rr.refract = r; + localL = localL.reflectRefract(rr, transmitted, rcpEta.value[0]); + + return sample_type::createFromTangentSpace(localL, interaction.getFromTangentSpace()); + } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index 54a2c8ac99..78fec05375 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -217,6 +217,82 @@ struct BeckmannCommon +struct BeckmannGenerateH +{ + using scalar_type = T; + using vector2_type = vector; + using vector3_type = vector; + + vector3_type __call(const vector2_type A, const vector3_type localV, const vector2_type u) + { + //stretch + vector3_type V = nbl::hlsl::normalize(vector3_type(A.x * localV.x, A.y * localV.y, localV.z)); + + vector2_type slope; + if (V.z > 0.9999)//V.z=NdotV=cosTheta in tangent space + { + scalar_type r = sqrt(-log(1.0 - u.x)); + scalar_type sinPhi = sin(2.0 * numbers::pi * u.y); + scalar_type cosPhi = cos(2.0 * numbers::pi * u.y); + slope = (vector2_type)r * vector2_type(cosPhi,sinPhi); + } + else + { + scalar_type cosTheta = V.z; + scalar_type sinTheta = sqrt(1.0 - cosTheta * cosTheta); + scalar_type tanTheta = sinTheta / cosTheta; + scalar_type cotTheta = 1.0 / tanTheta; + + scalar_type a = -1.0; + scalar_type c = erf(cosTheta); + scalar_type sample_x = max(u.x, 1.0e-6); + scalar_type theta = acos(cosTheta); + scalar_type fit = 1.0 + theta * (-0.876 + theta * (0.4265 - 0.0594*theta)); + scalar_type b = c - (1.0 + c) * pow(1.0-sample_x, fit); + + scalar_type normalization = 1.0 / (1.0 + c + numbers::inv_sqrtpi * tanTheta * exp(-cosTheta*cosTheta)); + + const int ITER_THRESHOLD = 10; + const float MAX_ACCEPTABLE_ERR = 1.0e-5; + int it = 0; + float value=1000.0; + while (++it < ITER_THRESHOLD && nbl::hlsl::abs(value) > MAX_ACCEPTABLE_ERR) + { + if (!(b >= a && b <= c)) + b = 0.5 * (a + c); + + float invErf = erfInv(b); + value = normalization * (1.0 + b + numbers::inv_sqrtpi * tanTheta * exp(-invErf * invErf)) - sample_x; + float derivative = normalization * (1.0 - invErf * cosTheta); + + if (value > 0.0) + c = b; + else + a = b; + + b -= value/derivative; + } + // TODO: investigate if we can replace these two erf^-1 calls with a box muller transform + slope.x = erfInv(b); + slope.y = erfInv(2.0 * max(u.y, 1.0e-6) - 1.0); + } + + scalar_type sinTheta = sqrt(1.0 - V.z*V.z); + scalar_type cosPhi = sinTheta==0.0 ? 1.0 : clamp(V.x/sinTheta, -1.0, 1.0); + scalar_type sinPhi = sinTheta==0.0 ? 0.0 : clamp(V.y/sinTheta, -1.0, 1.0); + //rotate + scalar_type tmp = cosPhi*slope.x - sinPhi*slope.y; + slope.y = sinPhi*slope.x + cosPhi*slope.y; + slope.x = tmp; + + //unstretch + slope = vector2_type(A.x,A.y)*slope; + + return nbl::hlsl::normalize(vector3_type(-slope, 1.0)); + } +}; } template @@ -258,6 +334,11 @@ struct Beckmann generateH(const vector3_type localV, const vector2_type u) + { + return impl::BeckmannGenerateH::__call(__base.A, localV, u); + } + template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { @@ -323,6 +404,11 @@ struct Beckmann generateH(const vector3_type localV, const vector2_type u) + { + return impl::BeckmannGenerateH::__call(__base.A, localV, u); + } + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { @@ -391,6 +477,11 @@ struct Beckmann generateH(const vector3_type localV, const vector2_type u) + { + return impl::BeckmannGenerateH::__call(__base.A, localV, u); + } + template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { @@ -458,6 +549,11 @@ struct Beckmann generateH(const vector3_type localV, const vector2_type u) + { + return impl::BeckmannGenerateH::__call(__base.A, localV, u); + } + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index 7f9c77ad1c..2fbececd65 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -296,6 +296,36 @@ struct GGXCommon) > scalar_type ay2; scalar_type a2; }; + +template +struct GGXGenerateH +{ + using scalar_type = T; + using vector2_type = vector; + using vector3_type = vector; + + vector3_type __call(const vector2_type A, const vector3_type localV, const vector2_type u) + { + vector3_type V = nbl::hlsl::normalize(vector3_type(A.x*localV.x, A.y*localV.y, localV.z));//stretch view vector so that we're sampling as if roughness=1.0 + + scalar_type lensq = V.x*V.x + V.y*V.y; + vector3_type T1 = lensq > 0.0 ? vector3_type(-V.y, V.x, 0.0) * rsqrt(lensq) : vector3_type(1.0,0.0,0.0); + vector3_type T2 = cross(V,T1); + + scalar_type r = sqrt(u.x); + scalar_type phi = 2.0 * numbers::pi * u.y; + scalar_type t1 = r * cos(phi); + scalar_type t2 = r * sin(phi); + scalar_type s = 0.5 * (1.0 + V.z); + t2 = (1.0 - s)*sqrt(1.0 - t1*t1) + s*t2; + + //reprojection onto hemisphere + //TODO try it wothout the max(), not sure if -t1*t1-t2*t2>-1.0 + vector3_type H = t1*T1 + t2*T2 + sqrt(max(0.0, 1.0-t1*t1-t2*t2))*V; + //unstretch + return nbl::hlsl::normalize(vector3_type(A.x*H.x, A.y*H.y, H.z)); + } +}; } template @@ -338,6 +368,11 @@ struct GGX generateH(const vector3_type localV, const vector2_type u) + { + return impl::GGXGenerateH::__call(__base.A, localV, u); + } + template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { @@ -404,6 +439,11 @@ struct GGX generateH(const vector3_type localV, const vector2_type u) + { + return impl::GGXGenerateH::__call(__base.A, localV, u); + } + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { @@ -473,6 +513,11 @@ struct GGX generateH(const vector3_type localV, const vector2_type u) + { + return impl::GGXGenerateH::__call(__base.A, localV, u); + } + template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { @@ -541,6 +586,11 @@ struct GGX generateH(const vector3_type localV, const vector2_type u) + { + return impl::GGXGenerateH::__call(__base.A, localV, u); + } + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { From 72226bba1784422cf160a2a426ab3ae15ccd6cb5 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 9 Sep 2025 17:05:59 +0700 Subject: [PATCH 07/38] use new cook torrance base in microfacet bxdfs --- .../hlsl/bxdf/reflection/beckmann.hlsl | 318 ++---------------- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 286 ++-------------- .../hlsl/bxdf/transmission/beckmann.hlsl | 263 ++------------- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 289 ++-------------- 4 files changed, 109 insertions(+), 1047 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 267a8bad99..99ea9c4e35 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -19,8 +19,8 @@ namespace bxdf namespace reflection { -template -struct SBeckmannAnisotropic; +// template +// struct SBeckmannAnisotropic; template) struct SBeckmannIsotropic @@ -39,11 +39,8 @@ struct SBeckmannIsotropic NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); - using ndf_type = ndf::Beckmann; + using ndf_type = ndf::Beckmann; using fresnel_type = fresnel::Conductor; - using measure_transform_type = ndf::SDualMeasureQuant; - - NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_MAX; struct SCreationParams { @@ -53,23 +50,11 @@ struct SBeckmannIsotropic }; using creation_type = SCreationParams; - struct SBeckmannQuery - { - using scalar_type = scalar_type; - - scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } - scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - - scalar_type lambda_L; - scalar_type lambda_V; - }; - using query_type = SBeckmannQuery; - static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) { this_t retval; - retval.__base.ndf.A = vector2_type(A, A); - retval.__base.ndf.a2 = A*A; + retval.__base.ndf.__base.A = vector2_type(A, A); + retval.__base.ndf.__base.a2 = A*A; retval.__base.fresnel.eta = ior0; retval.__base.fresnel.etak = ior1; retval.__base.fresnel.etak2 = ior1*ior1; @@ -80,112 +65,33 @@ struct SBeckmannIsotropic return create(params.A, params.ior0, params.ior1); } - query_type createQuery(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) - { - query_type query; - ndf_type beckmann_ndf = __base.ndf; - query.lambda_L = beckmann_ndf.LambdaC2(_sample.getNdotL2()); - query.lambda_V = beckmann_ndf.LambdaC2(interaction.getNdotV2()); - return query; - } + // TODO: isotropic should also include anisotropic overloads - spectral_type eval(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - if (interaction.getNdotV() > numeric_limits::min) - { - struct SBeckmannG2overG1Query - { - using scalar_type = scalar_type; - - scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } - scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - - scalar_type lambda_L; - scalar_type lambda_V; - }; - - SBeckmannG2overG1Query g2_query; - g2_query.lambda_L = query.getLambdaL(); - g2_query.lambda_V = query.getLambdaV(); - - measure_transform_type dualMeasure = __base.template __DG(g2_query, _sample, interaction, cache); - dualMeasure.maxNdotV = interaction.getNdotV(_clamp); - scalar_type DG = dualMeasure.getProjectedLightMeasure(); - return __base.fresnel(cache.getVdotH()) * DG; - } - else - return hlsl::promote(0.0); + return __base.eval(_sample, interaction, cache); } sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache) { - SBeckmannAnisotropic beckmann_aniso = SBeckmannAnisotropic::create(__base.ndf.A.x, __base.ndf.A.y, __base.fresnel.eta, __base.fresnel.etak); - anisocache_type anisocache; - sample_type s = beckmann_aniso.generate(anisotropic_interaction_type::create(interaction), u, anisocache); - cache = anisocache.iso_cache; - return s; + return __base.generate(interaction, u, cache); } - scalar_type pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - struct SBeckmannDG1Query - { - using scalar_type = scalar_type; - - scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } - scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - - scalar_type ndf; - scalar_type lambda_V; - }; - - ndf_type beckmann_ndf = __base.ndf; - - SBeckmannDG1Query dg1_query; - dg1_query.ndf = __base.__D(cache); - dg1_query.lambda_V = query.getLambdaV(); - - measure_transform_type dualMeasure = __base.template __DG1(dg1_query); - dualMeasure.maxNdotV = interaction.getNdotV(_clamp); - return dualMeasure.getProjectedLightMeasure(); + return __base.pdf(_sample, interaction, cache); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - scalar_type _pdf = pdf(query, interaction, cache); - - spectral_type quo = hlsl::promote(0.0); - if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) - { - struct SBeckmannG2overG1Query - { - using scalar_type = scalar_type; - - scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } - scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - - scalar_type lambda_L; - scalar_type lambda_V; - }; - - ndf_type beckmann_ndf = __base.ndf; - SBeckmannG2overG1Query g2_query; - g2_query.lambda_L = query.getLambdaL(); - g2_query.lambda_V = query.getLambdaV(); - scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1(g2_query, _sample, interaction, cache); - const spectral_type reflectance = __base.fresnel(cache.getVdotH()); - quo = reflectance * G2_over_G1; - } - - return quotient_pdf_type::create(quo, _pdf); + return __base.quotient_and_pdf(_sample, interaction, cache); } - SCookTorrance __base; + SCookTorrance __base; }; -template -NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration) -struct SBeckmannAnisotropic) > +template) +struct SBeckmannAnisotropic { using this_t = SBeckmannAnisotropic; NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); @@ -201,11 +107,8 @@ struct SBeckmannAnisotropic; + using ndf_type = ndf::Beckmann; using fresnel_type = fresnel::Conductor; - using measure_transform_type = ndf::SDualMeasureQuant; - - NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_MAX; struct SCreationParams { @@ -216,24 +119,12 @@ struct SBeckmannAnisotropic numeric_limits::min) - { - struct SBeckmannG2overG1Query - { - using scalar_type = scalar_type; - - scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } - scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - - scalar_type lambda_L; - scalar_type lambda_V; - }; - - SBeckmannG2overG1Query g2_query; - g2_query.lambda_L = query.getLambdaL(); - g2_query.lambda_V = query.getLambdaV(); - - measure_transform_type dualMeasure = __base.template __DG(g2_query, _sample, interaction, cache); - dualMeasure.maxNdotV = interaction.getNdotV(_clamp); - scalar_type DG = dualMeasure.getProjectedLightMeasure(); - return __base.fresnel(cache.getVdotH()) * DG; - } - else - return hlsl::promote(0.0); - } - - vector3_type __generate(NBL_CONST_REF_ARG(vector3_type) localV, const vector2_type u) + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - vector2_type A = __base.ndf.A; - //stretch - vector3_type V = nbl::hlsl::normalize(vector3_type(A.x * localV.x, A.y * localV.y, localV.z)); - - vector2_type slope; - if (V.z > 0.9999)//V.z=NdotV=cosTheta in tangent space - { - scalar_type r = sqrt(-log(1.0 - u.x)); - scalar_type sinPhi = sin(2.0 * numbers::pi * u.y); - scalar_type cosPhi = cos(2.0 * numbers::pi * u.y); - slope = (vector2_type)r * vector2_type(cosPhi,sinPhi); - } - else - { - scalar_type cosTheta = V.z; - scalar_type sinTheta = sqrt(1.0 - cosTheta * cosTheta); - scalar_type tanTheta = sinTheta / cosTheta; - scalar_type cotTheta = 1.0 / tanTheta; - - scalar_type a = -1.0; - scalar_type c = erf(cosTheta); - scalar_type sample_x = max(u.x, 1.0e-6); - scalar_type theta = acos(cosTheta); - scalar_type fit = 1.0 + theta * (-0.876 + theta * (0.4265 - 0.0594*theta)); - scalar_type b = c - (1.0 + c) * pow(1.0-sample_x, fit); - - scalar_type normalization = 1.0 / (1.0 + c + numbers::inv_sqrtpi * tanTheta * exp(-cosTheta*cosTheta)); - - const int ITER_THRESHOLD = 10; - const float MAX_ACCEPTABLE_ERR = 1.0e-5; - int it = 0; - float value=1000.0; - while (++it < ITER_THRESHOLD && nbl::hlsl::abs(value) > MAX_ACCEPTABLE_ERR) - { - if (!(b >= a && b <= c)) - b = 0.5 * (a + c); - - float invErf = erfInv(b); - value = normalization * (1.0 + b + numbers::inv_sqrtpi * tanTheta * exp(-invErf * invErf)) - sample_x; - float derivative = normalization * (1.0 - invErf * cosTheta); - - if (value > 0.0) - c = b; - else - a = b; - - b -= value/derivative; - } - // TODO: investigate if we can replace these two erf^-1 calls with a box muller transform - slope.x = erfInv(b); - slope.y = erfInv(2.0 * max(u.y, 1.0e-6) - 1.0); - } - - scalar_type sinTheta = sqrt(1.0 - V.z*V.z); - scalar_type cosPhi = sinTheta==0.0 ? 1.0 : clamp(V.x/sinTheta, -1.0, 1.0); - scalar_type sinPhi = sinTheta==0.0 ? 0.0 : clamp(V.y/sinTheta, -1.0, 1.0); - //rotate - scalar_type tmp = cosPhi*slope.x - sinPhi*slope.y; - slope.y = sinPhi*slope.x + cosPhi*slope.y; - slope.x = tmp; - - //unstretch - slope = vector2_type(A.x,A.y)*slope; - - return nbl::hlsl::normalize(vector3_type(-slope, 1.0)); + return __base.eval(_sample, interaction, cache); } sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache) { - const vector3_type localV = interaction.getTangentSpaceV(); - const vector3_type H = __generate(localV, u); - - cache = anisocache_type::createForReflection(localV, H); - ray_dir_info_type localL; - bxdf::Reflect r = bxdf::Reflect::create(localV, H); - localL.direction = r(cache.iso_cache.getVdotH()); - - return sample_type::createFromTangentSpace(localL, interaction.getFromTangentSpace()); + return __base.generate(interaction, u, cache); } - scalar_type pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + scalar_type pdf(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - struct SBeckmannDG1Query - { - using scalar_type = scalar_type; - - scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } - scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - - scalar_type ndf; - scalar_type lambda_V; - }; - - ndf_type beckmann_ndf = __base.ndf; - - SBeckmannDG1Query dg1_query; - dg1_query.ndf = __base.__D(cache); - dg1_query.lambda_V = query.getLambdaV(); - - measure_transform_type dualMeasure = __base.template __DG1(dg1_query); - dualMeasure.maxNdotV = interaction.getNdotV(_clamp); - return dualMeasure.getProjectedLightMeasure(); + return __base.pdf(_sample, interaction, cache); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - scalar_type _pdf = pdf(query, interaction, cache); - - spectral_type quo = hlsl::promote(0.0); - if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) - { - struct SBeckmannG2overG1Query - { - using scalar_type = scalar_type; - - scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } - scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - - scalar_type lambda_L; - scalar_type lambda_V; - }; - - ndf_type beckmann_ndf = __base.ndf; - SBeckmannG2overG1Query g2_query; - g2_query.lambda_L = query.getLambdaL(); - g2_query.lambda_V = query.getLambdaV(); - scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1(g2_query, _sample, interaction, cache); - const spectral_type reflectance = __base.fresnel(cache.getVdotH()); - quo = reflectance * G2_over_G1; - } - - return quotient_pdf_type::create(quo, _pdf); + return __base.quotient_and_pdf(_sample, interaction, cache); } - SCookTorrance __base; + SCookTorrance __base; }; } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index f552e8f51d..1b990e67f9 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -19,8 +19,8 @@ namespace bxdf namespace reflection { -template -struct SGGXAnisotropic; +// template +// struct SGGXAnisotropic; template) struct SGGXIsotropic @@ -39,11 +39,8 @@ struct SGGXIsotropic NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); - using ndf_type = ndf::GGX; + using ndf_type = ndf::GGX; using fresnel_type = fresnel::Conductor; - using measure_transform_type = ndf::SDualMeasureQuant; - - NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_MAX; struct SCreationParams { @@ -53,24 +50,12 @@ struct SGGXIsotropic }; using creation_type = SCreationParams; - struct SGGXQuery - { - using scalar_type = scalar_type; - - scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } - scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } - - scalar_type devsh_v; - scalar_type devsh_l; - }; - using query_type = SGGXQuery; - static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) { this_t retval; - retval.__base.ndf.A = vector2_type(A, A); - retval.__base.ndf.a2 = A*A; - retval.__base.ndf.one_minus_a2 = scalar_type(1.0) - A*A; + retval.__base.ndf.__base.A = vector2_type(A, A); + retval.__base.ndf.__base.a2 = A*A; + retval.__base.ndf.__base.one_minus_a2 = scalar_type(1.0) - A*A; retval.__base.fresnel.eta = ior0; retval.__base.fresnel.etak = ior1; retval.__base.fresnel.etak2 = ior1*ior1; @@ -81,120 +66,31 @@ struct SGGXIsotropic return create(params.A, params.ior0, params.ior1); } - query_type createQuery(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - query_type query; - ndf_type ggx_ndf = __base.ndf; - query.devsh_v = ggx_ndf.devsh_part(interaction.getNdotV2()); - query.devsh_l = ggx_ndf.devsh_part(_sample.getNdotL2()); - return query; - } - - spectral_type eval(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) - { - if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) - { - struct SGGXG2XQuery - { - using scalar_type = scalar_type; - - scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } - scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } - BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } - - scalar_type devsh_v; - scalar_type devsh_l; - BxDFClampMode _clamp; - }; - - SGGXG2XQuery g2_query; - g2_query.devsh_v = query.getDevshV(); - g2_query.devsh_l = query.getDevshL(); - g2_query._clamp = _clamp; - - measure_transform_type dualMeasure = __base.template __DG(g2_query, _sample, interaction, cache); - dualMeasure.maxNdotL = _sample.getNdotL(_clamp); - scalar_type DG = dualMeasure.getProjectedLightMeasure(); - return __base.fresnel(cache.getVdotH()) * DG; - } - else - return hlsl::promote(0.0); + return __base.eval(_sample, interaction, cache); } sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache) { - SGGXAnisotropic ggx_aniso = SGGXAnisotropic::create(__base.ndf.A.x, __base.ndf.A.y, __base.fresnel.eta, __base.fresnel.etak); - anisocache_type anisocache; - sample_type s = ggx_aniso.generate(anisotropic_interaction_type::create(interaction), u, anisocache); - cache = anisocache.iso_cache; - return s; + return __base.generate(interaction, u, cache); } - scalar_type pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - struct SGGXDG1Query - { - using scalar_type = scalar_type; - - scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } - scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; } - - scalar_type ndf; - scalar_type G1_over_2NdotV; - }; - - SGGXDG1Query dg1_query; - ndf_type ggx_ndf = __base.ndf; - dg1_query.ndf = __base.__D(cache); - - const scalar_type devsh_v = query.getDevshV(); - dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(interaction.getNdotV(_clamp), devsh_v); - - measure_transform_type dualMeasure = __base.template __DG1(dg1_query); - return dualMeasure.getMicrofacetMeasure(); + return __base.pdf(_sample, interaction, cache); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - scalar_type _pdf = pdf(query, interaction, cache); - - spectral_type quo = hlsl::promote(0.0); - if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) - { - struct SGGXG2XQuery - { - using scalar_type = scalar_type; - - scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } - scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } - BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } - - scalar_type devsh_v; - scalar_type devsh_l; - BxDFClampMode _clamp; - }; - - ndf_type ggx_ndf = __base.ndf; - - SGGXG2XQuery g2_query; - g2_query.devsh_v = query.getDevshV(); - g2_query.devsh_l = query.getDevshL(); - g2_query._clamp = _clamp; - const scalar_type G2_over_G1 = ggx_ndf.template G2_over_G1(g2_query, _sample, interaction, cache); - - const spectral_type reflectance = __base.fresnel(cache.getVdotH()); - quo = reflectance * G2_over_G1; - } - - return quotient_pdf_type::create(quo, _pdf); + return __base.quotient_and_pdf(_sample, interaction, cache); } - SCookTorrance __base; + SCookTorrance __base; }; -template -NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration) -struct SGGXAnisotropic) > +template) +struct SGGXAnisotropic { using this_t = SGGXAnisotropic; NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); @@ -210,11 +106,8 @@ struct SGGXAnisotropic; + using ndf_type = ndf::GGX; using fresnel_type = fresnel::Conductor; - using measure_transform_type = ndf::SDualMeasureQuant; - - NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_MAX; struct SCreationParams { @@ -225,25 +118,13 @@ struct SGGXAnisotropic numeric_limits::min && interaction.getNdotV() > numeric_limits::min) - { - struct SGGXG2XQuery - { - using scalar_type = scalar_type; - - scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } - scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } - BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } - - scalar_type devsh_v; - scalar_type devsh_l; - BxDFClampMode _clamp; - }; - - SGGXG2XQuery g2_query; - g2_query.devsh_v = query.getDevshV(); - g2_query.devsh_l = query.getDevshL(); - g2_query._clamp = _clamp; - - measure_transform_type dualMeasure = __base.template __DG(g2_query, _sample, interaction, cache); - dualMeasure.maxNdotL = _sample.getNdotL(_clamp); - scalar_type DG = dualMeasure.getProjectedLightMeasure(); - return __base.fresnel(cache.getVdotH()) * DG; - } - else - return hlsl::promote(0.0); - } - - vector3_type __generate(NBL_CONST_REF_ARG(vector3_type) localV, const vector2_type u) - { - vector2_type A = __base.ndf.A; - vector3_type V = nbl::hlsl::normalize(vector3_type(A.x*localV.x, A.y*localV.y, localV.z));//stretch view vector so that we're sampling as if roughness=1.0 - - scalar_type lensq = V.x*V.x + V.y*V.y; - vector3_type T1 = lensq > 0.0 ? vector3_type(-V.y, V.x, 0.0) * rsqrt(lensq) : vector3_type(1.0,0.0,0.0); - vector3_type T2 = cross(V,T1); - - scalar_type r = sqrt(u.x); - scalar_type phi = 2.0 * numbers::pi * u.y; - scalar_type t1 = r * cos(phi); - scalar_type t2 = r * sin(phi); - scalar_type s = 0.5 * (1.0 + V.z); - t2 = (1.0 - s)*sqrt(1.0 - t1*t1) + s*t2; - - //reprojection onto hemisphere - //TODO try it wothout the max(), not sure if -t1*t1-t2*t2>-1.0 - vector3_type H = t1*T1 + t2*T2 + sqrt(max(0.0, 1.0-t1*t1-t2*t2))*V; - //unstretch - return nbl::hlsl::normalize(vector3_type(A.x*H.x, A.y*H.y, H.z)); + return __base.eval(_sample, interaction, cache); } sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache) { - const vector3_type localV = interaction.getTangentSpaceV(); - const vector3_type H = __generate(localV, u); - - cache = anisocache_type::createForReflection(localV, H); - ray_dir_info_type localL; - bxdf::Reflect r = bxdf::Reflect::create(localV, H); - localL.direction = r(cache.iso_cache.getVdotH()); - - return sample_type::createFromTangentSpace(localL, interaction.getFromTangentSpace()); + return __base.generate(interaction, u, cache); } scalar_type pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - struct SGGXDG1Query - { - using scalar_type = scalar_type; - - scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } - scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; } - - scalar_type ndf; - scalar_type G1_over_2NdotV; - }; - - SGGXDG1Query dg1_query; - ndf_type ggx_ndf = __base.ndf; - dg1_query.ndf = __base.__D(cache); - - const scalar_type devsh_v = query.getDevshV(); - dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(interaction.getNdotV(_clamp), devsh_v); - - measure_transform_type dualMeasure = __base.template __DG1(dg1_query); - return dualMeasure.getMicrofacetMeasure(); + return __base.pdf(_sample, interaction, cache); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - scalar_type _pdf = pdf(query, interaction, cache); - - spectral_type quo = hlsl::promote(0.0); - if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) - { - struct SGGXG2XQuery - { - using scalar_type = scalar_type; - - scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } - scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } - BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } - - scalar_type devsh_v; - scalar_type devsh_l; - BxDFClampMode _clamp; - }; - - ndf_type ggx_ndf = __base.ndf; - - SGGXG2XQuery g2_query; - g2_query.devsh_v = query.getDevshV(); - g2_query.devsh_l = query.getDevshL(); - g2_query._clamp = BxDFClampMode::BCM_MAX; - const scalar_type G2_over_G1 = ggx_ndf.template G2_over_G1(g2_query, _sample, interaction, cache); - - const spectral_type reflectance = __base.fresnel(cache.getVdotH()); - quo = reflectance * G2_over_G1; - } - - return quotient_pdf_type::create(quo, _pdf); + return __base.quotient_and_pdf(_sample, interaction, cache); } - SCookTorrance __base; + SCookTorrance __base; }; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 1dc6d85f73..fbb6824147 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -19,8 +19,8 @@ namespace bxdf namespace transmission { -template -struct SBeckmannDielectricAnisotropic; +// template +// struct SBeckmannDielectricAnisotropic; template) struct SBeckmannDielectricIsotropic @@ -40,13 +40,9 @@ struct SBeckmannDielectricIsotropic NBL_BXDF_CONFIG_ALIAS(quotient_pdf_type, Config); NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); - using brdf_type = reflection::SBeckmannIsotropic; - using ndf_type = ndf::Beckmann; + using ndf_type = ndf::Beckmann; using fresnel_type = fresnel::Dielectric; - using measure_transform_type = ndf::SDualMeasureQuant; - - NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; struct SCreationParams { @@ -55,23 +51,11 @@ struct SBeckmannDielectricIsotropic }; using creation_type = SCreationParams; - struct SBeckmannQuery - { - using scalar_type = scalar_type; - - scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } - scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - - scalar_type lambda_L; - scalar_type lambda_V; - }; - using query_type = SBeckmannQuery; - static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type A) { this_t retval; - retval.__base.ndf.A = vector2_type(A, A); - retval.__base.ndf.a2 = A*A; + retval.__base.ndf.__base.A = vector2_type(A, A); + retval.__base.ndf.__base.a2 = A*A; retval.__base.fresnel.orientedEta = orientedEta; retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; return retval; @@ -81,106 +65,31 @@ struct SBeckmannDielectricIsotropic return create(params.orientedEta, params.A); } - query_type createQuery(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - query_type query; - ndf_type beckmann_ndf = __base.ndf; - query.lambda_L = beckmann_ndf.LambdaC2(_sample.getNdotL2()); - query.lambda_V = beckmann_ndf.LambdaC2(interaction.getNdotV2()); - return query; - } - - spectral_type eval(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) - { - struct SBeckmannG2overG1Query - { - using scalar_type = scalar_type; - - scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } - scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - - scalar_type lambda_L; - scalar_type lambda_V; - }; - - SBeckmannG2overG1Query g2_query; - g2_query.lambda_L = query.getLambdaL(); - g2_query.lambda_V = query.getLambdaV(); - - fresnel::OrientedEtas orientedEta = __base.fresnel.orientedEta; - measure_transform_type dualMeasure = __base.template __DG(g2_query, _sample, interaction, cache); - dualMeasure.absNdotV = interaction.getNdotV(_clamp); - dualMeasure.orientedEta = orientedEta.value[0]; - scalar_type DG = dualMeasure.getProjectedLightMeasure(); - - return hlsl::promote(__base.fresnel(hlsl::abs(cache.getVdotH()))[0]) * DG; + return __base.eval(_sample, interaction, cache); } sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) { - SBeckmannDielectricAnisotropic beckmann_aniso = SBeckmannDielectricAnisotropic::create(__base.fresnel.orientedEta, __base.ndf.A.x, __base.ndf.A.y); - anisocache_type anisocache; - sample_type s = beckmann_aniso.generate(anisotropic_interaction_type::create(interaction), u, anisocache); - cache = anisocache.iso_cache; - return s; + return __base.generate(interaction, u, cache); } - scalar_type pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - struct SBeckmannDG1Query - { - using scalar_type = scalar_type; - - scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } - scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - - scalar_type ndf; - scalar_type lambda_V; - }; - - const scalar_type reflectance = __base.fresnel(hlsl::abs(cache.getVdotH()))[0]; - - SBeckmannDG1Query dg1_query; - dg1_query.ndf = __base.__D(cache); - dg1_query.lambda_V = query.getLambdaV(); - - fresnel::OrientedEtas orientedEta = __base.fresnel.orientedEta; - measure_transform_type dualMeasure = __base.template __DG1(dg1_query, cache); - dualMeasure.absNdotV = interaction.getNdotV(_clamp); - dualMeasure.orientedEta = orientedEta.value[0]; - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * dualMeasure.getProjectedLightMeasure(); + return __base.pdf(_sample, interaction, cache); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - scalar_type _pdf = pdf(query, interaction, cache); - - struct SBeckmannG2overG1Query - { - using scalar_type = scalar_type; - - scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } - scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - - scalar_type lambda_L; - scalar_type lambda_V; - }; - - ndf_type beckmann_ndf = __base.ndf; - SBeckmannG2overG1Query g2_query; - g2_query.lambda_L = query.getLambdaL(); - g2_query.lambda_V = query.getLambdaV(); - scalar_type quo = beckmann_ndf.template G2_over_G1(g2_query, _sample, interaction, cache); - - return quotient_pdf_type::create(quo, _pdf); + return __base.quotient_and_pdf(_sample, interaction, cache); } - SCookTorrance __base; + SCookTorrance __base; }; -template -NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration) -struct SBeckmannDielectricAnisotropic) > +template) +struct SBeckmannDielectricAnisotropic { using this_t = SBeckmannDielectricAnisotropic; NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); @@ -197,13 +106,9 @@ struct SBeckmannDielectricAnisotropic; - using ndf_type = ndf::Beckmann; + using ndf_type = ndf::Beckmann; using fresnel_type = fresnel::Dielectric; - using measure_transform_type = ndf::SDualMeasureQuant; - - NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; struct SCreationParams { @@ -213,24 +118,12 @@ struct SBeckmannDielectricAnisotropic) orientedEta, scalar_type ax, scalar_type ay) { this_t retval; - retval.__base.ndf.A = vector2_type(ax, ay); - retval.__base.ndf.ax2 = ax*ax; - retval.__base.ndf.ay2 = ay*ay; + retval.__base.ndf.__base.A = vector2_type(ax, ay); + retval.__base.ndf.__base.ax2 = ax*ax; + retval.__base.ndf.__base.ay2 = ay*ay; retval.__base.fresnel.orientedEta = orientedEta; retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; return retval; @@ -240,76 +133,14 @@ struct SBeckmannDielectricAnisotropic orientedEta = __base.fresnel.orientedEta; - measure_transform_type dualMeasure = __base.template __DG(g2_query, _sample, interaction, cache); - dualMeasure.absNdotV = interaction.getNdotV(_clamp); - dualMeasure.orientedEta = orientedEta.value[0]; - scalar_type DG = dualMeasure.getProjectedLightMeasure(); - - return hlsl::promote(__base.fresnel(hlsl::abs(cache.getVdotH()))[0]) * DG; - } - - sample_type __generate_wo_clamps(const vector3_type localV, const vector3_type H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(anisocache_type) cache) - { - const scalar_type localVdotH = nbl::hlsl::dot(localV,H); - const scalar_type reflectance = __base.fresnel(hlsl::abs(cache.getVdotH()))[0]; - - scalar_type rcpChoiceProb; - bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); - - cache = anisocache_type::createForReflection(localV, H); - - const scalar_type VdotH = cache.iso_cache.getVdotH(); - Refract r = Refract::create(localV, H); - cache.iso_cache.LdotH = hlsl::mix(VdotH, r.getNdotT(rcpEta.value2[0]), transmitted); - ray_dir_info_type localL; - bxdf::ReflectRefract rr; - rr.refract = r; - localL = localL.reflectRefract(rr, transmitted, rcpEta.value[0]); - - return sample_type::createFromTangentSpace(localL, m); + return __base.eval(_sample, interaction, cache); } sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) { - const vector3_type localV = interaction.getTangentSpaceV(); - - fresnel::OrientedEtas orientedEta = __base.fresnel.orientedEta; - fresnel::OrientedEtaRcps rcpEta = orientedEta.getReciprocals(); - - const vector3_type upperHemisphereV = hlsl::mix(localV, -localV, interaction.getNdotV() < scalar_type(0.0)); - - spectral_type dummyior; - brdf_type beckmann = brdf_type::create(__base.ndf.A.x, __base.ndf.A.y, dummyior, dummyior); - const vector3_type H = beckmann.__generate(upperHemisphereV, u.xy); - - return __generate_wo_clamps(localV, H, interaction.getFromTangentSpace(), u, rcpEta, cache); + return __base.generate(interaction, u, cache); } sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u) @@ -318,57 +149,17 @@ struct SBeckmannDielectricAnisotropic orientedEta = __base.fresnel.orientedEta; - measure_transform_type dualMeasure = __base.template __DG1(dg1_query, cache); - dualMeasure.absNdotV = interaction.getNdotV(_clamp); - dualMeasure.orientedEta = orientedEta.value[0]; - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * dualMeasure.getProjectedLightMeasure(); + return __base.pdf(_sample, interaction, cache); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - scalar_type _pdf = pdf(query, interaction, cache); - - struct SBeckmannG2overG1Query - { - using scalar_type = scalar_type; - - scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } - scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - - scalar_type lambda_L; - scalar_type lambda_V; - }; - - ndf_type beckmann_ndf = __base.ndf; - SBeckmannG2overG1Query g2_query; - g2_query.lambda_L = query.getLambdaL(); - g2_query.lambda_V = query.getLambdaV(); - scalar_type quo = beckmann_ndf.template G2_over_G1(g2_query, _sample, interaction, cache); - - return quotient_pdf_type::create(quo, _pdf); + return __base.quotient_and_pdf(_sample, interaction, cache); } - SCookTorrance __base; + SCookTorrance __base; }; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 2819c84570..e2c661668c 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -19,8 +19,8 @@ namespace bxdf namespace transmission { -template -struct SGGXDielectricAnisotropic; +// template +// struct SGGXDielectricAnisotropic; template) struct SGGXDielectricIsotropic @@ -40,13 +40,9 @@ struct SGGXDielectricIsotropic NBL_BXDF_CONFIG_ALIAS(quotient_pdf_type, Config); NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); - using brdf_type = reflection::SGGXIsotropic; - using ndf_type = ndf::GGX; + using ndf_type = ndf::GGX; using fresnel_type = fresnel::Dielectric; - using measure_transform_type = ndf::SDualMeasureQuant; - - NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; struct SCreationParams { @@ -55,24 +51,12 @@ struct SGGXDielectricIsotropic }; using creation_type = SCreationParams; - struct SGGXQuery - { - using scalar_type = scalar_type; - - scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } - scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } - - scalar_type devsh_v; - scalar_type devsh_l; - }; - using query_type = SGGXQuery; - static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type A) { this_t retval; - retval.__base.ndf.A = vector2_type(A, A); - retval.__base.ndf.a2 = A*A; - retval.__base.ndf.one_minus_a2 = scalar_type(1.0) - A*A; + retval.__base.ndf.__base.A = vector2_type(A, A); + retval.__base.ndf.__base.a2 = A*A; + retval.__base.ndf.__base.one_minus_a2 = scalar_type(1.0) - A*A; retval.__base.fresnel.orientedEta = orientedEta; retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; return retval; @@ -82,118 +66,31 @@ struct SGGXDielectricIsotropic return create(params.orientedEta, params.A); } - query_type createQuery(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) - { - query_type query; - ndf_type ggx_ndf = __base.ndf; - query.devsh_v = ggx_ndf.devsh_part(interaction.getNdotV2()); - query.devsh_l = ggx_ndf.devsh_part(_sample.getNdotL2()); - return query; - } - - spectral_type eval(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - struct SGGXG2XQuery - { - using scalar_type = scalar_type; - - scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } - scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } - BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } - - scalar_type devsh_v; - scalar_type devsh_l; - BxDFClampMode _clamp; - }; - - SGGXG2XQuery g2_query; - g2_query.devsh_v = query.getDevshV(); - g2_query.devsh_l = query.getDevshL(); - g2_query._clamp = _clamp; - - fresnel::OrientedEtas orientedEta = __base.fresnel.orientedEta; - measure_transform_type dualMeasure = __base.template __DG(g2_query, _sample, interaction, cache); - dualMeasure.absNdotL = _sample.getNdotL(_clamp); - dualMeasure.orientedEta = orientedEta.value[0]; - scalar_type DG = dualMeasure.getProjectedLightMeasure(); - - return hlsl::promote(__base.fresnel(hlsl::abs(cache.getVdotH()))[0]) * DG; + return __base.eval(_sample, interaction, cache); } sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) { - SGGXDielectricAnisotropic ggx_aniso = SGGXDielectricAnisotropic::create(__base.fresnel.orientedEta, __base.ndf.A.x, __base.ndf.A.y); - anisocache_type anisocache; - sample_type s = ggx_aniso.generate(anisotropic_interaction_type::create(interaction), u, anisocache); - cache = anisocache.iso_cache; - return s; + return __base.generate(interaction, u, cache); } - scalar_type pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - struct SGGXDG1Query - { - using scalar_type = scalar_type; - - scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } - scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; } - scalar_type getOrientedEta() NBL_CONST_MEMBER_FUNC { return orientedEta; } - - scalar_type ndf; - scalar_type G1_over_2NdotV; - scalar_type orientedEta; - }; - - SGGXDG1Query dg1_query; - fresnel::OrientedEtas orientedEta = __base.fresnel.orientedEta; - dg1_query.orientedEta = orientedEta.value[0]; - - const scalar_type reflectance = __base.fresnel(hlsl::abs(cache.getVdotH()))[0]; - - ndf_type ggx_ndf = __base.ndf; - dg1_query.ndf = __base.__D(cache); - dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(interaction.getNdotV(_clamp), query.getDevshV()); - - measure_transform_type dualMeasure = __base.template __DG1(dg1_query, cache); - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * dualMeasure.getMicrofacetMeasure(); + return __base.pdf(_sample, interaction, cache); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - scalar_type _pdf = pdf(query, interaction, cache); - const bool transmitted = cache.isTransmission(); - - struct SGGXG2XQuery - { - using scalar_type = scalar_type; - - scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } - scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } - BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } - - scalar_type devsh_v; - scalar_type devsh_l; - BxDFClampMode _clamp; - }; - - ndf_type ggx_ndf = __base.ndf; - SGGXG2XQuery g2_query; - g2_query.devsh_v = query.getDevshV(); - g2_query.devsh_l = query.getDevshL(); - g2_query._clamp = _clamp; - - scalar_type quo; - quo = ggx_ndf.template G2_over_G1(g2_query, _sample, interaction, cache); - - return quotient_pdf_type::create(quo, _pdf); + return __base.quotient_and_pdf(_sample, interaction, cache); } - SCookTorrance __base; + SCookTorrance __base; }; -template -NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration) -struct SGGXDielectricAnisotropic) > +template) +struct SGGXDielectricAnisotropic { using this_t = SGGXDielectricAnisotropic; NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); @@ -210,13 +107,9 @@ struct SGGXDielectricAnisotropic; using ndf_type = ndf::GGX; using fresnel_type = fresnel::Dielectric; - using measure_transform_type = ndf::SDualMeasureQuant; - - NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; struct SCreationParams { @@ -226,25 +119,13 @@ struct SGGXDielectricAnisotropic) orientedEta, scalar_type ax, scalar_type ay) { this_t retval; - retval.__base.ndf.A = vector2_type(ax, ay); - retval.__base.ndf.ax2 = ax*ax; - retval.__base.ndf.ay2 = ay*ay; - retval.__base.ndf.a2 = ax*ay; + retval.__base.ndf.__base.A = vector2_type(ax, ay); + retval.__base.ndf.__base.ax2 = ax*ax; + retval.__base.ndf.__base.ay2 = ay*ay; + retval.__base.ndf.__base.a2 = ax*ay; retval.__base.fresnel.orientedEta = orientedEta; retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; return retval; @@ -254,79 +135,14 @@ struct SGGXDielectricAnisotropic orientedEta = __base.fresnel.orientedEta; - measure_transform_type dualMeasure = __base.template __DG(g2_query, _sample, interaction, cache); - dualMeasure.absNdotL = _sample.getNdotL(_clamp); - dualMeasure.orientedEta = orientedEta.value[0]; - scalar_type DG = dualMeasure.getProjectedLightMeasure(); - - return hlsl::promote(__base.fresnel(hlsl::abs(cache.getVdotH()))[0]) * DG; - } - - sample_type __generate_wo_clamps(const vector3_type localV, const vector3_type H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(anisocache_type) cache) + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - const scalar_type localVdotH = nbl::hlsl::dot(localV,H); - const scalar_type reflectance = __base.fresnel(hlsl::abs(cache.getVdotH()))[0]; - - scalar_type rcpChoiceProb; - bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); - - cache = anisocache_type::createForReflection(localV, H); - - const scalar_type VdotH = cache.iso_cache.getVdotH(); - Refract r = Refract::create(localV, H); - cache.iso_cache.LdotH = hlsl::mix(VdotH, r.getNdotT(rcpEta.value2[0]), transmitted); - ray_dir_info_type localL; - bxdf::ReflectRefract rr; - rr.refract = r; - localL = localL.reflectRefract(rr, transmitted, rcpEta.value[0]); - - return sample_type::createFromTangentSpace(localL, m); + return __base.eval(_sample, interaction, cache); } sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) { - const vector3_type localV = interaction.getTangentSpaceV(); - - fresnel::OrientedEtas orientedEta = __base.fresnel.orientedEta; - fresnel::OrientedEtaRcps rcpEta = orientedEta.getReciprocals(); - - const vector3_type upperHemisphereV = hlsl::mix(localV, -localV, interaction.getNdotV() < scalar_type(0.0)); - - spectral_type dummyior; - brdf_type ggx = brdf_type::create(__base.ndf.A.x, __base.ndf.A.y, dummyior, dummyior); - const vector3_type H = ggx.__generate(upperHemisphereV, u.xy); - - return __generate_wo_clamps(localV, H, interaction.getFromTangentSpace(), u, rcpEta, cache); + return __base.generate(interaction, u, cache); } sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u) @@ -335,66 +151,17 @@ struct SGGXDielectricAnisotropic orientedEta = __base.fresnel.orientedEta; - dg1_query.orientedEta = orientedEta.value[0]; - - const scalar_type reflectance = __base.fresnel(hlsl::abs(cache.getVdotH()))[0]; - - ndf_type ggx_ndf = __base.ndf; - dg1_query.ndf = __base.__D(cache); - dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(interaction.getNdotV(_clamp), query.getDevshV()); - - measure_transform_type dualMeasure = __base.template __DG1(dg1_query, cache); - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * dualMeasure.getMicrofacetMeasure(); + return __base.pdf(_sample, interaction, cache); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - scalar_type _pdf = pdf(query, interaction, cache); - const bool transmitted = cache.isTransmission(); - - struct SGGXG2XQuery - { - using scalar_type = scalar_type; - - scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } - scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } - BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } - - scalar_type devsh_v; - scalar_type devsh_l; - BxDFClampMode _clamp; - }; - - ndf_type ggx_ndf = __base.ndf; - SGGXG2XQuery g2_query; - g2_query.devsh_v = query.getDevshV(); - g2_query.devsh_l = query.getDevshL(); - g2_query._clamp = _clamp; - - scalar_type quo; - quo = ggx_ndf.template G2_over_G1(g2_query, _sample, interaction, cache); - - return quotient_pdf_type::create(quo, _pdf); + return __base.quotient_and_pdf(_sample, interaction, cache); } - SCookTorrance __base; + SCookTorrance __base; }; } From ad13044a6cf9652663c6b2337d75a51848ada6b4 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 10 Sep 2025 12:19:19 +0700 Subject: [PATCH 08/38] numerous typo bug fixes --- .../builtin/hlsl/bxdf/cook_torrance_base.hlsl | 62 +++++------ .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 66 +++++++----- include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 100 ++++++++++-------- .../ndf/microfacet_to_light_transform.hlsl | 12 +-- .../hlsl/bxdf/reflection/beckmann.hlsl | 6 +- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 12 +-- .../hlsl/bxdf/transmission/beckmann.hlsl | 8 +- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 8 +- 8 files changed, 149 insertions(+), 125 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl index 0df9b13325..7ed24195f8 100644 --- a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl @@ -22,12 +22,13 @@ template struct SCookTorrance; template -NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration && ndf::NDF && fresnel::Fresnel) -struct SCookTorrance && ndf::NDF && fresnel::Fresnel) > +NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration /*&& ndf::NDF*/ && fresnel::Fresnel) +struct SCookTorrance /*&& ndf::NDF*/ && fresnel::Fresnel) > { 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(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); @@ -51,12 +52,12 @@ struct SCookTorrance(qq, _sample, interaction, cache); scalar_type DG = D.projectedLightMeasure; - if (any >(ndf.A > hlsl::promote(numeric_limits::min))) + if (any >(ndf.__base.A > hlsl::promote(numeric_limits::min))) { quant_type G2 = ndf.template correlated(gq, qq, _sample, interaction); DG *= G2.microfacetMeasure; } - return __base.fresnel(cache.getVdotH()) * DG; + return fresnel(cache.getVdotH()) * DG; } else return hlsl::promote(0.0); @@ -74,12 +75,12 @@ struct SCookTorrance(qq, _sample, interaction, cache); scalar_type DG = D.projectedLightMeasure; - if (any >(ndf.A > hlsl::promote(numeric_limits::min))) + if (any >(ndf.__base.A > hlsl::promote(numeric_limits::min))) { quant_type G2 = ndf.template correlated(gq, qq, _sample, interaction); DG *= G2.microfacetMeasure; } - return __base.fresnel(cache.getVdotH()) * DG; + return fresnel(cache.getVdotH()) * DG; } else return hlsl::promote(0.0); @@ -130,7 +131,7 @@ struct SCookTorrance(0.0); if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) @@ -138,8 +139,8 @@ struct SCookTorrance(_sample, interaction); - scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1(gq, _sample, interaction, cache); - const spectral_type reflectance = __base.fresnel(cache.getVdotH()); + scalar_type G2_over_G1 = ndf.template G2_over_G1(gq, _sample, interaction, cache); + const spectral_type reflectance = fresnel(cache.getVdotH()); quo = reflectance * G2_over_G1; } @@ -147,7 +148,7 @@ struct SCookTorrance(0.0); if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) @@ -155,8 +156,8 @@ struct SCookTorrance(_sample, interaction); - scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1(gq, _sample, interaction, cache); - const spectral_type reflectance = __base.fresnel(cache.getVdotH()); + scalar_type G2_over_G1 = ndf.template G2_over_G1(gq, _sample, interaction, cache); + const spectral_type reflectance = fresnel(cache.getVdotH()); quo = reflectance * G2_over_G1; } @@ -168,13 +169,14 @@ struct SCookTorrance -NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration && ndf::NDF && fresnel::Fresnel) -struct SCookTorrance && ndf::NDF && fresnel::Fresnel) > +NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration /*&& ndf::NDF*/ && fresnel::Fresnel) +struct SCookTorrance /*&& ndf::NDF*/ && fresnel::Fresnel) > { 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); @@ -190,36 +192,36 @@ struct SCookTorrance orientedEta = __base.fresnel.orientedEta; + fresnel::OrientedEtas orientedEta = fresnel.orientedEta; quant_query_type qq = ndf.template createQuantQuery(cache, orientedEta.value[0]); g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); quant_type D = ndf.template D(qq, _sample, interaction, cache); scalar_type DG = D.projectedLightMeasure; - if (any >(ndf.A > hlsl::promote(numeric_limits::min))) + if (any >(ndf.__base.A > hlsl::promote(numeric_limits::min))) { quant_type G2 = ndf.template correlated(gq, qq, _sample, interaction); DG *= G2.microfacetMeasure; } - return hlsl::promote(__base.fresnel(hlsl::abs(cache.getVdotH()))[0]) * DG; + return hlsl::promote(fresnel(hlsl::abs(cache.getVdotH()))[0]) * DG; } spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { using quant_query_type = typename N::quant_query_type; using g2g1_query_type = typename N::g2g1_query_type; - fresnel::OrientedEtas orientedEta = __base.fresnel.orientedEta; + fresnel::OrientedEtas orientedEta = fresnel.orientedEta; quant_query_type qq = ndf.template createQuantQuery(cache, orientedEta.value[0]); g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); quant_type D = ndf.template D(qq, _sample, interaction, cache); scalar_type DG = D.projectedLightMeasure; - if (any >(ndf.A > hlsl::promote(numeric_limits::min))) + if (any >(ndf.__base.A > hlsl::promote(numeric_limits::min))) { quant_type G2 = ndf.template correlated(gq, qq, _sample, interaction); DG *= G2.microfacetMeasure; } - return hlsl::promote(__base.fresnel(hlsl::abs(cache.getVdotH()))[0]) * DG; + return hlsl::promote(fresnel(hlsl::abs(cache.getVdotH()))[0]) * DG; } sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(isocache_type) cache) @@ -233,13 +235,13 @@ struct SCookTorrance orientedEta = __base.fresnel.orientedEta; + fresnel::OrientedEtas orientedEta = fresnel.orientedEta; fresnel::OrientedEtaRcps rcpEta = orientedEta.getReciprocals(); const vector3_type upperHemisphereV = hlsl::mix(localV, -localV, interaction.getNdotV() < scalar_type(0.0)); const vector3_type H = ndf.generateH(upperHemisphereV, u.xy); - const scalar_type reflectance = __base.fresnel(hlsl::abs(cache.getVdotH()))[0]; + const scalar_type reflectance = fresnel(hlsl::abs(cache.getVdotH()))[0]; scalar_type rcpChoiceProb; scalar_type z = u.z; @@ -262,12 +264,12 @@ struct SCookTorrance orientedEta = __base.fresnel.orientedEta; + fresnel::OrientedEtas orientedEta = fresnel.orientedEta; quant_query_type qq = ndf.template createQuantQuery(cache, orientedEta.value[0]); dg1_query_type dq = ndf.template createDG1Query(interaction, cache); quant_type DG1 = ndf.template DG1(dq, qq, _sample, interaction); - const spectral_type reflectance = __base.fresnel(cache.getVdotH()); + const scalar_type reflectance = fresnel(hlsl::abs(cache.getVdotH()))[0]; return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * DG1.projectedLightMeasure; } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) @@ -275,34 +277,34 @@ struct SCookTorrance orientedEta = __base.fresnel.orientedEta; + fresnel::OrientedEtas orientedEta = fresnel.orientedEta; quant_query_type qq = ndf.template createQuantQuery(cache, orientedEta.value[0]); dg1_query_type dq = ndf.template createDG1Query(interaction, cache); quant_type DG1 = ndf.template DG1(dq, qq, _sample, interaction); - const spectral_type reflectance = __base.fresnel(cache.getVdotH()); + const scalar_type reflectance = fresnel(hlsl::abs(cache.getVdotH()))[0]; return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * DG1.projectedLightMeasure; } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - scalar_type _pdf = pdf(interaction, cache); + scalar_type _pdf = pdf(_sample, interaction, cache); using g2g1_query_type = typename N::g2g1_query_type; g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); - scalar_type quo = beckmann_ndf.template G2_over_G1(gq, _sample, interaction, cache); + scalar_type quo = ndf.template G2_over_G1(gq, _sample, interaction, cache); return quotient_pdf_type::create(quo, _pdf); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - scalar_type _pdf = pdf(interaction, cache); + scalar_type _pdf = pdf(_sample, interaction, cache); using g2g1_query_type = typename N::g2g1_query_type; g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); - scalar_type quo = beckmann_ndf.template G2_over_G1(gq, _sample, interaction, cache); + scalar_type quo = ndf.template G2_over_G1(gq, _sample, interaction, cache); return quotient_pdf_type::create(quo, _pdf); } diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index 78fec05375..398df717e2 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -89,7 +89,7 @@ struct SBeckmannG2overG1Query }; template -struct SQuantQuery +struct SBeckmannQuantQuery { using scalar_type = T; @@ -124,7 +124,7 @@ struct BeckmannCommon(scalar_type(0.0), nom / denom, c < scalar_type(1.6)); } - static scalar_type LambdaC2(scalar_type NdotX2) + scalar_type LambdaC2(scalar_type NdotX2) { return Lambda(C2(NdotX2)); } @@ -182,7 +182,7 @@ struct BeckmannCommon(scalar_type(0.0), nom / denom, c < scalar_type(1.6)); } - static scalar_type LambdaC2(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2) + scalar_type LambdaC2(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2) { return Lambda(C2(TdotX2, BdotX2, NdotX2)); } @@ -225,7 +225,7 @@ struct BeckmannGenerateH using vector2_type = vector; using vector3_type = vector; - vector3_type __call(const vector2_type A, const vector3_type localV, const vector2_type u) + static vector3_type __call(const vector2_type A, const vector3_type localV, const vector2_type u) { //stretch vector3_type V = nbl::hlsl::normalize(vector3_type(A.x * localV.x, A.y * localV.y, localV.z)); @@ -306,10 +306,12 @@ struct Beckmann; using quant_type = SDualMeasureQuant; + using vector2_type = vector; + using vector3_type = vector; using dg1_query_type = typename base_type::dg1_query_type; using g2g1_query_type = typename base_type::g2g1_query_type; - using quant_query_type = SQuantQuery; + using quant_query_type = impl::SBeckmannQuantQuery; template) quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) @@ -322,15 +324,15 @@ struct Beckmann(cache); - dg1_query.lambda_V = base_type::LambdaC2(interaction.getNdotV2()); + dg1_query.lambda_V = __base.LambdaC2(interaction.getNdotV2()); return dg1_query; } template && surface_interactions::Isotropic) g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { g2g1_query_type g2_query; - g2_query.lambda_L = base_type::LambdaC2(_sample.getNdotL2()); - g2_query.lambda_V = base_type::LambdaC2(interaction.getNdotV2()); + g2_query.lambda_L = __base.LambdaC2(_sample.getNdotL2()); + g2_query.lambda_V = __base.LambdaC2(interaction.getNdotV2()); return g2_query; } @@ -376,10 +378,12 @@ struct Beckmann; using quant_type = SDualMeasureQuant; + using vector2_type = vector; + using vector3_type = vector; using dg1_query_type = typename base_type::dg1_query_type; using g2g1_query_type = typename base_type::g2g1_query_type; - using quant_query_type = SQuantQuery; + using quant_query_type = impl::SBeckmannQuantQuery; template) quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) @@ -392,15 +396,15 @@ struct Beckmann(cache); - dg1_query.lambda_V = base_type::LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + dg1_query.lambda_V = __base.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); return dg1_query; } template && surface_interactions::Anisotropic) g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { g2g1_query_type g2_query; - g2_query.lambda_L = base_type::LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); - g2_query.lambda_V = base_type::LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + g2_query.lambda_L = __base.LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); + g2_query.lambda_V = __base.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); return g2_query; } @@ -447,10 +451,12 @@ struct Beckmann; using quant_type = SDualMeasureQuant; + using vector2_type = vector; + using vector3_type = vector; using dg1_query_type = typename base_type::dg1_query_type; using g2g1_query_type = typename base_type::g2g1_query_type; - using quant_query_type = SQuantQuery; + using quant_query_type = impl::SBeckmannQuantQuery; template) quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) @@ -465,15 +471,15 @@ struct Beckmann(cache); - dg1_query.lambda_V = base_type::LambdaC2(interaction.getNdotV2()); + dg1_query.lambda_V = __base.LambdaC2(interaction.getNdotV2()); return dg1_query; } template && surface_interactions::Isotropic) g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { g2g1_query_type g2_query; - g2_query.lambda_L = base_type::LambdaC2(_sample.getNdotL2()); - g2_query.lambda_V = base_type::LambdaC2(interaction.getNdotV2()); + g2_query.lambda_L = __base.LambdaC2(_sample.getNdotL2()); + g2_query.lambda_V = __base.LambdaC2(interaction.getNdotV2()); return g2_query; } @@ -486,21 +492,21 @@ struct Beckmann(cache); - return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); } template && surface_interactions::Isotropic) quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { scalar_type dg1 = __base.DG1(query); - return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); } template && surface_interactions::Isotropic) quant_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { scalar_type g = __base.template correlated(query, _sample, interaction); - return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); } template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) @@ -519,10 +525,12 @@ struct Beckmann; using quant_type = SDualMeasureQuant; + using vector2_type = vector; + using vector3_type = vector; using dg1_query_type = typename base_type::dg1_query_type; using g2g1_query_type = typename base_type::g2g1_query_type; - using quant_query_type = SQuantQuery; + using quant_query_type = impl::SBeckmannQuantQuery; template) quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) @@ -537,15 +545,15 @@ struct Beckmann(cache); - dg1_query.lambda_V = base_type::LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + dg1_query.lambda_V = __base.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); return dg1_query; } template && surface_interactions::Anisotropic) g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { g2g1_query_type g2_query; - g2_query.lambda_L = base_type::LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); - g2_query.lambda_V = base_type::LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + g2_query.lambda_L = __base.LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); + g2_query.lambda_V = __base.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); return g2_query; } @@ -558,21 +566,21 @@ struct Beckmann(cache); - return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); } template && surface_interactions::Anisotropic) quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - scalar_type dg1 = __base.template DG1(query); - return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + scalar_type dg1 = __base.DG1(query); + return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); } template && surface_interactions::Anisotropic) quant_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { scalar_type g = __base.template correlated(query, _sample, interaction); - return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); } template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index 2fbececd65..30ec30ebea 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -65,9 +65,10 @@ namespace ndf namespace impl { +template struct SGGXDG1Query { - using scalar_type = scalar_type; + using scalar_type = T; scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; } @@ -76,9 +77,10 @@ struct SGGXDG1Query scalar_type G1_over_2NdotV; }; +template struct SGGXG2XQuery { - using scalar_type = scalar_type; + using scalar_type = T; scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } @@ -90,7 +92,7 @@ struct SGGXG2XQuery }; template -struct SQuantQuery +struct SGGXQuantQuery { using scalar_type = T; @@ -125,13 +127,13 @@ struct GGXCommon) > return scalar_type(0.5) * query.getNdf() * query.getG1over2NdotV(); } - static scalar_type devsh_part(scalar_type NdotX2) + scalar_type devsh_part(scalar_type NdotX2) { assert(a2 >= numeric_limits::min); return sqrt(a2 + one_minus_a2 * NdotX2); } - static scalar_type G1_wo_numerator(scalar_type absNdotX, scalar_type NdotX2) + scalar_type G1_wo_numerator(scalar_type absNdotX, scalar_type NdotX2) { return scalar_type(1.0) / (absNdotX + devsh_part(NdotX2)); } @@ -159,7 +161,7 @@ struct GGXCommon) > { BxDFClampMode _clamp = query.getClampMode(); assert(_clamp != BxDFClampMode::BCM_NONE); - return scalar_type(4.0) * interaction.getNdotV(_clamp) * _sample.getNdotL(_clamp) * correlated_wo_numerator(query, _sample, interaction); + return scalar_type(4.0) * interaction.getNdotV(_clamp) * _sample.getNdotL(_clamp) * correlated_wo_numerator(query, _sample, interaction); } template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) @@ -227,13 +229,13 @@ struct GGXCommon) > return ggx.DG1(query); } - static scalar_type devsh_part(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2) + scalar_type devsh_part(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2) { assert(ax2 >= numeric_limits::min && ay2 >= numeric_limits::min); return sqrt(TdotX2 * ax2 + BdotX2 * ay2 + NdotX2); } - static scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2) + scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2) { return scalar_type(1.0) / (NdotX + devsh_part(TdotX2, BdotX2, NdotX2)); } @@ -260,7 +262,7 @@ struct GGXCommon) > { BxDFClampMode _clamp = query.getClampMode(); assert(_clamp != BxDFClampMode::BCM_NONE); - return scalar_type(4.0) * interaction.getNdotV(_clamp) * _sample.getNdotL(_clamp) * correlated_wo_numerator(query, _sample, interaction); + return scalar_type(4.0) * interaction.getNdotV(_clamp) * _sample.getNdotL(_clamp) * correlated_wo_numerator(query, _sample, interaction); } template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) @@ -304,7 +306,7 @@ struct GGXGenerateH using vector2_type = vector; using vector3_type = vector; - vector3_type __call(const vector2_type A, const vector3_type localV, const vector2_type u) + static vector3_type __call(const vector2_type A, const vector3_type localV, const vector2_type u) { vector3_type V = nbl::hlsl::normalize(vector3_type(A.x*localV.x, A.y*localV.y, localV.z));//stretch view vector so that we're sampling as if roughness=1.0 @@ -339,10 +341,12 @@ struct GGX; using quant_type = SDualMeasureQuant; + using vector2_type = vector; + using vector3_type = vector; using dg1_query_type = typename base_type::dg1_query_type; using g2g1_query_type = typename base_type::g2g1_query_type; - using quant_query_type = SQuantQuery; + using quant_query_type = impl::SGGXQuantQuery; template) quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) @@ -355,15 +359,15 @@ struct GGX(cache); - dg1_query.devsh_v = base_type::devsh_part(interaction.getNdotV2()); + dg1_query.G1_over_2NdotV = __base.G1_wo_numerator(interaction.getNdotV(BxDFClampMode::BCM_ABS), interaction.getNdotV2()); return dg1_query; } template && surface_interactions::Isotropic) g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { g2g1_query_type g2_query; - g2_query.devsh_l = base_type::devsh_part(_sample.getNdotL2()); - g2_query.devsh_v = base_type::devsh_part(interaction.getNdotV2()); + g2_query.devsh_l = __base.devsh_part(_sample.getNdotL2()); + g2_query.devsh_v = __base.devsh_part(interaction.getNdotV2()); g2_query._clamp = BxDFClampMode::BCM_MAX; return g2_query; } @@ -395,9 +399,9 @@ struct GGX && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) - quant_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { - return __base.template G2_over_G1(query, _sample, interaction, cache); + return __base.template G2_over_G1(query, _sample, interaction, cache); } base_type __base; @@ -410,10 +414,12 @@ struct GGX; using quant_type = SDualMeasureQuant; + using vector2_type = vector; + using vector3_type = vector; using dg1_query_type = typename base_type::dg1_query_type; using g2g1_query_type = typename base_type::g2g1_query_type; - using quant_query_type = SQuantQuery; + using quant_query_type = impl::SGGXQuantQuery; template) quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) @@ -426,15 +432,15 @@ struct GGX(cache); - dg1_query.devsh_v = base_type::devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + dg1_query.G1_over_2NdotV = __base.G1_wo_numerator(interaction.getNdotV(BxDFClampMode::BCM_ABS), interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); return dg1_query; } template && surface_interactions::Anisotropic) g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { g2g1_query_type g2_query; - g2_query.devsh_l = base_type::devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); - g2_query.devsh_v = base_type::devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + g2_query.devsh_l = __base.devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); + g2_query.devsh_v = __base.devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); g2_query._clamp = BxDFClampMode::BCM_MAX; return g2_query; } @@ -466,7 +472,7 @@ struct GGX && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - quant_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { return __base.template G2_over_G1(query, _sample, interaction, cache); } @@ -482,10 +488,12 @@ struct GGX; using quant_type = SDualMeasureQuant; + using vector2_type = vector; + using vector3_type = vector; using dg1_query_type = typename base_type::dg1_query_type; using g2g1_query_type = typename base_type::g2g1_query_type; - using quant_query_type = SQuantQuery; + using quant_query_type = impl::SGGXQuantQuery; template) quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) @@ -500,15 +508,15 @@ struct GGX(cache); - dg1_query.devsh_v = base_type::devsh_part(interaction.getNdotV2()); + dg1_query.G1_over_2NdotV = __base.G1_wo_numerator(interaction.getNdotV(BxDFClampMode::BCM_ABS), interaction.getNdotV2()); return dg1_query; } template && surface_interactions::Isotropic) g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { g2g1_query_type g2_query; - g2_query.devsh_l = base_type::devsh_part(_sample.getNdotL2()); - g2_query.devsh_v = base_type::devsh_part(interaction.getNdotV2()); + g2_query.devsh_l = __base.devsh_part(_sample.getNdotL2()); + g2_query.devsh_v = __base.devsh_part(interaction.getNdotV2()); g2_query._clamp = BxDFClampMode::BCM_ABS; return g2_query; } @@ -522,27 +530,27 @@ struct GGX(cache); - return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); } template && surface_interactions::Isotropic) quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { scalar_type dg1 = __base.DG1(query); - return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); } template && surface_interactions::Isotropic) quant_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - scalar_type g = __base.template correlated(query, _sample, interaction); - return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + scalar_type g = __base.template correlated(query, _sample, interaction); + return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); } template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) - quant_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { - return __base.template G2_over_G1(query, _sample, interaction, cache); + return __base.template G2_over_G1(query, _sample, interaction, cache); } base_type __base; @@ -555,10 +563,12 @@ struct GGX; using quant_type = SDualMeasureQuant; + using vector2_type = vector; + using vector3_type = vector; using dg1_query_type = typename base_type::dg1_query_type; using g2g1_query_type = typename base_type::g2g1_query_type; - using quant_query_type = SQuantQuery; + using quant_query_type = impl::SGGXQuantQuery; template) quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) @@ -573,15 +583,15 @@ struct GGX(cache); - dg1_query.devsh_v = base_type::devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + dg1_query.G1_over_2NdotV = __base.G1_wo_numerator(interaction.getNdotV(BxDFClampMode::BCM_ABS), interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); return dg1_query; } template && surface_interactions::Anisotropic) g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { g2g1_query_type g2_query; - g2_query.devsh_l = base_type::devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); - g2_query.devsh_v = base_type::devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + g2_query.devsh_l = __base.devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); + g2_query.devsh_v = __base.devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); g2_query._clamp = BxDFClampMode::BCM_ABS; return g2_query; } @@ -595,25 +605,25 @@ struct GGX(cache); - return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); } template && surface_interactions::Anisotropic) quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - scalar_type dg1 = __base.template DG1(query); - return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + scalar_type dg1 = __base.DG1(query); + return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); } template && surface_interactions::Anisotropic) - quant_type correlated(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + quant_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { scalar_type g = __base.template correlated(query, _sample, interaction); - return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); } template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - quant_type G2_over_G1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { return __base.template G2_over_G1(query, _sample, interaction, cache); } @@ -626,8 +636,12 @@ namespace impl { template struct is_ggx : bool_constant< - is_same >::value || - is_same >::value + is_same >::value || + is_same >::value || + is_same >::value || + is_same >::value || + is_same >::value || + is_same >::value > {}; } diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl index f53fcca645..901695825c 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl @@ -38,15 +38,15 @@ namespace impl template struct createDualMeasureQuantity_helper { - using scalar_type = vector_traits::scalar_type; + using scalar_type = typename vector_traits::scalar_type; static SDualMeasureQuant __call(const T microfacetMeasure, scalar_type clampedNdotV, scalar_type clampedNdotL, scalar_type VdotHLdotH, scalar_type VdotH_etaLdotH) { SDualMeasureQuant retval; retval.microfacetMeasure = microfacetMeasure; // do constexpr booleans first so optimizer picks up this and short circuits - const bool transmitted = reflect_refract==MTT_REFRACT || reflect_refract!=MTT_REFLECT && VdotHLdotH(0.25,VdotHLdotH,transmitted); + const bool transmitted = reflect_refract==MTT_REFRACT || (reflect_refract!=MTT_REFLECT && VdotHLdotH < scalar_type(0.0)); + retval.projectedLightMeasure = microfacetMeasure*mix(scalar_type(0.25),VdotHLdotH,transmitted); scalar_type denominator = clampedNdotV; if (transmitted) // VdotHLdotH is negative under transmission, so thats denominator is negative denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; @@ -57,13 +57,13 @@ struct createDualMeasureQuantity_helper } template -SDualMeasureQuant createDualMeasureQuantity(const T specialMeasure, vector_traits::scalar_type clampedNdotV, vector_traits::scalar_type clampedNdotL) +SDualMeasureQuant createDualMeasureQuantity(const T specialMeasure, typename vector_traits::scalar_type clampedNdotV, typename vector_traits::scalar_type clampedNdotL) { - vector_traits::scalar_type dummy; + typename vector_traits::scalar_type dummy; return impl::createDualMeasureQuantity_helper::__call(specialMeasure,clampedNdotV,clampedNdotL,dummy,dummy); } template -SDualMeasureQuant createDualMeasureQuantity(const T specialMeasure, vector_traits::scalar_type clampedNdotV, vector_traits::scalar_type clampedNdotL, vector_traits::scalar_type VdotHLdotH, vector_traits::scalar_type VdotH_etaLdotH) +SDualMeasureQuant createDualMeasureQuantity(const T specialMeasure, typename vector_traits::scalar_type clampedNdotV, typename vector_traits::scalar_type clampedNdotL, typename vector_traits::scalar_type VdotHLdotH, typename vector_traits::scalar_type VdotH_etaLdotH) { return impl::createDualMeasureQuantity_helper::__call(specialMeasure,clampedNdotV,clampedNdotL,VdotHLdotH,VdotH_etaLdotH); } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 99ea9c4e35..28c5a8123b 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -39,7 +39,7 @@ struct SBeckmannIsotropic NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); - using ndf_type = ndf::Beckmann; + using ndf_type = ndf::Beckmann; using fresnel_type = fresnel::Conductor; struct SCreationParams @@ -107,7 +107,7 @@ struct SBeckmannAnisotropic NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); - using ndf_type = ndf::Beckmann; + using ndf_type = ndf::Beckmann; using fresnel_type = fresnel::Conductor; struct SCreationParams @@ -145,7 +145,7 @@ struct SBeckmannAnisotropic return __base.generate(interaction, u, cache); } - scalar_type pdf(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { return __base.pdf(_sample, interaction, cache); } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 1b990e67f9..51441f5876 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -39,7 +39,7 @@ struct SGGXIsotropic NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); - using ndf_type = ndf::GGX; + using ndf_type = ndf::GGX; using fresnel_type = fresnel::Conductor; struct SCreationParams @@ -76,7 +76,7 @@ struct SGGXIsotropic return __base.generate(interaction, u, cache); } - scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { return __base.pdf(_sample, interaction, cache); } @@ -106,7 +106,7 @@ struct SGGXAnisotropic NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); - using ndf_type = ndf::GGX; + using ndf_type = ndf::GGX; using fresnel_type = fresnel::Conductor; struct SCreationParams @@ -135,7 +135,7 @@ struct SGGXAnisotropic return create(params.ax, params.ay, params.ior0, params.ior1); } - spectral_type eval(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { return __base.eval(_sample, interaction, cache); } @@ -145,12 +145,12 @@ struct SGGXAnisotropic return __base.generate(interaction, u, cache); } - scalar_type pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { return __base.pdf(_sample, interaction, cache); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { return __base.quotient_and_pdf(_sample, interaction, cache); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index fbb6824147..e2f4000894 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -41,7 +41,7 @@ struct SBeckmannDielectricIsotropic NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); - using ndf_type = ndf::Beckmann; + using ndf_type = ndf::Beckmann; using fresnel_type = fresnel::Dielectric; struct SCreationParams @@ -75,7 +75,7 @@ struct SBeckmannDielectricIsotropic return __base.generate(interaction, u, cache); } - scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { return __base.pdf(_sample, interaction, cache); } @@ -107,7 +107,7 @@ struct SBeckmannDielectricAnisotropic NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); - using ndf_type = ndf::Beckmann; + using ndf_type = ndf::Beckmann; using fresnel_type = fresnel::Dielectric; struct SCreationParams @@ -149,7 +149,7 @@ struct SBeckmannDielectricAnisotropic return generate(interaction, u, dummycache); } - scalar_type pdf(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { return __base.pdf(_sample, interaction, cache); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index e2c661668c..e05d7489ce 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -41,7 +41,7 @@ struct SGGXDielectricIsotropic NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); - using ndf_type = ndf::GGX; + using ndf_type = ndf::GGX; using fresnel_type = fresnel::Dielectric; struct SCreationParams @@ -76,7 +76,7 @@ struct SGGXDielectricIsotropic return __base.generate(interaction, u, cache); } - scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { return __base.pdf(_sample, interaction, cache); } @@ -108,7 +108,7 @@ struct SGGXDielectricAnisotropic NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); - using ndf_type = ndf::GGX; + using ndf_type = ndf::GGX; using fresnel_type = fresnel::Dielectric; struct SCreationParams @@ -151,7 +151,7 @@ struct SGGXDielectricAnisotropic return generate(interaction, u, dummycache); } - scalar_type pdf(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { return __base.pdf(_sample, interaction, cache); } From d8d2116c3acbb79ec67f9c720ef2a617bdae862c Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 10 Sep 2025 15:12:45 +0700 Subject: [PATCH 09/38] fixes to ggx ndf --- include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index 30ec30ebea..cb5a1c05cd 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -71,10 +71,10 @@ struct SGGXDG1Query using scalar_type = T; scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } - scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; } + scalar_type getG1() NBL_CONST_MEMBER_FUNC { return G1; } scalar_type ndf; - scalar_type G1_over_2NdotV; + scalar_type G1; }; template @@ -124,7 +124,7 @@ struct GGXCommon) > scalar_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query) { - return scalar_type(0.5) * query.getNdf() * query.getG1over2NdotV(); + return query.getNdf() * query.getG1(); } scalar_type devsh_part(scalar_type NdotX2) @@ -359,7 +359,8 @@ struct GGX(cache); - dg1_query.G1_over_2NdotV = __base.G1_wo_numerator(interaction.getNdotV(BxDFClampMode::BCM_ABS), interaction.getNdotV2()); + scalar_type clampedNdotV = interaction.getNdotV(BxDFClampMode::BCM_MAX); + dg1_query.G1 = scalar_type(2.0) * clampedNdotV * __base.G1_wo_numerator(clampedNdotV, interaction.getNdotV2()); return dg1_query; } template && surface_interactions::Isotropic) @@ -432,7 +433,8 @@ struct GGX(cache); - dg1_query.G1_over_2NdotV = __base.G1_wo_numerator(interaction.getNdotV(BxDFClampMode::BCM_ABS), interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + scalar_type clampedNdotV = interaction.getNdotV(BxDFClampMode::BCM_MAX); + dg1_query.G1 = scalar_type(2.0) * clampedNdotV * __base.G1_wo_numerator(clampedNdotV, interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); return dg1_query; } template && surface_interactions::Anisotropic) @@ -508,7 +510,8 @@ struct GGX(cache); - dg1_query.G1_over_2NdotV = __base.G1_wo_numerator(interaction.getNdotV(BxDFClampMode::BCM_ABS), interaction.getNdotV2()); + scalar_type clampedNdotV = interaction.getNdotV(BxDFClampMode::BCM_ABS); + dg1_query.G1 = scalar_type(2.0) * clampedNdotV * __base.G1_wo_numerator(clampedNdotV, interaction.getNdotV2()); return dg1_query; } template && surface_interactions::Isotropic) @@ -583,7 +586,8 @@ struct GGX(cache); - dg1_query.G1_over_2NdotV = __base.G1_wo_numerator(interaction.getNdotV(BxDFClampMode::BCM_ABS), interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + scalar_type clampedNdotV = interaction.getNdotV(BxDFClampMode::BCM_ABS); + dg1_query.G1 = scalar_type(2.0) * clampedNdotV * __base.G1_wo_numerator(clampedNdotV, interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); return dg1_query; } template && surface_interactions::Anisotropic) From 238b08eadc07e3d0798f216ce3e0fdd31b6ba53a Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 10 Sep 2025 15:22:56 +0700 Subject: [PATCH 10/38] fixed conductor fresnel naming ior as eta --- include/nbl/builtin/hlsl/bxdf/fresnel.hlsl | 26 +++++++++---------- .../hlsl/bxdf/reflection/beckmann.hlsl | 12 ++++----- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 12 ++++----- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl index 915b0d20a1..1bb3cf7085 100644 --- a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl @@ -347,21 +347,21 @@ struct Conductor using scalar_type = typename vector_traits::scalar_type; using vector_type = T; - static Conductor create(NBL_CONST_REF_ARG(T) eta, NBL_CONST_REF_ARG(T) etak) + static Conductor create(NBL_CONST_REF_ARG(T) ior, NBL_CONST_REF_ARG(T) iork) { Conductor retval; - retval.eta = eta; - retval.etak = etak; - retval.etak2 = etak*etak; + retval.ior = ior; + retval.iork = iork; + retval.iork2 = iork*iork; return retval; } - static Conductor create(NBL_CONST_REF_ARG(complex_t) eta) + static Conductor create(NBL_CONST_REF_ARG(complex_t) ior) { Conductor retval; - retval.eta = eta.real(); - retval.etak = eta.imag(); - retval.etak2 = eta.imag()*eta.imag(); + retval.ior = ior.real(); + retval.iork = ior.imag(); + retval.iork2 = ior.imag()*ior.imag(); return retval; } @@ -370,9 +370,9 @@ struct Conductor const scalar_type cosTheta2 = clampedCosTheta * clampedCosTheta; //const float sinTheta2 = 1.0 - cosTheta2; - const T etaLen2 = eta * eta + etak2; + const T etaLen2 = ior * ior + iork2; assert(hlsl::all(etaLen2 > hlsl::promote(hlsl::exp2(-numeric_limits::digits)))); - const T etaCosTwice = eta * clampedCosTheta * 2.0f; + const T etaCosTwice = ior * clampedCosTheta * 2.0f; const T rs_common = etaLen2 + (T)(cosTheta2); const T rs2 = (rs_common - etaCosTwice) / (rs_common + etaCosTwice); @@ -383,9 +383,9 @@ struct Conductor return (rs2 + rp2) * 0.5f; } - T eta; - T etak; - T etak2; + T ior; + T iork; + T iork2; }; template) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 28c5a8123b..a75fb1f39a 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -55,9 +55,9 @@ struct SBeckmannIsotropic this_t retval; retval.__base.ndf.__base.A = vector2_type(A, A); retval.__base.ndf.__base.a2 = A*A; - retval.__base.fresnel.eta = ior0; - retval.__base.fresnel.etak = ior1; - retval.__base.fresnel.etak2 = ior1*ior1; + retval.__base.fresnel.ior = ior0; + retval.__base.fresnel.iork = ior1; + retval.__base.fresnel.iork2 = ior1*ior1; return retval; } static this_t create(NBL_CONST_REF_ARG(creation_type) params) @@ -125,9 +125,9 @@ struct SBeckmannAnisotropic retval.__base.ndf.__base.A = vector2_type(ax, ay); retval.__base.ndf.__base.ax2 = ax*ax; retval.__base.ndf.__base.ay2 = ay*ay; - retval.__base.fresnel.eta = ior0; - retval.__base.fresnel.etak = ior1; - retval.__base.fresnel.etak2 = ior1*ior1; + retval.__base.fresnel.ior = ior0; + retval.__base.fresnel.iork = ior1; + retval.__base.fresnel.iork2 = ior1*ior1; return retval; } static this_t create(NBL_CONST_REF_ARG(creation_type) params) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 51441f5876..141a0587e0 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -56,9 +56,9 @@ struct SGGXIsotropic retval.__base.ndf.__base.A = vector2_type(A, A); retval.__base.ndf.__base.a2 = A*A; retval.__base.ndf.__base.one_minus_a2 = scalar_type(1.0) - A*A; - retval.__base.fresnel.eta = ior0; - retval.__base.fresnel.etak = ior1; - retval.__base.fresnel.etak2 = ior1*ior1; + retval.__base.fresnel.ior = ior0; + retval.__base.fresnel.iork = ior1; + retval.__base.fresnel.iork2 = ior1*ior1; return retval; } static this_t create(NBL_CONST_REF_ARG(creation_type) params) @@ -125,9 +125,9 @@ struct SGGXAnisotropic retval.__base.ndf.__base.ax2 = ax*ax; retval.__base.ndf.__base.ay2 = ay*ay; retval.__base.ndf.__base.a2 = ax*ay; - retval.__base.fresnel.eta = ior0; - retval.__base.fresnel.etak = ior1; - retval.__base.fresnel.etak2 = ior1*ior1; + retval.__base.fresnel.ior = ior0; + retval.__base.fresnel.iork = ior1; + retval.__base.fresnel.iork2 = ior1*ior1; return retval; } static this_t create(NBL_CONST_REF_ARG(creation_type) params) From 8bc707fef8f80ef1a8d8a6ba7049926b99cf0d6c Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 10 Sep 2025 16:24:58 +0700 Subject: [PATCH 11/38] minor fixes to beckmann ndf, removed obsolete comments --- .../builtin/hlsl/bxdf/cook_torrance_base.hlsl | 8 +- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 83 +++++++------------ include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 46 ---------- .../hlsl/bxdf/reflection/beckmann.hlsl | 1 + .../hlsl/bxdf/transmission/beckmann.hlsl | 1 + 5 files changed, 38 insertions(+), 101 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl index 7ed24195f8..ac6bd0866e 100644 --- a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl @@ -22,8 +22,8 @@ template struct SCookTorrance; template -NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration /*&& ndf::NDF*/ && fresnel::Fresnel) -struct SCookTorrance /*&& ndf::NDF*/ && fresnel::Fresnel) > +NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration && ndf::NDF && fresnel::Fresnel) +struct SCookTorrance && ndf::NDF && fresnel::Fresnel) > { NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); @@ -169,8 +169,8 @@ struct SCookTorrance -NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration /*&& ndf::NDF*/ && fresnel::Fresnel) -struct SCookTorrance /*&& ndf::NDF*/ && fresnel::Fresnel) > +NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration && ndf::NDF && fresnel::Fresnel) +struct SCookTorrance && ndf::NDF && fresnel::Fresnel) > { NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index 398df717e2..5ffd3024b7 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -16,56 +16,11 @@ namespace bxdf namespace ndf { -// namespace beckmann_concepts -// { -// #define NBL_CONCEPT_NAME DG1BrdfQuery -// #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) -// #define NBL_CONCEPT_TPLT_PRM_NAMES (T) -// #define NBL_CONCEPT_PARAM_0 (query, T) -// NBL_CONCEPT_BEGIN(1) -// #define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 -// NBL_CONCEPT_END( -// ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) -// ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getNdf()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) -// ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) -// ); -// #undef query -// #include - -// #define NBL_CONCEPT_NAME DG1BsdfQuery -// #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) -// #define NBL_CONCEPT_TPLT_PRM_NAMES (T) -// #define NBL_CONCEPT_PARAM_0 (query, T) -// NBL_CONCEPT_BEGIN(1) -// #define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 -// NBL_CONCEPT_END( -// ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) -// ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(DG1BrdfQuery, T)) -// ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getOrientedEta()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) -// ); -// #undef query -// #include - -// #define NBL_CONCEPT_NAME G2overG1Query -// #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) -// #define NBL_CONCEPT_TPLT_PRM_NAMES (T) -// #define NBL_CONCEPT_PARAM_0 (query, T) -// NBL_CONCEPT_BEGIN(1) -// #define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 -// NBL_CONCEPT_END( -// ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) -// ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) -// ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) -// ); -// #undef query -// #include -// } - namespace impl { template -struct SBeckmannDG1Query // TODO: need to specialize? or just ignore orientedEta if not needed +struct SBeckmannDG1Query { using scalar_type = T; @@ -114,8 +69,9 @@ struct BeckmannCommon) scalar_type D(NBL_CONST_REF_ARG(MicrofacetCache) cache) { - scalar_type nom = exp2((cache.getNdotH2() - scalar_type(1.0)) / (log(2.0) * a2 * cache.getNdotH2())); - scalar_type denom = a2 * cache.getNdotH2() * cache.getNdotH2(); + scalar_type NdotH2 = cache.getNdotH2(); + scalar_type nom = exp2((NdotH2 - scalar_type(1.0)) / (log(2.0) * a2 * NdotH2)); + scalar_type denom = a2 * NdotH2 * NdotH2; return numbers::inv_pi * nom / denom; } @@ -124,6 +80,17 @@ struct BeckmannCommon(onePlusLambda_V, scalar_type(1.0) + query.getLambdaL()), cache.isTransmission()); + scalar_type lambda_L = query.getLambdaL(); + return onePlusLambda_V * hlsl::mix(scalar_type(1.0)/(onePlusLambda_V + lambda_L), bxdf::beta(onePlusLambda_V, scalar_type(1.0) + lambda_L), cache.isTransmission()); } vector A; // TODO: remove? @@ -171,7 +139,7 @@ struct BeckmannCommon(-(cache.getTdotH2() / ax2 + cache.getBdotH2() / ay2) / cache.getNdotH2()); - scalar_type denom = A.x * A.y * cache.getNdotH2() * cache.getNdotH2(); + scalar_type denom = a2 * cache.getNdotH2() * cache.getNdotH2(); return numbers::inv_pi * nom / denom; } @@ -182,6 +150,17 @@ struct BeckmannCommon(onePlusLambda_V, scalar_type(1.0) + query.getLambdaL()), cache.isTransmission()); + scalar_type lambda_L = query.getLambdaL(); + return onePlusLambda_V * hlsl::mix(scalar_type(1.0)/(onePlusLambda_V + lambda_L), bxdf::beta(onePlusLambda_V, scalar_type(1.0) + lambda_L), cache.isTransmission()); } vector A; scalar_type ax2; scalar_type ay2; + scalar_type a2; }; template diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index cb5a1c05cd..485f22e72c 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -16,52 +16,6 @@ namespace bxdf namespace ndf { -// namespace ggx_concepts -// { -// #define NBL_CONCEPT_NAME DG1BrdfQuery -// #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) -// #define NBL_CONCEPT_TPLT_PRM_NAMES (T) -// #define NBL_CONCEPT_PARAM_0 (query, T) -// NBL_CONCEPT_BEGIN(1) -// #define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 -// NBL_CONCEPT_END( -// ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) -// ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getNdf()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) -// ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getG1over2NdotV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) -// ); -// #undef query -// #include - -// #define NBL_CONCEPT_NAME DG1BsdfQuery -// #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) -// #define NBL_CONCEPT_TPLT_PRM_NAMES (T) -// #define NBL_CONCEPT_PARAM_0 (query, T) -// NBL_CONCEPT_BEGIN(1) -// #define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 -// NBL_CONCEPT_END( -// ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) -// ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(DG1BrdfQuery, T)) -// ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getOrientedEta()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) -// ); -// #undef query -// #include - -// #define NBL_CONCEPT_NAME G2XQuery -// #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) -// #define NBL_CONCEPT_TPLT_PRM_NAMES (T) -// #define NBL_CONCEPT_PARAM_0 (query, T) -// NBL_CONCEPT_BEGIN(1) -// #define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 -// NBL_CONCEPT_END( -// ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) -// ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getDevshV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) -// ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getDevshL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) -// ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getClampMode()), ::nbl::hlsl::is_same_v, BxDFClampMode)) -// ); -// #undef query -// #include -// } - namespace impl { diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index a75fb1f39a..7b675a1c73 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -125,6 +125,7 @@ struct SBeckmannAnisotropic retval.__base.ndf.__base.A = vector2_type(ax, ay); retval.__base.ndf.__base.ax2 = ax*ax; retval.__base.ndf.__base.ay2 = ay*ay; + retval.__base.ndf.__base.a2 = ax*ay; retval.__base.fresnel.ior = ior0; retval.__base.fresnel.iork = ior1; retval.__base.fresnel.iork2 = ior1*ior1; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index e2f4000894..09d39e41bf 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -124,6 +124,7 @@ struct SBeckmannDielectricAnisotropic retval.__base.ndf.__base.A = vector2_type(ax, ay); retval.__base.ndf.__base.ax2 = ax*ax; retval.__base.ndf.__base.ay2 = ay*ay; + retval.__base.ndf.__base.a2 = ax*ay; retval.__base.fresnel.orientedEta = orientedEta; retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; return retval; From 9fb28cf04e3ceac6d0c6d7d228f657ef8e77f0e4 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 11 Sep 2025 11:26:17 +0700 Subject: [PATCH 12/38] added luminosity contribution hint to cook torrance bsdfs --- .../builtin/hlsl/bxdf/cook_torrance_base.hlsl | 11 ++++--- .../hlsl/bxdf/transmission/beckmann.hlsl | 33 ++++++++++++++----- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 33 ++++++++++++++----- 3 files changed, 54 insertions(+), 23 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl index ac6bd0866e..b3d2fed7ec 100644 --- a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl @@ -224,14 +224,14 @@ struct SCookTorrance(fresnel(hlsl::abs(cache.getVdotH()))[0]) * DG; } - sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(isocache_type) cache) + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(isocache_type) cache, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) { anisocache_type anisocache; - sample_type s = generate(anisotropic_interaction_type::create(interaction), u, anisocache); + sample_type s = generate(anisotropic_interaction_type::create(interaction), u, anisocache, luminosityContributionHint); cache = anisocache.iso_cache; return s; } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(anisocache_type) cache) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(anisocache_type) cache, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) { const vector3_type localV = interaction.getTangentSpaceV(); @@ -242,10 +242,11 @@ struct SCookTorrance(hlsl::promote(reflectance), luminosityContributionHint); + scalar_type rcpChoiceProb; scalar_type z = u.z; - bool transmitted = math::partitionRandVariable(reflectance, z, rcpChoiceProb); + bool transmitted = math::partitionRandVariable(reflectionProb, z, rcpChoiceProb); cache = anisocache_type::createForReflection(localV, H); diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 09d39e41bf..bdc2d0deb0 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -19,9 +19,6 @@ namespace bxdf namespace transmission { -// template -// struct SBeckmannDielectricAnisotropic; - template) struct SBeckmannDielectricIsotropic { @@ -48,21 +45,29 @@ struct SBeckmannDielectricIsotropic { scalar_type A; fresnel::OrientedEtas orientedEta; + spectral_type luminosityContributionHint; }; using creation_type = SCreationParams; - static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type A) + static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type A, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) { this_t retval; retval.__base.ndf.__base.A = vector2_type(A, A); retval.__base.ndf.__base.a2 = A*A; retval.__base.fresnel.orientedEta = orientedEta; retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; + retval.luminosityContributionHint = luminosityContributionHint; return retval; } + static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type A) + { + static_assert(vector_traits::Dimension == 3); + const spectral_type rec709 = spectral_type(0.2126, 0.7152, 0.0722); + return create(orientedEta, A, rec709); + } static this_t create(NBL_CONST_REF_ARG(creation_type) params) { - return create(params.orientedEta, params.A); + return create(params.orientedEta, params.A, params.luminosityContributionHint); } spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) @@ -72,7 +77,7 @@ struct SBeckmannDielectricIsotropic sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) { - return __base.generate(interaction, u, cache); + return __base.generate(interaction, u, cache, luminosityContributionHint); } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) @@ -86,6 +91,7 @@ struct SBeckmannDielectricIsotropic } SCookTorrance __base; + spectral_type luminosityContributionHint; }; template) @@ -115,10 +121,11 @@ struct SBeckmannDielectricAnisotropic scalar_type ax; scalar_type ay; fresnel::OrientedEtas orientedEta; + spectral_type luminosityContributionHint; }; using creation_type = SCreationParams; - static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type ax, scalar_type ay) + static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) { this_t retval; retval.__base.ndf.__base.A = vector2_type(ax, ay); @@ -127,11 +134,18 @@ struct SBeckmannDielectricAnisotropic retval.__base.ndf.__base.a2 = ax*ay; retval.__base.fresnel.orientedEta = orientedEta; retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; + retval.luminosityContributionHint = luminosityContributionHint; return retval; } + static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type ax, scalar_type ay) + { + static_assert(vector_traits::Dimension == 3); + const spectral_type rec709 = spectral_type(0.2126, 0.7152, 0.0722); + return create(orientedEta, ax, ay, rec709); + } static this_t create(NBL_CONST_REF_ARG(creation_type) params) { - return create(params.orientedEta, params.ax, params.ay); + return create(params.orientedEta, params.ax, params.ay, params.luminosityContributionHint); } spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) @@ -141,7 +155,7 @@ struct SBeckmannDielectricAnisotropic sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) { - return __base.generate(interaction, u, cache); + return __base.generate(interaction, u, cache, luminosityContributionHint); } sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u) @@ -161,6 +175,7 @@ struct SBeckmannDielectricAnisotropic } SCookTorrance __base; + spectral_type luminosityContributionHint; }; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index e05d7489ce..b46e176125 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -19,9 +19,6 @@ namespace bxdf namespace transmission { -// template -// struct SGGXDielectricAnisotropic; - template) struct SGGXDielectricIsotropic { @@ -48,10 +45,11 @@ struct SGGXDielectricIsotropic { scalar_type A; fresnel::OrientedEtas orientedEta; + spectral_type luminosityContributionHint; }; using creation_type = SCreationParams; - static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type A) + static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type A, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) { this_t retval; retval.__base.ndf.__base.A = vector2_type(A, A); @@ -59,11 +57,18 @@ struct SGGXDielectricIsotropic retval.__base.ndf.__base.one_minus_a2 = scalar_type(1.0) - A*A; retval.__base.fresnel.orientedEta = orientedEta; retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; + retval.luminosityContributionHint = luminosityContributionHint; return retval; } + static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type A) + { + static_assert(vector_traits::Dimension == 3); + const spectral_type rec709 = spectral_type(0.2126, 0.7152, 0.0722); + return create(orientedEta, A, rec709); + } static this_t create(NBL_CONST_REF_ARG(creation_type) params) { - return create(params.orientedEta, params.A); + return create(params.orientedEta, params.A, params.luminosityContributionHint); } spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) @@ -73,7 +78,7 @@ struct SGGXDielectricIsotropic sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) { - return __base.generate(interaction, u, cache); + return __base.generate(interaction, u, cache, luminosityContributionHint); } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) @@ -87,6 +92,7 @@ struct SGGXDielectricIsotropic } SCookTorrance __base; + spectral_type luminosityContributionHint; }; template) @@ -116,10 +122,11 @@ struct SGGXDielectricAnisotropic scalar_type ax; scalar_type ay; fresnel::OrientedEtas orientedEta; + spectral_type luminosityContributionHint; }; using creation_type = SCreationParams; - static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type ax, scalar_type ay) + static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) { this_t retval; retval.__base.ndf.__base.A = vector2_type(ax, ay); @@ -128,11 +135,18 @@ struct SGGXDielectricAnisotropic retval.__base.ndf.__base.a2 = ax*ay; retval.__base.fresnel.orientedEta = orientedEta; retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; + retval.luminosityContributionHint = luminosityContributionHint; return retval; } + static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type ax, scalar_type ay) + { + static_assert(vector_traits::Dimension == 3); + const spectral_type rec709 = spectral_type(0.2126, 0.7152, 0.0722); + return create(orientedEta, ax, ay, rec709); + } static this_t create(NBL_CONST_REF_ARG(creation_type) params) { - return create(params.orientedEta, params.ax, params.ay); + return create(params.orientedEta, params.ax, params.ay, params.luminosityContributionHint); } spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) @@ -142,7 +156,7 @@ struct SGGXDielectricAnisotropic sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) { - return __base.generate(interaction, u, cache); + return __base.generate(interaction, u, cache, luminosityContributionHint); } sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u) @@ -162,6 +176,7 @@ struct SGGXDielectricAnisotropic } SCookTorrance __base; + spectral_type luminosityContributionHint; }; } From 4cb8a0a701023b683538bc64dd58a44fe3326ed8 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 11 Sep 2025 13:43:16 +0700 Subject: [PATCH 13/38] added aniso overloads to isotropic bxdf methods --- .../hlsl/bxdf/reflection/beckmann.hlsl | 21 ++++++++++++++----- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 19 ++++++++++++++--- .../hlsl/bxdf/transmission/beckmann.hlsl | 16 ++++++++++++++ .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 18 +++++++++++++++- 4 files changed, 65 insertions(+), 9 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 7b675a1c73..7e07a8c609 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -19,9 +19,6 @@ namespace bxdf namespace reflection { -// template -// struct SBeckmannAnisotropic; - template) struct SBeckmannIsotropic { @@ -65,27 +62,41 @@ struct SBeckmannIsotropic return create(params.A, params.ior0, params.ior1); } - // TODO: isotropic should also include anisotropic overloads - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { return __base.eval(_sample, interaction, cache); } + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + { + return __base.eval(_sample, interaction.isotropic, cache.iso_cache); + } sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache) { return __base.generate(interaction, u, cache); } + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache) + { + return __base.generate(interaction.isotropic, u, cache.iso_cache); + } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { return __base.pdf(_sample, interaction, cache); } + scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + { + return __base.pdf(_sample, interaction.isotropic, cache.iso_cache); + } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { return __base.quotient_and_pdf(_sample, interaction, cache); } + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + { + return __base.quotient_and_pdf(_sample, interaction.isotropic, cache.iso_cache); + } SCookTorrance __base; }; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 141a0587e0..4e31be4639 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -19,9 +19,6 @@ namespace bxdf namespace reflection { -// template -// struct SGGXAnisotropic; - template) struct SGGXIsotropic { @@ -70,21 +67,37 @@ struct SGGXIsotropic { return __base.eval(_sample, interaction, cache); } + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + { + return __base.eval(_sample, interaction.isotropic, cache.iso_cache); + } sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache) { return __base.generate(interaction, u, cache); } + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache) + { + return __base.generate(interaction.isotropic, u, cache.iso_cache); + } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { return __base.pdf(_sample, interaction, cache); } + scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + { + return __base.pdf(_sample, interaction.isotropic, cache.iso_cache); + } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { return __base.quotient_and_pdf(_sample, interaction, cache); } + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + { + return __base.quotient_and_pdf(_sample, interaction.isotropic, cache.iso_cache); + } SCookTorrance __base; }; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index bdc2d0deb0..046c2dc4ea 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -74,21 +74,37 @@ struct SBeckmannDielectricIsotropic { return __base.eval(_sample, interaction, cache); } + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + { + return __base.eval(_sample, interaction.isotropic, cache.iso_cache); + } sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) { return __base.generate(interaction, u, cache, luminosityContributionHint); } + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) + { + return __base.generate(interaction.isotropic, u, cache.iso_cache, luminosityContributionHint); + } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { return __base.pdf(_sample, interaction, cache); } + scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + { + return __base.pdf(_sample, interaction.isotropic, cache.iso_cache); + } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { return __base.quotient_and_pdf(_sample, interaction, cache); } + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + { + return __base.quotient_and_pdf(_sample, interaction.isotropic, cache.iso_cache); + } SCookTorrance __base; spectral_type luminosityContributionHint; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index b46e176125..0c46826c6b 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -75,21 +75,37 @@ struct SGGXDielectricIsotropic { return __base.eval(_sample, interaction, cache); } + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + { + return __base.eval(_sample, interaction.isotropic, cache.iso_cache); + } sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) { return __base.generate(interaction, u, cache, luminosityContributionHint); } + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) + { + return __base.generate(interaction.isotropic, u, cache.iso_cache, luminosityContributionHint); + } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - return __base.pdf(_sample, interaction, cache); + return __base.pdf(_sample, interaction, cache); + } + scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + { + return __base.pdf(_sample, interaction.isotropic, cache.iso_cache); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { return __base.quotient_and_pdf(_sample, interaction, cache); } + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + { + return __base.quotient_and_pdf(_sample, interaction.isotropic, cache.iso_cache); + } SCookTorrance __base; spectral_type luminosityContributionHint; From 392dc317feabe464d3a30575e96fd231faacc3f0 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 11 Sep 2025 17:20:32 +0700 Subject: [PATCH 14/38] checks for invalid generate sample --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 7 +++++-- include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl | 6 ++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index d8ec1b21e3..400f215ea0 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -11,6 +11,7 @@ #include "nbl/builtin/hlsl/ieee754.hlsl" #include "nbl/builtin/hlsl/tgmath.hlsl" #include "nbl/builtin/hlsl/math/functions.hlsl" +// #include "nbl/builtin/hlsl/glsl_compat/core.hlsl" #include "nbl/builtin/hlsl/cpp_compat/promote.hlsl" #include "nbl/builtin/hlsl/bxdf/fresnel.hlsl" #include "nbl/builtin/hlsl/sampling/quotient_and_pdf.hlsl" @@ -429,6 +430,8 @@ struct SLightSample } scalar_type getNdotL2() NBL_CONST_MEMBER_FUNC { return NdotL2; } + bool isValid() NBL_CONST_MEMBER_FUNC { return !hlsl::all >(hlsl::glsl::equal(L.getDirection(), hlsl::promote(0.0))); } + RayDirInfo L; @@ -737,7 +740,7 @@ struct SAnisotropicMicrofacetCache { this_t retval; retval.iso_cache = isocache_type::create(V,L,N,orientedEtas,H); - const bool valid = retval.iso_cache.NdotH >= 0.0; + const bool valid = retval.iso_cache.getNdotH() >= 0.0; if (valid) { retval.TdotH = nbl::hlsl::dot(T,H); @@ -755,7 +758,7 @@ struct SAnisotropicMicrofacetCache this_t retval; vector3_type H; retval.iso_cache = isocache_type::template create(interaction.isotropic,_sample,orientedEtas,H); - const bool valid = retval.iso_cache.NdotH >= 0.0; + const bool valid = retval.iso_cache.getNdotH() >= 0.0; if (valid) { retval.TdotH = nbl::hlsl::dot(interaction.getT(),H); diff --git a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl index b3d2fed7ec..07b10c3e73 100644 --- a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl @@ -257,6 +257,12 @@ struct SCookTorrance Date: Fri, 12 Sep 2025 11:47:40 +0700 Subject: [PATCH 15/38] removed obsolete commented out stuff --- .../ndf/microfacet_to_light_transform.hlsl | 177 ------------------ 1 file changed, 177 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl index 901695825c..4a4679d137 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl @@ -68,183 +68,6 @@ SDualMeasureQuant createDualMeasureQuantity(const T specialMeasure, typename return impl::createDualMeasureQuantity_helper::__call(specialMeasure,clampedNdotV,clampedNdotL,VdotHLdotH,VdotH_etaLdotH); } -/* -template -struct SDualMeasureQuant; - -template -struct SDualMeasureQuant -{ - using this_t = SDualMeasureQuant; - using scalar_type = T; - - NBL_CONSTEXPR_STATIC_INLINE MicrofacetTransformTypes Type = MTT_REFLECT; - - scalar_type getMicrofacetMeasure() - { - return pdf; - } - - // this computes the max(NdotL,0)/(4*max(NdotV,0)*max(NdotL,0)) factor which transforms PDFs in the f in projected microfacet f * NdotH measure to projected light measure f * NdotL - scalar_type getProjectedLightMeasure() - { - return scalar_type(0.25) * pdf / maxNdotV; - } - - scalar_type pdf; - scalar_type maxNdotV; -}; - -template -struct SDualMeasureQuant -{ - using this_t = SDualMeasureQuant; - using scalar_type = T; - - NBL_CONSTEXPR_STATIC_INLINE MicrofacetTransformTypes Type = MTT_REFLECT; - - scalar_type getMicrofacetMeasure() - { - return pdf; - } - - // this computes the max(NdotL,0)/(4*max(NdotV,0)*max(NdotL,0)) factor which transforms PDFs in the f in projected microfacet f * NdotH measure to projected light measure f * NdotL - scalar_type getProjectedLightMeasure() - { - return pdf * maxNdotL; - } - - scalar_type pdf; - scalar_type maxNdotL; -}; - -template -struct SDualMeasureQuant -{ - using this_t = SDualMeasureQuant; - using scalar_type = T; - - NBL_CONSTEXPR_STATIC_INLINE MicrofacetTransformTypes Type = MTT_REFRACT; - - scalar_type getMicrofacetMeasure() - { - return pdf; - } - - scalar_type getProjectedLightMeasure() - { - const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); - // VdotHLdotH is negative under transmission, so thats denominator is negative - scalar_type denominator = absNdotV * (-VdotH_etaLdotH * VdotH_etaLdotH); - return pdf * VdotHLdotH / denominator; - } - - scalar_type pdf; - scalar_type absNdotV; - scalar_type VdotH; - scalar_type LdotH; - scalar_type VdotHLdotH; - scalar_type orientedEta; -}; - -template -struct SDualMeasureQuant -{ - using this_t = SDualMeasureQuant; - using scalar_type = T; - - NBL_CONSTEXPR_STATIC_INLINE MicrofacetTransformTypes Type = MTT_REFRACT; - - scalar_type getMicrofacetMeasure() - { - return pdf; - } - - scalar_type getProjectedLightMeasure() - { - const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); - // VdotHLdotH is negative under transmission, so thats denominator is negative - scalar_type denominator = absNdotL * (-scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH)); - return pdf * denominator; - } - - scalar_type pdf; - scalar_type absNdotL; - scalar_type VdotH; - scalar_type LdotH; - scalar_type VdotHLdotH; - scalar_type orientedEta; -}; - -template -struct SDualMeasureQuant -{ - using this_t = SDualMeasureQuant; - using scalar_type = T; - - NBL_CONSTEXPR_STATIC_INLINE MicrofacetTransformTypes Type = MTT_REFLECT_REFRACT; - - scalar_type getMicrofacetMeasure() - { - return pdf; - } - - scalar_type getProjectedLightMeasure() - { - scalar_type denominator = absNdotV; - if (transmitted) - { - const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); - // VdotHLdotH is negative under transmission, so thats denominator is negative - denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; - } - return pdf * (transmitted ? VdotHLdotH : scalar_type(0.25)) / denominator; - } - - scalar_type pdf; - scalar_type absNdotV; - bool transmitted; - scalar_type VdotH; - scalar_type LdotH; - scalar_type VdotHLdotH; - scalar_type orientedEta; -}; - -template -struct SDualMeasureQuant -{ - using this_t = SDualMeasureQuant; - using scalar_type = T; - - NBL_CONSTEXPR_STATIC_INLINE MicrofacetTransformTypes Type = MTT_REFLECT_REFRACT; - - scalar_type getMicrofacetMeasure() - { - return pdf; - } - - scalar_type getProjectedLightMeasure() - { - scalar_type denominator = absNdotL; - if (transmitted) - { - const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); - // VdotHLdotH is negative under transmission, so thats denominator is negative - denominator *= -scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); - } - return pdf * denominator; - } - - scalar_type pdf; - scalar_type absNdotL; - bool transmitted; - scalar_type VdotH; - scalar_type LdotH; - scalar_type VdotHLdotH; - scalar_type orientedEta; -}; -*/ - } } } From 4a7f5322db7de29b724476e34e203566be72be86 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 12 Sep 2025 17:00:44 +0700 Subject: [PATCH 16/38] added cartesian-polar conversions from unit tests --- include/nbl/builtin/hlsl/math/functions.hlsl | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/nbl/builtin/hlsl/math/functions.hlsl b/include/nbl/builtin/hlsl/math/functions.hlsl index 20442c467b..c3236c713a 100644 --- a/include/nbl/builtin/hlsl/math/functions.hlsl +++ b/include/nbl/builtin/hlsl/math/functions.hlsl @@ -192,6 +192,21 @@ typename cpp_compat_intrinsics_impl::mul_helper::return_t applyChainRu return hlsl::mul(dFdG, dGdR); } +// takes in normalized vectors +template +vector polarToCartesian(vector theta_phi) +{ + return vector(hlsl::cos(theta_phi.y) * hlsl::cos(theta_phi.x), + hlsl::sin(theta_phi.y) * hlsl::cos(theta_phi.x), + hlsl::sin(theta_phi.x)); +} + +template +vector cartesianToPolar(vector coords) +{ + return vector(hlsl::acos(clamp(coords.z, -1, 1)), hlsl::atan2(coords.y, coords.x)); +} + } } } From ce5fbac2aeeeb36466dc737f9f472bedc3499f7d Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 15 Sep 2025 15:26:20 +0700 Subject: [PATCH 17/38] vector hashes --- .../nbl/builtin/hlsl/cpp_compat/vector.hlsl | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/include/nbl/builtin/hlsl/cpp_compat/vector.hlsl b/include/nbl/builtin/hlsl/cpp_compat/vector.hlsl index 3658c838e3..e34b87193b 100644 --- a/include/nbl/builtin/hlsl/cpp_compat/vector.hlsl +++ b/include/nbl/builtin/hlsl/cpp_compat/vector.hlsl @@ -12,6 +12,7 @@ #include #include "nbl/core/hash/blake.h" +#include "nbl/core/algorithm/utility.h" namespace nbl::hlsl { @@ -92,4 +93,31 @@ struct blake3_hasher::update_impl,Dummy> } #endif } + +#ifndef __HLSL_VERSION +namespace std +{ +template +struct hash > +{ + size_t operator()(const nbl::hlsl::vector& v) const noexcept + { + size_t seed = 0; + NBL_UNROLL for (uint16_t i = 0; i < N; i++) + nbl::core::hash_combine(seed, v[i]); + return seed; + } +}; + +template +struct hash > +{ + size_t operator()(const nbl::hlsl::vector& v) const noexcept + { + std::hash hasher; + return hasher(v.x); + } +}; +} +#endif #endif \ No newline at end of file From 0f2ee0be5ce3c743261189266941ddaef4f4fb02 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 17 Sep 2025 15:26:00 +0700 Subject: [PATCH 18/38] fix fresnel usage in bxdf pdf --- include/nbl/builtin/glsl/bxdf/geom/smith/common.glsl | 4 ++-- include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/nbl/builtin/glsl/bxdf/geom/smith/common.glsl b/include/nbl/builtin/glsl/bxdf/geom/smith/common.glsl index 43114f9453..815a97c849 100644 --- a/include/nbl/builtin/glsl/bxdf/geom/smith/common.glsl +++ b/include/nbl/builtin/glsl/bxdf/geom/smith/common.glsl @@ -21,7 +21,7 @@ float nbl_glsl_smith_VNDF_pdf_wo_clamps(in float ndf, in float lambda_V, in floa { onePlusLambda_V = 1.0+lambda_V; - return nbl_glsl_microfacet_to_light_measure_transform((transmitted ? (1.0-reflectance):reflectance)*ndf/onePlusLambda_V,absNdotV,transmitted,VdotH,LdotH,VdotHLdotH,orientedEta); + return nbl_glsl_microfacet_to_light_measure_transform(reflectance*ndf/onePlusLambda_V,absNdotV,transmitted,VdotH,LdotH,VdotHLdotH,orientedEta); } // for when you know the NDF and the uncorrelated smith masking function @@ -45,7 +45,7 @@ float nbl_glsl_smith_FVNDF_pdf_wo_clamps(in float fresnel_ndf, in float G1_over_ float nbl_glsl_smith_VNDF_pdf_wo_clamps(in float ndf, in float G1_over_2NdotV, in float absNdotV, in bool transmitted, in float VdotH, in float LdotH, in float VdotHLdotH, in float orientedEta, in float reflectance) { - float FN = (transmitted ? (1.0 - reflectance) : reflectance) * ndf; + float FN = reflectance * ndf; // fresnel already takes into account transmission return nbl_glsl_smith_FVNDF_pdf_wo_clamps(FN, G1_over_2NdotV, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); } diff --git a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl index 07b10c3e73..81caeaadf7 100644 --- a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl @@ -277,7 +277,7 @@ struct SCookTorrance(dq, qq, _sample, interaction); const scalar_type reflectance = fresnel(hlsl::abs(cache.getVdotH()))[0]; - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * DG1.projectedLightMeasure; + return reflectance * DG1.projectedLightMeasure; } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { @@ -290,7 +290,7 @@ struct SCookTorrance(dq, qq, _sample, interaction); const scalar_type reflectance = fresnel(hlsl::abs(cache.getVdotH()))[0]; - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * DG1.projectedLightMeasure; + return reflectance * DG1.projectedLightMeasure; } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) From b5f02e6c2b222f78bab88c0539d8a5a6f69deee0 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 17 Sep 2025 16:49:28 +0700 Subject: [PATCH 19/38] fix F calc in generate --- include/nbl/builtin/glsl/bxdf/geom/smith/common.glsl | 4 ++-- include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/nbl/builtin/glsl/bxdf/geom/smith/common.glsl b/include/nbl/builtin/glsl/bxdf/geom/smith/common.glsl index 815a97c849..43114f9453 100644 --- a/include/nbl/builtin/glsl/bxdf/geom/smith/common.glsl +++ b/include/nbl/builtin/glsl/bxdf/geom/smith/common.glsl @@ -21,7 +21,7 @@ float nbl_glsl_smith_VNDF_pdf_wo_clamps(in float ndf, in float lambda_V, in floa { onePlusLambda_V = 1.0+lambda_V; - return nbl_glsl_microfacet_to_light_measure_transform(reflectance*ndf/onePlusLambda_V,absNdotV,transmitted,VdotH,LdotH,VdotHLdotH,orientedEta); + return nbl_glsl_microfacet_to_light_measure_transform((transmitted ? (1.0-reflectance):reflectance)*ndf/onePlusLambda_V,absNdotV,transmitted,VdotH,LdotH,VdotHLdotH,orientedEta); } // for when you know the NDF and the uncorrelated smith masking function @@ -45,7 +45,7 @@ float nbl_glsl_smith_FVNDF_pdf_wo_clamps(in float fresnel_ndf, in float G1_over_ float nbl_glsl_smith_VNDF_pdf_wo_clamps(in float ndf, in float G1_over_2NdotV, in float absNdotV, in bool transmitted, in float VdotH, in float LdotH, in float VdotHLdotH, in float orientedEta, in float reflectance) { - float FN = reflectance * ndf; // fresnel already takes into account transmission + float FN = (transmitted ? (1.0 - reflectance) : reflectance) * ndf; return nbl_glsl_smith_FVNDF_pdf_wo_clamps(FN, G1_over_2NdotV, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); } diff --git a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl index 81caeaadf7..2e150ca047 100644 --- a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl @@ -241,7 +241,7 @@ struct SCookTorrance(hlsl::promote(reflectance), luminosityContributionHint); scalar_type rcpChoiceProb; @@ -277,7 +277,7 @@ struct SCookTorrance(dq, qq, _sample, interaction); const scalar_type reflectance = fresnel(hlsl::abs(cache.getVdotH()))[0]; - return reflectance * DG1.projectedLightMeasure; + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * DG1.projectedLightMeasure; } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { @@ -290,7 +290,7 @@ struct SCookTorrance(dq, qq, _sample, interaction); const scalar_type reflectance = fresnel(hlsl::abs(cache.getVdotH()))[0]; - return reflectance * DG1.projectedLightMeasure; + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * DG1.projectedLightMeasure; } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) From 9655049a0920da965785d7383de7d9116228fe5d Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 22 Sep 2025 11:35:50 +0700 Subject: [PATCH 20/38] minor fixes to non cook torrance bxdf generate --- include/nbl/builtin/hlsl/bxdf/base/lambertian.hlsl | 12 ++++++------ include/nbl/builtin/hlsl/bxdf/base/oren_nayar.hlsl | 8 ++++---- .../nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl | 4 ++-- .../nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl | 4 ++-- .../builtin/hlsl/bxdf/transmission/lambertian.hlsl | 4 ++-- .../builtin/hlsl/bxdf/transmission/oren_nayar.hlsl | 4 ++-- .../hlsl/bxdf/transmission/smooth_dielectric.hlsl | 3 ++- 7 files changed, 20 insertions(+), 19 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/base/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/base/lambertian.hlsl index 2ea840f217..2a6c3ddbdb 100644 --- a/include/nbl/builtin/hlsl/bxdf/base/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/base/lambertian.hlsl @@ -30,17 +30,17 @@ struct SLambertianBase return hlsl::promote(_sample.getNdotL(_clamp) * numbers::inv_pi * hlsl::mix(1.0, 0.5, IsBSDF)); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u) + template) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const T u) { - // static_assert(!IsBSDF); ray_dir_info_type L; L.direction = sampling::ProjectedHemisphere::generate(u); return sample_type::createFromTangentSpace(L, interaction.getFromTangentSpace()); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u) + template) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const T u) { - // static_assert(IsBSDF); ray_dir_info_type L; L.direction = sampling::ProjectedSphere::generate(u); return sample_type::createFromTangentSpace(L, interaction.getFromTangentSpace()); @@ -48,7 +48,7 @@ struct SLambertianBase scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample) { - if (IsBSDF) + NBL_IF_CONSTEXPR (IsBSDF) return sampling::ProjectedSphere::pdf(_sample.getNdotL(_clamp)); else return sampling::ProjectedHemisphere::pdf(_sample.getNdotL(_clamp)); @@ -57,7 +57,7 @@ struct SLambertianBase quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) { sampling::quotient_and_pdf qp; - if (IsBSDF) + NBL_IF_CONSTEXPR (IsBSDF) qp = sampling::ProjectedSphere::template quotient_and_pdf(_sample.getNdotL(_clamp)); else qp = sampling::ProjectedHemisphere::template quotient_and_pdf(_sample.getNdotL(_clamp)); diff --git a/include/nbl/builtin/hlsl/bxdf/base/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/base/oren_nayar.hlsl index fdf4684cf7..9b9b1735f0 100644 --- a/include/nbl/builtin/hlsl/bxdf/base/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/base/oren_nayar.hlsl @@ -65,17 +65,17 @@ struct SOrenNayarBase return __eval(query, _sample, interaction); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u) + template) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const T u) { - // static_assert(!IsBSDF); ray_dir_info_type L; L.direction = sampling::ProjectedHemisphere::generate(u); return sample_type::createFromTangentSpace(L, interaction.getFromTangentSpace()); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u) + template) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const T u) { - // static_assert(IsBSDF); ray_dir_info_type L; L.direction = sampling::ProjectedSphere::generate(u); return sample_type::createFromTangentSpace(L, interaction.getFromTangentSpace()); diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl index 04902fec58..e34e6f47dd 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl @@ -35,11 +35,11 @@ struct SLambertian sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u) { - return __base.generate(anisotropic_interaction_type::create(interaction), u); + return __base.template generate(anisotropic_interaction_type::create(interaction), u); } sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u) { - return __base.generate(interaction, u); + return __base.template generate(interaction, u); } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl index 5a70eb140a..fb1015a71e 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl @@ -45,11 +45,11 @@ struct SOrenNayar sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u) { - return __base.generate(anisotropic_interaction_type::create(interaction), u); + return __base.template generate(anisotropic_interaction_type::create(interaction), u); } sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u) { - return __base.generate(interaction, u); + return __base.template generate(interaction, u); } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample) diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl index 21fb48f317..429409882d 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl @@ -35,11 +35,11 @@ struct SLambertian sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector3_type u) { - return __base.generate(anisotropic_interaction_type::create(interaction), u); + return __base.template generate(anisotropic_interaction_type::create(interaction), u); } sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u) { - return __base.generate(interaction, u); + return __base.template generate(interaction, u); } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample) diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/oren_nayar.hlsl index a7640fd8d7..a349f25a6a 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/oren_nayar.hlsl @@ -45,11 +45,11 @@ struct SOrenNayar sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector3_type u) { - return __base.generate(anisotropic_interaction_type::create(interaction), u); + return __base.template generate(anisotropic_interaction_type::create(interaction), u); } sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u) { - return __base.generate(interaction, u); + return __base.template generate(interaction, u); } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample) diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index b640bc2f18..134d81296f 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -68,6 +68,7 @@ struct SSmoothDielectric 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) { return quotient_pdf_type::create(1.0, bit_cast(numeric_limits::infinity)); @@ -159,7 +160,7 @@ struct SThinSmoothDielectric return 0; } - // isotropic only? + // 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) { const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(interaction.getNdotV(), _sample.getNdotL()); From a1743d25bbfa709dc78e0df228344e6d4bda895d Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 22 Sep 2025 11:58:09 +0700 Subject: [PATCH 21/38] split out bxdf concept typdefs --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 29 +++++++++++++++-------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index f692f3b140..98539a623e 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -792,6 +792,23 @@ 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) +#define NBL_CONCEPT_PARAM_0 (bxdf, T) +NBL_CONCEPT_BEGIN(1) +#define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +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::spectral_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) +); +#undef bxdf +#include + #define NBL_CONCEPT_NAME bxdf_common #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) #define NBL_CONCEPT_TPLT_PRM_NAMES (T) @@ -803,11 +820,7 @@ NBL_CONCEPT_BEGIN(3) #define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 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::spectral_type)) - ((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) + ((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)), ::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)) @@ -941,11 +954,7 @@ NBL_CONCEPT_BEGIN(4) #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)(T::scalar_type)) - ((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_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(aniso, anisocache)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) From e6d663b77abdf4016e876372550a3a363ac83d25 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 22 Sep 2025 11:58:36 +0700 Subject: [PATCH 22/38] removed redundant thin_smooth_dielectric create --- .../hlsl/bxdf/transmission/smooth_dielectric.hlsl | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index 134d81296f..34835a4a62 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -98,19 +98,14 @@ struct SThinSmoothDielectric NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; - static this_t create(NBL_CONST_REF_ARG(fresnel::Dielectric) f, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) + static this_t create(NBL_CONST_REF_ARG(fresnel::Dielectric) f) { + static_assert(vector_traits::Dimension == 3); this_t retval; retval.fresnel = f; - retval.luminosityContributionHint = luminosityContributionHint; + retval.luminosityContributionHint = spectral_type(0.2126, 0.7152, 0.0722); // rec709 return retval; } - static this_t create(NBL_CONST_REF_ARG(fresnel::Dielectric) f) - { - static_assert(vector_traits::Dimension == 3); - const spectral_type rec709 = spectral_type(0.2126, 0.7152, 0.0722); - return create(f, rec709); - } spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) { From 340cee3dbb46096238e8eb9b40fcf10386873172 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 22 Sep 2025 14:38:54 +0700 Subject: [PATCH 23/38] added and use notEqual spirv intrinsic --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 2 +- .../nbl/builtin/hlsl/glsl_compat/core.hlsl | 53 +++++++++++++++++++ .../builtin/hlsl/spirv_intrinsics/core.hlsl | 14 +++++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 98539a623e..5c965489ea 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -436,7 +436,7 @@ struct SLightSample } scalar_type getNdotL2() NBL_CONST_MEMBER_FUNC { return NdotL2; } - bool isValid() NBL_CONST_MEMBER_FUNC { return !hlsl::all >(hlsl::glsl::equal(L.getDirection(), hlsl::promote(0.0))); } + bool isValid() NBL_CONST_MEMBER_FUNC { return hlsl::any >(hlsl::glsl::notEqual(L.getDirection(), hlsl::promote(0.0))); } RayDirInfo L; diff --git a/include/nbl/builtin/hlsl/glsl_compat/core.hlsl b/include/nbl/builtin/hlsl/glsl_compat/core.hlsl index 9c124c6ae3..7e92cbf282 100644 --- a/include/nbl/builtin/hlsl/glsl_compat/core.hlsl +++ b/include/nbl/builtin/hlsl/glsl_compat/core.hlsl @@ -242,6 +242,9 @@ namespace impl template struct equal_helper; +template +struct notEqual_helper; + #ifdef __HLSL_VERSION template @@ -268,6 +271,30 @@ struct equal_helper +NBL_PARTIAL_REQ_TOP(spirv::NotEqualIntrinsicCallable && concepts::Vectorial && concepts::Integral) +struct notEqual_helper && concepts::Vectorial && concepts::Integral) > +{ + using return_t = vector::Dimension>; + + static return_t __call(const Vectorial lhs, const Vectorial rhs) + { + return spirv::INotEqual(lhs, rhs); + } +}; + +template +NBL_PARTIAL_REQ_TOP(spirv::NotEqualIntrinsicCallable && concepts::Vectorial && concepts::FloatingPoint) +struct notEqual_helper && concepts::Vectorial && concepts::FloatingPoint) > +{ + using return_t = vector::Dimension>; + + static return_t __call(const Vectorial lhs, const Vectorial rhs) + { + return spirv::FOrdNotEqual(lhs, rhs); + } +}; + #else template @@ -290,6 +317,26 @@ struct equal_helper } }; +template +NBL_PARTIAL_REQ_TOP(concepts::Vectorial) +struct notEqual_helper) > +{ + using return_t = vector::Dimension>; + + static return_t __call(const Vectorial lhs, const Vectorial rhs) + { + using traits = hlsl::vector_traits; + array_get getter; + array_set setter; + + return_t output; + for (uint32_t i = 0; i < traits::Dimension; ++i) + setter(output, i, getter(lhs, i) != getter(rhs, i)); + + return output; + } +}; + #endif } @@ -299,6 +346,12 @@ inline vector::Dimension> equal(NBL_CONST_REF_ARG(T) x, NB return impl::equal_helper::__call(x, y); } +template +inline vector::Dimension> notEqual(NBL_CONST_REF_ARG(T) x, NBL_CONST_REF_ARG(T) y) +{ + return impl::notEqual_helper::__call(x, y); +} + } } } diff --git a/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl b/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl index 94abdaff28..a7614469dd 100644 --- a/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl +++ b/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl @@ -364,6 +364,20 @@ NBL_VALID_EXPRESSION(FOrdEqualIsCallable, (T), FOrdEqual(experimental::declva template NBL_BOOL_CONCEPT EqualIntrinsicCallable = IEqualIsCallable || FOrdEqualIsCallable; +template || concepts::IntVector) +[[vk::ext_instruction(spv::OpINotEqual)]] +conditional_t, vector::Dimension>, bool> INotEqual(T lhs, T rhs); + +template || concepts::FloatingPointVector) +[[vk::ext_instruction(spv::OpFOrdNotEqual)]] +conditional_t, vector::Dimension>, bool> FOrdNotEqual(T lhs, T rhs); + +NBL_VALID_EXPRESSION(INotEqualIsCallable, (T), INotEqual(experimental::declval(),experimental::declval())); +NBL_VALID_EXPRESSION(FOrdNotEqualIsCallable, (T), FOrdNotEqual(experimental::declval(),experimental::declval())); + +template +NBL_BOOL_CONCEPT NotEqualIntrinsicCallable = INotEqualIsCallable || FOrdNotEqualIsCallable; + template && (!concepts::Vector || (concepts::Vector && vector_traits::Dimension==vector_traits::Dimension))) [[vk::ext_instruction(spv::OpSelect)]] T select(U a, T x, T y); From a3733b1e122980e94bf9e2825a7e69771ca1c2b0 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 22 Sep 2025 16:15:45 +0700 Subject: [PATCH 24/38] moved polar coord stuff into its own file --- include/nbl/builtin/hlsl/math/functions.hlsl | 15 ------ include/nbl/builtin/hlsl/math/polar.hlsl | 53 ++++++++++++++++++++ src/nbl/builtin/CMakeLists.txt | 1 + 3 files changed, 54 insertions(+), 15 deletions(-) create mode 100644 include/nbl/builtin/hlsl/math/polar.hlsl diff --git a/include/nbl/builtin/hlsl/math/functions.hlsl b/include/nbl/builtin/hlsl/math/functions.hlsl index c3236c713a..20442c467b 100644 --- a/include/nbl/builtin/hlsl/math/functions.hlsl +++ b/include/nbl/builtin/hlsl/math/functions.hlsl @@ -192,21 +192,6 @@ typename cpp_compat_intrinsics_impl::mul_helper::return_t applyChainRu return hlsl::mul(dFdG, dGdR); } -// takes in normalized vectors -template -vector polarToCartesian(vector theta_phi) -{ - return vector(hlsl::cos(theta_phi.y) * hlsl::cos(theta_phi.x), - hlsl::sin(theta_phi.y) * hlsl::cos(theta_phi.x), - hlsl::sin(theta_phi.x)); -} - -template -vector cartesianToPolar(vector coords) -{ - return vector(hlsl::acos(clamp(coords.z, -1, 1)), hlsl::atan2(coords.y, coords.x)); -} - } } } diff --git a/include/nbl/builtin/hlsl/math/polar.hlsl b/include/nbl/builtin/hlsl/math/polar.hlsl new file mode 100644 index 0000000000..7b30e3bb8f --- /dev/null +++ b/include/nbl/builtin/hlsl/math/polar.hlsl @@ -0,0 +1,53 @@ +// Copyright (C) 2018-2025 - 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_MATH_POLAR_INCLUDED_ +#define _NBL_BUILTIN_HLSL_MATH_POLAR_INCLUDED_ + +#include "nbl/builtin/hlsl/cpp_compat.hlsl" +#include "nbl/builtin/hlsl/numbers.hlsl" + +namespace nbl +{ +namespace hlsl +{ +namespace math +{ + +template +struct Polar +{ + using scalar_type = T; + using vector2_type = vector; + using vector3_type = vector; + + // should be normalized + static Polar createFromCartesian(const vector3_type coords) + { + Polar retval; + retval.theta = hlsl::acos(coords.z); + retval.phi = hlsl::atan2(coords.y, coords.x); + return retval; + } + + static vector3_type ToCartesian(const scalar_type theta, const scalar_type phi) + { + return vector(hlsl::cos(phi) * hlsl::cos(theta), + hlsl::sin(phi) * hlsl::cos(theta), + hlsl::sin(theta)); + } + + vector3_type getCartesian() + { + return ToCartesian(theta, phi); + } + + scalar_type theta; + scalar_type phi; +}; + +} +} +} + +#endif diff --git a/src/nbl/builtin/CMakeLists.txt b/src/nbl/builtin/CMakeLists.txt index cc81b093a2..0c8104f8b8 100644 --- a/src/nbl/builtin/CMakeLists.txt +++ b/src/nbl/builtin/CMakeLists.txt @@ -223,6 +223,7 @@ LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/math/linalg/transform.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/math/functions.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/math/geometry.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/math/intutil.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/math/polar.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/math/angle_adding.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/math/equations/quadratic.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/math/equations/cubic.hlsl") From 3e3589bf59818d0faa95580c04d51a5ddc11f321 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 22 Sep 2025 16:38:24 +0700 Subject: [PATCH 25/38] made smith functions return measureless --- .../builtin/hlsl/bxdf/cook_torrance_base.hlsl | 24 ++++--------------- include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 2 +- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 20 +++++++--------- include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 20 +++++++--------- 4 files changed, 22 insertions(+), 44 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl index 2e150ca047..72f45da390 100644 --- a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl @@ -25,17 +25,7 @@ template NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration && ndf::NDF && fresnel::Fresnel) struct SCookTorrance && ndf::NDF && fresnel::Fresnel) > { - 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(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); - NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); - NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); + MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); using quant_type = typename N::quant_type; @@ -54,8 +44,7 @@ struct SCookTorrance >(ndf.__base.A > hlsl::promote(numeric_limits::min))) { - quant_type G2 = ndf.template correlated(gq, qq, _sample, interaction); - DG *= G2.microfacetMeasure; + DG *= ndf.template correlated(gq, _sample, interaction); } return fresnel(cache.getVdotH()) * DG; } @@ -77,8 +66,7 @@ struct SCookTorrance >(ndf.__base.A > hlsl::promote(numeric_limits::min))) { - quant_type G2 = ndf.template correlated(gq, qq, _sample, interaction); - DG *= G2.microfacetMeasure; + DG *= ndf.template correlated(gq, _sample, interaction); } return fresnel(cache.getVdotH()) * DG; } @@ -200,8 +188,7 @@ struct SCookTorrance >(ndf.__base.A > hlsl::promote(numeric_limits::min))) { - quant_type G2 = ndf.template correlated(gq, qq, _sample, interaction); - DG *= G2.microfacetMeasure; + DG *= ndf.template correlated(gq, _sample, interaction); } return hlsl::promote(fresnel(hlsl::abs(cache.getVdotH()))[0]) * DG; } @@ -218,8 +205,7 @@ struct SCookTorrance >(ndf.__base.A > hlsl::promote(numeric_limits::min))) { - quant_type G2 = ndf.template correlated(gq, qq, _sample, interaction); - DG *= G2.microfacetMeasure; + DG *= ndf.template correlated(gq, _sample, interaction); } return hlsl::promote(fresnel(hlsl::abs(cache.getVdotH()))[0]) * DG; } diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl index 4fbf49433d..40407c9731 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -46,7 +46,7 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::quant_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template D(quant_query, _sample, interaction, cache)), ::nbl::hlsl::is_same_v, typename T::quant_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template DG1(dg1_query, quant_query, _sample, interaction)), ::nbl::hlsl::is_same_v, typename T::quant_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template correlated(g2_query, quant_query, _sample, interaction)), ::nbl::hlsl::is_same_v, typename T::quant_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template correlated(g2_query, _sample, interaction)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template G2_over_G1(g2_query, _sample, interaction, cache)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ); #undef g2_query diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index 5ffd3024b7..b973af9ed9 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -337,10 +337,9 @@ struct Beckmann && surface_interactions::Isotropic) - quant_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - scalar_type g = __base.template correlated(query, _sample, interaction); - return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); + return __base.template correlated(query, _sample, interaction); } template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) @@ -409,10 +408,9 @@ struct Beckmann && surface_interactions::Anisotropic) - quant_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - scalar_type g = __base.template correlated(query, _sample, interaction); - return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); + return __base.template correlated(query, _sample, interaction); } template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) @@ -484,10 +482,9 @@ struct Beckmann && surface_interactions::Isotropic) - quant_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - scalar_type g = __base.template correlated(query, _sample, interaction); - return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + return __base.template correlated(query, _sample, interaction); } template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) @@ -558,10 +555,9 @@ struct Beckmann && surface_interactions::Anisotropic) - quant_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - scalar_type g = __base.template correlated(query, _sample, interaction); - return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + return __base.template correlated(query, _sample, interaction); } template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index 485f22e72c..5da686673a 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -347,10 +347,9 @@ struct GGX && surface_interactions::Isotropic) - quant_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - scalar_type g = __base.template correlated(query, _sample, interaction); - return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); + return __base.template correlated(query, _sample, interaction); } template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) @@ -421,10 +420,9 @@ struct GGX && surface_interactions::Anisotropic) - quant_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - scalar_type g = __base.template correlated(query, _sample, interaction); - return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); + return __base.template correlated(query, _sample, interaction); } template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) @@ -498,10 +496,9 @@ struct GGX && surface_interactions::Isotropic) - quant_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - scalar_type g = __base.template correlated(query, _sample, interaction); - return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + return __base.template correlated(query, _sample, interaction); } template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) @@ -574,10 +571,9 @@ struct GGX && surface_interactions::Anisotropic) - quant_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - scalar_type g = __base.template correlated(query, _sample, interaction); - return createDualMeasureQuantity(g, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + return __base.template correlated(query, _sample, interaction); } template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) From 4bdf199dfec386169eaeb5c34cd694fbbcb141fc Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 22 Sep 2025 16:40:58 +0700 Subject: [PATCH 26/38] use type alias macro from config --- .../hlsl/bxdf/reflection/beckmann.hlsl | 26 ++----------------- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 26 ++----------------- .../hlsl/bxdf/transmission/beckmann.hlsl | 15 +---------- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 15 +---------- .../bxdf/transmission/smooth_dielectric.hlsl | 11 +------- 5 files changed, 7 insertions(+), 86 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 7e07a8c609..7e0ed86f15 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -23,18 +23,7 @@ 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(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); - NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); - NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); + MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); using ndf_type = ndf::Beckmann; using fresnel_type = fresnel::Conductor; @@ -105,18 +94,7 @@ 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(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); - NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); - NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); + MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); using ndf_type = ndf::Beckmann; using fresnel_type = fresnel::Conductor; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 4e31be4639..96ac5f3630 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -23,18 +23,7 @@ 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(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); - NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); - NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); + MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); using ndf_type = ndf::GGX; using fresnel_type = fresnel::Conductor; @@ -106,18 +95,7 @@ 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(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); - NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); - NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); + MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); using ndf_type = ndf::GGX; using fresnel_type = fresnel::Conductor; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 046c2dc4ea..6bb83b20b6 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -23,20 +23,7 @@ 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(matrix3x3_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); - NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); - NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); + MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); using ndf_type = ndf::Beckmann; using fresnel_type = fresnel::Dielectric; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 0c46826c6b..b6480436cf 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -23,20 +23,7 @@ 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(matrix3x3_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); - NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); - NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); + MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); using ndf_type = ndf::GGX; using fresnel_type = fresnel::Dielectric; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index 34835a4a62..d715be9dae 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -21,16 +21,7 @@ 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); NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; From 4faecc38efe93237e48b795402451366eeb1c5ba Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 23 Sep 2025 11:15:33 +0700 Subject: [PATCH 27/38] adjust ndf concept, change fresnel conductor ior to eta --- .../builtin/hlsl/bxdf/cook_torrance_base.hlsl | 13 +-------- include/nbl/builtin/hlsl/bxdf/fresnel.hlsl | 25 ++++++++--------- include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 3 ++ .../hlsl/bxdf/reflection/beckmann.hlsl | 28 +++++++++---------- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 28 +++++++++---------- 5 files changed, 44 insertions(+), 53 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl index 72f45da390..d4198718cb 100644 --- a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl @@ -160,18 +160,7 @@ template NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration && ndf::NDF && fresnel::Fresnel) struct SCookTorrance && ndf::NDF && fresnel::Fresnel) > { - 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); - NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); - NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); + MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); using quant_type = typename N::quant_type; diff --git a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl index 79503b136c..83ffdc8722 100644 --- a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl @@ -347,21 +347,21 @@ struct Conductor using scalar_type = typename vector_traits::scalar_type; using vector_type = T; - static Conductor create(NBL_CONST_REF_ARG(T) ior, NBL_CONST_REF_ARG(T) iork) + static Conductor create(NBL_CONST_REF_ARG(T) eta, NBL_CONST_REF_ARG(T) etak) { Conductor retval; - retval.ior = ior; - retval.iork = iork; - retval.iork2 = iork*iork; + retval.eta = eta; + retval.etak2 = etak * etak; + retval.etaLen2 = eta * eta + retval.etak2; return retval; } - static Conductor create(NBL_CONST_REF_ARG(complex_t) ior) + static Conductor create(NBL_CONST_REF_ARG(complex_t) eta) { Conductor retval; - retval.ior = ior.real(); - retval.iork = ior.imag(); - retval.iork2 = ior.imag()*ior.imag(); + retval.eta = eta.real(); + retval.etak2 = eta.imag() * eta.imag(); + retval.etaLen2 = eta * eta + retval.etak2; return retval; } @@ -370,9 +370,8 @@ struct Conductor const scalar_type cosTheta2 = clampedCosTheta * clampedCosTheta; //const float sinTheta2 = 1.0 - cosTheta2; - const T etaLen2 = ior * ior + iork2; assert(hlsl::all(etaLen2 > hlsl::promote(hlsl::exp2(-numeric_limits::digits)))); - const T etaCosTwice = ior * clampedCosTheta * 2.0f; + const T etaCosTwice = eta * clampedCosTheta * 2.0f; const T rs_common = etaLen2 + (T)(cosTheta2); const T rs2 = (rs_common - etaCosTwice) / (rs_common + etaCosTwice); @@ -383,9 +382,9 @@ struct Conductor return (rs2 + rp2) * 0.5f; } - T ior; - T iork; - T iork2; + T eta; + T etak2; + T etaLen2; }; template) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl index 40407c9731..5e35cfd803 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -44,6 +44,9 @@ NBL_CONCEPT_BEGIN(7) NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::quant_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::dg1_query_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::g2g1_query_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::quant_query_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template D(quant_query, _sample, interaction, cache)), ::nbl::hlsl::is_same_v, typename T::quant_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template DG1(dg1_query, quant_query, _sample, interaction)), ::nbl::hlsl::is_same_v, typename T::quant_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template correlated(g2_query, _sample, interaction)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 7e0ed86f15..21f3c9a280 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -31,24 +31,24 @@ struct SBeckmannIsotropic struct SCreationParams { scalar_type A; - spectral_type ior0; - spectral_type ior1; + spectral_type eta; + spectral_type etak; }; using creation_type = SCreationParams; - static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) + static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) eta, NBL_CONST_REF_ARG(spectral_type) etak) { this_t retval; retval.__base.ndf.__base.A = vector2_type(A, A); retval.__base.ndf.__base.a2 = A*A; - retval.__base.fresnel.ior = ior0; - retval.__base.fresnel.iork = ior1; - retval.__base.fresnel.iork2 = ior1*ior1; + retval.__base.fresnel.eta = eta; + retval.__base.fresnel.etak2 = etak * etak; + retval.__base.fresnel.etaLen2 = eta * eta + retval.__base.fresnel.etak2; return retval; } static this_t create(NBL_CONST_REF_ARG(creation_type) params) { - return create(params.A, params.ior0, params.ior1); + return create(params.A, params.eta, params.etak); } spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) @@ -103,26 +103,26 @@ struct SBeckmannAnisotropic { scalar_type ax; scalar_type ay; - spectral_type ior0; - spectral_type ior1; + spectral_type eta; + spectral_type etak; }; using creation_type = SCreationParams; - static this_t create(scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) + static this_t create(scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) eta, NBL_CONST_REF_ARG(spectral_type) etak) { this_t retval; retval.__base.ndf.__base.A = vector2_type(ax, ay); retval.__base.ndf.__base.ax2 = ax*ax; retval.__base.ndf.__base.ay2 = ay*ay; retval.__base.ndf.__base.a2 = ax*ay; - retval.__base.fresnel.ior = ior0; - retval.__base.fresnel.iork = ior1; - retval.__base.fresnel.iork2 = ior1*ior1; + retval.__base.fresnel.eta = eta; + retval.__base.fresnel.etak2 = etak * etak; + retval.__base.fresnel.etaLen2 = eta * eta + retval.__base.fresnel.etak2; return retval; } static this_t create(NBL_CONST_REF_ARG(creation_type) params) { - return create(params.ax, params.ay, params.ior0, params.ior1); + return create(params.ax, params.ay, params.eta, params.etak); } spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 96ac5f3630..4c4157a0bd 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -31,25 +31,25 @@ struct SGGXIsotropic struct SCreationParams { scalar_type A; - spectral_type ior0; - spectral_type ior1; + spectral_type eta; + spectral_type etak; }; using creation_type = SCreationParams; - static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) + static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) eta, NBL_CONST_REF_ARG(spectral_type) etak) { this_t retval; retval.__base.ndf.__base.A = vector2_type(A, A); retval.__base.ndf.__base.a2 = A*A; retval.__base.ndf.__base.one_minus_a2 = scalar_type(1.0) - A*A; - retval.__base.fresnel.ior = ior0; - retval.__base.fresnel.iork = ior1; - retval.__base.fresnel.iork2 = ior1*ior1; + retval.__base.fresnel.eta = eta; + retval.__base.fresnel.etak2 = etak * etak; + retval.__base.fresnel.etaLen2 = eta * eta + retval.__base.fresnel.etak2; return retval; } static this_t create(NBL_CONST_REF_ARG(creation_type) params) { - return create(params.A, params.ior0, params.ior1); + return create(params.A, params.eta, params.etak); } spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) @@ -104,26 +104,26 @@ struct SGGXAnisotropic { scalar_type ax; scalar_type ay; - spectral_type ior0; - spectral_type ior1; + spectral_type eta; + spectral_type etak; }; using creation_type = SCreationParams; - static this_t create(scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) + static this_t create(scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) eta, NBL_CONST_REF_ARG(spectral_type) etak) { this_t retval; retval.__base.ndf.__base.A = vector2_type(ax, ay); retval.__base.ndf.__base.ax2 = ax*ax; retval.__base.ndf.__base.ay2 = ay*ay; retval.__base.ndf.__base.a2 = ax*ay; - retval.__base.fresnel.ior = ior0; - retval.__base.fresnel.iork = ior1; - retval.__base.fresnel.iork2 = ior1*ior1; + retval.__base.fresnel.eta = eta; + retval.__base.fresnel.etak2 = etak * etak; + retval.__base.fresnel.etaLen2 = eta * eta + retval.__base.fresnel.etak2; return retval; } static this_t create(NBL_CONST_REF_ARG(creation_type) params) { - return create(params.ax, params.ay, params.ior0, params.ior1); + return create(params.ax, params.ay, params.eta, params.etak); } spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) From 407da2fff11320e4e277c88b327fbaab0c146896 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 23 Sep 2025 16:01:08 +0700 Subject: [PATCH 28/38] combine brdf/bsdf cook torrance into same struct, old stuff commented for now --- .../builtin/hlsl/bxdf/cook_torrance_base.hlsl | 554 +++++++++++++----- .../hlsl/bxdf/reflection/beckmann.hlsl | 9 +- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 9 +- .../hlsl/bxdf/transmission/beckmann.hlsl | 38 +- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 38 +- 5 files changed, 435 insertions(+), 213 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl index d4198718cb..691d04d090 100644 --- a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl @@ -17,13 +17,61 @@ namespace hlsl namespace bxdf { -// N (NDF), F (fresnel) -template -struct SCookTorrance; +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 -NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration && ndf::NDF && fresnel::Fresnel) -struct SCookTorrance && ndf::NDF && fresnel::Fresnel) > +template +struct quant_query_helper; + +template +struct quant_query_helper +{ + using quant_query_type = typename N::quant_query_type; + + template + static quant_query_type __call(NBL_REF_ARG(N) ndf, NBL_CONST_REF_ARG(F) fresnel, NBL_CONST_REF_ARG(C) cache) + { + return ndf.template createQuantQuery(cache, fresnel.orientedEta.value[0]); + } +}; + +template +struct quant_query_helper +{ + using quant_query_type = typename N::quant_query_type; + + template + static quant_query_type __call(NBL_REF_ARG(N) ndf, NBL_CONST_REF_ARG(F) fresnel, NBL_CONST_REF_ARG(C) cache) + { + typename N::scalar_type dummy; + return ndf.template createQuantQuery(cache, dummy); + } +}; +} + +// N (NDF), F (fresnel) +template +struct SCookTorrance { MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); @@ -31,201 +79,88 @@ struct SCookTorrance numeric_limits::min) + if (IsBSDF || (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min)) { using quant_query_type = typename N::quant_query_type; using g2g1_query_type = typename N::g2g1_query_type; scalar_type dummy; quant_query_type qq = ndf.template createQuantQuery(cache, dummy); - g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); quant_type D = ndf.template D(qq, _sample, interaction, cache); scalar_type DG = D.projectedLightMeasure; if (any >(ndf.__base.A > hlsl::promote(numeric_limits::min))) { + g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); DG *= ndf.template correlated(gq, _sample, interaction); } - return fresnel(cache.getVdotH()) * DG; + NBL_IF_CONSTEXPR(IsBSDF) + return impl::__implicit_promote::__call(fresnel(hlsl::abs(cache.getVdotH()))) * DG; + else + return impl::__implicit_promote::__call(fresnel(cache.getVdotH())) * DG; } else return hlsl::promote(0.0); } spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - if (interaction.getNdotV() > numeric_limits::min) + if (IsBSDF || (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min)) { using quant_query_type = typename N::quant_query_type; using g2g1_query_type = typename N::g2g1_query_type; scalar_type dummy; quant_query_type qq = ndf.template createQuantQuery(cache, dummy); - g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); quant_type D = ndf.template D(qq, _sample, interaction, cache); scalar_type DG = D.projectedLightMeasure; if (any >(ndf.__base.A > hlsl::promote(numeric_limits::min))) { + g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); DG *= ndf.template correlated(gq, _sample, interaction); } - return fresnel(cache.getVdotH()) * DG; + NBL_IF_CONSTEXPR(IsBSDF) + return impl::__implicit_promote::__call(fresnel(hlsl::abs(cache.getVdotH()))) * DG; + else + return impl::__implicit_promote::__call(fresnel(cache.getVdotH())) * DG; } else return hlsl::promote(0.0); } - sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache) - { - anisocache_type anisocache; - sample_type s = generate(anisotropic_interaction_type::create(interaction), u, anisocache); - cache = anisocache.iso_cache; - return s; - } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache) + template) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const T u, NBL_REF_ARG(anisocache_type) cache) { const vector3_type localV = interaction.getTangentSpaceV(); - const vector3_type H = ndf.generateH(localV, u); + const vector3_type localH = ndf.generateH(localV, u); - cache = anisocache_type::createForReflection(localV, H); + cache = anisocache_type::createForReflection(localV, localH); ray_dir_info_type localL; - bxdf::Reflect r = bxdf::Reflect::create(localV, H); + bxdf::Reflect r = bxdf::Reflect::create(localV, localH); localL = localL.reflect(r); return sample_type::createFromTangentSpace(localL, interaction.getFromTangentSpace()); } - - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) - { - using quant_query_type = typename N::quant_query_type; - using dg1_query_type = typename N::dg1_query_type; - - scalar_type dummy; - quant_query_type qq = ndf.template createQuantQuery(cache, dummy); - dg1_query_type dq = ndf.template createDG1Query(interaction, cache); - quant_type DG1 = ndf.template DG1(dq, qq, _sample, interaction); - return DG1.projectedLightMeasure; - } - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - using quant_query_type = typename N::quant_query_type; - using dg1_query_type = typename N::dg1_query_type; - - scalar_type dummy; - quant_query_type qq = ndf.template createQuantQuery(cache, dummy); - dg1_query_type dq = ndf.template createDG1Query(interaction, cache); - quant_type DG1 = ndf.template DG1(dq, qq, _sample, interaction); - return DG1.projectedLightMeasure; - } - - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) - { - scalar_type _pdf = pdf(_sample, interaction, cache); - - spectral_type quo = hlsl::promote(0.0); - if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) - { - using g2g1_query_type = typename N::g2g1_query_type; - - g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); - scalar_type G2_over_G1 = ndf.template G2_over_G1(gq, _sample, interaction, cache); - const spectral_type reflectance = fresnel(cache.getVdotH()); - quo = reflectance * G2_over_G1; - } - - return quotient_pdf_type::create(quo, _pdf); - } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - scalar_type _pdf = pdf(_sample, interaction, cache); - - spectral_type quo = hlsl::promote(0.0); - if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) - { - using g2g1_query_type = typename N::g2g1_query_type; - - g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); - scalar_type G2_over_G1 = ndf.template G2_over_G1(gq, _sample, interaction, cache); - const spectral_type reflectance = fresnel(cache.getVdotH()); - quo = reflectance * G2_over_G1; - } - - return quotient_pdf_type::create(quo, _pdf); - } - - N ndf; - F fresnel; -}; - -template -NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration && ndf::NDF && fresnel::Fresnel) -struct SCookTorrance && ndf::NDF && fresnel::Fresnel) > -{ - MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); - - using quant_type = typename N::quant_type; - - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + template) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const T u, NBL_REF_ARG(anisocache_type) cache) { - using quant_query_type = typename N::quant_query_type; - using g2g1_query_type = typename N::g2g1_query_type; - - fresnel::OrientedEtas orientedEta = fresnel.orientedEta; - quant_query_type qq = ndf.template createQuantQuery(cache, orientedEta.value[0]); - g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); - - quant_type D = ndf.template D(qq, _sample, interaction, cache); - scalar_type DG = D.projectedLightMeasure; - if (any >(ndf.__base.A > hlsl::promote(numeric_limits::min))) - { - DG *= ndf.template correlated(gq, _sample, interaction); - } - return hlsl::promote(fresnel(hlsl::abs(cache.getVdotH()))[0]) * DG; - } - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - using quant_query_type = typename N::quant_query_type; - using g2g1_query_type = typename N::g2g1_query_type; - - fresnel::OrientedEtas orientedEta = fresnel.orientedEta; - quant_query_type qq = ndf.template createQuantQuery(cache, orientedEta.value[0]); - g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); - - quant_type D = ndf.template D(qq, _sample, interaction, cache); - scalar_type DG = D.projectedLightMeasure; - if (any >(ndf.__base.A > hlsl::promote(numeric_limits::min))) - { - DG *= ndf.template correlated(gq, _sample, interaction); - } - return hlsl::promote(fresnel(hlsl::abs(cache.getVdotH()))[0]) * DG; - } - - sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(isocache_type) cache, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) - { - anisocache_type anisocache; - sample_type s = generate(anisotropic_interaction_type::create(interaction), u, anisocache, luminosityContributionHint); - cache = anisocache.iso_cache; - return s; - } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(anisocache_type) cache, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) - { - const vector3_type localV = interaction.getTangentSpaceV(); - fresnel::OrientedEtas orientedEta = fresnel.orientedEta; fresnel::OrientedEtaRcps rcpEta = orientedEta.getReciprocals(); + const vector3_type localV = interaction.getTangentSpaceV(); const vector3_type upperHemisphereV = hlsl::mix(localV, -localV, interaction.getNdotV() < scalar_type(0.0)); - const vector3_type H = ndf.generateH(upperHemisphereV, u.xy); + const vector3_type localH = ndf.generateH(upperHemisphereV, u.xy); - const scalar_type reflectance = fresnel(hlsl::abs(hlsl::dot(localV, H)))[0]; + const scalar_type reflectance = fresnel(hlsl::abs(hlsl::dot(localV, localH)))[0]; const scalar_type reflectionProb = hlsl::dot(hlsl::promote(reflectance), luminosityContributionHint); scalar_type rcpChoiceProb; scalar_type z = u.z; bool transmitted = math::partitionRandVariable(reflectionProb, z, rcpChoiceProb); - cache = anisocache_type::createForReflection(localV, H); + cache = anisocache_type::createForReflection(localV, localH); - Refract r = Refract::create(localV, H); + Refract r = Refract::create(localV, localH); cache.iso_cache.LdotH = hlsl::mix(cache.getVdotH(), r.getNdotT(rcpEta.value2[0]), transmitted); ray_dir_info_type localL; bxdf::ReflectRefract rr; @@ -246,36 +181,58 @@ struct SCookTorrance orientedEta = fresnel.orientedEta; - quant_query_type qq = ndf.template createQuantQuery(cache, orientedEta.value[0]); dg1_query_type dq = ndf.template createDG1Query(interaction, cache); + + quant_query_type qq = impl::quant_query_helper::template __call(ndf, fresnel, cache); quant_type DG1 = ndf.template DG1(dq, qq, _sample, interaction); - const scalar_type reflectance = fresnel(hlsl::abs(cache.getVdotH()))[0]; - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * DG1.projectedLightMeasure; + NBL_IF_CONSTEXPR(IsBSDF) + { + const scalar_type reflectance = fresnel(hlsl::abs(cache.getVdotH()))[0]; + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * DG1.projectedLightMeasure; + } + else + { + return DG1.projectedLightMeasure; + } } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { using quant_query_type = typename N::quant_query_type; using dg1_query_type = typename N::dg1_query_type; - fresnel::OrientedEtas orientedEta = fresnel.orientedEta; - quant_query_type qq = ndf.template createQuantQuery(cache, orientedEta.value[0]); dg1_query_type dq = ndf.template createDG1Query(interaction, cache); + + quant_query_type qq = impl::quant_query_helper::template __call(ndf, fresnel, cache); quant_type DG1 = ndf.template DG1(dq, qq, _sample, interaction); - const scalar_type reflectance = fresnel(hlsl::abs(cache.getVdotH()))[0]; - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * DG1.projectedLightMeasure; + NBL_IF_CONSTEXPR(IsBSDF) + { + const scalar_type reflectance = fresnel(hlsl::abs(cache.getVdotH()))[0]; + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * DG1.projectedLightMeasure; + } + else + { + return DG1.projectedLightMeasure; + } } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { scalar_type _pdf = pdf(_sample, interaction, cache); - using g2g1_query_type = typename N::g2g1_query_type; + spectral_type quo = hlsl::promote(0.0); + if (IsBSDF || (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min)) + { + using g2g1_query_type = typename N::g2g1_query_type; - g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); - scalar_type quo = ndf.template G2_over_G1(gq, _sample, interaction, cache); + g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); + scalar_type G2_over_G1 = ndf.template G2_over_G1(gq, _sample, interaction, cache); + NBL_IF_CONSTEXPR(IsBSDF) + quo = hlsl::promote(G2_over_G1); + else + quo = fresnel(cache.getVdotH()) * G2_over_G1; + } return quotient_pdf_type::create(quo, _pdf); } @@ -283,18 +240,301 @@ struct SCookTorrance(0.0); + if (IsBSDF || (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min)) + { + using g2g1_query_type = typename N::g2g1_query_type; - g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); - scalar_type quo = ndf.template G2_over_G1(gq, _sample, interaction, cache); + g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); + scalar_type G2_over_G1 = ndf.template G2_over_G1(gq, _sample, interaction, cache); + NBL_IF_CONSTEXPR(IsBSDF) + quo = hlsl::promote(G2_over_G1); + else + quo = fresnel(cache.getVdotH()) * G2_over_G1; + } return quotient_pdf_type::create(quo, _pdf); } N ndf; F fresnel; + spectral_type luminosityContributionHint; }; +// template +// NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration && ndf::NDF && fresnel::Fresnel) +// struct SCookTorrance && ndf::NDF && fresnel::Fresnel) > +// { +// MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); + +// using quant_type = typename N::quant_type; + +// spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) +// { +// if (interaction.getNdotV() > numeric_limits::min) +// { +// using quant_query_type = typename N::quant_query_type; +// using g2g1_query_type = typename N::g2g1_query_type; + +// scalar_type dummy; +// quant_query_type qq = ndf.template createQuantQuery(cache, dummy); +// g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); + +// quant_type D = ndf.template D(qq, _sample, interaction, cache); +// scalar_type DG = D.projectedLightMeasure; +// if (any >(ndf.__base.A > hlsl::promote(numeric_limits::min))) +// { +// DG *= ndf.template correlated(gq, _sample, interaction); +// } +// return fresnel(cache.getVdotH()) * DG; +// } +// else +// return hlsl::promote(0.0); +// } +// spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// if (interaction.getNdotV() > numeric_limits::min) +// { +// using quant_query_type = typename N::quant_query_type; +// using g2g1_query_type = typename N::g2g1_query_type; + +// scalar_type dummy; +// quant_query_type qq = ndf.template createQuantQuery(cache, dummy); +// g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); + +// quant_type D = ndf.template D(qq, _sample, interaction, cache); +// scalar_type DG = D.projectedLightMeasure; +// if (any >(ndf.__base.A > hlsl::promote(numeric_limits::min))) +// { +// DG *= ndf.template correlated(gq, _sample, interaction); +// } +// return fresnel(cache.getVdotH()) * DG; +// } +// else +// return hlsl::promote(0.0); +// } + +// sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache) +// { +// anisocache_type anisocache; +// sample_type s = generate(anisotropic_interaction_type::create(interaction), u, anisocache); +// cache = anisocache.iso_cache; +// return s; +// } +// sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache) +// { +// const vector3_type localV = interaction.getTangentSpaceV(); +// const vector3_type H = ndf.generateH(localV, u); + +// cache = anisocache_type::createForReflection(localV, H); +// ray_dir_info_type localL; +// bxdf::Reflect r = bxdf::Reflect::create(localV, H); +// localL = localL.reflect(r); + +// return sample_type::createFromTangentSpace(localL, interaction.getFromTangentSpace()); +// } + +// scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) +// { +// using quant_query_type = typename N::quant_query_type; +// using dg1_query_type = typename N::dg1_query_type; + +// scalar_type dummy; +// quant_query_type qq = ndf.template createQuantQuery(cache, dummy); +// dg1_query_type dq = ndf.template createDG1Query(interaction, cache); +// quant_type DG1 = ndf.template DG1(dq, qq, _sample, interaction); +// return DG1.projectedLightMeasure; +// } +// scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// using quant_query_type = typename N::quant_query_type; +// using dg1_query_type = typename N::dg1_query_type; + +// scalar_type dummy; +// quant_query_type qq = ndf.template createQuantQuery(cache, dummy); +// dg1_query_type dq = ndf.template createDG1Query(interaction, cache); +// quant_type DG1 = ndf.template DG1(dq, qq, _sample, interaction); +// return DG1.projectedLightMeasure; +// } + +// quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) +// { +// scalar_type _pdf = pdf(_sample, interaction, cache); + +// spectral_type quo = hlsl::promote(0.0); +// if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) +// { +// using g2g1_query_type = typename N::g2g1_query_type; + +// g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); +// scalar_type G2_over_G1 = ndf.template G2_over_G1(gq, _sample, interaction, cache); +// const spectral_type reflectance = fresnel(cache.getVdotH()); +// quo = reflectance * G2_over_G1; +// } + +// return quotient_pdf_type::create(quo, _pdf); +// } +// quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// scalar_type _pdf = pdf(_sample, interaction, cache); + +// spectral_type quo = hlsl::promote(0.0); +// if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) +// { +// using g2g1_query_type = typename N::g2g1_query_type; + +// g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); +// scalar_type G2_over_G1 = ndf.template G2_over_G1(gq, _sample, interaction, cache); +// const spectral_type reflectance = fresnel(cache.getVdotH()); +// quo = reflectance * G2_over_G1; +// } + +// return quotient_pdf_type::create(quo, _pdf); +// } + +// N ndf; +// F fresnel; +// }; + +// template +// NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration && ndf::NDF && fresnel::Fresnel) +// struct SCookTorrance && ndf::NDF && fresnel::Fresnel) > +// { +// MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); + +// using quant_type = typename N::quant_type; + +// spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) +// { +// using quant_query_type = typename N::quant_query_type; +// using g2g1_query_type = typename N::g2g1_query_type; + +// fresnel::OrientedEtas orientedEta = fresnel.orientedEta; +// quant_query_type qq = ndf.template createQuantQuery(cache, orientedEta.value[0]); +// g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); + +// quant_type D = ndf.template D(qq, _sample, interaction, cache); +// scalar_type DG = D.projectedLightMeasure; +// if (any >(ndf.__base.A > hlsl::promote(numeric_limits::min))) +// { +// DG *= ndf.template correlated(gq, _sample, interaction); +// } +// return hlsl::promote(fresnel(hlsl::abs(cache.getVdotH()))[0]) * DG; +// } +// spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// using quant_query_type = typename N::quant_query_type; +// using g2g1_query_type = typename N::g2g1_query_type; + +// fresnel::OrientedEtas orientedEta = fresnel.orientedEta; +// quant_query_type qq = ndf.template createQuantQuery(cache, orientedEta.value[0]); +// g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); + +// quant_type D = ndf.template D(qq, _sample, interaction, cache); +// scalar_type DG = D.projectedLightMeasure; +// if (any >(ndf.__base.A > hlsl::promote(numeric_limits::min))) +// { +// DG *= ndf.template correlated(gq, _sample, interaction); +// } +// return hlsl::promote(fresnel(hlsl::abs(cache.getVdotH()))[0]) * DG; +// } + +// sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(isocache_type) cache, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) +// { +// anisocache_type anisocache; +// sample_type s = generate(anisotropic_interaction_type::create(interaction), u, anisocache, luminosityContributionHint); +// cache = anisocache.iso_cache; +// return s; +// } +// sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(anisocache_type) cache, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) +// { +// const vector3_type localV = interaction.getTangentSpaceV(); + +// fresnel::OrientedEtas orientedEta = fresnel.orientedEta; +// fresnel::OrientedEtaRcps rcpEta = orientedEta.getReciprocals(); + +// const vector3_type upperHemisphereV = hlsl::mix(localV, -localV, interaction.getNdotV() < scalar_type(0.0)); +// const vector3_type H = ndf.generateH(upperHemisphereV, u.xy); + +// const scalar_type reflectance = fresnel(hlsl::abs(hlsl::dot(localV, H)))[0]; +// const scalar_type reflectionProb = hlsl::dot(hlsl::promote(reflectance), luminosityContributionHint); + +// scalar_type rcpChoiceProb; +// scalar_type z = u.z; +// bool transmitted = math::partitionRandVariable(reflectionProb, z, rcpChoiceProb); + +// cache = anisocache_type::createForReflection(localV, H); + +// Refract r = Refract::create(localV, H); +// cache.iso_cache.LdotH = hlsl::mix(cache.getVdotH(), r.getNdotT(rcpEta.value2[0]), transmitted); +// ray_dir_info_type localL; +// bxdf::ReflectRefract rr; +// rr.refract = r; +// localL = localL.reflectRefract(rr, transmitted, rcpEta.value[0]); + +// // fail if samples have invalid paths +// if ((!transmitted && hlsl::sign(localL.getDirection().z) != hlsl::sign(localV.z)) || (transmitted && hlsl::sign(localL.getDirection().z) == hlsl::sign(localV.z))) +// { +// localL.direction = vector3_type(0,0,0); // should check if sample direction is invalid +// } + +// return sample_type::createFromTangentSpace(localL, interaction.getFromTangentSpace()); +// } + +// scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) +// { +// using quant_query_type = typename N::quant_query_type; +// using dg1_query_type = typename N::dg1_query_type; + +// fresnel::OrientedEtas orientedEta = fresnel.orientedEta; +// quant_query_type qq = ndf.template createQuantQuery(cache, orientedEta.value[0]); +// dg1_query_type dq = ndf.template createDG1Query(interaction, cache); +// quant_type DG1 = ndf.template DG1(dq, qq, _sample, interaction); + +// const scalar_type reflectance = fresnel(hlsl::abs(cache.getVdotH()))[0]; +// return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * DG1.projectedLightMeasure; +// } +// scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// using quant_query_type = typename N::quant_query_type; +// using dg1_query_type = typename N::dg1_query_type; + +// fresnel::OrientedEtas orientedEta = fresnel.orientedEta; +// quant_query_type qq = ndf.template createQuantQuery(cache, orientedEta.value[0]); +// dg1_query_type dq = ndf.template createDG1Query(interaction, cache); +// quant_type DG1 = ndf.template DG1(dq, qq, _sample, interaction); + +// const scalar_type reflectance = fresnel(hlsl::abs(cache.getVdotH()))[0]; +// return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * DG1.projectedLightMeasure; +// } + +// quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) +// { +// scalar_type _pdf = pdf(_sample, interaction, cache); + +// using g2g1_query_type = typename N::g2g1_query_type; + +// g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); +// scalar_type quo = ndf.template G2_over_G1(gq, _sample, interaction, cache); + +// return quotient_pdf_type::create(quo, _pdf); +// } +// quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// scalar_type _pdf = pdf(_sample, interaction, cache); + +// using g2g1_query_type = typename N::g2g1_query_type; + +// g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); +// scalar_type quo = ndf.template G2_over_G1(gq, _sample, interaction, cache); + +// return quotient_pdf_type::create(quo, _pdf); +// } + +// N ndf; +// F fresnel; +// }; + } } } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 21f3c9a280..22018b0fff 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -62,11 +62,14 @@ struct SBeckmannIsotropic sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache) { - return __base.generate(interaction, u, cache); + anisocache_type aniso_cache; + sample_type s = __base.template generate(anisotropic_interaction_type::create(interaction), u, aniso_cache); + cache = aniso_cache.iso_cache; + return s; } sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache) { - return __base.generate(interaction.isotropic, u, cache.iso_cache); + return __base.template generate(interaction, u, cache); } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) @@ -132,7 +135,7 @@ struct SBeckmannAnisotropic sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache) { - return __base.generate(interaction, u, cache); + return __base.template generate(interaction, u, cache); } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 4c4157a0bd..d063acdba2 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -63,11 +63,14 @@ struct SGGXIsotropic sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache) { - return __base.generate(interaction, u, cache); + anisocache_type aniso_cache; + sample_type s = __base.template generate(anisotropic_interaction_type::create(interaction), u, aniso_cache); + cache = aniso_cache.iso_cache; + return s; } sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache) { - return __base.generate(interaction.isotropic, u, cache.iso_cache); + return __base.template generate(interaction, u, cache); } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) @@ -133,7 +136,7 @@ struct SGGXAnisotropic sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache) { - return __base.generate(interaction, u, cache); + return __base.template generate(interaction, u, cache); } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 6bb83b20b6..7b0565423b 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -43,7 +43,7 @@ struct SBeckmannDielectricIsotropic retval.__base.ndf.__base.a2 = A*A; retval.__base.fresnel.orientedEta = orientedEta; retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; - retval.luminosityContributionHint = luminosityContributionHint; + retval.__base.luminosityContributionHint = luminosityContributionHint; return retval; } static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type A) @@ -66,13 +66,16 @@ struct SBeckmannDielectricIsotropic return __base.eval(_sample, interaction.isotropic, cache.iso_cache); } - sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(isocache_type) cache) { - return __base.generate(interaction, u, cache, luminosityContributionHint); + anisocache_type aniso_cache; + sample_type s = __base.template generate(anisotropic_interaction_type::create(interaction), u, aniso_cache); + cache = aniso_cache.iso_cache; + return s; } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(anisocache_type) cache) { - return __base.generate(interaction.isotropic, u, cache.iso_cache, luminosityContributionHint); + return __base.template generate(interaction, u, cache); } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) @@ -94,27 +97,13 @@ struct SBeckmannDielectricIsotropic } SCookTorrance __base; - spectral_type luminosityContributionHint; }; template) struct SBeckmannDielectricAnisotropic { using this_t = SBeckmannDielectricAnisotropic; - 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(matrix3x3_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); - NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); - NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); + MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); using ndf_type = ndf::Beckmann; using fresnel_type = fresnel::Dielectric; @@ -137,7 +126,7 @@ struct SBeckmannDielectricAnisotropic retval.__base.ndf.__base.a2 = ax*ay; retval.__base.fresnel.orientedEta = orientedEta; retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; - retval.luminosityContributionHint = luminosityContributionHint; + retval.__base.luminosityContributionHint = luminosityContributionHint; return retval; } static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type ax, scalar_type ay) @@ -156,12 +145,12 @@ struct SBeckmannDielectricAnisotropic return __base.eval(_sample, interaction, cache); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(anisocache_type) cache) { - return __base.generate(interaction, u, cache, luminosityContributionHint); + return __base.template generate(interaction, u, cache); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u) { anisocache_type dummycache; return generate(interaction, u, dummycache); @@ -178,7 +167,6 @@ struct SBeckmannDielectricAnisotropic } SCookTorrance __base; - spectral_type luminosityContributionHint; }; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index b6480436cf..e0750a6c98 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -44,7 +44,7 @@ struct SGGXDielectricIsotropic retval.__base.ndf.__base.one_minus_a2 = scalar_type(1.0) - A*A; retval.__base.fresnel.orientedEta = orientedEta; retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; - retval.luminosityContributionHint = luminosityContributionHint; + retval.__base.luminosityContributionHint = luminosityContributionHint; return retval; } static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type A) @@ -67,13 +67,16 @@ struct SGGXDielectricIsotropic return __base.eval(_sample, interaction.isotropic, cache.iso_cache); } - sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(isocache_type) cache) { - return __base.generate(interaction, u, cache, luminosityContributionHint); + anisocache_type aniso_cache; + sample_type s = __base.template generate(anisotropic_interaction_type::create(interaction), u, aniso_cache); + cache = aniso_cache.iso_cache; + return s; } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(anisocache_type) cache) { - return __base.generate(interaction.isotropic, u, cache.iso_cache, luminosityContributionHint); + return __base.template generate(interaction, u, cache); } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) @@ -95,27 +98,13 @@ struct SGGXDielectricIsotropic } SCookTorrance __base; - spectral_type luminosityContributionHint; }; template) struct SGGXDielectricAnisotropic { using this_t = SGGXDielectricAnisotropic; - 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(matrix3x3_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); - NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); - NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); + MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); using ndf_type = ndf::GGX; using fresnel_type = fresnel::Dielectric; @@ -138,7 +127,7 @@ struct SGGXDielectricAnisotropic retval.__base.ndf.__base.a2 = ax*ay; retval.__base.fresnel.orientedEta = orientedEta; retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; - retval.luminosityContributionHint = luminosityContributionHint; + retval.__base.luminosityContributionHint = luminosityContributionHint; return retval; } static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type ax, scalar_type ay) @@ -157,12 +146,12 @@ struct SGGXDielectricAnisotropic return __base.eval(_sample, interaction, cache); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(anisocache_type) cache) { - return __base.generate(interaction, u, cache, luminosityContributionHint); + return __base.template generate(interaction, u, cache); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u) { anisocache_type dummycache; return generate(interaction, u, dummycache); @@ -179,7 +168,6 @@ struct SGGXDielectricAnisotropic } SCookTorrance __base; - spectral_type luminosityContributionHint; }; } From 638b8b5a877a7e0eb265ce99bace7747f1ebcc03 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 23 Sep 2025 16:43:20 +0700 Subject: [PATCH 29/38] moved duplicate code in eval, pdf, quotient_pdf into templated interaction/cache versions --- .../builtin/hlsl/bxdf/cook_torrance_base.hlsl | 101 ++++++------------ 1 file changed, 32 insertions(+), 69 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl index 691d04d090..fda557d083 100644 --- a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl @@ -77,7 +77,8 @@ struct SCookTorrance using quant_type = typename N::quant_type; - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + template + spectral_type __eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { if (IsBSDF || (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min)) { @@ -85,14 +86,14 @@ struct SCookTorrance using g2g1_query_type = typename N::g2g1_query_type; scalar_type dummy; - quant_query_type qq = ndf.template createQuantQuery(cache, dummy); + quant_query_type qq = ndf.template createQuantQuery(cache, dummy); - quant_type D = ndf.template D(qq, _sample, interaction, cache); + quant_type D = ndf.template D(qq, _sample, interaction, cache); scalar_type DG = D.projectedLightMeasure; - if (any >(ndf.__base.A > hlsl::promote(numeric_limits::min))) + if (D.microfacetMeasure < numeric_limits::infinity) { - g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); - DG *= ndf.template correlated(gq, _sample, interaction); + g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); + DG *= ndf.template correlated(gq, _sample, interaction); } NBL_IF_CONSTEXPR(IsBSDF) return impl::__implicit_promote::__call(fresnel(hlsl::abs(cache.getVdotH()))) * DG; @@ -102,30 +103,13 @@ struct SCookTorrance else return hlsl::promote(0.0); } + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + { + return __eval(_sample, interaction, cache); + } spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - if (IsBSDF || (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min)) - { - using quant_query_type = typename N::quant_query_type; - using g2g1_query_type = typename N::g2g1_query_type; - - scalar_type dummy; - quant_query_type qq = ndf.template createQuantQuery(cache, dummy); - - quant_type D = ndf.template D(qq, _sample, interaction, cache); - scalar_type DG = D.projectedLightMeasure; - if (any >(ndf.__base.A > hlsl::promote(numeric_limits::min))) - { - g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); - DG *= ndf.template correlated(gq, _sample, interaction); - } - NBL_IF_CONSTEXPR(IsBSDF) - return impl::__implicit_promote::__call(fresnel(hlsl::abs(cache.getVdotH()))) * DG; - else - return impl::__implicit_promote::__call(fresnel(cache.getVdotH())) * DG; - } - else - return hlsl::promote(0.0); + return __eval(_sample, interaction, cache); } template) @@ -176,15 +160,16 @@ struct SCookTorrance return sample_type::createFromTangentSpace(localL, interaction.getFromTangentSpace()); } - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + template + scalar_type __pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { using quant_query_type = typename N::quant_query_type; using dg1_query_type = typename N::dg1_query_type; - dg1_query_type dq = ndf.template createDG1Query(interaction, cache); + dg1_query_type dq = ndf.template createDG1Query(interaction, cache); - quant_query_type qq = impl::quant_query_helper::template __call(ndf, fresnel, cache); - quant_type DG1 = ndf.template DG1(dq, qq, _sample, interaction); + quant_query_type qq = impl::quant_query_helper::template __call(ndf, fresnel, cache); + quant_type DG1 = ndf.template DG1(dq, qq, _sample, interaction); NBL_IF_CONSTEXPR(IsBSDF) { @@ -196,38 +181,27 @@ struct SCookTorrance return DG1.projectedLightMeasure; } } + scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + { + return __pdf(_sample, interaction, cache); + } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - using quant_query_type = typename N::quant_query_type; - using dg1_query_type = typename N::dg1_query_type; - - dg1_query_type dq = ndf.template createDG1Query(interaction, cache); - - quant_query_type qq = impl::quant_query_helper::template __call(ndf, fresnel, cache); - quant_type DG1 = ndf.template DG1(dq, qq, _sample, interaction); - - NBL_IF_CONSTEXPR(IsBSDF) - { - const scalar_type reflectance = fresnel(hlsl::abs(cache.getVdotH()))[0]; - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * DG1.projectedLightMeasure; - } - else - { - return DG1.projectedLightMeasure; - } + return __pdf(_sample, interaction, cache); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + template + 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) { - scalar_type _pdf = pdf(_sample, interaction, cache); + scalar_type _pdf = __pdf(_sample, interaction, cache); spectral_type quo = hlsl::promote(0.0); if (IsBSDF || (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min)) { using g2g1_query_type = typename N::g2g1_query_type; - g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); - scalar_type G2_over_G1 = ndf.template G2_over_G1(gq, _sample, interaction, cache); + g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); + scalar_type G2_over_G1 = ndf.template G2_over_G1(gq, _sample, interaction, cache); NBL_IF_CONSTEXPR(IsBSDF) quo = hlsl::promote(G2_over_G1); else @@ -236,24 +210,13 @@ struct SCookTorrance return quotient_pdf_type::create(quo, _pdf); } + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + { + return __quotient_and_pdf(_sample, interaction, cache); + } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - scalar_type _pdf = pdf(_sample, interaction, cache); - - spectral_type quo = hlsl::promote(0.0); - if (IsBSDF || (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min)) - { - using g2g1_query_type = typename N::g2g1_query_type; - - g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); - scalar_type G2_over_G1 = ndf.template G2_over_G1(gq, _sample, interaction, cache); - NBL_IF_CONSTEXPR(IsBSDF) - quo = hlsl::promote(G2_over_G1); - else - quo = fresnel(cache.getVdotH()) * G2_over_G1; - } - - return quotient_pdf_type::create(quo, _pdf); + return __quotient_and_pdf(_sample, interaction, cache); } N ndf; From c5878208ae5c9aa0f928316025a634c96167d329 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 24 Sep 2025 14:46:22 +0700 Subject: [PATCH 30/38] some changes to fresnel, cook torrance base --- .../nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl | 12 ++++++------ include/nbl/builtin/hlsl/bxdf/fresnel.hlsl | 2 ++ include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 4 ++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl index fda557d083..a70b2cded5 100644 --- a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl @@ -128,34 +128,34 @@ struct SCookTorrance template) sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const T u, NBL_REF_ARG(anisocache_type) cache) { - fresnel::OrientedEtas orientedEta = fresnel.orientedEta; - fresnel::OrientedEtaRcps rcpEta = orientedEta.getReciprocals(); + fresnel::OrientedEtaRcps rcpEta = fresnel.getOrientedEtaRcps(); const vector3_type localV = interaction.getTangentSpaceV(); const vector3_type upperHemisphereV = hlsl::mix(localV, -localV, interaction.getNdotV() < scalar_type(0.0)); const vector3_type localH = ndf.generateH(upperHemisphereV, u.xy); - const scalar_type reflectance = fresnel(hlsl::abs(hlsl::dot(localV, localH)))[0]; + const scalar_type VdotH = hlsl::dot(localV, localH); + const scalar_type reflectance = fresnel(hlsl::abs(VdotH))[0]; const scalar_type reflectionProb = hlsl::dot(hlsl::promote(reflectance), luminosityContributionHint); scalar_type rcpChoiceProb; scalar_type z = u.z; bool transmitted = math::partitionRandVariable(reflectionProb, z, rcpChoiceProb); - cache = anisocache_type::createForReflection(localV, localH); - Refract r = Refract::create(localV, localH); - cache.iso_cache.LdotH = hlsl::mix(cache.getVdotH(), r.getNdotT(rcpEta.value2[0]), transmitted); ray_dir_info_type localL; bxdf::ReflectRefract rr; rr.refract = r; localL = localL.reflectRefract(rr, transmitted, rcpEta.value[0]); // fail if samples have invalid paths + // TODO fix this: if (ComputeMicrofacetNormal::isTransmissionPath(VdotH, hlsl::dot(localL.getDirection(), localH)) != transmitted) if ((!transmitted && hlsl::sign(localL.getDirection().z) != hlsl::sign(localV.z)) || (transmitted && hlsl::sign(localL.getDirection().z) == hlsl::sign(localV.z))) { localL.direction = vector3_type(0,0,0); // should check if sample direction is invalid } + else + cache = anisocache_type::create(localV, localH, transmitted, rcpEta); return sample_type::createFromTangentSpace(localL, interaction.getFromTangentSpace()); } diff --git a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl index 83ffdc8722..6cf4621950 100644 --- a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl @@ -420,6 +420,8 @@ struct Dielectric return __call(orientedEta2, clampedCosTheta); } + OrientedEtaRcps getOrientedEtaRcps() NBL_CONST_MEMBER_FUNC { return orientedEta.getReciprocals(); } + OrientedEtas orientedEta; T orientedEta2; }; diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index 5da686673a..f274c5ae26 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -313,7 +313,7 @@ struct GGX(cache); - scalar_type clampedNdotV = interaction.getNdotV(BxDFClampMode::BCM_MAX); + scalar_type clampedNdotV = interaction.getNdotV(); dg1_query.G1 = scalar_type(2.0) * clampedNdotV * __base.G1_wo_numerator(clampedNdotV, interaction.getNdotV2()); return dg1_query; } @@ -386,7 +386,7 @@ struct GGX(cache); - scalar_type clampedNdotV = interaction.getNdotV(BxDFClampMode::BCM_MAX); + scalar_type clampedNdotV = interaction.getNdotV(); dg1_query.G1 = scalar_type(2.0) * clampedNdotV * __base.G1_wo_numerator(clampedNdotV, interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); return dg1_query; } From d4383604a76b1a37fac3e469bb2a80566bd5d24c Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 24 Sep 2025 16:48:36 +0700 Subject: [PATCH 31/38] reverted ggx ndf to use optimizations --- include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 92 +++++++++++++++---- .../ndf/microfacet_to_light_transform.hlsl | 2 + 2 files changed, 75 insertions(+), 19 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index f274c5ae26..b257d692fd 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -25,10 +25,10 @@ struct SGGXDG1Query using scalar_type = T; scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } - scalar_type getG1() NBL_CONST_MEMBER_FUNC { return G1; } + scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; } scalar_type ndf; - scalar_type G1; + scalar_type G1_over_2NdotV; }; template @@ -78,7 +78,7 @@ struct GGXCommon) > scalar_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query) { - return query.getNdf() * query.getG1(); + return scalar_type(0.5) * query.getNdf() * query.getG1over2NdotV(); } scalar_type devsh_part(scalar_type NdotX2) @@ -166,6 +166,8 @@ struct GGXCommon) > return numbers::inv_pi / (a2 * denom * denom); } + // TODO: potential idea for making GGX spin using covariance matrix of sorts: https://www.desmos.com/3d/weq2ginq9o + // burley scalar_type D(scalar_type a2, scalar_type TdotH, scalar_type BdotH, scalar_type NdotH, scalar_type anisotropy) { @@ -314,7 +316,7 @@ struct GGX(cache); scalar_type clampedNdotV = interaction.getNdotV(); - dg1_query.G1 = scalar_type(2.0) * clampedNdotV * __base.G1_wo_numerator(clampedNdotV, interaction.getNdotV2()); + dg1_query.G1_over_2NdotV = __base.G1_wo_numerator(clampedNdotV, interaction.getNdotV2()); return dg1_query; } template && surface_interactions::Isotropic) @@ -336,20 +338,26 @@ struct GGX(cache); - return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); + quant_type dmq; + dmq.microfacetMeasure = d; + dmq.projectedLightMeasure = d * _sample.getNdotL(BxDFClampMode::BCM_MAX); + return dmq; } template && surface_interactions::Isotropic) quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { scalar_type dg1 = __base.DG1(query); - return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); + quant_type dmq; + dmq.microfacetMeasure = dg1; + dmq.projectedLightMeasure = dg1;// TODO: figure this out * _sample.getNdotL(BxDFClampMode::BCM_MAX); + return dmq; } template && surface_interactions::Isotropic) scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - return __base.template correlated(query, _sample, interaction); + return __base.template correlated_wo_numerator(query, _sample, interaction); } template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) @@ -387,7 +395,7 @@ struct GGX(cache); scalar_type clampedNdotV = interaction.getNdotV(); - dg1_query.G1 = scalar_type(2.0) * clampedNdotV * __base.G1_wo_numerator(clampedNdotV, interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + dg1_query.G1_over_2NdotV = __base.G1_wo_numerator(clampedNdotV, interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); return dg1_query; } template && surface_interactions::Anisotropic) @@ -409,20 +417,26 @@ struct GGX(cache); - return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); + quant_type dmq; + dmq.microfacetMeasure = d; + dmq.projectedLightMeasure = d * _sample.getNdotL(BxDFClampMode::BCM_MAX); + return dmq; } template && surface_interactions::Anisotropic) quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { scalar_type dg1 = __base.DG1(query); - return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); + quant_type dmq; + dmq.microfacetMeasure = dg1; + dmq.projectedLightMeasure = dg1;// TODO: figure this out * _sample.getNdotL(BxDFClampMode::BCM_MAX); + return dmq; } template && surface_interactions::Anisotropic) scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - return __base.template correlated(query, _sample, interaction); + return __base.template correlated_wo_numerator(query, _sample, interaction); } template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) @@ -463,7 +477,7 @@ struct GGX(cache); scalar_type clampedNdotV = interaction.getNdotV(BxDFClampMode::BCM_ABS); - dg1_query.G1 = scalar_type(2.0) * clampedNdotV * __base.G1_wo_numerator(clampedNdotV, interaction.getNdotV2()); + dg1_query.G1_over_2NdotV = __base.G1_wo_numerator(clampedNdotV, interaction.getNdotV2()); return dg1_query; } template && surface_interactions::Isotropic) @@ -485,20 +499,40 @@ struct GGX(cache); - return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + quant_type dmq; + dmq.microfacetMeasure = d; // note: microfacetMeasure/2NdotV + + const scalar_type VdotHLdotH = quant_query.getVdotHLdotH(); + const scalar_type VdotH_etaLdotH = quant_query.getVdotH_etaLdotH(); + const bool transmitted = reflect_refract==MTT_REFRACT || (reflect_refract!=MTT_REFLECT && VdotHLdotH < scalar_type(0.0)); + scalar_type NdotL_over_denominator = _sample.getNdotL(BxDFClampMode::BCM_ABS); + if (transmitted) + NdotL_over_denominator *= -scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); + dmq.projectedLightMeasure = d * NdotL_over_denominator; + return dmq; } template && surface_interactions::Isotropic) quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { scalar_type dg1 = __base.DG1(query); - return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + quant_type dmq; + dmq.microfacetMeasure = dg1; // note: microfacetMeasure/2NdotV + + const scalar_type VdotHLdotH = quant_query.getVdotHLdotH(); + const scalar_type VdotH_etaLdotH = quant_query.getVdotH_etaLdotH(); + const bool transmitted = reflect_refract==MTT_REFRACT || (reflect_refract!=MTT_REFLECT && VdotHLdotH < scalar_type(0.0)); + scalar_type NdotL_over_denominator = _sample.getNdotL(BxDFClampMode::BCM_ABS); + if (transmitted) + NdotL_over_denominator *= -scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); + dmq.projectedLightMeasure = dg1;// TODO: figure this out * NdotL_over_denominator; + return dmq; } template && surface_interactions::Isotropic) scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - return __base.template correlated(query, _sample, interaction); + return __base.template correlated_wo_numerator(query, _sample, interaction); } template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) @@ -538,7 +572,7 @@ struct GGX(cache); scalar_type clampedNdotV = interaction.getNdotV(BxDFClampMode::BCM_ABS); - dg1_query.G1 = scalar_type(2.0) * clampedNdotV * __base.G1_wo_numerator(clampedNdotV, interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + dg1_query.G1_over_2NdotV = __base.G1_wo_numerator(clampedNdotV, interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); return dg1_query; } template && surface_interactions::Anisotropic) @@ -560,20 +594,40 @@ struct GGX(cache); - return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + quant_type dmq; + dmq.microfacetMeasure = d; // note: microfacetMeasure/2NdotV + + const scalar_type VdotHLdotH = quant_query.getVdotHLdotH(); + const scalar_type VdotH_etaLdotH = quant_query.getVdotH_etaLdotH(); + const bool transmitted = reflect_refract==MTT_REFRACT || (reflect_refract!=MTT_REFLECT && VdotHLdotH < scalar_type(0.0)); + scalar_type NdotL_over_denominator = _sample.getNdotL(BxDFClampMode::BCM_ABS); + if (transmitted) + NdotL_over_denominator *= -scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); + dmq.projectedLightMeasure = d * NdotL_over_denominator; + return dmq; } template && surface_interactions::Anisotropic) quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { scalar_type dg1 = __base.DG1(query); - return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); + quant_type dmq; + dmq.microfacetMeasure = dg1; // note: microfacetMeasure/2NdotV + + const scalar_type VdotHLdotH = quant_query.getVdotHLdotH(); + const scalar_type VdotH_etaLdotH = quant_query.getVdotH_etaLdotH(); + const bool transmitted = reflect_refract==MTT_REFRACT || (reflect_refract!=MTT_REFLECT && VdotHLdotH < scalar_type(0.0)); + scalar_type NdotL_over_denominator = _sample.getNdotL(BxDFClampMode::BCM_ABS); + if (transmitted) + NdotL_over_denominator *= -scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); + dmq.projectedLightMeasure = dg1;// TODO: figure this out * NdotL_over_denominator; + return dmq; } template && surface_interactions::Anisotropic) scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - return __base.template correlated(query, _sample, interaction); + return __base.template correlated_wo_numerator(query, _sample, interaction); } template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl index 4a4679d137..badfbd99f0 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl @@ -42,6 +42,7 @@ struct createDualMeasureQuantity_helper static SDualMeasureQuant __call(const T microfacetMeasure, scalar_type clampedNdotV, scalar_type clampedNdotL, scalar_type VdotHLdotH, scalar_type VdotH_etaLdotH) { + assert(clampedNdotV >= scalar_type(0.0) && clampedNdotL >= scalar_type(0.0)); SDualMeasureQuant retval; retval.microfacetMeasure = microfacetMeasure; // do constexpr booleans first so optimizer picks up this and short circuits @@ -56,6 +57,7 @@ struct createDualMeasureQuantity_helper }; } +// specialMeasure meaning the measure defined by the specialization of createDualMeasureQuantity_helper; note that GGX redefines it somewhat template SDualMeasureQuant createDualMeasureQuantity(const T specialMeasure, typename vector_traits::scalar_type clampedNdotV, typename vector_traits::scalar_type clampedNdotL) { From 5f49f11be09e86dec25e038e5c073b19bff4295c Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 25 Sep 2025 16:39:35 +0700 Subject: [PATCH 32/38] pdf function checks for backfacing V --- .../builtin/hlsl/bxdf/cook_torrance_base.hlsl | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl index a70b2cded5..c957c5b79d 100644 --- a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl @@ -183,11 +183,17 @@ struct SCookTorrance } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - return __pdf(_sample, interaction, cache); + if (IsBSDF || (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min)) + return __pdf(_sample, interaction, cache); + else + return scalar_type(0.0); } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - return __pdf(_sample, interaction, cache); + if (IsBSDF || (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min)) + return __pdf(_sample, interaction, cache); + else + return scalar_type(0.0); } template @@ -196,17 +202,14 @@ struct SCookTorrance scalar_type _pdf = __pdf(_sample, interaction, cache); spectral_type quo = hlsl::promote(0.0); - if (IsBSDF || (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min)) - { - using g2g1_query_type = typename N::g2g1_query_type; - - g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); - scalar_type G2_over_G1 = ndf.template G2_over_G1(gq, _sample, interaction, cache); - NBL_IF_CONSTEXPR(IsBSDF) - quo = hlsl::promote(G2_over_G1); - else - quo = fresnel(cache.getVdotH()) * G2_over_G1; - } + + using g2g1_query_type = typename N::g2g1_query_type; + g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); + scalar_type G2_over_G1 = ndf.template G2_over_G1(gq, _sample, interaction, cache); + NBL_IF_CONSTEXPR(IsBSDF) + quo = hlsl::promote(G2_over_G1); + else + quo = fresnel(cache.getVdotH()) * G2_over_G1; return quotient_pdf_type::create(quo, _pdf); } From 627074b6074675498c590b0cf42e691f3d1fb2f5 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 25 Sep 2025 16:40:59 +0700 Subject: [PATCH 33/38] reduced beckmann, ggx ndfs to single struct with enable_ifs --- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 279 +++------------- include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 298 +++--------------- 2 files changed, 93 insertions(+), 484 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index b973af9ed9..c7274fdbba 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -109,14 +109,13 @@ struct BeckmannCommon && surface_interactions::Isotropic) - scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query) { return scalar_type(1.0) / (scalar_type(1.0) + query.getLambdaV() + query.getLambdaL()); } - template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) { scalar_type onePlusLambda_V = scalar_type(1.0) + query.getLambdaV(); scalar_type lambda_L = query.getLambdaL(); @@ -138,8 +137,9 @@ struct BeckmannCommon) scalar_type D(NBL_CONST_REF_ARG(MicrofacetCache) cache) { - scalar_type nom = exp(-(cache.getTdotH2() / ax2 + cache.getBdotH2() / ay2) / cache.getNdotH2()); - scalar_type denom = a2 * cache.getNdotH2() * cache.getNdotH2(); + scalar_type NdotH2 = cache.getNdotH2(); + scalar_type nom = exp(-(cache.getTdotH2() / ax2 + cache.getBdotH2() / ay2) / NdotH2); + scalar_type denom = a2 * NdotH2 * NdotH2; return numbers::inv_pi * nom / denom; } @@ -179,14 +179,13 @@ struct BeckmannCommon && surface_interactions::Anisotropic) - scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query) { return scalar_type(1.0) / (scalar_type(1.0) + query.getLambdaV() + query.getLambdaL()); } - template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) { scalar_type onePlusLambda_V = scalar_type(1.0) + query.getLambdaV(); scalar_type lambda_L = query.getLambdaL(); @@ -276,16 +275,12 @@ struct BeckmannGenerateH }; } -template -struct Beckmann; -// partial spec for brdf -template -NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) -struct Beckmann) > +template) +struct Beckmann { using scalar_type = T; - using base_type = impl::BeckmannCommon; + using base_type = impl::BeckmannCommon; using quant_type = SDualMeasureQuant; using vector2_type = vector; using vector3_type = vector; @@ -294,240 +289,52 @@ struct Beckmann; - template) - quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) - { - quant_query_type dummy; // brdfs don't make use of this - return dummy; - } - template && ReadableIsotropicMicrofacetCache) - dg1_query_type createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) - { - dg1_query_type dg1_query; - dg1_query.ndf = __base.template D(cache); - dg1_query.lambda_V = __base.LambdaC2(interaction.getNdotV2()); - return dg1_query; - } - template && surface_interactions::Isotropic) - g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) - { - g2g1_query_type g2_query; - g2_query.lambda_L = __base.LambdaC2(_sample.getNdotL2()); - g2_query.lambda_V = __base.LambdaC2(interaction.getNdotV2()); - return g2_query; - } + NBL_CONSTEXPR_STATIC_INLINE bool IsBSDF = reflect_refract != MTT_REFLECT; + template + NBL_CONSTEXPR_STATIC_INLINE bool RequiredInteraction = IsAnisotropic ? surface_interactions::Anisotropic : surface_interactions::Isotropic; + template + NBL_CONSTEXPR_STATIC_INLINE bool RequiredMicrofacetCache = IsAnisotropic ? AnisotropicMicrofacetCache : ReadableIsotropicMicrofacetCache; - vector generateH(const vector3_type localV, const vector2_type u) - { - return impl::BeckmannGenerateH::__call(__base.A, localV, u); - } - - template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) - quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) - { - scalar_type d = __base.template D(cache); - return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); - } - - template && surface_interactions::Isotropic) - quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) - { - scalar_type dg1 = __base.DG1(query); - return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); - } - - template && surface_interactions::Isotropic) - scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) - { - return __base.template correlated(query, _sample, interaction); - } - - template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) - { - return __base.template G2_over_G1(query, _sample, interaction, cache); - } - - base_type __base; -}; - -template -NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) -struct Beckmann) > -{ - using scalar_type = T; - using base_type = impl::BeckmannCommon; - using quant_type = SDualMeasureQuant; - using vector2_type = vector; - using vector3_type = vector; - - using dg1_query_type = typename base_type::dg1_query_type; - using g2g1_query_type = typename base_type::g2g1_query_type; - using quant_query_type = impl::SBeckmannQuantQuery; - - template) - quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) + template NBL_FUNC_REQUIRES(RequiredMicrofacetCache) + enable_if_t createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) { quant_query_type dummy; // brdfs don't make use of this return dummy; } - template && AnisotropicMicrofacetCache) - dg1_query_type createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) - { - dg1_query_type dg1_query; - dg1_query.ndf = __base.template D(cache); - dg1_query.lambda_V = __base.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); - return dg1_query; - } - template && surface_interactions::Anisotropic) - g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) - { - g2g1_query_type g2_query; - g2_query.lambda_L = __base.LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); - g2_query.lambda_V = __base.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); - return g2_query; - } - - vector generateH(const vector3_type localV, const vector2_type u) - { - return impl::BeckmannGenerateH::__call(__base.A, localV, u); - } - - template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) - { - scalar_type d = __base.template D(cache); - return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); - } - - template && surface_interactions::Anisotropic) - quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) - { - scalar_type dg1 = __base.DG1(query); - return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); - } - - template && surface_interactions::Anisotropic) - scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) - { - return __base.template correlated(query, _sample, interaction); - } - - template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) - { - return __base.template G2_over_G1(query, _sample, interaction, cache); - } - - base_type __base; -}; - -// partial for bsdf -template -NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) -struct Beckmann) > -{ - using scalar_type = T; - using base_type = impl::BeckmannCommon; - using quant_type = SDualMeasureQuant; - using vector2_type = vector; - using vector3_type = vector; - - using dg1_query_type = typename base_type::dg1_query_type; - using g2g1_query_type = typename base_type::g2g1_query_type; - using quant_query_type = impl::SBeckmannQuantQuery; - - template) - quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) + template NBL_FUNC_REQUIRES(RequiredMicrofacetCache) + enable_if_t createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) { quant_query_type quant_query; quant_query.VdotHLdotH = cache.getVdotHLdotH(); quant_query.VdotH_etaLdotH = cache.getVdotH() + orientedEta * cache.getLdotH(); return quant_query; } - template && ReadableIsotropicMicrofacetCache) - dg1_query_type createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template NBL_FUNC_REQUIRES(RequiredInteraction && RequiredMicrofacetCache) + enable_if_t createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { dg1_query_type dg1_query; dg1_query.ndf = __base.template D(cache); dg1_query.lambda_V = __base.LambdaC2(interaction.getNdotV2()); return dg1_query; } - template && surface_interactions::Isotropic) - g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + template NBL_FUNC_REQUIRES(LightSample && RequiredInteraction) + enable_if_t createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { g2g1_query_type g2_query; g2_query.lambda_L = __base.LambdaC2(_sample.getNdotL2()); g2_query.lambda_V = __base.LambdaC2(interaction.getNdotV2()); return g2_query; } - - vector generateH(const vector3_type localV, const vector2_type u) - { - return impl::BeckmannGenerateH::__call(__base.A, localV, u); - } - - template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) - quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) - { - scalar_type d = __base.template D(cache); - return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); - } - - template && surface_interactions::Isotropic) - quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) - { - scalar_type dg1 = __base.DG1(query); - return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); - } - - template && surface_interactions::Isotropic) - scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) - { - return __base.template correlated(query, _sample, interaction); - } - - template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) - { - return __base.template G2_over_G1(query, _sample, interaction, cache); - } - - base_type __base; -}; - -template -NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) -struct Beckmann) > -{ - using scalar_type = T; - using base_type = impl::BeckmannCommon; - using quant_type = SDualMeasureQuant; - using vector2_type = vector; - using vector3_type = vector; - - using dg1_query_type = typename base_type::dg1_query_type; - using g2g1_query_type = typename base_type::g2g1_query_type; - using quant_query_type = impl::SBeckmannQuantQuery; - - template) - quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) - { - quant_query_type quant_query; - quant_query.VdotHLdotH = cache.getVdotHLdotH(); - quant_query.VdotH_etaLdotH = cache.getVdotH() + orientedEta * cache.getLdotH(); - return quant_query; - } - template && AnisotropicMicrofacetCache) - dg1_query_type createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template NBL_FUNC_REQUIRES(RequiredInteraction && RequiredMicrofacetCache) + enable_if_t createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { dg1_query_type dg1_query; dg1_query.ndf = __base.template D(cache); dg1_query.lambda_V = __base.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); return dg1_query; } - template && surface_interactions::Anisotropic) - g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + template NBL_FUNC_REQUIRES(LightSample && RequiredInteraction) + enable_if_t createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { g2g1_query_type g2_query; g2_query.lambda_L = __base.LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); @@ -540,30 +347,42 @@ struct Beckmann::__call(__base.A, localV, u); } - template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template NBL_FUNC_REQUIRES(LightSample && RequiredInteraction && RequiredMicrofacetCache) + enable_if_t D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + { + scalar_type d = __base.template D(cache); + return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); + } + template NBL_FUNC_REQUIRES(LightSample && RequiredInteraction && RequiredMicrofacetCache) + enable_if_t D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { scalar_type d = __base.template D(cache); return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); } - template && surface_interactions::Anisotropic) - quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + template NBL_FUNC_REQUIRES(LightSample && RequiredInteraction) + enable_if_t DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + scalar_type dg1 = __base.DG1(query); + return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); + } + template NBL_FUNC_REQUIRES(LightSample && RequiredInteraction) + enable_if_t DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { scalar_type dg1 = __base.DG1(query); return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); } - template && surface_interactions::Anisotropic) + template && RequiredInteraction) scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - return __base.template correlated(query, _sample, interaction); + return __base.correlated(query); } - template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + template && RequiredInteraction && RequiredMicrofacetCache) scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { - return __base.template G2_over_G1(query, _sample, interaction, cache); + return __base.template G2_over_G1(query, cache); } base_type __base; diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index b257d692fd..b1bb0cca02 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -286,16 +286,12 @@ struct GGXGenerateH }; } -template -struct GGX; -// partial spec for brdf -template -NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) -struct GGX) > +template) +struct GGX { using scalar_type = T; - using base_type = impl::GGXCommon; + using base_type = impl::GGXCommon; using quant_type = SDualMeasureQuant; using vector2_type = vector; using vector3_type = vector; @@ -304,107 +300,61 @@ struct GGX; - template) - quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) + NBL_CONSTEXPR_STATIC_INLINE bool IsBSDF = reflect_refract != MTT_REFLECT; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = IsBSDF ? BxDFClampMode::BCM_ABS : BxDFClampMode::BCM_MAX; + template + NBL_CONSTEXPR_STATIC_INLINE bool RequiredInteraction = IsAnisotropic ? surface_interactions::Anisotropic : surface_interactions::Isotropic; + template + NBL_CONSTEXPR_STATIC_INLINE bool RequiredMicrofacetCache = IsAnisotropic ? AnisotropicMicrofacetCache : ReadableIsotropicMicrofacetCache; + + template NBL_FUNC_REQUIRES(RequiredMicrofacetCache) + enable_if_t createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) { quant_query_type dummy; // brdfs don't make use of this return dummy; } - template && ReadableIsotropicMicrofacetCache) - dg1_query_type createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template NBL_FUNC_REQUIRES(RequiredMicrofacetCache) + enable_if_t createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) + { + quant_query_type quant_query; + quant_query.VdotHLdotH = cache.getVdotHLdotH(); + quant_query.VdotH_etaLdotH = cache.getVdotH() + orientedEta * cache.getLdotH(); + return quant_query; + } + template NBL_FUNC_REQUIRES(RequiredInteraction && RequiredMicrofacetCache) + enable_if_t createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { dg1_query_type dg1_query; dg1_query.ndf = __base.template D(cache); - scalar_type clampedNdotV = interaction.getNdotV(); + scalar_type clampedNdotV = interaction.getNdotV(_clamp); dg1_query.G1_over_2NdotV = __base.G1_wo_numerator(clampedNdotV, interaction.getNdotV2()); return dg1_query; } - template && surface_interactions::Isotropic) - g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + template NBL_FUNC_REQUIRES(LightSample && RequiredInteraction) + enable_if_t createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { g2g1_query_type g2_query; g2_query.devsh_l = __base.devsh_part(_sample.getNdotL2()); g2_query.devsh_v = __base.devsh_part(interaction.getNdotV2()); - g2_query._clamp = BxDFClampMode::BCM_MAX; + g2_query._clamp = _clamp; return g2_query; } - - vector generateH(const vector3_type localV, const vector2_type u) - { - return impl::GGXGenerateH::__call(__base.A, localV, u); - } - - template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) - quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) - { - scalar_type d = __base.template D(cache); - quant_type dmq; - dmq.microfacetMeasure = d; - dmq.projectedLightMeasure = d * _sample.getNdotL(BxDFClampMode::BCM_MAX); - return dmq; - } - - template && surface_interactions::Isotropic) - quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) - { - scalar_type dg1 = __base.DG1(query); - quant_type dmq; - dmq.microfacetMeasure = dg1; - dmq.projectedLightMeasure = dg1;// TODO: figure this out * _sample.getNdotL(BxDFClampMode::BCM_MAX); - return dmq; - } - - template && surface_interactions::Isotropic) - scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) - { - return __base.template correlated_wo_numerator(query, _sample, interaction); - } - - template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) - { - return __base.template G2_over_G1(query, _sample, interaction, cache); - } - - base_type __base; -}; - -template -NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) -struct GGX) > -{ - using scalar_type = T; - using base_type = impl::GGXCommon; - using quant_type = SDualMeasureQuant; - using vector2_type = vector; - using vector3_type = vector; - - using dg1_query_type = typename base_type::dg1_query_type; - using g2g1_query_type = typename base_type::g2g1_query_type; - using quant_query_type = impl::SGGXQuantQuery; - - template) - quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) - { - quant_query_type dummy; // brdfs don't make use of this - return dummy; - } - template && AnisotropicMicrofacetCache) - dg1_query_type createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template NBL_FUNC_REQUIRES(RequiredInteraction && RequiredMicrofacetCache) + enable_if_t createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { dg1_query_type dg1_query; dg1_query.ndf = __base.template D(cache); - scalar_type clampedNdotV = interaction.getNdotV(); + scalar_type clampedNdotV = interaction.getNdotV(_clamp); dg1_query.G1_over_2NdotV = __base.G1_wo_numerator(clampedNdotV, interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); return dg1_query; } - template && surface_interactions::Anisotropic) - g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + template NBL_FUNC_REQUIRES(LightSample && RequiredInteraction) + enable_if_t createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { g2g1_query_type g2_query; g2_query.devsh_l = __base.devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); g2_query.devsh_v = __base.devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); - g2_query._clamp = BxDFClampMode::BCM_MAX; + g2_query._clamp = _clamp; return g2_query; } @@ -413,8 +363,8 @@ struct GGX::__call(__base.A, localV, u); } - template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template NBL_FUNC_REQUIRES(LightSample && RequiredInteraction && RequiredMicrofacetCache) + enable_if_t D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { scalar_type d = __base.template D(cache); quant_type dmq; @@ -422,81 +372,8 @@ struct GGX && surface_interactions::Anisotropic) - quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) - { - scalar_type dg1 = __base.DG1(query); - quant_type dmq; - dmq.microfacetMeasure = dg1; - dmq.projectedLightMeasure = dg1;// TODO: figure this out * _sample.getNdotL(BxDFClampMode::BCM_MAX); - return dmq; - } - - template && surface_interactions::Anisotropic) - scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) - { - return __base.template correlated_wo_numerator(query, _sample, interaction); - } - - template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) - { - return __base.template G2_over_G1(query, _sample, interaction, cache); - } - - base_type __base; -}; - -// partial for bsdf -template -NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) -struct GGX) > -{ - using scalar_type = T; - using base_type = impl::GGXCommon; - using quant_type = SDualMeasureQuant; - using vector2_type = vector; - using vector3_type = vector; - - using dg1_query_type = typename base_type::dg1_query_type; - using g2g1_query_type = typename base_type::g2g1_query_type; - using quant_query_type = impl::SGGXQuantQuery; - - template) - quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) - { - quant_query_type quant_query; - quant_query.VdotHLdotH = cache.getVdotHLdotH(); - quant_query.VdotH_etaLdotH = cache.getVdotH() + orientedEta * cache.getLdotH(); - return quant_query; - } - template && ReadableIsotropicMicrofacetCache) - dg1_query_type createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) - { - dg1_query_type dg1_query; - dg1_query.ndf = __base.template D(cache); - scalar_type clampedNdotV = interaction.getNdotV(BxDFClampMode::BCM_ABS); - dg1_query.G1_over_2NdotV = __base.G1_wo_numerator(clampedNdotV, interaction.getNdotV2()); - return dg1_query; - } - template && surface_interactions::Isotropic) - g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) - { - g2g1_query_type g2_query; - g2_query.devsh_l = __base.devsh_part(_sample.getNdotL2()); - g2_query.devsh_v = __base.devsh_part(interaction.getNdotV2()); - g2_query._clamp = BxDFClampMode::BCM_ABS; - return g2_query; - } - - vector generateH(const vector3_type localV, const vector2_type u) - { - return impl::GGXGenerateH::__call(__base.A, localV, u); - } - - template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) - quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template NBL_FUNC_REQUIRES(LightSample && RequiredInteraction && RequiredMicrofacetCache) + enable_if_t D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { scalar_type d = __base.template D(cache); quant_type dmq; @@ -512,103 +389,17 @@ struct GGX && surface_interactions::Isotropic) - quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + template NBL_FUNC_REQUIRES(LightSample && RequiredInteraction) + enable_if_t DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { scalar_type dg1 = __base.DG1(query); quant_type dmq; - dmq.microfacetMeasure = dg1; // note: microfacetMeasure/2NdotV - - const scalar_type VdotHLdotH = quant_query.getVdotHLdotH(); - const scalar_type VdotH_etaLdotH = quant_query.getVdotH_etaLdotH(); - const bool transmitted = reflect_refract==MTT_REFRACT || (reflect_refract!=MTT_REFLECT && VdotHLdotH < scalar_type(0.0)); - scalar_type NdotL_over_denominator = _sample.getNdotL(BxDFClampMode::BCM_ABS); - if (transmitted) - NdotL_over_denominator *= -scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); - dmq.projectedLightMeasure = dg1;// TODO: figure this out * NdotL_over_denominator; - return dmq; - } - - template && surface_interactions::Isotropic) - scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) - { - return __base.template correlated_wo_numerator(query, _sample, interaction); - } - - template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) - { - return __base.template G2_over_G1(query, _sample, interaction, cache); - } - - base_type __base; -}; - -template -NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) -struct GGX) > -{ - using scalar_type = T; - using base_type = impl::GGXCommon; - using quant_type = SDualMeasureQuant; - using vector2_type = vector; - using vector3_type = vector; - - using dg1_query_type = typename base_type::dg1_query_type; - using g2g1_query_type = typename base_type::g2g1_query_type; - using quant_query_type = impl::SGGXQuantQuery; - - template) - quant_query_type createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) - { - quant_query_type quant_query; - quant_query.VdotHLdotH = cache.getVdotHLdotH(); - quant_query.VdotH_etaLdotH = cache.getVdotH() + orientedEta * cache.getLdotH(); - return quant_query; - } - template && AnisotropicMicrofacetCache) - dg1_query_type createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) - { - dg1_query_type dg1_query; - dg1_query.ndf = __base.template D(cache); - scalar_type clampedNdotV = interaction.getNdotV(BxDFClampMode::BCM_ABS); - dg1_query.G1_over_2NdotV = __base.G1_wo_numerator(clampedNdotV, interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); - return dg1_query; - } - template && surface_interactions::Anisotropic) - g2g1_query_type createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) - { - g2g1_query_type g2_query; - g2_query.devsh_l = __base.devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); - g2_query.devsh_v = __base.devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); - g2_query._clamp = BxDFClampMode::BCM_ABS; - return g2_query; - } - - vector generateH(const vector3_type localV, const vector2_type u) - { - return impl::GGXGenerateH::__call(__base.A, localV, u); - } - - template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) - { - scalar_type d = __base.template D(cache); - quant_type dmq; - dmq.microfacetMeasure = d; // note: microfacetMeasure/2NdotV - - const scalar_type VdotHLdotH = quant_query.getVdotHLdotH(); - const scalar_type VdotH_etaLdotH = quant_query.getVdotH_etaLdotH(); - const bool transmitted = reflect_refract==MTT_REFRACT || (reflect_refract!=MTT_REFLECT && VdotHLdotH < scalar_type(0.0)); - scalar_type NdotL_over_denominator = _sample.getNdotL(BxDFClampMode::BCM_ABS); - if (transmitted) - NdotL_over_denominator *= -scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); - dmq.projectedLightMeasure = d * NdotL_over_denominator; + dmq.microfacetMeasure = dg1; + dmq.projectedLightMeasure = dg1;// TODO: figure this out * _sample.getNdotL(BxDFClampMode::BCM_MAX); return dmq; } - - template && surface_interactions::Anisotropic) - quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + template NBL_FUNC_REQUIRES(LightSample && RequiredInteraction) + enable_if_t DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { scalar_type dg1 = __base.DG1(query); quant_type dmq; @@ -624,13 +415,13 @@ struct GGX && surface_interactions::Anisotropic) + template && RequiredInteraction) scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { return __base.template correlated_wo_numerator(query, _sample, interaction); } - template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + template && RequiredInteraction && RequiredMicrofacetCache) scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { return __base.template G2_over_G1(query, _sample, interaction, cache); @@ -639,7 +430,6 @@ struct GGX From 3896231e38405e37f830252fed0aadae592cbc42 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 26 Sep 2025 14:18:51 +0700 Subject: [PATCH 34/38] put concepts back in for ndf impl --- include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 15 +++ .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 119 ++++++++++-------- include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 97 ++++++++------ 3 files changed, 139 insertions(+), 92 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl index 5e35cfd803..09265a2cf0 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -16,6 +16,21 @@ namespace bxdf namespace ndf { +namespace impl +{ +template +struct NDFQuantQuery +{ + using scalar_type = T; + + scalar_type getVdotHLdotH() NBL_CONST_MEMBER_FUNC { return VdotHLdotH; } + scalar_type getVdotH_etaLdotH() NBL_CONST_MEMBER_FUNC { return VdotH_etaLdotH; } + + scalar_type VdotHLdotH; + scalar_type VdotH_etaLdotH; +}; +} + namespace dummy_impl { using sample_t = SLightSample >; diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index c7274fdbba..ff8b695b6b 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -6,6 +6,7 @@ #include "nbl/builtin/hlsl/limits.hlsl" #include "nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl" +#include "nbl/builtin/hlsl/bxdf/ndf.hlsl" namespace nbl { @@ -16,6 +17,37 @@ namespace bxdf namespace ndf { +namespace beckmann_concepts +{ +#define NBL_CONCEPT_NAME DG1Query +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (query, T) +NBL_CONCEPT_BEGIN(1) +#define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getNdf()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) +); +#undef query +#include + +#define NBL_CONCEPT_NAME G2overG1Query +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (query, T) +NBL_CONCEPT_BEGIN(1) +#define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) +); +#undef query +#include +} + namespace impl { @@ -43,18 +75,6 @@ struct SBeckmannG2overG1Query scalar_type lambda_V; }; -template -struct SBeckmannQuantQuery -{ - using scalar_type = T; - - scalar_type getVdotHLdotH() NBL_CONST_MEMBER_FUNC { return VdotHLdotH; } - scalar_type getVdotH_etaLdotH() NBL_CONST_MEMBER_FUNC { return VdotH_etaLdotH; } - - scalar_type VdotHLdotH; - scalar_type VdotH_etaLdotH; -}; - template struct BeckmannCommon; @@ -63,8 +83,6 @@ NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) struct BeckmannCommon) > { using scalar_type = T; - using dg1_query_type = SBeckmannDG1Query; - using g2g1_query_type = SBeckmannG2overG1Query; template) scalar_type D(NBL_CONST_REF_ARG(MicrofacetCache) cache) @@ -75,22 +93,12 @@ struct BeckmannCommon * nom / denom; } - scalar_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query) + template) + static scalar_type DG1(NBL_CONST_REF_ARG(Query) query) { return query.getNdf() / (scalar_type(1.0) + query.getLambdaV()); } - //conversion between alpha and Phong exponent, Walter et.al. - static scalar_type phong_exp_to_alpha2(scalar_type _n) - { - return 2.0 / (_n + 2.0); - } - //+INF for a2==0.0 - static scalar_type alpha2_to_phong_exp(scalar_type a2) - { - return 2.0 / a2 - 2.0; - } - scalar_type C2(scalar_type NdotX2) { return NdotX2 / (a2 * (scalar_type(1.0) - NdotX2)); @@ -109,13 +117,14 @@ struct BeckmannCommon) + static scalar_type correlated(NBL_CONST_REF_ARG(Query) query) { return scalar_type(1.0) / (scalar_type(1.0) + query.getLambdaV() + query.getLambdaL()); } - template) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template && ReadableIsotropicMicrofacetCache) + static scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) { scalar_type onePlusLambda_V = scalar_type(1.0) + query.getLambdaV(); scalar_type lambda_L = query.getLambdaL(); @@ -131,8 +140,6 @@ NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) struct BeckmannCommon) > { using scalar_type = T; - using dg1_query_type = SBeckmannDG1Query; - using g2g1_query_type = SBeckmannG2overG1Query; template) scalar_type D(NBL_CONST_REF_ARG(MicrofacetCache) cache) @@ -143,24 +150,14 @@ struct BeckmannCommon * nom / denom; } - scalar_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query) + template) + static scalar_type DG1(NBL_CONST_REF_ARG(Query) query) { BeckmannCommon beckmann; scalar_type dg = beckmann.DG1(query); return dg; } - //conversion between alpha and Phong exponent, Walter et.al. - static scalar_type phong_exp_to_alpha2(scalar_type _n) - { - return 2.0 / (_n + 2.0); - } - //+INF for a2==0.0 - static scalar_type alpha2_to_phong_exp(scalar_type a2) - { - return 2.0 / a2 - 2.0; - } - scalar_type C2(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2) { return NdotX2 / (TdotX2 * ax2 + BdotX2 * ay2); @@ -179,13 +176,14 @@ struct BeckmannCommon) + static scalar_type correlated(NBL_CONST_REF_ARG(Query) query) { return scalar_type(1.0) / (scalar_type(1.0) + query.getLambdaV() + query.getLambdaL()); } - template) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template && AnisotropicMicrofacetCache) + static scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) { scalar_type onePlusLambda_V = scalar_type(1.0) + query.getLambdaV(); scalar_type lambda_L = query.getLambdaL(); @@ -285,9 +283,9 @@ struct Beckmann using vector2_type = vector; using vector3_type = vector; - using dg1_query_type = typename base_type::dg1_query_type; - using g2g1_query_type = typename base_type::g2g1_query_type; - using quant_query_type = impl::SBeckmannQuantQuery; + using dg1_query_type = impl::SBeckmannDG1Query; + using g2g1_query_type = impl::SBeckmannG2overG1Query; + using quant_query_type = impl::NDFQuantQuery; NBL_CONSTEXPR_STATIC_INLINE bool IsBSDF = reflect_refract != MTT_REFLECT; template @@ -363,31 +361,46 @@ struct Beckmann template NBL_FUNC_REQUIRES(LightSample && RequiredInteraction) enable_if_t DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - scalar_type dg1 = __base.DG1(query); + scalar_type dg1 = base_type::template DG1(query); return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); } template NBL_FUNC_REQUIRES(LightSample && RequiredInteraction) enable_if_t DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - scalar_type dg1 = __base.DG1(query); + scalar_type dg1 = base_type::template DG1(query); return createDualMeasureQuantity(dg1, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); } template && RequiredInteraction) scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - return __base.correlated(query); + return base_type::template correlated(query); } template && RequiredInteraction && RequiredMicrofacetCache) scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { - return __base.template G2_over_G1(query, cache); + return base_type::template G2_over_G1(query, cache); } base_type __base; }; +template +struct PhongExponent +{ + //conversion between alpha and Phong exponent, Walter et.al. + static T ToAlpha2(T _n) + { + return T(2.0) / (_n + T(2.0)); + } + //+INF for a2==0.0 + static T FromAlpha2(T a2) + { + return T(2.0) / a2 - T(2.0); + } +}; + } } } diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index b1bb0cca02..68b5ec2c27 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -6,6 +6,7 @@ #include "nbl/builtin/hlsl/limits.hlsl" #include "nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl" +#include "nbl/builtin/hlsl/bxdf/ndf.hlsl" namespace nbl { @@ -16,6 +17,38 @@ namespace bxdf namespace ndf { +namespace ggx_concepts +{ +#define NBL_CONCEPT_NAME DG1Query +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (query, T) +NBL_CONCEPT_BEGIN(1) +#define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getNdf()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getG1over2NdotV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) +); +#undef query +#include + +#define NBL_CONCEPT_NAME G2overG1Query +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (query, T) +NBL_CONCEPT_BEGIN(1) +#define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getDevshV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getDevshL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getClampMode()), ::nbl::hlsl::is_same_v, BxDFClampMode)) +); +#undef query +#include +} + namespace impl { @@ -45,18 +78,6 @@ struct SGGXG2XQuery BxDFClampMode _clamp; }; -template -struct SGGXQuantQuery -{ - using scalar_type = T; - - scalar_type getVdotHLdotH() NBL_CONST_MEMBER_FUNC { return VdotHLdotH; } - scalar_type getVdotH_etaLdotH() NBL_CONST_MEMBER_FUNC { return VdotH_etaLdotH; } - - scalar_type VdotHLdotH; - scalar_type VdotH_etaLdotH; -}; - template struct GGXCommon; @@ -65,8 +86,6 @@ NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) struct GGXCommon) > { using scalar_type = T; - using dg1_query_type = SGGXDG1Query; - using g2g1_query_type = SGGXG2XQuery; // trowbridge-reitz template) @@ -76,7 +95,8 @@ struct GGXCommon) > return a2 * numbers::inv_pi / (denom * denom); } - scalar_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query) + template) + static scalar_type DG1(NBL_CONST_REF_ARG(Query) query) { return scalar_type(0.5) * query.getNdf() * query.getG1over2NdotV(); } @@ -99,8 +119,8 @@ struct GGXCommon) > } // without numerator, numerator is 2 * NdotV * NdotL, we factor out 4 * NdotV * NdotL, hence 0.5 - template && surface_interactions::Isotropic) - scalar_type correlated_wo_numerator(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + template && LightSample && surface_interactions::Isotropic) + static scalar_type correlated_wo_numerator(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { BxDFClampMode _clamp = query.getClampMode(); assert(_clamp != BxDFClampMode::BCM_NONE); @@ -110,16 +130,16 @@ struct GGXCommon) > return scalar_type(0.5) / (Vterm + Lterm); } - template && surface_interactions::Isotropic) - scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + template && LightSample && surface_interactions::Isotropic) + static scalar_type correlated(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { BxDFClampMode _clamp = query.getClampMode(); assert(_clamp != BxDFClampMode::BCM_NONE); return scalar_type(4.0) * interaction.getNdotV(_clamp) * _sample.getNdotL(_clamp) * correlated_wo_numerator(query, _sample, interaction); } - template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template && LightSample && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) + static scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { BxDFClampMode _clamp = query.getClampMode(); assert(_clamp != BxDFClampMode::BCM_NONE); @@ -156,8 +176,6 @@ NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) struct GGXCommon) > { using scalar_type = T; - using dg1_query_type = SGGXDG1Query; - using g2g1_query_type = SGGXG2XQuery; template) scalar_type D(NBL_CONST_REF_ARG(MicrofacetCache) cache) @@ -179,7 +197,8 @@ struct GGXCommon) > return w2 * w2 * atab * numbers::inv_pi; } - scalar_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query) + template) + static scalar_type DG1(NBL_CONST_REF_ARG(Query) query) { GGXCommon ggx; return ggx.DG1(query); @@ -202,8 +221,8 @@ struct GGXCommon) > } // without numerator - template && surface_interactions::Anisotropic) - scalar_type correlated_wo_numerator(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + template && LightSample && surface_interactions::Anisotropic) + static scalar_type correlated_wo_numerator(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { BxDFClampMode _clamp = query.getClampMode(); assert(_clamp != BxDFClampMode::BCM_NONE); @@ -213,16 +232,16 @@ struct GGXCommon) > return scalar_type(0.5) / (Vterm + Lterm); } - template && surface_interactions::Anisotropic) - scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + template && LightSample && surface_interactions::Anisotropic) + static scalar_type correlated(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { BxDFClampMode _clamp = query.getClampMode(); assert(_clamp != BxDFClampMode::BCM_NONE); return scalar_type(4.0) * interaction.getNdotV(_clamp) * _sample.getNdotL(_clamp) * correlated_wo_numerator(query, _sample, interaction); } - template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template && LightSample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + static scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { BxDFClampMode _clamp = query.getClampMode(); assert(_clamp != BxDFClampMode::BCM_NONE); @@ -278,8 +297,8 @@ struct GGXGenerateH t2 = (1.0 - s)*sqrt(1.0 - t1*t1) + s*t2; //reprojection onto hemisphere - //TODO try it wothout the max(), not sure if -t1*t1-t2*t2>-1.0 - vector3_type H = t1*T1 + t2*T2 + sqrt(max(0.0, 1.0-t1*t1-t2*t2))*V; + //tested, seems -t1*t1-t2*t2>-1.0 + vector3_type H = t1*T1 + t2*T2 + sqrt(1.0-t1*t1-t2*t2)*V; //unstretch return nbl::hlsl::normalize(vector3_type(A.x*H.x, A.y*H.y, H.z)); } @@ -296,9 +315,9 @@ struct GGX using vector2_type = vector; using vector3_type = vector; - using dg1_query_type = typename base_type::dg1_query_type; - using g2g1_query_type = typename base_type::g2g1_query_type; - using quant_query_type = impl::SGGXQuantQuery; + using dg1_query_type = impl::SGGXDG1Query; + using g2g1_query_type = impl::SGGXG2XQuery; + using quant_query_type = impl::NDFQuantQuery; NBL_CONSTEXPR_STATIC_INLINE bool IsBSDF = reflect_refract != MTT_REFLECT; NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = IsBSDF ? BxDFClampMode::BCM_ABS : BxDFClampMode::BCM_MAX; @@ -392,7 +411,7 @@ struct GGX template NBL_FUNC_REQUIRES(LightSample && RequiredInteraction) enable_if_t DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - scalar_type dg1 = __base.DG1(query); + scalar_type dg1 = base_type::template DG1(query); quant_type dmq; dmq.microfacetMeasure = dg1; dmq.projectedLightMeasure = dg1;// TODO: figure this out * _sample.getNdotL(BxDFClampMode::BCM_MAX); @@ -401,7 +420,7 @@ struct GGX template NBL_FUNC_REQUIRES(LightSample && RequiredInteraction) enable_if_t DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - scalar_type dg1 = __base.DG1(query); + scalar_type dg1 = base_type::template DG1(query); quant_type dmq; dmq.microfacetMeasure = dg1; // note: microfacetMeasure/2NdotV @@ -418,13 +437,13 @@ struct GGX template && RequiredInteraction) scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - return __base.template correlated_wo_numerator(query, _sample, interaction); + return base_type::template correlated_wo_numerator(query, _sample, interaction); } template && RequiredInteraction && RequiredMicrofacetCache) scalar_type G2_over_G1(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { - return __base.template G2_over_G1(query, _sample, interaction, cache); + return base_type::template G2_over_G1(query, _sample, interaction, cache); } base_type __base; From 91b39d56ccdc5d92603260abbfded7c74efbf5a1 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 26 Sep 2025 14:50:14 +0700 Subject: [PATCH 35/38] ggx ndf determine clamp with template bool --- include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 53 ++++++---------------- 1 file changed, 13 insertions(+), 40 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index 68b5ec2c27..b60a96c193 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -43,7 +43,6 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getDevshV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getDevshL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getClampMode()), ::nbl::hlsl::is_same_v, BxDFClampMode)) ); #undef query #include @@ -71,22 +70,22 @@ struct SGGXG2XQuery scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } - BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } scalar_type devsh_v; scalar_type devsh_l; - BxDFClampMode _clamp; }; -template +template struct GGXCommon; -template +template NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) -struct GGXCommon) > +struct GGXCommon) > { using scalar_type = T; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = IsBSDF ? BxDFClampMode::BCM_ABS : BxDFClampMode::BCM_MAX; + // trowbridge-reitz template) scalar_type D(NBL_CONST_REF_ARG(MicrofacetCache) cache) @@ -122,9 +121,6 @@ struct GGXCommon) > template && LightSample && surface_interactions::Isotropic) static scalar_type correlated_wo_numerator(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - BxDFClampMode _clamp = query.getClampMode(); - assert(_clamp != BxDFClampMode::BCM_NONE); - scalar_type Vterm = _sample.getNdotL(_clamp) * query.getDevshV(); scalar_type Lterm = interaction.getNdotV(_clamp) * query.getDevshL(); return scalar_type(0.5) / (Vterm + Lterm); @@ -133,17 +129,12 @@ struct GGXCommon) > template && LightSample && surface_interactions::Isotropic) static scalar_type correlated(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - BxDFClampMode _clamp = query.getClampMode(); - assert(_clamp != BxDFClampMode::BCM_NONE); return scalar_type(4.0) * interaction.getNdotV(_clamp) * _sample.getNdotL(_clamp) * correlated_wo_numerator(query, _sample, interaction); } template && LightSample && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) static scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { - BxDFClampMode _clamp = query.getClampMode(); - assert(_clamp != BxDFClampMode::BCM_NONE); - scalar_type G2_over_G1; scalar_type NdotV = interaction.getNdotV(_clamp); scalar_type NdotL = _sample.getNdotL(_clamp); @@ -171,12 +162,14 @@ struct GGXCommon) > scalar_type one_minus_a2; }; -template +template NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) -struct GGXCommon) > +struct GGXCommon) > { using scalar_type = T; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = IsBSDF ? BxDFClampMode::BCM_ABS : BxDFClampMode::BCM_MAX; + template) scalar_type D(NBL_CONST_REF_ARG(MicrofacetCache) cache) { @@ -186,17 +179,6 @@ struct GGXCommon) > // TODO: potential idea for making GGX spin using covariance matrix of sorts: https://www.desmos.com/3d/weq2ginq9o - // burley - scalar_type D(scalar_type a2, scalar_type TdotH, scalar_type BdotH, scalar_type NdotH, scalar_type anisotropy) - { - scalar_type antiAniso = scalar_type(1.0) - anisotropy; - scalar_type atab = a2 * antiAniso; - scalar_type anisoTdotH = antiAniso * TdotH; - scalar_type anisoNdotH = antiAniso * NdotH; - scalar_type w2 = antiAniso/(BdotH * BdotH + anisoTdotH * anisoTdotH + anisoNdotH * anisoNdotH * a2); - return w2 * w2 * atab * numbers::inv_pi; - } - template) static scalar_type DG1(NBL_CONST_REF_ARG(Query) query) { @@ -224,9 +206,6 @@ struct GGXCommon) > template && LightSample && surface_interactions::Anisotropic) static scalar_type correlated_wo_numerator(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - BxDFClampMode _clamp = query.getClampMode(); - assert(_clamp != BxDFClampMode::BCM_NONE); - scalar_type Vterm = _sample.getNdotL(_clamp) * query.getDevshV(); scalar_type Lterm = interaction.getNdotV(_clamp) * query.getDevshL(); return scalar_type(0.5) / (Vterm + Lterm); @@ -235,17 +214,12 @@ struct GGXCommon) > template && LightSample && surface_interactions::Anisotropic) static scalar_type correlated(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - BxDFClampMode _clamp = query.getClampMode(); - assert(_clamp != BxDFClampMode::BCM_NONE); return scalar_type(4.0) * interaction.getNdotV(_clamp) * _sample.getNdotL(_clamp) * correlated_wo_numerator(query, _sample, interaction); } template && LightSample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) static scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { - BxDFClampMode _clamp = query.getClampMode(); - assert(_clamp != BxDFClampMode::BCM_NONE); - scalar_type G2_over_G1; scalar_type NdotV = interaction.getNdotV(_clamp); scalar_type NdotL = _sample.getNdotL(_clamp); @@ -309,8 +283,10 @@ struct GGXGenerateH template) struct GGX { + NBL_CONSTEXPR_STATIC_INLINE bool IsBSDF = reflect_refract != MTT_REFLECT; + using scalar_type = T; - using base_type = impl::GGXCommon; + using base_type = impl::GGXCommon; using quant_type = SDualMeasureQuant; using vector2_type = vector; using vector3_type = vector; @@ -319,8 +295,7 @@ struct GGX using g2g1_query_type = impl::SGGXG2XQuery; using quant_query_type = impl::NDFQuantQuery; - NBL_CONSTEXPR_STATIC_INLINE bool IsBSDF = reflect_refract != MTT_REFLECT; - NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = IsBSDF ? BxDFClampMode::BCM_ABS : BxDFClampMode::BCM_MAX; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = IsBSDF ? BxDFClampMode::BCM_ABS : BxDFClampMode::BCM_NONE; template NBL_CONSTEXPR_STATIC_INLINE bool RequiredInteraction = IsAnisotropic ? surface_interactions::Anisotropic : surface_interactions::Isotropic; template @@ -355,7 +330,6 @@ struct GGX g2g1_query_type g2_query; g2_query.devsh_l = __base.devsh_part(_sample.getNdotL2()); g2_query.devsh_v = __base.devsh_part(interaction.getNdotV2()); - g2_query._clamp = _clamp; return g2_query; } template NBL_FUNC_REQUIRES(RequiredInteraction && RequiredMicrofacetCache) @@ -373,7 +347,6 @@ struct GGX g2g1_query_type g2_query; g2_query.devsh_l = __base.devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); g2_query.devsh_v = __base.devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); - g2_query._clamp = _clamp; return g2_query; } From 2a3cda3ac10ecd490bad82d1777873d9ca8f3ad8 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 26 Sep 2025 15:20:42 +0700 Subject: [PATCH 36/38] moved A out of ndf base into generate base --- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 41 +++++++++++-------- include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 41 ++++++++++--------- .../hlsl/bxdf/reflection/beckmann.hlsl | 14 ++++--- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 16 ++++---- .../hlsl/bxdf/transmission/beckmann.hlsl | 14 ++++--- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 16 ++++---- 6 files changed, 79 insertions(+), 63 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index ff8b695b6b..c3fed16d51 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -203,10 +203,10 @@ struct BeckmannGenerateH using vector2_type = vector; using vector3_type = vector; - static vector3_type __call(const vector2_type A, const vector3_type localV, const vector2_type u) + vector3_type __call(const vector3_type localV, const vector2_type u) { //stretch - vector3_type V = nbl::hlsl::normalize(vector3_type(A.x * localV.x, A.y * localV.y, localV.z)); + vector3_type V = nbl::hlsl::normalize(vector3_type(ax * localV.x, ay * localV.y, localV.z)); vector2_type slope; if (V.z > 0.9999)//V.z=NdotV=cosTheta in tangent space @@ -266,19 +266,22 @@ struct BeckmannGenerateH slope.x = tmp; //unstretch - slope = vector2_type(A.x,A.y)*slope; + slope = vector2_type(ax, ay) * slope; return nbl::hlsl::normalize(vector3_type(-slope, 1.0)); } + + scalar_type ax; + scalar_type ay; }; } -template) +template) struct Beckmann { using scalar_type = T; - using base_type = impl::BeckmannCommon; + using base_type = impl::BeckmannCommon; using quant_type = SDualMeasureQuant; using vector2_type = vector; using vector3_type = vector; @@ -287,6 +290,7 @@ struct Beckmann using g2g1_query_type = impl::SBeckmannG2overG1Query; using quant_query_type = impl::NDFQuantQuery; + NBL_CONSTEXPR_STATIC_INLINE bool IsAnisotropic = _IsAnisotropic; NBL_CONSTEXPR_STATIC_INLINE bool IsBSDF = reflect_refract != MTT_REFLECT; template NBL_CONSTEXPR_STATIC_INLINE bool RequiredInteraction = IsAnisotropic ? surface_interactions::Anisotropic : surface_interactions::Isotropic; @@ -311,50 +315,50 @@ struct Beckmann enable_if_t createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { dg1_query_type dg1_query; - dg1_query.ndf = __base.template D(cache); - dg1_query.lambda_V = __base.LambdaC2(interaction.getNdotV2()); + dg1_query.ndf = __ndf_base.template D(cache); + dg1_query.lambda_V = __ndf_base.LambdaC2(interaction.getNdotV2()); return dg1_query; } template NBL_FUNC_REQUIRES(LightSample && RequiredInteraction) enable_if_t createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { g2g1_query_type g2_query; - g2_query.lambda_L = __base.LambdaC2(_sample.getNdotL2()); - g2_query.lambda_V = __base.LambdaC2(interaction.getNdotV2()); + g2_query.lambda_L = __ndf_base.LambdaC2(_sample.getNdotL2()); + g2_query.lambda_V = __ndf_base.LambdaC2(interaction.getNdotV2()); return g2_query; } template NBL_FUNC_REQUIRES(RequiredInteraction && RequiredMicrofacetCache) enable_if_t createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { dg1_query_type dg1_query; - dg1_query.ndf = __base.template D(cache); - dg1_query.lambda_V = __base.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + dg1_query.ndf = __ndf_base.template D(cache); + dg1_query.lambda_V = __ndf_base.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); return dg1_query; } template NBL_FUNC_REQUIRES(LightSample && RequiredInteraction) enable_if_t createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { g2g1_query_type g2_query; - g2_query.lambda_L = __base.LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); - g2_query.lambda_V = __base.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + g2_query.lambda_L = __ndf_base.LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); + g2_query.lambda_V = __ndf_base.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); return g2_query; } - vector generateH(const vector3_type localV, const vector2_type u) + vector3_type generateH(const vector3_type localV, const vector2_type u) { - return impl::BeckmannGenerateH::__call(__base.A, localV, u); + return __generate_base.__call(localV, u); } template NBL_FUNC_REQUIRES(LightSample && RequiredInteraction && RequiredMicrofacetCache) enable_if_t D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { - scalar_type d = __base.template D(cache); + scalar_type d = __ndf_base.template D(cache); return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX)); } template NBL_FUNC_REQUIRES(LightSample && RequiredInteraction && RequiredMicrofacetCache) enable_if_t D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { - scalar_type d = __base.template D(cache); + scalar_type d = __ndf_base.template D(cache); return createDualMeasureQuantity(d, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH()); } @@ -383,7 +387,8 @@ struct Beckmann return base_type::template G2_over_G1(query, cache); } - base_type __base; + base_type __ndf_base; + impl::BeckmannGenerateH __generate_base; }; template diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index b60a96c193..4f2cff504e 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -157,7 +157,6 @@ struct GGXCommon A; // TODO: remove? scalar_type a2; scalar_type one_minus_a2; }; @@ -242,7 +241,6 @@ struct GGXCommon A; scalar_type ax2; scalar_type ay2; scalar_type a2; @@ -255,9 +253,9 @@ struct GGXGenerateH using vector2_type = vector; using vector3_type = vector; - static vector3_type __call(const vector2_type A, const vector3_type localV, const vector2_type u) + vector3_type __call(const vector3_type localV, const vector2_type u) { - vector3_type V = nbl::hlsl::normalize(vector3_type(A.x*localV.x, A.y*localV.y, localV.z));//stretch view vector so that we're sampling as if roughness=1.0 + vector3_type V = nbl::hlsl::normalize(vector3_type(ax * localV.x, ay * localV.y, localV.z));//stretch view vector so that we're sampling as if roughness=1.0 scalar_type lensq = V.x*V.x + V.y*V.y; vector3_type T1 = lensq > 0.0 ? vector3_type(-V.y, V.x, 0.0) * rsqrt(lensq) : vector3_type(1.0,0.0,0.0); @@ -274,15 +272,19 @@ struct GGXGenerateH //tested, seems -t1*t1-t2*t2>-1.0 vector3_type H = t1*T1 + t2*T2 + sqrt(1.0-t1*t1-t2*t2)*V; //unstretch - return nbl::hlsl::normalize(vector3_type(A.x*H.x, A.y*H.y, H.z)); + return nbl::hlsl::normalize(vector3_type(ax*H.x, ay*H.y, H.z)); } + + scalar_type ax; + scalar_type ay; }; } -template) +template) struct GGX { + NBL_CONSTEXPR_STATIC_INLINE bool IsAnisotropic = _IsAnisotropic; NBL_CONSTEXPR_STATIC_INLINE bool IsBSDF = reflect_refract != MTT_REFLECT; using scalar_type = T; @@ -319,46 +321,46 @@ struct GGX enable_if_t createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { dg1_query_type dg1_query; - dg1_query.ndf = __base.template D(cache); + dg1_query.ndf = __ndf_base.template D(cache); scalar_type clampedNdotV = interaction.getNdotV(_clamp); - dg1_query.G1_over_2NdotV = __base.G1_wo_numerator(clampedNdotV, interaction.getNdotV2()); + dg1_query.G1_over_2NdotV = __ndf_base.G1_wo_numerator(clampedNdotV, interaction.getNdotV2()); return dg1_query; } template NBL_FUNC_REQUIRES(LightSample && RequiredInteraction) enable_if_t createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { g2g1_query_type g2_query; - g2_query.devsh_l = __base.devsh_part(_sample.getNdotL2()); - g2_query.devsh_v = __base.devsh_part(interaction.getNdotV2()); + g2_query.devsh_l = __ndf_base.devsh_part(_sample.getNdotL2()); + g2_query.devsh_v = __ndf_base.devsh_part(interaction.getNdotV2()); return g2_query; } template NBL_FUNC_REQUIRES(RequiredInteraction && RequiredMicrofacetCache) enable_if_t createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { dg1_query_type dg1_query; - dg1_query.ndf = __base.template D(cache); + dg1_query.ndf = __ndf_base.template D(cache); scalar_type clampedNdotV = interaction.getNdotV(_clamp); - dg1_query.G1_over_2NdotV = __base.G1_wo_numerator(clampedNdotV, interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + dg1_query.G1_over_2NdotV = __ndf_base.G1_wo_numerator(clampedNdotV, interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); return dg1_query; } template NBL_FUNC_REQUIRES(LightSample && RequiredInteraction) enable_if_t createG2G1Query(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { g2g1_query_type g2_query; - g2_query.devsh_l = __base.devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); - g2_query.devsh_v = __base.devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + g2_query.devsh_l = __ndf_base.devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); + g2_query.devsh_v = __ndf_base.devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); return g2_query; } - vector generateH(const vector3_type localV, const vector2_type u) + vector3_type generateH(const vector3_type localV, const vector2_type u) { - return impl::GGXGenerateH::__call(__base.A, localV, u); + return __generate_base.__call(localV, u); } template NBL_FUNC_REQUIRES(LightSample && RequiredInteraction && RequiredMicrofacetCache) enable_if_t D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { - scalar_type d = __base.template D(cache); + scalar_type d = __ndf_base.template D(cache); quant_type dmq; dmq.microfacetMeasure = d; dmq.projectedLightMeasure = d * _sample.getNdotL(BxDFClampMode::BCM_MAX); @@ -367,7 +369,7 @@ struct GGX template NBL_FUNC_REQUIRES(LightSample && RequiredInteraction && RequiredMicrofacetCache) enable_if_t D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { - scalar_type d = __base.template D(cache); + scalar_type d = __ndf_base.template D(cache); quant_type dmq; dmq.microfacetMeasure = d; // note: microfacetMeasure/2NdotV @@ -419,7 +421,8 @@ struct GGX return base_type::template G2_over_G1(query, _sample, interaction, cache); } - base_type __base; + base_type __ndf_base; + impl::GGXGenerateH __generate_base; }; namespace impl diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 22018b0fff..05d617d8ca 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -39,8 +39,9 @@ struct SBeckmannIsotropic static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) eta, NBL_CONST_REF_ARG(spectral_type) etak) { this_t retval; - retval.__base.ndf.__base.A = vector2_type(A, A); - retval.__base.ndf.__base.a2 = A*A; + retval.__base.ndf.__ndf_base.a2 = A*A; + retval.__base.ndf.__generate_base.ax = A; + retval.__base.ndf.__generate_base.ay = A; retval.__base.fresnel.eta = eta; retval.__base.fresnel.etak2 = etak * etak; retval.__base.fresnel.etaLen2 = eta * eta + retval.__base.fresnel.etak2; @@ -114,10 +115,11 @@ struct SBeckmannAnisotropic static this_t create(scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) eta, NBL_CONST_REF_ARG(spectral_type) etak) { this_t retval; - retval.__base.ndf.__base.A = vector2_type(ax, ay); - retval.__base.ndf.__base.ax2 = ax*ax; - retval.__base.ndf.__base.ay2 = ay*ay; - retval.__base.ndf.__base.a2 = ax*ay; + retval.__base.ndf.__ndf_base.ax2 = ax*ax; + retval.__base.ndf.__ndf_base.ay2 = ay*ay; + retval.__base.ndf.__ndf_base.a2 = ax*ay; + retval.__base.ndf.__generate_base.ax = ax; + retval.__base.ndf.__generate_base.ay = ay; retval.__base.fresnel.eta = eta; retval.__base.fresnel.etak2 = etak * etak; retval.__base.fresnel.etaLen2 = eta * eta + retval.__base.fresnel.etak2; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index d063acdba2..0bed5c9e01 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -39,9 +39,10 @@ struct SGGXIsotropic static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) eta, NBL_CONST_REF_ARG(spectral_type) etak) { this_t retval; - retval.__base.ndf.__base.A = vector2_type(A, A); - retval.__base.ndf.__base.a2 = A*A; - retval.__base.ndf.__base.one_minus_a2 = scalar_type(1.0) - A*A; + retval.__base.ndf.__ndf_base.a2 = A*A; + retval.__base.ndf.__ndf_base.one_minus_a2 = scalar_type(1.0) - A*A; + retval.__base.ndf.__generate_base.ax = A; + retval.__base.ndf.__generate_base.ay = A; retval.__base.fresnel.eta = eta; retval.__base.fresnel.etak2 = etak * etak; retval.__base.fresnel.etaLen2 = eta * eta + retval.__base.fresnel.etak2; @@ -115,10 +116,11 @@ struct SGGXAnisotropic static this_t create(scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) eta, NBL_CONST_REF_ARG(spectral_type) etak) { this_t retval; - retval.__base.ndf.__base.A = vector2_type(ax, ay); - retval.__base.ndf.__base.ax2 = ax*ax; - retval.__base.ndf.__base.ay2 = ay*ay; - retval.__base.ndf.__base.a2 = ax*ay; + retval.__base.ndf.__ndf_base.ax2 = ax*ax; + retval.__base.ndf.__ndf_base.ay2 = ay*ay; + retval.__base.ndf.__ndf_base.a2 = ax*ay; + retval.__base.ndf.__generate_base.ax = ax; + retval.__base.ndf.__generate_base.ay = ay; retval.__base.fresnel.eta = eta; retval.__base.fresnel.etak2 = etak * etak; retval.__base.fresnel.etaLen2 = eta * eta + retval.__base.fresnel.etak2; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 7b0565423b..db3be603ff 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -39,8 +39,9 @@ struct SBeckmannDielectricIsotropic static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type A, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) { this_t retval; - retval.__base.ndf.__base.A = vector2_type(A, A); - retval.__base.ndf.__base.a2 = A*A; + retval.__base.ndf.__ndf_base.a2 = A*A; + retval.__base.ndf.__generate_base.ax = A; + retval.__base.ndf.__generate_base.ay = A; retval.__base.fresnel.orientedEta = orientedEta; retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; retval.__base.luminosityContributionHint = luminosityContributionHint; @@ -120,10 +121,11 @@ struct SBeckmannDielectricAnisotropic static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) { this_t retval; - retval.__base.ndf.__base.A = vector2_type(ax, ay); - retval.__base.ndf.__base.ax2 = ax*ax; - retval.__base.ndf.__base.ay2 = ay*ay; - retval.__base.ndf.__base.a2 = ax*ay; + retval.__base.ndf.__ndf_base.ax2 = ax*ax; + retval.__base.ndf.__ndf_base.ay2 = ay*ay; + retval.__base.ndf.__ndf_base.a2 = ax*ay; + retval.__base.ndf.__generate_base.ax = ax; + retval.__base.ndf.__generate_base.ay = ay; retval.__base.fresnel.orientedEta = orientedEta; retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; retval.__base.luminosityContributionHint = luminosityContributionHint; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index e0750a6c98..74865e7619 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -39,9 +39,10 @@ struct SGGXDielectricIsotropic static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type A, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) { this_t retval; - retval.__base.ndf.__base.A = vector2_type(A, A); - retval.__base.ndf.__base.a2 = A*A; - retval.__base.ndf.__base.one_minus_a2 = scalar_type(1.0) - A*A; + retval.__base.ndf.__ndf_base.a2 = A*A; + retval.__base.ndf.__ndf_base.one_minus_a2 = scalar_type(1.0) - A*A; + retval.__base.ndf.__generate_base.ax = A; + retval.__base.ndf.__generate_base.ay = A; retval.__base.fresnel.orientedEta = orientedEta; retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; retval.__base.luminosityContributionHint = luminosityContributionHint; @@ -121,10 +122,11 @@ struct SGGXDielectricAnisotropic static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) { this_t retval; - retval.__base.ndf.__base.A = vector2_type(ax, ay); - retval.__base.ndf.__base.ax2 = ax*ax; - retval.__base.ndf.__base.ay2 = ay*ay; - retval.__base.ndf.__base.a2 = ax*ay; + retval.__base.ndf.__ndf_base.ax2 = ax*ax; + retval.__base.ndf.__ndf_base.ay2 = ay*ay; + retval.__base.ndf.__ndf_base.a2 = ax*ay; + retval.__base.ndf.__generate_base.ax = ax; + retval.__base.ndf.__generate_base.ay = ay; retval.__base.fresnel.orientedEta = orientedEta; retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; retval.__base.luminosityContributionHint = luminosityContributionHint; From c9f93661936db1f16fb4a5780be80f673989426e Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 26 Sep 2025 16:29:11 +0700 Subject: [PATCH 37/38] added create methods to ndfs, cook torrance base; slight changes to cook torrance template --- .../builtin/hlsl/bxdf/cook_torrance_base.hlsl | 372 ++++-------------- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 22 ++ include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 23 ++ .../hlsl/bxdf/reflection/beckmann.hlsl | 4 +- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 4 +- .../hlsl/bxdf/transmission/beckmann.hlsl | 4 +- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 4 +- 7 files changed, 138 insertions(+), 295 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl index c957c5b79d..5f640b5b2f 100644 --- a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl @@ -67,23 +67,76 @@ struct quant_query_helper return ndf.template createQuantQuery(cache, dummy); } }; + +template +struct CookTorranceParams; + +template +struct CookTorranceParams +{ + using scalar_type = typename F::scalar_type; + using spectral_type = Spectral; + + scalar_type A; + F fresnel; + spectral_type luminosityContributionHint; // if not BSDF, ignore +}; + +template +struct CookTorranceParams +{ + using scalar_type = typename F::scalar_type; + using spectral_type = Spectral; + + scalar_type ax; + scalar_type ay; + F fresnel; + spectral_type luminosityContributionHint; +}; } // N (NDF), F (fresnel) -template +template struct SCookTorrance { MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); + using this_t = SCookTorrance; using quant_type = typename N::quant_type; + using ndf_type = N; + using fresnel_type = F; + + NBL_CONSTEXPR_STATIC_INLINE bool IsAnisotropic = ndf_type::IsAnisotropic; + NBL_CONSTEXPR_STATIC_INLINE bool IsBSDF = ndf_type::IsBSDF; + + using create_params_type = impl::CookTorranceParams; + + template > + enable_if_t create(NBL_CONST_REF_ARG(create_params_type) params) + { + this_t retval; + retval.ndf = ndf_type::create(params.A); + retval.fresnel = params.fresnel; + retval.luminosityContributionHint = luminosityContributionHint; + return retval; + } + template > + enable_if_t create(NBL_CONST_REF_ARG(create_params_type) params) + { + this_t retval; + retval.ndf = ndf_type::create(params.ax, params.ay); + retval.fresnel = params.fresnel; + retval.luminosityContributionHint = luminosityContributionHint; + return retval; + } template spectral_type __eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { if (IsBSDF || (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min)) { - using quant_query_type = typename N::quant_query_type; - using g2g1_query_type = typename N::g2g1_query_type; + using quant_query_type = typename ndf_type::quant_query_type; + using g2g1_query_type = typename ndf_type::g2g1_query_type; scalar_type dummy; quant_query_type qq = ndf.template createQuantQuery(cache, dummy); @@ -96,14 +149,15 @@ struct SCookTorrance DG *= ndf.template correlated(gq, _sample, interaction); } NBL_IF_CONSTEXPR(IsBSDF) - return impl::__implicit_promote::__call(fresnel(hlsl::abs(cache.getVdotH()))) * DG; + return impl::__implicit_promote::__call(fresnel(hlsl::abs(cache.getVdotH()))) * DG; else - return impl::__implicit_promote::__call(fresnel(cache.getVdotH())) * DG; + return impl::__implicit_promote::__call(fresnel(cache.getVdotH())) * DG; } else return hlsl::promote(0.0); } - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + template > + enable_if_t eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { return __eval(_sample, interaction, cache); } @@ -159,16 +213,32 @@ struct SCookTorrance return sample_type::createFromTangentSpace(localL, interaction.getFromTangentSpace()); } + template NBL_FUNC_REQUIRES(is_same_v) + enable_if_t generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const T u, NBL_REF_ARG(anisocache_type) cache) + { + anisocache_type aniso_cache; + sample_type s = generate(anisotropic_interaction_type::create(interaction), u, aniso_cache); + cache = aniso_cache.iso_cache; + return s; + } + template NBL_FUNC_REQUIRES(is_same_v) + enable_if_t generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const T u, NBL_REF_ARG(anisocache_type) cache) + { + anisocache_type aniso_cache; + sample_type s = generate(anisotropic_interaction_type::create(interaction), u, aniso_cache); + cache = aniso_cache.iso_cache; + 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) { - using quant_query_type = typename N::quant_query_type; - using dg1_query_type = typename N::dg1_query_type; + using quant_query_type = typename ndf_type::quant_query_type; + using dg1_query_type = typename ndf_type::dg1_query_type; dg1_query_type dq = ndf.template createDG1Query(interaction, cache); - quant_query_type qq = impl::quant_query_helper::template __call(ndf, fresnel, cache); + quant_query_type qq = impl::quant_query_helper::template __call(ndf, fresnel, cache); quant_type DG1 = ndf.template DG1(dq, qq, _sample, interaction); NBL_IF_CONSTEXPR(IsBSDF) @@ -181,7 +251,8 @@ struct SCookTorrance return DG1.projectedLightMeasure; } } - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + template > + enable_if_t pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { if (IsBSDF || (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min)) return __pdf(_sample, interaction, cache); @@ -213,7 +284,8 @@ struct SCookTorrance return quotient_pdf_type::create(quo, _pdf); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + template > + enable_if_t quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { return __quotient_and_pdf(_sample, interaction, cache); } @@ -222,285 +294,11 @@ struct SCookTorrance return __quotient_and_pdf(_sample, interaction, cache); } - N ndf; - F fresnel; + ndf_type ndf; + fresnel_type fresnel; spectral_type luminosityContributionHint; }; -// template -// NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration && ndf::NDF && fresnel::Fresnel) -// struct SCookTorrance && ndf::NDF && fresnel::Fresnel) > -// { -// MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); - -// using quant_type = typename N::quant_type; - -// spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) -// { -// if (interaction.getNdotV() > numeric_limits::min) -// { -// using quant_query_type = typename N::quant_query_type; -// using g2g1_query_type = typename N::g2g1_query_type; - -// scalar_type dummy; -// quant_query_type qq = ndf.template createQuantQuery(cache, dummy); -// g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); - -// quant_type D = ndf.template D(qq, _sample, interaction, cache); -// scalar_type DG = D.projectedLightMeasure; -// if (any >(ndf.__base.A > hlsl::promote(numeric_limits::min))) -// { -// DG *= ndf.template correlated(gq, _sample, interaction); -// } -// return fresnel(cache.getVdotH()) * DG; -// } -// else -// return hlsl::promote(0.0); -// } -// spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) -// { -// if (interaction.getNdotV() > numeric_limits::min) -// { -// using quant_query_type = typename N::quant_query_type; -// using g2g1_query_type = typename N::g2g1_query_type; - -// scalar_type dummy; -// quant_query_type qq = ndf.template createQuantQuery(cache, dummy); -// g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); - -// quant_type D = ndf.template D(qq, _sample, interaction, cache); -// scalar_type DG = D.projectedLightMeasure; -// if (any >(ndf.__base.A > hlsl::promote(numeric_limits::min))) -// { -// DG *= ndf.template correlated(gq, _sample, interaction); -// } -// return fresnel(cache.getVdotH()) * DG; -// } -// else -// return hlsl::promote(0.0); -// } - -// sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache) -// { -// anisocache_type anisocache; -// sample_type s = generate(anisotropic_interaction_type::create(interaction), u, anisocache); -// cache = anisocache.iso_cache; -// return s; -// } -// sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache) -// { -// const vector3_type localV = interaction.getTangentSpaceV(); -// const vector3_type H = ndf.generateH(localV, u); - -// cache = anisocache_type::createForReflection(localV, H); -// ray_dir_info_type localL; -// bxdf::Reflect r = bxdf::Reflect::create(localV, H); -// localL = localL.reflect(r); - -// return sample_type::createFromTangentSpace(localL, interaction.getFromTangentSpace()); -// } - -// scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) -// { -// using quant_query_type = typename N::quant_query_type; -// using dg1_query_type = typename N::dg1_query_type; - -// scalar_type dummy; -// quant_query_type qq = ndf.template createQuantQuery(cache, dummy); -// dg1_query_type dq = ndf.template createDG1Query(interaction, cache); -// quant_type DG1 = ndf.template DG1(dq, qq, _sample, interaction); -// return DG1.projectedLightMeasure; -// } -// scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) -// { -// using quant_query_type = typename N::quant_query_type; -// using dg1_query_type = typename N::dg1_query_type; - -// scalar_type dummy; -// quant_query_type qq = ndf.template createQuantQuery(cache, dummy); -// dg1_query_type dq = ndf.template createDG1Query(interaction, cache); -// quant_type DG1 = ndf.template DG1(dq, qq, _sample, interaction); -// return DG1.projectedLightMeasure; -// } - -// quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) -// { -// scalar_type _pdf = pdf(_sample, interaction, cache); - -// spectral_type quo = hlsl::promote(0.0); -// if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) -// { -// using g2g1_query_type = typename N::g2g1_query_type; - -// g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); -// scalar_type G2_over_G1 = ndf.template G2_over_G1(gq, _sample, interaction, cache); -// const spectral_type reflectance = fresnel(cache.getVdotH()); -// quo = reflectance * G2_over_G1; -// } - -// return quotient_pdf_type::create(quo, _pdf); -// } -// quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) -// { -// scalar_type _pdf = pdf(_sample, interaction, cache); - -// spectral_type quo = hlsl::promote(0.0); -// if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) -// { -// using g2g1_query_type = typename N::g2g1_query_type; - -// g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); -// scalar_type G2_over_G1 = ndf.template G2_over_G1(gq, _sample, interaction, cache); -// const spectral_type reflectance = fresnel(cache.getVdotH()); -// quo = reflectance * G2_over_G1; -// } - -// return quotient_pdf_type::create(quo, _pdf); -// } - -// N ndf; -// F fresnel; -// }; - -// template -// NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration && ndf::NDF && fresnel::Fresnel) -// struct SCookTorrance && ndf::NDF && fresnel::Fresnel) > -// { -// MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); - -// using quant_type = typename N::quant_type; - -// spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) -// { -// using quant_query_type = typename N::quant_query_type; -// using g2g1_query_type = typename N::g2g1_query_type; - -// fresnel::OrientedEtas orientedEta = fresnel.orientedEta; -// quant_query_type qq = ndf.template createQuantQuery(cache, orientedEta.value[0]); -// g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); - -// quant_type D = ndf.template D(qq, _sample, interaction, cache); -// scalar_type DG = D.projectedLightMeasure; -// if (any >(ndf.__base.A > hlsl::promote(numeric_limits::min))) -// { -// DG *= ndf.template correlated(gq, _sample, interaction); -// } -// return hlsl::promote(fresnel(hlsl::abs(cache.getVdotH()))[0]) * DG; -// } -// spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) -// { -// using quant_query_type = typename N::quant_query_type; -// using g2g1_query_type = typename N::g2g1_query_type; - -// fresnel::OrientedEtas orientedEta = fresnel.orientedEta; -// quant_query_type qq = ndf.template createQuantQuery(cache, orientedEta.value[0]); -// g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); - -// quant_type D = ndf.template D(qq, _sample, interaction, cache); -// scalar_type DG = D.projectedLightMeasure; -// if (any >(ndf.__base.A > hlsl::promote(numeric_limits::min))) -// { -// DG *= ndf.template correlated(gq, _sample, interaction); -// } -// return hlsl::promote(fresnel(hlsl::abs(cache.getVdotH()))[0]) * DG; -// } - -// sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(isocache_type) cache, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) -// { -// anisocache_type anisocache; -// sample_type s = generate(anisotropic_interaction_type::create(interaction), u, anisocache, luminosityContributionHint); -// cache = anisocache.iso_cache; -// return s; -// } -// sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(anisocache_type) cache, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) -// { -// const vector3_type localV = interaction.getTangentSpaceV(); - -// fresnel::OrientedEtas orientedEta = fresnel.orientedEta; -// fresnel::OrientedEtaRcps rcpEta = orientedEta.getReciprocals(); - -// const vector3_type upperHemisphereV = hlsl::mix(localV, -localV, interaction.getNdotV() < scalar_type(0.0)); -// const vector3_type H = ndf.generateH(upperHemisphereV, u.xy); - -// const scalar_type reflectance = fresnel(hlsl::abs(hlsl::dot(localV, H)))[0]; -// const scalar_type reflectionProb = hlsl::dot(hlsl::promote(reflectance), luminosityContributionHint); - -// scalar_type rcpChoiceProb; -// scalar_type z = u.z; -// bool transmitted = math::partitionRandVariable(reflectionProb, z, rcpChoiceProb); - -// cache = anisocache_type::createForReflection(localV, H); - -// Refract r = Refract::create(localV, H); -// cache.iso_cache.LdotH = hlsl::mix(cache.getVdotH(), r.getNdotT(rcpEta.value2[0]), transmitted); -// ray_dir_info_type localL; -// bxdf::ReflectRefract rr; -// rr.refract = r; -// localL = localL.reflectRefract(rr, transmitted, rcpEta.value[0]); - -// // fail if samples have invalid paths -// if ((!transmitted && hlsl::sign(localL.getDirection().z) != hlsl::sign(localV.z)) || (transmitted && hlsl::sign(localL.getDirection().z) == hlsl::sign(localV.z))) -// { -// localL.direction = vector3_type(0,0,0); // should check if sample direction is invalid -// } - -// return sample_type::createFromTangentSpace(localL, interaction.getFromTangentSpace()); -// } - -// scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) -// { -// using quant_query_type = typename N::quant_query_type; -// using dg1_query_type = typename N::dg1_query_type; - -// fresnel::OrientedEtas orientedEta = fresnel.orientedEta; -// quant_query_type qq = ndf.template createQuantQuery(cache, orientedEta.value[0]); -// dg1_query_type dq = ndf.template createDG1Query(interaction, cache); -// quant_type DG1 = ndf.template DG1(dq, qq, _sample, interaction); - -// const scalar_type reflectance = fresnel(hlsl::abs(cache.getVdotH()))[0]; -// return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * DG1.projectedLightMeasure; -// } -// scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) -// { -// using quant_query_type = typename N::quant_query_type; -// using dg1_query_type = typename N::dg1_query_type; - -// fresnel::OrientedEtas orientedEta = fresnel.orientedEta; -// quant_query_type qq = ndf.template createQuantQuery(cache, orientedEta.value[0]); -// dg1_query_type dq = ndf.template createDG1Query(interaction, cache); -// quant_type DG1 = ndf.template DG1(dq, qq, _sample, interaction); - -// const scalar_type reflectance = fresnel(hlsl::abs(cache.getVdotH()))[0]; -// return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * DG1.projectedLightMeasure; -// } - -// quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) -// { -// scalar_type _pdf = pdf(_sample, interaction, cache); - -// using g2g1_query_type = typename N::g2g1_query_type; - -// g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); -// scalar_type quo = ndf.template G2_over_G1(gq, _sample, interaction, cache); - -// return quotient_pdf_type::create(quo, _pdf); -// } -// quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) -// { -// scalar_type _pdf = pdf(_sample, interaction, cache); - -// using g2g1_query_type = typename N::g2g1_query_type; - -// g2g1_query_type gq = ndf.template createG2G1Query(_sample, interaction); -// scalar_type quo = ndf.template G2_over_G1(gq, _sample, interaction, cache); - -// return quotient_pdf_type::create(quo, _pdf); -// } - -// N ndf; -// F fresnel; -// }; - } } } diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index c3fed16d51..83f26e4c25 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -280,6 +280,7 @@ struct BeckmannGenerateH template) struct Beckmann { + using this_t = Beckmann; using scalar_type = T; using base_type = impl::BeckmannCommon; using quant_type = SDualMeasureQuant; @@ -297,6 +298,27 @@ struct Beckmann template NBL_CONSTEXPR_STATIC_INLINE bool RequiredMicrofacetCache = IsAnisotropic ? AnisotropicMicrofacetCache : ReadableIsotropicMicrofacetCache; + template > + enable_if_t create(scalar_type A) + { + this_t retval; + retval.__ndf_base.a2 = A*A; + retval.__generate_base.ax = A; + retval.__generate_base.ay = A; + return retval; + } + template > + enable_if_t create(scalar_type ax, scalar_type ay) + { + this_t retval; + retval.__ndf_base.ax2 = ax*ax; + retval.__ndf_base.ay2 = ay*ay; + retval.__ndf_base.a2 = ax*ay; + retval.__generate_base.ax = ax; + retval.__generate_base.ay = ay; + return retval; + } + template NBL_FUNC_REQUIRES(RequiredMicrofacetCache) enable_if_t createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) { diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index 4f2cff504e..bd58f4203f 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -287,6 +287,7 @@ struct GGX NBL_CONSTEXPR_STATIC_INLINE bool IsAnisotropic = _IsAnisotropic; NBL_CONSTEXPR_STATIC_INLINE bool IsBSDF = reflect_refract != MTT_REFLECT; + using this_t = GGX; using scalar_type = T; using base_type = impl::GGXCommon; using quant_type = SDualMeasureQuant; @@ -303,6 +304,28 @@ struct GGX template NBL_CONSTEXPR_STATIC_INLINE bool RequiredMicrofacetCache = IsAnisotropic ? AnisotropicMicrofacetCache : ReadableIsotropicMicrofacetCache; + template > + enable_if_t create(scalar_type A) + { + this_t retval; + retval.__ndf_base.a2 = A*A; + retval.__ndf_base.one_minus_a2 = scalar_type(1.0) - A*A; + retval.__generate_base.ax = A; + retval.__generate_base.ay = A; + return retval; + } + template > + enable_if_t create(scalar_type ax, scalar_type ay) + { + this_t retval; + retval.__ndf_base.ax2 = ax*ax; + retval.__ndf_base.ay2 = ay*ay; + retval.__ndf_base.a2 = ax*ay; + retval.__generate_base.ax = ax; + retval.__generate_base.ay = ay; + return retval; + } + template NBL_FUNC_REQUIRES(RequiredMicrofacetCache) enable_if_t createQuantQuery(NBL_CONST_REF_ARG(MicrofacetCache) cache, scalar_type orientedEta) { diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 05d617d8ca..c6a0094bac 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -91,7 +91,7 @@ struct SBeckmannIsotropic return __base.quotient_and_pdf(_sample, interaction.isotropic, cache.iso_cache); } - SCookTorrance __base; + SCookTorrance __base; }; template) @@ -150,7 +150,7 @@ struct SBeckmannAnisotropic return __base.quotient_and_pdf(_sample, interaction, cache); } - SCookTorrance __base; + SCookTorrance __base; }; } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 0bed5c9e01..aff18fead3 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -92,7 +92,7 @@ struct SGGXIsotropic return __base.quotient_and_pdf(_sample, interaction.isotropic, cache.iso_cache); } - SCookTorrance __base; + SCookTorrance __base; }; template) @@ -151,7 +151,7 @@ struct SGGXAnisotropic return __base.quotient_and_pdf(_sample, interaction, cache); } - SCookTorrance __base; + SCookTorrance __base; }; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index db3be603ff..88bc795452 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -97,7 +97,7 @@ struct SBeckmannDielectricIsotropic return __base.quotient_and_pdf(_sample, interaction.isotropic, cache.iso_cache); } - SCookTorrance __base; + SCookTorrance __base; }; template) @@ -168,7 +168,7 @@ struct SBeckmannDielectricAnisotropic return __base.quotient_and_pdf(_sample, interaction, cache); } - SCookTorrance __base; + SCookTorrance __base; }; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 74865e7619..feff0f5e3f 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -98,7 +98,7 @@ struct SGGXDielectricIsotropic return __base.quotient_and_pdf(_sample, interaction.isotropic, cache.iso_cache); } - SCookTorrance __base; + SCookTorrance __base; }; template) @@ -169,7 +169,7 @@ struct SGGXDielectricAnisotropic return __base.quotient_and_pdf(_sample, interaction, cache); } - SCookTorrance __base; + SCookTorrance __base; }; } From fd128e6718681cb044deff97df282ccd5154e343 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 26 Sep 2025 17:10:38 +0700 Subject: [PATCH 38/38] make beckmann + ggx bxdfs typedefs of cooktorrance base, functionality moved into base --- .../builtin/hlsl/bxdf/cook_torrance_base.hlsl | 32 +- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 4 +- include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 4 +- .../hlsl/bxdf/reflection/beckmann.hlsl | 269 +++++++-------- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 271 +++++++-------- .../hlsl/bxdf/transmission/beckmann.hlsl | 308 ++++++++--------- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 310 +++++++++--------- 7 files changed, 608 insertions(+), 590 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl index 5f640b5b2f..ac576eb307 100644 --- a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl @@ -96,7 +96,7 @@ struct CookTorranceParams } // N (NDF), F (fresnel) -template +template && ndf::NDF && fresnel::Fresnel) struct SCookTorrance { MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); @@ -109,24 +109,24 @@ struct SCookTorrance NBL_CONSTEXPR_STATIC_INLINE bool IsAnisotropic = ndf_type::IsAnisotropic; NBL_CONSTEXPR_STATIC_INLINE bool IsBSDF = ndf_type::IsBSDF; - using create_params_type = impl::CookTorranceParams; + using creation_params_type = impl::CookTorranceParams; template > - enable_if_t create(NBL_CONST_REF_ARG(create_params_type) params) + static enable_if_t create(NBL_CONST_REF_ARG(creation_params_type) params) { this_t retval; retval.ndf = ndf_type::create(params.A); retval.fresnel = params.fresnel; - retval.luminosityContributionHint = luminosityContributionHint; + retval.luminosityContributionHint = params.luminosityContributionHint; return retval; } template > - enable_if_t create(NBL_CONST_REF_ARG(create_params_type) params) + static enable_if_t create(NBL_CONST_REF_ARG(creation_params_type) params) { this_t retval; retval.ndf = ndf_type::create(params.ax, params.ay); retval.fresnel = params.fresnel; - retval.luminosityContributionHint = luminosityContributionHint; + retval.luminosityContributionHint = params.luminosityContributionHint; return retval; } @@ -166,8 +166,8 @@ struct SCookTorrance return __eval(_sample, interaction, cache); } - template) - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const T u, NBL_REF_ARG(anisocache_type) cache) + template > + enable_if_t generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache) { const vector3_type localV = interaction.getTangentSpaceV(); const vector3_type localH = ndf.generateH(localV, u); @@ -179,8 +179,8 @@ struct SCookTorrance return sample_type::createFromTangentSpace(localL, interaction.getFromTangentSpace()); } - template) - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const T u, NBL_REF_ARG(anisocache_type) cache) + template > + enable_if_t generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(anisocache_type) cache) { fresnel::OrientedEtaRcps rcpEta = fresnel.getOrientedEtaRcps(); @@ -213,19 +213,19 @@ struct SCookTorrance return sample_type::createFromTangentSpace(localL, interaction.getFromTangentSpace()); } - template NBL_FUNC_REQUIRES(is_same_v) - enable_if_t generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const T u, NBL_REF_ARG(anisocache_type) cache) + template, typename D=bool_constant > + enable_if_t generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache) { anisocache_type aniso_cache; - sample_type s = generate(anisotropic_interaction_type::create(interaction), u, aniso_cache); + sample_type s = generate(anisotropic_interaction_type::create(interaction), u, aniso_cache); cache = aniso_cache.iso_cache; return s; } - template NBL_FUNC_REQUIRES(is_same_v) - enable_if_t generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const T u, NBL_REF_ARG(anisocache_type) cache) + template, typename D=bool_constant > + enable_if_t generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(isocache_type) cache) { anisocache_type aniso_cache; - sample_type s = generate(anisotropic_interaction_type::create(interaction), u, aniso_cache); + sample_type s = generate(anisotropic_interaction_type::create(interaction), u, aniso_cache); cache = aniso_cache.iso_cache; return s; } diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index 83f26e4c25..051d5f03f8 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -299,7 +299,7 @@ struct Beckmann NBL_CONSTEXPR_STATIC_INLINE bool RequiredMicrofacetCache = IsAnisotropic ? AnisotropicMicrofacetCache : ReadableIsotropicMicrofacetCache; template > - enable_if_t create(scalar_type A) + static enable_if_t create(scalar_type A) { this_t retval; retval.__ndf_base.a2 = A*A; @@ -308,7 +308,7 @@ struct Beckmann return retval; } template > - enable_if_t create(scalar_type ax, scalar_type ay) + static enable_if_t create(scalar_type ax, scalar_type ay) { this_t retval; retval.__ndf_base.ax2 = ax*ax; diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index bd58f4203f..484194156d 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -305,7 +305,7 @@ struct GGX NBL_CONSTEXPR_STATIC_INLINE bool RequiredMicrofacetCache = IsAnisotropic ? AnisotropicMicrofacetCache : ReadableIsotropicMicrofacetCache; template > - enable_if_t create(scalar_type A) + static enable_if_t create(scalar_type A) { this_t retval; retval.__ndf_base.a2 = A*A; @@ -315,7 +315,7 @@ struct GGX return retval; } template > - enable_if_t create(scalar_type ax, scalar_type ay) + static enable_if_t create(scalar_type ax, scalar_type ay) { this_t retval; retval.__ndf_base.ax2 = ax*ax; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index c6a0094bac..86ca38df59 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -19,139 +19,142 @@ namespace bxdf namespace reflection { -template) -struct SBeckmannIsotropic -{ - using this_t = SBeckmannIsotropic; - MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); - - using ndf_type = ndf::Beckmann; - using fresnel_type = fresnel::Conductor; - - struct SCreationParams - { - scalar_type A; - spectral_type eta; - spectral_type etak; - }; - using creation_type = SCreationParams; - - static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) eta, NBL_CONST_REF_ARG(spectral_type) etak) - { - this_t retval; - retval.__base.ndf.__ndf_base.a2 = A*A; - retval.__base.ndf.__generate_base.ax = A; - retval.__base.ndf.__generate_base.ay = A; - retval.__base.fresnel.eta = eta; - retval.__base.fresnel.etak2 = etak * etak; - retval.__base.fresnel.etaLen2 = eta * eta + retval.__base.fresnel.etak2; - return retval; - } - static this_t create(NBL_CONST_REF_ARG(creation_type) params) - { - return create(params.A, params.eta, params.etak); - } - - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) - { - return __base.eval(_sample, interaction, cache); - } - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - return __base.eval(_sample, interaction.isotropic, cache.iso_cache); - } - - sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache) - { - anisocache_type aniso_cache; - sample_type s = __base.template generate(anisotropic_interaction_type::create(interaction), u, aniso_cache); - cache = aniso_cache.iso_cache; - return s; - } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache) - { - return __base.template generate(interaction, u, cache); - } - - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) - { - return __base.pdf(_sample, interaction, cache); - } - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - return __base.pdf(_sample, interaction.isotropic, cache.iso_cache); - } - - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) - { - return __base.quotient_and_pdf(_sample, interaction, cache); - } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - return __base.quotient_and_pdf(_sample, interaction.isotropic, cache.iso_cache); - } - - SCookTorrance __base; -}; - -template) -struct SBeckmannAnisotropic -{ - using this_t = SBeckmannAnisotropic; - MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); - - using ndf_type = ndf::Beckmann; - using fresnel_type = fresnel::Conductor; - - struct SCreationParams - { - scalar_type ax; - scalar_type ay; - spectral_type eta; - spectral_type etak; - }; - using creation_type = SCreationParams; - - static this_t create(scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) eta, NBL_CONST_REF_ARG(spectral_type) etak) - { - this_t retval; - retval.__base.ndf.__ndf_base.ax2 = ax*ax; - retval.__base.ndf.__ndf_base.ay2 = ay*ay; - retval.__base.ndf.__ndf_base.a2 = ax*ay; - retval.__base.ndf.__generate_base.ax = ax; - retval.__base.ndf.__generate_base.ay = ay; - retval.__base.fresnel.eta = eta; - retval.__base.fresnel.etak2 = etak * etak; - retval.__base.fresnel.etaLen2 = eta * eta + retval.__base.fresnel.etak2; - return retval; - } - static this_t create(NBL_CONST_REF_ARG(creation_type) params) - { - return create(params.ax, params.ay, params.eta, params.etak); - } - - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - return __base.eval(_sample, interaction, cache); - } - - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache) - { - return __base.template generate(interaction, u, cache); - } - - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - return __base.pdf(_sample, interaction, cache); - } - - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - return __base.quotient_and_pdf(_sample, interaction, cache); - } - - SCookTorrance __base; -}; +template +using SBeckmannIsotropic = SCookTorrance, fresnel::Conductor >; + +template +using SBeckmannAnisotropic = SCookTorrance, fresnel::Conductor >; + +// template) +// struct SBeckmannIsotropic +// { +// using this_t = SBeckmannIsotropic; +// MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); + +// using ndf_type = ndf::Beckmann; +// using fresnel_type = fresnel::Conductor; + +// struct SCreationParams +// { +// scalar_type A; +// spectral_type eta; +// spectral_type etak; +// }; +// using creation_type = SCreationParams; + +// static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) eta, NBL_CONST_REF_ARG(spectral_type) etak) +// { +// this_t retval; +// retval.__base.ndf.__ndf_base.a2 = A*A; +// retval.__base.ndf.__generate_base.ax = A; +// retval.__base.ndf.__generate_base.ay = A; +// retval.__base.fresnel.eta = eta; +// retval.__base.fresnel.etak2 = etak * etak; +// retval.__base.fresnel.etaLen2 = eta * eta + retval.__base.fresnel.etak2; +// return retval; +// } +// static this_t create(NBL_CONST_REF_ARG(creation_type) params) +// { +// return create(params.A, params.eta, params.etak); +// } + +// spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) +// { +// return __base.eval(_sample, interaction, cache); +// } +// spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// return __base.eval(_sample, interaction.isotropic, cache.iso_cache); +// } + +// sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache) +// { +// return __base.generate(interaction, u, cache); +// } +// sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache) +// { +// return __base.generate(interaction, u, cache); +// } + +// scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) +// { +// return __base.pdf(_sample, interaction, cache); +// } +// scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// return __base.pdf(_sample, interaction.isotropic, cache.iso_cache); +// } + +// quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) +// { +// return __base.quotient_and_pdf(_sample, interaction, cache); +// } +// quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// return __base.quotient_and_pdf(_sample, interaction.isotropic, cache.iso_cache); +// } + +// SCookTorrance __base; +// }; + +// template) +// struct SBeckmannAnisotropic +// { +// using this_t = SBeckmannAnisotropic; +// MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); + +// using ndf_type = ndf::Beckmann; +// using fresnel_type = fresnel::Conductor; + +// struct SCreationParams +// { +// scalar_type ax; +// scalar_type ay; +// spectral_type eta; +// spectral_type etak; +// }; +// using creation_type = SCreationParams; + +// static this_t create(scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) eta, NBL_CONST_REF_ARG(spectral_type) etak) +// { +// this_t retval; +// retval.__base.ndf.__ndf_base.ax2 = ax*ax; +// retval.__base.ndf.__ndf_base.ay2 = ay*ay; +// retval.__base.ndf.__ndf_base.a2 = ax*ay; +// retval.__base.ndf.__generate_base.ax = ax; +// retval.__base.ndf.__generate_base.ay = ay; +// retval.__base.fresnel.eta = eta; +// retval.__base.fresnel.etak2 = etak * etak; +// retval.__base.fresnel.etaLen2 = eta * eta + retval.__base.fresnel.etak2; +// return retval; +// } +// static this_t create(NBL_CONST_REF_ARG(creation_type) params) +// { +// return create(params.ax, params.ay, params.eta, params.etak); +// } + +// spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// return __base.eval(_sample, interaction, cache); +// } + +// sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache) +// { +// return __base.generate(interaction, u, cache); +// } + +// scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// return __base.pdf(_sample, interaction, cache); +// } + +// quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// return __base.quotient_and_pdf(_sample, interaction, cache); +// } + +// SCookTorrance __base; +// }; } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index aff18fead3..718f72e187 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -19,140 +19,143 @@ namespace bxdf namespace reflection { -template) -struct SGGXIsotropic -{ - using this_t = SGGXIsotropic; - MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); - - using ndf_type = ndf::GGX; - using fresnel_type = fresnel::Conductor; - - struct SCreationParams - { - scalar_type A; - spectral_type eta; - spectral_type etak; - }; - using creation_type = SCreationParams; - - static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) eta, NBL_CONST_REF_ARG(spectral_type) etak) - { - this_t retval; - retval.__base.ndf.__ndf_base.a2 = A*A; - retval.__base.ndf.__ndf_base.one_minus_a2 = scalar_type(1.0) - A*A; - retval.__base.ndf.__generate_base.ax = A; - retval.__base.ndf.__generate_base.ay = A; - retval.__base.fresnel.eta = eta; - retval.__base.fresnel.etak2 = etak * etak; - retval.__base.fresnel.etaLen2 = eta * eta + retval.__base.fresnel.etak2; - return retval; - } - static this_t create(NBL_CONST_REF_ARG(creation_type) params) - { - return create(params.A, params.eta, params.etak); - } - - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) - { - return __base.eval(_sample, interaction, cache); - } - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - return __base.eval(_sample, interaction.isotropic, cache.iso_cache); - } - - sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache) - { - anisocache_type aniso_cache; - sample_type s = __base.template generate(anisotropic_interaction_type::create(interaction), u, aniso_cache); - cache = aniso_cache.iso_cache; - return s; - } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache) - { - return __base.template generate(interaction, u, cache); - } - - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) - { - return __base.pdf(_sample, interaction, cache); - } - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - return __base.pdf(_sample, interaction.isotropic, cache.iso_cache); - } - - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) - { - return __base.quotient_and_pdf(_sample, interaction, cache); - } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - return __base.quotient_and_pdf(_sample, interaction.isotropic, cache.iso_cache); - } - - SCookTorrance __base; -}; - -template) -struct SGGXAnisotropic -{ - using this_t = SGGXAnisotropic; - MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); - - using ndf_type = ndf::GGX; - using fresnel_type = fresnel::Conductor; - - struct SCreationParams - { - scalar_type ax; - scalar_type ay; - spectral_type eta; - spectral_type etak; - }; - using creation_type = SCreationParams; - - static this_t create(scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) eta, NBL_CONST_REF_ARG(spectral_type) etak) - { - this_t retval; - retval.__base.ndf.__ndf_base.ax2 = ax*ax; - retval.__base.ndf.__ndf_base.ay2 = ay*ay; - retval.__base.ndf.__ndf_base.a2 = ax*ay; - retval.__base.ndf.__generate_base.ax = ax; - retval.__base.ndf.__generate_base.ay = ay; - retval.__base.fresnel.eta = eta; - retval.__base.fresnel.etak2 = etak * etak; - retval.__base.fresnel.etaLen2 = eta * eta + retval.__base.fresnel.etak2; - return retval; - } - static this_t create(NBL_CONST_REF_ARG(creation_type) params) - { - return create(params.ax, params.ay, params.eta, params.etak); - } - - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - return __base.eval(_sample, interaction, cache); - } - - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache) - { - return __base.template generate(interaction, u, cache); - } - - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - return __base.pdf(_sample, interaction, cache); - } - - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - return __base.quotient_and_pdf(_sample, interaction, cache); - } - - SCookTorrance __base; -}; +template +using SGGXIsotropic = SCookTorrance, fresnel::Conductor >; + +template +using SGGXAnisotropic = SCookTorrance, fresnel::Conductor >; + +// template) +// struct SGGXIsotropic +// { +// using this_t = SGGXIsotropic; +// MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); + +// using ndf_type = ndf::GGX; +// using fresnel_type = fresnel::Conductor; + +// struct SCreationParams +// { +// scalar_type A; +// spectral_type eta; +// spectral_type etak; +// }; +// using creation_type = SCreationParams; + +// static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) eta, NBL_CONST_REF_ARG(spectral_type) etak) +// { +// this_t retval; +// retval.__base.ndf.__ndf_base.a2 = A*A; +// retval.__base.ndf.__ndf_base.one_minus_a2 = scalar_type(1.0) - A*A; +// retval.__base.ndf.__generate_base.ax = A; +// retval.__base.ndf.__generate_base.ay = A; +// retval.__base.fresnel.eta = eta; +// retval.__base.fresnel.etak2 = etak * etak; +// retval.__base.fresnel.etaLen2 = eta * eta + retval.__base.fresnel.etak2; +// return retval; +// } +// static this_t create(NBL_CONST_REF_ARG(creation_type) params) +// { +// return create(params.A, params.eta, params.etak); +// } + +// spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) +// { +// return __base.eval(_sample, interaction, cache); +// } +// spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// return __base.eval(_sample, interaction.isotropic, cache.iso_cache); +// } + +// sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache) +// { +// return __base.generate(interaction, u, cache); +// } +// sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache) +// { +// return __base.generate(interaction, u, cache); +// } + +// scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) +// { +// return __base.pdf(_sample, interaction, cache); +// } +// scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// return __base.pdf(_sample, interaction.isotropic, cache.iso_cache); +// } + +// quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) +// { +// return __base.quotient_and_pdf(_sample, interaction, cache); +// } +// quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// return __base.quotient_and_pdf(_sample, interaction.isotropic, cache.iso_cache); +// } + +// SCookTorrance __base; +// }; + +// template) +// struct SGGXAnisotropic +// { +// using this_t = SGGXAnisotropic; +// MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); + +// using ndf_type = ndf::GGX; +// using fresnel_type = fresnel::Conductor; + +// struct SCreationParams +// { +// scalar_type ax; +// scalar_type ay; +// spectral_type eta; +// spectral_type etak; +// }; +// using creation_type = SCreationParams; + +// static this_t create(scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) eta, NBL_CONST_REF_ARG(spectral_type) etak) +// { +// this_t retval; +// retval.__base.ndf.__ndf_base.ax2 = ax*ax; +// retval.__base.ndf.__ndf_base.ay2 = ay*ay; +// retval.__base.ndf.__ndf_base.a2 = ax*ay; +// retval.__base.ndf.__generate_base.ax = ax; +// retval.__base.ndf.__generate_base.ay = ay; +// retval.__base.fresnel.eta = eta; +// retval.__base.fresnel.etak2 = etak * etak; +// retval.__base.fresnel.etaLen2 = eta * eta + retval.__base.fresnel.etak2; +// return retval; +// } +// static this_t create(NBL_CONST_REF_ARG(creation_type) params) +// { +// return create(params.ax, params.ay, params.eta, params.etak); +// } + +// spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// return __base.eval(_sample, interaction, cache); +// } + +// sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache) +// { +// return __base.generate(interaction, u, cache); +// } + +// scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// return __base.pdf(_sample, interaction, cache); +// } + +// quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// return __base.quotient_and_pdf(_sample, interaction, cache); +// } + +// SCookTorrance __base; +// }; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 88bc795452..dfe8b79796 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -19,157 +19,163 @@ namespace bxdf namespace transmission { -template) -struct SBeckmannDielectricIsotropic -{ - using this_t = SBeckmannDielectricIsotropic; - MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); - - using ndf_type = ndf::Beckmann; - using fresnel_type = fresnel::Dielectric; - - struct SCreationParams - { - scalar_type A; - fresnel::OrientedEtas orientedEta; - spectral_type luminosityContributionHint; - }; - using creation_type = SCreationParams; - - static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type A, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) - { - this_t retval; - retval.__base.ndf.__ndf_base.a2 = A*A; - retval.__base.ndf.__generate_base.ax = A; - retval.__base.ndf.__generate_base.ay = A; - retval.__base.fresnel.orientedEta = orientedEta; - retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; - retval.__base.luminosityContributionHint = luminosityContributionHint; - return retval; - } - static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type A) - { - static_assert(vector_traits::Dimension == 3); - const spectral_type rec709 = spectral_type(0.2126, 0.7152, 0.0722); - return create(orientedEta, A, rec709); - } - static this_t create(NBL_CONST_REF_ARG(creation_type) params) - { - return create(params.orientedEta, params.A, params.luminosityContributionHint); - } - - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) - { - return __base.eval(_sample, interaction, cache); - } - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - return __base.eval(_sample, interaction.isotropic, cache.iso_cache); - } - - sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(isocache_type) cache) - { - anisocache_type aniso_cache; - sample_type s = __base.template generate(anisotropic_interaction_type::create(interaction), u, aniso_cache); - cache = aniso_cache.iso_cache; - return s; - } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(anisocache_type) cache) - { - return __base.template generate(interaction, u, cache); - } - - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) - { - return __base.pdf(_sample, interaction, cache); - } - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - return __base.pdf(_sample, interaction.isotropic, cache.iso_cache); - } - - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) - { - return __base.quotient_and_pdf(_sample, interaction, cache); - } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - return __base.quotient_and_pdf(_sample, interaction.isotropic, cache.iso_cache); - } - - SCookTorrance __base; -}; - -template) -struct SBeckmannDielectricAnisotropic -{ - using this_t = SBeckmannDielectricAnisotropic; - MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); - - using ndf_type = ndf::Beckmann; - using fresnel_type = fresnel::Dielectric; - - struct SCreationParams - { - scalar_type ax; - scalar_type ay; - fresnel::OrientedEtas orientedEta; - spectral_type luminosityContributionHint; - }; - using creation_type = SCreationParams; - - static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) - { - this_t retval; - retval.__base.ndf.__ndf_base.ax2 = ax*ax; - retval.__base.ndf.__ndf_base.ay2 = ay*ay; - retval.__base.ndf.__ndf_base.a2 = ax*ay; - retval.__base.ndf.__generate_base.ax = ax; - retval.__base.ndf.__generate_base.ay = ay; - retval.__base.fresnel.orientedEta = orientedEta; - retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; - retval.__base.luminosityContributionHint = luminosityContributionHint; - return retval; - } - static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type ax, scalar_type ay) - { - static_assert(vector_traits::Dimension == 3); - const spectral_type rec709 = spectral_type(0.2126, 0.7152, 0.0722); - return create(orientedEta, ax, ay, rec709); - } - static this_t create(NBL_CONST_REF_ARG(creation_type) params) - { - return create(params.orientedEta, params.ax, params.ay, params.luminosityContributionHint); - } - - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - return __base.eval(_sample, interaction, cache); - } - - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(anisocache_type) cache) - { - return __base.template generate(interaction, u, cache); - } - - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u) - { - anisocache_type dummycache; - return generate(interaction, u, dummycache); - } - - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - return __base.pdf(_sample, interaction, cache); - } - - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - return __base.quotient_and_pdf(_sample, interaction, cache); - } - - SCookTorrance __base; -}; +template +using SBeckmannDielectricIsotropic = SCookTorrance, fresnel::Dielectric >; + +template +using SBeckmannDielectricAnisotropic = SCookTorrance, fresnel::Dielectric >; + +// template) +// struct SBeckmannDielectricIsotropic +// { +// using this_t = SBeckmannDielectricIsotropic; +// MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); + +// using ndf_type = ndf::Beckmann; +// using fresnel_type = fresnel::Dielectric; + +// struct SCreationParams +// { +// scalar_type A; +// fresnel::OrientedEtas orientedEta; +// spectral_type luminosityContributionHint; +// }; +// using creation_type = SCreationParams; + +// static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type A, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) +// { +// this_t retval; +// retval.__base.ndf.__ndf_base.a2 = A*A; +// retval.__base.ndf.__generate_base.ax = A; +// retval.__base.ndf.__generate_base.ay = A; +// retval.__base.fresnel.orientedEta = orientedEta; +// retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; +// retval.__base.luminosityContributionHint = luminosityContributionHint; +// return retval; +// } +// static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type A) +// { +// static_assert(vector_traits::Dimension == 3); +// const spectral_type rec709 = spectral_type(0.2126, 0.7152, 0.0722); +// return create(orientedEta, A, rec709); +// } +// static this_t create(NBL_CONST_REF_ARG(creation_type) params) +// { +// return create(params.orientedEta, params.A, params.luminosityContributionHint); +// } + +// spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) +// { +// return __base.eval(_sample, interaction, cache); +// } +// spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// return __base.eval(_sample, interaction.isotropic, cache.iso_cache); +// } + +// sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(isocache_type) cache) +// { +// anisocache_type aniso_cache; +// sample_type s = __base.generate(anisotropic_interaction_type::create(interaction), u, aniso_cache); +// cache = aniso_cache.iso_cache; +// return s; +// } +// sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(anisocache_type) cache) +// { +// return __base.generate(interaction, u, cache); +// } + +// scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) +// { +// return __base.pdf(_sample, interaction, cache); +// } +// scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// return __base.pdf(_sample, interaction.isotropic, cache.iso_cache); +// } + +// quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) +// { +// return __base.quotient_and_pdf(_sample, interaction, cache); +// } +// quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// return __base.quotient_and_pdf(_sample, interaction.isotropic, cache.iso_cache); +// } + +// SCookTorrance __base; +// }; + +// template) +// struct SBeckmannDielectricAnisotropic +// { +// using this_t = SBeckmannDielectricAnisotropic; +// MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); + +// using ndf_type = ndf::Beckmann; +// using fresnel_type = fresnel::Dielectric; + +// struct SCreationParams +// { +// scalar_type ax; +// scalar_type ay; +// fresnel::OrientedEtas orientedEta; +// spectral_type luminosityContributionHint; +// }; +// using creation_type = SCreationParams; + +// static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) +// { +// this_t retval; +// retval.__base.ndf.__ndf_base.ax2 = ax*ax; +// retval.__base.ndf.__ndf_base.ay2 = ay*ay; +// retval.__base.ndf.__ndf_base.a2 = ax*ay; +// retval.__base.ndf.__generate_base.ax = ax; +// retval.__base.ndf.__generate_base.ay = ay; +// retval.__base.fresnel.orientedEta = orientedEta; +// retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; +// retval.__base.luminosityContributionHint = luminosityContributionHint; +// return retval; +// } +// static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type ax, scalar_type ay) +// { +// static_assert(vector_traits::Dimension == 3); +// const spectral_type rec709 = spectral_type(0.2126, 0.7152, 0.0722); +// return create(orientedEta, ax, ay, rec709); +// } +// static this_t create(NBL_CONST_REF_ARG(creation_type) params) +// { +// return create(params.orientedEta, params.ax, params.ay, params.luminosityContributionHint); +// } + +// spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// return __base.eval(_sample, interaction, cache); +// } + +// sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(anisocache_type) cache) +// { +// return __base.generate(interaction, u, cache); +// } + +// sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u) +// { +// anisocache_type dummycache; +// return generate(interaction, u, dummycache); +// } + +// scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// return __base.pdf(_sample, interaction, cache); +// } + +// quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// return __base.quotient_and_pdf(_sample, interaction, cache); +// } + +// SCookTorrance __base; +// }; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index feff0f5e3f..41e163b56e 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -19,158 +19,164 @@ namespace bxdf namespace transmission { -template) -struct SGGXDielectricIsotropic -{ - using this_t = SGGXDielectricIsotropic; - MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); - - using ndf_type = ndf::GGX; - using fresnel_type = fresnel::Dielectric; - - struct SCreationParams - { - scalar_type A; - fresnel::OrientedEtas orientedEta; - spectral_type luminosityContributionHint; - }; - using creation_type = SCreationParams; - - static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type A, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) - { - this_t retval; - retval.__base.ndf.__ndf_base.a2 = A*A; - retval.__base.ndf.__ndf_base.one_minus_a2 = scalar_type(1.0) - A*A; - retval.__base.ndf.__generate_base.ax = A; - retval.__base.ndf.__generate_base.ay = A; - retval.__base.fresnel.orientedEta = orientedEta; - retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; - retval.__base.luminosityContributionHint = luminosityContributionHint; - return retval; - } - static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type A) - { - static_assert(vector_traits::Dimension == 3); - const spectral_type rec709 = spectral_type(0.2126, 0.7152, 0.0722); - return create(orientedEta, A, rec709); - } - static this_t create(NBL_CONST_REF_ARG(creation_type) params) - { - return create(params.orientedEta, params.A, params.luminosityContributionHint); - } - - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) - { - return __base.eval(_sample, interaction, cache); - } - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - return __base.eval(_sample, interaction.isotropic, cache.iso_cache); - } - - sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(isocache_type) cache) - { - anisocache_type aniso_cache; - sample_type s = __base.template generate(anisotropic_interaction_type::create(interaction), u, aniso_cache); - cache = aniso_cache.iso_cache; - return s; - } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(anisocache_type) cache) - { - return __base.template generate(interaction, u, cache); - } - - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) - { - return __base.pdf(_sample, interaction, cache); - } - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - return __base.pdf(_sample, interaction.isotropic, cache.iso_cache); - } - - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) - { - return __base.quotient_and_pdf(_sample, interaction, cache); - } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - return __base.quotient_and_pdf(_sample, interaction.isotropic, cache.iso_cache); - } - - SCookTorrance __base; -}; - -template) -struct SGGXDielectricAnisotropic -{ - using this_t = SGGXDielectricAnisotropic; - MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); - - using ndf_type = ndf::GGX; - using fresnel_type = fresnel::Dielectric; - - struct SCreationParams - { - scalar_type ax; - scalar_type ay; - fresnel::OrientedEtas orientedEta; - spectral_type luminosityContributionHint; - }; - using creation_type = SCreationParams; - - static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) - { - this_t retval; - retval.__base.ndf.__ndf_base.ax2 = ax*ax; - retval.__base.ndf.__ndf_base.ay2 = ay*ay; - retval.__base.ndf.__ndf_base.a2 = ax*ay; - retval.__base.ndf.__generate_base.ax = ax; - retval.__base.ndf.__generate_base.ay = ay; - retval.__base.fresnel.orientedEta = orientedEta; - retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; - retval.__base.luminosityContributionHint = luminosityContributionHint; - return retval; - } - static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type ax, scalar_type ay) - { - static_assert(vector_traits::Dimension == 3); - const spectral_type rec709 = spectral_type(0.2126, 0.7152, 0.0722); - return create(orientedEta, ax, ay, rec709); - } - static this_t create(NBL_CONST_REF_ARG(creation_type) params) - { - return create(params.orientedEta, params.ax, params.ay, params.luminosityContributionHint); - } - - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - return __base.eval(_sample, interaction, cache); - } - - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(anisocache_type) cache) - { - return __base.template generate(interaction, u, cache); - } - - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u) - { - anisocache_type dummycache; - return generate(interaction, u, dummycache); - } - - scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - return __base.pdf(_sample, interaction, cache); - } - - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - return __base.quotient_and_pdf(_sample, interaction, cache); - } - - SCookTorrance __base; -}; +template +using SGGXDielectricIsotropic = SCookTorrance, fresnel::Dielectric >; + +template +using SGGXDielectricAnisotropic = SCookTorrance, fresnel::Dielectric >; + +// template) +// struct SGGXDielectricIsotropic +// { +// using this_t = SGGXDielectricIsotropic; +// MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); + +// using ndf_type = ndf::GGX; +// using fresnel_type = fresnel::Dielectric; + +// struct SCreationParams +// { +// scalar_type A; +// fresnel::OrientedEtas orientedEta; +// spectral_type luminosityContributionHint; +// }; +// using creation_type = SCreationParams; + +// static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type A, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) +// { +// this_t retval; +// retval.__base.ndf.__ndf_base.a2 = A*A; +// retval.__base.ndf.__ndf_base.one_minus_a2 = scalar_type(1.0) - A*A; +// retval.__base.ndf.__generate_base.ax = A; +// retval.__base.ndf.__generate_base.ay = A; +// retval.__base.fresnel.orientedEta = orientedEta; +// retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; +// retval.__base.luminosityContributionHint = luminosityContributionHint; +// return retval; +// } +// static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type A) +// { +// static_assert(vector_traits::Dimension == 3); +// const spectral_type rec709 = spectral_type(0.2126, 0.7152, 0.0722); +// return create(orientedEta, A, rec709); +// } +// static this_t create(NBL_CONST_REF_ARG(creation_type) params) +// { +// return create(params.orientedEta, params.A, params.luminosityContributionHint); +// } + +// spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) +// { +// return __base.eval(_sample, interaction, cache); +// } +// spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// return __base.eval(_sample, interaction.isotropic, cache.iso_cache); +// } + +// sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(isocache_type) cache) +// { +// anisocache_type aniso_cache; +// sample_type s = __base.generate(anisotropic_interaction_type::create(interaction), u, aniso_cache); +// cache = aniso_cache.iso_cache; +// return s; +// } +// sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(anisocache_type) cache) +// { +// return __base.generate(interaction, u, cache); +// } + +// scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) +// { +// return __base.pdf(_sample, interaction, cache); +// } +// scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// return __base.pdf(_sample, interaction.isotropic, cache.iso_cache); +// } + +// quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) +// { +// return __base.quotient_and_pdf(_sample, interaction, cache); +// } +// quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// return __base.quotient_and_pdf(_sample, interaction.isotropic, cache.iso_cache); +// } + +// SCookTorrance __base; +// }; + +// template) +// struct SGGXDielectricAnisotropic +// { +// using this_t = SGGXDielectricAnisotropic; +// MICROFACET_BXDF_CONFIG_TYPE_ALIASES(Config); + +// using ndf_type = ndf::GGX; +// using fresnel_type = fresnel::Dielectric; + +// struct SCreationParams +// { +// scalar_type ax; +// scalar_type ay; +// fresnel::OrientedEtas orientedEta; +// spectral_type luminosityContributionHint; +// }; +// using creation_type = SCreationParams; + +// static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) +// { +// this_t retval; +// retval.__base.ndf.__ndf_base.ax2 = ax*ax; +// retval.__base.ndf.__ndf_base.ay2 = ay*ay; +// retval.__base.ndf.__ndf_base.a2 = ax*ay; +// retval.__base.ndf.__generate_base.ax = ax; +// retval.__base.ndf.__generate_base.ay = ay; +// retval.__base.fresnel.orientedEta = orientedEta; +// retval.__base.fresnel.orientedEta2 = orientedEta.value * orientedEta.value; +// retval.__base.luminosityContributionHint = luminosityContributionHint; +// return retval; +// } +// static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type ax, scalar_type ay) +// { +// static_assert(vector_traits::Dimension == 3); +// const spectral_type rec709 = spectral_type(0.2126, 0.7152, 0.0722); +// return create(orientedEta, ax, ay, rec709); +// } +// static this_t create(NBL_CONST_REF_ARG(creation_type) params) +// { +// return create(params.orientedEta, params.ax, params.ay, params.luminosityContributionHint); +// } + +// spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// return __base.eval(_sample, interaction, cache); +// } + +// sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(anisocache_type) cache) +// { +// return __base.generate(interaction, u, cache); +// } + +// sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u) +// { +// anisocache_type dummycache; +// return generate(interaction, u, dummycache); +// } + +// scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// return __base.pdf(_sample, interaction, cache); +// } + +// quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) +// { +// return __base.quotient_and_pdf(_sample, interaction, cache); +// } + +// SCookTorrance __base; +// }; }