@@ -596,7 +596,7 @@ bool closestHitProgram(in uint depth, in uint _sample, inout Ray_t ray, inout nb
596
596
if (BSDFNode_isNotDiffuse(bsdf))
597
597
{
598
598
if (ray._payload.hasDiffuse)
599
- return true ;
599
+ return false ;
600
600
}
601
601
else
602
602
ray._payload.hasDiffuse = true;
@@ -613,47 +613,55 @@ bool closestHitProgram(in uint depth, in uint _sample, inout Ray_t ray, inout nb
613
613
const float monochromeEta = dot (throughputCIE_Y,BSDFNode_getEta(bsdf)[0 ])/ (throughputCIE_Y.r+ throughputCIE_Y.g+ throughputCIE_Y.b);
614
614
615
615
// do NEE
616
- const float neeProbability = 1.0 ;// BSDFNode_getNEEProb(bsdf);
616
+ #ifndef NEE_ONLY
617
+ // to turn off NEE, set this to 0
618
+ const float neeProbability = BSDFNode_getNEEProb(bsdf);
617
619
float rcpChoiceProb;
618
620
if (! nbl_glsl_partitionRandVariable(neeProbability,epsilon[0 ].z,rcpChoiceProb))
619
621
{
622
+ #endif
620
623
vec3 neeContrib; float lightPdf, t;
621
624
nbl_glsl_LightSample nee_sample = nbl_glsl_light_generate_and_remainder_and_pdf(
622
625
neeContrib, lightPdf, t,
623
626
intersection, interaction,
624
627
isBSDF, epsilon[0 ], depth
625
628
);
626
- // We don't allow non watertight transmitters in this renderer
629
+ // We don't allow non watertight transmitters in this renderer & scene, one cannot reach a light from the backface (optimization)
627
630
bool validPath = nee_sample.NdotL> nbl_glsl_FLT_MIN;
628
631
// but if we allowed non-watertight transmitters (single water surface), it would make sense just to apply this line by itself
629
632
nbl_glsl_AnisotropicMicrofacetCache _cache;
630
633
validPath = validPath && nbl_glsl_calcAnisotropicMicrofacetCache(_cache, interaction, nee_sample, monochromeEta);
634
+ // infinite PDF would mean a point light or a thin line, but our lights have finite radiance per steradian (area lights)
631
635
if (lightPdf< nbl_glsl_FLT_MAX)
632
636
{
633
- if (any (isnan(nee_sample.L)))
634
- ray._payload.accumulation += vec3 (1000 .f,0 .f,0 .f);
635
- else
636
- if (all (equal (vec3 (69 .f),nee_sample.L)))
637
- ray._payload.accumulation += vec3 (0 .f,1000 .f,0 .f);
638
- else
639
- if (validPath)
640
- {
641
- float bsdfPdf;
642
- neeContrib *= nbl_glsl_bsdf_cos_remainder_and_pdf(bsdfPdf,nee_sample,interaction,bsdf,monochromeEta,_cache)* throughput;
643
- const float otherGenOverChoice = bsdfPdf* rcpChoiceProb;
637
+ // debug coloring
638
+ if (any (isnan(nee_sample.L)))
639
+ ray._payload.accumulation += vec3 (1000 .f,0 .f,0 .f);
640
+ else
641
+ if (all (equal (vec3 (69 .f),nee_sample.L)))
642
+ ray._payload.accumulation += vec3 (0 .f,1000 .f,0 .f);
643
+ else
644
+ if (validPath) // normally one would check for a valid path first, because zero solid angle light is less likely
645
+ {
646
+ float bsdfPdf;
647
+ // this is kinda the wrong fuction to use, we should use eval_and_pdf instead (because eval returns 0 for directions accidentally coincident with dirac delta)
648
+ neeContrib *= nbl_glsl_bsdf_cos_remainder_and_pdf(bsdfPdf,nee_sample,interaction,bsdf,monochromeEta,_cache)* throughput;
649
+ // this is why we need to multiply `bsdfPdf` back in, and why we have a check for the BxDF PDF not being INF
644
650
#ifndef NEE_ONLY
645
- const float otherGenOverLightAndChoice = otherGenOverChoice/ lightPdf;
646
- neeContrib *= otherGenOverChoice/ (1 .f+ otherGenOverLightAndChoice* otherGenOverLightAndChoice); // MIS weight
651
+ const float otherGenOverChoice = bsdfPdf* rcpChoiceProb;
652
+ const float otherGenOverLightAndChoice = otherGenOverChoice/ lightPdf;
653
+ // MIS weight (TODO: is it correct? should `otherGenOverLightAndChoice` contain the `rcpChoiceProb` ?)
654
+ neeContrib *= otherGenOverChoice/ (1 .f+ otherGenOverLightAndChoice* otherGenOverLightAndChoice);
647
655
#else
648
- neeContrib *= otherGenOverChoice ;
656
+ neeContrib *= bsdfPdf ;
649
657
#endif
650
- if (bsdfPdf< nbl_glsl_FLT_MAX && getLuma(neeContrib)> lumaContributionThreshold && traceRay(t,intersection+ nee_sample.L* t* getStartTolerance(depth),nee_sample.L)==-1 )
651
- ray._payload.accumulation += neeContrib;
652
- }}
658
+ if (bsdfPdf< nbl_glsl_FLT_MAX && getLuma(neeContrib)> lumaContributionThreshold && traceRay(t,intersection+ nee_sample.L* t* getStartTolerance(depth),nee_sample.L)==-1 )
659
+ ray._payload.accumulation += neeContrib;
660
+ }
661
+ }
662
+ #ifndef NEE_ONLY
653
663
}
654
- #if NEE_ONLY
655
- return false;
656
- #endif
664
+
657
665
// sample BSDF
658
666
float bsdfPdf; vec3 bsdfSampleL;
659
667
{
@@ -682,6 +690,7 @@ bool closestHitProgram(in uint depth, in uint _sample, inout Ray_t ray, inout nb
682
690
#endif
683
691
return true;
684
692
}
693
+ #endif
685
694
}
686
695
return false;
687
696
}
0 commit comments