Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
4b3224a
initial iridescent fresnel, only single channel ior
keptsecret Aug 26, 2025
9c71906
iridescent fresnel does rgb IOR, use in brdf
keptsecret Aug 26, 2025
0f51306
some bug fixes
keptsecret Aug 27, 2025
f205d4e
replace loop for vector operations in fresnel
keptsecret Aug 27, 2025
f6daa6f
added iridescent btdf
keptsecret Aug 27, 2025
09402ea
added unit tests
keptsecret Aug 27, 2025
a77c337
merge bxdfs, fix conflicts
keptsecret Aug 28, 2025
aa0f6e8
latest example
keptsecret Aug 28, 2025
d2cb193
moved colorspace transform mats into struct functions
keptsecret Aug 28, 2025
33fc955
some more colorspace utility
keptsecret Aug 28, 2025
0f6c7a2
merge latest bxdf_fixes, fix conflicts
keptsecret Nov 3, 2025
d8b6773
restore encode/decode matrices
keptsecret Nov 3, 2025
65239d9
colorspace specific dominant wavelengths (still missing ACES), use gl…
keptsecret Nov 3, 2025
9a8b77e
update iridescent fresnel to match fresnel concept
keptsecret Nov 3, 2025
702ec8d
Merge branch 'master' into iridescence_bxdf
keptsecret Nov 4, 2025
76ad0ed
minor typo fixes
keptsecret Nov 4, 2025
53c930f
minor fixes to cook torrance, ndf infinity, move util functions into …
keptsecret Nov 4, 2025
23de8ed
changes to angle adding usage
keptsecret Nov 4, 2025
ff9e03f
better orthonormality for H
keptsecret Nov 4, 2025
18b3922
minor change to ggx clamp
keptsecret Nov 4, 2025
a5d8f5c
Merge branch 'master' into iridescence_bxdf
keptsecret Nov 5, 2025
f3dd05c
minor changes to create complex_t in angle_adding
keptsecret Nov 5, 2025
68d3614
refactor out common section of cook torrance generate
keptsecret Nov 5, 2025
aebfecf
added luma contribution hint, getPrefixThroughputWeights to interacti…
keptsecret Nov 6, 2025
b53fa1b
cook torrance bsdf can use spectral fresnel, uses interaction.getPref…
keptsecret Nov 6, 2025
946b050
thin smooth dielectric use luma coeff from interaction
keptsecret Nov 6, 2025
1a2f561
split iridescent fresnel by SupportsTransmission, adjusted fresnel co…
keptsecret Nov 7, 2025
4b8a06b
fix edge cases for iridescent fresnel
keptsecret Nov 7, 2025
5782a49
removed redundant weight in interaction
keptsecret Nov 7, 2025
55471ca
removed duplicate fresnel code, added creation params for iridescent
keptsecret Nov 10, 2025
64be771
split out iridescent fresnel vars into base struct
keptsecret Nov 10, 2025
8f9a114
renamed private funcs, replace enable_if usage with NBL_FUNC_REQUIRES
keptsecret Nov 10, 2025
8a71f40
avoid promoting 1d fresnel to 3d just to dot product, added private f…
keptsecret Nov 10, 2025
dee1b61
init ndf quants, minor cook torrance fixes
keptsecret Nov 11, 2025
cd9b18b
primaries wavelengths for aces colorspaces (not sure they're correct)
keptsecret Nov 11, 2025
0984c7e
fixes to angle adder, handle some edge cases
keptsecret Nov 11, 2025
3d7ded6
Merge branch 'master' into iridescence_bxdf
keptsecret Nov 12, 2025
1908749
Bugfix `sincos_accumulator::create`
devshgraphicsprogramming Nov 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 76 additions & 50 deletions include/nbl/builtin/hlsl/bxdf/base/cook_torrance_base.hlsl

Large diffs are not rendered by default.

9 changes: 0 additions & 9 deletions include/nbl/builtin/hlsl/bxdf/common.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,6 @@ NBL_CONCEPT_END(
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.getNdotV2()), ::nbl::hlsl::is_same_v, typename T::scalar_type))
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.getPathOrigin()), ::nbl::hlsl::is_same_v, PathOrigin))
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.getLuminosityContributionHint()), ::nbl::hlsl::is_same_v, typename T::spectral_type))
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((iso.getPrefixThroughputWeights()), ::nbl::hlsl::is_same_v, typename T::spectral_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))
);
Expand Down Expand Up @@ -223,7 +222,6 @@ struct SIsotropic
retval.NdotV = nbl::hlsl::dot<vector3_type>(retval.N, retval.V.getDirection());
retval.NdotV2 = retval.NdotV * retval.NdotV;
retval.luminosityContributionHint = hlsl::promote<spectral_type>(1.0);
retval.throughputWeights = hlsl::promote<spectral_type>(1.0);

