From 34ee35ccc08a310c13f25e8940d34ca78ba303bb Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 25 Nov 2024 17:05:01 +0700 Subject: [PATCH 001/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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/112] 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;