88#include "nbl/builtin/hlsl/bxdf/config.hlsl"
99#include "nbl/builtin/hlsl/bxdf/ndf.hlsl"
1010#include "nbl/builtin/hlsl/bxdf/fresnel.hlsl"
11+ #include "nbl/builtin/hlsl/sampling/basic.hlsl"
1112#include "nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl"
1213
1314namespace nbl
@@ -130,19 +131,22 @@ struct SCookTorrance
130131
131132 template<class Interaction=conditional_t<IsAnisotropic,anisotropic_interaction_type,isotropic_interaction_type>,
132133 typename C=bool_constant<!fresnel_type::ReturnsMonochrome> NBL_FUNC_REQUIRES (C::value && !fresnel_type::ReturnsMonochrome)
133- static scalar_type __getScaledReflectance (NBL_CONST_REF_ARG (fresnel_type) orientedFresnel, NBL_CONST_REF_ARG (Interaction) interaction, scalar_type clampedVdotH)
134+ static scalar_type __getScaledReflectance (NBL_CONST_REF_ARG (fresnel_type) orientedFresnel, NBL_CONST_REF_ARG (Interaction) interaction, scalar_type clampedVdotH, bool transmitted, NBL_REF_ARG (spectral_type) outFresnelVal )
134135 {
135136 spectral_type throughputWeights = interaction.getLuminosityContributionHint ();
136- return hlsl::dot<spectral_type>(impl::__implicit_promote<spectral_type, typename fresnel_type::vector_type>::__call (orientedFresnel (clampedVdotH)), throughputWeights);
137+ spectral_type reflectance = orientedFresnel (clampedVdotH);
138+ outFresnelVal = hlsl::mix (reflectance, hlsl::promote<spectral_type>(1.0 )-reflectance, transmitted);
139+ return hlsl::dot<spectral_type>(outFresnelVal, throughputWeights);
137140 }
138141 template<class Interaction=conditional_t<IsAnisotropic,anisotropic_interaction_type,isotropic_interaction_type>,
139142 typename C=bool_constant<fresnel_type::ReturnsMonochrome> NBL_FUNC_REQUIRES (C::value && fresnel_type::ReturnsMonochrome)
140- static scalar_type __getScaledReflectance (NBL_CONST_REF_ARG (fresnel_type) orientedFresnel, NBL_CONST_REF_ARG (Interaction) interaction, scalar_type clampedVdotH)
143+ static scalar_type __getScaledReflectance (NBL_CONST_REF_ARG (fresnel_type) orientedFresnel, NBL_CONST_REF_ARG (Interaction) interaction, scalar_type clampedVdotH, bool transmitted, NBL_REF_ARG (spectral_type) outFresnelVal )
141144 {
142- return orientedFresnel (clampedVdotH)[0 ];
145+ scalar_type reflectance = orientedFresnel (clampedVdotH)[0 ];
146+ return hlsl::mix (reflectance, scalar_type (1.0 )-reflectance, transmitted);
143147 }
144148
145- bool __dotIsUnity (const vector3_type a, const vector3_type b, const scalar_type value)
149+ bool __dotIsValue (const vector3_type a, const vector3_type b, const scalar_type value)
146150 {
147151 const scalar_type ab = hlsl::dot (a, b);
148152 return hlsl::max (ab, value / ab) <= scalar_type (value + 1e-3 );
@@ -209,11 +213,11 @@ struct SCookTorrance
209213 ray_dir_info_type V = interaction.getV ();
210214 const matrix3x3_type fromTangent = interaction.getFromTangentSpace ();
211215 // tangent frame orthonormality
212- assert (__dotIsUnity (fromTangent[0 ],fromTangent[1 ],0.0 ));
213- assert (__dotIsUnity (fromTangent[1 ],fromTangent[2 ],0.0 ));
214- assert (__dotIsUnity (fromTangent[2 ],fromTangent[0 ],0.0 ));
216+ assert (__dotIsValue (fromTangent[0 ],fromTangent[1 ],0.0 ));
217+ assert (__dotIsValue (fromTangent[1 ],fromTangent[2 ],0.0 ));
218+ assert (__dotIsValue (fromTangent[2 ],fromTangent[0 ],0.0 ));
215219 // NDF sampling produced a unit length direction
216- assert (__dotIsUnity (localH,localH,1.0 ));
220+ assert (__dotIsValue (localH,localH,1.0 ));
217221 const vector3_type H = hlsl::mul (interaction.getFromTangentSpace (), localH);
218222 Refract<scalar_type> r = Refract<scalar_type>::create (V.getDirection (), H);
219223
@@ -276,7 +280,7 @@ struct SCookTorrance
276280 const scalar_type NdotV = localV.z;
277281
278282 fresnel_type _f = __getOrientedFresnel (fresnel, NdotV);
279- fresnel::OrientedEtaRcps<monochrome_type> rcpEta = _f.getOrientedEtaRcps ();
283+ fresnel::OrientedEtaRcps<monochrome_type> rcpEta = _f.getRefractionOrientedEtaRcps ();
280284
281285 const vector3_type upperHemisphereV = ieee754::flipSignIfRHSNegative<vector3_type>(localV, hlsl::promote<vector3_type>(NdotV));
282286 const vector3_type localH = ndf.generateH (upperHemisphereV, u.xy);
@@ -294,11 +298,14 @@ struct SCookTorrance
294298 assert (NdotV*VdotH >= scalar_type (0.0 ));
295299 }
296300
297- const scalar_type reflectance = __getScaledReflectance (_f, interaction, hlsl::abs (VdotH));
301+ spectral_type dummy;
302+ const scalar_type reflectance = __getScaledReflectance (_f, interaction, hlsl::abs (VdotH), false , dummy);
298303
299304 scalar_type rcpChoiceProb;
300305 scalar_type z = u.z;
301- bool transmitted = math::partitionRandVariable (reflectance, z, rcpChoiceProb);
306+ sampling::PartitionRandVariable<scalar_type> partitionRandVariable;
307+ partitionRandVariable.leftProb = reflectance;
308+ bool transmitted = partitionRandVariable (z, rcpChoiceProb);
302309
303310 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);
304311 bool valid;
@@ -337,8 +344,9 @@ struct SCookTorrance
337344
338345 NBL_IF_CONSTEXPR (IsBSDF)
339346 {
340- const scalar_type reflectance = __getScaledReflectance (_f, interaction, hlsl::abs (cache.getVdotH ()));
341- return hlsl::mix (reflectance, scalar_type (1.0 ) - reflectance, cache.isTransmission ()) * DG1.projectedLightMeasure;
347+ spectral_type dummy;
348+ const scalar_type reflectance = __getScaledReflectance (_f, interaction, hlsl::abs (cache.getVdotH ()), cache.isTransmission (), dummy);
349+ return reflectance * DG1.projectedLightMeasure;
342350 }
343351 else
344352 {
@@ -389,10 +397,9 @@ struct SCookTorrance
389397 quo = hlsl::promote<spectral_type>(G2_over_G1);
390398 else
391399 {
392- const scalar_type scaled_reflectance = __getScaledReflectance (_f, interaction, hlsl::abs (cache.getVdotH ()));
393- spectral_type reflectance = impl::__implicit_promote<spectral_type, typename fresnel_type::vector_type>::__call (_f (hlsl::abs (cache.getVdotH ())));
394- quo = hlsl::mix (reflectance / scaled_reflectance,
395- (hlsl::promote<spectral_type>(1.0 ) - reflectance) / (scalar_type (1.0 ) - scaled_reflectance), cache.isTransmission ()) * G2_over_G1;
400+ spectral_type reflectance;
401+ const scalar_type scaled_reflectance = __getScaledReflectance (_f, interaction, hlsl::abs (cache.getVdotH ()), cache.isTransmission (), reflectance);
402+ quo = reflectance / scaled_reflectance * G2_over_G1;
396403 }
397404 }
398405 else
@@ -409,6 +416,18 @@ struct SCookTorrance
409416 fresnel_type fresnel; // always front-facing
410417};
411418
419+
420+ template<class Config, class N, class F>
421+ struct traits<SCookTorrance<Config,N,F> >
422+ {
423+ using __type = SCookTorrance<Config,N,F>;
424+
425+ NBL_CONSTEXPR_STATIC_INLINE BxDFType type = conditional_value<__type::IsBSDF, BxDFType, BxDFType::BT_BSDF, BxDFType::BT_BRDF>::value;
426+ NBL_CONSTEXPR_STATIC_INLINE bool IsMicrofacet = true ;
427+ NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = !__type::IsBSDF;
428+ NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = !__type::IsBSDF;
429+ };
430+
412431}
413432}
414433}
0 commit comments