Skip to content

Commit d438360

Browse files
committed
reverted ggx ndf to use optimizations
1 parent c587820 commit d438360

File tree

2 files changed

+75
-19
lines changed

2 files changed

+75
-19
lines changed

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

Lines changed: 73 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ struct SGGXDG1Query
2525
using scalar_type = T;
2626

2727
scalar_type getNdf() NBL_CONST_MEMBER_FUNC { return ndf; }
28-
scalar_type getG1() NBL_CONST_MEMBER_FUNC { return G1; }
28+
scalar_type getG1over2NdotV() NBL_CONST_MEMBER_FUNC { return G1_over_2NdotV; }
2929

3030
scalar_type ndf;
31-
scalar_type G1;
31+
scalar_type G1_over_2NdotV;
3232
};
3333

3434
template<typename T>
@@ -78,7 +78,7 @@ struct GGXCommon<T,false NBL_PARTIAL_REQ_BOT(concepts::FloatingPointScalar<T>) >
7878

7979
scalar_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query)
8080
{
81-
return query.getNdf() * query.getG1();
81+
return scalar_type(0.5) * query.getNdf() * query.getG1over2NdotV();
8282
}
8383

8484
scalar_type devsh_part(scalar_type NdotX2)
@@ -166,6 +166,8 @@ struct GGXCommon<T,true NBL_PARTIAL_REQ_BOT(concepts::FloatingPointScalar<T>) >
166166
return numbers::inv_pi<scalar_type> / (a2 * denom * denom);
167167
}
168168

169+
// TODO: potential idea for making GGX spin using covariance matrix of sorts: https://www.desmos.com/3d/weq2ginq9o
170+
169171
// burley
170172
scalar_type D(scalar_type a2, scalar_type TdotH, scalar_type BdotH, scalar_type NdotH, scalar_type anisotropy)
171173
{
@@ -314,7 +316,7 @@ struct GGX<T,false,MTT_REFLECT NBL_PARTIAL_REQ_BOT(concepts::FloatingPointScalar
314316
dg1_query_type dg1_query;
315317
dg1_query.ndf = __base.template D<MicrofacetCache>(cache);
316318
scalar_type clampedNdotV = interaction.getNdotV();
317-
dg1_query.G1 = scalar_type(2.0) * clampedNdotV * __base.G1_wo_numerator(clampedNdotV, interaction.getNdotV2());
319+
dg1_query.G1_over_2NdotV = __base.G1_wo_numerator(clampedNdotV, interaction.getNdotV2());
318320
return dg1_query;
319321
}
320322
template<class LS, class Interaction NBL_FUNC_REQUIRES(LightSample<LS> && surface_interactions::Isotropic<Interaction>)
@@ -336,20 +338,26 @@ struct GGX<T,false,MTT_REFLECT NBL_PARTIAL_REQ_BOT(concepts::FloatingPointScalar
336338
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)
337339
{
338340
scalar_type d = __base.template D<MicrofacetCache>(cache);
339-
return createDualMeasureQuantity<T>(d, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX));
341+
quant_type dmq;
342+
dmq.microfacetMeasure = d;
343+
dmq.projectedLightMeasure = d * _sample.getNdotL(BxDFClampMode::BCM_MAX);
344+
return dmq;
340345
}
341346

342347
template<class LS, class Interaction NBL_FUNC_REQUIRES(LightSample<LS> && surface_interactions::Isotropic<Interaction>)
343348
quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction)
344349
{
345350
scalar_type dg1 = __base.DG1(query);
346-
return createDualMeasureQuantity<T>(dg1, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX));
351+
quant_type dmq;
352+
dmq.microfacetMeasure = dg1;
353+
dmq.projectedLightMeasure = dg1;// TODO: figure this out * _sample.getNdotL(BxDFClampMode::BCM_MAX);
354+
return dmq;
347355
}
348356

349357
template<class LS, class Interaction NBL_FUNC_REQUIRES(LightSample<LS> && surface_interactions::Isotropic<Interaction>)
350358
scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction)
351359
{
352-
return __base.template correlated<LS, Interaction>(query, _sample, interaction);
360+
return __base.template correlated_wo_numerator<LS, Interaction>(query, _sample, interaction);
353361
}
354362

