Skip to content

Commit a1289f1

Browse files
committed
changes to ggx ndf usage, separate fresnel from vndf
1 parent adf93a4 commit a1289f1

File tree

8 files changed

+141
-128
lines changed

8 files changed

+141
-128
lines changed

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

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -240,30 +240,16 @@ struct ReflectRefract
240240
using vector_type = vector<T, 3>;
241241
using scalar_type = T;
242242

243-
static this_t create(NBL_CONST_REF_ARG(vector_type) I, NBL_CONST_REF_ARG(vector_type) N)
244-
{
245-
this_t retval;
246-
retval._refract = Refract<scalar_type>::create(I, N);
247-
return retval;
248-
}
249-
250-
static this_t create(NBL_CONST_REF_ARG(Refract<scalar_type>) refract)
251-
{
252-
this_t retval;
253-
retval._refract = refract;
254-
return retval;
255-
}
256-
257243
// when you know you'll reflect
258244
scalar_type getNdotR()
259245
{
260-
return _refract.getNdotI();
246+
return refract.getNdotI();
261247
}
262248

263249
// when you know you'll refract
264250
scalar_type getNdotT(const scalar_type rcpOrientedEta)
265251
{
266-
return _refract.getNdotT(rcpOrientedEta*rcpOrientedEta);
252+
return refract.getNdotT(rcpOrientedEta*rcpOrientedEta);
267253
}
268254

269255
scalar_type getNdotTorR(const bool doRefract, const scalar_type rcpOrientedEta)
@@ -274,17 +260,17 @@ struct ReflectRefract
274260
vector_type operator()(const bool doRefract, const scalar_type rcpOrientedEta)
275261
{
276262
scalar_type NdotI = getNdotR();
277-
return _refract.N * (NdotI * (hlsl::mix<scalar_type>(1.0f, rcpOrientedEta, doRefract)) + hlsl::mix(NdotI, getNdotT(rcpOrientedEta), doRefract)) - _refract.I * (hlsl::mix<scalar_type>(1.0f, rcpOrientedEta, doRefract));
263+
return refract.N * (NdotI * (hlsl::mix<scalar_type>(1.0f, rcpOrientedEta, doRefract)) + hlsl::mix(NdotI, getNdotT(rcpOrientedEta), doRefract)) - refract.I * (hlsl::mix<scalar_type>(1.0f, rcpOrientedEta, doRefract));
278264
}
279265

280266
vector_type operator()(const scalar_type NdotTorR, const scalar_type rcpOrientedEta)
281267
{
282268
scalar_type NdotI = getNdotR();
283269
bool doRefract = ComputeMicrofacetNormal<scalar_type>::isTransmissionPath(NdotI, NdotTorR);
284-
return _refract.N * (NdotI * (hlsl::mix<scalar_type>(1.0f, rcpOrientedEta, doRefract)) + hlsl::mix(NdotI, NdotTorR, doRefract)) - _refract.I * (hlsl::mix<scalar_type>(1.0f, rcpOrientedEta, doRefract));
270+
return refract.N * (NdotI * (hlsl::mix<scalar_type>(1.0f, rcpOrientedEta, doRefract)) + hlsl::mix(NdotI, NdotTorR, doRefract)) - refract.I * (hlsl::mix<scalar_type>(1.0f, rcpOrientedEta, doRefract));
285271
}
286272

287-
Refract<scalar_type> _refract;
273+
Refract<scalar_type> refract;
288274
};
289275

290276

include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ struct Beckmann<T,false NBL_PARTIAL_REQ_BOT(concepts::FloatingPointScalar<T>) >
4545
}
4646

4747
// bsdf
48-
scalar_type DG1(scalar_type ndf, scalar_type absNdotV, scalar_type lambda_V, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, scalar_type reflectance, NBL_REF_ARG(scalar_type) onePlusLambda_V)
48+
scalar_type DG1(scalar_type ndf, scalar_type absNdotV, scalar_type lambda_V, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, NBL_REF_ARG(scalar_type) onePlusLambda_V)
4949
{
5050
onePlusLambda_V = scalar_type(1.0) + lambda_V;
51-
return ndf::microfacet_to_light_measure_transform<scalar_type,false,ndf::MTT_REFLECT_REFRACT>::__call(hlsl::mix(reflectance, scalar_type(1.0) - reflectance, transmitted) * ndf / onePlusLambda_V, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta);
51+
return ndf::microfacet_to_light_measure_transform<scalar_type,false,ndf::MTT_REFLECT_REFRACT>::__call(ndf / onePlusLambda_V, absNdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta);
5252
}
5353

