@@ -217,6 +217,82 @@ struct BeckmannCommon<T,true NBL_PARTIAL_REQ_BOT(concepts::FloatingPointScalar<T
217
217
scalar_type ax2;
218
218
scalar_type ay2;
219
219
};
220
+
221
+ template<typename T>
222
+ struct BeckmannGenerateH
223
+ {
224
+ using scalar_type = T;
225
+ using vector2_type = vector <T, 2 >;
226
+ using vector3_type = vector <T, 3 >;
227
+
228
+ vector3_type __call (const vector2_type A, const vector3_type localV, const vector2_type u)
229
+ {
230
+ //stretch
231
+ vector3_type V = nbl::hlsl::normalize<vector3_type>(vector3_type (A.x * localV.x, A.y * localV.y, localV.z));
232
+
233
+ vector2_type slope;
234
+ if (V.z > 0.9999 )//V.z=NdotV=cosTheta in tangent space
235
+ {
236
+ scalar_type r = sqrt<scalar_type>(-log<scalar_type>(1.0 - u.x));
237
+ scalar_type sinPhi = sin<scalar_type>(2.0 * numbers::pi<scalar_type> * u.y);
238
+ scalar_type cosPhi = cos<scalar_type>(2.0 * numbers::pi<scalar_type> * u.y);
239
+ slope = (vector2_type)r * vector2_type (cosPhi,sinPhi);
240
+ }
241
+ else
242
+ {
243
+ scalar_type cosTheta = V.z;
244
+ scalar_type sinTheta = sqrt<scalar_type>(1.0 - cosTheta * cosTheta);
245
+ scalar_type tanTheta = sinTheta / cosTheta;
246
+ scalar_type cotTheta = 1.0 / tanTheta;
247
+
248
+ scalar_type a = -1.0 ;
249
+ scalar_type c = erf<scalar_type>(cosTheta);
250
+ scalar_type sample_x = max <scalar_type>(u.x, 1. 0e-6 );
251
+ scalar_type theta = acos<scalar_type>(cosTheta);
252
+ scalar_type fit = 1.0 + theta * (-0.876 + theta * (0.4265 - 0.0594 *theta));
253
+ scalar_type b = c - (1.0 + c) * pow<scalar_type>(1.0 -sample_x, fit);
254
+
255
+ scalar_type normalization = 1.0 / (1.0 + c + numbers::inv_sqrtpi<scalar_type> * tanTheta * exp<scalar_type>(-cosTheta*cosTheta));
256
+
257
+ const int ITER_THRESHOLD = 10 ;
258
+ const float MAX_ACCEPTABLE_ERR = 1. 0e-5 ;
259
+ int it = 0 ;
260
+ float value=1000.0 ;
261
+ while (++it < ITER_THRESHOLD && nbl::hlsl::abs<scalar_type>(value) > MAX_ACCEPTABLE_ERR)
262
+ {
263
+ if (!(b >= a && b <= c))
264
+ b = 0.5 * (a + c);
265
+
266
+ float invErf = erfInv<scalar_type>(b);
267
+ value = normalization * (1.0 + b + numbers::inv_sqrtpi<scalar_type> * tanTheta * exp<scalar_type>(-invErf * invErf)) - sample_x;
268
+ float derivative = normalization * (1.0 - invErf * cosTheta);
269
+
270
+ if (value > 0.0 )
271
+ c = b;
272
+ else
273
+ a = b;
274
+
275
+ b -= value/derivative;
276
+ }
277
+ // TODO: investigate if we can replace these two erf^-1 calls with a box muller transform
278
+ slope.x = erfInv<scalar_type>(b);
279
+ slope.y = erfInv<scalar_type>(2.0 * max <scalar_type>(u.y, 1. 0e-6 ) - 1.0 );
280
+ }
281
+
282
+ scalar_type sinTheta = sqrt<scalar_type>(1.0 - V.z*V.z);
283
+ scalar_type cosPhi = sinTheta==0.0 ? 1.0 : clamp <scalar_type>(V.x/sinTheta, -1.0 , 1.0 );
284
+ scalar_type sinPhi = sinTheta==0.0 ? 0.0 : clamp <scalar_type>(V.y/sinTheta, -1.0 , 1.0 );
285
+ //rotate
286
+ scalar_type tmp = cosPhi*slope.x - sinPhi*slope.y;
287
+ slope.y = sinPhi*slope.x + cosPhi*slope.y;
288
+ slope.x = tmp;
289
+
290
+ //unstretch
291
+ slope = vector2_type (A.x,A.y)*slope;
292
+
293
+ return nbl::hlsl::normalize<vector3_type>(vector3_type (-slope, 1.0 ));
294
+ }
295
+ };
220
296
}
221
297
222
298
template<typename T, bool IsAnisotropic, MicrofacetTransformTypes reflect_refract NBL_STRUCT_CONSTRAINABLE>
@@ -258,6 +334,11 @@ struct Beckmann<T,false,MTT_REFLECT NBL_PARTIAL_REQ_BOT(concepts::FloatingPointS
258
334
return g2_query;
259
335
}
260
336
337
+ vector <T, 3 > generateH (const vector3_type localV, const vector2_type u)
338
+ {
339
+ return impl::BeckmannGenerateH<scalar_type>::__call (__base.A, localV, u);
340
+ }
341
+
261
342
template<class LS, class Interaction, class MicrofacetCache NBL_FUNC_REQUIRES (LightSample<LS> && surface_interactions::Isotropic<Interaction> && ReadableIsotropicMicrofacetCache<MicrofacetCache>)
262
343
quant_type D (NBL_CONST_REF_ARG (quant_query_type) quant_query, NBL_CONST_REF_ARG (LS) _sample, NBL_CONST_REF_ARG (Interaction) interaction, NBL_CONST_REF_ARG (MicrofacetCache) cache)
263
344
{
@@ -323,6 +404,11 @@ struct Beckmann<T,true,MTT_REFLECT NBL_PARTIAL_REQ_BOT(concepts::FloatingPointSc
323
404
return g2_query;
324
405
}
325
406
407
+ vector <T, 3 > generateH (const vector3_type localV, const vector2_type u)
408
+ {
409
+ return impl::BeckmannGenerateH<scalar_type>::__call (__base.A, localV, u);
410
+ }
411
+
326
412
template<class LS, class Interaction, class MicrofacetCache NBL_FUNC_REQUIRES (LightSample<LS> && surface_interactions::Anisotropic <Interaction> && AnisotropicMicrofacetCache<MicrofacetCache>)
327
413
quant_type D (NBL_CONST_REF_ARG (quant_query_type) quant_query, NBL_CONST_REF_ARG (LS) _sample, NBL_CONST_REF_ARG (Interaction) interaction, NBL_CONST_REF_ARG (MicrofacetCache) cache)
328
414
{
@@ -391,6 +477,11 @@ struct Beckmann<T,false,reflect_refract NBL_PARTIAL_REQ_BOT(concepts::FloatingPo
391
477
return g2_query;
392
478
}
393
479
480
+ vector <T, 3 > generateH (const vector3_type localV, const vector2_type u)
481
+ {
482
+ return impl::BeckmannGenerateH<scalar_type>::__call (__base.A, localV, u);
483
+ }
484
+
394
485
template<class LS, class Interaction, class MicrofacetCache NBL_FUNC_REQUIRES (LightSample<LS> && surface_interactions::Isotropic<Interaction> && ReadableIsotropicMicrofacetCache<MicrofacetCache>)
395
486
quant_type D (NBL_CONST_REF_ARG (quant_query_type) quant_query, NBL_CONST_REF_ARG (LS) _sample, NBL_CONST_REF_ARG (Interaction) interaction, NBL_CONST_REF_ARG (MicrofacetCache) cache)
396
487
{
@@ -458,6 +549,11 @@ struct Beckmann<T,true,reflect_refract NBL_PARTIAL_REQ_BOT(concepts::FloatingPoi
458
549
return g2_query;
459
550
}
460
551
552
+ vector <T, 3 > generateH (const vector3_type localV, const vector2_type u)
553
+ {
554
+ return impl::BeckmannGenerateH<scalar_type>::__call (__base.A, localV, u);
555
+ }
556
+
461
557
template<class LS, class Interaction, class MicrofacetCache NBL_FUNC_REQUIRES (LightSample<LS> && surface_interactions::Anisotropic <Interaction> && AnisotropicMicrofacetCache<MicrofacetCache>)
462
558
quant_type D (NBL_CONST_REF_ARG (quant_query_type) quant_query, NBL_CONST_REF_ARG (LS) _sample, NBL_CONST_REF_ARG (Interaction) interaction, NBL_CONST_REF_ARG (MicrofacetCache) cache)
463
559
{
0 commit comments