@@ -43,10 +43,10 @@ vec3 ToLocal(vec3 X, vec3 Y, vec3 Z, vec3 V)
43
43
return vec3 (dot (V, X), dot (V, Y), dot (V, Z));
44
44
}
45
45
46
- float FresnelMix(Material mat, float eta, vec3 V, vec3 L, vec3 H )
46
+ float FresnelMix(Material mat, float eta, float VDotH )
47
47
{
48
- float metallicFresnel = SchlickFresnel(abs ( dot (L, H)) );
49
- float dielectricFresnel = DielectricFresnel(abs ( dot (V, H)) , eta);
48
+ float metallicFresnel = SchlickFresnel(VDotH );
49
+ float dielectricFresnel = DielectricFresnel(VDotH , eta);
50
50
return mix (dielectricFresnel, metallicFresnel, mat.metallic);
51
51
}
52
52
@@ -81,7 +81,7 @@ vec3 EvalSpecReflection(Material mat, float eta, vec3 specCol, vec3 V, vec3 L, v
81
81
if (L.z <= 0.0 )
82
82
return vec3 (0.0 );
83
83
84
- float FM = FresnelMix(mat, eta, V, L, H);
84
+ float FM = FresnelMix(mat, eta, dot ( L, H) );
85
85
vec3 F = mix (specCol, vec3 (1.0 ), FM);
86
86
float D = GTR2(H.z, mat.roughness);
87
87
float G1 = SmithG(abs (V.z), mat.roughness);
@@ -104,7 +104,7 @@ vec3 EvalSpecRefraction(Material mat, float eta, vec3 V, vec3 L, vec3 H, inout f
104
104
denom *= denom;
105
105
float G1 = SmithG(abs (V.z), mat.roughness);
106
106
float G2 = G1 * SmithG(abs (L.z), mat.roughness);
107
- float jacobian = abs (dot (L, H)) * eta * eta / denom;
107
+ float jacobian = abs (dot (L, H)) / denom;
108
108
109
109
pdf = G1 * max (0.0 , dot (V, H)) * D * jacobian / V.z;
110
110
@@ -160,13 +160,19 @@ vec3 DisneySample(State state, vec3 V, vec3 N, inout vec3 L, inout float pdf)
160
160
float r1 = rand();
161
161
float r2 = rand();
162
162
163
+ vec3 T, B;
164
+ Onb(N, T, B);
165
+ V = ToLocal(T, B, N, V); // NDotL = L.z; NDotV = V.z; NDotH = H.z
166
+
163
167
// Specular and sheen color
164
168
vec3 specCol, sheenCol;
165
169
GetSpecColor(state.mat, state.eta, specCol, sheenCol);
166
170
167
171
// Lobe weights
168
172
float diffuseWt, specReflectWt, specRefractWt, clearcoatWt;
169
- float approxFresnel = FresnelMix(state.mat, state.eta, V, reflect (V, N), N);
173
+ // TODO: Recheck fresnel. Not sure if correct. VDotN produces fireflies with rough dielectric.
174
+ // VDotH matches Mitsuba and gets rid of all fireflies but H isn't available at this stage
175
+ float approxFresnel = FresnelMix(state.mat, state.eta, V.z);
170
176
GetLobeProbabilities(state.mat, state.eta, specCol, approxFresnel, diffuseWt, specReflectWt, specRefractWt, clearcoatWt);
171
177
172
178
// CDF for picking a lobe
@@ -176,11 +182,6 @@ vec3 DisneySample(State state, vec3 V, vec3 N, inout vec3 L, inout float pdf)
176
182
cdf[2 ] = cdf[1 ] + specRefractWt;
177
183
cdf[3 ] = cdf[2 ] + clearcoatWt;
178
184
179
- vec3 T, B;
180
- Onb(N, T, B);
181
- // NDotL = L.z; NDotV = V.z; NDotH = H.z
182
- V = ToLocal(T, B, N, V);
183
-
184
185
if (r1 < cdf[0 ]) // Diffuse Reflection Lobe
185
186
{
186
187
r1 /= cdf[0 ];
@@ -196,7 +197,7 @@ vec3 DisneySample(State state, vec3 V, vec3 N, inout vec3 L, inout float pdf)
196
197
r1 = (r1 - cdf[0 ]) / (cdf[1 ] - cdf[0 ]);
197
198
vec3 H = SampleGGXVNDF(V, state.mat.roughness, r1, r2);
198
199
199
- if (dot (V, H) < 0.0 )
200
+ if (H.z < 0.0 )
200
201
H = - H;
201
202
202
203
L = normalize (reflect (- V, H));
@@ -209,7 +210,7 @@ vec3 DisneySample(State state, vec3 V, vec3 N, inout vec3 L, inout float pdf)
209
210
r1 = (r1 - cdf[1 ]) / (cdf[2 ] - cdf[1 ]);
210
211
vec3 H = SampleGGXVNDF(V, state.mat.roughness, r1, r2);
211
212
212
- if (dot (V, H) < 0.0 )
213
+ if (H.z < 0.0 )
213
214
H = - H;
214
215
215
216
L = normalize (refract (- V, H, state.eta));
@@ -222,7 +223,7 @@ vec3 DisneySample(State state, vec3 V, vec3 N, inout vec3 L, inout float pdf)
222
223
r1 = (r1 - cdf[2 ]) / (1.0 - cdf[2 ]);
223
224
vec3 H = SampleGTR1(state.mat.clearcoatRoughness, r1, r2);
224
225
225
- if (dot (V, H) < 0.0 )
226
+ if (H.z < 0.0 )
226
227
H = - H;
227
228
228
229
L = normalize (reflect (- V, H));
@@ -242,8 +243,7 @@ vec3 DisneyEval(State state, vec3 V, vec3 N, vec3 L, inout float bsdfPdf)
242
243
243
244
vec3 T, B;
244
245
Onb(N, T, B);
245
- // NDotL = L.z; NDotV = V.z; NDotH = H.z
246
- V = ToLocal(T, B, N, V);
246
+ V = ToLocal(T, B, N, V); // NDotL = L.z; NDotV = V.z; NDotH = H.z
247
247
L = ToLocal(T, B, N, L);
248
248
249
249
vec3 H;
@@ -252,7 +252,7 @@ vec3 DisneyEval(State state, vec3 V, vec3 N, vec3 L, inout float bsdfPdf)
252
252
else
253
253
H = normalize (L + V * state.eta);
254
254
255
- if (dot (V, H) < 0.0 )
255
+ if (H.z < 0.0 )
256
256
H = - H;
257
257
258
258
// Specular and sheen color
@@ -261,7 +261,7 @@ vec3 DisneyEval(State state, vec3 V, vec3 N, vec3 L, inout float bsdfPdf)
261
261
262
262
// Lobe weights
263
263
float diffuseWt, specReflectWt, specRefractWt, clearcoatWt;
264
- float approxFresnel = FresnelMix(state.mat, state.eta, V, L, H );
264
+ float approxFresnel = FresnelMix(state.mat, state.eta, dot ( V, H) );
265
265
GetLobeProbabilities(state.mat, state.eta, specCol, approxFresnel, diffuseWt, specReflectWt, specRefractWt, clearcoatWt);
266
266
267
267
float pdf;
0 commit comments