355363
template<class LS, class Interaction, class MicrofacetCache NBL_FUNC_REQUIRES(LightSample<LS> && surface_interactions::Isotropic<Interaction> && ReadableIsotropicMicrofacetCache<MicrofacetCache>)
@@ -387,7 +395,7 @@ struct GGX<T,true,MTT_REFLECT NBL_PARTIAL_REQ_BOT(concepts::FloatingPointScalar<
387395
dg1_query_type dg1_query;
388396
dg1_query.ndf = __base.template D<MicrofacetCache>(cache);
389397
scalar_type clampedNdotV = interaction.getNdotV();
390-
dg1_query.G1 = scalar_type(2.0) * clampedNdotV * __base.G1_wo_numerator(clampedNdotV, interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2());
398+
dg1_query.G1_over_2NdotV = __base.G1_wo_numerator(clampedNdotV, interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2());
391399
return dg1_query;
392400
}
393401
template<class LS, class Interaction NBL_FUNC_REQUIRES(LightSample<LS> && surface_interactions::Anisotropic<Interaction>)
@@ -409,20 +417,26 @@ struct GGX<T,true,MTT_REFLECT NBL_PARTIAL_REQ_BOT(concepts::FloatingPointScalar<
409417
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)
410418
{
411419
scalar_type d = __base.template D<MicrofacetCache>(cache);
412-
return createDualMeasureQuantity<T>(d, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX));
420+
quant_type dmq;
421+
dmq.microfacetMeasure = d;
422+
dmq.projectedLightMeasure = d * _sample.getNdotL(BxDFClampMode::BCM_MAX);
423+
return dmq;
413424
}
414425

415426
template<class LS, class Interaction NBL_FUNC_REQUIRES(LightSample<LS> && surface_interactions::Anisotropic<Interaction>)
416427
quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction)
417428
{
418429
scalar_type dg1 = __base.DG1(query);
419-
return createDualMeasureQuantity<T>(dg1, interaction.getNdotV(BxDFClampMode::BCM_MAX), _sample.getNdotL(BxDFClampMode::BCM_MAX));
430+
quant_type dmq;
431+
dmq.microfacetMeasure = dg1;
432+
dmq.projectedLightMeasure = dg1;// TODO: figure this out * _sample.getNdotL(BxDFClampMode::BCM_MAX);
433+
return dmq;
420434
}
421435

422436
template<class LS, class Interaction NBL_FUNC_REQUIRES(LightSample<LS> && surface_interactions::Anisotropic<Interaction>)
423437
scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction)
424438
{
425-
return __base.template correlated<LS, Interaction>(query, _sample, interaction);
439+
return __base.template correlated_wo_numerator<LS, Interaction>(query, _sample, interaction);
426440
}
427441

