@@ -28,81 +28,87 @@ struct GGX<T,false NBL_PARTIAL_REQ_BOT(concepts::FloatingPointScalar<T>) >
28
28
using this_t = GGX<T,false>;
29
29
30
30
// trowbridge-reitz
31
- scalar_type D(scalar_type a2, scalar_type NdotH2)
31
+ scalar_type D(scalar_type NdotH2)
32
32
{
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 ;
34
34
return a2 * numbers::inv_pi<scalar_type> / (denom * denom);
35
35
}
36
36
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)
38
44
{
39
- scalar_type FNG = fresnel_ndf * G1_over_2NdotV;
45
+ scalar_type NG = ndf * G1_over_2NdotV;
40
46
scalar_type factor = scalar_type(0.5);
41
47
if (transmitted)
42
48
{
43
49
const scalar_type VdotH_etaLdotH = (VdotH + orientedEta * LdotH);
44
50
// VdotHLdotH is negative under transmission, so this factor is negative
45
51
factor *= -scalar_type(2.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH);
46
52
}
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;
59
54
}
60
55
61
- scalar_type devsh_part(scalar_type NdotX2, scalar_type a2, scalar_type one_minus_a2 )
56
+ scalar_type devsh_part(scalar_type NdotX2)
62
57
{
58
+ assert(a2 >= numeric_limits<scalar_type>::min);
63
59
return sqrt(a2 + one_minus_a2 * NdotX2);
64
60
}
65
61
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)
67
63
{
68
- return scalar_type(1.0) / (NdotX + devsh_part(NdotX2,a2,one_minus_a2 ));
64
+ return scalar_type(1.0) / (NdotX + devsh_part(NdotX2));
69
65
}
70
66
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)
72
68
{
73
69
return scalar_type(1.0) / (NdotX + devsh_part);
74
70
}
75
71
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)
77
73
{
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);
81
76
return scalar_type(0.5) / (Vterm + Lterm);
82
77
}
83
78
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)
85
80
{
86
81
scalar_type G2_over_G1;
87
82
if (transmitted)
88
83
{
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;
95
89
}
96
90
else
97
91
{
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);
100
93
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;
102
95
}
103
96
104
97
return G2_over_G1;
105
98
}
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;
106
112
};
107
113
108
114
template<typename T>
@@ -111,9 +117,11 @@ struct GGX<T,true NBL_PARTIAL_REQ_BOT(concepts::FloatingPointScalar<T>) >
111
117
{
112
118
using scalar_type = T;
113
119
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)
115
121
{
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;
117
125
scalar_type denom = TdotH2 / ax2 + BdotH2 / ay2 + NdotH2;
118
126
return numbers::inv_pi<scalar_type> / (a2 * denom * denom);
119
127
}
@@ -135,54 +143,70 @@ struct GGX<T,true NBL_PARTIAL_REQ_BOT(concepts::FloatingPointScalar<T>) >
135
143
return ggx.DG1(ndf, G1_over_2NdotV);
136
144
}
137
145
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)
139
147
{
140
148
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);
142
150
}
143
151
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)
145
153
{
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);
146
157
return sqrt(TdotX2 * ax2 + BdotX2 * ay2 + NdotX2);
147
158
}
148
159
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)
150
161
{
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));
152
163
}
153
164
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)
155
166
{
156
167
return scalar_type(1.0) / (NdotX + devsh_part);
157
168
}
158
169
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)
160
171
{
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);
163
174
return scalar_type(0.5) / (Vterm + Lterm);
164
175
}
165
176
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)
167
178
{
168
179
scalar_type G2_over_G1;
169
180
if (transmitted)
170
181
{
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 ;
176
187
}
177
188
else
178
189
{
179
- scalar_type devsh_v = devsh_part(TdotV2, BdotV2, NdotV2, ax2, ay2 );
190
+ scalar_type devsh_v = devsh_part(TdotV2, BdotV2, NdotV2);
180
191
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;
182
193
}
183
194
184
195
return G2_over_G1;
185
196
}
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;
186
210
};
187
211
188
212
0 commit comments