return retval;
}
Expand All @@ -238,19 +236,13 @@ struct SIsotropic

PathOrigin getPathOrigin() NBL_CONST_MEMBER_FUNC { return PathOrigin::PO_SENSOR; }
spectral_type getLuminosityContributionHint() NBL_CONST_MEMBER_FUNC { return luminosityContributionHint; }
spectral_type getPrefixThroughputWeights() NBL_CONST_MEMBER_FUNC
{
spectral_type prefixThroughputWeights = luminosityContributionHint * throughputWeights;
return prefixThroughputWeights / math::lpNorm<spectral_type,1>(prefixThroughputWeights);
}

RayDirInfo V;
vector3_type N;
scalar_type NdotV;
scalar_type NdotV2;

spectral_type luminosityContributionHint;
spectral_type throughputWeights; // product of all quotients so far
};

#define NBL_CONCEPT_NAME Anisotropic
Expand Down Expand Up @@ -337,7 +329,6 @@ struct SAnisotropic
scalar_type getNdotV2() NBL_CONST_MEMBER_FUNC { return isotropic.getNdotV2(); }
PathOrigin getPathOrigin() NBL_CONST_MEMBER_FUNC { return isotropic.getPathOrigin(); }
spectral_type getLuminosityContributionHint() NBL_CONST_MEMBER_FUNC { return isotropic.getLuminosityContributionHint(); }
spectral_type getPrefixThroughputWeights() NBL_CONST_MEMBER_FUNC { return isotropic.getPrefixThroughputWeights(); }

vector3_type getT() NBL_CONST_MEMBER_FUNC { return T; }
vector3_type getB() NBL_CONST_MEMBER_FUNC { return B; }
Expand Down
156 changes: 76 additions & 80 deletions include/nbl/builtin/hlsl/bxdf/fresnel.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -345,14 +345,16 @@ struct Schlick
using vector_type = T;
using eta_type = vector_type;

NBL_CONSTEXPR_STATIC_INLINE bool ReturnsMonochrome = vector_traits<vector_type>::Dimension == 1;

static Schlick<T> create(NBL_CONST_REF_ARG(T) F0)
{
Schlick<T> retval;
retval.F0 = F0;
return retval;
}