5454
scalar_type G1(scalar_type lambda)
@@ -113,10 +113,10 @@ struct Beckmann<T,true NBL_PARTIAL_REQ_BOT(concepts::FloatingPointScalar<T>) >
113113
return dg;
114114
}
115115

116-
scalar_type DG1(scalar_type ndf, scalar_type absNdotV, scalar_type lambda_V, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, scalar_type reflectance, NBL_REF_ARG(scalar_type) onePlusLambda_V)
116+
scalar_type DG1(scalar_type ndf, scalar_type absNdotV, scalar_type lambda_V, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, NBL_REF_ARG(scalar_type) onePlusLambda_V)
117117
{
118118
Beckmann<T,false> beckmann;
119-
scalar_type dg = beckmann.DG1(ndf, absNdotV, lambda_V, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta, reflectance, onePlusLambda_V);
119+
scalar_type dg = beckmann.DG1(ndf, absNdotV, lambda_V, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta, onePlusLambda_V);
120120
return dg;
121121
}
122122

include/nbl/builtin/hlsl/bxdf/ndf/ggx.hlsl

Lines changed: 77 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -28,81 +28,87 @@ struct GGX<T,false NBL_PARTIAL_REQ_BOT(concepts::FloatingPointScalar<T>) >
2828
using this_t = GGX<T,false>;
2929

3030
// trowbridge-reitz
31-
scalar_type D(scalar_type a2, scalar_type NdotH2)
31+
scalar_type D(scalar_type NdotH2)
3232
{
33-
scalar_type denom = NdotH2 * (a2 - scalar_type(1.0)) + scalar_type(1.0);
33+
scalar_type denom = scalar_type(1.0) - one_minus_a2 * NdotH2;
3434
return a2 * numbers::inv_pi<scalar_type> / (denom * denom);
3535
}
3636

37-
scalar_type FVNDF(scalar_type fresnel_ndf, scalar_type G1_over_2NdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta)
37+
scalar_type DG1(scalar_type ndf, scalar_type G1_over_2NdotV)
38+
{
39+
scalar_type dummy = scalar_type(0.0);
40+
return DG1(ndf, G1_over_2NdotV, false, dummy, dummy, dummy, dummy);
41+
}
42+
43+
scalar_type DG1(scalar_type ndf, scalar_type G1_over_2NdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta)
3844
{
39-
scalar_type FNG = fresnel_ndf * G1_over_2NdotV;
45+
scalar_type NG = ndf * G1_over_2NdotV;
4046
scalar_type factor = scalar_type(0.5);
4147
if (transmitted)
4248
{
4349
const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH);
4450
// VdotHLdotH is negative under transmission, so this factor is negative
4551
factor *= -scalar_type(2.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH);
4652
}
47-
return FNG * factor;
48-
}
49-
50-
scalar_type DG1(scalar_type ndf, scalar_type G1_over_2NdotV)
51-
{
52-
return ndf * scalar_type(0.5) * G1_over_2NdotV;
53-
}
54-
55-
scalar_type DG1(scalar_type ndf, scalar_type G1_over_2NdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, scalar_type reflectance)
56-
{
57-
scalar_type FN = hlsl::mix(reflectance, scalar_type(1.0) - reflectance, transmitted) * ndf;
58-
return FVNDF(FN, G1_over_2NdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta);
53+
return NG * factor;
5954
}
6055

61-
scalar_type devsh_part(scalar_type NdotX2, scalar_type a2, scalar_type one_minus_a2)
56+
scalar_type devsh_part(scalar_type NdotX2)
6257
{
58+
assert(a2 >= numeric_limits<scalar_type>::min);
6359
return sqrt(a2 + one_minus_a2 * NdotX2);
6460
}
6561

66-
scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type NdotX2, scalar_type a2, scalar_type one_minus_a2)
62+
scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type NdotX2)
6763
{
68-
return scalar_type(1.0) / (NdotX + devsh_part(NdotX2,a2,one_minus_a2));
64+
return scalar_type(1.0) / (NdotX + devsh_part(NdotX2));
6965
}
7066

