-
Notifications
You must be signed in to change notification settings - Fork 66
Bxdf fixes cook torrance #930
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
template<typename C=bool_constant<!IsAnisotropic>, typename T=conditional_t<IsBSDF, vector3_type, vector2_type> > | ||
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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can use conditional_t
directly in a function signature, there's no need to add another template parameter T
P.S. also try to use NBL_FUNC_REQUIRES instead of the enable_if_t
fresnel_type _f = fresnel; | ||
NBL_IF_CONSTEXPR(IsBSDF) | ||
_f = impl::getOrientedFresnel<fresnel_type, IsBSDF>::__call(fresnel, interaction.getNdotV()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
either don't passIsBSDF
to impl::getOrientedFresnel
or skip the NBL_IF_CONSTEXPR
spectral_type quo = hlsl::promote<spectral_type>(0.0); | ||
const bool notTIR = impl::check_TIR_helper<fresnel_type, IsBSDF>::template __call<MicrofacetCache>(_f, cache); | ||
if (notTIR) | ||
assert(notTIR); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add a comment why
include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl
Outdated
Show resolved
Hide resolved
include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl
Outdated
Show resolved
Hide resolved
dmq.microfacetMeasure = dg1; | ||
dmq.projectedLightMeasure = dg1;// TODO: figure this out * _sample.getNdotL(BxDFClampMode::BCM_MAX); | ||
return dmq; | ||
} | ||
template<class LS, class Interaction, typename C=bool_constant<IsBSDF> NBL_FUNC_REQUIRES(LightSample<LS> && RequiredInteraction<Interaction>) | ||
enable_if_t<C::value && IsBSDF, 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_type::template DG1<dg1_query_type>(query); | ||
quant_type dmq; | ||
dmq.microfacetMeasure = dg1; // note: microfacetMeasure/2NdotV |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if your base DG1
returns something else than actual DG1 like DG1_over_4NdotV
, then it should be called DG1_over_4NdotV
then you assign straight to projectedLightMeasure
in the reflective case and properly multiply the 4*NdotV
back in for the microfacetMeasure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ideally you should really just return DG1_over_2NdotV
cause extra 0.5 mul is kinda pointless inside
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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for the projectedLightMeasure
transmittance you'd just do mix(0.5,2.0,transmitted)*DG1_over_2NdotV
and then
if (transmitted)
dmq.projectedLightMeasure *= VdotHLdotH*neg_rcp2_VdotH_etaLdotH;
dmq.microfacetMeasure *= 2.0*clampedNdotV;
template<class LS, class Interaction, class MicrofacetCache, typename C=bool_constant<!IsBSDF> NBL_FUNC_REQUIRES(LightSample<LS> && RequiredInteraction<Interaction> && RequiredMicrofacetCache<MicrofacetCache>) | ||
enable_if_t<C::value && !IsBSDF, 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 = __ndf_base.template D<MicrofacetCache>(cache); | ||
quant_type dmq; | ||
dmq.microfacetMeasure = d; | ||
dmq.projectedLightMeasure = d * _sample.getNdotL(BxDFClampMode::BCM_MAX); | ||
return dmq; | ||
} | ||
template<class LS, class Interaction, class MicrofacetCache, typename C=bool_constant<IsBSDF> NBL_FUNC_REQUIRES(LightSample<LS> && RequiredInteraction<Interaction> && RequiredMicrofacetCache<MicrofacetCache>) | ||
enable_if_t<C::value && IsBSDF, 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 = __ndf_base.template D<MicrofacetCache>(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; | ||
return dmq; | ||
} | ||
|
||
template<class LS, class Interaction, typename C=bool_constant<!IsBSDF> NBL_FUNC_REQUIRES(LightSample<LS> && RequiredInteraction<Interaction>) | ||
enable_if_t<C::value && !IsBSDF, 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_type::template DG1<dg1_query_type>(query); | ||
quant_type dmq; | ||
dmq.microfacetMeasure = dg1; | ||
dmq.projectedLightMeasure = dg1;// TODO: figure this out * _sample.getNdotL(BxDFClampMode::BCM_MAX); | ||
return dmq; | ||
} | ||
template<class LS, class Interaction, typename C=bool_constant<IsBSDF> NBL_FUNC_REQUIRES(LightSample<LS> && RequiredInteraction<Interaction>) | ||
enable_if_t<C::value && IsBSDF, 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_type::template DG1<dg1_query_type>(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; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This stuff maybe we can rethink, I'd be tempted to allow an NDF "skip" providing D
and correlated
if it has both the DG1
and Dcorrelated
methods (so the cook torrance can leverage that and skip multiplying D
with correlated
by itself for eval
)
NBL_CONSTEXPR_STATIC_INLINE bool IsBSDF = ndf_type::NDFSurfaceType != ndf::MTT_REFLECT; | ||
|
||
template<class Interaction, class MicrofacetCache> | ||
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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why make static
and pass the f
if its your member?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it because the fresnel is already properly oriented? then give f
a clear name like reorientedFresnel
and since its static
you may as well make the __checkValid
into a standalone struct functor with a partial spec on IsBSDF
, that way you don't call impl::check_TIR_helper
but you can call cache.isValid(reorientedFresnel.getRefractionOrientedEta())
directly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually if you use impl::checkValid<IsBSDF>::template __call()
here
Nabla/include/nbl/builtin/hlsl/bxdf/base/cook_torrance_base.hlsl
Lines 350 to 351 in dcc2464
const bool notTIR = impl::check_TIR_helper<fresnel_type, IsBSDF>::template __call<MicrofacetCache>(_f, cache); | |
assert(notTIR); |
then there's no need to have an impl::check_TIR_helper
at all
else | ||
dmq.projectedLightMeasure = d * _sample.getNdotL(BxDFClampMode::BCM_MAX); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
btw you can always use ABS, because it should be the callee's job to not call you on backfacing BRDF if it chooses to
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is just the NDF
…cache with defaults
bool isValid(const scalar_type eta) NBL_CONST_MEMBER_FUNC | ||
{ | ||
fresnel::OrientedEtas<monochrome_type> orientedEta = fresnel::OrientedEtas<monochrome_type>::create(scalar_type(1.0), hlsl::promote<monochrome_type>(eta)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't get what you're doing here
bool isValid(const scalar_type eta) NBL_CONST_MEMBER_FUNC | ||
{ | ||
return iso_cache.isValid(orientedEta); | ||
return iso_cache.isValid(eta); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't get whats going on here
const scalar_type viewShortenFactor = hlsl::mix(scalar_type(1.0), rcpOrientedEta.value[0], transmitted); | ||
retval.iso_cache.VdotL = VdotH * (VdotH * viewShortenFactor + LdotH) - viewShortenFactor; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
even though I gave you this, it might be invalid.
refl -> VdotH*(VdotH+LdotH) - 1 = 2*VdotH^2 -1
trans -> VdotH*(VdotH/eta+LdotH) - 1/eta != VdotH^2/eta - VdotH/eta + VdotH*LdotH
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeh its messed up.
Need to bring back the original with one slight opt
retval.iso_cache.VdotL = VdotH * hlsl::mix(
scalar_type(2.0) * VdotH - scalar_type(1.0),
VdotH * rcpOrientedEta.value[0] + LdotH - rcpOrientedEta.value[0],
transmitted
);
Description
Continues #899 , #916 and #919
Testing
TODO list: