@roomle/web-sdk 5.1.0-alpha.2 → 5.1.0-alpha.3
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/lib/{BufferGeometry-Cd2ewNVQ.mjs → BufferGeometry-Bl5whHAB.mjs} +1 -1
- package/lib/{BufferGeometry-Cd2ewNVQ.mjs.map → BufferGeometry-Bl5whHAB.mjs.map} +1 -1
- package/lib/ConfiguratorKernel.js +2 -2
- package/lib/ConfiguratorKernel.wasm +0 -0
- package/lib/{GLTFExporter-n80QLoDf.mjs → GLTFExporter-yQ7mMauu.mjs} +1 -1
- package/lib/{GLTFExporter-n80QLoDf.mjs.map → GLTFExporter-yQ7mMauu.mjs.map} +1 -1
- package/lib/{GaussianBlurNode-Cwy3kx8H.mjs → GaussianBlurNode-DNBEf5-n.mjs} +14 -14
- package/lib/{GaussianBlurNode-Cwy3kx8H.mjs.map → GaussianBlurNode-DNBEf5-n.mjs.map} +1 -1
- package/lib/{PointLightHelper-DlPLsDNy.mjs → PointLightHelper-CuPSBuDU.mjs} +2 -2
- package/lib/{PointLightHelper-DlPLsDNy.mjs.map → PointLightHelper-CuPSBuDU.mjs.map} +1 -1
- package/lib/RoomleCore.wasm +0 -0
- package/lib/RoomleToolsCore.wasm +0 -0
- package/lib/{SpotLightHelper-YWHbVXAF.mjs → SpotLightHelper-m-Rh8vGU.mjs} +2 -2
- package/lib/{SpotLightHelper-YWHbVXAF.mjs.map → SpotLightHelper-m-Rh8vGU.mjs.map} +1 -1
- package/lib/{USDZExporter-Bm-c5e_n.mjs → USDZExporter-MdkuT226.mjs} +1 -1
- package/lib/{USDZExporter-Bm-c5e_n.mjs.map → USDZExporter-MdkuT226.mjs.map} +1 -1
- package/lib/{api-B5wIZIHt.mjs → api-KWh-ESd5.mjs} +2 -2
- package/lib/{api-B5wIZIHt.mjs.map → api-KWh-ESd5.mjs.map} +1 -1
- package/lib/{asset-loader.worker-CE4O0JU-.mjs → asset-loader.worker-CzI1oyTY.mjs} +1 -1
- package/lib/asset-loader.worker-CzI1oyTY.mjs.map +1 -0
- package/lib/{banana-for-scale-D0bw51dn.mjs → banana-for-scale-DpKXNBt_.mjs} +2 -2
- package/lib/{banana-for-scale-D0bw51dn.mjs.map → banana-for-scale-DpKXNBt_.mjs.map} +1 -1
- package/lib/{budgeteer.sw-yR2xApHT.mjs → budgeteer.sw-D80jTmYa.mjs} +1 -1
- package/lib/budgeteer.sw-D80jTmYa.mjs.map +1 -0
- package/lib/{component-dimensioning-VIUcXV7r.mjs → component-dimensioning-luQ3LgrU.mjs} +4 -4
- package/lib/{component-dimensioning-VIUcXV7r.mjs.map → component-dimensioning-luQ3LgrU.mjs.map} +1 -1
- package/lib/{component-raycast-helper-CEAdBcdx.mjs → component-raycast-helper-hj6sm7jw.mjs} +3 -3
- package/lib/{component-raycast-helper-CEAdBcdx.mjs.map → component-raycast-helper-hj6sm7jw.mjs.map} +1 -1
- package/lib/{configurator-CxlLvBCx.mjs → configurator-CQ7KsW0O.mjs} +4 -4
- package/lib/{configurator-CxlLvBCx.mjs.map → configurator-CQ7KsW0O.mjs.map} +1 -1
- package/lib/configurator-ymHt9qjg.mjs +2 -0
- package/lib/{continuous-drawing-helper-Dr1r-5N2.mjs → continuous-drawing-helper-DqHIR_qF.mjs} +1 -1
- package/lib/{continuous-drawing-helper-Dr1r-5N2.mjs.map → continuous-drawing-helper-DqHIR_qF.mjs.map} +1 -1
- package/lib/{dimensioning-helper-ChQDwSjn.mjs → dimensioning-helper-CGPjS2hW.mjs} +2 -2
- package/lib/{dimensioning-helper-ChQDwSjn.mjs.map → dimensioning-helper-CGPjS2hW.mjs.map} +1 -1
- package/lib/dimensioning-helper-VndKlIXS.mjs +2 -0
- package/lib/{glb-viewer-27e6wfY4.mjs → glb-viewer-BWMMzvuG.mjs} +4 -4
- package/lib/{glb-viewer-27e6wfY4.mjs.map → glb-viewer-BWMMzvuG.mjs.map} +1 -1
- package/lib/glb-viewer-D5QHd6Da.mjs +2 -0
- package/lib/{highlight-coordinator-C05kDjj5.mjs → highlight-coordinator-DYjBxYpy.mjs} +2 -2
- package/lib/{highlight-coordinator-C05kDjj5.mjs.map → highlight-coordinator-DYjBxYpy.mjs.map} +1 -1
- package/lib/{homag-intelligence-BRQ1WoQo.mjs → homag-intelligence-lbse0Y0v.mjs} +3 -3
- package/lib/{homag-intelligence-BRQ1WoQo.mjs.map → homag-intelligence-lbse0Y0v.mjs.map} +1 -1
- package/lib/hosek-wilkie-sky-iMar2iw-.mjs +3755 -0
- package/lib/hosek-wilkie-sky-iMar2iw-.mjs.map +1 -0
- package/lib/{imos-ix-poc-export-helper-DhxAAMc9.mjs → imos-ix-poc-export-helper-CyGqK7nu.mjs} +1 -1
- package/lib/{imos-ix-poc-export-helper-DhxAAMc9.mjs.map → imos-ix-poc-export-helper-CyGqK7nu.mjs.map} +1 -1
- package/lib/{layer-DaGoZ5YI.mjs → layer-DRMDGxT7.mjs} +2 -2
- package/lib/layer-DRMDGxT7.mjs.map +1 -0
- package/lib/{material-viewer-Byi5t7-x.mjs → material-viewer-BKTxh5Ui.mjs} +4 -4
- package/lib/{material-viewer-Byi5t7-x.mjs.map → material-viewer-BKTxh5Ui.mjs.map} +1 -1
- package/lib/{packages-3jOdcfbr.mjs → packages-B4K6xrdJ.mjs} +5 -5
- package/lib/{packages-3jOdcfbr.mjs.map → packages-B4K6xrdJ.mjs.map} +1 -1
- package/lib/planner-BM825oIz.mjs +2 -0
- package/lib/{planner-BeINcWRR.mjs → planner-HMMHSMAp.mjs} +3 -3
- package/lib/{planner-BeINcWRR.mjs.map → planner-HMMHSMAp.mjs.map} +1 -1
- package/lib/{plugin-system-DR5maiUo.mjs → plugin-system-CRaC04G5.mjs} +2 -2
- package/lib/{plugin-system-DR5maiUo.mjs.map → plugin-system-CRaC04G5.mjs.map} +1 -1
- package/lib/roomle-headless.d.ts +162 -4
- package/lib/roomle-headless.js +11 -11
- package/lib/roomle-renderer-Ato6RMrd.mjs.map +1 -1
- package/lib/{roomle-sdk-CsSQAqQG.mjs → roomle-sdk-5aB4wxLW.mjs} +3045 -2876
- package/lib/roomle-sdk-5aB4wxLW.mjs.map +1 -0
- package/lib/roomle-sdk.d.ts +162 -4
- package/lib/roomle-sdk.js +8 -8
- package/lib/{roomle-webgpu-renderer-BBE14A8V.mjs → roomle-webgpu-renderer-BfZKcXSz.mjs} +349 -344
- package/lib/{roomle-webgpu-renderer-BBE14A8V.mjs.map → roomle-webgpu-renderer-BfZKcXSz.mjs.map} +1 -1
- package/lib/{scene-renderer-B8SBMSQ7.mjs → scene-renderer-DXvavD4L.mjs} +3 -3
- package/lib/{scene-renderer-B8SBMSQ7.mjs.map → scene-renderer-DXvavD4L.mjs.map} +1 -1
- package/lib/{script-loader-Dx3gOiB3.mjs → script-loader-axxcKvph.mjs} +2 -2
- package/lib/{script-loader-Dx3gOiB3.mjs.map → script-loader-axxcKvph.mjs.map} +1 -1
- package/lib/src-Bbq3Hqzn.mjs +2 -0
- package/lib/src-HhklrVDg.mjs +1950 -0
- package/lib/src-HhklrVDg.mjs.map +1 -0
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/package.json +1 -1
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/src/embind/configuratorCoreInterface.d.ts +16 -0
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/src/embind/configuratorCoreInterface.js +5 -1
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/src/embind/configuratorCoreInterface.js.map +1 -1
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/src/embind/plannerCoreInterface.d.ts +2 -8
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/src/embind/plannerCoreInterface.js +1 -5
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/src/embind/plannerCoreInterface.js.map +1 -1
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/wasm_modern/ConfiguratorKernel.js +2 -2
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/wasm_modern/ConfiguratorKernel.wasm +0 -0
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/wasm_modern/RoomleCore.wasm +0 -0
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/wasm_modern/RoomleToolsCore.wasm +0 -0
- package/lib/{stats-helper-W654V5ay.mjs → stats-helper-BSmoG68E.mjs} +2 -2
- package/lib/{stats-helper-W654V5ay.mjs.map → stats-helper-BSmoG68E.mjs.map} +1 -1
- package/lib/three.tsl-BTc4fg8T.mjs +2 -0
- package/lib/{three.tsl-B7hcNZE8.mjs → three.tsl-Cf0-sCqB.mjs} +70 -66
- package/lib/{three.tsl-B7hcNZE8.mjs.map → three.tsl-Cf0-sCqB.mjs.map} +1 -1
- package/lib/{threejs-utils-WK7Uu2TS.mjs → threejs-utils-CLdyrCet.mjs} +14 -14
- package/lib/threejs-utils-CLdyrCet.mjs.map +1 -0
- package/lib/{tools-core-CWrR_N9g.mjs → tools-core-DusxT3AY.mjs} +3 -3
- package/lib/{tools-core-CWrR_N9g.mjs.map → tools-core-DusxT3AY.mjs.map} +1 -1
- package/lib/webgpu-BHAP6BLI.mjs +3140 -0
- package/lib/webgpu-BHAP6BLI.mjs.map +1 -0
- package/lib/workers-B_wmKVL0.mjs +6 -0
- package/lib/{workers-B-AqdQMe.mjs.map → workers-B_wmKVL0.mjs.map} +1 -1
- package/package.json +2 -2
- package/lib/asset-loader.worker-CE4O0JU-.mjs.map +0 -1
- package/lib/budgeteer.sw-yR2xApHT.mjs.map +0 -1
- package/lib/configurator-h8QoUnMz.mjs +0 -2
- package/lib/dimensioning-helper-BEGkpZFA.mjs +0 -2
- package/lib/glb-viewer-Dc2Tl8Ef.mjs +0 -2
- package/lib/layer-DaGoZ5YI.mjs.map +0 -1
- package/lib/planner-Ler1UMAp.mjs +0 -2
- package/lib/roomle-sdk-CsSQAqQG.mjs.map +0 -1
- package/lib/three.tsl-BBUCm-uB.mjs +0 -2
- package/lib/threejs-utils-WK7Uu2TS.mjs.map +0 -1
- package/lib/webgpu-DSecxaB8.mjs +0 -5084
- package/lib/webgpu-DSecxaB8.mjs.map +0 -1
- package/lib/workers-B-AqdQMe.mjs +0 -6
|
@@ -0,0 +1,3140 @@
|
|
|
1
|
+
import { Ar as e, Ci as t, Di as n, E as r, Gn as i, Hr as a, Mr as o, On as s, S as c, Si as l, U as u, Ur as d, V as f, Xr as p, Yt as m, Zr as h, ci as g, cn as _, ct as v, h as y, ht as b, jr as x, kr as S, ln as C, m as ee, on as te, qt as w, si as ne, sn as T, vi as re, w as ie, wi as E, yn as ae } from "./three.core-0KaTx8dm.mjs";
|
|
2
|
+
import { t as oe } from "./Pass-DLiMLT5k.mjs";
|
|
3
|
+
import { C as se, Dt as ce, Fn as le, Gn as ue, H as de, Hn as D, Rn as O, Vn as fe, X as k, ln as pe, vt as me } from "./three.webgpu-D3nSEIjD.mjs";
|
|
4
|
+
import { l as he, n as ge, o as _e, r as ve, t as ye } from "./src-HhklrVDg.mjs";
|
|
5
|
+
import { At as A, B as be, Dt as j, E as M, Ft as xe, Ht as Se, M as N, Ot as Ce, Pt as we, Rt as Te, St as P, Tt as F, Ut as I, jt as Ee, kt as De, pt as L, z as Oe } from "./three.tsl-Cf0-sCqB.mjs";
|
|
6
|
+
Object.defineProperty(D.prototype, "layout", { get() {
|
|
7
|
+
return this;
|
|
8
|
+
} }), D.prototype.isStruct = !0;
|
|
9
|
+
var ke = new D({
|
|
10
|
+
min: "array<f32, 3>",
|
|
11
|
+
max: "array<f32, 3>"
|
|
12
|
+
}, "BVHBoundingBox");
|
|
13
|
+
ke.getLength = () => 6;
|
|
14
|
+
var Ae = new D({
|
|
15
|
+
bounds: "BVHBoundingBox",
|
|
16
|
+
rightChildOrTriangleOffset: "uint",
|
|
17
|
+
splitAxisOrTriangleCount: "uint"
|
|
18
|
+
}, "BVHNode");
|
|
19
|
+
Ae.getLength = () => ke.getLength() + 2;
|
|
20
|
+
var je = new D({
|
|
21
|
+
matrixWorld: "mat4x4f",
|
|
22
|
+
inverseMatrixWorld: "mat4x4f",
|
|
23
|
+
nodeOffset: "uint",
|
|
24
|
+
visible: "uint",
|
|
25
|
+
_alignment0: "uint",
|
|
26
|
+
_alignment1: "uint"
|
|
27
|
+
}, "TransformStruct"), R = new D({
|
|
28
|
+
origin: "vec3f",
|
|
29
|
+
direction: "vec3f"
|
|
30
|
+
}, "Ray"), z = new D({
|
|
31
|
+
indices: "vec4u",
|
|
32
|
+
normal: "vec3f",
|
|
33
|
+
didHit: "bool",
|
|
34
|
+
barycoord: "vec3f",
|
|
35
|
+
objectIndex: "uint",
|
|
36
|
+
side: "float",
|
|
37
|
+
dist: "float"
|
|
38
|
+
}, "IntersectionResult"), Me = new D({
|
|
39
|
+
faceIndices: "vec4u",
|
|
40
|
+
closestPoint: "vec3f",
|
|
41
|
+
found: "bool",
|
|
42
|
+
barycoord: "vec3f",
|
|
43
|
+
objectIndex: "uint",
|
|
44
|
+
faceNormal: "vec3f",
|
|
45
|
+
side: "float",
|
|
46
|
+
distanceSq: "float"
|
|
47
|
+
}, "PointQueryResult"), Ne = ue.nodeProxyConstructor ?? ((e, t) => new Proxy(e, {
|
|
48
|
+
get(e, n, r) {
|
|
49
|
+
let i = Reflect.get(t, n, r);
|
|
50
|
+
return i === void 0 && n === "functionNode" ? t : i;
|
|
51
|
+
},
|
|
52
|
+
set(e, n, r) {
|
|
53
|
+
return Reflect.set(t, n, r);
|
|
54
|
+
}
|
|
55
|
+
})), Pe = class extends ce {
|
|
56
|
+
static get type() {
|
|
57
|
+
return "ProxyCallNode";
|
|
58
|
+
}
|
|
59
|
+
constructor(e, t) {
|
|
60
|
+
super(), this.proxyNode = e, this.params = t;
|
|
61
|
+
}
|
|
62
|
+
setup() {
|
|
63
|
+
return this.proxyNode.proxyNode.call(...this.params);
|
|
64
|
+
}
|
|
65
|
+
}, Fe = class {
|
|
66
|
+
get isNode() {
|
|
67
|
+
return !0;
|
|
68
|
+
}
|
|
69
|
+
get proxyNode() {
|
|
70
|
+
let { proxyObject: e, proxyProperty: t } = this, n = t.split("."), r = e;
|
|
71
|
+
for (let e = 0, t = n.length; e < t; e++) r = r[n[e]];
|
|
72
|
+
return r && "functionNode" in r ? r.functionNode : r;
|
|
73
|
+
}
|
|
74
|
+
constructor(e, t = null) {
|
|
75
|
+
return this.proxyObject = t, this.proxyProperty = e, new Proxy(this, {
|
|
76
|
+
get(e, t) {
|
|
77
|
+
if (t in e) return Reflect.get(e, t);
|
|
78
|
+
{
|
|
79
|
+
let n = e.proxyNode;
|
|
80
|
+
if (!n) return;
|
|
81
|
+
let r = Reflect.get(n, t);
|
|
82
|
+
return typeof r == "function" ? r.bind(n) : r;
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
set(e, t, n) {
|
|
86
|
+
if (t in e) return Reflect.set(e, t, n);
|
|
87
|
+
throw Error("NodeProxy: Cannot set members of proxied nodes.");
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}, B = (...e) => new Fe(...e), V = (...e) => {
|
|
92
|
+
let t = new Fe(...e);
|
|
93
|
+
return Ne((...e) => new Pe(t, e), t);
|
|
94
|
+
};
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region ../../node_modules/three-gpu-pathtracer/src/webgpu/lib/three-mesh-bvh/utils/toObjectBVH.js
|
|
97
|
+
function Ie(e) {
|
|
98
|
+
return e instanceof ge ? e : (Array.isArray(e) || (e = [e]), new ge(e.map((e) => {
|
|
99
|
+
if (e.isObject3D) return e;
|
|
100
|
+
if (e.isBufferGeometry) return new _(e);
|
|
101
|
+
if (e instanceof _e) {
|
|
102
|
+
let t = new _();
|
|
103
|
+
return t.geometry.boundsTree = e, t;
|
|
104
|
+
}
|
|
105
|
+
}), {
|
|
106
|
+
strategy: 2,
|
|
107
|
+
targetLeafSize: 1
|
|
108
|
+
}));
|
|
109
|
+
}
|
|
110
|
+
//#endregion
|
|
111
|
+
//#region ../../node_modules/three-gpu-pathtracer/src/webgpu/lib/three-mesh-bvh/utils/packBVHBufferUtils.js
|
|
112
|
+
var H = /* @__PURE__ */ new E(), U = /* @__PURE__ */ new E();
|
|
113
|
+
function Le(e, t) {
|
|
114
|
+
let n = e ? e.array : null, r = new Uint32Array(t.length * 3);
|
|
115
|
+
for (let e = 0, i = t.length; e < i; e++) {
|
|
116
|
+
let i = 3 * e, a = 3 * t[e];
|
|
117
|
+
for (let e = 0; e < 3; e++) r[i + e] = n ? n[a + e] : a + e;
|
|
118
|
+
}
|
|
119
|
+
return r;
|
|
120
|
+
}
|
|
121
|
+
function Re(e, t, n, r, i, a = !1) {
|
|
122
|
+
let o = new Uint16Array(i), s = new Uint32Array(i), c = new Float32Array(i), l = [], u = 0;
|
|
123
|
+
return e._roots.forEach((e) => {
|
|
124
|
+
let i = new Uint16Array(e), d = new Uint32Array(e);
|
|
125
|
+
l.push(r);
|
|
126
|
+
for (let l = 0, f = e.byteLength / 32; l < f; l++) {
|
|
127
|
+
let f = l * 8, p = f * 2, m = r * 8, h = m * 2, g = new Float32Array(e, l * 32, 6);
|
|
128
|
+
if (l === 0) for (let e = 0; e < 3; e++) {
|
|
129
|
+
let t = g[e + 0], n = g[e + 3];
|
|
130
|
+
t > n ? (c[m + e + 0] = 1, c[m + e + 3] = -1) : (c[m + e + 0] = t, c[m + e + 3] = n);
|
|
131
|
+
}
|
|
132
|
+
else c.set(g, m);
|
|
133
|
+
if (i[p + 15] === 65535) if (a) {
|
|
134
|
+
s[m + 6] = u, o[h + 15] = 65280;
|
|
135
|
+
let e = i[p + 14], t = 0;
|
|
136
|
+
for (let r = 0; r < e; r++) {
|
|
137
|
+
let e = n[u].data.bvh._roots.length;
|
|
138
|
+
u += e, t += e;
|
|
139
|
+
}
|
|
140
|
+
o[h + 14] = t;
|
|
141
|
+
} else s[m + 6] = d[f + 6] + t, o[h + 14] = i[p + 14], o[h + 15] = he;
|
|
142
|
+
else s[m + 6] = d[f + 6], s[m + 7] = d[f + 7];
|
|
143
|
+
r++;
|
|
144
|
+
}
|
|
145
|
+
}), l;
|
|
146
|
+
}
|
|
147
|
+
function ze(e, t, n, r, i) {
|
|
148
|
+
let { geometry: a } = e, { start: o, count: s, vertexStart: c } = t;
|
|
149
|
+
if (e.indirect) {
|
|
150
|
+
let t = Le(a.index, e._indirectBuffer);
|
|
151
|
+
for (let e = 0; e < t.length; e++) i[e + r] = t[e] - c + n;
|
|
152
|
+
} else if (a.index) for (let e = 0; e < s; e++) i[e + r] = a.index.getX(e + o) - c + n;
|
|
153
|
+
else for (let e = 0; e < s; e++) i[e + r] = e + o + n;
|
|
154
|
+
}
|
|
155
|
+
function Be(e, t, n, r, i, a) {
|
|
156
|
+
let { geometry: o, mesh: s = null } = e, { vertexStart: c, vertexCount: l } = t, u = new Float32Array(r), d = i.getLength();
|
|
157
|
+
i.membersLayout.forEach(({ name: e }, t) => {
|
|
158
|
+
let r = o.attributes[e];
|
|
159
|
+
a.getDefaultAttributeValue(e, H);
|
|
160
|
+
for (let i = 0; i < l; i++) {
|
|
161
|
+
if (r) {
|
|
162
|
+
switch (U.fromBufferAttribute(r, i + c), r.itemSize) {
|
|
163
|
+
case 1:
|
|
164
|
+
U.y = H.y, U.z = H.z, U.w = H.w;
|
|
165
|
+
break;
|
|
166
|
+
case 2:
|
|
167
|
+
U.z = H.z, U.w = H.w;
|
|
168
|
+
break;
|
|
169
|
+
case 3:
|
|
170
|
+
U.w = H.w;
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
s && (e === "position" || e === "normal" || e === "tangent") && s.applyBoneTransform(i + c, U);
|
|
174
|
+
} else U.copy(H);
|
|
175
|
+
U.toArray(u, (n + i) * d + t * 4);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
//#endregion
|
|
180
|
+
//#region ../../node_modules/three-gpu-pathtracer/src/webgpu/lib/three-mesh-bvh/nodes/WGSLTagFnNode.js
|
|
181
|
+
var Ve = ue.nodeProxyConstructor ?? ((e, t) => new Proxy(e, {
|
|
182
|
+
get(e, n, r) {
|
|
183
|
+
let i = Reflect.get(t, n, r);
|
|
184
|
+
return i === void 0 && n === "functionNode" ? t : i;
|
|
185
|
+
},
|
|
186
|
+
set(e, n, r) {
|
|
187
|
+
return Reflect.set(t, n, r);
|
|
188
|
+
}
|
|
189
|
+
})), He = class extends ce {
|
|
190
|
+
constructor(e) {
|
|
191
|
+
super(), this.literal = e;
|
|
192
|
+
}
|
|
193
|
+
build() {
|
|
194
|
+
return this.literal;
|
|
195
|
+
}
|
|
196
|
+
}, Ue = class extends ce {
|
|
197
|
+
constructor(e, t = "property") {
|
|
198
|
+
super(), this.node = e, this.output = t;
|
|
199
|
+
}
|
|
200
|
+
build(e) {
|
|
201
|
+
return this.node.build(e, this.output);
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
function We(e) {
|
|
205
|
+
return typeof e == "function" && e.functionNode && !e.isNode ? e.functionNode : e;
|
|
206
|
+
}
|
|
207
|
+
function Ge(e) {
|
|
208
|
+
return e = We(e), e.isNode ? new Ue(e) : null;
|
|
209
|
+
}
|
|
210
|
+
function Ke(e) {
|
|
211
|
+
let t = [];
|
|
212
|
+
for (let n of e) if (Array.isArray(n)) for (let e of n) {
|
|
213
|
+
let n = Ge(e);
|
|
214
|
+
n && t.push(n);
|
|
215
|
+
}
|
|
216
|
+
return t;
|
|
217
|
+
}
|
|
218
|
+
function qe(e) {
|
|
219
|
+
return e.map((e) => (e = We(e), e && e.isNode ? e instanceof Xe ? new Ue(e, "inline") : new Ue(e) : e));
|
|
220
|
+
}
|
|
221
|
+
function Je(e, t, n) {
|
|
222
|
+
let r = "";
|
|
223
|
+
for (let i = 0, a = e.length; i < a; i++) if (r += e[i], i < t.length) {
|
|
224
|
+
let e = We(t[i]);
|
|
225
|
+
Array.isArray(e) || (typeof e == "string" || typeof e == "number" ? r += String(e) : r += e.build(n));
|
|
226
|
+
}
|
|
227
|
+
return r;
|
|
228
|
+
}
|
|
229
|
+
var Ye = class extends de {
|
|
230
|
+
static get type() {
|
|
231
|
+
return "WGSLTagFnNode";
|
|
232
|
+
}
|
|
233
|
+
constructor(e, t, n = "wgsl") {
|
|
234
|
+
super("", Ke(t), n), this.tokens = e, this.args = t;
|
|
235
|
+
}
|
|
236
|
+
getNodeFunction(e) {
|
|
237
|
+
let { tokens: t } = this, n = qe(this.args), r = e.getDataFromNode(this), i = r.nodeFunction;
|
|
238
|
+
if (i === void 0) {
|
|
239
|
+
let a = "";
|
|
240
|
+
for (let r = 0, i = t.length; r < i; r++) if (a += t[r], r < n.length) {
|
|
241
|
+
let t = n[r];
|
|
242
|
+
Array.isArray(t) || (typeof t == "string" || typeof t == "number" ? a += String(t) : t.isStructLayoutNode ? a += t.getNodeType(e) : t.isStruct ? a += t.layout.getNodeType(e) : a += "_arg" + r);
|
|
243
|
+
}
|
|
244
|
+
a = a.replace(/\/\/.+[\n\r]/g, ""), i = e.parser.parseFunction(a), r.nodeFunction = i;
|
|
245
|
+
}
|
|
246
|
+
return i;
|
|
247
|
+
}
|
|
248
|
+
generate(e, t) {
|
|
249
|
+
let n = super.generate(e, t), r = Je(this.tokens, qe(this.args), e), { type: i } = this.getNodeFunction(e), a = e.getCodeFromNode(this, i);
|
|
250
|
+
return a.code = r.replace(/\/\/.+[\n\r]/g, "").replace(/->\s*void/, "").trim(), n;
|
|
251
|
+
}
|
|
252
|
+
}, Xe = class extends se {
|
|
253
|
+
static get type() {
|
|
254
|
+
return "WGSLTagCodeNode";
|
|
255
|
+
}
|
|
256
|
+
constructor(e, t, n = "wgsl") {
|
|
257
|
+
super("", Ke(t), n), this.tokens = e, this.args = t;
|
|
258
|
+
}
|
|
259
|
+
build(e, t) {
|
|
260
|
+
return t === "inline" ? Je(this.tokens, qe(this.args), e) : super.build(e, t);
|
|
261
|
+
}
|
|
262
|
+
generate(e) {
|
|
263
|
+
super.generate(e);
|
|
264
|
+
let t = e.getCodeFromNode(this, this.getNodeType(e));
|
|
265
|
+
return t.code = Je(this.tokens, qe(this.args), e), t.code;
|
|
266
|
+
}
|
|
267
|
+
}, Ze = (e) => Ve((...t) => {
|
|
268
|
+
if (t.length === 1 && t[0] && typeof t[0] == "object" && !t[0].isNode) {
|
|
269
|
+
let e = t[0];
|
|
270
|
+
for (let t in e) typeof e[t] == "string" && (e[t] = new He(e[t]));
|
|
271
|
+
}
|
|
272
|
+
return e.call(...t);
|
|
273
|
+
}, e), W = (e, ...t) => Ze(new Ye(e, t)), G = (e, ...t) => new Xe(e, t), Qe = De(60);
|
|
274
|
+
//#endregion
|
|
275
|
+
//#region ../../node_modules/three-gpu-pathtracer/src/webgpu/lib/three-mesh-bvh/shapecastFns/getShapecastFn.js
|
|
276
|
+
function $e(e, t) {
|
|
277
|
+
let { name: n = `bvh_shapecast_fn_${Math.random().toString(36).substring(2, 7)}`, shapeStruct: r, resultStruct: i = null, boundsOrderFn: a = null, intersectsBoundsFn: o, intersectRangeFn: s, transformShapeFn: c = null, transformResultFn: l = null, resetShapeFn: u = null } = t, { nodes: d, transforms: f } = e.storage, p = "";
|
|
278
|
+
l && (p = G`${l}( result, i );`);
|
|
279
|
+
let m = "";
|
|
280
|
+
c && (m = G`${c}( &localShape, i );`);
|
|
281
|
+
let h = "";
|
|
282
|
+
u && (h = G`${u}( i );`);
|
|
283
|
+
let g = "";
|
|
284
|
+
a && (g = G`
|
|
285
|
+
let leftToRight = ${a}( shape, splitAxis, node );
|
|
286
|
+
c1 = select( rightIndex, leftIndex, leftToRight );
|
|
287
|
+
c2 = select( leftIndex, rightIndex, leftToRight );
|
|
288
|
+
`);
|
|
289
|
+
let _ = i ? G`result: ptr<function, ${i}>` : "", v = i ? "result" : "", y = (e) => G`
|
|
290
|
+
|
|
291
|
+
var pointer: i32 = 0;
|
|
292
|
+
var stack: array<u32, ${Qe}>;
|
|
293
|
+
stack[ 0 ] = rootNodeIndex;
|
|
294
|
+
|
|
295
|
+
loop {
|
|
296
|
+
|
|
297
|
+
if ( pointer < 0 || pointer >= i32( ${Qe} ) ) {
|
|
298
|
+
|
|
299
|
+
break;
|
|
300
|
+
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
let nodeIndex = stack[ pointer ];
|
|
304
|
+
let node = ${d}[ nodeIndex ];
|
|
305
|
+
pointer = pointer - 1;
|
|
306
|
+
|
|
307
|
+
if ( ${o}( shape, node.bounds, ${v} ) == 0u ) {
|
|
308
|
+
|
|
309
|
+
continue;
|
|
310
|
+
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
let infoX = node.splitAxisOrTriangleCount;
|
|
314
|
+
let infoY = node.rightChildOrTriangleOffset;
|
|
315
|
+
let isLeaf = ( infoX & 0xffff0000u ) != 0u;
|
|
316
|
+
|
|
317
|
+
if ( isLeaf ) {
|
|
318
|
+
|
|
319
|
+
let count = infoX & 0x0000ffffu;
|
|
320
|
+
let offset = infoY;
|
|
321
|
+
${e}
|
|
322
|
+
|
|
323
|
+
} else {
|
|
324
|
+
|
|
325
|
+
let leftIndex = nodeIndex + 1u;
|
|
326
|
+
let splitAxis = infoX & 0x0000ffffu;
|
|
327
|
+
let rightIndex = nodeIndex + infoY;
|
|
328
|
+
|
|
329
|
+
var c1 = rightIndex;
|
|
330
|
+
var c2 = leftIndex;
|
|
331
|
+
${g}
|
|
332
|
+
|
|
333
|
+
pointer = pointer + 1;
|
|
334
|
+
stack[ pointer ] = c2;
|
|
335
|
+
|
|
336
|
+
pointer = pointer + 1;
|
|
337
|
+
stack[ pointer ] = c1;
|
|
338
|
+
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
`, b = W`
|
|
344
|
+
// fn
|
|
345
|
+
fn ${n}_blas( shape: ${r}, rootNodeIndex: u32, ${_} ) -> bool {
|
|
346
|
+
|
|
347
|
+
var didHit = false;
|
|
348
|
+
${y(G`
|
|
349
|
+
|
|
350
|
+
didHit = ${s}( shape, offset, count, ${v} ) || didHit;
|
|
351
|
+
|
|
352
|
+
`)}
|
|
353
|
+
|
|
354
|
+
return didHit;
|
|
355
|
+
|
|
356
|
+
}
|
|
357
|
+
`, x = W`
|
|
358
|
+
// fn
|
|
359
|
+
fn ${n}( shape: ${r}, ${_} ) -> bool {
|
|
360
|
+
|
|
361
|
+
const rootNodeIndex = 0u;
|
|
362
|
+
var didHit = false;
|
|
363
|
+
${y(G`
|
|
364
|
+
|
|
365
|
+
for ( var i = offset; i < offset + count; i ++ ) {
|
|
366
|
+
|
|
367
|
+
let transform = ${f}[ i ];
|
|
368
|
+
if ( transform.visible == 0u ) {
|
|
369
|
+
|
|
370
|
+
continue;
|
|
371
|
+
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Transform shape into object local space
|
|
375
|
+
var localShape = shape;
|
|
376
|
+
${m}
|
|
377
|
+
|
|
378
|
+
if ( ${b}( localShape, transform.nodeOffset, ${v} ) ) {
|
|
379
|
+
|
|
380
|
+
${p}
|
|
381
|
+
didHit = true;
|
|
382
|
+
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
${h}
|
|
386
|
+
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
`)}
|
|
390
|
+
|
|
391
|
+
return didHit;
|
|
392
|
+
|
|
393
|
+
}
|
|
394
|
+
`;
|
|
395
|
+
return x.outputType = i, x.functionName = n, x;
|
|
396
|
+
}
|
|
397
|
+
//#endregion
|
|
398
|
+
//#region ../../node_modules/three-gpu-pathtracer/src/webgpu/lib/three-mesh-bvh/tsl/fns.js
|
|
399
|
+
var et = W`
|
|
400
|
+
// fn
|
|
401
|
+
fn closestPointToTriangle(
|
|
402
|
+
p: vec3f,
|
|
403
|
+
v0: vec3f,
|
|
404
|
+
v1: vec3f,
|
|
405
|
+
v2: vec3f
|
|
406
|
+
) -> vec3f {
|
|
407
|
+
|
|
408
|
+
let v10 = v1 - v0;
|
|
409
|
+
let v21 = v2 - v1;
|
|
410
|
+
let v02 = v0 - v2;
|
|
411
|
+
let p0 = p - v0;
|
|
412
|
+
let p1 = p - v1;
|
|
413
|
+
let p2 = p - v2;
|
|
414
|
+
|
|
415
|
+
let nor = cross( v10, v02 );
|
|
416
|
+
let q = cross( nor, p0 );
|
|
417
|
+
let d = 1.0 / dot( nor, nor );
|
|
418
|
+
var u = d * dot( q, v02 );
|
|
419
|
+
var v = d * dot( q, v10 );
|
|
420
|
+
var w = 1.0 - u - v;
|
|
421
|
+
|
|
422
|
+
if ( u < 0.0 ) {
|
|
423
|
+
|
|
424
|
+
w = clamp( dot( p2, v02 ) / dot( v02, v02 ), 0.0, 1.0 );
|
|
425
|
+
u = 0.0;
|
|
426
|
+
v = 1.0 - w;
|
|
427
|
+
|
|
428
|
+
} else if ( v < 0.0 ) {
|
|
429
|
+
|
|
430
|
+
u = clamp( dot( p0, v10 ) / dot( v10, v10 ), 0.0, 1.0 );
|
|
431
|
+
v = 0.0;
|
|
432
|
+
w = 1.0 - u;
|
|
433
|
+
|
|
434
|
+
} else if ( w < 0.0 ) {
|
|
435
|
+
|
|
436
|
+
v = clamp( dot( p1, v21 ) / dot( v21, v21 ), 0.0, 1.0 );
|
|
437
|
+
w = 0.0;
|
|
438
|
+
u = 1.0 - v;
|
|
439
|
+
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
return vec3f( w, u, v );
|
|
443
|
+
|
|
444
|
+
}
|
|
445
|
+
`, tt = W`
|
|
446
|
+
// fn
|
|
447
|
+
fn intersectRayTriangle( ray: ${R}, a: vec3f, b: vec3f, c: vec3f, threshold: f32 ) -> ${z} {
|
|
448
|
+
|
|
449
|
+
const DET_EPSILON = 1e-15;
|
|
450
|
+
|
|
451
|
+
var result: ${z};
|
|
452
|
+
result.didHit = false;
|
|
453
|
+
|
|
454
|
+
let edge1 = b - a;
|
|
455
|
+
let edge2 = c - a;
|
|
456
|
+
let n = cross( edge1, edge2 );
|
|
457
|
+
|
|
458
|
+
let det = - dot( ray.direction, n );
|
|
459
|
+
if ( abs( det ) < DET_EPSILON ) {
|
|
460
|
+
|
|
461
|
+
return result;
|
|
462
|
+
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
let invdet = 1.0 / det;
|
|
466
|
+
|
|
467
|
+
let AO = ray.origin - a;
|
|
468
|
+
let DAO = cross( AO, ray.direction );
|
|
469
|
+
|
|
470
|
+
let u = dot( edge2, DAO ) * invdet;
|
|
471
|
+
if ( u < 0.0 || u > 1.0 ) {
|
|
472
|
+
|
|
473
|
+
return result;
|
|
474
|
+
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
let v = - dot( edge1, DAO ) * invdet;
|
|
478
|
+
if ( v < 0.0 || u + v > 1.0 ) {
|
|
479
|
+
|
|
480
|
+
return result;
|
|
481
|
+
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
let t = dot( AO, n ) * invdet;
|
|
485
|
+
let w = 1.0 - u - v;
|
|
486
|
+
if ( t < threshold ) {
|
|
487
|
+
|
|
488
|
+
return result;
|
|
489
|
+
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
result.didHit = true;
|
|
493
|
+
result.barycoord = vec3f( w, u, v );
|
|
494
|
+
result.dist = t;
|
|
495
|
+
result.side = sign( det );
|
|
496
|
+
result.normal = result.side * normalize( n );
|
|
497
|
+
|
|
498
|
+
return result;
|
|
499
|
+
|
|
500
|
+
}
|
|
501
|
+
`, nt = W`
|
|
502
|
+
// fn
|
|
503
|
+
fn ndcToCameraRay( ndc: vec2f, inverseModelViewProjection: mat4x4f ) -> ${R} {
|
|
504
|
+
|
|
505
|
+
var homogeneous = vec4f();
|
|
506
|
+
var ray: ${R};
|
|
507
|
+
|
|
508
|
+
homogeneous = inverseModelViewProjection * vec4f( ndc, 0.0, 1.0 );
|
|
509
|
+
ray.origin = homogeneous.xyz / homogeneous.w;
|
|
510
|
+
|
|
511
|
+
homogeneous = inverseModelViewProjection * vec4f( ndc, 1.0, 1.0 );
|
|
512
|
+
ray.direction = ( homogeneous.xyz / homogeneous.w ) - ray.origin;
|
|
513
|
+
|
|
514
|
+
return ray;
|
|
515
|
+
|
|
516
|
+
}
|
|
517
|
+
`;
|
|
518
|
+
//#endregion
|
|
519
|
+
//#region ../../node_modules/three-gpu-pathtracer/src/webgpu/lib/three-mesh-bvh/shapecastFns/getRaycastFirstHitFn.js
|
|
520
|
+
function rt(e) {
|
|
521
|
+
let { index: t, attributes: n, transforms: r } = e.storage, i = M(1).toVar(`bvh_rayScalar_${Math.random().toString(36).substring(2, 7)}`);
|
|
522
|
+
return e.getShapecastFn({
|
|
523
|
+
name: "bvh_RaycastFirstHit",
|
|
524
|
+
shapeStruct: R,
|
|
525
|
+
resultStruct: z,
|
|
526
|
+
boundsOrderFn: W`
|
|
527
|
+
fn getBoundsOrder( ray: ${R}, splitAxis: u32, node: ${Ae} ) -> bool {
|
|
528
|
+
|
|
529
|
+
return ray.direction[ splitAxis ] >= 0.0;
|
|
530
|
+
|
|
531
|
+
}
|
|
532
|
+
`,
|
|
533
|
+
intersectsBoundsFn: W`
|
|
534
|
+
fn rayIntersectsBounds( ray: ${R}, bounds: ${ke}, result: ptr<function, ${z}> ) -> u32 {
|
|
535
|
+
|
|
536
|
+
let boundsMin = vec3( bounds.min[0], bounds.min[1], bounds.min[2] );
|
|
537
|
+
let boundsMax = vec3( bounds.max[0], bounds.max[1], bounds.max[2] );
|
|
538
|
+
|
|
539
|
+
let invDir = 1.0 / ray.direction;
|
|
540
|
+
let tMinPlane = ( boundsMin - ray.origin ) * invDir;
|
|
541
|
+
let tMaxPlane = ( boundsMax - ray.origin ) * invDir;
|
|
542
|
+
|
|
543
|
+
let tMinHit = vec3f(
|
|
544
|
+
min( tMinPlane.x, tMaxPlane.x ),
|
|
545
|
+
min( tMinPlane.y, tMaxPlane.y ),
|
|
546
|
+
min( tMinPlane.z, tMaxPlane.z )
|
|
547
|
+
);
|
|
548
|
+
|
|
549
|
+
let tMaxHit = vec3f(
|
|
550
|
+
max( tMinPlane.x, tMaxPlane.x ),
|
|
551
|
+
max( tMinPlane.y, tMaxPlane.y ),
|
|
552
|
+
max( tMinPlane.z, tMaxPlane.z )
|
|
553
|
+
);
|
|
554
|
+
|
|
555
|
+
let t0 = max( max( tMinHit.x, tMinHit.y ), tMinHit.z );
|
|
556
|
+
let t1 = min( min( tMaxHit.x, tMaxHit.y ), tMaxHit.z );
|
|
557
|
+
|
|
558
|
+
let dist = max( t0, 0.0 );
|
|
559
|
+
if ( t1 < dist ) {
|
|
560
|
+
|
|
561
|
+
return 0u;
|
|
562
|
+
|
|
563
|
+
} else if ( result.didHit && dist * ${i} >= result.dist ) {
|
|
564
|
+
|
|
565
|
+
return 0u;
|
|
566
|
+
|
|
567
|
+
} else {
|
|
568
|
+
|
|
569
|
+
return 1u;
|
|
570
|
+
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
`,
|
|
576
|
+
intersectRangeFn: W`
|
|
577
|
+
fn intersectRange( ray: ${R}, offset: u32, count: u32, result: ptr<function, ${z}> ) -> bool {
|
|
578
|
+
|
|
579
|
+
var didHit = false;
|
|
580
|
+
for ( var ti = offset; ti < offset + count; ti = ti + 1u ) {
|
|
581
|
+
|
|
582
|
+
let i0 = ${t}[ ti * 3u ];
|
|
583
|
+
let i1 = ${t}[ ti * 3u + 1u ];
|
|
584
|
+
let i2 = ${t}[ ti * 3u + 2u ];
|
|
585
|
+
|
|
586
|
+
let a = ${n}[ i0 ].position.xyz;
|
|
587
|
+
let b = ${n}[ i1 ].position.xyz;
|
|
588
|
+
let c = ${n}[ i2 ].position.xyz;
|
|
589
|
+
|
|
590
|
+
var triResult = ${tt}( ray, a, b, c, 0.0 );
|
|
591
|
+
triResult.dist *= ${i};
|
|
592
|
+
if ( triResult.didHit && ( ! result.didHit || triResult.dist < result.dist ) ) {
|
|
593
|
+
|
|
594
|
+
result.didHit = true;
|
|
595
|
+
result.dist = triResult.dist;
|
|
596
|
+
result.normal = triResult.normal;
|
|
597
|
+
result.side = triResult.side;
|
|
598
|
+
result.barycoord = triResult.barycoord;
|
|
599
|
+
result.indices = vec4u( i0, i1, i2, ti );
|
|
600
|
+
|
|
601
|
+
didHit = true;
|
|
602
|
+
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
return didHit;
|
|
608
|
+
|
|
609
|
+
}
|
|
610
|
+
`,
|
|
611
|
+
transformShapeFn: W`
|
|
612
|
+
fn transformRay( ray: ptr<function, ${R}>, objectIndex: u32 ) -> void {
|
|
613
|
+
|
|
614
|
+
let toLocal = ${r}[ objectIndex ].inverseMatrixWorld;
|
|
615
|
+
ray.origin = ( toLocal * vec4f( ray.origin, 1.0 ) ).xyz;
|
|
616
|
+
ray.direction = ( toLocal * vec4f( ray.direction, 0.0 ) ).xyz;
|
|
617
|
+
|
|
618
|
+
let len = length( ray.direction );
|
|
619
|
+
ray.direction /= len;
|
|
620
|
+
${i} = 1.0 / len;
|
|
621
|
+
|
|
622
|
+
}
|
|
623
|
+
`,
|
|
624
|
+
transformResultFn: W`
|
|
625
|
+
fn transformResult( hit: ptr<function, ${z}>, objectIndex: u32 ) -> void {
|
|
626
|
+
|
|
627
|
+
let toLocal = ${r}[ objectIndex ].inverseMatrixWorld;
|
|
628
|
+
hit.normal = normalize( ( transpose( toLocal ) * vec4f( hit.normal, 0.0 ) ).xyz );
|
|
629
|
+
hit.objectIndex = objectIndex;
|
|
630
|
+
|
|
631
|
+
}
|
|
632
|
+
`,
|
|
633
|
+
resetShapeFn: W`
|
|
634
|
+
fn resetRayScalar( objectIndex: u32 ) -> void {
|
|
635
|
+
|
|
636
|
+
${i} = 1.0;
|
|
637
|
+
|
|
638
|
+
}
|
|
639
|
+
`
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
//#endregion
|
|
643
|
+
//#region ../../node_modules/three-gpu-pathtracer/src/webgpu/lib/three-mesh-bvh/shapecastFns/getSampleTrianglePointFn.js
|
|
644
|
+
function it(e) {
|
|
645
|
+
let { storage: t, structs: n } = e, r = n.attributes.membersLayout.map(({ name: e }) => `result.${e} = a0.${e} * barycoord.x + a1.${e} * barycoord.y + a2.${e} * barycoord.z;`).join("\n");
|
|
646
|
+
return W`
|
|
647
|
+
// fn
|
|
648
|
+
fn bvh_sampleTrianglePoint( barycoord: vec3f, indices: vec3u ) -> ${n.attributes} {
|
|
649
|
+
|
|
650
|
+
var result: ${n.attributes};
|
|
651
|
+
var a0 = ${t.attributes}[ indices.x ];
|
|
652
|
+
var a1 = ${t.attributes}[ indices.y ];
|
|
653
|
+
var a2 = ${t.attributes}[ indices.z ];
|
|
654
|
+
${r}
|
|
655
|
+
return result;
|
|
656
|
+
|
|
657
|
+
}
|
|
658
|
+
`;
|
|
659
|
+
}
|
|
660
|
+
//#endregion
|
|
661
|
+
//#region ../../node_modules/three-gpu-pathtracer/src/webgpu/lib/three-mesh-bvh/shapecastFns/getClosestPointToPointFn.js
|
|
662
|
+
function at(e) {
|
|
663
|
+
let { index: t, attributes: n, transforms: r } = e.storage, i = be().toVar("bvh_toWorldMat");
|
|
664
|
+
return e.getShapecastFn({
|
|
665
|
+
name: "bvh_ClosestPointToPoint",
|
|
666
|
+
shapeStruct: "vec3f",
|
|
667
|
+
resultStruct: Me,
|
|
668
|
+
boundsOrderFn: W`
|
|
669
|
+
fn cppBoundsOrder( shape: vec3f, splitAxis: u32, node: ${Ae} ) -> bool {
|
|
670
|
+
|
|
671
|
+
let toWorld = ${i};
|
|
672
|
+
|
|
673
|
+
// get center
|
|
674
|
+
let bMin = vec3f( node.bounds.min[ 0 ], node.bounds.min[ 1 ], node.bounds.min[ 2 ] );
|
|
675
|
+
let bMax = vec3f( node.bounds.max[ 0 ], node.bounds.max[ 1 ], node.bounds.max[ 2 ] );
|
|
676
|
+
let center = bMin * 0.5 + bMax * 0.5;
|
|
677
|
+
|
|
678
|
+
// determine the order in world space
|
|
679
|
+
let worldCenter = ( toWorld * vec4f( center, 1.0 ) ).xyz;
|
|
680
|
+
let worldAxis = normalize( toWorld[ splitAxis ].xyz );
|
|
681
|
+
return dot( shape - worldCenter, worldAxis ) <= 0.0;
|
|
682
|
+
|
|
683
|
+
}
|
|
684
|
+
`,
|
|
685
|
+
intersectsBoundsFn: W`
|
|
686
|
+
fn cppIntersectsBounds( shape: vec3f, bounds: ${ke}, result: ptr<function, ${Me}> ) -> u32 {
|
|
687
|
+
|
|
688
|
+
// return 1u;
|
|
689
|
+
// we need to check this no matter what if the result has not been found yet
|
|
690
|
+
if ( ! result.found ) {
|
|
691
|
+
|
|
692
|
+
return 1u;
|
|
693
|
+
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
let toWorld = ${i};
|
|
697
|
+
|
|
698
|
+
// transform to world space
|
|
699
|
+
let bMin = vec3f( bounds.min[ 0 ], bounds.min[ 1 ], bounds.min[ 2 ] );
|
|
700
|
+
let bMax = vec3f( bounds.max[ 0 ], bounds.max[ 1 ], bounds.max[ 2 ] );
|
|
701
|
+
let center = ( bMin + bMax ) * 0.5;
|
|
702
|
+
let halfExtent = ( bMax - bMin ) * 0.5;
|
|
703
|
+
let worldCenter = ( toWorld * vec4f( center, 1.0 ) ).xyz;
|
|
704
|
+
let worldHalfExtent =
|
|
705
|
+
abs( toWorld[ 0 ].xyz ) * halfExtent.x +
|
|
706
|
+
abs( toWorld[ 1 ].xyz ) * halfExtent.y +
|
|
707
|
+
abs( toWorld[ 2 ].xyz ) * halfExtent.z;
|
|
708
|
+
let worldMin = worldCenter - worldHalfExtent;
|
|
709
|
+
let worldMax = worldCenter + worldHalfExtent;
|
|
710
|
+
|
|
711
|
+
// intersect if the distance to the bounds is not bigger than the already found
|
|
712
|
+
let d = shape - clamp( shape, worldMin, worldMax );
|
|
713
|
+
return select( 0u, 1u, dot( d, d ) < result.distanceSq );
|
|
714
|
+
|
|
715
|
+
}
|
|
716
|
+
`,
|
|
717
|
+
intersectRangeFn: W`
|
|
718
|
+
fn cppIntersectsRange( shape: vec3f, offset: u32, count: u32, result: ptr<function, ${Me}> ) -> bool {
|
|
719
|
+
|
|
720
|
+
var didHit = false;
|
|
721
|
+
let toWorld = ${i};
|
|
722
|
+
|
|
723
|
+
for ( var i = offset; i < offset + count; i ++ ) {
|
|
724
|
+
|
|
725
|
+
// transform the triangle to world space
|
|
726
|
+
let i0 = ${t}[ i * 3u + 0u ];
|
|
727
|
+
let i1 = ${t}[ i * 3u + 1u ];
|
|
728
|
+
let i2 = ${t}[ i * 3u + 2u ];
|
|
729
|
+
let a = ( toWorld * vec4f( ${n}[ i0 ].position.xyz, 1.0 ) ).xyz;
|
|
730
|
+
let b = ( toWorld * vec4f( ${n}[ i1 ].position.xyz, 1.0 ) ).xyz;
|
|
731
|
+
let c = ( toWorld * vec4f( ${n}[ i2 ].position.xyz, 1.0 ) ).xyz;
|
|
732
|
+
|
|
733
|
+
let barycoord = ${et}( shape, a, b, c );
|
|
734
|
+
let closestPoint = barycoord.x * a + barycoord.y * b + barycoord.z * c;
|
|
735
|
+
let delta = shape - closestPoint;
|
|
736
|
+
let distSq = dot( delta, delta );
|
|
737
|
+
|
|
738
|
+
// copy the content over
|
|
739
|
+
if ( ! result.found || distSq < result.distanceSq ) {
|
|
740
|
+
|
|
741
|
+
let normal = normalize( cross( a - b, b - c ) );
|
|
742
|
+
|
|
743
|
+
result.closestPoint = closestPoint;
|
|
744
|
+
result.barycoord = barycoord;
|
|
745
|
+
result.distanceSq = distSq;
|
|
746
|
+
result.faceNormal = normal;
|
|
747
|
+
result.side = sign( dot( normal, delta ) );
|
|
748
|
+
result.faceIndices = vec4u( i0, i1, i2, i );
|
|
749
|
+
result.found = true;
|
|
750
|
+
didHit = true;
|
|
751
|
+
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
return didHit;
|
|
757
|
+
|
|
758
|
+
}
|
|
759
|
+
`,
|
|
760
|
+
transformShapeFn: W`
|
|
761
|
+
fn cppTransformShape( shape: ptr<function, vec3f>, objectIndex: u32 ) -> void {
|
|
762
|
+
|
|
763
|
+
${i} = ${r}[ objectIndex ].matrixWorld;
|
|
764
|
+
|
|
765
|
+
}
|
|
766
|
+
`,
|
|
767
|
+
transformResultFn: W`
|
|
768
|
+
fn cppTransformResult( result: ptr<function, ${Me}>, objectIndex: u32 ) -> void {
|
|
769
|
+
|
|
770
|
+
result.objectIndex = objectIndex;
|
|
771
|
+
|
|
772
|
+
}
|
|
773
|
+
`
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
//#endregion
|
|
777
|
+
//#region ../../node_modules/three-gpu-pathtracer/src/webgpu/lib/three-mesh-bvh/BVHComputeData.js
|
|
778
|
+
var K = /* @__PURE__ */ new T(), ot = /* @__PURE__ */ new T();
|
|
779
|
+
function st(e) {
|
|
780
|
+
let t = e;
|
|
781
|
+
for (; t;) {
|
|
782
|
+
if (t.visible === !1) return !1;
|
|
783
|
+
t = t.parent;
|
|
784
|
+
}
|
|
785
|
+
return !0;
|
|
786
|
+
}
|
|
787
|
+
function ct(e) {
|
|
788
|
+
return e._roots.reduce((e, t) => e + t.byteLength, 0);
|
|
789
|
+
}
|
|
790
|
+
var lt = class {
|
|
791
|
+
constructor(e, t = {}) {
|
|
792
|
+
e = Ie(e);
|
|
793
|
+
let { attributes: n = { position: "vec4f" }, autogenerateBvh: r = !0 } = t;
|
|
794
|
+
this._bvhCache = /* @__PURE__ */ new Map(), this.autogenerateBvh = r, this.attributes = n, this.bvh = e, this.storage = new ut(), this.structs = new ut({ transform: je }), this.fns = new ut({
|
|
795
|
+
raycastFirstHit: rt(this),
|
|
796
|
+
closestPointToPoint: at(this),
|
|
797
|
+
sampleTrianglePoint: null
|
|
798
|
+
}, V);
|
|
799
|
+
}
|
|
800
|
+
getShapecastFn(e) {
|
|
801
|
+
return $e(this, e);
|
|
802
|
+
}
|
|
803
|
+
update() {
|
|
804
|
+
this.dispose();
|
|
805
|
+
let { attributes: e, structs: t, bvh: n } = this, r = [], i = [], a = ct(n), o = 0, s = 0;
|
|
806
|
+
n.primitiveBuffer.forEach((e) => {
|
|
807
|
+
let t = n.getObjectFromId(e), c = n.getInstanceFromId(e), l = {
|
|
808
|
+
start: 0,
|
|
809
|
+
count: 0,
|
|
810
|
+
vertexStart: 0,
|
|
811
|
+
vertexCount: 0
|
|
812
|
+
}, u = this.getBVH(t, c, l);
|
|
813
|
+
if (!u) throw Error("BVHComputeData: BVH not found.");
|
|
814
|
+
if (!r.find((e) => e.bvh === u)) {
|
|
815
|
+
let e = {
|
|
816
|
+
index: r.length,
|
|
817
|
+
bvh: u,
|
|
818
|
+
range: l,
|
|
819
|
+
bvhNodeOffsets: null,
|
|
820
|
+
indexBufferOffset: null
|
|
821
|
+
};
|
|
822
|
+
a += ct(u), o += e.range.count, s += e.range.vertexCount, r.push(e);
|
|
823
|
+
}
|
|
824
|
+
let d = r.find((e) => u === e.bvh);
|
|
825
|
+
u._roots.forEach((n, r) => {
|
|
826
|
+
i.push({
|
|
827
|
+
data: d,
|
|
828
|
+
root: r,
|
|
829
|
+
object: t,
|
|
830
|
+
instanceId: c,
|
|
831
|
+
compositeId: e
|
|
832
|
+
});
|
|
833
|
+
});
|
|
834
|
+
});
|
|
835
|
+
let c = Math.max(i.length, 2);
|
|
836
|
+
o = Math.max(o, 2), s = Math.max(s, 2);
|
|
837
|
+
let l = new D(e, "bvh_GeometryStruct"), u = 0, d = 0, f = 0, p = new Uint32Array(o), m = /* @__PURE__ */ new ArrayBuffer(s * l.getLength() * 4), h = new ArrayBuffer(a);
|
|
838
|
+
Re(n, 0, i, 0, h, !0), f += ct(n) / 32, r.forEach((e) => {
|
|
839
|
+
e.bvhNodeOffsets = Re(e.bvh, d / 3, i, f, h, !1), ze(e.bvh, e.range, u, d, p), Be(e.bvh, e.range, u, m, l, this), e.indexBufferOffset = d, d += e.range.count, u += e.range.vertexCount, f += ct(e.bvh) / 32;
|
|
840
|
+
});
|
|
841
|
+
let g = /* @__PURE__ */ new ArrayBuffer(t.transform.getLength() * c * 4);
|
|
842
|
+
i.forEach((e, t) => {
|
|
843
|
+
ot.copy(n.matrixWorld).invert(), this.writeTransformData(e, ot, t, g);
|
|
844
|
+
});
|
|
845
|
+
let _ = P(new le(new Uint32Array(h), 1), Ae).toReadOnly().setName("bvh_nodes"), v = P(new le(new Uint32Array(g), 1), t.transform).toReadOnly().setName("bvh_transforms"), y = P(new le(p, 1), "uint").toReadOnly().setName("bvh_index"), b = P(new le(new Uint32Array(m), l.getLength()), l).toReadOnly().setName("bvh_attributes");
|
|
846
|
+
this.storage.transforms = v, this.storage.nodes = _, this.storage.index = y, this.storage.attributes = b, this.structs.attributes = l, this.fns.sampleTrianglePoint = it(this), this._bvhCache.clear();
|
|
847
|
+
}
|
|
848
|
+
writeTransformData(e, t, n, r) {
|
|
849
|
+
let { structs: i } = this, a = new Float32Array(r), o = new Uint32Array(r), { object: s, instanceId: c, root: l, data: u } = e, { bvhNodeOffsets: d } = u;
|
|
850
|
+
s.isInstancedMesh || s.isBatchedMesh ? (s.getMatrixAt(c, K), K.premultiply(s.matrixWorld)) : K.copy(s.matrixWorld), K.premultiply(t), K.toArray(a, n * i.transform.getLength()), K.invert(), K.toArray(a, n * i.transform.getLength() + 16), o[n * i.transform.getLength() + 32] = d[l];
|
|
851
|
+
let f = st(s);
|
|
852
|
+
s.isBatchedMesh && (f &&= s.getVisibleAt(c)), o[n * i.transform.getLength() + 33] = f ? 1 : 0;
|
|
853
|
+
}
|
|
854
|
+
getBVH(e, t, n) {
|
|
855
|
+
let { autogenerateBvh: r, _bvhCache: i } = this, a = null;
|
|
856
|
+
if (e.boundsTree || e.isSkinnedMesh) {
|
|
857
|
+
let t = e.geometry;
|
|
858
|
+
if (n.count = t.index ? t.index.count : t.attributes.position.count, n.vertexCount = t.attributes.position.count, a = e.boundsTree || null, a === null && r) {
|
|
859
|
+
let t = e.uuid;
|
|
860
|
+
a = i.get(t) || new ye(e), i.set(t, a);
|
|
861
|
+
}
|
|
862
|
+
} else if (e.isBatchedMesh) {
|
|
863
|
+
let o = e.getGeometryIdAt(t), s = e.getGeometryRangeAt(o);
|
|
864
|
+
if (Object.assign(n, s), a = e.boundsTrees[o] || null, a === null && r) {
|
|
865
|
+
let t = `batched_${e.geometry.uuid}_${s.start}_${s.count}`;
|
|
866
|
+
a = i.get(t) || new ve(e.geometry, { range: { ...n } }), i.set(t, a);
|
|
867
|
+
}
|
|
868
|
+
} else {
|
|
869
|
+
let t = e.geometry;
|
|
870
|
+
if (n.count = t.index ? t.index.count : t.attributes.position.count, n.vertexCount = t.attributes.position.count, a = e.geometry.boundsTree || null, a === null && r) {
|
|
871
|
+
let e = t.uuid;
|
|
872
|
+
a = i.get(e) || new ve(t), i.set(e, a);
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
return a;
|
|
876
|
+
}
|
|
877
|
+
getDefaultAttributeValue(e, t) {
|
|
878
|
+
switch (e) {
|
|
879
|
+
case "position":
|
|
880
|
+
case "color":
|
|
881
|
+
t.set(1, 1, 1, 1);
|
|
882
|
+
break;
|
|
883
|
+
default: t.set(0, 0, 0, 0);
|
|
884
|
+
}
|
|
885
|
+
return t;
|
|
886
|
+
}
|
|
887
|
+
dispose() {
|
|
888
|
+
let { storage: e } = this;
|
|
889
|
+
for (let t in e) e[t].value?.dispose(), delete e[t];
|
|
890
|
+
}
|
|
891
|
+
}, ut = class {
|
|
892
|
+
constructor(e = {}, t = B) {
|
|
893
|
+
let n = {};
|
|
894
|
+
return new Proxy({ ...e }, {
|
|
895
|
+
get(e, r) {
|
|
896
|
+
return n[r] || (n[r] = t(r, e)), n[r];
|
|
897
|
+
},
|
|
898
|
+
set(e, t, n) {
|
|
899
|
+
return e[t] = n, !0;
|
|
900
|
+
}
|
|
901
|
+
});
|
|
902
|
+
}
|
|
903
|
+
}, dt = I("\n fn sampleTexel( tex: texture_2d<f32>, coord: vec2f ) -> vec4f {\n\n // Manual bilinear filtering using textureLoad to support filterable float32 textures\n // on all devices\n let size = vec2f( textureDimensions( tex, 0 ) );\n let pxCoord = coord * size - 0.5;\n let px = vec2i( floor( pxCoord ) );\n let fr = fract( pxCoord );\n\n // get the four sibling samples\n let s00 = textureLoad( tex, clamp( px, vec2i( 0 ), vec2i( size ) - 1 ), 0 );\n let s10 = textureLoad( tex, clamp( px + vec2i( 1, 0 ), vec2i( 0 ), vec2i( size ) - 1 ), 0 );\n let s01 = textureLoad( tex, clamp( px + vec2i( 0, 1 ), vec2i( 0 ), vec2i( size ) - 1 ), 0 );\n let s11 = textureLoad( tex, clamp( px + vec2i( 1, 1 ), vec2i( 0 ), vec2i( size ) - 1 ), 0 );\n\n // interpolate on the x axis\n let y0 = mix( s00, s10, fr.x );\n let y1 = mix( s01, s11, fr.x );\n\n // then y\n return mix( y0, y1, fr.y );\n\n }\n"), ft = class extends me {
|
|
904
|
+
get texture() {
|
|
905
|
+
return this._texNode.value;
|
|
906
|
+
}
|
|
907
|
+
set texture(e) {
|
|
908
|
+
this._texNode.value = e;
|
|
909
|
+
}
|
|
910
|
+
get fromTexture() {
|
|
911
|
+
return this._fromTexNode.value;
|
|
912
|
+
}
|
|
913
|
+
set fromTexture(e) {
|
|
914
|
+
this._fromTexNode.value = e;
|
|
915
|
+
}
|
|
916
|
+
get toneMapping() {
|
|
917
|
+
return this._toneMapping.toneMapping;
|
|
918
|
+
}
|
|
919
|
+
set toneMapping(e) {
|
|
920
|
+
this._toneMapping.setToneMapping(e);
|
|
921
|
+
}
|
|
922
|
+
get transition() {
|
|
923
|
+
return this._transitionUniform.value;
|
|
924
|
+
}
|
|
925
|
+
set transition(e) {
|
|
926
|
+
this._transitionUniform.value = e;
|
|
927
|
+
}
|
|
928
|
+
get exposure() {
|
|
929
|
+
return this._toneMapping.exposureNode.value;
|
|
930
|
+
}
|
|
931
|
+
set exposure(e) {
|
|
932
|
+
this._toneMapping.exposureNode.value = e;
|
|
933
|
+
}
|
|
934
|
+
constructor(e) {
|
|
935
|
+
super();
|
|
936
|
+
let t = F(new O());
|
|
937
|
+
this._texNode = t;
|
|
938
|
+
let n = F(new O());
|
|
939
|
+
this._fromTexNode = n;
|
|
940
|
+
let r = xe(we()), i = A(1);
|
|
941
|
+
this._transitionUniform = i;
|
|
942
|
+
let a = Ce(0, 1, W`
|
|
943
|
+
fn fade( uv: vec2f ) -> vec4f {
|
|
944
|
+
|
|
945
|
+
if ( ${i} <= 0.0 ) {
|
|
946
|
+
|
|
947
|
+
return ${dt}( ${n}, uv );
|
|
948
|
+
|
|
949
|
+
} else if ( ${i} >= 1.0 ) {
|
|
950
|
+
|
|
951
|
+
return ${dt}( ${t}, uv );
|
|
952
|
+
|
|
953
|
+
} else {
|
|
954
|
+
|
|
955
|
+
let col0 = ${dt}( ${n}, uv );
|
|
956
|
+
let col1 = ${dt}( ${t}, uv );
|
|
957
|
+
return mix( col0, col1, ${i} );
|
|
958
|
+
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
}
|
|
962
|
+
`(r));
|
|
963
|
+
this._toneMapping = a, this.transparent = !0, this.colorNode = Te(a.rgb, a.a), this.setValues(e);
|
|
964
|
+
}
|
|
965
|
+
}, q = class {
|
|
966
|
+
get computeNode() {
|
|
967
|
+
return this.kernel.computeNode;
|
|
968
|
+
}
|
|
969
|
+
get workgroupSize() {
|
|
970
|
+
return this.kernel.workgroupSize;
|
|
971
|
+
}
|
|
972
|
+
set needsUpdate(e) {
|
|
973
|
+
this.setWorkgroupSize(...this.workgroupSize);
|
|
974
|
+
}
|
|
975
|
+
constructor(e, t = {}) {
|
|
976
|
+
let { workgroupSize: n = [64] } = t;
|
|
977
|
+
this._fn = e, this.kernel = null, this.setWorkgroupSize(...n);
|
|
978
|
+
}
|
|
979
|
+
defineUniformAccessors(e) {
|
|
980
|
+
for (let t in e) {
|
|
981
|
+
if (t in this) throw Error(`ComputeNode: Uniform name ${t} is already defined.`);
|
|
982
|
+
"value" in e[t] && Object.defineProperty(this, t, {
|
|
983
|
+
get() {
|
|
984
|
+
return e[t].value;
|
|
985
|
+
},
|
|
986
|
+
set(n) {
|
|
987
|
+
e[t].value = n;
|
|
988
|
+
}
|
|
989
|
+
});
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
setWorkgroupSize(e = 64, t = 1, n = 1) {
|
|
993
|
+
return this.kernel = this._fn.computeKernel([
|
|
994
|
+
e,
|
|
995
|
+
t,
|
|
996
|
+
n
|
|
997
|
+
]), this;
|
|
998
|
+
}
|
|
999
|
+
getDispatchSize(e = 1, t = 1, n = 1, r = []) {
|
|
1000
|
+
let [i, a, o] = this.workgroupSize;
|
|
1001
|
+
return r.length = 3, r[0] = Math.ceil(e / i), r[1] = Math.ceil(t / a), r[2] = Math.ceil(n / o), r;
|
|
1002
|
+
}
|
|
1003
|
+
}, pt = Se("\n\n struct PcgState {\n s0: vec4u,\n s1: vec4u,\n };\n\n var<private> g_state: PcgState;\n");
|
|
1004
|
+
I("\n fn pcgInitialize( pixelIndex: u32, pathIndex: u32, bounceIndex: u32 ) -> void {\n let pixel = vec2( ( pixelIndex >> 16 ) & 0xFF, pixelIndex & 0xFF );\n\n //white noise seed\n g_state.s0 = vec4u( pixel | vec2( bounceIndex << 16 ), pathIndex, pixel.x + pixel.y);\n\n //blue noise seed\n g_state.s1 = vec4u(pathIndex, pathIndex*15843, pathIndex*31 + 4566, pathIndex*2345 + 58585);\n\n }\n", [pt]);
|
|
1005
|
+
var mt = I("\n fn pcg4d(v: ptr<private, vec4u>) -> void {\n *v = *v * 1664525u + 1013904223u;\n *v = *v + v.yzxy * v.wxyz;\n *v = *v ^ (*v >> vec4u(16u));\n *v = *v + v.yzxy * v.wxyz;\n }\n");
|
|
1006
|
+
I("\n fn pcgRand( _id: u32 ) -> f32 {\n pcg4d(&g_state.s0);\n return abs( f32( g_state.s0.x ) / f32(0xffffffffu) );\n }\n", [mt, pt]), I("\n fn pcgRand2( _id: u32 ) -> vec2f {\n pcg4d(&g_state.s0);\n return abs( vec2f( g_state.s0.xy ) / f32(0xffffffffu) );\n }\n", [mt, pt]), I("\n fn pcgRand3( _id: u32 ) -> vec3f {\n pcg4d(&g_state.s0);\n return abs( vec3f( g_state.s0.xyz ) / f32(0xffffffffu) );\n }\n", [mt, pt]), I("\n fn pcgRand4( _id: u32 ) -> vec4f {\n pcg4d(&g_state.s0);\n return abs( vec4f( g_state.s0 ) / f32(0xffffffffu) );\n }\n", [mt, pt]), I("fn noop() -> void {}");
|
|
1007
|
+
var ht = De(256 * 256), gt = M(1 / 16777216), _t = Se("\n\n const SOBOL_DIRECTIONS_1 = array<u32, 32>(\n 0x80000000u, 0xc0000000u, 0xa0000000u, 0xf0000000u,\n 0x88000000u, 0xcc000000u, 0xaa000000u, 0xff000000u,\n 0x80800000u, 0xc0c00000u, 0xa0a00000u, 0xf0f00000u,\n 0x88880000u, 0xcccc0000u, 0xaaaa0000u, 0xffff0000u,\n 0x80008000u, 0xc000c000u, 0xa000a000u, 0xf000f000u,\n 0x88008800u, 0xcc00cc00u, 0xaa00aa00u, 0xff00ff00u,\n 0x80808080u, 0xc0c0c0c0u, 0xa0a0a0a0u, 0xf0f0f0f0u,\n 0x88888888u, 0xccccccccu, 0xaaaaaaaau, 0xffffffffu\n );\n\n const SOBOL_DIRECTIONS_2 = array<u32, 32>(\n 0x80000000u, 0xc0000000u, 0x60000000u, 0x90000000u,\n 0xe8000000u, 0x5c000000u, 0x8e000000u, 0xc5000000u,\n 0x68800000u, 0x9cc00000u, 0xee600000u, 0x55900000u,\n 0x80680000u, 0xc09c0000u, 0x60ee0000u, 0x90550000u,\n 0xe8808000u, 0x5cc0c000u, 0x8e606000u, 0xc5909000u,\n 0x6868e800u, 0x9c9c5c00u, 0xeeee8e00u, 0x5555c500u,\n 0x8000e880u, 0xc0005cc0u, 0x60008e60u, 0x9000c590u,\n 0xe8006868u, 0x5c009c9cu, 0x8e00eeeeu, 0xc5005555u\n );\n\n const SOBOL_DIRECTIONS_3 = array<u32, 32>(\n 0x80000000u, 0xc0000000u, 0x20000000u, 0x50000000u,\n 0xf8000000u, 0x74000000u, 0xa2000000u, 0x93000000u,\n 0xd8800000u, 0x25400000u, 0x59e00000u, 0xe6d00000u,\n 0x78080000u, 0xb40c0000u, 0x82020000u, 0xc3050000u,\n 0x208f8000u, 0x51474000u, 0xfbea2000u, 0x75d93000u,\n 0xa0858800u, 0x914e5400u, 0xdbe79e00u, 0x25db6d00u,\n 0x58800080u, 0xe54000c0u, 0x79e00020u, 0xb6d00050u,\n 0x800800f8u, 0xc00c0074u, 0x200200a2u, 0x50050093u\n );\n\n const SOBOL_DIRECTIONS_4 = array<u32, 32>(\n 0x80000000u, 0x40000000u, 0x20000000u, 0xb0000000u,\n 0xf8000000u, 0xdc000000u, 0x7a000000u, 0x9d000000u,\n 0x5a800000u, 0x2fc00000u, 0xa1600000u, 0xf0b00000u,\n 0xda880000u, 0x6fc40000u, 0x81620000u, 0x40bb0000u,\n 0x22878000u, 0xb3c9c000u, 0xfb65a000u, 0xddb2d000u,\n 0x78022800u, 0x9c0b3c00u, 0x5a0fb600u, 0x2d0ddb00u,\n 0xa2878080u, 0xf3c9c040u, 0xdb65a020u, 0x6db2d0b0u,\n 0x800228f8u, 0x400b3cdcu, 0x200fb67au, 0xb00ddb9du\n );\n\n"), vt = De(0).toVar("sobolPixelIndex"), yt = De(0).toVar("sobolPathIndex"), bt = De(0).toVar("sobolBounceIndex"), xt = I("\n\n fn getMaskedSobol( index: u32, directions: array<u32, 32> ) -> u32 {\n\n var X = 0u;\n for ( var bit = 0u; bit < 32u; bit ++ ) {\n\n let mask = ( index >> bit ) & 1u;\n X ^= mask * directions[ bit ];\n\n }\n return X;\n\n }\n\n"), St = (e = 1) => {
|
|
1008
|
+
if (e <= 0) return;
|
|
1009
|
+
let t = e > 1 ? `vec${e}u` : "u32", n = I(`
|
|
1010
|
+
|
|
1011
|
+
fn sobolReverseBits_${t}( in: ${t} ) -> ${t} {
|
|
1012
|
+
|
|
1013
|
+
var x = in;
|
|
1014
|
+
x = ( ( ( x & ${t}( 0xaaaaaaaau ) ) >> ${t}( 1 ) ) | ( ( x & ${t}( 0x55555555u ) ) << ${t}( 1 ) ) );
|
|
1015
|
+
x = ( ( ( x & ${t}( 0xccccccccu ) ) >> ${t}( 2 ) ) | ( ( x & ${t}( 0x33333333u ) ) << ${t}( 2 ) ) );
|
|
1016
|
+
x = ( ( ( x & ${t}( 0xf0f0f0f0u ) ) >> ${t}( 4 ) ) | ( ( x & ${t}( 0x0f0f0f0fu ) ) << ${t}( 4 ) ) );
|
|
1017
|
+
x = ( ( ( x & ${t}( 0xff00ff00u ) ) >> ${t}( 8 ) ) | ( ( x & ${t}( 0x00ff00ffu ) ) << ${t}( 8 ) ) );
|
|
1018
|
+
return ( ( x >> ${t}( 16 ) ) | ( x << ${t}( 16 ) ) );
|
|
1019
|
+
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
`), r = I(`
|
|
1023
|
+
|
|
1024
|
+
fn sobolHashCombine_${t}( seed: u32, v: ${t} ) -> ${t} {
|
|
1025
|
+
|
|
1026
|
+
return ${t}( seed ) ^ ( v + ${t}( ( seed << 6 ) + ( seed >> 2 ) ) );
|
|
1027
|
+
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
`), i = I(`
|
|
1031
|
+
|
|
1032
|
+
fn sobolLaineKarrasPermutation_${t}( in: ${t}, seed: ${t} ) -> ${t} {
|
|
1033
|
+
|
|
1034
|
+
var x = in;
|
|
1035
|
+
x += seed;
|
|
1036
|
+
x ^= x * 0x6c50b47cu;
|
|
1037
|
+
x ^= x * 0xb82f1e52u;
|
|
1038
|
+
x ^= x * 0xc7afe638u;
|
|
1039
|
+
x ^= x * 0x8d22f6e6u;
|
|
1040
|
+
return x;
|
|
1041
|
+
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
`);
|
|
1045
|
+
return {
|
|
1046
|
+
reverseBits: n,
|
|
1047
|
+
hashCombine: r,
|
|
1048
|
+
lkPermutation: i,
|
|
1049
|
+
scramble: W`
|
|
1050
|
+
|
|
1051
|
+
fn nestedUniformScrambleBase2_${t}( x: ${t}, seed: ${t} ) -> ${t} {
|
|
1052
|
+
|
|
1053
|
+
var res = ${i}( x, seed );
|
|
1054
|
+
res = ${n}( res );
|
|
1055
|
+
return res;
|
|
1056
|
+
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
`
|
|
1060
|
+
};
|
|
1061
|
+
}, J = Array.from({ length: 5 }, (e, t) => St(t)), Ct = W`
|
|
1062
|
+
${[_t]}
|
|
1063
|
+
|
|
1064
|
+
fn generateSobolPoint( id: u32 ) -> vec4f {
|
|
1065
|
+
|
|
1066
|
+
var index = id;
|
|
1067
|
+
if ( index >= ${ht} ) {
|
|
1068
|
+
|
|
1069
|
+
index = index % ${ht};
|
|
1070
|
+
// return vec4( 0.0 );
|
|
1071
|
+
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
// NOTE: this sobol "direction" is also available but we can't write out 5 components
|
|
1075
|
+
// uint x = index & 0x00ffffffu;
|
|
1076
|
+
let x = ${J[1].reverseBits}( ${xt}( index, SOBOL_DIRECTIONS_1 ) ) & 0x00ffffffu;
|
|
1077
|
+
let y = ${J[1].reverseBits}( ${xt}( index, SOBOL_DIRECTIONS_2 ) ) & 0x00ffffffu;
|
|
1078
|
+
let z = ${J[1].reverseBits}( ${xt}( index, SOBOL_DIRECTIONS_3 ) ) & 0x00ffffffu;
|
|
1079
|
+
let w = ${J[1].reverseBits}( ${xt}( index, SOBOL_DIRECTIONS_4 ) ) & 0x00ffffffu;
|
|
1080
|
+
|
|
1081
|
+
return vec4( f32( x ), f32( y ), f32( z ), f32( w ) ) * ${gt};
|
|
1082
|
+
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
`, wt = I("\n\n fn sobolHash( in: u32 ) -> u32 {\n\n var x = in;\n // finalizer from murmurhash3\n x ^= x >> 16;\n x *= 0x85ebca6bu;\n x ^= x >> 13;\n x *= 0xc2b2ae35u;\n x ^= x >> 16;\n return x;\n\n }\n\n"), Tt = W`
|
|
1086
|
+
|
|
1087
|
+
fn sobolGetSeed( effect: u32 ) -> u32 {
|
|
1088
|
+
|
|
1089
|
+
return ${wt}(
|
|
1090
|
+
${J[1].hashCombine}(
|
|
1091
|
+
${J[1].hashCombine}(
|
|
1092
|
+
${wt}( ${bt} ),
|
|
1093
|
+
${vt}
|
|
1094
|
+
),
|
|
1095
|
+
effect
|
|
1096
|
+
)
|
|
1097
|
+
);
|
|
1098
|
+
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
`, Et = (e = 1, t = Ct) => {
|
|
1102
|
+
if (e <= 0) return;
|
|
1103
|
+
let n = e > 1 ? `vec${e}u` : "u32", r = e > 1 ? `vec${e}f` : "f32", i = ".r", a = "1u";
|
|
1104
|
+
return e === 2 ? (i = ".rg", a = "vec2( 1u, 2u )") : e === 3 ? (i = ".rgb", a = "vec3( 1u, 2u, 3u )") : e === 4 && (i = "", a = "vec4( 1u, 2u, 3u, 4u )"), W`
|
|
1105
|
+
|
|
1106
|
+
fn sobol${e}( effect: u32 ) -> ${r} {
|
|
1107
|
+
|
|
1108
|
+
let seed = ${Tt}( effect );
|
|
1109
|
+
let index = ${yt};
|
|
1110
|
+
|
|
1111
|
+
let shuffle_seed = ${J[1].hashCombine}( seed, 0u );
|
|
1112
|
+
let shuffled_index = ${J[1].scramble}( ${J[1].reverseBits}( index ), shuffle_seed );
|
|
1113
|
+
let sobol_pt = ${t}( shuffled_index )${i};
|
|
1114
|
+
var result = ${n}( sobol_pt * 16777216.0 );
|
|
1115
|
+
|
|
1116
|
+
let seed2 = ${J[e].hashCombine}( seed, ${a} );
|
|
1117
|
+
result = ${J[e].scramble}( result, seed2 );
|
|
1118
|
+
|
|
1119
|
+
return ${gt} * ${r}( result >> ${n}( 8 ) );
|
|
1120
|
+
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
`;
|
|
1124
|
+
}, Dt = Et(1), Y = Et(2);
|
|
1125
|
+
Et(3), Et(4);
|
|
1126
|
+
var Ot = W`
|
|
1127
|
+
|
|
1128
|
+
fn sobolInit( pixelIndex: u32, pathIndex: u32, bounceIndex: u32 ) -> void {
|
|
1129
|
+
|
|
1130
|
+
${vt} = pixelIndex;
|
|
1131
|
+
${yt} = pathIndex;
|
|
1132
|
+
${bt} = bounceIndex;
|
|
1133
|
+
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
`, kt = W`
|
|
1137
|
+
|
|
1138
|
+
fn sobolNextBounce() -> void {
|
|
1139
|
+
|
|
1140
|
+
${bt}++;
|
|
1141
|
+
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
`, X = Se("\n\n const PI: f32 = 3.141592653589793;\n const EPSILON: f32 = 1e-5;\n const MIN_ROUGHNESS: f32 = 1e-3;\n\n"), At = new D({
|
|
1145
|
+
color: "vec3f",
|
|
1146
|
+
specularPdf: "float",
|
|
1147
|
+
direction: "vec3f",
|
|
1148
|
+
pdf: "float"
|
|
1149
|
+
}, "ScatterRecord"), jt = new D({
|
|
1150
|
+
color: "vec3",
|
|
1151
|
+
map: "int",
|
|
1152
|
+
metalness: "float",
|
|
1153
|
+
metalnessMap: "int",
|
|
1154
|
+
roughness: "float",
|
|
1155
|
+
roughnessMap: "int",
|
|
1156
|
+
ior: "float",
|
|
1157
|
+
transmission: "float",
|
|
1158
|
+
transmissionMap: "int",
|
|
1159
|
+
emissiveIntensity: "float",
|
|
1160
|
+
emissive: "vec3",
|
|
1161
|
+
emissiveMap: "int",
|
|
1162
|
+
normalMap: "int",
|
|
1163
|
+
normalScale: "vec2",
|
|
1164
|
+
clearcoat: "float",
|
|
1165
|
+
clearcoatMap: "int",
|
|
1166
|
+
clearcoatNormalMap: "int",
|
|
1167
|
+
clearcoatNormalScale: "vec2",
|
|
1168
|
+
clearcoatRoughness: "float",
|
|
1169
|
+
clearcoatRoughnessMap: "int",
|
|
1170
|
+
iridescenceMap: "int",
|
|
1171
|
+
iridescenceThicknessMap: "int",
|
|
1172
|
+
iridescence: "float",
|
|
1173
|
+
iridescenceIor: "float",
|
|
1174
|
+
iridescenceThicknessMinimum: "float",
|
|
1175
|
+
iridescenceThicknessMaximum: "float",
|
|
1176
|
+
specularColor: "vec3",
|
|
1177
|
+
specularColorMap: "int",
|
|
1178
|
+
specularIntensity: "float",
|
|
1179
|
+
specularIntensityMap: "int",
|
|
1180
|
+
thinFilm: "int",
|
|
1181
|
+
attenuationColor: "vec3",
|
|
1182
|
+
attenuationDistance: "float",
|
|
1183
|
+
alphaMap: "int",
|
|
1184
|
+
castShadow: "int",
|
|
1185
|
+
opacity: "float",
|
|
1186
|
+
alphaTest: "float",
|
|
1187
|
+
side: "float",
|
|
1188
|
+
matte: "int",
|
|
1189
|
+
sheen: "float",
|
|
1190
|
+
sheenColor: "vec3",
|
|
1191
|
+
sheenColorMap: "int",
|
|
1192
|
+
sheenRoughness: "float",
|
|
1193
|
+
sheenRoughnessMap: "int",
|
|
1194
|
+
vertexColors: "int",
|
|
1195
|
+
flatShading: "int",
|
|
1196
|
+
transparent: "int",
|
|
1197
|
+
fogVolume: "int",
|
|
1198
|
+
mapTransform: "mat3",
|
|
1199
|
+
metalnessMapTransform: "mat3",
|
|
1200
|
+
roughnessMapTransform: "mat3",
|
|
1201
|
+
transmissionMapTransform: "mat3",
|
|
1202
|
+
emissiveMapTransform: "mat3",
|
|
1203
|
+
normalMapTransform: "mat3",
|
|
1204
|
+
clearcoatMapTransform: "mat3",
|
|
1205
|
+
clearcoatNormalMapTransform: "mat3",
|
|
1206
|
+
clearcoatRoughnessMapTransform: "mat3",
|
|
1207
|
+
sheenColorMapTransform: "mat3",
|
|
1208
|
+
sheenRoughnessMapTransform: "mat3",
|
|
1209
|
+
iridescenceMapTransform: "mat3",
|
|
1210
|
+
iridescenceThicknessMapTransform: "mat3",
|
|
1211
|
+
specularColorMapTransform: "mat3",
|
|
1212
|
+
specularIntensityMapTransform: "mat3",
|
|
1213
|
+
alphaMapTransform: "mat3"
|
|
1214
|
+
}, "Material"), Mt = new D({
|
|
1215
|
+
volumeParticle: "bool",
|
|
1216
|
+
faceNormal: "vec3f",
|
|
1217
|
+
frontFace: "bool",
|
|
1218
|
+
normal: "vec3f",
|
|
1219
|
+
normalBasis: "mat3x3f",
|
|
1220
|
+
normalInvBasis: "mat3x3f",
|
|
1221
|
+
eta: "f32",
|
|
1222
|
+
f0: "f32",
|
|
1223
|
+
roughness: "f32",
|
|
1224
|
+
metalness: "f32",
|
|
1225
|
+
color: "vec3f",
|
|
1226
|
+
emission: "vec3f",
|
|
1227
|
+
ior: "f32",
|
|
1228
|
+
transmission: "f32",
|
|
1229
|
+
thinFilm: "bool",
|
|
1230
|
+
attenuationColor: "vec3f",
|
|
1231
|
+
attenuationDistance: " f32",
|
|
1232
|
+
clearcoatNormal: "vec3f",
|
|
1233
|
+
clearcoatBasis: "mat3x3f",
|
|
1234
|
+
clearcoatInvBasis: "mat3x3f",
|
|
1235
|
+
clearcoat: "f32",
|
|
1236
|
+
clearcoatRoughness: "f32",
|
|
1237
|
+
sheen: "f32",
|
|
1238
|
+
sheenColor: "vec3f",
|
|
1239
|
+
sheenRoughness: "f32",
|
|
1240
|
+
iridescence: "f32",
|
|
1241
|
+
iridescenceIor: "f32",
|
|
1242
|
+
iridescenceThickness: "f32",
|
|
1243
|
+
specularColor: "vec3f",
|
|
1244
|
+
specularIntensity: "f32"
|
|
1245
|
+
}, "SurfaceRecord"), Nt = new D({
|
|
1246
|
+
rotation: "mat3x3f",
|
|
1247
|
+
intensity: "float",
|
|
1248
|
+
blur: "float"
|
|
1249
|
+
}, "EnvironmentInfo"), Pt = new D({
|
|
1250
|
+
diffuse: "float",
|
|
1251
|
+
specular: "float",
|
|
1252
|
+
transmission: "float",
|
|
1253
|
+
clearcoat: "float"
|
|
1254
|
+
}, "LobeWeights"), Ft = new D({
|
|
1255
|
+
NdotV: "float",
|
|
1256
|
+
NdotL: "float",
|
|
1257
|
+
NdotH: "float",
|
|
1258
|
+
VdotH: "float",
|
|
1259
|
+
VdotNc: "float",
|
|
1260
|
+
LdotNc: "float",
|
|
1261
|
+
HdotNc: "float"
|
|
1262
|
+
}, "BxDFContext"), It = I("\n\n fn inverse(m: mat3x3f) -> mat3x3f {\n var adj: mat3x3f;\n adj[0][0] = (m[1][1] * m[2][2] - m[2][1] * m[1][2]);\n adj[1][0] = - (m[1][0] * m[2][2] - m[2][0] * m[1][2]);\n adj[2][0] = (m[1][0] * m[2][1] - m[2][0] * m[1][1]);\n adj[0][1] = - (m[0][1] * m[2][2] - m[2][1] * m[0][2]);\n adj[1][1] = (m[0][0] * m[2][2] - m[2][0] * m[0][2]);\n adj[2][1] = - (m[0][0] * m[2][1] - m[2][0] * m[0][1]);\n adj[0][2] = (m[0][1] * m[1][2] - m[1][1] * m[0][2]);\n adj[1][2] = - (m[0][0] * m[1][2] - m[1][0] * m[0][2]);\n adj[2][2] = (m[0][0] * m[1][1] - m[1][0] * m[0][1]);\n\n let det = ( m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1])\n - m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0])\n + m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]));\n\n return adj * ( 1.0 / det );\n }\n\n"), Lt = I("\n\n fn getBasisFromNormal( normal: vec3f ) -> mat3x3f {\n\n var other: vec3f;\n if ( abs( normal.x ) > 0.5 ) {\n\n other = vec3f( 0.0, 1.0, 0.0 );\n\n } else {\n\n other = vec3f( 1.0, 0.0, 0.0 );\n\n }\n\n let ortho = normalize( cross( normal, other ) );\n let ortho2 = normalize( cross( normal, ortho ) );\n return mat3x3f( ortho2, ortho, normal );\n\n }\n\n"), Rt = I("\n\n fn iorToF0( ior: f32 ) -> f32 {\n return pow( ( 1 - ior ) / ( 1 + ior ), 2 );\n }\n\n"), zt = I("\n\n fn iorToF0General( transmittedIor: f32, incidentIor: f32 ) -> f32 {\n\n return pow( ( transmittedIor - incidentIor ) / ( transmittedIor + incidentIor ), 2 );\n\n }\n\n"), Bt = I("\n\n fn iorToF0GeneralVec( transmittedIor: vec3f, incidentIor: vec3f ) -> vec3f {\n\n let v = ( transmittedIor - incidentIor ) / ( transmittedIor + incidentIor );\n return v * v;\n\n }\n\n"), Vt = I("\n\n fn fresnel0ToIor( f0: vec3f ) -> vec3f {\n\n let sqrtF0 = sqrt( f0 );\n return ( vec3( 1.0 ) + sqrtF0 ) / ( vec3( 1.0 ) - sqrtF0 );\n\n }\n\n"), Ht = I("\n\n fn schlickFresnel( cosine: f32, f0: f32 ) -> f32 {\n\n return f0 + ( 1.0 - f0 ) * pow( 1.0 - cosine, 5.0 );\n\n }\n\n"), Ut = I("\n\n fn schlickFresnelVec( cosine: f32, f0: vec3f, f90: vec3f ) -> vec3f {\n\n return f0 + ( f90 - f0 ) * pow( 1.0 - cosine, 5.0 );\n\n }\n\n"), Wt = I("\n\n fn evaluateFresnel( cosine: f32, eta: f32, f0: vec3f, f90: vec3f ) -> vec3f {\n\n if ( totalInternalReflection( cosine, eta ) ) {\n\n return f90;\n\n }\n\n return f0 + ( f90 - f0 ) * pow( 1.0 - cosine, 5.0 );\n }\n\n", [I("\n\n fn totalInternalReflection( cosTheta: f32, eta: f32 ) -> bool {\n\n let sinTheta = sqrt( 1.0 - cosTheta * cosTheta );\n return eta * sinTheta > 1.0;\n\n }\n\n")]), Gt = I("\n\n fn isTerminatingScatter( scatterRec: ScatterRecord ) -> bool {\n return scatterRec.pdf <= 0;\n }\n\n", [At]), Kt = I("\n\n fn applyWrap( v: f32, wrapMode: i32 ) -> f32 {\n\n var res = v;\n if ( wrapMode == 1 ) {\n\n // ClampToEdge\n res = clamp( res, 0.0, 1.0 );\n\n } else if ( wrapMode == 2 ) {\n\n // MirroredRepeat\n res = 1.0 - abs( 2.0 * fract( res * 0.5 ) - 1.0 );\n\n } else {\n\n // Repeat\n res = fract( res );\n\n }\n\n return res;\n\n }\n\n"), qt = (e, t, n) => W`
|
|
1263
|
+
|
|
1264
|
+
fn sampleTexel( uv: vec2f, packed: i32, lod: f32 ) -> vec4f {
|
|
1265
|
+
|
|
1266
|
+
let wrapS = ( packed >> 24 ) & 0x3;
|
|
1267
|
+
let wrapT = ( packed >> 26 ) & 0x3;
|
|
1268
|
+
let nearest = ( packed >> 28 ) & 0x1;
|
|
1269
|
+
let texIndex = packed & 0xFFFFFF;
|
|
1270
|
+
|
|
1271
|
+
// look up the texture's rect and page within the atlas. three wraps a
|
|
1272
|
+
// uniformArray in a struct ( textureInfoStruct ) with a "value" array member.
|
|
1273
|
+
let info = ${e}[ u32( texIndex ) ];
|
|
1274
|
+
let offset = vec2f( vec2u( info.x & 0xFFFFu, info.x >> 16u ) );
|
|
1275
|
+
let size = vec2f( vec2u( info.y & 0xFFFFu, info.y >> 16u ) );
|
|
1276
|
+
let page = i32( info.z & 0xFFFFu );
|
|
1277
|
+
|
|
1278
|
+
// wrap is applied on the logical uv first, then remapped into the tile
|
|
1279
|
+
let wrappedUv = vec2f(
|
|
1280
|
+
${Kt}( uv.x, wrapS ),
|
|
1281
|
+
${Kt}( uv.y, wrapT ),
|
|
1282
|
+
);
|
|
1283
|
+
|
|
1284
|
+
let pageDim = vec2f( textureDimensions( ${t}, 0 ).xy );
|
|
1285
|
+
|
|
1286
|
+
if ( nearest == 1 ) {
|
|
1287
|
+
|
|
1288
|
+
let tileTexel = clamp( vec2i( wrappedUv * size ), vec2i( 0 ), vec2i( size ) - vec2i( 1 ) );
|
|
1289
|
+
return textureLoad( ${t}, vec2i( offset ) + tileTexel, page, 0 );
|
|
1290
|
+
|
|
1291
|
+
} else {
|
|
1292
|
+
|
|
1293
|
+
var atlasUv = ( offset + wrappedUv * size ) / pageDim;
|
|
1294
|
+
|
|
1295
|
+
// clamp to half a texel inside the tile so bilinear taps never bleed into
|
|
1296
|
+
// neighboring atlas tiles
|
|
1297
|
+
let minUv = ( offset + vec2f( 0.5 ) ) / pageDim;
|
|
1298
|
+
let maxUv = ( offset + size - vec2f( 0.5 ) ) / pageDim;
|
|
1299
|
+
atlasUv = clamp( atlasUv, minUv, maxUv );
|
|
1300
|
+
|
|
1301
|
+
return textureSampleLevel( ${t}, ${n}, atlasUv, page, lod );
|
|
1302
|
+
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
}
|
|
1306
|
+
`, Jt = I("\n\n fn diffuseDirection( wo: vec3f, uv: vec2f ) -> vec3f {\n\n var lightDirection = sampleSphere( uv );\n lightDirection.z += 1.0;\n lightDirection = normalize( lightDirection );\n\n return lightDirection;\n\n }\n\n", [I("\n\n fn sampleSphere( uv: vec2f ) -> vec3f {\n\n let u = ( uv.x - 0.5 ) * 2.0;\n let t = uv.y * PI * 2.0;\n let f = sqrt( 1.0 - u * u );\n\n return vec3f( f * cos( t ), f * sin( t ), u );\n\n }\n\n", [X])]), Yt = I("\n\n fn getLobeWeights(wo: vec3f, woClearcoat: vec3f, wh: vec3f, clearcoatIor: f32, surf: SurfaceRecord) -> LobeWeights {\n\n // TODO: experiment with this; I don't see any usage of normal?\n let metalness = surf.metalness;\n let transmission = surf.transmission;\n let HdotL = dot( wh, wo );\n let fEstimate = evaluateFresnel( HdotL, surf.eta, vec3f( surf.f0 ), vec3f( 1.0 ) ).x;\n\n let transSpecularProb = mix( max( 0.25, fEstimate ), 1.0, metalness );\n let diffSpecularProb = 0.5 + 0.5 * metalness;\n\n var weights: LobeWeights;\n weights.diffuse = ( 1.0 - transmission ) * ( 1.0 - diffSpecularProb );\n weights.specular = transmission * transSpecularProb + ( 1.0 - transmission ) * diffSpecularProb;\n\n let clearcoatF0 = iorToF0( clearcoatIor );\n let clearcoatFresnel = schlickFresnel( saturate( woClearcoat.z ), clearcoatF0 );\n weights.clearcoat = surf.clearcoat * clearcoatFresnel;\n\n weights.transmission = transmission * ( 1.0 - transSpecularProb );\n\n let totalWeight = weights.diffuse + weights.specular;\n if ( totalWeight > 0 ) {\n weights.diffuse = ( weights.diffuse / totalWeight ) * ( 1 - weights.clearcoat );\n weights.specular = ( weights.specular / totalWeight ) * ( 1 - weights.clearcoat );\n }\n // weights.transmission /= totalWeight;\n\n return weights;\n\n }\n\n", [
|
|
1307
|
+
Ht,
|
|
1308
|
+
Rt,
|
|
1309
|
+
Wt,
|
|
1310
|
+
Pt,
|
|
1311
|
+
X
|
|
1312
|
+
]), Xt = I("\n\n fn sampleEnvironment(\n envMap: texture_2d<f32>,\n envMapSampler: sampler,\n env: EnvironmentInfo,\n direction: vec3f,\n uv: vec2f,\n ) -> vec4f {\n\n let offsetDir = sampleHemisphere( direction, uv ) * 0.5 * env.blur;\n let sampleDir = normalize( env.rotation * direction + offsetDir );\n let col = sampleEquirectColor( envMap, envMapSampler, sampleDir );\n\n return vec4f( env.intensity * col.rgb, col.a );\n\n }\n\n", [
|
|
1313
|
+
I("\n\n fn sampleEquirectColor( envMap: texture_2d<f32>, envMapSampler: sampler, direction: vec3f ) -> vec4f {\n\n return textureSampleLevel( envMap, envMapSampler, equirectDirectionToUv( direction ), 0 );\n\n }\n\n", [I("\n\n fn equirectDirectionToUv(direction: vec3f) -> vec2f {\n\n // from Spherical.setFromCartesianCoords\n var uv = vec2f( atan2( direction.z, direction.x ), acos( direction.y ) );\n uv /= vec2f( 2.0 * PI, PI );\n\n // apply adjustments to get values in range [0, 1] and y right side up\n uv.x += 0.5;\n uv.y = 1.0 - uv.y;\n return uv;\n\n }\n\n")]),
|
|
1314
|
+
I("\n\n fn sampleHemisphere( n: vec3f, uv: vec2f ) -> vec3f {\n\n // https://www.rorydriscoll.com/2009/01/07/better-sampling/\n // https://graphics.pixar.com/library/OrthonormalB/paper.pdf\n let sign = select( sign( n.z ), 1.0, n.z == 0.0 );\n let a = - 1.0 / ( sign + n.z );\n let b = n.x * n.y * a;\n let b1 = vec3( 1.0 + sign * n.x * n.x * a, sign * b, - sign * n.x );\n let b2 = vec3( b, sign + n.y * n.y * a, - n.y );\n\n let r = sqrt( uv.x );\n let theta = 2.0 * PI * uv.y;\n let x = r * cos( theta );\n let y = r * sin( theta );\n return x * b1 + y * b2 + sqrt( 1.0 - uv.x ) * n;\n\n }\n\n", [X]),
|
|
1315
|
+
Nt
|
|
1316
|
+
]), Zt = I("\n\n fn weightedAlphaBlend( prevColor: vec4f, newColor: vec4f, weight: f32 ) -> vec4f {\n\n let invWeight = 1.0 - weight;\n let totalAlpha = prevColor.a * invWeight + newColor.a * weight;\n var blendedColor = vec4f( 0 );\n if ( totalAlpha != 0.0 ) {\n\n let prevContrib = prevColor.rgb * invWeight * prevColor.a / totalAlpha;\n let resContrib = newColor.rgb * weight * newColor.a / totalAlpha;\n blendedColor = vec4f( prevContrib + resContrib, totalAlpha );\n\n }\n\n return blendedColor;\n\n }\n\n"), Qt = class extends q {
|
|
1317
|
+
constructor() {
|
|
1318
|
+
let e = {
|
|
1319
|
+
bvhData: { value: null },
|
|
1320
|
+
material: { value: null },
|
|
1321
|
+
prevOutputTarget: j(new O(1, 1)).toReadOnly(),
|
|
1322
|
+
outputTarget: j(new O(1, 1)).toWriteOnly(),
|
|
1323
|
+
sampleCountTarget: j(new O(1, 1)).toReadWrite(),
|
|
1324
|
+
offset: A(new l()),
|
|
1325
|
+
tileSize: A(new l()),
|
|
1326
|
+
seed: A(0),
|
|
1327
|
+
bounces: A(5),
|
|
1328
|
+
inverseProjectionMatrix: A(new T()),
|
|
1329
|
+
cameraToModelMatrix: A(new T()),
|
|
1330
|
+
envMap: F(new f()),
|
|
1331
|
+
envMapSampler: L(new f()),
|
|
1332
|
+
envMapRotation: A(new te()),
|
|
1333
|
+
envMapIntensity: A(1),
|
|
1334
|
+
background: F(new f()),
|
|
1335
|
+
backgroundSampler: L(new f()),
|
|
1336
|
+
backgroundRotation: A(new te()),
|
|
1337
|
+
backgroundIntensity: A(1),
|
|
1338
|
+
backgroundBlurriness: A(0),
|
|
1339
|
+
textures: F(new f()),
|
|
1340
|
+
textureSampler: L(new f()),
|
|
1341
|
+
globalId: N
|
|
1342
|
+
}, t = B("bvhData.value.fns.raycastFirstHit.outputType", e), n = V("bvhData.value.fns.raycastFirstHit", e), r = V("bvhData.value.fns.sampleTrianglePoint", e), i = V("bvhData.value.fns.getSurfaceRecord", e), a = V("material.value.bsdfSample", e), o = W`
|
|
1343
|
+
|
|
1344
|
+
fn compute(
|
|
1345
|
+
|
|
1346
|
+
// indices and target
|
|
1347
|
+
globalId: vec3u,
|
|
1348
|
+
|
|
1349
|
+
// tiles
|
|
1350
|
+
offset: vec2u,
|
|
1351
|
+
tileSize: vec2u,
|
|
1352
|
+
|
|
1353
|
+
// settings
|
|
1354
|
+
inverseProjectionMatrix: mat4x4f,
|
|
1355
|
+
cameraToModelMatrix: mat4x4f,
|
|
1356
|
+
seed: u32,
|
|
1357
|
+
bounces: u32,
|
|
1358
|
+
|
|
1359
|
+
// environment
|
|
1360
|
+
envMap: texture_2d<f32>,
|
|
1361
|
+
envMapSampler: sampler,
|
|
1362
|
+
envMapRotation: mat3x3f,
|
|
1363
|
+
envMapIntensity: f32,
|
|
1364
|
+
|
|
1365
|
+
background: texture_2d<f32>,
|
|
1366
|
+
backgroundSampler: sampler,
|
|
1367
|
+
backgroundRotation: mat3x3f,
|
|
1368
|
+
backgroundIntensity: f32,
|
|
1369
|
+
backgroundBlurriness: f32,
|
|
1370
|
+
|
|
1371
|
+
) -> void {
|
|
1372
|
+
|
|
1373
|
+
let transforms = &${B("bvhData.value.storage.transforms", e)};
|
|
1374
|
+
let materials = &${B("bvhData.value.storage.materials", e)};
|
|
1375
|
+
|
|
1376
|
+
let envInfo = EnvironmentInfo(
|
|
1377
|
+
envMapRotation,
|
|
1378
|
+
envMapIntensity,
|
|
1379
|
+
0.0 // blur,
|
|
1380
|
+
);
|
|
1381
|
+
|
|
1382
|
+
let backgroundInfo = EnvironmentInfo(
|
|
1383
|
+
backgroundRotation,
|
|
1384
|
+
backgroundIntensity,
|
|
1385
|
+
backgroundBlurriness,
|
|
1386
|
+
);
|
|
1387
|
+
|
|
1388
|
+
// make sure we don't bleed over the edge of our tile
|
|
1389
|
+
if ( globalId.x >= tileSize.x || globalId.y >= tileSize.y ) {
|
|
1390
|
+
|
|
1391
|
+
return;
|
|
1392
|
+
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
// to screen coordinates
|
|
1396
|
+
let indexUV = offset + globalId.xy;
|
|
1397
|
+
let targetDimensions = textureDimensions( ${e.outputTarget} );
|
|
1398
|
+
if ( indexUV.x >= targetDimensions.x || indexUV.y >= targetDimensions.y ) {
|
|
1399
|
+
|
|
1400
|
+
return;
|
|
1401
|
+
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
let uv = vec2f( indexUV ) / vec2f( targetDimensions );
|
|
1405
|
+
let ndc = uv * 2.0 - vec2f( 1.0 );
|
|
1406
|
+
|
|
1407
|
+
let pixelIndex = ( indexUV.x << 16 ) | indexUV.y;
|
|
1408
|
+
${Ot}( pixelIndex, seed, 0 );
|
|
1409
|
+
|
|
1410
|
+
// scene ray
|
|
1411
|
+
var jitter = 2.0 * ${Y}( ${0} ) / vec2f( targetDimensions.xy );
|
|
1412
|
+
var ray = ${nt}( ndc + jitter, cameraToModelMatrix * inverseProjectionMatrix );
|
|
1413
|
+
ray.direction = normalize( ray.direction );
|
|
1414
|
+
|
|
1415
|
+
var resultColor = vec4f( 0, 0, 0, 1 );
|
|
1416
|
+
var throughputColor = vec3f( 1.0 );
|
|
1417
|
+
|
|
1418
|
+
for ( var bounce = 0u; bounce < bounces; bounce ++ ) {
|
|
1419
|
+
|
|
1420
|
+
var hitResult: ${t};
|
|
1421
|
+
if ( ${n}( ray, &hitResult ) ) {
|
|
1422
|
+
|
|
1423
|
+
let object = transforms[ hitResult.objectIndex ];
|
|
1424
|
+
var material = materials[ object.materialIndex ];
|
|
1425
|
+
|
|
1426
|
+
// apply per-object colors
|
|
1427
|
+
material.color *= object.color.rgb;
|
|
1428
|
+
material.opacity *= object.color.a;
|
|
1429
|
+
|
|
1430
|
+
var vertexData = ${r}( hitResult.barycoord, hitResult.indices.xyz );
|
|
1431
|
+
vertexData.normal = normalize( transpose( object.inverseMatrixWorld ) * vertexData.normal );
|
|
1432
|
+
vertexData.position = object.matrixWorld * vertexData.position;
|
|
1433
|
+
|
|
1434
|
+
let surface = ${i}( material, vertexData, hitResult.side, hitResult.normal );
|
|
1435
|
+
|
|
1436
|
+
resultColor += vec4f( throughputColor * surface.emission, 0.0 );
|
|
1437
|
+
|
|
1438
|
+
let scatterRec = ${a}( - ray.direction, surface );
|
|
1439
|
+
|
|
1440
|
+
if ( ${Gt}( scatterRec ) ) {
|
|
1441
|
+
|
|
1442
|
+
break;
|
|
1443
|
+
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1446
|
+
throughputColor *= scatterRec.color;
|
|
1447
|
+
throughputColor /= scatterRec.pdf;
|
|
1448
|
+
|
|
1449
|
+
// TODO: Investigate offsetting this position to not self-intersect multiple times
|
|
1450
|
+
// Adding + scatterRec.direction * 1e-1 seems to fix almost all the fireflies
|
|
1451
|
+
// However that seems like a very large distance to offset
|
|
1452
|
+
ray.origin = vertexData.position.xyz;
|
|
1453
|
+
ray.direction = scatterRec.direction;
|
|
1454
|
+
|
|
1455
|
+
} else {
|
|
1456
|
+
|
|
1457
|
+
let rng = ${Y}( ${1} );
|
|
1458
|
+
if ( bounce > 0u ) {
|
|
1459
|
+
|
|
1460
|
+
resultColor += ${Xt}( envMap, envMapSampler, envInfo, ray.direction, rng ) * vec4f( throughputColor, 0.0 );
|
|
1461
|
+
|
|
1462
|
+
} else {
|
|
1463
|
+
|
|
1464
|
+
resultColor = ${Xt}( background, backgroundSampler, backgroundInfo, ray.direction, rng );
|
|
1465
|
+
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
break;
|
|
1469
|
+
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
${kt}();
|
|
1473
|
+
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
let sampleCount = textureLoad( ${e.sampleCountTarget}, indexUV ).r + 1;
|
|
1477
|
+
let prevColor = textureLoad( ${e.prevOutputTarget}, indexUV );
|
|
1478
|
+
let blendedColor = ${Zt}( prevColor, resultColor, 1.0 / f32( sampleCount ) );
|
|
1479
|
+
textureStore( ${e.sampleCountTarget}, indexUV, vec4( sampleCount ) );
|
|
1480
|
+
textureStore( ${e.outputTarget}, indexUV, blendedColor );
|
|
1481
|
+
|
|
1482
|
+
}`;
|
|
1483
|
+
super(o(e)), this.defineUniformAccessors(e);
|
|
1484
|
+
}
|
|
1485
|
+
};
|
|
1486
|
+
//#endregion
|
|
1487
|
+
//#region ../../node_modules/three-gpu-pathtracer/src/utils/TextureUtils.js
|
|
1488
|
+
function $t(e) {
|
|
1489
|
+
let t = new Uint16Array(e.length);
|
|
1490
|
+
for (let n = 0, r = e.length; n < r; ++n) t[n] = u.toHalfFloat(e[n]);
|
|
1491
|
+
return t;
|
|
1492
|
+
}
|
|
1493
|
+
//#endregion
|
|
1494
|
+
//#region ../../node_modules/three-gpu-pathtracer/src/uniforms/EquirectHdrInfoUniform.js
|
|
1495
|
+
function en(e, t, n = 0, r = e.length) {
|
|
1496
|
+
let i = n, a = n + r - 1;
|
|
1497
|
+
for (; i < a;) {
|
|
1498
|
+
let n = i + a >> 1;
|
|
1499
|
+
e[n] < t ? i = n + 1 : a = n;
|
|
1500
|
+
}
|
|
1501
|
+
return i - n;
|
|
1502
|
+
}
|
|
1503
|
+
function tn(e, t, n) {
|
|
1504
|
+
return .2126 * e + .7152 * t + .0722 * n;
|
|
1505
|
+
}
|
|
1506
|
+
function nn(e, t = b) {
|
|
1507
|
+
let n = e.clone();
|
|
1508
|
+
n.source = new h({ ...n.image });
|
|
1509
|
+
let { width: r, height: i, data: a } = n.image, o = a;
|
|
1510
|
+
if (n.type !== t) {
|
|
1511
|
+
o = t === 1016 ? new Uint16Array(a.length) : new Float32Array(a.length);
|
|
1512
|
+
let e;
|
|
1513
|
+
e = a instanceof Int8Array || a instanceof Int16Array || a instanceof Int32Array ? 2 ** (8 * a.BYTES_PER_ELEMENT - 1) - 1 : 2 ** (8 * a.BYTES_PER_ELEMENT) - 1;
|
|
1514
|
+
for (let r = 0, i = a.length; r < i; r++) {
|
|
1515
|
+
let i = a[r];
|
|
1516
|
+
n.type === 1016 && (i = u.fromHalfFloat(a[r])), n.type !== 1015 && n.type !== 1016 && (i /= e), t === 1016 && (o[r] = u.toHalfFloat(i));
|
|
1517
|
+
}
|
|
1518
|
+
n.image.data = o, n.type = t;
|
|
1519
|
+
}
|
|
1520
|
+
if (n.flipY) {
|
|
1521
|
+
let e = o;
|
|
1522
|
+
o = o.slice();
|
|
1523
|
+
for (let t = 0; t < i; t++) for (let n = 0; n < r; n++) {
|
|
1524
|
+
let a = i - t - 1, s = 4 * (t * r + n), c = 4 * (a * r + n);
|
|
1525
|
+
o[c + 0] = e[s + 0], o[c + 1] = e[s + 1], o[c + 2] = e[s + 2], o[c + 3] = e[s + 3];
|
|
1526
|
+
}
|
|
1527
|
+
n.flipY = !1, n.image.data = o;
|
|
1528
|
+
}
|
|
1529
|
+
return n;
|
|
1530
|
+
}
|
|
1531
|
+
var rn = class {
|
|
1532
|
+
constructor() {
|
|
1533
|
+
let e = new f($t(new Float32Array([
|
|
1534
|
+
0,
|
|
1535
|
+
0,
|
|
1536
|
+
0,
|
|
1537
|
+
0
|
|
1538
|
+
])), 1, 1);
|
|
1539
|
+
e.type = b, e.format = i, e.minFilter = w, e.magFilter = w, e.wrapS = o, e.wrapT = o, e.generateMipmaps = !1, e.needsUpdate = !0;
|
|
1540
|
+
let t = new f($t(new Float32Array([0, 1])), 1, 2);
|
|
1541
|
+
t.type = b, t.format = S, t.minFilter = w, t.magFilter = w, t.generateMipmaps = !1, t.needsUpdate = !0;
|
|
1542
|
+
let n = new f($t(new Float32Array([
|
|
1543
|
+
0,
|
|
1544
|
+
0,
|
|
1545
|
+
1,
|
|
1546
|
+
1
|
|
1547
|
+
])), 2, 2);
|
|
1548
|
+
n.type = b, n.format = S, n.minFilter = w, n.magFilter = w, n.generateMipmaps = !1, n.needsUpdate = !0, this.map = e, this.marginalWeights = t, this.conditionalWeights = n, this.totalSum = 0;
|
|
1549
|
+
}
|
|
1550
|
+
dispose() {
|
|
1551
|
+
this.marginalWeights.dispose(), this.conditionalWeights.dispose(), this.map.dispose();
|
|
1552
|
+
}
|
|
1553
|
+
updateFrom(e) {
|
|
1554
|
+
let t = nn(e);
|
|
1555
|
+
t.wrapS = o, t.wrapT = c;
|
|
1556
|
+
let { width: n, height: r, data: i } = t.image, a = new Float32Array(n * r), s = new Float32Array(n * r), l = new Float32Array(r), d = new Float32Array(r), f = 0, p = 0;
|
|
1557
|
+
for (let e = 0; e < r; e++) {
|
|
1558
|
+
let t = 0;
|
|
1559
|
+
for (let r = 0; r < n; r++) {
|
|
1560
|
+
let o = e * n + r, c = tn(u.fromHalfFloat(i[4 * o + 0]), u.fromHalfFloat(i[4 * o + 1]), u.fromHalfFloat(i[4 * o + 2]));
|
|
1561
|
+
t += c, f += c, a[o] = c, s[o] = t;
|
|
1562
|
+
}
|
|
1563
|
+
if (t !== 0) for (let r = e * n, i = e * n + n; r < i; r++) a[r] /= t, s[r] /= t;
|
|
1564
|
+
p += t, l[e] = t, d[e] = p;
|
|
1565
|
+
}
|
|
1566
|
+
if (p !== 0) for (let e = 0, t = l.length; e < t; e++) l[e] /= p, d[e] /= p;
|
|
1567
|
+
let m = new Uint16Array(r), h = new Uint16Array(n * r);
|
|
1568
|
+
for (let e = 0; e < r; e++) {
|
|
1569
|
+
let t = en(d, (e + 1) / r);
|
|
1570
|
+
m[e] = u.toHalfFloat((t + .5) / r);
|
|
1571
|
+
}
|
|
1572
|
+
for (let e = 0; e < r; e++) for (let t = 0; t < n; t++) {
|
|
1573
|
+
let r = e * n + t, i = en(s, (t + 1) / n, e * n, n);
|
|
1574
|
+
h[r] = u.toHalfFloat((i + .5) / n);
|
|
1575
|
+
}
|
|
1576
|
+
this.dispose();
|
|
1577
|
+
let { marginalWeights: g, conditionalWeights: _ } = this;
|
|
1578
|
+
g.image = {
|
|
1579
|
+
width: r,
|
|
1580
|
+
height: 1,
|
|
1581
|
+
data: m
|
|
1582
|
+
}, g.needsUpdate = !0, _.image = {
|
|
1583
|
+
width: n,
|
|
1584
|
+
height: r,
|
|
1585
|
+
data: h
|
|
1586
|
+
}, _.needsUpdate = !0, this.totalSum = f, this.map = t;
|
|
1587
|
+
}
|
|
1588
|
+
}, an = class extends q {
|
|
1589
|
+
constructor() {
|
|
1590
|
+
let e = {
|
|
1591
|
+
globalId: N,
|
|
1592
|
+
outputTarget: j(new O(1, 1)).toWriteOnly()
|
|
1593
|
+
}, t = W`
|
|
1594
|
+
fn compute( globalId: vec3u ) -> void {
|
|
1595
|
+
|
|
1596
|
+
textureStore( ${e.outputTarget}, globalId.xy, vec4( 0, 0, 0, 1 ) );
|
|
1597
|
+
|
|
1598
|
+
}
|
|
1599
|
+
`;
|
|
1600
|
+
super(t(e)), this.defineUniformAccessors({ target: e.outputTarget });
|
|
1601
|
+
}
|
|
1602
|
+
}, on = class {
|
|
1603
|
+
constructor(t) {
|
|
1604
|
+
this.renderer = t, this.camera = null, this.samples = 0, this.bounces = 7, this.lowResMode = !1, this._renderTask = null, this.outputTarget = new O(1, 1), this.outputTarget.format = i, this.outputTarget.type = v, this.outputTarget.colorSpace = r.workingColorSpace, this.outputTarget.name = "Output #0", this.outputTarget.generateMipmaps = !1, this.prevOutputTarget = new O(1, 1), this.prevOutputTarget.format = i, this.prevOutputTarget.type = v, this.prevOutputTarget.colorSpace = r.workingColorSpace, this.prevOutputTarget.name = "Output #1", this.prevOutputTarget.generateMipmaps = !1, this.sampleCountTarget = new O(1, 1), this.sampleCountTarget.format = e, this.sampleCountTarget.type = re, this.sampleCountTarget.name = "Sample Count", this.sampleCountTarget.generateMipmaps = !1, this.sampleCountClearKernel = new an().setWorkgroupSize(8, 8, 1), this.outputTargetClearKernel = new an().setWorkgroupSize(8, 8, 1);
|
|
1605
|
+
}
|
|
1606
|
+
setCamera(e) {
|
|
1607
|
+
this.camera = e, this.reset();
|
|
1608
|
+
}
|
|
1609
|
+
setBVHData(e) {}
|
|
1610
|
+
setTextures(e) {}
|
|
1611
|
+
setMaterial(e) {}
|
|
1612
|
+
setEnvironment(e, t, n, r, i, a, o) {}
|
|
1613
|
+
setSize(e, t) {
|
|
1614
|
+
e = Math.ceil(e), t = Math.ceil(t);
|
|
1615
|
+
let { width: n, height: r } = this.outputTarget;
|
|
1616
|
+
return n === e && r === t ? !1 : (this.outputTarget.dispose(), this.prevOutputTarget.dispose(), this.sampleCountTarget.dispose(), this.outputTarget = this.outputTarget.clone(), this.prevOutputTarget = this.outputTarget.clone(), this.sampleCountTarget = this.sampleCountTarget.clone(), this.outputTarget.setSize(e, t), this.prevOutputTarget.setSize(e, t), this.sampleCountTarget.setSize(e, t), this.reset(), !0);
|
|
1617
|
+
}
|
|
1618
|
+
getSize(e) {
|
|
1619
|
+
let { width: t, height: n } = this.outputTarget;
|
|
1620
|
+
return e.x = t, e.y = n, e;
|
|
1621
|
+
}
|
|
1622
|
+
update() {
|
|
1623
|
+
let { camera: e, renderer: t } = this;
|
|
1624
|
+
!e || !t.initialized || (this._renderTask ||= this.createRenderTask(), this._renderTask.next());
|
|
1625
|
+
}
|
|
1626
|
+
*createRenderTask() {}
|
|
1627
|
+
reset() {
|
|
1628
|
+
let { renderer: e, outputTargetClearKernel: t, sampleCountClearKernel: n, outputTarget: r, prevOutputTarget: i, sampleCountTarget: a } = this;
|
|
1629
|
+
if (!e.initialized) return;
|
|
1630
|
+
let { width: o, height: s } = r, c = t.getDispatchSize(o, s);
|
|
1631
|
+
t.target = r, e.compute(t.kernel, c), t.target = i, e.compute(t.kernel, c), n.target = a, e.compute(n.kernel, c), this.samples = 0, this._renderTask = null;
|
|
1632
|
+
}
|
|
1633
|
+
dispose() {
|
|
1634
|
+
this.outputTarget.dispose(), this.prevOutputTarget.dispose(), this.sampleCountTarget.dispose(), this._renderTask = null;
|
|
1635
|
+
}
|
|
1636
|
+
}, sn = class extends on {
|
|
1637
|
+
constructor(e) {
|
|
1638
|
+
super(e), this.tiles = new l(2, 2), this.envInfo = new rn(), this.samples = 0, this.kernel = new Qt().setWorkgroupSize(8, 8, 1);
|
|
1639
|
+
}
|
|
1640
|
+
setBVHData(e) {
|
|
1641
|
+
this.kernel.bvhData = e, this.kernel.needsUpdate = !0, this.reset();
|
|
1642
|
+
}
|
|
1643
|
+
setMaterial(e) {
|
|
1644
|
+
this.kernel.material = e.getData(), this.kernel.needsUpdate = !0, this.reset();
|
|
1645
|
+
}
|
|
1646
|
+
setEnvironment(e, t, n, r, i, a, o) {
|
|
1647
|
+
let { kernel: s } = this;
|
|
1648
|
+
s.background.isTexture && s.background.dispose(), e !== null && (this.envInfo.updateFrom(e), s.envMap = this.envInfo.map, s.kernel.computeNode.parameters.envMapSampler.node.value = this.envInfo.map);
|
|
1649
|
+
let c = new T().makeRotationFromEuler(n).invert();
|
|
1650
|
+
s.envMapRotation.setFromMatrix4(c), s.envMapIntensity = t, s.background = r, s.kernel.computeNode.parameters.backgroundSampler.node.value = r, c.makeRotationFromEuler(a).invert(), s.backgroundRotation.setFromMatrix4(c), s.backgroundIntensity = i, s.backgroundBlurriness = o;
|
|
1651
|
+
}
|
|
1652
|
+
setTiles(e) {
|
|
1653
|
+
this.tiles.copy(e);
|
|
1654
|
+
}
|
|
1655
|
+
*createRenderTask() {
|
|
1656
|
+
let { renderer: e, camera: t, kernel: n, bounces: r, tiles: i, outputTarget: a, sampleCountTarget: o, lowResMode: s } = this;
|
|
1657
|
+
for (t.updateMatrixWorld(), n.outputTarget = a, n.sampleCountTarget = o, n.bounces = r, n.inverseProjectionMatrix.copy(t.projectionMatrixInverse), n.cameraToModelMatrix.copy(t.matrixWorld);;) {
|
|
1658
|
+
let t = n.tileSize;
|
|
1659
|
+
s ? this.getSize(t) : this.getSize(t).divide(i).ceil();
|
|
1660
|
+
let r = n.getDispatchSize(t.x, t.y);
|
|
1661
|
+
n.seed += 1, e.copyTextureToTexture(this.outputTarget, this.prevOutputTarget), [this.outputTarget, this.prevOutputTarget] = [this.prevOutputTarget, this.outputTarget], n.prevOutputTarget = this.prevOutputTarget, n.outputTarget = this.outputTarget;
|
|
1662
|
+
for (let a = 0; a < i.x; a++) for (let o = 0; o < i.y; o++) n.offset.set(a, o).multiply(t), e.compute(n.kernel, r), yield;
|
|
1663
|
+
this.samples++;
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
dispose() {
|
|
1667
|
+
super.dispose(), this.envInfo.dispose();
|
|
1668
|
+
}
|
|
1669
|
+
}, Z = new D({
|
|
1670
|
+
origin: "vec3f",
|
|
1671
|
+
seed: "uint",
|
|
1672
|
+
direction: "vec3f",
|
|
1673
|
+
_alignment0: "uint",
|
|
1674
|
+
throughputColor: "vec3f",
|
|
1675
|
+
currentBounce: "uint",
|
|
1676
|
+
pixel: "vec2u",
|
|
1677
|
+
resultColor: "vec4f"
|
|
1678
|
+
}, "QueuedRay"), Q = new D({
|
|
1679
|
+
indices: "vec3u",
|
|
1680
|
+
seed: "uint",
|
|
1681
|
+
barycoord: "vec2f",
|
|
1682
|
+
pixel_x: "uint",
|
|
1683
|
+
pixel_y: "uint",
|
|
1684
|
+
view: "vec3f",
|
|
1685
|
+
currentBounce: "uint",
|
|
1686
|
+
throughputColor: "vec3f",
|
|
1687
|
+
objectIndex: "uint",
|
|
1688
|
+
normal: "vec3f",
|
|
1689
|
+
side: "float",
|
|
1690
|
+
resultColor: "vec4f"
|
|
1691
|
+
}, "QueuedHit"), cn = class extends q {
|
|
1692
|
+
constructor() {
|
|
1693
|
+
let e = {
|
|
1694
|
+
rayWorkGroupSize: A(new t()),
|
|
1695
|
+
tileSize: A(new l()),
|
|
1696
|
+
tileCount: A(new l()),
|
|
1697
|
+
tileOffset: A(1),
|
|
1698
|
+
rayQueue: P(new k(1, Z.getLength()), Z).toReadOnly(),
|
|
1699
|
+
queueSizes: P(new k(4, 1), "u32"),
|
|
1700
|
+
outputTileIndex: P(new k(2, 1), "u32").setName("outputTileIndex"),
|
|
1701
|
+
outputDispatch: P(new k(3, 1), "u32").setName("outputDispatch")
|
|
1702
|
+
}, n = W`
|
|
1703
|
+
fn compute(
|
|
1704
|
+
rayWorkGroupSize: vec3u,
|
|
1705
|
+
|
|
1706
|
+
tileSize: vec2u,
|
|
1707
|
+
tileCount: vec2u,
|
|
1708
|
+
tileOffset: u32,
|
|
1709
|
+
) -> void {
|
|
1710
|
+
|
|
1711
|
+
let rayQueue = &${e.rayQueue};
|
|
1712
|
+
let queueSizes = &${e.queueSizes};
|
|
1713
|
+
|
|
1714
|
+
let outputTileIndex = &${e.outputTileIndex};
|
|
1715
|
+
let outputDispatch = &${e.outputDispatch};
|
|
1716
|
+
|
|
1717
|
+
// reset hit queue size from previous iteration
|
|
1718
|
+
queueSizes[ 2 ] = 0u;
|
|
1719
|
+
queueSizes[ 3 ] = 0u;
|
|
1720
|
+
|
|
1721
|
+
// keep the queue index small
|
|
1722
|
+
let queueCapacity = arrayLength( rayQueue );
|
|
1723
|
+
if ( queueSizes[ 0 ] >= queueCapacity ) {
|
|
1724
|
+
|
|
1725
|
+
// uint division results in a floored value
|
|
1726
|
+
let offset = queueSizes[ 0 ] / queueCapacity;
|
|
1727
|
+
queueSizes[ 0 ] = queueSizes[ 0 ] - queueCapacity * offset;
|
|
1728
|
+
queueSizes[ 1 ] = queueSizes[ 1 ] - queueCapacity * offset;
|
|
1729
|
+
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
// calculate the amount of elements in the queue
|
|
1733
|
+
var queueSize = queueSizes[ 1 ] - queueSizes[ 0 ];
|
|
1734
|
+
|
|
1735
|
+
// calculate the overhead of space in the queue and how much space we need to run a new tile
|
|
1736
|
+
let overhead = queueCapacity - queueSize;
|
|
1737
|
+
let requiredSpace = tileSize.x * tileSize.y;
|
|
1738
|
+
|
|
1739
|
+
if ( overhead >= requiredSpace ) {
|
|
1740
|
+
|
|
1741
|
+
// calculate the necessary dispatch size to cover the tile
|
|
1742
|
+
outputDispatch[ 0 ] = u32( ceil( f32( tileSize.x ) / f32( rayWorkGroupSize.x ) ) );
|
|
1743
|
+
outputDispatch[ 1 ] = u32( ceil( f32( tileSize.y ) / f32( rayWorkGroupSize.y ) ) );
|
|
1744
|
+
outputDispatch[ 2 ] = 1;
|
|
1745
|
+
|
|
1746
|
+
// calculate the tile index to generate rays for
|
|
1747
|
+
let totalTiles = tileCount.x * tileCount.y;
|
|
1748
|
+
let currentIndex = outputTileIndex[ 1 ] * tileCount.x + outputTileIndex[ 0 ];
|
|
1749
|
+
let nextIndex = ( currentIndex + tileOffset ) % totalTiles;
|
|
1750
|
+
|
|
1751
|
+
outputTileIndex[ 0 ] = nextIndex % tileCount.x;
|
|
1752
|
+
outputTileIndex[ 1 ] = nextIndex / tileCount.x;
|
|
1753
|
+
|
|
1754
|
+
} else {
|
|
1755
|
+
|
|
1756
|
+
outputDispatch[ 0 ] = 0;
|
|
1757
|
+
outputDispatch[ 1 ] = 0;
|
|
1758
|
+
outputDispatch[ 2 ] = 0;
|
|
1759
|
+
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
}
|
|
1763
|
+
`;
|
|
1764
|
+
super(n(e)), this.defineUniformAccessors(e);
|
|
1765
|
+
}
|
|
1766
|
+
}, ln = class extends q {
|
|
1767
|
+
constructor() {
|
|
1768
|
+
let e = {
|
|
1769
|
+
cameraToModelMatrix: A(new T()),
|
|
1770
|
+
inverseProjectionMatrix: A(new T()),
|
|
1771
|
+
seed: A(0),
|
|
1772
|
+
tileIndexBuffer: P(new k(2, 1), "u32"),
|
|
1773
|
+
tileSize: A(new l()),
|
|
1774
|
+
rayQueue: P(new k(1, Z.getLength()), Z),
|
|
1775
|
+
queueSizes: P(new k(4, 1), "u32").toAtomic(),
|
|
1776
|
+
sampleCountTarget: j(new O()).toReadWrite(),
|
|
1777
|
+
globalId: N
|
|
1778
|
+
}, t = W`
|
|
1779
|
+
fn compute(
|
|
1780
|
+
cameraToModelMatrix: mat4x4f,
|
|
1781
|
+
inverseProjectionMatrix: mat4x4f,
|
|
1782
|
+
|
|
1783
|
+
seed: u32,
|
|
1784
|
+
tileSize: vec2u,
|
|
1785
|
+
|
|
1786
|
+
globalId: vec3u
|
|
1787
|
+
) -> void {
|
|
1788
|
+
|
|
1789
|
+
let rayQueue = &${e.rayQueue};
|
|
1790
|
+
let queueSizes = &${e.queueSizes};
|
|
1791
|
+
let tileIndexBuffer = &${e.tileIndexBuffer};
|
|
1792
|
+
|
|
1793
|
+
// don't overstep the edge of the tile
|
|
1794
|
+
if ( globalId.x >= tileSize.x || globalId.y >= tileSize.y ) {
|
|
1795
|
+
|
|
1796
|
+
return;
|
|
1797
|
+
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
// calculate the pixel index and ensure we are not generating rays outside the texture bounds
|
|
1801
|
+
let offset = vec2( tileIndexBuffer[ 0 ] * tileSize.x, tileIndexBuffer[ 1 ] * tileSize.y );
|
|
1802
|
+
let indexUV = offset + globalId.xy;
|
|
1803
|
+
let targetDimensions = textureDimensions( ${e.sampleCountTarget} );
|
|
1804
|
+
if ( indexUV.x >= targetDimensions.x || indexUV.y >= targetDimensions.y ) {
|
|
1805
|
+
|
|
1806
|
+
return;
|
|
1807
|
+
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1810
|
+
// calculate the screen uv
|
|
1811
|
+
let uv = vec2f( indexUV ) / vec2f( targetDimensions );
|
|
1812
|
+
let ndc = uv * 2.0 - vec2f( 1.0 );
|
|
1813
|
+
|
|
1814
|
+
// check whether ray is already active (added on the queue) and skip it if it is
|
|
1815
|
+
let ACTIVE_FLAG = 0xF0000000u;
|
|
1816
|
+
let combinedField = textureLoad( ${e.sampleCountTarget}, indexUV ).r;
|
|
1817
|
+
let isActive = ( ACTIVE_FLAG & combinedField ) != 0;
|
|
1818
|
+
let samples = ( ( ~ ACTIVE_FLAG ) & combinedField );
|
|
1819
|
+
|
|
1820
|
+
if ( isActive ) {
|
|
1821
|
+
|
|
1822
|
+
return;
|
|
1823
|
+
|
|
1824
|
+
}
|
|
1825
|
+
|
|
1826
|
+
// get the ray index
|
|
1827
|
+
let queueCapacity = arrayLength( rayQueue );
|
|
1828
|
+
let index = atomicAdd( &queueSizes[ 1 ], 1 ) % queueCapacity;
|
|
1829
|
+
|
|
1830
|
+
let pixelIndex = ( indexUV.x << 16 ) | indexUV.y;
|
|
1831
|
+
${Ot}( pixelIndex, seed, 0 );
|
|
1832
|
+
|
|
1833
|
+
// write the ray data
|
|
1834
|
+
var jitter = 2.0 * ${Y}( ${0} ) / vec2f( targetDimensions.xy );
|
|
1835
|
+
var ray = ${nt}( ndc + jitter, cameraToModelMatrix * inverseProjectionMatrix );
|
|
1836
|
+
ray.direction = normalize( ray.direction );
|
|
1837
|
+
|
|
1838
|
+
rayQueue[ index ].origin = ray.origin;
|
|
1839
|
+
rayQueue[ index ].direction = ray.direction;
|
|
1840
|
+
rayQueue[ index ].pixel = indexUV;
|
|
1841
|
+
rayQueue[ index ].throughputColor = vec3f( 1.0 );
|
|
1842
|
+
rayQueue[ index ].currentBounce = 0;
|
|
1843
|
+
rayQueue[ index ].resultColor = vec4f( 0.0, 0.0, 0.0, 1.0 );
|
|
1844
|
+
rayQueue[ index ].seed = seed;
|
|
1845
|
+
|
|
1846
|
+
// write the active params
|
|
1847
|
+
textureStore( ${e.sampleCountTarget}, indexUV, vec4( ACTIVE_FLAG | samples ) );
|
|
1848
|
+
|
|
1849
|
+
}
|
|
1850
|
+
`;
|
|
1851
|
+
super(t(e)), this.defineUniformAccessors(e);
|
|
1852
|
+
}
|
|
1853
|
+
}, un = class extends q {
|
|
1854
|
+
constructor() {
|
|
1855
|
+
let e = {
|
|
1856
|
+
bvhData: { value: null },
|
|
1857
|
+
prevOutputTarget: j(new O(1, 1)).toReadOnly(),
|
|
1858
|
+
outputTarget: j(new O(1, 1)).toWriteOnly(),
|
|
1859
|
+
sampleCountTarget: j(new O(1, 1)).toReadWrite(),
|
|
1860
|
+
rayQueue: P(new k(1, Z.getLength()), Z).toReadOnly(),
|
|
1861
|
+
hitQueue: P(new k(1, Q.getLength()), Q),
|
|
1862
|
+
queueSizes: P(new k(4, 1), "u32").toAtomic(),
|
|
1863
|
+
envMap: F(new f()),
|
|
1864
|
+
envMapSampler: L(new f()),
|
|
1865
|
+
envMapRotation: A(new te()),
|
|
1866
|
+
envMapIntensity: A(1),
|
|
1867
|
+
background: F(new f()),
|
|
1868
|
+
backgroundSampler: L(new f()),
|
|
1869
|
+
backgroundRotation: A(new te()),
|
|
1870
|
+
backgroundIntensity: A(1),
|
|
1871
|
+
backgroundBlurriness: A(0),
|
|
1872
|
+
globalId: N
|
|
1873
|
+
}, t = B("bvhData.value.fns.raycastFirstHit.outputType", e), n = B("bvhData.value.fns.raycastFirstHit", e), r = W`
|
|
1874
|
+
|
|
1875
|
+
fn compute(
|
|
1876
|
+
// environment
|
|
1877
|
+
envMap: texture_2d<f32>,
|
|
1878
|
+
envMapSampler: sampler,
|
|
1879
|
+
envMapRotation: mat3x3f,
|
|
1880
|
+
envMapIntensity: f32,
|
|
1881
|
+
|
|
1882
|
+
background: texture_2d<f32>,
|
|
1883
|
+
backgroundSampler: sampler,
|
|
1884
|
+
backgroundRotation: mat3x3f,
|
|
1885
|
+
backgroundIntensity: f32,
|
|
1886
|
+
backgroundBlurriness: f32,
|
|
1887
|
+
|
|
1888
|
+
globalId: vec3u
|
|
1889
|
+
) -> void {
|
|
1890
|
+
|
|
1891
|
+
let rayQueue = &${e.rayQueue};
|
|
1892
|
+
let hitQueue = &${e.hitQueue};
|
|
1893
|
+
let queueSizes = &${e.queueSizes};
|
|
1894
|
+
|
|
1895
|
+
let envInfo = EnvironmentInfo(
|
|
1896
|
+
envMapRotation,
|
|
1897
|
+
envMapIntensity,
|
|
1898
|
+
0.0 // blur,
|
|
1899
|
+
);
|
|
1900
|
+
|
|
1901
|
+
let backgroundInfo = EnvironmentInfo(
|
|
1902
|
+
backgroundRotation,
|
|
1903
|
+
backgroundIntensity,
|
|
1904
|
+
backgroundBlurriness,
|
|
1905
|
+
);
|
|
1906
|
+
|
|
1907
|
+
// skip any rays invocations beyond the ray count
|
|
1908
|
+
let queueCapacity = arrayLength( rayQueue );
|
|
1909
|
+
let rayIndex = ( globalId.x + atomicLoad( &queueSizes[ 0 ] ) );
|
|
1910
|
+
if ( rayIndex >= atomicLoad( &queueSizes[ 1 ] ) ) {
|
|
1911
|
+
|
|
1912
|
+
return;
|
|
1913
|
+
|
|
1914
|
+
}
|
|
1915
|
+
|
|
1916
|
+
// get the ray info
|
|
1917
|
+
let ACTIVE_FLAG = 0xF0000000u;
|
|
1918
|
+
let input = rayQueue[ rayIndex % queueCapacity ];
|
|
1919
|
+
let indexUV = input.pixel;
|
|
1920
|
+
|
|
1921
|
+
let pixelIndex = ( indexUV.x << 16 ) | indexUV.y;
|
|
1922
|
+
${Ot}( pixelIndex, input.seed, input.currentBounce );
|
|
1923
|
+
|
|
1924
|
+
// run intersection
|
|
1925
|
+
let ray = Ray( input.origin, input.direction );
|
|
1926
|
+
var hitResult: ${t};
|
|
1927
|
+
if ( ${n}( ray, &hitResult ) ) {
|
|
1928
|
+
|
|
1929
|
+
// TODO: we process all of these materials immediately to push to the ray queue
|
|
1930
|
+
let index = atomicAdd( &queueSizes[ 3 ], 1 );
|
|
1931
|
+
hitQueue[ index ].view = - input.direction;
|
|
1932
|
+
hitQueue[ index ].indices = hitResult.indices.xyz;
|
|
1933
|
+
hitQueue[ index ].barycoord = hitResult.barycoord.xy;
|
|
1934
|
+
hitQueue[ index ].normal = hitResult.normal.xyz;
|
|
1935
|
+
hitQueue[ index ].side = hitResult.side;
|
|
1936
|
+
hitQueue[ index ].pixel_x = indexUV.x;
|
|
1937
|
+
hitQueue[ index ].pixel_y = indexUV.y;
|
|
1938
|
+
hitQueue[ index ].objectIndex = hitResult.objectIndex;
|
|
1939
|
+
hitQueue[ index ].throughputColor = input.throughputColor;
|
|
1940
|
+
hitQueue[ index ].currentBounce = input.currentBounce;
|
|
1941
|
+
hitQueue[ index ].resultColor = input.resultColor;
|
|
1942
|
+
hitQueue[ index ].seed = input.seed;
|
|
1943
|
+
|
|
1944
|
+
} else {
|
|
1945
|
+
|
|
1946
|
+
let rng = ${Y}( ${1} );
|
|
1947
|
+
var resultColor = input.resultColor;
|
|
1948
|
+
if ( input.currentBounce > 0u ) {
|
|
1949
|
+
|
|
1950
|
+
resultColor += ${Xt}( envMap, envMapSampler, envInfo, input.direction, rng ) * vec4f( input.throughputColor, 0.0 );
|
|
1951
|
+
|
|
1952
|
+
} else {
|
|
1953
|
+
|
|
1954
|
+
resultColor = ${Xt}( background, backgroundSampler, backgroundInfo, input.direction, rng );
|
|
1955
|
+
|
|
1956
|
+
}
|
|
1957
|
+
|
|
1958
|
+
let sampleCount = ( textureLoad( ${e.sampleCountTarget}, indexUV ).r & ( ~ ACTIVE_FLAG ) ) + 1;
|
|
1959
|
+
let prevColor = textureLoad( ${e.prevOutputTarget}, indexUV );
|
|
1960
|
+
let blendedColor = ${Zt}( prevColor, resultColor, 1.0 / f32( sampleCount ) );
|
|
1961
|
+
textureStore( ${e.sampleCountTarget}, indexUV, vec4( sampleCount ) );
|
|
1962
|
+
textureStore( ${e.outputTarget}, indexUV, blendedColor );
|
|
1963
|
+
|
|
1964
|
+
}
|
|
1965
|
+
|
|
1966
|
+
}
|
|
1967
|
+
`;
|
|
1968
|
+
super(r(e)), this.defineUniformAccessors(e);
|
|
1969
|
+
}
|
|
1970
|
+
}, dn = class extends q {
|
|
1971
|
+
constructor() {
|
|
1972
|
+
let e = {
|
|
1973
|
+
processed: A(0),
|
|
1974
|
+
queueSizes: P(new k(4, 1), "u32")
|
|
1975
|
+
}, t = W`
|
|
1976
|
+
fn compute( processed: u32 ) -> void {
|
|
1977
|
+
|
|
1978
|
+
let queueSizes = &${e.queueSizes};
|
|
1979
|
+
var queueSize = queueSizes[ 1 ] - queueSizes[ 0 ];
|
|
1980
|
+
if ( processed > queueSize ) {
|
|
1981
|
+
|
|
1982
|
+
queueSizes[ 0 ] = queueSizes[ 1 ];
|
|
1983
|
+
|
|
1984
|
+
} else {
|
|
1985
|
+
|
|
1986
|
+
queueSizes[ 0 ] = queueSizes[ 0 ] + processed;
|
|
1987
|
+
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1990
|
+
}
|
|
1991
|
+
`;
|
|
1992
|
+
super(t(e)), this.defineUniformAccessors(e);
|
|
1993
|
+
}
|
|
1994
|
+
}, fn = class extends q {
|
|
1995
|
+
constructor(e = {}) {
|
|
1996
|
+
let { type: t = "u32" } = e, n = {
|
|
1997
|
+
globalId: N,
|
|
1998
|
+
outputTarget: P(new k(1, 1), t)
|
|
1999
|
+
}, r = W`
|
|
2000
|
+
fn compute( globalId: vec3u ) -> void {
|
|
2001
|
+
|
|
2002
|
+
${n.outputTarget}[ globalId.x ] = 0;
|
|
2003
|
+
|
|
2004
|
+
}
|
|
2005
|
+
`;
|
|
2006
|
+
super(r(n)), this.defineUniformAccessors({ target: n.outputTarget });
|
|
2007
|
+
}
|
|
2008
|
+
}, pn = class extends q {
|
|
2009
|
+
constructor() {
|
|
2010
|
+
let e = {
|
|
2011
|
+
bvhData: { value: null },
|
|
2012
|
+
material: { value: null },
|
|
2013
|
+
prevOutputTarget: j(new O(1, 1)).toReadOnly(),
|
|
2014
|
+
outputTarget: j(new O(1, 1)).toWriteOnly(),
|
|
2015
|
+
sampleCountTarget: j(new O(1, 1)).toReadWrite(),
|
|
2016
|
+
smoothNormals: A(1),
|
|
2017
|
+
bounces: A(1),
|
|
2018
|
+
rayQueue: P(new k(1, Z.getLength()), Z),
|
|
2019
|
+
hitQueue: P(new k(1, Q.getLength()), Q),
|
|
2020
|
+
queueSizes: P(new k(4, 1), "u32").toAtomic(),
|
|
2021
|
+
textures: F(new f()),
|
|
2022
|
+
textureSampler: L(new f()),
|
|
2023
|
+
globalId: N
|
|
2024
|
+
}, t = V("bvhData.value.fns.sampleTrianglePoint", e), n = V("bvhData.value.fns.getSurfaceRecord", e), r = V("material.value.bsdfSample", e), i = W`
|
|
2025
|
+
|
|
2026
|
+
fn compute(
|
|
2027
|
+
// settings
|
|
2028
|
+
smoothNormals: u32,
|
|
2029
|
+
bounces: u32,
|
|
2030
|
+
|
|
2031
|
+
globalId: vec3u
|
|
2032
|
+
) -> void {
|
|
2033
|
+
|
|
2034
|
+
let rayQueue = &${e.rayQueue};
|
|
2035
|
+
let hitQueue = &${e.hitQueue};
|
|
2036
|
+
let queueSizes = &${e.queueSizes};
|
|
2037
|
+
|
|
2038
|
+
let materials = &${B("bvhData.value.storage.materials", e)};
|
|
2039
|
+
let transforms = &${B("bvhData.value.storage.transforms", e)};
|
|
2040
|
+
|
|
2041
|
+
// skip any rays invocations beyond the ray count
|
|
2042
|
+
let hitQueueCapacity = arrayLength( hitQueue );
|
|
2043
|
+
let hitIndex = ( globalId.x + atomicLoad( &queueSizes[ 2 ] ) );
|
|
2044
|
+
if ( hitIndex >= atomicLoad( &queueSizes[ 3 ] ) ) {
|
|
2045
|
+
|
|
2046
|
+
return;
|
|
2047
|
+
|
|
2048
|
+
}
|
|
2049
|
+
|
|
2050
|
+
// get the ray info
|
|
2051
|
+
let ACTIVE_FLAG = 0xF0000000u;
|
|
2052
|
+
let input = hitQueue[ hitIndex ];
|
|
2053
|
+
let indexUV = vec2u( input.pixel_x, input.pixel_y );
|
|
2054
|
+
|
|
2055
|
+
let pixelIndex = ( indexUV.x << 16 ) | indexUV.y;
|
|
2056
|
+
${Ot}( pixelIndex, input.seed, input.currentBounce );
|
|
2057
|
+
|
|
2058
|
+
let object = transforms[ input.objectIndex ];
|
|
2059
|
+
var material = materials[ object.materialIndex ];
|
|
2060
|
+
|
|
2061
|
+
// apply per-object colors
|
|
2062
|
+
material.color *= object.color.rgb;
|
|
2063
|
+
material.opacity *= object.color.a;
|
|
2064
|
+
|
|
2065
|
+
let barycoord = vec3( input.barycoord, 1.0 - input.barycoord.x - input.barycoord.y );
|
|
2066
|
+
var vertexData = ${t}( barycoord, input.indices.xyz );
|
|
2067
|
+
vertexData.normal = normalize( transpose( object.inverseMatrixWorld ) * vertexData.normal );
|
|
2068
|
+
vertexData.position = object.matrixWorld * vertexData.position;
|
|
2069
|
+
|
|
2070
|
+
let surface = ${n}( material, vertexData, input.side, input.normal );
|
|
2071
|
+
|
|
2072
|
+
let scatterRec = ${r}( input.view, surface );
|
|
2073
|
+
|
|
2074
|
+
let resultColor = input.resultColor + vec4f( input.throughputColor * surface.emission, 0.0 );
|
|
2075
|
+
|
|
2076
|
+
let isTerminated = input.currentBounce >= bounces || ${Gt}( scatterRec );
|
|
2077
|
+
|
|
2078
|
+
if ( isTerminated ) {
|
|
2079
|
+
|
|
2080
|
+
// terminate ray, write color
|
|
2081
|
+
let sampleCount = ( textureLoad( ${e.sampleCountTarget}, indexUV ).r & ( ~ ACTIVE_FLAG ) ) + 1;
|
|
2082
|
+
let prevColor = textureLoad( ${e.prevOutputTarget}, indexUV );
|
|
2083
|
+
let blendedColor = ${Zt}( prevColor, resultColor, 1.0 / f32( sampleCount ) );
|
|
2084
|
+
textureStore( ${e.sampleCountTarget}, indexUV, vec4( sampleCount ) );
|
|
2085
|
+
textureStore( ${e.outputTarget}, indexUV, blendedColor );
|
|
2086
|
+
|
|
2087
|
+
} else {
|
|
2088
|
+
|
|
2089
|
+
let rayQueueCapacity = arrayLength( rayQueue );
|
|
2090
|
+
let index = atomicAdd( &queueSizes[ 1 ], 1 ) % rayQueueCapacity;
|
|
2091
|
+
rayQueue[ index ].origin = vertexData.position.xyz;
|
|
2092
|
+
rayQueue[ index ].direction = scatterRec.direction;
|
|
2093
|
+
rayQueue[ index ].pixel = indexUV;
|
|
2094
|
+
rayQueue[ index ].throughputColor = input.throughputColor * scatterRec.color / scatterRec.pdf;
|
|
2095
|
+
rayQueue[ index ].currentBounce = input.currentBounce + 1;
|
|
2096
|
+
rayQueue[ index ].resultColor = resultColor;
|
|
2097
|
+
rayQueue[ index ].seed = input.seed;
|
|
2098
|
+
|
|
2099
|
+
}
|
|
2100
|
+
|
|
2101
|
+
}`;
|
|
2102
|
+
super(i(e)), this.defineUniformAccessors(e);
|
|
2103
|
+
}
|
|
2104
|
+
}, mn = 25e4, hn = 134217728, gn = Math.floor(hn / (Z.getLength() * 4)), _n = Math.floor(hn / (Q.getLength() * 4)), vn = class extends on {
|
|
2105
|
+
constructor(e) {
|
|
2106
|
+
super(e), this.tiles = new l(3, 3), this.envInfo = new rn(), this.rayQueue = new k(gn, Z.getLength()), this.rayQueue.name = "Ray Queue", this.hitQueue = new k(_n, Q.getLength()), this.hitQueue.name = "Hit Queue", this.queueSizes = new k(4, 1), this.queueSizes.name = "Queue Sizes", this.tileIndexBuffer = new k(2, 1), this.rayGenerationDispatch = new k(3, 1), this.hitProcessDispatch = new k(3, 1), this.primeRayGenerationDispatchKernel = new cn().setWorkgroupSize(1, 1, 1), this.enqueueRaysKernel = new ln().setWorkgroupSize(8, 8, 1), this.rayIntersectionKernel = new un().setWorkgroupSize(64, 1, 1), this.updateRayQueueParamsKernel = new dn().setWorkgroupSize(1, 1, 1), this.hitProcessKernel = new pn().setWorkgroupSize(64, 1, 1), this.zeroDispatchKernel = new fn().setWorkgroupSize(1, 1, 1), this.volumeKernel = null, this.lightConnectionKernel = null;
|
|
2107
|
+
}
|
|
2108
|
+
setBVHData(e) {
|
|
2109
|
+
this.rayIntersectionKernel.bvhData = e, this.rayIntersectionKernel.needsUpdate = !0, this.hitProcessKernel.bvhData = e, this.hitProcessKernel.needsUpdate = !0, this.reset();
|
|
2110
|
+
}
|
|
2111
|
+
setMaterial(e) {
|
|
2112
|
+
this.hitProcessKernel.material = e.getData(), this.hitProcessKernel.needsUpdate = !0, this.reset();
|
|
2113
|
+
}
|
|
2114
|
+
setEnvironment(e, t, n, r, i, a, o) {
|
|
2115
|
+
let s = this.rayIntersectionKernel;
|
|
2116
|
+
s.background.isTexture && s.background.dispose(), e !== null && (this.envInfo.updateFrom(e), s.envMap = this.envInfo.map, s.kernel.computeNode.parameters.envMapSampler.node.value = this.envInfo.map);
|
|
2117
|
+
let c = new T().makeRotationFromEuler(n).invert();
|
|
2118
|
+
s.envMapRotation.setFromMatrix4(c), s.envMapIntensity = t, s.background = r, s.kernel.computeNode.parameters.backgroundSampler.node.value = r, c.makeRotationFromEuler(a).invert(), s.backgroundRotation.setFromMatrix4(c), s.backgroundIntensity = i, s.backgroundBlurriness = o;
|
|
2119
|
+
}
|
|
2120
|
+
setTiles(e) {
|
|
2121
|
+
this.tiles.copy(e);
|
|
2122
|
+
}
|
|
2123
|
+
getTileSize(e) {
|
|
2124
|
+
return this.getSize(e).divide(this.tiles).ceil(), e;
|
|
2125
|
+
}
|
|
2126
|
+
dispose() {
|
|
2127
|
+
super.dispose(), this.envInfo.dispose();
|
|
2128
|
+
}
|
|
2129
|
+
reset() {
|
|
2130
|
+
let { renderer: e, sampleCountClearKernel: t, zeroDispatchKernel: n, sampleCountTarget: r, hitProcessDispatch: i, rayGenerationDispatch: a, queueSizes: o, tileIndexBuffer: s } = this;
|
|
2131
|
+
if (!e.initialized) return;
|
|
2132
|
+
super.reset(), this.enqueueRaysKernel.seed = 0;
|
|
2133
|
+
let { width: c, height: l } = r, u = t.getDispatchSize(c, l);
|
|
2134
|
+
t.target = r, e.compute(t.kernel, u), n.target = o, e.compute(n.kernel, [o.count]), n.target = i, e.compute(n.kernel, [i.count]), n.target = a, e.compute(n.kernel, [a.count]), n.target = s, e.compute(n.kernel, [s.count]);
|
|
2135
|
+
}
|
|
2136
|
+
*createRenderTask() {
|
|
2137
|
+
let { renderer: e, camera: t, bounces: n, tiles: r, sampleCountTarget: i, rayQueue: a, hitQueue: o, queueSizes: s, rayGenerationDispatch: c, tileIndexBuffer: u, primeRayGenerationDispatchKernel: d, enqueueRaysKernel: f, rayIntersectionKernel: p, updateRayQueueParamsKernel: m, hitProcessKernel: h, lowResMode: g } = this;
|
|
2138
|
+
t.updateMatrixWorld(), d.tileOffset = 0;
|
|
2139
|
+
let _ = new l(), v = mn / (i.width * i.height * n), y = g ? 5 : 1, b = 0;
|
|
2140
|
+
for (;;) {
|
|
2141
|
+
for (let l = 0; l < y; l++) {
|
|
2142
|
+
this.getTileSize(_), e.copyTextureToTexture(this.outputTarget, this.prevOutputTarget), [this.outputTarget, this.prevOutputTarget] = [this.prevOutputTarget, this.outputTarget], p.prevOutputTarget = this.prevOutputTarget, p.outputTarget = this.outputTarget, h.prevOutputTarget = this.prevOutputTarget, h.outputTarget = this.outputTarget, d.rayWorkGroupSize.set(8, 8, 1), d.tileCount.copy(r), d.tileSize.copy(_), d.rayQueue = a, d.queueSizes = s, d.outputTileIndex = u, d.outputDispatch = c, f.seed++, f.cameraToModelMatrix.copy(t.matrixWorld), f.inverseProjectionMatrix.copy(t.projectionMatrixInverse), f.tileIndexBuffer = u, f.tileSize.copy(_), f.rayQueue = a, f.queueSizes = s, f.sampleCountTarget = i;
|
|
2143
|
+
for (let t = 0; t < r.x * r.y; t++) e.compute(d.kernel, [
|
|
2144
|
+
1,
|
|
2145
|
+
1,
|
|
2146
|
+
1
|
|
2147
|
+
]), e.compute(f.kernel, c), d.tileOffset = 1;
|
|
2148
|
+
let l = p.getDispatchSize(mn, 1, 1);
|
|
2149
|
+
p.sampleCountTarget = i, p.rayQueue = a, p.queueSizes = s, p.hitQueue = o, e.compute(p.kernel, l);
|
|
2150
|
+
let g = l[0] * p.workgroupSize[0];
|
|
2151
|
+
m.processed = g, m.queueSizes = s, e.compute(m.kernel, [
|
|
2152
|
+
1,
|
|
2153
|
+
1,
|
|
2154
|
+
1
|
|
2155
|
+
]), h.sampleCountTarget = i, h.bounces = n, h.rayQueue = a, h.queueSizes = s, h.hitQueue = o, e.compute(h.kernel, h.getDispatchSize(g, 1, 1)), b += v, this.samples = Math.floor(b);
|
|
2156
|
+
}
|
|
2157
|
+
yield;
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
2160
|
+
}, yn = "\n\n // TODO: possibly this should be renamed something related to material or path tracing logic\n\n #ifndef RAY_OFFSET\n #define RAY_OFFSET 1e-4\n #endif\n\n // adjust the hit point by the surface normal by a factor of some offset and the\n // maximum component-wise value of the current point to accommodate floating point\n // error as values increase.\n vec3 stepRayOrigin( vec3 rayOrigin, vec3 rayDirection, vec3 offset, float dist ) {\n\n vec3 point = rayOrigin + rayDirection * dist;\n vec3 absPoint = abs( point );\n float maxPoint = max( absPoint.x, max( absPoint.y, absPoint.z ) );\n return point + offset * ( maxPoint + 1.0 ) * RAY_OFFSET;\n\n }\n\n // https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_volume/README.md#attenuation\n vec3 transmissionAttenuation( float dist, vec3 attColor, float attDist ) {\n\n vec3 ot = - log( attColor ) / attDist;\n return exp( - ot * dist );\n\n }\n\n vec3 getHalfVector( vec3 wi, vec3 wo, float eta ) {\n\n // get the half vector - assuming if the light incident vector is on the other side\n // of the that it's transmissive.\n vec3 h;\n if ( wi.z > 0.0 ) {\n\n h = normalize( wi + wo );\n\n } else {\n\n // Scale by the ior ratio to retrieve the appropriate half vector\n // From Section 2.2 on computing the transmission half vector:\n // https://blog.selfshadow.com/publications/s2015-shading-course/burley/s2015_pbs_disney_bsdf_notes.pdf\n h = normalize( wi + wo * eta );\n\n }\n\n h *= sign( h.z );\n return h;\n\n }\n\n vec3 getHalfVector( vec3 a, vec3 b ) {\n\n return normalize( a + b );\n\n }\n\n // The discrepancy between interpolated surface normal and geometry normal can cause issues when a ray\n // is cast that is on the top side of the geometry normal plane but below the surface normal plane. If\n // we find a ray like that we ignore it to avoid artifacts.\n // This function returns if the direction is on the same side of both planes.\n bool isDirectionValid( vec3 direction, vec3 surfaceNormal, vec3 geometryNormal ) {\n\n bool aboveSurfaceNormal = dot( direction, surfaceNormal ) > 0.0;\n bool aboveGeometryNormal = dot( direction, geometryNormal ) > 0.0;\n return aboveSurfaceNormal == aboveGeometryNormal;\n\n }\n\n // ray sampling x and z are swapped to align with expected background view\n vec2 equirectDirectionToUv( vec3 direction ) {\n\n // from Spherical.setFromCartesianCoords\n vec2 uv = vec2( atan( direction.z, direction.x ), acos( direction.y ) );\n uv /= vec2( 2.0 * PI, PI );\n\n // apply adjustments to get values in range [0, 1] and y right side up\n uv.x += 0.5;\n uv.y = 1.0 - uv.y;\n return uv;\n\n }\n\n vec3 equirectUvToDirection( vec2 uv ) {\n\n // undo above adjustments\n uv.x -= 0.5;\n uv.y = 1.0 - uv.y;\n\n // from Vector3.setFromSphericalCoords\n float theta = uv.x * 2.0 * PI;\n float phi = uv.y * PI;\n\n float sinPhi = sin( phi );\n\n return vec3( sinPhi * cos( theta ), cos( phi ), sinPhi * sin( theta ) );\n\n }\n\n // power heuristic for multiple importance sampling\n float misHeuristic( float a, float b ) {\n\n float aa = a * a;\n float bb = b * b;\n return aa / ( aa + bb );\n\n }\n\n // tentFilter from Peter Shirley's 'Realistic Ray Tracing (2nd Edition)' book, pg. 60\n // erichlof/THREE.js-PathTracing-Renderer/\n float tentFilter( float x ) {\n\n return x < 0.5 ? sqrt( 2.0 * x ) - 1.0 : 1.0 - sqrt( 2.0 - ( 2.0 * x ) );\n\n }\n", bn = class extends d {
|
|
2161
|
+
constructor() {
|
|
2162
|
+
super({
|
|
2163
|
+
uniforms: {
|
|
2164
|
+
envMap: { value: null },
|
|
2165
|
+
flipEnvMap: { value: -1 }
|
|
2166
|
+
},
|
|
2167
|
+
vertexShader: "\n varying vec2 vUv;\n void main() {\n\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n }",
|
|
2168
|
+
fragmentShader: `
|
|
2169
|
+
#define ENVMAP_TYPE_CUBE_UV
|
|
2170
|
+
|
|
2171
|
+
uniform samplerCube envMap;
|
|
2172
|
+
uniform float flipEnvMap;
|
|
2173
|
+
varying vec2 vUv;
|
|
2174
|
+
|
|
2175
|
+
#include <common>
|
|
2176
|
+
#include <cube_uv_reflection_fragment>
|
|
2177
|
+
|
|
2178
|
+
${yn}
|
|
2179
|
+
|
|
2180
|
+
void main() {
|
|
2181
|
+
|
|
2182
|
+
vec3 rayDirection = equirectUvToDirection( vUv );
|
|
2183
|
+
rayDirection.x *= flipEnvMap;
|
|
2184
|
+
gl_FragColor = textureCube( envMap, rayDirection );
|
|
2185
|
+
|
|
2186
|
+
}`
|
|
2187
|
+
}), this.depthWrite = !1, this.depthTest = !1;
|
|
2188
|
+
}
|
|
2189
|
+
}, xn = class {
|
|
2190
|
+
constructor(e) {
|
|
2191
|
+
this._renderer = e, this._quad = new oe(new bn());
|
|
2192
|
+
}
|
|
2193
|
+
generate(e, t = null, r = null) {
|
|
2194
|
+
if (!e.isCubeTexture) throw Error("CubeToEquirectMaterial: Source can only be cube textures.");
|
|
2195
|
+
let a = e.images[0], s = this._renderer, c = this._quad;
|
|
2196
|
+
t === null && (t = 4 * a.height), r === null && (r = 2 * a.height);
|
|
2197
|
+
let l = new n(t, r, {
|
|
2198
|
+
type: v,
|
|
2199
|
+
colorSpace: a.colorSpace
|
|
2200
|
+
}), d = a.height, p = Math.log2(d) - 2, h = 1 / d, g = 1 / (3 * Math.max(2 ** p, 112));
|
|
2201
|
+
c.material.defines.CUBEUV_MAX_MIP = `${p}.0`, c.material.defines.CUBEUV_TEXEL_WIDTH = g, c.material.defines.CUBEUV_TEXEL_HEIGHT = h, c.material.uniforms.envMap.value = e, c.material.uniforms.flipEnvMap.value = e.isRenderTargetTexture ? 1 : -1, c.material.needsUpdate = !0;
|
|
2202
|
+
let _ = s.getRenderTarget(), y = s.autoClear;
|
|
2203
|
+
s.autoClear = !0, s.setRenderTarget(l), c.render(s), s.setRenderTarget(_), s.autoClear = y;
|
|
2204
|
+
let x = new Uint16Array(t * r * 4), S = new Float32Array(t * r * 4);
|
|
2205
|
+
s.readRenderTargetPixels(l, 0, 0, t, r, S), l.dispose();
|
|
2206
|
+
for (let e = 0, t = S.length; e < t; e++) x[e] = u.toHalfFloat(S[e]);
|
|
2207
|
+
let C = new f(x, t, r, i, b);
|
|
2208
|
+
return C.minFilter = m, C.magFilter = w, C.wrapS = o, C.wrapT = o, C.mapping = 303, C.needsUpdate = !0, C;
|
|
2209
|
+
}
|
|
2210
|
+
dispose() {
|
|
2211
|
+
this._quad.dispose();
|
|
2212
|
+
}
|
|
2213
|
+
};
|
|
2214
|
+
//#endregion
|
|
2215
|
+
//#region ../../node_modules/three-gpu-pathtracer/src/core/utils/sceneUpdateUtils.js
|
|
2216
|
+
function Sn(e) {
|
|
2217
|
+
return `${e.source.uuid}:${e.colorSpace}`;
|
|
2218
|
+
}
|
|
2219
|
+
//#endregion
|
|
2220
|
+
//#region ../../node_modules/three-gpu-pathtracer/src/webgpu/nodes/ggx.wgsl.js
|
|
2221
|
+
var Cn = I("\n\n fn ggxDirection( incidentDir: vec3f, alpha: vec2f, uv: vec2f ) -> vec3f {\n\n // Implementation from reference [1]\n // stretch view\n let V = normalize( vec3f( alpha * incidentDir.xy, incidentDir.z ) );\n\n // orthonormal basis\n var T1: vec3f;\n if ( V.z < 0.9999 ) {\n T1 = normalize( cross( V, vec3( 0.0, 0.0, 1.0 ) ) );\n } else {\n T1 = vec3( 1.0, 0.0, 0.0 );\n }\n\n let T2 = cross( T1, V );\n\n // sample point with polar coordinates (r, phi)\n let a = 1.0 / ( 1.0 + V.z );\n let r = sqrt( uv.x );\n var phi: f32;\n if ( uv.y < a ) {\n phi = uv.y / a * PI;\n } else {\n phi = PI + ( uv.y - a ) / ( 1.0 - a ) * PI;\n }\n let P1 = r * cos( phi );\n var P2 = r * sin( phi );\n if ( uv.y >= a ) {\n P2 *= V.z;\n }\n\n // compute normal\n var N = P1 * T1 + P2 * T2 + V * sqrt( max( 0.0, 1.0 - P1 * P1 - P2 * P2 ) );\n\n // unstretch\n N = normalize( vec3( alpha * N.xy, max( 0.0, N.z ) ) );\n\n return N;\n\n }\n\n", [X]), wn = I("\n\n fn ggxLamda( theta: f32, alpha: f32 ) -> f32 {\n\n let tanTheta = tan( theta );\n let tanTheta2 = tanTheta * tanTheta;\n let alpha2 = alpha * alpha;\n\n let numerator = - 1.0 + sqrt( 1.0 + alpha2 * tanTheta2 );\n return numerator / 2.0;\n\n }\n\n"), Tn = I("\n\n fn ggxShadowMaskG1( cosTheta: f32, alpha: f32 ) -> f32 {\n\n let a2 = alpha * alpha;\n let cosTheta2 = cosTheta * cosTheta;\n let denom = cosTheta + sqrt( cosTheta2 * ( 1 - a2 ) + a2 );\n return 2.0 * cosTheta / denom;\n\n }\n\n", [wn]), En = I("\n\n fn ggxSmithVisibility( NdotV: f32, NdotL: f32, alpha: f32 ) -> f32 {\n\n // Original formulation of G_SmithGGX Correlated\n // lambda_v = ( -1 + sqrt ( alphaG2 * (1 - NdotL2 ) / NdotL2 + 1)) * 0.5 f;\n // lambda_l = ( -1 + sqrt ( alphaG2 * (1 - NdotV2 ) / NdotV2 + 1)) * 0.5 f;\n // G_SmithGGXCorrelated = 1 / (1 + lambda_v + lambda_l );\n // V_SmithGGXCorrelated = G_SmithGGXCorrelated / (4.0 f * NdotL * NdotV );\n\n // This is an optimized version\n let alpha2 = alpha * alpha;\n // Caution: the \"NdotL *\" and \"NdotV *\" are explicitely inversed , this is not a mistake.\n let Lambda_GGXV = NdotL * sqrt (( - NdotV * alpha2 + NdotV ) * NdotV + alpha2 );\n let Lambda_GGXL = NdotV * sqrt (( - NdotL * alpha2 + NdotL ) * NdotL + alpha2 );\n\n return 0.5 / ( Lambda_GGXV + Lambda_GGXL );\n\n }\n\n", [wn]), Dn = I("\n fn ggxDistribution( NdotH: f32, alpha: f32 ) -> f32 {\n\n let a2 = max( alpha * alpha, EPSILON );\n let denom = NdotH * NdotH * ( a2 - 1 ) + 1;\n\n return ( a2 / ( PI * denom * denom ) );\n\n }\n"), On = I("\n fn ggxReflectionAdjustedPDF( NdotV: f32, NdotH: f32, alpha: f32 ) -> f32 {\n\n let D = ggxDistribution( NdotH, alpha );\n let G1 = ggxShadowMaskG1( NdotV, alpha );\n\n return D * G1 / ( 4 * NdotV );\n\n }\n", [Dn, Tn]), kn = (e) => I("\n\n fn getSurfaceRecord(\n material: Material,\n vertexData: bvh_GeometryStruct,\n side: f32,\n faceNormal: vec3f,\n ) -> SurfaceRecord {\n let uv = vertexData.uv.xy;\n\n var normal = faceNormal * side;\n if ( material.flatShading == 0 ) {\n\n normal = vertexData.normal.xyz;\n\n }\n normal = normalize( normal );\n let baseNormal = normal;\n\n if ( material.normalMap != -1 ) {\n\n // some provided tangents can be malformed (0, 0, 0) causing the normal to be degenerate\n // resulting in NaNs and slow path tracing.\n if ( length( vertexData.tangent.xyz ) > 0.0 && vertexData.tangent.w != 0.0 ) {\n\n let tangent = normalize( vertexData.tangent.xyz );\n let bitangent = normalize( cross( baseNormal, tangent ) * vertexData.tangent.w );\n let vTBN = mat3x3f( tangent, bitangent, baseNormal );\n\n let uvPrime = material.normalMapTransform * vec3( uv, 1.0 );\n var texNormal = sampleTexel( uvPrime.xy, material.normalMap, 0 ).xyz;\n texNormal = texNormal * 2.0 - 1.0;\n texNormal = texNormal * vec3f( material.normalScale, 1.0 );\n normal = normalize( vTBN * texNormal );\n\n }\n\n }\n\n normal *= side;\n\n var albedo = vec4( material.color, material.opacity );\n\n if ( material.vertexColors == 1 ) {\n\n let vertexColor = vertexData.color.xyz;\n albedo *= vec4f( vertexColor, 1.0 );\n\n }\n\n if ( material.map != -1 ) {\n\n let uvPrime = material.mapTransform * vec3f( uv, 1 );\n let texColor = sampleTexel( uvPrime.xy, material.map, 0 );\n albedo *= vec4f( texColor.rgb, 1.0 );\n\n }\n\n var roughness = material.roughness;\n if ( material.roughnessMap != -1 ) {\n\n let uvPrime = material.roughnessMapTransform * vec3f( uv, 1 );\n let texColor = sampleTexel( uvPrime.xy, material.roughnessMap, 0 );\n roughness *= texColor.g;\n\n }\n\n var metalness = material.metalness;\n if ( material.metalnessMap != -1 ) {\n\n let uvPrime = material.metalnessMapTransform * vec3f( uv, 1 );\n let texColor = sampleTexel( uvPrime.xy, material.metalnessMap, 0 );\n metalness *= texColor.b;\n\n }\n\n var emission = material.emissiveIntensity * material.emissive;\n if ( material.emissiveMap != -1 ) {\n\n let uvPrime = material.emissiveMapTransform * vec3f( uv, 1 );\n let texColor = sampleTexel( uvPrime.xy, material.emissiveMap, 0 );\n emission *= texColor.rgb;\n\n }\n\n var transmission = material.transmission;\n if ( material.transmissionMap != -1 ) {\n\n let uvPrime = material.transmissionMapTransform * vec3f( uv, 1 );\n let texColor = sampleTexel( uvPrime.xy, material.transmissionMap, 0 );\n transmission *= texColor.r;\n\n }\n\n var clearcoat = material.clearcoat;\n if ( material.clearcoatMap != -1 ) {\n\n let uvPrime = material.clearcoatMapTransform * vec3f( uv, 1 );\n let texColor = sampleTexel( uvPrime.xy, material.clearcoatMap, 0 );\n clearcoat *= texColor.r;\n\n }\n\n var clearcoatRoughness = material.clearcoatRoughness;\n if ( material.clearcoatRoughnessMap != -1 ) {\n\n let uvPrime = material.clearcoatRoughnessMapTransform * vec3f( uv, 1 );\n let texColor = sampleTexel( uvPrime.xy, material.clearcoatRoughnessMap, 0 );\n clearcoatRoughness *= texColor.g;\n\n }\n\n var clearcoatNormal = baseNormal;\n if ( material.clearcoatNormalMap != -1 ) {\n\n // some provided tangents can be malformed (0, 0, 0) causing the normal to be degenerate\n // resulting in NaNs and slow path tracing.\n if ( length( vertexData.tangent.xyz ) > 0.0 && vertexData.tangent.w != 0.0 ) {\n\n let tangent = normalize( vertexData.tangent.xyz );\n let bitangent = normalize( cross( baseNormal, tangent ) * vertexData.tangent.w );\n let vTBN = mat3x3f( tangent, bitangent, baseNormal );\n\n let uvPrime = material.clearcoatNormalMapTransform * vec3( uv, 1.0 );\n var texNormal = sampleTexel( uvPrime.xy, material.clearcoatNormalMap, 0 ).xyz;\n texNormal = texNormal * 2.0 - 1.0;\n texNormal = texNormal * vec3f( material.clearcoatNormalScale, 1.0 );\n clearcoatNormal = normalize( vTBN * texNormal );\n\n }\n\n }\n clearcoatNormal *= side;\n\n var sheenColor = material.sheenColor;\n if ( material.sheenColorMap != -1 ) {\n\n let uvPrime = material.sheenColorMapTransform * vec3f( uv, 1 );\n let texColor = sampleTexel( uvPrime.xy, material.sheenColorMap, 0 );\n sheenColor *= texColor.rgb;\n\n }\n\n var sheenRoughness = material.sheenRoughness;\n if ( material.sheenRoughnessMap != -1 ) {\n\n let uvPrime = material.sheenRoughnessMapTransform * vec3f( uv, 1 );\n let texColor = sampleTexel( uvPrime.xy, material.sheenRoughnessMap, 0 );\n sheenRoughness *= texColor.r;\n\n }\n\n var iridescence = material.iridescence;\n if ( material.iridescenceMap != -1 ) {\n\n let uvPrime = material.iridescenceMapTransform * vec3f( uv, 1 );\n let texColor = sampleTexel( uvPrime.xy, material.iridescenceMap, 0 );\n iridescence *= texColor.r;\n\n }\n\n var iridescenceThickness = material.iridescenceThicknessMaximum;\n if ( material.iridescenceThicknessMap != -1 ) {\n\n let uvPrime = material.iridescenceThicknessMapTransform * vec3f( uv, 1 );\n let texColor = sampleTexel( uvPrime.xy, material.iridescenceThicknessMap, 0 );\n\n iridescenceThickness = mix(\n material.iridescenceThicknessMinimum,\n material.iridescenceThicknessMaximum,\n texColor.g,\n );\n\n }\n\n var specularColor = material.specularColor;\n if ( material.specularColorMap != -1 ) {\n\n let uvPrime = material.specularColorMapTransform * vec3f( uv, 1 );\n let texColor = sampleTexel( uvPrime.xy, material.specularColorMap, 0 );\n specularColor *= texColor.rgb;\n\n }\n\n var specularIntensity = material.specularIntensity;\n if ( material.specularIntensityMap != -1 ) {\n\n let uvPrime = material.specularIntensityMapTransform * vec3f( uv, 1 );\n let texColor = sampleTexel( uvPrime.xy, material.specularIntensityMap, 0 );\n specularIntensity *= texColor.r;\n\n }\n\n var surf: SurfaceRecord;\n\n surf.volumeParticle = false;\n surf.faceNormal = faceNormal;\n surf.normal = normal;\n\n surf.metalness = metalness;\n surf.color = albedo.rgb;\n surf.emission = emission;\n\n surf.ior = material.ior;\n surf.transmission = transmission;\n surf.thinFilm = material.thinFilm == 1;\n surf.attenuationColor = material.attenuationColor;\n surf.attenuationDistance = material.attenuationDistance;\n\n surf.clearcoatNormal = clearcoatNormal;\n surf.clearcoat = clearcoat;\n\n surf.iridescence = iridescence;\n surf.iridescenceIor = material.iridescenceIor;\n surf.iridescenceThickness = iridescenceThickness;\n\n surf.specularColor = specularColor;\n surf.specularIntensity = specularIntensity;\n\n surf.roughness = clamp( roughness, MIN_ROUGHNESS, 1.0 );\n surf.clearcoatRoughness = clamp( clearcoatRoughness, MIN_ROUGHNESS, 1.0 );\n surf.sheenRoughness = clamp( sheenRoughness, MIN_ROUGHNESS, 1.0 );\n\n // frontFace is used to determine transmissive properties and PDF. If no transmission is used\n // then we can just always assume this is a front face.\n surf.frontFace = side == 1.0 || transmission == 0.0;\n if ( material.thinFilm == 1 || surf.frontFace ) {\n surf.eta = 1.0 / material.ior;\n } else {\n surf.eta = material.ior;\n }\n surf.f0 = iorToF0( surf.eta );\n\n // get the normal frames\n surf.normalBasis = getBasisFromNormal( surf.normal );\n surf.normalInvBasis = inverse( surf.normalBasis );\n\n surf.clearcoatBasis = getBasisFromNormal( surf.clearcoatNormal );\n surf.clearcoatInvBasis = inverse( surf.clearcoatBasis );\n\n return surf;\n }\n\n", [
|
|
2222
|
+
It,
|
|
2223
|
+
Rt,
|
|
2224
|
+
Lt,
|
|
2225
|
+
e,
|
|
2226
|
+
Mt,
|
|
2227
|
+
X
|
|
2228
|
+
]), An = I("\n\n fn diffuseBrdf( NdotV: f32, NdotL: f32, VdotH: f32, surf: SurfaceRecord ) -> vec3f {\n\n // https://blog.selfshadow.com/publications/s2015-shading-course/burley/s2015_pbs_disney_bsdf_notes.pdf\n // See equation (4)\n\n let fl = schlickFresnel( NdotL, 0.0 );\n let fv = schlickFresnel( NdotV, 0.0 );\n\n let alpha = surf.roughness * surf.roughness;\n let bias = mix( 0.0, 0.5, alpha ) - 1;\n let energyFactor = mix( 1.0, 1.0 / 1.51, alpha );\n\n let rr = 2.0 * alpha * VdotH * VdotH;\n let retro = rr * ( fl + fv + fl * fv * ( rr + 2.0 * bias ) );\n let fresnel = ( 1.0 + bias * fl ) * ( 1.0f + bias * fv );\n\n // TODO: subsurface approx?\n\n return energyFactor * ( surf.color / PI ) * ( retro + fresnel );\n\n }\n\n", [
|
|
2229
|
+
X,
|
|
2230
|
+
Ht,
|
|
2231
|
+
Mt
|
|
2232
|
+
]), jn = I("\n\n fn specularBrdf( NdotL: f32, NdotV: f32, NdotH: f32, alpha: f32 ) -> vec3f {\n\n let Vis = ggxSmithVisibility( NdotV, NdotL, alpha );\n let D = ggxDistribution( NdotH, alpha );\n\n return vec3f( D * Vis );\n\n }\n\n", [En, Dn]), Mn = I("\n\n fn fresnelMix( VdotH: f32, ior: f32, base: vec3f, layer: vec3f ) -> vec3f {\n\n let f0 = iorToF0( ior );\n let F = schlickFresnel( abs( VdotH ), f0 );\n\n return base + F * layer;\n\n }\n\n", [Ht, Rt]), Nn = Oe(3.2404542, -.969266, .0556434, -1.5371385, 1.8760108, -.2040259, -.4985314, .041556, 1.0572252), Pn = I("\n\n fn iridescentFresnel(\n cosTheta1: f32, baseF0: vec3f, iridescenceIor: f32,\n outsideIor: f32, iridescenceThickness: f32,\n ) -> vec3f {\n\n let sinTheta2Sq = pow( outsideIor / iridescenceIor, 2.0 ) * ( 1.0 - pow( cosTheta1, 2.0 ) );\n let cosTheta2Sq = 1.0 - sinTheta2Sq;\n\n // Handle total internal reflection\n if ( cosTheta2Sq < 0.0 ) {\n\n return vec3( 1.0 );\n\n }\n\n let cosTheta2 = sqrt( cosTheta2Sq );\n\n // First interface: air -> iridescent thin film\n let R0 = iorToF0General( iridescenceIor, outsideIor );\n let R12 = schlickFresnel( cosTheta1, R0 );\n let R21 = R12;\n let T121 = 1.0 - R12;\n let phi12 = select( 0.0, PI, iridescenceIor < outsideIor );\n let phi21 = PI - phi12;\n\n // Second interface: iridescent thin film -> base material\n let baseIor = fresnel0ToIor( baseF0 + 0.0001 ); // guard against 1.0\n let R1 = iorToF0GeneralVec( baseIor, vec3( iridescenceIor ) );\n let R23 = schlickFresnelVec( cosTheta2, R1, vec3( 1.0 ) );\n let phi23 = select( vec3( 0.0 ), vec3( PI ), baseIor < vec3( iridescenceIor ) );\n\n // Phase shift\n let OPD = 2.0 * iridescenceIor * iridescenceThickness * cosTheta2;\n let phi = vec3( phi21 ) + phi23;\n\n // Analytical integration\n // Compound terms\n let R123 = clamp( R12 * R23, vec3( 1e-5 ), vec3( 0.9999 ) );\n let r123 = sqrt( R123 );\n let Rs = T121 * T121 * R23 / ( vec3( 1.0 ) - R123 );\n\n // Reflectance term for m = 0 (DC term amplitude)\n let C0 = R12 + Rs;\n var I = C0;\n\n // Reflectance term for m > 0 (pairs of diracs)\n var Cm = Rs - T121;\n for (var m = 1; m <= 2; m += 1) {\n\n Cm *= r123;\n let Sm = 2.0 * evalSensitivity( f32( m ) * OPD, f32( m ) * phi );\n I += Cm * Sm;\n\n }\n\n return max( I, vec3(0.0) );\n\n }\n\n", [
|
|
2233
|
+
zt,
|
|
2234
|
+
Bt,
|
|
2235
|
+
Ht,
|
|
2236
|
+
Vt,
|
|
2237
|
+
W`
|
|
2238
|
+
|
|
2239
|
+
fn evalSensitivity( OPD: f32, shift: vec3f ) -> vec3f {
|
|
2240
|
+
|
|
2241
|
+
let phase = 2.0 * ${Math.PI} * OPD * 1.0e-9;
|
|
2242
|
+
const val = vec3(5.4856e-13, 4.4201e-13, 5.2481e-13);
|
|
2243
|
+
const pos = vec3(1.6810e+06, 1.7953e+06, 2.2084e+06);
|
|
2244
|
+
const _var = vec3(4.3278e+09, 9.3046e+09, 6.6121e+09);
|
|
2245
|
+
|
|
2246
|
+
var xyz = val * sqrt(2.0 * ${Math.PI} * _var) * cos(pos * phase + shift) * exp(-phase * phase * _var);
|
|
2247
|
+
xyz.x += 9.7470e-14 * sqrt(2.0 * ${Math.PI} * 4.5282e+09) * cos(2.2399e+06 * phase + shift.x) * exp(-4.5282e+09 * phase * phase);
|
|
2248
|
+
xyz /= 1.0685e-7;
|
|
2249
|
+
|
|
2250
|
+
let rgb = ${Nn} * xyz;
|
|
2251
|
+
return rgb;
|
|
2252
|
+
|
|
2253
|
+
}
|
|
2254
|
+
|
|
2255
|
+
`
|
|
2256
|
+
]), Fn = I("\n\n fn iridescentDielectricLayer(\n dielectricBase: vec3f, base: vec3f, specular: vec3f, HdotL: f32,\n outsideIor: f32, baseIor: f32, iridescenceIor: f32, thickness: f32, strength: f32,\n ) -> vec3f {\n\n let baseF0 = vec3( iorToF0( baseIor ) );\n\n let iridescentF = iridescentFresnel( HdotL, baseF0, iridescenceIor, outsideIor, thickness );\n\n return mix( dielectricBase, rgbMix( base, specular, iridescentF ), strength );\n\n }\n\n", [
|
|
2257
|
+
Rt,
|
|
2258
|
+
Pn,
|
|
2259
|
+
I("\n\n fn rgbMix( base: vec3f, specular: vec3f, rgbAlpha: vec3f ) -> vec3f {\n\n let alphaMax = max( max( rgbAlpha.x, rgbAlpha.y ), rgbAlpha.z );\n return ( 1 - alphaMax ) * base + rgbAlpha * specular;\n\n }\n\n")
|
|
2260
|
+
]), In = I("\n\n fn iridescentConductorLayer(\n metalBase: vec3f, specular: vec3f, baseF0: vec3f, HdotL: f32,\n outsideIor: f32, iridescenceIor: f32, thickness: f32, strength: f32,\n ) -> vec3f {\n\n let iridescenceF = iridescentFresnel( HdotL, baseF0, iridescenceIor, outsideIor, thickness );\n\n return mix( metalBase, specular * iridescenceF, strength );\n\n }\n\n", [Pn]), Ln = (e) => I("\n\n fn conductorFresnel( NdotV: f32, VdotH: f32, f0: vec3f, bsdf: vec3f, alpha: f32 ) -> vec3f {\n\n let ss = bsdf * schlickFresnelVec( abs( VdotH ), f0, vec3f( 1 ) );\n\n let uv = vec2( NdotV, sqrt( alpha ) );\n let energySs = max( textureSampleLevel( turquinTexture, turquinTexture_sampler, uv, 0 ).r, 1e-5 );\n\n return ss * ( 1.0 + f0 * ( 1.0 - energySs ) / energySs );\n\n }\n\n", [Ut, e]), Rn = I("\n\n fn fresnelCoat( VdotNc: f32, ior: f32, base: vec3f, layer: vec3f, weight: f32 ) -> vec3f {\n\n let f0 = iorToF0( ior );\n let F = schlickFresnel( abs( VdotNc ), f0 );\n\n return mix( base, layer, weight * F );\n\n }\n\n", [Rt, Ht]), zn = W`
|
|
2261
|
+
|
|
2262
|
+
fn albedo(
|
|
2263
|
+
texture: texture_storage_2d<r16float, write>,
|
|
2264
|
+
|
|
2265
|
+
globalId: vec3u,
|
|
2266
|
+
) -> void {
|
|
2267
|
+
|
|
2268
|
+
const INTEGRATION_SAMPLES = ( 1 << 20 );
|
|
2269
|
+
let pixelIndex = ( globalId.x << 16 ) | globalId.y;
|
|
2270
|
+
${Ot}( pixelIndex, 0, 0 );
|
|
2271
|
+
|
|
2272
|
+
let dimensions = textureDimensions( texture ).xy;
|
|
2273
|
+
let uv = ( vec2f( globalId.xy ) + vec2f( 0.5 ) ) / vec2f( dimensions );
|
|
2274
|
+
|
|
2275
|
+
let cosThetaO = uv.x;
|
|
2276
|
+
let roughness = uv.y;
|
|
2277
|
+
|
|
2278
|
+
let alpha = roughness * roughness;
|
|
2279
|
+
|
|
2280
|
+
let wo = vec3( sqrt( 1 - cosThetaO * cosThetaO ), 0 , cosThetaO );
|
|
2281
|
+
|
|
2282
|
+
var result = 0.0;
|
|
2283
|
+
for ( var i = 0; i < INTEGRATION_SAMPLES; i++ ) {
|
|
2284
|
+
|
|
2285
|
+
let wh = ${Cn}( wo, vec2( alpha ), ${Y}(${3}) );
|
|
2286
|
+
var wi = - reflect( wo, wh );
|
|
2287
|
+
|
|
2288
|
+
let NdotV = max( wo.z, EPSILON );
|
|
2289
|
+
let NdotL = saturate( wi.z );
|
|
2290
|
+
let NdotH = saturate( wh.z );
|
|
2291
|
+
|
|
2292
|
+
let specular = ${jn}( NdotL, NdotV, NdotH, alpha );
|
|
2293
|
+
let pdf = ${On}( NdotV, NdotH, alpha );
|
|
2294
|
+
|
|
2295
|
+
var weight = 0.0;
|
|
2296
|
+
if ( pdf != 0.0 ) {
|
|
2297
|
+
weight = 1 / pdf;
|
|
2298
|
+
}
|
|
2299
|
+
|
|
2300
|
+
result += specular.x * NdotL * weight;
|
|
2301
|
+
|
|
2302
|
+
}
|
|
2303
|
+
|
|
2304
|
+
result /= f32( INTEGRATION_SAMPLES );
|
|
2305
|
+
|
|
2306
|
+
textureStore( texture, globalId.xy, vec4( result ) );
|
|
2307
|
+
|
|
2308
|
+
}
|
|
2309
|
+
|
|
2310
|
+
`, Bn = 4096, Vn = new ie();
|
|
2311
|
+
function Hn(e) {
|
|
2312
|
+
return `${e.source.uuid}:${e.source.version}`;
|
|
2313
|
+
}
|
|
2314
|
+
function Un(e, t, n, r) {
|
|
2315
|
+
if (e[t].x + n > r) return -1;
|
|
2316
|
+
let i = n, a = 0, o = t;
|
|
2317
|
+
for (; i > 0;) {
|
|
2318
|
+
if (o >= e.length) return -1;
|
|
2319
|
+
a = Math.max(a, e[o].y), i -= e[o].width, o++;
|
|
2320
|
+
}
|
|
2321
|
+
return a;
|
|
2322
|
+
}
|
|
2323
|
+
function Wn(e, t, n, r) {
|
|
2324
|
+
let i = t + r, a = [], o = !1;
|
|
2325
|
+
for (let s = 0; s < e.length; s++) {
|
|
2326
|
+
let c = e[s], l = c.x + c.width;
|
|
2327
|
+
l <= t ? a.push(c) : c.x >= i ? (o ||= (a.push({
|
|
2328
|
+
x: t,
|
|
2329
|
+
y: n,
|
|
2330
|
+
width: r
|
|
2331
|
+
}), !0), a.push(c)) : (o ||= (a.push({
|
|
2332
|
+
x: t,
|
|
2333
|
+
y: n,
|
|
2334
|
+
width: r
|
|
2335
|
+
}), !0), l > i && a.push({
|
|
2336
|
+
x: i,
|
|
2337
|
+
y: c.y,
|
|
2338
|
+
width: l - i
|
|
2339
|
+
}));
|
|
2340
|
+
}
|
|
2341
|
+
o || a.push({
|
|
2342
|
+
x: t,
|
|
2343
|
+
y: n,
|
|
2344
|
+
width: r
|
|
2345
|
+
}), e.length = 0;
|
|
2346
|
+
for (let t = 0; t < a.length; t++) {
|
|
2347
|
+
let n = a[t], r = e[e.length - 1];
|
|
2348
|
+
r && r.y === n.y && r.x + r.width === n.x ? r.width += n.width : e.push(n);
|
|
2349
|
+
}
|
|
2350
|
+
}
|
|
2351
|
+
function Gn(e, t, n, r, i) {
|
|
2352
|
+
let a = Infinity, o = 0, s = -1;
|
|
2353
|
+
for (let c = 0; c < e.length; c++) {
|
|
2354
|
+
let l = Un(e, c, t, r);
|
|
2355
|
+
l >= 0 && l + n <= i && l < a && (a = l, o = e[c].x, s = c);
|
|
2356
|
+
}
|
|
2357
|
+
return s === -1 ? null : (Wn(e, o, a + n, t), {
|
|
2358
|
+
x: o,
|
|
2359
|
+
y: a
|
|
2360
|
+
});
|
|
2361
|
+
}
|
|
2362
|
+
var Kn = class {
|
|
2363
|
+
get width() {
|
|
2364
|
+
return this.renderTarget.width;
|
|
2365
|
+
}
|
|
2366
|
+
get height() {
|
|
2367
|
+
return this.renderTarget.height;
|
|
2368
|
+
}
|
|
2369
|
+
get pageCount() {
|
|
2370
|
+
return this.renderTarget.depth;
|
|
2371
|
+
}
|
|
2372
|
+
get texture() {
|
|
2373
|
+
return this.renderTarget.texture;
|
|
2374
|
+
}
|
|
2375
|
+
constructor(e = {}) {
|
|
2376
|
+
this.renderTarget = new x(1, 1, {
|
|
2377
|
+
depthBuffer: !1,
|
|
2378
|
+
depth: 1,
|
|
2379
|
+
...e
|
|
2380
|
+
}), this.texture.isArrayTexture = !0, this.textureInfo = [new E()], this.hashes = [], this.quadMesh = new pe(new C()), this.quadMesh.material.blending = 0;
|
|
2381
|
+
}
|
|
2382
|
+
setTextures(e, t) {
|
|
2383
|
+
if (this._hashesMatch(t)) return;
|
|
2384
|
+
let n = t.reduce((e, t) => Math.max(e, t.width, t.height), 1);
|
|
2385
|
+
n = Math.min(Bn, n);
|
|
2386
|
+
let r = n, i = n, { renderTarget: a } = this, { placements: o, pageCount: s } = this._packTextures(t, r, i);
|
|
2387
|
+
a.setSize(r, i, s), this.texture.isArrayTexture = !0, this._buildTextureInfo(o), this._renderTextures(e, t, o);
|
|
2388
|
+
let c = Array(t.length);
|
|
2389
|
+
for (let e = 0, n = t.length; e < n; e++) c[e] = Hn(t[e]);
|
|
2390
|
+
this.hashes = c;
|
|
2391
|
+
}
|
|
2392
|
+
dispose() {
|
|
2393
|
+
this.renderTarget.dispose(), this.quadMesh.material.dispose();
|
|
2394
|
+
}
|
|
2395
|
+
_hashesMatch(e) {
|
|
2396
|
+
let t = this.hashes;
|
|
2397
|
+
if (t.length !== e.length) return !1;
|
|
2398
|
+
for (let n = 0, r = e.length; n < r; n++) if (t[n] !== Hn(e[n])) return !1;
|
|
2399
|
+
return !0;
|
|
2400
|
+
}
|
|
2401
|
+
_packTextures(e, t, n) {
|
|
2402
|
+
let r = [];
|
|
2403
|
+
for (let i = 0, a = e.length; i < a; i++) {
|
|
2404
|
+
let a = e[i];
|
|
2405
|
+
r.push({
|
|
2406
|
+
index: i,
|
|
2407
|
+
w: Math.min(a.width, t),
|
|
2408
|
+
h: Math.min(a.height, n)
|
|
2409
|
+
});
|
|
2410
|
+
}
|
|
2411
|
+
let i = r.sort((e, t) => t.h - e.h), a = Array(e.length), o = [];
|
|
2412
|
+
for (let e = 0, r = i.length; e < r; e++) {
|
|
2413
|
+
let r = i[e], s = null, c = -1;
|
|
2414
|
+
for (let e = 0; e < o.length; e++) if (s = Gn(o[e], r.w, r.h, t, n), s) {
|
|
2415
|
+
c = e;
|
|
2416
|
+
break;
|
|
2417
|
+
}
|
|
2418
|
+
if (!s) {
|
|
2419
|
+
let e = [{
|
|
2420
|
+
x: 0,
|
|
2421
|
+
y: 0,
|
|
2422
|
+
width: t
|
|
2423
|
+
}];
|
|
2424
|
+
s = Gn(e, r.w, r.h, t, n), o.push(e), c = o.length - 1;
|
|
2425
|
+
}
|
|
2426
|
+
a[r.index] = {
|
|
2427
|
+
x: s.x,
|
|
2428
|
+
y: s.y,
|
|
2429
|
+
w: r.w,
|
|
2430
|
+
h: r.h,
|
|
2431
|
+
page: c
|
|
2432
|
+
};
|
|
2433
|
+
}
|
|
2434
|
+
return {
|
|
2435
|
+
placements: a,
|
|
2436
|
+
pageCount: Math.max(o.length, 1)
|
|
2437
|
+
};
|
|
2438
|
+
}
|
|
2439
|
+
_buildTextureInfo(e) {
|
|
2440
|
+
let t = this.textureInfo;
|
|
2441
|
+
t.length = 0;
|
|
2442
|
+
for (let n = 0, r = e.length; n < r; n++) {
|
|
2443
|
+
let { x: r, y: i, w: a, h: o, page: s } = e[n], c = new E();
|
|
2444
|
+
c.x = r & 65535 | (i & 65535) << 16, c.y = a & 65535 | (o & 65535) << 16, c.z = s & 65535, c.w = 0, t.push(c);
|
|
2445
|
+
}
|
|
2446
|
+
t.length === 0 && t.push(new E(0, 0, 0, 0));
|
|
2447
|
+
}
|
|
2448
|
+
_renderTextures(e, t, n) {
|
|
2449
|
+
let { quadMesh: r, renderTarget: i, width: a, height: o } = this, s = e.getRenderTarget(), c = e.toneMapping, l = e.autoClear, u = e.getScissorTest(), d = e.getClearAlpha();
|
|
2450
|
+
e.getClearColor(Vn), e.toneMapping = 0, e.autoClear = !1, e.setScissorTest(!0), e.setClearColor(0, 0);
|
|
2451
|
+
for (let t = 0, n = i.depth; t < n; t++) i.viewport.set(0, 0, a, o), i.scissor.set(0, 0, a, o), e.setRenderTarget(i, t), e.clear();
|
|
2452
|
+
for (let a = 0, o = t.length; a < o; a++) {
|
|
2453
|
+
let { x: o, y: s, w: c, h: l, page: u } = n[a], d = t[a].clone();
|
|
2454
|
+
d.matrixAutoUpdate = !1, d.matrix.identity(), d.needsUpdate = !0, r.material.map = d, i.viewport.set(o, s, c, l), i.scissor.set(o, s, c, l), e.setRenderTarget(i, u), r.render(e), d.dispose();
|
|
2455
|
+
}
|
|
2456
|
+
i.viewport.set(0, 0, a, o), i.scissor.set(0, 0, a, o), r.material.map = null, e.setClearColor(Vn, d), e.setScissorTest(u), e.autoClear = l, e.setRenderTarget(s), e.toneMapping = c;
|
|
2457
|
+
}
|
|
2458
|
+
}, qn = new E(), Jn = new D({
|
|
2459
|
+
matrixWorld: "mat4x4f",
|
|
2460
|
+
inverseMatrixWorld: "mat4x4f",
|
|
2461
|
+
nodeOffset: "uint",
|
|
2462
|
+
visible: "uint",
|
|
2463
|
+
materialIndex: "uint",
|
|
2464
|
+
_alignment0: "uint",
|
|
2465
|
+
color: "vec4f"
|
|
2466
|
+
}, "TransformStruct"), Yn = class extends lt {
|
|
2467
|
+
constructor(e, t = {}) {
|
|
2468
|
+
super(e, {
|
|
2469
|
+
attributes: {
|
|
2470
|
+
position: "vec4f",
|
|
2471
|
+
normal: "vec4f",
|
|
2472
|
+
tangent: "vec4f",
|
|
2473
|
+
color: "vec4f",
|
|
2474
|
+
uv: "vec4f"
|
|
2475
|
+
},
|
|
2476
|
+
...t
|
|
2477
|
+
}), this.structs.transform = Jn, this.structs.material = jt, this.storage.materials = null, this.materials = [], this.bvhMap = /* @__PURE__ */ new Map(), this.textureAtlas = new Kn();
|
|
2478
|
+
}
|
|
2479
|
+
useTransparencyRaycastFn() {
|
|
2480
|
+
let { textureAtlas: e, storage: t, structs: n, fns: r } = this, i = e.texture, a = qt(Ee(e.textureInfo, "uvec4"), F(i), L(i));
|
|
2481
|
+
r.getSurfaceRecord = kn(a);
|
|
2482
|
+
let o = new fe(n.material).toVar("bvh_material"), s = M(1).toVar("bvh_rayScalar"), c = M(1).toVar("bvh_baseOpacity");
|
|
2483
|
+
r.raycastFirstHit = this.getShapecastFn({
|
|
2484
|
+
name: "raycastFirstHit",
|
|
2485
|
+
shapeStruct: R,
|
|
2486
|
+
resultStruct: z,
|
|
2487
|
+
boundsOrderFn: W`
|
|
2488
|
+
fn getBoundsOrder( ray: ${R}, splitAxis: u32, node: ${Ae} ) -> bool {
|
|
2489
|
+
|
|
2490
|
+
return ray.direction[ splitAxis ] >= 0.0;
|
|
2491
|
+
|
|
2492
|
+
}
|
|
2493
|
+
`,
|
|
2494
|
+
intersectsBoundsFn: W`
|
|
2495
|
+
fn rayIntersectsBounds( ray: ${R}, bounds: ${ke}, result: ptr<function, ${z}> ) -> u32 {
|
|
2496
|
+
|
|
2497
|
+
// early-out if our object is completely transparent
|
|
2498
|
+
if ( ${c} == 0.0 ) {
|
|
2499
|
+
|
|
2500
|
+
return 0u;
|
|
2501
|
+
|
|
2502
|
+
}
|
|
2503
|
+
|
|
2504
|
+
let boundsMin = vec3( bounds.min[0], bounds.min[1], bounds.min[2] );
|
|
2505
|
+
let boundsMax = vec3( bounds.max[0], bounds.max[1], bounds.max[2] );
|
|
2506
|
+
|
|
2507
|
+
let invDir = 1.0 / ray.direction;
|
|
2508
|
+
let tMinPlane = ( boundsMin - ray.origin ) * invDir;
|
|
2509
|
+
let tMaxPlane = ( boundsMax - ray.origin ) * invDir;
|
|
2510
|
+
|
|
2511
|
+
let tMinHit = min( tMinPlane, tMaxPlane );
|
|
2512
|
+
let tMaxHit = max( tMinPlane, tMaxPlane );
|
|
2513
|
+
|
|
2514
|
+
let t0 = max( max( tMinHit.x, tMinHit.y ), tMinHit.z );
|
|
2515
|
+
let t1 = min( min( tMaxHit.x, tMaxHit.y ), tMaxHit.z );
|
|
2516
|
+
|
|
2517
|
+
let dist = max( t0, 0.0 );
|
|
2518
|
+
if ( t1 < dist ) {
|
|
2519
|
+
|
|
2520
|
+
return 0u;
|
|
2521
|
+
|
|
2522
|
+
} else if ( result.didHit && dist * ${s} >= result.dist ) {
|
|
2523
|
+
|
|
2524
|
+
return 0u;
|
|
2525
|
+
|
|
2526
|
+
} else {
|
|
2527
|
+
|
|
2528
|
+
return 1u;
|
|
2529
|
+
|
|
2530
|
+
}
|
|
2531
|
+
|
|
2532
|
+
}
|
|
2533
|
+
|
|
2534
|
+
`,
|
|
2535
|
+
intersectRangeFn: W`
|
|
2536
|
+
fn intersectRange( ray: ${R}, offset: u32, count: u32, result: ptr<function, ${z}> ) -> bool {
|
|
2537
|
+
|
|
2538
|
+
var didHit = false;
|
|
2539
|
+
for ( var ti = offset; ti < offset + count; ti = ti + 1u ) {
|
|
2540
|
+
|
|
2541
|
+
let i0 = ${t.index}[ ti * 3u ];
|
|
2542
|
+
let i1 = ${t.index}[ ti * 3u + 1u ];
|
|
2543
|
+
let i2 = ${t.index}[ ti * 3u + 2u ];
|
|
2544
|
+
|
|
2545
|
+
let a = ${t.attributes}[ i0 ].position.xyz;
|
|
2546
|
+
let b = ${t.attributes}[ i1 ].position.xyz;
|
|
2547
|
+
let c = ${t.attributes}[ i2 ].position.xyz;
|
|
2548
|
+
|
|
2549
|
+
var triResult = ${tt}( ray, a, b, c, 1e-5 );
|
|
2550
|
+
triResult.dist *= ${s};
|
|
2551
|
+
if ( triResult.didHit && ( ! result.didHit || triResult.dist < result.dist ) ) {
|
|
2552
|
+
|
|
2553
|
+
let material = ${o};
|
|
2554
|
+
|
|
2555
|
+
// TODO: if material is a transmissive volume we may need to assume double-sidedness
|
|
2556
|
+
if ( material.side != 0 && triResult.side != material.side ) {
|
|
2557
|
+
|
|
2558
|
+
continue;
|
|
2559
|
+
|
|
2560
|
+
}
|
|
2561
|
+
|
|
2562
|
+
if ( material.transparent != 0 || material.alphaTest > 0.0 ) {
|
|
2563
|
+
|
|
2564
|
+
var opacity = ${c};
|
|
2565
|
+
|
|
2566
|
+
// account for alpha component of albedo map
|
|
2567
|
+
if ( material.map != - 1 ) {
|
|
2568
|
+
|
|
2569
|
+
let barycoord = triResult.barycoord;
|
|
2570
|
+
let a = ${t.attributes}[ i0 ].uv.xy;
|
|
2571
|
+
let b = ${t.attributes}[ i1 ].uv.xy;
|
|
2572
|
+
let c = ${t.attributes}[ i2 ].uv.xy;
|
|
2573
|
+
let uv = barycoord.x * a + barycoord.y * b + barycoord.z * c;
|
|
2574
|
+
let uvPrime = material.mapTransform * vec3f( uv, 1 );
|
|
2575
|
+
|
|
2576
|
+
opacity *= ${a}( uvPrime.xy, material.map, 0 ).a;
|
|
2577
|
+
|
|
2578
|
+
}
|
|
2579
|
+
|
|
2580
|
+
// account for green component of alpha map
|
|
2581
|
+
if ( material.alphaMap != - 1 ) {
|
|
2582
|
+
|
|
2583
|
+
let barycoord = triResult.barycoord;
|
|
2584
|
+
let a = ${t.attributes}[ i0 ].uv.xy;
|
|
2585
|
+
let b = ${t.attributes}[ i1 ].uv.xy;
|
|
2586
|
+
let c = ${t.attributes}[ i2 ].uv.xy;
|
|
2587
|
+
let uv = barycoord.x * a + barycoord.y * b + barycoord.z * c;
|
|
2588
|
+
let uvPrime = material.alphaMapTransform * vec3f( uv, 1 );
|
|
2589
|
+
|
|
2590
|
+
opacity *= ${a}( uvPrime.xy, material.alphaMap, 0 ).g;
|
|
2591
|
+
|
|
2592
|
+
}
|
|
2593
|
+
|
|
2594
|
+
if ( material.transparent != 0 && opacity < ${Dt}( ${4} + ti ) ) {
|
|
2595
|
+
|
|
2596
|
+
continue;
|
|
2597
|
+
|
|
2598
|
+
}
|
|
2599
|
+
|
|
2600
|
+
if ( opacity < material.alphaTest ) {
|
|
2601
|
+
|
|
2602
|
+
continue;
|
|
2603
|
+
|
|
2604
|
+
}
|
|
2605
|
+
|
|
2606
|
+
}
|
|
2607
|
+
|
|
2608
|
+
result.didHit = true;
|
|
2609
|
+
result.dist = triResult.dist;
|
|
2610
|
+
result.normal = triResult.normal;
|
|
2611
|
+
result.side = triResult.side;
|
|
2612
|
+
result.barycoord = triResult.barycoord;
|
|
2613
|
+
result.indices = vec4u( i0, i1, i2, ti );
|
|
2614
|
+
|
|
2615
|
+
didHit = true;
|
|
2616
|
+
|
|
2617
|
+
}
|
|
2618
|
+
|
|
2619
|
+
}
|
|
2620
|
+
|
|
2621
|
+
return didHit;
|
|
2622
|
+
|
|
2623
|
+
}
|
|
2624
|
+
`,
|
|
2625
|
+
transformShapeFn: W`
|
|
2626
|
+
fn transformRay( ray: ptr<function, ${R}>, objectIndex: u32 ) -> void {
|
|
2627
|
+
|
|
2628
|
+
let toLocal = ${t.transforms}[ objectIndex ].inverseMatrixWorld;
|
|
2629
|
+
ray.origin = ( toLocal * vec4f( ray.origin, 1.0 ) ).xyz;
|
|
2630
|
+
ray.direction = ( toLocal * vec4f( ray.direction, 0.0 ) ).xyz;
|
|
2631
|
+
|
|
2632
|
+
let len = length( ray.direction );
|
|
2633
|
+
ray.direction /= len;
|
|
2634
|
+
${s} = 1.0 / len;
|
|
2635
|
+
|
|
2636
|
+
let object = ${t.transforms}[ objectIndex ];
|
|
2637
|
+
${o} = ${t.materials}[ object.materialIndex ];
|
|
2638
|
+
if ( ${o}.transparent == 1 ) {
|
|
2639
|
+
|
|
2640
|
+
${c} = ${o}.opacity * object.color.a;
|
|
2641
|
+
|
|
2642
|
+
} else {
|
|
2643
|
+
|
|
2644
|
+
${c} = 1.0;
|
|
2645
|
+
|
|
2646
|
+
}
|
|
2647
|
+
|
|
2648
|
+
}
|
|
2649
|
+
`,
|
|
2650
|
+
transformResultFn: W`
|
|
2651
|
+
fn transformResult( hit: ptr<function, ${z}>, objectIndex: u32 ) -> void {
|
|
2652
|
+
|
|
2653
|
+
let toLocal = ${t.transforms}[ objectIndex ].inverseMatrixWorld;
|
|
2654
|
+
hit.normal = normalize( ( transpose( toLocal ) * vec4f( hit.normal, 0.0 ) ).xyz );
|
|
2655
|
+
hit.objectIndex = objectIndex;
|
|
2656
|
+
|
|
2657
|
+
}
|
|
2658
|
+
`
|
|
2659
|
+
});
|
|
2660
|
+
}
|
|
2661
|
+
update() {
|
|
2662
|
+
super.update();
|
|
2663
|
+
let { materials: e, structs: t } = this, { materialData: n, textures: r } = this.writeMaterialsBuffer(e);
|
|
2664
|
+
this.textures = r;
|
|
2665
|
+
let i = P(new le(n, t.material.getLength()), t.material).toReadOnly().setName("bvh_materials");
|
|
2666
|
+
this.storage.materials = i, this.bvhMap.clear(), this.materials.length = 0, this.useTransparencyRaycastFn();
|
|
2667
|
+
}
|
|
2668
|
+
writeMaterialsBuffer(e) {
|
|
2669
|
+
function t(e) {
|
|
2670
|
+
switch (e) {
|
|
2671
|
+
case o: return 0;
|
|
2672
|
+
case c: return 1;
|
|
2673
|
+
case ae: return 2;
|
|
2674
|
+
default: return 0;
|
|
2675
|
+
}
|
|
2676
|
+
}
|
|
2677
|
+
function n(e, n) {
|
|
2678
|
+
if (n in e && e[n]) {
|
|
2679
|
+
let r = e[n], i = Sn(r);
|
|
2680
|
+
s.has(i) || (s.set(i, s.size), l.push(r));
|
|
2681
|
+
let a = s.get(i), o = t(r.wrapS), c = t(r.wrapT);
|
|
2682
|
+
return (r.magFilter === 1003 ? 1 : 0) << 28 | c << 26 | o << 24 | a;
|
|
2683
|
+
} else return -1;
|
|
2684
|
+
}
|
|
2685
|
+
function r(e, t, n) {
|
|
2686
|
+
return t in e ? e[t] : n;
|
|
2687
|
+
}
|
|
2688
|
+
function i(e, t, n, r) {
|
|
2689
|
+
let i = e[t] && e[t].isTexture ? e[t] : null;
|
|
2690
|
+
if (i) {
|
|
2691
|
+
i.matrixAutoUpdate && i.updateMatrix();
|
|
2692
|
+
let e = i.matrix.elements;
|
|
2693
|
+
for (let t = 0; t < 3; t++) n[r + 4 * t + 0] = e[3 * t + 0], n[r + 4 * t + 1] = e[3 * t + 1], n[r + 4 * t + 2] = e[3 * t + 2], n[r + 4 * t + 3] = 0;
|
|
2694
|
+
}
|
|
2695
|
+
return 12;
|
|
2696
|
+
}
|
|
2697
|
+
let a = 0, s = /* @__PURE__ */ new Map(), l = [], u = Math.max(e.length, 2), d = new Float32Array(u * this.structs.material.getLength()), f = new Int32Array(d.buffer);
|
|
2698
|
+
for (let t = 0, o = e.length; t < o; t++) {
|
|
2699
|
+
let o = e[t];
|
|
2700
|
+
d[a++] = o.color.r, d[a++] = o.color.g, d[a++] = o.color.b, f[a++] = n(o, "map"), d[a++] = r(o, "metalness", 0), f[a++] = n(o, "metalnessMap"), d[a++] = r(o, "roughness", 0), f[a++] = n(o, "roughnessMap"), d[a++] = r(o, "ior", 1.5), d[a++] = r(o, "transmission", 0), f[a++] = n(o, "transmissionMap"), d[a++] = r(o, "emissiveIntensity", 0), "emissive" in o ? (d[a++] = o.emissive.r, d[a++] = o.emissive.g, d[a++] = o.emissive.b) : (d[a++] = 0, d[a++] = 0, d[a++] = 0), f[a++] = n(o, "emissiveMap"), f[a++] = n(o, "normalMap"), a++, "normalScale" in o ? (d[a++] = o.normalScale.x, d[a++] = o.normalScale.y) : (d[a++] = 1, d[a++] = 1), d[a++] = r(o, "clearcoat", 0), f[a++] = n(o, "clearcoatMap"), f[a++] = n(o, "clearcoatNormalMap"), a++, "clearcoatNormalScale" in o ? (d[a++] = o.clearcoatNormalScale.x, d[a++] = o.clearcoatNormalScale.y) : (d[a++] = 1, d[a++] = 1), d[a++] = r(o, "clearcoatRoughness", 0), f[a++] = n(o, "clearcoatRoughnessMap"), f[a++] = n(o, "iridescenceMap"), f[a++] = n(o, "iridescenceThicknessMap"), d[a++] = r(o, "iridescence", 0), d[a++] = r(o, "iridescenceIOR", 1.3);
|
|
2701
|
+
let s = r(o, "iridescenceThicknessRange", [100, 400]);
|
|
2702
|
+
d[a++] = s[0], d[a++] = s[1], a++, a++, "specularColor" in o ? (d[a++] = o.specularColor.r, d[a++] = o.specularColor.g, d[a++] = o.specularColor.b) : (d[a++] = 1, d[a++] = 1, d[a++] = 1), f[a++] = n(o, "specularColorMap"), d[a++] = r(o, "specularIntensity", 1), f[a++] = n(o, "specularIntensityMap");
|
|
2703
|
+
let c = r(o, "thickness", 0) === 0 && r(o, "attenuationDistance", Infinity) === Infinity;
|
|
2704
|
+
if (f[a++] = Number(c), a++, "attenuationColor" in o ? (d[a++] = o.attenuationColor.r, d[a++] = o.attenuationColor.g, d[a++] = o.attenuationColor.b) : (d[a++] = 1, d[a++] = 1, d[a++] = 1), d[a++] = r(o, "attenuationDistance", Infinity), f[a++] = n(o, "alphaMap"), f[a++] = Number(r(o, "castShadow", !0)), d[a++] = o.opacity, d[a++] = o.alphaTest, !c && o.transmission > 0) d[a++] = 0;
|
|
2705
|
+
else switch (o.side) {
|
|
2706
|
+
case 0:
|
|
2707
|
+
d[a++] = 1;
|
|
2708
|
+
break;
|
|
2709
|
+
case 1:
|
|
2710
|
+
d[a++] = -1;
|
|
2711
|
+
break;
|
|
2712
|
+
case 2:
|
|
2713
|
+
d[a++] = 0;
|
|
2714
|
+
break;
|
|
2715
|
+
}
|
|
2716
|
+
f[a++] = Number(r(o, "matte", !1)), d[a++] = r(o, "sheen", 0), a++, "sheenColor" in o ? (d[a++] = o.sheenColor.r, d[a++] = o.sheenColor.g, d[a++] = o.sheenColor.b) : (d[a++] = 0, d[a++] = 0, d[a++] = 0), f[a++] = n(o, "sheenColorMap"), d[a++] = r(o, "sheenRoughness", 0), f[a++] = n(o, "sheenRoughnessMap"), f[a++] = Number(o.vertexColors), f[a++] = Number(o.flatShading), f[a++] = Number(o.transparent), f[a++] = 0, a++, a++, a += i(o, "map", d, a), a += i(o, "metalnessMap", d, a), a += i(o, "roughnessMap", d, a), a += i(o, "transmissionMap", d, a), a += i(o, "emissiveMap", d, a), a += i(o, "normalMap", d, a), a += i(o, "clearcoatMap", d, a), a += i(o, "clearcoatNormalMap", d, a), a += i(o, "clearcoatRoughnessMap", d, a), a += i(o, "sheenColorMap", d, a), a += i(o, "sheenRoughnessMap", d, a), a += i(o, "iridescenceMap", d, a), a += i(o, "iridescenceThicknessMap", d, a), a += i(o, "specularColorMap", d, a), a += i(o, "specularIntensityMap", d, a), a += i(o, "alphaMap", d, a);
|
|
2717
|
+
}
|
|
2718
|
+
return {
|
|
2719
|
+
materialData: d,
|
|
2720
|
+
textures: l
|
|
2721
|
+
};
|
|
2722
|
+
}
|
|
2723
|
+
writeTransformData(e, t, n, r) {
|
|
2724
|
+
super.writeTransformData(e, t, n, r);
|
|
2725
|
+
let { materials: i } = this, { object: a, instanceId: o, root: s } = e, c = a.material;
|
|
2726
|
+
if (Array.isArray(c)) {
|
|
2727
|
+
let { materialIndex: e } = a.geometry.groups[s];
|
|
2728
|
+
c = c[e];
|
|
2729
|
+
}
|
|
2730
|
+
let l = i.indexOf(c);
|
|
2731
|
+
l === -1 && (l = i.length, i.push(c));
|
|
2732
|
+
let u = new Uint32Array(r);
|
|
2733
|
+
u[n * Jn.getLength() + 34] = l, a.isInstancedMesh && a.instanceColor ? (a.getColorAt(o, qn), qn.w = 1) : a.isBatchedMesh && a._colorsTexture ? a.getColorAt(o, qn) : qn.setScalar(1);
|
|
2734
|
+
let d = new Float32Array(r);
|
|
2735
|
+
qn.toArray(d, n * Jn.getLength() + 36);
|
|
2736
|
+
}
|
|
2737
|
+
getBVH(e, t, n) {
|
|
2738
|
+
let { bvhMap: r } = this, i = super.getBVH(e, t, n);
|
|
2739
|
+
if (r.has(i)) {
|
|
2740
|
+
let e = r.get(i);
|
|
2741
|
+
if (Object.assign(n, e.range), i !== e.bvh && i instanceof ye) {
|
|
2742
|
+
let t = i.mesh, n = e.bvh.mesh;
|
|
2743
|
+
n.matrixWorld.copy(t.matrixWorld).decompose(n.position, n.quaternion, n.scale), i.refit();
|
|
2744
|
+
}
|
|
2745
|
+
return e.bvh;
|
|
2746
|
+
} else if (i.indirect) {
|
|
2747
|
+
let e = new y();
|
|
2748
|
+
e.attributes = i.geometry.attributes;
|
|
2749
|
+
let t;
|
|
2750
|
+
if (i.geometry.index) t = i.geometry.index.array.slice(n.start, n.count + n.start);
|
|
2751
|
+
else {
|
|
2752
|
+
let { start: e, count: r } = n;
|
|
2753
|
+
t = new Uint32Array(r);
|
|
2754
|
+
for (let r = 0, i = n.count; r < i; r++) t[r] = e + r;
|
|
2755
|
+
}
|
|
2756
|
+
e.index = new ee(t, 1), n.start = 0;
|
|
2757
|
+
let a;
|
|
2758
|
+
if (i instanceof ye) {
|
|
2759
|
+
let t = i.mesh, n = new p(e);
|
|
2760
|
+
n.copy(t), n.matrixWorld.copy(t.matrixWorld).decompose(n.position, n.quaternion, n.scale), a = new ye(n, {
|
|
2761
|
+
strategy: 2,
|
|
2762
|
+
maxLeafSize: 5
|
|
2763
|
+
});
|
|
2764
|
+
} else a = new ve(e, {
|
|
2765
|
+
strategy: 2,
|
|
2766
|
+
maxLeafSize: 5
|
|
2767
|
+
});
|
|
2768
|
+
return r.set(i, {
|
|
2769
|
+
bvh: a,
|
|
2770
|
+
range: { ...n }
|
|
2771
|
+
}), a;
|
|
2772
|
+
} else return i;
|
|
2773
|
+
}
|
|
2774
|
+
}, Xn = class extends me {
|
|
2775
|
+
set texture(e) {
|
|
2776
|
+
this._texNode.value = e;
|
|
2777
|
+
}
|
|
2778
|
+
set layer(e) {
|
|
2779
|
+
this._layerUniform.value = e;
|
|
2780
|
+
}
|
|
2781
|
+
constructor() {
|
|
2782
|
+
super(), this.blending = 0, this._texNode = F(new f()), this._layerUniform = A(0), this.colorNode = I("\n fn atlasDebug( tex: texture_2d_array<f32>, coord: vec2f, layer: f32 ) -> vec4f {\n\n // flip y so texel origin shows at the top-left\n let dims = vec2f( textureDimensions( tex, 0 ).xy );\n let texel = vec2i( vec2f( coord.x, 1.0 - coord.y ) * dims );\n return textureLoad( tex, texel, i32( layer ), 0 );\n\n }\n ")(this._texNode, xe(we()), this._layerUniform);
|
|
2783
|
+
}
|
|
2784
|
+
};
|
|
2785
|
+
//#endregion
|
|
2786
|
+
//#region ../../node_modules/three-gpu-pathtracer/src/core/utils/GeometryPreparationUtils.js
|
|
2787
|
+
function Zn(e, t) {
|
|
2788
|
+
if (!e.index) {
|
|
2789
|
+
let t = e.attributes.position.count, n = Array(t);
|
|
2790
|
+
for (let e = 0; e < t; e++) n[e] = e;
|
|
2791
|
+
e.setIndex(n);
|
|
2792
|
+
}
|
|
2793
|
+
if (!e.attributes.normal && t && t.includes("normal") && e.computeVertexNormals(), !e.attributes.uv && t && t.includes("uv")) {
|
|
2794
|
+
let t = e.attributes.position.count;
|
|
2795
|
+
e.setAttribute("uv", new ee(new Float32Array(t * 2), 2, !1));
|
|
2796
|
+
}
|
|
2797
|
+
if (!e.attributes.uv2 && t && t.includes("uv2")) {
|
|
2798
|
+
let t = e.attributes.position.count;
|
|
2799
|
+
e.setAttribute("uv2", new ee(new Float32Array(t * 2), 2, !1));
|
|
2800
|
+
}
|
|
2801
|
+
if (!e.attributes.tangent && t && t.includes("tangent")) if (e.attributes.uv && e.attributes.normal) e.computeTangents();
|
|
2802
|
+
else {
|
|
2803
|
+
let t = e.attributes.position.count;
|
|
2804
|
+
e.setAttribute("tangent", new ee(new Float32Array(t * 4), 4, !1));
|
|
2805
|
+
}
|
|
2806
|
+
if (!e.attributes.color && t && t.includes("color")) {
|
|
2807
|
+
let t = e.attributes.position.count, n = new Float32Array(t * 4);
|
|
2808
|
+
n.fill(1), e.setAttribute("color", new ee(n, 4));
|
|
2809
|
+
}
|
|
2810
|
+
}
|
|
2811
|
+
//#endregion
|
|
2812
|
+
//#region ../../node_modules/three-gpu-pathtracer/src/webgpu/materials/PathtracingMaterial.js
|
|
2813
|
+
var Qn = class {
|
|
2814
|
+
init() {}
|
|
2815
|
+
getBsdfNode() {
|
|
2816
|
+
return W`
|
|
2817
|
+
|
|
2818
|
+
fn bsdfSample( worldWo: vec3f, surf: SurfaceRecord ) -> ScatterRecord {
|
|
2819
|
+
|
|
2820
|
+
var record: ScatterRecord;
|
|
2821
|
+
|
|
2822
|
+
let wo = normalize( surf.normalInvBasis * worldWo );
|
|
2823
|
+
let wi = ${Jt}( wo, ${Y}( ${3} ) );
|
|
2824
|
+
record.color = surf.color * max( wi.z, 0.0 );
|
|
2825
|
+
record.pdf = max( wi.z, 0.0 ) / PI;
|
|
2826
|
+
record.direction = normalize( surf.normalBasis * wi );
|
|
2827
|
+
|
|
2828
|
+
return record;
|
|
2829
|
+
|
|
2830
|
+
}
|
|
2831
|
+
|
|
2832
|
+
`;
|
|
2833
|
+
}
|
|
2834
|
+
getData() {
|
|
2835
|
+
return { bsdfSample: this.getBsdfNode() };
|
|
2836
|
+
}
|
|
2837
|
+
}, $n = new URL("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACsUlEQVR4AcTWjXISMRiF4WTb3v+1dqblH5QnzsGPdUF0tDDzepLdJe9JEGX69uTXdDqd2jNf0/v7e1PifBBP6TGtVqu22+0uJb66yNR7b0rs9/t2PB6bAnP+59FMb29vbbvdts1m01KiFiGfFzJ3/V8wvb6+jp0rAR/H4XAY1/zdAGGINPO/yawhR4HeeyMlh5OAkwgpkqxiC/0J9b3T+dXgIqkCMIZiKSEVCN4Dc/kI86Jn9zQKuGEhQmIlYAzXFQieDcR1bP4o41vw8vLSeu/jG0BABmIYVzwzJwVcz1jOi7gW3BsFeu+jgFNw0SIRKlBPwjx4xrMVi5vLW3DA/VHg/DmMAr3/OAU3LUIAQiVgjFw3hnnw3iUI4Z7EZNe9/zwBczfgwSwqiaAIjCueCa5nbJ1bjAKkvXcxcAIp4I0WyoIyKAFzGczn1DWMw6XAMJ//IIcCUADeUBetsoxr1meN3ZNzfilw7jC+DSkRuQKoC1h0Cf+izll6zlqXAoQVu4cCqPIsZoG56JG59+c5v4jGjrNz0kBcUQLEFqlkwZr+g7uF59xbPIEUkAqQBvKQAhYLFr3Her1uwXOjgKMnSxoTVxSIWN6SK2JhkqQx/O6QMMblI6hyBZAC5IE83CpBDKIkmbmsjAJklYjlI2JFsvMIyVBln5+f49eXDFcfgRKkiLhmdi5JQ+RJJaBASJGIk+MEcvzElcgJQ6TJSJOES3LXU0Iq8PHx0UYBO0fkESeX5IQVUrhGFsgqxJXxEZCHeYnIa2b3kjAoEFIgeavEOIH6EWTX8p50LleCnFDCONQCGTuJUcDus3NJHmoJY2IQBjLM566lQDJyeVUgJX4nJg8RJgmXiDxJDvOrEyCvJ2DHIdIkqbEEcdI4kNRx5hJXBe7JFalCsntE6pmMk8TG8jsAAAD//yGAaM0AAAAGSURBVAMAifCfleVLEBEAAAAASUVORK5CYII=", "" + import.meta.url).toString(), er = await new ne().loadAsync($n), tr = M(1.5), nr = M(.001), rr = class extends Qn {
|
|
2838
|
+
constructor(e = {}) {
|
|
2839
|
+
super();
|
|
2840
|
+
let { specularBrdf: t = jn, diffuseBrdf: n = An, fresnelMix: r = Mn, conductorFresnel: i = Ln, fresnelCoat: a = Rn, iridescentDielectricLayer: o = Fn, iridescentConductorLayer: s = In, calculateTurquinTexture: c = !1 } = e;
|
|
2841
|
+
c ? (this.turquinTexture = new O(32, 32), this.turquinTexture.type = b) : (this.turquinTexture = er, this.turquinTexture.flipY = !1), this.turquinTexture.format = S, this.turquinTexture.minFilter = w, this.turquinTexture.magFilter = w;
|
|
2842
|
+
let l = F(this.turquinTexture).setName("turquinTexture");
|
|
2843
|
+
this.specularBrdf = t, this.diffuseBrdf = n, this.fresnelMix = r, this.conductorFresnel = i(l), this.fresnelCoat = a, this.iridescentDielectricLayer = o, this.iridescentConductorLayer = s, this.calculateTurquinTexture = c;
|
|
2844
|
+
}
|
|
2845
|
+
init(e) {
|
|
2846
|
+
if (!this.calculateTurquinTexture) return;
|
|
2847
|
+
let t = new q(zn({
|
|
2848
|
+
texture: j(this.turquinTexture).toWriteOnly(),
|
|
2849
|
+
globalId: N
|
|
2850
|
+
}), { workgroupSize: [
|
|
2851
|
+
16,
|
|
2852
|
+
16,
|
|
2853
|
+
1
|
|
2854
|
+
] });
|
|
2855
|
+
e.compute(t.kernel, [
|
|
2856
|
+
2,
|
|
2857
|
+
2,
|
|
2858
|
+
1
|
|
2859
|
+
]);
|
|
2860
|
+
}
|
|
2861
|
+
getBsdfNode() {
|
|
2862
|
+
return W`
|
|
2863
|
+
|
|
2864
|
+
fn bsdfSample( worldWo: vec3f, surf: ${Mt} ) -> ${At} {
|
|
2865
|
+
|
|
2866
|
+
var result: ${At};
|
|
2867
|
+
result.pdf = 0.0;
|
|
2868
|
+
|
|
2869
|
+
let alpha = surf.roughness * surf.roughness;
|
|
2870
|
+
let clearcoatAlpha = surf.clearcoatRoughness * surf.clearcoatRoughness;
|
|
2871
|
+
|
|
2872
|
+
let normalBasis = surf.normalBasis;
|
|
2873
|
+
let invBasis = surf.normalInvBasis;
|
|
2874
|
+
let clearcoatBasis = surf.clearcoatBasis;
|
|
2875
|
+
let invClearcoatBasis = surf.clearcoatInvBasis;
|
|
2876
|
+
|
|
2877
|
+
let wo = normalize( invBasis * worldWo );
|
|
2878
|
+
let woClearcoat = normalize( invClearcoatBasis * worldWo );
|
|
2879
|
+
|
|
2880
|
+
// TODO: handle such intersections better;
|
|
2881
|
+
// Sometimes .z < 0.0 on a pretty round surface e.g. sphere
|
|
2882
|
+
// Disabling this condition leads to more fireflies on ClearCoatCarPaint example
|
|
2883
|
+
// This could also be fixed by offsetting rays by 1e-1
|
|
2884
|
+
// Also, this will be an invalid condition when transmission is implemented
|
|
2885
|
+
if ( wo.z < 0.0 || woClearcoat.z < 0.0 ) {
|
|
2886
|
+
|
|
2887
|
+
return result;
|
|
2888
|
+
|
|
2889
|
+
}
|
|
2890
|
+
|
|
2891
|
+
let weights = ${Yt}( wo, woClearcoat, vec3( 0, 0, 1 ), ${tr}, surf );
|
|
2892
|
+
|
|
2893
|
+
var cdf: vec4f;
|
|
2894
|
+
cdf.x = weights.diffuse;
|
|
2895
|
+
cdf.y = weights.specular + cdf.x;
|
|
2896
|
+
cdf.z = weights.clearcoat + cdf.y;
|
|
2897
|
+
cdf.w = 0; // weights.transmission + cdf.z;
|
|
2898
|
+
|
|
2899
|
+
let r = ${Dt}( ${2} ) * cdf.z;
|
|
2900
|
+
|
|
2901
|
+
let directionUV = ${Y}( ${3} );
|
|
2902
|
+
var wi: vec3f;
|
|
2903
|
+
var wiClearcoat: vec3f;
|
|
2904
|
+
var wh: vec3f;
|
|
2905
|
+
var whClearcoat: vec3f;
|
|
2906
|
+
|
|
2907
|
+
if ( r <= cdf.x ) { // diffuse
|
|
2908
|
+
|
|
2909
|
+
wi = ${Jt}( wo, directionUV );
|
|
2910
|
+
wh = normalize( wi + wo );
|
|
2911
|
+
|
|
2912
|
+
wiClearcoat = normalize( invClearcoatBasis * normalBasis * wi );
|
|
2913
|
+
whClearcoat = normalize( invClearcoatBasis * normalBasis * wh );
|
|
2914
|
+
|
|
2915
|
+
} else if ( r <= cdf.y ) { // specular
|
|
2916
|
+
|
|
2917
|
+
wh = ${Cn}( wo, vec2( alpha ), directionUV );
|
|
2918
|
+
wi = - normalize( reflect( wo, wh ) );
|
|
2919
|
+
|
|
2920
|
+
wiClearcoat = normalize( invClearcoatBasis * normalBasis * wi );
|
|
2921
|
+
whClearcoat = normalize( invClearcoatBasis * normalBasis * wh );
|
|
2922
|
+
|
|
2923
|
+
} else if ( r <= cdf.z ) { // clearcoat
|
|
2924
|
+
|
|
2925
|
+
whClearcoat = ${Cn}( woClearcoat, vec2( clearcoatAlpha ), directionUV );
|
|
2926
|
+
wiClearcoat = - normalize( reflect( woClearcoat, whClearcoat ) );
|
|
2927
|
+
|
|
2928
|
+
wi = normalize( invBasis * clearcoatBasis * wiClearcoat );
|
|
2929
|
+
wh = normalize( invBasis * clearcoatBasis * whClearcoat );
|
|
2930
|
+
|
|
2931
|
+
} else if ( r <= cdf.w ) { // transmission / refraction
|
|
2932
|
+
|
|
2933
|
+
// NOT IMPLEMENTED
|
|
2934
|
+
|
|
2935
|
+
}
|
|
2936
|
+
|
|
2937
|
+
var ctx: ${Ft};
|
|
2938
|
+
ctx.NdotV = max( wo.z, ${nr} );
|
|
2939
|
+
ctx.NdotL = max( wi.z, ${nr} );
|
|
2940
|
+
ctx.NdotH = saturate( wh.z );
|
|
2941
|
+
ctx.VdotH = saturate( dot( wo, wh ) );
|
|
2942
|
+
|
|
2943
|
+
ctx.VdotNc = max( woClearcoat.z, ${nr} );
|
|
2944
|
+
ctx.LdotNc = max( wiClearcoat.z, ${nr} );
|
|
2945
|
+
ctx.HdotNc = saturate( whClearcoat.z );
|
|
2946
|
+
|
|
2947
|
+
if ( weights.diffuse > 0.0 ) {
|
|
2948
|
+
|
|
2949
|
+
result.pdf += weights.diffuse * max( wi.z, 0.0 ) / PI;
|
|
2950
|
+
|
|
2951
|
+
}
|
|
2952
|
+
|
|
2953
|
+
if ( weights.specular > 0.0 && wi.z > 0.0 ) {
|
|
2954
|
+
|
|
2955
|
+
result.pdf += weights.specular * ${On}( ctx.NdotV, ctx.NdotH, alpha );
|
|
2956
|
+
|
|
2957
|
+
}
|
|
2958
|
+
|
|
2959
|
+
if ( weights.clearcoat > 0.0 && wiClearcoat.z > 0.0 ) {
|
|
2960
|
+
|
|
2961
|
+
result.pdf += weights.clearcoat * ${On}( ctx.VdotNc, ctx.HdotNc, clearcoatAlpha );
|
|
2962
|
+
|
|
2963
|
+
}
|
|
2964
|
+
|
|
2965
|
+
result.color = ${W`
|
|
2966
|
+
|
|
2967
|
+
fn bsdfEval( ctx: ${Ft}, surf: ${Mt} ) -> vec3f {
|
|
2968
|
+
|
|
2969
|
+
let alpha = surf.roughness * surf.roughness;
|
|
2970
|
+
|
|
2971
|
+
let specular = ${this.specularBrdf}( ctx.NdotL, ctx.NdotV, ctx.NdotH, alpha );
|
|
2972
|
+
let diffuse = ${this.diffuseBrdf}( ctx.NdotV, ctx.NdotL, ctx.VdotH, surf );
|
|
2973
|
+
let dielectricBase = ${this.fresnelMix}( ctx.VdotH, surf.ior, diffuse, specular );
|
|
2974
|
+
|
|
2975
|
+
let dielectric = ${this.iridescentDielectricLayer}(
|
|
2976
|
+
dielectricBase, diffuse, specular, ctx.VdotH, /* outsideIor */ 1.0,
|
|
2977
|
+
surf.ior, surf.iridescenceIor, surf.iridescenceThickness, surf.iridescence
|
|
2978
|
+
);
|
|
2979
|
+
|
|
2980
|
+
let metallicBase = ${this.conductorFresnel}( ctx.NdotV, ctx.VdotH, surf.color, specular, alpha );
|
|
2981
|
+
|
|
2982
|
+
let metallic = ${this.iridescentConductorLayer}(
|
|
2983
|
+
metallicBase, specular, surf.color, ctx.VdotH, /* outsideIor */ 1.0,
|
|
2984
|
+
surf.iridescenceIor, surf.iridescenceThickness, surf.iridescence
|
|
2985
|
+
);
|
|
2986
|
+
|
|
2987
|
+
let material = mix( dielectric, metallic, surf.metalness );
|
|
2988
|
+
|
|
2989
|
+
let clearcoatAlpha = surf.clearcoatRoughness * surf.clearcoatRoughness;
|
|
2990
|
+
let clearcoat = ${this.specularBrdf}( ctx.LdotNc, ctx.VdotNc, ctx.HdotNc, clearcoatAlpha );
|
|
2991
|
+
|
|
2992
|
+
let coatedMaterial = ${this.fresnelCoat}( ctx.VdotNc, ${tr}, material, clearcoat, surf.clearcoat );
|
|
2993
|
+
|
|
2994
|
+
return coatedMaterial;
|
|
2995
|
+
|
|
2996
|
+
}
|
|
2997
|
+
|
|
2998
|
+
`}( ctx, surf );
|
|
2999
|
+
result.color *= max( 0.0, wi.z );
|
|
3000
|
+
result.direction = normalize( normalBasis * wi );
|
|
3001
|
+
|
|
3002
|
+
return result;
|
|
3003
|
+
|
|
3004
|
+
}
|
|
3005
|
+
|
|
3006
|
+
`;
|
|
3007
|
+
}
|
|
3008
|
+
}, $ = new l(), ir = new ie(), ar = class {
|
|
3009
|
+
get bounces() {
|
|
3010
|
+
return this._pathTracer.bounces;
|
|
3011
|
+
}
|
|
3012
|
+
set bounces(e) {
|
|
3013
|
+
this._pathTracer.bounces = e, this._pathTracer.reset();
|
|
3014
|
+
}
|
|
3015
|
+
get samples() {
|
|
3016
|
+
return this._pathTracer.samples;
|
|
3017
|
+
}
|
|
3018
|
+
get fadeState() {
|
|
3019
|
+
return this._fadeState;
|
|
3020
|
+
}
|
|
3021
|
+
get textureAtlas() {
|
|
3022
|
+
return this._bvhData.textureAtlas;
|
|
3023
|
+
}
|
|
3024
|
+
useMegakernel(e) {
|
|
3025
|
+
this._pathTracer.dispose(), this._pathTracer = e ? new sn(this._renderer) : new vn(this._renderer), this._pathTracer.setBVHData(this._bvhData), this._pathTracer.setMaterial(this.material), this.setCamera(this.camera), this.updateEnvironment();
|
|
3026
|
+
}
|
|
3027
|
+
constructor(e) {
|
|
3028
|
+
this._renderer = e, this._timer = new g(), this._envColorTexture = new f(), this._envColorTexture.image.data = new Uint8Array([
|
|
3029
|
+
255,
|
|
3030
|
+
255,
|
|
3031
|
+
255,
|
|
3032
|
+
255
|
|
3033
|
+
]), this._envColorTexture.needsUpdate = !0, this._envColorTexture.minFilter = w, this._envColorTexture.magFilter = w, this._backgroundColorTexture = new f(), this._backgroundColorTexture.image.data = new Uint8Array([
|
|
3034
|
+
255,
|
|
3035
|
+
255,
|
|
3036
|
+
255,
|
|
3037
|
+
255
|
|
3038
|
+
]), this._backgroundColorTexture.needsUpdate = !0, this._backgroundColorTexture.minFilter = w, this._backgroundColorTexture.magFilter = w, this._resetTime = -1, this._fadeState = 0, this._size = new l(), this._blitQuad = new oe(new ft()), this._lowResTarget = new O(1, 1), this._lowResTarget.type = v, this._lowResTarget.generateMipmaps = !1, this.minSamples = 1, this.renderDelay = 500, this.fadeDuration = 500, this.dynamicLowRes = !0, this.lowResScale = .2, this.renderScale = 1, this.synchronizeRenderSize = !0, this.generateMissingAttributes = !0, this.commonAttributes = [
|
|
3039
|
+
"normal",
|
|
3040
|
+
"uv",
|
|
3041
|
+
"tangent",
|
|
3042
|
+
"color"
|
|
3043
|
+
], this.material = new rr(), this._pathTracer = new sn(e), this.setScene(new a(), new s());
|
|
3044
|
+
}
|
|
3045
|
+
setScene(e, t) {
|
|
3046
|
+
e.updateMatrixWorld(!0), t.updateMatrixWorld(), e.traverse((e) => {
|
|
3047
|
+
this.generateMissingAttributes && e.geometry?.isBufferGeometry && Zn(e.geometry, this.commonAttributes), e.isSkinnedMesh ? e.boundsTree ? e.boundsTree.refit() : e.boundsTree = new ye(e, {
|
|
3048
|
+
strategy: 2,
|
|
3049
|
+
maxLeafSize: 5,
|
|
3050
|
+
indirect: !0
|
|
3051
|
+
}) : e.isMesh && (e.geometry.boundsTree || (e.geometry.boundsTree = new ve(e.geometry, {
|
|
3052
|
+
strategy: 2,
|
|
3053
|
+
maxLeafSize: 5
|
|
3054
|
+
})));
|
|
3055
|
+
});
|
|
3056
|
+
let n = new Yn(e);
|
|
3057
|
+
n.update(), n.textureAtlas.setTextures(this._renderer, n.textures), this.scene = e, this._bvhData = n, this._pathTracer.setBVHData(n), this.setCamera(t), this.updateEnvironment();
|
|
3058
|
+
}
|
|
3059
|
+
getMaterial() {
|
|
3060
|
+
return this.material;
|
|
3061
|
+
}
|
|
3062
|
+
setMaterial(e) {
|
|
3063
|
+
this.material = e, this._pathTracer.setMaterial(e);
|
|
3064
|
+
}
|
|
3065
|
+
setSceneAsync(...e) {
|
|
3066
|
+
this.setScene(...e);
|
|
3067
|
+
}
|
|
3068
|
+
setCamera(e) {
|
|
3069
|
+
this.camera = e, this.updateCamera();
|
|
3070
|
+
}
|
|
3071
|
+
updateCamera() {
|
|
3072
|
+
let e = this.camera;
|
|
3073
|
+
e.updateMatrixWorld(), this._pathTracer.setCamera(e), this.reset();
|
|
3074
|
+
}
|
|
3075
|
+
updateEnvironment() {
|
|
3076
|
+
let { _renderer: e, _pathTracer: t, scene: n, _envColorTexture: r, _backgroundColorTexture: i } = this, a = or(e, n.environment || ir.set(0), r), o = or(e, n.background, i);
|
|
3077
|
+
t.setEnvironment(a, n.environmentIntensity, n.environmentRotation, o, n.backgroundIntensity, n.backgroundRotation, n.backgroundBlurriness);
|
|
3078
|
+
}
|
|
3079
|
+
setSize(e, t) {
|
|
3080
|
+
(this._size.x !== e || this._size.y !== t) && (this._size.set(e, t), this.reset());
|
|
3081
|
+
}
|
|
3082
|
+
reset() {
|
|
3083
|
+
this._pathTracer.reset(), this._resetTime = 0, this._fadeState = 0;
|
|
3084
|
+
}
|
|
3085
|
+
renderSample() {
|
|
3086
|
+
let e = this._renderer, t = this._size, n = this._blitQuad, r = this._pathTracer, i = this._lowResTarget, a = this._timer, { renderDelay: o, dynamicLowRes: s, synchronizeRenderSize: c, renderScale: l, lowResScale: u, minSamples: d } = this;
|
|
3087
|
+
if (a.update(), !this._renderer._initialized) return;
|
|
3088
|
+
this.material.initialized || (this.material.init(e), this.material.initialized = !0);
|
|
3089
|
+
let f = 1e3 * a.getDelta();
|
|
3090
|
+
this._resetTime += f;
|
|
3091
|
+
let p = e.toneMapping, m = e.toneMappingExposure, h = e.getRenderTarget(), g = e.autoClear;
|
|
3092
|
+
if (e.toneMapping = 0, e.toneMappingExposure = 1, c) {
|
|
3093
|
+
e.getDrawingBufferSize($);
|
|
3094
|
+
let t = Math.floor(l * $.x), n = Math.floor(l * $.y);
|
|
3095
|
+
this.setSize(t, n);
|
|
3096
|
+
}
|
|
3097
|
+
let { width: _, height: v } = t, y = this._resetTime < o;
|
|
3098
|
+
y && (_ = Math.ceil(u * _), v = Math.ceil(u * v)), r.getSize($), ($.x !== _ || $.y !== v) && (!y && s && (i.setSize(Math.ceil(u * _), Math.ceil(u * v)), e.copyTextureToTexture(r.outputTarget, i)), r.setSize(_, v)), !y && r.samples >= d && (this._fadeState += f / this.fadeDuration, this._fadeState = Math.min(1, this._fadeState)), (!y || y && s) && (r.lowResMode = y, r.update());
|
|
3099
|
+
let b = y && s ? 1 : this._fadeState;
|
|
3100
|
+
e.autoClear = s ? !0 : b === 1, n.material.transition = s ? b : 1, n.material.opacity = s ? 1 : b, n.material.fromTexture = i, n.material.texture = r.outputTarget, n.material.toneMapping = p, n.material.toneMappingExposure = m, n.render(e), e.autoClear = g, e.toneMapping = p, e.toneMappingExposure = m, e.setRenderTarget(h);
|
|
3101
|
+
}
|
|
3102
|
+
renderTextureAtlas(e = 0) {
|
|
3103
|
+
let t = this._renderer;
|
|
3104
|
+
if (!t._initialized) return;
|
|
3105
|
+
this._atlasDebugQuad ||= new oe(new Xn());
|
|
3106
|
+
let n = this._atlasDebugQuad;
|
|
3107
|
+
n.material.texture = this.textureAtlas.texture, n.material.layer = e, t.setRenderTarget(null), n.render(t);
|
|
3108
|
+
}
|
|
3109
|
+
dispose() {
|
|
3110
|
+
this._pathTracer.dispose(), this._blitQuad.dispose(), this._lowResTarget.dispose(), this._envColorTexture.dispose(), this._backgroundColorTexture.dispose(), this._atlasDebugQuad?.dispose();
|
|
3111
|
+
}
|
|
3112
|
+
async getDetailedSampleCount() {
|
|
3113
|
+
let e = this._pathTracer.sampleCountTarget, { width: t, height: n } = e, r = this._renderer, i = { textures: [e] }, a = await r.readRenderTargetPixelsAsync(i, 0, 0, t, n), o = new Uint32Array(a.buffer), s = Math.ceil(t / 64) * 64, c = 0, l = Number.MAX_VALUE, u = -Number.MAX_VALUE;
|
|
3114
|
+
for (let e = 0, n = o.length; e < n; e++) {
|
|
3115
|
+
if (e % s >= t) continue;
|
|
3116
|
+
let n = o[e] & 268435455;
|
|
3117
|
+
c += n, l = Math.min(l, n), u = Math.max(u, n);
|
|
3118
|
+
}
|
|
3119
|
+
return {
|
|
3120
|
+
min: l,
|
|
3121
|
+
max: u,
|
|
3122
|
+
avg: Math.floor(c / (t * n))
|
|
3123
|
+
};
|
|
3124
|
+
}
|
|
3125
|
+
getRenderTime() {
|
|
3126
|
+
return this._resetTime;
|
|
3127
|
+
}
|
|
3128
|
+
};
|
|
3129
|
+
function or(e, t, n) {
|
|
3130
|
+
if (t) t.isColor ? (n.image.data[0] = t.r * 255, n.image.data[1] = t.g * 255, n.image.data[2] = t.b * 255, n.image.data[3] = 255, n.needsUpdate = !0, t = n) : t?.isCubeTexture && (t = new xn(e).generate(t));
|
|
3131
|
+
else {
|
|
3132
|
+
let r = e.getClearAlpha();
|
|
3133
|
+
e.getClearColor(ir), n.image.data[0] = ir.r * 255, n.image.data[1] = ir.g * 255, n.image.data[2] = ir.b * 255, n.image.data[3] = r * 255, n.needsUpdate = !0, t = n;
|
|
3134
|
+
}
|
|
3135
|
+
return t;
|
|
3136
|
+
}
|
|
3137
|
+
//#endregion
|
|
3138
|
+
export { ar as WebGPUPathTracer };
|
|
3139
|
+
|
|
3140
|
+
//# sourceMappingURL=webgpu-BHAP6BLI.mjs.map
|