@meimu/mutracer 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/bvh.worker.js +1 -1
- package/dist/mutracer.umd.js +4114 -4015
- package/docs/api.md +11 -9
- package/docs/threejs.md +30 -4
- package/lib/Engine.js +18 -1
- package/lib/Engine.js.map +1 -1
- package/lib/main.d.ts +1 -1
- package/lib/main.js.map +1 -1
- package/lib/oidn.d.ts +1 -1
- package/lib/oidnBundledWeights.cdn.d.ts +2 -2
- package/lib/renderer/MaterialTable.d.ts +1 -0
- package/lib/renderer/MaterialTable.js +10 -4
- package/lib/renderer/MaterialTable.js.map +1 -1
- package/lib/renderer/WGPUBloomPass.js +18 -18
- package/lib/renderer/WGPUFullQuadPass.js +6 -6
- package/lib/renderer/WGPUJNLMDenoiser.js +69 -69
- package/lib/renderer/WGPURayTraceOutput.js +14 -14
- package/lib/renderer/WGPURayTracePass.d.ts +2 -0
- package/lib/renderer/WGPURayTracePass.js +12 -6
- package/lib/renderer/WGPURayTracePass.js.map +1 -1
- package/lib/renderer/WGPURenderingPipeline.js +15 -15
- package/lib/renderer/WebGLJNLMDenoiser.js +69 -69
- package/lib/renderer/WebGLRayTraceOutputPass.js +4 -4
- package/lib/renderer/WebGLRayTracePass.d.ts +1 -0
- package/lib/renderer/WebGLRayTracePass.js +7 -1
- package/lib/renderer/WebGLRayTracePass.js.map +1 -1
- package/lib/renderer/envMapCreation.d.ts +5 -1
- package/lib/renderer/envMapCreation.js +42 -5
- package/lib/renderer/envMapCreation.js.map +1 -1
- package/lib/renderer/geometryUpdates.js +1 -1
- package/lib/renderer/geometryUpdates.js.map +1 -1
- package/lib/renderer/glsl/chunks/cameraRay.glsl.js +12 -12
- package/lib/renderer/glsl/chunks/envMap.glsl.js +66 -54
- package/lib/renderer/glsl/chunks/envMap.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/intersect.glsl.js +316 -310
- package/lib/renderer/glsl/chunks/intersect.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/materialBuffer.glsl.js +151 -119
- package/lib/renderer/glsl/chunks/materialBuffer.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/openPbrBsdf.glsl.js +414 -414
- package/lib/renderer/glsl/chunks/rand.glsl.js +3 -3
- package/lib/renderer/glsl/chunks/random.glsl.js +3 -3
- package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js +40 -39
- package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/sampleLight.glsl.js +69 -69
- package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js +78 -78
- package/lib/renderer/glsl/chunks/sampleShadowCatcher.glsl.js +12 -12
- package/lib/renderer/glsl/chunks/sampling.glsl.js +75 -75
- package/lib/renderer/glsl/chunks/sobol.glsl.js +61 -61
- package/lib/renderer/glsl/chunks/textureLinear.glsl.js +5 -5
- package/lib/renderer/glsl/chunks/uvProjection.glsl.js +11 -11
- package/lib/renderer/glsl/depthQuery.frag.js +5 -5
- package/lib/renderer/glsl/depthQuery.frag.js.map +1 -1
- package/lib/renderer/glsl/normalizeRayTraceOutput.frag.js +8 -8
- package/lib/renderer/glsl/rayTrace.frag.js +133 -133
- package/lib/renderer/glsl/rayTrace.frag.js.map +1 -1
- package/lib/renderer/glsl/shadowCatcher.frag.js +9 -9
- package/lib/renderer/glsl/shadowCatcher.frag.js.map +1 -1
- package/lib/renderer/glsl/webglPipeline.frag.js +52 -52
- package/lib/renderer/lightsUtil.js +6 -4
- package/lib/renderer/lightsUtil.js.map +1 -1
- package/lib/renderer/materialChanges.js +1 -1
- package/lib/renderer/materialChanges.js.map +1 -1
- package/lib/renderer/materialComparison.generated.js +36 -18
- package/lib/renderer/materialComparison.generated.js.map +1 -1
- package/lib/renderer/prepareMeshBVH.js +2 -2
- package/lib/renderer/prepareMeshBVH.js.map +1 -1
- package/lib/renderer/sceneChangeDetector.js +4 -1
- package/lib/renderer/sceneChangeDetector.js.map +1 -1
- package/lib/renderer/sceneLightChanges.js +3 -2
- package/lib/renderer/sceneLightChanges.js.map +1 -1
- package/lib/renderer/scratchSampling.js +18 -18
- package/lib/renderer/wgsl/chunks/common.wgsl.js +4 -4
- package/lib/renderer/wgsl/chunks/envMap.wgsl.d.ts +1 -1
- package/lib/renderer/wgsl/chunks/envMap.wgsl.js +39 -31
- package/lib/renderer/wgsl/chunks/envMap.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/intersect.wgsl.js +475 -469
- package/lib/renderer/wgsl/chunks/intersect.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js +8 -8
- package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js +93 -59
- package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/openPbrBsdf.wgsl.js +469 -469
- package/lib/renderer/wgsl/chunks/pdm_displacement.wgsl.d.ts +1 -1
- package/lib/renderer/wgsl/chunks/pdm_displacement.wgsl.js +117 -120
- package/lib/renderer/wgsl/chunks/pdm_displacement.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/rand.wgsl.js +3 -3
- package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js +25 -22
- package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js +127 -127
- package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js +136 -136
- package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js +6 -6
- package/lib/renderer/wgsl/chunks/sampling.wgsl.js +73 -73
- package/lib/renderer/wgsl/chunks/sobol.wgsl.js +62 -62
- package/lib/renderer/wgsl/chunks/uvProjection.wgsl.js +11 -11
- package/lib/renderer/wgsl/compose.frag.wgsl.js +105 -105
- package/lib/renderer/wgsl/customDenoise.wgsl.js +10 -10
- package/lib/renderer/wgsl/depthQuery.wgsl.d.ts +1 -1
- package/lib/renderer/wgsl/depthQuery.wgsl.js +5 -5
- package/lib/renderer/wgsl/depthQuery.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/offlineAdaptive.compute.js +28 -28
- package/lib/renderer/wgsl/rayTrace.compute.js +251 -248
- package/lib/renderer/wgsl/rayTrace.compute.js.map +1 -1
- package/lib/scene/EnvironmentLight.d.ts +9 -3
- package/lib/scene/EnvironmentLight.js +9 -2
- package/lib/scene/EnvironmentLight.js.map +1 -1
- package/lib/scene/Scene.d.ts +4 -0
- package/lib/scene/Scene.js.map +1 -1
- package/lib/scene/SpotLight.d.ts +2 -2
- package/lib/scene/SpotLight.js +1 -1
- package/lib/scene/SpotLight.js.map +1 -1
- package/lib/scene/Texture.d.ts +17 -6
- package/lib/scene/Texture.js +13 -4
- package/lib/scene/Texture.js.map +1 -1
- package/lib/util/fromTHREE.js +151 -29
- package/lib/util/fromTHREE.js.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/lib/version.js.map +1 -1
- package/package.json +1 -1
|
@@ -32,7 +32,7 @@ return;
|
|
|
32
32
|
// So here the code are injected separately.
|
|
33
33
|
const bounceCodeOnIntelMac = glsl `
|
|
34
34
|
|
|
35
|
-
for(int
|
|
35
|
+
for(int vU = 0; vU < BOUNCES; vU++) {{
|
|
36
36
|
if (aa.abort) {
|
|
37
37
|
return vec4(aa.li, aa.alpha);
|
|
38
38
|
}
|
|
@@ -40,10 +40,10 @@ bounce(aa, depth, si, mat, outAux);
|
|
|
40
40
|
}}
|
|
41
41
|
`;
|
|
42
42
|
const bounceCodeOnOther = glsl `
|
|
43
|
-
bool
|
|
44
|
-
int
|
|
43
|
+
bool vg = !si.isTransparency;
|
|
44
|
+
int qO = min(BOUNCES, bounceLimit);
|
|
45
45
|
for(int idx = 0; idx < min(BOUNCES * 3, ${MAX_PATH_EVENTS}); idx++) {
|
|
46
|
-
if (
|
|
46
|
+
if (vg && idx > qO) {
|
|
47
47
|
aa.abort = true;
|
|
48
48
|
}
|
|
49
49
|
if (aa.abort) {
|
|
@@ -93,7 +93,7 @@ ${envMap.main}
|
|
|
93
93
|
${samplingGlsl}
|
|
94
94
|
${openPbrBsdfGlsl}
|
|
95
95
|
|
|
96
|
-
float
|
|
96
|
+
float mw;
|
|
97
97
|
float bf;
|
|
98
98
|
|
|
99
99
|
${sampleLightGlsl}
|
|
@@ -139,18 +139,18 @@ vec4 bg = cx(aa.ray.o, aa.ray.d);
|
|
|
139
139
|
bg.rgb = ai(bg.rgb, bf);
|
|
140
140
|
float cT = aa.scatteringIsDelta ? 1.0
|
|
141
141
|
: aG(aa.scatteringPdf,
|
|
142
|
-
|
|
142
|
+
iB(cY(aa.ray.d)) * envLightSelectionPmf);
|
|
143
143
|
aa.li += cT * aa.beta * bg.rgb * bg.a;
|
|
144
144
|
aa.alpha = max(aa.alpha, bg.a);
|
|
145
145
|
}
|
|
146
146
|
else {
|
|
147
|
-
vec2
|
|
148
|
-
vec3 emission = textureLinear(envMap,
|
|
147
|
+
vec2 tQ = cY(aa.ray.d);
|
|
148
|
+
vec3 emission = textureLinear(envMap, tQ).rgb;
|
|
149
149
|
emission = ai(emission, bf);
|
|
150
150
|
aa.li += aa.beta * emission *
|
|
151
151
|
aG(
|
|
152
152
|
aa.scatteringPdf,
|
|
153
|
-
|
|
153
|
+
iB(tQ) * envLightSelectionPmf
|
|
154
154
|
);
|
|
155
155
|
}
|
|
156
156
|
#else
|
|
@@ -177,10 +177,10 @@ aa.alpha = bg.a;
|
|
|
177
177
|
outAux.isBlank = bg.a < 0.01;
|
|
178
178
|
}
|
|
179
179
|
else {
|
|
180
|
-
Ray cam =
|
|
181
|
-
bool
|
|
180
|
+
Ray cam = hC(v_Texcoord + sa());
|
|
181
|
+
bool mM = dot(cam.d, aa.ray.d) > 0.0;
|
|
182
182
|
if (transmissiveOutputAlphaMin < 1.0) {
|
|
183
|
-
if (
|
|
183
|
+
if (mM) {
|
|
184
184
|
aa.alpha = max(aa.alpha, bg.a);
|
|
185
185
|
} else {
|
|
186
186
|
aa.alpha = 1.0;
|
|
@@ -188,7 +188,7 @@ aa.alpha = 1.0;
|
|
|
188
188
|
}
|
|
189
189
|
#if !defined(USE_ENVMAP)
|
|
190
190
|
|
|
191
|
-
if (
|
|
191
|
+
if (mM) {
|
|
192
192
|
aa.li = aa.beta * aG(aa.scatteringPdf, 1.0) * bg.rgb;
|
|
193
193
|
}
|
|
194
194
|
#endif
|
|
@@ -214,7 +214,7 @@ cH = true;
|
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
216
|
if (!cH) {
|
|
217
|
-
|
|
217
|
+
mc(si, mat, aa);
|
|
218
218
|
}
|
|
219
219
|
else {
|
|
220
220
|
aa.ray.o = si.position + aa.ray.d * EPS;
|
|
@@ -245,8 +245,8 @@ si.albedoSampled = true;
|
|
|
245
245
|
#ifdef USE_RR
|
|
246
246
|
if (depth >= RR_MAX && !cH) {
|
|
247
247
|
|
|
248
|
-
float
|
|
249
|
-
float q = max(0.0, 1.0 -
|
|
248
|
+
float oz = max(max(aa.beta.x, aa.beta.y), aa.beta.z);
|
|
249
|
+
float q = max(0.0, 1.0 - oz);
|
|
250
250
|
if (dz(cw(RUSSIAN_ROULETTE)) < q) {
|
|
251
251
|
|
|
252
252
|
|
|
@@ -264,18 +264,18 @@ return;
|
|
|
264
264
|
}
|
|
265
265
|
|
|
266
266
|
|
|
267
|
-
|
|
268
|
-
|
|
267
|
+
cZ(aa.ray, si, true);
|
|
268
|
+
eX(mat, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);
|
|
269
269
|
si.isTransparency = mat.transmissionWeight > 0.001 || mat.subsurfaceWeight > 0.001 || mat.alpha < 0.999;
|
|
270
270
|
|
|
271
271
|
|
|
272
272
|
|
|
273
273
|
|
|
274
274
|
if (dispersionWavelengths == 1 && si.hit && mat.transmissionWeight > 0.001 && mat.transmissionDispersionScale > 0.001) {
|
|
275
|
-
bf =
|
|
275
|
+
bf = mw;
|
|
276
276
|
}
|
|
277
277
|
if (mat.transmissionWeight > 0.001 && bf > 0.0) {
|
|
278
|
-
mat.specularIor =
|
|
278
|
+
mat.specularIor = eN(
|
|
279
279
|
bf,
|
|
280
280
|
mat.specularIor,
|
|
281
281
|
mat.transmissionDispersionScale,
|
|
@@ -287,20 +287,20 @@ if (cH) {
|
|
|
287
287
|
return;
|
|
288
288
|
}
|
|
289
289
|
|
|
290
|
-
bool
|
|
290
|
+
bool hy = eo(3u) < mat.alpha;
|
|
291
291
|
#ifdef NUM_LIGHTS
|
|
292
292
|
|
|
293
293
|
LightSampleRec lightSample;
|
|
294
294
|
for (int i = 0; i < NUM_LIGHTS; i++) {
|
|
295
295
|
|
|
296
|
-
Light light =
|
|
297
|
-
float d =
|
|
298
|
-
bool
|
|
299
|
-
if (d != INF && !(
|
|
296
|
+
Light light = qx(i);
|
|
297
|
+
float d = mz(aa.ray, light, lightSample);
|
|
298
|
+
bool mD = si.hit && d > distance(si.position, aa.ray.o);
|
|
299
|
+
if (d != INF && !(mD && hy)) {
|
|
300
300
|
lightSample.pdf *= light.selectionPmf;
|
|
301
|
-
float
|
|
301
|
+
float fa = aG(aa.scatteringPdf, lightSample.pdf);
|
|
302
302
|
lightSample.emission = ai(lightSample.emission, bf);
|
|
303
|
-
aa.li +=
|
|
303
|
+
aa.li += fa * aa.beta * lightSample.emission;
|
|
304
304
|
|
|
305
305
|
aa.alpha = 1.0;
|
|
306
306
|
aa.abort = true;
|
|
@@ -309,7 +309,7 @@ aa.abort = true;
|
|
|
309
309
|
#endif
|
|
310
310
|
|
|
311
311
|
#ifdef USE_ENVMAP
|
|
312
|
-
if (!(si.hit &&
|
|
312
|
+
if (!(si.hit && hy)) {
|
|
313
313
|
if (aa.isNextRefraction) {
|
|
314
314
|
|
|
315
315
|
|
|
@@ -317,20 +317,20 @@ vec4 bg = cx(aa.ray.o, aa.ray.d);
|
|
|
317
317
|
bg.rgb = ai(bg.rgb, bf);
|
|
318
318
|
float cT = aa.scatteringIsDelta ? 1.0
|
|
319
319
|
: aG(aa.scatteringPdf,
|
|
320
|
-
|
|
320
|
+
iB(cY(aa.ray.d)) * envLightSelectionPmf);
|
|
321
321
|
aa.li += cT * aa.beta * bg.rgb * bg.a;
|
|
322
322
|
aa.alpha = max(aa.alpha, bg.a);
|
|
323
323
|
aa.abort = true;
|
|
324
324
|
return;
|
|
325
325
|
}
|
|
326
|
-
vec2 uv =
|
|
326
|
+
vec2 uv = cY(aa.ray.d);
|
|
327
327
|
vec3 emission = textureLinear(envMap, uv).rgb;
|
|
328
|
-
float
|
|
328
|
+
float fa = aG(
|
|
329
329
|
aa.scatteringPdf,
|
|
330
|
-
|
|
330
|
+
iB(uv) * envLightSelectionPmf
|
|
331
331
|
);
|
|
332
332
|
emission = ai(emission, bf);
|
|
333
|
-
aa.li += aa.beta * emission *
|
|
333
|
+
aa.li += aa.beta * emission * fa;
|
|
334
334
|
|
|
335
335
|
|
|
336
336
|
#if !defined(USE_BACKGROUND)
|
|
@@ -345,105 +345,105 @@ depth++;
|
|
|
345
345
|
}
|
|
346
346
|
|
|
347
347
|
|
|
348
|
-
vec2
|
|
348
|
+
vec2 kz(float radius, float xi) {
|
|
349
349
|
float x = 0.25;
|
|
350
|
-
for (int
|
|
350
|
+
for (int nH = 0; nH < 10; nH++) {
|
|
351
351
|
float x2 = x * x;
|
|
352
352
|
float x3 = x2 * x;
|
|
353
|
-
float
|
|
353
|
+
float kP = 1.0 - x;
|
|
354
354
|
float value = 10.0 * x2 - 20.0 * x3 + 15.0 * x2 * x2 -
|
|
355
355
|
4.0 * x2 * x3 - xi;
|
|
356
|
-
float
|
|
357
|
-
if (abs(value) < 1e-6 ||
|
|
358
|
-
x = clamp(x - value /
|
|
356
|
+
float mk = 20.0 * x * kP * kP * kP;
|
|
357
|
+
if (abs(value) < 1e-6 || mk == 0.0) break;
|
|
358
|
+
x = clamp(x - value / mk, 0.0, 1.0);
|
|
359
359
|
}
|
|
360
|
-
float
|
|
360
|
+
float jo = x * radius;
|
|
361
361
|
return vec2(
|
|
362
|
-
|
|
363
|
-
sqrt(max(radius * radius -
|
|
362
|
+
jo,
|
|
363
|
+
sqrt(max(radius * radius - jo * jo, 0.0))
|
|
364
364
|
);
|
|
365
365
|
}
|
|
366
366
|
|
|
367
|
-
float
|
|
368
|
-
if (
|
|
369
|
-
float
|
|
370
|
-
return
|
|
367
|
+
float iT(float radius, float gw) {
|
|
368
|
+
if (gw >= radius) return 0.0;
|
|
369
|
+
float oh = radius - gw;
|
|
370
|
+
return oh * oh * oh;
|
|
371
371
|
}
|
|
372
372
|
|
|
373
373
|
|
|
374
|
-
vec3
|
|
374
|
+
vec3 mu(ad source, float radius) {
|
|
375
375
|
vec3 geometricNormal = source.faceNormal;
|
|
376
376
|
if (dot(geometricNormal, source.vertexNormal) < 0.0) geometricNormal = -geometricNormal;
|
|
377
377
|
vec3 tangent;
|
|
378
378
|
vec3 bitangent;
|
|
379
379
|
aL(geometricNormal, tangent, bitangent);
|
|
380
|
-
vec3
|
|
381
|
-
|
|
382
|
-
for (int
|
|
383
|
-
vec2
|
|
384
|
-
float cA =
|
|
385
|
-
float
|
|
386
|
-
vec3
|
|
387
|
-
vec3
|
|
380
|
+
vec3 iF = vec3(0.0);
|
|
381
|
+
|
|
382
|
+
for (int ig = 0; ig < BEVEL_SAMPLES; ig++) {
|
|
383
|
+
vec2 ph = fo(CAMERA_BEVEL_BASE + uint(ig));
|
|
384
|
+
float cA = ph.x;
|
|
385
|
+
float oG = ph.y;
|
|
386
|
+
vec3 dj = geometricNormal;
|
|
387
|
+
vec3 fH = tangent;
|
|
388
388
|
vec3 ek = bitangent;
|
|
389
|
-
float
|
|
390
|
-
float
|
|
391
|
-
float
|
|
389
|
+
float ge = 0.5;
|
|
390
|
+
float hY = 0.25;
|
|
391
|
+
float gG = 0.25;
|
|
392
392
|
if (cA < 0.5) {
|
|
393
393
|
cA *= 2.0;
|
|
394
394
|
}
|
|
395
395
|
else if (cA < 0.75) {
|
|
396
|
-
vec3
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
396
|
+
vec3 mK = dj;
|
|
397
|
+
dj = fH;
|
|
398
|
+
fH = mK;
|
|
399
|
+
ge = 0.25;
|
|
400
|
+
hY = 0.5;
|
|
401
401
|
cA = (cA - 0.5) * 4.0;
|
|
402
402
|
}
|
|
403
403
|
else {
|
|
404
|
-
vec3
|
|
405
|
-
|
|
406
|
-
ek =
|
|
407
|
-
|
|
408
|
-
|
|
404
|
+
vec3 mK = dj;
|
|
405
|
+
dj = ek;
|
|
406
|
+
ek = mK;
|
|
407
|
+
ge = 0.25;
|
|
408
|
+
gG = 0.5;
|
|
409
409
|
cA = (cA - 0.75) * 4.0;
|
|
410
410
|
}
|
|
411
411
|
|
|
412
|
-
vec2
|
|
412
|
+
vec2 gU = kz(radius, oG);
|
|
413
413
|
float phi = TWOPI * cA;
|
|
414
|
-
vec3
|
|
415
|
-
(cos(phi) *
|
|
414
|
+
vec3 qv = gU.x *
|
|
415
|
+
(cos(phi) * fH + sin(phi) * ek);
|
|
416
416
|
Ray ray;
|
|
417
|
-
|
|
417
|
+
iC(
|
|
418
418
|
ray,
|
|
419
|
-
source.position +
|
|
420
|
-
-
|
|
419
|
+
source.position + dj * gU.y + qv,
|
|
420
|
+
-dj
|
|
421
421
|
);
|
|
422
422
|
ad hit;
|
|
423
|
-
|
|
423
|
+
iM(
|
|
424
424
|
ray,
|
|
425
425
|
hit,
|
|
426
426
|
source.instanceIndex,
|
|
427
|
-
max(2.0 *
|
|
427
|
+
max(2.0 * gU.y, EPS)
|
|
428
428
|
);
|
|
429
429
|
if (!hit.hit) continue;
|
|
430
430
|
|
|
431
|
-
float
|
|
432
|
-
float
|
|
433
|
-
float
|
|
434
|
-
float weight =
|
|
435
|
-
|
|
436
|
-
|
|
431
|
+
float kQ = ge * abs(dot(dj, hit.faceNormal));
|
|
432
|
+
float mG = hY * abs(dot(fH, hit.faceNormal));
|
|
433
|
+
float kb = gG * abs(dot(ek, hit.faceNormal));
|
|
434
|
+
float weight = kQ / max(
|
|
435
|
+
kQ * kQ + mG * mG +
|
|
436
|
+
kb * kb,
|
|
437
437
|
1e-8
|
|
438
438
|
);
|
|
439
|
-
weight *=
|
|
440
|
-
max(
|
|
441
|
-
|
|
439
|
+
weight *= iT(radius, distance(hit.position, source.position)) /
|
|
440
|
+
max(iT(radius, gU.x), 1e-8);
|
|
441
|
+
iF += weight * hit.vertexNormal;
|
|
442
442
|
}
|
|
443
443
|
|
|
444
|
-
if (dot(
|
|
445
|
-
vec3
|
|
446
|
-
vec3 result = source.normal +
|
|
444
|
+
if (dot(iF, iF) <= 1e-12) return source.normal;
|
|
445
|
+
vec3 jH = normalize(iF);
|
|
446
|
+
vec3 result = source.normal + jH - source.vertexNormal;
|
|
447
447
|
return dot(result, result) > 1e-12 ? normalize(result) : source.normal;
|
|
448
448
|
}
|
|
449
449
|
|
|
@@ -463,7 +463,7 @@ ${intelMac ? bounceCodeOnIntelMac : bounceCodeOnOther}
|
|
|
463
463
|
return vec4(aa.li, aa.alpha);
|
|
464
464
|
}
|
|
465
465
|
|
|
466
|
-
vec4
|
|
466
|
+
vec4 iD(ad si, Ray ray, J mat, inout RayTraceAuxiliary outAux) {
|
|
467
467
|
float coverage = clamp(mat.alpha, 0.0, 1.0);
|
|
468
468
|
if (!si.hit || (mat.materialType != STANDARD && mat.materialType != UNLIT) || coverage >= 1.0) {
|
|
469
469
|
return bw(si, ray, mat, outAux);
|
|
@@ -473,49 +473,49 @@ return bw(si, ray, mat, outAux);
|
|
|
473
473
|
|
|
474
474
|
|
|
475
475
|
|
|
476
|
-
Ray
|
|
477
|
-
|
|
478
|
-
ad
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
J
|
|
482
|
-
|
|
483
|
-
RayTraceAuxiliary
|
|
484
|
-
if (
|
|
485
|
-
|
|
476
|
+
Ray nY = ray;
|
|
477
|
+
nY.o = si.position + ray.d * (EPS * 0.02);
|
|
478
|
+
ad dE = si;
|
|
479
|
+
dE.albedoSampled = false;
|
|
480
|
+
cZ(nY, dE, false);
|
|
481
|
+
J nX;
|
|
482
|
+
eX(nX, dE.materialIndex, dE.uv, dE.uv1, dE.instanceIndex, dE.vertexColor);
|
|
483
|
+
RayTraceAuxiliary gm = outAux;
|
|
484
|
+
if (dE.hit && (nX.materialType == STANDARD || nX.materialType == UNLIT)) {
|
|
485
|
+
gm.albedo = nX.transmissionWeight > 0.5
|
|
486
486
|
? vec3(1.0)
|
|
487
|
-
:
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
487
|
+
: nX.baseColor;
|
|
488
|
+
gm.normal = dot(
|
|
489
|
+
dE.normal,
|
|
490
|
+
dE.position - vec3(viewInv[3])
|
|
491
491
|
) > 0.0
|
|
492
|
-
? -
|
|
493
|
-
:
|
|
494
|
-
|
|
492
|
+
? -dE.normal
|
|
493
|
+
: dE.normal;
|
|
494
|
+
dE.albedoSampled = nX.transmissionWeight > 0.5;
|
|
495
495
|
}
|
|
496
|
-
vec4 back = bw(
|
|
496
|
+
vec4 back = bw(dE, nY, nX, gm);
|
|
497
497
|
if (coverage <= 0.0) {
|
|
498
|
-
outAux =
|
|
498
|
+
outAux = gm;
|
|
499
499
|
return back;
|
|
500
500
|
}
|
|
501
501
|
|
|
502
|
-
ad
|
|
503
|
-
J
|
|
504
|
-
|
|
505
|
-
RayTraceAuxiliary
|
|
506
|
-
vec4
|
|
507
|
-
outAux.albedo = mix(
|
|
508
|
-
vec3
|
|
509
|
-
outAux.normal = dot(
|
|
510
|
-
? normalize(
|
|
502
|
+
ad tu = si;
|
|
503
|
+
J tR = mat;
|
|
504
|
+
tR.alpha = 1.0;
|
|
505
|
+
RayTraceAuxiliary iW = outAux;
|
|
506
|
+
vec4 qY = bw(tu, ray, tR, iW);
|
|
507
|
+
outAux.albedo = mix(gm.albedo, iW.albedo, coverage);
|
|
508
|
+
vec3 fV = mix(gm.normal, iW.normal, coverage);
|
|
509
|
+
outAux.normal = dot(fV, fV) > 1e-12
|
|
510
|
+
? normalize(fV)
|
|
511
511
|
: vec3(0.0);
|
|
512
|
-
outAux.isBlank =
|
|
513
|
-
return mix(back,
|
|
512
|
+
outAux.isBlank = gm.isBlank && iW.isBlank;
|
|
513
|
+
return mix(back, qY, coverage);
|
|
514
514
|
}
|
|
515
515
|
|
|
516
516
|
|
|
517
517
|
|
|
518
|
-
vec4
|
|
518
|
+
vec4 my(Ray ray, out RayTraceAuxiliary outAux) {
|
|
519
519
|
|
|
520
520
|
ad si;
|
|
521
521
|
J mat;
|
|
@@ -528,13 +528,13 @@ si.mediumScattering = vec3(0.0);
|
|
|
528
528
|
si.mediumAnisotropy = 0.0;
|
|
529
529
|
#endif
|
|
530
530
|
|
|
531
|
-
|
|
532
|
-
|
|
531
|
+
cZ(ray, si, false);
|
|
532
|
+
eX(mat, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);
|
|
533
533
|
si.isTransparency = mat.transmissionWeight > 0.001 || mat.subsurfaceWeight > 0.001 || mat.alpha < 0.999;
|
|
534
534
|
|
|
535
535
|
#ifdef HAS_BEVEL
|
|
536
536
|
if (bevelEnabled && mat.bevel > 0.0) {
|
|
537
|
-
si.normal =
|
|
537
|
+
si.normal = mu(si, mat.bevel);
|
|
538
538
|
}
|
|
539
539
|
#endif
|
|
540
540
|
|
|
@@ -551,32 +551,32 @@ si.albedoSampled = mat.transmissionWeight > 0.5;
|
|
|
551
551
|
}
|
|
552
552
|
|
|
553
553
|
if (mat.transmissionDispersionScale > 0.001) {
|
|
554
|
-
mat.specularIor =
|
|
554
|
+
mat.specularIor = eN(
|
|
555
555
|
bf,
|
|
556
556
|
mat.specularIor,
|
|
557
557
|
mat.transmissionDispersionScale,
|
|
558
558
|
mat.dispersionAbbeNumber
|
|
559
559
|
);
|
|
560
560
|
}
|
|
561
|
-
return
|
|
561
|
+
return iD(si, ray, mat, outAux);
|
|
562
562
|
}
|
|
563
563
|
|
|
564
564
|
void main() {
|
|
565
565
|
|
|
566
|
-
|
|
567
|
-
|
|
566
|
+
su();
|
|
567
|
+
kh(v_Texcoord * viewportSize, int(uint(sampleCount) ^ eg(uint(sequenceSeed))));
|
|
568
568
|
|
|
569
569
|
|
|
570
570
|
bf = dispersionWavelengths == 1 ? 0.0 : wavelength;
|
|
571
|
-
|
|
571
|
+
mw = wavelength;
|
|
572
572
|
if (dispersionWavelengths == 1 && wavelength > 0.0) {
|
|
573
573
|
float channel = floor(dz(CAMERA_WAVELENGTH) * 3.0);
|
|
574
|
-
|
|
574
|
+
mw = channel < 1.0 ? 650.0 : channel < 2.0 ? 510.0 : 475.0;
|
|
575
575
|
}
|
|
576
576
|
|
|
577
577
|
|
|
578
578
|
|
|
579
|
-
Ray cam =
|
|
579
|
+
Ray cam = nN();
|
|
580
580
|
|
|
581
581
|
RayTraceAuxiliary outAux;
|
|
582
582
|
outAux.albedo = vec3(0.0);
|
|
@@ -584,7 +584,7 @@ outAux.normal = vec3(0.0);
|
|
|
584
584
|
outAux.isBlank = false;
|
|
585
585
|
outAux.isShadowCatcher = false;
|
|
586
586
|
|
|
587
|
-
vec4 aF =
|
|
587
|
+
vec4 aF = my(cam, outAux);
|
|
588
588
|
|
|
589
589
|
|
|
590
590
|
|
|
@@ -612,10 +612,10 @@ out_albedo = vec4(outAux.albedo, outAux.isBlank ? 0.0 : 1.0);
|
|
|
612
612
|
out_normal = vec4(outAux.normal, 1.0);
|
|
613
613
|
|
|
614
614
|
|
|
615
|
-
float
|
|
615
|
+
float jq = dot(aF.rgb, vec3(0.2126, 0.7152, 0.0722));
|
|
616
616
|
out_moments = outAux.isShadowCatcher
|
|
617
617
|
? vec4(0.0)
|
|
618
|
-
: vec4(
|
|
618
|
+
: vec4(jq, jq * jq, 1.0, 0.0);
|
|
619
619
|
|
|
620
620
|
}`
|
|
621
621
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rayTrace.frag.js","sourceRoot":"","sources":["../../../src/renderer/glsl/rayTrace.frag.ts"],"names":[],"mappings":"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","sourcesContent":["import { MAX_PATH_EVENTS } from '../pathLimits.js';\nimport cameraRayGlsl from './chunks/cameraRay.glsl.js';\n// Portions adapted from ray-tracing-renderer@0.10.15\n// (https://github.com/hoverinc/ray-tracing-renderer).\n// Copyright (c) 2019 HOVER, MIT license; see LICENSES/RayTracingRenderer-MIT.txt.\n\nimport commonGlsl from './chunks/common.glsl.js';\nimport rayTraceCore from './chunks/rayTraceCore.glsl.js';\nimport textureLinear from './chunks/textureLinear.glsl.js';\nimport materialBufferGlsl from './chunks/materialBuffer.glsl.js';\nimport intersect from './chunks/intersect.glsl.js';\nimport randGlsl from './chunks/rand.glsl.js';\nimport random from './chunks/random.glsl.js';\nimport envMap from './chunks/envMap.glsl.js';\nimport sampleMaterialGlsl from './chunks/sampleMaterial.glsl.js';\nimport sampleLightGlsl from './chunks/sampleLight.glsl.js';\nimport { FragmentShader, glsl, Shader } from '../shader.js';\nimport openPbrBsdfGlsl from './chunks/openPbrBsdf.glsl.js';\nimport samplingGlsl from './chunks/sampling.glsl.js';\nimport { isIntelMac } from '../util.js';\nimport uvProjectionGlsl from './chunks/uvProjection.glsl.js';\n\nconst doubleTransmissionCheckCode = glsl`\n#if defined(HAS_TRANSMISSION) || defined(HAS_ALPHA)\n if (!si.isTransparency && BOUNCES < 16 && depth * 2 > BOUNCES) {\n path.abort = true;\n return;\n }\n#endif\n`;\n\n// bounce fix on intel mac\n// The intel mac only have one bounce if the loop is not unrolled\n// But windows will have extremely slow shader compilation if the loop is unrolled\n// So here the code are injected separately.\nconst bounceCodeOnIntelMac = glsl`\n// Mark loop can be unrolled\nfor(int _idx_ = 0; _idx_ < BOUNCES; _idx_++) {{\n if (path.abort) {\n return vec4(path.li, path.alpha);\n }\n bounce(path, depth, si, mat, outAux);\n}}\n`;\nconst bounceCodeOnOther = glsl`\nbool isOpaque = !si.isTransparency;\nint activeBounceLimit = min(BOUNCES, bounceLimit);\nfor(int idx = 0; idx < min(BOUNCES * 3, ${MAX_PATH_EVENTS}); idx++) {\n if (isOpaque && idx > activeBounceLimit) {\n path.abort = true;\n }\n if (path.abort) {\n return vec4(path.li, path.alpha);\n }\n bounce(path, depth, si, mat, outAux);\n}\n`;\n\nexport default function createRayTraceFragmentShader() {\n const intelMac = isIntelMac();\n return new FragmentShader({\n name: 'rayTraceFrag',\n outputs: ['color', 'albedo', 'normal', 'moments'],\n defines: {\n BOUNCES: 2\n },\n uniforms: {\n cameraApertureRadius: Shader.uniform('float', 0),\n cameraFocusDistance: Shader.uniform('float', 10),\n\n viewProjectionInv: Shader.uniform('mat4'),\n viewInv: Shader.uniform('mat4'),\n transmissiveOutputAlphaMin: Shader.uniform('float'),\n openPbrEnergyLut: Shader.uniform('sampler2D'),\n\n viewportSize: Shader.uniform('vec2'),\n\n wavelength: Shader.uniform('float', 0),\n bevelEnabled: Shader.uniform('bool', true),\n dispersionWavelengths: Shader.uniform('int', 3),\n bounceLimit: Shader.uniform('int', 8)\n },\n includes: [rayTraceCore, materialBufferGlsl, intersect, random, envMap],\n main: glsl`\n${commonGlsl}\n\n${randGlsl}\n${random.main}\n\n${textureLinear}\n\n${rayTraceCore.main}\n\n${uvProjectionGlsl}\n\n${materialBufferGlsl.main}\n${intersect.main}\n${envMap.main}\n\n${samplingGlsl}\n${openPbrBsdfGlsl}\n\nfloat heroWavelength;\nfloat pathWavelength;\n\n${sampleLightGlsl}\n${sampleMaterialGlsl}\n\n${cameraRayGlsl}\nstruct RayTraceAuxiliary {\n // Denoising guides and auxiliary pixel classification.\n vec3 albedo;\n vec3 normal;\n bool isBlank;\n // The primary ray hit a shadow catcher, whose sample the catcher pass owns.\n bool isShadowCatcher;\n};\n\nvoid bounce(inout Path path, inout int depth, inout SurfaceInteraction si, inout OpenPbrResolvedMaterial mat, inout RayTraceAuxiliary outAux) {\n samplingBounce = uint(max(depth, 0));\n // The bounce will be doubled on the transmission material.\n // For other materials. We will quite early\n // TODO It is only used on Mac with AMD card. If I enabled it on windows.\n // It will cause shader compilation too slow.\n${intelMac ? doubleTransmissionCheckCode : ''}\n\n bool isShadowCatcher = mat.materialType == SHADOW_CATCHER;\n if (isShadowCatcher) {\n if (path.fromEye) {\n // Match the composed shadow with neutral receiver guides, while keeping\n // background coverage and radiance independent of the invisible ground.\n outAux.albedo = vec3(1.0);\n outAux.normal = dot(si.normal, path.ray.d) > 0.0 ? -si.normal : si.normal;\n si.hit = false;\n outAux.isShadowCatcher = true;\n }\n else {\n // The catcher belongs only to the shadow-mask pass. Keep its default\n // white material out of glossy and transmission reflections.\n#ifdef USE_ENVMAP\n if (path.isNextRefraction) {\n // The invisible catcher can sit between a transmitted camera ray and\n // the grounded skybox. Use the displayed background here instead of\n // terminating early with the raw lighting environment.\n vec4 bg = sampleBackgroundFromRay(path.ray.o, path.ray.d);\n bg.rgb = sampling_spectral_rgb_filter(bg.rgb, pathWavelength);\n float backgroundMisWeight = path.scatteringIsDelta ? 1.0\n : sampling_power_heuristic(path.scatteringPdf,\n envMapPdf(cartesianToEquirect(path.ray.d)) * envLightSelectionPmf);\n path.li += backgroundMisWeight * path.beta * bg.rgb * bg.a;\n path.alpha = max(path.alpha, bg.a);\n }\n else {\n vec2 envUv = cartesianToEquirect(path.ray.d);\n vec3 emission = textureLinear(envMap, envUv).rgb;\n emission = sampling_spectral_rgb_filter(emission, pathWavelength);\n path.li += path.beta * emission *\n sampling_power_heuristic(\n path.scatteringPdf,\n envMapPdf(envUv) * envLightSelectionPmf\n );\n }\n#else\n vec4 bg = sampleBackgroundFromRay(path.ray.o, path.ray.d);\n bg.rgb = sampling_spectral_rgb_filter(bg.rgb, pathWavelength);\n path.li += path.beta * bg.rgb * bg.a;\n#endif\n path.abort = true;\n return;\n }\n }\n\n if (!si.hit) {\n // Sample from background if first ray not hit anything.\n vec4 bg = sampleBackgroundFromRay(path.ray.o, path.ray.d);\n // Dispersion renders one additive pass per RGB wavelength. Background\n // radiance has to be split in the same way as lights and emissive\n // surfaces, otherwise the full skybox is accumulated three times.\n bg.rgb = sampling_spectral_rgb_filter(bg.rgb, pathWavelength);\n if (path.fromEye) {\n path.li = bg.rgb * bg.a;\n path.alpha = bg.a;\n // Only treat as blank pixels when the background is transparent\n outAux.isBlank = bg.a < 0.01;\n }\n else {\n Ray cam = initCameraRay(v_Texcoord + pixelJitter());\n bool towardsCam = dot(cam.d, path.ray.d) > 0.0;\n if (transmissiveOutputAlphaMin < 1.0) {\n if (towardsCam) {\n path.alpha = max(path.alpha, bg.a);\n } else {\n path.alpha = 1.0;\n }\n }\n#if !defined(USE_ENVMAP)\n // TODO treat background as a light source\n if (towardsCam) {\n path.li = path.beta * sampling_power_heuristic(path.scatteringPdf, 1.0) * bg.rgb;\n }\n#endif\n }\n path.abort = true;\n return;\n }\n\n bool sampleIgnored = false;\n if ((mat.materialType == STANDARD || mat.materialType == UNLIT)) {\n if (transmissiveOutputAlphaMin < 1.0) {\n // TODO increase the alpha when there are more bounces.\n float alpha = max(1.0 - mat.transmissionWeight, 1.0 - pow(1.0 - transmissiveOutputAlphaMin, float(depth)));\n path.alpha = max(alpha, path.alpha);\n }\n float alpha = mat.alpha;\n if (alpha < 1.0) {\n // Alpha is sampled as stochastic coverage. An accepted surface branch\n // must use full radiance weight; multiplying by alpha again is biased.\n path.alpha = max(path.alpha, alpha);\n if (hashedSample(3u) > alpha) {\n sampleIgnored = true;\n }\n }\n if (!sampleIgnored) {\n SampleMaterial(si, mat, path);\n }\n else {\n path.ray.o = si.position + path.ray.d * EPS;\n }\n }\n\n if (!si.albedoSampled && !sampleIgnored) {\n // Select denoising guides.\n if ((mat.materialType == STANDARD || mat.materialType == UNLIT) &&\n !(mat.transmissionWeight > 0.5 ||\n (mat.specularRoughness <= 0.02 && mat.baseMetalness > 0.98))) {\n // Alpha-blended decals can be skipped stochastically. In that case keep\n // looking for the first useful rough-surface guide behind the decal,\n // even though it is reached after depth zero.\n outAux.albedo = mat.baseColor;\n outAux.normal = dot(si.normal, si.position - vec3(viewInv[3])) > 0.0\n ? -si.normal\n : si.normal;\n si.albedoSampled = true;\n }\n if (depth > 4) {\n si.albedoSampled = true;\n }\n }\n\n\n // Russian Roulette sampling\n#ifdef USE_RR\n if (depth >= RR_MAX && !sampleIgnored) {\n // Max-component survival (pbrt-v4) avoids over-amplifying saturated paths.\n float maxComponent = max(max(path.beta.x, path.beta.y), path.beta.z);\n float q = max(0.0, 1.0 - maxComponent);\n if (sample1D(bounceDim(RUSSIAN_ROULETTE)) < q) {\n // TODO we force use alpha 1.0 here.\n // To avoid the glass pixels is transparent even if it's on an opaque object.\n path.alpha = 1.0;\n path.abort = true;\n }\n else {\n path.beta /= 1.0 - q;\n }\n }\n#endif\n\n if (path.abort) {\n return;\n }\n\n // Next ray hit\n intersectScene(path.ray, si, true);\n getMaterial(mat, si.materialIndex, si.uv, si.uv1, si.instanceIndex);\n si.isTransparency = mat.transmissionWeight > 0.001 || mat.subsurfaceWeight > 0.001 || mat.alpha < 0.999;\n\n // Dynamic preview only becomes spectral when the primary visible surface\n // actually disperses transmitted light. Direct background and ordinary\n // opaque materials stay full RGB and therefore remain noise-free.\n if (dispersionWavelengths == 1 && si.hit && mat.transmissionWeight > 0.001 && mat.transmissionDispersionScale > 0.001) {\n pathWavelength = heroWavelength;\n }\n if (mat.transmissionWeight > 0.001 && pathWavelength > 0.0) {\n mat.specularIor = sampling_cauchy_ior(\n pathWavelength,\n mat.specularIor,\n mat.transmissionDispersionScale,\n mat.dispersionAbbeNumber\n );\n }\n\n if (sampleIgnored) {\n return;\n }\n\n bool isAlphaOccluded = hashedSample(3u) < mat.alpha;\n#ifdef NUM_LIGHTS\n // Use light if hit the light\n LightSampleRec lightSample;\n for (int i = 0; i < NUM_LIGHTS; i++) {\n // Fetch light Data\n Light light = fetchLight(i);\n float d = intersectLight(path.ray, light, lightSample);\n bool occluded = si.hit && d > distance(si.position, path.ray.o);\n if (d != INF && !(occluded && isAlphaOccluded)) {\n lightSample.pdf *= light.selectionPmf;\n float misWeight = sampling_power_heuristic(path.scatteringPdf, lightSample.pdf);\n lightSample.emission = sampling_spectral_rgb_filter(lightSample.emission, pathWavelength);\n path.li += misWeight * path.beta * lightSample.emission;\n // TODO set alpha to 1.0 will cause some sharp edges\n path.alpha = 1.0;\n path.abort = true;\n }\n }\n#endif\n\n#ifdef USE_ENVMAP\n if (!(si.hit && isAlphaOccluded)) {\n if (path.isNextRefraction) {\n // Camera-visible transmission must use the displayed background. The\n // raw environment remains the lighting source for non-transmission rays.\n vec4 bg = sampleBackgroundFromRay(path.ray.o, path.ray.d);\n bg.rgb = sampling_spectral_rgb_filter(bg.rgb, pathWavelength);\n float backgroundMisWeight = path.scatteringIsDelta ? 1.0\n : sampling_power_heuristic(path.scatteringPdf,\n envMapPdf(cartesianToEquirect(path.ray.d)) * envLightSelectionPmf);\n path.li += backgroundMisWeight * path.beta * bg.rgb * bg.a;\n path.alpha = max(path.alpha, bg.a);\n path.abort = true;\n return;\n }\n vec2 uv = cartesianToEquirect(path.ray.d);\n vec3 emission = textureLinear(envMap, uv).rgb;\n float misWeight = sampling_power_heuristic(\n path.scatteringPdf,\n envMapPdf(uv) * envLightSelectionPmf\n );\n emission = sampling_spectral_rgb_filter(emission, pathWavelength);\n path.li += path.beta * emission * misWeight;\n\n // TODO force the min alpha to be 1 when showing envmap as background\n #if !defined(USE_BACKGROUND)\n path.alpha = 1.0;\n #endif\n path.abort = true;\n return;\n }\n#endif\n\n depth++;\n}\n\n\nvec2 bevelCubicSample(float radius, float xi) {\n float x = 0.25;\n for (int iteration = 0; iteration < 10; iteration++) {\n float x2 = x * x;\n float x3 = x2 * x;\n float oneMinusX = 1.0 - x;\n float value = 10.0 * x2 - 20.0 * x3 + 15.0 * x2 * x2 -\n 4.0 * x2 * x3 - xi;\n float derivative = 20.0 * x * oneMinusX * oneMinusX * oneMinusX;\n if (abs(value) < 1e-6 || derivative == 0.0) break;\n x = clamp(x - value / derivative, 0.0, 1.0);\n }\n float diskRadius = x * radius;\n return vec2(\n diskRadius,\n sqrt(max(radius * radius - diskRadius * diskRadius, 0.0))\n );\n}\n\nfloat bevelCubicPdf(float radius, float distanceToSource) {\n if (distanceToSource >= radius) return 0.0;\n float falloff = radius - distanceToSource;\n return falloff * falloff * falloff;\n}\n\n// Shader bevel. Usage: docs/materials.md (Renderer extensions)\nvec3 getBevelNormal(SurfaceInteraction source, float radius) {\n vec3 geometricNormal = source.faceNormal;\n if (dot(geometricNormal, source.vertexNormal) < 0.0) geometricNormal = -geometricNormal;\n vec3 tangent;\n vec3 bitangent;\n sampling_orthonormal_basis(geometricNormal, tangent, bitangent);\n vec3 normalSum = vec3(0.0);\n\n for (int sampleIndex = 0; sampleIndex < BEVEL_SAMPLES; sampleIndex++) {\n vec2 bevelRnd = sample2D(CAMERA_BEVEL_BASE + uint(sampleIndex));\n float axisSample = bevelRnd.x;\n float radialSample = bevelRnd.y;\n vec3 diskNormal = geometricNormal;\n vec3 diskTangent = tangent;\n vec3 diskBitangent = bitangent;\n float pickPdfNormal = 0.5;\n float pickPdfTangent = 0.25;\n float pickPdfBitangent = 0.25;\n if (axisSample < 0.5) {\n axisSample *= 2.0;\n }\n else if (axisSample < 0.75) {\n vec3 swapAxis = diskNormal;\n diskNormal = diskTangent;\n diskTangent = swapAxis;\n pickPdfNormal = 0.25;\n pickPdfTangent = 0.5;\n axisSample = (axisSample - 0.5) * 4.0;\n }\n else {\n vec3 swapAxis = diskNormal;\n diskNormal = diskBitangent;\n diskBitangent = swapAxis;\n pickPdfNormal = 0.25;\n pickPdfBitangent = 0.5;\n axisSample = (axisSample - 0.75) * 4.0;\n }\n\n vec2 diskSample = bevelCubicSample(radius, radialSample);\n float phi = TWOPI * axisSample;\n vec3 diskOffset = diskSample.x *\n (cos(phi) * diskTangent + sin(phi) * diskBitangent);\n Ray ray;\n initRay(\n ray,\n source.position + diskNormal * diskSample.y + diskOffset,\n -diskNormal\n );\n SurfaceInteraction hit;\n intersectSceneBevel(\n ray,\n hit,\n source.instanceIndex,\n max(2.0 * diskSample.y, EPS)\n );\n if (!hit.hit) continue;\n\n float pdfNormal = pickPdfNormal * abs(dot(diskNormal, hit.faceNormal));\n float pdfTangent = pickPdfTangent * abs(dot(diskTangent, hit.faceNormal));\n float pdfBitangent = pickPdfBitangent * abs(dot(diskBitangent, hit.faceNormal));\n float weight = pdfNormal / max(\n pdfNormal * pdfNormal + pdfTangent * pdfTangent +\n pdfBitangent * pdfBitangent,\n 1e-8\n );\n weight *= bevelCubicPdf(radius, distance(hit.position, source.position)) /\n max(bevelCubicPdf(radius, diskSample.x), 1e-8);\n normalSum += weight * hit.vertexNormal;\n }\n\n if (dot(normalSum, normalSum) <= 1e-12) return source.normal;\n vec3 bevelVertexNormal = normalize(normalSum);\n vec3 result = source.normal + bevelVertexNormal - source.vertexNormal;\n return dot(result, result) > 1e-12 ? normalize(result) : source.normal;\n}\n\nvec4 integrateOnePathSample(SurfaceInteraction si, Ray ray, OpenPbrResolvedMaterial mat, inout RayTraceAuxiliary outAux) {\n Path path;\n path.ray = ray;\n path.li = vec3(0);\n path.alpha = transmissiveOutputAlphaMin < 1.0 ? 0.0 : 1.0;\n path.beta = vec3(1.0);\n path.fromEye = true;\n path.scatteringPdf = 0.0;\n path.scatteringIsDelta = false;\n path.isNextRefraction = false;\n path.abort = false;\n int depth = 0;\n${intelMac ? bounceCodeOnIntelMac : bounceCodeOnOther}\n return vec4(path.li, path.alpha);\n}\n\nvec4 integrateOnePath(SurfaceInteraction si, Ray ray, OpenPbrResolvedMaterial mat, inout RayTraceAuxiliary outAux) {\n float coverage = clamp(mat.alpha, 0.0, 1.0);\n if (!si.hit || (mat.materialType != STANDARD && mat.materialType != UNLIT) || coverage >= 1.0) {\n return integrateOnePathSample(si, ray, mat, outAux);\n }\n\n // glTF BLEND is source-over opacity, not a physical glass boundary. Split\n // the primary ray so reflected radiance is attenuated by alpha every sample\n // while the complementary branch continues straight to the scene behind it.\n // Secondary alpha hits remain stochastic to avoid exponential path growth.\n Ray backRay = ray;\n backRay.o = si.position + ray.d * (EPS * 0.02);\n SurfaceInteraction backSi = si;\n backSi.albedoSampled = false;\n intersectScene(backRay, backSi, false);\n OpenPbrResolvedMaterial backMat;\n getMaterial(backMat, backSi.materialIndex, backSi.uv, backSi.uv1, backSi.instanceIndex);\n RayTraceAuxiliary backAux = outAux;\n if (backSi.hit && (backMat.materialType == STANDARD || backMat.materialType == UNLIT)) {\n backAux.albedo = backMat.transmissionWeight > 0.5\n ? vec3(1.0)\n : backMat.baseColor;\n backAux.normal = dot(\n backSi.normal,\n backSi.position - vec3(viewInv[3])\n ) > 0.0\n ? -backSi.normal\n : backSi.normal;\n backSi.albedoSampled = backMat.transmissionWeight > 0.5;\n }\n vec4 back = integrateOnePathSample(backSi, backRay, backMat, backAux);\n if (coverage <= 0.0) {\n outAux = backAux;\n return back;\n }\n\n SurfaceInteraction frontSi = si;\n OpenPbrResolvedMaterial frontMat = mat;\n frontMat.alpha = 1.0;\n RayTraceAuxiliary frontAux = outAux;\n vec4 front = integrateOnePathSample(frontSi, ray, frontMat, frontAux);\n outAux.albedo = mix(backAux.albedo, frontAux.albedo, coverage);\n vec3 blendedNormal = mix(backAux.normal, frontAux.normal, coverage);\n outAux.normal = dot(blendedNormal, blendedNormal) > 1e-12\n ? normalize(blendedNormal)\n : vec3(0.0);\n outAux.isBlank = backAux.isBlank && frontAux.isBlank;\n return mix(back, front, coverage);\n}\n\n// Path tracing integrator as described in\n// http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Path_Tracing.html#\nvec4 integrator(Ray ray, out RayTraceAuxiliary outAux) {\n\n SurfaceInteraction si;\n OpenPbrResolvedMaterial mat;\n\n si.albedoSampled = false;\n#ifdef HAS_MEDIUM\n si.mediumType = 0;\n si.mediumExtinction = vec3(0.0);\n si.mediumScattering = vec3(0.0);\n si.mediumAnisotropy = 0.0;\n#endif\n\n intersectScene(ray, si, false);\n getMaterial(mat, si.materialIndex, si.uv, si.uv1, si.instanceIndex);\n si.isTransparency = mat.transmissionWeight > 0.001 || mat.subsurfaceWeight > 0.001 || mat.alpha < 0.999;\n\n#ifdef HAS_BEVEL\n if (bevelEnabled && mat.bevel > 0.0) {\n si.normal = getBevelNormal(si, mat.bevel);\n }\n#endif\n\n // Keep a clean first-hit fallback for denoising. Glass retains this stable\n // guide; other delta paths may replace it at their first non-delta hit.\n if (si.hit && (mat.materialType == STANDARD || mat.materialType == UNLIT)) {\n outAux.albedo = mat.transmissionWeight > 0.5 ? vec3(1.0) : mat.baseColor;\n outAux.normal = dot(si.normal, si.position - vec3(viewInv[3])) > 0.0\n ? -si.normal\n : si.normal;\n // A refracted/reflected continuation is stochastic and therefore not a\n // clean OIDN feature. Keep the stable primary glass guide instead.\n si.albedoSampled = mat.transmissionWeight > 0.5;\n }\n\n if (mat.transmissionDispersionScale > 0.001) {\n mat.specularIor = sampling_cauchy_ior(\n pathWavelength,\n mat.specularIor,\n mat.transmissionDispersionScale,\n mat.dispersionAbbeNumber\n );\n }\n return integrateOnePath(si, ray, mat, outAux);\n}\n\nvoid main() {\n\n initRandom();\n rng_initialize(v_Texcoord * viewportSize, int(uint(sampleCount) ^ sampleHash(uint(sequenceSeed))));\n\n\n pathWavelength = dispersionWavelengths == 1 ? 0.0 : wavelength;\n heroWavelength = wavelength;\n if (dispersionWavelengths == 1 && wavelength > 0.0) {\n float channel = floor(sample1D(CAMERA_WAVELENGTH) * 3.0);\n heroWavelength = channel < 1.0 ? 650.0 : channel < 2.0 ? 510.0 : 475.0;\n }\n\n // Thin lens model with depth-of-field\n // http://www.pbr-book.org/3ed-2018/Camera_Models/Projective_Camera_Models.html#TheThinLensModelandDepthofField\n Ray cam = primaryCameraRay();\n\n RayTraceAuxiliary outAux;\n outAux.albedo = vec3(0.0);\n outAux.normal = vec3(0.0);\n outAux.isBlank = false;\n outAux.isShadowCatcher = false;\n\n vec4 liAndAlpha = integrator(cam, outAux);\n\n // Clamp at Integration Level to reduce fireflies.\n // TODO Path level configuration?\n#ifdef CLAMPING\n float clamping = float(CLAMPING);\n liAndAlpha.rgb = clamp(liAndAlpha.rgb, -clamping, clamping);\n#endif\n\n // Each sample will be accumulated three times.\n if (pathWavelength > 0.0) {\n // RGB will be normalized using accumated hit in out_albedo.a\n liAndAlpha.rgb *= 3.0;\n if (dispersionWavelengths != 1) {\n // Full spectral samples use three additive passes. Preview only submits\n // one hero wavelength, so its alpha must not be divided.\n liAndAlpha.a /= 3.0;\n }\n }\n if (!(liAndAlpha.x < INF && liAndAlpha.x > -EPS)) {\n liAndAlpha = vec4(0, 0, 0, 1);\n }\n\n out_color = liAndAlpha;\n out_albedo = vec4(outAux.albedo, outAux.isBlank ? 0.0 : 1.0);\n out_normal = vec4(outAux.normal, 1.0);\n // Moments and count of the built-in denoiser's guide value. The catcher\n // pass accumulates its own samples (see shadowCatcher.frag).\n float guideValue = dot(liAndAlpha.rgb, vec3(0.2126, 0.7152, 0.0722));\n out_moments = outAux.isShadowCatcher\n ? vec4(0.0)\n : vec4(guideValue, guideValue * guideValue, 1.0, 0.0);\n\n}`\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"rayTrace.frag.js","sourceRoot":"","sources":["../../../src/renderer/glsl/rayTrace.frag.ts"],"names":[],"mappings":"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","sourcesContent":["import { MAX_PATH_EVENTS } from '../pathLimits.js';\nimport cameraRayGlsl from './chunks/cameraRay.glsl.js';\n// Portions adapted from ray-tracing-renderer@0.10.15\n// (https://github.com/hoverinc/ray-tracing-renderer).\n// Copyright (c) 2019 HOVER, MIT license; see LICENSES/RayTracingRenderer-MIT.txt.\n\nimport commonGlsl from './chunks/common.glsl.js';\nimport rayTraceCore from './chunks/rayTraceCore.glsl.js';\nimport textureLinear from './chunks/textureLinear.glsl.js';\nimport materialBufferGlsl from './chunks/materialBuffer.glsl.js';\nimport intersect from './chunks/intersect.glsl.js';\nimport randGlsl from './chunks/rand.glsl.js';\nimport random from './chunks/random.glsl.js';\nimport envMap from './chunks/envMap.glsl.js';\nimport sampleMaterialGlsl from './chunks/sampleMaterial.glsl.js';\nimport sampleLightGlsl from './chunks/sampleLight.glsl.js';\nimport { FragmentShader, glsl, Shader } from '../shader.js';\nimport openPbrBsdfGlsl from './chunks/openPbrBsdf.glsl.js';\nimport samplingGlsl from './chunks/sampling.glsl.js';\nimport { isIntelMac } from '../util.js';\nimport uvProjectionGlsl from './chunks/uvProjection.glsl.js';\n\nconst doubleTransmissionCheckCode = glsl`\n#if defined(HAS_TRANSMISSION) || defined(HAS_ALPHA)\n if (!si.isTransparency && BOUNCES < 16 && depth * 2 > BOUNCES) {\n path.abort = true;\n return;\n }\n#endif\n`;\n\n// bounce fix on intel mac\n// The intel mac only have one bounce if the loop is not unrolled\n// But windows will have extremely slow shader compilation if the loop is unrolled\n// So here the code are injected separately.\nconst bounceCodeOnIntelMac = glsl`\n// Mark loop can be unrolled\nfor(int _idx_ = 0; _idx_ < BOUNCES; _idx_++) {{\n if (path.abort) {\n return vec4(path.li, path.alpha);\n }\n bounce(path, depth, si, mat, outAux);\n}}\n`;\nconst bounceCodeOnOther = glsl`\nbool isOpaque = !si.isTransparency;\nint activeBounceLimit = min(BOUNCES, bounceLimit);\nfor(int idx = 0; idx < min(BOUNCES * 3, ${MAX_PATH_EVENTS}); idx++) {\n if (isOpaque && idx > activeBounceLimit) {\n path.abort = true;\n }\n if (path.abort) {\n return vec4(path.li, path.alpha);\n }\n bounce(path, depth, si, mat, outAux);\n}\n`;\n\nexport default function createRayTraceFragmentShader() {\n const intelMac = isIntelMac();\n return new FragmentShader({\n name: 'rayTraceFrag',\n outputs: ['color', 'albedo', 'normal', 'moments'],\n defines: {\n BOUNCES: 2\n },\n uniforms: {\n cameraApertureRadius: Shader.uniform('float', 0),\n cameraFocusDistance: Shader.uniform('float', 10),\n\n viewProjectionInv: Shader.uniform('mat4'),\n viewInv: Shader.uniform('mat4'),\n transmissiveOutputAlphaMin: Shader.uniform('float'),\n openPbrEnergyLut: Shader.uniform('sampler2D'),\n\n viewportSize: Shader.uniform('vec2'),\n\n wavelength: Shader.uniform('float', 0),\n bevelEnabled: Shader.uniform('bool', true),\n dispersionWavelengths: Shader.uniform('int', 3),\n bounceLimit: Shader.uniform('int', 8)\n },\n includes: [rayTraceCore, materialBufferGlsl, intersect, random, envMap],\n main: glsl`\n${commonGlsl}\n\n${randGlsl}\n${random.main}\n\n${textureLinear}\n\n${rayTraceCore.main}\n\n${uvProjectionGlsl}\n\n${materialBufferGlsl.main}\n${intersect.main}\n${envMap.main}\n\n${samplingGlsl}\n${openPbrBsdfGlsl}\n\nfloat heroWavelength;\nfloat pathWavelength;\n\n${sampleLightGlsl}\n${sampleMaterialGlsl}\n\n${cameraRayGlsl}\nstruct RayTraceAuxiliary {\n // Denoising guides and auxiliary pixel classification.\n vec3 albedo;\n vec3 normal;\n bool isBlank;\n // The primary ray hit a shadow catcher, whose sample the catcher pass owns.\n bool isShadowCatcher;\n};\n\nvoid bounce(inout Path path, inout int depth, inout SurfaceInteraction si, inout OpenPbrResolvedMaterial mat, inout RayTraceAuxiliary outAux) {\n samplingBounce = uint(max(depth, 0));\n // The bounce will be doubled on the transmission material.\n // For other materials. We will quite early\n // TODO It is only used on Mac with AMD card. If I enabled it on windows.\n // It will cause shader compilation too slow.\n${intelMac ? doubleTransmissionCheckCode : ''}\n\n bool isShadowCatcher = mat.materialType == SHADOW_CATCHER;\n if (isShadowCatcher) {\n if (path.fromEye) {\n // Match the composed shadow with neutral receiver guides, while keeping\n // background coverage and radiance independent of the invisible ground.\n outAux.albedo = vec3(1.0);\n outAux.normal = dot(si.normal, path.ray.d) > 0.0 ? -si.normal : si.normal;\n si.hit = false;\n outAux.isShadowCatcher = true;\n }\n else {\n // The catcher belongs only to the shadow-mask pass. Keep its default\n // white material out of glossy and transmission reflections.\n#ifdef USE_ENVMAP\n if (path.isNextRefraction) {\n // The invisible catcher can sit between a transmitted camera ray and\n // the grounded skybox. Use the displayed background here instead of\n // terminating early with the raw lighting environment.\n vec4 bg = sampleBackgroundFromRay(path.ray.o, path.ray.d);\n bg.rgb = sampling_spectral_rgb_filter(bg.rgb, pathWavelength);\n float backgroundMisWeight = path.scatteringIsDelta ? 1.0\n : sampling_power_heuristic(path.scatteringPdf,\n envMapPdf(environmentUv(path.ray.d)) * envLightSelectionPmf);\n path.li += backgroundMisWeight * path.beta * bg.rgb * bg.a;\n path.alpha = max(path.alpha, bg.a);\n }\n else {\n vec2 envUv = environmentUv(path.ray.d);\n vec3 emission = textureLinear(envMap, envUv).rgb;\n emission = sampling_spectral_rgb_filter(emission, pathWavelength);\n path.li += path.beta * emission *\n sampling_power_heuristic(\n path.scatteringPdf,\n envMapPdf(envUv) * envLightSelectionPmf\n );\n }\n#else\n vec4 bg = sampleBackgroundFromRay(path.ray.o, path.ray.d);\n bg.rgb = sampling_spectral_rgb_filter(bg.rgb, pathWavelength);\n path.li += path.beta * bg.rgb * bg.a;\n#endif\n path.abort = true;\n return;\n }\n }\n\n if (!si.hit) {\n // Sample from background if first ray not hit anything.\n vec4 bg = sampleBackgroundFromRay(path.ray.o, path.ray.d);\n // Dispersion renders one additive pass per RGB wavelength. Background\n // radiance has to be split in the same way as lights and emissive\n // surfaces, otherwise the full skybox is accumulated three times.\n bg.rgb = sampling_spectral_rgb_filter(bg.rgb, pathWavelength);\n if (path.fromEye) {\n path.li = bg.rgb * bg.a;\n path.alpha = bg.a;\n // Only treat as blank pixels when the background is transparent\n outAux.isBlank = bg.a < 0.01;\n }\n else {\n Ray cam = initCameraRay(v_Texcoord + pixelJitter());\n bool towardsCam = dot(cam.d, path.ray.d) > 0.0;\n if (transmissiveOutputAlphaMin < 1.0) {\n if (towardsCam) {\n path.alpha = max(path.alpha, bg.a);\n } else {\n path.alpha = 1.0;\n }\n }\n#if !defined(USE_ENVMAP)\n // TODO treat background as a light source\n if (towardsCam) {\n path.li = path.beta * sampling_power_heuristic(path.scatteringPdf, 1.0) * bg.rgb;\n }\n#endif\n }\n path.abort = true;\n return;\n }\n\n bool sampleIgnored = false;\n if ((mat.materialType == STANDARD || mat.materialType == UNLIT)) {\n if (transmissiveOutputAlphaMin < 1.0) {\n // TODO increase the alpha when there are more bounces.\n float alpha = max(1.0 - mat.transmissionWeight, 1.0 - pow(1.0 - transmissiveOutputAlphaMin, float(depth)));\n path.alpha = max(alpha, path.alpha);\n }\n float alpha = mat.alpha;\n if (alpha < 1.0) {\n // Alpha is sampled as stochastic coverage. An accepted surface branch\n // must use full radiance weight; multiplying by alpha again is biased.\n path.alpha = max(path.alpha, alpha);\n if (hashedSample(3u) > alpha) {\n sampleIgnored = true;\n }\n }\n if (!sampleIgnored) {\n SampleMaterial(si, mat, path);\n }\n else {\n path.ray.o = si.position + path.ray.d * EPS;\n }\n }\n\n if (!si.albedoSampled && !sampleIgnored) {\n // Select denoising guides.\n if ((mat.materialType == STANDARD || mat.materialType == UNLIT) &&\n !(mat.transmissionWeight > 0.5 ||\n (mat.specularRoughness <= 0.02 && mat.baseMetalness > 0.98))) {\n // Alpha-blended decals can be skipped stochastically. In that case keep\n // looking for the first useful rough-surface guide behind the decal,\n // even though it is reached after depth zero.\n outAux.albedo = mat.baseColor;\n outAux.normal = dot(si.normal, si.position - vec3(viewInv[3])) > 0.0\n ? -si.normal\n : si.normal;\n si.albedoSampled = true;\n }\n if (depth > 4) {\n si.albedoSampled = true;\n }\n }\n\n\n // Russian Roulette sampling\n#ifdef USE_RR\n if (depth >= RR_MAX && !sampleIgnored) {\n // Max-component survival (pbrt-v4) avoids over-amplifying saturated paths.\n float maxComponent = max(max(path.beta.x, path.beta.y), path.beta.z);\n float q = max(0.0, 1.0 - maxComponent);\n if (sample1D(bounceDim(RUSSIAN_ROULETTE)) < q) {\n // TODO we force use alpha 1.0 here.\n // To avoid the glass pixels is transparent even if it's on an opaque object.\n path.alpha = 1.0;\n path.abort = true;\n }\n else {\n path.beta /= 1.0 - q;\n }\n }\n#endif\n\n if (path.abort) {\n return;\n }\n\n // Next ray hit\n intersectScene(path.ray, si, true);\n getMaterial(mat, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);\n si.isTransparency = mat.transmissionWeight > 0.001 || mat.subsurfaceWeight > 0.001 || mat.alpha < 0.999;\n\n // Dynamic preview only becomes spectral when the primary visible surface\n // actually disperses transmitted light. Direct background and ordinary\n // opaque materials stay full RGB and therefore remain noise-free.\n if (dispersionWavelengths == 1 && si.hit && mat.transmissionWeight > 0.001 && mat.transmissionDispersionScale > 0.001) {\n pathWavelength = heroWavelength;\n }\n if (mat.transmissionWeight > 0.001 && pathWavelength > 0.0) {\n mat.specularIor = sampling_cauchy_ior(\n pathWavelength,\n mat.specularIor,\n mat.transmissionDispersionScale,\n mat.dispersionAbbeNumber\n );\n }\n\n if (sampleIgnored) {\n return;\n }\n\n bool isAlphaOccluded = hashedSample(3u) < mat.alpha;\n#ifdef NUM_LIGHTS\n // Use light if hit the light\n LightSampleRec lightSample;\n for (int i = 0; i < NUM_LIGHTS; i++) {\n // Fetch light Data\n Light light = fetchLight(i);\n float d = intersectLight(path.ray, light, lightSample);\n bool occluded = si.hit && d > distance(si.position, path.ray.o);\n if (d != INF && !(occluded && isAlphaOccluded)) {\n lightSample.pdf *= light.selectionPmf;\n float misWeight = sampling_power_heuristic(path.scatteringPdf, lightSample.pdf);\n lightSample.emission = sampling_spectral_rgb_filter(lightSample.emission, pathWavelength);\n path.li += misWeight * path.beta * lightSample.emission;\n // TODO set alpha to 1.0 will cause some sharp edges\n path.alpha = 1.0;\n path.abort = true;\n }\n }\n#endif\n\n#ifdef USE_ENVMAP\n if (!(si.hit && isAlphaOccluded)) {\n if (path.isNextRefraction) {\n // Camera-visible transmission must use the displayed background. The\n // raw environment remains the lighting source for non-transmission rays.\n vec4 bg = sampleBackgroundFromRay(path.ray.o, path.ray.d);\n bg.rgb = sampling_spectral_rgb_filter(bg.rgb, pathWavelength);\n float backgroundMisWeight = path.scatteringIsDelta ? 1.0\n : sampling_power_heuristic(path.scatteringPdf,\n envMapPdf(environmentUv(path.ray.d)) * envLightSelectionPmf);\n path.li += backgroundMisWeight * path.beta * bg.rgb * bg.a;\n path.alpha = max(path.alpha, bg.a);\n path.abort = true;\n return;\n }\n vec2 uv = environmentUv(path.ray.d);\n vec3 emission = textureLinear(envMap, uv).rgb;\n float misWeight = sampling_power_heuristic(\n path.scatteringPdf,\n envMapPdf(uv) * envLightSelectionPmf\n );\n emission = sampling_spectral_rgb_filter(emission, pathWavelength);\n path.li += path.beta * emission * misWeight;\n\n // TODO force the min alpha to be 1 when showing envmap as background\n #if !defined(USE_BACKGROUND)\n path.alpha = 1.0;\n #endif\n path.abort = true;\n return;\n }\n#endif\n\n depth++;\n}\n\n\nvec2 bevelCubicSample(float radius, float xi) {\n float x = 0.25;\n for (int iteration = 0; iteration < 10; iteration++) {\n float x2 = x * x;\n float x3 = x2 * x;\n float oneMinusX = 1.0 - x;\n float value = 10.0 * x2 - 20.0 * x3 + 15.0 * x2 * x2 -\n 4.0 * x2 * x3 - xi;\n float derivative = 20.0 * x * oneMinusX * oneMinusX * oneMinusX;\n if (abs(value) < 1e-6 || derivative == 0.0) break;\n x = clamp(x - value / derivative, 0.0, 1.0);\n }\n float diskRadius = x * radius;\n return vec2(\n diskRadius,\n sqrt(max(radius * radius - diskRadius * diskRadius, 0.0))\n );\n}\n\nfloat bevelCubicPdf(float radius, float distanceToSource) {\n if (distanceToSource >= radius) return 0.0;\n float falloff = radius - distanceToSource;\n return falloff * falloff * falloff;\n}\n\n// Shader bevel. Usage: docs/materials.md (Renderer extensions)\nvec3 getBevelNormal(SurfaceInteraction source, float radius) {\n vec3 geometricNormal = source.faceNormal;\n if (dot(geometricNormal, source.vertexNormal) < 0.0) geometricNormal = -geometricNormal;\n vec3 tangent;\n vec3 bitangent;\n sampling_orthonormal_basis(geometricNormal, tangent, bitangent);\n vec3 normalSum = vec3(0.0);\n\n for (int sampleIndex = 0; sampleIndex < BEVEL_SAMPLES; sampleIndex++) {\n vec2 bevelRnd = sample2D(CAMERA_BEVEL_BASE + uint(sampleIndex));\n float axisSample = bevelRnd.x;\n float radialSample = bevelRnd.y;\n vec3 diskNormal = geometricNormal;\n vec3 diskTangent = tangent;\n vec3 diskBitangent = bitangent;\n float pickPdfNormal = 0.5;\n float pickPdfTangent = 0.25;\n float pickPdfBitangent = 0.25;\n if (axisSample < 0.5) {\n axisSample *= 2.0;\n }\n else if (axisSample < 0.75) {\n vec3 swapAxis = diskNormal;\n diskNormal = diskTangent;\n diskTangent = swapAxis;\n pickPdfNormal = 0.25;\n pickPdfTangent = 0.5;\n axisSample = (axisSample - 0.5) * 4.0;\n }\n else {\n vec3 swapAxis = diskNormal;\n diskNormal = diskBitangent;\n diskBitangent = swapAxis;\n pickPdfNormal = 0.25;\n pickPdfBitangent = 0.5;\n axisSample = (axisSample - 0.75) * 4.0;\n }\n\n vec2 diskSample = bevelCubicSample(radius, radialSample);\n float phi = TWOPI * axisSample;\n vec3 diskOffset = diskSample.x *\n (cos(phi) * diskTangent + sin(phi) * diskBitangent);\n Ray ray;\n initRay(\n ray,\n source.position + diskNormal * diskSample.y + diskOffset,\n -diskNormal\n );\n SurfaceInteraction hit;\n intersectSceneBevel(\n ray,\n hit,\n source.instanceIndex,\n max(2.0 * diskSample.y, EPS)\n );\n if (!hit.hit) continue;\n\n float pdfNormal = pickPdfNormal * abs(dot(diskNormal, hit.faceNormal));\n float pdfTangent = pickPdfTangent * abs(dot(diskTangent, hit.faceNormal));\n float pdfBitangent = pickPdfBitangent * abs(dot(diskBitangent, hit.faceNormal));\n float weight = pdfNormal / max(\n pdfNormal * pdfNormal + pdfTangent * pdfTangent +\n pdfBitangent * pdfBitangent,\n 1e-8\n );\n weight *= bevelCubicPdf(radius, distance(hit.position, source.position)) /\n max(bevelCubicPdf(radius, diskSample.x), 1e-8);\n normalSum += weight * hit.vertexNormal;\n }\n\n if (dot(normalSum, normalSum) <= 1e-12) return source.normal;\n vec3 bevelVertexNormal = normalize(normalSum);\n vec3 result = source.normal + bevelVertexNormal - source.vertexNormal;\n return dot(result, result) > 1e-12 ? normalize(result) : source.normal;\n}\n\nvec4 integrateOnePathSample(SurfaceInteraction si, Ray ray, OpenPbrResolvedMaterial mat, inout RayTraceAuxiliary outAux) {\n Path path;\n path.ray = ray;\n path.li = vec3(0);\n path.alpha = transmissiveOutputAlphaMin < 1.0 ? 0.0 : 1.0;\n path.beta = vec3(1.0);\n path.fromEye = true;\n path.scatteringPdf = 0.0;\n path.scatteringIsDelta = false;\n path.isNextRefraction = false;\n path.abort = false;\n int depth = 0;\n${intelMac ? bounceCodeOnIntelMac : bounceCodeOnOther}\n return vec4(path.li, path.alpha);\n}\n\nvec4 integrateOnePath(SurfaceInteraction si, Ray ray, OpenPbrResolvedMaterial mat, inout RayTraceAuxiliary outAux) {\n float coverage = clamp(mat.alpha, 0.0, 1.0);\n if (!si.hit || (mat.materialType != STANDARD && mat.materialType != UNLIT) || coverage >= 1.0) {\n return integrateOnePathSample(si, ray, mat, outAux);\n }\n\n // glTF BLEND is source-over opacity, not a physical glass boundary. Split\n // the primary ray so reflected radiance is attenuated by alpha every sample\n // while the complementary branch continues straight to the scene behind it.\n // Secondary alpha hits remain stochastic to avoid exponential path growth.\n Ray backRay = ray;\n backRay.o = si.position + ray.d * (EPS * 0.02);\n SurfaceInteraction backSi = si;\n backSi.albedoSampled = false;\n intersectScene(backRay, backSi, false);\n OpenPbrResolvedMaterial backMat;\n getMaterial(backMat, backSi.materialIndex, backSi.uv, backSi.uv1, backSi.instanceIndex, backSi.vertexColor);\n RayTraceAuxiliary backAux = outAux;\n if (backSi.hit && (backMat.materialType == STANDARD || backMat.materialType == UNLIT)) {\n backAux.albedo = backMat.transmissionWeight > 0.5\n ? vec3(1.0)\n : backMat.baseColor;\n backAux.normal = dot(\n backSi.normal,\n backSi.position - vec3(viewInv[3])\n ) > 0.0\n ? -backSi.normal\n : backSi.normal;\n backSi.albedoSampled = backMat.transmissionWeight > 0.5;\n }\n vec4 back = integrateOnePathSample(backSi, backRay, backMat, backAux);\n if (coverage <= 0.0) {\n outAux = backAux;\n return back;\n }\n\n SurfaceInteraction frontSi = si;\n OpenPbrResolvedMaterial frontMat = mat;\n frontMat.alpha = 1.0;\n RayTraceAuxiliary frontAux = outAux;\n vec4 front = integrateOnePathSample(frontSi, ray, frontMat, frontAux);\n outAux.albedo = mix(backAux.albedo, frontAux.albedo, coverage);\n vec3 blendedNormal = mix(backAux.normal, frontAux.normal, coverage);\n outAux.normal = dot(blendedNormal, blendedNormal) > 1e-12\n ? normalize(blendedNormal)\n : vec3(0.0);\n outAux.isBlank = backAux.isBlank && frontAux.isBlank;\n return mix(back, front, coverage);\n}\n\n// Path tracing integrator as described in\n// http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Path_Tracing.html#\nvec4 integrator(Ray ray, out RayTraceAuxiliary outAux) {\n\n SurfaceInteraction si;\n OpenPbrResolvedMaterial mat;\n\n si.albedoSampled = false;\n#ifdef HAS_MEDIUM\n si.mediumType = 0;\n si.mediumExtinction = vec3(0.0);\n si.mediumScattering = vec3(0.0);\n si.mediumAnisotropy = 0.0;\n#endif\n\n intersectScene(ray, si, false);\n getMaterial(mat, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);\n si.isTransparency = mat.transmissionWeight > 0.001 || mat.subsurfaceWeight > 0.001 || mat.alpha < 0.999;\n\n#ifdef HAS_BEVEL\n if (bevelEnabled && mat.bevel > 0.0) {\n si.normal = getBevelNormal(si, mat.bevel);\n }\n#endif\n\n // Keep a clean first-hit fallback for denoising. Glass retains this stable\n // guide; other delta paths may replace it at their first non-delta hit.\n if (si.hit && (mat.materialType == STANDARD || mat.materialType == UNLIT)) {\n outAux.albedo = mat.transmissionWeight > 0.5 ? vec3(1.0) : mat.baseColor;\n outAux.normal = dot(si.normal, si.position - vec3(viewInv[3])) > 0.0\n ? -si.normal\n : si.normal;\n // A refracted/reflected continuation is stochastic and therefore not a\n // clean OIDN feature. Keep the stable primary glass guide instead.\n si.albedoSampled = mat.transmissionWeight > 0.5;\n }\n\n if (mat.transmissionDispersionScale > 0.001) {\n mat.specularIor = sampling_cauchy_ior(\n pathWavelength,\n mat.specularIor,\n mat.transmissionDispersionScale,\n mat.dispersionAbbeNumber\n );\n }\n return integrateOnePath(si, ray, mat, outAux);\n}\n\nvoid main() {\n\n initRandom();\n rng_initialize(v_Texcoord * viewportSize, int(uint(sampleCount) ^ sampleHash(uint(sequenceSeed))));\n\n\n pathWavelength = dispersionWavelengths == 1 ? 0.0 : wavelength;\n heroWavelength = wavelength;\n if (dispersionWavelengths == 1 && wavelength > 0.0) {\n float channel = floor(sample1D(CAMERA_WAVELENGTH) * 3.0);\n heroWavelength = channel < 1.0 ? 650.0 : channel < 2.0 ? 510.0 : 475.0;\n }\n\n // Thin lens model with depth-of-field\n // http://www.pbr-book.org/3ed-2018/Camera_Models/Projective_Camera_Models.html#TheThinLensModelandDepthofField\n Ray cam = primaryCameraRay();\n\n RayTraceAuxiliary outAux;\n outAux.albedo = vec3(0.0);\n outAux.normal = vec3(0.0);\n outAux.isBlank = false;\n outAux.isShadowCatcher = false;\n\n vec4 liAndAlpha = integrator(cam, outAux);\n\n // Clamp at Integration Level to reduce fireflies.\n // TODO Path level configuration?\n#ifdef CLAMPING\n float clamping = float(CLAMPING);\n liAndAlpha.rgb = clamp(liAndAlpha.rgb, -clamping, clamping);\n#endif\n\n // Each sample will be accumulated three times.\n if (pathWavelength > 0.0) {\n // RGB will be normalized using accumated hit in out_albedo.a\n liAndAlpha.rgb *= 3.0;\n if (dispersionWavelengths != 1) {\n // Full spectral samples use three additive passes. Preview only submits\n // one hero wavelength, so its alpha must not be divided.\n liAndAlpha.a /= 3.0;\n }\n }\n if (!(liAndAlpha.x < INF && liAndAlpha.x > -EPS)) {\n liAndAlpha = vec4(0, 0, 0, 1);\n }\n\n out_color = liAndAlpha;\n out_albedo = vec4(outAux.albedo, outAux.isBlank ? 0.0 : 1.0);\n out_normal = vec4(outAux.normal, 1.0);\n // Moments and count of the built-in denoiser's guide value. The catcher\n // pass accumulates its own samples (see shadowCatcher.frag).\n float guideValue = dot(liAndAlpha.rgb, vec3(0.2126, 0.7152, 0.0722));\n out_moments = outAux.isShadowCatcher\n ? vec4(0.0)\n : vec4(guideValue, guideValue * guideValue, 1.0, 0.0);\n\n}`\n });\n}\n"]}
|