@@ -77,7 +77,7 @@ struct checkValid<F, false>
7777 using scalar_type = typename F::scalar_type;
7878
7979 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)
80+ static bool __call (NBL_CONST_REF_ARG (F) orientedFresnel , NBL_CONST_REF_ARG (Sample) _sample, NBL_CONST_REF_ARG (Interaction) interaction, NBL_CONST_REF_ARG (MicrofacetCache) cache)
8181 {
8282 return _sample.getNdotL () > numeric_limits<scalar_type>::min && interaction.getNdotV () > numeric_limits<scalar_type>::min ;
8383 }
@@ -86,12 +86,14 @@ struct checkValid<F, false>
8686template<class F>
8787struct checkValid<F, true >
8888{
89+ using scalar_type = typename F::scalar_type;
8990 using vector_type = typename F::vector_type; // expect monochrome
9091
9192 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)
93+ static bool __call (NBL_CONST_REF_ARG (F) orientedFresnel , NBL_CONST_REF_ARG (Sample) _sample, NBL_CONST_REF_ARG (Interaction) interaction, NBL_CONST_REF_ARG (MicrofacetCache) cache)
9394 {
94- return cache.isValid (fresnel.getRefractionOrientedEta ());
95+ fresnel::OrientedEtas<vector_type> orientedEta = fresnel::OrientedEtas<vector_type>::create (scalar_type (1.0 ), hlsl::promote<vector_type>(orientedFresnel.getRefractionOrientedEta ()));
96+ return cache.isValid (orientedEta);
9597 }
9698};
9799
@@ -268,12 +270,7 @@ struct SCookTorrance
268270 scalar_type rcpChoiceProb;
269271 scalar_type z = u.z;
270272 bool transmitted = math::partitionRandVariable (reflectance, z, rcpChoiceProb);
271-
272- ray_dir_info_type V = interaction.getV ();
273- const vector3_type H = hlsl::mul (interaction.getFromTangentSpace (), localH);
274- assert (hlsl::abs (hlsl::length (H) - scalar_type (1.0 )) < scalar_type (1e-4 ));
275- Refract<scalar_type> r = Refract<scalar_type>::create (V.getDirection (), H);
276- const scalar_type LdotH = hlsl::mix (VdotH, r.getNdotT (rcpEta.value2[0 ]), transmitted);
273+ const scalar_type LdotH = hlsl::mix (VdotH, ieee754::copySign (hlsl::sqrt (rcpEta.value2[0 ]*VdotH*VdotH + scalar_type (1.0 ) - rcpEta.value2[0 ]), -VdotH), transmitted);
277274
278275 // fail if samples have invalid paths
279276 const scalar_type NdotL = hlsl::mix (scalar_type (2.0 ) * VdotH * localH.z - NdotV,
@@ -284,7 +281,12 @@ struct SCookTorrance
284281 return sample_type::createInvalid (); // should check if sample direction is invalid
285282
286283 cache = anisocache_type::createPartial (VdotH, LdotH, localH.z, transmitted, rcpEta);
287- assert (cache.isValid (_f.getRefractionOrientedEta ()));
284+ assert (cache.isValid (fresnel::OrientedEtas<vector_type>::create (scalar_type (1.0 ), hlsl::promote<vector_type>(_f.getRefractionOrientedEta ()))));
285+
286+ ray_dir_info_type V = interaction.getV ();
287+ const vector3_type H = hlsl::mul (interaction.getFromTangentSpace (), localH);
288+ assert (hlsl::abs (hlsl::length (H) - scalar_type (1.0 )) < scalar_type (1e-4 ));
289+ Refract<scalar_type> r = Refract<scalar_type>::create (V.getDirection (), H);
288290
289291 struct reflect_refract_wrapper // so we don't recalculate LdotH
290292 {
@@ -364,7 +366,7 @@ struct SCookTorrance
364366 fresnel_type _f = impl::getOrientedFresnel<fresnel_type, IsBSDF>::__call (fresnel, interaction.getNdotV ());
365367
366368 const bool valid = impl::checkValid<fresnel_type, IsBSDF>::template __call<sample_type, Interaction, MicrofacetCache>(_f, _sample, interaction, cache);
367- assert (valid);
369+ assert (valid); // expect the generated sample to always be valid, different checks for brdf and btdf
368370
369371 scalar_type G2_over_G1 = scalar_type (1.0 );
370372 if (_pdf < bit_cast<scalar_type>(numeric_limits<scalar_type>::infinity))
0 commit comments