Skip to content

Commit 6a0e28d

Browse files
committed
various fixes to ggx ndf, cook torrance base
1 parent 971e140 commit 6a0e28d

File tree

4 files changed

+50
-40
lines changed

4 files changed

+50
-40
lines changed

include/nbl/builtin/hlsl/bxdf/base/cook_torrance_base.hlsl

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -69,28 +69,29 @@ struct quant_query_helper<N, F, false>
6969
};
7070

7171
template<class F, bool IsBSDF>
72-
struct check_TIR_helper;
72+
struct checkValid;
7373

7474
template<class F>
75-
struct check_TIR_helper<F, false>
75+
struct checkValid<F, false>
7676
{
77-
template<class MicrofacetCache>
78-
static bool __call(NBL_CONST_REF_ARG(F) fresnel, NBL_CONST_REF_ARG(MicrofacetCache) cache)
77+
using scalar_type = typename F::scalar_type;
78+
79+
template<class Sample, class Interaction, class MicrofacetCache>
80+
static bool __call(NBL_CONST_REF_ARG(F) fresnel, NBL_CONST_REF_ARG(Sample) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache)
7981
{
80-
return true;
82+
return _sample.getNdotL() > numeric_limits<scalar_type>::min && interaction.getNdotV() > numeric_limits<scalar_type>::min;
8183
}
8284
};
8385

8486
template<class F>
85-
struct check_TIR_helper<F, true>
87+
struct checkValid<F, true>
8688
{
8789
using vector_type = typename F::vector_type; // expect monochrome
8890

89-
template<class MicrofacetCache>
90-
static bool __call(NBL_CONST_REF_ARG(F) fresnel, NBL_CONST_REF_ARG(MicrofacetCache) cache)
91+
template<class Sample, class Interaction, class MicrofacetCache>
92+
static bool __call(NBL_CONST_REF_ARG(F) fresnel, NBL_CONST_REF_ARG(Sample) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache)
9193
{
92-
fresnel::OrientedEtas<vector_type> orientedEta = fresnel::OrientedEtas<vector_type>::create(typename F::scalar_type(1.0), hlsl::promote<vector_type>(fresnel.getRefractionOrientedEta()));
93-
return cache.isValid(orientedEta);
94+
return cache.isValid(fresnel.getRefractionOrientedEta());
9495
}
9596
};
9697

@@ -135,22 +136,13 @@ struct SCookTorrance
135136
NBL_CONSTEXPR_STATIC_INLINE bool IsBSDF = ndf_type::SupportedPaths != ndf::MTT_REFLECT;
136137
NBL_HLSL_BXDF_ANISOTROPIC_COND_DECLS(IsAnisotropic);
137138

138-
template<class Interaction, class MicrofacetCache>
139-
static bool __checkValid(NBL_CONST_REF_ARG(fresnel_type) f, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache)
140-
{
141-
NBL_IF_CONSTEXPR(IsBSDF)
142-
return impl::check_TIR_helper<fresnel_type, IsBSDF>::template __call<MicrofacetCache>(f, cache);
143-
else
144-
return _sample.getNdotL() > numeric_limits<scalar_type>::min && interaction.getNdotV() > numeric_limits<scalar_type>::min;
145-
}
146-
147139
template<class Interaction=conditional_t<IsAnisotropic,anisotropic_interaction_type,isotropic_interaction_type>,
148140
class MicrofacetCache=conditional_t<IsAnisotropic,anisocache_type,isocache_type>
149141
NBL_FUNC_REQUIRES(RequiredInteraction<Interaction> && RequiredMicrofacetCache<MicrofacetCache>)
150142
spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache)
151143
{
152144
fresnel_type _f = impl::getOrientedFresnel<fresnel_type, IsBSDF>::__call(fresnel, interaction.getNdotV());
153-
if (!__checkValid<Interaction, MicrofacetCache>(_f, _sample, interaction, cache))
145+
if (!impl::checkValid<fresnel_type, IsBSDF>::template __call<sample_type, Interaction, MicrofacetCache>(_f, _sample, interaction, cache))
154146
return hlsl::promote<spectral_type>(0.0);
155147

156148
using quant_query_type = typename ndf_type::quant_query_type;
@@ -279,8 +271,8 @@ struct SCookTorrance
279271

280272
return sample_type::create(L, T, B, NdotL);
281273
}
282-
template<typename C=bool_constant<!IsAnisotropic>, typename T=conditional_t<IsBSDF, vector3_type, vector2_type> >
283-
enable_if_t<C::value && !IsAnisotropic, sample_type> generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const T u, NBL_REF_ARG(isocache_type) cache)
274+
template<typename C=bool_constant<!IsAnisotropic> >
275+
enable_if_t<C::value && !IsAnisotropic, sample_type> generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const conditional_t<IsBSDF, vector3_type, vector2_type> u, NBL_REF_ARG(isocache_type) cache)
284276
{
285277
anisocache_type aniso_cache;
286278
sample_type s = generate(anisotropic_interaction_type::create(interaction), u, aniso_cache);
@@ -315,10 +307,8 @@ struct SCookTorrance
315307
NBL_FUNC_REQUIRES(RequiredInteraction<Interaction> && RequiredMicrofacetCache<MicrofacetCache>)
316308
scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache)
317309
{
318-
fresnel_type _f = fresnel;
319-
NBL_IF_CONSTEXPR(IsBSDF)
320-
_f = impl::getOrientedFresnel<fresnel_type, IsBSDF>::__call(fresnel, interaction.getNdotV());
321-
if (!__checkValid<anisotropic_interaction_type, anisocache_type>(_f, _sample, interaction, cache))
310+
fresnel_type _f = impl::getOrientedFresnel<fresnel_type, IsBSDF>::__call(fresnel, interaction.getNdotV());
311+
if (!impl::checkValid<fresnel_type, IsBSDF>::template __call<sample_type, Interaction, MicrofacetCache>(_f, _sample, interaction, cache))
322312
return scalar_type(0.0);
323313

324314
scalar_type _pdf = __pdf<anisotropic_interaction_type, anisocache_type>(_sample, interaction, cache);
@@ -336,8 +326,8 @@ struct SCookTorrance
336326
scalar_type _pdf = __pdf<Interaction, MicrofacetCache>(_sample, interaction, cache);
337327
fresnel_type _f = impl::getOrientedFresnel<fresnel_type, IsBSDF>::__call(fresnel, interaction.getNdotV());
338328

339-
const bool notTIR = impl::check_TIR_helper<fresnel_type, IsBSDF>::template __call<MicrofacetCache>(_f, cache);
340-
assert(notTIR);
329+
const bool valid = impl::checkValid<fresnel_type, IsBSDF>::template __call<sample_type, Interaction, MicrofacetCache>(_f, _sample, interaction, cache);
330+
assert(valid);
341331

342332
scalar_type G2_over_G1 = scalar_type(1.0);
343333
if (_pdf < bit_cast<scalar_type>(numeric_limits<scalar_type>::infinity))

include/nbl/builtin/hlsl/bxdf/common.hlsl

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ struct SLightSample
491491
#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)
492492
#define NBL_CONCEPT_TPLT_PRM_NAMES (T)
493493
#define NBL_CONCEPT_PARAM_0 (cache, T)
494-
#define NBL_CONCEPT_PARAM_1 (eta, fresnel::OrientedEtas<vector<typename T::scalar_type,1> >)
494+
#define NBL_CONCEPT_PARAM_1 (eta, typename T::scalar_type)
495495
NBL_CONCEPT_BEGIN(2)
496496
#define cache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0
497497
#define eta NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1
@@ -664,8 +664,9 @@ struct SIsotropicMicrofacetCache
664664
// similar with BSDF sampling, as fresnel can be high while reflection can be invalid, or low while refraction would be invalid too
665665
bool isTransmission() NBL_CONST_MEMBER_FUNC { return getVdotHLdotH() < scalar_type(0.0); }
666666

667-
bool isValid(NBL_CONST_REF_ARG(fresnel::OrientedEtas<monochrome_type>) orientedEta) NBL_CONST_MEMBER_FUNC
667+
bool isValid(const scalar_type eta) NBL_CONST_MEMBER_FUNC
668668
{
669+
fresnel::OrientedEtas<monochrome_type> orientedEta = fresnel::OrientedEtas<monochrome_type>::create(scalar_type(1.0), hlsl::promote<monochrome_type>(eta));
669670
return ComputeMicrofacetNormal<scalar_type>::isValidMicrofacet(isTransmission(), VdotL, absNdotH, orientedEta);
670671
}
671672

@@ -849,9 +850,9 @@ struct SAnisotropicMicrofacetCache
849850
scalar_type getNdotH2() NBL_CONST_MEMBER_FUNC { return iso_cache.getNdotH2(); }
850851
bool isTransmission() NBL_CONST_MEMBER_FUNC { return iso_cache.isTransmission(); }
851852

852-
bool isValid(NBL_CONST_REF_ARG(fresnel::OrientedEtas<monochrome_type>) orientedEta) NBL_CONST_MEMBER_FUNC
853+
bool isValid(const scalar_type eta) NBL_CONST_MEMBER_FUNC
853854
{
854-
return iso_cache.isValid(orientedEta);
855+
return iso_cache.isValid(eta);
855856
}
856857

857858
scalar_type getTdotH() NBL_CONST_MEMBER_FUNC { return TdotH; }

include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ struct GGX
273273
dmq.projectedLightMeasure = d * NdotL_over_denominator;
274274
}
275275
else
276-
dmq.projectedLightMeasure = d * _sample.getNdotL(BxDFClampMode::BCM_MAX);
276+
dmq.projectedLightMeasure = d * _sample.getNdotL(BxDFClampMode::BCM_ABS);
277277
return dmq;
278278
}
279279

