-
Couldn't load subscription status.
- Fork 67
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
…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
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 not take OrientedEta<monochrome_type> ?
| 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
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.
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); |
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 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) |
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.
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)
| 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; |
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.
double check (assert) that this optimized NdotL actually computes to same as actual NdotL computed the slow way
| 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); |
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 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
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.
the reason why we made the whole reflect_refract_wrapper was to skip computing NdotL using worldspace dependant variables.
| 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) |
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.
fresnel rename to orientedFresnel !
| else | ||
| return hlsl::promote<spectral_type>(0.0); |
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 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
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.
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
| 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; | ||
| } |
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.
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); |
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 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)); |
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 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); |
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.
result of refraction should be normalized already when inputs are normalized
Description
Continues #899 , #916 and #919
Testing
TODO list: