Skip to content

Conversation

@devshgraphicsprogramming
Copy link
Member

@devshgraphicsprogramming devshgraphicsprogramming commented Sep 16, 2025

Description

Continues #899 , #916 and #919

Testing

TODO list:

Comment on lines 667 to 669
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));
Copy link
Member Author

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

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not take OrientedEta<monochrome_type> ?

Comment on lines 853 to 855
bool isValid(const scalar_type eta) NBL_CONST_MEMBER_FUNC
{
return iso_cache.isValid(orientedEta);
return iso_cache.isValid(eta);
Copy link
Member Author

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

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its super misleading to call orientedEta into eta now, it makes one think that it doesn't depend on NdotV

assert(notTIR);
const bool valid = impl::checkValid<fresnel_type, IsBSDF>::template __call<sample_type, Interaction, MicrofacetCache>(_f, _sample, interaction, cache);
assert(valid);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a comment qhy

}

template<typename C=bool_constant<!IsBSDF> >
enable_if_t<C::value && !IsBSDF, sample_type> generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NBL_FUNC_REQuirES is better syntax than the enable_if

btw why do you still have two generate ? where you could have a const conditional_t<IsBSDF,vector3_type,vector2_type> u

Continues: #930 (comment)

Comment on lines 268 to 269
const scalar_type viewShortenFactor = hlsl::mix(scalar_type(1.0), rcpEta.value[0], transmitted);
const scalar_type NdotL = localH.z * (VdotH * viewShortenFactor + LdotH) - NdotV * viewShortenFactor;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

double check (assert) that this optimized NdotL actually computes to same as actual NdotL computed the slow way

Comment on lines 263 to 265
const vector3_type H = hlsl::mul(interaction.getFromTangentSpace(), localH);
Refract<scalar_type> r = Refract<scalar_type>::create(V.getDirection(), H);
const scalar_type LdotH = hlsl::mix(VdotH, r.getNdotT(rcpEta.value2[0]), transmitted);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you want to compute your own getNdotT (LdotH ) so you don't need the worldspace H and V until you already clear the isTransmissionPath check

That also lets you compute NdotL without using any world-space inputs

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the reason why we made the whole reflect_refract_wrapper was to skip computing NdotL using worldspace dependant variables.

Comment on lines 80 to 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)
{
return true;
return _sample.getNdotL() > numeric_limits<scalar_type>::min && interaction.getNdotV() > numeric_limits<scalar_type>::min;
}
};

template<class F>
struct check_TIR_helper<F, true>
struct checkValid<F, true>
{
using vector_type = typename F::vector_type; // expect monochrome

template<class MicrofacetCache>
static bool __call(NBL_CONST_REF_ARG(F) fresnel, NBL_CONST_REF_ARG(MicrofacetCache) cache)
template<class Sample, class Interaction, class MicrofacetCache>
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)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fresnel rename to orientedFresnel !

Comment on lines +179 to +180
else
return hlsl::promote<spectral_type>(0.0);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you cannot have this else if you want the compiler to throw away calls to ndf.template D

you need to add an if (DG>max_value) return 0.0; AFTER the overwrite_DG

Copy link
Member Author

@devshgraphicsprogramming devshgraphicsprogramming Oct 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

another way is to add that sidechannel NBL_REF(bool) on the D and Dcorrelated functions which tells us if PDF is inf for this sample

Comment on lines +132 to +141
template<typename C=bool_constant<!HasOverwrite> >
static enable_if_t<C::value && !HasOverwrite, void> __call(NBL_REF_ARG(scalar_type) DG, N ndf, 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)
{
}
template<typename C=bool_constant<HasOverwrite> >
static enable_if_t<C::value && HasOverwrite, void> __call(NBL_REF_ARG(scalar_type) DG, N ndf, 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)
{
quant_type dg = ndf.template Dcorrelated<LS, Interaction, MicrofacetCache>(query, quant_query, _sample, interaction, cache);
DG = dg.projectedLightMeasure;
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool, but if you're gonna do it this way, you could even stick the methods in SCookTorrance which would save you a lot of typedef aliases

which kinda gives me an idea that all the impl functors could be done and hidden this way

if (dg < bit_cast<scalar_type>(numeric_limits<scalar_type>::infinity))
dg *= correlated_wo_numerator<LS, Interaction>(query, _sample, interaction);
else
dg = scalar_type(0.0);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can already return 0,0 for both and call it a day

const scalar_type NdotL = localH.z * (VdotH * viewShortenFactor + LdotH) - NdotV * viewShortenFactor;
// VNDF sampling guarantees that `VdotH` has same sign as `NdotV`
// and `transmitted` controls the sign of `LdotH` relative to `VdotH` by construction (reflect -> same sign, or refract -> opposite sign)
const vector3_type H = hlsl::normalize(hlsl::mul(interaction.getFromTangentSpace(), localH));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should assert the length of H is already near 1 and the matrix is orthonormal

bxdf::ReflectRefract<scalar_type> rr;
rr.refract = r;
L = V.reflectRefract(rr, transmitted, rcpEta.value[0]);
L.direction = hlsl::normalize(L.direction);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

result of refraction should be normalized already when inputs are normalized

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants