From 34ee35ccc08a310c13f25e8940d34ca78ba303bb Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 25 Nov 2024 17:05:01 +0700 Subject: [PATCH 001/188] some test bxdfs using concepts and templates --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 691 ++++++++++++---------- 1 file changed, 366 insertions(+), 325 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index c6e8679d3b..31e01aca64 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -19,26 +19,49 @@ namespace bxdf namespace ray_dir_info { +#define NBL_CONCEPT_NAME Basic +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (U)(T) +#define NBL_CONCEPT_PARAM_0 (a,U) +#define NBL_CONCEPT_PARAM_1 (N,vector) +#define NBL_CONCEPT_PARAM_2 (dir,T) +NBL_CONCEPT_BEGIN(3) +#define a NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +#define N NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 +#define dir NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +NBL_CONCEPT_END( + // add check for T is_scalar_v ? + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((a.getDirection()), ::nbl::hlsl::is_same_v, vector)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((a.transmit()), ::nbl::hlsl::is_same_v, U)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((a.reflect(N, dir)), ::nbl::hlsl::is_same_v, U)) +); +#undef dir +#undef N +#undef a +#include + // no ray-differentials, nothing -struct Basic +template +struct SBasic { - float3 getDirection() {return direction;} - - Basic transmit() - { - Basic retval; - retval.direction = -direction; - return retval; - } - - Basic reflect(const float3 N, const float directionDotN) - { - Basic retval; - retval.direction = nbl::hlsl::reflect(direction,N,directionDotN); - return retval; - } - - float3 direction; + using vector_t = vector; + vector_t getDirection() { return direction; } + + SBasic transmit() + { + SBasic retval; + retval.direction = -direction; + return retval; + } + + SBasic reflect(const float3 N, const float directionDotN) + { + SBasic retval; + retval.direction = nbl::hlsl::reflect(direction,N,directionDotN); + return retval; + } + + vector_t direction; }; // more to come! @@ -48,67 +71,85 @@ struct Basic namespace surface_interactions { -template -struct Isotropic +#define NBL_CONCEPT_NAME Isotropic // doesn't work yet +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename)(typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (U)(B)(T) // B should be of type Basic +#define NBL_CONCEPT_PARAM_0 (a,U) +#define NBL_CONCEPT_PARAM_1 (V,ray_dir_info::SBasic) +#define NBL_CONCEPT_PARAM_2 (N,vector) +NBL_CONCEPT_BEGIN(1) +#define a NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +#define N NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 +#define V NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((U::create(V,N)), ::nbl::hlsl::is_same_v, U)) +); +#undef V +#undef N +#undef a +#include + +template) // another typename T for RayDirInfo ? +struct SIsotropic { - // WARNING: Changed since GLSL, now arguments need to be normalized! - static Isotropic create(const RayDirInfo normalizedV, const float3 normalizedN) - { - Isotropic retval; - retval.V = normalizedV; - retval.N = normalizedN; - - retval.NdotV = dot(retval.N,retval.V.getDirection()); - retval.NdotV_squared = retval.NdotV*retval.NdotV; - - return retval; - } - - RayDirInfo V; - float3 N; - float NdotV; - float NdotV2; // old NdotV_squared + // WARNING: Changed since GLSL, now arguments need to be normalized! + static SIsotropic create(NBL_CONST_REF_ARG(RayDirInfo) normalizedV, const float3 normalizedN) + { + SIsotropic retval; + retval.V = normalizedV; + retval.N = normalizedN; + + retval.NdotV = dot(retval.N, retval.V.getDirection()); + retval.NdotV_squared = retval.NdotV * retval.NdotV; + + return retval; + } + + RayDirInfo V; + float3 N; + float NdotV; + float NdotV2; // old NdotV_squared }; template struct Anisotropic : Isotropic { - // WARNING: Changed since GLSL, now arguments need to be normalized! - static Anisotropic create( - const Isotropic isotropic, - const float3 normalizedT, - const float normalizedB - ) - { - Anisotropic retval; - retval::Isotropic = isotropic; - retval.T = normalizedT; - retval.B = normalizedB; - - const float3 V = retval.getDirection(); - retval.TdotV = dot(V,retval.T); - retval.BdotV = dot(V,retval.B); - - return retval; - } - static Anisotropic create(const Isotropic isotropic, const float3 normalizedT) - { - return create(isotropic,normalizedT,cross(isotropic.N,normalizedT)); - } - static Anisotropic create(const Isotropic isotropic) - { - float2x3 TB = nbl::hlsl::frisvad(isotropic.N); - return create(isotropic,TB[0],TB[1]); - } - - float3 getTangentSpaceV() {return float3(Tdot,BdotV,Isotropic::NdotV);} - // WARNING: its the transpose of the old GLSL function return value! - float3x3 getTangentFrame() {return float3x3(T,B,Isotropic::N);} - - float3 T; - float3 B; - float3 TdotV; - float3 BdotV; + // WARNING: Changed since GLSL, now arguments need to be normalized! + static Anisotropic create( + const Isotropic isotropic, + const float3 normalizedT, + const float normalizedB + ) + { + Anisotropic retval; + retval::Isotropic = isotropic; + retval.T = normalizedT; + retval.B = normalizedB; + + const float3 V = retval.getDirection(); + retval.TdotV = dot(V,retval.T); + retval.BdotV = dot(V,retval.B); + + return retval; + } + static Anisotropic create(const Isotropic isotropic, const float3 normalizedT) + { + return create(isotropic,normalizedT,cross(isotropic.N,normalizedT)); + } + static Anisotropic create(const Isotropic isotropic) + { + float2x3 TB = nbl::hlsl::frisvad(isotropic.N); + return create(isotropic,TB[0],TB[1]); + } + + float3 getTangentSpaceV() {return float3(Tdot,BdotV,Isotropic::NdotV);} + // WARNING: its the transpose of the old GLSL function return value! + float3x3 getTangentFrame() {return float3x3(T,B,Isotropic::N);} + + float3 T; + float3 B; + float3 TdotV; + float3 BdotV; }; } @@ -117,265 +158,265 @@ struct Anisotropic : Isotropic template struct LightSample { - static LightSample createTangentSpace( - const float3 tangentSpaceV, - const RayDirInfo tangentSpaceL, - const float3x3 tangentFrame // WARNING: its the transpose of the old GLSL function return value! - ) - { - LightSample retval; - - retval.L = RayDirInfo::transform(tangentSpaceL,tangentFrame); - retval.VdotL = dot(tangentSpaceV,tangentSpaceL); + static LightSample createTangentSpace( + const float3 tangentSpaceV, + const RayDirInfo tangentSpaceL, + const float3x3 tangentFrame // WARNING: its the transpose of the old GLSL function return value! + ) + { + LightSample retval; + + retval.L = RayDirInfo::transform(tangentSpaceL,tangentFrame); + retval.VdotL = dot(tangentSpaceV,tangentSpaceL); + + retval.TdotL = tangentSpaceL.x; + retval.BdotL = tangentSpaceL.y; + retval.NdotL = tangentSpaceL.z; + retval.NdotL2 = retval.NdotL*retval.NdotL; + + return retval; + } + static LightSample create(const RayDirInfo L, const float VdotL, const float3 N) + { + LightSample retval; + + retval.L = L; + retval.VdotL = VdotL; + + retval.TdotL = nbl::hlsl::numeric_limits::nan(); + retval.BdotL = nbl::hlsl::numeric_limits::nan(); + retval.NdotL = dot(N,L); + retval.NdotL2 = retval.NdotL*retval.NdotL; + + return retval; + } + static LightSample create(const RayDirInfo L, const float VdotL, const float3 T, const float3 B, const float3 N) + { + LightSample retval = create(L,VdotL,N); + + retval.TdotL = dot(T,L); + retval.BdotL = dot(B,L); + + return retval; + } + // overloads for surface_interactions + template + static LightSample create(const float3 L, const surface_interactions::Isotropic interaction) + { + const float3 V = interaction.V.getDirection(); + const float VdotL = dot(V,L); + return create(L,VdotL,interaction.N); + } + template + static LightSample create(const float3 L, const surface_interactions::Anisotropic interaction) + { + const float3 V = interaction.V.getDirection(); + const float VdotL = dot(V,L); + return create(L,VdotL,interaction.T,interaction.B,interaction.N); + } + // + float3 getTangentSpaceL() + { + return float3(TdotL,BdotL,NdotL); + } - retval.TdotL = tangentSpaceL.x; - retval.BdotL = tangentSpaceL.y; - retval.NdotL = tangentSpaceL.z; - retval.NdotL2 = retval.NdotL*retval.NdotL; - - return retval; - } - static LightSample create(const RayDirInfo L, const float VdotL, const float3 N) - { - LightSample retval; - - retval.L = L; - retval.VdotL = VdotL; + RayDirInfo L; + float VdotL; - retval.TdotL = nbl::hlsl::numeric_limits::nan(); - retval.BdotL = nbl::hlsl::numeric_limits::nan(); - retval.NdotL = dot(N,L); - retval.NdotL2 = retval.NdotL*retval.NdotL; - - return retval; - } - static LightSample create(const RayDirInfo L, const float VdotL, const float3 T, const float3 B, const float3 N) - { - LightSample retval = create(L,VdotL,N); - - retval.TdotL = dot(T,L); - retval.BdotL = dot(B,L); - - return retval; - } - // overloads for surface_interactions - template - static LightSample create(const float3 L, const surface_interactions::Isotropic interaction) - { - const float3 V = interaction.V.getDirection(); - const float VdotL = dot(V,L); - return create(L,VdotL,interaction.N); - } - template - static LightSample create(const float3 L, const surface_interactions::Anisotropic interaction) - { - const float3 V = interaction.V.getDirection(); - const float VdotL = dot(V,L); - return create(L,VdotL,interaction.T,interaction.B,interaction.N); - } - // - float3 getTangentSpaceL() - { - return float3(TdotL,BdotL,NdotL); - } - - RayDirInfo L; - float VdotL; - - float TdotL; - float BdotL; - float NdotL; - float NdotL2; + float TdotL; + float BdotL; + float NdotL; + float NdotL2; }; // struct IsotropicMicrofacetCache { - // always valid because its specialized for the reflective case - static IsotropicMicrofacetCache createForReflection(const float NdotV, const float NdotL, const float VdotL, out float LplusV_rcpLen) - { - LplusV_rcpLen = inversesqrt(2.0+2.0*VdotL); + // always valid because its specialized for the reflective case + static IsotropicMicrofacetCache createForReflection(const float NdotV, const float NdotL, const float VdotL, out float LplusV_rcpLen) + { + LplusV_rcpLen = inversesqrt(2.0+2.0*VdotL); + + IsotropicMicrofacetCache retval; + + retval.VdotH = LplusV_rcpLen*VdotL+LplusV_rcpLen; + retval.LdotH = retval.VdotH; + retval.NdotH = (NdotL+NdotV)*LplusV_rcpLen; + retval.NdotH2 = retval.NdotH*retval.NdotH; + + return retval; + } + static IsotropicMicrofacetCache createForReflection(const float NdotV, const float NdotL, const float VdotL) + { + float dummy; + return createForReflection(NdotV,NdotL,VdotL,dummy); + } + template + static IsotropicMicrofacetCache createForReflection( + const surface_interactions::Isotropic interaction, + const LightSample _sample) + { + return createForReflection(interaction.NdotV,_sample.NdotL,_sample.VdotL); + } + // transmissive cases need to be checked if the path is valid before usage + static bool compute( + out IsotropicMicrofacetCache retval, + const bool transmitted, const float3 V, const float3 L, + const float3 N, const float NdotL, const float VdotL, + const float orientedEta, const float rcpOrientedEta, out float3 H + ) + { + // TODO: can we optimize? + H = computeMicrofacetNormal(transmitted,V,L,orientedEta); + retval.NdotH = dot(N,H); + + // not coming from the medium (reflected) OR + // exiting at the macro scale AND ( (not L outside the cone of possible directions given IoR with constraint VdotH*LdotH<0.0) OR (microfacet not facing toward the macrosurface, i.e. non heightfield profile of microsurface) ) + const bool valid = !transmitted || (VdotL<=-min(orientedEta,rcpOrientedEta) && _cache.NdotH>nbl::hlsl::numeric_limits::min()); + if (valid) + { + // TODO: can we optimize? + retval.VdotH = dot(V,H); + retval.LdotH = dot(L,H); + retval.NdotH2 = retval.NdotH*retval.NdotH; + return true; + } + return false; + } + template + static bool compute( + out IsotropicMicrofacetCache retval, + const surface_interactions::Isotropic interaction, + const LightSample _sample, + const float eta, out float3 H + ) + { + const float NdotV = interaction.NdotV; + const float NdotL = _sample.NdotL; + const bool transmitted = nbl_glsl_isTransmissionPath(NdotV,NdotL); + + float orientedEta, rcpOrientedEta; + const bool backside = nbl_glsl_getOrientedEtas(orientedEta,rcpOrientedEta,NdotV,eta); + + const vec3 V = interaction.V.getDirection(); + const vec3 L = _sample.L; + const float VdotL = dot(V,L); + return nbl_glsl_calcIsotropicMicrofacetCache(_cache,transmitted,V,L,interaction.N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); + } + template + static bool compute( + out IsotropicMicrofacetCache retval, + const surface_interactions::Isotropic interaction, + const LightSample _sample, + const float eta + ) + { + float3 dummy; + return nbl_glsl_calcIsotropicMicrofacetCache(_cache,transmitted,V,L,interaction.N,NdotL,VdotL,orientedEta,rcpOrientedEta,dummy); + } - IsotropicMicrofacetCache retval; - - retval.VdotH = LplusV_rcpLen*VdotL+LplusV_rcpLen; - retval.LdotH = retval.VdotH; - retval.NdotH = (NdotL+NdotV)*LplusV_rcpLen; - retval.NdotH2 = retval.NdotH*retval.NdotH; - - return retval; - } - static IsotropicMicrofacetCache createForReflection(const float NdotV, const float NdotL, const float VdotL) - { - float dummy; - return createForReflection(NdotV,NdotL,VdotL,dummy); - } - template - static IsotropicMicrofacetCache createForReflection( - const surface_interactions::Isotropic interaction, - const LightSample _sample) - { - return createForReflection(interaction.NdotV,_sample.NdotL,_sample.VdotL); - } - // transmissive cases need to be checked if the path is valid before usage - static bool compute( - out IsotropicMicrofacetCache retval, - const bool transmitted, const float3 V, const float3 L, - const float3 N, const float NdotL, const float VdotL, - const float orientedEta, const float rcpOrientedEta, out float3 H - ) - { - // TODO: can we optimize? - H = computeMicrofacetNormal(transmitted,V,L,orientedEta); - retval.NdotH = dot(N,H); - - // not coming from the medium (reflected) OR - // exiting at the macro scale AND ( (not L outside the cone of possible directions given IoR with constraint VdotH*LdotH<0.0) OR (microfacet not facing toward the macrosurface, i.e. non heightfield profile of microsurface) ) - const bool valid = !transmitted || (VdotL<=-min(orientedEta,rcpOrientedEta) && _cache.NdotH>nbl::hlsl::numeric_limits::min()); - if (valid) + bool isValidVNDFMicrofacet(const bool is_bsdf, const bool transmission, const float VdotL, const float eta, const float rcp_eta) { - // TODO: can we optimize? - retval.VdotH = dot(V,H); - retval.LdotH = dot(L,H); - retval.NdotH2 = retval.NdotH*retval.NdotH; - return true; + return NdotH >= 0.0 && !(is_bsdf && transmission && (VdotL > -min(eta,rcp_eta))); } - return false; - } - template - static bool compute( - out IsotropicMicrofacetCache retval, - const surface_interactions::Isotropic interaction, - const LightSample _sample, - const float eta, out float3 H - ) - { - const float NdotV = interaction.NdotV; - const float NdotL = _sample.NdotL; - const bool transmitted = nbl_glsl_isTransmissionPath(NdotV,NdotL); - - float orientedEta, rcpOrientedEta; - const bool backside = nbl_glsl_getOrientedEtas(orientedEta,rcpOrientedEta,NdotV,eta); - - const vec3 V = interaction.V.getDirection(); - const vec3 L = _sample.L; - const float VdotL = dot(V,L); - return nbl_glsl_calcIsotropicMicrofacetCache(_cache,transmitted,V,L,interaction.N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); - } - template - static bool compute( - out IsotropicMicrofacetCache retval, - const surface_interactions::Isotropic interaction, - const LightSample _sample, - const float eta - ) - { - float3 dummy; - return nbl_glsl_calcIsotropicMicrofacetCache(_cache,transmitted,V,L,interaction.N,NdotL,VdotL,orientedEta,rcpOrientedEta,dummy); - } - - bool isValidVNDFMicrofacet(const bool is_bsdf, const bool transmission, const float VdotL, const float eta, const float rcp_eta) - { - return NdotH >= 0.0 && !(is_bsdf && transmission && (VdotL > -min(eta,rcp_eta))); - } - - float VdotH; - float LdotH; - float NdotH; - float NdotH2; + + float VdotH; + float LdotH; + float NdotH; + float NdotH2; }; struct AnisotropicMicrofacetCache : IsotropicMicrofacetCache { - // always valid by construction - static AnisotropicMicrofacetCache create(const float3 tangentSpaceV, const float3 tangentSpaceH) - { - AnisotropicMicrofacetCache retval; - - retval.VdotH = dot(tangentSpaceV,tangentSpaceH); - retval.LdotH = retval.VdotH; - retval.NdotH = tangentSpaceH.z; - retval.NdotH2 = retval.NdotH*retval.NdotH; - retval.TdotH = tangentSpaceH.x; - retval.BdotH = tangentSpaceH.y; - - return retval; - } - static AnisotropicMicrofacetCache create( - const float3 tangentSpaceV, - const float3 tangentSpaceH, - const bool transmitted, - const float rcpOrientedEta, - const float rcpOrientedEta2 - ) - { - AnisotropicMicrofacetCache retval = create(tangentSpaceV,tangentSpaceH); - if (transmitted) + // always valid by construction + static AnisotropicMicrofacetCache create(const float3 tangentSpaceV, const float3 tangentSpaceH) { - const float VdotH = retval.VdotH; - LdotH = transmitted ? refract_compute_NdotT(VdotH<0.0,VdotH*VdotH,rcpOrientedEta2); + AnisotropicMicrofacetCache retval; + + retval.VdotH = dot(tangentSpaceV,tangentSpaceH); + retval.LdotH = retval.VdotH; + retval.NdotH = tangentSpaceH.z; + retval.NdotH2 = retval.NdotH*retval.NdotH; + retval.TdotH = tangentSpaceH.x; + retval.BdotH = tangentSpaceH.y; + + return retval; } - - return retval; - } - // always valid because its specialized for the reflective case - static AnisotropicMicrofacetCache createForReflection(const float3 tangentSpaceV, const float3 tangentSpaceL, const float VdotL) - { - AnisotropicMicrofacetCache retval; - - float LplusV_rcpLen; - retval = createForReflection(tangentSpaceV.z,tangentSpaceL.z,VdotL,LplusV_rcpLen); - retval.TdotH = (tangentSpaceV.x+tangentSpaceL.x)*LplusV_rcpLen; - retval.BdotH = (tangentSpaceV.y+tangentSpaceL.y)*LplusV_rcpLen; - - return retval; - } - template - static AnisotropicMicrofacetCache createForReflection( - const surface_interactions::Anisotropic interaction, - const LightSample _sample) - { - return createForReflection(interaction.getTangentSpaceV(),_sample.getTangentSpaceL(),_sample.VdotL); - } - // transmissive cases need to be checked if the path is valid before usage - static bool compute( - out AnisotropicMicrofacetCache retval, - const bool transmitted, const float3 V, const float3 L, - const float3 T, const float3 B, const float3 N, - const float NdotL, const float VdotL, - const float orientedEta, const float rcpOrientedEta, out float3 H - ) - { - float3 H; - const bool valid = IsotropicMicrofacetCache::compute(retval,transmitted,V,L,N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); - if (valid) + static AnisotropicMicrofacetCache create( + const float3 tangentSpaceV, + const float3 tangentSpaceH, + const bool transmitted, + const float rcpOrientedEta, + const float rcpOrientedEta2 + ) + { + AnisotropicMicrofacetCache retval = create(tangentSpaceV,tangentSpaceH); + if (transmitted) + { + const float VdotH = retval.VdotH; + LdotH = transmitted ? refract_compute_NdotT(VdotH<0.0,VdotH*VdotH,rcpOrientedEta2); + } + + return retval; + } + // always valid because its specialized for the reflective case + static AnisotropicMicrofacetCache createForReflection(const float3 tangentSpaceV, const float3 tangentSpaceL, const float VdotL) + { + AnisotropicMicrofacetCache retval; + + float LplusV_rcpLen; + retval = createForReflection(tangentSpaceV.z,tangentSpaceL.z,VdotL,LplusV_rcpLen); + retval.TdotH = (tangentSpaceV.x+tangentSpaceL.x)*LplusV_rcpLen; + retval.BdotH = (tangentSpaceV.y+tangentSpaceL.y)*LplusV_rcpLen; + + return retval; + } + template + static AnisotropicMicrofacetCache createForReflection( + const surface_interactions::Anisotropic interaction, + const LightSample _sample) + { + return createForReflection(interaction.getTangentSpaceV(),_sample.getTangentSpaceL(),_sample.VdotL); + } + // transmissive cases need to be checked if the path is valid before usage + static bool compute( + out AnisotropicMicrofacetCache retval, + const bool transmitted, const float3 V, const float3 L, + const float3 T, const float3 B, const float3 N, + const float NdotL, const float VdotL, + const float orientedEta, const float rcpOrientedEta, out float3 H + ) { - retval.TdotH = dot(T,H); - retval.BdotH = dot(B,H); + float3 H; + const bool valid = IsotropicMicrofacetCache::compute(retval,transmitted,V,L,N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); + if (valid) + { + retval.TdotH = dot(T,H); + retval.BdotH = dot(B,H); + } + return valid; } - return valid; - } - template - static bool compute( - out AnisotropicMicrofacetCache retval, - const surface_interactions::Anisotropic interaction, - const LightSample _sample, - const float eta - ) - { - float3 H; - const bool valid = IsotropicMicrofacetCache::compute(retval,interaction,_sample,eta,H); - if (valid) + template + static bool compute( + out AnisotropicMicrofacetCache retval, + const surface_interactions::Anisotropic interaction, + const LightSample _sample, + const float eta + ) { - retval.TdotH = dot(interaction.T,H); - retval.BdotH = dot(interaction.B,H); + float3 H; + const bool valid = IsotropicMicrofacetCache::compute(retval,interaction,_sample,eta,H); + if (valid) + { + retval.TdotH = dot(interaction.T,H); + retval.BdotH = dot(interaction.B,H); + } + return valid; } - return valid; - } - float TdotH; - float BdotH; + float TdotH; + float BdotH; }; @@ -383,21 +424,21 @@ struct AnisotropicMicrofacetCache : IsotropicMicrofacetCache template struct quotient_and_pdf { - quotient_and_pdf create(const SpectralBins _quotient, const float _pdf) - { - quotient_and_pdf retval; - retval.quotient = _quotient; - retval.pdf = _pdf; - return retval; - } - - SpectralBins value() - { - return quotient*pdf; - } - - SpectralBins quotient; - float pdf; + quotient_and_pdf create(const SpectralBins _quotient, const float _pdf) + { + quotient_and_pdf retval; + retval.quotient = _quotient; + retval.pdf = _pdf; + return retval; + } + + SpectralBins value() + { + return quotient*pdf; + } + + SpectralBins quotient; + float pdf; }; From f6752c6732d6db05fabe478d9fa820febad349c8 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 25 Nov 2024 17:53:05 +0700 Subject: [PATCH 002/188] some corrections --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 43 +++++++++++------------ 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 31e01aca64..49929f1202 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -21,21 +21,20 @@ namespace ray_dir_info #define NBL_CONCEPT_NAME Basic #define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename) -#define NBL_CONCEPT_TPLT_PRM_NAMES (U)(T) -#define NBL_CONCEPT_PARAM_0 (a,U) -#define NBL_CONCEPT_PARAM_1 (N,vector) -#define NBL_CONCEPT_PARAM_2 (dir,T) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(U) +#define NBL_CONCEPT_PARAM_0 (a,T) +#define NBL_CONCEPT_PARAM_1 (N,vector) +#define NBL_CONCEPT_PARAM_2 (dirDotN,U) NBL_CONCEPT_BEGIN(3) #define a NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define N NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 -#define dir NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +#define dirDotN NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 NBL_CONCEPT_END( - // add check for T is_scalar_v ? - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((a.getDirection()), ::nbl::hlsl::is_same_v, vector)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((a.transmit()), ::nbl::hlsl::is_same_v, U)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((a.reflect(N, dir)), ::nbl::hlsl::is_same_v, U)) -); -#undef dir + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((a.getDirection()), ::nbl::hlsl::is_same_v, vector)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((a.transmit()), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((a.reflect(N, dirDotN)), ::nbl::hlsl::is_same_v, T)) +) && nbl::hlsl::is_scalar_v; +#undef dirDotN #undef N #undef a #include @@ -71,21 +70,21 @@ struct SBasic namespace surface_interactions { -#define NBL_CONCEPT_NAME Isotropic // doesn't work yet +#define NBL_CONCEPT_NAME Isotropic #define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename)(typename) -#define NBL_CONCEPT_TPLT_PRM_NAMES (U)(B)(T) // B should be of type Basic -#define NBL_CONCEPT_PARAM_0 (a,U) -#define NBL_CONCEPT_PARAM_1 (V,ray_dir_info::SBasic) -#define NBL_CONCEPT_PARAM_2 (N,vector) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(B)(U) // B is type Basic +#define NBL_CONCEPT_PARAM_0 (a,T) +#define NBL_CONCEPT_PARAM_1 (V,B) +#define NBL_CONCEPT_PARAM_2 (N,vector) NBL_CONCEPT_BEGIN(1) #define a NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 -#define N NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 -#define V NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +#define V NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 +#define N NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((U::create(V,N)), ::nbl::hlsl::is_same_v, U)) -); -#undef V + ((NBL_CONCEPT_REQ_EXPR)(T::create(V,N))) +) && ray_dir_info::Basic; #undef N +#undef V #undef a #include @@ -100,7 +99,7 @@ struct SIsotropic retval.N = normalizedN; retval.NdotV = dot(retval.N, retval.V.getDirection()); - retval.NdotV_squared = retval.NdotV * retval.NdotV; + retval.NdotV2 = retval.NdotV * retval.NdotV; return retval; } From 42fcb2a99b56776347bd229b8c6c77e2a64e2da9 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 26 Nov 2024 11:25:00 +0700 Subject: [PATCH 003/188] anisotropic concept --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 138 ++++++++++++++-------- 1 file changed, 88 insertions(+), 50 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 49929f1202..98b904afcc 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -22,21 +22,22 @@ namespace ray_dir_info #define NBL_CONCEPT_NAME Basic #define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename) #define NBL_CONCEPT_TPLT_PRM_NAMES (T)(U) -#define NBL_CONCEPT_PARAM_0 (a,T) +#define NBL_CONCEPT_PARAM_0 (rdirinfo,T) #define NBL_CONCEPT_PARAM_1 (N,vector) #define NBL_CONCEPT_PARAM_2 (dirDotN,U) -NBL_CONCEPT_BEGIN(3) -#define a NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +NBL_CONCEPT_BEGIN(4) +#define rdirinfo NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define N NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define dirDotN NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((a.getDirection()), ::nbl::hlsl::is_same_v, vector)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((a.transmit()), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((a.reflect(N, dirDotN)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.direction), ::nbl::hlsl::is_same_v, vector)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.getDirection()), ::nbl::hlsl::is_same_v, vector)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.transmit()), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.reflect(N, dirDotN)), ::nbl::hlsl::is_same_v, T)) ) && nbl::hlsl::is_scalar_v; #undef dirDotN #undef N -#undef a +#undef rdirinfo #include // no ray-differentials, nothing @@ -56,7 +57,7 @@ struct SBasic SBasic reflect(const float3 N, const float directionDotN) { SBasic retval; - retval.direction = nbl::hlsl::reflect(direction,N,directionDotN); + retval.direction = nbl::hlsl::reflect(direction,N,directionDotN); // TODO: template return retval; } @@ -72,83 +73,120 @@ namespace surface_interactions #define NBL_CONCEPT_NAME Isotropic #define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename)(typename) -#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(B)(U) // B is type Basic -#define NBL_CONCEPT_PARAM_0 (a,T) -#define NBL_CONCEPT_PARAM_1 (V,B) -#define NBL_CONCEPT_PARAM_2 (N,vector) -NBL_CONCEPT_BEGIN(1) -#define a NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 -#define V NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 -#define N NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(B)(U) // B is type Basic +#define NBL_CONCEPT_PARAM_0 (iso,T) +#define NBL_CONCEPT_PARAM_1 (normV,B) +#define NBL_CONCEPT_PARAM_2 (normN,vector) +NBL_CONCEPT_BEGIN(5) +#define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +#define normV NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 +#define normN NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_EXPR)(T::create(V,N))) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.V), ::nbl::hlsl::is_same_v, B)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.N), ::nbl::hlsl::is_same_v, vector)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.NdotV), ::nbl::hlsl::is_same_v, U)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.NdotV2), ::nbl::hlsl::is_same_v, U)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(normV,normN)), ::nbl::hlsl::is_same_v, T)) ) && ray_dir_info::Basic; -#undef N -#undef V -#undef a +#undef normN +#undef normV +#undef iso #include -template) // another typename T for RayDirInfo ? +template) struct SIsotropic { + using vector_t = vector; // WARNING: Changed since GLSL, now arguments need to be normalized! - static SIsotropic create(NBL_CONST_REF_ARG(RayDirInfo) normalizedV, const float3 normalizedN) + static SIsotropic create(NBL_CONST_REF_ARG(RayDirInfo) normalizedV, NBL_CONST_REF_ARG(vector_t) normalizedN) { - SIsotropic retval; + SIsotropic retval; retval.V = normalizedV; retval.N = normalizedN; - retval.NdotV = dot(retval.N, retval.V.getDirection()); - retval.NdotV2 = retval.NdotV * retval.NdotV; + retval.NdotV = dot(retval.N,retval.V.getDirection()); + retval.NdotV2 = retval.NdotV*retval.NdotV; return retval; } RayDirInfo V; - float3 N; - float NdotV; - float NdotV2; // old NdotV_squared + vector_t N; + T NdotV; + T NdotV2; // old NdotV_squared }; -template -struct Anisotropic : Isotropic +#define NBL_CONCEPT_NAME Anisotropic +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename)(typename)(typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(I)(B)(U) // I is type Isotropic, B is type Basic +#define NBL_CONCEPT_PARAM_0 (aniso,T) +#define NBL_CONCEPT_PARAM_1 (iso,I) +#define NBL_CONCEPT_PARAM_2 (normT,vector) +#define NBL_CONCEPT_PARAM_3 (normB,U) +NBL_CONCEPT_BEGIN(9) +#define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +#define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 +#define normT NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +#define normB NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.T), ::nbl::hlsl::is_same_v, vector)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.B), ::nbl::hlsl::is_same_v, vector)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.TdotV), ::nbl::hlsl::is_same_v, vector)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.BdotV), ::nbl::hlsl::is_same_v, vector)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(iso,normT,normB)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(iso,normT)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(iso)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getTangentSpaceV()), ::nbl::hlsl::is_same_v, vector)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getTangentFrame()), ::nbl::hlsl::is_same_v, matrix)) +) && Isotropic && ray_dir_info::Basic; +#undef normB +#undef normT +#undef iso +#undef aniso +#include + +template) +struct SAnisotropic : SIsotropic { + using vector_t = vector; + using matrix_t = matrix; + // WARNING: Changed since GLSL, now arguments need to be normalized! - static Anisotropic create( - const Isotropic isotropic, - const float3 normalizedT, - const float normalizedB + static SAnisotropic create( + NBL_CONST_REF_ARG(SIsotropic) isotropic, + NBL_CONST_REF_ARG(vector_t) normalizedT, + const U normalizedB ) { - Anisotropic retval; - retval::Isotropic = isotropic; + SAnisotropic retval; + //(SIsotropic) retval = isotropic; retval.T = normalizedT; retval.B = normalizedB; - const float3 V = retval.getDirection(); - retval.TdotV = dot(V,retval.T); - retval.BdotV = dot(V,retval.B); + const vector_t V = retval.getDirection(); + retval.TdotV = dot(V, retval.T); + retval.BdotV = dot(V, retval.B); return retval; } - static Anisotropic create(const Isotropic isotropic, const float3 normalizedT) + static SAnisotropic create(NBL_CONST_REF_ARG(SIsotropic) isotropic, NBL_CONST_REF_ARG(vector_t) normalizedT) { - return create(isotropic,normalizedT,cross(isotropic.N,normalizedT)); + return create(isotropic, normalizedT, cross(isotropic.N, normalizedT)); } - static Anisotropic create(const Isotropic isotropic) + static SAnisotropic create(NBL_CONST_REF_ARG(SIsotropic) isotropic) { - float2x3 TB = nbl::hlsl::frisvad(isotropic.N); - return create(isotropic,TB[0],TB[1]); + matrix TB = nbl::hlsl::frisvad(isotropic.N); // TODO: template + return create(isotropic, TB[0], TB[1]); } - float3 getTangentSpaceV() {return float3(Tdot,BdotV,Isotropic::NdotV);} + vector_t getTangentSpaceV() { return vector_t(TdotV, BdotV, SIsotropic::NdotV); } // WARNING: its the transpose of the old GLSL function return value! - float3x3 getTangentFrame() {return float3x3(T,B,Isotropic::N);} + matrix_t getTangentFrame() { return matrix_t(T, B, SIsotropic::N); } - float3 T; - float3 B; - float3 TdotV; - float3 BdotV; + vector_t T; + vector_t B; + vector_t TdotV; + vector_t BdotV; }; } From 81e56f4510546ca89e953b8d8eeee04f891d5c05 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 26 Nov 2024 16:13:54 +0700 Subject: [PATCH 004/188] concepts for existing stuff --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 399 ++++++++++++++++------ 1 file changed, 293 insertions(+), 106 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 98b904afcc..3afcb12df8 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -6,6 +6,8 @@ #include "nbl/builtin/hlsl/limits.hlsl" #include "nbl/builtin/hlsl/numbers.hlsl" +#include "nbl/builtin/hlsl/type_traits.hlsl" +#include "nbl/builtin/hlsl/concepts.hlsl" #include "nbl/builtin/hlsl/math/functions.glsl" namespace nbl @@ -192,16 +194,70 @@ struct SAnisotropic : SIsotropic } -template -struct LightSample +#define NBL_CONCEPT_NAME Sample +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename)(typename)(typename)(typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(I)(A)(B)(U) // I type Isotropic, A type Aniso, B type Basic (getting clunky) +#define NBL_CONCEPT_PARAM_0 (sample_,T) +#define NBL_CONCEPT_PARAM_1 (iso,I) +#define NBL_CONCEPT_PARAM_2 (aniso,A) +#define NBL_CONCEPT_PARAM_3 (rdirinfo,B) +#define NBL_CONCEPT_PARAM_4 (pV,vector) +#define NBL_CONCEPT_PARAM_5 (frame,matrix) +#define NBL_CONCEPT_PARAM_6 (pT,vector) +#define NBL_CONCEPT_PARAM_7 (pB,vector) +#define NBL_CONCEPT_PARAM_8 (pN,vector) +#define NBL_CONCEPT_PARAM_9 (pVdotL,U) +NBL_CONCEPT_BEGIN(12) +#define sample_ NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +#define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 +#define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +#define rdirinfo NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 +#define pV NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 +#define frame NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 +#define pT NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 +#define pB NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_7 +#define pN NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_8 +#define pVdotL NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_9 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((sample_.L), ::nbl::hlsl::is_same_v, B)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((sample_.VdotL), ::nbl::hlsl::is_same_v, U)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((sample_.TdotL), ::nbl::hlsl::is_same_v, U)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((sample_.BdotL), ::nbl::hlsl::is_same_v, U)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((sample_.NdotL), ::nbl::hlsl::is_same_v, U)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((sample_.NdotL2), ::nbl::hlsl::is_same_v, U)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createTangentSpace(pV,rdirinfo,frame)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(rdirinfo,pVdotL,pN)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(rdirinfo,pVdotL,pT,pB,pN)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create(pV,iso)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create(pV,aniso)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((sample_.getTangentSpaceL()), ::nbl::hlsl::is_same_v, vector)) +) && surface_interactions::Anisotropic && surface_interactions::Isotropic && + ray_dir_info::Basic; +#undef pVdotL +#undef pN +#undef pB +#undef pT +#undef frame +#undef pV +#undef rdirinfo +#undef aniso +#undef iso +#undef sample_ +#include + +template) +struct SLightSample { - static LightSample createTangentSpace( - const float3 tangentSpaceV, - const RayDirInfo tangentSpaceL, - const float3x3 tangentFrame // WARNING: its the transpose of the old GLSL function return value! + using vector_t = vector; + using matrix_t = matrix; + + static SLightSample createTangentSpace( + NBL_CONST_REF_ARG(vector_t) tangentSpaceV, + NBL_CONST_REF_ARG(RayDirInfo) tangentSpaceL, + NBL_CONST_REF_ARG(matrix_t) tangentFrame // WARNING: its the transpose of the old GLSL function return value! ) { - LightSample retval; + SLightSample retval; retval.L = RayDirInfo::transform(tangentSpaceL,tangentFrame); retval.VdotL = dot(tangentSpaceV,tangentSpaceL); @@ -213,23 +269,23 @@ struct LightSample return retval; } - static LightSample create(const RayDirInfo L, const float VdotL, const float3 N) + static SLightSample create(NBL_CONST_REF_ARG(RayDirInfo) L, const U VdotL, NBL_CONST_REF_ARG(vector_t) N) { - LightSample retval; + SLightSample retval; retval.L = L; retval.VdotL = VdotL; - retval.TdotL = nbl::hlsl::numeric_limits::nan(); - retval.BdotL = nbl::hlsl::numeric_limits::nan(); + retval.TdotL = nbl::hlsl::numeric_limits::signaling_NaN; + retval.BdotL = nbl::hlsl::numeric_limits::signaling_NaN; retval.NdotL = dot(N,L); - retval.NdotL2 = retval.NdotL*retval.NdotL; + retval.NdotL2 = retval.NdotL * retval.NdotL; return retval; } - static LightSample create(const RayDirInfo L, const float VdotL, const float3 T, const float3 B, const float3 N) + static SLightSample create(NBL_CONST_REF_ARG(RayDirInfo) L, const U VdotL, NBL_CONST_REF_ARG(vector_t) T, NBL_CONST_REF_ARG(vector_t) B, NBL_CONST_REF_ARG(vector_t) N) { - LightSample retval = create(L,VdotL,N); + SLightSample retval = create(L,VdotL,N); retval.TdotL = dot(T,L); retval.BdotL = dot(B,L); @@ -238,138 +294,269 @@ struct LightSample } // overloads for surface_interactions template - static LightSample create(const float3 L, const surface_interactions::Isotropic interaction) + static SLightSample create(NBL_CONST_REF_ARG(vector_t) L, NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction) { - const float3 V = interaction.V.getDirection(); + const vector_t V = interaction.V.getDirection(); const float VdotL = dot(V,L); - return create(L,VdotL,interaction.N); + return create(L, VdotL, interaction.N); } template - static LightSample create(const float3 L, const surface_interactions::Anisotropic interaction) + static SLightSample create(NBL_CONST_REF_ARG(vector_t) L, NBL_CONST_REF_ARG(surface_interactions::SAnisotropic) interaction) { - const float3 V = interaction.V.getDirection(); + const vector_t V = interaction.V.getDirection(); const float VdotL = dot(V,L); return create(L,VdotL,interaction.T,interaction.B,interaction.N); } // - float3 getTangentSpaceL() + vector_t getTangentSpaceL() { - return float3(TdotL,BdotL,NdotL); + return vector_t(TdotL, BdotL, NdotL); } RayDirInfo L; - float VdotL; + U VdotL; - float TdotL; - float BdotL; - float NdotL; - float NdotL2; + U TdotL; + U BdotL; + U NdotL; + U NdotL2; }; -// -struct IsotropicMicrofacetCache +// everything after here needs testing because godbolt timeout +#define NBL_CONCEPT_NAME IsotropicMicrofacetCache +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename)(typename)(typename)(typename)(typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(S)(I)(B)(C)(U) // S type Sample, I type Isotropic, B/C type Basic (getting clunky) +#define NBL_CONCEPT_PARAM_0 (cache,T) +#define NBL_CONCEPT_PARAM_1 (iso,I) +#define NBL_CONCEPT_PARAM_2 (pNdotV,U) +#define NBL_CONCEPT_PARAM_3 (pNdotL,U) +#define NBL_CONCEPT_PARAM_4 (pVdotL,U) +#define NBL_CONCEPT_PARAM_5 (rcplen,U) +#define NBL_CONCEPT_PARAM_6 (sample_,S) +#define NBL_CONCEPT_PARAM_7 (V,vector) +#define NBL_CONCEPT_PARAM_8 (L,vector) +#define NBL_CONCEPT_PARAM_9 (N,vector) +#define NBL_CONCEPT_PARAM_10 (H,vector) +#define NBL_CONCEPT_PARAM_11 (eta0,U) +#define NBL_CONCEPT_PARAM_12 (eta1,U) +#define NBL_CONCEPT_PARAM_13 (b0,bool) +#define NBL_CONCEPT_PARAM_14 (b1,bool) +NBL_CONCEPT_BEGIN(11) +#define cache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +#define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 +#define pNdotV NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +#define pNdotL NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 +#define pVdotL NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 +#define rcplen NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 +#define sample_ NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 +#define V NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_7 +#define L NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_8 +#define N NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_9 +#define H NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_10 +#define eta0 NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_11 +#define eta1 NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_12 +#define b0 NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_13 +#define b1 NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_14 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.VdotH), ::nbl::hlsl::is_same_v, U)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.LdotH), ::nbl::hlsl::is_same_v, U)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.NdotH), ::nbl::hlsl::is_same_v, U)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.NdotH2), ::nbl::hlsl::is_same_v, U)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(pNdotV,pNdotL,pVdotL,rcplen)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(pNdotV,pNdotL,pVdotL)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(iso,sample_)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::compute(cache,b0,V,L,N,pNdotL,pVdotL,eta0,eta1,H)), ::nbl::hlsl::is_same_v, bool)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,iso,sample_,eta0,H)), ::nbl::hlsl::is_same_v, bool)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,iso,sample_,eta0)), ::nbl::hlsl::is_same_v, bool)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.isValidVNDFMicrofacet(b0,b1,pVdotL,eta0,eta1)), ::nbl::hlsl::is_same_v, bool)) +) && surface_interactions::Isotropic && + ray_dir_info::Basic && ray_dir_info::Basic; +#undef b1 +#undef b0 +#undef eta1 +#undef eta0 +#undef H +#undef N +#undef L +#undef V +#undef sample_ +#undef rcplen +#undef pVdotL +#undef pNdotL +#undef pNdotV +#undef iso +#undef cache +#include + +template ) +struct SIsotropicMicrofacetCache { + using vector_t = vector; + // always valid because its specialized for the reflective case - static IsotropicMicrofacetCache createForReflection(const float NdotV, const float NdotL, const float VdotL, out float LplusV_rcpLen) + static SIsotropicMicrofacetCache createForReflection(const T NdotV, const T NdotL, const T VdotL, out T LplusV_rcpLen) { - LplusV_rcpLen = inversesqrt(2.0+2.0*VdotL); + //TODOLplusV_rcpLen = inversesqrt(2.0+2.0*VdotL); - IsotropicMicrofacetCache retval; + SIsotropicMicrofacetCache retval; - retval.VdotH = LplusV_rcpLen*VdotL+LplusV_rcpLen; + retval.VdotH = LplusV_rcpLen * VdotL + LplusV_rcpLen; retval.LdotH = retval.VdotH; - retval.NdotH = (NdotL+NdotV)*LplusV_rcpLen; - retval.NdotH2 = retval.NdotH*retval.NdotH; + retval.NdotH = (NdotL + NdotV) * LplusV_rcpLen; + retval.NdotH2 = retval.NdotH * retval.NdotH; return retval; } - static IsotropicMicrofacetCache createForReflection(const float NdotV, const float NdotL, const float VdotL) + static SIsotropicMicrofacetCache createForReflection(const T NdotV, const T NdotL, const T VdotL) { float dummy; - return createForReflection(NdotV,NdotL,VdotL,dummy); + return createForReflection(NdotV, NdotL, VdotL, dummy); } template - static IsotropicMicrofacetCache createForReflection( - const surface_interactions::Isotropic interaction, - const LightSample _sample) + static SIsotropicMicrofacetCache createForReflection( + NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction, + NBL_CONST_REF_ARG(SLightSample) _sample) { - return createForReflection(interaction.NdotV,_sample.NdotL,_sample.VdotL); + return createForReflection(interaction.NdotV, _sample.NdotL, _sample.VdotL); } // transmissive cases need to be checked if the path is valid before usage static bool compute( - out IsotropicMicrofacetCache retval, - const bool transmitted, const float3 V, const float3 L, - const float3 N, const float NdotL, const float VdotL, - const float orientedEta, const float rcpOrientedEta, out float3 H + out SIsotropicMicrofacetCache retval, + const bool transmitted, NBL_CONST_REF_ARG(vector_t) V, NBL_CONST_REF_ARG(vector_t) L, + NBL_CONST_REF_ARG(vector_t) N, const T NdotL, const T VdotL, + const T orientedEta, const T rcpOrientedEta, out vector_t H ) { // TODO: can we optimize? - H = computeMicrofacetNormal(transmitted,V,L,orientedEta); - retval.NdotH = dot(N,H); + //TODOH = computeMicrofacetNormal(transmitted,V,L,orientedEta); + retval.NdotH = dot(N, H); // not coming from the medium (reflected) OR // exiting at the macro scale AND ( (not L outside the cone of possible directions given IoR with constraint VdotH*LdotH<0.0) OR (microfacet not facing toward the macrosurface, i.e. non heightfield profile of microsurface) ) - const bool valid = !transmitted || (VdotL<=-min(orientedEta,rcpOrientedEta) && _cache.NdotH>nbl::hlsl::numeric_limits::min()); + const bool valid = !transmitted || (VdotL <= -min(orientedEta, rcpOrientedEta) && retval.NdotH > nbl::hlsl::numeric_limits::min()); if (valid) { // TODO: can we optimize? retval.VdotH = dot(V,H); retval.LdotH = dot(L,H); - retval.NdotH2 = retval.NdotH*retval.NdotH; + retval.NdotH2 = retval.NdotH * retval.NdotH; return true; } return false; } template static bool compute( - out IsotropicMicrofacetCache retval, - const surface_interactions::Isotropic interaction, - const LightSample _sample, - const float eta, out float3 H + out SIsotropicMicrofacetCache retval, + NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction, + NBL_CONST_REF_ARG(SLightSample) _sample, + const T eta, out vector_t H ) { - const float NdotV = interaction.NdotV; - const float NdotL = _sample.NdotL; - const bool transmitted = nbl_glsl_isTransmissionPath(NdotV,NdotL); + const T NdotV = interaction.NdotV; + const T NdotL = _sample.NdotL; + //TODOconst bool transmitted = nbl_glsl_isTransmissionPath(NdotV,NdotL); float orientedEta, rcpOrientedEta; - const bool backside = nbl_glsl_getOrientedEtas(orientedEta,rcpOrientedEta,NdotV,eta); + //TODOconst bool backside = nbl_glsl_getOrientedEtas(orientedEta,rcpOrientedEta,NdotV,eta); - const vec3 V = interaction.V.getDirection(); - const vec3 L = _sample.L; - const float VdotL = dot(V,L); - return nbl_glsl_calcIsotropicMicrofacetCache(_cache,transmitted,V,L,interaction.N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); + const vector_t V = interaction.V.getDirection(); + const vector_t L = _sample.L; + const float VdotL = dot(V, L); + return true;//TODOnbl_glsl_calcIsotropicMicrofacetCache(_cache,transmitted,V,L,interaction.N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); } template static bool compute( - out IsotropicMicrofacetCache retval, - const surface_interactions::Isotropic interaction, - const LightSample _sample, - const float eta + out SIsotropicMicrofacetCache retval, + NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction, + NBL_CONST_REF_ARG(SLightSample) _sample, + const T eta ) { - float3 dummy; - return nbl_glsl_calcIsotropicMicrofacetCache(_cache,transmitted,V,L,interaction.N,NdotL,VdotL,orientedEta,rcpOrientedEta,dummy); + vector_t dummy; + return true;//TODOnbl_glsl_calcIsotropicMicrofacetCache(_cache,transmitted,V,L,interaction.N,NdotL,VdotL,orientedEta,rcpOrientedEta,dummy); } - bool isValidVNDFMicrofacet(const bool is_bsdf, const bool transmission, const float VdotL, const float eta, const float rcp_eta) + bool isValidVNDFMicrofacet(const bool is_bsdf, const bool transmission, const float VdotL, const T eta, const T rcp_eta) { - return NdotH >= 0.0 && !(is_bsdf && transmission && (VdotL > -min(eta,rcp_eta))); + return NdotH >= 0.0 && !(is_bsdf && transmission && (VdotL > -min(eta, rcp_eta))); } - float VdotH; - float LdotH; - float NdotH; - float NdotH2; + T VdotH; + T LdotH; + T NdotH; + T NdotH2; }; -struct AnisotropicMicrofacetCache : IsotropicMicrofacetCache + +#define NBL_CONCEPT_NAME AnisotropicMicrofacetCache +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename)(typename)(typename)(typename)(typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(S)(I)(A)(B)(C)(U) // S type Sample, A type Anisotropic, B/C type Basic (getting clunky) +#define NBL_CONCEPT_PARAM_0 (cache,T) +#define NBL_CONCEPT_PARAM_1 (aniso,I) +#define NBL_CONCEPT_PARAM_2 (pNdotL,U) +#define NBL_CONCEPT_PARAM_3 (pVdotL,U) +#define NBL_CONCEPT_PARAM_4 (sample_,S) +#define NBL_CONCEPT_PARAM_5 (V,vector) +#define NBL_CONCEPT_PARAM_6 (L,vector) +#define NBL_CONCEPT_PARAM_7 (T,vector) +#define NBL_CONCEPT_PARAM_8 (B,vector) +#define NBL_CONCEPT_PARAM_9 (N,vector) +#define NBL_CONCEPT_PARAM_10 (H,vector) +#define NBL_CONCEPT_PARAM_11 (eta0,U) +#define NBL_CONCEPT_PARAM_12 (eta1,U) +#define NBL_CONCEPT_PARAM_13 (b0,bool) +NBL_CONCEPT_BEGIN(11) +#define cache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +#define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 +#define pNdotL NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +#define pVdotL NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 +#define sample_ NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 +#define V NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 +#define L NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 +#define T NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_7 +#define B NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_8 +#define N NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_9 +#define H NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_10 +#define eta0 NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_11 +#define eta1 NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_12 +#define b0 NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_13 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.TdotH), ::nbl::hlsl::is_same_v, U)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.BdotH), ::nbl::hlsl::is_same_v, U)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,H)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,H,b0,eta0,eta1)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(V,L,pVdotL)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(aniso,sample_)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::compute(cache,b0,V,L,T,B,N,pNdotL,pVdotL,eta0,eta1,H)), ::nbl::hlsl::is_same_v, bool)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,aniso,sample_)), ::nbl::hlsl::is_same_v, bool)) +) && surface_interactions::Anisotropic && + ray_dir_info::Basic && ray_dir_info::Basic; +#undef b0 +#undef eta1 +#undef eta0 +#undef H +#undef N +#undef B +#undef T +#undef L +#undef V +#undef sample_ +#undef pVdotL +#undef pNdotL +#undef aniso +#undef cache +#include + +template ) +struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache { + using vector_t = vector; + // always valid by construction - static AnisotropicMicrofacetCache create(const float3 tangentSpaceV, const float3 tangentSpaceH) + static SAnisotropicMicrofacetCache create(NBL_CONST_REF_ARG(vector_t) tangentSpaceV, NBL_CONST_REF_ARG(vector_t) tangentSpaceH) { - AnisotropicMicrofacetCache retval; + SAnisotropicMicrofacetCache retval; retval.VdotH = dot(tangentSpaceV,tangentSpaceH); retval.LdotH = retval.VdotH; @@ -380,53 +567,53 @@ struct AnisotropicMicrofacetCache : IsotropicMicrofacetCache return retval; } - static AnisotropicMicrofacetCache create( - const float3 tangentSpaceV, - const float3 tangentSpaceH, + static SAnisotropicMicrofacetCache create( + NBL_CONST_REF_ARG(vector_t) tangentSpaceV, + NBL_CONST_REF_ARG(vector_t) tangentSpaceH, const bool transmitted, - const float rcpOrientedEta, - const float rcpOrientedEta2 + const T rcpOrientedEta, + const T rcpOrientedEta2 ) { - AnisotropicMicrofacetCache retval = create(tangentSpaceV,tangentSpaceH); + SAnisotropicMicrofacetCache retval = create(tangentSpaceV,tangentSpaceH); if (transmitted) { - const float VdotH = retval.VdotH; + const T VdotH = retval.VdotH; LdotH = transmitted ? refract_compute_NdotT(VdotH<0.0,VdotH*VdotH,rcpOrientedEta2); } return retval; } // always valid because its specialized for the reflective case - static AnisotropicMicrofacetCache createForReflection(const float3 tangentSpaceV, const float3 tangentSpaceL, const float VdotL) + static SAnisotropicMicrofacetCache createForReflection(const float3 tangentSpaceV, const float3 tangentSpaceL, const float VdotL) { - AnisotropicMicrofacetCache retval; + SAnisotropicMicrofacetCache retval; float LplusV_rcpLen; - retval = createForReflection(tangentSpaceV.z,tangentSpaceL.z,VdotL,LplusV_rcpLen); - retval.TdotH = (tangentSpaceV.x+tangentSpaceL.x)*LplusV_rcpLen; - retval.BdotH = (tangentSpaceV.y+tangentSpaceL.y)*LplusV_rcpLen; + retval = createForReflection(tangentSpaceV.z, tangentSpaceL.z, VdotL, LplusV_rcpLen); + retval.TdotH = (tangentSpaceV.x + tangentSpaceL.x)*LplusV_rcpLen; + retval.BdotH = (tangentSpaceV.y + tangentSpaceL.y)*LplusV_rcpLen; return retval; } template - static AnisotropicMicrofacetCache createForReflection( - const surface_interactions::Anisotropic interaction, - const LightSample _sample) + static SAnisotropicMicrofacetCache createForReflection( + NBL_CONST_REF_ARG(surface_interactions::SAnisotropic) interaction, + NBL_CONST_REF_ARG(SLightSample) _sample) { - return createForReflection(interaction.getTangentSpaceV(),_sample.getTangentSpaceL(),_sample.VdotL); + return createForReflection(interaction.getTangentSpaceV(), _sample.getTangentSpaceL(), _sample.VdotL); } // transmissive cases need to be checked if the path is valid before usage static bool compute( - out AnisotropicMicrofacetCache retval, - const bool transmitted, const float3 V, const float3 L, - const float3 T, const float3 B, const float3 N, - const float NdotL, const float VdotL, - const float orientedEta, const float rcpOrientedEta, out float3 H + out SAnisotropicMicrofacetCache retval, + const bool transmitted, NBL_CONST_REF_ARG(vector_t) V, NBL_CONST_REF_ARG(vector_t) L, + NBL_CONST_REF_ARG(vector_t) T, NBL_CONST_REF_ARG(vector_t) B, NBL_CONST_REF_ARG(vector_t) N, + const T NdotL, const T VdotL, + const T orientedEta, const T rcpOrientedEta, out vector_t H ) { - float3 H; - const bool valid = IsotropicMicrofacetCache::compute(retval,transmitted,V,L,N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); + vector_t H; + const bool valid = SIsotropicMicrofacetCache::compute(retval,transmitted,V,L,N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); if (valid) { retval.TdotH = dot(T,H); @@ -436,14 +623,14 @@ struct AnisotropicMicrofacetCache : IsotropicMicrofacetCache } template static bool compute( - out AnisotropicMicrofacetCache retval, - const surface_interactions::Anisotropic interaction, - const LightSample _sample, - const float eta + out SAnisotropicMicrofacetCache retval, + NBL_CONST_REF_ARG(surface_interactions::SAnisotropic) interaction, + NBL_CONST_REF_ARG(SLightSample) _sample, + const T eta ) { - float3 H; - const bool valid = IsotropicMicrofacetCache::compute(retval,interaction,_sample,eta,H); + vector_t H; + const bool valid = SIsotropicMicrofacetCache::compute(retval,interaction,_sample,eta,H); if (valid) { retval.TdotH = dot(interaction.T,H); @@ -452,8 +639,8 @@ struct AnisotropicMicrofacetCache : IsotropicMicrofacetCache return valid; } - float TdotH; - float BdotH; + T TdotH; + T BdotH; }; From 1e7395342bf67b48ee773c3cd269bc7d3e497e6d Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 27 Nov 2024 16:22:58 +0700 Subject: [PATCH 005/188] more templated stuff, new type trait dimensions --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 41 ++- include/nbl/builtin/hlsl/math/functions.hlsl | 261 +++++++++++++++++++ include/nbl/builtin/hlsl/type_traits.hlsl | 15 ++ 3 files changed, 307 insertions(+), 10 deletions(-) create mode 100644 include/nbl/builtin/hlsl/math/functions.hlsl diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 3afcb12df8..49c5900769 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -1,4 +1,4 @@ -// Copyright (C) 2018-2022 - DevSH Graphics Programming Sp. z O.O. +// Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h #ifndef _NBL_BUILTIN_HLSL_BXDF_COMMON_INCLUDED_ @@ -8,7 +8,7 @@ #include "nbl/builtin/hlsl/numbers.hlsl" #include "nbl/builtin/hlsl/type_traits.hlsl" #include "nbl/builtin/hlsl/concepts.hlsl" -#include "nbl/builtin/hlsl/math/functions.glsl" +#include "nbl/builtin/hlsl/math/functions.hlsl" namespace nbl { @@ -17,6 +17,27 @@ namespace hlsl namespace bxdf { +// returns unnormalized vector +// TODO: template these? +float computeUnnormalizedMicrofacetNormal(bool _refract, float3 V, float3 L, float orientedEta) +{ + const float etaFactor = (_refract ? orientedEta : 1.0); + const float3 tmpH = V + L * etaFactor; + return _refract ? (-tmpH) : tmpH; +} +// returns normalized vector, but NaN when +float3 computeMicrofacetNormal(bool _refract, float3 V, float3 L, float orientedEta) +{ + const float3 H = computeUnnormalizedMicrofacetNormal(_refract,V,L,orientedEta); + const float unnormRcpLen = rsqrt(dot(H,H)); + return H * unnormRcpLen; +} + +// if V and L are on different sides of the surface normal, then their dot product sign bits will differ, hence XOR will yield 1 at last bit +bool isTransmissionPath(float NdotV, float NdotL) +{ + return bool((asuint(NdotV) ^ asuint(NdotL)) & 0x80000000u); +} namespace ray_dir_info { @@ -59,7 +80,7 @@ struct SBasic SBasic reflect(const float3 N, const float directionDotN) { SBasic retval; - retval.direction = nbl::hlsl::reflect(direction,N,directionDotN); // TODO: template + retval.direction = math::reflect(direction,N,directionDotN); return retval; } @@ -177,7 +198,7 @@ struct SAnisotropic : SIsotropic } static SAnisotropic create(NBL_CONST_REF_ARG(SIsotropic) isotropic) { - matrix TB = nbl::hlsl::frisvad(isotropic.N); // TODO: template + matrix TB = math::frisvad(isotropic.N); return create(isotropic, TB[0], TB[1]); } @@ -397,7 +418,7 @@ struct SIsotropicMicrofacetCache // always valid because its specialized for the reflective case static SIsotropicMicrofacetCache createForReflection(const T NdotV, const T NdotL, const T VdotL, out T LplusV_rcpLen) { - //TODOLplusV_rcpLen = inversesqrt(2.0+2.0*VdotL); + LplusV_rcpLen = rsqrt(2.0 + 2.0 * VdotL); SIsotropicMicrofacetCache retval; @@ -429,7 +450,7 @@ struct SIsotropicMicrofacetCache ) { // TODO: can we optimize? - //TODOH = computeMicrofacetNormal(transmitted,V,L,orientedEta); + H = computeMicrofacetNormal(transmitted,V,L,orientedEta); retval.NdotH = dot(N, H); // not coming from the medium (reflected) OR @@ -455,15 +476,15 @@ struct SIsotropicMicrofacetCache { const T NdotV = interaction.NdotV; const T NdotL = _sample.NdotL; - //TODOconst bool transmitted = nbl_glsl_isTransmissionPath(NdotV,NdotL); + const bool transmitted = isTransmissionPath(NdotV,NdotL); float orientedEta, rcpOrientedEta; - //TODOconst bool backside = nbl_glsl_getOrientedEtas(orientedEta,rcpOrientedEta,NdotV,eta); + const bool backside = getOrientedEtas(orientedEta,rcpOrientedEta,NdotV,eta); const vector_t V = interaction.V.getDirection(); const vector_t L = _sample.L; const float VdotL = dot(V, L); - return true;//TODOnbl_glsl_calcIsotropicMicrofacetCache(_cache,transmitted,V,L,interaction.N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); + return compute(retval,transmitted,V,L,interaction.N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); } template static bool compute( @@ -474,7 +495,7 @@ struct SIsotropicMicrofacetCache ) { vector_t dummy; - return true;//TODOnbl_glsl_calcIsotropicMicrofacetCache(_cache,transmitted,V,L,interaction.N,NdotL,VdotL,orientedEta,rcpOrientedEta,dummy); + return compute(retval,transmitted,V,L,interaction.N,NdotL,VdotL,orientedEta,rcpOrientedEta,dummy); } bool isValidVNDFMicrofacet(const bool is_bsdf, const bool transmission, const float VdotL, const T eta, const T rcp_eta) diff --git a/include/nbl/builtin/hlsl/math/functions.hlsl b/include/nbl/builtin/hlsl/math/functions.hlsl new file mode 100644 index 0000000000..c02c5c4777 --- /dev/null +++ b/include/nbl/builtin/hlsl/math/functions.hlsl @@ -0,0 +1,261 @@ +// Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_BUILTIN_HLSL_MATH_FUNCTIONS_INCLUDED_ +#define _NBL_BUILTIN_HLSL_MATH_FUNCTIONS_INCLUDED_ + +#include + +namespace nbl +{ +namespace hlsl +{ +namespace math +{ + +namespace impl +{ +template +struct lp_norm; + +// infinity case +template +struct lp_norm +{ + static scalar_type_t __call(const T v) + { + scalar_type_t retval = abs(v[0]); + for (int i = 1; i < dimensions_v; i++) + retval = max(abs(v[i]),retval); + return retval; + } +}; + +// TOOD: is this doing what it should be? +template +struct lp_norm +{ + static scalar_type_t __sum(const T v) + { + scalar_type_t retval = abs(v[0]); + for (int i = 1; i < dimensions_v; i++) + retval += abs(v[i]); + return retval; + } + + static scalar_type_t __call(const T v) + { + return __sum(v); + } +}; + +template +struct lp_norm +{ + static scalar_type_t __sum(const T v) + { + return dot(v, v); // TODO: wait for overloaded dot? + } + + static scalar_type_t __call(const T v) + { + return sqrt(__sum(v)); + } +}; + +// TODO: even/odd cases +} + +template0) +scalar_type_t lpNormPreroot(NBL_CONST_REF_ARG(T) v) +{ + return impl::lp_norm::__sum(v); +} + +template +scalar_type_t lpNorm(NBL_CONST_REF_ARG(T) v) +{ + return impl::lp_norm::__call(v); +} + + +template ) +vector reflect(vector I, vector N, T NdotI) +{ + return N * 2.0 * NdotI - I; +} + +template ) +vector reflect(vector I, vector N) +{ + T NdotI = dot(N, I); + return reflect(I, N, NdotI); +} + + +namespace impl +{ +template +struct orientedEtas; + +template<> +struct orientedEtas +{ + static bool __call(out float orientedEta, out float rcpOrientedEta, float NdotI, float eta) + { + const bool backside = NdotI < 0.0; + const float rcpEta = 1.0 / eta; + orientedEta = backside ? rcpEta : eta; + rcpOrientedEta = backside ? eta : rcpEta; + return backside; + } +}; + +template<> +struct orientedEtas +{ + static bool __call(out float3 orientedEta, out float3 rcpOrientedEta, float NdotI, float3 eta) + { + const bool backside = NdotI < 0.0; + const float3 rcpEta = (float3)1.0 / eta; + orientedEta = backside ? rcpEta:eta; + rcpOrientedEta = backside ? eta:rcpEta; + return backside; + } +}; +} + +template || is_vector_v) +bool getOrientedEtas(out T orientedEta, out T rcpOrientedEta, scalar_type_t NdotI, T eta) +{ + return impl::orientedEtas::__call(orientedEta, rcpOrientedEta, NdotI, eta); +} + + +namespace impl +{ +struct refract +{ + using this_t = refract; + + static this_t create(float3 I, float3 N, bool backside, float NdotI, float NdotI2, float rcpOrientedEta, float rcpOrientedEta2) + { + this_t retval; + retval.I = I; + retval.N = N; + retval.backside = backside; + retval.NdotI = NdotI; + retval.NdotI2 = NdotI2; + retval.rcpOrientedEta = rcpOrientedEta; + retval.rcpOrientedEta2 = rcpOrientedEta2; + return retval; + } + + static this_t create(float3 I, float3 N, float NdotI, float eta) + { + this_t retval; + retval.I = I; + retval.N = N; + float orientedEta; + retval.backside = getOrientedEtas(orientedEta, retval.rcpOrientedEta, NdotI, eta); + retval.NdotI = NdotI; + retval.NdotI2 = NdotI * NdotI; + retval.rcpOrientedEta2 = retval.rcpOrientedEta * retval.rcpOrientedEta; + return retval; + } + + static this_t create(float3 I, float3 N, float eta) + { + this_t retval; + retval.I = I; + retval.N = N; + retval.NdotI = dot(N, I); + float orientedEta; + retval.backside = getOrientedEtas(orientedEta, retval.rcpOrientedEta, retval.NdotI, eta); + retval.NdotI2 = retval.NdotI * retval.NdotI; + retval.rcpOrientedEta2 = retval.rcpOrientedEta * retval.rcpOrientedEta; + return retval; + } + + float computeNdotT() + { + float NdotT2 = rcpOrientedEta2 * NdotI2 + 1.0 - rcpOrientedEta2; + float absNdotT = sqrt(NdotT2); + return backside ? absNdotT : -(absNdotT); + } + + float3 doRefract() + { + return N * (NdotI * rcpOrientedEta + computeNdotT()) - rcpOrientedEta * I; + } + + float3 doReflectRefract(bool r) + { + const float NdotTorR = r ? computeNdotT(): NdotI; + return N * (NdotI * (r ? rcpOrientedEta : 1.0) + NdotTorR) - I * (r ? rcpOrientedEta : 1.0); + } + + float3 I; + float3 N; + bool backside; + float NdotI; + float NdotI2; + float rcpOrientedEta; + float rcpOrientedEta2; +}; +} + +float3 refract(float3 I, float3 N, bool backside, float NdotI, float NdotI2, float rcpOrientedEta, float rcpOrientedEta2) +{ + impl::refract r = impl::refract::create(I, N, backside, NdotI, NdotI2, rcpOrientedEta, rcpOrientedEta2); + return r.doRefract(); +} + +float3 refract(float3 I, float3 N, float NdotI, float eta) +{ + impl::refract r = impl::refract::create(I, N, NdotI, eta); + return r.doRefract(); +} + +float3 refract(float3 I, float3 N, float eta) +{ + impl::refract r = impl::refract::create(I, N, eta); + return r.doRefract(); +} + +float3 reflectRefract(bool _refract, float3 I, float3 N, bool backside, float NdotI, float NdotI2, float rcpOrientedEta, float rcpOrientedEta2) +{ + impl::refract r = impl::refract::create(I, N, backside, NdotI, NdotI2, rcpOrientedEta, rcpOrientedEta2); + return r.doReflectRefract(_refract); +} + +float3 reflectRefract(bool _refract, float3 I, float3 N, float NdotI, float eta) +{ + impl::refract r = impl::refract::create(I, N, NdotI, eta); + return r.doReflectRefract(_refract); +} + + +// valid only for `theta` in [-PI,PI] +template ) +void sincos(T theta, out T s, out T c) +{ + c = cos(theta); + s = sqrt(1.0-c*c); + s = (theta < 0.0) ? -s : s; // TODO: test with XOR +} + +template ) +matrix frisvad(vector n) // TODO: confirm dimensions of matrix +{ + const float a = 1.0 / (1.0 + n.z); + const float b = -n.x * n.y * a; + return (n.z < -0.9999999) ? matrix(vector(0.0,-1.0,0.0), vector(-1.0,0.0,0.0)) : + matrix(vector(1.0-n.x*n.x*a, b, -n.x), vector(b, 1.0-n.y*n.y*a, -n.y)); +} + +} +} +} + +#endif diff --git a/include/nbl/builtin/hlsl/type_traits.hlsl b/include/nbl/builtin/hlsl/type_traits.hlsl index 58cedd81dd..d672173c20 100644 --- a/include/nbl/builtin/hlsl/type_traits.hlsl +++ b/include/nbl/builtin/hlsl/type_traits.hlsl @@ -699,6 +699,21 @@ struct unsigned_integer_of_size<8> template using unsigned_integer_of_size_t = typename unsigned_integer_of_size::type; + +template::value> +struct dimensions : integral_constant {}; + +template +struct dimensions : integral_constant {}; + +template +struct dimensions,false> : integral_constant {}; + +// matrix? + +template +NBL_CONSTEXPR uint32_t dimensions_v = dimensions::value; + } } From 6253da8bdcd4c4f3fa8d14011159a8dcf85f01d0 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 27 Nov 2024 16:53:01 +0700 Subject: [PATCH 006/188] template conditionalabs --- include/nbl/builtin/hlsl/math/functions.hlsl | 47 ++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/include/nbl/builtin/hlsl/math/functions.hlsl b/include/nbl/builtin/hlsl/math/functions.hlsl index c02c5c4777..3f16b8ae9b 100644 --- a/include/nbl/builtin/hlsl/math/functions.hlsl +++ b/include/nbl/builtin/hlsl/math/functions.hlsl @@ -254,6 +254,53 @@ matrix frisvad(vector n) // TODO: confirm dimensions of matrix matrix(vector(1.0-n.x*n.x*a, b, -n.x), vector(b, 1.0-n.y*n.y*a, -n.y)); } +bool partitionRandVariable(in float leftProb, inout float xi, out float rcpChoiceProb) +{ + NBL_CONSTEXPR float NEXT_ULP_AFTER_UNITY = asfloat(0x3f800001u); + const bool pickRight = xi >= leftProb * NEXT_ULP_AFTER_UNITY; + + // This is all 100% correct taking into account the above NEXT_ULP_AFTER_UNITY + xi -= pickRight ? leftProb : 0.0; + + rcpChoiceProb = 1.0 / (pickRight ? (1.0 - leftProb) : leftProb); + xi *= rcpChoiceProb; + + return pickRight; +} + + +// @ return abs(x) if cond==true, max(x,0.0) otherwise +template || is_vector_v) +T conditionalAbsOrMax(bool cond, T x, T limit); + +template <> +float conditionalAbsOrMax(bool cond, float x, float limit) +{ + const float condAbs = asfloat(asuint(x) & uint(cond ? 0x7fFFffFFu:0xffFFffFFu)); + return max(condAbs,limit); +} + +template <> +float2 conditionalAbsOrMax(bool cond, float2 x, float2 limit) +{ + const float2 condAbs = asfloat(asuint(x) & select(cond, (uint2)0x7fFFffFFu, (uint2)0xffFFffFFu)); + return max(condAbs,limit); +} + +template <> +float3 conditionalAbsOrMax(bool cond, float3 x, float3 limit) +{ + const float3 condAbs = asfloat(asuint(x) & select(cond, (uint3)0x7fFFffFFu, (uint3)0xffFFffFFu)); + return max(condAbs,limit); +} + +template <> +float4 conditionalAbsOrMax(bool cond, float4 x, float4 limit) +{ + const float4 condAbs = asfloat(asuint(x) & select(cond, (uint4)0x7fFFffFFu, (uint4)0xffFFffFFu)); + return max(condAbs,limit); +} + } } } From d13cad45306a0a4f34549fa95eff1b6e72660278 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 28 Nov 2024 14:13:02 +0700 Subject: [PATCH 007/188] completed adapting functions? --- include/nbl/builtin/hlsl/math/functions.hlsl | 218 ++++++++++++++++++- 1 file changed, 217 insertions(+), 1 deletion(-) diff --git a/include/nbl/builtin/hlsl/math/functions.hlsl b/include/nbl/builtin/hlsl/math/functions.hlsl index 3f16b8ae9b..ab48bb574b 100644 --- a/include/nbl/builtin/hlsl/math/functions.hlsl +++ b/include/nbl/builtin/hlsl/math/functions.hlsl @@ -5,6 +5,8 @@ #define _NBL_BUILTIN_HLSL_MATH_FUNCTIONS_INCLUDED_ #include +#include "nbl/builtin/hlsl/numbers.hlsl" +#include "nbl/builtin/hlsl/spirv_intrinsics/core.hlsl" namespace nbl { @@ -246,7 +248,7 @@ void sincos(T theta, out T s, out T c) } template ) -matrix frisvad(vector n) // TODO: confirm dimensions of matrix +matrix frisvad(vector n) // TODO: confirm dimensions of matrix { const float a = 1.0 / (1.0 + n.z); const float b = -n.x * n.y * a; @@ -301,6 +303,220 @@ float4 conditionalAbsOrMax(bool cond, float4 x, float4 limit) return max(condAbs,limit); } +namespace impl +{ +struct bitFields // need template? +{ + using this_t = bitFields; + + static this_t create(uint base, uint value, uint offset, uint count) + { + this_t retval; + retval.base = base; + retval.value = value; + retval.offset = offset; + retval.count = count; + return retval; + } + + uint __insert() + { + const uint shifted_masked_value = (value & ((0x1u << count) - 1u)) << offset; + const uint lo = base & ((0x1u << offset) - 1u); + const uint hi = base ^ lo; + return (hi << count) | shifted_masked_value | lo; + } + + uint __overwrite() + { + return spirv::bitFieldInsert(base, value, offset, count); + } + + uint base; + uint value; + uint offset; + uint count; +}; +} + +uint bitFieldOverwrite(uint base, uint value, uint offset, uint count) +{ + impl::bitFields b = impl::bitFields::create(base, value, offset, count); + return b.__overwrite(); +} + +uint bitFieldInsert(uint base, uint value, uint offset, uint count) +{ + impl::bitFields b = impl::bitFields::create(base, value, offset, count); + return b.__insert(); +} + +namespace impl +{ +struct trigonometry +{ + using this_t = trigonometry; + + static this_t create() + { + this_t retval; + retval.tmp0 = 0; + retval.tmp1 = 0; + retval.tmp2 = 0; + retval.tmp3 = 0; + retval.tmp4 = 0; + retval.tmp5 = 0; + return retval; + } + + static this_t create(float cosA, float cosB, float cosC, float sinA, float sinB, float sinC) + { + this_t retval; + retval.tmp0 = cosA; + retval.tmp1 = cosB; + retval.tmp2 = cosC; + retval.tmp3 = sinA; + retval.tmp4 = sinB; + retval.tmp5 = sinC; + return retval; + } + + float getArccosSumofABC_minus_PI() + { + const bool AltminusB = tmp0 < (-tmp1); + const float cosSumAB = tmp0 * tmp1 - tmp3 * tmp4; + const bool ABltminusC = cosSumAB < (-tmp2); + const bool ABltC = cosSumAB < tmp2; + // apply triple angle formula + const float absArccosSumABC = acos(clamp(cosSumAB * tmp2 - (tmp0 * tmp4 + tmp3 * tmp1) * tmp5, -1.f, 1.f)); + return ((AltminusB ? ABltC : ABltminusC) ? (-absArccosSumABC) : absArccosSumABC) + (AltminusB | ABltminusC ? numbers::pi : (-numbers::pi)); + } + + static void combineCosForSumOfAcos(float cosA, float cosB, float biasA, float biasB, out float out0, out float out1) + { + const float bias = biasA + biasB; + const float a = cosA; + const float b = cosB; + const bool reverse = abs(min(a, b)) > max(a, b); + const float c = a * b - sqrt((1.0f - a * a) * (1.0f - b * b)); + + if (reverse) + { + out0 = -c; + out1 = bias + numbers::pi; + } + else + { + out0 = c; + out1 = bias; + } + } + + float tmp0; + float tmp1; + float tmp2; + float tmp3; + float tmp4; + float tmp5; +}; +} + +float getArccosSumofABC_minus_PI(float cosA, float cosB, float cosC, float sinA, float sinB, float sinC) +{ + impl::trigonometry trig = impl::trigonometry::create(cosA, cosB, cosC, sinA, sinB, sinC); + return trig.getArccosSumofABC_minus_PI(); +} + +void combineCosForSumOfAcos(float cosA, float cosB, float biasA, float biasB, out float out0, out float out1) +{ + impl::trigonometry trig = impl::trigonometry::create(); + impl::trigonometry::combineCosForSumOfAcos(cosA, cosB, biasA, biasB, trig.tmp0, trig.tmp1); + out0 = trig.tmp0; + out1 = trig.tmp1; +} + +// returns acos(a) + acos(b) +float getSumofArccosAB(float cosA, float cosB) +{ + impl::trigonometry trig = impl::trigonometry::create(); + impl::trigonometry::combineCosForSumOfAcos(cosA, cosB, 0.0f, 0.0f, trig.tmp0, trig.tmp1); + return acos(trig.tmp0) + trig.tmp1; +} + +// returns acos(a) + acos(b) + acos(c) + acos(d) +float getSumofArccosABCD(float cosA, float cosB, float cosC, float cosD) +{ + impl::trigonometry trig = impl::trigonometry::create(); + impl::trigonometry::combineCosForSumOfAcos(cosA, cosB, 0.0f, 0.0f, trig.tmp0, trig.tmp1); + impl::trigonometry::combineCosForSumOfAcos(cosC, cosD, 0.0f, 0.0f, trig.tmp2, trig.tmp3); + impl::trigonometry::combineCosForSumOfAcos(trig.tmp0, trig.tmp2, trig.tmp1, trig.tmp3, trig.tmp4, trig.tmp5); + return acos(trig.tmp4) + trig.tmp5; +} + +namespace impl +{ +template +struct applyChainRule4D +{ + static matrix __call(matrix dFdG, matrix dGdR) + { + return mul(dFdG, dGdR); + } +}; + +template +struct applyChainRule3D : applyChainRule4D +{ + static vector __call(matrix dFdG, vector dGdR) + { + return mul(dFdG, dGdR); + } +}; + +template +struct applyChainRule2D : applyChainRule4D +{ + static vector __call(vector dFdG, T dGdR) + { + return mul(dFdG, dGdR); + } +}; + +template +struct applyChainRule1D : applyChainRule4D +{ + static T __call(T dFdG, T dGdR) + { + return dFdG * dGdR; + } +}; +} + +// possible to derive M,N,P automatically? +template && M>1 && N>1 && P>1) +matrix applyChainRule(matrix dFdG, matrix dGdR) +{ + return impl::applyChainRule4D::__call(dFdG, dGdR); +} + +template && M>1 && N>1) +vector applyChainRule(matrix dFdG, vector dGdR) +{ + return impl::applyChainRule3D::__call(dFdG, dGdR); +} + +template && M>1) +vector applyChainRule(vector dFdG, T dGdR) +{ + return impl::applyChainRule2D::__call(dFdG, dGdR); +} + +template) +T applyChainRule(T dFdG, T dGdR) +{ + return impl::applyChainRule1D::__call(dFdG, dGdR); +} + } } } From 7110c504d0768f3d03f439e40a322f55a53ff9c4 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 28 Nov 2024 17:13:49 +0700 Subject: [PATCH 008/188] added bxdf concept --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 53 +++++++++++++++++-- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 16 +++--- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 16 +++--- 3 files changed, 67 insertions(+), 18 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 49c5900769..bd8c2a7f22 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -665,13 +665,35 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache }; +// don't know what this concept is for yet +#define NBL_CONCEPT_NAME generalized_spectral_of +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(F) +#define NBL_CONCEPT_PARAM_0 (spec,T) +#define NBL_CONCEPT_PARAM_1 (field,F) +NBL_CONCEPT_BEGIN(3) +#define spec NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +#define field NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((spec[field]), ::nbl::hlsl::is_scalar_v)) // correctness? + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((spec * field), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((field * spec), ::nbl::hlsl::is_same_v, T)) +) && is_scalar_v; +#undef field +#undef spec +#include + +template +NBL_BOOL_CONCEPT spectral_of = generalized_spectral_of || is_vector_v || is_scalar_v; + // finally fixed the semantic F-up, value/pdf = quotient not remainder -template +template && is_floating_point_v) struct quotient_and_pdf { - quotient_and_pdf create(const SpectralBins _quotient, const float _pdf) + using this_t = quotient_and_pdf; + static this_t create(NBL_CONST_REF_ARG(SpectralBins) _quotient, NBL_CONST_REF_ARG(Pdf) _pdf) { - quotient_and_pdf retval; + this_t retval; retval.quotient = _quotient; retval.pdf = _pdf; return retval; @@ -683,9 +705,32 @@ struct quotient_and_pdf } SpectralBins quotient; - float pdf; + Pdf pdf; }; +typedef quotient_and_pdf quotient_and_pdf_scalar; +typedef quotient_and_pdf, float32_t> quotient_and_pdf_rgb; + + +#define NBL_CONCEPT_NAME BxDF +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename)(typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(LS)(Q)(S)(P) +#define NBL_CONCEPT_PARAM_0 (bxdf,T) +#define NBL_CONCEPT_PARAM_1 (spec,S) +#define NBL_CONCEPT_PARAM_2 (pdf,P) +NBL_CONCEPT_BEGIN(3) +#define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +#define spec NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 +#define pdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.eval()), ::nbl::hlsl::is_same_v, S)) // function parameters? + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.generate()), ::nbl::hlsl::is_same_v, LS)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.quotient_and_pdf()), ::nbl::hlsl::is_same_v, Q)) +) && Sample && spectral_of && is_floating_point_v

; +#undef pdf +#undef spec +#undef bxdf +#include } } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 878cd7b6f3..6ad474714b 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -15,22 +15,24 @@ namespace bxdf namespace reflection { -template -LightSample cos_generate(const surface_interactions::Isotropic interaction) +template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) +LightSample cos_generate(NBL_CONST_REF_ARG(Iso) interaction) { - return LightSample(interaction.V.reflect(interaction.N,interaction.NdotV),interaction.NdotV,interaction.N); + return LightSample(interaction.V.reflect(interaction.N,interaction.NdotV),interaction.NdotV,interaction.N); } -template -LightSample cos_generate(const surface_interactions::Anisotropic interaction) +template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) +LightSample cos_generate(NBL_CONST_REF_ARG(Aniso) interaction) { - return LightSample(interaction.V.reflect(interaction.N,interaction.NdotV),interaction.NdotV,interaction.T,interaction.B,interaction.N); + return LightSample(interaction.V.reflect(interaction.N,interaction.NdotV),interaction.NdotV,interaction.T,interaction.B,interaction.N); } // for information why we don't check the relation between `V` and `L` or `N` and `H`, see comments for `nbl::hlsl::transmission::cos_quotient_and_pdf` template quotient_and_pdf cos_quotient_and_pdf() { - return quotient_and_pdf::create(SpectralBins(1.f),nbl::hlsl::numeric_limits::inf()); + return quotient_and_pdf::create(SpectralBins(1.f),nbl::hlsl::numeric_limits::inf()); } } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index ff708548b8..fa685d9fef 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -15,15 +15,17 @@ namespace bxdf namespace transmission { -template -LightSample cos_generate(const surface_interactions::Isotropic interaction) +template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) +LightSample cos_generate(NBL_CONST_REF_ARG(Iso) interaction) { - return LightSample(interaction.V.transmit(),-1.f,interaction.N); + return LightSample(interaction.V.transmit(),-1.f,interaction.N); } -template -LightSample cos_generate(const surface_interactions::Anisotropic interaction) +template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) +LightSample cos_generate(NBL_CONST_REF_ARG(Aniso) interaction) { - return LightSample(interaction.V.transmit(),-1.f,interaction.T,interaction.B,interaction.N); + return LightSample(interaction.V.transmit(),-1.f,interaction.T,interaction.B,interaction.N); } // Why don't we check that the incoming and outgoing directions equal each other @@ -35,7 +37,7 @@ LightSample cos_generate(const surface_interactions::Anisotropic quotient_and_pdf cos_quotient_and_pdf() { - return quotient_and_pdf::create(SpectralBins(1.f),nbl::hlsl::numeric_limits::inf()); + return quotient_and_pdf::create(SpectralBins(1.f),nbl::hlsl::numeric_limits::inf()); } } From 98a0be1d7428277e8932c71286265b100710dc35 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 29 Nov 2024 12:03:23 +0700 Subject: [PATCH 009/188] fresnel function templates --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 89 +++++++++++++++++++++-- 1 file changed, 82 insertions(+), 7 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index bd8c2a7f22..ea4f4761c2 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -479,7 +479,7 @@ struct SIsotropicMicrofacetCache const bool transmitted = isTransmissionPath(NdotV,NdotL); float orientedEta, rcpOrientedEta; - const bool backside = getOrientedEtas(orientedEta,rcpOrientedEta,NdotV,eta); + const bool backside = math::getOrientedEtas(orientedEta,rcpOrientedEta,NdotV,eta); const vector_t V = interaction.V.getDirection(); const vector_t L = _sample.L; @@ -671,11 +671,11 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache #define NBL_CONCEPT_TPLT_PRM_NAMES (T)(F) #define NBL_CONCEPT_PARAM_0 (spec,T) #define NBL_CONCEPT_PARAM_1 (field,F) -NBL_CONCEPT_BEGIN(3) +NBL_CONCEPT_BEGIN(2) #define spec NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define field NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((spec[field]), ::nbl::hlsl::is_scalar_v)) // correctness? + //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((spec[field]), ::nbl::hlsl::is_scalar_v)) // correctness? ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((spec * field), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((field * spec), ::nbl::hlsl::is_same_v, T)) ) && is_scalar_v; @@ -714,24 +714,99 @@ typedef quotient_and_pdf, float32_t> quotient_and_pdf_rgb; #define NBL_CONCEPT_NAME BxDF #define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename)(typename) -#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(LS)(Q)(S)(P) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(LS)(SI)(Q)(S)(P) #define NBL_CONCEPT_PARAM_0 (bxdf,T) #define NBL_CONCEPT_PARAM_1 (spec,S) #define NBL_CONCEPT_PARAM_2 (pdf,P) +#define NBL_CONCEPT_PARAM_3 (sample_,LS) +#define NBL_CONCEPT_PARAM_4 (interaction,SI) NBL_CONCEPT_BEGIN(3) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define spec NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define pdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +#define sample_ NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 +#define interaction NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.eval()), ::nbl::hlsl::is_same_v, S)) // function parameters? - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.generate()), ::nbl::hlsl::is_same_v, LS)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.quotient_and_pdf()), ::nbl::hlsl::is_same_v, Q)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.eval(sample_,interaction)), ::nbl::hlsl::is_same_v, S)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.generate(interaction,interaction.N)), ::nbl::hlsl::is_same_v, LS)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.quotient_and_pdf(sample_,interaction)), ::nbl::hlsl::is_same_v, Q)) ) && Sample && spectral_of && is_floating_point_v

; +#undef interaction +#undef sample_ #undef pdf #undef spec #undef bxdf #include +// fresnel stuff +namespace impl +{ +template // but why would you not use float? +struct fresnel +{ + using vector_t = vector; + + static vector_t conductor(vector_t eta, vector_t etak, T cosTheta) + { + const T cosTheta2 = cosTheta * cosTheta; + //const float sinTheta2 = 1.0 - cosTheta2; + + const vector_t etaLen2 = eta * eta + etak * etak; + const vector_t etaCosTwice = eta * cosTheta * 2.0; + + const vector_t rs_common = etaLen2 + (vector_t)(cosTheta2); + const vector_t rs2 = (rs_common - etaCosTwice) / (rs_common + etaCosTwice); + + const vector_t rp_common = etaLen2 * cosTheta2 + (vector_t)(1.0); + const vector_t rp2 = (rp_common - etaCosTwice) / (rp_common + etaCosTwice); + + return (rs2 + rp2)*0.5; + } + + template + static U dielectric(U orientedEta2, T absCosTheta) + { + const T sinTheta2 = 1.0 - absCosTheta * absCosTheta; + + // the max() clamping can handle TIR when orientedEta2<1.0 + const U t0 = sqrt(max((U)(orientedEta2) - sinTheta2, (U)(0.0))); + const U rs = ((U)(absCosTheta) - t0) / ((U)(absCosTheta) + t0); + + const U t2 = orientedEta2 * absCosTheta; + const U rp = (t0 - t2) / (t0 + t2); + + return (rs * rs + rp * rp) * 0.5; + } +}; +} + +template) +vector fresnelSchlick(vector F0, T VdotH) +{ + T x = 1.0 - VdotH; + return F0 + (1.0 - F0) * x*x*x*x*x; +} + +template) +vector fresnelConductor(vector eta, vector etak, T cosTheta) +{ + return impl::fresnel::conductor(eta, etak, cosTheta); +} + +template && (is_scalar_v || is_vector_v)) +T fresnelDielectricFrontFaceOnly(T eta, U cosTheta) +{ + return impl::fresnel::template dielectric(eta * eta, cosTheta); +} + +template && (is_scalar_v || is_vector_v)) +T fresnelDielectric(T eta, U cosTheta) +{ + T orientedEta, rcpOrientedEta; + math::getOrientedEtas(orientedEta, rcpOrientedEta, cosTheta, eta); + return impl::fresnel::template dielectric(orientedEta * orientedEta, abs(cosTheta)); +} + } } } From eef66c6e909e1562b4f29d9b526dfa9ad993943d Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 29 Nov 2024 16:27:08 +0700 Subject: [PATCH 010/188] lambertian, oren nayar brdf --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 22 ++-- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 91 ++++++++++++++- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 6 +- .../hlsl/sampling/concentric_mapping.hlsl | 41 +++++++ .../builtin/hlsl/sampling/cos_weighted.hlsl | 107 ++++++++++++++++++ 5 files changed, 251 insertions(+), 16 deletions(-) create mode 100644 include/nbl/builtin/hlsl/sampling/concentric_mapping.hlsl create mode 100644 include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index ea4f4761c2..5bb2b1f4a4 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -713,25 +713,29 @@ typedef quotient_and_pdf, float32_t> quotient_and_pdf_rgb; #define NBL_CONCEPT_NAME BxDF -#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename)(typename) -#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(LS)(SI)(Q)(S)(P) +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename)(typename)(typename)(typename)(typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(LS)(I)(A)(Q)(S)(P) #define NBL_CONCEPT_PARAM_0 (bxdf,T) #define NBL_CONCEPT_PARAM_1 (spec,S) #define NBL_CONCEPT_PARAM_2 (pdf,P) #define NBL_CONCEPT_PARAM_3 (sample_,LS) -#define NBL_CONCEPT_PARAM_4 (interaction,SI) -NBL_CONCEPT_BEGIN(3) +#define NBL_CONCEPT_PARAM_4 (iso,I) +#define NBL_CONCEPT_PARAM_5 (aniso,A) +NBL_CONCEPT_BEGIN(4) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define spec NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define pdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 #define sample_ NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 -#define interaction NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 +#define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 +#define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.eval(sample_,interaction)), ::nbl::hlsl::is_same_v, S)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.generate(interaction,interaction.N)), ::nbl::hlsl::is_same_v, LS)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.quotient_and_pdf(sample_,interaction)), ::nbl::hlsl::is_same_v, Q)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template eval(sample_,iso)), ::nbl::hlsl::is_scalar_v)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template generate(aniso,aniso.N)), ::nbl::hlsl::is_same_v, LS)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template pdf(sample_,iso)), ::nbl::hlsl::is_scalar_v)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template quotient_and_pdf(sample_,iso)), ::nbl::hlsl::is_same_v, Q)) ) && Sample && spectral_of && is_floating_point_v

; -#undef interaction +#undef aniso +#undef iso #undef sample_ #undef pdf #undef spec diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 6ad474714b..375c7b71d9 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -4,7 +4,8 @@ #ifndef _NBL_BUILTIN_HLSL_BXDF_REFLECTION_INCLUDED_ #define _NBL_BUILTIN_HLSL_BXDF_REFLECTION_INCLUDED_ -#include +#include "nbl/builtin/hlsl/bxdf/common.hlsl" +#inclued "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" namespace nbl { @@ -15,6 +16,7 @@ namespace bxdf namespace reflection { +// still need these? template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) LightSample cos_generate(NBL_CONST_REF_ARG(Iso) interaction) @@ -29,12 +31,93 @@ LightSample cos_generate(NBL_CONST_REF_ARG(Aniso) interaction) } // for information why we don't check the relation between `V` and `L` or `N` and `H`, see comments for `nbl::hlsl::transmission::cos_quotient_and_pdf` -template -quotient_and_pdf cos_quotient_and_pdf() +template && is_floating_point_v) +quotient_and_pdf cos_quotient_and_pdf() { - return quotient_and_pdf::create(SpectralBins(1.f),nbl::hlsl::numeric_limits::inf()); + return quotient_and_pdf::create(SpectralBins(1.f),nbl::hlsl::numeric_limits::inf()); } + +template) +struct SLambertianBxDF +{ + template && surface_interactions::Isotropic) // maybe put template in struct vs function? + Scalar eval(LightSample _sample, Iso interaction) + { + return max(_sample.NdotL, 0.0) * numbers::inv_pi; + } + + template && surface_interactions::Anisotropic) + LightSample generate(Aniso interaction, vector u) + { + vector L = projected_hemisphere_generate(u); + return LightSample::createTangentSpace(interaction.getTangentSpaceV(), L, interaction.getTangentFrame()); + } + + template && surface_interactions::Isotropic) + Scalar pdf(LightSample _sample, Iso interaction) + { + return projected_hemisphere_pdf(max(_sample.NdotL, 0.0)); + } + + // TODO: check math here + template && Sample && surface_interactions::Anisotropic) + quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction) + { + Scalar pdf; + Scalar q = projected_hemisphere_quotient_and_pdf(pdf, max(_sample.NdotL, 0.0)); + return quotient_and_pdf::create(SpectralBins(q), pdf); + } +}; + + +template) +struct SOrenNayarBxDF +{ + using vector_t2 = vector; + + Scalar rec_pi_factored_out_wo_clamps(Scalar VdotL, Scalar maxNdotL, Scalar maxNdotV) + { + Scalar A2 = A * 0.5; + vector_t2 AB = vector_t2(1.0, 0.0) + vector_t2(-0.5, 0.45) * vector_t2(A2, A2) / vector_t2(A2 + 0.33, A2 + 0.09); + Scalar C = 1.0 / max(maxNdotL, maxNdotV); + + Scalar cos_phi_sin_theta = max(VdotL - maxNdotL * maxNdotV, 0.0); + return (AB.x + AB.y * cos_phi_sin_theta * C); + } + + template && surface_interactions::Isotropic) // maybe put template in struct vs function? + Scalar eval(LightSample _sample, Iso interaction) + { + return maxNdotL * numbers::inv_pi * rec_pi_factored_out_wo_clamps(_sample.VdotL, max(_sample.NdotL,0.0), max(interaction.NdotV,0.0)); + } + + template && surface_interactions::Anisotropic) + LightSample generate(Aniso interaction, vector u) + { + vector L = projected_hemisphere_generate(u); + return LightSample::createTangentSpace(interaction.getTangentSpaceV(), L, interaction.getTangentFrame()); + } + + template && surface_interactions::Isotropic) + Scalar pdf(LightSample _sample, Iso interaction) + { + return projected_hemisphere_pdf(max(_sample.NdotL, 0.0)); + } + + // TODO: check math here + template && Sample && surface_interactions::Anisotropic) + quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction) + { + Scalar pdf; + projected_hemisphere_quotient_and_pdf(pdf, max(_sample.NdotL, 0.0)); + Scalar q = rec_pi_factored_out_wo_clamps(_sample.VdotL, max(_sample.NdotL,0.0), max(interaction.NdotV,0.0)); + return quotient_and_pdf::create(SpectralBins(q), pdf); + } + + Scalar A; // set A first before eval +}; + } } } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index fa685d9fef..41cca108e3 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -34,10 +34,10 @@ LightSample cos_generate(NBL_CONST_REF_ARG(Aniso) interaction) // - Our own generator can never pick an improbable path, so no checking necessary // - For other generators the estimator will be `f_BSDF*f_Light*f_Visibility*clampedCos(theta)/(1+(p_BSDF^alpha+p_otherNonChosenGenerator^alpha+...)/p_ChosenGenerator^alpha)` // therefore when `p_BSDF` equals `nbl_glsl_FLT_INF` it will drive the overall MIS estimator for the other generators to 0 so no checking necessary -template -quotient_and_pdf cos_quotient_and_pdf() +template && is_floating_point_v) +quotient_and_pdf cos_quotient_and_pdf() { - return quotient_and_pdf::create(SpectralBins(1.f),nbl::hlsl::numeric_limits::inf()); + return quotient_and_pdf::create(SpectralBins(1.f),nbl::hlsl::numeric_limits::inf()); } } diff --git a/include/nbl/builtin/hlsl/sampling/concentric_mapping.hlsl b/include/nbl/builtin/hlsl/sampling/concentric_mapping.hlsl new file mode 100644 index 0000000000..c6e425e6c8 --- /dev/null +++ b/include/nbl/builtin/hlsl/sampling/concentric_mapping.hlsl @@ -0,0 +1,41 @@ +#ifndef _NBL_BUILTIN_HLSL_SAMPLING_CONCENTRIC_MAPPING_INCLUDED_ +#define _NBL_BUILTIN_HLSL_SAMPLING_CONCENTRIC_MAPPING_INCLUDED_ + +#include "nbl/builtin/hlsl/math/functions.hlsl" + +namespace nbl +{ +namespace hlsl +{ + +template +vector concentricMapping(vector _u) +{ + //map [0;1]^2 to [-1;1]^2 + vector u = 2.0 * _u - 1.0; + + vector p; + if (u == (vector)(0.0)) + p = (vector)(0.0); + else + { + T r; + T theta; + if (abs(u.x) > abs(u.y)) { + r = u.x; + theta = 0.25 * numbers::pi * (u.y / u.x); + } else { + r = u.y; + theta = 0.5 * numbers::pi - 0.25 * numbers::pi * (u.x / u.y); + } + + p = r * vector(cos(theta), sin(theta)); + } + + return p; +} + +} +} + +#endif \ No newline at end of file diff --git a/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl b/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl new file mode 100644 index 0000000000..311101d4fd --- /dev/null +++ b/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl @@ -0,0 +1,107 @@ +// Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h + +#ifndef _NBL_BUILTIN_HLSL_SAMPLING_COS_WEIGHTED_INCLUDED_ +#define _NBL_BUILTIN_HLSL_SAMPLING_COS_WEIGHTED_INCLUDED_ + +#include "nbl/builtin/hlsl/concepts.hlsl" +#include "nbl/builtin/hlsl/sampling/concentric_mapping.glsl" + +namespace nbl +{ +namespace hlsl +{ + +namespace impl +{ +template +struct ProjectedHemisphere +{ + using vector_t2 = vector; + using vector_t3 = vector; + + static vector_t3 generate(vector_t2 _sample) + { + vector_t2 p = concentricMapping(_sample * 0.99999 + 0.000005); + T z = sqrt(max(0.0, 1.0 - p.x * p.x - p.y * p.y)); + return vector_t3(p.x, p.y, z); + } + + static T pdf(T L_z) + { + return L_z * numbers::inv_pi; + } + + static T quotient_and_pdf(out T pdf, T L) + { + pdf = pdf(L); + return 1.0; + } +}; +} + +// probably could've split into separate structs and ProjectedSphere inherit ProjectedHemisphere +template) +vector projected_hemisphere_generate(vector _sample) +{ + return impl::ProjectedHemisphere::generate(_sample); +} + +template) +T projected_hemisphere_pdf(T L_z) +{ + return impl::ProjectedHemisphere::pdf(L_z); +} + +template) +T projected_hemisphere_quotient_and_pdf(out T pdf, T L) +{ + return impl::ProjectedHemisphere::quotient_and_pdf(pdf, L); +} + +template) +T projected_hemisphere_quotient_and_pdf(out T pdf, vector L) +{ + return impl::ProjectedHemisphere::quotient_and_pdf(pdf, L.z); +} + + +template) +vector projected_sphere_generate(vector _sample) +{ + vector retval = impl::ProjectedHemisphere::generate(_sample.xy); + const bool chooseLower = _sample.z > 0.5; + retval.z = chooseLower ? (-retval.z) : retval.z; + if (chooseLower) + _sample.z -= 0.5f; + _sample.z *= 2.f; + return retval; +} + +template) +T projected_sphere_pdf(T L_z) +{ + return 0.5 * impl::ProjectedHemisphere::pdf(L_z); +} + +template) +T projected_sphere_quotient_and_pdf(out T pdf, T L) +{ + T retval = impl::ProjectedHemisphere::quotient_and_pdf(pdf, L); + pdf *= 0.5; + return retval; +} + +template) +T projected_sphere_quotient_and_pdf(out T pdf, vector L) +{ + T retval = impl::ProjectedHemisphere::quotient_and_pdf(pdf, L.z); + pdf *= 0.5; + return retval; +} + +} +} + +#endif From eec84865bbc91c3c1fd0ec977ffe259ce3a0749d Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 2 Dec 2024 11:09:28 +0700 Subject: [PATCH 011/188] removed dimensions, extended rank/extent to vectors/matrix --- include/nbl/builtin/hlsl/math/functions.hlsl | 4 +- include/nbl/builtin/hlsl/type_traits.hlsl | 66 +++++++++----------- 2 files changed, 32 insertions(+), 38 deletions(-) diff --git a/include/nbl/builtin/hlsl/math/functions.hlsl b/include/nbl/builtin/hlsl/math/functions.hlsl index ab48bb574b..6f075e76ba 100644 --- a/include/nbl/builtin/hlsl/math/functions.hlsl +++ b/include/nbl/builtin/hlsl/math/functions.hlsl @@ -27,7 +27,7 @@ struct lp_norm static scalar_type_t __call(const T v) { scalar_type_t retval = abs(v[0]); - for (int i = 1; i < dimensions_v; i++) + for (int i = 1; i < rank::value; i++) retval = max(abs(v[i]),retval); return retval; } @@ -40,7 +40,7 @@ struct lp_norm static scalar_type_t __sum(const T v) { scalar_type_t retval = abs(v[0]); - for (int i = 1; i < dimensions_v; i++) + for (int i = 1; i < rank::value; i++) retval += abs(v[i]); return retval; } diff --git a/include/nbl/builtin/hlsl/type_traits.hlsl b/include/nbl/builtin/hlsl/type_traits.hlsl index d672173c20..85e442a3d0 100644 --- a/include/nbl/builtin/hlsl/type_traits.hlsl +++ b/include/nbl/builtin/hlsl/type_traits.hlsl @@ -363,27 +363,6 @@ struct is_compound : bool_constant::value> {}; template struct is_aggregate : is_compound {}; -template -struct rank : integral_constant { }; - -template -struct rank : integral_constant::value> { }; - -template -struct rank : integral_constant::value> { }; - -template -struct extent : integral_constant {}; - -template -struct extent : integral_constant {}; - -template -struct extent : integral_constant::value> {}; - -template -struct extent : integral_constant::value> {}; - template struct enable_if {}; @@ -648,6 +627,36 @@ template NBL_CONSTEXPR bool is_matrix_v = is_matrix::value; +#ifdef __HLSL_VERSION +template +struct rank : integral_constant::value ? 2 : (is_vector::value ? 1 : 0)> { }; + +template +struct rank : integral_constant::value> { }; + +template +struct rank : integral_constant::value> { }; + +template +struct extent : integral_constant {}; + +template +struct extent : integral_constant {}; + +template +struct extent : integral_constant::value> {}; + +template +struct extent : integral_constant::value> {}; + +template +struct extent, 0> : integral_constant {}; + +template +struct extent, I> : integral_constant::value> {}; +#endif + + template::value> struct scalar_type { @@ -699,21 +708,6 @@ struct unsigned_integer_of_size<8> template using unsigned_integer_of_size_t = typename unsigned_integer_of_size::type; - -template::value> -struct dimensions : integral_constant {}; - -template -struct dimensions : integral_constant {}; - -template -struct dimensions,false> : integral_constant {}; - -// matrix? - -template -NBL_CONSTEXPR uint32_t dimensions_v = dimensions::value; - } } From fcadc22e7d730cd157778b0212cc0380c3fcaeaa Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 2 Dec 2024 16:49:54 +0700 Subject: [PATCH 012/188] impl geom_smith and ndf funcs --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 11 + include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl | 236 ++++++++++++++++++ include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 144 +++++++++++ include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 4 +- 4 files changed, 393 insertions(+), 2 deletions(-) create mode 100644 include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl create mode 100644 include/nbl/builtin/hlsl/bxdf/ndf.hlsl diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 5bb2b1f4a4..80ec1b8094 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -811,6 +811,17 @@ T fresnelDielectric(T eta, U cosTheta) return impl::fresnel::template dielectric(orientedEta * orientedEta, abs(cosTheta)); } +template) +vector diffuseFresnelCorrectionFactor(vector n, vector n2) +{ + // assert(n*n==n2); + vector TIR = n < (vector)1.0; + vector invdenum = lerp((vector)1.0, (vector)1.0 / (n2 * n2 * ((vector)554.33 - 380.7 * n)), TIR); + vector num = n * lerp((vector)(0.1921156102251088), n * 298.25 - 261.38 * n2 + 138.43, TIR); + num += lerp((vector)(0.8078843897748912), (vector)(-1.67), TIR); + return num * invdenum; +} + } } } diff --git a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl new file mode 100644 index 0000000000..c18eda6d3a --- /dev/null +++ b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl @@ -0,0 +1,236 @@ +// Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_BUILTIN_HLSL_BXDF_GEOM_INCLUDED_ +#define _NBL_BUILTIN_HLSL_BXDF_GEOM_INCLUDED_ + +#include "nbl/builtin/hlsl/bxdf/ndf.hlsl" + +namespace nbl +{ +namespace hlsl +{ +namespace bxdf +{ +namespace smith +{ + +// TODO: need struct specializations? don't know which is used vs. helper + +template) +T G1(T lambda) +{ + return 1.0 / (1.0 + lambda); +} + +template) +T VNDF_pdf_wo_clamps(T ndf, T lambda_V, T maxNdotV, out T onePlusLambda_V) +{ + onePlusLambda_V = 1.0 + lambda_V; + + return ndf::microfacet_to_light_measure_transform(ndf / onePlusLambda_V, maxNdotV); +} + +template) +T VNDF_pdf_wo_clamps(T ndf, T lambda_V, T absNdotV, bool transmitted, T VdotH, T LdotH, T VdotHLdotH, T orientedEta, T reflectance, out T onePlusLambda_V) +{ + onePlusLambda_V = 1.0 + lambda_V; + + return ndf::microfacet_to_light_measure_transform((transmitted ? (1.0 - reflectance) : reflectance) * ndf / onePlusLambda_V, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); +} + +template) +T VNDF_pdf_wo_clamps(T ndf, T G1_over_2NdotV) +{ + return ndf * 0.5 * G1_over_2NdotV; +} + +template) +T FVNDF_pdf_wo_clamps(T fresnel_ndf, T G1_over_2NdotV, T absNdotV, bool transmitted, T VdotH, T LdotH, T VdotHLdotH, T orientedEta) +{ + T FNG = fresnel_ndf * G1_over_2NdotV; + T factor = 0.5; + if (transmitted) + { + const T VdotH_etaLdotH = (VdotH + orientedEta * LdotH); + // VdotHLdotH is negative under transmission, so this factor is negative + factor *= -2.0 * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); + } + return FNG * factor; +} + +template) +T VNDF_pdf_wo_clamps(T ndf, T G1_over_2NdotV, T absNdotV, bool transmitted, T VdotH, T LdotH, T VdotHLdotH, T orientedEta, T reflectance) +{ + T FN = (transmitted ? (1.0 - reflectance) : reflectance) * ndf; + return FVNDF_pdf_wo_clamps(FN, G1_over_2NdotV, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); +} + + +// beckmann +template) +T beckmann_C2(T NdotX2, T a2) +{ + return NdotX2 / (a2 * (1.0 - NdotX2)); +} + +template) +T beckmann_C2(T TdotX2, T BdotX2, T NdotX2, T ax2, T ay2) +{ + return NdotX2/(TdotX2 * ax2 + BdotX2 * ay2); +} + +template) +T beckmann_Lambda(T c2) +{ + T c = sqrt(c2); + T nom = 1.0 - 1.259 * c + 0.396 * c2; + T denom = 2.181 * c2 + 3.535 * c; + return lerp(0.0, nom / denom, c < 1.6); +} + +template) +T beckmann_Lambda(T NdotX2, T a2) +{ + return beckmann_Lambda(beckmann_C2(NdotX2, a2)); +} + +template) +T beckmann_Lambda(T TdotX2, T BdotX2, T NdotX2, T ax2, T ay2) +{ + return beckmann_Lambda(beckmann_C2(TdotX2, BdotX2, NdotX2, ax2, ay2)); +} + +template) +T beckmann_smith_correlated(T NdotV2, T NdotL2, T a2) +{ + T c2 = beckmann_C2(NdotV2, a2); + T L_v = beckmann_Lambda(c2); + c2 = beckmann_C2(NdotL2, a2); + T L_l = beckmann_Lambda(c2); + return G1(L_v + L_l); +} + +template) +T beckmann_smith_correlated(T TdotV2, T BdotV2, T NdotV2, T TdotL2, T BdotL2, T NdotL2, T ax2, T ay2) +{ + T c2 = beckmann_C2(TdotV2, BdotV2, NdotV2, ax2, ay2); + T L_v = beckmann_Lambda(c2); + c2 = beckmann_C2(TdotL2, BdotL2, NdotL2, ax2, ay2); + T L_l = beckmann_Lambda(c2); + return G1(L_v + L_l); +} + +template) +T beckmann_smith_G2_over_G1(T lambdaV_plus_one, T NdotL2, T a2) +{ + T lambdaL = beckmann_Lambda(NdotL2, a2); + return lambdaV_plus_one / (lambdaV_plus_one+lambdaL); +} + +template) +T beckmann_smith_G2_over_G1(T lambdaV_plus_one, T TdotL2, T BdotL2, T NdotL2, T ax2, T ay2) +{ + T c2 = beckmann_C2(TdotL2, BdotL2, NdotL2, ax2, ay2); + T lambdaL = beckmann_Lambda(c2); + return lambdaV_plus_one / (lambdaV_plus_one + lambdaL); +} + + +// ggx +template) +T ggx_devsh_part(T NdotX2, T a2, T one_minus_a2) +{ + return sqrt(a2 + one_minus_a2 * NdotX2); +} + +template) +T ggx_devsh_part(T TdotX2, T BdotX2, T NdotX2, T ax2, T ay2) +{ + return sqrt(TdotX2 * ax2 + BdotX2 * ay2 + NdotX2); +} + +template) +T ggx_G1_wo_numerator(T NdotX, T NdotX2, T a2, T one_minus_a2) +{ + return 1.0 / (NdotX + ggx_devsh_part(NdotX2,a2,one_minus_a2)); +} + +template) +T ggx_G1_wo_numerator(T NdotX, T TdotX2, T BdotX2, T NdotX2, T ax2, T ay2) +{ + return 1.0 / (NdotX + ggx_devsh_part(TdotX2, BdotX2, NdotX2, ax2, ay2)); +} + +template) +T ggx_G1_wo_numerator(T NdotX, T devsh_part) +{ + return 1.0 / (NdotX + devsh_part); +} + +template) +T ggx_correlated_wo_numerator(T NdotV, T NdotV2, T NdotL, T NdotL2, T a2, T one_minus_a2) +{ + T Vterm = NdotL * ggx_devsh_part(NdotV2,a2,one_minus_a2); + T Lterm = NdotV * ggx_devsh_part(NdotL2,a2,one_minus_a2); + return 0.5 / (Vterm + Lterm); +} + +template) +T ggx_correlated_wo_numerator(T NdotV, T NdotV2, T NdotL, T NdotL2, T a2) +{ + return ggx_correlated_wo_numerator(NdotV,NdotV2,NdotL,NdotL2,a2,1.0 - a2); +} + +template) +T ggx_correlated_wo_numerator(T NdotV, T TdotV2, T BdotV2, T NdotV2, T NdotL, T TdotL2, T BdotL2, T NdotL2, T ax2, T ay2) +{ + T Vterm = NdotL * ggx_devsh_part(TdotV2,BdotV2,NdotV2,ax2,ay2); + T Lterm = NdotV * ggx_devsh_part(TdotL2,BdotL2,NdotL2,ax2,ay2); + return 0.5 / (Vterm + Lterm); +} + +template) +T ggx_G2_over_G1(T NdotL, T NdotL2, T NdotV, T NdotV2, T a2, T one_minus_a2) +{ + T devsh_v = ggx_devsh_part(NdotV2,a2,one_minus_a2); + T G2_over_G1 = NdotL*(devsh_v + NdotV); // alternative `Vterm+NdotL*NdotV /// NdotL*NdotV could come as a parameter + G2_over_G1 /= NdotV*ggx_devsh_part(NdotL2,a2,one_minus_a2) + NdotL*devsh_v; + + return G2_over_G1; +} + +template) +T ggx_G2_over_G1_devsh(T NdotL, T NdotL2, T NdotV, T devsh_v, T a2, T one_minus_a2) +{ + T G2_over_G1 = NdotL*(devsh_v + NdotV); // alternative `Vterm+NdotL*NdotV /// NdotL*NdotV could come as a parameter + G2_over_G1 /= NdotV*ggx_devsh_part(NdotL2,a2,one_minus_a2) + NdotL*devsh_v; + + return G2_over_G1; +} + +template) +T ggx_G2_over_G1(T NdotL, T TdotL2, T BdotL2, T NdotL2, T NdotV, T TdotV2, T BdotV2, T NdotV2, T ax2, T ay2) +{ + T devsh_v = ggx_devsh_part(TdotV2,BdotV2,NdotV2,ax2,ay2); + T G2_over_G1 = NdotL*(devsh_v + NdotV); + G2_over_G1 /= NdotV*ggx_devsh_part(TdotL2,BdotL2,NdotL2,ax2,ay2) + NdotL*devsh_v; + + return G2_over_G1; +} + +template) +T ggx_G2_over_G1_devsh(T NdotL, T TdotL2, T BdotL2, T NdotL2, T NdotV, T devsh_v, T ax2, T ay2) +{ + T G2_over_G1 = NdotL*(devsh_v + NdotV); + G2_over_G1 /= NdotV*ggx_devsh_part(TdotL2,BdotL2,NdotL2,ax2,ay2) + NdotL*devsh_v; + + return G2_over_G1; +} + +} +} +} +} + +#endif \ No newline at end of file diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl new file mode 100644 index 0000000000..0c4ea17718 --- /dev/null +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -0,0 +1,144 @@ +// Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_BUILTIN_HLSL_BXDF_NDF_INCLUDED_ +#define _NBL_BUILTIN_HLSL_BXDF_NDF_INCLUDED_ + +#include "nbl/builtin/hlsl/limits.hlsl" +#include "nbl/builtin/hlsl/bxdf/common.hlsl" + +namespace nbl +{ +namespace hlsl +{ +namespace bxdf +{ +namespace ndf +{ + +// common +namespace impl +{ +template +struct microfacet_to_light_measure_transform +{ + static T __call(T NDFcos, T absNdotV, bool transmitted, T VdotH, T LdotH, T VdotHLdotH, T orientedEta) + { + T denominator = absNdotV; + if (transmitted) + { + const T VdotH_etaLdotH = (VdotH+orientedEta*LdotH); + // VdotHLdotH is negative under transmission, so thats denominator is negative + denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; + } + return NDFcos * (transmitted ? VdotHLdotH : 0.25) / denominator; + } + + static T __call(T NDFcos, T maxNdotV) + { + return 0.25 * NDFcos / maxNdotV; + } + +}; + +template +struct microfacet_to_light_measure_transform +{ + static T __call(T NDFcos_already_in_reflective_dL_measure, T absNdotL, bool transmitted, T VdotH, T LdotH, T VdotHLdotH, T orientedEta) + { + T denominator = absNdotL; + if (transmitted) + { + const T VdotH_etaLdotH = (VdotH+orientedEta*LdotH); + // VdotHLdotH is negative under transmission, so thats denominator is negative + denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; + } + return NDFcos_already_in_reflective_dL_measure * (transmitted ? VdotHLdotH : 0.25) / denominator; + } + + static T __call(T NDFcos_already_in_reflective_dL_measure, T maxNdotL) + { + return NDFcos_already_in_reflective_dL_measure * maxNdotL; + } +}; +} + +template) +T microfacet_to_light_measure_transform(T NDFcos, T absNdotV, bool transmitted, T VdotH, T LdotH, T VdotHLdotH, T orientedEta) +{ + return impl::microfacet_to_light_measure_transform::__call(NDFcos, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); +} + +template) +T microfacet_to_light_measure_transform(T NDFcos, T maxNdotV) +{ + return impl::microfacet_to_light_measure_transform::__call(NDFcos, maxNdotV); +} + + +// blinn-phong +template) +T blinn_phong(T NdotH, T n) +{ + return isinf(n) ? numeric_limits::infinity : numbers::inv_pi * 0.5 * (n + 2.0) * pow(NdotH,n); +} +//ashikhmin-shirley ndf +template) +T blinn_phong(T NdotH, T one_minus_NdotH2_rcp, T TdotH2, T BdotH2, T nx, T ny) +{ + T n = (TdotH2 * ny + BdotH2 * nx) * one_minus_NdotH2_rcp; + return (isinf(nx) || isinf(ny)) ? numeric_limits::infinity : sqrt((nx + 2.0) * (ny + 2.0)) * numbers::inv_pi * 0.5 * pow(NdotH, n); +} + + +// beckmann +template) +T beckmann(T a2, T NdotH2) +{ + T nom = exp( (NdotH2 - 1.0) / (a2 * NdotH2) ); // exp(x) == exp2(x/log(2)) ? + T denom = a2 * NdotH2 * NdotH2; + return numbers::inv_pi * nom / denom; +} + +template) +T beckmann(T ax, T ay, T ax2, T ay2, T TdotH2, T BdotH2, T NdotH2) +{ + T nom = exp(-(TdotH2 / ax2 + BdotH2 / ay2) / NdotH2); + T denom = ax * ay * NdotH2 * NdotH2; + return numbers::inv_pi * nom / denom; +} + + +// ggx +template) +T ggx_trowbridge_reitz(T a2, T NdotH2) +{ + T denom = NdotH2 * (a2 - 1.0) + 1.0; + return a2* numbers::inv_pi / (denom * denom); +} + +template) +T ggx_burley_aniso(T anisotropy, T a2, T TdotH, T BdotH, T NdotH) +{ + T antiAniso = 1.0 - anisotropy; + T atab = a2 * antiAniso; + T anisoTdotH = antiAniso * TdotH; + T anisoNdotH = antiAniso * NdotH; + T w2 = antiAniso/(BdotH * BdotH + anisoTdotH * anisoTdotH + anisoNdotH * anisoNdotH * a2); + return w2 * w2 * atab * numbers::inv_pi; +} + +template) +T ggx_aniso(T TdotH2, T BdotH2, T NdotH2, T ax, T ay, T ax2, T ay2) +{ + T a2 = ax * ay; + T denom = TdotH2 / ax2 + BdotH2 / ay2 + NdotH2; + return numbers::inv_pi / (a2 * denom * denom); +} + +} +} +} +} + +#endif \ No newline at end of file diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 375c7b71d9..14f263c79e 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -1,4 +1,4 @@ -// Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. +// Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h #ifndef _NBL_BUILTIN_HLSL_BXDF_REFLECTION_INCLUDED_ @@ -34,7 +34,7 @@ LightSample cos_generate(NBL_CONST_REF_ARG(Aniso) interaction) template && is_floating_point_v) quotient_and_pdf cos_quotient_and_pdf() { - return quotient_and_pdf::create(SpectralBins(1.f),nbl::hlsl::numeric_limits::inf()); + return quotient_and_pdf::create(SpectralBins(1.f), numeric_limits::infinity); } From 9742aa1e98f07eb80584806d236ddbb63f753423 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 3 Dec 2024 17:12:42 +0700 Subject: [PATCH 013/188] more bxdfs, fix concepts --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 50 +++- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 270 +++++++++++++++++- include/nbl/builtin/hlsl/math/functions.hlsl | 83 ++++++ 3 files changed, 394 insertions(+), 9 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 80ec1b8094..4f4a173893 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -154,8 +154,8 @@ NBL_CONCEPT_BEGIN(9) NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.T), ::nbl::hlsl::is_same_v, vector)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.B), ::nbl::hlsl::is_same_v, vector)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.TdotV), ::nbl::hlsl::is_same_v, vector)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.BdotV), ::nbl::hlsl::is_same_v, vector)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.TdotV), ::nbl::hlsl::is_same_v, U)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.BdotV), ::nbl::hlsl::is_same_v, U)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(iso,normT,normB)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(iso,normT)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(iso)), ::nbl::hlsl::is_same_v, T)) @@ -208,8 +208,8 @@ struct SAnisotropic : SIsotropic vector_t T; vector_t B; - vector_t TdotV; - vector_t BdotV; + U TdotV; + U BdotV; }; } @@ -721,7 +721,7 @@ typedef quotient_and_pdf, float32_t> quotient_and_pdf_rgb; #define NBL_CONCEPT_PARAM_3 (sample_,LS) #define NBL_CONCEPT_PARAM_4 (iso,I) #define NBL_CONCEPT_PARAM_5 (aniso,A) -NBL_CONCEPT_BEGIN(4) +NBL_CONCEPT_BEGIN(2) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define spec NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define pdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 @@ -729,11 +729,45 @@ NBL_CONCEPT_BEGIN(4) #define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 #define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template eval(sample_,iso)), ::nbl::hlsl::is_scalar_v)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template generate(aniso,aniso.N)), ::nbl::hlsl::is_same_v, LS)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template pdf(sample_,iso)), ::nbl::hlsl::is_scalar_v)) + //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template pdf(sample_,iso)), ::nbl::hlsl::is_scalar_v)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template quotient_and_pdf(sample_,iso)), ::nbl::hlsl::is_same_v, Q)) -) && Sample && spectral_of && is_floating_point_v

; +) && is_scalar_v(sample_,iso))> && && Sample && spectral_of && is_floating_point_v

; +#undef aniso +#undef iso +#undef sample_ +#undef pdf +#undef spec +#undef bxdf +#include + +#define NBL_CONCEPT_NAME MicrofacetBxDF +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename)(typename)(typename)(typename)(typename)(typename)(typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(LS)(IC)(AC)(I)(A)(Q)(S)(P) +#define NBL_CONCEPT_PARAM_0 (bxdf,T) +#define NBL_CONCEPT_PARAM_1 (spec,S) +#define NBL_CONCEPT_PARAM_2 (pdf,P) +#define NBL_CONCEPT_PARAM_3 (sample_,LS) +#define NBL_CONCEPT_PARAM_4 (iso,I) +#define NBL_CONCEPT_PARAM_5 (aniso,A) +#define NBL_CONCEPT_PARAM_4 (isocache,IC) +#define NBL_CONCEPT_PARAM_5 (anisocache,AC) +NBL_CONCEPT_BEGIN(1) +#define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +#define spec NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 +#define pdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +#define sample_ NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 +#define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 +#define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 +#define isocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 +#define anisocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_7 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template generate(aniso,aniso.N,anisocache)), ::nbl::hlsl::is_same_v, LS)) + //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template pdf(sample_,iso)), ::nbl::hlsl::is_scalar_v)) + //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template quotient_and_pdf(sample_,iso)), ::nbl::hlsl::is_same_v, Q)) +) && is_scalar_v(sample_,iso,isocache))> && Sample && spectral_of && is_floating_point_v

; +#undef anisocache +#undef isocache #undef aniso #undef iso #undef sample_ diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 14f263c79e..b287f7f76c 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -5,7 +5,8 @@ #define _NBL_BUILTIN_HLSL_BXDF_REFLECTION_INCLUDED_ #include "nbl/builtin/hlsl/bxdf/common.hlsl" -#inclued "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" +#include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" +#include "nbl/builtin/hlsl/bxdf/geom_smith.hlsl" namespace nbl { @@ -118,6 +119,273 @@ struct SOrenNayarBxDF Scalar A; // set A first before eval }; +template) +struct SBlinnPhongBxDF +{ + using vector_t2 = vector; + using vector_t3 = vector; + + template + static T phong_exp_to_alpha2(T n) + { + return 2.0 / (n + 2.0); + } + + template + static T alpha2_to_phong_exp(T a2) + { + return 2.0 / a2 - 2.0; + } + + template // this or specialize? + Scalar eval_DG_wo_clamps(vector_t2 a2) + { + if (aniso) + { + Scalar DG = ndf::blinn_phong(NdotH, 1.0 / (1.0 - NdotH2), TdotH2, BdotH2, n.x, n.y); + if (any(a2 > numeric_limits::min)) + DG *= smith::beckmann_smith_correlated(TdotV2, BdotV2, NdotV2, TdotL2, BdotL2, NdotL2, a2.x, a2.y); + return DG; + } + else + { + Scalar NG = ndf::blinn_phong(NdotH, n); + if (any(a2 > numeric_limits::min)) + NG *= smith::beckmann_smith_correlated(NdotV2, NdotL2, a2.x); + return NG; + } + } + + template + vector_t3 eval_wo_clamps() + { + Scalar scalar_part; + if (aniso) + { + vector_t2 a2 = phong_exp_to_alpha2(n); + scalar_part = eval_DG_wo_clamps(NdotH, NdotV2, NdotL2, a2); + } + else + { + vector_t2 a2 = (vector_t2)phong_exp_to_alpha2(n); + scalar_part = eval_DG_wo_clamps(NdotH, NdotV2, NdotL2, a2); + } + return fresnelConductor(ior[0], ior[1], VdotH) * microfacet_to_light_measure_transform(scalar_part, NdotV); + } + + template && surface_interactions::Isotropic && IsotropicMicrofacetCache) // maybe put template in struct vs function? + vector_t3 eval(LightSample _sample, Iso interaction, Cache cache) + { + if (interaction.NdotV > numeric_limits::min) + { + // maybe make in static method? + NdotH = cache.NdotH; + NdotV = interaction.NdotV; + NdotV2 = interaction.NdotV2; + NdotL2 = _sample.NdotL2; + VdotH = cache.VdotH; + return eval_wo_clamps(); + } + else + return (vector_t3)0.0; + } + + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) // maybe put template in struct vs function? + vector_t3 eval(LightSample _sample, Aniso interaction, Cache cache) + { + if (interaction.NdotV > numeric_limits::min) + { + // maybe make in static method? + NdotH = cache.NdotH; + NdotV = interaction.NdotV; + NdotV2 = interaction.NdotV2; + NdotL2 = _sample.NdotL2; + VdotH = cache.VdotH; + NdotH2 = cache.NdotH2; + TdotH2 = cache.TdotH * cache.TdotH; + BdotH2 = cache.BdotH * cache.BdotH; + TdotL2 = _sample.TdotL * _sample.TdotL; + BdotL2 = _sample.BdotL * _sample.BdotL; + TdotV2 = interaction.TdotV * interaction.TdotV; + BdotV2 = interaction.BdotV * interaction.BdotV; + return eval_wo_clamps(); + } + else + return (vector_t3)0.0; + } + + vector_t3 generate(vector u, Scalar n) + { + Scalar phi = 2.0 * numbers::pi; * u.y; + Scalar cosTheta = pow(u.x, 1.0/(n+1.0)); + Scalar sinTheta = sqrt(1.0 - cosTheta * cosTheta); + Scalar cosPhi = cos(phi); + Scalar sinPhi = sin(phi); + return vector_t3(cosPhi * sinTheta, sinPhi * sinTheta, cosTheta); + } + + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + LightSample generate(Aniso interaction, vector u, out Cache cache) + { + const vector_t3 H = generate(u, n.x); + const vector_t3 localV = interaction.getTangentSpaceV(); + + cache = Aniso::create(localV, H); + vector_t3 localL = math::reflect(localV, H, cache.VdotH); + + return LightSample::createTangentSpace(localV, localL, interaction.getTangentFrame()); + } + + // where pdf? + + // set these first before eval + vector_t2 n; + matrix ior; + + // iso + Scalar NdotH; + Scalar NdotV; + Scalar NdotV2; + Scalar NdotL2; + Scalar VdotH; + + // aniso + Scalar NdotH2; + Scalar TdotH2; + Scalar BdotH2; + Scalar TdotL2; + Scalar BdotL2; + Scalar TdotV2; + Scalar BdotV2; +}; + +template) +struct SBeckmannBxDF +{ + using vector_t2 = vector; + using vector_t3 = vector; + + template && surface_interactions::Isotropic && IsotropicMicrofacetCache) // maybe put template in struct vs function? + vector_t3 eval(LightSample _sample, Iso interaction, Cache cache) + { + // TODO + } + + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) // maybe put template in struct vs function? + vector_t3 eval(LightSample _sample, Aniso interaction, Cache cache) + { + // TODO + } + + vector_t3 generate(vector_t3 localV, vector_t2 u) + { + //stretch + vector_t3 V = normalize(vector_t3(A.x * localV.x, A.y * localV.y, localV.z)); + + vector_t2 slope; + if (V.z > 0.9999)//V.z=NdotV=cosTheta in tangent space + { + Scalar r = sqrt(-log(1.0 - u.x)); + Scalar sinPhi = sin(2.0 * numbers::pi * u.y); + Scalar cosPhi = cos(2.0 * numbers::pi * u.y); + slope = (vector_t2)r * vector_t2(cosPhi,sinPhi); + } + else + { + Scalar cosTheta = V.z; + Scalar sinTheta = sqrt(1.0 - cosTheta * cosTheta); + Scalar tanTheta = sinTheta / cosTheta; + Scalar cotTheta = 1.0 / tanTheta; + + Scalar a = -1.0; + Scalar c = math::erf(cosTheta); + Scalar sample_x = max(u.x, 1.0e-6); + Scalar theta = acos(cosTheta); + Scalar fit = 1.0 + theta * (-0.876 + theta * (0.4265 - 0.0594*theta)); + Scalar b = c - (1.0 + c) * pow(1.0-sample_x, fit); + + Scalar normalization = 1.0 / (1.0 + c + numbers::inv_sqrtpi * tanTheta * exp(-cosTheta*cosTheta)); + + const int ITER_THRESHOLD = 10; + const float MAX_ACCEPTABLE_ERR = 1.0e-5; + int it = 0; + float value=1000.0; + while (++itMAX_ACCEPTABLE_ERR) + { + if (!(b>=a && b<=c)) + b = 0.5 * (a+c); + + float invErf = math::erfInv(b); + value = normalization * (1.0 + b + numbers::inv_sqrtpi * tanTheta * exp(-invErf*invErf)) - sample_x; + float derivative = normalization * (1.0 - invErf*cosTheta); + + if (value > 0.0) + c = b; + else + a = b; + + b -= value/derivative; + } + // TODO: investigate if we can replace these two erf^-1 calls with a box muller transform + slope.x = math::erfInv(b); + slope.y = math::erfInv(2.0 * max(u.y,1.0e-6) - 1.0); + } + + Scalar sinTheta = sqrt(1.0 - V.z*V.z); + Scalar cosPhi = sinTheta==0.0 ? 1.0 : clamp(V.x/sinTheta, -1.0, 1.0); + Scalar sinPhi = sinTheta==0.0 ? 0.0 : clamp(V.y/sinTheta, -1.0, 1.0); + //rotate + Scalar tmp = cosPhi*slope.x - sinPhi*slope.y; + slope.y = sinPhi*slope.x + cosPhi*slope.y; + slope.x = tmp; + + //unstretch + slope = vector_t2(ax,ay)*slope; + + return normalize(vector_t3(-slope, 1.0)); + } + + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + LightSample generate(Aniso interaction, vector u, out Cache cache) + { + const vector_t3 localV = interaction.getTangentSpaceV(); + const vector_t3 H = generate(localV, u); + + cache = Aniso::create(localV, H); + vector_t3 localL = math::reflect(localV, H, cache.VdotH); + + return LightSample::createTangentSpace(localV, localL, interaction.getTangentFrame()); + } + + template && surface_interactions::Isotropic, && IsotropicMicrofacetCache) + Scalar pdf(LightSample _sample, Iso interaction, Cache cache) + { + Scalar NdotH2 = cache.NdotH2; + Scalar ndf = ndf::beckmann(A.x*A.x, NdotH2); + + const Scalar lambda = smith::beckmann_Lambda(interaction.NdotV2, A.x*A.x); + Scalar dummy; + return smith::VNDF_pdf_wo_clamps(ndf, lambda, interaction.NdotV, dummy); + } + + template && surface_interactions::Anisotropic, && AnisotropicMicrofacetCache) + Scalar pdf(LightSample _sample, Aniso interaction, Cache cache) + { + Scalar NdotH2 = cache.NdotH2; + Scalar ndf = ndf::beckmann(A.x, A.y, A.x*A.x, A.y*A.y, cache.TdotH * cache.TdotH, cache.BdotH * cache.BdotH, NdotH2); + + const Scalar c2 = smith::beckmann_C2(interaction.TdotV * interaction.TdotV, interaction.BdotV * interaction.BdotV, interaction.NdotV2, A.x, A.y); + Scalar lambda = smith::beckmann_Lambda(c2); + Scalar dummy; + return smith::VNDF_pdf_wo_clamps(ndf, lambda, interaction.NdotV, dummy); + } + + // TODO: remainder_and_pdf funcs + + // set these first before eval + vector_t2 A; +}; + } } } diff --git a/include/nbl/builtin/hlsl/math/functions.hlsl b/include/nbl/builtin/hlsl/math/functions.hlsl index 6f075e76ba..b1684f30de 100644 --- a/include/nbl/builtin/hlsl/math/functions.hlsl +++ b/include/nbl/builtin/hlsl/math/functions.hlsl @@ -15,6 +15,89 @@ namespace hlsl namespace math { +// TODO: move erfs to a tgmath.hlsl later +namespace impl +{ +template +struct erf; + +template<> +struct erf +{ + static float __call(float _x) + { + const float a1 = 0.254829592; + const float a2 = -0.284496736; + const float a3 = 1.421413741; + const float a4 = -1.453152027; + const float a5 = 1.061405429; + const float p = 0.3275911; + + float sign = sign(_x); + float x = abs(_x); + + float t = 1.0 / (1.0 + p*x); + float y = 1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * exp(-x * x); + + return sign * y; + } +}; + + +template +struct erfInv; + +template<> +struct erfInv +{ + static float __call(float _x) + { + float x = clamp(_x, -0.99999, 0.99999); + float w = -log((1.0-x) * (1.0+x)); + float p; + if (w<5.0) + { + w -= 2.5; + p = 2.81022636e-08; + p = 3.43273939e-07 + p*w; + p = -3.5233877e-06 + p*w; + p = -4.39150654e-06 + p*w; + p = 0.00021858087 + p*w; + p = -0.00125372503 + p*w; + p = -0.00417768164 + p*w; + p = 0.246640727 + p*w; + p = 1.50140941 + p*w; + } + else + { + w = sqrt(w) - 3.0; + p = -0.000200214257; + p = 0.000100950558 + p*w; + p = 0.00134934322 + p*w; + p = -0.00367342844 + p*w; + p = 0.00573950773 + p*w; + p = -0.0076224613 + p*w; + p = 0.00943887047 + p*w; + p = 1.00167406 + p*w; + p = 2.83297682 + p*w; + } + return p*x; + } +}; +} + +template +T erf(T _x) +{ + return impl::erf::__call(_x); +} + +template +T erfInv(T _x) +{ + return impl::erfInv::__call(_x); +} + namespace impl { template From 8433133bc94761510ca1e06407725096fcef9c8c Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 4 Dec 2024 17:05:28 +0700 Subject: [PATCH 014/188] restructure existing bxdfs --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 84 +++++ include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 302 ++++++++++++++---- 2 files changed, 317 insertions(+), 69 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 4f4a173893..6a47db0252 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -776,6 +776,90 @@ NBL_CONCEPT_END( #undef bxdf #include +template) +struct SBxDFParams +{ + using this_t = SBxDFParams; + + template && surface_interactions::Isotropic) // maybe put template in struct vs function? + static this_t create(LightSample _sample, Iso interaction) + { + this_t retval; + retval.NdotV = interaction.NdotV; + retval.NdotV2 = interaction.NdotV2; + retval.NdotL = _sample.NdotL; + retval.NdotL2 = _sample.NdotL2; + return retval; + } + + template && surface_interactions::Anisotropic) + static SBxDFParams create(LightSample _sample, Aniso interaction) + { + this_t retval; + retval.NdotV = interaction.NdotV; + retval.NdotV2 = interaction.NdotV2; + retval.NdotL = _sample.NdotL; + retval.NdotL2 = _sample.NdotL2; + + retval.TdotL2 = _sample.TdotL * _sample.TdotL; + retval.BdotL2 = _sample.BdotL * _sample.BdotL; + retval.TdotV2 = interaction.TdotV * interaction.TdotV; + retval.BdotV2 = interaction.BdotV * interaction.BdotV; + return retval; + } + + template && surface_interactions::Isotropic && IsotropicMicrofacetCache) // maybe put template in struct vs function? + static this_t create(LightSample _sample, Iso interaction, Cache cache) + { + this_t retval; + retval.NdotH = cache.NdotH; + retval.NdotV = interaction.NdotV; + retval.NdotV2 = interaction.NdotV2; + retval.NdotL = _sample.NdotL; + retval.NdotL2 = _sample.NdotL2; + retval.VdotH = cache.VdotH; + return retval; + } + + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + static SBxDFParams create(LightSample _sample, Aniso interaction, Cache cache) + { + this_t retval; + retval.NdotH = cache.NdotH; + retval.NdotV = interaction.NdotV; + retval.NdotV2 = interaction.NdotV2; + retval.NdotL = _sample.NdotL; + retval.NdotL2 = _sample.NdotL2; + retval.VdotH = cache.VdotH; + + retval.NdotH2 = cache.NdotH2; + retval.TdotH2 = cache.TdotH * cache.TdotH; + retval.BdotH2 = cache.BdotH * cache.BdotH; + retval.TdotL2 = _sample.TdotL * _sample.TdotL; + retval.BdotL2 = _sample.BdotL * _sample.BdotL; + retval.TdotV2 = interaction.TdotV * interaction.TdotV; + retval.BdotV2 = interaction.BdotV * interaction.BdotV; + return retval; + } + + // iso + Scalar NdotH; + Scalar NdotV; + Scalar NdotV2; + Scalar NdotL; + Scalar NdotL2; + Scalar VdotH; + + // aniso + Scalar NdotH2; + Scalar TdotH2; + Scalar BdotH2; + Scalar TdotL2; + Scalar BdotL2; + Scalar TdotV2; + Scalar BdotV2; +} + // fresnel stuff namespace impl { diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index b287f7f76c..92a0e88d25 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -38,36 +38,79 @@ quotient_and_pdf cos_quotient_and_pdf() return quotient_and_pdf::create(SpectralBins(1.f), numeric_limits::infinity); } +// new bxdf structure +// static create() method, takes light sample and interaction (and cache) as argument --> fill in _dot_ variables used in later calculations, return bxdf struct +// store them as well? + template) struct SLambertianBxDF { + static SLambertianBxDF create() + { + SLambertianBxDF retval; + // nothing here, just keeping in convention with others + return retval; + } + + Scalar __eval_pi_factored_out(Scalar maxNdotL) + { + return maxNdotL; + } + + template && surface_interactions::Isotropic) // maybe put template in struct vs function? + Scalar __eval_wo_clamps(LightSample _sample, Iso interaction) + { + // probably doesn't need to use the param struct + return __eval_pi_factored_out(_sample.NdotL) * numbers::inv_pi; + } + template && surface_interactions::Isotropic) // maybe put template in struct vs function? Scalar eval(LightSample _sample, Iso interaction) { - return max(_sample.NdotL, 0.0) * numbers::inv_pi; + // probably doesn't need to use the param struct + return __eval_pi_factored_out(max(_sample.NdotL, 0.0)) * numbers::inv_pi; } template && surface_interactions::Anisotropic) - LightSample generate(Aniso interaction, vector u) + LightSample generate_wo_clamps(Aniso interaction, vector u) { vector L = projected_hemisphere_generate(u); return LightSample::createTangentSpace(interaction.getTangentSpaceV(), L, interaction.getTangentFrame()); } + template && surface_interactions::Anisotropic) + LightSample generate(Aniso interaction, vector u) + { + return generate_wo_clamps(interaction, u); + } + + template && surface_interactions::Isotropic) + Scalar pdf_wo_clamps(LightSample _sample, Iso interaction) + { + return projected_hemisphere_pdf(_sample.NdotL); + } + template && surface_interactions::Isotropic) Scalar pdf(LightSample _sample, Iso interaction) { return projected_hemisphere_pdf(max(_sample.NdotL, 0.0)); } - // TODO: check math here + template && Sample && surface_interactions::Anisotropic) + quotient_and_pdf quotient_and_pdf_wo_clamps(LightSample _sample, Iso interaction) + { + Scalar pdf; + Scalar q = projected_hemisphere_quotient_and_pdf(pdf, _sample.NdotL); + return quotient_and_pdf::create(SpectralBins(q), pdf); + } + template && Sample && surface_interactions::Anisotropic) quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction) { Scalar pdf; Scalar q = projected_hemisphere_quotient_and_pdf(pdf, max(_sample.NdotL, 0.0)); - return quotient_and_pdf::create(SpectralBins(q), pdf); + return quotient_and_pdf::create(SpectralBins(q), pdf); } }; @@ -75,9 +118,17 @@ struct SLambertianBxDF template) struct SOrenNayarBxDF { + using this_t = SOrenNayarBxDF; using vector_t2 = vector; - Scalar rec_pi_factored_out_wo_clamps(Scalar VdotL, Scalar maxNdotL, Scalar maxNdotV) + static this_t create(Scalar A) + { + this_t retval; + retval.A = A; + return retval; + } + + Scalar __rec_pi_factored_out_wo_clamps(Scalar VdotL, Scalar maxNdotL, Scalar maxNdotV) { Scalar A2 = A * 0.5; vector_t2 AB = vector_t2(1.0, 0.0) + vector_t2(-0.5, 0.45) * vector_t2(A2, A2) / vector_t2(A2 + 0.33, A2 + 0.09); @@ -87,43 +138,80 @@ struct SOrenNayarBxDF return (AB.x + AB.y * cos_phi_sin_theta * C); } + template && surface_interactions::Isotropic) // maybe put template in struct vs function? + Scalar __eval_wo_clamps(LightSample _sample, Iso interaction) + { + return maxNdotL * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(_sample.VdotL, _sample.NdotL, interaction.NdotV); + } + template && surface_interactions::Isotropic) // maybe put template in struct vs function? Scalar eval(LightSample _sample, Iso interaction) { - return maxNdotL * numbers::inv_pi * rec_pi_factored_out_wo_clamps(_sample.VdotL, max(_sample.NdotL,0.0), max(interaction.NdotV,0.0)); + return maxNdotL * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(_sample.VdotL, max(_sample.NdotL,0.0), max(interaction.NdotV,0.0)); } template && surface_interactions::Anisotropic) - LightSample generate(Aniso interaction, vector u) + LightSample generate_wo_clamps(Aniso interaction, vector u) { vector L = projected_hemisphere_generate(u); return LightSample::createTangentSpace(interaction.getTangentSpaceV(), L, interaction.getTangentFrame()); } + template && surface_interactions::Anisotropic) + LightSample generate(Aniso interaction, vector u) + { + return generate_wo_clamps(interaction, u); + } + + template && surface_interactions::Isotropic) + Scalar pdf_wo_clamps(LightSample _sample, Iso interaction) + { + return projected_hemisphere_pdf(_sample.NdotL, 0.0); + } + template && surface_interactions::Isotropic) Scalar pdf(LightSample _sample, Iso interaction) { return projected_hemisphere_pdf(max(_sample.NdotL, 0.0)); } - // TODO: check math here - template && Sample && surface_interactions::Anisotropic) + // pdf type same as scalar? + template && Sample && surface_interactions::Anisotropic) + quotient_and_pdf quotient_and_pdf_wo_clamps(LightSample _sample, Iso interaction) + { + Scalar pdf; + projected_hemisphere_quotient_and_pdf(pdf, _sample.NdotL); + Scalar q = __rec_pi_factored_out_wo_clamps(_sample.VdotL, _sample.NdotL, interaction.NdotV); + return quotient_and_pdf::create(SpectralBins(q), pdf); + } + + template && Sample && surface_interactions::Anisotropic) quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction) { Scalar pdf; projected_hemisphere_quotient_and_pdf(pdf, max(_sample.NdotL, 0.0)); - Scalar q = rec_pi_factored_out_wo_clamps(_sample.VdotL, max(_sample.NdotL,0.0), max(interaction.NdotV,0.0)); + Scalar q = __rec_pi_factored_out_wo_clamps(_sample.VdotL, max(_sample.NdotL,0.0), max(interaction.NdotV,0.0)); return quotient_and_pdf::create(SpectralBins(q), pdf); } - Scalar A; // set A first before eval + Scalar A; }; template) struct SBlinnPhongBxDF { + using this_t = SBlinnPhongBxDF; using vector_t2 = vector; using vector_t3 = vector; + using params_t = SBxDFParams; + + static this_t create(vector_t2 n, matrix ior) + { + this_t retval; + retval.n = n; + retval.ior = ior; + return retval; + } template static T phong_exp_to_alpha2(T n) @@ -138,39 +226,39 @@ struct SBlinnPhongBxDF } template // this or specialize? - Scalar eval_DG_wo_clamps(vector_t2 a2) + Scalar __eval_DG_wo_clamps(params_t params, vector_t2 a2) { if (aniso) { - Scalar DG = ndf::blinn_phong(NdotH, 1.0 / (1.0 - NdotH2), TdotH2, BdotH2, n.x, n.y); - if (any(a2 > numeric_limits::min)) - DG *= smith::beckmann_smith_correlated(TdotV2, BdotV2, NdotV2, TdotL2, BdotL2, NdotL2, a2.x, a2.y); + Scalar DG = ndf::blinn_phong(params.NdotH, 1.0 / (1.0 - params.NdotH2), params.TdotH2, params.BdotH2, n.x, n.y); + if (any(a2 > numeric_limits::min)) + DG *= smith::beckmann_smith_correlated(params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, a2.x, a2.y); return DG; } else { - Scalar NG = ndf::blinn_phong(NdotH, n); - if (any(a2 > numeric_limits::min)) - NG *= smith::beckmann_smith_correlated(NdotV2, NdotL2, a2.x); + Scalar NG = ndf::blinn_phong(params.NdotH, n); + if (any(a2 > numeric_limits::min)) + NG *= smith::beckmann_smith_correlated(params.NdotV2, params.NdotL2, a2.x); return NG; } } template - vector_t3 eval_wo_clamps() + vector_t3 __eval_wo_clamps(params_t params) { Scalar scalar_part; if (aniso) { vector_t2 a2 = phong_exp_to_alpha2(n); - scalar_part = eval_DG_wo_clamps(NdotH, NdotV2, NdotL2, a2); + scalar_part = __eval_DG_wo_clamps(params, a2); } else { vector_t2 a2 = (vector_t2)phong_exp_to_alpha2(n); - scalar_part = eval_DG_wo_clamps(NdotH, NdotV2, NdotL2, a2); + scalar_part = __eval_DG_wo_clamps(params, a2); } - return fresnelConductor(ior[0], ior[1], VdotH) * microfacet_to_light_measure_transform(scalar_part, NdotV); + return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_to_light_measure_transform(scalar_part, params.NdotV); } template && surface_interactions::Isotropic && IsotropicMicrofacetCache) // maybe put template in struct vs function? @@ -178,13 +266,8 @@ struct SBlinnPhongBxDF { if (interaction.NdotV > numeric_limits::min) { - // maybe make in static method? - NdotH = cache.NdotH; - NdotV = interaction.NdotV; - NdotV2 = interaction.NdotV2; - NdotL2 = _sample.NdotL2; - VdotH = cache.VdotH; - return eval_wo_clamps(); + params_t params = params_t::template create(_sample, interaction, cache); + return __eval_wo_clamps(params); } else return (vector_t3)0.0; @@ -195,20 +278,8 @@ struct SBlinnPhongBxDF { if (interaction.NdotV > numeric_limits::min) { - // maybe make in static method? - NdotH = cache.NdotH; - NdotV = interaction.NdotV; - NdotV2 = interaction.NdotV2; - NdotL2 = _sample.NdotL2; - VdotH = cache.VdotH; - NdotH2 = cache.NdotH2; - TdotH2 = cache.TdotH * cache.TdotH; - BdotH2 = cache.BdotH * cache.BdotH; - TdotL2 = _sample.TdotL * _sample.TdotL; - BdotL2 = _sample.BdotL * _sample.BdotL; - TdotV2 = interaction.TdotV * interaction.TdotV; - BdotV2 = interaction.BdotV * interaction.BdotV; - return eval_wo_clamps(); + params_t params = params_t::template create(_sample, interaction, cache); + return __eval_wo_clamps(params); } else return (vector_t3)0.0; @@ -238,46 +309,98 @@ struct SBlinnPhongBxDF // where pdf? - // set these first before eval vector_t2 n; matrix ior; - - // iso - Scalar NdotH; - Scalar NdotV; - Scalar NdotV2; - Scalar NdotL2; - Scalar VdotH; - - // aniso - Scalar NdotH2; - Scalar TdotH2; - Scalar BdotH2; - Scalar TdotL2; - Scalar BdotL2; - Scalar TdotV2; - Scalar BdotV2; }; template) struct SBeckmannBxDF { - using vector_t2 = vector; - using vector_t3 = vector; + using this_t = SBeckmannBxDF; + using vector_t2 = vector; + using vector_t3 = vector; + using params_t = SBxDFParams; + + // iso + static this_t create(Scalar A,matrix ior;) + { + this_t retval; + retval.A = vector_t2(A,A); + retval.ior = ior; + return retval; + } + + // aniso + static this_t create(Scalar ax,Scalar ay,matrix ior;) + { + this_t retval; + retval.A = vector_t2(ax,ay); + retval.ior = ior; + return retval; + } + + template // this or specialize? + Scalar __eval_DG_wo_clamps(params_t params) + { + if (aniso) + { + const Scalar ax2 = A.x*A.x; + const Scalar ay2 = A.y*A.y; + Scalar NG = ndf::beckmann(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + if (any(A > numeric_limits::min)) + NG *= smith::beckmann_smith_correlated(params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, ay2, ax2); + return NG; + } + else + { + Scalar a2 = A.x*A.x; + Scalar NG = ndf::beckmann(a2, params.NdotH2); + if (a2 > numeric_limits::min) + NG *= smith::beckmann_smith_correlated(params.NdotV2, params.NdotL2, a2.x); + return NG; + } + } + + template + vector_t3 __eval_wo_clamps(params_t params) + { + Scalar scalar_part; + if (aniso) + { + scalar_part = __eval_DG_wo_clamps(params); + } + else + { + scalar_part = __eval_DG_wo_clamps(params); + } + return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_to_light_measure_transform(scalar_part, params.NdotV); + } template && surface_interactions::Isotropic && IsotropicMicrofacetCache) // maybe put template in struct vs function? vector_t3 eval(LightSample _sample, Iso interaction, Cache cache) { - // TODO + if (interaction.NdotV > numeric_limits::min) + { + params_t params = params_t::template create(_sample, interaction, cache); + return __eval_wo_clamps(params); + } + else + return (vector_t3)0.0; } template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) // maybe put template in struct vs function? vector_t3 eval(LightSample _sample, Aniso interaction, Cache cache) { - // TODO + if (interaction.NdotV > numeric_limits::min) + { + params_t params = params_t::template create(_sample, interaction, cache); + return __eval_wo_clamps(params); + } + else + return (vector_t3)0.0; } - vector_t3 generate(vector_t3 localV, vector_t2 u) + vector_t3 __generate(vector_t3 localV, vector_t2 u) { //stretch vector_t3 V = normalize(vector_t3(A.x * localV.x, A.y * localV.y, localV.z)); @@ -349,7 +472,7 @@ struct SBeckmannBxDF LightSample generate(Aniso interaction, vector u, out Cache cache) { const vector_t3 localV = interaction.getTangentSpaceV(); - const vector_t3 H = generate(localV, u); + const vector_t3 H = __generate(localV, u); cache = Aniso::create(localV, H); vector_t3 localL = math::reflect(localV, H, cache.VdotH); @@ -357,7 +480,7 @@ struct SBeckmannBxDF return LightSample::createTangentSpace(localV, localL, interaction.getTangentFrame()); } - template && surface_interactions::Isotropic, && IsotropicMicrofacetCache) + template && surface_interactions::Isotropic && IsotropicMicrofacetCache) Scalar pdf(LightSample _sample, Iso interaction, Cache cache) { Scalar NdotH2 = cache.NdotH2; @@ -368,7 +491,7 @@ struct SBeckmannBxDF return smith::VNDF_pdf_wo_clamps(ndf, lambda, interaction.NdotV, dummy); } - template && surface_interactions::Anisotropic, && AnisotropicMicrofacetCache) + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) Scalar pdf(LightSample _sample, Aniso interaction, Cache cache) { Scalar NdotH2 = cache.NdotH2; @@ -381,9 +504,50 @@ struct SBeckmannBxDF } // TODO: remainder_and_pdf funcs + template && Sample && surface_interactions::Isotropic && IsotropicMicrofacetCache) + quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction, Cache cache) + { + const Scalar ndf = ndf::beckmann(A.x*A.x, cache.NdotH2); + const Scalar lambda = smith::beckmann_Lambda(interaction.NdotV2, A.x*A.x); + + Scalar onePlusLambda_V; + Scalar pdf = smith::VNDF_pdf_wo_clamps(ndf, lambda, interaction.NdotV, onePlusLambda_V); + vector_t3 rem = (vector_t3)0.0; + if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) + { + const vector_t3 reflectance = fresnelConductor(ior[0], ior[1], cache.VdotH); + Scalar G2_over_G1 = smith::beckmann_smith_G2_over_G1(onePlusLambda_V, _sample.NdotL2, a2); + rem = reflectance * G2_over_G1; + } + + return quotient_and_pdf::create(SpectralBins(rem), pdf); + } + + template && Sample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + quotient_and_pdf quotient_and_pdf(LightSample _sample, Aniso interaction, Cache cache) + { + params_t params = params_t::template create(_sample, interaction, cache); + const Scalar ax2 = A.x*A.x; + const Scalar ay2 = A.y*A.y; + + const Scalar ndf = ndf::beckmann(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + Scalar onePlusLambda_V; + const Scalar c2 = smith::beckmann_C2(params.TdotV2, params.BdotV2, params.NdotV2, A.x, A.y); + Scalar lambda = smith::beckmann_Lambda(c2); + Scalar pdf = smith::VNDF_pdf_wo_clamps(ndf, lambda, interaction.NdotV, onePlusLambda_V); + vector_t3 rem = (vector_t3)0.0; + if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) + { + const vector_t3 reflectance = fresnel_conductor(ior[0], ior[1], cache.VdotH); + Scalar G2_over_G1 = smith::beckmann_smith_G2_over_G1(onePlusLambda_V, params.TdotL2, params.BdotL2, params.NdotL2, A.x, A.y); + rem = reflectance * G2_over_G1; + } + + return quotient_and_pdf::create(SpectralBins(rem), pdf); + } - // set these first before eval vector_t2 A; + matrix ior; }; } From bafe6239da4ea6d3f62fe33e6d2250b256b1d0a7 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 5 Dec 2024 11:45:26 +0700 Subject: [PATCH 015/188] ggx brdf --- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 257 ++++++++++++++++-- 1 file changed, 232 insertions(+), 25 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 92a0e88d25..bb75765fb9 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -258,13 +258,13 @@ struct SBlinnPhongBxDF vector_t2 a2 = (vector_t2)phong_exp_to_alpha2(n); scalar_part = __eval_DG_wo_clamps(params, a2); } - return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_to_light_measure_transform(scalar_part, params.NdotV); + return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_to_light_measure_transform(scalar_part, params.NdotV); } template && surface_interactions::Isotropic && IsotropicMicrofacetCache) // maybe put template in struct vs function? vector_t3 eval(LightSample _sample, Iso interaction, Cache cache) { - if (interaction.NdotV > numeric_limits::min) + if (interaction.NdotV > numeric_limits::min) { params_t params = params_t::template create(_sample, interaction, cache); return __eval_wo_clamps(params); @@ -276,7 +276,7 @@ struct SBlinnPhongBxDF template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) // maybe put template in struct vs function? vector_t3 eval(LightSample _sample, Aniso interaction, Cache cache) { - if (interaction.NdotV > numeric_limits::min) + if (interaction.NdotV > numeric_limits::min) { params_t params = params_t::template create(_sample, interaction, cache); return __eval_wo_clamps(params); @@ -322,7 +322,7 @@ struct SBeckmannBxDF using params_t = SBxDFParams; // iso - static this_t create(Scalar A,matrix ior;) + static this_t create(Scalar A,matrix ior) { this_t retval; retval.A = vector_t2(A,A); @@ -331,7 +331,7 @@ struct SBeckmannBxDF } // aniso - static this_t create(Scalar ax,Scalar ay,matrix ior;) + static this_t create(Scalar ax,Scalar ay,matrix ior) { this_t retval; retval.A = vector_t2(ax,ay); @@ -348,7 +348,7 @@ struct SBeckmannBxDF const Scalar ay2 = A.y*A.y; Scalar NG = ndf::beckmann(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); if (any(A > numeric_limits::min)) - NG *= smith::beckmann_smith_correlated(params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, ay2, ax2); + NG *= smith::beckmann_smith_correlated(params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, ax2, ay2); return NG; } else @@ -364,22 +364,14 @@ struct SBeckmannBxDF template vector_t3 __eval_wo_clamps(params_t params) { - Scalar scalar_part; - if (aniso) - { - scalar_part = __eval_DG_wo_clamps(params); - } - else - { - scalar_part = __eval_DG_wo_clamps(params); - } - return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_to_light_measure_transform(scalar_part, params.NdotV); + Scalar scalar_part = __eval_DG_wo_clamps(params); + return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_to_light_measure_transform(scalar_part, params.NdotV); } template && surface_interactions::Isotropic && IsotropicMicrofacetCache) // maybe put template in struct vs function? vector_t3 eval(LightSample _sample, Iso interaction, Cache cache) { - if (interaction.NdotV > numeric_limits::min) + if (interaction.NdotV > numeric_limits::min) { params_t params = params_t::template create(_sample, interaction, cache); return __eval_wo_clamps(params); @@ -391,7 +383,7 @@ struct SBeckmannBxDF template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) // maybe put template in struct vs function? vector_t3 eval(LightSample _sample, Aniso interaction, Cache cache) { - if (interaction.NdotV > numeric_limits::min) + if (interaction.NdotV > numeric_limits::min) { params_t params = params_t::template create(_sample, interaction, cache); return __eval_wo_clamps(params); @@ -503,7 +495,6 @@ struct SBeckmannBxDF return smith::VNDF_pdf_wo_clamps(ndf, lambda, interaction.NdotV, dummy); } - // TODO: remainder_and_pdf funcs template && Sample && surface_interactions::Isotropic && IsotropicMicrofacetCache) quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction, Cache cache) { @@ -512,15 +503,15 @@ struct SBeckmannBxDF Scalar onePlusLambda_V; Scalar pdf = smith::VNDF_pdf_wo_clamps(ndf, lambda, interaction.NdotV, onePlusLambda_V); - vector_t3 rem = (vector_t3)0.0; + vector_t3 quo = (vector_t3)0.0; if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { const vector_t3 reflectance = fresnelConductor(ior[0], ior[1], cache.VdotH); Scalar G2_over_G1 = smith::beckmann_smith_G2_over_G1(onePlusLambda_V, _sample.NdotL2, a2); - rem = reflectance * G2_over_G1; + quo = reflectance * G2_over_G1; } - return quotient_and_pdf::create(SpectralBins(rem), pdf); + return quotient_and_pdf::create(SpectralBins(quo), pdf); } template && Sample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) @@ -535,15 +526,231 @@ struct SBeckmannBxDF const Scalar c2 = smith::beckmann_C2(params.TdotV2, params.BdotV2, params.NdotV2, A.x, A.y); Scalar lambda = smith::beckmann_Lambda(c2); Scalar pdf = smith::VNDF_pdf_wo_clamps(ndf, lambda, interaction.NdotV, onePlusLambda_V); - vector_t3 rem = (vector_t3)0.0; + vector_t3 quo = (vector_t3)0.0; if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { const vector_t3 reflectance = fresnel_conductor(ior[0], ior[1], cache.VdotH); Scalar G2_over_G1 = smith::beckmann_smith_G2_over_G1(onePlusLambda_V, params.TdotL2, params.BdotL2, params.NdotL2, A.x, A.y); - rem = reflectance * G2_over_G1; + quo = reflectance * G2_over_G1; + } + + return quotient_and_pdf::create(SpectralBins(quo), pdf); + } + + vector_t2 A; + matrix ior; +}; + +template) +struct SGGXBxDF +{ + using this_t = SBeckmannBxDF; + using vector_t2 = vector; + using vector_t3 = vector; + using params_t = SBxDFParams; + + // iso + static this_t create(Scalar A,matrix ior) + { + this_t retval; + retval.A = vector_t2(A,A); + retval.ior = ior; + return retval; + } + + // aniso + static this_t create(Scalar ax,Scalar ay,matrix ior) + { + this_t retval; + retval.A = vector_t2(ax,ay); + retval.ior = ior; + return retval; + } + + template // this or specialize? + Scalar __eval_DG_wo_clamps(params_t params) + { + if (aniso) + { + const Scalar ax2 = A.x*A.x; + const Scalar ay2 = A.y*A.y; + Scalar NG = ndf::ggx_aniso(params.TdotH2, params.BdotH2, params.NdotH2, A.x, A.y, ax2, ay2); + if (any(A > numeric_limits::min)) + NG *= smith::ggx_correlated_wo_numerator(params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2, ax2, ay2); + return NG; + } + else + { + Scalar a2 = A.x*A.x; + Scalar NG = ndf::ggx_trowbridge_reitz(a2, params.NdotH2); + if (a2 > numeric_limits::min) + NG *= smith::ggx_correlated_wo_numerator(max(params.NdotV,0.0), params.NdotV2, max(params.NdotL,0.0), params.NdotL2, a2); + return NG; + } + } + + template + vector_t3 __eval_wo_clamps(params_t params) + { + Scalar scalar_part = __eval_DG_wo_clamps(params); + return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_to_light_measure_transform(scalar_part, params.NdotL); + } + + template && surface_interactions::Isotropic && IsotropicMicrofacetCache) // maybe put template in struct vs function? + vector_t3 eval(LightSample _sample, Iso interaction, Cache cache) + { + if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) + { + params_t params = params_t::template create(_sample, interaction, cache); + return __eval_wo_clamps(params); + } + else + return (vector_t3)0.0; + } + + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) // maybe put template in struct vs function? + vector_t3 eval(LightSample _sample, Aniso interaction, Cache cache) + { + if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) + { + params_t params = params_t::template create(_sample, interaction, cache); + return __eval_wo_clamps(params); + } + else + return (vector_t3)0.0; + } + + vector_t3 __generate(vector_t3 localV, vector_t2 u) + { + vector_t3 V = normalize(vector_t3(A.x*localV.x, A.y*localV.y, localV.z));//stretch view vector so that we're sampling as if roughness=1.0 + + Scalar lensq = V.x*V.x + V.y*V.y; + vector_t3 T1 = lensq > 0.0 ? vector_t3(-V.y, V.x, 0.0) * rsqrt(lensq) : vector_t3(1.0,0.0,0.0); + vector_t3 T2 = cross(V,T1); + + Scalar r = sqrt(u.x); + Scalar phi = 2.0 * nbl_glsl_PI * u.y; + Scalar t1 = r * cos(phi); + Scalar t2 = r * sin(phi); + Scalar s = 0.5 * (1.0 + V.z); + t2 = (1.0 - s)*sqrt(1.0 - t1*t1) + s*t2; + + //reprojection onto hemisphere + //TODO try it wothout the max(), not sure if -t1*t1-t2*t2>-1.0 + vector_t3 H = t1*T1 + t2*T2 + sqrt(max(0.0, 1.0-t1*t1-t2*t2))*V; + //unstretch + return normalize(vector_t3(A.x*H.x, A.y*H.y, H.z)); + } + + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + LightSample generate(Aniso interaction, vector u, out Cache cache) + { + const vector_t3 localV = interaction.getTangentSpaceV(); + const vector_t3 H = __generate(localV, u); + + cache = Aniso::create(localV, H); + vector_t3 localL = math::reflect(localV, H, cache.VdotH); + + return LightSample::createTangentSpace(localV, localL, interaction.getTangentFrame()); + } + + template && surface_interactions::Isotropic && IsotropicMicrofacetCache) + Scalar pdf(LightSample _sample, Iso interaction, Cache cache) + { + const Scalar a2 = A.x*A.x; + Scalar ndf = ndf::ggx_trowbridge_reitz(a2, cache.NdotH2); + + const Scalar devsh_v = smith::ggx_devsh_part(interaction.NdotV2, a2, 1.0-a2); + const Scalar G1_over_2NdotV = smith::ggx_G1_wo_numerator(interaction.NdotV, devsh_v); + return smith::VNDF_pdf_wo_clamps(ndf, G1_over_2NdotV); + } + + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + Scalar pdf(LightSample _sample, Aniso interaction, Cache cache) + { + const Scalar ax2 = A.x*A.x; + const Scalar ay2 = A.y*A.y; + Scalar ndf = ndf::ggx_aniso(cache.TdotH * cache.TdotH, cache.BdotH * cache.BdotH, cache.NdotH2, A.x, A.y, ax2, ay2); + + const Scalar devsh_v = smith::ggx_devsh_part(interaction.TdotV * interaction.TdotV, interaction.BdotV * interaction.BdotV, interaction.NdotV2, ax2, ay2); + const Scalar G1_over_2NdotV = smith::ggx_G1_wo_numerator(interaction.NdotV, devsh_v); + return smith::VNDF_pdf_wo_clamps(ndf, G1_over_2NdotV); + } + + template && Sample && surface_interactions::Isotropic && IsotropicMicrofacetCache) + quotient_and_pdf quotient_and_pdf_wo_clamps(LightSample _sample, Iso interaction, Cache cache, vector_t3 reflectance) + { + const Scalar a2 = A.x*A.x; + const Scalar one_minus_a2 = 1.0 - a2; + + const Scalar ndf = ndf::ggx_trowbridge_reitz(a2, cache.NdotH2); + const Scalar devsh_v = smith::ggx_devsh_part(interaction.NdotV2, a2, one_minus_a2); + Scalar pdf = pdf(_sample, interaction, cache); + + Scalar G2_over_G1 = smith::ggx_G2_over_G1_devsh(_sample.NdotL, _sample.NdotL2, interaction.NdotV, devsh_v, a2, one_minus_a2); + vector_t3 quo = reflectance * G2_over_G1; + + return quotient_and_pdf::create(SpectralBins(quo), pdf); + } + + template && Sample && surface_interactions::Isotropic && IsotropicMicrofacetCache) + quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction, Cache cache) + { + const Scalar a2 = A.x*A.x; + const Scalar one_minus_a2 = 1.0 - a2; + + const Scalar ndf = ndf::ggx_trowbridge_reitz(a2, cache.NdotH2); + const Scalar devsh_v = smith::ggx_devsh_part(interaction.NdotV2, a2, one_minus_a2); + Scalar pdf = pdf(_sample, interaction, cache); + + vector_t3 quo = (vector_t3)0.0; + if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) + { + const vector_t3 reflectance = fresnelConductor(ior[0], ior[1], cache.VdotH); + Scalar G2_over_G1 = smith::ggx_G2_over_G1_devsh(_sample.NdotL, _sample.NdotL2, interaction.NdotV, devsh_v, a2, one_minus_a2); + quo = reflectance * G2_over_G1; + } + + return quotient_and_pdf::create(SpectralBins(quo), pdf); + } + + template && Sample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + quotient_and_pdf quotient_and_pdf_wo_clamps(LightSample _sample, Aniso interaction, Cache cache, vector_t3 reflectance) + { + params_t params = params_t::template create(_sample, interaction, cache); + const Scalar ax2 = A.x*A.x; + const Scalar ay2 = A.y*A.y; + + const Scalar ndf = ndf::ggx_aniso(params.TdotH2, params.BdotH2, params.NdotH2, A.x, A.y, ax2, ay2); + const Scalar devsh_v = smith::ggx_devsh_part(interaction.NdotV2, a2, one_minus_a2); + Scalar pdf = pdf(_sample, interaction, cache); + + Scalar G2_over_G1 = smith::ggx_G2_over_G1_devsh(params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2, params.NdotV, devsh_v, ax2, ay2); + vector_t3 quo = reflectance * G2_over_G1; + + return quotient_and_pdf::create(SpectralBins(quo), pdf); + } + + template && Sample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + quotient_and_pdf quotient_and_pdf(LightSample _sample, Aniso interaction, Cache cache) + { + params_t params = params_t::template create(_sample, interaction, cache); + const Scalar ax2 = A.x*A.x; + const Scalar ay2 = A.y*A.y; + + const Scalar ndf = ndf::ggx_aniso(params.TdotH2, params.BdotH2, params.NdotH2, A.x, A.y, ax2, ay2); + const Scalar devsh_v = smith::ggx_devsh_part(interaction.NdotV2, a2, one_minus_a2); + Scalar pdf = pdf(_sample, interaction, cache); + + vector_t3 quo = (vector_t3)0.0; + if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) + { + const vector_t3 reflectance = fresnel_conductor(ior[0], ior[1], cache.VdotH); + Scalar G2_over_G1 = smith::ggx_G2_over_G1_devsh(params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2, params.NdotV, devsh_v, ax2, ay2); + quo = reflectance * G2_over_G1; } - return quotient_and_pdf::create(SpectralBins(rem), pdf); + return quotient_and_pdf::create(SpectralBins(quo), pdf); } vector_t2 A; From 3ad9f443e41105a1a622dc6e894cdb352205dd43 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 5 Dec 2024 18:15:05 +0700 Subject: [PATCH 016/188] some bsdfs --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 32 +++ include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 8 +- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 228 +++++++++++++++++- 3 files changed, 261 insertions(+), 7 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 6a47db0252..7cd25b4a62 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -915,6 +915,12 @@ vector fresnelConductor(vector eta, vector etak, T cosTheta) return impl::fresnel::conductor(eta, etak, cosTheta); } +template && (is_scalar_v || is_vector_v)) +T fresnelDielectric_common(T eta, U cosTheta) +{ + return impl::fresnel::template dielectric(eta, cosTheta); +} + template && (is_scalar_v || is_vector_v)) T fresnelDielectricFrontFaceOnly(T eta, U cosTheta) { @@ -929,6 +935,32 @@ T fresnelDielectric(T eta, U cosTheta) return impl::fresnel::template dielectric(orientedEta * orientedEta, abs(cosTheta)); } +namespace impl +{ +// gets the sum of all R, T R T, T R^3 T, T R^5 T, ... paths +template) +struct ThinDielectricInfiniteScatter +{ + static vector __call(vector singleInterfaceReflectance) + { + const vector doubleInterfaceReflectance = singleInterfaceReflectance * singleInterfaceReflectance; + return lerp((singleInterfaceReflectance - doubleInterfaceReflectance) / ((vector)(1.0) - doubleInterfaceReflectance) * 2.0, (vector)(1.0), doubleInterfaceReflectance > (vector)(0.9999)); + } + + static T __call(T singleInterfaceReflectance) + { + const T doubleInterfaceReflectance = singleInterfaceReflectance * singleInterfaceReflectance; + return doubleInterfaceReflectance > 0.9999 ? 1.0 : ((singleInterfaceReflectance - doubleInterfaceReflectance) / (1.0 - doubleInterfaceReflectance) * 2.0); + } +}; +} + +template || is_vector_v) +T thindielectricInfiniteScatter(T singleInterfaceReflectance) +{ + return impl::ThinDielectricInfiniteScatter >::__call(singleInterfaceReflectance); +} + template) vector diffuseFresnelCorrectionFactor(vector n, vector n2) { diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index bb75765fb9..daabc31769 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -88,13 +88,13 @@ struct SLambertianBxDF template && surface_interactions::Isotropic) Scalar pdf_wo_clamps(LightSample _sample, Iso interaction) { - return projected_hemisphere_pdf(_sample.NdotL); + return projected_hemisphere_pdf(_sample.NdotL); } template && surface_interactions::Isotropic) Scalar pdf(LightSample _sample, Iso interaction) { - return projected_hemisphere_pdf(max(_sample.NdotL, 0.0)); + return projected_hemisphere_pdf(max(_sample.NdotL, 0.0)); } template && Sample && surface_interactions::Anisotropic) @@ -166,13 +166,13 @@ struct SOrenNayarBxDF template && surface_interactions::Isotropic) Scalar pdf_wo_clamps(LightSample _sample, Iso interaction) { - return projected_hemisphere_pdf(_sample.NdotL, 0.0); + return projected_hemisphere_pdf(_sample.NdotL, 0.0); } template && surface_interactions::Isotropic) Scalar pdf(LightSample _sample, Iso interaction) { - return projected_hemisphere_pdf(max(_sample.NdotL, 0.0)); + return projected_hemisphere_pdf(max(_sample.NdotL, 0.0)); } // pdf type same as scalar? diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index 41cca108e3..0b11a9bb92 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -1,10 +1,11 @@ -// Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. +// Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h #ifndef _NBL_BUILTIN_HLSL_BXDF_TRANSMISSION_INCLUDED_ #define _NBL_BUILTIN_HLSL_BXDF_TRANSMISSION_INCLUDED_ -#include +#include "nbl/builtin/hlsl/bxdf/common.hlsl" +#include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" namespace nbl { @@ -37,9 +38,230 @@ LightSample cos_generate(NBL_CONST_REF_ARG(Aniso) interaction) template && is_floating_point_v) quotient_and_pdf cos_quotient_and_pdf() { - return quotient_and_pdf::create(SpectralBins(1.f),nbl::hlsl::numeric_limits::inf()); + return quotient_and_pdf::create(SpectralBins(1.f),nbl::hlsl::numeric_limits::inf()); } +// basic bxdf +template) +struct SLambertianBxDF +{ + static SLambertianBxDF create() + { + SLambertianBxDF retval; + // nothing here, just keeping in convention with others + return retval; + } + + Scalar __eval_pi_factored_out(Scalar absNdotL) + { + return absNdotL; + } + + template && surface_interactions::Isotropic) // maybe put template in struct vs function? + Scalar __eval_wo_clamps(LightSample _sample, Iso interaction) + { + // probably doesn't need to use the param struct + return __eval_pi_factored_out(_sample.NdotL) * numbers::inv_pi * 0.5; + } + + template && surface_interactions::Isotropic) // maybe put template in struct vs function? + Scalar eval(LightSample _sample, Iso interaction) + { + // probably doesn't need to use the param struct + return __eval_pi_factored_out(abs(_sample.NdotL)) * numbers::inv_pi * 0.5; + } + + template && surface_interactions::Anisotropic) + LightSample generate_wo_clamps(Aniso interaction, vector u) + { + vector L = projected_sphere_generate(u); + return LightSample::createTangentSpace(interaction.getTangentSpaceV(), L, interaction.getTangentFrame()); + } + + template && surface_interactions::Anisotropic) + LightSample generate(Aniso interaction, vector u) + { + return generate_wo_clamps(interaction, u); + } + + template && surface_interactions::Isotropic) + Scalar pdf_wo_clamps(LightSample _sample, Iso interaction) + { + return projected_sphere_pdf(_sample.NdotL, 0.0); + } + + template && surface_interactions::Isotropic) + Scalar pdf(LightSample _sample, Iso interaction) + { + return projected_sphere_pdf(abs(_sample.NdotL)); + } + + template && Sample && surface_interactions::Anisotropic) + quotient_and_pdf quotient_and_pdf_wo_clamps(LightSample _sample, Iso interaction) + { + Scalar pdf; + Scalar q = projected_sphere_quotient_and_pdf(pdf, _sample.NdotL); + return quotient_and_pdf::create(SpectralBins(q), pdf); + } + + template && Sample && surface_interactions::Anisotropic) + quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction) + { + Scalar pdf; + Scalar q = projected_sphere_quotient_and_pdf(pdf, abs(_sample.NdotL)); + return quotient_and_pdf::create(SpectralBins(q), pdf); + } +}; + +// no oren nayar + +// microfacet bxdfs + +// the dielectric ones don't fit the concept at all :( +template) +struct SSmoothDielectricBxDF +{ + using vector_t3 = vector; + + static SSmoothDielectricBxDF create(vector_t3 eta) + { + SSmoothDielectricBxDF retval; + retval.eta = eta; + return retval; + } + + // where eval? + + template) + LightSample __generate_wo_clamps(vector_t3 V, vector_t3 T, vector_t3 B, vector_t3 N, bool backside, Scalar NdotV, Scalar absNdotV, Scalar NdotV2, inout vector_t3 u, Scalar rcpOrientedEta, Scalar orientedEta2, Scalar rcpOrientedEta2, out bool transmitted) + { + const vector_t3 reflectance = fresnelDielectric_common(orientedEta2, absNdotV); + + Scalar rcpChoiceProb; + transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); + + const vector_t3 L = math::reflectRefract(transmitted, V, N, backside, NdotV, NdotV2, rcpOrientedEta, rcpOrientedEta2); + return LightSample::create(L, dot(V, L), T, B, N); + } + + template && surface_interactions::Anisotropic) + LightSample generate_wo_clamps(Aniso interaction, inout vector u) // TODO: check vec3? + { + Scalar orientedEta, rcpOrientedEta; + const bool backside = math::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.NdotV, eta); + bool dummy; + return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, backside, interaction.NdotV, + interaction.NdotV, interaction.NdotV*interaction.NdotV, u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, dummy); + } + + template && surface_interactions::Anisotropic) + LightSample generate(Aniso interaction, inout vector u) + { + Scalar orientedEta, rcpOrientedEta; + const bool backside = math::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.NdotV, eta); + bool dummy; + return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, backside, interaction.NdotV, + abs(interaction.NdotV), interaction.NdotV*interaction.NdotV, u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, dummy); + } + + // where pdf? + + template && Sample && surface_interactions::Anisotropic) + quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction) + { + const bool transmitted = isTransmissionPath(interaction.NdotV, _sample.NdotL); + + float dummy, rcpOrientedEta; + const bool backside = math::getOrientedEtas(dummy, rcpOrientedEta, interaction.NdotV, eta); + + const Scalar pdf = 1.0 / 0.0; + Scalar quo = transmitted ? rcpOrientedEta2 : 1.0; + return quotient_and_pdf::create(SpectralBins(quo), pdf); + } + + vector_t3 eta; +}; + +template) +struct SSmoothDielectricBxDF +{ + using vector_t3 = vector; + + static SSmoothDielectricBxDF create(vector_t3 eta2, vector_t3 luminosityContributionHint) + { + SSmoothDielectricBxDF retval; + retval.eta2 = eta2; + retval.luminosityContributionHint = luminosityContributionHint; + return retval; + } + + // where eval? + + // usually `luminosityContributionHint` would be the Rec.709 luma coefficients (the Y row of the RGB to CIE XYZ matrix) + // its basically a set of weights that determine + // assert(1.0==luminosityContributionHint.r+luminosityContributionHint.g+luminosityContributionHint.b); + // `remainderMetadata` is a variable in which the generator function returns byproducts of sample generation that would otherwise have to be redundantly calculated in `remainder_and_pdf` + template) + LightSample __generate_wo_clamps(vector_t3 V, vector_t3 T, vector_t3 B, vector_t3 N, Scalar NdotV, Scalar absNdotV, inout vector_t3 u, vector_t3 eta2, vector_t3 luminosityContributionHint, out vector_t3 remainderMetadata) + { + // we will only ever intersect from the outside + const vector_t3 reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2,absNdotV)); + + // we are only allowed one choice for the entire ray, so make the probability a weighted sum + const Scalar reflectionProb = dot(reflectance, luminosityContributionHint); + + Scalar rcpChoiceProb; + const bool transmitted = math::partitionRandVariable(reflectionProb, u.z, rcpChoiceProb); + remainderMetadata = (transmitted ? ((vector_t3)(1.0) - reflectance) : reflectance) * rcpChoiceProb; + + const vector_t3 L = (transmitted ? (vector_t3)(0.0) : N * 2.0 * NdotV) - V; + return LightSample::create(L, dot(V, L), T, B, N); + } + + template && surface_interactions::Anisotropic) + LightSample generate_wo_clamps(Aniso interaction, inout vector u) // TODO: check vec3? + { + return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, interaction.NdotV, interaction.NdotV, u, eta2, luminosityContributionHint); + } + + template && surface_interactions::Anisotropic) + LightSample generate(Aniso interaction, inout vector u) + { + return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, interaction.NdotV, abs(interaction.NdotV), u, eta2, luminosityContributionHint); + } + + // where pdf? + + template && Sample && surface_interactions::Anisotropic) + quotient_and_pdf quotient_and_pdf_wo_clamps(LightSample _sample, Iso interaction) + { + const bool transmitted = isTransmissionPath(interaction.NdotV, _sample.NdotL); + const vec3 reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, interaction.NdotV)); + const vec3 sampleValue = transmitted ? ((vector_t3)(1.0) - reflectance) : reflectance; + + const Scalar sampleProb = dot(sampleValue,luminosityContributionHint); + + const Scalar pdf = 1.0 / 0.0; + return quotient_and_pdf::create(SpectralBins(sampleValue / sampleProb), pdf); + } + + template && Sample && surface_interactions::Anisotropic) + quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction) + { + const bool transmitted = isTransmissionPath(interaction.NdotV, _sample.NdotL); + const vec3 reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, abs(interaction.NdotV))); + const vec3 sampleValue = transmitted ? ((vector_t3)(1.0) - reflectance) : reflectance; + + const Scalar sampleProb = dot(sampleValue,luminosityContributionHint); + + const Scalar pdf = 1.0 / 0.0; + return quotient_and_pdf::create(SpectralBins(sampleValue / sampleProb), pdf); + } + + vector_t3 eta2; + vector_t3 luminosityContributionHint; +}; + } } } From bc13d1f1a13a8e6447850736d03231c808e821de Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 6 Dec 2024 15:13:38 +0700 Subject: [PATCH 017/188] beckmann bsdf, bug fixes --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 20 +- include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 2 +- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 4 +- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 229 +++++++++++++++++- include/nbl/builtin/hlsl/math/functions.hlsl | 24 +- 5 files changed, 255 insertions(+), 24 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 7cd25b4a62..0b45ec2e23 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -18,18 +18,20 @@ namespace bxdf { // returns unnormalized vector -// TODO: template these? -float computeUnnormalizedMicrofacetNormal(bool _refract, float3 V, float3 L, float orientedEta) +template) +T computeUnnormalizedMicrofacetNormal(bool _refract, vector V, vector L, T orientedEta) { - const float etaFactor = (_refract ? orientedEta : 1.0); - const float3 tmpH = V + L * etaFactor; + const T etaFactor = (_refract ? orientedEta : 1.0); + const vector tmpH = V + L * etaFactor; return _refract ? (-tmpH) : tmpH; } -// returns normalized vector, but NaN when -float3 computeMicrofacetNormal(bool _refract, float3 V, float3 L, float orientedEta) + +// returns normalized vector, but NaN when result is length 0 +template) +T computeMicrofacetNormal(bool _refract, vector V, vector L, T orientedEta) { - const float3 H = computeUnnormalizedMicrofacetNormal(_refract,V,L,orientedEta); - const float unnormRcpLen = rsqrt(dot(H,H)); + const vector H = computeUnnormalizedMicrofacetNormal(_refract,V,L,orientedEta); + const T unnormRcpLen = rsqrt(dot(H,H)); return H * unnormRcpLen; } @@ -450,7 +452,7 @@ struct SIsotropicMicrofacetCache ) { // TODO: can we optimize? - H = computeMicrofacetNormal(transmitted,V,L,orientedEta); + H = computeMicrofacetNormal(transmitted,V,L,orientedEta); retval.NdotH = dot(N, H); // not coming from the medium (reflected) OR diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl index 0c4ea17718..5d36f8b203 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -78,7 +78,7 @@ T microfacet_to_light_measure_transform(T NDFcos, T maxNdotV) // blinn-phong template) -T blinn_phong(T NdotH, T n) +T blinn_phong(T NdotH, T n) // n is shininess exponent { return isinf(n) ? numeric_limits::infinity : numbers::inv_pi * 0.5 * (n + 2.0) * pow(NdotH,n); } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index daabc31769..70a626d0ed 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -544,7 +544,7 @@ struct SBeckmannBxDF template) struct SGGXBxDF { - using this_t = SBeckmannBxDF; + using this_t = SGGXBxDF; using vector_t2 = vector; using vector_t3 = vector; using params_t = SBxDFParams; @@ -593,7 +593,7 @@ struct SGGXBxDF vector_t3 __eval_wo_clamps(params_t params) { Scalar scalar_part = __eval_DG_wo_clamps(params); - return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_to_light_measure_transform(scalar_part, params.NdotL); + return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_to_light_measure_transform(scalar_part, params.NdotL); } template && surface_interactions::Isotropic && IsotropicMicrofacetCache) // maybe put template in struct vs function? diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index 0b11a9bb92..9abdf9abc5 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -1,11 +1,12 @@ // Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". -// For conditions of distribution and use, see copyright notice in nabla.h +// For conditions of distribution and use, see copyright notice nabla.h #ifndef _NBL_BUILTIN_HLSL_BXDF_TRANSMISSION_INCLUDED_ #define _NBL_BUILTIN_HLSL_BXDF_TRANSMISSION_INCLUDED_ #include "nbl/builtin/hlsl/bxdf/common.hlsl" #include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" +#include "nbl/builtin/hlsl/bxdf/reflection.hlsl" namespace nbl { @@ -48,7 +49,7 @@ struct SLambertianBxDF static SLambertianBxDF create() { SLambertianBxDF retval; - // nothing here, just keeping in convention with others + // nothing here, just keeping convention with others return retval; } @@ -57,14 +58,14 @@ struct SLambertianBxDF return absNdotL; } - template && surface_interactions::Isotropic) // maybe put template in struct vs function? + template && surface_interactions::Isotropic) // maybe put template struct vs function? Scalar __eval_wo_clamps(LightSample _sample, Iso interaction) { // probably doesn't need to use the param struct return __eval_pi_factored_out(_sample.NdotL) * numbers::inv_pi * 0.5; } - template && surface_interactions::Isotropic) // maybe put template in struct vs function? + template && surface_interactions::Isotropic) // maybe put template struct vs function? Scalar eval(LightSample _sample, Iso interaction) { // probably doesn't need to use the param struct @@ -166,12 +167,12 @@ struct SSmoothDielectricBxDF // where pdf? - template && Sample && surface_interactions::Anisotropic) + template && Sample && surface_interactions::Isotropic) quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction) { const bool transmitted = isTransmissionPath(interaction.NdotV, _sample.NdotL); - float dummy, rcpOrientedEta; + Scalar dummy, rcpOrientedEta; const bool backside = math::getOrientedEtas(dummy, rcpOrientedEta, interaction.NdotV, eta); const Scalar pdf = 1.0 / 0.0; @@ -182,7 +183,7 @@ struct SSmoothDielectricBxDF vector_t3 eta; }; -template) +template) struct SSmoothDielectricBxDF { using vector_t3 = vector; @@ -200,7 +201,7 @@ struct SSmoothDielectricBxDF // usually `luminosityContributionHint` would be the Rec.709 luma coefficients (the Y row of the RGB to CIE XYZ matrix) // its basically a set of weights that determine // assert(1.0==luminosityContributionHint.r+luminosityContributionHint.g+luminosityContributionHint.b); - // `remainderMetadata` is a variable in which the generator function returns byproducts of sample generation that would otherwise have to be redundantly calculated in `remainder_and_pdf` + // `remainderMetadata` is a variable which the generator function returns byproducts of sample generation that would otherwise have to be redundantly calculated `remainder_and_pdf` template) LightSample __generate_wo_clamps(vector_t3 V, vector_t3 T, vector_t3 B, vector_t3 N, Scalar NdotV, Scalar absNdotV, inout vector_t3 u, vector_t3 eta2, vector_t3 luminosityContributionHint, out vector_t3 remainderMetadata) { @@ -232,7 +233,7 @@ struct SSmoothDielectricBxDF // where pdf? - template && Sample && surface_interactions::Anisotropic) + template && Sample && surface_interactions::Isotropic) quotient_and_pdf quotient_and_pdf_wo_clamps(LightSample _sample, Iso interaction) { const bool transmitted = isTransmissionPath(interaction.NdotV, _sample.NdotL); @@ -245,7 +246,7 @@ struct SSmoothDielectricBxDF return quotient_and_pdf::create(SpectralBins(sampleValue / sampleProb), pdf); } - template && Sample && surface_interactions::Anisotropic) + template && Sample && surface_interactions::Isotropic) quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction) { const bool transmitted = isTransmissionPath(interaction.NdotV, _sample.NdotL); @@ -262,6 +263,214 @@ struct SSmoothDielectricBxDF vector_t3 luminosityContributionHint; }; +template) +struct SBeckmannDielectricBxDF +{ + using vector_t3 = vector; + using vector_t2 = vector; + using matrix_t3x3 = matrix; + using params_t = SBxDFParams; + + static SBeckmannDielectricBxDF create(vector_t3 eta, Scalar A) + { + SBeckmannDielectricBxDF retval; + retval.eta = eta; + retval.A = vector_t2(A, A); + return retval; + } + + static SBeckmannDielectricBxDF create(vector_t3 eta, Scalar ax, Scalar ay) + { + SBeckmannDielectricBxDF retval; + retval.eta = eta; + retval.A = vector_t2(ax, ay); + return retval; + } + + template && surface_interactions::Isotropic && IsotropicMicrofacetCache) + vector_t3 eval(LightSample _sample, Iso interaction, Cache cache) + { + float orientedEta, dummy; + const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); + const float orientedEta2 = orientedEta * orientedEta; + + const float VdotHLdotH = cache.VdotH * cache.LdotH; + const bool transmitted = VdotHLdotH < 0.0; + + matrix dummyior; + params_t params = params_t::template create(_sample, interaction, cache); + reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, dummyior); + const float scalar_part = beckmann::template __eval_DG_wo_clamps(params); + + return fresnelDielectric_common(orientedEta2, abs(cache.VdotH)) * microfacet_to_light_measure_transform(scalar_part,abs(interaction.NdotV),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); + } + + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + vector_t3 eval(LightSample _sample, Aniso interaction, Cache cache) + { + float orientedEta, dummy; + const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); + const float orientedEta2 = orientedEta * orientedEta; + + const float VdotHLdotH = cache.VdotH * cache.LdotH; + const bool transmitted = VdotHLdotH < 0.0; + + matrix dummyior; + params_t params = params_t::template create(_sample, interaction, cache); + reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior); + const float scalar_part = beckmann::template __eval_DG_wo_clamps(params); + + return fresnelDielectric_common(orientedEta2, abs(cache.VdotH)) * microfacet_to_light_measure_transform(scalar_part,abs(interaction.NdotV),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); + } + + template && AnisotropicMicrofacetCache) + LightSample __generate_wo_clamps(vector_t3 localV, bool backside, vector_t3 H, matrix_t3x3 m, inout vector_t3 u, Scalar rcpOrientedEta, Scalar orientedEta2, Scalar rcpOrientedEta2, out Cache cache) + { + const Scalar VdotH = dot(localV,H); + const Scalar reflectance = fresnelDielectric_common(orientedEta2,abs(VdotH)); + + Scalar rcpChoiceProb; + bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); + + vec3 localL; + cache = Aniso::create(localV, H); + + const Scalar VdotH = cache.VdotH; + cache.LdotH = transmitted ? nbl_glsl_refract_compute_NdotT(VdotH<0.0,VdotH*VdotH,rcpOrientedEta2):VdotH; + tangentSpaceL = math::reflectRefract_impl(transmitted, tangentSpaceV, tangentSpaceH, VdotH, cache.LdotH, rcpOrientedEta); + + return LightSample::createTangentSpace(localV, localL, m); + } + + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + LightSample generate(Aniso interaction, inout vector u, out Cache cache) + { + const vector_t3 localV = interaction.getTangentSpaceV(); + + Scalar orientedEta, rcpOrientedEta; + const bool backside = math::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.NdotV, eta); + + const vector_t3 upperHemisphereV = backside ? -localV : localV; + + matrix dummyior; + reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior); + const vector_t3 H = beckmann.__generate(upperHemisphereV, u.xy); + + return __generate_wo_clamps(localV, backside, H, interaction.getTangentFrame(), rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, cache); + } + + template && surface_interactions::Anisotropic) + LightSample generate(Aniso interaction, inout vector u) + { + SAnisotropicMicrofacetCache dummycache; + return generate >(interaction, u, dummycache); + } + + Scalar pdf_wo_clamps(bool transmitted, Scalar reflectance, Scalar ndf, Scalar absNdotV, Scalar NdotV2, Scalar VdotH, Scalar LdotH, Scalar VdotHLdotH, Scalar orientedEta, out Scalar onePlusLambda_V) + { + const Scalar lambda = smith::beckmann_Lambda(NdotV2, A.x*A.x); + return smith::VNDF_pdf_wo_clamps(ndf,lambda,absNdotV,transmitted,VdotH,LdotH,VdotHLdotH,orientedEta,reflectance,onePlusLambda_V); + } + + Scalar pdf_wo_clamps(bool transmitted, Scalar reflectance, Scalar ndf, Scalar absNdotV, Scalar TdotV2, Scalar BdotV2, Scalar NdotV2, Scalar VdotH, Scalar LdotH, Scalar VdotHLdotH, Scalar ax2, Scalar ay2, Scalar orientedEta, out Scalar onePlusLambda_V) + { + Scalar c2 = smith::beckmann_C2(TdotV2, BdotV2, NdotV2, ax2, ay2); + Scalar lambda = smith::beckmann_Lambda(c2); + return smith::VNDF_pdf_wo_clamps(ndf,lambda,absNdotV,transmitted,VdotH,LdotH,VdotHLdotH,orientedEta,reflectance,onePlusLambda_V); + } + + template && surface_interactions::Isotropic && IsotropicMicrofacetCache) + Scalar pdf(LightSample _sample, Iso interaction, Cache cache) + { + Scalar ndf = ndf::beckmann(A.x*A.x, cache.NdotH2); + + Scalar orientedEta, dummy; + const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); + const Scalar orientedEta2 = orientedEta * orientedEta; + + const float VdotHLdotH = cache.VdotH * cache.LdotH; + const bool transmitted = VdotHLdotH < 0.0; + + const Scalar reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + + const Scalar absNdotV = abs(interaction.NdotV); + return pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, interaction.NdotV2, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta, dummy); + } + + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + Scalar pdf(LightSample _sample, Aniso interaction, Cache cache) + { + const Scalar ax2 = A.x*A.x; + const Scalar ay2 = A.y*A.y; + params_t params = params_t::template create(_sample, interaction, cache); + + Scalar ndf = ndf::beckmann(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + + Scalar orientedEta, dummy; + const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); + const Scalar orientedEta2 = orientedEta * orientedEta; + + const float VdotHLdotH = cache.VdotH * cache.LdotH; + const bool transmitted = VdotHLdotH < 0.0; + + const Scalar reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + + const Scalar absNdotV = abs(interaction.NdotV); + return pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.VdotH, cache.LdotH, VdotHLdotH, ax2, ay2, orientedEta, dummy); + } + + template && Sample && surface_interactions::Isotropic && IsotropicMicrofacetCache) + quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction, Cache cache) + { + Scalar ndf = ndf::beckmann(A.x*A.x, cache.NdotH2); + + Scalar orientedEta, dummy; + const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); + const Scalar orientedEta2 = orientedEta * orientedEta; + + const float VdotHLdotH = cache.VdotH * cache.LdotH; + const bool transmitted = VdotHLdotH < 0.0; + + const Scalar reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + const Scalar absNdotV = abs(interaction.NdotV); + + float onePlusLambda_V; + pdf = pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, interaction.NdotV2, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta, dummy); + Scalar quo = smith::beckmann_smith_G2_over_G1(onePlusLambda_V, NdotL2, a2); + + return quotient_and_pdf::create(SpectralBins(quo), pdf); + } + + template && Sample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + quotient_and_pdf quotient_and_pdf(LightSample _sample, Aniso interaction, Cache cache) + { + const Scalar ax2 = A.x*A.x; + const Scalar ay2 = A.y*A.y; + params_t params = params_t::template create(_sample, interaction, cache); + + Scalar ndf = ndf::beckmann(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + + Scalar orientedEta, dummy; + const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); + const Scalar orientedEta2 = orientedEta * orientedEta; + + const float VdotHLdotH = cache.VdotH * cache.LdotH; + const bool transmitted = VdotHLdotH < 0.0; + + const Scalar reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + const Scalar absNdotV = abs(interaction.NdotV); + + float onePlusLambda_V; + pdf = pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.VdotH, cache.LdotH, VdotHLdotH, ax2, ay2, orientedEta, dummy); + Scalar quo = smith::beckmann_smith_G2_over_G1(onePlusLambda_V, TdotL2, BdotL2, NdotL2, ax2, ay2); + + return quotient_and_pdf::create(SpectralBins(quo), pdf); + } + + vector_t2 A; + vector_t3 eta; +}; + } } } diff --git a/include/nbl/builtin/hlsl/math/functions.hlsl b/include/nbl/builtin/hlsl/math/functions.hlsl index b1684f30de..1c1b7361ea 100644 --- a/include/nbl/builtin/hlsl/math/functions.hlsl +++ b/include/nbl/builtin/hlsl/math/functions.hlsl @@ -274,10 +274,15 @@ struct refract return N * (NdotI * rcpOrientedEta + computeNdotT()) - rcpOrientedEta * I; } + static float3 doReflectRefract(bool _refract, float3 _I, float3 _N, float _NdotI, float _NdotTorR, float _rcpOrientedEta) + { + return _N * (_NdotI * (_refract ? _rcpOrientedEta : 1.0) + _NdotTorR) - _I * (_refract ? _rcpOrientedEta : 1.0); + } + float3 doReflectRefract(bool r) { - const float NdotTorR = r ? computeNdotT(): NdotI; - return N * (NdotI * (r ? rcpOrientedEta : 1.0) + NdotTorR) - I * (r ? rcpOrientedEta : 1.0); + const float NdotTorR = r ? computeNdotT() : NdotI; + return doReflectRefract(r, I, N, NdotI, NdotTorR, rcpOrientedEta); } float3 I; @@ -308,6 +313,21 @@ float3 refract(float3 I, float3 N, float eta) return r.doRefract(); } +// I don't like exposing these next two +float3 reflectRefract_computeNdotT(bool backside, float NdotI2, float rcpOrientedEta2) +{ + impl::refract r; + r.NdotI2 = NdotI2; + r.rcpOrientedEta2 = rcpOrientedEta2; + r.backside = backside; + return r.computeNdotT(); +} + +float3 reflectRefract_impl(bool _refract, float3 _I, float3 _N, float _NdotI, float _NdotTorR, float _rcpOrientedEta) +{ + return impl::refract::doReflectRefract(_refract, _I, _N, _NdotI, _NdotTorR, _rcpOrientedEta); +} + float3 reflectRefract(bool _refract, float3 I, float3 N, bool backside, float NdotI, float NdotI2, float rcpOrientedEta, float rcpOrientedEta2) { impl::refract r = impl::refract::create(I, N, backside, NdotI, NdotI2, rcpOrientedEta, rcpOrientedEta2); From f56476ed545ba83c367a5ecd36fd747c889f4d1d Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 9 Dec 2024 15:41:41 +0700 Subject: [PATCH 018/188] typedefs in concepts --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 664 ++++++++++--------- include/nbl/builtin/hlsl/math/functions.hlsl | 65 +- 2 files changed, 374 insertions(+), 355 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 0b45ec2e23..e80e74808a 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -45,32 +45,36 @@ namespace ray_dir_info { #define NBL_CONCEPT_NAME Basic -#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename) -#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(U) -#define NBL_CONCEPT_PARAM_0 (rdirinfo,T) -#define NBL_CONCEPT_PARAM_1 (N,vector) -#define NBL_CONCEPT_PARAM_2 (dirDotN,U) -NBL_CONCEPT_BEGIN(4) +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (rdirinfo, T) +#define NBL_CONCEPT_PARAM_1 (N, typename vector3_type) +#define NBL_CONCEPT_PARAM_2 (dirDotN, typename T::scalar_type) +NBL_CONCEPT_BEGIN(7) #define rdirinfo NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define N NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define dirDotN NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.direction), ::nbl::hlsl::is_same_v, vector)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.getDirection()), ::nbl::hlsl::is_same_v, vector)) + ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.direction), ::nbl::hlsl::is_same_v, typename T::vector3_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.getDirection()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.transmit()), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.reflect(N, dirDotN)), ::nbl::hlsl::is_same_v, T)) -) && nbl::hlsl::is_scalar_v; + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.refract(N, dirDotN)), ::nbl::hlsl::is_same_v, T)) +) && is_scalar_v && is_vector_v; #undef dirDotN #undef N #undef rdirinfo #include -// no ray-differentials, nothing template struct SBasic { - using vector_t = vector; - vector_t getDirection() { return direction; } + using scalar_type = T; + using vector3_type = vector; + + vector3_type getDirection() { return direction; } SBasic transmit() { @@ -79,14 +83,21 @@ struct SBasic return retval; } - SBasic reflect(const float3 N, const float directionDotN) + SBasic reflect(NBL_CONST_REF_ARG(vector3_type) N, scalar_type directionDotN) { SBasic retval; retval.direction = math::reflect(direction,N,directionDotN); return retval; } - vector_t direction; + SBasic refract(NBL_CONST_REF_ARG(vector3_type) N, scalar_type eta) + { + SBasic retval; + retval.direction = math::refract(direction,N,eta); + return retval; + } + + vector3_type direction; }; // more to come! @@ -97,190 +108,203 @@ namespace surface_interactions { #define NBL_CONCEPT_NAME Isotropic -#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename)(typename) -#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(B)(U) // B is type Basic -#define NBL_CONCEPT_PARAM_0 (iso,T) -#define NBL_CONCEPT_PARAM_1 (normV,B) -#define NBL_CONCEPT_PARAM_2 (normN,vector) -NBL_CONCEPT_BEGIN(5) +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (iso, T) +#define NBL_CONCEPT_PARAM_1 (normV, typename T::ray_dir_info_type) +#define NBL_CONCEPT_PARAM_2 (normN, typename T::vector3_type) +NBL_CONCEPT_BEGIN(8) #define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define normV NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define normN NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.V), ::nbl::hlsl::is_same_v, B)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.N), ::nbl::hlsl::is_same_v, vector)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.NdotV), ::nbl::hlsl::is_same_v, U)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.NdotV2), ::nbl::hlsl::is_same_v, U)) + ((NBL_CONCEPT_REQ_TYPE)(T::ray_dir_info_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.V), ::nbl::hlsl::is_same_v, typename T::ray_dir_info_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.N), ::nbl::hlsl::is_same_v, typename T::vector3_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.NdotV), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.NdotV2), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(normV,normN)), ::nbl::hlsl::is_same_v, T)) -) && ray_dir_info::Basic; +) && ray_dir_info::Basic; #undef normN #undef normV #undef iso #include -template) +template) struct SIsotropic { - using vector_t = vector; + using ray_dir_info_type = RayDirInfo; + using scalar_type = typename RayDirInfo::scalar_type; + using vector3_type = typename RayDirInfo::vector3_type; + // WARNING: Changed since GLSL, now arguments need to be normalized! - static SIsotropic create(NBL_CONST_REF_ARG(RayDirInfo) normalizedV, NBL_CONST_REF_ARG(vector_t) normalizedN) + static SIsotropic create(NBL_CONST_REF_ARG(RayDirInfo) normalizedV, NBL_CONST_REF_ARG(vector3_type) normalizedN) { SIsotropic retval; retval.V = normalizedV; retval.N = normalizedN; - - retval.NdotV = dot(retval.N,retval.V.getDirection()); - retval.NdotV2 = retval.NdotV*retval.NdotV; + retval.NdotV = dot(retval.N, retval.V.getDirection()); + retval.NdotV2 = retval.NdotV * retval.NdotV; return retval; } RayDirInfo V; - vector_t N; - T NdotV; - T NdotV2; // old NdotV_squared + vector3_type N; + scalar_type NdotV; + scalar_type NdotV2; }; #define NBL_CONCEPT_NAME Anisotropic -#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename)(typename)(typename) -#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(I)(B)(U) // I is type Isotropic, B is type Basic -#define NBL_CONCEPT_PARAM_0 (aniso,T) -#define NBL_CONCEPT_PARAM_1 (iso,I) -#define NBL_CONCEPT_PARAM_2 (normT,vector) -#define NBL_CONCEPT_PARAM_3 (normB,U) -NBL_CONCEPT_BEGIN(9) +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (aniso, T) +#define NBL_CONCEPT_PARAM_1 (iso, typename T::isotropic_type) +#define NBL_CONCEPT_PARAM_2 (normT, typename T::vector3_type) +#define NBL_CONCEPT_PARAM_3 (normB, typename T::scalar_type) +NBL_CONCEPT_BEGIN(12) #define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define normT NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 #define normB NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.T), ::nbl::hlsl::is_same_v, vector)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.B), ::nbl::hlsl::is_same_v, vector)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.TdotV), ::nbl::hlsl::is_same_v, U)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.BdotV), ::nbl::hlsl::is_same_v, U)) + ((NBL_CONCEPT_REQ_TYPE)(T::ray_dir_info_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::matrix3x3_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.T), ::nbl::hlsl::is_same_v, typename T::vector3_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.B), ::nbl::hlsl::is_same_v, typename T::vector3_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.TdotV), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.BdotV), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(iso,normT,normB)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(iso,normT)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(iso)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getTangentSpaceV()), ::nbl::hlsl::is_same_v, vector)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getTangentFrame()), ::nbl::hlsl::is_same_v, matrix)) -) && Isotropic && ray_dir_info::Basic; + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getTangentSpaceV()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getTangentFrame()), ::nbl::hlsl::is_same_v, typename T::matrix3x3_type)) +) && Isotropic && ray_dir_info::Basic; #undef normB #undef normT #undef iso #undef aniso #include -template) -struct SAnisotropic : SIsotropic +template) +struct SAnisotropic : SIsotropic { - using vector_t = vector; - using matrix_t = matrix; + using ray_dir_info_type = RayDirInfo; + using scalar_type = typename RayDirInfo::scalar_type; + using vector3_type = typename RayDirInfo::vector3_type; + using matrix3x3_type = matrix; + using isotropic_type = SIsotropic; // WARNING: Changed since GLSL, now arguments need to be normalized! - static SAnisotropic create( - NBL_CONST_REF_ARG(SIsotropic) isotropic, - NBL_CONST_REF_ARG(vector_t) normalizedT, - const U normalizedB + static SAnisotropic create( + NBL_CONST_REF_ARG(isotropic_type) isotropic, + NBL_CONST_REF_ARG(vector3_type) normalizedT, + const scalar_type normalizedB ) { - SAnisotropic retval; - //(SIsotropic) retval = isotropic; + SAnisotropic retval; + //(SIsotropic) retval = isotropic; retval.T = normalizedT; retval.B = normalizedB; - const vector_t V = retval.getDirection(); + const vector3_type V = retval.getDirection(); retval.TdotV = dot(V, retval.T); retval.BdotV = dot(V, retval.B); return retval; } - static SAnisotropic create(NBL_CONST_REF_ARG(SIsotropic) isotropic, NBL_CONST_REF_ARG(vector_t) normalizedT) + static SAnisotropic create(NBL_CONST_REF_ARG(isotropic_type) isotropic, NBL_CONST_REF_ARG(vector3_type) normalizedT) { return create(isotropic, normalizedT, cross(isotropic.N, normalizedT)); } - static SAnisotropic create(NBL_CONST_REF_ARG(SIsotropic) isotropic) + static SAnisotropic create(NBL_CONST_REF_ARG(isotropic_type) isotropic) { - matrix TB = math::frisvad(isotropic.N); + matrix TB = math::frisvad(isotropic.N); return create(isotropic, TB[0], TB[1]); } - vector_t getTangentSpaceV() { return vector_t(TdotV, BdotV, SIsotropic::NdotV); } + vector3_type getTangentSpaceV() { return vector3_type(TdotV, BdotV, isotropic_type::NdotV); } // WARNING: its the transpose of the old GLSL function return value! - matrix_t getTangentFrame() { return matrix_t(T, B, SIsotropic::N); } + matrix3x3_type getTangentFrame() { return matrix3x3_type(T, B, isotropic_type::N); } - vector_t T; - vector_t B; - U TdotV; - U BdotV; + vector3_type T; + vector3_type B; + scalar_type TdotV; + scalar_type BdotV; }; } #define NBL_CONCEPT_NAME Sample -#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename)(typename)(typename)(typename) -#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(I)(A)(B)(U) // I type Isotropic, A type Aniso, B type Basic (getting clunky) -#define NBL_CONCEPT_PARAM_0 (sample_,T) -#define NBL_CONCEPT_PARAM_1 (iso,I) -#define NBL_CONCEPT_PARAM_2 (aniso,A) -#define NBL_CONCEPT_PARAM_3 (rdirinfo,B) -#define NBL_CONCEPT_PARAM_4 (pV,vector) -#define NBL_CONCEPT_PARAM_5 (frame,matrix) -#define NBL_CONCEPT_PARAM_6 (pT,vector) -#define NBL_CONCEPT_PARAM_7 (pB,vector) -#define NBL_CONCEPT_PARAM_8 (pN,vector) -#define NBL_CONCEPT_PARAM_9 (pVdotL,U) -NBL_CONCEPT_BEGIN(12) -#define sample_ NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (_sample, T) +#define NBL_CONCEPT_PARAM_1 (iso, typename T::isotropic_type) +#define NBL_CONCEPT_PARAM_2 (aniso, typename T::anisotropic_type) +#define NBL_CONCEPT_PARAM_3 (rdirinfo, typename T::ray_dir_info_type) +#define NBL_CONCEPT_PARAM_4 (pV, typename T::vector3_type) +#define NBL_CONCEPT_PARAM_5 (frame, typename T::matrix3x3_type) +#define NBL_CONCEPT_PARAM_6 (pVdotL, typename T::scalar_type) +NBL_CONCEPT_BEGIN(17) +#define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 #define rdirinfo NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 #define pV NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 #define frame NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 -#define pT NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 -#define pB NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_7 -#define pN NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_8 -#define pVdotL NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_9 +#define pVdotL NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((sample_.L), ::nbl::hlsl::is_same_v, B)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((sample_.VdotL), ::nbl::hlsl::is_same_v, U)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((sample_.TdotL), ::nbl::hlsl::is_same_v, U)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((sample_.BdotL), ::nbl::hlsl::is_same_v, U)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((sample_.NdotL), ::nbl::hlsl::is_same_v, U)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((sample_.NdotL2), ::nbl::hlsl::is_same_v, U)) + ((NBL_CONCEPT_REQ_TYPE)(T::ray_dir_info_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::matrix3x3_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.L), ::nbl::hlsl::is_same_v, typename T::ray_dir_info_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.VdotL), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.TdotL), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.BdotL), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.NdotL), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.NdotL2), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createTangentSpace(pV,rdirinfo,frame)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(rdirinfo,pVdotL,pN)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(rdirinfo,pVdotL,pT,pB,pN)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create(pV,iso)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create(pV,aniso)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((sample_.getTangentSpaceL()), ::nbl::hlsl::is_same_v, vector)) -) && surface_interactions::Anisotropic && surface_interactions::Isotropic && - ray_dir_info::Basic; + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(rdirinfo,pVdotL,pV)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(rdirinfo,pVdotL,pV,pV,pV)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create(pV,iso)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create(pV,aniso)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getTangentSpaceL()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) +) && surface_interactions::Anisotropic && surface_interactions::Isotropic && + ray_dir_info::Basic; #undef pVdotL -#undef pN -#undef pB -#undef pT #undef frame #undef pV #undef rdirinfo #undef aniso #undef iso -#undef sample_ +#undef _sample #include -template) +template) struct SLightSample { - using vector_t = vector; - using matrix_t = matrix; + using this_t = SLightSample; + using ray_dir_info_type = RayDirInfo; + using scalar_type = typename RayDirInfo::scalar_type; + using vector3_type = typename RayDirInfo::vector3_type; + using matrix3x3_type = matrix; - static SLightSample createTangentSpace( - NBL_CONST_REF_ARG(vector_t) tangentSpaceV, + using isotropic_type = surface_interactions::SIsotropic; + using anisotropic_type = surface_interactions::SAnisotropic; + + static this_t createTangentSpace( + NBL_CONST_REF_ARG(vector3_type) tangentSpaceV, NBL_CONST_REF_ARG(RayDirInfo) tangentSpaceL, - NBL_CONST_REF_ARG(matrix_t) tangentFrame // WARNING: its the transpose of the old GLSL function return value! + NBL_CONST_REF_ARG(matrix3x3_type) tangentFrame // WARNING: its the transpose of the old GLSL function return value! ) { - SLightSample retval; + this_t retval; retval.L = RayDirInfo::transform(tangentSpaceL,tangentFrame); retval.VdotL = dot(tangentSpaceV,tangentSpaceL); @@ -292,23 +316,23 @@ struct SLightSample return retval; } - static SLightSample create(NBL_CONST_REF_ARG(RayDirInfo) L, const U VdotL, NBL_CONST_REF_ARG(vector_t) N) + static this_t create(NBL_CONST_REF_ARG(RayDirInfo) L, const scalar_type VdotL, NBL_CONST_REF_ARG(vector3_type) N) { - SLightSample retval; + this_t retval; retval.L = L; retval.VdotL = VdotL; - retval.TdotL = nbl::hlsl::numeric_limits::signaling_NaN; - retval.BdotL = nbl::hlsl::numeric_limits::signaling_NaN; + retval.TdotL = nbl::hlsl::numeric_limits::signaling_NaN; + retval.BdotL = nbl::hlsl::numeric_limits::signaling_NaN; retval.NdotL = dot(N,L); retval.NdotL2 = retval.NdotL * retval.NdotL; return retval; } - static SLightSample create(NBL_CONST_REF_ARG(RayDirInfo) L, const U VdotL, NBL_CONST_REF_ARG(vector_t) T, NBL_CONST_REF_ARG(vector_t) B, NBL_CONST_REF_ARG(vector_t) N) + static this_t create(NBL_CONST_REF_ARG(RayDirInfo) L, const scalar_type VdotL, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N) { - SLightSample retval = create(L,VdotL,N); + this_t retval = create(L,VdotL,N); retval.TdotL = dot(T,L); retval.BdotL = dot(B,L); @@ -317,96 +341,72 @@ struct SLightSample } // overloads for surface_interactions template - static SLightSample create(NBL_CONST_REF_ARG(vector_t) L, NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction) + static this_t create(NBL_CONST_REF_ARG(vector3_type) L, NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction) { - const vector_t V = interaction.V.getDirection(); - const float VdotL = dot(V,L); + const vector3_type V = interaction.V.getDirection(); + const scalar_type VdotL = dot(V,L); return create(L, VdotL, interaction.N); } template - static SLightSample create(NBL_CONST_REF_ARG(vector_t) L, NBL_CONST_REF_ARG(surface_interactions::SAnisotropic) interaction) + static this_t create(NBL_CONST_REF_ARG(vector3_type) L, NBL_CONST_REF_ARG(surface_interactions::SAnisotropic) interaction) { - const vector_t V = interaction.V.getDirection(); - const float VdotL = dot(V,L); + const vector3_type V = interaction.V.getDirection(); + const scalar_type VdotL = dot(V,L); return create(L,VdotL,interaction.T,interaction.B,interaction.N); } // - vector_t getTangentSpaceL() + vector3_type getTangentSpaceL() { - return vector_t(TdotL, BdotL, NdotL); + return vector3_type(TdotL, BdotL, NdotL); } RayDirInfo L; - U VdotL; + scalar_type VdotL; - U TdotL; - U BdotL; - U NdotL; - U NdotL2; + scalar_type TdotL; + scalar_type BdotL; + scalar_type NdotL; + scalar_type NdotL2; }; -// everything after here needs testing because godbolt timeout #define NBL_CONCEPT_NAME IsotropicMicrofacetCache -#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename)(typename)(typename)(typename)(typename) -#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(S)(I)(B)(C)(U) // S type Sample, I type Isotropic, B/C type Basic (getting clunky) -#define NBL_CONCEPT_PARAM_0 (cache,T) -#define NBL_CONCEPT_PARAM_1 (iso,I) -#define NBL_CONCEPT_PARAM_2 (pNdotV,U) -#define NBL_CONCEPT_PARAM_3 (pNdotL,U) -#define NBL_CONCEPT_PARAM_4 (pVdotL,U) -#define NBL_CONCEPT_PARAM_5 (rcplen,U) -#define NBL_CONCEPT_PARAM_6 (sample_,S) -#define NBL_CONCEPT_PARAM_7 (V,vector) -#define NBL_CONCEPT_PARAM_8 (L,vector) -#define NBL_CONCEPT_PARAM_9 (N,vector) -#define NBL_CONCEPT_PARAM_10 (H,vector) -#define NBL_CONCEPT_PARAM_11 (eta0,U) -#define NBL_CONCEPT_PARAM_12 (eta1,U) -#define NBL_CONCEPT_PARAM_13 (b0,bool) -#define NBL_CONCEPT_PARAM_14 (b1,bool) -NBL_CONCEPT_BEGIN(11) +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (cache, T) +#define NBL_CONCEPT_PARAM_1 (iso, typename T::isotropic_type) +#define NBL_CONCEPT_PARAM_2 (pNdotV, typename T::scalar_type) +#define NBL_CONCEPT_PARAM_3 (_sample, typename T::sample_type) +#define NBL_CONCEPT_PARAM_4 (V, typename T::vector3_type) +#define NBL_CONCEPT_PARAM_5 (b0, bool) +NBL_CONCEPT_BEGIN(16) #define cache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define pNdotV NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 -#define pNdotL NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 -#define pVdotL NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 -#define rcplen NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 -#define sample_ NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 -#define V NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_7 -#define L NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_8 -#define N NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_9 -#define H NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_10 -#define eta0 NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_11 -#define eta1 NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_12 -#define b0 NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_13 -#define b1 NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_14 +#define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 +#define V NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 +#define b0 NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_TYPE)(T::ray_dir_info_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.VdotH), ::nbl::hlsl::is_same_v, U)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.LdotH), ::nbl::hlsl::is_same_v, U)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.NdotH), ::nbl::hlsl::is_same_v, U)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.NdotH2), ::nbl::hlsl::is_same_v, U)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(pNdotV,pNdotL,pVdotL,rcplen)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(pNdotV,pNdotL,pVdotL)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(iso,sample_)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::compute(cache,b0,V,L,N,pNdotL,pVdotL,eta0,eta1,H)), ::nbl::hlsl::is_same_v, bool)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,iso,sample_,eta0,H)), ::nbl::hlsl::is_same_v, bool)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,iso,sample_,eta0)), ::nbl::hlsl::is_same_v, bool)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.isValidVNDFMicrofacet(b0,b1,pVdotL,eta0,eta1)), ::nbl::hlsl::is_same_v, bool)) -) && surface_interactions::Isotropic && - ray_dir_info::Basic && ray_dir_info::Basic; -#undef b1 + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(pNdotV,pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(iso,_sample)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::compute(cache,b0,V,V,V,pNdotV,pNdotV,pNdotV,pNdotV,V)), ::nbl::hlsl::is_same_v, bool)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,iso,_sample,pNdotV,V)), ::nbl::hlsl::is_same_v, bool)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,iso,_sample,pNdotV)), ::nbl::hlsl::is_same_v, bool)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.isValidVNDFMicrofacet(b0,b0,pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, bool)) +) && surface_interactions::Isotropic; #undef b0 -#undef eta1 -#undef eta0 -#undef H -#undef N -#undef L #undef V -#undef sample_ -#undef rcplen -#undef pVdotL -#undef pNdotL +#undef _sample #undef pNdotV #undef iso #undef cache @@ -415,14 +415,21 @@ NBL_CONCEPT_END( template ) struct SIsotropicMicrofacetCache { - using vector_t = vector; + using this_t = SIsotropicMicrofacetCache; + using scalar_type = T; + using vector3_type = vector; + using matrix3x3_type = matrix; + + using ray_dir_info_type = ray_dir_info::SBasic; + using isotropic_type = surface_interactions::SIsotropic; + using sample_type = SLightSample; // always valid because its specialized for the reflective case - static SIsotropicMicrofacetCache createForReflection(const T NdotV, const T NdotL, const T VdotL, out T LplusV_rcpLen) + static this_t createForReflection(const scalar_type NdotV, const scalar_type NdotL, const scalar_type VdotL, out scalar_type LplusV_rcpLen) { LplusV_rcpLen = rsqrt(2.0 + 2.0 * VdotL); - SIsotropicMicrofacetCache retval; + this_t retval; retval.VdotH = LplusV_rcpLen * VdotL + LplusV_rcpLen; retval.LdotH = retval.VdotH; @@ -431,33 +438,33 @@ struct SIsotropicMicrofacetCache return retval; } - static SIsotropicMicrofacetCache createForReflection(const T NdotV, const T NdotL, const T VdotL) + static this_t createForReflection(const scalar_type NdotV, const scalar_type NdotL, const scalar_type VdotL) { float dummy; return createForReflection(NdotV, NdotL, VdotL, dummy); } - template - static SIsotropicMicrofacetCache createForReflection( - NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction, - NBL_CONST_REF_ARG(SLightSample) _sample) + template && ray_dir_info::Basic) + static this_t createForReflection( + NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction, + NBL_CONST_REF_ARG(SLightSample) _sample) { return createForReflection(interaction.NdotV, _sample.NdotL, _sample.VdotL); } // transmissive cases need to be checked if the path is valid before usage static bool compute( - out SIsotropicMicrofacetCache retval, - const bool transmitted, NBL_CONST_REF_ARG(vector_t) V, NBL_CONST_REF_ARG(vector_t) L, - NBL_CONST_REF_ARG(vector_t) N, const T NdotL, const T VdotL, - const T orientedEta, const T rcpOrientedEta, out vector_t H + out this_t retval, + const bool transmitted, NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) L, + NBL_CONST_REF_ARG(vector3_type) N, const scalar_type NdotL, const scalar_type VdotL, + const scalar_type orientedEta, const scalar_type rcpOrientedEta, out vector3_type H ) { // TODO: can we optimize? - H = computeMicrofacetNormal(transmitted,V,L,orientedEta); + H = computeMicrofacetNormal(transmitted,V,L,orientedEta); retval.NdotH = dot(N, H); // not coming from the medium (reflected) OR // exiting at the macro scale AND ( (not L outside the cone of possible directions given IoR with constraint VdotH*LdotH<0.0) OR (microfacet not facing toward the macrosurface, i.e. non heightfield profile of microsurface) ) - const bool valid = !transmitted || (VdotL <= -min(orientedEta, rcpOrientedEta) && retval.NdotH > nbl::hlsl::numeric_limits::min()); + const bool valid = !transmitted || (VdotL <= -min(orientedEta, rcpOrientedEta) && retval.NdotH > nbl::hlsl::numeric_limits::min()); if (valid) { // TODO: can we optimize? @@ -468,118 +475,105 @@ struct SIsotropicMicrofacetCache } return false; } - template + template && ray_dir_info::Basic) static bool compute( - out SIsotropicMicrofacetCache retval, - NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction, - NBL_CONST_REF_ARG(SLightSample) _sample, - const T eta, out vector_t H + out this_t retval, + NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction, + NBL_CONST_REF_ARG(SLightSample) _sample, + const scalar_type eta, out vector3_type H ) { - const T NdotV = interaction.NdotV; - const T NdotL = _sample.NdotL; + const scalar_type NdotV = interaction.NdotV; + const scalar_type NdotL = _sample.NdotL; const bool transmitted = isTransmissionPath(NdotV,NdotL); - float orientedEta, rcpOrientedEta; - const bool backside = math::getOrientedEtas(orientedEta,rcpOrientedEta,NdotV,eta); + scalar_type orientedEta, rcpOrientedEta; + const bool backside = math::getOrientedEtas(orientedEta,rcpOrientedEta,NdotV,eta); - const vector_t V = interaction.V.getDirection(); - const vector_t L = _sample.L; - const float VdotL = dot(V, L); + const vector3_type V = interaction.V.getDirection(); + const vector3_type L = _sample.L; + const scalar_type VdotL = dot(V, L); return compute(retval,transmitted,V,L,interaction.N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); } - template + template && ray_dir_info::Basic) static bool compute( - out SIsotropicMicrofacetCache retval, - NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction, - NBL_CONST_REF_ARG(SLightSample) _sample, - const T eta + out this_t retval, + NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction, + NBL_CONST_REF_ARG(SLightSample) _sample, + const scalar_type eta ) { - vector_t dummy; + vector3_type dummy; return compute(retval,transmitted,V,L,interaction.N,NdotL,VdotL,orientedEta,rcpOrientedEta,dummy); } - bool isValidVNDFMicrofacet(const bool is_bsdf, const bool transmission, const float VdotL, const T eta, const T rcp_eta) + bool isValidVNDFMicrofacet(const bool is_bsdf, const bool transmission, const scalar_type VdotL, const scalar_type eta, const scalar_type rcp_eta) { return NdotH >= 0.0 && !(is_bsdf && transmission && (VdotL > -min(eta, rcp_eta))); } - T VdotH; - T LdotH; - T NdotH; - T NdotH2; + scalar_type VdotH; + scalar_type LdotH; + scalar_type NdotH; + scalar_type NdotH2; }; #define NBL_CONCEPT_NAME AnisotropicMicrofacetCache -#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename)(typename)(typename)(typename)(typename) -#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(S)(I)(A)(B)(C)(U) // S type Sample, A type Anisotropic, B/C type Basic (getting clunky) -#define NBL_CONCEPT_PARAM_0 (cache,T) -#define NBL_CONCEPT_PARAM_1 (aniso,I) -#define NBL_CONCEPT_PARAM_2 (pNdotL,U) -#define NBL_CONCEPT_PARAM_3 (pVdotL,U) -#define NBL_CONCEPT_PARAM_4 (sample_,S) -#define NBL_CONCEPT_PARAM_5 (V,vector) -#define NBL_CONCEPT_PARAM_6 (L,vector) -#define NBL_CONCEPT_PARAM_7 (T,vector) -#define NBL_CONCEPT_PARAM_8 (B,vector) -#define NBL_CONCEPT_PARAM_9 (N,vector) -#define NBL_CONCEPT_PARAM_10 (H,vector) -#define NBL_CONCEPT_PARAM_11 (eta0,U) -#define NBL_CONCEPT_PARAM_12 (eta1,U) -#define NBL_CONCEPT_PARAM_13 (b0,bool) -NBL_CONCEPT_BEGIN(11) +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (cache, T) +#define NBL_CONCEPT_PARAM_1 (aniso, typename T::anisotropic_type) +#define NBL_CONCEPT_PARAM_2 (pNdotL, typename T::scalar_type) +#define NBL_CONCEPT_PARAM_3 (_sample, typename T::sample_type) +#define NBL_CONCEPT_PARAM_4 (V, typename T::vector3_type) +#define NBL_CONCEPT_PARAM_5 (b0, bool) +NBL_CONCEPT_BEGIN(13) #define cache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define pNdotL NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 -#define pVdotL NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 -#define sample_ NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 -#define V NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 -#define L NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 -#define T NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_7 -#define B NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_8 -#define N NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_9 -#define H NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_10 -#define eta0 NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_11 -#define eta1 NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_12 -#define b0 NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_13 +#define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 +#define V NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 +#define b0 NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.TdotH), ::nbl::hlsl::is_same_v, U)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.BdotH), ::nbl::hlsl::is_same_v, U)) + ((NBL_CONCEPT_REQ_TYPE)(T::ray_dir_info_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::anisotropic_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.TdotH), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.BdotH), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,H)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,H,b0,eta0,eta1)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(V,L,pVdotL)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(aniso,sample_)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(aniso,_sample)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::compute(cache,b0,V,L,T,B,N,pNdotL,pVdotL,eta0,eta1,H)), ::nbl::hlsl::is_same_v, bool)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,aniso,sample_)), ::nbl::hlsl::is_same_v, bool)) -) && surface_interactions::Anisotropic && - ray_dir_info::Basic && ray_dir_info::Basic; + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,aniso,_sample)), ::nbl::hlsl::is_same_v, bool)) +) && surface_interactions::Anisotropic; #undef b0 -#undef eta1 -#undef eta0 -#undef H -#undef N -#undef B -#undef T -#undef L #undef V -#undef sample_ -#undef pVdotL +#undef _sample #undef pNdotL #undef aniso #undef cache #include -template ) -struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache +template ) +struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache { - using vector_t = vector; + using this_t = SAnisotropicMicrofacetCache; + using scalar_type = U; + using vector3_type = vector; + using matrix3x3_type = matrix; + + using ray_dir_info_type = ray_dir_info::SBasic; + using anisotropic_type = surface_interactions::SAnisotropic; + using sample_type = SLightSample; // always valid by construction - static SAnisotropicMicrofacetCache create(NBL_CONST_REF_ARG(vector_t) tangentSpaceV, NBL_CONST_REF_ARG(vector_t) tangentSpaceH) + static this_t create(NBL_CONST_REF_ARG(vector3_type) tangentSpaceV, NBL_CONST_REF_ARG(vector3_type) tangentSpaceH) { - SAnisotropicMicrofacetCache retval; + this_t retval; retval.VdotH = dot(tangentSpaceV,tangentSpaceH); retval.LdotH = retval.VdotH; @@ -590,29 +584,29 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache return retval; } - static SAnisotropicMicrofacetCache create( - NBL_CONST_REF_ARG(vector_t) tangentSpaceV, - NBL_CONST_REF_ARG(vector_t) tangentSpaceH, + static this_t create( + NBL_CONST_REF_ARG(vector3_type) tangentSpaceV, + NBL_CONST_REF_ARG(vector3_type) tangentSpaceH, const bool transmitted, - const T rcpOrientedEta, - const T rcpOrientedEta2 + const scalar_type rcpOrientedEta, + const scalar_type rcpOrientedEta2 ) { - SAnisotropicMicrofacetCache retval = create(tangentSpaceV,tangentSpaceH); + this_t retval = create(tangentSpaceV,tangentSpaceH); if (transmitted) { - const T VdotH = retval.VdotH; + const scalar_type VdotH = retval.VdotH; LdotH = transmitted ? refract_compute_NdotT(VdotH<0.0,VdotH*VdotH,rcpOrientedEta2); } return retval; } // always valid because its specialized for the reflective case - static SAnisotropicMicrofacetCache createForReflection(const float3 tangentSpaceV, const float3 tangentSpaceL, const float VdotL) + static this_t createForReflection(NBL_CONST_REF_ARG(vector3_type) tangentSpaceV, NBL_CONST_REF_ARG(vector3_type) tangentSpaceL, const scalar_type VdotL) { - SAnisotropicMicrofacetCache retval; + this_t retval; - float LplusV_rcpLen; + scalar_type LplusV_rcpLen; retval = createForReflection(tangentSpaceV.z, tangentSpaceL.z, VdotL, LplusV_rcpLen); retval.TdotH = (tangentSpaceV.x + tangentSpaceL.x)*LplusV_rcpLen; retval.BdotH = (tangentSpaceV.y + tangentSpaceL.y)*LplusV_rcpLen; @@ -620,23 +614,23 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache return retval; } template - static SAnisotropicMicrofacetCache createForReflection( - NBL_CONST_REF_ARG(surface_interactions::SAnisotropic) interaction, - NBL_CONST_REF_ARG(SLightSample) _sample) + static this_t createForReflection( + NBL_CONST_REF_ARG(surface_interactions::SAnisotropic) interaction, + NBL_CONST_REF_ARG(SLightSample) _sample) { return createForReflection(interaction.getTangentSpaceV(), _sample.getTangentSpaceL(), _sample.VdotL); } // transmissive cases need to be checked if the path is valid before usage static bool compute( - out SAnisotropicMicrofacetCache retval, - const bool transmitted, NBL_CONST_REF_ARG(vector_t) V, NBL_CONST_REF_ARG(vector_t) L, - NBL_CONST_REF_ARG(vector_t) T, NBL_CONST_REF_ARG(vector_t) B, NBL_CONST_REF_ARG(vector_t) N, - const T NdotL, const T VdotL, - const T orientedEta, const T rcpOrientedEta, out vector_t H + out this_t retval, + const bool transmitted, NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) L, + NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N, + const scalar_type NdotL, const scalar_type VdotL, + const scalar_type orientedEta, const scalar_type rcpOrientedEta, out vector3_type H ) { - vector_t H; - const bool valid = SIsotropicMicrofacetCache::compute(retval,transmitted,V,L,N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); + vector3_type H; + const bool valid = this_t::compute(retval,transmitted,V,L,N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); if (valid) { retval.TdotH = dot(T,H); @@ -646,14 +640,14 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache } template static bool compute( - out SAnisotropicMicrofacetCache retval, - NBL_CONST_REF_ARG(surface_interactions::SAnisotropic) interaction, - NBL_CONST_REF_ARG(SLightSample) _sample, - const T eta + out this_t retval, + NBL_CONST_REF_ARG(surface_interactions::SAnisotropic) interaction, + NBL_CONST_REF_ARG(SLightSample) _sample, + const scalar_type eta ) { - vector_t H; - const bool valid = SIsotropicMicrofacetCache::compute(retval,interaction,_sample,eta,H); + vector3_type H; + const bool valid = this_t::compute(retval,interaction,_sample,eta,H); if (valid) { retval.TdotH = dot(interaction.T,H); @@ -662,8 +656,8 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache return valid; } - T TdotH; - T BdotH; + scalar_type TdotH; + scalar_type BdotH; }; @@ -671,8 +665,8 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache #define NBL_CONCEPT_NAME generalized_spectral_of #define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename) #define NBL_CONCEPT_TPLT_PRM_NAMES (T)(F) -#define NBL_CONCEPT_PARAM_0 (spec,T) -#define NBL_CONCEPT_PARAM_1 (field,F) +#define NBL_CONCEPT_PARAM_0 (spec, T) +#define NBL_CONCEPT_PARAM_1 (field, F) NBL_CONCEPT_BEGIN(2) #define spec NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define field NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 @@ -715,64 +709,80 @@ typedef quotient_and_pdf, float32_t> quotient_and_pdf_rgb; #define NBL_CONCEPT_NAME BxDF -#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename)(typename)(typename)(typename)(typename) -#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(LS)(I)(A)(Q)(S)(P) -#define NBL_CONCEPT_PARAM_0 (bxdf,T) -#define NBL_CONCEPT_PARAM_1 (spec,S) -#define NBL_CONCEPT_PARAM_2 (pdf,P) -#define NBL_CONCEPT_PARAM_3 (sample_,LS) -#define NBL_CONCEPT_PARAM_4 (iso,I) -#define NBL_CONCEPT_PARAM_5 (aniso,A) -NBL_CONCEPT_BEGIN(2) +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (bxdf, T) +#define NBL_CONCEPT_PARAM_1 (spec, typename T::spectral_type) +#define NBL_CONCEPT_PARAM_2 (pdf, typename T::scalar_type) +#define NBL_CONCEPT_PARAM_3 (_sample, typename T::sample_type) +#define NBL_CONCEPT_PARAM_4 (iso, typename T::isotropic_type) +#define NBL_CONCEPT_PARAM_5 (aniso, typename T::anisotropic_type) +NBL_CONCEPT_BEGIN(8) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define spec NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define pdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 -#define sample_ NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 +#define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 #define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 #define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template generate(aniso,aniso.N)), ::nbl::hlsl::is_same_v, LS)) - //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template pdf(sample_,iso)), ::nbl::hlsl::is_scalar_v)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template quotient_and_pdf(sample_,iso)), ::nbl::hlsl::is_same_v, Q)) -) && is_scalar_v(sample_,iso))> && && Sample && spectral_of && is_floating_point_v

; + ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::anisotropic_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::spectral_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template generate(aniso,aniso.N)), ::nbl::hlsl::is_same_v, typename T::sample_type)) + //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template pdf(_sample,iso)), ::nbl::hlsl::is_scalar_v)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template quotient_and_pdf(_sample,iso)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) +) && is_scalar_v(_sample,iso))> && Sample && + spectral_of && is_floating_point_v; #undef aniso #undef iso -#undef sample_ +#undef _sample #undef pdf #undef spec #undef bxdf #include #define NBL_CONCEPT_NAME MicrofacetBxDF -#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename)(typename)(typename)(typename)(typename)(typename)(typename) -#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(LS)(IC)(AC)(I)(A)(Q)(S)(P) -#define NBL_CONCEPT_PARAM_0 (bxdf,T) -#define NBL_CONCEPT_PARAM_1 (spec,S) -#define NBL_CONCEPT_PARAM_2 (pdf,P) -#define NBL_CONCEPT_PARAM_3 (sample_,LS) -#define NBL_CONCEPT_PARAM_4 (iso,I) -#define NBL_CONCEPT_PARAM_5 (aniso,A) -#define NBL_CONCEPT_PARAM_4 (isocache,IC) -#define NBL_CONCEPT_PARAM_5 (anisocache,AC) +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (bxdf, T) +#define NBL_CONCEPT_PARAM_1 (spec, typename T::spectral_type) +#define NBL_CONCEPT_PARAM_2 (pdf, typename T::scalar_type) +#define NBL_CONCEPT_PARAM_3 (_sample, typename T::sample_type) +#define NBL_CONCEPT_PARAM_4 (iso, typename T::isotropic_type) +#define NBL_CONCEPT_PARAM_5 (aniso, typename T::anisotropic_type) +#define NBL_CONCEPT_PARAM_6 (isocache, typename T::isocache_type) +#define NBL_CONCEPT_PARAM_7 (anisocache, typename T::anisocache_type) NBL_CONCEPT_BEGIN(1) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define spec NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define pdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 -#define sample_ NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 +#define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 #define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 #define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 #define isocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 #define anisocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_7 NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template generate(aniso,aniso.N,anisocache)), ::nbl::hlsl::is_same_v, LS)) - //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template pdf(sample_,iso)), ::nbl::hlsl::is_scalar_v)) - //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template quotient_and_pdf(sample_,iso)), ::nbl::hlsl::is_same_v, Q)) -) && is_scalar_v(sample_,iso,isocache))> && Sample && spectral_of && is_floating_point_v

; + ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::anisotropic_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::spectral_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::isocache_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::anisocache_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template generate(aniso,aniso.N,anisocache)), ::nbl::hlsl::is_same_v, typename T::sample_type)) + //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template pdf(_sample,iso)), ::nbl::hlsl::is_scalar_v)) + //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template quotient_and_pdf(_sample,iso)), ::nbl::hlsl::is_same_v, Q)) +) && is_scalar_v(_sample,iso,isocache))> && + Sample && spectral_of && is_floating_point_v; #undef anisocache #undef isocache #undef aniso #undef iso -#undef sample_ +#undef _sample #undef pdf #undef spec #undef bxdf diff --git a/include/nbl/builtin/hlsl/math/functions.hlsl b/include/nbl/builtin/hlsl/math/functions.hlsl index 1c1b7361ea..bef105e318 100644 --- a/include/nbl/builtin/hlsl/math/functions.hlsl +++ b/include/nbl/builtin/hlsl/math/functions.hlsl @@ -174,7 +174,7 @@ template ) vector reflect(vector I, vector N) { T NdotI = dot(N, I); - return reflect(I, N, NdotI); + return reflect(I, N, NdotI); } @@ -219,11 +219,13 @@ bool getOrientedEtas(out T orientedEta, out T rcpOrientedEta, scalar_type_t N namespace impl { +template struct refract { using this_t = refract; + using vector_type = vector; - static this_t create(float3 I, float3 N, bool backside, float NdotI, float NdotI2, float rcpOrientedEta, float rcpOrientedEta2) + static this_t create(vector_type I, vector_type N, bool backside, T NdotI, T NdotI2, T rcpOrientedEta, T rcpOrientedEta2) { this_t retval; retval.I = I; @@ -236,85 +238,89 @@ struct refract return retval; } - static this_t create(float3 I, float3 N, float NdotI, float eta) + static this_t create(vector_type I, vector_type N, T NdotI, T eta) { this_t retval; retval.I = I; retval.N = N; - float orientedEta; - retval.backside = getOrientedEtas(orientedEta, retval.rcpOrientedEta, NdotI, eta); + T orientedEta; + retval.backside = getOrientedEtas(orientedEta, retval.rcpOrientedEta, NdotI, eta); retval.NdotI = NdotI; retval.NdotI2 = NdotI * NdotI; retval.rcpOrientedEta2 = retval.rcpOrientedEta * retval.rcpOrientedEta; return retval; } - static this_t create(float3 I, float3 N, float eta) + static this_t create(vector_type I, vector_type N, T eta) { this_t retval; retval.I = I; retval.N = N; retval.NdotI = dot(N, I); - float orientedEta; - retval.backside = getOrientedEtas(orientedEta, retval.rcpOrientedEta, retval.NdotI, eta); + T orientedEta; + retval.backside = getOrientedEtas(orientedEta, retval.rcpOrientedEta, retval.NdotI, eta); retval.NdotI2 = retval.NdotI * retval.NdotI; retval.rcpOrientedEta2 = retval.rcpOrientedEta * retval.rcpOrientedEta; return retval; } - float computeNdotT() + T computeNdotT() { - float NdotT2 = rcpOrientedEta2 * NdotI2 + 1.0 - rcpOrientedEta2; - float absNdotT = sqrt(NdotT2); + T NdotT2 = rcpOrientedEta2 * NdotI2 + 1.0 - rcpOrientedEta2; + T absNdotT = sqrt(NdotT2); return backside ? absNdotT : -(absNdotT); } - float3 doRefract() + vector_type doRefract() { return N * (NdotI * rcpOrientedEta + computeNdotT()) - rcpOrientedEta * I; } - static float3 doReflectRefract(bool _refract, float3 _I, float3 _N, float _NdotI, float _NdotTorR, float _rcpOrientedEta) + static vector_type doReflectRefract(bool _refract, vector_type _I, vector_type _N, T _NdotI, T _NdotTorR, T _rcpOrientedEta) { return _N * (_NdotI * (_refract ? _rcpOrientedEta : 1.0) + _NdotTorR) - _I * (_refract ? _rcpOrientedEta : 1.0); } - float3 doReflectRefract(bool r) + vector_type doReflectRefract(bool r) { - const float NdotTorR = r ? computeNdotT() : NdotI; + const T NdotTorR = r ? computeNdotT() : NdotI; return doReflectRefract(r, I, N, NdotI, NdotTorR, rcpOrientedEta); } - float3 I; - float3 N; + vector_type I; + vector_type N; bool backside; - float NdotI; - float NdotI2; - float rcpOrientedEta; - float rcpOrientedEta2; + T NdotI; + T NdotI2; + T rcpOrientedEta; + T rcpOrientedEta2; }; } -float3 refract(float3 I, float3 N, bool backside, float NdotI, float NdotI2, float rcpOrientedEta, float rcpOrientedEta2) +template) +vector refract(vector I, vector N, bool backside, T NdotI, T NdotI2, T rcpOrientedEta, T rcpOrientedEta2) { impl::refract r = impl::refract::create(I, N, backside, NdotI, NdotI2, rcpOrientedEta, rcpOrientedEta2); return r.doRefract(); } -float3 refract(float3 I, float3 N, float NdotI, float eta) +template) +vector refract(vector I, vector N, T NdotI, T eta) { impl::refract r = impl::refract::create(I, N, NdotI, eta); return r.doRefract(); } -float3 refract(float3 I, float3 N, float eta) +template) +vector refract(vector I, vector N, T eta) { impl::refract r = impl::refract::create(I, N, eta); return r.doRefract(); } // I don't like exposing these next two -float3 reflectRefract_computeNdotT(bool backside, float NdotI2, float rcpOrientedEta2) +template) +vector reflectRefract_computeNdotT(bool backside, T NdotI2, T rcpOrientedEta2) { impl::refract r; r.NdotI2 = NdotI2; @@ -323,18 +329,21 @@ float3 reflectRefract_computeNdotT(bool backside, float NdotI2, float rcpOriente return r.computeNdotT(); } -float3 reflectRefract_impl(bool _refract, float3 _I, float3 _N, float _NdotI, float _NdotTorR, float _rcpOrientedEta) +template) +vector reflectRefract_impl(bool _refract, vector _I, vector _N, T _NdotI, T _NdotTorR, T _rcpOrientedEta) { return impl::refract::doReflectRefract(_refract, _I, _N, _NdotI, _NdotTorR, _rcpOrientedEta); } -float3 reflectRefract(bool _refract, float3 I, float3 N, bool backside, float NdotI, float NdotI2, float rcpOrientedEta, float rcpOrientedEta2) +template) +vector reflectRefract(bool _refract, vector I, vector N, bool backside, T NdotI, T NdotI2, T rcpOrientedEta, T rcpOrientedEta2) { impl::refract r = impl::refract::create(I, N, backside, NdotI, NdotI2, rcpOrientedEta, rcpOrientedEta2); return r.doReflectRefract(_refract); } -float3 reflectRefract(bool _refract, float3 I, float3 N, float NdotI, float eta) +template) +vector reflectRefract(bool _refract, vector I, vector N, T NdotI, T eta) { impl::refract r = impl::refract::create(I, N, NdotI, eta); return r.doReflectRefract(_refract); From fe7c882ea6a075880b882533fc659c87ad91c897 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 9 Dec 2024 17:18:41 +0700 Subject: [PATCH 019/188] ndfs as structs() --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 13 +- include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 233 ++++++++++++++++------ 2 files changed, 184 insertions(+), 62 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index e80e74808a..80d5a06dbe 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -14,6 +14,17 @@ namespace nbl { namespace hlsl { + +// TODO: move into ieee754 namespace hlsl +namespace ieee754 +{ + template) + T condNegate(T a, bool flip) + { + return flip ? (-a) : a; + } +} + namespace bxdf { @@ -23,7 +34,7 @@ T computeUnnormalizedMicrofacetNormal(bool _refract, vector V, vector { const T etaFactor = (_refract ? orientedEta : 1.0); const vector tmpH = V + L * etaFactor; - return _refract ? (-tmpH) : tmpH; + return ieee754::condNegate(tmpH, _refract); } // returns normalized vector, but NaN when result is length 0 diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl index 5d36f8b203..e57f8c2e64 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -16,6 +16,178 @@ namespace bxdf namespace ndf { +template) +struct SIsotropicParams +{ + using this_t = SIsotropicParams; + + static this_t create(T NdotH, T n) // blinn-phong + { + this_t retval; + retval.NdotH = NdotH; + retval.n = n; + return this_t; + } + + static this_t create(T a2, T NdotH2) // beckmann, ggx + { + this_t retval; + retval.a2 = a2; + retval.NdotH = NdotH; + return this_t; + } + + T a2; + T n; + T NdotH; + T NdotH2; + T TdotH2; + T BdotH2; +}; + +template) +struct SAnisotropicParams +{ + using this_t = SAnisotropicParams; + + static this_t create(T NdotH, T one_minus_NdotH2_rcp, T TdotH2, T BdotH2, T nx, T ny) // blinn-phong + { + this_t retval; + retval.NdotH = NdotH; + retval.one_minus_NdotH2_rcp = one_minus_NdotH2_rcp; + retval.TdotH2 = TdotH2; + retval.BdotH2 = BdotH2; + retval.nx = nx; + retval.ny = ny; + return this_t; + } + + static this_t create(T ax, T ay, T ax2, T ay2, T TdotH2, T BdotH2, T NdotH2) // beckmann + { + this_t retval; + retval.ax = ax; + retval.ax2 = ax2; + retval.ay = ay; + retval.ay2 = ay2; + retval.TdotH2 = TdotH2; + retval.BdotH2 = BdotH2; + retval.NdotH2 = NdotH2; + return this_t; + } + + static this_t create(T TdotH2, T BdotH2, T NdotH2, T ax, T ay, T ax2, T ay2) // ggx aniso + { + this_t retval; + retval.ax = ax; + retval.ax2 = ax2; + retval.ay = ay; + retval.ay2 = ay2; + retval.TdotH2 = TdotH2; + retval.BdotH2 = BdotH2; + retval.NdotH2 = NdotH2; + return this_t; + } + + static this_t create(T a2, T TdotH, T BdotH, T NdotH) // ggx burley + { + this_t retval; + retval.ax = a2; + retval.TdotH = TdotH; + retval.BdotH = BdotH; + retval.NdotH = NdotH; + return this_t; + } + + T ax; + T ay; + T ax2; + T ay2; + T nx; + T ny; + T NdotH; + T TdotH; + T BdotH; + T NdotH2; + T TdotH2; + T BdotH2; + T one_minus_NdotH2_rcp; +}; + + +template) +struct BlinnPhong +{ + using scalar_type = T; + + // blinn-phong + scalar_type operator()(SIsotropicParams params) + { + // n is shininess exponent in original paper + return isinf(params.n) ? numeric_limits::infinity : numbers::inv_pi * 0.5 * (params.n + 2.0) * pow(params.NdotH, params.n); + } + + //ashikhmin-shirley ndf + scalar_type operator()(SAnisotropicParams params) + { + scalar_type n = (params.TdotH2 * params.ny + params.BdotH2 * params.nx) * params.one_minus_NdotH2_rcp; + return (isinf(params.nx) || isinf(params.ny)) ? numeric_limits::infinity : + sqrt((params.nx + 2.0) * (params.ny + 2.0)) * numbers::inv_pi * 0.5 * pow(params.NdotH, n); + } +}; + +template) +struct Beckmann +{ + using scalar_type = T; + + scalar_type operator()(SIsotropicParams params) + { + scalar_type nom = exp( (params.NdotH2 - 1.0) / (params.a2 * params.NdotH2) ); // exp(x) == exp2(x/log(2)) ? + scalar_type denom = params.a2 * params.NdotH2 * params.NdotH2; + return numbers::inv_pi * nom / denom; + } + + scalar_type operator()(SAnisotropicParams params) + { + scalar_type nom = exp(-(params.TdotH2 / params.ax2 + params.BdotH2 / params.ay2) / params.NdotH2); + scalar_type denom = params.ax * params.ay * params.NdotH2 * params.NdotH2; + return numbers::inv_pi * nom / denom; + } +}; + + +template) +struct GGX +{ + using scalar_type = T; + + // trowbridge-reitz + scalar_type operator()(SIsotropicParams params) + { + scalar_type denom = params.NdotH2 * (params.a2 - 1.0) + 1.0; + return params.a2 * numbers::inv_pi / (denom * denom); + } + + scalar_type operator()(SAnisotropicParams params) + { + scalar_type a2 = params.ax * params.ay; + scalar_type denom = params.TdotH2 / params.ax2 + params.BdotH2 / params.ay2 + params.NdotH2; + return numbers::inv_pi / (params.a2 * denom * denom); + } + + // burley + scalar_type operator()(SAnisotropicParams params, scalar_type anisotropy) + { + scalar_type antiAniso = 1.0 - anisotropy; + scalar_type atab = params.ax * antiAniso; + scalar_type anisoTdotH = antiAniso * params.TdotH; + scalar_type anisoNdotH = antiAniso * params.NdotH; + scalar_type w2 = antiAniso/(params.BdotH * params.BdotH + anisoTdotH * anisoTdotH + anisoNdotH * anisoNdotH * params.ax); + return w2 * w2 * atab * numbers::inv_pi; + } +}; + + // common namespace impl { @@ -75,67 +247,6 @@ T microfacet_to_light_measure_transform(T NDFcos, T maxNdotV) return impl::microfacet_to_light_measure_transform::__call(NDFcos, maxNdotV); } - -// blinn-phong -template) -T blinn_phong(T NdotH, T n) // n is shininess exponent -{ - return isinf(n) ? numeric_limits::infinity : numbers::inv_pi * 0.5 * (n + 2.0) * pow(NdotH,n); -} -//ashikhmin-shirley ndf -template) -T blinn_phong(T NdotH, T one_minus_NdotH2_rcp, T TdotH2, T BdotH2, T nx, T ny) -{ - T n = (TdotH2 * ny + BdotH2 * nx) * one_minus_NdotH2_rcp; - return (isinf(nx) || isinf(ny)) ? numeric_limits::infinity : sqrt((nx + 2.0) * (ny + 2.0)) * numbers::inv_pi * 0.5 * pow(NdotH, n); -} - - -// beckmann -template) -T beckmann(T a2, T NdotH2) -{ - T nom = exp( (NdotH2 - 1.0) / (a2 * NdotH2) ); // exp(x) == exp2(x/log(2)) ? - T denom = a2 * NdotH2 * NdotH2; - return numbers::inv_pi * nom / denom; -} - -template) -T beckmann(T ax, T ay, T ax2, T ay2, T TdotH2, T BdotH2, T NdotH2) -{ - T nom = exp(-(TdotH2 / ax2 + BdotH2 / ay2) / NdotH2); - T denom = ax * ay * NdotH2 * NdotH2; - return numbers::inv_pi * nom / denom; -} - - -// ggx -template) -T ggx_trowbridge_reitz(T a2, T NdotH2) -{ - T denom = NdotH2 * (a2 - 1.0) + 1.0; - return a2* numbers::inv_pi / (denom * denom); -} - -template) -T ggx_burley_aniso(T anisotropy, T a2, T TdotH, T BdotH, T NdotH) -{ - T antiAniso = 1.0 - anisotropy; - T atab = a2 * antiAniso; - T anisoTdotH = antiAniso * TdotH; - T anisoNdotH = antiAniso * NdotH; - T w2 = antiAniso/(BdotH * BdotH + anisoTdotH * anisoTdotH + anisoNdotH * anisoNdotH * a2); - return w2 * w2 * atab * numbers::inv_pi; -} - -template) -T ggx_aniso(T TdotH2, T BdotH2, T NdotH2, T ax, T ay, T ax2, T ay2) -{ - T a2 = ax * ay; - T denom = TdotH2 / ax2 + BdotH2 / ay2 + NdotH2; - return numbers::inv_pi / (a2 * denom * denom); -} - } } } From a12d8d187d02f4ecfbb992c62795397cc49c2d5a Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 10 Dec 2024 12:09:24 +0700 Subject: [PATCH 020/188] redid microfacet_to_light_transform as all structs --- include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 136 +++++++++++++++++-------- 1 file changed, 96 insertions(+), 40 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl index e57f8c2e64..bdb29b2e68 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -187,65 +187,121 @@ struct GGX } }; - // common namespace impl { -template -struct microfacet_to_light_measure_transform +template +struct is_ggx : bool_constant< + is_same >::value +> {}; +} + +template +struct is_ggx : impl::is_ggx {}; + +template +NBL_CONSTEXPR bool is_ggx_v = is_ggx::value; + + +enum MicrofacetTransformTypes : uint16_t { - static T __call(T NDFcos, T absNdotV, bool transmitted, T VdotH, T LdotH, T VdotHLdotH, T orientedEta) + REFLECT_BIT = 0b01, + REFRACT_BIT = 0b10, + REFLECT_REFRACT_BIT = 0b11 +}; + +template +struct microfacet_to_light_measure_transform; + + +template +struct microfacet_to_light_measure_transform +{ + using scalar_type = NDF::scalar_type; + + scalar_type operator()() { - T denominator = absNdotV; - if (transmitted) - { - const T VdotH_etaLdotH = (VdotH+orientedEta*LdotH); - // VdotHLdotH is negative under transmission, so thats denominator is negative - denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; - } - return NDFcos * (transmitted ? VdotHLdotH : 0.25) / denominator; + if (is_ggv_v) + return NDFcos * maxNdotL; + else + return 0.25 * NDFcos / maxNdotV; } - static T __call(T NDFcos, T maxNdotV) + T NDFcos + T maxNdotV + T maxNdotL +}; + +template +struct microfacet_to_light_measure_transform +{ + using scalar_type = NDF::scalar_type; + + scalar_type operator()() { - return 0.25 * NDFcos / maxNdotV; + scalar_type denominator; + if (is_ggv_v) + denominator = absNdotL; + else + denominator = absNdotV; + + const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); + // VdotHLdotH is negative under transmission, so thats denominator is negative + denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; + return NDFcos * VdotHLdotH / denominator; } + T NDFcos + T absNdotV + T absNdotL + + T VdotH + T LdotH + T VdotHLdotH + T orientedEta }; -template -struct microfacet_to_light_measure_transform +template +struct microfacet_to_light_measure_transform { - static T __call(T NDFcos_already_in_reflective_dL_measure, T absNdotL, bool transmitted, T VdotH, T LdotH, T VdotHLdotH, T orientedEta) + using scalar_type = NDF::scalar_type; + + scalar_type operator()() { - T denominator = absNdotL; - if (transmitted) + if (is_ggv_v) { - const T VdotH_etaLdotH = (VdotH+orientedEta*LdotH); - // VdotHLdotH is negative under transmission, so thats denominator is negative - denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; + T denominator = absNdotL; + if (transmitted) + { + const T VdotH_etaLdotH = (VdotH + orientedEta * LdotH); + // VdotHLdotH is negative under transmission, so thats denominator is negative + denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; + } + return NDFcos * (transmitted ? VdotHLdotH : 0.25) / denominator; + } + else + { + T denominator = absNdotV; + if (transmitted) + { + const T VdotH_etaLdotH = (VdotH + orientedEta * LdotH); + // VdotHLdotH is negative under transmission, so thats denominator is negative + denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; + } + return NDFcos * (transmitted ? VdotHLdotH : 0.25) / denominator; } - return NDFcos_already_in_reflective_dL_measure * (transmitted ? VdotHLdotH : 0.25) / denominator; - } - - static T __call(T NDFcos_already_in_reflective_dL_measure, T maxNdotL) - { - return NDFcos_already_in_reflective_dL_measure * maxNdotL; } -}; -} -template) -T microfacet_to_light_measure_transform(T NDFcos, T absNdotV, bool transmitted, T VdotH, T LdotH, T VdotHLdotH, T orientedEta) -{ - return impl::microfacet_to_light_measure_transform::__call(NDFcos, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); -} + bool transmitted + T NDFcos + T absNdotV + T absNdotL -template) -T microfacet_to_light_measure_transform(T NDFcos, T maxNdotV) -{ - return impl::microfacet_to_light_measure_transform::__call(NDFcos, maxNdotV); -} + T VdotH + T LdotH + T VdotHLdotH + T orientedEta +}; } } From 328c7ea81a0afe6aa2a2e2ea85b7d8e313ef0e9f Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 10 Dec 2024 14:21:28 +0700 Subject: [PATCH 021/188] fixed missing type --- include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 89 +++++++++++++++++++------- 1 file changed, 67 insertions(+), 22 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl index bdb29b2e68..ab9cacf5a7 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -217,8 +217,20 @@ struct microfacet_to_light_measure_transform; template struct microfacet_to_light_measure_transform { + using this_t = microfacet_to_light_measure_transform; using scalar_type = NDF::scalar_type; + static this_t create(scalar_type NDFcos, scalar_type maxNdotV) + { + this_t retval; + retval.NDFcos = NDFcos; + if (is_ggv_v) + retval.maxNdotL = maxNdotV; + else + retval.maxNdotV = maxNdotV; + return retval; + } + scalar_type operator()() { if (is_ggv_v) @@ -227,16 +239,32 @@ struct microfacet_to_light_measure_transform return 0.25 * NDFcos / maxNdotV; } - T NDFcos - T maxNdotV - T maxNdotL + scalar_type NDFcos + scalar_type maxNdotV + scalar_type maxNdotL }; template struct microfacet_to_light_measure_transform { + using this_t = microfacet_to_light_measure_transform; using scalar_type = NDF::scalar_type; + static this_t create(scalar_type NDFcos, scalar_type absNdotV, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) + { + this_t retval; + retval.NDFcos = NDFcos; + if (is_ggv_v) + retval.absNdotL = absNdotV; + else + retval.absNdotV = absNdotV; + retval.VdotH = VdotH; + retval.LdotH = LdotH; + retval.VdotHLdotH = VdotHLdotH; + retval.orientedEta = orientedEta; + return retval; + } + scalar_type operator()() { scalar_type denominator; @@ -251,29 +279,46 @@ struct microfacet_to_light_measure_transform return NDFcos * VdotHLdotH / denominator; } - T NDFcos - T absNdotV - T absNdotL + scalar_type NDFcos + scalar_type absNdotV + scalar_type absNdotL - T VdotH - T LdotH - T VdotHLdotH - T orientedEta + scalar_type VdotH + scalar_type LdotH + scalar_type VdotHLdotH + scalar_type orientedEta }; template struct microfacet_to_light_measure_transform { + using this_t = microfacet_to_light_measure_transform; using scalar_type = NDF::scalar_type; + static this_t create(scalar_type NDFcos, scalar_type absNdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) + { + this_t retval; + retval.NDFcos = NDFcos; + if (is_ggv_v) + retval.absNdotL = absNdotV; + else + retval.absNdotV = absNdotV; + retval.transmitted = transmitted; + retval.VdotH = VdotH; + retval.LdotH = LdotH; + retval.VdotHLdotH = VdotHLdotH; + retval.orientedEta = orientedEta; + return retval; + } + scalar_type operator()() { if (is_ggv_v) { - T denominator = absNdotL; + scalar_type denominator = absNdotL; if (transmitted) { - const T VdotH_etaLdotH = (VdotH + orientedEta * LdotH); + const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); // VdotHLdotH is negative under transmission, so thats denominator is negative denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; } @@ -281,10 +326,10 @@ struct microfacet_to_light_measure_transform } else { - T denominator = absNdotV; + scalar_type denominator = absNdotV; if (transmitted) { - const T VdotH_etaLdotH = (VdotH + orientedEta * LdotH); + const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); // VdotHLdotH is negative under transmission, so thats denominator is negative denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; } @@ -293,14 +338,14 @@ struct microfacet_to_light_measure_transform } bool transmitted - T NDFcos - T absNdotV - T absNdotL - - T VdotH - T LdotH - T VdotHLdotH - T orientedEta + scalar_type NDFcos + scalar_type absNdotV + scalar_type absNdotL + + scalar_type VdotH + scalar_type LdotH + scalar_type VdotHLdotH + scalar_type orientedEta }; } From aeafa07478aa06653b24e8e5728a0ca8547d955c Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 10 Dec 2024 16:38:04 +0700 Subject: [PATCH 022/188] changed geom smith to templated structs --- include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl | 337 ++++++++++-------- include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 12 +- 2 files changed, 203 insertions(+), 146 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl index c18eda6d3a..48e1afefcb 100644 --- a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl @@ -15,7 +15,6 @@ namespace bxdf namespace smith { -// TODO: need struct specializations? don't know which is used vs. helper template) T G1(T lambda) @@ -23,20 +22,21 @@ T G1(T lambda) return 1.0 / (1.0 + lambda); } -template) -T VNDF_pdf_wo_clamps(T ndf, T lambda_V, T maxNdotV, out T onePlusLambda_V) +template +T VNDF_pdf_wo_clamps(NDF ndf, typename NDF::scalar_type lambda_V, typename NDF::scalar_type maxNdotV, out typename NDF::scalar_type onePlusLambda_V) { onePlusLambda_V = 1.0 + lambda_V; - - return ndf::microfacet_to_light_measure_transform(ndf / onePlusLambda_V, maxNdotV); + ndf::microfacet_to_light_measure_transform transform = ndf::microfacet_to_light_measure_transform::create(ndf() / onePlusLambda_V, maxNdotV); + return transform(); } -template) -T VNDF_pdf_wo_clamps(T ndf, T lambda_V, T absNdotV, bool transmitted, T VdotH, T LdotH, T VdotHLdotH, T orientedEta, T reflectance, out T onePlusLambda_V) +template +T VNDF_pdf_wo_clamps(NDF ndf, typename NDF::scalar_type lambda_V, typename NDF::scalar_type absNdotV, bool transmitted, typename NDF::scalar_type VdotH, typename NDF::scalar_type LdotH, typename NDF::scalar_type VdotHLdotH, typename NDF::scalar_type orientedEta, typename NDF::scalar_type reflectance, out typename NDF::scalar_type onePlusLambda_V) { onePlusLambda_V = 1.0 + lambda_V; - - return ndf::microfacet_to_light_measure_transform((transmitted ? (1.0 - reflectance) : reflectance) * ndf / onePlusLambda_V, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); + ndf::microfacet_to_light_measure_transform transform + = ndf::microfacet_to_light_measure_transform::create((transmitted ? (1.0 - reflectance) : reflectance) * ndf() / onePlusLambda_V, , absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); + return transform(); } template) @@ -67,166 +67,223 @@ T VNDF_pdf_wo_clamps(T ndf, T G1_over_2NdotV, T absNdotV, bool transmitted, T Vd } -// beckmann -template) -T beckmann_C2(T NdotX2, T a2) +template) +struct SIsotropicParams { - return NdotX2 / (a2 * (1.0 - NdotX2)); -} + using this_t = SIsotropicParams; -template) -T beckmann_C2(T TdotX2, T BdotX2, T NdotX2, T ax2, T ay2) -{ - return NdotX2/(TdotX2 * ax2 + BdotX2 * ay2); -} + static this_t create(T a2, T NdotV2, T NdotL2, T lambdaV_plus_one) // beckmann + { + this_t retval; + retval.a2 = a2; + retval.NdotV2 = NdotV2; + retval.NdotL2 = NdotL2; + retval.lambdaV_plus_one = lambdaV_plus_one; + return this_t; + } -template) -T beckmann_Lambda(T c2) -{ - T c = sqrt(c2); - T nom = 1.0 - 1.259 * c + 0.396 * c2; - T denom = 2.181 * c2 + 3.535 * c; - return lerp(0.0, nom / denom, c < 1.6); -} + static this_t create(T a2, T NdotV, T NdotV2, T NdotL, T NdotL2) // ggx + { + this_t retval; + retval.a2 = a2; + retval.NdotV = NdotV; + retval.NdotV2 = NdotV2; + retval.NdotL = NdotL; + retval.NdotL2 = NdotL2; + retval.one_minus_a2 = 1.0 - a2; + return this_t; + } -template) -T beckmann_Lambda(T NdotX2, T a2) + T a2; + T NdotV; + T NdotL; + T NdotV2; + T NdotL2; + T lambdaV_plus_one; + T one_minus_a2; +}; + +template) +struct SAnisotropicParams { - return beckmann_Lambda(beckmann_C2(NdotX2, a2)); -} + using this_t = SAnisotropicParams; -template) -T beckmann_Lambda(T TdotX2, T BdotX2, T NdotX2, T ax2, T ay2) -{ - return beckmann_Lambda(beckmann_C2(TdotX2, BdotX2, NdotX2, ax2, ay2)); -} + static this_t create(T ax2, T ay2, T TdotV2, T BdotV2, T NdotV2, T TdotL2, T BdotL2, T NdotL2, T lambdaV_plus_one) // beckmann + { + this_t retval; + retval.ax2 = ax2; + retval.ay2 = ay2; + retval.TdotV2 = TdotV2; + retval.BdotV2 = BdotV2; + retval.NdotV2 = NdotV2; + retval.TdotL2 = TdotL2; + retval.BdotL2 = BdotL2; + retval.NdotL2 = NdotL2; + retval.lambdaV_plus_one = lambdaV_plus_one; + return this_t; + } -template) -T beckmann_smith_correlated(T NdotV2, T NdotL2, T a2) -{ - T c2 = beckmann_C2(NdotV2, a2); - T L_v = beckmann_Lambda(c2); - c2 = beckmann_C2(NdotL2, a2); - T L_l = beckmann_Lambda(c2); - return G1(L_v + L_l); -} + static this_t create(T ax2, T ay2, T NdotV, T TdotV2, T BdotV2, T NdotV2, T NdotL, T TdotL2, T BdotL2, T NdotL2) // ggx + { + this_t retval; + retval.ax2 = ax2; + retval.ay2 = ay2; + retval.NdotL = NdotL; + retval.NdotV = NdotV; + retval.TdotV2 = TdotV2; + retval.BdotV2 = BdotV2; + retval.NdotV2 = NdotV2; + retval.TdotL2 = TdotL2; + retval.BdotL2 = BdotL2; + retval.NdotL2 = NdotL2; + return this_t; + } -template) -T beckmann_smith_correlated(T TdotV2, T BdotV2, T NdotV2, T TdotL2, T BdotL2, T NdotL2, T ax2, T ay2) -{ - T c2 = beckmann_C2(TdotV2, BdotV2, NdotV2, ax2, ay2); - T L_v = beckmann_Lambda(c2); - c2 = beckmann_C2(TdotL2, BdotL2, NdotL2, ax2, ay2); - T L_l = beckmann_Lambda(c2); - return G1(L_v + L_l); -} + T ax2; + T ay2; + T NdotV; + T NdotL; + T TdotV2; + T BdotV2; + T NdotV2; + T TdotL2; + T BdotL2; + T NdotL2; + T lambdaV_plus_one; +}; -template) -T beckmann_smith_G2_over_G1(T lambdaV_plus_one, T NdotL2, T a2) -{ - T lambdaL = beckmann_Lambda(NdotL2, a2); - return lambdaV_plus_one / (lambdaV_plus_one+lambdaL); -} -template) -T beckmann_smith_G2_over_G1(T lambdaV_plus_one, T TdotL2, T BdotL2, T NdotL2, T ax2, T ay2) +// beckmann +template) +struct Beckmann { - T c2 = beckmann_C2(TdotL2, BdotL2, NdotL2, ax2, ay2); - T lambdaL = beckmann_Lambda(c2); - return lambdaV_plus_one / (lambdaV_plus_one + lambdaL); -} + using scalar_type = T; + scalar_type C2(scalar_type NdotX2, scalar_type a2) + { + return NdotX2 / (a2 * (1.0 - NdotX2)); + } -// ggx -template) -T ggx_devsh_part(T NdotX2, T a2, T one_minus_a2) -{ - return sqrt(a2 + one_minus_a2 * NdotX2); -} + scalar_type C2(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2, scalar_type ax2, scalar_type ay2) + { + return NdotX2 / (TdotX2 * ax2 + BdotX2 * ay2); + } -template) -T ggx_devsh_part(T TdotX2, T BdotX2, T NdotX2, T ax2, T ay2) -{ - return sqrt(TdotX2 * ax2 + BdotX2 * ay2 + NdotX2); -} + scalar_type Lambda(scalar_type c2) + { + scalar_type c = sqrt(c2); + scalar_type nom = 1.0 - 1.259 * c + 0.396 * c2; + scalar_type denom = 2.181 * c2 + 3.535 * c; + return lerp(0.0, nom / denom, c < 1.6); + } -template) -T ggx_G1_wo_numerator(T NdotX, T NdotX2, T a2, T one_minus_a2) -{ - return 1.0 / (NdotX + ggx_devsh_part(NdotX2,a2,one_minus_a2)); -} + scalar_type Lambda(scalar_type NdotX2, scalar_type a2) + { + return Lambda(C2(NdotX2, a2)); + } -template) -T ggx_G1_wo_numerator(T NdotX, T TdotX2, T BdotX2, T NdotX2, T ax2, T ay2) -{ - return 1.0 / (NdotX + ggx_devsh_part(TdotX2, BdotX2, NdotX2, ax2, ay2)); -} + scalar_type Lambda(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2, scalar_type ax2, scalar_type ay2) + { + return Lambda(C2(TdotX2, BdotX2, NdotX2, ax2, ay2)); + } -template) -T ggx_G1_wo_numerator(T NdotX, T devsh_part) -{ - return 1.0 / (NdotX + devsh_part); -} + scalar_type smith_correlated(SIsotropicParams params) + { + scalar_type c2 = C2(params.NdotV2, params.a2); + scalar_type L_v = Lambda(c2); + c2 = C2(params.NdotL2, params.a2); + scalar_type L_l = Lambda(c2); + return G1(L_v + L_l); + } -template) -T ggx_correlated_wo_numerator(T NdotV, T NdotV2, T NdotL, T NdotL2, T a2, T one_minus_a2) -{ - T Vterm = NdotL * ggx_devsh_part(NdotV2,a2,one_minus_a2); - T Lterm = NdotV * ggx_devsh_part(NdotL2,a2,one_minus_a2); - return 0.5 / (Vterm + Lterm); -} + scalar_type smith_correlated(SAnisotropicParams params) + { + scalar_type c2 = C2(params.TdotV2, params.BdotV2, params.NdotV2, params.ax2, params.ay2); + scalar_type L_v = Lambda(c2); + c2 = C2(params.TdotL2, params.BdotL2, params.NdotL2, params.ax2, params.ay2); + scalar_type L_l = Lambda(c2); + return G1(L_v + L_l); + } -template) -T ggx_correlated_wo_numerator(T NdotV, T NdotV2, T NdotL, T NdotL2, T a2) -{ - return ggx_correlated_wo_numerator(NdotV,NdotV2,NdotL,NdotL2,a2,1.0 - a2); -} + scalar_type smith_G2_over_G1(SIsotropicParams params) + { + scalar_type lambdaL = Lambda(params.NdotL2, params.a2); + return params.lambdaV_plus_one / (params.lambdaV_plus_one + lambdaL); + } -template) -T ggx_correlated_wo_numerator(T NdotV, T TdotV2, T BdotV2, T NdotV2, T NdotL, T TdotL2, T BdotL2, T NdotL2, T ax2, T ay2) -{ - T Vterm = NdotL * ggx_devsh_part(TdotV2,BdotV2,NdotV2,ax2,ay2); - T Lterm = NdotV * ggx_devsh_part(TdotL2,BdotL2,NdotL2,ax2,ay2); - return 0.5 / (Vterm + Lterm); -} + scalar_type smith_G2_over_G1(SAnisotropicParams params) + { + scalar_type c2 = C2(params.TdotL2, params.BdotL2, params.NdotL2, params.ax2, params.ay2); + scalar_type lambdaL = Lambda(c2); + return params.lambdaV_plus_one / (params.lambdaV_plus_one + lambdaL); + } +}; -template) -T ggx_G2_over_G1(T NdotL, T NdotL2, T NdotV, T NdotV2, T a2, T one_minus_a2) + +// ggx +template) +struct GGX { - T devsh_v = ggx_devsh_part(NdotV2,a2,one_minus_a2); - T G2_over_G1 = NdotL*(devsh_v + NdotV); // alternative `Vterm+NdotL*NdotV /// NdotL*NdotV could come as a parameter - G2_over_G1 /= NdotV*ggx_devsh_part(NdotL2,a2,one_minus_a2) + NdotL*devsh_v; + using scalar_type = T; - return G2_over_G1; -} + scalar_type devsh_part(scalar_type NdotX2, scalar_type a2, scalar_type one_minus_a2) + { + return sqrt(a2 + one_minus_a2 * NdotX2); + } -template) -T ggx_G2_over_G1_devsh(T NdotL, T NdotL2, T NdotV, T devsh_v, T a2, T one_minus_a2) -{ - T G2_over_G1 = NdotL*(devsh_v + NdotV); // alternative `Vterm+NdotL*NdotV /// NdotL*NdotV could come as a parameter - G2_over_G1 /= NdotV*ggx_devsh_part(NdotL2,a2,one_minus_a2) + NdotL*devsh_v; + scalar_type devsh_part(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2, scalar_type ax2, scalar_type ay2) + { + return sqrt(TdotX2 * ax2 + BdotX2 * ay2 + NdotX2); + } - return G2_over_G1; -} + scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type NdotX2, scalar_type a2, scalar_type one_minus_a2) + { + return 1.0 / (NdotX + ggx_devsh_part(NdotX2,a2,one_minus_a2)); + } -template) -T ggx_G2_over_G1(T NdotL, T TdotL2, T BdotL2, T NdotL2, T NdotV, T TdotV2, T BdotV2, T NdotV2, T ax2, T ay2) -{ - T devsh_v = ggx_devsh_part(TdotV2,BdotV2,NdotV2,ax2,ay2); - T G2_over_G1 = NdotL*(devsh_v + NdotV); - G2_over_G1 /= NdotV*ggx_devsh_part(TdotL2,BdotL2,NdotL2,ax2,ay2) + NdotL*devsh_v; + scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2, scalar_type ax2, scalar_type ay2) + { + return 1.0 / (NdotX + ggx_devsh_part(TdotX2, BdotX2, NdotX2, ax2, ay2)); + } - return G2_over_G1; -} + scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type devsh_part) + { + return 1.0 / (NdotX + devsh_part); + } -template) -T ggx_G2_over_G1_devsh(T NdotL, T TdotL2, T BdotL2, T NdotL2, T NdotV, T devsh_v, T ax2, T ay2) -{ - T G2_over_G1 = NdotL*(devsh_v + NdotV); - G2_over_G1 /= NdotV*ggx_devsh_part(TdotL2,BdotL2,NdotL2,ax2,ay2) + NdotL*devsh_v; + scalar_type correlated_wo_numerator(SIsotropicParams params) + { + scalar_type Vterm = params.NdotL * devsh_part(params.NdotV2, params.a2, params.one_minus_a2); + scalar_type Lterm = params.NdotV * devsh_part(params.NdotL2, params.a2, params.one_minus_a2); + return 0.5 / (Vterm + Lterm); + } - return G2_over_G1; -} + scalar_type correlated_wo_numerator(SAnisotropicParams params) + { + scalar_type Vterm = params.NdotL * devsh_part(params.TdotV2, params.BdotV2, params.NdotV2, params.ax2, params.ay2); + scalar_type Lterm = params.NdotV * devsh_part(params.TdotL2, params.BdotL2, params.NdotL2, params.ax2, params.ay2); + return 0.5 / (Vterm + Lterm); + } + + scalar_type G2_over_G1(SIsotropicParams params) + { + scalar_type devsh_v = devsh_part(params.NdotV2, params.a2, params.one_minus_a2); + scalar_type G2_over_G1 = params.NdotL * (devsh_v + params.NdotV); // alternative `Vterm+NdotL*NdotV /// NdotL*NdotV could come as a parameter + G2_over_G1 /= params.NdotV * devsh_part(params.NdotL2, params.a2, params.one_minus_a2) + params.NdotL * devsh_v; + + return G2_over_G1; + } + + scalar_type G2_over_G1(SAnisotropicParams params) + { + scalar_type devsh_v = devsh_part(params.TdotV2, params.BdotV2, params.NdotV2, params.ax2, params.ay2); + scalar_type G2_over_G1 = params.NdotL * (devsh_v + params.NdotV); + G2_over_G1 /= params.NdotV * devsh_part(params.TdotL2, params.BdotL2, params.NdotL2, params.ax2, params.ay2) + params.NdotL * devsh_v; + + return G2_over_G1; + } + +}; } } diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl index ab9cacf5a7..164df50532 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -114,7 +114,7 @@ struct SAnisotropicParams }; -template) +template) struct BlinnPhong { using scalar_type = T; @@ -135,7 +135,7 @@ struct BlinnPhong } }; -template) +template) struct Beckmann { using scalar_type = T; @@ -156,7 +156,7 @@ struct Beckmann }; -template) +template) struct GGX { using scalar_type = T; @@ -218,7 +218,7 @@ template struct microfacet_to_light_measure_transform { using this_t = microfacet_to_light_measure_transform; - using scalar_type = NDF::scalar_type; + using scalar_type = typename NDF::scalar_type; static this_t create(scalar_type NDFcos, scalar_type maxNdotV) { @@ -248,7 +248,7 @@ template struct microfacet_to_light_measure_transform { using this_t = microfacet_to_light_measure_transform; - using scalar_type = NDF::scalar_type; + using scalar_type = typename NDF::scalar_type; static this_t create(scalar_type NDFcos, scalar_type absNdotV, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) { @@ -293,7 +293,7 @@ template struct microfacet_to_light_measure_transform { using this_t = microfacet_to_light_measure_transform; - using scalar_type = NDF::scalar_type; + using scalar_type = typename NDF::scalar_type; static this_t create(scalar_type NDFcos, scalar_type absNdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) { From 91ca79eff56a06f22318e2b5b9f3d5675c5a05b6 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 11 Dec 2024 11:21:02 +0700 Subject: [PATCH 023/188] adjusted BxDF concept, new impl BxDF structs --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 20 +- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 676 +++++++++--------- 2 files changed, 358 insertions(+), 338 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 80d5a06dbe..05e06afb69 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -728,7 +728,7 @@ typedef quotient_and_pdf, float32_t> quotient_and_pdf_rgb; #define NBL_CONCEPT_PARAM_3 (_sample, typename T::sample_type) #define NBL_CONCEPT_PARAM_4 (iso, typename T::isotropic_type) #define NBL_CONCEPT_PARAM_5 (aniso, typename T::anisotropic_type) -NBL_CONCEPT_BEGIN(8) +NBL_CONCEPT_BEGIN(9) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define spec NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define pdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 @@ -742,11 +742,12 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) ((NBL_CONCEPT_REQ_TYPE)(T::spectral_type)) ((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template generate(aniso,aniso.N)), ::nbl::hlsl::is_same_v, typename T::sample_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.eval(_sample,iso)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.generate(aniso,aniso.N)), ::nbl::hlsl::is_same_v, typename T::sample_type)) //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template pdf(_sample,iso)), ::nbl::hlsl::is_scalar_v)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template quotient_and_pdf(_sample,iso)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) -) && is_scalar_v(_sample,iso))> && Sample && - spectral_of && is_floating_point_v; + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.quotient_and_pdf(_sample,iso)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) +) && Sample && spectral_of && + surface_interactions::Isotropic && surface_interactions::Anisotropic; #undef aniso #undef iso #undef _sample @@ -766,7 +767,7 @@ NBL_CONCEPT_END( #define NBL_CONCEPT_PARAM_5 (aniso, typename T::anisotropic_type) #define NBL_CONCEPT_PARAM_6 (isocache, typename T::isocache_type) #define NBL_CONCEPT_PARAM_7 (anisocache, typename T::anisocache_type) -NBL_CONCEPT_BEGIN(1) +NBL_CONCEPT_BEGIN(10) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define spec NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define pdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 @@ -784,11 +785,12 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) ((NBL_CONCEPT_REQ_TYPE)(T::isocache_type)) ((NBL_CONCEPT_REQ_TYPE)(T::anisocache_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template generate(aniso,aniso.N,anisocache)), ::nbl::hlsl::is_same_v, typename T::sample_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.generate(_sample,iso,isocache)), ::nbl::hlsl::is_same_v, vector)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.generate(aniso,aniso.N,anisocache)), ::nbl::hlsl::is_same_v, typename T::sample_type)) //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template pdf(_sample,iso)), ::nbl::hlsl::is_scalar_v)) //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template quotient_and_pdf(_sample,iso)), ::nbl::hlsl::is_same_v, Q)) -) && is_scalar_v(_sample,iso,isocache))> && - Sample && spectral_of && is_floating_point_v; +) && Sample && spectral_of && + IsotropicMicrofacetCache && AnisotropicMicrofacetCache; #undef anisocache #undef isocache #undef aniso diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 70a626d0ed..3c46255521 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -18,14 +18,14 @@ namespace reflection { // still need these? -template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) +template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) LightSample cos_generate(NBL_CONST_REF_ARG(Iso) interaction) { return LightSample(interaction.V.reflect(interaction.N,interaction.NdotV),interaction.NdotV,interaction.N); } -template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) +template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) LightSample cos_generate(NBL_CONST_REF_ARG(Aniso) interaction) { return LightSample(interaction.V.reflect(interaction.N,interaction.NdotV),interaction.NdotV,interaction.T,interaction.B,interaction.N); @@ -43,169 +43,178 @@ quotient_and_pdf cos_quotient_and_pdf() // store them as well? -template) +template && surface_interactions::Isotropic && surface_interactions::Anisotropic) struct SLambertianBxDF { - static SLambertianBxDF create() + using scalar_type = typename LightSample::scalar_type; + using isotropic_type = Iso; + using anisotropic_type = Aniso; + using sample_type = LightSample; + using spectral_type = vector; // TODO: most likely change this + using quotient_pdf_type = quotient_and_pdf; + + static SLambertianBxDF create() { - SLambertianBxDF retval; + SLambertianBxDF retval; // nothing here, just keeping in convention with others return retval; } - Scalar __eval_pi_factored_out(Scalar maxNdotL) + scalar_type __eval_pi_factored_out(scalar_type maxNdotL) { return maxNdotL; } - template && surface_interactions::Isotropic) // maybe put template in struct vs function? - Scalar __eval_wo_clamps(LightSample _sample, Iso interaction) + scalar_type __eval_wo_clamps(sample_type _sample, isotropic_type interaction) { // probably doesn't need to use the param struct - return __eval_pi_factored_out(_sample.NdotL) * numbers::inv_pi; + return __eval_pi_factored_out(_sample.NdotL) * numbers::inv_pi; } - template && surface_interactions::Isotropic) // maybe put template in struct vs function? - Scalar eval(LightSample _sample, Iso interaction) + scalar_type eval(sample_type _sample, isotropic_type interaction) { // probably doesn't need to use the param struct - return __eval_pi_factored_out(max(_sample.NdotL, 0.0)) * numbers::inv_pi; + return __eval_pi_factored_out(max(_sample.NdotL, 0.0)) * numbers::inv_pi; } - template && surface_interactions::Anisotropic) - LightSample generate_wo_clamps(Aniso interaction, vector u) + sample_type generate_wo_clamps(anisotropic_type interaction, vector u) { - vector L = projected_hemisphere_generate(u); - return LightSample::createTangentSpace(interaction.getTangentSpaceV(), L, interaction.getTangentFrame()); + vector L = projected_hemisphere_generate(u); + return sample_type::createTangentSpace(interaction.getTangentSpaceV(), L, interaction.getTangentFrame()); } - template && surface_interactions::Anisotropic) - LightSample generate(Aniso interaction, vector u) + sample_type generate(anisotropic_type interaction, vector u) { - return generate_wo_clamps(interaction, u); + return generate_wo_clamps(interaction, u); } - template && surface_interactions::Isotropic) - Scalar pdf_wo_clamps(LightSample _sample, Iso interaction) + scalar_type pdf_wo_clamps(sample_type _sample, isotropic_type interaction) { - return projected_hemisphere_pdf(_sample.NdotL); + return projected_hemisphere_pdf(_sample.NdotL); } - template && surface_interactions::Isotropic) - Scalar pdf(LightSample _sample, Iso interaction) + scalar_type pdf(sample_type _sample, isotropic_type interaction) { - return projected_hemisphere_pdf(max(_sample.NdotL, 0.0)); + return projected_hemisphere_pdf(max(_sample.NdotL, 0.0)); } - template && Sample && surface_interactions::Anisotropic) - quotient_and_pdf quotient_and_pdf_wo_clamps(LightSample _sample, Iso interaction) + quotient_pdf_type quotient_and_pdf_wo_clamps(sample_type _sample, isotropic_type interaction) { - Scalar pdf; - Scalar q = projected_hemisphere_quotient_and_pdf(pdf, _sample.NdotL); - return quotient_and_pdf::create(SpectralBins(q), pdf); + scalar_type pdf; + scalar_type q = projected_hemisphere_quotient_and_pdf(pdf, _sample.NdotL); + return quotient_pdf_type::create(spectral_type(q,q,q), pdf); } - template && Sample && surface_interactions::Anisotropic) - quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction) + quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction) { - Scalar pdf; - Scalar q = projected_hemisphere_quotient_and_pdf(pdf, max(_sample.NdotL, 0.0)); - return quotient_and_pdf::create(SpectralBins(q), pdf); + scalar_type pdf; + scalar_type q = projected_hemisphere_quotient_and_pdf(pdf, max(_sample.NdotL, 0.0)); + return quotient_pdf_type::create(spectral_type(q,q,q), pdf); } }; -template) +template && surface_interactions::Isotropic && surface_interactions::Anisotropic) struct SOrenNayarBxDF { - using this_t = SOrenNayarBxDF; - using vector_t2 = vector; + using scalar_type = typename LightSample::scalar_type; + using vector2_type = vector; + + using this_t = SOrenNayarBxDF; + using isotropic_type = Iso; + using anisotropic_type = Aniso; + using sample_type = LightSample; + using spectral_type = vector; // TODO: most likely change this + using quotient_pdf_type = quotient_and_pdf; - static this_t create(Scalar A) + static this_t create(scalar_type A) { this_t retval; retval.A = A; return retval; } - Scalar __rec_pi_factored_out_wo_clamps(Scalar VdotL, Scalar maxNdotL, Scalar maxNdotV) + scalar_type __rec_pi_factored_out_wo_clamps(scalar_type VdotL, scalar_type maxNdotL, scalar_type maxNdotV) { - Scalar A2 = A * 0.5; - vector_t2 AB = vector_t2(1.0, 0.0) + vector_t2(-0.5, 0.45) * vector_t2(A2, A2) / vector_t2(A2 + 0.33, A2 + 0.09); - Scalar C = 1.0 / max(maxNdotL, maxNdotV); + scalar_type A2 = A * 0.5; + vector2_type AB = vector2_type(1.0, 0.0) + vector2_type(-0.5, 0.45) * vector2_type(A2, A2) / vector2_type(A2 + 0.33, A2 + 0.09); + scalar_type C = 1.0 / max(maxNdotL, maxNdotV); - Scalar cos_phi_sin_theta = max(VdotL - maxNdotL * maxNdotV, 0.0); + scalar_type cos_phi_sin_theta = max(VdotL - maxNdotL * maxNdotV, 0.0); return (AB.x + AB.y * cos_phi_sin_theta * C); } - template && surface_interactions::Isotropic) // maybe put template in struct vs function? - Scalar __eval_wo_clamps(LightSample _sample, Iso interaction) + scalar_type __eval_wo_clamps(sample_type _sample, isotropic_type interaction) { - return maxNdotL * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(_sample.VdotL, _sample.NdotL, interaction.NdotV); + return maxNdotL * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(_sample.VdotL, _sample.NdotL, interaction.NdotV); } - template && surface_interactions::Isotropic) // maybe put template in struct vs function? - Scalar eval(LightSample _sample, Iso interaction) + scalar_type eval(sample_type _sample, isotropic_type interaction) { - return maxNdotL * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(_sample.VdotL, max(_sample.NdotL,0.0), max(interaction.NdotV,0.0)); + return maxNdotL * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(_sample.VdotL, max(_sample.NdotL,0.0), max(interaction.NdotV,0.0)); } - template && surface_interactions::Anisotropic) - LightSample generate_wo_clamps(Aniso interaction, vector u) + sample_type generate_wo_clamps(anisotropic_type interaction, vector2_type u) { - vector L = projected_hemisphere_generate(u); - return LightSample::createTangentSpace(interaction.getTangentSpaceV(), L, interaction.getTangentFrame()); + vector L = projected_hemisphere_generate(u); + return sample_type::createTangentSpace(interaction.getTangentSpaceV(), L, interaction.getTangentFrame()); } - template && surface_interactions::Anisotropic) - LightSample generate(Aniso interaction, vector u) + sample_type generate(anisotropic_type interaction, vector2_type u) { - return generate_wo_clamps(interaction, u); + return generate_wo_clamps(interaction, u); } - template && surface_interactions::Isotropic) - Scalar pdf_wo_clamps(LightSample _sample, Iso interaction) + scalar_type pdf_wo_clamps(sample_type _sample, isotropic_type interaction) { - return projected_hemisphere_pdf(_sample.NdotL, 0.0); + return projected_hemisphere_pdf(_sample.NdotL, 0.0); } - template && surface_interactions::Isotropic) - Scalar pdf(LightSample _sample, Iso interaction) + scalar_type pdf(sample_type _sample, isotropic_type interaction) { - return projected_hemisphere_pdf(max(_sample.NdotL, 0.0)); + return projected_hemisphere_pdf(max(_sample.NdotL, 0.0)); } // pdf type same as scalar? - template && Sample && surface_interactions::Anisotropic) - quotient_and_pdf quotient_and_pdf_wo_clamps(LightSample _sample, Iso interaction) + quotient_pdf_type quotient_and_pdf_wo_clamps(sample_type _sample, isotropic_type interaction) { - Scalar pdf; - projected_hemisphere_quotient_and_pdf(pdf, _sample.NdotL); - Scalar q = __rec_pi_factored_out_wo_clamps(_sample.VdotL, _sample.NdotL, interaction.NdotV); - return quotient_and_pdf::create(SpectralBins(q), pdf); + scalar_type pdf; + projected_hemisphere_quotient_and_pdf(pdf, _sample.NdotL); + scalar_type q = __rec_pi_factored_out_wo_clamps(_sample.VdotL, _sample.NdotL, interaction.NdotV); + return quotient_pdf_type::create(spectral_type(q), pdf); } - template && Sample && surface_interactions::Anisotropic) - quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction) + quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction) { - Scalar pdf; - projected_hemisphere_quotient_and_pdf(pdf, max(_sample.NdotL, 0.0)); - Scalar q = __rec_pi_factored_out_wo_clamps(_sample.VdotL, max(_sample.NdotL,0.0), max(interaction.NdotV,0.0)); - return quotient_and_pdf::create(SpectralBins(q), pdf); + scalar_type pdf; + projected_hemisphere_quotient_and_pdf(pdf, max(_sample.NdotL, 0.0)); + scalar_type q = __rec_pi_factored_out_wo_clamps(_sample.VdotL, max(_sample.NdotL,0.0), max(interaction.NdotV,0.0)); + return quotient_pdf_type::create(spectral_type(q), pdf); } - Scalar A; + scalar_type A; }; -template) +template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SBlinnPhongBxDF { - using this_t = SBlinnPhongBxDF; - using vector_t2 = vector; - using vector_t3 = vector; - using params_t = SBxDFParams; - - static this_t create(vector_t2 n, matrix ior) + using scalar_type = typename LightSample::scalar_type + using vector2_type = vector; + using vector3_type = vector; + using matrix2x3_type = matrix; + + using this_t = SBlinnPhongBxDF; + using params_t = SBxDFParams; + + using isotropic_type = typename IsoCache::isotropic_type; + using anisotropic_type = typename AnisoCache::anisotropic_type + using sample_type = LightSample; + using spectral_type = vector; // TODO: most likely change this + using quotient_pdf_type = quotient_and_pdf; + using isocache_type = IsoCache; + using anisocache_type = AnisoCache; + + static this_t create(vector2_type n, matrix2x3_type ior) { this_t retval; retval.n = n; @@ -226,200 +235,209 @@ struct SBlinnPhongBxDF } template // this or specialize? - Scalar __eval_DG_wo_clamps(params_t params, vector_t2 a2) + scalar_type __eval_DG_wo_clamps(params_t params, vector2_type a2) { if (aniso) { - Scalar DG = ndf::blinn_phong(params.NdotH, 1.0 / (1.0 - params.NdotH2), params.TdotH2, params.BdotH2, n.x, n.y); - if (any(a2 > numeric_limits::min)) - DG *= smith::beckmann_smith_correlated(params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, a2.x, a2.y); + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(params.NdotH, 1.0 / (1.0 - params.NdotH2), params.TdotH2, params.BdotH2, n.x, n.y); + ndf::BlinnPhong blinn_phong; + scalar_type DG = blinn_phong(ndfparams); + if (any(a2 > numeric_limits::min)) + { + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(a2.x, a2.y, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, 0); + smith::Beckmann beckmann; + DG *= beckmann.smith_correlated(smithparams); + } return DG; } else { - Scalar NG = ndf::blinn_phong(params.NdotH, n); - if (any(a2 > numeric_limits::min)) - NG *= smith::beckmann_smith_correlated(params.NdotV2, params.NdotL2, a2.x); + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(params.NdotH, n); + ndf::BlinnPhong blinn_phong; + scalar_type NG = blinn_phong(ndfparams); + if (any(a2 > numeric_limits::min)) + { + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2.x, params.NdotV2, params.NdotL2, 0); + smith::Beckmann beckmann; + NG *= beckmann.smith_correlated(smithparams); + } return NG; } } template - vector_t3 __eval_wo_clamps(params_t params) + vector3_type __eval_wo_clamps(params_t params) { - Scalar scalar_part; + scalar_type scalar_part; if (aniso) { - vector_t2 a2 = phong_exp_to_alpha2(n); + vector2_type a2 = phong_exp_to_alpha2(n); scalar_part = __eval_DG_wo_clamps(params, a2); } else { - vector_t2 a2 = (vector_t2)phong_exp_to_alpha2(n); + vector2_type a2 = (vector2_type)phong_exp_to_alpha2(n); scalar_part = __eval_DG_wo_clamps(params, a2); } - return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_to_light_measure_transform(scalar_part, params.NdotV); + return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_to_light_measure_transform(scalar_part, params.NdotV); } - template && surface_interactions::Isotropic && IsotropicMicrofacetCache) // maybe put template in struct vs function? - vector_t3 eval(LightSample _sample, Iso interaction, Cache cache) + vector3_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) { - if (interaction.NdotV > numeric_limits::min) + if (interaction.NdotV > numeric_limits::min) { - params_t params = params_t::template create(_sample, interaction, cache); + params_t params = params_t::template create(_sample, interaction, cache); return __eval_wo_clamps(params); } else - return (vector_t3)0.0; + return (vector3_type)0.0; } - template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) // maybe put template in struct vs function? - vector_t3 eval(LightSample _sample, Aniso interaction, Cache cache) + vector3_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) { - if (interaction.NdotV > numeric_limits::min) + if (interaction.NdotV > numeric_limits::min) { - params_t params = params_t::template create(_sample, interaction, cache); + params_t params = params_t::template create(_sample, interaction, cache); return __eval_wo_clamps(params); } else - return (vector_t3)0.0; + return (vector3_type)0.0; } - vector_t3 generate(vector u, Scalar n) + vector3_type generate(vector2_type u, scalar_type n) { - Scalar phi = 2.0 * numbers::pi; * u.y; - Scalar cosTheta = pow(u.x, 1.0/(n+1.0)); - Scalar sinTheta = sqrt(1.0 - cosTheta * cosTheta); - Scalar cosPhi = cos(phi); - Scalar sinPhi = sin(phi); - return vector_t3(cosPhi * sinTheta, sinPhi * sinTheta, cosTheta); + scalar_type phi = 2.0 * numbers::pi; * u.y; + scalar_type cosTheta = pow(u.x, 1.0/(n+1.0)); + scalar_type sinTheta = sqrt(1.0 - cosTheta * cosTheta); + scalar_type cosPhi = cos(phi); + scalar_type sinPhi = sin(phi); + return vector3_type(cosPhi * sinTheta, sinPhi * sinTheta, cosTheta); } - template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - LightSample generate(Aniso interaction, vector u, out Cache cache) + sample_type generate(anisotropic_type interaction, vector2_type u, out anisocache_type cache) { - const vector_t3 H = generate(u, n.x); - const vector_t3 localV = interaction.getTangentSpaceV(); + const vector3_type H = generate(u, n.x); + const vector3_type localV = interaction.getTangentSpaceV(); - cache = Aniso::create(localV, H); - vector_t3 localL = math::reflect(localV, H, cache.VdotH); + cache = anisocache_type::create(localV, H); + vector3_type localL = math::reflect(localV, H, cache.VdotH); - return LightSample::createTangentSpace(localV, localL, interaction.getTangentFrame()); + return sample_type::createTangentSpace(localV, localL, interaction.getTangentFrame()); } // where pdf? - vector_t2 n; - matrix ior; + vector2_type n; + matrix2x3_type ior; }; -template) +template) struct SBeckmannBxDF { - using this_t = SBeckmannBxDF; - using vector_t2 = vector; - using vector_t3 = vector; - using params_t = SBxDFParams; + using this_t = SBeckmannBxDF; + using vector2_type = vector; + using vector3_type = vector; + using params_t = SBxDFParams; // iso - static this_t create(Scalar A,matrix ior) + static this_t create(scalar_type A,matrix ior) { this_t retval; - retval.A = vector_t2(A,A); + retval.A = vector2_type(A,A); retval.ior = ior; return retval; } // aniso - static this_t create(Scalar ax,Scalar ay,matrix ior) + static this_t create(scalar_type ax,scalar_type ay,matrix ior) { this_t retval; - retval.A = vector_t2(ax,ay); + retval.A = vector2_type(ax,ay); retval.ior = ior; return retval; } template // this or specialize? - Scalar __eval_DG_wo_clamps(params_t params) + scalar_type __eval_DG_wo_clamps(params_t params) { if (aniso) { - const Scalar ax2 = A.x*A.x; - const Scalar ay2 = A.y*A.y; - Scalar NG = ndf::beckmann(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); - if (any(A > numeric_limits::min)) - NG *= smith::beckmann_smith_correlated(params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, ax2, ay2); + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; + scalar_type NG = ndf::beckmann(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + if (any(A > numeric_limits::min)) + NG *= smith::beckmann_smith_correlated(params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, ax2, ay2); return NG; } else { - Scalar a2 = A.x*A.x; - Scalar NG = ndf::beckmann(a2, params.NdotH2); - if (a2 > numeric_limits::min) - NG *= smith::beckmann_smith_correlated(params.NdotV2, params.NdotL2, a2.x); + scalar_type a2 = A.x*A.x; + scalar_type NG = ndf::beckmann(a2, params.NdotH2); + if (a2 > numeric_limits::min) + NG *= smith::beckmann_smith_correlated(params.NdotV2, params.NdotL2, a2.x); return NG; } } template - vector_t3 __eval_wo_clamps(params_t params) + vector3_type __eval_wo_clamps(params_t params) { - Scalar scalar_part = __eval_DG_wo_clamps(params); - return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_to_light_measure_transform(scalar_part, params.NdotV); + scalar_type scalar_part = __eval_DG_wo_clamps(params); + return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_to_light_measure_transform(scalar_part, params.NdotV); } template && surface_interactions::Isotropic && IsotropicMicrofacetCache) // maybe put template in struct vs function? - vector_t3 eval(LightSample _sample, Iso interaction, Cache cache) + vector3_type eval(LightSample _sample, Iso interaction, Cache cache) { - if (interaction.NdotV > numeric_limits::min) + if (interaction.NdotV > numeric_limits::min) { params_t params = params_t::template create(_sample, interaction, cache); return __eval_wo_clamps(params); } else - return (vector_t3)0.0; + return (vector3_type)0.0; } template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) // maybe put template in struct vs function? - vector_t3 eval(LightSample _sample, Aniso interaction, Cache cache) + vector3_type eval(LightSample _sample, Aniso interaction, Cache cache) { - if (interaction.NdotV > numeric_limits::min) + if (interaction.NdotV > numeric_limits::min) { params_t params = params_t::template create(_sample, interaction, cache); return __eval_wo_clamps(params); } else - return (vector_t3)0.0; + return (vector3_type)0.0; } - vector_t3 __generate(vector_t3 localV, vector_t2 u) + vector3_type __generate(vector3_type localV, vector2_type u) { //stretch - vector_t3 V = normalize(vector_t3(A.x * localV.x, A.y * localV.y, localV.z)); + vector3_type V = normalize(vector3_type(A.x * localV.x, A.y * localV.y, localV.z)); - vector_t2 slope; + vector2_type slope; if (V.z > 0.9999)//V.z=NdotV=cosTheta in tangent space { - Scalar r = sqrt(-log(1.0 - u.x)); - Scalar sinPhi = sin(2.0 * numbers::pi * u.y); - Scalar cosPhi = cos(2.0 * numbers::pi * u.y); - slope = (vector_t2)r * vector_t2(cosPhi,sinPhi); + scalar_type r = sqrt(-log(1.0 - u.x)); + scalar_type sinPhi = sin(2.0 * numbers::pi * u.y); + scalar_type cosPhi = cos(2.0 * numbers::pi * u.y); + slope = (vector2_type)r * vector2_type(cosPhi,sinPhi); } else { - Scalar cosTheta = V.z; - Scalar sinTheta = sqrt(1.0 - cosTheta * cosTheta); - Scalar tanTheta = sinTheta / cosTheta; - Scalar cotTheta = 1.0 / tanTheta; + scalar_type cosTheta = V.z; + scalar_type sinTheta = sqrt(1.0 - cosTheta * cosTheta); + scalar_type tanTheta = sinTheta / cosTheta; + scalar_type cotTheta = 1.0 / tanTheta; - Scalar a = -1.0; - Scalar c = math::erf(cosTheta); - Scalar sample_x = max(u.x, 1.0e-6); - Scalar theta = acos(cosTheta); - Scalar fit = 1.0 + theta * (-0.876 + theta * (0.4265 - 0.0594*theta)); - Scalar b = c - (1.0 + c) * pow(1.0-sample_x, fit); + scalar_type a = -1.0; + scalar_type c = math::erf(cosTheta); + scalar_type sample_x = max(u.x, 1.0e-6); + scalar_type theta = acos(cosTheta); + scalar_type fit = 1.0 + theta * (-0.876 + theta * (0.4265 - 0.0594*theta)); + scalar_type b = c - (1.0 + c) * pow(1.0-sample_x, fit); - Scalar normalization = 1.0 / (1.0 + c + numbers::inv_sqrtpi * tanTheta * exp(-cosTheta*cosTheta)); + scalar_type normalization = 1.0 / (1.0 + c + numbers::inv_sqrtpi * tanTheta * exp(-cosTheta*cosTheta)); const int ITER_THRESHOLD = 10; const float MAX_ACCEPTABLE_ERR = 1.0e-5; @@ -430,8 +448,8 @@ struct SBeckmannBxDF if (!(b>=a && b<=c)) b = 0.5 * (a+c); - float invErf = math::erfInv(b); - value = normalization * (1.0 + b + numbers::inv_sqrtpi * tanTheta * exp(-invErf*invErf)) - sample_x; + float invErf = math::erfInv(b); + value = normalization * (1.0 + b + numbers::inv_sqrtpi * tanTheta * exp(-invErf*invErf)) - sample_x; float derivative = normalization * (1.0 - invErf*cosTheta); if (value > 0.0) @@ -442,319 +460,319 @@ struct SBeckmannBxDF b -= value/derivative; } // TODO: investigate if we can replace these two erf^-1 calls with a box muller transform - slope.x = math::erfInv(b); - slope.y = math::erfInv(2.0 * max(u.y,1.0e-6) - 1.0); + slope.x = math::erfInv(b); + slope.y = math::erfInv(2.0 * max(u.y,1.0e-6) - 1.0); } - Scalar sinTheta = sqrt(1.0 - V.z*V.z); - Scalar cosPhi = sinTheta==0.0 ? 1.0 : clamp(V.x/sinTheta, -1.0, 1.0); - Scalar sinPhi = sinTheta==0.0 ? 0.0 : clamp(V.y/sinTheta, -1.0, 1.0); + scalar_type sinTheta = sqrt(1.0 - V.z*V.z); + scalar_type cosPhi = sinTheta==0.0 ? 1.0 : clamp(V.x/sinTheta, -1.0, 1.0); + scalar_type sinPhi = sinTheta==0.0 ? 0.0 : clamp(V.y/sinTheta, -1.0, 1.0); //rotate - Scalar tmp = cosPhi*slope.x - sinPhi*slope.y; + scalar_type tmp = cosPhi*slope.x - sinPhi*slope.y; slope.y = sinPhi*slope.x + cosPhi*slope.y; slope.x = tmp; //unstretch - slope = vector_t2(ax,ay)*slope; + slope = vector2_type(ax,ay)*slope; - return normalize(vector_t3(-slope, 1.0)); + return normalize(vector3_type(-slope, 1.0)); } template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - LightSample generate(Aniso interaction, vector u, out Cache cache) + LightSample generate(Aniso interaction, vector u, out Cache cache) { - const vector_t3 localV = interaction.getTangentSpaceV(); - const vector_t3 H = __generate(localV, u); + const vector3_type localV = interaction.getTangentSpaceV(); + const vector3_type H = __generate(localV, u); - cache = Aniso::create(localV, H); - vector_t3 localL = math::reflect(localV, H, cache.VdotH); + cache = Aniso::create(localV, H); + vector3_type localL = math::reflect(localV, H, cache.VdotH); return LightSample::createTangentSpace(localV, localL, interaction.getTangentFrame()); } template && surface_interactions::Isotropic && IsotropicMicrofacetCache) - Scalar pdf(LightSample _sample, Iso interaction, Cache cache) + scalar_type pdf(LightSample _sample, Iso interaction, Cache cache) { - Scalar NdotH2 = cache.NdotH2; - Scalar ndf = ndf::beckmann(A.x*A.x, NdotH2); + scalar_type NdotH2 = cache.NdotH2; + scalar_type ndf = ndf::beckmann(A.x*A.x, NdotH2); - const Scalar lambda = smith::beckmann_Lambda(interaction.NdotV2, A.x*A.x); - Scalar dummy; - return smith::VNDF_pdf_wo_clamps(ndf, lambda, interaction.NdotV, dummy); + const scalar_type lambda = smith::beckmann_Lambda(interaction.NdotV2, A.x*A.x); + scalar_type dummy; + return smith::VNDF_pdf_wo_clamps(ndf, lambda, interaction.NdotV, dummy); } template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - Scalar pdf(LightSample _sample, Aniso interaction, Cache cache) + scalar_type pdf(LightSample _sample, Aniso interaction, Cache cache) { - Scalar NdotH2 = cache.NdotH2; - Scalar ndf = ndf::beckmann(A.x, A.y, A.x*A.x, A.y*A.y, cache.TdotH * cache.TdotH, cache.BdotH * cache.BdotH, NdotH2); + scalar_type NdotH2 = cache.NdotH2; + scalar_type ndf = ndf::beckmann(A.x, A.y, A.x*A.x, A.y*A.y, cache.TdotH * cache.TdotH, cache.BdotH * cache.BdotH, NdotH2); - const Scalar c2 = smith::beckmann_C2(interaction.TdotV * interaction.TdotV, interaction.BdotV * interaction.BdotV, interaction.NdotV2, A.x, A.y); - Scalar lambda = smith::beckmann_Lambda(c2); - Scalar dummy; - return smith::VNDF_pdf_wo_clamps(ndf, lambda, interaction.NdotV, dummy); + const scalar_type c2 = smith::beckmann_C2(interaction.TdotV * interaction.TdotV, interaction.BdotV * interaction.BdotV, interaction.NdotV2, A.x, A.y); + scalar_type lambda = smith::beckmann_Lambda(c2); + scalar_type dummy; + return smith::VNDF_pdf_wo_clamps(ndf, lambda, interaction.NdotV, dummy); } - template && Sample && surface_interactions::Isotropic && IsotropicMicrofacetCache) - quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction, Cache cache) + template && Sample && surface_interactions::Isotropic && IsotropicMicrofacetCache) + quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction, Cache cache) { - const Scalar ndf = ndf::beckmann(A.x*A.x, cache.NdotH2); - const Scalar lambda = smith::beckmann_Lambda(interaction.NdotV2, A.x*A.x); + const scalar_type ndf = ndf::beckmann(A.x*A.x, cache.NdotH2); + const scalar_type lambda = smith::beckmann_Lambda(interaction.NdotV2, A.x*A.x); - Scalar onePlusLambda_V; - Scalar pdf = smith::VNDF_pdf_wo_clamps(ndf, lambda, interaction.NdotV, onePlusLambda_V); - vector_t3 quo = (vector_t3)0.0; - if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) + scalar_type onePlusLambda_V; + scalar_type pdf = smith::VNDF_pdf_wo_clamps(ndf, lambda, interaction.NdotV, onePlusLambda_V); + vector3_type quo = (vector3_type)0.0; + if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { - const vector_t3 reflectance = fresnelConductor(ior[0], ior[1], cache.VdotH); - Scalar G2_over_G1 = smith::beckmann_smith_G2_over_G1(onePlusLambda_V, _sample.NdotL2, a2); + const vector3_type reflectance = fresnelConductor(ior[0], ior[1], cache.VdotH); + scalar_type G2_over_G1 = smith::beckmann_smith_G2_over_G1(onePlusLambda_V, _sample.NdotL2, a2); quo = reflectance * G2_over_G1; } - return quotient_and_pdf::create(SpectralBins(quo), pdf); + return quotient_and_pdf::create(SpectralBins(quo), pdf); } - template && Sample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - quotient_and_pdf quotient_and_pdf(LightSample _sample, Aniso interaction, Cache cache) + template && Sample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + quotient_and_pdf quotient_and_pdf(LightSample _sample, Aniso interaction, Cache cache) { params_t params = params_t::template create(_sample, interaction, cache); - const Scalar ax2 = A.x*A.x; - const Scalar ay2 = A.y*A.y; - - const Scalar ndf = ndf::beckmann(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); - Scalar onePlusLambda_V; - const Scalar c2 = smith::beckmann_C2(params.TdotV2, params.BdotV2, params.NdotV2, A.x, A.y); - Scalar lambda = smith::beckmann_Lambda(c2); - Scalar pdf = smith::VNDF_pdf_wo_clamps(ndf, lambda, interaction.NdotV, onePlusLambda_V); - vector_t3 quo = (vector_t3)0.0; - if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; + + const scalar_type ndf = ndf::beckmann(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + scalar_type onePlusLambda_V; + const scalar_type c2 = smith::beckmann_C2(params.TdotV2, params.BdotV2, params.NdotV2, A.x, A.y); + scalar_type lambda = smith::beckmann_Lambda(c2); + scalar_type pdf = smith::VNDF_pdf_wo_clamps(ndf, lambda, interaction.NdotV, onePlusLambda_V); + vector3_type quo = (vector3_type)0.0; + if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { - const vector_t3 reflectance = fresnel_conductor(ior[0], ior[1], cache.VdotH); - Scalar G2_over_G1 = smith::beckmann_smith_G2_over_G1(onePlusLambda_V, params.TdotL2, params.BdotL2, params.NdotL2, A.x, A.y); + const vector3_type reflectance = fresnel_conductor(ior[0], ior[1], cache.VdotH); + scalar_type G2_over_G1 = smith::beckmann_smith_G2_over_G1(onePlusLambda_V, params.TdotL2, params.BdotL2, params.NdotL2, A.x, A.y); quo = reflectance * G2_over_G1; } - return quotient_and_pdf::create(SpectralBins(quo), pdf); + return quotient_and_pdf::create(SpectralBins(quo), pdf); } - vector_t2 A; - matrix ior; + vector2_type A; + matrix ior; }; -template) +template) struct SGGXBxDF { - using this_t = SGGXBxDF; - using vector_t2 = vector; - using vector_t3 = vector; - using params_t = SBxDFParams; + using this_t = SGGXBxDF; + using vector2_type = vector; + using vector3_type = vector; + using params_t = SBxDFParams; // iso - static this_t create(Scalar A,matrix ior) + static this_t create(scalar_type A,matrix ior) { this_t retval; - retval.A = vector_t2(A,A); + retval.A = vector2_type(A,A); retval.ior = ior; return retval; } // aniso - static this_t create(Scalar ax,Scalar ay,matrix ior) + static this_t create(scalar_type ax,scalar_type ay,matrix ior) { this_t retval; - retval.A = vector_t2(ax,ay); + retval.A = vector2_type(ax,ay); retval.ior = ior; return retval; } template // this or specialize? - Scalar __eval_DG_wo_clamps(params_t params) + scalar_type __eval_DG_wo_clamps(params_t params) { if (aniso) { - const Scalar ax2 = A.x*A.x; - const Scalar ay2 = A.y*A.y; - Scalar NG = ndf::ggx_aniso(params.TdotH2, params.BdotH2, params.NdotH2, A.x, A.y, ax2, ay2); - if (any(A > numeric_limits::min)) - NG *= smith::ggx_correlated_wo_numerator(params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2, ax2, ay2); + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; + scalar_type NG = ndf::ggx_aniso(params.TdotH2, params.BdotH2, params.NdotH2, A.x, A.y, ax2, ay2); + if (any(A > numeric_limits::min)) + NG *= smith::ggx_correlated_wo_numerator(params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2, ax2, ay2); return NG; } else { - Scalar a2 = A.x*A.x; - Scalar NG = ndf::ggx_trowbridge_reitz(a2, params.NdotH2); - if (a2 > numeric_limits::min) - NG *= smith::ggx_correlated_wo_numerator(max(params.NdotV,0.0), params.NdotV2, max(params.NdotL,0.0), params.NdotL2, a2); + scalar_type a2 = A.x*A.x; + scalar_type NG = ndf::ggx_trowbridge_reitz(a2, params.NdotH2); + if (a2 > numeric_limits::min) + NG *= smith::ggx_correlated_wo_numerator(max(params.NdotV,0.0), params.NdotV2, max(params.NdotL,0.0), params.NdotL2, a2); return NG; } } template - vector_t3 __eval_wo_clamps(params_t params) + vector3_type __eval_wo_clamps(params_t params) { - Scalar scalar_part = __eval_DG_wo_clamps(params); - return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_to_light_measure_transform(scalar_part, params.NdotL); + scalar_type scalar_part = __eval_DG_wo_clamps(params); + return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_to_light_measure_transform(scalar_part, params.NdotL); } template && surface_interactions::Isotropic && IsotropicMicrofacetCache) // maybe put template in struct vs function? - vector_t3 eval(LightSample _sample, Iso interaction, Cache cache) + vector3_type eval(LightSample _sample, Iso interaction, Cache cache) { - if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) + if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { params_t params = params_t::template create(_sample, interaction, cache); return __eval_wo_clamps(params); } else - return (vector_t3)0.0; + return (vector3_type)0.0; } template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) // maybe put template in struct vs function? - vector_t3 eval(LightSample _sample, Aniso interaction, Cache cache) + vector3_type eval(LightSample _sample, Aniso interaction, Cache cache) { - if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) + if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { params_t params = params_t::template create(_sample, interaction, cache); return __eval_wo_clamps(params); } else - return (vector_t3)0.0; + return (vector3_type)0.0; } - vector_t3 __generate(vector_t3 localV, vector_t2 u) + vector3_type __generate(vector3_type localV, vector2_type u) { - vector_t3 V = normalize(vector_t3(A.x*localV.x, A.y*localV.y, localV.z));//stretch view vector so that we're sampling as if roughness=1.0 + vector3_type V = normalize(vector3_type(A.x*localV.x, A.y*localV.y, localV.z));//stretch view vector so that we're sampling as if roughness=1.0 - Scalar lensq = V.x*V.x + V.y*V.y; - vector_t3 T1 = lensq > 0.0 ? vector_t3(-V.y, V.x, 0.0) * rsqrt(lensq) : vector_t3(1.0,0.0,0.0); - vector_t3 T2 = cross(V,T1); + scalar_type lensq = V.x*V.x + V.y*V.y; + vector3_type T1 = lensq > 0.0 ? vector3_type(-V.y, V.x, 0.0) * rsqrt(lensq) : vector3_type(1.0,0.0,0.0); + vector3_type T2 = cross(V,T1); - Scalar r = sqrt(u.x); - Scalar phi = 2.0 * nbl_glsl_PI * u.y; - Scalar t1 = r * cos(phi); - Scalar t2 = r * sin(phi); - Scalar s = 0.5 * (1.0 + V.z); + scalar_type r = sqrt(u.x); + scalar_type phi = 2.0 * nbl_glsl_PI * u.y; + scalar_type t1 = r * cos(phi); + scalar_type t2 = r * sin(phi); + scalar_type s = 0.5 * (1.0 + V.z); t2 = (1.0 - s)*sqrt(1.0 - t1*t1) + s*t2; //reprojection onto hemisphere //TODO try it wothout the max(), not sure if -t1*t1-t2*t2>-1.0 - vector_t3 H = t1*T1 + t2*T2 + sqrt(max(0.0, 1.0-t1*t1-t2*t2))*V; + vector3_type H = t1*T1 + t2*T2 + sqrt(max(0.0, 1.0-t1*t1-t2*t2))*V; //unstretch - return normalize(vector_t3(A.x*H.x, A.y*H.y, H.z)); + return normalize(vector3_type(A.x*H.x, A.y*H.y, H.z)); } template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - LightSample generate(Aniso interaction, vector u, out Cache cache) + LightSample generate(Aniso interaction, vector u, out Cache cache) { - const vector_t3 localV = interaction.getTangentSpaceV(); - const vector_t3 H = __generate(localV, u); + const vector3_type localV = interaction.getTangentSpaceV(); + const vector3_type H = __generate(localV, u); - cache = Aniso::create(localV, H); - vector_t3 localL = math::reflect(localV, H, cache.VdotH); + cache = Aniso::create(localV, H); + vector3_type localL = math::reflect(localV, H, cache.VdotH); return LightSample::createTangentSpace(localV, localL, interaction.getTangentFrame()); } template && surface_interactions::Isotropic && IsotropicMicrofacetCache) - Scalar pdf(LightSample _sample, Iso interaction, Cache cache) + scalar_type pdf(LightSample _sample, Iso interaction, Cache cache) { - const Scalar a2 = A.x*A.x; - Scalar ndf = ndf::ggx_trowbridge_reitz(a2, cache.NdotH2); + const scalar_type a2 = A.x*A.x; + scalar_type ndf = ndf::ggx_trowbridge_reitz(a2, cache.NdotH2); - const Scalar devsh_v = smith::ggx_devsh_part(interaction.NdotV2, a2, 1.0-a2); - const Scalar G1_over_2NdotV = smith::ggx_G1_wo_numerator(interaction.NdotV, devsh_v); - return smith::VNDF_pdf_wo_clamps(ndf, G1_over_2NdotV); + const scalar_type devsh_v = smith::ggx_devsh_part(interaction.NdotV2, a2, 1.0-a2); + const scalar_type G1_over_2NdotV = smith::ggx_G1_wo_numerator(interaction.NdotV, devsh_v); + return smith::VNDF_pdf_wo_clamps(ndf, G1_over_2NdotV); } template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - Scalar pdf(LightSample _sample, Aniso interaction, Cache cache) + scalar_type pdf(LightSample _sample, Aniso interaction, Cache cache) { - const Scalar ax2 = A.x*A.x; - const Scalar ay2 = A.y*A.y; - Scalar ndf = ndf::ggx_aniso(cache.TdotH * cache.TdotH, cache.BdotH * cache.BdotH, cache.NdotH2, A.x, A.y, ax2, ay2); + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; + scalar_type ndf = ndf::ggx_aniso(cache.TdotH * cache.TdotH, cache.BdotH * cache.BdotH, cache.NdotH2, A.x, A.y, ax2, ay2); - const Scalar devsh_v = smith::ggx_devsh_part(interaction.TdotV * interaction.TdotV, interaction.BdotV * interaction.BdotV, interaction.NdotV2, ax2, ay2); - const Scalar G1_over_2NdotV = smith::ggx_G1_wo_numerator(interaction.NdotV, devsh_v); - return smith::VNDF_pdf_wo_clamps(ndf, G1_over_2NdotV); + const scalar_type devsh_v = smith::ggx_devsh_part(interaction.TdotV * interaction.TdotV, interaction.BdotV * interaction.BdotV, interaction.NdotV2, ax2, ay2); + const scalar_type G1_over_2NdotV = smith::ggx_G1_wo_numerator(interaction.NdotV, devsh_v); + return smith::VNDF_pdf_wo_clamps(ndf, G1_over_2NdotV); } - template && Sample && surface_interactions::Isotropic && IsotropicMicrofacetCache) - quotient_and_pdf quotient_and_pdf_wo_clamps(LightSample _sample, Iso interaction, Cache cache, vector_t3 reflectance) + template && Sample && surface_interactions::Isotropic && IsotropicMicrofacetCache) + quotient_and_pdf quotient_and_pdf_wo_clamps(LightSample _sample, Iso interaction, Cache cache, vector3_type reflectance) { - const Scalar a2 = A.x*A.x; - const Scalar one_minus_a2 = 1.0 - a2; + const scalar_type a2 = A.x*A.x; + const scalar_type one_minus_a2 = 1.0 - a2; - const Scalar ndf = ndf::ggx_trowbridge_reitz(a2, cache.NdotH2); - const Scalar devsh_v = smith::ggx_devsh_part(interaction.NdotV2, a2, one_minus_a2); - Scalar pdf = pdf(_sample, interaction, cache); + const scalar_type ndf = ndf::ggx_trowbridge_reitz(a2, cache.NdotH2); + const scalar_type devsh_v = smith::ggx_devsh_part(interaction.NdotV2, a2, one_minus_a2); + scalar_type pdf = pdf(_sample, interaction, cache); - Scalar G2_over_G1 = smith::ggx_G2_over_G1_devsh(_sample.NdotL, _sample.NdotL2, interaction.NdotV, devsh_v, a2, one_minus_a2); - vector_t3 quo = reflectance * G2_over_G1; + scalar_type G2_over_G1 = smith::ggx_G2_over_G1_devsh(_sample.NdotL, _sample.NdotL2, interaction.NdotV, devsh_v, a2, one_minus_a2); + vector3_type quo = reflectance * G2_over_G1; - return quotient_and_pdf::create(SpectralBins(quo), pdf); + return quotient_and_pdf::create(SpectralBins(quo), pdf); } - template && Sample && surface_interactions::Isotropic && IsotropicMicrofacetCache) - quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction, Cache cache) + template && Sample && surface_interactions::Isotropic && IsotropicMicrofacetCache) + quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction, Cache cache) { - const Scalar a2 = A.x*A.x; - const Scalar one_minus_a2 = 1.0 - a2; + const scalar_type a2 = A.x*A.x; + const scalar_type one_minus_a2 = 1.0 - a2; - const Scalar ndf = ndf::ggx_trowbridge_reitz(a2, cache.NdotH2); - const Scalar devsh_v = smith::ggx_devsh_part(interaction.NdotV2, a2, one_minus_a2); - Scalar pdf = pdf(_sample, interaction, cache); + const scalar_type ndf = ndf::ggx_trowbridge_reitz(a2, cache.NdotH2); + const scalar_type devsh_v = smith::ggx_devsh_part(interaction.NdotV2, a2, one_minus_a2); + scalar_type pdf = pdf(_sample, interaction, cache); - vector_t3 quo = (vector_t3)0.0; - if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) + vector3_type quo = (vector3_type)0.0; + if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { - const vector_t3 reflectance = fresnelConductor(ior[0], ior[1], cache.VdotH); - Scalar G2_over_G1 = smith::ggx_G2_over_G1_devsh(_sample.NdotL, _sample.NdotL2, interaction.NdotV, devsh_v, a2, one_minus_a2); + const vector3_type reflectance = fresnelConductor(ior[0], ior[1], cache.VdotH); + scalar_type G2_over_G1 = smith::ggx_G2_over_G1_devsh(_sample.NdotL, _sample.NdotL2, interaction.NdotV, devsh_v, a2, one_minus_a2); quo = reflectance * G2_over_G1; } - return quotient_and_pdf::create(SpectralBins(quo), pdf); + return quotient_and_pdf::create(SpectralBins(quo), pdf); } - template && Sample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - quotient_and_pdf quotient_and_pdf_wo_clamps(LightSample _sample, Aniso interaction, Cache cache, vector_t3 reflectance) + template && Sample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + quotient_and_pdf quotient_and_pdf_wo_clamps(LightSample _sample, Aniso interaction, Cache cache, vector3_type reflectance) { params_t params = params_t::template create(_sample, interaction, cache); - const Scalar ax2 = A.x*A.x; - const Scalar ay2 = A.y*A.y; + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; - const Scalar ndf = ndf::ggx_aniso(params.TdotH2, params.BdotH2, params.NdotH2, A.x, A.y, ax2, ay2); - const Scalar devsh_v = smith::ggx_devsh_part(interaction.NdotV2, a2, one_minus_a2); - Scalar pdf = pdf(_sample, interaction, cache); + const scalar_type ndf = ndf::ggx_aniso(params.TdotH2, params.BdotH2, params.NdotH2, A.x, A.y, ax2, ay2); + const scalar_type devsh_v = smith::ggx_devsh_part(interaction.NdotV2, a2, one_minus_a2); + scalar_type pdf = pdf(_sample, interaction, cache); - Scalar G2_over_G1 = smith::ggx_G2_over_G1_devsh(params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2, params.NdotV, devsh_v, ax2, ay2); - vector_t3 quo = reflectance * G2_over_G1; + scalar_type G2_over_G1 = smith::ggx_G2_over_G1_devsh(params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2, params.NdotV, devsh_v, ax2, ay2); + vector3_type quo = reflectance * G2_over_G1; - return quotient_and_pdf::create(SpectralBins(quo), pdf); + return quotient_and_pdf::create(SpectralBins(quo), pdf); } - template && Sample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - quotient_and_pdf quotient_and_pdf(LightSample _sample, Aniso interaction, Cache cache) + template && Sample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + quotient_and_pdf quotient_and_pdf(LightSample _sample, Aniso interaction, Cache cache) { params_t params = params_t::template create(_sample, interaction, cache); - const Scalar ax2 = A.x*A.x; - const Scalar ay2 = A.y*A.y; + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; - const Scalar ndf = ndf::ggx_aniso(params.TdotH2, params.BdotH2, params.NdotH2, A.x, A.y, ax2, ay2); - const Scalar devsh_v = smith::ggx_devsh_part(interaction.NdotV2, a2, one_minus_a2); - Scalar pdf = pdf(_sample, interaction, cache); + const scalar_type ndf = ndf::ggx_aniso(params.TdotH2, params.BdotH2, params.NdotH2, A.x, A.y, ax2, ay2); + const scalar_type devsh_v = smith::ggx_devsh_part(interaction.NdotV2, a2, one_minus_a2); + scalar_type pdf = pdf(_sample, interaction, cache); - vector_t3 quo = (vector_t3)0.0; - if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) + vector3_type quo = (vector3_type)0.0; + if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { - const vector_t3 reflectance = fresnel_conductor(ior[0], ior[1], cache.VdotH); - Scalar G2_over_G1 = smith::ggx_G2_over_G1_devsh(params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2, params.NdotV, devsh_v, ax2, ay2); + const vector3_type reflectance = fresnel_conductor(ior[0], ior[1], cache.VdotH); + scalar_type G2_over_G1 = smith::ggx_G2_over_G1_devsh(params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2, params.NdotV, devsh_v, ax2, ay2); quo = reflectance * G2_over_G1; } - return quotient_and_pdf::create(SpectralBins(quo), pdf); + return quotient_and_pdf::create(SpectralBins(quo), pdf); } - vector_t2 A; - matrix ior; + vector2_type A; + matrix ior; }; } From 34017835232f9d44524c353ea0f30f6cc0b1fc95 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 11 Dec 2024 16:19:51 +0700 Subject: [PATCH 024/188] refactored brdfs --- include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl | 8 +- include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 15 +- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 279 +++++++++++------- 3 files changed, 172 insertions(+), 130 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl index 48e1afefcb..2141f7cee2 100644 --- a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl @@ -23,19 +23,19 @@ T G1(T lambda) } template -T VNDF_pdf_wo_clamps(NDF ndf, typename NDF::scalar_type lambda_V, typename NDF::scalar_type maxNdotV, out typename NDF::scalar_type onePlusLambda_V) +T VNDF_pdf_wo_clamps(typename NDF::scalar_type ndf, typename NDF::scalar_type lambda_V, typename NDF::scalar_type maxNdotV, out typename NDF::scalar_type onePlusLambda_V) { onePlusLambda_V = 1.0 + lambda_V; - ndf::microfacet_to_light_measure_transform transform = ndf::microfacet_to_light_measure_transform::create(ndf() / onePlusLambda_V, maxNdotV); + ndf::microfacet_to_light_measure_transform transform = ndf::microfacet_to_light_measure_transform::create(ndf / onePlusLambda_V, maxNdotV); return transform(); } template -T VNDF_pdf_wo_clamps(NDF ndf, typename NDF::scalar_type lambda_V, typename NDF::scalar_type absNdotV, bool transmitted, typename NDF::scalar_type VdotH, typename NDF::scalar_type LdotH, typename NDF::scalar_type VdotHLdotH, typename NDF::scalar_type orientedEta, typename NDF::scalar_type reflectance, out typename NDF::scalar_type onePlusLambda_V) +T VNDF_pdf_wo_clamps(typename NDF::scalar_type ndf, typename NDF::scalar_type lambda_V, typename NDF::scalar_type absNdotV, bool transmitted, typename NDF::scalar_type VdotH, typename NDF::scalar_type LdotH, typename NDF::scalar_type VdotHLdotH, typename NDF::scalar_type orientedEta, typename NDF::scalar_type reflectance, out typename NDF::scalar_type onePlusLambda_V) { onePlusLambda_V = 1.0 + lambda_V; ndf::microfacet_to_light_measure_transform transform - = ndf::microfacet_to_light_measure_transform::create((transmitted ? (1.0 - reflectance) : reflectance) * ndf() / onePlusLambda_V, , absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); + = ndf::microfacet_to_light_measure_transform::create((transmitted ? (1.0 - reflectance) : reflectance) * ndf / onePlusLambda_V, , absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); return transform(); } diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl index 164df50532..77899f26a7 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -62,20 +62,7 @@ struct SAnisotropicParams return this_t; } - static this_t create(T ax, T ay, T ax2, T ay2, T TdotH2, T BdotH2, T NdotH2) // beckmann - { - this_t retval; - retval.ax = ax; - retval.ax2 = ax2; - retval.ay = ay; - retval.ay2 = ay2; - retval.TdotH2 = TdotH2; - retval.BdotH2 = BdotH2; - retval.NdotH2 = NdotH2; - return this_t; - } - - static this_t create(T TdotH2, T BdotH2, T NdotH2, T ax, T ay, T ax2, T ay2) // ggx aniso + static this_t create(T ax, T ay, T ax2, T ay2, T TdotH2, T BdotH2, T NdotH2) // beckmann, ggx aniso { this_t retval; retval.ax = ax; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 3c46255521..a555e5e5a8 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -279,7 +279,8 @@ struct SBlinnPhongBxDF vector2_type a2 = (vector2_type)phong_exp_to_alpha2(n); scalar_part = __eval_DG_wo_clamps(params, a2); } - return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_to_light_measure_transform(scalar_part, params.NdotV); + microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotV); + return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_transform(); } vector3_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) @@ -331,16 +332,27 @@ struct SBlinnPhongBxDF matrix2x3_type ior; }; -template) +template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SBeckmannBxDF { + using scalar_type = typename LightSample::scalar_type + using vector2_type = vector; + using vector3_type = vector; + using matrix2x3_type = matrix; + using this_t = SBeckmannBxDF; - using vector2_type = vector; - using vector3_type = vector; using params_t = SBxDFParams; + using isotropic_type = typename IsoCache::isotropic_type; + using anisotropic_type = typename AnisoCache::anisotropic_type + using sample_type = LightSample; + using spectral_type = vector; // TODO: most likely change this + using quotient_pdf_type = quotient_and_pdf; + using isocache_type = IsoCache; + using anisocache_type = AnisoCache; + // iso - static this_t create(scalar_type A,matrix ior) + static this_t create(scalar_type A,matrix2x3_type ior) { this_t retval; retval.A = vector2_type(A,A); @@ -349,7 +361,7 @@ struct SBeckmannBxDF } // aniso - static this_t create(scalar_type ax,scalar_type ay,matrix ior) + static this_t create(scalar_type ax,scalar_type ay,matrix2x3_type ior) { this_t retval; retval.A = vector2_type(ax,ay); @@ -364,17 +376,29 @@ struct SBeckmannBxDF { const scalar_type ax2 = A.x*A.x; const scalar_type ay2 = A.y*A.y; - scalar_type NG = ndf::beckmann(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + ndf::Beckmann beckmann_ndf; + scalar_type NG = beckmann_ndf(ndfparams); if (any(A > numeric_limits::min)) - NG *= smith::beckmann_smith_correlated(params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, ax2, ay2); + { + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, 0); + smith::Beckmann beckmann_smith; + NG *= beckmann_smith.smith_correlated(smithparams); + } return NG; } else { scalar_type a2 = A.x*A.x; - scalar_type NG = ndf::beckmann(a2, params.NdotH2); + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH2); + ndf::Beckmann beckmann_ndf; + scalar_type NG = beckmann_ndf(ndfparams); if (a2 > numeric_limits::min) - NG *= smith::beckmann_smith_correlated(params.NdotV2, params.NdotL2, a2.x); + { + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2.x, params.NdotV2, params.NdotL2, 0); + smith::Beckmann beckmann_smith; + NG *= beckmann_smith.smith_correlated(smithparams); + } return NG; } } @@ -383,27 +407,26 @@ struct SBeckmannBxDF vector3_type __eval_wo_clamps(params_t params) { scalar_type scalar_part = __eval_DG_wo_clamps(params); - return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_to_light_measure_transform(scalar_part, params.NdotV); + microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotV); + return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_transform(); } - template && surface_interactions::Isotropic && IsotropicMicrofacetCache) // maybe put template in struct vs function? - vector3_type eval(LightSample _sample, Iso interaction, Cache cache) + vector3_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) { if (interaction.NdotV > numeric_limits::min) { - params_t params = params_t::template create(_sample, interaction, cache); + params_t params = params_t::template create(_sample, interaction, cache); return __eval_wo_clamps(params); } else return (vector3_type)0.0; } - template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) // maybe put template in struct vs function? - vector3_type eval(LightSample _sample, Aniso interaction, Cache cache) + vector3_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) { if (interaction.NdotV > numeric_limits::min) { - params_t params = params_t::template create(_sample, interaction, cache); + params_t params = params_t::template create(_sample, interaction, cache); return __eval_wo_clamps(params); } else @@ -478,97 +501,117 @@ struct SBeckmannBxDF return normalize(vector3_type(-slope, 1.0)); } - template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - LightSample generate(Aniso interaction, vector u, out Cache cache) + sample_type generate(anisotropic_type interaction, vector2_type u, out anisocache_type cache) { const vector3_type localV = interaction.getTangentSpaceV(); const vector3_type H = __generate(localV, u); - cache = Aniso::create(localV, H); + cache = anisocache_type::create(localV, H); vector3_type localL = math::reflect(localV, H, cache.VdotH); - return LightSample::createTangentSpace(localV, localL, interaction.getTangentFrame()); + return sample_type::createTangentSpace(localV, localL, interaction.getTangentFrame()); } - template && surface_interactions::Isotropic && IsotropicMicrofacetCache) - scalar_type pdf(LightSample _sample, Iso interaction, Cache cache) + scalar_type pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) { - scalar_type NdotH2 = cache.NdotH2; - scalar_type ndf = ndf::beckmann(A.x*A.x, NdotH2); + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, cache.NdotH2); + ndf::Beckmann beckmann_ndf; + scalar_type ndf = beckmann_ndf(ndfparams); - const scalar_type lambda = smith::beckmann_Lambda(interaction.NdotV2, A.x*A.x); + smith::Beckmann beckmann_smith; + const scalar_type lambda = beckmann_smith.Lambda(interaction.NdotV2, A.x*A.x); scalar_type dummy; - return smith::VNDF_pdf_wo_clamps(ndf, lambda, interaction.NdotV, dummy); + return smith::VNDF_pdf_wo_clamps >(ndf, lambda, interaction.NdotV, dummy); } - template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - scalar_type pdf(LightSample _sample, Aniso interaction, Cache cache) + scalar_type pdf(sample_type _sample, anisotropic_type interaction, anisocache_type cache) { - scalar_type NdotH2 = cache.NdotH2; - scalar_type ndf = ndf::beckmann(A.x, A.y, A.x*A.x, A.y*A.y, cache.TdotH * cache.TdotH, cache.BdotH * cache.BdotH, NdotH2); + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, A.x*A.x, A.y*A.y, cache.TdotH * cache.TdotH, cache.BdotH * cache.BdotH, cache.NdotH2); + ndf::Beckmann beckmann_ndf; + scalar_type ndf = backmann_ndf(ndfparams); - const scalar_type c2 = smith::beckmann_C2(interaction.TdotV * interaction.TdotV, interaction.BdotV * interaction.BdotV, interaction.NdotV2, A.x, A.y); - scalar_type lambda = smith::beckmann_Lambda(c2); + smith::Beckmann beckmann_smith; + const scalar_type c2 = beckmann_smith.C2(interaction.TdotV * interaction.TdotV, interaction.BdotV * interaction.BdotV, interaction.NdotV2, A.x, A.y); + scalar_type lambda = beckmann_smith.Lambda(c2); scalar_type dummy; - return smith::VNDF_pdf_wo_clamps(ndf, lambda, interaction.NdotV, dummy); + return smith::VNDF_pdf_wo_clamps >(ndf, lambda, interaction.NdotV, dummy); } - template && Sample && surface_interactions::Isotropic && IsotropicMicrofacetCache) - quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction, Cache cache) + quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) { - const scalar_type ndf = ndf::beckmann(A.x*A.x, cache.NdotH2); - const scalar_type lambda = smith::beckmann_Lambda(interaction.NdotV2, A.x*A.x); + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, cache.NdotH2); + ndf::Beckmann beckmann_ndf; + const scalar_type ndf = beckmann_ndf(ndfparams); + + smith::Beckmann beckmann_smith; + const scalar_type lambda = beckmann_smith.Lambda(interaction.NdotV2, A.x*A.x); scalar_type onePlusLambda_V; - scalar_type pdf = smith::VNDF_pdf_wo_clamps(ndf, lambda, interaction.NdotV, onePlusLambda_V); + scalar_type pdf = smith::VNDF_pdf_wo_clamps >(ndf, lambda, interaction.NdotV, onePlusLambda_V); vector3_type quo = (vector3_type)0.0; if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, 0, _sample.NdotL2, onePlusLambda_V); const vector3_type reflectance = fresnelConductor(ior[0], ior[1], cache.VdotH); - scalar_type G2_over_G1 = smith::beckmann_smith_G2_over_G1(onePlusLambda_V, _sample.NdotL2, a2); + scalar_type G2_over_G1 = beckmann_smith.smith_G2_over_G1(smithparams); quo = reflectance * G2_over_G1; } - return quotient_and_pdf::create(SpectralBins(quo), pdf); + return quotient_pdf_type::create(spectral_type(quo), pdf); } - template && Sample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - quotient_and_pdf quotient_and_pdf(LightSample _sample, Aniso interaction, Cache cache) + quotient_pdf_type quotient_and_pdf(sample_type _sample, anisotropic_type interaction, anisocache_type cache) { - params_t params = params_t::template create(_sample, interaction, cache); + params_t params = params_t::template create(_sample, interaction, cache); const scalar_type ax2 = A.x*A.x; const scalar_type ay2 = A.y*A.y; - const scalar_type ndf = ndf::beckmann(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + ndf::Beckmann beckmann_ndf; + scalar_type ndf = backmann_ndf(ndfparams); + + smith::Beckmann beckmann_smith; scalar_type onePlusLambda_V; - const scalar_type c2 = smith::beckmann_C2(params.TdotV2, params.BdotV2, params.NdotV2, A.x, A.y); - scalar_type lambda = smith::beckmann_Lambda(c2); - scalar_type pdf = smith::VNDF_pdf_wo_clamps(ndf, lambda, interaction.NdotV, onePlusLambda_V); + const scalar_type c2 = smith::beckmann_smith.C2(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); + scalar_type lambda = beckmann_smith.Lambda(c2); + scalar_type pdf = smith::VNDF_pdf_wo_clamps >(ndf, lambda, interaction.NdotV, onePlusLambda_V); vector3_type quo = (vector3_type)0.0; if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) - { + { + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, onePlusLambda_V); const vector3_type reflectance = fresnel_conductor(ior[0], ior[1], cache.VdotH); - scalar_type G2_over_G1 = smith::beckmann_smith_G2_over_G1(onePlusLambda_V, params.TdotL2, params.BdotL2, params.NdotL2, A.x, A.y); + scalar_type G2_over_G1 = smith::beckmann_smith.smith_G2_over_G1(smithparams); quo = reflectance * G2_over_G1; } - return quotient_and_pdf::create(SpectralBins(quo), pdf); + return quotient_pdf_type::create(spectral_type(quo), pdf); } vector2_type A; - matrix ior; + matrix2x3_type ior; }; -template) +template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SGGXBxDF { + using scalar_type = typename LightSample::scalar_type + using vector2_type = vector; + using vector3_type = vector; + using matrix2x3_type = matrix; + using this_t = SGGXBxDF; - using vector2_type = vector; - using vector3_type = vector; using params_t = SBxDFParams; + using isotropic_type = typename IsoCache::isotropic_type; + using anisotropic_type = typename AnisoCache::anisotropic_type + using sample_type = LightSample; + using spectral_type = vector; // TODO: most likely change this + using quotient_pdf_type = quotient_and_pdf; + using isocache_type = IsoCache; + using anisocache_type = AnisoCache; + // iso - static this_t create(scalar_type A,matrix ior) + static this_t create(scalar_type A,matrix2x3_type ior) { this_t retval; retval.A = vector2_type(A,A); @@ -577,7 +620,7 @@ struct SGGXBxDF } // aniso - static this_t create(scalar_type ax,scalar_type ay,matrix ior) + static this_t create(scalar_type ax,scalar_type ay,matrix2x3_type ior) { this_t retval; retval.A = vector2_type(ax,ay); @@ -592,17 +635,29 @@ struct SGGXBxDF { const scalar_type ax2 = A.x*A.x; const scalar_type ay2 = A.y*A.y; - scalar_type NG = ndf::ggx_aniso(params.TdotH2, params.BdotH2, params.NdotH2, A.x, A.y, ax2, ay2); + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + ndf::GGX ggx_ndf; + scalar_type NG = ggx_ndf(ndfparams); if (any(A > numeric_limits::min)) - NG *= smith::ggx_correlated_wo_numerator(params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2, ax2, ay2); + { + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2); + smith::GGX ggx_smith; + NG *= ggx_smith.correlated_wo_numerator(smithparams); + } return NG; } else { scalar_type a2 = A.x*A.x; - scalar_type NG = ndf::ggx_trowbridge_reitz(a2, params.NdotH2); + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH2); + ndf::GGX ggx_ndf; + scalar_type NG = ggx_ndf(ndfparams); if (a2 > numeric_limits::min) - NG *= smith::ggx_correlated_wo_numerator(max(params.NdotV,0.0), params.NdotV2, max(params.NdotL,0.0), params.NdotL2, a2); + { + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, max(params.NdotV,0.0), params.NdotV2, max(params.NdotL,0.0), params.NdotL2); + smith::GGX ggx_smith; + NG *= ggx_smith.correlated_wo_numerator(smithparams); + } return NG; } } @@ -611,27 +666,26 @@ struct SGGXBxDF vector3_type __eval_wo_clamps(params_t params) { scalar_type scalar_part = __eval_DG_wo_clamps(params); - return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_to_light_measure_transform(scalar_part, params.NdotL); + microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotL); + return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_transform(); } - template && surface_interactions::Isotropic && IsotropicMicrofacetCache) // maybe put template in struct vs function? - vector3_type eval(LightSample _sample, Iso interaction, Cache cache) + vector3_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) { if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { - params_t params = params_t::template create(_sample, interaction, cache); + params_t params = params_t::template create(_sample, interaction, cache); return __eval_wo_clamps(params); } else return (vector3_type)0.0; } - template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) // maybe put template in struct vs function? - vector3_type eval(LightSample _sample, Aniso interaction, Cache cache) + vector3_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) { if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { - params_t params = params_t::template create(_sample, interaction, cache); + params_t params = params_t::template create(_sample, interaction, cache); return __eval_wo_clamps(params); } else @@ -660,119 +714,120 @@ struct SGGXBxDF return normalize(vector3_type(A.x*H.x, A.y*H.y, H.z)); } - template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - LightSample generate(Aniso interaction, vector u, out Cache cache) + sample_type generate(anisotropic_type interaction, vector2_type u, out anisocache_type cache) { const vector3_type localV = interaction.getTangentSpaceV(); const vector3_type H = __generate(localV, u); - cache = Aniso::create(localV, H); + cache = anisocache_type::create(localV, H); vector3_type localL = math::reflect(localV, H, cache.VdotH); - return LightSample::createTangentSpace(localV, localL, interaction.getTangentFrame()); + return sample_type::createTangentSpace(localV, localL, interaction.getTangentFrame()); } - template && surface_interactions::Isotropic && IsotropicMicrofacetCache) - scalar_type pdf(LightSample _sample, Iso interaction, Cache cache) + scalar_type pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) { const scalar_type a2 = A.x*A.x; - scalar_type ndf = ndf::ggx_trowbridge_reitz(a2, cache.NdotH2); + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, cache.NdotH2); + ndf::GGX ggx_ndf; + scalar_type ndf = ggx_ndf(ndfparams); - const scalar_type devsh_v = smith::ggx_devsh_part(interaction.NdotV2, a2, 1.0-a2); - const scalar_type G1_over_2NdotV = smith::ggx_G1_wo_numerator(interaction.NdotV, devsh_v); + smith::GGX ggx_smith; + const scalar_type devsh_v = ggx_smith.devsh_part(interaction.NdotV2, a2, 1.0-a2); + const scalar_type G1_over_2NdotV = ggx_smith.G1_wo_numerator(interaction.NdotV, devsh_v); return smith::VNDF_pdf_wo_clamps(ndf, G1_over_2NdotV); } - template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - scalar_type pdf(LightSample _sample, Aniso interaction, Cache cache) + scalar_type pdf(sample_type _sample, anisotropic_type interaction, anisocache_type cache) { const scalar_type ax2 = A.x*A.x; const scalar_type ay2 = A.y*A.y; scalar_type ndf = ndf::ggx_aniso(cache.TdotH * cache.TdotH, cache.BdotH * cache.BdotH, cache.NdotH2, A.x, A.y, ax2, ay2); - const scalar_type devsh_v = smith::ggx_devsh_part(interaction.TdotV * interaction.TdotV, interaction.BdotV * interaction.BdotV, interaction.NdotV2, ax2, ay2); - const scalar_type G1_over_2NdotV = smith::ggx_G1_wo_numerator(interaction.NdotV, devsh_v); + smith::GGX ggx_smith; + const scalar_type devsh_v = ggx_smith.devsh_part(interaction.TdotV * interaction.TdotV, interaction.BdotV * interaction.BdotV, interaction.NdotV2, ax2, ay2); + const scalar_type G1_over_2NdotV = ggx_smith.G1_wo_numerator(interaction.NdotV, devsh_v); return smith::VNDF_pdf_wo_clamps(ndf, G1_over_2NdotV); } - template && Sample && surface_interactions::Isotropic && IsotropicMicrofacetCache) - quotient_and_pdf quotient_and_pdf_wo_clamps(LightSample _sample, Iso interaction, Cache cache, vector3_type reflectance) + quotient_pdf_type quotient_and_pdf_wo_clamps(sample_type _sample, isotropic_type interaction, isocache_type cache, vector3_type reflectance) { const scalar_type a2 = A.x*A.x; const scalar_type one_minus_a2 = 1.0 - a2; - const scalar_type ndf = ndf::ggx_trowbridge_reitz(a2, cache.NdotH2); - const scalar_type devsh_v = smith::ggx_devsh_part(interaction.NdotV2, a2, one_minus_a2); - scalar_type pdf = pdf(_sample, interaction, cache); + smith::GGX ggx_smith; + const scalar_type devsh_v = ggx_smith.devsh_part(interaction.NdotV2, a2, one_minus_a2); + scalar_type pdf = pdf(_sample, interaction, cache); - scalar_type G2_over_G1 = smith::ggx_G2_over_G1_devsh(_sample.NdotL, _sample.NdotL2, interaction.NdotV, devsh_v, a2, one_minus_a2); + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, interaction.NdotV, interaction.NdotV2, _sample.NdotL, _sample.NdotL2) + scalar_type G2_over_G1 = ggx_smith.G2_over_G1(smithparams); vector3_type quo = reflectance * G2_over_G1; - return quotient_and_pdf::create(SpectralBins(quo), pdf); + return quotient_pdf_type::create(spectral_type(quo), pdf); } - template && Sample && surface_interactions::Isotropic && IsotropicMicrofacetCache) - quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction, Cache cache) + quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) { const scalar_type a2 = A.x*A.x; const scalar_type one_minus_a2 = 1.0 - a2; - const scalar_type ndf = ndf::ggx_trowbridge_reitz(a2, cache.NdotH2); - const scalar_type devsh_v = smith::ggx_devsh_part(interaction.NdotV2, a2, one_minus_a2); - scalar_type pdf = pdf(_sample, interaction, cache); + smith::GGX ggx_smith; + const scalar_type devsh_v = ggx_smith.devsh_part(interaction.NdotV2, a2, one_minus_a2); + scalar_type pdf = pdf(_sample, interaction, cache); vector3_type quo = (vector3_type)0.0; if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { const vector3_type reflectance = fresnelConductor(ior[0], ior[1], cache.VdotH); - scalar_type G2_over_G1 = smith::ggx_G2_over_G1_devsh(_sample.NdotL, _sample.NdotL2, interaction.NdotV, devsh_v, a2, one_minus_a2); + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, interaction.NdotV, interaction.NdotV2, _sample.NdotL, _sample.NdotL2) + scalar_type G2_over_G1 = ggx_smith.G2_over_G1(smithparams); quo = reflectance * G2_over_G1; } - return quotient_and_pdf::create(SpectralBins(quo), pdf); + return quotient_pdf_type::create(spectral_type(quo), pdf); } - template && Sample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - quotient_and_pdf quotient_and_pdf_wo_clamps(LightSample _sample, Aniso interaction, Cache cache, vector3_type reflectance) + quotient_pdf_type quotient_and_pdf_wo_clamps(sample_type _sample, anisotropic_type interaction, anisocache_type cache, vector3_type reflectance) { - params_t params = params_t::template create(_sample, interaction, cache); + params_t params = params_t::template create(_sample, interaction, cache); const scalar_type ax2 = A.x*A.x; const scalar_type ay2 = A.y*A.y; - const scalar_type ndf = ndf::ggx_aniso(params.TdotH2, params.BdotH2, params.NdotH2, A.x, A.y, ax2, ay2); - const scalar_type devsh_v = smith::ggx_devsh_part(interaction.NdotV2, a2, one_minus_a2); - scalar_type pdf = pdf(_sample, interaction, cache); + smith::GGX ggx_smith; + const scalar_type devsh_v = ggx_smith.devsh_part(interaction.NdotV2, a2, one_minus_a2); + scalar_type pdf = pdf(_sample, interaction, cache); - scalar_type G2_over_G1 = smith::ggx_G2_over_G1_devsh(params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2, params.NdotV, devsh_v, ax2, ay2); + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2) + scalar_type G2_over_G1 = ggx_smith.G2_over_G1(smithparams); vector3_type quo = reflectance * G2_over_G1; - return quotient_and_pdf::create(SpectralBins(quo), pdf); + return quotient_pdf_type::create(spectral_type(quo), pdf); } - template && Sample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - quotient_and_pdf quotient_and_pdf(LightSample _sample, Aniso interaction, Cache cache) + quotient_pdf_type quotient_and_pdf(sample_type _sample, anisotropic_type interaction, anisocache_type cache) { - params_t params = params_t::template create(_sample, interaction, cache); + params_t params = params_t::template create(_sample, interaction, cache); const scalar_type ax2 = A.x*A.x; const scalar_type ay2 = A.y*A.y; - const scalar_type ndf = ndf::ggx_aniso(params.TdotH2, params.BdotH2, params.NdotH2, A.x, A.y, ax2, ay2); - const scalar_type devsh_v = smith::ggx_devsh_part(interaction.NdotV2, a2, one_minus_a2); - scalar_type pdf = pdf(_sample, interaction, cache); + smith::GGX ggx_smith; + const scalar_type devsh_v = ggx_smith.devsh_part(interaction.NdotV2, a2, one_minus_a2); + scalar_type pdf = pdf(_sample, interaction, cache); vector3_type quo = (vector3_type)0.0; if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { const vector3_type reflectance = fresnel_conductor(ior[0], ior[1], cache.VdotH); - scalar_type G2_over_G1 = smith::ggx_G2_over_G1_devsh(params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2, params.NdotV, devsh_v, ax2, ay2); + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2) + scalar_type G2_over_G1 = ggx_smith.G2_over_G1(smithparams); quo = reflectance * G2_over_G1; } - return quotient_and_pdf::create(SpectralBins(quo), pdf); + return quotient_pdf_type::create(spectral_type(quo), pdf); } vector2_type A; - matrix ior; + matrix2x3_type ior; }; } From 311542394185b145b2f542a3c9fdb8a11c501949 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 11 Dec 2024 16:28:46 +0700 Subject: [PATCH 025/188] corrected concept macro usage --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 05e06afb69..e07e331379 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -59,9 +59,9 @@ namespace ray_dir_info #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) #define NBL_CONCEPT_TPLT_PRM_NAMES (T) #define NBL_CONCEPT_PARAM_0 (rdirinfo, T) -#define NBL_CONCEPT_PARAM_1 (N, typename vector3_type) +#define NBL_CONCEPT_PARAM_1 (N, typename T::vector3_type) #define NBL_CONCEPT_PARAM_2 (dirDotN, typename T::scalar_type) -NBL_CONCEPT_BEGIN(7) +NBL_CONCEPT_BEGIN(3) #define rdirinfo NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define N NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define dirDotN NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 @@ -124,7 +124,7 @@ namespace surface_interactions #define NBL_CONCEPT_PARAM_0 (iso, T) #define NBL_CONCEPT_PARAM_1 (normV, typename T::ray_dir_info_type) #define NBL_CONCEPT_PARAM_2 (normN, typename T::vector3_type) -NBL_CONCEPT_BEGIN(8) +NBL_CONCEPT_BEGIN(3) #define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define normV NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define normN NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 @@ -175,7 +175,7 @@ struct SIsotropic #define NBL_CONCEPT_PARAM_1 (iso, typename T::isotropic_type) #define NBL_CONCEPT_PARAM_2 (normT, typename T::vector3_type) #define NBL_CONCEPT_PARAM_3 (normB, typename T::scalar_type) -NBL_CONCEPT_BEGIN(12) +NBL_CONCEPT_BEGIN(4) #define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define normT NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 @@ -260,7 +260,7 @@ struct SAnisotropic : SIsotropic #define NBL_CONCEPT_PARAM_4 (pV, typename T::vector3_type) #define NBL_CONCEPT_PARAM_5 (frame, typename T::matrix3x3_type) #define NBL_CONCEPT_PARAM_6 (pVdotL, typename T::scalar_type) -NBL_CONCEPT_BEGIN(17) +NBL_CONCEPT_BEGIN(7) #define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 @@ -390,7 +390,7 @@ struct SLightSample #define NBL_CONCEPT_PARAM_3 (_sample, typename T::sample_type) #define NBL_CONCEPT_PARAM_4 (V, typename T::vector3_type) #define NBL_CONCEPT_PARAM_5 (b0, bool) -NBL_CONCEPT_BEGIN(16) +NBL_CONCEPT_BEGIN(6) #define cache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define pNdotV NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 @@ -539,7 +539,7 @@ struct SIsotropicMicrofacetCache #define NBL_CONCEPT_PARAM_3 (_sample, typename T::sample_type) #define NBL_CONCEPT_PARAM_4 (V, typename T::vector3_type) #define NBL_CONCEPT_PARAM_5 (b0, bool) -NBL_CONCEPT_BEGIN(13) +NBL_CONCEPT_BEGIN(6) #define cache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define pNdotL NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 @@ -728,7 +728,7 @@ typedef quotient_and_pdf, float32_t> quotient_and_pdf_rgb; #define NBL_CONCEPT_PARAM_3 (_sample, typename T::sample_type) #define NBL_CONCEPT_PARAM_4 (iso, typename T::isotropic_type) #define NBL_CONCEPT_PARAM_5 (aniso, typename T::anisotropic_type) -NBL_CONCEPT_BEGIN(9) +NBL_CONCEPT_BEGIN(6) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define spec NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define pdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 @@ -767,7 +767,7 @@ NBL_CONCEPT_END( #define NBL_CONCEPT_PARAM_5 (aniso, typename T::anisotropic_type) #define NBL_CONCEPT_PARAM_6 (isocache, typename T::isocache_type) #define NBL_CONCEPT_PARAM_7 (anisocache, typename T::anisocache_type) -NBL_CONCEPT_BEGIN(10) +NBL_CONCEPT_BEGIN(8) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define spec NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define pdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 From b244c12e162a450c0fcc325a4c839f542c214695 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 12 Dec 2024 17:31:03 +0700 Subject: [PATCH 026/188] finished beckmann+ggx bsdfs, fixed typos --- include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl | 8 +- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 63 +- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 708 ++++++++++++------ 3 files changed, 524 insertions(+), 255 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl index 2141f7cee2..0129278df8 100644 --- a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl @@ -187,7 +187,7 @@ struct Beckmann return Lambda(C2(TdotX2, BdotX2, NdotX2, ax2, ay2)); } - scalar_type smith_correlated(SIsotropicParams params) + scalar_type correlated(SIsotropicParams params) { scalar_type c2 = C2(params.NdotV2, params.a2); scalar_type L_v = Lambda(c2); @@ -196,7 +196,7 @@ struct Beckmann return G1(L_v + L_l); } - scalar_type smith_correlated(SAnisotropicParams params) + scalar_type correlated(SAnisotropicParams params) { scalar_type c2 = C2(params.TdotV2, params.BdotV2, params.NdotV2, params.ax2, params.ay2); scalar_type L_v = Lambda(c2); @@ -205,13 +205,13 @@ struct Beckmann return G1(L_v + L_l); } - scalar_type smith_G2_over_G1(SIsotropicParams params) + scalar_type G2_over_G1(SIsotropicParams params) { scalar_type lambdaL = Lambda(params.NdotL2, params.a2); return params.lambdaV_plus_one / (params.lambdaV_plus_one + lambdaL); } - scalar_type smith_G2_over_G1(SAnisotropicParams params) + scalar_type G2_over_G1(SAnisotropicParams params) { scalar_type c2 = C2(params.TdotL2, params.BdotL2, params.NdotL2, params.ax2, params.ay2); scalar_type lambdaL = Lambda(c2); diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index a555e5e5a8..5e14cd7a9b 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -18,14 +18,14 @@ namespace reflection { // still need these? -template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) +template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) LightSample cos_generate(NBL_CONST_REF_ARG(Iso) interaction) { return LightSample(interaction.V.reflect(interaction.N,interaction.NdotV),interaction.NdotV,interaction.N); } -template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) +template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) LightSample cos_generate(NBL_CONST_REF_ARG(Aniso) interaction) { return LightSample(interaction.V.reflect(interaction.N,interaction.NdotV),interaction.NdotV,interaction.T,interaction.B,interaction.N); @@ -35,7 +35,7 @@ LightSample cos_generate(NBL_CONST_REF_ARG(Aniso) interaction) template && is_floating_point_v) quotient_and_pdf cos_quotient_and_pdf() { - return quotient_and_pdf::create(SpectralBins(1.f), numeric_limits::infinity); + return quotient_and_pdf::create(SpectralBins(1.f), numeric_limits::infinity); } // new bxdf structure @@ -46,6 +46,7 @@ quotient_and_pdf cos_quotient_and_pdf() template && surface_interactions::Isotropic && surface_interactions::Anisotropic) struct SLambertianBxDF { + using this_t = SLambertianBxDF; using scalar_type = typename LightSample::scalar_type; using isotropic_type = Iso; using anisotropic_type = Aniso; @@ -53,9 +54,9 @@ struct SLambertianBxDF using spectral_type = vector; // TODO: most likely change this using quotient_pdf_type = quotient_and_pdf; - static SLambertianBxDF create() + static this_t create() { - SLambertianBxDF retval; + this_t retval; // nothing here, just keeping in convention with others return retval; } @@ -117,10 +118,10 @@ struct SLambertianBxDF template && surface_interactions::Isotropic && surface_interactions::Anisotropic) struct SOrenNayarBxDF { + using this_t = SOrenNayarBxDF; using scalar_type = typename LightSample::scalar_type; using vector2_type = vector; - using this_t = SOrenNayarBxDF; using isotropic_type = Iso; using anisotropic_type = Aniso; using sample_type = LightSample; @@ -195,15 +196,16 @@ struct SOrenNayarBxDF scalar_type A; }; + +// microfacet bxdfs template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SBlinnPhongBxDF { + using this_t = SBlinnPhongBxDF; using scalar_type = typename LightSample::scalar_type using vector2_type = vector; using vector3_type = vector; using matrix2x3_type = matrix; - - using this_t = SBlinnPhongBxDF; using params_t = SBxDFParams; using isotropic_type = typename IsoCache::isotropic_type; @@ -246,7 +248,7 @@ struct SBlinnPhongBxDF { smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(a2.x, a2.y, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, 0); smith::Beckmann beckmann; - DG *= beckmann.smith_correlated(smithparams); + DG *= beckmann.correlated(smithparams); } return DG; } @@ -259,7 +261,7 @@ struct SBlinnPhongBxDF { smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2.x, params.NdotV2, params.NdotL2, 0); smith::Beckmann beckmann; - NG *= beckmann.smith_correlated(smithparams); + NG *= beckmann.correlated(smithparams); } return NG; } @@ -279,7 +281,7 @@ struct SBlinnPhongBxDF vector2_type a2 = (vector2_type)phong_exp_to_alpha2(n); scalar_part = __eval_DG_wo_clamps(params, a2); } - microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotV); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotV); return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_transform(); } @@ -320,7 +322,7 @@ struct SBlinnPhongBxDF const vector3_type H = generate(u, n.x); const vector3_type localV = interaction.getTangentSpaceV(); - cache = anisocache_type::create(localV, H); + cache = anisocache_type::create(localV, H); vector3_type localL = math::reflect(localV, H, cache.VdotH); return sample_type::createTangentSpace(localV, localL, interaction.getTangentFrame()); @@ -335,12 +337,11 @@ struct SBlinnPhongBxDF template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SBeckmannBxDF { + using this_t = SBeckmannBxDF; using scalar_type = typename LightSample::scalar_type using vector2_type = vector; using vector3_type = vector; using matrix2x3_type = matrix; - - using this_t = SBeckmannBxDF; using params_t = SBxDFParams; using isotropic_type = typename IsoCache::isotropic_type; @@ -383,7 +384,7 @@ struct SBeckmannBxDF { smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, 0); smith::Beckmann beckmann_smith; - NG *= beckmann_smith.smith_correlated(smithparams); + NG *= beckmann_smith.correlated(smithparams); } return NG; } @@ -397,7 +398,7 @@ struct SBeckmannBxDF { smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2.x, params.NdotV2, params.NdotL2, 0); smith::Beckmann beckmann_smith; - NG *= beckmann_smith.smith_correlated(smithparams); + NG *= beckmann_smith.correlated(smithparams); } return NG; } @@ -407,7 +408,7 @@ struct SBeckmannBxDF vector3_type __eval_wo_clamps(params_t params) { scalar_type scalar_part = __eval_DG_wo_clamps(params); - microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotV); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotV); return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_transform(); } @@ -506,7 +507,7 @@ struct SBeckmannBxDF const vector3_type localV = interaction.getTangentSpaceV(); const vector3_type H = __generate(localV, u); - cache = anisocache_type::create(localV, H); + cache = anisocache_type::create(localV, H); vector3_type localL = math::reflect(localV, H, cache.VdotH); return sample_type::createTangentSpace(localV, localL, interaction.getTangentFrame()); @@ -539,12 +540,13 @@ struct SBeckmannBxDF quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) { + const scalar_type a2 = A.x*A.x; ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, cache.NdotH2); ndf::Beckmann beckmann_ndf; const scalar_type ndf = beckmann_ndf(ndfparams); smith::Beckmann beckmann_smith; - const scalar_type lambda = beckmann_smith.Lambda(interaction.NdotV2, A.x*A.x); + const scalar_type lambda = beckmann_smith.Lambda(interaction.NdotV2, a2); scalar_type onePlusLambda_V; scalar_type pdf = smith::VNDF_pdf_wo_clamps >(ndf, lambda, interaction.NdotV, onePlusLambda_V); @@ -553,7 +555,7 @@ struct SBeckmannBxDF { smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, 0, _sample.NdotL2, onePlusLambda_V); const vector3_type reflectance = fresnelConductor(ior[0], ior[1], cache.VdotH); - scalar_type G2_over_G1 = beckmann_smith.smith_G2_over_G1(smithparams); + scalar_type G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); quo = reflectance * G2_over_G1; } @@ -580,7 +582,7 @@ struct SBeckmannBxDF { smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, onePlusLambda_V); const vector3_type reflectance = fresnel_conductor(ior[0], ior[1], cache.VdotH); - scalar_type G2_over_G1 = smith::beckmann_smith.smith_G2_over_G1(smithparams); + scalar_type G2_over_G1 = smith::beckmann_smith.G2_over_G1(smithparams); quo = reflectance * G2_over_G1; } @@ -594,12 +596,11 @@ struct SBeckmannBxDF template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SGGXBxDF { + using this_t = SGGXBxDF; using scalar_type = typename LightSample::scalar_type using vector2_type = vector; using vector3_type = vector; using matrix2x3_type = matrix; - - using this_t = SGGXBxDF; using params_t = SBxDFParams; using isotropic_type = typename IsoCache::isotropic_type; @@ -666,7 +667,7 @@ struct SGGXBxDF vector3_type __eval_wo_clamps(params_t params) { scalar_type scalar_part = __eval_DG_wo_clamps(params); - microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotL); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotL); return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_transform(); } @@ -719,7 +720,7 @@ struct SGGXBxDF const vector3_type localV = interaction.getTangentSpaceV(); const vector3_type H = __generate(localV, u); - cache = anisocache_type::create(localV, H); + cache = anisocache_type::create(localV, H); vector3_type localL = math::reflect(localV, H, cache.VdotH); return sample_type::createTangentSpace(localV, localL, interaction.getTangentFrame()); @@ -759,7 +760,7 @@ struct SGGXBxDF const scalar_type devsh_v = ggx_smith.devsh_part(interaction.NdotV2, a2, one_minus_a2); scalar_type pdf = pdf(_sample, interaction, cache); - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, interaction.NdotV, interaction.NdotV2, _sample.NdotL, _sample.NdotL2) + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, interaction.NdotV, interaction.NdotV2, _sample.NdotL, _sample.NdotL2); scalar_type G2_over_G1 = ggx_smith.G2_over_G1(smithparams); vector3_type quo = reflectance * G2_over_G1; @@ -779,7 +780,7 @@ struct SGGXBxDF if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { const vector3_type reflectance = fresnelConductor(ior[0], ior[1], cache.VdotH); - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, interaction.NdotV, interaction.NdotV2, _sample.NdotL, _sample.NdotL2) + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, interaction.NdotV, interaction.NdotV2, _sample.NdotL, _sample.NdotL2); scalar_type G2_over_G1 = ggx_smith.G2_over_G1(smithparams); quo = reflectance * G2_over_G1; } @@ -797,7 +798,7 @@ struct SGGXBxDF const scalar_type devsh_v = ggx_smith.devsh_part(interaction.NdotV2, a2, one_minus_a2); scalar_type pdf = pdf(_sample, interaction, cache); - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2) + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2); scalar_type G2_over_G1 = ggx_smith.G2_over_G1(smithparams); vector3_type quo = reflectance * G2_over_G1; @@ -818,7 +819,7 @@ struct SGGXBxDF if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { const vector3_type reflectance = fresnel_conductor(ior[0], ior[1], cache.VdotH); - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2) + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2); scalar_type G2_over_G1 = ggx_smith.G2_over_G1(smithparams); quo = reflectance * G2_over_G1; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index 9abdf9abc5..056394323d 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -39,78 +39,78 @@ LightSample cos_generate(NBL_CONST_REF_ARG(Aniso) interaction) template && is_floating_point_v) quotient_and_pdf cos_quotient_and_pdf() { - return quotient_and_pdf::create(SpectralBins(1.f),nbl::hlsl::numeric_limits::inf()); + return quotient_and_pdf::create(SpectralBins(1.f),nbl::hlsl::numeric_limits::inf()); } // basic bxdf -template) +template && surface_interactions::Isotropic && surface_interactions::Anisotropic) struct SLambertianBxDF { - static SLambertianBxDF create() + using this_t = SLambertianBxDF; + using scalar_type = typename LightSample::scalar_type; + using isotropic_type = Iso; + using anisotropic_type = Aniso; + using sample_type = LightSample; + using spectral_type = vector; // TODO: most likely change this + using quotient_pdf_type = quotient_and_pdf; + + static this_t create() { - SLambertianBxDF retval; + this_t retval; // nothing here, just keeping convention with others return retval; } - Scalar __eval_pi_factored_out(Scalar absNdotL) + scalar_type __eval_pi_factored_out(scalar_type absNdotL) { return absNdotL; } - template && surface_interactions::Isotropic) // maybe put template struct vs function? - Scalar __eval_wo_clamps(LightSample _sample, Iso interaction) + scalar_type __eval_wo_clamps(sample_type _sample, isotropic_type interaction) { // probably doesn't need to use the param struct - return __eval_pi_factored_out(_sample.NdotL) * numbers::inv_pi * 0.5; + return __eval_pi_factored_out(_sample.NdotL) * numbers::inv_pi * 0.5; } - template && surface_interactions::Isotropic) // maybe put template struct vs function? - Scalar eval(LightSample _sample, Iso interaction) + scalar_type eval(sample_type _sample, isotropic_type interaction) { // probably doesn't need to use the param struct - return __eval_pi_factored_out(abs(_sample.NdotL)) * numbers::inv_pi * 0.5; + return __eval_pi_factored_out(abs(_sample.NdotL)) * numbers::inv_pi * 0.5; } - template && surface_interactions::Anisotropic) - LightSample generate_wo_clamps(Aniso interaction, vector u) + sample_type generate_wo_clamps(anisotropic_type interaction, vector u) { - vector L = projected_sphere_generate(u); - return LightSample::createTangentSpace(interaction.getTangentSpaceV(), L, interaction.getTangentFrame()); + vector L = projected_sphere_generate(u); + return sample_type::createTangentSpace(interaction.getTangentSpaceV(), L, interaction.getTangentFrame()); } - template && surface_interactions::Anisotropic) - LightSample generate(Aniso interaction, vector u) + sample_type generate(anisotropic_type interaction, vector u) { - return generate_wo_clamps(interaction, u); + return generate_wo_clamps(interaction, u); } - template && surface_interactions::Isotropic) - Scalar pdf_wo_clamps(LightSample _sample, Iso interaction) + scalar_type pdf_wo_clamps(sample_type _sample, isotropic_type interaction) { - return projected_sphere_pdf(_sample.NdotL, 0.0); + return projected_sphere_pdf(_sample.NdotL, 0.0); } - template && surface_interactions::Isotropic) - Scalar pdf(LightSample _sample, Iso interaction) + scalar_type pdf(sample_type _sample, isotropic_type interaction) { - return projected_sphere_pdf(abs(_sample.NdotL)); + return projected_sphere_pdf(abs(_sample.NdotL)); } - template && Sample && surface_interactions::Anisotropic) - quotient_and_pdf quotient_and_pdf_wo_clamps(LightSample _sample, Iso interaction) + quotient_pdf_type quotient_and_pdf_wo_clamps(sample_type _sample, isotropic_type interaction) { - Scalar pdf; - Scalar q = projected_sphere_quotient_and_pdf(pdf, _sample.NdotL); - return quotient_and_pdf::create(SpectralBins(q), pdf); + scalar_type pdf; + scalar_type q = projected_sphere_quotient_and_pdf(pdf, _sample.NdotL); + return quotient_pdf_type::create(spectral_type(q), pdf); } - template && Sample && surface_interactions::Anisotropic) - quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction) + quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction) { - Scalar pdf; - Scalar q = projected_sphere_quotient_and_pdf(pdf, abs(_sample.NdotL)); - return quotient_and_pdf::create(SpectralBins(q), pdf); + scalar_type pdf; + scalar_type q = projected_sphere_quotient_and_pdf(pdf, abs(_sample.NdotL)); + return quotient_pdf_type::create(spectral_type(q), pdf); } }; @@ -119,78 +119,96 @@ struct SLambertianBxDF // microfacet bxdfs // the dielectric ones don't fit the concept at all :( -template) +template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SSmoothDielectricBxDF { - using vector_t3 = vector; - - static SSmoothDielectricBxDF create(vector_t3 eta) - { - SSmoothDielectricBxDF retval; + using this_t = SSmoothDielectricBxDF; + using scalar_type = typename LightSample::scalar_type + using vector3_type = vector; + using params_t = SBxDFParams; + + using isotropic_type = typename IsoCache::isotropic_type; + using anisotropic_type = typename AnisoCache::anisotropic_type + using sample_type = LightSample; + using spectral_type = vector; // TODO: most likely change this + using quotient_pdf_type = quotient_and_pdf; + using isocache_type = IsoCache; + using anisocache_type = AnisoCache; + + static this_t create(vector3_type eta) + { + this_t retval; retval.eta = eta; return retval; } // where eval? - template) - LightSample __generate_wo_clamps(vector_t3 V, vector_t3 T, vector_t3 B, vector_t3 N, bool backside, Scalar NdotV, Scalar absNdotV, Scalar NdotV2, inout vector_t3 u, Scalar rcpOrientedEta, Scalar orientedEta2, Scalar rcpOrientedEta2, out bool transmitted) + sample_type __generate_wo_clamps(vector3_type V, vector3_type T, vector3_type B, vector3_type N, bool backside, scalar_type NdotV, scalar_type absNdotV, scalar_type NdotV2, inout vector3_type u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, out bool transmitted) { - const vector_t3 reflectance = fresnelDielectric_common(orientedEta2, absNdotV); + const vector3_type reflectance = fresnelDielectric_common(orientedEta2, absNdotV); - Scalar rcpChoiceProb; + scalar_type rcpChoiceProb; transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); - const vector_t3 L = math::reflectRefract(transmitted, V, N, backside, NdotV, NdotV2, rcpOrientedEta, rcpOrientedEta2); - return LightSample::create(L, dot(V, L), T, B, N); + const vector3_type L = math::reflectRefract(transmitted, V, N, backside, NdotV, NdotV2, rcpOrientedEta, rcpOrientedEta2); + return sample_type::create(L, dot(V, L), T, B, N); } - template && surface_interactions::Anisotropic) - LightSample generate_wo_clamps(Aniso interaction, inout vector u) // TODO: check vec3? + sample_type generate_wo_clamps(anisotropic_type interaction, inout vector u) // TODO: check vec3? { - Scalar orientedEta, rcpOrientedEta; - const bool backside = math::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.NdotV, eta); + scalar_type orientedEta, rcpOrientedEta; + const bool backside = math::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.NdotV, eta); bool dummy; - return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, backside, interaction.NdotV, + return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, backside, interaction.NdotV, interaction.NdotV, interaction.NdotV*interaction.NdotV, u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, dummy); } - template && surface_interactions::Anisotropic) - LightSample generate(Aniso interaction, inout vector u) + sample_type generate(anisotropic_type interaction, inout vector u) { - Scalar orientedEta, rcpOrientedEta; - const bool backside = math::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.NdotV, eta); + scalar_type orientedEta, rcpOrientedEta; + const bool backside = math::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.NdotV, eta); bool dummy; - return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, backside, interaction.NdotV, + return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, backside, interaction.NdotV, abs(interaction.NdotV), interaction.NdotV*interaction.NdotV, u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, dummy); } // where pdf? - template && Sample && surface_interactions::Isotropic) - quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction) + quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction) { const bool transmitted = isTransmissionPath(interaction.NdotV, _sample.NdotL); - Scalar dummy, rcpOrientedEta; - const bool backside = math::getOrientedEtas(dummy, rcpOrientedEta, interaction.NdotV, eta); + scalar_type dummy, rcpOrientedEta; + const bool backside = math::getOrientedEtas(dummy, rcpOrientedEta, interaction.NdotV, eta); - const Scalar pdf = 1.0 / 0.0; - Scalar quo = transmitted ? rcpOrientedEta2 : 1.0; - return quotient_and_pdf::create(SpectralBins(quo), pdf); + const scalar_type pdf = 1.0 / 0.0; + scalar_type quo = transmitted ? rcpOrientedEta2 : 1.0; + return quotient_pdf_type::create(spectral_type(quo), pdf); } - vector_t3 eta; + vector3_type eta; }; -template) -struct SSmoothDielectricBxDF +template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) +struct SSmoothDielectricBxDF { - using vector_t3 = vector; - - static SSmoothDielectricBxDF create(vector_t3 eta2, vector_t3 luminosityContributionHint) - { - SSmoothDielectricBxDF retval; + using this_t = SSmoothDielectricBxDF; + using scalar_type = typename LightSample::scalar_type + using vector3_type = vector; + using params_t = SBxDFParams; + + using isotropic_type = typename IsoCache::isotropic_type; + using anisotropic_type = typename AnisoCache::anisotropic_type + using sample_type = LightSample; + using spectral_type = vector; // TODO: most likely change this + using quotient_pdf_type = quotient_and_pdf; + using isocache_type = IsoCache; + using anisocache_type = AnisoCache; + + static this_t create(vector3_type eta2, vector3_type luminosityContributionHint) + { + this_t retval; retval.eta2 = eta2; retval.luminosityContributionHint = luminosityContributionHint; return retval; @@ -202,273 +220,523 @@ struct SSmoothDielectricBxDF // its basically a set of weights that determine // assert(1.0==luminosityContributionHint.r+luminosityContributionHint.g+luminosityContributionHint.b); // `remainderMetadata` is a variable which the generator function returns byproducts of sample generation that would otherwise have to be redundantly calculated `remainder_and_pdf` - template) - LightSample __generate_wo_clamps(vector_t3 V, vector_t3 T, vector_t3 B, vector_t3 N, Scalar NdotV, Scalar absNdotV, inout vector_t3 u, vector_t3 eta2, vector_t3 luminosityContributionHint, out vector_t3 remainderMetadata) + sample_type __generate_wo_clamps(vector3_type V, vector3_type T, vector3_type B, vector3_type N, scalar_type NdotV, scalar_type absNdotV, inout vector3_type u, vector3_type eta2, vector3_type luminosityContributionHint, out vector3_type remainderMetadata) { // we will only ever intersect from the outside - const vector_t3 reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2,absNdotV)); + const vector3_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2,absNdotV)); // we are only allowed one choice for the entire ray, so make the probability a weighted sum - const Scalar reflectionProb = dot(reflectance, luminosityContributionHint); + const scalar_type reflectionProb = dot(reflectance, luminosityContributionHint); - Scalar rcpChoiceProb; + scalar_type rcpChoiceProb; const bool transmitted = math::partitionRandVariable(reflectionProb, u.z, rcpChoiceProb); - remainderMetadata = (transmitted ? ((vector_t3)(1.0) - reflectance) : reflectance) * rcpChoiceProb; + remainderMetadata = (transmitted ? ((vector3_type)(1.0) - reflectance) : reflectance) * rcpChoiceProb; - const vector_t3 L = (transmitted ? (vector_t3)(0.0) : N * 2.0 * NdotV) - V; - return LightSample::create(L, dot(V, L), T, B, N); + const vector3_type L = (transmitted ? (vector3_type)(0.0) : N * 2.0 * NdotV) - V; + return sample_type::create(L, dot(V, L), T, B, N); } - template && surface_interactions::Anisotropic) - LightSample generate_wo_clamps(Aniso interaction, inout vector u) // TODO: check vec3? + sample_type generate_wo_clamps(anisotropic_type interaction, inout vector u) // TODO: check vec3? { - return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, interaction.NdotV, interaction.NdotV, u, eta2, luminosityContributionHint); + return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, interaction.NdotV, interaction.NdotV, u, eta2, luminosityContributionHint); } - template && surface_interactions::Anisotropic) - LightSample generate(Aniso interaction, inout vector u) + sample_type generate(anisotropic_type interaction, inout vector u) { - return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, interaction.NdotV, abs(interaction.NdotV), u, eta2, luminosityContributionHint); + return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, interaction.NdotV, abs(interaction.NdotV), u, eta2, luminosityContributionHint); } // where pdf? - template && Sample && surface_interactions::Isotropic) - quotient_and_pdf quotient_and_pdf_wo_clamps(LightSample _sample, Iso interaction) + quotient_pdf_type quotient_and_pdf_wo_clamps(sample_type _sample, isotropic_type interaction) { const bool transmitted = isTransmissionPath(interaction.NdotV, _sample.NdotL); - const vec3 reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, interaction.NdotV)); - const vec3 sampleValue = transmitted ? ((vector_t3)(1.0) - reflectance) : reflectance; + const vec3 reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, interaction.NdotV)); + const vec3 sampleValue = transmitted ? ((vector3_type)(1.0) - reflectance) : reflectance; - const Scalar sampleProb = dot(sampleValue,luminosityContributionHint); + const scalar_type sampleProb = dot(sampleValue,luminosityContributionHint); - const Scalar pdf = 1.0 / 0.0; - return quotient_and_pdf::create(SpectralBins(sampleValue / sampleProb), pdf); + const scalar_type pdf = 1.0 / 0.0; + return quotient_pdf_type::create(spectral_type(sampleValue / sampleProb), pdf); } - template && Sample && surface_interactions::Isotropic) - quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction) + quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction) { const bool transmitted = isTransmissionPath(interaction.NdotV, _sample.NdotL); - const vec3 reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, abs(interaction.NdotV))); - const vec3 sampleValue = transmitted ? ((vector_t3)(1.0) - reflectance) : reflectance; + const vec3 reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, abs(interaction.NdotV))); + const vec3 sampleValue = transmitted ? ((vector3_type)(1.0) - reflectance) : reflectance; - const Scalar sampleProb = dot(sampleValue,luminosityContributionHint); + const scalar_type sampleProb = dot(sampleValue,luminosityContributionHint); - const Scalar pdf = 1.0 / 0.0; - return quotient_and_pdf::create(SpectralBins(sampleValue / sampleProb), pdf); + const scalar_type pdf = 1.0 / 0.0; + return quotient_pdf_type::create(spectral_type(sampleValue / sampleProb), pdf); } - vector_t3 eta2; - vector_t3 luminosityContributionHint; + vector3_type eta2; + vector3_type luminosityContributionHint; }; -template) +template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SBeckmannDielectricBxDF { - using vector_t3 = vector; - using vector_t2 = vector; - using matrix_t3x3 = matrix; - using params_t = SBxDFParams; - - static SBeckmannDielectricBxDF create(vector_t3 eta, Scalar A) - { - SBeckmannDielectricBxDF retval; + using this_t = SBeckmannDielectricBxDF; + using scalar_type = typename LightSample::scalar_type + using vector2_type = vector; + using vector3_type = vector; + using matrix3x3_type = matrix; + using params_t = SBxDFParams; + + using isotropic_type = typename IsoCache::isotropic_type; + using anisotropic_type = typename AnisoCache::anisotropic_type + using sample_type = LightSample; + using spectral_type = vector; // TODO: most likely change this + using quotient_pdf_type = quotient_and_pdf; + using isocache_type = IsoCache; + using anisocache_type = AnisoCache; + + static this_t create(vector3_type eta, scalar_type A) + { + this_t retval; retval.eta = eta; - retval.A = vector_t2(A, A); + retval.A = vector2_type(A, A); return retval; } - static SBeckmannDielectricBxDF create(vector_t3 eta, Scalar ax, Scalar ay) + static this_t create(vector3_type eta, scalar_type ax, scalar_type ay) { - SBeckmannDielectricBxDF retval; + this_t retval; retval.eta = eta; - retval.A = vector_t2(ax, ay); + retval.A = vector2_type(ax, ay); return retval; } - template && surface_interactions::Isotropic && IsotropicMicrofacetCache) - vector_t3 eval(LightSample _sample, Iso interaction, Cache cache) + vector3_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) { - float orientedEta, dummy; - const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); - const float orientedEta2 = orientedEta * orientedEta; + scalar_type orientedEta, dummy; + const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); + const scalar_type orientedEta2 = orientedEta * orientedEta; - const float VdotHLdotH = cache.VdotH * cache.LdotH; + const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - matrix dummyior; - params_t params = params_t::template create(_sample, interaction, cache); - reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, dummyior); - const float scalar_part = beckmann::template __eval_DG_wo_clamps(params); + matrix dummyior; + params_t params = params_t::template create(_sample, interaction, cache); + reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, dummyior); + const scalar_type scalar_part = beckmann.template __eval_DG_wo_clamps(params); - return fresnelDielectric_common(orientedEta2, abs(cache.VdotH)) * microfacet_to_light_measure_transform(scalar_part,abs(interaction.NdotV),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,abs(interaction.NdotV),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); + return fresnelDielectric_common(orientedEta2, abs(cache.VdotH)) * microfacet_transform(); } - template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - vector_t3 eval(LightSample _sample, Aniso interaction, Cache cache) + vector3_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) { - float orientedEta, dummy; - const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); - const float orientedEta2 = orientedEta * orientedEta; + scalar_type orientedEta, dummy; + const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); + const scalar_type orientedEta2 = orientedEta * orientedEta; - const float VdotHLdotH = cache.VdotH * cache.LdotH; + const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - matrix dummyior; - params_t params = params_t::template create(_sample, interaction, cache); - reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior); - const float scalar_part = beckmann::template __eval_DG_wo_clamps(params); + matrix dummyior; + params_t params = params_t::template create(_sample, interaction, cache); + reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior); + const scalar_type scalar_part = beckmann.template __eval_DG_wo_clamps(params); - return fresnelDielectric_common(orientedEta2, abs(cache.VdotH)) * microfacet_to_light_measure_transform(scalar_part,abs(interaction.NdotV),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,abs(interaction.NdotV),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); + return fresnelDielectric_common(orientedEta2, abs(cache.VdotH)) * microfacet_transform(); } - template && AnisotropicMicrofacetCache) - LightSample __generate_wo_clamps(vector_t3 localV, bool backside, vector_t3 H, matrix_t3x3 m, inout vector_t3 u, Scalar rcpOrientedEta, Scalar orientedEta2, Scalar rcpOrientedEta2, out Cache cache) + sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix_t3x3 m, inout vector3_type u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, out anisocache_type cache) { - const Scalar VdotH = dot(localV,H); - const Scalar reflectance = fresnelDielectric_common(orientedEta2,abs(VdotH)); + const scalar_type VdotH = dot(localV,H); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2,abs(VdotH)); - Scalar rcpChoiceProb; + scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); - vec3 localL; - cache = Aniso::create(localV, H); + cache = anisocache_type::create(localV, H); - const Scalar VdotH = cache.VdotH; - cache.LdotH = transmitted ? nbl_glsl_refract_compute_NdotT(VdotH<0.0,VdotH*VdotH,rcpOrientedEta2):VdotH; - tangentSpaceL = math::reflectRefract_impl(transmitted, tangentSpaceV, tangentSpaceH, VdotH, cache.LdotH, rcpOrientedEta); + const scalar_type VdotH = cache.VdotH; + cache.LdotH = transmitted ? reflectRefract_computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; + vector3_type localL = math::reflectRefract_impl(transmitted, tangentSpaceV, tangentSpaceH, VdotH, cache.LdotH, rcpOrientedEta); - return LightSample::createTangentSpace(localV, localL, m); + return sample_type::createTangentSpace(localV, localL, m); } - template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - LightSample generate(Aniso interaction, inout vector u, out Cache cache) + sample_type generate(anisotropic_type interaction, inout vector3_type u, out anisocache_type cache) { - const vector_t3 localV = interaction.getTangentSpaceV(); + const vector3_type localV = interaction.getTangentSpaceV(); - Scalar orientedEta, rcpOrientedEta; - const bool backside = math::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.NdotV, eta); + scalar_type orientedEta, rcpOrientedEta; + const bool backside = math::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.NdotV, eta); - const vector_t3 upperHemisphereV = backside ? -localV : localV; + const vector3_type upperHemisphereV = backside ? -localV : localV; - matrix dummyior; - reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior); - const vector_t3 H = beckmann.__generate(upperHemisphereV, u.xy); + matrix dummyior; + reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior); + const vector3_type H = beckmann.__generate(upperHemisphereV, u.xy); - return __generate_wo_clamps(localV, backside, H, interaction.getTangentFrame(), rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, cache); + return __generate_wo_clamps(localV, backside, H, interaction.getTangentFrame(), rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, cache); } - template && surface_interactions::Anisotropic) - LightSample generate(Aniso interaction, inout vector u) + sample_type generate(anisotropic_type interaction, inout vector3_type u) { - SAnisotropicMicrofacetCache dummycache; - return generate >(interaction, u, dummycache); + anisocache_type dummycache; + return generate(interaction, u, dummycache); } - Scalar pdf_wo_clamps(bool transmitted, Scalar reflectance, Scalar ndf, Scalar absNdotV, Scalar NdotV2, Scalar VdotH, Scalar LdotH, Scalar VdotHLdotH, Scalar orientedEta, out Scalar onePlusLambda_V) + scalar_type pdf_wo_clamps(bool transmitted, scalar_type reflectance, scalar_type ndf, scalar_type absNdotV, scalar_type NdotV2, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, out scalar_type onePlusLambda_V) { - const Scalar lambda = smith::beckmann_Lambda(NdotV2, A.x*A.x); - return smith::VNDF_pdf_wo_clamps(ndf,lambda,absNdotV,transmitted,VdotH,LdotH,VdotHLdotH,orientedEta,reflectance,onePlusLambda_V); + smith::Beckmann beckmann_smith; + const scalar_type lambda = beckmann_smith.Lambda(NdotV2, A.x*A.x); + return smith::VNDF_pdf_wo_clamps >(ndf,lambda,absNdotV,transmitted,VdotH,LdotH,VdotHLdotH,orientedEta,reflectance,onePlusLambda_V); } - Scalar pdf_wo_clamps(bool transmitted, Scalar reflectance, Scalar ndf, Scalar absNdotV, Scalar TdotV2, Scalar BdotV2, Scalar NdotV2, Scalar VdotH, Scalar LdotH, Scalar VdotHLdotH, Scalar ax2, Scalar ay2, Scalar orientedEta, out Scalar onePlusLambda_V) + scalar_type pdf_wo_clamps(bool transmitted, scalar_type reflectance, scalar_type ndf, scalar_type absNdotV, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type ax2, scalar_type ay2, scalar_type orientedEta, out scalar_type onePlusLambda_V) { - Scalar c2 = smith::beckmann_C2(TdotV2, BdotV2, NdotV2, ax2, ay2); - Scalar lambda = smith::beckmann_Lambda(c2); - return smith::VNDF_pdf_wo_clamps(ndf,lambda,absNdotV,transmitted,VdotH,LdotH,VdotHLdotH,orientedEta,reflectance,onePlusLambda_V); + smith::Beckmann beckmann_smith; + scalar_type c2 = beckmann_smith.C2(TdotV2, BdotV2, NdotV2, ax2, ay2); + scalar_type lambda = beckmann_smith.Lambda(c2); + return smith::VNDF_pdf_wo_clamps >(ndf,lambda,absNdotV,transmitted,VdotH,LdotH,VdotHLdotH,orientedEta,reflectance,onePlusLambda_V); } - template && surface_interactions::Isotropic && IsotropicMicrofacetCache) - Scalar pdf(LightSample _sample, Iso interaction, Cache cache) + scalar_type pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) { - Scalar ndf = ndf::beckmann(A.x*A.x, cache.NdotH2); + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(A.x*A.x, cache.NdotH2); + ndf::Beckmann beckmann_ndf; + scalar_type ndf = beckmann_ndf(ndfparams); - Scalar orientedEta, dummy; - const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); - const Scalar orientedEta2 = orientedEta * orientedEta; + scalar_type orientedEta, dummy; + const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); + const scalar_type orientedEta2 = orientedEta * orientedEta; - const float VdotHLdotH = cache.VdotH * cache.LdotH; + const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const Scalar reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); - const Scalar absNdotV = abs(interaction.NdotV); + const scalar_type absNdotV = abs(interaction.NdotV); return pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, interaction.NdotV2, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta, dummy); } - template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - Scalar pdf(LightSample _sample, Aniso interaction, Cache cache) + scalar_type pdf(sample_type _sample, anisotropic_type interaction, anisocache_type cache) { - const Scalar ax2 = A.x*A.x; - const Scalar ay2 = A.y*A.y; - params_t params = params_t::template create(_sample, interaction, cache); + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; + params_t params = params_t::template create(_sample, interaction, cache); - Scalar ndf = ndf::beckmann(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + ndf::Beckmann beckmann_ndf; + scalar_type ndf = backmann_ndf(ndfparams); - Scalar orientedEta, dummy; - const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); - const Scalar orientedEta2 = orientedEta * orientedEta; + scalar_type orientedEta, dummy; + const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); + const scalar_type orientedEta2 = orientedEta * orientedEta; - const float VdotHLdotH = cache.VdotH * cache.LdotH; + const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const Scalar reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); - const Scalar absNdotV = abs(interaction.NdotV); + const scalar_type absNdotV = abs(interaction.NdotV); return pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.VdotH, cache.LdotH, VdotHLdotH, ax2, ay2, orientedEta, dummy); } - template && Sample && surface_interactions::Isotropic && IsotropicMicrofacetCache) - quotient_and_pdf quotient_and_pdf(LightSample _sample, Iso interaction, Cache cache) + quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) { - Scalar ndf = ndf::beckmann(A.x*A.x, cache.NdotH2); + const scalar_type a2 = A.x*A.x; + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, cache.NdotH2); + ndf::Beckmann beckmann_ndf; + scalar_type ndf = beckmann_ndf(ndfparams); - Scalar orientedEta, dummy; - const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); - const Scalar orientedEta2 = orientedEta * orientedEta; + scalar_type orientedEta, dummy; + const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); + const scalar_type orientedEta2 = orientedEta * orientedEta; - const float VdotHLdotH = cache.VdotH * cache.LdotH; + const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const Scalar reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); - const Scalar absNdotV = abs(interaction.NdotV); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + const scalar_type absNdotV = abs(interaction.NdotV); - float onePlusLambda_V; - pdf = pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, interaction.NdotV2, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta, dummy); - Scalar quo = smith::beckmann_smith_G2_over_G1(onePlusLambda_V, NdotL2, a2); + scalar_type onePlusLambda_V; + scalar_type pdf = pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, interaction.NdotV2, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta, dummy); - return quotient_and_pdf::create(SpectralBins(quo), pdf); + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, 0, _sample.NdotL2, onePlusLambda_V); + smith::Beckmann beckmann_smith; + scalar_type quo = beckmann_smith.G2_over_G1(smithparams); + + return quotient_pdf_type::create(spectral_type(quo), pdf); } - template && Sample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - quotient_and_pdf quotient_and_pdf(LightSample _sample, Aniso interaction, Cache cache) + quotient_pdf_type quotient_and_pdf(sample_type _sample, anisotropic_type interaction, anisocache_type cache) { - const Scalar ax2 = A.x*A.x; - const Scalar ay2 = A.y*A.y; - params_t params = params_t::template create(_sample, interaction, cache); + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; + params_t params = params_t::template create(_sample, interaction, cache); - Scalar ndf = ndf::beckmann(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + ndf::Beckmann beckmann_ndf; + scalar_type ndf = backmann_ndf(ndfparams); - Scalar orientedEta, dummy; - const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); - const Scalar orientedEta2 = orientedEta * orientedEta; + scalar_type orientedEta, dummy; + const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); + const scalar_type orientedEta2 = orientedEta * orientedEta; - const float VdotHLdotH = cache.VdotH * cache.LdotH; + const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const Scalar reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); - const Scalar absNdotV = abs(interaction.NdotV); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + const scalar_type absNdotV = abs(interaction.NdotV); + + scalar_type onePlusLambda_V; + scalar_type pdf = pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.VdotH, cache.LdotH, VdotHLdotH, ax2, ay2, orientedEta, dummy); + + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, onePlusLambda_V); + smith::Beckmann beckmann_smith; + scalar_type quo = beckmann_smith.G2_over_G1(smithparams); + + return quotient_pdf_type::create(spectral_type(quo), pdf); + } + + vector2_type A; + vector3_type eta; +}; + +template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) +struct SGGXDielectricBxDF +{ + using this_t = SGGXDielectricBxDF; + using scalar_type = typename LightSample::scalar_type + using vector2_type = vector; + using vector3_type = vector; + using matrix3x3_type = matrix; + using params_t = SBxDFParams; + + using isotropic_type = typename IsoCache::isotropic_type; + using anisotropic_type = typename AnisoCache::anisotropic_type + using sample_type = LightSample; + using spectral_type = vector; // TODO: most likely change this + using quotient_pdf_type = quotient_and_pdf; + using isocache_type = IsoCache; + using anisocache_type = AnisoCache; + + static this_t create(vector3_type eta, scalar_type A) + { + this_t retval; + retval.eta = eta; + retval.A = vector2_type(A, A); + return retval; + } + + static this_t create(vector3_type eta, scalar_type ax, scalar_type ay) + { + this_t retval; + retval.eta = eta; + retval.A = vector2_type(ax, ay); + return retval; + } + + vector3_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) + { + scalar_type orientedEta, dummy; + const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); + const scalar_type orientedEta2 = orientedEta * orientedEta; - float onePlusLambda_V; - pdf = pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.VdotH, cache.LdotH, VdotHLdotH, ax2, ay2, orientedEta, dummy); - Scalar quo = smith::beckmann_smith_G2_over_G1(onePlusLambda_V, TdotL2, BdotL2, NdotL2, ax2, ay2); + const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; + const bool transmitted = VdotHLdotH < 0.0; + + matrix dummyior; + params_t params = params_t::template create(_sample, interaction, cache); + reflection::GGX ggx = reflection::GGX::create(A.x, dummyior); + const scalar_type NG_already_in_reflective_dL_measure = ggx.template __eval_DG_wo_clamps(params); + + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,abs(_sample.NdotL),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); + return fresnelDielectric_common(orientedEta2, abs(cache.VdotH)) * microfacet_transform(); + } + + vector3_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) + { + scalar_type orientedEta, dummy; + const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); + const scalar_type orientedEta2 = orientedEta * orientedEta; + + const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; + const bool transmitted = VdotHLdotH < 0.0; + + matrix dummyior; + params_t params = params_t::template create(_sample, interaction, cache); + reflection::GGX ggx = reflection::GGX::create(A.x, A.y dummyior); + const scalar_type NG_already_in_reflective_dL_measure = ggx.template __eval_DG_wo_clamps(params); + + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,abs(_sample.NdotL),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); + return fresnelDielectric_common(orientedEta2, abs(cache.VdotH)) * microfacet_transform(); + } + + sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix_t3x3 m, inout vector3_type u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, out anisocache_type cache) + { + const scalar_type VdotH = dot(localV,H); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2,abs(VdotH)); + + scalar_type rcpChoiceProb; + bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); + + cache = anisocache_type::create(localV, H); + + const scalar_type VdotH = cache.VdotH; + cache.LdotH = transmitted ? reflectRefract_computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; + vector3_type localL = math::reflectRefract_impl(transmitted, tangentSpaceV, tangentSpaceH, VdotH, cache.LdotH, rcpOrientedEta); + + return sample_type::createTangentSpace(localV, localL, m); + } + + sample_type generate(anisotropic_type interaction, inout vector3_type u, out anisocache_type cache) + { + const vector3_type localV = interaction.getTangentSpaceV(); + + scalar_type orientedEta, rcpOrientedEta; + const bool backside = math::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.NdotV, eta); + + const vector3_type upperHemisphereV = backside ? -localV : localV; + + matrix dummyior; + reflection::SGGXBxDF ggx = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior); + const vector3_type H = ggx.__generate(upperHemisphereV, u.xy); + + return __generate_wo_clamps(localV, backside, H, interaction.getTangentFrame(), rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, cache); + } + + sample_type generate(anisotropic_type interaction, inout vector3_type u) + { + anisocache_type dummycache; + return generate(interaction, u, dummycache); + } + + scalar_type pdf_wo_clamps(bool transmitted, scalar_type reflectance, scalar_type ndf, scalar_type devsh_v, scalar_type absNdotV, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) + { + smith::GGX ggx_smith; + const scalar_type lambda = ggx_smith.G1_wo_numerator(absNdotV, A.x*A.x); + return smith::VNDF_pdf_wo_clamps(ndf,lambda,absNdotV,transmitted,VdotH,LdotH,VdotHLdotH,orientedEta,reflectance); + } + + scalar_type pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) + { + const scalar_type a2 = A.x*A.x; + params_t params = params_t::template create(_sample, interaction, cache); + + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotV, params.NdotV2, params.NdotL, params.NdotL2); + ndf::GGX ggx_ndf; + scalar_type ndf = ggx_ndf(ndfparams); + + smith::GGX ggx_smith; + const scalar_type devsh_v = ggx_smith.devsh_part(params.NdotV2, a2, 1.0-a2); + + scalar_type orientedEta, dummy; + const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); + const scalar_type orientedEta2 = orientedEta * orientedEta; + + const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; + const bool transmitted = VdotHLdotH < 0.0; + + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + + const scalar_type absNdotV = abs(interaction.NdotV); + return pdf_wo_clamps(transmitted, reflectance, ndf, devsh_v, absNdotV, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta); + } + + scalar_type pdf(sample_type _sample, anisotropic_type interaction, anisocache_type cache) + { + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; + params_t params = params_t::template create(_sample, interaction, cache); + + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + ndf::GGX ggx_ndf; + scalar_type ndf = ggx_ndf(ndfparams); + + smith::GGX ggx_smith; + const scalar_type devsh_v = ggx_smith.devsh_part(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); + + scalar_type orientedEta, dummy; + const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); + const scalar_type orientedEta2 = orientedEta * orientedEta; + + const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; + const bool transmitted = VdotHLdotH < 0.0; + + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + + const scalar_type absNdotV = abs(interaction.NdotV); + return pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.VdotH, cache.LdotH, VdotHLdotH, ax2, ay2, orientedEta, dummy); + } + + quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) + { + const scalar_type a2 = A.x*A.x; + params_t params = params_t::template create(_sample, interaction, cache); + + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotV, params.NdotV2, params.NdotL, params.NdotL2); + ndf::GGX ggx_ndf; + scalar_type ndf = ggx_ndf(ndfparams); + + smith::GGX ggx_smith; + const scalar_type devsh_v = ggx_smith.devsh_part(params.NdotV2, a2, 1.0-a2); + + scalar_type orientedEta, dummy; + const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); + const scalar_type orientedEta2 = orientedEta * orientedEta; + + const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; + const bool transmitted = VdotHLdotH < 0.0; + + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + + const scalar_type absNdotV = abs(interaction.NdotV); + scalar_type pdf = pdf_wo_clamps(transmitted, reflectance, ndf, devsh_v, absNdotV, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta); + + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.NdotV, params.NdotV2, params.NdotL, params.NdotL2); + scalar_type quo = ggx_smith.G2_over_G1(smithparams); + + return quotient_pdf_type::create(spectral_type(quo), pdf); + } + + quotient_pdf_type quotient_and_pdf(sample_type _sample, anisotropic_type interaction, anisocache_type cache) + { + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; + params_t params = params_t::template create(_sample, interaction, cache); + + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + ndf::GGX ggx_ndf; + scalar_type ndf = ggx_ndf(ndfparams); + + smith::GGX ggx_smith; + const scalar_type devsh_v = ggx_smith.devsh_part(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); + + scalar_type orientedEta, dummy; + const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); + const scalar_type orientedEta2 = orientedEta * orientedEta; + + const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; + const bool transmitted = VdotHLdotH < 0.0; + + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + const scalar_type absNdotV = abs(interaction.NdotV); + + scalar_type pdf = pdf_wo_clamps(transmitted, reflectance, ndf, devsh_v, absNdotV, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta); + + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, absNdotV, params.TdotV2, params.BdotV2, params.NdotV2, abs(params.NdotL), params.TdotL2, params.BdotL2, params.NdotL2); + scalar_type quo = ggx_smith.G2_over_G1(smithparams); - return quotient_and_pdf::create(SpectralBins(quo), pdf); + return quotient_pdf_type::create(spectral_type(quo), pdf); } - vector_t2 A; - vector_t3 eta; + vector2_type A; + vector3_type eta; }; } From e8d5aa326c2c14766fcb07f33e973295bd69d027 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 13 Dec 2024 17:30:22 +0700 Subject: [PATCH 027/188] changes for cpp compat --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 46 +++++++++---------- include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl | 2 +- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 4 +- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 14 +++--- include/nbl/builtin/hlsl/math/functions.hlsl | 12 ++--- 5 files changed, 39 insertions(+), 39 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index e07e331379..c31da51e59 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -42,7 +42,7 @@ template) T computeMicrofacetNormal(bool _refract, vector V, vector L, T orientedEta) { const vector H = computeUnnormalizedMicrofacetNormal(_refract,V,L,orientedEta); - const T unnormRcpLen = rsqrt(dot(H,H)); + const T unnormRcpLen = rsqrt(dot(H,H)); return H * unnormRcpLen; } @@ -156,7 +156,7 @@ struct SIsotropic SIsotropic retval; retval.V = normalizedV; retval.N = normalizedN; - retval.NdotV = dot(retval.N, retval.V.getDirection()); + retval.NdotV = dot(retval.N, retval.V.getDirection()); retval.NdotV2 = retval.NdotV * retval.NdotV; return retval; @@ -222,8 +222,8 @@ struct SAnisotropic : SIsotropic retval.B = normalizedB; const vector3_type V = retval.getDirection(); - retval.TdotV = dot(V, retval.T); - retval.BdotV = dot(V, retval.B); + retval.TdotV = dot(V, retval.T); + retval.BdotV = dot(V, retval.B); return retval; } @@ -318,7 +318,7 @@ struct SLightSample this_t retval; retval.L = RayDirInfo::transform(tangentSpaceL,tangentFrame); - retval.VdotL = dot(tangentSpaceV,tangentSpaceL); + retval.VdotL = dot(tangentSpaceV,tangentSpaceL); retval.TdotL = tangentSpaceL.x; retval.BdotL = tangentSpaceL.y; @@ -336,7 +336,7 @@ struct SLightSample retval.TdotL = nbl::hlsl::numeric_limits::signaling_NaN; retval.BdotL = nbl::hlsl::numeric_limits::signaling_NaN; - retval.NdotL = dot(N,L); + retval.NdotL = dot(N,L); retval.NdotL2 = retval.NdotL * retval.NdotL; return retval; @@ -345,8 +345,8 @@ struct SLightSample { this_t retval = create(L,VdotL,N); - retval.TdotL = dot(T,L); - retval.BdotL = dot(B,L); + retval.TdotL = dot(T,L); + retval.BdotL = dot(B,L); return retval; } @@ -355,14 +355,14 @@ struct SLightSample static this_t create(NBL_CONST_REF_ARG(vector3_type) L, NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction) { const vector3_type V = interaction.V.getDirection(); - const scalar_type VdotL = dot(V,L); + const scalar_type VdotL = dot(V,L); return create(L, VdotL, interaction.N); } template static this_t create(NBL_CONST_REF_ARG(vector3_type) L, NBL_CONST_REF_ARG(surface_interactions::SAnisotropic) interaction) { const vector3_type V = interaction.V.getDirection(); - const scalar_type VdotL = dot(V,L); + const scalar_type VdotL = dot(V,L); return create(L,VdotL,interaction.T,interaction.B,interaction.N); } // @@ -471,7 +471,7 @@ struct SIsotropicMicrofacetCache { // TODO: can we optimize? H = computeMicrofacetNormal(transmitted,V,L,orientedEta); - retval.NdotH = dot(N, H); + retval.NdotH = dot(N, H); // not coming from the medium (reflected) OR // exiting at the macro scale AND ( (not L outside the cone of possible directions given IoR with constraint VdotH*LdotH<0.0) OR (microfacet not facing toward the macrosurface, i.e. non heightfield profile of microsurface) ) @@ -479,8 +479,8 @@ struct SIsotropicMicrofacetCache if (valid) { // TODO: can we optimize? - retval.VdotH = dot(V,H); - retval.LdotH = dot(L,H); + retval.VdotH = dot(V,H); + retval.LdotH = dot(L,H); retval.NdotH2 = retval.NdotH * retval.NdotH; return true; } @@ -503,7 +503,7 @@ struct SIsotropicMicrofacetCache const vector3_type V = interaction.V.getDirection(); const vector3_type L = _sample.L; - const scalar_type VdotL = dot(V, L); + const scalar_type VdotL = dot(V, L); return compute(retval,transmitted,V,L,interaction.N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); } template && ray_dir_info::Basic) @@ -586,7 +586,7 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache { this_t retval; - retval.VdotH = dot(tangentSpaceV,tangentSpaceH); + retval.VdotH = dot(tangentSpaceV,tangentSpaceH); retval.LdotH = retval.VdotH; retval.NdotH = tangentSpaceH.z; retval.NdotH2 = retval.NdotH*retval.NdotH; @@ -644,8 +644,8 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache const bool valid = this_t::compute(retval,transmitted,V,L,N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); if (valid) { - retval.TdotH = dot(T,H); - retval.BdotH = dot(B,H); + retval.TdotH = dot(T,H); + retval.BdotH = dot(B,H); } return valid; } @@ -661,8 +661,8 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache const bool valid = this_t::compute(retval,interaction,_sample,eta,H); if (valid) { - retval.TdotH = dot(interaction.T,H); - retval.BdotH = dot(interaction.B,H); + retval.TdotH = dot(interaction.T,H); + retval.BdotH = dot(interaction.B,H); } return valid; } @@ -969,7 +969,7 @@ struct ThinDielectricInfiniteScatter static vector __call(vector singleInterfaceReflectance) { const vector doubleInterfaceReflectance = singleInterfaceReflectance * singleInterfaceReflectance; - return lerp((singleInterfaceReflectance - doubleInterfaceReflectance) / ((vector)(1.0) - doubleInterfaceReflectance) * 2.0, (vector)(1.0), doubleInterfaceReflectance > (vector)(0.9999)); + return lerp((singleInterfaceReflectance - doubleInterfaceReflectance) / ((vector)(1.0) - doubleInterfaceReflectance) * 2.0, (vector)(1.0), doubleInterfaceReflectance > (vector)(0.9999)); } static T __call(T singleInterfaceReflectance) @@ -991,9 +991,9 @@ vector diffuseFresnelCorrectionFactor(vector n, vector n2) { // assert(n*n==n2); vector TIR = n < (vector)1.0; - vector invdenum = lerp((vector)1.0, (vector)1.0 / (n2 * n2 * ((vector)554.33 - 380.7 * n)), TIR); - vector num = n * lerp((vector)(0.1921156102251088), n * 298.25 - 261.38 * n2 + 138.43, TIR); - num += lerp((vector)(0.8078843897748912), (vector)(-1.67), TIR); + vector invdenum = lerp((vector)1.0, (vector)1.0 / (n2 * n2 * ((vector)554.33 - 380.7 * n)), TIR); + vector num = n * lerp((vector)(0.1921156102251088), n * 298.25 - 261.38 * n2 + 138.43, TIR); + num += lerp((vector)(0.8078843897748912), (vector)(-1.67), TIR); return num * invdenum; } diff --git a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl index 0129278df8..95042bf166 100644 --- a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl @@ -174,7 +174,7 @@ struct Beckmann scalar_type c = sqrt(c2); scalar_type nom = 1.0 - 1.259 * c + 0.396 * c2; scalar_type denom = 2.181 * c2 + 3.535 * c; - return lerp(0.0, nom / denom, c < 1.6); + return lerp(0.0, nom / denom, c < 1.6); } scalar_type Lambda(scalar_type NdotX2, scalar_type a2) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 5e14cd7a9b..702e855da6 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -489,8 +489,8 @@ struct SBeckmannBxDF } scalar_type sinTheta = sqrt(1.0 - V.z*V.z); - scalar_type cosPhi = sinTheta==0.0 ? 1.0 : clamp(V.x/sinTheta, -1.0, 1.0); - scalar_type sinPhi = sinTheta==0.0 ? 0.0 : clamp(V.y/sinTheta, -1.0, 1.0); + scalar_type cosPhi = sinTheta==0.0 ? 1.0 : clamp(V.x/sinTheta, -1.0, 1.0); + scalar_type sinPhi = sinTheta==0.0 ? 0.0 : clamp(V.y/sinTheta, -1.0, 1.0); //rotate scalar_type tmp = cosPhi*slope.x - sinPhi*slope.y; slope.y = sinPhi*slope.x + cosPhi*slope.y; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index 056394323d..377d277339 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -152,7 +152,7 @@ struct SSmoothDielectricBxDF transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); const vector3_type L = math::reflectRefract(transmitted, V, N, backside, NdotV, NdotV2, rcpOrientedEta, rcpOrientedEta2); - return sample_type::create(L, dot(V, L), T, B, N); + return sample_type::create(L, dot(V, L), T, B, N); } sample_type generate_wo_clamps(anisotropic_type interaction, inout vector u) // TODO: check vec3? @@ -226,14 +226,14 @@ struct SSmoothDielectricBxDF const vector3_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2,absNdotV)); // we are only allowed one choice for the entire ray, so make the probability a weighted sum - const scalar_type reflectionProb = dot(reflectance, luminosityContributionHint); + const scalar_type reflectionProb = dot(reflectance, luminosityContributionHint); scalar_type rcpChoiceProb; const bool transmitted = math::partitionRandVariable(reflectionProb, u.z, rcpChoiceProb); remainderMetadata = (transmitted ? ((vector3_type)(1.0) - reflectance) : reflectance) * rcpChoiceProb; const vector3_type L = (transmitted ? (vector3_type)(0.0) : N * 2.0 * NdotV) - V; - return sample_type::create(L, dot(V, L), T, B, N); + return sample_type::create(L, dot(V, L), T, B, N); } sample_type generate_wo_clamps(anisotropic_type interaction, inout vector u) // TODO: check vec3? @@ -254,7 +254,7 @@ struct SSmoothDielectricBxDF const vec3 reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, interaction.NdotV)); const vec3 sampleValue = transmitted ? ((vector3_type)(1.0) - reflectance) : reflectance; - const scalar_type sampleProb = dot(sampleValue,luminosityContributionHint); + const scalar_type sampleProb = dot(sampleValue,luminosityContributionHint); const scalar_type pdf = 1.0 / 0.0; return quotient_pdf_type::create(spectral_type(sampleValue / sampleProb), pdf); @@ -266,7 +266,7 @@ struct SSmoothDielectricBxDF const vec3 reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, abs(interaction.NdotV))); const vec3 sampleValue = transmitted ? ((vector3_type)(1.0) - reflectance) : reflectance; - const scalar_type sampleProb = dot(sampleValue,luminosityContributionHint); + const scalar_type sampleProb = dot(sampleValue,luminosityContributionHint); const scalar_type pdf = 1.0 / 0.0; return quotient_pdf_type::create(spectral_type(sampleValue / sampleProb), pdf); @@ -350,7 +350,7 @@ struct SBeckmannDielectricBxDF sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix_t3x3 m, inout vector3_type u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, out anisocache_type cache) { - const scalar_type VdotH = dot(localV,H); + const scalar_type VdotH = dot(localV,H); const scalar_type reflectance = fresnelDielectric_common(orientedEta2,abs(VdotH)); scalar_type rcpChoiceProb; @@ -579,7 +579,7 @@ struct SGGXDielectricBxDF sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix_t3x3 m, inout vector3_type u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, out anisocache_type cache) { - const scalar_type VdotH = dot(localV,H); + const scalar_type VdotH = dot(localV,H); const scalar_type reflectance = fresnelDielectric_common(orientedEta2,abs(VdotH)); scalar_type rcpChoiceProb; diff --git a/include/nbl/builtin/hlsl/math/functions.hlsl b/include/nbl/builtin/hlsl/math/functions.hlsl index bef105e318..3b2afa2318 100644 --- a/include/nbl/builtin/hlsl/math/functions.hlsl +++ b/include/nbl/builtin/hlsl/math/functions.hlsl @@ -4,7 +4,7 @@ #ifndef _NBL_BUILTIN_HLSL_MATH_FUNCTIONS_INCLUDED_ #define _NBL_BUILTIN_HLSL_MATH_FUNCTIONS_INCLUDED_ -#include +#include "nbl/builtin/hlsl/cpp_compat.hlsl" #include "nbl/builtin/hlsl/numbers.hlsl" #include "nbl/builtin/hlsl/spirv_intrinsics/core.hlsl" @@ -52,7 +52,7 @@ struct erfInv { static float __call(float _x) { - float x = clamp(_x, -0.99999, 0.99999); + float x = clamp(_x, -0.99999, 0.99999); float w = -log((1.0-x) * (1.0+x)); float p; if (w<5.0) @@ -139,7 +139,7 @@ struct lp_norm { static scalar_type_t __sum(const T v) { - return dot(v, v); // TODO: wait for overloaded dot? + return dot(v, v); // TODO: wait for overloaded dot? } static scalar_type_t __call(const T v) @@ -173,7 +173,7 @@ vector reflect(vector I, vector N, T NdotI) template ) vector reflect(vector I, vector N) { - T NdotI = dot(N, I); + T NdotI = dot(N, I); return reflect(I, N, NdotI); } @@ -256,7 +256,7 @@ struct refract this_t retval; retval.I = I; retval.N = N; - retval.NdotI = dot(N, I); + retval.NdotI = dot(N, I); T orientedEta; retval.backside = getOrientedEtas(orientedEta, retval.rcpOrientedEta, retval.NdotI, eta); retval.NdotI2 = retval.NdotI * retval.NdotI; @@ -500,7 +500,7 @@ struct trigonometry const bool ABltminusC = cosSumAB < (-tmp2); const bool ABltC = cosSumAB < tmp2; // apply triple angle formula - const float absArccosSumABC = acos(clamp(cosSumAB * tmp2 - (tmp0 * tmp4 + tmp3 * tmp1) * tmp5, -1.f, 1.f)); + const float absArccosSumABC = acos(clamp(cosSumAB * tmp2 - (tmp0 * tmp4 + tmp3 * tmp1) * tmp5, -1.f, 1.f)); return ((AltminusB ? ABltC : ABltminusC) ? (-absArccosSumABC) : absArccosSumABC) + (AltminusB | ABltminusC ? numbers::pi : (-numbers::pi)); } From d632b3a70dd65b43df119ceb488f5c31c3420339 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 16 Dec 2024 11:17:45 +0700 Subject: [PATCH 028/188] moved math functions to tgmath --- include/nbl/builtin/hlsl/math/functions.hlsl | 83 --------------- include/nbl/builtin/hlsl/tgmath.hlsl | 103 +++++++++++++++++++ 2 files changed, 103 insertions(+), 83 deletions(-) create mode 100644 include/nbl/builtin/hlsl/tgmath.hlsl diff --git a/include/nbl/builtin/hlsl/math/functions.hlsl b/include/nbl/builtin/hlsl/math/functions.hlsl index 3b2afa2318..87419517b8 100644 --- a/include/nbl/builtin/hlsl/math/functions.hlsl +++ b/include/nbl/builtin/hlsl/math/functions.hlsl @@ -15,89 +15,6 @@ namespace hlsl namespace math { -// TODO: move erfs to a tgmath.hlsl later -namespace impl -{ -template -struct erf; - -template<> -struct erf -{ - static float __call(float _x) - { - const float a1 = 0.254829592; - const float a2 = -0.284496736; - const float a3 = 1.421413741; - const float a4 = -1.453152027; - const float a5 = 1.061405429; - const float p = 0.3275911; - - float sign = sign(_x); - float x = abs(_x); - - float t = 1.0 / (1.0 + p*x); - float y = 1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * exp(-x * x); - - return sign * y; - } -}; - - -template -struct erfInv; - -template<> -struct erfInv -{ - static float __call(float _x) - { - float x = clamp(_x, -0.99999, 0.99999); - float w = -log((1.0-x) * (1.0+x)); - float p; - if (w<5.0) - { - w -= 2.5; - p = 2.81022636e-08; - p = 3.43273939e-07 + p*w; - p = -3.5233877e-06 + p*w; - p = -4.39150654e-06 + p*w; - p = 0.00021858087 + p*w; - p = -0.00125372503 + p*w; - p = -0.00417768164 + p*w; - p = 0.246640727 + p*w; - p = 1.50140941 + p*w; - } - else - { - w = sqrt(w) - 3.0; - p = -0.000200214257; - p = 0.000100950558 + p*w; - p = 0.00134934322 + p*w; - p = -0.00367342844 + p*w; - p = 0.00573950773 + p*w; - p = -0.0076224613 + p*w; - p = 0.00943887047 + p*w; - p = 1.00167406 + p*w; - p = 2.83297682 + p*w; - } - return p*x; - } -}; -} - -template -T erf(T _x) -{ - return impl::erf::__call(_x); -} - -template -T erfInv(T _x) -{ - return impl::erfInv::__call(_x); -} - namespace impl { template diff --git a/include/nbl/builtin/hlsl/tgmath.hlsl b/include/nbl/builtin/hlsl/tgmath.hlsl new file mode 100644 index 0000000000..80e06bda56 --- /dev/null +++ b/include/nbl/builtin/hlsl/tgmath.hlsl @@ -0,0 +1,103 @@ +// Copyright (C) 2022 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_BUILTIN_HLSL_TGMATH_INCLUDED_ +#define _NBL_BUILTIN_HLSL_TGMATH_INCLUDED_ + +#include +// C++ headers +#ifndef __HLSL_VERSION +#include +#endif + +namespace nbl +{ +namespace hlsl +{ + +namespace impl +{ +template +struct erf; + +template<> +struct erf +{ + static float __call(float _x) + { + const float a1 = 0.254829592; + const float a2 = -0.284496736; + const float a3 = 1.421413741; + const float a4 = -1.453152027; + const float a5 = 1.061405429; + const float p = 0.3275911; + + float sign = sign(_x); + float x = abs(_x); + + float t = 1.0 / (1.0 + p*x); + float y = 1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * exp(-x * x); + + return sign * y; + } +}; + + +template +struct erfInv; + +template<> +struct erfInv +{ + static float __call(float _x) + { + float x = clamp(_x, -0.99999, 0.99999); + float w = -log((1.0-x) * (1.0+x)); + float p; + if (w<5.0) + { + w -= 2.5; + p = 2.81022636e-08; + p = 3.43273939e-07 + p*w; + p = -3.5233877e-06 + p*w; + p = -4.39150654e-06 + p*w; + p = 0.00021858087 + p*w; + p = -0.00125372503 + p*w; + p = -0.00417768164 + p*w; + p = 0.246640727 + p*w; + p = 1.50140941 + p*w; + } + else + { + w = sqrt(w) - 3.0; + p = -0.000200214257; + p = 0.000100950558 + p*w; + p = 0.00134934322 + p*w; + p = -0.00367342844 + p*w; + p = 0.00573950773 + p*w; + p = -0.0076224613 + p*w; + p = 0.00943887047 + p*w; + p = 1.00167406 + p*w; + p = 2.83297682 + p*w; + } + return p*x; + } +}; +} + +template +T erf(T _x) +{ + return impl::erf::__call(_x); +} + +template +T erfInv(T _x) +{ + return impl::erfInv::__call(_x); +} + +} +} + +#endif From ffaaf87e160bfd0ad970ec0c9b4785fe9381388f Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 16 Dec 2024 11:48:04 +0700 Subject: [PATCH 029/188] rsqrt not in stl --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 4 ++-- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 2 +- include/nbl/builtin/hlsl/tgmath.hlsl | 11 +++++++++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index c31da51e59..b52f039227 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -42,7 +42,7 @@ template) T computeMicrofacetNormal(bool _refract, vector V, vector L, T orientedEta) { const vector H = computeUnnormalizedMicrofacetNormal(_refract,V,L,orientedEta); - const T unnormRcpLen = rsqrt(dot(H,H)); + const T unnormRcpLen = rsqrt(dot(H,H)); return H * unnormRcpLen; } @@ -438,7 +438,7 @@ struct SIsotropicMicrofacetCache // always valid because its specialized for the reflective case static this_t createForReflection(const scalar_type NdotV, const scalar_type NdotL, const scalar_type VdotL, out scalar_type LplusV_rcpLen) { - LplusV_rcpLen = rsqrt(2.0 + 2.0 * VdotL); + LplusV_rcpLen = rsqrt(2.0 + 2.0 * VdotL); this_t retval; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 702e855da6..195f4dc291 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -698,7 +698,7 @@ struct SGGXBxDF vector3_type V = normalize(vector3_type(A.x*localV.x, A.y*localV.y, localV.z));//stretch view vector so that we're sampling as if roughness=1.0 scalar_type lensq = V.x*V.x + V.y*V.y; - vector3_type T1 = lensq > 0.0 ? vector3_type(-V.y, V.x, 0.0) * rsqrt(lensq) : vector3_type(1.0,0.0,0.0); + vector3_type T1 = lensq > 0.0 ? vector3_type(-V.y, V.x, 0.0) * rsqrt(lensq) : vector3_type(1.0,0.0,0.0); vector3_type T2 = cross(V,T1); scalar_type r = sqrt(u.x); diff --git a/include/nbl/builtin/hlsl/tgmath.hlsl b/include/nbl/builtin/hlsl/tgmath.hlsl index 80e06bda56..fe2e65a71a 100644 --- a/include/nbl/builtin/hlsl/tgmath.hlsl +++ b/include/nbl/builtin/hlsl/tgmath.hlsl @@ -97,6 +97,17 @@ T erfInv(T _x) return impl::erfInv::__call(_x); } + +template +T rsqrt(T _x) +{ +#ifdef __HLSL_VERSION + return rsqrt(_x); +#else + return 1.0 / sqrt(_x); +#endif +} + } } From c3c97e14078a67dbabfde1cabe8067f99c658a90 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 16 Dec 2024 16:08:12 +0700 Subject: [PATCH 030/188] funcs use with c++ --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 7 ++- include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl | 2 +- include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 10 +-- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 62 +++++++++---------- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 60 +++++++++--------- .../hlsl/sampling/concentric_mapping.hlsl | 5 +- .../builtin/hlsl/sampling/cos_weighted.hlsl | 2 +- 7 files changed, 75 insertions(+), 73 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index b52f039227..c8b2ed0f57 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -8,6 +8,7 @@ #include "nbl/builtin/hlsl/numbers.hlsl" #include "nbl/builtin/hlsl/type_traits.hlsl" #include "nbl/builtin/hlsl/concepts.hlsl" +#include "nbl/builtin/hlsl/tgmath.hlsl" #include "nbl/builtin/hlsl/math/functions.hlsl" namespace nbl @@ -888,7 +889,7 @@ struct SBxDFParams // fresnel stuff namespace impl { -template // but why would you not use float? +template struct fresnel { using vector_t = vector; @@ -916,7 +917,7 @@ struct fresnel const T sinTheta2 = 1.0 - absCosTheta * absCosTheta; // the max() clamping can handle TIR when orientedEta2<1.0 - const U t0 = sqrt(max((U)(orientedEta2) - sinTheta2, (U)(0.0))); + const U t0 = sqrt(max((U)(orientedEta2) - sinTheta2, (U)(0.0))); const U rs = ((U)(absCosTheta) - t0) / ((U)(absCosTheta) + t0); const U t2 = orientedEta2 * absCosTheta; @@ -957,7 +958,7 @@ T fresnelDielectric(T eta, U cosTheta) { T orientedEta, rcpOrientedEta; math::getOrientedEtas(orientedEta, rcpOrientedEta, cosTheta, eta); - return impl::fresnel::template dielectric(orientedEta * orientedEta, abs(cosTheta)); + return impl::fresnel::template dielectric(orientedEta * orientedEta, abs(cosTheta)); } namespace impl diff --git a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl index 95042bf166..d8a46b0bbd 100644 --- a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl @@ -171,7 +171,7 @@ struct Beckmann scalar_type Lambda(scalar_type c2) { - scalar_type c = sqrt(c2); + scalar_type c = sqrt(c2); scalar_type nom = 1.0 - 1.259 * c + 0.396 * c2; scalar_type denom = 2.181 * c2 + 3.535 * c; return lerp(0.0, nom / denom, c < 1.6); diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl index 77899f26a7..0c9ed1e3ee 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -110,15 +110,15 @@ struct BlinnPhong scalar_type operator()(SIsotropicParams params) { // n is shininess exponent in original paper - return isinf(params.n) ? numeric_limits::infinity : numbers::inv_pi * 0.5 * (params.n + 2.0) * pow(params.NdotH, params.n); + return isinf(params.n) ? numeric_limits::infinity : numbers::inv_pi * 0.5 * (params.n + 2.0) * pow(params.NdotH, params.n); } //ashikhmin-shirley ndf scalar_type operator()(SAnisotropicParams params) { scalar_type n = (params.TdotH2 * params.ny + params.BdotH2 * params.nx) * params.one_minus_NdotH2_rcp; - return (isinf(params.nx) || isinf(params.ny)) ? numeric_limits::infinity : - sqrt((params.nx + 2.0) * (params.ny + 2.0)) * numbers::inv_pi * 0.5 * pow(params.NdotH, n); + return (isinf(params.nx) || isinf(params.ny)) ? numeric_limits::infinity : + sqrt((params.nx + 2.0) * (params.ny + 2.0)) * numbers::inv_pi * 0.5 * pow(params.NdotH, n); } }; @@ -129,14 +129,14 @@ struct Beckmann scalar_type operator()(SIsotropicParams params) { - scalar_type nom = exp( (params.NdotH2 - 1.0) / (params.a2 * params.NdotH2) ); // exp(x) == exp2(x/log(2)) ? + scalar_type nom = exp( (params.NdotH2 - 1.0) / (params.a2 * params.NdotH2) ); // exp(x) == exp2(x/log(2)) ? scalar_type denom = params.a2 * params.NdotH2 * params.NdotH2; return numbers::inv_pi * nom / denom; } scalar_type operator()(SAnisotropicParams params) { - scalar_type nom = exp(-(params.TdotH2 / params.ax2 + params.BdotH2 / params.ay2) / params.NdotH2); + scalar_type nom = exp(-(params.TdotH2 / params.ax2 + params.BdotH2 / params.ay2) / params.NdotH2); scalar_type denom = params.ax * params.ay * params.NdotH2 * params.NdotH2; return numbers::inv_pi * nom / denom; } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 195f4dc291..d7a30f09c2 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -96,7 +96,7 @@ struct SLambertianBxDF scalar_type pdf(sample_type _sample, isotropic_type interaction) { - return projected_hemisphere_pdf(max(_sample.NdotL, 0.0)); + return projected_hemisphere_pdf(max(_sample.NdotL, 0.0)); } quotient_pdf_type quotient_and_pdf_wo_clamps(sample_type _sample, isotropic_type interaction) @@ -109,7 +109,7 @@ struct SLambertianBxDF quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction) { scalar_type pdf; - scalar_type q = projected_hemisphere_quotient_and_pdf(pdf, max(_sample.NdotL, 0.0)); + scalar_type q = projected_hemisphere_quotient_and_pdf(pdf, max(_sample.NdotL, 0.0)); return quotient_pdf_type::create(spectral_type(q,q,q), pdf); } }; @@ -139,9 +139,9 @@ struct SOrenNayarBxDF { scalar_type A2 = A * 0.5; vector2_type AB = vector2_type(1.0, 0.0) + vector2_type(-0.5, 0.45) * vector2_type(A2, A2) / vector2_type(A2 + 0.33, A2 + 0.09); - scalar_type C = 1.0 / max(maxNdotL, maxNdotV); + scalar_type C = 1.0 / max(maxNdotL, maxNdotV); - scalar_type cos_phi_sin_theta = max(VdotL - maxNdotL * maxNdotV, 0.0); + scalar_type cos_phi_sin_theta = max(VdotL - maxNdotL * maxNdotV, 0.0); return (AB.x + AB.y * cos_phi_sin_theta * C); } @@ -152,7 +152,7 @@ struct SOrenNayarBxDF scalar_type eval(sample_type _sample, isotropic_type interaction) { - return maxNdotL * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(_sample.VdotL, max(_sample.NdotL,0.0), max(interaction.NdotV,0.0)); + return maxNdotL * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(_sample.VdotL, max(_sample.NdotL,0.0), max(interaction.NdotV,0.0)); } sample_type generate_wo_clamps(anisotropic_type interaction, vector2_type u) @@ -173,7 +173,7 @@ struct SOrenNayarBxDF scalar_type pdf(sample_type _sample, isotropic_type interaction) { - return projected_hemisphere_pdf(max(_sample.NdotL, 0.0)); + return projected_hemisphere_pdf(max(_sample.NdotL, 0.0)); } // pdf type same as scalar? @@ -188,8 +188,8 @@ struct SOrenNayarBxDF quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction) { scalar_type pdf; - projected_hemisphere_quotient_and_pdf(pdf, max(_sample.NdotL, 0.0)); - scalar_type q = __rec_pi_factored_out_wo_clamps(_sample.VdotL, max(_sample.NdotL,0.0), max(interaction.NdotV,0.0)); + projected_hemisphere_quotient_and_pdf(pdf, max(_sample.NdotL, 0.0)); + scalar_type q = __rec_pi_factored_out_wo_clamps(_sample.VdotL, max(_sample.NdotL,0.0), max(interaction.NdotV,0.0)); return quotient_pdf_type::create(spectral_type(q), pdf); } @@ -310,10 +310,10 @@ struct SBlinnPhongBxDF vector3_type generate(vector2_type u, scalar_type n) { scalar_type phi = 2.0 * numbers::pi; * u.y; - scalar_type cosTheta = pow(u.x, 1.0/(n+1.0)); - scalar_type sinTheta = sqrt(1.0 - cosTheta * cosTheta); - scalar_type cosPhi = cos(phi); - scalar_type sinPhi = sin(phi); + scalar_type cosTheta = pow(u.x, 1.0/(n+1.0)); + scalar_type sinTheta = sqrt(1.0 - cosTheta * cosTheta); + scalar_type cosPhi = cos(phi); + scalar_type sinPhi = sin(phi); return vector3_type(cosPhi * sinTheta, sinPhi * sinTheta, cosTheta); } @@ -442,38 +442,38 @@ struct SBeckmannBxDF vector2_type slope; if (V.z > 0.9999)//V.z=NdotV=cosTheta in tangent space { - scalar_type r = sqrt(-log(1.0 - u.x)); - scalar_type sinPhi = sin(2.0 * numbers::pi * u.y); - scalar_type cosPhi = cos(2.0 * numbers::pi * u.y); + scalar_type r = sqrt(-log(1.0 - u.x)); + scalar_type sinPhi = sin(2.0 * numbers::pi * u.y); + scalar_type cosPhi = cos(2.0 * numbers::pi * u.y); slope = (vector2_type)r * vector2_type(cosPhi,sinPhi); } else { scalar_type cosTheta = V.z; - scalar_type sinTheta = sqrt(1.0 - cosTheta * cosTheta); + scalar_type sinTheta = sqrt(1.0 - cosTheta * cosTheta); scalar_type tanTheta = sinTheta / cosTheta; scalar_type cotTheta = 1.0 / tanTheta; scalar_type a = -1.0; scalar_type c = math::erf(cosTheta); - scalar_type sample_x = max(u.x, 1.0e-6); - scalar_type theta = acos(cosTheta); + scalar_type sample_x = max(u.x, 1.0e-6); + scalar_type theta = acos(cosTheta); scalar_type fit = 1.0 + theta * (-0.876 + theta * (0.4265 - 0.0594*theta)); - scalar_type b = c - (1.0 + c) * pow(1.0-sample_x, fit); + scalar_type b = c - (1.0 + c) * pow(1.0-sample_x, fit); - scalar_type normalization = 1.0 / (1.0 + c + numbers::inv_sqrtpi * tanTheta * exp(-cosTheta*cosTheta)); + scalar_type normalization = 1.0 / (1.0 + c + numbers::inv_sqrtpi * tanTheta * exp(-cosTheta*cosTheta)); const int ITER_THRESHOLD = 10; const float MAX_ACCEPTABLE_ERR = 1.0e-5; int it = 0; float value=1000.0; - while (++itMAX_ACCEPTABLE_ERR) + while (++it(value)>MAX_ACCEPTABLE_ERR) { if (!(b>=a && b<=c)) b = 0.5 * (a+c); float invErf = math::erfInv(b); - value = normalization * (1.0 + b + numbers::inv_sqrtpi * tanTheta * exp(-invErf*invErf)) - sample_x; + value = normalization * (1.0 + b + numbers::inv_sqrtpi * tanTheta * exp(-invErf*invErf)) - sample_x; float derivative = normalization * (1.0 - invErf*cosTheta); if (value > 0.0) @@ -485,10 +485,10 @@ struct SBeckmannBxDF } // TODO: investigate if we can replace these two erf^-1 calls with a box muller transform slope.x = math::erfInv(b); - slope.y = math::erfInv(2.0 * max(u.y,1.0e-6) - 1.0); + slope.y = math::erfInv(2.0 * max(u.y,1.0e-6) - 1.0); } - scalar_type sinTheta = sqrt(1.0 - V.z*V.z); + scalar_type sinTheta = sqrt(1.0 - V.z*V.z); scalar_type cosPhi = sinTheta==0.0 ? 1.0 : clamp(V.x/sinTheta, -1.0, 1.0); scalar_type sinPhi = sinTheta==0.0 ? 0.0 : clamp(V.y/sinTheta, -1.0, 1.0); //rotate @@ -655,7 +655,7 @@ struct SGGXBxDF scalar_type NG = ggx_ndf(ndfparams); if (a2 > numeric_limits::min) { - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, max(params.NdotV,0.0), params.NdotV2, max(params.NdotL,0.0), params.NdotL2); + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, max(params.NdotV,0.0), params.NdotV2, max(params.NdotL,0.0), params.NdotL2); smith::GGX ggx_smith; NG *= ggx_smith.correlated_wo_numerator(smithparams); } @@ -699,18 +699,18 @@ struct SGGXBxDF scalar_type lensq = V.x*V.x + V.y*V.y; vector3_type T1 = lensq > 0.0 ? vector3_type(-V.y, V.x, 0.0) * rsqrt(lensq) : vector3_type(1.0,0.0,0.0); - vector3_type T2 = cross(V,T1); + vector3_type T2 = cross(V,T1); - scalar_type r = sqrt(u.x); + scalar_type r = sqrt(u.x); scalar_type phi = 2.0 * nbl_glsl_PI * u.y; - scalar_type t1 = r * cos(phi); - scalar_type t2 = r * sin(phi); + scalar_type t1 = r * cos(phi); + scalar_type t2 = r * sin(phi); scalar_type s = 0.5 * (1.0 + V.z); - t2 = (1.0 - s)*sqrt(1.0 - t1*t1) + s*t2; + t2 = (1.0 - s)*sqrt(1.0 - t1*t1) + s*t2; //reprojection onto hemisphere //TODO try it wothout the max(), not sure if -t1*t1-t2*t2>-1.0 - vector3_type H = t1*T1 + t2*T2 + sqrt(max(0.0, 1.0-t1*t1-t2*t2))*V; + vector3_type H = t1*T1 + t2*T2 + sqrt(max(0.0, 1.0-t1*t1-t2*t2))*V; //unstretch return normalize(vector3_type(A.x*H.x, A.y*H.y, H.z)); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index 377d277339..610128ccca 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -75,7 +75,7 @@ struct SLambertianBxDF scalar_type eval(sample_type _sample, isotropic_type interaction) { // probably doesn't need to use the param struct - return __eval_pi_factored_out(abs(_sample.NdotL)) * numbers::inv_pi * 0.5; + return __eval_pi_factored_out(abs(_sample.NdotL)) * numbers::inv_pi * 0.5; } sample_type generate_wo_clamps(anisotropic_type interaction, vector u) @@ -96,7 +96,7 @@ struct SLambertianBxDF scalar_type pdf(sample_type _sample, isotropic_type interaction) { - return projected_sphere_pdf(abs(_sample.NdotL)); + return projected_sphere_pdf(abs(_sample.NdotL)); } quotient_pdf_type quotient_and_pdf_wo_clamps(sample_type _sample, isotropic_type interaction) @@ -109,7 +109,7 @@ struct SLambertianBxDF quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction) { scalar_type pdf; - scalar_type q = projected_sphere_quotient_and_pdf(pdf, abs(_sample.NdotL)); + scalar_type q = projected_sphere_quotient_and_pdf(pdf, abs(_sample.NdotL)); return quotient_pdf_type::create(spectral_type(q), pdf); } }; @@ -170,7 +170,7 @@ struct SSmoothDielectricBxDF const bool backside = math::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.NdotV, eta); bool dummy; return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, backside, interaction.NdotV, - abs(interaction.NdotV), interaction.NdotV*interaction.NdotV, u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, dummy); + abs(interaction.NdotV), interaction.NdotV*interaction.NdotV, u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, dummy); } // where pdf? @@ -243,7 +243,7 @@ struct SSmoothDielectricBxDF sample_type generate(anisotropic_type interaction, inout vector u) { - return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, interaction.NdotV, abs(interaction.NdotV), u, eta2, luminosityContributionHint); + return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, interaction.NdotV, abs(interaction.NdotV), u, eta2, luminosityContributionHint); } // where pdf? @@ -263,7 +263,7 @@ struct SSmoothDielectricBxDF quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction) { const bool transmitted = isTransmissionPath(interaction.NdotV, _sample.NdotL); - const vec3 reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, abs(interaction.NdotV))); + const vec3 reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, abs(interaction.NdotV))); const vec3 sampleValue = transmitted ? ((vector3_type)(1.0) - reflectance) : reflectance; const scalar_type sampleProb = dot(sampleValue,luminosityContributionHint); @@ -325,8 +325,8 @@ struct SBeckmannDielectricBxDF const scalar_type scalar_part = beckmann.template __eval_DG_wo_clamps(params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,abs(interaction.NdotV),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); - return fresnelDielectric_common(orientedEta2, abs(cache.VdotH)) * microfacet_transform(); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,abs(interaction.NdotV),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); + return fresnelDielectric_common(orientedEta2, abs(cache.VdotH)) * microfacet_transform(); } vector3_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) @@ -344,14 +344,14 @@ struct SBeckmannDielectricBxDF const scalar_type scalar_part = beckmann.template __eval_DG_wo_clamps(params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,abs(interaction.NdotV),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); - return fresnelDielectric_common(orientedEta2, abs(cache.VdotH)) * microfacet_transform(); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,abs(interaction.NdotV),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); + return fresnelDielectric_common(orientedEta2, abs(cache.VdotH)) * microfacet_transform(); } sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix_t3x3 m, inout vector3_type u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, out anisocache_type cache) { const scalar_type VdotH = dot(localV,H); - const scalar_type reflectance = fresnelDielectric_common(orientedEta2,abs(VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2,abs(VdotH)); scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); @@ -415,9 +415,9 @@ struct SBeckmannDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); - const scalar_type absNdotV = abs(interaction.NdotV); + const scalar_type absNdotV = abs(interaction.NdotV); return pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, interaction.NdotV2, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta, dummy); } @@ -438,9 +438,9 @@ struct SBeckmannDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); - const scalar_type absNdotV = abs(interaction.NdotV); + const scalar_type absNdotV = abs(interaction.NdotV); return pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.VdotH, cache.LdotH, VdotHLdotH, ax2, ay2, orientedEta, dummy); } @@ -458,8 +458,8 @@ struct SBeckmannDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); - const scalar_type absNdotV = abs(interaction.NdotV); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + const scalar_type absNdotV = abs(interaction.NdotV); scalar_type onePlusLambda_V; scalar_type pdf = pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, interaction.NdotV2, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta, dummy); @@ -488,8 +488,8 @@ struct SBeckmannDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); - const scalar_type absNdotV = abs(interaction.NdotV); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + const scalar_type absNdotV = abs(interaction.NdotV); scalar_type onePlusLambda_V; scalar_type pdf = pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.VdotH, cache.LdotH, VdotHLdotH, ax2, ay2, orientedEta, dummy); @@ -555,7 +555,7 @@ struct SGGXDielectricBxDF ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,abs(_sample.NdotL),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); - return fresnelDielectric_common(orientedEta2, abs(cache.VdotH)) * microfacet_transform(); + return fresnelDielectric_common(orientedEta2, abs(cache.VdotH)) * microfacet_transform(); } vector3_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) @@ -574,13 +574,13 @@ struct SGGXDielectricBxDF ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,abs(_sample.NdotL),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); - return fresnelDielectric_common(orientedEta2, abs(cache.VdotH)) * microfacet_transform(); + return fresnelDielectric_common(orientedEta2, abs(cache.VdotH)) * microfacet_transform(); } sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix_t3x3 m, inout vector3_type u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, out anisocache_type cache) { const scalar_type VdotH = dot(localV,H); - const scalar_type reflectance = fresnelDielectric_common(orientedEta2,abs(VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2,abs(VdotH)); scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); @@ -642,9 +642,9 @@ struct SGGXDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); - const scalar_type absNdotV = abs(interaction.NdotV); + const scalar_type absNdotV = abs(interaction.NdotV); return pdf_wo_clamps(transmitted, reflectance, ndf, devsh_v, absNdotV, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta); } @@ -668,9 +668,9 @@ struct SGGXDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); - const scalar_type absNdotV = abs(interaction.NdotV); + const scalar_type absNdotV = abs(interaction.NdotV); return pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.VdotH, cache.LdotH, VdotHLdotH, ax2, ay2, orientedEta, dummy); } @@ -693,9 +693,9 @@ struct SGGXDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); - const scalar_type absNdotV = abs(interaction.NdotV); + const scalar_type absNdotV = abs(interaction.NdotV); scalar_type pdf = pdf_wo_clamps(transmitted, reflectance, ndf, devsh_v, absNdotV, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta); smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.NdotV, params.NdotV2, params.NdotL, params.NdotL2); @@ -724,8 +724,8 @@ struct SGGXDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); - const scalar_type absNdotV = abs(interaction.NdotV); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + const scalar_type absNdotV = abs(interaction.NdotV); scalar_type pdf = pdf_wo_clamps(transmitted, reflectance, ndf, devsh_v, absNdotV, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta); diff --git a/include/nbl/builtin/hlsl/sampling/concentric_mapping.hlsl b/include/nbl/builtin/hlsl/sampling/concentric_mapping.hlsl index c6e425e6c8..a1ba89a1ff 100644 --- a/include/nbl/builtin/hlsl/sampling/concentric_mapping.hlsl +++ b/include/nbl/builtin/hlsl/sampling/concentric_mapping.hlsl @@ -1,6 +1,7 @@ #ifndef _NBL_BUILTIN_HLSL_SAMPLING_CONCENTRIC_MAPPING_INCLUDED_ #define _NBL_BUILTIN_HLSL_SAMPLING_CONCENTRIC_MAPPING_INCLUDED_ +#include "nbl/builtin/hlsl/tgmath.hlsl" #include "nbl/builtin/hlsl/math/functions.hlsl" namespace nbl @@ -21,7 +22,7 @@ vector concentricMapping(vector _u) { T r; T theta; - if (abs(u.x) > abs(u.y)) { + if (abs(u.x) > abs(u.y)) { r = u.x; theta = 0.25 * numbers::pi * (u.y / u.x); } else { @@ -29,7 +30,7 @@ vector concentricMapping(vector _u) theta = 0.5 * numbers::pi - 0.25 * numbers::pi * (u.x / u.y); } - p = r * vector(cos(theta), sin(theta)); + p = r * vector(cos(theta), sin(theta)); } return p; diff --git a/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl b/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl index 311101d4fd..3f1653a1ab 100644 --- a/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl +++ b/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl @@ -24,7 +24,7 @@ struct ProjectedHemisphere static vector_t3 generate(vector_t2 _sample) { vector_t2 p = concentricMapping(_sample * 0.99999 + 0.000005); - T z = sqrt(max(0.0, 1.0 - p.x * p.x - p.y * p.y)); + T z = sqrt(max(0.0, 1.0 - p.x * p.x - p.y * p.y)); return vector_t3(p.x, p.y, z); } From 2c2b368b07c63f30b356e038c5f7f9aa6be83910 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 17 Dec 2024 10:39:09 +0700 Subject: [PATCH 031/188] hlsl bxdf test example init --- examples_tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples_tests b/examples_tests index a7d1600a7a..ba9fde50f4 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit a7d1600a7ac34aff07434ad3f0e125fe8f97841b +Subproject commit ba9fde50f4c3aec7270221e590ed9c86dd4d8184 From 67993ad0377049cd9b9fd171f3fa06335348635a Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 17 Dec 2024 15:03:23 +0700 Subject: [PATCH 032/188] fixed include --- include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl b/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl index 3f1653a1ab..1a319aee5f 100644 --- a/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl +++ b/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl @@ -6,7 +6,7 @@ #define _NBL_BUILTIN_HLSL_SAMPLING_COS_WEIGHTED_INCLUDED_ #include "nbl/builtin/hlsl/concepts.hlsl" -#include "nbl/builtin/hlsl/sampling/concentric_mapping.glsl" +#include "nbl/builtin/hlsl/sampling/concentric_mapping.hlsl" namespace nbl { From 4f230e8a5f193a90f7eb86ca4c7dfbb8d82de9bd Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 17 Dec 2024 16:01:34 +0700 Subject: [PATCH 033/188] use correct examples --- examples_tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples_tests b/examples_tests index 73ac5c8aaa..209170119c 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 73ac5c8aaabb4a33c46599de51ad2a5d5fff77cc +Subproject commit 209170119c3fb89ee4fe05642b28f904deb75c0f From 029116f550d11cd60007012b958c888053d425fa Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 17 Dec 2024 16:13:35 +0700 Subject: [PATCH 034/188] fixed cpp compat types --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 19 +++--- include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl | 4 +- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 6 +- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 28 ++++----- include/nbl/builtin/hlsl/math/functions.hlsl | 58 +++++++++---------- src/nbl/video/utilities/CComputeBlit.cpp | 1 + 6 files changed, 58 insertions(+), 58 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index c8b2ed0f57..e0e943e4ff 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -437,7 +437,7 @@ struct SIsotropicMicrofacetCache using sample_type = SLightSample; // always valid because its specialized for the reflective case - static this_t createForReflection(const scalar_type NdotV, const scalar_type NdotL, const scalar_type VdotL, out scalar_type LplusV_rcpLen) + static this_t createForReflection(const scalar_type NdotV, const scalar_type NdotL, const scalar_type VdotL, NBL_REF_ARG(scalar_type) LplusV_rcpLen) { LplusV_rcpLen = rsqrt(2.0 + 2.0 * VdotL); @@ -464,10 +464,10 @@ struct SIsotropicMicrofacetCache } // transmissive cases need to be checked if the path is valid before usage static bool compute( - out this_t retval, + NBL_REF_ARG(this_t) retval, const bool transmitted, NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) L, NBL_CONST_REF_ARG(vector3_type) N, const scalar_type NdotL, const scalar_type VdotL, - const scalar_type orientedEta, const scalar_type rcpOrientedEta, out vector3_type H + const scalar_type orientedEta, const scalar_type rcpOrientedEta, NBL_REF_ARG(vector3_type) H ) { // TODO: can we optimize? @@ -489,10 +489,10 @@ struct SIsotropicMicrofacetCache } template && ray_dir_info::Basic) static bool compute( - out this_t retval, + NBL_REF_ARG(this_t) retval, NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction, NBL_CONST_REF_ARG(SLightSample) _sample, - const scalar_type eta, out vector3_type H + const scalar_type eta, NBL_REF_ARG(vector3_type) H ) { const scalar_type NdotV = interaction.NdotV; @@ -509,7 +509,7 @@ struct SIsotropicMicrofacetCache } template && ray_dir_info::Basic) static bool compute( - out this_t retval, + NBL_REF_ARG(this_t) retval, NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction, NBL_CONST_REF_ARG(SLightSample) _sample, const scalar_type eta @@ -634,14 +634,13 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache } // transmissive cases need to be checked if the path is valid before usage static bool compute( - out this_t retval, + NBL_REF_ARG(this_t) retval, const bool transmitted, NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) L, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N, const scalar_type NdotL, const scalar_type VdotL, - const scalar_type orientedEta, const scalar_type rcpOrientedEta, out vector3_type H + const scalar_type orientedEta, const scalar_type rcpOrientedEta, NBL_REF_ARG(vector3_type) H ) { - vector3_type H; const bool valid = this_t::compute(retval,transmitted,V,L,N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); if (valid) { @@ -652,7 +651,7 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache } template static bool compute( - out this_t retval, + NBL_REF_ARG(this_t) retval, NBL_CONST_REF_ARG(surface_interactions::SAnisotropic) interaction, NBL_CONST_REF_ARG(SLightSample) _sample, const scalar_type eta diff --git a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl index d8a46b0bbd..7b0f3a2cf3 100644 --- a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl @@ -23,7 +23,7 @@ T G1(T lambda) } template -T VNDF_pdf_wo_clamps(typename NDF::scalar_type ndf, typename NDF::scalar_type lambda_V, typename NDF::scalar_type maxNdotV, out typename NDF::scalar_type onePlusLambda_V) +T VNDF_pdf_wo_clamps(typename NDF::scalar_type ndf, typename NDF::scalar_type lambda_V, typename NDF::scalar_type maxNdotV, NBL_REF_ARG(typename NDF::scalar_type) onePlusLambda_V) { onePlusLambda_V = 1.0 + lambda_V; ndf::microfacet_to_light_measure_transform transform = ndf::microfacet_to_light_measure_transform::create(ndf / onePlusLambda_V, maxNdotV); @@ -31,7 +31,7 @@ T VNDF_pdf_wo_clamps(typename NDF::scalar_type ndf, typename NDF::scalar_type la } template -T VNDF_pdf_wo_clamps(typename NDF::scalar_type ndf, typename NDF::scalar_type lambda_V, typename NDF::scalar_type absNdotV, bool transmitted, typename NDF::scalar_type VdotH, typename NDF::scalar_type LdotH, typename NDF::scalar_type VdotHLdotH, typename NDF::scalar_type orientedEta, typename NDF::scalar_type reflectance, out typename NDF::scalar_type onePlusLambda_V) +T VNDF_pdf_wo_clamps(typename NDF::scalar_type ndf, typename NDF::scalar_type lambda_V, typename NDF::scalar_type absNdotV, bool transmitted, typename NDF::scalar_type VdotH, typename NDF::scalar_type LdotH, typename NDF::scalar_type VdotHLdotH, typename NDF::scalar_type orientedEta, typename NDF::scalar_type reflectance, NBL_REF_ARG(typename NDF::scalar_type) onePlusLambda_V) { onePlusLambda_V = 1.0 + lambda_V; ndf::microfacet_to_light_measure_transform transform diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index d7a30f09c2..9111f83cf2 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -317,7 +317,7 @@ struct SBlinnPhongBxDF return vector3_type(cosPhi * sinTheta, sinPhi * sinTheta, cosTheta); } - sample_type generate(anisotropic_type interaction, vector2_type u, out anisocache_type cache) + sample_type generate(anisotropic_type interaction, vector2_type u, NBL_REF_ARG(anisocache_type) cache) { const vector3_type H = generate(u, n.x); const vector3_type localV = interaction.getTangentSpaceV(); @@ -502,7 +502,7 @@ struct SBeckmannBxDF return normalize(vector3_type(-slope, 1.0)); } - sample_type generate(anisotropic_type interaction, vector2_type u, out anisocache_type cache) + sample_type generate(anisotropic_type interaction, vector2_type u, NBL_REF_ARG(anisocache_type) cache) { const vector3_type localV = interaction.getTangentSpaceV(); const vector3_type H = __generate(localV, u); @@ -715,7 +715,7 @@ struct SGGXBxDF return normalize(vector3_type(A.x*H.x, A.y*H.y, H.z)); } - sample_type generate(anisotropic_type interaction, vector2_type u, out anisocache_type cache) + sample_type generate(anisotropic_type interaction, vector2_type u, NBL_REF_ARG(anisocache_type) cache) { const vector3_type localV = interaction.getTangentSpaceV(); const vector3_type H = __generate(localV, u); diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index 610128ccca..73ec07e246 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -144,7 +144,7 @@ struct SSmoothDielectricBxDF // where eval? - sample_type __generate_wo_clamps(vector3_type V, vector3_type T, vector3_type B, vector3_type N, bool backside, scalar_type NdotV, scalar_type absNdotV, scalar_type NdotV2, inout vector3_type u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, out bool transmitted) + sample_type __generate_wo_clamps(vector3_type V, vector3_type T, vector3_type B, vector3_type N, bool backside, scalar_type NdotV, scalar_type absNdotV, scalar_type NdotV2, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(bool) transmitted) { const vector3_type reflectance = fresnelDielectric_common(orientedEta2, absNdotV); @@ -155,7 +155,7 @@ struct SSmoothDielectricBxDF return sample_type::create(L, dot(V, L), T, B, N); } - sample_type generate_wo_clamps(anisotropic_type interaction, inout vector u) // TODO: check vec3? + sample_type generate_wo_clamps(anisotropic_type interaction, NBL_REF_ARG(vector) u) // TODO: check vec3? { scalar_type orientedEta, rcpOrientedEta; const bool backside = math::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.NdotV, eta); @@ -164,7 +164,7 @@ struct SSmoothDielectricBxDF interaction.NdotV, interaction.NdotV*interaction.NdotV, u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, dummy); } - sample_type generate(anisotropic_type interaction, inout vector u) + sample_type generate(anisotropic_type interaction, NBL_REF_ARG(vector) u) { scalar_type orientedEta, rcpOrientedEta; const bool backside = math::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.NdotV, eta); @@ -220,7 +220,7 @@ struct SSmoothDielectricBxDF // its basically a set of weights that determine // assert(1.0==luminosityContributionHint.r+luminosityContributionHint.g+luminosityContributionHint.b); // `remainderMetadata` is a variable which the generator function returns byproducts of sample generation that would otherwise have to be redundantly calculated `remainder_and_pdf` - sample_type __generate_wo_clamps(vector3_type V, vector3_type T, vector3_type B, vector3_type N, scalar_type NdotV, scalar_type absNdotV, inout vector3_type u, vector3_type eta2, vector3_type luminosityContributionHint, out vector3_type remainderMetadata) + sample_type __generate_wo_clamps(vector3_type V, vector3_type T, vector3_type B, vector3_type N, scalar_type NdotV, scalar_type absNdotV, NBL_REF_ARG(vector3_type) u, vector3_type eta2, vector3_type luminosityContributionHint, NBL_REF_ARG(vector3_type) remainderMetadata) { // we will only ever intersect from the outside const vector3_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2,absNdotV)); @@ -236,12 +236,12 @@ struct SSmoothDielectricBxDF return sample_type::create(L, dot(V, L), T, B, N); } - sample_type generate_wo_clamps(anisotropic_type interaction, inout vector u) // TODO: check vec3? + sample_type generate_wo_clamps(anisotropic_type interaction, NBL_REF_ARG(vector) u) // TODO: check vec3? { return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, interaction.NdotV, interaction.NdotV, u, eta2, luminosityContributionHint); } - sample_type generate(anisotropic_type interaction, inout vector u) + sample_type generate(anisotropic_type interaction, NBL_REF_ARG(vector) u) { return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, interaction.NdotV, abs(interaction.NdotV), u, eta2, luminosityContributionHint); } @@ -348,7 +348,7 @@ struct SBeckmannDielectricBxDF return fresnelDielectric_common(orientedEta2, abs(cache.VdotH)) * microfacet_transform(); } - sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix_t3x3 m, inout vector3_type u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, out anisocache_type cache) + sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix_t3x3 m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) { const scalar_type VdotH = dot(localV,H); const scalar_type reflectance = fresnelDielectric_common(orientedEta2,abs(VdotH)); @@ -365,7 +365,7 @@ struct SBeckmannDielectricBxDF return sample_type::createTangentSpace(localV, localL, m); } - sample_type generate(anisotropic_type interaction, inout vector3_type u, out anisocache_type cache) + sample_type generate(anisotropic_type interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) { const vector3_type localV = interaction.getTangentSpaceV(); @@ -381,20 +381,20 @@ struct SBeckmannDielectricBxDF return __generate_wo_clamps(localV, backside, H, interaction.getTangentFrame(), rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, cache); } - sample_type generate(anisotropic_type interaction, inout vector3_type u) + sample_type generate(anisotropic_type interaction, NBL_REF_ARG(vector3_type) u) { anisocache_type dummycache; return generate(interaction, u, dummycache); } - scalar_type pdf_wo_clamps(bool transmitted, scalar_type reflectance, scalar_type ndf, scalar_type absNdotV, scalar_type NdotV2, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, out scalar_type onePlusLambda_V) + scalar_type pdf_wo_clamps(bool transmitted, scalar_type reflectance, scalar_type ndf, scalar_type absNdotV, scalar_type NdotV2, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, NBL_REF_ARG(scalar_type) onePlusLambda_V) { smith::Beckmann beckmann_smith; const scalar_type lambda = beckmann_smith.Lambda(NdotV2, A.x*A.x); return smith::VNDF_pdf_wo_clamps >(ndf,lambda,absNdotV,transmitted,VdotH,LdotH,VdotHLdotH,orientedEta,reflectance,onePlusLambda_V); } - scalar_type pdf_wo_clamps(bool transmitted, scalar_type reflectance, scalar_type ndf, scalar_type absNdotV, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type ax2, scalar_type ay2, scalar_type orientedEta, out scalar_type onePlusLambda_V) + scalar_type pdf_wo_clamps(bool transmitted, scalar_type reflectance, scalar_type ndf, scalar_type absNdotV, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type ax2, scalar_type ay2, scalar_type orientedEta, NBL_REF_ARG(scalar_type) onePlusLambda_V) { smith::Beckmann beckmann_smith; scalar_type c2 = beckmann_smith.C2(TdotV2, BdotV2, NdotV2, ax2, ay2); @@ -577,7 +577,7 @@ struct SGGXDielectricBxDF return fresnelDielectric_common(orientedEta2, abs(cache.VdotH)) * microfacet_transform(); } - sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix_t3x3 m, inout vector3_type u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, out anisocache_type cache) + sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix_t3x3 m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) { const scalar_type VdotH = dot(localV,H); const scalar_type reflectance = fresnelDielectric_common(orientedEta2,abs(VdotH)); @@ -594,7 +594,7 @@ struct SGGXDielectricBxDF return sample_type::createTangentSpace(localV, localL, m); } - sample_type generate(anisotropic_type interaction, inout vector3_type u, out anisocache_type cache) + sample_type generate(anisotropic_type interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) { const vector3_type localV = interaction.getTangentSpaceV(); @@ -610,7 +610,7 @@ struct SGGXDielectricBxDF return __generate_wo_clamps(localV, backside, H, interaction.getTangentFrame(), rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, cache); } - sample_type generate(anisotropic_type interaction, inout vector3_type u) + sample_type generate(anisotropic_type interaction, NBL_REF_ARG(vector3_type) u) { anisocache_type dummycache; return generate(interaction, u, dummycache); diff --git a/include/nbl/builtin/hlsl/math/functions.hlsl b/include/nbl/builtin/hlsl/math/functions.hlsl index 8496c214b9..0c5d9fd613 100644 --- a/include/nbl/builtin/hlsl/math/functions.hlsl +++ b/include/nbl/builtin/hlsl/math/functions.hlsl @@ -103,7 +103,7 @@ struct orientedEtas; template<> struct orientedEtas { - static bool __call(out float orientedEta, out float rcpOrientedEta, float NdotI, float eta) + static bool __call(NBL_REF_ARG(float) orientedEta, NBL_REF_ARG(float) rcpOrientedEta, float NdotI, float eta) { const bool backside = NdotI < 0.0; const float rcpEta = 1.0 / eta; @@ -114,12 +114,12 @@ struct orientedEtas }; template<> -struct orientedEtas +struct orientedEtas { - static bool __call(out float3 orientedEta, out float3 rcpOrientedEta, float NdotI, float3 eta) + static bool __call(NBL_REF_ARG(float32_t3) orientedEta, NBL_REF_ARG(float32_t3) rcpOrientedEta, float NdotI, float32_t3 eta) { const bool backside = NdotI < 0.0; - const float3 rcpEta = (float3)1.0 / eta; + const float32_t3 rcpEta = (float32_t3)1.0 / eta; orientedEta = backside ? rcpEta:eta; rcpOrientedEta = backside ? eta:rcpEta; return backside; @@ -128,7 +128,7 @@ struct orientedEtas } template || is_vector_v) -bool getOrientedEtas(out T orientedEta, out T rcpOrientedEta, scalar_type_t NdotI, T eta) +bool getOrientedEtas(NBL_REF_ARG(T) orientedEta, NBL_REF_ARG(T) rcpOrientedEta, scalar_type_t NdotI, T eta) { return impl::orientedEtas::__call(orientedEta, rcpOrientedEta, NdotI, eta); } @@ -269,7 +269,7 @@ vector reflectRefract(bool _refract, vector I, vector N, T NdotI, // valid only for `theta` in [-PI,PI] template ) -void sincos(T theta, out T s, out T c) +void sincos(T theta, NBL_REF_ARG(T) s, NBL_REF_ARG(T) c) { c = cos(theta); s = sqrt(1.0-c*c); @@ -285,7 +285,7 @@ matrix frisvad(vector n) // TODO: confirm dimensions of matrix matrix(vector(1.0-n.x*n.x*a, b, -n.x), vector(b, 1.0-n.y*n.y*a, -n.y)); } -bool partitionRandVariable(in float leftProb, inout float xi, out float rcpChoiceProb) +bool partitionRandVariable(float leftProb, NBL_REF_ARG(float) xi, NBL_REF_ARG(float) rcpChoiceProb) { #ifdef __HLSL_VERSION NBL_CONSTEXPR float NEXT_ULP_AFTER_UNITY = asfloat(0x3f800001u); @@ -314,28 +314,28 @@ T conditionalAbsOrMax(bool cond, T x, T limit); template <> float conditionalAbsOrMax(bool cond, float x, float limit) { - const float condAbs = asfloat(asuint(x) & uint(cond ? 0x7fFFffFFu:0xffFFffFFu)); + const float condAbs = asfloat(asuint(x) & uint(cond ? 0x7fFFffFFu : 0xffFFffFFu)); return max(condAbs,limit); } template <> -float2 conditionalAbsOrMax(bool cond, float2 x, float2 limit) +float32_t2 conditionalAbsOrMax(bool cond, float32_t2 x, float32_t2 limit) { - const float2 condAbs = asfloat(asuint(x) & select(cond, (uint2)0x7fFFffFFu, (uint2)0xffFFffFFu)); + const float32_t2 condAbs = asfloat(asuint(x) & select(cond, (uint32_t2)0x7fFFffFFu, (uint32_t2)0xffFFffFFu)); return max(condAbs,limit); } template <> -float3 conditionalAbsOrMax(bool cond, float3 x, float3 limit) +float32_t3 conditionalAbsOrMax(bool cond, float32_t3 x, float32_t3 limit) { - const float3 condAbs = asfloat(asuint(x) & select(cond, (uint3)0x7fFFffFFu, (uint3)0xffFFffFFu)); + const float32_t3 condAbs = asfloat(asuint(x) & select(cond, (uint32_t3)0x7fFFffFFu, (uint32_t3)0xffFFffFFu)); return max(condAbs,limit); } template <> -float4 conditionalAbsOrMax(bool cond, float4 x, float4 limit) +float32_t4 conditionalAbsOrMax(bool cond, float32_t4 x, float32_t4 limit) { - const float4 condAbs = asfloat(asuint(x) & select(cond, (uint4)0x7fFFffFFu, (uint4)0xffFFffFFu)); + const float32_t4 condAbs = asfloat(asuint(x) & select(cond, (uint32_t4)0x7fFFffFFu, (uint32_t4)0xffFFffFFu)); return max(condAbs,limit); } #endif @@ -346,7 +346,7 @@ struct bitFields // need template? { using this_t = bitFields; - static this_t create(uint base, uint value, uint offset, uint count) + static this_t create(uint32_t base, uint32_t value, uint32_t offset, uint32_t count) { this_t retval; retval.base = base; @@ -356,33 +356,33 @@ struct bitFields // need template? return retval; } - uint __insert() + uint32_t __insert() { - const uint shifted_masked_value = (value & ((0x1u << count) - 1u)) << offset; - const uint lo = base & ((0x1u << offset) - 1u); - const uint hi = base ^ lo; + const uint32_t shifted_masked_value = (value & ((0x1u << count) - 1u)) << offset; + const uint32_t lo = base & ((0x1u << offset) - 1u); + const uint32_t hi = base ^ lo; return (hi << count) | shifted_masked_value | lo; } - uint __overwrite() + uint32_t __overwrite() { - return spirv::bitFieldInsert(base, value, offset, count); + return spirv::bitFieldInsert(base, value, offset, count); } - uint base; - uint value; - uint offset; - uint count; + uint32_t base; + uint32_t value; + uint32_t offset; + uint32_t count; }; } -uint bitFieldOverwrite(uint base, uint value, uint offset, uint count) +uint32_t bitFieldOverwrite(uint32_t base, uint32_t value, uint32_t offset, uint32_t count) { impl::bitFields b = impl::bitFields::create(base, value, offset, count); return b.__overwrite(); } -uint bitFieldInsert(uint base, uint value, uint offset, uint count) +uint32_t bitFieldInsert(uint32_t base, uint32_t value, uint32_t offset, uint32_t count) { impl::bitFields b = impl::bitFields::create(base, value, offset, count); return b.__insert(); @@ -429,7 +429,7 @@ struct trigonometry return ((AltminusB ? ABltC : ABltminusC) ? (-absArccosSumABC) : absArccosSumABC) + (AltminusB | ABltminusC ? numbers::pi : (-numbers::pi)); } - static void combineCosForSumOfAcos(float cosA, float cosB, float biasA, float biasB, out float out0, out float out1) + static void combineCosForSumOfAcos(float cosA, float cosB, float biasA, float biasB, NBL_REF_ARG(float) out0, NBL_REF_ARG(float) out1) { const float bias = biasA + biasB; const float a = cosA; @@ -464,7 +464,7 @@ float getArccosSumofABC_minus_PI(float cosA, float cosB, float cosC, float sinA, return trig.getArccosSumofABC_minus_PI(); } -void combineCosForSumOfAcos(float cosA, float cosB, float biasA, float biasB, out float out0, out float out1) +void combineCosForSumOfAcos(float cosA, float cosB, float biasA, float biasB, NBL_REF_ARG(float) out0, NBL_REF_ARG(float) out1) { impl::trigonometry trig = impl::trigonometry::create(); impl::trigonometry::combineCosForSumOfAcos(cosA, cosB, biasA, biasB, trig.tmp0, trig.tmp1); diff --git a/src/nbl/video/utilities/CComputeBlit.cpp b/src/nbl/video/utilities/CComputeBlit.cpp index 3d6c85cd74..cb8cb3e45b 100644 --- a/src/nbl/video/utilities/CComputeBlit.cpp +++ b/src/nbl/video/utilities/CComputeBlit.cpp @@ -1,5 +1,6 @@ #include "nbl/video/utilities/CComputeBlit.h" #include "nbl/builtin/hlsl/binding_info.hlsl" +#include "nbl/builtin/hlsl/tgmath.hlsl" using namespace nbl::core; using namespace nbl::hlsl; From aa91c06cf7135c3074fcfd5c44b8d3b8e577020a Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 17 Dec 2024 17:33:18 +0700 Subject: [PATCH 035/188] some bug fixes --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 12 ++++++------ include/nbl/builtin/hlsl/math/functions.hlsl | 11 +++++++++-- include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl | 10 +++++----- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index e0e943e4ff..0ad1a7b070 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -154,10 +154,10 @@ struct SIsotropic // WARNING: Changed since GLSL, now arguments need to be normalized! static SIsotropic create(NBL_CONST_REF_ARG(RayDirInfo) normalizedV, NBL_CONST_REF_ARG(vector3_type) normalizedN) { - SIsotropic retval; + SIsotropic retval; retval.V = normalizedV; retval.N = normalizedN; - retval.NdotV = dot(retval.N, retval.V.getDirection()); + retval.NdotV = dot(retval.N, retval.V.getDirection()); retval.NdotV2 = retval.NdotV * retval.NdotV; return retval; @@ -234,7 +234,7 @@ struct SAnisotropic : SIsotropic } static SAnisotropic create(NBL_CONST_REF_ARG(isotropic_type) isotropic) { - matrix TB = math::frisvad(isotropic.N); + matrix TB = math::frisvad(isotropic.N); return create(isotropic, TB[0], TB[1]); } @@ -516,7 +516,7 @@ struct SIsotropicMicrofacetCache ) { vector3_type dummy; - return compute(retval,transmitted,V,L,interaction.N,NdotL,VdotL,orientedEta,rcpOrientedEta,dummy); + return compute(retval,interaction,_sample,eta,dummy); } bool isValidVNDFMicrofacet(const bool is_bsdf, const bool transmission, const scalar_type VdotL, const scalar_type eta, const scalar_type rcp_eta) @@ -608,7 +608,7 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache if (transmitted) { const scalar_type VdotH = retval.VdotH; - LdotH = transmitted ? refract_compute_NdotT(VdotH<0.0,VdotH*VdotH,rcpOrientedEta2); + retval.LdotH = transmitted ? refract_compute_NdotT(VdotH<0.0,VdotH*VdotH,rcpOrientedEta2) : VdotH; } return retval; @@ -883,7 +883,7 @@ struct SBxDFParams Scalar BdotL2; Scalar TdotV2; Scalar BdotV2; -} +}; // fresnel stuff namespace impl diff --git a/include/nbl/builtin/hlsl/math/functions.hlsl b/include/nbl/builtin/hlsl/math/functions.hlsl index 0c5d9fd613..b36cfcdfd3 100644 --- a/include/nbl/builtin/hlsl/math/functions.hlsl +++ b/include/nbl/builtin/hlsl/math/functions.hlsl @@ -290,8 +290,8 @@ bool partitionRandVariable(float leftProb, NBL_REF_ARG(float) xi, NBL_REF_ARG(fl #ifdef __HLSL_VERSION NBL_CONSTEXPR float NEXT_ULP_AFTER_UNITY = asfloat(0x3f800001u); #else - NBL_CONSTEXPR uint32_t val = 0x3f800001u; - NBL_CONSTEXPR float32_t NEXT_ULP_AFTER_UNITY = reinterpret_cast( val ); + uint32_t val = 0x3f800001u; + float32_t NEXT_ULP_AFTER_UNITY = reinterpret_cast( val ); #endif const bool pickRight = xi >= leftProb * NEXT_ULP_AFTER_UNITY; @@ -366,7 +366,14 @@ struct bitFields // need template? uint32_t __overwrite() { +#ifdef __HLSL_VERSION return spirv::bitFieldInsert(base, value, offset, count); +#else + // TODO: double check implementation + const uint32_t shifted_masked_value = ~(0xffffffffu << count) << offset; + base &= ~shifted_masked_value; + return base | (value << offset); +#endif } uint32_t base; diff --git a/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl b/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl index 1a319aee5f..4c3961f26f 100644 --- a/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl +++ b/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl @@ -33,7 +33,7 @@ struct ProjectedHemisphere return L_z * numbers::inv_pi; } - static T quotient_and_pdf(out T pdf, T L) + static T quotient_and_pdf(NBL_REF_ARG(T) pdf, T L) { pdf = pdf(L); return 1.0; @@ -55,13 +55,13 @@ T projected_hemisphere_pdf(T L_z) } template) -T projected_hemisphere_quotient_and_pdf(out T pdf, T L) +T projected_hemisphere_quotient_and_pdf(NBL_REF_ARG(T) pdf, T L) { return impl::ProjectedHemisphere::quotient_and_pdf(pdf, L); } template) -T projected_hemisphere_quotient_and_pdf(out T pdf, vector L) +T projected_hemisphere_quotient_and_pdf(NBL_REF_ARG(T) pdf, vector L) { return impl::ProjectedHemisphere::quotient_and_pdf(pdf, L.z); } @@ -86,7 +86,7 @@ T projected_sphere_pdf(T L_z) } template) -T projected_sphere_quotient_and_pdf(out T pdf, T L) +T projected_sphere_quotient_and_pdf(NBL_REF_ARG(T) pdf, T L) { T retval = impl::ProjectedHemisphere::quotient_and_pdf(pdf, L); pdf *= 0.5; @@ -94,7 +94,7 @@ T projected_sphere_quotient_and_pdf(out T pdf, T L) } template) -T projected_sphere_quotient_and_pdf(out T pdf, vector L) +T projected_sphere_quotient_and_pdf(NBL_REF_ARG(T) pdf, vector L) { T retval = impl::ProjectedHemisphere::quotient_and_pdf(pdf, L.z); pdf *= 0.5; From 362d8cd91108ed4207a5e4e16113437dd72e7d46 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 18 Dec 2024 11:34:40 +0700 Subject: [PATCH 036/188] more bug,typo fixes --- include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl | 6 +- include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 76 ++++++++----------- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 56 +++++++------- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 8 +- 4 files changed, 70 insertions(+), 76 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl index 7b0f3a2cf3..a825448563 100644 --- a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl @@ -23,7 +23,7 @@ T G1(T lambda) } template -T VNDF_pdf_wo_clamps(typename NDF::scalar_type ndf, typename NDF::scalar_type lambda_V, typename NDF::scalar_type maxNdotV, NBL_REF_ARG(typename NDF::scalar_type) onePlusLambda_V) +typename NDF::scalar_type VNDF_pdf_wo_clamps(typename NDF::scalar_type ndf, typename NDF::scalar_type lambda_V, typename NDF::scalar_type maxNdotV, NBL_REF_ARG(typename NDF::scalar_type) onePlusLambda_V) { onePlusLambda_V = 1.0 + lambda_V; ndf::microfacet_to_light_measure_transform transform = ndf::microfacet_to_light_measure_transform::create(ndf / onePlusLambda_V, maxNdotV); @@ -31,11 +31,11 @@ T VNDF_pdf_wo_clamps(typename NDF::scalar_type ndf, typename NDF::scalar_type la } template -T VNDF_pdf_wo_clamps(typename NDF::scalar_type ndf, typename NDF::scalar_type lambda_V, typename NDF::scalar_type absNdotV, bool transmitted, typename NDF::scalar_type VdotH, typename NDF::scalar_type LdotH, typename NDF::scalar_type VdotHLdotH, typename NDF::scalar_type orientedEta, typename NDF::scalar_type reflectance, NBL_REF_ARG(typename NDF::scalar_type) onePlusLambda_V) +typename NDF::scalar_type VNDF_pdf_wo_clamps(typename NDF::scalar_type ndf, typename NDF::scalar_type lambda_V, typename NDF::scalar_type absNdotV, bool transmitted, typename NDF::scalar_type VdotH, typename NDF::scalar_type LdotH, typename NDF::scalar_type VdotHLdotH, typename NDF::scalar_type orientedEta, typename NDF::scalar_type reflectance, NBL_REF_ARG(typename NDF::scalar_type) onePlusLambda_V) { onePlusLambda_V = 1.0 + lambda_V; ndf::microfacet_to_light_measure_transform transform - = ndf::microfacet_to_light_measure_transform::create((transmitted ? (1.0 - reflectance) : reflectance) * ndf / onePlusLambda_V, , absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); + = ndf::microfacet_to_light_measure_transform::create((transmitted ? (1.0 - reflectance) : reflectance) * ndf / onePlusLambda_V, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); return transform(); } diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl index 0c9ed1e3ee..15f1a13988 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -21,28 +21,18 @@ struct SIsotropicParams { using this_t = SIsotropicParams; - static this_t create(T NdotH, T n) // blinn-phong + static this_t create(T n_or_a2, T NdotH, T NdotH2) // beckmann, ggx : a2; blinn-phong : n { this_t retval; + retval.n_or_a2 = n_or_a2; retval.NdotH = NdotH; - retval.n = n; - return this_t; - } - - static this_t create(T a2, T NdotH2) // beckmann, ggx - { - this_t retval; - retval.a2 = a2; - retval.NdotH = NdotH; + retval.NdotH2 = NdotH2; return this_t; } - T a2; - T n; + T n_or_a2; T NdotH; T NdotH2; - T TdotH2; - T BdotH2; }; template) @@ -110,7 +100,7 @@ struct BlinnPhong scalar_type operator()(SIsotropicParams params) { // n is shininess exponent in original paper - return isinf(params.n) ? numeric_limits::infinity : numbers::inv_pi * 0.5 * (params.n + 2.0) * pow(params.NdotH, params.n); + return isinf(params.n_or_a2) ? numeric_limits::infinity : numbers::inv_pi * 0.5 * (params.n_or_a2 + 2.0) * pow(params.NdotH, params.n_or_a2); } //ashikhmin-shirley ndf @@ -129,8 +119,8 @@ struct Beckmann scalar_type operator()(SIsotropicParams params) { - scalar_type nom = exp( (params.NdotH2 - 1.0) / (params.a2 * params.NdotH2) ); // exp(x) == exp2(x/log(2)) ? - scalar_type denom = params.a2 * params.NdotH2 * params.NdotH2; + scalar_type nom = exp( (params.NdotH2 - 1.0) / (params.n_or_a2 * params.NdotH2) ); // exp(x) == exp2(x/log(2)) ? + scalar_type denom = params.n_or_a2 * params.NdotH2 * params.NdotH2; return numbers::inv_pi * nom / denom; } @@ -151,8 +141,8 @@ struct GGX // trowbridge-reitz scalar_type operator()(SIsotropicParams params) { - scalar_type denom = params.NdotH2 * (params.a2 - 1.0) + 1.0; - return params.a2 * numbers::inv_pi / (denom * denom); + scalar_type denom = params.NdotH2 * (params.n_or_a2 - 1.0) + 1.0; + return params.n_or_a2 * numbers::inv_pi / (denom * denom); } scalar_type operator()(SAnisotropicParams params) @@ -211,7 +201,7 @@ struct microfacet_to_light_measure_transform { this_t retval; retval.NDFcos = NDFcos; - if (is_ggv_v) + if (is_ggx_v) retval.maxNdotL = maxNdotV; else retval.maxNdotV = maxNdotV; @@ -220,15 +210,15 @@ struct microfacet_to_light_measure_transform scalar_type operator()() { - if (is_ggv_v) + if (is_ggx_v) return NDFcos * maxNdotL; else return 0.25 * NDFcos / maxNdotV; } - scalar_type NDFcos - scalar_type maxNdotV - scalar_type maxNdotL + scalar_type NDFcos; + scalar_type maxNdotV; + scalar_type maxNdotL; }; template @@ -241,7 +231,7 @@ struct microfacet_to_light_measure_transform { this_t retval; retval.NDFcos = NDFcos; - if (is_ggv_v) + if (is_ggx_v) retval.absNdotL = absNdotV; else retval.absNdotV = absNdotV; @@ -255,7 +245,7 @@ struct microfacet_to_light_measure_transform scalar_type operator()() { scalar_type denominator; - if (is_ggv_v) + if (is_ggx_v) denominator = absNdotL; else denominator = absNdotV; @@ -266,14 +256,14 @@ struct microfacet_to_light_measure_transform return NDFcos * VdotHLdotH / denominator; } - scalar_type NDFcos - scalar_type absNdotV - scalar_type absNdotL + scalar_type NDFcos; + scalar_type absNdotV; + scalar_type absNdotL; - scalar_type VdotH - scalar_type LdotH - scalar_type VdotHLdotH - scalar_type orientedEta + scalar_type VdotH; + scalar_type LdotH; + scalar_type VdotHLdotH; + scalar_type orientedEta; }; template @@ -286,7 +276,7 @@ struct microfacet_to_light_measure_transform { this_t retval; retval.NDFcos = NDFcos; - if (is_ggv_v) + if (is_ggx_v) retval.absNdotL = absNdotV; else retval.absNdotV = absNdotV; @@ -300,7 +290,7 @@ struct microfacet_to_light_measure_transform scalar_type operator()() { - if (is_ggv_v) + if (is_ggx_v) { scalar_type denominator = absNdotL; if (transmitted) @@ -324,15 +314,15 @@ struct microfacet_to_light_measure_transform } } - bool transmitted - scalar_type NDFcos - scalar_type absNdotV - scalar_type absNdotL + bool transmitted; + scalar_type NDFcos; + scalar_type absNdotV; + scalar_type absNdotL; - scalar_type VdotH - scalar_type LdotH - scalar_type VdotHLdotH - scalar_type orientedEta + scalar_type VdotH; + scalar_type LdotH; + scalar_type VdotHLdotH; + scalar_type orientedEta; }; } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 9111f83cf2..8a8c1f1e83 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -147,12 +147,13 @@ struct SOrenNayarBxDF scalar_type __eval_wo_clamps(sample_type _sample, isotropic_type interaction) { - return maxNdotL * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(_sample.VdotL, _sample.NdotL, interaction.NdotV); + return _sample.NdotL * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(_sample.VdotL, _sample.NdotL, interaction.NdotV); } scalar_type eval(sample_type _sample, isotropic_type interaction) { - return maxNdotL * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(_sample.VdotL, max(_sample.NdotL,0.0), max(interaction.NdotV,0.0)); + scalar_type maxNdotL = max(_sample.NdotL,0.0); + return maxNdotL * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(_sample.VdotL, maxNdotL, max(interaction.NdotV,0.0)); } sample_type generate_wo_clamps(anisotropic_type interaction, vector2_type u) @@ -202,14 +203,14 @@ template; - using scalar_type = typename LightSample::scalar_type + using scalar_type = typename LightSample::scalar_type; using vector2_type = vector; using vector3_type = vector; using matrix2x3_type = matrix; using params_t = SBxDFParams; using isotropic_type = typename IsoCache::isotropic_type; - using anisotropic_type = typename AnisoCache::anisotropic_type + using anisotropic_type = typename AnisoCache::anisotropic_type; using sample_type = LightSample; using spectral_type = vector; // TODO: most likely change this using quotient_pdf_type = quotient_and_pdf; @@ -254,7 +255,7 @@ struct SBlinnPhongBxDF } else { - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(params.NdotH, n); + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(n, params.NdotH, params.NdotH2); ndf::BlinnPhong blinn_phong; scalar_type NG = blinn_phong(ndfparams); if (any(a2 > numeric_limits::min)) @@ -338,14 +339,14 @@ template; - using scalar_type = typename LightSample::scalar_type + using scalar_type = typename LightSample::scalar_type; using vector2_type = vector; using vector3_type = vector; using matrix2x3_type = matrix; using params_t = SBxDFParams; using isotropic_type = typename IsoCache::isotropic_type; - using anisotropic_type = typename AnisoCache::anisotropic_type + using anisotropic_type = typename AnisoCache::anisotropic_type; using sample_type = LightSample; using spectral_type = vector; // TODO: most likely change this using quotient_pdf_type = quotient_and_pdf; @@ -391,7 +392,7 @@ struct SBeckmannBxDF else { scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH2); + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); ndf::Beckmann beckmann_ndf; scalar_type NG = beckmann_ndf(ndfparams); if (a2 > numeric_limits::min) @@ -455,7 +456,7 @@ struct SBeckmannBxDF scalar_type cotTheta = 1.0 / tanTheta; scalar_type a = -1.0; - scalar_type c = math::erf(cosTheta); + scalar_type c = erf(cosTheta); scalar_type sample_x = max(u.x, 1.0e-6); scalar_type theta = acos(cosTheta); scalar_type fit = 1.0 + theta * (-0.876 + theta * (0.4265 - 0.0594*theta)); @@ -472,7 +473,7 @@ struct SBeckmannBxDF if (!(b>=a && b<=c)) b = 0.5 * (a+c); - float invErf = math::erfInv(b); + float invErf = erfInv(b); value = normalization * (1.0 + b + numbers::inv_sqrtpi * tanTheta * exp(-invErf*invErf)) - sample_x; float derivative = normalization * (1.0 - invErf*cosTheta); @@ -484,8 +485,8 @@ struct SBeckmannBxDF b -= value/derivative; } // TODO: investigate if we can replace these two erf^-1 calls with a box muller transform - slope.x = math::erfInv(b); - slope.y = math::erfInv(2.0 * max(u.y,1.0e-6) - 1.0); + slope.x = erfInv(b); + slope.y = erfInv(2.0 * max(u.y,1.0e-6) - 1.0); } scalar_type sinTheta = sqrt(1.0 - V.z*V.z); @@ -497,7 +498,7 @@ struct SBeckmannBxDF slope.x = tmp; //unstretch - slope = vector2_type(ax,ay)*slope; + slope = vector2_type(A.x,A.y)*slope; return normalize(vector3_type(-slope, 1.0)); } @@ -515,12 +516,13 @@ struct SBeckmannBxDF scalar_type pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) { - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, cache.NdotH2); + scalar_type a2 = A.x*A.x; + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, cache.NdotH, cache.NdotH2); ndf::Beckmann beckmann_ndf; scalar_type ndf = beckmann_ndf(ndfparams); smith::Beckmann beckmann_smith; - const scalar_type lambda = beckmann_smith.Lambda(interaction.NdotV2, A.x*A.x); + const scalar_type lambda = beckmann_smith.Lambda(interaction.NdotV2, a2); scalar_type dummy; return smith::VNDF_pdf_wo_clamps >(ndf, lambda, interaction.NdotV, dummy); } @@ -541,7 +543,7 @@ struct SBeckmannBxDF quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) { const scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, cache.NdotH2); + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, cache.NdotH, cache.NdotH2); ndf::Beckmann beckmann_ndf; const scalar_type ndf = beckmann_ndf(ndfparams); @@ -574,7 +576,7 @@ struct SBeckmannBxDF smith::Beckmann beckmann_smith; scalar_type onePlusLambda_V; - const scalar_type c2 = smith::beckmann_smith.C2(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); + const scalar_type c2 = beckmann_smith.C2(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); scalar_type lambda = beckmann_smith.Lambda(c2); scalar_type pdf = smith::VNDF_pdf_wo_clamps >(ndf, lambda, interaction.NdotV, onePlusLambda_V); vector3_type quo = (vector3_type)0.0; @@ -582,7 +584,7 @@ struct SBeckmannBxDF { smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, onePlusLambda_V); const vector3_type reflectance = fresnel_conductor(ior[0], ior[1], cache.VdotH); - scalar_type G2_over_G1 = smith::beckmann_smith.G2_over_G1(smithparams); + scalar_type G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); quo = reflectance * G2_over_G1; } @@ -597,14 +599,14 @@ template; - using scalar_type = typename LightSample::scalar_type + using scalar_type = typename LightSample::scalar_type; using vector2_type = vector; using vector3_type = vector; using matrix2x3_type = matrix; using params_t = SBxDFParams; using isotropic_type = typename IsoCache::isotropic_type; - using anisotropic_type = typename AnisoCache::anisotropic_type + using anisotropic_type = typename AnisoCache::anisotropic_type; using sample_type = LightSample; using spectral_type = vector; // TODO: most likely change this using quotient_pdf_type = quotient_and_pdf; @@ -650,7 +652,7 @@ struct SGGXBxDF else { scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH2); + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); ndf::GGX ggx_ndf; scalar_type NG = ggx_ndf(ndfparams); if (a2 > numeric_limits::min) @@ -702,7 +704,7 @@ struct SGGXBxDF vector3_type T2 = cross(V,T1); scalar_type r = sqrt(u.x); - scalar_type phi = 2.0 * nbl_glsl_PI * u.y; + scalar_type phi = 2.0 * numbers::pi * u.y; scalar_type t1 = r * cos(phi); scalar_type t2 = r * sin(phi); scalar_type s = 0.5 * (1.0 + V.z); @@ -729,7 +731,7 @@ struct SGGXBxDF scalar_type pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) { const scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, cache.NdotH2); + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, cache.NdotH, cache.NdotH2); ndf::GGX ggx_ndf; scalar_type ndf = ggx_ndf(ndfparams); @@ -743,7 +745,9 @@ struct SGGXBxDF { const scalar_type ax2 = A.x*A.x; const scalar_type ay2 = A.y*A.y; - scalar_type ndf = ndf::ggx_aniso(cache.TdotH * cache.TdotH, cache.BdotH * cache.BdotH, cache.NdotH2, A.x, A.y, ax2, ay2); + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, cache.TdotH * cache.TdotH, cache.BdotH * cache.BdotH, cache.NdotH2); + ndf::GGX ggx_ndf; + scalar_type ndf = ggx_ndf(ndfparams); smith::GGX ggx_smith; const scalar_type devsh_v = ggx_smith.devsh_part(interaction.TdotV * interaction.TdotV, interaction.BdotV * interaction.BdotV, interaction.NdotV2, ax2, ay2); @@ -795,7 +799,7 @@ struct SGGXBxDF const scalar_type ay2 = A.y*A.y; smith::GGX ggx_smith; - const scalar_type devsh_v = ggx_smith.devsh_part(interaction.NdotV2, a2, one_minus_a2); + const scalar_type devsh_v = ggx_smith.devsh_part(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); scalar_type pdf = pdf(_sample, interaction, cache); smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2); @@ -812,7 +816,7 @@ struct SGGXBxDF const scalar_type ay2 = A.y*A.y; smith::GGX ggx_smith; - const scalar_type devsh_v = ggx_smith.devsh_part(interaction.NdotV2, a2, one_minus_a2); + const scalar_type devsh_v = ggx_smith.devsh_part(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); scalar_type pdf = pdf(_sample, interaction, cache); vector3_type quo = (vector3_type)0.0; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index 73ec07e246..a857c66af4 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -404,7 +404,7 @@ struct SBeckmannDielectricBxDF scalar_type pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) { - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(A.x*A.x, cache.NdotH2); + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(A.x*A.x, cache.NdotH, cache.NdotH2); ndf::Beckmann beckmann_ndf; scalar_type ndf = beckmann_ndf(ndfparams); @@ -447,7 +447,7 @@ struct SBeckmannDielectricBxDF quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) { const scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, cache.NdotH2); + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, cache.NdotH, cache.NdotH2); ndf::Beckmann beckmann_ndf; scalar_type ndf = beckmann_ndf(ndfparams); @@ -628,7 +628,7 @@ struct SGGXDielectricBxDF const scalar_type a2 = A.x*A.x; params_t params = params_t::template create(_sample, interaction, cache); - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotV, params.NdotV2, params.NdotL, params.NdotL2); + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); ndf::GGX ggx_ndf; scalar_type ndf = ggx_ndf(ndfparams); @@ -679,7 +679,7 @@ struct SGGXDielectricBxDF const scalar_type a2 = A.x*A.x; params_t params = params_t::template create(_sample, interaction, cache); - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotV, params.NdotV2, params.NdotL, params.NdotL2); + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); ndf::GGX ggx_ndf; scalar_type ndf = ggx_ndf(ndfparams); From 7734550d5cf7e3c38ef4118586b19961810e0fab Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 19 Dec 2024 09:09:47 +0700 Subject: [PATCH 037/188] fixed bsdf bugs --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 4 ++ .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 42 +++++++++---------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 0ad1a7b070..9aa458aaf1 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -50,7 +50,11 @@ T computeMicrofacetNormal(bool _refract, vector V, vector L, T oriente // if V and L are on different sides of the surface normal, then their dot product sign bits will differ, hence XOR will yield 1 at last bit bool isTransmissionPath(float NdotV, float NdotL) { +#ifdef __HLSL_VERSION return bool((asuint(NdotV) ^ asuint(NdotL)) & 0x80000000u); +#else + return bool((reinterpret_cast(NdotV) ^ reinterpret_cast(NdotL)) & 0x80000000u); +#endif } namespace ray_dir_info diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index a857c66af4..b67990f410 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -123,12 +123,12 @@ template; - using scalar_type = typename LightSample::scalar_type + using scalar_type = typename LightSample::scalar_type; using vector3_type = vector; using params_t = SBxDFParams; using isotropic_type = typename IsoCache::isotropic_type; - using anisotropic_type = typename AnisoCache::anisotropic_type + using anisotropic_type = typename AnisoCache::anisotropic_type; using sample_type = LightSample; using spectral_type = vector; // TODO: most likely change this using quotient_pdf_type = quotient_and_pdf; @@ -155,7 +155,7 @@ struct SSmoothDielectricBxDF return sample_type::create(L, dot(V, L), T, B, N); } - sample_type generate_wo_clamps(anisotropic_type interaction, NBL_REF_ARG(vector) u) // TODO: check vec3? + sample_type generate_wo_clamps(anisotropic_type interaction, NBL_REF_ARG(vector) u) // TODO: check vector3_type? { scalar_type orientedEta, rcpOrientedEta; const bool backside = math::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.NdotV, eta); @@ -183,7 +183,7 @@ struct SSmoothDielectricBxDF const bool backside = math::getOrientedEtas(dummy, rcpOrientedEta, interaction.NdotV, eta); const scalar_type pdf = 1.0 / 0.0; - scalar_type quo = transmitted ? rcpOrientedEta2 : 1.0; + scalar_type quo = transmitted ? rcpOrientedEta : 1.0; return quotient_pdf_type::create(spectral_type(quo), pdf); } @@ -194,12 +194,12 @@ template { using this_t = SSmoothDielectricBxDF; - using scalar_type = typename LightSample::scalar_type + using scalar_type = typename LightSample::scalar_type; using vector3_type = vector; using params_t = SBxDFParams; using isotropic_type = typename IsoCache::isotropic_type; - using anisotropic_type = typename AnisoCache::anisotropic_type + using anisotropic_type = typename AnisoCache::anisotropic_type; using sample_type = LightSample; using spectral_type = vector; // TODO: most likely change this using quotient_pdf_type = quotient_and_pdf; @@ -236,7 +236,7 @@ struct SSmoothDielectricBxDF return sample_type::create(L, dot(V, L), T, B, N); } - sample_type generate_wo_clamps(anisotropic_type interaction, NBL_REF_ARG(vector) u) // TODO: check vec3? + sample_type generate_wo_clamps(anisotropic_type interaction, NBL_REF_ARG(vector) u) // TODO: check vector3_type? { return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, interaction.NdotV, interaction.NdotV, u, eta2, luminosityContributionHint); } @@ -251,8 +251,8 @@ struct SSmoothDielectricBxDF quotient_pdf_type quotient_and_pdf_wo_clamps(sample_type _sample, isotropic_type interaction) { const bool transmitted = isTransmissionPath(interaction.NdotV, _sample.NdotL); - const vec3 reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, interaction.NdotV)); - const vec3 sampleValue = transmitted ? ((vector3_type)(1.0) - reflectance) : reflectance; + const vector3_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, interaction.NdotV)); + const vector3_type sampleValue = transmitted ? ((vector3_type)(1.0) - reflectance) : reflectance; const scalar_type sampleProb = dot(sampleValue,luminosityContributionHint); @@ -263,8 +263,8 @@ struct SSmoothDielectricBxDF quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction) { const bool transmitted = isTransmissionPath(interaction.NdotV, _sample.NdotL); - const vec3 reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, abs(interaction.NdotV))); - const vec3 sampleValue = transmitted ? ((vector3_type)(1.0) - reflectance) : reflectance; + const vector3_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, abs(interaction.NdotV))); + const vector3_type sampleValue = transmitted ? ((vector3_type)(1.0) - reflectance) : reflectance; const scalar_type sampleProb = dot(sampleValue,luminosityContributionHint); @@ -280,14 +280,14 @@ template; - using scalar_type = typename LightSample::scalar_type + using scalar_type = typename LightSample::scalar_type; using vector2_type = vector; using vector3_type = vector; using matrix3x3_type = matrix; using params_t = SBxDFParams; using isotropic_type = typename IsoCache::isotropic_type; - using anisotropic_type = typename AnisoCache::anisotropic_type + using anisotropic_type = typename AnisoCache::anisotropic_type; using sample_type = LightSample; using spectral_type = vector; // TODO: most likely change this using quotient_pdf_type = quotient_and_pdf; @@ -348,7 +348,7 @@ struct SBeckmannDielectricBxDF return fresnelDielectric_common(orientedEta2, abs(cache.VdotH)) * microfacet_transform(); } - sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix_t3x3 m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) + sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix3x3_type m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) { const scalar_type VdotH = dot(localV,H); const scalar_type reflectance = fresnelDielectric_common(orientedEta2,abs(VdotH)); @@ -360,7 +360,7 @@ struct SBeckmannDielectricBxDF const scalar_type VdotH = cache.VdotH; cache.LdotH = transmitted ? reflectRefract_computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; - vector3_type localL = math::reflectRefract_impl(transmitted, tangentSpaceV, tangentSpaceH, VdotH, cache.LdotH, rcpOrientedEta); + vector3_type localL = math::reflectRefract_impl(transmitted, localV, H, VdotH, cache.LdotH, rcpOrientedEta); return sample_type::createTangentSpace(localV, localL, m); } @@ -509,14 +509,14 @@ template; - using scalar_type = typename LightSample::scalar_type + using scalar_type = typename LightSample::scalar_type; using vector2_type = vector; using vector3_type = vector; using matrix3x3_type = matrix; using params_t = SBxDFParams; using isotropic_type = typename IsoCache::isotropic_type; - using anisotropic_type = typename AnisoCache::anisotropic_type + using anisotropic_type = typename AnisoCache::anisotropic_type; using sample_type = LightSample; using spectral_type = vector; // TODO: most likely change this using quotient_pdf_type = quotient_and_pdf; @@ -550,7 +550,7 @@ struct SGGXDielectricBxDF matrix dummyior; params_t params = params_t::template create(_sample, interaction, cache); - reflection::GGX ggx = reflection::GGX::create(A.x, dummyior); + reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, dummyior); const scalar_type NG_already_in_reflective_dL_measure = ggx.template __eval_DG_wo_clamps(params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = @@ -569,7 +569,7 @@ struct SGGXDielectricBxDF matrix dummyior; params_t params = params_t::template create(_sample, interaction, cache); - reflection::GGX ggx = reflection::GGX::create(A.x, A.y dummyior); + reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, A.y, dummyior); const scalar_type NG_already_in_reflective_dL_measure = ggx.template __eval_DG_wo_clamps(params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = @@ -577,7 +577,7 @@ struct SGGXDielectricBxDF return fresnelDielectric_common(orientedEta2, abs(cache.VdotH)) * microfacet_transform(); } - sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix_t3x3 m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) + sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix3x3_type m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) { const scalar_type VdotH = dot(localV,H); const scalar_type reflectance = fresnelDielectric_common(orientedEta2,abs(VdotH)); @@ -589,7 +589,7 @@ struct SGGXDielectricBxDF const scalar_type VdotH = cache.VdotH; cache.LdotH = transmitted ? reflectRefract_computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; - vector3_type localL = math::reflectRefract_impl(transmitted, tangentSpaceV, tangentSpaceH, VdotH, cache.LdotH, rcpOrientedEta); + vector3_type localL = math::reflectRefract_impl(transmitted, localV, H, VdotH, cache.LdotH, rcpOrientedEta); return sample_type::createTangentSpace(localV, localL, m); } From 2aa51ebc341cf48371eb8647410b94a4748fa925 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 20 Dec 2024 10:53:06 +0700 Subject: [PATCH 038/188] use bit_cast instead of reinterpret_cast --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 9aa458aaf1..3d3ede9228 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -53,7 +53,7 @@ bool isTransmissionPath(float NdotV, float NdotL) #ifdef __HLSL_VERSION return bool((asuint(NdotV) ^ asuint(NdotL)) & 0x80000000u); #else - return bool((reinterpret_cast(NdotV) ^ reinterpret_cast(NdotL)) & 0x80000000u); + return bool((bit_cast(NdotV) ^ bit_cast(NdotL)) & 0x80000000u); #endif } From b53c6056fde5e3a1e444cb5702a642008edf61a9 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 20 Dec 2024 11:39:11 +0700 Subject: [PATCH 039/188] fix concepts --- examples_tests | 2 +- include/nbl/builtin/hlsl/bxdf/common.hlsl | 25 ++++++++++------------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/examples_tests b/examples_tests index 5ba4dfd0aa..9212b655e1 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 5ba4dfd0aab9722fb44074e840041a5bc4611de2 +Subproject commit 9212b655e1bae175913f6b59b8af07b6bb307783 diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 3d3ede9228..1c4f442ae9 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -179,12 +179,10 @@ struct SIsotropic #define NBL_CONCEPT_PARAM_0 (aniso, T) #define NBL_CONCEPT_PARAM_1 (iso, typename T::isotropic_type) #define NBL_CONCEPT_PARAM_2 (normT, typename T::vector3_type) -#define NBL_CONCEPT_PARAM_3 (normB, typename T::scalar_type) -NBL_CONCEPT_BEGIN(4) +NBL_CONCEPT_BEGIN(3) #define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define normT NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 -#define normB NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::ray_dir_info_type)) ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_type)) @@ -195,11 +193,10 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.B), ::nbl::hlsl::is_same_v, typename T::vector3_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.TdotV), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.BdotV), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(iso,normT,normB)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(iso,normT,normT)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getTangentSpaceV()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getTangentFrame()), ::nbl::hlsl::is_same_v, typename T::matrix3x3_type)) ) && Isotropic && ray_dir_info::Basic; -#undef normB #undef normT #undef iso #undef aniso @@ -218,7 +215,7 @@ struct SAnisotropic : SIsotropic static SAnisotropic create( NBL_CONST_REF_ARG(isotropic_type) isotropic, NBL_CONST_REF_ARG(vector3_type) normalizedT, - const scalar_type normalizedB + NBL_CONST_REF_ARG(vector3_type) normalizedB ) { SAnisotropic retval; @@ -408,10 +405,10 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) ((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.VdotH), ::nbl::hlsl::is_same_v, U)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.LdotH), ::nbl::hlsl::is_same_v, U)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.NdotH), ::nbl::hlsl::is_same_v, U)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.NdotH2), ::nbl::hlsl::is_same_v, U)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.VdotH), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.LdotH), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.NdotH), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.NdotH2), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(pNdotV,pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(iso,_sample)), ::nbl::hlsl::is_same_v, T)) @@ -559,11 +556,11 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.TdotH), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.BdotH), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,H)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,H,b0,eta0,eta1)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(V,L,pVdotL)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V,b0,pNdotL,pNdotL)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(V,V,pNdotL)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(aniso,_sample)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::compute(cache,b0,V,L,T,B,N,pNdotL,pVdotL,eta0,eta1,H)), ::nbl::hlsl::is_same_v, bool)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::compute(cache,b0,V,V,V,V,V,pNdotL,pNdotL,pNdotL,pNdotL,V)), ::nbl::hlsl::is_same_v, bool)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,aniso,_sample)), ::nbl::hlsl::is_same_v, bool)) ) && surface_interactions::Anisotropic; #undef b0 From 5a3e7e6985a245aff11f2af94595d7d4c306380e Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 20 Dec 2024 15:02:22 +0700 Subject: [PATCH 040/188] fix aniso inter create --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 14 +++++++++----- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 1c4f442ae9..3efeace07d 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -161,7 +161,7 @@ struct SIsotropic SIsotropic retval; retval.V = normalizedV; retval.N = normalizedN; - retval.NdotV = dot(retval.N, retval.V.getDirection()); + retval.NdotV = dot(retval.N, retval.V.getDirection()); retval.NdotV2 = retval.NdotV * retval.NdotV; return retval; @@ -219,13 +219,17 @@ struct SAnisotropic : SIsotropic ) { SAnisotropic retval; - //(SIsotropic) retval = isotropic; + (SIsotropic) retval = isotropic; + // retval.V = isotropic.V; + // retval.N = isotropic.N; + // retval.NdotV = isotropic.NdotV; + // retval.NdotV2 = isotropic.NdotV2; + retval.T = normalizedT; retval.B = normalizedB; - const vector3_type V = retval.getDirection(); - retval.TdotV = dot(V, retval.T); - retval.BdotV = dot(V, retval.B); + retval.TdotV = dot(retval.V.getDirection(), retval.T); + retval.BdotV = dot(retval.V.getDirection(), retval.B); return retval; } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 8a8c1f1e83..684c4cc1e6 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -75,7 +75,7 @@ struct SLambertianBxDF scalar_type eval(sample_type _sample, isotropic_type interaction) { // probably doesn't need to use the param struct - return __eval_pi_factored_out(max(_sample.NdotL, 0.0)) * numbers::inv_pi; + return __eval_pi_factored_out(max(_sample.NdotL, 0.0)) * numbers::inv_pi; } sample_type generate_wo_clamps(anisotropic_type interaction, vector u) From 1286459f2c7ca5cf7131786f802a1a67a0c6092f Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 23 Dec 2024 16:08:39 +0700 Subject: [PATCH 041/188] fixed all? bugs --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 52 +++++------ include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 22 +++-- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 90 ++++++++++--------- .../hlsl/sampling/concentric_mapping.hlsl | 2 +- .../builtin/hlsl/sampling/cos_weighted.hlsl | 6 +- 5 files changed, 95 insertions(+), 77 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 3efeace07d..1d63832907 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -43,7 +43,7 @@ template) T computeMicrofacetNormal(bool _refract, vector V, vector L, T orientedEta) { const vector H = computeUnnormalizedMicrofacetNormal(_refract,V,L,orientedEta); - const T unnormRcpLen = rsqrt(dot(H,H)); + const T unnormRcpLen = rsqrt(nbl::hlsl::dot(H,H)); return H * unnormRcpLen; } @@ -90,7 +90,7 @@ struct SBasic using scalar_type = T; using vector3_type = vector; - vector3_type getDirection() { return direction; } + vector3_type getDirection() NBL_CONST_MEMBER_FUNC { return direction; } SBasic transmit() { @@ -161,7 +161,7 @@ struct SIsotropic SIsotropic retval; retval.V = normalizedV; retval.N = normalizedN; - retval.NdotV = dot(retval.N, retval.V.getDirection()); + retval.NdotV = nbl::hlsl::dot(retval.N, retval.V.getDirection()); retval.NdotV2 = retval.NdotV * retval.NdotV; return retval; @@ -228,8 +228,8 @@ struct SAnisotropic : SIsotropic retval.T = normalizedT; retval.B = normalizedB; - retval.TdotV = dot(retval.V.getDirection(), retval.T); - retval.BdotV = dot(retval.V.getDirection(), retval.B); + retval.TdotV = nbl::hlsl::dot(retval.V.getDirection(), retval.T); + retval.BdotV = nbl::hlsl::dot(retval.V.getDirection(), retval.B); return retval; } @@ -323,12 +323,14 @@ struct SLightSample { this_t retval; - retval.L = RayDirInfo::transform(tangentSpaceL,tangentFrame); - retval.VdotL = dot(tangentSpaceV,tangentSpaceL); - - retval.TdotL = tangentSpaceL.x; - retval.BdotL = tangentSpaceL.y; - retval.NdotL = tangentSpaceL.z; + //retval.L = RayDirInfo::transform(tangentSpaceL,tangentFrame); + const vector3_type L = tangentSpaceL.getDirection(); + retval.L.direction = nbl::hlsl::mul(tangentFrame, L); // frame must be an orthonormal matrix + retval.VdotL = nbl::hlsl::dot(tangentSpaceV, L); + + retval.TdotL = L.x; + retval.BdotL = L.y; + retval.NdotL = L.z; retval.NdotL2 = retval.NdotL*retval.NdotL; return retval; @@ -342,7 +344,7 @@ struct SLightSample retval.TdotL = nbl::hlsl::numeric_limits::signaling_NaN; retval.BdotL = nbl::hlsl::numeric_limits::signaling_NaN; - retval.NdotL = dot(N,L); + retval.NdotL = nbl::hlsl::dot(N,L); retval.NdotL2 = retval.NdotL * retval.NdotL; return retval; @@ -351,8 +353,8 @@ struct SLightSample { this_t retval = create(L,VdotL,N); - retval.TdotL = dot(T,L); - retval.BdotL = dot(B,L); + retval.TdotL = nbl::hlsl::dot(T,L); + retval.BdotL = nbl::hlsl::dot(B,L); return retval; } @@ -361,14 +363,14 @@ struct SLightSample static this_t create(NBL_CONST_REF_ARG(vector3_type) L, NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction) { const vector3_type V = interaction.V.getDirection(); - const scalar_type VdotL = dot(V,L); + const scalar_type VdotL = nbl::hlsl::dot(V,L); return create(L, VdotL, interaction.N); } template static this_t create(NBL_CONST_REF_ARG(vector3_type) L, NBL_CONST_REF_ARG(surface_interactions::SAnisotropic) interaction) { const vector3_type V = interaction.V.getDirection(); - const scalar_type VdotL = dot(V,L); + const scalar_type VdotL = nbl::hlsl::dot(V,L); return create(L,VdotL,interaction.T,interaction.B,interaction.N); } // @@ -477,7 +479,7 @@ struct SIsotropicMicrofacetCache { // TODO: can we optimize? H = computeMicrofacetNormal(transmitted,V,L,orientedEta); - retval.NdotH = dot(N, H); + retval.NdotH = nbl::hlsl::dot(N, H); // not coming from the medium (reflected) OR // exiting at the macro scale AND ( (not L outside the cone of possible directions given IoR with constraint VdotH*LdotH<0.0) OR (microfacet not facing toward the macrosurface, i.e. non heightfield profile of microsurface) ) @@ -485,8 +487,8 @@ struct SIsotropicMicrofacetCache if (valid) { // TODO: can we optimize? - retval.VdotH = dot(V,H); - retval.LdotH = dot(L,H); + retval.VdotH = nbl::hlsl::dot(V,H); + retval.LdotH = nbl::hlsl::dot(L,H); retval.NdotH2 = retval.NdotH * retval.NdotH; return true; } @@ -509,7 +511,7 @@ struct SIsotropicMicrofacetCache const vector3_type V = interaction.V.getDirection(); const vector3_type L = _sample.L; - const scalar_type VdotL = dot(V, L); + const scalar_type VdotL = nbl::hlsl::dot(V, L); return compute(retval,transmitted,V,L,interaction.N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); } template && ray_dir_info::Basic) @@ -592,7 +594,7 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache { this_t retval; - retval.VdotH = dot(tangentSpaceV,tangentSpaceH); + retval.VdotH = nbl::hlsl::dot(tangentSpaceV,tangentSpaceH); retval.LdotH = retval.VdotH; retval.NdotH = tangentSpaceH.z; retval.NdotH2 = retval.NdotH*retval.NdotH; @@ -649,8 +651,8 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache const bool valid = this_t::compute(retval,transmitted,V,L,N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); if (valid) { - retval.TdotH = dot(T,H); - retval.BdotH = dot(B,H); + retval.TdotH = nbl::hlsl::dot(T,H); + retval.BdotH = nbl::hlsl::dot(B,H); } return valid; } @@ -666,8 +668,8 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache const bool valid = this_t::compute(retval,interaction,_sample,eta,H); if (valid) { - retval.TdotH = dot(interaction.T,H); - retval.BdotH = dot(interaction.B,H); + retval.TdotH = nbl::hlsl::dot(interaction.T,H); + retval.BdotH = nbl::hlsl::dot(interaction.B,H); } return valid; } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 684c4cc1e6..fc7e6eee34 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -48,6 +48,7 @@ struct SLambertianBxDF { using this_t = SLambertianBxDF; using scalar_type = typename LightSample::scalar_type; + using ray_dir_info_type = typename LightSample::ray_dir_info_type; using isotropic_type = Iso; using anisotropic_type = Aniso; using sample_type = LightSample; @@ -80,7 +81,8 @@ struct SLambertianBxDF sample_type generate_wo_clamps(anisotropic_type interaction, vector u) { - vector L = projected_hemisphere_generate(u); + ray_dir_info_type L; + L.direction = projected_hemisphere_generate(u); return sample_type::createTangentSpace(interaction.getTangentSpaceV(), L, interaction.getTangentFrame()); } @@ -121,6 +123,7 @@ struct SOrenNayarBxDF using this_t = SOrenNayarBxDF; using scalar_type = typename LightSample::scalar_type; using vector2_type = vector; + using ray_dir_info_type = typename LightSample::ray_dir_info_type; using isotropic_type = Iso; using anisotropic_type = Aniso; @@ -158,7 +161,8 @@ struct SOrenNayarBxDF sample_type generate_wo_clamps(anisotropic_type interaction, vector2_type u) { - vector L = projected_hemisphere_generate(u); + ray_dir_info_type L; + L.direction = projected_hemisphere_generate(u); return sample_type::createTangentSpace(interaction.getTangentSpaceV(), L, interaction.getTangentFrame()); } @@ -204,6 +208,7 @@ struct SBlinnPhongBxDF { using this_t = SBlinnPhongBxDF; using scalar_type = typename LightSample::scalar_type; + using ray_dir_info_type = typename LightSample::ray_dir_info_type; using vector2_type = vector; using vector3_type = vector; using matrix2x3_type = matrix; @@ -324,7 +329,8 @@ struct SBlinnPhongBxDF const vector3_type localV = interaction.getTangentSpaceV(); cache = anisocache_type::create(localV, H); - vector3_type localL = math::reflect(localV, H, cache.VdotH); + ray_dir_info_type localL; + localL.direction = math::reflect(localV, H, cache.VdotH); return sample_type::createTangentSpace(localV, localL, interaction.getTangentFrame()); } @@ -340,6 +346,7 @@ struct SBeckmannBxDF { using this_t = SBeckmannBxDF; using scalar_type = typename LightSample::scalar_type; + using ray_dir_info_type = typename LightSample::ray_dir_info_type; using vector2_type = vector; using vector3_type = vector; using matrix2x3_type = matrix; @@ -468,7 +475,7 @@ struct SBeckmannBxDF const float MAX_ACCEPTABLE_ERR = 1.0e-5; int it = 0; float value=1000.0; - while (++it(value)>MAX_ACCEPTABLE_ERR) + while (++it(value)>MAX_ACCEPTABLE_ERR) { if (!(b>=a && b<=c)) b = 0.5 * (a+c); @@ -509,7 +516,8 @@ struct SBeckmannBxDF const vector3_type H = __generate(localV, u); cache = anisocache_type::create(localV, H); - vector3_type localL = math::reflect(localV, H, cache.VdotH); + ray_dir_info_type localL; + localL.direction = math::reflect(localV, H, cache.VdotH); return sample_type::createTangentSpace(localV, localL, interaction.getTangentFrame()); } @@ -600,6 +608,7 @@ struct SGGXBxDF { using this_t = SGGXBxDF; using scalar_type = typename LightSample::scalar_type; + using ray_dir_info_type = typename LightSample::ray_dir_info_type; using vector2_type = vector; using vector3_type = vector; using matrix2x3_type = matrix; @@ -723,7 +732,8 @@ struct SGGXBxDF const vector3_type H = __generate(localV, u); cache = anisocache_type::create(localV, H); - vector3_type localL = math::reflect(localV, H, cache.VdotH); + ray_dir_info_type localL; + localL.direction = math::reflect(localV, H, cache.VdotH); return sample_type::createTangentSpace(localV, localL, interaction.getTangentFrame()); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index b67990f410..5e2b7a47a6 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -48,6 +48,7 @@ struct SLambertianBxDF { using this_t = SLambertianBxDF; using scalar_type = typename LightSample::scalar_type; + using ray_dir_info_type = typename LightSample::ray_dir_info_type; using isotropic_type = Iso; using anisotropic_type = Aniso; using sample_type = LightSample; @@ -75,16 +76,17 @@ struct SLambertianBxDF scalar_type eval(sample_type _sample, isotropic_type interaction) { // probably doesn't need to use the param struct - return __eval_pi_factored_out(abs(_sample.NdotL)) * numbers::inv_pi * 0.5; + return __eval_pi_factored_out(nbl::hlsl::abs(_sample.NdotL)) * numbers::inv_pi * 0.5; } - sample_type generate_wo_clamps(anisotropic_type interaction, vector u) + sample_type generate_wo_clamps(anisotropic_type interaction, vector u) { - vector L = projected_sphere_generate(u); + ray_dir_info_type L; + L.direction = projected_sphere_generate(u); return sample_type::createTangentSpace(interaction.getTangentSpaceV(), L, interaction.getTangentFrame()); } - sample_type generate(anisotropic_type interaction, vector u) + sample_type generate(anisotropic_type interaction, vector u) { return generate_wo_clamps(interaction, u); } @@ -96,7 +98,7 @@ struct SLambertianBxDF scalar_type pdf(sample_type _sample, isotropic_type interaction) { - return projected_sphere_pdf(abs(_sample.NdotL)); + return projected_sphere_pdf(nbl::hlsl::abs(_sample.NdotL)); } quotient_pdf_type quotient_and_pdf_wo_clamps(sample_type _sample, isotropic_type interaction) @@ -109,7 +111,7 @@ struct SLambertianBxDF quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction) { scalar_type pdf; - scalar_type q = projected_sphere_quotient_and_pdf(pdf, abs(_sample.NdotL)); + scalar_type q = projected_sphere_quotient_and_pdf(pdf, nbl::hlsl::abs(_sample.NdotL)); return quotient_pdf_type::create(spectral_type(q), pdf); } }; @@ -152,7 +154,7 @@ struct SSmoothDielectricBxDF transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); const vector3_type L = math::reflectRefract(transmitted, V, N, backside, NdotV, NdotV2, rcpOrientedEta, rcpOrientedEta2); - return sample_type::create(L, dot(V, L), T, B, N); + return sample_type::create(L, nbl::hlsl::dot(V, L), T, B, N); } sample_type generate_wo_clamps(anisotropic_type interaction, NBL_REF_ARG(vector) u) // TODO: check vector3_type? @@ -170,7 +172,7 @@ struct SSmoothDielectricBxDF const bool backside = math::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.NdotV, eta); bool dummy; return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, backside, interaction.NdotV, - abs(interaction.NdotV), interaction.NdotV*interaction.NdotV, u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, dummy); + nbl::hlsl::abs(interaction.NdotV), interaction.NdotV*interaction.NdotV, u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, dummy); } // where pdf? @@ -226,14 +228,14 @@ struct SSmoothDielectricBxDF const vector3_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2,absNdotV)); // we are only allowed one choice for the entire ray, so make the probability a weighted sum - const scalar_type reflectionProb = dot(reflectance, luminosityContributionHint); + const scalar_type reflectionProb = nbl::hlsl::dot(reflectance, luminosityContributionHint); scalar_type rcpChoiceProb; const bool transmitted = math::partitionRandVariable(reflectionProb, u.z, rcpChoiceProb); remainderMetadata = (transmitted ? ((vector3_type)(1.0) - reflectance) : reflectance) * rcpChoiceProb; const vector3_type L = (transmitted ? (vector3_type)(0.0) : N * 2.0 * NdotV) - V; - return sample_type::create(L, dot(V, L), T, B, N); + return sample_type::create(L, nbl::hlsl::dot(V, L), T, B, N); } sample_type generate_wo_clamps(anisotropic_type interaction, NBL_REF_ARG(vector) u) // TODO: check vector3_type? @@ -243,7 +245,7 @@ struct SSmoothDielectricBxDF sample_type generate(anisotropic_type interaction, NBL_REF_ARG(vector) u) { - return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, interaction.NdotV, abs(interaction.NdotV), u, eta2, luminosityContributionHint); + return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, interaction.NdotV, nbl::hlsl::abs(interaction.NdotV), u, eta2, luminosityContributionHint); } // where pdf? @@ -254,7 +256,7 @@ struct SSmoothDielectricBxDF const vector3_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, interaction.NdotV)); const vector3_type sampleValue = transmitted ? ((vector3_type)(1.0) - reflectance) : reflectance; - const scalar_type sampleProb = dot(sampleValue,luminosityContributionHint); + const scalar_type sampleProb = nbl::hlsl::dot(sampleValue,luminosityContributionHint); const scalar_type pdf = 1.0 / 0.0; return quotient_pdf_type::create(spectral_type(sampleValue / sampleProb), pdf); @@ -263,10 +265,10 @@ struct SSmoothDielectricBxDF quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction) { const bool transmitted = isTransmissionPath(interaction.NdotV, _sample.NdotL); - const vector3_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, abs(interaction.NdotV))); + const vector3_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, nbl::hlsl::abs(interaction.NdotV))); const vector3_type sampleValue = transmitted ? ((vector3_type)(1.0) - reflectance) : reflectance; - const scalar_type sampleProb = dot(sampleValue,luminosityContributionHint); + const scalar_type sampleProb = nbl::hlsl::dot(sampleValue,luminosityContributionHint); const scalar_type pdf = 1.0 / 0.0; return quotient_pdf_type::create(spectral_type(sampleValue / sampleProb), pdf); @@ -281,6 +283,7 @@ struct SBeckmannDielectricBxDF { using this_t = SBeckmannDielectricBxDF; using scalar_type = typename LightSample::scalar_type; + using ray_dir_info_type = typename LightSample::ray_dir_info_type; using vector2_type = vector; using vector3_type = vector; using matrix3x3_type = matrix; @@ -325,8 +328,8 @@ struct SBeckmannDielectricBxDF const scalar_type scalar_part = beckmann.template __eval_DG_wo_clamps(params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,abs(interaction.NdotV),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); - return fresnelDielectric_common(orientedEta2, abs(cache.VdotH)) * microfacet_transform(); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,nbl::hlsl::abs(interaction.NdotV),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); + return fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); } vector3_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) @@ -344,14 +347,14 @@ struct SBeckmannDielectricBxDF const scalar_type scalar_part = beckmann.template __eval_DG_wo_clamps(params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,abs(interaction.NdotV),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); - return fresnelDielectric_common(orientedEta2, abs(cache.VdotH)) * microfacet_transform(); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,nbl::hlsl::abs(interaction.NdotV),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); + return fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); } sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix3x3_type m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) { - const scalar_type VdotH = dot(localV,H); - const scalar_type reflectance = fresnelDielectric_common(orientedEta2,abs(VdotH)); + const scalar_type VdotH = nbl::hlsl::dot(localV,H); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2,nbl::hlsl::abs(VdotH)); scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); @@ -360,7 +363,8 @@ struct SBeckmannDielectricBxDF const scalar_type VdotH = cache.VdotH; cache.LdotH = transmitted ? reflectRefract_computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; - vector3_type localL = math::reflectRefract_impl(transmitted, localV, H, VdotH, cache.LdotH, rcpOrientedEta); + ray_dir_info_type localL; + localL.direction = math::reflectRefract_impl(transmitted, localV, H, VdotH, cache.LdotH, rcpOrientedEta); return sample_type::createTangentSpace(localV, localL, m); } @@ -415,9 +419,9 @@ struct SBeckmannDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); - const scalar_type absNdotV = abs(interaction.NdotV); + const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); return pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, interaction.NdotV2, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta, dummy); } @@ -438,9 +442,9 @@ struct SBeckmannDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); - const scalar_type absNdotV = abs(interaction.NdotV); + const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); return pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.VdotH, cache.LdotH, VdotHLdotH, ax2, ay2, orientedEta, dummy); } @@ -458,8 +462,8 @@ struct SBeckmannDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); - const scalar_type absNdotV = abs(interaction.NdotV); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); + const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); scalar_type onePlusLambda_V; scalar_type pdf = pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, interaction.NdotV2, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta, dummy); @@ -488,8 +492,8 @@ struct SBeckmannDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); - const scalar_type absNdotV = abs(interaction.NdotV); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); + const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); scalar_type onePlusLambda_V; scalar_type pdf = pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.VdotH, cache.LdotH, VdotHLdotH, ax2, ay2, orientedEta, dummy); @@ -510,6 +514,7 @@ struct SGGXDielectricBxDF { using this_t = SGGXDielectricBxDF; using scalar_type = typename LightSample::scalar_type; + using ray_dir_info_type = typename LightSample::ray_dir_info_type; using vector2_type = vector; using vector3_type = vector; using matrix3x3_type = matrix; @@ -555,7 +560,7 @@ struct SGGXDielectricBxDF ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,abs(_sample.NdotL),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); - return fresnelDielectric_common(orientedEta2, abs(cache.VdotH)) * microfacet_transform(); + return fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); } vector3_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) @@ -574,13 +579,13 @@ struct SGGXDielectricBxDF ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,abs(_sample.NdotL),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); - return fresnelDielectric_common(orientedEta2, abs(cache.VdotH)) * microfacet_transform(); + return fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); } sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix3x3_type m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) { - const scalar_type VdotH = dot(localV,H); - const scalar_type reflectance = fresnelDielectric_common(orientedEta2,abs(VdotH)); + const scalar_type VdotH = nbl::hlsl::dot(localV,H); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2,nbl::hlsl::abs(VdotH)); scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); @@ -589,7 +594,8 @@ struct SGGXDielectricBxDF const scalar_type VdotH = cache.VdotH; cache.LdotH = transmitted ? reflectRefract_computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; - vector3_type localL = math::reflectRefract_impl(transmitted, localV, H, VdotH, cache.LdotH, rcpOrientedEta); + ray_dir_info_type localL; + localL.direction = math::reflectRefract_impl(transmitted, localV, H, VdotH, cache.LdotH, rcpOrientedEta); return sample_type::createTangentSpace(localV, localL, m); } @@ -642,9 +648,9 @@ struct SGGXDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); - const scalar_type absNdotV = abs(interaction.NdotV); + const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); return pdf_wo_clamps(transmitted, reflectance, ndf, devsh_v, absNdotV, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta); } @@ -668,9 +674,9 @@ struct SGGXDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); - const scalar_type absNdotV = abs(interaction.NdotV); + const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); return pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.VdotH, cache.LdotH, VdotHLdotH, ax2, ay2, orientedEta, dummy); } @@ -693,9 +699,9 @@ struct SGGXDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); - const scalar_type absNdotV = abs(interaction.NdotV); + const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); scalar_type pdf = pdf_wo_clamps(transmitted, reflectance, ndf, devsh_v, absNdotV, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta); smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.NdotV, params.NdotV2, params.NdotL, params.NdotL2); @@ -724,8 +730,8 @@ struct SGGXDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, abs(cache.VdotH)); - const scalar_type absNdotV = abs(interaction.NdotV); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); + const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); scalar_type pdf = pdf_wo_clamps(transmitted, reflectance, ndf, devsh_v, absNdotV, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta); diff --git a/include/nbl/builtin/hlsl/sampling/concentric_mapping.hlsl b/include/nbl/builtin/hlsl/sampling/concentric_mapping.hlsl index a1ba89a1ff..2b06581740 100644 --- a/include/nbl/builtin/hlsl/sampling/concentric_mapping.hlsl +++ b/include/nbl/builtin/hlsl/sampling/concentric_mapping.hlsl @@ -13,7 +13,7 @@ template vector concentricMapping(vector _u) { //map [0;1]^2 to [-1;1]^2 - vector u = 2.0 * _u - 1.0; + vector u = 2.0f * _u - 1.0f; vector p; if (u == (vector)(0.0)) diff --git a/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl b/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl index 4c3961f26f..4f2989d0f9 100644 --- a/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl +++ b/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl @@ -23,7 +23,7 @@ struct ProjectedHemisphere static vector_t3 generate(vector_t2 _sample) { - vector_t2 p = concentricMapping(_sample * 0.99999 + 0.000005); + vector_t2 p = concentricMapping(_sample * 0.99999f + 0.000005f); T z = sqrt(max(0.0, 1.0 - p.x * p.x - p.y * p.y)); return vector_t3(p.x, p.y, z); } @@ -33,9 +33,9 @@ struct ProjectedHemisphere return L_z * numbers::inv_pi; } - static T quotient_and_pdf(NBL_REF_ARG(T) pdf, T L) + static T quotient_and_pdf(NBL_REF_ARG(T) _pdf, T L) { - pdf = pdf(L); + _pdf = pdf(L); return 1.0; } }; From 3b78a0639ac49b8bde013da5be5ab3086ac1568d Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 25 Dec 2024 11:23:06 +0700 Subject: [PATCH 042/188] more bug fixes --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 6 ++-- include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl | 8 ++--- include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 8 ++--- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 30 +++++++++++++------ 4 files changed, 32 insertions(+), 20 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 1d63832907..4ec27e77d3 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -853,7 +853,7 @@ struct SBxDFParams return retval; } - template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + template && surface_interactions::Anisotropic)// TODO: && AnisotropicMicrofacetCache) static SBxDFParams create(LightSample _sample, Aniso interaction, Cache cache) { this_t retval; @@ -906,7 +906,7 @@ struct fresnel //const float sinTheta2 = 1.0 - cosTheta2; const vector_t etaLen2 = eta * eta + etak * etak; - const vector_t etaCosTwice = eta * cosTheta * 2.0; + const vector_t etaCosTwice = eta * cosTheta * 2.0f; const vector_t rs_common = etaLen2 + (vector_t)(cosTheta2); const vector_t rs2 = (rs_common - etaCosTwice) / (rs_common + etaCosTwice); @@ -914,7 +914,7 @@ struct fresnel const vector_t rp_common = etaLen2 * cosTheta2 + (vector_t)(1.0); const vector_t rp2 = (rp_common - etaCosTwice) / (rp_common + etaCosTwice); - return (rs2 + rp2)*0.5; + return (rs2 + rp2) * 0.5f; } template diff --git a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl index a825448563..cf3cda81c9 100644 --- a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl @@ -79,7 +79,7 @@ struct SIsotropicParams retval.NdotV2 = NdotV2; retval.NdotL2 = NdotL2; retval.lambdaV_plus_one = lambdaV_plus_one; - return this_t; + return retval; } static this_t create(T a2, T NdotV, T NdotV2, T NdotL, T NdotL2) // ggx @@ -91,7 +91,7 @@ struct SIsotropicParams retval.NdotL = NdotL; retval.NdotL2 = NdotL2; retval.one_minus_a2 = 1.0 - a2; - return this_t; + return retval; } T a2; @@ -120,7 +120,7 @@ struct SAnisotropicParams retval.BdotL2 = BdotL2; retval.NdotL2 = NdotL2; retval.lambdaV_plus_one = lambdaV_plus_one; - return this_t; + return retval; } static this_t create(T ax2, T ay2, T NdotV, T TdotV2, T BdotV2, T NdotV2, T NdotL, T TdotL2, T BdotL2, T NdotL2) // ggx @@ -136,7 +136,7 @@ struct SAnisotropicParams retval.TdotL2 = TdotL2; retval.BdotL2 = BdotL2; retval.NdotL2 = NdotL2; - return this_t; + return retval; } T ax2; diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl index 15f1a13988..f57563250a 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -27,7 +27,7 @@ struct SIsotropicParams retval.n_or_a2 = n_or_a2; retval.NdotH = NdotH; retval.NdotH2 = NdotH2; - return this_t; + return retval; } T n_or_a2; @@ -49,7 +49,7 @@ struct SAnisotropicParams retval.BdotH2 = BdotH2; retval.nx = nx; retval.ny = ny; - return this_t; + return retval; } static this_t create(T ax, T ay, T ax2, T ay2, T TdotH2, T BdotH2, T NdotH2) // beckmann, ggx aniso @@ -62,7 +62,7 @@ struct SAnisotropicParams retval.TdotH2 = TdotH2; retval.BdotH2 = BdotH2; retval.NdotH2 = NdotH2; - return this_t; + return retval; } static this_t create(T a2, T TdotH, T BdotH, T NdotH) // ggx burley @@ -72,7 +72,7 @@ struct SAnisotropicParams retval.TdotH = TdotH; retval.BdotH = BdotH; retval.NdotH = NdotH; - return this_t; + return retval; } T ax; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index fc7e6eee34..7e5fd09e5e 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -341,7 +341,7 @@ struct SBlinnPhongBxDF matrix2x3_type ior; }; -template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) +template)// && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SBeckmannBxDF { using this_t = SBeckmannBxDF; @@ -417,7 +417,11 @@ struct SBeckmannBxDF { scalar_type scalar_part = __eval_DG_wo_clamps(params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotV); - return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_transform(); +#ifdef __HLSL_VERSION + return fresnelConductor(ior._m00_m10_m20, iorior._m01_m11_m21, params.VdotH) * microfacet_transform(); +#else + return fresnelConductor(vector3_type(ior[0][0],ior[0][1],ior[0][2]), vector3_type(ior[1][0],ior[1][1],ior[1][2]), params.VdotH) * microfacet_transform(); +#endif } vector3_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) @@ -445,7 +449,7 @@ struct SBeckmannBxDF vector3_type __generate(vector3_type localV, vector2_type u) { //stretch - vector3_type V = normalize(vector3_type(A.x * localV.x, A.y * localV.y, localV.z)); + vector3_type V = nbl::hlsl::normalize(vector3_type(A.x * localV.x, A.y * localV.y, localV.z)); vector2_type slope; if (V.z > 0.9999)//V.z=NdotV=cosTheta in tangent space @@ -507,7 +511,7 @@ struct SBeckmannBxDF //unstretch slope = vector2_type(A.x,A.y)*slope; - return normalize(vector3_type(-slope, 1.0)); + return nbl::hlsl::normalize(vector3_type(-slope, 1.0)); } sample_type generate(anisotropic_type interaction, vector2_type u, NBL_REF_ARG(anisocache_type) cache) @@ -564,7 +568,11 @@ struct SBeckmannBxDF if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, 0, _sample.NdotL2, onePlusLambda_V); - const vector3_type reflectance = fresnelConductor(ior[0], ior[1], cache.VdotH); +#ifdef __HLSL_VERSION + const vector3_type reflectance = fresnelConductor(ior._m00_m10_m20, iorior._m01_m11_m21, cache.VdotH); +#else + const vector3_type reflectance = fresnelConductor(vector3_type(ior[0][0],ior[0][1],ior[0][2]), vector3_type(ior[1][0],ior[1][1],ior[1][2]), cache.VdotH); +#endif scalar_type G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); quo = reflectance * G2_over_G1; } @@ -580,7 +588,7 @@ struct SBeckmannBxDF ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); ndf::Beckmann beckmann_ndf; - scalar_type ndf = backmann_ndf(ndfparams); + scalar_type ndf = beckmann_ndf(ndfparams); smith::Beckmann beckmann_smith; scalar_type onePlusLambda_V; @@ -591,7 +599,11 @@ struct SBeckmannBxDF if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, onePlusLambda_V); - const vector3_type reflectance = fresnel_conductor(ior[0], ior[1], cache.VdotH); +#ifdef __HLSL_VERSION + const vector3_type reflectance = fresnelConductor(ior._m00_m10_m20, iorior._m01_m11_m21, cache.VdotH); +#else + const vector3_type reflectance = fresnelConductor(vector3_type(ior[0][0],ior[0][1],ior[0][2]), vector3_type(ior[1][0],ior[1][1],ior[1][2]), cache.VdotH); +#endif scalar_type G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); quo = reflectance * G2_over_G1; } @@ -706,7 +718,7 @@ struct SGGXBxDF vector3_type __generate(vector3_type localV, vector2_type u) { - vector3_type V = normalize(vector3_type(A.x*localV.x, A.y*localV.y, localV.z));//stretch view vector so that we're sampling as if roughness=1.0 + vector3_type V = nbl::hlsl::normalize(vector3_type(A.x*localV.x, A.y*localV.y, localV.z));//stretch view vector so that we're sampling as if roughness=1.0 scalar_type lensq = V.x*V.x + V.y*V.y; vector3_type T1 = lensq > 0.0 ? vector3_type(-V.y, V.x, 0.0) * rsqrt(lensq) : vector3_type(1.0,0.0,0.0); @@ -723,7 +735,7 @@ struct SGGXBxDF //TODO try it wothout the max(), not sure if -t1*t1-t2*t2>-1.0 vector3_type H = t1*T1 + t2*T2 + sqrt(max(0.0, 1.0-t1*t1-t2*t2))*V; //unstretch - return normalize(vector3_type(A.x*H.x, A.y*H.y, H.z)); + return nbl::hlsl::normalize(vector3_type(A.x*H.x, A.y*H.y, H.z)); } sample_type generate(anisotropic_type interaction, vector2_type u, NBL_REF_ARG(anisocache_type) cache) From 5bfdf2f9ba2ffa88002b65cb33d2c8ef0bbb0567 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 25 Dec 2024 15:44:37 +0700 Subject: [PATCH 043/188] lots more typo fixes --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 14 ++-- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 2 +- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 66 +++++++++---------- 3 files changed, 41 insertions(+), 41 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 4ec27e77d3..8842343098 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -389,6 +389,7 @@ struct SLightSample }; +// TODO: figure out the commented constraints, templated RayDirInfo not really working for some reason #define NBL_CONCEPT_NAME IsotropicMicrofacetCache #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) #define NBL_CONCEPT_TPLT_PRM_NAMES (T) @@ -417,10 +418,10 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.NdotH2), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(pNdotV,pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(iso,_sample)), ::nbl::hlsl::is_same_v, T)) + //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(iso,_sample)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::compute(cache,b0,V,V,V,pNdotV,pNdotV,pNdotV,pNdotV,V)), ::nbl::hlsl::is_same_v, bool)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,iso,_sample,pNdotV,V)), ::nbl::hlsl::is_same_v, bool)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,iso,_sample,pNdotV)), ::nbl::hlsl::is_same_v, bool)) + //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,iso,_sample,pNdotV,V)), ::nbl::hlsl::is_same_v, bool)) + //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,iso,_sample,pNdotV)), ::nbl::hlsl::is_same_v, bool)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.isValidVNDFMicrofacet(b0,b0,pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, bool)) ) && surface_interactions::Isotropic; #undef b0 @@ -565,9 +566,9 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V,b0,pNdotL,pNdotL)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(V,V,pNdotL)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(aniso,_sample)), ::nbl::hlsl::is_same_v, T)) + //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(aniso,_sample)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::compute(cache,b0,V,V,V,V,V,pNdotL,pNdotL,pNdotL,pNdotL,V)), ::nbl::hlsl::is_same_v, bool)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,aniso,_sample)), ::nbl::hlsl::is_same_v, bool)) + //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,aniso,_sample)), ::nbl::hlsl::is_same_v, bool)) ) && surface_interactions::Anisotropic; #undef b0 #undef V @@ -679,7 +680,6 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache }; -// don't know what this concept is for yet #define NBL_CONCEPT_NAME generalized_spectral_of #define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename) #define NBL_CONCEPT_TPLT_PRM_NAMES (T)(F) @@ -853,7 +853,7 @@ struct SBxDFParams return retval; } - template && surface_interactions::Anisotropic)// TODO: && AnisotropicMicrofacetCache) + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) static SBxDFParams create(LightSample _sample, Aniso interaction, Cache cache) { this_t retval; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 7e5fd09e5e..d66bb50dc0 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -341,7 +341,7 @@ struct SBlinnPhongBxDF matrix2x3_type ior; }; -template)// && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) +template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SBeckmannBxDF { using this_t = SBeckmannBxDF; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index 5e2b7a47a6..553da3f147 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -137,7 +137,7 @@ struct SSmoothDielectricBxDF using isocache_type = IsoCache; using anisocache_type = AnisoCache; - static this_t create(vector3_type eta) + static this_t create(scalar_type eta) { this_t retval; retval.eta = eta; @@ -148,7 +148,7 @@ struct SSmoothDielectricBxDF sample_type __generate_wo_clamps(vector3_type V, vector3_type T, vector3_type B, vector3_type N, bool backside, scalar_type NdotV, scalar_type absNdotV, scalar_type NdotV2, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(bool) transmitted) { - const vector3_type reflectance = fresnelDielectric_common(orientedEta2, absNdotV); + const vector3_type reflectance = fresnelDielectric_common(orientedEta2, absNdotV); scalar_type rcpChoiceProb; transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); @@ -189,7 +189,7 @@ struct SSmoothDielectricBxDF return quotient_pdf_type::create(spectral_type(quo), pdf); } - vector3_type eta; + scalar_type eta; }; template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) @@ -225,7 +225,7 @@ struct SSmoothDielectricBxDF sample_type __generate_wo_clamps(vector3_type V, vector3_type T, vector3_type B, vector3_type N, scalar_type NdotV, scalar_type absNdotV, NBL_REF_ARG(vector3_type) u, vector3_type eta2, vector3_type luminosityContributionHint, NBL_REF_ARG(vector3_type) remainderMetadata) { // we will only ever intersect from the outside - const vector3_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2,absNdotV)); + const vector3_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2,absNdotV)); // we are only allowed one choice for the entire ray, so make the probability a weighted sum const scalar_type reflectionProb = nbl::hlsl::dot(reflectance, luminosityContributionHint); @@ -253,7 +253,7 @@ struct SSmoothDielectricBxDF quotient_pdf_type quotient_and_pdf_wo_clamps(sample_type _sample, isotropic_type interaction) { const bool transmitted = isTransmissionPath(interaction.NdotV, _sample.NdotL); - const vector3_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, interaction.NdotV)); + const vector3_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, interaction.NdotV)); const vector3_type sampleValue = transmitted ? ((vector3_type)(1.0) - reflectance) : reflectance; const scalar_type sampleProb = nbl::hlsl::dot(sampleValue,luminosityContributionHint); @@ -265,7 +265,7 @@ struct SSmoothDielectricBxDF quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction) { const bool transmitted = isTransmissionPath(interaction.NdotV, _sample.NdotL); - const vector3_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, nbl::hlsl::abs(interaction.NdotV))); + const vector3_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, nbl::hlsl::abs(interaction.NdotV))); const vector3_type sampleValue = transmitted ? ((vector3_type)(1.0) - reflectance) : reflectance; const scalar_type sampleProb = nbl::hlsl::dot(sampleValue,luminosityContributionHint); @@ -297,7 +297,7 @@ struct SBeckmannDielectricBxDF using isocache_type = IsoCache; using anisocache_type = AnisoCache; - static this_t create(vector3_type eta, scalar_type A) + static this_t create(scalar_type eta, scalar_type A) { this_t retval; retval.eta = eta; @@ -305,7 +305,7 @@ struct SBeckmannDielectricBxDF return retval; } - static this_t create(vector3_type eta, scalar_type ax, scalar_type ay) + static this_t create(scalar_type eta, scalar_type ax, scalar_type ay) { this_t retval; retval.eta = eta; @@ -329,7 +329,7 @@ struct SBeckmannDielectricBxDF ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,nbl::hlsl::abs(interaction.NdotV),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); - return fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); + return (vector3_type)fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); } vector3_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) @@ -348,13 +348,13 @@ struct SBeckmannDielectricBxDF ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,nbl::hlsl::abs(interaction.NdotV),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); - return fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); + return (vector3_type)fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); } sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix3x3_type m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) { - const scalar_type VdotH = nbl::hlsl::dot(localV,H); - const scalar_type reflectance = fresnelDielectric_common(orientedEta2,nbl::hlsl::abs(VdotH)); + const scalar_type localVdotH = nbl::hlsl::dot(localV,H); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2,nbl::hlsl::abs(localVdotH)); scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); @@ -362,7 +362,7 @@ struct SBeckmannDielectricBxDF cache = anisocache_type::create(localV, H); const scalar_type VdotH = cache.VdotH; - cache.LdotH = transmitted ? reflectRefract_computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; + cache.LdotH = transmitted ? math::reflectRefract_computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; ray_dir_info_type localL; localL.direction = math::reflectRefract_impl(transmitted, localV, H, VdotH, cache.LdotH, rcpOrientedEta); @@ -382,7 +382,7 @@ struct SBeckmannDielectricBxDF reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior); const vector3_type H = beckmann.__generate(upperHemisphereV, u.xy); - return __generate_wo_clamps(localV, backside, H, interaction.getTangentFrame(), rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, cache); + return __generate_wo_clamps(localV, backside, H, interaction.getTangentFrame(), u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, cache); } sample_type generate(anisotropic_type interaction, NBL_REF_ARG(vector3_type) u) @@ -419,7 +419,7 @@ struct SBeckmannDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); return pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, interaction.NdotV2, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta, dummy); @@ -433,7 +433,7 @@ struct SBeckmannDielectricBxDF ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); ndf::Beckmann beckmann_ndf; - scalar_type ndf = backmann_ndf(ndfparams); + scalar_type ndf = beckmann_ndf(ndfparams); scalar_type orientedEta, dummy; const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); @@ -442,7 +442,7 @@ struct SBeckmannDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); return pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.VdotH, cache.LdotH, VdotHLdotH, ax2, ay2, orientedEta, dummy); @@ -462,7 +462,7 @@ struct SBeckmannDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); scalar_type onePlusLambda_V; @@ -483,7 +483,7 @@ struct SBeckmannDielectricBxDF ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); ndf::Beckmann beckmann_ndf; - scalar_type ndf = backmann_ndf(ndfparams); + scalar_type ndf = beckmann_ndf(ndfparams); scalar_type orientedEta, dummy; const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); @@ -492,7 +492,7 @@ struct SBeckmannDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); scalar_type onePlusLambda_V; @@ -506,7 +506,7 @@ struct SBeckmannDielectricBxDF } vector2_type A; - vector3_type eta; + scalar_type eta; }; template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) @@ -528,7 +528,7 @@ struct SGGXDielectricBxDF using isocache_type = IsoCache; using anisocache_type = AnisoCache; - static this_t create(vector3_type eta, scalar_type A) + static this_t create(scalar_type eta, scalar_type A) { this_t retval; retval.eta = eta; @@ -536,7 +536,7 @@ struct SGGXDielectricBxDF return retval; } - static this_t create(vector3_type eta, scalar_type ax, scalar_type ay) + static this_t create(scalar_type eta, scalar_type ax, scalar_type ay) { this_t retval; retval.eta = eta; @@ -560,7 +560,7 @@ struct SGGXDielectricBxDF ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,abs(_sample.NdotL),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); - return fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); + return fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); } vector3_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) @@ -579,13 +579,13 @@ struct SGGXDielectricBxDF ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,abs(_sample.NdotL),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); - return fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); + return fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); } sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix3x3_type m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) { const scalar_type VdotH = nbl::hlsl::dot(localV,H); - const scalar_type reflectance = fresnelDielectric_common(orientedEta2,nbl::hlsl::abs(VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2,nbl::hlsl::abs(VdotH)); scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); @@ -593,7 +593,7 @@ struct SGGXDielectricBxDF cache = anisocache_type::create(localV, H); const scalar_type VdotH = cache.VdotH; - cache.LdotH = transmitted ? reflectRefract_computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; + cache.LdotH = transmitted ? math::reflectRefract_computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; ray_dir_info_type localL; localL.direction = math::reflectRefract_impl(transmitted, localV, H, VdotH, cache.LdotH, rcpOrientedEta); @@ -613,7 +613,7 @@ struct SGGXDielectricBxDF reflection::SGGXBxDF ggx = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior); const vector3_type H = ggx.__generate(upperHemisphereV, u.xy); - return __generate_wo_clamps(localV, backside, H, interaction.getTangentFrame(), rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, cache); + return __generate_wo_clamps(localV, backside, H, interaction.getTangentFrame(), u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, cache); } sample_type generate(anisotropic_type interaction, NBL_REF_ARG(vector3_type) u) @@ -648,7 +648,7 @@ struct SGGXDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); return pdf_wo_clamps(transmitted, reflectance, ndf, devsh_v, absNdotV, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta); @@ -674,7 +674,7 @@ struct SGGXDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); return pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.VdotH, cache.LdotH, VdotHLdotH, ax2, ay2, orientedEta, dummy); @@ -699,7 +699,7 @@ struct SGGXDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); scalar_type pdf = pdf_wo_clamps(transmitted, reflectance, ndf, devsh_v, absNdotV, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta); @@ -730,7 +730,7 @@ struct SGGXDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); scalar_type pdf = pdf_wo_clamps(transmitted, reflectance, ndf, devsh_v, absNdotV, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta); @@ -742,7 +742,7 @@ struct SGGXDielectricBxDF } vector2_type A; - vector3_type eta; + scalar_type eta; }; } From ecdbbf7b05c3645baabeb52035d9657ec228fa68 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 26 Dec 2024 11:18:15 +0700 Subject: [PATCH 044/188] final? bxdf concept, bug fixes --- examples_tests | 2 +- include/nbl/builtin/hlsl/bxdf/common.hlsl | 4 ++-- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 4 ---- include/nbl/builtin/hlsl/math/functions.hlsl | 19 +++++++++---------- 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/examples_tests b/examples_tests index 32f959d5f9..382c862cd2 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 32f959d5f98d63e402dbbf2f65366078b67c77cc +Subproject commit 382c862cd2a491285cb374281c4685789fa3ab89 diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 8842343098..83a24c931d 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -792,10 +792,10 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) ((NBL_CONCEPT_REQ_TYPE)(T::isocache_type)) ((NBL_CONCEPT_REQ_TYPE)(T::anisocache_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.generate(_sample,iso,isocache)), ::nbl::hlsl::is_same_v, vector)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.eval(_sample,iso,isocache)), ::nbl::hlsl::is_same_v, vector)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.generate(aniso,aniso.N,anisocache)), ::nbl::hlsl::is_same_v, typename T::sample_type)) //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template pdf(_sample,iso)), ::nbl::hlsl::is_scalar_v)) - //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template quotient_and_pdf(_sample,iso)), ::nbl::hlsl::is_same_v, Q)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.quotient_and_pdf(_sample,iso,isocache)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) ) && Sample && spectral_of && IsotropicMicrofacetCache && AnisotropicMicrofacetCache; #undef anisocache diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index d66bb50dc0..482571b039 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -38,10 +38,6 @@ quotient_and_pdf cos_quotient_and_pdf() return quotient_and_pdf::create(SpectralBins(1.f), numeric_limits::infinity); } -// new bxdf structure -// static create() method, takes light sample and interaction (and cache) as argument --> fill in _dot_ variables used in later calculations, return bxdf struct -// store them as well? - template && surface_interactions::Isotropic && surface_interactions::Anisotropic) struct SLambertianBxDF diff --git a/include/nbl/builtin/hlsl/math/functions.hlsl b/include/nbl/builtin/hlsl/math/functions.hlsl index 30bd11cecd..82aaca651e 100644 --- a/include/nbl/builtin/hlsl/math/functions.hlsl +++ b/include/nbl/builtin/hlsl/math/functions.hlsl @@ -84,7 +84,7 @@ scalar_type_t lpNorm(NBL_CONST_REF_ARG(T) v) template ) vector reflect(vector I, vector N, T NdotI) { - return N * 2.0 * NdotI - I; + return N * 2.0f * NdotI - I; } template ) @@ -217,29 +217,28 @@ struct refract template) vector refract(vector I, vector N, bool backside, T NdotI, T NdotI2, T rcpOrientedEta, T rcpOrientedEta2) { - impl::refract r = impl::refract::create(I, N, backside, NdotI, NdotI2, rcpOrientedEta, rcpOrientedEta2); + impl::refract r = impl::refract::create(I, N, backside, NdotI, NdotI2, rcpOrientedEta, rcpOrientedEta2); return r.doRefract(); } template) vector refract(vector I, vector N, T NdotI, T eta) { - impl::refract r = impl::refract::create(I, N, NdotI, eta); + impl::refract r = impl::refract::create(I, N, NdotI, eta); return r.doRefract(); } template) vector refract(vector I, vector N, T eta) { - impl::refract r = impl::refract::create(I, N, eta); + impl::refract r = impl::refract::create(I, N, eta); return r.doRefract(); } -// I don't like exposing these next two template) -vector reflectRefract_computeNdotT(bool backside, T NdotI2, T rcpOrientedEta2) +T reflectRefract_computeNdotT(bool backside, T NdotI2, T rcpOrientedEta2) { - impl::refract r; + impl::refract r; r.NdotI2 = NdotI2; r.rcpOrientedEta2 = rcpOrientedEta2; r.backside = backside; @@ -249,20 +248,20 @@ vector reflectRefract_computeNdotT(bool backside, T NdotI2, T rcpOrientedEt template) vector reflectRefract_impl(bool _refract, vector _I, vector _N, T _NdotI, T _NdotTorR, T _rcpOrientedEta) { - return impl::refract::doReflectRefract(_refract, _I, _N, _NdotI, _NdotTorR, _rcpOrientedEta); + return impl::refract::doReflectRefract(_refract, _I, _N, _NdotI, _NdotTorR, _rcpOrientedEta); } template) vector reflectRefract(bool _refract, vector I, vector N, bool backside, T NdotI, T NdotI2, T rcpOrientedEta, T rcpOrientedEta2) { - impl::refract r = impl::refract::create(I, N, backside, NdotI, NdotI2, rcpOrientedEta, rcpOrientedEta2); + impl::refract r = impl::refract::create(I, N, backside, NdotI, NdotI2, rcpOrientedEta, rcpOrientedEta2); return r.doReflectRefract(_refract); } template) vector reflectRefract(bool _refract, vector I, vector N, T NdotI, T eta) { - impl::refract r = impl::refract::create(I, N, NdotI, eta); + impl::refract r = impl::refract::create(I, N, NdotI, eta); return r.doReflectRefract(_refract); } From 9d2a2f325d9b65f19cdeb6173b00f9aa49901efb Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 3 Jan 2025 15:22:45 +0700 Subject: [PATCH 045/188] bug fixes --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 10 +++++----- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 83a24c931d..3614704228 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -219,11 +219,11 @@ struct SAnisotropic : SIsotropic ) { SAnisotropic retval; - (SIsotropic) retval = isotropic; - // retval.V = isotropic.V; - // retval.N = isotropic.N; - // retval.NdotV = isotropic.NdotV; - // retval.NdotV2 = isotropic.NdotV2; + //(SIsotropic) retval = isotropic; + retval.V = isotropic.V; + retval.N = isotropic.N; + retval.NdotV = isotropic.NdotV; + retval.NdotV2 = isotropic.NdotV2; retval.T = normalizedT; retval.B = normalizedB; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 482571b039..ef6b271845 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -246,7 +246,7 @@ struct SBlinnPhongBxDF ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(params.NdotH, 1.0 / (1.0 - params.NdotH2), params.TdotH2, params.BdotH2, n.x, n.y); ndf::BlinnPhong blinn_phong; scalar_type DG = blinn_phong(ndfparams); - if (any(a2 > numeric_limits::min)) + if (any>(a2 > (vector2_type)numeric_limits::min)) { smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(a2.x, a2.y, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, 0); smith::Beckmann beckmann; @@ -259,7 +259,7 @@ struct SBlinnPhongBxDF ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(n, params.NdotH, params.NdotH2); ndf::BlinnPhong blinn_phong; scalar_type NG = blinn_phong(ndfparams); - if (any(a2 > numeric_limits::min)) + if (any>(a2 > (vector2_type)numeric_limits::min)) { smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2.x, params.NdotV2, params.NdotL2, 0); smith::Beckmann beckmann; @@ -384,7 +384,7 @@ struct SBeckmannBxDF ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); ndf::Beckmann beckmann_ndf; scalar_type NG = beckmann_ndf(ndfparams); - if (any(A > numeric_limits::min)) + if (any>(A > (vector2_type)numeric_limits::min)) { smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, 0); smith::Beckmann beckmann_smith; @@ -400,7 +400,7 @@ struct SBeckmannBxDF scalar_type NG = beckmann_ndf(ndfparams); if (a2 > numeric_limits::min) { - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2.x, params.NdotV2, params.NdotL2, 0); + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.NdotV2, params.NdotL2, 0); smith::Beckmann beckmann_smith; NG *= beckmann_smith.correlated(smithparams); } @@ -416,7 +416,7 @@ struct SBeckmannBxDF #ifdef __HLSL_VERSION return fresnelConductor(ior._m00_m10_m20, iorior._m01_m11_m21, params.VdotH) * microfacet_transform(); #else - return fresnelConductor(vector3_type(ior[0][0],ior[0][1],ior[0][2]), vector3_type(ior[1][0],ior[1][1],ior[1][2]), params.VdotH) * microfacet_transform(); + return fresnelConductor(vector3_type(ior[0][0],ior[1][0],ior[2][0]), vector3_type(ior[0][1],ior[1][1],ior[2][1]), params.VdotH) * microfacet_transform(); #endif } @@ -567,7 +567,7 @@ struct SBeckmannBxDF #ifdef __HLSL_VERSION const vector3_type reflectance = fresnelConductor(ior._m00_m10_m20, iorior._m01_m11_m21, cache.VdotH); #else - const vector3_type reflectance = fresnelConductor(vector3_type(ior[0][0],ior[0][1],ior[0][2]), vector3_type(ior[1][0],ior[1][1],ior[1][2]), cache.VdotH); + const vector3_type reflectance = fresnelConductor(vector3_type(ior[0][0],ior[1][0],ior[2][0]), vector3_type(ior[0][1],ior[1][1],ior[2][1]), cache.VdotH); #endif scalar_type G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); quo = reflectance * G2_over_G1; @@ -598,7 +598,7 @@ struct SBeckmannBxDF #ifdef __HLSL_VERSION const vector3_type reflectance = fresnelConductor(ior._m00_m10_m20, iorior._m01_m11_m21, cache.VdotH); #else - const vector3_type reflectance = fresnelConductor(vector3_type(ior[0][0],ior[0][1],ior[0][2]), vector3_type(ior[1][0],ior[1][1],ior[1][2]), cache.VdotH); + const vector3_type reflectance = fresnelConductor(vector3_type(ior[0][0],ior[1][0],ior[2][0]), vector3_type(ior[0][1],ior[1][1],ior[2][1]), cache.VdotH); #endif scalar_type G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); quo = reflectance * G2_over_G1; @@ -658,7 +658,7 @@ struct SGGXBxDF ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); ndf::GGX ggx_ndf; scalar_type NG = ggx_ndf(ndfparams); - if (any(A > numeric_limits::min)) + if (any>(A > (vector2_type)numeric_limits::min)) { smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2); smith::GGX ggx_smith; From 2539b13ecfb059a0052858835820bbe01f058b2c Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 3 Jan 2025 15:53:59 +0700 Subject: [PATCH 046/188] use simpler getcolumn method --- examples_tests | 2 +- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 21 ++++++------------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/examples_tests b/examples_tests index 76db1201e0..9de6ae862d 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 76db1201e02c1eae6079bd3b481e578c52b4aa07 +Subproject commit 9de6ae862d082d892e911808fd473647d0c65c0f diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index ef6b271845..1d3a7f8cfc 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -413,11 +413,8 @@ struct SBeckmannBxDF { scalar_type scalar_part = __eval_DG_wo_clamps(params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotV); -#ifdef __HLSL_VERSION - return fresnelConductor(ior._m00_m10_m20, iorior._m01_m11_m21, params.VdotH) * microfacet_transform(); -#else - return fresnelConductor(vector3_type(ior[0][0],ior[1][0],ior[2][0]), vector3_type(ior[0][1],ior[1][1],ior[2][1]), params.VdotH) * microfacet_transform(); -#endif + matrix ior_T = nbl::hlsl::transpose >(ior); + return fresnelConductor(ior_T[0], ior_T[1], params.VdotH) * microfacet_transform(); } vector3_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) @@ -564,11 +561,8 @@ struct SBeckmannBxDF if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, 0, _sample.NdotL2, onePlusLambda_V); -#ifdef __HLSL_VERSION - const vector3_type reflectance = fresnelConductor(ior._m00_m10_m20, iorior._m01_m11_m21, cache.VdotH); -#else - const vector3_type reflectance = fresnelConductor(vector3_type(ior[0][0],ior[1][0],ior[2][0]), vector3_type(ior[0][1],ior[1][1],ior[2][1]), cache.VdotH); -#endif + matrix ior_T = nbl::hlsl::transpose >(ior); + const vector3_type reflectance = fresnelConductor(ior_T[0], ior_T[1], cache.VdotH); scalar_type G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); quo = reflectance * G2_over_G1; } @@ -595,11 +589,8 @@ struct SBeckmannBxDF if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, onePlusLambda_V); -#ifdef __HLSL_VERSION - const vector3_type reflectance = fresnelConductor(ior._m00_m10_m20, iorior._m01_m11_m21, cache.VdotH); -#else - const vector3_type reflectance = fresnelConductor(vector3_type(ior[0][0],ior[1][0],ior[2][0]), vector3_type(ior[0][1],ior[1][1],ior[2][1]), cache.VdotH); -#endif + matrix ior_T = nbl::hlsl::transpose >(ior); + const vector3_type reflectance = fresnelConductor(ior_T[0], ior_T[1], cache.VdotH); scalar_type G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); quo = reflectance * G2_over_G1; } From 796c65ba1a749a9cbd33acb0d1c2c64080f457fb Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 6 Jan 2025 11:15:52 +0700 Subject: [PATCH 047/188] more brdf bug fixes and example update --- examples_tests | 2 +- include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 2 +- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 30 +++++++++++-------- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/examples_tests b/examples_tests index 9de6ae862d..6dbc89ac55 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 9de6ae862d082d892e911808fd473647d0c65c0f +Subproject commit 6dbc89ac557a0531ca390183e4b251910cc54347 diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl index f57563250a..029625e3fe 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -149,7 +149,7 @@ struct GGX { scalar_type a2 = params.ax * params.ay; scalar_type denom = params.TdotH2 / params.ax2 + params.BdotH2 / params.ay2 + params.NdotH2; - return numbers::inv_pi / (params.a2 * denom * denom); + return numbers::inv_pi / (a2 * denom * denom); } // burley diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 1d3a7f8cfc..53760cbd80 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -164,7 +164,7 @@ struct SOrenNayarBxDF sample_type generate(anisotropic_type interaction, vector2_type u) { - return generate_wo_clamps(interaction, u); + return generate_wo_clamps(interaction, u); } scalar_type pdf_wo_clamps(sample_type _sample, isotropic_type interaction) @@ -284,7 +284,8 @@ struct SBlinnPhongBxDF scalar_part = __eval_DG_wo_clamps(params, a2); } ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotV); - return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_transform(); + matrix ior_T = nbl::hlsl::transpose >(ior); + return fresnelConductor(ior_T[0], ior_T[1], params.VdotH) * microfacet_transform(); } vector3_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) @@ -678,7 +679,8 @@ struct SGGXBxDF { scalar_type scalar_part = __eval_DG_wo_clamps(params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotL); - return fresnelConductor(ior[0], ior[1], params.VdotH) * microfacet_transform(); + matrix ior_T = nbl::hlsl::transpose >(ior); + return fresnelConductor(ior_T[0], ior_T[1], params.VdotH) * microfacet_transform(); } vector3_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) @@ -771,13 +773,13 @@ struct SGGXBxDF smith::GGX ggx_smith; const scalar_type devsh_v = ggx_smith.devsh_part(interaction.NdotV2, a2, one_minus_a2); - scalar_type pdf = pdf(_sample, interaction, cache); + scalar_type _pdf = pdf(_sample, interaction, cache); smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, interaction.NdotV, interaction.NdotV2, _sample.NdotL, _sample.NdotL2); scalar_type G2_over_G1 = ggx_smith.G2_over_G1(smithparams); vector3_type quo = reflectance * G2_over_G1; - return quotient_pdf_type::create(spectral_type(quo), pdf); + return quotient_pdf_type::create(spectral_type(quo), _pdf); } quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) @@ -787,18 +789,19 @@ struct SGGXBxDF smith::GGX ggx_smith; const scalar_type devsh_v = ggx_smith.devsh_part(interaction.NdotV2, a2, one_minus_a2); - scalar_type pdf = pdf(_sample, interaction, cache); + scalar_type _pdf = pdf(_sample, interaction, cache); vector3_type quo = (vector3_type)0.0; if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { - const vector3_type reflectance = fresnelConductor(ior[0], ior[1], cache.VdotH); + matrix ior_T = nbl::hlsl::transpose >(ior); + const vector3_type reflectance = fresnelConductor(ior_T[0], ior_T[1], cache.VdotH); smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, interaction.NdotV, interaction.NdotV2, _sample.NdotL, _sample.NdotL2); scalar_type G2_over_G1 = ggx_smith.G2_over_G1(smithparams); quo = reflectance * G2_over_G1; } - return quotient_pdf_type::create(spectral_type(quo), pdf); + return quotient_pdf_type::create(spectral_type(quo), _pdf); } quotient_pdf_type quotient_and_pdf_wo_clamps(sample_type _sample, anisotropic_type interaction, anisocache_type cache, vector3_type reflectance) @@ -809,13 +812,13 @@ struct SGGXBxDF smith::GGX ggx_smith; const scalar_type devsh_v = ggx_smith.devsh_part(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); - scalar_type pdf = pdf(_sample, interaction, cache); + scalar_type _pdf = pdf(_sample, interaction, cache); smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2); scalar_type G2_over_G1 = ggx_smith.G2_over_G1(smithparams); vector3_type quo = reflectance * G2_over_G1; - return quotient_pdf_type::create(spectral_type(quo), pdf); + return quotient_pdf_type::create(spectral_type(quo), _pdf); } quotient_pdf_type quotient_and_pdf(sample_type _sample, anisotropic_type interaction, anisocache_type cache) @@ -826,18 +829,19 @@ struct SGGXBxDF smith::GGX ggx_smith; const scalar_type devsh_v = ggx_smith.devsh_part(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); - scalar_type pdf = pdf(_sample, interaction, cache); + scalar_type _pdf = pdf(_sample, interaction, cache); vector3_type quo = (vector3_type)0.0; if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { - const vector3_type reflectance = fresnel_conductor(ior[0], ior[1], cache.VdotH); + matrix ior_T = nbl::hlsl::transpose >(ior); + const vector3_type reflectance = fresnelConductor(ior_T[0], ior_T[1], cache.VdotH); smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2); scalar_type G2_over_G1 = ggx_smith.G2_over_G1(smithparams); quo = reflectance * G2_over_G1; } - return quotient_pdf_type::create(spectral_type(quo), pdf); + return quotient_pdf_type::create(spectral_type(quo), _pdf); } vector2_type A; From 9ad1be407c5413fa932f8e49f75981619b88e941 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 6 Jan 2025 16:56:01 +0700 Subject: [PATCH 048/188] bug fixes, microfacet_transform needs rechecking --- include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 26 ++++++++++------- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 29 ++++++++++++------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl index 029625e3fe..dfaf4f06a1 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -244,16 +244,22 @@ struct microfacet_to_light_measure_transform scalar_type operator()() { - scalar_type denominator; if (is_ggx_v) - denominator = absNdotL; + { + scalar_type denominator = absNdotL; + const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); + // VdotHLdotH is negative under transmission, so thats denominator is negative + denominator *= -4.0 * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); + return NDFcos * denominator; + } else - denominator = absNdotV; - - const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); - // VdotHLdotH is negative under transmission, so thats denominator is negative - denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; - return NDFcos * VdotHLdotH / denominator; + { + scalar_type denominator = absNdotV; + const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); + // VdotHLdotH is negative under transmission, so thats denominator is negative + denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; + return NDFcos * VdotHLdotH / denominator; + } } scalar_type NDFcos; @@ -297,9 +303,9 @@ struct microfacet_to_light_measure_transform { const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); // VdotHLdotH is negative under transmission, so thats denominator is negative - denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; + denominator *= -4.0 * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); } - return NDFcos * (transmitted ? VdotHLdotH : 0.25) / denominator; + return NDFcos * denominator; } else { diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index 553da3f147..7c398ec8c8 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -216,7 +216,10 @@ struct SSmoothDielectricBxDF return retval; } - // where eval? + vector3_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) + { + return (vector3_type)0; + } // usually `luminosityContributionHint` would be the Rec.709 luma coefficients (the Y row of the RGB to CIE XYZ matrix) // its basically a set of weights that determine @@ -248,7 +251,11 @@ struct SSmoothDielectricBxDF return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, interaction.NdotV, nbl::hlsl::abs(interaction.NdotV), u, eta2, luminosityContributionHint); } - // where pdf? + // eval and pdf return 0 because smooth dielectric/conductor BxDFs are dirac delta distributions, model perfectly specular objects that scatter light to only one outgoing direction + scalar_type pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) + { + return 0; + } quotient_pdf_type quotient_and_pdf_wo_clamps(sample_type _sample, isotropic_type interaction) { @@ -466,9 +473,9 @@ struct SBeckmannDielectricBxDF const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); scalar_type onePlusLambda_V; - scalar_type pdf = pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, interaction.NdotV2, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta, dummy); + scalar_type pdf = pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, interaction.NdotV2, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta, onePlusLambda_V); - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, 0, _sample.NdotL2, onePlusLambda_V); + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, interaction.NdotV2, _sample.NdotL2, onePlusLambda_V); smith::Beckmann beckmann_smith; scalar_type quo = beckmann_smith.G2_over_G1(smithparams); @@ -496,7 +503,7 @@ struct SBeckmannDielectricBxDF const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); scalar_type onePlusLambda_V; - scalar_type pdf = pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.VdotH, cache.LdotH, VdotHLdotH, ax2, ay2, orientedEta, dummy); + scalar_type pdf = pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.VdotH, cache.LdotH, VdotHLdotH, ax2, ay2, orientedEta, onePlusLambda_V); smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, onePlusLambda_V); smith::Beckmann beckmann_smith; @@ -560,7 +567,7 @@ struct SGGXDielectricBxDF ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,abs(_sample.NdotL),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); - return fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); + return (vector3_type)fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); } vector3_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) @@ -579,13 +586,13 @@ struct SGGXDielectricBxDF ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,abs(_sample.NdotL),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); - return fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); + return (vector3_type)fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); } sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix3x3_type m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) { - const scalar_type VdotH = nbl::hlsl::dot(localV,H); - const scalar_type reflectance = fresnelDielectric_common(orientedEta2,nbl::hlsl::abs(VdotH)); + const scalar_type localVdotH = nbl::hlsl::dot(localV,H); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2,nbl::hlsl::abs(localVdotH)); scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); @@ -610,7 +617,7 @@ struct SGGXDielectricBxDF const vector3_type upperHemisphereV = backside ? -localV : localV; matrix dummyior; - reflection::SGGXBxDF ggx = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior); + reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, A.y, dummyior); const vector3_type H = ggx.__generate(upperHemisphereV, u.xy); return __generate_wo_clamps(localV, backside, H, interaction.getTangentFrame(), u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, cache); @@ -683,7 +690,7 @@ struct SGGXDielectricBxDF quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) { const scalar_type a2 = A.x*A.x; - params_t params = params_t::template create(_sample, interaction, cache); + params_t params = params_t::template create(_sample, interaction, cache); ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); ndf::GGX ggx_ndf; From 567875c9164582682ec1de1119028e3ad3f8428a Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 8 Jan 2025 16:26:52 +0700 Subject: [PATCH 049/188] bug fixes #2 (I think) --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 12 ++--- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 52 +++++++++++-------- 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 3614704228..01e6a16c4e 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -344,7 +344,7 @@ struct SLightSample retval.TdotL = nbl::hlsl::numeric_limits::signaling_NaN; retval.BdotL = nbl::hlsl::numeric_limits::signaling_NaN; - retval.NdotL = nbl::hlsl::dot(N,L); + retval.NdotL = nbl::hlsl::dot(N,L.direction); retval.NdotL2 = retval.NdotL * retval.NdotL; return retval; @@ -353,8 +353,8 @@ struct SLightSample { this_t retval = create(L,VdotL,N); - retval.TdotL = nbl::hlsl::dot(T,L); - retval.BdotL = nbl::hlsl::dot(B,L); + retval.TdotL = nbl::hlsl::dot(T,L.direction); + retval.BdotL = nbl::hlsl::dot(B,L.direction); return retval; } @@ -923,13 +923,13 @@ struct fresnel const T sinTheta2 = 1.0 - absCosTheta * absCosTheta; // the max() clamping can handle TIR when orientedEta2<1.0 - const U t0 = sqrt(max((U)(orientedEta2) - sinTheta2, (U)(0.0))); + const U t0 = nbl::hlsl::sqrt(nbl::hlsl::max((U)(orientedEta2) - sinTheta2, (U)(0.0))); const U rs = ((U)(absCosTheta) - t0) / ((U)(absCosTheta) + t0); const U t2 = orientedEta2 * absCosTheta; const U rp = (t0 - t2) / (t0 + t2); - return (rs * rs + rp * rp) * 0.5; + return (rs * rs + rp * rp) * 0.5f; } }; } @@ -976,7 +976,7 @@ struct ThinDielectricInfiniteScatter static vector __call(vector singleInterfaceReflectance) { const vector doubleInterfaceReflectance = singleInterfaceReflectance * singleInterfaceReflectance; - return lerp((singleInterfaceReflectance - doubleInterfaceReflectance) / ((vector)(1.0) - doubleInterfaceReflectance) * 2.0, (vector)(1.0), doubleInterfaceReflectance > (vector)(0.9999)); + return lerp>((singleInterfaceReflectance - doubleInterfaceReflectance) / ((vector)(1.0) - doubleInterfaceReflectance) * 2.0f, (vector)(1.0), doubleInterfaceReflectance > (vector)(0.9999)); } static T __call(T singleInterfaceReflectance) diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index 7c398ec8c8..c9277106a2 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -39,7 +39,7 @@ LightSample cos_generate(NBL_CONST_REF_ARG(Aniso) interaction) template && is_floating_point_v) quotient_and_pdf cos_quotient_and_pdf() { - return quotient_and_pdf::create(SpectralBins(1.f),nbl::hlsl::numeric_limits::inf()); + return quotient_and_pdf::create(SpectralBins(1.f), numeric_limits::infinity); } // basic bxdf @@ -116,16 +116,14 @@ struct SLambertianBxDF } }; -// no oren nayar // microfacet bxdfs - -// the dielectric ones don't fit the concept at all :( template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SSmoothDielectricBxDF { using this_t = SSmoothDielectricBxDF; using scalar_type = typename LightSample::scalar_type; + using ray_dir_info_type = typename LightSample::ray_dir_info_type; using vector3_type = vector; using params_t = SBxDFParams; @@ -144,20 +142,24 @@ struct SSmoothDielectricBxDF return retval; } - // where eval? + vector3_type eval(sample_type _sample, isotropic_type interaction) + { + return (vector3_type)0; + } sample_type __generate_wo_clamps(vector3_type V, vector3_type T, vector3_type B, vector3_type N, bool backside, scalar_type NdotV, scalar_type absNdotV, scalar_type NdotV2, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(bool) transmitted) { - const vector3_type reflectance = fresnelDielectric_common(orientedEta2, absNdotV); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, absNdotV); scalar_type rcpChoiceProb; transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); - - const vector3_type L = math::reflectRefract(transmitted, V, N, backside, NdotV, NdotV2, rcpOrientedEta, rcpOrientedEta2); - return sample_type::create(L, nbl::hlsl::dot(V, L), T, B, N); + + ray_dir_info_type L; + L.direction = math::reflectRefract(transmitted, V, N, backside, NdotV, NdotV2, rcpOrientedEta, rcpOrientedEta2); + return sample_type::create(L, nbl::hlsl::dot(V, L.direction), T, B, N); } - sample_type generate_wo_clamps(anisotropic_type interaction, NBL_REF_ARG(vector) u) // TODO: check vector3_type? + sample_type generate_wo_clamps(anisotropic_type interaction, NBL_REF_ARG(vector) u) { scalar_type orientedEta, rcpOrientedEta; const bool backside = math::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.NdotV, eta); @@ -175,7 +177,11 @@ struct SSmoothDielectricBxDF nbl::hlsl::abs(interaction.NdotV), interaction.NdotV*interaction.NdotV, u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, dummy); } - // where pdf? + // eval and pdf return 0 because smooth dielectric/conductor BxDFs are dirac delta distributions, model perfectly specular objects that scatter light to only one outgoing direction + scalar_type pdf(sample_type _sample, isotropic_type interaction) + { + return 0; + } quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction) { @@ -184,7 +190,7 @@ struct SSmoothDielectricBxDF scalar_type dummy, rcpOrientedEta; const bool backside = math::getOrientedEtas(dummy, rcpOrientedEta, interaction.NdotV, eta); - const scalar_type pdf = 1.0 / 0.0; + const scalar_type pdf = numeric_limits::infinity; scalar_type quo = transmitted ? rcpOrientedEta : 1.0; return quotient_pdf_type::create(spectral_type(quo), pdf); } @@ -197,6 +203,7 @@ struct SSmoothDielectricBxDF { using this_t = SSmoothDielectricBxDF; using scalar_type = typename LightSample::scalar_type; + using ray_dir_info_type = typename LightSample::ray_dir_info_type; using vector3_type = vector; using params_t = SBxDFParams; @@ -216,7 +223,7 @@ struct SSmoothDielectricBxDF return retval; } - vector3_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) + vector3_type eval(sample_type _sample, isotropic_type interaction) { return (vector3_type)0; } @@ -237,22 +244,25 @@ struct SSmoothDielectricBxDF const bool transmitted = math::partitionRandVariable(reflectionProb, u.z, rcpChoiceProb); remainderMetadata = (transmitted ? ((vector3_type)(1.0) - reflectance) : reflectance) * rcpChoiceProb; - const vector3_type L = (transmitted ? (vector3_type)(0.0) : N * 2.0 * NdotV) - V; - return sample_type::create(L, nbl::hlsl::dot(V, L), T, B, N); + ray_dir_info_type L; + L.direction = (transmitted ? (vector3_type)(0.0) : N * 2.0f * NdotV) - V; + return sample_type::create(L, nbl::hlsl::dot(V, L.direction), T, B, N); } - sample_type generate_wo_clamps(anisotropic_type interaction, NBL_REF_ARG(vector) u) // TODO: check vector3_type? + sample_type generate_wo_clamps(anisotropic_type interaction, NBL_REF_ARG(vector) u) { - return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, interaction.NdotV, interaction.NdotV, u, eta2, luminosityContributionHint); + vector3_type dummy; + return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, interaction.NdotV, interaction.NdotV, u, eta2, luminosityContributionHint, dummy); } sample_type generate(anisotropic_type interaction, NBL_REF_ARG(vector) u) { - return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, interaction.NdotV, nbl::hlsl::abs(interaction.NdotV), u, eta2, luminosityContributionHint); + vector3_type dummy; + return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, interaction.NdotV, nbl::hlsl::abs(interaction.NdotV), u, eta2, luminosityContributionHint, dummy); } // eval and pdf return 0 because smooth dielectric/conductor BxDFs are dirac delta distributions, model perfectly specular objects that scatter light to only one outgoing direction - scalar_type pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) + scalar_type pdf(sample_type _sample, isotropic_type interaction) { return 0; } @@ -265,7 +275,7 @@ struct SSmoothDielectricBxDF const scalar_type sampleProb = nbl::hlsl::dot(sampleValue,luminosityContributionHint); - const scalar_type pdf = 1.0 / 0.0; + const scalar_type pdf = numeric_limits::infinity; return quotient_pdf_type::create(spectral_type(sampleValue / sampleProb), pdf); } @@ -277,7 +287,7 @@ struct SSmoothDielectricBxDF const scalar_type sampleProb = nbl::hlsl::dot(sampleValue,luminosityContributionHint); - const scalar_type pdf = 1.0 / 0.0; + const scalar_type pdf = numeric_limits::infinity; return quotient_pdf_type::create(spectral_type(sampleValue / sampleProb), pdf); } From ac23035254f984ca3c65f40d77dc1db2c5dcd9d9 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 10 Jan 2025 11:48:04 +0700 Subject: [PATCH 050/188] uniform sampling, update embed cmakelists --- examples_tests | 2 +- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 2 +- .../nbl/builtin/hlsl/sampling/uniform.hlsl | 86 +++++++++++++++++++ src/nbl/builtin/CMakeLists.txt | 10 +++ 4 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 include/nbl/builtin/hlsl/sampling/uniform.hlsl diff --git a/examples_tests b/examples_tests index 17b253c0fa..fac1ed1a08 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 17b253c0fa0650caf283ba0040a27f7e8e88221b +Subproject commit fac1ed1a08858bfdcf362f034a5c0d9a5dd4431b diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 53760cbd80..5170832232 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -312,7 +312,7 @@ struct SBlinnPhongBxDF vector3_type generate(vector2_type u, scalar_type n) { - scalar_type phi = 2.0 * numbers::pi; * u.y; + scalar_type phi = 2.0 * numbers::pi * u.y; scalar_type cosTheta = pow(u.x, 1.0/(n+1.0)); scalar_type sinTheta = sqrt(1.0 - cosTheta * cosTheta); scalar_type cosPhi = cos(phi); diff --git a/include/nbl/builtin/hlsl/sampling/uniform.hlsl b/include/nbl/builtin/hlsl/sampling/uniform.hlsl new file mode 100644 index 0000000000..09dce6989c --- /dev/null +++ b/include/nbl/builtin/hlsl/sampling/uniform.hlsl @@ -0,0 +1,86 @@ +// Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h + +#ifndef _NBL_BUILTIN_HLSL_SAMPLING_COS_WEIGHTED_INCLUDED_ +#define _NBL_BUILTIN_HLSL_SAMPLING_COS_WEIGHTED_INCLUDED_ + +#include "nbl/builtin/hlsl/concepts.hlsl" +#include "nbl/builtin/hlsl/tgmath.hlsl" + +namespace nbl +{ +namespace hlsl +{ + +namespace impl +{ +template +struct UniformHemisphere +{ + using vector_t2 = vector; + using vector_t3 = vector; + + static vector_t3 generate(vector_t2 _sample) + { + T z = _sample.x; + T r = sqrt(max(0.0, 1.0 - z * z)); + T phi = 2.0 * numbers::pi * _sample.y; + return vector_t3(r * cos(phi), r * sin(phi), z); + } + + static T pdf() + { + return 1.0 / (2.0 * numbers::pi); + } +}; + +template +struct UniformSphere +{ + using vector_t2 = vector; + using vector_t3 = vector; + + static vector_t3 generate(vector_t2 _sample) + { + T z = 1 - 2 * _sample.x; + T r = sqrt(max(0.0, 1.0 - z * z)); + T phi = 2.0 * numbers::pi * _sample.y; + return vector_t3(r * cos(phi), r * sin(phi), z); + } + + static T pdf() + { + return 1.0 / (4.0 * numbers::pi); + } +}; +} + +template) +vector uniform_hemisphere_generate(vector _sample) +{ + return impl::UniformHemisphere::generate(_sample); +} + +template) +T uniform_hemisphere_pdf() +{ + return impl::UniformHemisphere::pdf(); +} + +template) +vector uniform_sphere_generate(vector _sample) +{ + return impl::UniformSphere::generate(_sample); +} + +template) +T uniform_sphere_pdf() +{ + return impl::UniformSphere::pdf(); +} + +} +} + +#endif diff --git a/src/nbl/builtin/CMakeLists.txt b/src/nbl/builtin/CMakeLists.txt index 78809c5c1e..ae6892d82f 100644 --- a/src/nbl/builtin/CMakeLists.txt +++ b/src/nbl/builtin/CMakeLists.txt @@ -309,6 +309,10 @@ LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/shapes/circle.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/shapes/ellipse.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/shapes/line.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/shapes/beziers.hlsl") +#sampling +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/sampling/concentric_mapping.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/sampling/cos_weighted.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/sampling/uniform.hlsl") # LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/ndarray_addressing.hlsl") # @@ -318,6 +322,12 @@ LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/fft/common.hlsl") #sort LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/sort/common.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/sort/counting.hlsl") +#bxdf +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/common.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/geom_smith.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/nxdf.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/reflection.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/transmission.hlsl") #subgroup LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/subgroup/ballot.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/subgroup/basic.hlsl") From ccaa0a5d1d433eadce7369e44f71eec861e0d951 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 10 Jan 2025 12:02:34 +0700 Subject: [PATCH 051/188] fix cmake, include bugs --- examples_tests | 2 +- include/nbl/builtin/hlsl/sampling/uniform.hlsl | 5 +++-- src/nbl/builtin/CMakeLists.txt | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/examples_tests b/examples_tests index fac1ed1a08..1ecd0c0489 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit fac1ed1a08858bfdcf362f034a5c0d9a5dd4431b +Subproject commit 1ecd0c0489f93a410e56e97c04c0010fe2318a64 diff --git a/include/nbl/builtin/hlsl/sampling/uniform.hlsl b/include/nbl/builtin/hlsl/sampling/uniform.hlsl index 09dce6989c..f52fcedaa5 100644 --- a/include/nbl/builtin/hlsl/sampling/uniform.hlsl +++ b/include/nbl/builtin/hlsl/sampling/uniform.hlsl @@ -2,10 +2,11 @@ // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h -#ifndef _NBL_BUILTIN_HLSL_SAMPLING_COS_WEIGHTED_INCLUDED_ -#define _NBL_BUILTIN_HLSL_SAMPLING_COS_WEIGHTED_INCLUDED_ +#ifndef _NBL_BUILTIN_HLSL_SAMPLING_UNIFORM_INCLUDED_ +#define _NBL_BUILTIN_HLSL_SAMPLING_UNIFORM_INCLUDED_ #include "nbl/builtin/hlsl/concepts.hlsl" +#include "nbl/builtin/hlsl/numbers.hlsl" #include "nbl/builtin/hlsl/tgmath.hlsl" namespace nbl diff --git a/src/nbl/builtin/CMakeLists.txt b/src/nbl/builtin/CMakeLists.txt index ae6892d82f..9c913f0703 100644 --- a/src/nbl/builtin/CMakeLists.txt +++ b/src/nbl/builtin/CMakeLists.txt @@ -325,7 +325,7 @@ LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/sort/counting.hlsl") #bxdf LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/common.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/geom_smith.hlsl") -LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/nxdf.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/ndf.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/reflection.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/transmission.hlsl") #subgroup From cf6c5c2563863b628d6b230d0058c11cf2d8f3d5 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 13 Jan 2025 16:54:01 +0700 Subject: [PATCH 052/188] changed ior, spectral_type usage in bxdf + concept --- examples_tests | 2 +- include/nbl/builtin/hlsl/bxdf/common.hlsl | 87 +++++----- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 134 ++++++++-------- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 148 +++++++++--------- 4 files changed, 185 insertions(+), 186 deletions(-) diff --git a/examples_tests b/examples_tests index 1ecd0c0489..887c3a0130 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 1ecd0c0489f93a410e56e97c04c0010fe2318a64 +Subproject commit 887c3a0130dcc8b158abd27821e09b86d19aa2a8 diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 01e6a16c4e..04972a5a00 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -792,7 +792,7 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) ((NBL_CONCEPT_REQ_TYPE)(T::isocache_type)) ((NBL_CONCEPT_REQ_TYPE)(T::anisocache_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.eval(_sample,iso,isocache)), ::nbl::hlsl::is_same_v, vector)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.eval(_sample,iso,isocache)), ::nbl::hlsl::is_same_v, T::spectral_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.generate(aniso,aniso.N,anisocache)), ::nbl::hlsl::is_same_v, typename T::sample_type)) //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template pdf(_sample,iso)), ::nbl::hlsl::is_scalar_v)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.quotient_and_pdf(_sample,iso,isocache)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) @@ -898,90 +898,91 @@ namespace impl template struct fresnel { - using vector_t = vector; + using scalar_t = typename scalar_type::type; - static vector_t conductor(vector_t eta, vector_t etak, T cosTheta) + static T conductor(T eta, T etak, scalar_t cosTheta) { - const T cosTheta2 = cosTheta * cosTheta; + const scalar_t cosTheta2 = cosTheta * cosTheta; //const float sinTheta2 = 1.0 - cosTheta2; - const vector_t etaLen2 = eta * eta + etak * etak; - const vector_t etaCosTwice = eta * cosTheta * 2.0f; + const T etaLen2 = eta * eta + etak * etak; + const T etaCosTwice = eta * cosTheta * 2.0f; - const vector_t rs_common = etaLen2 + (vector_t)(cosTheta2); - const vector_t rs2 = (rs_common - etaCosTwice) / (rs_common + etaCosTwice); + const T rs_common = etaLen2 + (T)(cosTheta2); + const T rs2 = (rs_common - etaCosTwice) / (rs_common + etaCosTwice); - const vector_t rp_common = etaLen2 * cosTheta2 + (vector_t)(1.0); - const vector_t rp2 = (rp_common - etaCosTwice) / (rp_common + etaCosTwice); + const T rp_common = etaLen2 * cosTheta2 + (T)(1.0); + const T rp2 = (rp_common - etaCosTwice) / (rp_common + etaCosTwice); return (rs2 + rp2) * 0.5f; } - template - static U dielectric(U orientedEta2, T absCosTheta) + static T dielectric(T orientedEta2, scalar_t absCosTheta) { - const T sinTheta2 = 1.0 - absCosTheta * absCosTheta; + const scalar_t sinTheta2 = 1.0 - absCosTheta * absCosTheta; // the max() clamping can handle TIR when orientedEta2<1.0 - const U t0 = nbl::hlsl::sqrt(nbl::hlsl::max((U)(orientedEta2) - sinTheta2, (U)(0.0))); - const U rs = ((U)(absCosTheta) - t0) / ((U)(absCosTheta) + t0); + const T t0 = nbl::hlsl::sqrt(nbl::hlsl::max((T)(orientedEta2) - sinTheta2, (T)(0.0))); + const T rs = ((T)(absCosTheta) - t0) / ((T)(absCosTheta) + t0); - const U t2 = orientedEta2 * absCosTheta; - const U rp = (t0 - t2) / (t0 + t2); + const T t2 = orientedEta2 * absCosTheta; + const T rp = (t0 - t2) / (t0 + t2); return (rs * rs + rp * rp) * 0.5f; } }; } -template) -vector fresnelSchlick(vector F0, T VdotH) +template || is_vector_v) +T fresnelSchlick(T F0, typename scalar_type::type VdotH) { T x = 1.0 - VdotH; return F0 + (1.0 - F0) * x*x*x*x*x; } -template) -vector fresnelConductor(vector eta, vector etak, T cosTheta) +template || is_vector_v) +T fresnelConductor(T eta, T etak, typename scalar_type::type cosTheta) { return impl::fresnel::conductor(eta, etak, cosTheta); } -template && (is_scalar_v || is_vector_v)) -T fresnelDielectric_common(T eta, U cosTheta) +template || is_vector_v) +T fresnelDielectric_common(T eta, typename scalar_type::type cosTheta) { - return impl::fresnel::template dielectric(eta, cosTheta); + return impl::fresnel::dielectric(eta, cosTheta); } -template && (is_scalar_v || is_vector_v)) -T fresnelDielectricFrontFaceOnly(T eta, U cosTheta) +template || is_vector_v) +T fresnelDielectricFrontFaceOnly(T eta, typename scalar_type::type cosTheta) { - return impl::fresnel::template dielectric(eta * eta, cosTheta); + return impl::fresnel::dielectric(eta * eta, cosTheta); } -template && (is_scalar_v || is_vector_v)) -T fresnelDielectric(T eta, U cosTheta) +template || is_vector_v) +T fresnelDielectric(T eta, typename scalar_type::type cosTheta) { T orientedEta, rcpOrientedEta; math::getOrientedEtas(orientedEta, rcpOrientedEta, cosTheta, eta); - return impl::fresnel::template dielectric(orientedEta * orientedEta, abs(cosTheta)); + return impl::fresnel::dielectric(orientedEta * orientedEta, abs::type>(cosTheta)); } namespace impl { // gets the sum of all R, T R T, T R^3 T, T R^5 T, ... paths -template) +template struct ThinDielectricInfiniteScatter { - static vector __call(vector singleInterfaceReflectance) - { - const vector doubleInterfaceReflectance = singleInterfaceReflectance * singleInterfaceReflectance; - return lerp>((singleInterfaceReflectance - doubleInterfaceReflectance) / ((vector)(1.0) - doubleInterfaceReflectance) * 2.0f, (vector)(1.0), doubleInterfaceReflectance > (vector)(0.9999)); - } + using scalar_t = typename scalar_type::type; static T __call(T singleInterfaceReflectance) { const T doubleInterfaceReflectance = singleInterfaceReflectance * singleInterfaceReflectance; + return lerp((singleInterfaceReflectance - doubleInterfaceReflectance) / ((T)(1.0) - doubleInterfaceReflectance) * 2.0f, (T)(1.0), doubleInterfaceReflectance > (T)(0.9999)); + } + + static scalar_t __call(scalar_t singleInterfaceReflectance) // TODO: check redundancy when lerp on line 980 works + { + const scalar_t doubleInterfaceReflectance = singleInterfaceReflectance * singleInterfaceReflectance; return doubleInterfaceReflectance > 0.9999 ? 1.0 : ((singleInterfaceReflectance - doubleInterfaceReflectance) / (1.0 - doubleInterfaceReflectance) * 2.0); } }; @@ -990,17 +991,17 @@ struct ThinDielectricInfiniteScatter template || is_vector_v) T thindielectricInfiniteScatter(T singleInterfaceReflectance) { - return impl::ThinDielectricInfiniteScatter >::__call(singleInterfaceReflectance); + return impl::ThinDielectricInfiniteScatter::__call(singleInterfaceReflectance); } -template) -vector diffuseFresnelCorrectionFactor(vector n, vector n2) +template || is_vector_v) +T diffuseFresnelCorrectionFactor(T n, T n2) { // assert(n*n==n2); - vector TIR = n < (vector)1.0; - vector invdenum = lerp((vector)1.0, (vector)1.0 / (n2 * n2 * ((vector)554.33 - 380.7 * n)), TIR); - vector num = n * lerp((vector)(0.1921156102251088), n * 298.25 - 261.38 * n2 + 138.43, TIR); - num += lerp((vector)(0.8078843897748912), (vector)(-1.67), TIR); + // vector TIR = n < (T)1.0; // maybe make extent work in C++? + T invdenum = lerp((T)1.0, (T)1.0 / (n2 * n2 * ((T)554.33 - 380.7 * n)), n < (T)1.0); + T num = n * lerp((T)(0.1921156102251088), n * 298.25 - 261.38 * n2 + 138.43, n < (T)1.0); + num += lerp((T)(0.8078843897748912), (T)(-1.67), n < (T)1.0); return num * invdenum; } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 5170832232..ad4266e71e 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -39,16 +39,16 @@ quotient_and_pdf cos_quotient_and_pdf() } -template && surface_interactions::Isotropic && surface_interactions::Anisotropic) +template && surface_interactions::Isotropic && surface_interactions::Anisotropic) struct SLambertianBxDF { - using this_t = SLambertianBxDF; + using this_t = SLambertianBxDF; using scalar_type = typename LightSample::scalar_type; using ray_dir_info_type = typename LightSample::ray_dir_info_type; using isotropic_type = Iso; using anisotropic_type = Aniso; using sample_type = LightSample; - using spectral_type = vector; // TODO: most likely change this + using spectral_type = Spectrum; using quotient_pdf_type = quotient_and_pdf; static this_t create() @@ -101,22 +101,22 @@ struct SLambertianBxDF { scalar_type pdf; scalar_type q = projected_hemisphere_quotient_and_pdf(pdf, _sample.NdotL); - return quotient_pdf_type::create(spectral_type(q,q,q), pdf); + return quotient_pdf_type::create((spectral_type)(q), pdf); } quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction) { scalar_type pdf; scalar_type q = projected_hemisphere_quotient_and_pdf(pdf, max(_sample.NdotL, 0.0)); - return quotient_pdf_type::create(spectral_type(q,q,q), pdf); + return quotient_pdf_type::create((spectral_type)(q), pdf); } }; -template && surface_interactions::Isotropic && surface_interactions::Anisotropic) +template && surface_interactions::Isotropic && surface_interactions::Anisotropic) struct SOrenNayarBxDF { - using this_t = SOrenNayarBxDF; + using this_t = SOrenNayarBxDF; using scalar_type = typename LightSample::scalar_type; using vector2_type = vector; using ray_dir_info_type = typename LightSample::ray_dir_info_type; @@ -124,7 +124,7 @@ struct SOrenNayarBxDF using isotropic_type = Iso; using anisotropic_type = Aniso; using sample_type = LightSample; - using spectral_type = vector; // TODO: most likely change this + using spectral_type = Spectrum; using quotient_pdf_type = quotient_and_pdf; static this_t create(scalar_type A) @@ -183,7 +183,7 @@ struct SOrenNayarBxDF scalar_type pdf; projected_hemisphere_quotient_and_pdf(pdf, _sample.NdotL); scalar_type q = __rec_pi_factored_out_wo_clamps(_sample.VdotL, _sample.NdotL, interaction.NdotV); - return quotient_pdf_type::create(spectral_type(q), pdf); + return quotient_pdf_type::create((spectral_type)(q), pdf); } quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction) @@ -191,7 +191,7 @@ struct SOrenNayarBxDF scalar_type pdf; projected_hemisphere_quotient_and_pdf(pdf, max(_sample.NdotL, 0.0)); scalar_type q = __rec_pi_factored_out_wo_clamps(_sample.VdotL, max(_sample.NdotL,0.0), max(interaction.NdotV,0.0)); - return quotient_pdf_type::create(spectral_type(q), pdf); + return quotient_pdf_type::create((spectral_type)(q), pdf); } scalar_type A; @@ -199,10 +199,10 @@ struct SOrenNayarBxDF // microfacet bxdfs -template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) +template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SBlinnPhongBxDF { - using this_t = SBlinnPhongBxDF; + using this_t = SBlinnPhongBxDF; using scalar_type = typename LightSample::scalar_type; using ray_dir_info_type = typename LightSample::ray_dir_info_type; using vector2_type = vector; @@ -213,16 +213,17 @@ struct SBlinnPhongBxDF using isotropic_type = typename IsoCache::isotropic_type; using anisotropic_type = typename AnisoCache::anisotropic_type; using sample_type = LightSample; - using spectral_type = vector; // TODO: most likely change this + using spectral_type = Spectrum; using quotient_pdf_type = quotient_and_pdf; using isocache_type = IsoCache; using anisocache_type = AnisoCache; - static this_t create(vector2_type n, matrix2x3_type ior) + static this_t create(vector2_type n, spectral_type ior0, spectral_type ior1) { this_t retval; retval.n = n; - retval.ior = ior; + retval.ior0 = ior0; + retval.ior1 = ior1; return retval; } @@ -284,8 +285,7 @@ struct SBlinnPhongBxDF scalar_part = __eval_DG_wo_clamps(params, a2); } ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotV); - matrix ior_T = nbl::hlsl::transpose >(ior); - return fresnelConductor(ior_T[0], ior_T[1], params.VdotH) * microfacet_transform(); + return fresnelConductor(ior0, ior1, params.VdotH) * microfacet_transform(); } vector3_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) @@ -335,13 +335,13 @@ struct SBlinnPhongBxDF // where pdf? vector2_type n; - matrix2x3_type ior; + spectral_type ior0, ior1; }; -template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) +template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SBeckmannBxDF { - using this_t = SBeckmannBxDF; + using this_t = SBeckmannBxDF; using scalar_type = typename LightSample::scalar_type; using ray_dir_info_type = typename LightSample::ray_dir_info_type; using vector2_type = vector; @@ -352,26 +352,28 @@ struct SBeckmannBxDF using isotropic_type = typename IsoCache::isotropic_type; using anisotropic_type = typename AnisoCache::anisotropic_type; using sample_type = LightSample; - using spectral_type = vector; // TODO: most likely change this + using spectral_type = Spectrum; using quotient_pdf_type = quotient_and_pdf; using isocache_type = IsoCache; using anisocache_type = AnisoCache; // iso - static this_t create(scalar_type A,matrix2x3_type ior) + static this_t create(scalar_type A, spectral_type ior0, spectral_type ior1) { this_t retval; retval.A = vector2_type(A,A); - retval.ior = ior; + retval.ior0 = ior0; + retval.ior1 = ior1; return retval; } // aniso - static this_t create(scalar_type ax,scalar_type ay,matrix2x3_type ior) + static this_t create(scalar_type ax, scalar_type ay, spectral_type ior0, spectral_type ior1) { this_t retval; retval.A = vector2_type(ax,ay); - retval.ior = ior; + retval.ior0 = ior0; + retval.ior1 = ior1; return retval; } @@ -410,15 +412,14 @@ struct SBeckmannBxDF } template - vector3_type __eval_wo_clamps(params_t params) + spectral_type __eval_wo_clamps(params_t params) { scalar_type scalar_part = __eval_DG_wo_clamps(params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotV); - matrix ior_T = nbl::hlsl::transpose >(ior); - return fresnelConductor(ior_T[0], ior_T[1], params.VdotH) * microfacet_transform(); + return fresnelConductor(ior0, ior1, params.VdotH) * microfacet_transform(); } - vector3_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) + spectral_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) { if (interaction.NdotV > numeric_limits::min) { @@ -426,10 +427,10 @@ struct SBeckmannBxDF return __eval_wo_clamps(params); } else - return (vector3_type)0.0; + return (spectral_type)0.0; } - vector3_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) + spectral_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) { if (interaction.NdotV > numeric_limits::min) { @@ -437,7 +438,7 @@ struct SBeckmannBxDF return __eval_wo_clamps(params); } else - return (vector3_type)0.0; + return (spectral_type)0.0; } vector3_type __generate(vector3_type localV, vector2_type u) @@ -558,17 +559,16 @@ struct SBeckmannBxDF scalar_type onePlusLambda_V; scalar_type pdf = smith::VNDF_pdf_wo_clamps >(ndf, lambda, interaction.NdotV, onePlusLambda_V); - vector3_type quo = (vector3_type)0.0; + spectral_type quo = (spectral_type)0.0; if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, 0, _sample.NdotL2, onePlusLambda_V); - matrix ior_T = nbl::hlsl::transpose >(ior); - const vector3_type reflectance = fresnelConductor(ior_T[0], ior_T[1], cache.VdotH); + const spectral_type reflectance = fresnelConductor(ior0, ior1, cache.VdotH); scalar_type G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); quo = reflectance * G2_over_G1; } - return quotient_pdf_type::create(spectral_type(quo), pdf); + return quotient_pdf_type::create(quo, pdf); } quotient_pdf_type quotient_and_pdf(sample_type _sample, anisotropic_type interaction, anisocache_type cache) @@ -586,27 +586,26 @@ struct SBeckmannBxDF const scalar_type c2 = beckmann_smith.C2(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); scalar_type lambda = beckmann_smith.Lambda(c2); scalar_type pdf = smith::VNDF_pdf_wo_clamps >(ndf, lambda, interaction.NdotV, onePlusLambda_V); - vector3_type quo = (vector3_type)0.0; + spectral_type quo = (spectral_type)0.0; if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, onePlusLambda_V); - matrix ior_T = nbl::hlsl::transpose >(ior); - const vector3_type reflectance = fresnelConductor(ior_T[0], ior_T[1], cache.VdotH); + const spectral_type reflectance = fresnelConductor(ior0, ior1, cache.VdotH); scalar_type G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); quo = reflectance * G2_over_G1; } - return quotient_pdf_type::create(spectral_type(quo), pdf); + return quotient_pdf_type::create(quo, pdf); } vector2_type A; - matrix2x3_type ior; + spectral_type ior0, ior1; }; -template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) +template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SGGXBxDF { - using this_t = SGGXBxDF; + using this_t = SGGXBxDF; using scalar_type = typename LightSample::scalar_type; using ray_dir_info_type = typename LightSample::ray_dir_info_type; using vector2_type = vector; @@ -617,26 +616,28 @@ struct SGGXBxDF using isotropic_type = typename IsoCache::isotropic_type; using anisotropic_type = typename AnisoCache::anisotropic_type; using sample_type = LightSample; - using spectral_type = vector; // TODO: most likely change this + using spectral_type = Spectrum; using quotient_pdf_type = quotient_and_pdf; using isocache_type = IsoCache; using anisocache_type = AnisoCache; // iso - static this_t create(scalar_type A,matrix2x3_type ior) + static this_t create(scalar_type A, spectral_type ior0, spectral_type ior1) { this_t retval; retval.A = vector2_type(A,A); - retval.ior = ior; + retval.ior0 = ior0; + retval.ior1 = ior1; return retval; } // aniso - static this_t create(scalar_type ax,scalar_type ay,matrix2x3_type ior) + static this_t create(scalar_type ax, scalar_type ay, spectral_type ior0, spectral_type ior1) { this_t retval; retval.A = vector2_type(ax,ay); - retval.ior = ior; + retval.ior0 = ior0; + retval.ior1 = ior1; return retval; } @@ -675,15 +676,14 @@ struct SGGXBxDF } template - vector3_type __eval_wo_clamps(params_t params) + spectral_type __eval_wo_clamps(params_t params) { scalar_type scalar_part = __eval_DG_wo_clamps(params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotL); - matrix ior_T = nbl::hlsl::transpose >(ior); - return fresnelConductor(ior_T[0], ior_T[1], params.VdotH) * microfacet_transform(); + return fresnelConductor(ior0, ior1, params.VdotH) * microfacet_transform(); } - vector3_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) + spectral_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) { if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { @@ -694,7 +694,7 @@ struct SGGXBxDF return (vector3_type)0.0; } - vector3_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) + spectral_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) { if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { @@ -766,7 +766,7 @@ struct SGGXBxDF return smith::VNDF_pdf_wo_clamps(ndf, G1_over_2NdotV); } - quotient_pdf_type quotient_and_pdf_wo_clamps(sample_type _sample, isotropic_type interaction, isocache_type cache, vector3_type reflectance) + quotient_pdf_type quotient_and_pdf_wo_clamps(sample_type _sample, isotropic_type interaction, isocache_type cache, spectral_type reflectance) { const scalar_type a2 = A.x*A.x; const scalar_type one_minus_a2 = 1.0 - a2; @@ -777,9 +777,9 @@ struct SGGXBxDF smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, interaction.NdotV, interaction.NdotV2, _sample.NdotL, _sample.NdotL2); scalar_type G2_over_G1 = ggx_smith.G2_over_G1(smithparams); - vector3_type quo = reflectance * G2_over_G1; + spectral_type quo = reflectance * G2_over_G1; - return quotient_pdf_type::create(spectral_type(quo), _pdf); + return quotient_pdf_type::create(quo, _pdf); } quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) @@ -791,20 +791,19 @@ struct SGGXBxDF const scalar_type devsh_v = ggx_smith.devsh_part(interaction.NdotV2, a2, one_minus_a2); scalar_type _pdf = pdf(_sample, interaction, cache); - vector3_type quo = (vector3_type)0.0; + spectral_type quo = (spectral_type)0.0; if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { - matrix ior_T = nbl::hlsl::transpose >(ior); - const vector3_type reflectance = fresnelConductor(ior_T[0], ior_T[1], cache.VdotH); + const spectral_type reflectance = fresnelConductor(ior0, ior1, cache.VdotH); smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, interaction.NdotV, interaction.NdotV2, _sample.NdotL, _sample.NdotL2); scalar_type G2_over_G1 = ggx_smith.G2_over_G1(smithparams); quo = reflectance * G2_over_G1; } - return quotient_pdf_type::create(spectral_type(quo), _pdf); + return quotient_pdf_type::create(quo, _pdf); } - quotient_pdf_type quotient_and_pdf_wo_clamps(sample_type _sample, anisotropic_type interaction, anisocache_type cache, vector3_type reflectance) + quotient_pdf_type quotient_and_pdf_wo_clamps(sample_type _sample, anisotropic_type interaction, anisocache_type cache, spectral_type reflectance) { params_t params = params_t::template create(_sample, interaction, cache); const scalar_type ax2 = A.x*A.x; @@ -816,9 +815,9 @@ struct SGGXBxDF smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2); scalar_type G2_over_G1 = ggx_smith.G2_over_G1(smithparams); - vector3_type quo = reflectance * G2_over_G1; + spectral_type quo = reflectance * G2_over_G1; - return quotient_pdf_type::create(spectral_type(quo), _pdf); + return quotient_pdf_type::create(quo, _pdf); } quotient_pdf_type quotient_and_pdf(sample_type _sample, anisotropic_type interaction, anisocache_type cache) @@ -831,21 +830,20 @@ struct SGGXBxDF const scalar_type devsh_v = ggx_smith.devsh_part(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); scalar_type _pdf = pdf(_sample, interaction, cache); - vector3_type quo = (vector3_type)0.0; + spectral_type quo = (spectral_type)0.0; if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { - matrix ior_T = nbl::hlsl::transpose >(ior); - const vector3_type reflectance = fresnelConductor(ior_T[0], ior_T[1], cache.VdotH); + const spectral_type reflectance = fresnelConductor(ior0, ior1, cache.VdotH); smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2); scalar_type G2_over_G1 = ggx_smith.G2_over_G1(smithparams); quo = reflectance * G2_over_G1; } - return quotient_pdf_type::create(spectral_type(quo), _pdf); + return quotient_pdf_type::create(quo, _pdf); } vector2_type A; - matrix2x3_type ior; + spectral_type ior0, ior1; }; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index c9277106a2..a592151eff 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -43,16 +43,16 @@ quotient_and_pdf cos_quotient_and_pdf() } // basic bxdf -template && surface_interactions::Isotropic && surface_interactions::Anisotropic) +template && surface_interactions::Isotropic && surface_interactions::Anisotropic) struct SLambertianBxDF { - using this_t = SLambertianBxDF; + using this_t = SLambertianBxDF; using scalar_type = typename LightSample::scalar_type; using ray_dir_info_type = typename LightSample::ray_dir_info_type; using isotropic_type = Iso; using anisotropic_type = Aniso; using sample_type = LightSample; - using spectral_type = vector; // TODO: most likely change this + using spectral_type = Spectrum; using quotient_pdf_type = quotient_and_pdf; static this_t create() @@ -105,23 +105,23 @@ struct SLambertianBxDF { scalar_type pdf; scalar_type q = projected_sphere_quotient_and_pdf(pdf, _sample.NdotL); - return quotient_pdf_type::create(spectral_type(q), pdf); + return quotient_pdf_type::create((spectral_type)(q), pdf); } quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction) { scalar_type pdf; scalar_type q = projected_sphere_quotient_and_pdf(pdf, nbl::hlsl::abs(_sample.NdotL)); - return quotient_pdf_type::create(spectral_type(q), pdf); + return quotient_pdf_type::create((spectral_type)(q), pdf); } }; // microfacet bxdfs -template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) +template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SSmoothDielectricBxDF { - using this_t = SSmoothDielectricBxDF; + using this_t = SSmoothDielectricBxDF; using scalar_type = typename LightSample::scalar_type; using ray_dir_info_type = typename LightSample::ray_dir_info_type; using vector3_type = vector; @@ -130,7 +130,7 @@ struct SSmoothDielectricBxDF using isotropic_type = typename IsoCache::isotropic_type; using anisotropic_type = typename AnisoCache::anisotropic_type; using sample_type = LightSample; - using spectral_type = vector; // TODO: most likely change this + using spectral_type = Spectrum; using quotient_pdf_type = quotient_and_pdf; using isocache_type = IsoCache; using anisocache_type = AnisoCache; @@ -142,14 +142,14 @@ struct SSmoothDielectricBxDF return retval; } - vector3_type eval(sample_type _sample, isotropic_type interaction) + spectral_type eval(sample_type _sample, isotropic_type interaction) { - return (vector3_type)0; + return (spectral_type)0; } sample_type __generate_wo_clamps(vector3_type V, vector3_type T, vector3_type B, vector3_type N, bool backside, scalar_type NdotV, scalar_type absNdotV, scalar_type NdotV2, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(bool) transmitted) { - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, absNdotV); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, absNdotV); scalar_type rcpChoiceProb; transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); @@ -192,16 +192,16 @@ struct SSmoothDielectricBxDF const scalar_type pdf = numeric_limits::infinity; scalar_type quo = transmitted ? rcpOrientedEta : 1.0; - return quotient_pdf_type::create(spectral_type(quo), pdf); + return quotient_pdf_type::create((spectral_type)(quo), pdf); } scalar_type eta; }; -template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) -struct SSmoothDielectricBxDF +template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) +struct SSmoothDielectricBxDF { - using this_t = SSmoothDielectricBxDF; + using this_t = SSmoothDielectricBxDF; using scalar_type = typename LightSample::scalar_type; using ray_dir_info_type = typename LightSample::ray_dir_info_type; using vector3_type = vector; @@ -210,12 +210,12 @@ struct SSmoothDielectricBxDF using isotropic_type = typename IsoCache::isotropic_type; using anisotropic_type = typename AnisoCache::anisotropic_type; using sample_type = LightSample; - using spectral_type = vector; // TODO: most likely change this + using spectral_type = Spectrum; using quotient_pdf_type = quotient_and_pdf; using isocache_type = IsoCache; using anisocache_type = AnisoCache; - static this_t create(vector3_type eta2, vector3_type luminosityContributionHint) + static this_t create(spectral_type eta2, spectral_type luminosityContributionHint) { this_t retval; retval.eta2 = eta2; @@ -223,26 +223,26 @@ struct SSmoothDielectricBxDF return retval; } - vector3_type eval(sample_type _sample, isotropic_type interaction) + spectral_type eval(sample_type _sample, isotropic_type interaction) { - return (vector3_type)0; + return (spectral_type)0; } // usually `luminosityContributionHint` would be the Rec.709 luma coefficients (the Y row of the RGB to CIE XYZ matrix) // its basically a set of weights that determine // assert(1.0==luminosityContributionHint.r+luminosityContributionHint.g+luminosityContributionHint.b); - // `remainderMetadata` is a variable which the generator function returns byproducts of sample generation that would otherwise have to be redundantly calculated `remainder_and_pdf` - sample_type __generate_wo_clamps(vector3_type V, vector3_type T, vector3_type B, vector3_type N, scalar_type NdotV, scalar_type absNdotV, NBL_REF_ARG(vector3_type) u, vector3_type eta2, vector3_type luminosityContributionHint, NBL_REF_ARG(vector3_type) remainderMetadata) + // `remainderMetadata` is a variable which the generator function returns byproducts of sample generation that would otherwise have to be redundantly calculated `quotient_and_pdf` + sample_type __generate_wo_clamps(vector3_type V, vector3_type T, vector3_type B, vector3_type N, scalar_type NdotV, scalar_type absNdotV, NBL_REF_ARG(vector3_type) u, spectral_type eta2, spectral_type luminosityContributionHint, NBL_REF_ARG(spectral_type) remainderMetadata) { // we will only ever intersect from the outside - const vector3_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2,absNdotV)); + const spectral_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2,absNdotV)); // we are only allowed one choice for the entire ray, so make the probability a weighted sum - const scalar_type reflectionProb = nbl::hlsl::dot(reflectance, luminosityContributionHint); + const scalar_type reflectionProb = nbl::hlsl::dot(reflectance, luminosityContributionHint); scalar_type rcpChoiceProb; const bool transmitted = math::partitionRandVariable(reflectionProb, u.z, rcpChoiceProb); - remainderMetadata = (transmitted ? ((vector3_type)(1.0) - reflectance) : reflectance) * rcpChoiceProb; + remainderMetadata = (transmitted ? ((spectral_type)(1.0) - reflectance) : reflectance) * rcpChoiceProb; ray_dir_info_type L; L.direction = (transmitted ? (vector3_type)(0.0) : N * 2.0f * NdotV) - V; @@ -270,35 +270,35 @@ struct SSmoothDielectricBxDF quotient_pdf_type quotient_and_pdf_wo_clamps(sample_type _sample, isotropic_type interaction) { const bool transmitted = isTransmissionPath(interaction.NdotV, _sample.NdotL); - const vector3_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, interaction.NdotV)); - const vector3_type sampleValue = transmitted ? ((vector3_type)(1.0) - reflectance) : reflectance; + const spectral_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, interaction.NdotV)); + const spectral_type sampleValue = transmitted ? ((spectral_type)(1.0) - reflectance) : reflectance; - const scalar_type sampleProb = nbl::hlsl::dot(sampleValue,luminosityContributionHint); + const scalar_type sampleProb = nbl::hlsl::dot(sampleValue,luminosityContributionHint); const scalar_type pdf = numeric_limits::infinity; - return quotient_pdf_type::create(spectral_type(sampleValue / sampleProb), pdf); + return quotient_pdf_type::create((spectral_type)(sampleValue / sampleProb), pdf); } quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction) { const bool transmitted = isTransmissionPath(interaction.NdotV, _sample.NdotL); - const vector3_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, nbl::hlsl::abs(interaction.NdotV))); - const vector3_type sampleValue = transmitted ? ((vector3_type)(1.0) - reflectance) : reflectance; + const spectral_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, nbl::hlsl::abs(interaction.NdotV))); + const spectral_type sampleValue = transmitted ? ((spectral_type)(1.0) - reflectance) : reflectance; - const scalar_type sampleProb = nbl::hlsl::dot(sampleValue,luminosityContributionHint); + const scalar_type sampleProb = nbl::hlsl::dot(sampleValue,luminosityContributionHint); const scalar_type pdf = numeric_limits::infinity; - return quotient_pdf_type::create(spectral_type(sampleValue / sampleProb), pdf); + return quotient_pdf_type::create((spectral_type)(sampleValue / sampleProb), pdf); } - vector3_type eta2; - vector3_type luminosityContributionHint; + spectral_type eta2; + spectral_type luminosityContributionHint; }; -template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) +template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SBeckmannDielectricBxDF { - using this_t = SBeckmannDielectricBxDF; + using this_t = SBeckmannDielectricBxDF; using scalar_type = typename LightSample::scalar_type; using ray_dir_info_type = typename LightSample::ray_dir_info_type; using vector2_type = vector; @@ -309,7 +309,7 @@ struct SBeckmannDielectricBxDF using isotropic_type = typename IsoCache::isotropic_type; using anisotropic_type = typename AnisoCache::anisotropic_type; using sample_type = LightSample; - using spectral_type = vector; // TODO: most likely change this + using spectral_type = Spectrum; using quotient_pdf_type = quotient_and_pdf; using isocache_type = IsoCache; using anisocache_type = AnisoCache; @@ -330,7 +330,7 @@ struct SBeckmannDielectricBxDF return retval; } - vector3_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) + spectral_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) { scalar_type orientedEta, dummy; const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); @@ -339,17 +339,17 @@ struct SBeckmannDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - matrix dummyior; + spectral_type dummyior; params_t params = params_t::template create(_sample, interaction, cache); - reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, dummyior); + reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, dummyior, dummyior); const scalar_type scalar_part = beckmann.template __eval_DG_wo_clamps(params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,nbl::hlsl::abs(interaction.NdotV),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); - return (vector3_type)fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); + return (spectral_type)fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); } - vector3_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) + spectral_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) { scalar_type orientedEta, dummy; const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); @@ -358,20 +358,20 @@ struct SBeckmannDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - matrix dummyior; + spectral_type dummyior; params_t params = params_t::template create(_sample, interaction, cache); - reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior); + reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior, dummyior); const scalar_type scalar_part = beckmann.template __eval_DG_wo_clamps(params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,nbl::hlsl::abs(interaction.NdotV),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); - return (vector3_type)fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); + return (spectral_type)fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); } sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix3x3_type m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) { const scalar_type localVdotH = nbl::hlsl::dot(localV,H); - const scalar_type reflectance = fresnelDielectric_common(orientedEta2,nbl::hlsl::abs(localVdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2,nbl::hlsl::abs(localVdotH)); scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); @@ -395,8 +395,8 @@ struct SBeckmannDielectricBxDF const vector3_type upperHemisphereV = backside ? -localV : localV; - matrix dummyior; - reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior); + spectral_type dummyior; + reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior, dummyior); const vector3_type H = beckmann.__generate(upperHemisphereV, u.xy); return __generate_wo_clamps(localV, backside, H, interaction.getTangentFrame(), u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, cache); @@ -436,7 +436,7 @@ struct SBeckmannDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); return pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, interaction.NdotV2, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta, dummy); @@ -459,7 +459,7 @@ struct SBeckmannDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); return pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.VdotH, cache.LdotH, VdotHLdotH, ax2, ay2, orientedEta, dummy); @@ -479,7 +479,7 @@ struct SBeckmannDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); scalar_type onePlusLambda_V; @@ -489,7 +489,7 @@ struct SBeckmannDielectricBxDF smith::Beckmann beckmann_smith; scalar_type quo = beckmann_smith.G2_over_G1(smithparams); - return quotient_pdf_type::create(spectral_type(quo), pdf); + return quotient_pdf_type::create((spectral_type)(quo), pdf); } quotient_pdf_type quotient_and_pdf(sample_type _sample, anisotropic_type interaction, anisocache_type cache) @@ -509,7 +509,7 @@ struct SBeckmannDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); scalar_type onePlusLambda_V; @@ -519,17 +519,17 @@ struct SBeckmannDielectricBxDF smith::Beckmann beckmann_smith; scalar_type quo = beckmann_smith.G2_over_G1(smithparams); - return quotient_pdf_type::create(spectral_type(quo), pdf); + return quotient_pdf_type::create((spectral_type)(quo), pdf); } vector2_type A; scalar_type eta; }; -template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) +template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SGGXDielectricBxDF { - using this_t = SGGXDielectricBxDF; + using this_t = SGGXDielectricBxDF; using scalar_type = typename LightSample::scalar_type; using ray_dir_info_type = typename LightSample::ray_dir_info_type; using vector2_type = vector; @@ -540,7 +540,7 @@ struct SGGXDielectricBxDF using isotropic_type = typename IsoCache::isotropic_type; using anisotropic_type = typename AnisoCache::anisotropic_type; using sample_type = LightSample; - using spectral_type = vector; // TODO: most likely change this + using spectral_type = Spectrum; using quotient_pdf_type = quotient_and_pdf; using isocache_type = IsoCache; using anisocache_type = AnisoCache; @@ -561,7 +561,7 @@ struct SGGXDielectricBxDF return retval; } - vector3_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) + spectral_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) { scalar_type orientedEta, dummy; const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); @@ -570,17 +570,17 @@ struct SGGXDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - matrix dummyior; + spectral_type dummyior; params_t params = params_t::template create(_sample, interaction, cache); - reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, dummyior); + reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, dummyior, dummyior); const scalar_type NG_already_in_reflective_dL_measure = ggx.template __eval_DG_wo_clamps(params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,abs(_sample.NdotL),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); - return (vector3_type)fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); + return (spectral_type)fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); } - vector3_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) + spectral_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) { scalar_type orientedEta, dummy; const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); @@ -589,20 +589,20 @@ struct SGGXDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - matrix dummyior; + spectral_type dummyior; params_t params = params_t::template create(_sample, interaction, cache); - reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, A.y, dummyior); + reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, A.y, dummyior, dummyior); const scalar_type NG_already_in_reflective_dL_measure = ggx.template __eval_DG_wo_clamps(params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,abs(_sample.NdotL),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); - return (vector3_type)fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); + return (spectral_type)fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); } sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix3x3_type m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) { const scalar_type localVdotH = nbl::hlsl::dot(localV,H); - const scalar_type reflectance = fresnelDielectric_common(orientedEta2,nbl::hlsl::abs(localVdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2,nbl::hlsl::abs(localVdotH)); scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); @@ -626,8 +626,8 @@ struct SGGXDielectricBxDF const vector3_type upperHemisphereV = backside ? -localV : localV; - matrix dummyior; - reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, A.y, dummyior); + spectral_type dummyior; + reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, A.y, dummyior, dummyior); const vector3_type H = ggx.__generate(upperHemisphereV, u.xy); return __generate_wo_clamps(localV, backside, H, interaction.getTangentFrame(), u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, cache); @@ -665,7 +665,7 @@ struct SGGXDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); return pdf_wo_clamps(transmitted, reflectance, ndf, devsh_v, absNdotV, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta); @@ -691,7 +691,7 @@ struct SGGXDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); return pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.VdotH, cache.LdotH, VdotHLdotH, ax2, ay2, orientedEta, dummy); @@ -716,7 +716,7 @@ struct SGGXDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); scalar_type pdf = pdf_wo_clamps(transmitted, reflectance, ndf, devsh_v, absNdotV, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta); @@ -724,7 +724,7 @@ struct SGGXDielectricBxDF smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.NdotV, params.NdotV2, params.NdotL, params.NdotL2); scalar_type quo = ggx_smith.G2_over_G1(smithparams); - return quotient_pdf_type::create(spectral_type(quo), pdf); + return quotient_pdf_type::create((spectral_type)(quo), pdf); } quotient_pdf_type quotient_and_pdf(sample_type _sample, anisotropic_type interaction, anisocache_type cache) @@ -747,7 +747,7 @@ struct SGGXDielectricBxDF const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); scalar_type pdf = pdf_wo_clamps(transmitted, reflectance, ndf, devsh_v, absNdotV, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta); @@ -755,7 +755,7 @@ struct SGGXDielectricBxDF smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, absNdotV, params.TdotV2, params.BdotV2, params.NdotV2, abs(params.NdotL), params.TdotL2, params.BdotL2, params.NdotL2); scalar_type quo = ggx_smith.G2_over_G1(smithparams); - return quotient_pdf_type::create(spectral_type(quo), pdf); + return quotient_pdf_type::create((spectral_type)(quo), pdf); } vector2_type A; From d79346b163bac1c5c30ec3e92e99af7bdb9d8035 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 14 Jan 2025 10:56:00 +0700 Subject: [PATCH 053/188] pcg hash --- examples_tests | 2 +- include/nbl/builtin/hlsl/random/pcg.hlsl | 62 ++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 include/nbl/builtin/hlsl/random/pcg.hlsl diff --git a/examples_tests b/examples_tests index 887c3a0130..9ab4e8e412 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 887c3a0130dcc8b158abd27821e09b86d19aa2a8 +Subproject commit 9ab4e8e4126dbde0266cba4f32578be5d4d8a966 diff --git a/include/nbl/builtin/hlsl/random/pcg.hlsl b/include/nbl/builtin/hlsl/random/pcg.hlsl new file mode 100644 index 0000000000..307ab438b7 --- /dev/null +++ b/include/nbl/builtin/hlsl/random/pcg.hlsl @@ -0,0 +1,62 @@ +// Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h + +#ifndef _NBL_BUILTIN_GLSL_RANDOM_PCG_HLSL_INCLUDED_ +#define _NBL_BUILTIN_GLSL_RANDOM_PCG_HLSL_INCLUDED_ + +namespace nbl +{ +namespace hlsl +{ + +namespace impl +{ + +uint32_t pcg_hash(uint32_t v) +{ + uint32_t state = v * 747796405u + 2891336453u; + uint32_t word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u; + return (word >> 22u) ^ word; +} + +template +struct PCGHash; + +template<> +struct PCGHash +{ + static uint32_t __call(uint32_t v) + { + return pcg_hash(v); + } +}; + +template +struct PCGHash> +{ + static vector __call(vector v) + { + vector retval; + for (int i = 0; i < N; i++) + retval[i] = pcg_hash(v[i]); + return retval; + } +}; +} + +template +T pcg32(T v) +{ + return impl::PCGHash::__call(v); +} + +uint32_t2 pcg32x2(uint32_t v) +{ + return impl::PCGHash::__call(uint32_t2(v, v+1)); +} + +} +} + +#endif From 2217e81f3392e9b7a6da8802072c24b18bc32866 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 14 Jan 2025 11:08:58 +0700 Subject: [PATCH 054/188] pcg hash in cmakelist --- src/nbl/builtin/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/nbl/builtin/CMakeLists.txt b/src/nbl/builtin/CMakeLists.txt index 4a851d5469..9d57d6af9f 100644 --- a/src/nbl/builtin/CMakeLists.txt +++ b/src/nbl/builtin/CMakeLists.txt @@ -105,6 +105,7 @@ LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "glsl/property_pool/copy.comp") # random numbers LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "glsl/random/xoroshiro.glsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/random/xoroshiro.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/random/pcg.hlsl") # sampling LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "glsl/sampling/bilinear.glsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "glsl/sampling/box_muller_transform.glsl") From e413e786f20d3df8b68379db90915c9ca3a6c3e8 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 15 Jan 2025 14:53:49 +0700 Subject: [PATCH 055/188] fix aniso microfacet cache create bug --- examples_tests | 2 +- include/nbl/builtin/hlsl/bxdf/common.hlsl | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples_tests b/examples_tests index 9ab4e8e412..a66dc44096 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 9ab4e8e4126dbde0266cba4f32578be5d4d8a966 +Subproject commit a66dc440963f10bb52f4f061f2313b87e70fb701 diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 04972a5a00..cb1555749c 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -627,9 +627,9 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache this_t retval; scalar_type LplusV_rcpLen; - retval = createForReflection(tangentSpaceV.z, tangentSpaceL.z, VdotL, LplusV_rcpLen); - retval.TdotH = (tangentSpaceV.x + tangentSpaceL.x)*LplusV_rcpLen; - retval.BdotH = (tangentSpaceV.y + tangentSpaceL.y)*LplusV_rcpLen; + retval = (this_t)SIsotropicMicrofacetCache::createForReflection(tangentSpaceV.z, tangentSpaceL.z, VdotL, LplusV_rcpLen); + retval.TdotH = (tangentSpaceV.x + tangentSpaceL.x) * LplusV_rcpLen; + retval.BdotH = (tangentSpaceV.y + tangentSpaceL.y) * LplusV_rcpLen; return retval; } From 8052ada4e41d300f94f82e487b628797b9775f0c Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 16 Jan 2025 11:45:53 +0700 Subject: [PATCH 056/188] bug fixes for ggx dielectric, clamp --- examples_tests | 2 +- include/nbl/builtin/hlsl/bxdf/common.hlsl | 33 ++++++++++++++----- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 8 ++--- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 10 +++--- 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/examples_tests b/examples_tests index a66dc44096..983efc3408 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit a66dc440963f10bb52f4f061f2313b87e70fb701 +Subproject commit 983efc34083c26db069b041fe81b62f823b705c8 diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index cb1555749c..97e5983cc4 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -808,13 +808,20 @@ NBL_CONCEPT_END( #undef bxdf #include +enum BxDFClampMode : uint16_t +{ + BCM_NONE = 0, + BCM_MAX, + BCM_ABS +}; + template) struct SBxDFParams { using this_t = SBxDFParams; template && surface_interactions::Isotropic) // maybe put template in struct vs function? - static this_t create(LightSample _sample, Iso interaction) + static this_t create(LightSample _sample, Iso interaction, BxDFClampMode clamp = BCM_NONE) { this_t retval; retval.NdotV = interaction.NdotV; @@ -825,7 +832,7 @@ struct SBxDFParams } template && surface_interactions::Anisotropic) - static SBxDFParams create(LightSample _sample, Aniso interaction) + static SBxDFParams create(LightSample _sample, Aniso interaction, BxDFClampMode clamp = BCM_NONE) { this_t retval; retval.NdotV = interaction.NdotV; @@ -840,27 +847,35 @@ struct SBxDFParams return retval; } - template && surface_interactions::Isotropic && IsotropicMicrofacetCache) // maybe put template in struct vs function? - static this_t create(LightSample _sample, Iso interaction, Cache cache) + template && surface_interactions::Isotropic && IsotropicMicrofacetCache) + static this_t create(LightSample _sample, Iso interaction, Cache cache, BxDFClampMode clamp = BCM_NONE) { this_t retval; retval.NdotH = cache.NdotH; - retval.NdotV = interaction.NdotV; + retval.NdotV = clamp == BCM_ABS ? abs(interaction.NdotV) : + clamp == BCM_MAX ? max(interaction.NdotV, 0.0) : + interaction.NdotV; retval.NdotV2 = interaction.NdotV2; - retval.NdotL = _sample.NdotL; + retval.NdotL = clamp == BCM_ABS ? abs(_sample.NdotL) : + clamp == BCM_MAX ? max(_sample.NdotL, 0.0) : + _sample.NdotL; retval.NdotL2 = _sample.NdotL2; retval.VdotH = cache.VdotH; return retval; } template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - static SBxDFParams create(LightSample _sample, Aniso interaction, Cache cache) + static SBxDFParams create(LightSample _sample, Aniso interaction, Cache cache, BxDFClampMode clamp = BCM_NONE) { this_t retval; retval.NdotH = cache.NdotH; - retval.NdotV = interaction.NdotV; + retval.NdotV = clamp == BCM_ABS ? abs(interaction.NdotV) : + clamp == BCM_MAX ? max(interaction.NdotV, 0.0) : + interaction.NdotV; retval.NdotV2 = interaction.NdotV2; - retval.NdotL = _sample.NdotL; + retval.NdotL = clamp == BCM_ABS ? abs(_sample.NdotL) : + clamp == BCM_MAX ? max(_sample.NdotL, 0.0) : + _sample.NdotL; retval.NdotL2 = _sample.NdotL2; retval.VdotH = cache.VdotH; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index ad4266e71e..7282d2c943 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -641,7 +641,7 @@ struct SGGXBxDF return retval; } - template // this or specialize? + template scalar_type __eval_DG_wo_clamps(params_t params) { if (aniso) @@ -667,7 +667,7 @@ struct SGGXBxDF scalar_type NG = ggx_ndf(ndfparams); if (a2 > numeric_limits::min) { - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, max(params.NdotV,0.0), params.NdotV2, max(params.NdotL,0.0), params.NdotL2); + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.NdotV, params.NdotV2, params.NdotL, params.NdotL2); smith::GGX ggx_smith; NG *= ggx_smith.correlated_wo_numerator(smithparams); } @@ -687,7 +687,7 @@ struct SGGXBxDF { if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { - params_t params = params_t::template create(_sample, interaction, cache); + params_t params = params_t::template create(_sample, interaction, cache, BCM_MAX); return __eval_wo_clamps(params); } else @@ -698,7 +698,7 @@ struct SGGXBxDF { if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) { - params_t params = params_t::template create(_sample, interaction, cache); + params_t params = params_t::template create(_sample, interaction, cache, BCM_MAX); return __eval_wo_clamps(params); } else diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index a592151eff..08c3702555 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -575,8 +575,8 @@ struct SGGXDielectricBxDF reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, dummyior, dummyior); const scalar_type NG_already_in_reflective_dL_measure = ggx.template __eval_DG_wo_clamps(params); - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,abs(_sample.NdotL),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,nbl::hlsl::abs(_sample.NdotL),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); return (spectral_type)fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); } @@ -590,12 +590,12 @@ struct SGGXDielectricBxDF const bool transmitted = VdotHLdotH < 0.0; spectral_type dummyior; - params_t params = params_t::template create(_sample, interaction, cache); + params_t params = params_t::template create(_sample, interaction, cache, BCM_ABS); reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, A.y, dummyior, dummyior); const scalar_type NG_already_in_reflective_dL_measure = ggx.template __eval_DG_wo_clamps(params); - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,abs(_sample.NdotL),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,nbl::hlsl::abs(_sample.NdotL),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); return (spectral_type)fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); } From d1761071316af9a463a00873a610ee37c73bfdc1 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 16 Jan 2025 14:48:54 +0700 Subject: [PATCH 057/188] calculation fixes --- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 4 ++-- include/nbl/builtin/hlsl/bxdf/transmission.hlsl | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 7282d2c943..722e209898 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -691,7 +691,7 @@ struct SGGXBxDF return __eval_wo_clamps(params); } else - return (vector3_type)0.0; + return (spectral_type)0.0; } spectral_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) @@ -702,7 +702,7 @@ struct SGGXBxDF return __eval_wo_clamps(params); } else - return (vector3_type)0.0; + return (spectral_type)0.0; } vector3_type __generate(vector3_type localV, vector2_type u) diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index 08c3702555..c811014646 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -571,7 +571,7 @@ struct SGGXDielectricBxDF const bool transmitted = VdotHLdotH < 0.0; spectral_type dummyior; - params_t params = params_t::template create(_sample, interaction, cache); + params_t params = params_t::template create(_sample, interaction, cache, BCM_ABS); reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, dummyior, dummyior); const scalar_type NG_already_in_reflective_dL_measure = ggx.template __eval_DG_wo_clamps(params); @@ -642,14 +642,14 @@ struct SGGXDielectricBxDF scalar_type pdf_wo_clamps(bool transmitted, scalar_type reflectance, scalar_type ndf, scalar_type devsh_v, scalar_type absNdotV, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) { smith::GGX ggx_smith; - const scalar_type lambda = ggx_smith.G1_wo_numerator(absNdotV, A.x*A.x); + const scalar_type lambda = ggx_smith.G1_wo_numerator(absNdotV, devsh_v); return smith::VNDF_pdf_wo_clamps(ndf,lambda,absNdotV,transmitted,VdotH,LdotH,VdotHLdotH,orientedEta,reflectance); } scalar_type pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) { const scalar_type a2 = A.x*A.x; - params_t params = params_t::template create(_sample, interaction, cache); + params_t params = params_t::template create(_sample, interaction, cache, BCM_ABS); ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); ndf::GGX ggx_ndf; @@ -675,7 +675,7 @@ struct SGGXDielectricBxDF { const scalar_type ax2 = A.x*A.x; const scalar_type ay2 = A.y*A.y; - params_t params = params_t::template create(_sample, interaction, cache); + params_t params = params_t::template create(_sample, interaction, cache, BCM_ABS); ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); ndf::GGX ggx_ndf; @@ -700,7 +700,7 @@ struct SGGXDielectricBxDF quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) { const scalar_type a2 = A.x*A.x; - params_t params = params_t::template create(_sample, interaction, cache); + params_t params = params_t::template create(_sample, interaction, cache, BCM_ABS); ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); ndf::GGX ggx_ndf; @@ -731,7 +731,7 @@ struct SGGXDielectricBxDF { const scalar_type ax2 = A.x*A.x; const scalar_type ay2 = A.y*A.y; - params_t params = params_t::template create(_sample, interaction, cache); + params_t params = params_t::template create(_sample, interaction, cache, BCM_ABS); ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); ndf::GGX ggx_ndf; From 1a1327f57d4b428be4578ef1ac39516e27160e74 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 17 Jan 2025 14:47:10 +0700 Subject: [PATCH 058/188] use param structs for eval/quotient_and_pdf funcs --- examples_tests | 2 +- include/nbl/builtin/hlsl/bxdf/common.hlsl | 65 ++- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 369 +++++---------- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 443 ++++++------------ 4 files changed, 312 insertions(+), 567 deletions(-) diff --git a/examples_tests b/examples_tests index 983efc3408..e6e434a9e0 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 983efc34083c26db069b041fe81b62f823b705c8 +Subproject commit e6e434a9e0ebfe92bf3187f4bcd81acd0f01de27 diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 97e5983cc4..a83057779d 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -735,13 +735,15 @@ typedef quotient_and_pdf, float32_t> quotient_and_pdf_rgb; #define NBL_CONCEPT_PARAM_3 (_sample, typename T::sample_type) #define NBL_CONCEPT_PARAM_4 (iso, typename T::isotropic_type) #define NBL_CONCEPT_PARAM_5 (aniso, typename T::anisotropic_type) -NBL_CONCEPT_BEGIN(6) +#define NBL_CONCEPT_PARAM_6 (param, typename T::params_t) +NBL_CONCEPT_BEGIN(7) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define spec NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define pdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 #define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 #define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 #define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 +#define param NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_type)) @@ -749,12 +751,14 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) ((NBL_CONCEPT_REQ_TYPE)(T::spectral_type)) ((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.eval(_sample,iso)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::params_t)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.eval(param)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.generate(aniso,aniso.N)), ::nbl::hlsl::is_same_v, typename T::sample_type)) //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template pdf(_sample,iso)), ::nbl::hlsl::is_scalar_v)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.quotient_and_pdf(_sample,iso)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.quotient_and_pdf(param)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) ) && Sample && spectral_of && surface_interactions::Isotropic && surface_interactions::Anisotropic; +#undef param #undef aniso #undef iso #undef _sample @@ -774,7 +778,8 @@ NBL_CONCEPT_END( #define NBL_CONCEPT_PARAM_5 (aniso, typename T::anisotropic_type) #define NBL_CONCEPT_PARAM_6 (isocache, typename T::isocache_type) #define NBL_CONCEPT_PARAM_7 (anisocache, typename T::anisocache_type) -NBL_CONCEPT_BEGIN(8) +#define NBL_CONCEPT_PARAM_8 (param, typename T::params_t) +NBL_CONCEPT_BEGIN(9) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define spec NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define pdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 @@ -783,6 +788,7 @@ NBL_CONCEPT_BEGIN(8) #define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 #define isocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 #define anisocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_7 +#define param NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_8 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_type)) @@ -792,12 +798,13 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) ((NBL_CONCEPT_REQ_TYPE)(T::isocache_type)) ((NBL_CONCEPT_REQ_TYPE)(T::anisocache_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.eval(_sample,iso,isocache)), ::nbl::hlsl::is_same_v, T::spectral_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.eval(param)), ::nbl::hlsl::is_same_v, T::spectral_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.generate(aniso,aniso.N,anisocache)), ::nbl::hlsl::is_same_v, typename T::sample_type)) //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template pdf(_sample,iso)), ::nbl::hlsl::is_scalar_v)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.quotient_and_pdf(_sample,iso,isocache)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.quotient_and_pdf(param)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) ) && Sample && spectral_of && IsotropicMicrofacetCache && AnisotropicMicrofacetCache; +#undef param #undef anisocache #undef isocache #undef aniso @@ -824,10 +831,16 @@ struct SBxDFParams static this_t create(LightSample _sample, Iso interaction, BxDFClampMode clamp = BCM_NONE) { this_t retval; - retval.NdotV = interaction.NdotV; + retval.NdotV = clamp == BCM_ABS ? abs(interaction.NdotV) : + clamp == BCM_MAX ? max(interaction.NdotV, 0.0) : + interaction.NdotV; retval.NdotV2 = interaction.NdotV2; - retval.NdotL = _sample.NdotL; + retval.NdotL = clamp == BCM_ABS ? abs(_sample.NdotL) : + clamp == BCM_MAX ? max(_sample.NdotL, 0.0) : + _sample.NdotL; retval.NdotL2 = _sample.NdotL2; + retval.VdotL = _sample.VdotL; + retval.is_aniso = false; return retval; } @@ -835,11 +848,17 @@ struct SBxDFParams static SBxDFParams create(LightSample _sample, Aniso interaction, BxDFClampMode clamp = BCM_NONE) { this_t retval; - retval.NdotV = interaction.NdotV; + retval.NdotV = clamp == BCM_ABS ? abs(interaction.NdotV) : + clamp == BCM_MAX ? max(interaction.NdotV, 0.0) : + interaction.NdotV; retval.NdotV2 = interaction.NdotV2; - retval.NdotL = _sample.NdotL; + retval.NdotL = clamp == BCM_ABS ? abs(_sample.NdotL) : + clamp == BCM_MAX ? max(_sample.NdotL, 0.0) : + _sample.NdotL; retval.NdotL2 = _sample.NdotL2; + retval.VdotL = _sample.VdotL; + retval.is_aniso = true; retval.TdotL2 = _sample.TdotL * _sample.TdotL; retval.BdotL2 = _sample.BdotL * _sample.BdotL; retval.TdotV2 = interaction.TdotV * interaction.TdotV; @@ -852,6 +871,7 @@ struct SBxDFParams { this_t retval; retval.NdotH = cache.NdotH; + retval.NdotH2 = cache.NdotH2; retval.NdotV = clamp == BCM_ABS ? abs(interaction.NdotV) : clamp == BCM_MAX ? max(interaction.NdotV, 0.0) : interaction.NdotV; @@ -861,6 +881,9 @@ struct SBxDFParams _sample.NdotL; retval.NdotL2 = _sample.NdotL2; retval.VdotH = cache.VdotH; + retval.LdotH = cache.LdotH; + retval.VdotL = _sample.VdotL; + retval.is_aniso = false; return retval; } @@ -869,17 +892,22 @@ struct SBxDFParams { this_t retval; retval.NdotH = cache.NdotH; + retval.NdotH2 = cache.NdotH2; retval.NdotV = clamp == BCM_ABS ? abs(interaction.NdotV) : clamp == BCM_MAX ? max(interaction.NdotV, 0.0) : interaction.NdotV; + retval.uNdotV = interaction.NdotV; retval.NdotV2 = interaction.NdotV2; retval.NdotL = clamp == BCM_ABS ? abs(_sample.NdotL) : clamp == BCM_MAX ? max(_sample.NdotL, 0.0) : _sample.NdotL; + retval.uNdotL = _sample.NdotL; retval.NdotL2 = _sample.NdotL2; retval.VdotH = cache.VdotH; + retval.LdotH = cache.LdotH; + retval.VdotL = _sample.VdotL; - retval.NdotH2 = cache.NdotH2; + retval.is_aniso = true; retval.TdotH2 = cache.TdotH * cache.TdotH; retval.BdotH2 = cache.BdotH * cache.BdotH; retval.TdotL2 = _sample.TdotL * _sample.TdotL; @@ -889,22 +917,35 @@ struct SBxDFParams return retval; } + Scalar getMaxNdotV() { return max(NdotV, 0.0); } + Scalar getAbsNdotV() { return abs(NdotV); } + + Scalar getMaxNdotL() { return max(NdotL, 0.0); } + Scalar getAbsNdotL() { return abs(NdotL); } + // iso Scalar NdotH; + Scalar NdotH2; Scalar NdotV; Scalar NdotV2; Scalar NdotL; Scalar NdotL2; Scalar VdotH; + Scalar LdotH; + Scalar VdotL; // aniso - Scalar NdotH2; + bool is_aniso; Scalar TdotH2; Scalar BdotH2; Scalar TdotL2; Scalar BdotL2; Scalar TdotV2; Scalar BdotV2; + + // original, unclamped + Scalar uNdotL; + Scalar uNdotV; }; // fresnel stuff diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 722e209898..e8c6abb97a 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -38,7 +38,7 @@ quotient_and_pdf cos_quotient_and_pdf() return quotient_and_pdf::create(SpectralBins(1.f), numeric_limits::infinity); } - +// basic bxdfs template && surface_interactions::Isotropic && surface_interactions::Anisotropic) struct SLambertianBxDF { @@ -50,6 +50,7 @@ struct SLambertianBxDF using sample_type = LightSample; using spectral_type = Spectrum; using quotient_pdf_type = quotient_and_pdf; + using params_t = SBxDFParams; static this_t create() { @@ -63,16 +64,9 @@ struct SLambertianBxDF return maxNdotL; } - scalar_type __eval_wo_clamps(sample_type _sample, isotropic_type interaction) - { - // probably doesn't need to use the param struct - return __eval_pi_factored_out(_sample.NdotL) * numbers::inv_pi; - } - - scalar_type eval(sample_type _sample, isotropic_type interaction) + scalar_type eval(NBL_CONST_REF_ARG(params_t) params) { - // probably doesn't need to use the param struct - return __eval_pi_factored_out(max(_sample.NdotL, 0.0)) * numbers::inv_pi; + return __eval_pi_factored_out(params.NdotL) * numbers::inv_pi; } sample_type generate_wo_clamps(anisotropic_type interaction, vector u) @@ -87,28 +81,16 @@ struct SLambertianBxDF return generate_wo_clamps(interaction, u); } - scalar_type pdf_wo_clamps(sample_type _sample, isotropic_type interaction) + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) { - return projected_hemisphere_pdf(_sample.NdotL); + return projected_hemisphere_pdf(params.NdotL); } - scalar_type pdf(sample_type _sample, isotropic_type interaction) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) { - return projected_hemisphere_pdf(max(_sample.NdotL, 0.0)); - } - - quotient_pdf_type quotient_and_pdf_wo_clamps(sample_type _sample, isotropic_type interaction) - { - scalar_type pdf; - scalar_type q = projected_hemisphere_quotient_and_pdf(pdf, _sample.NdotL); - return quotient_pdf_type::create((spectral_type)(q), pdf); - } - - quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction) - { - scalar_type pdf; - scalar_type q = projected_hemisphere_quotient_and_pdf(pdf, max(_sample.NdotL, 0.0)); - return quotient_pdf_type::create((spectral_type)(q), pdf); + scalar_type _pdf; + scalar_type q = projected_hemisphere_quotient_and_pdf(_pdf, params.NdotL); + return quotient_pdf_type::create((spectral_type)(q), _pdf); } }; @@ -126,6 +108,7 @@ struct SOrenNayarBxDF using sample_type = LightSample; using spectral_type = Spectrum; using quotient_pdf_type = quotient_and_pdf; + using params_t = SBxDFParams; static this_t create(scalar_type A) { @@ -144,15 +127,9 @@ struct SOrenNayarBxDF return (AB.x + AB.y * cos_phi_sin_theta * C); } - scalar_type __eval_wo_clamps(sample_type _sample, isotropic_type interaction) - { - return _sample.NdotL * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(_sample.VdotL, _sample.NdotL, interaction.NdotV); - } - - scalar_type eval(sample_type _sample, isotropic_type interaction) + scalar_type eval(params_t params) { - scalar_type maxNdotL = max(_sample.NdotL,0.0); - return maxNdotL * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(_sample.VdotL, maxNdotL, max(interaction.NdotV,0.0)); + return params.NdotL * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(params.VdotL, params.NdotL, params.NdotV); } sample_type generate_wo_clamps(anisotropic_type interaction, vector2_type u) @@ -167,31 +144,17 @@ struct SOrenNayarBxDF return generate_wo_clamps(interaction, u); } - scalar_type pdf_wo_clamps(sample_type _sample, isotropic_type interaction) - { - return projected_hemisphere_pdf(_sample.NdotL, 0.0); - } - - scalar_type pdf(sample_type _sample, isotropic_type interaction) + scalar_type pdf(params_t params) { - return projected_hemisphere_pdf(max(_sample.NdotL, 0.0)); + return projected_hemisphere_pdf(params.NdotL); } - // pdf type same as scalar? - quotient_pdf_type quotient_and_pdf_wo_clamps(sample_type _sample, isotropic_type interaction) + quotient_pdf_type quotient_and_pdf(params_t params) { - scalar_type pdf; - projected_hemisphere_quotient_and_pdf(pdf, _sample.NdotL); - scalar_type q = __rec_pi_factored_out_wo_clamps(_sample.VdotL, _sample.NdotL, interaction.NdotV); - return quotient_pdf_type::create((spectral_type)(q), pdf); - } - - quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction) - { - scalar_type pdf; - projected_hemisphere_quotient_and_pdf(pdf, max(_sample.NdotL, 0.0)); - scalar_type q = __rec_pi_factored_out_wo_clamps(_sample.VdotL, max(_sample.NdotL,0.0), max(interaction.NdotV,0.0)); - return quotient_pdf_type::create((spectral_type)(q), pdf); + scalar_type _pdf; + projected_hemisphere_quotient_and_pdf(_pdf, params.NdotL); + scalar_type q = __rec_pi_factored_out_wo_clamps(params.VdotL, params.NdotL, params.NdotV); + return quotient_pdf_type::create((spectral_type)(q), _pdf); } scalar_type A; @@ -199,6 +162,8 @@ struct SOrenNayarBxDF // microfacet bxdfs + +// do not use, not tested, also shit template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SBlinnPhongBxDF { @@ -377,10 +342,9 @@ struct SBeckmannBxDF return retval; } - template // this or specialize? scalar_type __eval_DG_wo_clamps(params_t params) { - if (aniso) + if (params.is_aniso) { const scalar_type ax2 = A.x*A.x; const scalar_type ay2 = A.y*A.y; @@ -411,31 +375,13 @@ struct SBeckmannBxDF } } - template - spectral_type __eval_wo_clamps(params_t params) - { - scalar_type scalar_part = __eval_DG_wo_clamps(params); - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotV); - return fresnelConductor(ior0, ior1, params.VdotH) * microfacet_transform(); - } - - spectral_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) - { - if (interaction.NdotV > numeric_limits::min) - { - params_t params = params_t::template create(_sample, interaction, cache); - return __eval_wo_clamps(params); - } - else - return (spectral_type)0.0; - } - - spectral_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) + spectral_type eval(params_t params) { - if (interaction.NdotV > numeric_limits::min) + if (params.NdotV > numeric_limits::min) { - params_t params = params_t::template create(_sample, interaction, cache); - return __eval_wo_clamps(params); + scalar_type scalar_part = __eval_DG_wo_clamps(params); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotV); + return fresnelConductor(ior0, ior1, params.VdotH) * microfacet_transform(); } else return (spectral_type)0.0; @@ -521,81 +467,64 @@ struct SBeckmannBxDF return sample_type::createTangentSpace(localV, localL, interaction.getTangentFrame()); } - scalar_type pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) + scalar_type pdf(params_t params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { - scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, cache.NdotH, cache.NdotH2); - ndf::Beckmann beckmann_ndf; - scalar_type ndf = beckmann_ndf(ndfparams); + scalar_type ndf, lambda; + if (params.is_aniso) + { + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, A.x*A.x, A.y*A.y, params.TdotH2, params.BdotH2, params.NdotH2); + ndf::Beckmann beckmann_ndf; + ndf = beckmann_ndf(ndfparams); - smith::Beckmann beckmann_smith; - const scalar_type lambda = beckmann_smith.Lambda(interaction.NdotV2, a2); - scalar_type dummy; - return smith::VNDF_pdf_wo_clamps >(ndf, lambda, interaction.NdotV, dummy); - } + smith::Beckmann beckmann_smith; + const scalar_type c2 = beckmann_smith.C2(params.TdotV2, params.BdotV2, params.NdotV2, A.x, A.y); + lambda = beckmann_smith.Lambda(c2); + } + else + { + scalar_type a2 = A.x*A.x; + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); + ndf::Beckmann beckmann_ndf; + ndf = beckmann_ndf(ndfparams); - scalar_type pdf(sample_type _sample, anisotropic_type interaction, anisocache_type cache) - { - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, A.x*A.x, A.y*A.y, cache.TdotH * cache.TdotH, cache.BdotH * cache.BdotH, cache.NdotH2); - ndf::Beckmann beckmann_ndf; - scalar_type ndf = backmann_ndf(ndfparams); + smith::Beckmann beckmann_smith; + lambda = beckmann_smith.Lambda(params.NdotV2, a2); + } - smith::Beckmann beckmann_smith; - const scalar_type c2 = beckmann_smith.C2(interaction.TdotV * interaction.TdotV, interaction.BdotV * interaction.BdotV, interaction.NdotV2, A.x, A.y); - scalar_type lambda = beckmann_smith.Lambda(c2); - scalar_type dummy; - return smith::VNDF_pdf_wo_clamps >(ndf, lambda, interaction.NdotV, dummy); + return smith::VNDF_pdf_wo_clamps >(ndf, lambda, params.NdotV, onePlusLambda_V); } - quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) + scalar_type pdf(params_t params) { - const scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, cache.NdotH, cache.NdotH2); - ndf::Beckmann beckmann_ndf; - const scalar_type ndf = beckmann_ndf(ndfparams); - - smith::Beckmann beckmann_smith; - const scalar_type lambda = beckmann_smith.Lambda(interaction.NdotV2, a2); - - scalar_type onePlusLambda_V; - scalar_type pdf = smith::VNDF_pdf_wo_clamps >(ndf, lambda, interaction.NdotV, onePlusLambda_V); - spectral_type quo = (spectral_type)0.0; - if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) - { - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, 0, _sample.NdotL2, onePlusLambda_V); - const spectral_type reflectance = fresnelConductor(ior0, ior1, cache.VdotH); - scalar_type G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); - quo = reflectance * G2_over_G1; - } - - return quotient_pdf_type::create(quo, pdf); + scalar_type dummy; + return pdf(params, dummy); } - quotient_pdf_type quotient_and_pdf(sample_type _sample, anisotropic_type interaction, anisocache_type cache) + quotient_pdf_type quotient_and_pdf(params_t params) { - params_t params = params_t::template create(_sample, interaction, cache); - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; - - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); - ndf::Beckmann beckmann_ndf; - scalar_type ndf = beckmann_ndf(ndfparams); + scalar_type onePlusLambda_V; + scalar_type _pdf = pdf(params, onePlusLambda_V); smith::Beckmann beckmann_smith; - scalar_type onePlusLambda_V; - const scalar_type c2 = beckmann_smith.C2(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); - scalar_type lambda = beckmann_smith.Lambda(c2); - scalar_type pdf = smith::VNDF_pdf_wo_clamps >(ndf, lambda, interaction.NdotV, onePlusLambda_V); spectral_type quo = (spectral_type)0.0; - if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) + if (params.NdotL > numeric_limits::min && params.NdotV > numeric_limits::min) { - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, onePlusLambda_V); - const spectral_type reflectance = fresnelConductor(ior0, ior1, cache.VdotH); - scalar_type G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); + scalar_type G2_over_G1; + if (params.is_aniso) + { + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(A.x*A.x, A.y*A.y, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, onePlusLambda_V); + G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); + } + else + { + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(A.x*A.x, params.NdotV2, params.NdotL2, onePlusLambda_V); + G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); + } + const spectral_type reflectance = fresnelConductor(ior0, ior1, params.VdotH); quo = reflectance * G2_over_G1; } - return quotient_pdf_type::create(quo, pdf); + return quotient_pdf_type::create(quo, _pdf); } vector2_type A; @@ -641,10 +570,9 @@ struct SGGXBxDF return retval; } - template scalar_type __eval_DG_wo_clamps(params_t params) { - if (aniso) + if (params.is_aniso) { const scalar_type ax2 = A.x*A.x; const scalar_type ay2 = A.y*A.y; @@ -675,31 +603,13 @@ struct SGGXBxDF } } - template - spectral_type __eval_wo_clamps(params_t params) - { - scalar_type scalar_part = __eval_DG_wo_clamps(params); - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotL); - return fresnelConductor(ior0, ior1, params.VdotH) * microfacet_transform(); - } - - spectral_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) - { - if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) - { - params_t params = params_t::template create(_sample, interaction, cache, BCM_MAX); - return __eval_wo_clamps(params); - } - else - return (spectral_type)0.0; - } - - spectral_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) + spectral_type eval(params_t params) { - if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) + if (params.NdotL > numeric_limits::min && params.NdotV > numeric_limits::min) { - params_t params = params_t::template create(_sample, interaction, cache, BCM_MAX); - return __eval_wo_clamps(params); + scalar_type scalar_part = __eval_DG_wo_clamps(params); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotL); + return fresnelConductor(ior0, ior1, params.VdotH) * microfacet_transform(); } else return (spectral_type)0.0; @@ -739,103 +649,58 @@ struct SGGXBxDF return sample_type::createTangentSpace(localV, localL, interaction.getTangentFrame()); } - scalar_type pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) - { - const scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, cache.NdotH, cache.NdotH2); - ndf::GGX ggx_ndf; - scalar_type ndf = ggx_ndf(ndfparams); - - smith::GGX ggx_smith; - const scalar_type devsh_v = ggx_smith.devsh_part(interaction.NdotV2, a2, 1.0-a2); - const scalar_type G1_over_2NdotV = ggx_smith.G1_wo_numerator(interaction.NdotV, devsh_v); - return smith::VNDF_pdf_wo_clamps(ndf, G1_over_2NdotV); - } - - scalar_type pdf(sample_type _sample, anisotropic_type interaction, anisocache_type cache) - { - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, cache.TdotH * cache.TdotH, cache.BdotH * cache.BdotH, cache.NdotH2); - ndf::GGX ggx_ndf; - scalar_type ndf = ggx_ndf(ndfparams); - - smith::GGX ggx_smith; - const scalar_type devsh_v = ggx_smith.devsh_part(interaction.TdotV * interaction.TdotV, interaction.BdotV * interaction.BdotV, interaction.NdotV2, ax2, ay2); - const scalar_type G1_over_2NdotV = ggx_smith.G1_wo_numerator(interaction.NdotV, devsh_v); - return smith::VNDF_pdf_wo_clamps(ndf, G1_over_2NdotV); - } - - quotient_pdf_type quotient_and_pdf_wo_clamps(sample_type _sample, isotropic_type interaction, isocache_type cache, spectral_type reflectance) - { - const scalar_type a2 = A.x*A.x; - const scalar_type one_minus_a2 = 1.0 - a2; - - smith::GGX ggx_smith; - const scalar_type devsh_v = ggx_smith.devsh_part(interaction.NdotV2, a2, one_minus_a2); - scalar_type _pdf = pdf(_sample, interaction, cache); - - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, interaction.NdotV, interaction.NdotV2, _sample.NdotL, _sample.NdotL2); - scalar_type G2_over_G1 = ggx_smith.G2_over_G1(smithparams); - spectral_type quo = reflectance * G2_over_G1; - - return quotient_pdf_type::create(quo, _pdf); - } - - quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) + scalar_type pdf(params_t params) { - const scalar_type a2 = A.x*A.x; - const scalar_type one_minus_a2 = 1.0 - a2; - - smith::GGX ggx_smith; - const scalar_type devsh_v = ggx_smith.devsh_part(interaction.NdotV2, a2, one_minus_a2); - scalar_type _pdf = pdf(_sample, interaction, cache); - - spectral_type quo = (spectral_type)0.0; - if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) + scalar_type ndf, G1_over_2NdotV; + if (params.is_aniso) { - const spectral_type reflectance = fresnelConductor(ior0, ior1, cache.VdotH); - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, interaction.NdotV, interaction.NdotV2, _sample.NdotL, _sample.NdotL2); - scalar_type G2_over_G1 = ggx_smith.G2_over_G1(smithparams); - quo = reflectance * G2_over_G1; - } - - return quotient_pdf_type::create(quo, _pdf); - } - - quotient_pdf_type quotient_and_pdf_wo_clamps(sample_type _sample, anisotropic_type interaction, anisocache_type cache, spectral_type reflectance) - { - params_t params = params_t::template create(_sample, interaction, cache); - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + ndf::GGX ggx_ndf; + ndf = ggx_ndf(ndfparams); - smith::GGX ggx_smith; - const scalar_type devsh_v = ggx_smith.devsh_part(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); - scalar_type _pdf = pdf(_sample, interaction, cache); + smith::GGX ggx_smith; + const scalar_type devsh_v = ggx_smith.devsh_part(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); + G1_over_2NdotV = ggx_smith.G1_wo_numerator(params.NdotV, devsh_v); + } + else + { + const scalar_type a2 = A.x*A.x; + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); + ndf::GGX ggx_ndf; + ndf = ggx_ndf(ndfparams); - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2); - scalar_type G2_over_G1 = ggx_smith.G2_over_G1(smithparams); - spectral_type quo = reflectance * G2_over_G1; - - return quotient_pdf_type::create(quo, _pdf); + smith::GGX ggx_smith; + const scalar_type devsh_v = ggx_smith.devsh_part(params.NdotV2, a2, 1.0-a2); + G1_over_2NdotV = ggx_smith.G1_wo_numerator(params.NdotV, devsh_v); + } + return smith::VNDF_pdf_wo_clamps(ndf, G1_over_2NdotV); } - quotient_pdf_type quotient_and_pdf(sample_type _sample, anisotropic_type interaction, anisocache_type cache) + quotient_pdf_type quotient_and_pdf(params_t params) { - params_t params = params_t::template create(_sample, interaction, cache); - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; - - smith::GGX ggx_smith; - const scalar_type devsh_v = ggx_smith.devsh_part(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); - scalar_type _pdf = pdf(_sample, interaction, cache); + scalar_type _pdf = pdf(params); spectral_type quo = (spectral_type)0.0; - if (_sample.NdotL > numeric_limits::min && interaction.NdotV > numeric_limits::min) + if (params.NdotL > numeric_limits::min && params.NdotV > numeric_limits::min) { - const spectral_type reflectance = fresnelConductor(ior0, ior1, cache.VdotH); - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2); - scalar_type G2_over_G1 = ggx_smith.G2_over_G1(smithparams); + scalar_type G2_over_G1; + smith::GGX ggx_smith; + if (params.is_aniso) + { + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2); + G2_over_G1 = ggx_smith.G2_over_G1(smithparams); + } + else + { + const scalar_type a2 = A.x*A.x; + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.NdotV, params.NdotV2, params.NdotL, params.NdotL2); + scalar_type G2_over_G1 = ggx_smith.G2_over_G1(smithparams); + } + const spectral_type reflectance = fresnelConductor(ior0, ior1, params.VdotH); quo = reflectance * G2_over_G1; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index c811014646..2a14dc6f95 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -54,6 +54,7 @@ struct SLambertianBxDF using sample_type = LightSample; using spectral_type = Spectrum; using quotient_pdf_type = quotient_and_pdf; + using params_t = SBxDFParams; static this_t create() { @@ -67,16 +68,9 @@ struct SLambertianBxDF return absNdotL; } - scalar_type __eval_wo_clamps(sample_type _sample, isotropic_type interaction) - { - // probably doesn't need to use the param struct - return __eval_pi_factored_out(_sample.NdotL) * numbers::inv_pi * 0.5; - } - - scalar_type eval(sample_type _sample, isotropic_type interaction) + scalar_type eval(params_t params) { - // probably doesn't need to use the param struct - return __eval_pi_factored_out(nbl::hlsl::abs(_sample.NdotL)) * numbers::inv_pi * 0.5; + return __eval_pi_factored_out(params.NdotL) * numbers::inv_pi * 0.5; } sample_type generate_wo_clamps(anisotropic_type interaction, vector u) @@ -91,28 +85,16 @@ struct SLambertianBxDF return generate_wo_clamps(interaction, u); } - scalar_type pdf_wo_clamps(sample_type _sample, isotropic_type interaction) - { - return projected_sphere_pdf(_sample.NdotL, 0.0); - } - - scalar_type pdf(sample_type _sample, isotropic_type interaction) - { - return projected_sphere_pdf(nbl::hlsl::abs(_sample.NdotL)); - } - - quotient_pdf_type quotient_and_pdf_wo_clamps(sample_type _sample, isotropic_type interaction) + scalar_type pdf(params_t params) { - scalar_type pdf; - scalar_type q = projected_sphere_quotient_and_pdf(pdf, _sample.NdotL); - return quotient_pdf_type::create((spectral_type)(q), pdf); + return projected_sphere_pdf(params.NdotL); } - quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction) + quotient_pdf_type quotient_and_pdf(params_t params) { - scalar_type pdf; - scalar_type q = projected_sphere_quotient_and_pdf(pdf, nbl::hlsl::abs(_sample.NdotL)); - return quotient_pdf_type::create((spectral_type)(q), pdf); + scalar_type _pdf; + scalar_type q = projected_sphere_quotient_and_pdf(_pdf, params.NdotL); + return quotient_pdf_type::create((spectral_type)(q), _pdf); } }; @@ -142,7 +124,7 @@ struct SSmoothDielectricBxDF return retval; } - spectral_type eval(sample_type _sample, isotropic_type interaction) + spectral_type eval(params_t params) { return (spectral_type)0; } @@ -178,21 +160,21 @@ struct SSmoothDielectricBxDF } // eval and pdf return 0 because smooth dielectric/conductor BxDFs are dirac delta distributions, model perfectly specular objects that scatter light to only one outgoing direction - scalar_type pdf(sample_type _sample, isotropic_type interaction) + scalar_type pdf(params_t params) { return 0; } - quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction) + quotient_pdf_type quotient_and_pdf(params_t params) { - const bool transmitted = isTransmissionPath(interaction.NdotV, _sample.NdotL); + const bool transmitted = isTransmissionPath(params.uNdotV, params.uNdotL); scalar_type dummy, rcpOrientedEta; - const bool backside = math::getOrientedEtas(dummy, rcpOrientedEta, interaction.NdotV, eta); + const bool backside = math::getOrientedEtas(dummy, rcpOrientedEta, params.NdotV, eta); - const scalar_type pdf = numeric_limits::infinity; + const scalar_type _pdf = numeric_limits::infinity; scalar_type quo = transmitted ? rcpOrientedEta : 1.0; - return quotient_pdf_type::create((spectral_type)(quo), pdf); + return quotient_pdf_type::create((spectral_type)(quo), _pdf); } scalar_type eta; @@ -223,7 +205,7 @@ struct SSmoothDielectricBxDF return retval; } - spectral_type eval(sample_type _sample, isotropic_type interaction) + spectral_type eval(params_t params) { return (spectral_type)0; } @@ -261,34 +243,21 @@ struct SSmoothDielectricBxDF return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, interaction.NdotV, nbl::hlsl::abs(interaction.NdotV), u, eta2, luminosityContributionHint, dummy); } - // eval and pdf return 0 because smooth dielectric/conductor BxDFs are dirac delta distributions, model perfectly specular objects that scatter light to only one outgoing direction - scalar_type pdf(sample_type _sample, isotropic_type interaction) + scalar_type pdf(params_t params) { return 0; } - quotient_pdf_type quotient_and_pdf_wo_clamps(sample_type _sample, isotropic_type interaction) - { - const bool transmitted = isTransmissionPath(interaction.NdotV, _sample.NdotL); - const spectral_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, interaction.NdotV)); - const spectral_type sampleValue = transmitted ? ((spectral_type)(1.0) - reflectance) : reflectance; - - const scalar_type sampleProb = nbl::hlsl::dot(sampleValue,luminosityContributionHint); - - const scalar_type pdf = numeric_limits::infinity; - return quotient_pdf_type::create((spectral_type)(sampleValue / sampleProb), pdf); - } - - quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction) + quotient_pdf_type quotient_and_pdf_wo_clamps(params_t params) // isotropic { - const bool transmitted = isTransmissionPath(interaction.NdotV, _sample.NdotL); - const spectral_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, nbl::hlsl::abs(interaction.NdotV))); + const bool transmitted = isTransmissionPath(params.uNdotV, params.uNdotL); + const spectral_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, params.NdotV)); const spectral_type sampleValue = transmitted ? ((spectral_type)(1.0) - reflectance) : reflectance; const scalar_type sampleProb = nbl::hlsl::dot(sampleValue,luminosityContributionHint); - const scalar_type pdf = numeric_limits::infinity; - return quotient_pdf_type::create((spectral_type)(sampleValue / sampleProb), pdf); + const scalar_type _pdf = numeric_limits::infinity; + return quotient_pdf_type::create((spectral_type)(sampleValue / sampleProb), _pdf); } spectral_type eta2; @@ -330,42 +299,26 @@ struct SBeckmannDielectricBxDF return retval; } - spectral_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) - { - scalar_type orientedEta, dummy; - const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); - const scalar_type orientedEta2 = orientedEta * orientedEta; - - const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; - const bool transmitted = VdotHLdotH < 0.0; - - spectral_type dummyior; - params_t params = params_t::template create(_sample, interaction, cache); - reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, dummyior, dummyior); - const scalar_type scalar_part = beckmann.template __eval_DG_wo_clamps(params); - - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,nbl::hlsl::abs(interaction.NdotV),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); - return (spectral_type)fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); - } - - spectral_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) + spectral_type eval(params_t params) { scalar_type orientedEta, dummy; - const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); + const bool backside = math::getOrientedEtas(orientedEta, dummy, params.VdotH, eta); const scalar_type orientedEta2 = orientedEta * orientedEta; - const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; + const scalar_type VdotHLdotH = params.VdotH * params.LdotH; const bool transmitted = VdotHLdotH < 0.0; spectral_type dummyior; - params_t params = params_t::template create(_sample, interaction, cache); - reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior, dummyior); - const scalar_type scalar_part = beckmann.template __eval_DG_wo_clamps(params); + reflection::SBeckmannBxDF beckmann; + if (params.is_aniso) + beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior, dummyior); + else + beckmann = reflection::SBeckmannBxDF::create(A.x, dummyior, dummyior); + const scalar_type scalar_part = beckmann.__eval_DG_wo_clamps(params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,nbl::hlsl::abs(interaction.NdotV),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); - return (spectral_type)fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,params.NdotV,transmitted,params.VdotH,params.LdotH,VdotHLdotH,orientedEta); + return (spectral_type)fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(params.VdotH)) * microfacet_transform(); } sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix3x3_type m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) @@ -408,118 +361,70 @@ struct SBeckmannDielectricBxDF return generate(interaction, u, dummycache); } - scalar_type pdf_wo_clamps(bool transmitted, scalar_type reflectance, scalar_type ndf, scalar_type absNdotV, scalar_type NdotV2, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, NBL_REF_ARG(scalar_type) onePlusLambda_V) - { - smith::Beckmann beckmann_smith; - const scalar_type lambda = beckmann_smith.Lambda(NdotV2, A.x*A.x); - return smith::VNDF_pdf_wo_clamps >(ndf,lambda,absNdotV,transmitted,VdotH,LdotH,VdotHLdotH,orientedEta,reflectance,onePlusLambda_V); - } - - scalar_type pdf_wo_clamps(bool transmitted, scalar_type reflectance, scalar_type ndf, scalar_type absNdotV, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type ax2, scalar_type ay2, scalar_type orientedEta, NBL_REF_ARG(scalar_type) onePlusLambda_V) - { - smith::Beckmann beckmann_smith; - scalar_type c2 = beckmann_smith.C2(TdotV2, BdotV2, NdotV2, ax2, ay2); - scalar_type lambda = beckmann_smith.Lambda(c2); - return smith::VNDF_pdf_wo_clamps >(ndf,lambda,absNdotV,transmitted,VdotH,LdotH,VdotHLdotH,orientedEta,reflectance,onePlusLambda_V); - } - - scalar_type pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) + scalar_type pdf(params_t params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(A.x*A.x, cache.NdotH, cache.NdotH2); - ndf::Beckmann beckmann_ndf; - scalar_type ndf = beckmann_ndf(ndfparams); - scalar_type orientedEta, dummy; - const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); + const bool backside = math::getOrientedEtas(orientedEta, dummy, params.VdotH, eta); const scalar_type orientedEta2 = orientedEta * orientedEta; - const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; + const scalar_type VdotHLdotH = params.VdotH * params.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); - - const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); - return pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, interaction.NdotV2, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta, dummy); - } - - scalar_type pdf(sample_type _sample, anisotropic_type interaction, anisocache_type cache) - { - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; - params_t params = params_t::template create(_sample, interaction, cache); - - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); - ndf::Beckmann beckmann_ndf; - scalar_type ndf = beckmann_ndf(ndfparams); - - scalar_type orientedEta, dummy; - const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); - const scalar_type orientedEta2 = orientedEta * orientedEta; + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(params.VdotH)); + + scalar_type ndf, lambda; + if (params.is_aniso) + { + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + ndf::Beckmann beckmann_ndf; + ndf = beckmann_ndf(ndfparams); - const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; - const bool transmitted = VdotHLdotH < 0.0; + smith::Beckmann beckmann_smith; + scalar_type c2 = beckmann_smith.C2(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); + lambda = beckmann_smith.Lambda(c2); + } + else + { + const scalar_type a2 = A.x*A.x; + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); + ndf::Beckmann beckmann_ndf; + ndf = beckmann_ndf(ndfparams); - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); - - const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); - return pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.VdotH, cache.LdotH, VdotHLdotH, ax2, ay2, orientedEta, dummy); + smith::Beckmann beckmann_smith; + lambda = beckmann_smith.Lambda(params.NdotV2, a2); + } + + return smith::VNDF_pdf_wo_clamps >(ndf,lambda,params.NdotV,transmitted,params.VdotH,params.LdotH,VdotHLdotH,orientedEta,reflectance,onePlusLambda_V); } - quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) + scalar_type pdf(params_t params) { - const scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, cache.NdotH, cache.NdotH2); - ndf::Beckmann beckmann_ndf; - scalar_type ndf = beckmann_ndf(ndfparams); - - scalar_type orientedEta, dummy; - const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); - const scalar_type orientedEta2 = orientedEta * orientedEta; - - const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; - const bool transmitted = VdotHLdotH < 0.0; - - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); - const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); - - scalar_type onePlusLambda_V; - scalar_type pdf = pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, interaction.NdotV2, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta, onePlusLambda_V); - - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, interaction.NdotV2, _sample.NdotL2, onePlusLambda_V); - smith::Beckmann beckmann_smith; - scalar_type quo = beckmann_smith.G2_over_G1(smithparams); - - return quotient_pdf_type::create((spectral_type)(quo), pdf); + scalar_type dummy; + return pdf(params, dummy); } - quotient_pdf_type quotient_and_pdf(sample_type _sample, anisotropic_type interaction, anisocache_type cache) + quotient_pdf_type quotient_and_pdf(params_t params) { - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; - params_t params = params_t::template create(_sample, interaction, cache); - - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); - ndf::Beckmann beckmann_ndf; - scalar_type ndf = beckmann_ndf(ndfparams); - - scalar_type orientedEta, dummy; - const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); - const scalar_type orientedEta2 = orientedEta * orientedEta; - - const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; - const bool transmitted = VdotHLdotH < 0.0; - - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); - const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); - scalar_type onePlusLambda_V; - scalar_type pdf = pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.VdotH, cache.LdotH, VdotHLdotH, ax2, ay2, orientedEta, onePlusLambda_V); + scalar_type _pdf = pdf(params, onePlusLambda_V); - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, onePlusLambda_V); - smith::Beckmann beckmann_smith; - scalar_type quo = beckmann_smith.G2_over_G1(smithparams); + scalar_type quo; + if (params.is_aniso) + { + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(A.x*A.x, A.y*A.y, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, onePlusLambda_V); + smith::Beckmann beckmann_smith; + quo = beckmann_smith.G2_over_G1(smithparams); + } + else + { + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(A.x*A.x, params.NdotV2, params.NdotL2, onePlusLambda_V); + smith::Beckmann beckmann_smith; + quo = beckmann_smith.G2_over_G1(smithparams); + } - return quotient_pdf_type::create((spectral_type)(quo), pdf); + return quotient_pdf_type::create((spectral_type)(quo), _pdf); } vector2_type A; @@ -561,42 +466,32 @@ struct SGGXDielectricBxDF return retval; } - spectral_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) - { - scalar_type orientedEta, dummy; - const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); - const scalar_type orientedEta2 = orientedEta * orientedEta; - - const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; - const bool transmitted = VdotHLdotH < 0.0; - - spectral_type dummyior; - params_t params = params_t::template create(_sample, interaction, cache, BCM_ABS); - reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, dummyior, dummyior); - const scalar_type NG_already_in_reflective_dL_measure = ggx.template __eval_DG_wo_clamps(params); - - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,nbl::hlsl::abs(_sample.NdotL),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); - return (spectral_type)fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); - } - - spectral_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) + spectral_type eval(params_t params) { scalar_type orientedEta, dummy; - const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); + const bool backside = math::getOrientedEtas(orientedEta, dummy, params.VdotH, eta); const scalar_type orientedEta2 = orientedEta * orientedEta; - const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; + const scalar_type VdotHLdotH = params.VdotH * params.LdotH; const bool transmitted = VdotHLdotH < 0.0; - spectral_type dummyior; - params_t params = params_t::template create(_sample, interaction, cache, BCM_ABS); - reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, A.y, dummyior, dummyior); - const scalar_type NG_already_in_reflective_dL_measure = ggx.template __eval_DG_wo_clamps(params); + scalar_type NG_already_in_reflective_dL_measure; + if (params.is_aniso) + { + spectral_type dummyior; + reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, A.y, dummyior, dummyior); + NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(params); + } + else + { + spectral_type dummyior; + reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, dummyior, dummyior); + NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(params); + } ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,nbl::hlsl::abs(_sample.NdotL),transmitted,cache.VdotH,cache.LdotH,VdotHLdotH,orientedEta); - return (spectral_type)fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)) * microfacet_transform(); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,params.NdotL,transmitted,params.VdotH,params.LdotH,VdotHLdotH,orientedEta); + return (spectral_type)fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(params.VdotH)) * microfacet_transform(); } sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix3x3_type m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) @@ -639,123 +534,67 @@ struct SGGXDielectricBxDF return generate(interaction, u, dummycache); } - scalar_type pdf_wo_clamps(bool transmitted, scalar_type reflectance, scalar_type ndf, scalar_type devsh_v, scalar_type absNdotV, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) - { - smith::GGX ggx_smith; - const scalar_type lambda = ggx_smith.G1_wo_numerator(absNdotV, devsh_v); - return smith::VNDF_pdf_wo_clamps(ndf,lambda,absNdotV,transmitted,VdotH,LdotH,VdotHLdotH,orientedEta,reflectance); - } - - scalar_type pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) + scalar_type pdf(params_t params) { - const scalar_type a2 = A.x*A.x; - params_t params = params_t::template create(_sample, interaction, cache, BCM_ABS); - - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); - ndf::GGX ggx_ndf; - scalar_type ndf = ggx_ndf(ndfparams); - - smith::GGX ggx_smith; - const scalar_type devsh_v = ggx_smith.devsh_part(params.NdotV2, a2, 1.0-a2); - scalar_type orientedEta, dummy; - const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); + const bool backside = math::getOrientedEtas(orientedEta, dummy, params.VdotH, eta); const scalar_type orientedEta2 = orientedEta * orientedEta; - const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; + const scalar_type VdotHLdotH = params.VdotH * params.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); + const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(params.VdotH)); - const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); - return pdf_wo_clamps(transmitted, reflectance, ndf, devsh_v, absNdotV, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta); - } + scalar_type ndf, devsh_v; + if (params.is_aniso) + { + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; - scalar_type pdf(sample_type _sample, anisotropic_type interaction, anisocache_type cache) - { - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; - params_t params = params_t::template create(_sample, interaction, cache, BCM_ABS); + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + ndf::GGX ggx_ndf; + ndf = ggx_ndf(ndfparams); - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); - ndf::GGX ggx_ndf; - scalar_type ndf = ggx_ndf(ndfparams); + smith::GGX ggx_smith; + devsh_v = ggx_smith.devsh_part(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); + } + else + { + const scalar_type a2 = A.x*A.x; + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); + ndf::GGX ggx_ndf; + ndf = ggx_ndf(ndfparams); - smith::GGX ggx_smith; - const scalar_type devsh_v = ggx_smith.devsh_part(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); - - scalar_type orientedEta, dummy; - const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); - const scalar_type orientedEta2 = orientedEta * orientedEta; - - const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; - const bool transmitted = VdotHLdotH < 0.0; - - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); - - const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); - return pdf_wo_clamps(transmitted, reflectance, ndf, absNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.VdotH, cache.LdotH, VdotHLdotH, ax2, ay2, orientedEta, dummy); - } - - quotient_pdf_type quotient_and_pdf(sample_type _sample, isotropic_type interaction, isocache_type cache) - { - const scalar_type a2 = A.x*A.x; - params_t params = params_t::template create(_sample, interaction, cache, BCM_ABS); - - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); - ndf::GGX ggx_ndf; - scalar_type ndf = ggx_ndf(ndfparams); + smith::GGX ggx_smith; + devsh_v = ggx_smith.devsh_part(params.NdotV2, a2, 1.0-a2); + } smith::GGX ggx_smith; - const scalar_type devsh_v = ggx_smith.devsh_part(params.NdotV2, a2, 1.0-a2); - - scalar_type orientedEta, dummy; - const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); - const scalar_type orientedEta2 = orientedEta * orientedEta; - - const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; - const bool transmitted = VdotHLdotH < 0.0; - - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); - - const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); - scalar_type pdf = pdf_wo_clamps(transmitted, reflectance, ndf, devsh_v, absNdotV, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta); - - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.NdotV, params.NdotV2, params.NdotL, params.NdotL2); - scalar_type quo = ggx_smith.G2_over_G1(smithparams); - - return quotient_pdf_type::create((spectral_type)(quo), pdf); + const scalar_type lambda = ggx_smith.G1_wo_numerator(params.NdotV, devsh_v); + return smith::VNDF_pdf_wo_clamps(ndf, lambda, params.NdotV, transmitted, params.VdotH, params.LdotH, VdotHLdotH, orientedEta, reflectance); } - quotient_pdf_type quotient_and_pdf(sample_type _sample, anisotropic_type interaction, anisocache_type cache) + quotient_pdf_type quotient_and_pdf(params_t params) { const scalar_type ax2 = A.x*A.x; const scalar_type ay2 = A.y*A.y; - params_t params = params_t::template create(_sample, interaction, cache, BCM_ABS); - - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); - ndf::GGX ggx_ndf; - scalar_type ndf = ggx_ndf(ndfparams); - - smith::GGX ggx_smith; - const scalar_type devsh_v = ggx_smith.devsh_part(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); - - scalar_type orientedEta, dummy; - const bool backside = math::getOrientedEtas(orientedEta, dummy, cache.VdotH, eta); - const scalar_type orientedEta2 = orientedEta * orientedEta; - - const scalar_type VdotHLdotH = cache.VdotH * cache.LdotH; - const bool transmitted = VdotHLdotH < 0.0; - - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(cache.VdotH)); - const scalar_type absNdotV = nbl::hlsl::abs(interaction.NdotV); - scalar_type pdf = pdf_wo_clamps(transmitted, reflectance, ndf, devsh_v, absNdotV, cache.VdotH, cache.LdotH, VdotHLdotH, orientedEta); - - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, absNdotV, params.TdotV2, params.BdotV2, params.NdotV2, abs(params.NdotL), params.TdotL2, params.BdotL2, params.NdotL2); - scalar_type quo = ggx_smith.G2_over_G1(smithparams); + scalar_type _pdf = pdf(params); - return quotient_pdf_type::create((spectral_type)(quo), pdf); + smith::GGX ggx_smith; + scalar_type quo; + if (params.is_aniso) + { + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2); + quo = ggx_smith.G2_over_G1(smithparams); + } + else + { + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(ax2, params.NdotV, params.NdotV2, params.NdotL, params.NdotL2); + quo = ggx_smith.G2_over_G1(smithparams); + } + + return quotient_pdf_type::create((spectral_type)(quo), _pdf); } vector2_type A; From bde6e60e17b6a02f30322e950a62dd9f6253f6ee Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 20 Jan 2025 11:44:54 +0700 Subject: [PATCH 059/188] some bug fixes --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 26 +++++++++---------- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 12 ++++----- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index a83057779d..a2654a7263 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -19,7 +19,7 @@ namespace hlsl // TODO: move into ieee754 namespace hlsl namespace ieee754 { - template) + template) T condNegate(T a, bool flip) { return flip ? (-a) : a; @@ -752,10 +752,10 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::spectral_type)) ((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) ((NBL_CONCEPT_REQ_TYPE)(T::params_t)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.eval(param)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.generate(aniso,aniso.N)), ::nbl::hlsl::is_same_v, typename T::sample_type)) - //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template pdf(_sample,iso)), ::nbl::hlsl::is_scalar_v)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.quotient_and_pdf(param)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.eval(param)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(aniso,aniso.N)), ::nbl::hlsl::is_same_v, typename T::sample_type)) + //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template pdf(_sample,iso)), ::nbl::hlsl::is_scalar_v)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) ) && Sample && spectral_of && surface_interactions::Isotropic && surface_interactions::Anisotropic; #undef param @@ -798,10 +798,10 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) ((NBL_CONCEPT_REQ_TYPE)(T::isocache_type)) ((NBL_CONCEPT_REQ_TYPE)(T::anisocache_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.eval(param)), ::nbl::hlsl::is_same_v, T::spectral_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.generate(aniso,aniso.N,anisocache)), ::nbl::hlsl::is_same_v, typename T::sample_type)) - //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.template pdf(_sample,iso)), ::nbl::hlsl::is_scalar_v)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T.quotient_and_pdf(param)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.eval(param)), ::nbl::hlsl::is_same_v, T::spectral_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(aniso,aniso.N,anisocache)), ::nbl::hlsl::is_same_v, typename T::sample_type)) + //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.template pdf(_sample,iso)), ::nbl::hlsl::is_scalar_v)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) ) && Sample && spectral_of && IsotropicMicrofacetCache && AnisotropicMicrofacetCache; #undef param @@ -917,11 +917,11 @@ struct SBxDFParams return retval; } - Scalar getMaxNdotV() { return max(NdotV, 0.0); } - Scalar getAbsNdotV() { return abs(NdotV); } + Scalar getMaxNdotV() { return max(uNdotV, 0.0); } + Scalar getAbsNdotV() { return abs(uNdotV); } - Scalar getMaxNdotL() { return max(NdotL, 0.0); } - Scalar getAbsNdotL() { return abs(NdotL); } + Scalar getMaxNdotL() { return max(uNdotL, 0.0); } + Scalar getAbsNdotL() { return abs(uNdotL); } // iso Scalar NdotH; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index e8c6abb97a..edbd6e1a6f 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -507,7 +507,7 @@ struct SBeckmannBxDF smith::Beckmann beckmann_smith; spectral_type quo = (spectral_type)0.0; - if (params.NdotL > numeric_limits::min && params.NdotV > numeric_limits::min) + if (params.uNdotL > numeric_limits::min && params.uNdotV > numeric_limits::min) { scalar_type G2_over_G1; if (params.is_aniso) @@ -662,7 +662,7 @@ struct SGGXBxDF smith::GGX ggx_smith; const scalar_type devsh_v = ggx_smith.devsh_part(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); - G1_over_2NdotV = ggx_smith.G1_wo_numerator(params.NdotV, devsh_v); + G1_over_2NdotV = ggx_smith.G1_wo_numerator(params.uNdotV, devsh_v); } else { @@ -673,7 +673,7 @@ struct SGGXBxDF smith::GGX ggx_smith; const scalar_type devsh_v = ggx_smith.devsh_part(params.NdotV2, a2, 1.0-a2); - G1_over_2NdotV = ggx_smith.G1_wo_numerator(params.NdotV, devsh_v); + G1_over_2NdotV = ggx_smith.G1_wo_numerator(params.uNdotV, devsh_v); } return smith::VNDF_pdf_wo_clamps(ndf, G1_over_2NdotV); } @@ -683,7 +683,7 @@ struct SGGXBxDF scalar_type _pdf = pdf(params); spectral_type quo = (spectral_type)0.0; - if (params.NdotL > numeric_limits::min && params.NdotV > numeric_limits::min) + if (params.uNdotL > numeric_limits::min && params.uNdotV > numeric_limits::min) { scalar_type G2_over_G1; smith::GGX ggx_smith; @@ -691,13 +691,13 @@ struct SGGXBxDF { const scalar_type ax2 = A.x*A.x; const scalar_type ay2 = A.y*A.y; - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2); + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.uNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.uNdotL, params.TdotL2, params.BdotL2, params.NdotL2); G2_over_G1 = ggx_smith.G2_over_G1(smithparams); } else { const scalar_type a2 = A.x*A.x; - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.NdotV, params.NdotV2, params.NdotL, params.NdotL2); + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.uNdotV, params.NdotV2, params.uNdotL, params.NdotL2); scalar_type G2_over_G1 = ggx_smith.G2_over_G1(smithparams); } const spectral_type reflectance = fresnelConductor(ior0, ior1, params.VdotH); From 3618e4ced3a54a920f840e27b7118527a0999c67 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 20 Jan 2025 16:29:02 +0700 Subject: [PATCH 060/188] more typo bug fixes --- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 6 +++--- include/nbl/builtin/hlsl/bxdf/transmission.hlsl | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index edbd6e1a6f..111e0f4d22 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -380,7 +380,7 @@ struct SBeckmannBxDF if (params.NdotV > numeric_limits::min) { scalar_type scalar_part = __eval_DG_wo_clamps(params); - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotV); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.uNdotV); return fresnelConductor(ior0, ior1, params.VdotH) * microfacet_transform(); } else @@ -491,7 +491,7 @@ struct SBeckmannBxDF lambda = beckmann_smith.Lambda(params.NdotV2, a2); } - return smith::VNDF_pdf_wo_clamps >(ndf, lambda, params.NdotV, onePlusLambda_V); + return smith::VNDF_pdf_wo_clamps >(ndf, lambda, params.uNdotV, onePlusLambda_V); } scalar_type pdf(params_t params) @@ -605,7 +605,7 @@ struct SGGXBxDF spectral_type eval(params_t params) { - if (params.NdotL > numeric_limits::min && params.NdotV > numeric_limits::min) + if (params.uNdotL > numeric_limits::min && params.uNdotV > numeric_limits::min) { scalar_type scalar_part = __eval_DG_wo_clamps(params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotL); diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index 2a14dc6f95..17b656c38d 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -248,7 +248,7 @@ struct SSmoothDielectricBxDF return 0; } - quotient_pdf_type quotient_and_pdf_wo_clamps(params_t params) // isotropic + quotient_pdf_type quotient_and_pdf(params_t params) // isotropic { const bool transmitted = isTransmissionPath(params.uNdotV, params.uNdotL); const spectral_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, params.NdotV)); From 5a00f7df86194b8f0e1cf065a9d9a0c07b63920e Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 21 Jan 2025 17:23:40 +0700 Subject: [PATCH 061/188] fix some calculations, ray dir info type --- examples_tests | 2 +- include/nbl/builtin/hlsl/bxdf/common.hlsl | 71 ++++++++++++------- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 10 +-- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 10 +-- 4 files changed, 57 insertions(+), 36 deletions(-) diff --git a/examples_tests b/examples_tests index 3305441824..3625ad2d55 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 33054418243f6f6fcd39f48a72bb6a5b996349f0 +Subproject commit 3625ad2d55e619e36f38fbf1cbd2a742677b02b2 diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index a2654a7263..2c8511d1f6 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -66,19 +66,24 @@ namespace ray_dir_info #define NBL_CONCEPT_PARAM_0 (rdirinfo, T) #define NBL_CONCEPT_PARAM_1 (N, typename T::vector3_type) #define NBL_CONCEPT_PARAM_2 (dirDotN, typename T::scalar_type) -NBL_CONCEPT_BEGIN(3) +#define NBL_CONCEPT_PARAM_3 (m, typename T::matrix3x3_type) +NBL_CONCEPT_BEGIN(4) #define rdirinfo NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define N NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define dirDotN NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +#define m NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::matrix3x3_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.direction), ::nbl::hlsl::is_same_v, typename T::vector3_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.getDirection()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.transmit()), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.reflect(N, dirDotN)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.refract(N, dirDotN)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::transform(m, rdirinfo)), ::nbl::hlsl::is_same_v, T)) ) && is_scalar_v && is_vector_v; +#undef m #undef dirDotN #undef N #undef rdirinfo @@ -89,30 +94,46 @@ struct SBasic { using scalar_type = T; using vector3_type = vector; + using matrix3x3_type = matrix; vector3_type getDirection() NBL_CONST_MEMBER_FUNC { return direction; } - SBasic transmit() + SBasic transmit() { - SBasic retval; + SBasic retval; retval.direction = -direction; return retval; } - SBasic reflect(NBL_CONST_REF_ARG(vector3_type) N, scalar_type directionDotN) + SBasic reflect(NBL_CONST_REF_ARG(vector3_type) N, scalar_type directionDotN) { - SBasic retval; + SBasic retval; retval.direction = math::reflect(direction,N,directionDotN); return retval; } - SBasic refract(NBL_CONST_REF_ARG(vector3_type) N, scalar_type eta) + SBasic refract(NBL_CONST_REF_ARG(vector3_type) N, scalar_type eta) { - SBasic retval; + SBasic retval; retval.direction = math::refract(direction,N,eta); return retval; } + // WARNING: matrix must be orthonormal + static SBasic transform(NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_CONST_REF_ARG(SBasic) r) + { +#ifndef __HLSL__VERSION + matrix3x3_type m_T = nbl::hlsl::transpose(m); + assert(nbl::hlsl::abs(nbl::hlsl::dot(m_T[0], m_T[1])) < 1e-5); + assert(nbl::hlsl::abs(nbl::hlsl::dot(m_T[0], m_T[2])) < 1e-5); + assert(nbl::hlsl::abs(nbl::hlsl::dot(m_T[1], m_T[2])) < 1e-5); +#endif + + SBasic retval; + retval.direction = nbl::hlsl::mul(m, r.direction); + return retval; + } + vector3_type direction; }; // more to come! @@ -195,7 +216,8 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.BdotV), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(iso,normT,normT)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getTangentSpaceV()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getTangentFrame()), ::nbl::hlsl::is_same_v, typename T::matrix3x3_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getToTangentSpace()), ::nbl::hlsl::is_same_v, typename T::matrix3x3_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getFromTangentSpace()), ::nbl::hlsl::is_same_v, typename T::matrix3x3_type)) ) && Isotropic && ray_dir_info::Basic; #undef normT #undef iso @@ -244,8 +266,8 @@ struct SAnisotropic : SIsotropic } vector3_type getTangentSpaceV() { return vector3_type(TdotV, BdotV, isotropic_type::NdotV); } - // WARNING: its the transpose of the old GLSL function return value! - matrix3x3_type getTangentFrame() { return matrix3x3_type(T, B, isotropic_type::N); } + matrix3x3_type getToTangentSpace() { return matrix3x3_type(T, B, isotropic_type::N); } + matrix3x3_type getFromTangentSpace() { return nbl::hlsl::transpose(matrix3x3_type(T, B, isotropic_type::N)); } vector3_type T; vector3_type B; @@ -286,7 +308,7 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.BdotL), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.NdotL), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.NdotL2), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createTangentSpace(pV,rdirinfo,frame)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createFromTangentSpace(pV,rdirinfo,frame)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(rdirinfo,pVdotL,pV)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(rdirinfo,pVdotL,pV,pV,pV)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create(pV,iso)), ::nbl::hlsl::is_same_v, T)) @@ -315,30 +337,29 @@ struct SLightSample using isotropic_type = surface_interactions::SIsotropic; using anisotropic_type = surface_interactions::SAnisotropic; - static this_t createTangentSpace( + static this_t createFromTangentSpace( NBL_CONST_REF_ARG(vector3_type) tangentSpaceV, NBL_CONST_REF_ARG(RayDirInfo) tangentSpaceL, - NBL_CONST_REF_ARG(matrix3x3_type) tangentFrame // WARNING: its the transpose of the old GLSL function return value! + NBL_CONST_REF_ARG(matrix3x3_type) tangentFrame ) { this_t retval; - - //retval.L = RayDirInfo::transform(tangentSpaceL,tangentFrame); - const vector3_type L = tangentSpaceL.getDirection(); - retval.L.direction = nbl::hlsl::mul(tangentFrame, L); // frame must be an orthonormal matrix - retval.VdotL = nbl::hlsl::dot(tangentSpaceV, L); - - retval.TdotL = L.x; - retval.BdotL = L.y; - retval.NdotL = L.z; + + const vector3_type tsL = tangentSpaceL.getDirection(); + retval.L = ray_dir_info_type::transform(tangentFrame, tangentSpaceL); + retval.VdotL = nbl::hlsl::dot(tangentSpaceV, tsL); + + retval.TdotL = tsL.x; + retval.BdotL = tsL.y; + retval.NdotL = tsL.z; retval.NdotL2 = retval.NdotL*retval.NdotL; - + return retval; } static this_t create(NBL_CONST_REF_ARG(RayDirInfo) L, const scalar_type VdotL, NBL_CONST_REF_ARG(vector3_type) N) { this_t retval; - + retval.L = L; retval.VdotL = VdotL; @@ -346,7 +367,7 @@ struct SLightSample retval.BdotL = nbl::hlsl::numeric_limits::signaling_NaN; retval.NdotL = nbl::hlsl::dot(N,L.direction); retval.NdotL2 = retval.NdotL * retval.NdotL; - + return retval; } static this_t create(NBL_CONST_REF_ARG(RayDirInfo) L, const scalar_type VdotL, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 111e0f4d22..97c797955a 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -73,7 +73,7 @@ struct SLambertianBxDF { ray_dir_info_type L; L.direction = projected_hemisphere_generate(u); - return sample_type::createTangentSpace(interaction.getTangentSpaceV(), L, interaction.getTangentFrame()); + return sample_type::createFromTangentSpace(interaction.getTangentSpaceV(), L, interaction.getFromTangentSpace()); } sample_type generate(anisotropic_type interaction, vector u) @@ -136,7 +136,7 @@ struct SOrenNayarBxDF { ray_dir_info_type L; L.direction = projected_hemisphere_generate(u); - return sample_type::createTangentSpace(interaction.getTangentSpaceV(), L, interaction.getTangentFrame()); + return sample_type::createFromTangentSpace(interaction.getTangentSpaceV(), L, interaction.getFromTangentSpace()); } sample_type generate(anisotropic_type interaction, vector2_type u) @@ -294,7 +294,7 @@ struct SBlinnPhongBxDF ray_dir_info_type localL; localL.direction = math::reflect(localV, H, cache.VdotH); - return sample_type::createTangentSpace(localV, localL, interaction.getTangentFrame()); + return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); } // where pdf? @@ -464,7 +464,7 @@ struct SBeckmannBxDF ray_dir_info_type localL; localL.direction = math::reflect(localV, H, cache.VdotH); - return sample_type::createTangentSpace(localV, localL, interaction.getTangentFrame()); + return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); } scalar_type pdf(params_t params, NBL_REF_ARG(scalar_type) onePlusLambda_V) @@ -646,7 +646,7 @@ struct SGGXBxDF ray_dir_info_type localL; localL.direction = math::reflect(localV, H, cache.VdotH); - return sample_type::createTangentSpace(localV, localL, interaction.getTangentFrame()); + return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); } scalar_type pdf(params_t params) diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index 17b656c38d..17682a7384 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -77,7 +77,7 @@ struct SLambertianBxDF { ray_dir_info_type L; L.direction = projected_sphere_generate(u); - return sample_type::createTangentSpace(interaction.getTangentSpaceV(), L, interaction.getTangentFrame()); + return sample_type::createFromTangentSpace(interaction.getTangentSpaceV(), L, interaction.getFromTangentSpace()); } sample_type generate(anisotropic_type interaction, vector u) @@ -336,7 +336,7 @@ struct SBeckmannDielectricBxDF ray_dir_info_type localL; localL.direction = math::reflectRefract_impl(transmitted, localV, H, VdotH, cache.LdotH, rcpOrientedEta); - return sample_type::createTangentSpace(localV, localL, m); + return sample_type::createFromTangentSpace(localV, localL, m); } sample_type generate(anisotropic_type interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) @@ -352,7 +352,7 @@ struct SBeckmannDielectricBxDF reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior, dummyior); const vector3_type H = beckmann.__generate(upperHemisphereV, u.xy); - return __generate_wo_clamps(localV, backside, H, interaction.getTangentFrame(), u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, cache); + return __generate_wo_clamps(localV, backside, H, interaction.getFromTangentSpace(), u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, cache); } sample_type generate(anisotropic_type interaction, NBL_REF_ARG(vector3_type) u) @@ -509,7 +509,7 @@ struct SGGXDielectricBxDF ray_dir_info_type localL; localL.direction = math::reflectRefract_impl(transmitted, localV, H, VdotH, cache.LdotH, rcpOrientedEta); - return sample_type::createTangentSpace(localV, localL, m); + return sample_type::createFromTangentSpace(localV, localL, m); } sample_type generate(anisotropic_type interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) @@ -525,7 +525,7 @@ struct SGGXDielectricBxDF reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, A.y, dummyior, dummyior); const vector3_type H = ggx.__generate(upperHemisphereV, u.xy); - return __generate_wo_clamps(localV, backside, H, interaction.getTangentFrame(), u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, cache); + return __generate_wo_clamps(localV, backside, H, interaction.getFromTangentSpace(), u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, cache); } sample_type generate(anisotropic_type interaction, NBL_REF_ARG(vector3_type) u) From 35ded62f390f92b14dff946f8493ad51451faf13 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 22 Jan 2025 15:15:12 +0700 Subject: [PATCH 062/188] fix not reading variables to param struct --- examples_tests | 2 +- include/nbl/builtin/hlsl/bxdf/common.hlsl | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/examples_tests b/examples_tests index 3625ad2d55..839d42c7cf 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 3625ad2d55e619e36f38fbf1cbd2a742677b02b2 +Subproject commit 839d42c7cfd5d11e550f1463a32fd3650eb3a99f diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 2c8511d1f6..eb315f52fb 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -855,10 +855,12 @@ struct SBxDFParams retval.NdotV = clamp == BCM_ABS ? abs(interaction.NdotV) : clamp == BCM_MAX ? max(interaction.NdotV, 0.0) : interaction.NdotV; + retval.uNdotV = interaction.NdotV; retval.NdotV2 = interaction.NdotV2; retval.NdotL = clamp == BCM_ABS ? abs(_sample.NdotL) : clamp == BCM_MAX ? max(_sample.NdotL, 0.0) : _sample.NdotL; + retval.uNdotL = _sample.NdotL; retval.NdotL2 = _sample.NdotL2; retval.VdotL = _sample.VdotL; retval.is_aniso = false; @@ -872,10 +874,12 @@ struct SBxDFParams retval.NdotV = clamp == BCM_ABS ? abs(interaction.NdotV) : clamp == BCM_MAX ? max(interaction.NdotV, 0.0) : interaction.NdotV; + retval.uNdotV = interaction.NdotV; retval.NdotV2 = interaction.NdotV2; retval.NdotL = clamp == BCM_ABS ? abs(_sample.NdotL) : clamp == BCM_MAX ? max(_sample.NdotL, 0.0) : _sample.NdotL; + retval.uNdotL = _sample.NdotL; retval.NdotL2 = _sample.NdotL2; retval.VdotL = _sample.VdotL; @@ -896,10 +900,12 @@ struct SBxDFParams retval.NdotV = clamp == BCM_ABS ? abs(interaction.NdotV) : clamp == BCM_MAX ? max(interaction.NdotV, 0.0) : interaction.NdotV; + retval.uNdotV = interaction.NdotV; retval.NdotV2 = interaction.NdotV2; retval.NdotL = clamp == BCM_ABS ? abs(_sample.NdotL) : clamp == BCM_MAX ? max(_sample.NdotL, 0.0) : _sample.NdotL; + retval.uNdotL = _sample.NdotL; retval.NdotL2 = _sample.NdotL2; retval.VdotH = cache.VdotH; retval.LdotH = cache.LdotH; From 7d8e98228a396eeb306f4cd58a1956364b9ec8a4 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 22 Jan 2025 15:59:41 +0700 Subject: [PATCH 063/188] duplicate variable bug fix --- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 97c797955a..79c340155e 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -698,7 +698,7 @@ struct SGGXBxDF { const scalar_type a2 = A.x*A.x; smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.uNdotV, params.NdotV2, params.uNdotL, params.NdotL2); - scalar_type G2_over_G1 = ggx_smith.G2_over_G1(smithparams); + G2_over_G1 = ggx_smith.G2_over_G1(smithparams); } const spectral_type reflectance = fresnelConductor(ior0, ior1, params.VdotH); quo = reflectance * G2_over_G1; From 6e5c569ba1c0a490f5a96b39f5d8680c2e43cfaa Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 24 Jan 2025 14:56:33 +0700 Subject: [PATCH 064/188] latest example: chi2 --- examples_tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples_tests b/examples_tests index 839d42c7cf..8ea15380de 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 839d42c7cfd5d11e550f1463a32fd3650eb3a99f +Subproject commit 8ea15380de98a95ce183dde6c27bc3f867804f0e From a1d18d3d66c31ac85b5f5d2027c4c8bc23c6c12a Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 27 Jan 2025 10:59:21 +0700 Subject: [PATCH 065/188] fix extent/rank type trait definition order --- include/nbl/builtin/hlsl/type_traits.hlsl | 38 +++++++++++------------ 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/include/nbl/builtin/hlsl/type_traits.hlsl b/include/nbl/builtin/hlsl/type_traits.hlsl index d6e3092e45..e5ae7229e9 100644 --- a/include/nbl/builtin/hlsl/type_traits.hlsl +++ b/include/nbl/builtin/hlsl/type_traits.hlsl @@ -577,25 +577,6 @@ template using conditional_t = typename conditional::type; -// Template Variables -template -NBL_CONSTEXPR bool is_same_v = is_same::value; -template -NBL_CONSTEXPR bool is_unsigned_v = is_unsigned::value; -template -NBL_CONSTEXPR bool is_integral_v = is_integral::value; -template -NBL_CONSTEXPR bool is_floating_point_v = is_floating_point::value; -template -NBL_CONSTEXPR bool is_signed_v = is_signed::value; -template -NBL_CONSTEXPR bool is_scalar_v = is_scalar::value; -template -NBL_CONSTEXPR uint32_t alignment_of_v = alignment_of::value; -template -NBL_CONSTEXPR uint64_t extent_v = extent::value; - - // Overlapping definitions template using make_void_t = typename make_void::type; @@ -660,6 +641,25 @@ struct extent, I> : integral_constant: #endif +// Template Variables +template +NBL_CONSTEXPR bool is_same_v = is_same::value; +template +NBL_CONSTEXPR bool is_unsigned_v = is_unsigned::value; +template +NBL_CONSTEXPR bool is_integral_v = is_integral::value; +template +NBL_CONSTEXPR bool is_floating_point_v = is_floating_point::value; +template +NBL_CONSTEXPR bool is_signed_v = is_signed::value; +template +NBL_CONSTEXPR bool is_scalar_v = is_scalar::value; +template +NBL_CONSTEXPR uint32_t alignment_of_v = alignment_of::value; +template +NBL_CONSTEXPR uint64_t extent_v = extent::value; + + template::value> struct scalar_type { From aceb79942694579851992edd91a038e9f4b688c0 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 27 Jan 2025 17:01:58 +0700 Subject: [PATCH 066/188] fix c++ compile --- examples_tests | 2 +- include/nbl/builtin/hlsl/bxdf/common.hlsl | 10 +++++----- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 12 ++++++------ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples_tests b/examples_tests index dcc2927d77..8781cb08ac 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit dcc2927d77d371231c62243ed8d1992219a9ef55 +Subproject commit 8781cb08ace883d996ced0538cf749fa5426e709 diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index eb315f52fb..370798c25b 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -265,9 +265,9 @@ struct SAnisotropic : SIsotropic return create(isotropic, TB[0], TB[1]); } - vector3_type getTangentSpaceV() { return vector3_type(TdotV, BdotV, isotropic_type::NdotV); } - matrix3x3_type getToTangentSpace() { return matrix3x3_type(T, B, isotropic_type::N); } - matrix3x3_type getFromTangentSpace() { return nbl::hlsl::transpose(matrix3x3_type(T, B, isotropic_type::N)); } + vector3_type getTangentSpaceV() NBL_CONST_MEMBER_FUNC { return vector3_type(TdotV, BdotV, isotropic_type::NdotV); } + matrix3x3_type getToTangentSpace() NBL_CONST_MEMBER_FUNC { return matrix3x3_type(T, B, isotropic_type::N); } + matrix3x3_type getFromTangentSpace() NBL_CONST_MEMBER_FUNC { return nbl::hlsl::transpose(matrix3x3_type(T, B, isotropic_type::N)); } vector3_type T; vector3_type B; @@ -395,7 +395,7 @@ struct SLightSample return create(L,VdotL,interaction.T,interaction.B,interaction.N); } // - vector3_type getTangentSpaceL() + vector3_type getTangentSpaceL() NBL_CONST_MEMBER_FUNC { return vector3_type(TdotL, BdotL, NdotL); } @@ -648,7 +648,7 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache this_t retval; scalar_type LplusV_rcpLen; - retval = (this_t)SIsotropicMicrofacetCache::createForReflection(tangentSpaceV.z, tangentSpaceL.z, VdotL, LplusV_rcpLen); + retval = (this_t)SIsotropicMicrofacetCache::createForReflection(tangentSpaceV.z, tangentSpaceL.z, VdotL, LplusV_rcpLen); retval.TdotH = (tangentSpaceV.x + tangentSpaceL.x) * LplusV_rcpLen; retval.BdotH = (tangentSpaceV.y + tangentSpaceL.y) * LplusV_rcpLen; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 79c340155e..a75cfcd1f9 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -420,14 +420,14 @@ struct SBeckmannBxDF const float MAX_ACCEPTABLE_ERR = 1.0e-5; int it = 0; float value=1000.0; - while (++it(value)>MAX_ACCEPTABLE_ERR) + while (++it < ITER_THRESHOLD && nbl::hlsl::abs(value) > MAX_ACCEPTABLE_ERR) { - if (!(b>=a && b<=c)) - b = 0.5 * (a+c); + if (!(b >= a && b <= c)) + b = 0.5 * (a + c); float invErf = erfInv(b); - value = normalization * (1.0 + b + numbers::inv_sqrtpi * tanTheta * exp(-invErf*invErf)) - sample_x; - float derivative = normalization * (1.0 - invErf*cosTheta); + value = normalization * (1.0 + b + numbers::inv_sqrtpi * tanTheta * exp(-invErf * invErf)) - sample_x; + float derivative = normalization * (1.0 - invErf * cosTheta); if (value > 0.0) c = b; @@ -438,7 +438,7 @@ struct SBeckmannBxDF } // TODO: investigate if we can replace these two erf^-1 calls with a box muller transform slope.x = erfInv(b); - slope.y = erfInv(2.0 * max(u.y,1.0e-6) - 1.0); + slope.y = erfInv(2.0 * max(u.y, 1.0e-6) - 1.0); } scalar_type sinTheta = sqrt(1.0 - V.z*V.z); From a0dddce5a77b7a1b2a0ddc25a9471f6e2c39fb35 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 29 Jan 2025 17:03:41 +0700 Subject: [PATCH 067/188] bxdf traits, bug fixes --- examples_tests | 2 +- .../nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl | 90 +++++++++++++++++++ include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl | 16 ++-- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 2 +- src/nbl/builtin/CMakeLists.txt | 1 + 5 files changed, 100 insertions(+), 11 deletions(-) create mode 100644 include/nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl diff --git a/examples_tests b/examples_tests index 8781cb08ac..9387298379 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 8781cb08ace883d996ced0538cf749fa5426e709 +Subproject commit 9387298379805f90f5f36982f2f18917bc837a17 diff --git a/include/nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl b/include/nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl new file mode 100644 index 0000000000..ad058aeccf --- /dev/null +++ b/include/nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl @@ -0,0 +1,90 @@ +// Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_BUILTIN_HLSL_BXDF_BXDF_TRAITS_INCLUDED_ +#define _NBL_BUILTIN_HLSL_BXDF_BXDF_TRAITS_INCLUDED_ + +#include "nbl/builtin/hlsl/bxdf/common.hlsl" +#include "nbl/builtin/hlsl/bxdf/reflection.hlsl" +#include "nbl/builtin/hlsl/bxdf/transmission.hlsl" + +namespace nbl +{ +namespace hlsl +{ + +enum BxDFType : uint16_t +{ + BT_BSDF = 0, + BT_BRDF, + BT_BTDF +}; + +template +struct bxdf_traits; + +template +struct bxdf_traits > +{ + NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = false; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; +}; + +template +struct bxdf_traits > +{ + NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; +}; + +// no blinn phong + +template +struct bxdf_traits > +{ + NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; +}; + +template +struct bxdf_traits > +{ + NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; +}; + + +template +struct bxdf_traits > +{ + NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = false; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; +}; + +// TODO: smooth dielectrics + +template +struct bxdf_traits > +{ + NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; +}; + +template +struct bxdf_traits > +{ + NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; +}; + +} +} + +#endif \ No newline at end of file diff --git a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl index cf3cda81c9..50a8e5cdf3 100644 --- a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl @@ -15,13 +15,6 @@ namespace bxdf namespace smith { - -template) -T G1(T lambda) -{ - return 1.0 / (1.0 + lambda); -} - template typename NDF::scalar_type VNDF_pdf_wo_clamps(typename NDF::scalar_type ndf, typename NDF::scalar_type lambda_V, typename NDF::scalar_type maxNdotV, NBL_REF_ARG(typename NDF::scalar_type) onePlusLambda_V) { @@ -159,6 +152,11 @@ struct Beckmann { using scalar_type = T; + scalar_type G1(scalar_type lambda) + { + return 1.0 / (1.0 + lambda); + } + scalar_type C2(scalar_type NdotX2, scalar_type a2) { return NdotX2 / (a2 * (1.0 - NdotX2)); @@ -193,7 +191,7 @@ struct Beckmann scalar_type L_v = Lambda(c2); c2 = C2(params.NdotL2, params.a2); scalar_type L_l = Lambda(c2); - return G1(L_v + L_l); + return G1(L_v + L_l); } scalar_type correlated(SAnisotropicParams params) @@ -202,7 +200,7 @@ struct Beckmann scalar_type L_v = Lambda(c2); c2 = C2(params.TdotL2, params.BdotL2, params.NdotL2, params.ax2, params.ay2); scalar_type L_l = Lambda(c2); - return G1(L_v + L_l); + return G1(L_v + L_l); } scalar_type G2_over_G1(SIsotropicParams params) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index a75cfcd1f9..bf534e2f8d 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -377,7 +377,7 @@ struct SBeckmannBxDF spectral_type eval(params_t params) { - if (params.NdotV > numeric_limits::min) + if (params.uNdotV > numeric_limits::min) { scalar_type scalar_part = __eval_DG_wo_clamps(params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.uNdotV); diff --git a/src/nbl/builtin/CMakeLists.txt b/src/nbl/builtin/CMakeLists.txt index 61f8afc8f6..3b4b7151b3 100644 --- a/src/nbl/builtin/CMakeLists.txt +++ b/src/nbl/builtin/CMakeLists.txt @@ -331,6 +331,7 @@ LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/geom_smith.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/ndf.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/reflection.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/transmission.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/bxdf_traits.hlsl") #subgroup LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/subgroup/ballot.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/subgroup/basic.hlsl") From 772c9b6df1060d5e59476de93a631a48ea92bc6b Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 30 Jan 2025 13:41:44 +0700 Subject: [PATCH 068/188] latest unit tests --- examples_tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples_tests b/examples_tests index 9387298379..de11fe214e 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 9387298379805f90f5f36982f2f18917bc837a17 +Subproject commit de11fe214e752e7b29001c5c1a1dcda04dfb6cbc From c4de15168684f634f057bc40c3e98507091e0403 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 30 Jan 2025 16:21:22 +0700 Subject: [PATCH 069/188] latest test #2 --- examples_tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples_tests b/examples_tests index de11fe214e..da1a4ade14 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit de11fe214e752e7b29001c5c1a1dcda04dfb6cbc +Subproject commit da1a4ade14fa02a9b8ad9ab850473a3b1b9db287 From 4bf43e3eb6c51dc18c1c5c4e7c74a5f4880558c7 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 31 Jan 2025 13:29:20 +0700 Subject: [PATCH 070/188] fixes to get smooth dielectric working --- examples_tests | 2 +- .../nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl | 16 +++++++- include/nbl/builtin/hlsl/bxdf/common.hlsl | 11 ++--- include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl | 2 +- .../nbl/builtin/hlsl/impl/tgmath_impl.hlsl | 40 +++++++++---------- 5 files changed, 43 insertions(+), 28 deletions(-) diff --git a/examples_tests b/examples_tests index a92746361c..d7f7a87fa0 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit a92746361cdf02328284db57888c564e36e2cd52 +Subproject commit d7f7a87fa08a56a16cd1bcc7d4d9fd48fc8c278c diff --git a/include/nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl b/include/nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl index ad058aeccf..e63cf0113e 100644 --- a/include/nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl @@ -66,7 +66,21 @@ struct bxdf_traits > NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; }; -// TODO: smooth dielectrics +template +struct bxdf_traits > +{ + NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; +}; + +template +struct bxdf_traits > +{ + NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; +}; template struct bxdf_traits > diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 370798c25b..e518f0dcba 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -10,6 +10,7 @@ #include "nbl/builtin/hlsl/concepts.hlsl" #include "nbl/builtin/hlsl/tgmath.hlsl" #include "nbl/builtin/hlsl/math/functions.hlsl" +#include "nbl/builtin/hlsl/vector_utils/vector_traits.hlsl" namespace nbl { @@ -1060,7 +1061,7 @@ struct ThinDielectricInfiniteScatter static T __call(T singleInterfaceReflectance) { const T doubleInterfaceReflectance = singleInterfaceReflectance * singleInterfaceReflectance; - return lerp((singleInterfaceReflectance - doubleInterfaceReflectance) / ((T)(1.0) - doubleInterfaceReflectance) * 2.0f, (T)(1.0), doubleInterfaceReflectance > (T)(0.9999)); + return nbl::hlsl::mix((singleInterfaceReflectance - doubleInterfaceReflectance) / ((T)(1.0) - doubleInterfaceReflectance) * 2.0f, (T)(1.0), doubleInterfaceReflectance > (T)(0.9999)); } static scalar_t __call(scalar_t singleInterfaceReflectance) // TODO: check redundancy when lerp on line 980 works @@ -1081,10 +1082,10 @@ template || is_vector_v) T diffuseFresnelCorrectionFactor(T n, T n2) { // assert(n*n==n2); - // vector TIR = n < (T)1.0; // maybe make extent work in C++? - T invdenum = lerp((T)1.0, (T)1.0 / (n2 * n2 * ((T)554.33 - 380.7 * n)), n < (T)1.0); - T num = n * lerp((T)(0.1921156102251088), n * 298.25 - 261.38 * n2 + 138.43, n < (T)1.0); - num += lerp((T)(0.8078843897748912), (T)(-1.67), n < (T)1.0); + vector::Dimension> TIR = n < (T)1.0; + T invdenum = nbl::hlsl::mix((T)1.0, (T)1.0 / (n2 * n2 * ((T)554.33 - 380.7 * n)), TIR); + T num = n * nbl::hlsl::mix((T)(0.1921156102251088), n * 298.25 - 261.38 * n2 + 138.43, TIR); + num += nbl::hlsl::mix((T)(0.8078843897748912), (T)(-1.67), TIR); return num * invdenum; } diff --git a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl index 50a8e5cdf3..61aa10399c 100644 --- a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl @@ -172,7 +172,7 @@ struct Beckmann scalar_type c = sqrt(c2); scalar_type nom = 1.0 - 1.259 * c + 0.396 * c2; scalar_type denom = 2.181 * c2 + 3.535 * c; - return lerp(0.0, nom / denom, c < 1.6); + return nbl::hlsl::mix(0.0, nom / denom, c < 1.6); } scalar_type Lambda(scalar_type NdotX2, scalar_type a2) diff --git a/include/nbl/builtin/hlsl/impl/tgmath_impl.hlsl b/include/nbl/builtin/hlsl/impl/tgmath_impl.hlsl index 9ae3f5ff56..0b67d42851 100644 --- a/include/nbl/builtin/hlsl/impl/tgmath_impl.hlsl +++ b/include/nbl/builtin/hlsl/impl/tgmath_impl.hlsl @@ -96,13 +96,13 @@ struct HELPER_NAME NBL_PARTIAL_REQ_TOP(is_same_v(experimental::declval())), T>) -struct cos_helper(experimental::declval())), T>) > -{ - static T __call(T arg) - { - return spirv::cos(arg); - } +template NBL_PARTIAL_REQ_TOP(is_same_v(experimental::declval())), T>) +struct cos_helper(experimental::declval())), T>) > +{ + static T __call(T arg) + { + return spirv::cos(arg); + } }; AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(acos_helper, acos, T) @@ -272,11 +272,11 @@ requires concepts::FloatingPointScalar struct isinf_helper { using return_t = bool; - static inline return_t __call(const T arg) + static inline return_t __call(const T arg) { - // GCC and Clang will always return false with call to std::isinf when fast math is enabled, - // this implementation will always return appropriate output regardless is fas math is enabled or not - using AsUint = typename unsigned_integer_of_size::type; + // GCC and Clang will always return false with call to std::isinf when fast math is enabled, + // this implementation will always return appropriate output regardless is fas math is enabled or not + using AsUint = typename unsigned_integer_of_size::type; return tgmath_impl::isinf_uint_impl(reinterpret_cast(arg)); } }; @@ -286,7 +286,7 @@ requires concepts::FloatingPointScalar struct isnan_helper { using return_t = bool; - static inline return_t __call(const T arg) + static inline return_t __call(const T arg) { // GCC and Clang will always return false with call to std::isnan when fast math is enabled, // this implementation will always return appropriate output regardless is fas math is enabled or not @@ -301,7 +301,7 @@ struct erf_helper(x); + return std::erf(x); } }; @@ -313,13 +313,13 @@ struct roundEven_helper(x); - if (result % 2 != 0) - result >= 0 ? ++result : --result; - return result; + float tmp; + if (std::abs(std::modf(x, &tmp)) == 0.5f) + { + int32_t result = static_cast(x); + if (result % 2 != 0) + result >= 0 ? ++result : --result; + return result; } return std::round(x); From edca69a42f2f61614a5042d641b206376f46100e Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 12 Feb 2025 13:39:44 +0700 Subject: [PATCH 071/188] pcg prng as structs --- examples_tests | 2 +- include/nbl/builtin/hlsl/random/pcg.hlsl | 64 ++++++++++++------------ 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/examples_tests b/examples_tests index da1a4ade14..111c11b51d 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit da1a4ade14fa02a9b8ad9ab850473a3b1b9db287 +Subproject commit 111c11b51d6076d67654a67eb53774f1c27dc55d diff --git a/include/nbl/builtin/hlsl/random/pcg.hlsl b/include/nbl/builtin/hlsl/random/pcg.hlsl index 307ab438b7..6d4f22edf8 100644 --- a/include/nbl/builtin/hlsl/random/pcg.hlsl +++ b/include/nbl/builtin/hlsl/random/pcg.hlsl @@ -10,51 +10,51 @@ namespace nbl namespace hlsl { -namespace impl +struct PCGStateHolder { + void pcg32_state_advance() + { + state = state * 747796405u + 2891336453u; + } -uint32_t pcg_hash(uint32_t v) -{ - uint32_t state = v * 747796405u + 2891336453u; - uint32_t word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u; - return (word >> 22u) ^ word; -} - -template -struct PCGHash; + uint32_t state; +}; -template<> -struct PCGHash +struct PCG32 { - static uint32_t __call(uint32_t v) + static PCG32 construct(NBL_CONST_REF_ARG(uint32_t) initialState) { - return pcg_hash(v); + PCGStateHolder stateHolder = {initialState}; + return PCG32(stateHolder); } -}; -template -struct PCGHash> -{ - static vector __call(vector v) + uint32_t operator()() { - vector retval; - for (int i = 0; i < N; i++) - retval[i] = pcg_hash(v[i]); - return retval; + const uint32_t word = ((stateHolder.state >> ((stateHolder.state >> 28u) + 4u)) ^ stateHolder.state) * 277803737u; + const uint32_t result = (word >> 22u) ^ word; + stateHolder.pcg32_state_advance(); + + return result; } + + PCGStateHolder stateHolder; }; -} -template -T pcg32(T v) +struct PCG32x2 { - return impl::PCGHash::__call(v); -} + static PCG32x2 construct(NBL_CONST_REF_ARG(uint32_t) initialState) + { + PCG32 rng = PCG32::construct(initialState); + return PCG32x2(rng); + } -uint32_t2 pcg32x2(uint32_t v) -{ - return impl::PCGHash::__call(uint32_t2(v, v+1)); -} + uint32_t2 operator()() + { + return uint32_t2(rng(), rng()); + } + + PCG rng; +}; } } From 967ec9e60af56850ca558fa3a8acca5b93369c96 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 12 Feb 2025 13:50:37 +0700 Subject: [PATCH 072/188] fix pcg bug --- include/nbl/builtin/hlsl/random/pcg.hlsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/nbl/builtin/hlsl/random/pcg.hlsl b/include/nbl/builtin/hlsl/random/pcg.hlsl index 6d4f22edf8..7d8fc58a08 100644 --- a/include/nbl/builtin/hlsl/random/pcg.hlsl +++ b/include/nbl/builtin/hlsl/random/pcg.hlsl @@ -53,7 +53,7 @@ struct PCG32x2 return uint32_t2(rng(), rng()); } - PCG rng; + PCG32 rng; }; } From 133764630777a903201c49f4257359b76dbcf736 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 27 Feb 2025 10:47:40 +0700 Subject: [PATCH 073/188] quick fix for compiling params in dxc --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 354 +++++++++++++++------- 1 file changed, 249 insertions(+), 105 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index e518f0dcba..f8d5c7ef1a 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -44,7 +44,7 @@ template) T computeMicrofacetNormal(bool _refract, vector V, vector L, T orientedEta) { const vector H = computeUnnormalizedMicrofacetNormal(_refract,V,L,orientedEta); - const T unnormRcpLen = rsqrt(nbl::hlsl::dot(H,H)); + const T unnormRcpLen = rsqrt(nbl::hlsl::dot >(H,H)); return H * unnormRcpLen; } @@ -105,7 +105,7 @@ struct SBasic retval.direction = -direction; return retval; } - + SBasic reflect(NBL_CONST_REF_ARG(vector3_type) N, scalar_type directionDotN) { SBasic retval; @@ -176,6 +176,7 @@ struct SIsotropic using ray_dir_info_type = RayDirInfo; using scalar_type = typename RayDirInfo::scalar_type; using vector3_type = typename RayDirInfo::vector3_type; + using isotropic_type = SIsotropic; // WARNING: Changed since GLSL, now arguments need to be normalized! static SIsotropic create(NBL_CONST_REF_ARG(RayDirInfo) normalizedV, NBL_CONST_REF_ARG(vector3_type) normalizedN) @@ -247,10 +248,10 @@ struct SAnisotropic : SIsotropic retval.N = isotropic.N; retval.NdotV = isotropic.NdotV; retval.NdotV2 = isotropic.NdotV2; - + retval.T = normalizedT; retval.B = normalizedB; - + retval.TdotV = nbl::hlsl::dot(retval.V.getDirection(), retval.T); retval.BdotV = nbl::hlsl::dot(retval.V.getDirection(), retval.B); @@ -278,6 +279,21 @@ struct SAnisotropic : SIsotropic } +template +struct interaction_traits; + +template +struct interaction_traits > +{ + NBL_CONSTEXPR_STATIC_INLINE bool is_aniso = false; +}; + +template +struct interaction_traits > +{ + NBL_CONSTEXPR_STATIC_INLINE bool is_aniso = true; +}; + #define NBL_CONCEPT_NAME Sample #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) @@ -312,8 +328,8 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createFromTangentSpace(pV,rdirinfo,frame)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(rdirinfo,pVdotL,pV)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(rdirinfo,pVdotL,pV,pV,pV)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create(pV,iso)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create(pV,aniso)), ::nbl::hlsl::is_same_v, T)) + //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create(pV,iso)), ::nbl::hlsl::is_same_v, T)) // NOTE: temporarily commented out due to dxc bug https://github.com/microsoft/DirectXShaderCompiler/issues/7154 + //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create(pV,aniso)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getTangentSpaceL()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) ) && surface_interactions::Anisotropic && surface_interactions::Isotropic && ray_dir_info::Basic; @@ -374,27 +390,27 @@ struct SLightSample static this_t create(NBL_CONST_REF_ARG(RayDirInfo) L, const scalar_type VdotL, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N) { this_t retval = create(L,VdotL,N); - + retval.TdotL = nbl::hlsl::dot(T,L.direction); retval.BdotL = nbl::hlsl::dot(B,L.direction); - + return retval; } - // overloads for surface_interactions - template - static this_t create(NBL_CONST_REF_ARG(vector3_type) L, NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction) - { - const vector3_type V = interaction.V.getDirection(); - const scalar_type VdotL = nbl::hlsl::dot(V,L); - return create(L, VdotL, interaction.N); - } - template - static this_t create(NBL_CONST_REF_ARG(vector3_type) L, NBL_CONST_REF_ARG(surface_interactions::SAnisotropic) interaction) - { - const vector3_type V = interaction.V.getDirection(); - const scalar_type VdotL = nbl::hlsl::dot(V,L); - return create(L,VdotL,interaction.T,interaction.B,interaction.N); - } + // overloads for surface_interactions, NOTE: temporarily commented out due to dxc bug https://github.com/microsoft/DirectXShaderCompiler/issues/7154 + // template + // static this_t create(NBL_CONST_REF_ARG(vector3_type) L, NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction) + // { + // const vector3_type V = interaction.V.getDirection(); + // const scalar_type VdotL = nbl::hlsl::dot(V,L); + // return create(L, VdotL, interaction.N); + // } + // template + // static this_t create(NBL_CONST_REF_ARG(vector3_type) L, NBL_CONST_REF_ARG(surface_interactions::SAnisotropic) interaction) + // { + // const vector3_type V = interaction.V.getDirection(); + // const scalar_type VdotL = nbl::hlsl::dot(V,L); + // return create(L,VdotL,interaction.T,interaction.B,interaction.N); + // } // vector3_type getTangentSpaceL() NBL_CONST_MEMBER_FUNC { @@ -404,7 +420,7 @@ struct SLightSample RayDirInfo L; scalar_type VdotL; - scalar_type TdotL; + scalar_type TdotL; scalar_type BdotL; scalar_type NdotL; scalar_type NdotL2; @@ -472,12 +488,12 @@ struct SIsotropicMicrofacetCache LplusV_rcpLen = rsqrt(2.0 + 2.0 * VdotL); this_t retval; - + retval.VdotH = LplusV_rcpLen * VdotL + LplusV_rcpLen; retval.LdotH = retval.VdotH; retval.NdotH = (NdotL + NdotV) * LplusV_rcpLen; retval.NdotH2 = retval.NdotH * retval.NdotH; - + return retval; } static this_t createForReflection(const scalar_type NdotV, const scalar_type NdotL, const scalar_type VdotL) @@ -503,10 +519,10 @@ struct SIsotropicMicrofacetCache // TODO: can we optimize? H = computeMicrofacetNormal(transmitted,V,L,orientedEta); retval.NdotH = nbl::hlsl::dot(N, H); - + // not coming from the medium (reflected) OR - // exiting at the macro scale AND ( (not L outside the cone of possible directions given IoR with constraint VdotH*LdotH<0.0) OR (microfacet not facing toward the macrosurface, i.e. non heightfield profile of microsurface) ) - const bool valid = !transmitted || (VdotL <= -min(orientedEta, rcpOrientedEta) && retval.NdotH > nbl::hlsl::numeric_limits::min()); + // exiting at the macro scale AND ( (not L outside the cone of possible directions given IoR with constraint VdotH*LdotH<0.0) OR (microfacet not facing toward the macrosurface, i.e. non heightfield profile of microsurface) ) + const bool valid = !transmitted || (VdotL <= -min(orientedEta, rcpOrientedEta) && retval.NdotH > nbl::hlsl::numeric_limits::min); if (valid) { // TODO: can we optimize? @@ -520,7 +536,7 @@ struct SIsotropicMicrofacetCache template && ray_dir_info::Basic) static bool compute( NBL_REF_ARG(this_t) retval, - NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction, + NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction, NBL_CONST_REF_ARG(SLightSample) _sample, const scalar_type eta, NBL_REF_ARG(vector3_type) H ) @@ -528,19 +544,19 @@ struct SIsotropicMicrofacetCache const scalar_type NdotV = interaction.NdotV; const scalar_type NdotL = _sample.NdotL; const bool transmitted = isTransmissionPath(NdotV,NdotL); - + scalar_type orientedEta, rcpOrientedEta; const bool backside = math::getOrientedEtas(orientedEta,rcpOrientedEta,NdotV,eta); const vector3_type V = interaction.V.getDirection(); - const vector3_type L = _sample.L; + const vector3_type L = _sample.L.direction; const scalar_type VdotL = nbl::hlsl::dot(V, L); return compute(retval,transmitted,V,L,interaction.N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); } template && ray_dir_info::Basic) static bool compute( NBL_REF_ARG(this_t) retval, - NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction, + NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction, NBL_CONST_REF_ARG(SLightSample) _sample, const scalar_type eta ) @@ -610,24 +626,25 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache using ray_dir_info_type = ray_dir_info::SBasic; using anisotropic_type = surface_interactions::SAnisotropic; + using isocache_type = SIsotropicMicrofacetCache; using sample_type = SLightSample; // always valid by construction static this_t create(NBL_CONST_REF_ARG(vector3_type) tangentSpaceV, NBL_CONST_REF_ARG(vector3_type) tangentSpaceH) { this_t retval; - + retval.VdotH = nbl::hlsl::dot(tangentSpaceV,tangentSpaceH); retval.LdotH = retval.VdotH; retval.NdotH = tangentSpaceH.z; retval.NdotH2 = retval.NdotH*retval.NdotH; retval.TdotH = tangentSpaceH.x; retval.BdotH = tangentSpaceH.y; - + return retval; } static this_t create( - NBL_CONST_REF_ARG(vector3_type) tangentSpaceV, + NBL_CONST_REF_ARG(vector3_type) tangentSpaceV, NBL_CONST_REF_ARG(vector3_type) tangentSpaceH, const bool transmitted, const scalar_type rcpOrientedEta, @@ -640,24 +657,28 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache const scalar_type VdotH = retval.VdotH; retval.LdotH = transmitted ? refract_compute_NdotT(VdotH<0.0,VdotH*VdotH,rcpOrientedEta2) : VdotH; } - + return retval; } // always valid because its specialized for the reflective case static this_t createForReflection(NBL_CONST_REF_ARG(vector3_type) tangentSpaceV, NBL_CONST_REF_ARG(vector3_type) tangentSpaceL, const scalar_type VdotL) { this_t retval; - + scalar_type LplusV_rcpLen; - retval = (this_t)SIsotropicMicrofacetCache::createForReflection(tangentSpaceV.z, tangentSpaceL.z, VdotL, LplusV_rcpLen); + isocache_type isocache = SIsotropicMicrofacetCache::createForReflection(tangentSpaceV.z, tangentSpaceL.z, VdotL, LplusV_rcpLen); + retval.VdotH = isocache.VdotH; + retval.LdotH = isocache.LdotH; + retval.NdotH = isocache.NdotH; + retval.NdotH2 = isocache.NdotH2; retval.TdotH = (tangentSpaceV.x + tangentSpaceL.x) * LplusV_rcpLen; retval.BdotH = (tangentSpaceV.y + tangentSpaceL.y) * LplusV_rcpLen; - + return retval; } template static this_t createForReflection( - NBL_CONST_REF_ARG(surface_interactions::SAnisotropic) interaction, + NBL_CONST_REF_ARG(surface_interactions::SAnisotropic) interaction, NBL_CONST_REF_ARG(SLightSample) _sample) { return createForReflection(interaction.getTangentSpaceV(), _sample.getTangentSpaceL(), _sample.VdotL); @@ -671,7 +692,12 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache const scalar_type orientedEta, const scalar_type rcpOrientedEta, NBL_REF_ARG(vector3_type) H ) { - const bool valid = this_t::compute(retval,transmitted,V,L,N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); + isocache_type iso = (isocache_type)retval; + const bool valid = isocache_type::compute(iso,transmitted,V,L,N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); + retval.VdotH = iso.VdotH; + retval.LdotH = iso.LdotH; + retval.NdotH = iso.NdotH; + retval.NdotH2 = iso.NdotH2; if (valid) { retval.TdotH = nbl::hlsl::dot(T,H); @@ -682,13 +708,18 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache template static bool compute( NBL_REF_ARG(this_t) retval, - NBL_CONST_REF_ARG(surface_interactions::SAnisotropic) interaction, + NBL_CONST_REF_ARG(surface_interactions::SAnisotropic) interaction, NBL_CONST_REF_ARG(SLightSample) _sample, const scalar_type eta ) { + isocache_type iso = (isocache_type)retval; vector3_type H; - const bool valid = this_t::compute(retval,interaction,_sample,eta,H); + const bool valid = isocache_type::compute(iso,interaction,_sample,eta,H); + retval.VdotH = iso.VdotH; + retval.LdotH = iso.LdotH; + retval.NdotH = iso.NdotH; + retval.NdotH2 = iso.NdotH2; if (valid) { retval.TdotH = nbl::hlsl::dot(interaction.T,H); @@ -701,6 +732,21 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache scalar_type BdotH; }; +template +struct microfacet_cache_traits; + +template +struct microfacet_cache_traits > +{ + NBL_CONSTEXPR_STATIC_INLINE bool is_aniso = false; +}; + +template +struct microfacet_cache_traits > +{ + NBL_CONSTEXPR_STATIC_INLINE bool is_aniso = true; +}; + #define NBL_CONCEPT_NAME generalized_spectral_of #define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename) @@ -739,7 +785,7 @@ struct quotient_and_pdf { return quotient*pdf; } - + SpectralBins quotient; Pdf pdf; }; @@ -844,47 +890,33 @@ enum BxDFClampMode : uint16_t BCM_ABS }; -template) -struct SBxDFParams +namespace impl { - using this_t = SBxDFParams; +// this is to substitute the lack of compile-time `if constexpr` on HLSL +template +struct __extract_aniso_vars; - template && surface_interactions::Isotropic) // maybe put template in struct vs function? - static this_t create(LightSample _sample, Iso interaction, BxDFClampMode clamp = BCM_NONE) +template +struct __extract_aniso_vars +{ + static __extract_aniso_vars create(NBL_CONST_REF_ARG(LightSample) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - this_t retval; - retval.NdotV = clamp == BCM_ABS ? abs(interaction.NdotV) : - clamp == BCM_MAX ? max(interaction.NdotV, 0.0) : - interaction.NdotV; - retval.uNdotV = interaction.NdotV; - retval.NdotV2 = interaction.NdotV2; - retval.NdotL = clamp == BCM_ABS ? abs(_sample.NdotL) : - clamp == BCM_MAX ? max(_sample.NdotL, 0.0) : - _sample.NdotL; - retval.uNdotL = _sample.NdotL; - retval.NdotL2 = _sample.NdotL2; - retval.VdotL = _sample.VdotL; - retval.is_aniso = false; + __extract_aniso_vars retval; return retval; } - template && surface_interactions::Anisotropic) - static SBxDFParams create(LightSample _sample, Aniso interaction, BxDFClampMode clamp = BCM_NONE) - { - this_t retval; - retval.NdotV = clamp == BCM_ABS ? abs(interaction.NdotV) : - clamp == BCM_MAX ? max(interaction.NdotV, 0.0) : - interaction.NdotV; - retval.uNdotV = interaction.NdotV; - retval.NdotV2 = interaction.NdotV2; - retval.NdotL = clamp == BCM_ABS ? abs(_sample.NdotL) : - clamp == BCM_MAX ? max(_sample.NdotL, 0.0) : - _sample.NdotL; - retval.uNdotL = _sample.NdotL; - retval.NdotL2 = _sample.NdotL2; - retval.VdotL = _sample.VdotL; + T TdotL2; + T BdotL2; + T TdotV2; + T BdotV2; +}; - retval.is_aniso = true; +template +struct __extract_aniso_vars +{ + static __extract_aniso_vars create(NBL_CONST_REF_ARG(LightSample) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + { + __extract_aniso_vars retval; retval.TdotL2 = _sample.TdotL * _sample.TdotL; retval.BdotL2 = _sample.BdotL * _sample.BdotL; retval.TdotV2 = interaction.TdotV * interaction.TdotV; @@ -892,42 +924,109 @@ struct SBxDFParams return retval; } - template && surface_interactions::Isotropic && IsotropicMicrofacetCache) - static this_t create(LightSample _sample, Iso interaction, Cache cache, BxDFClampMode clamp = BCM_NONE) + T TdotL2; + T BdotL2; + T TdotV2; + T BdotV2; +}; + +template +struct __extract_aniso_vars2; + +template +struct __extract_aniso_vars2 +{ + static __extract_aniso_vars2 create(NBL_CONST_REF_ARG(Cache) cache) + { + __extract_aniso_vars2 retval; + return retval; + } + + T TdotH2; + T BdotH2; +}; + +template +struct __extract_aniso_vars2 +{ + static __extract_aniso_vars2 create(NBL_CONST_REF_ARG(Cache) cache) + { + __extract_aniso_vars2 retval; + retval.TdotH2 = cache.TdotH * cache.TdotH; + retval.BdotH2 = cache.BdotH * cache.BdotH; + return retval; + } + + T TdotH2; + T BdotH2; +}; +} + +// unified param struct for calls to BxDF::eval, BxDF::pdf, BxDF::quotient_and_pdf +template) +struct SBxDFParams +{ + using this_t = SBxDFParams; + + template && (surface_interactions::Isotropic || surface_interactions::Anisotropic)) // maybe put template in struct vs function? + static this_t create(NBL_CONST_REF_ARG(LightSample) _sample, NBL_CONST_REF_ARG(Interaction) interaction, BxDFClampMode _clamp) { this_t retval; - retval.NdotH = cache.NdotH; - retval.NdotH2 = cache.NdotH2; - retval.NdotV = clamp == BCM_ABS ? abs(interaction.NdotV) : - clamp == BCM_MAX ? max(interaction.NdotV, 0.0) : + retval.NdotV = _clamp == BCM_ABS ? abs(interaction.NdotV) : + _clamp == BCM_MAX ? max(interaction.NdotV, 0.0) : interaction.NdotV; retval.uNdotV = interaction.NdotV; retval.NdotV2 = interaction.NdotV2; - retval.NdotL = clamp == BCM_ABS ? abs(_sample.NdotL) : - clamp == BCM_MAX ? max(_sample.NdotL, 0.0) : + retval.NdotL = _clamp == BCM_ABS ? abs(_sample.NdotL) : + _clamp == BCM_MAX ? max(_sample.NdotL, 0.0) : _sample.NdotL; retval.uNdotL = _sample.NdotL; retval.NdotL2 = _sample.NdotL2; - retval.VdotH = cache.VdotH; - retval.LdotH = cache.LdotH; retval.VdotL = _sample.VdotL; - retval.is_aniso = false; + + retval.is_aniso = interaction_traits::is_aniso; + impl::__extract_aniso_vars::is_aniso> vars = impl::__extract_aniso_vars::is_aniso>::create(_sample, interaction); + retval.TdotL2 = vars.TdotL2; + retval.BdotL2 = vars.BdotL2; + retval.TdotV2 = vars.TdotV2; + retval.BdotV2 = vars.BdotV2; return retval; } - template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - static SBxDFParams create(LightSample _sample, Aniso interaction, Cache cache, BxDFClampMode clamp = BCM_NONE) + // template && surface_interactions::Anisotropic) + // static this_t create(LightSample _sample, Aniso interaction, BxDFClampMode clamp = BCM_NONE) + // { + // this_t retval; + // retval.NdotV = clamp == BCM_ABS ? abs(interaction.NdotV) : + // clamp == BCM_MAX ? max(interaction.NdotV, 0.0) : + // interaction.NdotV; + // retval.uNdotV = interaction.NdotV; + // retval.NdotV2 = interaction.NdotV2; + // retval.NdotL = clamp == BCM_ABS ? abs(_sample.NdotL) : + // clamp == BCM_MAX ? max(_sample.NdotL, 0.0) : + // _sample.NdotL; + // retval.uNdotL = _sample.NdotL; + // retval.NdotL2 = _sample.NdotL2; + // retval.VdotL = _sample.VdotL; + + // retval.is_aniso = true; + + // return retval; + // } + + template && (surface_interactions::Isotropic || surface_interactions::Anisotropic) && (IsotropicMicrofacetCache || AnisotropicMicrofacetCache)) + static this_t create(NBL_CONST_REF_ARG(LightSample) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(Cache) cache, BxDFClampMode _clamp) { this_t retval; retval.NdotH = cache.NdotH; retval.NdotH2 = cache.NdotH2; - retval.NdotV = clamp == BCM_ABS ? abs(interaction.NdotV) : - clamp == BCM_MAX ? max(interaction.NdotV, 0.0) : + retval.NdotV = _clamp == BCM_ABS ? abs(interaction.NdotV) : + _clamp == BCM_MAX ? max(interaction.NdotV, 0.0) : interaction.NdotV; retval.uNdotV = interaction.NdotV; retval.NdotV2 = interaction.NdotV2; - retval.NdotL = clamp == BCM_ABS ? abs(_sample.NdotL) : - clamp == BCM_MAX ? max(_sample.NdotL, 0.0) : + retval.NdotL = _clamp == BCM_ABS ? abs(_sample.NdotL) : + _clamp == BCM_MAX ? max(_sample.NdotL, 0.0) : _sample.NdotL; retval.uNdotL = _sample.NdotL; retval.NdotL2 = _sample.NdotL2; @@ -935,16 +1034,48 @@ struct SBxDFParams retval.LdotH = cache.LdotH; retval.VdotL = _sample.VdotL; - retval.is_aniso = true; - retval.TdotH2 = cache.TdotH * cache.TdotH; - retval.BdotH2 = cache.BdotH * cache.BdotH; - retval.TdotL2 = _sample.TdotL * _sample.TdotL; - retval.BdotL2 = _sample.BdotL * _sample.BdotL; - retval.TdotV2 = interaction.TdotV * interaction.TdotV; - retval.BdotV2 = interaction.BdotV * interaction.BdotV; + retval.is_aniso = interaction_traits::is_aniso; + impl::__extract_aniso_vars::is_aniso> vars = impl::__extract_aniso_vars::is_aniso>::create(_sample, interaction); + retval.TdotL2 = vars.TdotL2; + retval.BdotL2 = vars.BdotL2; + retval.TdotV2 = vars.TdotV2; + retval.BdotV2 = vars.BdotV2; + impl::__extract_aniso_vars2::is_aniso> vars2 = impl::__extract_aniso_vars2::is_aniso>::create(cache); + retval.TdotH2 = vars2.TdotH2; + retval.BdotH2 = vars2.BdotH2; return retval; } + // template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + // static this_t create(LightSample _sample, Aniso interaction, Cache cache, BxDFClampMode clamp = BCM_NONE) + // { + // this_t retval; + // retval.NdotH = cache.NdotH; + // retval.NdotH2 = cache.NdotH2; + // retval.NdotV = clamp == BCM_ABS ? abs(interaction.NdotV) : + // clamp == BCM_MAX ? max(interaction.NdotV, 0.0) : + // interaction.NdotV; + // retval.uNdotV = interaction.NdotV; + // retval.NdotV2 = interaction.NdotV2; + // retval.NdotL = clamp == BCM_ABS ? abs(_sample.NdotL) : + // clamp == BCM_MAX ? max(_sample.NdotL, 0.0) : + // _sample.NdotL; + // retval.uNdotL = _sample.NdotL; + // retval.NdotL2 = _sample.NdotL2; + // retval.VdotH = cache.VdotH; + // retval.LdotH = cache.LdotH; + // retval.VdotL = _sample.VdotL; + + // retval.is_aniso = true; + // retval.TdotH2 = cache.TdotH * cache.TdotH; + // retval.BdotH2 = cache.BdotH * cache.BdotH; + // retval.TdotL2 = _sample.TdotL * _sample.TdotL; + // retval.BdotL2 = _sample.BdotL * _sample.BdotL; + // retval.TdotV2 = interaction.TdotV * interaction.TdotV; + // retval.BdotV2 = interaction.BdotV * interaction.BdotV; + // return retval; + // } + Scalar getMaxNdotV() { return max(uNdotV, 0.0); } Scalar getAbsNdotV() { return abs(uNdotV); } @@ -976,6 +1107,19 @@ struct SBxDFParams Scalar uNdotV; }; +// unified param struct for calls to BxDF::create +template) +struct SBxDFCreationParams +{ + bool is_aniso; + vector A; // roughness + Spectrum ior0; // source ior + Spectrum ior1; // destination ior + Scalar eta; // in most cases, eta will be calculated from ior0 and ior1; see monochromeEta in pathtracer.hlsl + Spectrum eta2; + Spectrum luminosityContributionHint; +}; + // fresnel stuff namespace impl { @@ -983,7 +1127,7 @@ template struct fresnel { using scalar_t = typename scalar_type::type; - + static T conductor(T eta, T etak, scalar_t cosTheta) { const scalar_t cosTheta2 = cosTheta * cosTheta; @@ -997,7 +1141,7 @@ struct fresnel const T rp_common = etaLen2 * cosTheta2 + (T)(1.0); const T rp2 = (rp_common - etaCosTwice) / (rp_common + etaCosTwice); - + return (rs2 + rp2) * 0.5f; } From d3b3c59916bc2c43eebc65fb2a7b287947202502 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 27 Feb 2025 17:40:00 +0700 Subject: [PATCH 074/188] refactor changes to interaction, cache, new fresnel funcs --- examples_tests | 2 +- include/nbl/builtin/hlsl/bxdf/common.hlsl | 241 +++++------------- include/nbl/builtin/hlsl/bxdf/fresnel.hlsl | 115 ++++++++- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 20 +- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 63 ++--- include/nbl/builtin/hlsl/type_traits.hlsl | 30 ++- src/nbl/builtin/CMakeLists.txt | 1 + 7 files changed, 232 insertions(+), 240 deletions(-) diff --git a/examples_tests b/examples_tests index ff95b3bd8f..f3144f14c1 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit ff95b3bd8f58190aea2e1f961f414c7d195f6c4d +Subproject commit f3144f14c107d86667a23f64b2686a71b20ee473 diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index f8d5c7ef1a..0e3ee5bdd0 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -10,6 +10,7 @@ #include "nbl/builtin/hlsl/concepts.hlsl" #include "nbl/builtin/hlsl/tgmath.hlsl" #include "nbl/builtin/hlsl/math/functions.hlsl" +#include "nbl/builtin/hlsl/bxdf/fresnel.hlsl" #include "nbl/builtin/hlsl/vector_utils/vector_traits.hlsl" namespace nbl @@ -109,14 +110,15 @@ struct SBasic SBasic reflect(NBL_CONST_REF_ARG(vector3_type) N, scalar_type directionDotN) { SBasic retval; - retval.direction = math::reflect(direction,N,directionDotN); + retval.direction = bxdf::reflect(direction,N,directionDotN); return retval; } SBasic refract(NBL_CONST_REF_ARG(vector3_type) N, scalar_type eta) { SBasic retval; - retval.direction = math::refract(direction,N,eta); + bxdf::refract r = bxdf::refract::create(direction,N,eta); + retval.direction = r.doRefract(); return retval; } @@ -176,7 +178,6 @@ struct SIsotropic using ray_dir_info_type = RayDirInfo; using scalar_type = typename RayDirInfo::scalar_type; using vector3_type = typename RayDirInfo::vector3_type; - using isotropic_type = SIsotropic; // WARNING: Changed since GLSL, now arguments need to be normalized! static SIsotropic create(NBL_CONST_REF_ARG(RayDirInfo) normalizedV, NBL_CONST_REF_ARG(vector3_type) normalizedN) @@ -227,7 +228,7 @@ NBL_CONCEPT_END( #include template) -struct SAnisotropic : SIsotropic +struct SAnisotropic { using ray_dir_info_type = RayDirInfo; using scalar_type = typename RayDirInfo::scalar_type; @@ -243,17 +244,13 @@ struct SAnisotropic : SIsotropic ) { SAnisotropic retval; - //(SIsotropic) retval = isotropic; - retval.V = isotropic.V; - retval.N = isotropic.N; - retval.NdotV = isotropic.NdotV; - retval.NdotV2 = isotropic.NdotV2; + retval.isotropic = isotropic; retval.T = normalizedT; retval.B = normalizedB; - retval.TdotV = nbl::hlsl::dot(retval.V.getDirection(), retval.T); - retval.BdotV = nbl::hlsl::dot(retval.V.getDirection(), retval.B); + retval.TdotV = nbl::hlsl::dot(retval.isotropic.V.getDirection(), retval.T); + retval.BdotV = nbl::hlsl::dot(retval.isotropic.V.getDirection(), retval.B); return retval; } @@ -263,14 +260,16 @@ struct SAnisotropic : SIsotropic } static SAnisotropic create(NBL_CONST_REF_ARG(isotropic_type) isotropic) { - matrix TB = math::frisvad(isotropic.N); - return create(isotropic, TB[0], TB[1]); + vector3_type T, B; + math::frisvad(isotropic.N, T, B); + return create(isotropic, nbl::hlsl::normalize(T), nbl::hlsl::normalize(B)); } - vector3_type getTangentSpaceV() NBL_CONST_MEMBER_FUNC { return vector3_type(TdotV, BdotV, isotropic_type::NdotV); } - matrix3x3_type getToTangentSpace() NBL_CONST_MEMBER_FUNC { return matrix3x3_type(T, B, isotropic_type::N); } - matrix3x3_type getFromTangentSpace() NBL_CONST_MEMBER_FUNC { return nbl::hlsl::transpose(matrix3x3_type(T, B, isotropic_type::N)); } + vector3_type getTangentSpaceV() NBL_CONST_MEMBER_FUNC { return vector3_type(TdotV, BdotV, isotropic.NdotV); } + matrix3x3_type getToTangentSpace() NBL_CONST_MEMBER_FUNC { return matrix3x3_type(T, B, isotropic.N); } + matrix3x3_type getFromTangentSpace() NBL_CONST_MEMBER_FUNC { return nbl::hlsl::transpose(matrix3x3_type(T, B, isotropic.N)); } + isotropic_type isotropic; vector3_type T; vector3_type B; scalar_type TdotV; @@ -546,7 +545,7 @@ struct SIsotropicMicrofacetCache const bool transmitted = isTransmissionPath(NdotV,NdotL); scalar_type orientedEta, rcpOrientedEta; - const bool backside = math::getOrientedEtas(orientedEta,rcpOrientedEta,NdotV,eta); + const bool backside = bxdf::getOrientedEtas(orientedEta,rcpOrientedEta,NdotV,eta); const vector3_type V = interaction.V.getDirection(); const vector3_type L = _sample.L.direction; @@ -617,7 +616,7 @@ NBL_CONCEPT_END( #include template ) -struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache +struct SAnisotropicMicrofacetCache { using this_t = SAnisotropicMicrofacetCache; using scalar_type = U; @@ -634,10 +633,10 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache { this_t retval; - retval.VdotH = nbl::hlsl::dot(tangentSpaceV,tangentSpaceH); - retval.LdotH = retval.VdotH; - retval.NdotH = tangentSpaceH.z; - retval.NdotH2 = retval.NdotH*retval.NdotH; + retval.iso_cache.VdotH = nbl::hlsl::dot(tangentSpaceV,tangentSpaceH); + retval.iso_cache.LdotH = retval.iso_cache.VdotH; + retval.iso_cache.NdotH = tangentSpaceH.z; + retval.iso_cache.NdotH2 = retval.iso_cache.NdotH * retval.iso_cache.NdotH; retval.TdotH = tangentSpaceH.x; retval.BdotH = tangentSpaceH.y; @@ -654,8 +653,8 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache this_t retval = create(tangentSpaceV,tangentSpaceH); if (transmitted) { - const scalar_type VdotH = retval.VdotH; - retval.LdotH = transmitted ? refract_compute_NdotT(VdotH<0.0,VdotH*VdotH,rcpOrientedEta2) : VdotH; + const scalar_type VdotH = retval.iso_cache.VdotH; + retval.iso_cache.LdotH = transmitted ? refract_compute_NdotT(VdotH<0.0,VdotH*VdotH,rcpOrientedEta2) : VdotH; } return retval; @@ -666,11 +665,7 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache this_t retval; scalar_type LplusV_rcpLen; - isocache_type isocache = SIsotropicMicrofacetCache::createForReflection(tangentSpaceV.z, tangentSpaceL.z, VdotL, LplusV_rcpLen); - retval.VdotH = isocache.VdotH; - retval.LdotH = isocache.LdotH; - retval.NdotH = isocache.NdotH; - retval.NdotH2 = isocache.NdotH2; + retval.iso_cache = SIsotropicMicrofacetCache::createForReflection(tangentSpaceV.z, tangentSpaceL.z, VdotL, LplusV_rcpLen); retval.TdotH = (tangentSpaceV.x + tangentSpaceL.x) * LplusV_rcpLen; retval.BdotH = (tangentSpaceV.y + tangentSpaceL.y) * LplusV_rcpLen; @@ -692,12 +687,7 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache const scalar_type orientedEta, const scalar_type rcpOrientedEta, NBL_REF_ARG(vector3_type) H ) { - isocache_type iso = (isocache_type)retval; - const bool valid = isocache_type::compute(iso,transmitted,V,L,N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); - retval.VdotH = iso.VdotH; - retval.LdotH = iso.LdotH; - retval.NdotH = iso.NdotH; - retval.NdotH2 = iso.NdotH2; + const bool valid = isocache_type::compute(retval.iso_cache,transmitted,V,L,N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); if (valid) { retval.TdotH = nbl::hlsl::dot(T,H); @@ -713,13 +703,8 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache const scalar_type eta ) { - isocache_type iso = (isocache_type)retval; vector3_type H; - const bool valid = isocache_type::compute(iso,interaction,_sample,eta,H); - retval.VdotH = iso.VdotH; - retval.LdotH = iso.LdotH; - retval.NdotH = iso.NdotH; - retval.NdotH2 = iso.NdotH2; + const bool valid = isocache_type::compute(retval.iso_cache,interaction,_sample,eta,H); if (valid) { retval.TdotH = nbl::hlsl::dot(interaction.T,H); @@ -728,6 +713,7 @@ struct SAnisotropicMicrofacetCache : SIsotropicMicrofacetCache return valid; } + isocache_type iso_cache; scalar_type TdotH; scalar_type BdotH; }; @@ -902,9 +888,13 @@ struct __extract_aniso_vars static __extract_aniso_vars create(NBL_CONST_REF_ARG(LightSample) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { __extract_aniso_vars retval; + retval.NdotV = interaction.NdotV; + retval.NdotV2 = interaction.NdotV2; return retval; } + T NdotV; + T NdotV2; T TdotL2; T BdotL2; T TdotV2; @@ -917,6 +907,8 @@ struct __extract_aniso_vars static __extract_aniso_vars create(NBL_CONST_REF_ARG(LightSample) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { __extract_aniso_vars retval; + retval.NdotV = interaction.isotropic.NdotV; + retval.NdotV2 = interaction.isotropic.NdotV2; retval.TdotL2 = _sample.TdotL * _sample.TdotL; retval.BdotL2 = _sample.BdotL * _sample.BdotL; retval.TdotV2 = interaction.TdotV * interaction.TdotV; @@ -924,6 +916,8 @@ struct __extract_aniso_vars return retval; } + T NdotV; + T NdotV2; T TdotL2; T BdotL2; T TdotV2; @@ -939,9 +933,17 @@ struct __extract_aniso_vars2 static __extract_aniso_vars2 create(NBL_CONST_REF_ARG(Cache) cache) { __extract_aniso_vars2 retval; + retval.NdotH = cache.NdotH; + retval.NdotH2 = cache.NdotH2; + retval.VdotH = cache.VdotH; + retval.LdotH = cache.LdotH; return retval; } + T NdotH; + T NdotH2; + T VdotH; + T LdotH; T TdotH2; T BdotH2; }; @@ -952,11 +954,19 @@ struct __extract_aniso_vars2 static __extract_aniso_vars2 create(NBL_CONST_REF_ARG(Cache) cache) { __extract_aniso_vars2 retval; + retval.NdotH = cache.iso_cache.NdotH; + retval.NdotH2 = cache.iso_cache.NdotH2; + retval.VdotH = cache.iso_cache.VdotH; + retval.LdotH = cache.iso_cache.LdotH; retval.TdotH2 = cache.TdotH * cache.TdotH; retval.BdotH2 = cache.BdotH * cache.BdotH; return retval; } + T NdotH; + T NdotH2; + T VdotH; + T LdotH; T TdotH2; T BdotH2; }; @@ -971,12 +981,14 @@ struct SBxDFParams template && (surface_interactions::Isotropic || surface_interactions::Anisotropic)) // maybe put template in struct vs function? static this_t create(NBL_CONST_REF_ARG(LightSample) _sample, NBL_CONST_REF_ARG(Interaction) interaction, BxDFClampMode _clamp) { + impl::__extract_aniso_vars::is_aniso> vars = impl::__extract_aniso_vars::is_aniso>::create(_sample, interaction); + this_t retval; - retval.NdotV = _clamp == BCM_ABS ? abs(interaction.NdotV) : - _clamp == BCM_MAX ? max(interaction.NdotV, 0.0) : - interaction.NdotV; - retval.uNdotV = interaction.NdotV; - retval.NdotV2 = interaction.NdotV2; + retval.NdotV = _clamp == BCM_ABS ? abs(vars.NdotV) : + _clamp == BCM_MAX ? max(vars.NdotV, 0.0) : + vars.NdotV; + retval.uNdotV = vars.NdotV; + retval.NdotV2 = vars.NdotV2; retval.NdotL = _clamp == BCM_ABS ? abs(_sample.NdotL) : _clamp == BCM_MAX ? max(_sample.NdotL, 0.0) : _sample.NdotL; @@ -985,7 +997,6 @@ struct SBxDFParams retval.VdotL = _sample.VdotL; retval.is_aniso = interaction_traits::is_aniso; - impl::__extract_aniso_vars::is_aniso> vars = impl::__extract_aniso_vars::is_aniso>::create(_sample, interaction); retval.TdotL2 = vars.TdotL2; retval.BdotL2 = vars.BdotL2; retval.TdotV2 = vars.TdotV2; @@ -1017,30 +1028,31 @@ struct SBxDFParams template && (surface_interactions::Isotropic || surface_interactions::Anisotropic) && (IsotropicMicrofacetCache || AnisotropicMicrofacetCache)) static this_t create(NBL_CONST_REF_ARG(LightSample) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(Cache) cache, BxDFClampMode _clamp) { + impl::__extract_aniso_vars::is_aniso> vars = impl::__extract_aniso_vars::is_aniso>::create(_sample, interaction); + impl::__extract_aniso_vars2::is_aniso> vars2 = impl::__extract_aniso_vars2::is_aniso>::create(cache); + this_t retval; - retval.NdotH = cache.NdotH; - retval.NdotH2 = cache.NdotH2; - retval.NdotV = _clamp == BCM_ABS ? abs(interaction.NdotV) : - _clamp == BCM_MAX ? max(interaction.NdotV, 0.0) : - interaction.NdotV; - retval.uNdotV = interaction.NdotV; - retval.NdotV2 = interaction.NdotV2; + retval.NdotH = vars2.NdotH; + retval.NdotH2 = vars2.NdotH2; + retval.NdotV = _clamp == BCM_ABS ? abs(vars.NdotV) : + _clamp == BCM_MAX ? max(vars.NdotV, 0.0) : + vars.NdotV; + retval.uNdotV = vars.NdotV; + retval.NdotV2 = vars.NdotV2; retval.NdotL = _clamp == BCM_ABS ? abs(_sample.NdotL) : _clamp == BCM_MAX ? max(_sample.NdotL, 0.0) : _sample.NdotL; retval.uNdotL = _sample.NdotL; retval.NdotL2 = _sample.NdotL2; - retval.VdotH = cache.VdotH; - retval.LdotH = cache.LdotH; + retval.VdotH = vars2.VdotH; + retval.LdotH = vars2.LdotH; retval.VdotL = _sample.VdotL; retval.is_aniso = interaction_traits::is_aniso; - impl::__extract_aniso_vars::is_aniso> vars = impl::__extract_aniso_vars::is_aniso>::create(_sample, interaction); retval.TdotL2 = vars.TdotL2; retval.BdotL2 = vars.BdotL2; retval.TdotV2 = vars.TdotV2; retval.BdotV2 = vars.BdotV2; - impl::__extract_aniso_vars2::is_aniso> vars2 = impl::__extract_aniso_vars2::is_aniso>::create(cache); retval.TdotH2 = vars2.TdotH2; retval.BdotH2 = vars2.BdotH2; return retval; @@ -1120,119 +1132,6 @@ struct SBxDFCreationParams Spectrum luminosityContributionHint; }; -// fresnel stuff -namespace impl -{ -template -struct fresnel -{ - using scalar_t = typename scalar_type::type; - - static T conductor(T eta, T etak, scalar_t cosTheta) - { - const scalar_t cosTheta2 = cosTheta * cosTheta; - //const float sinTheta2 = 1.0 - cosTheta2; - - const T etaLen2 = eta * eta + etak * etak; - const T etaCosTwice = eta * cosTheta * 2.0f; - - const T rs_common = etaLen2 + (T)(cosTheta2); - const T rs2 = (rs_common - etaCosTwice) / (rs_common + etaCosTwice); - - const T rp_common = etaLen2 * cosTheta2 + (T)(1.0); - const T rp2 = (rp_common - etaCosTwice) / (rp_common + etaCosTwice); - - return (rs2 + rp2) * 0.5f; - } - - static T dielectric(T orientedEta2, scalar_t absCosTheta) - { - const scalar_t sinTheta2 = 1.0 - absCosTheta * absCosTheta; - - // the max() clamping can handle TIR when orientedEta2<1.0 - const T t0 = nbl::hlsl::sqrt(nbl::hlsl::max((T)(orientedEta2) - sinTheta2, (T)(0.0))); - const T rs = ((T)(absCosTheta) - t0) / ((T)(absCosTheta) + t0); - - const T t2 = orientedEta2 * absCosTheta; - const T rp = (t0 - t2) / (t0 + t2); - - return (rs * rs + rp * rp) * 0.5f; - } -}; -} - -template || is_vector_v) -T fresnelSchlick(T F0, typename scalar_type::type VdotH) -{ - T x = 1.0 - VdotH; - return F0 + (1.0 - F0) * x*x*x*x*x; -} - -template || is_vector_v) -T fresnelConductor(T eta, T etak, typename scalar_type::type cosTheta) -{ - return impl::fresnel::conductor(eta, etak, cosTheta); -} - -template || is_vector_v) -T fresnelDielectric_common(T eta, typename scalar_type::type cosTheta) -{ - return impl::fresnel::dielectric(eta, cosTheta); -} - -template || is_vector_v) -T fresnelDielectricFrontFaceOnly(T eta, typename scalar_type::type cosTheta) -{ - return impl::fresnel::dielectric(eta * eta, cosTheta); -} - -template || is_vector_v) -T fresnelDielectric(T eta, typename scalar_type::type cosTheta) -{ - T orientedEta, rcpOrientedEta; - math::getOrientedEtas(orientedEta, rcpOrientedEta, cosTheta, eta); - return impl::fresnel::dielectric(orientedEta * orientedEta, abs::type>(cosTheta)); -} - -namespace impl -{ -// gets the sum of all R, T R T, T R^3 T, T R^5 T, ... paths -template -struct ThinDielectricInfiniteScatter -{ - using scalar_t = typename scalar_type::type; - - static T __call(T singleInterfaceReflectance) - { - const T doubleInterfaceReflectance = singleInterfaceReflectance * singleInterfaceReflectance; - return nbl::hlsl::mix((singleInterfaceReflectance - doubleInterfaceReflectance) / ((T)(1.0) - doubleInterfaceReflectance) * 2.0f, (T)(1.0), doubleInterfaceReflectance > (T)(0.9999)); - } - - static scalar_t __call(scalar_t singleInterfaceReflectance) // TODO: check redundancy when lerp on line 980 works - { - const scalar_t doubleInterfaceReflectance = singleInterfaceReflectance * singleInterfaceReflectance; - return doubleInterfaceReflectance > 0.9999 ? 1.0 : ((singleInterfaceReflectance - doubleInterfaceReflectance) / (1.0 - doubleInterfaceReflectance) * 2.0); - } -}; -} - -template || is_vector_v) -T thindielectricInfiniteScatter(T singleInterfaceReflectance) -{ - return impl::ThinDielectricInfiniteScatter::__call(singleInterfaceReflectance); -} - -template || is_vector_v) -T diffuseFresnelCorrectionFactor(T n, T n2) -{ - // assert(n*n==n2); - vector::Dimension> TIR = n < (T)1.0; - T invdenum = nbl::hlsl::mix((T)1.0, (T)1.0 / (n2 * n2 * ((T)554.33 - 380.7 * n)), TIR); - T num = n * nbl::hlsl::mix((T)(0.1921156102251088), n * 298.25 - 261.38 * n2 + 138.43, TIR); - num += nbl::hlsl::mix((T)(0.8078843897748912), (T)(-1.67), TIR); - return num * invdenum; -} - } } } diff --git a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl index 5d54c6c261..b499089f5e 100644 --- a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl @@ -5,9 +5,9 @@ #define _NBL_BUILTIN_HLSL_BXDF_FRESNEL_INCLUDED_ #include "nbl/builtin/hlsl/cpp_compat.hlsl" +#include "nbl/builtin/hlsl/concepts.hlsl" #include "nbl/builtin/hlsl/numbers.hlsl" #include "nbl/builtin/hlsl/vector_utils/vector_traits.hlsl" -#include "nbl/builtin/hlsl/spirv_intrinsics/core.hlsl" namespace nbl { @@ -55,26 +55,24 @@ bool getOrientedEtas(NBL_REF_ARG(T) orientedEta, NBL_REF_ARG(T) rcpOrientedEta, return impl::orientedEtas::__call(orientedEta, rcpOrientedEta, NdotI, eta); } -} - -template ::Dimensions == 3) +template::Dimension == 3) T reflect(NBL_CONST_REF_ARG(T) I, NBL_CONST_REF_ARG(T) N, typename vector_traits::scalar_type NdotI) { return N * 2.0f * NdotI - I; } -template ::Dimensions == 3) +template::Dimension == 3) T reflect(NBL_CONST_REF_ARG(T) I, NBL_CONST_REF_ARG(T) N) { typename vector_traits::scalar_type NdotI = nbl::hlsl::dot(N, I); return reflect(I, N, NdotI); } -template::Dimensions == 3) +template::Dimension == 3) struct refract { - using this_t = refract; + using this_t = refract; using scalar_type = typename vector_traits::scalar_type; using vector_type = T; @@ -96,7 +94,7 @@ struct refract this_t retval; retval.I = I; retval.N = N; - T orientedEta; + scalar_type orientedEta; retval.backside = bxdf::getOrientedEtas(orientedEta, retval.rcpOrientedEta, NdotI, eta); retval.NdotI = NdotI; retval.NdotI2 = NdotI * NdotI; @@ -136,19 +134,110 @@ struct refract vector_type doReflectRefract(bool r) { - const T NdotTorR = r ? computeNdotT(backside, NdotI2, rcpOrientedEta2) : NdotI; + const scalar_type NdotTorR = r ? computeNdotT(backside, NdotI2, rcpOrientedEta2) : NdotI; return doReflectRefract(r, I, N, NdotI, NdotTorR, rcpOrientedEta); } vector_type I; vector_type N; bool backside; - T NdotI; - T NdotI2; - T rcpOrientedEta; - T rcpOrientedEta2; + scalar_type NdotI; + scalar_type NdotI2; + scalar_type rcpOrientedEta; + scalar_type rcpOrientedEta2; }; + +template || is_vector_v) +struct fresnel +{ + using scalar_t = typename scalar_type::type; + + static T schlick(NBL_CONST_REF_ARG(T) F0, scalar_t VdotH) + { + T x = 1.0 - VdotH; + return F0 + (1.0 - F0) * x*x*x*x*x; + } + + static T conductor(NBL_CONST_REF_ARG(T) eta, NBL_CONST_REF_ARG(T) etak, scalar_t cosTheta) + { + const scalar_t cosTheta2 = cosTheta * cosTheta; + //const float sinTheta2 = 1.0 - cosTheta2; + + const T etaLen2 = eta * eta + etak * etak; + const T etaCosTwice = eta * cosTheta * 2.0f; + + const T rs_common = etaLen2 + (T)(cosTheta2); + const T rs2 = (rs_common - etaCosTwice) / (rs_common + etaCosTwice); + + const T rp_common = etaLen2 * cosTheta2 + (T)(1.0); + const T rp2 = (rp_common - etaCosTwice) / (rp_common + etaCosTwice); + + return (rs2 + rp2) * 0.5f; + } + + static T dielectric_common(NBL_CONST_REF_ARG(T) orientedEta2, scalar_t absCosTheta) + { + const scalar_t sinTheta2 = 1.0 - absCosTheta * absCosTheta; + + // the max() clamping can handle TIR when orientedEta2<1.0 + const T t0 = nbl::hlsl::sqrt(nbl::hlsl::max((T)(orientedEta2) - sinTheta2, (T)(0.0))); + const T rs = ((T)(absCosTheta) - t0) / ((T)(absCosTheta) + t0); + + const T t2 = orientedEta2 * absCosTheta; + const T rp = (t0 - t2) / (t0 + t2); + + return (rs * rs + rp * rp) * 0.5f; + } + + static T dielectricFrontFaceOnly(NBL_CONST_REF_ARG(T) orientedEta2, scalar_t absCosTheta) + { + return dielectric_common(orientedEta2, absCosTheta); + } + + static T dielectric(NBL_CONST_REF_ARG(T) eta, scalar_t cosTheta) + { + T orientedEta, rcpOrientedEta; + bxdf::getOrientedEtas(orientedEta, rcpOrientedEta, cosTheta, eta); + return dielectric_common(orientedEta * orientedEta, cosTheta); + } +}; + +namespace impl +{ +// gets the sum of all R, T R T, T R^3 T, T R^5 T, ... paths +template +struct ThinDielectricInfiniteScatter +{ + using scalar_t = typename scalar_type::type; + + static T __call(T singleInterfaceReflectance) + { + const T doubleInterfaceReflectance = singleInterfaceReflectance * singleInterfaceReflectance; + return nbl::hlsl::mix((singleInterfaceReflectance - doubleInterfaceReflectance) / ((T)(1.0) - doubleInterfaceReflectance) * 2.0f, (T)(1.0), doubleInterfaceReflectance > (T)(0.9999)); + } +}; +} + +template || is_vector_v) +T thindielectricInfiniteScatter(T singleInterfaceReflectance) +{ + return impl::ThinDielectricInfiniteScatter::__call(singleInterfaceReflectance); +} + +template || is_vector_v) +T diffuseFresnelCorrectionFactor(T n, T n2) +{ + // assert(n*n==n2); + vector::Dimension> TIR = n < (T)1.0; + T invdenum = nbl::hlsl::mix((T)1.0, (T)1.0 / (n2 * n2 * ((T)554.33 - 380.7 * n)), TIR); + T num = n * nbl::hlsl::mix((T)(0.1921156102251088), n * 298.25 - 261.38 * n2 + 138.43, TIR); + num += nbl::hlsl::mix((T)(0.8078843897748912), (T)(-1.67), TIR); + return num * invdenum; +} + +} + } } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index bf534e2f8d..a9e539f620 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -250,12 +250,12 @@ struct SBlinnPhongBxDF scalar_part = __eval_DG_wo_clamps(params, a2); } ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotV); - return fresnelConductor(ior0, ior1, params.VdotH) * microfacet_transform(); + return fresnel::conductor(ior0, ior1, params.VdotH) * microfacet_transform(); } vector3_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) { - if (interaction.NdotV > numeric_limits::min) + if (interaction.isotropic.NdotV > numeric_limits::min) { params_t params = params_t::template create(_sample, interaction, cache); return __eval_wo_clamps(params); @@ -266,7 +266,7 @@ struct SBlinnPhongBxDF vector3_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) { - if (interaction.NdotV > numeric_limits::min) + if (interaction.isotropic.NdotV > numeric_limits::min) { params_t params = params_t::template create(_sample, interaction, cache); return __eval_wo_clamps(params); @@ -292,7 +292,7 @@ struct SBlinnPhongBxDF cache = anisocache_type::create(localV, H); ray_dir_info_type localL; - localL.direction = math::reflect(localV, H, cache.VdotH); + localL.direction = bxdf::reflect(localV, H, cache.iso_cache.VdotH); return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); } @@ -381,7 +381,7 @@ struct SBeckmannBxDF { scalar_type scalar_part = __eval_DG_wo_clamps(params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.uNdotV); - return fresnelConductor(ior0, ior1, params.VdotH) * microfacet_transform(); + return fresnel::conductor(ior0, ior1, params.VdotH) * microfacet_transform(); } else return (spectral_type)0.0; @@ -462,7 +462,7 @@ struct SBeckmannBxDF cache = anisocache_type::create(localV, H); ray_dir_info_type localL; - localL.direction = math::reflect(localV, H, cache.VdotH); + localL.direction = bxdf::reflect(localV, H, cache.iso_cache.VdotH); return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); } @@ -520,7 +520,7 @@ struct SBeckmannBxDF smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(A.x*A.x, params.NdotV2, params.NdotL2, onePlusLambda_V); G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); } - const spectral_type reflectance = fresnelConductor(ior0, ior1, params.VdotH); + const spectral_type reflectance = fresnel::conductor(ior0, ior1, params.VdotH); quo = reflectance * G2_over_G1; } @@ -609,7 +609,7 @@ struct SGGXBxDF { scalar_type scalar_part = __eval_DG_wo_clamps(params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotL); - return fresnelConductor(ior0, ior1, params.VdotH) * microfacet_transform(); + return fresnel::conductor(ior0, ior1, params.VdotH) * microfacet_transform(); } else return (spectral_type)0.0; @@ -644,7 +644,7 @@ struct SGGXBxDF cache = anisocache_type::create(localV, H); ray_dir_info_type localL; - localL.direction = math::reflect(localV, H, cache.VdotH); + localL.direction = bxdf::reflect(localV, H, cache.iso_cache.VdotH); return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); } @@ -700,7 +700,7 @@ struct SGGXBxDF smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.uNdotV, params.NdotV2, params.uNdotL, params.NdotL2); G2_over_G1 = ggx_smith.G2_over_G1(smithparams); } - const spectral_type reflectance = fresnelConductor(ior0, ior1, params.VdotH); + const spectral_type reflectance = fresnel::conductor(ior0, ior1, params.VdotH); quo = reflectance * G2_over_G1; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index 17682a7384..71768f5622 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -131,32 +131,33 @@ struct SSmoothDielectricBxDF sample_type __generate_wo_clamps(vector3_type V, vector3_type T, vector3_type B, vector3_type N, bool backside, scalar_type NdotV, scalar_type absNdotV, scalar_type NdotV2, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(bool) transmitted) { - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, absNdotV); + const scalar_type reflectance = fresnel::dielectric_common(orientedEta2, absNdotV); scalar_type rcpChoiceProb; transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); ray_dir_info_type L; - L.direction = math::reflectRefract(transmitted, V, N, backside, NdotV, NdotV2, rcpOrientedEta, rcpOrientedEta2); + refract r = refract::create(V, N, backside, NdotV, NdotV2, rcpOrientedEta, rcpOrientedEta2); + L.direction = r.doReflectRefract(transmitted); return sample_type::create(L, nbl::hlsl::dot(V, L.direction), T, B, N); } sample_type generate_wo_clamps(anisotropic_type interaction, NBL_REF_ARG(vector) u) { scalar_type orientedEta, rcpOrientedEta; - const bool backside = math::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.NdotV, eta); + const bool backside = bxdf::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.isotropic.NdotV, eta); bool dummy; - return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, backside, interaction.NdotV, - interaction.NdotV, interaction.NdotV*interaction.NdotV, u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, dummy); + return __generate_wo_clamps(interaction.isotropic.V.direction, interaction.T, interaction.B, interaction.isotropic.N, backside, interaction.isotropic.NdotV, + interaction.isotropic.NdotV, interaction.isotropic.NdotV*interaction.isotropic.NdotV, u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, dummy); } sample_type generate(anisotropic_type interaction, NBL_REF_ARG(vector) u) { scalar_type orientedEta, rcpOrientedEta; - const bool backside = math::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.NdotV, eta); + const bool backside = bxdf::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.isotropic.NdotV, eta); bool dummy; - return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, backside, interaction.NdotV, - nbl::hlsl::abs(interaction.NdotV), interaction.NdotV*interaction.NdotV, u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, dummy); + return __generate_wo_clamps(interaction.isotropic.V.direction, interaction.T, interaction.B, interaction.isotropic.N, backside, interaction.isotropic.NdotV, + nbl::hlsl::abs(interaction.isotropic.NdotV), interaction.isotropic.NdotV*interaction.isotropic.NdotV, u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, dummy); } // eval and pdf return 0 because smooth dielectric/conductor BxDFs are dirac delta distributions, model perfectly specular objects that scatter light to only one outgoing direction @@ -170,7 +171,7 @@ struct SSmoothDielectricBxDF const bool transmitted = isTransmissionPath(params.uNdotV, params.uNdotL); scalar_type dummy, rcpOrientedEta; - const bool backside = math::getOrientedEtas(dummy, rcpOrientedEta, params.NdotV, eta); + const bool backside = bxdf::getOrientedEtas(dummy, rcpOrientedEta, params.NdotV, eta); const scalar_type _pdf = numeric_limits::infinity; scalar_type quo = transmitted ? rcpOrientedEta : 1.0; @@ -217,7 +218,7 @@ struct SSmoothDielectricBxDF sample_type __generate_wo_clamps(vector3_type V, vector3_type T, vector3_type B, vector3_type N, scalar_type NdotV, scalar_type absNdotV, NBL_REF_ARG(vector3_type) u, spectral_type eta2, spectral_type luminosityContributionHint, NBL_REF_ARG(spectral_type) remainderMetadata) { // we will only ever intersect from the outside - const spectral_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2,absNdotV)); + const spectral_type reflectance = thindielectricInfiniteScatter(fresnel::dielectric_common(eta2,absNdotV)); // we are only allowed one choice for the entire ray, so make the probability a weighted sum const scalar_type reflectionProb = nbl::hlsl::dot(reflectance, luminosityContributionHint); @@ -234,13 +235,13 @@ struct SSmoothDielectricBxDF sample_type generate_wo_clamps(anisotropic_type interaction, NBL_REF_ARG(vector) u) { vector3_type dummy; - return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, interaction.NdotV, interaction.NdotV, u, eta2, luminosityContributionHint, dummy); + return __generate_wo_clamps(interaction.isotropic.V.direction, interaction.T, interaction.B, interaction.isotropic.N, interaction.isotropic.NdotV, interaction.isotropic.NdotV, u, eta2, luminosityContributionHint, dummy); } sample_type generate(anisotropic_type interaction, NBL_REF_ARG(vector) u) { vector3_type dummy; - return __generate_wo_clamps(interaction.V.direction, interaction.T, interaction.B, interaction.N, interaction.NdotV, nbl::hlsl::abs(interaction.NdotV), u, eta2, luminosityContributionHint, dummy); + return __generate_wo_clamps(interaction.isotropic.V.direction, interaction.T, interaction.B, interaction.isotropic.N, interaction.isotropic.NdotV, nbl::hlsl::abs(interaction.isotropic.NdotV), u, eta2, luminosityContributionHint, dummy); } scalar_type pdf(params_t params) @@ -251,7 +252,7 @@ struct SSmoothDielectricBxDF quotient_pdf_type quotient_and_pdf(params_t params) // isotropic { const bool transmitted = isTransmissionPath(params.uNdotV, params.uNdotL); - const spectral_type reflectance = thindielectricInfiniteScatter(fresnelDielectric_common(eta2, params.NdotV)); + const spectral_type reflectance = thindielectricInfiniteScatter(fresnel::dielectric_common(eta2, params.NdotV)); const spectral_type sampleValue = transmitted ? ((spectral_type)(1.0) - reflectance) : reflectance; const scalar_type sampleProb = nbl::hlsl::dot(sampleValue,luminosityContributionHint); @@ -302,7 +303,7 @@ struct SBeckmannDielectricBxDF spectral_type eval(params_t params) { scalar_type orientedEta, dummy; - const bool backside = math::getOrientedEtas(orientedEta, dummy, params.VdotH, eta); + const bool backside = bxdf::getOrientedEtas(orientedEta, dummy, params.VdotH, eta); const scalar_type orientedEta2 = orientedEta * orientedEta; const scalar_type VdotHLdotH = params.VdotH * params.LdotH; @@ -318,23 +319,23 @@ struct SBeckmannDielectricBxDF ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,params.NdotV,transmitted,params.VdotH,params.LdotH,VdotHLdotH,orientedEta); - return (spectral_type)fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(params.VdotH)) * microfacet_transform(); + return (spectral_type)fresnel::dielectric_common(orientedEta2, nbl::hlsl::abs(params.VdotH)) * microfacet_transform(); } sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix3x3_type m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) { const scalar_type localVdotH = nbl::hlsl::dot(localV,H); - const scalar_type reflectance = fresnelDielectric_common(orientedEta2,nbl::hlsl::abs(localVdotH)); + const scalar_type reflectance = fresnel::dielectric_common(orientedEta2,nbl::hlsl::abs(localVdotH)); scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); cache = anisocache_type::create(localV, H); - const scalar_type VdotH = cache.VdotH; - cache.LdotH = transmitted ? math::reflectRefract_computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; + const scalar_type VdotH = cache.iso_cache.VdotH; + cache.iso_cache.LdotH = transmitted ? refract::computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; ray_dir_info_type localL; - localL.direction = math::reflectRefract_impl(transmitted, localV, H, VdotH, cache.LdotH, rcpOrientedEta); + localL.direction = refract::doReflectRefract(transmitted, localV, H, VdotH, cache.iso_cache.LdotH, rcpOrientedEta); return sample_type::createFromTangentSpace(localV, localL, m); } @@ -344,7 +345,7 @@ struct SBeckmannDielectricBxDF const vector3_type localV = interaction.getTangentSpaceV(); scalar_type orientedEta, rcpOrientedEta; - const bool backside = math::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.NdotV, eta); + const bool backside = bxdf::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.isotropic.NdotV, eta); const vector3_type upperHemisphereV = backside ? -localV : localV; @@ -364,13 +365,13 @@ struct SBeckmannDielectricBxDF scalar_type pdf(params_t params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { scalar_type orientedEta, dummy; - const bool backside = math::getOrientedEtas(orientedEta, dummy, params.VdotH, eta); + const bool backside = bxdf::getOrientedEtas(orientedEta, dummy, params.VdotH, eta); const scalar_type orientedEta2 = orientedEta * orientedEta; const scalar_type VdotHLdotH = params.VdotH * params.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(params.VdotH)); + const scalar_type reflectance = fresnel::dielectric_common(orientedEta2, nbl::hlsl::abs(params.VdotH)); scalar_type ndf, lambda; if (params.is_aniso) @@ -469,7 +470,7 @@ struct SGGXDielectricBxDF spectral_type eval(params_t params) { scalar_type orientedEta, dummy; - const bool backside = math::getOrientedEtas(orientedEta, dummy, params.VdotH, eta); + const bool backside = bxdf::getOrientedEtas(orientedEta, dummy, params.VdotH, eta); const scalar_type orientedEta2 = orientedEta * orientedEta; const scalar_type VdotHLdotH = params.VdotH * params.LdotH; @@ -491,23 +492,23 @@ struct SGGXDielectricBxDF ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,params.NdotL,transmitted,params.VdotH,params.LdotH,VdotHLdotH,orientedEta); - return (spectral_type)fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(params.VdotH)) * microfacet_transform(); + return (spectral_type)fresnel::dielectric_common(orientedEta2, nbl::hlsl::abs(params.VdotH)) * microfacet_transform(); } sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix3x3_type m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) { const scalar_type localVdotH = nbl::hlsl::dot(localV,H); - const scalar_type reflectance = fresnelDielectric_common(orientedEta2,nbl::hlsl::abs(localVdotH)); + const scalar_type reflectance = fresnel::dielectric_common(orientedEta2,nbl::hlsl::abs(localVdotH)); scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); cache = anisocache_type::create(localV, H); - const scalar_type VdotH = cache.VdotH; - cache.LdotH = transmitted ? math::reflectRefract_computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; + const scalar_type VdotH = cache.iso_cache.VdotH; + cache.iso_cache.LdotH = transmitted ? refract::computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; ray_dir_info_type localL; - localL.direction = math::reflectRefract_impl(transmitted, localV, H, VdotH, cache.LdotH, rcpOrientedEta); + localL.direction = refract::doReflectRefract(transmitted, localV, H, VdotH, cache.iso_cache.LdotH, rcpOrientedEta); return sample_type::createFromTangentSpace(localV, localL, m); } @@ -517,7 +518,7 @@ struct SGGXDielectricBxDF const vector3_type localV = interaction.getTangentSpaceV(); scalar_type orientedEta, rcpOrientedEta; - const bool backside = math::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.NdotV, eta); + const bool backside = bxdf::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.isotropic.NdotV, eta); const vector3_type upperHemisphereV = backside ? -localV : localV; @@ -537,13 +538,13 @@ struct SGGXDielectricBxDF scalar_type pdf(params_t params) { scalar_type orientedEta, dummy; - const bool backside = math::getOrientedEtas(orientedEta, dummy, params.VdotH, eta); + const bool backside = bxdf::getOrientedEtas(orientedEta, dummy, params.VdotH, eta); const scalar_type orientedEta2 = orientedEta * orientedEta; const scalar_type VdotHLdotH = params.VdotH * params.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnelDielectric_common(orientedEta2, nbl::hlsl::abs(params.VdotH)); + const scalar_type reflectance = fresnel::dielectric_common(orientedEta2, nbl::hlsl::abs(params.VdotH)); scalar_type ndf, devsh_v; if (params.is_aniso) diff --git a/include/nbl/builtin/hlsl/type_traits.hlsl b/include/nbl/builtin/hlsl/type_traits.hlsl index e28ad571bc..85f87d92a6 100644 --- a/include/nbl/builtin/hlsl/type_traits.hlsl +++ b/include/nbl/builtin/hlsl/type_traits.hlsl @@ -582,6 +582,22 @@ template using conditional_t = typename conditional::type; +// Template variables +template +NBL_CONSTEXPR bool is_same_v = is_same::value; +template +NBL_CONSTEXPR bool is_unsigned_v = is_unsigned::value; +template +NBL_CONSTEXPR bool is_integral_v = is_integral::value; +template +NBL_CONSTEXPR bool is_floating_point_v = is_floating_point::value; +template +NBL_CONSTEXPR bool is_signed_v = is_signed::value; +template +NBL_CONSTEXPR bool is_scalar_v = is_scalar::value; +template +NBL_CONSTEXPR uint32_t alignment_of_v = alignment_of::value; + // Overlapping definitions template using make_void_t = typename make_void::type; @@ -659,20 +675,6 @@ struct extent, I> : integral_constant: // Template Variables -template -NBL_CONSTEXPR bool is_same_v = is_same::value; -template -NBL_CONSTEXPR bool is_unsigned_v = is_unsigned::value; -template -NBL_CONSTEXPR bool is_integral_v = is_integral::value; -template -NBL_CONSTEXPR bool is_floating_point_v = is_floating_point::value; -template -NBL_CONSTEXPR bool is_signed_v = is_signed::value; -template -NBL_CONSTEXPR bool is_scalar_v = is_scalar::value; -template -NBL_CONSTEXPR uint32_t alignment_of_v = alignment_of::value; template NBL_CONSTEXPR uint64_t extent_v = extent::value; diff --git a/src/nbl/builtin/CMakeLists.txt b/src/nbl/builtin/CMakeLists.txt index f6fcbc9d24..ea74fb029f 100644 --- a/src/nbl/builtin/CMakeLists.txt +++ b/src/nbl/builtin/CMakeLists.txt @@ -324,6 +324,7 @@ LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/sort/common.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/sort/counting.hlsl") #bxdf LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/common.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/fresnel.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/geom_smith.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/ndf.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/reflection.hlsl") From 705c4e9b7ec1be1ef5b988b23a445bef582f367e Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 28 Feb 2025 16:37:56 +0700 Subject: [PATCH 075/188] fixes to match new bxdf params --- examples_tests | 2 +- .../nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl | 2 +- include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl | 8 +- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 78 +++++++++++++--- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 90 ++++++++++++++++--- include/nbl/builtin/hlsl/limits.hlsl | 2 +- .../hlsl/sampling/concentric_mapping.hlsl | 10 ++- 7 files changed, 154 insertions(+), 38 deletions(-) diff --git a/examples_tests b/examples_tests index f3144f14c1..a1334527a4 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit f3144f14c107d86667a23f64b2686a71b20ee473 +Subproject commit a1334527a4ac822a3220f557084672bb7c4ec86e diff --git a/include/nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl b/include/nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl index e63cf0113e..78b23830bc 100644 --- a/include/nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl @@ -101,4 +101,4 @@ struct bxdf_traits > } } -#endif \ No newline at end of file +#endif diff --git a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl index 61aa10399c..04f933dcc5 100644 --- a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl @@ -27,7 +27,7 @@ template typename NDF::scalar_type VNDF_pdf_wo_clamps(typename NDF::scalar_type ndf, typename NDF::scalar_type lambda_V, typename NDF::scalar_type absNdotV, bool transmitted, typename NDF::scalar_type VdotH, typename NDF::scalar_type LdotH, typename NDF::scalar_type VdotHLdotH, typename NDF::scalar_type orientedEta, typename NDF::scalar_type reflectance, NBL_REF_ARG(typename NDF::scalar_type) onePlusLambda_V) { onePlusLambda_V = 1.0 + lambda_V; - ndf::microfacet_to_light_measure_transform transform + ndf::microfacet_to_light_measure_transform transform = ndf::microfacet_to_light_measure_transform::create((transmitted ? (1.0 - reflectance) : reflectance) * ndf / onePlusLambda_V, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); return transform(); } @@ -159,7 +159,7 @@ struct Beckmann scalar_type C2(scalar_type NdotX2, scalar_type a2) { - return NdotX2 / (a2 * (1.0 - NdotX2)); + return NdotX2 / (a2 * (1.0 - NdotX2)); } scalar_type C2(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2, scalar_type ax2, scalar_type ay2) @@ -236,12 +236,12 @@ struct GGX scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type NdotX2, scalar_type a2, scalar_type one_minus_a2) { - return 1.0 / (NdotX + ggx_devsh_part(NdotX2,a2,one_minus_a2)); + return 1.0 / (NdotX + devsh_part(NdotX2,a2,one_minus_a2)); } scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2, scalar_type ax2, scalar_type ay2) { - return 1.0 / (NdotX + ggx_devsh_part(TdotX2, BdotX2, NdotX2, ax2, ay2)); + return 1.0 / (NdotX + devsh_part(TdotX2, BdotX2, NdotX2, ax2, ay2)); } scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type devsh_part) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index a9e539f620..05bbf0bf53 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -18,13 +18,13 @@ namespace reflection { // still need these? -template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) LightSample cos_generate(NBL_CONST_REF_ARG(Iso) interaction) { return LightSample(interaction.V.reflect(interaction.N,interaction.NdotV),interaction.NdotV,interaction.N); } -template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) LightSample cos_generate(NBL_CONST_REF_ARG(Aniso) interaction) { @@ -59,6 +59,16 @@ struct SLambertianBxDF return retval; } + static this_t create(SBxDFCreationParams params) + { + return create(); + } + + void init(SBxDFCreationParams params) + { + // do nothing + } + scalar_type __eval_pi_factored_out(scalar_type maxNdotL) { return maxNdotL; @@ -117,6 +127,16 @@ struct SOrenNayarBxDF return retval; } + static this_t create(SBxDFCreationParams params) + { + return create(params.A.x); + } + + void init(SBxDFCreationParams params) + { + A = params.A.x; + } + scalar_type __rec_pi_factored_out_wo_clamps(scalar_type VdotL, scalar_type maxNdotL, scalar_type maxNdotV) { scalar_type A2 = A * 0.5; @@ -212,7 +232,7 @@ struct SBlinnPhongBxDF ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(params.NdotH, 1.0 / (1.0 - params.NdotH2), params.TdotH2, params.BdotH2, n.x, n.y); ndf::BlinnPhong blinn_phong; scalar_type DG = blinn_phong(ndfparams); - if (any>(a2 > (vector2_type)numeric_limits::min)) + if (any >(a2 > (vector2_type)numeric_limits::min)) { smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(a2.x, a2.y, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, 0); smith::Beckmann beckmann; @@ -225,7 +245,7 @@ struct SBlinnPhongBxDF ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(n, params.NdotH, params.NdotH2); ndf::BlinnPhong blinn_phong; scalar_type NG = blinn_phong(ndfparams); - if (any>(a2 > (vector2_type)numeric_limits::min)) + if (any >(a2 > (vector2_type)numeric_limits::min)) { smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2.x, params.NdotV2, params.NdotL2, 0); smith::Beckmann beckmann; @@ -342,6 +362,21 @@ struct SBeckmannBxDF return retval; } + static this_t create(SBxDFCreationParams params) + { + if (params.is_aniso) + return create(params.A.x, params.A.y, params.ior0, params.ior1); + else + return create(params.A.x, params.ior0, params.ior1); + } + + void init(SBxDFCreationParams params) + { + A = params.A; + ior0 = params.ior0; + ior1 = params.ior1; + } + scalar_type __eval_DG_wo_clamps(params_t params) { if (params.is_aniso) @@ -351,7 +386,7 @@ struct SBeckmannBxDF ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); ndf::Beckmann beckmann_ndf; scalar_type NG = beckmann_ndf(ndfparams); - if (any>(A > (vector2_type)numeric_limits::min)) + if (any >(A > (vector2_type)numeric_limits::min)) { smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, 0); smith::Beckmann beckmann_smith; @@ -406,14 +441,14 @@ struct SBeckmannBxDF scalar_type sinTheta = sqrt(1.0 - cosTheta * cosTheta); scalar_type tanTheta = sinTheta / cosTheta; scalar_type cotTheta = 1.0 / tanTheta; - + scalar_type a = -1.0; scalar_type c = erf(cosTheta); scalar_type sample_x = max(u.x, 1.0e-6); scalar_type theta = acos(cosTheta); scalar_type fit = 1.0 + theta * (-0.876 + theta * (0.4265 - 0.0594*theta)); scalar_type b = c - (1.0 + c) * pow(1.0-sample_x, fit); - + scalar_type normalization = 1.0 / (1.0 + c + numbers::inv_sqrtpi * tanTheta * exp(-cosTheta*cosTheta)); const int ITER_THRESHOLD = 10; @@ -440,7 +475,7 @@ struct SBeckmannBxDF slope.x = erfInv(b); slope.y = erfInv(2.0 * max(u.y, 1.0e-6) - 1.0); } - + scalar_type sinTheta = sqrt(1.0 - V.z*V.z); scalar_type cosPhi = sinTheta==0.0 ? 1.0 : clamp(V.x/sinTheta, -1.0, 1.0); scalar_type sinPhi = sinTheta==0.0 ? 0.0 : clamp(V.y/sinTheta, -1.0, 1.0); @@ -459,7 +494,7 @@ struct SBeckmannBxDF { const vector3_type localV = interaction.getTangentSpaceV(); const vector3_type H = __generate(localV, u); - + cache = anisocache_type::create(localV, H); ray_dir_info_type localL; localL.direction = bxdf::reflect(localV, H, cache.iso_cache.VdotH); @@ -523,7 +558,7 @@ struct SBeckmannBxDF const spectral_type reflectance = fresnel::conductor(ior0, ior1, params.VdotH); quo = reflectance * G2_over_G1; } - + return quotient_pdf_type::create(quo, _pdf); } @@ -570,6 +605,21 @@ struct SGGXBxDF return retval; } + static this_t create(SBxDFCreationParams params) + { + if (params.is_aniso) + return create(params.A.x, params.A.y, params.ior0, params.ior1); + else + return create(params.A.x, params.ior0, params.ior1); + } + + void init(SBxDFCreationParams params) + { + A = params.A; + ior0 = params.ior0; + ior1 = params.ior1; + } + scalar_type __eval_DG_wo_clamps(params_t params) { if (params.is_aniso) @@ -579,7 +629,7 @@ struct SGGXBxDF ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); ndf::GGX ggx_ndf; scalar_type NG = ggx_ndf(ndfparams); - if (any>(A > (vector2_type)numeric_limits::min)) + if (any >(A > (vector2_type)numeric_limits::min)) { smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2); smith::GGX ggx_smith; @@ -629,7 +679,7 @@ struct SGGXBxDF scalar_type t2 = r * sin(phi); scalar_type s = 0.5 * (1.0 + V.z); t2 = (1.0 - s)*sqrt(1.0 - t1*t1) + s*t2; - + //reprojection onto hemisphere //TODO try it wothout the max(), not sure if -t1*t1-t2*t2>-1.0 vector3_type H = t1*T1 + t2*T2 + sqrt(max(0.0, 1.0-t1*t1-t2*t2))*V; @@ -641,7 +691,7 @@ struct SGGXBxDF { const vector3_type localV = interaction.getTangentSpaceV(); const vector3_type H = __generate(localV, u); - + cache = anisocache_type::create(localV, H); ray_dir_info_type localL; localL.direction = bxdf::reflect(localV, H, cache.iso_cache.VdotH); @@ -703,7 +753,7 @@ struct SGGXBxDF const spectral_type reflectance = fresnel::conductor(ior0, ior1, params.VdotH); quo = reflectance * G2_over_G1; } - + return quotient_pdf_type::create(quo, _pdf); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index 71768f5622..fec527cd39 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -17,13 +17,13 @@ namespace bxdf namespace transmission { -template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) LightSample cos_generate(NBL_CONST_REF_ARG(Iso) interaction) { return LightSample(interaction.V.transmit(),-1.f,interaction.N); } -template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) LightSample cos_generate(NBL_CONST_REF_ARG(Aniso) interaction) { @@ -63,6 +63,16 @@ struct SLambertianBxDF return retval; } + static this_t create(SBxDFCreationParams params) + { + return create(); + } + + void init(SBxDFCreationParams params) + { + // do nothing + } + scalar_type __eval_pi_factored_out(scalar_type absNdotL) { return absNdotL; @@ -100,8 +110,11 @@ struct SLambertianBxDF // microfacet bxdfs -template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) -struct SSmoothDielectricBxDF +template // NBL_FUNC_REQUIRES(Sample && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) // dxc won't let me put this in +struct SSmoothDielectricBxDF; + +template +struct SSmoothDielectricBxDF { using this_t = SSmoothDielectricBxDF; using scalar_type = typename LightSample::scalar_type; @@ -124,6 +137,16 @@ struct SSmoothDielectricBxDF return retval; } + static this_t create(SBxDFCreationParams params) + { + return create(params.eta); + } + + void init(SBxDFCreationParams params) + { + eta = params.eta; + } + spectral_type eval(params_t params) { return (spectral_type)0; @@ -169,7 +192,7 @@ struct SSmoothDielectricBxDF quotient_pdf_type quotient_and_pdf(params_t params) { const bool transmitted = isTransmissionPath(params.uNdotV, params.uNdotL); - + scalar_type dummy, rcpOrientedEta; const bool backside = bxdf::getOrientedEtas(dummy, rcpOrientedEta, params.NdotV, eta); @@ -181,7 +204,7 @@ struct SSmoothDielectricBxDF scalar_type eta; }; -template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) +template struct SSmoothDielectricBxDF { using this_t = SSmoothDielectricBxDF; @@ -206,13 +229,24 @@ struct SSmoothDielectricBxDF return retval; } + static this_t create(SBxDFCreationParams params) + { + return create(params.eta2, params.luminosityContributionHint); + } + + void init(SBxDFCreationParams params) + { + eta2 = params.eta2; + luminosityContributionHint = params.luminosityContributionHint; + } + spectral_type eval(params_t params) { return (spectral_type)0; } // usually `luminosityContributionHint` would be the Rec.709 luma coefficients (the Y row of the RGB to CIE XYZ matrix) - // its basically a set of weights that determine + // its basically a set of weights that determine // assert(1.0==luminosityContributionHint.r+luminosityContributionHint.g+luminosityContributionHint.b); // `remainderMetadata` is a variable which the generator function returns byproducts of sample generation that would otherwise have to be redundantly calculated `quotient_and_pdf` sample_type __generate_wo_clamps(vector3_type V, vector3_type T, vector3_type B, vector3_type N, scalar_type NdotV, scalar_type absNdotV, NBL_REF_ARG(vector3_type) u, spectral_type eta2, spectral_type luminosityContributionHint, NBL_REF_ARG(spectral_type) remainderMetadata) @@ -226,7 +260,7 @@ struct SSmoothDielectricBxDF scalar_type rcpChoiceProb; const bool transmitted = math::partitionRandVariable(reflectionProb, u.z, rcpChoiceProb); remainderMetadata = (transmitted ? ((spectral_type)(1.0) - reflectance) : reflectance) * rcpChoiceProb; - + ray_dir_info_type L; L.direction = (transmitted ? (vector3_type)(0.0) : N * 2.0f * NdotV) - V; return sample_type::create(L, nbl::hlsl::dot(V, L.direction), T, B, N); @@ -300,12 +334,26 @@ struct SBeckmannDielectricBxDF return retval; } + static this_t create(SBxDFCreationParams params) + { + if (params.is_aniso) + return create(params.eta, params.A.x, params.A.y); + else + return create(params.eta, params.A.x); + } + + void init(SBxDFCreationParams params) + { + A = params.A; + eta = params.eta; + } + spectral_type eval(params_t params) { scalar_type orientedEta, dummy; const bool backside = bxdf::getOrientedEtas(orientedEta, dummy, params.VdotH, eta); const scalar_type orientedEta2 = orientedEta * orientedEta; - + const scalar_type VdotHLdotH = params.VdotH * params.LdotH; const bool transmitted = VdotHLdotH < 0.0; @@ -329,7 +377,7 @@ struct SBeckmannDielectricBxDF scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); - + cache = anisocache_type::create(localV, H); const scalar_type VdotH = cache.iso_cache.VdotH; @@ -396,7 +444,7 @@ struct SBeckmannDielectricBxDF smith::Beckmann beckmann_smith; lambda = beckmann_smith.Lambda(params.NdotV2, a2); } - + return smith::VNDF_pdf_wo_clamps >(ndf,lambda,params.NdotV,transmitted,params.VdotH,params.LdotH,VdotHLdotH,orientedEta,reflectance,onePlusLambda_V); } @@ -467,12 +515,26 @@ struct SGGXDielectricBxDF return retval; } + static this_t create(SBxDFCreationParams params) + { + if (params.is_aniso) + return create(params.eta, params.A.x, params.A.y); + else + return create(params.eta, params.A.x); + } + + void init(SBxDFCreationParams params) + { + A = params.A; + eta = params.eta; + } + spectral_type eval(params_t params) { scalar_type orientedEta, dummy; const bool backside = bxdf::getOrientedEtas(orientedEta, dummy, params.VdotH, eta); const scalar_type orientedEta2 = orientedEta * orientedEta; - + const scalar_type VdotHLdotH = params.VdotH * params.LdotH; const bool transmitted = VdotHLdotH < 0.0; @@ -502,7 +564,7 @@ struct SGGXDielectricBxDF scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); - + cache = anisocache_type::create(localV, H); const scalar_type VdotH = cache.iso_cache.VdotH; @@ -579,7 +641,7 @@ struct SGGXDielectricBxDF { const scalar_type ax2 = A.x*A.x; const scalar_type ay2 = A.y*A.y; - + scalar_type _pdf = pdf(params); smith::GGX ggx_smith; diff --git a/include/nbl/builtin/hlsl/limits.hlsl b/include/nbl/builtin/hlsl/limits.hlsl index 146957dc3e..2cb175a5fd 100644 --- a/include/nbl/builtin/hlsl/limits.hlsl +++ b/include/nbl/builtin/hlsl/limits.hlsl @@ -129,7 +129,7 @@ struct num_base : type_identity NBL_CONSTEXPR_STATIC_INLINE int32_t float_max_decimal_exponent = 4*S16 + 30*S32 + 232*S64; NBL_CONSTEXPR_STATIC_INLINE int32_t float_exponent_bits = 8 * size - 1 - (float_digits-1); - NBL_CONSTEXPR_STATIC_INLINE int32_t float_max_exponent = 1 << (float_exponent_bits-1); + NBL_CONSTEXPR_STATIC_INLINE int32_t float_max_exponent = int32_t(1) << (float_exponent_bits-1); NBL_CONSTEXPR_STATIC_INLINE int32_t float_min_exponent = 3 - float_max_exponent; NBL_CONSTEXPR_STATIC_INLINE bool is_bool = is_same::value; diff --git a/include/nbl/builtin/hlsl/sampling/concentric_mapping.hlsl b/include/nbl/builtin/hlsl/sampling/concentric_mapping.hlsl index 2b06581740..e884a4ecc6 100644 --- a/include/nbl/builtin/hlsl/sampling/concentric_mapping.hlsl +++ b/include/nbl/builtin/hlsl/sampling/concentric_mapping.hlsl @@ -14,9 +14,13 @@ vector concentricMapping(vector _u) { //map [0;1]^2 to [-1;1]^2 vector u = 2.0f * _u - 1.0f; - + vector p; + #ifdef __HLSL_VERSION + if (nbl::hlsl::all >(u == (vector)(0.0))) + #else if (u == (vector)(0.0)) + #endif p = (vector)(0.0); else { @@ -29,7 +33,7 @@ vector concentricMapping(vector _u) r = u.y; theta = 0.5 * numbers::pi - 0.25 * numbers::pi * (u.x / u.y); } - + p = r * vector(cos(theta), sin(theta)); } @@ -39,4 +43,4 @@ vector concentricMapping(vector _u) } } -#endif \ No newline at end of file +#endif From 6fcccfebbe23cf67988b20ba1e0299024af88962 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 3 Mar 2025 11:18:28 +0700 Subject: [PATCH 076/188] fix any/all bugs, typos --- examples_tests | 2 +- include/nbl/builtin/hlsl/bxdf/fresnel.hlsl | 2 +- include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl | 4 ++-- include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples_tests b/examples_tests index 800534f62a..98bd4e4345 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 800534f62a80f34c2896b2c48c2faa439ddc7724 +Subproject commit 98bd4e4345c4fc882a536e5bad18bba062510caa diff --git a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl index 3e3a75b138..a7f77dd4ac 100644 --- a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl @@ -62,7 +62,7 @@ T reflect(NBL_CONST_REF_ARG(T) I, NBL_CONST_REF_ARG(T) N, typename vector_traits return N * 2.0f * NdotI - I; } -template::Dimensions == 3) +template::Dimension == 3) struct refract { using this_t = refract; diff --git a/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl b/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl index 1d43d9b14a..f5d4ddd140 100644 --- a/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl +++ b/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl @@ -139,8 +139,8 @@ template AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(length_helper, length, template AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(normalize_helper, normalize, (T), (T), T) template AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(rsqrt_helper, inverseSqrt, (T), (T), T) template AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(fract_helper, fract, (T), (T), T) -template AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(all_helper, any, (T), (T), T) -template AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(any_helper, any, (T), (T), T) +template AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(all_helper, any, (T), (T), bool) +template AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(any_helper, any, (T), (T), bool) template AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(sign_helper, fSign, (T), (T), T) template AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(sign_helper, sSign, (T), (T), T) template AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(radians_helper, radians, (T), (T), T) diff --git a/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl b/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl index 3ca4c5c37c..8d7fbc0830 100644 --- a/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl +++ b/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl @@ -260,11 +260,11 @@ enable_if_t, Integral> bitCount(Integral mat); template [[vk::ext_instruction(spv::OpAll)]] -enable_if_t && is_same_v::scalar_type, bool>, BooleanVector> all(BooleanVector vec); +enable_if_t && is_same_v::scalar_type, bool>, bool> all(BooleanVector vec); template [[vk::ext_instruction(spv::OpAny)]] -enable_if_t&& is_same_v::scalar_type, bool>, BooleanVector> any(BooleanVector vec); +enable_if_t&& is_same_v::scalar_type, bool>, bool> any(BooleanVector vec); } From d31a92b6531830f95ebe686f3d64b8e50288dec5 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 4 Mar 2025 16:59:35 +0700 Subject: [PATCH 077/188] removed condNegate, use flipSign --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 0e3ee5bdd0..1ddff69d72 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -8,6 +8,7 @@ #include "nbl/builtin/hlsl/numbers.hlsl" #include "nbl/builtin/hlsl/type_traits.hlsl" #include "nbl/builtin/hlsl/concepts.hlsl" +#include "nbl/builtin/hlsl/ieee754.hlsl" #include "nbl/builtin/hlsl/tgmath.hlsl" #include "nbl/builtin/hlsl/math/functions.hlsl" #include "nbl/builtin/hlsl/bxdf/fresnel.hlsl" @@ -18,16 +19,6 @@ namespace nbl namespace hlsl { -// TODO: move into ieee754 namespace hlsl -namespace ieee754 -{ - template) - T condNegate(T a, bool flip) - { - return flip ? (-a) : a; - } -} - namespace bxdf { @@ -37,7 +28,7 @@ T computeUnnormalizedMicrofacetNormal(bool _refract, vector V, vector { const T etaFactor = (_refract ? orientedEta : 1.0); const vector tmpH = V + L * etaFactor; - return ieee754::condNegate(tmpH, _refract); + return ieee754::flipSign(tmpH, _refract); } // returns normalized vector, but NaN when result is length 0 From dc9db3efecf2fb9220f80f88adabf8d0580629f6 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 5 Mar 2025 14:25:18 +0700 Subject: [PATCH 078/188] added concept macro for checking type alias --- examples_tests | 2 +- include/nbl/builtin/hlsl/bxdf/common.hlsl | 42 ++++++++++++++------ include/nbl/builtin/hlsl/concepts.hlsl | 7 +++- include/nbl/builtin/hlsl/math/functions.hlsl | 2 +- 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/examples_tests b/examples_tests index 98bd4e4345..631f7f1da0 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 98bd4e4345c4fc882a536e5bad18bba062510caa +Subproject commit 631f7f1da020e1db77b0ef4a788eff2afd069439 diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 1ddff69d72..56168959a4 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -75,7 +75,9 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.reflect(N, dirDotN)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.refract(N, dirDotN)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::transform(m, rdirinfo)), ::nbl::hlsl::is_same_v, T)) -) && is_scalar_v && is_vector_v; + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(is_scalar_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(is_vector_v, typename T::vector3_type)) +); #undef m #undef dirDotN #undef N @@ -157,7 +159,8 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.NdotV), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.NdotV2), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(normV,normN)), ::nbl::hlsl::is_same_v, T)) -) && ray_dir_info::Basic; + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(ray_dir_info::Basic, typename T::ray_dir_info_type)) +); #undef normN #undef normV #undef iso @@ -212,7 +215,9 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getTangentSpaceV()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getToTangentSpace()), ::nbl::hlsl::is_same_v, typename T::matrix3x3_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getFromTangentSpace()), ::nbl::hlsl::is_same_v, typename T::matrix3x3_type)) -) && Isotropic && ray_dir_info::Basic; + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(Isotropic, typename T::isotropic_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(ray_dir_info::Basic, typename T::ray_dir_info_type)) +); #undef normT #undef iso #undef aniso @@ -252,7 +257,7 @@ struct SAnisotropic static SAnisotropic create(NBL_CONST_REF_ARG(isotropic_type) isotropic) { vector3_type T, B; - math::frisvad(isotropic.N, T, B); + math::frisvad(isotropic.N, T, B); return create(isotropic, nbl::hlsl::normalize(T), nbl::hlsl::normalize(B)); } @@ -321,8 +326,10 @@ NBL_CONCEPT_END( //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create(pV,iso)), ::nbl::hlsl::is_same_v, T)) // NOTE: temporarily commented out due to dxc bug https://github.com/microsoft/DirectXShaderCompiler/issues/7154 //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create(pV,aniso)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getTangentSpaceL()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) -) && surface_interactions::Anisotropic && surface_interactions::Isotropic && - ray_dir_info::Basic; + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(ray_dir_info::Basic, typename T::ray_dir_info_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Isotropic, typename T::isotropic_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Anisotropic, typename T::anisotropic_type)) +); #undef pVdotL #undef frame #undef pV @@ -451,7 +458,8 @@ NBL_CONCEPT_END( //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,iso,_sample,pNdotV,V)), ::nbl::hlsl::is_same_v, bool)) //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,iso,_sample,pNdotV)), ::nbl::hlsl::is_same_v, bool)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.isValidVNDFMicrofacet(b0,b0,pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, bool)) -) && surface_interactions::Isotropic; + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Isotropic, typename T::isotropic_type)) +); #undef b0 #undef V #undef _sample @@ -597,7 +605,8 @@ NBL_CONCEPT_END( //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(aniso,_sample)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::compute(cache,b0,V,V,V,V,V,pNdotL,pNdotL,pNdotL,pNdotL,V)), ::nbl::hlsl::is_same_v, bool)) //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,aniso,_sample)), ::nbl::hlsl::is_same_v, bool)) -) && surface_interactions::Anisotropic; + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Anisotropic, typename T::anisotropic_type)) +); #undef b0 #undef V #undef _sample @@ -737,7 +746,8 @@ NBL_CONCEPT_END( //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((spec[field]), ::nbl::hlsl::is_scalar_v)) // correctness? ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((spec * field), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((field * spec), ::nbl::hlsl::is_same_v, T)) -) && is_scalar_v; + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(is_scalar_v, F)) +); #undef field #undef spec #include @@ -801,8 +811,11 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(aniso,aniso.N)), ::nbl::hlsl::is_same_v, typename T::sample_type)) //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template pdf(_sample,iso)), ::nbl::hlsl::is_scalar_v)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) -) && Sample && spectral_of && - surface_interactions::Isotropic && surface_interactions::Anisotropic; + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(Sample, typename T::sample_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(spectral_of, typename T::spectral_type, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Isotropic, typename T::isotropic_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Anisotropic, typename T::anisotropic_type)) +); #undef param #undef aniso #undef iso @@ -847,8 +860,11 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(aniso,aniso.N,anisocache)), ::nbl::hlsl::is_same_v, typename T::sample_type)) //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.template pdf(_sample,iso)), ::nbl::hlsl::is_scalar_v)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) -) && Sample && spectral_of && - IsotropicMicrofacetCache && AnisotropicMicrofacetCache; + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(Sample, typename T::sample_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(spectral_of, typename T::spectral_type, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(IsotropicMicrofacetCache, typename T::isocache_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(AnisotropicMicrofacetCache, typename T::anisocache_type)) +); #undef param #undef anisocache #undef isocache diff --git a/include/nbl/builtin/hlsl/concepts.hlsl b/include/nbl/builtin/hlsl/concepts.hlsl index c057fb0aff..7091acab37 100644 --- a/include/nbl/builtin/hlsl/concepts.hlsl +++ b/include/nbl/builtin/hlsl/concepts.hlsl @@ -32,6 +32,7 @@ namespace concepts #define NBL_CONCEPT_REQ_EXPR 1 // #define NBL_CONCEPT_REQ_EXPR_RET_TYPE 2 +#define NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT 3 //! Now diverge @@ -69,8 +70,9 @@ concept NBL_CONCEPT_NAME = requires BOOST_PP_EXPR_IF(LOCAL_PARAM_COUNT,(BOOST_PP #define NBL_IMPL_CONCEPT_REQ_TYPE(...) typename __VA_ARGS__; #define NBL_IMPL_CONCEPT_REQ_EXPR(...) __VA_ARGS__; #define NBL_IMPL_CONCEPT_REQ_EXPR_RET_TYPE(E,C,...) {E}; C; +#define NBL_IMPL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT(C,...) C< __VA_ARGS__ >; // -#define NBL_IMPL_CONCEPT (NBL_IMPL_CONCEPT_REQ_TYPE,NBL_IMPL_CONCEPT_REQ_EXPR,NBL_IMPL_CONCEPT_REQ_EXPR_RET_TYPE) +#define NBL_IMPL_CONCEPT (NBL_IMPL_CONCEPT_REQ_TYPE,NBL_IMPL_CONCEPT_REQ_EXPR,NBL_IMPL_CONCEPT_REQ_EXPR_RET_TYPE,NBL_IMPL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT) // #define NBL_IMPL_CONCEPT_END_DEF(r,unused,i,e) NBL_EVAL(BOOST_PP_TUPLE_ELEM(BOOST_PP_SEQ_HEAD(e),NBL_IMPL_CONCEPT) BOOST_PP_SEQ_TAIL(e)) // @@ -105,8 +107,9 @@ concept NBL_CONCEPT_NAME = requires BOOST_PP_EXPR_IF(LOCAL_PARAM_COUNT,(BOOST_PP #define NBL_IMPL_CONCEPT_REQ_TYPE(...) ::nbl::hlsl::make_void_t #define NBL_IMPL_CONCEPT_REQ_EXPR(...) ::nbl::hlsl::make_void_t #define NBL_IMPL_CONCEPT_REQ_EXPR_RET_TYPE(E,C,...) ::nbl::hlsl::enable_if_t > +#define NBL_IMPL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT(C,...) ::nbl::hlsl::enable_if_t > // -#define NBL_IMPL_CONCEPT_SFINAE (NBL_IMPL_CONCEPT_REQ_TYPE,NBL_IMPL_CONCEPT_REQ_EXPR,NBL_IMPL_CONCEPT_REQ_EXPR_RET_TYPE) +#define NBL_IMPL_CONCEPT_SFINAE (NBL_IMPL_CONCEPT_REQ_TYPE,NBL_IMPL_CONCEPT_REQ_EXPR,NBL_IMPL_CONCEPT_REQ_EXPR_RET_TYPE,NBL_IMPL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT) // #define NBL_IMPL_CONCEPT_END_DEF(r,unused,i,e) template \ struct BOOST_PP_CAT(__requirement,i) : ::nbl::hlsl::false_type {}; \ diff --git a/include/nbl/builtin/hlsl/math/functions.hlsl b/include/nbl/builtin/hlsl/math/functions.hlsl index 283841d4ab..6c34b5dab0 100644 --- a/include/nbl/builtin/hlsl/math/functions.hlsl +++ b/include/nbl/builtin/hlsl/math/functions.hlsl @@ -103,7 +103,7 @@ void sincos(T theta, NBL_REF_ARG(T) s, NBL_REF_ARG(T) c) template ::Dimension == 3) void frisvad(NBL_CONST_REF_ARG(T) normal, NBL_REF_ARG(T) tangent, NBL_REF_ARG(T) bitangent) { - const typename vector_traits::scalar_type a = NBL_FP64_LITERAL(1.0) / (NBL_FP64_LITERAL(1.0) + normal.z); + const typename vector_traits::scalar_type a = typename vector_traits::scalar_type(NBL_FP64_LITERAL(1.0)) / (typename vector_traits::scalar_type(NBL_FP64_LITERAL(1.0)) + normal.z); const typename vector_traits::scalar_type b = -normal.x * normal.y * a; if (normal.z < -NBL_FP64_LITERAL(0.9999999)) { From 6ca571ead968bf1aee28c507fd8282b34db5ad54 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 7 Mar 2025 10:49:32 +0700 Subject: [PATCH 079/188] more bug fixes #6 --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 30 ++++--- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 62 +++++++------- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 82 +++++++++---------- include/nbl/builtin/hlsl/cpp_compat/basic.h | 2 +- include/nbl/builtin/hlsl/math/functions.hlsl | 2 +- 5 files changed, 91 insertions(+), 87 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 56168959a4..b003664c87 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -23,20 +23,24 @@ namespace bxdf { // returns unnormalized vector -template) -T computeUnnormalizedMicrofacetNormal(bool _refract, vector V, vector L, T orientedEta) +template) +T computeUnnormalizedMicrofacetNormal(bool _refract, NBL_CONST_REF_ARG(T) V, NBL_CONST_REF_ARG(T) L, typename vector_traits::scalar_type orientedEta) { - const T etaFactor = (_refract ? orientedEta : 1.0); - const vector tmpH = V + L * etaFactor; - return ieee754::flipSign(tmpH, _refract); + const typename vector_traits::scalar_type etaFactor = (_refract ? orientedEta : 1.0); + T tmpH = V + L * etaFactor; + // ieee754::flipSign(tmpH, _refract) doesn't work with vectors + tmpH.x = ieee754::flipSign::scalar_type>(tmpH.x, _refract); + tmpH.y = ieee754::flipSign::scalar_type>(tmpH.y, _refract); + tmpH.z = ieee754::flipSign::scalar_type>(tmpH.z, _refract); + return tmpH; } // returns normalized vector, but NaN when result is length 0 -template) -T computeMicrofacetNormal(bool _refract, vector V, vector L, T orientedEta) +template) +T computeMicrofacetNormal(bool _refract, NBL_CONST_REF_ARG(T) V, NBL_CONST_REF_ARG(T) L, typename vector_traits::scalar_type orientedEta) { - const vector H = computeUnnormalizedMicrofacetNormal(_refract,V,L,orientedEta); - const T unnormRcpLen = rsqrt(nbl::hlsl::dot >(H,H)); + const T H = computeUnnormalizedMicrofacetNormal(_refract,V,L,orientedEta); + const typename vector_traits::scalar_type unnormRcpLen = rsqrt::scalar_type>(nbl::hlsl::dot(H,H)); return H * unnormRcpLen; } @@ -377,8 +381,8 @@ struct SLightSample retval.L = L; retval.VdotL = VdotL; - retval.TdotL = nbl::hlsl::numeric_limits::signaling_NaN; - retval.BdotL = nbl::hlsl::numeric_limits::signaling_NaN; + retval.TdotL = nbl::hlsl::numeric_limits::quiet_NaN; + retval.BdotL = nbl::hlsl::numeric_limits::quiet_NaN; retval.NdotL = nbl::hlsl::dot(N,L.direction); retval.NdotL2 = retval.NdotL * retval.NdotL; @@ -515,7 +519,7 @@ struct SIsotropicMicrofacetCache ) { // TODO: can we optimize? - H = computeMicrofacetNormal(transmitted,V,L,orientedEta); + H = computeMicrofacetNormal(transmitted,V,L,orientedEta); retval.NdotH = nbl::hlsl::dot(N, H); // not coming from the medium (reflected) OR @@ -704,7 +708,7 @@ struct SAnisotropicMicrofacetCache ) { vector3_type H; - const bool valid = isocache_type::compute(retval.iso_cache,interaction,_sample,eta,H); + const bool valid = isocache_type::template compute(retval.iso_cache,interaction.isotropic,_sample,eta,H); if (valid) { retval.TdotH = nbl::hlsl::dot(interaction.T,H); diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 05bbf0bf53..ed92da147e 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -59,12 +59,12 @@ struct SLambertianBxDF return retval; } - static this_t create(SBxDFCreationParams params) + static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) { return create(); } - void init(SBxDFCreationParams params) + void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) { // do nothing } @@ -79,14 +79,14 @@ struct SLambertianBxDF return __eval_pi_factored_out(params.NdotL) * numbers::inv_pi; } - sample_type generate_wo_clamps(anisotropic_type interaction, vector u) + sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector) u) { ray_dir_info_type L; L.direction = projected_hemisphere_generate(u); return sample_type::createFromTangentSpace(interaction.getTangentSpaceV(), L, interaction.getFromTangentSpace()); } - sample_type generate(anisotropic_type interaction, vector u) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector) u) { return generate_wo_clamps(interaction, u); } @@ -127,12 +127,12 @@ struct SOrenNayarBxDF return retval; } - static this_t create(SBxDFCreationParams params) + static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) { return create(params.A.x); } - void init(SBxDFCreationParams params) + void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) { A = params.A.x; } @@ -147,29 +147,29 @@ struct SOrenNayarBxDF return (AB.x + AB.y * cos_phi_sin_theta * C); } - scalar_type eval(params_t params) + scalar_type eval(NBL_CONST_REF_ARG(params_t) params) { return params.NdotL * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(params.VdotL, params.NdotL, params.NdotV); } - sample_type generate_wo_clamps(anisotropic_type interaction, vector2_type u) + sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector2_type) u) { ray_dir_info_type L; L.direction = projected_hemisphere_generate(u); return sample_type::createFromTangentSpace(interaction.getTangentSpaceV(), L, interaction.getFromTangentSpace()); } - sample_type generate(anisotropic_type interaction, vector2_type u) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector2_type) u) { return generate_wo_clamps(interaction, u); } - scalar_type pdf(params_t params) + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) { return projected_hemisphere_pdf(params.NdotL); } - quotient_pdf_type quotient_and_pdf(params_t params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) { scalar_type _pdf; projected_hemisphere_quotient_and_pdf(_pdf, params.NdotL); @@ -343,7 +343,7 @@ struct SBeckmannBxDF using anisocache_type = AnisoCache; // iso - static this_t create(scalar_type A, spectral_type ior0, spectral_type ior1) + static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) { this_t retval; retval.A = vector2_type(A,A); @@ -353,7 +353,7 @@ struct SBeckmannBxDF } // aniso - static this_t create(scalar_type ax, scalar_type ay, spectral_type ior0, spectral_type ior1) + static this_t create(scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) { this_t retval; retval.A = vector2_type(ax,ay); @@ -362,7 +362,7 @@ struct SBeckmannBxDF return retval; } - static this_t create(SBxDFCreationParams params) + static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) { if (params.is_aniso) return create(params.A.x, params.A.y, params.ior0, params.ior1); @@ -370,14 +370,14 @@ struct SBeckmannBxDF return create(params.A.x, params.ior0, params.ior1); } - void init(SBxDFCreationParams params) + void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) { A = params.A; ior0 = params.ior0; ior1 = params.ior1; } - scalar_type __eval_DG_wo_clamps(params_t params) + scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_t) params) { if (params.is_aniso) { @@ -422,7 +422,7 @@ struct SBeckmannBxDF return (spectral_type)0.0; } - vector3_type __generate(vector3_type localV, vector2_type u) + vector3_type __generate(NBL_CONST_REF_ARG(vector3_type) localV, NBL_CONST_REF_ARG(vector2_type) u) { //stretch vector3_type V = nbl::hlsl::normalize(vector3_type(A.x * localV.x, A.y * localV.y, localV.z)); @@ -490,7 +490,7 @@ struct SBeckmannBxDF return nbl::hlsl::normalize(vector3_type(-slope, 1.0)); } - sample_type generate(anisotropic_type interaction, vector2_type u, NBL_REF_ARG(anisocache_type) cache) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector2_type) u, NBL_REF_ARG(anisocache_type) cache) { const vector3_type localV = interaction.getTangentSpaceV(); const vector3_type H = __generate(localV, u); @@ -502,7 +502,7 @@ struct SBeckmannBxDF return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); } - scalar_type pdf(params_t params, NBL_REF_ARG(scalar_type) onePlusLambda_V) + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { scalar_type ndf, lambda; if (params.is_aniso) @@ -529,13 +529,13 @@ struct SBeckmannBxDF return smith::VNDF_pdf_wo_clamps >(ndf, lambda, params.uNdotV, onePlusLambda_V); } - scalar_type pdf(params_t params) + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) { scalar_type dummy; return pdf(params, dummy); } - quotient_pdf_type quotient_and_pdf(params_t params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) { scalar_type onePlusLambda_V; scalar_type _pdf = pdf(params, onePlusLambda_V); @@ -586,7 +586,7 @@ struct SGGXBxDF using anisocache_type = AnisoCache; // iso - static this_t create(scalar_type A, spectral_type ior0, spectral_type ior1) + static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) { this_t retval; retval.A = vector2_type(A,A); @@ -596,7 +596,7 @@ struct SGGXBxDF } // aniso - static this_t create(scalar_type ax, scalar_type ay, spectral_type ior0, spectral_type ior1) + static this_t create(scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) { this_t retval; retval.A = vector2_type(ax,ay); @@ -605,7 +605,7 @@ struct SGGXBxDF return retval; } - static this_t create(SBxDFCreationParams params) + static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) { if (params.is_aniso) return create(params.A.x, params.A.y, params.ior0, params.ior1); @@ -613,14 +613,14 @@ struct SGGXBxDF return create(params.A.x, params.ior0, params.ior1); } - void init(SBxDFCreationParams params) + void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) { A = params.A; ior0 = params.ior0; ior1 = params.ior1; } - scalar_type __eval_DG_wo_clamps(params_t params) + scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_t) params) { if (params.is_aniso) { @@ -653,7 +653,7 @@ struct SGGXBxDF } } - spectral_type eval(params_t params) + spectral_type eval(NBL_CONST_REF_ARG(params_t) params) { if (params.uNdotL > numeric_limits::min && params.uNdotV > numeric_limits::min) { @@ -665,7 +665,7 @@ struct SGGXBxDF return (spectral_type)0.0; } - vector3_type __generate(vector3_type localV, vector2_type u) + vector3_type __generate(NBL_CONST_REF_ARG(vector3_type) localV, NBL_CONST_REF_ARG(vector2_type) u) { vector3_type V = nbl::hlsl::normalize(vector3_type(A.x*localV.x, A.y*localV.y, localV.z));//stretch view vector so that we're sampling as if roughness=1.0 @@ -687,7 +687,7 @@ struct SGGXBxDF return nbl::hlsl::normalize(vector3_type(A.x*H.x, A.y*H.y, H.z)); } - sample_type generate(anisotropic_type interaction, vector2_type u, NBL_REF_ARG(anisocache_type) cache) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector2_type) u, NBL_REF_ARG(anisocache_type) cache) { const vector3_type localV = interaction.getTangentSpaceV(); const vector3_type H = __generate(localV, u); @@ -699,7 +699,7 @@ struct SGGXBxDF return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); } - scalar_type pdf(params_t params) + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) { scalar_type ndf, G1_over_2NdotV; if (params.is_aniso) @@ -728,7 +728,7 @@ struct SGGXBxDF return smith::VNDF_pdf_wo_clamps(ndf, G1_over_2NdotV); } - quotient_pdf_type quotient_and_pdf(params_t params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) { scalar_type _pdf = pdf(params); diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index fec527cd39..52b540a171 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -63,12 +63,12 @@ struct SLambertianBxDF return retval; } - static this_t create(SBxDFCreationParams params) + static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) { return create(); } - void init(SBxDFCreationParams params) + void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) { // do nothing } @@ -78,29 +78,29 @@ struct SLambertianBxDF return absNdotL; } - scalar_type eval(params_t params) + scalar_type eval(NBL_CONST_REF_ARG(params_t) params) { return __eval_pi_factored_out(params.NdotL) * numbers::inv_pi * 0.5; } - sample_type generate_wo_clamps(anisotropic_type interaction, vector u) + sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector) u) { ray_dir_info_type L; L.direction = projected_sphere_generate(u); return sample_type::createFromTangentSpace(interaction.getTangentSpaceV(), L, interaction.getFromTangentSpace()); } - sample_type generate(anisotropic_type interaction, vector u) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector) u) { return generate_wo_clamps(interaction, u); } - scalar_type pdf(params_t params) + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) { return projected_sphere_pdf(params.NdotL); } - quotient_pdf_type quotient_and_pdf(params_t params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) { scalar_type _pdf; scalar_type q = projected_sphere_quotient_and_pdf(_pdf, params.NdotL); @@ -137,22 +137,22 @@ struct SSmoothDielectricBxDF return retval; } - static this_t create(SBxDFCreationParams params) + static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) { return create(params.eta); } - void init(SBxDFCreationParams params) + void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) { eta = params.eta; } - spectral_type eval(params_t params) + spectral_type eval(NBL_CONST_REF_ARG(params_t) params) { return (spectral_type)0; } - sample_type __generate_wo_clamps(vector3_type V, vector3_type T, vector3_type B, vector3_type N, bool backside, scalar_type NdotV, scalar_type absNdotV, scalar_type NdotV2, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(bool) transmitted) + sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N, bool backside, scalar_type NdotV, scalar_type absNdotV, scalar_type NdotV2, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(bool) transmitted) { const scalar_type reflectance = fresnel::dielectric_common(orientedEta2, absNdotV); @@ -165,7 +165,7 @@ struct SSmoothDielectricBxDF return sample_type::create(L, nbl::hlsl::dot(V, L.direction), T, B, N); } - sample_type generate_wo_clamps(anisotropic_type interaction, NBL_REF_ARG(vector) u) + sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector) u) { scalar_type orientedEta, rcpOrientedEta; const bool backside = bxdf::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.isotropic.NdotV, eta); @@ -174,7 +174,7 @@ struct SSmoothDielectricBxDF interaction.isotropic.NdotV, interaction.isotropic.NdotV*interaction.isotropic.NdotV, u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, dummy); } - sample_type generate(anisotropic_type interaction, NBL_REF_ARG(vector) u) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector) u) { scalar_type orientedEta, rcpOrientedEta; const bool backside = bxdf::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.isotropic.NdotV, eta); @@ -184,12 +184,12 @@ struct SSmoothDielectricBxDF } // eval and pdf return 0 because smooth dielectric/conductor BxDFs are dirac delta distributions, model perfectly specular objects that scatter light to only one outgoing direction - scalar_type pdf(params_t params) + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) { return 0; } - quotient_pdf_type quotient_and_pdf(params_t params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) { const bool transmitted = isTransmissionPath(params.uNdotV, params.uNdotL); @@ -221,7 +221,7 @@ struct SSmoothDielectricBxDF using isocache_type = IsoCache; using anisocache_type = AnisoCache; - static this_t create(spectral_type eta2, spectral_type luminosityContributionHint) + static this_t create(NBL_CONST_REF_ARG(spectral_type) eta2, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) { this_t retval; retval.eta2 = eta2; @@ -229,18 +229,18 @@ struct SSmoothDielectricBxDF return retval; } - static this_t create(SBxDFCreationParams params) + static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) { return create(params.eta2, params.luminosityContributionHint); } - void init(SBxDFCreationParams params) + void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) { eta2 = params.eta2; luminosityContributionHint = params.luminosityContributionHint; } - spectral_type eval(params_t params) + spectral_type eval(NBL_CONST_REF_ARG(params_t) params) { return (spectral_type)0; } @@ -249,7 +249,7 @@ struct SSmoothDielectricBxDF // its basically a set of weights that determine // assert(1.0==luminosityContributionHint.r+luminosityContributionHint.g+luminosityContributionHint.b); // `remainderMetadata` is a variable which the generator function returns byproducts of sample generation that would otherwise have to be redundantly calculated `quotient_and_pdf` - sample_type __generate_wo_clamps(vector3_type V, vector3_type T, vector3_type B, vector3_type N, scalar_type NdotV, scalar_type absNdotV, NBL_REF_ARG(vector3_type) u, spectral_type eta2, spectral_type luminosityContributionHint, NBL_REF_ARG(spectral_type) remainderMetadata) + sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N, scalar_type NdotV, scalar_type absNdotV, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(spectral_type) eta2, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint, NBL_REF_ARG(spectral_type) remainderMetadata) { // we will only ever intersect from the outside const spectral_type reflectance = thindielectricInfiniteScatter(fresnel::dielectric_common(eta2,absNdotV)); @@ -266,24 +266,24 @@ struct SSmoothDielectricBxDF return sample_type::create(L, nbl::hlsl::dot(V, L.direction), T, B, N); } - sample_type generate_wo_clamps(anisotropic_type interaction, NBL_REF_ARG(vector) u) + sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector) u) { vector3_type dummy; return __generate_wo_clamps(interaction.isotropic.V.direction, interaction.T, interaction.B, interaction.isotropic.N, interaction.isotropic.NdotV, interaction.isotropic.NdotV, u, eta2, luminosityContributionHint, dummy); } - sample_type generate(anisotropic_type interaction, NBL_REF_ARG(vector) u) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector) u) { vector3_type dummy; return __generate_wo_clamps(interaction.isotropic.V.direction, interaction.T, interaction.B, interaction.isotropic.N, interaction.isotropic.NdotV, nbl::hlsl::abs(interaction.isotropic.NdotV), u, eta2, luminosityContributionHint, dummy); } - scalar_type pdf(params_t params) + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) { return 0; } - quotient_pdf_type quotient_and_pdf(params_t params) // isotropic + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) // isotropic { const bool transmitted = isTransmissionPath(params.uNdotV, params.uNdotL); const spectral_type reflectance = thindielectricInfiniteScatter(fresnel::dielectric_common(eta2, params.NdotV)); @@ -334,7 +334,7 @@ struct SBeckmannDielectricBxDF return retval; } - static this_t create(SBxDFCreationParams params) + static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) { if (params.is_aniso) return create(params.eta, params.A.x, params.A.y); @@ -342,13 +342,13 @@ struct SBeckmannDielectricBxDF return create(params.eta, params.A.x); } - void init(SBxDFCreationParams params) + void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) { A = params.A; eta = params.eta; } - spectral_type eval(params_t params) + spectral_type eval(NBL_CONST_REF_ARG(params_t) params) { scalar_type orientedEta, dummy; const bool backside = bxdf::getOrientedEtas(orientedEta, dummy, params.VdotH, eta); @@ -370,7 +370,7 @@ struct SBeckmannDielectricBxDF return (spectral_type)fresnel::dielectric_common(orientedEta2, nbl::hlsl::abs(params.VdotH)) * microfacet_transform(); } - sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix3x3_type m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) + sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) localV, bool backside, NBL_CONST_REF_ARG(vector3_type) H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) { const scalar_type localVdotH = nbl::hlsl::dot(localV,H); const scalar_type reflectance = fresnel::dielectric_common(orientedEta2,nbl::hlsl::abs(localVdotH)); @@ -388,7 +388,7 @@ struct SBeckmannDielectricBxDF return sample_type::createFromTangentSpace(localV, localL, m); } - sample_type generate(anisotropic_type interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) { const vector3_type localV = interaction.getTangentSpaceV(); @@ -404,13 +404,13 @@ struct SBeckmannDielectricBxDF return __generate_wo_clamps(localV, backside, H, interaction.getFromTangentSpace(), u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, cache); } - sample_type generate(anisotropic_type interaction, NBL_REF_ARG(vector3_type) u) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector3_type) u) { anisocache_type dummycache; return generate(interaction, u, dummycache); } - scalar_type pdf(params_t params, NBL_REF_ARG(scalar_type) onePlusLambda_V) + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { scalar_type orientedEta, dummy; const bool backside = bxdf::getOrientedEtas(orientedEta, dummy, params.VdotH, eta); @@ -448,13 +448,13 @@ struct SBeckmannDielectricBxDF return smith::VNDF_pdf_wo_clamps >(ndf,lambda,params.NdotV,transmitted,params.VdotH,params.LdotH,VdotHLdotH,orientedEta,reflectance,onePlusLambda_V); } - scalar_type pdf(params_t params) + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) { scalar_type dummy; return pdf(params, dummy); } - quotient_pdf_type quotient_and_pdf(params_t params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) { scalar_type onePlusLambda_V; scalar_type _pdf = pdf(params, onePlusLambda_V); @@ -515,7 +515,7 @@ struct SGGXDielectricBxDF return retval; } - static this_t create(SBxDFCreationParams params) + static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) { if (params.is_aniso) return create(params.eta, params.A.x, params.A.y); @@ -523,13 +523,13 @@ struct SGGXDielectricBxDF return create(params.eta, params.A.x); } - void init(SBxDFCreationParams params) + void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) { A = params.A; eta = params.eta; } - spectral_type eval(params_t params) + spectral_type eval(NBL_CONST_REF_ARG(params_t) params) { scalar_type orientedEta, dummy; const bool backside = bxdf::getOrientedEtas(orientedEta, dummy, params.VdotH, eta); @@ -557,7 +557,7 @@ struct SGGXDielectricBxDF return (spectral_type)fresnel::dielectric_common(orientedEta2, nbl::hlsl::abs(params.VdotH)) * microfacet_transform(); } - sample_type __generate_wo_clamps(vector3_type localV, bool backside, vector3_type H, matrix3x3_type m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) + sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) localV, bool backside, NBL_CONST_REF_ARG(vector3_type) H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) { const scalar_type localVdotH = nbl::hlsl::dot(localV,H); const scalar_type reflectance = fresnel::dielectric_common(orientedEta2,nbl::hlsl::abs(localVdotH)); @@ -575,7 +575,7 @@ struct SGGXDielectricBxDF return sample_type::createFromTangentSpace(localV, localL, m); } - sample_type generate(anisotropic_type interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) { const vector3_type localV = interaction.getTangentSpaceV(); @@ -591,13 +591,13 @@ struct SGGXDielectricBxDF return __generate_wo_clamps(localV, backside, H, interaction.getFromTangentSpace(), u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, cache); } - sample_type generate(anisotropic_type interaction, NBL_REF_ARG(vector3_type) u) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector3_type) u) { anisocache_type dummycache; return generate(interaction, u, dummycache); } - scalar_type pdf(params_t params) + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) { scalar_type orientedEta, dummy; const bool backside = bxdf::getOrientedEtas(orientedEta, dummy, params.VdotH, eta); @@ -637,7 +637,7 @@ struct SGGXDielectricBxDF return smith::VNDF_pdf_wo_clamps(ndf, lambda, params.NdotV, transmitted, params.VdotH, params.LdotH, VdotHLdotH, orientedEta, reflectance); } - quotient_pdf_type quotient_and_pdf(params_t params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) { const scalar_type ax2 = A.x*A.x; const scalar_type ay2 = A.y*A.y; diff --git a/include/nbl/builtin/hlsl/cpp_compat/basic.h b/include/nbl/builtin/hlsl/cpp_compat/basic.h index 5bdbdb7a76..e1c3be9063 100644 --- a/include/nbl/builtin/hlsl/cpp_compat/basic.h +++ b/include/nbl/builtin/hlsl/cpp_compat/basic.h @@ -17,7 +17,7 @@ struct static_cast_helper #ifndef __HLSL_VERSION return static_cast(u); #else - return To(u); + return (To)(u); #endif } }; diff --git a/include/nbl/builtin/hlsl/math/functions.hlsl b/include/nbl/builtin/hlsl/math/functions.hlsl index 6c34b5dab0..f83189a5dd 100644 --- a/include/nbl/builtin/hlsl/math/functions.hlsl +++ b/include/nbl/builtin/hlsl/math/functions.hlsl @@ -160,7 +160,7 @@ struct conditionalAbsOrMax_helper::scalar_type)>; + using UintOfTSize = unsigned_integer_of_size_t::scalar_type)>; const int dimensionOfT = vector_traits::Dimension; using Uint32VectorWithDimensionOfT = vector; using scalar_type = typename vector_traits::scalar_type; From 39a8a9b3765c10806cea172c0520c69604de21da Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 7 Mar 2025 17:01:05 +0700 Subject: [PATCH 080/188] minor fixes, infinity use --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 51 ------------------- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 4 +- 2 files changed, 2 insertions(+), 53 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index b003664c87..e6caa17bca 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -1015,27 +1015,6 @@ struct SBxDFParams return retval; } - // template && surface_interactions::Anisotropic) - // static this_t create(LightSample _sample, Aniso interaction, BxDFClampMode clamp = BCM_NONE) - // { - // this_t retval; - // retval.NdotV = clamp == BCM_ABS ? abs(interaction.NdotV) : - // clamp == BCM_MAX ? max(interaction.NdotV, 0.0) : - // interaction.NdotV; - // retval.uNdotV = interaction.NdotV; - // retval.NdotV2 = interaction.NdotV2; - // retval.NdotL = clamp == BCM_ABS ? abs(_sample.NdotL) : - // clamp == BCM_MAX ? max(_sample.NdotL, 0.0) : - // _sample.NdotL; - // retval.uNdotL = _sample.NdotL; - // retval.NdotL2 = _sample.NdotL2; - // retval.VdotL = _sample.VdotL; - - // retval.is_aniso = true; - - // return retval; - // } - template && (surface_interactions::Isotropic || surface_interactions::Anisotropic) && (IsotropicMicrofacetCache || AnisotropicMicrofacetCache)) static this_t create(NBL_CONST_REF_ARG(LightSample) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(Cache) cache, BxDFClampMode _clamp) { @@ -1069,36 +1048,6 @@ struct SBxDFParams return retval; } - // template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - // static this_t create(LightSample _sample, Aniso interaction, Cache cache, BxDFClampMode clamp = BCM_NONE) - // { - // this_t retval; - // retval.NdotH = cache.NdotH; - // retval.NdotH2 = cache.NdotH2; - // retval.NdotV = clamp == BCM_ABS ? abs(interaction.NdotV) : - // clamp == BCM_MAX ? max(interaction.NdotV, 0.0) : - // interaction.NdotV; - // retval.uNdotV = interaction.NdotV; - // retval.NdotV2 = interaction.NdotV2; - // retval.NdotL = clamp == BCM_ABS ? abs(_sample.NdotL) : - // clamp == BCM_MAX ? max(_sample.NdotL, 0.0) : - // _sample.NdotL; - // retval.uNdotL = _sample.NdotL; - // retval.NdotL2 = _sample.NdotL2; - // retval.VdotH = cache.VdotH; - // retval.LdotH = cache.LdotH; - // retval.VdotL = _sample.VdotL; - - // retval.is_aniso = true; - // retval.TdotH2 = cache.TdotH * cache.TdotH; - // retval.BdotH2 = cache.BdotH * cache.BdotH; - // retval.TdotL2 = _sample.TdotL * _sample.TdotL; - // retval.BdotL2 = _sample.BdotL * _sample.BdotL; - // retval.TdotV2 = interaction.TdotV * interaction.TdotV; - // retval.BdotV2 = interaction.BdotV * interaction.BdotV; - // return retval; - // } - Scalar getMaxNdotV() { return max(uNdotV, 0.0); } Scalar getAbsNdotV() { return abs(uNdotV); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index 52b540a171..3d25d9f249 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -196,7 +196,7 @@ struct SSmoothDielectricBxDF scalar_type dummy, rcpOrientedEta; const bool backside = bxdf::getOrientedEtas(dummy, rcpOrientedEta, params.NdotV, eta); - const scalar_type _pdf = numeric_limits::infinity; + const scalar_type _pdf = bit_cast(numeric_limits::infinity); scalar_type quo = transmitted ? rcpOrientedEta : 1.0; return quotient_pdf_type::create((spectral_type)(quo), _pdf); } @@ -291,7 +291,7 @@ struct SSmoothDielectricBxDF const scalar_type sampleProb = nbl::hlsl::dot(sampleValue,luminosityContributionHint); - const scalar_type _pdf = numeric_limits::infinity; + const scalar_type _pdf = bit_cast(numeric_limits::infinity); return quotient_pdf_type::create((spectral_type)(sampleValue / sampleProb), _pdf); } From b02f8e66354955371fc5e939c2c8e40e14e88aea Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 11 Mar 2025 11:24:07 +0700 Subject: [PATCH 081/188] condAbsOrMax in param struct --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index e6caa17bca..16e42b85dd 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -995,14 +995,10 @@ struct SBxDFParams impl::__extract_aniso_vars::is_aniso> vars = impl::__extract_aniso_vars::is_aniso>::create(_sample, interaction); this_t retval; - retval.NdotV = _clamp == BCM_ABS ? abs(vars.NdotV) : - _clamp == BCM_MAX ? max(vars.NdotV, 0.0) : - vars.NdotV; + retval.NdotV = math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, vars.NdotV, 0.0); retval.uNdotV = vars.NdotV; retval.NdotV2 = vars.NdotV2; - retval.NdotL = _clamp == BCM_ABS ? abs(_sample.NdotL) : - _clamp == BCM_MAX ? max(_sample.NdotL, 0.0) : - _sample.NdotL; + retval.NdotL = math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.NdotL, 0.0); retval.uNdotL = _sample.NdotL; retval.NdotL2 = _sample.NdotL2; retval.VdotL = _sample.VdotL; @@ -1024,14 +1020,10 @@ struct SBxDFParams this_t retval; retval.NdotH = vars2.NdotH; retval.NdotH2 = vars2.NdotH2; - retval.NdotV = _clamp == BCM_ABS ? abs(vars.NdotV) : - _clamp == BCM_MAX ? max(vars.NdotV, 0.0) : - vars.NdotV; + retval.NdotV = math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, vars.NdotV, 0.0); retval.uNdotV = vars.NdotV; retval.NdotV2 = vars.NdotV2; - retval.NdotL = _clamp == BCM_ABS ? abs(_sample.NdotL) : - _clamp == BCM_MAX ? max(_sample.NdotL, 0.0) : - _sample.NdotL; + retval.NdotL = math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.NdotL, 0.0); retval.uNdotL = _sample.NdotL; retval.NdotL2 = _sample.NdotL2; retval.VdotH = vars2.VdotH; From e0ccc9e833a096a5178f95b52708f9c2929f1fcc Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 2 Apr 2025 15:17:41 +0700 Subject: [PATCH 082/188] some style changes, refactor sampling funcs --- .../nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl | 29 ++--- include/nbl/builtin/hlsl/bxdf/common.hlsl | 1 + include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 16 ++- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 8 +- include/nbl/builtin/hlsl/concepts/core.hlsl | 2 +- include/nbl/builtin/hlsl/cpp_compat/basic.h | 2 +- .../hlsl/sampling/concentric_mapping.hlsl | 19 +++- .../builtin/hlsl/sampling/cos_weighted.hlsl | 103 ++++++++---------- .../nbl/builtin/hlsl/sampling/uniform.hlsl | 50 +++------ 9 files changed, 98 insertions(+), 132 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl b/include/nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl index 78b23830bc..2422c76b7b 100644 --- a/include/nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl @@ -1,8 +1,8 @@ -// Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O. +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h -#ifndef _NBL_BUILTIN_HLSL_BXDF_BXDF_TRAITS_INCLUDED_ -#define _NBL_BUILTIN_HLSL_BXDF_BXDF_TRAITS_INCLUDED_ +#ifndef _NBL_BUILTIN_HLSL_BXDF_TRAITS_INCLUDED_ +#define _NBL_BUILTIN_HLSL_BXDF_TRAITS_INCLUDED_ #include "nbl/builtin/hlsl/bxdf/common.hlsl" #include "nbl/builtin/hlsl/bxdf/reflection.hlsl" @@ -12,6 +12,8 @@ namespace nbl { namespace hlsl { +namespace bxdf +{ enum BxDFType : uint16_t { @@ -21,10 +23,10 @@ enum BxDFType : uint16_t }; template -struct bxdf_traits; +struct traits; template -struct bxdf_traits > +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = false; @@ -32,7 +34,7 @@ struct bxdf_traits > }; template -struct bxdf_traits > +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; @@ -42,7 +44,7 @@ struct bxdf_traits > // no blinn phong template -struct bxdf_traits > +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; @@ -50,7 +52,7 @@ struct bxdf_traits > }; template -struct bxdf_traits > +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; @@ -59,7 +61,7 @@ struct bxdf_traits > template -struct bxdf_traits > +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = false; @@ -67,7 +69,7 @@ struct bxdf_traits > }; template -struct bxdf_traits > +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; @@ -75,7 +77,7 @@ struct bxdf_traits }; template -struct bxdf_traits > +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; @@ -83,7 +85,7 @@ struct bxdf_traits > }; template -struct bxdf_traits > +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; @@ -91,13 +93,14 @@ struct bxdf_traits > }; template -struct bxdf_traits > +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; }; +} } } diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 16e42b85dd..1c3f698b8b 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -11,6 +11,7 @@ #include "nbl/builtin/hlsl/ieee754.hlsl" #include "nbl/builtin/hlsl/tgmath.hlsl" #include "nbl/builtin/hlsl/math/functions.hlsl" +#include "nbl/builtin/hlsl/cpp_compat/promote.hlsl" #include "nbl/builtin/hlsl/bxdf/fresnel.hlsl" #include "nbl/builtin/hlsl/vector_utils/vector_traits.hlsl" diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index ed92da147e..8c5b2c5718 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -82,7 +82,7 @@ struct SLambertianBxDF sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector) u) { ray_dir_info_type L; - L.direction = projected_hemisphere_generate(u); + L.direction = sampling::ProjectedHemisphere::generate(u); return sample_type::createFromTangentSpace(interaction.getTangentSpaceV(), L, interaction.getFromTangentSpace()); } @@ -93,14 +93,13 @@ struct SLambertianBxDF scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) { - return projected_hemisphere_pdf(params.NdotL); + return sampling::ProjectedHemisphere::pdf(params.NdotL); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) { scalar_type _pdf; - scalar_type q = projected_hemisphere_quotient_and_pdf(_pdf, params.NdotL); - return quotient_pdf_type::create((spectral_type)(q), _pdf); + return sampling::ProjectedHemisphere::template quotient_and_pdf(params.NdotL); } }; @@ -155,7 +154,7 @@ struct SOrenNayarBxDF sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector2_type) u) { ray_dir_info_type L; - L.direction = projected_hemisphere_generate(u); + L.direction = sampling::ProjectedHemisphere::generate(u); return sample_type::createFromTangentSpace(interaction.getTangentSpaceV(), L, interaction.getFromTangentSpace()); } @@ -166,15 +165,14 @@ struct SOrenNayarBxDF scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) { - return projected_hemisphere_pdf(params.NdotL); + return sampling::ProjectedHemisphere::pdf(params.NdotL); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) { - scalar_type _pdf; - projected_hemisphere_quotient_and_pdf(_pdf, params.NdotL); + scalar_type _pdf = pdf(params); scalar_type q = __rec_pi_factored_out_wo_clamps(params.VdotL, params.NdotL, params.NdotV); - return quotient_pdf_type::create((spectral_type)(q), _pdf); + return quotient_pdf_type::create(hlsl::promote(q), _pdf); } scalar_type A; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index 3d25d9f249..ccd0ae9b49 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -86,7 +86,7 @@ struct SLambertianBxDF sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector) u) { ray_dir_info_type L; - L.direction = projected_sphere_generate(u); + L.direction = sampling::ProjectedSphere::generate(u); return sample_type::createFromTangentSpace(interaction.getTangentSpaceV(), L, interaction.getFromTangentSpace()); } @@ -97,14 +97,12 @@ struct SLambertianBxDF scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) { - return projected_sphere_pdf(params.NdotL); + return sampling::ProjectedSphere::pdf(params.NdotL); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) { - scalar_type _pdf; - scalar_type q = projected_sphere_quotient_and_pdf(_pdf, params.NdotL); - return quotient_pdf_type::create((spectral_type)(q), _pdf); + return sampling::ProjectedSphere::template quotient_and_pdf(params.NdotL); } }; diff --git a/include/nbl/builtin/hlsl/concepts/core.hlsl b/include/nbl/builtin/hlsl/concepts/core.hlsl index c1bc0277df..dcbafae8a5 100644 --- a/include/nbl/builtin/hlsl/concepts/core.hlsl +++ b/include/nbl/builtin/hlsl/concepts/core.hlsl @@ -47,7 +47,7 @@ template NBL_BOOL_CONCEPT UnsignedIntegralScalar = !nbl::hlsl::is_signed_v && ::nbl::hlsl::is_integral_v && nbl::hlsl::is_scalar_v; template -NBL_BOOL_CONCEPT FloatingPointScalar = (nbl::hlsl::is_floating_point_v && nbl::hlsl::is_scalar_v); +NBL_BOOL_CONCEPT FloatingPointScalar = nbl::hlsl::is_floating_point_v && nbl::hlsl::is_scalar_v; template NBL_BOOL_CONCEPT BooleanScalar = concepts::Boolean && nbl::hlsl::is_scalar_v; diff --git a/include/nbl/builtin/hlsl/cpp_compat/basic.h b/include/nbl/builtin/hlsl/cpp_compat/basic.h index f3135bbc13..3802bd69ea 100644 --- a/include/nbl/builtin/hlsl/cpp_compat/basic.h +++ b/include/nbl/builtin/hlsl/cpp_compat/basic.h @@ -17,7 +17,7 @@ struct static_cast_helper #ifndef __HLSL_VERSION return static_cast(u); #else - return (To)(u); + return To(u); #endif } }; diff --git a/include/nbl/builtin/hlsl/sampling/concentric_mapping.hlsl b/include/nbl/builtin/hlsl/sampling/concentric_mapping.hlsl index e884a4ecc6..6bfea6c03b 100644 --- a/include/nbl/builtin/hlsl/sampling/concentric_mapping.hlsl +++ b/include/nbl/builtin/hlsl/sampling/concentric_mapping.hlsl @@ -1,3 +1,7 @@ +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h + #ifndef _NBL_BUILTIN_HLSL_SAMPLING_CONCENTRIC_MAPPING_INCLUDED_ #define _NBL_BUILTIN_HLSL_SAMPLING_CONCENTRIC_MAPPING_INCLUDED_ @@ -8,30 +12,32 @@ namespace nbl { namespace hlsl { +namespace sampling +{ template vector concentricMapping(vector _u) { //map [0;1]^2 to [-1;1]^2 - vector u = 2.0f * _u - 1.0f; + vector u = 2.0f * _u - hlsl::promote >(1.0); vector p; #ifdef __HLSL_VERSION - if (nbl::hlsl::all >(u == (vector)(0.0))) + if (nbl::hlsl::all >(u == hlsl::promote >(0.0))) #else - if (u == (vector)(0.0)) + if (u == hlsl::promote >(0.0)) #endif - p = (vector)(0.0); + p = hlsl::promote >(0.0); else { T r; T theta; if (abs(u.x) > abs(u.y)) { r = u.x; - theta = 0.25 * numbers::pi * (u.y / u.x); + theta = 0.25 * numbers::pi * (u.y / u.x); } else { r = u.y; - theta = 0.5 * numbers::pi - 0.25 * numbers::pi * (u.x / u.y); + theta = 0.5 * numbers::pi - 0.25 * numbers::pi * (u.x / u.y); } p = r * vector(cos(theta), sin(theta)); @@ -40,6 +46,7 @@ vector concentricMapping(vector _u) return p; } +} } } diff --git a/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl b/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl index 4f2989d0f9..24aa041e14 100644 --- a/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl +++ b/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl @@ -7,15 +7,16 @@ #include "nbl/builtin/hlsl/concepts.hlsl" #include "nbl/builtin/hlsl/sampling/concentric_mapping.hlsl" +#include "nbl/builtin/hlsl/bxdf/common.hlsl" namespace nbl { namespace hlsl { - -namespace impl +namespace sampling { -template + +template) struct ProjectedHemisphere { using vector_t2 = vector; @@ -23,8 +24,8 @@ struct ProjectedHemisphere static vector_t3 generate(vector_t2 _sample) { - vector_t2 p = concentricMapping(_sample * 0.99999f + 0.000005f); - T z = sqrt(max(0.0, 1.0 - p.x * p.x - p.y * p.y)); + vector_t2 p = concentricMapping(_sample * T(0.99999) + T(0.000005)); + T z = hlsl::sqrt(hlsl::max(T(0.0), T(1.0) - p.x * p.x - p.y * p.y)); return vector_t3(p.x, p.y, z); } @@ -33,74 +34,56 @@ struct ProjectedHemisphere return L_z * numbers::inv_pi; } - static T quotient_and_pdf(NBL_REF_ARG(T) _pdf, T L) + template + static bxdf::quotient_and_pdf quotient_and_pdf(T L) { - _pdf = pdf(L); - return 1.0; + return bxdf::quotient_and_pdf::create(hlsl::promote(1.0), pdf(L)); } -}; -} - -// probably could've split into separate structs and ProjectedSphere inherit ProjectedHemisphere -template) -vector projected_hemisphere_generate(vector _sample) -{ - return impl::ProjectedHemisphere::generate(_sample); -} - -template) -T projected_hemisphere_pdf(T L_z) -{ - return impl::ProjectedHemisphere::pdf(L_z); -} -template) -T projected_hemisphere_quotient_and_pdf(NBL_REF_ARG(T) pdf, T L) -{ - return impl::ProjectedHemisphere::quotient_and_pdf(pdf, L); -} + template + static bxdf::quotient_and_pdf quotient_and_pdf(vector_t3 L) + { + return quotient_and_pdf(L.z); + } +}; template) -T projected_hemisphere_quotient_and_pdf(NBL_REF_ARG(T) pdf, vector L) +struct ProjectedSphere { - return impl::ProjectedHemisphere::quotient_and_pdf(pdf, L.z); -} + using vector_t2 = vector; + using vector_t3 = vector; + using hemisphere_t = ProjectedHemisphere; + static vector_t3 generate(vector_t2 _sample) + { + vector_t3 retval = hemisphere_t::generate(_sample.xy); + const bool chooseLower = _sample.z > T(0.5); + retval.z = chooseLower ? (-retval.z) : retval.z; + if (chooseLower) + _sample.z -= T(0.5); + _sample.z *= T(2.0); + return retval; + } -template) -vector projected_sphere_generate(vector _sample) -{ - vector retval = impl::ProjectedHemisphere::generate(_sample.xy); - const bool chooseLower = _sample.z > 0.5; - retval.z = chooseLower ? (-retval.z) : retval.z; - if (chooseLower) - _sample.z -= 0.5f; - _sample.z *= 2.f; - return retval; -} + static T pdf(T L_z) + { + return T(0.5) * hemisphere_t::pdf(L_z); + } -template) -T projected_sphere_pdf(T L_z) -{ - return 0.5 * impl::ProjectedHemisphere::pdf(L_z); -} + template + static bxdf::quotient_and_pdf quotient_and_pdf(T L) + { + return bxdf::quotient_and_pdf::create(hlsl::promote(1.0), pdf(L)); + } -template) -T projected_sphere_quotient_and_pdf(NBL_REF_ARG(T) pdf, T L) -{ - T retval = impl::ProjectedHemisphere::quotient_and_pdf(pdf, L); - pdf *= 0.5; - return retval; + template + static bxdf::quotient_and_pdf quotient_and_pdf(vector_t3 L) + { + return quotient_and_pdf(L.z); + } } -template) -T projected_sphere_quotient_and_pdf(NBL_REF_ARG(T) pdf, vector L) -{ - T retval = impl::ProjectedHemisphere::quotient_and_pdf(pdf, L.z); - pdf *= 0.5; - return retval; } - } } diff --git a/include/nbl/builtin/hlsl/sampling/uniform.hlsl b/include/nbl/builtin/hlsl/sampling/uniform.hlsl index f52fcedaa5..2c6f6c233f 100644 --- a/include/nbl/builtin/hlsl/sampling/uniform.hlsl +++ b/include/nbl/builtin/hlsl/sampling/uniform.hlsl @@ -1,4 +1,4 @@ -// Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O. +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h @@ -13,10 +13,10 @@ namespace nbl { namespace hlsl { - -namespace impl +namespace sampling { -template + +template) struct UniformHemisphere { using vector_t2 = vector; @@ -25,14 +25,14 @@ struct UniformHemisphere static vector_t3 generate(vector_t2 _sample) { T z = _sample.x; - T r = sqrt(max(0.0, 1.0 - z * z)); - T phi = 2.0 * numbers::pi * _sample.y; - return vector_t3(r * cos(phi), r * sin(phi), z); + T r = hlsl::sqrt(hlsl::max(T(0.0), T(1.0) - z * z)); + T phi = T(2.0) * numbers::pi * _sample.y; + return vector_t3(r * hlsl::cos(phi), r * hlsl::sin(phi), z); } static T pdf() { - return 1.0 / (2.0 * numbers::pi); + return T(1.0) / (T(2.0) * numbers::pi); } }; @@ -44,43 +44,19 @@ struct UniformSphere static vector_t3 generate(vector_t2 _sample) { - T z = 1 - 2 * _sample.x; - T r = sqrt(max(0.0, 1.0 - z * z)); - T phi = 2.0 * numbers::pi * _sample.y; - return vector_t3(r * cos(phi), r * sin(phi), z); + T z = T(1.0) - T(2.0) * _sample.x; + T r = hlsl::sqrt(hlsl::max(T(0.0), T(1.0) - z * z)); + T phi = T(2.0) * numbers::pi * _sample.y; + return vector_t3(r * hlsl::cos(phi), r * hlsl::sin(phi), z); } static T pdf() { - return 1.0 / (4.0 * numbers::pi); + return T(1.0) / (T(4.0) * numbers::pi); } }; } -template) -vector uniform_hemisphere_generate(vector _sample) -{ - return impl::UniformHemisphere::generate(_sample); -} - -template) -T uniform_hemisphere_pdf() -{ - return impl::UniformHemisphere::pdf(); -} - -template) -vector uniform_sphere_generate(vector _sample) -{ - return impl::UniformSphere::generate(_sample); -} - -template) -T uniform_sphere_pdf() -{ - return impl::UniformSphere::pdf(); -} - } } From b2b77945d623a3e08b63b95223df92d20eab3248 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 2 Apr 2025 17:12:51 +0700 Subject: [PATCH 083/188] new equal func for vectors --- examples_tests | 2 +- .../nbl/builtin/hlsl/glsl_compat/core.hlsl | 65 +++++++++++++++++++ .../hlsl/sampling/concentric_mapping.hlsl | 7 +- .../builtin/hlsl/sampling/cos_weighted.hlsl | 4 +- .../builtin/hlsl/spirv_intrinsics/core.hlsl | 9 +++ 5 files changed, 79 insertions(+), 8 deletions(-) diff --git a/examples_tests b/examples_tests index 01bfc9b0e6..37326879c9 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 01bfc9b0e67b152517eb5612e7a4ee2e402dca66 +Subproject commit 37326879c97a2df27c3ce21cebcaa2580501175c diff --git a/include/nbl/builtin/hlsl/glsl_compat/core.hlsl b/include/nbl/builtin/hlsl/glsl_compat/core.hlsl index 337db5e22f..a2ae13df23 100644 --- a/include/nbl/builtin/hlsl/glsl_compat/core.hlsl +++ b/include/nbl/builtin/hlsl/glsl_compat/core.hlsl @@ -8,6 +8,9 @@ #include "nbl/builtin/hlsl/spirv_intrinsics/core.hlsl" #include "nbl/builtin/hlsl/type_traits.hlsl" #include "nbl/builtin/hlsl/spirv_intrinsics/glsl.std.450.hlsl" +#include "nbl/builtin/hlsl/concepts/core.hlsl" +#include "nbl/builtin/hlsl/concepts/vector.hlsl" +#include "nbl/builtin/hlsl/concepts/matrix.hlsl" namespace nbl { @@ -234,6 +237,68 @@ T bitfieldReverse(T value) #endif +namespace impl +{ +template +struct equal_helper; + +#ifdef __HLSL_VERSION + +template +NBL_PARTIAL_REQ_TOP(concepts::Vectorial && concepts::Integral) +struct equal_helper && concepts::Integral) > +{ + using return_t = vector::Dimension>; + + static return_t __call(const Vectorial lhs, const Vectorial rhs) + { + return spirv::IEqual(lhs, rhs); + } +}; + +template +NBL_PARTIAL_REQ_TOP(concepts::Vectorial && concepts::FloatingPoint) +struct equal_helper && concepts::FloatingPoint) > +{ + using return_t = vector::Dimension>; + + static return_t __call(const Vectorial lhs, const Vectorial rhs) + { + return spirv::FOrdEqual(lhs, rhs); + } +}; + +#else + +template +NBL_PARTIAL_REQ_TOP(concepts::Vectorial) +struct equal_helper) > +{ + using return_t = vector::Dimension>; + + static return_t __call(const Vectorial lhs, const Vectorial rhs) + { + using traits = hlsl::vector_traits; + array_get getter; + array_set setter; + + return_t output; + for (uint32_t i = 0; i < traits::Dimension; ++i) + setter(output, i, getter(lhs, i) == getter(rhs, i)); + + return output; + } +}; + +#endif +} + +template +inline T equal(NBL_CONST_REF_ARG(T) x, NBL_CONST_REF_ARG(T) y) +{ + return impl::equal_helper::__call(x, y); +} + } } } diff --git a/include/nbl/builtin/hlsl/sampling/concentric_mapping.hlsl b/include/nbl/builtin/hlsl/sampling/concentric_mapping.hlsl index 6bfea6c03b..1a5c96b6df 100644 --- a/include/nbl/builtin/hlsl/sampling/concentric_mapping.hlsl +++ b/include/nbl/builtin/hlsl/sampling/concentric_mapping.hlsl @@ -5,6 +5,7 @@ #ifndef _NBL_BUILTIN_HLSL_SAMPLING_CONCENTRIC_MAPPING_INCLUDED_ #define _NBL_BUILTIN_HLSL_SAMPLING_CONCENTRIC_MAPPING_INCLUDED_ +#include "nbl/builtin/hlsl/glsl_compat/core.hlsl" #include "nbl/builtin/hlsl/tgmath.hlsl" #include "nbl/builtin/hlsl/math/functions.hlsl" @@ -22,11 +23,7 @@ vector concentricMapping(vector _u) vector u = 2.0f * _u - hlsl::promote >(1.0); vector p; - #ifdef __HLSL_VERSION - if (nbl::hlsl::all >(u == hlsl::promote >(0.0))) - #else - if (u == hlsl::promote >(0.0)) - #endif + if (hlsl::all >(glsl::equal(u, hlsl::promote >(0.0)))) p = hlsl::promote >(0.0); else { diff --git a/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl b/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl index 24aa041e14..78b30cbc62 100644 --- a/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl +++ b/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl @@ -54,7 +54,7 @@ struct ProjectedSphere using vector_t3 = vector; using hemisphere_t = ProjectedHemisphere; - static vector_t3 generate(vector_t2 _sample) + static vector_t3 generate(vector_t3 _sample) { vector_t3 retval = hemisphere_t::generate(_sample.xy); const bool chooseLower = _sample.z > T(0.5); @@ -81,7 +81,7 @@ struct ProjectedSphere { return quotient_and_pdf(L.z); } -} +}; } } diff --git a/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl b/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl index 2ef3e17871..88daa477ac 100644 --- a/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl +++ b/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl @@ -346,6 +346,15 @@ template) [[vk::ext_instruction(spv::OpISubBorrow)]] SubBorrowOutput subBorrow(T operand1, T operand2); + +template && !is_matrix_v) +[[vk::ext_instruction(spv::OpIEqual)]] +conditional_t, vector::Dimension>, bool> IEqual(T lhs, T rhs); + +template && !is_matrix_v) +[[vk::ext_instruction(spv::OpFOrdEqual)]] +conditional_t, vector::Dimension>, bool> FOrdEqual(T lhs, T rhs); + } #endif From bc68c223fc761d999c58e504bd3d348e4b97a24d Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 3 Apr 2025 14:28:38 +0700 Subject: [PATCH 084/188] refactor fresnel funcs usage --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 12 +- include/nbl/builtin/hlsl/bxdf/fresnel.hlsl | 299 +++++++++++++----- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 27 +- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 102 +++--- 4 files changed, 295 insertions(+), 145 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 1c3f698b8b..74874ba100 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -108,15 +108,16 @@ struct SBasic SBasic reflect(NBL_CONST_REF_ARG(vector3_type) N, scalar_type directionDotN) { SBasic retval; - retval.direction = bxdf::reflect(direction,N,directionDotN); + bxdf::Reflect r = bxdf::Reflect::create(direction,N,directionDotN); + retval.direction = r(); return retval; } SBasic refract(NBL_CONST_REF_ARG(vector3_type) N, scalar_type eta) { SBasic retval; - bxdf::refract r = bxdf::refract::create(direction,N,eta); - retval.direction = r.doRefract(); + bxdf::Refract r = bxdf::Refract::create(direction,N,eta); + retval.direction = r(); return retval; } @@ -548,13 +549,12 @@ struct SIsotropicMicrofacetCache const scalar_type NdotL = _sample.NdotL; const bool transmitted = isTransmissionPath(NdotV,NdotL); - scalar_type orientedEta, rcpOrientedEta; - const bool backside = bxdf::getOrientedEtas(orientedEta,rcpOrientedEta,NdotV,eta); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(NdotV, eta); const vector3_type V = interaction.V.getDirection(); const vector3_type L = _sample.L.direction; const scalar_type VdotL = nbl::hlsl::dot(V, L); - return compute(retval,transmitted,V,L,interaction.N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); + return compute(retval,transmitted,V,L,interaction.N,NdotL,VdotL,orientedEta.value,orientedEta.rcp,H); } template && ray_dir_info::Basic) static bool compute( diff --git a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl index a7f77dd4ac..211b2e1bf0 100644 --- a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl @@ -17,55 +17,110 @@ namespace hlsl namespace bxdf { -namespace impl +namespace fresnel { -template -struct orientedEtas; -template<> -struct orientedEtas +template || is_vector_v) +struct OrientedEtas { - static bool __call(NBL_REF_ARG(float) orientedEta, NBL_REF_ARG(float) rcpOrientedEta, float NdotI, float eta) + using scalar_type = typename vector_traits::scalar_type; + + static OrientedEtas create(scalar_type NdotI, T eta) + { + OrientedEtas retval; + retval.backside = NdotI < hlsl::promote(0.0); + const T rcpEta = hlsl::promote(1.0) / eta; + retval.value = retval.backside ? rcpEta : eta; + retval.rcp = retval.backside ? eta : rcpEta; + return retval; + } + + static T diffuseFresnelCorrectionFactor(T n, T n2) { - const bool backside = NdotI < 0.0; - const float rcpEta = 1.0 / eta; - orientedEta = backside ? rcpEta : eta; - rcpOrientedEta = backside ? eta : rcpEta; - return backside; + // assert(n*n==n2); + vector::Dimension> TIR = n < (T)1.0; + T invdenum = nbl::hlsl::mix((T)1.0, (T)1.0 / (n2 * n2 * ((T)554.33 - 380.7 * n)), TIR); + T num = n * nbl::hlsl::mix((T)(0.1921156102251088), n * 298.25 - 261.38 * n2 + 138.43, TIR); + num += nbl::hlsl::mix((T)(0.8078843897748912), (T)(-1.67), TIR); + return num * invdenum; } + + T value; + T rcp; + bool backside; }; -template<> -struct orientedEtas +template || is_vector_v) +struct OrientedEtaRcps { - static bool __call(NBL_REF_ARG(float32_t3) orientedEta, NBL_REF_ARG(float32_t3) rcpOrientedEta, float NdotI, float32_t3 eta) + using scalar_type = typename vector_traits::scalar_type; + + static OrientedEtaRcps create(scalar_type NdotI, T eta) { - const bool backside = NdotI < 0.0; - const float32_t3 rcpEta = (float32_t3)1.0 / eta; - orientedEta = backside ? rcpEta:eta; - rcpOrientedEta = backside ? eta:rcpEta; - return backside; + OrientedEtaRcps retval; + retval.backside = NdotI < hlsl::promote(0.0); + const T rcpEta = hlsl::promote(1.0) / eta; + retval.value = retval.backside ? eta : rcpEta; + retval.value2 = retval.value * retval.value; + return retval; } + + static T diffuseFresnelCorrectionFactor(T n, T n2) + { + return OrientedEtas::diffuseFresnelCorrectionFactor(n, n2); + } + + T value; + T value2; + bool backside; }; + } -template || is_vector_v) -bool getOrientedEtas(NBL_REF_ARG(T) orientedEta, NBL_REF_ARG(T) rcpOrientedEta, scalar_type_t NdotI, T eta) +template && vector_traits::Dimension == 3) +struct Reflect { - return impl::orientedEtas::__call(orientedEta, rcpOrientedEta, NdotI, eta); -} + using this_t = Reflect; + using vector_type = T; + using scalar_type = typename vector_traits::scalar_type; + static this_t computeNdotI(NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N) + { + return hlsl::dot(N, I); + } -template) -T reflect(NBL_CONST_REF_ARG(T) I, NBL_CONST_REF_ARG(T) N, typename vector_traits::scalar_type NdotI) -{ - return N * 2.0f * NdotI - I; -} + static this_t create(NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N, scalar_type NdotI) + { + this_t retval; + retval.I = I; + retval.N = N; + retval.NdotI = NdotI; + return retval; + } + + static this_t create(NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N) + { + this_t retval; + retval.I = I; + retval.N = N; + retval.NdotI = computeNdotI(I, N); + return retval; + } + + vector_type operator()() + { + return N * 2.0f * NdotI - I; + } + + vector_type I; + vector_type N; + scalar_type NdotI; +}; -template::Dimension == 3) -struct refract +template && vector_traits::Dimension == 3) +struct Refract { - using this_t = refract; + using this_t = Refract; using vector_type = T; using scalar_type = typename vector_traits::scalar_type; @@ -87,10 +142,11 @@ struct refract this_t retval; retval.I = I; retval.N = N; - scalar_type orientedEta; - retval.backside = getOrientedEtas(orientedEta, retval.rcpOrientedEta, NdotI, eta); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(NdotI, eta); + retval.backside = orientedEta.backside; retval.NdotI = NdotI; retval.NdotI2 = NdotI * NdotI; + retval.rcpOrientedEta = orientedEta.rcp; retval.rcpOrientedEta2 = retval.rcpOrientedEta * retval.rcpOrientedEta; return retval; } @@ -101,9 +157,10 @@ struct refract retval.I = I; retval.N = N; retval.NdotI = dot(N, I); - scalar_type orientedEta; - retval.backside = getOrientedEtas(orientedEta, retval.rcpOrientedEta, retval.NdotI, eta); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(retval.NdotI, eta); + retval.backside = orientedEta.backside; retval.NdotI2 = retval.NdotI * retval.NdotI; + retval.rcpOrientedEta = orientedEta.rcp; retval.rcpOrientedEta2 = retval.rcpOrientedEta * retval.rcpOrientedEta; return retval; } @@ -115,46 +172,108 @@ struct refract return backside ? absNdotT : -(absNdotT); } - vector_type doRefract() + vector_type operator()() { return N * (NdotI * rcpOrientedEta + computeNdotT(backside, NdotI2, rcpOrientedEta2)) - rcpOrientedEta * I; } - static vector_type doReflectRefract(bool _refract, NBL_CONST_REF_ARG(vector_type) _I, NBL_CONST_REF_ARG(vector_type) _N, scalar_type _NdotI, scalar_type _NdotTorR, scalar_type _rcpOrientedEta) + vector_type I; + vector_type N; + bool backside; + scalar_type NdotI; + scalar_type NdotI2; + scalar_type rcpOrientedEta; + scalar_type rcpOrientedEta2; +}; + +template && vector_traits::Dimension == 3) +struct ReflectRefract +{ + using this_t = ReflectRefract; + using vector_type = T; + using scalar_type = typename vector_traits::scalar_type; + + static this_t create(bool refract, NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N, scalar_type NdotI, scalar_type NdotTorR, scalar_type rcpOrientedEta) + { + this_t retval; + retval.refract = refract; + retval.I = I; + retval.N = N; + retval.NdotI = NdotI; + retval.NdotTorR = NdotTorR; + retval.rcpOrientedEta = rcpOrientedEta; + return retval; + } + + static this_t create(bool r, NBL_CONST_REF_ARG(Refract) refract) { - return _N * (_NdotI * (_refract ? _rcpOrientedEta : 1.0f) + _NdotTorR) - _I * (_refract ? _rcpOrientedEta : 1.0f); + this_t retval; + retval.refract = r; + retval.I = refract.I; + retval.N = refract.N; + retval.NdotI = refract.NdotI; + retval.NdotTorR = r ? Refract::computeNdotT(refract.backside, refract.NdotI2, refract.rcpOrientedEta2) : refract.NdotI; + retval.rcpOrientedEta = refract.rcpOrientedEta; + return retval; } - vector_type doReflectRefract(bool r) + vector_type operator()() { - const scalar_type NdotTorR = r ? computeNdotT(backside, NdotI2, rcpOrientedEta2) : NdotI; - return doReflectRefract(r, I, N, NdotI, NdotTorR, rcpOrientedEta); + return N * (NdotI * (refract ? rcpOrientedEta : 1.0f) + NdotTorR) - I * (refract ? rcpOrientedEta : 1.0f); } + bool refract; vector_type I; vector_type N; - bool backside; scalar_type NdotI; - scalar_type NdotI2; + scalar_type NdotTorR; scalar_type rcpOrientedEta; - scalar_type rcpOrientedEta2; }; +namespace fresnel +{ + template || is_vector_v) -struct fresnel +struct Schlick { - using scalar_t = typename scalar_type::type; + using scalar_type = typename vector_traits::scalar_type; + + static Schlick create(NBL_CONST_REF_ARG(T) F0, scalar_type VdotH) + { + Schlick retval; + retval.F0 = F0; + retval.VdotH = VdotH; + return retval; + } - static T schlick(NBL_CONST_REF_ARG(T) F0, scalar_t VdotH) + T operator()() { T x = 1.0 - VdotH; return F0 + (1.0 - F0) * x*x*x*x*x; } - static T conductor(NBL_CONST_REF_ARG(T) eta, NBL_CONST_REF_ARG(T) etak, scalar_t cosTheta) + T F0; + scalar_type VdotH; +}; + +template || is_vector_v) +struct Conductor +{ + using scalar_type = typename vector_traits::scalar_type; + + static Conductor create(NBL_CONST_REF_ARG(T) eta, NBL_CONST_REF_ARG(T) etak, scalar_type cosTheta) { - const scalar_t cosTheta2 = cosTheta * cosTheta; + Conductor retval; + retval.eta = eta; + retval.etak = etak; + retval.cosTheta = cosTheta; + return retval; + } + + T operator()() + { + const scalar_type cosTheta2 = cosTheta * cosTheta; //const float sinTheta2 = 1.0 - cosTheta2; const T etaLen2 = eta * eta + etak * etak; @@ -169,13 +288,32 @@ struct fresnel return (rs2 + rp2) * 0.5f; } - static T dielectric_common(NBL_CONST_REF_ARG(T) orientedEta2, scalar_t absCosTheta) + T eta; + T etak; + scalar_type cosTheta; +}; + +template || is_vector_v) +struct Dielectric +{ + using scalar_type = typename vector_traits::scalar_type; + + static Dielectric create(NBL_CONST_REF_ARG(T) eta, scalar_type cosTheta) { - const scalar_t sinTheta2 = 1.0 - absCosTheta * absCosTheta; + Dielectric retval; + OrientedEtas orientedEta = OrientedEtas::create(cosTheta, eta); + retval.eta2 = orientedEta.value * orientedEta.value; + retval.cosTheta = cosTheta; + return retval; + } + + static T __call(NBL_CONST_REF_ARG(T) orientedEta2, scalar_type absCosTheta) + { + const scalar_type sinTheta2 = 1.0 - absCosTheta * absCosTheta; // the max() clamping can handle TIR when orientedEta2<1.0 - const T t0 = nbl::hlsl::sqrt(nbl::hlsl::max((T)(orientedEta2) - sinTheta2, (T)(0.0))); - const T rs = ((T)(absCosTheta) - t0) / ((T)(absCosTheta) + t0); + const T t0 = hlsl::sqrt(hlsl::max(orientedEta2 - sinTheta2, hlsl::promote(0.0))); + const T rs = (hlsl::promote(absCosTheta) - t0) / (hlsl::promote(absCosTheta) + t0); const T t2 = orientedEta2 * absCosTheta; const T rp = (t0 - t2) / (t0 + t2); @@ -183,50 +321,49 @@ struct fresnel return (rs * rs + rp * rp) * 0.5f; } - static T dielectricFrontFaceOnly(NBL_CONST_REF_ARG(T) orientedEta2, scalar_t absCosTheta) + T operator()() + { + return __call(eta2, cosTheta); + } + + T eta2; + scalar_type cosTheta; +}; + +template || is_vector_v) +struct DielectricFrontFaceOnly +{ + using scalar_type = typename vector_traits::scalar_type; + + static DielectricFrontFaceOnly create(NBL_CONST_REF_ARG(T) orientedEta2, scalar_type absCosTheta) { - return dielectric_common(orientedEta2, absCosTheta); + Dielectric retval; + retval.orientedEta2 = orientedEta2; + retval.absCosTheta = hlsl::abs(absCosTheta); + return retval; } - static T dielectric(NBL_CONST_REF_ARG(T) eta, scalar_t cosTheta) + T operator()() { - T orientedEta, rcpOrientedEta; - bxdf::getOrientedEtas(orientedEta, rcpOrientedEta, cosTheta, eta); - return dielectric_common(orientedEta * orientedEta, cosTheta); + return Dielectric::__call(orientedEta2, absCosTheta); } + + T orientedEta2; + scalar_type absCosTheta; }; -namespace impl -{ + // gets the sum of all R, T R T, T R^3 T, T R^5 T, ... paths template struct ThinDielectricInfiniteScatter { - using scalar_t = typename scalar_type::type; - - static T __call(T singleInterfaceReflectance) + T operator()(T singleInterfaceReflectance) { const T doubleInterfaceReflectance = singleInterfaceReflectance * singleInterfaceReflectance; - return nbl::hlsl::mix((singleInterfaceReflectance - doubleInterfaceReflectance) / ((T)(1.0) - doubleInterfaceReflectance) * 2.0f, (T)(1.0), doubleInterfaceReflectance > (T)(0.9999)); + return hlsl::mix((singleInterfaceReflectance - doubleInterfaceReflectance) / (hlsl::promote(1.0) - doubleInterfaceReflectance) * 2.0f, hlsl::promote(1.0), doubleInterfaceReflectance > hlsl::promote(0.9999)); } }; -} -template || is_vector_v) -T thindielectricInfiniteScatter(T singleInterfaceReflectance) -{ - return impl::ThinDielectricInfiniteScatter::__call(singleInterfaceReflectance); -} - -template || is_vector_v) -T diffuseFresnelCorrectionFactor(T n, T n2) -{ - // assert(n*n==n2); - vector::Dimension> TIR = n < (T)1.0; - T invdenum = nbl::hlsl::mix((T)1.0, (T)1.0 / (n2 * n2 * ((T)554.33 - 380.7 * n)), TIR); - T num = n * nbl::hlsl::mix((T)(0.1921156102251088), n * 298.25 - 261.38 * n2 + 138.43, TIR); - num += nbl::hlsl::mix((T)(0.8078843897748912), (T)(-1.67), TIR); - return num * invdenum; } } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 8c5b2c5718..b500848d56 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -268,7 +268,8 @@ struct SBlinnPhongBxDF scalar_part = __eval_DG_wo_clamps(params, a2); } ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotV); - return fresnel::conductor(ior0, ior1, params.VdotH) * microfacet_transform(); + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.VdotH); + return f() * microfacet_transform(); } vector3_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) @@ -310,7 +311,8 @@ struct SBlinnPhongBxDF cache = anisocache_type::create(localV, H); ray_dir_info_type localL; - localL.direction = bxdf::reflect(localV, H, cache.iso_cache.VdotH); + bxdf::Reflect r = bxdf::Reflect::create(localV, H, cache.iso_cache.VdotH); + localL.direction = r(); return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); } @@ -414,7 +416,8 @@ struct SBeckmannBxDF { scalar_type scalar_part = __eval_DG_wo_clamps(params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.uNdotV); - return fresnel::conductor(ior0, ior1, params.VdotH) * microfacet_transform(); + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.VdotH); + return f() * microfacet_transform(); } else return (spectral_type)0.0; @@ -495,7 +498,8 @@ struct SBeckmannBxDF cache = anisocache_type::create(localV, H); ray_dir_info_type localL; - localL.direction = bxdf::reflect(localV, H, cache.iso_cache.VdotH); + bxdf::Reflect r = bxdf::Reflect::create(localV, H, cache.iso_cache.VdotH); + localL.direction = r(); return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); } @@ -553,7 +557,8 @@ struct SBeckmannBxDF smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(A.x*A.x, params.NdotV2, params.NdotL2, onePlusLambda_V); G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); } - const spectral_type reflectance = fresnel::conductor(ior0, ior1, params.VdotH); + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.VdotH); + const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; } @@ -657,7 +662,8 @@ struct SGGXBxDF { scalar_type scalar_part = __eval_DG_wo_clamps(params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotL); - return fresnel::conductor(ior0, ior1, params.VdotH) * microfacet_transform(); + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.VdotH); + return f() * microfacet_transform(); } else return (spectral_type)0.0; @@ -692,7 +698,8 @@ struct SGGXBxDF cache = anisocache_type::create(localV, H); ray_dir_info_type localL; - localL.direction = bxdf::reflect(localV, H, cache.iso_cache.VdotH); + bxdf::Reflect r = bxdf::Reflect::create(localV, H, cache.iso_cache.VdotH); + localL.direction = r(); return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); } @@ -748,7 +755,8 @@ struct SGGXBxDF smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.uNdotV, params.NdotV2, params.uNdotL, params.NdotL2); G2_over_G1 = ggx_smith.G2_over_G1(smithparams); } - const spectral_type reflectance = fresnel::conductor(ior0, ior1, params.VdotH); + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.VdotH); + const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; } @@ -761,6 +769,9 @@ struct SGGXBxDF } } +// After Clang-HLSL introduces https://en.cppreference.com/w/cpp/language/namespace_alias +// namespace brdf = bxdf::reflection; + } } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index ccd0ae9b49..617bb12550 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -152,33 +152,32 @@ struct SSmoothDielectricBxDF sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N, bool backside, scalar_type NdotV, scalar_type absNdotV, scalar_type NdotV2, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(bool) transmitted) { - const scalar_type reflectance = fresnel::dielectric_common(orientedEta2, absNdotV); + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, absNdotV); scalar_type rcpChoiceProb; transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); ray_dir_info_type L; - refract r = refract::create(V, N, backside, NdotV, NdotV2, rcpOrientedEta, rcpOrientedEta2); - L.direction = r.doReflectRefract(transmitted); + Refract r = Refract::create(V, N, backside, NdotV, NdotV2, rcpOrientedEta, rcpOrientedEta2); + bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, r); + L.direction = rr(); return sample_type::create(L, nbl::hlsl::dot(V, L.direction), T, B, N); } sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector) u) { - scalar_type orientedEta, rcpOrientedEta; - const bool backside = bxdf::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.isotropic.NdotV, eta); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.NdotV, eta); bool dummy; - return __generate_wo_clamps(interaction.isotropic.V.direction, interaction.T, interaction.B, interaction.isotropic.N, backside, interaction.isotropic.NdotV, - interaction.isotropic.NdotV, interaction.isotropic.NdotV*interaction.isotropic.NdotV, u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, dummy); + return __generate_wo_clamps(interaction.isotropic.V.direction, interaction.T, interaction.B, interaction.isotropic.N, orientedEta.backside, interaction.isotropic.NdotV, + interaction.isotropic.NdotV, interaction.isotropic.NdotV*interaction.isotropic.NdotV, u, orientedEta.rcp, orientedEta.value*orientedEta.value, orientedEta.rcp*orientedEta.rcp, dummy); } sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector) u) { - scalar_type orientedEta, rcpOrientedEta; - const bool backside = bxdf::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.isotropic.NdotV, eta); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.NdotV, eta); bool dummy; - return __generate_wo_clamps(interaction.isotropic.V.direction, interaction.T, interaction.B, interaction.isotropic.N, backside, interaction.isotropic.NdotV, - nbl::hlsl::abs(interaction.isotropic.NdotV), interaction.isotropic.NdotV*interaction.isotropic.NdotV, u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, dummy); + return __generate_wo_clamps(interaction.isotropic.V.direction, interaction.T, interaction.B, interaction.isotropic.N, orientedEta.backside, interaction.isotropic.NdotV, + nbl::hlsl::abs(interaction.isotropic.NdotV), interaction.isotropic.NdotV*interaction.isotropic.NdotV, u, orientedEta.rcp, orientedEta.value*orientedEta.value, orientedEta.rcp*orientedEta.rcp, dummy); } // eval and pdf return 0 because smooth dielectric/conductor BxDFs are dirac delta distributions, model perfectly specular objects that scatter light to only one outgoing direction @@ -191,11 +190,10 @@ struct SSmoothDielectricBxDF { const bool transmitted = isTransmissionPath(params.uNdotV, params.uNdotL); - scalar_type dummy, rcpOrientedEta; - const bool backside = bxdf::getOrientedEtas(dummy, rcpOrientedEta, params.NdotV, eta); + fresnel::OrientedEtaRcps rcpOrientedEtas = fresnel::OrientedEtaRcps::create(params.NdotV, eta); const scalar_type _pdf = bit_cast(numeric_limits::infinity); - scalar_type quo = transmitted ? rcpOrientedEta : 1.0; + scalar_type quo = transmitted ? rcpOrientedEtas.value : 1.0; return quotient_pdf_type::create((spectral_type)(quo), _pdf); } @@ -250,7 +248,8 @@ struct SSmoothDielectricBxDF sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N, scalar_type NdotV, scalar_type absNdotV, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(spectral_type) eta2, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint, NBL_REF_ARG(spectral_type) remainderMetadata) { // we will only ever intersect from the outside - const spectral_type reflectance = thindielectricInfiniteScatter(fresnel::dielectric_common(eta2,absNdotV)); + fresnel::ThinDielectricInfiniteScatter scatter; + const spectral_type reflectance = scatter(fresnel::Dielectric::__call(eta2,absNdotV)); // we are only allowed one choice for the entire ray, so make the probability a weighted sum const scalar_type reflectionProb = nbl::hlsl::dot(reflectance, luminosityContributionHint); @@ -284,7 +283,8 @@ struct SSmoothDielectricBxDF quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) // isotropic { const bool transmitted = isTransmissionPath(params.uNdotV, params.uNdotL); - const spectral_type reflectance = thindielectricInfiniteScatter(fresnel::dielectric_common(eta2, params.NdotV)); + fresnel::ThinDielectricInfiniteScatter scatter; + const spectral_type reflectance = scatter(fresnel::Dielectric::__call(eta2, params.NdotV)); const spectral_type sampleValue = transmitted ? ((spectral_type)(1.0) - reflectance) : reflectance; const scalar_type sampleProb = nbl::hlsl::dot(sampleValue,luminosityContributionHint); @@ -348,9 +348,8 @@ struct SBeckmannDielectricBxDF spectral_type eval(NBL_CONST_REF_ARG(params_t) params) { - scalar_type orientedEta, dummy; - const bool backside = bxdf::getOrientedEtas(orientedEta, dummy, params.VdotH, eta); - const scalar_type orientedEta2 = orientedEta * orientedEta; + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.VdotH, eta); + const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; const scalar_type VdotHLdotH = params.VdotH * params.LdotH; const bool transmitted = VdotHLdotH < 0.0; @@ -364,14 +363,15 @@ struct SBeckmannDielectricBxDF const scalar_type scalar_part = beckmann.__eval_DG_wo_clamps(params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,params.NdotV,transmitted,params.VdotH,params.LdotH,VdotHLdotH,orientedEta); - return (spectral_type)fresnel::dielectric_common(orientedEta2, nbl::hlsl::abs(params.VdotH)) * microfacet_transform(); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,params.NdotV,transmitted,params.VdotH,params.LdotH,VdotHLdotH,orientedEta.value); + scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.VdotH)); + return hlsl::promote(f) * microfacet_transform(); } sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) localV, bool backside, NBL_CONST_REF_ARG(vector3_type) H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) { const scalar_type localVdotH = nbl::hlsl::dot(localV,H); - const scalar_type reflectance = fresnel::dielectric_common(orientedEta2,nbl::hlsl::abs(localVdotH)); + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2,nbl::hlsl::abs(localVdotH)); scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); @@ -379,9 +379,10 @@ struct SBeckmannDielectricBxDF cache = anisocache_type::create(localV, H); const scalar_type VdotH = cache.iso_cache.VdotH; - cache.iso_cache.LdotH = transmitted ? refract::computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; + cache.iso_cache.LdotH = transmitted ? Refract::computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; ray_dir_info_type localL; - localL.direction = refract::doReflectRefract(transmitted, localV, H, VdotH, cache.iso_cache.LdotH, rcpOrientedEta); + bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, localV, H, VdotH, cache.iso_cache.LdotH, rcpOrientedEta); + localL.direction = rr(); return sample_type::createFromTangentSpace(localV, localL, m); } @@ -390,16 +391,15 @@ struct SBeckmannDielectricBxDF { const vector3_type localV = interaction.getTangentSpaceV(); - scalar_type orientedEta, rcpOrientedEta; - const bool backside = bxdf::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.isotropic.NdotV, eta); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.NdotV, eta); - const vector3_type upperHemisphereV = backside ? -localV : localV; + const vector3_type upperHemisphereV = orientedEta.backside ? -localV : localV; spectral_type dummyior; reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior, dummyior); const vector3_type H = beckmann.__generate(upperHemisphereV, u.xy); - return __generate_wo_clamps(localV, backside, H, interaction.getFromTangentSpace(), u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, cache); + return __generate_wo_clamps(localV, orientedEta.backside, H, interaction.getFromTangentSpace(), u, orientedEta.rcp, orientedEta.value*orientedEta.value, orientedEta.rcp*orientedEta.rcp, cache); } sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector3_type) u) @@ -410,14 +410,13 @@ struct SBeckmannDielectricBxDF scalar_type pdf(NBL_CONST_REF_ARG(params_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { - scalar_type orientedEta, dummy; - const bool backside = bxdf::getOrientedEtas(orientedEta, dummy, params.VdotH, eta); - const scalar_type orientedEta2 = orientedEta * orientedEta; + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.VdotH, eta); + const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; const scalar_type VdotHLdotH = params.VdotH * params.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnel::dielectric_common(orientedEta2, nbl::hlsl::abs(params.VdotH)); + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.VdotH)); scalar_type ndf, lambda; if (params.is_aniso) @@ -443,7 +442,7 @@ struct SBeckmannDielectricBxDF lambda = beckmann_smith.Lambda(params.NdotV2, a2); } - return smith::VNDF_pdf_wo_clamps >(ndf,lambda,params.NdotV,transmitted,params.VdotH,params.LdotH,VdotHLdotH,orientedEta,reflectance,onePlusLambda_V); + return smith::VNDF_pdf_wo_clamps >(ndf,lambda,params.NdotV,transmitted,params.VdotH,params.LdotH,VdotHLdotH,orientedEta.value,reflectance,onePlusLambda_V); } scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) @@ -529,9 +528,9 @@ struct SGGXDielectricBxDF spectral_type eval(NBL_CONST_REF_ARG(params_t) params) { - scalar_type orientedEta, dummy; - const bool backside = bxdf::getOrientedEtas(orientedEta, dummy, params.VdotH, eta); - const scalar_type orientedEta2 = orientedEta * orientedEta; + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.VdotH, eta); + const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; + const scalar_type VdotHLdotH = params.VdotH * params.LdotH; const bool transmitted = VdotHLdotH < 0.0; @@ -551,14 +550,15 @@ struct SGGXDielectricBxDF } ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,params.NdotL,transmitted,params.VdotH,params.LdotH,VdotHLdotH,orientedEta); - return (spectral_type)fresnel::dielectric_common(orientedEta2, nbl::hlsl::abs(params.VdotH)) * microfacet_transform(); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,params.NdotL,transmitted,params.VdotH,params.LdotH,VdotHLdotH,orientedEta.value); + scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.VdotH)); + return hlsl::promote(f) * microfacet_transform(); } sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) localV, bool backside, NBL_CONST_REF_ARG(vector3_type) H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) { const scalar_type localVdotH = nbl::hlsl::dot(localV,H); - const scalar_type reflectance = fresnel::dielectric_common(orientedEta2,nbl::hlsl::abs(localVdotH)); + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2,nbl::hlsl::abs(localVdotH)); scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); @@ -566,9 +566,10 @@ struct SGGXDielectricBxDF cache = anisocache_type::create(localV, H); const scalar_type VdotH = cache.iso_cache.VdotH; - cache.iso_cache.LdotH = transmitted ? refract::computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; + cache.iso_cache.LdotH = transmitted ? Refract::computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; ray_dir_info_type localL; - localL.direction = refract::doReflectRefract(transmitted, localV, H, VdotH, cache.iso_cache.LdotH, rcpOrientedEta); + bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, localV, H, VdotH, cache.iso_cache.LdotH, rcpOrientedEta); + localL.direction = rr(); return sample_type::createFromTangentSpace(localV, localL, m); } @@ -577,16 +578,15 @@ struct SGGXDielectricBxDF { const vector3_type localV = interaction.getTangentSpaceV(); - scalar_type orientedEta, rcpOrientedEta; - const bool backside = bxdf::getOrientedEtas(orientedEta, rcpOrientedEta, interaction.isotropic.NdotV, eta); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.NdotV, eta); - const vector3_type upperHemisphereV = backside ? -localV : localV; + const vector3_type upperHemisphereV = orientedEta.backside ? -localV : localV; spectral_type dummyior; reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, A.y, dummyior, dummyior); const vector3_type H = ggx.__generate(upperHemisphereV, u.xy); - return __generate_wo_clamps(localV, backside, H, interaction.getFromTangentSpace(), u, rcpOrientedEta, orientedEta*orientedEta, rcpOrientedEta*rcpOrientedEta, cache); + return __generate_wo_clamps(localV, orientedEta.backside, H, interaction.getFromTangentSpace(), u, orientedEta.rcp, orientedEta.value*orientedEta.value, orientedEta.rcp*orientedEta.rcp, cache); } sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector3_type) u) @@ -597,14 +597,13 @@ struct SGGXDielectricBxDF scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) { - scalar_type orientedEta, dummy; - const bool backside = bxdf::getOrientedEtas(orientedEta, dummy, params.VdotH, eta); - const scalar_type orientedEta2 = orientedEta * orientedEta; + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.VdotH, eta); + const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; const scalar_type VdotHLdotH = params.VdotH * params.LdotH; const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnel::dielectric_common(orientedEta2, nbl::hlsl::abs(params.VdotH)); + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.VdotH)); scalar_type ndf, devsh_v; if (params.is_aniso) @@ -632,7 +631,7 @@ struct SGGXDielectricBxDF smith::GGX ggx_smith; const scalar_type lambda = ggx_smith.G1_wo_numerator(params.NdotV, devsh_v); - return smith::VNDF_pdf_wo_clamps(ndf, lambda, params.NdotV, transmitted, params.VdotH, params.LdotH, VdotHLdotH, orientedEta, reflectance); + return smith::VNDF_pdf_wo_clamps(ndf, lambda, params.NdotV, transmitted, params.VdotH, params.LdotH, VdotHLdotH, orientedEta.value, reflectance); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) @@ -664,6 +663,9 @@ struct SGGXDielectricBxDF } } +// After Clang-HLSL introduces https://en.cppreference.com/w/cpp/language/namespace_alias +// namespace bsdf = bxdf::transmission; + } } From 2b8bbbbec58c995286f90838e5cfbd5474682fcb Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 3 Apr 2025 16:35:28 +0700 Subject: [PATCH 085/188] getters for interaction, samples --- examples_tests | 2 +- include/nbl/builtin/hlsl/bxdf/common.hlsl | 140 ++++++++++-------- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 38 ++--- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 58 ++++---- 4 files changed, 128 insertions(+), 110 deletions(-) diff --git a/examples_tests b/examples_tests index 37326879c9..4864a4525e 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 37326879c97a2df27c3ce21cebcaa2580501175c +Subproject commit 4864a4525e998186423f0376c480cda2e71759da diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 74874ba100..b95eccc6a1 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -41,18 +41,13 @@ template) T computeMicrofacetNormal(bool _refract, NBL_CONST_REF_ARG(T) V, NBL_CONST_REF_ARG(T) L, typename vector_traits::scalar_type orientedEta) { const T H = computeUnnormalizedMicrofacetNormal(_refract,V,L,orientedEta); - const typename vector_traits::scalar_type unnormRcpLen = rsqrt::scalar_type>(nbl::hlsl::dot(H,H)); - return H * unnormRcpLen; + return hlsl::normalize(H); } // if V and L are on different sides of the surface normal, then their dot product sign bits will differ, hence XOR will yield 1 at last bit bool isTransmissionPath(float NdotV, float NdotL) { -#ifdef __HLSL_VERSION - return bool((asuint(NdotV) ^ asuint(NdotL)) & 0x80000000u); -#else return bool((bit_cast(NdotV) ^ bit_cast(NdotL)) & 0x80000000u); -#endif } namespace ray_dir_info @@ -65,24 +60,29 @@ namespace ray_dir_info #define NBL_CONCEPT_PARAM_1 (N, typename T::vector3_type) #define NBL_CONCEPT_PARAM_2 (dirDotN, typename T::scalar_type) #define NBL_CONCEPT_PARAM_3 (m, typename T::matrix3x3_type) -NBL_CONCEPT_BEGIN(4) +#define NBL_CONCEPT_PARAM_4 (rfl, Reflect) +#define NBL_CONCEPT_PARAM_5 (rfr, Refract) +NBL_CONCEPT_BEGIN(6) #define rdirinfo NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define N NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define dirDotN NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 #define m NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 +#define rfl NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 +#define rfr NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) ((NBL_CONCEPT_REQ_TYPE)(T::matrix3x3_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.direction), ::nbl::hlsl::is_same_v, typename T::vector3_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.getDirection()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.transmit()), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.reflect(N, dirDotN)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.refract(N, dirDotN)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::transform(m, rdirinfo)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.reflect(rfl)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.refract(rfr)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.transform(m)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(is_scalar_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(is_vector_v, typename T::vector3_type)) ); +#undef rfr +#undef rfl #undef m #undef dirDotN #undef N @@ -105,34 +105,30 @@ struct SBasic return retval; } - SBasic reflect(NBL_CONST_REF_ARG(vector3_type) N, scalar_type directionDotN) + SBasic reflect(NBL_CONST_REF_ARG(Reflect) r) { SBasic retval; - bxdf::Reflect r = bxdf::Reflect::create(direction,N,directionDotN); retval.direction = r(); return retval; } - SBasic refract(NBL_CONST_REF_ARG(vector3_type) N, scalar_type eta) + SBasic refract(NBL_CONST_REF_ARG(Refract) r) { SBasic retval; - bxdf::Refract r = bxdf::Refract::create(direction,N,eta); retval.direction = r(); return retval; } // WARNING: matrix must be orthonormal - static SBasic transform(NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_CONST_REF_ARG(SBasic) r) + SBasic transform(NBL_CONST_REF_ARG(matrix3x3_type) m) NBL_CONST_MEMBER_FUNC { -#ifndef __HLSL__VERSION matrix3x3_type m_T = nbl::hlsl::transpose(m); assert(nbl::hlsl::abs(nbl::hlsl::dot(m_T[0], m_T[1])) < 1e-5); assert(nbl::hlsl::abs(nbl::hlsl::dot(m_T[0], m_T[2])) < 1e-5); assert(nbl::hlsl::abs(nbl::hlsl::dot(m_T[1], m_T[2])) < 1e-5); -#endif SBasic retval; - retval.direction = nbl::hlsl::mul(m, r.direction); + retval.direction = nbl::hlsl::mul(m, direction); return retval; } @@ -160,10 +156,10 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::ray_dir_info_type)) ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.V), ::nbl::hlsl::is_same_v, typename T::ray_dir_info_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.N), ::nbl::hlsl::is_same_v, typename T::vector3_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.NdotV), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.NdotV2), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.getV()), ::nbl::hlsl::is_same_v, typename T::ray_dir_info_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.getN()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.getNdotV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.getNdotV2()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(normV,normN)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(ray_dir_info::Basic, typename T::ray_dir_info_type)) ); @@ -191,6 +187,11 @@ struct SIsotropic return retval; } + RayDirInfo getV() NBL_CONST_MEMBER_FUNC { return V; } + vector3_type getN() NBL_CONST_MEMBER_FUNC { return N; } + scalar_type getNdotV() NBL_CONST_MEMBER_FUNC { return NdotV; } + scalar_type getNdotV2() NBL_CONST_MEMBER_FUNC { return NdotV2; } + RayDirInfo V; vector3_type N; scalar_type NdotV; @@ -213,10 +214,10 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) ((NBL_CONCEPT_REQ_TYPE)(T::matrix3x3_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.T), ::nbl::hlsl::is_same_v, typename T::vector3_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.B), ::nbl::hlsl::is_same_v, typename T::vector3_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.TdotV), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.BdotV), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getT()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getB()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getTdotV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getBdotV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(iso,normT,normT)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getTangentSpaceV()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getToTangentSpace()), ::nbl::hlsl::is_same_v, typename T::matrix3x3_type)) @@ -251,22 +252,27 @@ struct SAnisotropic retval.T = normalizedT; retval.B = normalizedB; - retval.TdotV = nbl::hlsl::dot(retval.isotropic.V.getDirection(), retval.T); - retval.BdotV = nbl::hlsl::dot(retval.isotropic.V.getDirection(), retval.B); + retval.TdotV = nbl::hlsl::dot(retval.isotropic.getV().getDirection(), retval.T); + retval.BdotV = nbl::hlsl::dot(retval.isotropic.getV().getDirection(), retval.B); return retval; } static SAnisotropic create(NBL_CONST_REF_ARG(isotropic_type) isotropic, NBL_CONST_REF_ARG(vector3_type) normalizedT) { - return create(isotropic, normalizedT, cross(isotropic.N, normalizedT)); + return create(isotropic, normalizedT, cross(isotropic.getN(), normalizedT)); } static SAnisotropic create(NBL_CONST_REF_ARG(isotropic_type) isotropic) { vector3_type T, B; - math::frisvad(isotropic.N, T, B); + math::frisvad(isotropic.getN(), T, B); return create(isotropic, nbl::hlsl::normalize(T), nbl::hlsl::normalize(B)); } + vector3_type getT() NBL_CONST_MEMBER_FUNC { return T; } + vector3_type getB() NBL_CONST_MEMBER_FUNC { return B; } + scalar_type getTdotV() NBL_CONST_MEMBER_FUNC { return TdotV; } + scalar_type getBdotV() NBL_CONST_MEMBER_FUNC { return BdotV; } + vector3_type getTangentSpaceV() NBL_CONST_MEMBER_FUNC { return vector3_type(TdotV, BdotV, isotropic.NdotV); } matrix3x3_type getToTangentSpace() NBL_CONST_MEMBER_FUNC { return matrix3x3_type(T, B, isotropic.N); } matrix3x3_type getFromTangentSpace() NBL_CONST_MEMBER_FUNC { return nbl::hlsl::transpose(matrix3x3_type(T, B, isotropic.N)); } @@ -320,12 +326,12 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) ((NBL_CONCEPT_REQ_TYPE)(T::matrix3x3_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.L), ::nbl::hlsl::is_same_v, typename T::ray_dir_info_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.VdotL), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.TdotL), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.BdotL), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.NdotL), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.NdotL2), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getL()), ::nbl::hlsl::is_same_v, typename T::ray_dir_info_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getVdotL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getTdotL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getBdotL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getNdotL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getNdotL2()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createFromTangentSpace(pV,rdirinfo,frame)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(rdirinfo,pVdotL,pV)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(rdirinfo,pVdotL,pV,pV,pV)), ::nbl::hlsl::is_same_v, T)) @@ -366,7 +372,7 @@ struct SLightSample this_t retval; const vector3_type tsL = tangentSpaceL.getDirection(); - retval.L = ray_dir_info_type::transform(tangentFrame, tangentSpaceL); + retval.L = tangentSpaceL.transform(tangentFrame); retval.VdotL = nbl::hlsl::dot(tangentSpaceV, tsL); retval.TdotL = tsL.x; @@ -385,7 +391,7 @@ struct SLightSample retval.TdotL = nbl::hlsl::numeric_limits::quiet_NaN; retval.BdotL = nbl::hlsl::numeric_limits::quiet_NaN; - retval.NdotL = nbl::hlsl::dot(N,L.direction); + retval.NdotL = nbl::hlsl::dot(N,L.getDirection()); retval.NdotL2 = retval.NdotL * retval.NdotL; return retval; @@ -394,8 +400,8 @@ struct SLightSample { this_t retval = create(L,VdotL,N); - retval.TdotL = nbl::hlsl::dot(T,L.direction); - retval.BdotL = nbl::hlsl::dot(B,L.direction); + retval.TdotL = nbl::hlsl::dot(T,L.getDirection()); + retval.BdotL = nbl::hlsl::dot(B,L.getDirection()); return retval; } @@ -420,6 +426,14 @@ struct SLightSample return vector3_type(TdotL, BdotL, NdotL); } + RayDirInfo getL() NBL_CONST_MEMBER_FUNC { return L; } + scalar_type getVdotL() NBL_CONST_MEMBER_FUNC { return VdotL; } + scalar_type getTdotL() NBL_CONST_MEMBER_FUNC { return TdotL; } + scalar_type getBdotL() NBL_CONST_MEMBER_FUNC { return BdotL; } + scalar_type getNdotL() NBL_CONST_MEMBER_FUNC { return NdotL; } + scalar_type getNdotL2() NBL_CONST_MEMBER_FUNC { return NdotL2; } + + RayDirInfo L; scalar_type VdotL; @@ -510,7 +524,7 @@ struct SIsotropicMicrofacetCache NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction, NBL_CONST_REF_ARG(SLightSample) _sample) { - return createForReflection(interaction.NdotV, _sample.NdotL, _sample.VdotL); + return createForReflection(interaction.getNdotV(), _sample.NdotL, _sample.VdotL); } // transmissive cases need to be checked if the path is valid before usage static bool compute( @@ -545,16 +559,16 @@ struct SIsotropicMicrofacetCache const scalar_type eta, NBL_REF_ARG(vector3_type) H ) { - const scalar_type NdotV = interaction.NdotV; + const scalar_type NdotV = interaction.getNdotV(); const scalar_type NdotL = _sample.NdotL; const bool transmitted = isTransmissionPath(NdotV,NdotL); fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(NdotV, eta); - const vector3_type V = interaction.V.getDirection(); + const vector3_type V = interaction.getV().getDirection(); const vector3_type L = _sample.L.direction; const scalar_type VdotL = nbl::hlsl::dot(V, L); - return compute(retval,transmitted,V,L,interaction.N,NdotL,VdotL,orientedEta.value,orientedEta.rcp,H); + return compute(retval,transmitted,V,L,interaction.getN(),NdotL,VdotL,orientedEta.value,orientedEta.rcp,H); } template && ray_dir_info::Basic) static bool compute( @@ -712,8 +726,8 @@ struct SAnisotropicMicrofacetCache const bool valid = isocache_type::template compute(retval.iso_cache,interaction.isotropic,_sample,eta,H); if (valid) { - retval.TdotH = nbl::hlsl::dot(interaction.T,H); - retval.BdotH = nbl::hlsl::dot(interaction.B,H); + retval.TdotH = nbl::hlsl::dot(interaction.getT(),H); + retval.BdotH = nbl::hlsl::dot(interaction.getB(),H); } return valid; } @@ -900,8 +914,8 @@ struct __extract_aniso_vars static __extract_aniso_vars create(NBL_CONST_REF_ARG(LightSample) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { __extract_aniso_vars retval; - retval.NdotV = interaction.NdotV; - retval.NdotV2 = interaction.NdotV2; + retval.NdotV = interaction.getNdotV(); + retval.NdotV2 = interaction.getNdotV2(); return retval; } @@ -919,12 +933,12 @@ struct __extract_aniso_vars static __extract_aniso_vars create(NBL_CONST_REF_ARG(LightSample) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { __extract_aniso_vars retval; - retval.NdotV = interaction.isotropic.NdotV; - retval.NdotV2 = interaction.isotropic.NdotV2; - retval.TdotL2 = _sample.TdotL * _sample.TdotL; - retval.BdotL2 = _sample.BdotL * _sample.BdotL; - retval.TdotV2 = interaction.TdotV * interaction.TdotV; - retval.BdotV2 = interaction.BdotV * interaction.BdotV; + retval.NdotV = interaction.isotropic.getNdotV(); + retval.NdotV2 = interaction.isotropic.getNdotV2(); + retval.TdotL2 = _sample.getTdotL() * _sample.getTdotL(); + retval.BdotL2 = _sample.getBdotL() * _sample.getBdotL(); + retval.TdotV2 = interaction.getTdotV() * interaction.getTdotV(); + retval.BdotV2 = interaction.getBdotV() * interaction.getBdotV(); return retval; } @@ -999,10 +1013,10 @@ struct SBxDFParams retval.NdotV = math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, vars.NdotV, 0.0); retval.uNdotV = vars.NdotV; retval.NdotV2 = vars.NdotV2; - retval.NdotL = math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.NdotL, 0.0); - retval.uNdotL = _sample.NdotL; - retval.NdotL2 = _sample.NdotL2; - retval.VdotL = _sample.VdotL; + retval.uNdotL = _sample.getNdotL(); + retval.NdotL = math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, retval.uNdotL, 0.0); + retval.NdotL2 = _sample.getNdotL2(); + retval.VdotL = _sample.getVdotL(); retval.is_aniso = interaction_traits::is_aniso; retval.TdotL2 = vars.TdotL2; @@ -1024,12 +1038,12 @@ struct SBxDFParams retval.NdotV = math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, vars.NdotV, 0.0); retval.uNdotV = vars.NdotV; retval.NdotV2 = vars.NdotV2; - retval.NdotL = math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.NdotL, 0.0); - retval.uNdotL = _sample.NdotL; - retval.NdotL2 = _sample.NdotL2; + retval.uNdotL = _sample.getNdotL(); + retval.NdotL = math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, retval.uNdotL, 0.0); + retval.NdotL2 = _sample.getNdotL2(); + retval.VdotL = _sample.getVdotL(); retval.VdotH = vars2.VdotH; retval.LdotH = vars2.LdotH; - retval.VdotL = _sample.VdotL; retval.is_aniso = interaction_traits::is_aniso; retval.TdotL2 = vars.TdotL2; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index b500848d56..638a08a33f 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -18,25 +18,25 @@ namespace reflection { // still need these? -template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) -LightSample cos_generate(NBL_CONST_REF_ARG(Iso) interaction) -{ - return LightSample(interaction.V.reflect(interaction.N,interaction.NdotV),interaction.NdotV,interaction.N); -} -template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) -LightSample cos_generate(NBL_CONST_REF_ARG(Aniso) interaction) -{ - return LightSample(interaction.V.reflect(interaction.N,interaction.NdotV),interaction.NdotV,interaction.T,interaction.B,interaction.N); -} +// template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) +// LightSample cos_generate(NBL_CONST_REF_ARG(Iso) interaction) +// { +// return LightSample(interaction.V.reflect(interaction.N,interaction.NdotV),interaction.NdotV,interaction.N); +// } +// template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) +// LightSample cos_generate(NBL_CONST_REF_ARG(Aniso) interaction) +// { +// return LightSample(interaction.V.reflect(interaction.N,interaction.NdotV),interaction.NdotV,interaction.T,interaction.B,interaction.N); +// } // for information why we don't check the relation between `V` and `L` or `N` and `H`, see comments for `nbl::hlsl::transmission::cos_quotient_and_pdf` -template && is_floating_point_v) -quotient_and_pdf cos_quotient_and_pdf() -{ - return quotient_and_pdf::create(SpectralBins(1.f), numeric_limits::infinity); -} +// template && is_floating_point_v) +// quotient_and_pdf cos_quotient_and_pdf() +// { +// return quotient_and_pdf::create(SpectralBins(1.f), numeric_limits::infinity); +// } // basic bxdfs template && surface_interactions::Isotropic && surface_interactions::Anisotropic) @@ -274,7 +274,7 @@ struct SBlinnPhongBxDF vector3_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) { - if (interaction.isotropic.NdotV > numeric_limits::min) + if (interaction.isotropic.getNdotV() > numeric_limits::min) { params_t params = params_t::template create(_sample, interaction, cache); return __eval_wo_clamps(params); @@ -285,7 +285,7 @@ struct SBlinnPhongBxDF vector3_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) { - if (interaction.isotropic.NdotV > numeric_limits::min) + if (interaction.isotropic.getNdotV() > numeric_limits::min) { params_t params = params_t::template create(_sample, interaction, cache); return __eval_wo_clamps(params); diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index 617bb12550..f4926fef9d 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -17,18 +17,18 @@ namespace bxdf namespace transmission { -template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) -LightSample cos_generate(NBL_CONST_REF_ARG(Iso) interaction) -{ - return LightSample(interaction.V.transmit(),-1.f,interaction.N); -} -template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) -LightSample cos_generate(NBL_CONST_REF_ARG(Aniso) interaction) -{ - return LightSample(interaction.V.transmit(),-1.f,interaction.T,interaction.B,interaction.N); -} +// template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) +// LightSample cos_generate(NBL_CONST_REF_ARG(Iso) interaction) +// { +// return LightSample(interaction.V.transmit(),-1.f,interaction.N); +// } +// template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) +// LightSample cos_generate(NBL_CONST_REF_ARG(Aniso) interaction) +// { +// return LightSample(interaction.V.transmit(),-1.f,interaction.T,interaction.B,interaction.N); +// } // Why don't we check that the incoming and outgoing directions equal each other // (or similar for other delta distributions such as reflect, or smooth [thin] dielectrics): @@ -36,11 +36,11 @@ LightSample cos_generate(NBL_CONST_REF_ARG(Aniso) interaction) // - Our own generator can never pick an improbable path, so no checking necessary // - For other generators the estimator will be `f_BSDF*f_Light*f_Visibility*clampedCos(theta)/(1+(p_BSDF^alpha+p_otherNonChosenGenerator^alpha+...)/p_ChosenGenerator^alpha)` // therefore when `p_BSDF` equals `nbl_glsl_FLT_INF` it will drive the overall MIS estimator for the other generators to 0 so no checking necessary -template && is_floating_point_v) -quotient_and_pdf cos_quotient_and_pdf() -{ - return quotient_and_pdf::create(SpectralBins(1.f), numeric_limits::infinity); -} +// template && is_floating_point_v) +// quotient_and_pdf cos_quotient_and_pdf() +// { +// return quotient_and_pdf::create(SpectralBins(1.f), numeric_limits::infinity); +// } // basic bxdf template && surface_interactions::Isotropic && surface_interactions::Anisotropic) @@ -166,18 +166,20 @@ struct SSmoothDielectricBxDF sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector) u) { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.NdotV, eta); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), eta); + scalar_type NdotV = interaction.isotropic.getNdotV(); bool dummy; - return __generate_wo_clamps(interaction.isotropic.V.direction, interaction.T, interaction.B, interaction.isotropic.N, orientedEta.backside, interaction.isotropic.NdotV, - interaction.isotropic.NdotV, interaction.isotropic.NdotV*interaction.isotropic.NdotV, u, orientedEta.rcp, orientedEta.value*orientedEta.value, orientedEta.rcp*orientedEta.rcp, dummy); + return __generate_wo_clamps(interaction.isotropic.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.isotropic.getN(), orientedEta.backside, NdotV, + NdotV, NdotV*NdotV, u, orientedEta.rcp, orientedEta.value*orientedEta.value, orientedEta.rcp*orientedEta.rcp, dummy); } sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector) u) { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.NdotV, eta); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), eta); + scalar_type NdotV = interaction.isotropic.getNdotV(); bool dummy; - return __generate_wo_clamps(interaction.isotropic.V.direction, interaction.T, interaction.B, interaction.isotropic.N, orientedEta.backside, interaction.isotropic.NdotV, - nbl::hlsl::abs(interaction.isotropic.NdotV), interaction.isotropic.NdotV*interaction.isotropic.NdotV, u, orientedEta.rcp, orientedEta.value*orientedEta.value, orientedEta.rcp*orientedEta.rcp, dummy); + return __generate_wo_clamps(interaction.isotropic.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.isotropic.getN(), orientedEta.backside, NdotV, + nbl::hlsl::abs(NdotV), NdotV*NdotV, u, orientedEta.rcp, orientedEta.value*orientedEta.value, orientedEta.rcp*orientedEta.rcp, dummy); } // eval and pdf return 0 because smooth dielectric/conductor BxDFs are dirac delta distributions, model perfectly specular objects that scatter light to only one outgoing direction @@ -265,14 +267,16 @@ struct SSmoothDielectricBxDF sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector) u) { + scalar_type NdotV = interaction.isotropic.getNdotV(); vector3_type dummy; - return __generate_wo_clamps(interaction.isotropic.V.direction, interaction.T, interaction.B, interaction.isotropic.N, interaction.isotropic.NdotV, interaction.isotropic.NdotV, u, eta2, luminosityContributionHint, dummy); + return __generate_wo_clamps(interaction.isotropic.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.isotropic.getN(), NdotV, NdotV, u, eta2, luminosityContributionHint, dummy); } sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector) u) { + scalar_type NdotV = interaction.isotropic.getNdotV(); vector3_type dummy; - return __generate_wo_clamps(interaction.isotropic.V.direction, interaction.T, interaction.B, interaction.isotropic.N, interaction.isotropic.NdotV, nbl::hlsl::abs(interaction.isotropic.NdotV), u, eta2, luminosityContributionHint, dummy); + return __generate_wo_clamps(interaction.isotropic.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.isotropic.getN(), NdotV, nbl::hlsl::abs(NdotV), u, eta2, luminosityContributionHint, dummy); } scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) @@ -391,7 +395,7 @@ struct SBeckmannDielectricBxDF { const vector3_type localV = interaction.getTangentSpaceV(); - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.NdotV, eta); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), eta); const vector3_type upperHemisphereV = orientedEta.backside ? -localV : localV; @@ -578,7 +582,7 @@ struct SGGXDielectricBxDF { const vector3_type localV = interaction.getTangentSpaceV(); - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.NdotV, eta); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), eta); const vector3_type upperHemisphereV = orientedEta.backside ? -localV : localV; From 2e368abbf870be84e5862e07559104f1bfbd7385 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 4 Apr 2025 11:20:45 +0700 Subject: [PATCH 086/188] getters for microfacet cache --- examples_tests | 2 +- include/nbl/builtin/hlsl/bxdf/common.hlsl | 66 +++++++++++-------- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 6 +- .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 8 +-- .../nbl/builtin/hlsl/glsl_compat/core.hlsl | 2 +- 5 files changed, 49 insertions(+), 35 deletions(-) diff --git a/examples_tests b/examples_tests index 4864a4525e..9dc93dd995 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 4864a4525e998186423f0376c480cda2e71759da +Subproject commit 9dc93dd995c004f1396179ea1530658bd3a82c53 diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index b95eccc6a1..bae8f264c8 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -467,10 +467,10 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) ((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.VdotH), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.LdotH), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.NdotH), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.NdotH2), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getVdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getLdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getNdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getNdotH2()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(pNdotV,pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, T)) //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(iso,_sample)), ::nbl::hlsl::is_same_v, T)) @@ -524,7 +524,7 @@ struct SIsotropicMicrofacetCache NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction, NBL_CONST_REF_ARG(SLightSample) _sample) { - return createForReflection(interaction.getNdotV(), _sample.NdotL, _sample.VdotL); + return createForReflection(interaction.getNdotV(), _sample.getNdotL(), _sample.getVdotL()); } // transmissive cases need to be checked if the path is valid before usage static bool compute( @@ -560,13 +560,13 @@ struct SIsotropicMicrofacetCache ) { const scalar_type NdotV = interaction.getNdotV(); - const scalar_type NdotL = _sample.NdotL; + const scalar_type NdotL = _sample.getNdotL(); const bool transmitted = isTransmissionPath(NdotV,NdotL); fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(NdotV, eta); const vector3_type V = interaction.getV().getDirection(); - const vector3_type L = _sample.L.direction; + const vector3_type L = _sample.getL().getDirection(); const scalar_type VdotL = nbl::hlsl::dot(V, L); return compute(retval,transmitted,V,L,interaction.getN(),NdotL,VdotL,orientedEta.value,orientedEta.rcp,H); } @@ -587,6 +587,11 @@ struct SIsotropicMicrofacetCache return NdotH >= 0.0 && !(is_bsdf && transmission && (VdotL > -min(eta, rcp_eta))); } + scalar_type getVdotH() NBL_CONST_MEMBER_FUNC { return VdotH; } + scalar_type getLdotH() NBL_CONST_MEMBER_FUNC { return LdotH; } + scalar_type getNdotH() NBL_CONST_MEMBER_FUNC { return NdotH; } + scalar_type getNdotH2() NBL_CONST_MEMBER_FUNC { return NdotH2; } + scalar_type VdotH; scalar_type LdotH; scalar_type NdotH; @@ -616,8 +621,8 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) ((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.TdotH), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.BdotH), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getTdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getBdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V,b0,pNdotL,pNdotL)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(V,V,pNdotL)), ::nbl::hlsl::is_same_v, T)) @@ -653,9 +658,9 @@ struct SAnisotropicMicrofacetCache this_t retval; retval.iso_cache.VdotH = nbl::hlsl::dot(tangentSpaceV,tangentSpaceH); - retval.iso_cache.LdotH = retval.iso_cache.VdotH; + retval.iso_cache.LdotH = retval.iso_cache.getVdotH(); retval.iso_cache.NdotH = tangentSpaceH.z; - retval.iso_cache.NdotH2 = retval.iso_cache.NdotH * retval.iso_cache.NdotH; + retval.iso_cache.NdotH2 = retval.iso_cache.getNdotH() * retval.iso_cache.getNdotH(); retval.TdotH = tangentSpaceH.x; retval.BdotH = tangentSpaceH.y; @@ -695,7 +700,7 @@ struct SAnisotropicMicrofacetCache NBL_CONST_REF_ARG(surface_interactions::SAnisotropic) interaction, NBL_CONST_REF_ARG(SLightSample) _sample) { - return createForReflection(interaction.getTangentSpaceV(), _sample.getTangentSpaceL(), _sample.VdotL); + return createForReflection(interaction.getTangentSpaceV(), _sample.getTangentSpaceL(), _sample.getVdotL()); } // transmissive cases need to be checked if the path is valid before usage static bool compute( @@ -732,6 +737,9 @@ struct SAnisotropicMicrofacetCache return valid; } + scalar_type getTdotH() NBL_CONST_MEMBER_FUNC { return TdotH; } + scalar_type getBdotH() NBL_CONST_MEMBER_FUNC { return BdotH; } + isocache_type iso_cache; scalar_type TdotH; scalar_type BdotH; @@ -935,10 +943,14 @@ struct __extract_aniso_vars __extract_aniso_vars retval; retval.NdotV = interaction.isotropic.getNdotV(); retval.NdotV2 = interaction.isotropic.getNdotV2(); - retval.TdotL2 = _sample.getTdotL() * _sample.getTdotL(); - retval.BdotL2 = _sample.getBdotL() * _sample.getBdotL(); - retval.TdotV2 = interaction.getTdotV() * interaction.getTdotV(); - retval.BdotV2 = interaction.getBdotV() * interaction.getBdotV(); + const T TdotL = _sample.getTdotL(); + const T BdotL = _sample.getBdotL(); + retval.TdotL2 = TdotL * TdotL; + retval.BdotL2 = BdotL * BdotL; + const T TdotV = interaction.getTdotV(); + const T BdotV = interaction.getBdotV(); + retval.TdotV2 = TdotV * TdotV; + retval.BdotV2 = BdotV * BdotV; return retval; } @@ -959,10 +971,10 @@ struct __extract_aniso_vars2 static __extract_aniso_vars2 create(NBL_CONST_REF_ARG(Cache) cache) { __extract_aniso_vars2 retval; - retval.NdotH = cache.NdotH; - retval.NdotH2 = cache.NdotH2; - retval.VdotH = cache.VdotH; - retval.LdotH = cache.LdotH; + retval.NdotH = cache.getNdotH(); + retval.NdotH2 = cache.getNdotH2(); + retval.VdotH = cache.getVdotH(); + retval.LdotH = cache.getLdotH(); return retval; } @@ -980,12 +992,14 @@ struct __extract_aniso_vars2 static __extract_aniso_vars2 create(NBL_CONST_REF_ARG(Cache) cache) { __extract_aniso_vars2 retval; - retval.NdotH = cache.iso_cache.NdotH; - retval.NdotH2 = cache.iso_cache.NdotH2; - retval.VdotH = cache.iso_cache.VdotH; - retval.LdotH = cache.iso_cache.LdotH; - retval.TdotH2 = cache.TdotH * cache.TdotH; - retval.BdotH2 = cache.BdotH * cache.BdotH; + retval.NdotH = cache.iso_cache.getNdotH(); + retval.NdotH2 = cache.iso_cache.getNdotH2(); + retval.VdotH = cache.iso_cache.getVdotH(); + retval.LdotH = cache.iso_cache.getLdotH(); + const T TdotH = cache.getTdotH(); + const T BdotH = cache.getBdotH(); + retval.TdotH2 = TdotH * TdotH; + retval.BdotH2 = BdotH * BdotH; return retval; } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 638a08a33f..352f1d17b8 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -311,7 +311,7 @@ struct SBlinnPhongBxDF cache = anisocache_type::create(localV, H); ray_dir_info_type localL; - bxdf::Reflect r = bxdf::Reflect::create(localV, H, cache.iso_cache.VdotH); + bxdf::Reflect r = bxdf::Reflect::create(localV, H, cache.iso_cache.getVdotH()); localL.direction = r(); return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); @@ -498,7 +498,7 @@ struct SBeckmannBxDF cache = anisocache_type::create(localV, H); ray_dir_info_type localL; - bxdf::Reflect r = bxdf::Reflect::create(localV, H, cache.iso_cache.VdotH); + bxdf::Reflect r = bxdf::Reflect::create(localV, H, cache.iso_cache.getVdotH()); localL.direction = r(); return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); @@ -698,7 +698,7 @@ struct SGGXBxDF cache = anisocache_type::create(localV, H); ray_dir_info_type localL; - bxdf::Reflect r = bxdf::Reflect::create(localV, H, cache.iso_cache.VdotH); + bxdf::Reflect r = bxdf::Reflect::create(localV, H, cache.iso_cache.getVdotH()); localL.direction = r(); return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index f4926fef9d..d9afa8a639 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -382,10 +382,10 @@ struct SBeckmannDielectricBxDF cache = anisocache_type::create(localV, H); - const scalar_type VdotH = cache.iso_cache.VdotH; + const scalar_type VdotH = cache.iso_cache.getVdotH(); cache.iso_cache.LdotH = transmitted ? Refract::computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; ray_dir_info_type localL; - bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, localV, H, VdotH, cache.iso_cache.LdotH, rcpOrientedEta); + bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, localV, H, VdotH, cache.iso_cache.getLdotH(), rcpOrientedEta); localL.direction = rr(); return sample_type::createFromTangentSpace(localV, localL, m); @@ -569,10 +569,10 @@ struct SGGXDielectricBxDF cache = anisocache_type::create(localV, H); - const scalar_type VdotH = cache.iso_cache.VdotH; + const scalar_type VdotH = cache.iso_cache.getVdotH(); cache.iso_cache.LdotH = transmitted ? Refract::computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; ray_dir_info_type localL; - bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, localV, H, VdotH, cache.iso_cache.LdotH, rcpOrientedEta); + bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, localV, H, VdotH, cache.iso_cache.getLdotH(), rcpOrientedEta); localL.direction = rr(); return sample_type::createFromTangentSpace(localV, localL, m); diff --git a/include/nbl/builtin/hlsl/glsl_compat/core.hlsl b/include/nbl/builtin/hlsl/glsl_compat/core.hlsl index a2ae13df23..88d2f4b7a6 100644 --- a/include/nbl/builtin/hlsl/glsl_compat/core.hlsl +++ b/include/nbl/builtin/hlsl/glsl_compat/core.hlsl @@ -294,7 +294,7 @@ struct equal_helper } template -inline T equal(NBL_CONST_REF_ARG(T) x, NBL_CONST_REF_ARG(T) y) +inline vector::Dimension> equal(NBL_CONST_REF_ARG(T) x, NBL_CONST_REF_ARG(T) y) { return impl::equal_helper::__call(x, y); } From bd5233294e55dbea49bd07bc2406179b6a93257d Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 4 Apr 2025 11:35:01 +0700 Subject: [PATCH 087/188] added vector spec for flipSign --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 5 +-- include/nbl/builtin/hlsl/ieee754.hlsl | 46 ++++++++++++++++++++--- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index bae8f264c8..1ec90da568 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -29,10 +29,7 @@ T computeUnnormalizedMicrofacetNormal(bool _refract, NBL_CONST_REF_ARG(T) V, NBL { const typename vector_traits::scalar_type etaFactor = (_refract ? orientedEta : 1.0); T tmpH = V + L * etaFactor; - // ieee754::flipSign(tmpH, _refract) doesn't work with vectors - tmpH.x = ieee754::flipSign::scalar_type>(tmpH.x, _refract); - tmpH.y = ieee754::flipSign::scalar_type>(tmpH.y, _refract); - tmpH.z = ieee754::flipSign::scalar_type>(tmpH.z, _refract); + tmpH = ieee754::flipSign(tmpH, _refract); return tmpH; } diff --git a/include/nbl/builtin/hlsl/ieee754.hlsl b/include/nbl/builtin/hlsl/ieee754.hlsl index 4b281c2111..50cc2de98c 100644 --- a/include/nbl/builtin/hlsl/ieee754.hlsl +++ b/include/nbl/builtin/hlsl/ieee754.hlsl @@ -142,13 +142,47 @@ NBL_CONSTEXPR_INLINE_FUNC FloatingPoint copySign(FloatingPoint to, FloatingPoint return bit_cast(toAsUint | extractSignPreserveBitPattern(from)); } -template ) -NBL_CONSTEXPR_INLINE_FUNC FloatingPoint flipSign(FloatingPoint val, bool flip = true) +namespace impl +{ +template +struct flipSign_helper; + +template +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointLikeScalar) +struct flipSign_helper) > +{ + static FloatingPoint __call(FloatingPoint val, bool flip = true) + { + using AsFloat = typename float_of_size::type; + using AsUint = typename unsigned_integer_of_size::type; + const AsUint asUint = ieee754::impl::bitCastToUintType(val); + return bit_cast(asUint ^ (flip ? ieee754::traits::signMask : AsUint(0ull))); + } +}; + +template +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointLikeVectorial) +struct flipSign_helper) > { - using AsFloat = typename float_of_size::type; - using AsUint = typename unsigned_integer_of_size::type; - const AsUint asUint = ieee754::impl::bitCastToUintType(val); - return bit_cast(asUint ^ (flip ? ieee754::traits::signMask : AsUint(0ull))); + static Vectorial __call(Vectorial val, bool flip = true) + { + using traits = hlsl::vector_traits; + array_get getter; + array_get setter; + + Vectorial output; + for (uint32_t i = 0; i < traits::Dimension; ++i) + setter(output, i, flipSign_helper::__call(getter(val, i), flip)); + + return output; + } +}; +} + +template +NBL_CONSTEXPR_INLINE_FUNC T flipSign(T val, bool flip = true) +{ + return impl::flipSign_helper::__call(val, flip); } } From bff0aa64f16af60f840b52a5c096d90ad805d3c6 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 4 Apr 2025 14:30:24 +0700 Subject: [PATCH 088/188] added rng wrapper for 2d/3d uints --- examples_tests | 2 +- include/nbl/builtin/hlsl/random/pcg.hlsl | 16 ----- include/nbl/builtin/hlsl/random/rand_gen.hlsl | 59 +++++++++++++++++++ 3 files changed, 60 insertions(+), 17 deletions(-) create mode 100644 include/nbl/builtin/hlsl/random/rand_gen.hlsl diff --git a/examples_tests b/examples_tests index 9dc93dd995..6f3706aaaf 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 9dc93dd995c004f1396179ea1530658bd3a82c53 +Subproject commit 6f3706aaaf35af9df173bc4dcb6c92885d831526 diff --git a/include/nbl/builtin/hlsl/random/pcg.hlsl b/include/nbl/builtin/hlsl/random/pcg.hlsl index 1c06255ae2..45059e68f4 100644 --- a/include/nbl/builtin/hlsl/random/pcg.hlsl +++ b/include/nbl/builtin/hlsl/random/pcg.hlsl @@ -33,22 +33,6 @@ struct PCG32 uint32_t state; }; -struct PCG32x2 -{ - static PCG32x2 construct(NBL_CONST_REF_ARG(uint32_t) initialState) - { - PCG32 rng = PCG32::construct(initialState); - return PCG32x2(rng); - } - - uint32_t2 operator()() - { - return uint32_t2(rng(), rng()); - } - - PCG32 rng; -}; - } } } diff --git a/include/nbl/builtin/hlsl/random/rand_gen.hlsl b/include/nbl/builtin/hlsl/random/rand_gen.hlsl new file mode 100644 index 0000000000..b114b94e9d --- /dev/null +++ b/include/nbl/builtin/hlsl/random/rand_gen.hlsl @@ -0,0 +1,59 @@ +#ifndef _NBL_HLSL_RANDOM_RANDGEN_INCLUDED_ +#define _NBL_HLSL_RANDOM_RANDGEN_INCLUDED_ + +#include "nbl/builtin/hlsl/type_traits.hlsl" + +namespace nbl +{ +namespace hlsl +{ +namespace random +{ + +template +struct Uniform2D +{ + using rng_type = RNG; + using seed_type = conditional_t >; + + static Uniform2D construct(seed_type seed) + { + Uniform2D retval; + retval.rng = rng_type::construct(seed); + return retval; + } + + uint32_t2 operator()() + { + return uint32_t2(rng(), rng()); + } + + rng_type rng; +}; + +template +struct Uniform3D +{ + using rng_type = RNG; + using seed_type = conditional_t >; + + static Uniform3D construct(seed_type seed) + { + Uniform3D retval; + retval.rng = rng_type::construct(seed); + return retval; + } + + uint32_t3 operator()() + { + return uint32_t3(rng(), rng(), rng()); + } + + rng_type rng; +}; + +} +} +} + +#endif \ No newline at end of file From deda14aa0d7fe0061fc0a876d665b5686e74e0bd Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 4 Apr 2025 16:23:24 +0700 Subject: [PATCH 089/188] added OpSelect intrinsic for mix, fix mix behavior with bool --- include/nbl/builtin/hlsl/bxdf/fresnel.hlsl | 10 +++++----- include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl | 2 +- .../hlsl/cpp_compat/impl/intrinsics_impl.hlsl | 16 ++++++++++------ .../nbl/builtin/hlsl/spirv_intrinsics/core.hlsl | 5 +++++ 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl index 211b2e1bf0..70bdfefe94 100644 --- a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl @@ -39,9 +39,9 @@ struct OrientedEtas { // assert(n*n==n2); vector::Dimension> TIR = n < (T)1.0; - T invdenum = nbl::hlsl::mix((T)1.0, (T)1.0 / (n2 * n2 * ((T)554.33 - 380.7 * n)), TIR); - T num = n * nbl::hlsl::mix((T)(0.1921156102251088), n * 298.25 - 261.38 * n2 + 138.43, TIR); - num += nbl::hlsl::mix((T)(0.8078843897748912), (T)(-1.67), TIR); + T invdenum = nbl::hlsl::mix(hlsl::promote(1.0), hlsl::promote(1.0) / (n2 * n2 * (hlsl::promote(554.33) - 380.7 * n)), TIR); + T num = n * nbl::hlsl::mix(hlsl::promote(0.1921156102251088), n * 298.25 - 261.38 * n2 + 138.43, TIR); + num += nbl::hlsl::mix(hlsl::promote(0.8078843897748912), hlsl::promote(-1.67), TIR); return num * invdenum; } @@ -219,7 +219,7 @@ struct ReflectRefract vector_type operator()() { - return N * (NdotI * (refract ? rcpOrientedEta : 1.0f) + NdotTorR) - I * (refract ? rcpOrientedEta : 1.0f); + return N * (NdotI * (hlsl::mix(1.0f, rcpOrientedEta, refract)) + NdotTorR) - I * (hlsl::mix(1.0f, rcpOrientedEta, refract)); } bool refract; @@ -360,7 +360,7 @@ struct ThinDielectricInfiniteScatter T operator()(T singleInterfaceReflectance) { const T doubleInterfaceReflectance = singleInterfaceReflectance * singleInterfaceReflectance; - return hlsl::mix((singleInterfaceReflectance - doubleInterfaceReflectance) / (hlsl::promote(1.0) - doubleInterfaceReflectance) * 2.0f, hlsl::promote(1.0), doubleInterfaceReflectance > hlsl::promote(0.9999)); + return hlsl::mix(hlsl::promote(1.0), (singleInterfaceReflectance - doubleInterfaceReflectance) / (hlsl::promote(1.0) - doubleInterfaceReflectance) * 2.0f, doubleInterfaceReflectance > hlsl::promote(0.9999)); } }; diff --git a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl index 04f933dcc5..a39a90b72f 100644 --- a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl @@ -172,7 +172,7 @@ struct Beckmann scalar_type c = sqrt(c2); scalar_type nom = 1.0 - 1.259 * c + 0.396 * c2; scalar_type denom = 2.181 * c2 + 3.535 * c; - return nbl::hlsl::mix(0.0, nom / denom, c < 1.6); + return hlsl::mix(0.0, nom / denom, c < 1.6); } scalar_type Lambda(scalar_type NdotX2, scalar_type a2) diff --git a/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl b/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl index d42df65dfb..8b2e3aa3b0 100644 --- a/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl +++ b/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl @@ -240,13 +240,17 @@ struct mix_helper(e } }; -template NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) -struct mix_helper) > +template +NBL_PARTIAL_REQ_TOP((concepts::Scalar || concepts::Vectorial) && !concepts::Boolean && concepts::Boolean) +struct mix_helper || concepts::Vectorial) && !concepts::Boolean && concepts::Boolean) > { using return_t = conditional_t, vector::scalar_type, vector_traits::Dimension>, T>; - static inline return_t __call(const T x, const T y, const bool a) + // for a component of a that is false, the corresponding component of x is returned + // for a component of a that is true, the corresponding component of y is returned + // so we make sure this is correct when calling the operation + static inline return_t __call(const T x, const T y, const U a) { - return a ? x : y; + return spirv::select(a, y, x); } }; @@ -862,8 +866,8 @@ struct mix_helper }; template -NBL_PARTIAL_REQ_TOP(concepts::Vectorial && concepts::Boolean && vector_traits::Dimension == vector_traits::Dimension) -struct mix_helper && concepts::Boolean && vector_traits::Dimension == vector_traits::Dimension) > +NBL_PARTIAL_REQ_TOP(VECTOR_SPECIALIZATION_CONCEPT && concepts::Boolean && vector_traits::Dimension == vector_traits::Dimension) +struct mix_helper && vector_traits::Dimension == vector_traits::Dimension) > { using return_t = T; static return_t __call(NBL_CONST_REF_ARG(T) x, NBL_CONST_REF_ARG(T) y, NBL_CONST_REF_ARG(U) a) diff --git a/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl b/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl index 88daa477ac..635346a47a 100644 --- a/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl +++ b/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl @@ -355,6 +355,11 @@ template && !is_matrix_v) [[vk::ext_instruction(spv::OpFOrdEqual)]] conditional_t, vector::Dimension>, bool> FOrdEqual(T lhs, T rhs); + +template && !is_matrix_v && is_same_v::scalar_type, bool>) +[[vk::ext_instruction(spv::OpSelect)]] +T select(U a, T x, T y); + } #endif From 576b81401dee898a2d87a92d20d7ec0d5bb9dd95 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 14 Apr 2025 11:00:26 +0700 Subject: [PATCH 090/188] changes to uniform rand wrapper --- examples_tests | 2 +- include/nbl/builtin/hlsl/random/lcg.hlsl | 8 +- include/nbl/builtin/hlsl/random/pcg.hlsl | 8 +- include/nbl/builtin/hlsl/random/rand_gen.hlsl | 43 ++++------ .../nbl/builtin/hlsl/random/xoroshiro.hlsl | 84 ++++++++++--------- 5 files changed, 70 insertions(+), 75 deletions(-) diff --git a/examples_tests b/examples_tests index 6f3706aaaf..6d298fdfd2 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 6f3706aaaf35af9df173bc4dcb6c92885d831526 +Subproject commit 6d298fdfd2cfb3d1bd1aabbb4912e6b1080e0f38 diff --git a/include/nbl/builtin/hlsl/random/lcg.hlsl b/include/nbl/builtin/hlsl/random/lcg.hlsl index 046161bc6b..0ac0d809aa 100644 --- a/include/nbl/builtin/hlsl/random/lcg.hlsl +++ b/include/nbl/builtin/hlsl/random/lcg.hlsl @@ -13,13 +13,15 @@ namespace random struct Lcg { - static Lcg create(const uint32_t _state) + using seed_type = uint32_t; + + static Lcg create(NBL_CONST_REF_ARG(seed_type) _state) { Lcg retval; retval.state = _state; return retval; } - + uint32_t operator()() { uint32_t LCG_A = 1664525u; @@ -30,7 +32,7 @@ struct Lcg return state; } - uint32_t state; + seed_type state; }; } diff --git a/include/nbl/builtin/hlsl/random/pcg.hlsl b/include/nbl/builtin/hlsl/random/pcg.hlsl index 45059e68f4..2b881e29a2 100644 --- a/include/nbl/builtin/hlsl/random/pcg.hlsl +++ b/include/nbl/builtin/hlsl/random/pcg.hlsl @@ -13,7 +13,9 @@ namespace random struct PCG32 { - static PCG32 construct(NBL_CONST_REF_ARG(uint32_t) initialState) + using seed_type = uint32_t; + + static PCG32 construct(NBL_CONST_REF_ARG(seed_type) initialState) { PCG32 retval; retval.state = initialState; @@ -22,7 +24,7 @@ struct PCG32 uint32_t operator()() { - const uint32_t oldState = state; + const seed_type oldState = state; state = state * 747796405u + 2891336453u; const uint32_t word = ((oldState >> ((oldState >> 28u) + 4u)) ^ oldState) * 277803737u; const uint32_t result = (word >> 22u) ^ word; @@ -30,7 +32,7 @@ struct PCG32 return result; } - uint32_t state; + seed_type state; }; } diff --git a/include/nbl/builtin/hlsl/random/rand_gen.hlsl b/include/nbl/builtin/hlsl/random/rand_gen.hlsl index b114b94e9d..7cd7288b8b 100644 --- a/include/nbl/builtin/hlsl/random/rand_gen.hlsl +++ b/include/nbl/builtin/hlsl/random/rand_gen.hlsl @@ -10,45 +10,32 @@ namespace hlsl namespace random { -template -struct Uniform2D +template +struct Uniform { using rng_type = RNG; - using seed_type = conditional_t >; + using return_type = vector; - static Uniform2D construct(seed_type seed) + static Uniform construct(rng_type rng) { - Uniform2D retval; - retval.rng = rng_type::construct(seed); + Uniform retval; + retval.rng = rng; return retval; } - uint32_t2 operator()() + return_type operator()() { - return uint32_t2(rng(), rng()); - } - - rng_type rng; -}; - -template -struct Uniform3D -{ - using rng_type = RNG; - using seed_type = conditional_t >; - - static Uniform3D construct(seed_type seed) - { - Uniform3D retval; - retval.rng = rng_type::construct(seed); + array_set setter; + + return_type retval; +#ifdef __HLSL_VERSION + [unroll] +#endif + for (uint32_t i = 0; i < DIM; i++) + setter(retval, i, rng()); return retval; } - uint32_t3 operator()() - { - return uint32_t3(rng(), rng(), rng()); - } - rng_type rng; }; diff --git a/include/nbl/builtin/hlsl/random/xoroshiro.hlsl b/include/nbl/builtin/hlsl/random/xoroshiro.hlsl index 577b89bb95..1a150f1909 100644 --- a/include/nbl/builtin/hlsl/random/xoroshiro.hlsl +++ b/include/nbl/builtin/hlsl/random/xoroshiro.hlsl @@ -1,16 +1,16 @@ -// Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. -// This file is part of the "Nabla Engine". -// For conditions of distribution and use, see copyright notice in nabla.h -#ifndef _NBL_BUILTIN_HLSL_RANDOM_XOROSHIRO_HLSL_INCLUDED_ -#define _NBL_BUILTIN_HLSL_RANDOM_XOROSHIRO_HLSL_INCLUDED_ - -#include - -#include - -namespace nbl -{ -namespace hlsl +// Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_BUILTIN_HLSL_RANDOM_XOROSHIRO_HLSL_INCLUDED_ +#define _NBL_BUILTIN_HLSL_RANDOM_XOROSHIRO_HLSL_INCLUDED_ + +#include + +#include + +namespace nbl +{ +namespace hlsl { // TODO //namespace random @@ -18,58 +18,62 @@ namespace hlsl struct Xoroshiro64StateHolder { - void xoroshiro64_state_advance() - { - state[1] ^= state[0]; - state[0] = rotl(state[0], 26u) ^ state[1] ^ (state[1]<<9u); // a, b - state[1] = rotl(state[1], 13u); // c + void xoroshiro64_state_advance() + { + state[1] ^= state[0]; + state[0] = rotl(state[0], 26u) ^ state[1] ^ (state[1]<<9u); // a, b + state[1] = rotl(state[1], 13u); // c } - + uint32_t2 state; -}; - +}; + struct Xoroshiro64Star { + using seed_type = uint32_t2; + // TODO: create - static Xoroshiro64Star construct(NBL_CONST_REF_ARG(uint32_t2) initialState) + static Xoroshiro64Star construct(NBL_CONST_REF_ARG(seed_type) initialState) { Xoroshiro64StateHolder stateHolder = {initialState}; return Xoroshiro64Star(stateHolder); } - + uint32_t operator()() { - const uint32_t result = stateHolder.state[0]*0x9E3779BBu; - stateHolder.xoroshiro64_state_advance(); - + const uint32_t result = stateHolder.state[0]*0x9E3779BBu; + stateHolder.xoroshiro64_state_advance(); + return result; } - + Xoroshiro64StateHolder stateHolder; -}; - +}; + struct Xoroshiro64StarStar { + using seed_type = uint32_t2; + // TODO: create - static Xoroshiro64StarStar construct(NBL_CONST_REF_ARG(uint32_t2) initialState) + static Xoroshiro64StarStar construct(NBL_CONST_REF_ARG(seed_type) initialState) { Xoroshiro64StateHolder stateHolder = {initialState}; return Xoroshiro64StarStar(stateHolder); } - + uint32_t operator()() { - const uint32_t result = rotl(stateHolder.state[0]*0x9E3779BBu,5u)*5u; - stateHolder.xoroshiro64_state_advance(); - + const uint32_t result = rotl(stateHolder.state[0]*0x9E3779BBu,5u)*5u; + stateHolder.xoroshiro64_state_advance(); + return result; } Xoroshiro64StateHolder stateHolder; -}; - -//} -} -} - +}; + +//} +} +} + #endif \ No newline at end of file From 268b573591a5abc3bceb2b40f22b2f6c30cf3625 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 14 Apr 2025 14:30:32 +0700 Subject: [PATCH 091/188] moved quotient_pdf to sampling namespace, split bxdf files --- examples_tests | 2 +- include/nbl/builtin/hlsl/bxdf/common.hlsl | 52 +- include/nbl/builtin/hlsl/bxdf/reflection.hlsl | 765 +----------------- .../hlsl/bxdf/reflection/beckmann.hlsl | 271 +++++++ .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 223 +++++ .../hlsl/bxdf/reflection/lambertian.hlsl | 89 ++ .../hlsl/bxdf/reflection/oren_nayar.hlsl | 99 +++ .../nbl/builtin/hlsl/bxdf/transmission.hlsl | 663 +-------------- .../hlsl/bxdf/transmission/beckmann.hlsl | 205 +++++ .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 209 +++++ .../hlsl/bxdf/transmission/lambertian.hlsl | 88 ++ .../bxdf/transmission/smooth_dielectric.hlsl | 218 +++++ .../builtin/hlsl/sampling/cos_weighted.hlsl | 28 +- .../hlsl/sampling/quotient_and_pdf.hlsl | 49 ++ .../nbl/builtin/hlsl/sampling/uniform.hlsl | 13 + 15 files changed, 1492 insertions(+), 1482 deletions(-) create mode 100644 include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl create mode 100644 include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl create mode 100644 include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl create mode 100644 include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl create mode 100644 include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl create mode 100644 include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl create mode 100644 include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl create mode 100644 include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl create mode 100644 include/nbl/builtin/hlsl/sampling/quotient_and_pdf.hlsl diff --git a/examples_tests b/examples_tests index 6d298fdfd2..dd7c0c7a12 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 6d298fdfd2cfb3d1bd1aabbb4912e6b1080e0f38 +Subproject commit dd7c0c7a12cc5a15d5d48f97cf2b7647ff07f426 diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 1ec90da568..f7dc49b3f5 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -13,6 +13,7 @@ #include "nbl/builtin/hlsl/math/functions.hlsl" #include "nbl/builtin/hlsl/cpp_compat/promote.hlsl" #include "nbl/builtin/hlsl/bxdf/fresnel.hlsl" +#include "nbl/builtin/hlsl/sampling/quotient_and_pdf.hlsl" #include "nbl/builtin/hlsl/vector_utils/vector_traits.hlsl" namespace nbl @@ -758,53 +759,6 @@ struct microfacet_cache_traits > }; -#define NBL_CONCEPT_NAME generalized_spectral_of -#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename) -#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(F) -#define NBL_CONCEPT_PARAM_0 (spec, T) -#define NBL_CONCEPT_PARAM_1 (field, F) -NBL_CONCEPT_BEGIN(2) -#define spec NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 -#define field NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 -NBL_CONCEPT_END( - //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((spec[field]), ::nbl::hlsl::is_scalar_v)) // correctness? - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((spec * field), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((field * spec), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(is_scalar_v, F)) -); -#undef field -#undef spec -#include - -template -NBL_BOOL_CONCEPT spectral_of = generalized_spectral_of || is_vector_v || is_scalar_v; - -// finally fixed the semantic F-up, value/pdf = quotient not remainder -template && is_floating_point_v) -struct quotient_and_pdf -{ - using this_t = quotient_and_pdf; - static this_t create(NBL_CONST_REF_ARG(SpectralBins) _quotient, NBL_CONST_REF_ARG(Pdf) _pdf) - { - this_t retval; - retval.quotient = _quotient; - retval.pdf = _pdf; - return retval; - } - - SpectralBins value() - { - return quotient*pdf; - } - - SpectralBins quotient; - Pdf pdf; -}; - -typedef quotient_and_pdf quotient_and_pdf_scalar; -typedef quotient_and_pdf, float32_t> quotient_and_pdf_rgb; - - #define NBL_CONCEPT_NAME BxDF #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) #define NBL_CONCEPT_TPLT_PRM_NAMES (T) @@ -836,7 +790,7 @@ NBL_CONCEPT_END( //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template pdf(_sample,iso)), ::nbl::hlsl::is_scalar_v)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(Sample, typename T::sample_type)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(spectral_of, typename T::spectral_type, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(sampling::spectral_of, typename T::spectral_type, typename T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Isotropic, typename T::isotropic_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Anisotropic, typename T::anisotropic_type)) ); @@ -885,7 +839,7 @@ NBL_CONCEPT_END( //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.template pdf(_sample,iso)), ::nbl::hlsl::is_scalar_v)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(Sample, typename T::sample_type)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(spectral_of, typename T::spectral_type, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(sampling::spectral_of, typename T::spectral_type, typename T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(IsotropicMicrofacetCache, typename T::isocache_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(AnisotropicMicrofacetCache, typename T::anisocache_type)) ); diff --git a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl index 352f1d17b8..ed049d3d1a 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection.hlsl @@ -1,774 +1,19 @@ -// Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O. +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h #ifndef _NBL_BUILTIN_HLSL_BXDF_REFLECTION_INCLUDED_ #define _NBL_BUILTIN_HLSL_BXDF_REFLECTION_INCLUDED_ -#include "nbl/builtin/hlsl/bxdf/common.hlsl" -#include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" -#include "nbl/builtin/hlsl/bxdf/geom_smith.hlsl" +#include "nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl" +#include "nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl" +#include "nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl" +#include "nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl" namespace nbl { namespace hlsl { -namespace bxdf -{ -namespace reflection -{ - -// still need these? -// template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) -// LightSample cos_generate(NBL_CONST_REF_ARG(Iso) interaction) -// { -// return LightSample(interaction.V.reflect(interaction.N,interaction.NdotV),interaction.NdotV,interaction.N); -// } -// template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) -// LightSample cos_generate(NBL_CONST_REF_ARG(Aniso) interaction) -// { -// return LightSample(interaction.V.reflect(interaction.N,interaction.NdotV),interaction.NdotV,interaction.T,interaction.B,interaction.N); -// } - -// for information why we don't check the relation between `V` and `L` or `N` and `H`, see comments for `nbl::hlsl::transmission::cos_quotient_and_pdf` -// template && is_floating_point_v) -// quotient_and_pdf cos_quotient_and_pdf() -// { -// return quotient_and_pdf::create(SpectralBins(1.f), numeric_limits::infinity); -// } - -// basic bxdfs -template && surface_interactions::Isotropic && surface_interactions::Anisotropic) -struct SLambertianBxDF -{ - using this_t = SLambertianBxDF; - using scalar_type = typename LightSample::scalar_type; - using ray_dir_info_type = typename LightSample::ray_dir_info_type; - using isotropic_type = Iso; - using anisotropic_type = Aniso; - using sample_type = LightSample; - using spectral_type = Spectrum; - using quotient_pdf_type = quotient_and_pdf; - using params_t = SBxDFParams; - - static this_t create() - { - this_t retval; - // nothing here, just keeping in convention with others - return retval; - } - - static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - return create(); - } - - void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - // do nothing - } - - scalar_type __eval_pi_factored_out(scalar_type maxNdotL) - { - return maxNdotL; - } - - scalar_type eval(NBL_CONST_REF_ARG(params_t) params) - { - return __eval_pi_factored_out(params.NdotL) * numbers::inv_pi; - } - - sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector) u) - { - ray_dir_info_type L; - L.direction = sampling::ProjectedHemisphere::generate(u); - return sample_type::createFromTangentSpace(interaction.getTangentSpaceV(), L, interaction.getFromTangentSpace()); - } - - sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector) u) - { - return generate_wo_clamps(interaction, u); - } - - scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) - { - return sampling::ProjectedHemisphere::pdf(params.NdotL); - } - - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) - { - scalar_type _pdf; - return sampling::ProjectedHemisphere::template quotient_and_pdf(params.NdotL); - } -}; - - -template && surface_interactions::Isotropic && surface_interactions::Anisotropic) -struct SOrenNayarBxDF -{ - using this_t = SOrenNayarBxDF; - using scalar_type = typename LightSample::scalar_type; - using vector2_type = vector; - using ray_dir_info_type = typename LightSample::ray_dir_info_type; - - using isotropic_type = Iso; - using anisotropic_type = Aniso; - using sample_type = LightSample; - using spectral_type = Spectrum; - using quotient_pdf_type = quotient_and_pdf; - using params_t = SBxDFParams; - - static this_t create(scalar_type A) - { - this_t retval; - retval.A = A; - return retval; - } - - static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - return create(params.A.x); - } - - void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - A = params.A.x; - } - - scalar_type __rec_pi_factored_out_wo_clamps(scalar_type VdotL, scalar_type maxNdotL, scalar_type maxNdotV) - { - scalar_type A2 = A * 0.5; - vector2_type AB = vector2_type(1.0, 0.0) + vector2_type(-0.5, 0.45) * vector2_type(A2, A2) / vector2_type(A2 + 0.33, A2 + 0.09); - scalar_type C = 1.0 / max(maxNdotL, maxNdotV); - - scalar_type cos_phi_sin_theta = max(VdotL - maxNdotL * maxNdotV, 0.0); - return (AB.x + AB.y * cos_phi_sin_theta * C); - } - - scalar_type eval(NBL_CONST_REF_ARG(params_t) params) - { - return params.NdotL * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(params.VdotL, params.NdotL, params.NdotV); - } - - sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector2_type) u) - { - ray_dir_info_type L; - L.direction = sampling::ProjectedHemisphere::generate(u); - return sample_type::createFromTangentSpace(interaction.getTangentSpaceV(), L, interaction.getFromTangentSpace()); - } - - sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector2_type) u) - { - return generate_wo_clamps(interaction, u); - } - - scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) - { - return sampling::ProjectedHemisphere::pdf(params.NdotL); - } - - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) - { - scalar_type _pdf = pdf(params); - scalar_type q = __rec_pi_factored_out_wo_clamps(params.VdotL, params.NdotL, params.NdotV); - return quotient_pdf_type::create(hlsl::promote(q), _pdf); - } - - scalar_type A; -}; - - -// microfacet bxdfs - -// do not use, not tested, also shit -template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) -struct SBlinnPhongBxDF -{ - using this_t = SBlinnPhongBxDF; - using scalar_type = typename LightSample::scalar_type; - using ray_dir_info_type = typename LightSample::ray_dir_info_type; - using vector2_type = vector; - using vector3_type = vector; - using matrix2x3_type = matrix; - using params_t = SBxDFParams; - - using isotropic_type = typename IsoCache::isotropic_type; - using anisotropic_type = typename AnisoCache::anisotropic_type; - using sample_type = LightSample; - using spectral_type = Spectrum; - using quotient_pdf_type = quotient_and_pdf; - using isocache_type = IsoCache; - using anisocache_type = AnisoCache; - - static this_t create(vector2_type n, spectral_type ior0, spectral_type ior1) - { - this_t retval; - retval.n = n; - retval.ior0 = ior0; - retval.ior1 = ior1; - return retval; - } - - template - static T phong_exp_to_alpha2(T n) - { - return 2.0 / (n + 2.0); - } - - template - static T alpha2_to_phong_exp(T a2) - { - return 2.0 / a2 - 2.0; - } - - template // this or specialize? - scalar_type __eval_DG_wo_clamps(params_t params, vector2_type a2) - { - if (aniso) - { - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(params.NdotH, 1.0 / (1.0 - params.NdotH2), params.TdotH2, params.BdotH2, n.x, n.y); - ndf::BlinnPhong blinn_phong; - scalar_type DG = blinn_phong(ndfparams); - if (any >(a2 > (vector2_type)numeric_limits::min)) - { - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(a2.x, a2.y, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, 0); - smith::Beckmann beckmann; - DG *= beckmann.correlated(smithparams); - } - return DG; - } - else - { - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(n, params.NdotH, params.NdotH2); - ndf::BlinnPhong blinn_phong; - scalar_type NG = blinn_phong(ndfparams); - if (any >(a2 > (vector2_type)numeric_limits::min)) - { - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2.x, params.NdotV2, params.NdotL2, 0); - smith::Beckmann beckmann; - NG *= beckmann.correlated(smithparams); - } - return NG; - } - } - - template - vector3_type __eval_wo_clamps(params_t params) - { - scalar_type scalar_part; - if (aniso) - { - vector2_type a2 = phong_exp_to_alpha2(n); - scalar_part = __eval_DG_wo_clamps(params, a2); - } - else - { - vector2_type a2 = (vector2_type)phong_exp_to_alpha2(n); - scalar_part = __eval_DG_wo_clamps(params, a2); - } - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotV); - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.VdotH); - return f() * microfacet_transform(); - } - - vector3_type eval(sample_type _sample, isotropic_type interaction, isocache_type cache) - { - if (interaction.isotropic.getNdotV() > numeric_limits::min) - { - params_t params = params_t::template create(_sample, interaction, cache); - return __eval_wo_clamps(params); - } - else - return (vector3_type)0.0; - } - - vector3_type eval(sample_type _sample, anisotropic_type interaction, anisocache_type cache) - { - if (interaction.isotropic.getNdotV() > numeric_limits::min) - { - params_t params = params_t::template create(_sample, interaction, cache); - return __eval_wo_clamps(params); - } - else - return (vector3_type)0.0; - } - - vector3_type generate(vector2_type u, scalar_type n) - { - scalar_type phi = 2.0 * numbers::pi * u.y; - scalar_type cosTheta = pow(u.x, 1.0/(n+1.0)); - scalar_type sinTheta = sqrt(1.0 - cosTheta * cosTheta); - scalar_type cosPhi = cos(phi); - scalar_type sinPhi = sin(phi); - return vector3_type(cosPhi * sinTheta, sinPhi * sinTheta, cosTheta); - } - - sample_type generate(anisotropic_type interaction, vector2_type u, NBL_REF_ARG(anisocache_type) cache) - { - const vector3_type H = generate(u, n.x); - const vector3_type localV = interaction.getTangentSpaceV(); - - cache = anisocache_type::create(localV, H); - ray_dir_info_type localL; - bxdf::Reflect r = bxdf::Reflect::create(localV, H, cache.iso_cache.getVdotH()); - localL.direction = r(); - - return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); - } - - // where pdf? - - vector2_type n; - spectral_type ior0, ior1; -}; - -template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) -struct SBeckmannBxDF -{ - using this_t = SBeckmannBxDF; - using scalar_type = typename LightSample::scalar_type; - using ray_dir_info_type = typename LightSample::ray_dir_info_type; - using vector2_type = vector; - using vector3_type = vector; - using matrix2x3_type = matrix; - using params_t = SBxDFParams; - - using isotropic_type = typename IsoCache::isotropic_type; - using anisotropic_type = typename AnisoCache::anisotropic_type; - using sample_type = LightSample; - using spectral_type = Spectrum; - using quotient_pdf_type = quotient_and_pdf; - using isocache_type = IsoCache; - using anisocache_type = AnisoCache; - - // iso - static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) - { - this_t retval; - retval.A = vector2_type(A,A); - retval.ior0 = ior0; - retval.ior1 = ior1; - return retval; - } - - // aniso - static this_t create(scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) - { - this_t retval; - retval.A = vector2_type(ax,ay); - retval.ior0 = ior0; - retval.ior1 = ior1; - return retval; - } - static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - if (params.is_aniso) - return create(params.A.x, params.A.y, params.ior0, params.ior1); - else - return create(params.A.x, params.ior0, params.ior1); - } - - void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - A = params.A; - ior0 = params.ior0; - ior1 = params.ior1; - } - - scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_t) params) - { - if (params.is_aniso) - { - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); - ndf::Beckmann beckmann_ndf; - scalar_type NG = beckmann_ndf(ndfparams); - if (any >(A > (vector2_type)numeric_limits::min)) - { - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, 0); - smith::Beckmann beckmann_smith; - NG *= beckmann_smith.correlated(smithparams); - } - return NG; - } - else - { - scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); - ndf::Beckmann beckmann_ndf; - scalar_type NG = beckmann_ndf(ndfparams); - if (a2 > numeric_limits::min) - { - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.NdotV2, params.NdotL2, 0); - smith::Beckmann beckmann_smith; - NG *= beckmann_smith.correlated(smithparams); - } - return NG; - } - } - - spectral_type eval(params_t params) - { - if (params.uNdotV > numeric_limits::min) - { - scalar_type scalar_part = __eval_DG_wo_clamps(params); - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.uNdotV); - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.VdotH); - return f() * microfacet_transform(); - } - else - return (spectral_type)0.0; - } - - vector3_type __generate(NBL_CONST_REF_ARG(vector3_type) localV, NBL_CONST_REF_ARG(vector2_type) u) - { - //stretch - vector3_type V = nbl::hlsl::normalize(vector3_type(A.x * localV.x, A.y * localV.y, localV.z)); - - vector2_type slope; - if (V.z > 0.9999)//V.z=NdotV=cosTheta in tangent space - { - scalar_type r = sqrt(-log(1.0 - u.x)); - scalar_type sinPhi = sin(2.0 * numbers::pi * u.y); - scalar_type cosPhi = cos(2.0 * numbers::pi * u.y); - slope = (vector2_type)r * vector2_type(cosPhi,sinPhi); - } - else - { - scalar_type cosTheta = V.z; - scalar_type sinTheta = sqrt(1.0 - cosTheta * cosTheta); - scalar_type tanTheta = sinTheta / cosTheta; - scalar_type cotTheta = 1.0 / tanTheta; - - scalar_type a = -1.0; - scalar_type c = erf(cosTheta); - scalar_type sample_x = max(u.x, 1.0e-6); - scalar_type theta = acos(cosTheta); - scalar_type fit = 1.0 + theta * (-0.876 + theta * (0.4265 - 0.0594*theta)); - scalar_type b = c - (1.0 + c) * pow(1.0-sample_x, fit); - - scalar_type normalization = 1.0 / (1.0 + c + numbers::inv_sqrtpi * tanTheta * exp(-cosTheta*cosTheta)); - - const int ITER_THRESHOLD = 10; - const float MAX_ACCEPTABLE_ERR = 1.0e-5; - int it = 0; - float value=1000.0; - while (++it < ITER_THRESHOLD && nbl::hlsl::abs(value) > MAX_ACCEPTABLE_ERR) - { - if (!(b >= a && b <= c)) - b = 0.5 * (a + c); - - float invErf = erfInv(b); - value = normalization * (1.0 + b + numbers::inv_sqrtpi * tanTheta * exp(-invErf * invErf)) - sample_x; - float derivative = normalization * (1.0 - invErf * cosTheta); - - if (value > 0.0) - c = b; - else - a = b; - - b -= value/derivative; - } - // TODO: investigate if we can replace these two erf^-1 calls with a box muller transform - slope.x = erfInv(b); - slope.y = erfInv(2.0 * max(u.y, 1.0e-6) - 1.0); - } - - scalar_type sinTheta = sqrt(1.0 - V.z*V.z); - scalar_type cosPhi = sinTheta==0.0 ? 1.0 : clamp(V.x/sinTheta, -1.0, 1.0); - scalar_type sinPhi = sinTheta==0.0 ? 0.0 : clamp(V.y/sinTheta, -1.0, 1.0); - //rotate - scalar_type tmp = cosPhi*slope.x - sinPhi*slope.y; - slope.y = sinPhi*slope.x + cosPhi*slope.y; - slope.x = tmp; - - //unstretch - slope = vector2_type(A.x,A.y)*slope; - - return nbl::hlsl::normalize(vector3_type(-slope, 1.0)); - } - - sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector2_type) u, NBL_REF_ARG(anisocache_type) cache) - { - const vector3_type localV = interaction.getTangentSpaceV(); - const vector3_type H = __generate(localV, u); - - cache = anisocache_type::create(localV, H); - ray_dir_info_type localL; - bxdf::Reflect r = bxdf::Reflect::create(localV, H, cache.iso_cache.getVdotH()); - localL.direction = r(); - - return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); - } - - scalar_type pdf(NBL_CONST_REF_ARG(params_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) - { - scalar_type ndf, lambda; - if (params.is_aniso) - { - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, A.x*A.x, A.y*A.y, params.TdotH2, params.BdotH2, params.NdotH2); - ndf::Beckmann beckmann_ndf; - ndf = beckmann_ndf(ndfparams); - - smith::Beckmann beckmann_smith; - const scalar_type c2 = beckmann_smith.C2(params.TdotV2, params.BdotV2, params.NdotV2, A.x, A.y); - lambda = beckmann_smith.Lambda(c2); - } - else - { - scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); - ndf::Beckmann beckmann_ndf; - ndf = beckmann_ndf(ndfparams); - - smith::Beckmann beckmann_smith; - lambda = beckmann_smith.Lambda(params.NdotV2, a2); - } - - return smith::VNDF_pdf_wo_clamps >(ndf, lambda, params.uNdotV, onePlusLambda_V); - } - - scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) - { - scalar_type dummy; - return pdf(params, dummy); - } - - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) - { - scalar_type onePlusLambda_V; - scalar_type _pdf = pdf(params, onePlusLambda_V); - - smith::Beckmann beckmann_smith; - spectral_type quo = (spectral_type)0.0; - if (params.uNdotL > numeric_limits::min && params.uNdotV > numeric_limits::min) - { - scalar_type G2_over_G1; - if (params.is_aniso) - { - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(A.x*A.x, A.y*A.y, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, onePlusLambda_V); - G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); - } - else - { - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(A.x*A.x, params.NdotV2, params.NdotL2, onePlusLambda_V); - G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); - } - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.VdotH); - const spectral_type reflectance = f(); - quo = reflectance * G2_over_G1; - } - - return quotient_pdf_type::create(quo, _pdf); - } - - vector2_type A; - spectral_type ior0, ior1; -}; - -template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) -struct SGGXBxDF -{ - using this_t = SGGXBxDF; - using scalar_type = typename LightSample::scalar_type; - using ray_dir_info_type = typename LightSample::ray_dir_info_type; - using vector2_type = vector; - using vector3_type = vector; - using matrix2x3_type = matrix; - using params_t = SBxDFParams; - - using isotropic_type = typename IsoCache::isotropic_type; - using anisotropic_type = typename AnisoCache::anisotropic_type; - using sample_type = LightSample; - using spectral_type = Spectrum; - using quotient_pdf_type = quotient_and_pdf; - using isocache_type = IsoCache; - using anisocache_type = AnisoCache; - - // iso - static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) - { - this_t retval; - retval.A = vector2_type(A,A); - retval.ior0 = ior0; - retval.ior1 = ior1; - return retval; - } - - // aniso - static this_t create(scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) - { - this_t retval; - retval.A = vector2_type(ax,ay); - retval.ior0 = ior0; - retval.ior1 = ior1; - return retval; - } - - static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - if (params.is_aniso) - return create(params.A.x, params.A.y, params.ior0, params.ior1); - else - return create(params.A.x, params.ior0, params.ior1); - } - - void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - A = params.A; - ior0 = params.ior0; - ior1 = params.ior1; - } - - scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_t) params) - { - if (params.is_aniso) - { - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); - ndf::GGX ggx_ndf; - scalar_type NG = ggx_ndf(ndfparams); - if (any >(A > (vector2_type)numeric_limits::min)) - { - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2); - smith::GGX ggx_smith; - NG *= ggx_smith.correlated_wo_numerator(smithparams); - } - return NG; - } - else - { - scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); - ndf::GGX ggx_ndf; - scalar_type NG = ggx_ndf(ndfparams); - if (a2 > numeric_limits::min) - { - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.NdotV, params.NdotV2, params.NdotL, params.NdotL2); - smith::GGX ggx_smith; - NG *= ggx_smith.correlated_wo_numerator(smithparams); - } - return NG; - } - } - - spectral_type eval(NBL_CONST_REF_ARG(params_t) params) - { - if (params.uNdotL > numeric_limits::min && params.uNdotV > numeric_limits::min) - { - scalar_type scalar_part = __eval_DG_wo_clamps(params); - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotL); - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.VdotH); - return f() * microfacet_transform(); - } - else - return (spectral_type)0.0; - } - - vector3_type __generate(NBL_CONST_REF_ARG(vector3_type) localV, NBL_CONST_REF_ARG(vector2_type) u) - { - vector3_type V = nbl::hlsl::normalize(vector3_type(A.x*localV.x, A.y*localV.y, localV.z));//stretch view vector so that we're sampling as if roughness=1.0 - - scalar_type lensq = V.x*V.x + V.y*V.y; - vector3_type T1 = lensq > 0.0 ? vector3_type(-V.y, V.x, 0.0) * rsqrt(lensq) : vector3_type(1.0,0.0,0.0); - vector3_type T2 = cross(V,T1); - - scalar_type r = sqrt(u.x); - scalar_type phi = 2.0 * numbers::pi * u.y; - scalar_type t1 = r * cos(phi); - scalar_type t2 = r * sin(phi); - scalar_type s = 0.5 * (1.0 + V.z); - t2 = (1.0 - s)*sqrt(1.0 - t1*t1) + s*t2; - - //reprojection onto hemisphere - //TODO try it wothout the max(), not sure if -t1*t1-t2*t2>-1.0 - vector3_type H = t1*T1 + t2*T2 + sqrt(max(0.0, 1.0-t1*t1-t2*t2))*V; - //unstretch - return nbl::hlsl::normalize(vector3_type(A.x*H.x, A.y*H.y, H.z)); - } - - sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector2_type) u, NBL_REF_ARG(anisocache_type) cache) - { - const vector3_type localV = interaction.getTangentSpaceV(); - const vector3_type H = __generate(localV, u); - - cache = anisocache_type::create(localV, H); - ray_dir_info_type localL; - bxdf::Reflect r = bxdf::Reflect::create(localV, H, cache.iso_cache.getVdotH()); - localL.direction = r(); - - return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); - } - - scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) - { - scalar_type ndf, G1_over_2NdotV; - if (params.is_aniso) - { - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); - ndf::GGX ggx_ndf; - ndf = ggx_ndf(ndfparams); - - smith::GGX ggx_smith; - const scalar_type devsh_v = ggx_smith.devsh_part(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); - G1_over_2NdotV = ggx_smith.G1_wo_numerator(params.uNdotV, devsh_v); - } - else - { - const scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); - ndf::GGX ggx_ndf; - ndf = ggx_ndf(ndfparams); - - smith::GGX ggx_smith; - const scalar_type devsh_v = ggx_smith.devsh_part(params.NdotV2, a2, 1.0-a2); - G1_over_2NdotV = ggx_smith.G1_wo_numerator(params.uNdotV, devsh_v); - } - return smith::VNDF_pdf_wo_clamps(ndf, G1_over_2NdotV); - } - - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) - { - scalar_type _pdf = pdf(params); - - spectral_type quo = (spectral_type)0.0; - if (params.uNdotL > numeric_limits::min && params.uNdotV > numeric_limits::min) - { - scalar_type G2_over_G1; - smith::GGX ggx_smith; - if (params.is_aniso) - { - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.uNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.uNdotL, params.TdotL2, params.BdotL2, params.NdotL2); - G2_over_G1 = ggx_smith.G2_over_G1(smithparams); - } - else - { - const scalar_type a2 = A.x*A.x; - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.uNdotV, params.NdotV2, params.uNdotL, params.NdotL2); - G2_over_G1 = ggx_smith.G2_over_G1(smithparams); - } - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.VdotH); - const spectral_type reflectance = f(); - quo = reflectance * G2_over_G1; - } - - return quotient_pdf_type::create(quo, _pdf); - } - - vector2_type A; - spectral_type ior0, ior1; -}; - -} -} // After Clang-HLSL introduces https://en.cppreference.com/w/cpp/language/namespace_alias // namespace brdf = bxdf::reflection; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl new file mode 100644 index 0000000000..a7cf63ec38 --- /dev/null +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -0,0 +1,271 @@ +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_BUILTIN_HLSL_BXDF_REFLECTION_BECKMANN_INCLUDED_ +#define _NBL_BUILTIN_HLSL_BXDF_REFLECTION_BECKMANN_INCLUDED_ + +#include "nbl/builtin/hlsl/bxdf/common.hlsl" +#include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" +#include "nbl/builtin/hlsl/bxdf/geom_smith.hlsl" + +namespace nbl +{ +namespace hlsl +{ +namespace bxdf +{ +namespace reflection +{ + +template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) +struct SBeckmannBxDF +{ + using this_t = SBeckmannBxDF; + using scalar_type = typename LightSample::scalar_type; + using ray_dir_info_type = typename LightSample::ray_dir_info_type; + using vector2_type = vector; + using vector3_type = vector; + using matrix2x3_type = matrix; + using params_t = SBxDFParams; + + using isotropic_type = typename IsoCache::isotropic_type; + using anisotropic_type = typename AnisoCache::anisotropic_type; + using sample_type = LightSample; + using spectral_type = Spectrum; + using quotient_pdf_type = sampling::quotient_and_pdf; + using isocache_type = IsoCache; + using anisocache_type = AnisoCache; + + // iso + static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) + { + this_t retval; + retval.A = vector2_type(A,A); + retval.ior0 = ior0; + retval.ior1 = ior1; + return retval; + } + + // aniso + static this_t create(scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) + { + this_t retval; + retval.A = vector2_type(ax,ay); + retval.ior0 = ior0; + retval.ior1 = ior1; + return retval; + } + + static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) + { + if (params.is_aniso) + return create(params.A.x, params.A.y, params.ior0, params.ior1); + else + return create(params.A.x, params.ior0, params.ior1); + } + + void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) + { + A = params.A; + ior0 = params.ior0; + ior1 = params.ior1; + } + + scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_t) params) + { + if (params.is_aniso) + { + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + ndf::Beckmann beckmann_ndf; + scalar_type NG = beckmann_ndf(ndfparams); + if (any >(A > (vector2_type)numeric_limits::min)) + { + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, 0); + smith::Beckmann beckmann_smith; + NG *= beckmann_smith.correlated(smithparams); + } + return NG; + } + else + { + scalar_type a2 = A.x*A.x; + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); + ndf::Beckmann beckmann_ndf; + scalar_type NG = beckmann_ndf(ndfparams); + if (a2 > numeric_limits::min) + { + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.NdotV2, params.NdotL2, 0); + smith::Beckmann beckmann_smith; + NG *= beckmann_smith.correlated(smithparams); + } + return NG; + } + } + + spectral_type eval(params_t params) + { + if (params.uNdotV > numeric_limits::min) + { + scalar_type scalar_part = __eval_DG_wo_clamps(params); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.uNdotV); + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.VdotH); + return f() * microfacet_transform(); + } + else + return (spectral_type)0.0; + } + + vector3_type __generate(NBL_CONST_REF_ARG(vector3_type) localV, NBL_CONST_REF_ARG(vector2_type) u) + { + //stretch + vector3_type V = nbl::hlsl::normalize(vector3_type(A.x * localV.x, A.y * localV.y, localV.z)); + + vector2_type slope; + if (V.z > 0.9999)//V.z=NdotV=cosTheta in tangent space + { + scalar_type r = sqrt(-log(1.0 - u.x)); + scalar_type sinPhi = sin(2.0 * numbers::pi * u.y); + scalar_type cosPhi = cos(2.0 * numbers::pi * u.y); + slope = (vector2_type)r * vector2_type(cosPhi,sinPhi); + } + else + { + scalar_type cosTheta = V.z; + scalar_type sinTheta = sqrt(1.0 - cosTheta * cosTheta); + scalar_type tanTheta = sinTheta / cosTheta; + scalar_type cotTheta = 1.0 / tanTheta; + + scalar_type a = -1.0; + scalar_type c = erf(cosTheta); + scalar_type sample_x = max(u.x, 1.0e-6); + scalar_type theta = acos(cosTheta); + scalar_type fit = 1.0 + theta * (-0.876 + theta * (0.4265 - 0.0594*theta)); + scalar_type b = c - (1.0 + c) * pow(1.0-sample_x, fit); + + scalar_type normalization = 1.0 / (1.0 + c + numbers::inv_sqrtpi * tanTheta * exp(-cosTheta*cosTheta)); + + const int ITER_THRESHOLD = 10; + const float MAX_ACCEPTABLE_ERR = 1.0e-5; + int it = 0; + float value=1000.0; + while (++it < ITER_THRESHOLD && nbl::hlsl::abs(value) > MAX_ACCEPTABLE_ERR) + { + if (!(b >= a && b <= c)) + b = 0.5 * (a + c); + + float invErf = erfInv(b); + value = normalization * (1.0 + b + numbers::inv_sqrtpi * tanTheta * exp(-invErf * invErf)) - sample_x; + float derivative = normalization * (1.0 - invErf * cosTheta); + + if (value > 0.0) + c = b; + else + a = b; + + b -= value/derivative; + } + // TODO: investigate if we can replace these two erf^-1 calls with a box muller transform + slope.x = erfInv(b); + slope.y = erfInv(2.0 * max(u.y, 1.0e-6) - 1.0); + } + + scalar_type sinTheta = sqrt(1.0 - V.z*V.z); + scalar_type cosPhi = sinTheta==0.0 ? 1.0 : clamp(V.x/sinTheta, -1.0, 1.0); + scalar_type sinPhi = sinTheta==0.0 ? 0.0 : clamp(V.y/sinTheta, -1.0, 1.0); + //rotate + scalar_type tmp = cosPhi*slope.x - sinPhi*slope.y; + slope.y = sinPhi*slope.x + cosPhi*slope.y; + slope.x = tmp; + + //unstretch + slope = vector2_type(A.x,A.y)*slope; + + return nbl::hlsl::normalize(vector3_type(-slope, 1.0)); + } + + sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector2_type) u, NBL_REF_ARG(anisocache_type) cache) + { + const vector3_type localV = interaction.getTangentSpaceV(); + const vector3_type H = __generate(localV, u); + + cache = anisocache_type::create(localV, H); + ray_dir_info_type localL; + bxdf::Reflect r = bxdf::Reflect::create(localV, H, cache.iso_cache.getVdotH()); + localL.direction = r(); + + return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); + } + + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) + { + scalar_type ndf, lambda; + if (params.is_aniso) + { + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, A.x*A.x, A.y*A.y, params.TdotH2, params.BdotH2, params.NdotH2); + ndf::Beckmann beckmann_ndf; + ndf = beckmann_ndf(ndfparams); + + smith::Beckmann beckmann_smith; + const scalar_type c2 = beckmann_smith.C2(params.TdotV2, params.BdotV2, params.NdotV2, A.x, A.y); + lambda = beckmann_smith.Lambda(c2); + } + else + { + scalar_type a2 = A.x*A.x; + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); + ndf::Beckmann beckmann_ndf; + ndf = beckmann_ndf(ndfparams); + + smith::Beckmann beckmann_smith; + lambda = beckmann_smith.Lambda(params.NdotV2, a2); + } + + return smith::VNDF_pdf_wo_clamps >(ndf, lambda, params.uNdotV, onePlusLambda_V); + } + + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) + { + scalar_type dummy; + return pdf(params, dummy); + } + + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) + { + scalar_type onePlusLambda_V; + scalar_type _pdf = pdf(params, onePlusLambda_V); + + smith::Beckmann beckmann_smith; + spectral_type quo = (spectral_type)0.0; + if (params.uNdotL > numeric_limits::min && params.uNdotV > numeric_limits::min) + { + scalar_type G2_over_G1; + if (params.is_aniso) + { + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(A.x*A.x, A.y*A.y, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, onePlusLambda_V); + G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); + } + else + { + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(A.x*A.x, params.NdotV2, params.NdotL2, onePlusLambda_V); + G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); + } + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.VdotH); + const spectral_type reflectance = f(); + quo = reflectance * G2_over_G1; + } + + return quotient_pdf_type::create(quo, _pdf); + } + + vector2_type A; + spectral_type ior0, ior1; +}; + +} +} +} +} + +#endif diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl new file mode 100644 index 0000000000..0621ce6f63 --- /dev/null +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -0,0 +1,223 @@ +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_BUILTIN_HLSL_BXDF_REFLECTION_GGX_INCLUDED_ +#define _NBL_BUILTIN_HLSL_BXDF_REFLECTION_GGX_INCLUDED_ + +#include "nbl/builtin/hlsl/bxdf/common.hlsl" +#include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" +#include "nbl/builtin/hlsl/bxdf/geom_smith.hlsl" + +namespace nbl +{ +namespace hlsl +{ +namespace bxdf +{ +namespace reflection +{ + +template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) +struct SGGXBxDF +{ + using this_t = SGGXBxDF; + using scalar_type = typename LightSample::scalar_type; + using ray_dir_info_type = typename LightSample::ray_dir_info_type; + using vector2_type = vector; + using vector3_type = vector; + using matrix2x3_type = matrix; + using params_t = SBxDFParams; + + using isotropic_type = typename IsoCache::isotropic_type; + using anisotropic_type = typename AnisoCache::anisotropic_type; + using sample_type = LightSample; + using spectral_type = Spectrum; + using quotient_pdf_type = sampling::quotient_and_pdf; + using isocache_type = IsoCache; + using anisocache_type = AnisoCache; + + // iso + static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) + { + this_t retval; + retval.A = vector2_type(A,A); + retval.ior0 = ior0; + retval.ior1 = ior1; + return retval; + } + + // aniso + static this_t create(scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) + { + this_t retval; + retval.A = vector2_type(ax,ay); + retval.ior0 = ior0; + retval.ior1 = ior1; + return retval; + } + + static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) + { + if (params.is_aniso) + return create(params.A.x, params.A.y, params.ior0, params.ior1); + else + return create(params.A.x, params.ior0, params.ior1); + } + + void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) + { + A = params.A; + ior0 = params.ior0; + ior1 = params.ior1; + } + + scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_t) params) + { + if (params.is_aniso) + { + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + ndf::GGX ggx_ndf; + scalar_type NG = ggx_ndf(ndfparams); + if (any >(A > (vector2_type)numeric_limits::min)) + { + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2); + smith::GGX ggx_smith; + NG *= ggx_smith.correlated_wo_numerator(smithparams); + } + return NG; + } + else + { + scalar_type a2 = A.x*A.x; + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); + ndf::GGX ggx_ndf; + scalar_type NG = ggx_ndf(ndfparams); + if (a2 > numeric_limits::min) + { + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.NdotV, params.NdotV2, params.NdotL, params.NdotL2); + smith::GGX ggx_smith; + NG *= ggx_smith.correlated_wo_numerator(smithparams); + } + return NG; + } + } + + spectral_type eval(NBL_CONST_REF_ARG(params_t) params) + { + if (params.uNdotL > numeric_limits::min && params.uNdotV > numeric_limits::min) + { + scalar_type scalar_part = __eval_DG_wo_clamps(params); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotL); + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.VdotH); + return f() * microfacet_transform(); + } + else + return (spectral_type)0.0; + } + + vector3_type __generate(NBL_CONST_REF_ARG(vector3_type) localV, NBL_CONST_REF_ARG(vector2_type) u) + { + vector3_type V = nbl::hlsl::normalize(vector3_type(A.x*localV.x, A.y*localV.y, localV.z));//stretch view vector so that we're sampling as if roughness=1.0 + + scalar_type lensq = V.x*V.x + V.y*V.y; + vector3_type T1 = lensq > 0.0 ? vector3_type(-V.y, V.x, 0.0) * rsqrt(lensq) : vector3_type(1.0,0.0,0.0); + vector3_type T2 = cross(V,T1); + + scalar_type r = sqrt(u.x); + scalar_type phi = 2.0 * numbers::pi * u.y; + scalar_type t1 = r * cos(phi); + scalar_type t2 = r * sin(phi); + scalar_type s = 0.5 * (1.0 + V.z); + t2 = (1.0 - s)*sqrt(1.0 - t1*t1) + s*t2; + + //reprojection onto hemisphere + //TODO try it wothout the max(), not sure if -t1*t1-t2*t2>-1.0 + vector3_type H = t1*T1 + t2*T2 + sqrt(max(0.0, 1.0-t1*t1-t2*t2))*V; + //unstretch + return nbl::hlsl::normalize(vector3_type(A.x*H.x, A.y*H.y, H.z)); + } + + sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector2_type) u, NBL_REF_ARG(anisocache_type) cache) + { + const vector3_type localV = interaction.getTangentSpaceV(); + const vector3_type H = __generate(localV, u); + + cache = anisocache_type::create(localV, H); + ray_dir_info_type localL; + bxdf::Reflect r = bxdf::Reflect::create(localV, H, cache.iso_cache.getVdotH()); + localL.direction = r(); + + return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); + } + + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) + { + scalar_type ndf, G1_over_2NdotV; + if (params.is_aniso) + { + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + ndf::GGX ggx_ndf; + ndf = ggx_ndf(ndfparams); + + smith::GGX ggx_smith; + const scalar_type devsh_v = ggx_smith.devsh_part(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); + G1_over_2NdotV = ggx_smith.G1_wo_numerator(params.uNdotV, devsh_v); + } + else + { + const scalar_type a2 = A.x*A.x; + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); + ndf::GGX ggx_ndf; + ndf = ggx_ndf(ndfparams); + + smith::GGX ggx_smith; + const scalar_type devsh_v = ggx_smith.devsh_part(params.NdotV2, a2, 1.0-a2); + G1_over_2NdotV = ggx_smith.G1_wo_numerator(params.uNdotV, devsh_v); + } + return smith::VNDF_pdf_wo_clamps(ndf, G1_over_2NdotV); + } + + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) + { + scalar_type _pdf = pdf(params); + + spectral_type quo = (spectral_type)0.0; + if (params.uNdotL > numeric_limits::min && params.uNdotV > numeric_limits::min) + { + scalar_type G2_over_G1; + smith::GGX ggx_smith; + if (params.is_aniso) + { + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.uNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.uNdotL, params.TdotL2, params.BdotL2, params.NdotL2); + G2_over_G1 = ggx_smith.G2_over_G1(smithparams); + } + else + { + const scalar_type a2 = A.x*A.x; + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.uNdotV, params.NdotV2, params.uNdotL, params.NdotL2); + G2_over_G1 = ggx_smith.G2_over_G1(smithparams); + } + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.VdotH); + const spectral_type reflectance = f(); + quo = reflectance * G2_over_G1; + } + + return quotient_pdf_type::create(quo, _pdf); + } + + vector2_type A; + spectral_type ior0, ior1; +}; + +} +} +} +} + +#endif diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl new file mode 100644 index 0000000000..8e47e39e85 --- /dev/null +++ b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl @@ -0,0 +1,89 @@ +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_BUILTIN_HLSL_BXDF_REFLECTION_LAMBERTIAN_INCLUDED_ +#define _NBL_BUILTIN_HLSL_BXDF_REFLECTION_LAMBERTIAN_INCLUDED_ + +#include "nbl/builtin/hlsl/bxdf/common.hlsl" +#include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" +#include "nbl/builtin/hlsl/bxdf/geom_smith.hlsl" + +namespace nbl +{ +namespace hlsl +{ +namespace bxdf +{ +namespace reflection +{ + +template && surface_interactions::Isotropic && surface_interactions::Anisotropic) +struct SLambertianBxDF +{ + using this_t = SLambertianBxDF; + using scalar_type = typename LightSample::scalar_type; + using ray_dir_info_type = typename LightSample::ray_dir_info_type; + using isotropic_type = Iso; + using anisotropic_type = Aniso; + using sample_type = LightSample; + using spectral_type = Spectrum; + using quotient_pdf_type = sampling::quotient_and_pdf; + using params_t = SBxDFParams; + + static this_t create() + { + this_t retval; + // nothing here, just keeping in convention with others + return retval; + } + + static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) + { + return create(); + } + + void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) + { + // do nothing + } + + scalar_type __eval_pi_factored_out(scalar_type maxNdotL) + { + return maxNdotL; + } + + scalar_type eval(NBL_CONST_REF_ARG(params_t) params) + { + return __eval_pi_factored_out(params.NdotL) * numbers::inv_pi; + } + + sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector) u) + { + ray_dir_info_type L; + L.direction = sampling::ProjectedHemisphere::generate(u); + return sample_type::createFromTangentSpace(interaction.getTangentSpaceV(), L, interaction.getFromTangentSpace()); + } + + sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector) u) + { + return generate_wo_clamps(interaction, u); + } + + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) + { + return sampling::ProjectedHemisphere::pdf(params.NdotL); + } + + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) + { + scalar_type _pdf; + return sampling::ProjectedHemisphere::template quotient_and_pdf(params.NdotL); + } +}; + +} +} +} +} + +#endif diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl new file mode 100644 index 0000000000..b9525be19f --- /dev/null +++ b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl @@ -0,0 +1,99 @@ +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_BUILTIN_HLSL_BXDF_REFLECTION_OREN_NAYAR_INCLUDED_ +#define _NBL_BUILTIN_HLSL_BXDF_REFLECTION_OREN_NAYAR_INCLUDED_ + +#include "nbl/builtin/hlsl/bxdf/common.hlsl" +#include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" +#include "nbl/builtin/hlsl/bxdf/geom_smith.hlsl" + +namespace nbl +{ +namespace hlsl +{ +namespace bxdf +{ +namespace reflection +{ + +template && surface_interactions::Isotropic && surface_interactions::Anisotropic) +struct SOrenNayarBxDF +{ + using this_t = SOrenNayarBxDF; + using scalar_type = typename LightSample::scalar_type; + using vector2_type = vector; + using ray_dir_info_type = typename LightSample::ray_dir_info_type; + + using isotropic_type = Iso; + using anisotropic_type = Aniso; + using sample_type = LightSample; + using spectral_type = Spectrum; + using quotient_pdf_type = sampling::quotient_and_pdf; + using params_t = SBxDFParams; + + static this_t create(scalar_type A) + { + this_t retval; + retval.A = A; + return retval; + } + + static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) + { + return create(params.A.x); + } + + void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) + { + A = params.A.x; + } + + scalar_type __rec_pi_factored_out_wo_clamps(scalar_type VdotL, scalar_type maxNdotL, scalar_type maxNdotV) + { + scalar_type A2 = A * 0.5; + vector2_type AB = vector2_type(1.0, 0.0) + vector2_type(-0.5, 0.45) * vector2_type(A2, A2) / vector2_type(A2 + 0.33, A2 + 0.09); + scalar_type C = 1.0 / max(maxNdotL, maxNdotV); + + scalar_type cos_phi_sin_theta = max(VdotL - maxNdotL * maxNdotV, 0.0); + return (AB.x + AB.y * cos_phi_sin_theta * C); + } + + scalar_type eval(NBL_CONST_REF_ARG(params_t) params) + { + return params.NdotL * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(params.VdotL, params.NdotL, params.NdotV); + } + + sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector2_type) u) + { + ray_dir_info_type L; + L.direction = sampling::ProjectedHemisphere::generate(u); + return sample_type::createFromTangentSpace(interaction.getTangentSpaceV(), L, interaction.getFromTangentSpace()); + } + + sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector2_type) u) + { + return generate_wo_clamps(interaction, u); + } + + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) + { + return sampling::ProjectedHemisphere::pdf(params.NdotL); + } + + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) + { + scalar_type _pdf = pdf(params); + scalar_type q = __rec_pi_factored_out_wo_clamps(params.VdotL, params.NdotL, params.NdotV); + return quotient_pdf_type::create(hlsl::promote(q), _pdf); + } + + scalar_type A; +}; + +} +} +} +} + +#endif diff --git a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl index d9afa8a639..81f531e1a6 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission.hlsl @@ -1,672 +1,19 @@ -// Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O. +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice nabla.h #ifndef _NBL_BUILTIN_HLSL_BXDF_TRANSMISSION_INCLUDED_ #define _NBL_BUILTIN_HLSL_BXDF_TRANSMISSION_INCLUDED_ -#include "nbl/builtin/hlsl/bxdf/common.hlsl" -#include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" -#include "nbl/builtin/hlsl/bxdf/reflection.hlsl" +#include "nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl" +#include "nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl" +#include "nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl" +#include "nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl" namespace nbl { namespace hlsl { -namespace bxdf -{ -namespace transmission -{ - -// template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) -// LightSample cos_generate(NBL_CONST_REF_ARG(Iso) interaction) -// { -// return LightSample(interaction.V.transmit(),-1.f,interaction.N); -// } -// template && surface_interactions::Isotropic && surface_interactions::Anisotropic && ray_dir_info::Basic && is_scalar_v) -// LightSample cos_generate(NBL_CONST_REF_ARG(Aniso) interaction) -// { -// return LightSample(interaction.V.transmit(),-1.f,interaction.T,interaction.B,interaction.N); -// } - -// Why don't we check that the incoming and outgoing directions equal each other -// (or similar for other delta distributions such as reflect, or smooth [thin] dielectrics): -// - The `quotient_and_pdf` functions are meant to be used with MIS and RIS -// - Our own generator can never pick an improbable path, so no checking necessary -// - For other generators the estimator will be `f_BSDF*f_Light*f_Visibility*clampedCos(theta)/(1+(p_BSDF^alpha+p_otherNonChosenGenerator^alpha+...)/p_ChosenGenerator^alpha)` -// therefore when `p_BSDF` equals `nbl_glsl_FLT_INF` it will drive the overall MIS estimator for the other generators to 0 so no checking necessary -// template && is_floating_point_v) -// quotient_and_pdf cos_quotient_and_pdf() -// { -// return quotient_and_pdf::create(SpectralBins(1.f), numeric_limits::infinity); -// } - -// basic bxdf -template && surface_interactions::Isotropic && surface_interactions::Anisotropic) -struct SLambertianBxDF -{ - using this_t = SLambertianBxDF; - using scalar_type = typename LightSample::scalar_type; - using ray_dir_info_type = typename LightSample::ray_dir_info_type; - using isotropic_type = Iso; - using anisotropic_type = Aniso; - using sample_type = LightSample; - using spectral_type = Spectrum; - using quotient_pdf_type = quotient_and_pdf; - using params_t = SBxDFParams; - - static this_t create() - { - this_t retval; - // nothing here, just keeping convention with others - return retval; - } - - static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - return create(); - } - - void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - // do nothing - } - - scalar_type __eval_pi_factored_out(scalar_type absNdotL) - { - return absNdotL; - } - - scalar_type eval(NBL_CONST_REF_ARG(params_t) params) - { - return __eval_pi_factored_out(params.NdotL) * numbers::inv_pi * 0.5; - } - - sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector) u) - { - ray_dir_info_type L; - L.direction = sampling::ProjectedSphere::generate(u); - return sample_type::createFromTangentSpace(interaction.getTangentSpaceV(), L, interaction.getFromTangentSpace()); - } - - sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector) u) - { - return generate_wo_clamps(interaction, u); - } - - scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) - { - return sampling::ProjectedSphere::pdf(params.NdotL); - } - - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) - { - return sampling::ProjectedSphere::template quotient_and_pdf(params.NdotL); - } -}; - - -// microfacet bxdfs -template // NBL_FUNC_REQUIRES(Sample && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) // dxc won't let me put this in -struct SSmoothDielectricBxDF; - -template -struct SSmoothDielectricBxDF -{ - using this_t = SSmoothDielectricBxDF; - using scalar_type = typename LightSample::scalar_type; - using ray_dir_info_type = typename LightSample::ray_dir_info_type; - using vector3_type = vector; - using params_t = SBxDFParams; - - using isotropic_type = typename IsoCache::isotropic_type; - using anisotropic_type = typename AnisoCache::anisotropic_type; - using sample_type = LightSample; - using spectral_type = Spectrum; - using quotient_pdf_type = quotient_and_pdf; - using isocache_type = IsoCache; - using anisocache_type = AnisoCache; - - static this_t create(scalar_type eta) - { - this_t retval; - retval.eta = eta; - return retval; - } - - static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - return create(params.eta); - } - - void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - eta = params.eta; - } - - spectral_type eval(NBL_CONST_REF_ARG(params_t) params) - { - return (spectral_type)0; - } - - sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N, bool backside, scalar_type NdotV, scalar_type absNdotV, scalar_type NdotV2, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(bool) transmitted) - { - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, absNdotV); - - scalar_type rcpChoiceProb; - transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); - - ray_dir_info_type L; - Refract r = Refract::create(V, N, backside, NdotV, NdotV2, rcpOrientedEta, rcpOrientedEta2); - bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, r); - L.direction = rr(); - return sample_type::create(L, nbl::hlsl::dot(V, L.direction), T, B, N); - } - - sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector) u) - { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), eta); - scalar_type NdotV = interaction.isotropic.getNdotV(); - bool dummy; - return __generate_wo_clamps(interaction.isotropic.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.isotropic.getN(), orientedEta.backside, NdotV, - NdotV, NdotV*NdotV, u, orientedEta.rcp, orientedEta.value*orientedEta.value, orientedEta.rcp*orientedEta.rcp, dummy); - } - - sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector) u) - { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), eta); - scalar_type NdotV = interaction.isotropic.getNdotV(); - bool dummy; - return __generate_wo_clamps(interaction.isotropic.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.isotropic.getN(), orientedEta.backside, NdotV, - nbl::hlsl::abs(NdotV), NdotV*NdotV, u, orientedEta.rcp, orientedEta.value*orientedEta.value, orientedEta.rcp*orientedEta.rcp, dummy); - } - - // eval and pdf return 0 because smooth dielectric/conductor BxDFs are dirac delta distributions, model perfectly specular objects that scatter light to only one outgoing direction - scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) - { - return 0; - } - - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) - { - const bool transmitted = isTransmissionPath(params.uNdotV, params.uNdotL); - - fresnel::OrientedEtaRcps rcpOrientedEtas = fresnel::OrientedEtaRcps::create(params.NdotV, eta); - - const scalar_type _pdf = bit_cast(numeric_limits::infinity); - scalar_type quo = transmitted ? rcpOrientedEtas.value : 1.0; - return quotient_pdf_type::create((spectral_type)(quo), _pdf); - } - - scalar_type eta; -}; - -template -struct SSmoothDielectricBxDF -{ - using this_t = SSmoothDielectricBxDF; - using scalar_type = typename LightSample::scalar_type; - using ray_dir_info_type = typename LightSample::ray_dir_info_type; - using vector3_type = vector; - using params_t = SBxDFParams; - - using isotropic_type = typename IsoCache::isotropic_type; - using anisotropic_type = typename AnisoCache::anisotropic_type; - using sample_type = LightSample; - using spectral_type = Spectrum; - using quotient_pdf_type = quotient_and_pdf; - using isocache_type = IsoCache; - using anisocache_type = AnisoCache; - - static this_t create(NBL_CONST_REF_ARG(spectral_type) eta2, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) - { - this_t retval; - retval.eta2 = eta2; - retval.luminosityContributionHint = luminosityContributionHint; - return retval; - } - - static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - return create(params.eta2, params.luminosityContributionHint); - } - - void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - eta2 = params.eta2; - luminosityContributionHint = params.luminosityContributionHint; - } - - spectral_type eval(NBL_CONST_REF_ARG(params_t) params) - { - return (spectral_type)0; - } - - // usually `luminosityContributionHint` would be the Rec.709 luma coefficients (the Y row of the RGB to CIE XYZ matrix) - // its basically a set of weights that determine - // assert(1.0==luminosityContributionHint.r+luminosityContributionHint.g+luminosityContributionHint.b); - // `remainderMetadata` is a variable which the generator function returns byproducts of sample generation that would otherwise have to be redundantly calculated `quotient_and_pdf` - sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N, scalar_type NdotV, scalar_type absNdotV, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(spectral_type) eta2, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint, NBL_REF_ARG(spectral_type) remainderMetadata) - { - // we will only ever intersect from the outside - fresnel::ThinDielectricInfiniteScatter scatter; - const spectral_type reflectance = scatter(fresnel::Dielectric::__call(eta2,absNdotV)); - - // we are only allowed one choice for the entire ray, so make the probability a weighted sum - const scalar_type reflectionProb = nbl::hlsl::dot(reflectance, luminosityContributionHint); - - scalar_type rcpChoiceProb; - const bool transmitted = math::partitionRandVariable(reflectionProb, u.z, rcpChoiceProb); - remainderMetadata = (transmitted ? ((spectral_type)(1.0) - reflectance) : reflectance) * rcpChoiceProb; - - ray_dir_info_type L; - L.direction = (transmitted ? (vector3_type)(0.0) : N * 2.0f * NdotV) - V; - return sample_type::create(L, nbl::hlsl::dot(V, L.direction), T, B, N); - } - - sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector) u) - { - scalar_type NdotV = interaction.isotropic.getNdotV(); - vector3_type dummy; - return __generate_wo_clamps(interaction.isotropic.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.isotropic.getN(), NdotV, NdotV, u, eta2, luminosityContributionHint, dummy); - } - - sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector) u) - { - scalar_type NdotV = interaction.isotropic.getNdotV(); - vector3_type dummy; - return __generate_wo_clamps(interaction.isotropic.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.isotropic.getN(), NdotV, nbl::hlsl::abs(NdotV), u, eta2, luminosityContributionHint, dummy); - } - - scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) - { - return 0; - } - - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) // isotropic - { - const bool transmitted = isTransmissionPath(params.uNdotV, params.uNdotL); - fresnel::ThinDielectricInfiniteScatter scatter; - const spectral_type reflectance = scatter(fresnel::Dielectric::__call(eta2, params.NdotV)); - const spectral_type sampleValue = transmitted ? ((spectral_type)(1.0) - reflectance) : reflectance; - - const scalar_type sampleProb = nbl::hlsl::dot(sampleValue,luminosityContributionHint); - - const scalar_type _pdf = bit_cast(numeric_limits::infinity); - return quotient_pdf_type::create((spectral_type)(sampleValue / sampleProb), _pdf); - } - - spectral_type eta2; - spectral_type luminosityContributionHint; -}; - -template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) -struct SBeckmannDielectricBxDF -{ - using this_t = SBeckmannDielectricBxDF; - using scalar_type = typename LightSample::scalar_type; - using ray_dir_info_type = typename LightSample::ray_dir_info_type; - using vector2_type = vector; - using vector3_type = vector; - using matrix3x3_type = matrix; - using params_t = SBxDFParams; - - using isotropic_type = typename IsoCache::isotropic_type; - using anisotropic_type = typename AnisoCache::anisotropic_type; - using sample_type = LightSample; - using spectral_type = Spectrum; - using quotient_pdf_type = quotient_and_pdf; - using isocache_type = IsoCache; - using anisocache_type = AnisoCache; - - static this_t create(scalar_type eta, scalar_type A) - { - this_t retval; - retval.eta = eta; - retval.A = vector2_type(A, A); - return retval; - } - - static this_t create(scalar_type eta, scalar_type ax, scalar_type ay) - { - this_t retval; - retval.eta = eta; - retval.A = vector2_type(ax, ay); - return retval; - } - - static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - if (params.is_aniso) - return create(params.eta, params.A.x, params.A.y); - else - return create(params.eta, params.A.x); - } - - void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - A = params.A; - eta = params.eta; - } - - spectral_type eval(NBL_CONST_REF_ARG(params_t) params) - { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.VdotH, eta); - const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; - - const scalar_type VdotHLdotH = params.VdotH * params.LdotH; - const bool transmitted = VdotHLdotH < 0.0; - spectral_type dummyior; - reflection::SBeckmannBxDF beckmann; - if (params.is_aniso) - beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior, dummyior); - else - beckmann = reflection::SBeckmannBxDF::create(A.x, dummyior, dummyior); - const scalar_type scalar_part = beckmann.__eval_DG_wo_clamps(params); - - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,params.NdotV,transmitted,params.VdotH,params.LdotH,VdotHLdotH,orientedEta.value); - scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.VdotH)); - return hlsl::promote(f) * microfacet_transform(); - } - - sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) localV, bool backside, NBL_CONST_REF_ARG(vector3_type) H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) - { - const scalar_type localVdotH = nbl::hlsl::dot(localV,H); - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2,nbl::hlsl::abs(localVdotH)); - - scalar_type rcpChoiceProb; - bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); - - cache = anisocache_type::create(localV, H); - - const scalar_type VdotH = cache.iso_cache.getVdotH(); - cache.iso_cache.LdotH = transmitted ? Refract::computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; - ray_dir_info_type localL; - bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, localV, H, VdotH, cache.iso_cache.getLdotH(), rcpOrientedEta); - localL.direction = rr(); - - return sample_type::createFromTangentSpace(localV, localL, m); - } - - sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) - { - const vector3_type localV = interaction.getTangentSpaceV(); - - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), eta); - - const vector3_type upperHemisphereV = orientedEta.backside ? -localV : localV; - - spectral_type dummyior; - reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior, dummyior); - const vector3_type H = beckmann.__generate(upperHemisphereV, u.xy); - - return __generate_wo_clamps(localV, orientedEta.backside, H, interaction.getFromTangentSpace(), u, orientedEta.rcp, orientedEta.value*orientedEta.value, orientedEta.rcp*orientedEta.rcp, cache); - } - - sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector3_type) u) - { - anisocache_type dummycache; - return generate(interaction, u, dummycache); - } - - scalar_type pdf(NBL_CONST_REF_ARG(params_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) - { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.VdotH, eta); - const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; - - const scalar_type VdotHLdotH = params.VdotH * params.LdotH; - const bool transmitted = VdotHLdotH < 0.0; - - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.VdotH)); - - scalar_type ndf, lambda; - if (params.is_aniso) - { - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); - ndf::Beckmann beckmann_ndf; - ndf = beckmann_ndf(ndfparams); - - smith::Beckmann beckmann_smith; - scalar_type c2 = beckmann_smith.C2(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); - lambda = beckmann_smith.Lambda(c2); - } - else - { - const scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); - ndf::Beckmann beckmann_ndf; - ndf = beckmann_ndf(ndfparams); - - smith::Beckmann beckmann_smith; - lambda = beckmann_smith.Lambda(params.NdotV2, a2); - } - - return smith::VNDF_pdf_wo_clamps >(ndf,lambda,params.NdotV,transmitted,params.VdotH,params.LdotH,VdotHLdotH,orientedEta.value,reflectance,onePlusLambda_V); - } - - scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) - { - scalar_type dummy; - return pdf(params, dummy); - } - - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) - { - scalar_type onePlusLambda_V; - scalar_type _pdf = pdf(params, onePlusLambda_V); - - scalar_type quo; - if (params.is_aniso) - { - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(A.x*A.x, A.y*A.y, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, onePlusLambda_V); - smith::Beckmann beckmann_smith; - quo = beckmann_smith.G2_over_G1(smithparams); - } - else - { - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(A.x*A.x, params.NdotV2, params.NdotL2, onePlusLambda_V); - smith::Beckmann beckmann_smith; - quo = beckmann_smith.G2_over_G1(smithparams); - } - - return quotient_pdf_type::create((spectral_type)(quo), _pdf); - } - - vector2_type A; - scalar_type eta; -}; - -template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) -struct SGGXDielectricBxDF -{ - using this_t = SGGXDielectricBxDF; - using scalar_type = typename LightSample::scalar_type; - using ray_dir_info_type = typename LightSample::ray_dir_info_type; - using vector2_type = vector; - using vector3_type = vector; - using matrix3x3_type = matrix; - using params_t = SBxDFParams; - - using isotropic_type = typename IsoCache::isotropic_type; - using anisotropic_type = typename AnisoCache::anisotropic_type; - using sample_type = LightSample; - using spectral_type = Spectrum; - using quotient_pdf_type = quotient_and_pdf; - using isocache_type = IsoCache; - using anisocache_type = AnisoCache; - - static this_t create(scalar_type eta, scalar_type A) - { - this_t retval; - retval.eta = eta; - retval.A = vector2_type(A, A); - return retval; - } - - static this_t create(scalar_type eta, scalar_type ax, scalar_type ay) - { - this_t retval; - retval.eta = eta; - retval.A = vector2_type(ax, ay); - return retval; - } - - static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - if (params.is_aniso) - return create(params.eta, params.A.x, params.A.y); - else - return create(params.eta, params.A.x); - } - - void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - A = params.A; - eta = params.eta; - } - - spectral_type eval(NBL_CONST_REF_ARG(params_t) params) - { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.VdotH, eta); - const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; - - - const scalar_type VdotHLdotH = params.VdotH * params.LdotH; - const bool transmitted = VdotHLdotH < 0.0; - - scalar_type NG_already_in_reflective_dL_measure; - if (params.is_aniso) - { - spectral_type dummyior; - reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, A.y, dummyior, dummyior); - NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(params); - } - else - { - spectral_type dummyior; - reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, dummyior, dummyior); - NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(params); - } - - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,params.NdotL,transmitted,params.VdotH,params.LdotH,VdotHLdotH,orientedEta.value); - scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.VdotH)); - return hlsl::promote(f) * microfacet_transform(); - } - - sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) localV, bool backside, NBL_CONST_REF_ARG(vector3_type) H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) - { - const scalar_type localVdotH = nbl::hlsl::dot(localV,H); - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2,nbl::hlsl::abs(localVdotH)); - - scalar_type rcpChoiceProb; - bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); - - cache = anisocache_type::create(localV, H); - - const scalar_type VdotH = cache.iso_cache.getVdotH(); - cache.iso_cache.LdotH = transmitted ? Refract::computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; - ray_dir_info_type localL; - bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, localV, H, VdotH, cache.iso_cache.getLdotH(), rcpOrientedEta); - localL.direction = rr(); - - return sample_type::createFromTangentSpace(localV, localL, m); - } - - sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) - { - const vector3_type localV = interaction.getTangentSpaceV(); - - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), eta); - - const vector3_type upperHemisphereV = orientedEta.backside ? -localV : localV; - - spectral_type dummyior; - reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, A.y, dummyior, dummyior); - const vector3_type H = ggx.__generate(upperHemisphereV, u.xy); - - return __generate_wo_clamps(localV, orientedEta.backside, H, interaction.getFromTangentSpace(), u, orientedEta.rcp, orientedEta.value*orientedEta.value, orientedEta.rcp*orientedEta.rcp, cache); - } - - sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector3_type) u) - { - anisocache_type dummycache; - return generate(interaction, u, dummycache); - } - - scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) - { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.VdotH, eta); - const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; - - const scalar_type VdotHLdotH = params.VdotH * params.LdotH; - const bool transmitted = VdotHLdotH < 0.0; - - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.VdotH)); - - scalar_type ndf, devsh_v; - if (params.is_aniso) - { - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; - - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); - ndf::GGX ggx_ndf; - ndf = ggx_ndf(ndfparams); - - smith::GGX ggx_smith; - devsh_v = ggx_smith.devsh_part(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); - } - else - { - const scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); - ndf::GGX ggx_ndf; - ndf = ggx_ndf(ndfparams); - - smith::GGX ggx_smith; - devsh_v = ggx_smith.devsh_part(params.NdotV2, a2, 1.0-a2); - } - - smith::GGX ggx_smith; - const scalar_type lambda = ggx_smith.G1_wo_numerator(params.NdotV, devsh_v); - return smith::VNDF_pdf_wo_clamps(ndf, lambda, params.NdotV, transmitted, params.VdotH, params.LdotH, VdotHLdotH, orientedEta.value, reflectance); - } - - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) - { - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; - - scalar_type _pdf = pdf(params); - - smith::GGX ggx_smith; - scalar_type quo; - if (params.is_aniso) - { - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2); - quo = ggx_smith.G2_over_G1(smithparams); - } - else - { - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(ax2, params.NdotV, params.NdotV2, params.NdotL, params.NdotL2); - quo = ggx_smith.G2_over_G1(smithparams); - } - - return quotient_pdf_type::create((spectral_type)(quo), _pdf); - } - - vector2_type A; - scalar_type eta; -}; - -} -} // After Clang-HLSL introduces https://en.cppreference.com/w/cpp/language/namespace_alias // namespace bsdf = bxdf::transmission; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl new file mode 100644 index 0000000000..5a2ef6e475 --- /dev/null +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -0,0 +1,205 @@ +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_BUILTIN_HLSL_BXDF_TRANSMISSION_BECKMANN_INCLUDED_ +#define _NBL_BUILTIN_HLSL_BXDF_TRANSMISSION_BECKMANN_INCLUDED_ + +#include "nbl/builtin/hlsl/bxdf/common.hlsl" +#include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" +#include "nbl/builtin/hlsl/bxdf/reflection.hlsl" + +namespace nbl +{ +namespace hlsl +{ +namespace bxdf +{ +namespace transmission +{ + +template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) +struct SBeckmannDielectricBxDF +{ + using this_t = SBeckmannDielectricBxDF; + using scalar_type = typename LightSample::scalar_type; + using ray_dir_info_type = typename LightSample::ray_dir_info_type; + using vector2_type = vector; + using vector3_type = vector; + using matrix3x3_type = matrix; + using params_t = SBxDFParams; + + using isotropic_type = typename IsoCache::isotropic_type; + using anisotropic_type = typename AnisoCache::anisotropic_type; + using sample_type = LightSample; + using spectral_type = Spectrum; + using quotient_pdf_type = sampling::quotient_and_pdf; + using isocache_type = IsoCache; + using anisocache_type = AnisoCache; + + static this_t create(scalar_type eta, scalar_type A) + { + this_t retval; + retval.eta = eta; + retval.A = vector2_type(A, A); + return retval; + } + + static this_t create(scalar_type eta, scalar_type ax, scalar_type ay) + { + this_t retval; + retval.eta = eta; + retval.A = vector2_type(ax, ay); + return retval; + } + + static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) + { + if (params.is_aniso) + return create(params.eta, params.A.x, params.A.y); + else + return create(params.eta, params.A.x); + } + + void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) + { + A = params.A; + eta = params.eta; + } + + spectral_type eval(NBL_CONST_REF_ARG(params_t) params) + { + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.VdotH, eta); + const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; + + const scalar_type VdotHLdotH = params.VdotH * params.LdotH; + const bool transmitted = VdotHLdotH < 0.0; + + spectral_type dummyior; + reflection::SBeckmannBxDF beckmann; + if (params.is_aniso) + beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior, dummyior); + else + beckmann = reflection::SBeckmannBxDF::create(A.x, dummyior, dummyior); + const scalar_type scalar_part = beckmann.__eval_DG_wo_clamps(params); + + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,params.NdotV,transmitted,params.VdotH,params.LdotH,VdotHLdotH,orientedEta.value); + scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.VdotH)); + return hlsl::promote(f) * microfacet_transform(); + } + + sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) localV, bool backside, NBL_CONST_REF_ARG(vector3_type) H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) + { + const scalar_type localVdotH = nbl::hlsl::dot(localV,H); + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2,nbl::hlsl::abs(localVdotH)); + + scalar_type rcpChoiceProb; + bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); + + cache = anisocache_type::create(localV, H); + + const scalar_type VdotH = cache.iso_cache.getVdotH(); + cache.iso_cache.LdotH = transmitted ? Refract::computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; + ray_dir_info_type localL; + bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, localV, H, VdotH, cache.iso_cache.getLdotH(), rcpOrientedEta); + localL.direction = rr(); + + return sample_type::createFromTangentSpace(localV, localL, m); + } + + sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) + { + const vector3_type localV = interaction.getTangentSpaceV(); + + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), eta); + + const vector3_type upperHemisphereV = orientedEta.backside ? -localV : localV; + + spectral_type dummyior; + reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior, dummyior); + const vector3_type H = beckmann.__generate(upperHemisphereV, u.xy); + + return __generate_wo_clamps(localV, orientedEta.backside, H, interaction.getFromTangentSpace(), u, orientedEta.rcp, orientedEta.value*orientedEta.value, orientedEta.rcp*orientedEta.rcp, cache); + } + + sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector3_type) u) + { + anisocache_type dummycache; + return generate(interaction, u, dummycache); + } + + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) + { + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.VdotH, eta); + const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; + + const scalar_type VdotHLdotH = params.VdotH * params.LdotH; + const bool transmitted = VdotHLdotH < 0.0; + + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.VdotH)); + + scalar_type ndf, lambda; + if (params.is_aniso) + { + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + ndf::Beckmann beckmann_ndf; + ndf = beckmann_ndf(ndfparams); + + smith::Beckmann beckmann_smith; + scalar_type c2 = beckmann_smith.C2(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); + lambda = beckmann_smith.Lambda(c2); + } + else + { + const scalar_type a2 = A.x*A.x; + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); + ndf::Beckmann beckmann_ndf; + ndf = beckmann_ndf(ndfparams); + + smith::Beckmann beckmann_smith; + lambda = beckmann_smith.Lambda(params.NdotV2, a2); + } + + return smith::VNDF_pdf_wo_clamps >(ndf,lambda,params.NdotV,transmitted,params.VdotH,params.LdotH,VdotHLdotH,orientedEta.value,reflectance,onePlusLambda_V); + } + + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) + { + scalar_type dummy; + return pdf(params, dummy); + } + + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) + { + scalar_type onePlusLambda_V; + scalar_type _pdf = pdf(params, onePlusLambda_V); + + scalar_type quo; + if (params.is_aniso) + { + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(A.x*A.x, A.y*A.y, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, onePlusLambda_V); + smith::Beckmann beckmann_smith; + quo = beckmann_smith.G2_over_G1(smithparams); + } + else + { + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(A.x*A.x, params.NdotV2, params.NdotL2, onePlusLambda_V); + smith::Beckmann beckmann_smith; + quo = beckmann_smith.G2_over_G1(smithparams); + } + + return quotient_pdf_type::create((spectral_type)(quo), _pdf); + } + + vector2_type A; + scalar_type eta; +}; + +} +} +} +} + +#endif diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl new file mode 100644 index 0000000000..1fbe092bca --- /dev/null +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -0,0 +1,209 @@ +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_BUILTIN_HLSL_BXDF_TRANSMISSION_GGX_INCLUDED_ +#define _NBL_BUILTIN_HLSL_BXDF_TRANSMISSION_GGX_INCLUDED_ + +#include "nbl/builtin/hlsl/bxdf/common.hlsl" +#include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" +#include "nbl/builtin/hlsl/bxdf/reflection.hlsl" + +namespace nbl +{ +namespace hlsl +{ +namespace bxdf +{ +namespace transmission +{ + +template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) +struct SGGXDielectricBxDF +{ + using this_t = SGGXDielectricBxDF; + using scalar_type = typename LightSample::scalar_type; + using ray_dir_info_type = typename LightSample::ray_dir_info_type; + using vector2_type = vector; + using vector3_type = vector; + using matrix3x3_type = matrix; + using params_t = SBxDFParams; + + using isotropic_type = typename IsoCache::isotropic_type; + using anisotropic_type = typename AnisoCache::anisotropic_type; + using sample_type = LightSample; + using spectral_type = Spectrum; + using quotient_pdf_type = sampling::quotient_and_pdf; + using isocache_type = IsoCache; + using anisocache_type = AnisoCache; + + static this_t create(scalar_type eta, scalar_type A) + { + this_t retval; + retval.eta = eta; + retval.A = vector2_type(A, A); + return retval; + } + + static this_t create(scalar_type eta, scalar_type ax, scalar_type ay) + { + this_t retval; + retval.eta = eta; + retval.A = vector2_type(ax, ay); + return retval; + } + + static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) + { + if (params.is_aniso) + return create(params.eta, params.A.x, params.A.y); + else + return create(params.eta, params.A.x); + } + + void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) + { + A = params.A; + eta = params.eta; + } + + spectral_type eval(NBL_CONST_REF_ARG(params_t) params) + { + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.VdotH, eta); + const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; + + + const scalar_type VdotHLdotH = params.VdotH * params.LdotH; + const bool transmitted = VdotHLdotH < 0.0; + + scalar_type NG_already_in_reflective_dL_measure; + if (params.is_aniso) + { + spectral_type dummyior; + reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, A.y, dummyior, dummyior); + NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(params); + } + else + { + spectral_type dummyior; + reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, dummyior, dummyior); + NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(params); + } + + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,params.NdotL,transmitted,params.VdotH,params.LdotH,VdotHLdotH,orientedEta.value); + scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.VdotH)); + return hlsl::promote(f) * microfacet_transform(); + } + + sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) localV, bool backside, NBL_CONST_REF_ARG(vector3_type) H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) + { + const scalar_type localVdotH = nbl::hlsl::dot(localV,H); + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2,nbl::hlsl::abs(localVdotH)); + + scalar_type rcpChoiceProb; + bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); + + cache = anisocache_type::create(localV, H); + + const scalar_type VdotH = cache.iso_cache.getVdotH(); + cache.iso_cache.LdotH = transmitted ? Refract::computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; + ray_dir_info_type localL; + bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, localV, H, VdotH, cache.iso_cache.getLdotH(), rcpOrientedEta); + localL.direction = rr(); + + return sample_type::createFromTangentSpace(localV, localL, m); + } + + sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) + { + const vector3_type localV = interaction.getTangentSpaceV(); + + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), eta); + + const vector3_type upperHemisphereV = orientedEta.backside ? -localV : localV; + + spectral_type dummyior; + reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, A.y, dummyior, dummyior); + const vector3_type H = ggx.__generate(upperHemisphereV, u.xy); + + return __generate_wo_clamps(localV, orientedEta.backside, H, interaction.getFromTangentSpace(), u, orientedEta.rcp, orientedEta.value*orientedEta.value, orientedEta.rcp*orientedEta.rcp, cache); + } + + sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector3_type) u) + { + anisocache_type dummycache; + return generate(interaction, u, dummycache); + } + + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) + { + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.VdotH, eta); + const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; + + const scalar_type VdotHLdotH = params.VdotH * params.LdotH; + const bool transmitted = VdotHLdotH < 0.0; + + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.VdotH)); + + scalar_type ndf, devsh_v; + if (params.is_aniso) + { + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; + + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); + ndf::GGX ggx_ndf; + ndf = ggx_ndf(ndfparams); + + smith::GGX ggx_smith; + devsh_v = ggx_smith.devsh_part(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); + } + else + { + const scalar_type a2 = A.x*A.x; + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); + ndf::GGX ggx_ndf; + ndf = ggx_ndf(ndfparams); + + smith::GGX ggx_smith; + devsh_v = ggx_smith.devsh_part(params.NdotV2, a2, 1.0-a2); + } + + smith::GGX ggx_smith; + const scalar_type lambda = ggx_smith.G1_wo_numerator(params.NdotV, devsh_v); + return smith::VNDF_pdf_wo_clamps(ndf, lambda, params.NdotV, transmitted, params.VdotH, params.LdotH, VdotHLdotH, orientedEta.value, reflectance); + } + + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) + { + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; + + scalar_type _pdf = pdf(params); + + smith::GGX ggx_smith; + scalar_type quo; + if (params.is_aniso) + { + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2); + quo = ggx_smith.G2_over_G1(smithparams); + } + else + { + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(ax2, params.NdotV, params.NdotV2, params.NdotL, params.NdotL2); + quo = ggx_smith.G2_over_G1(smithparams); + } + + return quotient_pdf_type::create((spectral_type)(quo), _pdf); + } + + vector2_type A; + scalar_type eta; +}; + +} +} +} +} + +#endif diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl new file mode 100644 index 0000000000..b4258f22a3 --- /dev/null +++ b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl @@ -0,0 +1,88 @@ +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_BUILTIN_HLSL_BXDF_TRANSMISSION_LAMBERTIAN_INCLUDED_ +#define _NBL_BUILTIN_HLSL_BXDF_TRANSMISSION_LAMBERTIAN_INCLUDED_ + +#include "nbl/builtin/hlsl/bxdf/common.hlsl" +#include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" +#include "nbl/builtin/hlsl/bxdf/reflection.hlsl" + +namespace nbl +{ +namespace hlsl +{ +namespace bxdf +{ +namespace transmission +{ + +template && surface_interactions::Isotropic && surface_interactions::Anisotropic) +struct SLambertianBxDF +{ + using this_t = SLambertianBxDF; + using scalar_type = typename LightSample::scalar_type; + using ray_dir_info_type = typename LightSample::ray_dir_info_type; + using isotropic_type = Iso; + using anisotropic_type = Aniso; + using sample_type = LightSample; + using spectral_type = Spectrum; + using quotient_pdf_type = sampling::quotient_and_pdf; + using params_t = SBxDFParams; + + static this_t create() + { + this_t retval; + // nothing here, just keeping convention with others + return retval; + } + + static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) + { + return create(); + } + + void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) + { + // do nothing + } + + scalar_type __eval_pi_factored_out(scalar_type absNdotL) + { + return absNdotL; + } + + scalar_type eval(NBL_CONST_REF_ARG(params_t) params) + { + return __eval_pi_factored_out(params.NdotL) * numbers::inv_pi * 0.5; + } + + sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector) u) + { + ray_dir_info_type L; + L.direction = sampling::ProjectedSphere::generate(u); + return sample_type::createFromTangentSpace(interaction.getTangentSpaceV(), L, interaction.getFromTangentSpace()); + } + + sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector) u) + { + return generate_wo_clamps(interaction, u); + } + + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) + { + return sampling::ProjectedSphere::pdf(params.NdotL); + } + + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) + { + return sampling::ProjectedSphere::template quotient_and_pdf(params.NdotL); + } +}; + +} +} +} +} + +#endif diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl new file mode 100644 index 0000000000..604360545f --- /dev/null +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -0,0 +1,218 @@ +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_BUILTIN_HLSL_BXDF_TRANSMISSION_SMOOTH_DIELECTRIC_INCLUDED_ +#define _NBL_BUILTIN_HLSL_BXDF_TRANSMISSION_SMOOTH_DIELECTRIC_INCLUDED_ + +#include "nbl/builtin/hlsl/bxdf/common.hlsl" +#include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" +#include "nbl/builtin/hlsl/bxdf/reflection.hlsl" + +namespace nbl +{ +namespace hlsl +{ +namespace bxdf +{ +namespace transmission +{ + +template // NBL_FUNC_REQUIRES(Sample && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) // dxc won't let me put this in +struct SSmoothDielectricBxDF; + +template +struct SSmoothDielectricBxDF +{ + using this_t = SSmoothDielectricBxDF; + using scalar_type = typename LightSample::scalar_type; + using ray_dir_info_type = typename LightSample::ray_dir_info_type; + using vector3_type = vector; + using params_t = SBxDFParams; + + using isotropic_type = typename IsoCache::isotropic_type; + using anisotropic_type = typename AnisoCache::anisotropic_type; + using sample_type = LightSample; + using spectral_type = Spectrum; + using quotient_pdf_type = sampling::quotient_and_pdf; + using isocache_type = IsoCache; + using anisocache_type = AnisoCache; + + static this_t create(scalar_type eta) + { + this_t retval; + retval.eta = eta; + return retval; + } + + static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) + { + return create(params.eta); + } + + void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) + { + eta = params.eta; + } + + spectral_type eval(NBL_CONST_REF_ARG(params_t) params) + { + return (spectral_type)0; + } + + sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N, bool backside, scalar_type NdotV, scalar_type absNdotV, scalar_type NdotV2, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(bool) transmitted) + { + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, absNdotV); + + scalar_type rcpChoiceProb; + transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); + + ray_dir_info_type L; + Refract r = Refract::create(V, N, backside, NdotV, NdotV2, rcpOrientedEta, rcpOrientedEta2); + bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, r); + L.direction = rr(); + return sample_type::create(L, nbl::hlsl::dot(V, L.direction), T, B, N); + } + + sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector) u) + { + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), eta); + scalar_type NdotV = interaction.isotropic.getNdotV(); + bool dummy; + return __generate_wo_clamps(interaction.isotropic.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.isotropic.getN(), orientedEta.backside, NdotV, + NdotV, NdotV*NdotV, u, orientedEta.rcp, orientedEta.value*orientedEta.value, orientedEta.rcp*orientedEta.rcp, dummy); + } + + sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector) u) + { + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), eta); + scalar_type NdotV = interaction.isotropic.getNdotV(); + bool dummy; + return __generate_wo_clamps(interaction.isotropic.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.isotropic.getN(), orientedEta.backside, NdotV, + nbl::hlsl::abs(NdotV), NdotV*NdotV, u, orientedEta.rcp, orientedEta.value*orientedEta.value, orientedEta.rcp*orientedEta.rcp, dummy); + } + + // eval and pdf return 0 because smooth dielectric/conductor BxDFs are dirac delta distributions, model perfectly specular objects that scatter light to only one outgoing direction + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) + { + return 0; + } + + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) + { + const bool transmitted = isTransmissionPath(params.uNdotV, params.uNdotL); + + fresnel::OrientedEtaRcps rcpOrientedEtas = fresnel::OrientedEtaRcps::create(params.NdotV, eta); + + const scalar_type _pdf = bit_cast(numeric_limits::infinity); + scalar_type quo = transmitted ? rcpOrientedEtas.value : 1.0; + return quotient_pdf_type::create((spectral_type)(quo), _pdf); + } + + scalar_type eta; +}; + +template +struct SSmoothDielectricBxDF +{ + using this_t = SSmoothDielectricBxDF; + using scalar_type = typename LightSample::scalar_type; + using ray_dir_info_type = typename LightSample::ray_dir_info_type; + using vector3_type = vector; + using params_t = SBxDFParams; + + using isotropic_type = typename IsoCache::isotropic_type; + using anisotropic_type = typename AnisoCache::anisotropic_type; + using sample_type = LightSample; + using spectral_type = Spectrum; + using quotient_pdf_type = sampling::quotient_and_pdf; + using isocache_type = IsoCache; + using anisocache_type = AnisoCache; + + static this_t create(NBL_CONST_REF_ARG(spectral_type) eta2, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) + { + this_t retval; + retval.eta2 = eta2; + retval.luminosityContributionHint = luminosityContributionHint; + return retval; + } + + static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) + { + return create(params.eta2, params.luminosityContributionHint); + } + + void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) + { + eta2 = params.eta2; + luminosityContributionHint = params.luminosityContributionHint; + } + + spectral_type eval(NBL_CONST_REF_ARG(params_t) params) + { + return (spectral_type)0; + } + + // usually `luminosityContributionHint` would be the Rec.709 luma coefficients (the Y row of the RGB to CIE XYZ matrix) + // its basically a set of weights that determine + // assert(1.0==luminosityContributionHint.r+luminosityContributionHint.g+luminosityContributionHint.b); + // `remainderMetadata` is a variable which the generator function returns byproducts of sample generation that would otherwise have to be redundantly calculated `quotient_and_pdf` + sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N, scalar_type NdotV, scalar_type absNdotV, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(spectral_type) eta2, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint, NBL_REF_ARG(spectral_type) remainderMetadata) + { + // we will only ever intersect from the outside + fresnel::ThinDielectricInfiniteScatter scatter; + const spectral_type reflectance = scatter(fresnel::Dielectric::__call(eta2,absNdotV)); + + // we are only allowed one choice for the entire ray, so make the probability a weighted sum + const scalar_type reflectionProb = nbl::hlsl::dot(reflectance, luminosityContributionHint); + + scalar_type rcpChoiceProb; + const bool transmitted = math::partitionRandVariable(reflectionProb, u.z, rcpChoiceProb); + remainderMetadata = (transmitted ? ((spectral_type)(1.0) - reflectance) : reflectance) * rcpChoiceProb; + + ray_dir_info_type L; + L.direction = (transmitted ? (vector3_type)(0.0) : N * 2.0f * NdotV) - V; + return sample_type::create(L, nbl::hlsl::dot(V, L.direction), T, B, N); + } + + sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector) u) + { + scalar_type NdotV = interaction.isotropic.getNdotV(); + vector3_type dummy; + return __generate_wo_clamps(interaction.isotropic.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.isotropic.getN(), NdotV, NdotV, u, eta2, luminosityContributionHint, dummy); + } + + sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector) u) + { + scalar_type NdotV = interaction.isotropic.getNdotV(); + vector3_type dummy; + return __generate_wo_clamps(interaction.isotropic.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.isotropic.getN(), NdotV, nbl::hlsl::abs(NdotV), u, eta2, luminosityContributionHint, dummy); + } + + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) + { + return 0; + } + + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) // isotropic + { + const bool transmitted = isTransmissionPath(params.uNdotV, params.uNdotL); + fresnel::ThinDielectricInfiniteScatter scatter; + const spectral_type reflectance = scatter(fresnel::Dielectric::__call(eta2, params.NdotV)); + const spectral_type sampleValue = transmitted ? ((spectral_type)(1.0) - reflectance) : reflectance; + + const scalar_type sampleProb = nbl::hlsl::dot(sampleValue,luminosityContributionHint); + + const scalar_type _pdf = bit_cast(numeric_limits::infinity); + return quotient_pdf_type::create((spectral_type)(sampleValue / sampleProb), _pdf); + } + + spectral_type eta2; + spectral_type luminosityContributionHint; +}; + +} +} +} +} + +#endif diff --git a/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl b/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl index 78b30cbc62..5604e397b4 100644 --- a/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl +++ b/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl @@ -1,4 +1,4 @@ -// Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O. +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h @@ -7,7 +7,7 @@ #include "nbl/builtin/hlsl/concepts.hlsl" #include "nbl/builtin/hlsl/sampling/concentric_mapping.hlsl" -#include "nbl/builtin/hlsl/bxdf/common.hlsl" +#include "nbl/builtin/hlsl/sampling/quotient_and_pdf.hlsl" namespace nbl { @@ -34,16 +34,16 @@ struct ProjectedHemisphere return L_z * numbers::inv_pi; } - template - static bxdf::quotient_and_pdf quotient_and_pdf(T L) + template + static sampling::quotient_and_pdf quotient_and_pdf(T L) { - return bxdf::quotient_and_pdf::create(hlsl::promote(1.0), pdf(L)); + return sampling::quotient_and_pdf::create(hlsl::promote(1.0), pdf(L)); } - template - static bxdf::quotient_and_pdf quotient_and_pdf(vector_t3 L) + template + static sampling::quotient_and_pdf quotient_and_pdf(vector_t3 L) { - return quotient_and_pdf(L.z); + return sampling::quotient_and_pdf::create(hlsl::promote(1.0), pdf(L.z)); } }; @@ -70,16 +70,16 @@ struct ProjectedSphere return T(0.5) * hemisphere_t::pdf(L_z); } - template - static bxdf::quotient_and_pdf quotient_and_pdf(T L) + template + static sampling::quotient_and_pdf quotient_and_pdf(T L) { - return bxdf::quotient_and_pdf::create(hlsl::promote(1.0), pdf(L)); + return sampling::quotient_and_pdf::create(hlsl::promote(1.0), pdf(L)); } - template - static bxdf::quotient_and_pdf quotient_and_pdf(vector_t3 L) + template + static sampling::quotient_and_pdf quotient_and_pdf(vector_t3 L) { - return quotient_and_pdf(L.z); + return sampling::quotient_and_pdf::create(hlsl::promote(1.0), pdf(L.z)); } }; diff --git a/include/nbl/builtin/hlsl/sampling/quotient_and_pdf.hlsl b/include/nbl/builtin/hlsl/sampling/quotient_and_pdf.hlsl new file mode 100644 index 0000000000..e48983c047 --- /dev/null +++ b/include/nbl/builtin/hlsl/sampling/quotient_and_pdf.hlsl @@ -0,0 +1,49 @@ +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h + +#ifndef _NBL_BUILTIN_HLSL_SAMPLING_QUOTIENT_AND_PDF_INCLUDED_ +#define _NBL_BUILTIN_HLSL_SAMPLING_QUOTIENT_AND_PDF_INCLUDED_ + +#include "nbl/builtin/hlsl/concepts/vector.hlsl" + +namespace nbl +{ +namespace hlsl +{ +namespace sampling +{ + +template +NBL_BOOL_CONCEPT spectral_of = concepts::Vectorial || concepts::Scalar || concepts::Scalar; + +// finally fixed the semantic F-up, value/pdf = quotient not remainder +template && is_floating_point_v

) +struct quotient_and_pdf +{ + using this_t = quotient_and_pdf; + static this_t create(NBL_CONST_REF_ARG(Q) _quotient, NBL_CONST_REF_ARG(P) _pdf) + { + this_t retval; + retval.quotient = _quotient; + retval.pdf = _pdf; + return retval; + } + + Q value() + { + return quotient*pdf; + } + + Q quotient; + P pdf; +}; + +typedef quotient_and_pdf quotient_and_pdf_scalar; +typedef quotient_and_pdf, float32_t> quotient_and_pdf_rgb; + +} +} +} + +#endif diff --git a/include/nbl/builtin/hlsl/sampling/uniform.hlsl b/include/nbl/builtin/hlsl/sampling/uniform.hlsl index 2c6f6c233f..48284a1c31 100644 --- a/include/nbl/builtin/hlsl/sampling/uniform.hlsl +++ b/include/nbl/builtin/hlsl/sampling/uniform.hlsl @@ -8,6 +8,7 @@ #include "nbl/builtin/hlsl/concepts.hlsl" #include "nbl/builtin/hlsl/numbers.hlsl" #include "nbl/builtin/hlsl/tgmath.hlsl" +#include "nbl/builtin/hlsl/sampling/quotient_and_pdf.hlsl" namespace nbl { @@ -34,6 +35,12 @@ struct UniformHemisphere { return T(1.0) / (T(2.0) * numbers::pi); } + + template + static sampling::quotient_and_pdf quotient_and_pdf() + { + return sampling::quotient_and_pdf::create(hlsl::promote(1.0), pdf()); + } }; template @@ -54,6 +61,12 @@ struct UniformSphere { return T(1.0) / (T(4.0) * numbers::pi); } + + template + static sampling::quotient_and_pdf quotient_and_pdf() + { + return sampling::quotient_and_pdf::create(hlsl::promote(1.0), pdf()); + } }; } From 7162a29002b4fd9b4654ee857b4eceb5fa7f8860 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 14 Apr 2025 16:29:20 +0700 Subject: [PATCH 092/188] fixes to mix, flipSign constraints --- .../hlsl/cpp_compat/impl/intrinsics_impl.hlsl | 4 +- include/nbl/builtin/hlsl/ieee754.hlsl | 46 +++++++++++++------ .../builtin/hlsl/spirv_intrinsics/core.hlsl | 2 +- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl b/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl index 8b2e3aa3b0..0908ce457b 100644 --- a/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl +++ b/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl @@ -241,8 +241,8 @@ struct mix_helper(e }; template -NBL_PARTIAL_REQ_TOP((concepts::Scalar || concepts::Vectorial) && !concepts::Boolean && concepts::Boolean) -struct mix_helper || concepts::Vectorial) && !concepts::Boolean && concepts::Boolean) > +NBL_PARTIAL_REQ_TOP(concepts::Boolean && ((concepts::Vector && concepts::Vector && vector_traits::Dimension==vector_traits::Dimension) || concepts::Scalar)) +struct mix_helper && ((concepts::Vector && concepts::Vector && vector_traits::Dimension==vector_traits::Dimension) || concepts::Scalar)) > { using return_t = conditional_t, vector::scalar_type, vector_traits::Dimension>, T>; // for a component of a that is false, the corresponding component of x is returned diff --git a/include/nbl/builtin/hlsl/ieee754.hlsl b/include/nbl/builtin/hlsl/ieee754.hlsl index 50cc2de98c..3616b8ba3a 100644 --- a/include/nbl/builtin/hlsl/ieee754.hlsl +++ b/include/nbl/builtin/hlsl/ieee754.hlsl @@ -144,14 +144,14 @@ NBL_CONSTEXPR_INLINE_FUNC FloatingPoint copySign(FloatingPoint to, FloatingPoint namespace impl { -template +template struct flipSign_helper; -template -NBL_PARTIAL_REQ_TOP(concepts::FloatingPointLikeScalar) -struct flipSign_helper) > +template +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointLikeScalar && concepts::BooleanScalar) +struct flipSign_helper && concepts::BooleanScalar) > { - static FloatingPoint __call(FloatingPoint val, bool flip = true) + static FloatingPoint __call(FloatingPoint val, Bool flip) { using AsFloat = typename float_of_size::type; using AsUint = typename unsigned_integer_of_size::type; @@ -160,11 +160,11 @@ struct flipSign_helper -NBL_PARTIAL_REQ_TOP(concepts::FloatingPointLikeVectorial) -struct flipSign_helper) > +template +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointLikeVectorial && concepts::BooleanScalar) +struct flipSign_helper && concepts::BooleanScalar) > { - static Vectorial __call(Vectorial val, bool flip = true) + static Vectorial __call(Vectorial val, Bool flip) { using traits = hlsl::vector_traits; array_get getter; @@ -172,17 +172,37 @@ struct flipSign_helper::__call(getter(val, i), flip)); + setter(output, i, flipSign_helper::__call(getter(val, i), flip)); + + return output; + } +}; + +template +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointLikeVectorial && concepts::Boolean && !concepts::Scalar && vector_traits::Dimension==vector_traits::Dimension) +struct flipSign_helper && concepts::Boolean && !concepts::Scalar && vector_traits::Dimension==vector_traits::Dimension) > +{ + static Vectorial __call(Vectorial val, BoolVector flip) + { + using traits_v = hlsl::vector_traits; + using traits_f = hlsl::vector_traits; + array_get getter_v; + array_get getter_f; + array_get setter; + + Vectorial output; + for (uint32_t i = 0; i < traits_v::Dimension; ++i) + setter(output, i, flipSign_helper::__call(getter_v(val, i), getter_f(flip, i))); return output; } }; } -template -NBL_CONSTEXPR_INLINE_FUNC T flipSign(T val, bool flip = true) +template +NBL_CONSTEXPR_INLINE_FUNC T flipSign(T val, U flip) { - return impl::flipSign_helper::__call(val, flip); + return impl::flipSign_helper::__call(val, flip); } } diff --git a/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl b/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl index 635346a47a..88941b8d6d 100644 --- a/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl +++ b/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl @@ -356,7 +356,7 @@ template && !is_matrix_v) conditional_t, vector::Dimension>, bool> FOrdEqual(T lhs, T rhs); -template && !is_matrix_v && is_same_v::scalar_type, bool>) +template && (is_scalar_v || (is_vector_v && is_vector_v && vector_traits::Dimension==vector_traits::Dimension)) && is_same_v::scalar_type, bool>) [[vk::ext_instruction(spv::OpSelect)]] T select(U a, T x, T y); From 540919b457e98cdebe86aa466e626eb44bbaa983 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 15 Apr 2025 11:12:08 +0700 Subject: [PATCH 093/188] changes to oriented eta, reflect, refract --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 8 +- include/nbl/builtin/hlsl/bxdf/fresnel.hlsl | 119 ++++++++---------- .../hlsl/bxdf/reflection/beckmann.hlsl | 2 +- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 2 +- .../hlsl/bxdf/transmission/beckmann.hlsl | 13 +- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 13 +- .../bxdf/transmission/smooth_dielectric.hlsl | 18 +-- 7 files changed, 86 insertions(+), 89 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index f7dc49b3f5..8e94550ec5 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -58,8 +58,8 @@ namespace ray_dir_info #define NBL_CONCEPT_PARAM_1 (N, typename T::vector3_type) #define NBL_CONCEPT_PARAM_2 (dirDotN, typename T::scalar_type) #define NBL_CONCEPT_PARAM_3 (m, typename T::matrix3x3_type) -#define NBL_CONCEPT_PARAM_4 (rfl, Reflect) -#define NBL_CONCEPT_PARAM_5 (rfr, Refract) +#define NBL_CONCEPT_PARAM_4 (rfl, Reflect) +#define NBL_CONCEPT_PARAM_5 (rfr, Refract) NBL_CONCEPT_BEGIN(6) #define rdirinfo NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define N NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 @@ -103,14 +103,14 @@ struct SBasic return retval; } - SBasic reflect(NBL_CONST_REF_ARG(Reflect) r) + SBasic reflect(NBL_CONST_REF_ARG(Reflect) r) { SBasic retval; retval.direction = r(); return retval; } - SBasic refract(NBL_CONST_REF_ARG(Refract) r) + SBasic refract(NBL_CONST_REF_ARG(Refract) r) { SBasic retval; retval.direction = r(); diff --git a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl index 70bdfefe94..e7dbb0d6e5 100644 --- a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl @@ -4,6 +4,7 @@ #ifndef _NBL_BUILTIN_HLSL_BXDF_FRESNEL_INCLUDED_ #define _NBL_BUILTIN_HLSL_BXDF_FRESNEL_INCLUDED_ +#include "nbl/builtin/hlsl/ieee754.hlsl" #include "nbl/builtin/hlsl/cpp_compat.hlsl" #include "nbl/builtin/hlsl/concepts.hlsl" #include "nbl/builtin/hlsl/numbers.hlsl" @@ -28,23 +29,13 @@ struct OrientedEtas static OrientedEtas create(scalar_type NdotI, T eta) { OrientedEtas retval; - retval.backside = NdotI < hlsl::promote(0.0); + retval.backside = NdotI < scalar_type(0.0); const T rcpEta = hlsl::promote(1.0) / eta; retval.value = retval.backside ? rcpEta : eta; retval.rcp = retval.backside ? eta : rcpEta; return retval; } - static T diffuseFresnelCorrectionFactor(T n, T n2) - { - // assert(n*n==n2); - vector::Dimension> TIR = n < (T)1.0; - T invdenum = nbl::hlsl::mix(hlsl::promote(1.0), hlsl::promote(1.0) / (n2 * n2 * (hlsl::promote(554.33) - 380.7 * n)), TIR); - T num = n * nbl::hlsl::mix(hlsl::promote(0.1921156102251088), n * 298.25 - 261.38 * n2 + 138.43, TIR); - num += nbl::hlsl::mix(hlsl::promote(0.8078843897748912), hlsl::promote(-1.67), TIR); - return num * invdenum; - } - T value; T rcp; bool backside; @@ -58,16 +49,24 @@ struct OrientedEtaRcps static OrientedEtaRcps create(scalar_type NdotI, T eta) { OrientedEtaRcps retval; - retval.backside = NdotI < hlsl::promote(0.0); + retval.backside = NdotI < scalar_type(0.0); const T rcpEta = hlsl::promote(1.0) / eta; retval.value = retval.backside ? eta : rcpEta; retval.value2 = retval.value * retval.value; return retval; } - static T diffuseFresnelCorrectionFactor(T n, T n2) + T diffuseFresnelCorrectionFactor() { - return OrientedEtas::diffuseFresnelCorrectionFactor(n, n2); + // assert(n*n==n2); + const T n = hlsl::promote(1.0) / value; + const T n2 = hlsl::promote(1.0) / value2; + + vector::Dimension> TIR = n < hlsl::promote(1.0); + T invdenum = nbl::hlsl::mix(hlsl::promote(1.0), hlsl::promote(1.0) / (n2 * n2 * (hlsl::promote(554.33) - hlsl::promote(380.7) * n)), TIR); + T num = n * nbl::hlsl::mix(hlsl::promote(0.1921156102251088), n * hlsl::promote(298.25) - hlsl::promote(261.38) * n2 + hlsl::promote(138.43), TIR); + num += nbl::hlsl::mix(hlsl::promote(0.8078843897748912), hlsl::promote(-1.67), TIR); + return num * invdenum; } T value; @@ -77,17 +76,12 @@ struct OrientedEtaRcps } -template && vector_traits::Dimension == 3) +template) struct Reflect { using this_t = Reflect; - using vector_type = T; - using scalar_type = typename vector_traits::scalar_type; - - static this_t computeNdotI(NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N) - { - return hlsl::dot(N, I); - } + using vector_type = vector; + using scalar_type = T; static this_t create(NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N, scalar_type NdotI) { @@ -107,6 +101,11 @@ struct Reflect return retval; } + void recomputeNdotI() + { + NdotI = hlsl::dot(N, I); + } + vector_type operator()() { return N * 2.0f * NdotI - I; @@ -117,86 +116,75 @@ struct Reflect scalar_type NdotI; }; -template && vector_traits::Dimension == 3) +template) struct Refract { using this_t = Refract; - using vector_type = T; - using scalar_type = typename vector_traits::scalar_type; + using vector_type = vector; + using scalar_type = T; - static this_t create(NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N, bool backside, scalar_type NdotI, scalar_type NdotI2, scalar_type rcpOrientedEta, scalar_type rcpOrientedEta2) + static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEtas, NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N) { this_t retval; retval.I = I; retval.N = N; - retval.backside = backside; - retval.NdotI = NdotI; - retval.NdotI2 = NdotI2; - retval.rcpOrientedEta = rcpOrientedEta; - retval.rcpOrientedEta2 = rcpOrientedEta2; + retval.NdotI = hlsl::dot(N, I); + retval.NdotI2 = retval.NdotI * retval.NdotI; + retval.rcpOrientedEta = rcpEtas; + retval.recomputeNdotT(rcpEtas.backside, retval.NdotI2, rcpEtas.value2); return retval; } - static this_t create(NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N, scalar_type NdotI, scalar_type eta) + static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEtas, NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N, const scalar_type NdotI) { this_t retval; retval.I = I; retval.N = N; - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(NdotI, eta); - retval.backside = orientedEta.backside; retval.NdotI = NdotI; - retval.NdotI2 = NdotI * NdotI; - retval.rcpOrientedEta = orientedEta.rcp; - retval.rcpOrientedEta2 = retval.rcpOrientedEta * retval.rcpOrientedEta; + retval.NdotI2 = retval.NdotI * retval.NdotI; + retval.rcpOrientedEta = rcpEtas; + retval.recomputeNdotT(rcpEtas.backside, retval.NdotI2, rcpEtas.value2); return retval; } - static this_t create(NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N, scalar_type eta) + void recomputeNdotI() { - this_t retval; - retval.I = I; - retval.N = N; - retval.NdotI = dot(N, I); - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(retval.NdotI, eta); - retval.backside = orientedEta.backside; - retval.NdotI2 = retval.NdotI * retval.NdotI; - retval.rcpOrientedEta = orientedEta.rcp; - retval.rcpOrientedEta2 = retval.rcpOrientedEta * retval.rcpOrientedEta; - return retval; + NdotI = hlsl::dot(N, I); + NdotI2 = NdotI * NdotI; } - static scalar_type computeNdotT(bool backside, scalar_type NdotI2, scalar_type rcpOrientedEta2) + void recomputeNdotT(bool backside, scalar_type _NdotI2, scalar_type rcpOrientedEta2) { - scalar_type NdotT2 = rcpOrientedEta2 * NdotI2 + 1.0 - rcpOrientedEta2; + scalar_type NdotT2 = rcpOrientedEta2 * _NdotI2 + 1.0 - rcpOrientedEta2; scalar_type absNdotT = sqrt(NdotT2); - return backside ? absNdotT : -(absNdotT); + NdotT = ieee754::flipSign(absNdotT, backside); } vector_type operator()() { - return N * (NdotI * rcpOrientedEta + computeNdotT(backside, NdotI2, rcpOrientedEta2)) - rcpOrientedEta * I; + recomputeNdotT(rcpOrientedEta.backside, NdotI2, rcpOrientedEta.value2); + return N * (NdotI * rcpOrientedEta.value + NdotT) - rcpOrientedEta.value * I; } vector_type I; vector_type N; - bool backside; + scalar_type NdotT; scalar_type NdotI; scalar_type NdotI2; - scalar_type rcpOrientedEta; - scalar_type rcpOrientedEta2; + fresnel::OrientedEtaRcps rcpOrientedEta; }; -template && vector_traits::Dimension == 3) +template) struct ReflectRefract { using this_t = ReflectRefract; - using vector_type = T; - using scalar_type = typename vector_traits::scalar_type; + using vector_type = vector; + using scalar_type = T; static this_t create(bool refract, NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N, scalar_type NdotI, scalar_type NdotTorR, scalar_type rcpOrientedEta) { this_t retval; - retval.refract = refract; + retval.is_refract = refract; retval.I = I; retval.N = N; retval.NdotI = NdotI; @@ -205,24 +193,25 @@ struct ReflectRefract return retval; } - static this_t create(bool r, NBL_CONST_REF_ARG(Refract) refract) + static this_t create(bool r, NBL_CONST_REF_ARG(Refract) refract) { this_t retval; - retval.refract = r; + retval.is_refract = r; retval.I = refract.I; retval.N = refract.N; retval.NdotI = refract.NdotI; - retval.NdotTorR = r ? Refract::computeNdotT(refract.backside, refract.NdotI2, refract.rcpOrientedEta2) : refract.NdotI; - retval.rcpOrientedEta = refract.rcpOrientedEta; + retval.NdotTorR = hlsl::mix(refract.NdotI, refract.NdotT, r); + retval.rcpOrientedEta = refract.rcpOrientedEta.value; return retval; } vector_type operator()() { - return N * (NdotI * (hlsl::mix(1.0f, rcpOrientedEta, refract)) + NdotTorR) - I * (hlsl::mix(1.0f, rcpOrientedEta, refract)); + return N * (NdotI * (hlsl::mix(1.0f, rcpOrientedEta, is_refract)) + NdotTorR) - I * (hlsl::mix(1.0f, rcpOrientedEta, is_refract)); } - bool refract; + bool is_refract; + Refract refract; vector_type I; vector_type N; scalar_type NdotI; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index a7cf63ec38..ec3cd8d624 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -192,7 +192,7 @@ struct SBeckmannBxDF cache = anisocache_type::create(localV, H); ray_dir_info_type localL; - bxdf::Reflect r = bxdf::Reflect::create(localV, H, cache.iso_cache.getVdotH()); + bxdf::Reflect r = bxdf::Reflect::create(localV, H, cache.iso_cache.getVdotH()); localL.direction = r(); return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 0621ce6f63..e30af54a17 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -146,7 +146,7 @@ struct SGGXBxDF cache = anisocache_type::create(localV, H); ray_dir_info_type localL; - bxdf::Reflect r = bxdf::Reflect::create(localV, H, cache.iso_cache.getVdotH()); + bxdf::Reflect r = bxdf::Reflect::create(localV, H, cache.iso_cache.getVdotH()); localL.direction = r(); return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 5a2ef6e475..49731fd0f3 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -88,10 +88,10 @@ struct SBeckmannDielectricBxDF return hlsl::promote(f) * microfacet_transform(); } - sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) localV, bool backside, NBL_CONST_REF_ARG(vector3_type) H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) + sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) localV, NBL_CONST_REF_ARG(vector3_type) H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(anisocache_type) cache) { const scalar_type localVdotH = nbl::hlsl::dot(localV,H); - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2,nbl::hlsl::abs(localVdotH)); + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta.value * orientedEta.value,nbl::hlsl::abs(localVdotH)); scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); @@ -99,9 +99,11 @@ struct SBeckmannDielectricBxDF cache = anisocache_type::create(localV, H); const scalar_type VdotH = cache.iso_cache.getVdotH(); - cache.iso_cache.LdotH = transmitted ? Refract::computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; + Refract r; + r.recomputeNdotT(VdotH < 0.0, VdotH * VdotH, rcpEta.value2); + cache.iso_cache.LdotH = hlsl::mix(VdotH, r.NdotT, transmitted); ray_dir_info_type localL; - bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, localV, H, VdotH, cache.iso_cache.getLdotH(), rcpOrientedEta); + bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, localV, H, VdotH, cache.iso_cache.getLdotH(), rcpEta.value); localL.direction = rr(); return sample_type::createFromTangentSpace(localV, localL, m); @@ -112,6 +114,7 @@ struct SBeckmannDielectricBxDF const vector3_type localV = interaction.getTangentSpaceV(); fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), eta); + fresnel::OrientedEtaRcps rcpEta = fresnel::OrientedEtaRcps::create(interaction.isotropic.getNdotV(), eta); const vector3_type upperHemisphereV = orientedEta.backside ? -localV : localV; @@ -119,7 +122,7 @@ struct SBeckmannDielectricBxDF reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior, dummyior); const vector3_type H = beckmann.__generate(upperHemisphereV, u.xy); - return __generate_wo_clamps(localV, orientedEta.backside, H, interaction.getFromTangentSpace(), u, orientedEta.rcp, orientedEta.value*orientedEta.value, orientedEta.rcp*orientedEta.rcp, cache); + return __generate_wo_clamps(localV, H, interaction.getFromTangentSpace(), u, orientedEta, rcpEta, cache); } sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector3_type) u) diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 1fbe092bca..1b0aa8a4c0 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -95,10 +95,10 @@ struct SGGXDielectricBxDF return hlsl::promote(f) * microfacet_transform(); } - sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) localV, bool backside, NBL_CONST_REF_ARG(vector3_type) H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(anisocache_type) cache) + sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) localV, NBL_CONST_REF_ARG(vector3_type) H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(anisocache_type) cache) { const scalar_type localVdotH = nbl::hlsl::dot(localV,H); - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2,nbl::hlsl::abs(localVdotH)); + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta.value * orientedEta.value,nbl::hlsl::abs(localVdotH)); scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); @@ -106,9 +106,11 @@ struct SGGXDielectricBxDF cache = anisocache_type::create(localV, H); const scalar_type VdotH = cache.iso_cache.getVdotH(); - cache.iso_cache.LdotH = transmitted ? Refract::computeNdotT(VdotH < 0.0, VdotH * VdotH, rcpOrientedEta2) : VdotH; + Refract r; + r.recomputeNdotT(VdotH < 0.0, VdotH * VdotH, rcpEta.value2); + cache.iso_cache.LdotH = hlsl::mix(VdotH, r.NdotT, transmitted); ray_dir_info_type localL; - bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, localV, H, VdotH, cache.iso_cache.getLdotH(), rcpOrientedEta); + bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, localV, H, VdotH, cache.iso_cache.getLdotH(), rcpEta.value); localL.direction = rr(); return sample_type::createFromTangentSpace(localV, localL, m); @@ -119,6 +121,7 @@ struct SGGXDielectricBxDF const vector3_type localV = interaction.getTangentSpaceV(); fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), eta); + fresnel::OrientedEtaRcps rcpEta = fresnel::OrientedEtaRcps::create(interaction.isotropic.getNdotV(), eta); const vector3_type upperHemisphereV = orientedEta.backside ? -localV : localV; @@ -126,7 +129,7 @@ struct SGGXDielectricBxDF reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, A.y, dummyior, dummyior); const vector3_type H = ggx.__generate(upperHemisphereV, u.xy); - return __generate_wo_clamps(localV, orientedEta.backside, H, interaction.getFromTangentSpace(), u, orientedEta.rcp, orientedEta.value*orientedEta.value, orientedEta.rcp*orientedEta.rcp, cache); + return __generate_wo_clamps(localV, H, interaction.getFromTangentSpace(), u, orientedEta, rcpEta, cache); } sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector3_type) u) diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index 604360545f..d65508a03d 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -59,16 +59,16 @@ struct SSmoothDielectricBxDF return (spectral_type)0; } - sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N, bool backside, scalar_type NdotV, scalar_type absNdotV, scalar_type NdotV2, NBL_REF_ARG(vector3_type) u, scalar_type rcpOrientedEta, scalar_type orientedEta2, scalar_type rcpOrientedEta2, NBL_REF_ARG(bool) transmitted) + sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N, scalar_type NdotV, scalar_type absNdotV, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(bool) transmitted) { - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, absNdotV); + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta.value*orientedEta.value, absNdotV); scalar_type rcpChoiceProb; transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); ray_dir_info_type L; - Refract r = Refract::create(V, N, backside, NdotV, NdotV2, rcpOrientedEta, rcpOrientedEta2); - bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, r); + Refract r = Refract::create(rcpEta, V, N, NdotV); + bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, r); L.direction = rr(); return sample_type::create(L, nbl::hlsl::dot(V, L.direction), T, B, N); } @@ -76,19 +76,21 @@ struct SSmoothDielectricBxDF sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector) u) { fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), eta); + fresnel::OrientedEtaRcps rcpEta = fresnel::OrientedEtaRcps::create(interaction.isotropic.getNdotV(), eta); scalar_type NdotV = interaction.isotropic.getNdotV(); bool dummy; - return __generate_wo_clamps(interaction.isotropic.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.isotropic.getN(), orientedEta.backside, NdotV, - NdotV, NdotV*NdotV, u, orientedEta.rcp, orientedEta.value*orientedEta.value, orientedEta.rcp*orientedEta.rcp, dummy); + return __generate_wo_clamps(interaction.isotropic.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.isotropic.getN(), NdotV, + NdotV, u, orientedEta, rcpEta, dummy); } sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector) u) { fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), eta); + fresnel::OrientedEtaRcps rcpEta = fresnel::OrientedEtaRcps::create(interaction.isotropic.getNdotV(), eta); scalar_type NdotV = interaction.isotropic.getNdotV(); bool dummy; - return __generate_wo_clamps(interaction.isotropic.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.isotropic.getN(), orientedEta.backside, NdotV, - nbl::hlsl::abs(NdotV), NdotV*NdotV, u, orientedEta.rcp, orientedEta.value*orientedEta.value, orientedEta.rcp*orientedEta.rcp, dummy); + return __generate_wo_clamps(interaction.isotropic.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.isotropic.getN(), NdotV, + nbl::hlsl::abs(NdotV), u, orientedEta, rcpEta, dummy); } // eval and pdf return 0 because smooth dielectric/conductor BxDFs are dirac delta distributions, model perfectly specular objects that scatter light to only one outgoing direction From ac70036b2bc1512c63885caf04248851857812e9 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 15 Apr 2025 13:52:44 +0700 Subject: [PATCH 094/188] changes to reflectrefract, fresnel funcs --- include/nbl/builtin/hlsl/bxdf/fresnel.hlsl | 74 +++++++++++-------- .../hlsl/bxdf/transmission/beckmann.hlsl | 2 +- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 2 +- .../bxdf/transmission/smooth_dielectric.hlsl | 8 +- 4 files changed, 47 insertions(+), 39 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl index e7dbb0d6e5..3008f38531 100644 --- a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl @@ -181,10 +181,9 @@ struct ReflectRefract using vector_type = vector; using scalar_type = T; - static this_t create(bool refract, NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N, scalar_type NdotI, scalar_type NdotTorR, scalar_type rcpOrientedEta) + static this_t create(bool r, NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N, scalar_type NdotI, scalar_type NdotTorR, scalar_type rcpOrientedEta) { this_t retval; - retval.is_refract = refract; retval.I = I; retval.N = N; retval.NdotI = NdotI; @@ -196,7 +195,6 @@ struct ReflectRefract static this_t create(bool r, NBL_CONST_REF_ARG(Refract) refract) { this_t retval; - retval.is_refract = r; retval.I = refract.I; retval.N = refract.N; retval.NdotI = refract.NdotI; @@ -205,12 +203,23 @@ struct ReflectRefract return retval; } - vector_type operator()() + // when you know you'll reflect + void recomputeNdotR() + { + refract.recomputeNdotI(); + } + + // when you know you'll refract + void recomputeNdotT(bool backside, scalar_type _NdotI2, scalar_type rcpOrientedEta2) + { + refract.recomputeNdotT(backside, _NdotI2, rcpOrientedEta2); + } + + vector_type operator()(const bool doRefract) { - return N * (NdotI * (hlsl::mix(1.0f, rcpOrientedEta, is_refract)) + NdotTorR) - I * (hlsl::mix(1.0f, rcpOrientedEta, is_refract)); + return N * (NdotI * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)) + NdotTorR) - I * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)); } - bool is_refract; Refract refract; vector_type I; vector_type N; @@ -228,22 +237,24 @@ struct Schlick { using scalar_type = typename vector_traits::scalar_type; - static Schlick create(NBL_CONST_REF_ARG(T) F0, scalar_type VdotH) + static Schlick create(NBL_CONST_REF_ARG(T) F0, scalar_type clampedCosTheta) { Schlick retval; retval.F0 = F0; - retval.VdotH = VdotH; + retval.clampedCosTheta = clampedCosTheta; return retval; } T operator()() { - T x = 1.0 - VdotH; + assert(clampedCosTheta > scalar_type(0.0)); + assert(hlsl::promote(0.02) < F0 && F0 <= hlsl::promote(1.0)); + T x = 1.0 - clampedCosTheta; return F0 + (1.0 - F0) * x*x*x*x*x; } T F0; - scalar_type VdotH; + scalar_type clampedCosTheta; }; template || is_vector_v) @@ -251,22 +262,23 @@ struct Conductor { using scalar_type = typename vector_traits::scalar_type; - static Conductor create(NBL_CONST_REF_ARG(T) eta, NBL_CONST_REF_ARG(T) etak, scalar_type cosTheta) + static Conductor create(NBL_CONST_REF_ARG(T) eta, NBL_CONST_REF_ARG(T) etak, scalar_type clampedCosTheta) { Conductor retval; retval.eta = eta; - retval.etak = etak; - retval.cosTheta = cosTheta; + retval.etak2 = etak*etak; + retval.clampedCosTheta = clampedCosTheta; return retval; } T operator()() { - const scalar_type cosTheta2 = cosTheta * cosTheta; + const scalar_type cosTheta2 = clampedCosTheta * clampedCosTheta; //const float sinTheta2 = 1.0 - cosTheta2; - const T etaLen2 = eta * eta + etak * etak; - const T etaCosTwice = eta * cosTheta * 2.0f; + const T etaLen2 = eta * eta + etak2; + assert(etaLen2 > hlsl::promote(hlsl::exp2(-numeric_limits::digits))); + const T etaCosTwice = eta * clampedCosTheta * 2.0f; const T rs_common = etaLen2 + (T)(cosTheta2); const T rs2 = (rs_common - etaCosTwice) / (rs_common + etaCosTwice); @@ -278,8 +290,8 @@ struct Conductor } T eta; - T etak; - scalar_type cosTheta; + T etak2; + scalar_type clampedCosTheta; }; template || is_vector_v) @@ -290,9 +302,10 @@ struct Dielectric static Dielectric create(NBL_CONST_REF_ARG(T) eta, scalar_type cosTheta) { Dielectric retval; - OrientedEtas orientedEta = OrientedEtas::create(cosTheta, eta); - retval.eta2 = orientedEta.value * orientedEta.value; - retval.cosTheta = cosTheta; + scalar_type absCosTheta = hlsl::abs(cosTheta); + OrientedEtas orientedEta = OrientedEtas::create(absCosTheta, eta); + retval.orientedEta2 = orientedEta.value * orientedEta.value; + retval.absCosTheta = absCosTheta; return retval; } @@ -312,11 +325,11 @@ struct Dielectric T operator()() { - return __call(eta2, cosTheta); + return __call(orientedEta2, absCosTheta); } - T eta2; - scalar_type cosTheta; + T orientedEta2; + scalar_type absCosTheta; }; template || is_vector_v) @@ -343,15 +356,12 @@ struct DielectricFrontFaceOnly // gets the sum of all R, T R T, T R^3 T, T R^5 T, ... paths -template -struct ThinDielectricInfiniteScatter +template) +T thinDielectricInfiniteScatter(const T singleInterfaceReflectance) { - T operator()(T singleInterfaceReflectance) - { - const T doubleInterfaceReflectance = singleInterfaceReflectance * singleInterfaceReflectance; - return hlsl::mix(hlsl::promote(1.0), (singleInterfaceReflectance - doubleInterfaceReflectance) / (hlsl::promote(1.0) - doubleInterfaceReflectance) * 2.0f, doubleInterfaceReflectance > hlsl::promote(0.9999)); - } -}; + const T doubleInterfaceReflectance = singleInterfaceReflectance * singleInterfaceReflectance; + return hlsl::mix(hlsl::promote(1.0), (singleInterfaceReflectance - doubleInterfaceReflectance) / (hlsl::promote(1.0) - doubleInterfaceReflectance) * 2.0f, doubleInterfaceReflectance > hlsl::promote(0.9999)); +} } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 49731fd0f3..6eb1dd2662 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -104,7 +104,7 @@ struct SBeckmannDielectricBxDF cache.iso_cache.LdotH = hlsl::mix(VdotH, r.NdotT, transmitted); ray_dir_info_type localL; bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, localV, H, VdotH, cache.iso_cache.getLdotH(), rcpEta.value); - localL.direction = rr(); + localL.direction = rr(transmitted); return sample_type::createFromTangentSpace(localV, localL, m); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 1b0aa8a4c0..d9b7985275 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -111,7 +111,7 @@ struct SGGXDielectricBxDF cache.iso_cache.LdotH = hlsl::mix(VdotH, r.NdotT, transmitted); ray_dir_info_type localL; bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, localV, H, VdotH, cache.iso_cache.getLdotH(), rcpEta.value); - localL.direction = rr(); + localL.direction = rr(transmitted); return sample_type::createFromTangentSpace(localV, localL, m); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index d65508a03d..f57d87dcda 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -69,7 +69,7 @@ struct SSmoothDielectricBxDF ray_dir_info_type L; Refract r = Refract::create(rcpEta, V, N, NdotV); bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, r); - L.direction = rr(); + L.direction = rr(transmitted); return sample_type::create(L, nbl::hlsl::dot(V, L.direction), T, B, N); } @@ -161,8 +161,7 @@ struct SSmoothDielectricBxDF sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N, scalar_type NdotV, scalar_type absNdotV, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(spectral_type) eta2, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint, NBL_REF_ARG(spectral_type) remainderMetadata) { // we will only ever intersect from the outside - fresnel::ThinDielectricInfiniteScatter scatter; - const spectral_type reflectance = scatter(fresnel::Dielectric::__call(eta2,absNdotV)); + const spectral_type reflectance = fresnel::thinDielectricInfiniteScatter(fresnel::Dielectric::__call(eta2,absNdotV)); // we are only allowed one choice for the entire ray, so make the probability a weighted sum const scalar_type reflectionProb = nbl::hlsl::dot(reflectance, luminosityContributionHint); @@ -198,8 +197,7 @@ struct SSmoothDielectricBxDF quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) // isotropic { const bool transmitted = isTransmissionPath(params.uNdotV, params.uNdotL); - fresnel::ThinDielectricInfiniteScatter scatter; - const spectral_type reflectance = scatter(fresnel::Dielectric::__call(eta2, params.NdotV)); + const spectral_type reflectance = fresnel::thinDielectricInfiniteScatter(fresnel::Dielectric::__call(eta2, params.NdotV)); const spectral_type sampleValue = transmitted ? ((spectral_type)(1.0) - reflectance) : reflectance; const scalar_type sampleProb = nbl::hlsl::dot(sampleValue,luminosityContributionHint); From 4c7dfa6b7fbd6ad392f705df850c1179ab9ba5e3 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 15 Apr 2025 15:49:12 +0700 Subject: [PATCH 095/188] change VNDF usage to structs --- include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl | 165 +++++++++++++++--- .../hlsl/bxdf/reflection/beckmann.hlsl | 6 +- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 4 +- .../hlsl/bxdf/transmission/beckmann.hlsl | 6 +- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 4 +- 5 files changed, 152 insertions(+), 33 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl index a39a90b72f..b578ec40b9 100644 --- a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl @@ -15,48 +15,155 @@ namespace bxdf namespace smith { -template -typename NDF::scalar_type VNDF_pdf_wo_clamps(typename NDF::scalar_type ndf, typename NDF::scalar_type lambda_V, typename NDF::scalar_type maxNdotV, NBL_REF_ARG(typename NDF::scalar_type) onePlusLambda_V) +namespace brdf { - onePlusLambda_V = 1.0 + lambda_V; - ndf::microfacet_to_light_measure_transform transform = ndf::microfacet_to_light_measure_transform::create(ndf / onePlusLambda_V, maxNdotV); - return transform(); -} template -typename NDF::scalar_type VNDF_pdf_wo_clamps(typename NDF::scalar_type ndf, typename NDF::scalar_type lambda_V, typename NDF::scalar_type absNdotV, bool transmitted, typename NDF::scalar_type VdotH, typename NDF::scalar_type LdotH, typename NDF::scalar_type VdotHLdotH, typename NDF::scalar_type orientedEta, typename NDF::scalar_type reflectance, NBL_REF_ARG(typename NDF::scalar_type) onePlusLambda_V) +struct VNDF_pdf; + +template +struct VNDF_pdf > { - onePlusLambda_V = 1.0 + lambda_V; - ndf::microfacet_to_light_measure_transform transform - = ndf::microfacet_to_light_measure_transform::create((transmitted ? (1.0 - reflectance) : reflectance) * ndf / onePlusLambda_V, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); - return transform(); -} + using scalar_type = T; + using ndf_type = ndf::Beckmann; + using this_t = VNDF_pdf; + + static this_t create(scalar_type ndf, scalar_type maxNdotV) + { + this_t retval; + retval.ndf = ndf; + retval.maxNdotV = maxNdotV; + return retval; + } + + scalar_type operator()(scalar_type lambda_V) + { + onePlusLambda_V = 1.0 + lambda_V; + ndf::microfacet_to_light_measure_transform transform = ndf::microfacet_to_light_measure_transform::create(ndf / onePlusLambda_V, maxNdotV); + return transform(); + } + + scalar_type ndf; + scalar_type maxNdotV; + scalar_type onePlusLambda_V; +}; -template) -T VNDF_pdf_wo_clamps(T ndf, T G1_over_2NdotV) +template +struct VNDF_pdf > { - return ndf * 0.5 * G1_over_2NdotV; + using scalar_type = T; + using ndf_type = ndf::GGX; + using this_t = VNDF_pdf; + + static this_t create(scalar_type ndf, scalar_type maxNdotV) + { + this_t retval; + retval.ndf = ndf; + retval.maxNdotV = maxNdotV; + return retval; + } + + scalar_type operator()(scalar_type G1_over_2NdotV) + { + return ndf * 0.5 * G1_over_2NdotV; + } + + scalar_type ndf; + scalar_type maxNdotV; + scalar_type onePlusLambda_V; +}; + } -template) -T FVNDF_pdf_wo_clamps(T fresnel_ndf, T G1_over_2NdotV, T absNdotV, bool transmitted, T VdotH, T LdotH, T VdotHLdotH, T orientedEta) +namespace bsdf +{ + +template) +struct FVNDF_pdf { - T FNG = fresnel_ndf * G1_over_2NdotV; - T factor = 0.5; - if (transmitted) + static FVNDF_pdf create(T fresnel_ndf, T absNdotV) { - const T VdotH_etaLdotH = (VdotH + orientedEta * LdotH); - // VdotHLdotH is negative under transmission, so this factor is negative - factor *= -2.0 * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); + FVNDF_pdf retval; + retval.fresnel_ndf = fresnel_ndf; + retval.absNdotV = absNdotV; + return retval; } - return FNG * factor; -} -template) -T VNDF_pdf_wo_clamps(T ndf, T G1_over_2NdotV, T absNdotV, bool transmitted, T VdotH, T LdotH, T VdotHLdotH, T orientedEta, T reflectance) + T operator()(T G1_over_2NdotV, bool transmitted, T VdotH, T LdotH, T VdotHLdotH, T orientedEta) + { + T FNG = fresnel_ndf * G1_over_2NdotV; + T factor = 0.5; + if (transmitted) + { + const T VdotH_etaLdotH = (VdotH + orientedEta * LdotH); + // VdotHLdotH is negative under transmission, so this factor is negative + factor *= -2.0 * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); + } + return FNG * factor; + } + + T fresnel_ndf; + T absNdotV; +}; + +template +struct VNDF_pdf; + +template +struct VNDF_pdf > +{ + using scalar_type = T; + using ndf_type = ndf::Beckmann; + using this_t = VNDF_pdf; + + static this_t create(scalar_type ndf, scalar_type absNdotV) + { + this_t retval; + retval.ndf = ndf; + retval.absNdotV = absNdotV; + return retval; + } + + scalar_type operator()(scalar_type lambda_V, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, scalar_type reflectance) + { + onePlusLambda_V = 1.0 + lambda_V; + ndf::microfacet_to_light_measure_transform transform + = ndf::microfacet_to_light_measure_transform::create(hlsl::mix(reflectance, scalar_type(1.0) - reflectance, transmitted) * ndf / onePlusLambda_V, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); + return transform(); + } + + scalar_type ndf; + scalar_type absNdotV; + scalar_type onePlusLambda_V; +}; + +template +struct VNDF_pdf > { - T FN = (transmitted ? (1.0 - reflectance) : reflectance) * ndf; - return FVNDF_pdf_wo_clamps(FN, G1_over_2NdotV, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); + using scalar_type = T; + using ndf_type = ndf::GGX; + using this_t = VNDF_pdf; + + static this_t create(scalar_type ndf, scalar_type absNdotV) + { + this_t retval; + retval.ndf = ndf; + retval.absNdotV = absNdotV; + return retval; + } + + scalar_type operator()(scalar_type G1_over_2NdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, scalar_type reflectance) + { + scalar_type FN = hlsl::mix(reflectance, scalar_type(1.0) - reflectance, transmitted) * ndf; + FVNDF_pdf fvndf = FVNDF_pdf::create(FN, absNdotV); + return fvndf(G1_over_2NdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); + } + + scalar_type ndf; + scalar_type absNdotV; + scalar_type onePlusLambda_V; +}; + } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index ec3cd8d624..2aaca1042b 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -222,7 +222,11 @@ struct SBeckmannBxDF lambda = beckmann_smith.Lambda(params.NdotV2, a2); } - return smith::VNDF_pdf_wo_clamps >(ndf, lambda, params.uNdotV, onePlusLambda_V); + smith::brdf::VNDF_pdf > vndf = smith::brdf::VNDF_pdf >::create(ndf, params.uNdotV); + scalar_type _pdf = vndf(lambda); + onePlusLambda_V = vndf.onePlusLambda_V; + + return _pdf; } scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index e30af54a17..77be86395d 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -178,7 +178,9 @@ struct SGGXBxDF const scalar_type devsh_v = ggx_smith.devsh_part(params.NdotV2, a2, 1.0-a2); G1_over_2NdotV = ggx_smith.G1_wo_numerator(params.uNdotV, devsh_v); } - return smith::VNDF_pdf_wo_clamps(ndf, G1_over_2NdotV); + + smith::brdf::VNDF_pdf > vndf = smith::brdf::VNDF_pdf >::create(ndf, params.uNdotV); + return vndf(G1_over_2NdotV); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 6eb1dd2662..f66c3ee8c9 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -165,7 +165,11 @@ struct SBeckmannDielectricBxDF lambda = beckmann_smith.Lambda(params.NdotV2, a2); } - return smith::VNDF_pdf_wo_clamps >(ndf,lambda,params.NdotV,transmitted,params.VdotH,params.LdotH,VdotHLdotH,orientedEta.value,reflectance,onePlusLambda_V); + smith::bsdf::VNDF_pdf > vndf = smith::bsdf::VNDF_pdf >::create(ndf, params.NdotV); + scalar_type _pdf = vndf(lambda,transmitted,params.VdotH,params.LdotH,VdotHLdotH,orientedEta.value,reflectance); + onePlusLambda_V = vndf.onePlusLambda_V; + + return _pdf; } scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index d9b7985275..00b0a15740 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -174,7 +174,9 @@ struct SGGXDielectricBxDF smith::GGX ggx_smith; const scalar_type lambda = ggx_smith.G1_wo_numerator(params.NdotV, devsh_v); - return smith::VNDF_pdf_wo_clamps(ndf, lambda, params.NdotV, transmitted, params.VdotH, params.LdotH, VdotHLdotH, orientedEta.value, reflectance); + + smith::bsdf::VNDF_pdf > vndf = smith::bsdf::VNDF_pdf >::create(ndf, params.NdotV); + return vndf(lambda, transmitted, params.VdotH, params.LdotH, VdotHLdotH, orientedEta.value, reflectance); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) From b982f2c74e58838b66f2af6596383a6a12b7ce22 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 15 Apr 2025 16:57:12 +0700 Subject: [PATCH 096/188] compute microfacet normals as structs --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 105 ++++++++---------- .../bxdf/transmission/smooth_dielectric.hlsl | 4 +- 2 files changed, 50 insertions(+), 59 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 8e94550ec5..d906a2ea32 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -24,29 +24,47 @@ namespace hlsl namespace bxdf { -// returns unnormalized vector -template) -T computeUnnormalizedMicrofacetNormal(bool _refract, NBL_CONST_REF_ARG(T) V, NBL_CONST_REF_ARG(T) L, typename vector_traits::scalar_type orientedEta) +template) +struct ComputeMicrofacetNormal { - const typename vector_traits::scalar_type etaFactor = (_refract ? orientedEta : 1.0); - T tmpH = V + L * etaFactor; - tmpH = ieee754::flipSign(tmpH, _refract); - return tmpH; -} + using vector_type = T; + using scalar_type = typename vector_traits::scalar_type; -// returns normalized vector, but NaN when result is length 0 -template) -T computeMicrofacetNormal(bool _refract, NBL_CONST_REF_ARG(T) V, NBL_CONST_REF_ARG(T) L, typename vector_traits::scalar_type orientedEta) -{ - const T H = computeUnnormalizedMicrofacetNormal(_refract,V,L,orientedEta); - return hlsl::normalize(H); -} + static ComputeMicrofacetNormal create(NBL_CONST_REF_ARG(vector_type) V, NBL_CONST_REF_ARG(vector_type) L, NBL_CONST_REF_ARG(vector_type) N, scalar_type eta) + { + ComputeMicrofacetNormal retval; + retval.V = V; + retval.L = L; + retval.orientedEta = fresnel::OrientedEtas::create(hlsl::dot(V, N), eta); + return retval; + } + + vector_type unnormalized(const bool _refract) + { + const scalar_type etaFactor = hlsl::mix(scalar_type(1.0), orientedEta.value, _refract); + vector_type tmpH = V + L * etaFactor; + tmpH = ieee754::flipSign(tmpH, _refract); + return tmpH; + } + + // returns normalized vector, but NaN when result is length 0 + vector_type normalized(const bool _refract) + { + const vector_type H = unnormalized(_refract,V,L,orientedEta); + return hlsl::normalize(H); + } + + // if V and L are on different sides of the surface normal, then their dot product sign bits will differ, hence XOR will yield 1 at last bit + static bool isTransmissionPath(float NdotV, float NdotL) + { + return bool((bit_cast(NdotV) ^ bit_cast(NdotL)) & 0x80000000u); + } + + vector_type V; + vector_type L; + fresnel::OrientedEtas orientedEta; +}; -// if V and L are on different sides of the surface normal, then their dot product sign bits will differ, hence XOR will yield 1 at last bit -bool isTransmissionPath(float NdotV, float NdotL) -{ - return bool((bit_cast(NdotV) ^ bit_cast(NdotL)) & 0x80000000u); -} namespace ray_dir_info { @@ -284,21 +302,6 @@ struct SAnisotropic } -template -struct interaction_traits; - -template -struct interaction_traits > -{ - NBL_CONSTEXPR_STATIC_INLINE bool is_aniso = false; -}; - -template -struct interaction_traits > -{ - NBL_CONSTEXPR_STATIC_INLINE bool is_aniso = true; -}; - #define NBL_CONCEPT_NAME Sample #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) @@ -533,7 +536,10 @@ struct SIsotropicMicrofacetCache ) { // TODO: can we optimize? - H = computeMicrofacetNormal(transmitted,V,L,orientedEta); + ComputeMicrofacetNormal computeMicrofacetNormal = ComputeMicrofacetNormal::create(V,L,N,1.0); + computeMicrofacetNormal.orientedEta.value = orientedEta; + computeMicrofacetNormal.orientedEta.rcp = rcpOrientedEta; + H = computeMicrofacetNormal.normalized(transmitted); retval.NdotH = nbl::hlsl::dot(N, H); // not coming from the medium (reflected) OR @@ -559,7 +565,7 @@ struct SIsotropicMicrofacetCache { const scalar_type NdotV = interaction.getNdotV(); const scalar_type NdotL = _sample.getNdotL(); - const bool transmitted = isTransmissionPath(NdotV,NdotL); + const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(NdotV,NdotL); fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(NdotV, eta); @@ -743,21 +749,6 @@ struct SAnisotropicMicrofacetCache scalar_type BdotH; }; -template -struct microfacet_cache_traits; - -template -struct microfacet_cache_traits > -{ - NBL_CONSTEXPR_STATIC_INLINE bool is_aniso = false; -}; - -template -struct microfacet_cache_traits > -{ - NBL_CONSTEXPR_STATIC_INLINE bool is_aniso = true; -}; - #define NBL_CONCEPT_NAME BxDF #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) @@ -972,7 +963,7 @@ struct SBxDFParams template && (surface_interactions::Isotropic || surface_interactions::Anisotropic)) // maybe put template in struct vs function? static this_t create(NBL_CONST_REF_ARG(LightSample) _sample, NBL_CONST_REF_ARG(Interaction) interaction, BxDFClampMode _clamp) { - impl::__extract_aniso_vars::is_aniso> vars = impl::__extract_aniso_vars::is_aniso>::create(_sample, interaction); + impl::__extract_aniso_vars > vars = impl::__extract_aniso_vars >::create(_sample, interaction); this_t retval; retval.NdotV = math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, vars.NdotV, 0.0); @@ -983,7 +974,7 @@ struct SBxDFParams retval.NdotL2 = _sample.getNdotL2(); retval.VdotL = _sample.getVdotL(); - retval.is_aniso = interaction_traits::is_aniso; + retval.is_aniso = surface_interactions::Anisotropic; retval.TdotL2 = vars.TdotL2; retval.BdotL2 = vars.BdotL2; retval.TdotV2 = vars.TdotV2; @@ -994,8 +985,8 @@ struct SBxDFParams template && (surface_interactions::Isotropic || surface_interactions::Anisotropic) && (IsotropicMicrofacetCache || AnisotropicMicrofacetCache)) static this_t create(NBL_CONST_REF_ARG(LightSample) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(Cache) cache, BxDFClampMode _clamp) { - impl::__extract_aniso_vars::is_aniso> vars = impl::__extract_aniso_vars::is_aniso>::create(_sample, interaction); - impl::__extract_aniso_vars2::is_aniso> vars2 = impl::__extract_aniso_vars2::is_aniso>::create(cache); + impl::__extract_aniso_vars > vars = impl::__extract_aniso_vars >::create(_sample, interaction); + impl::__extract_aniso_vars2 > vars2 = impl::__extract_aniso_vars2 >::create(cache); this_t retval; retval.NdotH = vars2.NdotH; @@ -1010,7 +1001,7 @@ struct SBxDFParams retval.VdotH = vars2.VdotH; retval.LdotH = vars2.LdotH; - retval.is_aniso = interaction_traits::is_aniso; + retval.is_aniso = surface_interactions::Anisotropic; retval.TdotL2 = vars.TdotL2; retval.BdotL2 = vars.BdotL2; retval.TdotV2 = vars.TdotV2; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index f57d87dcda..f6f1206f4a 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -101,7 +101,7 @@ struct SSmoothDielectricBxDF quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) { - const bool transmitted = isTransmissionPath(params.uNdotV, params.uNdotL); + const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(params.uNdotV, params.uNdotL); fresnel::OrientedEtaRcps rcpOrientedEtas = fresnel::OrientedEtaRcps::create(params.NdotV, eta); @@ -196,7 +196,7 @@ struct SSmoothDielectricBxDF quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) // isotropic { - const bool transmitted = isTransmissionPath(params.uNdotV, params.uNdotL); + const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(params.uNdotV, params.uNdotL); const spectral_type reflectance = fresnel::thinDielectricInfiniteScatter(fresnel::Dielectric::__call(eta2, params.NdotV)); const spectral_type sampleValue = transmitted ? ((spectral_type)(1.0) - reflectance) : reflectance; From a0334a09fa7490e811c78efd433ef12bb3a1a787 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 16 Apr 2025 13:26:36 +0700 Subject: [PATCH 097/188] renamed light sample concept --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 83 +++++++++++++------ .../hlsl/bxdf/reflection/beckmann.hlsl | 10 +-- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 10 +-- .../hlsl/bxdf/reflection/lambertian.hlsl | 10 +-- .../hlsl/bxdf/reflection/oren_nayar.hlsl | 10 +-- .../hlsl/bxdf/transmission/beckmann.hlsl | 10 +-- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 10 +-- .../hlsl/bxdf/transmission/lambertian.hlsl | 10 +-- .../bxdf/transmission/smooth_dielectric.hlsl | 26 +++--- 9 files changed, 107 insertions(+), 72 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index d906a2ea32..123c30ea01 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -30,15 +30,31 @@ struct ComputeMicrofacetNormal using vector_type = T; using scalar_type = typename vector_traits::scalar_type; - static ComputeMicrofacetNormal create(NBL_CONST_REF_ARG(vector_type) V, NBL_CONST_REF_ARG(vector_type) L, NBL_CONST_REF_ARG(vector_type) N, scalar_type eta) + static ComputeMicrofacetNormal create(NBL_CONST_REF_ARG(vector_type) V, NBL_CONST_REF_ARG(vector_type) L, NBL_CONST_REF_ARG(vector_type) H, scalar_type eta) { ComputeMicrofacetNormal retval; retval.V = V; retval.L = L; - retval.orientedEta = fresnel::OrientedEtas::create(hlsl::dot(V, N), eta); + retval.orientedEta = fresnel::OrientedEtas::create(hlsl::dot(V, H), eta); return retval; } + // NDFs are defined in terms of `abs(NdotH)` and microfacets are two sided. Note that `N` itself is the definition of the upper hemisphere direction. + // The possible directions of L form a cone around -V with the cosine of the angle equal higher or equal to min(orientedEta, 1.f/orientedEta), and vice versa. + // This means that for: + // - Eta>1 the L will be longer than V projected on V, and VdotH<0 for all L + // - whereas with Eta<1 the L is shorter, and VdotH>0 for all L + // Because to be a refraction `VdotH` and `LdotH` must differ in sign, so whenever one is positive the other is negative. + // Since we're considering single scattering, the V and L must enter the microfacet described by H same way they enter the macro-medium described by N. + // All this means that by looking at the sign of VdotH we can also tell the sign of VdotN. + // However the whole `V+L*eta` formula is backwards because what it should be is `-V-L*eta` so the sign flip is applied just to restore the H-finding to that value. + + // The math: + // dot(V,H) = V2 + VdotL*eta = 1 + VdotL*eta, note that VdotL<=1 so VdotH>=0 when eta==1 + // then with valid transmission path constraint: + // VdotH <= 1-orientedEta2 for orientedEta<1 -> VdotH<0 + // VdotH <= 0 for orientedEta>1 + // so for transmission VdotH<=0, H needs to be flipped to be consistent with oriented eta vector_type unnormalized(const bool _refract) { const scalar_type etaFactor = hlsl::mix(scalar_type(1.0), orientedEta.value, _refract); @@ -284,6 +300,17 @@ struct SAnisotropic return create(isotropic, nbl::hlsl::normalize(T), nbl::hlsl::normalize(B)); } + static SAnisotropic create(NBL_CONST_REF_ARG(RayDirInfo) normalizedV, NBL_CONST_REF_ARG(vector3_type) normalizedN) + { + isotropic_type isotropic = isotropic_type::create(normalizedV, normalizedN); + return create(isotropic); + } + + RayDirInfo getV() NBL_CONST_MEMBER_FUNC { return isotropic.V; } + vector3_type getN() NBL_CONST_MEMBER_FUNC { return isotropic.N; } + scalar_type getNdotV() NBL_CONST_MEMBER_FUNC { return isotropic.NdotV; } + scalar_type getNdotV2() NBL_CONST_MEMBER_FUNC { return isotropic.NdotV2; } + vector3_type getT() NBL_CONST_MEMBER_FUNC { return T; } vector3_type getB() NBL_CONST_MEMBER_FUNC { return B; } scalar_type getTdotV() NBL_CONST_MEMBER_FUNC { return TdotV; } @@ -303,7 +330,7 @@ struct SAnisotropic } -#define NBL_CONCEPT_NAME Sample +#define NBL_CONCEPT_NAME LightSample #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) #define NBL_CONCEPT_TPLT_PRM_NAMES (T) #define NBL_CONCEPT_PARAM_0 (_sample, T) @@ -760,7 +787,8 @@ struct SAnisotropicMicrofacetCache #define NBL_CONCEPT_PARAM_4 (iso, typename T::isotropic_type) #define NBL_CONCEPT_PARAM_5 (aniso, typename T::anisotropic_type) #define NBL_CONCEPT_PARAM_6 (param, typename T::params_t) -NBL_CONCEPT_BEGIN(7) +#define NBL_CONCEPT_PARAM_7 (u, vector) +NBL_CONCEPT_BEGIN(8) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define spec NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define pdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 @@ -768,6 +796,7 @@ NBL_CONCEPT_BEGIN(7) #define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 #define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 #define param NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 +#define u NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_7 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_type)) @@ -777,14 +806,16 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) ((NBL_CONCEPT_REQ_TYPE)(T::params_t)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.eval(param)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(aniso,aniso.N)), ::nbl::hlsl::is_same_v, typename T::sample_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(iso,u)), ::nbl::hlsl::is_same_v, typename T::sample_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(aniso,u)), ::nbl::hlsl::is_same_v, typename T::sample_type)) //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template pdf(_sample,iso)), ::nbl::hlsl::is_scalar_v)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(Sample, typename T::sample_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(LightSample, typename T::sample_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(sampling::spectral_of, typename T::spectral_type, typename T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Isotropic, typename T::isotropic_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Anisotropic, typename T::anisotropic_type)) ); +#undef u #undef param #undef aniso #undef iso @@ -806,7 +837,8 @@ NBL_CONCEPT_END( #define NBL_CONCEPT_PARAM_6 (isocache, typename T::isocache_type) #define NBL_CONCEPT_PARAM_7 (anisocache, typename T::anisocache_type) #define NBL_CONCEPT_PARAM_8 (param, typename T::params_t) -NBL_CONCEPT_BEGIN(9) +#define NBL_CONCEPT_PARAM_9 (u, vector) +NBL_CONCEPT_BEGIN(10) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define spec NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define pdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 @@ -816,6 +848,7 @@ NBL_CONCEPT_BEGIN(9) #define isocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 #define anisocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_7 #define param NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_8 +#define u NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_9 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_type)) @@ -826,14 +859,16 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::isocache_type)) ((NBL_CONCEPT_REQ_TYPE)(T::anisocache_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.eval(param)), ::nbl::hlsl::is_same_v, T::spectral_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(aniso,aniso.N,anisocache)), ::nbl::hlsl::is_same_v, typename T::sample_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(iso,u,isocache)), ::nbl::hlsl::is_same_v, typename T::sample_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(aniso,u,anisocache)), ::nbl::hlsl::is_same_v, typename T::sample_type)) //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.template pdf(_sample,iso)), ::nbl::hlsl::is_scalar_v)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(Sample, typename T::sample_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(LightSample, typename T::sample_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(sampling::spectral_of, typename T::spectral_type, typename T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(IsotropicMicrofacetCache, typename T::isocache_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(AnisotropicMicrofacetCache, typename T::anisocache_type)) ); +#undef u #undef param #undef anisocache #undef isocache @@ -855,15 +890,15 @@ enum BxDFClampMode : uint16_t namespace impl { // this is to substitute the lack of compile-time `if constexpr` on HLSL -template +template struct __extract_aniso_vars; -template -struct __extract_aniso_vars +template +struct __extract_aniso_vars { - static __extract_aniso_vars create(NBL_CONST_REF_ARG(LightSample) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + static __extract_aniso_vars create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - __extract_aniso_vars retval; + __extract_aniso_vars retval; retval.NdotV = interaction.getNdotV(); retval.NdotV2 = interaction.getNdotV2(); return retval; @@ -877,12 +912,12 @@ struct __extract_aniso_vars T BdotV2; }; -template -struct __extract_aniso_vars +template +struct __extract_aniso_vars { - static __extract_aniso_vars create(NBL_CONST_REF_ARG(LightSample) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + static __extract_aniso_vars create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - __extract_aniso_vars retval; + __extract_aniso_vars retval; retval.NdotV = interaction.isotropic.getNdotV(); retval.NdotV2 = interaction.isotropic.getNdotV2(); const T TdotL = _sample.getTdotL(); @@ -960,10 +995,10 @@ struct SBxDFParams { using this_t = SBxDFParams; - template && (surface_interactions::Isotropic || surface_interactions::Anisotropic)) // maybe put template in struct vs function? - static this_t create(NBL_CONST_REF_ARG(LightSample) _sample, NBL_CONST_REF_ARG(Interaction) interaction, BxDFClampMode _clamp) + template && (surface_interactions::Isotropic || surface_interactions::Anisotropic)) // maybe put template in struct vs function? + static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, BxDFClampMode _clamp) { - impl::__extract_aniso_vars > vars = impl::__extract_aniso_vars >::create(_sample, interaction); + impl::__extract_aniso_vars > vars = impl::__extract_aniso_vars >::create(_sample, interaction); this_t retval; retval.NdotV = math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, vars.NdotV, 0.0); @@ -982,10 +1017,10 @@ struct SBxDFParams return retval; } - template && (surface_interactions::Isotropic || surface_interactions::Anisotropic) && (IsotropicMicrofacetCache || AnisotropicMicrofacetCache)) - static this_t create(NBL_CONST_REF_ARG(LightSample) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(Cache) cache, BxDFClampMode _clamp) + template && (surface_interactions::Isotropic || surface_interactions::Anisotropic) && (IsotropicMicrofacetCache || AnisotropicMicrofacetCache)) + static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(Cache) cache, BxDFClampMode _clamp) { - impl::__extract_aniso_vars > vars = impl::__extract_aniso_vars >::create(_sample, interaction); + impl::__extract_aniso_vars > vars = impl::__extract_aniso_vars >::create(_sample, interaction); impl::__extract_aniso_vars2 > vars2 = impl::__extract_aniso_vars2 >::create(cache); this_t retval; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 2aaca1042b..6f83b6ce55 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -17,12 +17,12 @@ namespace bxdf namespace reflection { -template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) +template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SBeckmannBxDF { - using this_t = SBeckmannBxDF; - using scalar_type = typename LightSample::scalar_type; - using ray_dir_info_type = typename LightSample::ray_dir_info_type; + using this_t = SBeckmannBxDF; + using scalar_type = typename LS::scalar_type; + using ray_dir_info_type = typename LS::ray_dir_info_type; using vector2_type = vector; using vector3_type = vector; using matrix2x3_type = matrix; @@ -30,7 +30,7 @@ struct SBeckmannBxDF using isotropic_type = typename IsoCache::isotropic_type; using anisotropic_type = typename AnisoCache::anisotropic_type; - using sample_type = LightSample; + using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; using isocache_type = IsoCache; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 77be86395d..e9c7abd66e 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -17,12 +17,12 @@ namespace bxdf namespace reflection { -template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) +template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SGGXBxDF { - using this_t = SGGXBxDF; - using scalar_type = typename LightSample::scalar_type; - using ray_dir_info_type = typename LightSample::ray_dir_info_type; + using this_t = SGGXBxDF; + using scalar_type = typename LS::scalar_type; + using ray_dir_info_type = typename LS::ray_dir_info_type; using vector2_type = vector; using vector3_type = vector; using matrix2x3_type = matrix; @@ -30,7 +30,7 @@ struct SGGXBxDF using isotropic_type = typename IsoCache::isotropic_type; using anisotropic_type = typename AnisoCache::anisotropic_type; - using sample_type = LightSample; + using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; using isocache_type = IsoCache; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl index 8e47e39e85..619b2a3196 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl @@ -17,15 +17,15 @@ namespace bxdf namespace reflection { -template && surface_interactions::Isotropic && surface_interactions::Anisotropic) +template && surface_interactions::Isotropic && surface_interactions::Anisotropic) struct SLambertianBxDF { - using this_t = SLambertianBxDF; - using scalar_type = typename LightSample::scalar_type; - using ray_dir_info_type = typename LightSample::ray_dir_info_type; + using this_t = SLambertianBxDF; + using scalar_type = typename LS::scalar_type; + using ray_dir_info_type = typename LS::ray_dir_info_type; using isotropic_type = Iso; using anisotropic_type = Aniso; - using sample_type = LightSample; + using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; using params_t = SBxDFParams; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl index b9525be19f..1f35433061 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl @@ -17,17 +17,17 @@ namespace bxdf namespace reflection { -template && surface_interactions::Isotropic && surface_interactions::Anisotropic) +template && surface_interactions::Isotropic && surface_interactions::Anisotropic) struct SOrenNayarBxDF { - using this_t = SOrenNayarBxDF; - using scalar_type = typename LightSample::scalar_type; + using this_t = SOrenNayarBxDF; + using scalar_type = typename LS::scalar_type; using vector2_type = vector; - using ray_dir_info_type = typename LightSample::ray_dir_info_type; + using ray_dir_info_type = typename LS::ray_dir_info_type; using isotropic_type = Iso; using anisotropic_type = Aniso; - using sample_type = LightSample; + using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; using params_t = SBxDFParams; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index f66c3ee8c9..87228d2bef 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -17,12 +17,12 @@ namespace bxdf namespace transmission { -template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) +template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SBeckmannDielectricBxDF { - using this_t = SBeckmannDielectricBxDF; - using scalar_type = typename LightSample::scalar_type; - using ray_dir_info_type = typename LightSample::ray_dir_info_type; + using this_t = SBeckmannDielectricBxDF; + using scalar_type = typename LS::scalar_type; + using ray_dir_info_type = typename LS::ray_dir_info_type; using vector2_type = vector; using vector3_type = vector; using matrix3x3_type = matrix; @@ -30,7 +30,7 @@ struct SBeckmannDielectricBxDF using isotropic_type = typename IsoCache::isotropic_type; using anisotropic_type = typename AnisoCache::anisotropic_type; - using sample_type = LightSample; + using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; using isocache_type = IsoCache; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 00b0a15740..f83b919383 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -17,12 +17,12 @@ namespace bxdf namespace transmission { -template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) +template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SGGXDielectricBxDF { - using this_t = SGGXDielectricBxDF; - using scalar_type = typename LightSample::scalar_type; - using ray_dir_info_type = typename LightSample::ray_dir_info_type; + using this_t = SGGXDielectricBxDF; + using scalar_type = typename LS::scalar_type; + using ray_dir_info_type = typename LS::ray_dir_info_type; using vector2_type = vector; using vector3_type = vector; using matrix3x3_type = matrix; @@ -30,7 +30,7 @@ struct SGGXDielectricBxDF using isotropic_type = typename IsoCache::isotropic_type; using anisotropic_type = typename AnisoCache::anisotropic_type; - using sample_type = LightSample; + using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; using isocache_type = IsoCache; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl index b4258f22a3..13f84ed9ab 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl @@ -17,15 +17,15 @@ namespace bxdf namespace transmission { -template && surface_interactions::Isotropic && surface_interactions::Anisotropic) +template && surface_interactions::Isotropic && surface_interactions::Anisotropic) struct SLambertianBxDF { - using this_t = SLambertianBxDF; - using scalar_type = typename LightSample::scalar_type; - using ray_dir_info_type = typename LightSample::ray_dir_info_type; + using this_t = SLambertianBxDF; + using scalar_type = typename LS::scalar_type; + using ray_dir_info_type = typename LS::ray_dir_info_type; using isotropic_type = Iso; using anisotropic_type = Aniso; - using sample_type = LightSample; + using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; using params_t = SBxDFParams; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index f6f1206f4a..5dcec8bfaf 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -17,21 +17,21 @@ namespace bxdf namespace transmission { -template // NBL_FUNC_REQUIRES(Sample && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) // dxc won't let me put this in +template // NBL_FUNC_REQUIRES(Sample && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) // dxc won't let me put this in struct SSmoothDielectricBxDF; -template -struct SSmoothDielectricBxDF +template +struct SSmoothDielectricBxDF { - using this_t = SSmoothDielectricBxDF; - using scalar_type = typename LightSample::scalar_type; - using ray_dir_info_type = typename LightSample::ray_dir_info_type; + using this_t = SSmoothDielectricBxDF; + using scalar_type = typename LS::scalar_type; + using ray_dir_info_type = typename LS::ray_dir_info_type; using vector3_type = vector; using params_t = SBxDFParams; using isotropic_type = typename IsoCache::isotropic_type; using anisotropic_type = typename AnisoCache::anisotropic_type; - using sample_type = LightSample; + using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; using isocache_type = IsoCache; @@ -113,18 +113,18 @@ struct SSmoothDielectricBxDF scalar_type eta; }; -template -struct SSmoothDielectricBxDF +template +struct SSmoothDielectricBxDF { - using this_t = SSmoothDielectricBxDF; - using scalar_type = typename LightSample::scalar_type; - using ray_dir_info_type = typename LightSample::ray_dir_info_type; + using this_t = SSmoothDielectricBxDF; + using scalar_type = typename LS::scalar_type; + using ray_dir_info_type = typename LS::ray_dir_info_type; using vector3_type = vector; using params_t = SBxDFParams; using isotropic_type = typename IsoCache::isotropic_type; using anisotropic_type = typename AnisoCache::anisotropic_type; - using sample_type = LightSample; + using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; using isocache_type = IsoCache; From 79ef0d73fda186187cb3fd810646754561d9f43a Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 16 Apr 2025 14:34:01 +0700 Subject: [PATCH 098/188] changes to microfacet cache member funcs --- examples_tests | 2 +- include/nbl/builtin/hlsl/bxdf/common.hlsl | 74 +++++++++---------- .../hlsl/bxdf/reflection/lambertian.hlsl | 5 ++ .../hlsl/bxdf/reflection/oren_nayar.hlsl | 5 ++ 4 files changed, 47 insertions(+), 39 deletions(-) diff --git a/examples_tests b/examples_tests index dd7c0c7a12..9b071a6567 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit dd7c0c7a12cc5a15d5d48f97cf2b7647ff07f426 +Subproject commit 9b071a656775966350513899c1af5901d48a684a diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 123c30ea01..8cdd8f5ac2 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -433,22 +433,20 @@ struct SLightSample return retval; } - // overloads for surface_interactions, NOTE: temporarily commented out due to dxc bug https://github.com/microsoft/DirectXShaderCompiler/issues/7154 - // template - // static this_t create(NBL_CONST_REF_ARG(vector3_type) L, NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction) - // { - // const vector3_type V = interaction.V.getDirection(); - // const scalar_type VdotL = nbl::hlsl::dot(V,L); - // return create(L, VdotL, interaction.N); - // } - // template - // static this_t create(NBL_CONST_REF_ARG(vector3_type) L, NBL_CONST_REF_ARG(surface_interactions::SAnisotropic) interaction) - // { - // const vector3_type V = interaction.V.getDirection(); - // const scalar_type VdotL = nbl::hlsl::dot(V,L); - // return create(L,VdotL,interaction.T,interaction.B,interaction.N); - // } - // + + template) + static this_t create(NBL_CONST_REF_ARG(vector3_type) L, NBL_CONST_REF_ARG(SurfaceInteraction) interaction) + { + const vector3_type V = interaction.V.getDirection(); + const scalar_type VdotL = nbl::hlsl::dot(V,L); + this_t retval; + if (surface_interactions::Anisotropic) // TODO use NBL_IF_CONSTEXPR when pr #860 is merged + retval = create(L,VdotL,interaction.T,interaction.B,interaction.N); + else + retval = create(L, VdotL, interaction.N); + return retval; + } + vector3_type getTangentSpaceL() NBL_CONST_MEMBER_FUNC { return vector3_type(TdotL, BdotL, NdotL); @@ -501,10 +499,10 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getNdotH2()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(pNdotV,pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, T)) - //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(iso,_sample)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(iso,_sample)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::compute(cache,b0,V,V,V,pNdotV,pNdotV,pNdotV,pNdotV,V)), ::nbl::hlsl::is_same_v, bool)) - //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,iso,_sample,pNdotV,V)), ::nbl::hlsl::is_same_v, bool)) - //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,iso,_sample,pNdotV)), ::nbl::hlsl::is_same_v, bool)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,iso,_sample,pNdotV,V)), ::nbl::hlsl::is_same_v, bool)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,iso,_sample,pNdotV)), ::nbl::hlsl::is_same_v, bool)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.isValidVNDFMicrofacet(b0,b0,pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, bool)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Isotropic, typename T::isotropic_type)) ); @@ -547,10 +545,10 @@ struct SIsotropicMicrofacetCache float dummy; return createForReflection(NdotV, NdotL, VdotL, dummy); } - template && ray_dir_info::Basic) + template && LightSample) static this_t createForReflection( - NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction, - NBL_CONST_REF_ARG(SLightSample) _sample) + NBL_CONST_REF_ARG(IsotropicInteraction) interaction, + NBL_CONST_REF_ARG(LS) _sample) { return createForReflection(interaction.getNdotV(), _sample.getNdotL(), _sample.getVdotL()); } @@ -582,11 +580,11 @@ struct SIsotropicMicrofacetCache } return false; } - template && ray_dir_info::Basic) + template && LightSample) static bool compute( NBL_REF_ARG(this_t) retval, - NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction, - NBL_CONST_REF_ARG(SLightSample) _sample, + NBL_CONST_REF_ARG(IsotropicInteraction) interaction, + NBL_CONST_REF_ARG(LS) _sample, const scalar_type eta, NBL_REF_ARG(vector3_type) H ) { @@ -601,16 +599,16 @@ struct SIsotropicMicrofacetCache const scalar_type VdotL = nbl::hlsl::dot(V, L); return compute(retval,transmitted,V,L,interaction.getN(),NdotL,VdotL,orientedEta.value,orientedEta.rcp,H); } - template && ray_dir_info::Basic) + template && LightSample) static bool compute( NBL_REF_ARG(this_t) retval, - NBL_CONST_REF_ARG(surface_interactions::SIsotropic) interaction, - NBL_CONST_REF_ARG(SLightSample) _sample, + NBL_CONST_REF_ARG(IsotropicInteraction) interaction, + NBL_CONST_REF_ARG(LS) _sample, const scalar_type eta ) { vector3_type dummy; - return compute(retval,interaction,_sample,eta,dummy); + return compute(retval,interaction,_sample,eta,dummy); } bool isValidVNDFMicrofacet(const bool is_bsdf, const bool transmission, const scalar_type VdotL, const scalar_type eta, const scalar_type rcp_eta) @@ -657,9 +655,9 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V,b0,pNdotL,pNdotL)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(V,V,pNdotL)), ::nbl::hlsl::is_same_v, T)) - //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(aniso,_sample)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(aniso,_sample)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::compute(cache,b0,V,V,V,V,V,pNdotL,pNdotL,pNdotL,pNdotL,V)), ::nbl::hlsl::is_same_v, bool)) - //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,aniso,_sample)), ::nbl::hlsl::is_same_v, bool)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,aniso,_sample,pNdotL)), ::nbl::hlsl::is_same_v, bool)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Anisotropic, typename T::anisotropic_type)) ); #undef b0 @@ -726,10 +724,10 @@ struct SAnisotropicMicrofacetCache return retval; } - template + template && LightSample) static this_t createForReflection( - NBL_CONST_REF_ARG(surface_interactions::SAnisotropic) interaction, - NBL_CONST_REF_ARG(SLightSample) _sample) + NBL_CONST_REF_ARG(AnisotropicInteraction) interaction, + NBL_CONST_REF_ARG(LS) _sample) { return createForReflection(interaction.getTangentSpaceV(), _sample.getTangentSpaceL(), _sample.getVdotL()); } @@ -750,16 +748,16 @@ struct SAnisotropicMicrofacetCache } return valid; } - template + template && LightSample) static bool compute( NBL_REF_ARG(this_t) retval, - NBL_CONST_REF_ARG(surface_interactions::SAnisotropic) interaction, - NBL_CONST_REF_ARG(SLightSample) _sample, + NBL_CONST_REF_ARG(AnisotropicInteraction) interaction, + NBL_CONST_REF_ARG(LS) _sample, const scalar_type eta ) { vector3_type H; - const bool valid = isocache_type::template compute(retval.iso_cache,interaction.isotropic,_sample,eta,H); + const bool valid = isocache_type::template compute(retval.iso_cache,interaction.isotropic,_sample,eta,H); if (valid) { retval.TdotH = nbl::hlsl::dot(interaction.getT(),H); diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl index 619b2a3196..8b6a6ae27d 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl @@ -69,6 +69,11 @@ struct SLambertianBxDF return generate_wo_clamps(interaction, u); } + sample_type generate(NBL_CONST_REF_ARG(isotropic_type) interaction, NBL_CONST_REF_ARG(vector) u) + { + return generate_wo_clamps(anisotropic_type::create(interaction), u); + } + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) { return sampling::ProjectedHemisphere::pdf(params.NdotL); diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl index 1f35433061..9e7bfe16d1 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl @@ -76,6 +76,11 @@ struct SOrenNayarBxDF return generate_wo_clamps(interaction, u); } + sample_type generate(NBL_CONST_REF_ARG(isotropic_type) interaction, NBL_CONST_REF_ARG(vector) u) + { + return generate_wo_clamps(anisotropic_type::create(interaction), u); + } + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) { return sampling::ProjectedHemisphere::pdf(params.NdotL); From cc5fab563c98934b6f073c85a0d1e82dfc6f2e72 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 16 Apr 2025 14:43:46 +0700 Subject: [PATCH 099/188] added isotropic generate --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 1 - include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl | 8 ++++++++ include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 8 ++++++++ include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl | 8 ++++++++ include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl | 8 ++++++++ .../nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl | 5 +++++ 6 files changed, 37 insertions(+), 1 deletion(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 8cdd8f5ac2..07e8872ec9 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -470,7 +470,6 @@ struct SLightSample }; -// TODO: figure out the commented constraints, templated RayDirInfo not really working for some reason #define NBL_CONCEPT_NAME IsotropicMicrofacetCache #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) #define NBL_CONCEPT_TPLT_PRM_NAMES (T) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 6f83b6ce55..3bee3b7718 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -198,6 +198,14 @@ struct SBeckmannBxDF return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); } + sample_type generate(NBL_CONST_REF_ARG(isotropic_type) interaction, NBL_CONST_REF_ARG(vector2_type) u, NBL_REF_ARG(isocache_type) cache) + { + anisocache_type anisocache; + sample_type s = generate(anisotropic_type::create(interaction), u, anisocache); + cache = anisocache.iso_cache; + return s; + } + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { scalar_type ndf, lambda; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index e9c7abd66e..4e3180d1c8 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -152,6 +152,14 @@ struct SGGXBxDF return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); } + sample_type generate(NBL_CONST_REF_ARG(isotropic_type) interaction, NBL_CONST_REF_ARG(vector2_type) u, NBL_REF_ARG(isocache_type) cache) + { + anisocache_type anisocache; + sample_type s = generate(anisotropic_type::create(interaction), u, anisocache); + cache = anisocache.iso_cache; + return s; + } + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) { scalar_type ndf, G1_over_2NdotV; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 87228d2bef..34fa0001d4 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -131,6 +131,14 @@ struct SBeckmannDielectricBxDF return generate(interaction, u, dummycache); } + sample_type generate(NBL_CONST_REF_ARG(isotropic_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) + { + anisocache_type anisocache; + sample_type s = generate(anisotropic_type::create(interaction), u, anisocache); + cache = anisocache.iso_cache; + return s; + } + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.VdotH, eta); diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index f83b919383..b105aeb4ad 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -138,6 +138,14 @@ struct SGGXDielectricBxDF return generate(interaction, u, dummycache); } + sample_type generate(NBL_CONST_REF_ARG(isotropic_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) + { + anisocache_type anisocache; + sample_type s = generate(anisotropic_type::create(interaction), u, anisocache); + cache = anisocache.iso_cache; + return s; + } + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) { fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.VdotH, eta); diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl index 13f84ed9ab..652da8abad 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl @@ -69,6 +69,11 @@ struct SLambertianBxDF return generate_wo_clamps(interaction, u); } + sample_type generate(NBL_CONST_REF_ARG(isotropic_type) interaction, NBL_CONST_REF_ARG(vector) u) + { + return generate_wo_clamps(anisotropic_type::create(interaction), u); + } + scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) { return sampling::ProjectedSphere::pdf(params.NdotL); From f99933b3ae311fa64c5d4f6029cd278b9431e372 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 16 Apr 2025 16:59:46 +0700 Subject: [PATCH 100/188] fix surface interaction, microfacet cache concepts + default concepts --- examples_tests | 2 +- include/nbl/builtin/hlsl/bxdf/common.hlsl | 167 ++++++++++-------- include/nbl/builtin/hlsl/bxdf/fresnel.hlsl | 2 +- .../hlsl/bxdf/reflection/beckmann.hlsl | 2 +- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 2 +- .../hlsl/bxdf/transmission/beckmann.hlsl | 2 +- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 2 +- 7 files changed, 98 insertions(+), 81 deletions(-) diff --git a/examples_tests b/examples_tests index 9b071a6567..61757af8b5 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 9b071a656775966350513899c1af5901d48a684a +Subproject commit 61757af8b5417c276f843fcc463cf33c80a5ea92 diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 07e8872ec9..56961d1105 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -470,22 +470,16 @@ struct SLightSample }; -#define NBL_CONCEPT_NAME IsotropicMicrofacetCache +#define NBL_CONCEPT_NAME ReadableIsotropicMicrofacetCache #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) #define NBL_CONCEPT_TPLT_PRM_NAMES (T) #define NBL_CONCEPT_PARAM_0 (cache, T) -#define NBL_CONCEPT_PARAM_1 (iso, typename T::isotropic_type) -#define NBL_CONCEPT_PARAM_2 (pNdotV, typename T::scalar_type) -#define NBL_CONCEPT_PARAM_3 (_sample, typename T::sample_type) -#define NBL_CONCEPT_PARAM_4 (V, typename T::vector3_type) -#define NBL_CONCEPT_PARAM_5 (b0, bool) -NBL_CONCEPT_BEGIN(6) +#define NBL_CONCEPT_PARAM_1 (pNdotV, typename T::scalar_type) +#define NBL_CONCEPT_PARAM_2 (b0, bool) +NBL_CONCEPT_BEGIN(3) #define cache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 -#define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 -#define pNdotV NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 -#define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 -#define V NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 -#define b0 NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 +#define pNdotV NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 +#define b0 NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::ray_dir_info_type)) ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_type)) @@ -496,16 +490,39 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getLdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getNdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getNdotH2()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(pNdotV,pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(iso,_sample)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::compute(cache,b0,V,V,V,pNdotV,pNdotV,pNdotV,pNdotV,V)), ::nbl::hlsl::is_same_v, bool)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,iso,_sample,pNdotV,V)), ::nbl::hlsl::is_same_v, bool)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,iso,_sample,pNdotV)), ::nbl::hlsl::is_same_v, bool)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.isValidVNDFMicrofacet(b0,b0,pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, bool)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Isotropic, typename T::isotropic_type)) ); #undef b0 +#undef pNdotV +#undef cache +#include + +#define NBL_CONCEPT_NAME CreatableIsotropicMicrofacetCache +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (cache, T) +#define NBL_CONCEPT_PARAM_1 (iso, typename T::isotropic_type) +#define NBL_CONCEPT_PARAM_2 (pNdotV, typename T::scalar_type) +#define NBL_CONCEPT_PARAM_3 (_sample, typename T::sample_type) +#define NBL_CONCEPT_PARAM_4 (V, typename T::vector3_type) +#define NBL_CONCEPT_PARAM_5 (eta, fresnel::OrientedEtas) +NBL_CONCEPT_BEGIN(6) +#define cache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +#define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 +#define pNdotV NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +#define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 +#define V NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 +#define eta NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(pNdotV,pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(iso,_sample)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V,V,eta,V)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create(iso,_sample,eta,V)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(ReadableIsotropicMicrofacetCache, T)) +); +#undef eta #undef V #undef _sample #undef pNdotV @@ -551,68 +568,53 @@ struct SIsotropicMicrofacetCache { return createForReflection(interaction.getNdotV(), _sample.getNdotL(), _sample.getVdotL()); } + // transmissive cases need to be checked if the path is valid before usage - static bool compute( - NBL_REF_ARG(this_t) retval, - const bool transmitted, NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) L, - NBL_CONST_REF_ARG(vector3_type) N, const scalar_type NdotL, const scalar_type VdotL, - const scalar_type orientedEta, const scalar_type rcpOrientedEta, NBL_REF_ARG(vector3_type) H - ) + static this_t create( + NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) L, NBL_CONST_REF_ARG(vector3_type) N, + NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEtas, NBL_REF_ARG(vector3_type) H) { - // TODO: can we optimize? + this_t retval; + const scalar_type NdotV = hlsl::dot(N, V); + const scalar_type NdotL = hlsl::dot(N, L); + const scalar_type VdotL = hlsl::dot(V, L); + const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(NdotV,NdotL); + ComputeMicrofacetNormal computeMicrofacetNormal = ComputeMicrofacetNormal::create(V,L,N,1.0); - computeMicrofacetNormal.orientedEta.value = orientedEta; - computeMicrofacetNormal.orientedEta.rcp = rcpOrientedEta; + computeMicrofacetNormal.orientedEta.value = orientedEtas.value; + computeMicrofacetNormal.orientedEta.rcp = orientedEtas.rcp; H = computeMicrofacetNormal.normalized(transmitted); - retval.NdotH = nbl::hlsl::dot(N, H); + retval.NdotH = hlsl::dot(N, H); // not coming from the medium (reflected) OR // exiting at the macro scale AND ( (not L outside the cone of possible directions given IoR with constraint VdotH*LdotH<0.0) OR (microfacet not facing toward the macrosurface, i.e. non heightfield profile of microsurface) ) - const bool valid = !transmitted || (VdotL <= -min(orientedEta, rcpOrientedEta) && retval.NdotH > nbl::hlsl::numeric_limits::min); + const bool valid = !transmitted || (VdotL <= -hlsl::min(orientedEtas.value, orientedEtas.rcp) && retval.NdotH >= nbl::hlsl::numeric_limits::min); if (valid) { - // TODO: can we optimize? - retval.VdotH = nbl::hlsl::dot(V,H); - retval.LdotH = nbl::hlsl::dot(L,H); + retval.VdotH = hlsl::dot(V,H); + retval.LdotH = hlsl::dot(L,H); retval.NdotH2 = retval.NdotH * retval.NdotH; - return true; } - return false; + else + retval.NdotH = -1.0; + return retval; } + template && LightSample) - static bool compute( - NBL_REF_ARG(this_t) retval, + static this_t create( NBL_CONST_REF_ARG(IsotropicInteraction) interaction, NBL_CONST_REF_ARG(LS) _sample, - const scalar_type eta, NBL_REF_ARG(vector3_type) H - ) + NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEtas, NBL_REF_ARG(vector3_type) H) { - const scalar_type NdotV = interaction.getNdotV(); - const scalar_type NdotL = _sample.getNdotL(); - const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(NdotV,NdotL); - - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(NdotV, eta); - const vector3_type V = interaction.getV().getDirection(); const vector3_type L = _sample.getL().getDirection(); - const scalar_type VdotL = nbl::hlsl::dot(V, L); - return compute(retval,transmitted,V,L,interaction.getN(),NdotL,VdotL,orientedEta.value,orientedEta.rcp,H); - } - template && LightSample) - static bool compute( - NBL_REF_ARG(this_t) retval, - NBL_CONST_REF_ARG(IsotropicInteraction) interaction, - NBL_CONST_REF_ARG(LS) _sample, - const scalar_type eta - ) - { - vector3_type dummy; - return compute(retval,interaction,_sample,eta,dummy); + + return create(V,L,interaction.getN(),orientedEtas,H); } bool isValidVNDFMicrofacet(const bool is_bsdf, const bool transmission, const scalar_type VdotL, const scalar_type eta, const scalar_type rcp_eta) { - return NdotH >= 0.0 && !(is_bsdf && transmission && (VdotL > -min(eta, rcp_eta))); + return NdotH >= 0.0 && !(is_bsdf && transmission && (VdotL > -hlsl::min(eta, rcp_eta))); } scalar_type getVdotH() NBL_CONST_MEMBER_FUNC { return VdotH; } @@ -636,13 +638,15 @@ struct SIsotropicMicrofacetCache #define NBL_CONCEPT_PARAM_3 (_sample, typename T::sample_type) #define NBL_CONCEPT_PARAM_4 (V, typename T::vector3_type) #define NBL_CONCEPT_PARAM_5 (b0, bool) -NBL_CONCEPT_BEGIN(6) +#define NBL_CONCEPT_PARAM_6 (eta, fresnel::OrientedEtas) +NBL_CONCEPT_BEGIN(7) #define cache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define pNdotL NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 #define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 #define V NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 #define b0 NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 +#define eta NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::ray_dir_info_type)) ((NBL_CONCEPT_REQ_TYPE)(T::anisotropic_type)) @@ -655,10 +659,11 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V,b0,pNdotL,pNdotL)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(V,V,pNdotL)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(aniso,_sample)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::compute(cache,b0,V,V,V,V,V,pNdotL,pNdotL,pNdotL,pNdotL,V)), ::nbl::hlsl::is_same_v, bool)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template compute(cache,aniso,_sample,pNdotL)), ::nbl::hlsl::is_same_v, bool)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V,V,V,V,eta,V)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create(aniso,_sample,eta)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Anisotropic, typename T::anisotropic_type)) ); +#undef eta #undef b0 #undef V #undef _sample @@ -678,6 +683,7 @@ struct SAnisotropicMicrofacetCache using ray_dir_info_type = ray_dir_info::SBasic; using anisotropic_type = surface_interactions::SAnisotropic; using isocache_type = SIsotropicMicrofacetCache; + using isotropic_type = isocache_type::isotropic_type; using sample_type = SLightSample; // always valid by construction @@ -731,40 +737,51 @@ struct SAnisotropicMicrofacetCache return createForReflection(interaction.getTangentSpaceV(), _sample.getTangentSpaceL(), _sample.getVdotL()); } // transmissive cases need to be checked if the path is valid before usage - static bool compute( - NBL_REF_ARG(this_t) retval, - const bool transmitted, NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) L, + static this_t create( + NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) L, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N, - const scalar_type NdotL, const scalar_type VdotL, - const scalar_type orientedEta, const scalar_type rcpOrientedEta, NBL_REF_ARG(vector3_type) H + NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEtas, NBL_REF_ARG(vector3_type) H ) { - const bool valid = isocache_type::compute(retval.iso_cache,transmitted,V,L,N,NdotL,VdotL,orientedEta,rcpOrientedEta,H); + this_t retval; + retval.iso_cache = isocache_type::create(V,L,N,orientedEtas,H); + const bool valid = retval.iso_cache.NdotH >= 0.0; if (valid) { retval.TdotH = nbl::hlsl::dot(T,H); retval.BdotH = nbl::hlsl::dot(B,H); } - return valid; + return retval; } template && LightSample) - static bool compute( - NBL_REF_ARG(this_t) retval, + static this_t create( NBL_CONST_REF_ARG(AnisotropicInteraction) interaction, NBL_CONST_REF_ARG(LS) _sample, - const scalar_type eta + NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEtas ) { + this_t retval; vector3_type H; - const bool valid = isocache_type::template compute(retval.iso_cache,interaction.isotropic,_sample,eta,H); + retval.iso_cache = isocache_type::template create(interaction.isotropic,_sample,orientedEtas,H); + const bool valid = retval.iso_cache.NdotH >= 0.0; if (valid) { retval.TdotH = nbl::hlsl::dot(interaction.getT(),H); retval.BdotH = nbl::hlsl::dot(interaction.getB(),H); } - return valid; + return retval; + } + + bool isValidVNDFMicrofacet(const bool is_bsdf, const bool transmission, const scalar_type VdotL, const scalar_type eta, const scalar_type rcp_eta) + { + return iso_cache.isValidVNDFMicrofacet(is_bsdf, transmission, VdotL, eta, rcp_eta); } + scalar_type getVdotH() NBL_CONST_MEMBER_FUNC { return iso_cache.VdotH; } + scalar_type getLdotH() NBL_CONST_MEMBER_FUNC { return iso_cache.LdotH; } + scalar_type getNdotH() NBL_CONST_MEMBER_FUNC { return iso_cache.NdotH; } + scalar_type getNdotH2() NBL_CONST_MEMBER_FUNC { return iso_cache.NdotH2; } + scalar_type getTdotH() NBL_CONST_MEMBER_FUNC { return TdotH; } scalar_type getBdotH() NBL_CONST_MEMBER_FUNC { return BdotH; } @@ -862,7 +879,7 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(LightSample, typename T::sample_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(sampling::spectral_of, typename T::spectral_type, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(IsotropicMicrofacetCache, typename T::isocache_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(CreatableIsotropicMicrofacetCache, typename T::isocache_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(AnisotropicMicrofacetCache, typename T::anisocache_type)) ); #undef u @@ -1014,7 +1031,7 @@ struct SBxDFParams return retval; } - template && (surface_interactions::Isotropic || surface_interactions::Anisotropic) && (IsotropicMicrofacetCache || AnisotropicMicrofacetCache)) + template && (surface_interactions::Isotropic || surface_interactions::Anisotropic) && (CreatableIsotropicMicrofacetCache || AnisotropicMicrofacetCache)) static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(Cache) cache, BxDFClampMode _clamp) { impl::__extract_aniso_vars > vars = impl::__extract_aniso_vars >::create(_sample, interaction); diff --git a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl index 3008f38531..506daa5b61 100644 --- a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl @@ -277,7 +277,7 @@ struct Conductor //const float sinTheta2 = 1.0 - cosTheta2; const T etaLen2 = eta * eta + etak2; - assert(etaLen2 > hlsl::promote(hlsl::exp2(-numeric_limits::digits))); + assert(hlsl::any(etaLen2 > hlsl::promote(hlsl::exp2(-numeric_limits::digits)))); const T etaCosTwice = eta * clampedCosTheta * 2.0f; const T rs_common = etaLen2 + (T)(cosTheta2); diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 3bee3b7718..52baa4437a 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -17,7 +17,7 @@ namespace bxdf namespace reflection { -template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) +template && CreatableIsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SBeckmannBxDF { using this_t = SBeckmannBxDF; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 4e3180d1c8..f18894668d 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -17,7 +17,7 @@ namespace bxdf namespace reflection { -template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) +template && CreatableIsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SGGXBxDF { using this_t = SGGXBxDF; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 34fa0001d4..554fccfcb0 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -17,7 +17,7 @@ namespace bxdf namespace transmission { -template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) +template && CreatableIsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SBeckmannDielectricBxDF { using this_t = SBeckmannDielectricBxDF; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index b105aeb4ad..c9fdec144b 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -17,7 +17,7 @@ namespace bxdf namespace transmission { -template && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) +template && CreatableIsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SGGXDielectricBxDF { using this_t = SGGXDielectricBxDF; From f2f9210dcc217edc92dae1ad56cfcf5c86010a32 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 16 Apr 2025 17:05:07 +0700 Subject: [PATCH 101/188] minor bug fix --- examples_tests | 2 +- include/nbl/builtin/hlsl/bxdf/common.hlsl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples_tests b/examples_tests index 61757af8b5..2ae583ff5b 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 61757af8b5417c276f843fcc463cf33c80a5ea92 +Subproject commit 2ae583ff5bcc49948017bb856dbdfb3de991d764 diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 56961d1105..13eef72c19 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -683,7 +683,7 @@ struct SAnisotropicMicrofacetCache using ray_dir_info_type = ray_dir_info::SBasic; using anisotropic_type = surface_interactions::SAnisotropic; using isocache_type = SIsotropicMicrofacetCache; - using isotropic_type = isocache_type::isotropic_type; + using isotropic_type = typename isocache_type::isotropic_type; using sample_type = SLightSample; // always valid by construction From 493bc494bd3619eb9abba3f544465272239a6a68 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 17 Apr 2025 11:44:57 +0700 Subject: [PATCH 102/188] minor changes --- examples_tests | 2 +- include/nbl/builtin/hlsl/bxdf/common.hlsl | 4 ++-- .../builtin/hlsl/bxdf/reflection/lambertian.hlsl | 4 ++-- .../hlsl/bxdf/transmission/lambertian.hlsl | 3 ++- ...{rand_gen.hlsl => dim_adaptor_recursive.hlsl} | 11 ++++++----- .../nbl/builtin/hlsl/sampling/cos_weighted.hlsl | 16 ++++++++-------- .../builtin/hlsl/sampling/quotient_and_pdf.hlsl | 7 ++++--- include/nbl/builtin/hlsl/sampling/uniform.hlsl | 14 +++++++------- 8 files changed, 32 insertions(+), 29 deletions(-) rename include/nbl/builtin/hlsl/random/{rand_gen.hlsl => dim_adaptor_recursive.hlsl} (63%) diff --git a/examples_tests b/examples_tests index 2ae583ff5b..d4d94e61de 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 2ae583ff5bcc49948017bb856dbdfb3de991d764 +Subproject commit d4d94e61dead828a09525b27291686ab58b06e05 diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 13eef72c19..0d22ce93ab 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -825,7 +825,7 @@ NBL_CONCEPT_END( //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template pdf(_sample,iso)), ::nbl::hlsl::is_scalar_v)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(LightSample, typename T::sample_type)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(sampling::spectral_of, typename T::spectral_type, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(sampling::Spectral, typename T::spectral_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Isotropic, typename T::isotropic_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Anisotropic, typename T::anisotropic_type)) ); @@ -878,7 +878,7 @@ NBL_CONCEPT_END( //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.template pdf(_sample,iso)), ::nbl::hlsl::is_scalar_v)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(LightSample, typename T::sample_type)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(sampling::spectral_of, typename T::spectral_type, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(sampling::Spectral, typename T::spectral_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(CreatableIsotropicMicrofacetCache, typename T::isocache_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(AnisotropicMicrofacetCache, typename T::anisocache_type)) ); diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl index 8b6a6ae27d..4ebe0d93b1 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl @@ -81,8 +81,8 @@ struct SLambertianBxDF quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) { - scalar_type _pdf; - return sampling::ProjectedHemisphere::template quotient_and_pdf(params.NdotL); + sampling::quotient_and_pdf qp = sampling::ProjectedHemisphere::template quotient_and_pdf(params.NdotL); + return quotient_pdf_type::create(hlsl::promote(qp.quotient), qp.pdf); } }; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl index 652da8abad..21b5058a6f 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl @@ -81,7 +81,8 @@ struct SLambertianBxDF quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) { - return sampling::ProjectedSphere::template quotient_and_pdf(params.NdotL); + sampling::quotient_and_pdf qp = sampling::ProjectedSphere::template quotient_and_pdf(params.NdotL); + return quotient_pdf_type::create(hlsl::promote(qp.quotient), qp.pdf); } }; diff --git a/include/nbl/builtin/hlsl/random/rand_gen.hlsl b/include/nbl/builtin/hlsl/random/dim_adaptor_recursive.hlsl similarity index 63% rename from include/nbl/builtin/hlsl/random/rand_gen.hlsl rename to include/nbl/builtin/hlsl/random/dim_adaptor_recursive.hlsl index 7cd7288b8b..8ec882de78 100644 --- a/include/nbl/builtin/hlsl/random/rand_gen.hlsl +++ b/include/nbl/builtin/hlsl/random/dim_adaptor_recursive.hlsl @@ -1,5 +1,5 @@ -#ifndef _NBL_HLSL_RANDOM_RANDGEN_INCLUDED_ -#define _NBL_HLSL_RANDOM_RANDGEN_INCLUDED_ +#ifndef _NBL_HLSL_RANDOM_DIM_ADAPTOR_RECURSIVE_INCLUDED_ +#define _NBL_HLSL_RANDOM_DIM_ADAPTOR_RECURSIVE_INCLUDED_ #include "nbl/builtin/hlsl/type_traits.hlsl" @@ -10,15 +10,16 @@ namespace hlsl namespace random { +// adapts PRNG for multiple dimensions using recursive calls, rather than hash based template -struct Uniform +struct DimAdaptorRecursive { using rng_type = RNG; using return_type = vector; - static Uniform construct(rng_type rng) + static DimAdaptorRecursive construct(rng_type rng) { - Uniform retval; + DimAdaptorRecursive retval; retval.rng = rng; return retval; } diff --git a/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl b/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl index 5604e397b4..d80778ed9a 100644 --- a/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl +++ b/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl @@ -34,16 +34,16 @@ struct ProjectedHemisphere return L_z * numbers::inv_pi; } - template + template) static sampling::quotient_and_pdf quotient_and_pdf(T L) { - return sampling::quotient_and_pdf::create(hlsl::promote(1.0), pdf(L)); + return sampling::quotient_and_pdf::create(U(1.0), pdf(L)); } - template + template) static sampling::quotient_and_pdf quotient_and_pdf(vector_t3 L) { - return sampling::quotient_and_pdf::create(hlsl::promote(1.0), pdf(L.z)); + return sampling::quotient_and_pdf::create(U(1.0), pdf(L.z)); } }; @@ -70,16 +70,16 @@ struct ProjectedSphere return T(0.5) * hemisphere_t::pdf(L_z); } - template + template) static sampling::quotient_and_pdf quotient_and_pdf(T L) { - return sampling::quotient_and_pdf::create(hlsl::promote(1.0), pdf(L)); + return sampling::quotient_and_pdf::create(U(1.0), pdf(L)); } - template + template) static sampling::quotient_and_pdf quotient_and_pdf(vector_t3 L) { - return sampling::quotient_and_pdf::create(hlsl::promote(1.0), pdf(L.z)); + return sampling::quotient_and_pdf::create(U(1.0), pdf(L.z)); } }; diff --git a/include/nbl/builtin/hlsl/sampling/quotient_and_pdf.hlsl b/include/nbl/builtin/hlsl/sampling/quotient_and_pdf.hlsl index e48983c047..0620b2bad6 100644 --- a/include/nbl/builtin/hlsl/sampling/quotient_and_pdf.hlsl +++ b/include/nbl/builtin/hlsl/sampling/quotient_and_pdf.hlsl @@ -6,6 +6,7 @@ #define _NBL_BUILTIN_HLSL_SAMPLING_QUOTIENT_AND_PDF_INCLUDED_ #include "nbl/builtin/hlsl/concepts/vector.hlsl" +#include "nbl/builtin/hlsl/vector_utils/vector_traits.hlsl" namespace nbl { @@ -14,11 +15,11 @@ namespace hlsl namespace sampling { -template -NBL_BOOL_CONCEPT spectral_of = concepts::Vectorial || concepts::Scalar || concepts::Scalar; +template +NBL_BOOL_CONCEPT Spectral = (concepts::Vectorial || concepts::Scalar) && is_floating_point_v::scalar_type>; // finally fixed the semantic F-up, value/pdf = quotient not remainder -template && is_floating_point_v

) +template && is_floating_point_v

) struct quotient_and_pdf { using this_t = quotient_and_pdf; diff --git a/include/nbl/builtin/hlsl/sampling/uniform.hlsl b/include/nbl/builtin/hlsl/sampling/uniform.hlsl index 48284a1c31..69a83d5a93 100644 --- a/include/nbl/builtin/hlsl/sampling/uniform.hlsl +++ b/include/nbl/builtin/hlsl/sampling/uniform.hlsl @@ -36,14 +36,14 @@ struct UniformHemisphere return T(1.0) / (T(2.0) * numbers::pi); } - template - static sampling::quotient_and_pdf quotient_and_pdf() + template) + static quotient_and_pdf quotient_and_pdf() { - return sampling::quotient_and_pdf::create(hlsl::promote(1.0), pdf()); + return quotient_and_pdf::create(U(1.0), pdf()); } }; -template +template) struct UniformSphere { using vector_t2 = vector; @@ -62,10 +62,10 @@ struct UniformSphere return T(1.0) / (T(4.0) * numbers::pi); } - template - static sampling::quotient_and_pdf quotient_and_pdf() + template) + static quotient_and_pdf quotient_and_pdf() { - return sampling::quotient_and_pdf::create(hlsl::promote(1.0), pdf()); + return quotient_and_pdf::create(U(1.0), pdf()); } }; } From 4b87a4a7ac7b3668e82268f13fb047a861773677 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 17 Apr 2025 14:30:16 +0700 Subject: [PATCH 103/188] renamed some typedefs --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 80 +++++++++---------- .../hlsl/bxdf/reflection/beckmann.hlsl | 10 +-- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 10 +-- .../hlsl/bxdf/reflection/lambertian.hlsl | 12 +-- .../hlsl/bxdf/reflection/oren_nayar.hlsl | 12 +-- .../hlsl/bxdf/transmission/beckmann.hlsl | 12 +-- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 12 +-- .../hlsl/bxdf/transmission/lambertian.hlsl | 12 +-- .../bxdf/transmission/smooth_dielectric.hlsl | 16 ++-- 9 files changed, 88 insertions(+), 88 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 0d22ce93ab..53484bdba8 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -234,7 +234,7 @@ struct SIsotropic #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) #define NBL_CONCEPT_TPLT_PRM_NAMES (T) #define NBL_CONCEPT_PARAM_0 (aniso, T) -#define NBL_CONCEPT_PARAM_1 (iso, typename T::isotropic_type) +#define NBL_CONCEPT_PARAM_1 (iso, typename T::isotropic_interaction_type) #define NBL_CONCEPT_PARAM_2 (normT, typename T::vector3_type) NBL_CONCEPT_BEGIN(3) #define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 @@ -242,7 +242,7 @@ NBL_CONCEPT_BEGIN(3) #define normT NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::ray_dir_info_type)) - ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_interaction_type)) ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) ((NBL_CONCEPT_REQ_TYPE)(T::matrix3x3_type)) @@ -254,7 +254,7 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getTangentSpaceV()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getToTangentSpace()), ::nbl::hlsl::is_same_v, typename T::matrix3x3_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getFromTangentSpace()), ::nbl::hlsl::is_same_v, typename T::matrix3x3_type)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(Isotropic, typename T::isotropic_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(Isotropic, typename T::isotropic_interaction_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(ray_dir_info::Basic, typename T::ray_dir_info_type)) ); #undef normT @@ -269,11 +269,11 @@ struct SAnisotropic using scalar_type = typename RayDirInfo::scalar_type; using vector3_type = typename RayDirInfo::vector3_type; using matrix3x3_type = matrix; - using isotropic_type = SIsotropic; + using isotropic_interaction_type = SIsotropic; // WARNING: Changed since GLSL, now arguments need to be normalized! static SAnisotropic create( - NBL_CONST_REF_ARG(isotropic_type) isotropic, + NBL_CONST_REF_ARG(isotropic_interaction_type) isotropic, NBL_CONST_REF_ARG(vector3_type) normalizedT, NBL_CONST_REF_ARG(vector3_type) normalizedB ) @@ -289,11 +289,11 @@ struct SAnisotropic return retval; } - static SAnisotropic create(NBL_CONST_REF_ARG(isotropic_type) isotropic, NBL_CONST_REF_ARG(vector3_type) normalizedT) + static SAnisotropic create(NBL_CONST_REF_ARG(isotropic_interaction_type) isotropic, NBL_CONST_REF_ARG(vector3_type) normalizedT) { return create(isotropic, normalizedT, cross(isotropic.getN(), normalizedT)); } - static SAnisotropic create(NBL_CONST_REF_ARG(isotropic_type) isotropic) + static SAnisotropic create(NBL_CONST_REF_ARG(isotropic_interaction_type) isotropic) { vector3_type T, B; math::frisvad(isotropic.getN(), T, B); @@ -302,7 +302,7 @@ struct SAnisotropic static SAnisotropic create(NBL_CONST_REF_ARG(RayDirInfo) normalizedV, NBL_CONST_REF_ARG(vector3_type) normalizedN) { - isotropic_type isotropic = isotropic_type::create(normalizedV, normalizedN); + isotropic_interaction_type isotropic = isotropic_interaction_type::create(normalizedV, normalizedN); return create(isotropic); } @@ -320,7 +320,7 @@ struct SAnisotropic matrix3x3_type getToTangentSpace() NBL_CONST_MEMBER_FUNC { return matrix3x3_type(T, B, isotropic.N); } matrix3x3_type getFromTangentSpace() NBL_CONST_MEMBER_FUNC { return nbl::hlsl::transpose(matrix3x3_type(T, B, isotropic.N)); } - isotropic_type isotropic; + isotropic_interaction_type isotropic; vector3_type T; vector3_type B; scalar_type TdotV; @@ -334,8 +334,8 @@ struct SAnisotropic #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) #define NBL_CONCEPT_TPLT_PRM_NAMES (T) #define NBL_CONCEPT_PARAM_0 (_sample, T) -#define NBL_CONCEPT_PARAM_1 (iso, typename T::isotropic_type) -#define NBL_CONCEPT_PARAM_2 (aniso, typename T::anisotropic_type) +#define NBL_CONCEPT_PARAM_1 (iso, typename T::isotropic_interaction_type) +#define NBL_CONCEPT_PARAM_2 (aniso, typename T::anisotropic_interaction_type) #define NBL_CONCEPT_PARAM_3 (rdirinfo, typename T::ray_dir_info_type) #define NBL_CONCEPT_PARAM_4 (pV, typename T::vector3_type) #define NBL_CONCEPT_PARAM_5 (frame, typename T::matrix3x3_type) @@ -350,7 +350,7 @@ NBL_CONCEPT_BEGIN(7) #define pVdotL NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::ray_dir_info_type)) - ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_interaction_type)) ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) ((NBL_CONCEPT_REQ_TYPE)(T::matrix3x3_type)) @@ -367,8 +367,8 @@ NBL_CONCEPT_END( //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create(pV,aniso)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getTangentSpaceL()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(ray_dir_info::Basic, typename T::ray_dir_info_type)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Isotropic, typename T::isotropic_type)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Anisotropic, typename T::anisotropic_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Isotropic, typename T::isotropic_interaction_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Anisotropic, typename T::anisotropic_interaction_type)) ); #undef pVdotL #undef frame @@ -388,8 +388,8 @@ struct SLightSample using vector3_type = typename RayDirInfo::vector3_type; using matrix3x3_type = matrix; - using isotropic_type = surface_interactions::SIsotropic; - using anisotropic_type = surface_interactions::SAnisotropic; + using isotropic_interaction_type = surface_interactions::SIsotropic; + using anisotropic_interaction_type = surface_interactions::SAnisotropic; static this_t createFromTangentSpace( NBL_CONST_REF_ARG(vector3_type) tangentSpaceV, @@ -482,7 +482,7 @@ NBL_CONCEPT_BEGIN(3) #define b0 NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::ray_dir_info_type)) - ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_interaction_type)) ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) ((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) @@ -491,7 +491,7 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getNdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getNdotH2()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.isValidVNDFMicrofacet(b0,b0,pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, bool)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Isotropic, typename T::isotropic_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Isotropic, typename T::isotropic_interaction_type)) ); #undef b0 #undef pNdotV @@ -502,7 +502,7 @@ NBL_CONCEPT_END( #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) #define NBL_CONCEPT_TPLT_PRM_NAMES (T) #define NBL_CONCEPT_PARAM_0 (cache, T) -#define NBL_CONCEPT_PARAM_1 (iso, typename T::isotropic_type) +#define NBL_CONCEPT_PARAM_1 (iso, typename T::isotropic_interaction_type) #define NBL_CONCEPT_PARAM_2 (pNdotV, typename T::scalar_type) #define NBL_CONCEPT_PARAM_3 (_sample, typename T::sample_type) #define NBL_CONCEPT_PARAM_4 (V, typename T::vector3_type) @@ -517,9 +517,9 @@ NBL_CONCEPT_BEGIN(6) NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(pNdotV,pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(iso,_sample)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(iso,_sample)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V,V,eta,V)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create(iso,_sample,eta,V)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create(iso,_sample,eta,V)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(ReadableIsotropicMicrofacetCache, T)) ); #undef eta @@ -539,7 +539,7 @@ struct SIsotropicMicrofacetCache using matrix3x3_type = matrix; using ray_dir_info_type = ray_dir_info::SBasic; - using isotropic_type = surface_interactions::SIsotropic; + using isotropic_interaction_type = surface_interactions::SIsotropic; using sample_type = SLightSample; // always valid because its specialized for the reflective case @@ -633,7 +633,7 @@ struct SIsotropicMicrofacetCache #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) #define NBL_CONCEPT_TPLT_PRM_NAMES (T) #define NBL_CONCEPT_PARAM_0 (cache, T) -#define NBL_CONCEPT_PARAM_1 (aniso, typename T::anisotropic_type) +#define NBL_CONCEPT_PARAM_1 (aniso, typename T::anisotropic_interaction_type) #define NBL_CONCEPT_PARAM_2 (pNdotL, typename T::scalar_type) #define NBL_CONCEPT_PARAM_3 (_sample, typename T::sample_type) #define NBL_CONCEPT_PARAM_4 (V, typename T::vector3_type) @@ -649,7 +649,7 @@ NBL_CONCEPT_BEGIN(7) #define eta NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::ray_dir_info_type)) - ((NBL_CONCEPT_REQ_TYPE)(T::anisotropic_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::anisotropic_interaction_type)) ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) ((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) @@ -658,10 +658,10 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V,b0,pNdotL,pNdotL)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(V,V,pNdotL)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(aniso,_sample)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(aniso,_sample)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V,V,V,V,eta,V)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create(aniso,_sample,eta)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Anisotropic, typename T::anisotropic_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create(aniso,_sample,eta)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Anisotropic, typename T::anisotropic_interaction_type)) ); #undef eta #undef b0 @@ -681,9 +681,9 @@ struct SAnisotropicMicrofacetCache using matrix3x3_type = matrix; using ray_dir_info_type = ray_dir_info::SBasic; - using anisotropic_type = surface_interactions::SAnisotropic; + using anisotropic_interaction_type = surface_interactions::SAnisotropic; using isocache_type = SIsotropicMicrofacetCache; - using isotropic_type = typename isocache_type::isotropic_type; + using isotropic_interaction_type = typename isocache_type::isotropic_interaction_type; using sample_type = SLightSample; // always valid by construction @@ -762,7 +762,7 @@ struct SAnisotropicMicrofacetCache { this_t retval; vector3_type H; - retval.iso_cache = isocache_type::template create(interaction.isotropic,_sample,orientedEtas,H); + retval.iso_cache = isocache_type::template create(interaction.isotropic,_sample,orientedEtas,H); const bool valid = retval.iso_cache.NdotH >= 0.0; if (valid) { @@ -798,8 +798,8 @@ struct SAnisotropicMicrofacetCache #define NBL_CONCEPT_PARAM_1 (spec, typename T::spectral_type) #define NBL_CONCEPT_PARAM_2 (pdf, typename T::scalar_type) #define NBL_CONCEPT_PARAM_3 (_sample, typename T::sample_type) -#define NBL_CONCEPT_PARAM_4 (iso, typename T::isotropic_type) -#define NBL_CONCEPT_PARAM_5 (aniso, typename T::anisotropic_type) +#define NBL_CONCEPT_PARAM_4 (iso, typename T::isotropic_interaction_type) +#define NBL_CONCEPT_PARAM_5 (aniso, typename T::anisotropic_interaction_type) #define NBL_CONCEPT_PARAM_6 (param, typename T::params_t) #define NBL_CONCEPT_PARAM_7 (u, vector) NBL_CONCEPT_BEGIN(8) @@ -813,8 +813,8 @@ NBL_CONCEPT_BEGIN(8) #define u NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_7 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) - ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_type)) - ((NBL_CONCEPT_REQ_TYPE)(T::anisotropic_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_interaction_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::anisotropic_interaction_type)) ((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) ((NBL_CONCEPT_REQ_TYPE)(T::spectral_type)) ((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) @@ -826,8 +826,8 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(LightSample, typename T::sample_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(sampling::Spectral, typename T::spectral_type)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Isotropic, typename T::isotropic_type)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Anisotropic, typename T::anisotropic_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Isotropic, typename T::isotropic_interaction_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Anisotropic, typename T::anisotropic_interaction_type)) ); #undef u #undef param @@ -846,8 +846,8 @@ NBL_CONCEPT_END( #define NBL_CONCEPT_PARAM_1 (spec, typename T::spectral_type) #define NBL_CONCEPT_PARAM_2 (pdf, typename T::scalar_type) #define NBL_CONCEPT_PARAM_3 (_sample, typename T::sample_type) -#define NBL_CONCEPT_PARAM_4 (iso, typename T::isotropic_type) -#define NBL_CONCEPT_PARAM_5 (aniso, typename T::anisotropic_type) +#define NBL_CONCEPT_PARAM_4 (iso, typename T::isotropic_interaction_type) +#define NBL_CONCEPT_PARAM_5 (aniso, typename T::anisotropic_interaction_type) #define NBL_CONCEPT_PARAM_6 (isocache, typename T::isocache_type) #define NBL_CONCEPT_PARAM_7 (anisocache, typename T::anisocache_type) #define NBL_CONCEPT_PARAM_8 (param, typename T::params_t) @@ -865,8 +865,8 @@ NBL_CONCEPT_BEGIN(10) #define u NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_9 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) - ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_type)) - ((NBL_CONCEPT_REQ_TYPE)(T::anisotropic_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_interaction_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::anisotropic_interaction_type)) ((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) ((NBL_CONCEPT_REQ_TYPE)(T::spectral_type)) ((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 52baa4437a..839b5f4c43 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -28,8 +28,8 @@ struct SBeckmannBxDF using matrix2x3_type = matrix; using params_t = SBxDFParams; - using isotropic_type = typename IsoCache::isotropic_type; - using anisotropic_type = typename AnisoCache::anisotropic_type; + using isotropic_interaction_type = typename IsoCache::isotropic_interaction_type; + using anisotropic_interaction_type = typename AnisoCache::anisotropic_interaction_type; using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; @@ -185,7 +185,7 @@ struct SBeckmannBxDF return nbl::hlsl::normalize(vector3_type(-slope, 1.0)); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector2_type) u, NBL_REF_ARG(anisocache_type) cache) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector2_type) u, NBL_REF_ARG(anisocache_type) cache) { const vector3_type localV = interaction.getTangentSpaceV(); const vector3_type H = __generate(localV, u); @@ -198,10 +198,10 @@ struct SBeckmannBxDF return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); } - sample_type generate(NBL_CONST_REF_ARG(isotropic_type) interaction, NBL_CONST_REF_ARG(vector2_type) u, NBL_REF_ARG(isocache_type) cache) + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector2_type) u, NBL_REF_ARG(isocache_type) cache) { anisocache_type anisocache; - sample_type s = generate(anisotropic_type::create(interaction), u, anisocache); + sample_type s = generate(anisotropic_interaction_type::create(interaction), u, anisocache); cache = anisocache.iso_cache; return s; } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index f18894668d..d3f8099676 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -28,8 +28,8 @@ struct SGGXBxDF using matrix2x3_type = matrix; using params_t = SBxDFParams; - using isotropic_type = typename IsoCache::isotropic_type; - using anisotropic_type = typename AnisoCache::anisotropic_type; + using isotropic_interaction_type = typename IsoCache::isotropic_interaction_type; + using anisotropic_interaction_type = typename AnisoCache::anisotropic_interaction_type; using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; @@ -139,7 +139,7 @@ struct SGGXBxDF return nbl::hlsl::normalize(vector3_type(A.x*H.x, A.y*H.y, H.z)); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector2_type) u, NBL_REF_ARG(anisocache_type) cache) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector2_type) u, NBL_REF_ARG(anisocache_type) cache) { const vector3_type localV = interaction.getTangentSpaceV(); const vector3_type H = __generate(localV, u); @@ -152,10 +152,10 @@ struct SGGXBxDF return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); } - sample_type generate(NBL_CONST_REF_ARG(isotropic_type) interaction, NBL_CONST_REF_ARG(vector2_type) u, NBL_REF_ARG(isocache_type) cache) + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector2_type) u, NBL_REF_ARG(isocache_type) cache) { anisocache_type anisocache; - sample_type s = generate(anisotropic_type::create(interaction), u, anisocache); + sample_type s = generate(anisotropic_interaction_type::create(interaction), u, anisocache); cache = anisocache.iso_cache; return s; } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl index 4ebe0d93b1..20b6715241 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl @@ -23,8 +23,8 @@ struct SLambertianBxDF using this_t = SLambertianBxDF; using scalar_type = typename LS::scalar_type; using ray_dir_info_type = typename LS::ray_dir_info_type; - using isotropic_type = Iso; - using anisotropic_type = Aniso; + using isotropic_interaction_type = Iso; + using anisotropic_interaction_type = Aniso; using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; @@ -57,21 +57,21 @@ struct SLambertianBxDF return __eval_pi_factored_out(params.NdotL) * numbers::inv_pi; } - sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector) u) + sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector) u) { ray_dir_info_type L; L.direction = sampling::ProjectedHemisphere::generate(u); return sample_type::createFromTangentSpace(interaction.getTangentSpaceV(), L, interaction.getFromTangentSpace()); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector) u) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector) u) { return generate_wo_clamps(interaction, u); } - sample_type generate(NBL_CONST_REF_ARG(isotropic_type) interaction, NBL_CONST_REF_ARG(vector) u) + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector) u) { - return generate_wo_clamps(anisotropic_type::create(interaction), u); + return generate_wo_clamps(anisotropic_interaction_type::create(interaction), u); } scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl index 9e7bfe16d1..97a318edc4 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl @@ -25,8 +25,8 @@ struct SOrenNayarBxDF using vector2_type = vector; using ray_dir_info_type = typename LS::ray_dir_info_type; - using isotropic_type = Iso; - using anisotropic_type = Aniso; + using isotropic_interaction_type = Iso; + using anisotropic_interaction_type = Aniso; using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; @@ -64,21 +64,21 @@ struct SOrenNayarBxDF return params.NdotL * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(params.VdotL, params.NdotL, params.NdotV); } - sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector2_type) u) + sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector2_type) u) { ray_dir_info_type L; L.direction = sampling::ProjectedHemisphere::generate(u); return sample_type::createFromTangentSpace(interaction.getTangentSpaceV(), L, interaction.getFromTangentSpace()); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector2_type) u) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector2_type) u) { return generate_wo_clamps(interaction, u); } - sample_type generate(NBL_CONST_REF_ARG(isotropic_type) interaction, NBL_CONST_REF_ARG(vector) u) + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector) u) { - return generate_wo_clamps(anisotropic_type::create(interaction), u); + return generate_wo_clamps(anisotropic_interaction_type::create(interaction), u); } scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 554fccfcb0..283215f591 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -28,8 +28,8 @@ struct SBeckmannDielectricBxDF using matrix3x3_type = matrix; using params_t = SBxDFParams; - using isotropic_type = typename IsoCache::isotropic_type; - using anisotropic_type = typename AnisoCache::anisotropic_type; + using isotropic_interaction_type = typename IsoCache::isotropic_interaction_type; + using anisotropic_interaction_type = typename AnisoCache::anisotropic_interaction_type; using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; @@ -109,7 +109,7 @@ struct SBeckmannDielectricBxDF return sample_type::createFromTangentSpace(localV, localL, m); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) { const vector3_type localV = interaction.getTangentSpaceV(); @@ -125,16 +125,16 @@ struct SBeckmannDielectricBxDF return __generate_wo_clamps(localV, H, interaction.getFromTangentSpace(), u, orientedEta, rcpEta, cache); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector3_type) u) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u) { anisocache_type dummycache; return generate(interaction, u, dummycache); } - sample_type generate(NBL_CONST_REF_ARG(isotropic_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) { anisocache_type anisocache; - sample_type s = generate(anisotropic_type::create(interaction), u, anisocache); + sample_type s = generate(anisotropic_interaction_type::create(interaction), u, anisocache); cache = anisocache.iso_cache; return s; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index c9fdec144b..e20564001c 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -28,8 +28,8 @@ struct SGGXDielectricBxDF using matrix3x3_type = matrix; using params_t = SBxDFParams; - using isotropic_type = typename IsoCache::isotropic_type; - using anisotropic_type = typename AnisoCache::anisotropic_type; + using isotropic_interaction_type = typename IsoCache::isotropic_interaction_type; + using anisotropic_interaction_type = typename AnisoCache::anisotropic_interaction_type; using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; @@ -116,7 +116,7 @@ struct SGGXDielectricBxDF return sample_type::createFromTangentSpace(localV, localL, m); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(anisocache_type) cache) { const vector3_type localV = interaction.getTangentSpaceV(); @@ -132,16 +132,16 @@ struct SGGXDielectricBxDF return __generate_wo_clamps(localV, H, interaction.getFromTangentSpace(), u, orientedEta, rcpEta, cache); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector3_type) u) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u) { anisocache_type dummycache; return generate(interaction, u, dummycache); } - sample_type generate(NBL_CONST_REF_ARG(isotropic_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) { anisocache_type anisocache; - sample_type s = generate(anisotropic_type::create(interaction), u, anisocache); + sample_type s = generate(anisotropic_interaction_type::create(interaction), u, anisocache); cache = anisocache.iso_cache; return s; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl index 21b5058a6f..1eee08a486 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl @@ -23,8 +23,8 @@ struct SLambertianBxDF using this_t = SLambertianBxDF; using scalar_type = typename LS::scalar_type; using ray_dir_info_type = typename LS::ray_dir_info_type; - using isotropic_type = Iso; - using anisotropic_type = Aniso; + using isotropic_interaction_type = Iso; + using anisotropic_interaction_type = Aniso; using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; @@ -57,21 +57,21 @@ struct SLambertianBxDF return __eval_pi_factored_out(params.NdotL) * numbers::inv_pi * 0.5; } - sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector) u) + sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector) u) { ray_dir_info_type L; L.direction = sampling::ProjectedSphere::generate(u); return sample_type::createFromTangentSpace(interaction.getTangentSpaceV(), L, interaction.getFromTangentSpace()); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_CONST_REF_ARG(vector) u) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector) u) { return generate_wo_clamps(interaction, u); } - sample_type generate(NBL_CONST_REF_ARG(isotropic_type) interaction, NBL_CONST_REF_ARG(vector) u) + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector) u) { - return generate_wo_clamps(anisotropic_type::create(interaction), u); + return generate_wo_clamps(anisotropic_interaction_type::create(interaction), u); } scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index 5dcec8bfaf..d163148020 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -29,8 +29,8 @@ struct SSmoothDielectricBxDF using vector3_type = vector; using params_t = SBxDFParams; - using isotropic_type = typename IsoCache::isotropic_type; - using anisotropic_type = typename AnisoCache::anisotropic_type; + using isotropic_interaction_type = typename IsoCache::isotropic_interaction_type; + using anisotropic_interaction_type = typename AnisoCache::anisotropic_interaction_type; using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; @@ -73,7 +73,7 @@ struct SSmoothDielectricBxDF return sample_type::create(L, nbl::hlsl::dot(V, L.direction), T, B, N); } - sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector) u) + sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector) u) { fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), eta); fresnel::OrientedEtaRcps rcpEta = fresnel::OrientedEtaRcps::create(interaction.isotropic.getNdotV(), eta); @@ -83,7 +83,7 @@ struct SSmoothDielectricBxDF NdotV, u, orientedEta, rcpEta, dummy); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector) u) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector) u) { fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), eta); fresnel::OrientedEtaRcps rcpEta = fresnel::OrientedEtaRcps::create(interaction.isotropic.getNdotV(), eta); @@ -122,8 +122,8 @@ struct SSmoothDielectricBxDF using vector3_type = vector; using params_t = SBxDFParams; - using isotropic_type = typename IsoCache::isotropic_type; - using anisotropic_type = typename AnisoCache::anisotropic_type; + using isotropic_interaction_type = typename IsoCache::isotropic_interaction_type; + using anisotropic_interaction_type = typename AnisoCache::anisotropic_interaction_type; using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; @@ -175,14 +175,14 @@ struct SSmoothDielectricBxDF return sample_type::create(L, nbl::hlsl::dot(V, L.direction), T, B, N); } - sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector) u) + sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector) u) { scalar_type NdotV = interaction.isotropic.getNdotV(); vector3_type dummy; return __generate_wo_clamps(interaction.isotropic.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.isotropic.getN(), NdotV, NdotV, u, eta2, luminosityContributionHint, dummy); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_type) interaction, NBL_REF_ARG(vector) u) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector) u) { scalar_type NdotV = interaction.isotropic.getNdotV(); vector3_type dummy; From 31f2af8bc5998ba5f642aee19507a934234972f0 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 17 Apr 2025 16:06:01 +0700 Subject: [PATCH 104/188] moved typedefs, template params dependencies into bxdfs --- examples_tests | 2 +- .../nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl | 24 ++-- include/nbl/builtin/hlsl/bxdf/common.hlsl | 123 ++++++++---------- .../hlsl/bxdf/reflection/beckmann.hlsl | 8 +- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 8 +- .../hlsl/bxdf/reflection/lambertian.hlsl | 2 +- .../hlsl/bxdf/reflection/oren_nayar.hlsl | 2 +- .../hlsl/bxdf/transmission/beckmann.hlsl | 16 +-- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 14 +- .../hlsl/bxdf/transmission/lambertian.hlsl | 2 +- .../bxdf/transmission/smooth_dielectric.hlsl | 22 ++-- 11 files changed, 102 insertions(+), 121 deletions(-) diff --git a/examples_tests b/examples_tests index d4d94e61de..cf2dbcffd3 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit d4d94e61dead828a09525b27291686ab58b06e05 +Subproject commit cf2dbcffd37ddc8d8268e256bef94477c84cb636 diff --git a/include/nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl b/include/nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl index 2422c76b7b..5ef93e7abf 100644 --- a/include/nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl @@ -43,16 +43,16 @@ struct traits > // no blinn phong -template -struct traits > +template +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; }; -template -struct traits > +template +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; @@ -68,32 +68,32 @@ struct traits > NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; }; -template -struct traits > +template +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; }; -template -struct traits > +template +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; }; -template -struct traits > +template +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; }; -template -struct traits > +template +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 53484bdba8..56ea8e9c2e 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -262,23 +262,24 @@ NBL_CONCEPT_END( #undef aniso #include -template) +template) struct SAnisotropic { - using ray_dir_info_type = RayDirInfo; - using scalar_type = typename RayDirInfo::scalar_type; - using vector3_type = typename RayDirInfo::vector3_type; + using this_t = SAnisotropic; + using isotropic_interaction_type = IsotropicInteraction; + using ray_dir_info_type = typename isotropic_interaction_type::ray_dir_info_type; + using scalar_type = typename ray_dir_info_type::scalar_type; + using vector3_type = typename ray_dir_info_type::vector3_type; using matrix3x3_type = matrix; - using isotropic_interaction_type = SIsotropic; // WARNING: Changed since GLSL, now arguments need to be normalized! - static SAnisotropic create( + static this_t create( NBL_CONST_REF_ARG(isotropic_interaction_type) isotropic, NBL_CONST_REF_ARG(vector3_type) normalizedT, NBL_CONST_REF_ARG(vector3_type) normalizedB ) { - SAnisotropic retval; + this_t retval; retval.isotropic = isotropic; retval.T = normalizedT; @@ -289,24 +290,24 @@ struct SAnisotropic return retval; } - static SAnisotropic create(NBL_CONST_REF_ARG(isotropic_interaction_type) isotropic, NBL_CONST_REF_ARG(vector3_type) normalizedT) + static this_t create(NBL_CONST_REF_ARG(isotropic_interaction_type) isotropic, NBL_CONST_REF_ARG(vector3_type) normalizedT) { return create(isotropic, normalizedT, cross(isotropic.getN(), normalizedT)); } - static SAnisotropic create(NBL_CONST_REF_ARG(isotropic_interaction_type) isotropic) + static this_t create(NBL_CONST_REF_ARG(isotropic_interaction_type) isotropic) { vector3_type T, B; math::frisvad(isotropic.getN(), T, B); return create(isotropic, nbl::hlsl::normalize(T), nbl::hlsl::normalize(B)); } - static SAnisotropic create(NBL_CONST_REF_ARG(RayDirInfo) normalizedV, NBL_CONST_REF_ARG(vector3_type) normalizedN) + static this_t create(NBL_CONST_REF_ARG(ray_dir_info_type) normalizedV, NBL_CONST_REF_ARG(vector3_type) normalizedN) { isotropic_interaction_type isotropic = isotropic_interaction_type::create(normalizedV, normalizedN); return create(isotropic); } - RayDirInfo getV() NBL_CONST_MEMBER_FUNC { return isotropic.V; } + ray_dir_info_type getV() NBL_CONST_MEMBER_FUNC { return isotropic.V; } vector3_type getN() NBL_CONST_MEMBER_FUNC { return isotropic.N; } scalar_type getNdotV() NBL_CONST_MEMBER_FUNC { return isotropic.NdotV; } scalar_type getNdotV2() NBL_CONST_MEMBER_FUNC { return isotropic.NdotV2; } @@ -334,23 +335,20 @@ struct SAnisotropic #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) #define NBL_CONCEPT_TPLT_PRM_NAMES (T) #define NBL_CONCEPT_PARAM_0 (_sample, T) -#define NBL_CONCEPT_PARAM_1 (iso, typename T::isotropic_interaction_type) -#define NBL_CONCEPT_PARAM_2 (aniso, typename T::anisotropic_interaction_type) -#define NBL_CONCEPT_PARAM_3 (rdirinfo, typename T::ray_dir_info_type) -#define NBL_CONCEPT_PARAM_4 (pV, typename T::vector3_type) -#define NBL_CONCEPT_PARAM_5 (frame, typename T::matrix3x3_type) -#define NBL_CONCEPT_PARAM_6 (pVdotL, typename T::scalar_type) -NBL_CONCEPT_BEGIN(7) +#define NBL_CONCEPT_PARAM_1 (inter, surface_interactions::SIsotropic) +#define NBL_CONCEPT_PARAM_2 (rdirinfo, typename T::ray_dir_info_type) +#define NBL_CONCEPT_PARAM_3 (pV, typename T::vector3_type) +#define NBL_CONCEPT_PARAM_4 (frame, typename T::matrix3x3_type) +#define NBL_CONCEPT_PARAM_5 (pVdotL, typename T::scalar_type) +NBL_CONCEPT_BEGIN(6) #define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 -#define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 -#define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 -#define rdirinfo NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 -#define pV NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 -#define frame NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 -#define pVdotL NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 +#define inter NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 +#define rdirinfo NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +#define pV NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 +#define frame NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 +#define pVdotL NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::ray_dir_info_type)) - ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_interaction_type)) ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) ((NBL_CONCEPT_REQ_TYPE)(T::matrix3x3_type)) @@ -363,19 +361,15 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createFromTangentSpace(pV,rdirinfo,frame)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(rdirinfo,pVdotL,pV)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(rdirinfo,pVdotL,pV,pV,pV)), ::nbl::hlsl::is_same_v, T)) - //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create(pV,iso)), ::nbl::hlsl::is_same_v, T)) // NOTE: temporarily commented out due to dxc bug https://github.com/microsoft/DirectXShaderCompiler/issues/7154 - //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create(pV,aniso)), ::nbl::hlsl::is_same_v, T)) + // ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create >(pV,inter)), ::nbl::hlsl::is_same_v, T)) // NOTE: temporarily commented out due to dxc bug https://github.com/microsoft/DirectXShaderCompiler/issues/7154 ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getTangentSpaceL()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(ray_dir_info::Basic, typename T::ray_dir_info_type)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Isotropic, typename T::isotropic_interaction_type)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Anisotropic, typename T::anisotropic_interaction_type)) ); #undef pVdotL #undef frame #undef pV #undef rdirinfo -#undef aniso -#undef iso +#undef inter #undef _sample #include @@ -384,16 +378,13 @@ struct SLightSample { using this_t = SLightSample; using ray_dir_info_type = RayDirInfo; - using scalar_type = typename RayDirInfo::scalar_type; - using vector3_type = typename RayDirInfo::vector3_type; + using scalar_type = typename ray_dir_info_type::scalar_type; + using vector3_type = typename ray_dir_info_type::vector3_type; using matrix3x3_type = matrix; - using isotropic_interaction_type = surface_interactions::SIsotropic; - using anisotropic_interaction_type = surface_interactions::SAnisotropic; - static this_t createFromTangentSpace( NBL_CONST_REF_ARG(vector3_type) tangentSpaceV, - NBL_CONST_REF_ARG(RayDirInfo) tangentSpaceL, + NBL_CONST_REF_ARG(ray_dir_info_type) tangentSpaceL, NBL_CONST_REF_ARG(matrix3x3_type) tangentFrame ) { @@ -410,7 +401,7 @@ struct SLightSample return retval; } - static this_t create(NBL_CONST_REF_ARG(RayDirInfo) L, const scalar_type VdotL, NBL_CONST_REF_ARG(vector3_type) N) + static this_t create(NBL_CONST_REF_ARG(ray_dir_info_type) L, const scalar_type VdotL, NBL_CONST_REF_ARG(vector3_type) N) { this_t retval; @@ -424,7 +415,7 @@ struct SLightSample return retval; } - static this_t create(NBL_CONST_REF_ARG(RayDirInfo) L, const scalar_type VdotL, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N) + static this_t create(NBL_CONST_REF_ARG(ray_dir_info_type) L, const scalar_type VdotL, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N) { this_t retval = create(L,VdotL,N); @@ -452,7 +443,7 @@ struct SLightSample return vector3_type(TdotL, BdotL, NdotL); } - RayDirInfo getL() NBL_CONST_MEMBER_FUNC { return L; } + ray_dir_info_type getL() NBL_CONST_MEMBER_FUNC { return L; } scalar_type getVdotL() NBL_CONST_MEMBER_FUNC { return VdotL; } scalar_type getTdotL() NBL_CONST_MEMBER_FUNC { return TdotL; } scalar_type getBdotL() NBL_CONST_MEMBER_FUNC { return BdotL; } @@ -481,17 +472,13 @@ NBL_CONCEPT_BEGIN(3) #define pNdotV NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define b0 NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_TYPE)(T::ray_dir_info_type)) - ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_interaction_type)) ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) - ((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getVdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getLdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getNdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getNdotH2()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.isValidVNDFMicrofacet(b0,b0,pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, bool)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Isotropic, typename T::isotropic_interaction_type)) ); #undef b0 #undef pNdotV @@ -502,9 +489,9 @@ NBL_CONCEPT_END( #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) #define NBL_CONCEPT_TPLT_PRM_NAMES (T) #define NBL_CONCEPT_PARAM_0 (cache, T) -#define NBL_CONCEPT_PARAM_1 (iso, typename T::isotropic_interaction_type) +#define NBL_CONCEPT_PARAM_1 (iso, surface_interactions::SIsotropic >) #define NBL_CONCEPT_PARAM_2 (pNdotV, typename T::scalar_type) -#define NBL_CONCEPT_PARAM_3 (_sample, typename T::sample_type) +#define NBL_CONCEPT_PARAM_3 (_sample, SLightSample >) #define NBL_CONCEPT_PARAM_4 (V, typename T::vector3_type) #define NBL_CONCEPT_PARAM_5 (eta, fresnel::OrientedEtas) NBL_CONCEPT_BEGIN(6) @@ -517,9 +504,9 @@ NBL_CONCEPT_BEGIN(6) NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(pNdotV,pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(iso,_sample)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection >,SLightSample > >(iso,_sample)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V,V,eta,V)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create(iso,_sample,eta,V)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create >,SLightSample > >(iso,_sample,eta,V)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(ReadableIsotropicMicrofacetCache, T)) ); #undef eta @@ -538,10 +525,6 @@ struct SIsotropicMicrofacetCache using vector3_type = vector; using matrix3x3_type = matrix; - using ray_dir_info_type = ray_dir_info::SBasic; - using isotropic_interaction_type = surface_interactions::SIsotropic; - using sample_type = SLightSample; - // always valid because its specialized for the reflective case static this_t createForReflection(const scalar_type NdotV, const scalar_type NdotL, const scalar_type VdotL, NBL_REF_ARG(scalar_type) LplusV_rcpLen) { @@ -617,7 +600,12 @@ struct SIsotropicMicrofacetCache return NdotH >= 0.0 && !(is_bsdf && transmission && (VdotL > -hlsl::min(eta, rcp_eta))); } - scalar_type getVdotH() NBL_CONST_MEMBER_FUNC { return VdotH; } + scalar_type getVdotH() NBL_CONST_MEMBER_FUNC + { + assert(VdotH >= scalar_type(0.0)); + return VdotH; + } + scalar_type getLdotH() NBL_CONST_MEMBER_FUNC { return LdotH; } scalar_type getNdotH() NBL_CONST_MEMBER_FUNC { return NdotH; } scalar_type getNdotH2() NBL_CONST_MEMBER_FUNC { return NdotH2; } @@ -633,9 +621,9 @@ struct SIsotropicMicrofacetCache #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) #define NBL_CONCEPT_TPLT_PRM_NAMES (T) #define NBL_CONCEPT_PARAM_0 (cache, T) -#define NBL_CONCEPT_PARAM_1 (aniso, typename T::anisotropic_interaction_type) +#define NBL_CONCEPT_PARAM_1 (aniso, surface_interactions::SAnisotropic > >) #define NBL_CONCEPT_PARAM_2 (pNdotL, typename T::scalar_type) -#define NBL_CONCEPT_PARAM_3 (_sample, typename T::sample_type) +#define NBL_CONCEPT_PARAM_3 (_sample, SLightSample >) #define NBL_CONCEPT_PARAM_4 (V, typename T::vector3_type) #define NBL_CONCEPT_PARAM_5 (b0, bool) #define NBL_CONCEPT_PARAM_6 (eta, fresnel::OrientedEtas) @@ -648,20 +636,18 @@ NBL_CONCEPT_BEGIN(7) #define b0 NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 #define eta NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_TYPE)(T::ray_dir_info_type)) - ((NBL_CONCEPT_REQ_TYPE)(T::anisotropic_interaction_type)) ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) - ((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::isocache_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getTdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getBdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V,b0,pNdotL,pNdotL)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(V,V,pNdotL)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection(aniso,_sample)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection > >,SLightSample > >(aniso,_sample)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V,V,V,V,eta,V)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create(aniso,_sample,eta)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Anisotropic, typename T::anisotropic_interaction_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create > >,SLightSample > >(aniso,_sample,eta)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(CreatableIsotropicMicrofacetCache, typename T::isocache_type)) ); #undef eta #undef b0 @@ -672,20 +658,15 @@ NBL_CONCEPT_END( #undef cache #include -template ) +template) struct SAnisotropicMicrofacetCache { - using this_t = SAnisotropicMicrofacetCache; - using scalar_type = U; + using this_t = SAnisotropicMicrofacetCache; + using isocache_type = IsoCache; + using scalar_type = typename IsoCache::scalar_type; using vector3_type = vector; using matrix3x3_type = matrix; - using ray_dir_info_type = ray_dir_info::SBasic; - using anisotropic_interaction_type = surface_interactions::SAnisotropic; - using isocache_type = SIsotropicMicrofacetCache; - using isotropic_interaction_type = typename isocache_type::isotropic_interaction_type; - using sample_type = SLightSample; - // always valid by construction static this_t create(NBL_CONST_REF_ARG(vector3_type) tangentSpaceV, NBL_CONST_REF_ARG(vector3_type) tangentSpaceH) { @@ -723,7 +704,7 @@ struct SAnisotropicMicrofacetCache this_t retval; scalar_type LplusV_rcpLen; - retval.iso_cache = SIsotropicMicrofacetCache::createForReflection(tangentSpaceV.z, tangentSpaceL.z, VdotL, LplusV_rcpLen); + retval.iso_cache = isocache_type::createForReflection(tangentSpaceV.z, tangentSpaceL.z, VdotL, LplusV_rcpLen); retval.TdotH = (tangentSpaceV.x + tangentSpaceL.x) * LplusV_rcpLen; retval.BdotH = (tangentSpaceV.y + tangentSpaceL.y) * LplusV_rcpLen; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 839b5f4c43..00335ca112 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -17,10 +17,10 @@ namespace bxdf namespace reflection { -template && CreatableIsotropicMicrofacetCache && AnisotropicMicrofacetCache) +template && surface_interactions::Isotropic && surface_interactions::Anisotropic && CreatableIsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SBeckmannBxDF { - using this_t = SBeckmannBxDF; + using this_t = SBeckmannBxDF; using scalar_type = typename LS::scalar_type; using ray_dir_info_type = typename LS::ray_dir_info_type; using vector2_type = vector; @@ -28,8 +28,8 @@ struct SBeckmannBxDF using matrix2x3_type = matrix; using params_t = SBxDFParams; - using isotropic_interaction_type = typename IsoCache::isotropic_interaction_type; - using anisotropic_interaction_type = typename AnisoCache::anisotropic_interaction_type; + using isotropic_interaction_type = Iso; + using anisotropic_interaction_type = Aniso; using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index d3f8099676..e8c9d7263f 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -17,10 +17,10 @@ namespace bxdf namespace reflection { -template && CreatableIsotropicMicrofacetCache && AnisotropicMicrofacetCache) +template && surface_interactions::Isotropic && surface_interactions::Anisotropic && CreatableIsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SGGXBxDF { - using this_t = SGGXBxDF; + using this_t = SGGXBxDF; using scalar_type = typename LS::scalar_type; using ray_dir_info_type = typename LS::ray_dir_info_type; using vector2_type = vector; @@ -28,8 +28,8 @@ struct SGGXBxDF using matrix2x3_type = matrix; using params_t = SBxDFParams; - using isotropic_interaction_type = typename IsoCache::isotropic_interaction_type; - using anisotropic_interaction_type = typename AnisoCache::anisotropic_interaction_type; + using isotropic_interaction_type = Iso; + using anisotropic_interaction_type = Aniso; using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl index 20b6715241..f3f59577c7 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl @@ -17,7 +17,7 @@ namespace bxdf namespace reflection { -template && surface_interactions::Isotropic && surface_interactions::Anisotropic) +template && surface_interactions::Isotropic && surface_interactions::Anisotropic) struct SLambertianBxDF { using this_t = SLambertianBxDF; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl index 97a318edc4..16f20d42e1 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl @@ -17,7 +17,7 @@ namespace bxdf namespace reflection { -template && surface_interactions::Isotropic && surface_interactions::Anisotropic) +template && surface_interactions::Isotropic && surface_interactions::Anisotropic) struct SOrenNayarBxDF { using this_t = SOrenNayarBxDF; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 283215f591..84401c30b4 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -17,10 +17,10 @@ namespace bxdf namespace transmission { -template && CreatableIsotropicMicrofacetCache && AnisotropicMicrofacetCache) +template && surface_interactions::Isotropic && surface_interactions::Anisotropic && CreatableIsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SBeckmannDielectricBxDF { - using this_t = SBeckmannDielectricBxDF; + using this_t = SBeckmannDielectricBxDF; using scalar_type = typename LS::scalar_type; using ray_dir_info_type = typename LS::ray_dir_info_type; using vector2_type = vector; @@ -28,8 +28,8 @@ struct SBeckmannDielectricBxDF using matrix3x3_type = matrix; using params_t = SBxDFParams; - using isotropic_interaction_type = typename IsoCache::isotropic_interaction_type; - using anisotropic_interaction_type = typename AnisoCache::anisotropic_interaction_type; + using isotropic_interaction_type = Iso; + using anisotropic_interaction_type = Aniso; using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; @@ -75,11 +75,11 @@ struct SBeckmannDielectricBxDF const bool transmitted = VdotHLdotH < 0.0; spectral_type dummyior; - reflection::SBeckmannBxDF beckmann; + reflection::SBeckmannBxDF beckmann; if (params.is_aniso) - beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior, dummyior); + beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior, dummyior); else - beckmann = reflection::SBeckmannBxDF::create(A.x, dummyior, dummyior); + beckmann = reflection::SBeckmannBxDF::create(A.x, dummyior, dummyior); const scalar_type scalar_part = beckmann.__eval_DG_wo_clamps(params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = @@ -119,7 +119,7 @@ struct SBeckmannDielectricBxDF const vector3_type upperHemisphereV = orientedEta.backside ? -localV : localV; spectral_type dummyior; - reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior, dummyior); + reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior, dummyior); const vector3_type H = beckmann.__generate(upperHemisphereV, u.xy); return __generate_wo_clamps(localV, H, interaction.getFromTangentSpace(), u, orientedEta, rcpEta, cache); diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index e20564001c..41ec8f7beb 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -17,10 +17,10 @@ namespace bxdf namespace transmission { -template && CreatableIsotropicMicrofacetCache && AnisotropicMicrofacetCache) +template && surface_interactions::Isotropic && surface_interactions::Anisotropic && CreatableIsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SGGXDielectricBxDF { - using this_t = SGGXDielectricBxDF; + using this_t = SGGXDielectricBxDF; using scalar_type = typename LS::scalar_type; using ray_dir_info_type = typename LS::ray_dir_info_type; using vector2_type = vector; @@ -28,8 +28,8 @@ struct SGGXDielectricBxDF using matrix3x3_type = matrix; using params_t = SBxDFParams; - using isotropic_interaction_type = typename IsoCache::isotropic_interaction_type; - using anisotropic_interaction_type = typename AnisoCache::anisotropic_interaction_type; + using isotropic_interaction_type = Iso; + using anisotropic_interaction_type = Aniso; using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; @@ -79,13 +79,13 @@ struct SGGXDielectricBxDF if (params.is_aniso) { spectral_type dummyior; - reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, A.y, dummyior, dummyior); + reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, A.y, dummyior, dummyior); NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(params); } else { spectral_type dummyior; - reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, dummyior, dummyior); + reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, dummyior, dummyior); NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(params); } @@ -126,7 +126,7 @@ struct SGGXDielectricBxDF const vector3_type upperHemisphereV = orientedEta.backside ? -localV : localV; spectral_type dummyior; - reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, A.y, dummyior, dummyior); + reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, A.y, dummyior, dummyior); const vector3_type H = ggx.__generate(upperHemisphereV, u.xy); return __generate_wo_clamps(localV, H, interaction.getFromTangentSpace(), u, orientedEta, rcpEta, cache); diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl index 1eee08a486..b26daeae63 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl @@ -17,7 +17,7 @@ namespace bxdf namespace transmission { -template && surface_interactions::Isotropic && surface_interactions::Anisotropic) +template && surface_interactions::Isotropic && surface_interactions::Anisotropic) struct SLambertianBxDF { using this_t = SLambertianBxDF; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index d163148020..b44443ffbd 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -17,20 +17,20 @@ namespace bxdf namespace transmission { -template // NBL_FUNC_REQUIRES(Sample && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) // dxc won't let me put this in +template // NBL_FUNC_REQUIRES(Sample && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) // dxc won't let me put this in struct SSmoothDielectricBxDF; -template -struct SSmoothDielectricBxDF +template +struct SSmoothDielectricBxDF { - using this_t = SSmoothDielectricBxDF; + using this_t = SSmoothDielectricBxDF; using scalar_type = typename LS::scalar_type; using ray_dir_info_type = typename LS::ray_dir_info_type; using vector3_type = vector; using params_t = SBxDFParams; - using isotropic_interaction_type = typename IsoCache::isotropic_interaction_type; - using anisotropic_interaction_type = typename AnisoCache::anisotropic_interaction_type; + using isotropic_interaction_type = Iso; + using anisotropic_interaction_type = Aniso; using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; @@ -113,17 +113,17 @@ struct SSmoothDielectricBxDF scalar_type eta; }; -template -struct SSmoothDielectricBxDF +template +struct SSmoothDielectricBxDF { - using this_t = SSmoothDielectricBxDF; + using this_t = SSmoothDielectricBxDF; using scalar_type = typename LS::scalar_type; using ray_dir_info_type = typename LS::ray_dir_info_type; using vector3_type = vector; using params_t = SBxDFParams; - using isotropic_interaction_type = typename IsoCache::isotropic_interaction_type; - using anisotropic_interaction_type = typename AnisoCache::anisotropic_interaction_type; + using isotropic_interaction_type = Iso; + using anisotropic_interaction_type = Aniso; using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; From 927ef6834f4b9a9268fd2e3c0aeda31b09eb93a5 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 18 Apr 2025 16:58:27 +0700 Subject: [PATCH 105/188] make param struct per bxdf --- examples_tests | 2 +- include/nbl/builtin/hlsl/bxdf/common.hlsl | 190 -------------- .../hlsl/bxdf/reflection/beckmann.hlsl | 243 ++++++++++++----- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 247 +++++++++++++----- .../hlsl/bxdf/reflection/lambertian.hlsl | 96 ++++++- .../hlsl/bxdf/reflection/oren_nayar.hlsl | 97 ++++++- .../hlsl/bxdf/transmission/beckmann.hlsl | 231 ++++++++++++---- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 221 ++++++++++++---- .../hlsl/bxdf/transmission/lambertian.hlsl | 96 ++++++- .../bxdf/transmission/smooth_dielectric.hlsl | 142 +++++++++- .../hlsl/cpp_compat/impl/intrinsics_impl.hlsl | 19 ++ 11 files changed, 1109 insertions(+), 475 deletions(-) diff --git a/examples_tests b/examples_tests index cf2dbcffd3..c4a9602bf5 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit cf2dbcffd37ddc8d8268e256bef94477c84cb636 +Subproject commit c4a9602bf50dd7f4bb97582ce30440cdf706de53 diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 56ea8e9c2e..6f0e7c46c1 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -882,196 +882,6 @@ enum BxDFClampMode : uint16_t BCM_ABS }; -namespace impl -{ -// this is to substitute the lack of compile-time `if constexpr` on HLSL -template -struct __extract_aniso_vars; - -template -struct __extract_aniso_vars -{ - static __extract_aniso_vars create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) - { - __extract_aniso_vars retval; - retval.NdotV = interaction.getNdotV(); - retval.NdotV2 = interaction.getNdotV2(); - return retval; - } - - T NdotV; - T NdotV2; - T TdotL2; - T BdotL2; - T TdotV2; - T BdotV2; -}; - -template -struct __extract_aniso_vars -{ - static __extract_aniso_vars create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) - { - __extract_aniso_vars retval; - retval.NdotV = interaction.isotropic.getNdotV(); - retval.NdotV2 = interaction.isotropic.getNdotV2(); - const T TdotL = _sample.getTdotL(); - const T BdotL = _sample.getBdotL(); - retval.TdotL2 = TdotL * TdotL; - retval.BdotL2 = BdotL * BdotL; - const T TdotV = interaction.getTdotV(); - const T BdotV = interaction.getBdotV(); - retval.TdotV2 = TdotV * TdotV; - retval.BdotV2 = BdotV * BdotV; - return retval; - } - - T NdotV; - T NdotV2; - T TdotL2; - T BdotL2; - T TdotV2; - T BdotV2; -}; - -template -struct __extract_aniso_vars2; - -template -struct __extract_aniso_vars2 -{ - static __extract_aniso_vars2 create(NBL_CONST_REF_ARG(Cache) cache) - { - __extract_aniso_vars2 retval; - retval.NdotH = cache.getNdotH(); - retval.NdotH2 = cache.getNdotH2(); - retval.VdotH = cache.getVdotH(); - retval.LdotH = cache.getLdotH(); - return retval; - } - - T NdotH; - T NdotH2; - T VdotH; - T LdotH; - T TdotH2; - T BdotH2; -}; - -template -struct __extract_aniso_vars2 -{ - static __extract_aniso_vars2 create(NBL_CONST_REF_ARG(Cache) cache) - { - __extract_aniso_vars2 retval; - retval.NdotH = cache.iso_cache.getNdotH(); - retval.NdotH2 = cache.iso_cache.getNdotH2(); - retval.VdotH = cache.iso_cache.getVdotH(); - retval.LdotH = cache.iso_cache.getLdotH(); - const T TdotH = cache.getTdotH(); - const T BdotH = cache.getBdotH(); - retval.TdotH2 = TdotH * TdotH; - retval.BdotH2 = BdotH * BdotH; - return retval; - } - - T NdotH; - T NdotH2; - T VdotH; - T LdotH; - T TdotH2; - T BdotH2; -}; -} - -// unified param struct for calls to BxDF::eval, BxDF::pdf, BxDF::quotient_and_pdf -template) -struct SBxDFParams -{ - using this_t = SBxDFParams; - - template && (surface_interactions::Isotropic || surface_interactions::Anisotropic)) // maybe put template in struct vs function? - static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, BxDFClampMode _clamp) - { - impl::__extract_aniso_vars > vars = impl::__extract_aniso_vars >::create(_sample, interaction); - - this_t retval; - retval.NdotV = math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, vars.NdotV, 0.0); - retval.uNdotV = vars.NdotV; - retval.NdotV2 = vars.NdotV2; - retval.uNdotL = _sample.getNdotL(); - retval.NdotL = math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, retval.uNdotL, 0.0); - retval.NdotL2 = _sample.getNdotL2(); - retval.VdotL = _sample.getVdotL(); - - retval.is_aniso = surface_interactions::Anisotropic; - retval.TdotL2 = vars.TdotL2; - retval.BdotL2 = vars.BdotL2; - retval.TdotV2 = vars.TdotV2; - retval.BdotV2 = vars.BdotV2; - return retval; - } - - template && (surface_interactions::Isotropic || surface_interactions::Anisotropic) && (CreatableIsotropicMicrofacetCache || AnisotropicMicrofacetCache)) - static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(Cache) cache, BxDFClampMode _clamp) - { - impl::__extract_aniso_vars > vars = impl::__extract_aniso_vars >::create(_sample, interaction); - impl::__extract_aniso_vars2 > vars2 = impl::__extract_aniso_vars2 >::create(cache); - - this_t retval; - retval.NdotH = vars2.NdotH; - retval.NdotH2 = vars2.NdotH2; - retval.NdotV = math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, vars.NdotV, 0.0); - retval.uNdotV = vars.NdotV; - retval.NdotV2 = vars.NdotV2; - retval.uNdotL = _sample.getNdotL(); - retval.NdotL = math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, retval.uNdotL, 0.0); - retval.NdotL2 = _sample.getNdotL2(); - retval.VdotL = _sample.getVdotL(); - retval.VdotH = vars2.VdotH; - retval.LdotH = vars2.LdotH; - - retval.is_aniso = surface_interactions::Anisotropic; - retval.TdotL2 = vars.TdotL2; - retval.BdotL2 = vars.BdotL2; - retval.TdotV2 = vars.TdotV2; - retval.BdotV2 = vars.BdotV2; - retval.TdotH2 = vars2.TdotH2; - retval.BdotH2 = vars2.BdotH2; - return retval; - } - - Scalar getMaxNdotV() { return max(uNdotV, 0.0); } - Scalar getAbsNdotV() { return abs(uNdotV); } - - Scalar getMaxNdotL() { return max(uNdotL, 0.0); } - Scalar getAbsNdotL() { return abs(uNdotL); } - - // iso - Scalar NdotH; - Scalar NdotH2; - Scalar NdotV; - Scalar NdotV2; - Scalar NdotL; - Scalar NdotL2; - Scalar VdotH; - Scalar LdotH; - Scalar VdotL; - - // aniso - bool is_aniso; - Scalar TdotH2; - Scalar BdotH2; - Scalar TdotL2; - Scalar BdotL2; - Scalar TdotV2; - Scalar BdotV2; - - // original, unclamped - Scalar uNdotL; - Scalar uNdotV; -}; - // unified param struct for calls to BxDF::create template) struct SBxDFCreationParams diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 00335ca112..f5f272c9dd 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -17,6 +17,86 @@ namespace bxdf namespace reflection { +template +struct BeckmannParams; + +template +NBL_PARTIAL_REQ_TOP(!surface_interactions::Anisotropic && !AnisotropicMicrofacetCache) +struct BeckmannParams && !AnisotropicMicrofacetCache) > +{ + using this_t = BeckmannParams; + + static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, NBL_CONST_REF_ARG(MC) cache, BxDFClampMode _clamp) + { + this_t retval; + retval._sample = _sample; + retval.interaction = interaction; + retval.cache = cache; + retval._clamp = _clamp; + return retval; + } + + // iso + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } + Scalar getNdotH2() NBL_CONST_MEMBER_FUNC { return cache.getNdotH2(); } + Scalar getVdotH() NBL_CONST_MEMBER_FUNC { return cache.getVdotH(); } + Scalar getLdotH() NBL_CONST_MEMBER_FUNC { return cache.getLdotH(); } + + LS _sample; + SI interaction; + MC cache; + BxDFClampMode _clamp; +}; +template +NBL_PARTIAL_REQ_TOP(surface_interactions::Anisotropic && AnisotropicMicrofacetCache) +struct BeckmannParams && AnisotropicMicrofacetCache) > +{ + using this_t = BeckmannParams; + + static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, NBL_CONST_REF_ARG(MC) cache, BxDFClampMode _clamp) + { + this_t retval; + retval._sample = _sample; + retval.interaction = interaction; + retval.cache = cache; + retval._clamp = _clamp; + return retval; + } + + // iso + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } + Scalar getNdotH2() NBL_CONST_MEMBER_FUNC { return cache.getNdotH2(); } + Scalar getVdotH() NBL_CONST_MEMBER_FUNC { return cache.getVdotH(); } + Scalar getLdotH() NBL_CONST_MEMBER_FUNC { return cache.getLdotH(); } + + // aniso + Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL() * _sample.getTdotL(); } + Scalar getBdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getBdotL() * _sample.getBdotL(); } + Scalar getTdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getTdotV() * interaction.getTdotV(); } + Scalar getBdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getBdotV() * interaction.getBdotV(); } + Scalar getTdotH2() NBL_CONST_MEMBER_FUNC {return cache.getTdotH() * cache.getTdotH(); } + Scalar getBdotH2() NBL_CONST_MEMBER_FUNC {return cache.getBdotH() * cache.getBdotH(); } + + LS _sample; + SI interaction; + MC cache; + BxDFClampMode _clamp; +}; + template && surface_interactions::Isotropic && surface_interactions::Anisotropic && CreatableIsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SBeckmannBxDF { @@ -25,8 +105,6 @@ struct SBeckmannBxDF using ray_dir_info_type = typename LS::ray_dir_info_type; using vector2_type = vector; using vector3_type = vector; - using matrix2x3_type = matrix; - using params_t = SBxDFParams; using isotropic_interaction_type = Iso; using anisotropic_interaction_type = Aniso; @@ -36,6 +114,10 @@ struct SBeckmannBxDF using isocache_type = IsoCache; using anisocache_type = AnisoCache; + using params_isotropic_t = BeckmannParams; + using params_anisotropic_t = BeckmannParams; + + // iso static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) { @@ -71,46 +153,55 @@ struct SBeckmannBxDF ior1 = params.ior1; } - scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_t) params) + scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_isotropic_t) params) { - if (params.is_aniso) + scalar_type a2 = A.x*A.x; + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.getNdotH(), params.getNdotH2()); + ndf::Beckmann beckmann_ndf; + scalar_type NG = beckmann_ndf(ndfparams); + if (a2 > numeric_limits::min) { - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); - ndf::Beckmann beckmann_ndf; - scalar_type NG = beckmann_ndf(ndfparams); - if (any >(A > (vector2_type)numeric_limits::min)) - { - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, 0); - smith::Beckmann beckmann_smith; - NG *= beckmann_smith.correlated(smithparams); - } - return NG; + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.getNdotV2(), params.getNdotL2(), 0); + smith::Beckmann beckmann_smith; + NG *= beckmann_smith.correlated(smithparams); } - else + return NG; + } + scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_anisotropic_t) params) + { + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); + ndf::Beckmann beckmann_ndf; + scalar_type NG = beckmann_ndf(ndfparams); + if (any >(A > (vector2_type)numeric_limits::min)) { - scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); - ndf::Beckmann beckmann_ndf; - scalar_type NG = beckmann_ndf(ndfparams); - if (a2 > numeric_limits::min) - { - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.NdotV2, params.NdotL2, 0); - smith::Beckmann beckmann_smith; - NG *= beckmann_smith.correlated(smithparams); - } - return NG; + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2(), 0); + smith::Beckmann beckmann_smith; + NG *= beckmann_smith.correlated(smithparams); } + return NG; } - spectral_type eval(params_t params) + spectral_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) { - if (params.uNdotV > numeric_limits::min) + if (params.getNdotVUnclamped() > numeric_limits::min) { scalar_type scalar_part = __eval_DG_wo_clamps(params); - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.uNdotV); - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.VdotH); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.getNdotVUnclamped()); + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); + return f() * microfacet_transform(); + } + else + return (spectral_type)0.0; + } + spectral_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) + { + if (params.getNdotVUnclamped() > numeric_limits::min) + { + scalar_type scalar_part = __eval_DG_wo_clamps(params); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.getNdotVUnclamped()); + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); return f() * microfacet_transform(); } else @@ -206,64 +297,82 @@ struct SBeckmannBxDF return s; } - scalar_type pdf(NBL_CONST_REF_ARG(params_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) + scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { scalar_type ndf, lambda; - if (params.is_aniso) - { - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, A.x*A.x, A.y*A.y, params.TdotH2, params.BdotH2, params.NdotH2); - ndf::Beckmann beckmann_ndf; - ndf = beckmann_ndf(ndfparams); + scalar_type a2 = A.x*A.x; + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.getNdotH(), params.getNdotH2()); + ndf::Beckmann beckmann_ndf; + ndf = beckmann_ndf(ndfparams); - smith::Beckmann beckmann_smith; - const scalar_type c2 = beckmann_smith.C2(params.TdotV2, params.BdotV2, params.NdotV2, A.x, A.y); - lambda = beckmann_smith.Lambda(c2); - } - else - { - scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); - ndf::Beckmann beckmann_ndf; - ndf = beckmann_ndf(ndfparams); + smith::Beckmann beckmann_smith; + lambda = beckmann_smith.Lambda(params.getNdotV2(), a2); - smith::Beckmann beckmann_smith; - lambda = beckmann_smith.Lambda(params.NdotV2, a2); - } + smith::brdf::VNDF_pdf > vndf = smith::brdf::VNDF_pdf >::create(ndf, params.getNdotVUnclamped()); + scalar_type _pdf = vndf(lambda); + onePlusLambda_V = vndf.onePlusLambda_V; + + return _pdf; + } + scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) + { + scalar_type ndf, lambda; + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, A.x*A.x, A.y*A.y, params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); + ndf::Beckmann beckmann_ndf; + ndf = beckmann_ndf(ndfparams); - smith::brdf::VNDF_pdf > vndf = smith::brdf::VNDF_pdf >::create(ndf, params.uNdotV); + smith::Beckmann beckmann_smith; + const scalar_type c2 = beckmann_smith.C2(params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), A.x, A.y); + lambda = beckmann_smith.Lambda(c2); + + smith::brdf::VNDF_pdf > vndf = smith::brdf::VNDF_pdf >::create(ndf, params.getNdotVUnclamped()); scalar_type _pdf = vndf(lambda); onePlusLambda_V = vndf.onePlusLambda_V; return _pdf; } - scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) + scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + { + scalar_type dummy; + return pdf(params, dummy); + } + scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { scalar_type dummy; return pdf(params, dummy); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) { scalar_type onePlusLambda_V; scalar_type _pdf = pdf(params, onePlusLambda_V); smith::Beckmann beckmann_smith; spectral_type quo = (spectral_type)0.0; - if (params.uNdotL > numeric_limits::min && params.uNdotV > numeric_limits::min) + if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) { - scalar_type G2_over_G1; - if (params.is_aniso) - { - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(A.x*A.x, A.y*A.y, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, onePlusLambda_V); - G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); - } - else - { - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(A.x*A.x, params.NdotV2, params.NdotL2, onePlusLambda_V); - G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); - } - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.VdotH); + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(A.x*A.x, params.getNdotV2(), params.getNdotL2(), onePlusLambda_V); + scalar_type G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); + const spectral_type reflectance = f(); + quo = reflectance * G2_over_G1; + } + + return quotient_pdf_type::create(quo, _pdf); + } + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) + { + scalar_type onePlusLambda_V; + scalar_type _pdf = pdf(params, onePlusLambda_V); + + smith::Beckmann beckmann_smith; + spectral_type quo = (spectral_type)0.0; + if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) + { + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(A.x*A.x, A.y*A.y, params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2(), onePlusLambda_V); + scalar_type G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index e8c9d7263f..601ed78eb9 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -17,6 +17,86 @@ namespace bxdf namespace reflection { +template +struct GGXParams; + +template +NBL_PARTIAL_REQ_TOP(!surface_interactions::Anisotropic && !AnisotropicMicrofacetCache) +struct GGXParams && !AnisotropicMicrofacetCache) > +{ + using this_t = GGXParams; + + static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, NBL_CONST_REF_ARG(MC) cache, BxDFClampMode _clamp) + { + this_t retval; + retval._sample = _sample; + retval.interaction = interaction; + retval.cache = cache; + retval._clamp = _clamp; + return retval; + } + + // iso + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } + Scalar getNdotH2() NBL_CONST_MEMBER_FUNC { return cache.getNdotH2(); } + Scalar getVdotH() NBL_CONST_MEMBER_FUNC { return cache.getVdotH(); } + Scalar getLdotH() NBL_CONST_MEMBER_FUNC { return cache.getLdotH(); } + + LS _sample; + SI interaction; + MC cache; + BxDFClampMode _clamp; +}; +template +NBL_PARTIAL_REQ_TOP(surface_interactions::Anisotropic && AnisotropicMicrofacetCache) +struct GGXParams && AnisotropicMicrofacetCache) > +{ + using this_t = GGXParams; + + static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, NBL_CONST_REF_ARG(MC) cache, BxDFClampMode _clamp) + { + this_t retval; + retval._sample = _sample; + retval.interaction = interaction; + retval.cache = cache; + retval._clamp = _clamp; + return retval; + } + + // iso + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } + Scalar getNdotH2() NBL_CONST_MEMBER_FUNC { return cache.getNdotH2(); } + Scalar getVdotH() NBL_CONST_MEMBER_FUNC { return cache.getVdotH(); } + Scalar getLdotH() NBL_CONST_MEMBER_FUNC { return cache.getLdotH(); } + + // aniso + Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL() * _sample.getTdotL(); } + Scalar getBdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getBdotL() * _sample.getBdotL(); } + Scalar getTdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getTdotV() * interaction.getTdotV(); } + Scalar getBdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getBdotV() * interaction.getBdotV(); } + Scalar getTdotH2() NBL_CONST_MEMBER_FUNC {return cache.getTdotH() * cache.getTdotH(); } + Scalar getBdotH2() NBL_CONST_MEMBER_FUNC {return cache.getBdotH() * cache.getBdotH(); } + + LS _sample; + SI interaction; + MC cache; + BxDFClampMode _clamp; +}; + template && surface_interactions::Isotropic && surface_interactions::Anisotropic && CreatableIsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SGGXBxDF { @@ -26,7 +106,6 @@ struct SGGXBxDF using vector2_type = vector; using vector3_type = vector; using matrix2x3_type = matrix; - using params_t = SBxDFParams; using isotropic_interaction_type = Iso; using anisotropic_interaction_type = Aniso; @@ -36,6 +115,10 @@ struct SGGXBxDF using isocache_type = IsoCache; using anisocache_type = AnisoCache; + using params_isotropic_t = GGXParams; + using params_anisotropic_t = GGXParams; + + // iso static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) { @@ -71,46 +154,55 @@ struct SGGXBxDF ior1 = params.ior1; } - scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_t) params) + scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_isotropic_t) params) { - if (params.is_aniso) + scalar_type a2 = A.x*A.x; + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.getNdotH(), params.getNdotH2()); + ndf::GGX ggx_ndf; + scalar_type NG = ggx_ndf(ndfparams); + if (a2 > numeric_limits::min) { - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); - ndf::GGX ggx_ndf; - scalar_type NG = ggx_ndf(ndfparams); - if (any >(A > (vector2_type)numeric_limits::min)) - { - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2); - smith::GGX ggx_smith; - NG *= ggx_smith.correlated_wo_numerator(smithparams); - } - return NG; + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.getNdotV(), params.getNdotV2(), params.getNdotL(), params.getNdotL2()); + smith::GGX ggx_smith; + NG *= ggx_smith.correlated_wo_numerator(smithparams); } - else + return NG; + } + scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_anisotropic_t) params) + { + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); + ndf::GGX ggx_ndf; + scalar_type NG = ggx_ndf(ndfparams); + if (any >(A > (vector2_type)numeric_limits::min)) { - scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); - ndf::GGX ggx_ndf; - scalar_type NG = ggx_ndf(ndfparams); - if (a2 > numeric_limits::min) - { - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.NdotV, params.NdotV2, params.NdotL, params.NdotL2); - smith::GGX ggx_smith; - NG *= ggx_smith.correlated_wo_numerator(smithparams); - } - return NG; + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.getNdotV(), params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getNdotL(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); + smith::GGX ggx_smith; + NG *= ggx_smith.correlated_wo_numerator(smithparams); } + return NG; } - spectral_type eval(NBL_CONST_REF_ARG(params_t) params) + spectral_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) { - if (params.uNdotL > numeric_limits::min && params.uNdotV > numeric_limits::min) + if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) { scalar_type scalar_part = __eval_DG_wo_clamps(params); - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.NdotL); - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.VdotH); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.getNdotL()); + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); + return f() * microfacet_transform(); + } + else + return (spectral_type)0.0; + } + spectral_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) + { + if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) + { + scalar_type scalar_part = __eval_DG_wo_clamps(params); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.getNdotL()); + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); return f() * microfacet_transform(); } else @@ -160,60 +252,75 @@ struct SGGXBxDF return s; } - scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) + scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) { scalar_type ndf, G1_over_2NdotV; - if (params.is_aniso) - { - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); - ndf::GGX ggx_ndf; - ndf = ggx_ndf(ndfparams); + const scalar_type a2 = A.x*A.x; + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.getNdotH(), params.getNdotH2()); + ndf::GGX ggx_ndf; + ndf = ggx_ndf(ndfparams); - smith::GGX ggx_smith; - const scalar_type devsh_v = ggx_smith.devsh_part(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); - G1_over_2NdotV = ggx_smith.G1_wo_numerator(params.uNdotV, devsh_v); - } - else - { - const scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); - ndf::GGX ggx_ndf; - ndf = ggx_ndf(ndfparams); + smith::GGX ggx_smith; + const scalar_type devsh_v = ggx_smith.devsh_part(params.getNdotV2(), a2, 1.0-a2); + G1_over_2NdotV = ggx_smith.G1_wo_numerator(params.getNdotVUnclamped(), devsh_v); - smith::GGX ggx_smith; - const scalar_type devsh_v = ggx_smith.devsh_part(params.NdotV2, a2, 1.0-a2); - G1_over_2NdotV = ggx_smith.G1_wo_numerator(params.uNdotV, devsh_v); - } + smith::brdf::VNDF_pdf > vndf = smith::brdf::VNDF_pdf >::create(ndf, params.getNdotVUnclamped()); + return vndf(G1_over_2NdotV); + } + scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) + { + scalar_type ndf, G1_over_2NdotV; + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); + ndf::GGX ggx_ndf; + ndf = ggx_ndf(ndfparams); + + smith::GGX ggx_smith; + const scalar_type devsh_v = ggx_smith.devsh_part(params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), ax2, ay2); + G1_over_2NdotV = ggx_smith.G1_wo_numerator(params.getNdotVUnclamped(), devsh_v); - smith::brdf::VNDF_pdf > vndf = smith::brdf::VNDF_pdf >::create(ndf, params.uNdotV); + smith::brdf::VNDF_pdf > vndf = smith::brdf::VNDF_pdf >::create(ndf, params.getNdotVUnclamped()); return vndf(G1_over_2NdotV); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) { scalar_type _pdf = pdf(params); spectral_type quo = (spectral_type)0.0; - if (params.uNdotL > numeric_limits::min && params.uNdotV > numeric_limits::min) + if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) { scalar_type G2_over_G1; smith::GGX ggx_smith; - if (params.is_aniso) - { - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.uNdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.uNdotL, params.TdotL2, params.BdotL2, params.NdotL2); - G2_over_G1 = ggx_smith.G2_over_G1(smithparams); - } - else - { - const scalar_type a2 = A.x*A.x; - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.uNdotV, params.NdotV2, params.uNdotL, params.NdotL2); - G2_over_G1 = ggx_smith.G2_over_G1(smithparams); - } - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.VdotH); + + const scalar_type a2 = A.x*A.x; + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.getNdotVUnclamped(), params.getNdotV2(), params.getNdotLUnclamped(), params.getNdotL2()); + G2_over_G1 = ggx_smith.G2_over_G1(smithparams); + + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); + const spectral_type reflectance = f(); + quo = reflectance * G2_over_G1; + } + + return quotient_pdf_type::create(quo, _pdf); + } + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) + { + scalar_type _pdf = pdf(params); + + spectral_type quo = (spectral_type)0.0; + if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) + { + scalar_type G2_over_G1; + smith::GGX ggx_smith; + + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.getNdotVUnclamped(), params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getNdotLUnclamped(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); + G2_over_G1 = ggx_smith.G2_over_G1(smithparams); + + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl index f3f59577c7..394a7e677f 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl @@ -17,6 +17,72 @@ namespace bxdf namespace reflection { +template +struct LambertianParams; + +template +NBL_PARTIAL_REQ_TOP(!surface_interactions::Anisotropic) +struct LambertianParams) > +{ + using this_t = LambertianParams; + + static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, BxDFClampMode _clamp) + { + this_t retval; + retval._sample = _sample; + retval.interaction = interaction; + retval._clamp = _clamp; + return retval; + } + + // iso + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + + LS _sample; + SI interaction; + BxDFClampMode _clamp; +}; +template +NBL_PARTIAL_REQ_TOP(surface_interactions::Anisotropic) +struct LambertianParams) > +{ + using this_t = LambertianParams; + + static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, BxDFClampMode _clamp) + { + this_t retval; + retval._sample = _sample; + retval.interaction = interaction; + retval._clamp = _clamp; + return retval; + } + + // iso + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + + // aniso + Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL() * _sample.getTdotL(); } + Scalar getBdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getBdotL() * _sample.getBdotL(); } + Scalar getTdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getTdotV() * interaction.getTdotV(); } + Scalar getBdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getBdotV() * interaction.getBdotV(); } + + LS _sample; + SI interaction; + BxDFClampMode _clamp; +}; + template && surface_interactions::Isotropic && surface_interactions::Anisotropic) struct SLambertianBxDF { @@ -28,7 +94,10 @@ struct SLambertianBxDF using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; - using params_t = SBxDFParams; + + using params_isotropic_t = LambertianParams; + using params_anisotropic_t = LambertianParams; + static this_t create() { @@ -52,9 +121,13 @@ struct SLambertianBxDF return maxNdotL; } - scalar_type eval(NBL_CONST_REF_ARG(params_t) params) + scalar_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) { - return __eval_pi_factored_out(params.NdotL) * numbers::inv_pi; + return __eval_pi_factored_out(params.getNdotL()) * numbers::inv_pi; + } + scalar_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) + { + return __eval_pi_factored_out(params.getNdotL()) * numbers::inv_pi; } sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector) u) @@ -74,14 +147,23 @@ struct SLambertianBxDF return generate_wo_clamps(anisotropic_interaction_type::create(interaction), u); } - scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) + scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + { + return sampling::ProjectedHemisphere::pdf(params.getNdotL()); + } + scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { - return sampling::ProjectedHemisphere::pdf(params.NdotL); + return sampling::ProjectedHemisphere::pdf(params.getNdotL()); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + { + sampling::quotient_and_pdf qp = sampling::ProjectedHemisphere::template quotient_and_pdf(params.getNdotL()); + return quotient_pdf_type::create(hlsl::promote(qp.quotient), qp.pdf); + } + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { - sampling::quotient_and_pdf qp = sampling::ProjectedHemisphere::template quotient_and_pdf(params.NdotL); + sampling::quotient_and_pdf qp = sampling::ProjectedHemisphere::template quotient_and_pdf(params.getNdotL()); return quotient_pdf_type::create(hlsl::promote(qp.quotient), qp.pdf); } }; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl index 16f20d42e1..281f3f12e1 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl @@ -17,6 +17,72 @@ namespace bxdf namespace reflection { +template +struct OrenNayarParams; + +template +NBL_PARTIAL_REQ_TOP(!surface_interactions::Anisotropic) +struct OrenNayarParams) > +{ + using this_t = OrenNayarParams; + + static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, BxDFClampMode _clamp) + { + this_t retval; + retval._sample = _sample; + retval.interaction = interaction; + retval._clamp = _clamp; + return retval; + } + + // iso + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + + LS _sample; + SI interaction; + BxDFClampMode _clamp; +}; +template +NBL_PARTIAL_REQ_TOP(surface_interactions::Anisotropic) +struct OrenNayarParams) > +{ + using this_t = OrenNayarParams; + + static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, BxDFClampMode _clamp) + { + this_t retval; + retval._sample = _sample; + retval.interaction = interaction; + retval._clamp = _clamp; + return retval; + } + + // iso + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + + // aniso + Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL() * _sample.getTdotL(); } + Scalar getBdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getBdotL() * _sample.getBdotL(); } + Scalar getTdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getTdotV() * interaction.getTdotV(); } + Scalar getBdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getBdotV() * interaction.getBdotV(); } + + LS _sample; + SI interaction; + BxDFClampMode _clamp; +}; + template && surface_interactions::Isotropic && surface_interactions::Anisotropic) struct SOrenNayarBxDF { @@ -30,7 +96,10 @@ struct SOrenNayarBxDF using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; - using params_t = SBxDFParams; + + using params_isotropic_t = OrenNayarParams; + using params_anisotropic_t = OrenNayarParams; + static this_t create(scalar_type A) { @@ -59,9 +128,13 @@ struct SOrenNayarBxDF return (AB.x + AB.y * cos_phi_sin_theta * C); } - scalar_type eval(NBL_CONST_REF_ARG(params_t) params) + scalar_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) + { + return params.getNdotL() * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(params.getVdotL(), params.getNdotL(), params.getNdotV()); + } + scalar_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) { - return params.NdotL * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(params.VdotL, params.NdotL, params.NdotV); + return params.getNdotL() * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(params.getVdotL(), params.getNdotL(), params.getNdotV()); } sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector2_type) u) @@ -81,15 +154,25 @@ struct SOrenNayarBxDF return generate_wo_clamps(anisotropic_interaction_type::create(interaction), u); } - scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) + scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) { - return sampling::ProjectedHemisphere::pdf(params.NdotL); + return sampling::ProjectedHemisphere::pdf(params.getNdotL()); + } + scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) + { + return sampling::ProjectedHemisphere::pdf(params.getNdotL()); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + { + scalar_type _pdf = pdf(params); + scalar_type q = __rec_pi_factored_out_wo_clamps(params.getVdotL(), params.getNdotL(), params.getNdotV()); + return quotient_pdf_type::create(hlsl::promote(q), _pdf); + } + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { scalar_type _pdf = pdf(params); - scalar_type q = __rec_pi_factored_out_wo_clamps(params.VdotL, params.NdotL, params.NdotV); + scalar_type q = __rec_pi_factored_out_wo_clamps(params.getVdotL(), params.getNdotL(), params.getNdotV()); return quotient_pdf_type::create(hlsl::promote(q), _pdf); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 84401c30b4..652e69e459 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -17,6 +17,86 @@ namespace bxdf namespace transmission { +template +struct BeckmannParams; + +template +NBL_PARTIAL_REQ_TOP(!surface_interactions::Anisotropic && !AnisotropicMicrofacetCache) +struct BeckmannParams && !AnisotropicMicrofacetCache) > +{ + using this_t = BeckmannParams; + + static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, NBL_CONST_REF_ARG(MC) cache, BxDFClampMode _clamp) + { + this_t retval; + retval._sample = _sample; + retval.interaction = interaction; + retval.cache = cache; + retval._clamp = _clamp; + return retval; + } + + // iso + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } + Scalar getNdotH2() NBL_CONST_MEMBER_FUNC { return cache.getNdotH2(); } + Scalar getVdotH() NBL_CONST_MEMBER_FUNC { return cache.getVdotH(); } + Scalar getLdotH() NBL_CONST_MEMBER_FUNC { return cache.getLdotH(); } + + LS _sample; + SI interaction; + MC cache; + BxDFClampMode _clamp; +}; +template +NBL_PARTIAL_REQ_TOP(surface_interactions::Anisotropic && AnisotropicMicrofacetCache) +struct BeckmannParams && AnisotropicMicrofacetCache) > +{ + using this_t = BeckmannParams; + + static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, NBL_CONST_REF_ARG(MC) cache, BxDFClampMode _clamp) + { + this_t retval; + retval._sample = _sample; + retval.interaction = interaction; + retval.cache = cache; + retval._clamp = _clamp; + return retval; + } + + // iso + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } + Scalar getNdotH2() NBL_CONST_MEMBER_FUNC { return cache.getNdotH2(); } + Scalar getVdotH() NBL_CONST_MEMBER_FUNC { return cache.getVdotH(); } + Scalar getLdotH() NBL_CONST_MEMBER_FUNC { return cache.getLdotH(); } + + // aniso + Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL() * _sample.getTdotL(); } + Scalar getBdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getBdotL() * _sample.getBdotL(); } + Scalar getTdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getTdotV() * interaction.getTdotV(); } + Scalar getBdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getBdotV() * interaction.getBdotV(); } + Scalar getTdotH2() NBL_CONST_MEMBER_FUNC {return cache.getTdotH() * cache.getTdotH(); } + Scalar getBdotH2() NBL_CONST_MEMBER_FUNC {return cache.getBdotH() * cache.getBdotH(); } + + LS _sample; + SI interaction; + MC cache; + BxDFClampMode _clamp; +}; + template && surface_interactions::Isotropic && surface_interactions::Anisotropic && CreatableIsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SBeckmannDielectricBxDF { @@ -26,7 +106,6 @@ struct SBeckmannDielectricBxDF using vector2_type = vector; using vector3_type = vector; using matrix3x3_type = matrix; - using params_t = SBxDFParams; using isotropic_interaction_type = Iso; using anisotropic_interaction_type = Aniso; @@ -35,6 +114,11 @@ struct SBeckmannDielectricBxDF using quotient_pdf_type = sampling::quotient_and_pdf; using isocache_type = IsoCache; using anisocache_type = AnisoCache; + using brdf_type = reflection::SBeckmannBxDF; + + using params_isotropic_t = BeckmannParams; + using params_anisotropic_t = BeckmannParams; + static this_t create(scalar_type eta, scalar_type A) { @@ -66,25 +150,40 @@ struct SBeckmannDielectricBxDF eta = params.eta; } - spectral_type eval(NBL_CONST_REF_ARG(params_t) params) + spectral_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.VdotH, eta); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), eta); const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; - const scalar_type VdotHLdotH = params.VdotH * params.LdotH; + const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); const bool transmitted = VdotHLdotH < 0.0; spectral_type dummyior; - reflection::SBeckmannBxDF beckmann; - if (params.is_aniso) - beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior, dummyior); - else - beckmann = reflection::SBeckmannBxDF::create(A.x, dummyior, dummyior); - const scalar_type scalar_part = beckmann.__eval_DG_wo_clamps(params); + brdf_type beckmann = brdf_type::create(A.x, dummyior, dummyior); + typename brdf_type::params_isotropic_t brdf_params = typename brdf_type::params_isotropic_t::create(params._sample, params.interaction, params.cache, params._clamp); + const scalar_type scalar_part = beckmann.__eval_DG_wo_clamps(brdf_params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,params.NdotV,transmitted,params.VdotH,params.LdotH,VdotHLdotH,orientedEta.value); - scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.VdotH)); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,params.getNdotV(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value); + scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH())); + return hlsl::promote(f) * microfacet_transform(); + } + spectral_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) + { + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), eta); + const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; + + const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); + const bool transmitted = VdotHLdotH < 0.0; + + spectral_type dummyior; + brdf_type beckmann = brdf_type::create(A.x, A.y, dummyior, dummyior); + typename brdf_type::params_anisotropic_t brdf_params = typename brdf_type::params_anisotropic_t::create(params._sample, params.interaction, params.cache, params._clamp); + const scalar_type scalar_part = beckmann.__eval_DG_wo_clamps(brdf_params); + + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,params.getNdotV(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value); + scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH())); return hlsl::promote(f) * microfacet_transform(); } @@ -119,7 +218,7 @@ struct SBeckmannDielectricBxDF const vector3_type upperHemisphereV = orientedEta.backside ? -localV : localV; spectral_type dummyior; - reflection::SBeckmannBxDF beckmann = reflection::SBeckmannBxDF::create(A.x, A.y, dummyior, dummyior); + brdf_type beckmann = brdf_type::create(A.x, A.y, dummyior, dummyior); const vector3_type H = beckmann.__generate(upperHemisphereV, u.xy); return __generate_wo_clamps(localV, H, interaction.getFromTangentSpace(), u, orientedEta, rcpEta, cache); @@ -139,71 +238,91 @@ struct SBeckmannDielectricBxDF return s; } - scalar_type pdf(NBL_CONST_REF_ARG(params_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) + scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.VdotH, eta); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), eta); const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; - const scalar_type VdotHLdotH = params.VdotH * params.LdotH; + const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.VdotH)); + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH())); scalar_type ndf, lambda; - if (params.is_aniso) - { - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); - ndf::Beckmann beckmann_ndf; - ndf = beckmann_ndf(ndfparams); - - smith::Beckmann beckmann_smith; - scalar_type c2 = beckmann_smith.C2(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); - lambda = beckmann_smith.Lambda(c2); - } - else - { - const scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); - ndf::Beckmann beckmann_ndf; - ndf = beckmann_ndf(ndfparams); - - smith::Beckmann beckmann_smith; - lambda = beckmann_smith.Lambda(params.NdotV2, a2); - } - - smith::bsdf::VNDF_pdf > vndf = smith::bsdf::VNDF_pdf >::create(ndf, params.NdotV); - scalar_type _pdf = vndf(lambda,transmitted,params.VdotH,params.LdotH,VdotHLdotH,orientedEta.value,reflectance); + const scalar_type a2 = A.x*A.x; + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.getNdotH(), params.getNdotH2()); + ndf::Beckmann beckmann_ndf; + ndf = beckmann_ndf(ndfparams); + + smith::Beckmann beckmann_smith; + lambda = beckmann_smith.Lambda(params.getNdotV2(), a2); + + smith::bsdf::VNDF_pdf > vndf = smith::bsdf::VNDF_pdf >::create(ndf, params.getNdotV()); + scalar_type _pdf = vndf(lambda,transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value,reflectance); + onePlusLambda_V = vndf.onePlusLambda_V; + + return _pdf; + } + scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) + { + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), eta); + const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; + + const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); + const bool transmitted = VdotHLdotH < 0.0; + + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH())); + + scalar_type ndf, lambda; + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); + ndf::Beckmann beckmann_ndf; + ndf = beckmann_ndf(ndfparams); + + smith::Beckmann beckmann_smith; + scalar_type c2 = beckmann_smith.C2(params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), ax2, ay2); + lambda = beckmann_smith.Lambda(c2); + + smith::bsdf::VNDF_pdf > vndf = smith::bsdf::VNDF_pdf >::create(ndf, params.getNdotV()); + scalar_type _pdf = vndf(lambda,transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value,reflectance); onePlusLambda_V = vndf.onePlusLambda_V; return _pdf; } - scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) + scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + { + scalar_type dummy; + return pdf(params, dummy); + } + scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { scalar_type dummy; return pdf(params, dummy); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) { scalar_type onePlusLambda_V; scalar_type _pdf = pdf(params, onePlusLambda_V); scalar_type quo; - if (params.is_aniso) - { - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(A.x*A.x, A.y*A.y, params.TdotV2, params.BdotV2, params.NdotV2, params.TdotL2, params.BdotL2, params.NdotL2, onePlusLambda_V); - smith::Beckmann beckmann_smith; - quo = beckmann_smith.G2_over_G1(smithparams); - } - else - { - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(A.x*A.x, params.NdotV2, params.NdotL2, onePlusLambda_V); - smith::Beckmann beckmann_smith; - quo = beckmann_smith.G2_over_G1(smithparams); - } + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(A.x*A.x, params.getNdotV2(), params.getNdotL2(), onePlusLambda_V); + smith::Beckmann beckmann_smith; + quo = beckmann_smith.G2_over_G1(smithparams); + + return quotient_pdf_type::create((spectral_type)(quo), _pdf); + } + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) + { + scalar_type onePlusLambda_V; + scalar_type _pdf = pdf(params, onePlusLambda_V); + + scalar_type quo; + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(A.x*A.x, A.y*A.y, params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2(), onePlusLambda_V); + smith::Beckmann beckmann_smith; + quo = beckmann_smith.G2_over_G1(smithparams); return quotient_pdf_type::create((spectral_type)(quo), _pdf); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 41ec8f7beb..7935b5a431 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -17,6 +17,86 @@ namespace bxdf namespace transmission { +template +struct GGXParams; + +template +NBL_PARTIAL_REQ_TOP(!surface_interactions::Anisotropic && !AnisotropicMicrofacetCache) +struct GGXParams && !AnisotropicMicrofacetCache) > +{ + using this_t = GGXParams; + + static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, NBL_CONST_REF_ARG(MC) cache, BxDFClampMode _clamp) + { + this_t retval; + retval._sample = _sample; + retval.interaction = interaction; + retval.cache = cache; + retval._clamp = _clamp; + return retval; + } + + // iso + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } + Scalar getNdotH2() NBL_CONST_MEMBER_FUNC { return cache.getNdotH2(); } + Scalar getVdotH() NBL_CONST_MEMBER_FUNC { return cache.getVdotH(); } + Scalar getLdotH() NBL_CONST_MEMBER_FUNC { return cache.getLdotH(); } + + LS _sample; + SI interaction; + MC cache; + BxDFClampMode _clamp; +}; +template +NBL_PARTIAL_REQ_TOP(surface_interactions::Anisotropic && AnisotropicMicrofacetCache) +struct GGXParams && AnisotropicMicrofacetCache) > +{ + using this_t = GGXParams; + + static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, NBL_CONST_REF_ARG(MC) cache, BxDFClampMode _clamp) + { + this_t retval; + retval._sample = _sample; + retval.interaction = interaction; + retval.cache = cache; + retval._clamp = _clamp; + return retval; + } + + // iso + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } + Scalar getNdotH2() NBL_CONST_MEMBER_FUNC { return cache.getNdotH2(); } + Scalar getVdotH() NBL_CONST_MEMBER_FUNC { return cache.getVdotH(); } + Scalar getLdotH() NBL_CONST_MEMBER_FUNC { return cache.getLdotH(); } + + // aniso + Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL() * _sample.getTdotL(); } + Scalar getBdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getBdotL() * _sample.getBdotL(); } + Scalar getTdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getTdotV() * interaction.getTdotV(); } + Scalar getBdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getBdotV() * interaction.getBdotV(); } + Scalar getTdotH2() NBL_CONST_MEMBER_FUNC {return cache.getTdotH() * cache.getTdotH(); } + Scalar getBdotH2() NBL_CONST_MEMBER_FUNC {return cache.getBdotH() * cache.getBdotH(); } + + LS _sample; + SI interaction; + MC cache; + BxDFClampMode _clamp; +}; + template && surface_interactions::Isotropic && surface_interactions::Anisotropic && CreatableIsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SGGXDielectricBxDF { @@ -26,7 +106,6 @@ struct SGGXDielectricBxDF using vector2_type = vector; using vector3_type = vector; using matrix3x3_type = matrix; - using params_t = SBxDFParams; using isotropic_interaction_type = Iso; using anisotropic_interaction_type = Aniso; @@ -35,6 +114,10 @@ struct SGGXDielectricBxDF using quotient_pdf_type = sampling::quotient_and_pdf; using isocache_type = IsoCache; using anisocache_type = AnisoCache; + using brdf_type = reflection::SGGXBxDF; + + using params_isotropic_t = GGXParams; + using params_anisotropic_t = GGXParams; static this_t create(scalar_type eta, scalar_type A) { @@ -66,32 +149,44 @@ struct SGGXDielectricBxDF eta = params.eta; } - spectral_type eval(NBL_CONST_REF_ARG(params_t) params) + spectral_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.VdotH, eta); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), eta); const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; - const scalar_type VdotHLdotH = params.VdotH * params.LdotH; + const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); const bool transmitted = VdotHLdotH < 0.0; scalar_type NG_already_in_reflective_dL_measure; - if (params.is_aniso) - { - spectral_type dummyior; - reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, A.y, dummyior, dummyior); - NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(params); - } - else - { - spectral_type dummyior; - reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, dummyior, dummyior); - NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(params); - } + spectral_type dummyior; + brdf_type ggx = brdf_type::create(A.x, dummyior, dummyior); + typename brdf_type::params_isotropic_t brdf_params = typename brdf_type::params_isotropic_t::create(params._sample, params.interaction, params.cache, params._clamp); + NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(brdf_params); + + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,params.getNdotL(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value); + scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH())); + return hlsl::promote(f) * microfacet_transform(); + } + spectral_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) + { + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), eta); + const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; + + + const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); + const bool transmitted = VdotHLdotH < 0.0; + + scalar_type NG_already_in_reflective_dL_measure; + spectral_type dummyior; + brdf_type ggx = brdf_type::create(A.x, A.y, dummyior, dummyior); + typename brdf_type::params_anisotropic_t brdf_params = typename brdf_type::params_anisotropic_t::create(params._sample, params.interaction, params.cache, params._clamp); + NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(brdf_params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,params.NdotL,transmitted,params.VdotH,params.LdotH,VdotHLdotH,orientedEta.value); - scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.VdotH)); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,params.getNdotL(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value); + scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH())); return hlsl::promote(f) * microfacet_transform(); } @@ -126,7 +221,7 @@ struct SGGXDielectricBxDF const vector3_type upperHemisphereV = orientedEta.backside ? -localV : localV; spectral_type dummyior; - reflection::SGGXBxDF ggx = reflection::SGGXBxDF::create(A.x, A.y, dummyior, dummyior); + brdf_type ggx = brdf_type::create(A.x, A.y, dummyior, dummyior); const vector3_type H = ggx.__generate(upperHemisphereV, u.xy); return __generate_wo_clamps(localV, H, interaction.getFromTangentSpace(), u, orientedEta, rcpEta, cache); @@ -146,48 +241,56 @@ struct SGGXDielectricBxDF return s; } - scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) + scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.VdotH, eta); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), eta); const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; - const scalar_type VdotHLdotH = params.VdotH * params.LdotH; + const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.VdotH)); + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH())); scalar_type ndf, devsh_v; - if (params.is_aniso) - { - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; + const scalar_type a2 = A.x*A.x; + ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.getNdotH(), params.getNdotH2()); + ndf::GGX ggx_ndf; + ndf = ggx_ndf(ndfparams); - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.TdotH2, params.BdotH2, params.NdotH2); - ndf::GGX ggx_ndf; - ndf = ggx_ndf(ndfparams); + smith::GGX ggx_smith; + devsh_v = ggx_smith.devsh_part(params.getNdotV2(), a2, 1.0-a2); + const scalar_type lambda = ggx_smith.G1_wo_numerator(params.getNdotV(), devsh_v); - smith::GGX ggx_smith; - devsh_v = ggx_smith.devsh_part(params.TdotV2, params.BdotV2, params.NdotV2, ax2, ay2); - } - else - { - const scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.NdotH, params.NdotH2); - ndf::GGX ggx_ndf; - ndf = ggx_ndf(ndfparams); + smith::bsdf::VNDF_pdf > vndf = smith::bsdf::VNDF_pdf >::create(ndf, params.getNdotV()); + return vndf(lambda, transmitted, params.getVdotH(), params.getLdotH(), VdotHLdotH, orientedEta.value, reflectance); + } + scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) + { + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), eta); + const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; + + const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); + const bool transmitted = VdotHLdotH < 0.0; + + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH())); + + scalar_type ndf, devsh_v; + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; - smith::GGX ggx_smith; - devsh_v = ggx_smith.devsh_part(params.NdotV2, a2, 1.0-a2); - } + ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); + ndf::GGX ggx_ndf; + ndf = ggx_ndf(ndfparams); smith::GGX ggx_smith; - const scalar_type lambda = ggx_smith.G1_wo_numerator(params.NdotV, devsh_v); + devsh_v = ggx_smith.devsh_part(params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), ax2, ay2); + const scalar_type lambda = ggx_smith.G1_wo_numerator(params.getNdotV(), devsh_v); - smith::bsdf::VNDF_pdf > vndf = smith::bsdf::VNDF_pdf >::create(ndf, params.NdotV); - return vndf(lambda, transmitted, params.VdotH, params.LdotH, VdotHLdotH, orientedEta.value, reflectance); + smith::bsdf::VNDF_pdf > vndf = smith::bsdf::VNDF_pdf >::create(ndf, params.getNdotV()); + return vndf(lambda, transmitted, params.getVdotH(), params.getLdotH(), VdotHLdotH, orientedEta.value, reflectance); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) { const scalar_type ax2 = A.x*A.x; const scalar_type ay2 = A.y*A.y; @@ -196,16 +299,22 @@ struct SGGXDielectricBxDF smith::GGX ggx_smith; scalar_type quo; - if (params.is_aniso) - { - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.NdotV, params.TdotV2, params.BdotV2, params.NdotV2, params.NdotL, params.TdotL2, params.BdotL2, params.NdotL2); - quo = ggx_smith.G2_over_G1(smithparams); - } - else - { - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(ax2, params.NdotV, params.NdotV2, params.NdotL, params.NdotL2); - quo = ggx_smith.G2_over_G1(smithparams); - } + smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(ax2, params.getNdotV(), params.getNdotV2(), params.getNdotL(), params.getNdotL2()); + quo = ggx_smith.G2_over_G1(smithparams); + + return quotient_pdf_type::create((spectral_type)(quo), _pdf); + } + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) + { + const scalar_type ax2 = A.x*A.x; + const scalar_type ay2 = A.y*A.y; + + scalar_type _pdf = pdf(params); + + smith::GGX ggx_smith; + scalar_type quo; + smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.getNdotV(), params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getNdotL(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); + quo = ggx_smith.G2_over_G1(smithparams); return quotient_pdf_type::create((spectral_type)(quo), _pdf); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl index b26daeae63..668ccd4bf0 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl @@ -17,6 +17,72 @@ namespace bxdf namespace transmission { +template +struct LambertianParams; + +template +NBL_PARTIAL_REQ_TOP(!surface_interactions::Anisotropic) +struct LambertianParams) > +{ + using this_t = LambertianParams; + + static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, BxDFClampMode _clamp) + { + this_t retval; + retval._sample = _sample; + retval.interaction = interaction; + retval._clamp = _clamp; + return retval; + } + + // iso + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + + LS _sample; + SI interaction; + BxDFClampMode _clamp; +}; +template +NBL_PARTIAL_REQ_TOP(surface_interactions::Anisotropic) +struct LambertianParams) > +{ + using this_t = LambertianParams; + + static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, BxDFClampMode _clamp) + { + this_t retval; + retval._sample = _sample; + retval.interaction = interaction; + retval._clamp = _clamp; + return retval; + } + + // iso + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + + // aniso + Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL() * _sample.getTdotL(); } + Scalar getBdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getBdotL() * _sample.getBdotL(); } + Scalar getTdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getTdotV() * interaction.getTdotV(); } + Scalar getBdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getBdotV() * interaction.getBdotV(); } + + LS _sample; + SI interaction; + BxDFClampMode _clamp; +}; + template && surface_interactions::Isotropic && surface_interactions::Anisotropic) struct SLambertianBxDF { @@ -28,7 +94,10 @@ struct SLambertianBxDF using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; - using params_t = SBxDFParams; + + using params_isotropic_t = LambertianParams; + using params_anisotropic_t = LambertianParams; + static this_t create() { @@ -52,9 +121,13 @@ struct SLambertianBxDF return absNdotL; } - scalar_type eval(NBL_CONST_REF_ARG(params_t) params) + scalar_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) { - return __eval_pi_factored_out(params.NdotL) * numbers::inv_pi * 0.5; + return __eval_pi_factored_out(params.getNdotL()) * numbers::inv_pi * 0.5; + } + scalar_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) + { + return __eval_pi_factored_out(params.getNdotL()) * numbers::inv_pi * 0.5; } sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector) u) @@ -74,14 +147,23 @@ struct SLambertianBxDF return generate_wo_clamps(anisotropic_interaction_type::create(interaction), u); } - scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) + scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + { + return sampling::ProjectedSphere::pdf(params.getNdotL()); + } + scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { - return sampling::ProjectedSphere::pdf(params.NdotL); + return sampling::ProjectedSphere::pdf(params.getNdotL()); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + { + sampling::quotient_and_pdf qp = sampling::ProjectedSphere::template quotient_and_pdf(params.getNdotL()); + return quotient_pdf_type::create(hlsl::promote(qp.quotient), qp.pdf); + } + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { - sampling::quotient_and_pdf qp = sampling::ProjectedSphere::template quotient_and_pdf(params.NdotL); + sampling::quotient_and_pdf qp = sampling::ProjectedSphere::template quotient_and_pdf(params.getNdotL()); return quotient_pdf_type::create(hlsl::promote(qp.quotient), qp.pdf); } }; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index b44443ffbd..3935eb62b2 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -17,6 +17,72 @@ namespace bxdf namespace transmission { +template +struct SmoothDielectricParams; + +template +NBL_PARTIAL_REQ_TOP(!surface_interactions::Anisotropic) +struct SmoothDielectricParams) > +{ + using this_t = SmoothDielectricParams; + + static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, BxDFClampMode _clamp) + { + this_t retval; + retval._sample = _sample; + retval.interaction = interaction; + retval._clamp = _clamp; + return retval; + } + + // iso + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + + LS _sample; + SI interaction; + BxDFClampMode _clamp; +}; +template +NBL_PARTIAL_REQ_TOP(surface_interactions::Anisotropic) +struct SmoothDielectricParams) > +{ + using this_t = SmoothDielectricParams; + + static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, BxDFClampMode _clamp) + { + this_t retval; + retval._sample = _sample; + retval.interaction = interaction; + retval._clamp = _clamp; + return retval; + } + + // iso + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + + // aniso + Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL() * _sample.getTdotL(); } + Scalar getBdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getBdotL() * _sample.getBdotL(); } + Scalar getTdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getTdotV() * interaction.getTdotV(); } + Scalar getBdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getBdotV() * interaction.getBdotV(); } + + LS _sample; + SI interaction; + BxDFClampMode _clamp; +}; + template // NBL_FUNC_REQUIRES(Sample && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) // dxc won't let me put this in struct SSmoothDielectricBxDF; @@ -27,7 +93,6 @@ struct SSmoothDielectricBxDF; - using params_t = SBxDFParams; using isotropic_interaction_type = Iso; using anisotropic_interaction_type = Aniso; @@ -37,6 +102,10 @@ struct SSmoothDielectricBxDF; + using params_anisotropic_t = SmoothDielectricParams; + + static this_t create(scalar_type eta) { this_t retval; @@ -54,7 +123,11 @@ struct SSmoothDielectricBxDF(NdotV), u, orientedEta, rcpEta, dummy); } + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector) u) + { + return generate(anisotropic_interaction_type::create(interaction), u); + } // eval and pdf return 0 because smooth dielectric/conductor BxDFs are dirac delta distributions, model perfectly specular objects that scatter light to only one outgoing direction - scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) + scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) { return 0; } + scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) + { + return 0; + } + + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + { + const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(params.getNdotVUnclamped(), params.getNdotLUnclamped()); + + fresnel::OrientedEtaRcps rcpOrientedEtas = fresnel::OrientedEtaRcps::create(params.getNdotV(), eta); - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) + const scalar_type _pdf = bit_cast(numeric_limits::infinity); + scalar_type quo = hlsl::mix(1.0, rcpOrientedEtas.value, transmitted); + return quotient_pdf_type::create((spectral_type)(quo), _pdf); + } + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { - const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(params.uNdotV, params.uNdotL); + const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(params.getNdotVUnclamped(), params.getNdotLUnclamped()); - fresnel::OrientedEtaRcps rcpOrientedEtas = fresnel::OrientedEtaRcps::create(params.NdotV, eta); + fresnel::OrientedEtaRcps rcpOrientedEtas = fresnel::OrientedEtaRcps::create(params.getNdotV(), eta); const scalar_type _pdf = bit_cast(numeric_limits::infinity); - scalar_type quo = transmitted ? rcpOrientedEtas.value : 1.0; + scalar_type quo = hlsl::mix(1.0, rcpOrientedEtas.value, transmitted); return quotient_pdf_type::create((spectral_type)(quo), _pdf); } @@ -120,7 +211,6 @@ struct SSmoothDielectricBxDF; - using params_t = SBxDFParams; using isotropic_interaction_type = Iso; using anisotropic_interaction_type = Aniso; @@ -130,6 +220,10 @@ struct SSmoothDielectricBxDF; + using params_anisotropic_t = SmoothDielectricParams; + + static this_t create(NBL_CONST_REF_ARG(spectral_type) eta2, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) { this_t retval; @@ -149,7 +243,11 @@ struct SSmoothDielectricBxDF(NdotV), u, eta2, luminosityContributionHint, dummy); } - scalar_type pdf(NBL_CONST_REF_ARG(params_t) params) + scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + { + return 0; + } + scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { return 0; } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_t) params) // isotropic + // isotropic only? + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + { + const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(params.getNdotVUnclamped(), params.getNdotLUnclamped()); + const spectral_type reflectance = fresnel::thinDielectricInfiniteScatter(fresnel::Dielectric::__call(eta2, params.getNdotV())); + const spectral_type sampleValue = hlsl::mix(reflectance, (spectral_type)(1.0) - reflectance, transmitted); + + const scalar_type sampleProb = nbl::hlsl::dot(sampleValue,luminosityContributionHint); + + const scalar_type _pdf = bit_cast(numeric_limits::infinity); + return quotient_pdf_type::create((spectral_type)(sampleValue / sampleProb), _pdf); + } + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { - const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(params.uNdotV, params.uNdotL); - const spectral_type reflectance = fresnel::thinDielectricInfiniteScatter(fresnel::Dielectric::__call(eta2, params.NdotV)); - const spectral_type sampleValue = transmitted ? ((spectral_type)(1.0) - reflectance) : reflectance; + const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(params.getNdotVUnclamped(), params.getNdotLUnclamped()); + const spectral_type reflectance = fresnel::thinDielectricInfiniteScatter(fresnel::Dielectric::__call(eta2, params.getNdotV())); + const spectral_type sampleValue = hlsl::mix(reflectance, (spectral_type)(1.0) - reflectance, transmitted); const scalar_type sampleProb = nbl::hlsl::dot(sampleValue,luminosityContributionHint); diff --git a/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl b/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl index 0908ce457b..1453fd1fc8 100644 --- a/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl +++ b/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl @@ -865,6 +865,25 @@ struct mix_helper } }; +template +NBL_PARTIAL_REQ_TOP(VECTOR_SPECIALIZATION_CONCEPT&& concepts::Boolean&& !(vector_traits::Dimension == vector_traits::Dimension) && concepts::BooleanScalar) +struct mix_helper&& !(vector_traits::Dimension == vector_traits::Dimension) && concepts::BooleanScalar) > +{ + using return_t = T; + static return_t __call(NBL_CONST_REF_ARG(T) x, NBL_CONST_REF_ARG(T) y, NBL_CONST_REF_ARG(U) a) + { + using traitsT = hlsl::vector_traits; + array_get getterT; + array_set setter; + + return_t output; + for (uint32_t i = 0; i < traitsT::Dimension; ++i) + setter(output, i, mix_helper::__call(getterT(x, i), getterT(y, i), a)); + + return output; + } +}; + template NBL_PARTIAL_REQ_TOP(VECTOR_SPECIALIZATION_CONCEPT && concepts::Boolean && vector_traits::Dimension == vector_traits::Dimension) struct mix_helper && vector_traits::Dimension == vector_traits::Dimension) > From 1cc205d566033b9c4f74b2c0ed6c1447b43c6bca Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 18 Apr 2025 17:11:06 +0700 Subject: [PATCH 106/188] minor fix to bxdf concepts --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 48 ++++++++++++++--------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 6f0e7c46c1..f816e8f031 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -781,17 +781,19 @@ struct SAnisotropicMicrofacetCache #define NBL_CONCEPT_PARAM_3 (_sample, typename T::sample_type) #define NBL_CONCEPT_PARAM_4 (iso, typename T::isotropic_interaction_type) #define NBL_CONCEPT_PARAM_5 (aniso, typename T::anisotropic_interaction_type) -#define NBL_CONCEPT_PARAM_6 (param, typename T::params_t) -#define NBL_CONCEPT_PARAM_7 (u, vector) -NBL_CONCEPT_BEGIN(8) +#define NBL_CONCEPT_PARAM_6 (param_iso, typename T::params_isotropic_t) +#define NBL_CONCEPT_PARAM_7 (param_aniso, typename T::params_anisotropic_t) +#define NBL_CONCEPT_PARAM_8 (u, vector) +NBL_CONCEPT_BEGIN(9) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define spec NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define pdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 #define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 #define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 #define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 -#define param NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 -#define u NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_7 +#define param_iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 +#define param_aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_7 +#define u NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_8 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_interaction_type)) @@ -799,19 +801,22 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) ((NBL_CONCEPT_REQ_TYPE)(T::spectral_type)) ((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) - ((NBL_CONCEPT_REQ_TYPE)(T::params_t)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.eval(param)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::params_isotropic_t)) + ((NBL_CONCEPT_REQ_TYPE)(T::params_anisotropic_t)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.eval(param_iso)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.eval(param_aniso)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(iso,u)), ::nbl::hlsl::is_same_v, typename T::sample_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(aniso,u)), ::nbl::hlsl::is_same_v, typename T::sample_type)) - //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template pdf(_sample,iso)), ::nbl::hlsl::is_scalar_v)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param_iso)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param_aniso)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(LightSample, typename T::sample_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(sampling::Spectral, typename T::spectral_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Isotropic, typename T::isotropic_interaction_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Anisotropic, typename T::anisotropic_interaction_type)) ); #undef u -#undef param +#undef param_aniso +#undef param_iso #undef aniso #undef iso #undef _sample @@ -831,9 +836,10 @@ NBL_CONCEPT_END( #define NBL_CONCEPT_PARAM_5 (aniso, typename T::anisotropic_interaction_type) #define NBL_CONCEPT_PARAM_6 (isocache, typename T::isocache_type) #define NBL_CONCEPT_PARAM_7 (anisocache, typename T::anisocache_type) -#define NBL_CONCEPT_PARAM_8 (param, typename T::params_t) -#define NBL_CONCEPT_PARAM_9 (u, vector) -NBL_CONCEPT_BEGIN(10) +#define NBL_CONCEPT_PARAM_8 (param_iso, typename T::params_isotropic_t) +#define NBL_CONCEPT_PARAM_9 (param_aniso, typename T::params_anisotropic_t) +#define NBL_CONCEPT_PARAM_10 (u, vector) +NBL_CONCEPT_BEGIN(11) #define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define spec NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define pdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 @@ -842,8 +848,9 @@ NBL_CONCEPT_BEGIN(10) #define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 #define isocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 #define anisocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_7 -#define param NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_8 -#define u NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_9 +#define param_iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_8 +#define param_aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_9 +#define u NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_10 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_interaction_type)) @@ -853,18 +860,23 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) ((NBL_CONCEPT_REQ_TYPE)(T::isocache_type)) ((NBL_CONCEPT_REQ_TYPE)(T::anisocache_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.eval(param)), ::nbl::hlsl::is_same_v, T::spectral_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::params_isotropic_t)) + ((NBL_CONCEPT_REQ_TYPE)(T::params_anisotropic_t)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.eval(param_iso)), ::nbl::hlsl::is_same_v, T::spectral_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.eval(param_aniso)), ::nbl::hlsl::is_same_v, T::spectral_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(iso,u,isocache)), ::nbl::hlsl::is_same_v, typename T::sample_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(aniso,u,anisocache)), ::nbl::hlsl::is_same_v, typename T::sample_type)) //((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.template pdf(_sample,iso)), ::nbl::hlsl::is_scalar_v)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param_iso)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param_aniso)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(LightSample, typename T::sample_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(sampling::Spectral, typename T::spectral_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(CreatableIsotropicMicrofacetCache, typename T::isocache_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(AnisotropicMicrofacetCache, typename T::anisocache_type)) ); #undef u -#undef param +#undef param_aniso +#undef param_iso #undef anisocache #undef isocache #undef aniso From f0491a91261a4282ac5be6bbd0c77d18f93defcf Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 25 Jun 2025 16:12:49 +0700 Subject: [PATCH 107/188] update example test --- examples_tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples_tests b/examples_tests index 20cc57eaea..41d1111c2f 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 20cc57eaea399d68da28f709d6b63878eba67a61 +Subproject commit 41d1111c2f46d11a547f8efe2a70017cfac1b5e5 From 5d740157c732c93bc3c65fd4eb96c9f0084fd037 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 26 Jun 2025 16:32:44 +0700 Subject: [PATCH 108/188] latest example --- examples_tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples_tests b/examples_tests index eaa132075c..a6de5908a2 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit eaa132075c5c8564723b07d28ce58bb3040b4dba +Subproject commit a6de5908a269d0f6853e0c1e94dec8fcdbe6540e From d24ac0e77c2c9f59e48fd9b4fedf6dbdd0bdc2a5 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 27 Jun 2025 14:54:32 +0700 Subject: [PATCH 109/188] fixed a few typo bugs --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 4 ++-- include/nbl/builtin/hlsl/ieee754.hlsl | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index f816e8f031..36e0f883ec 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -66,7 +66,7 @@ struct ComputeMicrofacetNormal // returns normalized vector, but NaN when result is length 0 vector_type normalized(const bool _refract) { - const vector_type H = unnormalized(_refract,V,L,orientedEta); + const vector_type H = unnormalized(_refract); return hlsl::normalize(H); } @@ -743,7 +743,7 @@ struct SAnisotropicMicrofacetCache { this_t retval; vector3_type H; - retval.iso_cache = isocache_type::template create(interaction.isotropic,_sample,orientedEtas,H); + retval.iso_cache = isocache_type::template create(interaction.isotropic,_sample,orientedEtas,H); const bool valid = retval.iso_cache.NdotH >= 0.0; if (valid) { diff --git a/include/nbl/builtin/hlsl/ieee754.hlsl b/include/nbl/builtin/hlsl/ieee754.hlsl index 3616b8ba3a..a32ba589f2 100644 --- a/include/nbl/builtin/hlsl/ieee754.hlsl +++ b/include/nbl/builtin/hlsl/ieee754.hlsl @@ -168,7 +168,7 @@ struct flipSign_helper; array_get getter; - array_get setter; + array_set setter; Vectorial output; for (uint32_t i = 0; i < traits::Dimension; ++i) @@ -188,7 +188,7 @@ struct flipSign_helper; array_get getter_v; array_get getter_f; - array_get setter; + array_set setter; Vectorial output; for (uint32_t i = 0; i < traits_v::Dimension; ++i) From 48816a02ece62d541c6f1635ce4f8cb72dd8f1b8 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 9 Jul 2025 17:02:04 +0700 Subject: [PATCH 110/188] update vulkan headers to match master, not sure why it wasn't --- 3rdparty/Vulkan-Headers | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rdparty/Vulkan-Headers b/3rdparty/Vulkan-Headers index 31aa7f634b..234c4b7370 160000 --- a/3rdparty/Vulkan-Headers +++ b/3rdparty/Vulkan-Headers @@ -1 +1 @@ -Subproject commit 31aa7f634b052d87ede4664053e85f3f4d1d50d3 +Subproject commit 234c4b7370a8ea3239a214c9e871e4b17c89f4ab From f0e6aea856916f78e50b641b59e9569835d390b6 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 10 Jul 2025 15:26:31 +0700 Subject: [PATCH 111/188] changes to usage in common.hlsl --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 177 +++++++++++------- .../hlsl/bxdf/reflection/beckmann.hlsl | 17 +- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 17 +- .../hlsl/bxdf/reflection/lambertian.hlsl | 10 - .../hlsl/bxdf/reflection/oren_nayar.hlsl | 10 - .../hlsl/bxdf/transmission/beckmann.hlsl | 16 +- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 16 +- .../hlsl/bxdf/transmission/lambertian.hlsl | 10 - .../bxdf/transmission/smooth_dielectric.hlsl | 29 +-- 9 files changed, 120 insertions(+), 182 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 36e0f883ec..6754163725 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -24,18 +24,32 @@ namespace hlsl namespace bxdf { -template) +template) struct ComputeMicrofacetNormal { - using vector_type = T; - using scalar_type = typename vector_traits::scalar_type; + using scalar_type = T; + using vector_type = vector; + using monochrome_type = vector; + + using unsigned_integer_type = typename unsigned_integer_of_size::type; static ComputeMicrofacetNormal create(NBL_CONST_REF_ARG(vector_type) V, NBL_CONST_REF_ARG(vector_type) L, NBL_CONST_REF_ARG(vector_type) H, scalar_type eta) { ComputeMicrofacetNormal retval; retval.V = V; retval.L = L; - retval.orientedEta = fresnel::OrientedEtas::create(hlsl::dot(V, H), eta); + fresnel::OrientedEtas orientedEtas = fresnel::OrientedEtas::create(hlsl::dot(V, H), eta); + retval.orientedEta = orientedEtas.value; + return retval; + } + + static ComputeMicrofacetNormal create(NBL_CONST_REF_ARG(vector_type) V, NBL_CONST_REF_ARG(vector_type) L, scalar_type VdotH, scalar_type eta) + { + ComputeMicrofacetNormal retval; + retval.V = V; + retval.L = L; + fresnel::OrientedEtas orientedEtas = fresnel::OrientedEtas::create(VdotH, eta); + retval.orientedEta = orientedEtas.value; return retval; } @@ -57,6 +71,7 @@ struct ComputeMicrofacetNormal // so for transmission VdotH<=0, H needs to be flipped to be consistent with oriented eta vector_type unnormalized(const bool _refract) { + assert(hlsl::dot(V, L) <= -hlsl::min(orientedEta, scalar_type(1.0) / orientedEta)); const scalar_type etaFactor = hlsl::mix(scalar_type(1.0), orientedEta.value, _refract); vector_type tmpH = V + L * etaFactor; tmpH = ieee754::flipSign(tmpH, _refract); @@ -71,14 +86,14 @@ struct ComputeMicrofacetNormal } // if V and L are on different sides of the surface normal, then their dot product sign bits will differ, hence XOR will yield 1 at last bit - static bool isTransmissionPath(float NdotV, float NdotL) + static bool isTransmissionPath(scalar_type NdotV, scalar_type NdotL) { - return bool((bit_cast(NdotV) ^ bit_cast(NdotL)) & 0x80000000u); + return bool((hlsl::bit_cast(NdotV) ^ hlsl::bit_cast(NdotL)) & unsigned_integer_type(1u)<<(sizeof(scalar_type)*8u-1u)); } vector_type V; vector_type L; - fresnel::OrientedEtas orientedEta; + scalar_type orientedEta; }; @@ -307,19 +322,19 @@ struct SAnisotropic return create(isotropic); } - ray_dir_info_type getV() NBL_CONST_MEMBER_FUNC { return isotropic.V; } - vector3_type getN() NBL_CONST_MEMBER_FUNC { return isotropic.N; } - scalar_type getNdotV() NBL_CONST_MEMBER_FUNC { return isotropic.NdotV; } - scalar_type getNdotV2() NBL_CONST_MEMBER_FUNC { return isotropic.NdotV2; } + ray_dir_info_type getV() NBL_CONST_MEMBER_FUNC { return isotropic.getV(); } + vector3_type getN() NBL_CONST_MEMBER_FUNC { return isotropic.getN(); } + scalar_type getNdotV() NBL_CONST_MEMBER_FUNC { return isotropic.getNdotV(); } + scalar_type getNdotV2() NBL_CONST_MEMBER_FUNC { return isotropic.getNdotV2(); } vector3_type getT() NBL_CONST_MEMBER_FUNC { return T; } vector3_type getB() NBL_CONST_MEMBER_FUNC { return B; } scalar_type getTdotV() NBL_CONST_MEMBER_FUNC { return TdotV; } scalar_type getBdotV() NBL_CONST_MEMBER_FUNC { return BdotV; } - vector3_type getTangentSpaceV() NBL_CONST_MEMBER_FUNC { return vector3_type(TdotV, BdotV, isotropic.NdotV); } - matrix3x3_type getToTangentSpace() NBL_CONST_MEMBER_FUNC { return matrix3x3_type(T, B, isotropic.N); } - matrix3x3_type getFromTangentSpace() NBL_CONST_MEMBER_FUNC { return nbl::hlsl::transpose(matrix3x3_type(T, B, isotropic.N)); } + vector3_type getTangentSpaceV() NBL_CONST_MEMBER_FUNC { return vector3_type(TdotV, BdotV, isotropic.getNdotV()); } + matrix3x3_type getToTangentSpace() NBL_CONST_MEMBER_FUNC { return matrix3x3_type(T, B, isotropic.getN()); } + matrix3x3_type getFromTangentSpace() NBL_CONST_MEMBER_FUNC { return nbl::hlsl::transpose(matrix3x3_type(T, B, isotropic.getN())); } isotropic_interaction_type isotropic; vector3_type T; @@ -478,7 +493,7 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getLdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getNdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getNdotH2()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.isValidVNDFMicrofacet(b0,b0,pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, bool)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::isValidMicrofacetCache(b0,pNdotV,pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, bool)) ); #undef b0 #undef pNdotV @@ -493,7 +508,7 @@ NBL_CONCEPT_END( #define NBL_CONCEPT_PARAM_2 (pNdotV, typename T::scalar_type) #define NBL_CONCEPT_PARAM_3 (_sample, SLightSample >) #define NBL_CONCEPT_PARAM_4 (V, typename T::vector3_type) -#define NBL_CONCEPT_PARAM_5 (eta, fresnel::OrientedEtas) +#define NBL_CONCEPT_PARAM_5 (eta, fresnel::OrientedEtas >) NBL_CONCEPT_BEGIN(6) #define cache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 @@ -517,13 +532,14 @@ NBL_CONCEPT_END( #undef cache #include -template ) +template ) struct SIsotropicMicrofacetCache { using this_t = SIsotropicMicrofacetCache; using scalar_type = T; using vector3_type = vector; using matrix3x3_type = matrix; + using monochrome_type = vector; // always valid because its specialized for the reflective case static this_t createForReflection(const scalar_type NdotV, const scalar_type NdotL, const scalar_type VdotL, NBL_REF_ARG(scalar_type) LplusV_rcpLen) @@ -553,53 +569,89 @@ struct SIsotropicMicrofacetCache } // transmissive cases need to be checked if the path is valid before usage - static this_t create( - NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) L, NBL_CONST_REF_ARG(vector3_type) N, - NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEtas, NBL_REF_ARG(vector3_type) H) + static this_t create(const bool transmitted, NBL_CONST_REF_ARG(ComputeMicrofacetNormal) computeMicrofacetNormal, const scalar_type VdotL, + NBL_CONST_REF_ARG(vector3_type) N, NBL_REF_ARG(vector3_type) H) { this_t retval; - const scalar_type NdotV = hlsl::dot(N, V); - const scalar_type NdotL = hlsl::dot(N, L); - const scalar_type VdotL = hlsl::dot(V, L); - const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(NdotV,NdotL); - - ComputeMicrofacetNormal computeMicrofacetNormal = ComputeMicrofacetNormal::create(V,L,N,1.0); - computeMicrofacetNormal.orientedEta.value = orientedEtas.value; - computeMicrofacetNormal.orientedEta.rcp = orientedEtas.rcp; H = computeMicrofacetNormal.normalized(transmitted); retval.NdotH = hlsl::dot(N, H); // not coming from the medium (reflected) OR // exiting at the macro scale AND ( (not L outside the cone of possible directions given IoR with constraint VdotH*LdotH<0.0) OR (microfacet not facing toward the macrosurface, i.e. non heightfield profile of microsurface) ) - const bool valid = !transmitted || (VdotL <= -hlsl::min(orientedEtas.value, orientedEtas.rcp) && retval.NdotH >= nbl::hlsl::numeric_limits::min); + const bool valid = isValidMicrofacetCache(transmitted, VdotL, retval.NdotH, computeMicrofacetNormal.orientedEta.value, computeMicrofacetNormal.orientedEta.rcp); if (valid) { - retval.VdotH = hlsl::dot(V,H); - retval.LdotH = hlsl::dot(L,H); + retval.VdotH = hlsl::dot(computeMicrofacetNormal.V,H); + retval.LdotH = hlsl::dot(computeMicrofacetNormal.L,H); retval.NdotH2 = retval.NdotH * retval.NdotH; } else - retval.NdotH = -1.0; + retval.NdotH = nbl::hlsl::numeric_limits::quiet_NaN; return retval; } + static this_t create( + NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) L, NBL_CONST_REF_ARG(vector3_type) N, + NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEtas, NBL_REF_ARG(vector3_type) H) + { + this_t retval; + const scalar_type NdotV = hlsl::dot(N, V); + const scalar_type NdotL = hlsl::dot(N, L); + const scalar_type VdotL = hlsl::dot(V, L); + const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(NdotV,NdotL); + + ComputeMicrofacetNormal computeMicrofacetNormal = ComputeMicrofacetNormal::create(V,L,N,1.0); + computeMicrofacetNormal.orientedEta = orientedEtas; + + return create(transmitted, computeMicrofacetNormal, VdotL, N, H); + } + + static this_t create( + NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) L, NBL_CONST_REF_ARG(vector3_type) N, + NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEtas) + { + vector3_type dummy; + return create(V, L, N, orientedEtas, dummy); + } + template && LightSample) static this_t create( NBL_CONST_REF_ARG(IsotropicInteraction) interaction, NBL_CONST_REF_ARG(LS) _sample, - NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEtas, NBL_REF_ARG(vector3_type) H) + NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEtas, NBL_REF_ARG(vector3_type) H) { const vector3_type V = interaction.getV().getDirection(); const vector3_type L = _sample.getL().getDirection(); + const vector3_type N = interaction.getN(); + + const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(interaction.getNdotV(),_sample.getNdotL()); - return create(V,L,interaction.getN(),orientedEtas,H); + ComputeMicrofacetNormal computeMicrofacetNormal = ComputeMicrofacetNormal::create(V,L,N,1.0); + computeMicrofacetNormal.orientedEta = orientedEtas; + + return create(transmitted, computeMicrofacetNormal, _sample.getVdotL(), N, H); } - bool isValidVNDFMicrofacet(const bool is_bsdf, const bool transmission, const scalar_type VdotL, const scalar_type eta, const scalar_type rcp_eta) + template && LightSample) + static this_t create( + NBL_CONST_REF_ARG(IsotropicInteraction) interaction, + NBL_CONST_REF_ARG(LS) _sample, + NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEtas) + { + vector3_type dummy; + return create(interaction,_sample,orientedEtas,dummy); + } + + static bool isValidMicrofacetCache(const bool transmitted, const scalar_type VdotL, const scalar_type NdotH, const scalar_type eta, const scalar_type rcp_eta) { - return NdotH >= 0.0 && !(is_bsdf && transmission && (VdotL > -hlsl::min(eta, rcp_eta))); + return !transmitted || (VdotL <= -hlsl::min(eta, rcp_eta) && NdotH >= nbl::hlsl::numeric_limits::min); } + // bool isValidVNDFMicrofacet(const bool is_bsdf, const bool transmission, const scalar_type VdotL, const scalar_type eta, const scalar_type rcp_eta) + // { + // return NdotH >= 0.0 && !(is_bsdf && transmission && (VdotL > -hlsl::min(eta, rcp_eta))); + // } + scalar_type getVdotH() NBL_CONST_MEMBER_FUNC { assert(VdotH >= scalar_type(0.0)); @@ -626,8 +678,9 @@ struct SIsotropicMicrofacetCache #define NBL_CONCEPT_PARAM_3 (_sample, SLightSample >) #define NBL_CONCEPT_PARAM_4 (V, typename T::vector3_type) #define NBL_CONCEPT_PARAM_5 (b0, bool) -#define NBL_CONCEPT_PARAM_6 (eta, fresnel::OrientedEtas) -NBL_CONCEPT_BEGIN(7) +#define NBL_CONCEPT_PARAM_6 (eta, fresnel::OrientedEtas >) +#define NBL_CONCEPT_PARAM_7 (rcp_eta, fresnel::OrientedEtaRcps >) +NBL_CONCEPT_BEGIN(8) #define cache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define pNdotL NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 @@ -635,20 +688,22 @@ NBL_CONCEPT_BEGIN(7) #define V NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 #define b0 NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 #define eta NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 +#define rcp_eta NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_7 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) ((NBL_CONCEPT_REQ_TYPE)(T::isocache_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getTdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getBdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V,b0,pNdotL,pNdotL)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(V,V)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V,b0,rcp_eta)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(V,V,pNdotL)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection > >,SLightSample > >(aniso,_sample)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V,V,V,V,eta,V)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create > >,SLightSample > >(aniso,_sample,eta)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(CreatableIsotropicMicrofacetCache, typename T::isocache_type)) ); +#undef rcp_eta #undef eta #undef b0 #undef V @@ -666,9 +721,10 @@ struct SAnisotropicMicrofacetCache using scalar_type = typename IsoCache::scalar_type; using vector3_type = vector; using matrix3x3_type = matrix; + using monochrome_type = vector; // always valid by construction - static this_t create(NBL_CONST_REF_ARG(vector3_type) tangentSpaceV, NBL_CONST_REF_ARG(vector3_type) tangentSpaceH) + static this_t createForReflection(NBL_CONST_REF_ARG(vector3_type) tangentSpaceV, NBL_CONST_REF_ARG(vector3_type) tangentSpaceH) { this_t retval; @@ -685,15 +741,14 @@ struct SAnisotropicMicrofacetCache NBL_CONST_REF_ARG(vector3_type) tangentSpaceV, NBL_CONST_REF_ARG(vector3_type) tangentSpaceH, const bool transmitted, - const scalar_type rcpOrientedEta, - const scalar_type rcpOrientedEta2 + NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpOrientedEta ) { this_t retval = create(tangentSpaceV,tangentSpaceH); if (transmitted) { const scalar_type VdotH = retval.iso_cache.VdotH; - retval.iso_cache.LdotH = transmitted ? refract_compute_NdotT(VdotH<0.0,VdotH*VdotH,rcpOrientedEta2) : VdotH; + retval.iso_cache.LdotH = refract_compute_NdotT(VdotH<0.0,VdotH*VdotH,rcpOrientedEta.value2); } return retval; @@ -721,7 +776,7 @@ struct SAnisotropicMicrofacetCache static this_t create( NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) L, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N, - NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEtas, NBL_REF_ARG(vector3_type) H + NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEtas, NBL_REF_ARG(vector3_type) H ) { this_t retval; @@ -738,7 +793,7 @@ struct SAnisotropicMicrofacetCache static this_t create( NBL_CONST_REF_ARG(AnisotropicInteraction) interaction, NBL_CONST_REF_ARG(LS) _sample, - NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEtas + NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEtas ) { this_t retval; @@ -753,15 +808,20 @@ struct SAnisotropicMicrofacetCache return retval; } - bool isValidVNDFMicrofacet(const bool is_bsdf, const bool transmission, const scalar_type VdotL, const scalar_type eta, const scalar_type rcp_eta) + static bool isValidMicrofacetCache(const bool transmitted, const scalar_type VdotL, const scalar_type NdotH, const scalar_type eta, const scalar_type rcp_eta) { - return iso_cache.isValidVNDFMicrofacet(is_bsdf, transmission, VdotL, eta, rcp_eta); + return isocache_type::isValidMicrofacetCache(transmitted, VdotL, NdotH, eta, rcp_eta); } - scalar_type getVdotH() NBL_CONST_MEMBER_FUNC { return iso_cache.VdotH; } - scalar_type getLdotH() NBL_CONST_MEMBER_FUNC { return iso_cache.LdotH; } - scalar_type getNdotH() NBL_CONST_MEMBER_FUNC { return iso_cache.NdotH; } - scalar_type getNdotH2() NBL_CONST_MEMBER_FUNC { return iso_cache.NdotH2; } + // bool isValidVNDFMicrofacet(const bool is_bsdf, const bool transmission, const scalar_type VdotL, const scalar_type eta, const scalar_type rcp_eta) + // { + // return iso_cache.isValidVNDFMicrofacet(is_bsdf, transmission, VdotL, eta, rcp_eta); + // } + + scalar_type getVdotH() NBL_CONST_MEMBER_FUNC { return iso_cache.getVdotH(); } + scalar_type getLdotH() NBL_CONST_MEMBER_FUNC { return iso_cache.getLdotH(); } + scalar_type getNdotH() NBL_CONST_MEMBER_FUNC { return iso_cache.getNdotH(); } + scalar_type getNdotH2() NBL_CONST_MEMBER_FUNC { return iso_cache.getNdotH2(); } scalar_type getTdotH() NBL_CONST_MEMBER_FUNC { return TdotH; } scalar_type getBdotH() NBL_CONST_MEMBER_FUNC { return BdotH; } @@ -894,19 +954,6 @@ enum BxDFClampMode : uint16_t BCM_ABS }; -// unified param struct for calls to BxDF::create -template) -struct SBxDFCreationParams -{ - bool is_aniso; - vector A; // roughness - Spectrum ior0; // source ior - Spectrum ior1; // destination ior - Scalar eta; // in most cases, eta will be calculated from ior0 and ior1; see monochromeEta in pathtracer.hlsl - Spectrum eta2; - Spectrum luminosityContributionHint; -}; - } } } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index f5f272c9dd..d8a4c3c3c5 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -138,21 +138,6 @@ struct SBeckmannBxDF return retval; } - static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - if (params.is_aniso) - return create(params.A.x, params.A.y, params.ior0, params.ior1); - else - return create(params.A.x, params.ior0, params.ior1); - } - - void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - A = params.A; - ior0 = params.ior0; - ior1 = params.ior1; - } - scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_isotropic_t) params) { scalar_type a2 = A.x*A.x; @@ -281,7 +266,7 @@ struct SBeckmannBxDF const vector3_type localV = interaction.getTangentSpaceV(); const vector3_type H = __generate(localV, u); - cache = anisocache_type::create(localV, H); + cache = anisocache_type::createForReflection(localV, H); ray_dir_info_type localL; bxdf::Reflect r = bxdf::Reflect::create(localV, H, cache.iso_cache.getVdotH()); localL.direction = r(); diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 601ed78eb9..afa87765c6 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -139,21 +139,6 @@ struct SGGXBxDF return retval; } - static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - if (params.is_aniso) - return create(params.A.x, params.A.y, params.ior0, params.ior1); - else - return create(params.A.x, params.ior0, params.ior1); - } - - void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - A = params.A; - ior0 = params.ior0; - ior1 = params.ior1; - } - scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_isotropic_t) params) { scalar_type a2 = A.x*A.x; @@ -236,7 +221,7 @@ struct SGGXBxDF const vector3_type localV = interaction.getTangentSpaceV(); const vector3_type H = __generate(localV, u); - cache = anisocache_type::create(localV, H); + cache = anisocache_type::createForReflection(localV, H); ray_dir_info_type localL; bxdf::Reflect r = bxdf::Reflect::create(localV, H, cache.iso_cache.getVdotH()); localL.direction = r(); diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl index 394a7e677f..8a9dc55ef1 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl @@ -106,16 +106,6 @@ struct SLambertianBxDF return retval; } - static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - return create(); - } - - void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - // do nothing - } - scalar_type __eval_pi_factored_out(scalar_type maxNdotL) { return maxNdotL; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl index 281f3f12e1..6cca0d0eac 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl @@ -108,16 +108,6 @@ struct SOrenNayarBxDF return retval; } - static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - return create(params.A.x); - } - - void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - A = params.A.x; - } - scalar_type __rec_pi_factored_out_wo_clamps(scalar_type VdotL, scalar_type maxNdotL, scalar_type maxNdotV) { scalar_type A2 = A * 0.5; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 652e69e459..27440ef9f2 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -136,20 +136,6 @@ struct SBeckmannDielectricBxDF return retval; } - static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - if (params.is_aniso) - return create(params.eta, params.A.x, params.A.y); - else - return create(params.eta, params.A.x); - } - - void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - A = params.A; - eta = params.eta; - } - spectral_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) { fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), eta); @@ -195,7 +181,7 @@ struct SBeckmannDielectricBxDF scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); - cache = anisocache_type::create(localV, H); + cache = anisocache_type::createForReflection(localV, H); const scalar_type VdotH = cache.iso_cache.getVdotH(); Refract r; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 7935b5a431..7c6cb42820 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -135,20 +135,6 @@ struct SGGXDielectricBxDF return retval; } - static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - if (params.is_aniso) - return create(params.eta, params.A.x, params.A.y); - else - return create(params.eta, params.A.x); - } - - void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - A = params.A; - eta = params.eta; - } - spectral_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) { fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), eta); @@ -198,7 +184,7 @@ struct SGGXDielectricBxDF scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); - cache = anisocache_type::create(localV, H); + cache = anisocache_type::createForReflection(localV, H); const scalar_type VdotH = cache.iso_cache.getVdotH(); Refract r; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl index 668ccd4bf0..1138c2a06c 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl @@ -106,16 +106,6 @@ struct SLambertianBxDF return retval; } - static this_t create(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - return create(); - } - - void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - // do nothing - } - scalar_type __eval_pi_factored_out(scalar_type absNdotL) { return absNdotL; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index 3935eb62b2..903289827c 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -113,16 +113,6 @@ struct SSmoothDielectricBxDF) params) - { - return create(params.eta); - } - - void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - eta = params.eta; - } - spectral_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) { return (spectral_type)0; @@ -182,7 +172,7 @@ struct SSmoothDielectricBxDF::isTransmissionPath(params.getNdotVUnclamped(), params.getNdotLUnclamped()); + const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(params.getNdotVUnclamped(), params.getNdotLUnclamped()); fresnel::OrientedEtaRcps rcpOrientedEtas = fresnel::OrientedEtaRcps::create(params.getNdotV(), eta); @@ -192,7 +182,7 @@ struct SSmoothDielectricBxDF::isTransmissionPath(params.getNdotVUnclamped(), params.getNdotLUnclamped()); + const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(params.getNdotVUnclamped(), params.getNdotLUnclamped()); fresnel::OrientedEtaRcps rcpOrientedEtas = fresnel::OrientedEtaRcps::create(params.getNdotV(), eta); @@ -232,17 +222,6 @@ struct SSmoothDielectricBxDF) params) - { - return create(params.eta2, params.luminosityContributionHint); - } - - void init(NBL_CONST_REF_ARG(SBxDFCreationParams) params) - { - eta2 = params.eta2; - luminosityContributionHint = params.luminosityContributionHint; - } - spectral_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) { return (spectral_type)0; @@ -299,7 +278,7 @@ struct SSmoothDielectricBxDF::isTransmissionPath(params.getNdotVUnclamped(), params.getNdotLUnclamped()); + const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(params.getNdotVUnclamped(), params.getNdotLUnclamped()); const spectral_type reflectance = fresnel::thinDielectricInfiniteScatter(fresnel::Dielectric::__call(eta2, params.getNdotV())); const spectral_type sampleValue = hlsl::mix(reflectance, (spectral_type)(1.0) - reflectance, transmitted); @@ -310,7 +289,7 @@ struct SSmoothDielectricBxDF::isTransmissionPath(params.getNdotVUnclamped(), params.getNdotLUnclamped()); + const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(params.getNdotVUnclamped(), params.getNdotLUnclamped()); const spectral_type reflectance = fresnel::thinDielectricInfiniteScatter(fresnel::Dielectric::__call(eta2, params.getNdotV())); const spectral_type sampleValue = hlsl::mix(reflectance, (spectral_type)(1.0) - reflectance, transmitted); From 64ec3586eb1e1eb7633b4b1e4734f62b22b1759f Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 10 Jul 2025 17:04:46 +0700 Subject: [PATCH 112/188] changes to OrientedEtas, reflect/refract usage --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 21 +++---- include/nbl/builtin/hlsl/bxdf/fresnel.hlsl | 58 +++++++------------ .../hlsl/bxdf/transmission/beckmann.hlsl | 39 +++++++------ .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 39 +++++++------ .../bxdf/transmission/smooth_dielectric.hlsl | 24 ++++---- 5 files changed, 81 insertions(+), 100 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 6754163725..c3bf426538 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -109,13 +109,15 @@ namespace ray_dir_info #define NBL_CONCEPT_PARAM_3 (m, typename T::matrix3x3_type) #define NBL_CONCEPT_PARAM_4 (rfl, Reflect) #define NBL_CONCEPT_PARAM_5 (rfr, Refract) -NBL_CONCEPT_BEGIN(6) +#define NBL_CONCEPT_PARAM_6 (backside, bool) +NBL_CONCEPT_BEGIN(7) #define rdirinfo NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define N NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define dirDotN NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 #define m NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 #define rfl NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 #define rfr NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 +#define backside NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) @@ -123,11 +125,12 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.getDirection()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.transmit()), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.reflect(rfl)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.refract(rfr)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.refract(rfr, backside, dirDotN)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.transform(m)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(is_scalar_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(is_vector_v, typename T::vector3_type)) ); +#undef backside #undef rfr #undef rfl #undef m @@ -159,10 +162,10 @@ struct SBasic return retval; } - SBasic refract(NBL_CONST_REF_ARG(Refract) r) + SBasic refract(NBL_CONST_REF_ARG(Refract) r, const bool backside, scalar_type rcpOrientedEta) { SBasic retval; - retval.direction = r(); + retval.direction = r(backside, rcpOrientedEta); return retval; } @@ -647,11 +650,6 @@ struct SIsotropicMicrofacetCache return !transmitted || (VdotL <= -hlsl::min(eta, rcp_eta) && NdotH >= nbl::hlsl::numeric_limits::min); } - // bool isValidVNDFMicrofacet(const bool is_bsdf, const bool transmission, const scalar_type VdotL, const scalar_type eta, const scalar_type rcp_eta) - // { - // return NdotH >= 0.0 && !(is_bsdf && transmission && (VdotL > -hlsl::min(eta, rcp_eta))); - // } - scalar_type getVdotH() NBL_CONST_MEMBER_FUNC { assert(VdotH >= scalar_type(0.0)); @@ -813,11 +811,6 @@ struct SAnisotropicMicrofacetCache return isocache_type::isValidMicrofacetCache(transmitted, VdotL, NdotH, eta, rcp_eta); } - // bool isValidVNDFMicrofacet(const bool is_bsdf, const bool transmission, const scalar_type VdotL, const scalar_type eta, const scalar_type rcp_eta) - // { - // return iso_cache.isValidVNDFMicrofacet(is_bsdf, transmission, VdotL, eta, rcp_eta); - // } - scalar_type getVdotH() NBL_CONST_MEMBER_FUNC { return iso_cache.getVdotH(); } scalar_type getLdotH() NBL_CONST_MEMBER_FUNC { return iso_cache.getLdotH(); } scalar_type getNdotH() NBL_CONST_MEMBER_FUNC { return iso_cache.getNdotH(); } diff --git a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl index 506daa5b61..25ad3ca705 100644 --- a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl @@ -21,7 +21,7 @@ namespace bxdf namespace fresnel { -template || is_vector_v) +template) struct OrientedEtas { using scalar_type = typename vector_traits::scalar_type; @@ -29,19 +29,18 @@ struct OrientedEtas static OrientedEtas create(scalar_type NdotI, T eta) { OrientedEtas retval; - retval.backside = NdotI < scalar_type(0.0); + const bool backside = NdotI < scalar_type(0.0); const T rcpEta = hlsl::promote(1.0) / eta; - retval.value = retval.backside ? rcpEta : eta; - retval.rcp = retval.backside ? eta : rcpEta; + retval.value = backside ? rcpEta : eta; + retval.rcp = backside ? eta : rcpEta; return retval; } T value; T rcp; - bool backside; }; -template || is_vector_v) +template) struct OrientedEtaRcps { using scalar_type = typename vector_traits::scalar_type; @@ -49,9 +48,9 @@ struct OrientedEtaRcps static OrientedEtaRcps create(scalar_type NdotI, T eta) { OrientedEtaRcps retval; - retval.backside = NdotI < scalar_type(0.0); + const bool backside = NdotI < scalar_type(0.0); const T rcpEta = hlsl::promote(1.0) / eta; - retval.value = retval.backside ? eta : rcpEta; + retval.value = backside ? eta : rcpEta; retval.value2 = retval.value * retval.value; return retval; } @@ -71,7 +70,6 @@ struct OrientedEtaRcps T value; T value2; - bool backside; }; } @@ -97,7 +95,7 @@ struct Reflect this_t retval; retval.I = I; retval.N = N; - retval.NdotI = computeNdotI(I, N); + retval.recomputeNdotI(); return retval; } @@ -121,29 +119,16 @@ struct Refract { using this_t = Refract; using vector_type = vector; + using monochrome_type = vector; using scalar_type = T; - static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEtas, NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N) + static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEtas, NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N, const bool backside) { this_t retval; retval.I = I; retval.N = N; - retval.NdotI = hlsl::dot(N, I); - retval.NdotI2 = retval.NdotI * retval.NdotI; - retval.rcpOrientedEta = rcpEtas; - retval.recomputeNdotT(rcpEtas.backside, retval.NdotI2, rcpEtas.value2); - return retval; - } - - static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEtas, NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N, const scalar_type NdotI) - { - this_t retval; - retval.I = I; - retval.N = N; - retval.NdotI = NdotI; - retval.NdotI2 = retval.NdotI * retval.NdotI; - retval.rcpOrientedEta = rcpEtas; - retval.recomputeNdotT(rcpEtas.backside, retval.NdotI2, rcpEtas.value2); + retval.recomputeNdotI(); + retval.recomputeNdotT(backside, retval.NdotI2, rcpEtas.value2[0]); return retval; } @@ -160,10 +145,10 @@ struct Refract NdotT = ieee754::flipSign(absNdotT, backside); } - vector_type operator()() + vector_type operator()(const bool backside, scalar_type rcpOrientedEta) { - recomputeNdotT(rcpOrientedEta.backside, NdotI2, rcpOrientedEta.value2); - return N * (NdotI * rcpOrientedEta.value + NdotT) - rcpOrientedEta.value * I; + recomputeNdotT(rcpOrientedEta.backside, NdotI2, rcpOrientedEta*rcpOrientedEta); + return N * (NdotI * rcpOrientedEta + NdotT) - rcpOrientedEta * I; } vector_type I; @@ -171,7 +156,6 @@ struct Refract scalar_type NdotT; scalar_type NdotI; scalar_type NdotI2; - fresnel::OrientedEtaRcps rcpOrientedEta; }; template) @@ -192,14 +176,14 @@ struct ReflectRefract return retval; } - static this_t create(bool r, NBL_CONST_REF_ARG(Refract) refract) + static this_t create(bool r, NBL_CONST_REF_ARG(Refract) refract, scalar_type rcpOrientedEta) { this_t retval; retval.I = refract.I; retval.N = refract.N; retval.NdotI = refract.NdotI; retval.NdotTorR = hlsl::mix(refract.NdotI, refract.NdotT, r); - retval.rcpOrientedEta = refract.rcpOrientedEta.value; + retval.rcpOrientedEta = rcpOrientedEta; return retval; } @@ -232,7 +216,7 @@ struct ReflectRefract namespace fresnel { -template || is_vector_v) +template || concepts::FloatingPointLikeVectorial) struct Schlick { using scalar_type = typename vector_traits::scalar_type; @@ -257,7 +241,7 @@ struct Schlick scalar_type clampedCosTheta; }; -template || is_vector_v) +template || concepts::FloatingPointLikeVectorial) struct Conductor { using scalar_type = typename vector_traits::scalar_type; @@ -294,7 +278,7 @@ struct Conductor scalar_type clampedCosTheta; }; -template || is_vector_v) +template || concepts::FloatingPointLikeVectorial) struct Dielectric { using scalar_type = typename vector_traits::scalar_type; @@ -332,7 +316,7 @@ struct Dielectric scalar_type absCosTheta; }; -template || is_vector_v) +template || concepts::FloatingPointLikeVectorial) struct DielectricFrontFaceOnly { using scalar_type = typename vector_traits::scalar_type; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 27440ef9f2..249e04f847 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -106,6 +106,7 @@ struct SBeckmannDielectricBxDF using vector2_type = vector; using vector3_type = vector; using matrix3x3_type = matrix; + using monochrome_type = vector; using isotropic_interaction_type = Iso; using anisotropic_interaction_type = Aniso; @@ -138,8 +139,8 @@ struct SBeckmannDielectricBxDF spectral_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), eta); - const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); + const scalar_type orientedEta2 = orientedEta.value[0] * orientedEta.value[0]; const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); const bool transmitted = VdotHLdotH < 0.0; @@ -150,14 +151,14 @@ struct SBeckmannDielectricBxDF const scalar_type scalar_part = beckmann.__eval_DG_wo_clamps(brdf_params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,params.getNdotV(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,params.getNdotV(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH())); return hlsl::promote(f) * microfacet_transform(); } spectral_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), eta); - const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); + const scalar_type orientedEta2 = orientedEta.value[0] * orientedEta.value[0]; const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); const bool transmitted = VdotHLdotH < 0.0; @@ -168,15 +169,15 @@ struct SBeckmannDielectricBxDF const scalar_type scalar_part = beckmann.__eval_DG_wo_clamps(brdf_params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,params.getNdotV(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,params.getNdotV(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH())); return hlsl::promote(f) * microfacet_transform(); } - sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) localV, NBL_CONST_REF_ARG(vector3_type) H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(anisocache_type) cache) + sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) localV, NBL_CONST_REF_ARG(vector3_type) H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(anisocache_type) cache) { const scalar_type localVdotH = nbl::hlsl::dot(localV,H); - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta.value * orientedEta.value,nbl::hlsl::abs(localVdotH)); + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta.value[0] * orientedEta.value[0],nbl::hlsl::abs(localVdotH)); scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); @@ -185,10 +186,10 @@ struct SBeckmannDielectricBxDF const scalar_type VdotH = cache.iso_cache.getVdotH(); Refract r; - r.recomputeNdotT(VdotH < 0.0, VdotH * VdotH, rcpEta.value2); + r.recomputeNdotT(VdotH < 0.0, VdotH * VdotH, rcpEta.value2[0]); cache.iso_cache.LdotH = hlsl::mix(VdotH, r.NdotT, transmitted); ray_dir_info_type localL; - bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, localV, H, VdotH, cache.iso_cache.getLdotH(), rcpEta.value); + bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, localV, H, VdotH, cache.iso_cache.getLdotH(), rcpEta.value[0]); localL.direction = rr(transmitted); return sample_type::createFromTangentSpace(localV, localL, m); @@ -198,10 +199,10 @@ struct SBeckmannDielectricBxDF { const vector3_type localV = interaction.getTangentSpaceV(); - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), eta); - fresnel::OrientedEtaRcps rcpEta = fresnel::OrientedEtaRcps::create(interaction.isotropic.getNdotV(), eta); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), hlsl::promote(eta)); + fresnel::OrientedEtaRcps rcpEta = fresnel::OrientedEtaRcps::create(interaction.isotropic.getNdotV(), hlsl::promote(eta)); - const vector3_type upperHemisphereV = orientedEta.backside ? -localV : localV; + const vector3_type upperHemisphereV = hlsl::mix(localV, -localV, interaction.isotropic.getNdotV() < scalar_type(0.0)); spectral_type dummyior; brdf_type beckmann = brdf_type::create(A.x, A.y, dummyior, dummyior); @@ -226,8 +227,8 @@ struct SBeckmannDielectricBxDF scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), eta); - const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); + const scalar_type orientedEta2 = orientedEta.value[0] * orientedEta.value[0]; const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); const bool transmitted = VdotHLdotH < 0.0; @@ -244,15 +245,15 @@ struct SBeckmannDielectricBxDF lambda = beckmann_smith.Lambda(params.getNdotV2(), a2); smith::bsdf::VNDF_pdf > vndf = smith::bsdf::VNDF_pdf >::create(ndf, params.getNdotV()); - scalar_type _pdf = vndf(lambda,transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value,reflectance); + scalar_type _pdf = vndf(lambda,transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0],reflectance); onePlusLambda_V = vndf.onePlusLambda_V; return _pdf; } scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), eta); - const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); + const scalar_type orientedEta2 = orientedEta.value[0] * orientedEta.value[0]; const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); const bool transmitted = VdotHLdotH < 0.0; @@ -271,7 +272,7 @@ struct SBeckmannDielectricBxDF lambda = beckmann_smith.Lambda(c2); smith::bsdf::VNDF_pdf > vndf = smith::bsdf::VNDF_pdf >::create(ndf, params.getNdotV()); - scalar_type _pdf = vndf(lambda,transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value,reflectance); + scalar_type _pdf = vndf(lambda,transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0],reflectance); onePlusLambda_V = vndf.onePlusLambda_V; return _pdf; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 7c6cb42820..8074d4b9eb 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -106,6 +106,7 @@ struct SGGXDielectricBxDF using vector2_type = vector; using vector3_type = vector; using matrix3x3_type = matrix; + using monochrome_type = vector; using isotropic_interaction_type = Iso; using anisotropic_interaction_type = Aniso; @@ -137,8 +138,8 @@ struct SGGXDielectricBxDF spectral_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), eta); - const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); + const scalar_type orientedEta2 = orientedEta.value[0] * orientedEta.value[0]; const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); @@ -151,14 +152,14 @@ struct SGGXDielectricBxDF NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(brdf_params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,params.getNdotL(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,params.getNdotL(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH())); return hlsl::promote(f) * microfacet_transform(); } spectral_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), eta); - const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); + const scalar_type orientedEta2 = orientedEta.value[0] * orientedEta.value[0]; const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); @@ -171,15 +172,15 @@ struct SGGXDielectricBxDF NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(brdf_params); ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,params.getNdotL(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value); + ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,params.getNdotL(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH())); return hlsl::promote(f) * microfacet_transform(); } - sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) localV, NBL_CONST_REF_ARG(vector3_type) H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(anisocache_type) cache) + sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) localV, NBL_CONST_REF_ARG(vector3_type) H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(anisocache_type) cache) { const scalar_type localVdotH = nbl::hlsl::dot(localV,H); - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta.value * orientedEta.value,nbl::hlsl::abs(localVdotH)); + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta.value[0] * orientedEta.value[0],nbl::hlsl::abs(localVdotH)); scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); @@ -188,10 +189,10 @@ struct SGGXDielectricBxDF const scalar_type VdotH = cache.iso_cache.getVdotH(); Refract r; - r.recomputeNdotT(VdotH < 0.0, VdotH * VdotH, rcpEta.value2); + r.recomputeNdotT(VdotH < 0.0, VdotH * VdotH, rcpEta.value2[0]); cache.iso_cache.LdotH = hlsl::mix(VdotH, r.NdotT, transmitted); ray_dir_info_type localL; - bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, localV, H, VdotH, cache.iso_cache.getLdotH(), rcpEta.value); + bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, localV, H, VdotH, cache.iso_cache.getLdotH(), rcpEta.value[0]); localL.direction = rr(transmitted); return sample_type::createFromTangentSpace(localV, localL, m); @@ -201,10 +202,10 @@ struct SGGXDielectricBxDF { const vector3_type localV = interaction.getTangentSpaceV(); - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), eta); - fresnel::OrientedEtaRcps rcpEta = fresnel::OrientedEtaRcps::create(interaction.isotropic.getNdotV(), eta); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), hlsl::promote(eta)); + fresnel::OrientedEtaRcps rcpEta = fresnel::OrientedEtaRcps::create(interaction.isotropic.getNdotV(), hlsl::promote(eta)); - const vector3_type upperHemisphereV = orientedEta.backside ? -localV : localV; + const vector3_type upperHemisphereV = hlsl::mix(localV, -localV, interaction.isotropic.getNdotV() < scalar_type(0.0)); spectral_type dummyior; brdf_type ggx = brdf_type::create(A.x, A.y, dummyior, dummyior); @@ -229,8 +230,8 @@ struct SGGXDielectricBxDF scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), eta); - const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); + const scalar_type orientedEta2 = orientedEta.value[0] * orientedEta.value[0]; const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); const bool transmitted = VdotHLdotH < 0.0; @@ -248,12 +249,12 @@ struct SGGXDielectricBxDF const scalar_type lambda = ggx_smith.G1_wo_numerator(params.getNdotV(), devsh_v); smith::bsdf::VNDF_pdf > vndf = smith::bsdf::VNDF_pdf >::create(ndf, params.getNdotV()); - return vndf(lambda, transmitted, params.getVdotH(), params.getLdotH(), VdotHLdotH, orientedEta.value, reflectance); + return vndf(lambda, transmitted, params.getVdotH(), params.getLdotH(), VdotHLdotH, orientedEta.value[0], reflectance); } scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), eta); - const scalar_type orientedEta2 = orientedEta.value * orientedEta.value; + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); + const scalar_type orientedEta2 = orientedEta.value[0] * orientedEta.value[0]; const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); const bool transmitted = VdotHLdotH < 0.0; @@ -273,7 +274,7 @@ struct SGGXDielectricBxDF const scalar_type lambda = ggx_smith.G1_wo_numerator(params.getNdotV(), devsh_v); smith::bsdf::VNDF_pdf > vndf = smith::bsdf::VNDF_pdf >::create(ndf, params.getNdotV()); - return vndf(lambda, transmitted, params.getVdotH(), params.getLdotH(), VdotHLdotH, orientedEta.value, reflectance); + return vndf(lambda, transmitted, params.getVdotH(), params.getLdotH(), VdotHLdotH, orientedEta.value[0], reflectance); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index 903289827c..482b6220c1 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -93,6 +93,7 @@ struct SSmoothDielectricBxDF; + using monochrome_type = vector; using isotropic_interaction_type = Iso; using anisotropic_interaction_type = Aniso; @@ -122,24 +123,24 @@ struct SSmoothDielectricBxDF) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(bool) transmitted) + sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N, scalar_type NdotV, scalar_type absNdotV, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(bool) transmitted) { - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta.value*orientedEta.value, absNdotV); + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta.value[0]*orientedEta.value[0], absNdotV); scalar_type rcpChoiceProb; transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); ray_dir_info_type L; Refract r = Refract::create(rcpEta, V, N, NdotV); - bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, r); + bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, r, orientedEta.rcp[0]); L.direction = rr(transmitted); return sample_type::create(L, nbl::hlsl::dot(V, L.direction), T, B, N); } sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector) u) { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), eta); - fresnel::OrientedEtaRcps rcpEta = fresnel::OrientedEtaRcps::create(interaction.isotropic.getNdotV(), eta); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), hlsl::promote(eta)); + fresnel::OrientedEtaRcps rcpEta = fresnel::OrientedEtaRcps::create(interaction.isotropic.getNdotV(), hlsl::promote(eta)); scalar_type NdotV = interaction.isotropic.getNdotV(); bool dummy; return __generate_wo_clamps(interaction.isotropic.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.isotropic.getN(), NdotV, @@ -148,8 +149,8 @@ struct SSmoothDielectricBxDF) u) { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), eta); - fresnel::OrientedEtaRcps rcpEta = fresnel::OrientedEtaRcps::create(interaction.isotropic.getNdotV(), eta); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), hlsl::promote(eta)); + fresnel::OrientedEtaRcps rcpEta = fresnel::OrientedEtaRcps::create(interaction.isotropic.getNdotV(), hlsl::promote(eta)); scalar_type NdotV = interaction.isotropic.getNdotV(); bool dummy; return __generate_wo_clamps(interaction.isotropic.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.isotropic.getN(), NdotV, @@ -174,20 +175,20 @@ struct SSmoothDielectricBxDF::isTransmissionPath(params.getNdotVUnclamped(), params.getNdotLUnclamped()); - fresnel::OrientedEtaRcps rcpOrientedEtas = fresnel::OrientedEtaRcps::create(params.getNdotV(), eta); + fresnel::OrientedEtaRcps rcpOrientedEtas = fresnel::OrientedEtaRcps::create(params.getNdotV(), hlsl::promote(eta)); const scalar_type _pdf = bit_cast(numeric_limits::infinity); - scalar_type quo = hlsl::mix(1.0, rcpOrientedEtas.value, transmitted); + scalar_type quo = hlsl::mix(1.0, rcpOrientedEtas.value[0], transmitted); return quotient_pdf_type::create((spectral_type)(quo), _pdf); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(params.getNdotVUnclamped(), params.getNdotLUnclamped()); - fresnel::OrientedEtaRcps rcpOrientedEtas = fresnel::OrientedEtaRcps::create(params.getNdotV(), eta); + fresnel::OrientedEtaRcps rcpOrientedEtas = fresnel::OrientedEtaRcps::create(params.getNdotV(), hlsl::promote(eta)); const scalar_type _pdf = bit_cast(numeric_limits::infinity); - scalar_type quo = hlsl::mix(1.0, rcpOrientedEtas.value, transmitted); + scalar_type quo = hlsl::mix(1.0, rcpOrientedEtas.value[0], transmitted); return quotient_pdf_type::create((spectral_type)(quo), _pdf); } @@ -201,6 +202,7 @@ struct SSmoothDielectricBxDF; + using monochrome_type = vector; using isotropic_interaction_type = Iso; using anisotropic_interaction_type = Aniso; From af22570af3f230c942d109187db96d3f9139d4d5 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 11 Jul 2025 11:29:13 +0700 Subject: [PATCH 113/188] minor corrections to changes yesterday --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 56 ++++++------------ include/nbl/builtin/hlsl/bxdf/fresnel.hlsl | 59 +++++++++++-------- .../hlsl/bxdf/transmission/beckmann.hlsl | 3 +- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 3 +- .../bxdf/transmission/smooth_dielectric.hlsl | 2 +- 5 files changed, 54 insertions(+), 69 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index c3bf426538..2c0c2786dd 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -35,12 +35,7 @@ struct ComputeMicrofacetNormal static ComputeMicrofacetNormal create(NBL_CONST_REF_ARG(vector_type) V, NBL_CONST_REF_ARG(vector_type) L, NBL_CONST_REF_ARG(vector_type) H, scalar_type eta) { - ComputeMicrofacetNormal retval; - retval.V = V; - retval.L = L; - fresnel::OrientedEtas orientedEtas = fresnel::OrientedEtas::create(hlsl::dot(V, H), eta); - retval.orientedEta = orientedEtas.value; - return retval; + return create(V, L, hlsl::dot(V, H), eta); } static ComputeMicrofacetNormal create(NBL_CONST_REF_ARG(vector_type) V, NBL_CONST_REF_ARG(vector_type) L, scalar_type VdotH, scalar_type eta) @@ -91,6 +86,11 @@ struct ComputeMicrofacetNormal return bool((hlsl::bit_cast(NdotV) ^ hlsl::bit_cast(NdotL)) & unsigned_integer_type(1u)<<(sizeof(scalar_type)*8u-1u)); } + static bool isValidMicrofacet(const bool transmitted, const scalar_type VdotL, const scalar_type NdotH, const scalar_type eta, const scalar_type rcp_eta) + { + return !transmitted || (VdotL <= -hlsl::min(eta, rcp_eta) && NdotH >= nbl::hlsl::numeric_limits::min); + } + vector_type V; vector_type L; scalar_type orientedEta; @@ -105,19 +105,17 @@ namespace ray_dir_info #define NBL_CONCEPT_TPLT_PRM_NAMES (T) #define NBL_CONCEPT_PARAM_0 (rdirinfo, T) #define NBL_CONCEPT_PARAM_1 (N, typename T::vector3_type) -#define NBL_CONCEPT_PARAM_2 (dirDotN, typename T::scalar_type) +#define NBL_CONCEPT_PARAM_2 (rcpEta, typename T::scalar_type) #define NBL_CONCEPT_PARAM_3 (m, typename T::matrix3x3_type) #define NBL_CONCEPT_PARAM_4 (rfl, Reflect) #define NBL_CONCEPT_PARAM_5 (rfr, Refract) -#define NBL_CONCEPT_PARAM_6 (backside, bool) -NBL_CONCEPT_BEGIN(7) +NBL_CONCEPT_BEGIN(6) #define rdirinfo NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define N NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 -#define dirDotN NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +#define rcpEta NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 #define m NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 #define rfl NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 #define rfr NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 -#define backside NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) @@ -125,16 +123,15 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.getDirection()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.transmit()), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.reflect(rfl)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.refract(rfr, backside, dirDotN)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.refract(rfr, rcpEta)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.transform(m)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(is_scalar_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(is_vector_v, typename T::vector3_type)) ); -#undef backside #undef rfr #undef rfl #undef m -#undef dirDotN +#undef rcpEta #undef N #undef rdirinfo #include @@ -162,10 +159,10 @@ struct SBasic return retval; } - SBasic refract(NBL_CONST_REF_ARG(Refract) r, const bool backside, scalar_type rcpOrientedEta) + SBasic refract(NBL_CONST_REF_ARG(Refract) r, scalar_type rcpOrientedEta) { SBasic retval; - retval.direction = r(backside, rcpOrientedEta); + retval.direction = r(rcpOrientedEta); return retval; } @@ -426,8 +423,8 @@ struct SLightSample retval.L = L; retval.VdotL = VdotL; - retval.TdotL = nbl::hlsl::numeric_limits::quiet_NaN; - retval.BdotL = nbl::hlsl::numeric_limits::quiet_NaN; + retval.TdotL = bit_cast(numeric_limits::quiet_NaN); + retval.BdotL = bit_cast(numeric_limits::quiet_NaN); retval.NdotL = nbl::hlsl::dot(N,L.getDirection()); retval.NdotL2 = retval.NdotL * retval.NdotL; @@ -483,12 +480,8 @@ struct SLightSample #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) #define NBL_CONCEPT_TPLT_PRM_NAMES (T) #define NBL_CONCEPT_PARAM_0 (cache, T) -#define NBL_CONCEPT_PARAM_1 (pNdotV, typename T::scalar_type) -#define NBL_CONCEPT_PARAM_2 (b0, bool) -NBL_CONCEPT_BEGIN(3) +NBL_CONCEPT_BEGIN(1) #define cache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 -#define pNdotV NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 -#define b0 NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) @@ -496,10 +489,7 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getLdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getNdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getNdotH2()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::isValidMicrofacetCache(b0,pNdotV,pNdotV,pNdotV,pNdotV)), ::nbl::hlsl::is_same_v, bool)) ); -#undef b0 -#undef pNdotV #undef cache #include @@ -581,7 +571,7 @@ struct SIsotropicMicrofacetCache // not coming from the medium (reflected) OR // exiting at the macro scale AND ( (not L outside the cone of possible directions given IoR with constraint VdotH*LdotH<0.0) OR (microfacet not facing toward the macrosurface, i.e. non heightfield profile of microsurface) ) - const bool valid = isValidMicrofacetCache(transmitted, VdotL, retval.NdotH, computeMicrofacetNormal.orientedEta.value, computeMicrofacetNormal.orientedEta.rcp); + const bool valid = ComputeMicrofacetNormal::isValidMicrofacet(transmitted, VdotL, retval.NdotH, computeMicrofacetNormal.orientedEta.value, computeMicrofacetNormal.orientedEta.rcp); if (valid) { retval.VdotH = hlsl::dot(computeMicrofacetNormal.V,H); @@ -589,7 +579,7 @@ struct SIsotropicMicrofacetCache retval.NdotH2 = retval.NdotH * retval.NdotH; } else - retval.NdotH = nbl::hlsl::numeric_limits::quiet_NaN; + retval.NdotH = bit_cast(numeric_limits::quiet_NaN); return retval; } @@ -645,11 +635,6 @@ struct SIsotropicMicrofacetCache return create(interaction,_sample,orientedEtas,dummy); } - static bool isValidMicrofacetCache(const bool transmitted, const scalar_type VdotL, const scalar_type NdotH, const scalar_type eta, const scalar_type rcp_eta) - { - return !transmitted || (VdotL <= -hlsl::min(eta, rcp_eta) && NdotH >= nbl::hlsl::numeric_limits::min); - } - scalar_type getVdotH() NBL_CONST_MEMBER_FUNC { assert(VdotH >= scalar_type(0.0)); @@ -806,11 +791,6 @@ struct SAnisotropicMicrofacetCache return retval; } - static bool isValidMicrofacetCache(const bool transmitted, const scalar_type VdotL, const scalar_type NdotH, const scalar_type eta, const scalar_type rcp_eta) - { - return isocache_type::isValidMicrofacetCache(transmitted, VdotL, NdotH, eta, rcp_eta); - } - scalar_type getVdotH() NBL_CONST_MEMBER_FUNC { return iso_cache.getVdotH(); } scalar_type getLdotH() NBL_CONST_MEMBER_FUNC { return iso_cache.getLdotH(); } scalar_type getNdotH() NBL_CONST_MEMBER_FUNC { return iso_cache.getNdotH(); } diff --git a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl index 25ad3ca705..8f6a9871d2 100644 --- a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl @@ -21,25 +21,6 @@ namespace bxdf namespace fresnel { -template) -struct OrientedEtas -{ - using scalar_type = typename vector_traits::scalar_type; - - static OrientedEtas create(scalar_type NdotI, T eta) - { - OrientedEtas retval; - const bool backside = NdotI < scalar_type(0.0); - const T rcpEta = hlsl::promote(1.0) / eta; - retval.value = backside ? rcpEta : eta; - retval.rcp = backside ? eta : rcpEta; - return retval; - } - - T value; - T rcp; -}; - template) struct OrientedEtaRcps { @@ -72,6 +53,33 @@ struct OrientedEtaRcps T value2; }; +template) +struct OrientedEtas +{ + using scalar_type = typename vector_traits::scalar_type; + + static OrientedEtas create(scalar_type NdotI, T eta) + { + OrientedEtas retval; + const bool backside = NdotI < scalar_type(0.0); + const T rcpEta = hlsl::promote(1.0) / eta; + retval.value = backside ? rcpEta : eta; + retval.rcp = backside ? eta : rcpEta; + return retval; + } + + OrientedEtaRcps getReciprocals() NBL_CONST_MEMBER_FUNC + { + OrientedEtaRcps retval; + retval.value = rcp; + retval.value2 = rcp * rcp; + return retval; + } + + T value; + T rcp; +}; + } template) @@ -122,13 +130,13 @@ struct Refract using monochrome_type = vector; using scalar_type = T; - static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEtas, NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N, const bool backside) + static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEtas, NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N) { this_t retval; retval.I = I; retval.N = N; retval.recomputeNdotI(); - retval.recomputeNdotT(backside, retval.NdotI2, rcpEtas.value2[0]); + retval.recomputeNdotT(retval.NdotI < scalar_type(0.0), rcpEtas.value2[0]); return retval; } @@ -138,16 +146,15 @@ struct Refract NdotI2 = NdotI * NdotI; } - void recomputeNdotT(bool backside, scalar_type _NdotI2, scalar_type rcpOrientedEta2) + void recomputeNdotT(bool backside, scalar_type rcpOrientedEta2) { - scalar_type NdotT2 = rcpOrientedEta2 * _NdotI2 + 1.0 - rcpOrientedEta2; + scalar_type NdotT2 = rcpOrientedEta2 * NdotI2 + 1.0 - rcpOrientedEta2; scalar_type absNdotT = sqrt(NdotT2); - NdotT = ieee754::flipSign(absNdotT, backside); + NdotT = ieee754::copySign(absNdotT, -NdotI); // TODO: make a ieee754::copySignIntoPositive, see https://github.com/Devsh-Graphics-Programming/Nabla/pull/899#discussion_r2197473145 } - vector_type operator()(const bool backside, scalar_type rcpOrientedEta) + vector_type operator()(scalar_type rcpOrientedEta) { - recomputeNdotT(rcpOrientedEta.backside, NdotI2, rcpOrientedEta*rcpOrientedEta); return N * (NdotI * rcpOrientedEta + NdotT) - rcpOrientedEta * I; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 249e04f847..6e877fcdc7 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -185,8 +185,7 @@ struct SBeckmannDielectricBxDF cache = anisocache_type::createForReflection(localV, H); const scalar_type VdotH = cache.iso_cache.getVdotH(); - Refract r; - r.recomputeNdotT(VdotH < 0.0, VdotH * VdotH, rcpEta.value2[0]); + Refract r = Refract::create(rcpEta, localV, H); cache.iso_cache.LdotH = hlsl::mix(VdotH, r.NdotT, transmitted); ray_dir_info_type localL; bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, localV, H, VdotH, cache.iso_cache.getLdotH(), rcpEta.value[0]); diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 8074d4b9eb..226b0589af 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -188,8 +188,7 @@ struct SGGXDielectricBxDF cache = anisocache_type::createForReflection(localV, H); const scalar_type VdotH = cache.iso_cache.getVdotH(); - Refract r; - r.recomputeNdotT(VdotH < 0.0, VdotH * VdotH, rcpEta.value2[0]); + Refract r = Refract::create(rcpEta, localV, H); cache.iso_cache.LdotH = hlsl::mix(VdotH, r.NdotT, transmitted); ray_dir_info_type localL; bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, localV, H, VdotH, cache.iso_cache.getLdotH(), rcpEta.value[0]); diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index 482b6220c1..17bf95968c 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -131,7 +131,7 @@ struct SSmoothDielectricBxDF r = Refract::create(rcpEta, V, N, NdotV); + Refract r = Refract::create(rcpEta, V, N); bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, r, orientedEta.rcp[0]); L.direction = rr(transmitted); return sample_type::create(L, nbl::hlsl::dot(V, L.direction), T, B, N); From 21292a7a7439acf0a0ae4dc8eb4be0203688af9b Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 11 Jul 2025 12:21:58 +0700 Subject: [PATCH 114/188] changes to fresnel structs template requirements --- include/nbl/builtin/hlsl/bxdf/fresnel.hlsl | 40 +++++++++++-------- .../hlsl/bxdf/transmission/beckmann.hlsl | 20 +++++----- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 20 +++++----- .../bxdf/transmission/smooth_dielectric.hlsl | 4 +- 4 files changed, 46 insertions(+), 38 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl index 8f6a9871d2..a588f71d5c 100644 --- a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl @@ -172,24 +172,22 @@ struct ReflectRefract using vector_type = vector; using scalar_type = T; - static this_t create(bool r, NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N, scalar_type NdotI, scalar_type NdotTorR, scalar_type rcpOrientedEta) + static this_t create(NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N, scalar_type NdotI, scalar_type rcpOrientedEta) { this_t retval; retval.I = I; retval.N = N; retval.NdotI = NdotI; - retval.NdotTorR = NdotTorR; retval.rcpOrientedEta = rcpOrientedEta; return retval; } - static this_t create(bool r, NBL_CONST_REF_ARG(Refract) refract, scalar_type rcpOrientedEta) + static this_t create(NBL_CONST_REF_ARG(Refract) refract, scalar_type rcpOrientedEta) { this_t retval; retval.I = refract.I; retval.N = refract.N; retval.NdotI = refract.NdotI; - retval.NdotTorR = hlsl::mix(refract.NdotI, refract.NdotT, r); retval.rcpOrientedEta = rcpOrientedEta; return retval; } @@ -197,25 +195,35 @@ struct ReflectRefract // when you know you'll reflect void recomputeNdotR() { - refract.recomputeNdotI(); + _refract.recomputeNdotI(); + NdotI = _refract.NdotI; } // when you know you'll refract void recomputeNdotT(bool backside, scalar_type _NdotI2, scalar_type rcpOrientedEta2) { - refract.recomputeNdotT(backside, _NdotI2, rcpOrientedEta2); + _refract.recomputeNdotT(backside, _NdotI2, rcpOrientedEta2); + } + + vector_type reflect() + { + return N * NdotI * 2.0f - I; + } + + vector_type refract() + { + return N * (NdotI * rcpOrientedEta + _refract.NdotT) - I * rcpOrientedEta; } vector_type operator()(const bool doRefract) { - return N * (NdotI * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)) + NdotTorR) - I * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)); + return N * (NdotI * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)) + hlsl::mix(NdotI, _refract.NdotT, doRefract)) - I * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)); } - Refract refract; + Refract _refract; vector_type I; vector_type N; scalar_type NdotI; - scalar_type NdotTorR; scalar_type rcpOrientedEta; }; @@ -223,7 +231,7 @@ struct ReflectRefract namespace fresnel { -template || concepts::FloatingPointLikeVectorial) +template) struct Schlick { using scalar_type = typename vector_traits::scalar_type; @@ -239,7 +247,7 @@ struct Schlick T operator()() { assert(clampedCosTheta > scalar_type(0.0)); - assert(hlsl::promote(0.02) < F0 && F0 <= hlsl::promote(1.0)); + assert(hlsl::all(hlsl::promote(0.02) < F0 && F0 <= hlsl::promote(1.0))); T x = 1.0 - clampedCosTheta; return F0 + (1.0 - F0) * x*x*x*x*x; } @@ -248,7 +256,7 @@ struct Schlick scalar_type clampedCosTheta; }; -template || concepts::FloatingPointLikeVectorial) +template) struct Conductor { using scalar_type = typename vector_traits::scalar_type; @@ -268,7 +276,7 @@ struct Conductor //const float sinTheta2 = 1.0 - cosTheta2; const T etaLen2 = eta * eta + etak2; - assert(hlsl::any(etaLen2 > hlsl::promote(hlsl::exp2(-numeric_limits::digits)))); + assert(hlsl::all(etaLen2 > hlsl::promote(hlsl::exp2(-numeric_limits::digits)))); const T etaCosTwice = eta * clampedCosTheta * 2.0f; const T rs_common = etaLen2 + (T)(cosTheta2); @@ -285,7 +293,7 @@ struct Conductor scalar_type clampedCosTheta; }; -template || concepts::FloatingPointLikeVectorial) +template) struct Dielectric { using scalar_type = typename vector_traits::scalar_type; @@ -323,7 +331,7 @@ struct Dielectric scalar_type absCosTheta; }; -template || concepts::FloatingPointLikeVectorial) +template) struct DielectricFrontFaceOnly { using scalar_type = typename vector_traits::scalar_type; @@ -347,7 +355,7 @@ struct DielectricFrontFaceOnly // gets the sum of all R, T R T, T R^3 T, T R^5 T, ... paths -template) +template || concepts::FloatingPointLikeVectorial) T thinDielectricInfiniteScatter(const T singleInterfaceReflectance) { const T doubleInterfaceReflectance = singleInterfaceReflectance * singleInterfaceReflectance; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 6e877fcdc7..40e8f7d711 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -140,7 +140,7 @@ struct SBeckmannDielectricBxDF spectral_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) { fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); - const scalar_type orientedEta2 = orientedEta.value[0] * orientedEta.value[0]; + const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); const bool transmitted = VdotHLdotH < 0.0; @@ -152,13 +152,13 @@ struct SBeckmannDielectricBxDF ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,params.getNdotV(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); - scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH())); + scalar_type f = fresnel::Dielectric::__call(orientedEta2, hlsl::abs(params.getVdotH()))[0]; return hlsl::promote(f) * microfacet_transform(); } spectral_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) { fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); - const scalar_type orientedEta2 = orientedEta.value[0] * orientedEta.value[0]; + const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); const bool transmitted = VdotHLdotH < 0.0; @@ -170,14 +170,14 @@ struct SBeckmannDielectricBxDF ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,params.getNdotV(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); - scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH())); + scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; return hlsl::promote(f) * microfacet_transform(); } sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) localV, NBL_CONST_REF_ARG(vector3_type) H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(anisocache_type) cache) { const scalar_type localVdotH = nbl::hlsl::dot(localV,H); - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta.value[0] * orientedEta.value[0],nbl::hlsl::abs(localVdotH)); + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta.value * orientedEta.value,nbl::hlsl::abs(localVdotH))[0]; scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); @@ -188,7 +188,7 @@ struct SBeckmannDielectricBxDF Refract r = Refract::create(rcpEta, localV, H); cache.iso_cache.LdotH = hlsl::mix(VdotH, r.NdotT, transmitted); ray_dir_info_type localL; - bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, localV, H, VdotH, cache.iso_cache.getLdotH(), rcpEta.value[0]); + bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(localV, H, VdotH, rcpEta.value[0]); localL.direction = rr(transmitted); return sample_type::createFromTangentSpace(localV, localL, m); @@ -227,12 +227,12 @@ struct SBeckmannDielectricBxDF scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); - const scalar_type orientedEta2 = orientedEta.value[0] * orientedEta.value[0]; + const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH())); + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; scalar_type ndf, lambda; const scalar_type a2 = A.x*A.x; @@ -252,12 +252,12 @@ struct SBeckmannDielectricBxDF scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); - const scalar_type orientedEta2 = orientedEta.value[0] * orientedEta.value[0]; + const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH())); + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; scalar_type ndf, lambda; const scalar_type ax2 = A.x*A.x; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 226b0589af..9e9f406124 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -139,7 +139,7 @@ struct SGGXDielectricBxDF spectral_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) { fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); - const scalar_type orientedEta2 = orientedEta.value[0] * orientedEta.value[0]; + const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); @@ -153,13 +153,13 @@ struct SGGXDielectricBxDF ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,params.getNdotL(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); - scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH())); + scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; return hlsl::promote(f) * microfacet_transform(); } spectral_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) { fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); - const scalar_type orientedEta2 = orientedEta.value[0] * orientedEta.value[0]; + const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); @@ -173,14 +173,14 @@ struct SGGXDielectricBxDF ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,params.getNdotL(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); - scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH())); + scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; return hlsl::promote(f) * microfacet_transform(); } sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) localV, NBL_CONST_REF_ARG(vector3_type) H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(anisocache_type) cache) { const scalar_type localVdotH = nbl::hlsl::dot(localV,H); - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta.value[0] * orientedEta.value[0],nbl::hlsl::abs(localVdotH)); + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta.value * orientedEta.value,nbl::hlsl::abs(localVdotH))[0]; scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); @@ -191,7 +191,7 @@ struct SGGXDielectricBxDF Refract r = Refract::create(rcpEta, localV, H); cache.iso_cache.LdotH = hlsl::mix(VdotH, r.NdotT, transmitted); ray_dir_info_type localL; - bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, localV, H, VdotH, cache.iso_cache.getLdotH(), rcpEta.value[0]); + bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(localV, H, VdotH, rcpEta.value[0]); localL.direction = rr(transmitted); return sample_type::createFromTangentSpace(localV, localL, m); @@ -230,12 +230,12 @@ struct SGGXDielectricBxDF scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) { fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); - const scalar_type orientedEta2 = orientedEta.value[0] * orientedEta.value[0]; + const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH())); + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; scalar_type ndf, devsh_v; const scalar_type a2 = A.x*A.x; @@ -253,12 +253,12 @@ struct SGGXDielectricBxDF scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); - const scalar_type orientedEta2 = orientedEta.value[0] * orientedEta.value[0]; + const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); const bool transmitted = VdotHLdotH < 0.0; - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH())); + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; scalar_type ndf, devsh_v; const scalar_type ax2 = A.x*A.x; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index 17bf95968c..4a32d3090a 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -125,14 +125,14 @@ struct SSmoothDielectricBxDF) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(bool) transmitted) { - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta.value[0]*orientedEta.value[0], absNdotV); + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta.value*orientedEta.value, absNdotV)[0]; scalar_type rcpChoiceProb; transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); ray_dir_info_type L; Refract r = Refract::create(rcpEta, V, N); - bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(transmitted, r, orientedEta.rcp[0]); + bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(r, orientedEta.rcp[0]); L.direction = rr(transmitted); return sample_type::create(L, nbl::hlsl::dot(V, L.direction), T, B, N); } From 772e6a7e8a385042d94ab1ceb88caea4dc21a8fa Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 14 Jul 2025 11:50:42 +0700 Subject: [PATCH 115/188] more changes to reflect/refract usage, moved ComputeMicrofacetNormal into fresnel --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 75 +-------- include/nbl/builtin/hlsl/bxdf/fresnel.hlsl | 155 ++++++++++++------ .../hlsl/bxdf/reflection/beckmann.hlsl | 4 +- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 4 +- .../hlsl/bxdf/transmission/beckmann.hlsl | 6 +- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 6 +- .../bxdf/transmission/smooth_dielectric.hlsl | 2 +- 7 files changed, 121 insertions(+), 131 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 2c0c2786dd..be96dead88 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -24,79 +24,6 @@ namespace hlsl namespace bxdf { -template) -struct ComputeMicrofacetNormal -{ - using scalar_type = T; - using vector_type = vector; - using monochrome_type = vector; - - using unsigned_integer_type = typename unsigned_integer_of_size::type; - - static ComputeMicrofacetNormal create(NBL_CONST_REF_ARG(vector_type) V, NBL_CONST_REF_ARG(vector_type) L, NBL_CONST_REF_ARG(vector_type) H, scalar_type eta) - { - return create(V, L, hlsl::dot(V, H), eta); - } - - static ComputeMicrofacetNormal create(NBL_CONST_REF_ARG(vector_type) V, NBL_CONST_REF_ARG(vector_type) L, scalar_type VdotH, scalar_type eta) - { - ComputeMicrofacetNormal retval; - retval.V = V; - retval.L = L; - fresnel::OrientedEtas orientedEtas = fresnel::OrientedEtas::create(VdotH, eta); - retval.orientedEta = orientedEtas.value; - return retval; - } - - // NDFs are defined in terms of `abs(NdotH)` and microfacets are two sided. Note that `N` itself is the definition of the upper hemisphere direction. - // The possible directions of L form a cone around -V with the cosine of the angle equal higher or equal to min(orientedEta, 1.f/orientedEta), and vice versa. - // This means that for: - // - Eta>1 the L will be longer than V projected on V, and VdotH<0 for all L - // - whereas with Eta<1 the L is shorter, and VdotH>0 for all L - // Because to be a refraction `VdotH` and `LdotH` must differ in sign, so whenever one is positive the other is negative. - // Since we're considering single scattering, the V and L must enter the microfacet described by H same way they enter the macro-medium described by N. - // All this means that by looking at the sign of VdotH we can also tell the sign of VdotN. - // However the whole `V+L*eta` formula is backwards because what it should be is `-V-L*eta` so the sign flip is applied just to restore the H-finding to that value. - - // The math: - // dot(V,H) = V2 + VdotL*eta = 1 + VdotL*eta, note that VdotL<=1 so VdotH>=0 when eta==1 - // then with valid transmission path constraint: - // VdotH <= 1-orientedEta2 for orientedEta<1 -> VdotH<0 - // VdotH <= 0 for orientedEta>1 - // so for transmission VdotH<=0, H needs to be flipped to be consistent with oriented eta - vector_type unnormalized(const bool _refract) - { - assert(hlsl::dot(V, L) <= -hlsl::min(orientedEta, scalar_type(1.0) / orientedEta)); - const scalar_type etaFactor = hlsl::mix(scalar_type(1.0), orientedEta.value, _refract); - vector_type tmpH = V + L * etaFactor; - tmpH = ieee754::flipSign(tmpH, _refract); - return tmpH; - } - - // returns normalized vector, but NaN when result is length 0 - vector_type normalized(const bool _refract) - { - const vector_type H = unnormalized(_refract); - return hlsl::normalize(H); - } - - // if V and L are on different sides of the surface normal, then their dot product sign bits will differ, hence XOR will yield 1 at last bit - static bool isTransmissionPath(scalar_type NdotV, scalar_type NdotL) - { - return bool((hlsl::bit_cast(NdotV) ^ hlsl::bit_cast(NdotL)) & unsigned_integer_type(1u)<<(sizeof(scalar_type)*8u-1u)); - } - - static bool isValidMicrofacet(const bool transmitted, const scalar_type VdotL, const scalar_type NdotH, const scalar_type eta, const scalar_type rcp_eta) - { - return !transmitted || (VdotL <= -hlsl::min(eta, rcp_eta) && NdotH >= nbl::hlsl::numeric_limits::min); - } - - vector_type V; - vector_type L; - scalar_type orientedEta; -}; - - namespace ray_dir_info { @@ -571,7 +498,7 @@ struct SIsotropicMicrofacetCache // not coming from the medium (reflected) OR // exiting at the macro scale AND ( (not L outside the cone of possible directions given IoR with constraint VdotH*LdotH<0.0) OR (microfacet not facing toward the macrosurface, i.e. non heightfield profile of microsurface) ) - const bool valid = ComputeMicrofacetNormal::isValidMicrofacet(transmitted, VdotL, retval.NdotH, computeMicrofacetNormal.orientedEta.value, computeMicrofacetNormal.orientedEta.rcp); + const bool valid = ComputeMicrofacetNormal::isValidMicrofacet(transmitted, VdotL, retval.NdotH, computeMicrofacetNormal.orientedEta); if (valid) { retval.VdotH = hlsl::dot(computeMicrofacetNormal.V,H); diff --git a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl index a588f71d5c..9257b9b2cc 100644 --- a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl @@ -82,6 +82,80 @@ struct OrientedEtas } + +template) +struct ComputeMicrofacetNormal +{ + using scalar_type = T; + using vector_type = vector; + using monochrome_type = vector; + + using unsigned_integer_type = typename unsigned_integer_of_size::type; + + static ComputeMicrofacetNormal create(NBL_CONST_REF_ARG(vector_type) V, NBL_CONST_REF_ARG(vector_type) L, NBL_CONST_REF_ARG(vector_type) H, scalar_type eta) + { + return create(V, L, hlsl::dot(V, H), eta); + } + + static ComputeMicrofacetNormal create(NBL_CONST_REF_ARG(vector_type) V, NBL_CONST_REF_ARG(vector_type) L, scalar_type VdotH, scalar_type eta) + { + ComputeMicrofacetNormal retval; + retval.V = V; + retval.L = L; + fresnel::OrientedEtas orientedEtas = fresnel::OrientedEtas::create(VdotH, eta); + retval.orientedEta = orientedEtas.value; + return retval; + } + + // NDFs are defined in terms of `abs(NdotH)` and microfacets are two sided. Note that `N` itself is the definition of the upper hemisphere direction. + // The possible directions of L form a cone around -V with the cosine of the angle equal higher or equal to min(orientedEta, 1.f/orientedEta), and vice versa. + // This means that for: + // - Eta>1 the L will be longer than V projected on V, and VdotH<0 for all L + // - whereas with Eta<1 the L is shorter, and VdotH>0 for all L + // Because to be a refraction `VdotH` and `LdotH` must differ in sign, so whenever one is positive the other is negative. + // Since we're considering single scattering, the V and L must enter the microfacet described by H same way they enter the macro-medium described by N. + // All this means that by looking at the sign of VdotH we can also tell the sign of VdotN. + // However the whole `V+L*eta` formula is backwards because what it should be is `-V-L*eta` so the sign flip is applied just to restore the H-finding to that value. + + // The math: + // dot(V,H) = V2 + VdotL*eta = 1 + VdotL*eta, note that VdotL<=1 so VdotH>=0 when eta==1 + // then with valid transmission path constraint: + // VdotH <= 1-orientedEta2 for orientedEta<1 -> VdotH<0 + // VdotH <= 0 for orientedEta>1 + // so for transmission VdotH<=0, H needs to be flipped to be consistent with oriented eta + vector_type unnormalized(const bool _refract) + { + assert(hlsl::dot(V, L) <= -hlsl::min(orientedEta, scalar_type(1.0) / orientedEta)); + const scalar_type etaFactor = hlsl::mix(scalar_type(1.0), orientedEta.value, _refract); + vector_type tmpH = V + L * etaFactor; + tmpH = ieee754::flipSign(tmpH, _refract); + return tmpH; + } + + // returns normalized vector, but NaN when result is length 0 + vector_type normalized(const bool _refract) + { + const vector_type H = unnormalized(_refract); + return hlsl::normalize(H); + } + + // if V and L are on different sides of the surface normal, then their dot product sign bits will differ, hence XOR will yield 1 at last bit + static bool isTransmissionPath(scalar_type NdotV, scalar_type NdotL) + { + return bool((hlsl::bit_cast(NdotV) ^ hlsl::bit_cast(NdotL)) & unsigned_integer_type(1u)<<(sizeof(scalar_type)*8u-1u)); + } + + static bool isValidMicrofacet(const bool transmitted, const scalar_type VdotL, const scalar_type NdotH, NBL_CONST_REF_ARG(fresnel::OrientedEtas >) orientedEta) + { + return !transmitted || (VdotL <= -hlsl::min(orientedEta.value, orientedEta.rcp) && NdotH >= nbl::hlsl::numeric_limits::min); + } + + vector_type V; + vector_type L; + scalar_type orientedEta; +}; + + template) struct Reflect { @@ -89,37 +163,31 @@ struct Reflect using vector_type = vector; using scalar_type = T; - static this_t create(NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N, scalar_type NdotI) + static this_t create(NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N) { this_t retval; retval.I = I; retval.N = N; - retval.NdotI = NdotI; return retval; } - static this_t create(NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N) + scalar_type getNdotI() { - this_t retval; - retval.I = I; - retval.N = N; - retval.recomputeNdotI(); - return retval; + return hlsl::dot(N, I); } - void recomputeNdotI() + vector_type operator()() { - NdotI = hlsl::dot(N, I); + return N * 2.0f * getNdotI() - I; } - vector_type operator()() + vector_type operator()(const scalar_type NdotI) { return N * 2.0f * NdotI - I; } vector_type I; vector_type N; - scalar_type NdotI; }; template) @@ -130,39 +198,39 @@ struct Refract using monochrome_type = vector; using scalar_type = T; - static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEtas, NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N) + static this_t create(NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N) { this_t retval; retval.I = I; retval.N = N; - retval.recomputeNdotI(); - retval.recomputeNdotT(retval.NdotI < scalar_type(0.0), rcpEtas.value2[0]); return retval; } - void recomputeNdotI() + scalar_type getNdotI() { - NdotI = hlsl::dot(N, I); - NdotI2 = NdotI * NdotI; + return hlsl::dot(N, I); } - void recomputeNdotT(bool backside, scalar_type rcpOrientedEta2) + scalar_type getNdotT(const scalar_type rcpOrientedEta2) { - scalar_type NdotT2 = rcpOrientedEta2 * NdotI2 + 1.0 - rcpOrientedEta2; + scalar_type NdotI = getNdotI(); + scalar_type NdotT2 = rcpOrientedEta2 * NdotI*NdotI + 1.0 - rcpOrientedEta2; scalar_type absNdotT = sqrt(NdotT2); - NdotT = ieee754::copySign(absNdotT, -NdotI); // TODO: make a ieee754::copySignIntoPositive, see https://github.com/Devsh-Graphics-Programming/Nabla/pull/899#discussion_r2197473145 + return ieee754::copySign(absNdotT, -NdotI); // TODO: make a ieee754::copySignIntoPositive, see https://github.com/Devsh-Graphics-Programming/Nabla/pull/899#discussion_r2197473145 + } + + vector_type operator()(const scalar_type rcpOrientedEta) + { + return N * (getNdotI() * rcpOrientedEta + getNdotT(rcpOrientedEta*rcpOrientedEta)) - rcpOrientedEta * I; } - vector_type operator()(scalar_type rcpOrientedEta) + vector_type operator()(const scalar_type rcpOrientedEta, const scalar_type NdotI, const scalar_type NdotT) { return N * (NdotI * rcpOrientedEta + NdotT) - rcpOrientedEta * I; } vector_type I; vector_type N; - scalar_type NdotT; - scalar_type NdotI; - scalar_type NdotI2; }; template) @@ -172,12 +240,10 @@ struct ReflectRefract using vector_type = vector; using scalar_type = T; - static this_t create(NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N, scalar_type NdotI, scalar_type rcpOrientedEta) + static this_t create(NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N, scalar_type rcpOrientedEta) { this_t retval; - retval.I = I; - retval.N = N; - retval.NdotI = NdotI; + retval._refract = Refract::create(I, N); retval.rcpOrientedEta = rcpOrientedEta; return retval; } @@ -185,45 +251,42 @@ struct ReflectRefract static this_t create(NBL_CONST_REF_ARG(Refract) refract, scalar_type rcpOrientedEta) { this_t retval; - retval.I = refract.I; - retval.N = refract.N; - retval.NdotI = refract.NdotI; + retval._refract = refract; retval.rcpOrientedEta = rcpOrientedEta; return retval; } // when you know you'll reflect - void recomputeNdotR() + scalar_type getNdotR() { - _refract.recomputeNdotI(); - NdotI = _refract.NdotI; + return _refract.getNdotI(); } // when you know you'll refract - void recomputeNdotT(bool backside, scalar_type _NdotI2, scalar_type rcpOrientedEta2) + scalar_type getNdotT() { - _refract.recomputeNdotT(backside, _NdotI2, rcpOrientedEta2); + return _refract.getNdotT(rcpOrientedEta*rcpOrientedEta); } - vector_type reflect() + scalar_type getNdotTorR(const bool doRefract) { - return N * NdotI * 2.0f - I; + return hlsl::mix(getNdotR(), getNdotT(), doRefract); } - vector_type refract() + vector_type operator()(const bool doRefract) { - return N * (NdotI * rcpOrientedEta + _refract.NdotT) - I * rcpOrientedEta; + scalar_type NdotI = getNdotR(); + return _refract.N * (NdotI * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)) + hlsl::mix(NdotI, getNdotT(), doRefract)) - _refract.I * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)); } - vector_type operator()(const bool doRefract) + vector_type operator()(const scalar_type NdotTorR) { - return N * (NdotI * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)) + hlsl::mix(NdotI, _refract.NdotT, doRefract)) - I * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)); + scalar_type NdotI = getNdotR(); + bool doRefract = ComputeMicrofacetNormal::isTransmissionPath(NdotI, NdotTorR); + return _refract.N * (NdotI * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)) + hlsl::mix(NdotI, NdotTorR, doRefract)) - _refract.I * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)); } Refract _refract; - vector_type I; - vector_type N; - scalar_type NdotI; scalar_type rcpOrientedEta; }; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index d8a4c3c3c5..a3ea96694f 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -268,8 +268,8 @@ struct SBeckmannBxDF cache = anisocache_type::createForReflection(localV, H); ray_dir_info_type localL; - bxdf::Reflect r = bxdf::Reflect::create(localV, H, cache.iso_cache.getVdotH()); - localL.direction = r(); + bxdf::Reflect r = bxdf::Reflect::create(localV, H); + localL.direction = r(cache.iso_cache.getVdotH()); return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index afa87765c6..d5d749e5fc 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -223,8 +223,8 @@ struct SGGXBxDF cache = anisocache_type::createForReflection(localV, H); ray_dir_info_type localL; - bxdf::Reflect r = bxdf::Reflect::create(localV, H, cache.iso_cache.getVdotH()); - localL.direction = r(); + bxdf::Reflect r = bxdf::Reflect::create(localV, H); + localL.direction = r(cache.iso_cache.getVdotH()); return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 40e8f7d711..ca4089f727 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -185,10 +185,10 @@ struct SBeckmannDielectricBxDF cache = anisocache_type::createForReflection(localV, H); const scalar_type VdotH = cache.iso_cache.getVdotH(); - Refract r = Refract::create(rcpEta, localV, H); - cache.iso_cache.LdotH = hlsl::mix(VdotH, r.NdotT, transmitted); + Refract r = Refract::create(localV, H); + cache.iso_cache.LdotH = hlsl::mix(VdotH, r.getNdotT(rcpEta.value2[0]), transmitted); ray_dir_info_type localL; - bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(localV, H, VdotH, rcpEta.value[0]); + bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(localV, H, rcpEta.value[0]); localL.direction = rr(transmitted); return sample_type::createFromTangentSpace(localV, localL, m); diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 9e9f406124..08e53c619e 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -188,10 +188,10 @@ struct SGGXDielectricBxDF cache = anisocache_type::createForReflection(localV, H); const scalar_type VdotH = cache.iso_cache.getVdotH(); - Refract r = Refract::create(rcpEta, localV, H); - cache.iso_cache.LdotH = hlsl::mix(VdotH, r.NdotT, transmitted); + Refract r = Refract::create(localV, H); + cache.iso_cache.LdotH = hlsl::mix(VdotH, r.getNdotT(rcpEta.value2[0]), transmitted); ray_dir_info_type localL; - bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(localV, H, VdotH, rcpEta.value[0]); + bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(localV, H, rcpEta.value[0]); localL.direction = rr(transmitted); return sample_type::createFromTangentSpace(localV, localL, m); diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index 4a32d3090a..71cbd4dfa2 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -131,7 +131,7 @@ struct SSmoothDielectricBxDF r = Refract::create(rcpEta, V, N); + Refract r = Refract::create(V, N); bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(r, orientedEta.rcp[0]); L.direction = rr(transmitted); return sample_type::create(L, nbl::hlsl::dot(V, L.direction), T, B, N); From 52fb1fc90faab3b9725d3c274381c5222b426951 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 15 Jul 2025 15:38:51 +0700 Subject: [PATCH 116/188] restructured NDF + geom smith --- include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl | 398 ------------------ include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 153 +------ .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 169 ++++++++ include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 163 +++++++ .../hlsl/bxdf/reflection/beckmann.hlsl | 60 +-- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 56 +-- .../hlsl/bxdf/reflection/lambertian.hlsl | 1 - .../hlsl/bxdf/reflection/oren_nayar.hlsl | 1 - .../hlsl/bxdf/transmission/beckmann.hlsl | 42 +- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 40 +- .../bxdf/transmission/smooth_dielectric.hlsl | 1 - 11 files changed, 415 insertions(+), 669 deletions(-) delete mode 100644 include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl create mode 100644 include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl create mode 100644 include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl diff --git a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl b/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl deleted file mode 100644 index b578ec40b9..0000000000 --- a/include/nbl/builtin/hlsl/bxdf/geom_smith.hlsl +++ /dev/null @@ -1,398 +0,0 @@ -// Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O. -// This file is part of the "Nabla Engine". -// For conditions of distribution and use, see copyright notice in nabla.h -#ifndef _NBL_BUILTIN_HLSL_BXDF_GEOM_INCLUDED_ -#define _NBL_BUILTIN_HLSL_BXDF_GEOM_INCLUDED_ - -#include "nbl/builtin/hlsl/bxdf/ndf.hlsl" - -namespace nbl -{ -namespace hlsl -{ -namespace bxdf -{ -namespace smith -{ - -namespace brdf -{ - -template -struct VNDF_pdf; - -template -struct VNDF_pdf > -{ - using scalar_type = T; - using ndf_type = ndf::Beckmann; - using this_t = VNDF_pdf; - - static this_t create(scalar_type ndf, scalar_type maxNdotV) - { - this_t retval; - retval.ndf = ndf; - retval.maxNdotV = maxNdotV; - return retval; - } - - scalar_type operator()(scalar_type lambda_V) - { - onePlusLambda_V = 1.0 + lambda_V; - ndf::microfacet_to_light_measure_transform transform = ndf::microfacet_to_light_measure_transform::create(ndf / onePlusLambda_V, maxNdotV); - return transform(); - } - - scalar_type ndf; - scalar_type maxNdotV; - scalar_type onePlusLambda_V; -}; - -template -struct VNDF_pdf > -{ - using scalar_type = T; - using ndf_type = ndf::GGX; - using this_t = VNDF_pdf; - - static this_t create(scalar_type ndf, scalar_type maxNdotV) - { - this_t retval; - retval.ndf = ndf; - retval.maxNdotV = maxNdotV; - return retval; - } - - scalar_type operator()(scalar_type G1_over_2NdotV) - { - return ndf * 0.5 * G1_over_2NdotV; - } - - scalar_type ndf; - scalar_type maxNdotV; - scalar_type onePlusLambda_V; -}; - -} - -namespace bsdf -{ - -template) -struct FVNDF_pdf -{ - static FVNDF_pdf create(T fresnel_ndf, T absNdotV) - { - FVNDF_pdf retval; - retval.fresnel_ndf = fresnel_ndf; - retval.absNdotV = absNdotV; - return retval; - } - - T operator()(T G1_over_2NdotV, bool transmitted, T VdotH, T LdotH, T VdotHLdotH, T orientedEta) - { - T FNG = fresnel_ndf * G1_over_2NdotV; - T factor = 0.5; - if (transmitted) - { - const T VdotH_etaLdotH = (VdotH + orientedEta * LdotH); - // VdotHLdotH is negative under transmission, so this factor is negative - factor *= -2.0 * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); - } - return FNG * factor; - } - - T fresnel_ndf; - T absNdotV; -}; - -template -struct VNDF_pdf; - -template -struct VNDF_pdf > -{ - using scalar_type = T; - using ndf_type = ndf::Beckmann; - using this_t = VNDF_pdf; - - static this_t create(scalar_type ndf, scalar_type absNdotV) - { - this_t retval; - retval.ndf = ndf; - retval.absNdotV = absNdotV; - return retval; - } - - scalar_type operator()(scalar_type lambda_V, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, scalar_type reflectance) - { - onePlusLambda_V = 1.0 + lambda_V; - ndf::microfacet_to_light_measure_transform transform - = ndf::microfacet_to_light_measure_transform::create(hlsl::mix(reflectance, scalar_type(1.0) - reflectance, transmitted) * ndf / onePlusLambda_V, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); - return transform(); - } - - scalar_type ndf; - scalar_type absNdotV; - scalar_type onePlusLambda_V; -}; - -template -struct VNDF_pdf > -{ - using scalar_type = T; - using ndf_type = ndf::GGX; - using this_t = VNDF_pdf; - - static this_t create(scalar_type ndf, scalar_type absNdotV) - { - this_t retval; - retval.ndf = ndf; - retval.absNdotV = absNdotV; - return retval; - } - - scalar_type operator()(scalar_type G1_over_2NdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, scalar_type reflectance) - { - scalar_type FN = hlsl::mix(reflectance, scalar_type(1.0) - reflectance, transmitted) * ndf; - FVNDF_pdf fvndf = FVNDF_pdf::create(FN, absNdotV); - return fvndf(G1_over_2NdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); - } - - scalar_type ndf; - scalar_type absNdotV; - scalar_type onePlusLambda_V; -}; - -} - - -template) -struct SIsotropicParams -{ - using this_t = SIsotropicParams; - - static this_t create(T a2, T NdotV2, T NdotL2, T lambdaV_plus_one) // beckmann - { - this_t retval; - retval.a2 = a2; - retval.NdotV2 = NdotV2; - retval.NdotL2 = NdotL2; - retval.lambdaV_plus_one = lambdaV_plus_one; - return retval; - } - - static this_t create(T a2, T NdotV, T NdotV2, T NdotL, T NdotL2) // ggx - { - this_t retval; - retval.a2 = a2; - retval.NdotV = NdotV; - retval.NdotV2 = NdotV2; - retval.NdotL = NdotL; - retval.NdotL2 = NdotL2; - retval.one_minus_a2 = 1.0 - a2; - return retval; - } - - T a2; - T NdotV; - T NdotL; - T NdotV2; - T NdotL2; - T lambdaV_plus_one; - T one_minus_a2; -}; - -template) -struct SAnisotropicParams -{ - using this_t = SAnisotropicParams; - - static this_t create(T ax2, T ay2, T TdotV2, T BdotV2, T NdotV2, T TdotL2, T BdotL2, T NdotL2, T lambdaV_plus_one) // beckmann - { - this_t retval; - retval.ax2 = ax2; - retval.ay2 = ay2; - retval.TdotV2 = TdotV2; - retval.BdotV2 = BdotV2; - retval.NdotV2 = NdotV2; - retval.TdotL2 = TdotL2; - retval.BdotL2 = BdotL2; - retval.NdotL2 = NdotL2; - retval.lambdaV_plus_one = lambdaV_plus_one; - return retval; - } - - static this_t create(T ax2, T ay2, T NdotV, T TdotV2, T BdotV2, T NdotV2, T NdotL, T TdotL2, T BdotL2, T NdotL2) // ggx - { - this_t retval; - retval.ax2 = ax2; - retval.ay2 = ay2; - retval.NdotL = NdotL; - retval.NdotV = NdotV; - retval.TdotV2 = TdotV2; - retval.BdotV2 = BdotV2; - retval.NdotV2 = NdotV2; - retval.TdotL2 = TdotL2; - retval.BdotL2 = BdotL2; - retval.NdotL2 = NdotL2; - return retval; - } - - T ax2; - T ay2; - T NdotV; - T NdotL; - T TdotV2; - T BdotV2; - T NdotV2; - T TdotL2; - T BdotL2; - T NdotL2; - T lambdaV_plus_one; -}; - - -// beckmann -template) -struct Beckmann -{ - using scalar_type = T; - - scalar_type G1(scalar_type lambda) - { - return 1.0 / (1.0 + lambda); - } - - scalar_type C2(scalar_type NdotX2, scalar_type a2) - { - return NdotX2 / (a2 * (1.0 - NdotX2)); - } - - scalar_type C2(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2, scalar_type ax2, scalar_type ay2) - { - return NdotX2 / (TdotX2 * ax2 + BdotX2 * ay2); - } - - scalar_type Lambda(scalar_type c2) - { - scalar_type c = sqrt(c2); - scalar_type nom = 1.0 - 1.259 * c + 0.396 * c2; - scalar_type denom = 2.181 * c2 + 3.535 * c; - return hlsl::mix(0.0, nom / denom, c < 1.6); - } - - scalar_type Lambda(scalar_type NdotX2, scalar_type a2) - { - return Lambda(C2(NdotX2, a2)); - } - - scalar_type Lambda(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2, scalar_type ax2, scalar_type ay2) - { - return Lambda(C2(TdotX2, BdotX2, NdotX2, ax2, ay2)); - } - - scalar_type correlated(SIsotropicParams params) - { - scalar_type c2 = C2(params.NdotV2, params.a2); - scalar_type L_v = Lambda(c2); - c2 = C2(params.NdotL2, params.a2); - scalar_type L_l = Lambda(c2); - return G1(L_v + L_l); - } - - scalar_type correlated(SAnisotropicParams params) - { - scalar_type c2 = C2(params.TdotV2, params.BdotV2, params.NdotV2, params.ax2, params.ay2); - scalar_type L_v = Lambda(c2); - c2 = C2(params.TdotL2, params.BdotL2, params.NdotL2, params.ax2, params.ay2); - scalar_type L_l = Lambda(c2); - return G1(L_v + L_l); - } - - scalar_type G2_over_G1(SIsotropicParams params) - { - scalar_type lambdaL = Lambda(params.NdotL2, params.a2); - return params.lambdaV_plus_one / (params.lambdaV_plus_one + lambdaL); - } - - scalar_type G2_over_G1(SAnisotropicParams params) - { - scalar_type c2 = C2(params.TdotL2, params.BdotL2, params.NdotL2, params.ax2, params.ay2); - scalar_type lambdaL = Lambda(c2); - return params.lambdaV_plus_one / (params.lambdaV_plus_one + lambdaL); - } -}; - - -// ggx -template) -struct GGX -{ - using scalar_type = T; - - scalar_type devsh_part(scalar_type NdotX2, scalar_type a2, scalar_type one_minus_a2) - { - return sqrt(a2 + one_minus_a2 * NdotX2); - } - - scalar_type devsh_part(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2, scalar_type ax2, scalar_type ay2) - { - return sqrt(TdotX2 * ax2 + BdotX2 * ay2 + NdotX2); - } - - scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type NdotX2, scalar_type a2, scalar_type one_minus_a2) - { - return 1.0 / (NdotX + devsh_part(NdotX2,a2,one_minus_a2)); - } - - scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2, scalar_type ax2, scalar_type ay2) - { - return 1.0 / (NdotX + devsh_part(TdotX2, BdotX2, NdotX2, ax2, ay2)); - } - - scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type devsh_part) - { - return 1.0 / (NdotX + devsh_part); - } - - scalar_type correlated_wo_numerator(SIsotropicParams params) - { - scalar_type Vterm = params.NdotL * devsh_part(params.NdotV2, params.a2, params.one_minus_a2); - scalar_type Lterm = params.NdotV * devsh_part(params.NdotL2, params.a2, params.one_minus_a2); - return 0.5 / (Vterm + Lterm); - } - - scalar_type correlated_wo_numerator(SAnisotropicParams params) - { - scalar_type Vterm = params.NdotL * devsh_part(params.TdotV2, params.BdotV2, params.NdotV2, params.ax2, params.ay2); - scalar_type Lterm = params.NdotV * devsh_part(params.TdotL2, params.BdotL2, params.NdotL2, params.ax2, params.ay2); - return 0.5 / (Vterm + Lterm); - } - - scalar_type G2_over_G1(SIsotropicParams params) - { - scalar_type devsh_v = devsh_part(params.NdotV2, params.a2, params.one_minus_a2); - scalar_type G2_over_G1 = params.NdotL * (devsh_v + params.NdotV); // alternative `Vterm+NdotL*NdotV /// NdotL*NdotV could come as a parameter - G2_over_G1 /= params.NdotV * devsh_part(params.NdotL2, params.a2, params.one_minus_a2) + params.NdotL * devsh_v; - - return G2_over_G1; - } - - scalar_type G2_over_G1(SAnisotropicParams params) - { - scalar_type devsh_v = devsh_part(params.TdotV2, params.BdotV2, params.NdotV2, params.ax2, params.ay2); - scalar_type G2_over_G1 = params.NdotL * (devsh_v + params.NdotV); - G2_over_G1 /= params.NdotV * devsh_part(params.TdotL2, params.BdotL2, params.NdotL2, params.ax2, params.ay2) + params.NdotL * devsh_v; - - return G2_over_G1; - } - -}; - -} -} -} -} - -#endif \ No newline at end of file diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl index dfaf4f06a1..4cc462cc8d 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -16,160 +16,19 @@ namespace bxdf namespace ndf { -template) -struct SIsotropicParams -{ - using this_t = SIsotropicParams; - - static this_t create(T n_or_a2, T NdotH, T NdotH2) // beckmann, ggx : a2; blinn-phong : n - { - this_t retval; - retval.n_or_a2 = n_or_a2; - retval.NdotH = NdotH; - retval.NdotH2 = NdotH2; - return retval; - } - - T n_or_a2; - T NdotH; - T NdotH2; -}; - -template) -struct SAnisotropicParams -{ - using this_t = SAnisotropicParams; - - static this_t create(T NdotH, T one_minus_NdotH2_rcp, T TdotH2, T BdotH2, T nx, T ny) // blinn-phong - { - this_t retval; - retval.NdotH = NdotH; - retval.one_minus_NdotH2_rcp = one_minus_NdotH2_rcp; - retval.TdotH2 = TdotH2; - retval.BdotH2 = BdotH2; - retval.nx = nx; - retval.ny = ny; - return retval; - } - - static this_t create(T ax, T ay, T ax2, T ay2, T TdotH2, T BdotH2, T NdotH2) // beckmann, ggx aniso - { - this_t retval; - retval.ax = ax; - retval.ax2 = ax2; - retval.ay = ay; - retval.ay2 = ay2; - retval.TdotH2 = TdotH2; - retval.BdotH2 = BdotH2; - retval.NdotH2 = NdotH2; - return retval; - } - - static this_t create(T a2, T TdotH, T BdotH, T NdotH) // ggx burley - { - this_t retval; - retval.ax = a2; - retval.TdotH = TdotH; - retval.BdotH = BdotH; - retval.NdotH = NdotH; - return retval; - } - - T ax; - T ay; - T ax2; - T ay2; - T nx; - T ny; - T NdotH; - T TdotH; - T BdotH; - T NdotH2; - T TdotH2; - T BdotH2; - T one_minus_NdotH2_rcp; -}; - - -template) -struct BlinnPhong -{ - using scalar_type = T; - - // blinn-phong - scalar_type operator()(SIsotropicParams params) - { - // n is shininess exponent in original paper - return isinf(params.n_or_a2) ? numeric_limits::infinity : numbers::inv_pi * 0.5 * (params.n_or_a2 + 2.0) * pow(params.NdotH, params.n_or_a2); - } - - //ashikhmin-shirley ndf - scalar_type operator()(SAnisotropicParams params) - { - scalar_type n = (params.TdotH2 * params.ny + params.BdotH2 * params.nx) * params.one_minus_NdotH2_rcp; - return (isinf(params.nx) || isinf(params.ny)) ? numeric_limits::infinity : - sqrt((params.nx + 2.0) * (params.ny + 2.0)) * numbers::inv_pi * 0.5 * pow(params.NdotH, n); - } -}; +template +struct Beckmann; -template) -struct Beckmann -{ - using scalar_type = T; - - scalar_type operator()(SIsotropicParams params) - { - scalar_type nom = exp( (params.NdotH2 - 1.0) / (params.n_or_a2 * params.NdotH2) ); // exp(x) == exp2(x/log(2)) ? - scalar_type denom = params.n_or_a2 * params.NdotH2 * params.NdotH2; - return numbers::inv_pi * nom / denom; - } - - scalar_type operator()(SAnisotropicParams params) - { - scalar_type nom = exp(-(params.TdotH2 / params.ax2 + params.BdotH2 / params.ay2) / params.NdotH2); - scalar_type denom = params.ax * params.ay * params.NdotH2 * params.NdotH2; - return numbers::inv_pi * nom / denom; - } -}; - - -template) -struct GGX -{ - using scalar_type = T; - - // trowbridge-reitz - scalar_type operator()(SIsotropicParams params) - { - scalar_type denom = params.NdotH2 * (params.n_or_a2 - 1.0) + 1.0; - return params.n_or_a2 * numbers::inv_pi / (denom * denom); - } - - scalar_type operator()(SAnisotropicParams params) - { - scalar_type a2 = params.ax * params.ay; - scalar_type denom = params.TdotH2 / params.ax2 + params.BdotH2 / params.ay2 + params.NdotH2; - return numbers::inv_pi / (a2 * denom * denom); - } - - // burley - scalar_type operator()(SAnisotropicParams params, scalar_type anisotropy) - { - scalar_type antiAniso = 1.0 - anisotropy; - scalar_type atab = params.ax * antiAniso; - scalar_type anisoTdotH = antiAniso * params.TdotH; - scalar_type anisoNdotH = antiAniso * params.NdotH; - scalar_type w2 = antiAniso/(params.BdotH * params.BdotH + anisoTdotH * anisoTdotH + anisoNdotH * anisoNdotH * params.ax); - return w2 * w2 * atab * numbers::inv_pi; - } -}; +template +struct GGX; // common namespace impl { template struct is_ggx : bool_constant< - is_same >::value + is_same >::value || + is_same >::value > {}; } diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl new file mode 100644 index 0000000000..f457eab8f9 --- /dev/null +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -0,0 +1,169 @@ +// Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_BUILTIN_HLSL_BXDF_NDF_BECKMANN_INCLUDED_ +#define _NBL_BUILTIN_HLSL_BXDF_NDF_BECKMANN_INCLUDED_ + +#include "nbl/builtin/hlsl/limits.hlsl" +#include "nbl/builtin/hlsl/bxdf/ndf.hlsl" + +namespace nbl +{ +namespace hlsl +{ +namespace bxdf +{ +namespace ndf +{ + +// TODO: get beta from lgamma, see: https://www.cec.uchile.cl/cinetica/pcordero/MC_libros/NumericalRecipesinC.pdf + +// TODO: use query_type for D, lambda, beta, DG1 when that's implemented +template +struct Beckmann +{ + using scalar_type = T; + using this_t = Beckmann; + + scalar_type D(scalar_type a2, scalar_type NdotH2) + { + scalar_type nom = exp( (NdotH2 - 1.0) / (a2 * NdotH2) ); // exp(x) == exp2(x/log(2)) ? + scalar_type denom = a2 * NdotH2 * NdotH2; + return numbers::inv_pi * nom / denom; + } + + // brdf + scalar_type DG1(scalar_type ndf, scalar_type maxNdotV, scalar_type lambda_V) + { + onePlusLambda_V = 1.0 + lambda_V; + ndf::microfacet_to_light_measure_transform transform = ndf::microfacet_to_light_measure_transform::create(ndf / onePlusLambda_V, maxNdotV); + return transform(); + } + + // bsdf + scalar_type DG1(scalar_type ndf, scalar_type absNdotV, scalar_type lambda_V, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, scalar_type reflectance) + { + onePlusLambda_V = 1.0 + lambda_V; + ndf::microfacet_to_light_measure_transform transform + = ndf::microfacet_to_light_measure_transform::create(hlsl::mix(reflectance, scalar_type(1.0) - reflectance, transmitted) * ndf / onePlusLambda_V, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); + return transform(); + } + + scalar_type G1(scalar_type lambda) + { + return 1.0 / (1.0 + lambda); + } + + scalar_type C2(scalar_type NdotX2, scalar_type a2) + { + return NdotX2 / (a2 * (1.0 - NdotX2)); + } + + scalar_type Lambda(scalar_type c2) + { + scalar_type c = sqrt(c2); + scalar_type nom = 1.0 - 1.259 * c + 0.396 * c2; + scalar_type denom = 2.181 * c2 + 3.535 * c; + return hlsl::mix(0.0, nom / denom, c < 1.6); + } + + scalar_type Lambda(scalar_type NdotX2, scalar_type a2) + { + return Lambda(C2(NdotX2, a2)); + } + + scalar_type correlated(scalar_type a2, scalar_type NdotV2, scalar_type NdotL2) + { + scalar_type c2 = C2(NdotV2, a2); + scalar_type L_v = Lambda(c2); + c2 = C2(NdotL2, a2); + scalar_type L_l = Lambda(c2); + return G1(L_v + L_l); + } + + scalar_type G2_over_G1(scalar_type a2, scalar_type NdotL2, scalar_type lambdaV_plus_one) + { + scalar_type lambdaL = Lambda(NdotL2, a2); + return lambdaV_plus_one / (lambdaV_plus_one + lambdaL); + } + + scalar_type onePlusLambda_V; +}; + + +template +struct Beckmann +{ + using scalar_type = T; + + scalar_type D(scalar_type ax, scalar_type ay, scalar_type ax2, scalar_type ay2, scalar_type TdotH2, scalar_type BdotH2, scalar_type NdotH2) + { + scalar_type nom = exp(-(TdotH2 / ax2 + BdotH2 / ay2) / NdotH2); + scalar_type denom = ax * ay * NdotH2 * NdotH2; + return numbers::inv_pi * nom / denom; + } + + scalar_type DG1(scalar_type ndf, scalar_type maxNdotV, scalar_type lambda_V) + { + Beckmann beckmann; + scalar_type dg = beckmann.DG1(ndf, maxNdotV, lambda_V); + onePlusLambda_V = beckmann.onePlusLambda_V; + return dg; + } + + scalar_type DG1(scalar_type ndf, scalar_type absNdotV, scalar_type lambda_V, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, scalar_type reflectance) + { + Beckmann beckmann; + scalar_type dg = beckmann.DG1(ndf, absNdotV, lambda_V, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta, reflectance); + onePlusLambda_V = beckmann.onePlusLambda_V; + return dg; + } + + scalar_type G1(scalar_type lambda) + { + return 1.0 / (1.0 + lambda); + } + + scalar_type C2(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2, scalar_type ax2, scalar_type ay2) + { + return NdotX2 / (TdotX2 * ax2 + BdotX2 * ay2); + } + + scalar_type Lambda(scalar_type c2) + { + scalar_type c = sqrt(c2); + scalar_type nom = 1.0 - 1.259 * c + 0.396 * c2; + scalar_type denom = 2.181 * c2 + 3.535 * c; + return hlsl::mix(0.0, nom / denom, c < 1.6); + } + + scalar_type Lambda(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2, scalar_type ax2, scalar_type ay2) + { + return Lambda(C2(TdotX2, BdotX2, NdotX2, ax2, ay2)); + } + + scalar_type correlated(scalar_type ax2, scalar_type ay2, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2) + { + scalar_type c2 = C2(TdotV2, BdotV2, NdotV2, ax2, ay2); + scalar_type L_v = Lambda(c2); + c2 = C2(TdotL2, BdotL2, NdotL2, ax2, ay2); + scalar_type L_l = Lambda(c2); + return G1(L_v + L_l); + } + + scalar_type G2_over_G1(scalar_type ax2, scalar_type ay2, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2, scalar_type lambdaV_plus_one) + { + scalar_type c2 = C2(TdotL2, BdotL2, NdotL2, ax2, ay2); + scalar_type lambdaL = Lambda(c2); + return lambdaV_plus_one / (lambdaV_plus_one + lambdaL); + } + + scalar_type onePlusLambda_V; +}; + +} +} +} +} + +#endif diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl new file mode 100644 index 0000000000..5d07e7e267 --- /dev/null +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -0,0 +1,163 @@ +// Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_BUILTIN_HLSL_BXDF_NDF_GGX_INCLUDED_ +#define _NBL_BUILTIN_HLSL_BXDF_NDF_GGX_INCLUDED_ + +#include "nbl/builtin/hlsl/limits.hlsl" +#include "nbl/builtin/hlsl/bxdf/ndf.hlsl" + +namespace nbl +{ +namespace hlsl +{ +namespace bxdf +{ +namespace ndf +{ + +// TODO: use query_type when that's implemented +template +struct GGX +{ + using scalar_type = T; + using this_t = GGX; + + // trowbridge-reitz + scalar_type D(scalar_type a2, scalar_type NdotH2) + { + scalar_type denom = NdotH2 * (a2 - 1.0) + 1.0; + return a2 * numbers::inv_pi / (denom * denom); + } + + scalar_type FVNDF(scalar_type fresnel_ndf, scalar_type G1_over_2NdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) + { + scalar_type FNG = fresnel_ndf * G1_over_2NdotV; + scalar_type factor = 0.5; + if (transmitted) + { + const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); + // VdotHLdotH is negative under transmission, so this factor is negative + factor *= -2.0 * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); + } + return FNG * factor; + } + + scalar_type DG1(scalar_type ndf, scalar_type G1_over_2NdotV) + { + return ndf * 0.5 * G1_over_2NdotV; + } + + scalar_type DG1(scalar_type ndf, scalar_type G1_over_2NdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, scalar_type reflectance) + { + scalar_type FN = hlsl::mix(reflectance, scalar_type(1.0) - reflectance, transmitted) * ndf; + return FVNDF(FN, G1_over_2NdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); + } + + scalar_type devsh_part(scalar_type NdotX2, scalar_type a2, scalar_type one_minus_a2) + { + return sqrt(a2 + one_minus_a2 * NdotX2); + } + + scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type NdotX2, scalar_type a2, scalar_type one_minus_a2) + { + return 1.0 / (NdotX + devsh_part(NdotX2,a2,one_minus_a2)); + } + + scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type devsh_part) + { + return 1.0 / (NdotX + devsh_part); + } + + scalar_type correlated_wo_numerator(scalar_type a2, scalar_type NdotV, scalar_type NdotV2, scalar_type NdotL, scalar_type NdotL2) + { + scalar_type one_minus_a2 = scalar_type(1.0) - a2; + scalar_type Vterm = NdotL * devsh_part(NdotV2, a2, one_minus_a2); + scalar_type Lterm = NdotV * devsh_part(NdotL2, a2, one_minus_a2); + return 0.5 / (Vterm + Lterm); + } + + scalar_type G2_over_G1(scalar_type a2, scalar_type NdotV, scalar_type NdotV2, scalar_type NdotL, scalar_type NdotL2) + { + scalar_type one_minus_a2 = scalar_type(1.0) - a2; + scalar_type devsh_v = devsh_part(NdotV2, a2, one_minus_a2); + scalar_type G2_over_G1 = NdotL * (devsh_v + NdotV); // alternative `Vterm+NdotL*NdotV /// NdotL*NdotV could come as a parameter + G2_over_G1 /= NdotV * devsh_part(NdotL2, a2, one_minus_a2) + NdotL * devsh_v; + + return G2_over_G1; + } +}; + +template +struct GGX +{ + using scalar_type = T; + + scalar_type D(scalar_type ax, scalar_type ay, scalar_type ax2, scalar_type ay2, scalar_type TdotH2, scalar_type BdotH2, scalar_type NdotH2) + { + scalar_type a2 = ax * ay; + scalar_type denom = TdotH2 / ax2 + BdotH2 / ay2 + NdotH2; + return numbers::inv_pi / (a2 * denom * denom); + } + + // burley + scalar_type D(scalar_type a2, scalar_type TdotH, scalar_type BdotH, scalar_type NdotH, scalar_type anisotropy) + { + scalar_type antiAniso = 1.0 - anisotropy; + scalar_type atab = a2 * antiAniso; + scalar_type anisoTdotH = antiAniso * TdotH; + scalar_type anisoNdotH = antiAniso * NdotH; + scalar_type w2 = antiAniso/(BdotH * BdotH + anisoTdotH * anisoTdotH + anisoNdotH * anisoNdotH * a2); + return w2 * w2 * atab * numbers::inv_pi; + } + + scalar_type DG1(scalar_type ndf, scalar_type G1_over_2NdotV) + { + GGX ggx; + return ggx.DG1(ndf, G1_over_2NdotV); + } + + scalar_type DG1(scalar_type ndf, scalar_type G1_over_2NdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, scalar_type reflectance) + { + GGX ggx; + return ggx.DG1(ndf, G1_over_2NdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta, reflectance); + } + + scalar_type devsh_part(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2, scalar_type ax2, scalar_type ay2) + { + return sqrt(TdotX2 * ax2 + BdotX2 * ay2 + NdotX2); + } + + scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2, scalar_type ax2, scalar_type ay2) + { + return 1.0 / (NdotX + devsh_part(TdotX2, BdotX2, NdotX2, ax2, ay2)); + } + + scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type devsh_part) + { + return 1.0 / (NdotX + devsh_part); + } + + scalar_type correlated_wo_numerator(scalar_type ax2, scalar_type ay2, scalar_type NdotV, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type NdotL, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2) + { + scalar_type Vterm = NdotL * devsh_part(TdotV2, BdotV2, NdotV2, ax2, ay2); + scalar_type Lterm = NdotV * devsh_part(TdotL2, BdotL2, NdotL2, ax2, ay2); + return 0.5 / (Vterm + Lterm); + } + + scalar_type G2_over_G1(scalar_type ax2, scalar_type ay2, scalar_type NdotV, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type NdotL, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2) + { + scalar_type devsh_v = devsh_part(TdotV2, BdotV2, NdotV2, ax2, ay2); + scalar_type G2_over_G1 = NdotL * (devsh_v + NdotV); + G2_over_G1 /= NdotV * devsh_part(TdotL2, BdotL2, NdotL2, ax2, ay2) + NdotL * devsh_v; + + return G2_over_G1; + } +}; + +} +} +} +} + +#endif diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index a3ea96694f..87032f6088 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -6,7 +6,7 @@ #include "nbl/builtin/hlsl/bxdf/common.hlsl" #include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" -#include "nbl/builtin/hlsl/bxdf/geom_smith.hlsl" +#include "nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl" namespace nbl { @@ -141,14 +141,11 @@ struct SBeckmannBxDF scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_isotropic_t) params) { scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.getNdotH(), params.getNdotH2()); - ndf::Beckmann beckmann_ndf; - scalar_type NG = beckmann_ndf(ndfparams); + ndf::Beckmann beckmann_ndf; + scalar_type NG = beckmann_ndf.D(a2, params.getNdotH2()); if (a2 > numeric_limits::min) { - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.getNdotV2(), params.getNdotL2(), 0); - smith::Beckmann beckmann_smith; - NG *= beckmann_smith.correlated(smithparams); + NG *= beckmann_ndf.correlated(a2, params.getNdotV2(), params.getNdotL2()); } return NG; } @@ -156,14 +153,11 @@ struct SBeckmannBxDF { const scalar_type ax2 = A.x*A.x; const scalar_type ay2 = A.y*A.y; - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); - ndf::Beckmann beckmann_ndf; - scalar_type NG = beckmann_ndf(ndfparams); - if (any >(A > (vector2_type)numeric_limits::min)) + ndf::Beckmann beckmann_ndf; + scalar_type NG = beckmann_ndf.D(A.x, A.y, ax2, ay2, params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); + if (hlsl::any >(A > (vector2_type)numeric_limits::min)) { - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2(), 0); - smith::Beckmann beckmann_smith; - NG *= beckmann_smith.correlated(smithparams); + NG *= beckmann_ndf.correlated(ax2, ay2, params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); } return NG; } @@ -286,33 +280,27 @@ struct SBeckmannBxDF { scalar_type ndf, lambda; scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.getNdotH(), params.getNdotH2()); - ndf::Beckmann beckmann_ndf; - ndf = beckmann_ndf(ndfparams); + ndf::Beckmann beckmann_ndf; + ndf = beckmann_ndf.D(a2, params.getNdotH2()); - smith::Beckmann beckmann_smith; - lambda = beckmann_smith.Lambda(params.getNdotV2(), a2); + lambda = beckmann_ndf.Lambda(params.getNdotV2(), a2); - smith::brdf::VNDF_pdf > vndf = smith::brdf::VNDF_pdf >::create(ndf, params.getNdotVUnclamped()); - scalar_type _pdf = vndf(lambda); - onePlusLambda_V = vndf.onePlusLambda_V; + scalar_type _pdf = beckmann_ndf.DG1(ndf, params.getNdotVUnclamped(), lambda); + onePlusLambda_V = beckmann_ndf.onePlusLambda_V; return _pdf; } scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { scalar_type ndf, lambda; - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, A.x*A.x, A.y*A.y, params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); - ndf::Beckmann beckmann_ndf; - ndf = beckmann_ndf(ndfparams); + ndf::Beckmann beckmann_ndf; + ndf = beckmann_ndf.D(A.x, A.y, A.x*A.x, A.y*A.y, params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); - smith::Beckmann beckmann_smith; - const scalar_type c2 = beckmann_smith.C2(params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), A.x, A.y); - lambda = beckmann_smith.Lambda(c2); + const scalar_type c2 = beckmann_ndf.C2(params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), A.x, A.y); + lambda = beckmann_ndf.Lambda(c2); - smith::brdf::VNDF_pdf > vndf = smith::brdf::VNDF_pdf >::create(ndf, params.getNdotVUnclamped()); - scalar_type _pdf = vndf(lambda); - onePlusLambda_V = vndf.onePlusLambda_V; + scalar_type _pdf = beckmann_ndf.DG1(ndf, params.getNdotVUnclamped(), lambda); + onePlusLambda_V = beckmann_ndf.onePlusLambda_V; return _pdf; } @@ -333,12 +321,11 @@ struct SBeckmannBxDF scalar_type onePlusLambda_V; scalar_type _pdf = pdf(params, onePlusLambda_V); - smith::Beckmann beckmann_smith; + ndf::Beckmann beckmann_ndf; spectral_type quo = (spectral_type)0.0; if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) { - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(A.x*A.x, params.getNdotV2(), params.getNdotL2(), onePlusLambda_V); - scalar_type G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); + scalar_type G2_over_G1 = beckmann_ndf.G2_over_G1(A.x*A.x, params.getNdotL2(), onePlusLambda_V); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; @@ -351,12 +338,11 @@ struct SBeckmannBxDF scalar_type onePlusLambda_V; scalar_type _pdf = pdf(params, onePlusLambda_V); - smith::Beckmann beckmann_smith; + ndf::Beckmann beckmann_ndf; spectral_type quo = (spectral_type)0.0; if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) { - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(A.x*A.x, A.y*A.y, params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2(), onePlusLambda_V); - scalar_type G2_over_G1 = beckmann_smith.G2_over_G1(smithparams); + scalar_type G2_over_G1 = beckmann_ndf.G2_over_G1(A.x*A.x, A.y*A.y, params.getTdotL2(), params.getBdotL2(), params.getNdotL2(), onePlusLambda_V); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index d5d749e5fc..f02df9fdc6 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -6,7 +6,7 @@ #include "nbl/builtin/hlsl/bxdf/common.hlsl" #include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" -#include "nbl/builtin/hlsl/bxdf/geom_smith.hlsl" +#include "nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl" namespace nbl { @@ -142,14 +142,11 @@ struct SGGXBxDF scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_isotropic_t) params) { scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.getNdotH(), params.getNdotH2()); - ndf::GGX ggx_ndf; - scalar_type NG = ggx_ndf(ndfparams); + ndf::GGX ggx_ndf; + scalar_type NG = ggx_ndf.D(a2, params.getNdotH2()); if (a2 > numeric_limits::min) { - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.getNdotV(), params.getNdotV2(), params.getNdotL(), params.getNdotL2()); - smith::GGX ggx_smith; - NG *= ggx_smith.correlated_wo_numerator(smithparams); + NG *= ggx_ndf.correlated_wo_numerator(a2, params.getNdotV(), params.getNdotV2(), params.getNdotL(), params.getNdotL2()); } return NG; } @@ -157,14 +154,11 @@ struct SGGXBxDF { const scalar_type ax2 = A.x*A.x; const scalar_type ay2 = A.y*A.y; - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); - ndf::GGX ggx_ndf; - scalar_type NG = ggx_ndf(ndfparams); + ndf::GGX ggx_ndf; + scalar_type NG = ggx_ndf.D(A.x, A.y, ax2, ay2, params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); if (any >(A > (vector2_type)numeric_limits::min)) { - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.getNdotV(), params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getNdotL(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); - smith::GGX ggx_smith; - NG *= ggx_smith.correlated_wo_numerator(smithparams); + NG *= ggx_ndf.correlated_wo_numerator(ax2, ay2, params.getNdotV(), params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getNdotL(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); } return NG; } @@ -241,32 +235,26 @@ struct SGGXBxDF { scalar_type ndf, G1_over_2NdotV; const scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.getNdotH(), params.getNdotH2()); - ndf::GGX ggx_ndf; - ndf = ggx_ndf(ndfparams); + ndf::GGX ggx_ndf; + ndf = ggx_ndf.D(a2, params.getNdotH2()); - smith::GGX ggx_smith; - const scalar_type devsh_v = ggx_smith.devsh_part(params.getNdotV2(), a2, 1.0-a2); - G1_over_2NdotV = ggx_smith.G1_wo_numerator(params.getNdotVUnclamped(), devsh_v); + const scalar_type devsh_v = ggx_ndf.devsh_part(params.getNdotV2(), a2, 1.0-a2); + G1_over_2NdotV = ggx_ndf.G1_wo_numerator(params.getNdotVUnclamped(), devsh_v); - smith::brdf::VNDF_pdf > vndf = smith::brdf::VNDF_pdf >::create(ndf, params.getNdotVUnclamped()); - return vndf(G1_over_2NdotV); + return ggx_ndf.DG1(ndf, G1_over_2NdotV); } scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { scalar_type ndf, G1_over_2NdotV; const scalar_type ax2 = A.x*A.x; const scalar_type ay2 = A.y*A.y; - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); - ndf::GGX ggx_ndf; - ndf = ggx_ndf(ndfparams); + ndf::GGX ggx_ndf; + ndf = ggx_ndf.D(A.x, A.y, ax2, ay2, params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); - smith::GGX ggx_smith; - const scalar_type devsh_v = ggx_smith.devsh_part(params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), ax2, ay2); - G1_over_2NdotV = ggx_smith.G1_wo_numerator(params.getNdotVUnclamped(), devsh_v); + const scalar_type devsh_v = ggx_ndf.devsh_part(params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), ax2, ay2); + G1_over_2NdotV = ggx_ndf.G1_wo_numerator(params.getNdotVUnclamped(), devsh_v); - smith::brdf::VNDF_pdf > vndf = smith::brdf::VNDF_pdf >::create(ndf, params.getNdotVUnclamped()); - return vndf(G1_over_2NdotV); + return ggx_ndf.DG1(ndf, G1_over_2NdotV); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) @@ -277,11 +265,10 @@ struct SGGXBxDF if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) { scalar_type G2_over_G1; - smith::GGX ggx_smith; + ndf::GGX ggx_ndf; const scalar_type a2 = A.x*A.x; - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(a2, params.getNdotVUnclamped(), params.getNdotV2(), params.getNdotLUnclamped(), params.getNdotL2()); - G2_over_G1 = ggx_smith.G2_over_G1(smithparams); + G2_over_G1 = ggx_ndf.G2_over_G1(a2, params.getNdotVUnclamped(), params.getNdotV2(), params.getNdotLUnclamped(), params.getNdotL2()); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); @@ -298,12 +285,11 @@ struct SGGXBxDF if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) { scalar_type G2_over_G1; - smith::GGX ggx_smith; + ndf::GGX ggx_ndf; const scalar_type ax2 = A.x*A.x; const scalar_type ay2 = A.y*A.y; - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.getNdotVUnclamped(), params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getNdotLUnclamped(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); - G2_over_G1 = ggx_smith.G2_over_G1(smithparams); + G2_over_G1 = ggx_ndf.G2_over_G1(ax2, ay2, params.getNdotVUnclamped(), params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getNdotLUnclamped(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl index 8a9dc55ef1..029a32569e 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl @@ -6,7 +6,6 @@ #include "nbl/builtin/hlsl/bxdf/common.hlsl" #include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" -#include "nbl/builtin/hlsl/bxdf/geom_smith.hlsl" namespace nbl { diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl index 6cca0d0eac..700292d0c8 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl @@ -6,7 +6,6 @@ #include "nbl/builtin/hlsl/bxdf/common.hlsl" #include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" -#include "nbl/builtin/hlsl/bxdf/geom_smith.hlsl" namespace nbl { diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index ca4089f727..8837602a78 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -236,16 +236,13 @@ struct SBeckmannDielectricBxDF scalar_type ndf, lambda; const scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.getNdotH(), params.getNdotH2()); - ndf::Beckmann beckmann_ndf; - ndf = beckmann_ndf(ndfparams); + ndf::Beckmann beckmann_ndf; + ndf = beckmann_ndf.D(a2, params.getNdotH2()); - smith::Beckmann beckmann_smith; - lambda = beckmann_smith.Lambda(params.getNdotV2(), a2); + lambda = beckmann_ndf.Lambda(params.getNdotV2(), a2); - smith::bsdf::VNDF_pdf > vndf = smith::bsdf::VNDF_pdf >::create(ndf, params.getNdotV()); - scalar_type _pdf = vndf(lambda,transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0],reflectance); - onePlusLambda_V = vndf.onePlusLambda_V; + scalar_type _pdf = beckmann_ndf.DG1(ndf,params.getNdotV(),lambda,transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0],reflectance); + onePlusLambda_V = beckmann_ndf.onePlusLambda_V; return _pdf; } @@ -262,17 +259,14 @@ struct SBeckmannDielectricBxDF scalar_type ndf, lambda; const scalar_type ax2 = A.x*A.x; const scalar_type ay2 = A.y*A.y; - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); - ndf::Beckmann beckmann_ndf; - ndf = beckmann_ndf(ndfparams); + ndf::Beckmann beckmann_ndf; + ndf = beckmann_ndf.D(A.x, A.y, ax2, ay2, params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); - smith::Beckmann beckmann_smith; - scalar_type c2 = beckmann_smith.C2(params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), ax2, ay2); - lambda = beckmann_smith.Lambda(c2); + scalar_type c2 = beckmann_ndf.C2(params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), ax2, ay2); + lambda = beckmann_ndf.Lambda(c2); - smith::bsdf::VNDF_pdf > vndf = smith::bsdf::VNDF_pdf >::create(ndf, params.getNdotV()); - scalar_type _pdf = vndf(lambda,transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0],reflectance); - onePlusLambda_V = vndf.onePlusLambda_V; + scalar_type _pdf = beckmann_ndf.DG1(ndf,params.getNdotV(),lambda,transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0],reflectance); + onePlusLambda_V = beckmann_ndf.onePlusLambda_V; return _pdf; } @@ -294,11 +288,10 @@ struct SBeckmannDielectricBxDF scalar_type _pdf = pdf(params, onePlusLambda_V); scalar_type quo; - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(A.x*A.x, params.getNdotV2(), params.getNdotL2(), onePlusLambda_V); - smith::Beckmann beckmann_smith; - quo = beckmann_smith.G2_over_G1(smithparams); + ndf::Beckmann beckmann_ndf; + quo = beckmann_ndf.G2_over_G1(A.x*A.x, params.getNdotL2(), onePlusLambda_V); - return quotient_pdf_type::create((spectral_type)(quo), _pdf); + return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { @@ -306,11 +299,10 @@ struct SBeckmannDielectricBxDF scalar_type _pdf = pdf(params, onePlusLambda_V); scalar_type quo; - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(A.x*A.x, A.y*A.y, params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2(), onePlusLambda_V); - smith::Beckmann beckmann_smith; - quo = beckmann_smith.G2_over_G1(smithparams); + ndf::Beckmann beckmann_ndf; + quo = beckmann_ndf.G2_over_G1(A.x*A.x, A.y*A.y, params.getTdotL2(), params.getBdotL2(), params.getNdotL2(), onePlusLambda_V); - return quotient_pdf_type::create((spectral_type)(quo), _pdf); + return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } vector2_type A; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 08e53c619e..48f932fca3 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -239,16 +239,13 @@ struct SGGXDielectricBxDF scalar_type ndf, devsh_v; const scalar_type a2 = A.x*A.x; - ndf::SIsotropicParams ndfparams = ndf::SIsotropicParams::create(a2, params.getNdotH(), params.getNdotH2()); - ndf::GGX ggx_ndf; - ndf = ggx_ndf(ndfparams); + ndf::GGX ggx_ndf; + ndf = ggx_ndf.D(a2, params.getNdotH2()); - smith::GGX ggx_smith; - devsh_v = ggx_smith.devsh_part(params.getNdotV2(), a2, 1.0-a2); - const scalar_type lambda = ggx_smith.G1_wo_numerator(params.getNdotV(), devsh_v); + devsh_v = ggx_ndf.devsh_part(params.getNdotV2(), a2, 1.0-a2); + const scalar_type lambda = ggx_ndf.G1_wo_numerator(params.getNdotV(), devsh_v); - smith::bsdf::VNDF_pdf > vndf = smith::bsdf::VNDF_pdf >::create(ndf, params.getNdotV()); - return vndf(lambda, transmitted, params.getVdotH(), params.getLdotH(), VdotHLdotH, orientedEta.value[0], reflectance); + return ggx_ndf.DG1(ndf, lambda, transmitted, params.getVdotH(), params.getLdotH(), VdotHLdotH, orientedEta.value[0], reflectance); } scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { @@ -264,16 +261,13 @@ struct SGGXDielectricBxDF const scalar_type ax2 = A.x*A.x; const scalar_type ay2 = A.y*A.y; - ndf::SAnisotropicParams ndfparams = ndf::SAnisotropicParams::create(A.x, A.y, ax2, ay2, params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); - ndf::GGX ggx_ndf; - ndf = ggx_ndf(ndfparams); + ndf::GGX ggx_ndf; + ndf = ggx_ndf.D(A.x, A.y, ax2, ay2, params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); - smith::GGX ggx_smith; - devsh_v = ggx_smith.devsh_part(params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), ax2, ay2); - const scalar_type lambda = ggx_smith.G1_wo_numerator(params.getNdotV(), devsh_v); + devsh_v = ggx_ndf.devsh_part(params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), ax2, ay2); + const scalar_type lambda = ggx_ndf.G1_wo_numerator(params.getNdotV(), devsh_v); - smith::bsdf::VNDF_pdf > vndf = smith::bsdf::VNDF_pdf >::create(ndf, params.getNdotV()); - return vndf(lambda, transmitted, params.getVdotH(), params.getLdotH(), VdotHLdotH, orientedEta.value[0], reflectance); + return ggx_ndf.DG1(ndf, lambda, transmitted, params.getVdotH(), params.getLdotH(), VdotHLdotH, orientedEta.value[0], reflectance); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) @@ -283,12 +277,11 @@ struct SGGXDielectricBxDF scalar_type _pdf = pdf(params); - smith::GGX ggx_smith; + ndf::GGX ggx_ndf; scalar_type quo; - smith::SIsotropicParams smithparams = smith::SIsotropicParams::create(ax2, params.getNdotV(), params.getNdotV2(), params.getNdotL(), params.getNdotL2()); - quo = ggx_smith.G2_over_G1(smithparams); + quo = ggx_ndf.G2_over_G1(ax2, params.getNdotV(), params.getNdotV2(), params.getNdotL(), params.getNdotL2()); - return quotient_pdf_type::create((spectral_type)(quo), _pdf); + return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { @@ -297,12 +290,11 @@ struct SGGXDielectricBxDF scalar_type _pdf = pdf(params); - smith::GGX ggx_smith; + ndf::GGX ggx_ndf; scalar_type quo; - smith::SAnisotropicParams smithparams = smith::SAnisotropicParams::create(ax2, ay2, params.getNdotV(), params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getNdotL(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); - quo = ggx_smith.G2_over_G1(smithparams); + quo = ggx_ndf.G2_over_G1(ax2, ay2, params.getNdotV(), params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getNdotL(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); - return quotient_pdf_type::create((spectral_type)(quo), _pdf); + return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } vector2_type A; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index 71cbd4dfa2..83b382119d 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -6,7 +6,6 @@ #include "nbl/builtin/hlsl/bxdf/common.hlsl" #include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" -#include "nbl/builtin/hlsl/bxdf/reflection.hlsl" namespace nbl { From 49870072b51cd8a050f8757cad216f0d2271f643 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 15 Jul 2025 16:34:11 +0700 Subject: [PATCH 117/188] change microfacet light measure transform usage --- include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 99 ++++--------------- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 7 +- .../hlsl/bxdf/reflection/beckmann.hlsl | 16 +-- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 16 +-- .../hlsl/bxdf/transmission/beckmann.hlsl | 14 ++- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 14 ++- 6 files changed, 47 insertions(+), 119 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl index 4cc462cc8d..bc953c9799 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -41,71 +41,41 @@ NBL_CONSTEXPR bool is_ggx_v = is_ggx::value; enum MicrofacetTransformTypes : uint16_t { - REFLECT_BIT = 0b01, - REFRACT_BIT = 0b10, - REFLECT_REFRACT_BIT = 0b11 + MTT_REFLECT = 0b01, + MTT_REFRACT = 0b10, + MTT_REFLECT_REFRACT = 0b11 }; -template +template struct microfacet_to_light_measure_transform; - template -struct microfacet_to_light_measure_transform +struct microfacet_to_light_measure_transform { - using this_t = microfacet_to_light_measure_transform; + using this_t = microfacet_to_light_measure_transform; using scalar_type = typename NDF::scalar_type; - static this_t create(scalar_type NDFcos, scalar_type maxNdotV) - { - this_t retval; - retval.NDFcos = NDFcos; - if (is_ggx_v) - retval.maxNdotL = maxNdotV; - else - retval.maxNdotV = maxNdotV; - return retval; - } - - scalar_type operator()() + // this computes the max(NdotL,0)/(4*max(NdotV,0)*max(NdotL,0)) factor which transforms PDFs in the f in projected microfacet f * NdotH measure to projected light measure f * NdotL + static scalar_type __call(scalar_type NDFcos, scalar_type maxNdotV /* or maxNdotL for GGX*/) { if (is_ggx_v) - return NDFcos * maxNdotL; + return NDFcos * maxNdotV; else return 0.25 * NDFcos / maxNdotV; } - - scalar_type NDFcos; - scalar_type maxNdotV; - scalar_type maxNdotL; }; template -struct microfacet_to_light_measure_transform +struct microfacet_to_light_measure_transform { - using this_t = microfacet_to_light_measure_transform; + using this_t = microfacet_to_light_measure_transform; using scalar_type = typename NDF::scalar_type; - static this_t create(scalar_type NDFcos, scalar_type absNdotV, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) - { - this_t retval; - retval.NDFcos = NDFcos; - if (is_ggx_v) - retval.absNdotL = absNdotV; - else - retval.absNdotV = absNdotV; - retval.VdotH = VdotH; - retval.LdotH = LdotH; - retval.VdotHLdotH = VdotHLdotH; - retval.orientedEta = orientedEta; - return retval; - } - - scalar_type operator()() + static scalar_type __call(scalar_type NDFcos, scalar_type absNdotV, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) { if (is_ggx_v) { - scalar_type denominator = absNdotL; + scalar_type denominator = absNdotV; const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); // VdotHLdotH is negative under transmission, so thats denominator is negative denominator *= -4.0 * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); @@ -120,44 +90,19 @@ struct microfacet_to_light_measure_transform return NDFcos * VdotHLdotH / denominator; } } - - scalar_type NDFcos; - scalar_type absNdotV; - scalar_type absNdotL; - - scalar_type VdotH; - scalar_type LdotH; - scalar_type VdotHLdotH; - scalar_type orientedEta; }; template -struct microfacet_to_light_measure_transform +struct microfacet_to_light_measure_transform { - using this_t = microfacet_to_light_measure_transform; + using this_t = microfacet_to_light_measure_transform; using scalar_type = typename NDF::scalar_type; - static this_t create(scalar_type NDFcos, scalar_type absNdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) - { - this_t retval; - retval.NDFcos = NDFcos; - if (is_ggx_v) - retval.absNdotL = absNdotV; - else - retval.absNdotV = absNdotV; - retval.transmitted = transmitted; - retval.VdotH = VdotH; - retval.LdotH = LdotH; - retval.VdotHLdotH = VdotHLdotH; - retval.orientedEta = orientedEta; - return retval; - } - - scalar_type operator()() + static scalar_type __call(scalar_type NDFcos, scalar_type absNdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) { if (is_ggx_v) { - scalar_type denominator = absNdotL; + scalar_type denominator = absNdotV; if (transmitted) { const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); @@ -178,16 +123,6 @@ struct microfacet_to_light_measure_transform return NDFcos * (transmitted ? VdotHLdotH : 0.25) / denominator; } } - - bool transmitted; - scalar_type NDFcos; - scalar_type absNdotV; - scalar_type absNdotL; - - scalar_type VdotH; - scalar_type LdotH; - scalar_type VdotHLdotH; - scalar_type orientedEta; }; } diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index f457eab8f9..a59baa9552 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -36,17 +36,14 @@ struct Beckmann scalar_type DG1(scalar_type ndf, scalar_type maxNdotV, scalar_type lambda_V) { onePlusLambda_V = 1.0 + lambda_V; - ndf::microfacet_to_light_measure_transform transform = ndf::microfacet_to_light_measure_transform::create(ndf / onePlusLambda_V, maxNdotV); - return transform(); + return ndf::microfacet_to_light_measure_transform::__call(ndf / onePlusLambda_V, maxNdotV); } // bsdf scalar_type DG1(scalar_type ndf, scalar_type absNdotV, scalar_type lambda_V, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, scalar_type reflectance) { onePlusLambda_V = 1.0 + lambda_V; - ndf::microfacet_to_light_measure_transform transform - = ndf::microfacet_to_light_measure_transform::create(hlsl::mix(reflectance, scalar_type(1.0) - reflectance, transmitted) * ndf / onePlusLambda_V, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); - return transform(); + return ndf::microfacet_to_light_measure_transform::__call(hlsl::mix(reflectance, scalar_type(1.0) - reflectance, transmitted) * ndf / onePlusLambda_V, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); } scalar_type G1(scalar_type lambda) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 87032f6088..b413bfabc3 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -166,25 +166,25 @@ struct SBeckmannBxDF { if (params.getNdotVUnclamped() > numeric_limits::min) { - scalar_type scalar_part = __eval_DG_wo_clamps(params); - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.getNdotVUnclamped()); + const scalar_type scalar_part = __eval_DG_wo_clamps(params); + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::MTT_REFLECT>::__call(scalar_part, params.getNdotVUnclamped()); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); - return f() * microfacet_transform(); + return f() * microfacet_transform; } else - return (spectral_type)0.0; + return hlsl::promote(0.0); } spectral_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) { if (params.getNdotVUnclamped() > numeric_limits::min) { - scalar_type scalar_part = __eval_DG_wo_clamps(params); - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.getNdotVUnclamped()); + const scalar_type scalar_part = __eval_DG_wo_clamps(params); + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::MTT_REFLECT>::__call(scalar_part, params.getNdotVUnclamped()); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); - return f() * microfacet_transform(); + return f() * microfacet_transform; } else - return (spectral_type)0.0; + return hlsl::promote(0.0); } vector3_type __generate(NBL_CONST_REF_ARG(vector3_type) localV, NBL_CONST_REF_ARG(vector2_type) u) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index f02df9fdc6..fab05d1d79 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -167,25 +167,25 @@ struct SGGXBxDF { if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) { - scalar_type scalar_part = __eval_DG_wo_clamps(params); - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.getNdotL()); + const scalar_type scalar_part = __eval_DG_wo_clamps(params); + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::MTT_REFLECT>::__call(scalar_part, params.getNdotL()); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); - return f() * microfacet_transform(); + return f() * microfacet_transform; } else - return (spectral_type)0.0; + return hlsl::promote(0.0); } spectral_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) { if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) { - scalar_type scalar_part = __eval_DG_wo_clamps(params); - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT> microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::REFLECT_BIT>::create(scalar_part, params.getNdotL()); + const scalar_type scalar_part = __eval_DG_wo_clamps(params); + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::MTT_REFLECT>::__call(scalar_part, params.getNdotL()); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); - return f() * microfacet_transform(); + return f() * microfacet_transform; } else - return (spectral_type)0.0; + return hlsl::promote(0.0); } vector3_type __generate(NBL_CONST_REF_ARG(vector3_type) localV, NBL_CONST_REF_ARG(vector2_type) u) diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 8837602a78..2f41fbd41e 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -150,10 +150,9 @@ struct SBeckmannDielectricBxDF typename brdf_type::params_isotropic_t brdf_params = typename brdf_type::params_isotropic_t::create(params._sample, params.interaction, params.cache, params._clamp); const scalar_type scalar_part = beckmann.__eval_DG_wo_clamps(brdf_params); - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,params.getNdotV(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); - scalar_type f = fresnel::Dielectric::__call(orientedEta2, hlsl::abs(params.getVdotH()))[0]; - return hlsl::promote(f) * microfacet_transform(); + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::MTT_REFLECT_REFRACT>::__call(scalar_part,params.getNdotV(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); + const scalar_type f = fresnel::Dielectric::__call(orientedEta2, hlsl::abs(params.getVdotH()))[0]; + return hlsl::promote(f) * microfacet_transform; } spectral_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) { @@ -168,10 +167,9 @@ struct SBeckmannDielectricBxDF typename brdf_type::params_anisotropic_t brdf_params = typename brdf_type::params_anisotropic_t::create(params._sample, params.interaction, params.cache, params._clamp); const scalar_type scalar_part = beckmann.__eval_DG_wo_clamps(brdf_params); - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(scalar_part,params.getNdotV(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); - scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; - return hlsl::promote(f) * microfacet_transform(); + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::MTT_REFLECT_REFRACT>::__call(scalar_part,params.getNdotV(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); + const scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; + return hlsl::promote(f) * microfacet_transform; } sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) localV, NBL_CONST_REF_ARG(vector3_type) H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(anisocache_type) cache) diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 48f932fca3..c402c38190 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -151,10 +151,9 @@ struct SGGXDielectricBxDF typename brdf_type::params_isotropic_t brdf_params = typename brdf_type::params_isotropic_t::create(params._sample, params.interaction, params.cache, params._clamp); NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(brdf_params); - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,params.getNdotL(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); - scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; - return hlsl::promote(f) * microfacet_transform(); + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::MTT_REFLECT_REFRACT>::__call(NG_already_in_reflective_dL_measure,params.getNdotL(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); + const scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; + return hlsl::promote(f) * microfacet_transform; } spectral_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) { @@ -171,10 +170,9 @@ struct SGGXDielectricBxDF typename brdf_type::params_anisotropic_t brdf_params = typename brdf_type::params_anisotropic_t::create(params._sample, params.interaction, params.cache, params._clamp); NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(brdf_params); - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT> microfacet_transform = - ndf::microfacet_to_light_measure_transform,ndf::REFLECT_REFRACT_BIT>::create(NG_already_in_reflective_dL_measure,params.getNdotL(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); - scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; - return hlsl::promote(f) * microfacet_transform(); + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::MTT_REFLECT_REFRACT>::__call(NG_already_in_reflective_dL_measure,params.getNdotL(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); + const scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; + return hlsl::promote(f) * microfacet_transform; } sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) localV, NBL_CONST_REF_ARG(vector3_type) H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(anisocache_type) cache) From 5e3d27a6b0e1f85f4253866e18f12ef8d34b6c2f Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 15 Jul 2025 16:41:06 +0700 Subject: [PATCH 118/188] cast scalar constants to type --- include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 8 +++---- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 24 +++++++++---------- include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 20 ++++++++-------- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl index bc953c9799..358b7a4139 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -61,7 +61,7 @@ struct microfacet_to_light_measure_transform if (is_ggx_v) return NDFcos * maxNdotV; else - return 0.25 * NDFcos / maxNdotV; + return scalar_type(0.25) * NDFcos / maxNdotV; } }; @@ -78,7 +78,7 @@ struct microfacet_to_light_measure_transform scalar_type denominator = absNdotV; const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); // VdotHLdotH is negative under transmission, so thats denominator is negative - denominator *= -4.0 * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); + denominator *= -scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); return NDFcos * denominator; } else @@ -107,7 +107,7 @@ struct microfacet_to_light_measure_transform { const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); // VdotHLdotH is negative under transmission, so thats denominator is negative - denominator *= -4.0 * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); + denominator *= -scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); } return NDFcos * denominator; } @@ -120,7 +120,7 @@ struct microfacet_to_light_measure_transform // VdotHLdotH is negative under transmission, so thats denominator is negative denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; } - return NDFcos * (transmitted ? VdotHLdotH : 0.25) / denominator; + return NDFcos * (transmitted ? VdotHLdotH : scalar_type(0.25)) / denominator; } } }; diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index a59baa9552..6e95479184 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -27,7 +27,7 @@ struct Beckmann scalar_type D(scalar_type a2, scalar_type NdotH2) { - scalar_type nom = exp( (NdotH2 - 1.0) / (a2 * NdotH2) ); // exp(x) == exp2(x/log(2)) ? + scalar_type nom = exp( (NdotH2 - scalar_type(1.0)) / (a2 * NdotH2) ); // exp(x) == exp2(x/log(2)) ? scalar_type denom = a2 * NdotH2 * NdotH2; return numbers::inv_pi * nom / denom; } @@ -35,33 +35,33 @@ struct Beckmann // brdf scalar_type DG1(scalar_type ndf, scalar_type maxNdotV, scalar_type lambda_V) { - onePlusLambda_V = 1.0 + lambda_V; + onePlusLambda_V = scalar_type(1.0) + lambda_V; return ndf::microfacet_to_light_measure_transform::__call(ndf / onePlusLambda_V, maxNdotV); } // bsdf scalar_type DG1(scalar_type ndf, scalar_type absNdotV, scalar_type lambda_V, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, scalar_type reflectance) { - onePlusLambda_V = 1.0 + lambda_V; + onePlusLambda_V = scalar_type(1.0) + lambda_V; return ndf::microfacet_to_light_measure_transform::__call(hlsl::mix(reflectance, scalar_type(1.0) - reflectance, transmitted) * ndf / onePlusLambda_V, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); } scalar_type G1(scalar_type lambda) { - return 1.0 / (1.0 + lambda); + return scalar_type(1.0) / (scalar_type(1.0) + lambda); } scalar_type C2(scalar_type NdotX2, scalar_type a2) { - return NdotX2 / (a2 * (1.0 - NdotX2)); + return NdotX2 / (a2 * (scalar_type(1.0) - NdotX2)); } scalar_type Lambda(scalar_type c2) { scalar_type c = sqrt(c2); - scalar_type nom = 1.0 - 1.259 * c + 0.396 * c2; - scalar_type denom = 2.181 * c2 + 3.535 * c; - return hlsl::mix(0.0, nom / denom, c < 1.6); + scalar_type nom = scalar_type(1.0) - scalar_type(1.259) * c + scalar_type(0.396) * c2; + scalar_type denom = scalar_type(2.181) * c2 + scalar_type(3.535) * c; + return hlsl::mix(scalar_type(0.0), nom / denom, c < scalar_type(1.6)); } scalar_type Lambda(scalar_type NdotX2, scalar_type a2) @@ -118,7 +118,7 @@ struct Beckmann scalar_type G1(scalar_type lambda) { - return 1.0 / (1.0 + lambda); + return scalar_type(1.0) / (scalar_type(1.0) + lambda); } scalar_type C2(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2, scalar_type ax2, scalar_type ay2) @@ -129,9 +129,9 @@ struct Beckmann scalar_type Lambda(scalar_type c2) { scalar_type c = sqrt(c2); - scalar_type nom = 1.0 - 1.259 * c + 0.396 * c2; - scalar_type denom = 2.181 * c2 + 3.535 * c; - return hlsl::mix(0.0, nom / denom, c < 1.6); + scalar_type nom = scalar_type(1.0) - scalar_type(1.259) * c + scalar_type(0.396) * c2; + scalar_type denom = scalar_type(2.181) * c2 + scalar_type(3.535) * c; + return hlsl::mix(scalar_type(0.0), nom / denom, c < scalar_type(1.6)); } scalar_type Lambda(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2, scalar_type ax2, scalar_type ay2) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index 5d07e7e267..f9c4258e67 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -26,26 +26,26 @@ struct GGX // trowbridge-reitz scalar_type D(scalar_type a2, scalar_type NdotH2) { - scalar_type denom = NdotH2 * (a2 - 1.0) + 1.0; + scalar_type denom = NdotH2 * (a2 - scalar_type(1.0)) + scalar_type(1.0); return a2 * numbers::inv_pi / (denom * denom); } scalar_type FVNDF(scalar_type fresnel_ndf, scalar_type G1_over_2NdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) { scalar_type FNG = fresnel_ndf * G1_over_2NdotV; - scalar_type factor = 0.5; + scalar_type factor = scalar_type(0.5); if (transmitted) { const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); // VdotHLdotH is negative under transmission, so this factor is negative - factor *= -2.0 * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); + factor *= -scalar_type(2.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); } return FNG * factor; } scalar_type DG1(scalar_type ndf, scalar_type G1_over_2NdotV) { - return ndf * 0.5 * G1_over_2NdotV; + return ndf * scalar_type(0.5) * G1_over_2NdotV; } scalar_type DG1(scalar_type ndf, scalar_type G1_over_2NdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, scalar_type reflectance) @@ -61,12 +61,12 @@ struct GGX scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type NdotX2, scalar_type a2, scalar_type one_minus_a2) { - return 1.0 / (NdotX + devsh_part(NdotX2,a2,one_minus_a2)); + return scalar_type(1.0) / (NdotX + devsh_part(NdotX2,a2,one_minus_a2)); } scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type devsh_part) { - return 1.0 / (NdotX + devsh_part); + return scalar_type(1.0) / (NdotX + devsh_part); } scalar_type correlated_wo_numerator(scalar_type a2, scalar_type NdotV, scalar_type NdotV2, scalar_type NdotL, scalar_type NdotL2) @@ -74,7 +74,7 @@ struct GGX scalar_type one_minus_a2 = scalar_type(1.0) - a2; scalar_type Vterm = NdotL * devsh_part(NdotV2, a2, one_minus_a2); scalar_type Lterm = NdotV * devsh_part(NdotL2, a2, one_minus_a2); - return 0.5 / (Vterm + Lterm); + return scalar_type(0.5) / (Vterm + Lterm); } scalar_type G2_over_G1(scalar_type a2, scalar_type NdotV, scalar_type NdotV2, scalar_type NdotL, scalar_type NdotL2) @@ -103,7 +103,7 @@ struct GGX // burley scalar_type D(scalar_type a2, scalar_type TdotH, scalar_type BdotH, scalar_type NdotH, scalar_type anisotropy) { - scalar_type antiAniso = 1.0 - anisotropy; + scalar_type antiAniso = scalar_type(1.0) - anisotropy; scalar_type atab = a2 * antiAniso; scalar_type anisoTdotH = antiAniso * TdotH; scalar_type anisoNdotH = antiAniso * NdotH; @@ -130,12 +130,12 @@ struct GGX scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2, scalar_type ax2, scalar_type ay2) { - return 1.0 / (NdotX + devsh_part(TdotX2, BdotX2, NdotX2, ax2, ay2)); + return scalar_type(1.0) / (NdotX + devsh_part(TdotX2, BdotX2, NdotX2, ax2, ay2)); } scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type devsh_part) { - return 1.0 / (NdotX + devsh_part); + return scalar_type(1.0) / (NdotX + devsh_part); } scalar_type correlated_wo_numerator(scalar_type ax2, scalar_type ay2, scalar_type NdotV, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type NdotL, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2) From 675971c22664678c8d39969d8560533d171d2930 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 16 Jul 2025 11:02:56 +0700 Subject: [PATCH 119/188] beta and lgamma functions --- include/nbl/builtin/hlsl/tgmath.hlsl | 12 ++++++ include/nbl/builtin/hlsl/tgmath/impl.hlsl | 45 +++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/include/nbl/builtin/hlsl/tgmath.hlsl b/include/nbl/builtin/hlsl/tgmath.hlsl index c2f784cfc0..2c76e1b3d0 100644 --- a/include/nbl/builtin/hlsl/tgmath.hlsl +++ b/include/nbl/builtin/hlsl/tgmath.hlsl @@ -231,6 +231,18 @@ inline FrexpOutput frexpStruct(NBL_CONST_REF_ARG(T) val) return tgmath_impl::frexpStruct_helper::__call(val); } +template +inline T lgamma(NBL_CONST_REF_ARG(T) val) +{ + return tgmath_impl::lgamma_helper::__call(val); +} + +template +inline T beta(NBL_CONST_REF_ARG(T) v1, NBL_CONST_REF_ARG(T) v2) +{ + return tgmath_impl::beta_helper::__call(v1, v2); +} + } } diff --git a/include/nbl/builtin/hlsl/tgmath/impl.hlsl b/include/nbl/builtin/hlsl/tgmath/impl.hlsl index e0bdaf731a..c7868154f9 100644 --- a/include/nbl/builtin/hlsl/tgmath/impl.hlsl +++ b/include/nbl/builtin/hlsl/tgmath/impl.hlsl @@ -90,6 +90,11 @@ struct modfStruct_helper; template struct frexpStruct_helper; +template +struct lgamma_helper; +template +struct beta_helper; + #ifdef __HLSL_VERSION #define DECLVAL(r,data,i,_T) BOOST_PP_COMMA_IF(BOOST_PP_NOT_EQUAL(i,0)) experimental::declval<_T>() @@ -203,6 +208,43 @@ struct erf_helper) +struct lgamma_helper +{ + // implementation from Numerical Recipes in C, 2nd ed. + NBL_CONSTEXPR_STATIC_INLINE T coeff[6] = { + 76.18009172947146,-86.50532032941677, + 24.01409824083091,-1.231739572450155, + 0.1208650973866179e-2,-0.5395239384953e-5 + }; + + static T __call(T val) + { + T x, y; + y = x = val; + T tmp = x + T(5.5); + tmp -= (x + T(0.5)) * log_helper::__call(tmp); + + T ser = T(1.000000000190015); + [unroll] + for (uint32_t j = 0; j < 6; j++) + ser += coeff[j] / ++y; + return -tmp + log_helper::__call(T(2.5066282746310005) * ser / x); + } +}; + +// beta function +template) +struct beta_helper +{ + // implementation from Numerical Recipes in C, 2nd ed. + static T __call(T v1, T v2) + { + return exp_helper::__call(lgamma_helper::__call(v1) + lgamma_helper::__call(v2) - lgamma_helper::__call(v1+v2)); + } +}; + #else // C++ only specializations @@ -248,6 +290,9 @@ template AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(round_helper, round, co template AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(trunc_helper, trunc, concepts::FloatingPointScalar, (T), (T), T) template AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(ceil_helper, ceil, concepts::FloatingPointScalar, (T), (T), T) +template AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(lgamma_helper, lgamma, concepts::FloatingPointScalar, (T), (T), T) +template AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(beta_helper, beta, concepts::FloatingPointScalar, (T), (T)(T), T) + #undef DECL_ARG #undef WRAP #undef ARG From 2e6de670aa2aa4e7b527dd07607a4255253eca7e Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 16 Jul 2025 15:13:11 +0700 Subject: [PATCH 120/188] fix templating and bugs with beta, lgamma --- include/nbl/builtin/hlsl/tgmath/impl.hlsl | 25 +++++++++++------------ 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/include/nbl/builtin/hlsl/tgmath/impl.hlsl b/include/nbl/builtin/hlsl/tgmath/impl.hlsl index c7868154f9..4cc363dd0f 100644 --- a/include/nbl/builtin/hlsl/tgmath/impl.hlsl +++ b/include/nbl/builtin/hlsl/tgmath/impl.hlsl @@ -209,16 +209,11 @@ struct erf_helper) -struct lgamma_helper +template +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) +struct lgamma_helper) > { // implementation from Numerical Recipes in C, 2nd ed. - NBL_CONSTEXPR_STATIC_INLINE T coeff[6] = { - 76.18009172947146,-86.50532032941677, - 24.01409824083091,-1.231739572450155, - 0.1208650973866179e-2,-0.5395239384953e-5 - }; - static T __call(T val) { T x, y; @@ -227,16 +222,20 @@ struct lgamma_helper tmp -= (x + T(0.5)) * log_helper::__call(tmp); T ser = T(1.000000000190015); - [unroll] - for (uint32_t j = 0; j < 6; j++) - ser += coeff[j] / ++y; + ser += T(76.18009172947146) / ++y; + ser += T(-86.50532032941677) / ++y; + ser += T(24.01409824083091) / ++y; + ser += T(-1.231739572450155) / ++y; + ser += T(0.1208650973866179e-2) / ++y; + ser += T(-0.5395239384953e-5) / ++y; return -tmp + log_helper::__call(T(2.5066282746310005) * ser / x); } }; // beta function -template) -struct beta_helper +template +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) +struct beta_helper) > { // implementation from Numerical Recipes in C, 2nd ed. static T __call(T v1, T v2) From 97637f973b8d55c57516a1aa5bd9a2a77ddd8b11 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 16 Jul 2025 16:56:40 +0700 Subject: [PATCH 121/188] use beta function in transmission case for beckmann ndf --- include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 4 +-- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 25 ++++++++++++++----- .../hlsl/bxdf/reflection/beckmann.hlsl | 4 +-- .../hlsl/bxdf/transmission/beckmann.hlsl | 6 +++-- 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl index 358b7a4139..4a5b5a4d5f 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -16,10 +16,10 @@ namespace bxdf namespace ndf { -template +template struct Beckmann; -template +template struct GGX; // common diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index 6e95479184..2d504896d4 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -16,11 +16,15 @@ namespace bxdf namespace ndf { +// template +// struct Beckmann; + // TODO: get beta from lgamma, see: https://www.cec.uchile.cl/cinetica/pcordero/MC_libros/NumericalRecipesinC.pdf // TODO: use query_type for D, lambda, beta, DG1 when that's implemented template -struct Beckmann +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) +struct Beckmann) > { using scalar_type = T; using this_t = Beckmann; @@ -78,10 +82,14 @@ struct Beckmann return G1(L_v + L_l); } - scalar_type G2_over_G1(scalar_type a2, scalar_type NdotL2, scalar_type lambdaV_plus_one) + scalar_type G2_over_G1(scalar_type a2, bool transmitted, scalar_type NdotL2, scalar_type lambdaV_plus_one) { scalar_type lambdaL = Lambda(NdotL2, a2); - return lambdaV_plus_one / (lambdaV_plus_one + lambdaL); + return hlsl::mix( + lambdaV_plus_one / (lambdaV_plus_one + lambdaL), + lambdaV_plus_one * hlsl::beta(lambdaV_plus_one, scalar_type(1.0) + lambdaL), + transmitted + ); } scalar_type onePlusLambda_V; @@ -89,7 +97,8 @@ struct Beckmann template -struct Beckmann +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) +struct Beckmann) > { using scalar_type = T; @@ -148,11 +157,15 @@ struct Beckmann return G1(L_v + L_l); } - scalar_type G2_over_G1(scalar_type ax2, scalar_type ay2, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2, scalar_type lambdaV_plus_one) + scalar_type G2_over_G1(scalar_type ax2, scalar_type ay2, bool transmitted, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2, scalar_type lambdaV_plus_one) { scalar_type c2 = C2(TdotL2, BdotL2, NdotL2, ax2, ay2); scalar_type lambdaL = Lambda(c2); - return lambdaV_plus_one / (lambdaV_plus_one + lambdaL); + return hlsl::mix( + lambdaV_plus_one / (lambdaV_plus_one + lambdaL), + lambdaV_plus_one * hlsl::beta(lambdaV_plus_one, scalar_type(1.0) + lambdaL), + transmitted + ); } scalar_type onePlusLambda_V; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index b413bfabc3..6056f4caf1 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -325,7 +325,7 @@ struct SBeckmannBxDF spectral_type quo = (spectral_type)0.0; if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) { - scalar_type G2_over_G1 = beckmann_ndf.G2_over_G1(A.x*A.x, params.getNdotL2(), onePlusLambda_V); + scalar_type G2_over_G1 = beckmann_ndf.G2_over_G1(A.x*A.x, false, params.getNdotL2(), onePlusLambda_V); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; @@ -342,7 +342,7 @@ struct SBeckmannBxDF spectral_type quo = (spectral_type)0.0; if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) { - scalar_type G2_over_G1 = beckmann_ndf.G2_over_G1(A.x*A.x, A.y*A.y, params.getTdotL2(), params.getBdotL2(), params.getNdotL2(), onePlusLambda_V); + scalar_type G2_over_G1 = beckmann_ndf.G2_over_G1(A.x*A.x, A.y*A.y, false, params.getTdotL2(), params.getBdotL2(), params.getNdotL2(), onePlusLambda_V); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 2f41fbd41e..ed5ff90347 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -284,10 +284,11 @@ struct SBeckmannDielectricBxDF { scalar_type onePlusLambda_V; scalar_type _pdf = pdf(params, onePlusLambda_V); + const bool transmitted = params.getVdotH() * params.getLdotH() < 0.0; scalar_type quo; ndf::Beckmann beckmann_ndf; - quo = beckmann_ndf.G2_over_G1(A.x*A.x, params.getNdotL2(), onePlusLambda_V); + quo = beckmann_ndf.G2_over_G1(A.x*A.x, transmitted, params.getNdotL2(), onePlusLambda_V); return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } @@ -295,10 +296,11 @@ struct SBeckmannDielectricBxDF { scalar_type onePlusLambda_V; scalar_type _pdf = pdf(params, onePlusLambda_V); + const bool transmitted = params.getVdotH() * params.getLdotH() < 0.0; scalar_type quo; ndf::Beckmann beckmann_ndf; - quo = beckmann_ndf.G2_over_G1(A.x*A.x, A.y*A.y, params.getTdotL2(), params.getBdotL2(), params.getNdotL2(), onePlusLambda_V); + quo = beckmann_ndf.G2_over_G1(A.x*A.x, A.y*A.y, transmitted, params.getTdotL2(), params.getBdotL2(), params.getNdotL2(), onePlusLambda_V); return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } From 3966339c9bb8227d852fb145b079bfeb64967a0c Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 17 Jul 2025 11:51:16 +0700 Subject: [PATCH 122/188] ggx using beta function for transmission --- include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 49 ++++++++++++++----- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 6 +-- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 6 ++- 3 files changed, 44 insertions(+), 17 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index f9c4258e67..5868a94a4f 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -18,7 +18,8 @@ namespace ndf // TODO: use query_type when that's implemented template -struct GGX +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) +struct GGX) > { using scalar_type = T; using this_t = GGX; @@ -77,19 +78,33 @@ struct GGX return scalar_type(0.5) / (Vterm + Lterm); } - scalar_type G2_over_G1(scalar_type a2, scalar_type NdotV, scalar_type NdotV2, scalar_type NdotL, scalar_type NdotL2) + scalar_type G2_over_G1(scalar_type a2, bool transmitted, scalar_type NdotV, scalar_type NdotV2, scalar_type NdotL, scalar_type NdotL2) { - scalar_type one_minus_a2 = scalar_type(1.0) - a2; - scalar_type devsh_v = devsh_part(NdotV2, a2, one_minus_a2); - scalar_type G2_over_G1 = NdotL * (devsh_v + NdotV); // alternative `Vterm+NdotL*NdotV /// NdotL*NdotV could come as a parameter - G2_over_G1 /= NdotV * devsh_part(NdotL2, a2, one_minus_a2) + NdotL * devsh_v; + scalar_type G2_over_G1; + if (transmitted) + { + scalar_type one_minus_a2 = scalar_type(1.0) - a2; + scalar_type devsh_v = devsh_part(NdotV2, a2, one_minus_a2); + scalar_type L_v = 0.5 * (devsh_v / NdotV - 1.0); + scalar_type L_l = 0.5 * (devsh_part(NdotL2, a2, one_minus_a2) / NdotL - 1.0); + G2_over_G1 = hlsl::beta(1.0 + L_l, 1.0 + L_v); + G2_over_G1 *= 1.0 + L_v; + } + else + { + scalar_type one_minus_a2 = scalar_type(1.0) - a2; + scalar_type devsh_v = devsh_part(NdotV2, a2, one_minus_a2); + G2_over_G1 = NdotL * (devsh_v + NdotV); // alternative `Vterm+NdotL*NdotV /// NdotL*NdotV could come as a parameter + G2_over_G1 /= NdotV * devsh_part(NdotL2, a2, one_minus_a2) + NdotL * devsh_v; + } return G2_over_G1; } }; template -struct GGX +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) +struct GGX) > { using scalar_type = T; @@ -145,11 +160,23 @@ struct GGX return 0.5 / (Vterm + Lterm); } - scalar_type G2_over_G1(scalar_type ax2, scalar_type ay2, scalar_type NdotV, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type NdotL, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2) + scalar_type G2_over_G1(scalar_type ax2, scalar_type ay2, bool transmitted, scalar_type NdotV, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type NdotL, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2) { - scalar_type devsh_v = devsh_part(TdotV2, BdotV2, NdotV2, ax2, ay2); - scalar_type G2_over_G1 = NdotL * (devsh_v + NdotV); - G2_over_G1 /= NdotV * devsh_part(TdotL2, BdotL2, NdotL2, ax2, ay2) + NdotL * devsh_v; + scalar_type G2_over_G1; + if (transmitted) + { + scalar_type devsh_v = devsh_part(TdotV2, BdotV2, NdotV2, ax2, ay2); + scalar_type L_v = 0.5 * (devsh_v / NdotV - 1.0); + scalar_type L_l = 0.5 * (devsh_part(TdotL2, BdotL2, NdotL2, ax2, ay2) / NdotL - 1.0); + G2_over_G1 = hlsl::beta(1.0 + L_l, 1.0 + L_v); + G2_over_G1 *= 1.0 + L_v; + } + else + { + scalar_type devsh_v = devsh_part(TdotV2, BdotV2, NdotV2, ax2, ay2); + G2_over_G1 = NdotL * (devsh_v + NdotV); + G2_over_G1 /= NdotV * devsh_part(TdotL2, BdotL2, NdotL2, ax2, ay2) + NdotL * devsh_v; + } return G2_over_G1; } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index fab05d1d79..c069367388 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -264,11 +264,10 @@ struct SGGXBxDF spectral_type quo = (spectral_type)0.0; if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) { - scalar_type G2_over_G1; ndf::GGX ggx_ndf; const scalar_type a2 = A.x*A.x; - G2_over_G1 = ggx_ndf.G2_over_G1(a2, params.getNdotVUnclamped(), params.getNdotV2(), params.getNdotLUnclamped(), params.getNdotL2()); + const scalar_type G2_over_G1 = ggx_ndf.G2_over_G1(a2, false, params.getNdotVUnclamped(), params.getNdotV2(), params.getNdotLUnclamped(), params.getNdotL2()); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); @@ -284,12 +283,11 @@ struct SGGXBxDF spectral_type quo = (spectral_type)0.0; if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) { - scalar_type G2_over_G1; ndf::GGX ggx_ndf; const scalar_type ax2 = A.x*A.x; const scalar_type ay2 = A.y*A.y; - G2_over_G1 = ggx_ndf.G2_over_G1(ax2, ay2, params.getNdotVUnclamped(), params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getNdotLUnclamped(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); + const scalar_type G2_over_G1 = ggx_ndf.G2_over_G1(ax2, ay2, false, params.getNdotVUnclamped(), params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getNdotLUnclamped(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index c402c38190..fae6f782bb 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -274,10 +274,11 @@ struct SGGXDielectricBxDF const scalar_type ay2 = A.y*A.y; scalar_type _pdf = pdf(params); + const bool transmitted = params.getVdotH() * params.getLdotH() < 0.0; ndf::GGX ggx_ndf; scalar_type quo; - quo = ggx_ndf.G2_over_G1(ax2, params.getNdotV(), params.getNdotV2(), params.getNdotL(), params.getNdotL2()); + quo = ggx_ndf.G2_over_G1(ax2, transmitted, params.getNdotV(), params.getNdotV2(), params.getNdotL(), params.getNdotL2()); return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } @@ -287,10 +288,11 @@ struct SGGXDielectricBxDF const scalar_type ay2 = A.y*A.y; scalar_type _pdf = pdf(params); + const bool transmitted = params.getVdotH() * params.getLdotH() < 0.0; ndf::GGX ggx_ndf; scalar_type quo; - quo = ggx_ndf.G2_over_G1(ax2, ay2, params.getNdotV(), params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getNdotL(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); + quo = ggx_ndf.G2_over_G1(ax2, ay2, transmitted, params.getNdotV(), params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getNdotL(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } From 13cc7c3a3d7e61f1f0e502300e5a2cbf7fba8ba0 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 17 Jul 2025 14:05:37 +0700 Subject: [PATCH 123/188] add casting for ggx ndf --- include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index 5868a94a4f..9e26974c21 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -85,10 +85,10 @@ struct GGX) > { scalar_type one_minus_a2 = scalar_type(1.0) - a2; scalar_type devsh_v = devsh_part(NdotV2, a2, one_minus_a2); - scalar_type L_v = 0.5 * (devsh_v / NdotV - 1.0); - scalar_type L_l = 0.5 * (devsh_part(NdotL2, a2, one_minus_a2) / NdotL - 1.0); - G2_over_G1 = hlsl::beta(1.0 + L_l, 1.0 + L_v); - G2_over_G1 *= 1.0 + L_v; + scalar_type L_v = scalar_type(0.5) * (devsh_v / NdotV - scalar_type(1.0)); + scalar_type L_l = scalar_type(0.5) * (devsh_part(NdotL2, a2, one_minus_a2) / NdotL - scalar_type(1.0)); + G2_over_G1 = hlsl::beta(scalar_type(1.0) + L_l, scalar_type(1.0) + L_v); + G2_over_G1 *= scalar_type(1.0) + L_v; } else { @@ -157,7 +157,7 @@ struct GGX) > { scalar_type Vterm = NdotL * devsh_part(TdotV2, BdotV2, NdotV2, ax2, ay2); scalar_type Lterm = NdotV * devsh_part(TdotL2, BdotL2, NdotL2, ax2, ay2); - return 0.5 / (Vterm + Lterm); + return scalar_type(0.5) / (Vterm + Lterm); } scalar_type G2_over_G1(scalar_type ax2, scalar_type ay2, bool transmitted, scalar_type NdotV, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type NdotL, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2) @@ -166,10 +166,10 @@ struct GGX) > if (transmitted) { scalar_type devsh_v = devsh_part(TdotV2, BdotV2, NdotV2, ax2, ay2); - scalar_type L_v = 0.5 * (devsh_v / NdotV - 1.0); - scalar_type L_l = 0.5 * (devsh_part(TdotL2, BdotL2, NdotL2, ax2, ay2) / NdotL - 1.0); - G2_over_G1 = hlsl::beta(1.0 + L_l, 1.0 + L_v); - G2_over_G1 *= 1.0 + L_v; + scalar_type L_v = scalar_type(0.5) * (devsh_v / NdotV - scalar_type(1.0)); + scalar_type L_l = scalar_type(0.5) * (devsh_part(TdotL2, BdotL2, NdotL2, ax2, ay2) / NdotL - scalar_type(1.0)); + G2_over_G1 = hlsl::beta(scalar_type(1.0) + L_l, scalar_type(1.0) + L_v); + G2_over_G1 *= scalar_type(1.0) + L_v; } else { From 0538049c4c67015cd17acb5179eb1edfdd19bc5a Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 18 Jul 2025 10:56:36 +0700 Subject: [PATCH 124/188] clean up mix_helper partial specs --- .../hlsl/cpp_compat/impl/intrinsics_impl.hlsl | 39 +++++++++++++------ .../builtin/hlsl/spirv_intrinsics/core.hlsl | 6 ++- .../hlsl/spirv_intrinsics/glsl.std.450.hlsl | 3 ++ 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl b/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl index 0c4c4a4b69..c38b9a1e66 100644 --- a/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl +++ b/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl @@ -39,6 +39,21 @@ inline bool isinf_uint_impl(UnsignedInteger val) return (val & (~ieee754::traits::signMask)) == ieee754::traits::inf; } +namespace impl +{ +#ifndef __HLSL_VERSION +template +NBL_BOOL_CONCEPT MixIsCallable = always_true(), declval(), declval()))>; +#endif +template +NBL_BOOL_CONCEPT MixCallingBuiltins = +#ifdef __HLSL_VERSION +spirv::FMixIsCallable || spirv::SelectIsCallable; +#else +MixIsCallable; +#endif +} + template struct dot_helper; template @@ -230,8 +245,8 @@ struct inverse_helper NBL_PARTIAL_REQ_TOP(always_true(experimental::declval(), experimental::declval(), experimental::declval()))>) -struct mix_helper(experimental::declval(), experimental::declval(), experimental::declval()))>) > +template NBL_PARTIAL_REQ_TOP(spirv::FMixIsCallable) +struct mix_helper) > { using return_t = conditional_t, vector::scalar_type, vector_traits::Dimension>, T>; static inline return_t __call(const T x, const T y, const T a) @@ -241,8 +256,8 @@ struct mix_helper(e }; template -NBL_PARTIAL_REQ_TOP(concepts::Boolean && ((concepts::Vector && concepts::Vector && vector_traits::Dimension==vector_traits::Dimension) || concepts::Scalar)) -struct mix_helper && ((concepts::Vector && concepts::Vector && vector_traits::Dimension==vector_traits::Dimension) || concepts::Scalar)) > +NBL_PARTIAL_REQ_TOP(spirv::SelectIsCallable) +struct mix_helper) > { using return_t = conditional_t, vector::scalar_type, vector_traits::Dimension>, T>; // for a component of a that is false, the corresponding component of x is returned @@ -445,13 +460,13 @@ struct bitCount_helper }; template -requires (concepts::FloatingPointScalar && (concepts::FloatingPointScalar || concepts::BooleanScalar)) +requires (impl::MixIsCallable /*&& (concepts::FloatingPointScalar || concepts::FloatingPointVector) && (concepts::FloatingPointScalar || concepts::Boolean || ((concepts::Vector || concepts::FloatingPointVector) && vector_traits::Dimension==vector_traits::Dimension))*/) struct mix_helper { using return_t = T; static inline return_t __call(const T x, const T y, const U a) { - return glm::mix(x, y, a); + return glm::mix(x, y, a); } }; @@ -848,8 +863,8 @@ struct smoothStep_helper }; template -NBL_PARTIAL_REQ_TOP(VECTOR_SPECIALIZATION_CONCEPT) -struct mix_helper +NBL_PARTIAL_REQ_TOP(VECTOR_SPECIALIZATION_CONCEPT && !impl::MixCallingBuiltins) +struct mix_helper) > { using return_t = T; static return_t __call(NBL_CONST_REF_ARG(T) x, NBL_CONST_REF_ARG(T) y, NBL_CONST_REF_ARG(T) a) @@ -867,8 +882,8 @@ struct mix_helper }; template -NBL_PARTIAL_REQ_TOP(VECTOR_SPECIALIZATION_CONCEPT&& concepts::Boolean&& !(vector_traits::Dimension == vector_traits::Dimension) && concepts::BooleanScalar) -struct mix_helper&& !(vector_traits::Dimension == vector_traits::Dimension) && concepts::BooleanScalar) > +NBL_PARTIAL_REQ_TOP(VECTOR_SPECIALIZATION_CONCEPT && !impl::MixCallingBuiltins && concepts::BooleanScalar) +struct mix_helper && concepts::BooleanScalar) > { using return_t = T; static return_t __call(NBL_CONST_REF_ARG(T) x, NBL_CONST_REF_ARG(T) y, NBL_CONST_REF_ARG(U) a) @@ -886,8 +901,8 @@ struct mix_helper -NBL_PARTIAL_REQ_TOP(VECTOR_SPECIALIZATION_CONCEPT && concepts::Boolean && vector_traits::Dimension == vector_traits::Dimension) -struct mix_helper && vector_traits::Dimension == vector_traits::Dimension) > +NBL_PARTIAL_REQ_TOP(VECTOR_SPECIALIZATION_CONCEPT && !impl::MixCallingBuiltins && concepts::Boolean && concepts::Vectorial && vector_traits::Dimension == vector_traits::Dimension) +struct mix_helper && concepts::Boolean && concepts::Vectorial && vector_traits::Dimension == vector_traits::Dimension) > { using return_t = T; static return_t __call(NBL_CONST_REF_ARG(T) x, NBL_CONST_REF_ARG(T) y, NBL_CONST_REF_ARG(U) a) diff --git a/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl b/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl index 88941b8d6d..125a833796 100644 --- a/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl +++ b/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl @@ -10,6 +10,7 @@ #include #include #include +#include #include namespace nbl @@ -356,10 +357,13 @@ template && !is_matrix_v) conditional_t, vector::Dimension>, bool> FOrdEqual(T lhs, T rhs); -template && (is_scalar_v || (is_vector_v && is_vector_v && vector_traits::Dimension==vector_traits::Dimension)) && is_same_v::scalar_type, bool>) +template && (!concepts::Vector || (concepts::Vector && vector_traits::Dimension==vector_traits::Dimension))) [[vk::ext_instruction(spv::OpSelect)]] T select(U a, T x, T y); +template +NBL_BOOL_CONCEPT SelectIsCallable = always_true(),experimental::declval(),experimental::declval()))>; + } #endif diff --git a/include/nbl/builtin/hlsl/spirv_intrinsics/glsl.std.450.hlsl b/include/nbl/builtin/hlsl/spirv_intrinsics/glsl.std.450.hlsl index feda59e45c..b08087a299 100644 --- a/include/nbl/builtin/hlsl/spirv_intrinsics/glsl.std.450.hlsl +++ b/include/nbl/builtin/hlsl/spirv_intrinsics/glsl.std.450.hlsl @@ -95,6 +95,9 @@ template) [[vk::ext_instruction(GLSLstd450::GLSLstd450FMix, "GLSL.std.450")]] T fMix(T x, T y, T a); +template +NBL_BOOL_CONCEPT FMixIsCallable = always_true(experimental::declval(), experimental::declval(), experimental::declval()))>; + template::Square) [[vk::ext_instruction(GLSLstd450::GLSLstd450Determinant, "GLSL.std.450")]] typename matrix_traits::scalar_type determinant(NBL_CONST_REF_ARG(SquareMatrix) mat); From d93c19411623284fc92cdca206faf38c93081690 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 18 Jul 2025 12:00:10 +0700 Subject: [PATCH 125/188] minor fixes: flipSign_helper, rank, extent --- include/nbl/builtin/hlsl/ieee754.hlsl | 6 ++++++ include/nbl/builtin/hlsl/type_traits.hlsl | 8 -------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/include/nbl/builtin/hlsl/ieee754.hlsl b/include/nbl/builtin/hlsl/ieee754.hlsl index a32ba589f2..6bdfcf2514 100644 --- a/include/nbl/builtin/hlsl/ieee754.hlsl +++ b/include/nbl/builtin/hlsl/ieee754.hlsl @@ -3,6 +3,7 @@ #include #include +#include namespace nbl { @@ -156,7 +157,12 @@ struct flipSign_helper::type; using AsUint = typename unsigned_integer_of_size::type; const AsUint asUint = ieee754::impl::bitCastToUintType(val); + // can't use mix_helper because circular dep +#ifdef __HLSL_VERSION + return bit_cast(asUint ^ spirv::select(AsUint(0ull), ieee754::traits::signMask, flip)); +#else return bit_cast(asUint ^ (flip ? ieee754::traits::signMask : AsUint(0ull))); +#endif } }; diff --git a/include/nbl/builtin/hlsl/type_traits.hlsl b/include/nbl/builtin/hlsl/type_traits.hlsl index 2bad563829..a9701619dd 100644 --- a/include/nbl/builtin/hlsl/type_traits.hlsl +++ b/include/nbl/builtin/hlsl/type_traits.hlsl @@ -598,12 +598,6 @@ using is_aggregate = std::is_aggregate; template using type_identity = std::type_identity; -template -using rank = std::rank; - -template -struct extent : std::extent {}; - template using enable_if = std::enable_if; @@ -694,7 +688,6 @@ template NBL_CONSTEXPR bool is_matrix_v = is_matrix::value; -#ifdef __HLSL_VERSION template struct rank : integral_constant, 0> : integral_constant {}; template struct extent, I> : integral_constant::value> {}; -#endif // Template Variables From e3a4d8c146c7c4311056c184c354d896526916f0 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 18 Jul 2025 16:29:25 +0700 Subject: [PATCH 126/188] additional template partial spec on equal_helper --- include/nbl/builtin/hlsl/glsl_compat/core.hlsl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/nbl/builtin/hlsl/glsl_compat/core.hlsl b/include/nbl/builtin/hlsl/glsl_compat/core.hlsl index 88d2f4b7a6..c36bfd207c 100644 --- a/include/nbl/builtin/hlsl/glsl_compat/core.hlsl +++ b/include/nbl/builtin/hlsl/glsl_compat/core.hlsl @@ -245,8 +245,8 @@ struct equal_helper; #ifdef __HLSL_VERSION template -NBL_PARTIAL_REQ_TOP(concepts::Vectorial && concepts::Integral) -struct equal_helper && concepts::Integral) > +NBL_PARTIAL_REQ_TOP(always_true(experimental::declval(),experimental::declval()))> && concepts::Vectorial && concepts::Integral) +struct equal_helper(experimental::declval(),experimental::declval()))> && concepts::Vectorial && concepts::Integral) > { using return_t = vector::Dimension>; @@ -257,8 +257,8 @@ struct equal_helper }; template -NBL_PARTIAL_REQ_TOP(concepts::Vectorial && concepts::FloatingPoint) -struct equal_helper && concepts::FloatingPoint) > +NBL_PARTIAL_REQ_TOP(always_true(experimental::declval(),experimental::declval()))> && concepts::Vectorial && concepts::FloatingPoint) +struct equal_helper(experimental::declval(),experimental::declval()))> && concepts::Vectorial && concepts::FloatingPoint) > { using return_t = vector::Dimension>; From 8bfd9f5349fd48272596ebbec943c6b549c76ea9 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 18 Jul 2025 16:58:30 +0700 Subject: [PATCH 127/188] changed sampling header names to reflect working on spheres --- examples_tests | 2 +- .../nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl | 2 +- include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 2 +- .../builtin/hlsl/bxdf/reflection/lambertian.hlsl | 2 +- .../builtin/hlsl/bxdf/reflection/oren_nayar.hlsl | 2 +- .../builtin/hlsl/bxdf/transmission/beckmann.hlsl | 2 +- .../nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl | 2 +- .../builtin/hlsl/bxdf/transmission/lambertian.hlsl | 2 +- .../hlsl/bxdf/transmission/smooth_dielectric.hlsl | 2 +- ...cos_weighted.hlsl => cos_weighted_spheres.hlsl} | 4 ++-- .../{uniform.hlsl => uniform_spheres.hlsl} | 4 ++-- src/nbl/builtin/CMakeLists.txt | 14 ++++++++++++-- 12 files changed, 25 insertions(+), 15 deletions(-) rename include/nbl/builtin/hlsl/sampling/{cos_weighted.hlsl => cos_weighted_spheres.hlsl} (94%) rename include/nbl/builtin/hlsl/sampling/{uniform.hlsl => uniform_spheres.hlsl} (93%) diff --git a/examples_tests b/examples_tests index da0ed36ca1..dbd75ea02a 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit da0ed36ca1de51d30ffc19e972c1c038694cd681 +Subproject commit dbd75ea02aeff229d693a50b78c285692e4fde68 diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 6056f4caf1..0a824895ca 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -5,7 +5,7 @@ #define _NBL_BUILTIN_HLSL_BXDF_REFLECTION_BECKMANN_INCLUDED_ #include "nbl/builtin/hlsl/bxdf/common.hlsl" -#include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" +#include "nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl" #include "nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl" namespace nbl diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index c069367388..4a10de13a3 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -5,7 +5,7 @@ #define _NBL_BUILTIN_HLSL_BXDF_REFLECTION_GGX_INCLUDED_ #include "nbl/builtin/hlsl/bxdf/common.hlsl" -#include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" +#include "nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl" #include "nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl" namespace nbl diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl index 029a32569e..f25a128b20 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl @@ -5,7 +5,7 @@ #define _NBL_BUILTIN_HLSL_BXDF_REFLECTION_LAMBERTIAN_INCLUDED_ #include "nbl/builtin/hlsl/bxdf/common.hlsl" -#include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" +#include "nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl" namespace nbl { diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl index 700292d0c8..9792f03ed0 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl @@ -5,7 +5,7 @@ #define _NBL_BUILTIN_HLSL_BXDF_REFLECTION_OREN_NAYAR_INCLUDED_ #include "nbl/builtin/hlsl/bxdf/common.hlsl" -#include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" +#include "nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl" namespace nbl { diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index ed5ff90347..e9504edf94 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -5,7 +5,7 @@ #define _NBL_BUILTIN_HLSL_BXDF_TRANSMISSION_BECKMANN_INCLUDED_ #include "nbl/builtin/hlsl/bxdf/common.hlsl" -#include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" +#include "nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl" #include "nbl/builtin/hlsl/bxdf/reflection.hlsl" namespace nbl diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index fae6f782bb..9ed573b581 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -5,7 +5,7 @@ #define _NBL_BUILTIN_HLSL_BXDF_TRANSMISSION_GGX_INCLUDED_ #include "nbl/builtin/hlsl/bxdf/common.hlsl" -#include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" +#include "nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl" #include "nbl/builtin/hlsl/bxdf/reflection.hlsl" namespace nbl diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl index 1138c2a06c..1f16b1e53b 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl @@ -5,7 +5,7 @@ #define _NBL_BUILTIN_HLSL_BXDF_TRANSMISSION_LAMBERTIAN_INCLUDED_ #include "nbl/builtin/hlsl/bxdf/common.hlsl" -#include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" +#include "nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl" #include "nbl/builtin/hlsl/bxdf/reflection.hlsl" namespace nbl diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index 83b382119d..82e27d4a33 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -5,7 +5,7 @@ #define _NBL_BUILTIN_HLSL_BXDF_TRANSMISSION_SMOOTH_DIELECTRIC_INCLUDED_ #include "nbl/builtin/hlsl/bxdf/common.hlsl" -#include "nbl/builtin/hlsl/sampling/cos_weighted.hlsl" +#include "nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl" namespace nbl { diff --git a/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl b/include/nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl similarity index 94% rename from include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl rename to include/nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl index d80778ed9a..8cf321ad24 100644 --- a/include/nbl/builtin/hlsl/sampling/cos_weighted.hlsl +++ b/include/nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl @@ -2,8 +2,8 @@ // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h -#ifndef _NBL_BUILTIN_HLSL_SAMPLING_COS_WEIGHTED_INCLUDED_ -#define _NBL_BUILTIN_HLSL_SAMPLING_COS_WEIGHTED_INCLUDED_ +#ifndef _NBL_BUILTIN_HLSL_SAMPLING_COS_WEIGHTED_SPHERES_INCLUDED_ +#define _NBL_BUILTIN_HLSL_SAMPLING_COS_WEIGHTED_SPHERES_INCLUDED_ #include "nbl/builtin/hlsl/concepts.hlsl" #include "nbl/builtin/hlsl/sampling/concentric_mapping.hlsl" diff --git a/include/nbl/builtin/hlsl/sampling/uniform.hlsl b/include/nbl/builtin/hlsl/sampling/uniform_spheres.hlsl similarity index 93% rename from include/nbl/builtin/hlsl/sampling/uniform.hlsl rename to include/nbl/builtin/hlsl/sampling/uniform_spheres.hlsl index 69a83d5a93..d7189f7c97 100644 --- a/include/nbl/builtin/hlsl/sampling/uniform.hlsl +++ b/include/nbl/builtin/hlsl/sampling/uniform_spheres.hlsl @@ -2,8 +2,8 @@ // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h -#ifndef _NBL_BUILTIN_HLSL_SAMPLING_UNIFORM_INCLUDED_ -#define _NBL_BUILTIN_HLSL_SAMPLING_UNIFORM_INCLUDED_ +#ifndef _NBL_BUILTIN_HLSL_SAMPLING_UNIFORM_SPHERES_INCLUDED_ +#define _NBL_BUILTIN_HLSL_SAMPLING_UNIFORM_SPHERES_INCLUDED_ #include "nbl/builtin/hlsl/concepts.hlsl" #include "nbl/builtin/hlsl/numbers.hlsl" diff --git a/src/nbl/builtin/CMakeLists.txt b/src/nbl/builtin/CMakeLists.txt index ae057f43e7..19712f4cd0 100644 --- a/src/nbl/builtin/CMakeLists.txt +++ b/src/nbl/builtin/CMakeLists.txt @@ -318,8 +318,8 @@ LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/shapes/line.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/shapes/beziers.hlsl") #sampling LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/sampling/concentric_mapping.hlsl") -LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/sampling/cos_weighted.hlsl") -LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/sampling/uniform.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/sampling/cos_weighted_spheres.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/sampling/uniform_spheres.hlsl") # LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/ndarray_addressing.hlsl") # @@ -337,6 +337,16 @@ LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/ndf.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/reflection.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/transmission.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/bxdf_traits.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/ndf/beckmann.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/ndf/ggx.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/reflection/beckmann.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/reflection/ggx.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/reflection/lambertian.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/reflection/oren_nayar.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/transmission/beckmann.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/transmission/ggx.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/transmission/lambertian.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/transmission/smooth_dielectric.hlsl") #subgroup LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/subgroup/ballot.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/subgroup/basic.hlsl") From dfa787f02b27417bf31211424de4d2cb08aed5ab Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 21 Jul 2025 10:37:39 +0700 Subject: [PATCH 128/188] quotient_and_pdf only takes vectors now, use vec1 in place of scalar --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 9 +++++++-- .../hlsl/bxdf/reflection/lambertian.hlsl | 8 ++++---- .../hlsl/bxdf/transmission/lambertian.hlsl | 8 ++++---- .../hlsl/sampling/cos_weighted_spheres.hlsl | 20 +++++++++++-------- .../hlsl/sampling/quotient_and_pdf.hlsl | 8 +------- .../hlsl/sampling/uniform_spheres.hlsl | 10 ++++++---- 6 files changed, 34 insertions(+), 29 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index be96dead88..c36e77599e 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -770,7 +770,7 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param_iso)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param_aniso)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(LightSample, typename T::sample_type)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(sampling::Spectral, typename T::spectral_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(concepts::FloatingPointLikeVectorial, typename T::spectral_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Isotropic, typename T::isotropic_interaction_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Anisotropic, typename T::anisotropic_interaction_type)) ); @@ -830,7 +830,7 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param_iso)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param_aniso)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(LightSample, typename T::sample_type)) - ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(sampling::Spectral, typename T::spectral_type)) + ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(concepts::FloatingPointLikeVectorial, typename T::spectral_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(CreatableIsotropicMicrofacetCache, typename T::isocache_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(AnisotropicMicrofacetCache, typename T::anisocache_type)) ); @@ -854,6 +854,11 @@ enum BxDFClampMode : uint16_t BCM_ABS }; +template +using quotient_and_pdf_scalar = sampling::quotient_and_pdf, float32_t> ; +template +using quotient_and_pdf_rgb = sampling::quotient_and_pdf, T> ; + } } } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl index f25a128b20..cf33394808 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl @@ -147,13 +147,13 @@ struct SLambertianBxDF quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) { - sampling::quotient_and_pdf qp = sampling::ProjectedHemisphere::template quotient_and_pdf(params.getNdotL()); - return quotient_pdf_type::create(hlsl::promote(qp.quotient), qp.pdf); + sampling::quotient_and_pdf, scalar_type> qp = sampling::ProjectedHemisphere::template quotient_and_pdf(params.getNdotL()); + return quotient_pdf_type::create(hlsl::promote(qp.quotient[0]), qp.pdf); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { - sampling::quotient_and_pdf qp = sampling::ProjectedHemisphere::template quotient_and_pdf(params.getNdotL()); - return quotient_pdf_type::create(hlsl::promote(qp.quotient), qp.pdf); + sampling::quotient_and_pdf, scalar_type> qp = sampling::ProjectedHemisphere::template quotient_and_pdf(params.getNdotL()); + return quotient_pdf_type::create(hlsl::promote(qp.quotient[0]), qp.pdf); } }; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl index 1f16b1e53b..bbafdc0c6f 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl @@ -148,13 +148,13 @@ struct SLambertianBxDF quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) { - sampling::quotient_and_pdf qp = sampling::ProjectedSphere::template quotient_and_pdf(params.getNdotL()); - return quotient_pdf_type::create(hlsl::promote(qp.quotient), qp.pdf); + sampling::quotient_and_pdf, scalar_type> qp = sampling::ProjectedSphere::template quotient_and_pdf(params.getNdotL()); + return quotient_pdf_type::create(hlsl::promote(qp.quotient[0]), qp.pdf); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { - sampling::quotient_and_pdf qp = sampling::ProjectedSphere::template quotient_and_pdf(params.getNdotL()); - return quotient_pdf_type::create(hlsl::promote(qp.quotient), qp.pdf); + sampling::quotient_and_pdf, scalar_type> qp = sampling::ProjectedSphere::template quotient_and_pdf(params.getNdotL()); + return quotient_pdf_type::create(hlsl::promote(qp.quotient[0]), qp.pdf); } }; diff --git a/include/nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl b/include/nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl index 8cf321ad24..72ae719eeb 100644 --- a/include/nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl +++ b/include/nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl @@ -35,15 +35,17 @@ struct ProjectedHemisphere } template) - static sampling::quotient_and_pdf quotient_and_pdf(T L) + static sampling::quotient_and_pdf, T> quotient_and_pdf(T L) { - return sampling::quotient_and_pdf::create(U(1.0), pdf(L)); + using vector_t1 = vector; + return sampling::quotient_and_pdf::create(hlsl::promote(1.0), pdf(L)); } template) - static sampling::quotient_and_pdf quotient_and_pdf(vector_t3 L) + static sampling::quotient_and_pdf, T> quotient_and_pdf(vector_t3 L) { - return sampling::quotient_and_pdf::create(U(1.0), pdf(L.z)); + using vector_t1 = vector; + return sampling::quotient_and_pdf::create(hlsl::promote(1.0), pdf(L.z)); } }; @@ -71,15 +73,17 @@ struct ProjectedSphere } template) - static sampling::quotient_and_pdf quotient_and_pdf(T L) + static sampling::quotient_and_pdf, T> quotient_and_pdf(T L) { - return sampling::quotient_and_pdf::create(U(1.0), pdf(L)); + using vector_t1 = vector; + return sampling::quotient_and_pdf::create(hlsl::promote(1.0), pdf(L)); } template) - static sampling::quotient_and_pdf quotient_and_pdf(vector_t3 L) + static sampling::quotient_and_pdf, T> quotient_and_pdf(vector_t3 L) { - return sampling::quotient_and_pdf::create(U(1.0), pdf(L.z)); + using vector_t1 = vector; + return sampling::quotient_and_pdf::create(hlsl::promote(1.0), pdf(L.z)); } }; diff --git a/include/nbl/builtin/hlsl/sampling/quotient_and_pdf.hlsl b/include/nbl/builtin/hlsl/sampling/quotient_and_pdf.hlsl index 0620b2bad6..6aebd583ea 100644 --- a/include/nbl/builtin/hlsl/sampling/quotient_and_pdf.hlsl +++ b/include/nbl/builtin/hlsl/sampling/quotient_and_pdf.hlsl @@ -15,11 +15,8 @@ namespace hlsl namespace sampling { -template -NBL_BOOL_CONCEPT Spectral = (concepts::Vectorial || concepts::Scalar) && is_floating_point_v::scalar_type>; - // finally fixed the semantic F-up, value/pdf = quotient not remainder -template && is_floating_point_v

) +template && concepts::FloatingPointLikeScalar

) struct quotient_and_pdf { using this_t = quotient_and_pdf; @@ -40,9 +37,6 @@ struct quotient_and_pdf P pdf; }; -typedef quotient_and_pdf quotient_and_pdf_scalar; -typedef quotient_and_pdf, float32_t> quotient_and_pdf_rgb; - } } } diff --git a/include/nbl/builtin/hlsl/sampling/uniform_spheres.hlsl b/include/nbl/builtin/hlsl/sampling/uniform_spheres.hlsl index d7189f7c97..e4c9385499 100644 --- a/include/nbl/builtin/hlsl/sampling/uniform_spheres.hlsl +++ b/include/nbl/builtin/hlsl/sampling/uniform_spheres.hlsl @@ -37,9 +37,10 @@ struct UniformHemisphere } template) - static quotient_and_pdf quotient_and_pdf() + static quotient_and_pdf, T> quotient_and_pdf() { - return quotient_and_pdf::create(U(1.0), pdf()); + using vector_t1 = vector; + return quotient_and_pdf::create(hlsl::promote(1.0), pdf()); } }; @@ -63,9 +64,10 @@ struct UniformSphere } template) - static quotient_and_pdf quotient_and_pdf() + static quotient_and_pdf, T> quotient_and_pdf() { - return quotient_and_pdf::create(U(1.0), pdf()); + using vector_t1 = vector; + return quotient_and_pdf::create(hlsl::promote(1.0), pdf()); } }; } From af82605ea47b18aad15c7116c02d4fb4b871cb53 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 21 Jul 2025 11:20:49 +0700 Subject: [PATCH 129/188] minor fixes to mix, equal intrinsics --- include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl | 4 ++-- include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl b/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl index c38b9a1e66..2dbcc4f4aa 100644 --- a/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl +++ b/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl @@ -48,7 +48,7 @@ NBL_BOOL_CONCEPT MixIsCallable = always_true(), dec template NBL_BOOL_CONCEPT MixCallingBuiltins = #ifdef __HLSL_VERSION -spirv::FMixIsCallable || spirv::SelectIsCallable; +(spirv::FMixIsCallable && is_same_v) || spirv::SelectIsCallable; #else MixIsCallable; #endif @@ -460,7 +460,7 @@ struct bitCount_helper }; template -requires (impl::MixIsCallable /*&& (concepts::FloatingPointScalar || concepts::FloatingPointVector) && (concepts::FloatingPointScalar || concepts::Boolean || ((concepts::Vector || concepts::FloatingPointVector) && vector_traits::Dimension==vector_traits::Dimension))*/) +requires (impl::MixIsCallable) struct mix_helper { using return_t = T; diff --git a/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl b/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl index 125a833796..b0a315272d 100644 --- a/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl +++ b/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl @@ -348,11 +348,11 @@ template) SubBorrowOutput subBorrow(T operand1, T operand2); -template && !is_matrix_v) +template || concepts::IntVector) [[vk::ext_instruction(spv::OpIEqual)]] conditional_t, vector::Dimension>, bool> IEqual(T lhs, T rhs); -template && !is_matrix_v) +template || concepts::FloatingPointVector) [[vk::ext_instruction(spv::OpFOrdEqual)]] conditional_t, vector::Dimension>, bool> FOrdEqual(T lhs, T rhs); From 9b864e294774acd917fcb5f9ab2954fa2969c97c Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 21 Jul 2025 11:45:51 +0700 Subject: [PATCH 130/188] minor fixes to fresnel stuff --- include/nbl/builtin/hlsl/bxdf/fresnel.hlsl | 21 +++++++--------- .../hlsl/bxdf/transmission/beckmann.hlsl | 4 ++-- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 4 ++-- .../bxdf/transmission/smooth_dielectric.hlsl | 24 +++++++++---------- 4 files changed, 25 insertions(+), 28 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl index 9257b9b2cc..b8d028e2aa 100644 --- a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl @@ -178,7 +178,7 @@ struct Reflect vector_type operator()() { - return N * 2.0f * getNdotI() - I; + return operator()(getNdotI()); } vector_type operator()(const scalar_type NdotI) @@ -240,19 +240,17 @@ struct ReflectRefract using vector_type = vector; using scalar_type = T; - static this_t create(NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N, scalar_type rcpOrientedEta) + static this_t create(NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N) { this_t retval; retval._refract = Refract::create(I, N); - retval.rcpOrientedEta = rcpOrientedEta; return retval; } - static this_t create(NBL_CONST_REF_ARG(Refract) refract, scalar_type rcpOrientedEta) + static this_t create(NBL_CONST_REF_ARG(Refract) refract) { this_t retval; retval._refract = refract; - retval.rcpOrientedEta = rcpOrientedEta; return retval; } @@ -263,23 +261,23 @@ struct ReflectRefract } // when you know you'll refract - scalar_type getNdotT() + scalar_type getNdotT(const scalar_type rcpOrientedEta) { return _refract.getNdotT(rcpOrientedEta*rcpOrientedEta); } - scalar_type getNdotTorR(const bool doRefract) + scalar_type getNdotTorR(const bool doRefract, const scalar_type rcpOrientedEta) { - return hlsl::mix(getNdotR(), getNdotT(), doRefract); + return hlsl::mix(getNdotR(), getNdotT(rcpOrientedEta), doRefract); } - vector_type operator()(const bool doRefract) + vector_type operator()(const bool doRefract, const scalar_type rcpOrientedEta) { scalar_type NdotI = getNdotR(); - return _refract.N * (NdotI * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)) + hlsl::mix(NdotI, getNdotT(), doRefract)) - _refract.I * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)); + return _refract.N * (NdotI * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)) + hlsl::mix(NdotI, getNdotT(rcpOrientedEta), doRefract)) - _refract.I * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)); } - vector_type operator()(const scalar_type NdotTorR) + vector_type operator()(const scalar_type NdotTorR, const scalar_type rcpOrientedEta) { scalar_type NdotI = getNdotR(); bool doRefract = ComputeMicrofacetNormal::isTransmissionPath(NdotI, NdotTorR); @@ -287,7 +285,6 @@ struct ReflectRefract } Refract _refract; - scalar_type rcpOrientedEta; }; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index e9504edf94..259dbd43a6 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -186,8 +186,8 @@ struct SBeckmannDielectricBxDF Refract r = Refract::create(localV, H); cache.iso_cache.LdotH = hlsl::mix(VdotH, r.getNdotT(rcpEta.value2[0]), transmitted); ray_dir_info_type localL; - bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(localV, H, rcpEta.value[0]); - localL.direction = rr(transmitted); + bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(localV, H); + localL.direction = rr(transmitted, rcpEta.value[0]); return sample_type::createFromTangentSpace(localV, localL, m); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 9ed573b581..29aa371b17 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -189,8 +189,8 @@ struct SGGXDielectricBxDF Refract r = Refract::create(localV, H); cache.iso_cache.LdotH = hlsl::mix(VdotH, r.getNdotT(rcpEta.value2[0]), transmitted); ray_dir_info_type localL; - bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(localV, H, rcpEta.value[0]); - localL.direction = rr(transmitted); + bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(localV, H); + localL.direction = rr(transmitted, rcpEta.value[0]); return sample_type::createFromTangentSpace(localV, localL, m); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index 82e27d4a33..4a6c198e96 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -115,11 +115,11 @@ struct SSmoothDielectricBxDF(0); } spectral_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) { - return (spectral_type)0; + return hlsl::promote(0); } sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N, scalar_type NdotV, scalar_type absNdotV, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(bool) transmitted) @@ -131,8 +131,8 @@ struct SSmoothDielectricBxDF r = Refract::create(V, N); - bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(r, orientedEta.rcp[0]); - L.direction = rr(transmitted); + bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(r); + L.direction = rr(transmitted, orientedEta.rcp[0]); return sample_type::create(L, nbl::hlsl::dot(V, L.direction), T, B, N); } @@ -178,7 +178,7 @@ struct SSmoothDielectricBxDF(numeric_limits::infinity); scalar_type quo = hlsl::mix(1.0, rcpOrientedEtas.value[0], transmitted); - return quotient_pdf_type::create((spectral_type)(quo), _pdf); + return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { @@ -188,7 +188,7 @@ struct SSmoothDielectricBxDF(numeric_limits::infinity); scalar_type quo = hlsl::mix(1.0, rcpOrientedEtas.value[0], transmitted); - return quotient_pdf_type::create((spectral_type)(quo), _pdf); + return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } scalar_type eta; @@ -225,11 +225,11 @@ struct SSmoothDielectricBxDF(0); } spectral_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) { - return (spectral_type)0; + return hlsl::promote(0); } // usually `luminosityContributionHint` would be the Rec.709 luma coefficients (the Y row of the RGB to CIE XYZ matrix) @@ -246,7 +246,7 @@ struct SSmoothDielectricBxDF(1.0) - reflectance) : reflectance) * rcpChoiceProb; ray_dir_info_type L; L.direction = (transmitted ? (vector3_type)(0.0) : N * 2.0f * NdotV) - V; @@ -286,18 +286,18 @@ struct SSmoothDielectricBxDF(sampleValue,luminosityContributionHint); const scalar_type _pdf = bit_cast(numeric_limits::infinity); - return quotient_pdf_type::create((spectral_type)(sampleValue / sampleProb), _pdf); + return quotient_pdf_type::create(sampleValue / sampleProb, _pdf); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(params.getNdotVUnclamped(), params.getNdotLUnclamped()); const spectral_type reflectance = fresnel::thinDielectricInfiniteScatter(fresnel::Dielectric::__call(eta2, params.getNdotV())); - const spectral_type sampleValue = hlsl::mix(reflectance, (spectral_type)(1.0) - reflectance, transmitted); + const spectral_type sampleValue = hlsl::mix(reflectance, hlsl::promote(1.0) - reflectance, transmitted); const scalar_type sampleProb = nbl::hlsl::dot(sampleValue,luminosityContributionHint); const scalar_type _pdf = bit_cast(numeric_limits::infinity); - return quotient_pdf_type::create((spectral_type)(sampleValue / sampleProb), _pdf); + return quotient_pdf_type::create(sampleValue / sampleProb, _pdf); } spectral_type eta2; From 81366a780dc4f9b3521304b58a09d1fa157fc517 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 21 Jul 2025 14:40:42 +0700 Subject: [PATCH 131/188] some changes to ndf usage --- include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 143 +++++++++--------- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 14 +- include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 19 +++ .../hlsl/bxdf/reflection/beckmann.hlsl | 4 +- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 4 +- .../hlsl/bxdf/transmission/beckmann.hlsl | 4 +- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 4 +- 7 files changed, 106 insertions(+), 86 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl index 4a5b5a4d5f..24d4776230 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -6,6 +6,8 @@ #include "nbl/builtin/hlsl/limits.hlsl" #include "nbl/builtin/hlsl/bxdf/common.hlsl" +// #include "nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl" +// #include "nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl" namespace nbl { @@ -16,29 +18,6 @@ namespace bxdf namespace ndf { -template -struct Beckmann; - -template -struct GGX; - -// common -namespace impl -{ -template -struct is_ggx : bool_constant< - is_same >::value || - is_same >::value -> {}; -} - -template -struct is_ggx : impl::is_ggx {}; - -template -NBL_CONSTEXPR bool is_ggx_v = is_ggx::value; - - enum MicrofacetTransformTypes : uint16_t { MTT_REFLECT = 0b01, @@ -46,82 +25,102 @@ enum MicrofacetTransformTypes : uint16_t MTT_REFLECT_REFRACT = 0b11 }; -template +template struct microfacet_to_light_measure_transform; -template -struct microfacet_to_light_measure_transform +template +struct microfacet_to_light_measure_transform { - using this_t = microfacet_to_light_measure_transform; - using scalar_type = typename NDF::scalar_type; + using this_t = microfacet_to_light_measure_transform; + using scalar_type = T; // this computes the max(NdotL,0)/(4*max(NdotV,0)*max(NdotL,0)) factor which transforms PDFs in the f in projected microfacet f * NdotH measure to projected light measure f * NdotL - static scalar_type __call(scalar_type NDFcos, scalar_type maxNdotV /* or maxNdotL for GGX*/) + static scalar_type __call(scalar_type NDFcos, scalar_type maxNdotV) { - if (is_ggx_v) - return NDFcos * maxNdotV; - else - return scalar_type(0.25) * NDFcos / maxNdotV; + return scalar_type(0.25) * NDFcos / maxNdotV; } }; -template -struct microfacet_to_light_measure_transform +template +struct microfacet_to_light_measure_transform { - using this_t = microfacet_to_light_measure_transform; - using scalar_type = typename NDF::scalar_type; + using this_t = microfacet_to_light_measure_transform; + using scalar_type = T; + + // this computes the max(NdotL,0)/(4*max(NdotV,0)*max(NdotL,0)) factor which transforms PDFs in the f in projected microfacet f * NdotH measure to projected light measure f * NdotL + static scalar_type __call(scalar_type NDFcos, scalar_type maxNdotL) + { + return NDFcos * maxNdotL; + } +}; + +template +struct microfacet_to_light_measure_transform +{ + using this_t = microfacet_to_light_measure_transform; + using scalar_type = T; static scalar_type __call(scalar_type NDFcos, scalar_type absNdotV, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) { - if (is_ggx_v) - { - scalar_type denominator = absNdotV; - const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); - // VdotHLdotH is negative under transmission, so thats denominator is negative - denominator *= -scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); - return NDFcos * denominator; - } - else + scalar_type denominator = absNdotV; + const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); + // VdotHLdotH is negative under transmission, so thats denominator is negative + denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; + return NDFcos * VdotHLdotH / denominator; + } +}; + +template +struct microfacet_to_light_measure_transform +{ + using this_t = microfacet_to_light_measure_transform; + using scalar_type = T; + + static scalar_type __call(scalar_type NDFcos, scalar_type absNdotV, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) + { + scalar_type denominator = absNdotV; + const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); + // VdotHLdotH is negative under transmission, so thats denominator is negative + denominator *= -scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); + return NDFcos * denominator; + } +}; + +template +struct microfacet_to_light_measure_transform +{ + using this_t = microfacet_to_light_measure_transform; + using scalar_type = T; + + static scalar_type __call(scalar_type NDFcos, scalar_type absNdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) + { + scalar_type denominator = absNdotV; + if (transmitted) { - scalar_type denominator = absNdotV; const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); // VdotHLdotH is negative under transmission, so thats denominator is negative denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; - return NDFcos * VdotHLdotH / denominator; } + return NDFcos * (transmitted ? VdotHLdotH : scalar_type(0.25)) / denominator; } }; -template -struct microfacet_to_light_measure_transform +template +struct microfacet_to_light_measure_transform { - using this_t = microfacet_to_light_measure_transform; - using scalar_type = typename NDF::scalar_type; + using this_t = microfacet_to_light_measure_transform; + using scalar_type = T; static scalar_type __call(scalar_type NDFcos, scalar_type absNdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) { - if (is_ggx_v) + scalar_type denominator = absNdotV; + if (transmitted) { - scalar_type denominator = absNdotV; - if (transmitted) - { - const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); - // VdotHLdotH is negative under transmission, so thats denominator is negative - denominator *= -scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); - } - return NDFcos * denominator; - } - else - { - scalar_type denominator = absNdotV; - if (transmitted) - { - const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); - // VdotHLdotH is negative under transmission, so thats denominator is negative - denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; - } - return NDFcos * (transmitted ? VdotHLdotH : scalar_type(0.25)) / denominator; + const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); + // VdotHLdotH is negative under transmission, so thats denominator is negative + denominator *= -scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); } + return NDFcos * denominator; } }; diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index 2d504896d4..ea5bfe37db 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -16,10 +16,12 @@ namespace bxdf namespace ndf { -// template -// struct Beckmann; +// forward declare +// template +// struct microfacet_to_light_measure_transform; -// TODO: get beta from lgamma, see: https://www.cec.uchile.cl/cinetica/pcordero/MC_libros/NumericalRecipesinC.pdf +template +struct Beckmann; // TODO: use query_type for D, lambda, beta, DG1 when that's implemented template @@ -27,7 +29,7 @@ NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) struct Beckmann) > { using scalar_type = T; - using this_t = Beckmann; + // using this_t = Beckmann; scalar_type D(scalar_type a2, scalar_type NdotH2) { @@ -40,14 +42,14 @@ struct Beckmann) > scalar_type DG1(scalar_type ndf, scalar_type maxNdotV, scalar_type lambda_V) { onePlusLambda_V = scalar_type(1.0) + lambda_V; - return ndf::microfacet_to_light_measure_transform::__call(ndf / onePlusLambda_V, maxNdotV); + return ndf::microfacet_to_light_measure_transform::__call(ndf / onePlusLambda_V, maxNdotV); } // bsdf scalar_type DG1(scalar_type ndf, scalar_type absNdotV, scalar_type lambda_V, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, scalar_type reflectance) { onePlusLambda_V = scalar_type(1.0) + lambda_V; - return ndf::microfacet_to_light_measure_transform::__call(hlsl::mix(reflectance, scalar_type(1.0) - reflectance, transmitted) * ndf / onePlusLambda_V, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); + return ndf::microfacet_to_light_measure_transform::__call(hlsl::mix(reflectance, scalar_type(1.0) - reflectance, transmitted) * ndf / onePlusLambda_V, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); } scalar_type G1(scalar_type lambda) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index 9e26974c21..0ca5c7d31b 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -16,6 +16,9 @@ namespace bxdf namespace ndf { +template +struct GGX; + // TODO: use query_type when that's implemented template NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) @@ -182,6 +185,22 @@ struct GGX) > } }; + +namespace impl +{ +template +struct is_ggx : bool_constant< + is_same >::value || + is_same >::value +> {}; +} + +template +struct is_ggx : impl::is_ggx {}; + +template +NBL_CONSTEXPR bool is_ggx_v = is_ggx::value; + } } } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 0a824895ca..43dcc16916 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -167,7 +167,7 @@ struct SBeckmannBxDF if (params.getNdotVUnclamped() > numeric_limits::min) { const scalar_type scalar_part = __eval_DG_wo_clamps(params); - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::MTT_REFLECT>::__call(scalar_part, params.getNdotVUnclamped()); + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, params.getNdotVUnclamped()); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); return f() * microfacet_transform; } @@ -179,7 +179,7 @@ struct SBeckmannBxDF if (params.getNdotVUnclamped() > numeric_limits::min) { const scalar_type scalar_part = __eval_DG_wo_clamps(params); - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::MTT_REFLECT>::__call(scalar_part, params.getNdotVUnclamped()); + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, params.getNdotVUnclamped()); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); return f() * microfacet_transform; } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 4a10de13a3..78015e671f 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -168,7 +168,7 @@ struct SGGXBxDF if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) { const scalar_type scalar_part = __eval_DG_wo_clamps(params); - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::MTT_REFLECT>::__call(scalar_part, params.getNdotL()); + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, params.getNdotL()); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); return f() * microfacet_transform; } @@ -180,7 +180,7 @@ struct SGGXBxDF if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) { const scalar_type scalar_part = __eval_DG_wo_clamps(params); - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::MTT_REFLECT>::__call(scalar_part, params.getNdotL()); + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, params.getNdotL()); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); return f() * microfacet_transform; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 259dbd43a6..27aadb60bf 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -150,7 +150,7 @@ struct SBeckmannDielectricBxDF typename brdf_type::params_isotropic_t brdf_params = typename brdf_type::params_isotropic_t::create(params._sample, params.interaction, params.cache, params._clamp); const scalar_type scalar_part = beckmann.__eval_DG_wo_clamps(brdf_params); - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::MTT_REFLECT_REFRACT>::__call(scalar_part,params.getNdotV(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part,params.getNdotV(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); const scalar_type f = fresnel::Dielectric::__call(orientedEta2, hlsl::abs(params.getVdotH()))[0]; return hlsl::promote(f) * microfacet_transform; } @@ -167,7 +167,7 @@ struct SBeckmannDielectricBxDF typename brdf_type::params_anisotropic_t brdf_params = typename brdf_type::params_anisotropic_t::create(params._sample, params.interaction, params.cache, params._clamp); const scalar_type scalar_part = beckmann.__eval_DG_wo_clamps(brdf_params); - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::MTT_REFLECT_REFRACT>::__call(scalar_part,params.getNdotV(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part,params.getNdotV(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); const scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; return hlsl::promote(f) * microfacet_transform; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 29aa371b17..0136ae55d0 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -151,7 +151,7 @@ struct SGGXDielectricBxDF typename brdf_type::params_isotropic_t brdf_params = typename brdf_type::params_isotropic_t::create(params._sample, params.interaction, params.cache, params._clamp); NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(brdf_params); - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::MTT_REFLECT_REFRACT>::__call(NG_already_in_reflective_dL_measure,params.getNdotL(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(NG_already_in_reflective_dL_measure,params.getNdotL(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); const scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; return hlsl::promote(f) * microfacet_transform; } @@ -170,7 +170,7 @@ struct SGGXDielectricBxDF typename brdf_type::params_anisotropic_t brdf_params = typename brdf_type::params_anisotropic_t::create(params._sample, params.interaction, params.cache, params._clamp); NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(brdf_params); - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform,ndf::MTT_REFLECT_REFRACT>::__call(NG_already_in_reflective_dL_measure,params.getNdotL(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(NG_already_in_reflective_dL_measure,params.getNdotL(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); const scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; return hlsl::promote(f) * microfacet_transform; } From 8bd28532ce61dbb019db2f495e9ef0f721b645e3 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 21 Jul 2025 16:51:51 +0700 Subject: [PATCH 132/188] new concept macro to evaluate valid expressions --- include/nbl/builtin/hlsl/concepts.hlsl | 18 ++++++++++++++++++ include/nbl/builtin/hlsl/glsl_compat/core.hlsl | 8 ++++---- .../builtin/hlsl/spirv_intrinsics/core.hlsl | 8 ++++++-- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/include/nbl/builtin/hlsl/concepts.hlsl b/include/nbl/builtin/hlsl/concepts.hlsl index 4b82955bb7..c51364bb5c 100644 --- a/include/nbl/builtin/hlsl/concepts.hlsl +++ b/include/nbl/builtin/hlsl/concepts.hlsl @@ -118,6 +118,24 @@ NBL_CONSTEXPR bool NBL_CONCEPT_NAME = BOOST_PP_SEQ_FOR_EACH_I(NBL_IMPL_CONCEPT_E // TODO: counterparts of all the other concepts #endif + +#include +#include + +#define NBL_IMPL_EXPR_DECLVAL(r,data,i,_T) BOOST_PP_COMMA_IF(BOOST_PP_NOT_EQUAL(i,0)) experimental::declval<_T>() +#define NBL_IMPL_EXPR_DECL_TEMP_ARG(r,data,i,_T) BOOST_PP_COMMA_IF(BOOST_PP_NOT_EQUAL(i,0)) typename _T +#define NBL_IMPL_EXPR_ITER_TEMP_ARG(r,data,i,_T) BOOST_PP_COMMA_IF(BOOST_PP_NOT_EQUAL(i,0)) _T +#define NBL_VALID_EXPRESSION(CONCEPT_NAME, FUNCTION_NAME, ARG_TYPE_LIST, ARG_TYPE_SET)\ +namespace impl\ +{\ +template\ +struct CONCEPT_NAME : false_type {};\ +template\ +struct CONCEPT_NAME(BOOST_PP_SEQ_FOR_EACH_I(NBL_IMPL_EXPR_DECLVAL, _, ARG_TYPE_SET)))> > : true_type {};\ +}\ +template\ +NBL_BOOL_CONCEPT CONCEPT_NAME = impl::CONCEPT_NAME::value;\ + } } } diff --git a/include/nbl/builtin/hlsl/glsl_compat/core.hlsl b/include/nbl/builtin/hlsl/glsl_compat/core.hlsl index c36bfd207c..9c124c6ae3 100644 --- a/include/nbl/builtin/hlsl/glsl_compat/core.hlsl +++ b/include/nbl/builtin/hlsl/glsl_compat/core.hlsl @@ -245,8 +245,8 @@ struct equal_helper; #ifdef __HLSL_VERSION template -NBL_PARTIAL_REQ_TOP(always_true(experimental::declval(),experimental::declval()))> && concepts::Vectorial && concepts::Integral) -struct equal_helper(experimental::declval(),experimental::declval()))> && concepts::Vectorial && concepts::Integral) > +NBL_PARTIAL_REQ_TOP(spirv::EqualIntrinsicCallable && concepts::Vectorial && concepts::Integral) +struct equal_helper && concepts::Vectorial && concepts::Integral) > { using return_t = vector::Dimension>; @@ -257,8 +257,8 @@ struct equal_helper -NBL_PARTIAL_REQ_TOP(always_true(experimental::declval(),experimental::declval()))> && concepts::Vectorial && concepts::FloatingPoint) -struct equal_helper(experimental::declval(),experimental::declval()))> && concepts::Vectorial && concepts::FloatingPoint) > +NBL_PARTIAL_REQ_TOP(spirv::EqualIntrinsicCallable && concepts::Vectorial && concepts::FloatingPoint) +struct equal_helper && concepts::Vectorial && concepts::FloatingPoint) > { using return_t = vector::Dimension>; diff --git a/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl b/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl index b0a315272d..738efab706 100644 --- a/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl +++ b/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl @@ -356,13 +356,17 @@ template || concepts::Fl [[vk::ext_instruction(spv::OpFOrdEqual)]] conditional_t, vector::Dimension>, bool> FOrdEqual(T lhs, T rhs); +NBL_VALID_EXPRESSION(IEqualIsCallable, IEqual, (T), (T)(T)) +NBL_VALID_EXPRESSION(FOrdEqualIsCallable, FOrdEqual, (T), (T)(T)) + +template +NBL_BOOL_CONCEPT EqualIntrinsicCallable = IEqualIsCallable || FOrdEqualIsCallable; template && (!concepts::Vector || (concepts::Vector && vector_traits::Dimension==vector_traits::Dimension))) [[vk::ext_instruction(spv::OpSelect)]] T select(U a, T x, T y); -template -NBL_BOOL_CONCEPT SelectIsCallable = always_true(),experimental::declval(),experimental::declval()))>; +NBL_VALID_EXPRESSION(SelectIsCallable, select, (T)(U), (U)(T)(T)) } From 5630e0e16a5830a28a23dc76d4683e39bb3865bf Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 22 Jul 2025 11:50:40 +0700 Subject: [PATCH 133/188] l2gamma and beta uses faster exp2,log2 --- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 2 +- include/nbl/builtin/hlsl/tgmath.hlsl | 6 ++++++ include/nbl/builtin/hlsl/tgmath/impl.hlsl | 18 +++++++++++++++++- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index ea5bfe37db..f06f07e5f1 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -81,7 +81,7 @@ struct Beckmann) > scalar_type L_v = Lambda(c2); c2 = C2(NdotL2, a2); scalar_type L_l = Lambda(c2); - return G1(L_v + L_l); + return scalar_type(1.0) / (scalar_type(1.0) + L_v + L_l); } scalar_type G2_over_G1(scalar_type a2, bool transmitted, scalar_type NdotL2, scalar_type lambdaV_plus_one) diff --git a/include/nbl/builtin/hlsl/tgmath.hlsl b/include/nbl/builtin/hlsl/tgmath.hlsl index 2c76e1b3d0..9505c17eb4 100644 --- a/include/nbl/builtin/hlsl/tgmath.hlsl +++ b/include/nbl/builtin/hlsl/tgmath.hlsl @@ -231,6 +231,12 @@ inline FrexpOutput frexpStruct(NBL_CONST_REF_ARG(T) val) return tgmath_impl::frexpStruct_helper::__call(val); } +template +inline T l2gamma(NBL_CONST_REF_ARG(T) val) +{ + return tgmath_impl::l2gamma_helper::__call(val); +} + template inline T lgamma(NBL_CONST_REF_ARG(T) val) { diff --git a/include/nbl/builtin/hlsl/tgmath/impl.hlsl b/include/nbl/builtin/hlsl/tgmath/impl.hlsl index 4cc363dd0f..8676a8c4b6 100644 --- a/include/nbl/builtin/hlsl/tgmath/impl.hlsl +++ b/include/nbl/builtin/hlsl/tgmath/impl.hlsl @@ -90,6 +90,8 @@ struct modfStruct_helper; template struct frexpStruct_helper; +template +struct l2gamma_helper; template struct lgamma_helper; template @@ -240,7 +242,7 @@ struct beta_helper) > // implementation from Numerical Recipes in C, 2nd ed. static T __call(T v1, T v2) { - return exp_helper::__call(lgamma_helper::__call(v1) + lgamma_helper::__call(v2) - lgamma_helper::__call(v1+v2)); + return exp2_helper::__call(l2gamma_helper::__call(v1) + l2gamma_helper::__call(v2) - l2gamma_helper::__call(v1+v2)); } }; @@ -568,6 +570,20 @@ struct erfInv_helper +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) +struct l2gamma_helper) > +{ + // modified Stirling's approximation for log2 up to 3rd polynomial + static T __call(T x) + { + const T l2x = log2_helper::__call(x); + const T one_over_ln2 = T(1.44269504088896); + return (x - T(0.5)) * l2x - one_over_ln2 * x + T(1.32574806473616) + one_over_ln2 / (T(12.0) * x) + one_over_ln2 / (T(360.0) * x * x * x); + } +}; + #ifdef __HLSL_VERSION // SPIR-V already defines specializations for builtin vector types #define VECTOR_SPECIALIZATION_CONCEPT concepts::Vectorial && !is_vector_v From e7fcfa3982a3beb9f064ad8353df6126e6b84ce0 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 22 Jul 2025 15:27:01 +0700 Subject: [PATCH 134/188] added threshold checks to lgamma, beta funcs --- include/nbl/builtin/hlsl/tgmath/impl.hlsl | 45 +++++++++++++++-------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/include/nbl/builtin/hlsl/tgmath/impl.hlsl b/include/nbl/builtin/hlsl/tgmath/impl.hlsl index 8676a8c4b6..45984f8cdd 100644 --- a/include/nbl/builtin/hlsl/tgmath/impl.hlsl +++ b/include/nbl/builtin/hlsl/tgmath/impl.hlsl @@ -216,22 +216,27 @@ NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) struct lgamma_helper) > { // implementation from Numerical Recipes in C, 2nd ed. - static T __call(T val) - { - T x, y; - y = x = val; - T tmp = x + T(5.5); - tmp -= (x + T(0.5)) * log_helper::__call(tmp); - - T ser = T(1.000000000190015); + static T __call(T val) + { + const T thresholds[3] = { 7e4, 1e19, 1e19 }; + if (val > thresholds[findLSB(uint32_t(sizeof(T)))]) + return bit_cast(numeric_limits::infinity); + + T x, y; + y = x = val; + T tmp = x + T(5.5); + tmp -= (x + T(0.5)) * log_helper::__call(tmp); + + T ser = T(1.000000000190015); ser += T(76.18009172947146) / ++y; ser += T(-86.50532032941677) / ++y; ser += T(24.01409824083091) / ++y; ser += T(-1.231739572450155) / ++y; ser += T(0.1208650973866179e-2) / ++y; - ser += T(-0.5395239384953e-5) / ++y; - return -tmp + log_helper::__call(T(2.5066282746310005) * ser / x); - } + if (sizeof(T)>2) + ser += T(-0.5395239384953e-5) / ++y; + return -tmp + log_helper::__call(T(2.5066282746310005) * ser / x); + } }; // beta function @@ -242,6 +247,12 @@ struct beta_helper) > // implementation from Numerical Recipes in C, 2nd ed. static T __call(T v1, T v2) { + // specialized for Cook Torrance BTDFs + assert(v1 >= 1.0 && v2 >= 1.0); + + if (v1+v2 > 1e6) + return T(0.0); + return exp2_helper::__call(l2gamma_helper::__call(v1) + l2gamma_helper::__call(v2) - l2gamma_helper::__call(v1+v2)); } }; @@ -576,12 +587,16 @@ NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) struct l2gamma_helper) > { // modified Stirling's approximation for log2 up to 3rd polynomial - static T __call(T x) - { - const T l2x = log2_helper::__call(x); + static T __call(T x) + { + const T thresholds[3] = {5e4, 1e19, 1e19}; + if (x > thresholds[findLSB(uint32_t(sizeof(T)))]) + return bit_cast(numeric_limits::infinity); + + const T l2x = log2_helper::__call(x); const T one_over_ln2 = T(1.44269504088896); return (x - T(0.5)) * l2x - one_over_ln2 * x + T(1.32574806473616) + one_over_ln2 / (T(12.0) * x) + one_over_ln2 / (T(360.0) * x * x * x); - } + } }; #ifdef __HLSL_VERSION From adf93a47b80ea8609cf661a4701473abb7e6b437 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 22 Jul 2025 16:37:24 +0700 Subject: [PATCH 135/188] minor changes to beckmann ndf usage --- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 81 ++++++++----------- .../hlsl/bxdf/reflection/beckmann.hlsl | 38 +++++---- .../hlsl/bxdf/transmission/beckmann.hlsl | 27 ++++--- 3 files changed, 70 insertions(+), 76 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index f06f07e5f1..9d370f6f9f 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -29,24 +29,23 @@ NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) struct Beckmann) > { using scalar_type = T; - // using this_t = Beckmann; - scalar_type D(scalar_type a2, scalar_type NdotH2) + scalar_type D(scalar_type NdotH2) { - scalar_type nom = exp( (NdotH2 - scalar_type(1.0)) / (a2 * NdotH2) ); // exp(x) == exp2(x/log(2)) ? + scalar_type nom = exp2((NdotH2 - scalar_type(1.0)) / (log(2.0) * a2 * NdotH2)); scalar_type denom = a2 * NdotH2 * NdotH2; return numbers::inv_pi * nom / denom; } // brdf - scalar_type DG1(scalar_type ndf, scalar_type maxNdotV, scalar_type lambda_V) + scalar_type DG1(scalar_type ndf, scalar_type maxNdotV, scalar_type lambda_V, NBL_REF_ARG(scalar_type) onePlusLambda_V) { onePlusLambda_V = scalar_type(1.0) + lambda_V; return ndf::microfacet_to_light_measure_transform::__call(ndf / onePlusLambda_V, maxNdotV); } // bsdf - scalar_type DG1(scalar_type ndf, scalar_type absNdotV, scalar_type lambda_V, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, scalar_type reflectance) + scalar_type DG1(scalar_type ndf, scalar_type absNdotV, scalar_type lambda_V, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, scalar_type reflectance, NBL_REF_ARG(scalar_type) onePlusLambda_V) { onePlusLambda_V = scalar_type(1.0) + lambda_V; return ndf::microfacet_to_light_measure_transform::__call(hlsl::mix(reflectance, scalar_type(1.0) - reflectance, transmitted) * ndf / onePlusLambda_V, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); @@ -57,7 +56,7 @@ struct Beckmann) > return scalar_type(1.0) / (scalar_type(1.0) + lambda); } - scalar_type C2(scalar_type NdotX2, scalar_type a2) + scalar_type C2(scalar_type NdotX2) { return NdotX2 / (a2 * (scalar_type(1.0) - NdotX2)); } @@ -70,31 +69,25 @@ struct Beckmann) > return hlsl::mix(scalar_type(0.0), nom / denom, c < scalar_type(1.6)); } - scalar_type Lambda(scalar_type NdotX2, scalar_type a2) + scalar_type LambdaC2(scalar_type NdotX2) { - return Lambda(C2(NdotX2, a2)); + return Lambda(C2(NdotX2)); } - scalar_type correlated(scalar_type a2, scalar_type NdotV2, scalar_type NdotL2) + scalar_type correlated(scalar_type NdotV2, scalar_type NdotL2) { - scalar_type c2 = C2(NdotV2, a2); - scalar_type L_v = Lambda(c2); - c2 = C2(NdotL2, a2); - scalar_type L_l = Lambda(c2); + scalar_type L_v = LambdaC2(NdotV2); + scalar_type L_l = LambdaC2(NdotL2); return scalar_type(1.0) / (scalar_type(1.0) + L_v + L_l); } - scalar_type G2_over_G1(scalar_type a2, bool transmitted, scalar_type NdotL2, scalar_type lambdaV_plus_one) + scalar_type G2_over_G1(bool transmitted, scalar_type NdotL2, scalar_type lambdaV_plus_one) { - scalar_type lambdaL = Lambda(NdotL2, a2); - return hlsl::mix( - lambdaV_plus_one / (lambdaV_plus_one + lambdaL), - lambdaV_plus_one * hlsl::beta(lambdaV_plus_one, scalar_type(1.0) + lambdaL), - transmitted - ); + scalar_type lambdaL = LambdaC2(NdotL2); + return lambdaV_plus_one * hlsl::mix(scalar_type(1.0)/(lambdaV_plus_one + lambdaL), hlsl::beta(lambdaV_plus_one, scalar_type(1.0) + lambdaL), transmitted); } - scalar_type onePlusLambda_V; + scalar_type a2; }; @@ -104,26 +97,26 @@ struct Beckmann) > { using scalar_type = T; - scalar_type D(scalar_type ax, scalar_type ay, scalar_type ax2, scalar_type ay2, scalar_type TdotH2, scalar_type BdotH2, scalar_type NdotH2) + scalar_type D(scalar_type TdotH2, scalar_type BdotH2, scalar_type NdotH2) { + const scalar_type ax2 = ax*ax; + const scalar_type ay2 = ay*ay; scalar_type nom = exp(-(TdotH2 / ax2 + BdotH2 / ay2) / NdotH2); scalar_type denom = ax * ay * NdotH2 * NdotH2; return numbers::inv_pi * nom / denom; } - scalar_type DG1(scalar_type ndf, scalar_type maxNdotV, scalar_type lambda_V) + scalar_type DG1(scalar_type ndf, scalar_type maxNdotV, scalar_type lambda_V, NBL_REF_ARG(scalar_type) onePlusLambda_V) { Beckmann beckmann; - scalar_type dg = beckmann.DG1(ndf, maxNdotV, lambda_V); - onePlusLambda_V = beckmann.onePlusLambda_V; + scalar_type dg = beckmann.DG1(ndf, maxNdotV, lambda_V, onePlusLambda_V); return dg; } - scalar_type DG1(scalar_type ndf, scalar_type absNdotV, scalar_type lambda_V, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, scalar_type reflectance) + scalar_type DG1(scalar_type ndf, scalar_type absNdotV, scalar_type lambda_V, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, scalar_type reflectance, NBL_REF_ARG(scalar_type) onePlusLambda_V) { Beckmann beckmann; - scalar_type dg = beckmann.DG1(ndf, absNdotV, lambda_V, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta, reflectance); - onePlusLambda_V = beckmann.onePlusLambda_V; + scalar_type dg = beckmann.DG1(ndf, absNdotV, lambda_V, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta, reflectance, onePlusLambda_V); return dg; } @@ -132,8 +125,10 @@ struct Beckmann) > return scalar_type(1.0) / (scalar_type(1.0) + lambda); } - scalar_type C2(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2, scalar_type ax2, scalar_type ay2) + scalar_type C2(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2) { + const scalar_type ax2 = ax*ax; + const scalar_type ay2 = ay*ay; return NdotX2 / (TdotX2 * ax2 + BdotX2 * ay2); } @@ -145,32 +140,26 @@ struct Beckmann) > return hlsl::mix(scalar_type(0.0), nom / denom, c < scalar_type(1.6)); } - scalar_type Lambda(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2, scalar_type ax2, scalar_type ay2) + scalar_type LambdaC2(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2) { - return Lambda(C2(TdotX2, BdotX2, NdotX2, ax2, ay2)); + return Lambda(C2(TdotX2, BdotX2, NdotX2)); } - scalar_type correlated(scalar_type ax2, scalar_type ay2, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2) + scalar_type correlated(scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2) { - scalar_type c2 = C2(TdotV2, BdotV2, NdotV2, ax2, ay2); - scalar_type L_v = Lambda(c2); - c2 = C2(TdotL2, BdotL2, NdotL2, ax2, ay2); - scalar_type L_l = Lambda(c2); - return G1(L_v + L_l); + scalar_type L_v = LambdaC2(TdotV2, BdotV2, NdotV2); + scalar_type L_l = LambdaC2(TdotL2, BdotL2, NdotL2); + return scalar_type(1.0) / (scalar_type(1.0) + L_v + L_l); } - scalar_type G2_over_G1(scalar_type ax2, scalar_type ay2, bool transmitted, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2, scalar_type lambdaV_plus_one) + scalar_type G2_over_G1(bool transmitted, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2, scalar_type lambdaV_plus_one) { - scalar_type c2 = C2(TdotL2, BdotL2, NdotL2, ax2, ay2); - scalar_type lambdaL = Lambda(c2); - return hlsl::mix( - lambdaV_plus_one / (lambdaV_plus_one + lambdaL), - lambdaV_plus_one * hlsl::beta(lambdaV_plus_one, scalar_type(1.0) + lambdaL), - transmitted - ); + scalar_type lambdaL = LambdaC2(TdotL2, BdotL2, NdotL2); + return lambdaV_plus_one * hlsl::mix(scalar_type(1.0)/(lambdaV_plus_one + lambdaL), hlsl::beta(lambdaV_plus_one, scalar_type(1.0) + lambdaL), transmitted); } - scalar_type onePlusLambda_V; + scalar_type ax; + scalar_type ay; }; } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 43dcc16916..2a072cd0d4 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -142,22 +142,23 @@ struct SBeckmannBxDF { scalar_type a2 = A.x*A.x; ndf::Beckmann beckmann_ndf; - scalar_type NG = beckmann_ndf.D(a2, params.getNdotH2()); + beckmann_ndf.a2 = a2; + scalar_type NG = beckmann_ndf.D(params.getNdotH2()); if (a2 > numeric_limits::min) { - NG *= beckmann_ndf.correlated(a2, params.getNdotV2(), params.getNdotL2()); + NG *= beckmann_ndf.correlated(params.getNdotV2(), params.getNdotL2()); } return NG; } scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_anisotropic_t) params) { - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; ndf::Beckmann beckmann_ndf; - scalar_type NG = beckmann_ndf.D(A.x, A.y, ax2, ay2, params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); + beckmann_ndf.ax = A.x; + beckmann_ndf.ay = A.y; + scalar_type NG = beckmann_ndf.D(params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); if (hlsl::any >(A > (vector2_type)numeric_limits::min)) { - NG *= beckmann_ndf.correlated(ax2, ay2, params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); + NG *= beckmann_ndf.correlated(params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); } return NG; } @@ -281,12 +282,12 @@ struct SBeckmannBxDF scalar_type ndf, lambda; scalar_type a2 = A.x*A.x; ndf::Beckmann beckmann_ndf; - ndf = beckmann_ndf.D(a2, params.getNdotH2()); + beckmann_ndf.a2 = a2; + ndf = beckmann_ndf.D(params.getNdotH2()); - lambda = beckmann_ndf.Lambda(params.getNdotV2(), a2); + lambda = beckmann_ndf.LambdaC2(params.getNdotV2()); - scalar_type _pdf = beckmann_ndf.DG1(ndf, params.getNdotVUnclamped(), lambda); - onePlusLambda_V = beckmann_ndf.onePlusLambda_V; + scalar_type _pdf = beckmann_ndf.DG1(ndf, params.getNdotVUnclamped(), lambda, onePlusLambda_V); return _pdf; } @@ -294,13 +295,13 @@ struct SBeckmannBxDF { scalar_type ndf, lambda; ndf::Beckmann beckmann_ndf; - ndf = beckmann_ndf.D(A.x, A.y, A.x*A.x, A.y*A.y, params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); + beckmann_ndf.ax = A.x; + beckmann_ndf.ay = A.y; + ndf = beckmann_ndf.D(params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); - const scalar_type c2 = beckmann_ndf.C2(params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), A.x, A.y); - lambda = beckmann_ndf.Lambda(c2); + lambda = beckmann_ndf.LambdaC2(params.getTdotV2(), params.getBdotV2(), params.getNdotV2()); - scalar_type _pdf = beckmann_ndf.DG1(ndf, params.getNdotVUnclamped(), lambda); - onePlusLambda_V = beckmann_ndf.onePlusLambda_V; + scalar_type _pdf = beckmann_ndf.DG1(ndf, params.getNdotVUnclamped(), lambda, onePlusLambda_V); return _pdf; } @@ -325,7 +326,8 @@ struct SBeckmannBxDF spectral_type quo = (spectral_type)0.0; if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) { - scalar_type G2_over_G1 = beckmann_ndf.G2_over_G1(A.x*A.x, false, params.getNdotL2(), onePlusLambda_V); + beckmann_ndf.a2 = A.x*A.x; + scalar_type G2_over_G1 = beckmann_ndf.G2_over_G1(false, params.getNdotL2(), onePlusLambda_V); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; @@ -342,7 +344,9 @@ struct SBeckmannBxDF spectral_type quo = (spectral_type)0.0; if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) { - scalar_type G2_over_G1 = beckmann_ndf.G2_over_G1(A.x*A.x, A.y*A.y, false, params.getTdotL2(), params.getBdotL2(), params.getNdotL2(), onePlusLambda_V); + beckmann_ndf.ax = A.x; + beckmann_ndf.ay = A.y; + scalar_type G2_over_G1 = beckmann_ndf.G2_over_G1(false, params.getTdotL2(), params.getBdotL2(), params.getNdotL2(), onePlusLambda_V); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 27aadb60bf..c7f38ad782 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -235,12 +235,12 @@ struct SBeckmannDielectricBxDF scalar_type ndf, lambda; const scalar_type a2 = A.x*A.x; ndf::Beckmann beckmann_ndf; - ndf = beckmann_ndf.D(a2, params.getNdotH2()); + beckmann_ndf.a2 = a2; + ndf = beckmann_ndf.D(params.getNdotH2()); - lambda = beckmann_ndf.Lambda(params.getNdotV2(), a2); + lambda = beckmann_ndf.LambdaC2(params.getNdotV2()); - scalar_type _pdf = beckmann_ndf.DG1(ndf,params.getNdotV(),lambda,transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0],reflectance); - onePlusLambda_V = beckmann_ndf.onePlusLambda_V; + scalar_type _pdf = beckmann_ndf.DG1(ndf,params.getNdotV(),lambda,transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0],reflectance,onePlusLambda_V); return _pdf; } @@ -255,16 +255,14 @@ struct SBeckmannDielectricBxDF const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; scalar_type ndf, lambda; - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; ndf::Beckmann beckmann_ndf; - ndf = beckmann_ndf.D(A.x, A.y, ax2, ay2, params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); + beckmann_ndf.ax = A.x; + beckmann_ndf.ay = A.y; + ndf = beckmann_ndf.D(params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); - scalar_type c2 = beckmann_ndf.C2(params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), ax2, ay2); - lambda = beckmann_ndf.Lambda(c2); + lambda = beckmann_ndf.LambdaC2(params.getTdotV2(), params.getBdotV2(), params.getNdotV2()); - scalar_type _pdf = beckmann_ndf.DG1(ndf,params.getNdotV(),lambda,transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0],reflectance); - onePlusLambda_V = beckmann_ndf.onePlusLambda_V; + scalar_type _pdf = beckmann_ndf.DG1(ndf,params.getNdotV(),lambda,transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0],reflectance,onePlusLambda_V); return _pdf; } @@ -288,7 +286,8 @@ struct SBeckmannDielectricBxDF scalar_type quo; ndf::Beckmann beckmann_ndf; - quo = beckmann_ndf.G2_over_G1(A.x*A.x, transmitted, params.getNdotL2(), onePlusLambda_V); + beckmann_ndf.a2 = A.x*A.x; + quo = beckmann_ndf.G2_over_G1(transmitted, params.getNdotL2(), onePlusLambda_V); return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } @@ -300,7 +299,9 @@ struct SBeckmannDielectricBxDF scalar_type quo; ndf::Beckmann beckmann_ndf; - quo = beckmann_ndf.G2_over_G1(A.x*A.x, A.y*A.y, transmitted, params.getTdotL2(), params.getBdotL2(), params.getNdotL2(), onePlusLambda_V); + beckmann_ndf.ax = A.x; + beckmann_ndf.ay = A.y; + quo = beckmann_ndf.G2_over_G1(transmitted, params.getTdotL2(), params.getBdotL2(), params.getNdotL2(), onePlusLambda_V); return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } From a1289f172bafa920693f60f60244e1636a80c2e4 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 23 Jul 2025 13:41:28 +0700 Subject: [PATCH 136/188] changes to ggx ndf usage, separate fresnel from vndf --- include/nbl/builtin/hlsl/bxdf/fresnel.hlsl | 24 +--- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 8 +- include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 130 +++++++++++------- .../hlsl/bxdf/reflection/beckmann.hlsl | 8 +- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 44 +++--- .../hlsl/bxdf/transmission/beckmann.hlsl | 11 +- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 41 +++--- .../bxdf/transmission/smooth_dielectric.hlsl | 3 +- 8 files changed, 141 insertions(+), 128 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl index b8d028e2aa..a674b635dc 100644 --- a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl @@ -240,30 +240,16 @@ struct ReflectRefract using vector_type = vector; using scalar_type = T; - static this_t create(NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N) - { - this_t retval; - retval._refract = Refract::create(I, N); - return retval; - } - - static this_t create(NBL_CONST_REF_ARG(Refract) refract) - { - this_t retval; - retval._refract = refract; - return retval; - } - // when you know you'll reflect scalar_type getNdotR() { - return _refract.getNdotI(); + return refract.getNdotI(); } // when you know you'll refract scalar_type getNdotT(const scalar_type rcpOrientedEta) { - return _refract.getNdotT(rcpOrientedEta*rcpOrientedEta); + return refract.getNdotT(rcpOrientedEta*rcpOrientedEta); } scalar_type getNdotTorR(const bool doRefract, const scalar_type rcpOrientedEta) @@ -274,17 +260,17 @@ struct ReflectRefract vector_type operator()(const bool doRefract, const scalar_type rcpOrientedEta) { scalar_type NdotI = getNdotR(); - return _refract.N * (NdotI * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)) + hlsl::mix(NdotI, getNdotT(rcpOrientedEta), doRefract)) - _refract.I * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)); + return refract.N * (NdotI * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)) + hlsl::mix(NdotI, getNdotT(rcpOrientedEta), doRefract)) - refract.I * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)); } vector_type operator()(const scalar_type NdotTorR, const scalar_type rcpOrientedEta) { scalar_type NdotI = getNdotR(); bool doRefract = ComputeMicrofacetNormal::isTransmissionPath(NdotI, NdotTorR); - return _refract.N * (NdotI * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)) + hlsl::mix(NdotI, NdotTorR, doRefract)) - _refract.I * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)); + return refract.N * (NdotI * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)) + hlsl::mix(NdotI, NdotTorR, doRefract)) - refract.I * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)); } - Refract _refract; + Refract refract; }; diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index 9d370f6f9f..2d614b4b7e 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -45,10 +45,10 @@ struct Beckmann) > } // bsdf - scalar_type DG1(scalar_type ndf, scalar_type absNdotV, scalar_type lambda_V, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, scalar_type reflectance, NBL_REF_ARG(scalar_type) onePlusLambda_V) + scalar_type DG1(scalar_type ndf, scalar_type absNdotV, scalar_type lambda_V, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, NBL_REF_ARG(scalar_type) onePlusLambda_V) { onePlusLambda_V = scalar_type(1.0) + lambda_V; - return ndf::microfacet_to_light_measure_transform::__call(hlsl::mix(reflectance, scalar_type(1.0) - reflectance, transmitted) * ndf / onePlusLambda_V, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); + return ndf::microfacet_to_light_measure_transform::__call(ndf / onePlusLambda_V, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); } scalar_type G1(scalar_type lambda) @@ -113,10 +113,10 @@ struct Beckmann) > return dg; } - scalar_type DG1(scalar_type ndf, scalar_type absNdotV, scalar_type lambda_V, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, scalar_type reflectance, NBL_REF_ARG(scalar_type) onePlusLambda_V) + scalar_type DG1(scalar_type ndf, scalar_type absNdotV, scalar_type lambda_V, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, NBL_REF_ARG(scalar_type) onePlusLambda_V) { Beckmann beckmann; - scalar_type dg = beckmann.DG1(ndf, absNdotV, lambda_V, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta, reflectance, onePlusLambda_V); + scalar_type dg = beckmann.DG1(ndf, absNdotV, lambda_V, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta, onePlusLambda_V); return dg; } diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index 0ca5c7d31b..387b254851 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -28,15 +28,21 @@ struct GGX) > using this_t = GGX; // trowbridge-reitz - scalar_type D(scalar_type a2, scalar_type NdotH2) + scalar_type D(scalar_type NdotH2) { - scalar_type denom = NdotH2 * (a2 - scalar_type(1.0)) + scalar_type(1.0); + scalar_type denom = scalar_type(1.0) - one_minus_a2 * NdotH2; return a2 * numbers::inv_pi / (denom * denom); } - scalar_type FVNDF(scalar_type fresnel_ndf, scalar_type G1_over_2NdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) + scalar_type DG1(scalar_type ndf, scalar_type G1_over_2NdotV) + { + scalar_type dummy = scalar_type(0.0); + return DG1(ndf, G1_over_2NdotV, false, dummy, dummy, dummy, dummy); + } + + scalar_type DG1(scalar_type ndf, scalar_type G1_over_2NdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) { - scalar_type FNG = fresnel_ndf * G1_over_2NdotV; + scalar_type NG = ndf * G1_over_2NdotV; scalar_type factor = scalar_type(0.5); if (transmitted) { @@ -44,65 +50,65 @@ struct GGX) > // VdotHLdotH is negative under transmission, so this factor is negative factor *= -scalar_type(2.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); } - return FNG * factor; - } - - scalar_type DG1(scalar_type ndf, scalar_type G1_over_2NdotV) - { - return ndf * scalar_type(0.5) * G1_over_2NdotV; - } - - scalar_type DG1(scalar_type ndf, scalar_type G1_over_2NdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, scalar_type reflectance) - { - scalar_type FN = hlsl::mix(reflectance, scalar_type(1.0) - reflectance, transmitted) * ndf; - return FVNDF(FN, G1_over_2NdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); + return NG * factor; } - scalar_type devsh_part(scalar_type NdotX2, scalar_type a2, scalar_type one_minus_a2) + scalar_type devsh_part(scalar_type NdotX2) { + assert(a2 >= numeric_limits::min); return sqrt(a2 + one_minus_a2 * NdotX2); } - scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type NdotX2, scalar_type a2, scalar_type one_minus_a2) + scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type NdotX2) { - return scalar_type(1.0) / (NdotX + devsh_part(NdotX2,a2,one_minus_a2)); + return scalar_type(1.0) / (NdotX + devsh_part(NdotX2)); } - scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type devsh_part) + scalar_type G1_wo_numerator_devsh_part(scalar_type NdotX, scalar_type devsh_part) { return scalar_type(1.0) / (NdotX + devsh_part); } - scalar_type correlated_wo_numerator(scalar_type a2, scalar_type NdotV, scalar_type NdotV2, scalar_type NdotL, scalar_type NdotL2) + scalar_type correlated_wo_numerator(scalar_type absNdotV, scalar_type NdotV2, scalar_type absNdotL, scalar_type NdotL2) { - scalar_type one_minus_a2 = scalar_type(1.0) - a2; - scalar_type Vterm = NdotL * devsh_part(NdotV2, a2, one_minus_a2); - scalar_type Lterm = NdotV * devsh_part(NdotL2, a2, one_minus_a2); + scalar_type Vterm = absNdotL * devsh_part(NdotV2); + scalar_type Lterm = absNdotV * devsh_part(NdotL2); return scalar_type(0.5) / (Vterm + Lterm); } - scalar_type G2_over_G1(scalar_type a2, bool transmitted, scalar_type NdotV, scalar_type NdotV2, scalar_type NdotL, scalar_type NdotL2) + scalar_type G2_over_G1(bool transmitted, scalar_type NdotV, scalar_type NdotV2, scalar_type NdotL, scalar_type NdotL2) { scalar_type G2_over_G1; if (transmitted) { - scalar_type one_minus_a2 = scalar_type(1.0) - a2; - scalar_type devsh_v = devsh_part(NdotV2, a2, one_minus_a2); - scalar_type L_v = scalar_type(0.5) * (devsh_v / NdotV - scalar_type(1.0)); - scalar_type L_l = scalar_type(0.5) * (devsh_part(NdotL2, a2, one_minus_a2) / NdotL - scalar_type(1.0)); - G2_over_G1 = hlsl::beta(scalar_type(1.0) + L_l, scalar_type(1.0) + L_v); - G2_over_G1 *= scalar_type(1.0) + L_v; + if (NdotV < 1e-7 || NdotL < 1e-7) + return 0.0; + scalar_type onePlusLambda_V = scalar_type(0.5) * (devsh_part(NdotV2) / NdotV + scalar_type(1.0)); + scalar_type onePlusLambda_L = scalar_type(0.5) * (devsh_part(NdotL2) / NdotL + scalar_type(1.0)); + G2_over_G1 = hlsl::beta(onePlusLambda_L, onePlusLambda_V) * onePlusLambda_V; } else { - scalar_type one_minus_a2 = scalar_type(1.0) - a2; - scalar_type devsh_v = devsh_part(NdotV2, a2, one_minus_a2); + scalar_type devsh_v = devsh_part(NdotV2); G2_over_G1 = NdotL * (devsh_v + NdotV); // alternative `Vterm+NdotL*NdotV /// NdotL*NdotV could come as a parameter - G2_over_G1 /= NdotV * devsh_part(NdotL2, a2, one_minus_a2) + NdotL * devsh_v; + G2_over_G1 /= NdotV * devsh_part(NdotL2) + NdotL * devsh_v; } return G2_over_G1; } + + // reflect only + scalar_type G2_over_G1(scalar_type NdotV, scalar_type NdotV2, scalar_type NdotL, scalar_type NdotL2) + { + scalar_type devsh_v = devsh_part(NdotV2); + scalar_type G2_over_G1 = NdotL * (devsh_v + NdotV); // alternative `Vterm+NdotL*NdotV /// NdotL*NdotV could come as a parameter + G2_over_G1 /= NdotV * devsh_part(NdotL2) + NdotL * devsh_v; + + return G2_over_G1; + } + + scalar_type a2; + scalar_type one_minus_a2; }; template @@ -111,9 +117,11 @@ struct GGX) > { using scalar_type = T; - scalar_type D(scalar_type ax, scalar_type ay, scalar_type ax2, scalar_type ay2, scalar_type TdotH2, scalar_type BdotH2, scalar_type NdotH2) + scalar_type D(scalar_type TdotH2, scalar_type BdotH2, scalar_type NdotH2) { - scalar_type a2 = ax * ay; + const scalar_type ax2 = ax*ax; + const scalar_type ay2 = ay*ay; + const scalar_type a2 = ax * ay; scalar_type denom = TdotH2 / ax2 + BdotH2 / ay2 + NdotH2; return numbers::inv_pi / (a2 * denom * denom); } @@ -135,54 +143,70 @@ struct GGX) > return ggx.DG1(ndf, G1_over_2NdotV); } - scalar_type DG1(scalar_type ndf, scalar_type G1_over_2NdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, scalar_type reflectance) + scalar_type DG1(scalar_type ndf, scalar_type G1_over_2NdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) { GGX ggx; - return ggx.DG1(ndf, G1_over_2NdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta, reflectance); + return ggx.DG1(ndf, G1_over_2NdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); } - scalar_type devsh_part(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2, scalar_type ax2, scalar_type ay2) + scalar_type devsh_part(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2) { + const scalar_type ax2 = ax*ax; + const scalar_type ay2 = ay*ay; + assert(ax2 >= numeric_limits::min && ay2 >= numeric_limits::min); return sqrt(TdotX2 * ax2 + BdotX2 * ay2 + NdotX2); } - scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2, scalar_type ax2, scalar_type ay2) + scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2) { - return scalar_type(1.0) / (NdotX + devsh_part(TdotX2, BdotX2, NdotX2, ax2, ay2)); + return scalar_type(1.0) / (NdotX + devsh_part(TdotX2, BdotX2, NdotX2)); } - scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type devsh_part) + scalar_type G1_wo_numerator_devsh_part(scalar_type NdotX, scalar_type devsh_part) { return scalar_type(1.0) / (NdotX + devsh_part); } - scalar_type correlated_wo_numerator(scalar_type ax2, scalar_type ay2, scalar_type NdotV, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type NdotL, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2) + scalar_type correlated_wo_numerator(scalar_type absNdotV, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type absNdotL, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2) { - scalar_type Vterm = NdotL * devsh_part(TdotV2, BdotV2, NdotV2, ax2, ay2); - scalar_type Lterm = NdotV * devsh_part(TdotL2, BdotL2, NdotL2, ax2, ay2); + scalar_type Vterm = absNdotL * devsh_part(TdotV2, BdotV2, NdotV2); + scalar_type Lterm = absNdotV * devsh_part(TdotL2, BdotL2, NdotL2); return scalar_type(0.5) / (Vterm + Lterm); } - scalar_type G2_over_G1(scalar_type ax2, scalar_type ay2, bool transmitted, scalar_type NdotV, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type NdotL, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2) + scalar_type G2_over_G1(bool transmitted, scalar_type NdotV, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type NdotL, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2) { scalar_type G2_over_G1; if (transmitted) { - scalar_type devsh_v = devsh_part(TdotV2, BdotV2, NdotV2, ax2, ay2); - scalar_type L_v = scalar_type(0.5) * (devsh_v / NdotV - scalar_type(1.0)); - scalar_type L_l = scalar_type(0.5) * (devsh_part(TdotL2, BdotL2, NdotL2, ax2, ay2) / NdotL - scalar_type(1.0)); - G2_over_G1 = hlsl::beta(scalar_type(1.0) + L_l, scalar_type(1.0) + L_v); - G2_over_G1 *= scalar_type(1.0) + L_v; + if (NdotV < 1e-7 || NdotL < 1e-7) + return 0.0; + scalar_type onePlusLambda_V = scalar_type(0.5) * (devsh_part(TdotV2, BdotV2, NdotV2) / NdotV + scalar_type(1.0)); + scalar_type onePlusLambda_L = scalar_type(0.5) * (devsh_part(TdotL2, BdotL2, NdotL2) / NdotL + scalar_type(1.0)); + G2_over_G1 = hlsl::beta(onePlusLambda_L, onePlusLambda_V) * onePlusLambda_V; } else { - scalar_type devsh_v = devsh_part(TdotV2, BdotV2, NdotV2, ax2, ay2); + scalar_type devsh_v = devsh_part(TdotV2, BdotV2, NdotV2); G2_over_G1 = NdotL * (devsh_v + NdotV); - G2_over_G1 /= NdotV * devsh_part(TdotL2, BdotL2, NdotL2, ax2, ay2) + NdotL * devsh_v; + G2_over_G1 /= NdotV * devsh_part(TdotL2, BdotL2, NdotL2) + NdotL * devsh_v; } return G2_over_G1; } + + // reflect only + scalar_type G2_over_G1(scalar_type NdotV, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type NdotL, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2) + { + scalar_type devsh_v = devsh_part(TdotV2, BdotV2, NdotV2); + scalar_type G2_over_G1 = NdotL * (devsh_v + NdotV); + G2_over_G1 /= NdotV * devsh_part(TdotL2, BdotL2, NdotL2) + NdotL * devsh_v; + + return G2_over_G1; + } + + scalar_type ax; + scalar_type ay; }; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 2a072cd0d4..c3556331f2 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -287,9 +287,7 @@ struct SBeckmannBxDF lambda = beckmann_ndf.LambdaC2(params.getNdotV2()); - scalar_type _pdf = beckmann_ndf.DG1(ndf, params.getNdotVUnclamped(), lambda, onePlusLambda_V); - - return _pdf; + return beckmann_ndf.DG1(ndf, params.getNdotVUnclamped(), lambda, onePlusLambda_V); } scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { @@ -301,9 +299,7 @@ struct SBeckmannBxDF lambda = beckmann_ndf.LambdaC2(params.getTdotV2(), params.getBdotV2(), params.getNdotV2()); - scalar_type _pdf = beckmann_ndf.DG1(ndf, params.getNdotVUnclamped(), lambda, onePlusLambda_V); - - return _pdf; + return beckmann_ndf.DG1(ndf, params.getNdotVUnclamped(), lambda, onePlusLambda_V); } scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 78015e671f..7cbb520562 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -143,22 +143,24 @@ struct SGGXBxDF { scalar_type a2 = A.x*A.x; ndf::GGX ggx_ndf; - scalar_type NG = ggx_ndf.D(a2, params.getNdotH2()); + ggx_ndf.a2 = a2; + ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; + scalar_type NG = ggx_ndf.D(params.getNdotH2()); if (a2 > numeric_limits::min) { - NG *= ggx_ndf.correlated_wo_numerator(a2, params.getNdotV(), params.getNdotV2(), params.getNdotL(), params.getNdotL2()); + NG *= ggx_ndf.correlated_wo_numerator(params.getNdotV(), params.getNdotV2(), params.getNdotL(), params.getNdotL2()); } return NG; } scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_anisotropic_t) params) { - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; ndf::GGX ggx_ndf; - scalar_type NG = ggx_ndf.D(A.x, A.y, ax2, ay2, params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); + ggx_ndf.ax = A.x; + ggx_ndf.ay = A.y; + scalar_type NG = ggx_ndf.D(params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); if (any >(A > (vector2_type)numeric_limits::min)) { - NG *= ggx_ndf.correlated_wo_numerator(ax2, ay2, params.getNdotV(), params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getNdotL(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); + NG *= ggx_ndf.correlated_wo_numerator(params.getNdotV(), params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getNdotL(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); } return NG; } @@ -236,10 +238,12 @@ struct SGGXBxDF scalar_type ndf, G1_over_2NdotV; const scalar_type a2 = A.x*A.x; ndf::GGX ggx_ndf; - ndf = ggx_ndf.D(a2, params.getNdotH2()); + ggx_ndf.a2 = a2; + ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; + ndf = ggx_ndf.D(params.getNdotH2()); - const scalar_type devsh_v = ggx_ndf.devsh_part(params.getNdotV2(), a2, 1.0-a2); - G1_over_2NdotV = ggx_ndf.G1_wo_numerator(params.getNdotVUnclamped(), devsh_v); + const scalar_type devsh_v = ggx_ndf.devsh_part(params.getNdotV2()); + G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(params.getNdotVUnclamped(), devsh_v); return ggx_ndf.DG1(ndf, G1_over_2NdotV); } @@ -249,10 +253,12 @@ struct SGGXBxDF const scalar_type ax2 = A.x*A.x; const scalar_type ay2 = A.y*A.y; ndf::GGX ggx_ndf; - ndf = ggx_ndf.D(A.x, A.y, ax2, ay2, params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); + ggx_ndf.ax = A.x; + ggx_ndf.ay = A.y; + ndf = ggx_ndf.D(params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); - const scalar_type devsh_v = ggx_ndf.devsh_part(params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), ax2, ay2); - G1_over_2NdotV = ggx_ndf.G1_wo_numerator(params.getNdotVUnclamped(), devsh_v); + const scalar_type devsh_v = ggx_ndf.devsh_part(params.getTdotV2(), params.getBdotV2(), params.getNdotV2()); + G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(params.getNdotVUnclamped(), devsh_v); return ggx_ndf.DG1(ndf, G1_over_2NdotV); } @@ -264,10 +270,12 @@ struct SGGXBxDF spectral_type quo = (spectral_type)0.0; if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) { - ndf::GGX ggx_ndf; - const scalar_type a2 = A.x*A.x; - const scalar_type G2_over_G1 = ggx_ndf.G2_over_G1(a2, false, params.getNdotVUnclamped(), params.getNdotV2(), params.getNdotLUnclamped(), params.getNdotL2()); + ndf::GGX ggx_ndf; + ggx_ndf.a2 = a2; + ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; + + const scalar_type G2_over_G1 = ggx_ndf.G2_over_G1(params.getNdotVUnclamped(), params.getNdotV2(), params.getNdotLUnclamped(), params.getNdotL2()); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); @@ -284,10 +292,10 @@ struct SGGXBxDF if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) { ndf::GGX ggx_ndf; + ggx_ndf.ax = A.x; + ggx_ndf.ay = A.y; - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; - const scalar_type G2_over_G1 = ggx_ndf.G2_over_G1(ax2, ay2, false, params.getNdotVUnclamped(), params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getNdotLUnclamped(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); + const scalar_type G2_over_G1 = ggx_ndf.G2_over_G1(params.getNdotVUnclamped(), params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getNdotLUnclamped(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index c7f38ad782..3fedcbcc09 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -186,7 +186,8 @@ struct SBeckmannDielectricBxDF Refract r = Refract::create(localV, H); cache.iso_cache.LdotH = hlsl::mix(VdotH, r.getNdotT(rcpEta.value2[0]), transmitted); ray_dir_info_type localL; - bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(localV, H); + bxdf::ReflectRefract rr; + rr.refract = r; localL.direction = rr(transmitted, rcpEta.value[0]); return sample_type::createFromTangentSpace(localV, localL, m); @@ -240,9 +241,7 @@ struct SBeckmannDielectricBxDF lambda = beckmann_ndf.LambdaC2(params.getNdotV2()); - scalar_type _pdf = beckmann_ndf.DG1(ndf,params.getNdotV(),lambda,transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0],reflectance,onePlusLambda_V); - - return _pdf; + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, transmitted) * beckmann_ndf.DG1(ndf,params.getNdotV(),lambda,transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0],onePlusLambda_V); } scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { @@ -262,9 +261,7 @@ struct SBeckmannDielectricBxDF lambda = beckmann_ndf.LambdaC2(params.getTdotV2(), params.getBdotV2(), params.getNdotV2()); - scalar_type _pdf = beckmann_ndf.DG1(ndf,params.getNdotV(),lambda,transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0],reflectance,onePlusLambda_V); - - return _pdf; + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, transmitted) * beckmann_ndf.DG1(ndf,params.getNdotV(),lambda,transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0],onePlusLambda_V); } scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 0136ae55d0..e84574cd91 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -189,7 +189,8 @@ struct SGGXDielectricBxDF Refract r = Refract::create(localV, H); cache.iso_cache.LdotH = hlsl::mix(VdotH, r.getNdotT(rcpEta.value2[0]), transmitted); ray_dir_info_type localL; - bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(localV, H); + bxdf::ReflectRefract rr; + rr.refract = r; localL.direction = rr(transmitted, rcpEta.value[0]); return sample_type::createFromTangentSpace(localV, localL, m); @@ -238,12 +239,14 @@ struct SGGXDielectricBxDF scalar_type ndf, devsh_v; const scalar_type a2 = A.x*A.x; ndf::GGX ggx_ndf; - ndf = ggx_ndf.D(a2, params.getNdotH2()); + ggx_ndf.a2 = a2; + ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; + ndf = ggx_ndf.D(params.getNdotH2()); - devsh_v = ggx_ndf.devsh_part(params.getNdotV2(), a2, 1.0-a2); - const scalar_type lambda = ggx_ndf.G1_wo_numerator(params.getNdotV(), devsh_v); + devsh_v = ggx_ndf.devsh_part(params.getNdotV2()); + const scalar_type lambda = ggx_ndf.G1_wo_numerator_devsh_part(params.getNdotV(), devsh_v); - return ggx_ndf.DG1(ndf, lambda, transmitted, params.getVdotH(), params.getLdotH(), VdotHLdotH, orientedEta.value[0], reflectance); + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, transmitted) * ggx_ndf.DG1(ndf, lambda, transmitted, params.getVdotH(), params.getLdotH(), VdotHLdotH, orientedEta.value[0]); } scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { @@ -256,43 +259,41 @@ struct SGGXDielectricBxDF const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; scalar_type ndf, devsh_v; - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; - ndf::GGX ggx_ndf; - ndf = ggx_ndf.D(A.x, A.y, ax2, ay2, params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); + ggx_ndf.ax = A.x; + ggx_ndf.ay = A.y; + ndf = ggx_ndf.D(params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); - devsh_v = ggx_ndf.devsh_part(params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), ax2, ay2); - const scalar_type lambda = ggx_ndf.G1_wo_numerator(params.getNdotV(), devsh_v); + devsh_v = ggx_ndf.devsh_part(params.getTdotV2(), params.getBdotV2(), params.getNdotV2()); + const scalar_type lambda = ggx_ndf.G1_wo_numerator_devsh_part(params.getNdotV(), devsh_v); - return ggx_ndf.DG1(ndf, lambda, transmitted, params.getVdotH(), params.getLdotH(), VdotHLdotH, orientedEta.value[0], reflectance); + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, transmitted) * ggx_ndf.DG1(ndf, lambda, transmitted, params.getVdotH(), params.getLdotH(), VdotHLdotH, orientedEta.value[0]); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) { - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; - scalar_type _pdf = pdf(params); const bool transmitted = params.getVdotH() * params.getLdotH() < 0.0; + const scalar_type a2 = A.x * A.x; ndf::GGX ggx_ndf; + ggx_ndf.a2 = a2; + ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; scalar_type quo; - quo = ggx_ndf.G2_over_G1(ax2, transmitted, params.getNdotV(), params.getNdotV2(), params.getNdotL(), params.getNdotL2()); + quo = ggx_ndf.G2_over_G1(transmitted, params.getNdotV(), params.getNdotV2(), params.getNdotL(), params.getNdotL2()); return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; - scalar_type _pdf = pdf(params); const bool transmitted = params.getVdotH() * params.getLdotH() < 0.0; ndf::GGX ggx_ndf; + ggx_ndf.ax = A.x; + ggx_ndf.ay = A.y; scalar_type quo; - quo = ggx_ndf.G2_over_G1(ax2, ay2, transmitted, params.getNdotV(), params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getNdotL(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); + quo = ggx_ndf.G2_over_G1(transmitted, params.getNdotV(), params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getNdotL(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index 4a6c198e96..97dae51043 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -131,7 +131,8 @@ struct SSmoothDielectricBxDF r = Refract::create(V, N); - bxdf::ReflectRefract rr = bxdf::ReflectRefract::create(r); + bxdf::ReflectRefract rr; + rr.refract = r; L.direction = rr(transmitted, orientedEta.rcp[0]); return sample_type::create(L, nbl::hlsl::dot(V, L.direction), T, B, N); } From 061f7d897e353bb34e112168dbaa6cd69d5977cc Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 23 Jul 2025 14:31:27 +0700 Subject: [PATCH 137/188] NBL_UNROLL macro --- include/nbl/builtin/hlsl/macros.h | 6 ++++++ include/nbl/builtin/hlsl/math/linalg/fast_affine.hlsl | 7 ------- include/nbl/builtin/hlsl/shapes/aabb.hlsl | 2 -- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/include/nbl/builtin/hlsl/macros.h b/include/nbl/builtin/hlsl/macros.h index cb4b684d54..944f06cdc9 100644 --- a/include/nbl/builtin/hlsl/macros.h +++ b/include/nbl/builtin/hlsl/macros.h @@ -34,6 +34,12 @@ inline auto functionAlias(Args&&... args) -> decltype(origFunctionName(std::forw #endif +#ifdef __HLSL_VERSION +#define NBL_UNROLL [[unroll]] +#else +#define NBL_UNROLL +#endif + #ifdef __HLSL_VERSION // cause DXC is insane #define NBL_FP64_LITERAL(LIT) LIT##l #else // and nobody except GCC supports C++23 `f64` suffix on float literals diff --git a/include/nbl/builtin/hlsl/math/linalg/fast_affine.hlsl b/include/nbl/builtin/hlsl/math/linalg/fast_affine.hlsl index a8134ee871..f9d7cd3546 100644 --- a/include/nbl/builtin/hlsl/math/linalg/fast_affine.hlsl +++ b/include/nbl/builtin/hlsl/math/linalg/fast_affine.hlsl @@ -18,12 +18,6 @@ namespace math { namespace linalg { -// TODO: move to macros -#ifdef __HLSL_VERSION -#define NBL_UNROLL [[unroll]] -#else -#define NBL_UNROLL -#endif // Multiply matrices as-if extended to be filled with identity elements template @@ -82,7 +76,6 @@ vector promoted_mul(NBL_CONST_REF_ARG(matrix) lhs, const vector } return retval; } -#undef NBL_UNROLL // useful for fast computation of a Normal Matrix template diff --git a/include/nbl/builtin/hlsl/shapes/aabb.hlsl b/include/nbl/builtin/hlsl/shapes/aabb.hlsl index d07b38df37..5b4b1be39d 100644 --- a/include/nbl/builtin/hlsl/shapes/aabb.hlsl +++ b/include/nbl/builtin/hlsl/shapes/aabb.hlsl @@ -90,7 +90,6 @@ struct union_helper> return retval; } }; -#define NBL_UNROLL [[unroll]] // without a translation component template struct transform_helper,matrix > @@ -131,7 +130,6 @@ struct transform_helper,matrix > return retval; } }; -#undef NBL_UNROLL } } From 1add8a3b6d3f2871326ac6cc27f3c1465b53d809 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 23 Jul 2025 14:48:06 +0700 Subject: [PATCH 138/188] minor changes to sphere sampling, rng usage --- include/nbl/builtin/hlsl/bxdf/fresnel.hlsl | 10 +++++++ .../hlsl/random/dim_adaptor_recursive.hlsl | 8 ++---- include/nbl/builtin/hlsl/random/lcg.hlsl | 2 +- include/nbl/builtin/hlsl/random/pcg.hlsl | 2 +- .../nbl/builtin/hlsl/random/xoroshiro.hlsl | 4 +-- .../hlsl/sampling/cos_weighted_spheres.hlsl | 28 ++++++++----------- .../hlsl/sampling/uniform_spheres.hlsl | 14 ++++------ 7 files changed, 35 insertions(+), 33 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl index a674b635dc..dfcc33d431 100644 --- a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl @@ -8,6 +8,7 @@ #include "nbl/builtin/hlsl/cpp_compat.hlsl" #include "nbl/builtin/hlsl/concepts.hlsl" #include "nbl/builtin/hlsl/numbers.hlsl" +#include "nbl/builtin/hlsl/complex.hlsl" #include "nbl/builtin/hlsl/vector_utils/vector_traits.hlsl" namespace nbl @@ -316,6 +317,15 @@ struct Conductor return retval; } + static Conductor create(NBL_CONST_REF_ARG(complex_t) eta, scalar_type clampedCosTheta) + { + Conductor retval; + retval.eta = eta.real(); + retval.etak2 = eta.imag()*eta.imag(); + retval.clampedCosTheta = clampedCosTheta; + return retval; + } + T operator()() { const scalar_type cosTheta2 = clampedCosTheta * clampedCosTheta; diff --git a/include/nbl/builtin/hlsl/random/dim_adaptor_recursive.hlsl b/include/nbl/builtin/hlsl/random/dim_adaptor_recursive.hlsl index 8ec882de78..cb0b522e68 100644 --- a/include/nbl/builtin/hlsl/random/dim_adaptor_recursive.hlsl +++ b/include/nbl/builtin/hlsl/random/dim_adaptor_recursive.hlsl @@ -1,6 +1,7 @@ #ifndef _NBL_HLSL_RANDOM_DIM_ADAPTOR_RECURSIVE_INCLUDED_ #define _NBL_HLSL_RANDOM_DIM_ADAPTOR_RECURSIVE_INCLUDED_ +#include #include "nbl/builtin/hlsl/type_traits.hlsl" namespace nbl @@ -17,7 +18,7 @@ struct DimAdaptorRecursive using rng_type = RNG; using return_type = vector; - static DimAdaptorRecursive construct(rng_type rng) + static DimAdaptorRecursive construct(NBL_REF_ARG(rng_type) rng) { DimAdaptorRecursive retval; retval.rng = rng; @@ -29,10 +30,7 @@ struct DimAdaptorRecursive array_set setter; return_type retval; -#ifdef __HLSL_VERSION - [unroll] -#endif - for (uint32_t i = 0; i < DIM; i++) + NBL_UNROLL for (uint32_t i = 0; i < DIM; i++) setter(retval, i, rng()); return retval; } diff --git a/include/nbl/builtin/hlsl/random/lcg.hlsl b/include/nbl/builtin/hlsl/random/lcg.hlsl index 0ac0d809aa..8d11d8eed2 100644 --- a/include/nbl/builtin/hlsl/random/lcg.hlsl +++ b/include/nbl/builtin/hlsl/random/lcg.hlsl @@ -15,7 +15,7 @@ struct Lcg { using seed_type = uint32_t; - static Lcg create(NBL_CONST_REF_ARG(seed_type) _state) + static Lcg create(const seed_type _state) { Lcg retval; retval.state = _state; diff --git a/include/nbl/builtin/hlsl/random/pcg.hlsl b/include/nbl/builtin/hlsl/random/pcg.hlsl index 2b881e29a2..f579890b1a 100644 --- a/include/nbl/builtin/hlsl/random/pcg.hlsl +++ b/include/nbl/builtin/hlsl/random/pcg.hlsl @@ -15,7 +15,7 @@ struct PCG32 { using seed_type = uint32_t; - static PCG32 construct(NBL_CONST_REF_ARG(seed_type) initialState) + static PCG32 construct(const seed_type initialState) { PCG32 retval; retval.state = initialState; diff --git a/include/nbl/builtin/hlsl/random/xoroshiro.hlsl b/include/nbl/builtin/hlsl/random/xoroshiro.hlsl index 1a150f1909..6cf3eff842 100644 --- a/include/nbl/builtin/hlsl/random/xoroshiro.hlsl +++ b/include/nbl/builtin/hlsl/random/xoroshiro.hlsl @@ -33,7 +33,7 @@ struct Xoroshiro64Star using seed_type = uint32_t2; // TODO: create - static Xoroshiro64Star construct(NBL_CONST_REF_ARG(seed_type) initialState) + static Xoroshiro64Star construct(const seed_type initialState) { Xoroshiro64StateHolder stateHolder = {initialState}; return Xoroshiro64Star(stateHolder); @@ -55,7 +55,7 @@ struct Xoroshiro64StarStar using seed_type = uint32_t2; // TODO: create - static Xoroshiro64StarStar construct(NBL_CONST_REF_ARG(seed_type) initialState) + static Xoroshiro64StarStar construct(const seed_type initialState) { Xoroshiro64StateHolder stateHolder = {initialState}; return Xoroshiro64StarStar(stateHolder); diff --git a/include/nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl b/include/nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl index 72ae719eeb..80a3cd2c52 100644 --- a/include/nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl +++ b/include/nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl @@ -34,18 +34,16 @@ struct ProjectedHemisphere return L_z * numbers::inv_pi; } - template) - static sampling::quotient_and_pdf, T> quotient_and_pdf(T L) + template > + static sampling::quotient_and_pdf quotient_and_pdf(T L) { - using vector_t1 = vector; - return sampling::quotient_and_pdf::create(hlsl::promote(1.0), pdf(L)); + return sampling::quotient_and_pdf::create(hlsl::promote(1.0), pdf(L)); } - template) - static sampling::quotient_and_pdf, T> quotient_and_pdf(vector_t3 L) + template > + static sampling::quotient_and_pdf quotient_and_pdf(vector_t3 L) { - using vector_t1 = vector; - return sampling::quotient_and_pdf::create(hlsl::promote(1.0), pdf(L.z)); + return sampling::quotient_and_pdf::create(hlsl::promote(1.0), pdf(L.z)); } }; @@ -72,18 +70,16 @@ struct ProjectedSphere return T(0.5) * hemisphere_t::pdf(L_z); } - template) - static sampling::quotient_and_pdf, T> quotient_and_pdf(T L) + template > + static sampling::quotient_and_pdf quotient_and_pdf(T L) { - using vector_t1 = vector; - return sampling::quotient_and_pdf::create(hlsl::promote(1.0), pdf(L)); + return sampling::quotient_and_pdf::create(hlsl::promote(1.0), pdf(L)); } - template) - static sampling::quotient_and_pdf, T> quotient_and_pdf(vector_t3 L) + template > + static sampling::quotient_and_pdf quotient_and_pdf(vector_t3 L) { - using vector_t1 = vector; - return sampling::quotient_and_pdf::create(hlsl::promote(1.0), pdf(L.z)); + return sampling::quotient_and_pdf::create(hlsl::promote(1.0), pdf(L.z)); } }; diff --git a/include/nbl/builtin/hlsl/sampling/uniform_spheres.hlsl b/include/nbl/builtin/hlsl/sampling/uniform_spheres.hlsl index e4c9385499..df4100db9b 100644 --- a/include/nbl/builtin/hlsl/sampling/uniform_spheres.hlsl +++ b/include/nbl/builtin/hlsl/sampling/uniform_spheres.hlsl @@ -36,11 +36,10 @@ struct UniformHemisphere return T(1.0) / (T(2.0) * numbers::pi); } - template) - static quotient_and_pdf, T> quotient_and_pdf() + template > + static quotient_and_pdf quotient_and_pdf() { - using vector_t1 = vector; - return quotient_and_pdf::create(hlsl::promote(1.0), pdf()); + return quotient_and_pdf::create(hlsl::promote(1.0), pdf()); } }; @@ -63,11 +62,10 @@ struct UniformSphere return T(1.0) / (T(4.0) * numbers::pi); } - template) - static quotient_and_pdf, T> quotient_and_pdf() + template > + static quotient_and_pdf quotient_and_pdf() { - using vector_t1 = vector; - return quotient_and_pdf::create(hlsl::promote(1.0), pdf()); + return quotient_and_pdf::create(hlsl::promote(1.0), pdf()); } }; } From 9760d710de9b3bdbb5d9c1099fbdce890a2f54da Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 23 Jul 2025 15:42:00 +0700 Subject: [PATCH 139/188] split diffuse correction factor into own struct --- include/nbl/builtin/hlsl/bxdf/fresnel.hlsl | 32 +++++++++++++++------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl index dfcc33d431..25a1eba175 100644 --- a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl @@ -22,6 +22,23 @@ namespace bxdf namespace fresnel { +// derived from the Earl Hammon GDC talk but improved for all IOR not just 1.333 with actual numerical integration and curve fitting +template) +struct DiffuseCorrectionFactor +{ + T operator()() + { + vector::Dimension> TIR = orientedEta < hlsl::promote(1.0); + T invdenum = nbl::hlsl::mix(hlsl::promote(1.0), hlsl::promote(1.0) / (orientedEta2 * orientedEta2 * (hlsl::promote(554.33) - hlsl::promote(380.7) * orientedEta)), TIR); + T num = orientedEta * nbl::hlsl::mix(hlsl::promote(0.1921156102251088), orientedEta * hlsl::promote(298.25) - hlsl::promote(261.38) * orientedEta2 + hlsl::promote(138.43), TIR); + num = num + nbl::hlsl::mix(hlsl::promote(0.8078843897748912), hlsl::promote(-1.67), TIR); + return num * invdenum; + } + + T orientedEta; + T orientedEta2; +}; + template) struct OrientedEtaRcps { @@ -37,17 +54,12 @@ struct OrientedEtaRcps return retval; } - T diffuseFresnelCorrectionFactor() + DiffuseCorrectionFactor createDiffuseCorrectionFactor() NBL_CONST_MEMBER_FUNC { - // assert(n*n==n2); - const T n = hlsl::promote(1.0) / value; - const T n2 = hlsl::promote(1.0) / value2; - - vector::Dimension> TIR = n < hlsl::promote(1.0); - T invdenum = nbl::hlsl::mix(hlsl::promote(1.0), hlsl::promote(1.0) / (n2 * n2 * (hlsl::promote(554.33) - hlsl::promote(380.7) * n)), TIR); - T num = n * nbl::hlsl::mix(hlsl::promote(0.1921156102251088), n * hlsl::promote(298.25) - hlsl::promote(261.38) * n2 + hlsl::promote(138.43), TIR); - num += nbl::hlsl::mix(hlsl::promote(0.8078843897748912), hlsl::promote(-1.67), TIR); - return num * invdenum; + DiffuseCorrectionFactor diffuseCorrectionFactor; + diffuseCorrectionFactor.orientedEta = hlsl::promote(1.0) / value; + diffuseCorrectionFactor.orientedEta2 = hlsl::promote(1.0) / value2; + return diffuseCorrectionFactor; } T value; From 73b0f6d2357ebccec44a8a843fd3d5a2c7566ca5 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 23 Jul 2025 15:54:30 +0700 Subject: [PATCH 140/188] split out angle adding stuff into new file --- examples_tests | 2 +- .../nbl/builtin/hlsl/math/angle_adding.hlsl | 127 ++++++++++++++++++ include/nbl/builtin/hlsl/math/functions.hlsl | 99 -------------- src/nbl/builtin/CMakeLists.txt | 1 + 4 files changed, 129 insertions(+), 100 deletions(-) create mode 100644 include/nbl/builtin/hlsl/math/angle_adding.hlsl diff --git a/examples_tests b/examples_tests index dbd75ea02a..765906175f 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit dbd75ea02aeff229d693a50b78c285692e4fde68 +Subproject commit 765906175f6b533ac5b013cec0ef85753f73b329 diff --git a/include/nbl/builtin/hlsl/math/angle_adding.hlsl b/include/nbl/builtin/hlsl/math/angle_adding.hlsl new file mode 100644 index 0000000000..9c1da04a0e --- /dev/null +++ b/include/nbl/builtin/hlsl/math/angle_adding.hlsl @@ -0,0 +1,127 @@ +// Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_BUILTIN_HLSL_MATH_ANGLE_ADDING_INCLUDED_ +#define _NBL_BUILTIN_HLSL_MATH_ANGLE_ADDING_INCLUDED_ + +#include "nbl/builtin/hlsl/cpp_compat.hlsl" +#include "nbl/builtin/hlsl/numbers.hlsl" +#include "nbl/builtin/hlsl/vector_utils/vector_traits.hlsl" +#include "nbl/builtin/hlsl/concepts/vector.hlsl" +#include "nbl/builtin/hlsl/spirv_intrinsics/core.hlsl" +#include "nbl/builtin/hlsl/ieee754.hlsl" + +namespace nbl +{ +namespace hlsl +{ +namespace math +{ + +namespace impl +{ +struct sincos_accumulator +{ + using this_t = sincos_accumulator; + + static this_t create() + { + this_t retval; + retval.tmp0 = 0; + retval.tmp1 = 0; + retval.tmp2 = 0; + retval.tmp3 = 0; + retval.tmp4 = 0; + retval.tmp5 = 0; + return retval; + } + + static this_t create(float cosA, float cosB, float cosC, float sinA, float sinB, float sinC) + { + this_t retval; + retval.tmp0 = cosA; + retval.tmp1 = cosB; + retval.tmp2 = cosC; + retval.tmp3 = sinA; + retval.tmp4 = sinB; + retval.tmp5 = sinC; + return retval; + } + + float getArccosSumofABC_minus_PI() + { + const bool AltminusB = tmp0 < (-tmp1); + const float cosSumAB = tmp0 * tmp1 - tmp3 * tmp4; + const bool ABltminusC = cosSumAB < (-tmp2); + const bool ABltC = cosSumAB < tmp2; + // apply triple angle formula + const float absArccosSumABC = acos(clamp(cosSumAB * tmp2 - (tmp0 * tmp4 + tmp3 * tmp1) * tmp5, -1.f, 1.f)); + return ((AltminusB ? ABltC : ABltminusC) ? (-absArccosSumABC) : absArccosSumABC) + ((AltminusB || ABltminusC) ? numbers::pi : (-numbers::pi)); + } + + static void combineCosForSumOfAcos(float cosA, float cosB, float biasA, float biasB, NBL_REF_ARG(float) out0, NBL_REF_ARG(float) out1) + { + const float bias = biasA + biasB; + const float a = cosA; + const float b = cosB; + const bool reverse = abs(min(a, b)) > max(a, b); + const float c = a * b - sqrt((1.0f - a * a) * (1.0f - b * b)); + + if (reverse) + { + out0 = -c; + out1 = bias + numbers::pi; + } + else + { + out0 = c; + out1 = bias; + } + } + + float tmp0; + float tmp1; + float tmp2; + float tmp3; + float tmp4; + float tmp5; +}; +} + +float getArccosSumofABC_minus_PI(float cosA, float cosB, float cosC, float sinA, float sinB, float sinC) +{ + impl::sincos_accumulator acc = impl::sincos_accumulator::create(cosA, cosB, cosC, sinA, sinB, sinC); + return acc.getArccosSumofABC_minus_PI(); +} + +void combineCosForSumOfAcos(float cosA, float cosB, float biasA, float biasB, NBL_REF_ARG(float) out0, NBL_REF_ARG(float) out1) +{ + impl::sincos_accumulator acc = impl::sincos_accumulator::create(); + impl::sincos_accumulator::combineCosForSumOfAcos(cosA, cosB, biasA, biasB, acc.tmp0, acc.tmp1); + out0 = acc.tmp0; + out1 = acc.tmp1; +} + +// returns acos(a) + acos(b) +float getSumofArccosAB(float cosA, float cosB) +{ + impl::sincos_accumulator acc = impl::sincos_accumulator::create(); + impl::sincos_accumulator::combineCosForSumOfAcos(cosA, cosB, 0.0f, 0.0f, acc.tmp0, acc.tmp1); + return acos(acc.tmp0) + acc.tmp1; +} + +// returns acos(a) + acos(b) + acos(c) + acos(d) +float getSumofArccosABCD(float cosA, float cosB, float cosC, float cosD) +{ + impl::sincos_accumulator acc = impl::sincos_accumulator::create(); + impl::sincos_accumulator::combineCosForSumOfAcos(cosA, cosB, 0.0f, 0.0f, acc.tmp0, acc.tmp1); + impl::sincos_accumulator::combineCosForSumOfAcos(cosC, cosD, 0.0f, 0.0f, acc.tmp2, acc.tmp3); + impl::sincos_accumulator::combineCosForSumOfAcos(acc.tmp0, acc.tmp2, acc.tmp1, acc.tmp3, acc.tmp4, acc.tmp5); + return acos(acc.tmp4) + acc.tmp5; +} + +} +} +} + +#endif diff --git a/include/nbl/builtin/hlsl/math/functions.hlsl b/include/nbl/builtin/hlsl/math/functions.hlsl index f7a84005e8..20442c467b 100644 --- a/include/nbl/builtin/hlsl/math/functions.hlsl +++ b/include/nbl/builtin/hlsl/math/functions.hlsl @@ -177,73 +177,6 @@ struct conditionalAbsOrMax_helper(condAbs, limit); } }; - -struct trigonometry -{ - using this_t = trigonometry; - - static this_t create() - { - this_t retval; - retval.tmp0 = 0; - retval.tmp1 = 0; - retval.tmp2 = 0; - retval.tmp3 = 0; - retval.tmp4 = 0; - retval.tmp5 = 0; - return retval; - } - - static this_t create(float cosA, float cosB, float cosC, float sinA, float sinB, float sinC) - { - this_t retval; - retval.tmp0 = cosA; - retval.tmp1 = cosB; - retval.tmp2 = cosC; - retval.tmp3 = sinA; - retval.tmp4 = sinB; - retval.tmp5 = sinC; - return retval; - } - - float getArccosSumofABC_minus_PI() - { - const bool AltminusB = tmp0 < (-tmp1); - const float cosSumAB = tmp0 * tmp1 - tmp3 * tmp4; - const bool ABltminusC = cosSumAB < (-tmp2); - const bool ABltC = cosSumAB < tmp2; - // apply triple angle formula - const float absArccosSumABC = acos(clamp(cosSumAB * tmp2 - (tmp0 * tmp4 + tmp3 * tmp1) * tmp5, -1.f, 1.f)); - return ((AltminusB ? ABltC : ABltminusC) ? (-absArccosSumABC) : absArccosSumABC) + ((AltminusB || ABltminusC) ? numbers::pi : (-numbers::pi)); - } - - static void combineCosForSumOfAcos(float cosA, float cosB, float biasA, float biasB, NBL_REF_ARG(float) out0, NBL_REF_ARG(float) out1) - { - const float bias = biasA + biasB; - const float a = cosA; - const float b = cosB; - const bool reverse = abs(min(a, b)) > max(a, b); - const float c = a * b - sqrt((1.0f - a * a) * (1.0f - b * b)); - - if (reverse) - { - out0 = -c; - out1 = bias + numbers::pi; - } - else - { - out0 = c; - out1 = bias; - } - } - - float tmp0; - float tmp1; - float tmp2; - float tmp3; - float tmp4; - float tmp5; -}; } // @ return abs(x) if cond==true, max(x,0.0) otherwise @@ -253,38 +186,6 @@ T conditionalAbsOrMax(bool cond, T x, T limit) return impl::conditionalAbsOrMax_helper::__call(cond, x, limit); } -float getArccosSumofABC_minus_PI(float cosA, float cosB, float cosC, float sinA, float sinB, float sinC) -{ - impl::trigonometry trig = impl::trigonometry::create(cosA, cosB, cosC, sinA, sinB, sinC); - return trig.getArccosSumofABC_minus_PI(); -} - -void combineCosForSumOfAcos(float cosA, float cosB, float biasA, float biasB, NBL_REF_ARG(float) out0, NBL_REF_ARG(float) out1) -{ - impl::trigonometry trig = impl::trigonometry::create(); - impl::trigonometry::combineCosForSumOfAcos(cosA, cosB, biasA, biasB, trig.tmp0, trig.tmp1); - out0 = trig.tmp0; - out1 = trig.tmp1; -} - -// returns acos(a) + acos(b) -float getSumofArccosAB(float cosA, float cosB) -{ - impl::trigonometry trig = impl::trigonometry::create(); - impl::trigonometry::combineCosForSumOfAcos(cosA, cosB, 0.0f, 0.0f, trig.tmp0, trig.tmp1); - return acos(trig.tmp0) + trig.tmp1; -} - -// returns acos(a) + acos(b) + acos(c) + acos(d) -float getSumofArccosABCD(float cosA, float cosB, float cosC, float cosD) -{ - impl::trigonometry trig = impl::trigonometry::create(); - impl::trigonometry::combineCosForSumOfAcos(cosA, cosB, 0.0f, 0.0f, trig.tmp0, trig.tmp1); - impl::trigonometry::combineCosForSumOfAcos(cosC, cosD, 0.0f, 0.0f, trig.tmp2, trig.tmp3); - impl::trigonometry::combineCosForSumOfAcos(trig.tmp0, trig.tmp2, trig.tmp1, trig.tmp3, trig.tmp4, trig.tmp5); - return acos(trig.tmp4) + trig.tmp5; -} - template && concepts::Matricial && (matrix_traits::ColumnCount == matrix_traits::RowCount)) typename cpp_compat_intrinsics_impl::mul_helper::return_t applyChainRule(Lhs dFdG, Rhs dGdR) { diff --git a/src/nbl/builtin/CMakeLists.txt b/src/nbl/builtin/CMakeLists.txt index 19712f4cd0..12ad5b080f 100644 --- a/src/nbl/builtin/CMakeLists.txt +++ b/src/nbl/builtin/CMakeLists.txt @@ -294,6 +294,7 @@ LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/math/linalg/fast_affine.hlsl" LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/math/functions.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/math/geometry.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/math/intutil.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/math/angle_adding.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/math/equations/quadratic.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/math/equations/cubic.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/math/equations/quartic.hlsl") From 4b3fdf209d46f2b6bf10cfac29b93a5e7874cf29 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 24 Jul 2025 15:27:24 +0700 Subject: [PATCH 141/188] new mpl find_lsb --- include/nbl/builtin/hlsl/mpl.hlsl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/nbl/builtin/hlsl/mpl.hlsl b/include/nbl/builtin/hlsl/mpl.hlsl index 2015b05b3d..8fb13db872 100644 --- a/include/nbl/builtin/hlsl/mpl.hlsl +++ b/include/nbl/builtin/hlsl/mpl.hlsl @@ -99,6 +99,14 @@ struct min }; template NBL_CONSTEXPR T min_v = min::value; + +template +struct find_lsb +{ + NBL_CONSTEXPR_STATIC_INLINE uint16_t value = log2::value; +}; +template +NBL_CONSTEXPR uint64_t find_lsb_v = find_lsb::value; } } } From dbd2508be849195a69b96f74c66e02e6b0600e0a Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 24 Jul 2025 17:03:43 +0700 Subject: [PATCH 142/188] beta, l2gamma, lgamma same in c++ and hlsl, some calculation changes --- include/nbl/builtin/hlsl/numbers.hlsl | 4 +- include/nbl/builtin/hlsl/tgmath/impl.hlsl | 121 ++++++++++++---------- 2 files changed, 67 insertions(+), 58 deletions(-) diff --git a/include/nbl/builtin/hlsl/numbers.hlsl b/include/nbl/builtin/hlsl/numbers.hlsl index e85e63246d..6671a44756 100644 --- a/include/nbl/builtin/hlsl/numbers.hlsl +++ b/include/nbl/builtin/hlsl/numbers.hlsl @@ -25,6 +25,8 @@ NBL_CONSTEXPR float_t inv_sqrtpi = float_t(0.5641895835477563); template NBL_CONSTEXPR float_t ln2 = float_t(0.6931471805599453); template +NBL_CONSTEXPR float_t inv_ln2 = float_t(1.44269504088896); +template NBL_CONSTEXPR float_t ln10 = float_t(2.302585092994046); template NBL_CONSTEXPR float_t sqrt2 = float_t(1.4142135623730951); @@ -35,7 +37,7 @@ NBL_CONSTEXPR float_t inv_sqrt3 = float_t(0.5773502691896257); template NBL_CONSTEXPR float_t egamma = float_t(0.5772156649015329); template -NBL_CONSTEXPR float_t phi = float_t(1.618033988749895); +NBL_CONSTEXPR float_t phi = float_t(1.618033988749895); } } diff --git a/include/nbl/builtin/hlsl/tgmath/impl.hlsl b/include/nbl/builtin/hlsl/tgmath/impl.hlsl index 45984f8cdd..e17492065a 100644 --- a/include/nbl/builtin/hlsl/tgmath/impl.hlsl +++ b/include/nbl/builtin/hlsl/tgmath/impl.hlsl @@ -8,6 +8,7 @@ #include #include #include +#include // C++ includes #ifndef __HLSL_VERSION @@ -210,54 +211,6 @@ struct erf_helper -NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) -struct lgamma_helper) > -{ - // implementation from Numerical Recipes in C, 2nd ed. - static T __call(T val) - { - const T thresholds[3] = { 7e4, 1e19, 1e19 }; - if (val > thresholds[findLSB(uint32_t(sizeof(T)))]) - return bit_cast(numeric_limits::infinity); - - T x, y; - y = x = val; - T tmp = x + T(5.5); - tmp -= (x + T(0.5)) * log_helper::__call(tmp); - - T ser = T(1.000000000190015); - ser += T(76.18009172947146) / ++y; - ser += T(-86.50532032941677) / ++y; - ser += T(24.01409824083091) / ++y; - ser += T(-1.231739572450155) / ++y; - ser += T(0.1208650973866179e-2) / ++y; - if (sizeof(T)>2) - ser += T(-0.5395239384953e-5) / ++y; - return -tmp + log_helper::__call(T(2.5066282746310005) * ser / x); - } -}; - -// beta function -template -NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) -struct beta_helper) > -{ - // implementation from Numerical Recipes in C, 2nd ed. - static T __call(T v1, T v2) - { - // specialized for Cook Torrance BTDFs - assert(v1 >= 1.0 && v2 >= 1.0); - - if (v1+v2 > 1e6) - return T(0.0); - - return exp2_helper::__call(l2gamma_helper::__call(v1) + l2gamma_helper::__call(v2) - l2gamma_helper::__call(v1+v2)); - } -}; - - #else // C++ only specializations #define DECL_ARG(r,data,i,_T) BOOST_PP_COMMA_IF(BOOST_PP_NOT_EQUAL(i,0)) const _T arg##i @@ -302,9 +255,6 @@ template AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(round_helper, round, co template AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(trunc_helper, trunc, concepts::FloatingPointScalar, (T), (T), T) template AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(ceil_helper, ceil, concepts::FloatingPointScalar, (T), (T), T) -template AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(lgamma_helper, lgamma, concepts::FloatingPointScalar, (T), (T), T) -template AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(beta_helper, beta, concepts::FloatingPointScalar, (T), (T)(T), T) - #undef DECL_ARG #undef WRAP #undef ARG @@ -583,19 +533,76 @@ struct erfInv_helper -NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) -struct l2gamma_helper) > +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar && sizeof(T)<8) +struct l2gamma_helper && sizeof(T)<8) > { // modified Stirling's approximation for log2 up to 3rd polynomial static T __call(T x) { - const T thresholds[3] = {5e4, 1e19, 1e19}; - if (x > thresholds[findLSB(uint32_t(sizeof(T)))]) + const T thresholds[4] = { 0, 5e4, 1e19, 1e19 }; // threshold values gotten from testing when the function returns nan/inf/nonsense + if (x > thresholds[mpl::find_lsb_v]) return bit_cast(numeric_limits::infinity); const T l2x = log2_helper::__call(x); - const T one_over_ln2 = T(1.44269504088896); - return (x - T(0.5)) * l2x - one_over_ln2 * x + T(1.32574806473616) + one_over_ln2 / (T(12.0) * x) + one_over_ln2 / (T(360.0) * x * x * x); + const T r = T(1.0) / x; + const T r2 = r * r; + return (x - T(0.5)) * l2x + T(1.32574806473616) + numbers::inv_ln2 * ((T(1.0/360.0) * r2 + T(1.0/12.0)) * r - x); + } +}; + +template +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar && 8<=sizeof(T)) +struct l2gamma_helper && 8<=sizeof(T)) > +{ + // implementation derived from Numerical Recipes in C, transformed for log2 + static T __call(T x) + { + const T thresholds[4] = { 0, 7e4, 1e19, 1e19 }; // threshold values gotten from testing when the function returns nan/inf/nonsense + if (x > thresholds[mpl::find_lsb_v]) + return bit_cast(numeric_limits::infinity); + + T a = x + T(5.5); + a = a * numbers::inv_ln2 - (x + T(0.5)) * log2_helper::__call(a); + + T b = x; + T ser = T(1.000000000190015); + ser += T(76.18009172947146) / ++b; + ser += T(-86.50532032941677) / ++b; + ser += T(24.01409824083091) / ++b; + ser += T(-1.231739572450155) / ++b; + ser += T(0.1208650973866179e-2) / ++b; + ser += T(-0.5395239384953e-5) / ++b; + return -a + log2_helper::__call(T(2.5066282746310005) * ser / x); + } +}; + +// logn-gamma function +template +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) +struct lgamma_helper) > +{ + static T __call(T val) + { + const T r = T(1.0) / log2_helper::__call(numbers::e); + return r * l2gamma_helper::__call(val); + } +}; + +// beta function +template +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) +struct beta_helper) > +{ + // implementation from Numerical Recipes in C, 2nd ed. + static T __call(T v1, T v2) + { + // specialized for Cook Torrance BTDFs + assert(v1 >= 1.0 && v2 >= 1.0); + + if (v1+v2 > 1e6) + return T(0.0); + + return exp2_helper::__call(l2gamma_helper::__call(v1) + l2gamma_helper::__call(v2) - l2gamma_helper::__call(v1+v2)); } }; From 27656c87e69a03fd22fc576acf9ab2af0faf5219 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 25 Jul 2025 10:49:02 +0700 Subject: [PATCH 143/188] moved VdotL into cache from light sample --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 46 +++++++++---------- .../hlsl/bxdf/reflection/beckmann.hlsl | 4 +- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 4 +- .../hlsl/bxdf/reflection/lambertian.hlsl | 2 - .../hlsl/bxdf/reflection/oren_nayar.hlsl | 4 +- .../hlsl/bxdf/transmission/beckmann.hlsl | 4 +- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 4 +- .../hlsl/bxdf/transmission/lambertian.hlsl | 2 - .../bxdf/transmission/smooth_dielectric.hlsl | 6 +-- 9 files changed, 33 insertions(+), 43 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index c36e77599e..369d6dea8d 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -281,33 +281,29 @@ struct SAnisotropic #define NBL_CONCEPT_PARAM_2 (rdirinfo, typename T::ray_dir_info_type) #define NBL_CONCEPT_PARAM_3 (pV, typename T::vector3_type) #define NBL_CONCEPT_PARAM_4 (frame, typename T::matrix3x3_type) -#define NBL_CONCEPT_PARAM_5 (pVdotL, typename T::scalar_type) -NBL_CONCEPT_BEGIN(6) +NBL_CONCEPT_BEGIN(5) #define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define inter NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define rdirinfo NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 #define pV NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 #define frame NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 -#define pVdotL NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::ray_dir_info_type)) ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) ((NBL_CONCEPT_REQ_TYPE)(T::matrix3x3_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getL()), ::nbl::hlsl::is_same_v, typename T::ray_dir_info_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getVdotL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getTdotL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getBdotL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getNdotL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getNdotL2()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createFromTangentSpace(pV,rdirinfo,frame)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(rdirinfo,pVdotL,pV)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(rdirinfo,pVdotL,pV,pV,pV)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(rdirinfo,pV)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(rdirinfo,pV,pV,pV)), ::nbl::hlsl::is_same_v, T)) // ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create >(pV,inter)), ::nbl::hlsl::is_same_v, T)) // NOTE: temporarily commented out due to dxc bug https://github.com/microsoft/DirectXShaderCompiler/issues/7154 ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getTangentSpaceL()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(ray_dir_info::Basic, typename T::ray_dir_info_type)) ); -#undef pVdotL #undef frame #undef pV #undef rdirinfo @@ -334,7 +330,6 @@ struct SLightSample const vector3_type tsL = tangentSpaceL.getDirection(); retval.L = tangentSpaceL.transform(tangentFrame); - retval.VdotL = nbl::hlsl::dot(tangentSpaceV, tsL); retval.TdotL = tsL.x; retval.BdotL = tsL.y; @@ -343,13 +338,11 @@ struct SLightSample return retval; } - static this_t create(NBL_CONST_REF_ARG(ray_dir_info_type) L, const scalar_type VdotL, NBL_CONST_REF_ARG(vector3_type) N) + static this_t create(NBL_CONST_REF_ARG(ray_dir_info_type) L, NBL_CONST_REF_ARG(vector3_type) N) { this_t retval; retval.L = L; - retval.VdotL = VdotL; - retval.TdotL = bit_cast(numeric_limits::quiet_NaN); retval.BdotL = bit_cast(numeric_limits::quiet_NaN); retval.NdotL = nbl::hlsl::dot(N,L.getDirection()); @@ -357,9 +350,9 @@ struct SLightSample return retval; } - static this_t create(NBL_CONST_REF_ARG(ray_dir_info_type) L, const scalar_type VdotL, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N) + static this_t create(NBL_CONST_REF_ARG(ray_dir_info_type) L, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N) { - this_t retval = create(L,VdotL,N); + this_t retval = create(L,N); retval.TdotL = nbl::hlsl::dot(T,L.getDirection()); retval.BdotL = nbl::hlsl::dot(B,L.getDirection()); @@ -374,9 +367,9 @@ struct SLightSample const scalar_type VdotL = nbl::hlsl::dot(V,L); this_t retval; if (surface_interactions::Anisotropic) // TODO use NBL_IF_CONSTEXPR when pr #860 is merged - retval = create(L,VdotL,interaction.T,interaction.B,interaction.N); + retval = create(L,interaction.T,interaction.B,interaction.N); else - retval = create(L, VdotL, interaction.N); + retval = create(L,interaction.N); return retval; } @@ -386,7 +379,6 @@ struct SLightSample } ray_dir_info_type getL() NBL_CONST_MEMBER_FUNC { return L; } - scalar_type getVdotL() NBL_CONST_MEMBER_FUNC { return VdotL; } scalar_type getTdotL() NBL_CONST_MEMBER_FUNC { return TdotL; } scalar_type getBdotL() NBL_CONST_MEMBER_FUNC { return BdotL; } scalar_type getNdotL() NBL_CONST_MEMBER_FUNC { return NdotL; } @@ -394,7 +386,6 @@ struct SLightSample RayDirInfo L; - scalar_type VdotL; scalar_type TdotL; scalar_type BdotL; @@ -412,6 +403,7 @@ NBL_CONCEPT_BEGIN(1) NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getVdotL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getVdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getLdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getNdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) @@ -467,7 +459,7 @@ struct SIsotropicMicrofacetCache LplusV_rcpLen = rsqrt(2.0 + 2.0 * VdotL); this_t retval; - + retval.VdotL = VdotL; retval.VdotH = LplusV_rcpLen * VdotL + LplusV_rcpLen; retval.LdotH = retval.VdotH; retval.NdotH = (NdotL + NdotV) * LplusV_rcpLen; @@ -485,7 +477,7 @@ struct SIsotropicMicrofacetCache NBL_CONST_REF_ARG(IsotropicInteraction) interaction, NBL_CONST_REF_ARG(LS) _sample) { - return createForReflection(interaction.getNdotV(), _sample.getNdotL(), _sample.getVdotL()); + return createForReflection(interaction.getNdotV(), _sample.getNdotL(), hlsl::dot(interaction.getV().getDirection(), _sample.getL().getDirection())); } // transmissive cases need to be checked if the path is valid before usage @@ -493,6 +485,7 @@ struct SIsotropicMicrofacetCache NBL_CONST_REF_ARG(vector3_type) N, NBL_REF_ARG(vector3_type) H) { this_t retval; + retval.VdotL = VdotL; H = computeMicrofacetNormal.normalized(transmitted); retval.NdotH = hlsl::dot(N, H); @@ -549,7 +542,7 @@ struct SIsotropicMicrofacetCache ComputeMicrofacetNormal computeMicrofacetNormal = ComputeMicrofacetNormal::create(V,L,N,1.0); computeMicrofacetNormal.orientedEta = orientedEtas; - return create(transmitted, computeMicrofacetNormal, _sample.getVdotL(), N, H); + return create(transmitted, computeMicrofacetNormal, hlsl::dot(V, L), N, H); } template && LightSample) @@ -568,10 +561,12 @@ struct SIsotropicMicrofacetCache return VdotH; } + scalar_type getVdotL() NBL_CONST_MEMBER_FUNC { return VdotL; } scalar_type getLdotH() NBL_CONST_MEMBER_FUNC { return LdotH; } scalar_type getNdotH() NBL_CONST_MEMBER_FUNC { return NdotH; } scalar_type getNdotH2() NBL_CONST_MEMBER_FUNC { return NdotH2; } + scalar_type VdotL; scalar_type VdotH; scalar_type LdotH; scalar_type NdotH; @@ -680,7 +675,7 @@ struct SAnisotropicMicrofacetCache NBL_CONST_REF_ARG(AnisotropicInteraction) interaction, NBL_CONST_REF_ARG(LS) _sample) { - return createForReflection(interaction.getTangentSpaceV(), _sample.getTangentSpaceL(), _sample.getVdotL()); + return createForReflection(interaction.getTangentSpaceV(), _sample.getTangentSpaceL(), hlsl::dot(interaction.getV().getDirection(), _sample.getL().getDirection())); } // transmissive cases need to be checked if the path is valid before usage static this_t create( @@ -718,6 +713,7 @@ struct SAnisotropicMicrofacetCache return retval; } + scalar_type getVdotL() NBL_CONST_MEMBER_FUNC { return iso_cache.getVdotL(); } scalar_type getVdotH() NBL_CONST_MEMBER_FUNC { return iso_cache.getVdotH(); } scalar_type getLdotH() NBL_CONST_MEMBER_FUNC { return iso_cache.getLdotH(); } scalar_type getNdotH() NBL_CONST_MEMBER_FUNC { return iso_cache.getNdotH(); } @@ -854,10 +850,10 @@ enum BxDFClampMode : uint16_t BCM_ABS }; -template -using quotient_and_pdf_scalar = sampling::quotient_and_pdf, float32_t> ; -template -using quotient_and_pdf_rgb = sampling::quotient_and_pdf, T> ; +template +using quotient_and_pdf_scalar = sampling::quotient_and_pdf, P> ; +template +using quotient_and_pdf_rgb = sampling::quotient_and_pdf, P> ; } } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index c3556331f2..26204ac3a1 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -43,7 +43,7 @@ struct BeckmannParams(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return cache.getVdotL(); } Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } Scalar getNdotH2() NBL_CONST_MEMBER_FUNC { return cache.getNdotH2(); } Scalar getVdotH() NBL_CONST_MEMBER_FUNC { return cache.getVdotH(); } @@ -77,7 +77,7 @@ struct BeckmannParams(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return cache.getVdotL(); } Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } Scalar getNdotH2() NBL_CONST_MEMBER_FUNC { return cache.getNdotH2(); } Scalar getVdotH() NBL_CONST_MEMBER_FUNC { return cache.getVdotH(); } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 7cbb520562..ff0ea6c9e8 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -43,7 +43,7 @@ struct GGXParams(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return cache.getVdotL(); } Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } Scalar getNdotH2() NBL_CONST_MEMBER_FUNC { return cache.getNdotH2(); } Scalar getVdotH() NBL_CONST_MEMBER_FUNC { return cache.getVdotH(); } @@ -77,7 +77,7 @@ struct GGXParams(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return cache.getVdotL(); } Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } Scalar getNdotH2() NBL_CONST_MEMBER_FUNC { return cache.getNdotH2(); } Scalar getVdotH() NBL_CONST_MEMBER_FUNC { return cache.getVdotH(); } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl index cf33394808..40ff1a832a 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl @@ -41,7 +41,6 @@ struct LambertianParams(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } LS _sample; SI interaction; @@ -69,7 +68,6 @@ struct LambertianParams(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } // aniso Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL() * _sample.getTdotL(); } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl index 9792f03ed0..23d7ddb3da 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl @@ -41,7 +41,7 @@ struct OrenNayarParams(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return hlsl::dot(interaction.getV().getDirection(), _sample.getL().getDirection()); } LS _sample; SI interaction; @@ -69,7 +69,7 @@ struct OrenNayarParams(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return hlsl::dot(interaction.getV().getDirection(), _sample.getL().getDirection()); } // aniso Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL() * _sample.getTdotL(); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 3fedcbcc09..46e06d6880 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -43,7 +43,7 @@ struct BeckmannParams(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return cache.getVdotL(); } Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } Scalar getNdotH2() NBL_CONST_MEMBER_FUNC { return cache.getNdotH2(); } Scalar getVdotH() NBL_CONST_MEMBER_FUNC { return cache.getVdotH(); } @@ -77,7 +77,7 @@ struct BeckmannParams(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return cache.getVdotL(); } Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } Scalar getNdotH2() NBL_CONST_MEMBER_FUNC { return cache.getNdotH2(); } Scalar getVdotH() NBL_CONST_MEMBER_FUNC { return cache.getVdotH(); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index e84574cd91..adf7f0f5dc 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -43,7 +43,7 @@ struct GGXParams(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return cache.getVdotL(); } Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } Scalar getNdotH2() NBL_CONST_MEMBER_FUNC { return cache.getNdotH2(); } Scalar getVdotH() NBL_CONST_MEMBER_FUNC { return cache.getVdotH(); } @@ -77,7 +77,7 @@ struct GGXParams(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } + Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return cache.getVdotL(); } Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } Scalar getNdotH2() NBL_CONST_MEMBER_FUNC { return cache.getNdotH2(); } Scalar getVdotH() NBL_CONST_MEMBER_FUNC { return cache.getVdotH(); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl index bbafdc0c6f..32b7dd053c 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl @@ -42,7 +42,6 @@ struct LambertianParams(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } LS _sample; SI interaction; @@ -70,7 +69,6 @@ struct LambertianParams(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } // aniso Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL() * _sample.getTdotL(); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index 97dae51043..a346297c63 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -41,7 +41,6 @@ struct SmoothDielectricParams(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } LS _sample; SI interaction; @@ -69,7 +68,6 @@ struct SmoothDielectricParams(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return _sample.getVdotL(); } // aniso Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL() * _sample.getTdotL(); } @@ -134,7 +132,7 @@ struct SSmoothDielectricBxDF rr; rr.refract = r; L.direction = rr(transmitted, orientedEta.rcp[0]); - return sample_type::create(L, nbl::hlsl::dot(V, L.direction), T, B, N); + return sample_type::create(L, T, B, N); } sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector) u) @@ -251,7 +249,7 @@ struct SSmoothDielectricBxDF(V, L.direction), T, B, N); + return sample_type::create(L, T, B, N); } sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector) u) From a36b104e33a3d4d7fcdda2d586d6e11ee6f9234f Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 25 Jul 2025 12:03:31 +0700 Subject: [PATCH 144/188] moved square of dot products into bxdf concepts themselves --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 51 ++++++++++++++----- .../hlsl/bxdf/reflection/beckmann.hlsl | 28 +++++----- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 28 +++++----- .../hlsl/bxdf/reflection/lambertian.hlsl | 22 ++++---- .../hlsl/bxdf/reflection/oren_nayar.hlsl | 24 ++++----- .../hlsl/bxdf/transmission/beckmann.hlsl | 28 +++++----- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 28 +++++----- .../hlsl/bxdf/transmission/lambertian.hlsl | 24 ++++----- .../bxdf/transmission/smooth_dielectric.hlsl | 24 ++++----- 9 files changed, 140 insertions(+), 117 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 369d6dea8d..032db9f382 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -112,6 +112,12 @@ struct SBasic } +enum BxDFClampMode : uint16_t +{ + BCM_NONE = 0, + BCM_MAX, + BCM_ABS +}; namespace surface_interactions { @@ -122,21 +128,24 @@ namespace surface_interactions #define NBL_CONCEPT_PARAM_0 (iso, T) #define NBL_CONCEPT_PARAM_1 (normV, typename T::ray_dir_info_type) #define NBL_CONCEPT_PARAM_2 (normN, typename T::vector3_type) -NBL_CONCEPT_BEGIN(3) +#define NBL_CONCEPT_PARAM_3 (clampMode, BxDFClampMode) +NBL_CONCEPT_BEGIN(4) #define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define normV NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define normN NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +#define clampMode NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::ray_dir_info_type)) ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.getV()), ::nbl::hlsl::is_same_v, typename T::ray_dir_info_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.getN()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.getNdotV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.getNdotV(clampMode)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.getNdotV2()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(normV,normN)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(ray_dir_info::Basic, typename T::ray_dir_info_type)) ); +#undef clampMode #undef normN #undef normV #undef iso @@ -163,7 +172,10 @@ struct SIsotropic RayDirInfo getV() NBL_CONST_MEMBER_FUNC { return V; } vector3_type getN() NBL_CONST_MEMBER_FUNC { return N; } - scalar_type getNdotV() NBL_CONST_MEMBER_FUNC { return NdotV; } + scalar_type getNdotV(BxDFClampMode _clamp = BxDFClampMode::BCM_NONE) NBL_CONST_MEMBER_FUNC + { + return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, NdotV, 0.0), NdotV, _clamp == BxDFClampMode::BCM_NONE); + } scalar_type getNdotV2() NBL_CONST_MEMBER_FUNC { return NdotV2; } RayDirInfo V; @@ -191,7 +203,9 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getT()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getB()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getTdotV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getTdotV2()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getBdotV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getBdotV2()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(iso,normT,normT)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getTangentSpaceV()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((aniso.getToTangentSpace()), ::nbl::hlsl::is_same_v, typename T::matrix3x3_type)) @@ -251,13 +265,15 @@ struct SAnisotropic ray_dir_info_type getV() NBL_CONST_MEMBER_FUNC { return isotropic.getV(); } vector3_type getN() NBL_CONST_MEMBER_FUNC { return isotropic.getN(); } - scalar_type getNdotV() NBL_CONST_MEMBER_FUNC { return isotropic.getNdotV(); } + scalar_type getNdotV(BxDFClampMode _clamp = BxDFClampMode::BCM_NONE) NBL_CONST_MEMBER_FUNC { return isotropic.getNdotV(_clamp); } scalar_type getNdotV2() NBL_CONST_MEMBER_FUNC { return isotropic.getNdotV2(); } vector3_type getT() NBL_CONST_MEMBER_FUNC { return T; } vector3_type getB() NBL_CONST_MEMBER_FUNC { return B; } scalar_type getTdotV() NBL_CONST_MEMBER_FUNC { return TdotV; } + scalar_type getTdotV2() NBL_CONST_MEMBER_FUNC { const scalar_type t = getTdotV(); return t*t; } scalar_type getBdotV() NBL_CONST_MEMBER_FUNC { return BdotV; } + scalar_type getBdotV2() NBL_CONST_MEMBER_FUNC { const scalar_type t = getBdotV(); return t*t; } vector3_type getTangentSpaceV() NBL_CONST_MEMBER_FUNC { return vector3_type(TdotV, BdotV, isotropic.getNdotV()); } matrix3x3_type getToTangentSpace() NBL_CONST_MEMBER_FUNC { return matrix3x3_type(T, B, isotropic.getN()); } @@ -281,12 +297,14 @@ struct SAnisotropic #define NBL_CONCEPT_PARAM_2 (rdirinfo, typename T::ray_dir_info_type) #define NBL_CONCEPT_PARAM_3 (pV, typename T::vector3_type) #define NBL_CONCEPT_PARAM_4 (frame, typename T::matrix3x3_type) -NBL_CONCEPT_BEGIN(5) +#define NBL_CONCEPT_PARAM_5 (clampMode, BxDFClampMode) +NBL_CONCEPT_BEGIN(6) #define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define inter NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define rdirinfo NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 #define pV NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 #define frame NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 +#define clampMode NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::ray_dir_info_type)) ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) @@ -294,8 +312,10 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::matrix3x3_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getL()), ::nbl::hlsl::is_same_v, typename T::ray_dir_info_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getTdotL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getTdotL2()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getBdotL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getNdotL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getBdotL2()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getNdotL(clampMode)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getNdotL2()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createFromTangentSpace(pV,rdirinfo,frame)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(rdirinfo,pV)), ::nbl::hlsl::is_same_v, T)) @@ -304,6 +324,7 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getTangentSpaceL()), ::nbl::hlsl::is_same_v, typename T::vector3_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(ray_dir_info::Basic, typename T::ray_dir_info_type)) ); +#undef clampMode #undef frame #undef pV #undef rdirinfo @@ -380,8 +401,13 @@ struct SLightSample ray_dir_info_type getL() NBL_CONST_MEMBER_FUNC { return L; } scalar_type getTdotL() NBL_CONST_MEMBER_FUNC { return TdotL; } + scalar_type getTdotL2() NBL_CONST_MEMBER_FUNC { const scalar_type t = getTdotL(); return t*t; } scalar_type getBdotL() NBL_CONST_MEMBER_FUNC { return BdotL; } - scalar_type getNdotL() NBL_CONST_MEMBER_FUNC { return NdotL; } + scalar_type getBdotL2() NBL_CONST_MEMBER_FUNC { const scalar_type t = getBdotL(); return t*t; } + scalar_type getNdotL(BxDFClampMode _clamp = BxDFClampMode::BCM_NONE) NBL_CONST_MEMBER_FUNC + { + return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, NdotL, 0.0), NdotL, _clamp == BxDFClampMode::BCM_NONE); + } scalar_type getNdotL2() NBL_CONST_MEMBER_FUNC { return NdotL2; } @@ -599,7 +625,9 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) ((NBL_CONCEPT_REQ_TYPE)(T::isocache_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getTdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getTdotH2()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getBdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getBdotH2()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(V,V)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V,b0,rcp_eta)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(V,V,pNdotL)), ::nbl::hlsl::is_same_v, T)) @@ -720,7 +748,9 @@ struct SAnisotropicMicrofacetCache scalar_type getNdotH2() NBL_CONST_MEMBER_FUNC { return iso_cache.getNdotH2(); } scalar_type getTdotH() NBL_CONST_MEMBER_FUNC { return TdotH; } + scalar_type getTdotH2() NBL_CONST_MEMBER_FUNC { const scalar_type t = getTdotH(); return t*t; } scalar_type getBdotH() NBL_CONST_MEMBER_FUNC { return BdotH; } + scalar_type getBdotH2() NBL_CONST_MEMBER_FUNC { const scalar_type t = getBdotH(); return t*t; } isocache_type iso_cache; scalar_type TdotH; @@ -843,13 +873,6 @@ NBL_CONCEPT_END( #undef bxdf #include -enum BxDFClampMode : uint16_t -{ - BCM_NONE = 0, - BCM_MAX, - BCM_ABS -}; - template using quotient_and_pdf_scalar = sampling::quotient_and_pdf, P> ; template diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 26204ac3a1..280c76c405 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -37,11 +37,11 @@ struct BeckmannParams(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return cache.getVdotL(); } Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } @@ -71,11 +71,11 @@ struct BeckmannParams(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return cache.getVdotL(); } Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } @@ -84,12 +84,12 @@ struct BeckmannParams(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return cache.getVdotL(); } Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } @@ -71,11 +71,11 @@ struct GGXParams(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return cache.getVdotL(); } Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } @@ -84,12 +84,12 @@ struct GGXParams(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } LS _sample; @@ -62,18 +62,18 @@ struct LambertianParams(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } // aniso - Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL() * _sample.getTdotL(); } - Scalar getBdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getBdotL() * _sample.getBdotL(); } - Scalar getTdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getTdotV() * interaction.getTdotV(); } - Scalar getBdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getBdotV() * interaction.getBdotV(); } + Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL2(); } + Scalar getBdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getBdotL2(); } + Scalar getTdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getTdotV2(); } + Scalar getBdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getBdotV2(); } LS _sample; SI interaction; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl index 23d7ddb3da..665d018f10 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl @@ -35,11 +35,11 @@ struct OrenNayarParams(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return hlsl::dot(interaction.getV().getDirection(), _sample.getL().getDirection()); } @@ -63,19 +63,19 @@ struct OrenNayarParams(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return hlsl::dot(interaction.getV().getDirection(), _sample.getL().getDirection()); } // aniso - Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL() * _sample.getTdotL(); } - Scalar getBdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getBdotL() * _sample.getBdotL(); } - Scalar getTdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getTdotV() * interaction.getTdotV(); } - Scalar getBdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getBdotV() * interaction.getBdotV(); } + Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL2(); } + Scalar getBdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getBdotL2(); } + Scalar getTdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getTdotV2(); } + Scalar getBdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getBdotV2(); } LS _sample; SI interaction; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 46e06d6880..8358b22d29 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -37,11 +37,11 @@ struct BeckmannParams(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return cache.getVdotL(); } Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } @@ -71,11 +71,11 @@ struct BeckmannParams(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return cache.getVdotL(); } Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } @@ -84,12 +84,12 @@ struct BeckmannParams(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return cache.getVdotL(); } Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } @@ -71,11 +71,11 @@ struct GGXParams(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return cache.getVdotL(); } Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } @@ -84,12 +84,12 @@ struct GGXParams(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } LS _sample; @@ -63,18 +63,18 @@ struct LambertianParams(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } // aniso - Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL() * _sample.getTdotL(); } - Scalar getBdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getBdotL() * _sample.getBdotL(); } - Scalar getTdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getTdotV() * interaction.getTdotV(); } - Scalar getBdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getBdotV() * interaction.getBdotV(); } + Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL2(); } + Scalar getBdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getBdotL2(); } + Scalar getTdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getTdotV2(); } + Scalar getBdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getBdotV2(); } LS _sample; SI interaction; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index a346297c63..a5490b6d4a 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -35,11 +35,11 @@ struct SmoothDielectricParams(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } LS _sample; @@ -62,18 +62,18 @@ struct SmoothDielectricParams(_clamp == BxDFClampMode::BCM_ABS, interaction.getNdotV(), 0.0), interaction.getNdotV(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } + Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } + Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, _sample.getNdotL(), 0.0), _sample.getNdotL(), _clamp == BxDFClampMode::BCM_NONE); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(); } + Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } + Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } // aniso - Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL() * _sample.getTdotL(); } - Scalar getBdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getBdotL() * _sample.getBdotL(); } - Scalar getTdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getTdotV() * interaction.getTdotV(); } - Scalar getBdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getBdotV() * interaction.getBdotV(); } + Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL2(); } + Scalar getBdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getBdotL2(); } + Scalar getTdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getTdotV2(); } + Scalar getBdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getBdotV2(); } LS _sample; SI interaction; From e63daa40d65c6b8379d6a9d1e76c3ad550eb222d Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 25 Jul 2025 15:54:40 +0700 Subject: [PATCH 145/188] beckmann ndf funcs take sample, cache and query structs, concepts for queries --- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 124 +++++++++++++----- .../hlsl/bxdf/reflection/beckmann.hlsl | 69 ++++++++-- .../hlsl/bxdf/transmission/beckmann.hlsl | 82 +++++++++--- 3 files changed, 213 insertions(+), 62 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index 2d614b4b7e..b7ba280c05 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -16,9 +16,57 @@ namespace bxdf namespace ndf { -// forward declare -// template -// struct microfacet_to_light_measure_transform; +namespace beckmann_concepts +{ +#define NBL_CONCEPT_NAME DG1BrdfQuery +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (query, T) +NBL_CONCEPT_BEGIN(1) +#define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getNdf()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getMaxNdotV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getOnePlusLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) +); +#undef query +#include + +#define NBL_CONCEPT_NAME DG1BsdfQuery +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (query, T) +NBL_CONCEPT_BEGIN(1) +#define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getNdf()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getAbsNdotV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getTransmitted()), ::nbl::hlsl::is_same_v, bool)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getVdotHLdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getOrientedEta()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getOnePlusLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) +); +#undef query +#include + +#define NBL_CONCEPT_NAME G2overG1Query +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (query, T) +NBL_CONCEPT_BEGIN(1) +#define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getTransmitted()), ::nbl::hlsl::is_same_v, bool)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getOnePlusLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) +); +#undef query +#include +} template struct Beckmann; @@ -30,25 +78,28 @@ struct Beckmann) > { using scalar_type = T; - scalar_type D(scalar_type NdotH2) + template) + scalar_type D(NBL_CONST_REF_ARG(MicrofacetCache) cache) { - scalar_type nom = exp2((NdotH2 - scalar_type(1.0)) / (log(2.0) * a2 * NdotH2)); - scalar_type denom = a2 * NdotH2 * NdotH2; + scalar_type nom = exp2((cache.getNdotH2() - scalar_type(1.0)) / (log(2.0) * a2 * cache.getNdotH2())); + scalar_type denom = a2 * cache.getNdotH2() * cache.getNdotH2(); return numbers::inv_pi * nom / denom; } // brdf - scalar_type DG1(scalar_type ndf, scalar_type maxNdotV, scalar_type lambda_V, NBL_REF_ARG(scalar_type) onePlusLambda_V) + template) + scalar_type DG1(NBL_REF_ARG(Query) query) { - onePlusLambda_V = scalar_type(1.0) + lambda_V; - return ndf::microfacet_to_light_measure_transform::__call(ndf / onePlusLambda_V, maxNdotV); + query.onePlusLambda_V = scalar_type(1.0) + query.getLambdaV(); + return ndf::microfacet_to_light_measure_transform::__call(query.getNdf() / query.getOnePlusLambdaV(), query.getMaxNdotV()); } // bsdf - scalar_type DG1(scalar_type ndf, scalar_type absNdotV, scalar_type lambda_V, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, NBL_REF_ARG(scalar_type) onePlusLambda_V) + template && ReadableIsotropicMicrofacetCache) + scalar_type DG1(NBL_REF_ARG(Query) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) { - onePlusLambda_V = scalar_type(1.0) + lambda_V; - return ndf::microfacet_to_light_measure_transform::__call(ndf / onePlusLambda_V, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); + query.onePlusLambda_V = scalar_type(1.0) + query.getLambdaV(); + return ndf::microfacet_to_light_measure_transform::__call(query.getNdf() / query.getOnePlusLambdaV(), query.getAbsNdotV(), query.getTransmitted(), cache.getVdotH(), cache.getLdotH(), query.getVdotHLdotH(), query.getOrientedEta()); } scalar_type G1(scalar_type lambda) @@ -74,17 +125,19 @@ struct Beckmann) > return Lambda(C2(NdotX2)); } - scalar_type correlated(scalar_type NdotV2, scalar_type NdotL2) + template && surface_interactions::Isotropic) + scalar_type correlated(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - scalar_type L_v = LambdaC2(NdotV2); - scalar_type L_l = LambdaC2(NdotL2); - return scalar_type(1.0) / (scalar_type(1.0) + L_v + L_l); + scalar_type lambda_V = LambdaC2(interaction.getNdotV2()); + scalar_type lambda_L = LambdaC2(_sample.getNdotL2()); + return scalar_type(1.0) / (scalar_type(1.0) + lambda_V + lambda_L); } - scalar_type G2_over_G1(bool transmitted, scalar_type NdotL2, scalar_type lambdaV_plus_one) + template && LightSample) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample) { - scalar_type lambdaL = LambdaC2(NdotL2); - return lambdaV_plus_one * hlsl::mix(scalar_type(1.0)/(lambdaV_plus_one + lambdaL), hlsl::beta(lambdaV_plus_one, scalar_type(1.0) + lambdaL), transmitted); + scalar_type lambda_L = LambdaC2(_sample.getNdotL2()); + return query.getOnePlusLambdaV() * hlsl::mix(scalar_type(1.0)/(query.getOnePlusLambdaV() + lambda_L), hlsl::beta(query.getOnePlusLambdaV(), scalar_type(1.0) + lambda_L), query.getTransmitted()); } scalar_type a2; @@ -97,26 +150,29 @@ struct Beckmann) > { using scalar_type = T; - scalar_type D(scalar_type TdotH2, scalar_type BdotH2, scalar_type NdotH2) + template) + scalar_type D(NBL_CONST_REF_ARG(MicrofacetCache) cache) { const scalar_type ax2 = ax*ax; const scalar_type ay2 = ay*ay; - scalar_type nom = exp(-(TdotH2 / ax2 + BdotH2 / ay2) / NdotH2); - scalar_type denom = ax * ay * NdotH2 * NdotH2; + scalar_type nom = exp(-(cache.getTdotH2() / ax2 + cache.getBdotH2() / ay2) / cache.getNdotH2()); + scalar_type denom = ax * ay * cache.getNdotH2() * cache.getNdotH2(); return numbers::inv_pi * nom / denom; } - scalar_type DG1(scalar_type ndf, scalar_type maxNdotV, scalar_type lambda_V, NBL_REF_ARG(scalar_type) onePlusLambda_V) + template) + scalar_type DG1(NBL_REF_ARG(Query) query) { Beckmann beckmann; - scalar_type dg = beckmann.DG1(ndf, maxNdotV, lambda_V, onePlusLambda_V); + scalar_type dg = beckmann.template DG1(query); return dg; } - scalar_type DG1(scalar_type ndf, scalar_type absNdotV, scalar_type lambda_V, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, NBL_REF_ARG(scalar_type) onePlusLambda_V) + template && AnisotropicMicrofacetCache) + scalar_type DG1(NBL_REF_ARG(Query) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) { Beckmann beckmann; - scalar_type dg = beckmann.DG1(ndf, absNdotV, lambda_V, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta, onePlusLambda_V); + scalar_type dg = beckmann.template DG1(query, cache.iso_cache); return dg; } @@ -145,17 +201,19 @@ struct Beckmann) > return Lambda(C2(TdotX2, BdotX2, NdotX2)); } - scalar_type correlated(scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2) + template && surface_interactions::Anisotropic) + scalar_type correlated(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - scalar_type L_v = LambdaC2(TdotV2, BdotV2, NdotV2); - scalar_type L_l = LambdaC2(TdotL2, BdotL2, NdotL2); - return scalar_type(1.0) / (scalar_type(1.0) + L_v + L_l); + scalar_type lambda_V = LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + scalar_type lambda_L = LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); + return scalar_type(1.0) / (scalar_type(1.0) + lambda_V + lambda_L); } - scalar_type G2_over_G1(bool transmitted, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2, scalar_type lambdaV_plus_one) + template && LightSample) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample) { - scalar_type lambdaL = LambdaC2(TdotL2, BdotL2, NdotL2); - return lambdaV_plus_one * hlsl::mix(scalar_type(1.0)/(lambdaV_plus_one + lambdaL), hlsl::beta(lambdaV_plus_one, scalar_type(1.0) + lambdaL), transmitted); + scalar_type lambda_L = LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); + return query.getOnePlusLambdaV() * hlsl::mix(scalar_type(1.0)/(query.getOnePlusLambdaV() + lambda_L), hlsl::beta(query.getOnePlusLambdaV(), scalar_type(1.0) + lambda_L), query.getTransmitted()); } scalar_type ax; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 280c76c405..42a1bbf53d 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -97,6 +97,34 @@ struct BeckmannParams +struct SBeckmannDG1Query +{ + using scalar_type = T; + + scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } + scalar_type getMaxNdotV() NBL_CONST_MEMBER_FUNC { return maxNdotV; } + scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } + scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } + + scalar_type ndf; + scalar_type maxNdotV; + scalar_type lambda_V; + scalar_type onePlusLambda_V; +}; + +template +struct SBeckmannG2overG1Query +{ + using scalar_type = T; + + bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } + scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } + + bool transmitted; + scalar_type onePlusLambda_V; +}; + template && surface_interactions::Isotropic && surface_interactions::Anisotropic && CreatableIsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SBeckmannBxDF { @@ -143,10 +171,10 @@ struct SBeckmannBxDF scalar_type a2 = A.x*A.x; ndf::Beckmann beckmann_ndf; beckmann_ndf.a2 = a2; - scalar_type NG = beckmann_ndf.D(params.getNdotH2()); + scalar_type NG = beckmann_ndf.template D(params.cache); if (a2 > numeric_limits::min) { - NG *= beckmann_ndf.correlated(params.getNdotV2(), params.getNdotL2()); + NG *= beckmann_ndf.template correlated(params._sample, params.interaction); } return NG; } @@ -155,10 +183,10 @@ struct SBeckmannBxDF ndf::Beckmann beckmann_ndf; beckmann_ndf.ax = A.x; beckmann_ndf.ay = A.y; - scalar_type NG = beckmann_ndf.D(params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); + scalar_type NG = beckmann_ndf.template D(params.cache); if (hlsl::any >(A > (vector2_type)numeric_limits::min)) { - NG *= beckmann_ndf.correlated(params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); + NG *= beckmann_ndf.template correlated(params._sample, params.interaction); } return NG; } @@ -279,27 +307,36 @@ struct SBeckmannBxDF scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { - scalar_type ndf, lambda; + SBeckmannDG1Query dg1_query; + dg1_query.maxNdotV = params.getNdotV(); + scalar_type a2 = A.x*A.x; ndf::Beckmann beckmann_ndf; beckmann_ndf.a2 = a2; - ndf = beckmann_ndf.D(params.getNdotH2()); + dg1_query.ndf = beckmann_ndf.template D(params.cache); - lambda = beckmann_ndf.LambdaC2(params.getNdotV2()); + dg1_query.lambda_V = beckmann_ndf.LambdaC2(params.getNdotV2()); - return beckmann_ndf.DG1(ndf, params.getNdotVUnclamped(), lambda, onePlusLambda_V); + scalar_type dg1 = beckmann_ndf.template DG1 >(dg1_query); + onePlusLambda_V = dg1_query.getOnePlusLambdaV(); + return dg1; } scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { + SBeckmannDG1Query dg1_query; + dg1_query.maxNdotV = params.getNdotV(); + scalar_type ndf, lambda; ndf::Beckmann beckmann_ndf; beckmann_ndf.ax = A.x; beckmann_ndf.ay = A.y; - ndf = beckmann_ndf.D(params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); + dg1_query.ndf = beckmann_ndf.template D(params.cache); - lambda = beckmann_ndf.LambdaC2(params.getTdotV2(), params.getBdotV2(), params.getNdotV2()); + dg1_query.lambda_V = beckmann_ndf.LambdaC2(params.getTdotV2(), params.getBdotV2(), params.getNdotV2()); - return beckmann_ndf.DG1(ndf, params.getNdotVUnclamped(), lambda, onePlusLambda_V); + scalar_type dg1 = beckmann_ndf.template DG1 >(dg1_query); + onePlusLambda_V = dg1_query.getOnePlusLambdaV(); + return dg1; } scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) @@ -323,7 +360,10 @@ struct SBeckmannBxDF if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) { beckmann_ndf.a2 = A.x*A.x; - scalar_type G2_over_G1 = beckmann_ndf.G2_over_G1(false, params.getNdotL2(), onePlusLambda_V); + SBeckmannG2overG1Query query; + query.transmitted = false; + query.onePlusLambda_V = onePlusLambda_V; + scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1, sample_type>(query, params._sample); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; @@ -342,7 +382,10 @@ struct SBeckmannBxDF { beckmann_ndf.ax = A.x; beckmann_ndf.ay = A.y; - scalar_type G2_over_G1 = beckmann_ndf.G2_over_G1(false, params.getTdotL2(), params.getBdotL2(), params.getNdotL2(), onePlusLambda_V); + SBeckmannG2overG1Query query; + query.transmitted = false; + query.onePlusLambda_V = onePlusLambda_V; + scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1, sample_type>(query, params._sample); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 8358b22d29..ce9249bfca 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -97,6 +97,40 @@ struct BeckmannParams +struct SBeckmannDG1Query +{ + using scalar_type = T; + + scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } + scalar_type getAbsNdotV() NBL_CONST_MEMBER_FUNC { return absNdotV; } + scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } + bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } + scalar_type getVdotHLdotH() NBL_CONST_MEMBER_FUNC { return VdotHLdotH; } + scalar_type getOrientedEta() NBL_CONST_MEMBER_FUNC { return orientedEta; } + scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } + + scalar_type ndf; + scalar_type absNdotV; + scalar_type lambda_V; + bool transmitted; + scalar_type VdotHLdotH; + scalar_type orientedEta; + scalar_type onePlusLambda_V; +}; + +template +struct SBeckmannG2overG1Query +{ + using scalar_type = T; + + bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } + scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } + + bool transmitted; + scalar_type onePlusLambda_V; +}; + template && surface_interactions::Isotropic && surface_interactions::Anisotropic && CreatableIsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SBeckmannDielectricBxDF { @@ -225,43 +259,57 @@ struct SBeckmannDielectricBxDF scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { + SBeckmannDG1Query dg1_query; + dg1_query.absNdotV = params.getNdotV(); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; + dg1_query.orientedEta = orientedEta.value[0]; const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); - const bool transmitted = VdotHLdotH < 0.0; + dg1_query.transmitted = VdotHLdotH < 0.0; + dg1_query.VdotHLdotH = VdotHLdotH; const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; - scalar_type ndf, lambda; const scalar_type a2 = A.x*A.x; ndf::Beckmann beckmann_ndf; beckmann_ndf.a2 = a2; - ndf = beckmann_ndf.D(params.getNdotH2()); + dg1_query.ndf = beckmann_ndf.template D(params.cache); + + dg1_query.lambda_V = beckmann_ndf.LambdaC2(params.getNdotV2()); - lambda = beckmann_ndf.LambdaC2(params.getNdotV2()); + scalar_type dg1 = beckmann_ndf.template DG1, isocache_type>(dg1_query, params.cache); + onePlusLambda_V = dg1_query.getOnePlusLambdaV(); - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, transmitted) * beckmann_ndf.DG1(ndf,params.getNdotV(),lambda,transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0],onePlusLambda_V); + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, dg1_query.getTransmitted()) * dg1; } scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { + SBeckmannDG1Query dg1_query; + dg1_query.absNdotV = params.getNdotV(); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; + dg1_query.orientedEta = orientedEta.value[0]; const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); - const bool transmitted = VdotHLdotH < 0.0; + dg1_query.transmitted = VdotHLdotH < 0.0; + dg1_query.VdotHLdotH = VdotHLdotH; const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; - scalar_type ndf, lambda; ndf::Beckmann beckmann_ndf; beckmann_ndf.ax = A.x; beckmann_ndf.ay = A.y; - ndf = beckmann_ndf.D(params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); + dg1_query.ndf = beckmann_ndf.template D(params.cache); + + dg1_query.lambda_V = beckmann_ndf.LambdaC2(params.getTdotV2(), params.getBdotV2(), params.getNdotV2()); - lambda = beckmann_ndf.LambdaC2(params.getTdotV2(), params.getBdotV2(), params.getNdotV2()); + scalar_type dg1 = beckmann_ndf.template DG1, anisocache_type>(dg1_query, params.cache); + onePlusLambda_V = dg1_query.getOnePlusLambdaV(); - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, transmitted) * beckmann_ndf.DG1(ndf,params.getNdotV(),lambda,transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0],onePlusLambda_V); + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, dg1_query.getTransmitted()) * dg1; } scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) @@ -279,12 +327,13 @@ struct SBeckmannDielectricBxDF { scalar_type onePlusLambda_V; scalar_type _pdf = pdf(params, onePlusLambda_V); - const bool transmitted = params.getVdotH() * params.getLdotH() < 0.0; - scalar_type quo; ndf::Beckmann beckmann_ndf; beckmann_ndf.a2 = A.x*A.x; - quo = beckmann_ndf.G2_over_G1(transmitted, params.getNdotL2(), onePlusLambda_V); + SBeckmannG2overG1Query query; + query.transmitted = params.getVdotH() * params.getLdotH() < 0.0; + query.onePlusLambda_V = onePlusLambda_V; + scalar_type quo = beckmann_ndf.template G2_over_G1, sample_type>(query, params._sample); return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } @@ -292,13 +341,14 @@ struct SBeckmannDielectricBxDF { scalar_type onePlusLambda_V; scalar_type _pdf = pdf(params, onePlusLambda_V); - const bool transmitted = params.getVdotH() * params.getLdotH() < 0.0; - scalar_type quo; ndf::Beckmann beckmann_ndf; beckmann_ndf.ax = A.x; beckmann_ndf.ay = A.y; - quo = beckmann_ndf.G2_over_G1(transmitted, params.getTdotL2(), params.getBdotL2(), params.getNdotL2(), onePlusLambda_V); + SBeckmannG2overG1Query query; + query.transmitted = params.getVdotH() * params.getLdotH() < 0.0; + query.onePlusLambda_V = onePlusLambda_V; + scalar_type quo = beckmann_ndf.template G2_over_G1, sample_type>(query, params._sample); return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } From c4c390ef86f219389bfcc1e09e714063fa6b4dbc Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 28 Jul 2025 13:53:03 +0700 Subject: [PATCH 146/188] ggx ndf funcs using query structs, new query concepts --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 7 + include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 150 ++++++++++-------- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 65 +++++--- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 64 +++++--- 4 files changed, 175 insertions(+), 111 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 032db9f382..4925873ad9 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -432,8 +432,10 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getVdotL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getVdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getLdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getVdotHLdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getNdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getNdotH2()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.isTransmission()), ::nbl::hlsl::is_same_v, bool)) ); #undef cache #include @@ -587,8 +589,11 @@ struct SIsotropicMicrofacetCache return VdotH; } + bool isTransmission() NBL_CONST_MEMBER_FUNC { return getVdotHLdotH() < scalar_type(0.0); } + scalar_type getVdotL() NBL_CONST_MEMBER_FUNC { return VdotL; } scalar_type getLdotH() NBL_CONST_MEMBER_FUNC { return LdotH; } + scalar_type getVdotHLdotH() NBL_CONST_MEMBER_FUNC { return getVdotH() * getLdotH(); } scalar_type getNdotH() NBL_CONST_MEMBER_FUNC { return NdotH; } scalar_type getNdotH2() NBL_CONST_MEMBER_FUNC { return NdotH2; } @@ -744,8 +749,10 @@ struct SAnisotropicMicrofacetCache scalar_type getVdotL() NBL_CONST_MEMBER_FUNC { return iso_cache.getVdotL(); } scalar_type getVdotH() NBL_CONST_MEMBER_FUNC { return iso_cache.getVdotH(); } scalar_type getLdotH() NBL_CONST_MEMBER_FUNC { return iso_cache.getLdotH(); } + scalar_type getVdotHLdotH() NBL_CONST_MEMBER_FUNC { return iso_cache.getVdotHLdotH(); } scalar_type getNdotH() NBL_CONST_MEMBER_FUNC { return iso_cache.getNdotH(); } scalar_type getNdotH2() NBL_CONST_MEMBER_FUNC { return iso_cache.getNdotH2(); } + bool isTransmission() NBL_CONST_MEMBER_FUNC { return iso_cache.isTransmission(); } scalar_type getTdotH() NBL_CONST_MEMBER_FUNC { return TdotH; } scalar_type getTdotH2() NBL_CONST_MEMBER_FUNC { const scalar_type t = getTdotH(); return t*t; } diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index 387b254851..610fcbbf9e 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -16,6 +16,39 @@ namespace bxdf namespace ndf { +namespace ggx_concepts +{ +#define NBL_CONCEPT_NAME DG1BrdfQuery +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (query, T) +NBL_CONCEPT_BEGIN(1) +#define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getNdf()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getG1over2NdotV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) +); +#undef query +#include + +#define NBL_CONCEPT_NAME DG1BsdfQuery +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (query, T) +NBL_CONCEPT_BEGIN(1) +#define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getNdf()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getG1over2NdotV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getTransmitted()), ::nbl::hlsl::is_same_v, bool)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getOrientedEta()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) +); +#undef query +#include +} + template struct GGX; @@ -28,27 +61,29 @@ struct GGX) > using this_t = GGX; // trowbridge-reitz - scalar_type D(scalar_type NdotH2) + template) + scalar_type D(NBL_CONST_REF_ARG(MicrofacetCache) cache) { - scalar_type denom = scalar_type(1.0) - one_minus_a2 * NdotH2; + scalar_type denom = scalar_type(1.0) - one_minus_a2 * cache.getNdotH2(); return a2 * numbers::inv_pi / (denom * denom); } - scalar_type DG1(scalar_type ndf, scalar_type G1_over_2NdotV) + template) + scalar_type DG1(NBL_REF_ARG(Query) query) { - scalar_type dummy = scalar_type(0.0); - return DG1(ndf, G1_over_2NdotV, false, dummy, dummy, dummy, dummy); + return scalar_type(0.5) * query.getNdf() * query.getG1over2NdotV(); } - scalar_type DG1(scalar_type ndf, scalar_type G1_over_2NdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) + template && ReadableIsotropicMicrofacetCache) + scalar_type DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) { - scalar_type NG = ndf * G1_over_2NdotV; + scalar_type NG = query.getNdf() * query.getG1over2NdotV(); scalar_type factor = scalar_type(0.5); - if (transmitted) + if (query.getTransmitted()) { - const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); + const scalar_type VdotH_etaLdotH = (cache.getVdotH() + query.getOrientedEta() * cache.getLdotH()); // VdotHLdotH is negative under transmission, so this factor is negative - factor *= -scalar_type(2.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); + factor *= -scalar_type(2.0) * cache.getVdotHLdotH() / (VdotH_etaLdotH * VdotH_etaLdotH); } return NG * factor; } @@ -59,54 +94,50 @@ struct GGX) > return sqrt(a2 + one_minus_a2 * NdotX2); } - scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type NdotX2) + scalar_type G1_wo_numerator(scalar_type absNdotX, scalar_type NdotX2) { - return scalar_type(1.0) / (NdotX + devsh_part(NdotX2)); + return scalar_type(1.0) / (absNdotX + devsh_part(NdotX2)); } - scalar_type G1_wo_numerator_devsh_part(scalar_type NdotX, scalar_type devsh_part) + scalar_type G1_wo_numerator_devsh_part(scalar_type absNdotX, scalar_type devsh_part) { - return scalar_type(1.0) / (NdotX + devsh_part); + // numerator is 2 * NdotX + return scalar_type(1.0) / (absNdotX + devsh_part); } - scalar_type correlated_wo_numerator(scalar_type absNdotV, scalar_type NdotV2, scalar_type absNdotL, scalar_type NdotL2) + template && surface_interactions::Isotropic) + scalar_type correlated_wo_numerator(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, BxDFClampMode _clamp) { - scalar_type Vterm = absNdotL * devsh_part(NdotV2); - scalar_type Lterm = absNdotV * devsh_part(NdotL2); + // numerator is 2 * NdotV * NdotL, we factor out 4 * NdotV * NdotL, hence 0.5 + scalar_type Vterm = _sample.getNdotL(_clamp) * devsh_part(interaction.getNdotV2()); + scalar_type Lterm = interaction.getNdotV(_clamp) * devsh_part(_sample.getNdotL2()); return scalar_type(0.5) / (Vterm + Lterm); } - scalar_type G2_over_G1(bool transmitted, scalar_type NdotV, scalar_type NdotV2, scalar_type NdotL, scalar_type NdotL2) + template && surface_interactions::Isotropic) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, bool transmitted, BxDFClampMode _clamp) { scalar_type G2_over_G1; + scalar_type NdotV = interaction.getNdotV(_clamp); + scalar_type NdotL = _sample.getNdotL(_clamp); if (transmitted) { if (NdotV < 1e-7 || NdotL < 1e-7) return 0.0; - scalar_type onePlusLambda_V = scalar_type(0.5) * (devsh_part(NdotV2) / NdotV + scalar_type(1.0)); - scalar_type onePlusLambda_L = scalar_type(0.5) * (devsh_part(NdotL2) / NdotL + scalar_type(1.0)); + scalar_type onePlusLambda_V = scalar_type(0.5) * (devsh_part(interaction.getNdotV2()) / NdotV + scalar_type(1.0)); + scalar_type onePlusLambda_L = scalar_type(0.5) * (devsh_part(_sample.getNdotL2()) / NdotL + scalar_type(1.0)); G2_over_G1 = hlsl::beta(onePlusLambda_L, onePlusLambda_V) * onePlusLambda_V; } else { - scalar_type devsh_v = devsh_part(NdotV2); + scalar_type devsh_v = devsh_part(interaction.getNdotV2()); G2_over_G1 = NdotL * (devsh_v + NdotV); // alternative `Vterm+NdotL*NdotV /// NdotL*NdotV could come as a parameter - G2_over_G1 /= NdotV * devsh_part(NdotL2) + NdotL * devsh_v; + G2_over_G1 /= NdotV * devsh_part(_sample.getNdotL2()) + NdotL * devsh_v; } return G2_over_G1; } - // reflect only - scalar_type G2_over_G1(scalar_type NdotV, scalar_type NdotV2, scalar_type NdotL, scalar_type NdotL2) - { - scalar_type devsh_v = devsh_part(NdotV2); - scalar_type G2_over_G1 = NdotL * (devsh_v + NdotV); // alternative `Vterm+NdotL*NdotV /// NdotL*NdotV could come as a parameter - G2_over_G1 /= NdotV * devsh_part(NdotL2) + NdotL * devsh_v; - - return G2_over_G1; - } - scalar_type a2; scalar_type one_minus_a2; }; @@ -117,12 +148,10 @@ struct GGX) > { using scalar_type = T; - scalar_type D(scalar_type TdotH2, scalar_type BdotH2, scalar_type NdotH2) + template) + scalar_type D(NBL_CONST_REF_ARG(MicrofacetCache) cache) { - const scalar_type ax2 = ax*ax; - const scalar_type ay2 = ay*ay; - const scalar_type a2 = ax * ay; - scalar_type denom = TdotH2 / ax2 + BdotH2 / ay2 + NdotH2; + scalar_type denom = cache.getTdotH2() / ax2 + cache.getBdotH2() / ay2 + cache.getNdotH2(); return numbers::inv_pi / (a2 * denom * denom); } @@ -137,22 +166,22 @@ struct GGX) > return w2 * w2 * atab * numbers::inv_pi; } - scalar_type DG1(scalar_type ndf, scalar_type G1_over_2NdotV) + template) + scalar_type DG1(NBL_REF_ARG(Query) query) { GGX ggx; - return ggx.DG1(ndf, G1_over_2NdotV); + return ggx.template DG1(query); } - scalar_type DG1(scalar_type ndf, scalar_type G1_over_2NdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) + template && AnisotropicMicrofacetCache) + scalar_type DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) { GGX ggx; - return ggx.DG1(ndf, G1_over_2NdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta); + return ggx.template DG1(query, cache.iso_cache); } scalar_type devsh_part(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2) { - const scalar_type ax2 = ax*ax; - const scalar_type ay2 = ay*ay; assert(ax2 >= numeric_limits::min && ay2 >= numeric_limits::min); return sqrt(TdotX2 * ax2 + BdotX2 * ay2 + NdotX2); } @@ -167,46 +196,41 @@ struct GGX) > return scalar_type(1.0) / (NdotX + devsh_part); } - scalar_type correlated_wo_numerator(scalar_type absNdotV, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type absNdotL, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2) + template && surface_interactions::Anisotropic) + scalar_type correlated_wo_numerator(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, BxDFClampMode _clamp) { - scalar_type Vterm = absNdotL * devsh_part(TdotV2, BdotV2, NdotV2); - scalar_type Lterm = absNdotV * devsh_part(TdotL2, BdotL2, NdotL2); + scalar_type Vterm = _sample.getNdotL(_clamp) * devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + scalar_type Lterm = interaction.getNdotV(_clamp) * devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); return scalar_type(0.5) / (Vterm + Lterm); } - scalar_type G2_over_G1(bool transmitted, scalar_type NdotV, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type NdotL, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2) + template && surface_interactions::Anisotropic) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, bool transmitted, BxDFClampMode _clamp) { scalar_type G2_over_G1; + scalar_type NdotV = interaction.getNdotV(_clamp); + scalar_type NdotL = _sample.getNdotL(_clamp); if (transmitted) { if (NdotV < 1e-7 || NdotL < 1e-7) return 0.0; - scalar_type onePlusLambda_V = scalar_type(0.5) * (devsh_part(TdotV2, BdotV2, NdotV2) / NdotV + scalar_type(1.0)); - scalar_type onePlusLambda_L = scalar_type(0.5) * (devsh_part(TdotL2, BdotL2, NdotL2) / NdotL + scalar_type(1.0)); + scalar_type onePlusLambda_V = scalar_type(0.5) * (devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()) / NdotV + scalar_type(1.0)); + scalar_type onePlusLambda_L = scalar_type(0.5) * (devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()) / NdotL + scalar_type(1.0)); G2_over_G1 = hlsl::beta(onePlusLambda_L, onePlusLambda_V) * onePlusLambda_V; } else { - scalar_type devsh_v = devsh_part(TdotV2, BdotV2, NdotV2); + scalar_type devsh_v = devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); G2_over_G1 = NdotL * (devsh_v + NdotV); - G2_over_G1 /= NdotV * devsh_part(TdotL2, BdotL2, NdotL2) + NdotL * devsh_v; + G2_over_G1 /= NdotV * devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()) + NdotL * devsh_v; } return G2_over_G1; } - // reflect only - scalar_type G2_over_G1(scalar_type NdotV, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type NdotL, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2) - { - scalar_type devsh_v = devsh_part(TdotV2, BdotV2, NdotV2); - scalar_type G2_over_G1 = NdotL * (devsh_v + NdotV); - G2_over_G1 /= NdotV * devsh_part(TdotL2, BdotL2, NdotL2) + NdotL * devsh_v; - - return G2_over_G1; - } - - scalar_type ax; - scalar_type ay; + scalar_type ax2; + scalar_type ay2; + scalar_type a2; }; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index edb798c3d2..a06417f096 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -97,6 +97,18 @@ struct GGXParams +struct SGGXDG1Query +{ + using scalar_type = T; + + scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } + scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; } + + scalar_type ndf; + scalar_type G1_over_2NdotV; +}; + template && surface_interactions::Isotropic && surface_interactions::Anisotropic && CreatableIsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SGGXBxDF { @@ -139,28 +151,29 @@ struct SGGXBxDF return retval; } - scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_isotropic_t) params) + scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_isotropic_t) params, BxDFClampMode _clamp) { scalar_type a2 = A.x*A.x; ndf::GGX ggx_ndf; ggx_ndf.a2 = a2; ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; - scalar_type NG = ggx_ndf.D(params.getNdotH2()); + scalar_type NG = ggx_ndf.template D(params.cache); if (a2 > numeric_limits::min) { - NG *= ggx_ndf.correlated_wo_numerator(params.getNdotV(), params.getNdotV2(), params.getNdotL(), params.getNdotL2()); + NG *= ggx_ndf.template correlated_wo_numerator(params._sample, params.interaction, _clamp); } return NG; } - scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_anisotropic_t) params) + scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_anisotropic_t) params, BxDFClampMode _clamp) { ndf::GGX ggx_ndf; - ggx_ndf.ax = A.x; - ggx_ndf.ay = A.y; - scalar_type NG = ggx_ndf.D(params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); + ggx_ndf.ax2 = A.x*A.x; + ggx_ndf.ay2 = A.y*A.y; + ggx_ndf.a2 = A.x*A.y; + scalar_type NG = ggx_ndf.template D(params.cache); if (any >(A > (vector2_type)numeric_limits::min)) { - NG *= ggx_ndf.correlated_wo_numerator(params.getNdotV(), params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getNdotL(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); + NG *= ggx_ndf.template correlated_wo_numerator(params._sample, params.interaction, _clamp); } return NG; } @@ -169,7 +182,7 @@ struct SGGXBxDF { if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) { - const scalar_type scalar_part = __eval_DG_wo_clamps(params); + const scalar_type scalar_part = __eval_DG_wo_clamps(params, BxDFClampMode::BCM_MAX); const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, params.getNdotL()); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); return f() * microfacet_transform; @@ -181,7 +194,7 @@ struct SGGXBxDF { if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) { - const scalar_type scalar_part = __eval_DG_wo_clamps(params); + const scalar_type scalar_part = __eval_DG_wo_clamps(params, BxDFClampMode::BCM_MAX); const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, params.getNdotL()); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); return f() * microfacet_transform; @@ -235,32 +248,31 @@ struct SGGXBxDF scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) { - scalar_type ndf, G1_over_2NdotV; + SGGXDG1Query dg1_query; const scalar_type a2 = A.x*A.x; ndf::GGX ggx_ndf; ggx_ndf.a2 = a2; ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; - ndf = ggx_ndf.D(params.getNdotH2()); + dg1_query.ndf = ggx_ndf.template D(params.cache); const scalar_type devsh_v = ggx_ndf.devsh_part(params.getNdotV2()); - G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(params.getNdotVUnclamped(), devsh_v); + dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(params.getNdotVUnclamped(), devsh_v); - return ggx_ndf.DG1(ndf, G1_over_2NdotV); + return ggx_ndf.template DG1 >(dg1_query); } scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { - scalar_type ndf, G1_over_2NdotV; - const scalar_type ax2 = A.x*A.x; - const scalar_type ay2 = A.y*A.y; + SGGXDG1Query dg1_query; ndf::GGX ggx_ndf; - ggx_ndf.ax = A.x; - ggx_ndf.ay = A.y; - ndf = ggx_ndf.D(params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); + ggx_ndf.ax2 = A.x*A.x; + ggx_ndf.ay2 = A.y*A.y; + ggx_ndf.a2 = A.x*A.y; + dg1_query.ndf = ggx_ndf.template D(params.cache); const scalar_type devsh_v = ggx_ndf.devsh_part(params.getTdotV2(), params.getBdotV2(), params.getNdotV2()); - G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(params.getNdotVUnclamped(), devsh_v); + dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(params.getNdotVUnclamped(), devsh_v); - return ggx_ndf.DG1(ndf, G1_over_2NdotV); + return ggx_ndf.template DG1 >(dg1_query); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) @@ -275,7 +287,7 @@ struct SGGXBxDF ggx_ndf.a2 = a2; ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; - const scalar_type G2_over_G1 = ggx_ndf.G2_over_G1(params.getNdotVUnclamped(), params.getNdotV2(), params.getNdotLUnclamped(), params.getNdotL2()); + const scalar_type G2_over_G1 = ggx_ndf.template G2_over_G1(params._sample, params.interaction, false, BxDFClampMode::BCM_MAX); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); @@ -292,10 +304,11 @@ struct SGGXBxDF if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) { ndf::GGX ggx_ndf; - ggx_ndf.ax = A.x; - ggx_ndf.ay = A.y; + ggx_ndf.ax2 = A.x*A.x; + ggx_ndf.ay2 = A.y*A.y; + ggx_ndf.a2 = A.x*A.y; - const scalar_type G2_over_G1 = ggx_ndf.G2_over_G1(params.getNdotVUnclamped(), params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getNdotLUnclamped(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); + const scalar_type G2_over_G1 = ggx_ndf.template G2_over_G1(params._sample, params.interaction, false, BxDFClampMode::BCM_MAX); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index e6e2029fdd..b06b9fd423 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -97,6 +97,22 @@ struct GGXParams +struct SGGXDG1Query +{ + using scalar_type = T; + + scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } + scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; } + bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } + scalar_type getOrientedEta() NBL_CONST_MEMBER_FUNC { return orientedEta; } + + scalar_type ndf; + scalar_type G1_over_2NdotV; + bool transmitted; + scalar_type orientedEta; +}; + template && surface_interactions::Isotropic && surface_interactions::Anisotropic && CreatableIsotropicMicrofacetCache && AnisotropicMicrofacetCache) struct SGGXDielectricBxDF { @@ -149,7 +165,7 @@ struct SGGXDielectricBxDF spectral_type dummyior; brdf_type ggx = brdf_type::create(A.x, dummyior, dummyior); typename brdf_type::params_isotropic_t brdf_params = typename brdf_type::params_isotropic_t::create(params._sample, params.interaction, params.cache, params._clamp); - NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(brdf_params); + NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(brdf_params, BxDFClampMode::BCM_ABS); const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(NG_already_in_reflective_dL_measure,params.getNdotL(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); const scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; @@ -168,7 +184,7 @@ struct SGGXDielectricBxDF spectral_type dummyior; brdf_type ggx = brdf_type::create(A.x, A.y, dummyior, dummyior); typename brdf_type::params_anisotropic_t brdf_params = typename brdf_type::params_anisotropic_t::create(params._sample, params.interaction, params.cache, params._clamp); - NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(brdf_params); + NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(brdf_params, BxDFClampMode::BCM_ABS); const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(NG_already_in_reflective_dL_measure,params.getNdotL(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); const scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; @@ -228,72 +244,76 @@ struct SGGXDielectricBxDF scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) { + SGGXDG1Query dg1_query; fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; + dg1_query.orientedEta = orientedEta.value[0]; - const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); - const bool transmitted = VdotHLdotH < 0.0; + dg1_query.transmitted = params.cache.isTransmission(); const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; - scalar_type ndf, devsh_v; + scalar_type devsh_v; const scalar_type a2 = A.x*A.x; ndf::GGX ggx_ndf; ggx_ndf.a2 = a2; ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; - ndf = ggx_ndf.D(params.getNdotH2()); + dg1_query.ndf = ggx_ndf.template D(params.cache); devsh_v = ggx_ndf.devsh_part(params.getNdotV2()); - const scalar_type lambda = ggx_ndf.G1_wo_numerator_devsh_part(params.getNdotV(), devsh_v); + dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(params.getNdotV(), devsh_v); - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, transmitted) * ggx_ndf.DG1(ndf, lambda, transmitted, params.getVdotH(), params.getLdotH(), VdotHLdotH, orientedEta.value[0]); + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, dg1_query.transmitted) * ggx_ndf.template DG1, isocache_type>(dg1_query, params.cache); } scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { + SGGXDG1Query dg1_query; fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; + dg1_query.orientedEta = orientedEta.value[0]; - const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); - const bool transmitted = VdotHLdotH < 0.0; + dg1_query.transmitted = params.cache.isTransmission(); const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; - scalar_type ndf, devsh_v; + scalar_type devsh_v; ndf::GGX ggx_ndf; - ggx_ndf.ax = A.x; - ggx_ndf.ay = A.y; - ndf = ggx_ndf.D(params.getTdotH2(), params.getBdotH2(), params.getNdotH2()); + ggx_ndf.ax2 = A.x*A.x; + ggx_ndf.ay2 = A.y*A.y; + ggx_ndf.a2 = A.x*A.y; + dg1_query.ndf = ggx_ndf.template D(params.cache); devsh_v = ggx_ndf.devsh_part(params.getTdotV2(), params.getBdotV2(), params.getNdotV2()); - const scalar_type lambda = ggx_ndf.G1_wo_numerator_devsh_part(params.getNdotV(), devsh_v); + dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(params.getNdotV(), devsh_v); - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, transmitted) * ggx_ndf.DG1(ndf, lambda, transmitted, params.getVdotH(), params.getLdotH(), VdotHLdotH, orientedEta.value[0]); + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, dg1_query.transmitted) * ggx_ndf.template DG1, anisocache_type>(dg1_query, params.cache); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) { scalar_type _pdf = pdf(params); - const bool transmitted = params.getVdotH() * params.getLdotH() < 0.0; + const bool transmitted = params.cache.isTransmission(); const scalar_type a2 = A.x * A.x; ndf::GGX ggx_ndf; ggx_ndf.a2 = a2; ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; scalar_type quo; - quo = ggx_ndf.G2_over_G1(transmitted, params.getNdotV(), params.getNdotV2(), params.getNdotL(), params.getNdotL2()); + quo = ggx_ndf.template G2_over_G1(params._sample, params.interaction, transmitted, BxDFClampMode::BCM_ABS); return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { scalar_type _pdf = pdf(params); - const bool transmitted = params.getVdotH() * params.getLdotH() < 0.0; + const bool transmitted = params.cache.isTransmission(); ndf::GGX ggx_ndf; - ggx_ndf.ax = A.x; - ggx_ndf.ay = A.y; + ggx_ndf.ax2 = A.x*A.x; + ggx_ndf.ay2 = A.y*A.y; + ggx_ndf.a2 = A.x*A.y; scalar_type quo; - quo = ggx_ndf.G2_over_G1(transmitted, params.getNdotV(), params.getTdotV2(), params.getBdotV2(), params.getNdotV2(), params.getNdotL(), params.getTdotL2(), params.getBdotL2(), params.getNdotL2()); + quo = ggx_ndf.template G2_over_G1(params._sample, params.interaction, transmitted, BxDFClampMode::BCM_ABS); return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } From dd1be94d81518f89af3191b562adad76bd2adbe1 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 28 Jul 2025 14:14:30 +0700 Subject: [PATCH 147/188] use cache functions: isTransmission, VdotHLdotH --- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 4 +--- .../hlsl/bxdf/transmission/beckmann.hlsl | 18 ++++++------------ .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 10 ++++------ 3 files changed, 11 insertions(+), 21 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index b7ba280c05..ecd1023eed 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -46,7 +46,6 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getAbsNdotV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getTransmitted()), ::nbl::hlsl::is_same_v, bool)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getVdotHLdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getOrientedEta()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getOnePlusLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ); @@ -71,7 +70,6 @@ NBL_CONCEPT_END( template struct Beckmann; -// TODO: use query_type for D, lambda, beta, DG1 when that's implemented template NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) struct Beckmann) > @@ -99,7 +97,7 @@ struct Beckmann) > scalar_type DG1(NBL_REF_ARG(Query) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) { query.onePlusLambda_V = scalar_type(1.0) + query.getLambdaV(); - return ndf::microfacet_to_light_measure_transform::__call(query.getNdf() / query.getOnePlusLambdaV(), query.getAbsNdotV(), query.getTransmitted(), cache.getVdotH(), cache.getLdotH(), query.getVdotHLdotH(), query.getOrientedEta()); + return ndf::microfacet_to_light_measure_transform::__call(query.getNdf() / query.getOnePlusLambdaV(), query.getAbsNdotV(), query.getTransmitted(), cache.getVdotH(), cache.getLdotH(), cache.getVdotHLdotH(), query.getOrientedEta()); } scalar_type G1(scalar_type lambda) diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index ce9249bfca..901dcdafc9 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -106,7 +106,6 @@ struct SBeckmannDG1Query scalar_type getAbsNdotV() NBL_CONST_MEMBER_FUNC { return absNdotV; } scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } - scalar_type getVdotHLdotH() NBL_CONST_MEMBER_FUNC { return VdotHLdotH; } scalar_type getOrientedEta() NBL_CONST_MEMBER_FUNC { return orientedEta; } scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } @@ -114,7 +113,6 @@ struct SBeckmannDG1Query scalar_type absNdotV; scalar_type lambda_V; bool transmitted; - scalar_type VdotHLdotH; scalar_type orientedEta; scalar_type onePlusLambda_V; }; @@ -176,8 +174,8 @@ struct SBeckmannDielectricBxDF fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; - const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); - const bool transmitted = VdotHLdotH < 0.0; + const scalar_type VdotHLdotH = params.cache.getVdotHLdotH(); + const bool transmitted = params.cache.isTransmission(); spectral_type dummyior; brdf_type beckmann = brdf_type::create(A.x, dummyior, dummyior); @@ -193,8 +191,8 @@ struct SBeckmannDielectricBxDF fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; - const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); - const bool transmitted = VdotHLdotH < 0.0; + const scalar_type VdotHLdotH = params.cache.getVdotHLdotH(); + const bool transmitted = params.cache.isTransmission(); spectral_type dummyior; brdf_type beckmann = brdf_type::create(A.x, A.y, dummyior, dummyior); @@ -266,9 +264,7 @@ struct SBeckmannDielectricBxDF const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; dg1_query.orientedEta = orientedEta.value[0]; - const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); - dg1_query.transmitted = VdotHLdotH < 0.0; - dg1_query.VdotHLdotH = VdotHLdotH; + dg1_query.transmitted = params.cache.isTransmission(); const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; @@ -293,9 +289,7 @@ struct SBeckmannDielectricBxDF const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; dg1_query.orientedEta = orientedEta.value[0]; - const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); - dg1_query.transmitted = VdotHLdotH < 0.0; - dg1_query.VdotHLdotH = VdotHLdotH; + dg1_query.transmitted = params.cache.isTransmission(); const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index b06b9fd423..ed15d46fa7 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -157,9 +157,8 @@ struct SGGXDielectricBxDF fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; - - const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); - const bool transmitted = VdotHLdotH < 0.0; + const scalar_type VdotHLdotH = params.cache.getVdotHLdotH(); + const bool transmitted = params.cache.isTransmission(); scalar_type NG_already_in_reflective_dL_measure; spectral_type dummyior; @@ -176,9 +175,8 @@ struct SGGXDielectricBxDF fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; - - const scalar_type VdotHLdotH = params.getVdotH() * params.getLdotH(); - const bool transmitted = VdotHLdotH < 0.0; + const scalar_type VdotHLdotH = params.cache.getVdotHLdotH(); + const bool transmitted = params.cache.isTransmission(); scalar_type NG_already_in_reflective_dL_measure; spectral_type dummyior; From ef2ad009d47d7cd6ac4461e1ba70a49afe06147f Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 28 Jul 2025 15:24:54 +0700 Subject: [PATCH 148/188] bxdf specialized beta function --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 32 +++++++++++++++++++ .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 4 +-- include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 5 ++- include/nbl/builtin/hlsl/tgmath/impl.hlsl | 1 - 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 4925873ad9..e36fd9d3c2 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -885,6 +885,38 @@ using quotient_and_pdf_scalar = sampling::quotient_and_pdf, P> ; template using quotient_and_pdf_rgb = sampling::quotient_and_pdf, P> ; +// beta function specialized for Cook Torrance BTDFs +namespace impl +{ +template && sizeof(T)<8) +struct beta +{ + static T __series_part(T x) + { + const T r = T(1.0) / x; + const T r2 = r * r; + return (T(1.0/360.0) * r2 + T(1.0/12.0)) * r - x; + } + + // removed values that cancel out in beta + static T __call(T x, T y) + { + const T l2x = hlsl::log2(x); + const T l2y = hlsl::log2(y); + const T l2xy = hlsl::log2(x+y); + + return hlsl::exp2((x - T(0.5)) * l2x + (y - T(0.5)) * l2y - (x + y - T(0.5)) * l2xy + + numbers::inv_ln2 * (__series_part(x) + __series_part(y) - __series_part(x+y)) + T(1.32574806473616)); + } +}; +} + +template +T beta(NBL_CONST_REF_ARG(T) x, NBL_CONST_REF_ARG(T) y) +{ + return impl::beta::__call(x, y); +} + } } } diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index ecd1023eed..78df527a45 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -135,7 +135,7 @@ struct Beckmann) > scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample) { scalar_type lambda_L = LambdaC2(_sample.getNdotL2()); - return query.getOnePlusLambdaV() * hlsl::mix(scalar_type(1.0)/(query.getOnePlusLambdaV() + lambda_L), hlsl::beta(query.getOnePlusLambdaV(), scalar_type(1.0) + lambda_L), query.getTransmitted()); + return query.getOnePlusLambdaV() * hlsl::mix(scalar_type(1.0)/(query.getOnePlusLambdaV() + lambda_L), bxdf::beta(query.getOnePlusLambdaV(), scalar_type(1.0) + lambda_L), query.getTransmitted()); } scalar_type a2; @@ -211,7 +211,7 @@ struct Beckmann) > scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample) { scalar_type lambda_L = LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); - return query.getOnePlusLambdaV() * hlsl::mix(scalar_type(1.0)/(query.getOnePlusLambdaV() + lambda_L), hlsl::beta(query.getOnePlusLambdaV(), scalar_type(1.0) + lambda_L), query.getTransmitted()); + return query.getOnePlusLambdaV() * hlsl::mix(scalar_type(1.0)/(query.getOnePlusLambdaV() + lambda_L), bxdf::beta(query.getOnePlusLambdaV(), scalar_type(1.0) + lambda_L), query.getTransmitted()); } scalar_type ax; diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index 610fcbbf9e..de05c01ed0 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -52,7 +52,6 @@ NBL_CONCEPT_END( template struct GGX; -// TODO: use query_type when that's implemented template NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) struct GGX) > @@ -126,7 +125,7 @@ struct GGX) > return 0.0; scalar_type onePlusLambda_V = scalar_type(0.5) * (devsh_part(interaction.getNdotV2()) / NdotV + scalar_type(1.0)); scalar_type onePlusLambda_L = scalar_type(0.5) * (devsh_part(_sample.getNdotL2()) / NdotL + scalar_type(1.0)); - G2_over_G1 = hlsl::beta(onePlusLambda_L, onePlusLambda_V) * onePlusLambda_V; + G2_over_G1 = bxdf::beta(onePlusLambda_L, onePlusLambda_V) * onePlusLambda_V; } else { @@ -216,7 +215,7 @@ struct GGX) > return 0.0; scalar_type onePlusLambda_V = scalar_type(0.5) * (devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()) / NdotV + scalar_type(1.0)); scalar_type onePlusLambda_L = scalar_type(0.5) * (devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()) / NdotL + scalar_type(1.0)); - G2_over_G1 = hlsl::beta(onePlusLambda_L, onePlusLambda_V) * onePlusLambda_V; + G2_over_G1 = bxdf::beta(onePlusLambda_L, onePlusLambda_V) * onePlusLambda_V; } else { diff --git a/include/nbl/builtin/hlsl/tgmath/impl.hlsl b/include/nbl/builtin/hlsl/tgmath/impl.hlsl index e17492065a..9af1fb0ebd 100644 --- a/include/nbl/builtin/hlsl/tgmath/impl.hlsl +++ b/include/nbl/builtin/hlsl/tgmath/impl.hlsl @@ -596,7 +596,6 @@ struct beta_helper) > // implementation from Numerical Recipes in C, 2nd ed. static T __call(T v1, T v2) { - // specialized for Cook Torrance BTDFs assert(v1 >= 1.0 && v2 >= 1.0); if (v1+v2 > 1e6) From 3a81eaf2c61681f267e27429bfe6fb677a32c8af Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 29 Jul 2025 12:03:30 +0700 Subject: [PATCH 149/188] unified bxdf config struct, used in lambertians, moved bxdf traits after each definition --- .../nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl | 77 +-------- include/nbl/builtin/hlsl/bxdf/config.hlsl | 155 ++++++++++++++++++ .../hlsl/bxdf/reflection/beckmann.hlsl | 10 ++ .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 10 ++ .../hlsl/bxdf/reflection/lambertian.hlsl | 31 ++-- .../hlsl/bxdf/reflection/oren_nayar.hlsl | 10 ++ .../hlsl/bxdf/transmission/beckmann.hlsl | 10 ++ .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 10 ++ .../hlsl/bxdf/transmission/lambertian.hlsl | 31 ++-- .../bxdf/transmission/smooth_dielectric.hlsl | 18 ++ 10 files changed, 266 insertions(+), 96 deletions(-) create mode 100644 include/nbl/builtin/hlsl/bxdf/config.hlsl diff --git a/include/nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl b/include/nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl index 5ef93e7abf..e57bb13837 100644 --- a/include/nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl @@ -5,8 +5,6 @@ #define _NBL_BUILTIN_HLSL_BXDF_TRAITS_INCLUDED_ #include "nbl/builtin/hlsl/bxdf/common.hlsl" -#include "nbl/builtin/hlsl/bxdf/reflection.hlsl" -#include "nbl/builtin/hlsl/bxdf/transmission.hlsl" namespace nbl { @@ -25,80 +23,7 @@ enum BxDFType : uint16_t template struct traits; -template -struct traits > -{ - NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; - NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = false; - NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; -}; - -template -struct traits > -{ - NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; - NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; - NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; -}; - -// no blinn phong - -template -struct traits > -{ - NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; - NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; - NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; -}; - -template -struct traits > -{ - NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; - NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; - NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; -}; - - -template -struct traits > -{ - NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; - NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = false; - NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; -}; - -template -struct traits > -{ - NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; - NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; - NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; -}; - -template -struct traits > -{ - NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; - NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; - NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; -}; - -template -struct traits > -{ - NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; - NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; - NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; -}; - -template -struct traits > -{ - NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; - NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; - NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; -}; +// defined individually after each bxdf definition } } diff --git a/include/nbl/builtin/hlsl/bxdf/config.hlsl b/include/nbl/builtin/hlsl/bxdf/config.hlsl new file mode 100644 index 0000000000..390dae9239 --- /dev/null +++ b/include/nbl/builtin/hlsl/bxdf/config.hlsl @@ -0,0 +1,155 @@ +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_BUILTIN_HLSL_BXDF_CONFIG_INCLUDED_ +#define _NBL_BUILTIN_HLSL_BXDF_CONFIG_INCLUDED_ + +#include "nbl/builtin/hlsl/bxdf/common.hlsl" + +namespace nbl +{ +namespace hlsl +{ +namespace bxdf +{ + +namespace config_concepts +{ +#define NBL_CONCEPT_NAME BasicConfiguration +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (conf, T) +NBL_CONCEPT_BEGIN(1) +#define conf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::vector2_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::ray_dir_info_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_interaction_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::anisotropic_interaction_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::spectral_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) +); +#undef conf +#include + +#define NBL_CONCEPT_NAME MicrofacetConfiguration +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (conf, T) +NBL_CONCEPT_BEGIN(1) +#define conf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::vector2_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::monochrome_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::matrix3x3_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::ray_dir_info_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::isotropic_interaction_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::anisotropic_interaction_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::spectral_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::isocache_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::anisocache_type)) +); +#undef conf +#include +} + +template +struct SConfiguration; + +template +NBL_PARTIAL_REQ_TOP(LightSample && surface_interactions::Isotropic && !surface_interactions::Anisotropic && concepts::FloatingPointLikeVectorial) +struct SConfiguration && surface_interactions::Isotropic && !surface_interactions::Anisotropic && concepts::FloatingPointLikeVectorial) > +{ + NBL_CONSTEXPR_STATIC_INLINE bool IsAnisotropic = false; + + using scalar_type = typename LS::scalar_type; + using ray_dir_info_type = typename LS::ray_dir_info_type; + using vector2_type = vector; + using vector3_type = vector; + + using isotropic_interaction_type = Interaction; + using anisotropic_interaction_type = surface_interactions::SAnisotropic; + using sample_type = LS; + using spectral_type = Spectrum; + using quotient_pdf_type = sampling::quotient_and_pdf; +}; + +template +NBL_PARTIAL_REQ_TOP(LightSample && surface_interactions::Anisotropic && concepts::FloatingPointLikeVectorial) +struct SConfiguration && surface_interactions::Anisotropic && concepts::FloatingPointLikeVectorial) > +{ + NBL_CONSTEXPR_STATIC_INLINE bool IsAnisotropic = true; + + using scalar_type = typename LS::scalar_type; + using ray_dir_info_type = typename LS::ray_dir_info_type; + using vector2_type = vector; + using vector3_type = vector; + + using isotropic_interaction_type = typename Interaction::isotropic_interaction_type; + using anisotropic_interaction_type = Interaction; + using sample_type = LS; + using spectral_type = Spectrum; + using quotient_pdf_type = sampling::quotient_and_pdf; +}; + +template +struct SMicrofacetConfiguration; + +template +NBL_PARTIAL_REQ_TOP(LightSample && surface_interactions::Isotropic && !surface_interactions::Anisotropic && + CreatableIsotropicMicrofacetCache && !AnisotropicMicrofacetCache && concepts::FloatingPointLikeVectorial) +struct SMicrofacetConfiguration && surface_interactions::Isotropic && !surface_interactions::Anisotropic && + CreatableIsotropicMicrofacetCache && !AnisotropicMicrofacetCache && concepts::FloatingPointLikeVectorial) > +{ + NBL_CONSTEXPR_STATIC_INLINE bool IsAnisotropic = false; + + using scalar_type = typename LS::scalar_type; + using ray_dir_info_type = typename LS::ray_dir_info_type; + using vector2_type = vector; + using vector3_type = vector; + using matrix3x3_type = matrix; + using monochrome_type = vector; + + using isotropic_interaction_type = Interaction; + using anisotropic_interaction_type = surface_interactions::SAnisotropic; + using sample_type = LS; + using spectral_type = Spectrum; + using quotient_pdf_type = sampling::quotient_and_pdf; + using isocache_type = MicrofacetCache; + using anisocache_type = SAnisotropicMicrofacetCache; +}; + +template +NBL_PARTIAL_REQ_TOP(LightSample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache && concepts::FloatingPointLikeVectorial) +struct SMicrofacetConfiguration && surface_interactions::Anisotropic && AnisotropicMicrofacetCache && concepts::FloatingPointLikeVectorial) > +{ + NBL_CONSTEXPR_STATIC_INLINE bool IsAnisotropic = true; + + using scalar_type = typename LS::scalar_type; + using ray_dir_info_type = typename LS::ray_dir_info_type; + using vector2_type = vector; + using vector3_type = vector; + using matrix3x3_type = matrix; + using monochrome_type = vector; + + using isotropic_interaction_type = typename Interaction::isotropic_interaction_type; + using anisotropic_interaction_type = Interaction; + using sample_type = LS; + using spectral_type = Spectrum; + using quotient_pdf_type = sampling::quotient_and_pdf; + using isocache_type = typename MicrofacetCache::isocache_type; + using anisocache_type = MicrofacetCache; +}; + +} +} +} + +#endif diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 42a1bbf53d..d45c77b384 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -5,6 +5,7 @@ #define _NBL_BUILTIN_HLSL_BXDF_REFLECTION_BECKMANN_INCLUDED_ #include "nbl/builtin/hlsl/bxdf/common.hlsl" +#include "nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl" #include "nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl" #include "nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl" @@ -399,6 +400,15 @@ struct SBeckmannBxDF }; } + +template +struct traits > +{ + NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; +}; + } } } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index a06417f096..3d4af89608 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -5,6 +5,7 @@ #define _NBL_BUILTIN_HLSL_BXDF_REFLECTION_GGX_INCLUDED_ #include "nbl/builtin/hlsl/bxdf/common.hlsl" +#include "nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl" #include "nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl" #include "nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl" @@ -323,6 +324,15 @@ struct SGGXBxDF }; } + +template +struct traits > +{ + NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; +}; + } } } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl index 0065fba906..c6425c5104 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl @@ -5,6 +5,8 @@ #define _NBL_BUILTIN_HLSL_BXDF_REFLECTION_LAMBERTIAN_INCLUDED_ #include "nbl/builtin/hlsl/bxdf/common.hlsl" +#include "nbl/builtin/hlsl/bxdf/config.hlsl" +#include "nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl" #include "nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl" namespace nbl @@ -80,20 +82,20 @@ struct LambertianParams && surface_interactions::Isotropic && surface_interactions::Anisotropic) +template) struct SLambertianBxDF { - using this_t = SLambertianBxDF; - using scalar_type = typename LS::scalar_type; - using ray_dir_info_type = typename LS::ray_dir_info_type; - using isotropic_interaction_type = Iso; - using anisotropic_interaction_type = Aniso; - using sample_type = LS; - using spectral_type = Spectrum; + using this_t = SLambertianBxDF; + using scalar_type = typename Config::scalar_type; + using ray_dir_info_type = typename Config::ray_dir_info_type; + using isotropic_interaction_type = typename Config::isotropic_interaction_type; + using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; + using sample_type = typename Config::sample_type; + using spectral_type = typename Config::spectral_type; using quotient_pdf_type = sampling::quotient_and_pdf; - using params_isotropic_t = LambertianParams; - using params_anisotropic_t = LambertianParams; + using params_isotropic_t = LambertianParams; + using params_anisotropic_t = LambertianParams; static this_t create() @@ -156,6 +158,15 @@ struct SLambertianBxDF }; } + +template +struct traits > +{ + NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = false; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; +}; + } } } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl index 665d018f10..a08810eb15 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl @@ -5,6 +5,7 @@ #define _NBL_BUILTIN_HLSL_BXDF_REFLECTION_OREN_NAYAR_INCLUDED_ #include "nbl/builtin/hlsl/bxdf/common.hlsl" +#include "nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl" #include "nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl" namespace nbl @@ -169,6 +170,15 @@ struct SOrenNayarBxDF }; } + +template +struct traits > +{ + NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; +}; + } } } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 901dcdafc9..92db440a14 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -5,6 +5,7 @@ #define _NBL_BUILTIN_HLSL_BXDF_TRANSMISSION_BECKMANN_INCLUDED_ #include "nbl/builtin/hlsl/bxdf/common.hlsl" +#include "nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl" #include "nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl" #include "nbl/builtin/hlsl/bxdf/reflection.hlsl" @@ -352,6 +353,15 @@ struct SBeckmannDielectricBxDF }; } + +template +struct traits > +{ + NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; +}; + } } } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index ed15d46fa7..e9782df034 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -5,6 +5,7 @@ #define _NBL_BUILTIN_HLSL_BXDF_TRANSMISSION_GGX_INCLUDED_ #include "nbl/builtin/hlsl/bxdf/common.hlsl" +#include "nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl" #include "nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl" #include "nbl/builtin/hlsl/bxdf/reflection.hlsl" @@ -321,6 +322,15 @@ struct SGGXDielectricBxDF }; } + +template +struct traits > +{ + NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; +}; + } } } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl index 7fb9d52b93..3be9df6996 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl @@ -5,6 +5,8 @@ #define _NBL_BUILTIN_HLSL_BXDF_TRANSMISSION_LAMBERTIAN_INCLUDED_ #include "nbl/builtin/hlsl/bxdf/common.hlsl" +#include "nbl/builtin/hlsl/bxdf/config.hlsl" +#include "nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl" #include "nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl" #include "nbl/builtin/hlsl/bxdf/reflection.hlsl" @@ -81,20 +83,20 @@ struct LambertianParams && surface_interactions::Isotropic && surface_interactions::Anisotropic) +template) struct SLambertianBxDF { - using this_t = SLambertianBxDF; - using scalar_type = typename LS::scalar_type; - using ray_dir_info_type = typename LS::ray_dir_info_type; - using isotropic_interaction_type = Iso; - using anisotropic_interaction_type = Aniso; - using sample_type = LS; - using spectral_type = Spectrum; + using this_t = SLambertianBxDF; + using scalar_type = typename Config::scalar_type; + using ray_dir_info_type = typename Config::ray_dir_info_type; + using isotropic_interaction_type = typename Config::isotropic_interaction_type; + using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; + using sample_type = typename Config::sample_type; + using spectral_type = typename Config::spectral_type; using quotient_pdf_type = sampling::quotient_and_pdf; - using params_isotropic_t = LambertianParams; - using params_anisotropic_t = LambertianParams; + using params_isotropic_t = LambertianParams; + using params_anisotropic_t = LambertianParams; static this_t create() @@ -157,6 +159,15 @@ struct SLambertianBxDF }; } + +template +struct traits > +{ + NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = false; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; +}; + } } } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index a5490b6d4a..01c704caef 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -5,6 +5,7 @@ #define _NBL_BUILTIN_HLSL_BXDF_TRANSMISSION_SMOOTH_DIELECTRIC_INCLUDED_ #include "nbl/builtin/hlsl/bxdf/common.hlsl" +#include "nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl" #include "nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl" namespace nbl @@ -304,6 +305,23 @@ struct SSmoothDielectricBxDF +struct traits > +{ + NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; +}; + +template +struct traits > +{ + NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; +}; + } } } From 3128bd2148d0f27454e8c00ec63cf36d6d2f54c2 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 29 Jul 2025 14:12:54 +0700 Subject: [PATCH 150/188] use config struct with oren-nayar, smooth dielectric/thin --- .../hlsl/bxdf/reflection/oren_nayar.hlsl | 27 ++++---- .../bxdf/transmission/smooth_dielectric.hlsl | 64 ++++++++----------- src/nbl/builtin/CMakeLists.txt | 1 + 3 files changed, 42 insertions(+), 50 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl index a08810eb15..97418c665c 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl @@ -5,6 +5,7 @@ #define _NBL_BUILTIN_HLSL_BXDF_REFLECTION_OREN_NAYAR_INCLUDED_ #include "nbl/builtin/hlsl/bxdf/common.hlsl" +#include "nbl/builtin/hlsl/bxdf/config.hlsl" #include "nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl" #include "nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl" @@ -83,23 +84,21 @@ struct OrenNayarParams && surface_interactions::Isotropic && surface_interactions::Anisotropic) +template) struct SOrenNayarBxDF { - using this_t = SOrenNayarBxDF; - using scalar_type = typename LS::scalar_type; + using this_t = SOrenNayarBxDF; + using scalar_type = typename Config::scalar_type; using vector2_type = vector; - using ray_dir_info_type = typename LS::ray_dir_info_type; - - using isotropic_interaction_type = Iso; - using anisotropic_interaction_type = Aniso; - using sample_type = LS; - using spectral_type = Spectrum; + using ray_dir_info_type = typename Config::ray_dir_info_type; + using isotropic_interaction_type = typename Config::isotropic_interaction_type; + using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; + using sample_type = typename Config::sample_type; + using spectral_type = typename Config::spectral_type; using quotient_pdf_type = sampling::quotient_and_pdf; - - using params_isotropic_t = OrenNayarParams; - using params_anisotropic_t = OrenNayarParams; + using params_isotropic_t = OrenNayarParams; + using params_anisotropic_t = OrenNayarParams; static this_t create(scalar_type A) { @@ -171,8 +170,8 @@ struct SOrenNayarBxDF } -template -struct traits > +template +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index 01c704caef..1ec7d3d15a 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -81,29 +81,23 @@ struct SmoothDielectricParams // NBL_FUNC_REQUIRES(Sample && IsotropicMicrofacetCache && AnisotropicMicrofacetCache) // dxc won't let me put this in -struct SSmoothDielectricBxDF; - -template -struct SSmoothDielectricBxDF +template) +struct SSmoothDielectricBxDF { - using this_t = SSmoothDielectricBxDF; - using scalar_type = typename LS::scalar_type; - using ray_dir_info_type = typename LS::ray_dir_info_type; + using this_t = SSmoothDielectricBxDF; + using scalar_type = typename Config::scalar_type; + using vector2_type = vector; using vector3_type = vector; using monochrome_type = vector; - - using isotropic_interaction_type = Iso; - using anisotropic_interaction_type = Aniso; - using sample_type = LS; - using spectral_type = Spectrum; + using ray_dir_info_type = typename Config::ray_dir_info_type; + using isotropic_interaction_type = typename Config::isotropic_interaction_type; + using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; + using sample_type = typename Config::sample_type; + using spectral_type = typename Config::spectral_type; using quotient_pdf_type = sampling::quotient_and_pdf; - using isocache_type = IsoCache; - using anisocache_type = AnisoCache; - - using params_isotropic_t = SmoothDielectricParams; - using params_anisotropic_t = SmoothDielectricParams; + using params_isotropic_t = SmoothDielectricParams; + using params_anisotropic_t = SmoothDielectricParams; static this_t create(scalar_type eta) { @@ -194,25 +188,23 @@ struct SSmoothDielectricBxDF -struct SSmoothDielectricBxDF +template) +struct SSmoothThinDielectricBxDF { - using this_t = SSmoothDielectricBxDF; - using scalar_type = typename LS::scalar_type; - using ray_dir_info_type = typename LS::ray_dir_info_type; + using this_t = SSmoothThinDielectricBxDF; + using scalar_type = typename Config::scalar_type; + using vector2_type = vector; using vector3_type = vector; using monochrome_type = vector; - - using isotropic_interaction_type = Iso; - using anisotropic_interaction_type = Aniso; - using sample_type = LS; - using spectral_type = Spectrum; + using ray_dir_info_type = typename Config::ray_dir_info_type; + using isotropic_interaction_type = typename Config::isotropic_interaction_type; + using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; + using sample_type = typename Config::sample_type; + using spectral_type = typename Config::spectral_type; using quotient_pdf_type = sampling::quotient_and_pdf; - using isocache_type = IsoCache; - using anisocache_type = AnisoCache; - using params_isotropic_t = SmoothDielectricParams; - using params_anisotropic_t = SmoothDielectricParams; + using params_isotropic_t = SmoothDielectricParams; + using params_anisotropic_t = SmoothDielectricParams; static this_t create(NBL_CONST_REF_ARG(spectral_type) eta2, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) @@ -306,16 +298,16 @@ struct SSmoothDielectricBxDF -struct traits > +template +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; }; -template -struct traits > +template +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; diff --git a/src/nbl/builtin/CMakeLists.txt b/src/nbl/builtin/CMakeLists.txt index 12ad5b080f..64202e4487 100644 --- a/src/nbl/builtin/CMakeLists.txt +++ b/src/nbl/builtin/CMakeLists.txt @@ -335,6 +335,7 @@ LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/common.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/fresnel.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/geom_smith.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/ndf.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/config.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/reflection.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/transmission.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/bxdf_traits.hlsl") From a5f577ac292a4573e1f382547240e7dae4144cf8 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 29 Jul 2025 17:19:18 +0700 Subject: [PATCH 151/188] use config structs in all beckmann, ggx bxdfs --- .../hlsl/bxdf/reflection/beckmann.hlsl | 221 +++++++++++------- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 207 +++++++++------- .../hlsl/bxdf/transmission/beckmann.hlsl | 201 +++++++++------- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 185 +++++++++------ 4 files changed, 493 insertions(+), 321 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index d45c77b384..7a689ded51 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -126,42 +126,34 @@ struct SBeckmannG2overG1Query scalar_type onePlusLambda_V; }; -template && surface_interactions::Isotropic && surface_interactions::Anisotropic && CreatableIsotropicMicrofacetCache && AnisotropicMicrofacetCache) -struct SBeckmannBxDF +template +struct SBeckmannAnisotropicBxDF; + +template) +struct SBeckmannIsotropicBxDF { - using this_t = SBeckmannBxDF; - using scalar_type = typename LS::scalar_type; - using ray_dir_info_type = typename LS::ray_dir_info_type; + using this_t = SBeckmannIsotropicBxDF; + using scalar_type = typename Config::scalar_type; using vector2_type = vector; using vector3_type = vector; + using ray_dir_info_type = typename Config::ray_dir_info_type; - using isotropic_interaction_type = Iso; - using anisotropic_interaction_type = Aniso; - using sample_type = LS; - using spectral_type = Spectrum; + using isotropic_interaction_type = typename Config::isotropic_interaction_type; + using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; + using sample_type = typename Config::sample_type; + using spectral_type = typename Config::spectral_type; using quotient_pdf_type = sampling::quotient_and_pdf; - using isocache_type = IsoCache; - using anisocache_type = AnisoCache; - - using params_isotropic_t = BeckmannParams; - using params_anisotropic_t = BeckmannParams; + using isocache_type = typename Config::isocache_type; + using anisocache_type = typename Config::anisocache_type; + using params_isotropic_t = BeckmannParams; + using params_anisotropic_t = BeckmannParams; // iso static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) { this_t retval; - retval.A = vector2_type(A,A); - retval.ior0 = ior0; - retval.ior1 = ior1; - return retval; - } - - // aniso - static this_t create(scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) - { - this_t retval; - retval.A = vector2_type(ax,ay); + retval.A = A; retval.ior0 = ior0; retval.ior1 = ior1; return retval; @@ -169,7 +161,7 @@ struct SBeckmannBxDF scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_isotropic_t) params) { - scalar_type a2 = A.x*A.x; + scalar_type a2 = A*A; ndf::Beckmann beckmann_ndf; beckmann_ndf.a2 = a2; scalar_type NG = beckmann_ndf.template D(params.cache); @@ -179,18 +171,6 @@ struct SBeckmannBxDF } return NG; } - scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_anisotropic_t) params) - { - ndf::Beckmann beckmann_ndf; - beckmann_ndf.ax = A.x; - beckmann_ndf.ay = A.y; - scalar_type NG = beckmann_ndf.template D(params.cache); - if (hlsl::any >(A > (vector2_type)numeric_limits::min)) - { - NG *= beckmann_ndf.template correlated(params._sample, params.interaction); - } - return NG; - } spectral_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) { @@ -204,6 +184,109 @@ struct SBeckmannBxDF else return hlsl::promote(0.0); } + + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector2_type) u, NBL_REF_ARG(isocache_type) cache) + { + SBeckmannAnisotropicBxDF beckmann_aniso = SBeckmannAnisotropicBxDF::create(A, A, ior0, ior1); + anisocache_type anisocache; + sample_type s = beckmann_aniso.generate(anisotropic_interaction_type::create(interaction), u, anisocache); + cache = anisocache.iso_cache; + return s; + } + + scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) + { + SBeckmannDG1Query dg1_query; + dg1_query.maxNdotV = params.getNdotV(); + + scalar_type a2 = A*A; + ndf::Beckmann beckmann_ndf; + beckmann_ndf.a2 = a2; + dg1_query.ndf = beckmann_ndf.template D(params.cache); + + dg1_query.lambda_V = beckmann_ndf.LambdaC2(params.getNdotV2()); + + scalar_type dg1 = beckmann_ndf.template DG1 >(dg1_query); + onePlusLambda_V = dg1_query.getOnePlusLambdaV(); + return dg1; + } + + scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + { + scalar_type dummy; + return pdf(params, dummy); + } + + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + { + scalar_type onePlusLambda_V; + scalar_type _pdf = pdf(params, onePlusLambda_V); + + ndf::Beckmann beckmann_ndf; + spectral_type quo = (spectral_type)0.0; + if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) + { + beckmann_ndf.a2 = A*A; + SBeckmannG2overG1Query query; + query.transmitted = false; + query.onePlusLambda_V = onePlusLambda_V; + scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1, sample_type>(query, params._sample); + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); + const spectral_type reflectance = f(); + quo = reflectance * G2_over_G1; + } + + return quotient_pdf_type::create(quo, _pdf); + } + + scalar_type A; + spectral_type ior0, ior1; +}; + +template +NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration) +struct SBeckmannAnisotropicBxDF) > +{ + using this_t = SBeckmannAnisotropicBxDF; + using scalar_type = typename Config::scalar_type; + using vector2_type = vector; + using vector3_type = vector; + using ray_dir_info_type = typename Config::ray_dir_info_type; + + using isotropic_interaction_type = typename Config::isotropic_interaction_type; + using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; + using sample_type = typename Config::sample_type; + using spectral_type = typename Config::spectral_type; + using quotient_pdf_type = sampling::quotient_and_pdf; + using isocache_type = typename Config::isocache_type; + using anisocache_type = typename Config::anisocache_type; + + using params_isotropic_t = BeckmannParams; + using params_anisotropic_t = BeckmannParams; + + // aniso + static this_t create(scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) + { + this_t retval; + retval.A = vector2_type(ax,ay); + retval.ior0 = ior0; + retval.ior1 = ior1; + return retval; + } + + scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_anisotropic_t) params) + { + ndf::Beckmann beckmann_ndf; + beckmann_ndf.ax = A.x; + beckmann_ndf.ay = A.y; + scalar_type NG = beckmann_ndf.template D(params.cache); + if (hlsl::any >(A > (vector2_type)numeric_limits::min)) + { + NG *= beckmann_ndf.template correlated(params._sample, params.interaction); + } + return NG; + } + spectral_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) { if (params.getNdotVUnclamped() > numeric_limits::min) @@ -298,30 +381,6 @@ struct SBeckmannBxDF return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); } - sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector2_type) u, NBL_REF_ARG(isocache_type) cache) - { - anisocache_type anisocache; - sample_type s = generate(anisotropic_interaction_type::create(interaction), u, anisocache); - cache = anisocache.iso_cache; - return s; - } - - scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) - { - SBeckmannDG1Query dg1_query; - dg1_query.maxNdotV = params.getNdotV(); - - scalar_type a2 = A.x*A.x; - ndf::Beckmann beckmann_ndf; - beckmann_ndf.a2 = a2; - dg1_query.ndf = beckmann_ndf.template D(params.cache); - - dg1_query.lambda_V = beckmann_ndf.LambdaC2(params.getNdotV2()); - - scalar_type dg1 = beckmann_ndf.template DG1 >(dg1_query); - onePlusLambda_V = dg1_query.getOnePlusLambdaV(); - return dg1; - } scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { SBeckmannDG1Query dg1_query; @@ -340,38 +399,12 @@ struct SBeckmannBxDF return dg1; } - scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) - { - scalar_type dummy; - return pdf(params, dummy); - } scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { scalar_type dummy; return pdf(params, dummy); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) - { - scalar_type onePlusLambda_V; - scalar_type _pdf = pdf(params, onePlusLambda_V); - - ndf::Beckmann beckmann_ndf; - spectral_type quo = (spectral_type)0.0; - if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) - { - beckmann_ndf.a2 = A.x*A.x; - SBeckmannG2overG1Query query; - query.transmitted = false; - query.onePlusLambda_V = onePlusLambda_V; - scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1, sample_type>(query, params._sample); - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); - const spectral_type reflectance = f(); - quo = reflectance * G2_over_G1; - } - - return quotient_pdf_type::create(quo, _pdf); - } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { scalar_type onePlusLambda_V; @@ -401,8 +434,16 @@ struct SBeckmannBxDF } -template -struct traits > +template +struct traits > +{ + NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; +}; + +template +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 3d4af89608..5db612aaae 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -110,43 +110,36 @@ struct SGGXDG1Query scalar_type G1_over_2NdotV; }; -template && surface_interactions::Isotropic && surface_interactions::Anisotropic && CreatableIsotropicMicrofacetCache && AnisotropicMicrofacetCache) -struct SGGXBxDF +template +struct SGGXAnisotropicBxDF; + +template) +struct SGGXIsotropicBxDF { - using this_t = SGGXBxDF; - using scalar_type = typename LS::scalar_type; - using ray_dir_info_type = typename LS::ray_dir_info_type; + using this_t = SGGXIsotropicBxDF; + using scalar_type = typename Config::scalar_type; using vector2_type = vector; using vector3_type = vector; using matrix2x3_type = matrix; + using ray_dir_info_type = typename Config::ray_dir_info_type; - using isotropic_interaction_type = Iso; - using anisotropic_interaction_type = Aniso; - using sample_type = LS; - using spectral_type = Spectrum; + using isotropic_interaction_type = typename Config::isotropic_interaction_type; + using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; + using sample_type = typename Config::sample_type; + using spectral_type = typename Config::spectral_type; using quotient_pdf_type = sampling::quotient_and_pdf; - using isocache_type = IsoCache; - using anisocache_type = AnisoCache; + using isocache_type = typename Config::isocache_type; + using anisocache_type = typename Config::anisocache_type; - using params_isotropic_t = GGXParams; - using params_anisotropic_t = GGXParams; + using params_isotropic_t = GGXParams; + using params_anisotropic_t = GGXParams; // iso static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) { this_t retval; - retval.A = vector2_type(A,A); - retval.ior0 = ior0; - retval.ior1 = ior1; - return retval; - } - - // aniso - static this_t create(scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) - { - this_t retval; - retval.A = vector2_type(ax,ay); + retval.A = A; retval.ior0 = ior0; retval.ior1 = ior1; return retval; @@ -154,7 +147,7 @@ struct SGGXBxDF scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_isotropic_t) params, BxDFClampMode _clamp) { - scalar_type a2 = A.x*A.x; + scalar_type a2 = A*A; ndf::GGX ggx_ndf; ggx_ndf.a2 = a2; ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; @@ -165,6 +158,103 @@ struct SGGXBxDF } return NG; } + + spectral_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) + { + if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) + { + const scalar_type scalar_part = __eval_DG_wo_clamps(params, BxDFClampMode::BCM_MAX); + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, params.getNdotL()); + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); + return f() * microfacet_transform; + } + else + return hlsl::promote(0.0); + } + + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector2_type) u, NBL_REF_ARG(isocache_type) cache) + { + SGGXAnisotropicBxDF ggx_aniso = SGGXAnisotropicBxDF::create(A, A, ior0, ior1); + anisocache_type anisocache; + sample_type s = ggx_aniso.generate(anisotropic_interaction_type::create(interaction), u, anisocache); + cache = anisocache.iso_cache; + return s; + } + + scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + { + SGGXDG1Query dg1_query; + const scalar_type a2 = A*A; + ndf::GGX ggx_ndf; + ggx_ndf.a2 = a2; + ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; + dg1_query.ndf = ggx_ndf.template D(params.cache); + + const scalar_type devsh_v = ggx_ndf.devsh_part(params.getNdotV2()); + dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(params.getNdotVUnclamped(), devsh_v); + + return ggx_ndf.template DG1 >(dg1_query); + } + + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + { + scalar_type _pdf = pdf(params); + + spectral_type quo = (spectral_type)0.0; + if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) + { + const scalar_type a2 = A*A; + ndf::GGX ggx_ndf; + ggx_ndf.a2 = a2; + ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; + + const scalar_type G2_over_G1 = ggx_ndf.template G2_over_G1(params._sample, params.interaction, false, BxDFClampMode::BCM_MAX); + + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); + const spectral_type reflectance = f(); + quo = reflectance * G2_over_G1; + } + + return quotient_pdf_type::create(quo, _pdf); + } + + scalar_type A; + spectral_type ior0, ior1; +}; + +template +NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration) +struct SGGXAnisotropicBxDF) > +{ + using this_t = SGGXAnisotropicBxDF; + using scalar_type = typename Config::scalar_type; + using vector2_type = vector; + using vector3_type = vector; + using matrix2x3_type = matrix; + using ray_dir_info_type = typename Config::ray_dir_info_type; + + using isotropic_interaction_type = typename Config::isotropic_interaction_type; + using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; + using sample_type = typename Config::sample_type; + using spectral_type = typename Config::spectral_type; + using quotient_pdf_type = sampling::quotient_and_pdf; + using isocache_type = typename Config::isocache_type; + using anisocache_type = typename Config::anisocache_type; + + using params_isotropic_t = GGXParams; + using params_anisotropic_t = GGXParams; + + + // aniso + static this_t create(scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) + { + this_t retval; + retval.A = vector2_type(ax,ay); + retval.ior0 = ior0; + retval.ior1 = ior1; + return retval; + } + scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_anisotropic_t) params, BxDFClampMode _clamp) { ndf::GGX ggx_ndf; @@ -179,18 +269,6 @@ struct SGGXBxDF return NG; } - spectral_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) - { - if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) - { - const scalar_type scalar_part = __eval_DG_wo_clamps(params, BxDFClampMode::BCM_MAX); - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, params.getNdotL()); - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); - return f() * microfacet_transform; - } - else - return hlsl::promote(0.0); - } spectral_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) { if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) @@ -239,28 +317,6 @@ struct SGGXBxDF return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); } - sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector2_type) u, NBL_REF_ARG(isocache_type) cache) - { - anisocache_type anisocache; - sample_type s = generate(anisotropic_interaction_type::create(interaction), u, anisocache); - cache = anisocache.iso_cache; - return s; - } - - scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) - { - SGGXDG1Query dg1_query; - const scalar_type a2 = A.x*A.x; - ndf::GGX ggx_ndf; - ggx_ndf.a2 = a2; - ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; - dg1_query.ndf = ggx_ndf.template D(params.cache); - - const scalar_type devsh_v = ggx_ndf.devsh_part(params.getNdotV2()); - dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(params.getNdotVUnclamped(), devsh_v); - - return ggx_ndf.template DG1 >(dg1_query); - } scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { SGGXDG1Query dg1_query; @@ -276,27 +332,6 @@ struct SGGXBxDF return ggx_ndf.template DG1 >(dg1_query); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) - { - scalar_type _pdf = pdf(params); - - spectral_type quo = (spectral_type)0.0; - if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) - { - const scalar_type a2 = A.x*A.x; - ndf::GGX ggx_ndf; - ggx_ndf.a2 = a2; - ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; - - const scalar_type G2_over_G1 = ggx_ndf.template G2_over_G1(params._sample, params.interaction, false, BxDFClampMode::BCM_MAX); - - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); - const spectral_type reflectance = f(); - quo = reflectance * G2_over_G1; - } - - return quotient_pdf_type::create(quo, _pdf); - } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { scalar_type _pdf = pdf(params); @@ -325,8 +360,16 @@ struct SGGXBxDF } -template -struct traits > +template +struct traits > +{ + NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; +}; + +template +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 92db440a14..2fee6a3a70 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -130,43 +130,38 @@ struct SBeckmannG2overG1Query scalar_type onePlusLambda_V; }; -template && surface_interactions::Isotropic && surface_interactions::Anisotropic && CreatableIsotropicMicrofacetCache && AnisotropicMicrofacetCache) -struct SBeckmannDielectricBxDF +template +struct SBeckmannDielectricAnisotropicBxDF; + +template) +struct SBeckmannDielectricIsotropicBxDF { - using this_t = SBeckmannDielectricBxDF; - using scalar_type = typename LS::scalar_type; - using ray_dir_info_type = typename LS::ray_dir_info_type; + using this_t = SBeckmannDielectricIsotropicBxDF; + using scalar_type = typename Config::scalar_type; using vector2_type = vector; using vector3_type = vector; using matrix3x3_type = matrix; using monochrome_type = vector; + using ray_dir_info_type = typename Config::ray_dir_info_type; - using isotropic_interaction_type = Iso; - using anisotropic_interaction_type = Aniso; - using sample_type = LS; - using spectral_type = Spectrum; + using isotropic_interaction_type = typename Config::isotropic_interaction_type; + using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; + using sample_type = typename Config::sample_type; + using spectral_type = typename Config::spectral_type; using quotient_pdf_type = sampling::quotient_and_pdf; - using isocache_type = IsoCache; - using anisocache_type = AnisoCache; - using brdf_type = reflection::SBeckmannBxDF; + using isocache_type = typename Config::isocache_type; + using anisocache_type = typename Config::anisocache_type; + using brdf_type = reflection::SBeckmannIsotropicBxDF; - using params_isotropic_t = BeckmannParams; - using params_anisotropic_t = BeckmannParams; + using params_isotropic_t = BeckmannParams; + using params_anisotropic_t = BeckmannParams; static this_t create(scalar_type eta, scalar_type A) { this_t retval; retval.eta = eta; - retval.A = vector2_type(A, A); - return retval; - } - - static this_t create(scalar_type eta, scalar_type ax, scalar_type ay) - { - this_t retval; - retval.eta = eta; - retval.A = vector2_type(ax, ay); + retval.A = A; return retval; } @@ -179,7 +174,7 @@ struct SBeckmannDielectricBxDF const bool transmitted = params.cache.isTransmission(); spectral_type dummyior; - brdf_type beckmann = brdf_type::create(A.x, dummyior, dummyior); + brdf_type beckmann = brdf_type::create(A, dummyior, dummyior); typename brdf_type::params_isotropic_t brdf_params = typename brdf_type::params_isotropic_t::create(params._sample, params.interaction, params.cache, params._clamp); const scalar_type scalar_part = beckmann.__eval_DG_wo_clamps(brdf_params); @@ -187,6 +182,100 @@ struct SBeckmannDielectricBxDF const scalar_type f = fresnel::Dielectric::__call(orientedEta2, hlsl::abs(params.getVdotH()))[0]; return hlsl::promote(f) * microfacet_transform; } + + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) + { + SBeckmannDielectricAnisotropicBxDF beckmann_aniso = SBeckmannDielectricAnisotropicBxDF::create(eta, A, A); + anisocache_type anisocache; + sample_type s = beckmann_aniso.generate(anisotropic_interaction_type::create(interaction), u, anisocache); + cache = anisocache.iso_cache; + return s; + } + + scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) + { + SBeckmannDG1Query dg1_query; + dg1_query.absNdotV = params.getNdotV(); + + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); + const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; + dg1_query.orientedEta = orientedEta.value[0]; + + dg1_query.transmitted = params.cache.isTransmission(); + + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; + + const scalar_type a2 = A*A; + ndf::Beckmann beckmann_ndf; + beckmann_ndf.a2 = a2; + dg1_query.ndf = beckmann_ndf.template D(params.cache); + + dg1_query.lambda_V = beckmann_ndf.LambdaC2(params.getNdotV2()); + + scalar_type dg1 = beckmann_ndf.template DG1, isocache_type>(dg1_query, params.cache); + onePlusLambda_V = dg1_query.getOnePlusLambdaV(); + + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, dg1_query.getTransmitted()) * dg1; + } + + scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + { + scalar_type dummy; + return pdf(params, dummy); + } + + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + { + scalar_type onePlusLambda_V; + scalar_type _pdf = pdf(params, onePlusLambda_V); + + ndf::Beckmann beckmann_ndf; + beckmann_ndf.a2 = A*A; + SBeckmannG2overG1Query query; + query.transmitted = params.getVdotH() * params.getLdotH() < 0.0; + query.onePlusLambda_V = onePlusLambda_V; + scalar_type quo = beckmann_ndf.template G2_over_G1, sample_type>(query, params._sample); + + return quotient_pdf_type::create(hlsl::promote(quo), _pdf); + } + + scalar_type A; + scalar_type eta; +}; + +template +NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration) +struct SBeckmannDielectricAnisotropicBxDF) > +{ + using this_t = SBeckmannDielectricAnisotropicBxDF; + using scalar_type = typename Config::scalar_type; + using vector2_type = vector; + using vector3_type = vector; + using matrix3x3_type = matrix; + using monochrome_type = vector; + using ray_dir_info_type = typename Config::ray_dir_info_type; + + using isotropic_interaction_type = typename Config::isotropic_interaction_type; + using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; + using sample_type = typename Config::sample_type; + using spectral_type = typename Config::spectral_type; + using quotient_pdf_type = sampling::quotient_and_pdf; + using isocache_type = typename Config::isocache_type; + using anisocache_type = typename Config::anisocache_type; + using brdf_type = reflection::SBeckmannAnisotropicBxDF; + + using params_isotropic_t = BeckmannParams; + using params_anisotropic_t = BeckmannParams; + + + static this_t create(scalar_type eta, scalar_type ax, scalar_type ay) + { + this_t retval; + retval.eta = eta; + retval.A = vector2_type(ax, ay); + return retval; + } + spectral_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) { fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); @@ -248,39 +337,6 @@ struct SBeckmannDielectricBxDF return generate(interaction, u, dummycache); } - sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) - { - anisocache_type anisocache; - sample_type s = generate(anisotropic_interaction_type::create(interaction), u, anisocache); - cache = anisocache.iso_cache; - return s; - } - - scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) - { - SBeckmannDG1Query dg1_query; - dg1_query.absNdotV = params.getNdotV(); - - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); - const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; - dg1_query.orientedEta = orientedEta.value[0]; - - dg1_query.transmitted = params.cache.isTransmission(); - - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; - - const scalar_type a2 = A.x*A.x; - ndf::Beckmann beckmann_ndf; - beckmann_ndf.a2 = a2; - dg1_query.ndf = beckmann_ndf.template D(params.cache); - - dg1_query.lambda_V = beckmann_ndf.LambdaC2(params.getNdotV2()); - - scalar_type dg1 = beckmann_ndf.template DG1, isocache_type>(dg1_query, params.cache); - onePlusLambda_V = dg1_query.getOnePlusLambdaV(); - - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, dg1_query.getTransmitted()) * dg1; - } scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { SBeckmannDG1Query dg1_query; @@ -307,31 +363,12 @@ struct SBeckmannDielectricBxDF return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, dg1_query.getTransmitted()) * dg1; } - scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) - { - scalar_type dummy; - return pdf(params, dummy); - } scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { scalar_type dummy; return pdf(params, dummy); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) - { - scalar_type onePlusLambda_V; - scalar_type _pdf = pdf(params, onePlusLambda_V); - - ndf::Beckmann beckmann_ndf; - beckmann_ndf.a2 = A.x*A.x; - SBeckmannG2overG1Query query; - query.transmitted = params.getVdotH() * params.getLdotH() < 0.0; - query.onePlusLambda_V = onePlusLambda_V; - scalar_type quo = beckmann_ndf.template G2_over_G1, sample_type>(query, params._sample); - - return quotient_pdf_type::create(hlsl::promote(quo), _pdf); - } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { scalar_type onePlusLambda_V; @@ -354,8 +391,16 @@ struct SBeckmannDielectricBxDF } -template -struct traits > +template +struct traits > +{ + NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; +}; + +template +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index e9782df034..a0ae026854 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -114,42 +114,37 @@ struct SGGXDG1Query scalar_type orientedEta; }; -template && surface_interactions::Isotropic && surface_interactions::Anisotropic && CreatableIsotropicMicrofacetCache && AnisotropicMicrofacetCache) -struct SGGXDielectricBxDF +template +struct SGGXDielectricAnisotropicBxDF; + +template) +struct SGGXDielectricIsotropicBxDF { - using this_t = SGGXDielectricBxDF; - using scalar_type = typename LS::scalar_type; - using ray_dir_info_type = typename LS::ray_dir_info_type; + using this_t = SGGXDielectricIsotropicBxDF; + using scalar_type = typename Config::scalar_type; using vector2_type = vector; using vector3_type = vector; using matrix3x3_type = matrix; using monochrome_type = vector; + using ray_dir_info_type = typename Config::ray_dir_info_type; - using isotropic_interaction_type = Iso; - using anisotropic_interaction_type = Aniso; - using sample_type = LS; - using spectral_type = Spectrum; + using isotropic_interaction_type = typename Config::isotropic_interaction_type; + using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; + using sample_type = typename Config::sample_type; + using spectral_type = typename Config::spectral_type; using quotient_pdf_type = sampling::quotient_and_pdf; - using isocache_type = IsoCache; - using anisocache_type = AnisoCache; - using brdf_type = reflection::SGGXBxDF; + using isocache_type = typename Config::isocache_type; + using anisocache_type = typename Config::anisocache_type; + using brdf_type = reflection::SGGXIsotropicBxDF; - using params_isotropic_t = GGXParams; - using params_anisotropic_t = GGXParams; + using params_isotropic_t = GGXParams; + using params_anisotropic_t = GGXParams; static this_t create(scalar_type eta, scalar_type A) { this_t retval; retval.eta = eta; - retval.A = vector2_type(A, A); - return retval; - } - - static this_t create(scalar_type eta, scalar_type ax, scalar_type ay) - { - this_t retval; - retval.eta = eta; - retval.A = vector2_type(ax, ay); + retval.A = A; return retval; } @@ -163,7 +158,7 @@ struct SGGXDielectricBxDF scalar_type NG_already_in_reflective_dL_measure; spectral_type dummyior; - brdf_type ggx = brdf_type::create(A.x, dummyior, dummyior); + brdf_type ggx = brdf_type::create(A, dummyior, dummyior); typename brdf_type::params_isotropic_t brdf_params = typename brdf_type::params_isotropic_t::create(params._sample, params.interaction, params.cache, params._clamp); NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(brdf_params, BxDFClampMode::BCM_ABS); @@ -171,6 +166,91 @@ struct SGGXDielectricBxDF const scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; return hlsl::promote(f) * microfacet_transform; } + + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) + { + SGGXDielectricAnisotropicBxDF ggx_aniso = SGGXDielectricAnisotropicBxDF::create(eta, A, A); + anisocache_type anisocache; + sample_type s = ggx_aniso.generate(anisotropic_interaction_type::create(interaction), u, anisocache); + cache = anisocache.iso_cache; + return s; + } + + scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + { + SGGXDG1Query dg1_query; + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); + const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; + dg1_query.orientedEta = orientedEta.value[0]; + + dg1_query.transmitted = params.cache.isTransmission(); + + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; + + scalar_type devsh_v; + const scalar_type a2 = A*A; + ndf::GGX ggx_ndf; + ggx_ndf.a2 = a2; + ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; + dg1_query.ndf = ggx_ndf.template D(params.cache); + + devsh_v = ggx_ndf.devsh_part(params.getNdotV2()); + dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(params.getNdotV(), devsh_v); + + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, dg1_query.transmitted) * ggx_ndf.template DG1, isocache_type>(dg1_query, params.cache); + } + + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + { + scalar_type _pdf = pdf(params); + const bool transmitted = params.cache.isTransmission(); + + const scalar_type a2 = A * A; + ndf::GGX ggx_ndf; + ggx_ndf.a2 = a2; + ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; + scalar_type quo; + quo = ggx_ndf.template G2_over_G1(params._sample, params.interaction, transmitted, BxDFClampMode::BCM_ABS); + + return quotient_pdf_type::create(hlsl::promote(quo), _pdf); + } + + scalar_type A; + scalar_type eta; +}; + +template +NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration) +struct SGGXDielectricAnisotropicBxDF) > +{ + using this_t = SGGXDielectricAnisotropicBxDF; + using scalar_type = typename Config::scalar_type; + using vector2_type = vector; + using vector3_type = vector; + using matrix3x3_type = matrix; + using monochrome_type = vector; + using ray_dir_info_type = typename Config::ray_dir_info_type; + + using isotropic_interaction_type = typename Config::isotropic_interaction_type; + using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; + using sample_type = typename Config::sample_type; + using spectral_type = typename Config::spectral_type; + using quotient_pdf_type = sampling::quotient_and_pdf; + using isocache_type = typename Config::isocache_type; + using anisocache_type = typename Config::anisocache_type; + using brdf_type = reflection::SGGXAnisotropicBxDF; + + using params_isotropic_t = GGXParams; + using params_anisotropic_t = GGXParams; + + static this_t create(scalar_type eta, scalar_type ax, scalar_type ay) + { + this_t retval; + retval.eta = eta; + retval.A = vector2_type(ax, ay); + return retval; + } + spectral_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) { fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); @@ -233,37 +313,6 @@ struct SGGXDielectricBxDF return generate(interaction, u, dummycache); } - sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) - { - anisocache_type anisocache; - sample_type s = generate(anisotropic_interaction_type::create(interaction), u, anisocache); - cache = anisocache.iso_cache; - return s; - } - - scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) - { - SGGXDG1Query dg1_query; - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); - const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; - dg1_query.orientedEta = orientedEta.value[0]; - - dg1_query.transmitted = params.cache.isTransmission(); - - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; - - scalar_type devsh_v; - const scalar_type a2 = A.x*A.x; - ndf::GGX ggx_ndf; - ggx_ndf.a2 = a2; - ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; - dg1_query.ndf = ggx_ndf.template D(params.cache); - - devsh_v = ggx_ndf.devsh_part(params.getNdotV2()); - dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(params.getNdotV(), devsh_v); - - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, dg1_query.transmitted) * ggx_ndf.template DG1, isocache_type>(dg1_query, params.cache); - } scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { SGGXDG1Query dg1_query; @@ -288,20 +337,6 @@ struct SGGXDielectricBxDF return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, dg1_query.transmitted) * ggx_ndf.template DG1, anisocache_type>(dg1_query, params.cache); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) - { - scalar_type _pdf = pdf(params); - const bool transmitted = params.cache.isTransmission(); - - const scalar_type a2 = A.x * A.x; - ndf::GGX ggx_ndf; - ggx_ndf.a2 = a2; - ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; - scalar_type quo; - quo = ggx_ndf.template G2_over_G1(params._sample, params.interaction, transmitted, BxDFClampMode::BCM_ABS); - - return quotient_pdf_type::create(hlsl::promote(quo), _pdf); - } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { scalar_type _pdf = pdf(params); @@ -323,8 +358,16 @@ struct SGGXDielectricBxDF } -template -struct traits > +template +struct traits > +{ + NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; + NBL_CONSTEXPR_STATIC_INLINE bool clampNdotL = true; +}; + +template +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; From 2a2bd22646329a66f1896096293301e2576585b3 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 30 Jul 2025 14:49:37 +0700 Subject: [PATCH 152/188] a number of minor fixes --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 8 ++++---- include/nbl/builtin/hlsl/bxdf/config.hlsl | 10 ++++------ include/nbl/builtin/hlsl/bxdf/fresnel.hlsl | 7 +++---- include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl | 4 ++-- include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 2 +- .../nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl | 2 +- .../nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl | 2 +- .../nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl | 2 +- include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl | 4 ++-- .../nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl | 2 +- .../hlsl/bxdf/transmission/smooth_dielectric.hlsl | 4 ++-- 11 files changed, 22 insertions(+), 25 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index e36fd9d3c2..14e1081ff6 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -634,7 +634,7 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getBdotH()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((cache.getBdotH2()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(V,V)), ::nbl::hlsl::is_same_v, T)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V,b0,rcp_eta)), ::nbl::hlsl::is_same_v, T)) + // ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V,b0,rcp_eta)), ::nbl::hlsl::is_same_v, T)) // TODO: refuses to compile when arg4 is rcp_eta for some reason, eta is fine ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createForReflection(V,V,pNdotL)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template createForReflection > >,SLightSample > >(aniso,_sample)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(V,V,V,V,V,eta,V)), ::nbl::hlsl::is_same_v, T)) @@ -682,11 +682,11 @@ struct SAnisotropicMicrofacetCache NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpOrientedEta ) { - this_t retval = create(tangentSpaceV,tangentSpaceH); + this_t retval = createForReflection(tangentSpaceV,tangentSpaceH); if (transmitted) { - const scalar_type VdotH = retval.iso_cache.VdotH; - retval.iso_cache.LdotH = refract_compute_NdotT(VdotH<0.0,VdotH*VdotH,rcpOrientedEta.value2); + Refract r = Refract::create(tangentSpaceV, tangentSpaceH); + retval.iso_cache.LdotH = r.getNdotT(rcpOrientedEta.value2[0]); } return retval; diff --git a/include/nbl/builtin/hlsl/bxdf/config.hlsl b/include/nbl/builtin/hlsl/bxdf/config.hlsl index 390dae9239..06d1d335a4 100644 --- a/include/nbl/builtin/hlsl/bxdf/config.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/config.hlsl @@ -103,10 +103,8 @@ template -NBL_PARTIAL_REQ_TOP(LightSample && surface_interactions::Isotropic && !surface_interactions::Anisotropic && - CreatableIsotropicMicrofacetCache && !AnisotropicMicrofacetCache && concepts::FloatingPointLikeVectorial) -struct SMicrofacetConfiguration && surface_interactions::Isotropic && !surface_interactions::Anisotropic && - CreatableIsotropicMicrofacetCache && !AnisotropicMicrofacetCache && concepts::FloatingPointLikeVectorial) > +NBL_PARTIAL_REQ_TOP(LightSample && surface_interactions::Isotropic && !surface_interactions::Anisotropic && CreatableIsotropicMicrofacetCache && !AnisotropicMicrofacetCache && concepts::FloatingPointLikeVectorial) +struct SMicrofacetConfiguration && surface_interactions::Isotropic && !surface_interactions::Anisotropic && CreatableIsotropicMicrofacetCache && !AnisotropicMicrofacetCache && concepts::FloatingPointLikeVectorial) > { NBL_CONSTEXPR_STATIC_INLINE bool IsAnisotropic = false; @@ -118,12 +116,12 @@ struct SMicrofacetConfiguration; using isotropic_interaction_type = Interaction; - using anisotropic_interaction_type = surface_interactions::SAnisotropic; + using anisotropic_interaction_type = surface_interactions::SAnisotropic; using sample_type = LS; using spectral_type = Spectrum; using quotient_pdf_type = sampling::quotient_and_pdf; using isocache_type = MicrofacetCache; - using anisocache_type = SAnisotropicMicrofacetCache; + using anisocache_type = SAnisotropicMicrofacetCache; }; template diff --git a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl index 25a1eba175..323687a51e 100644 --- a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl @@ -49,7 +49,7 @@ struct OrientedEtaRcps OrientedEtaRcps retval; const bool backside = NdotI < scalar_type(0.0); const T rcpEta = hlsl::promote(1.0) / eta; - retval.value = backside ? eta : rcpEta; + retval.value = hlsl::mix(rcpEta, eta, backside); retval.value2 = retval.value * retval.value; return retval; } @@ -76,8 +76,8 @@ struct OrientedEtas OrientedEtas retval; const bool backside = NdotI < scalar_type(0.0); const T rcpEta = hlsl::promote(1.0) / eta; - retval.value = backside ? rcpEta : eta; - retval.rcp = backside ? eta : rcpEta; + retval.value = hlsl::mix(eta, rcpEta, backside); + retval.rcp = hlsl::mix(rcpEta, eta, backside); return retval; } @@ -208,7 +208,6 @@ struct Refract { using this_t = Refract; using vector_type = vector; - using monochrome_type = vector; using scalar_type = T; static this_t create(NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 7a689ded51..5e5c03189e 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -142,7 +142,7 @@ struct SBeckmannIsotropicBxDF using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; using sample_type = typename Config::sample_type; using spectral_type = typename Config::spectral_type; - using quotient_pdf_type = sampling::quotient_and_pdf; + using quotient_pdf_type = typename Config::quotient_pdf_type; using isocache_type = typename Config::isocache_type; using anisocache_type = typename Config::anisocache_type; @@ -257,7 +257,7 @@ struct SBeckmannAnisotropicBxDF; + using quotient_pdf_type = typename Config::quotient_pdf_type; using isocache_type = typename Config::isocache_type; using anisocache_type = typename Config::anisocache_type; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 5db612aaae..1928e37717 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -127,7 +127,7 @@ struct SGGXIsotropicBxDF using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; using sample_type = typename Config::sample_type; using spectral_type = typename Config::spectral_type; - using quotient_pdf_type = sampling::quotient_and_pdf; + using quotient_pdf_type = typename Config::quotient_pdf_type; using isocache_type = typename Config::isocache_type; using anisocache_type = typename Config::anisocache_type; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl index c6425c5104..8629bc0cb9 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl @@ -92,7 +92,7 @@ struct SLambertianBxDF using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; using sample_type = typename Config::sample_type; using spectral_type = typename Config::spectral_type; - using quotient_pdf_type = sampling::quotient_and_pdf; + using quotient_pdf_type = typename Config::quotient_pdf_type; using params_isotropic_t = LambertianParams; using params_anisotropic_t = LambertianParams; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl index 97418c665c..aa29127dc1 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl @@ -95,7 +95,7 @@ struct SOrenNayarBxDF using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; using sample_type = typename Config::sample_type; using spectral_type = typename Config::spectral_type; - using quotient_pdf_type = sampling::quotient_and_pdf; + using quotient_pdf_type = typename Config::quotient_pdf_type; using params_isotropic_t = OrenNayarParams; using params_anisotropic_t = OrenNayarParams; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 2fee6a3a70..bfb147122c 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -148,7 +148,7 @@ struct SBeckmannDielectricIsotropicBxDF using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; using sample_type = typename Config::sample_type; using spectral_type = typename Config::spectral_type; - using quotient_pdf_type = sampling::quotient_and_pdf; + using quotient_pdf_type = typename Config::quotient_pdf_type; using isocache_type = typename Config::isocache_type; using anisocache_type = typename Config::anisocache_type; using brdf_type = reflection::SBeckmannIsotropicBxDF; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index a0ae026854..ba3c6b38d3 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -132,7 +132,7 @@ struct SGGXDielectricIsotropicBxDF using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; using sample_type = typename Config::sample_type; using spectral_type = typename Config::spectral_type; - using quotient_pdf_type = sampling::quotient_and_pdf; + using quotient_pdf_type = typename Config::quotient_pdf_type; using isocache_type = typename Config::isocache_type; using anisocache_type = typename Config::anisocache_type; using brdf_type = reflection::SGGXIsotropicBxDF; @@ -235,7 +235,7 @@ struct SGGXDielectricAnisotropicBxDF; + using quotient_pdf_type = typename Config::quotient_pdf_type; using isocache_type = typename Config::isocache_type; using anisocache_type = typename Config::anisocache_type; using brdf_type = reflection::SGGXAnisotropicBxDF; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl index 3be9df6996..5eb9e4d599 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl @@ -93,7 +93,7 @@ struct SLambertianBxDF using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; using sample_type = typename Config::sample_type; using spectral_type = typename Config::spectral_type; - using quotient_pdf_type = sampling::quotient_and_pdf; + using quotient_pdf_type = typename Config::quotient_pdf_type; using params_isotropic_t = LambertianParams; using params_anisotropic_t = LambertianParams; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index 1ec7d3d15a..4c59299171 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -94,7 +94,7 @@ struct SSmoothDielectricBxDF using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; using sample_type = typename Config::sample_type; using spectral_type = typename Config::spectral_type; - using quotient_pdf_type = sampling::quotient_and_pdf; + using quotient_pdf_type = typename Config::quotient_pdf_type; using params_isotropic_t = SmoothDielectricParams; using params_anisotropic_t = SmoothDielectricParams; @@ -201,7 +201,7 @@ struct SSmoothThinDielectricBxDF using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; using sample_type = typename Config::sample_type; using spectral_type = typename Config::spectral_type; - using quotient_pdf_type = sampling::quotient_and_pdf; + using quotient_pdf_type = typename Config::quotient_pdf_type; using params_isotropic_t = SmoothDielectricParams; using params_anisotropic_t = SmoothDielectricParams; From e81cfb485a596c73ad81836fc8e81927dca75f43 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 30 Jul 2025 14:52:56 +0700 Subject: [PATCH 153/188] latest example --- examples_tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples_tests b/examples_tests index 1aa3448928..7d42ed68b2 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 1aa344892888dfe6e34a53c945fa7b177821f73b +Subproject commit 7d42ed68b243eeae86e10e2ed6482aa9afc8a5b4 From 0eb30c45084274261f7fd5f1d86532679620823f Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 31 Jul 2025 15:34:36 +0700 Subject: [PATCH 154/188] use stirling approx only in bxdf beta func and lancosz for hlsl lgamma/beta, adjust thresholds --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 34 ++++++++++++++++------ include/nbl/builtin/hlsl/tgmath.hlsl | 2 +- include/nbl/builtin/hlsl/tgmath/impl.hlsl | 35 +++++++---------------- 3 files changed, 37 insertions(+), 34 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 14e1081ff6..4a84dfbc22 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -885,36 +885,52 @@ using quotient_and_pdf_scalar = sampling::quotient_and_pdf, P> ; template using quotient_and_pdf_rgb = sampling::quotient_and_pdf, P> ; -// beta function specialized for Cook Torrance BTDFs namespace impl { template && sizeof(T)<8) struct beta { + // beta function specialized for Cook Torrance BTDFs + // uses modified Stirling's approximation for log2 up to 6th polynomial static T __series_part(T x) { - const T r = T(1.0) / x; - const T r2 = r * r; - return (T(1.0/360.0) * r2 + T(1.0/12.0)) * r - x; + const T r = T(1.0) / x; + const T r2 = r * r; + T ser = T(0.0); + if (sizeof(T) > 2) + { + ser = -T(691.0/360360.0) * r2 + T(5.0/5940.0); + ser = ser * r2 - T(1.0/1680.0); + ser = ser * r2 + T(1.0/1260.0); + } + ser = ser * r2 - T(1.0/360.0); + ser = ser * r2 + T(1.0/12.0); + return ser * r - x; } // removed values that cancel out in beta - static T __call(T x, T y) - { + static T __call(T x, T y) + { + assert(v1 >= 1.0 && v2 >= 1.0); + + const T thresholds[4] = { 0, 5e5, 1e6, 1e15 }; // threshold values gotten from testing when the function returns nan/inf/1 + if (x+y > thresholds[mpl::find_lsb_v]) + return T(0.0); + const T l2x = hlsl::log2(x); const T l2y = hlsl::log2(y); const T l2xy = hlsl::log2(x+y); - return hlsl::exp2((x - T(0.5)) * l2x + (y - T(0.5)) * l2y - (x + y - T(0.5)) * l2xy + + return hlsl::exp2((x - T(0.5)) * l2x + (y - T(0.5)) * l2y - (x + y - T(0.5)) * l2xy + numbers::inv_ln2 * (__series_part(x) + __series_part(y) - __series_part(x+y)) + T(1.32574806473616)); - } + } }; } template T beta(NBL_CONST_REF_ARG(T) x, NBL_CONST_REF_ARG(T) y) { - return impl::beta::__call(x, y); + return impl::beta::__call(x, y)/impl::beta::__call(1.0, 1.0); } } diff --git a/include/nbl/builtin/hlsl/tgmath.hlsl b/include/nbl/builtin/hlsl/tgmath.hlsl index 9505c17eb4..04765f3ba7 100644 --- a/include/nbl/builtin/hlsl/tgmath.hlsl +++ b/include/nbl/builtin/hlsl/tgmath.hlsl @@ -246,7 +246,7 @@ inline T lgamma(NBL_CONST_REF_ARG(T) val) template inline T beta(NBL_CONST_REF_ARG(T) v1, NBL_CONST_REF_ARG(T) v2) { - return tgmath_impl::beta_helper::__call(v1, v2); + return tgmath_impl::beta_helper::__call(v1, v2)/tgmath_impl::beta_helper::__call(T(1.0), T(1.0)); // ensure beta(1,1)==1 } } diff --git a/include/nbl/builtin/hlsl/tgmath/impl.hlsl b/include/nbl/builtin/hlsl/tgmath/impl.hlsl index 9af1fb0ebd..d4a6430052 100644 --- a/include/nbl/builtin/hlsl/tgmath/impl.hlsl +++ b/include/nbl/builtin/hlsl/tgmath/impl.hlsl @@ -533,31 +533,14 @@ struct erfInv_helper -NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar && sizeof(T)<8) -struct l2gamma_helper && sizeof(T)<8) > -{ - // modified Stirling's approximation for log2 up to 3rd polynomial - static T __call(T x) - { - const T thresholds[4] = { 0, 5e4, 1e19, 1e19 }; // threshold values gotten from testing when the function returns nan/inf/nonsense - if (x > thresholds[mpl::find_lsb_v]) - return bit_cast(numeric_limits::infinity); - - const T l2x = log2_helper::__call(x); - const T r = T(1.0) / x; - const T r2 = r * r; - return (x - T(0.5)) * l2x + T(1.32574806473616) + numbers::inv_ln2 * ((T(1.0/360.0) * r2 + T(1.0/12.0)) * r - x); - } -}; - -template -NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar && 8<=sizeof(T)) -struct l2gamma_helper && 8<=sizeof(T)) > +NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) +struct l2gamma_helper) > { // implementation derived from Numerical Recipes in C, transformed for log2 static T __call(T x) { - const T thresholds[4] = { 0, 7e4, 1e19, 1e19 }; // threshold values gotten from testing when the function returns nan/inf/nonsense + // TODO: need a way to silence warning about thresholds being too large for T + const T thresholds[4] = { 0, 5e4, 1e36, 1e305 }; // threshold values gotten from testing when the function returns nan/inf if (x > thresholds[mpl::find_lsb_v]) return bit_cast(numeric_limits::infinity); @@ -570,8 +553,11 @@ struct l2gamma_helper && ser += T(-86.50532032941677) / ++b; ser += T(24.01409824083091) / ++b; ser += T(-1.231739572450155) / ++b; - ser += T(0.1208650973866179e-2) / ++b; - ser += T(-0.5395239384953e-5) / ++b; + if (sizeof(T) > 4) + { + ser += T(0.1208650973866179e-2) / ++b; + ser += T(-0.5395239384953e-5) / ++b; + } return -a + log2_helper::__call(T(2.5066282746310005) * ser / x); } }; @@ -598,7 +584,8 @@ struct beta_helper) > { assert(v1 >= 1.0 && v2 >= 1.0); - if (v1+v2 > 1e6) + const T thresholds[4] = { 0, 2e4, 1e6, 1e15 }; // threshold values gotten from testing when the function returns nan/inf/1 + if (v1+v2 > thresholds[mpl::find_lsb_v]) return T(0.0); return exp2_helper::__call(l2gamma_helper::__call(v1) + l2gamma_helper::__call(v2) - l2gamma_helper::__call(v1+v2)); From fad651e2c46c24e1204d07315cb07a1f30fc6ed9 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 1 Aug 2025 16:43:54 +0700 Subject: [PATCH 155/188] various minor fixes, ggx ndf devsh into query --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 15 ++-- include/nbl/builtin/hlsl/bxdf/config.hlsl | 15 +++- include/nbl/builtin/hlsl/bxdf/fresnel.hlsl | 1 + include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 74 +++++++++++++------ .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 42 ++++++++++- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 34 ++++++++- include/nbl/builtin/hlsl/tgmath/impl.hlsl | 2 - 7 files changed, 141 insertions(+), 42 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 4a84dfbc22..bc3b250d5c 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -583,18 +583,17 @@ struct SIsotropicMicrofacetCache return create(interaction,_sample,orientedEtas,dummy); } - scalar_type getVdotH() NBL_CONST_MEMBER_FUNC - { - assert(VdotH >= scalar_type(0.0)); - return VdotH; - } - bool isTransmission() NBL_CONST_MEMBER_FUNC { return getVdotHLdotH() < scalar_type(0.0); } scalar_type getVdotL() NBL_CONST_MEMBER_FUNC { return VdotL; } + scalar_type getVdotH() NBL_CONST_MEMBER_FUNC { return VdotH; } scalar_type getLdotH() NBL_CONST_MEMBER_FUNC { return LdotH; } scalar_type getVdotHLdotH() NBL_CONST_MEMBER_FUNC { return getVdotH() * getLdotH(); } - scalar_type getNdotH() NBL_CONST_MEMBER_FUNC { return NdotH; } + scalar_type getNdotH() NBL_CONST_MEMBER_FUNC + { + assert(NdotH >= scalar_type(0.0)); + return NdotH; + } scalar_type getNdotH2() NBL_CONST_MEMBER_FUNC { return NdotH2; } scalar_type VdotL; @@ -911,7 +910,7 @@ struct beta // removed values that cancel out in beta static T __call(T x, T y) { - assert(v1 >= 1.0 && v2 >= 1.0); + assert(x >= T(0.999) && y >= T(0.999)); const T thresholds[4] = { 0, 5e5, 1e6, 1e15 }; // threshold values gotten from testing when the function returns nan/inf/1 if (x+y > thresholds[mpl::find_lsb_v]) diff --git a/include/nbl/builtin/hlsl/bxdf/config.hlsl b/include/nbl/builtin/hlsl/bxdf/config.hlsl index 06d1d335a4..3d8bed31a5 100644 --- a/include/nbl/builtin/hlsl/bxdf/config.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/config.hlsl @@ -13,6 +13,7 @@ namespace hlsl namespace bxdf { +// TODO should just check `is_base_of` (but not possible right now cause of DXC limitations) namespace config_concepts { #define NBL_CONCEPT_NAME BasicConfiguration @@ -102,9 +103,12 @@ struct SConfiguration struct SMicrofacetConfiguration; +#define MICROFACET_CONF_ISO LightSample && surface_interactions::Isotropic && !surface_interactions::Anisotropic && CreatableIsotropicMicrofacetCache && !AnisotropicMicrofacetCache && concepts::FloatingPointLikeVectorial + template -NBL_PARTIAL_REQ_TOP(LightSample && surface_interactions::Isotropic && !surface_interactions::Anisotropic && CreatableIsotropicMicrofacetCache && !AnisotropicMicrofacetCache && concepts::FloatingPointLikeVectorial) -struct SMicrofacetConfiguration && surface_interactions::Isotropic && !surface_interactions::Anisotropic && CreatableIsotropicMicrofacetCache && !AnisotropicMicrofacetCache && concepts::FloatingPointLikeVectorial) > +NBL_PARTIAL_REQ_TOP(MICROFACET_CONF_ISO) +struct SMicrofacetConfiguration +#undef MICROFACET_CONF_ISO { NBL_CONSTEXPR_STATIC_INLINE bool IsAnisotropic = false; @@ -124,9 +128,12 @@ struct SMicrofacetConfiguration; }; +#define MICROFACET_CONF_ANISO LightSample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache && concepts::FloatingPointLikeVectorial + template -NBL_PARTIAL_REQ_TOP(LightSample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache && concepts::FloatingPointLikeVectorial) -struct SMicrofacetConfiguration && surface_interactions::Anisotropic && AnisotropicMicrofacetCache && concepts::FloatingPointLikeVectorial) > +NBL_PARTIAL_REQ_TOP(MICROFACET_CONF_ANISO) +struct SMicrofacetConfiguration +#undef MICROFACET_CONF_ANISO { NBL_CONSTEXPR_STATIC_INLINE bool IsAnisotropic = true; diff --git a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl index 323687a51e..472576bfb0 100644 --- a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl @@ -9,6 +9,7 @@ #include "nbl/builtin/hlsl/concepts.hlsl" #include "nbl/builtin/hlsl/numbers.hlsl" #include "nbl/builtin/hlsl/complex.hlsl" +#include "nbl/builtin/hlsl/tgmath.hlsl" #include "nbl/builtin/hlsl/vector_utils/vector_traits.hlsl" namespace nbl diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index de05c01ed0..9f88c48922 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -47,6 +47,22 @@ NBL_CONCEPT_END( ); #undef query #include + +#define NBL_CONCEPT_NAME G2XQuery +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (query, T) +NBL_CONCEPT_BEGIN(1) +#define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getDevshV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getDevshL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getTransmitted()), ::nbl::hlsl::is_same_v, bool)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getClampMode()), ::nbl::hlsl::is_same_v, BxDFClampMode)) +); +#undef query +#include } template @@ -104,34 +120,41 @@ struct GGX) > return scalar_type(1.0) / (absNdotX + devsh_part); } - template && surface_interactions::Isotropic) - scalar_type correlated_wo_numerator(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, BxDFClampMode _clamp) + template && LightSample && surface_interactions::Isotropic) + scalar_type correlated_wo_numerator(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { + BxDFClampMode _clamp = query.getClampMode(); + assert(_clamp != BxDFClampMode::BCM_NONE); + // numerator is 2 * NdotV * NdotL, we factor out 4 * NdotV * NdotL, hence 0.5 - scalar_type Vterm = _sample.getNdotL(_clamp) * devsh_part(interaction.getNdotV2()); - scalar_type Lterm = interaction.getNdotV(_clamp) * devsh_part(_sample.getNdotL2()); + scalar_type Vterm = _sample.getNdotL(_clamp) * query.getDevshV(); + scalar_type Lterm = interaction.getNdotV(_clamp) * query.getDevshL(); return scalar_type(0.5) / (Vterm + Lterm); } - template && surface_interactions::Isotropic) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, bool transmitted, BxDFClampMode _clamp) + template && LightSample && surface_interactions::Isotropic) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { + BxDFClampMode _clamp = query.getClampMode(); + assert(_clamp != BxDFClampMode::BCM_NONE); + scalar_type G2_over_G1; scalar_type NdotV = interaction.getNdotV(_clamp); scalar_type NdotL = _sample.getNdotL(_clamp); - if (transmitted) + scalar_type devsh_v = query.getDevshV(); + scalar_type devsh_l = query.getDevshL(); + if (query.getTransmitted()) { if (NdotV < 1e-7 || NdotL < 1e-7) return 0.0; - scalar_type onePlusLambda_V = scalar_type(0.5) * (devsh_part(interaction.getNdotV2()) / NdotV + scalar_type(1.0)); - scalar_type onePlusLambda_L = scalar_type(0.5) * (devsh_part(_sample.getNdotL2()) / NdotL + scalar_type(1.0)); + scalar_type onePlusLambda_V = scalar_type(0.5) * (devsh_v / NdotV + scalar_type(1.0)); + scalar_type onePlusLambda_L = scalar_type(0.5) * (devsh_l / NdotL + scalar_type(1.0)); G2_over_G1 = bxdf::beta(onePlusLambda_L, onePlusLambda_V) * onePlusLambda_V; } else { - scalar_type devsh_v = devsh_part(interaction.getNdotV2()); G2_over_G1 = NdotL * (devsh_v + NdotV); // alternative `Vterm+NdotL*NdotV /// NdotL*NdotV could come as a parameter - G2_over_G1 /= NdotV * devsh_part(_sample.getNdotL2()) + NdotL * devsh_v; + G2_over_G1 /= NdotV * devsh_l + NdotL * devsh_v; } return G2_over_G1; @@ -195,33 +218,40 @@ struct GGX) > return scalar_type(1.0) / (NdotX + devsh_part); } - template && surface_interactions::Anisotropic) - scalar_type correlated_wo_numerator(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, BxDFClampMode _clamp) + template && LightSample && surface_interactions::Anisotropic) + scalar_type correlated_wo_numerator(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { - scalar_type Vterm = _sample.getNdotL(_clamp) * devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); - scalar_type Lterm = interaction.getNdotV(_clamp) * devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); + BxDFClampMode _clamp = query.getClampMode(); + assert(_clamp != BxDFClampMode::BCM_NONE); + + scalar_type Vterm = _sample.getNdotL(_clamp) * query.getDevshV(); + scalar_type Lterm = interaction.getNdotV(_clamp) * query.getDevshL(); return scalar_type(0.5) / (Vterm + Lterm); } - template && surface_interactions::Anisotropic) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, bool transmitted, BxDFClampMode _clamp) + template && LightSample && surface_interactions::Anisotropic) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { + BxDFClampMode _clamp = query.getClampMode(); + assert(_clamp != BxDFClampMode::BCM_NONE); + scalar_type G2_over_G1; scalar_type NdotV = interaction.getNdotV(_clamp); scalar_type NdotL = _sample.getNdotL(_clamp); - if (transmitted) + scalar_type devsh_v = query.getDevshV(); + scalar_type devsh_l = query.getDevshL(); + if (query.getTransmitted()) { if (NdotV < 1e-7 || NdotL < 1e-7) return 0.0; - scalar_type onePlusLambda_V = scalar_type(0.5) * (devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()) / NdotV + scalar_type(1.0)); - scalar_type onePlusLambda_L = scalar_type(0.5) * (devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()) / NdotL + scalar_type(1.0)); + scalar_type onePlusLambda_V = scalar_type(0.5) * (devsh_v / NdotV + scalar_type(1.0)); + scalar_type onePlusLambda_L = scalar_type(0.5) * (devsh_l / NdotL + scalar_type(1.0)); G2_over_G1 = bxdf::beta(onePlusLambda_L, onePlusLambda_V) * onePlusLambda_V; } else { - scalar_type devsh_v = devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); G2_over_G1 = NdotL * (devsh_v + NdotV); - G2_over_G1 /= NdotV * devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()) + NdotL * devsh_v; + G2_over_G1 /= NdotV * devsh_l + NdotL * devsh_v; } return G2_over_G1; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 1928e37717..4fa449074a 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -110,6 +110,22 @@ struct SGGXDG1Query scalar_type G1_over_2NdotV; }; +template +struct SGGXG2XQuery +{ + using scalar_type = T; + + scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } + scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } + bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } + BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } + + scalar_type devsh_v; + scalar_type devsh_l; + bool transmitted; + BxDFClampMode _clamp; +}; + template struct SGGXAnisotropicBxDF; @@ -154,7 +170,11 @@ struct SGGXIsotropicBxDF scalar_type NG = ggx_ndf.template D(params.cache); if (a2 > numeric_limits::min) { - NG *= ggx_ndf.template correlated_wo_numerator(params._sample, params.interaction, _clamp); + SGGXG2XQuery g2_query; + g2_query.devsh_v = ggx_ndf.devsh_part(params.interaction.getNdotV2()); + g2_query.devsh_l = ggx_ndf.devsh_part(params._sample.getNdotL2()); + g2_query._clamp = _clamp; + NG *= ggx_ndf.template correlated_wo_numerator, sample_type, isotropic_interaction_type>(g2_query, params._sample, params.interaction); } return NG; } @@ -208,7 +228,12 @@ struct SGGXIsotropicBxDF ggx_ndf.a2 = a2; ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; - const scalar_type G2_over_G1 = ggx_ndf.template G2_over_G1(params._sample, params.interaction, false, BxDFClampMode::BCM_MAX); + SGGXG2XQuery g2_query; + g2_query.devsh_v = ggx_ndf.devsh_part(params.interaction.getNdotV2()); + g2_query.devsh_l = ggx_ndf.devsh_part(params._sample.getNdotL2()); + g2_query.transmitted = false; + g2_query._clamp = BxDFClampMode::BCM_MAX; + const scalar_type G2_over_G1 = ggx_ndf.template G2_over_G1, sample_type, isotropic_interaction_type, isocache_type>(g2_query, params._sample, params.interaction); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); @@ -264,7 +289,11 @@ struct SGGXAnisotropicBxDF(params.cache); if (any >(A > (vector2_type)numeric_limits::min)) { - NG *= ggx_ndf.template correlated_wo_numerator(params._sample, params.interaction, _clamp); + SGGXG2XQuery g2_query; + g2_query.devsh_v = ggx_ndf.devsh_part(params.interaction.getTdotV2(), params.interaction.getBdotV2(), params.interaction.getNdotV2()); + g2_query.devsh_l = ggx_ndf.devsh_part(params._sample.getTdotL2(), params._sample.getBdotL2(), params._sample.getNdotL2()); + g2_query._clamp = _clamp; + NG *= ggx_ndf.template correlated_wo_numerator, sample_type, anisotropic_interaction_type>(g2_query, params._sample, params.interaction); } return NG; } @@ -344,7 +373,12 @@ struct SGGXAnisotropicBxDF(params._sample, params.interaction, false, BxDFClampMode::BCM_MAX); + SGGXG2XQuery g2_query; + g2_query.devsh_v = ggx_ndf.devsh_part(params.interaction.getTdotV2(), params.interaction.getBdotV2(), params.interaction.getNdotV2()); + g2_query.devsh_l = ggx_ndf.devsh_part(params._sample.getTdotL2(), params._sample.getBdotL2(), params._sample.getNdotL2()); + g2_query.transmitted = false; + g2_query._clamp = BxDFClampMode::BCM_MAX; + const scalar_type G2_over_G1 = ggx_ndf.template G2_over_G1, sample_type, anisotropic_interaction_type, anisocache_type>(g2_query, params._sample, params.interaction); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index ba3c6b38d3..625d973442 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -114,6 +114,22 @@ struct SGGXDG1Query scalar_type orientedEta; }; +template +struct SGGXG2XQuery +{ + using scalar_type = T; + + scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } + scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } + bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } + BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } + + scalar_type devsh_v; + scalar_type devsh_l; + bool transmitted; + BxDFClampMode _clamp; +}; + template struct SGGXDielectricAnisotropicBxDF; @@ -209,8 +225,15 @@ struct SGGXDielectricIsotropicBxDF ndf::GGX ggx_ndf; ggx_ndf.a2 = a2; ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; + + SGGXG2XQuery g2_query; + g2_query.devsh_v = ggx_ndf.devsh_part(params.interaction.getNdotV2()); + g2_query.devsh_l = ggx_ndf.devsh_part(params._sample.getNdotL2()); + g2_query.transmitted = transmitted; + g2_query._clamp = BxDFClampMode::BCM_ABS; + scalar_type quo; - quo = ggx_ndf.template G2_over_G1(params._sample, params.interaction, transmitted, BxDFClampMode::BCM_ABS); + quo = ggx_ndf.template G2_over_G1, sample_type, isotropic_interaction_type, isocache_type>(g2_query, params._sample, params.interaction); return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } @@ -346,8 +369,15 @@ struct SGGXDielectricAnisotropicBxDF g2_query; + g2_query.devsh_v = ggx_ndf.devsh_part(params.interaction.getTdotV2(), params.interaction.getBdotV2(), params.interaction.getNdotV2()); + g2_query.devsh_l = ggx_ndf.devsh_part(params._sample.getTdotL2(), params._sample.getBdotL2(), params._sample.getNdotL2()); + g2_query.transmitted = transmitted; + g2_query._clamp = BxDFClampMode::BCM_ABS; + scalar_type quo; - quo = ggx_ndf.template G2_over_G1(params._sample, params.interaction, transmitted, BxDFClampMode::BCM_ABS); + quo = ggx_ndf.template G2_over_G1, sample_type, anisotropic_interaction_type, anisocache_type>(g2_query, params._sample, params.interaction); return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } diff --git a/include/nbl/builtin/hlsl/tgmath/impl.hlsl b/include/nbl/builtin/hlsl/tgmath/impl.hlsl index d4a6430052..68639e7d43 100644 --- a/include/nbl/builtin/hlsl/tgmath/impl.hlsl +++ b/include/nbl/builtin/hlsl/tgmath/impl.hlsl @@ -582,8 +582,6 @@ struct beta_helper) > // implementation from Numerical Recipes in C, 2nd ed. static T __call(T v1, T v2) { - assert(v1 >= 1.0 && v2 >= 1.0); - const T thresholds[4] = { 0, 2e4, 1e6, 1e15 }; // threshold values gotten from testing when the function returns nan/inf/1 if (v1+v2 > thresholds[mpl::find_lsb_v]) return T(0.0); From 11a4f4a6ebf4b5d15ec79d657e42cacf905e5785 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 4 Aug 2025 16:12:57 +0700 Subject: [PATCH 156/188] moved ggx query structs into bxdf struct --- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 83 ++++++++++------ .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 95 +++++++++++++------ 2 files changed, 120 insertions(+), 58 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 4fa449074a..21362fad7d 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -98,33 +98,6 @@ struct GGXParams -struct SGGXDG1Query -{ - using scalar_type = T; - - scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } - scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; } - - scalar_type ndf; - scalar_type G1_over_2NdotV; -}; - -template -struct SGGXG2XQuery -{ - using scalar_type = T; - - scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } - scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } - bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } - BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } - - scalar_type devsh_v; - scalar_type devsh_l; - bool transmitted; - BxDFClampMode _clamp; -}; template struct SGGXAnisotropicBxDF; @@ -150,6 +123,34 @@ struct SGGXIsotropicBxDF using params_isotropic_t = GGXParams; using params_anisotropic_t = GGXParams; + template + struct SGGXDG1Query + { + using scalar_type = T; + + scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } + scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; } + + scalar_type ndf; + scalar_type G1_over_2NdotV; + }; + + template + struct SGGXG2XQuery + { + using scalar_type = T; + + scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } + scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } + bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } + BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } + + scalar_type devsh_v; + scalar_type devsh_l; + bool transmitted; + BxDFClampMode _clamp; + }; + // iso static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) @@ -269,6 +270,34 @@ struct SGGXAnisotropicBxDF; using params_anisotropic_t = GGXParams; + template + struct SGGXDG1Query + { + using scalar_type = T; + + scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } + scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; } + + scalar_type ndf; + scalar_type G1_over_2NdotV; + }; + + template + struct SGGXG2XQuery + { + using scalar_type = T; + + scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } + scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } + bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } + BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } + + scalar_type devsh_v; + scalar_type devsh_l; + bool transmitted; + BxDFClampMode _clamp; + }; + // aniso static this_t create(scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 625d973442..3b540eaa1b 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -98,37 +98,6 @@ struct GGXParams -struct SGGXDG1Query -{ - using scalar_type = T; - - scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } - scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; } - bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } - scalar_type getOrientedEta() NBL_CONST_MEMBER_FUNC { return orientedEta; } - - scalar_type ndf; - scalar_type G1_over_2NdotV; - bool transmitted; - scalar_type orientedEta; -}; - -template -struct SGGXG2XQuery -{ - using scalar_type = T; - - scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } - scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } - bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } - BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } - - scalar_type devsh_v; - scalar_type devsh_l; - bool transmitted; - BxDFClampMode _clamp; -}; template struct SGGXDielectricAnisotropicBxDF; @@ -156,6 +125,38 @@ struct SGGXDielectricIsotropicBxDF using params_isotropic_t = GGXParams; using params_anisotropic_t = GGXParams; + template + struct SGGXDG1Query + { + using scalar_type = T; + + scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } + scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; } + bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } + scalar_type getOrientedEta() NBL_CONST_MEMBER_FUNC { return orientedEta; } + + scalar_type ndf; + scalar_type G1_over_2NdotV; + bool transmitted; + scalar_type orientedEta; + }; + + template + struct SGGXG2XQuery + { + using scalar_type = T; + + scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } + scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } + bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } + BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } + + scalar_type devsh_v; + scalar_type devsh_l; + bool transmitted; + BxDFClampMode _clamp; + }; + static this_t create(scalar_type eta, scalar_type A) { this_t retval; @@ -266,6 +267,38 @@ struct SGGXDielectricAnisotropicBxDF; using params_anisotropic_t = GGXParams; + template + struct SGGXDG1Query + { + using scalar_type = T; + + scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } + scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; } + bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } + scalar_type getOrientedEta() NBL_CONST_MEMBER_FUNC { return orientedEta; } + + scalar_type ndf; + scalar_type G1_over_2NdotV; + bool transmitted; + scalar_type orientedEta; + }; + + template + struct SGGXG2XQuery + { + using scalar_type = T; + + scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } + scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } + bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } + BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } + + scalar_type devsh_v; + scalar_type devsh_l; + bool transmitted; + BxDFClampMode _clamp; + }; + static this_t create(scalar_type eta, scalar_type ax, scalar_type ay) { this_t retval; From c6a542c974e89b99bdc9ce0b69f4baf8bcb125c6 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 4 Aug 2025 16:14:00 +0700 Subject: [PATCH 157/188] moved beckmann query structs into bxdf, minor change to dg1 usage --- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 28 ++--- .../hlsl/bxdf/reflection/beckmann.hlsl | 92 ++++++++++------ .../hlsl/bxdf/transmission/beckmann.hlsl | 102 +++++++++++------- 3 files changed, 140 insertions(+), 82 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index 78df527a45..d52fab7d64 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -27,7 +27,7 @@ NBL_CONCEPT_BEGIN(1) NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getNdf()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getMaxNdotV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getClampMode()), ::nbl::hlsl::is_same_v, BxDFClampMode)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getOnePlusLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ); @@ -43,7 +43,7 @@ NBL_CONCEPT_BEGIN(1) NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getNdf()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getAbsNdotV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getClampMode()), ::nbl::hlsl::is_same_v, BxDFClampMode)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getTransmitted()), ::nbl::hlsl::is_same_v, bool)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getOrientedEta()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) @@ -85,19 +85,19 @@ struct Beckmann) > } // brdf - template) - scalar_type DG1(NBL_REF_ARG(Query) query) + template && surface_interactions::Isotropic) + scalar_type DG1(NBL_REF_ARG(Query) query, NBL_CONST_REF_ARG(Interaction) interaction) { query.onePlusLambda_V = scalar_type(1.0) + query.getLambdaV(); - return ndf::microfacet_to_light_measure_transform::__call(query.getNdf() / query.getOnePlusLambdaV(), query.getMaxNdotV()); + return ndf::microfacet_to_light_measure_transform::__call(query.getNdf() / query.getOnePlusLambdaV(), interaction.getNdotV(query.getClampMode())); } // bsdf - template && ReadableIsotropicMicrofacetCache) - scalar_type DG1(NBL_REF_ARG(Query) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) + scalar_type DG1(NBL_REF_ARG(Query) query, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { query.onePlusLambda_V = scalar_type(1.0) + query.getLambdaV(); - return ndf::microfacet_to_light_measure_transform::__call(query.getNdf() / query.getOnePlusLambdaV(), query.getAbsNdotV(), query.getTransmitted(), cache.getVdotH(), cache.getLdotH(), cache.getVdotHLdotH(), query.getOrientedEta()); + return ndf::microfacet_to_light_measure_transform::__call(query.getNdf() / query.getOnePlusLambdaV(), interaction.getNdotV(query.getClampMode()), query.getTransmitted(), cache.getVdotH(), cache.getLdotH(), cache.getVdotHLdotH(), query.getOrientedEta()); } scalar_type G1(scalar_type lambda) @@ -158,19 +158,19 @@ struct Beckmann) > return numbers::inv_pi * nom / denom; } - template) - scalar_type DG1(NBL_REF_ARG(Query) query) + template && surface_interactions::Anisotropic) + scalar_type DG1(NBL_REF_ARG(Query) query, NBL_CONST_REF_ARG(Interaction) interaction) { Beckmann beckmann; - scalar_type dg = beckmann.template DG1(query); + scalar_type dg = beckmann.template DG1(query, interaction.isotropic); return dg; } - template && AnisotropicMicrofacetCache) - scalar_type DG1(NBL_REF_ARG(Query) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + scalar_type DG1(NBL_REF_ARG(Query) query, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { Beckmann beckmann; - scalar_type dg = beckmann.template DG1(query, cache.iso_cache); + scalar_type dg = beckmann.template DG1(query, interaction.isotropic, cache.iso_cache); return dg; } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 5e5c03189e..912228a73e 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -98,34 +98,6 @@ struct BeckmannParams -struct SBeckmannDG1Query -{ - using scalar_type = T; - - scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } - scalar_type getMaxNdotV() NBL_CONST_MEMBER_FUNC { return maxNdotV; } - scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } - - scalar_type ndf; - scalar_type maxNdotV; - scalar_type lambda_V; - scalar_type onePlusLambda_V; -}; - -template -struct SBeckmannG2overG1Query -{ - using scalar_type = T; - - bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } - scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } - - bool transmitted; - scalar_type onePlusLambda_V; -}; - template struct SBeckmannAnisotropicBxDF; @@ -149,6 +121,34 @@ struct SBeckmannIsotropicBxDF using params_isotropic_t = BeckmannParams; using params_anisotropic_t = BeckmannParams; + template + struct SBeckmannDG1Query + { + using scalar_type = T; + + scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } + BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } + scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } + scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } + + scalar_type ndf; + BxDFClampMode _clamp; + scalar_type lambda_V; + scalar_type onePlusLambda_V; + }; + + template + struct SBeckmannG2overG1Query + { + using scalar_type = T; + + bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } + scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } + + bool transmitted; + scalar_type onePlusLambda_V; + }; + // iso static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) { @@ -197,7 +197,7 @@ struct SBeckmannIsotropicBxDF scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { SBeckmannDG1Query dg1_query; - dg1_query.maxNdotV = params.getNdotV(); + dg1_query._clamp = BxDFClampMode::BCM_MAX; scalar_type a2 = A*A; ndf::Beckmann beckmann_ndf; @@ -206,7 +206,7 @@ struct SBeckmannIsotropicBxDF dg1_query.lambda_V = beckmann_ndf.LambdaC2(params.getNdotV2()); - scalar_type dg1 = beckmann_ndf.template DG1 >(dg1_query); + scalar_type dg1 = beckmann_ndf.template DG1, isotropic_interaction_type>(dg1_query, params.interaction); onePlusLambda_V = dg1_query.getOnePlusLambdaV(); return dg1; } @@ -264,6 +264,34 @@ struct SBeckmannAnisotropicBxDF; using params_anisotropic_t = BeckmannParams; + template + struct SBeckmannDG1Query + { + using scalar_type = T; + + scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } + BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } + scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } + scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } + + scalar_type ndf; + BxDFClampMode _clamp; + scalar_type lambda_V; + scalar_type onePlusLambda_V; + }; + + template + struct SBeckmannG2overG1Query + { + using scalar_type = T; + + bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } + scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } + + bool transmitted; + scalar_type onePlusLambda_V; + }; + // aniso static this_t create(scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) { @@ -384,7 +412,7 @@ struct SBeckmannAnisotropicBxDF dg1_query; - dg1_query.maxNdotV = params.getNdotV(); + dg1_query._clamp = BxDFClampMode::BCM_MAX; scalar_type ndf, lambda; ndf::Beckmann beckmann_ndf; @@ -394,7 +422,7 @@ struct SBeckmannAnisotropicBxDF >(dg1_query); + scalar_type dg1 = beckmann_ndf.template DG1, anisotropic_interaction_type>(dg1_query, params.interaction); onePlusLambda_V = dg1_query.getOnePlusLambdaV(); return dg1; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index bfb147122c..da38b602fb 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -98,38 +98,6 @@ struct BeckmannParams -struct SBeckmannDG1Query -{ - using scalar_type = T; - - scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } - scalar_type getAbsNdotV() NBL_CONST_MEMBER_FUNC { return absNdotV; } - scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } - scalar_type getOrientedEta() NBL_CONST_MEMBER_FUNC { return orientedEta; } - scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } - - scalar_type ndf; - scalar_type absNdotV; - scalar_type lambda_V; - bool transmitted; - scalar_type orientedEta; - scalar_type onePlusLambda_V; -}; - -template -struct SBeckmannG2overG1Query -{ - using scalar_type = T; - - bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } - scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } - - bool transmitted; - scalar_type onePlusLambda_V; -}; - template struct SBeckmannDielectricAnisotropicBxDF; @@ -156,6 +124,37 @@ struct SBeckmannDielectricIsotropicBxDF using params_isotropic_t = BeckmannParams; using params_anisotropic_t = BeckmannParams; + template + struct SBeckmannDG1Query + { + using scalar_type = T; + + scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } + BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } + scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } + bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } + scalar_type getOrientedEta() NBL_CONST_MEMBER_FUNC { return orientedEta; } + scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } + + scalar_type ndf; + BxDFClampMode _clamp; + scalar_type lambda_V; + bool transmitted; + scalar_type orientedEta; + scalar_type onePlusLambda_V; + }; + + template + struct SBeckmannG2overG1Query + { + using scalar_type = T; + + bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } + scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } + + bool transmitted; + scalar_type onePlusLambda_V; + }; static this_t create(scalar_type eta, scalar_type A) { @@ -195,7 +194,7 @@ struct SBeckmannDielectricIsotropicBxDF scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) { SBeckmannDG1Query dg1_query; - dg1_query.absNdotV = params.getNdotV(); + dg1_query._clamp = BxDFClampMode::BCM_ABS; fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; @@ -212,7 +211,7 @@ struct SBeckmannDielectricIsotropicBxDF dg1_query.lambda_V = beckmann_ndf.LambdaC2(params.getNdotV2()); - scalar_type dg1 = beckmann_ndf.template DG1, isocache_type>(dg1_query, params.cache); + scalar_type dg1 = beckmann_ndf.template DG1, isotropic_interaction_type, isocache_type>(dg1_query, params.interaction, params.cache); onePlusLambda_V = dg1_query.getOnePlusLambdaV(); return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, dg1_query.getTransmitted()) * dg1; @@ -267,6 +266,37 @@ struct SBeckmannDielectricAnisotropicBxDF; using params_anisotropic_t = BeckmannParams; + template + struct SBeckmannDG1Query + { + using scalar_type = T; + + scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } + BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } + scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } + bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } + scalar_type getOrientedEta() NBL_CONST_MEMBER_FUNC { return orientedEta; } + scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } + + scalar_type ndf; + BxDFClampMode _clamp; + scalar_type lambda_V; + bool transmitted; + scalar_type orientedEta; + scalar_type onePlusLambda_V; + }; + + template + struct SBeckmannG2overG1Query + { + using scalar_type = T; + + bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } + scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } + + bool transmitted; + scalar_type onePlusLambda_V; + }; static this_t create(scalar_type eta, scalar_type ax, scalar_type ay) { @@ -340,7 +370,7 @@ struct SBeckmannDielectricAnisotropicBxDF dg1_query; - dg1_query.absNdotV = params.getNdotV(); + dg1_query._clamp = BxDFClampMode::BCM_ABS; fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; @@ -357,7 +387,7 @@ struct SBeckmannDielectricAnisotropicBxDF, anisocache_type>(dg1_query, params.cache); + scalar_type dg1 = beckmann_ndf.template DG1, anisotropic_interaction_type, anisocache_type>(dg1_query, params.interaction, params.cache); onePlusLambda_V = dg1_query.getOnePlusLambdaV(); return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, dg1_query.getTransmitted()) * dg1; From 5ec0b95703a6d6ce81969c7c4670d10fd008fc64 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 4 Aug 2025 16:54:40 +0700 Subject: [PATCH 158/188] use isTransmission bool in cache struct --- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 16 ++++++-------- include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 16 ++++++-------- .../hlsl/bxdf/reflection/beckmann.hlsl | 10 ++------- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 10 ++------- .../hlsl/bxdf/transmission/beckmann.hlsl | 22 ++++--------------- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 22 ++++--------------- 6 files changed, 26 insertions(+), 70 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index d52fab7d64..a5063298a3 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -45,7 +45,6 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getNdf()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getClampMode()), ::nbl::hlsl::is_same_v, BxDFClampMode)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getTransmitted()), ::nbl::hlsl::is_same_v, bool)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getOrientedEta()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getOnePlusLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ); @@ -60,7 +59,6 @@ NBL_CONCEPT_BEGIN(1) #define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getTransmitted()), ::nbl::hlsl::is_same_v, bool)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getOnePlusLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ); #undef query @@ -97,7 +95,7 @@ struct Beckmann) > scalar_type DG1(NBL_REF_ARG(Query) query, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { query.onePlusLambda_V = scalar_type(1.0) + query.getLambdaV(); - return ndf::microfacet_to_light_measure_transform::__call(query.getNdf() / query.getOnePlusLambdaV(), interaction.getNdotV(query.getClampMode()), query.getTransmitted(), cache.getVdotH(), cache.getLdotH(), cache.getVdotHLdotH(), query.getOrientedEta()); + return ndf::microfacet_to_light_measure_transform::__call(query.getNdf() / query.getOnePlusLambdaV(), interaction.getNdotV(query.getClampMode()), cache.isTransmission(), cache.getVdotH(), cache.getLdotH(), cache.getVdotHLdotH(), query.getOrientedEta()); } scalar_type G1(scalar_type lambda) @@ -131,11 +129,11 @@ struct Beckmann) > return scalar_type(1.0) / (scalar_type(1.0) + lambda_V + lambda_L); } - template && LightSample) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample) + template && LightSample && ReadableIsotropicMicrofacetCache) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(MicrofacetCache) cache) { scalar_type lambda_L = LambdaC2(_sample.getNdotL2()); - return query.getOnePlusLambdaV() * hlsl::mix(scalar_type(1.0)/(query.getOnePlusLambdaV() + lambda_L), bxdf::beta(query.getOnePlusLambdaV(), scalar_type(1.0) + lambda_L), query.getTransmitted()); + return query.getOnePlusLambdaV() * hlsl::mix(scalar_type(1.0)/(query.getOnePlusLambdaV() + lambda_L), bxdf::beta(query.getOnePlusLambdaV(), scalar_type(1.0) + lambda_L), cache.isTransmission()); } scalar_type a2; @@ -207,11 +205,11 @@ struct Beckmann) > return scalar_type(1.0) / (scalar_type(1.0) + lambda_V + lambda_L); } - template && LightSample) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample) + template && LightSample && AnisotropicMicrofacetCache) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(MicrofacetCache) cache) { scalar_type lambda_L = LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); - return query.getOnePlusLambdaV() * hlsl::mix(scalar_type(1.0)/(query.getOnePlusLambdaV() + lambda_L), bxdf::beta(query.getOnePlusLambdaV(), scalar_type(1.0) + lambda_L), query.getTransmitted()); + return query.getOnePlusLambdaV() * hlsl::mix(scalar_type(1.0)/(query.getOnePlusLambdaV() + lambda_L), bxdf::beta(query.getOnePlusLambdaV(), scalar_type(1.0) + lambda_L), cache.isTransmission()); } scalar_type ax; diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index 9f88c48922..e661cdaa2c 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -42,7 +42,6 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getNdf()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getG1over2NdotV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getTransmitted()), ::nbl::hlsl::is_same_v, bool)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getOrientedEta()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ); #undef query @@ -58,7 +57,6 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getDevshV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getDevshL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getTransmitted()), ::nbl::hlsl::is_same_v, bool)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getClampMode()), ::nbl::hlsl::is_same_v, BxDFClampMode)) ); #undef query @@ -94,7 +92,7 @@ struct GGX) > { scalar_type NG = query.getNdf() * query.getG1over2NdotV(); scalar_type factor = scalar_type(0.5); - if (query.getTransmitted()) + if (cache.isTransmission()) { const scalar_type VdotH_etaLdotH = (cache.getVdotH() + query.getOrientedEta() * cache.getLdotH()); // VdotHLdotH is negative under transmission, so this factor is negative @@ -132,8 +130,8 @@ struct GGX) > return scalar_type(0.5) / (Vterm + Lterm); } - template && LightSample && surface_interactions::Isotropic) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + template && LightSample && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { BxDFClampMode _clamp = query.getClampMode(); assert(_clamp != BxDFClampMode::BCM_NONE); @@ -143,7 +141,7 @@ struct GGX) > scalar_type NdotL = _sample.getNdotL(_clamp); scalar_type devsh_v = query.getDevshV(); scalar_type devsh_l = query.getDevshL(); - if (query.getTransmitted()) + if (cache.isTransmission()) { if (NdotV < 1e-7 || NdotL < 1e-7) return 0.0; @@ -229,8 +227,8 @@ struct GGX) > return scalar_type(0.5) / (Vterm + Lterm); } - template && LightSample && surface_interactions::Anisotropic) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + template && LightSample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { BxDFClampMode _clamp = query.getClampMode(); assert(_clamp != BxDFClampMode::BCM_NONE); @@ -240,7 +238,7 @@ struct GGX) > scalar_type NdotL = _sample.getNdotL(_clamp); scalar_type devsh_v = query.getDevshV(); scalar_type devsh_l = query.getDevshL(); - if (query.getTransmitted()) + if (cache.isTransmission()) { if (NdotV < 1e-7 || NdotL < 1e-7) return 0.0; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 912228a73e..b725209825 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -142,10 +142,8 @@ struct SBeckmannIsotropicBxDF { using scalar_type = T; - bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } - bool transmitted; scalar_type onePlusLambda_V; }; @@ -228,9 +226,8 @@ struct SBeckmannIsotropicBxDF { beckmann_ndf.a2 = A*A; SBeckmannG2overG1Query query; - query.transmitted = false; query.onePlusLambda_V = onePlusLambda_V; - scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1, sample_type>(query, params._sample); + scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1, sample_type, isocache_type>(query, params._sample, params.cache); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; @@ -285,10 +282,8 @@ struct SBeckmannAnisotropicBxDF query; - query.transmitted = false; query.onePlusLambda_V = onePlusLambda_V; - scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1, sample_type>(query, params._sample); + scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1, sample_type, anisocache_type>(query, params._sample, params.cache); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 21362fad7d..85ab699c46 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -142,12 +142,10 @@ struct SGGXIsotropicBxDF scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } - bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } scalar_type devsh_v; scalar_type devsh_l; - bool transmitted; BxDFClampMode _clamp; }; @@ -232,9 +230,8 @@ struct SGGXIsotropicBxDF SGGXG2XQuery g2_query; g2_query.devsh_v = ggx_ndf.devsh_part(params.interaction.getNdotV2()); g2_query.devsh_l = ggx_ndf.devsh_part(params._sample.getNdotL2()); - g2_query.transmitted = false; g2_query._clamp = BxDFClampMode::BCM_MAX; - const scalar_type G2_over_G1 = ggx_ndf.template G2_over_G1, sample_type, isotropic_interaction_type, isocache_type>(g2_query, params._sample, params.interaction); + const scalar_type G2_over_G1 = ggx_ndf.template G2_over_G1, sample_type, isotropic_interaction_type, isocache_type>(g2_query, params._sample, params.interaction, params.cache); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); @@ -289,12 +286,10 @@ struct SGGXAnisotropicBxDF g2_query; g2_query.devsh_v = ggx_ndf.devsh_part(params.interaction.getTdotV2(), params.interaction.getBdotV2(), params.interaction.getNdotV2()); g2_query.devsh_l = ggx_ndf.devsh_part(params._sample.getTdotL2(), params._sample.getBdotL2(), params._sample.getNdotL2()); - g2_query.transmitted = false; g2_query._clamp = BxDFClampMode::BCM_MAX; - const scalar_type G2_over_G1 = ggx_ndf.template G2_over_G1, sample_type, anisotropic_interaction_type, anisocache_type>(g2_query, params._sample, params.interaction); + const scalar_type G2_over_G1 = ggx_ndf.template G2_over_G1, sample_type, anisotropic_interaction_type, anisocache_type>(g2_query, params._sample, params.interaction, params.cache); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index da38b602fb..c602452f29 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -132,14 +132,12 @@ struct SBeckmannDielectricIsotropicBxDF scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } scalar_type getOrientedEta() NBL_CONST_MEMBER_FUNC { return orientedEta; } scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } scalar_type ndf; BxDFClampMode _clamp; scalar_type lambda_V; - bool transmitted; scalar_type orientedEta; scalar_type onePlusLambda_V; }; @@ -149,10 +147,8 @@ struct SBeckmannDielectricIsotropicBxDF { using scalar_type = T; - bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } - bool transmitted; scalar_type onePlusLambda_V; }; @@ -200,8 +196,6 @@ struct SBeckmannDielectricIsotropicBxDF const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; dg1_query.orientedEta = orientedEta.value[0]; - dg1_query.transmitted = params.cache.isTransmission(); - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; const scalar_type a2 = A*A; @@ -214,7 +208,7 @@ struct SBeckmannDielectricIsotropicBxDF scalar_type dg1 = beckmann_ndf.template DG1, isotropic_interaction_type, isocache_type>(dg1_query, params.interaction, params.cache); onePlusLambda_V = dg1_query.getOnePlusLambdaV(); - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, dg1_query.getTransmitted()) * dg1; + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, params.cache.isTransmission()) * dg1; } scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) @@ -231,9 +225,8 @@ struct SBeckmannDielectricIsotropicBxDF ndf::Beckmann beckmann_ndf; beckmann_ndf.a2 = A*A; SBeckmannG2overG1Query query; - query.transmitted = params.getVdotH() * params.getLdotH() < 0.0; query.onePlusLambda_V = onePlusLambda_V; - scalar_type quo = beckmann_ndf.template G2_over_G1, sample_type>(query, params._sample); + scalar_type quo = beckmann_ndf.template G2_over_G1, sample_type, isocache_type>(query, params._sample, params.cache); return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } @@ -274,14 +267,12 @@ struct SBeckmannDielectricAnisotropicBxDF::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; ndf::Beckmann beckmann_ndf; @@ -390,7 +377,7 @@ struct SBeckmannDielectricAnisotropicBxDF, anisotropic_interaction_type, anisocache_type>(dg1_query, params.interaction, params.cache); onePlusLambda_V = dg1_query.getOnePlusLambdaV(); - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, dg1_query.getTransmitted()) * dg1; + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, params.cache.isTransmission()) * dg1; } scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) @@ -408,9 +395,8 @@ struct SBeckmannDielectricAnisotropicBxDF query; - query.transmitted = params.getVdotH() * params.getLdotH() < 0.0; query.onePlusLambda_V = onePlusLambda_V; - scalar_type quo = beckmann_ndf.template G2_over_G1, sample_type>(query, params._sample); + scalar_type quo = beckmann_ndf.template G2_over_G1, sample_type, anisocache_type>(query, params._sample, params.cache); return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 3b540eaa1b..09a3a39869 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -132,12 +132,10 @@ struct SGGXDielectricIsotropicBxDF scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; } - bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } scalar_type getOrientedEta() NBL_CONST_MEMBER_FUNC { return orientedEta; } scalar_type ndf; scalar_type G1_over_2NdotV; - bool transmitted; scalar_type orientedEta; }; @@ -148,12 +146,10 @@ struct SGGXDielectricIsotropicBxDF scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } - bool getTransmitted() NBL_CONST_MEMBER_FUNC { return transmitted; } BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } scalar_type devsh_v; scalar_type devsh_l; - bool transmitted; BxDFClampMode _clamp; }; @@ -200,8 +196,6 @@ struct SGGXDielectricIsotropicBxDF const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; dg1_query.orientedEta = orientedEta.value[0]; - dg1_query.transmitted = params.cache.isTransmission(); - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; scalar_type devsh_v; @@ -214,7 +208,7 @@ struct SGGXDielectricIsotropicBxDF devsh_v = ggx_ndf.devsh_part(params.getNdotV2()); dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(params.getNdotV(), devsh_v); - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, dg1_query.transmitted) * ggx_ndf.template DG1, isocache_type>(dg1_query, params.cache); + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, params.cache.isTransmission()) * ggx_ndf.template DG1, isocache_type>(dg1_query, params.cache); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) @@ -230,11 +224,10 @@ struct SGGXDielectricIsotropicBxDF SGGXG2XQuery g2_query; g2_query.devsh_v = ggx_ndf.devsh_part(params.interaction.getNdotV2()); g2_query.devsh_l = ggx_ndf.devsh_part(params._sample.getNdotL2()); - g2_query.transmitted = transmitted; g2_query._clamp = BxDFClampMode::BCM_ABS; scalar_type quo; - quo = ggx_ndf.template G2_over_G1, sample_type, isotropic_interaction_type, isocache_type>(g2_query, params._sample, params.interaction); + quo = ggx_ndf.template G2_over_G1, sample_type, isotropic_interaction_type, isocache_type>(g2_query, params._sample, params.interaction, params.cache); return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } @@ -274,12 +267,10 @@ struct SGGXDielectricAnisotropicBxDF::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; scalar_type devsh_v; @@ -390,7 +377,7 @@ struct SGGXDielectricAnisotropicBxDF, anisocache_type>(dg1_query, params.cache); + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, params.cache.isTransmission()) * ggx_ndf.template DG1, anisocache_type>(dg1_query, params.cache); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) @@ -406,11 +393,10 @@ struct SGGXDielectricAnisotropicBxDF g2_query; g2_query.devsh_v = ggx_ndf.devsh_part(params.interaction.getTdotV2(), params.interaction.getBdotV2(), params.interaction.getNdotV2()); g2_query.devsh_l = ggx_ndf.devsh_part(params._sample.getTdotL2(), params._sample.getBdotL2(), params._sample.getNdotL2()); - g2_query.transmitted = transmitted; g2_query._clamp = BxDFClampMode::BCM_ABS; scalar_type quo; - quo = ggx_ndf.template G2_over_G1, sample_type, anisotropic_interaction_type, anisocache_type>(g2_query, params._sample, params.interaction); + quo = ggx_ndf.template G2_over_G1, sample_type, anisotropic_interaction_type, anisocache_type>(g2_query, params._sample, params.interaction, params.cache); return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } From 5037acdf8442bc30da778342bb9fd036d6b29b2a Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 5 Aug 2025 11:07:51 +0700 Subject: [PATCH 159/188] changes to beckmann ndf G2 usage --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 10 ++++-- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 31 ++++++++----------- .../hlsl/bxdf/reflection/beckmann.hlsl | 20 +++++++++--- .../hlsl/bxdf/transmission/beckmann.hlsl | 10 ++++-- 4 files changed, 45 insertions(+), 26 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index bc3b250d5c..f6ff801abe 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -119,6 +119,12 @@ enum BxDFClampMode : uint16_t BCM_ABS }; +template) +T conditionalAbsOrMax(T x, BxDFClampMode _clamp) +{ + return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, x, 0.0), x, _clamp == BxDFClampMode::BCM_NONE); +} + namespace surface_interactions { @@ -174,7 +180,7 @@ struct SIsotropic vector3_type getN() NBL_CONST_MEMBER_FUNC { return N; } scalar_type getNdotV(BxDFClampMode _clamp = BxDFClampMode::BCM_NONE) NBL_CONST_MEMBER_FUNC { - return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, NdotV, 0.0), NdotV, _clamp == BxDFClampMode::BCM_NONE); + return bxdf::conditionalAbsOrMax(NdotV, _clamp); } scalar_type getNdotV2() NBL_CONST_MEMBER_FUNC { return NdotV2; } @@ -406,7 +412,7 @@ struct SLightSample scalar_type getBdotL2() NBL_CONST_MEMBER_FUNC { const scalar_type t = getBdotL(); return t*t; } scalar_type getNdotL(BxDFClampMode _clamp = BxDFClampMode::BCM_NONE) NBL_CONST_MEMBER_FUNC { - return hlsl::mix(math::conditionalAbsOrMax(_clamp == BxDFClampMode::BCM_ABS, NdotL, 0.0), NdotL, _clamp == BxDFClampMode::BCM_NONE); + return bxdf::conditionalAbsOrMax(NdotL, _clamp); } scalar_type getNdotL2() NBL_CONST_MEMBER_FUNC { return NdotL2; } diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index a5063298a3..197965185b 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -59,6 +59,7 @@ NBL_CONCEPT_BEGIN(1) #define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getOnePlusLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ); #undef query @@ -121,19 +122,16 @@ struct Beckmann) > return Lambda(C2(NdotX2)); } - template && surface_interactions::Isotropic) - scalar_type correlated(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + template) + scalar_type correlated(NBL_CONST_REF_ARG(Query) query) { - scalar_type lambda_V = LambdaC2(interaction.getNdotV2()); - scalar_type lambda_L = LambdaC2(_sample.getNdotL2()); - return scalar_type(1.0) / (scalar_type(1.0) + lambda_V + lambda_L); + return scalar_type(1.0) / (query.getOnePlusLambdaV() + query.getLambdaL()); } - template && LightSample && ReadableIsotropicMicrofacetCache) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template && ReadableIsotropicMicrofacetCache) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) { - scalar_type lambda_L = LambdaC2(_sample.getNdotL2()); - return query.getOnePlusLambdaV() * hlsl::mix(scalar_type(1.0)/(query.getOnePlusLambdaV() + lambda_L), bxdf::beta(query.getOnePlusLambdaV(), scalar_type(1.0) + lambda_L), cache.isTransmission()); + return query.getOnePlusLambdaV() * hlsl::mix(scalar_type(1.0)/(query.getOnePlusLambdaV() + query.getLambdaL()), bxdf::beta(query.getOnePlusLambdaV(), scalar_type(1.0) + query.getLambdaL()), cache.isTransmission()); } scalar_type a2; @@ -197,19 +195,16 @@ struct Beckmann) > return Lambda(C2(TdotX2, BdotX2, NdotX2)); } - template && surface_interactions::Anisotropic) - scalar_type correlated(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + template) + scalar_type correlated(NBL_CONST_REF_ARG(Query) query) { - scalar_type lambda_V = LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); - scalar_type lambda_L = LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); - return scalar_type(1.0) / (scalar_type(1.0) + lambda_V + lambda_L); + return scalar_type(1.0) / (query.getOnePlusLambdaV() + query.getLambdaL()); } - template && LightSample && AnisotropicMicrofacetCache) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template && AnisotropicMicrofacetCache) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) { - scalar_type lambda_L = LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); - return query.getOnePlusLambdaV() * hlsl::mix(scalar_type(1.0)/(query.getOnePlusLambdaV() + lambda_L), bxdf::beta(query.getOnePlusLambdaV(), scalar_type(1.0) + lambda_L), cache.isTransmission()); + return query.getOnePlusLambdaV() * hlsl::mix(scalar_type(1.0)/(query.getOnePlusLambdaV() + query.getLambdaL()), bxdf::beta(query.getOnePlusLambdaV(), scalar_type(1.0) + query.getLambdaL()), cache.isTransmission()); } scalar_type ax; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index b725209825..71e6e49122 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -142,8 +142,10 @@ struct SBeckmannIsotropicBxDF { using scalar_type = T; + scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } + scalar_type lambda_L; scalar_type onePlusLambda_V; }; @@ -165,7 +167,10 @@ struct SBeckmannIsotropicBxDF scalar_type NG = beckmann_ndf.template D(params.cache); if (a2 > numeric_limits::min) { - NG *= beckmann_ndf.template correlated(params._sample, params.interaction); + SBeckmannG2overG1Query query; + query.lambda_L = beckmann_ndf.LambdaC2(params._sample.getNdotL2()); + query.onePlusLambda_V = scalar_type(1.0) + beckmann_ndf.LambdaC2(params.interaction.getNdotV2()); + NG *= beckmann_ndf.template correlated >(query); } return NG; } @@ -226,8 +231,9 @@ struct SBeckmannIsotropicBxDF { beckmann_ndf.a2 = A*A; SBeckmannG2overG1Query query; + query.lambda_L = beckmann_ndf.LambdaC2(params._sample.getNdotL2()); query.onePlusLambda_V = onePlusLambda_V; - scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1, sample_type, isocache_type>(query, params._sample, params.cache); + scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1, isocache_type>(query, params.cache); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; @@ -282,8 +288,10 @@ struct SBeckmannAnisotropicBxDF(params.cache); if (hlsl::any >(A > (vector2_type)numeric_limits::min)) { - NG *= beckmann_ndf.template correlated(params._sample, params.interaction); + SBeckmannG2overG1Query query; + query.lambda_L = beckmann_ndf.LambdaC2(params._sample.getTdotL2(), params._sample.getBdotL2(), params._sample.getNdotL2()); + query.onePlusLambda_V = scalar_type(1.0) + beckmann_ndf.LambdaC2(params.interaction.getTdotV2(), params.interaction.getBdotV2(), params.interaction.getNdotV2()); + NG *= beckmann_ndf.template correlated >(query); } return NG; } @@ -440,8 +451,9 @@ struct SBeckmannAnisotropicBxDF query; + query.lambda_L = beckmann_ndf.LambdaC2(params._sample.getTdotL2(), params._sample.getBdotL2(), params._sample.getNdotL2()); query.onePlusLambda_V = onePlusLambda_V; - scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1, sample_type, anisocache_type>(query, params._sample, params.cache); + scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1, anisocache_type>(query, params.cache); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index c602452f29..cc0cec3636 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -147,8 +147,10 @@ struct SBeckmannDielectricIsotropicBxDF { using scalar_type = T; + scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } + scalar_type lambda_L; scalar_type onePlusLambda_V; }; @@ -225,8 +227,9 @@ struct SBeckmannDielectricIsotropicBxDF ndf::Beckmann beckmann_ndf; beckmann_ndf.a2 = A*A; SBeckmannG2overG1Query query; + query.lambda_L = beckmann_ndf.LambdaC2(params._sample.getNdotL2()); query.onePlusLambda_V = onePlusLambda_V; - scalar_type quo = beckmann_ndf.template G2_over_G1, sample_type, isocache_type>(query, params._sample, params.cache); + scalar_type quo = beckmann_ndf.template G2_over_G1, isocache_type>(query, params.cache); return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } @@ -282,8 +285,10 @@ struct SBeckmannDielectricAnisotropicBxDF query; + query.lambda_L = beckmann_ndf.LambdaC2(params._sample.getTdotL2(), params._sample.getBdotL2(), params._sample.getNdotL2()); query.onePlusLambda_V = onePlusLambda_V; - scalar_type quo = beckmann_ndf.template G2_over_G1, sample_type, anisocache_type>(query, params._sample, params.cache); + scalar_type quo = beckmann_ndf.template G2_over_G1, anisocache_type>(query, params.cache); return quotient_pdf_type::create(hlsl::promote(quo), _pdf); } From 2b4d5cde824da6b088af0a592b2efa8cb44e0114 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 5 Aug 2025 12:09:38 +0700 Subject: [PATCH 160/188] simplified bxdf config, removed redundant lines --- include/nbl/builtin/hlsl/bxdf/config.hlsl | 36 ++++-------- .../hlsl/bxdf/reflection/beckmann.hlsl | 48 ++++++++-------- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 50 ++++++++--------- .../hlsl/bxdf/reflection/lambertian.hlsl | 14 ++--- .../hlsl/bxdf/reflection/oren_nayar.hlsl | 16 +++--- .../hlsl/bxdf/transmission/beckmann.hlsl | 56 +++++++++---------- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 56 +++++++++---------- .../hlsl/bxdf/transmission/lambertian.hlsl | 14 ++--- .../bxdf/transmission/smooth_dielectric.hlsl | 40 ++++++------- 9 files changed, 158 insertions(+), 172 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/config.hlsl b/include/nbl/builtin/hlsl/bxdf/config.hlsl index 3d8bed31a5..471433ede6 100644 --- a/include/nbl/builtin/hlsl/bxdf/config.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/config.hlsl @@ -74,6 +74,7 @@ struct SConfiguration; using vector3_type = vector; + using monochrome_type = vector; using isotropic_interaction_type = Interaction; using anisotropic_interaction_type = surface_interactions::SAnisotropic; @@ -92,6 +93,7 @@ struct SConfiguration; using vector3_type = vector; + using monochrome_type = vector; using isotropic_interaction_type = typename Interaction::isotropic_interaction_type; using anisotropic_interaction_type = Interaction; @@ -107,23 +109,15 @@ struct SMicrofacetConfiguration; template NBL_PARTIAL_REQ_TOP(MICROFACET_CONF_ISO) -struct SMicrofacetConfiguration +struct SMicrofacetConfiguration : SConfiguration #undef MICROFACET_CONF_ISO { NBL_CONSTEXPR_STATIC_INLINE bool IsAnisotropic = false; - using scalar_type = typename LS::scalar_type; - using ray_dir_info_type = typename LS::ray_dir_info_type; - using vector2_type = vector; - using vector3_type = vector; - using matrix3x3_type = matrix; - using monochrome_type = vector; + using base_type = SConfiguration; + + using matrix3x3_type = matrix; - using isotropic_interaction_type = Interaction; - using anisotropic_interaction_type = surface_interactions::SAnisotropic; - using sample_type = LS; - using spectral_type = Spectrum; - using quotient_pdf_type = sampling::quotient_and_pdf; using isocache_type = MicrofacetCache; using anisocache_type = SAnisotropicMicrofacetCache; }; @@ -132,27 +126,21 @@ struct SMicrofacetConfiguration NBL_PARTIAL_REQ_TOP(MICROFACET_CONF_ANISO) -struct SMicrofacetConfiguration +struct SMicrofacetConfiguration : SConfiguration #undef MICROFACET_CONF_ANISO { NBL_CONSTEXPR_STATIC_INLINE bool IsAnisotropic = true; - using scalar_type = typename LS::scalar_type; - using ray_dir_info_type = typename LS::ray_dir_info_type; - using vector2_type = vector; - using vector3_type = vector; - using matrix3x3_type = matrix; - using monochrome_type = vector; + using base_type = SConfiguration; + + using matrix3x3_type = matrix; - using isotropic_interaction_type = typename Interaction::isotropic_interaction_type; - using anisotropic_interaction_type = Interaction; - using sample_type = LS; - using spectral_type = Spectrum; - using quotient_pdf_type = sampling::quotient_and_pdf; using isocache_type = typename MicrofacetCache::isocache_type; using anisocache_type = MicrofacetCache; }; +#define NBL_BXDF_CONFIG_ALIAS(TYPE,CONFIG) using TYPE = typename CONFIG::TYPE + } } } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 71e6e49122..480fbb1465 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -105,18 +105,18 @@ template; - using scalar_type = typename Config::scalar_type; - using vector2_type = vector; - using vector3_type = vector; - using ray_dir_info_type = typename Config::ray_dir_info_type; - - using isotropic_interaction_type = typename Config::isotropic_interaction_type; - using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; - using sample_type = typename Config::sample_type; - using spectral_type = typename Config::spectral_type; - using quotient_pdf_type = typename Config::quotient_pdf_type; - using isocache_type = typename Config::isocache_type; - using anisocache_type = typename Config::anisocache_type; + NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector3_type, Config); + NBL_BXDF_CONFIG_ALIAS(ray_dir_info_type, Config); + + NBL_BXDF_CONFIG_ALIAS(isotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(anisotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(sample_type, Config); + NBL_BXDF_CONFIG_ALIAS(spectral_type, Config); + NBL_BXDF_CONFIG_ALIAS(quotient_pdf_type, Config); + NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); + NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); using params_isotropic_t = BeckmannParams; using params_anisotropic_t = BeckmannParams; @@ -251,18 +251,18 @@ NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration) struct SBeckmannAnisotropicBxDF) > { using this_t = SBeckmannAnisotropicBxDF; - using scalar_type = typename Config::scalar_type; - using vector2_type = vector; - using vector3_type = vector; - using ray_dir_info_type = typename Config::ray_dir_info_type; - - using isotropic_interaction_type = typename Config::isotropic_interaction_type; - using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; - using sample_type = typename Config::sample_type; - using spectral_type = typename Config::spectral_type; - using quotient_pdf_type = typename Config::quotient_pdf_type; - using isocache_type = typename Config::isocache_type; - using anisocache_type = typename Config::anisocache_type; + NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector3_type, Config); + NBL_BXDF_CONFIG_ALIAS(ray_dir_info_type, Config); + + NBL_BXDF_CONFIG_ALIAS(isotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(anisotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(sample_type, Config); + NBL_BXDF_CONFIG_ALIAS(spectral_type, Config); + NBL_BXDF_CONFIG_ALIAS(quotient_pdf_type, Config); + NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); + NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); using params_isotropic_t = BeckmannParams; using params_anisotropic_t = BeckmannParams; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 85ab699c46..4c88396a3f 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -106,19 +106,18 @@ template; - using scalar_type = typename Config::scalar_type; - using vector2_type = vector; - using vector3_type = vector; - using matrix2x3_type = matrix; - using ray_dir_info_type = typename Config::ray_dir_info_type; - - using isotropic_interaction_type = typename Config::isotropic_interaction_type; - using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; - using sample_type = typename Config::sample_type; - using spectral_type = typename Config::spectral_type; - using quotient_pdf_type = typename Config::quotient_pdf_type; - using isocache_type = typename Config::isocache_type; - using anisocache_type = typename Config::anisocache_type; + NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector3_type, Config); + NBL_BXDF_CONFIG_ALIAS(ray_dir_info_type, Config); + + NBL_BXDF_CONFIG_ALIAS(isotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(anisotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(sample_type, Config); + NBL_BXDF_CONFIG_ALIAS(spectral_type, Config); + NBL_BXDF_CONFIG_ALIAS(quotient_pdf_type, Config); + NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); + NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); using params_isotropic_t = GGXParams; using params_anisotropic_t = GGXParams; @@ -250,19 +249,18 @@ NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration) struct SGGXAnisotropicBxDF) > { using this_t = SGGXAnisotropicBxDF; - using scalar_type = typename Config::scalar_type; - using vector2_type = vector; - using vector3_type = vector; - using matrix2x3_type = matrix; - using ray_dir_info_type = typename Config::ray_dir_info_type; - - using isotropic_interaction_type = typename Config::isotropic_interaction_type; - using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; - using sample_type = typename Config::sample_type; - using spectral_type = typename Config::spectral_type; - using quotient_pdf_type = sampling::quotient_and_pdf; - using isocache_type = typename Config::isocache_type; - using anisocache_type = typename Config::anisocache_type; + NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector3_type, Config); + NBL_BXDF_CONFIG_ALIAS(ray_dir_info_type, Config); + + NBL_BXDF_CONFIG_ALIAS(isotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(anisotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(sample_type, Config); + NBL_BXDF_CONFIG_ALIAS(spectral_type, Config); + NBL_BXDF_CONFIG_ALIAS(quotient_pdf_type, Config); + NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); + NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); using params_isotropic_t = GGXParams; using params_anisotropic_t = GGXParams; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl index 8629bc0cb9..90ca2dea58 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl @@ -86,13 +86,13 @@ template; - using scalar_type = typename Config::scalar_type; - using ray_dir_info_type = typename Config::ray_dir_info_type; - using isotropic_interaction_type = typename Config::isotropic_interaction_type; - using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; - using sample_type = typename Config::sample_type; - using spectral_type = typename Config::spectral_type; - using quotient_pdf_type = typename Config::quotient_pdf_type; + NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); + NBL_BXDF_CONFIG_ALIAS(ray_dir_info_type, Config); + NBL_BXDF_CONFIG_ALIAS(isotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(anisotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(sample_type, Config); + NBL_BXDF_CONFIG_ALIAS(spectral_type, Config); + NBL_BXDF_CONFIG_ALIAS(quotient_pdf_type, Config); using params_isotropic_t = LambertianParams; using params_anisotropic_t = LambertianParams; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl index aa29127dc1..66edca4761 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl @@ -88,14 +88,14 @@ template; - using scalar_type = typename Config::scalar_type; - using vector2_type = vector; - using ray_dir_info_type = typename Config::ray_dir_info_type; - using isotropic_interaction_type = typename Config::isotropic_interaction_type; - using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; - using sample_type = typename Config::sample_type; - using spectral_type = typename Config::spectral_type; - using quotient_pdf_type = typename Config::quotient_pdf_type; + NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); + NBL_BXDF_CONFIG_ALIAS(ray_dir_info_type, Config); + NBL_BXDF_CONFIG_ALIAS(isotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(anisotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(sample_type, Config); + NBL_BXDF_CONFIG_ALIAS(spectral_type, Config); + NBL_BXDF_CONFIG_ALIAS(quotient_pdf_type, Config); using params_isotropic_t = OrenNayarParams; using params_anisotropic_t = OrenNayarParams; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index cc0cec3636..f047011ab6 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -105,20 +105,20 @@ template; - using scalar_type = typename Config::scalar_type; - using vector2_type = vector; - using vector3_type = vector; - using matrix3x3_type = matrix; - using monochrome_type = vector; - using ray_dir_info_type = typename Config::ray_dir_info_type; - - using isotropic_interaction_type = typename Config::isotropic_interaction_type; - using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; - using sample_type = typename Config::sample_type; - using spectral_type = typename Config::spectral_type; - using quotient_pdf_type = typename Config::quotient_pdf_type; - using isocache_type = typename Config::isocache_type; - using anisocache_type = typename Config::anisocache_type; + NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector3_type, Config); + NBL_BXDF_CONFIG_ALIAS(matrix3x3_type, Config); + NBL_BXDF_CONFIG_ALIAS(monochrome_type, Config); + NBL_BXDF_CONFIG_ALIAS(ray_dir_info_type, Config); + + NBL_BXDF_CONFIG_ALIAS(isotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(anisotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(sample_type, Config); + NBL_BXDF_CONFIG_ALIAS(spectral_type, Config); + NBL_BXDF_CONFIG_ALIAS(quotient_pdf_type, Config); + NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); + NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); using brdf_type = reflection::SBeckmannIsotropicBxDF; using params_isotropic_t = BeckmannParams; @@ -243,20 +243,20 @@ NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration) struct SBeckmannDielectricAnisotropicBxDF) > { using this_t = SBeckmannDielectricAnisotropicBxDF; - using scalar_type = typename Config::scalar_type; - using vector2_type = vector; - using vector3_type = vector; - using matrix3x3_type = matrix; - using monochrome_type = vector; - using ray_dir_info_type = typename Config::ray_dir_info_type; - - using isotropic_interaction_type = typename Config::isotropic_interaction_type; - using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; - using sample_type = typename Config::sample_type; - using spectral_type = typename Config::spectral_type; - using quotient_pdf_type = sampling::quotient_and_pdf; - using isocache_type = typename Config::isocache_type; - using anisocache_type = typename Config::anisocache_type; + NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector3_type, Config); + NBL_BXDF_CONFIG_ALIAS(matrix3x3_type, Config); + NBL_BXDF_CONFIG_ALIAS(monochrome_type, Config); + NBL_BXDF_CONFIG_ALIAS(ray_dir_info_type, Config); + + NBL_BXDF_CONFIG_ALIAS(isotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(anisotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(sample_type, Config); + NBL_BXDF_CONFIG_ALIAS(spectral_type, Config); + NBL_BXDF_CONFIG_ALIAS(quotient_pdf_type, Config); + NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); + NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); using brdf_type = reflection::SBeckmannAnisotropicBxDF; using params_isotropic_t = BeckmannParams; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 09a3a39869..94847a5a64 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -106,20 +106,20 @@ template; - using scalar_type = typename Config::scalar_type; - using vector2_type = vector; - using vector3_type = vector; - using matrix3x3_type = matrix; - using monochrome_type = vector; - using ray_dir_info_type = typename Config::ray_dir_info_type; - - using isotropic_interaction_type = typename Config::isotropic_interaction_type; - using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; - using sample_type = typename Config::sample_type; - using spectral_type = typename Config::spectral_type; - using quotient_pdf_type = typename Config::quotient_pdf_type; - using isocache_type = typename Config::isocache_type; - using anisocache_type = typename Config::anisocache_type; + NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector3_type, Config); + NBL_BXDF_CONFIG_ALIAS(matrix3x3_type, Config); + NBL_BXDF_CONFIG_ALIAS(monochrome_type, Config); + NBL_BXDF_CONFIG_ALIAS(ray_dir_info_type, Config); + + NBL_BXDF_CONFIG_ALIAS(isotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(anisotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(sample_type, Config); + NBL_BXDF_CONFIG_ALIAS(spectral_type, Config); + NBL_BXDF_CONFIG_ALIAS(quotient_pdf_type, Config); + NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); + NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); using brdf_type = reflection::SGGXIsotropicBxDF; using params_isotropic_t = GGXParams; @@ -241,20 +241,20 @@ NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration) struct SGGXDielectricAnisotropicBxDF) > { using this_t = SGGXDielectricAnisotropicBxDF; - using scalar_type = typename Config::scalar_type; - using vector2_type = vector; - using vector3_type = vector; - using matrix3x3_type = matrix; - using monochrome_type = vector; - using ray_dir_info_type = typename Config::ray_dir_info_type; - - using isotropic_interaction_type = typename Config::isotropic_interaction_type; - using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; - using sample_type = typename Config::sample_type; - using spectral_type = typename Config::spectral_type; - using quotient_pdf_type = typename Config::quotient_pdf_type; - using isocache_type = typename Config::isocache_type; - using anisocache_type = typename Config::anisocache_type; + NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector3_type, Config); + NBL_BXDF_CONFIG_ALIAS(matrix3x3_type, Config); + NBL_BXDF_CONFIG_ALIAS(monochrome_type, Config); + NBL_BXDF_CONFIG_ALIAS(ray_dir_info_type, Config); + + NBL_BXDF_CONFIG_ALIAS(isotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(anisotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(sample_type, Config); + NBL_BXDF_CONFIG_ALIAS(spectral_type, Config); + NBL_BXDF_CONFIG_ALIAS(quotient_pdf_type, Config); + NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); + NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); using brdf_type = reflection::SGGXAnisotropicBxDF; using params_isotropic_t = GGXParams; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl index 5eb9e4d599..bb2f5fa485 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl @@ -87,13 +87,13 @@ template; - using scalar_type = typename Config::scalar_type; - using ray_dir_info_type = typename Config::ray_dir_info_type; - using isotropic_interaction_type = typename Config::isotropic_interaction_type; - using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; - using sample_type = typename Config::sample_type; - using spectral_type = typename Config::spectral_type; - using quotient_pdf_type = typename Config::quotient_pdf_type; + NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); + NBL_BXDF_CONFIG_ALIAS(ray_dir_info_type, Config); + NBL_BXDF_CONFIG_ALIAS(isotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(anisotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(sample_type, Config); + NBL_BXDF_CONFIG_ALIAS(spectral_type, Config); + NBL_BXDF_CONFIG_ALIAS(quotient_pdf_type, Config); using params_isotropic_t = LambertianParams; using params_anisotropic_t = LambertianParams; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index 4c59299171..ca931aaa79 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -85,16 +85,16 @@ template; - using scalar_type = typename Config::scalar_type; - using vector2_type = vector; - using vector3_type = vector; - using monochrome_type = vector; - using ray_dir_info_type = typename Config::ray_dir_info_type; - using isotropic_interaction_type = typename Config::isotropic_interaction_type; - using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; - using sample_type = typename Config::sample_type; - using spectral_type = typename Config::spectral_type; - using quotient_pdf_type = typename Config::quotient_pdf_type; + NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector3_type, Config); + NBL_BXDF_CONFIG_ALIAS(monochrome_type, Config); + NBL_BXDF_CONFIG_ALIAS(ray_dir_info_type, Config); + NBL_BXDF_CONFIG_ALIAS(isotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(anisotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(sample_type, Config); + NBL_BXDF_CONFIG_ALIAS(spectral_type, Config); + NBL_BXDF_CONFIG_ALIAS(quotient_pdf_type, Config); using params_isotropic_t = SmoothDielectricParams; using params_anisotropic_t = SmoothDielectricParams; @@ -192,16 +192,16 @@ template; - using scalar_type = typename Config::scalar_type; - using vector2_type = vector; - using vector3_type = vector; - using monochrome_type = vector; - using ray_dir_info_type = typename Config::ray_dir_info_type; - using isotropic_interaction_type = typename Config::isotropic_interaction_type; - using anisotropic_interaction_type = typename Config::anisotropic_interaction_type; - using sample_type = typename Config::sample_type; - using spectral_type = typename Config::spectral_type; - using quotient_pdf_type = typename Config::quotient_pdf_type; + NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector3_type, Config); + NBL_BXDF_CONFIG_ALIAS(monochrome_type, Config); + NBL_BXDF_CONFIG_ALIAS(ray_dir_info_type, Config); + NBL_BXDF_CONFIG_ALIAS(isotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(anisotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(sample_type, Config); + NBL_BXDF_CONFIG_ALIAS(spectral_type, Config); + NBL_BXDF_CONFIG_ALIAS(quotient_pdf_type, Config); using params_isotropic_t = SmoothDielectricParams; using params_anisotropic_t = SmoothDielectricParams; From 683c7f9e99fc465471c98cdb1a07dd15b330d0d6 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 5 Aug 2025 16:02:37 +0700 Subject: [PATCH 161/188] minor fixes to LightSample create, quotient_pdf --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 3 +-- .../builtin/hlsl/bxdf/reflection/beckmann.hlsl | 2 +- include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 2 +- .../builtin/hlsl/bxdf/reflection/lambertian.hlsl | 15 +++++---------- .../builtin/hlsl/bxdf/reflection/oren_nayar.hlsl | 6 +++--- .../builtin/hlsl/bxdf/transmission/beckmann.hlsl | 6 +++--- .../nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl | 6 +++--- .../hlsl/bxdf/transmission/lambertian.hlsl | 15 +++++---------- .../hlsl/bxdf/transmission/smooth_dielectric.hlsl | 4 ++-- .../builtin/hlsl/sampling/quotient_and_pdf.hlsl | 12 +++++++++++- 10 files changed, 35 insertions(+), 36 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index f6ff801abe..d72bf37d0e 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -323,7 +323,7 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getBdotL2()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getNdotL(clampMode)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((_sample.getNdotL2()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createFromTangentSpace(pV,rdirinfo,frame)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::createFromTangentSpace(rdirinfo,frame)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(rdirinfo,pV)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::create(rdirinfo,pV,pV,pV)), ::nbl::hlsl::is_same_v, T)) // ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::template create >(pV,inter)), ::nbl::hlsl::is_same_v, T)) // NOTE: temporarily commented out due to dxc bug https://github.com/microsoft/DirectXShaderCompiler/issues/7154 @@ -348,7 +348,6 @@ struct SLightSample using matrix3x3_type = matrix; static this_t createFromTangentSpace( - NBL_CONST_REF_ARG(vector3_type) tangentSpaceV, NBL_CONST_REF_ARG(ray_dir_info_type) tangentSpaceL, NBL_CONST_REF_ARG(matrix3x3_type) tangentFrame ) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 480fbb1465..20d699aa05 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -412,7 +412,7 @@ struct SBeckmannAnisotropicBxDF r = bxdf::Reflect::create(localV, H); localL.direction = r(cache.iso_cache.getVdotH()); - return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); + return sample_type::createFromTangentSpace(localL, interaction.getFromTangentSpace()); } scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 4c88396a3f..619bc9cd21 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -365,7 +365,7 @@ struct SGGXAnisotropicBxDF r = bxdf::Reflect::create(localV, H); localL.direction = r(cache.iso_cache.getVdotH()); - return sample_type::createFromTangentSpace(localV, localL, interaction.getFromTangentSpace()); + return sample_type::createFromTangentSpace(localL, interaction.getFromTangentSpace()); } scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl index 90ca2dea58..a28df7b0fa 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl @@ -105,25 +105,20 @@ struct SLambertianBxDF return retval; } - scalar_type __eval_pi_factored_out(scalar_type maxNdotL) - { - return maxNdotL; - } - scalar_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) { - return __eval_pi_factored_out(params.getNdotL()) * numbers::inv_pi; + return params.getNdotL() * numbers::inv_pi; } scalar_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) { - return __eval_pi_factored_out(params.getNdotL()) * numbers::inv_pi; + return params.getNdotL() * numbers::inv_pi; } sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector) u) { ray_dir_info_type L; L.direction = sampling::ProjectedHemisphere::generate(u); - return sample_type::createFromTangentSpace(interaction.getTangentSpaceV(), L, interaction.getFromTangentSpace()); + return sample_type::createFromTangentSpace(L, interaction.getFromTangentSpace()); } sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector) u) @@ -148,12 +143,12 @@ struct SLambertianBxDF quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) { sampling::quotient_and_pdf, scalar_type> qp = sampling::ProjectedHemisphere::template quotient_and_pdf(params.getNdotL()); - return quotient_pdf_type::create(hlsl::promote(qp.quotient[0]), qp.pdf); + return quotient_pdf_type::create(qp.quotient[0], qp.pdf); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { sampling::quotient_and_pdf, scalar_type> qp = sampling::ProjectedHemisphere::template quotient_and_pdf(params.getNdotL()); - return quotient_pdf_type::create(hlsl::promote(qp.quotient[0]), qp.pdf); + return quotient_pdf_type::create(qp.quotient[0], qp.pdf); } }; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl index 66edca4761..726f2d2cf5 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl @@ -130,7 +130,7 @@ struct SOrenNayarBxDF { ray_dir_info_type L; L.direction = sampling::ProjectedHemisphere::generate(u); - return sample_type::createFromTangentSpace(interaction.getTangentSpaceV(), L, interaction.getFromTangentSpace()); + return sample_type::createFromTangentSpace(L, interaction.getFromTangentSpace()); } sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector2_type) u) @@ -156,13 +156,13 @@ struct SOrenNayarBxDF { scalar_type _pdf = pdf(params); scalar_type q = __rec_pi_factored_out_wo_clamps(params.getVdotL(), params.getNdotL(), params.getNdotV()); - return quotient_pdf_type::create(hlsl::promote(q), _pdf); + return quotient_pdf_type::create(q, _pdf); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { scalar_type _pdf = pdf(params); scalar_type q = __rec_pi_factored_out_wo_clamps(params.getVdotL(), params.getNdotL(), params.getNdotV()); - return quotient_pdf_type::create(hlsl::promote(q), _pdf); + return quotient_pdf_type::create(q, _pdf); } scalar_type A; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index f047011ab6..3e19858eed 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -231,7 +231,7 @@ struct SBeckmannDielectricIsotropicBxDF query.onePlusLambda_V = onePlusLambda_V; scalar_type quo = beckmann_ndf.template G2_over_G1, isocache_type>(query, params.cache); - return quotient_pdf_type::create(hlsl::promote(quo), _pdf); + return quotient_pdf_type::create(quo, _pdf); } scalar_type A; @@ -336,7 +336,7 @@ struct SBeckmannDielectricAnisotropicBxDF, anisocache_type>(query, params.cache); - return quotient_pdf_type::create(hlsl::promote(quo), _pdf); + return quotient_pdf_type::create(quo, _pdf); } vector2_type A; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 94847a5a64..63030a33b3 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -229,7 +229,7 @@ struct SGGXDielectricIsotropicBxDF scalar_type quo; quo = ggx_ndf.template G2_over_G1, sample_type, isotropic_interaction_type, isocache_type>(g2_query, params._sample, params.interaction, params.cache); - return quotient_pdf_type::create(hlsl::promote(quo), _pdf); + return quotient_pdf_type::create(quo, _pdf); } scalar_type A; @@ -333,7 +333,7 @@ struct SGGXDielectricAnisotropicBxDF, sample_type, anisotropic_interaction_type, anisocache_type>(g2_query, params._sample, params.interaction, params.cache); - return quotient_pdf_type::create(hlsl::promote(quo), _pdf); + return quotient_pdf_type::create(quo, _pdf); } vector2_type A; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl index bb2f5fa485..843ad6bb4c 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl @@ -106,25 +106,20 @@ struct SLambertianBxDF return retval; } - scalar_type __eval_pi_factored_out(scalar_type absNdotL) - { - return absNdotL; - } - scalar_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) { - return __eval_pi_factored_out(params.getNdotL()) * numbers::inv_pi * 0.5; + return params.getNdotL() * numbers::inv_pi * 0.5; } scalar_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) { - return __eval_pi_factored_out(params.getNdotL()) * numbers::inv_pi * 0.5; + return params.getNdotL() * numbers::inv_pi * 0.5; } sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector) u) { ray_dir_info_type L; L.direction = sampling::ProjectedSphere::generate(u); - return sample_type::createFromTangentSpace(interaction.getTangentSpaceV(), L, interaction.getFromTangentSpace()); + return sample_type::createFromTangentSpace(L, interaction.getFromTangentSpace()); } sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector) u) @@ -149,12 +144,12 @@ struct SLambertianBxDF quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) { sampling::quotient_and_pdf, scalar_type> qp = sampling::ProjectedSphere::template quotient_and_pdf(params.getNdotL()); - return quotient_pdf_type::create(hlsl::promote(qp.quotient[0]), qp.pdf); + return quotient_pdf_type::create(qp.quotient[0], qp.pdf); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { sampling::quotient_and_pdf, scalar_type> qp = sampling::ProjectedSphere::template quotient_and_pdf(params.getNdotL()); - return quotient_pdf_type::create(hlsl::promote(qp.quotient[0]), qp.pdf); + return quotient_pdf_type::create(qp.quotient[0], qp.pdf); } }; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index ca931aaa79..44bb3ca024 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -172,7 +172,7 @@ struct SSmoothDielectricBxDF const scalar_type _pdf = bit_cast(numeric_limits::infinity); scalar_type quo = hlsl::mix(1.0, rcpOrientedEtas.value[0], transmitted); - return quotient_pdf_type::create(hlsl::promote(quo), _pdf); + return quotient_pdf_type::create(quo, _pdf); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) { @@ -182,7 +182,7 @@ struct SSmoothDielectricBxDF const scalar_type _pdf = bit_cast(numeric_limits::infinity); scalar_type quo = hlsl::mix(1.0, rcpOrientedEtas.value[0], transmitted); - return quotient_pdf_type::create(hlsl::promote(quo), _pdf); + return quotient_pdf_type::create(quo, _pdf); } scalar_type eta; diff --git a/include/nbl/builtin/hlsl/sampling/quotient_and_pdf.hlsl b/include/nbl/builtin/hlsl/sampling/quotient_and_pdf.hlsl index 6aebd583ea..26a62ea617 100644 --- a/include/nbl/builtin/hlsl/sampling/quotient_and_pdf.hlsl +++ b/include/nbl/builtin/hlsl/sampling/quotient_and_pdf.hlsl @@ -20,7 +20,9 @@ template; - static this_t create(NBL_CONST_REF_ARG(Q) _quotient, NBL_CONST_REF_ARG(P) _pdf) + using scalar_q = typename vector_traits::scalar_type; + + static this_t create(const Q _quotient, const P _pdf) { this_t retval; retval.quotient = _quotient; @@ -28,6 +30,14 @@ struct quotient_and_pdf return retval; } + static this_t create(const scalar_q _quotient, const P _pdf) + { + this_t retval; + retval.quotient = hlsl::promote(_quotient); + retval.pdf = _pdf; + return retval; + } + Q value() { return quotient*pdf; From fed36ffc3c76bb6b9f296c9e30a942e5adf5580e Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 5 Aug 2025 17:05:33 +0700 Subject: [PATCH 162/188] removed using existing param struct in basic bxdfs --- .../hlsl/bxdf/reflection/lambertian.hlsl | 30 +++++---- .../hlsl/bxdf/reflection/oren_nayar.hlsl | 32 +++++----- .../hlsl/bxdf/transmission/lambertian.hlsl | 29 +++++---- .../bxdf/transmission/smooth_dielectric.hlsl | 61 +++++++------------ 4 files changed, 66 insertions(+), 86 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl index a28df7b0fa..beaa72da50 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl @@ -92,12 +92,15 @@ struct SLambertianBxDF NBL_BXDF_CONFIG_ALIAS(anisotropic_interaction_type, Config); NBL_BXDF_CONFIG_ALIAS(sample_type, Config); NBL_BXDF_CONFIG_ALIAS(spectral_type, Config); + NBL_BXDF_CONFIG_ALIAS(monochrome_type, Config); NBL_BXDF_CONFIG_ALIAS(quotient_pdf_type, Config); + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_MAX; + + // TODO needs removing when all bxdfs changed using params_isotropic_t = LambertianParams; using params_anisotropic_t = LambertianParams; - static this_t create() { this_t retval; @@ -105,13 +108,13 @@ struct SLambertianBxDF return retval; } - scalar_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) + scalar_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) { - return params.getNdotL() * numbers::inv_pi; + return _sample.getNdotL(_clamp) * numbers::inv_pi; } - scalar_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) + scalar_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) { - return params.getNdotL() * numbers::inv_pi; + return eval(_sample, interaction.isotropic); } sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector) u) @@ -131,24 +134,19 @@ struct SLambertianBxDF return generate_wo_clamps(anisotropic_interaction_type::create(interaction), u); } - scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample) { - return sampling::ProjectedHemisphere::pdf(params.getNdotL()); - } - scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) - { - return sampling::ProjectedHemisphere::pdf(params.getNdotL()); + return sampling::ProjectedHemisphere::pdf(_sample.getNdotL(_clamp)); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) { - sampling::quotient_and_pdf, scalar_type> qp = sampling::ProjectedHemisphere::template quotient_and_pdf(params.getNdotL()); + sampling::quotient_and_pdf qp = sampling::ProjectedHemisphere::template quotient_and_pdf(_sample.getNdotL(_clamp)); return quotient_pdf_type::create(qp.quotient[0], qp.pdf); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) { - sampling::quotient_and_pdf, scalar_type> qp = sampling::ProjectedHemisphere::template quotient_and_pdf(params.getNdotL()); - return quotient_pdf_type::create(qp.quotient[0], qp.pdf); + return quotient_and_pdf(_sample, interaction.isotropic); } }; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl index 726f2d2cf5..95d671dd61 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl @@ -97,6 +97,9 @@ struct SOrenNayarBxDF NBL_BXDF_CONFIG_ALIAS(spectral_type, Config); NBL_BXDF_CONFIG_ALIAS(quotient_pdf_type, Config); + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_MAX; + + // TODO needs removing when all bxdfs changed using params_isotropic_t = OrenNayarParams; using params_anisotropic_t = OrenNayarParams; @@ -117,13 +120,14 @@ struct SOrenNayarBxDF return (AB.x + AB.y * cos_phi_sin_theta * C); } - scalar_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) + scalar_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) { - return params.getNdotL() * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(params.getVdotL(), params.getNdotL(), params.getNdotV()); + scalar_type NdotL = _sample.getNdotL(_clamp); + return NdotL * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(hlsl::dot(interaction.getV().getDirection(), _sample.getL().getDirection()), NdotL, interaction.getNdotV(_clamp)); } - scalar_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) + scalar_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) { - return params.getNdotL() * numbers::inv_pi * __rec_pi_factored_out_wo_clamps(params.getVdotL(), params.getNdotL(), params.getNdotV()); + return eval(_sample, interaction.isotropic); } sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector2_type) u) @@ -143,26 +147,20 @@ struct SOrenNayarBxDF return generate_wo_clamps(anisotropic_interaction_type::create(interaction), u); } - scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) - { - return sampling::ProjectedHemisphere::pdf(params.getNdotL()); - } - scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) + scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample) { - return sampling::ProjectedHemisphere::pdf(params.getNdotL()); + return sampling::ProjectedHemisphere::pdf(_sample.getNdotL(_clamp)); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) { - scalar_type _pdf = pdf(params); - scalar_type q = __rec_pi_factored_out_wo_clamps(params.getVdotL(), params.getNdotL(), params.getNdotV()); + scalar_type _pdf = pdf(_sample); + scalar_type q = __rec_pi_factored_out_wo_clamps(hlsl::dot(interaction.getV().getDirection(), _sample.getL().getDirection()), _sample.getNdotL(_clamp), interaction.getNdotV(_clamp)); return quotient_pdf_type::create(q, _pdf); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) { - scalar_type _pdf = pdf(params); - scalar_type q = __rec_pi_factored_out_wo_clamps(params.getVdotL(), params.getNdotL(), params.getNdotV()); - return quotient_pdf_type::create(q, _pdf); + return quotient_and_pdf(_sample, interaction.isotropic); } scalar_type A; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl index 843ad6bb4c..bfdd3a5c08 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl @@ -93,8 +93,12 @@ struct SLambertianBxDF NBL_BXDF_CONFIG_ALIAS(anisotropic_interaction_type, Config); NBL_BXDF_CONFIG_ALIAS(sample_type, Config); NBL_BXDF_CONFIG_ALIAS(spectral_type, Config); + NBL_BXDF_CONFIG_ALIAS(monochrome_type, Config); NBL_BXDF_CONFIG_ALIAS(quotient_pdf_type, Config); + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; + + // TODO needs removing when all bxdfs changed using params_isotropic_t = LambertianParams; using params_anisotropic_t = LambertianParams; @@ -106,13 +110,13 @@ struct SLambertianBxDF return retval; } - scalar_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) + scalar_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) { - return params.getNdotL() * numbers::inv_pi * 0.5; + return _sample.getNdotL(_clamp) * numbers::inv_pi * 0.5; } - scalar_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) + scalar_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) { - return params.getNdotL() * numbers::inv_pi * 0.5; + return eval(_sample, interaction.isotropic); } sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector) u) @@ -132,24 +136,19 @@ struct SLambertianBxDF return generate_wo_clamps(anisotropic_interaction_type::create(interaction), u); } - scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) - { - return sampling::ProjectedSphere::pdf(params.getNdotL()); - } - scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) + scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample) { - return sampling::ProjectedSphere::pdf(params.getNdotL()); + return sampling::ProjectedSphere::pdf(_sample.getNdotL(_clamp)); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) { - sampling::quotient_and_pdf, scalar_type> qp = sampling::ProjectedSphere::template quotient_and_pdf(params.getNdotL()); + sampling::quotient_and_pdf qp = sampling::ProjectedSphere::template quotient_and_pdf(_sample.getNdotL(_clamp)); return quotient_pdf_type::create(qp.quotient[0], qp.pdf); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) { - sampling::quotient_and_pdf, scalar_type> qp = sampling::ProjectedSphere::template quotient_and_pdf(params.getNdotL()); - return quotient_pdf_type::create(qp.quotient[0], qp.pdf); + return quotient_and_pdf(_sample, interaction.isotropic); } }; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index 44bb3ca024..101e93149c 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -96,6 +96,9 @@ struct SSmoothDielectricBxDF NBL_BXDF_CONFIG_ALIAS(spectral_type, Config); NBL_BXDF_CONFIG_ALIAS(quotient_pdf_type, Config); + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; + + // TODO needs removing when all bxdfs changed using params_isotropic_t = SmoothDielectricParams; using params_anisotropic_t = SmoothDielectricParams; @@ -106,11 +109,11 @@ struct SSmoothDielectricBxDF return retval; } - spectral_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) { return hlsl::promote(0); } - spectral_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) { return hlsl::promote(0); } @@ -155,34 +158,24 @@ struct SSmoothDielectricBxDF } // eval and pdf return 0 because smooth dielectric/conductor BxDFs are dirac delta distributions, model perfectly specular objects that scatter light to only one outgoing direction - scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) - { - return 0; - } - scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) + scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample) { return 0; } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) { - const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(params.getNdotVUnclamped(), params.getNdotLUnclamped()); + const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(interaction.getNdotV(), _sample.getNdotL()); - fresnel::OrientedEtaRcps rcpOrientedEtas = fresnel::OrientedEtaRcps::create(params.getNdotV(), hlsl::promote(eta)); + fresnel::OrientedEtaRcps rcpOrientedEtas = fresnel::OrientedEtaRcps::create(interaction.getNdotV(_clamp), hlsl::promote(eta)); const scalar_type _pdf = bit_cast(numeric_limits::infinity); scalar_type quo = hlsl::mix(1.0, rcpOrientedEtas.value[0], transmitted); return quotient_pdf_type::create(quo, _pdf); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) { - const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(params.getNdotVUnclamped(), params.getNdotLUnclamped()); - - fresnel::OrientedEtaRcps rcpOrientedEtas = fresnel::OrientedEtaRcps::create(params.getNdotV(), hlsl::promote(eta)); - - const scalar_type _pdf = bit_cast(numeric_limits::infinity); - scalar_type quo = hlsl::mix(1.0, rcpOrientedEtas.value[0], transmitted); - return quotient_pdf_type::create(quo, _pdf); + return quotient_and_pdf(_sample, interaction.isotropic); } scalar_type eta; @@ -203,6 +196,9 @@ struct SSmoothThinDielectricBxDF NBL_BXDF_CONFIG_ALIAS(spectral_type, Config); NBL_BXDF_CONFIG_ALIAS(quotient_pdf_type, Config); + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; + + // TODO needs removing when all bxdfs changed using params_isotropic_t = SmoothDielectricParams; using params_anisotropic_t = SmoothDielectricParams; @@ -215,11 +211,11 @@ struct SSmoothThinDielectricBxDF return retval; } - spectral_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) { return hlsl::promote(0); } - spectral_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) { return hlsl::promote(0); } @@ -259,37 +255,26 @@ struct SSmoothThinDielectricBxDF return __generate_wo_clamps(interaction.isotropic.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.isotropic.getN(), NdotV, nbl::hlsl::abs(NdotV), u, eta2, luminosityContributionHint, dummy); } - scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) - { - return 0; - } - scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) + scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample) { return 0; } // isotropic only? - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) { - const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(params.getNdotVUnclamped(), params.getNdotLUnclamped()); - const spectral_type reflectance = fresnel::thinDielectricInfiniteScatter(fresnel::Dielectric::__call(eta2, params.getNdotV())); - const spectral_type sampleValue = hlsl::mix(reflectance, (spectral_type)(1.0) - reflectance, transmitted); + const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(interaction.getNdotV(), _sample.getNdotL()); + const spectral_type reflectance = fresnel::thinDielectricInfiniteScatter(fresnel::Dielectric::__call(eta2, interaction.getNdotV(_clamp))); + const spectral_type sampleValue = hlsl::mix(reflectance, hlsl::promote(1.0) - reflectance, transmitted); const scalar_type sampleProb = nbl::hlsl::dot(sampleValue,luminosityContributionHint); const scalar_type _pdf = bit_cast(numeric_limits::infinity); return quotient_pdf_type::create(sampleValue / sampleProb, _pdf); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) { - const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(params.getNdotVUnclamped(), params.getNdotLUnclamped()); - const spectral_type reflectance = fresnel::thinDielectricInfiniteScatter(fresnel::Dielectric::__call(eta2, params.getNdotV())); - const spectral_type sampleValue = hlsl::mix(reflectance, hlsl::promote(1.0) - reflectance, transmitted); - - const scalar_type sampleProb = nbl::hlsl::dot(sampleValue,luminosityContributionHint); - - const scalar_type _pdf = bit_cast(numeric_limits::infinity); - return quotient_pdf_type::create(sampleValue / sampleProb, _pdf); + return quotient_and_pdf(_sample, interaction.isotropic); } spectral_type eta2; From 1eaabaae6ccbdbd5033f415b806cfe7cb109478a Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 6 Aug 2025 14:52:20 +0700 Subject: [PATCH 163/188] removed usage of params structs in microfacet bxdfs, removed unused param structs --- .../hlsl/bxdf/reflection/beckmann.hlsl | 170 +++++------------ .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 171 +++++------------ .../hlsl/bxdf/reflection/lambertian.hlsl | 68 ------- .../hlsl/bxdf/reflection/oren_nayar.hlsl | 70 ------- .../hlsl/bxdf/transmission/beckmann.hlsl | 174 +++++------------ .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 180 +++++------------- .../hlsl/bxdf/transmission/lambertian.hlsl | 69 ------- .../bxdf/transmission/smooth_dielectric.hlsl | 73 ------- 8 files changed, 182 insertions(+), 793 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 20d699aa05..5689427758 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -18,86 +18,6 @@ namespace bxdf namespace reflection { -template -struct BeckmannParams; - -template -NBL_PARTIAL_REQ_TOP(!surface_interactions::Anisotropic && !AnisotropicMicrofacetCache) -struct BeckmannParams && !AnisotropicMicrofacetCache) > -{ - using this_t = BeckmannParams; - - static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, NBL_CONST_REF_ARG(MC) cache, BxDFClampMode _clamp) - { - this_t retval; - retval._sample = _sample; - retval.interaction = interaction; - retval.cache = cache; - retval._clamp = _clamp; - return retval; - } - - // iso - Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } - Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } - Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return cache.getVdotL(); } - Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } - Scalar getNdotH2() NBL_CONST_MEMBER_FUNC { return cache.getNdotH2(); } - Scalar getVdotH() NBL_CONST_MEMBER_FUNC { return cache.getVdotH(); } - Scalar getLdotH() NBL_CONST_MEMBER_FUNC { return cache.getLdotH(); } - - LS _sample; - SI interaction; - MC cache; - BxDFClampMode _clamp; -}; -template -NBL_PARTIAL_REQ_TOP(surface_interactions::Anisotropic && AnisotropicMicrofacetCache) -struct BeckmannParams && AnisotropicMicrofacetCache) > -{ - using this_t = BeckmannParams; - - static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, NBL_CONST_REF_ARG(MC) cache, BxDFClampMode _clamp) - { - this_t retval; - retval._sample = _sample; - retval.interaction = interaction; - retval.cache = cache; - retval._clamp = _clamp; - return retval; - } - - // iso - Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } - Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } - Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return cache.getVdotL(); } - Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } - Scalar getNdotH2() NBL_CONST_MEMBER_FUNC { return cache.getNdotH2(); } - Scalar getVdotH() NBL_CONST_MEMBER_FUNC { return cache.getVdotH(); } - Scalar getLdotH() NBL_CONST_MEMBER_FUNC { return cache.getLdotH(); } - - // aniso - Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL2(); } - Scalar getBdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getBdotL2(); } - Scalar getTdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getTdotV2(); } - Scalar getBdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getBdotV2(); } - Scalar getTdotH2() NBL_CONST_MEMBER_FUNC { return cache.getTdotH2(); } - Scalar getBdotH2() NBL_CONST_MEMBER_FUNC { return cache.getBdotH2(); } - - LS _sample; - SI interaction; - MC cache; - BxDFClampMode _clamp; -}; - template struct SBeckmannAnisotropicBxDF; @@ -118,8 +38,7 @@ struct SBeckmannIsotropicBxDF NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); - using params_isotropic_t = BeckmannParams; - using params_anisotropic_t = BeckmannParams; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_MAX; template struct SBeckmannDG1Query @@ -159,29 +78,29 @@ struct SBeckmannIsotropicBxDF return retval; } - scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_isotropic_t) params) + scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { scalar_type a2 = A*A; ndf::Beckmann beckmann_ndf; beckmann_ndf.a2 = a2; - scalar_type NG = beckmann_ndf.template D(params.cache); + scalar_type NG = beckmann_ndf.template D(cache); if (a2 > numeric_limits::min) { SBeckmannG2overG1Query query; - query.lambda_L = beckmann_ndf.LambdaC2(params._sample.getNdotL2()); - query.onePlusLambda_V = scalar_type(1.0) + beckmann_ndf.LambdaC2(params.interaction.getNdotV2()); + query.lambda_L = beckmann_ndf.LambdaC2(_sample.getNdotL2()); + query.onePlusLambda_V = scalar_type(1.0) + beckmann_ndf.LambdaC2(interaction.getNdotV2()); NG *= beckmann_ndf.template correlated >(query); } return NG; } - spectral_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - if (params.getNdotVUnclamped() > numeric_limits::min) + if (interaction.getNdotV() > numeric_limits::min) { - const scalar_type scalar_part = __eval_DG_wo_clamps(params); - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, params.getNdotVUnclamped()); - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); + const scalar_type scalar_part = __eval_DG_wo_clamps(_sample, interaction, cache); + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, interaction.getNdotV()); + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); return f() * microfacet_transform; } else @@ -197,7 +116,7 @@ struct SBeckmannIsotropicBxDF return s; } - scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) + scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache, NBL_REF_ARG(scalar_type) onePlusLambda_V) { SBeckmannDG1Query dg1_query; dg1_query._clamp = BxDFClampMode::BCM_MAX; @@ -205,36 +124,36 @@ struct SBeckmannIsotropicBxDF scalar_type a2 = A*A; ndf::Beckmann beckmann_ndf; beckmann_ndf.a2 = a2; - dg1_query.ndf = beckmann_ndf.template D(params.cache); + dg1_query.ndf = beckmann_ndf.template D(cache); - dg1_query.lambda_V = beckmann_ndf.LambdaC2(params.getNdotV2()); + dg1_query.lambda_V = beckmann_ndf.LambdaC2(interaction.getNdotV2()); - scalar_type dg1 = beckmann_ndf.template DG1, isotropic_interaction_type>(dg1_query, params.interaction); + scalar_type dg1 = beckmann_ndf.template DG1, isotropic_interaction_type>(dg1_query, interaction); onePlusLambda_V = dg1_query.getOnePlusLambdaV(); return dg1; } - scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { scalar_type dummy; - return pdf(params, dummy); + return pdf(interaction, cache, dummy); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { scalar_type onePlusLambda_V; - scalar_type _pdf = pdf(params, onePlusLambda_V); + scalar_type _pdf = pdf(interaction, cache, onePlusLambda_V); ndf::Beckmann beckmann_ndf; spectral_type quo = (spectral_type)0.0; - if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) + if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) { beckmann_ndf.a2 = A*A; SBeckmannG2overG1Query query; - query.lambda_L = beckmann_ndf.LambdaC2(params._sample.getNdotL2()); + query.lambda_L = beckmann_ndf.LambdaC2(_sample.getNdotL2()); query.onePlusLambda_V = onePlusLambda_V; - scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1, isocache_type>(query, params.cache); - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); + scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1, isocache_type>(query, cache); + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; } @@ -264,8 +183,7 @@ struct SBeckmannAnisotropicBxDF; - using params_anisotropic_t = BeckmannParams; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_MAX; template struct SBeckmannDG1Query @@ -305,29 +223,29 @@ struct SBeckmannAnisotropicBxDF beckmann_ndf; beckmann_ndf.ax = A.x; beckmann_ndf.ay = A.y; - scalar_type NG = beckmann_ndf.template D(params.cache); + scalar_type NG = beckmann_ndf.template D(cache); if (hlsl::any >(A > (vector2_type)numeric_limits::min)) { SBeckmannG2overG1Query query; - query.lambda_L = beckmann_ndf.LambdaC2(params._sample.getTdotL2(), params._sample.getBdotL2(), params._sample.getNdotL2()); - query.onePlusLambda_V = scalar_type(1.0) + beckmann_ndf.LambdaC2(params.interaction.getTdotV2(), params.interaction.getBdotV2(), params.interaction.getNdotV2()); + query.lambda_L = beckmann_ndf.LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); + query.onePlusLambda_V = scalar_type(1.0) + beckmann_ndf.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); NG *= beckmann_ndf.template correlated >(query); } return NG; } - spectral_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - if (params.getNdotVUnclamped() > numeric_limits::min) + if (interaction.getNdotV() > numeric_limits::min) { - const scalar_type scalar_part = __eval_DG_wo_clamps(params); - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, params.getNdotVUnclamped()); - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); + const scalar_type scalar_part = __eval_DG_wo_clamps(_sample, interaction, cache); + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, interaction.getNdotV()); + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); return f() * microfacet_transform; } else @@ -415,7 +333,7 @@ struct SBeckmannAnisotropicBxDF dg1_query; dg1_query._clamp = BxDFClampMode::BCM_MAX; @@ -424,37 +342,37 @@ struct SBeckmannAnisotropicBxDF beckmann_ndf; beckmann_ndf.ax = A.x; beckmann_ndf.ay = A.y; - dg1_query.ndf = beckmann_ndf.template D(params.cache); + dg1_query.ndf = beckmann_ndf.template D(cache); - dg1_query.lambda_V = beckmann_ndf.LambdaC2(params.getTdotV2(), params.getBdotV2(), params.getNdotV2()); + dg1_query.lambda_V = beckmann_ndf.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); - scalar_type dg1 = beckmann_ndf.template DG1, anisotropic_interaction_type>(dg1_query, params.interaction); + scalar_type dg1 = beckmann_ndf.template DG1, anisotropic_interaction_type>(dg1_query, interaction); onePlusLambda_V = dg1_query.getOnePlusLambdaV(); return dg1; } - scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) + scalar_type pdf(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { scalar_type dummy; - return pdf(params, dummy); + return pdf(interaction, cache, dummy); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { scalar_type onePlusLambda_V; - scalar_type _pdf = pdf(params, onePlusLambda_V); + scalar_type _pdf = pdf(interaction, cache, onePlusLambda_V); ndf::Beckmann beckmann_ndf; spectral_type quo = (spectral_type)0.0; - if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) + if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) { beckmann_ndf.ax = A.x; beckmann_ndf.ay = A.y; SBeckmannG2overG1Query query; - query.lambda_L = beckmann_ndf.LambdaC2(params._sample.getTdotL2(), params._sample.getBdotL2(), params._sample.getNdotL2()); + query.lambda_L = beckmann_ndf.LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); query.onePlusLambda_V = onePlusLambda_V; - scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1, anisocache_type>(query, params.cache); - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); + scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1, anisocache_type>(query, cache); + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 619bc9cd21..b358d10c11 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -18,87 +18,6 @@ namespace bxdf namespace reflection { -template -struct GGXParams; - -template -NBL_PARTIAL_REQ_TOP(!surface_interactions::Anisotropic && !AnisotropicMicrofacetCache) -struct GGXParams && !AnisotropicMicrofacetCache) > -{ - using this_t = GGXParams; - - static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, NBL_CONST_REF_ARG(MC) cache, BxDFClampMode _clamp) - { - this_t retval; - retval._sample = _sample; - retval.interaction = interaction; - retval.cache = cache; - retval._clamp = _clamp; - return retval; - } - - // iso - Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } - Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } - Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return cache.getVdotL(); } - Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } - Scalar getNdotH2() NBL_CONST_MEMBER_FUNC { return cache.getNdotH2(); } - Scalar getVdotH() NBL_CONST_MEMBER_FUNC { return cache.getVdotH(); } - Scalar getLdotH() NBL_CONST_MEMBER_FUNC { return cache.getLdotH(); } - - LS _sample; - SI interaction; - MC cache; - BxDFClampMode _clamp; -}; -template -NBL_PARTIAL_REQ_TOP(surface_interactions::Anisotropic && AnisotropicMicrofacetCache) -struct GGXParams && AnisotropicMicrofacetCache) > -{ - using this_t = GGXParams; - - static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, NBL_CONST_REF_ARG(MC) cache, BxDFClampMode _clamp) - { - this_t retval; - retval._sample = _sample; - retval.interaction = interaction; - retval.cache = cache; - retval._clamp = _clamp; - return retval; - } - - // iso - Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } - Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } - Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return cache.getVdotL(); } - Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } - Scalar getNdotH2() NBL_CONST_MEMBER_FUNC { return cache.getNdotH2(); } - Scalar getVdotH() NBL_CONST_MEMBER_FUNC { return cache.getVdotH(); } - Scalar getLdotH() NBL_CONST_MEMBER_FUNC { return cache.getLdotH(); } - - // aniso - Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL2(); } - Scalar getBdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getBdotL2(); } - Scalar getTdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getTdotV2(); } - Scalar getBdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getBdotV2(); } - Scalar getTdotH2() NBL_CONST_MEMBER_FUNC { return cache.getTdotH2(); } - Scalar getBdotH2() NBL_CONST_MEMBER_FUNC { return cache.getBdotH2(); } - - LS _sample; - SI interaction; - MC cache; - BxDFClampMode _clamp; -}; - - template struct SGGXAnisotropicBxDF; @@ -119,8 +38,7 @@ struct SGGXIsotropicBxDF NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); - using params_isotropic_t = GGXParams; - using params_anisotropic_t = GGXParams; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_MAX; template struct SGGXDG1Query @@ -159,31 +77,31 @@ struct SGGXIsotropicBxDF return retval; } - scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(params_isotropic_t) params, BxDFClampMode _clamp) + scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache, BxDFClampMode _clamp) { scalar_type a2 = A*A; ndf::GGX ggx_ndf; ggx_ndf.a2 = a2; ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; - scalar_type NG = ggx_ndf.template D(params.cache); + scalar_type NG = ggx_ndf.template D(cache); if (a2 > numeric_limits::min) { SGGXG2XQuery g2_query; - g2_query.devsh_v = ggx_ndf.devsh_part(params.interaction.getNdotV2()); - g2_query.devsh_l = ggx_ndf.devsh_part(params._sample.getNdotL2()); + g2_query.devsh_v = ggx_ndf.devsh_part(interaction.getNdotV2()); + g2_query.devsh_l = ggx_ndf.devsh_part(_sample.getNdotL2()); g2_query._clamp = _clamp; - NG *= ggx_ndf.template correlated_wo_numerator, sample_type, isotropic_interaction_type>(g2_query, params._sample, params.interaction); + NG *= ggx_ndf.template correlated_wo_numerator, sample_type, isotropic_interaction_type>(g2_query, _sample, interaction); } return NG; } - spectral_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) + if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) { - const scalar_type scalar_part = __eval_DG_wo_clamps(params, BxDFClampMode::BCM_MAX); - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, params.getNdotL()); - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); + const scalar_type scalar_part = __eval_DG_wo_clamps(_sample, interaction, cache, BxDFClampMode::BCM_MAX); + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, _sample.getNdotL(_clamp)); + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); return f() * microfacet_transform; } else @@ -199,27 +117,27 @@ struct SGGXIsotropicBxDF return s; } - scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { SGGXDG1Query dg1_query; const scalar_type a2 = A*A; ndf::GGX ggx_ndf; ggx_ndf.a2 = a2; ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; - dg1_query.ndf = ggx_ndf.template D(params.cache); + dg1_query.ndf = ggx_ndf.template D(cache); - const scalar_type devsh_v = ggx_ndf.devsh_part(params.getNdotV2()); - dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(params.getNdotVUnclamped(), devsh_v); + const scalar_type devsh_v = ggx_ndf.devsh_part(interaction.getNdotV2()); + dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(interaction.getNdotV(_clamp), devsh_v); return ggx_ndf.template DG1 >(dg1_query); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - scalar_type _pdf = pdf(params); + scalar_type _pdf = pdf(interaction, cache); spectral_type quo = (spectral_type)0.0; - if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) + if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) { const scalar_type a2 = A*A; ndf::GGX ggx_ndf; @@ -227,12 +145,12 @@ struct SGGXIsotropicBxDF ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; SGGXG2XQuery g2_query; - g2_query.devsh_v = ggx_ndf.devsh_part(params.interaction.getNdotV2()); - g2_query.devsh_l = ggx_ndf.devsh_part(params._sample.getNdotL2()); + g2_query.devsh_v = ggx_ndf.devsh_part(interaction.getNdotV2()); + g2_query.devsh_l = ggx_ndf.devsh_part(_sample.getNdotL2()); g2_query._clamp = BxDFClampMode::BCM_MAX; - const scalar_type G2_over_G1 = ggx_ndf.template G2_over_G1, sample_type, isotropic_interaction_type, isocache_type>(g2_query, params._sample, params.interaction, params.cache); + const scalar_type G2_over_G1 = ggx_ndf.template G2_over_G1, sample_type, isotropic_interaction_type, isocache_type>(g2_query, _sample, interaction, cache); - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; } @@ -262,8 +180,7 @@ struct SGGXAnisotropicBxDF; - using params_anisotropic_t = GGXParams; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_MAX; template struct SGGXDG1Query @@ -302,31 +219,31 @@ struct SGGXAnisotropicBxDF ggx_ndf; ggx_ndf.ax2 = A.x*A.x; ggx_ndf.ay2 = A.y*A.y; ggx_ndf.a2 = A.x*A.y; - scalar_type NG = ggx_ndf.template D(params.cache); + scalar_type NG = ggx_ndf.template D(cache); if (any >(A > (vector2_type)numeric_limits::min)) { SGGXG2XQuery g2_query; - g2_query.devsh_v = ggx_ndf.devsh_part(params.interaction.getTdotV2(), params.interaction.getBdotV2(), params.interaction.getNdotV2()); - g2_query.devsh_l = ggx_ndf.devsh_part(params._sample.getTdotL2(), params._sample.getBdotL2(), params._sample.getNdotL2()); + g2_query.devsh_v = ggx_ndf.devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + g2_query.devsh_l = ggx_ndf.devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); g2_query._clamp = _clamp; - NG *= ggx_ndf.template correlated_wo_numerator, sample_type, anisotropic_interaction_type>(g2_query, params._sample, params.interaction); + NG *= ggx_ndf.template correlated_wo_numerator, sample_type, anisotropic_interaction_type>(g2_query, _sample, interaction); } return NG; } - spectral_type eval(NBL_CONST_REF_ARG(params_anisotropic_t) params) + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) + if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) { - const scalar_type scalar_part = __eval_DG_wo_clamps(params, BxDFClampMode::BCM_MAX); - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, params.getNdotL()); - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); + const scalar_type scalar_part = __eval_DG_wo_clamps(_sample, interaction, cache, BxDFClampMode::BCM_MAX); + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, _sample.getNdotL(_clamp)); + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); return f() * microfacet_transform; } else @@ -368,27 +285,27 @@ struct SGGXAnisotropicBxDF dg1_query; ndf::GGX ggx_ndf; ggx_ndf.ax2 = A.x*A.x; ggx_ndf.ay2 = A.y*A.y; ggx_ndf.a2 = A.x*A.y; - dg1_query.ndf = ggx_ndf.template D(params.cache); + dg1_query.ndf = ggx_ndf.template D(cache); - const scalar_type devsh_v = ggx_ndf.devsh_part(params.getTdotV2(), params.getBdotV2(), params.getNdotV2()); - dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(params.getNdotVUnclamped(), devsh_v); + const scalar_type devsh_v = ggx_ndf.devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(interaction.getNdotV(_clamp), devsh_v); return ggx_ndf.template DG1 >(dg1_query); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - scalar_type _pdf = pdf(params); + scalar_type _pdf = pdf(interaction, cache); spectral_type quo = (spectral_type)0.0; - if (params.getNdotLUnclamped() > numeric_limits::min && params.getNdotVUnclamped() > numeric_limits::min) + if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) { ndf::GGX ggx_ndf; ggx_ndf.ax2 = A.x*A.x; @@ -396,12 +313,12 @@ struct SGGXAnisotropicBxDF g2_query; - g2_query.devsh_v = ggx_ndf.devsh_part(params.interaction.getTdotV2(), params.interaction.getBdotV2(), params.interaction.getNdotV2()); - g2_query.devsh_l = ggx_ndf.devsh_part(params._sample.getTdotL2(), params._sample.getBdotL2(), params._sample.getNdotL2()); + g2_query.devsh_v = ggx_ndf.devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + g2_query.devsh_l = ggx_ndf.devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); g2_query._clamp = BxDFClampMode::BCM_MAX; - const scalar_type G2_over_G1 = ggx_ndf.template G2_over_G1, sample_type, anisotropic_interaction_type, anisocache_type>(g2_query, params._sample, params.interaction, params.cache); + const scalar_type G2_over_G1 = ggx_ndf.template G2_over_G1, sample_type, anisotropic_interaction_type, anisocache_type>(g2_query, _sample, interaction, cache); - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, params.getVdotH()); + fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl index beaa72da50..bc391dfdbd 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl @@ -18,70 +18,6 @@ namespace bxdf namespace reflection { -template -struct LambertianParams; - -template -NBL_PARTIAL_REQ_TOP(!surface_interactions::Anisotropic) -struct LambertianParams) > -{ - using this_t = LambertianParams; - - static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, BxDFClampMode _clamp) - { - this_t retval; - retval._sample = _sample; - retval.interaction = interaction; - retval._clamp = _clamp; - return retval; - } - - // iso - Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(); } - Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } - Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - - LS _sample; - SI interaction; - BxDFClampMode _clamp; -}; -template -NBL_PARTIAL_REQ_TOP(surface_interactions::Anisotropic) -struct LambertianParams) > -{ - using this_t = LambertianParams; - - static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, BxDFClampMode _clamp) - { - this_t retval; - retval._sample = _sample; - retval.interaction = interaction; - retval._clamp = _clamp; - return retval; - } - - // iso - Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } - Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } - Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - - // aniso - Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL2(); } - Scalar getBdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getBdotL2(); } - Scalar getTdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getTdotV2(); } - Scalar getBdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getBdotV2(); } - - LS _sample; - SI interaction; - BxDFClampMode _clamp; -}; - template) struct SLambertianBxDF { @@ -97,10 +33,6 @@ struct SLambertianBxDF NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_MAX; - // TODO needs removing when all bxdfs changed - using params_isotropic_t = LambertianParams; - using params_anisotropic_t = LambertianParams; - static this_t create() { this_t retval; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl index 95d671dd61..721e4ae994 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl @@ -18,72 +18,6 @@ namespace bxdf namespace reflection { -template -struct OrenNayarParams; - -template -NBL_PARTIAL_REQ_TOP(!surface_interactions::Anisotropic) -struct OrenNayarParams) > -{ - using this_t = OrenNayarParams; - - static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, BxDFClampMode _clamp) - { - this_t retval; - retval._sample = _sample; - retval.interaction = interaction; - retval._clamp = _clamp; - return retval; - } - - // iso - Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } - Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } - Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return hlsl::dot(interaction.getV().getDirection(), _sample.getL().getDirection()); } - - LS _sample; - SI interaction; - BxDFClampMode _clamp; -}; -template -NBL_PARTIAL_REQ_TOP(surface_interactions::Anisotropic) -struct OrenNayarParams) > -{ - using this_t = OrenNayarParams; - - static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, BxDFClampMode _clamp) - { - this_t retval; - retval._sample = _sample; - retval.interaction = interaction; - retval._clamp = _clamp; - return retval; - } - - // iso - Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } - Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } - Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return hlsl::dot(interaction.getV().getDirection(), _sample.getL().getDirection()); } - - // aniso - Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL2(); } - Scalar getBdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getBdotL2(); } - Scalar getTdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getTdotV2(); } - Scalar getBdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getBdotV2(); } - - LS _sample; - SI interaction; - BxDFClampMode _clamp; -}; - template) struct SOrenNayarBxDF { @@ -99,10 +33,6 @@ struct SOrenNayarBxDF NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_MAX; - // TODO needs removing when all bxdfs changed - using params_isotropic_t = OrenNayarParams; - using params_anisotropic_t = OrenNayarParams; - static this_t create(scalar_type A) { this_t retval; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 3e19858eed..0f5f6bb8a3 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -18,86 +18,6 @@ namespace bxdf namespace transmission { -template -struct BeckmannParams; - -template -NBL_PARTIAL_REQ_TOP(!surface_interactions::Anisotropic && !AnisotropicMicrofacetCache) -struct BeckmannParams && !AnisotropicMicrofacetCache) > -{ - using this_t = BeckmannParams; - - static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, NBL_CONST_REF_ARG(MC) cache, BxDFClampMode _clamp) - { - this_t retval; - retval._sample = _sample; - retval.interaction = interaction; - retval.cache = cache; - retval._clamp = _clamp; - return retval; - } - - // iso - Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } - Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } - Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return cache.getVdotL(); } - Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } - Scalar getNdotH2() NBL_CONST_MEMBER_FUNC { return cache.getNdotH2(); } - Scalar getVdotH() NBL_CONST_MEMBER_FUNC { return cache.getVdotH(); } - Scalar getLdotH() NBL_CONST_MEMBER_FUNC { return cache.getLdotH(); } - - LS _sample; - SI interaction; - MC cache; - BxDFClampMode _clamp; -}; -template -NBL_PARTIAL_REQ_TOP(surface_interactions::Anisotropic && AnisotropicMicrofacetCache) -struct BeckmannParams && AnisotropicMicrofacetCache) > -{ - using this_t = BeckmannParams; - - static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, NBL_CONST_REF_ARG(MC) cache, BxDFClampMode _clamp) - { - this_t retval; - retval._sample = _sample; - retval.interaction = interaction; - retval.cache = cache; - retval._clamp = _clamp; - return retval; - } - - // iso - Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } - Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } - Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return cache.getVdotL(); } - Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } - Scalar getNdotH2() NBL_CONST_MEMBER_FUNC { return cache.getNdotH2(); } - Scalar getVdotH() NBL_CONST_MEMBER_FUNC { return cache.getVdotH(); } - Scalar getLdotH() NBL_CONST_MEMBER_FUNC { return cache.getLdotH(); } - - // aniso - Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL2(); } - Scalar getBdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getBdotL2(); } - Scalar getTdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getTdotV2(); } - Scalar getBdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getBdotV2(); } - Scalar getTdotH2() NBL_CONST_MEMBER_FUNC { return cache.getTdotH2(); } - Scalar getBdotH2() NBL_CONST_MEMBER_FUNC { return cache.getBdotH2(); } - - LS _sample; - SI interaction; - MC cache; - BxDFClampMode _clamp; -}; - template struct SBeckmannDielectricAnisotropicBxDF; @@ -121,8 +41,7 @@ struct SBeckmannDielectricIsotropicBxDF NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); using brdf_type = reflection::SBeckmannIsotropicBxDF; - using params_isotropic_t = BeckmannParams; - using params_anisotropic_t = BeckmannParams; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; template struct SBeckmannDG1Query @@ -162,21 +81,20 @@ struct SBeckmannDielectricIsotropicBxDF return retval; } - spectral_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; - const scalar_type VdotHLdotH = params.cache.getVdotHLdotH(); - const bool transmitted = params.cache.isTransmission(); + const scalar_type VdotHLdotH = cache.getVdotHLdotH(); + const bool transmitted = cache.isTransmission(); spectral_type dummyior; brdf_type beckmann = brdf_type::create(A, dummyior, dummyior); - typename brdf_type::params_isotropic_t brdf_params = typename brdf_type::params_isotropic_t::create(params._sample, params.interaction, params.cache, params._clamp); - const scalar_type scalar_part = beckmann.__eval_DG_wo_clamps(brdf_params); + const scalar_type scalar_part = beckmann.__eval_DG_wo_clamps(_sample, interaction, cache); - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part,params.getNdotV(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); - const scalar_type f = fresnel::Dielectric::__call(orientedEta2, hlsl::abs(params.getVdotH()))[0]; + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part,interaction.getNdotV(_clamp),transmitted,cache.getVdotH(),cache.getLdotH(),VdotHLdotH,orientedEta.value[0]); + const scalar_type f = fresnel::Dielectric::__call(orientedEta2, hlsl::abs(cache.getVdotH()))[0]; return hlsl::promote(f) * microfacet_transform; } @@ -189,47 +107,47 @@ struct SBeckmannDielectricIsotropicBxDF return s; } - scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V) + scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache, NBL_REF_ARG(scalar_type) onePlusLambda_V) { SBeckmannDG1Query dg1_query; dg1_query._clamp = BxDFClampMode::BCM_ABS; - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; dg1_query.orientedEta = orientedEta.value[0]; - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; const scalar_type a2 = A*A; ndf::Beckmann beckmann_ndf; beckmann_ndf.a2 = a2; - dg1_query.ndf = beckmann_ndf.template D(params.cache); + dg1_query.ndf = beckmann_ndf.template D(cache); - dg1_query.lambda_V = beckmann_ndf.LambdaC2(params.getNdotV2()); + dg1_query.lambda_V = beckmann_ndf.LambdaC2(interaction.getNdotV2()); - scalar_type dg1 = beckmann_ndf.template DG1, isotropic_interaction_type, isocache_type>(dg1_query, params.interaction, params.cache); + scalar_type dg1 = beckmann_ndf.template DG1, isotropic_interaction_type, isocache_type>(dg1_query, interaction, cache); onePlusLambda_V = dg1_query.getOnePlusLambdaV(); - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, params.cache.isTransmission()) * dg1; + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * dg1; } - scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { scalar_type dummy; - return pdf(params, dummy); + return pdf(interaction, cache, dummy); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { scalar_type onePlusLambda_V; - scalar_type _pdf = pdf(params, onePlusLambda_V); + scalar_type _pdf = pdf(interaction, cache, onePlusLambda_V); ndf::Beckmann beckmann_ndf; beckmann_ndf.a2 = A*A; SBeckmannG2overG1Query query; - query.lambda_L = beckmann_ndf.LambdaC2(params._sample.getNdotL2()); + query.lambda_L = beckmann_ndf.LambdaC2(_sample.getNdotL2()); query.onePlusLambda_V = onePlusLambda_V; - scalar_type quo = beckmann_ndf.template G2_over_G1, isocache_type>(query, params.cache); + scalar_type quo = beckmann_ndf.template G2_over_G1, isocache_type>(query, cache); return quotient_pdf_type::create(quo, _pdf); } @@ -259,8 +177,7 @@ struct SBeckmannDielectricAnisotropicBxDF; - using params_isotropic_t = BeckmannParams; - using params_anisotropic_t = BeckmannParams; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; template struct SBeckmannDG1Query @@ -300,21 +217,20 @@ struct SBeckmannDielectricAnisotropicBxDF orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; - const scalar_type VdotHLdotH = params.cache.getVdotHLdotH(); - const bool transmitted = params.cache.isTransmission(); + const scalar_type VdotHLdotH = cache.getVdotHLdotH(); + const bool transmitted = cache.isTransmission(); spectral_type dummyior; brdf_type beckmann = brdf_type::create(A.x, A.y, dummyior, dummyior); - typename brdf_type::params_anisotropic_t brdf_params = typename brdf_type::params_anisotropic_t::create(params._sample, params.interaction, params.cache, params._clamp); - const scalar_type scalar_part = beckmann.__eval_DG_wo_clamps(brdf_params); + const scalar_type scalar_part = beckmann.__eval_DG_wo_clamps(_sample, interaction, cache); - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part,params.getNdotV(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); - const scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part,interaction.getNdotV(_clamp),transmitted,cache.getVdotH(),cache.getLdotH(),VdotHLdotH,orientedEta.value[0]); + const scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; return hlsl::promote(f) * microfacet_transform; } @@ -343,10 +259,10 @@ struct SBeckmannDielectricAnisotropicBxDF orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), hlsl::promote(eta)); - fresnel::OrientedEtaRcps rcpEta = fresnel::OrientedEtaRcps::create(interaction.isotropic.getNdotV(), hlsl::promote(eta)); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.getNdotV(), hlsl::promote(eta)); + fresnel::OrientedEtaRcps rcpEta = fresnel::OrientedEtaRcps::create(interaction.getNdotV(), hlsl::promote(eta)); - const vector3_type upperHemisphereV = hlsl::mix(localV, -localV, interaction.isotropic.getNdotV() < scalar_type(0.0)); + const vector3_type upperHemisphereV = hlsl::mix(localV, -localV, interaction.getNdotV() < scalar_type(0.0)); spectral_type dummyior; brdf_type beckmann = brdf_type::create(A.x, A.y, dummyior, dummyior); @@ -361,48 +277,48 @@ struct SBeckmannDielectricAnisotropicBxDF dg1_query; dg1_query._clamp = BxDFClampMode::BCM_ABS; - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; dg1_query.orientedEta = orientedEta.value[0]; - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; ndf::Beckmann beckmann_ndf; beckmann_ndf.ax = A.x; beckmann_ndf.ay = A.y; - dg1_query.ndf = beckmann_ndf.template D(params.cache); + dg1_query.ndf = beckmann_ndf.template D(cache); - dg1_query.lambda_V = beckmann_ndf.LambdaC2(params.getTdotV2(), params.getBdotV2(), params.getNdotV2()); + dg1_query.lambda_V = beckmann_ndf.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); - scalar_type dg1 = beckmann_ndf.template DG1, anisotropic_interaction_type, anisocache_type>(dg1_query, params.interaction, params.cache); + scalar_type dg1 = beckmann_ndf.template DG1, anisotropic_interaction_type, anisocache_type>(dg1_query, interaction, cache); onePlusLambda_V = dg1_query.getOnePlusLambdaV(); - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, params.cache.isTransmission()) * dg1; + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * dg1; } - scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) + scalar_type pdf(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { scalar_type dummy; - return pdf(params, dummy); + return pdf(interaction, cache, dummy); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { scalar_type onePlusLambda_V; - scalar_type _pdf = pdf(params, onePlusLambda_V); + scalar_type _pdf = pdf(interaction, cache, onePlusLambda_V); ndf::Beckmann beckmann_ndf; beckmann_ndf.ax = A.x; beckmann_ndf.ay = A.y; SBeckmannG2overG1Query query; - query.lambda_L = beckmann_ndf.LambdaC2(params._sample.getTdotL2(), params._sample.getBdotL2(), params._sample.getNdotL2()); + query.lambda_L = beckmann_ndf.LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); query.onePlusLambda_V = onePlusLambda_V; - scalar_type quo = beckmann_ndf.template G2_over_G1, anisocache_type>(query, params.cache); + scalar_type quo = beckmann_ndf.template G2_over_G1, anisocache_type>(query, cache); return quotient_pdf_type::create(quo, _pdf); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 63030a33b3..ec14856d48 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -18,87 +18,6 @@ namespace bxdf namespace transmission { -template -struct GGXParams; - -template -NBL_PARTIAL_REQ_TOP(!surface_interactions::Anisotropic && !AnisotropicMicrofacetCache) -struct GGXParams && !AnisotropicMicrofacetCache) > -{ - using this_t = GGXParams; - - static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, NBL_CONST_REF_ARG(MC) cache, BxDFClampMode _clamp) - { - this_t retval; - retval._sample = _sample; - retval.interaction = interaction; - retval.cache = cache; - retval._clamp = _clamp; - return retval; - } - - // iso - Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } - Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } - Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return cache.getVdotL(); } - Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } - Scalar getNdotH2() NBL_CONST_MEMBER_FUNC { return cache.getNdotH2(); } - Scalar getVdotH() NBL_CONST_MEMBER_FUNC { return cache.getVdotH(); } - Scalar getLdotH() NBL_CONST_MEMBER_FUNC { return cache.getLdotH(); } - - LS _sample; - SI interaction; - MC cache; - BxDFClampMode _clamp; -}; -template -NBL_PARTIAL_REQ_TOP(surface_interactions::Anisotropic && AnisotropicMicrofacetCache) -struct GGXParams && AnisotropicMicrofacetCache) > -{ - using this_t = GGXParams; - - static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, NBL_CONST_REF_ARG(MC) cache, BxDFClampMode _clamp) - { - this_t retval; - retval._sample = _sample; - retval.interaction = interaction; - retval.cache = cache; - retval._clamp = _clamp; - return retval; - } - - // iso - Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } - Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } - Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - Scalar getVdotL() NBL_CONST_MEMBER_FUNC { return cache.getVdotL(); } - Scalar getNdotH() NBL_CONST_MEMBER_FUNC { return cache.getNdotH(); } - Scalar getNdotH2() NBL_CONST_MEMBER_FUNC { return cache.getNdotH2(); } - Scalar getVdotH() NBL_CONST_MEMBER_FUNC { return cache.getVdotH(); } - Scalar getLdotH() NBL_CONST_MEMBER_FUNC { return cache.getLdotH(); } - - // aniso - Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL2(); } - Scalar getBdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getBdotL2(); } - Scalar getTdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getTdotV2(); } - Scalar getBdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getBdotV2(); } - Scalar getTdotH2() NBL_CONST_MEMBER_FUNC { return cache.getTdotH2(); } - Scalar getBdotH2() NBL_CONST_MEMBER_FUNC { return cache.getBdotH2(); } - - LS _sample; - SI interaction; - MC cache; - BxDFClampMode _clamp; -}; - - template struct SGGXDielectricAnisotropicBxDF; @@ -122,8 +41,10 @@ struct SGGXDielectricIsotropicBxDF NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); using brdf_type = reflection::SGGXIsotropicBxDF; - using params_isotropic_t = GGXParams; - using params_anisotropic_t = GGXParams; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; + + // using params_isotropic_t = GGXParams; + // using params_anisotropic_t = GGXParams; template struct SGGXDG1Query @@ -161,22 +82,21 @@ struct SGGXDielectricIsotropicBxDF return retval; } - spectral_type eval(NBL_CONST_REF_ARG(params_isotropic_t) params) + spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; - const scalar_type VdotHLdotH = params.cache.getVdotHLdotH(); - const bool transmitted = params.cache.isTransmission(); + const scalar_type VdotHLdotH = cache.getVdotHLdotH(); + const bool transmitted = cache.isTransmission(); scalar_type NG_already_in_reflective_dL_measure; spectral_type dummyior; brdf_type ggx = brdf_type::create(A, dummyior, dummyior); - typename brdf_type::params_isotropic_t brdf_params = typename brdf_type::params_isotropic_t::create(params._sample, params.interaction, params.cache, params._clamp); - NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(brdf_params, BxDFClampMode::BCM_ABS); + NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(_sample, interaction, cache, _clamp); - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(NG_already_in_reflective_dL_measure,params.getNdotL(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); - const scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(NG_already_in_reflective_dL_measure,_sample.getNdotL(_clamp),transmitted,cache.getVdotH(),cache.getLdotH(),VdotHLdotH,orientedEta.value[0]); + const scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; return hlsl::promote(f) * microfacet_transform; } @@ -189,32 +109,32 @@ struct SGGXDielectricIsotropicBxDF return s; } - scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { SGGXDG1Query dg1_query; - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; dg1_query.orientedEta = orientedEta.value[0]; - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; scalar_type devsh_v; const scalar_type a2 = A*A; ndf::GGX ggx_ndf; ggx_ndf.a2 = a2; ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; - dg1_query.ndf = ggx_ndf.template D(params.cache); + dg1_query.ndf = ggx_ndf.template D(cache); - devsh_v = ggx_ndf.devsh_part(params.getNdotV2()); - dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(params.getNdotV(), devsh_v); + devsh_v = ggx_ndf.devsh_part(interaction.getNdotV2()); + dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(interaction.getNdotV(_clamp), devsh_v); - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, params.cache.isTransmission()) * ggx_ndf.template DG1, isocache_type>(dg1_query, params.cache); + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * ggx_ndf.template DG1, isocache_type>(dg1_query, cache); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_isotropic_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - scalar_type _pdf = pdf(params); - const bool transmitted = params.cache.isTransmission(); + scalar_type _pdf = pdf(interaction, cache); + const bool transmitted = cache.isTransmission(); const scalar_type a2 = A * A; ndf::GGX ggx_ndf; @@ -222,12 +142,12 @@ struct SGGXDielectricIsotropicBxDF ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; SGGXG2XQuery g2_query; - g2_query.devsh_v = ggx_ndf.devsh_part(params.interaction.getNdotV2()); - g2_query.devsh_l = ggx_ndf.devsh_part(params._sample.getNdotL2()); - g2_query._clamp = BxDFClampMode::BCM_ABS; + g2_query.devsh_v = ggx_ndf.devsh_part(interaction.getNdotV2()); + g2_query.devsh_l = ggx_ndf.devsh_part(_sample.getNdotL2()); + g2_query._clamp = _clamp; scalar_type quo; - quo = ggx_ndf.template G2_over_G1, sample_type, isotropic_interaction_type, isocache_type>(g2_query, params._sample, params.interaction, params.cache); + quo = ggx_ndf.template G2_over_G1, sample_type, isotropic_interaction_type, isocache_type>(g2_query, _sample, interaction, cache); return quotient_pdf_type::create(quo, _pdf); } @@ -257,8 +177,7 @@ struct SGGXDielectricAnisotropicBxDF; - using params_isotropic_t = GGXParams; - using params_anisotropic_t = GGXParams; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; template struct SGGXDG1Query @@ -296,22 +215,21 @@ struct SGGXDielectricAnisotropicBxDF orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; - const scalar_type VdotHLdotH = params.cache.getVdotHLdotH(); - const bool transmitted = params.cache.isTransmission(); + const scalar_type VdotHLdotH = cache.getVdotHLdotH(); + const bool transmitted = cache.isTransmission(); scalar_type NG_already_in_reflective_dL_measure; spectral_type dummyior; brdf_type ggx = brdf_type::create(A.x, A.y, dummyior, dummyior); - typename brdf_type::params_anisotropic_t brdf_params = typename brdf_type::params_anisotropic_t::create(params._sample, params.interaction, params.cache, params._clamp); - NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(brdf_params, BxDFClampMode::BCM_ABS); + NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(_sample, interaction, cache, _clamp); - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(NG_already_in_reflective_dL_measure,params.getNdotL(),transmitted,params.getVdotH(),params.getLdotH(),VdotHLdotH,orientedEta.value[0]); - const scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; + const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(NG_already_in_reflective_dL_measure,_sample.getNdotL(_clamp),transmitted,cache.getVdotH(),cache.getLdotH(),VdotHLdotH,orientedEta.value[0]); + const scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; return hlsl::promote(f) * microfacet_transform; } @@ -340,10 +258,10 @@ struct SGGXDielectricAnisotropicBxDF orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), hlsl::promote(eta)); - fresnel::OrientedEtaRcps rcpEta = fresnel::OrientedEtaRcps::create(interaction.isotropic.getNdotV(), hlsl::promote(eta)); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.getNdotV(), hlsl::promote(eta)); + fresnel::OrientedEtaRcps rcpEta = fresnel::OrientedEtaRcps::create(interaction.getNdotV(), hlsl::promote(eta)); - const vector3_type upperHemisphereV = hlsl::mix(localV, -localV, interaction.isotropic.getNdotV() < scalar_type(0.0)); + const vector3_type upperHemisphereV = hlsl::mix(localV, -localV, interaction.getNdotV() < scalar_type(0.0)); spectral_type dummyior; brdf_type ggx = brdf_type::create(A.x, A.y, dummyior, dummyior); @@ -358,32 +276,32 @@ struct SGGXDielectricAnisotropicBxDF dg1_query; - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(params.getVdotH(), hlsl::promote(eta)); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; dg1_query.orientedEta = orientedEta.value[0]; - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(params.getVdotH()))[0]; + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; scalar_type devsh_v; ndf::GGX ggx_ndf; ggx_ndf.ax2 = A.x*A.x; ggx_ndf.ay2 = A.y*A.y; ggx_ndf.a2 = A.x*A.y; - dg1_query.ndf = ggx_ndf.template D(params.cache); + dg1_query.ndf = ggx_ndf.template D(cache); - devsh_v = ggx_ndf.devsh_part(params.getTdotV2(), params.getBdotV2(), params.getNdotV2()); - dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(params.getNdotV(), devsh_v); + devsh_v = ggx_ndf.devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(interaction.getNdotV(_clamp), devsh_v); - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, params.cache.isTransmission()) * ggx_ndf.template DG1, anisocache_type>(dg1_query, params.cache); + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * ggx_ndf.template DG1, anisocache_type>(dg1_query, cache); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - scalar_type _pdf = pdf(params); - const bool transmitted = params.cache.isTransmission(); + scalar_type _pdf = pdf(interaction, cache); + const bool transmitted = cache.isTransmission(); ndf::GGX ggx_ndf; ggx_ndf.ax2 = A.x*A.x; @@ -391,12 +309,12 @@ struct SGGXDielectricAnisotropicBxDF g2_query; - g2_query.devsh_v = ggx_ndf.devsh_part(params.interaction.getTdotV2(), params.interaction.getBdotV2(), params.interaction.getNdotV2()); - g2_query.devsh_l = ggx_ndf.devsh_part(params._sample.getTdotL2(), params._sample.getBdotL2(), params._sample.getNdotL2()); + g2_query.devsh_v = ggx_ndf.devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + g2_query.devsh_l = ggx_ndf.devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); g2_query._clamp = BxDFClampMode::BCM_ABS; scalar_type quo; - quo = ggx_ndf.template G2_over_G1, sample_type, anisotropic_interaction_type, anisocache_type>(g2_query, params._sample, params.interaction, params.cache); + quo = ggx_ndf.template G2_over_G1, sample_type, anisotropic_interaction_type, anisocache_type>(g2_query, _sample, interaction, cache); return quotient_pdf_type::create(quo, _pdf); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl index bfdd3a5c08..a38a046e04 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl @@ -19,70 +19,6 @@ namespace bxdf namespace transmission { -template -struct LambertianParams; - -template -NBL_PARTIAL_REQ_TOP(!surface_interactions::Anisotropic) -struct LambertianParams) > -{ - using this_t = LambertianParams; - - static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, BxDFClampMode _clamp) - { - this_t retval; - retval._sample = _sample; - retval.interaction = interaction; - retval._clamp = _clamp; - return retval; - } - - // iso - Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } - Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } - Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - - LS _sample; - SI interaction; - BxDFClampMode _clamp; -}; -template -NBL_PARTIAL_REQ_TOP(surface_interactions::Anisotropic) -struct LambertianParams) > -{ - using this_t = LambertianParams; - - static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, BxDFClampMode _clamp) - { - this_t retval; - retval._sample = _sample; - retval.interaction = interaction; - retval._clamp = _clamp; - return retval; - } - - // iso - Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } - Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } - Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - - // aniso - Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL2(); } - Scalar getBdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getBdotL2(); } - Scalar getTdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getTdotV2(); } - Scalar getBdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getBdotV2(); } - - LS _sample; - SI interaction; - BxDFClampMode _clamp; -}; - template) struct SLambertianBxDF { @@ -98,11 +34,6 @@ struct SLambertianBxDF NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; - // TODO needs removing when all bxdfs changed - using params_isotropic_t = LambertianParams; - using params_anisotropic_t = LambertianParams; - - static this_t create() { this_t retval; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index 101e93149c..6d0d501790 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -17,70 +17,6 @@ namespace bxdf namespace transmission { -template -struct SmoothDielectricParams; - -template -NBL_PARTIAL_REQ_TOP(!surface_interactions::Anisotropic) -struct SmoothDielectricParams) > -{ - using this_t = SmoothDielectricParams; - - static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, BxDFClampMode _clamp) - { - this_t retval; - retval._sample = _sample; - retval.interaction = interaction; - retval._clamp = _clamp; - return retval; - } - - // iso - Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } - Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } - Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - - LS _sample; - SI interaction; - BxDFClampMode _clamp; -}; -template -NBL_PARTIAL_REQ_TOP(surface_interactions::Anisotropic) -struct SmoothDielectricParams) > -{ - using this_t = SmoothDielectricParams; - - static this_t create(NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(SI) interaction, BxDFClampMode _clamp) - { - this_t retval; - retval._sample = _sample; - retval.interaction = interaction; - retval._clamp = _clamp; - return retval; - } - - // iso - Scalar getNdotV() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(_clamp); } - Scalar getNdotVUnclamped() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV(BxDFClampMode::BCM_NONE); } - Scalar getNdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getNdotV2(); } - Scalar getNdotL() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(_clamp); } - Scalar getNdotLUnclamped() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL(BxDFClampMode::BCM_NONE); } - Scalar getNdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getNdotL2(); } - - // aniso - Scalar getTdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getTdotL2(); } - Scalar getBdotL2() NBL_CONST_MEMBER_FUNC { return _sample.getBdotL2(); } - Scalar getTdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getTdotV2(); } - Scalar getBdotV2() NBL_CONST_MEMBER_FUNC { return interaction.getBdotV2(); } - - LS _sample; - SI interaction; - BxDFClampMode _clamp; -}; - template) struct SSmoothDielectricBxDF { @@ -98,10 +34,6 @@ struct SSmoothDielectricBxDF NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; - // TODO needs removing when all bxdfs changed - using params_isotropic_t = SmoothDielectricParams; - using params_anisotropic_t = SmoothDielectricParams; - static this_t create(scalar_type eta) { this_t retval; @@ -198,11 +130,6 @@ struct SSmoothThinDielectricBxDF NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; - // TODO needs removing when all bxdfs changed - using params_isotropic_t = SmoothDielectricParams; - using params_anisotropic_t = SmoothDielectricParams; - - static this_t create(NBL_CONST_REF_ARG(spectral_type) eta2, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint) { this_t retval; From eaa41ee068ec8296df38ccc86e3abceb1ee8c406 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 6 Aug 2025 16:20:19 +0700 Subject: [PATCH 164/188] don't pass vector by ref where not needed --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 38 +++++++++--------- .../hlsl/bxdf/reflection/beckmann.hlsl | 6 +-- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 6 +-- .../hlsl/bxdf/reflection/lambertian.hlsl | 12 ++---- .../hlsl/bxdf/reflection/oren_nayar.hlsl | 6 +-- .../hlsl/bxdf/transmission/beckmann.hlsl | 2 +- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 2 +- .../hlsl/bxdf/transmission/lambertian.hlsl | 7 ++-- .../bxdf/transmission/smooth_dielectric.hlsl | 39 ++++++------------- 9 files changed, 50 insertions(+), 68 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index d72bf37d0e..b91319d6e0 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -94,7 +94,7 @@ struct SBasic } // WARNING: matrix must be orthonormal - SBasic transform(NBL_CONST_REF_ARG(matrix3x3_type) m) NBL_CONST_MEMBER_FUNC + SBasic transform(const matrix3x3_type m) NBL_CONST_MEMBER_FUNC { matrix3x3_type m_T = nbl::hlsl::transpose(m); assert(nbl::hlsl::abs(nbl::hlsl::dot(m_T[0], m_T[1])) < 1e-5); @@ -165,7 +165,7 @@ struct SIsotropic using vector3_type = typename RayDirInfo::vector3_type; // WARNING: Changed since GLSL, now arguments need to be normalized! - static SIsotropic create(NBL_CONST_REF_ARG(RayDirInfo) normalizedV, NBL_CONST_REF_ARG(vector3_type) normalizedN) + static SIsotropic create(NBL_CONST_REF_ARG(RayDirInfo) normalizedV, const vector3_type normalizedN) { SIsotropic retval; retval.V = normalizedV; @@ -237,8 +237,8 @@ struct SAnisotropic // WARNING: Changed since GLSL, now arguments need to be normalized! static this_t create( NBL_CONST_REF_ARG(isotropic_interaction_type) isotropic, - NBL_CONST_REF_ARG(vector3_type) normalizedT, - NBL_CONST_REF_ARG(vector3_type) normalizedB + const vector3_type normalizedT, + const vector3_type normalizedB ) { this_t retval; @@ -252,7 +252,7 @@ struct SAnisotropic return retval; } - static this_t create(NBL_CONST_REF_ARG(isotropic_interaction_type) isotropic, NBL_CONST_REF_ARG(vector3_type) normalizedT) + static this_t create(NBL_CONST_REF_ARG(isotropic_interaction_type) isotropic, const vector3_type normalizedT) { return create(isotropic, normalizedT, cross(isotropic.getN(), normalizedT)); } @@ -263,7 +263,7 @@ struct SAnisotropic return create(isotropic, nbl::hlsl::normalize(T), nbl::hlsl::normalize(B)); } - static this_t create(NBL_CONST_REF_ARG(ray_dir_info_type) normalizedV, NBL_CONST_REF_ARG(vector3_type) normalizedN) + static this_t create(NBL_CONST_REF_ARG(ray_dir_info_type) normalizedV, const vector3_type normalizedN) { isotropic_interaction_type isotropic = isotropic_interaction_type::create(normalizedV, normalizedN); return create(isotropic); @@ -349,7 +349,7 @@ struct SLightSample static this_t createFromTangentSpace( NBL_CONST_REF_ARG(ray_dir_info_type) tangentSpaceL, - NBL_CONST_REF_ARG(matrix3x3_type) tangentFrame + const matrix3x3_type tangentFrame ) { this_t retval; @@ -364,7 +364,7 @@ struct SLightSample return retval; } - static this_t create(NBL_CONST_REF_ARG(ray_dir_info_type) L, NBL_CONST_REF_ARG(vector3_type) N) + static this_t create(NBL_CONST_REF_ARG(ray_dir_info_type) L, const vector3_type N) { this_t retval; @@ -376,7 +376,7 @@ struct SLightSample return retval; } - static this_t create(NBL_CONST_REF_ARG(ray_dir_info_type) L, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N) + static this_t create(NBL_CONST_REF_ARG(ray_dir_info_type) L, const vector3_type T, const vector3_type B, const vector3_type N) { this_t retval = create(L,N); @@ -387,7 +387,7 @@ struct SLightSample } template) - static this_t create(NBL_CONST_REF_ARG(vector3_type) L, NBL_CONST_REF_ARG(SurfaceInteraction) interaction) + static this_t create(const vector3_type L, NBL_CONST_REF_ARG(SurfaceInteraction) interaction) { const vector3_type V = interaction.V.getDirection(); const scalar_type VdotL = nbl::hlsl::dot(V,L); @@ -515,7 +515,7 @@ struct SIsotropicMicrofacetCache // transmissive cases need to be checked if the path is valid before usage static this_t create(const bool transmitted, NBL_CONST_REF_ARG(ComputeMicrofacetNormal) computeMicrofacetNormal, const scalar_type VdotL, - NBL_CONST_REF_ARG(vector3_type) N, NBL_REF_ARG(vector3_type) H) + const vector3_type N, NBL_REF_ARG(vector3_type) H) { this_t retval; retval.VdotL = VdotL; @@ -537,7 +537,7 @@ struct SIsotropicMicrofacetCache } static this_t create( - NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) L, NBL_CONST_REF_ARG(vector3_type) N, + const vector3_type V, const vector3_type L, const vector3_type N, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEtas, NBL_REF_ARG(vector3_type) H) { this_t retval; @@ -553,7 +553,7 @@ struct SIsotropicMicrofacetCache } static this_t create( - NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) L, NBL_CONST_REF_ARG(vector3_type) N, + const vector3_type V, const vector3_type L, const vector3_type N, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEtas) { vector3_type dummy; @@ -666,7 +666,7 @@ struct SAnisotropicMicrofacetCache using monochrome_type = vector; // always valid by construction - static this_t createForReflection(NBL_CONST_REF_ARG(vector3_type) tangentSpaceV, NBL_CONST_REF_ARG(vector3_type) tangentSpaceH) + static this_t createForReflection(const vector3_type tangentSpaceV, const vector3_type tangentSpaceH) { this_t retval; @@ -680,8 +680,8 @@ struct SAnisotropicMicrofacetCache return retval; } static this_t create( - NBL_CONST_REF_ARG(vector3_type) tangentSpaceV, - NBL_CONST_REF_ARG(vector3_type) tangentSpaceH, + const vector3_type tangentSpaceV, + const vector3_type tangentSpaceH, const bool transmitted, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpOrientedEta ) @@ -696,7 +696,7 @@ struct SAnisotropicMicrofacetCache return retval; } // always valid because its specialized for the reflective case - static this_t createForReflection(NBL_CONST_REF_ARG(vector3_type) tangentSpaceV, NBL_CONST_REF_ARG(vector3_type) tangentSpaceL, const scalar_type VdotL) + static this_t createForReflection(const vector3_type tangentSpaceV, const vector3_type tangentSpaceL, const scalar_type VdotL) { this_t retval; @@ -716,8 +716,8 @@ struct SAnisotropicMicrofacetCache } // transmissive cases need to be checked if the path is valid before usage static this_t create( - NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) L, - NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N, + const vector3_type V, const vector3_type L, + const vector3_type T, const vector3_type B, const vector3_type N, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEtas, NBL_REF_ARG(vector3_type) H ) { diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 5689427758..83e590266d 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -107,7 +107,7 @@ struct SBeckmannIsotropicBxDF return hlsl::promote(0.0); } - sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector2_type) u, NBL_REF_ARG(isocache_type) cache) + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache) { SBeckmannAnisotropicBxDF beckmann_aniso = SBeckmannAnisotropicBxDF::create(A, A, ior0, ior1); anisocache_type anisocache; @@ -252,7 +252,7 @@ struct SBeckmannAnisotropicBxDF(0.0); } - vector3_type __generate(NBL_CONST_REF_ARG(vector3_type) localV, NBL_CONST_REF_ARG(vector2_type) u) + vector3_type __generate(NBL_CONST_REF_ARG(vector3_type) localV, const vector2_type u) { //stretch vector3_type V = nbl::hlsl::normalize(vector3_type(A.x * localV.x, A.y * localV.y, localV.z)); @@ -320,7 +320,7 @@ struct SBeckmannAnisotropicBxDF(vector3_type(-slope, 1.0)); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector2_type) u, NBL_REF_ARG(anisocache_type) cache) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache) { const vector3_type localV = interaction.getTangentSpaceV(); const vector3_type H = __generate(localV, u); diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index b358d10c11..4701f0cdfc 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -108,7 +108,7 @@ struct SGGXIsotropicBxDF return hlsl::promote(0.0); } - sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector2_type) u, NBL_REF_ARG(isocache_type) cache) + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache) { SGGXAnisotropicBxDF ggx_aniso = SGGXAnisotropicBxDF::create(A, A, ior0, ior1); anisocache_type anisocache; @@ -250,7 +250,7 @@ struct SGGXAnisotropicBxDF(0.0); } - vector3_type __generate(NBL_CONST_REF_ARG(vector3_type) localV, NBL_CONST_REF_ARG(vector2_type) u) + vector3_type __generate(NBL_CONST_REF_ARG(vector3_type) localV, const vector2_type u) { vector3_type V = nbl::hlsl::normalize(vector3_type(A.x*localV.x, A.y*localV.y, localV.z));//stretch view vector so that we're sampling as if roughness=1.0 @@ -272,7 +272,7 @@ struct SGGXAnisotropicBxDF(vector3_type(A.x*H.x, A.y*H.y, H.z)); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector2_type) u, NBL_REF_ARG(anisocache_type) cache) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache) { const vector3_type localV = interaction.getTangentSpaceV(); const vector3_type H = __generate(localV, u); diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl index bc391dfdbd..98fce1af6c 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl @@ -23,6 +23,7 @@ struct SLambertianBxDF { using this_t = SLambertianBxDF; NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); NBL_BXDF_CONFIG_ALIAS(ray_dir_info_type, Config); NBL_BXDF_CONFIG_ALIAS(isotropic_interaction_type, Config); NBL_BXDF_CONFIG_ALIAS(anisotropic_interaction_type, Config); @@ -49,21 +50,16 @@ struct SLambertianBxDF return eval(_sample, interaction.isotropic); } - sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector) u) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u) { ray_dir_info_type L; L.direction = sampling::ProjectedHemisphere::generate(u); return sample_type::createFromTangentSpace(L, interaction.getFromTangentSpace()); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector) u) + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u) { - return generate_wo_clamps(interaction, u); - } - - sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector) u) - { - return generate_wo_clamps(anisotropic_interaction_type::create(interaction), u); + return generate(anisotropic_interaction_type::create(interaction), u); } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl index 721e4ae994..7b8885eee0 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl @@ -60,19 +60,19 @@ struct SOrenNayarBxDF return eval(_sample, interaction.isotropic); } - sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector2_type) u) + sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u) { ray_dir_info_type L; L.direction = sampling::ProjectedHemisphere::generate(u); return sample_type::createFromTangentSpace(L, interaction.getFromTangentSpace()); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector2_type) u) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u) { return generate_wo_clamps(interaction, u); } - sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector) u) + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u) { return generate_wo_clamps(anisotropic_interaction_type::create(interaction), u); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 0f5f6bb8a3..a5b64c762d 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -234,7 +234,7 @@ struct SBeckmannDielectricAnisotropicBxDF(f) * microfacet_transform; } - sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) localV, NBL_CONST_REF_ARG(vector3_type) H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(anisocache_type) cache) + sample_type __generate_wo_clamps(const vector3_type localV, const vector3_type H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(anisocache_type) cache) { const scalar_type localVdotH = nbl::hlsl::dot(localV,H); const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta.value * orientedEta.value,nbl::hlsl::abs(localVdotH))[0]; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index ec14856d48..250947de4e 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -233,7 +233,7 @@ struct SGGXDielectricAnisotropicBxDF(f) * microfacet_transform; } - sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) localV, NBL_CONST_REF_ARG(vector3_type) H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(anisocache_type) cache) + sample_type __generate_wo_clamps(const vector3_type localV, const vector3_type H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(anisocache_type) cache) { const scalar_type localVdotH = nbl::hlsl::dot(localV,H); const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta.value * orientedEta.value,nbl::hlsl::abs(localVdotH))[0]; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl index a38a046e04..143e0767c2 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl @@ -24,6 +24,7 @@ struct SLambertianBxDF { using this_t = SLambertianBxDF; NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector3_type, Config); NBL_BXDF_CONFIG_ALIAS(ray_dir_info_type, Config); NBL_BXDF_CONFIG_ALIAS(isotropic_interaction_type, Config); NBL_BXDF_CONFIG_ALIAS(anisotropic_interaction_type, Config); @@ -50,19 +51,19 @@ struct SLambertianBxDF return eval(_sample, interaction.isotropic); } - sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector) u) + sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u) { ray_dir_info_type L; L.direction = sampling::ProjectedSphere::generate(u); return sample_type::createFromTangentSpace(L, interaction.getFromTangentSpace()); } - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector) u) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u) { return generate_wo_clamps(interaction, u); } - sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(vector) u) + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector3_type u) { return generate_wo_clamps(anisotropic_interaction_type::create(interaction), u); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index 6d0d501790..f4ebf1dfdc 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -50,7 +50,7 @@ struct SSmoothDielectricBxDF return hlsl::promote(0); } - sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N, scalar_type NdotV, scalar_type absNdotV, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(bool) transmitted) + sample_type __generate_wo_clamps(const vector3_type V, const vector3_type T, const vector3_type B, const vector3_type N, scalar_type NdotV, scalar_type absNdotV, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(bool) transmitted) { const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta.value*orientedEta.value, absNdotV)[0]; @@ -65,26 +65,15 @@ struct SSmoothDielectricBxDF return sample_type::create(L, T, B, N); } - sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector) u) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u) { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), hlsl::promote(eta)); - fresnel::OrientedEtaRcps rcpEta = fresnel::OrientedEtaRcps::create(interaction.isotropic.getNdotV(), hlsl::promote(eta)); - scalar_type NdotV = interaction.isotropic.getNdotV(); + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.getNdotV(_clamp), hlsl::promote(eta)); + fresnel::OrientedEtaRcps rcpEta = fresnel::OrientedEtaRcps::create(interaction.getNdotV(_clamp), hlsl::promote(eta)); bool dummy; - return __generate_wo_clamps(interaction.isotropic.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.isotropic.getN(), NdotV, - NdotV, u, orientedEta, rcpEta, dummy); + return __generate_wo_clamps(interaction.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.getN(), interaction.getNdotV(), + interaction.getNdotV(_clamp), u, orientedEta, rcpEta, dummy); } - - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector) u) - { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.isotropic.getNdotV(), hlsl::promote(eta)); - fresnel::OrientedEtaRcps rcpEta = fresnel::OrientedEtaRcps::create(interaction.isotropic.getNdotV(), hlsl::promote(eta)); - scalar_type NdotV = interaction.isotropic.getNdotV(); - bool dummy; - return __generate_wo_clamps(interaction.isotropic.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.isotropic.getN(), NdotV, - nbl::hlsl::abs(NdotV), u, orientedEta, rcpEta, dummy); - } - sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector) u) + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u) { return generate(anisotropic_interaction_type::create(interaction), u); } @@ -151,7 +140,7 @@ struct SSmoothThinDielectricBxDF // its basically a set of weights that determine // assert(1.0==luminosityContributionHint.r+luminosityContributionHint.g+luminosityContributionHint.b); // `remainderMetadata` is a variable which the generator function returns byproducts of sample generation that would otherwise have to be redundantly calculated `quotient_and_pdf` - sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(vector3_type) V, NBL_CONST_REF_ARG(vector3_type) T, NBL_CONST_REF_ARG(vector3_type) B, NBL_CONST_REF_ARG(vector3_type) N, scalar_type NdotV, scalar_type absNdotV, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(spectral_type) eta2, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint, NBL_REF_ARG(spectral_type) remainderMetadata) + sample_type __generate_wo_clamps(const vector3_type V, const vector3_type T, const vector3_type B, const vector3_type N, scalar_type NdotV, scalar_type absNdotV, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(spectral_type) eta2, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint, NBL_REF_ARG(spectral_type) remainderMetadata) { // we will only ever intersect from the outside const spectral_type reflectance = fresnel::thinDielectricInfiniteScatter(fresnel::Dielectric::__call(eta2,absNdotV)); @@ -168,18 +157,14 @@ struct SSmoothThinDielectricBxDF return sample_type::create(L, T, B, N); } - sample_type generate_wo_clamps(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector) u) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u) { - scalar_type NdotV = interaction.isotropic.getNdotV(); vector3_type dummy; - return __generate_wo_clamps(interaction.isotropic.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.isotropic.getN(), NdotV, NdotV, u, eta2, luminosityContributionHint, dummy); + return __generate_wo_clamps(interaction.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.getN(), interaction.getNdotV(), interaction.getNdotV(_clamp), u, eta2, luminosityContributionHint, dummy); } - - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector) u) + sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u) { - scalar_type NdotV = interaction.isotropic.getNdotV(); - vector3_type dummy; - return __generate_wo_clamps(interaction.isotropic.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.isotropic.getN(), NdotV, nbl::hlsl::abs(NdotV), u, eta2, luminosityContributionHint, dummy); + return generate(anisotropic_interaction_type::create(interaction), u); } scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample) From 31542afc320a72fe252e5eef9b2fe9331c7f8e3d Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 6 Aug 2025 16:20:35 +0700 Subject: [PATCH 165/188] latest example --- examples_tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples_tests b/examples_tests index 7d42ed68b2..89b1f098d2 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 7d42ed68b243eeae86e10e2ed6482aa9afc8a5b4 +Subproject commit 89b1f098d27185f9954aa24a715171642b76b4ee From 0295e66a49e0bce5eda56edcdffd04464534b913 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 7 Aug 2025 10:25:16 +0700 Subject: [PATCH 166/188] pass lambdaV instead of onePlusLambdaV for beckmann ndf --- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 20 ++++---- .../hlsl/bxdf/reflection/beckmann.hlsl | 46 +++++-------------- .../hlsl/bxdf/transmission/beckmann.hlsl | 44 ++++-------------- 3 files changed, 31 insertions(+), 79 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index 197965185b..0e3fb703de 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -29,7 +29,6 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getNdf()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getClampMode()), ::nbl::hlsl::is_same_v, BxDFClampMode)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getOnePlusLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ); #undef query #include @@ -46,7 +45,6 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getClampMode()), ::nbl::hlsl::is_same_v, BxDFClampMode)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getOrientedEta()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getOnePlusLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ); #undef query #include @@ -60,7 +58,7 @@ NBL_CONCEPT_BEGIN(1) NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaL()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getOnePlusLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ); #undef query #include @@ -87,16 +85,14 @@ struct Beckmann) > template && surface_interactions::Isotropic) scalar_type DG1(NBL_REF_ARG(Query) query, NBL_CONST_REF_ARG(Interaction) interaction) { - query.onePlusLambda_V = scalar_type(1.0) + query.getLambdaV(); - return ndf::microfacet_to_light_measure_transform::__call(query.getNdf() / query.getOnePlusLambdaV(), interaction.getNdotV(query.getClampMode())); + return ndf::microfacet_to_light_measure_transform::__call(query.getNdf() / (scalar_type(1.0) + query.getLambdaV()), interaction.getNdotV(query.getClampMode())); } // bsdf template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) scalar_type DG1(NBL_REF_ARG(Query) query, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { - query.onePlusLambda_V = scalar_type(1.0) + query.getLambdaV(); - return ndf::microfacet_to_light_measure_transform::__call(query.getNdf() / query.getOnePlusLambdaV(), interaction.getNdotV(query.getClampMode()), cache.isTransmission(), cache.getVdotH(), cache.getLdotH(), cache.getVdotHLdotH(), query.getOrientedEta()); + return ndf::microfacet_to_light_measure_transform::__call(query.getNdf() / (scalar_type(1.0) + query.getLambdaV()), interaction.getNdotV(query.getClampMode()), cache.isTransmission(), cache.getVdotH(), cache.getLdotH(), cache.getVdotHLdotH(), query.getOrientedEta()); } scalar_type G1(scalar_type lambda) @@ -125,13 +121,14 @@ struct Beckmann) > template) scalar_type correlated(NBL_CONST_REF_ARG(Query) query) { - return scalar_type(1.0) / (query.getOnePlusLambdaV() + query.getLambdaL()); + return scalar_type(1.0) / (scalar_type(1.0) + query.getLambdaV() + query.getLambdaL()); } template && ReadableIsotropicMicrofacetCache) scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) { - return query.getOnePlusLambdaV() * hlsl::mix(scalar_type(1.0)/(query.getOnePlusLambdaV() + query.getLambdaL()), bxdf::beta(query.getOnePlusLambdaV(), scalar_type(1.0) + query.getLambdaL()), cache.isTransmission()); + scalar_type onePlusLambda_V = scalar_type(1.0) + query.getLambdaV(); + return onePlusLambda_V * hlsl::mix(scalar_type(1.0)/(onePlusLambda_V + query.getLambdaL()), bxdf::beta(onePlusLambda_V, scalar_type(1.0) + query.getLambdaL()), cache.isTransmission()); } scalar_type a2; @@ -198,13 +195,14 @@ struct Beckmann) > template) scalar_type correlated(NBL_CONST_REF_ARG(Query) query) { - return scalar_type(1.0) / (query.getOnePlusLambdaV() + query.getLambdaL()); + return scalar_type(1.0) / (scalar_type(1.0) + query.getLambdaV() + query.getLambdaL()); } template && AnisotropicMicrofacetCache) scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) { - return query.getOnePlusLambdaV() * hlsl::mix(scalar_type(1.0)/(query.getOnePlusLambdaV() + query.getLambdaL()), bxdf::beta(query.getOnePlusLambdaV(), scalar_type(1.0) + query.getLambdaL()), cache.isTransmission()); + scalar_type onePlusLambda_V = scalar_type(1.0) + query.getLambdaV(); + return onePlusLambda_V * hlsl::mix(scalar_type(1.0)/(onePlusLambda_V + query.getLambdaL()), bxdf::beta(onePlusLambda_V, scalar_type(1.0) + query.getLambdaL()), cache.isTransmission()); } scalar_type ax; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 83e590266d..6cecdf4781 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -48,12 +48,10 @@ struct SBeckmannIsotropicBxDF scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } scalar_type ndf; BxDFClampMode _clamp; scalar_type lambda_V; - scalar_type onePlusLambda_V; }; template @@ -62,10 +60,10 @@ struct SBeckmannIsotropicBxDF using scalar_type = T; scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } - scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } + scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } scalar_type lambda_L; - scalar_type onePlusLambda_V; + scalar_type lambda_V; }; // iso @@ -88,7 +86,7 @@ struct SBeckmannIsotropicBxDF { SBeckmannG2overG1Query query; query.lambda_L = beckmann_ndf.LambdaC2(_sample.getNdotL2()); - query.onePlusLambda_V = scalar_type(1.0) + beckmann_ndf.LambdaC2(interaction.getNdotV2()); + query.lambda_V = beckmann_ndf.LambdaC2(interaction.getNdotV2()); NG *= beckmann_ndf.template correlated >(query); } return NG; @@ -116,7 +114,7 @@ struct SBeckmannIsotropicBxDF return s; } - scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache, NBL_REF_ARG(scalar_type) onePlusLambda_V) + scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { SBeckmannDG1Query dg1_query; dg1_query._clamp = BxDFClampMode::BCM_MAX; @@ -125,24 +123,15 @@ struct SBeckmannIsotropicBxDF ndf::Beckmann beckmann_ndf; beckmann_ndf.a2 = a2; dg1_query.ndf = beckmann_ndf.template D(cache); - dg1_query.lambda_V = beckmann_ndf.LambdaC2(interaction.getNdotV2()); scalar_type dg1 = beckmann_ndf.template DG1, isotropic_interaction_type>(dg1_query, interaction); - onePlusLambda_V = dg1_query.getOnePlusLambdaV(); return dg1; } - scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) - { - scalar_type dummy; - return pdf(interaction, cache, dummy); - } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - scalar_type onePlusLambda_V; - scalar_type _pdf = pdf(interaction, cache, onePlusLambda_V); + scalar_type _pdf = pdf(interaction, cache); ndf::Beckmann beckmann_ndf; spectral_type quo = (spectral_type)0.0; @@ -151,7 +140,7 @@ struct SBeckmannIsotropicBxDF beckmann_ndf.a2 = A*A; SBeckmannG2overG1Query query; query.lambda_L = beckmann_ndf.LambdaC2(_sample.getNdotL2()); - query.onePlusLambda_V = onePlusLambda_V; + query.lambda_V = beckmann_ndf.LambdaC2(interaction.getNdotV2()); scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1, isocache_type>(query, cache); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); const spectral_type reflectance = f(); @@ -193,12 +182,10 @@ struct SBeckmannAnisotropicBxDF @@ -207,10 +194,10 @@ struct SBeckmannAnisotropicBxDF query; query.lambda_L = beckmann_ndf.LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); - query.onePlusLambda_V = scalar_type(1.0) + beckmann_ndf.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + query.lambda_V = beckmann_ndf.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); NG *= beckmann_ndf.template correlated >(query); } return NG; @@ -333,7 +320,7 @@ struct SBeckmannAnisotropicBxDF dg1_query; dg1_query._clamp = BxDFClampMode::BCM_MAX; @@ -343,24 +330,15 @@ struct SBeckmannAnisotropicBxDF(cache); - dg1_query.lambda_V = beckmann_ndf.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); scalar_type dg1 = beckmann_ndf.template DG1, anisotropic_interaction_type>(dg1_query, interaction); - onePlusLambda_V = dg1_query.getOnePlusLambdaV(); return dg1; } - scalar_type pdf(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - scalar_type dummy; - return pdf(interaction, cache, dummy); - } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - scalar_type onePlusLambda_V; - scalar_type _pdf = pdf(interaction, cache, onePlusLambda_V); + scalar_type _pdf = pdf(interaction, cache); ndf::Beckmann beckmann_ndf; spectral_type quo = (spectral_type)0.0; @@ -370,7 +348,7 @@ struct SBeckmannAnisotropicBxDF query; query.lambda_L = beckmann_ndf.LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); - query.onePlusLambda_V = onePlusLambda_V; + query.lambda_V = beckmann_ndf.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1, anisocache_type>(query, cache); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); const spectral_type reflectance = f(); diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index a5b64c762d..75e14fb408 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -52,13 +52,11 @@ struct SBeckmannDielectricIsotropicBxDF BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } scalar_type getOrientedEta() NBL_CONST_MEMBER_FUNC { return orientedEta; } - scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } scalar_type ndf; BxDFClampMode _clamp; scalar_type lambda_V; scalar_type orientedEta; - scalar_type onePlusLambda_V; }; template @@ -67,10 +65,10 @@ struct SBeckmannDielectricIsotropicBxDF using scalar_type = T; scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } - scalar_type getOnePlusLambdaV() NBL_CONST_MEMBER_FUNC { return onePlusLambda_V; } + scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } scalar_type lambda_L; - scalar_type onePlusLambda_V; + scalar_type lambda_V; }; static this_t create(scalar_type eta, scalar_type A) @@ -107,7 +105,7 @@ struct SBeckmannDielectricIsotropicBxDF return s; } - scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache, NBL_REF_ARG(scalar_type) onePlusLambda_V) + scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { SBeckmannDG1Query dg1_query; dg1_query._clamp = BxDFClampMode::BCM_ABS; @@ -122,31 +120,21 @@ struct SBeckmannDielectricIsotropicBxDF ndf::Beckmann beckmann_ndf; beckmann_ndf.a2 = a2; dg1_query.ndf = beckmann_ndf.template D(cache); - dg1_query.lambda_V = beckmann_ndf.LambdaC2(interaction.getNdotV2()); scalar_type dg1 = beckmann_ndf.template DG1, isotropic_interaction_type, isocache_type>(dg1_query, interaction, cache); - onePlusLambda_V = dg1_query.getOnePlusLambdaV(); - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * dg1; } - scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) - { - scalar_type dummy; - return pdf(interaction, cache, dummy); - } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - scalar_type onePlusLambda_V; - scalar_type _pdf = pdf(interaction, cache, onePlusLambda_V); + scalar_type _pdf = pdf(interaction, cache); ndf::Beckmann beckmann_ndf; beckmann_ndf.a2 = A*A; SBeckmannG2overG1Query query; query.lambda_L = beckmann_ndf.LambdaC2(_sample.getNdotL2()); - query.onePlusLambda_V = onePlusLambda_V; + query.lambda_V = beckmann_ndf.LambdaC2(interaction.getNdotV2()); scalar_type quo = beckmann_ndf.template G2_over_G1, isocache_type>(query, cache); return quotient_pdf_type::create(quo, _pdf); @@ -188,13 +176,11 @@ struct SBeckmannDielectricAnisotropicBxDF @@ -203,10 +189,10 @@ struct SBeckmannDielectricAnisotropicBxDF dg1_query; dg1_query._clamp = BxDFClampMode::BCM_ABS; @@ -292,32 +278,22 @@ struct SBeckmannDielectricAnisotropicBxDF(cache); - dg1_query.lambda_V = beckmann_ndf.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); scalar_type dg1 = beckmann_ndf.template DG1, anisotropic_interaction_type, anisocache_type>(dg1_query, interaction, cache); - onePlusLambda_V = dg1_query.getOnePlusLambdaV(); - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * dg1; } - scalar_type pdf(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - scalar_type dummy; - return pdf(interaction, cache, dummy); - } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - scalar_type onePlusLambda_V; - scalar_type _pdf = pdf(interaction, cache, onePlusLambda_V); + scalar_type _pdf = pdf(interaction, cache); ndf::Beckmann beckmann_ndf; beckmann_ndf.ax = A.x; beckmann_ndf.ay = A.y; SBeckmannG2overG1Query query; query.lambda_L = beckmann_ndf.LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); - query.onePlusLambda_V = onePlusLambda_V; + query.lambda_V = beckmann_ndf.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); scalar_type quo = beckmann_ndf.template G2_over_G1, anisocache_type>(query, cache); return quotient_pdf_type::create(quo, _pdf); From fa7bb8bfe6de7161ca517ebc622530654c11c824 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 7 Aug 2025 11:28:22 +0700 Subject: [PATCH 167/188] moved ndf query structs into bxdf function --- examples_tests | 2 +- .../hlsl/bxdf/reflection/beckmann.hlsl | 146 +++++++++-------- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 152 ++++++++++-------- .../hlsl/bxdf/transmission/beckmann.hlsl | 124 +++++++------- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 127 +++++++-------- 5 files changed, 289 insertions(+), 262 deletions(-) diff --git a/examples_tests b/examples_tests index 89b1f098d2..79cb7fe694 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 89b1f098d27185f9954aa24a715171642b76b4ee +Subproject commit 79cb7fe69406ada805482c04d12665dc1363ab06 diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 6cecdf4781..2766a600e2 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -40,32 +40,6 @@ struct SBeckmannIsotropicBxDF NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_MAX; - template - struct SBeckmannDG1Query - { - using scalar_type = T; - - scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } - BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } - scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - - scalar_type ndf; - BxDFClampMode _clamp; - scalar_type lambda_V; - }; - - template - struct SBeckmannG2overG1Query - { - using scalar_type = T; - - scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } - scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - - scalar_type lambda_L; - scalar_type lambda_V; - }; - // iso static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) { @@ -84,10 +58,21 @@ struct SBeckmannIsotropicBxDF scalar_type NG = beckmann_ndf.template D(cache); if (a2 > numeric_limits::min) { - SBeckmannG2overG1Query query; + struct SBeckmannG2overG1Query + { + using scalar_type = scalar_type; + + scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } + scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } + + scalar_type lambda_L; + scalar_type lambda_V; + }; + + SBeckmannG2overG1Query query; query.lambda_L = beckmann_ndf.LambdaC2(_sample.getNdotL2()); query.lambda_V = beckmann_ndf.LambdaC2(interaction.getNdotV2()); - NG *= beckmann_ndf.template correlated >(query); + NG *= beckmann_ndf.template correlated(query); } return NG; } @@ -116,7 +101,20 @@ struct SBeckmannIsotropicBxDF scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - SBeckmannDG1Query dg1_query; + struct SBeckmannDG1Query + { + using scalar_type = scalar_type; + + scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } + BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } + scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } + + scalar_type ndf; + BxDFClampMode _clamp; + scalar_type lambda_V; + }; + + SBeckmannDG1Query dg1_query; dg1_query._clamp = BxDFClampMode::BCM_MAX; scalar_type a2 = A*A; @@ -125,7 +123,7 @@ struct SBeckmannIsotropicBxDF dg1_query.ndf = beckmann_ndf.template D(cache); dg1_query.lambda_V = beckmann_ndf.LambdaC2(interaction.getNdotV2()); - scalar_type dg1 = beckmann_ndf.template DG1, isotropic_interaction_type>(dg1_query, interaction); + scalar_type dg1 = beckmann_ndf.template DG1(dg1_query, interaction); return dg1; } @@ -137,11 +135,22 @@ struct SBeckmannIsotropicBxDF spectral_type quo = (spectral_type)0.0; if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) { + struct SBeckmannG2overG1Query + { + using scalar_type = scalar_type; + + scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } + scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } + + scalar_type lambda_L; + scalar_type lambda_V; + }; + beckmann_ndf.a2 = A*A; - SBeckmannG2overG1Query query; + SBeckmannG2overG1Query query; query.lambda_L = beckmann_ndf.LambdaC2(_sample.getNdotL2()); query.lambda_V = beckmann_ndf.LambdaC2(interaction.getNdotV2()); - scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1, isocache_type>(query, cache); + scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1(query, cache); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; @@ -174,32 +183,6 @@ struct SBeckmannAnisotropicBxDF - struct SBeckmannDG1Query - { - using scalar_type = T; - - scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } - BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } - scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - - scalar_type ndf; - BxDFClampMode _clamp; - scalar_type lambda_V; - }; - - template - struct SBeckmannG2overG1Query - { - using scalar_type = T; - - scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } - scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - - scalar_type lambda_L; - scalar_type lambda_V; - }; - // aniso static this_t create(scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) { @@ -218,10 +201,21 @@ struct SBeckmannAnisotropicBxDF(cache); if (hlsl::any >(A > (vector2_type)numeric_limits::min)) { - SBeckmannG2overG1Query query; + struct SBeckmannG2overG1Query + { + using scalar_type = scalar_type; + + scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } + scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } + + scalar_type lambda_L; + scalar_type lambda_V; + }; + + SBeckmannG2overG1Query query; query.lambda_L = beckmann_ndf.LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); query.lambda_V = beckmann_ndf.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); - NG *= beckmann_ndf.template correlated >(query); + NG *= beckmann_ndf.template correlated(query); } return NG; } @@ -322,7 +316,20 @@ struct SBeckmannAnisotropicBxDF dg1_query; + struct SBeckmannDG1Query + { + using scalar_type = scalar_type; + + scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } + BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } + scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } + + scalar_type ndf; + BxDFClampMode _clamp; + scalar_type lambda_V; + }; + + SBeckmannDG1Query dg1_query; dg1_query._clamp = BxDFClampMode::BCM_MAX; scalar_type ndf, lambda; @@ -332,7 +339,7 @@ struct SBeckmannAnisotropicBxDF(cache); dg1_query.lambda_V = beckmann_ndf.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); - scalar_type dg1 = beckmann_ndf.template DG1, anisotropic_interaction_type>(dg1_query, interaction); + scalar_type dg1 = beckmann_ndf.template DG1(dg1_query, interaction); return dg1; } @@ -344,12 +351,23 @@ struct SBeckmannAnisotropicBxDF numeric_limits::min && interaction.getNdotV() > numeric_limits::min) { + struct SBeckmannG2overG1Query + { + using scalar_type = scalar_type; + + scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } + scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } + + scalar_type lambda_L; + scalar_type lambda_V; + }; + beckmann_ndf.ax = A.x; beckmann_ndf.ay = A.y; - SBeckmannG2overG1Query query; + SBeckmannG2overG1Query query; query.lambda_L = beckmann_ndf.LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); query.lambda_V = beckmann_ndf.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); - scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1, anisocache_type>(query, cache); + scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1(query, cache); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 4701f0cdfc..9be2a8fd29 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -40,33 +40,6 @@ struct SGGXIsotropicBxDF NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_MAX; - template - struct SGGXDG1Query - { - using scalar_type = T; - - scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } - scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; } - - scalar_type ndf; - scalar_type G1_over_2NdotV; - }; - - template - struct SGGXG2XQuery - { - using scalar_type = T; - - scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } - scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } - BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } - - scalar_type devsh_v; - scalar_type devsh_l; - BxDFClampMode _clamp; - }; - - // iso static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) { @@ -86,11 +59,24 @@ struct SGGXIsotropicBxDF scalar_type NG = ggx_ndf.template D(cache); if (a2 > numeric_limits::min) { - SGGXG2XQuery g2_query; + struct SGGXG2XQuery + { + using scalar_type = scalar_type; + + scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } + scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } + BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } + + scalar_type devsh_v; + scalar_type devsh_l; + BxDFClampMode _clamp; + }; + + SGGXG2XQuery g2_query; g2_query.devsh_v = ggx_ndf.devsh_part(interaction.getNdotV2()); g2_query.devsh_l = ggx_ndf.devsh_part(_sample.getNdotL2()); g2_query._clamp = _clamp; - NG *= ggx_ndf.template correlated_wo_numerator, sample_type, isotropic_interaction_type>(g2_query, _sample, interaction); + NG *= ggx_ndf.template correlated_wo_numerator(g2_query, _sample, interaction); } return NG; } @@ -119,7 +105,18 @@ struct SGGXIsotropicBxDF scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - SGGXDG1Query dg1_query; + struct SGGXDG1Query + { + using scalar_type = scalar_type; + + scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } + scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; } + + scalar_type ndf; + scalar_type G1_over_2NdotV; + }; + + SGGXDG1Query dg1_query; const scalar_type a2 = A*A; ndf::GGX ggx_ndf; ggx_ndf.a2 = a2; @@ -129,7 +126,7 @@ struct SGGXIsotropicBxDF const scalar_type devsh_v = ggx_ndf.devsh_part(interaction.getNdotV2()); dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(interaction.getNdotV(_clamp), devsh_v); - return ggx_ndf.template DG1 >(dg1_query); + return ggx_ndf.template DG1(dg1_query); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) @@ -139,16 +136,29 @@ struct SGGXIsotropicBxDF spectral_type quo = (spectral_type)0.0; if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) { + struct SGGXG2XQuery + { + using scalar_type = scalar_type; + + scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } + scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } + BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } + + scalar_type devsh_v; + scalar_type devsh_l; + BxDFClampMode _clamp; + }; + const scalar_type a2 = A*A; ndf::GGX ggx_ndf; ggx_ndf.a2 = a2; ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; - SGGXG2XQuery g2_query; + SGGXG2XQuery g2_query; g2_query.devsh_v = ggx_ndf.devsh_part(interaction.getNdotV2()); g2_query.devsh_l = ggx_ndf.devsh_part(_sample.getNdotL2()); g2_query._clamp = BxDFClampMode::BCM_MAX; - const scalar_type G2_over_G1 = ggx_ndf.template G2_over_G1, sample_type, isotropic_interaction_type, isocache_type>(g2_query, _sample, interaction, cache); + const scalar_type G2_over_G1 = ggx_ndf.template G2_over_G1(g2_query, _sample, interaction, cache); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); const spectral_type reflectance = f(); @@ -182,33 +192,6 @@ struct SGGXAnisotropicBxDF - struct SGGXDG1Query - { - using scalar_type = T; - - scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } - scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; } - - scalar_type ndf; - scalar_type G1_over_2NdotV; - }; - - template - struct SGGXG2XQuery - { - using scalar_type = T; - - scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } - scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } - BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } - - scalar_type devsh_v; - scalar_type devsh_l; - BxDFClampMode _clamp; - }; - - // aniso static this_t create(scalar_type ax, scalar_type ay, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) { @@ -228,11 +211,24 @@ struct SGGXAnisotropicBxDF(cache); if (any >(A > (vector2_type)numeric_limits::min)) { - SGGXG2XQuery g2_query; + struct SGGXG2XQuery + { + using scalar_type = scalar_type; + + scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } + scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } + BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } + + scalar_type devsh_v; + scalar_type devsh_l; + BxDFClampMode _clamp; + }; + + SGGXG2XQuery g2_query; g2_query.devsh_v = ggx_ndf.devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); g2_query.devsh_l = ggx_ndf.devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); g2_query._clamp = _clamp; - NG *= ggx_ndf.template correlated_wo_numerator, sample_type, anisotropic_interaction_type>(g2_query, _sample, interaction); + NG *= ggx_ndf.template correlated_wo_numerator(g2_query, _sample, interaction); } return NG; } @@ -287,7 +283,18 @@ struct SGGXAnisotropicBxDF dg1_query; + struct SGGXDG1Query + { + using scalar_type = scalar_type; + + scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } + scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; } + + scalar_type ndf; + scalar_type G1_over_2NdotV; + }; + + SGGXDG1Query dg1_query; ndf::GGX ggx_ndf; ggx_ndf.ax2 = A.x*A.x; ggx_ndf.ay2 = A.y*A.y; @@ -297,7 +304,7 @@ struct SGGXAnisotropicBxDF >(dg1_query); + return ggx_ndf.template DG1(dg1_query); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) @@ -307,16 +314,29 @@ struct SGGXAnisotropicBxDF numeric_limits::min && interaction.getNdotV() > numeric_limits::min) { + struct SGGXG2XQuery + { + using scalar_type = scalar_type; + + scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } + scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } + BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } + + scalar_type devsh_v; + scalar_type devsh_l; + BxDFClampMode _clamp; + }; + ndf::GGX ggx_ndf; ggx_ndf.ax2 = A.x*A.x; ggx_ndf.ay2 = A.y*A.y; ggx_ndf.a2 = A.x*A.y; - SGGXG2XQuery g2_query; + SGGXG2XQuery g2_query; g2_query.devsh_v = ggx_ndf.devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); g2_query.devsh_l = ggx_ndf.devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); g2_query._clamp = BxDFClampMode::BCM_MAX; - const scalar_type G2_over_G1 = ggx_ndf.template G2_over_G1, sample_type, anisotropic_interaction_type, anisocache_type>(g2_query, _sample, interaction, cache); + const scalar_type G2_over_G1 = ggx_ndf.template G2_over_G1(g2_query, _sample, interaction, cache); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); const spectral_type reflectance = f(); diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 75e14fb408..06e75265fd 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -43,34 +43,6 @@ struct SBeckmannDielectricIsotropicBxDF NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; - template - struct SBeckmannDG1Query - { - using scalar_type = T; - - scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } - BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } - scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - scalar_type getOrientedEta() NBL_CONST_MEMBER_FUNC { return orientedEta; } - - scalar_type ndf; - BxDFClampMode _clamp; - scalar_type lambda_V; - scalar_type orientedEta; - }; - - template - struct SBeckmannG2overG1Query - { - using scalar_type = T; - - scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } - scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - - scalar_type lambda_L; - scalar_type lambda_V; - }; - static this_t create(scalar_type eta, scalar_type A) { this_t retval; @@ -107,7 +79,22 @@ struct SBeckmannDielectricIsotropicBxDF scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - SBeckmannDG1Query dg1_query; + struct SBeckmannDG1Query + { + using scalar_type = scalar_type; + + scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } + BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } + scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } + scalar_type getOrientedEta() NBL_CONST_MEMBER_FUNC { return orientedEta; } + + scalar_type ndf; + BxDFClampMode _clamp; + scalar_type lambda_V; + scalar_type orientedEta; + }; + + SBeckmannDG1Query dg1_query; dg1_query._clamp = BxDFClampMode::BCM_ABS; fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); @@ -122,7 +109,7 @@ struct SBeckmannDielectricIsotropicBxDF dg1_query.ndf = beckmann_ndf.template D(cache); dg1_query.lambda_V = beckmann_ndf.LambdaC2(interaction.getNdotV2()); - scalar_type dg1 = beckmann_ndf.template DG1, isotropic_interaction_type, isocache_type>(dg1_query, interaction, cache); + scalar_type dg1 = beckmann_ndf.template DG1(dg1_query, interaction, cache); return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * dg1; } @@ -130,12 +117,23 @@ struct SBeckmannDielectricIsotropicBxDF { scalar_type _pdf = pdf(interaction, cache); + struct SBeckmannG2overG1Query + { + using scalar_type = scalar_type; + + scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } + scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } + + scalar_type lambda_L; + scalar_type lambda_V; + }; + ndf::Beckmann beckmann_ndf; beckmann_ndf.a2 = A*A; - SBeckmannG2overG1Query query; + SBeckmannG2overG1Query query; query.lambda_L = beckmann_ndf.LambdaC2(_sample.getNdotL2()); query.lambda_V = beckmann_ndf.LambdaC2(interaction.getNdotV2()); - scalar_type quo = beckmann_ndf.template G2_over_G1, isocache_type>(query, cache); + scalar_type quo = beckmann_ndf.template G2_over_G1(query, cache); return quotient_pdf_type::create(quo, _pdf); } @@ -167,34 +165,6 @@ struct SBeckmannDielectricAnisotropicBxDF - struct SBeckmannDG1Query - { - using scalar_type = T; - - scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } - BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } - scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - scalar_type getOrientedEta() NBL_CONST_MEMBER_FUNC { return orientedEta; } - - scalar_type ndf; - BxDFClampMode _clamp; - scalar_type lambda_V; - scalar_type orientedEta; - }; - - template - struct SBeckmannG2overG1Query - { - using scalar_type = T; - - scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } - scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - - scalar_type lambda_L; - scalar_type lambda_V; - }; - static this_t create(scalar_type eta, scalar_type ax, scalar_type ay) { this_t retval; @@ -265,7 +235,22 @@ struct SBeckmannDielectricAnisotropicBxDF dg1_query; + struct SBeckmannDG1Query + { + using scalar_type = scalar_type; + + scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } + BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } + scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } + scalar_type getOrientedEta() NBL_CONST_MEMBER_FUNC { return orientedEta; } + + scalar_type ndf; + BxDFClampMode _clamp; + scalar_type lambda_V; + scalar_type orientedEta; + }; + + SBeckmannDG1Query dg1_query; dg1_query._clamp = BxDFClampMode::BCM_ABS; fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); @@ -280,7 +265,7 @@ struct SBeckmannDielectricAnisotropicBxDF(cache); dg1_query.lambda_V = beckmann_ndf.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); - scalar_type dg1 = beckmann_ndf.template DG1, anisotropic_interaction_type, anisocache_type>(dg1_query, interaction, cache); + scalar_type dg1 = beckmann_ndf.template DG1(dg1_query, interaction, cache); return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * dg1; } @@ -288,13 +273,24 @@ struct SBeckmannDielectricAnisotropicBxDF beckmann_ndf; beckmann_ndf.ax = A.x; beckmann_ndf.ay = A.y; - SBeckmannG2overG1Query query; + SBeckmannG2overG1Query query; query.lambda_L = beckmann_ndf.LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); query.lambda_V = beckmann_ndf.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); - scalar_type quo = beckmann_ndf.template G2_over_G1, anisocache_type>(query, cache); + scalar_type quo = beckmann_ndf.template G2_over_G1(query, cache); return quotient_pdf_type::create(quo, _pdf); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 250947de4e..4db737f582 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -43,37 +43,6 @@ struct SGGXDielectricIsotropicBxDF NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; - // using params_isotropic_t = GGXParams; - // using params_anisotropic_t = GGXParams; - - template - struct SGGXDG1Query - { - using scalar_type = T; - - scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } - scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; } - scalar_type getOrientedEta() NBL_CONST_MEMBER_FUNC { return orientedEta; } - - scalar_type ndf; - scalar_type G1_over_2NdotV; - scalar_type orientedEta; - }; - - template - struct SGGXG2XQuery - { - using scalar_type = T; - - scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } - scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } - BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } - - scalar_type devsh_v; - scalar_type devsh_l; - BxDFClampMode _clamp; - }; - static this_t create(scalar_type eta, scalar_type A) { this_t retval; @@ -111,7 +80,20 @@ struct SGGXDielectricIsotropicBxDF scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - SGGXDG1Query dg1_query; + struct SGGXDG1Query + { + using scalar_type = scalar_type; + + scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } + scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; } + scalar_type getOrientedEta() NBL_CONST_MEMBER_FUNC { return orientedEta; } + + scalar_type ndf; + scalar_type G1_over_2NdotV; + scalar_type orientedEta; + }; + + SGGXDG1Query dg1_query; fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; dg1_query.orientedEta = orientedEta.value[0]; @@ -128,7 +110,7 @@ struct SGGXDielectricIsotropicBxDF devsh_v = ggx_ndf.devsh_part(interaction.getNdotV2()); dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(interaction.getNdotV(_clamp), devsh_v); - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * ggx_ndf.template DG1, isocache_type>(dg1_query, cache); + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * ggx_ndf.template DG1(dg1_query, cache); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) @@ -141,13 +123,26 @@ struct SGGXDielectricIsotropicBxDF ggx_ndf.a2 = a2; ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; - SGGXG2XQuery g2_query; + struct SGGXG2XQuery + { + using scalar_type = scalar_type; + + scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } + scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } + BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } + + scalar_type devsh_v; + scalar_type devsh_l; + BxDFClampMode _clamp; + }; + + SGGXG2XQuery g2_query; g2_query.devsh_v = ggx_ndf.devsh_part(interaction.getNdotV2()); g2_query.devsh_l = ggx_ndf.devsh_part(_sample.getNdotL2()); g2_query._clamp = _clamp; scalar_type quo; - quo = ggx_ndf.template G2_over_G1, sample_type, isotropic_interaction_type, isocache_type>(g2_query, _sample, interaction, cache); + quo = ggx_ndf.template G2_over_G1(g2_query, _sample, interaction, cache); return quotient_pdf_type::create(quo, _pdf); } @@ -179,34 +174,6 @@ struct SGGXDielectricAnisotropicBxDF - struct SGGXDG1Query - { - using scalar_type = T; - - scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } - scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; } - scalar_type getOrientedEta() NBL_CONST_MEMBER_FUNC { return orientedEta; } - - scalar_type ndf; - scalar_type G1_over_2NdotV; - scalar_type orientedEta; - }; - - template - struct SGGXG2XQuery - { - using scalar_type = T; - - scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } - scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } - BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } - - scalar_type devsh_v; - scalar_type devsh_l; - BxDFClampMode _clamp; - }; - static this_t create(scalar_type eta, scalar_type ax, scalar_type ay) { this_t retval; @@ -278,7 +245,20 @@ struct SGGXDielectricAnisotropicBxDF dg1_query; + struct SGGXDG1Query + { + using scalar_type = scalar_type; + + scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } + scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; } + scalar_type getOrientedEta() NBL_CONST_MEMBER_FUNC { return orientedEta; } + + scalar_type ndf; + scalar_type G1_over_2NdotV; + scalar_type orientedEta; + }; + + SGGXDG1Query dg1_query; fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; dg1_query.orientedEta = orientedEta.value[0]; @@ -295,7 +275,7 @@ struct SGGXDielectricAnisotropicBxDF, anisocache_type>(dg1_query, cache); + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * ggx_ndf.template DG1(dg1_query, cache); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) @@ -308,13 +288,26 @@ struct SGGXDielectricAnisotropicBxDF g2_query; + struct SGGXG2XQuery + { + using scalar_type = scalar_type; + + scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } + scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } + BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } + + scalar_type devsh_v; + scalar_type devsh_l; + BxDFClampMode _clamp; + }; + + SGGXG2XQuery g2_query; g2_query.devsh_v = ggx_ndf.devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); g2_query.devsh_l = ggx_ndf.devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); g2_query._clamp = BxDFClampMode::BCM_ABS; scalar_type quo; - quo = ggx_ndf.template G2_over_G1, sample_type, anisotropic_interaction_type, anisocache_type>(g2_query, _sample, interaction, cache); + quo = ggx_ndf.template G2_over_G1(g2_query, _sample, interaction, cache); return quotient_pdf_type::create(quo, _pdf); } From fe6af4a8b1e4ee1bb15f697e699715a24d57a1de Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 7 Aug 2025 15:52:11 +0700 Subject: [PATCH 168/188] added no-local-type-template-args to required args --- include/nbl/asset/utils/CHLSLCompiler.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/nbl/asset/utils/CHLSLCompiler.h b/include/nbl/asset/utils/CHLSLCompiler.h index e5fca33815..92a1dca394 100644 --- a/include/nbl/asset/utils/CHLSLCompiler.h +++ b/include/nbl/asset/utils/CHLSLCompiler.h @@ -146,6 +146,7 @@ class NBL_API2 CHLSLCompiler final : public IShaderCompiler L"-Wno-c++1z-extensions", L"-Wno-c++14-extensions", L"-Wno-gnu-static-float-init", + L"-Wno-local-type-template-args", L"-HV", L"202x" }); }; From 5503edc98bfe0338b98bf92163fc774a675b78b1 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 7 Aug 2025 16:34:50 +0700 Subject: [PATCH 169/188] use query structs for beckmann, ggx bxdfs --- .../hlsl/bxdf/reflection/beckmann.hlsl | 111 +++++++++++++----- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 97 +++++++++++---- .../hlsl/bxdf/transmission/beckmann.hlsl | 85 ++++++++++---- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 81 ++++++++++--- 4 files changed, 280 insertions(+), 94 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 2766a600e2..da9daeceff 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -40,6 +40,18 @@ struct SBeckmannIsotropicBxDF NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_MAX; + struct SBeckmannQuery + { + using scalar_type = scalar_type; + + scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } + scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } + + scalar_type lambda_L; + scalar_type lambda_V; + }; + using query_type = SBeckmannQuery; + // iso static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) { @@ -50,7 +62,18 @@ struct SBeckmannIsotropicBxDF return retval; } - scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + query_type createQuery(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) + { + query_type query; + ndf::Beckmann beckmann_ndf; + beckmann_ndf.a2 = A*A; + query.lambda_L = beckmann_ndf.LambdaC2(_sample.getNdotL2()); + query.lambda_V = beckmann_ndf.LambdaC2(interaction.getNdotV2()); + return query; + } + + template + scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(isocache_type) cache) { scalar_type a2 = A*A; ndf::Beckmann beckmann_ndf; @@ -69,19 +92,19 @@ struct SBeckmannIsotropicBxDF scalar_type lambda_V; }; - SBeckmannG2overG1Query query; - query.lambda_L = beckmann_ndf.LambdaC2(_sample.getNdotL2()); - query.lambda_V = beckmann_ndf.LambdaC2(interaction.getNdotV2()); - NG *= beckmann_ndf.template correlated(query); + SBeckmannG2overG1Query g2_query; + g2_query.lambda_L = query.getLambdaL(); + g2_query.lambda_V = query.getLambdaV(); + NG *= beckmann_ndf.template correlated(g2_query); } return NG; } - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + spectral_type eval(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { if (interaction.getNdotV() > numeric_limits::min) { - const scalar_type scalar_part = __eval_DG_wo_clamps(_sample, interaction, cache); + const scalar_type scalar_part = __eval_DG_wo_clamps(query, cache); const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, interaction.getNdotV()); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); return f() * microfacet_transform; @@ -99,7 +122,7 @@ struct SBeckmannIsotropicBxDF return s; } - scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + scalar_type pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { struct SBeckmannDG1Query { @@ -121,18 +144,18 @@ struct SBeckmannIsotropicBxDF ndf::Beckmann beckmann_ndf; beckmann_ndf.a2 = a2; dg1_query.ndf = beckmann_ndf.template D(cache); - dg1_query.lambda_V = beckmann_ndf.LambdaC2(interaction.getNdotV2()); + dg1_query.lambda_V = query.getLambdaV(); scalar_type dg1 = beckmann_ndf.template DG1(dg1_query, interaction); return dg1; } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - scalar_type _pdf = pdf(interaction, cache); + scalar_type _pdf = pdf(query, interaction, cache); ndf::Beckmann beckmann_ndf; - spectral_type quo = (spectral_type)0.0; + spectral_type quo = hlsl::promote(0.0); if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) { struct SBeckmannG2overG1Query @@ -147,10 +170,10 @@ struct SBeckmannIsotropicBxDF }; beckmann_ndf.a2 = A*A; - SBeckmannG2overG1Query query; - query.lambda_L = beckmann_ndf.LambdaC2(_sample.getNdotL2()); - query.lambda_V = beckmann_ndf.LambdaC2(interaction.getNdotV2()); - scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1(query, cache); + SBeckmannG2overG1Query g2_query; + g2_query.lambda_L = query.getLambdaL(); + g2_query.lambda_V = query.getLambdaV(); + scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1(g2_query, cache); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; @@ -183,6 +206,18 @@ struct SBeckmannAnisotropicBxDF beckmann_ndf; + beckmann_ndf.ax = A.x; + beckmann_ndf.ay = A.y; + query.lambda_L = beckmann_ndf.LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); + query.lambda_V = beckmann_ndf.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + return query; + } + + template + scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(anisocache_type) cache) { ndf::Beckmann beckmann_ndf; beckmann_ndf.ax = A.x; @@ -212,19 +259,19 @@ struct SBeckmannAnisotropicBxDF(query); + SBeckmannG2overG1Query g2_query; + g2_query.lambda_L = query.getLambdaL(); + g2_query.lambda_V = query.getLambdaV(); + NG *= beckmann_ndf.template correlated(g2_query); } return NG; } - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + spectral_type eval(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { if (interaction.getNdotV() > numeric_limits::min) { - const scalar_type scalar_part = __eval_DG_wo_clamps(_sample, interaction, cache); + const scalar_type scalar_part = __eval_DG_wo_clamps(query, cache); const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, interaction.getNdotV()); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); return f() * microfacet_transform; @@ -314,7 +361,7 @@ struct SBeckmannAnisotropicBxDF(cache); - dg1_query.lambda_V = beckmann_ndf.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + dg1_query.lambda_V = query.getLambdaV(); scalar_type dg1 = beckmann_ndf.template DG1(dg1_query, interaction); return dg1; } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - scalar_type _pdf = pdf(interaction, cache); + scalar_type _pdf = pdf(query, interaction, cache); ndf::Beckmann beckmann_ndf; - spectral_type quo = (spectral_type)0.0; + spectral_type quo = hlsl::promote(0.0); if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) { struct SBeckmannG2overG1Query @@ -364,10 +411,10 @@ struct SBeckmannAnisotropicBxDF(query, cache); + SBeckmannG2overG1Query g2_query; + g2_query.lambda_L = query.getLambdaL(); + g2_query.lambda_V = query.getLambdaV(); + scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1(g2_query, cache); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 9be2a8fd29..6737c904d8 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -40,6 +40,18 @@ struct SGGXIsotropicBxDF NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_MAX; + struct SGGXQuery + { + using scalar_type = scalar_type; + + scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } + scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } + + scalar_type devsh_v; + scalar_type devsh_l; + }; + using query_type = SGGXQuery; + // iso static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) { @@ -50,7 +62,19 @@ struct SGGXIsotropicBxDF return retval; } - scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache, BxDFClampMode _clamp) + query_type createQuery(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) + { + query_type query; + ndf::GGX ggx_ndf; + ggx_ndf.a2 = A*A; + ggx_ndf.one_minus_a2 = scalar_type(1.0) - A*A; + query.devsh_v = ggx_ndf.devsh_part(interaction.getNdotV2()); + query.devsh_l = ggx_ndf.devsh_part(_sample.getNdotL2()); + return query; + } + + template + scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache, BxDFClampMode _clamp) { scalar_type a2 = A*A; ndf::GGX ggx_ndf; @@ -73,19 +97,19 @@ struct SGGXIsotropicBxDF }; SGGXG2XQuery g2_query; - g2_query.devsh_v = ggx_ndf.devsh_part(interaction.getNdotV2()); - g2_query.devsh_l = ggx_ndf.devsh_part(_sample.getNdotL2()); + g2_query.devsh_v = query.getDevshV(); + g2_query.devsh_l = query.getDevshL(); g2_query._clamp = _clamp; NG *= ggx_ndf.template correlated_wo_numerator(g2_query, _sample, interaction); } return NG; } - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + spectral_type eval(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) { - const scalar_type scalar_part = __eval_DG_wo_clamps(_sample, interaction, cache, BxDFClampMode::BCM_MAX); + const scalar_type scalar_part = __eval_DG_wo_clamps(query, _sample, interaction, cache, BxDFClampMode::BCM_MAX); const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, _sample.getNdotL(_clamp)); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); return f() * microfacet_transform; @@ -103,7 +127,7 @@ struct SGGXIsotropicBxDF return s; } - scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + scalar_type pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { struct SGGXDG1Query { @@ -123,17 +147,17 @@ struct SGGXIsotropicBxDF ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; dg1_query.ndf = ggx_ndf.template D(cache); - const scalar_type devsh_v = ggx_ndf.devsh_part(interaction.getNdotV2()); + const scalar_type devsh_v = query.getDevshV(); dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(interaction.getNdotV(_clamp), devsh_v); return ggx_ndf.template DG1(dg1_query); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - scalar_type _pdf = pdf(interaction, cache); + scalar_type _pdf = pdf(query, interaction, cache); - spectral_type quo = (spectral_type)0.0; + spectral_type quo = hlsl::promote(0.0); if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) { struct SGGXG2XQuery @@ -155,8 +179,8 @@ struct SGGXIsotropicBxDF ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; SGGXG2XQuery g2_query; - g2_query.devsh_v = ggx_ndf.devsh_part(interaction.getNdotV2()); - g2_query.devsh_l = ggx_ndf.devsh_part(_sample.getNdotL2()); + g2_query.devsh_v = query.getDevshV(); + g2_query.devsh_l = query.getDevshL(); g2_query._clamp = BxDFClampMode::BCM_MAX; const scalar_type G2_over_G1 = ggx_ndf.template G2_over_G1(g2_query, _sample, interaction, cache); @@ -192,6 +216,18 @@ struct SGGXAnisotropicBxDF ggx_ndf; + ggx_ndf.ax2 = A.x*A.x; + ggx_ndf.ay2 = A.y*A.y; + ggx_ndf.a2 = A.x*A.y; + query.devsh_v = ggx_ndf.devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + query.devsh_l = ggx_ndf.devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); + return query; + } + + template + scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache, BxDFClampMode _clamp) { ndf::GGX ggx_ndf; ggx_ndf.ax2 = A.x*A.x; @@ -225,19 +274,19 @@ struct SGGXAnisotropicBxDF(g2_query, _sample, interaction); } return NG; } - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + spectral_type eval(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) { - const scalar_type scalar_part = __eval_DG_wo_clamps(_sample, interaction, cache, BxDFClampMode::BCM_MAX); + const scalar_type scalar_part = __eval_DG_wo_clamps(query, _sample, interaction, cache, BxDFClampMode::BCM_MAX); const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, _sample.getNdotL(_clamp)); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); return f() * microfacet_transform; @@ -281,7 +330,7 @@ struct SGGXAnisotropicBxDF(cache); - const scalar_type devsh_v = ggx_ndf.devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + const scalar_type devsh_v = query.getDevshV(); dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(interaction.getNdotV(_clamp), devsh_v); return ggx_ndf.template DG1(dg1_query); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - scalar_type _pdf = pdf(interaction, cache); + scalar_type _pdf = pdf(query, interaction, cache); - spectral_type quo = (spectral_type)0.0; + spectral_type quo = hlsl::promote(0.0); if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) { struct SGGXG2XQuery @@ -333,8 +382,8 @@ struct SGGXAnisotropicBxDF(g2_query, _sample, interaction, cache); diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 06e75265fd..3f04a11dcf 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -43,6 +43,18 @@ struct SBeckmannDielectricIsotropicBxDF NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; + struct SBeckmannQuery + { + using scalar_type = scalar_type; + + scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } + scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } + + scalar_type lambda_L; + scalar_type lambda_V; + }; + using query_type = SBeckmannQuery; + static this_t create(scalar_type eta, scalar_type A) { this_t retval; @@ -51,7 +63,17 @@ struct SBeckmannDielectricIsotropicBxDF return retval; } - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + query_type createQuery(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) + { + query_type query; + ndf::Beckmann beckmann_ndf; + beckmann_ndf.a2 = A*A; + query.lambda_L = beckmann_ndf.LambdaC2(_sample.getNdotL2()); + query.lambda_V = beckmann_ndf.LambdaC2(interaction.getNdotV2()); + return query; + } + + spectral_type eval(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; @@ -61,7 +83,7 @@ struct SBeckmannDielectricIsotropicBxDF spectral_type dummyior; brdf_type beckmann = brdf_type::create(A, dummyior, dummyior); - const scalar_type scalar_part = beckmann.__eval_DG_wo_clamps(_sample, interaction, cache); + const scalar_type scalar_part = beckmann.template __eval_DG_wo_clamps(query, cache); const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part,interaction.getNdotV(_clamp),transmitted,cache.getVdotH(),cache.getLdotH(),VdotHLdotH,orientedEta.value[0]); const scalar_type f = fresnel::Dielectric::__call(orientedEta2, hlsl::abs(cache.getVdotH()))[0]; @@ -77,7 +99,7 @@ struct SBeckmannDielectricIsotropicBxDF return s; } - scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + scalar_type pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { struct SBeckmannDG1Query { @@ -107,15 +129,15 @@ struct SBeckmannDielectricIsotropicBxDF ndf::Beckmann beckmann_ndf; beckmann_ndf.a2 = a2; dg1_query.ndf = beckmann_ndf.template D(cache); - dg1_query.lambda_V = beckmann_ndf.LambdaC2(interaction.getNdotV2()); + dg1_query.lambda_V = query.getLambdaV(); scalar_type dg1 = beckmann_ndf.template DG1(dg1_query, interaction, cache); return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * dg1; } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - scalar_type _pdf = pdf(interaction, cache); + scalar_type _pdf = pdf(query, interaction, cache); struct SBeckmannG2overG1Query { @@ -130,10 +152,10 @@ struct SBeckmannDielectricIsotropicBxDF ndf::Beckmann beckmann_ndf; beckmann_ndf.a2 = A*A; - SBeckmannG2overG1Query query; - query.lambda_L = beckmann_ndf.LambdaC2(_sample.getNdotL2()); - query.lambda_V = beckmann_ndf.LambdaC2(interaction.getNdotV2()); - scalar_type quo = beckmann_ndf.template G2_over_G1(query, cache); + SBeckmannG2overG1Query g2_query; + g2_query.lambda_L = query.getLambdaL(); + g2_query.lambda_V = query.getLambdaV(); + scalar_type quo = beckmann_ndf.template G2_over_G1(g2_query, cache); return quotient_pdf_type::create(quo, _pdf); } @@ -165,6 +187,18 @@ struct SBeckmannDielectricAnisotropicBxDF beckmann_ndf; + beckmann_ndf.ax = A.x; + beckmann_ndf.ay = A.y; + query.lambda_L = beckmann_ndf.LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); + query.lambda_V = beckmann_ndf.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + return query; + } + + spectral_type eval(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; @@ -183,7 +228,7 @@ struct SBeckmannDielectricAnisotropicBxDF(query, cache); const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part,interaction.getNdotV(_clamp),transmitted,cache.getVdotH(),cache.getLdotH(),VdotHLdotH,orientedEta.value[0]); const scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; @@ -233,7 +278,7 @@ struct SBeckmannDielectricAnisotropicBxDF(cache); - dg1_query.lambda_V = beckmann_ndf.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + dg1_query.lambda_V = query.getLambdaV(); scalar_type dg1 = beckmann_ndf.template DG1(dg1_query, interaction, cache); return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * dg1; } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - scalar_type _pdf = pdf(interaction, cache); + scalar_type _pdf = pdf(query, interaction, cache); struct SBeckmannG2overG1Query { @@ -287,10 +332,10 @@ struct SBeckmannDielectricAnisotropicBxDF beckmann_ndf; beckmann_ndf.ax = A.x; beckmann_ndf.ay = A.y; - SBeckmannG2overG1Query query; - query.lambda_L = beckmann_ndf.LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); - query.lambda_V = beckmann_ndf.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); - scalar_type quo = beckmann_ndf.template G2_over_G1(query, cache); + SBeckmannG2overG1Query g2_query; + g2_query.lambda_L = query.getLambdaL(); + g2_query.lambda_V = query.getLambdaV(); + scalar_type quo = beckmann_ndf.template G2_over_G1(g2_query, cache); return quotient_pdf_type::create(quo, _pdf); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 4db737f582..3cebf965ae 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -43,6 +43,18 @@ struct SGGXDielectricIsotropicBxDF NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; + struct SGGXQuery + { + using scalar_type = scalar_type; + + scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } + scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } + + scalar_type devsh_v; + scalar_type devsh_l; + }; + using query_type = SGGXQuery; + static this_t create(scalar_type eta, scalar_type A) { this_t retval; @@ -51,7 +63,18 @@ struct SGGXDielectricIsotropicBxDF return retval; } - spectral_type eval(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + query_type createQuery(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) + { + query_type query; + ndf::GGX ggx_ndf; + ggx_ndf.a2 = A*A; + ggx_ndf.one_minus_a2 = scalar_type(1.0) - A*A; + query.devsh_v = ggx_ndf.devsh_part(interaction.getNdotV2()); + query.devsh_l = ggx_ndf.devsh_part(_sample.getNdotL2()); + return query; + } + + spectral_type eval(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; @@ -62,7 +85,7 @@ struct SGGXDielectricIsotropicBxDF scalar_type NG_already_in_reflective_dL_measure; spectral_type dummyior; brdf_type ggx = brdf_type::create(A, dummyior, dummyior); - NG_already_in_reflective_dL_measure = ggx.__eval_DG_wo_clamps(_sample, interaction, cache, _clamp); + NG_already_in_reflective_dL_measure = ggx.template __eval_DG_wo_clamps(query, _sample, interaction, cache, _clamp); const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(NG_already_in_reflective_dL_measure,_sample.getNdotL(_clamp),transmitted,cache.getVdotH(),cache.getLdotH(),VdotHLdotH,orientedEta.value[0]); const scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; @@ -78,7 +101,7 @@ struct SGGXDielectricIsotropicBxDF return s; } - scalar_type pdf(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + scalar_type pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { struct SGGXDG1Query { @@ -100,22 +123,21 @@ struct SGGXDielectricIsotropicBxDF const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; - scalar_type devsh_v; const scalar_type a2 = A*A; ndf::GGX ggx_ndf; ggx_ndf.a2 = a2; ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; dg1_query.ndf = ggx_ndf.template D(cache); - devsh_v = ggx_ndf.devsh_part(interaction.getNdotV2()); + scalar_type devsh_v = query.getDevshV(); dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(interaction.getNdotV(_clamp), devsh_v); return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * ggx_ndf.template DG1(dg1_query, cache); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - scalar_type _pdf = pdf(interaction, cache); + scalar_type _pdf = pdf(query, interaction, cache); const bool transmitted = cache.isTransmission(); const scalar_type a2 = A * A; @@ -137,8 +159,8 @@ struct SGGXDielectricIsotropicBxDF }; SGGXG2XQuery g2_query; - g2_query.devsh_v = ggx_ndf.devsh_part(interaction.getNdotV2()); - g2_query.devsh_l = ggx_ndf.devsh_part(_sample.getNdotL2()); + g2_query.devsh_v = query.getDevshV(); + g2_query.devsh_l = query.getDevshL(); g2_query._clamp = _clamp; scalar_type quo; @@ -174,6 +196,18 @@ struct SGGXDielectricAnisotropicBxDF ggx_ndf; + ggx_ndf.ax2 = A.x*A.x; + ggx_ndf.ay2 = A.y*A.y; + ggx_ndf.a2 = A.x*A.y; + query.devsh_v = ggx_ndf.devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + query.devsh_l = ggx_ndf.devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); + return query; + } + + spectral_type eval(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; @@ -193,7 +239,7 @@ struct SGGXDielectricAnisotropicBxDF(query, _sample, interaction, cache, _clamp); const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(NG_already_in_reflective_dL_measure,_sample.getNdotL(_clamp),transmitted,cache.getVdotH(),cache.getLdotH(),VdotHLdotH,orientedEta.value[0]); const scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; @@ -243,7 +289,7 @@ struct SGGXDielectricAnisotropicBxDF::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; - scalar_type devsh_v; ndf::GGX ggx_ndf; ggx_ndf.ax2 = A.x*A.x; ggx_ndf.ay2 = A.y*A.y; ggx_ndf.a2 = A.x*A.y; dg1_query.ndf = ggx_ndf.template D(cache); - devsh_v = ggx_ndf.devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); + scalar_type devsh_v = query.getDevshV(); dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(interaction.getNdotV(_clamp), devsh_v); return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * ggx_ndf.template DG1(dg1_query, cache); } - quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - scalar_type _pdf = pdf(interaction, cache); + scalar_type _pdf = pdf(query, interaction, cache); const bool transmitted = cache.isTransmission(); ndf::GGX ggx_ndf; @@ -302,8 +347,8 @@ struct SGGXDielectricAnisotropicBxDF Date: Thu, 7 Aug 2025 16:35:38 +0700 Subject: [PATCH 170/188] latest example --- examples_tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples_tests b/examples_tests index 79cb7fe694..bdca73d8a0 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 79cb7fe69406ada805482c04d12665dc1363ab06 +Subproject commit bdca73d8a08e3642e4a7e5949cab7599f59ee8b8 From 2fefacb10553ca5e8b6ad736ed8d938067420794 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 8 Aug 2025 16:53:09 +0700 Subject: [PATCH 171/188] minor tweaks to ndf --- include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 2 -- include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 8 ++++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl index 24d4776230..a119af38d3 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -6,8 +6,6 @@ #include "nbl/builtin/hlsl/limits.hlsl" #include "nbl/builtin/hlsl/bxdf/common.hlsl" -// #include "nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl" -// #include "nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl" namespace nbl { diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index 0e3fb703de..ac2ad1f885 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -83,14 +83,14 @@ struct Beckmann) > // brdf template && surface_interactions::Isotropic) - scalar_type DG1(NBL_REF_ARG(Query) query, NBL_CONST_REF_ARG(Interaction) interaction) + scalar_type DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(Interaction) interaction) { return ndf::microfacet_to_light_measure_transform::__call(query.getNdf() / (scalar_type(1.0) + query.getLambdaV()), interaction.getNdotV(query.getClampMode())); } // bsdf template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) - scalar_type DG1(NBL_REF_ARG(Query) query, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + scalar_type DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { return ndf::microfacet_to_light_measure_transform::__call(query.getNdf() / (scalar_type(1.0) + query.getLambdaV()), interaction.getNdotV(query.getClampMode()), cache.isTransmission(), cache.getVdotH(), cache.getLdotH(), cache.getVdotHLdotH(), query.getOrientedEta()); } @@ -152,7 +152,7 @@ struct Beckmann) > } template && surface_interactions::Anisotropic) - scalar_type DG1(NBL_REF_ARG(Query) query, NBL_CONST_REF_ARG(Interaction) interaction) + scalar_type DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(Interaction) interaction) { Beckmann beckmann; scalar_type dg = beckmann.template DG1(query, interaction.isotropic); @@ -160,7 +160,7 @@ struct Beckmann) > } template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - scalar_type DG1(NBL_REF_ARG(Query) query, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + scalar_type DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { Beckmann beckmann; scalar_type dg = beckmann.template DG1(query, interaction.isotropic, cache.iso_cache); From c2af21b26f7676c57db4d72ab53f99bcbc08e6cf Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 8 Aug 2025 16:54:30 +0700 Subject: [PATCH 172/188] added a cook torrance base class --- .../builtin/hlsl/bxdf/cook_torrance_base.hlsl | 90 +++++++++++++++++++ src/nbl/builtin/CMakeLists.txt | 1 + 2 files changed, 91 insertions(+) create mode 100644 include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl diff --git a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl new file mode 100644 index 0000000000..737afc4b31 --- /dev/null +++ b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl @@ -0,0 +1,90 @@ +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_BUILTIN_HLSL_BXDF_COOK_TORRANCE_INCLUDED_ +#define _NBL_BUILTIN_HLSL_BXDF_COOK_TORRANCE_INCLUDED_ + +#include "nbl/builtin/hlsl/bxdf/common.hlsl" +#include "nbl/builtin/hlsl/bxdf/config.hlsl" + +namespace nbl +{ +namespace hlsl +{ +namespace bxdf +{ + +template) // TODO concepts for ndf and fresnel +struct SCookTorrance +{ + NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); + NBL_BXDF_CONFIG_ALIAS(vector3_type, Config); + NBL_BXDF_CONFIG_ALIAS(isotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(anisotropic_interaction_type, Config); + NBL_BXDF_CONFIG_ALIAS(sample_type, Config); + NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); + NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); + + scalar_type __D(NBL_CONST_REF_ARG(isocache_type) cache) + { + return ndf.template D(cache); + } + scalar_type __D(NBL_CONST_REF_ARG(anisocache_type) cache) + { + return ndf.template D(cache); + } + + // TODO need to make sure ndf functions have the same args -> concept + template + scalar_type __DG1(NBL_CONST_REF_ARG(Query) query) + { + return ndf.template DG1(dg1_query); + } + template + scalar_type __DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(isocache_type) cache) + { + return ndf.template DG1(dg1_query, cache); + } + template + scalar_type __DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(anisocache_type) cache) + { + return ndf.template DG1(dg1_query, cache); + } + + // TODO need to make sure ndf functions have the same args -> concept (query, sample, interaction) + template + scalar_type __DG(NBL_CONST_REF_ARG(Query) g2_query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + { + scalar_type DG = ggx_ndf.template D(cache); + if (any >(A > (vector2_type)numeric_limits::min)) + { + DG *= ggx_ndf.template correlated_wo_numerator(g2_query, _sample, interaction); + } + return DG; + } + template + scalar_type __DG(NBL_CONST_REF_ARG(Query) g2_query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + { + scalar_type DG = ggx_ndf.template D(cache); + if (any >(A > (vector2_type)numeric_limits::min)) + { + DG *= ggx_ndf.template correlated_wo_numerator(g2_query, _sample, interaction); + } + return DG; + } + + NDF getNDF() { return NDF; } + F getFresnel() { return fresnel; } + MLT getMicrofacetLightTransform( return microfacet_transform; ) + + NDF ndf; + F fresnel; + MLT microfacet_transform; +}; + +} +} +} + +#endif diff --git a/src/nbl/builtin/CMakeLists.txt b/src/nbl/builtin/CMakeLists.txt index 64202e4487..427791dfc4 100644 --- a/src/nbl/builtin/CMakeLists.txt +++ b/src/nbl/builtin/CMakeLists.txt @@ -336,6 +336,7 @@ LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/fresnel.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/geom_smith.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/ndf.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/config.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/cook_torrance_base.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/reflection.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/transmission.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/bxdf_traits.hlsl") From 56b2f7a369787636ec1f0f32374c7ba4304ec502 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 11 Aug 2025 11:29:17 +0700 Subject: [PATCH 173/188] changes to beckmann ndf DG1 for ndf concept --- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 43 ++++++------------- .../hlsl/bxdf/reflection/beckmann.hlsl | 22 ++++------ .../hlsl/bxdf/transmission/beckmann.hlsl | 20 ++------- 3 files changed, 25 insertions(+), 60 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index ac2ad1f885..f301e1a24e 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -18,7 +18,7 @@ namespace ndf namespace beckmann_concepts { -#define NBL_CONCEPT_NAME DG1BrdfQuery +#define NBL_CONCEPT_NAME DG1Query #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) #define NBL_CONCEPT_TPLT_PRM_NAMES (T) #define NBL_CONCEPT_PARAM_0 (query, T) @@ -27,28 +27,11 @@ NBL_CONCEPT_BEGIN(1) NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getNdf()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getClampMode()), ::nbl::hlsl::is_same_v, BxDFClampMode)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ); #undef query #include -#define NBL_CONCEPT_NAME DG1BsdfQuery -#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) -#define NBL_CONCEPT_TPLT_PRM_NAMES (T) -#define NBL_CONCEPT_PARAM_0 (query, T) -NBL_CONCEPT_BEGIN(1) -#define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 -NBL_CONCEPT_END( - ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getNdf()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getClampMode()), ::nbl::hlsl::is_same_v, BxDFClampMode)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getLambdaV()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((query.getOrientedEta()), ::nbl::hlsl::is_same_v, typename T::scalar_type)) -); -#undef query -#include - #define NBL_CONCEPT_NAME G2overG1Query #define NBL_CONCEPT_TPLT_PRM_KINDS (typename) #define NBL_CONCEPT_TPLT_PRM_NAMES (T) @@ -82,17 +65,17 @@ struct Beckmann) > } // brdf - template && surface_interactions::Isotropic) - scalar_type DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(Interaction) interaction) + template) + scalar_type DG1(NBL_CONST_REF_ARG(Query) query) { - return ndf::microfacet_to_light_measure_transform::__call(query.getNdf() / (scalar_type(1.0) + query.getLambdaV()), interaction.getNdotV(query.getClampMode())); + return query.getNdf() / (scalar_type(1.0) + query.getLambdaV()); } // bsdf - template && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) - scalar_type DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template && ReadableIsotropicMicrofacetCache) + scalar_type DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) { - return ndf::microfacet_to_light_measure_transform::__call(query.getNdf() / (scalar_type(1.0) + query.getLambdaV()), interaction.getNdotV(query.getClampMode()), cache.isTransmission(), cache.getVdotH(), cache.getLdotH(), cache.getVdotHLdotH(), query.getOrientedEta()); + return DG1(query); } scalar_type G1(scalar_type lambda) @@ -151,19 +134,19 @@ struct Beckmann) > return numbers::inv_pi * nom / denom; } - template && surface_interactions::Anisotropic) - scalar_type DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(Interaction) interaction) + template) + scalar_type DG1(NBL_CONST_REF_ARG(Query) query) { Beckmann beckmann; - scalar_type dg = beckmann.template DG1(query, interaction.isotropic); + scalar_type dg = beckmann.template DG1(query); return dg; } - template && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) - scalar_type DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template && AnisotropicMicrofacetCache) + scalar_type DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) { Beckmann beckmann; - scalar_type dg = beckmann.template DG1(query, interaction.isotropic, cache.iso_cache); + scalar_type dg = beckmann.template DG1(query, cache.iso_cache); return dg; } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index da9daeceff..ed34742c89 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -129,25 +129,22 @@ struct SBeckmannIsotropicBxDF using scalar_type = scalar_type; scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } - BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } scalar_type ndf; - BxDFClampMode _clamp; scalar_type lambda_V; }; - - SBeckmannDG1Query dg1_query; - dg1_query._clamp = BxDFClampMode::BCM_MAX; scalar_type a2 = A*A; ndf::Beckmann beckmann_ndf; beckmann_ndf.a2 = a2; + + SBeckmannDG1Query dg1_query; dg1_query.ndf = beckmann_ndf.template D(cache); dg1_query.lambda_V = query.getLambdaV(); - scalar_type dg1 = beckmann_ndf.template DG1(dg1_query, interaction); - return dg1; + scalar_type dg1 = beckmann_ndf.template DG1(dg1_query); + return ndf::microfacet_to_light_measure_transform::__call(dg1, interaction.getNdotV(_clamp)); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) @@ -368,26 +365,23 @@ struct SBeckmannAnisotropicBxDF beckmann_ndf; beckmann_ndf.ax = A.x; beckmann_ndf.ay = A.y; + + SBeckmannDG1Query dg1_query; dg1_query.ndf = beckmann_ndf.template D(cache); dg1_query.lambda_V = query.getLambdaV(); - scalar_type dg1 = beckmann_ndf.template DG1(dg1_query, interaction); - return dg1; + scalar_type dg1 = beckmann_ndf.template DG1(dg1_query); + return ndf::microfacet_to_light_measure_transform::__call(dg1, interaction.getNdotV(_clamp)); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 3f04a11dcf..901705a527 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -106,22 +106,16 @@ struct SBeckmannDielectricIsotropicBxDF using scalar_type = scalar_type; scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; } - BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - scalar_type getOrientedEta() NBL_CONST_MEMBER_FUNC { return orientedEta; } scalar_type ndf; - BxDFClampMode _clamp; scalar_type lambda_V; - scalar_type orientedEta; }; SBeckmannDG1Query dg1_query; - dg1_query._clamp = BxDFClampMode::BCM_ABS; fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; - dg1_query.orientedEta = orientedEta.value[0]; const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; @@ -131,8 +125,8 @@ struct SBeckmannDielectricIsotropicBxDF dg1_query.ndf = beckmann_ndf.template D(cache); dg1_query.lambda_V = query.getLambdaV(); - scalar_type dg1 = beckmann_ndf.template DG1(dg1_query, interaction, cache); - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * dg1; + scalar_type dg1 = beckmann_ndf.template DG1(dg1_query, cache); + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * ndf::microfacet_to_light_measure_transform::__call(dg1, interaction.getNdotV(_clamp), cache.isTransmission(), cache.getVdotH(), cache.getLdotH(), cache.getVdotHLdotH(), orientedEta.value[0]); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) @@ -285,22 +279,16 @@ struct SBeckmannDielectricAnisotropicBxDF orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; - dg1_query.orientedEta = orientedEta.value[0]; const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; @@ -310,8 +298,8 @@ struct SBeckmannDielectricAnisotropicBxDF(cache); dg1_query.lambda_V = query.getLambdaV(); - scalar_type dg1 = beckmann_ndf.template DG1(dg1_query, interaction, cache); - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * dg1; + scalar_type dg1 = beckmann_ndf.template DG1(dg1_query, cache); + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * ndf::microfacet_to_light_measure_transform::__call(dg1, interaction.getNdotV(_clamp), cache.isTransmission(), cache.getVdotH(), cache.getLdotH(), cache.getVdotHLdotH(), orientedEta.value[0]); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) From e89663b82c8f25114eccc8d51a52e504465bd94c Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 11 Aug 2025 12:03:43 +0700 Subject: [PATCH 174/188] make correlated and G2overG1 func sigs same in ndfs --- include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 16 ++++++++-------- include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 7 ++++--- .../builtin/hlsl/bxdf/reflection/beckmann.hlsl | 16 ++++++++-------- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 4 ++-- .../builtin/hlsl/bxdf/transmission/beckmann.hlsl | 8 ++++---- 5 files changed, 26 insertions(+), 25 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index f301e1a24e..4342dac19b 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -101,14 +101,14 @@ struct Beckmann) > return Lambda(C2(NdotX2)); } - template) - scalar_type correlated(NBL_CONST_REF_ARG(Query) query) + template && LightSample && surface_interactions::Isotropic) + scalar_type correlated(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { return scalar_type(1.0) / (scalar_type(1.0) + query.getLambdaV() + query.getLambdaL()); } - template && ReadableIsotropicMicrofacetCache) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template && LightSample && surface_interactions::Isotropic && ReadableIsotropicMicrofacetCache) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { scalar_type onePlusLambda_V = scalar_type(1.0) + query.getLambdaV(); return onePlusLambda_V * hlsl::mix(scalar_type(1.0)/(onePlusLambda_V + query.getLambdaL()), bxdf::beta(onePlusLambda_V, scalar_type(1.0) + query.getLambdaL()), cache.isTransmission()); @@ -175,14 +175,14 @@ struct Beckmann) > return Lambda(C2(TdotX2, BdotX2, NdotX2)); } - template) - scalar_type correlated(NBL_CONST_REF_ARG(Query) query) + template && LightSample && surface_interactions::Anisotropic) + scalar_type correlated(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { return scalar_type(1.0) / (scalar_type(1.0) + query.getLambdaV() + query.getLambdaL()); } - template && AnisotropicMicrofacetCache) - scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(MicrofacetCache) cache) + template && LightSample && surface_interactions::Anisotropic && AnisotropicMicrofacetCache) + scalar_type G2_over_G1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache) { scalar_type onePlusLambda_V = scalar_type(1.0) + query.getLambdaV(); return onePlusLambda_V * hlsl::mix(scalar_type(1.0)/(onePlusLambda_V + query.getLambdaL()), bxdf::beta(onePlusLambda_V, scalar_type(1.0) + query.getLambdaL()), cache.isTransmission()); diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index e661cdaa2c..261f677347 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -118,13 +118,13 @@ struct GGX) > return scalar_type(1.0) / (absNdotX + devsh_part); } + // without numerator, numerator is 2 * NdotV * NdotL, we factor out 4 * NdotV * NdotL, hence 0.5 template && LightSample && surface_interactions::Isotropic) - scalar_type correlated_wo_numerator(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + scalar_type correlated(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { BxDFClampMode _clamp = query.getClampMode(); assert(_clamp != BxDFClampMode::BCM_NONE); - // numerator is 2 * NdotV * NdotL, we factor out 4 * NdotV * NdotL, hence 0.5 scalar_type Vterm = _sample.getNdotL(_clamp) * query.getDevshV(); scalar_type Lterm = interaction.getNdotV(_clamp) * query.getDevshL(); return scalar_type(0.5) / (Vterm + Lterm); @@ -216,8 +216,9 @@ struct GGX) > return scalar_type(1.0) / (NdotX + devsh_part); } + // without numerator template && LightSample && surface_interactions::Anisotropic) - scalar_type correlated_wo_numerator(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) + scalar_type correlated(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction) { BxDFClampMode _clamp = query.getClampMode(); assert(_clamp != BxDFClampMode::BCM_NONE); diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index ed34742c89..01d22e3165 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -73,7 +73,7 @@ struct SBeckmannIsotropicBxDF } template - scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(isocache_type) cache) + scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { scalar_type a2 = A*A; ndf::Beckmann beckmann_ndf; @@ -95,7 +95,7 @@ struct SBeckmannIsotropicBxDF SBeckmannG2overG1Query g2_query; g2_query.lambda_L = query.getLambdaL(); g2_query.lambda_V = query.getLambdaV(); - NG *= beckmann_ndf.template correlated(g2_query); + NG *= beckmann_ndf.template correlated(g2_query, _sample, interaction); } return NG; } @@ -104,7 +104,7 @@ struct SBeckmannIsotropicBxDF { if (interaction.getNdotV() > numeric_limits::min) { - const scalar_type scalar_part = __eval_DG_wo_clamps(query, cache); + const scalar_type scalar_part = __eval_DG_wo_clamps(query, _sample, interaction, cache); const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, interaction.getNdotV()); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); return f() * microfacet_transform; @@ -170,7 +170,7 @@ struct SBeckmannIsotropicBxDF SBeckmannG2overG1Query g2_query; g2_query.lambda_L = query.getLambdaL(); g2_query.lambda_V = query.getLambdaV(); - scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1(g2_query, cache); + scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1(g2_query, _sample, interaction, cache); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; @@ -237,7 +237,7 @@ struct SBeckmannAnisotropicBxDF - scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(anisocache_type) cache) + scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { ndf::Beckmann beckmann_ndf; beckmann_ndf.ax = A.x; @@ -259,7 +259,7 @@ struct SBeckmannAnisotropicBxDF(g2_query); + NG *= beckmann_ndf.template correlated(g2_query, _sample, interaction); } return NG; } @@ -268,7 +268,7 @@ struct SBeckmannAnisotropicBxDF numeric_limits::min) { - const scalar_type scalar_part = __eval_DG_wo_clamps(query, cache); + const scalar_type scalar_part = __eval_DG_wo_clamps(query, _sample, interaction, cache); const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, interaction.getNdotV()); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); return f() * microfacet_transform; @@ -408,7 +408,7 @@ struct SBeckmannAnisotropicBxDF(g2_query, cache); + scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1(g2_query, _sample, interaction, cache); fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 6737c904d8..d63488ea04 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -100,7 +100,7 @@ struct SGGXIsotropicBxDF g2_query.devsh_v = query.getDevshV(); g2_query.devsh_l = query.getDevshL(); g2_query._clamp = _clamp; - NG *= ggx_ndf.template correlated_wo_numerator(g2_query, _sample, interaction); + NG *= ggx_ndf.template correlated(g2_query, _sample, interaction); } return NG; } @@ -277,7 +277,7 @@ struct SGGXAnisotropicBxDF(g2_query, _sample, interaction); + NG *= ggx_ndf.template correlated(g2_query, _sample, interaction); } return NG; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 901705a527..6a7f09ef49 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -83,7 +83,7 @@ struct SBeckmannDielectricIsotropicBxDF spectral_type dummyior; brdf_type beckmann = brdf_type::create(A, dummyior, dummyior); - const scalar_type scalar_part = beckmann.template __eval_DG_wo_clamps(query, cache); + const scalar_type scalar_part = beckmann.template __eval_DG_wo_clamps(query, _sample, interaction, cache); const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part,interaction.getNdotV(_clamp),transmitted,cache.getVdotH(),cache.getLdotH(),VdotHLdotH,orientedEta.value[0]); const scalar_type f = fresnel::Dielectric::__call(orientedEta2, hlsl::abs(cache.getVdotH()))[0]; @@ -149,7 +149,7 @@ struct SBeckmannDielectricIsotropicBxDF SBeckmannG2overG1Query g2_query; g2_query.lambda_L = query.getLambdaL(); g2_query.lambda_V = query.getLambdaV(); - scalar_type quo = beckmann_ndf.template G2_over_G1(g2_query, cache); + scalar_type quo = beckmann_ndf.template G2_over_G1(g2_query, _sample, interaction, cache); return quotient_pdf_type::create(quo, _pdf); } @@ -222,7 +222,7 @@ struct SBeckmannDielectricAnisotropicBxDF(query, cache); + const scalar_type scalar_part = beckmann.template __eval_DG_wo_clamps(query, _sample, interaction, cache); const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part,interaction.getNdotV(_clamp),transmitted,cache.getVdotH(),cache.getLdotH(),VdotHLdotH,orientedEta.value[0]); const scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; @@ -323,7 +323,7 @@ struct SBeckmannDielectricAnisotropicBxDF(g2_query, cache); + scalar_type quo = beckmann_ndf.template G2_over_G1(g2_query, _sample, interaction, cache); return quotient_pdf_type::create(quo, _pdf); } From 96cbe1cb6e7ddaf89a43002a942cc53e82ab3a09 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 11 Aug 2025 16:31:53 +0700 Subject: [PATCH 175/188] split out microfacet-to-light-transform, ndf concept --- .../builtin/hlsl/bxdf/cook_torrance_base.hlsl | 7 +- include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 140 +++++------------- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 2 +- include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 3 +- .../ndf/microfacet_to_light_transform.hlsl | 130 ++++++++++++++++ src/nbl/builtin/CMakeLists.txt | 1 + 6 files changed, 172 insertions(+), 111 deletions(-) create mode 100644 include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl diff --git a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl index 737afc4b31..8c219d9daf 100644 --- a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl @@ -6,6 +6,7 @@ #include "nbl/builtin/hlsl/bxdf/common.hlsl" #include "nbl/builtin/hlsl/bxdf/config.hlsl" +#include "nbl/builtin/hlsl/bxdf/ndf.hlsl" namespace nbl { @@ -14,7 +15,7 @@ namespace hlsl namespace bxdf { -template) // TODO concepts for ndf and fresnel +template && ndf::NDF) // TODO concepts for ndf and fresnel struct SCookTorrance { NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); @@ -74,11 +75,11 @@ struct SCookTorrance return DG; } - NDF getNDF() { return NDF; } + N getNDF() { return N; } F getFresnel() { return fresnel; } MLT getMicrofacetLightTransform( return microfacet_transform; ) - NDF ndf; + N ndf; F fresnel; MLT microfacet_transform; }; diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl index a119af38d3..525cbbf062 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -4,8 +4,7 @@ #ifndef _NBL_BUILTIN_HLSL_BXDF_NDF_INCLUDED_ #define _NBL_BUILTIN_HLSL_BXDF_NDF_INCLUDED_ -#include "nbl/builtin/hlsl/limits.hlsl" -#include "nbl/builtin/hlsl/bxdf/common.hlsl" +#include "nbl/builtin/hlsl/concepts.hlsl" namespace nbl { @@ -16,111 +15,42 @@ namespace bxdf namespace ndf { -enum MicrofacetTransformTypes : uint16_t +namespace dummy_impl { - MTT_REFLECT = 0b01, - MTT_REFRACT = 0b10, - MTT_REFLECT_REFRACT = 0b11 -}; - -template -struct microfacet_to_light_measure_transform; - -template -struct microfacet_to_light_measure_transform -{ - using this_t = microfacet_to_light_measure_transform; - using scalar_type = T; - - // this computes the max(NdotL,0)/(4*max(NdotV,0)*max(NdotL,0)) factor which transforms PDFs in the f in projected microfacet f * NdotH measure to projected light measure f * NdotL - static scalar_type __call(scalar_type NDFcos, scalar_type maxNdotV) - { - return scalar_type(0.25) * NDFcos / maxNdotV; - } -}; - -template -struct microfacet_to_light_measure_transform -{ - using this_t = microfacet_to_light_measure_transform; - using scalar_type = T; - - // this computes the max(NdotL,0)/(4*max(NdotV,0)*max(NdotL,0)) factor which transforms PDFs in the f in projected microfacet f * NdotH measure to projected light measure f * NdotL - static scalar_type __call(scalar_type NDFcos, scalar_type maxNdotL) - { - return NDFcos * maxNdotL; - } -}; - -template -struct microfacet_to_light_measure_transform -{ - using this_t = microfacet_to_light_measure_transform; - using scalar_type = T; - - static scalar_type __call(scalar_type NDFcos, scalar_type absNdotV, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) - { - scalar_type denominator = absNdotV; - const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); - // VdotHLdotH is negative under transmission, so thats denominator is negative - denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; - return NDFcos * VdotHLdotH / denominator; - } -}; - -template -struct microfacet_to_light_measure_transform -{ - using this_t = microfacet_to_light_measure_transform; - using scalar_type = T; - - static scalar_type __call(scalar_type NDFcos, scalar_type absNdotV, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) - { - scalar_type denominator = absNdotV; - const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); - // VdotHLdotH is negative under transmission, so thats denominator is negative - denominator *= -scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); - return NDFcos * denominator; - } -}; - -template -struct microfacet_to_light_measure_transform -{ - using this_t = microfacet_to_light_measure_transform; - using scalar_type = T; - - static scalar_type __call(scalar_type NDFcos, scalar_type absNdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) - { - scalar_type denominator = absNdotV; - if (transmitted) - { - const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); - // VdotHLdotH is negative under transmission, so thats denominator is negative - denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; - } - return NDFcos * (transmitted ? VdotHLdotH : scalar_type(0.25)) / denominator; - } -}; - -template -struct microfacet_to_light_measure_transform -{ - using this_t = microfacet_to_light_measure_transform; - using scalar_type = T; +struct DQuery {}; +struct DLightSample {}; +struct DInteraction {}; +struct DMicrofacetCache {}; +} - static scalar_type __call(scalar_type NDFcos, scalar_type absNdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) - { - scalar_type denominator = absNdotV; - if (transmitted) - { - const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); - // VdotHLdotH is negative under transmission, so thats denominator is negative - denominator *= -scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); - } - return NDFcos * denominator; - } -}; +#define NBL_CONCEPT_NAME NDF +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (ndf, T) +#define NBL_CONCEPT_PARAM_1 (query, dummy_impl::DQuery) +#define NBL_CONCEPT_PARAM_2 (_sample, dummy_impl::DLightSample) +#define NBL_CONCEPT_PARAM_3 (interaction, dummy_impl::DInteraction) +#define NBL_CONCEPT_PARAM_4 (cache, dummy_impl::DMicrofacetCache) +NBL_CONCEPT_BEGIN(5) +#define ndf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +#define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 +#define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 +#define interaction NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 +#define cache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template D(cache)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template DG1(query)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template DG1(query, cache)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template correlated(query, _sample, interaction)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template G2_over_G1(query, _sample, interaction, cache)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) +); +#undef cache +#undef interaction +#undef _sample +#undef query +#undef ndf +#include } } diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index 4342dac19b..934d238507 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -5,7 +5,7 @@ #define _NBL_BUILTIN_HLSL_BXDF_NDF_BECKMANN_INCLUDED_ #include "nbl/builtin/hlsl/limits.hlsl" -#include "nbl/builtin/hlsl/bxdf/ndf.hlsl" +#include "nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl" namespace nbl { diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index 261f677347..8cb639e339 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -5,7 +5,7 @@ #define _NBL_BUILTIN_HLSL_BXDF_NDF_GGX_INCLUDED_ #include "nbl/builtin/hlsl/limits.hlsl" -#include "nbl/builtin/hlsl/bxdf/ndf.hlsl" +#include "nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl" namespace nbl { @@ -71,7 +71,6 @@ NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar) struct GGX) > { using scalar_type = T; - using this_t = GGX; // trowbridge-reitz template) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl new file mode 100644 index 0000000000..47fcf6f05f --- /dev/null +++ b/include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl @@ -0,0 +1,130 @@ +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_BUILTIN_HLSL_BXDF_NDF_MICROFACET_LIGHT_TRANSFORM_INCLUDED_ +#define _NBL_BUILTIN_HLSL_BXDF_NDF_MICROFACET_LIGHT_TRANSFORM_INCLUDED_ + +#include "nbl/builtin/hlsl/limits.hlsl" +#include "nbl/builtin/hlsl/bxdf/common.hlsl" + +namespace nbl +{ +namespace hlsl +{ +namespace bxdf +{ +namespace ndf +{ + +enum MicrofacetTransformTypes : uint16_t +{ + MTT_REFLECT = 0b01, + MTT_REFRACT = 0b10, + MTT_REFLECT_REFRACT = 0b11 +}; + +template +struct microfacet_to_light_measure_transform; + +template +struct microfacet_to_light_measure_transform +{ + using this_t = microfacet_to_light_measure_transform; + using scalar_type = T; + + // this computes the max(NdotL,0)/(4*max(NdotV,0)*max(NdotL,0)) factor which transforms PDFs in the f in projected microfacet f * NdotH measure to projected light measure f * NdotL + static scalar_type __call(scalar_type NDFcos, scalar_type maxNdotV) + { + return scalar_type(0.25) * NDFcos / maxNdotV; + } +}; + +template +struct microfacet_to_light_measure_transform +{ + using this_t = microfacet_to_light_measure_transform; + using scalar_type = T; + + // this computes the max(NdotL,0)/(4*max(NdotV,0)*max(NdotL,0)) factor which transforms PDFs in the f in projected microfacet f * NdotH measure to projected light measure f * NdotL + static scalar_type __call(scalar_type NDFcos, scalar_type maxNdotL) + { + return NDFcos * maxNdotL; + } +}; + +template +struct microfacet_to_light_measure_transform +{ + using this_t = microfacet_to_light_measure_transform; + using scalar_type = T; + + static scalar_type __call(scalar_type NDFcos, scalar_type absNdotV, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) + { + scalar_type denominator = absNdotV; + const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); + // VdotHLdotH is negative under transmission, so thats denominator is negative + denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; + return NDFcos * VdotHLdotH / denominator; + } +}; + +template +struct microfacet_to_light_measure_transform +{ + using this_t = microfacet_to_light_measure_transform; + using scalar_type = T; + + static scalar_type __call(scalar_type NDFcos, scalar_type absNdotV, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) + { + scalar_type denominator = absNdotV; + const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); + // VdotHLdotH is negative under transmission, so thats denominator is negative + denominator *= -scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); + return NDFcos * denominator; + } +}; + +template +struct microfacet_to_light_measure_transform +{ + using this_t = microfacet_to_light_measure_transform; + using scalar_type = T; + + static scalar_type __call(scalar_type NDFcos, scalar_type absNdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) + { + scalar_type denominator = absNdotV; + if (transmitted) + { + const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); + // VdotHLdotH is negative under transmission, so thats denominator is negative + denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; + } + return NDFcos * (transmitted ? VdotHLdotH : scalar_type(0.25)) / denominator; + } +}; + +template +struct microfacet_to_light_measure_transform +{ + using this_t = microfacet_to_light_measure_transform; + using scalar_type = T; + + static scalar_type __call(scalar_type NDFcos, scalar_type absNdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) + { + scalar_type denominator = absNdotV; + if (transmitted) + { + const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); + // VdotHLdotH is negative under transmission, so thats denominator is negative + denominator *= -scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); + } + return NDFcos * denominator; + } +}; + +} +} +} +} + +#endif diff --git a/src/nbl/builtin/CMakeLists.txt b/src/nbl/builtin/CMakeLists.txt index 427791dfc4..d1dc9a1e88 100644 --- a/src/nbl/builtin/CMakeLists.txt +++ b/src/nbl/builtin/CMakeLists.txt @@ -342,6 +342,7 @@ LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/transmission.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/bxdf_traits.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/ndf/beckmann.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/ndf/ggx.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/reflection/beckmann.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/reflection/ggx.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bxdf/reflection/lambertian.hlsl") From fa940c3724215adc8aa8348d9939ba5e4c7d9374 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 11 Aug 2025 16:40:39 +0700 Subject: [PATCH 176/188] fresnel concept --- .../builtin/hlsl/bxdf/cook_torrance_base.hlsl | 3 ++- include/nbl/builtin/hlsl/bxdf/fresnel.hlsl | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl index 8c219d9daf..303c55d62c 100644 --- a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl @@ -7,6 +7,7 @@ #include "nbl/builtin/hlsl/bxdf/common.hlsl" #include "nbl/builtin/hlsl/bxdf/config.hlsl" #include "nbl/builtin/hlsl/bxdf/ndf.hlsl" +#include "nbl/builtin/hlsl/bxdf/fresnel.hlsl" namespace nbl { @@ -15,7 +16,7 @@ namespace hlsl namespace bxdf { -template && ndf::NDF) // TODO concepts for ndf and fresnel +template && ndf::NDF && fresnel::Fresnel) struct SCookTorrance { NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); diff --git a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl index 472576bfb0..bf530320be 100644 --- a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl @@ -290,10 +290,25 @@ struct ReflectRefract namespace fresnel { +#define NBL_CONCEPT_NAME Fresnel +#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) +#define NBL_CONCEPT_TPLT_PRM_NAMES (T) +#define NBL_CONCEPT_PARAM_0 (fresnel, T) +NBL_CONCEPT_BEGIN(1) +#define fresnel NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 +NBL_CONCEPT_END( + ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) + ((NBL_CONCEPT_REQ_TYPE)(T::vector_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((fresnel()), ::nbl::hlsl::is_same_v, typename T::vector_type)) +); +#undef fresnel +#include + template) struct Schlick { using scalar_type = typename vector_traits::scalar_type; + using vector_type = T; static Schlick create(NBL_CONST_REF_ARG(T) F0, scalar_type clampedCosTheta) { @@ -319,6 +334,7 @@ template struct Conductor { using scalar_type = typename vector_traits::scalar_type; + using vector_type = T; static Conductor create(NBL_CONST_REF_ARG(T) eta, NBL_CONST_REF_ARG(T) etak, scalar_type clampedCosTheta) { @@ -365,6 +381,7 @@ template struct Dielectric { using scalar_type = typename vector_traits::scalar_type; + using vector_type = T; static Dielectric create(NBL_CONST_REF_ARG(T) eta, scalar_type cosTheta) { @@ -403,6 +420,7 @@ template struct DielectricFrontFaceOnly { using scalar_type = typename vector_traits::scalar_type; + using vector_type = T; static DielectricFrontFaceOnly create(NBL_CONST_REF_ARG(T) orientedEta2, scalar_type absCosTheta) { From 062bdac9e95c0eda9c330ad0e1721c91152c7ddf Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 13 Aug 2025 16:06:39 +0700 Subject: [PATCH 177/188] added if_constexpr macro --- include/nbl/builtin/hlsl/cpp_compat/basic.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/nbl/builtin/hlsl/cpp_compat/basic.h b/include/nbl/builtin/hlsl/cpp_compat/basic.h index 3802bd69ea..87baa1f0d6 100644 --- a/include/nbl/builtin/hlsl/cpp_compat/basic.h +++ b/include/nbl/builtin/hlsl/cpp_compat/basic.h @@ -43,6 +43,7 @@ inline To _static_cast(From v) #define NBL_CONSTEXPR_INLINE_FUNC constexpr inline #define NBL_CONSTEXPR_FORCED_INLINE_FUNC NBL_FORCE_INLINE constexpr #define NBL_CONST_MEMBER_FUNC const +#define NBL_IF_CONSTEXPR(...) if constexpr (__VA_ARGS__) namespace nbl::hlsl { @@ -73,6 +74,7 @@ namespace nbl::hlsl #define NBL_CONSTEXPR_INLINE_FUNC inline #define NBL_CONSTEXPR_FORCED_INLINE_FUNC inline #define NBL_CONST_MEMBER_FUNC +#define NBL_IF_CONSTEXPR(...) if (__VA_ARGS__) namespace nbl { From a4d8410dd37fd82aa7e715087061f32c27fd5072 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 13 Aug 2025 16:12:37 +0700 Subject: [PATCH 178/188] overhaul microfacet light transform usage, cook torrance base class + refactor into bxdfs --- .../builtin/hlsl/bxdf/cook_torrance_base.hlsl | 74 +++++++--- include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 10 +- .../nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl | 12 +- include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl | 6 +- .../ndf/microfacet_to_light_transform.hlsl | 139 ++++++++++++++---- .../hlsl/bxdf/reflection/beckmann.hlsl | 120 +++++++-------- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 127 +++++++--------- .../hlsl/bxdf/transmission/beckmann.hlsl | 116 ++++++++++----- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 139 +++++++++++------- 9 files changed, 450 insertions(+), 293 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl index 303c55d62c..d7c03c85e2 100644 --- a/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl @@ -8,6 +8,7 @@ #include "nbl/builtin/hlsl/bxdf/config.hlsl" #include "nbl/builtin/hlsl/bxdf/ndf.hlsl" #include "nbl/builtin/hlsl/bxdf/fresnel.hlsl" +#include "nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl" namespace nbl { @@ -16,7 +17,8 @@ namespace hlsl namespace bxdf { -template && ndf::NDF && fresnel::Fresnel) +// N (NDF), F (fresnel), MT (measure transform, using DualMeasureQuant) +template && ndf::NDF && fresnel::Fresnel) struct SCookTorrance { NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); @@ -37,52 +39,80 @@ struct SCookTorrance return ndf.template D(cache); } - // TODO need to make sure ndf functions have the same args -> concept template - scalar_type __DG1(NBL_CONST_REF_ARG(Query) query) + MT __DG1(NBL_CONST_REF_ARG(Query) query) { - return ndf.template DG1(dg1_query); + MT measure_transform; + measure_transform.pdf = ndf.template DG1(query); + return measure_transform; } template - scalar_type __DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(isocache_type) cache) + MT __DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(isocache_type) cache) { - return ndf.template DG1(dg1_query, cache); + MT measure_transform; + measure_transform.pdf = ndf.template DG1(query, cache); + measure_transform.transmitted = cache.isTransmission(); + measure_transform.VdotH = cache.getVdotH(); + measure_transform.LdotH = cache.getLdotH(); + measure_transform.VdotHLdotH = cache.getVdotHLdotH(); + return measure_transform; } template - scalar_type __DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(anisocache_type) cache) + MT __DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(anisocache_type) cache) { - return ndf.template DG1(dg1_query, cache); + MT measure_transform; + measure_transform.pdf = ndf.template DG1(query, cache); + measure_transform.transmitted = cache.isTransmission(); + measure_transform.VdotH = cache.getVdotH(); + measure_transform.LdotH = cache.getLdotH(); + measure_transform.VdotHLdotH = cache.getVdotHLdotH(); + return measure_transform; } - // TODO need to make sure ndf functions have the same args -> concept (query, sample, interaction) template - scalar_type __DG(NBL_CONST_REF_ARG(Query) g2_query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + MT __DG(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - scalar_type DG = ggx_ndf.template D(cache); - if (any >(A > (vector2_type)numeric_limits::min)) + MT measure_transform; + measure_transform.pdf = ndf.template D(cache); + NBL_IF_CONSTEXPR(MT::Type == ndf::MicrofacetTransformTypes::MTT_REFLECT_REFRACT) + measure_transform.transmitted = cache.isTransmission(); + NBL_IF_CONSTEXPR(MT::Type == ndf::MicrofacetTransformTypes::MTT_REFRACT) { - DG *= ggx_ndf.template correlated_wo_numerator(g2_query, _sample, interaction); + measure_transform.VdotH = cache.getVdotH(); + measure_transform.LdotH = cache.getLdotH(); + measure_transform.VdotHLdotH = cache.getVdotHLdotH(); } - return DG; + if (any >(ndf.A > hlsl::promote(numeric_limits::min))) + { + measure_transform.pdf *= ndf.template correlated(query, _sample, interaction); + } + return measure_transform; } template - scalar_type __DG(NBL_CONST_REF_ARG(Query) g2_query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + MT __DG(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - scalar_type DG = ggx_ndf.template D(cache); - if (any >(A > (vector2_type)numeric_limits::min)) + MT measure_transform; + measure_transform.pdf = ndf.template D(cache); + NBL_IF_CONSTEXPR(MT::Type == ndf::MicrofacetTransformTypes::MTT_REFLECT_REFRACT) + measure_transform.transmitted = cache.isTransmission(); + NBL_IF_CONSTEXPR(MT::Type == ndf::MicrofacetTransformTypes::MTT_REFRACT) + { + measure_transform.VdotH = cache.getVdotH(); + measure_transform.LdotH = cache.getLdotH(); + measure_transform.VdotHLdotH = cache.getVdotHLdotH(); + } + if (any >(ndf.A > hlsl::promote(numeric_limits::min))) { - DG *= ggx_ndf.template correlated_wo_numerator(g2_query, _sample, interaction); + measure_transform.pdf *= ndf.template correlated(query, _sample, interaction); } - return DG; + return measure_transform; } - N getNDF() { return N; } + N getNDF() { return ndf; } F getFresnel() { return fresnel; } - MLT getMicrofacetLightTransform( return microfacet_transform; ) N ndf; F fresnel; - MLT microfacet_transform; }; } diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl index 525cbbf062..6bfb159914 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -39,11 +39,11 @@ NBL_CONCEPT_BEGIN(5) #define cache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template D(cache)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template DG1(query)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template DG1(query, cache)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template correlated(query, _sample, interaction)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template G2_over_G1(query, _sample, interaction, cache)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + // ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template D(cache)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + // ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template DG1(query)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + // ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template DG1(query, cache)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + // ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template correlated(query, _sample, interaction)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + // ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template G2_over_G1(query, _sample, interaction, cache)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ); #undef cache #undef interaction diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl index 934d238507..8076102d94 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl @@ -114,6 +114,7 @@ struct Beckmann) > return onePlusLambda_V * hlsl::mix(scalar_type(1.0)/(onePlusLambda_V + query.getLambdaL()), bxdf::beta(onePlusLambda_V, scalar_type(1.0) + query.getLambdaL()), cache.isTransmission()); } + vector A; scalar_type a2; }; @@ -127,10 +128,8 @@ struct Beckmann) > template) scalar_type D(NBL_CONST_REF_ARG(MicrofacetCache) cache) { - const scalar_type ax2 = ax*ax; - const scalar_type ay2 = ay*ay; scalar_type nom = exp(-(cache.getTdotH2() / ax2 + cache.getBdotH2() / ay2) / cache.getNdotH2()); - scalar_type denom = ax * ay * cache.getNdotH2() * cache.getNdotH2(); + scalar_type denom = A.x * A.y * cache.getNdotH2() * cache.getNdotH2(); return numbers::inv_pi * nom / denom; } @@ -157,8 +156,6 @@ struct Beckmann) > scalar_type C2(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2) { - const scalar_type ax2 = ax*ax; - const scalar_type ay2 = ay*ay; return NdotX2 / (TdotX2 * ax2 + BdotX2 * ay2); } @@ -188,8 +185,9 @@ struct Beckmann) > return onePlusLambda_V * hlsl::mix(scalar_type(1.0)/(onePlusLambda_V + query.getLambdaL()), bxdf::beta(onePlusLambda_V, scalar_type(1.0) + query.getLambdaL()), cache.isTransmission()); } - scalar_type ax; - scalar_type ay; + vector A; + scalar_type ax2; + scalar_type ay2; }; } diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl index 8cb639e339..c21ded7af1 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl @@ -81,7 +81,7 @@ struct GGX) > } template) - scalar_type DG1(NBL_REF_ARG(Query) query) + scalar_type DG1(NBL_CONST_REF_ARG(Query) query) { return scalar_type(0.5) * query.getNdf() * query.getG1over2NdotV(); } @@ -157,6 +157,7 @@ struct GGX) > return G2_over_G1; } + vector A; scalar_type a2; scalar_type one_minus_a2; }; @@ -186,7 +187,7 @@ struct GGX) > } template) - scalar_type DG1(NBL_REF_ARG(Query) query) + scalar_type DG1(NBL_CONST_REF_ARG(Query) query) { GGX ggx; return ggx.template DG1(query); @@ -255,6 +256,7 @@ struct GGX) > return G2_over_G1; } + vector A; scalar_type ax2; scalar_type ay2; scalar_type a2; diff --git a/include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl index 47fcf6f05f..d4118aaec4 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf/microfacet_to_light_transform.hlsl @@ -23,74 +23,127 @@ enum MicrofacetTransformTypes : uint16_t MTT_REFLECT_REFRACT = 0b11 }; -template -struct microfacet_to_light_measure_transform; +template +struct SDualMeasureQuant; template -struct microfacet_to_light_measure_transform +struct SDualMeasureQuant { - using this_t = microfacet_to_light_measure_transform; + using this_t = SDualMeasureQuant; using scalar_type = T; + NBL_CONSTEXPR_STATIC_INLINE MicrofacetTransformTypes Type = MTT_REFLECT; + + scalar_type getMicrofacetMeasure() + { + return pdf; + } + // this computes the max(NdotL,0)/(4*max(NdotV,0)*max(NdotL,0)) factor which transforms PDFs in the f in projected microfacet f * NdotH measure to projected light measure f * NdotL - static scalar_type __call(scalar_type NDFcos, scalar_type maxNdotV) + scalar_type getProjectedLightMeasure() { - return scalar_type(0.25) * NDFcos / maxNdotV; + return scalar_type(0.25) * pdf / maxNdotV; } + + scalar_type pdf; + scalar_type maxNdotV; }; template -struct microfacet_to_light_measure_transform +struct SDualMeasureQuant { - using this_t = microfacet_to_light_measure_transform; + using this_t = SDualMeasureQuant; using scalar_type = T; + NBL_CONSTEXPR_STATIC_INLINE MicrofacetTransformTypes Type = MTT_REFLECT; + + scalar_type getMicrofacetMeasure() + { + return pdf; + } + // this computes the max(NdotL,0)/(4*max(NdotV,0)*max(NdotL,0)) factor which transforms PDFs in the f in projected microfacet f * NdotH measure to projected light measure f * NdotL - static scalar_type __call(scalar_type NDFcos, scalar_type maxNdotL) + scalar_type getProjectedLightMeasure() { - return NDFcos * maxNdotL; + return pdf * maxNdotL; } + + scalar_type pdf; + scalar_type maxNdotL; }; template -struct microfacet_to_light_measure_transform +struct SDualMeasureQuant { - using this_t = microfacet_to_light_measure_transform; + using this_t = SDualMeasureQuant; using scalar_type = T; - static scalar_type __call(scalar_type NDFcos, scalar_type absNdotV, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) + NBL_CONSTEXPR_STATIC_INLINE MicrofacetTransformTypes Type = MTT_REFRACT; + + scalar_type getMicrofacetMeasure() + { + return pdf; + } + + scalar_type getProjectedLightMeasure() { - scalar_type denominator = absNdotV; const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); // VdotHLdotH is negative under transmission, so thats denominator is negative - denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; - return NDFcos * VdotHLdotH / denominator; + scalar_type denominator = absNdotV * (-VdotH_etaLdotH * VdotH_etaLdotH); + return pdf * VdotHLdotH / denominator; } + + scalar_type pdf; + scalar_type absNdotV; + scalar_type VdotH; + scalar_type LdotH; + scalar_type VdotHLdotH; + scalar_type orientedEta; }; template -struct microfacet_to_light_measure_transform +struct SDualMeasureQuant { - using this_t = microfacet_to_light_measure_transform; + using this_t = SDualMeasureQuant; using scalar_type = T; - static scalar_type __call(scalar_type NDFcos, scalar_type absNdotV, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) + NBL_CONSTEXPR_STATIC_INLINE MicrofacetTransformTypes Type = MTT_REFRACT; + + scalar_type getMicrofacetMeasure() + { + return pdf; + } + + scalar_type getProjectedLightMeasure() { - scalar_type denominator = absNdotV; const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); // VdotHLdotH is negative under transmission, so thats denominator is negative - denominator *= -scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); - return NDFcos * denominator; + scalar_type denominator = absNdotL * (-scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH)); + return pdf * denominator; } + + scalar_type pdf; + scalar_type absNdotL; + scalar_type VdotH; + scalar_type LdotH; + scalar_type VdotHLdotH; + scalar_type orientedEta; }; template -struct microfacet_to_light_measure_transform +struct SDualMeasureQuant { - using this_t = microfacet_to_light_measure_transform; + using this_t = SDualMeasureQuant; using scalar_type = T; - static scalar_type __call(scalar_type NDFcos, scalar_type absNdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) + NBL_CONSTEXPR_STATIC_INLINE MicrofacetTransformTypes Type = MTT_REFLECT_REFRACT; + + scalar_type getMicrofacetMeasure() + { + return pdf; + } + + scalar_type getProjectedLightMeasure() { scalar_type denominator = absNdotV; if (transmitted) @@ -99,29 +152,53 @@ struct microfacet_to_light_measure_transform // VdotHLdotH is negative under transmission, so thats denominator is negative denominator *= -VdotH_etaLdotH * VdotH_etaLdotH; } - return NDFcos * (transmitted ? VdotHLdotH : scalar_type(0.25)) / denominator; + return pdf * (transmitted ? VdotHLdotH : scalar_type(0.25)) / denominator; } + + scalar_type pdf; + scalar_type absNdotV; + bool transmitted; + scalar_type VdotH; + scalar_type LdotH; + scalar_type VdotHLdotH; + scalar_type orientedEta; }; template -struct microfacet_to_light_measure_transform +struct SDualMeasureQuant { - using this_t = microfacet_to_light_measure_transform; + using this_t = SDualMeasureQuant; using scalar_type = T; - static scalar_type __call(scalar_type NDFcos, scalar_type absNdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta) + NBL_CONSTEXPR_STATIC_INLINE MicrofacetTransformTypes Type = MTT_REFLECT_REFRACT; + + scalar_type getMicrofacetMeasure() { - scalar_type denominator = absNdotV; + return pdf; + } + + scalar_type getProjectedLightMeasure() + { + scalar_type denominator = absNdotL; if (transmitted) { const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH); // VdotHLdotH is negative under transmission, so thats denominator is negative denominator *= -scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH); } - return NDFcos * denominator; + return pdf * denominator; } + + scalar_type pdf; + scalar_type absNdotL; + bool transmitted; + scalar_type VdotH; + scalar_type LdotH; + scalar_type VdotHLdotH; + scalar_type orientedEta; }; + } } } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 01d22e3165..fe72bc4720 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -8,6 +8,7 @@ #include "nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl" #include "nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl" #include "nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl" +#include "nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl" namespace nbl { @@ -38,6 +39,10 @@ struct SBeckmannIsotropicBxDF NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); + using ndf_type = ndf::Beckmann; + using fresnel_type = fresnel::Conductor; + using measure_transform_type = ndf::SDualMeasureQuant; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_MAX; struct SBeckmannQuery @@ -59,27 +64,26 @@ struct SBeckmannIsotropicBxDF retval.A = A; retval.ior0 = ior0; retval.ior1 = ior1; + + retval.__base.ndf.A = vector2_type(A, A); + retval.__base.ndf.a2 = A*A; + retval.__base.fresnel.eta = ior0; + retval.__base.fresnel.etak2 = ior1*ior1; return retval; } query_type createQuery(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) { query_type query; - ndf::Beckmann beckmann_ndf; - beckmann_ndf.a2 = A*A; + ndf_type beckmann_ndf = __base.getNDF(); query.lambda_L = beckmann_ndf.LambdaC2(_sample.getNdotL2()); query.lambda_V = beckmann_ndf.LambdaC2(interaction.getNdotV2()); return query; } - template - scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) + spectral_type eval(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - scalar_type a2 = A*A; - ndf::Beckmann beckmann_ndf; - beckmann_ndf.a2 = a2; - scalar_type NG = beckmann_ndf.template D(cache); - if (a2 > numeric_limits::min) + if (interaction.getNdotV() > numeric_limits::min) { struct SBeckmannG2overG1Query { @@ -95,19 +99,14 @@ struct SBeckmannIsotropicBxDF SBeckmannG2overG1Query g2_query; g2_query.lambda_L = query.getLambdaL(); g2_query.lambda_V = query.getLambdaV(); - NG *= beckmann_ndf.template correlated(g2_query, _sample, interaction); - } - return NG; - } - spectral_type eval(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) - { - if (interaction.getNdotV() > numeric_limits::min) - { - const scalar_type scalar_part = __eval_DG_wo_clamps(query, _sample, interaction, cache); - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, interaction.getNdotV()); - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); - return f() * microfacet_transform; + measure_transform_type dualMeasure = __base.template __DG(g2_query, _sample, interaction, cache); + // const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, interaction.getNdotV(_clamp)); + dualMeasure.maxNdotV = interaction.getNdotV(_clamp); + scalar_type DG = dualMeasure.getProjectedLightMeasure(); + fresnel_type f = __base.getFresnel(); + f.clampedCosTheta = cache.getVdotH(); + return f() * DG; } else return hlsl::promote(0.0); @@ -135,23 +134,21 @@ struct SBeckmannIsotropicBxDF scalar_type lambda_V; }; - scalar_type a2 = A*A; - ndf::Beckmann beckmann_ndf; - beckmann_ndf.a2 = a2; + ndf_type beckmann_ndf = __base.getNDF(); SBeckmannDG1Query dg1_query; - dg1_query.ndf = beckmann_ndf.template D(cache); + dg1_query.ndf = __base.__D(cache); dg1_query.lambda_V = query.getLambdaV(); - scalar_type dg1 = beckmann_ndf.template DG1(dg1_query); - return ndf::microfacet_to_light_measure_transform::__call(dg1, interaction.getNdotV(_clamp)); + measure_transform_type dualMeasure = __base.template __DG1(dg1_query); + dualMeasure.maxNdotV = interaction.getNdotV(_clamp); + return dualMeasure.getProjectedLightMeasure(); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { scalar_type _pdf = pdf(query, interaction, cache); - ndf::Beckmann beckmann_ndf; spectral_type quo = hlsl::promote(0.0); if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) { @@ -166,12 +163,13 @@ struct SBeckmannIsotropicBxDF scalar_type lambda_V; }; - beckmann_ndf.a2 = A*A; + ndf_type beckmann_ndf = __base.getNDF(); SBeckmannG2overG1Query g2_query; g2_query.lambda_L = query.getLambdaL(); g2_query.lambda_V = query.getLambdaV(); scalar_type G2_over_G1 = beckmann_ndf.template G2_over_G1(g2_query, _sample, interaction, cache); - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); + fresnel_type f = __base.getFresnel(); + f.clampedCosTheta = cache.getVdotH(); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; } @@ -181,6 +179,7 @@ struct SBeckmannIsotropicBxDF scalar_type A; spectral_type ior0, ior1; + SCookTorrance __base; }; template @@ -201,6 +200,10 @@ struct SBeckmannAnisotropicBxDF; + using fresnel_type = fresnel::Conductor; + using measure_transform_type = ndf::SDualMeasureQuant; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_MAX; struct SBeckmannQuery @@ -222,28 +225,27 @@ struct SBeckmannAnisotropicBxDF beckmann_ndf; - beckmann_ndf.ax = A.x; - beckmann_ndf.ay = A.y; + ndf_type beckmann_ndf = __base.getNDF(); query.lambda_L = beckmann_ndf.LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); query.lambda_V = beckmann_ndf.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); return query; } - template - scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) + spectral_type eval(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - ndf::Beckmann beckmann_ndf; - beckmann_ndf.ax = A.x; - beckmann_ndf.ay = A.y; - scalar_type NG = beckmann_ndf.template D(cache); - if (hlsl::any >(A > (vector2_type)numeric_limits::min)) + if (interaction.getNdotV() > numeric_limits::min) { struct SBeckmannG2overG1Query { @@ -259,19 +261,13 @@ struct SBeckmannAnisotropicBxDF(g2_query, _sample, interaction); - } - return NG; - } - spectral_type eval(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - if (interaction.getNdotV() > numeric_limits::min) - { - const scalar_type scalar_part = __eval_DG_wo_clamps(query, _sample, interaction, cache); - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, interaction.getNdotV()); - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); - return f() * microfacet_transform; + measure_transform_type dualMeasure = __base.template __DG(g2_query, _sample, interaction, cache); + dualMeasure.maxNdotV = interaction.getNdotV(_clamp); + scalar_type DG = dualMeasure.getProjectedLightMeasure(); + fresnel_type f = __base.getFresnel(); + f.clampedCosTheta = cache.getVdotH(); + return f() * DG; } else return hlsl::promote(0.0); @@ -371,24 +367,21 @@ struct SBeckmannAnisotropicBxDF beckmann_ndf; - beckmann_ndf.ax = A.x; - beckmann_ndf.ay = A.y; + ndf_type beckmann_ndf = __base.getNDF(); SBeckmannDG1Query dg1_query; - dg1_query.ndf = beckmann_ndf.template D(cache); + dg1_query.ndf = __base.__D(cache); dg1_query.lambda_V = query.getLambdaV(); - scalar_type dg1 = beckmann_ndf.template DG1(dg1_query); - return ndf::microfacet_to_light_measure_transform::__call(dg1, interaction.getNdotV(_clamp)); + measure_transform_type dualMeasure = __base.template __DG1(dg1_query); + dualMeasure.maxNdotV = interaction.getNdotV(_clamp); + return dualMeasure.getProjectedLightMeasure(); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { scalar_type _pdf = pdf(query, interaction, cache); - ndf::Beckmann beckmann_ndf; spectral_type quo = hlsl::promote(0.0); if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) { @@ -403,13 +396,13 @@ struct SBeckmannAnisotropicBxDF(g2_query, _sample, interaction, cache); - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); + fresnel_type f = __base.getFresnel(); + f.clampedCosTheta = cache.getVdotH(); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; } @@ -419,6 +412,7 @@ struct SBeckmannAnisotropicBxDF __base; }; } diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index d63488ea04..6c1a0f9f41 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -8,6 +8,7 @@ #include "nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl" #include "nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl" #include "nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl" +#include "nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl" namespace nbl { @@ -38,6 +39,10 @@ struct SGGXIsotropicBxDF NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); + using ndf_type = ndf::GGX; + using fresnel_type = fresnel::Conductor; + using measure_transform_type = ndf::SDualMeasureQuant; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_MAX; struct SGGXQuery @@ -59,29 +64,27 @@ struct SGGXIsotropicBxDF retval.A = A; retval.ior0 = ior0; retval.ior1 = ior1; + + retval.__base.ndf.A = vector2_type(A, A); + retval.__base.ndf.a2 = A*A; + retval.__base.ndf.one_minus_a2 = scalar_type(1.0) - A*A; + retval.__base.fresnel.eta = ior0; + retval.__base.fresnel.etak2 = ior1*ior1; return retval; } query_type createQuery(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) { query_type query; - ndf::GGX ggx_ndf; - ggx_ndf.a2 = A*A; - ggx_ndf.one_minus_a2 = scalar_type(1.0) - A*A; + ndf_type ggx_ndf = __base.getNDF(); query.devsh_v = ggx_ndf.devsh_part(interaction.getNdotV2()); query.devsh_l = ggx_ndf.devsh_part(_sample.getNdotL2()); return query; } - template - scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache, BxDFClampMode _clamp) + spectral_type eval(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - scalar_type a2 = A*A; - ndf::GGX ggx_ndf; - ggx_ndf.a2 = a2; - ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; - scalar_type NG = ggx_ndf.template D(cache); - if (a2 > numeric_limits::min) + if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) { struct SGGXG2XQuery { @@ -100,19 +103,13 @@ struct SGGXIsotropicBxDF g2_query.devsh_v = query.getDevshV(); g2_query.devsh_l = query.getDevshL(); g2_query._clamp = _clamp; - NG *= ggx_ndf.template correlated(g2_query, _sample, interaction); - } - return NG; - } - spectral_type eval(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) - { - if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) - { - const scalar_type scalar_part = __eval_DG_wo_clamps(query, _sample, interaction, cache, BxDFClampMode::BCM_MAX); - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, _sample.getNdotL(_clamp)); - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); - return f() * microfacet_transform; + measure_transform_type dualMeasure = __base.template __DG(g2_query, _sample, interaction, cache); + dualMeasure.maxNdotL = _sample.getNdotL(_clamp); + scalar_type DG = dualMeasure.getProjectedLightMeasure(); + fresnel_type f = __base.getFresnel(); + f.clampedCosTheta = cache.getVdotH(); + return f() * DG; } else return hlsl::promote(0.0); @@ -141,16 +138,14 @@ struct SGGXIsotropicBxDF }; SGGXDG1Query dg1_query; - const scalar_type a2 = A*A; - ndf::GGX ggx_ndf; - ggx_ndf.a2 = a2; - ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; - dg1_query.ndf = ggx_ndf.template D(cache); + ndf_type ggx_ndf = __base.getNDF(); + dg1_query.ndf = __base.__D(cache); const scalar_type devsh_v = query.getDevshV(); dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(interaction.getNdotV(_clamp), devsh_v); - return ggx_ndf.template DG1(dg1_query); + measure_transform_type dualMeasure = __base.template __DG1(dg1_query); + return dualMeasure.getMicrofacetMeasure(); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) @@ -173,18 +168,16 @@ struct SGGXIsotropicBxDF BxDFClampMode _clamp; }; - const scalar_type a2 = A*A; - ndf::GGX ggx_ndf; - ggx_ndf.a2 = a2; - ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; + ndf_type ggx_ndf = __base.getNDF(); SGGXG2XQuery g2_query; g2_query.devsh_v = query.getDevshV(); g2_query.devsh_l = query.getDevshL(); - g2_query._clamp = BxDFClampMode::BCM_MAX; + g2_query._clamp = _clamp; const scalar_type G2_over_G1 = ggx_ndf.template G2_over_G1(g2_query, _sample, interaction, cache); - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); + fresnel_type f = __base.getFresnel(); + f.clampedCosTheta = cache.getVdotH(); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; } @@ -194,6 +187,7 @@ struct SGGXIsotropicBxDF scalar_type A; spectral_type ior0, ior1; + SCookTorrance __base; }; template @@ -214,6 +208,10 @@ struct SGGXAnisotropicBxDF; + using fresnel_type = fresnel::Conductor; + using measure_transform_type = ndf::SDualMeasureQuant; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_MAX; struct SGGXQuery @@ -235,30 +233,28 @@ struct SGGXAnisotropicBxDF ggx_ndf; - ggx_ndf.ax2 = A.x*A.x; - ggx_ndf.ay2 = A.y*A.y; - ggx_ndf.a2 = A.x*A.y; + ndf_type ggx_ndf = __base.getNDF(); query.devsh_v = ggx_ndf.devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); query.devsh_l = ggx_ndf.devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); return query; } - template - scalar_type __eval_DG_wo_clamps(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache, BxDFClampMode _clamp) + spectral_type eval(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) { - ndf::GGX ggx_ndf; - ggx_ndf.ax2 = A.x*A.x; - ggx_ndf.ay2 = A.y*A.y; - ggx_ndf.a2 = A.x*A.y; - scalar_type NG = ggx_ndf.template D(cache); - if (any >(A > (vector2_type)numeric_limits::min)) + if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) { struct SGGXG2XQuery { @@ -277,19 +273,13 @@ struct SGGXAnisotropicBxDF(g2_query, _sample, interaction); - } - return NG; - } - spectral_type eval(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) - { - if (_sample.getNdotL() > numeric_limits::min && interaction.getNdotV() > numeric_limits::min) - { - const scalar_type scalar_part = __eval_DG_wo_clamps(query, _sample, interaction, cache, BxDFClampMode::BCM_MAX); - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, _sample.getNdotL(_clamp)); - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); - return f() * microfacet_transform; + measure_transform_type dualMeasure = __base.template __DG(g2_query, _sample, interaction, cache); + dualMeasure.maxNdotL = _sample.getNdotL(_clamp); + scalar_type DG = dualMeasure.getProjectedLightMeasure(); + fresnel_type f = __base.getFresnel(); + f.clampedCosTheta = cache.getVdotH(); + return f() * DG; } else return hlsl::promote(0.0); @@ -344,16 +334,14 @@ struct SGGXAnisotropicBxDF ggx_ndf; - ggx_ndf.ax2 = A.x*A.x; - ggx_ndf.ay2 = A.y*A.y; - ggx_ndf.a2 = A.x*A.y; - dg1_query.ndf = ggx_ndf.template D(cache); + ndf_type ggx_ndf = __base.getNDF(); + dg1_query.ndf = __base.__D(cache); const scalar_type devsh_v = query.getDevshV(); dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(interaction.getNdotV(_clamp), devsh_v); - return ggx_ndf.template DG1(dg1_query); + measure_transform_type dualMeasure = __base.template __DG1(dg1_query); + return dualMeasure.getMicrofacetMeasure(); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) @@ -376,10 +364,7 @@ struct SGGXAnisotropicBxDF ggx_ndf; - ggx_ndf.ax2 = A.x*A.x; - ggx_ndf.ay2 = A.y*A.y; - ggx_ndf.a2 = A.x*A.y; + ndf_type ggx_ndf = __base.getNDF(); SGGXG2XQuery g2_query; g2_query.devsh_v = query.getDevshV(); @@ -387,7 +372,8 @@ struct SGGXAnisotropicBxDF(g2_query, _sample, interaction, cache); - fresnel::Conductor f = fresnel::Conductor::create(ior0, ior1, cache.getVdotH()); + fresnel_type f = __base.getFresnel(); + f.clampedCosTheta = cache.getVdotH(); const spectral_type reflectance = f(); quo = reflectance * G2_over_G1; } @@ -397,6 +383,7 @@ struct SGGXAnisotropicBxDF __base; }; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 6a7f09ef49..bf8338ab50 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -8,6 +8,7 @@ #include "nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl" #include "nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl" #include "nbl/builtin/hlsl/bxdf/reflection.hlsl" +#include "nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl" namespace nbl { @@ -41,6 +42,10 @@ struct SBeckmannDielectricIsotropicBxDF NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); using brdf_type = reflection::SBeckmannIsotropicBxDF; + using ndf_type = ndf::Beckmann; + using fresnel_type = fresnel::Dielectric; + using measure_transform_type = ndf::SDualMeasureQuant; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; struct SBeckmannQuery @@ -60,14 +65,16 @@ struct SBeckmannDielectricIsotropicBxDF this_t retval; retval.eta = eta; retval.A = A; + + retval.__base.ndf.A = vector2_type(A, A); + retval.__base.ndf.a2 = A*A; return retval; } query_type createQuery(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) { query_type query; - ndf::Beckmann beckmann_ndf; - beckmann_ndf.a2 = A*A; + ndf_type beckmann_ndf = __base.getNDF(); query.lambda_L = beckmann_ndf.LambdaC2(_sample.getNdotL2()); query.lambda_V = beckmann_ndf.LambdaC2(interaction.getNdotV2()); return query; @@ -78,16 +85,30 @@ struct SBeckmannDielectricIsotropicBxDF fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; - const scalar_type VdotHLdotH = cache.getVdotHLdotH(); - const bool transmitted = cache.isTransmission(); + struct SBeckmannG2overG1Query + { + using scalar_type = scalar_type; - spectral_type dummyior; - brdf_type beckmann = brdf_type::create(A, dummyior, dummyior); - const scalar_type scalar_part = beckmann.template __eval_DG_wo_clamps(query, _sample, interaction, cache); + scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } + scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part,interaction.getNdotV(_clamp),transmitted,cache.getVdotH(),cache.getLdotH(),VdotHLdotH,orientedEta.value[0]); - const scalar_type f = fresnel::Dielectric::__call(orientedEta2, hlsl::abs(cache.getVdotH()))[0]; - return hlsl::promote(f) * microfacet_transform; + scalar_type lambda_L; + scalar_type lambda_V; + }; + + SBeckmannG2overG1Query g2_query; + g2_query.lambda_L = query.getLambdaL(); + g2_query.lambda_V = query.getLambdaV(); + + measure_transform_type dualMeasure = __base.template __DG(g2_query, _sample, interaction, cache); + dualMeasure.absNdotV = interaction.getNdotV(_clamp); + dualMeasure.orientedEta = orientedEta.value[0]; + scalar_type DG = dualMeasure.getProjectedLightMeasure(); + + fresnel_type f = __base.getFresnel(); + f.orientedEta2 = orientedEta2; + f.absCosTheta = hlsl::abs(cache.getVdotH()); + return hlsl::promote(f()[0]) * DG; } sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) @@ -118,15 +139,14 @@ struct SBeckmannDielectricIsotropicBxDF const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; - - const scalar_type a2 = A*A; - ndf::Beckmann beckmann_ndf; - beckmann_ndf.a2 = a2; - dg1_query.ndf = beckmann_ndf.template D(cache); + + dg1_query.ndf = __base.__D(cache); dg1_query.lambda_V = query.getLambdaV(); - scalar_type dg1 = beckmann_ndf.template DG1(dg1_query, cache); - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * ndf::microfacet_to_light_measure_transform::__call(dg1, interaction.getNdotV(_clamp), cache.isTransmission(), cache.getVdotH(), cache.getLdotH(), cache.getVdotHLdotH(), orientedEta.value[0]); + measure_transform_type dualMeasure = __base.template __DG1(dg1_query, cache); + dualMeasure.absNdotV = interaction.getNdotV(_clamp); + dualMeasure.orientedEta = orientedEta.value[0]; + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * dualMeasure.getProjectedLightMeasure(); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) @@ -144,8 +164,7 @@ struct SBeckmannDielectricIsotropicBxDF scalar_type lambda_V; }; - ndf::Beckmann beckmann_ndf; - beckmann_ndf.a2 = A*A; + ndf_type beckmann_ndf = __base.getNDF(); SBeckmannG2overG1Query g2_query; g2_query.lambda_L = query.getLambdaL(); g2_query.lambda_V = query.getLambdaV(); @@ -156,6 +175,7 @@ struct SBeckmannDielectricIsotropicBxDF scalar_type A; scalar_type eta; + SCookTorrance __base; }; template @@ -179,6 +199,10 @@ struct SBeckmannDielectricAnisotropicBxDF; + using ndf_type = ndf::Beckmann; + using fresnel_type = fresnel::Dielectric; + using measure_transform_type = ndf::SDualMeasureQuant; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; struct SBeckmannQuery @@ -198,15 +222,17 @@ struct SBeckmannDielectricAnisotropicBxDF beckmann_ndf; - beckmann_ndf.ax = A.x; - beckmann_ndf.ay = A.y; + ndf_type beckmann_ndf = __base.getNDF(); query.lambda_L = beckmann_ndf.LambdaC2(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); query.lambda_V = beckmann_ndf.LambdaC2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); return query; @@ -217,16 +243,30 @@ struct SBeckmannDielectricAnisotropicBxDF orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; - const scalar_type VdotHLdotH = cache.getVdotHLdotH(); - const bool transmitted = cache.isTransmission(); + struct SBeckmannG2overG1Query + { + using scalar_type = scalar_type; - spectral_type dummyior; - brdf_type beckmann = brdf_type::create(A.x, A.y, dummyior, dummyior); - const scalar_type scalar_part = beckmann.template __eval_DG_wo_clamps(query, _sample, interaction, cache); + scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return lambda_L; } + scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return lambda_V; } + + scalar_type lambda_L; + scalar_type lambda_V; + }; + + SBeckmannG2overG1Query g2_query; + g2_query.lambda_L = query.getLambdaL(); + g2_query.lambda_V = query.getLambdaV(); + + measure_transform_type dualMeasure = __base.template __DG(g2_query, _sample, interaction, cache); + dualMeasure.absNdotV = interaction.getNdotV(_clamp); + dualMeasure.orientedEta = orientedEta.value[0]; + scalar_type DG = dualMeasure.getProjectedLightMeasure(); - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part,interaction.getNdotV(_clamp),transmitted,cache.getVdotH(),cache.getLdotH(),VdotHLdotH,orientedEta.value[0]); - const scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; - return hlsl::promote(f) * microfacet_transform; + fresnel_type f = __base.getFresnel(); + f.orientedEta2 = orientedEta2; + f.absCosTheta = hlsl::abs(cache.getVdotH()); + return hlsl::promote(f()[0]) * DG; } sample_type __generate_wo_clamps(const vector3_type localV, const vector3_type H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(anisocache_type) cache) @@ -292,14 +332,13 @@ struct SBeckmannDielectricAnisotropicBxDF::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; - ndf::Beckmann beckmann_ndf; - beckmann_ndf.ax = A.x; - beckmann_ndf.ay = A.y; - dg1_query.ndf = beckmann_ndf.template D(cache); + dg1_query.ndf = __base.__D(cache); dg1_query.lambda_V = query.getLambdaV(); - scalar_type dg1 = beckmann_ndf.template DG1(dg1_query, cache); - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * ndf::microfacet_to_light_measure_transform::__call(dg1, interaction.getNdotV(_clamp), cache.isTransmission(), cache.getVdotH(), cache.getLdotH(), cache.getVdotHLdotH(), orientedEta.value[0]); + measure_transform_type dualMeasure = __base.template __DG1(dg1_query, cache); + dualMeasure.absNdotV = interaction.getNdotV(_clamp); + dualMeasure.orientedEta = orientedEta.value[0]; + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * dualMeasure.getProjectedLightMeasure(); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) @@ -317,9 +356,7 @@ struct SBeckmannDielectricAnisotropicBxDF beckmann_ndf; - beckmann_ndf.ax = A.x; - beckmann_ndf.ay = A.y; + ndf_type beckmann_ndf = __base.getNDF(); SBeckmannG2overG1Query g2_query; g2_query.lambda_L = query.getLambdaL(); g2_query.lambda_V = query.getLambdaV(); @@ -330,6 +367,7 @@ struct SBeckmannDielectricAnisotropicBxDF __base; }; } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 3cebf965ae..14df4507ba 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -8,6 +8,7 @@ #include "nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl" #include "nbl/builtin/hlsl/sampling/cos_weighted_spheres.hlsl" #include "nbl/builtin/hlsl/bxdf/reflection.hlsl" +#include "nbl/builtin/hlsl/bxdf/cook_torrance_base.hlsl" namespace nbl { @@ -41,6 +42,10 @@ struct SGGXDielectricIsotropicBxDF NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); using brdf_type = reflection::SGGXIsotropicBxDF; + using ndf_type = ndf::GGX; + using fresnel_type = fresnel::Dielectric; + using measure_transform_type = ndf::SDualMeasureQuant; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; struct SGGXQuery @@ -60,15 +65,17 @@ struct SGGXDielectricIsotropicBxDF this_t retval; retval.eta = eta; retval.A = A; + + retval.__base.ndf.A = vector2_type(A, A); + retval.__base.ndf.a2 = A*A; + retval.__base.ndf.one_minus_a2 = scalar_type(1.0) - A*A; return retval; } query_type createQuery(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) { query_type query; - ndf::GGX ggx_ndf; - ggx_ndf.a2 = A*A; - ggx_ndf.one_minus_a2 = scalar_type(1.0) - A*A; + ndf_type ggx_ndf = __base.getNDF(); query.devsh_v = ggx_ndf.devsh_part(interaction.getNdotV2()); query.devsh_l = ggx_ndf.devsh_part(_sample.getNdotL2()); return query; @@ -79,17 +86,33 @@ struct SGGXDielectricIsotropicBxDF fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; - const scalar_type VdotHLdotH = cache.getVdotHLdotH(); - const bool transmitted = cache.isTransmission(); + struct SGGXG2XQuery + { + using scalar_type = scalar_type; - scalar_type NG_already_in_reflective_dL_measure; - spectral_type dummyior; - brdf_type ggx = brdf_type::create(A, dummyior, dummyior); - NG_already_in_reflective_dL_measure = ggx.template __eval_DG_wo_clamps(query, _sample, interaction, cache, _clamp); + scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } + scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } + BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } + + scalar_type devsh_v; + scalar_type devsh_l; + BxDFClampMode _clamp; + }; + + SGGXG2XQuery g2_query; + g2_query.devsh_v = query.getDevshV(); + g2_query.devsh_l = query.getDevshL(); + g2_query._clamp = _clamp; + + measure_transform_type dualMeasure = __base.template __DG(g2_query, _sample, interaction, cache); + dualMeasure.absNdotL = _sample.getNdotL(_clamp); + dualMeasure.orientedEta = orientedEta.value[0]; + scalar_type DG = dualMeasure.getProjectedLightMeasure(); - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(NG_already_in_reflective_dL_measure,_sample.getNdotL(_clamp),transmitted,cache.getVdotH(),cache.getLdotH(),VdotHLdotH,orientedEta.value[0]); - const scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; - return hlsl::promote(f) * microfacet_transform; + fresnel_type f = __base.getFresnel(); + f.orientedEta2 = orientedEta2; + f.absCosTheta = hlsl::abs(cache.getVdotH()); + return hlsl::promote(f()[0]) * DG; } sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) @@ -123,16 +146,12 @@ struct SGGXDielectricIsotropicBxDF const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; - const scalar_type a2 = A*A; - ndf::GGX ggx_ndf; - ggx_ndf.a2 = a2; - ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; - dg1_query.ndf = ggx_ndf.template D(cache); + ndf_type ggx_ndf = __base.getNDF(); + dg1_query.ndf = __base.__D(cache); + dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(interaction.getNdotV(_clamp), query.getDevshV()); - scalar_type devsh_v = query.getDevshV(); - dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(interaction.getNdotV(_clamp), devsh_v); - - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * ggx_ndf.template DG1(dg1_query, cache); + measure_transform_type dualMeasure = __base.template __DG1(dg1_query, cache); + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * dualMeasure.getMicrofacetMeasure(); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) @@ -140,11 +159,6 @@ struct SGGXDielectricIsotropicBxDF scalar_type _pdf = pdf(query, interaction, cache); const bool transmitted = cache.isTransmission(); - const scalar_type a2 = A * A; - ndf::GGX ggx_ndf; - ggx_ndf.a2 = a2; - ggx_ndf.one_minus_a2 = scalar_type(1.0) - a2; - struct SGGXG2XQuery { using scalar_type = scalar_type; @@ -158,6 +172,7 @@ struct SGGXDielectricIsotropicBxDF BxDFClampMode _clamp; }; + ndf_type ggx_ndf = __base.getNDF(); SGGXG2XQuery g2_query; g2_query.devsh_v = query.getDevshV(); g2_query.devsh_l = query.getDevshL(); @@ -171,6 +186,7 @@ struct SGGXDielectricIsotropicBxDF scalar_type A; scalar_type eta; + SCookTorrance __base; }; template @@ -194,6 +210,10 @@ struct SGGXDielectricAnisotropicBxDF; + using ndf_type = ndf::GGX; + using fresnel_type = fresnel::Dielectric; + using measure_transform_type = ndf::SDualMeasureQuant; + NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_ABS; struct SGGXQuery @@ -213,16 +233,18 @@ struct SGGXDielectricAnisotropicBxDF ggx_ndf; - ggx_ndf.ax2 = A.x*A.x; - ggx_ndf.ay2 = A.y*A.y; - ggx_ndf.a2 = A.x*A.y; + ndf_type ggx_ndf = __base.getNDF(); query.devsh_v = ggx_ndf.devsh_part(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()); query.devsh_l = ggx_ndf.devsh_part(_sample.getTdotL2(), _sample.getBdotL2(), _sample.getNdotL2()); return query; @@ -233,17 +255,33 @@ struct SGGXDielectricAnisotropicBxDF orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; - const scalar_type VdotHLdotH = cache.getVdotHLdotH(); - const bool transmitted = cache.isTransmission(); + struct SGGXG2XQuery + { + using scalar_type = scalar_type; - scalar_type NG_already_in_reflective_dL_measure; - spectral_type dummyior; - brdf_type ggx = brdf_type::create(A.x, A.y, dummyior, dummyior); - NG_already_in_reflective_dL_measure = ggx.template __eval_DG_wo_clamps(query, _sample, interaction, cache, _clamp); + scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } + scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } + BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } + + scalar_type devsh_v; + scalar_type devsh_l; + BxDFClampMode _clamp; + }; + + SGGXG2XQuery g2_query; + g2_query.devsh_v = query.getDevshV(); + g2_query.devsh_l = query.getDevshL(); + g2_query._clamp = _clamp; + + measure_transform_type dualMeasure = __base.template __DG(g2_query, _sample, interaction, cache); + dualMeasure.absNdotL = _sample.getNdotL(_clamp); + dualMeasure.orientedEta = orientedEta.value[0]; + scalar_type DG = dualMeasure.getProjectedLightMeasure(); - const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(NG_already_in_reflective_dL_measure,_sample.getNdotL(_clamp),transmitted,cache.getVdotH(),cache.getLdotH(),VdotHLdotH,orientedEta.value[0]); - const scalar_type f = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; - return hlsl::promote(f) * microfacet_transform; + fresnel_type f = __base.getFresnel(); + f.orientedEta2 = orientedEta2; + f.absCosTheta = hlsl::abs(cache.getVdotH()); + return hlsl::promote(f()[0]) * DG; } sample_type __generate_wo_clamps(const vector3_type localV, const vector3_type H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(anisocache_type) cache) @@ -311,16 +349,12 @@ struct SGGXDielectricAnisotropicBxDF::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; - ndf::GGX ggx_ndf; - ggx_ndf.ax2 = A.x*A.x; - ggx_ndf.ay2 = A.y*A.y; - ggx_ndf.a2 = A.x*A.y; - dg1_query.ndf = ggx_ndf.template D(cache); + ndf_type ggx_ndf = __base.getNDF(); + dg1_query.ndf = __base.__D(cache); + dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(interaction.getNdotV(_clamp), query.getDevshV()); - scalar_type devsh_v = query.getDevshV(); - dg1_query.G1_over_2NdotV = ggx_ndf.G1_wo_numerator_devsh_part(interaction.getNdotV(_clamp), devsh_v); - - return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * ggx_ndf.template DG1(dg1_query, cache); + measure_transform_type dualMeasure = __base.template __DG1(dg1_query, cache); + return hlsl::mix(reflectance, scalar_type(1.0) - reflectance, cache.isTransmission()) * dualMeasure.getMicrofacetMeasure(); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_CONST_REF_ARG(anisocache_type) cache) @@ -328,11 +362,6 @@ struct SGGXDielectricAnisotropicBxDF ggx_ndf; - ggx_ndf.ax2 = A.x*A.x; - ggx_ndf.ay2 = A.y*A.y; - ggx_ndf.a2 = A.x*A.y; - struct SGGXG2XQuery { using scalar_type = scalar_type; @@ -346,10 +375,11 @@ struct SGGXDielectricAnisotropicBxDF(g2_query, _sample, interaction, cache); @@ -359,6 +389,7 @@ struct SGGXDielectricAnisotropicBxDF __base; }; } From ee6bb2e231911ab5c952f27b30ad44dd3f36bce3 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 13 Aug 2025 16:31:51 +0700 Subject: [PATCH 179/188] fix ndf concept --- include/nbl/builtin/hlsl/bxdf/ndf.hlsl | 38 ++++++++++++++++++-------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl index 6bfb159914..4de597f59a 100644 --- a/include/nbl/builtin/hlsl/bxdf/ndf.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/ndf.hlsl @@ -5,6 +5,7 @@ #define _NBL_BUILTIN_HLSL_BXDF_NDF_INCLUDED_ #include "nbl/builtin/hlsl/concepts.hlsl" +#include "nbl/builtin/hlsl/bxdf/common.hlsl" namespace nbl { @@ -17,10 +18,23 @@ namespace ndf namespace dummy_impl { -struct DQuery {}; -struct DLightSample {}; -struct DInteraction {}; -struct DMicrofacetCache {}; +using sample_t = SLightSample >; +using interaction_t = surface_interactions::SAnisotropic > >; +using cache_t = SAnisotropicMicrofacetCache >; +struct DQuery // nonsense struct, just put in all the functions to pass the ndf query concepts +{ + using scalar_type = float; + + scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return 0; } + scalar_type getLambdaL() NBL_CONST_MEMBER_FUNC { return 0; } + scalar_type getLambdaV() NBL_CONST_MEMBER_FUNC { return 0; } + + scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return 0; } + scalar_type getOrientedEta() NBL_CONST_MEMBER_FUNC { return 0; } + scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return 0; } + scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return 0; } + BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return BxDFClampMode::BCM_NONE; } +}; } #define NBL_CONCEPT_NAME NDF @@ -28,9 +42,9 @@ struct DMicrofacetCache {}; #define NBL_CONCEPT_TPLT_PRM_NAMES (T) #define NBL_CONCEPT_PARAM_0 (ndf, T) #define NBL_CONCEPT_PARAM_1 (query, dummy_impl::DQuery) -#define NBL_CONCEPT_PARAM_2 (_sample, dummy_impl::DLightSample) -#define NBL_CONCEPT_PARAM_3 (interaction, dummy_impl::DInteraction) -#define NBL_CONCEPT_PARAM_4 (cache, dummy_impl::DMicrofacetCache) +#define NBL_CONCEPT_PARAM_2 (_sample, dummy_impl::sample_t) +#define NBL_CONCEPT_PARAM_3 (interaction, dummy_impl::interaction_t) +#define NBL_CONCEPT_PARAM_4 (cache, dummy_impl::cache_t) NBL_CONCEPT_BEGIN(5) #define ndf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 @@ -39,11 +53,11 @@ NBL_CONCEPT_BEGIN(5) #define cache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) - // ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template D(cache)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - // ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template DG1(query)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - // ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template DG1(query, cache)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - // ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template correlated(query, _sample, interaction)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) - // ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template G2_over_G1(query, _sample, interaction, cache)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template D(cache)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template DG1(query)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template DG1(query, cache)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template correlated(query, _sample, interaction)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template G2_over_G1(query, _sample, interaction, cache)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) ); #undef cache #undef interaction From 6705999dc11dcc7e640ef35d84f4a1296ab70f87 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 14 Aug 2025 12:53:23 +0700 Subject: [PATCH 180/188] removed redundant A in bxdfs, moved into ndfs --- include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl | 8 ++------ include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 7 ++----- include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl | 8 ++------ include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl | 8 ++------ 4 files changed, 8 insertions(+), 23 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index fe72bc4720..17d7d90bbe 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -61,7 +61,6 @@ struct SBeckmannIsotropicBxDF static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) { this_t retval; - retval.A = A; retval.ior0 = ior0; retval.ior1 = ior1; @@ -101,7 +100,6 @@ struct SBeckmannIsotropicBxDF g2_query.lambda_V = query.getLambdaV(); measure_transform_type dualMeasure = __base.template __DG(g2_query, _sample, interaction, cache); - // const scalar_type microfacet_transform = ndf::microfacet_to_light_measure_transform::__call(scalar_part, interaction.getNdotV(_clamp)); dualMeasure.maxNdotV = interaction.getNdotV(_clamp); scalar_type DG = dualMeasure.getProjectedLightMeasure(); fresnel_type f = __base.getFresnel(); @@ -114,7 +112,7 @@ struct SBeckmannIsotropicBxDF sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache) { - SBeckmannAnisotropicBxDF beckmann_aniso = SBeckmannAnisotropicBxDF::create(A, A, ior0, ior1); + SBeckmannAnisotropicBxDF beckmann_aniso = SBeckmannAnisotropicBxDF::create(__base.ndf.A.x, __base.ndf.A.y, ior0, ior1); anisocache_type anisocache; sample_type s = beckmann_aniso.generate(anisotropic_interaction_type::create(interaction), u, anisocache); cache = anisocache.iso_cache; @@ -177,7 +175,6 @@ struct SBeckmannIsotropicBxDF return quotient_pdf_type::create(quo, _pdf); } - scalar_type A; spectral_type ior0, ior1; SCookTorrance __base; }; @@ -222,7 +219,6 @@ struct SBeckmannAnisotropicBxDF(vector3_type(A.x * localV.x, A.y * localV.y, localV.z)); @@ -410,7 +407,6 @@ struct SBeckmannAnisotropicBxDF __base; }; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 6c1a0f9f41..12465f610c 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -61,7 +61,6 @@ struct SGGXIsotropicBxDF static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) { this_t retval; - retval.A = A; retval.ior0 = ior0; retval.ior1 = ior1; @@ -117,7 +116,7 @@ struct SGGXIsotropicBxDF sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache) { - SGGXAnisotropicBxDF ggx_aniso = SGGXAnisotropicBxDF::create(A, A, ior0, ior1); + SGGXAnisotropicBxDF ggx_aniso = SGGXAnisotropicBxDF::create(__base.ndf.A.x, __base.ndf.A.y, ior0, ior1); anisocache_type anisocache; sample_type s = ggx_aniso.generate(anisotropic_interaction_type::create(interaction), u, anisocache); cache = anisocache.iso_cache; @@ -185,7 +184,6 @@ struct SGGXIsotropicBxDF return quotient_pdf_type::create(quo, _pdf); } - scalar_type A; spectral_type ior0, ior1; SCookTorrance __base; }; @@ -230,7 +228,6 @@ struct SGGXAnisotropicBxDF(vector3_type(A.x*localV.x, A.y*localV.y, localV.z));//stretch view vector so that we're sampling as if roughness=1.0 scalar_type lensq = V.x*V.x + V.y*V.y; @@ -381,7 +379,6 @@ struct SGGXAnisotropicBxDF __base; }; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index bf8338ab50..23158f9888 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -64,7 +64,6 @@ struct SBeckmannDielectricIsotropicBxDF { this_t retval; retval.eta = eta; - retval.A = A; retval.__base.ndf.A = vector2_type(A, A); retval.__base.ndf.a2 = A*A; @@ -113,7 +112,7 @@ struct SBeckmannDielectricIsotropicBxDF sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) { - SBeckmannDielectricAnisotropicBxDF beckmann_aniso = SBeckmannDielectricAnisotropicBxDF::create(eta, A, A); + SBeckmannDielectricAnisotropicBxDF beckmann_aniso = SBeckmannDielectricAnisotropicBxDF::create(eta, __base.ndf.A.x, __base.ndf.A.y); anisocache_type anisocache; sample_type s = beckmann_aniso.generate(anisotropic_interaction_type::create(interaction), u, anisocache); cache = anisocache.iso_cache; @@ -173,7 +172,6 @@ struct SBeckmannDielectricIsotropicBxDF return quotient_pdf_type::create(quo, _pdf); } - scalar_type A; scalar_type eta; SCookTorrance __base; }; @@ -221,7 +219,6 @@ struct SBeckmannDielectricAnisotropicBxDF __base; }; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index 14df4507ba..d5380dc618 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -64,7 +64,6 @@ struct SGGXDielectricIsotropicBxDF { this_t retval; retval.eta = eta; - retval.A = A; retval.__base.ndf.A = vector2_type(A, A); retval.__base.ndf.a2 = A*A; @@ -117,7 +116,7 @@ struct SGGXDielectricIsotropicBxDF sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) { - SGGXDielectricAnisotropicBxDF ggx_aniso = SGGXDielectricAnisotropicBxDF::create(eta, A, A); + SGGXDielectricAnisotropicBxDF ggx_aniso = SGGXDielectricAnisotropicBxDF::create(eta, __base.ndf.A.x, __base.ndf.A.y); anisocache_type anisocache; sample_type s = ggx_aniso.generate(anisotropic_interaction_type::create(interaction), u, anisocache); cache = anisocache.iso_cache; @@ -184,7 +183,6 @@ struct SGGXDielectricIsotropicBxDF return quotient_pdf_type::create(quo, _pdf); } - scalar_type A; scalar_type eta; SCookTorrance __base; }; @@ -232,7 +230,6 @@ struct SGGXDielectricAnisotropicBxDF __base; }; From e36819f2901acc145b9e9cfb48a6ad11d7f78892 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 14 Aug 2025 16:46:38 +0700 Subject: [PATCH 181/188] removed redundant eta, ior in bxdfs; moved into fresnel structs --- include/nbl/builtin/hlsl/bxdf/fresnel.hlsl | 18 +++--- .../hlsl/bxdf/reflection/beckmann.hlsl | 12 +--- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 12 +--- .../hlsl/bxdf/transmission/beckmann.hlsl | 58 ++++++++----------- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 50 +++++++--------- 5 files changed, 62 insertions(+), 88 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl index bf530320be..5711ab428e 100644 --- a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl @@ -340,6 +340,7 @@ struct Conductor { Conductor retval; retval.eta = eta; + retval.etak = etak; retval.etak2 = etak*etak; retval.clampedCosTheta = clampedCosTheta; return retval; @@ -349,6 +350,7 @@ struct Conductor { Conductor retval; retval.eta = eta.real(); + retval.etak = eta.imag(); retval.etak2 = eta.imag()*eta.imag(); retval.clampedCosTheta = clampedCosTheta; return retval; @@ -373,6 +375,7 @@ struct Conductor } T eta; + T etak; T etak2; scalar_type clampedCosTheta; }; @@ -387,8 +390,7 @@ struct Dielectric { Dielectric retval; scalar_type absCosTheta = hlsl::abs(cosTheta); - OrientedEtas orientedEta = OrientedEtas::create(absCosTheta, eta); - retval.orientedEta2 = orientedEta.value * orientedEta.value; + retval.orientedEta = OrientedEtas::create(absCosTheta, eta); retval.absCosTheta = absCosTheta; return retval; } @@ -409,10 +411,10 @@ struct Dielectric T operator()() { - return __call(orientedEta2, absCosTheta); + return __call(orientedEta.value * orientedEta.value, absCosTheta); } - T orientedEta2; + OrientedEtas orientedEta; scalar_type absCosTheta; }; @@ -422,20 +424,20 @@ struct DielectricFrontFaceOnly using scalar_type = typename vector_traits::scalar_type; using vector_type = T; - static DielectricFrontFaceOnly create(NBL_CONST_REF_ARG(T) orientedEta2, scalar_type absCosTheta) + static DielectricFrontFaceOnly create(NBL_CONST_REF_ARG(T) eta, scalar_type absCosTheta) { Dielectric retval; - retval.orientedEta2 = orientedEta2; + retval.orientedEta = OrientedEtas::create(absCosTheta, eta); retval.absCosTheta = hlsl::abs(absCosTheta); return retval; } T operator()() { - return Dielectric::__call(orientedEta2, absCosTheta); + return Dielectric::__call(orientedEta.value * orientedEta.value, absCosTheta); } - T orientedEta2; + OrientedEtas orientedEta; scalar_type absCosTheta; }; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 17d7d90bbe..18abadc599 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -61,12 +61,10 @@ struct SBeckmannIsotropicBxDF static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) { this_t retval; - retval.ior0 = ior0; - retval.ior1 = ior1; - retval.__base.ndf.A = vector2_type(A, A); retval.__base.ndf.a2 = A*A; retval.__base.fresnel.eta = ior0; + retval.__base.fresnel.etak = ior1; retval.__base.fresnel.etak2 = ior1*ior1; return retval; } @@ -112,7 +110,7 @@ struct SBeckmannIsotropicBxDF sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache) { - SBeckmannAnisotropicBxDF beckmann_aniso = SBeckmannAnisotropicBxDF::create(__base.ndf.A.x, __base.ndf.A.y, ior0, ior1); + SBeckmannAnisotropicBxDF beckmann_aniso = SBeckmannAnisotropicBxDF::create(__base.ndf.A.x, __base.ndf.A.y, __base.fresnel.eta, __base.fresnel.etak); anisocache_type anisocache; sample_type s = beckmann_aniso.generate(anisotropic_interaction_type::create(interaction), u, anisocache); cache = anisocache.iso_cache; @@ -175,7 +173,6 @@ struct SBeckmannIsotropicBxDF return quotient_pdf_type::create(quo, _pdf); } - spectral_type ior0, ior1; SCookTorrance __base; }; @@ -219,13 +216,11 @@ struct SBeckmannAnisotropicBxDF __base; }; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 12465f610c..6d7599be82 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -61,13 +61,11 @@ struct SGGXIsotropicBxDF static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) { this_t retval; - retval.ior0 = ior0; - retval.ior1 = ior1; - retval.__base.ndf.A = vector2_type(A, A); retval.__base.ndf.a2 = A*A; retval.__base.ndf.one_minus_a2 = scalar_type(1.0) - A*A; retval.__base.fresnel.eta = ior0; + retval.__base.fresnel.etak = ior1; retval.__base.fresnel.etak2 = ior1*ior1; return retval; } @@ -116,7 +114,7 @@ struct SGGXIsotropicBxDF sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache) { - SGGXAnisotropicBxDF ggx_aniso = SGGXAnisotropicBxDF::create(__base.ndf.A.x, __base.ndf.A.y, ior0, ior1); + SGGXAnisotropicBxDF ggx_aniso = SGGXAnisotropicBxDF::create(__base.ndf.A.x, __base.ndf.A.y, __base.fresnel.eta, __base.fresnel.etak); anisocache_type anisocache; sample_type s = ggx_aniso.generate(anisotropic_interaction_type::create(interaction), u, anisocache); cache = anisocache.iso_cache; @@ -184,7 +182,6 @@ struct SGGXIsotropicBxDF return quotient_pdf_type::create(quo, _pdf); } - spectral_type ior0, ior1; SCookTorrance __base; }; @@ -228,14 +225,12 @@ struct SGGXAnisotropicBxDF __base; }; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 23158f9888..58c1576911 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -60,13 +60,12 @@ struct SBeckmannDielectricIsotropicBxDF }; using query_type = SBeckmannQuery; - static this_t create(scalar_type eta, scalar_type A) + static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type A) { this_t retval; - retval.eta = eta; - retval.__base.ndf.A = vector2_type(A, A); retval.__base.ndf.a2 = A*A; + retval.__base.fresnel.orientedEta = orientedEta; return retval; } @@ -81,9 +80,6 @@ struct SBeckmannDielectricIsotropicBxDF spectral_type eval(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); - const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; - struct SBeckmannG2overG1Query { using scalar_type = scalar_type; @@ -99,20 +95,20 @@ struct SBeckmannDielectricIsotropicBxDF g2_query.lambda_L = query.getLambdaL(); g2_query.lambda_V = query.getLambdaV(); + fresnel::OrientedEtas orientedEta = __base.fresnel.orientedEta; measure_transform_type dualMeasure = __base.template __DG(g2_query, _sample, interaction, cache); dualMeasure.absNdotV = interaction.getNdotV(_clamp); dualMeasure.orientedEta = orientedEta.value[0]; scalar_type DG = dualMeasure.getProjectedLightMeasure(); fresnel_type f = __base.getFresnel(); - f.orientedEta2 = orientedEta2; f.absCosTheta = hlsl::abs(cache.getVdotH()); return hlsl::promote(f()[0]) * DG; } sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) { - SBeckmannDielectricAnisotropicBxDF beckmann_aniso = SBeckmannDielectricAnisotropicBxDF::create(eta, __base.ndf.A.x, __base.ndf.A.y); + SBeckmannDielectricAnisotropicBxDF beckmann_aniso = SBeckmannDielectricAnisotropicBxDF::create(__base.fresnel.orientedEta, __base.ndf.A.x, __base.ndf.A.y); anisocache_type anisocache; sample_type s = beckmann_aniso.generate(anisotropic_interaction_type::create(interaction), u, anisocache); cache = anisocache.iso_cache; @@ -132,16 +128,15 @@ struct SBeckmannDielectricIsotropicBxDF scalar_type lambda_V; }; - SBeckmannDG1Query dg1_query; - - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); - const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; - - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; + fresnel_type f = __base.getFresnel(); + f.absCosTheta = hlsl::abs(cache.getVdotH()); + const scalar_type reflectance = f()[0]; + SBeckmannDG1Query dg1_query; dg1_query.ndf = __base.__D(cache); dg1_query.lambda_V = query.getLambdaV(); + fresnel::OrientedEtas orientedEta = __base.fresnel.orientedEta; measure_transform_type dualMeasure = __base.template __DG1(dg1_query, cache); dualMeasure.absNdotV = interaction.getNdotV(_clamp); dualMeasure.orientedEta = orientedEta.value[0]; @@ -172,7 +167,6 @@ struct SBeckmannDielectricIsotropicBxDF return quotient_pdf_type::create(quo, _pdf); } - scalar_type eta; SCookTorrance __base; }; @@ -215,14 +209,13 @@ struct SBeckmannDielectricAnisotropicBxDF) orientedEta, scalar_type ax, scalar_type ay) { this_t retval; - retval.eta = eta; - retval.__base.ndf.A = vector2_type(ax, ay); retval.__base.ndf.ax2 = ax*ax; retval.__base.ndf.ay2 = ay*ay; + retval.__base.fresnel.orientedEta = orientedEta; return retval; } @@ -237,9 +230,6 @@ struct SBeckmannDielectricAnisotropicBxDF orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); - const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; - struct SBeckmannG2overG1Query { using scalar_type = scalar_type; @@ -255,21 +245,23 @@ struct SBeckmannDielectricAnisotropicBxDF orientedEta = __base.fresnel.orientedEta; measure_transform_type dualMeasure = __base.template __DG(g2_query, _sample, interaction, cache); dualMeasure.absNdotV = interaction.getNdotV(_clamp); dualMeasure.orientedEta = orientedEta.value[0]; scalar_type DG = dualMeasure.getProjectedLightMeasure(); fresnel_type f = __base.getFresnel(); - f.orientedEta2 = orientedEta2; f.absCosTheta = hlsl::abs(cache.getVdotH()); return hlsl::promote(f()[0]) * DG; } - sample_type __generate_wo_clamps(const vector3_type localV, const vector3_type H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(anisocache_type) cache) + sample_type __generate_wo_clamps(const vector3_type localV, const vector3_type H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(anisocache_type) cache) { const scalar_type localVdotH = nbl::hlsl::dot(localV,H); - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta.value * orientedEta.value,nbl::hlsl::abs(localVdotH))[0]; + fresnel_type f = __base.getFresnel(); + f.absCosTheta = hlsl::abs(localVdotH); + const scalar_type reflectance = f()[0]; scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); @@ -291,8 +283,8 @@ struct SBeckmannDielectricAnisotropicBxDF orientedEta = fresnel::OrientedEtas::create(interaction.getNdotV(), hlsl::promote(eta)); - fresnel::OrientedEtaRcps rcpEta = fresnel::OrientedEtaRcps::create(interaction.getNdotV(), hlsl::promote(eta)); + fresnel::OrientedEtas orientedEta = __base.fresnel.orientedEta; + fresnel::OrientedEtaRcps rcpEta = orientedEta.getReciprocals(); const vector3_type upperHemisphereV = hlsl::mix(localV, -localV, interaction.getNdotV() < scalar_type(0.0)); @@ -300,7 +292,7 @@ struct SBeckmannDielectricAnisotropicBxDF orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); - const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; - - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; + fresnel_type f = __base.getFresnel(); + f.absCosTheta = hlsl::abs(cache.getVdotH()); + const scalar_type reflectance = f()[0]; + SBeckmannDG1Query dg1_query; dg1_query.ndf = __base.__D(cache); dg1_query.lambda_V = query.getLambdaV(); + fresnel::OrientedEtas orientedEta = __base.fresnel.orientedEta; measure_transform_type dualMeasure = __base.template __DG1(dg1_query, cache); dualMeasure.absNdotV = interaction.getNdotV(_clamp); dualMeasure.orientedEta = orientedEta.value[0]; @@ -362,7 +353,6 @@ struct SBeckmannDielectricAnisotropicBxDF __base; }; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index d5380dc618..b979984086 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -60,14 +60,13 @@ struct SGGXDielectricIsotropicBxDF }; using query_type = SGGXQuery; - static this_t create(scalar_type eta, scalar_type A) + static this_t create(NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, scalar_type A) { this_t retval; - retval.eta = eta; - retval.__base.ndf.A = vector2_type(A, A); retval.__base.ndf.a2 = A*A; retval.__base.ndf.one_minus_a2 = scalar_type(1.0) - A*A; + retval.__base.fresnel.orientedEta = orientedEta; return retval; } @@ -82,9 +81,6 @@ struct SGGXDielectricIsotropicBxDF spectral_type eval(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); - const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; - struct SGGXG2XQuery { using scalar_type = scalar_type; @@ -103,20 +99,20 @@ struct SGGXDielectricIsotropicBxDF g2_query.devsh_l = query.getDevshL(); g2_query._clamp = _clamp; + fresnel::OrientedEtas orientedEta = __base.fresnel.orientedEta; measure_transform_type dualMeasure = __base.template __DG(g2_query, _sample, interaction, cache); dualMeasure.absNdotL = _sample.getNdotL(_clamp); dualMeasure.orientedEta = orientedEta.value[0]; scalar_type DG = dualMeasure.getProjectedLightMeasure(); fresnel_type f = __base.getFresnel(); - f.orientedEta2 = orientedEta2; f.absCosTheta = hlsl::abs(cache.getVdotH()); return hlsl::promote(f()[0]) * DG; } sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) { - SGGXDielectricAnisotropicBxDF ggx_aniso = SGGXDielectricAnisotropicBxDF::create(eta, __base.ndf.A.x, __base.ndf.A.y); + SGGXDielectricAnisotropicBxDF ggx_aniso = SGGXDielectricAnisotropicBxDF::create(__base.fresnel.orientedEta, __base.ndf.A.x, __base.ndf.A.y); anisocache_type anisocache; sample_type s = ggx_aniso.generate(anisotropic_interaction_type::create(interaction), u, anisocache); cache = anisocache.iso_cache; @@ -139,11 +135,12 @@ struct SGGXDielectricIsotropicBxDF }; SGGXDG1Query dg1_query; - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); - const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; + fresnel::OrientedEtas orientedEta = __base.fresnel.orientedEta; dg1_query.orientedEta = orientedEta.value[0]; - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; + fresnel_type f = __base.getFresnel(); + f.absCosTheta = hlsl::abs(cache.getVdotH()); + const scalar_type reflectance = f()[0]; ndf_type ggx_ndf = __base.getNDF(); dg1_query.ndf = __base.__D(cache); @@ -183,7 +180,6 @@ struct SGGXDielectricIsotropicBxDF return quotient_pdf_type::create(quo, _pdf); } - scalar_type eta; SCookTorrance __base; }; @@ -226,15 +222,14 @@ struct SGGXDielectricAnisotropicBxDF) orientedEta, scalar_type ax, scalar_type ay) { this_t retval; - retval.eta = eta; - retval.__base.ndf.A = vector2_type(ax, ay); retval.__base.ndf.ax2 = ax*ax; retval.__base.ndf.ay2 = ay*ay; retval.__base.ndf.a2 = ax*ay; + retval.__base.fresnel.orientedEta = orientedEta; return retval; } @@ -249,9 +244,6 @@ struct SGGXDielectricAnisotropicBxDF orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); - const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; - struct SGGXG2XQuery { using scalar_type = scalar_type; @@ -270,21 +262,23 @@ struct SGGXDielectricAnisotropicBxDF orientedEta = __base.fresnel.orientedEta; measure_transform_type dualMeasure = __base.template __DG(g2_query, _sample, interaction, cache); dualMeasure.absNdotL = _sample.getNdotL(_clamp); dualMeasure.orientedEta = orientedEta.value[0]; scalar_type DG = dualMeasure.getProjectedLightMeasure(); fresnel_type f = __base.getFresnel(); - f.orientedEta2 = orientedEta2; f.absCosTheta = hlsl::abs(cache.getVdotH()); return hlsl::promote(f()[0]) * DG; } - sample_type __generate_wo_clamps(const vector3_type localV, const vector3_type H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(anisocache_type) cache) + sample_type __generate_wo_clamps(const vector3_type localV, const vector3_type H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(anisocache_type) cache) { const scalar_type localVdotH = nbl::hlsl::dot(localV,H); - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta.value * orientedEta.value,nbl::hlsl::abs(localVdotH))[0]; + fresnel_type f = __base.getFresnel(); + f.absCosTheta = hlsl::abs(localVdotH); + const scalar_type reflectance = f()[0]; scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); @@ -306,8 +300,8 @@ struct SGGXDielectricAnisotropicBxDF orientedEta = fresnel::OrientedEtas::create(interaction.getNdotV(), hlsl::promote(eta)); - fresnel::OrientedEtaRcps rcpEta = fresnel::OrientedEtaRcps::create(interaction.getNdotV(), hlsl::promote(eta)); + fresnel::OrientedEtas orientedEta = __base.fresnel.orientedEta; + fresnel::OrientedEtaRcps rcpEta = orientedEta.getReciprocals(); const vector3_type upperHemisphereV = hlsl::mix(localV, -localV, interaction.getNdotV() < scalar_type(0.0)); @@ -315,7 +309,7 @@ struct SGGXDielectricAnisotropicBxDF orientedEta = fresnel::OrientedEtas::create(cache.getVdotH(), hlsl::promote(eta)); - const monochrome_type orientedEta2 = orientedEta.value * orientedEta.value; + fresnel::OrientedEtas orientedEta = __base.fresnel.orientedEta; dg1_query.orientedEta = orientedEta.value[0]; - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta2, nbl::hlsl::abs(cache.getVdotH()))[0]; + fresnel_type f = __base.getFresnel(); + f.absCosTheta = hlsl::abs(cache.getVdotH()); + const scalar_type reflectance = f()[0]; ndf_type ggx_ndf = __base.getNDF(); dg1_query.ndf = __base.__D(cache); @@ -384,7 +379,6 @@ struct SGGXDielectricAnisotropicBxDF __base; }; From 4418b84f4d1da336541c0b3025db1a0c7f07de56 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 14 Aug 2025 16:48:01 +0700 Subject: [PATCH 182/188] latest example --- examples_tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples_tests b/examples_tests index bdca73d8a0..2a893f6b68 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit bdca73d8a08e3642e4a7e5949cab7599f59ee8b8 +Subproject commit 2a893f6b686b309071d3e594cb00571cc2b59acc From fc894f5b1f82c4375026534fdf1a2caac466af30 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 15 Aug 2025 11:49:07 +0700 Subject: [PATCH 183/188] added creation params for bxdfs --- .../hlsl/bxdf/reflection/beckmann.hlsl | 27 +++++++++++++++++-- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 27 +++++++++++++++++-- .../hlsl/bxdf/reflection/lambertian.hlsl | 7 +++++ .../hlsl/bxdf/reflection/oren_nayar.hlsl | 10 +++++++ .../hlsl/bxdf/transmission/beckmann.hlsl | 23 ++++++++++++++++ .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 23 ++++++++++++++++ .../hlsl/bxdf/transmission/lambertian.hlsl | 7 +++++ .../bxdf/transmission/smooth_dielectric.hlsl | 21 +++++++++++++++ 8 files changed, 141 insertions(+), 4 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 18abadc599..3df0f7adbe 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -45,6 +45,14 @@ struct SBeckmannIsotropicBxDF NBL_CONSTEXPR_STATIC_INLINE BxDFClampMode _clamp = BxDFClampMode::BCM_MAX; + struct SCreationParams + { + scalar_type A; + spectral_type ior0; + spectral_type ior1; + }; + using creation_type = SCreationParams; + struct SBeckmannQuery { using scalar_type = scalar_type; @@ -57,7 +65,6 @@ struct SBeckmannIsotropicBxDF }; using query_type = SBeckmannQuery; - // iso static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) { this_t retval; @@ -68,6 +75,10 @@ struct SBeckmannIsotropicBxDF retval.__base.fresnel.etak2 = ior1*ior1; return retval; } + static this_t create(NBL_CONST_REF_ARG(creation_type) params) + { + return create(params.A, params.ior0, params.ior1); + } query_type createQuery(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) { @@ -200,6 +211,15 @@ struct SBeckmannAnisotropicBxDF orientedEta; + }; + using creation_type = SCreationParams; + struct SBeckmannQuery { using scalar_type = scalar_type; @@ -68,6 +75,10 @@ struct SBeckmannDielectricIsotropicBxDF retval.__base.fresnel.orientedEta = orientedEta; return retval; } + static this_t create(NBL_CONST_REF_ARG(creation_type) params) + { + return create(params.orientedEta, params.A); + } query_type createQuery(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) { @@ -197,6 +208,14 @@ struct SBeckmannDielectricAnisotropicBxDF orientedEta; + }; + using creation_type = SCreationParams; + struct SBeckmannQuery { using scalar_type = scalar_type; @@ -218,6 +237,10 @@ struct SBeckmannDielectricAnisotropicBxDF orientedEta; + }; + using creation_type = SCreationParams; + struct SGGXQuery { using scalar_type = scalar_type; @@ -69,6 +76,10 @@ struct SGGXDielectricIsotropicBxDF retval.__base.fresnel.orientedEta = orientedEta; return retval; } + static this_t create(NBL_CONST_REF_ARG(creation_type) params) + { + return create(params.orientedEta, params.A); + } query_type createQuery(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) { @@ -210,6 +221,14 @@ struct SGGXDielectricAnisotropicBxDF orientedEta; + }; + using creation_type = SCreationParams; + struct SGGXQuery { using scalar_type = scalar_type; @@ -232,6 +251,10 @@ struct SGGXDielectricAnisotropicBxDF Date: Fri, 15 Aug 2025 12:00:43 +0700 Subject: [PATCH 184/188] removed BxDF suffix for bxdf names because it's redundant --- examples_tests | 2 +- .../hlsl/bxdf/reflection/beckmann.hlsl | 16 +++++++-------- .../nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl | 16 +++++++-------- .../hlsl/bxdf/reflection/lambertian.hlsl | 6 +++--- .../hlsl/bxdf/reflection/oren_nayar.hlsl | 6 +++--- .../hlsl/bxdf/transmission/beckmann.hlsl | 20 +++++++++---------- .../builtin/hlsl/bxdf/transmission/ggx.hlsl | 20 +++++++++---------- .../hlsl/bxdf/transmission/lambertian.hlsl | 6 +++--- .../bxdf/transmission/smooth_dielectric.hlsl | 12 +++++------ 9 files changed, 52 insertions(+), 52 deletions(-) diff --git a/examples_tests b/examples_tests index ec19f5df12..90b8a929f5 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit ec19f5df1268ae9e00333a6d930dee21c5579377 +Subproject commit 90b8a929f5a276af0d9a4708b0ec4c2172f7057d diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl index 3df0f7adbe..d2bf45cfd3 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl @@ -20,12 +20,12 @@ namespace reflection { template -struct SBeckmannAnisotropicBxDF; +struct SBeckmannAnisotropic; template) -struct SBeckmannIsotropicBxDF +struct SBeckmannIsotropic { - using this_t = SBeckmannIsotropicBxDF; + using this_t = SBeckmannIsotropic; NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); NBL_BXDF_CONFIG_ALIAS(vector3_type, Config); @@ -121,7 +121,7 @@ struct SBeckmannIsotropicBxDF sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache) { - SBeckmannAnisotropicBxDF beckmann_aniso = SBeckmannAnisotropicBxDF::create(__base.ndf.A.x, __base.ndf.A.y, __base.fresnel.eta, __base.fresnel.etak); + SBeckmannAnisotropic beckmann_aniso = SBeckmannAnisotropic::create(__base.ndf.A.x, __base.ndf.A.y, __base.fresnel.eta, __base.fresnel.etak); anisocache_type anisocache; sample_type s = beckmann_aniso.generate(anisotropic_interaction_type::create(interaction), u, anisocache); cache = anisocache.iso_cache; @@ -189,9 +189,9 @@ struct SBeckmannIsotropicBxDF template NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration) -struct SBeckmannAnisotropicBxDF) > +struct SBeckmannAnisotropic) > { - using this_t = SBeckmannAnisotropicBxDF; + using this_t = SBeckmannAnisotropic; NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); NBL_BXDF_CONFIG_ALIAS(vector3_type, Config); @@ -431,7 +431,7 @@ struct SBeckmannAnisotropicBxDF -struct traits > +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; @@ -439,7 +439,7 @@ struct traits > }; template -struct traits > +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl index 5c64fa1752..9062e595a3 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/ggx.hlsl @@ -20,12 +20,12 @@ namespace reflection { template -struct SGGXAnisotropicBxDF; +struct SGGXAnisotropic; template) -struct SGGXIsotropicBxDF +struct SGGXIsotropic { - using this_t = SGGXIsotropicBxDF; + using this_t = SGGXIsotropic; NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); NBL_BXDF_CONFIG_ALIAS(vector3_type, Config); @@ -125,7 +125,7 @@ struct SGGXIsotropicBxDF sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache) { - SGGXAnisotropicBxDF ggx_aniso = SGGXAnisotropicBxDF::create(__base.ndf.A.x, __base.ndf.A.y, __base.fresnel.eta, __base.fresnel.etak); + SGGXAnisotropic ggx_aniso = SGGXAnisotropic::create(__base.ndf.A.x, __base.ndf.A.y, __base.fresnel.eta, __base.fresnel.etak); anisocache_type anisocache; sample_type s = ggx_aniso.generate(anisotropic_interaction_type::create(interaction), u, anisocache); cache = anisocache.iso_cache; @@ -198,9 +198,9 @@ struct SGGXIsotropicBxDF template NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration) -struct SGGXAnisotropicBxDF) > +struct SGGXAnisotropic) > { - using this_t = SGGXAnisotropicBxDF; + using this_t = SGGXAnisotropic; NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); NBL_BXDF_CONFIG_ALIAS(vector3_type, Config); @@ -403,7 +403,7 @@ struct SGGXAnisotropicBxDF -struct traits > +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; @@ -411,7 +411,7 @@ struct traits > }; template -struct traits > +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl index 90d624bc4d..050e34566e 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/lambertian.hlsl @@ -19,9 +19,9 @@ namespace reflection { template) -struct SLambertianBxDF +struct SLambertian { - using this_t = SLambertianBxDF; + using this_t = SLambertian; NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); NBL_BXDF_CONFIG_ALIAS(ray_dir_info_type, Config); @@ -88,7 +88,7 @@ struct SLambertianBxDF } template -struct traits > +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = false; diff --git a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl index 4b89867221..dc805b0d03 100644 --- a/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/reflection/oren_nayar.hlsl @@ -19,9 +19,9 @@ namespace reflection { template) -struct SOrenNayarBxDF +struct SOrenNayar { - using this_t = SOrenNayarBxDF; + using this_t = SOrenNayar; NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); NBL_BXDF_CONFIG_ALIAS(ray_dir_info_type, Config); @@ -109,7 +109,7 @@ struct SOrenNayarBxDF } template -struct traits > +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BRDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index 24c9849abf..e9d659021a 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -20,12 +20,12 @@ namespace transmission { template -struct SBeckmannDielectricAnisotropicBxDF; +struct SBeckmannDielectricAnisotropic; template) -struct SBeckmannDielectricIsotropicBxDF +struct SBeckmannDielectricIsotropic { - using this_t = SBeckmannDielectricIsotropicBxDF; + using this_t = SBeckmannDielectricIsotropic; NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); NBL_BXDF_CONFIG_ALIAS(vector3_type, Config); @@ -40,7 +40,7 @@ struct SBeckmannDielectricIsotropicBxDF NBL_BXDF_CONFIG_ALIAS(quotient_pdf_type, Config); NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); - using brdf_type = reflection::SBeckmannIsotropicBxDF; + using brdf_type = reflection::SBeckmannIsotropic; using ndf_type = ndf::Beckmann; using fresnel_type = fresnel::Dielectric; @@ -119,7 +119,7 @@ struct SBeckmannDielectricIsotropicBxDF sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) { - SBeckmannDielectricAnisotropicBxDF beckmann_aniso = SBeckmannDielectricAnisotropicBxDF::create(__base.fresnel.orientedEta, __base.ndf.A.x, __base.ndf.A.y); + SBeckmannDielectricAnisotropic beckmann_aniso = SBeckmannDielectricAnisotropic::create(__base.fresnel.orientedEta, __base.ndf.A.x, __base.ndf.A.y); anisocache_type anisocache; sample_type s = beckmann_aniso.generate(anisotropic_interaction_type::create(interaction), u, anisocache); cache = anisocache.iso_cache; @@ -183,9 +183,9 @@ struct SBeckmannDielectricIsotropicBxDF template NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration) -struct SBeckmannDielectricAnisotropicBxDF) > +struct SBeckmannDielectricAnisotropic) > { - using this_t = SBeckmannDielectricAnisotropicBxDF; + using this_t = SBeckmannDielectricAnisotropic; NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); NBL_BXDF_CONFIG_ALIAS(vector3_type, Config); @@ -200,7 +200,7 @@ struct SBeckmannDielectricAnisotropicBxDF; + using brdf_type = reflection::SBeckmannAnisotropic; using ndf_type = ndf::Beckmann; using fresnel_type = fresnel::Dielectric; @@ -382,7 +382,7 @@ struct SBeckmannDielectricAnisotropicBxDF -struct traits > +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; @@ -390,7 +390,7 @@ struct traits > }; template -struct traits > +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index fa638928ed..d45a825455 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -20,12 +20,12 @@ namespace transmission { template -struct SGGXDielectricAnisotropicBxDF; +struct SGGXDielectricAnisotropic; template) -struct SGGXDielectricIsotropicBxDF +struct SGGXDielectricIsotropic { - using this_t = SGGXDielectricIsotropicBxDF; + using this_t = SGGXDielectricIsotropic; NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); NBL_BXDF_CONFIG_ALIAS(vector3_type, Config); @@ -40,7 +40,7 @@ struct SGGXDielectricIsotropicBxDF NBL_BXDF_CONFIG_ALIAS(quotient_pdf_type, Config); NBL_BXDF_CONFIG_ALIAS(isocache_type, Config); NBL_BXDF_CONFIG_ALIAS(anisocache_type, Config); - using brdf_type = reflection::SGGXIsotropicBxDF; + using brdf_type = reflection::SGGXIsotropic; using ndf_type = ndf::GGX; using fresnel_type = fresnel::Dielectric; @@ -123,7 +123,7 @@ struct SGGXDielectricIsotropicBxDF sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u, NBL_REF_ARG(isocache_type) cache) { - SGGXDielectricAnisotropicBxDF ggx_aniso = SGGXDielectricAnisotropicBxDF::create(__base.fresnel.orientedEta, __base.ndf.A.x, __base.ndf.A.y); + SGGXDielectricAnisotropic ggx_aniso = SGGXDielectricAnisotropic::create(__base.fresnel.orientedEta, __base.ndf.A.x, __base.ndf.A.y); anisocache_type anisocache; sample_type s = ggx_aniso.generate(anisotropic_interaction_type::create(interaction), u, anisocache); cache = anisocache.iso_cache; @@ -196,9 +196,9 @@ struct SGGXDielectricIsotropicBxDF template NBL_PARTIAL_REQ_TOP(config_concepts::MicrofacetConfiguration) -struct SGGXDielectricAnisotropicBxDF) > +struct SGGXDielectricAnisotropic) > { - using this_t = SGGXDielectricAnisotropicBxDF; + using this_t = SGGXDielectricAnisotropic; NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); NBL_BXDF_CONFIG_ALIAS(vector3_type, Config); @@ -213,7 +213,7 @@ struct SGGXDielectricAnisotropicBxDF; + using brdf_type = reflection::SGGXAnisotropic; using ndf_type = ndf::GGX; using fresnel_type = fresnel::Dielectric; @@ -408,7 +408,7 @@ struct SGGXDielectricAnisotropicBxDF -struct traits > +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; @@ -416,7 +416,7 @@ struct traits > }; template -struct traits > +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl index afa22974a5..21beb89887 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/lambertian.hlsl @@ -20,9 +20,9 @@ namespace transmission { template) -struct SLambertianBxDF +struct SLambertian { - using this_t = SLambertianBxDF; + using this_t = SLambertian; NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); NBL_BXDF_CONFIG_ALIAS(vector3_type, Config); NBL_BXDF_CONFIG_ALIAS(ray_dir_info_type, Config); @@ -94,7 +94,7 @@ struct SLambertianBxDF } template -struct traits > +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = false; diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index d999d1a98e..0b7552d5c1 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -18,9 +18,9 @@ namespace transmission { template) -struct SSmoothDielectricBxDF +struct SSmoothDielectric { - using this_t = SSmoothDielectricBxDF; + using this_t = SSmoothDielectric; NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); NBL_BXDF_CONFIG_ALIAS(vector3_type, Config); @@ -113,9 +113,9 @@ struct SSmoothDielectricBxDF }; template) -struct SSmoothThinDielectricBxDF +struct SSmoothThinDielectric { - using this_t = SSmoothThinDielectricBxDF; + using this_t = SSmoothThinDielectric; NBL_BXDF_CONFIG_ALIAS(scalar_type, Config); NBL_BXDF_CONFIG_ALIAS(vector2_type, Config); NBL_BXDF_CONFIG_ALIAS(vector3_type, Config); @@ -217,7 +217,7 @@ struct SSmoothThinDielectricBxDF } template -struct traits > +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; @@ -225,7 +225,7 @@ struct traits > }; template -struct traits > +struct traits > { NBL_CONSTEXPR_STATIC_INLINE BxDFType type = BT_BSDF; NBL_CONSTEXPR_STATIC_INLINE bool clampNdotV = true; From 4019c3005c3c8a3a14267160e9dbdb753c065f55 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 15 Aug 2025 15:02:22 +0700 Subject: [PATCH 185/188] minor fixes to smooth dielectric, reflect/refract --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 6 ++-- include/nbl/builtin/hlsl/bxdf/fresnel.hlsl | 36 ++++++++++++------- .../bxdf/transmission/smooth_dielectric.hlsl | 29 ++++++--------- 3 files changed, 37 insertions(+), 34 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index b91319d6e0..42d033d0e3 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -72,21 +72,21 @@ struct SBasic vector3_type getDirection() NBL_CONST_MEMBER_FUNC { return direction; } - SBasic transmit() + SBasic transmit() NBL_CONST_MEMBER_FUNC { SBasic retval; retval.direction = -direction; return retval; } - SBasic reflect(NBL_CONST_REF_ARG(Reflect) r) + SBasic reflect(NBL_CONST_REF_ARG(Reflect) r) NBL_CONST_MEMBER_FUNC { SBasic retval; retval.direction = r(); return retval; } - SBasic refract(NBL_CONST_REF_ARG(Refract) r, scalar_type rcpOrientedEta) + SBasic refract(NBL_CONST_REF_ARG(Refract) r, scalar_type rcpOrientedEta) NBL_CONST_MEMBER_FUNC { SBasic retval; retval.direction = r(rcpOrientedEta); diff --git a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl index 5711ab428e..8284f46e6e 100644 --- a/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/fresnel.hlsl @@ -185,17 +185,17 @@ struct Reflect return retval; } - scalar_type getNdotI() + scalar_type getNdotI() NBL_CONST_MEMBER_FUNC { return hlsl::dot(N, I); } - vector_type operator()() + vector_type operator()() NBL_CONST_MEMBER_FUNC { return operator()(getNdotI()); } - vector_type operator()(const scalar_type NdotI) + vector_type operator()(const scalar_type NdotI) NBL_CONST_MEMBER_FUNC { return N * 2.0f * NdotI - I; } @@ -219,12 +219,12 @@ struct Refract return retval; } - scalar_type getNdotI() + scalar_type getNdotI() NBL_CONST_MEMBER_FUNC { return hlsl::dot(N, I); } - scalar_type getNdotT(const scalar_type rcpOrientedEta2) + scalar_type getNdotT(const scalar_type rcpOrientedEta2) NBL_CONST_MEMBER_FUNC { scalar_type NdotI = getNdotI(); scalar_type NdotT2 = rcpOrientedEta2 * NdotI*NdotI + 1.0 - rcpOrientedEta2; @@ -232,12 +232,12 @@ struct Refract return ieee754::copySign(absNdotT, -NdotI); // TODO: make a ieee754::copySignIntoPositive, see https://github.com/Devsh-Graphics-Programming/Nabla/pull/899#discussion_r2197473145 } - vector_type operator()(const scalar_type rcpOrientedEta) + vector_type operator()(const scalar_type rcpOrientedEta) NBL_CONST_MEMBER_FUNC { return N * (getNdotI() * rcpOrientedEta + getNdotT(rcpOrientedEta*rcpOrientedEta)) - rcpOrientedEta * I; } - vector_type operator()(const scalar_type rcpOrientedEta, const scalar_type NdotI, const scalar_type NdotT) + vector_type operator()(const scalar_type rcpOrientedEta, const scalar_type NdotI, const scalar_type NdotT) NBL_CONST_MEMBER_FUNC { return N * (NdotI * rcpOrientedEta + NdotT) - rcpOrientedEta * I; } @@ -254,29 +254,39 @@ struct ReflectRefract using scalar_type = T; // when you know you'll reflect - scalar_type getNdotR() + scalar_type getNdotR() NBL_CONST_MEMBER_FUNC { return refract.getNdotI(); } // when you know you'll refract - scalar_type getNdotT(const scalar_type rcpOrientedEta) + scalar_type getNdotT(const scalar_type rcpOrientedEta) NBL_CONST_MEMBER_FUNC { return refract.getNdotT(rcpOrientedEta*rcpOrientedEta); } - scalar_type getNdotTorR(const bool doRefract, const scalar_type rcpOrientedEta) + scalar_type getNdotTorR(const bool doRefract, const scalar_type rcpOrientedEta) NBL_CONST_MEMBER_FUNC { return hlsl::mix(getNdotR(), getNdotT(rcpOrientedEta), doRefract); } - vector_type operator()(const bool doRefract, const scalar_type rcpOrientedEta) + vector_type operator()(const bool doRefract, const scalar_type rcpOrientedEta, NBL_REF_ARG(scalar_type) out_IdotTorR) NBL_CONST_MEMBER_FUNC { scalar_type NdotI = getNdotR(); - return refract.N * (NdotI * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)) + hlsl::mix(NdotI, getNdotT(rcpOrientedEta), doRefract)) - refract.I * (hlsl::mix(1.0f, rcpOrientedEta, doRefract)); + const scalar_type a = hlsl::mix(1.0f, rcpOrientedEta, doRefract); + const scalar_type b = NdotI * a + getNdotTorR(doRefract, rcpOrientedEta); + // assuming `I` is normalized + out_IdotTorR = NdotI * b - a; + return refract.N * b - refract.I * a; } - vector_type operator()(const scalar_type NdotTorR, const scalar_type rcpOrientedEta) + vector_type operator()(const bool doRefract, const scalar_type rcpOrientedEta) NBL_CONST_MEMBER_FUNC + { + scalar_type dummy; + return operator()(doRefract, rcpOrientedEta, dummy); + } + + vector_type operator()(const scalar_type NdotTorR, const scalar_type rcpOrientedEta) NBL_CONST_MEMBER_FUNC { scalar_type NdotI = getNdotR(); bool doRefract = ComputeMicrofacetNormal::isTransmissionPath(NdotI, NdotTorR); diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index 0b7552d5c1..4c4ba7f444 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -60,28 +60,20 @@ struct SSmoothDielectric return hlsl::promote(0); } - sample_type __generate_wo_clamps(const vector3_type V, const vector3_type T, const vector3_type B, const vector3_type N, scalar_type NdotV, scalar_type absNdotV, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtas) orientedEta, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps) rcpEta, NBL_REF_ARG(bool) transmitted) + sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u) { - const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta.value*orientedEta.value, absNdotV)[0]; + fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.getNdotV(_clamp), hlsl::promote(eta)); + const scalar_type reflectance = fresnel::Dielectric::__call(orientedEta.value*orientedEta.value, interaction.getNdotV(_clamp))[0]; scalar_type rcpChoiceProb; - transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); + bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); ray_dir_info_type L; - Refract r = Refract::create(V, N); + Refract r = Refract::create(interaction.getV().getDirection(), interaction.getN()); bxdf::ReflectRefract rr; rr.refract = r; L.direction = rr(transmitted, orientedEta.rcp[0]); - return sample_type::create(L, T, B, N); - } - - sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u) - { - fresnel::OrientedEtas orientedEta = fresnel::OrientedEtas::create(interaction.getNdotV(_clamp), hlsl::promote(eta)); - fresnel::OrientedEtaRcps rcpEta = fresnel::OrientedEtaRcps::create(interaction.getNdotV(_clamp), hlsl::promote(eta)); - bool dummy; - return __generate_wo_clamps(interaction.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.getN(), interaction.getNdotV(), - interaction.getNdotV(_clamp), u, orientedEta, rcpEta, dummy); + return sample_type::create(L, interaction.getT(), interaction.getB(), interaction.getN()); } sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u) { @@ -161,7 +153,7 @@ struct SSmoothThinDielectric // its basically a set of weights that determine // assert(1.0==luminosityContributionHint.r+luminosityContributionHint.g+luminosityContributionHint.b); // `remainderMetadata` is a variable which the generator function returns byproducts of sample generation that would otherwise have to be redundantly calculated `quotient_and_pdf` - sample_type __generate_wo_clamps(const vector3_type V, const vector3_type T, const vector3_type B, const vector3_type N, scalar_type NdotV, scalar_type absNdotV, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(spectral_type) eta2, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint, NBL_REF_ARG(spectral_type) remainderMetadata) + sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(ray_dir_info_type) V, const vector3_type T, const vector3_type B, const vector3_type N, scalar_type NdotV, scalar_type absNdotV, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(spectral_type) eta2, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint, NBL_REF_ARG(spectral_type) remainderMetadata) { // we will only ever intersect from the outside const spectral_type reflectance = fresnel::thinDielectricInfiniteScatter(fresnel::Dielectric::__call(eta2,absNdotV)); @@ -171,17 +163,18 @@ struct SSmoothThinDielectric scalar_type rcpChoiceProb; const bool transmitted = math::partitionRandVariable(reflectionProb, u.z, rcpChoiceProb); - remainderMetadata = (transmitted ? (hlsl::promote(1.0) - reflectance) : reflectance) * rcpChoiceProb; + remainderMetadata = hlsl::mix(reflectance, hlsl::promote(1.0) - reflectance, transmitted) * rcpChoiceProb; + Reflect r = Reflect::create(V.getDirection(), N); ray_dir_info_type L; - L.direction = (transmitted ? (vector3_type)(0.0) : N * 2.0f * NdotV) - V; + L.direction = hlsl::mix(V.reflect(r).getDirection(), V.transmit().getDirection(), transmitted); return sample_type::create(L, T, B, N); } sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u) { vector3_type dummy; - return __generate_wo_clamps(interaction.getV().getDirection(), interaction.getT(), interaction.getB(), interaction.getN(), interaction.getNdotV(), interaction.getNdotV(_clamp), u, eta2, luminosityContributionHint, dummy); + return __generate_wo_clamps(interaction.getV(), interaction.getT(), interaction.getB(), interaction.getN(), interaction.getNdotV(), interaction.getNdotV(_clamp), u, eta2, luminosityContributionHint, dummy); } sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u) { From bf413ced0dfca6f2391b0f6b3e8263432dae7a35 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 15 Aug 2025 15:35:39 +0700 Subject: [PATCH 186/188] added and use RayDirInfo reflectRefract method --- include/nbl/builtin/hlsl/bxdf/common.hlsl | 16 +++++++++++++++- .../builtin/hlsl/bxdf/transmission/beckmann.hlsl | 2 +- .../nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl | 2 +- .../bxdf/transmission/smooth_dielectric.hlsl | 6 +++--- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/common.hlsl b/include/nbl/builtin/hlsl/bxdf/common.hlsl index 42d033d0e3..f014e8ee4a 100644 --- a/include/nbl/builtin/hlsl/bxdf/common.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/common.hlsl @@ -36,13 +36,17 @@ namespace ray_dir_info #define NBL_CONCEPT_PARAM_3 (m, typename T::matrix3x3_type) #define NBL_CONCEPT_PARAM_4 (rfl, Reflect) #define NBL_CONCEPT_PARAM_5 (rfr, Refract) -NBL_CONCEPT_BEGIN(6) +#define NBL_CONCEPT_PARAM_6 (t, bool) +#define NBL_CONCEPT_PARAM_7 (rr, ReflectRefract) +NBL_CONCEPT_BEGIN(8) #define rdirinfo NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 #define N NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 #define rcpEta NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 #define m NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 #define rfl NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 #define rfr NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 +#define t NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 +#define rr NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_7 NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) @@ -51,10 +55,13 @@ NBL_CONCEPT_END( ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.transmit()), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.reflect(rfl)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.refract(rfr, rcpEta)), ::nbl::hlsl::is_same_v, T)) + ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.reflectRefract(rr, t, rcpEta)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.transform(m)), ::nbl::hlsl::is_same_v, T)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(is_scalar_v, typename T::scalar_type)) ((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(is_vector_v, typename T::vector3_type)) ); +#undef rr +#undef t #undef rfr #undef rfl #undef m @@ -93,6 +100,13 @@ struct SBasic return retval; } + SBasic reflectRefract(NBL_CONST_REF_ARG(ReflectRefract) rr, bool transmitted, scalar_type rcpOrientedEta) NBL_CONST_MEMBER_FUNC + { + SBasic retval; + retval.direction = rr(transmitted, rcpOrientedEta); + return retval; + } + // WARNING: matrix must be orthonormal SBasic transform(const matrix3x3_type m) NBL_CONST_MEMBER_FUNC { diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl index e9d659021a..d4f01ec437 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/beckmann.hlsl @@ -297,7 +297,7 @@ struct SBeckmannDielectricAnisotropic rr; rr.refract = r; - localL.direction = rr(transmitted, rcpEta.value[0]); + localL = localL.reflectRefract(rr, transmitted, rcpEta.value[0]); return sample_type::createFromTangentSpace(localL, m); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl index d45a825455..9bdaa28d33 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/ggx.hlsl @@ -314,7 +314,7 @@ struct SGGXDielectricAnisotropic rr; rr.refract = r; - localL.direction = rr(transmitted, rcpEta.value[0]); + localL = localL.reflectRefract(rr, transmitted, rcpEta.value[0]); return sample_type::createFromTangentSpace(localL, m); } diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index 4c4ba7f444..a0629dd66c 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -68,11 +68,11 @@ struct SSmoothDielectric scalar_type rcpChoiceProb; bool transmitted = math::partitionRandVariable(reflectance, u.z, rcpChoiceProb); - ray_dir_info_type L; - Refract r = Refract::create(interaction.getV().getDirection(), interaction.getN()); + ray_dir_info_type V = interaction.getV(); + Refract r = Refract::create(V.getDirection(), interaction.getN()); bxdf::ReflectRefract rr; rr.refract = r; - L.direction = rr(transmitted, orientedEta.rcp[0]); + ray_dir_info_type L = V.reflectRefract(rr, transmitted, orientedEta.rcp[0]); return sample_type::create(L, interaction.getT(), interaction.getB(), interaction.getN()); } sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u) From e810f472ce23918abbe094d49115e3e0635eb5eb Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 15 Aug 2025 15:46:52 +0700 Subject: [PATCH 187/188] fixes to smooth dielectric, default create method with rec709 luma coeffs --- .../hlsl/bxdf/transmission/smooth_dielectric.hlsl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl index a0629dd66c..20e72fdc35 100644 --- a/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl +++ b/include/nbl/builtin/hlsl/bxdf/transmission/smooth_dielectric.hlsl @@ -88,13 +88,7 @@ struct SSmoothDielectric quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) { - const bool transmitted = ComputeMicrofacetNormal::isTransmissionPath(interaction.getNdotV(), _sample.getNdotL()); - - fresnel::OrientedEtaRcps rcpOrientedEtas = fresnel::OrientedEtaRcps::create(interaction.getNdotV(_clamp), hlsl::promote(eta)); - - const scalar_type _pdf = bit_cast(numeric_limits::infinity); - scalar_type quo = hlsl::mix(1.0, rcpOrientedEtas.value[0], transmitted); - return quotient_pdf_type::create(quo, _pdf); + return quotient_pdf_type::create(1.0, bit_cast(numeric_limits::infinity)); } quotient_pdf_type quotient_and_pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) { @@ -135,6 +129,12 @@ struct SSmoothThinDielectric retval.luminosityContributionHint = luminosityContributionHint; return retval; } + static this_t create(NBL_CONST_REF_ARG(spectral_type) eta2) + { + static_assert(vector_traits::Dimension == 3); + const spectral_type rec709 = spectral_type(0.2126, 0.7152, 0.0722); + return create(eta2, rec709); + } static this_t create(NBL_CONST_REF_ARG(creation_type) params) { return create(params.eta2, params.luminosityContributionHint); From ff830452df22182988e57576a559d42e8c488549 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 15 Aug 2025 16:53:41 +0700 Subject: [PATCH 188/188] usage changes to NBL_VALID_EXPRESSION macro --- include/nbl/builtin/hlsl/concepts.hlsl | 7 +++---- include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl | 6 +++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/include/nbl/builtin/hlsl/concepts.hlsl b/include/nbl/builtin/hlsl/concepts.hlsl index c51364bb5c..6e0f380d01 100644 --- a/include/nbl/builtin/hlsl/concepts.hlsl +++ b/include/nbl/builtin/hlsl/concepts.hlsl @@ -122,19 +122,18 @@ NBL_CONSTEXPR bool NBL_CONCEPT_NAME = BOOST_PP_SEQ_FOR_EACH_I(NBL_IMPL_CONCEPT_E #include #include -#define NBL_IMPL_EXPR_DECLVAL(r,data,i,_T) BOOST_PP_COMMA_IF(BOOST_PP_NOT_EQUAL(i,0)) experimental::declval<_T>() #define NBL_IMPL_EXPR_DECL_TEMP_ARG(r,data,i,_T) BOOST_PP_COMMA_IF(BOOST_PP_NOT_EQUAL(i,0)) typename _T #define NBL_IMPL_EXPR_ITER_TEMP_ARG(r,data,i,_T) BOOST_PP_COMMA_IF(BOOST_PP_NOT_EQUAL(i,0)) _T -#define NBL_VALID_EXPRESSION(CONCEPT_NAME, FUNCTION_NAME, ARG_TYPE_LIST, ARG_TYPE_SET)\ +#define NBL_VALID_EXPRESSION(CONCEPT_NAME, ARG_TYPE_LIST, ...)\ namespace impl\ {\ template\ struct CONCEPT_NAME : false_type {};\ template\ -struct CONCEPT_NAME(BOOST_PP_SEQ_FOR_EACH_I(NBL_IMPL_EXPR_DECLVAL, _, ARG_TYPE_SET)))> > : true_type {};\ +struct CONCEPT_NAME > : true_type {};\ }\ template\ -NBL_BOOL_CONCEPT CONCEPT_NAME = impl::CONCEPT_NAME::value;\ +NBL_BOOL_CONCEPT CONCEPT_NAME = impl::CONCEPT_NAME::value\ } } diff --git a/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl b/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl index 738efab706..da713aae59 100644 --- a/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl +++ b/include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl @@ -356,8 +356,8 @@ template || concepts::Fl [[vk::ext_instruction(spv::OpFOrdEqual)]] conditional_t, vector::Dimension>, bool> FOrdEqual(T lhs, T rhs); -NBL_VALID_EXPRESSION(IEqualIsCallable, IEqual, (T), (T)(T)) -NBL_VALID_EXPRESSION(FOrdEqualIsCallable, FOrdEqual, (T), (T)(T)) +NBL_VALID_EXPRESSION(IEqualIsCallable, (T), IEqual(experimental::declval(),experimental::declval())); +NBL_VALID_EXPRESSION(FOrdEqualIsCallable, (T), FOrdEqual(experimental::declval(),experimental::declval())); template NBL_BOOL_CONCEPT EqualIntrinsicCallable = IEqualIsCallable || FOrdEqualIsCallable; @@ -366,7 +366,7 @@ template && (!conc [[vk::ext_instruction(spv::OpSelect)]] T select(U a, T x, T y); -NBL_VALID_EXPRESSION(SelectIsCallable, select, (T)(U), (U)(T)(T)) +NBL_VALID_EXPRESSION(SelectIsCallable, (T)(U), select(experimental::declval(),experimental::declval(),experimental::declval())); }