@meimu/mutracer 0.2.0 → 0.3.0
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/README.md +3 -0
- package/dist/assets/bvh.worker.js +1 -1
- package/dist/mutracer.umd.js +8949 -7915
- package/docs/api.md +42 -21
- package/docs/caustics.md +80 -0
- package/docs/materials.md +5 -4
- package/docs/progressive-rendering.md +50 -9
- package/docs/technical/continuous-spectrum.md +93 -0
- package/docs/updates.md +3 -1
- package/docs/viewer-checklist.md +65 -0
- package/docs/viewer.md +7 -5
- package/lib/Display.js +1 -1
- package/lib/Display.js.map +1 -1
- package/lib/Engine.d.ts +2 -0
- package/lib/Engine.js +47 -12
- package/lib/Engine.js.map +1 -1
- package/lib/Render.d.ts +61 -13
- package/lib/Render.js +169 -19
- package/lib/Render.js.map +1 -1
- package/lib/RenderLoop.d.ts +7 -3
- package/lib/RenderLoop.js +68 -44
- package/lib/RenderLoop.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/GPUTraceQueue.d.ts +2 -1
- package/lib/renderer/GPUTraceQueue.js +3 -1
- package/lib/renderer/GPUTraceQueue.js.map +1 -1
- package/lib/renderer/RenderingPipeline.d.ts +4 -0
- package/lib/renderer/RenderingPipeline.js.map +1 -1
- package/lib/renderer/WGPUCausticLightPass.d.ts +48 -0
- package/lib/renderer/WGPUCausticLightPass.js +217 -0
- package/lib/renderer/WGPUCausticLightPass.js.map +1 -0
- package/lib/renderer/WGPUEnvMapDistribution.js +18 -18
- package/lib/renderer/WGPUFullQuadPass.js +3 -3
- package/lib/renderer/WGPUPhotonMap.d.ts +37 -0
- package/lib/renderer/WGPUPhotonMap.js +191 -0
- package/lib/renderer/WGPUPhotonMap.js.map +1 -0
- package/lib/renderer/WGPURayTraceOutput.d.ts +13 -1
- package/lib/renderer/WGPURayTraceOutput.js +122 -28
- package/lib/renderer/WGPURayTraceOutput.js.map +1 -1
- package/lib/renderer/WGPURayTracePass.d.ts +48 -17
- package/lib/renderer/WGPURayTracePass.js +538 -340
- package/lib/renderer/WGPURayTracePass.js.map +1 -1
- package/lib/renderer/WGPURenderingPipeline.js +83 -47
- package/lib/renderer/WGPURenderingPipeline.js.map +1 -1
- package/lib/renderer/WebGLFullQuadPass.d.ts +2 -1
- package/lib/renderer/WebGLFullQuadPass.js +4 -0
- package/lib/renderer/WebGLFullQuadPass.js.map +1 -1
- package/lib/renderer/WebGLJNLMDenoiser.js +66 -66
- package/lib/renderer/WebGLRayTraceOutputPass.js +4 -4
- package/lib/renderer/WebGLRayTracePass.d.ts +6 -1
- package/lib/renderer/WebGLRayTracePass.js +43 -6
- package/lib/renderer/WebGLRayTracePass.js.map +1 -1
- package/lib/renderer/WebGLRenderingPipeline.js +10 -14
- package/lib/renderer/WebGLRenderingPipeline.js.map +1 -1
- package/lib/renderer/WebGLSkyBaker.js +60 -60
- package/lib/renderer/accumulationTarget.d.ts +2 -1
- package/lib/renderer/accumulationTarget.js.map +1 -1
- package/lib/renderer/causticDiagnostics.d.ts +31 -0
- package/lib/renderer/causticDiagnostics.js +5 -0
- package/lib/renderer/causticDiagnostics.js.map +1 -0
- package/lib/renderer/causticEmission.d.ts +10 -0
- package/lib/renderer/causticEmission.js +40 -0
- package/lib/renderer/causticEmission.js.map +1 -0
- package/lib/renderer/causticUniform.d.ts +12 -0
- package/lib/renderer/causticUniform.js +22 -0
- package/lib/renderer/causticUniform.js.map +1 -0
- package/lib/renderer/caustics.d.ts +16 -0
- package/lib/renderer/caustics.js +93 -0
- package/lib/renderer/caustics.js.map +1 -0
- package/lib/renderer/glsl/aovDisplay.frag.js +5 -5
- package/lib/renderer/glsl/aovReflectance.glsl.js +53 -53
- package/lib/renderer/glsl/aovReflectanceSamples.glsl.js +1 -1
- package/lib/renderer/glsl/aovTrace.frag.js +33 -33
- package/lib/renderer/glsl/chunks/cameraRay.glsl.js +9 -9
- package/lib/renderer/glsl/chunks/emissiveLight.glsl.d.ts +2 -0
- package/lib/renderer/glsl/chunks/emissiveLight.glsl.js +35 -0
- package/lib/renderer/glsl/chunks/emissiveLight.glsl.js.map +1 -0
- package/lib/renderer/glsl/chunks/envMap.glsl.js +73 -73
- package/lib/renderer/glsl/chunks/intersect.glsl.js +426 -428
- package/lib/renderer/glsl/chunks/intersect.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/materialBuffer.glsl.d.ts +1 -0
- package/lib/renderer/glsl/chunks/materialBuffer.glsl.js +156 -153
- package/lib/renderer/glsl/chunks/materialBuffer.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/openPbrBsdf.glsl.js +771 -771
- package/lib/renderer/glsl/chunks/rand.glsl.js +3 -3
- package/lib/renderer/glsl/chunks/random.glsl.js +6 -6
- package/lib/renderer/glsl/chunks/rayTraceCore.glsl.d.ts +1 -0
- package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js +68 -63
- package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/sampleLight.glsl.js +94 -76
- package/lib/renderer/glsl/chunks/sampleLight.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/sampleMaterial.glsl.d.ts +1 -0
- package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js +140 -117
- package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/sampleShadowCatcher.glsl.js +14 -14
- package/lib/renderer/glsl/chunks/sampling.glsl.js +89 -92
- package/lib/renderer/glsl/chunks/sampling.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/sobol.glsl.js +79 -79
- 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 +2 -2
- package/lib/renderer/glsl/normalizeRayTraceOutput.frag.js +10 -10
- package/lib/renderer/glsl/rayTrace.frag.d.ts +1 -1
- package/lib/renderer/glsl/rayTrace.frag.js +260 -237
- package/lib/renderer/glsl/rayTrace.frag.js.map +1 -1
- package/lib/renderer/glsl/shadowCatcher.frag.js +26 -26
- package/lib/renderer/glsl/shadowCatcher.frag.js.map +1 -1
- package/lib/renderer/glsl/webglPipeline.frag.js +59 -59
- package/lib/renderer/lightSampling.d.ts +3 -2
- package/lib/renderer/lightSampling.js +14 -8
- package/lib/renderer/lightSampling.js.map +1 -1
- package/lib/renderer/progressiveScheduler.js +4 -3
- package/lib/renderer/progressiveScheduler.js.map +1 -1
- package/lib/renderer/renderPipeline.d.ts +1 -0
- package/lib/renderer/renderPipeline.js.map +1 -1
- package/lib/renderer/researchTransport.d.ts +31 -0
- package/lib/renderer/researchTransport.js +5 -0
- package/lib/renderer/researchTransport.js.map +1 -0
- package/lib/renderer/sceneLayoutSchema.d.ts +1 -0
- package/lib/renderer/sceneLayoutSchema.js +2 -2
- package/lib/renderer/sceneLayoutSchema.js.map +1 -1
- package/lib/renderer/scratchSampling.js +6 -6
- package/lib/renderer/spectrum.d.ts +21 -0
- package/lib/renderer/spectrum.js +154 -0
- package/lib/renderer/spectrum.js.map +1 -0
- package/lib/renderer/webglLightSampling.d.ts +39 -0
- package/lib/renderer/webglLightSampling.js +15 -0
- package/lib/renderer/webglLightSampling.js.map +1 -0
- package/lib/renderer/wgpuBindlessSource.js +3 -3
- package/lib/renderer/wgpuShaderSource.d.ts +7 -0
- package/lib/renderer/wgpuShaderSource.js +2 -0
- package/lib/renderer/wgpuShaderSource.js.map +1 -1
- package/lib/renderer/wgsl/aovDisplay.wgsl.js +9 -9
- package/lib/renderer/wgsl/aovReflectance.wgsl.js +55 -55
- package/lib/renderer/wgsl/aovReflectanceSamples.wgsl.js +1 -1
- package/lib/renderer/wgsl/aovResolve.wgsl.js +2 -2
- package/lib/renderer/wgsl/aovSnapshot.wgsl.js +1 -1
- package/lib/renderer/wgsl/aovTrace.wgsl.js +33 -33
- package/lib/renderer/wgsl/bloom.wgsl.js +18 -18
- package/lib/renderer/wgsl/causticLight.compute.d.ts +6 -0
- package/lib/renderer/wgsl/causticLight.compute.js +537 -0
- package/lib/renderer/wgsl/causticLight.compute.js.map +1 -0
- package/lib/renderer/wgsl/chunks/background.wgsl.d.ts +2 -0
- package/lib/renderer/wgsl/chunks/background.wgsl.js +102 -0
- package/lib/renderer/wgsl/chunks/background.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.d.ts +2 -0
- package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.js +12 -0
- package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.d.ts +2 -0
- package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.js +16 -0
- package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/chunks/caustics.wgsl.d.ts +1 -0
- package/lib/renderer/wgsl/chunks/caustics.wgsl.js +62 -0
- package/lib/renderer/wgsl/chunks/caustics.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/chunks/common.wgsl.js +4 -4
- package/lib/renderer/wgsl/chunks/envMap.wgsl.js +37 -37
- package/lib/renderer/wgsl/chunks/intersect.wgsl.js +598 -592
- package/lib/renderer/wgsl/chunks/intersect.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js +14 -14
- package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.d.ts +2 -1
- package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js +75 -73
- package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/openPbrBsdf.wgsl.js +794 -794
- package/lib/renderer/wgsl/chunks/pdm_displacement.wgsl.js +139 -139
- package/lib/renderer/wgsl/chunks/rand.wgsl.js +3 -3
- package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.d.ts +2 -1
- package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js +35 -25
- package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/sampleLight.wgsl.d.ts +1 -1
- package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js +142 -138
- package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.d.ts +1 -1
- package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js +204 -187
- package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.d.ts +1 -1
- package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js +11 -11
- package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/sampling.wgsl.d.ts +1 -1
- package/lib/renderer/wgsl/chunks/sampling.wgsl.js +89 -93
- package/lib/renderer/wgsl/chunks/sampling.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/sobol.wgsl.js +83 -83
- package/lib/renderer/wgsl/chunks/uvProjection.wgsl.js +11 -11
- package/lib/renderer/wgsl/compose.frag.wgsl.js +98 -98
- package/lib/renderer/wgsl/customDenoise.wgsl.js +10 -10
- package/lib/renderer/wgsl/depthQuery.wgsl.js +2 -2
- package/lib/renderer/wgsl/jnlm.compute.js +74 -74
- package/lib/renderer/wgsl/offlineAdaptive.compute.js +25 -25
- package/lib/renderer/wgsl/oidnAuxiliary.wgsl.js +3 -3
- package/lib/renderer/wgsl/photonMap.compute.d.ts +29 -0
- package/lib/renderer/wgsl/photonMap.compute.js +352 -0
- package/lib/renderer/wgsl/photonMap.compute.js.map +1 -0
- package/lib/renderer/wgsl/proceduralSky.compute.js +64 -64
- package/lib/renderer/wgsl/rayTrace.compute.d.ts +9 -1
- package/lib/renderer/wgsl/rayTrace.compute.js +448 -522
- package/lib/renderer/wgsl/rayTrace.compute.js.map +1 -1
- package/lib/scene/MaterialState.d.ts +2 -2
- package/lib/scene/MaterialState.js +2 -2
- package/lib/scene/MaterialState.js.map +1 -1
- package/lib/settings/render.d.ts +11 -0
- package/lib/settings/render.js +1 -0
- package/lib/settings/render.js.map +1 -1
- package/lib/util/fromTHREE.js +2 -2
- 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/llms.txt +2 -1
- package/package.json +3 -3
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
export default /* wgsl */ `fn di(point: vec3f, height: f32, radius: f32) -> f32 {
|
|
2
|
+
let fQ = length(point);
|
|
3
|
+
if (fQ < 0.00001) {
|
|
4
|
+
return -radius;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
let iG = radius * point.y / fQ;
|
|
8
|
+
let iq = -1.5 * height;
|
|
9
|
+
var eq: f32;
|
|
10
|
+
if (iG >= 0.0) {
|
|
11
|
+
eq = radius;
|
|
12
|
+
}
|
|
13
|
+
else if (iG < iq) {
|
|
14
|
+
eq = -height * fQ / point.y;
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
let cv = 1.0
|
|
18
|
+
- iG * iG / (3.0 * iq * iq);
|
|
19
|
+
eq = radius * cv;
|
|
20
|
+
}
|
|
21
|
+
return fQ - eq;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
fn eM(origin: vec3f, direction: vec3f) -> vec3f {
|
|
25
|
+
if (!USE_GROUNDED_BACKGROUND) {
|
|
26
|
+
return direction;
|
|
27
|
+
}
|
|
28
|
+
let params = rtUniform.groundedBackgroundParams;
|
|
29
|
+
let bS = normalize(direction);
|
|
30
|
+
let center = vec3f(
|
|
31
|
+
rtUniform.groundedBackgroundCenter.x,
|
|
32
|
+
params.z + params.x,
|
|
33
|
+
rtUniform.groundedBackgroundCenter.y
|
|
34
|
+
);
|
|
35
|
+
let bs = origin - center;
|
|
36
|
+
let eE = dot(bs, bS);
|
|
37
|
+
let bj = eE * eE
|
|
38
|
+
- dot(bs, bs) + params.y * params.y;
|
|
39
|
+
if (
|
|
40
|
+
bj <= 0.0
|
|
41
|
+
|| di(bs, params.x, params.y) > 0.0
|
|
42
|
+
) {
|
|
43
|
+
return direction;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
var cw = -eE + sqrt(bj);
|
|
47
|
+
if (cw <= 0.0) {
|
|
48
|
+
return direction;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
let oA = bs + bS * cw;
|
|
52
|
+
if (oA.y >= 0.0) {
|
|
53
|
+
return normalize(oA);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (bS.y < -0.00001 && params.y > 1.5 * params.x) {
|
|
57
|
+
let hP = (-params.x - bs.y) / bS.y;
|
|
58
|
+
let ot = bs + bS * hP;
|
|
59
|
+
let oT = (2.0 / 3.0)
|
|
60
|
+
* sqrt(params.y * params.y - 2.25 * params.x * params.x);
|
|
61
|
+
if (hP > 0.0 && length(ot.xz) <= oT) {
|
|
62
|
+
return normalize(ot);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
var cI = 0.0;
|
|
67
|
+
for (var i = 0; i < 14; i++) {
|
|
68
|
+
let fd = (cI + cw) * 0.5;
|
|
69
|
+
let qq = bs + bS * fd;
|
|
70
|
+
if (di(qq, params.x, params.y) > 0.0) {
|
|
71
|
+
cw = fd;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
cI = fd;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
let hit = bs + bS * ((cI + cw) * 0.5);
|
|
78
|
+
return normalize(hit);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
fn ft(ray: Ray) -> vec4f {
|
|
82
|
+
var bg = vec4f(0.0);
|
|
83
|
+
if (USE_BACKGROUND_MAP) {
|
|
84
|
+
let d = eM(ray.o, ray.d);
|
|
85
|
+
let t = rtUniform.backgroundMapTransform;
|
|
86
|
+
let qS = vec3f(t.x * d.x - t.y * d.z, d.y, t.y * d.x + t.x * d.z);
|
|
87
|
+
let rotation = rtUniform.backgroundMapRotation;
|
|
88
|
+
let gU = transpose(mat3x3f(rotation[0].xyz, rotation[1].xyz, rotation[2].xyz)) * qS;
|
|
89
|
+
let aW = textureLinear(backgroundMap, eF(gU));
|
|
90
|
+
bg = vec4f(aW.rgb * t.z, aW.a);
|
|
91
|
+
}
|
|
92
|
+
else if (USE_BACKGROUND) {
|
|
93
|
+
bg = rtUniform.backgroundColor;
|
|
94
|
+
}
|
|
95
|
+
else if (USE_ENVMAP) {
|
|
96
|
+
bg = textureLinear(envMap, cT(ray.d));
|
|
97
|
+
}
|
|
98
|
+
return bg;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
`;
|
|
102
|
+
//# sourceMappingURL=background.wgsl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"background.wgsl.js","sourceRoot":"","sources":["../../../../src/renderer/wgsl/chunks/background.wgsl.ts"],"names":[],"mappings":"AAAA,eAAe,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoGzB,CAAC","sourcesContent":["export default /* wgsl */ `fn groundedSurfaceDistance(point: vec3f, height: f32, radius: f32) -> f32 {\n let pointLength = length(point);\n if (pointLength < 0.00001) {\n return -radius;\n }\n\n let originalY = radius * point.y / pointLength;\n let transitionY = -1.5 * height;\n var surfaceRadius: f32;\n if (originalY >= 0.0) {\n surfaceRadius = radius;\n }\n else if (originalY < transitionY) {\n surfaceRadius = -height * pointLength / point.y;\n }\n else {\n let factor = 1.0\n - originalY * originalY / (3.0 * transitionY * transitionY);\n surfaceRadius = radius * factor;\n }\n return pointLength - surfaceRadius;\n}\n\nfn groundedBackgroundDirection(origin: vec3f, direction: vec3f) -> vec3f {\n if (!USE_GROUNDED_BACKGROUND) {\n return direction;\n }\n let params = rtUniform.groundedBackgroundParams;\n let rayDirection = normalize(direction);\n let center = vec3f(\n rtUniform.groundedBackgroundCenter.x,\n params.z + params.x,\n rtUniform.groundedBackgroundCenter.y\n );\n let localOrigin = origin - center;\n let projectedOrigin = dot(localOrigin, rayDirection);\n let discriminant = projectedOrigin * projectedOrigin\n - dot(localOrigin, localOrigin) + params.y * params.y;\n if (\n discriminant <= 0.0\n || groundedSurfaceDistance(localOrigin, params.x, params.y) > 0.0\n ) {\n return direction;\n }\n\n var farDistance = -projectedOrigin + sqrt(discriminant);\n if (farDistance <= 0.0) {\n return direction;\n }\n\n let sphereHit = localOrigin + rayDirection * farDistance;\n if (sphereHit.y >= 0.0) {\n return normalize(sphereHit);\n }\n\n if (rayDirection.y < -0.00001 && params.y > 1.5 * params.x) {\n let groundDistance = (-params.x - localOrigin.y) / rayDirection.y;\n let groundHit = localOrigin + rayDirection * groundDistance;\n let groundRadius = (2.0 / 3.0)\n * sqrt(params.y * params.y - 2.25 * params.x * params.x);\n if (groundDistance > 0.0 && length(groundHit.xz) <= groundRadius) {\n return normalize(groundHit);\n }\n }\n\n var nearDistance = 0.0;\n for (var i = 0; i < 14; i++) {\n let middleDistance = (nearDistance + farDistance) * 0.5;\n let middlePoint = localOrigin + rayDirection * middleDistance;\n if (groundedSurfaceDistance(middlePoint, params.x, params.y) > 0.0) {\n farDistance = middleDistance;\n }\n else {\n nearDistance = middleDistance;\n }\n }\n let hit = localOrigin + rayDirection * ((nearDistance + farDistance) * 0.5);\n return normalize(hit);\n}\n\nfn sampleSceneBackground(ray: Ray) -> vec4f {\n var bg = vec4f(0.0);\n if (USE_BACKGROUND_MAP) {\n let d = groundedBackgroundDirection(ray.o, ray.d);\n let t = rtUniform.backgroundMapTransform;\n let backgroundDirection = vec3f(t.x * d.x - t.y * d.z, d.y, t.y * d.x + t.x * d.z);\n let rotation = rtUniform.backgroundMapRotation;\n let mapDirection = transpose(mat3x3f(rotation[0].xyz, rotation[1].xyz, rotation[2].xyz)) * backgroundDirection;\n let backgroundSample = textureLinear(backgroundMap, cartesianToEquirect(mapDirection));\n bg = vec4f(backgroundSample.rgb * t.z, backgroundSample.a);\n }\n else if (USE_BACKGROUND) {\n bg = rtUniform.backgroundColor;\n }\n else if (USE_ENVMAP) {\n bg = textureLinear(envMap, environmentUv(ray.d));\n }\n return bg;\n}\n\n`;\n"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
declare const _default: "\nfn causticAdjoint(view:vec3f,outgoing:vec3f,shading:vec3f,geometric:vec3f)->f32 {\n let numerator=abs(dot(view,shading)*dot(outgoing,geometric));\n let denominator=abs(dot(view,geometric)*dot(outgoing,shading));\n if(denominator==0.0){return 0.0;}\n return numerator/denominator;\n}\n";
|
|
2
|
+
export default _default;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Veach's adjoint shading-normal ratio. Directions point away from the vertex;
|
|
2
|
+
// view is toward the preceding light vertex, outgoing toward the camera.
|
|
3
|
+
// Reference: Veach 1997, thesis section 5.3 (mathematical formula, no copied code).
|
|
4
|
+
export default /* wgsl */ `
|
|
5
|
+
fn causticAdjoint(view:vec3f,vJ:vec3f,shading:vec3f,geometric:vec3f)->f32 {
|
|
6
|
+
let iF=abs(dot(view,shading)*dot(vJ,geometric));
|
|
7
|
+
let ah=abs(dot(view,geometric)*dot(vJ,shading));
|
|
8
|
+
if(ah==0.0){return 0.0;}
|
|
9
|
+
return iF/ah;
|
|
10
|
+
}
|
|
11
|
+
`;
|
|
12
|
+
//# sourceMappingURL=causticAdjoint.wgsl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"causticAdjoint.wgsl.js","sourceRoot":"","sources":["../../../../src/renderer/wgsl/chunks/causticAdjoint.wgsl.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,yEAAyE;AACzE,oFAAoF;AACpF,eAAe,UAAU,CAAC;;;;;;;CAOzB,CAAC","sourcesContent":["// Veach's adjoint shading-normal ratio. Directions point away from the vertex;\n// view is toward the preceding light vertex, outgoing toward the camera.\n// Reference: Veach 1997, thesis section 5.3 (mathematical formula, no copied code).\nexport default /* wgsl */ `\nfn causticAdjoint(view:vec3f,outgoing:vec3f,shading:vec3f,geometric:vec3f)->f32 {\n let numerator=abs(dot(view,shading)*dot(outgoing,geometric));\n let denominator=abs(dot(view,geometric)*dot(outgoing,shading));\n if(denominator==0.0){return 0.0;}\n return numerator/denominator;\n}\n`;\n"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
declare const _default: "\nfn causticAtomicAdd(index:u32,value:f32) {\n if(!(value>0.0)||!(value<3.402823e38)){return;}\n var previous=atomicLoad(&splats[index]);\n loop {\n let sum=bitcast<f32>(previous)+value;\n let replacement=bitcast<u32>(sum);\n let result=atomicCompareExchangeWeak(&splats[index],previous,replacement);\n if(result.exchanged){break;}\n previous=result.old_value;\n }\n}\n";
|
|
2
|
+
export default _default;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Float32 addition implemented with u32 compare/exchange works on baseline
|
|
2
|
+
// WebGPU, without a fixed radiance quantum or the Q16.16 saturation ceiling.
|
|
3
|
+
export default /* wgsl */ `
|
|
4
|
+
fn kM(index:u32,value:f32) {
|
|
5
|
+
if(!(value>0.0)||!(value<3.402823e38)){return;}
|
|
6
|
+
var previous=atomicLoad(&splats[index]);
|
|
7
|
+
loop {
|
|
8
|
+
let sum=bitcast<f32>(previous)+value;
|
|
9
|
+
let vN=bitcast<u32>(sum);
|
|
10
|
+
let result=atomicCompareExchangeWeak(&splats[index],previous,vN);
|
|
11
|
+
if(result.exchanged){break;}
|
|
12
|
+
previous=result.old_value;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
`;
|
|
16
|
+
//# sourceMappingURL=causticAtomic.wgsl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"causticAtomic.wgsl.js","sourceRoot":"","sources":["../../../../src/renderer/wgsl/chunks/causticAtomic.wgsl.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,6EAA6E;AAC7E,eAAe,UAAU,CAAC;;;;;;;;;;;;CAYzB,CAAC","sourcesContent":["// Float32 addition implemented with u32 compare/exchange works on baseline\n// WebGPU, without a fixed radiance quantum or the Q16.16 saturation ceiling.\nexport default /* wgsl */ `\nfn causticAtomicAdd(index:u32,value:f32) {\n if(!(value>0.0)||!(value<3.402823e38)){return;}\n var previous=atomicLoad(&splats[index]);\n loop {\n let sum=bitcast<f32>(previous)+value;\n let replacement=bitcast<u32>(sum);\n let result=atomicCompareExchangeWeak(&splats[index],previous,replacement);\n if(result.exchanged){break;}\n previous=result.old_value;\n }\n}\n`;\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function causticPartitionWGSL(mnee: boolean, lightTracing: boolean, photonMapping?: boolean, mneeMaxDepth?: number, hot?: boolean, photonMaxDepth?: number): string;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// Smooth classification is independent of the sampled lobe. The single-vertex
|
|
2
|
+
// marker records either an eligible delta transmission or a smooth reflection.
|
|
3
|
+
export function causticPartitionWGSL(mnee, lightTracing, photonMapping = false, mneeMaxDepth = 20, hot = false, photonMaxDepth = 20) {
|
|
4
|
+
return /* wgsl */ `
|
|
5
|
+
fn causticDim(slot:u32)->u32{return 1048576u+samplingBounce*4096u+slot;}
|
|
6
|
+
fn isCausticSpecular(m: OpenPbrResolvedMaterial) -> bool {
|
|
7
|
+
return m.baseWeight * (1.0 - m.baseMetalness) * (1.0 - m.transmissionWeight) <= 1e-6 &&
|
|
8
|
+
m.subsurfaceWeight <= 0.0 && m.fuzzWeight <= 0.0 && m.coatWeight <= 0.0 && m.causticRoughness <= 0.1;
|
|
9
|
+
}
|
|
10
|
+
fn isCausticT(m: OpenPbrResolvedMaterial) -> bool {
|
|
11
|
+
return isCausticSpecular(m) && m.transmissionWeight == 1.0 && m.causticRoughness == 0.0 && !m.thinWalled && !m.causticNormalMapped && m.alpha>=1.0;
|
|
12
|
+
}
|
|
13
|
+
fn isCausticR(m:OpenPbrResolvedMaterial)->bool{
|
|
14
|
+
return isCausticSpecular(m)&&m.causticRoughness==0.0&&!m.causticNormalMapped&&m.alpha>=1.0;
|
|
15
|
+
}
|
|
16
|
+
fn causticHitOwned(path: Path, xd: bool, vl: bool) -> bool {
|
|
17
|
+
let r1 = ${mnee} && xd && path.causticMneeReceiver && path.causticK == 1u && path.causticSingleT;
|
|
18
|
+
let r2 = ${lightTracing} && vl && path.causticK > 0u && path.causticReceiverPrimary;
|
|
19
|
+
let r3=${photonMapping}&&path.causticPhotonReceiver&&path.causticK>0u;
|
|
20
|
+
return path.causticHasReceiver && (r1 || r2 || r3);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
var<private> causticHot:array<vec3f,15>;
|
|
24
|
+
fn causticHotRecord(path:Path,emission:vec3f,kind:u32){
|
|
25
|
+
if(!${hot}){return;}
|
|
26
|
+
let value=max(max(path.beta.x*emission.x,path.beta.y*emission.y),path.beta.z*emission.z);
|
|
27
|
+
if(value<=100.0){return;}
|
|
28
|
+
causticHot[9][kind]+=1.0;
|
|
29
|
+
causticHot[0]+=vec3f(1.0,f32(samplingBounce),f32(path.causticK));
|
|
30
|
+
causticHot[1]+=vec3f(select(0.0,1.0,path.causticHasReceiver),select(0.0,1.0,path.causticSingleT),select(0.0,1.0,path.causticReceiverPrimary));
|
|
31
|
+
causticHot[2]+=vec3f(select(0.0,1.0,path.causticMneeReceiver),select(0.0,1.0,path.causticPhotonReceiver),value);
|
|
32
|
+
if(samplingBounce>=3u&&samplingBounce<=8u){causticHot[samplingBounce]+=vec3f(1.0,f32(path.causticK),value);}
|
|
33
|
+
}
|
|
34
|
+
fn causticEstimateRecord(value:vec3f,kind:u32){
|
|
35
|
+
if(!${hot}){return;}
|
|
36
|
+
let peak=max(max(value.x,value.y),value.z);if(peak>100.0){causticHot[10u+kind]+=vec3f(1.0,f32(samplingBounce),peak);}
|
|
37
|
+
}
|
|
38
|
+
fn causticEmitterRecord(si:SurfaceInteraction,path:Path,weight:f32,emission:vec3f){
|
|
39
|
+
if(!${hot}){return;}
|
|
40
|
+
let value=path.beta*weight*emission;if(max(max(value.x,value.y),value.z)<=100.0){return;}
|
|
41
|
+
let material=materialsBuffer[si.materialIndex];
|
|
42
|
+
causticHot[12]+=vec3f(1.0+dot(si.faceNormal,-path.ray.d),select(0.0,1.0,path.fromEye),material.doubleSided);
|
|
43
|
+
causticHot[13]+=vec3f(weight,material.matType,rtUniform.lightWeightTotal);
|
|
44
|
+
causticHot[14]+=vec3f(path.scatteringPdf,dot(material.emission,luminance),max(max(path.beta.x,path.beta.y),path.beta.z));
|
|
45
|
+
}
|
|
46
|
+
fn causticAdvance(path: ptr<function, Path>, m: OpenPbrResolvedMaterial, transmission: bool, surface: bool) {
|
|
47
|
+
if (surface && isCausticSpecular(m)) {
|
|
48
|
+
(*path).causticK++;
|
|
49
|
+
(*path).causticSingleT = (*path).causticK == 1u && ((isCausticT(m) && transmission)||(isCausticR(m)&&!transmission));
|
|
50
|
+
} else {
|
|
51
|
+
(*path).causticK = 0u;
|
|
52
|
+
(*path).causticSingleT = false;
|
|
53
|
+
(*path).causticPhotonReceiver=surface&&samplingBounce<=${photonMaxDepth}u&&m.materialType!=SHADOW_CATCHER;
|
|
54
|
+
(*path).causticHasReceiver = m.materialType != SHADOW_CATCHER;
|
|
55
|
+
(*path).causticMneeReceiver = surface && samplingBounce<=${mneeMaxDepth}u &&
|
|
56
|
+
m.baseWeight*(1.0-m.baseMetalness)*(1.0-m.transmissionWeight)>0.0 && m.subsurfaceWeight==0.0;
|
|
57
|
+
(*path).causticReceiverPrimary = (*path).fromEye && surface;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
`;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=caustics.wgsl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"caustics.wgsl.js","sourceRoot":"","sources":["../../../../src/renderer/wgsl/chunks/caustics.wgsl.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,+EAA+E;AAC/E,MAAM,UAAU,oBAAoB,CAAC,IAAa,EAAE,YAAqB,EAAC,aAAa,GAAC,KAAK,EAAC,YAAY,GAAC,EAAE,EAAC,GAAG,GAAC,KAAK,EAAC,cAAc,GAAC,EAAE;IACvI,OAAO,UAAU,CAAC;;;;;;;;;;;;;WAaP,IAAI;WACJ,YAAY;SACd,aAAa;;;;;;MAMjB,GAAG;;;;;;;;;;MAUH,GAAG;;;;MAIH,GAAG;;;;;;;;;;;;;;yDAcmD,cAAc;;2DAEZ,YAAY;;;;;CAK1E,CAAC;AACF,CAAC","sourcesContent":["// Smooth classification is independent of the sampled lobe. The single-vertex\n// marker records either an eligible delta transmission or a smooth reflection.\nexport function causticPartitionWGSL(mnee: boolean, lightTracing: boolean,photonMapping=false,mneeMaxDepth=20,hot=false,photonMaxDepth=20) {\n return /* wgsl */ `\nfn causticDim(slot:u32)->u32{return 1048576u+samplingBounce*4096u+slot;}\nfn isCausticSpecular(m: OpenPbrResolvedMaterial) -> bool {\n return m.baseWeight * (1.0 - m.baseMetalness) * (1.0 - m.transmissionWeight) <= 1e-6 &&\n m.subsurfaceWeight <= 0.0 && m.fuzzWeight <= 0.0 && m.coatWeight <= 0.0 && m.causticRoughness <= 0.1;\n}\nfn isCausticT(m: OpenPbrResolvedMaterial) -> bool {\n return isCausticSpecular(m) && m.transmissionWeight == 1.0 && m.causticRoughness == 0.0 && !m.thinWalled && !m.causticNormalMapped && m.alpha>=1.0;\n}\nfn isCausticR(m:OpenPbrResolvedMaterial)->bool{\n return isCausticSpecular(m)&&m.causticRoughness==0.0&&!m.causticNormalMapped&&m.alpha>=1.0;\n}\nfn causticHitOwned(path: Path, mneeLight: bool, tracingLight: bool) -> bool {\n let r1 = ${mnee} && mneeLight && path.causticMneeReceiver && path.causticK == 1u && path.causticSingleT;\n let r2 = ${lightTracing} && tracingLight && path.causticK > 0u && path.causticReceiverPrimary;\n let r3=${photonMapping}&&path.causticPhotonReceiver&&path.causticK>0u;\n return path.causticHasReceiver && (r1 || r2 || r3);\n}\n// Private evidence images count only unsuppressed PT contributions above 100 after MIS.\nvar<private> causticHot:array<vec3f,15>;\nfn causticHotRecord(path:Path,emission:vec3f,kind:u32){\n if(!${hot}){return;}\n let value=max(max(path.beta.x*emission.x,path.beta.y*emission.y),path.beta.z*emission.z);\n if(value<=100.0){return;}\n causticHot[9][kind]+=1.0;\n causticHot[0]+=vec3f(1.0,f32(samplingBounce),f32(path.causticK));\n causticHot[1]+=vec3f(select(0.0,1.0,path.causticHasReceiver),select(0.0,1.0,path.causticSingleT),select(0.0,1.0,path.causticReceiverPrimary));\n causticHot[2]+=vec3f(select(0.0,1.0,path.causticMneeReceiver),select(0.0,1.0,path.causticPhotonReceiver),value);\n if(samplingBounce>=3u&&samplingBounce<=8u){causticHot[samplingBounce]+=vec3f(1.0,f32(path.causticK),value);}\n}\nfn causticEstimateRecord(value:vec3f,kind:u32){\n if(!${hot}){return;}\n let peak=max(max(value.x,value.y),value.z);if(peak>100.0){causticHot[10u+kind]+=vec3f(1.0,f32(samplingBounce),peak);}\n}\nfn causticEmitterRecord(si:SurfaceInteraction,path:Path,weight:f32,emission:vec3f){\n if(!${hot}){return;}\n let value=path.beta*weight*emission;if(max(max(value.x,value.y),value.z)<=100.0){return;}\n let material=materialsBuffer[si.materialIndex];\n causticHot[12]+=vec3f(1.0+dot(si.faceNormal,-path.ray.d),select(0.0,1.0,path.fromEye),material.doubleSided);\n causticHot[13]+=vec3f(weight,material.matType,rtUniform.lightWeightTotal);\n causticHot[14]+=vec3f(path.scatteringPdf,dot(material.emission,luminance),max(max(path.beta.x,path.beta.y),path.beta.z));\n}\nfn causticAdvance(path: ptr<function, Path>, m: OpenPbrResolvedMaterial, transmission: bool, surface: bool) {\n if (surface && isCausticSpecular(m)) {\n (*path).causticK++;\n (*path).causticSingleT = (*path).causticK == 1u && ((isCausticT(m) && transmission)||(isCausticR(m)&&!transmission));\n } else {\n (*path).causticK = 0u;\n (*path).causticSingleT = false;\n (*path).causticPhotonReceiver=surface&&samplingBounce<=${photonMaxDepth}u&&m.materialType!=SHADOW_CATCHER;\n (*path).causticHasReceiver = m.materialType != SHADOW_CATCHER;\n (*path).causticMneeReceiver = surface && samplingBounce<=${mneeMaxDepth}u &&\n m.baseWeight*(1.0-m.baseMetalness)*(1.0-m.transmissionWeight)>0.0 && m.subsurfaceWeight==0.0;\n (*path).causticReceiverPrimary = (*path).fromEye && surface;\n }\n}\n`;\n}\n"]}
|
|
@@ -11,12 +11,12 @@ const ROUGHNESS_MIN = 0.001;
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
fn
|
|
14
|
+
fn sO(position: vec3f, geometricNormal: vec3f, direction: vec3f) -> vec3f {
|
|
15
15
|
let normal = select(-geometricNormal, geometricNormal, dot(geometricNormal, direction) >= 0.0);
|
|
16
|
-
let
|
|
16
|
+
let rb = vec3i(256.0 * normal);
|
|
17
17
|
let bits = bitcast<vec3i>(position);
|
|
18
|
-
let
|
|
19
|
-
return select(
|
|
18
|
+
let ye = bitcast<vec3f>(bits + select(rb, -rb, position < vec3f(0.0)));
|
|
19
|
+
return select(ye, position + normal / 65536.0, abs(position) < vec3f(1.0 / 32.0));
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
`;
|
|
@@ -11,40 +11,40 @@ fn textureLinear(tex: texture_2d<f32>, _uv: vec2f) -> vec4f {
|
|
|
11
11
|
|
|
12
12
|
let size = vec2f(textureDimensions(tex, 0));
|
|
13
13
|
|
|
14
|
-
let
|
|
15
|
-
let
|
|
16
|
-
let f = fract(
|
|
17
|
-
let
|
|
14
|
+
let uv2f = _uv * size - vec2f(0.5);
|
|
15
|
+
let yj = floor(uv2f);
|
|
16
|
+
let f = fract(uv2f);
|
|
17
|
+
let yi = vec2i(yj);
|
|
18
18
|
let maximum = vec2i(size) - vec2i(1);
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
let s1 = textureLoad(tex, clamp(
|
|
22
|
-
let s2 = textureLoad(tex, clamp(
|
|
23
|
-
let s3 = textureLoad(tex, clamp(
|
|
24
|
-
let s4 = textureLoad(tex, clamp(
|
|
21
|
+
let s1 = textureLoad(tex, clamp(yi + vec2i(0, 0), vec2i(0), maximum), 0);
|
|
22
|
+
let s2 = textureLoad(tex, clamp(yi + vec2i(1, 0), vec2i(0), maximum), 0);
|
|
23
|
+
let s3 = textureLoad(tex, clamp(yi + vec2i(0, 1), vec2i(0), maximum), 0);
|
|
24
|
+
let s4 = textureLoad(tex, clamp(yi + vec2i(1, 1), vec2i(0), maximum), 0);
|
|
25
25
|
|
|
26
26
|
return mix(mix(s1, s2, f.x), mix(s3, s4, f.x), f.y);
|
|
27
27
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
fn
|
|
31
|
-
var phi = atan2(-
|
|
30
|
+
fn eF(gh: vec3f) -> vec2f {
|
|
31
|
+
var phi = atan2(-gh.z, -gh.x);
|
|
32
32
|
if (phi < 0.0) {
|
|
33
33
|
phi += TWOPI;
|
|
34
34
|
}
|
|
35
|
-
let theta = acos(clamp(
|
|
35
|
+
let theta = acos(clamp(gh.y, -1.0, 1.0));
|
|
36
36
|
return vec2f(phi * 0.5 * INVPI, theta * INVPI);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
fn
|
|
39
|
+
fn jS() -> mat3x3f {
|
|
40
40
|
return mat3x3f(rtUniform.environmentRotation[0].xyz, rtUniform.environmentRotation[1].xyz, rtUniform.environmentRotation[2].xyz);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
fn
|
|
44
|
-
return
|
|
43
|
+
fn cT(nD: vec3f) -> vec2f {
|
|
44
|
+
return eF(transpose(jS()) * nD);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
fn
|
|
47
|
+
fn rv(u: f32, vOffset: ptr<function, i32>, pdf: ptr<function, vec2f>) -> f32 {
|
|
48
48
|
let size = vec2i(textureDimensions(envMap, 0));
|
|
49
49
|
|
|
50
50
|
var left = 0;
|
|
@@ -70,7 +70,7 @@ let s1 = textureLoad(envMapDistribution, vec2i(0, *vOffset + 1), 0).xy;
|
|
|
70
70
|
return (f32(*vOffset) + (u - s0.x) / (s1.x - s0.x)) / f32(size.y);
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
fn
|
|
73
|
+
fn ru(u: f32, vOffset: i32, pdf: ptr<function, vec2f>) -> f32 {
|
|
74
74
|
let size = vec2i(textureDimensions(envMap, 0));
|
|
75
75
|
|
|
76
76
|
var left = 0;
|
|
@@ -84,57 +84,57 @@ left = mid + 1;
|
|
|
84
84
|
right = mid;
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
|
-
let
|
|
87
|
+
let pw = left - 1;
|
|
88
88
|
|
|
89
89
|
|
|
90
90
|
|
|
91
|
-
let s0 = textureLoad(envMapDistribution, vec2i(1 +
|
|
92
|
-
let s1 = textureLoad(envMapDistribution, vec2i(1 +
|
|
91
|
+
let s0 = textureLoad(envMapDistribution, vec2i(1 + pw, vOffset), 0).xy;
|
|
92
|
+
let s1 = textureLoad(envMapDistribution, vec2i(1 + pw + 1, vOffset), 0).xy;
|
|
93
93
|
|
|
94
94
|
(*pdf).x = s0.y;
|
|
95
95
|
|
|
96
|
-
return (f32(
|
|
96
|
+
return (f32(pw) + (u - s0.x) / (s1.x - s0.x)) / f32(size.x);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
|
|
100
100
|
|
|
101
|
-
fn
|
|
101
|
+
fn envMapSolidAnglePdf(partialPdf: vec2f, v: f32) -> f32 {
|
|
102
102
|
if (!(v > 0.0 && v < 1.0)) { return 0.0; }
|
|
103
103
|
let sinTheta = sin(min(v, 1.0 - v) * PI);
|
|
104
|
-
return
|
|
104
|
+
return partialPdf.x * partialPdf.y * INVPI2 / (2.0 * sinTheta);
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
|
|
108
|
-
fn
|
|
109
|
-
var
|
|
108
|
+
fn pn(random: vec2f, uv: ptr<function, vec2f>, pdf: ptr<function, f32>) -> vec3f {
|
|
109
|
+
var partialPdf: vec2f;
|
|
110
110
|
var vOffset: i32;
|
|
111
111
|
|
|
112
|
-
(*uv).y =
|
|
113
|
-
(*uv).x =
|
|
112
|
+
(*uv).y = rv(random.x, &vOffset, &partialPdf);
|
|
113
|
+
(*uv).x = ru(random.y, vOffset, &partialPdf);
|
|
114
114
|
|
|
115
115
|
let phi = (*uv).x * TWOPI;
|
|
116
116
|
let theta = (*uv).y * PI;
|
|
117
|
-
let
|
|
117
|
+
let ct = cos(theta);
|
|
118
118
|
let sinTheta = sin(theta);
|
|
119
|
-
let
|
|
120
|
-
let
|
|
119
|
+
let vZ = cos(phi);
|
|
120
|
+
let wr = sin(phi);
|
|
121
121
|
|
|
122
|
-
let dir = vec3f(-sinTheta *
|
|
122
|
+
let dir = vec3f(-sinTheta * vZ, ct, -sinTheta * wr);
|
|
123
123
|
|
|
124
|
-
*pdf =
|
|
124
|
+
*pdf = envMapSolidAnglePdf(partialPdf, (*uv).y);
|
|
125
125
|
|
|
126
|
-
return
|
|
126
|
+
return jS() * dir;
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
fn
|
|
129
|
+
fn envMapPdf(_uv: vec2f) -> f32 {
|
|
130
130
|
let size = vec2f(textureDimensions(envMap, 0));
|
|
131
131
|
|
|
132
|
-
let
|
|
132
|
+
let yn = clamp(vec2i(_uv * size), vec2i(0), vec2i(size) - vec2i(1));
|
|
133
133
|
|
|
134
|
-
let
|
|
135
|
-
let
|
|
134
|
+
let ue = textureLoad(envMapDistribution, vec2i(1 + yn.x, yn.y), 0).y;
|
|
135
|
+
let uf = textureLoad(envMapDistribution, vec2i(0, yn.y), 0).y;
|
|
136
136
|
|
|
137
|
-
return
|
|
137
|
+
return envMapSolidAnglePdf(vec2f(ue, uf), _uv.y);
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
|