T operator()(const scalar_type clampedCosTheta)
T operator()(const scalar_type clampedCosTheta) NBL_CONST_MEMBER_FUNC
{
assert(clampedCosTheta >= scalar_type(0.0));
assert(hlsl::all(hlsl::promote<T>(0.02) < F0 && F0 <= hlsl::promote<T>(1.0)));
Expand All @@ -379,6 +381,8 @@ struct Conductor
using vector_type = T;
using eta_type = vector_type;

NBL_CONSTEXPR_STATIC_INLINE bool ReturnsMonochrome = vector_traits<vector_type>::Dimension == 1;

static Conductor<T> create(NBL_CONST_REF_ARG(T) eta, NBL_CONST_REF_ARG(T) etak)
{
Conductor<T> retval;
Expand All @@ -397,40 +401,25 @@ struct Conductor
return retval;
}

// TODO: will probably merge with __call at some point
static void __polarized(const T orientedEta, const T orientedEtak, const T cosTheta, NBL_REF_ARG(T) Rp, NBL_REF_ARG(T) Rs)
static void __polarized(const T orientedEta, const T etaLen2, const T clampedCosTheta, NBL_REF_ARG(T) Rp, NBL_REF_ARG(T) Rs)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool but this method/function should not be part of Conductor or Dielectric class, can make it free floating in fresnel namespace if you want

{
T cosTheta_2 = cosTheta * cosTheta;
T sinTheta2 = hlsl::promote<T>(1.0) - cosTheta_2;
const T cosTheta_2 = clampedCosTheta * clampedCosTheta;
const T eta = orientedEta;
const T eta2 = eta*eta;
const T etak = orientedEtak;
const T etak2 = etak*etak;

const T etaLen2 = eta2 + etak2;
assert(hlsl::all(etaLen2 > hlsl::promote<T>(hlsl::exp2<scalar_type>(-numeric_limits<scalar_type>::digits))));
T t1 = etaLen2 * cosTheta_2;
const T etaCosTwice = eta * cosTheta * scalar_type(2.0);
const T etaCosTwice = eta * clampedCosTheta * hlsl::promote<T>(2.0);

const T rs_common = etaLen2 + cosTheta_2;
Rs = (rs_common - etaCosTwice) / (rs_common + etaCosTwice);
const T rp_common = t1 + hlsl::promote<T>(1.0);
Rp = (rp_common - etaCosTwice) / (rp_common + etaCosTwice);
}

T operator()(const scalar_type clampedCosTheta)
T operator()(const scalar_type clampedCosTheta) NBL_CONST_MEMBER_FUNC
{
const scalar_type cosTheta_2 = clampedCosTheta * clampedCosTheta;
//const float sinTheta2 = 1.0 - cosTheta_2;

assert(hlsl::all(etaLen2 > hlsl::promote<T>(hlsl::exp2<scalar_type>(-numeric_limits<scalar_type>::digits))));
const T etaCosTwice = eta * clampedCosTheta * hlsl::promote<T>(2.0);

const T rs_common = etaLen2 + hlsl::promote<T>(cosTheta_2);
const T rs2 = (rs_common - etaCosTwice) / (rs_common + etaCosTwice);

const T rp_common = etaLen2 * cosTheta_2 + hlsl::promote<T>(1.0);
const T rp2 = (rp_common - etaCosTwice) / (rp_common + etaCosTwice);
T rs2, rp2;
__polarized(eta, etaLen2, hlsl::promote<T>(clampedCosTheta), rp2, rs2);

return (rs2 + rp2) * hlsl::promote<T>(0.5);
}
Expand All @@ -455,6 +444,8 @@ struct Dielectric
using vector_type = T;
using eta_type = vector_type;

NBL_CONSTEXPR_STATIC_INLINE bool ReturnsMonochrome = vector_traits<vector_type>::Dimension == 1;

static Dielectric<T> create(NBL_CONST_REF_ARG(OrientedEtas<T>) orientedEta)
{
Dielectric<T> retval;
Expand All @@ -463,15 +454,13 @@ struct Dielectric
return retval;
}

// TODO: will probably merge with __call at some point
static void __polarized(const T orientedEta, const T cosTheta, NBL_REF_ARG(T) Rp, NBL_REF_ARG(T) Rs)
static void __polarized(const T orientedEta2, const T cosTheta, NBL_REF_ARG(T) Rp, NBL_REF_ARG(T) Rs)
{
T sinTheta2 = hlsl::promote<T>(1.0) - cosTheta * cosTheta;
const T eta = orientedEta;
const T eta2 = eta * eta;
const T sinTheta2 = hlsl::promote<T>(1.0) - cosTheta * cosTheta;

T t0 = hlsl::sqrt(eta2 - sinTheta2);
T t2 = eta2 * cosTheta;
// the max() clamping can handle TIR when orientedEta2<1.0
T t0 = hlsl::sqrt(hlsl::max(orientedEta2 - sinTheta2, hlsl::promote<T>(0.0)));
T t2 = orientedEta2 * cosTheta;

T rp = (t0 - t2) / (t0 + t2);
Rp = rp * rp;
Expand All @@ -481,19 +470,13 @@ struct Dielectric

static T __call(NBL_CONST_REF_ARG(T) orientedEta2, const scalar_type clampedCosTheta)
{
const scalar_type sinTheta2 = scalar_type(1.0) - clampedCosTheta * clampedCosTheta;

// the max() clamping can handle TIR when orientedEta2<1.0
const T t0 = hlsl::sqrt<T>(hlsl::max<T>(orientedEta2 - sinTheta2, hlsl::promote<T>(0.0)));
const T rs = (hlsl::promote<T>(clampedCosTheta) - t0) / (hlsl::promote<T>(clampedCosTheta) + t0);

const T t2 = orientedEta2 * clampedCosTheta;
const T rp = (t0 - t2) / (t0 + t2);
T rs2, rp2;
__polarized(orientedEta2, hlsl::promote<T>(clampedCosTheta), rp2, rs2);

return (rs * rs + rp * rp) * scalar_type(0.5);
return (rs2 + rp2) * hlsl::promote<T>(0.5);
}

T operator()(const scalar_type clampedCosTheta)
T operator()(const scalar_type clampedCosTheta) NBL_CONST_MEMBER_FUNC
{
return __call(orientedEta2, clampedCosTheta);
}
Expand Down Expand Up @@ -560,37 +543,47 @@ struct iridescent_helper
return xyz / scalar_type(1.0685e-7);
}

T __call(const scalar_type clampedCosTheta)
template<typename Params>
static T __call(NBL_CONST_REF_ARG(Params) params, const scalar_type clampedCosTheta)
{
const vector_type wavelengths = vector_type(colorspace::scRGB::wavelength_R, colorspace::scRGB::wavelength_G, colorspace::scRGB::wavelength_B);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suppy colorspace from iridescent_base last template param (you can default to scSRGB)


scalar_type cosTheta_1 = clampedCosTheta;
const vector_type eta12 = params.getEta12();
const vector_type eta23 = params.getEta23();
const vector_type etak23 = params.getEtak23();
const scalar_type cosTheta_1 = clampedCosTheta;
vector_type cosTheta_2;

vector_type R12p, R23p, R12s, R23s;
const vector_type scale = scalar_type(1.0)/eta12;
const vector_type cosTheta2_2 = hlsl::promote<vector_type>(1.0) - hlsl::promote<vector_type>(1-cosTheta_1*cosTheta_1) * scale * scale;
const vector_type cosTheta2_2 = hlsl::promote<vector_type>(1.0) - hlsl::promote<vector_type>(1.0-cosTheta_1*cosTheta_1) * scale * scale;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this 1.0 should be wrapped in scalar_type(1.0) before - with cos theta

you can declare a const scalar_type unity = 1.0; somwhere in the function to save yourself a headache


cosTheta_2 = hlsl::sqrt(cosTheta2_2);
cosTheta_2 = hlsl::sqrt(hlsl::max(cosTheta2_2, hlsl::promote<vector_type>(0.0)));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a little code-style correctness note, after you clamp cosTheta_2 to not have imaginary numbers due to sqrt you loose the property that cosTheta2_2 == cosTheta_2*cosTheta_2 so you should "hide" cosTheta_2_2 in its own {} scope so its not accessible after the cosTheta_2 assignment

Dielectric<vector_type>::__polarized(eta12, hlsl::promote<vector_type>(cosTheta_1), R12p, R12s);

// Reflected part by the base
// if kappa==0, base material is dielectric
NBL_IF_CONSTEXPR(SupportsTransmission)
Dielectric<vector_type>::__polarized(eta23, cosTheta_2, R23p, R23s);
Dielectric<vector_type>::__polarized(eta23 * eta23, cosTheta_2, R23p, R23s);
else
Conductor<vector_type>::__polarized(eta23, etak23, cosTheta_2, R23p, R23s);
{
vector_type etaLen2 = eta23 * eta23 + etak23 * etak23;
Conductor<vector_type>::__polarized(eta23, etaLen2, cosTheta_2, R23p, R23s);
}

// Check for total internal reflection
R12s = hlsl::mix(R12s, hlsl::promote<vector_type>(1.0), cosTheta2_2 <= hlsl::promote<vector_type>(0.0));
R12p = hlsl::mix(R12p, hlsl::promote<vector_type>(1.0), cosTheta2_2 <= hlsl::promote<vector_type>(0.0));

R23s = hlsl::mix(R23s, hlsl::promote<vector_type>(0.0), cosTheta2_2 <= hlsl::promote<vector_type>(0.0));
R23p = hlsl::mix(R23p, hlsl::promote<vector_type>(0.0), cosTheta2_2 <= hlsl::promote<vector_type>(0.0));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can do const vector<bool,> tir = cosTheta2_2 <= hlsl::promote<vector_type>(0.0);

btw since you compute it as cosTheta_2 = hlsl::sqrt(hlsl::max(cosTheta2_2, hlsl::promote<vector_type>(0.0))); you can actually compute this condition as cosTheta2_2<=0.0

which in turns is hlsl::promote<vector_type>(1.0-cosTheta_1*cosTheta_1) * scale * scale >= 1.0

and in turn is hlsl::promote<>(1.0-cosTheta_1*cosTheta_1) >= eta12

So you can know the TIR waaay in advance


// Compute the transmission coefficients
vector_type T121p = hlsl::promote<vector_type>(1.0) - R12p;
vector_type T121s = hlsl::promote<vector_type>(1.0) - R12s;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually it would make sense to compute a vector<bool,> tir then do if (all(tir)) path that skips a lot of the calculations (since T121p, T121s, R23s, R23p and cosTheta2 are all zero then)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also it would make sense to have a notTIR instead of tir boolean (and if (!any(notTIR)) )

because you can make a const vector_type killFactor = vector_type(notTIR); // 0 when TIR, 1 otherwise

and then you can compute R23p, R23s, T121p and T121s as originalMixLHS*killFactor

then obviously you compute R12 from 1.0-T121


// Optical Path Difference
const vector_type D = hlsl::promote<vector_type>(2.0 * Dinc) * thinFilmIor * cosTheta_2;
const vector_type D = hlsl::promote<vector_type>(2.0 * params.getDinc()) * params.getThinFilmIor() * cosTheta_2;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hlsl::promote<vector_type>(2.0 * params.getDinc()) * params.getThinFilmIor() is a single vector which could be precomputed instead of getThinFilmIor()

const vector_type Dphi = hlsl::promote<vector_type>(2.0 * numbers::pi<scalar_type>) * D / wavelengths;

vector_type phi21p, phi21s, phi23p, phi23s, r123s, r123p, Rs;
Expand Down Expand Up @@ -639,6 +632,25 @@ struct iridescent_helper

return hlsl::max(colorspace::scRGB::FromXYZ(I), hlsl::promote<vector_type>(0.0)) * hlsl::promote<vector_type>(0.5);
}
};

