Skip to content

Commit e7bc784

Browse files
committed
moved generate H into ndfs, generate impl in cook torrance base
1 parent 4eeacf1 commit e7bc784

File tree

3 files changed

+199
-2
lines changed

3 files changed

+199
-2
lines changed

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

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,25 @@ struct SCookTorrance<Config, N, F, false NBL_PARTIAL_REQ_BOT(config_concepts::Mi
8585
return hlsl::promote<spectral_type>(0.0);
8686
}
8787

88-
// TODO: generate
88+
sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache)
89+
{
90+
anisocache_type anisocache;
91+
sample_type s = generate(anisotropic_interaction_type::create(interaction), u, anisocache);
92+
cache = anisocache.iso_cache;
93+
return s;
94+
}
95+
sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(anisocache_type) cache)
96+
{
97+
const vector3_type localV = interaction.getTangentSpaceV();
98+
const vector3_type H = ndf.generateH(localV, u);
99+
100+
cache = anisocache_type::createForReflection(localV, H);
101+
ray_dir_info_type localL;
102+
bxdf::Reflect<scalar_type> r = bxdf::Reflect<scalar_type>::create(localV, H);
103+
localL = localL.reflect(r);
104+
105+
return sample_type::createFromTangentSpace(localL, interaction.getFromTangentSpace());
106+
}
89107

90108
scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache)
91109
{
@@ -204,7 +222,40 @@ struct SCookTorrance<Config, N, F, true NBL_PARTIAL_REQ_BOT(config_concepts::Mic
204222
return hlsl::promote<spectral_type>(__base.fresnel(hlsl::abs(cache.getVdotH()))[0]) * DG;
205223
}
206224

207-
// TODO: generate
225+
sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(isocache_type) cache)
226+
{
227+
anisocache_type anisocache;
228+
sample_type s = generate(anisotropic_interaction_type::create(interaction), u, anisocache);
229+
cache = anisocache.iso_cache;
230+
return s;
231+
}
232+
sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(anisocache_type) cache)
233+
{
234+
const vector3_type localV = interaction.getTangentSpaceV();
235+
236+
fresnel::OrientedEtas<monochrome_type> orientedEta = __base.fresnel.orientedEta;
237+
fresnel::OrientedEtaRcps<monochrome_type> rcpEta = orientedEta.getReciprocals();
238+
239+
const vector3_type upperHemisphereV = hlsl::mix(localV, -localV, interaction.getNdotV() < scalar_type(0.0));
240+
const vector3_type H = ndf.generateH(upperHemisphereV, u.xy);
241+
242+
const scalar_type reflectance = __base.fresnel(hlsl::abs(cache.getVdotH()))[0];
243+
244+
scalar_type rcpChoiceProb;
245+
scalar_type z = u.z;
246+
bool transmitted = math::partitionRandVariable(reflectance, z, rcpChoiceProb);
247+
248+
cache = anisocache_type::createForReflection(localV, H);
249+
250+
Refract<scalar_type> r = Refract<scalar_type>::create(localV, H);
251+
cache.iso_cache.LdotH = hlsl::mix(cache.getVdotH(), r.getNdotT(rcpEta.value2[0]), transmitted);
252+
ray_dir_info_type localL;
253+
bxdf::ReflectRefract<scalar_type> rr;
254+
rr.refract = r;
255+
localL = localL.reflectRefract(rr, transmitted, rcpEta.value[0]);
256+
257+
return sample_type::createFromTangentSpace(localL, interaction.getFromTangentSpace());
258+
}
208259

209260
scalar_type pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache)
210261
{

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

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,82 @@ struct BeckmannCommon<T,true NBL_PARTIAL_REQ_BOT(concepts::FloatingPointScalar<T
217217
scalar_type ax2;
218218
scalar_type ay2;
219219
};
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+
};
220296
}
221297

