Skip to content

Commit 4a0d652

Browse files
Prototype of PDF computation for Proj Solid Angle sampling
1 parent 8cd651c commit 4a0d652

File tree

2 files changed

+136
-188
lines changed

2 files changed

+136
-188
lines changed

examples_tests/42.FragmentShaderPathTracer/common.glsl

Lines changed: 16 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// basic settings
2-
#define MAX_DEPTH 6
3-
#define SAMPLES 16
2+
#define MAX_DEPTH 2
3+
#define SAMPLES 128
44

55
// firefly and variance reduction techniques
66
//#define KILL_DIFFUSE_SPECULAR_PATHS
@@ -81,7 +81,6 @@ float Sphere_getSolidAngle(in Sphere sphere, in vec3 origin)
8181
return Sphere_getSolidAngle_impl(cosThetaMax);
8282
}
8383

84-
#define TRIANGLE_METHOD 0 // 0 area sampling, 1 solid angle sampling, 2 approximate projected solid angle sampling
8584
struct Triangle
8685
{
8786
vec3 vertex0;
@@ -147,6 +146,10 @@ uint BSDFNode_getType(in BSDFNode node)
147146
{
148147
return bitfieldExtract(node.data[0].w,OP_BITS_OFFSET,OP_BITS_SIZE);
149148
}
149+
bool BSDFNode_isBSDF(in BSDFNode node)
150+
{
151+
return BSDFNode_getType(node)==DIELECTRIC_OP;
152+
}
150153
bool BSDFNode_isNotDiffuse(in BSDFNode node)
151154
{
152155
return BSDFNode_getType(node)!=DIFFUSE_OP;
@@ -176,7 +179,7 @@ float BSDFNode_getMISWeight(in BSDFNode bsdf)
176179
{
177180
const float alpha = BSDFNode_getRoughness(bsdf);
178181
const bool notDiffuse = BSDFNode_isNotDiffuse(bsdf);
179-
const float DIFFUSE_MIS_WEIGHT = 0.5;
182+
const float DIFFUSE_MIS_WEIGHT = 0.0;
180183
return notDiffuse ? mix(1.0,DIFFUSE_MIS_WEIGHT,alpha):DIFFUSE_MIS_WEIGHT; // TODO: test alpha*alpha
181184
}
182185

@@ -232,6 +235,10 @@ struct ImmutableRay_t
232235
float maxT;
233236
vec3 direction;
234237
int typeDepthSampleIx;
238+
#ifdef TRIANGLE_METHOD
239+
vec3 normalAtOrigin;
240+
bool wasBSDFAtOrigin;
241+
#endif
235242
};
236243
struct MutableRay_t
237244
{
@@ -304,7 +311,7 @@ void missProgram()
304311
vec2 uv = SampleSphericalMap(rayStack[stackPtr]._immutable.direction);
305312
finalContribution *= textureLod(envMap, uv, 0.0).rgb;
306313
#else
307-
const vec3 kConstantEnvLightRadiance = vec3(0.15, 0.21, 0.3);
314+
const vec3 kConstantEnvLightRadiance = vec3(0.0);// 0.15, 0.21, 0.3);
308315
finalContribution *= kConstantEnvLightRadiance;
309316
#endif
310317
}
@@ -436,120 +443,6 @@ vec3 rand3d(in uint protoDimension, in uint _sample, inout irr_glsl_xoroshiro64s
436443
return vec3(seqVal)*uintBitsToFloat(0x2f800004u);
437444
}
438445

439-
#if 0
440-
void closestHitProgram(in ImmutableRay_t _immutable, inout irr_glsl_xoroshiro64star_state_t scramble_state)
441-
{
442-
const MutableRay_t mutable = rayStack[stackPtr]._mutable;
443-
444-
Sphere sphere = spheres[mutable.objectID];
445-
vec3 intersection = _immutable.origin+_immutable.direction*mutable.intersectionT;
446-
447-
irr_glsl_AnisotropicViewSurfaceInteraction interaction;
448-
{
449-
irr_glsl_IsotropicViewSurfaceInteraction isotropic;
450-
451-
isotropic.V.dir = -_immutable.direction;
452-
//isotropic.V.dPosdScreen = screw that
453-
const float radiusRcp = inversesqrt(sphere.radius2);
454-
isotropic.N = (intersection-sphere.position)*radiusRcp;
455-
isotropic.NdotV = dot(isotropic.V.dir,isotropic.N);
456-
isotropic.NdotV_squared = isotropic.NdotV*isotropic.NdotV;
457-
458-
interaction = irr_glsl_calcAnisotropicInteraction(isotropic);
459-
}
460-
461-
const uint bsdfLightIDs = sphere.bsdfLightIDs;
462-
const uint lightID = bitfieldExtract(bsdfLightIDs,16,16);
463-
464-
vec3 throughput = rayStack[stackPtr]._payload.throughput;
465-
466-
// finish MIS
467-
if (lightID!=INVALID_ID_16BIT) // has emissive
468-
{
469-
float lightPdf;
470-
vec3 lightVal = irr_glsl_light_deferred_eval_and_prob(lightPdf,sphere,_immutable.origin,interaction,lights[lightID]);
471-
rayStack[stackPtr]._payload.accumulation += throughput*lightVal/(1.0+lightPdf*lightPdf*rayStack[stackPtr]._payload.otherTechniqueHeuristic);
472-
}
473-
474-
const int sampleIx = bitfieldExtract(_immutable.typeDepthSampleIx,0,DEPTH_BITS_OFFSET);
475-
const int depth = bitfieldExtract(_immutable.typeDepthSampleIx,DEPTH_BITS_OFFSET,DEPTH_BITS_COUNT);
476-
477-
// check if we even have a BSDF at all
478-
uint bsdfID = bitfieldExtract(bsdfLightIDs,0,16);
479-
if (depth<MAX_DEPTH && bsdfID!=INVALID_ID_16BIT)
480-
{
481-
// common preload
482-
BSDFNode bsdf = bsdfs[bsdfID];
483-
uint opType = BSDFNode_getType(bsdf);
484-
485-
#ifdef KILL_DIFFUSE_SPECULAR_PATHS
486-
if (BSDFNode_isNotDiffuse(bsdf))
487-
{
488-
if (rayStack[stackPtr]._payload.hasDiffuse)
489-
return;
490-
}
491-
else
492-
rayStack[stackPtr]._payload.hasDiffuse = true;
493-
#endif
494-
495-
496-
const float bsdfGeneratorProbability = BSDFNode_getMISWeight(bsdf);
497-
vec3 epsilon = rand3d(depth,sampleIx,scramble_state);
498-
499-
float rcpChoiceProb;
500-
const bool doNEE = irr_glsl_partitionRandVariable(bsdfGeneratorProbability,epsilon.z,rcpChoiceProb);
501-
502-
503-
float maxT;
504-
// the probability of generating a sample w.r.t. the light generator only possible and used when it was generated with it!
505-
float lightPdf;
506-
GeneratorSample _sample;
507-
if (doNEE)
508-
{
509-
vec3 lightRemainder;
510-
_sample = irr_glsl_light_generate_and_remainder_and_pdf(
511-
lightRemainder,lightPdf,maxT,
512-
intersection,interaction,epsilon,
513-
depth
514-
);
515-
throughput *= lightRemainder;
516-
}
517-
else
518-
{
519-
maxT = FLT_MAX;
520-
_sample = irr_glsl_bsdf_cos_generate(interaction,epsilon,bsdf);
521-
}
522-
523-
// do a cool trick and always compute the bsdf parts this way! (no divergence)
524-
float bsdfPdf;
525-
// the value of the bsdf divided by the probability of the sample being generated
526-
throughput *= irr_glsl_bsdf_cos_remainder_and_pdf(bsdfPdf,_sample,interaction,bsdf);
527-
528-
// OETF smallest perceptible value
529-
const float bsdfPdfThreshold = getLuma(irr_glsl_eotf_sRGB(vec3(1.0)/255.0));
530-
const float lumaThroughputThreshold = bsdfPdfThreshold;
531-
if (bsdfPdf>bsdfPdfThreshold && getLuma(throughput)>lumaThroughputThreshold)
532-
{
533-
rayStack[stackPtr]._payload.throughput = throughput*rcpChoiceProb;
534-
535-
float heuristicFactor = rcpChoiceProb-1.0; // weightNonGenerator/weightGenerator
536-
heuristicFactor /= doNEE ? lightPdf:bsdfPdf; // weightNonGenerator/(weightGenerator*probGenerated)
537-
heuristicFactor *= heuristicFactor; // (weightNonGenerator/(weightGenerator*probGenerated))^2
538-
if (doNEE)
539-
heuristicFactor = 1.0/(1.0/bsdfPdf+heuristicFactor*bsdfPdf); // numerically stable, don't touch
540-
rayStack[stackPtr]._payload.otherTechniqueHeuristic = heuristicFactor;
541-
542-
// trace new ray
543-
rayStack[stackPtr]._immutable.origin = intersection+_sample.L*(doNEE ? maxT:1.0/*kSceneSize*/)*getStartTolerance(depth);
544-
rayStack[stackPtr]._immutable.maxT = maxT;
545-
rayStack[stackPtr]._immutable.direction = _sample.L;
546-
rayStack[stackPtr]._immutable.typeDepthSampleIx = bitfieldInsert(sampleIx,depth+1,DEPTH_BITS_OFFSET,DEPTH_BITS_COUNT)|(doNEE ? ANY_HIT_FLAG:0);
547-
stackPtr++;
548-
}
549-
}
550-
}
551-
#endif
552-
553446
bool traceRay(in ImmutableRay_t _immutable);
554447
void closestHitProgram(in ImmutableRay_t _immutable, inout irr_glsl_xoroshiro64star_state_t scramble_state);
555448

@@ -601,6 +494,10 @@ void main()
601494

602495
rayStack[stackPtr]._immutable.typeDepthSampleIx = bitfieldInsert(i,1,DEPTH_BITS_OFFSET,DEPTH_BITS_COUNT);
603496

497+
#ifdef TRIANGLE_METHOD
498+
rayStack[stackPtr]._immutable.normalAtOrigin = vec3(0.0,0.0,0.0);
499+
rayStack[stackPtr]._immutable.wasBSDFAtOrigin = false;
500+
#endif
604501

605502
rayStack[stackPtr]._payload.accumulation = vec3(0.0);
606503
rayStack[stackPtr]._payload.otherTechniqueHeuristic = 0.0; // needed for direct eye-light paths

0 commit comments

Comments
 (0)