71-
scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type devsh_part)
67+
scalar_type G1_wo_numerator_devsh_part(scalar_type NdotX, scalar_type devsh_part)
7268
{
7369
return scalar_type(1.0) / (NdotX + devsh_part);
7470
}
7571

76-
scalar_type correlated_wo_numerator(scalar_type a2, scalar_type NdotV, scalar_type NdotV2, scalar_type NdotL, scalar_type NdotL2)
72+
scalar_type correlated_wo_numerator(scalar_type absNdotV, scalar_type NdotV2, scalar_type absNdotL, scalar_type NdotL2)
7773
{
78-
scalar_type one_minus_a2 = scalar_type(1.0) - a2;
79-
scalar_type Vterm = NdotL * devsh_part(NdotV2, a2, one_minus_a2);
80-
scalar_type Lterm = NdotV * devsh_part(NdotL2, a2, one_minus_a2);
74+
scalar_type Vterm = absNdotL * devsh_part(NdotV2);
75+
scalar_type Lterm = absNdotV * devsh_part(NdotL2);
8176
return scalar_type(0.5) / (Vterm + Lterm);
8277
}
8378

84-
scalar_type G2_over_G1(scalar_type a2, bool transmitted, scalar_type NdotV, scalar_type NdotV2, scalar_type NdotL, scalar_type NdotL2)
79+
scalar_type G2_over_G1(bool transmitted, scalar_type NdotV, scalar_type NdotV2, scalar_type NdotL, scalar_type NdotL2)
8580
{
8681
scalar_type G2_over_G1;
8782
if (transmitted)
8883
{
89-
scalar_type one_minus_a2 = scalar_type(1.0) - a2;
90-
scalar_type devsh_v = devsh_part(NdotV2, a2, one_minus_a2);
91-
scalar_type L_v = scalar_type(0.5) * (devsh_v / NdotV - scalar_type(1.0));
92-
scalar_type L_l = scalar_type(0.5) * (devsh_part(NdotL2, a2, one_minus_a2) / NdotL - scalar_type(1.0));
93-
G2_over_G1 = hlsl::beta<scalar_type>(scalar_type(1.0) + L_l, scalar_type(1.0) + L_v);
94-
G2_over_G1 *= scalar_type(1.0) + L_v;
84+
if (NdotV < 1e-7 || NdotL < 1e-7)
85+
return 0.0;
86+
scalar_type onePlusLambda_V = scalar_type(0.5) * (devsh_part(NdotV2) / NdotV + scalar_type(1.0));
87+
scalar_type onePlusLambda_L = scalar_type(0.5) * (devsh_part(NdotL2) / NdotL + scalar_type(1.0));
88+
G2_over_G1 = hlsl::beta<scalar_type>(onePlusLambda_L, onePlusLambda_V) * onePlusLambda_V;
9589
}
9690
else
9791
{
98-
scalar_type one_minus_a2 = scalar_type(1.0) - a2;
99-
scalar_type devsh_v = devsh_part(NdotV2, a2, one_minus_a2);
92+
scalar_type devsh_v = devsh_part(NdotV2);
10093
G2_over_G1 = NdotL * (devsh_v + NdotV); // alternative `Vterm+NdotL*NdotV /// NdotL*NdotV could come as a parameter
101-
G2_over_G1 /= NdotV * devsh_part(NdotL2, a2, one_minus_a2) + NdotL * devsh_v;
94+
G2_over_G1 /= NdotV * devsh_part(NdotL2) + NdotL * devsh_v;
10295
}
10396

10497
return G2_over_G1;
10598
}
99+
100+
// reflect only
101+
scalar_type G2_over_G1(scalar_type NdotV, scalar_type NdotV2, scalar_type NdotL, scalar_type NdotL2)
102+
{
103+
scalar_type devsh_v = devsh_part(NdotV2);
104+
scalar_type G2_over_G1 = NdotL * (devsh_v + NdotV); // alternative `Vterm+NdotL*NdotV /// NdotL*NdotV could come as a parameter
105+
G2_over_G1 /= NdotV * devsh_part(NdotL2) + NdotL * devsh_v;
106+
107+
return G2_over_G1;
108+
}
109+
110+
scalar_type a2;
111+
scalar_type one_minus_a2;
106112
};
107113

