Skip to content

Commit 4b8a06b

Browse files
committed
fix edge cases for iridescent fresnel
1 parent 1a2f561 commit 4b8a06b

File tree

2 files changed

+26
-13
lines changed

2 files changed

+26
-13
lines changed

include/nbl/builtin/hlsl/bxdf/base/cook_torrance_base.hlsl

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,10 @@ struct SCookTorrance
128128
return cache.isValid(orientedEta);
129129
}
130130

131-
bool dotIsUnity(const vector3_type a, const vector3_type b)
131+
bool dotIsUnity(const vector3_type a, const vector3_type b, const scalar_type value)
132132
{
133133
const scalar_type ab = hlsl::dot(a, b);
134-
return hlsl::max(ab, scalar_type(1.0) / ab) <= scalar_type(1.0 + 1e-3);
134+
return hlsl::max(ab, value / ab) <= scalar_type(value + 1e-3);
135135
}
136136

137137
// bxdf stuff
@@ -197,11 +197,11 @@ struct SCookTorrance
197197
ray_dir_info_type V = interaction.getV();
198198
const matrix3x3_type fromTangent = interaction.getFromTangentSpace();
199199
// tangent frame orthonormality
200-
assert(dotIsUnity(fromTangent[0],fromTangent[1]));
201-
assert(dotIsUnity(fromTangent[1],fromTangent[2]));
202-
assert(dotIsUnity(fromTangent[2],fromTangent[0]));
200+
assert(dotIsUnity(fromTangent[0],fromTangent[1],0.0));
201+
assert(dotIsUnity(fromTangent[1],fromTangent[2],0.0));
202+
assert(dotIsUnity(fromTangent[2],fromTangent[0],0.0));
203203
// NDF sampling produced a unit length direction
204-
assert(dotIsUnity(localH,localH));
204+
assert(dotIsUnity(localH,localH,1.0));
205205
const vector3_type H = hlsl::mul(interaction.getFromTangentSpace(), localH);
206206
Refract<scalar_type> r = Refract<scalar_type>::create(V.getDirection(), H);
207207

@@ -238,7 +238,17 @@ struct SCookTorrance
238238
const vector3_type localV = interaction.getTangentSpaceV();
239239
const vector3_type localH = ndf.generateH(localV, u);
240240
const scalar_type VdotH = hlsl::dot(localV, localH);
241-
assert(VdotH >= scalar_type(0.0)); // VNDF sampling guarantees VdotH has same sign as NdotV (should be positive for BRDF)
241+
NBL_IF_CONSTEXPR(!ndf_type::GuaranteedVNDF) // VNDF sampling guarantees VdotH has same sign as NdotV (should be positive for BRDF)
242+
{
243+
// allow for rejection sampling, theoretically NdotV=0 or VdotH=0 is valid, but leads to 0 value contribution anyway
244+
if (VdotH <= scalar_type(0.0))
245+
return sample_type::createInvalid();
246+
assert(!hlsl::isnan(NdotV*VdotH));
247+
}
248+
else
249+
{
250+
assert(VdotH >= scalar_type(0.0));
251+
}
242252

243253
fresnel::OrientedEtaRcps<monochrome_type> dummy;
244254
bool valid;
@@ -263,7 +273,7 @@ struct SCookTorrance
263273
NBL_IF_CONSTEXPR(!ndf_type::GuaranteedVNDF)
264274
{
265275
// allow for rejection sampling, theoretically NdotV=0 or VdotH=0 is valid, but leads to 0 value contribution anyway
266-
if ((IsBSDF ? (NdotV*VdotH) : VdotH) <= scalar_type(0.0))
276+
if (NdotV*VdotH <= scalar_type(0.0))
267277
return sample_type::createInvalid();
268278
assert(!hlsl::isnan(NdotV*VdotH));
269279
}
@@ -283,7 +293,7 @@ struct SCookTorrance
283293
sample_type s = __generate_common(interaction, localH, NdotV, VdotH, transmitted, rcpEta, cache, valid);
284294
if (valid)
285295
{
286-
assert(cache.isValid(fresnel::OrientedEtas<vector_type>::create(scalar_type(1.0), hlsl::promote<vector_type>(_f.getRefractionOrientedEta()))));
296+
assert(cache.isValid(fresnel::OrientedEtas<monochrome_type>::create(scalar_type(1.0), hlsl::promote<monochrome_type>(_f.getRefractionOrientedEta()))));
287297
const vector3_type T = interaction.getT();
288298
const vector3_type B = interaction.getB();
289299
const vector3_type H = hlsl::mul(interaction.getFromTangentSpace(), localH);

include/nbl/builtin/hlsl/bxdf/fresnel.hlsl

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ struct Conductor
401401
static void __polarized(const T orientedEta, const T orientedEtak, const T cosTheta, NBL_REF_ARG(T) Rp, NBL_REF_ARG(T) Rs)
402402
{
403403
T cosTheta_2 = cosTheta * cosTheta;
404-
T sinTheta2 = hlsl::promote<T>(1.0) - cosTheta_2;
404+
// T sinTheta2 = hlsl::promote<T>(1.0) - cosTheta_2;
405405
const T eta = orientedEta;
406406
const T eta2 = eta*eta;
407407
const T etak = orientedEtak;
@@ -470,7 +470,7 @@ struct Dielectric
470470
const T eta = orientedEta;
471471
const T eta2 = eta * eta;
472472

473-
T t0 = hlsl::sqrt(eta2 - sinTheta2);
473+
T t0 = hlsl::sqrt(hlsl::max(eta2 - sinTheta2, hlsl::promote<T>(0.0)));
474474
T t2 = eta2 * cosTheta;
475475

476476
T rp = (t0 - t2) / (t0 + t2);
@@ -569,9 +569,9 @@ struct iridescent_helper
569569

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

574-
cosTheta_2 = hlsl::sqrt(cosTheta2_2);
574+
cosTheta_2 = hlsl::sqrt(hlsl::max(cosTheta2_2, hlsl::promote<vector_type>(0.0)));
575575
Dielectric<vector_type>::__polarized(eta12, hlsl::promote<vector_type>(cosTheta_1), R12p, R12s);
576576

577577
// Reflected part by the base
@@ -585,6 +585,9 @@ struct iridescent_helper
585585
R12s = hlsl::mix(R12s, hlsl::promote<vector_type>(1.0), cosTheta2_2 <= hlsl::promote<vector_type>(0.0));
586586
R12p = hlsl::mix(R12p, hlsl::promote<vector_type>(1.0), cosTheta2_2 <= hlsl::promote<vector_type>(0.0));
587587

588+
R23s = hlsl::mix(R23s, hlsl::promote<vector_type>(0.0), cosTheta2_2 <= hlsl::promote<vector_type>(0.0));
589+
R23p = hlsl::mix(R23p, hlsl::promote<vector_type>(0.0), cosTheta2_2 <= hlsl::promote<vector_type>(0.0));
590+
588591
// Compute the transmission coefficients
589592
vector_type T121p = hlsl::promote<vector_type>(1.0) - R12p;
590593
vector_type T121s = hlsl::promote<vector_type>(1.0) - R12s;

0 commit comments

Comments
 (0)