Skip to content

Commit 8b22095

Browse files
prepare for MIS (reimplement NEE)
1 parent 9ea21b4 commit 8b22095

File tree

2 files changed

+37
-102
lines changed

2 files changed

+37
-102
lines changed

examples_tests/42.FragmentShaderPathTracer/common.glsl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ mat2x3 rand3d(in uint protoDimension, in uint _sample, inout nbl_glsl_xoroshiro6
484484
return retval;
485485
}
486486

487-
int traceRay(inout float intersectionT, in ImmutableRay_t _immutable);
487+
int traceRay(inout float intersectionT, in vec3 origin, in vec3 direction);
488488
bool closestHitProgram(in uint depth, in uint _sample, inout Ray_t ray, inout nbl_glsl_xoroshiro64star_state_t scramble_state);
489489

490490
void main()
@@ -552,7 +552,7 @@ void main()
552552
for (int d=1; d<=MAX_DEPTH && hit && rayAlive; d+=2)
553553
{
554554
ray._mutable.intersectionT = FLT_MAX;
555-
ray._mutable.objectID = traceRay(ray._mutable.intersectionT,ray._immutable);
555+
ray._mutable.objectID = traceRay(ray._mutable.intersectionT,ray._immutable.origin,ray._immutable.direction);
556556
hit = ray._mutable.objectID!=-1;
557557
if (hit)
558558
rayAlive = closestHitProgram(3u, i, ray, scramble_state);

examples_tests/42.FragmentShaderPathTracer/litBySphere.frag

Lines changed: 35 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010

1111

1212

13-
int traceRay(inout float intersectionT, in ImmutableRay_t _immutable)
13+
int traceRay(inout float intersectionT, in vec3 origin, in vec3 direction)
1414
{
1515
int objectID = -1;
1616
for (int i=0; i<SPHERE_COUNT; i++)
1717
{
18-
float t = Sphere_intersect(spheres[i],_immutable.origin,_immutable.direction);
18+
float t = Sphere_intersect(spheres[i],origin,direction);
1919
bool closerIntersection = t>0.0 && t<intersectionT;
2020

2121
objectID = closerIntersection ? i:objectID;
@@ -36,6 +36,7 @@ vec3 nbl_glsl_light_deferred_eval_and_prob(out float pdf, in Sphere sphere, in v
3636
pdf = scene_getLightChoicePdf(light)/Sphere_getSolidAngle(sphere,origin);
3737
return Light_getRadiance(light);
3838
}
39+
#endif
3940

4041
nbl_glsl_LightSample nbl_glsl_light_generate_and_remainder_and_pdf(out vec3 remainder, out float pdf, out float newRayMaxT, in vec3 origin, in nbl_glsl_AnisotropicViewSurfaceInteraction interaction, in vec3 u, in uint depth)
4142
{
@@ -75,7 +76,6 @@ nbl_glsl_LightSample nbl_glsl_light_generate_and_remainder_and_pdf(out vec3 rema
7576

7677
return nbl_glsl_createLightSample(L,interaction);
7778
}
78-
#endif
7979

8080
bool closestHitProgram(in uint depth, in uint _sample, inout Ray_t ray, inout nbl_glsl_xoroshiro64star_state_t scramble_state)
8181
{
@@ -85,7 +85,7 @@ bool closestHitProgram(in uint depth, in uint _sample, inout Ray_t ray, inout nb
8585
const uint bsdfLightIDs = sphere.bsdfLightIDs;
8686

8787
vec3 throughput = ray._payload.throughput;
88-
#if 1
88+
#if 0
8989
// add emissive
9090
const uint lightID = bitfieldExtract(bsdfLightIDs,16,16);
9191
if (lightID!=INVALID_ID_16BIT) // has emissive
@@ -109,9 +109,8 @@ bool closestHitProgram(in uint depth, in uint _sample, inout Ray_t ray, inout nb
109109
//rand
110110
mat2x3 epsilon = rand3d(depth,_sample,scramble_state);
111111

112-
// intersection stuffs
112+
// interaction stuffs
113113
const vec3 intersection = ray._immutable.origin+ray._immutable.direction*_mutable.intersectionT;
114-
115114
nbl_glsl_AnisotropicViewSurfaceInteraction interaction;
116115
{
117116
nbl_glsl_IsotropicViewSurfaceInteraction isotropic;
@@ -125,28 +124,45 @@ bool closestHitProgram(in uint depth, in uint _sample, inout Ray_t ray, inout nb
125124
interaction = nbl_glsl_calcAnisotropicInteraction(isotropic);
126125
}
127126

128-
129-
130-
131-
nbl_glsl_AnisotropicMicrofacetCache _cache;
132-
133-
// do I need this?
127+
// thresholds
128+
const float bsdfPdfThreshold = 0.0001;
129+
const float lumaContributionThreshold = getLuma(nbl_glsl_eotf_sRGB(vec3(1.0)/255.0)); // OETF smallest perceptible value
134130
const vec3 throughputCIE_Y = transpose(nbl_glsl_sRGBtoXYZ)[1]*throughput;
135131
const float monochromeEta = dot(throughputCIE_Y,BSDFNode_getEta(bsdf)[0])/(throughputCIE_Y.r+throughputCIE_Y.g+throughputCIE_Y.b);
136-
132+
133+
// do NEE
134+
float rcpNEEProb = 1.0;
135+
if (true)
136+
{
137+
vec3 neeContrib; float lightPdf, t;
138+
nbl_glsl_LightSample _sample = nbl_glsl_light_generate_and_remainder_and_pdf(neeContrib,lightPdf,t,intersection,interaction,epsilon[1],depth);
139+
// We don't allow non watertight transmitters in this renderer
140+
bool validPath = _sample.NdotL>0.0;
141+
// but if we allowed non-watertight transmitters (single water surface), it would make sense just to apply this line by itself
142+
nbl_glsl_AnisotropicMicrofacetCache _cache;
143+
validPath = validPath && nbl_glsl_calcAnisotropicMicrofacetCache(_cache,interaction,_sample,monochromeEta);
144+
if (validPath)
145+
{
146+
float bsdfPdf;
147+
neeContrib *= nbl_glsl_bsdf_cos_remainder_and_pdf(bsdfPdf,_sample,interaction,bsdf,monochromeEta,_cache)*throughput;
148+
if (bsdfPdf<FLT_MAX && getLuma(neeContrib)>lumaContributionThreshold && traceRay(t,intersection+_sample.L*t*getStartTolerance(depth),_sample.L)==-1)
149+
ray._payload.accumulation += neeContrib*bsdfPdf;
150+
}
151+
}
152+
137153
// sample BSDF
138154
float bsdfPdf; vec3 bsdfSampleL;
139155
{
156+
nbl_glsl_AnisotropicMicrofacetCache _cache;
140157
nbl_glsl_LightSample _sample = nbl_glsl_bsdf_cos_generate(interaction,epsilon[0],bsdf,monochromeEta,_cache);
141158
// the value of the bsdf divided by the probability of the sample being generated
142159
throughput *= nbl_glsl_bsdf_cos_remainder_and_pdf(bsdfPdf,_sample,interaction,bsdf,monochromeEta,_cache);
143160
//
144161
bsdfSampleL = _sample.L;
145162
}
146163

147-
const float bsdfPdfThreshold = 0.0001;
148-
// OETF smallest perceptible value
149-
const float lumaThroughputThreshold = getLuma(nbl_glsl_eotf_sRGB(vec3(1.0)/255.0));
164+
// additional threshold
165+
const float lumaThroughputThreshold = lumaContributionThreshold;
150166
if (bsdfPdf>bsdfPdfThreshold && getLuma(throughput)>lumaThroughputThreshold)
151167
{
152168
ray._payload.throughput = throughput;
@@ -159,105 +175,27 @@ bool closestHitProgram(in uint depth, in uint _sample, inout Ray_t ray, inout nb
159175
}
160176
return false;
161177
}
162-
#if 0
163-
bool closestHitProgram(in uint depth, in uint _sample, inout Ray_t ray, inout nbl_glsl_xoroshiro64star_state_t scramble_state)
164-
{
165-
const MutableRay_t _mutable = ray._mutable;
166-
167-
Sphere sphere = spheres[_mutable.objectID];
168-
vec3 intersection = ray._immutable.origin+ray._immutable.direction*_mutable.intersectionT;
169-
170-
nbl_glsl_AnisotropicViewSurfaceInteraction interaction;
171-
{
172-
nbl_glsl_IsotropicViewSurfaceInteraction isotropic;
173-
174-
isotropic.V.dir = -ray._immutable.direction;
175-
//isotropic.V.dPosdScreen = screw that
176-
isotropic.N = Sphere_getNormal(sphere,intersection);
177-
isotropic.NdotV = dot(isotropic.V.dir,isotropic.N);
178-
isotropic.NdotV_squared = isotropic.NdotV*isotropic.NdotV;
179-
180-
interaction = nbl_glsl_calcAnisotropicInteraction(isotropic);
181-
}
182-
183-
const uint bsdfLightIDs = sphere.bsdfLightIDs;
184-
const uint lightID = bitfieldExtract(bsdfLightIDs,16,16);
185-
186-
vec3 throughput = ray._payload.throughput;
187-
178+
#if 0
188179
// finish MIS
189180
if (lightID!=INVALID_ID_16BIT) // has emissive
190181
{
191182
float lightPdf;
192183
vec3 lightVal = nbl_glsl_light_deferred_eval_and_prob(lightPdf,sphere,ray._immutable.origin,interaction,lights[lightID]);
193-
ray._payload.accumulation += throughput*lightVal/(1.0+lightPdf*lightPdf*ray._payload.otherTechniqueHeuristic);
184+
ray._payload.accumulation += ray._payload.throughput*lightVal/(1.0+lightPdf*lightPdf*ray._payload.otherTechniqueHeuristic);
194185
}
195186

196-
// check if we even have a BSDF at all
197-
uint bsdfID = bitfieldExtract(bsdfLightIDs,0,16);
198-
if (bsdfID!=INVALID_ID_16BIT)
199-
{
200-
// common preload
201-
BSDFNode bsdf = bsdfs[bsdfID];
202-
uint opType = BSDFNode_getType(bsdf);
203187

204-
#ifdef KILL_DIFFUSE_SPECULAR_PATHS
205-
if (BSDFNode_isNotDiffuse(bsdf))
206-
{
207-
if (ray._payload.hasDiffuse)
208-
return true;
209-
}
210-
else
211-
ray._payload.hasDiffuse = true;
212-
#endif
188+
213189

214190

215191
const float bsdfGeneratorProbability = BSDFNode_getMISWeight(bsdf);
216-
mat2x3 epsilon = rand3d(depth,_sample,scramble_state);
217-
218-
float rcpChoiceProb;
219192
const bool doNEE = nbl_glsl_partitionRandVariable(bsdfGeneratorProbability,epsilon[0].z,rcpChoiceProb);
220-
221193

222194
float maxT;
223195
// the probability of generating a sample w.r.t. the light generator only possible and used when it was generated with it!
224196
float lightPdf;
225197
nbl_glsl_LightSample _sample;
226-
nbl_glsl_AnisotropicMicrofacetCache _cache;
227-
if (doNEE)
228-
{
229-
vec3 lightRemainder;
230-
_sample = nbl_glsl_light_generate_and_remainder_and_pdf(
231-
lightRemainder,lightPdf,maxT,
232-
intersection,interaction,epsilon[0],
233-
depth
234-
);
235-
throughput *= lightRemainder;
236-
}
237-
238-
bool validPath = true;
239-
const vec3 throughputCIE_Y = transpose(nbl_glsl_sRGBtoXYZ)[1]*throughput;
240-
const float monochromeEta = dot(throughputCIE_Y,BSDFNode_getEta(bsdf)[0])/(throughputCIE_Y.r+throughputCIE_Y.g+throughputCIE_Y.b);
241-
if (doNEE)
242-
{
243-
// if we allowed non-watertight transmitters (single water surface), it would make sense just to apply this line.
244-
validPath = nbl_glsl_calcAnisotropicMicrofacetCache(_cache,interaction,_sample,monochromeEta);
245-
// but we don't allow non watertight transmitters in this renderer
246-
validPath = validPath && _sample.NdotL>0.0;
247-
}
248-
else
249-
{
250-
maxT = FLT_MAX;
251-
_sample = nbl_glsl_bsdf_cos_generate(interaction,epsilon[0],bsdf,monochromeEta,_cache);
252-
}
253198

254-
// do a cool trick and always compute the bsdf parts this way! (no divergence)
255-
float bsdfPdf;
256-
// the value of the bsdf divided by the probability of the sample being generated
257-
if (validPath)
258-
throughput *= nbl_glsl_bsdf_cos_remainder_and_pdf(bsdfPdf,_sample,interaction,bsdf,monochromeEta,_cache);
259-
else
260-
throughput = vec3(0.0);
261199

262200
// OETF smallest perceptible value
263201
const float bsdfPdfThreshold = getLuma(nbl_glsl_eotf_sRGB(vec3(1.0)/255.0));
@@ -280,7 +218,4 @@ bool closestHitProgram(in uint depth, in uint _sample, inout Ray_t ray, inout nb
280218
ray._immutable.anyHit = doNEE;
281219
return false;
282220
}
283-
}
284-
return true;
285-
}
286221
#endif

0 commit comments

Comments
 (0)