@@ -282,7 +282,7 @@ struct GGX
282282
{
283283
scalar_type dg1 = scalar_type(0.5) * query.getNdfwoNumerator() * query.getG1over2NdotV();
284284
quant_type dmq;
285-
dmq.microfacetMeasure = dg1; // note: microfacetMeasure/2NdotV
285+
dmq.microfacetMeasure = dg1; // note: microfacetMeasure/4NdotV
286286

287287
NBL_IF_CONSTEXPR(SupportsTransmission)
288288
{
@@ -294,7 +294,7 @@ struct GGX
294294
dmq.projectedLightMeasure = dg1;// TODO: figure this out * NdotL_over_denominator;
295295
}
296296
else
297-
dmq.projectedLightMeasure = dg1;// TODO: figure this out * _sample.getNdotL(BxDFClampMode::BCM_MAX);
297+
dmq.projectedLightMeasure = dg1;// TODO: figure this out * _sample.getNdotL(BxDFClampMode::BCM_ABS);
298298
return dmq;
299299
}
300300

include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,35 @@ enum MicrofacetTransformTypes : uint16_t
2323
MTT_REFLECT_REFRACT = 0b11
2424
};
2525

26+
namespace microfacet_transform_concepts
27+
{
28+
#define NBL_CONCEPT_NAME QuantQuery
29+
#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)
30+
#define NBL_CONCEPT_TPLT_PRM_NAMES (T)
31+
#define NBL_CONCEPT_PARAM_0 (query, T)
32+
NBL_CONCEPT_BEGIN(1)
33+
#define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0
34+
NBL_CONCEPT_END(
35+
((NBL_CONCEPT_REQ_TYPE)(T::scalar_type))
36+
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getVdotHLdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type))
37+
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getNeg_rcp2_VdotH_etaLdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type))
38+
);
39+
#undef query
40+
#include <nbl/builtin/hlsl/concepts/__end.hlsl>
41+
}
42+
2643
template<typename T>
2744
struct DualMeasureQuantQuery
2845
{
29-
using scalar_type = T;
46+
using scalar_type = T;
3047

31-
scalar_type getVdotHLdotH() NBL_CONST_MEMBER_FUNC { return VdotHLdotH; }
32-
scalar_type getNeg_rcp2_VdotH_etaLdotH () NBL_CONST_MEMBER_FUNC { return neg_rcp2_VdotH_etaLdotH ; }
48+
// note in pbrt it's `abs(VdotH)*abs(LdotH)`
49+
// we leverage the fact that under transmission the sign must always be negative and rest of the code already accounts for that
50+
scalar_type getVdotHLdotH() NBL_CONST_MEMBER_FUNC { return VdotHLdotH; }
51+
scalar_type getNeg_rcp2_VdotH_etaLdotH () NBL_CONST_MEMBER_FUNC { return neg_rcp2_VdotH_etaLdotH ; }
3352

34-
scalar_type VdotHLdotH;
35-
scalar_type neg_rcp2_VdotH_etaLdotH;
53+
scalar_type VdotHLdotH;
54+
scalar_type neg_rcp2_VdotH_etaLdotH;
3655
};
3756

3857

0 commit comments

Comments
 (0)