428442
template<class LS, class Interaction, class MicrofacetCache NBL_FUNC_REQUIRES(LightSample<LS> && surface_interactions::Anisotropic<Interaction> && AnisotropicMicrofacetCache<MicrofacetCache>)
@@ -463,7 +477,7 @@ struct GGX<T,false,reflect_refract NBL_PARTIAL_REQ_BOT(concepts::FloatingPointSc
463477
dg1_query_type dg1_query;
464478
dg1_query.ndf = __base.template D<MicrofacetCache>(cache);
465479
scalar_type clampedNdotV = interaction.getNdotV(BxDFClampMode::BCM_ABS);
466-
dg1_query.G1 = scalar_type(2.0) * clampedNdotV * __base.G1_wo_numerator(clampedNdotV, interaction.getNdotV2());
480+
dg1_query.G1_over_2NdotV = __base.G1_wo_numerator(clampedNdotV, interaction.getNdotV2());
467481
return dg1_query;
468482
}
469483
template<class LS, class Interaction NBL_FUNC_REQUIRES(LightSample<LS> && surface_interactions::Isotropic<Interaction>)
@@ -485,20 +499,40 @@ struct GGX<T,false,reflect_refract NBL_PARTIAL_REQ_BOT(concepts::FloatingPointSc
485499
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)
486500
{
487501
scalar_type d = __base.template D<MicrofacetCache>(cache);
488-
return createDualMeasureQuantity<T, reflect_refract>(d, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH());
502+
quant_type dmq;
503+
dmq.microfacetMeasure = d; // note: microfacetMeasure/2NdotV
504+
505+
const scalar_type VdotHLdotH = quant_query.getVdotHLdotH();
506+
const scalar_type VdotH_etaLdotH = quant_query.getVdotH_etaLdotH();
507+
const bool transmitted = reflect_refract==MTT_REFRACT || (reflect_refract!=MTT_REFLECT && VdotHLdotH < scalar_type(0.0));
508+
scalar_type NdotL_over_denominator = _sample.getNdotL(BxDFClampMode::BCM_ABS);
509+
if (transmitted)
510+
NdotL_over_denominator *= -scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH);
511+
dmq.projectedLightMeasure = d * NdotL_over_denominator;
512+
return dmq;
489513
}
490514

491515
template<class LS, class Interaction NBL_FUNC_REQUIRES(LightSample<LS> && surface_interactions::Isotropic<Interaction>)
492516
quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction)
493517
{
494518
scalar_type dg1 = __base.DG1(query);
495-
return createDualMeasureQuantity<T, reflect_refract>(dg1, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH());
519+
quant_type dmq;
520+
dmq.microfacetMeasure = dg1; // note: microfacetMeasure/2NdotV
521+
522+
const scalar_type VdotHLdotH = quant_query.getVdotHLdotH();
523+
const scalar_type VdotH_etaLdotH = quant_query.getVdotH_etaLdotH();
524+
const bool transmitted = reflect_refract==MTT_REFRACT || (reflect_refract!=MTT_REFLECT && VdotHLdotH < scalar_type(0.0));
525+
scalar_type NdotL_over_denominator = _sample.getNdotL(BxDFClampMode::BCM_ABS);
526+
if (transmitted)
527+
NdotL_over_denominator *= -scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH);
528+
dmq.projectedLightMeasure = dg1;// TODO: figure this out * NdotL_over_denominator;
529+
return dmq;
496530
}
497531

498532
template<class LS, class Interaction NBL_FUNC_REQUIRES(LightSample<LS> && surface_interactions::Isotropic<Interaction>)
499533
scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction)
500534
{
501-
return __base.template correlated<LS, Interaction>(query, _sample, interaction);
535+
return __base.template correlated_wo_numerator<LS, Interaction>(query, _sample, interaction);
502536
}
503537

504538
template<class LS, class Interaction, class MicrofacetCache NBL_FUNC_REQUIRES(LightSample<LS> && surface_interactions::Isotropic<Interaction> && ReadableIsotropicMicrofacetCache<MicrofacetCache>)
@@ -538,7 +572,7 @@ struct GGX<T,true,reflect_refract NBL_PARTIAL_REQ_BOT(concepts::FloatingPointSca
538572
dg1_query_type dg1_query;
539573
dg1_query.ndf = __base.template D<MicrofacetCache>(cache);
540574
scalar_type clampedNdotV = interaction.getNdotV(BxDFClampMode::BCM_ABS);
541-
dg1_query.G1 = scalar_type(2.0) * clampedNdotV * __base.G1_wo_numerator(clampedNdotV, interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2());
575+
dg1_query.G1_over_2NdotV = __base.G1_wo_numerator(clampedNdotV, interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2());
542576
return dg1_query;
543577
}
544578
template<class LS, class Interaction NBL_FUNC_REQUIRES(LightSample<LS> && surface_interactions::Anisotropic<Interaction>)
@@ -560,20 +594,40 @@ struct GGX<T,true,reflect_refract NBL_PARTIAL_REQ_BOT(concepts::FloatingPointSca
560594
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)
561595
{
562596
scalar_type d = __base.template D<MicrofacetCache>(cache);
563-
return createDualMeasureQuantity<T, reflect_refract>(d, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH());
597+
quant_type dmq;
598+
dmq.microfacetMeasure = d; // note: microfacetMeasure/2NdotV
599+
600+
const scalar_type VdotHLdotH = quant_query.getVdotHLdotH();
601+
const scalar_type VdotH_etaLdotH = quant_query.getVdotH_etaLdotH();
602+
const bool transmitted = reflect_refract==MTT_REFRACT || (reflect_refract!=MTT_REFLECT && VdotHLdotH < scalar_type(0.0));
603+
scalar_type NdotL_over_denominator = _sample.getNdotL(BxDFClampMode::BCM_ABS);
604+
if (transmitted)
605+
NdotL_over_denominator *= -scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH);
606+
dmq.projectedLightMeasure = d * NdotL_over_denominator;
607+
return dmq;
564608
}
565609