108114
template<typename T>
@@ -111,9 +117,11 @@ struct GGX<T,true NBL_PARTIAL_REQ_BOT(concepts::FloatingPointScalar<T>) >
111117
{
112118
using scalar_type = T;
113119

114-
scalar_type D(scalar_type ax, scalar_type ay, scalar_type ax2, scalar_type ay2, scalar_type TdotH2, scalar_type BdotH2, scalar_type NdotH2)
120+
scalar_type D(scalar_type TdotH2, scalar_type BdotH2, scalar_type NdotH2)
115121
{
116-
scalar_type a2 = ax * ay;
122+
const scalar_type ax2 = ax*ax;
123+
const scalar_type ay2 = ay*ay;
124+
const scalar_type a2 = ax * ay;
117125
scalar_type denom = TdotH2 / ax2 + BdotH2 / ay2 + NdotH2;
118126
return numbers::inv_pi<scalar_type> / (a2 * denom * denom);
119127
}
@@ -135,54 +143,70 @@ struct GGX<T,true NBL_PARTIAL_REQ_BOT(concepts::FloatingPointScalar<T>) >
135143
return ggx.DG1(ndf, G1_over_2NdotV);
136144
}
137145

138-
scalar_type DG1(scalar_type ndf, scalar_type G1_over_2NdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta, scalar_type reflectance)
146+
scalar_type DG1(scalar_type ndf, scalar_type G1_over_2NdotV, bool transmitted, scalar_type VdotH, scalar_type LdotH, scalar_type VdotHLdotH, scalar_type orientedEta)
139147
{
140148
GGX<T,false> ggx;
141-
return ggx.DG1(ndf, G1_over_2NdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta, reflectance);
149+
return ggx.DG1(ndf, G1_over_2NdotV, transmitted, VdotH, LdotH, VdotHLdotH, orientedEta);
142150
}
143151

144-
scalar_type devsh_part(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2, scalar_type ax2, scalar_type ay2)
152+
scalar_type devsh_part(scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2)
145153
{
154+
const scalar_type ax2 = ax*ax;
155+
const scalar_type ay2 = ay*ay;
156+
assert(ax2 >= numeric_limits<scalar_type>::min && ay2 >= numeric_limits<scalar_type>::min);
146157
return sqrt(TdotX2 * ax2 + BdotX2 * ay2 + NdotX2);
147158
}
148159

149-
scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2, scalar_type ax2, scalar_type ay2)
160+
scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type TdotX2, scalar_type BdotX2, scalar_type NdotX2)
150161
{
151-
return scalar_type(1.0) / (NdotX + devsh_part(TdotX2, BdotX2, NdotX2, ax2, ay2));
162+
return scalar_type(1.0) / (NdotX + devsh_part(TdotX2, BdotX2, NdotX2));
152163
}
153164

154-
scalar_type G1_wo_numerator(scalar_type NdotX, scalar_type devsh_part)
165+
scalar_type G1_wo_numerator_devsh_part(scalar_type NdotX, scalar_type devsh_part)
155166
{
156167
return scalar_type(1.0) / (NdotX + devsh_part);
157168
}
158169

159-
scalar_type correlated_wo_numerator(scalar_type ax2, scalar_type ay2, scalar_type NdotV, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type NdotL, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2)
170+
scalar_type correlated_wo_numerator(scalar_type absNdotV, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type absNdotL, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2)
160171
{
161-
scalar_type Vterm = NdotL * devsh_part(TdotV2, BdotV2, NdotV2, ax2, ay2);
162-
scalar_type Lterm = NdotV * devsh_part(TdotL2, BdotL2, NdotL2, ax2, ay2);
172+
scalar_type Vterm = absNdotL * devsh_part(TdotV2, BdotV2, NdotV2);
173+
scalar_type Lterm = absNdotV * devsh_part(TdotL2, BdotL2, NdotL2);
163174
return scalar_type(0.5) / (Vterm + Lterm);
164175
}
165176

