10
10
11
11
12
12
13
- int traceRay(inout float intersectionT, in ImmutableRay_t _immutable )
13
+ int traceRay(inout float intersectionT, in vec3 origin, in vec3 direction )
14
14
{
15
15
int objectID = - 1 ;
16
16
for (int i= 0 ; i< SPHERE_COUNT; i++ )
17
17
{
18
- float t = Sphere_intersect(spheres[i],_immutable. origin,_immutable. direction);
18
+ float t = Sphere_intersect(spheres[i],origin,direction);
19
19
bool closerIntersection = t> 0.0 && t< intersectionT;
20
20
21
21
objectID = closerIntersection ? i: objectID;
@@ -36,6 +36,7 @@ vec3 nbl_glsl_light_deferred_eval_and_prob(out float pdf, in Sphere sphere, in v
36
36
pdf = scene_getLightChoicePdf(light)/ Sphere_getSolidAngle(sphere,origin);
37
37
return Light_getRadiance(light);
38
38
}
39
+ #endif
39
40
40
41
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)
41
42
{
@@ -75,7 +76,6 @@ nbl_glsl_LightSample nbl_glsl_light_generate_and_remainder_and_pdf(out vec3 rema
75
76
76
77
return nbl_glsl_createLightSample(L,interaction);
77
78
}
78
- #endif
79
79
80
80
bool closestHitProgram(in uint depth, in uint _sample, inout Ray_t ray, inout nbl_glsl_xoroshiro64star_state_t scramble_state)
81
81
{
@@ -85,7 +85,7 @@ bool closestHitProgram(in uint depth, in uint _sample, inout Ray_t ray, inout nb
85
85
const uint bsdfLightIDs = sphere.bsdfLightIDs;
86
86
87
87
vec3 throughput = ray._payload.throughput;
88
- #if 1
88
+ #if 0
89
89
// add emissive
90
90
const uint lightID = bitfieldExtract(bsdfLightIDs,16 ,16 );
91
91
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
109
109
// rand
110
110
mat2x3 epsilon = rand3d(depth,_sample,scramble_state);
111
111
112
- // intersection stuffs
112
+ // interaction stuffs
113
113
const vec3 intersection = ray._immutable.origin+ ray._immutable.direction* _mutable.intersectionT;
114
-
115
114
nbl_glsl_AnisotropicViewSurfaceInteraction interaction;
116
115
{
117
116
nbl_glsl_IsotropicViewSurfaceInteraction isotropic;
@@ -125,28 +124,45 @@ bool closestHitProgram(in uint depth, in uint _sample, inout Ray_t ray, inout nb
125
124
interaction = nbl_glsl_calcAnisotropicInteraction(isotropic);
126
125
}
127
126
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
134
130
const vec3 throughputCIE_Y = transpose (nbl_glsl_sRGBtoXYZ)[1 ]* throughput;
135
131
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
+
137
153
// sample BSDF
138
154
float bsdfPdf; vec3 bsdfSampleL;
139
155
{
156
+ nbl_glsl_AnisotropicMicrofacetCache _cache;
140
157
nbl_glsl_LightSample _sample = nbl_glsl_bsdf_cos_generate(interaction,epsilon[0 ],bsdf,monochromeEta,_cache);
141
158
// the value of the bsdf divided by the probability of the sample being generated
142
159
throughput *= nbl_glsl_bsdf_cos_remainder_and_pdf(bsdfPdf,_sample,interaction,bsdf,monochromeEta,_cache);
143
160
//
144
161
bsdfSampleL = _sample.L;
145
162
}
146
163
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;
150
166
if (bsdfPdf> bsdfPdfThreshold && getLuma(throughput)> lumaThroughputThreshold)
151
167
{
152
168
ray._payload.throughput = throughput;
@@ -159,105 +175,27 @@ bool closestHitProgram(in uint depth, in uint _sample, inout Ray_t ray, inout nb
159
175
}
160
176
return false;
161
177
}
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
188
179
// finish MIS
189
180
if (lightID!= INVALID_ID_16BIT) // has emissive
190
181
{
191
182
float lightPdf;
192
183
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);
194
185
}
195
186
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);
203
187
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
+
213
189
214
190
215
191
const float bsdfGeneratorProbability = BSDFNode_getMISWeight(bsdf);
216
- mat2x3 epsilon = rand3d(depth,_sample,scramble_state);
217
-
218
- float rcpChoiceProb;
219
192
const bool doNEE = nbl_glsl_partitionRandVariable(bsdfGeneratorProbability,epsilon[0 ].z,rcpChoiceProb);
220
-
221
193
222
194
float maxT;
223
195
// the probability of generating a sample w.r.t. the light generator only possible and used when it was generated with it!
224
196
float lightPdf;
225
197
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
- }
253
198
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 );
261
199
262
200
// OETF smallest perceptible value
263
201
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
280
218
ray._immutable.anyHit = doNEE;
281
219
return false;
282
220
}
283
- }
284
- return true;
285
- }
286
221
#endif
0 commit comments