222298
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
258334
return g2_query;
259335
}
260336

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+
261342
template<class LS, class Interaction, class MicrofacetCache NBL_FUNC_REQUIRES(LightSample<LS> && surface_interactions::Isotropic<Interaction> && ReadableIsotropicMicrofacetCache<MicrofacetCache>)
262343
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)
263344
{
@@ -323,6 +404,11 @@ struct Beckmann<T,true,MTT_REFLECT NBL_PARTIAL_REQ_BOT(concepts::FloatingPointSc
323404
return g2_query;
324405
}
325406

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+
326412
template<class LS, class Interaction, class MicrofacetCache NBL_FUNC_REQUIRES(LightSample<LS> && surface_interactions::Anisotropic<Interaction> && AnisotropicMicrofacetCache<MicrofacetCache>)
327413
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)
328414
{
@@ -391,6 +477,11 @@ struct Beckmann<T,false,reflect_refract NBL_PARTIAL_REQ_BOT(concepts::FloatingPo
391477
return g2_query;
392478
}
393479

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+
394485
template<class LS, class Interaction, class MicrofacetCache NBL_FUNC_REQUIRES(LightSample<LS> && surface_interactions::Isotropic<Interaction> && ReadableIsotropicMicrofacetCache<MicrofacetCache>)
395486
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)
396487
{
@@ -458,6 +549,11 @@ struct Beckmann<T,true,reflect_refract NBL_PARTIAL_REQ_BOT(concepts::FloatingPoi
458549
return g2_query;
459550
}
460551

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+
461557
template<class LS, class Interaction, class MicrofacetCache NBL_FUNC_REQUIRES(LightSample<LS> && surface_interactions::Anisotropic<Interaction> && AnisotropicMicrofacetCache<MicrofacetCache>)
462558
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)
463559
{

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

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,36 @@ struct GGXCommon<T,true NBL_PARTIAL_REQ_BOT(concepts::FloatingPointScalar<T>) >
296296
scalar_type ay2;
297297
scalar_type a2;
298298
};
299+
300+
template<typename T>
301+
struct GGXGenerateH
302+
{
303+
using scalar_type = T;
304+
using vector2_type = vector<T, 2>;
305+
using vector3_type = vector<T, 3>;
306+
307+
vector3_type __call(const vector2_type A, const vector3_type localV, const vector2_type u)
308+
{
309+
vector3_type V = nbl::hlsl::normalize<vector3_type>(vector3_type(A.x*localV.x, A.y*localV.y, localV.z));//stretch view vector so that we're sampling as if roughness=1.0
310+
311+
scalar_type lensq = V.x*V.x + V.y*V.y;
312+
vector3_type T1 = lensq > 0.0 ? vector3_type(-V.y, V.x, 0.0) * rsqrt<scalar_type>(lensq) : vector3_type(1.0,0.0,0.0);
313+
vector3_type T2 = cross<scalar_type>(V,T1);
314+
315+
scalar_type r = sqrt<scalar_type>(u.x);
316+
scalar_type phi = 2.0 * numbers::pi<scalar_type> * u.y;
317+
scalar_type t1 = r * cos<scalar_type>(phi);
318+
scalar_type t2 = r * sin<scalar_type>(phi);
319+
scalar_type s = 0.5 * (1.0 + V.z);
320+
t2 = (1.0 - s)*sqrt<scalar_type>(1.0 - t1*t1) + s*t2;
321+
322+
//reprojection onto hemisphere
323+
//TODO try it wothout the max(), not sure if -t1*t1-t2*t2>-1.0
324+
vector3_type H = t1*T1 + t2*T2 + sqrt<scalar_type>(max<scalar_type>(0.0, 1.0-t1*t1-t2*t2))*V;
325+
//unstretch
326+
return nbl::hlsl::normalize<vector3_type>(vector3_type(A.x*H.x, A.y*H.y, H.z));
327+
}
328+
};
299329
}
300330

301331
template<typename T, bool IsAnisotropic, MicrofacetTransformTypes reflect_refract NBL_STRUCT_CONSTRAINABLE>
@@ -338,6 +368,11 @@ struct GGX<T,false,MTT_REFLECT NBL_PARTIAL_REQ_BOT(concepts::FloatingPointScalar
338368
return g2_query;
339369
}
340370

371+
vector<T, 3> generateH(const vector3_type localV, const vector2_type u)
372+
{
373+
return impl::GGXGenerateH<scalar_type>::__call(__base.A, localV, u);
374+
}
375+
341376
template<class LS, class Interaction, class MicrofacetCache NBL_FUNC_REQUIRES(LightSample<LS> && surface_interactions::Isotropic<Interaction> && ReadableIsotropicMicrofacetCache<MicrofacetCache>)
342377
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)
343378
{
@@ -404,6 +439,11 @@ struct GGX<T,true,MTT_REFLECT NBL_PARTIAL_REQ_BOT(concepts::FloatingPointScalar<
404439
return g2_query;
405440
}
406441

442+
vector<T, 3> generateH(const vector3_type localV, const vector2_type u)
443+
{
444+
return impl::GGXGenerateH<scalar_type>::__call(__base.A, localV, u);
445+
}
446+
407447
template<class LS, class Interaction, class MicrofacetCache NBL_FUNC_REQUIRES(LightSample<LS> && surface_interactions::Anisotropic<Interaction> && AnisotropicMicrofacetCache<MicrofacetCache>)
408448
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)
409449
{
@@ -473,6 +513,11 @@ struct GGX<T,false,reflect_refract NBL_PARTIAL_REQ_BOT(concepts::FloatingPointSc
473513
return g2_query;
474514
}
475515

516+
vector<T, 3> generateH(const vector3_type localV, const vector2_type u)
517+
{
518+
return impl::GGXGenerateH<scalar_type>::__call(__base.A, localV, u);
519+
}
520+
476521
template<class LS, class Interaction, class MicrofacetCache NBL_FUNC_REQUIRES(LightSample<LS> && surface_interactions::Isotropic<Interaction> && ReadableIsotropicMicrofacetCache<MicrofacetCache>)
477522
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)
478523
{
@@ -541,6 +586,11 @@ struct GGX<T,true,reflect_refract NBL_PARTIAL_REQ_BOT(concepts::FloatingPointSca
541586
return g2_query;
542587
}
543588

589+
vector<T, 3> generateH(const vector3_type localV, const vector2_type u)
590+
{
591+
return impl::GGXGenerateH<scalar_type>::__call(__base.A, localV, u);
592+
}
593+
544594
template<class LS, class Interaction, class MicrofacetCache NBL_FUNC_REQUIRES(LightSample<LS> && surface_interactions::Anisotropic<Interaction> && AnisotropicMicrofacetCache<MicrofacetCache>)
545595
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)
546596
{

0 commit comments

Comments
 (0)