166-
scalar_type G2_over_G1(scalar_type ax2, scalar_type ay2, bool transmitted, scalar_type NdotV, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type NdotL, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2)
177+
scalar_type G2_over_G1(bool transmitted, scalar_type NdotV, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type NdotL, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2)
167178
{
168179
scalar_type G2_over_G1;
169180
if (transmitted)
170181
{
171-
scalar_type devsh_v = devsh_part(TdotV2, BdotV2, NdotV2, ax2, ay2);
172-
scalar_type L_v = scalar_type(0.5) * (devsh_v / NdotV - scalar_type(1.0));
173-
scalar_type L_l = scalar_type(0.5) * (devsh_part(TdotL2, BdotL2, NdotL2, ax2, ay2) / NdotL - scalar_type(1.0));
174-
G2_over_G1 = hlsl::beta<scalar_type>(scalar_type(1.0) + L_l, scalar_type(1.0) + L_v);
175-
G2_over_G1 *= scalar_type(1.0) + L_v;
182+
if (NdotV < 1e-7 || NdotL < 1e-7)
183+
return 0.0;
184+
scalar_type onePlusLambda_V = scalar_type(0.5) * (devsh_part(TdotV2, BdotV2, NdotV2) / NdotV + scalar_type(1.0));
185+
scalar_type onePlusLambda_L = scalar_type(0.5) * (devsh_part(TdotL2, BdotL2, NdotL2) / NdotL + scalar_type(1.0));
186+
G2_over_G1 = hlsl::beta<scalar_type>(onePlusLambda_L, onePlusLambda_V) * onePlusLambda_V;
176187
}
177188
else
178189
{
179-
scalar_type devsh_v = devsh_part(TdotV2, BdotV2, NdotV2, ax2, ay2);
190+
scalar_type devsh_v = devsh_part(TdotV2, BdotV2, NdotV2);
180191
G2_over_G1 = NdotL * (devsh_v + NdotV);
181-
G2_over_G1 /= NdotV * devsh_part(TdotL2, BdotL2, NdotL2, ax2, ay2) + NdotL * devsh_v;
192+
G2_over_G1 /= NdotV * devsh_part(TdotL2, BdotL2, NdotL2) + NdotL * devsh_v;
182193
}
183194

184195
return G2_over_G1;
185196
}
197+
198+
// reflect only
199+
scalar_type G2_over_G1(scalar_type NdotV, scalar_type TdotV2, scalar_type BdotV2, scalar_type NdotV2, scalar_type NdotL, scalar_type TdotL2, scalar_type BdotL2, scalar_type NdotL2)
200+
{
201+
scalar_type devsh_v = devsh_part(TdotV2, BdotV2, NdotV2);
202+
scalar_type G2_over_G1 = NdotL * (devsh_v + NdotV);
203+
G2_over_G1 /= NdotV * devsh_part(TdotL2, BdotL2, NdotL2) + NdotL * devsh_v;
204+
205+
return G2_over_G1;
206+
}
207+
208+
scalar_type ax;
209+
scalar_type ay;
186210
};
187211

188212

include/nbl/builtin/hlsl/bxdf/reflection/beckmann.hlsl

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -287,9 +287,7 @@ struct SBeckmannBxDF
287287

288288
lambda = beckmann_ndf.LambdaC2(params.getNdotV2());
289289

290-
scalar_type _pdf = beckmann_ndf.DG1(ndf, params.getNdotVUnclamped(), lambda, onePlusLambda_V);
291-
292-
return _pdf;
290+
return beckmann_ndf.DG1(ndf, params.getNdotVUnclamped(), lambda, onePlusLambda_V);
293291
}
294292
scalar_type pdf(NBL_CONST_REF_ARG(params_anisotropic_t) params, NBL_REF_ARG(scalar_type) onePlusLambda_V)
295293
{
@@ -301,9 +299,7 @@ struct SBeckmannBxDF
301299

302300
lambda = beckmann_ndf.LambdaC2(params.getTdotV2(), params.getBdotV2(), params.getNdotV2());
303301

304-
scalar_type _pdf = beckmann_ndf.DG1(ndf, params.getNdotVUnclamped(), lambda, onePlusLambda_V);
305-
306-
return _pdf;
302+
return beckmann_ndf.DG1(ndf, params.getNdotVUnclamped(), lambda, onePlusLambda_V);
307303
}
308304

309305
scalar_type pdf(NBL_CONST_REF_ARG(params_isotropic_t) params)

0 commit comments

Comments
 (0)