template<typename T, bool SupportsTransmission NBL_PRIMARY_REQUIRES(concepts::FloatingPointLikeVectorial<T>)
struct iridescent_base
{
using scalar_type = typename vector_traits<T>::scalar_type;
using vector_type = T;

scalar_type getDinc() NBL_CONST_MEMBER_FUNC { return Dinc; }
vector_type getThinFilmIor() NBL_CONST_MEMBER_FUNC { return thinFilmIor; }
vector_type getEta12() NBL_CONST_MEMBER_FUNC { return eta12; }
vector_type getEta23() NBL_CONST_MEMBER_FUNC { return eta23; }
vector_type getEtak23() NBL_CONST_MEMBER_FUNC
{
NBL_IF_CONSTEXPR(SupportsTransmission)
return hlsl::promote<vector_type>(0.0);
else
return etak23;
}

scalar_type Dinc; // thickness of thin film in nanometers, rec. 100-25000nm
vector_type thinFilmIor;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still you are storking etak23 for dielectric iridescent.

don't take SupportsTransmission have etak23 and getEtak23() in your iridescent_base, define them in your Iridescent specializations and actually make them inherit instead of compose

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dinc and thinFilmIoR can be combined into a single member and getter

if you want more semantically clear initialization make creation parameter structs for Iridescent::create

Expand All @@ -656,32 +668,24 @@ struct Iridescent<T, false NBL_PARTIAL_REQ_BOT(concepts::FloatingPointLikeVector
using scalar_type = typename vector_traits<T>::scalar_type;
using vector_type = T; // assert dim==3?
using eta_type = vector_type;
using base_type = impl::iridescent_base<T, false>;

static this_t create(scalar_type Dinc, vector_type ior1, vector_type ior2, vector_type ior3, vector_type iork3)
{
this_t retval;
retval.helper.Dinc = Dinc;
retval.helper.thinFilmIor = ior2;
retval.helper.eta12 = ior2/ior1;
retval.helper.eta23 = ior3/ior2;
retval.helper.etak23 = iork3/ior2;
return retval;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where's our create from a creation parameters struct ?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NBL_CONSTEXPR_STATIC_INLINE bool ReturnsMonochrome = vector_traits<vector_type>::Dimension == 1;

T operator()(const scalar_type clampedCosTheta)
T operator()(const scalar_type clampedCosTheta) NBL_CONST_MEMBER_FUNC
{
return helper.__call(clampedCosTheta);
return impl::iridescent_helper<T,false>::template __call<base_type>(__base, clampedCosTheta);
}

OrientedEtaRcps<eta_type> getOrientedEtaRcps() NBL_CONST_MEMBER_FUNC
{
OrientedEtaRcps<eta_type> rcpEta;
rcpEta.value = hlsl::promote<eta_type>(1.0) / helper.eta23;
rcpEta.value = hlsl::promote<eta_type>(1.0) / __base.eta23;
rcpEta.value2 = rcpEta.value * rcpEta.value;
return rcpEta;
}

impl::iridescent_helper<T,false> helper;
base_type __base;
};

template<typename T>
Expand All @@ -692,28 +696,20 @@ struct Iridescent<T, true NBL_PARTIAL_REQ_BOT(concepts::FloatingPointLikeVectori
using scalar_type = typename vector_traits<T>::scalar_type;
using vector_type = T; // assert dim==3?
using eta_type = vector<scalar_type, 1>;
using base_type = impl::iridescent_base<T, true>;

static this_t create(scalar_type Dinc, vector_type ior1, vector_type ior2, vector_type ior3)
{
this_t retval;
retval.helper.Dinc = Dinc;
retval.helper.thinFilmIor = ior2;
retval.helper.eta12 = ior2/ior1;
retval.helper.eta23 = ior3/ior2;
retval.helper.etak23 = hlsl::promote<vector_type>(0.0);
return retval;
}
NBL_CONSTEXPR_STATIC_INLINE bool ReturnsMonochrome = vector_traits<vector_type>::Dimension == 1;

T operator()(const scalar_type clampedCosTheta)
T operator()(const scalar_type clampedCosTheta) NBL_CONST_MEMBER_FUNC
{
return helper.__call(clampedCosTheta);
return impl::iridescent_helper<T,true>::template __call<base_type>(__base, clampedCosTheta);
}

scalar_type getRefractionOrientedEta() NBL_CONST_MEMBER_FUNC { return helper.eta23[0]; }
scalar_type getRefractionOrientedEta() NBL_CONST_MEMBER_FUNC { return __base.eta23[0]; }
OrientedEtaRcps<eta_type> getOrientedEtaRcps() NBL_CONST_MEMBER_FUNC
{
OrientedEtaRcps<eta_type> rcpEta;
rcpEta.value = hlsl::promote<eta_type>(1.0) / helper.eta23[0];
rcpEta.value = hlsl::promote<eta_type>(1.0) / __base.eta23[0];
rcpEta.value2 = rcpEta.value * rcpEta.value;
return rcpEta;
}
Expand All @@ -722,15 +718,15 @@ struct Iridescent<T, true NBL_PARTIAL_REQ_BOT(concepts::FloatingPointLikeVectori
{
const bool flip = NdotI < scalar_type(0.0);
this_t orientedFresnel;
orientedFresnel.helper.Dinc = helper.Dinc;
orientedFresnel.helper.thinFilmIor = helper.thinFilmIor;
orientedFresnel.helper.eta12 = hlsl::mix(helper.eta12, hlsl::promote<vector_type>(1.0)/helper.eta12, flip);
orientedFresnel.helper.eta23 = hlsl::mix(helper.eta23, hlsl::promote<vector_type>(1.0)/helper.eta23, flip);
orientedFresnel.helper.etak23 = hlsl::promote<vector_type>(0.0);
orientedFresnel.__base.Dinc = __base.Dinc;
orientedFresnel.__base.thinFilmIor = __base.thinFilmIor;
orientedFresnel.__base.eta12 = hlsl::mix(__base.eta12, hlsl::promote<vector_type>(1.0)/__base.eta12, flip);
orientedFresnel.__base.eta23 = hlsl::mix(__base.eta23, hlsl::promote<vector_type>(1.0)/__base.eta23, flip);
orientedFresnel.__base.etak23 = hlsl::promote<vector_type>(0.0);
return orientedFresnel;
}

impl::iridescent_helper<T,true> helper;
base_type __base;
};


Expand Down
2 changes: 2 additions & 0 deletions include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,8 @@ struct Beckmann
if (isInfinity)
{
quant_type dmq;
dmq.microfacetMeasure = scalar_type(0.0);
dmq.projectedLightMeasure = scalar_type(0.0);
Comment on lines +342 to +343

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

both should be set to bit_cast<scale_type>(numeric_limits<scale_type>::inf) not 0s

return dmq;
}
scalar_type dg1 = D / (scalar_type(1.0) + query.getLambdaV());
Expand Down
4 changes: 4 additions & 0 deletions include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,11 @@ struct GGX
isInfinity = hlsl::isinf(D);
quant_type dmq;
if (isInfinity)
{
dmq.microfacetMeasure = scalar_type(0.0);
dmq.projectedLightMeasure = scalar_type(0.0);
Comment on lines +282 to +283

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

both should be set to bit_cast<scale_type>(numeric_limits<scale_type>::inf) not 0s

return dmq;
}

scalar_type dg1_over_2NdotV = D * query.getG1over2NdotV();
dmq.microfacetMeasure = scalar_type(2.0) * interaction.getNdotV(BxDFClampMode::BCM_ABS) * dg1_over_2NdotV;
Expand Down
Loading
Loading