566610
template<class LS, class Interaction NBL_FUNC_REQUIRES(LightSample<LS> && surface_interactions::Anisotropic<Interaction>)
567611
quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction)
568612
{
569613
scalar_type dg1 = __base.DG1(query);
570-
return createDualMeasureQuantity<T, reflect_refract>(dg1, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query.getVdotHLdotH(), quant_query.getVdotH_etaLdotH());
614+
quant_type dmq;
615+
dmq.microfacetMeasure = dg1; // note: microfacetMeasure/2NdotV
616+
617+
const scalar_type VdotHLdotH = quant_query.getVdotHLdotH();
618+
const scalar_type VdotH_etaLdotH = quant_query.getVdotH_etaLdotH();
619+
const bool transmitted = reflect_refract==MTT_REFRACT || (reflect_refract!=MTT_REFLECT && VdotHLdotH < scalar_type(0.0));
620+
scalar_type NdotL_over_denominator = _sample.getNdotL(BxDFClampMode::BCM_ABS);
621+
if (transmitted)
622+
NdotL_over_denominator *= -scalar_type(4.0) * VdotHLdotH / (VdotH_etaLdotH * VdotH_etaLdotH);
623+
dmq.projectedLightMeasure = dg1;// TODO: figure this out * NdotL_over_denominator;
624+
return dmq;
571625
}
572626

573627
template<class LS, class Interaction NBL_FUNC_REQUIRES(LightSample<LS> && surface_interactions::Anisotropic<Interaction>)
574628
scalar_type correlated(NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction)
575629
{
576-
return __base.template correlated<LS, Interaction>(query, _sample, interaction);
630+
return __base.template correlated_wo_numerator<LS, Interaction>(query, _sample, interaction);
577631
}
578632

579633
template<class LS, class Interaction, class MicrofacetCache NBL_FUNC_REQUIRES(LightSample<LS> && surface_interactions::Anisotropic<Interaction> && AnisotropicMicrofacetCache<MicrofacetCache>)

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ struct createDualMeasureQuantity_helper
4242

4343
static SDualMeasureQuant<T> __call(const T microfacetMeasure, scalar_type clampedNdotV, scalar_type clampedNdotL, scalar_type VdotHLdotH, scalar_type VdotH_etaLdotH)
4444
{
45+
assert(clampedNdotV >= scalar_type(0.0) && clampedNdotL >= scalar_type(0.0));
4546
SDualMeasureQuant<T> retval;
4647
retval.microfacetMeasure = microfacetMeasure;
4748
// do constexpr booleans first so optimizer picks up this and short circuits
@@ -56,6 +57,7 @@ struct createDualMeasureQuantity_helper
5657
};
5758
}
5859

60+
// specialMeasure meaning the measure defined by the specialization of createDualMeasureQuantity_helper; note that GGX redefines it somewhat
5961
template<typename T>
6062
SDualMeasureQuant<T> createDualMeasureQuantity(const T specialMeasure, typename vector_traits<T>::scalar_type clampedNdotV, typename vector_traits<T>::scalar_type clampedNdotL)
6163
{

0 commit comments

Comments
 (0)