@rosalana/sandbox 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +135 -3
- package/dist/errors/base.d.ts +1 -1
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/texture.d.ts +12 -0
- package/dist/index.cjs.js +23 -23
- package/dist/index.d.ts +57 -1
- package/dist/index.es.js +899 -571
- package/dist/tools/texture.d.ts +64 -0
- package/dist/tools/textures.d.ts +48 -0
- package/dist/tools/web_gl.d.ts +14 -1
- package/dist/types.d.ts +33 -0
- package/package.json +1 -1
package/dist/index.es.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
class
|
|
5
|
-
constructor(e,
|
|
6
|
-
this.target = e, this.type =
|
|
1
|
+
var N = Object.defineProperty;
|
|
2
|
+
var G = (u, e, t) => e in u ? N(u, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : u[e] = t;
|
|
3
|
+
var o = (u, e, t) => G(u, typeof e != "symbol" ? e + "" : e, t);
|
|
4
|
+
class b {
|
|
5
|
+
constructor(e, t, n, i) {
|
|
6
|
+
this.target = e, this.type = t, this.listener = n, this.options = i, this.target.addEventListener(
|
|
7
7
|
this.type,
|
|
8
8
|
this.listener,
|
|
9
9
|
this.options
|
|
@@ -16,23 +16,23 @@ class x {
|
|
|
16
16
|
this.options
|
|
17
17
|
);
|
|
18
18
|
}
|
|
19
|
-
static on(e,
|
|
20
|
-
return e.addEventListener(
|
|
19
|
+
static on(e, t, n, i) {
|
|
20
|
+
return e.addEventListener(t, n, i), () => e.removeEventListener(t, n, i);
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
class h extends Error {
|
|
24
|
-
constructor(
|
|
25
|
-
super(
|
|
26
|
-
|
|
27
|
-
this.code =
|
|
24
|
+
constructor(t, n) {
|
|
25
|
+
super(t);
|
|
26
|
+
o(this, "name", "SandboxError");
|
|
27
|
+
this.code = n;
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
-
class
|
|
30
|
+
class W extends h {
|
|
31
31
|
constructor() {
|
|
32
32
|
super("WebGL is not supported in this browser.", "CONTEXT_ERROR");
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
-
class
|
|
35
|
+
class ve extends h {
|
|
36
36
|
constructor() {
|
|
37
37
|
super(
|
|
38
38
|
"Failed to create WebGL context. The GPU may be unavailable.",
|
|
@@ -40,72 +40,72 @@ class de extends h {
|
|
|
40
40
|
);
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
-
class
|
|
44
|
-
constructor(e,
|
|
43
|
+
class z extends h {
|
|
44
|
+
constructor(e, t) {
|
|
45
45
|
super(
|
|
46
|
-
`Vertex and fragment shader WebGL versions do not match (${e} vs ${
|
|
46
|
+
`Vertex and fragment shader WebGL versions do not match (${e} vs ${t})`,
|
|
47
47
|
"VALIDATION_ERROR"
|
|
48
|
-
), this.vertexVersion = e, this.fragmentVersion =
|
|
48
|
+
), this.vertexVersion = e, this.fragmentVersion = t;
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
class _ extends h {
|
|
52
|
-
constructor(
|
|
52
|
+
constructor(t, n, i) {
|
|
53
53
|
const r = _.parseErrorLines(i), s = r.length > 0 ? ` at line(s): ${r.join(", ")}` : "";
|
|
54
54
|
super(
|
|
55
|
-
`${
|
|
55
|
+
`${t} shader compilation failed${s}
|
|
56
56
|
|
|
57
57
|
${i}`,
|
|
58
58
|
"SHADER_ERROR"
|
|
59
59
|
);
|
|
60
|
-
|
|
61
|
-
this.shaderType =
|
|
60
|
+
o(this, "lines");
|
|
61
|
+
this.shaderType = t, this.source = n, this.infoLog = i, this.lines = r;
|
|
62
62
|
}
|
|
63
|
-
static parseErrorLines(
|
|
64
|
-
const
|
|
63
|
+
static parseErrorLines(t) {
|
|
64
|
+
const n = [
|
|
65
65
|
/ERROR:\s*\d*:(\d+)/g,
|
|
66
66
|
/(\d+):(\d+)\(\d+\):/g,
|
|
67
67
|
/^(\d+):/gm
|
|
68
68
|
], i = /* @__PURE__ */ new Set();
|
|
69
|
-
for (const r of
|
|
69
|
+
for (const r of n) {
|
|
70
70
|
let s;
|
|
71
|
-
for (; (s = r.exec(
|
|
72
|
-
const
|
|
73
|
-
|
|
71
|
+
for (; (s = r.exec(t)) !== null; ) {
|
|
72
|
+
const a = parseInt(s[1], 10);
|
|
73
|
+
a > 0 && i.add(a);
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
return [...i].sort((r, s) => r - s);
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
|
-
class
|
|
80
|
-
constructor(e,
|
|
79
|
+
class U extends h {
|
|
80
|
+
constructor(e, t, n, i) {
|
|
81
81
|
super(
|
|
82
|
-
`The shader ${e} "${
|
|
82
|
+
`The shader ${e} "${t}" has type "${i}" but expected "${n}"`,
|
|
83
83
|
"SHADER_ERROR"
|
|
84
|
-
), this.requirement = e, this.name =
|
|
84
|
+
), this.requirement = e, this.name = t, this.expectedType = n, this.actualType = i;
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
|
-
class
|
|
87
|
+
class H extends h {
|
|
88
88
|
constructor() {
|
|
89
89
|
super("Shader source does not contain any function.", "SHADER_ERROR");
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
class q extends h {
|
|
93
|
-
constructor(e,
|
|
93
|
+
constructor(e, t) {
|
|
94
94
|
super(
|
|
95
|
-
`Syntax error in shader import statement at line ${e}: ${
|
|
95
|
+
`Syntax error in shader import statement at line ${e}: ${t}`,
|
|
96
96
|
"SHADER_ERROR"
|
|
97
|
-
), this.line = e, this.details =
|
|
97
|
+
), this.line = e, this.details = t;
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
|
-
class
|
|
101
|
-
constructor(e,
|
|
100
|
+
class j extends h {
|
|
101
|
+
constructor(e, t) {
|
|
102
102
|
super(
|
|
103
|
-
`Duplicate import name "${e}" found at line ${
|
|
103
|
+
`Duplicate import name "${e}" found at line ${t}. Each import must have a unique name.`,
|
|
104
104
|
"SHADER_ERROR"
|
|
105
|
-
), this.name = e, this.line =
|
|
105
|
+
), this.name = e, this.line = t;
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
|
-
class
|
|
108
|
+
class X extends h {
|
|
109
109
|
constructor(e) {
|
|
110
110
|
super(
|
|
111
111
|
`Can not find module '${e}'. Check if it is defined before usage or if the name is correct.`,
|
|
@@ -114,11 +114,11 @@ class j extends h {
|
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
class Y extends h {
|
|
117
|
-
constructor(e,
|
|
117
|
+
constructor(e, t) {
|
|
118
118
|
super(
|
|
119
|
-
`Method '${
|
|
119
|
+
`Method '${t}' not found in shader module '${e}'. Check if the method is defined in the module source code or if the name is correct.`,
|
|
120
120
|
"MODULE_ERROR"
|
|
121
|
-
), this.moduleName = e, this.methodName =
|
|
121
|
+
), this.moduleName = e, this.methodName = t;
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
class K extends h {
|
|
@@ -129,7 +129,7 @@ class K extends h {
|
|
|
129
129
|
), this.moduleName = e;
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
|
-
class
|
|
132
|
+
class Q extends h {
|
|
133
133
|
constructor(e) {
|
|
134
134
|
super(
|
|
135
135
|
`Name 'default' is reserved and cannot be used as a function name in module '${e}'.`,
|
|
@@ -137,7 +137,7 @@ class X extends h {
|
|
|
137
137
|
), this.moduleName = e;
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
|
-
class
|
|
140
|
+
class J extends h {
|
|
141
141
|
constructor(e) {
|
|
142
142
|
super(
|
|
143
143
|
`Module name '${e}' is not allowed. Module names cannot be 'sandbox' or start with 'sandbox/'.`,
|
|
@@ -145,7 +145,7 @@ class Q extends h {
|
|
|
145
145
|
), this.moduleName = e;
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
|
-
class
|
|
148
|
+
class Z extends h {
|
|
149
149
|
constructor(e) {
|
|
150
150
|
super(
|
|
151
151
|
`Module '${e}' is already defined. Overwriting existing modules is not allowed.`,
|
|
@@ -153,64 +153,84 @@ class J extends h {
|
|
|
153
153
|
), this.moduleName = e;
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
|
-
class
|
|
157
|
-
constructor(e,
|
|
156
|
+
class ee extends h {
|
|
157
|
+
constructor(e, t, n) {
|
|
158
158
|
super(
|
|
159
|
-
`Uniform '${
|
|
159
|
+
`Uniform '${n}' mentioned for function '${t}' of module '${e}' was not found among the module's declared uniforms. Check if the uniform is declared in the module source code or if the name is correct.`,
|
|
160
160
|
"MODULE_ERROR"
|
|
161
|
-
), this.moduleName = e, this.functionName =
|
|
161
|
+
), this.moduleName = e, this.functionName = t, this.uniformName = n;
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
|
-
class
|
|
165
|
-
constructor(e,
|
|
164
|
+
class te extends h {
|
|
165
|
+
constructor(e, t) {
|
|
166
166
|
super(
|
|
167
|
-
`Uniform '${
|
|
167
|
+
`Uniform '${t}' mentioned for function '${e}' was not imported from any module. Check if the function is imported from the correct module and if the uniform is declared in that module's source code with the correct name.`,
|
|
168
168
|
"MODULE_ERROR"
|
|
169
|
-
), this.functionName = e, this.uniformName =
|
|
169
|
+
), this.functionName = e, this.uniformName = t;
|
|
170
170
|
}
|
|
171
171
|
}
|
|
172
172
|
class ne extends h {
|
|
173
|
-
constructor(e,
|
|
173
|
+
constructor(e, t) {
|
|
174
174
|
super(
|
|
175
|
-
`Mention '${e}' called in function '${
|
|
175
|
+
`Mention '${e}' called in function '${t}' could not be replaced with the corresponding uniform reference. There might be an issue with the compilation process because the referenced uniform was not found among the shader requirements. Try use a different name for uniforms you want to mention in functions or check if the uniform is properly declared and mentioned in the module source code.`,
|
|
176
176
|
"MODULE_ERROR"
|
|
177
|
-
), this.mentionName = e, this.calledInFunction =
|
|
177
|
+
), this.mentionName = e, this.calledInFunction = t;
|
|
178
178
|
}
|
|
179
179
|
}
|
|
180
|
-
class
|
|
180
|
+
class S extends h {
|
|
181
181
|
constructor(e) {
|
|
182
182
|
super(`Shader program linking failed
|
|
183
183
|
|
|
184
184
|
${e}`, "PROGRAM_ERROR"), this.infoLog = e;
|
|
185
185
|
}
|
|
186
186
|
}
|
|
187
|
-
class
|
|
187
|
+
class ge extends h {
|
|
188
|
+
constructor(t) {
|
|
189
|
+
super(
|
|
190
|
+
`Failed to create WebGL texture for "${t}".`,
|
|
191
|
+
"TEXTURE_ERROR"
|
|
192
|
+
);
|
|
193
|
+
o(this, "name", "SandboxTextureCreationError");
|
|
194
|
+
this.textureName = t;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
class xe extends h {
|
|
198
|
+
constructor(t, n) {
|
|
199
|
+
super(
|
|
200
|
+
`Cannot bind texture "${t}": all ${n} texture units are in use.`,
|
|
201
|
+
"TEXTURE_ERROR"
|
|
202
|
+
);
|
|
203
|
+
o(this, "name", "SandboxTextureUnitLimitError");
|
|
204
|
+
this.textureName = t, this.maxUnits = n;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
class ie extends h {
|
|
188
208
|
constructor(e) {
|
|
189
209
|
super(`Error in onLoad callback: ${e}`, "UNKNOWN_ERROR");
|
|
190
210
|
}
|
|
191
211
|
}
|
|
192
|
-
class
|
|
193
|
-
constructor(e,
|
|
194
|
-
super(`Error in onBefore/onAfter hook callback with ID ${e}: ${
|
|
212
|
+
class re extends h {
|
|
213
|
+
constructor(e, t) {
|
|
214
|
+
super(`Error in onBefore/onAfter hook callback with ID ${e}: ${t}`, "UNKNOWN_ERROR");
|
|
195
215
|
}
|
|
196
216
|
}
|
|
197
|
-
class
|
|
217
|
+
class se {
|
|
198
218
|
constructor() {
|
|
199
219
|
/** Total elapsed time in seconds */
|
|
200
|
-
|
|
220
|
+
o(this, "time", 0);
|
|
201
221
|
/** Delta time since last frame in seconds */
|
|
202
|
-
|
|
222
|
+
o(this, "delta", 0);
|
|
203
223
|
/** Frame counter */
|
|
204
|
-
|
|
224
|
+
o(this, "frame", 0);
|
|
205
225
|
/** Is clock running */
|
|
206
|
-
|
|
226
|
+
o(this, "running", !1);
|
|
207
227
|
/** Smoothed frames per second */
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
228
|
+
o(this, "fps", 0);
|
|
229
|
+
o(this, "startTime", 0);
|
|
230
|
+
o(this, "lastTime", 0);
|
|
231
|
+
o(this, "rafId", null);
|
|
232
|
+
o(this, "callback", null);
|
|
233
|
+
o(this, "maxFps", 0);
|
|
214
234
|
this.loop = this.loop.bind(this);
|
|
215
235
|
}
|
|
216
236
|
/**
|
|
@@ -219,8 +239,8 @@ class re {
|
|
|
219
239
|
start(e) {
|
|
220
240
|
if (this.running) return this;
|
|
221
241
|
this.callback = e, this.running = !0;
|
|
222
|
-
const
|
|
223
|
-
return this.frame === 0 ? this.startTime =
|
|
242
|
+
const t = performance.now();
|
|
243
|
+
return this.frame === 0 ? this.startTime = t : this.startTime = t - this.time * 1e3, this.lastTime = t, this.rafId = requestAnimationFrame(this.loop), this;
|
|
224
244
|
}
|
|
225
245
|
/**
|
|
226
246
|
* Stop the animation loop.
|
|
@@ -278,29 +298,29 @@ class re {
|
|
|
278
298
|
loop(e) {
|
|
279
299
|
if (!this.running) return;
|
|
280
300
|
if (this.maxFps > 0) {
|
|
281
|
-
const
|
|
282
|
-
if (e - this.lastTime <
|
|
301
|
+
const n = 1e3 / this.maxFps;
|
|
302
|
+
if (e - this.lastTime < n) {
|
|
283
303
|
this.rafId = requestAnimationFrame(this.loop);
|
|
284
304
|
return;
|
|
285
305
|
}
|
|
286
306
|
}
|
|
287
307
|
this.delta = (e - this.lastTime) / 1e3, this.lastTime = e;
|
|
288
|
-
const
|
|
289
|
-
this.fps = this.fps * 0.95 +
|
|
308
|
+
const t = this.delta > 0 ? 1 / this.delta : 0;
|
|
309
|
+
this.fps = this.fps * 0.95 + t * 0.05, this.time = (e - this.startTime) / 1e3, this.frame++, this.callback && this.callback(this.getState()), this.rafId = requestAnimationFrame(this.loop);
|
|
290
310
|
}
|
|
291
311
|
}
|
|
292
|
-
class
|
|
312
|
+
class k {
|
|
293
313
|
constructor(e) {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
314
|
+
o(this, "gl");
|
|
315
|
+
o(this, "vao", null);
|
|
316
|
+
o(this, "vbo", null);
|
|
317
|
+
o(this, "ibo", null);
|
|
318
|
+
o(this, "vertexCount", 0);
|
|
319
|
+
o(this, "indexCount", 0);
|
|
320
|
+
o(this, "useIndices", !1);
|
|
301
321
|
// WebGL1 VAO extension (if available)
|
|
302
|
-
|
|
303
|
-
|
|
322
|
+
o(this, "vaoExt", null);
|
|
323
|
+
o(this, "isWebGL2");
|
|
304
324
|
this.gl = e, this.isWebGL2 = e instanceof WebGL2RenderingContext, this.isWebGL2 || (this.vaoExt = e.getExtension("OES_vertex_array_object"));
|
|
305
325
|
}
|
|
306
326
|
/**
|
|
@@ -308,7 +328,7 @@ class A {
|
|
|
308
328
|
* This is the most common use case for shader effects.
|
|
309
329
|
*/
|
|
310
330
|
static fullscreenQuad(e) {
|
|
311
|
-
const
|
|
331
|
+
const t = new k(e), n = new Float32Array([
|
|
312
332
|
// position texcoord
|
|
313
333
|
-1,
|
|
314
334
|
-1,
|
|
@@ -340,33 +360,33 @@ class A {
|
|
|
340
360
|
3
|
|
341
361
|
// second triangle
|
|
342
362
|
]);
|
|
343
|
-
return
|
|
363
|
+
return t.setup(n, i), t;
|
|
344
364
|
}
|
|
345
365
|
/**
|
|
346
366
|
* Setup geometry from vertex and index data.
|
|
347
367
|
*/
|
|
348
|
-
setup(e,
|
|
349
|
-
const
|
|
350
|
-
return this.createVAO(), this.bindVAO(), this.vbo =
|
|
368
|
+
setup(e, t) {
|
|
369
|
+
const n = this.gl;
|
|
370
|
+
return this.createVAO(), this.bindVAO(), this.vbo = n.createBuffer(), n.bindBuffer(n.ARRAY_BUFFER, this.vbo), n.bufferData(n.ARRAY_BUFFER, e, n.STATIC_DRAW), this.vertexCount = e.length / 4, t && (this.ibo = n.createBuffer(), n.bindBuffer(n.ELEMENT_ARRAY_BUFFER, this.ibo), n.bufferData(n.ELEMENT_ARRAY_BUFFER, t, n.STATIC_DRAW), this.indexCount = t.length, this.useIndices = !0), this.unbindVAO(), this;
|
|
351
371
|
}
|
|
352
372
|
/**
|
|
353
373
|
* Link vertex attributes to shader program.
|
|
354
374
|
* Call this after compiling shaders.
|
|
355
375
|
*/
|
|
356
376
|
linkAttributes(e) {
|
|
357
|
-
const
|
|
358
|
-
this.bindVAO(),
|
|
359
|
-
const
|
|
360
|
-
i >= 0 && (
|
|
377
|
+
const t = this.gl;
|
|
378
|
+
this.bindVAO(), t.bindBuffer(t.ARRAY_BUFFER, this.vbo);
|
|
379
|
+
const n = 4 * Float32Array.BYTES_PER_ELEMENT, i = this.getPositionLocation(e);
|
|
380
|
+
i >= 0 && (t.enableVertexAttribArray(i), t.vertexAttribPointer(i, 2, t.FLOAT, !1, n, 0));
|
|
361
381
|
const r = this.getTexcoordLocation(e);
|
|
362
|
-
return r >= 0 && (
|
|
382
|
+
return r >= 0 && (t.enableVertexAttribArray(r), t.vertexAttribPointer(
|
|
363
383
|
r,
|
|
364
384
|
2,
|
|
365
|
-
|
|
385
|
+
t.FLOAT,
|
|
366
386
|
!1,
|
|
367
|
-
|
|
387
|
+
n,
|
|
368
388
|
2 * Float32Array.BYTES_PER_ELEMENT
|
|
369
|
-
)), this.useIndices &&
|
|
389
|
+
)), this.useIndices && t.bindBuffer(t.ELEMENT_ARRAY_BUFFER, this.ibo), this.unbindVAO(), this;
|
|
370
390
|
}
|
|
371
391
|
/**
|
|
372
392
|
* Bind geometry for rendering.
|
|
@@ -399,16 +419,16 @@ class A {
|
|
|
399
419
|
* Tries common naming conventions.
|
|
400
420
|
*/
|
|
401
421
|
getPositionLocation(e) {
|
|
402
|
-
let
|
|
403
|
-
return
|
|
422
|
+
let t = e.getAttribLocation("a_position");
|
|
423
|
+
return t >= 0 || (t = e.getAttribLocation("aPosition"), t >= 0) || (t = e.getAttribLocation("position"), t >= 0) ? t : -1;
|
|
404
424
|
}
|
|
405
425
|
/**
|
|
406
426
|
* Get texcoord attribute location.
|
|
407
427
|
* Tries common naming conventions.
|
|
408
428
|
*/
|
|
409
429
|
getTexcoordLocation(e) {
|
|
410
|
-
let
|
|
411
|
-
return
|
|
430
|
+
let t = e.getAttribLocation("a_texcoord");
|
|
431
|
+
return t >= 0 || (t = e.getAttribLocation("aTexCoord"), t >= 0) || (t = e.getAttribLocation("texcoord"), t >= 0) || (t = e.getAttribLocation("a_uv"), t >= 0) ? t : -1;
|
|
412
432
|
}
|
|
413
433
|
// ============================================================================
|
|
414
434
|
// VAO helpers (handle WebGL1 vs WebGL2 differences)
|
|
@@ -426,12 +446,12 @@ class A {
|
|
|
426
446
|
this.vao && (this.isWebGL2 ? this.gl.deleteVertexArray(this.vao) : this.vaoExt && this.vaoExt.deleteVertexArrayOES(this.vao), this.vao = null);
|
|
427
447
|
}
|
|
428
448
|
}
|
|
429
|
-
class
|
|
449
|
+
class oe {
|
|
430
450
|
constructor(e) {
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
451
|
+
o(this, "gl");
|
|
452
|
+
o(this, "program", null);
|
|
453
|
+
o(this, "vertexShader", null);
|
|
454
|
+
o(this, "fragmentShader", null);
|
|
435
455
|
this.gl = e;
|
|
436
456
|
}
|
|
437
457
|
/**
|
|
@@ -439,8 +459,8 @@ class se {
|
|
|
439
459
|
* @throws ShaderCompilationError if compilation fails
|
|
440
460
|
* @throws ProgramLinkError if linking fails
|
|
441
461
|
*/
|
|
442
|
-
compile(e,
|
|
443
|
-
return this.destroy(), this.vertexShader = this.compileShader("vertex", e), this.fragmentShader = this.compileShader("fragment",
|
|
462
|
+
compile(e, t) {
|
|
463
|
+
return this.destroy(), this.vertexShader = this.compileShader("vertex", e), this.fragmentShader = this.compileShader("fragment", t), this.linkProgram(), this;
|
|
444
464
|
}
|
|
445
465
|
/**
|
|
446
466
|
* Bind this program for rendering.
|
|
@@ -477,17 +497,17 @@ class se {
|
|
|
477
497
|
* Compile a single shader.
|
|
478
498
|
* @throws ShaderCompilationError if compilation fails
|
|
479
499
|
*/
|
|
480
|
-
compileShader(e,
|
|
481
|
-
const
|
|
500
|
+
compileShader(e, t) {
|
|
501
|
+
const n = this.gl, i = e === "vertex" ? n.VERTEX_SHADER : n.FRAGMENT_SHADER, r = n.createShader(i);
|
|
482
502
|
if (!r)
|
|
483
503
|
throw new _(
|
|
484
504
|
e,
|
|
485
|
-
|
|
505
|
+
t,
|
|
486
506
|
"Failed to create shader object"
|
|
487
507
|
);
|
|
488
|
-
if (
|
|
489
|
-
const
|
|
490
|
-
throw
|
|
508
|
+
if (n.shaderSource(r, t), n.compileShader(r), !n.getShaderParameter(r, n.COMPILE_STATUS)) {
|
|
509
|
+
const a = n.getShaderInfoLog(r) || "Unknown error";
|
|
510
|
+
throw n.deleteShader(r), new _(e, t, a);
|
|
491
511
|
}
|
|
492
512
|
return r;
|
|
493
513
|
}
|
|
@@ -498,29 +518,29 @@ class se {
|
|
|
498
518
|
linkProgram() {
|
|
499
519
|
const e = this.gl;
|
|
500
520
|
if (!this.vertexShader || !this.fragmentShader)
|
|
501
|
-
throw new
|
|
502
|
-
const
|
|
503
|
-
if (!
|
|
504
|
-
throw new
|
|
505
|
-
if (e.attachShader(
|
|
506
|
-
const i = e.getProgramInfoLog(
|
|
507
|
-
throw e.deleteProgram(
|
|
521
|
+
throw new S("Shaders not compiled");
|
|
522
|
+
const t = e.createProgram();
|
|
523
|
+
if (!t)
|
|
524
|
+
throw new S("Failed to create program object");
|
|
525
|
+
if (e.attachShader(t, this.vertexShader), e.attachShader(t, this.fragmentShader), e.linkProgram(t), !e.getProgramParameter(t, e.LINK_STATUS)) {
|
|
526
|
+
const i = e.getProgramInfoLog(t) || "Unknown error";
|
|
527
|
+
throw e.deleteProgram(t), new S(i);
|
|
508
528
|
}
|
|
509
|
-
this.program =
|
|
529
|
+
this.program = t;
|
|
510
530
|
}
|
|
511
531
|
}
|
|
512
|
-
class
|
|
513
|
-
constructor(e,
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
this.name = e, this.value =
|
|
522
|
-
const
|
|
523
|
-
this.method =
|
|
532
|
+
class M {
|
|
533
|
+
constructor(e, t) {
|
|
534
|
+
o(this, "name");
|
|
535
|
+
o(this, "method");
|
|
536
|
+
o(this, "isArray");
|
|
537
|
+
o(this, "isMatrix");
|
|
538
|
+
o(this, "location", null);
|
|
539
|
+
o(this, "locationResolved", !1);
|
|
540
|
+
o(this, "value");
|
|
541
|
+
this.name = e, this.value = t;
|
|
542
|
+
const n = M.inferMethodInfo(t);
|
|
543
|
+
this.method = n.method, this.isArray = n.isArray, this.isMatrix = n.isMatrix;
|
|
524
544
|
}
|
|
525
545
|
/**
|
|
526
546
|
* Infer WebGL method and metadata from value type.
|
|
@@ -532,9 +552,9 @@ class k {
|
|
|
532
552
|
return { method: "uniform1f", isArray: !1, isMatrix: !1 };
|
|
533
553
|
if (!Array.isArray(e))
|
|
534
554
|
return { method: "uniform1f", isArray: !1, isMatrix: !1 };
|
|
535
|
-
const
|
|
536
|
-
if (Array.isArray(
|
|
537
|
-
switch (
|
|
555
|
+
const t = e.length, n = e[0];
|
|
556
|
+
if (Array.isArray(n))
|
|
557
|
+
switch (n.length) {
|
|
538
558
|
case 2:
|
|
539
559
|
return { method: "uniform2fv", isArray: !0, isMatrix: !1 };
|
|
540
560
|
case 3:
|
|
@@ -544,7 +564,7 @@ class k {
|
|
|
544
564
|
default:
|
|
545
565
|
return { method: "uniform1fv", isArray: !0, isMatrix: !1 };
|
|
546
566
|
}
|
|
547
|
-
switch (
|
|
567
|
+
switch (t) {
|
|
548
568
|
case 2:
|
|
549
569
|
return { method: "uniform2fv", isArray: !1, isMatrix: !1 };
|
|
550
570
|
case 3:
|
|
@@ -563,8 +583,8 @@ class k {
|
|
|
563
583
|
* Resolve and cache uniform location from program.
|
|
564
584
|
* Returns null if uniform doesn't exist (optimized out by compiler, etc.)
|
|
565
585
|
*/
|
|
566
|
-
resolveLocation(e,
|
|
567
|
-
return this.locationResolved || (this.location = e.getUniformLocation(
|
|
586
|
+
resolveLocation(e, t) {
|
|
587
|
+
return this.locationResolved || (this.location = e.getUniformLocation(t, this.name), this.locationResolved = !0), this.location;
|
|
568
588
|
}
|
|
569
589
|
/**
|
|
570
590
|
* Invalidate cached location (call when program changes).
|
|
@@ -589,9 +609,9 @@ class k {
|
|
|
589
609
|
* @param gl - WebGL context
|
|
590
610
|
* @param program - Current WebGL program (for location resolution)
|
|
591
611
|
*/
|
|
592
|
-
upload(e,
|
|
593
|
-
const
|
|
594
|
-
if (
|
|
612
|
+
upload(e, t) {
|
|
613
|
+
const n = this.resolveLocation(e, t);
|
|
614
|
+
if (n === null)
|
|
595
615
|
return;
|
|
596
616
|
const i = this.value;
|
|
597
617
|
let r;
|
|
@@ -599,38 +619,38 @@ class k {
|
|
|
599
619
|
i.flat()
|
|
600
620
|
) : r = new Float32Array(i), this.method) {
|
|
601
621
|
case "uniform1f":
|
|
602
|
-
e.uniform1f(
|
|
622
|
+
e.uniform1f(n, r);
|
|
603
623
|
break;
|
|
604
624
|
case "uniform1i":
|
|
605
|
-
e.uniform1i(
|
|
625
|
+
e.uniform1i(n, r);
|
|
606
626
|
break;
|
|
607
627
|
case "uniform1fv":
|
|
608
|
-
e.uniform1fv(
|
|
628
|
+
e.uniform1fv(n, r);
|
|
609
629
|
break;
|
|
610
630
|
case "uniform2fv":
|
|
611
|
-
e.uniform2fv(
|
|
631
|
+
e.uniform2fv(n, r);
|
|
612
632
|
break;
|
|
613
633
|
case "uniform3fv":
|
|
614
|
-
e.uniform3fv(
|
|
634
|
+
e.uniform3fv(n, r);
|
|
615
635
|
break;
|
|
616
636
|
case "uniform4fv":
|
|
617
|
-
e.uniform4fv(
|
|
637
|
+
e.uniform4fv(n, r);
|
|
618
638
|
break;
|
|
619
639
|
case "uniformMatrix2fv":
|
|
620
|
-
e.uniformMatrix2fv(
|
|
640
|
+
e.uniformMatrix2fv(n, !1, r);
|
|
621
641
|
break;
|
|
622
642
|
case "uniformMatrix3fv":
|
|
623
|
-
e.uniformMatrix3fv(
|
|
643
|
+
e.uniformMatrix3fv(n, !1, r);
|
|
624
644
|
break;
|
|
625
645
|
case "uniformMatrix4fv":
|
|
626
|
-
e.uniformMatrix4fv(
|
|
646
|
+
e.uniformMatrix4fv(n, !1, r);
|
|
627
647
|
break;
|
|
628
648
|
}
|
|
629
649
|
}
|
|
630
650
|
}
|
|
631
|
-
class
|
|
651
|
+
class E {
|
|
632
652
|
constructor(e) {
|
|
633
|
-
|
|
653
|
+
o(this, "parsed", null);
|
|
634
654
|
this.source = e;
|
|
635
655
|
}
|
|
636
656
|
/**
|
|
@@ -638,11 +658,11 @@ class w {
|
|
|
638
658
|
*/
|
|
639
659
|
parse() {
|
|
640
660
|
if (this.parsed) return this.parsed;
|
|
641
|
-
const e = this.detectVersion(),
|
|
661
|
+
const e = this.detectVersion(), t = this.detectImports(), n = this.detectUniforms(), i = this.detectFunctions(n);
|
|
642
662
|
return this.parsed = {
|
|
643
663
|
version: e,
|
|
644
|
-
imports:
|
|
645
|
-
uniforms:
|
|
664
|
+
imports: t,
|
|
665
|
+
uniforms: n,
|
|
646
666
|
functions: i
|
|
647
667
|
};
|
|
648
668
|
}
|
|
@@ -668,17 +688,17 @@ class w {
|
|
|
668
688
|
return /^\s*#version\s+300\s+es/m.test(this.source) ? 2 : 1;
|
|
669
689
|
}
|
|
670
690
|
detectImports() {
|
|
671
|
-
const e = /^[ \t]*#import\s+(\w+)(?:\s+as\s+(\w+))?\s+from\s+["'](.+)["']/gm,
|
|
672
|
-
let r, s = 1,
|
|
691
|
+
const e = /^[ \t]*#import\s+(\w+)(?:\s+as\s+(\w+))?\s+from\s+["'](.+)["']/gm, t = /^[ \t]*[^\w\s]?import\b/gm, n = [], i = /* @__PURE__ */ new Set();
|
|
692
|
+
let r, s = 1, a = 0;
|
|
673
693
|
for (; (r = e.exec(this.source)) !== null; ) {
|
|
674
|
-
s += (this.source.substring(
|
|
694
|
+
s += (this.source.substring(a, r.index).match(/\n/g) || []).length, a = r.index, i.add(s);
|
|
675
695
|
const f = r[1], c = r[2] || r[1], m = r[3];
|
|
676
|
-
if (
|
|
677
|
-
throw new
|
|
678
|
-
|
|
696
|
+
if (n.some((p) => p.alias === c))
|
|
697
|
+
throw new j(c, s);
|
|
698
|
+
n.push({ name: f, alias: c, module: m, line: s });
|
|
679
699
|
}
|
|
680
700
|
let l;
|
|
681
|
-
for (; (l =
|
|
701
|
+
for (; (l = t.exec(this.source)) !== null; ) {
|
|
682
702
|
const f = (this.source.substring(0, l.index).match(/\n/g) || []).length + 1;
|
|
683
703
|
if (i.has(f)) continue;
|
|
684
704
|
const c = this.source.split(`
|
|
@@ -688,12 +708,12 @@ class w {
|
|
|
688
708
|
this.diagnoseImport(c)
|
|
689
709
|
);
|
|
690
710
|
}
|
|
691
|
-
return
|
|
711
|
+
return n;
|
|
692
712
|
}
|
|
693
713
|
diagnoseImport(e) {
|
|
694
|
-
const
|
|
695
|
-
if (
|
|
696
|
-
return `Invalid prefix '${
|
|
714
|
+
const t = e.match(/^([^\w\s])import\b/);
|
|
715
|
+
if (t && t[1] !== "#")
|
|
716
|
+
return `Invalid prefix '${t[1]}'. Expected: #import <function> from '<module>'`;
|
|
697
717
|
if (/^import\b/.test(e))
|
|
698
718
|
return "Missing '#' prefix. Expected: #import <function> from '<module>'";
|
|
699
719
|
if (/^#import\s+from\b/.test(e))
|
|
@@ -703,65 +723,65 @@ class w {
|
|
|
703
723
|
if (/^#import\s+\w+\s+as\s*$/.test(e) || /^#import\s+\w+\s+as\s+from\b/.test(e))
|
|
704
724
|
return `Missing alias name after 'as'. Expected: #import ${e.split(/\s+/)[1]} as <alias> from '<module>'`;
|
|
705
725
|
if (/^#import\s+\w+\s+as\s+\w+\s*$/.test(e)) {
|
|
706
|
-
const
|
|
707
|
-
return `Missing 'from' clause. Expected: #import ${
|
|
726
|
+
const n = e.split(/\s+/);
|
|
727
|
+
return `Missing 'from' clause. Expected: #import ${n[1]} as ${n[3]} from '<module>'`;
|
|
708
728
|
}
|
|
709
729
|
if (/^#import\s+\w+(?:\s+as\s+\w+)?\s+from\s+\w+/.test(e)) {
|
|
710
|
-
const
|
|
711
|
-
return `Module name must be quoted. Expected: from '${
|
|
730
|
+
const n = e.match(/from\s+(\S+)/);
|
|
731
|
+
return `Module name must be quoted. Expected: from '${n == null ? void 0 : n[1]}'`;
|
|
712
732
|
}
|
|
713
733
|
return "Invalid syntax. Expected: #import <function> from '<module>'";
|
|
714
734
|
}
|
|
715
735
|
detectUniforms() {
|
|
716
|
-
const e = /^[ \t]*uniform\s+(?:(?:highp|mediump|lowp)\s+)?(\w+)\s+(\w+)(?:\[(\d+)\])?\s*;/gm,
|
|
717
|
-
let
|
|
718
|
-
for (; (
|
|
719
|
-
i += (this.source.substring(r,
|
|
720
|
-
const s =
|
|
721
|
-
|
|
736
|
+
const e = /^[ \t]*uniform\s+(?:(?:highp|mediump|lowp)\s+)?(\w+)\s+(\w+)(?:\[(\d+)\])?\s*;/gm, t = [];
|
|
737
|
+
let n, i = 1, r = 0;
|
|
738
|
+
for (; (n = e.exec(this.source)) !== null; ) {
|
|
739
|
+
i += (this.source.substring(r, n.index).match(/\n/g) || []).length, r = n.index;
|
|
740
|
+
const s = n[1], a = n[2], l = n[3] ? parseInt(n[3], 10) : void 0;
|
|
741
|
+
t.push({ name: a, type: s, line: i, arrayNum: l });
|
|
722
742
|
}
|
|
723
|
-
return
|
|
743
|
+
return t;
|
|
724
744
|
}
|
|
725
745
|
detectFunctions(e) {
|
|
726
|
-
const
|
|
727
|
-
`^[ \\t]*(${
|
|
746
|
+
const t = [], n = "void|float|int|uint|bool|vec[234]|ivec[234]|uvec[234]|bvec[234]|mat[234](?:x[234])?|sampler2D|samplerCube|sampler3D|sampler2DArray", i = new RegExp(
|
|
747
|
+
`^[ \\t]*(${n})\\s+(\\w+)\\s*\\(([^)]*)\\)\\s*\\{`,
|
|
728
748
|
"gm"
|
|
729
749
|
);
|
|
730
750
|
let r;
|
|
731
751
|
for (; (r = i.exec(this.source)) !== null; ) {
|
|
732
|
-
const s = r[1],
|
|
752
|
+
const s = r[1], a = r[2], l = r[3].trim(), f = r.index, c = (this.source.substring(0, f).match(/\n/g) || []).length + 1, m = this.source.indexOf("{", f), p = this.findClosingBrace(this.source, m);
|
|
733
753
|
if (p === -1) continue;
|
|
734
|
-
const g = this.source.slice(m, p + 1),
|
|
735
|
-
|
|
736
|
-
name:
|
|
754
|
+
const g = this.source.slice(m, p + 1), P = this.parseParams(l), $ = this.findFunctionCalls(g), D = this.findUniformCalls(g, e), B = this.findMentionCalls(g);
|
|
755
|
+
t.push({
|
|
756
|
+
name: a,
|
|
737
757
|
type: s,
|
|
738
|
-
params:
|
|
758
|
+
params: P,
|
|
739
759
|
body: g,
|
|
740
|
-
dependencies: [
|
|
760
|
+
dependencies: [...$, ...D, ...B],
|
|
741
761
|
line: c
|
|
742
762
|
});
|
|
743
763
|
}
|
|
744
|
-
return
|
|
764
|
+
return t;
|
|
745
765
|
}
|
|
746
766
|
parseParams(e) {
|
|
747
767
|
if (!e.trim()) return [];
|
|
748
|
-
const
|
|
749
|
-
for (const i of
|
|
768
|
+
const t = [], n = e.split(",");
|
|
769
|
+
for (const i of n) {
|
|
750
770
|
const r = i.trim();
|
|
751
771
|
if (!r) continue;
|
|
752
|
-
const
|
|
753
|
-
|
|
754
|
-
type:
|
|
755
|
-
name:
|
|
772
|
+
const a = r.replace(/\b(in|out|inout|const|highp|mediump|lowp)\b\s*/g, "").trim().match(/^(\w+)\s+(\w+)(?:\[\d*\])?$/);
|
|
773
|
+
a && t.push({
|
|
774
|
+
type: a[1],
|
|
775
|
+
name: a[2]
|
|
756
776
|
});
|
|
757
777
|
}
|
|
758
|
-
return
|
|
778
|
+
return t;
|
|
759
779
|
}
|
|
760
|
-
findClosingBrace(e,
|
|
761
|
-
let
|
|
762
|
-
for (let l =
|
|
780
|
+
findClosingBrace(e, t) {
|
|
781
|
+
let n = 0, i = !1, r = !1, s = !1, a = !1;
|
|
782
|
+
for (let l = t; l < e.length; l++) {
|
|
763
783
|
const f = e[l], c = e[l + 1], m = e[l - 1];
|
|
764
|
-
if (!r && !
|
|
784
|
+
if (!r && !a && f === "/" && c === "/") {
|
|
765
785
|
s = !0;
|
|
766
786
|
continue;
|
|
767
787
|
}
|
|
@@ -771,22 +791,22 @@ class w {
|
|
|
771
791
|
continue;
|
|
772
792
|
}
|
|
773
793
|
if (!r && !s && f === "/" && c === "*") {
|
|
774
|
-
|
|
794
|
+
a = !0, l++;
|
|
775
795
|
continue;
|
|
776
796
|
}
|
|
777
|
-
if (
|
|
778
|
-
|
|
797
|
+
if (a && f === "*" && c === "/") {
|
|
798
|
+
a = !1, l++;
|
|
779
799
|
continue;
|
|
780
800
|
}
|
|
781
|
-
if (!(s ||
|
|
801
|
+
if (!(s || a)) {
|
|
782
802
|
if (f === '"' && m !== "\\") {
|
|
783
803
|
r = !r;
|
|
784
804
|
continue;
|
|
785
805
|
}
|
|
786
806
|
if (!r) {
|
|
787
807
|
if (f === "{")
|
|
788
|
-
|
|
789
|
-
else if (f === "}" && (
|
|
808
|
+
n++, i = !0;
|
|
809
|
+
else if (f === "}" && (n--, i && n === 0))
|
|
790
810
|
return l;
|
|
791
811
|
}
|
|
792
812
|
}
|
|
@@ -794,7 +814,7 @@ class w {
|
|
|
794
814
|
return -1;
|
|
795
815
|
}
|
|
796
816
|
findFunctionCalls(e) {
|
|
797
|
-
const
|
|
817
|
+
const t = [], n = /* @__PURE__ */ new Set([
|
|
798
818
|
"if",
|
|
799
819
|
"else",
|
|
800
820
|
"for",
|
|
@@ -810,56 +830,56 @@ class w {
|
|
|
810
830
|
let r;
|
|
811
831
|
for (; (r = i.exec(e)) !== null; ) {
|
|
812
832
|
const s = r[1];
|
|
813
|
-
|
|
833
|
+
n.has(s) || t.push({
|
|
814
834
|
name: s,
|
|
815
835
|
type: "function",
|
|
816
836
|
index: r.index
|
|
817
837
|
});
|
|
818
838
|
}
|
|
819
|
-
return
|
|
839
|
+
return t;
|
|
820
840
|
}
|
|
821
|
-
findUniformCalls(e,
|
|
822
|
-
const
|
|
823
|
-
for (const i of
|
|
841
|
+
findUniformCalls(e, t) {
|
|
842
|
+
const n = [];
|
|
843
|
+
for (const i of t) {
|
|
824
844
|
const r = new RegExp(`\\b${i.name}\\b`, "g");
|
|
825
845
|
let s;
|
|
826
846
|
for (; (s = r.exec(e)) !== null; )
|
|
827
|
-
|
|
847
|
+
n.push({
|
|
828
848
|
name: i.name,
|
|
829
849
|
type: "uniform",
|
|
830
850
|
index: s.index
|
|
831
851
|
});
|
|
832
852
|
}
|
|
833
|
-
return
|
|
853
|
+
return n;
|
|
834
854
|
}
|
|
835
855
|
findMentionCalls(e) {
|
|
836
|
-
const
|
|
856
|
+
const t = [], n = /@(\w+)\.([a-zA-Z_]\w*)/g;
|
|
837
857
|
let i;
|
|
838
|
-
for (; (i =
|
|
858
|
+
for (; (i = n.exec(e)) !== null; ) {
|
|
839
859
|
const r = i[1], s = i[2];
|
|
840
|
-
|
|
860
|
+
t.push({
|
|
841
861
|
name: `${r}.${s}`,
|
|
842
862
|
type: "mention",
|
|
843
863
|
index: i.index
|
|
844
864
|
});
|
|
845
865
|
}
|
|
846
|
-
return
|
|
866
|
+
return t;
|
|
847
867
|
}
|
|
848
868
|
}
|
|
849
869
|
class F {
|
|
850
870
|
constructor(e) {
|
|
851
871
|
/** Flag to track if the shader has been compiled */
|
|
852
|
-
|
|
872
|
+
o(this, "isCompiled", !1);
|
|
853
873
|
/** Original and compiled shader parsers */
|
|
854
|
-
|
|
874
|
+
o(this, "original");
|
|
855
875
|
/** Compiled parser will be updated with rewritten source after processing imports */
|
|
856
|
-
|
|
876
|
+
o(this, "compiled");
|
|
857
877
|
/** Collected requirements from imports */
|
|
858
|
-
|
|
878
|
+
o(this, "requirements", {
|
|
859
879
|
uniforms: /* @__PURE__ */ new Map(),
|
|
860
880
|
functions: /* @__PURE__ */ new Map()
|
|
861
881
|
});
|
|
862
|
-
this.original = new
|
|
882
|
+
this.original = new E(e), this.compiled = new E(e);
|
|
863
883
|
}
|
|
864
884
|
/**
|
|
865
885
|
* Detect WebGL version from shader source
|
|
@@ -890,13 +910,13 @@ class F {
|
|
|
890
910
|
* Process all #import directives
|
|
891
911
|
*/
|
|
892
912
|
processImports() {
|
|
893
|
-
const e = this.original.parse(),
|
|
913
|
+
const e = this.original.parse(), t = e.functions.flatMap((n) => n.dependencies.filter((i) => i.type === "mention").map((i) => ({
|
|
894
914
|
name: i.name.split(".")[0],
|
|
895
915
|
uniform: i.name.split(".")[1]
|
|
896
916
|
})));
|
|
897
|
-
for (const
|
|
898
|
-
const i =
|
|
899
|
-
let s =
|
|
917
|
+
for (const n of e.imports) {
|
|
918
|
+
const i = w.resolve(n.module), r = i.extract(n.name);
|
|
919
|
+
let s = t.filter(
|
|
900
920
|
(l) => l.name === r.function.name
|
|
901
921
|
);
|
|
902
922
|
if (s.length > 0) {
|
|
@@ -909,82 +929,82 @@ class F {
|
|
|
909
929
|
r.dependencies.uniforms.some(
|
|
910
930
|
(p) => p.name === c.name
|
|
911
931
|
) || r.dependencies.uniforms.push(c);
|
|
912
|
-
const m =
|
|
913
|
-
return m > -1 &&
|
|
932
|
+
const m = t.indexOf(f);
|
|
933
|
+
return m > -1 && t.splice(m, 1), !1;
|
|
914
934
|
}
|
|
915
935
|
return !0;
|
|
916
936
|
}), s.length > 0)
|
|
917
|
-
throw new
|
|
918
|
-
|
|
937
|
+
throw new ee(
|
|
938
|
+
n.module,
|
|
919
939
|
r.function.name,
|
|
920
940
|
s[0].uniform
|
|
921
941
|
);
|
|
922
942
|
}
|
|
923
|
-
const
|
|
924
|
-
this.processExtraction(r,
|
|
943
|
+
const a = i.copy();
|
|
944
|
+
this.processExtraction(r, n.alias, a.options), y.merge(n.module, a);
|
|
925
945
|
}
|
|
926
|
-
if (
|
|
927
|
-
throw new
|
|
928
|
-
|
|
929
|
-
|
|
946
|
+
if (t.length > 0)
|
|
947
|
+
throw new te(
|
|
948
|
+
t[0].name,
|
|
949
|
+
t[0].uniform
|
|
930
950
|
);
|
|
931
951
|
}
|
|
932
952
|
/**
|
|
933
953
|
* Process an extraction: rewrite names and collect as requirements
|
|
934
954
|
*/
|
|
935
|
-
processExtraction(e,
|
|
936
|
-
const i = e.function, r = Math.random().toString(36).substring(2, 8), s = `${
|
|
955
|
+
processExtraction(e, t, n = {}) {
|
|
956
|
+
const i = e.function, r = Math.random().toString(36).substring(2, 8), s = `${t}_${r}`;
|
|
937
957
|
for (let l = e.dependencies.functions.length - 1; l >= 0; l--) {
|
|
938
|
-
const f = e.dependencies.functions[l], c = this.rewriteFunction(f,
|
|
958
|
+
const f = e.dependencies.functions[l], c = this.rewriteFunction(f, t, {
|
|
939
959
|
uniforms: e.dependencies.uniforms,
|
|
940
960
|
functions: e.dependencies.functions,
|
|
941
961
|
unique: s
|
|
942
962
|
});
|
|
943
963
|
this.requirements.functions.set(c.name, c);
|
|
944
964
|
}
|
|
945
|
-
const
|
|
965
|
+
const a = this.rewriteFunction(i, t, {
|
|
946
966
|
uniforms: e.dependencies.uniforms,
|
|
947
967
|
functions: e.dependencies.functions,
|
|
948
968
|
rename: !0,
|
|
949
969
|
unique: s
|
|
950
970
|
});
|
|
951
|
-
this.requirements.functions.set(
|
|
971
|
+
this.requirements.functions.set(a.name, a);
|
|
952
972
|
for (const l of e.dependencies.uniforms) {
|
|
953
|
-
if (
|
|
973
|
+
if (R.has(l.name)) continue;
|
|
954
974
|
const f = {
|
|
955
975
|
...l,
|
|
956
976
|
name: `${s}_${l.name}${l.arrayNum ? `[${l.arrayNum}]` : ""}`
|
|
957
977
|
};
|
|
958
|
-
if (
|
|
959
|
-
const c = Object.entries(
|
|
978
|
+
if (n[i.name]) {
|
|
979
|
+
const c = Object.entries(n[i.name]).find(
|
|
960
980
|
([m, p]) => p.uniform === l.name
|
|
961
981
|
);
|
|
962
982
|
c && (c[1].uniform = `${s}_${l.name}`);
|
|
963
983
|
}
|
|
964
984
|
this.requirements.uniforms.set(f.name, f);
|
|
965
985
|
}
|
|
966
|
-
|
|
986
|
+
n[i.name] && t !== i.name && (n[t] = n[i.name], delete n[i.name]);
|
|
967
987
|
}
|
|
968
988
|
/**
|
|
969
989
|
* Rewrite a function: namespace all uniform and helper function references
|
|
970
990
|
*/
|
|
971
|
-
rewriteFunction(e,
|
|
972
|
-
const i = new Set(
|
|
991
|
+
rewriteFunction(e, t, n = { rename: !1, uniforms: [], functions: [], unique: "" }) {
|
|
992
|
+
const i = new Set(n.uniforms.map((c) => c.name)), r = new Set(n.functions.map((c) => c.name)), s = [], a = n.unique ? n.unique : t;
|
|
973
993
|
for (const c of e.dependencies)
|
|
974
994
|
if (c.index !== void 0)
|
|
975
995
|
if (c.type === "uniform" && i.has(c.name)) {
|
|
976
|
-
if (
|
|
996
|
+
if (R.has(c.name)) continue;
|
|
977
997
|
s.push({
|
|
978
998
|
index: c.index,
|
|
979
999
|
oldText: c.name,
|
|
980
|
-
newText: `${
|
|
1000
|
+
newText: `${a}_${c.name}`
|
|
981
1001
|
});
|
|
982
1002
|
} else c.type === "function" && r.has(c.name) && s.push({
|
|
983
1003
|
index: c.index,
|
|
984
1004
|
oldText: c.name,
|
|
985
|
-
newText: `${
|
|
1005
|
+
newText: `${a}_${c.name}`
|
|
986
1006
|
});
|
|
987
|
-
const l = this.applyRewrites(e.body, s), f =
|
|
1007
|
+
const l = this.applyRewrites(e.body, s), f = n.rename ? t : `${a}_${e.name}`;
|
|
988
1008
|
return {
|
|
989
1009
|
...e,
|
|
990
1010
|
name: f,
|
|
@@ -994,10 +1014,10 @@ class F {
|
|
|
994
1014
|
/**
|
|
995
1015
|
* Apply rewrite operations to a string, processing from end to start
|
|
996
1016
|
*/
|
|
997
|
-
applyRewrites(e,
|
|
998
|
-
const
|
|
1017
|
+
applyRewrites(e, t) {
|
|
1018
|
+
const n = [...t].sort((r, s) => s.index - r.index);
|
|
999
1019
|
let i = e;
|
|
1000
|
-
for (const r of
|
|
1020
|
+
for (const r of n)
|
|
1001
1021
|
i = i.slice(0, r.index) + r.newText + i.slice(r.index + r.oldText.length);
|
|
1002
1022
|
return i;
|
|
1003
1023
|
}
|
|
@@ -1006,53 +1026,53 @@ class F {
|
|
|
1006
1026
|
*/
|
|
1007
1027
|
build() {
|
|
1008
1028
|
const e = this.original.parse();
|
|
1009
|
-
let
|
|
1010
|
-
|
|
1011
|
-
const
|
|
1012
|
-
i && (
|
|
1013
|
-
` +
|
|
1014
|
-
const r = this.findInsertionPointForFunctions(
|
|
1015
|
-
return s && (
|
|
1016
|
-
|
|
1017
|
-
`),
|
|
1018
|
-
}
|
|
1019
|
-
replaceMentions(e,
|
|
1020
|
-
let
|
|
1021
|
-
const i =
|
|
1029
|
+
let t = this.original.source;
|
|
1030
|
+
t = this.removeImportLines(t, e);
|
|
1031
|
+
const n = this.findInsertionPointForUniforms(t), i = this.generateUniformsCode();
|
|
1032
|
+
i && (t = t.slice(0, n) + i + `
|
|
1033
|
+
` + t.slice(n));
|
|
1034
|
+
const r = this.findInsertionPointForFunctions(t), s = this.generateFunctionCode();
|
|
1035
|
+
return s && (t = t.slice(0, r) + s + t.slice(r)), t = t.replace(/\n{3,}/g, `
|
|
1036
|
+
|
|
1037
|
+
`), t = this.replaceMentions(t, e), t;
|
|
1038
|
+
}
|
|
1039
|
+
replaceMentions(e, t) {
|
|
1040
|
+
let n = e;
|
|
1041
|
+
const i = t.functions.filter(
|
|
1022
1042
|
(r) => r.dependencies.some((s) => s.type === "mention")
|
|
1023
1043
|
);
|
|
1024
1044
|
for (const r of i) {
|
|
1025
|
-
const s = r.dependencies.filter((
|
|
1026
|
-
for (const
|
|
1027
|
-
const l =
|
|
1045
|
+
const s = r.dependencies.filter((a) => a.type === "mention");
|
|
1046
|
+
for (const a of s) {
|
|
1047
|
+
const l = a.name.split("."), f = new RegExp(`\\b${l[0]}_(\\w+)_${l[1]}\\b`, "g"), c = this.requirements.uniforms.keys().find((p) => {
|
|
1028
1048
|
var g;
|
|
1029
1049
|
return ((g = p.match(f)) == null ? void 0 : g[0]) === p;
|
|
1030
1050
|
});
|
|
1031
1051
|
if (!c)
|
|
1032
1052
|
throw new ne(
|
|
1033
|
-
|
|
1053
|
+
a.name,
|
|
1034
1054
|
r.name
|
|
1035
1055
|
);
|
|
1036
|
-
const m = new RegExp(`@\\b${
|
|
1037
|
-
|
|
1056
|
+
const m = new RegExp(`@\\b${a.name}\\b`, "g");
|
|
1057
|
+
n = n.replace(m, c);
|
|
1038
1058
|
}
|
|
1039
1059
|
}
|
|
1040
|
-
return
|
|
1060
|
+
return n;
|
|
1041
1061
|
}
|
|
1042
1062
|
/**
|
|
1043
1063
|
* Remove #import lines from shader source
|
|
1044
1064
|
*/
|
|
1045
|
-
removeImportLines(e,
|
|
1046
|
-
const
|
|
1047
|
-
`), i = new Set(
|
|
1048
|
-
return
|
|
1049
|
-
const
|
|
1050
|
-
if (!
|
|
1065
|
+
removeImportLines(e, t) {
|
|
1066
|
+
const n = e.split(`
|
|
1067
|
+
`), i = new Set(t.imports.map((r) => r.line));
|
|
1068
|
+
return n.filter((r, s) => {
|
|
1069
|
+
const a = i.has(s + 1);
|
|
1070
|
+
if (!a && r.trim() === "" && s > 0) {
|
|
1051
1071
|
const l = s - 1;
|
|
1052
1072
|
if (i.has(l + 1))
|
|
1053
1073
|
return !1;
|
|
1054
1074
|
}
|
|
1055
|
-
return !
|
|
1075
|
+
return !a;
|
|
1056
1076
|
}).join(`
|
|
1057
1077
|
`);
|
|
1058
1078
|
}
|
|
@@ -1060,48 +1080,48 @@ class F {
|
|
|
1060
1080
|
* Find insertion point for uniforms (after existing uniforms)
|
|
1061
1081
|
*/
|
|
1062
1082
|
findInsertionPointForUniforms(e) {
|
|
1063
|
-
const
|
|
1064
|
-
(
|
|
1083
|
+
const t = new E(e).parse(), n = t.uniforms.find(
|
|
1084
|
+
(a) => a.line === Math.max(...t.uniforms.map((l) => l.line ?? 0))
|
|
1065
1085
|
), i = e.split(`
|
|
1066
1086
|
`);
|
|
1067
1087
|
let r = 0;
|
|
1068
|
-
if (
|
|
1069
|
-
r =
|
|
1088
|
+
if (n && n.line)
|
|
1089
|
+
r = n.line;
|
|
1070
1090
|
else
|
|
1071
|
-
for (let
|
|
1072
|
-
const l = i[
|
|
1091
|
+
for (let a = 0; a < i.length; a++) {
|
|
1092
|
+
const l = i[a].trim();
|
|
1073
1093
|
if (l.startsWith("#version")) {
|
|
1074
|
-
r =
|
|
1094
|
+
r = a + 1;
|
|
1075
1095
|
continue;
|
|
1076
1096
|
}
|
|
1077
1097
|
if (l.startsWith("precision ")) {
|
|
1078
|
-
r =
|
|
1098
|
+
r = a + 1;
|
|
1079
1099
|
continue;
|
|
1080
1100
|
}
|
|
1081
1101
|
if (l === "" || l.startsWith("//")) {
|
|
1082
|
-
r ===
|
|
1102
|
+
r === a && (r = a + 1);
|
|
1083
1103
|
continue;
|
|
1084
1104
|
}
|
|
1085
1105
|
break;
|
|
1086
1106
|
}
|
|
1087
1107
|
let s = 0;
|
|
1088
|
-
for (let
|
|
1089
|
-
s += i[
|
|
1108
|
+
for (let a = 0; a < r; a++)
|
|
1109
|
+
s += i[a].length + 1;
|
|
1090
1110
|
return s;
|
|
1091
1111
|
}
|
|
1092
1112
|
findInsertionPointForFunctions(e) {
|
|
1093
|
-
const
|
|
1094
|
-
(
|
|
1113
|
+
const t = new E(e).parse(), n = t.functions.find(
|
|
1114
|
+
(a) => a.line === Math.min(...t.functions.map((l) => l.line ?? 1 / 0))
|
|
1095
1115
|
), i = e.split(`
|
|
1096
1116
|
`);
|
|
1097
1117
|
let r = 0;
|
|
1098
|
-
if (
|
|
1099
|
-
r =
|
|
1118
|
+
if (n && n.line)
|
|
1119
|
+
r = n.line - 2;
|
|
1100
1120
|
else
|
|
1101
|
-
throw new
|
|
1121
|
+
throw new H();
|
|
1102
1122
|
let s = 0;
|
|
1103
|
-
for (let
|
|
1104
|
-
s += i[
|
|
1123
|
+
for (let a = 0; a < r; a++)
|
|
1124
|
+
s += i[a].length + 1;
|
|
1105
1125
|
return s;
|
|
1106
1126
|
}
|
|
1107
1127
|
/**
|
|
@@ -1110,8 +1130,8 @@ class F {
|
|
|
1110
1130
|
generateUniformsCode() {
|
|
1111
1131
|
const e = [];
|
|
1112
1132
|
if (this.requirements.uniforms.size > 0)
|
|
1113
|
-
for (const
|
|
1114
|
-
e.push(`uniform ${
|
|
1133
|
+
for (const t of this.checkUniformsPresence())
|
|
1134
|
+
e.push(`uniform ${t.type} ${t.name};`);
|
|
1115
1135
|
return e.length === 0 ? "" : e.join(`
|
|
1116
1136
|
`) + `
|
|
1117
1137
|
`;
|
|
@@ -1122,10 +1142,10 @@ class F {
|
|
|
1122
1142
|
generateFunctionCode() {
|
|
1123
1143
|
const e = [];
|
|
1124
1144
|
if (this.requirements.functions.size > 0)
|
|
1125
|
-
for (const
|
|
1126
|
-
const
|
|
1145
|
+
for (const t of this.checkFunctionsPresence()) {
|
|
1146
|
+
const n = t.params.map((i) => `${i.type} ${i.name}`).join(", ");
|
|
1127
1147
|
e.push(`
|
|
1128
|
-
${
|
|
1148
|
+
${t.type} ${t.name}(${n}) ${t.body}`);
|
|
1129
1149
|
}
|
|
1130
1150
|
return e.length === 0 ? "" : e.join(`
|
|
1131
1151
|
`) + `
|
|
@@ -1135,91 +1155,91 @@ ${n.type} ${n.name}(${t}) ${n.body}`);
|
|
|
1135
1155
|
* Check which required uniforms are missing from the original shader
|
|
1136
1156
|
*/
|
|
1137
1157
|
checkUniformsPresence() {
|
|
1138
|
-
const e = this.original.parse(),
|
|
1139
|
-
for (const [i, r] of
|
|
1140
|
-
const s = e.uniforms.find((
|
|
1158
|
+
const e = this.original.parse(), t = [], n = this.requirements.uniforms;
|
|
1159
|
+
for (const [i, r] of n) {
|
|
1160
|
+
const s = e.uniforms.find((a) => a.name === i);
|
|
1141
1161
|
if (!s) {
|
|
1142
|
-
|
|
1162
|
+
t.push(r);
|
|
1143
1163
|
continue;
|
|
1144
1164
|
}
|
|
1145
1165
|
if (s.type !== r.type)
|
|
1146
|
-
throw new
|
|
1166
|
+
throw new U(
|
|
1147
1167
|
"uniform",
|
|
1148
1168
|
i,
|
|
1149
1169
|
r.type,
|
|
1150
1170
|
s.type
|
|
1151
1171
|
);
|
|
1152
1172
|
}
|
|
1153
|
-
return
|
|
1173
|
+
return t;
|
|
1154
1174
|
}
|
|
1155
1175
|
/**
|
|
1156
1176
|
* Check which required functions are missing from the original shader
|
|
1157
1177
|
*/
|
|
1158
1178
|
checkFunctionsPresence() {
|
|
1159
|
-
const e = this.original.parse(),
|
|
1160
|
-
for (const [i, r] of
|
|
1161
|
-
const s = e.functions.find((
|
|
1179
|
+
const e = this.original.parse(), t = [], n = this.requirements.functions;
|
|
1180
|
+
for (const [i, r] of n) {
|
|
1181
|
+
const s = e.functions.find((a) => a.name === i);
|
|
1162
1182
|
if (!s) {
|
|
1163
|
-
|
|
1183
|
+
t.push(r);
|
|
1164
1184
|
continue;
|
|
1165
1185
|
}
|
|
1166
1186
|
if (s.type !== r.type)
|
|
1167
|
-
throw new
|
|
1187
|
+
throw new U(
|
|
1168
1188
|
"function",
|
|
1169
1189
|
i,
|
|
1170
1190
|
r.type,
|
|
1171
1191
|
s.type
|
|
1172
1192
|
);
|
|
1173
1193
|
}
|
|
1174
|
-
return
|
|
1194
|
+
return t;
|
|
1175
1195
|
}
|
|
1176
1196
|
}
|
|
1177
1197
|
class v extends F {
|
|
1178
|
-
constructor(
|
|
1179
|
-
super(
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
this.name =
|
|
1183
|
-
}
|
|
1184
|
-
resolveOptions(
|
|
1185
|
-
if (!(
|
|
1186
|
-
const
|
|
1187
|
-
for (const r of
|
|
1198
|
+
constructor(t, n, i = {}) {
|
|
1199
|
+
super(n);
|
|
1200
|
+
o(this, "name");
|
|
1201
|
+
o(this, "options", {});
|
|
1202
|
+
this.name = t, this.options = this.resolveOptions(i);
|
|
1203
|
+
}
|
|
1204
|
+
resolveOptions(t) {
|
|
1205
|
+
if (!(t != null && t.default)) return t || {};
|
|
1206
|
+
const n = this.original.parse(), i = t.default;
|
|
1207
|
+
for (const r of n.functions)
|
|
1188
1208
|
if (!(r.name === "main" || r.name === "default"))
|
|
1189
|
-
if (
|
|
1190
|
-
const s =
|
|
1191
|
-
for (const
|
|
1192
|
-
|
|
1209
|
+
if (t[r.name]) {
|
|
1210
|
+
const s = t[r.name];
|
|
1211
|
+
for (const a in i)
|
|
1212
|
+
a in s || (s[a] = i[a]);
|
|
1193
1213
|
} else
|
|
1194
|
-
|
|
1195
|
-
return delete
|
|
1214
|
+
t[r.name] = { ...i };
|
|
1215
|
+
return delete t.default, t || {};
|
|
1196
1216
|
}
|
|
1197
1217
|
/**
|
|
1198
1218
|
* Define a module with given name and source, and register it
|
|
1199
1219
|
*/
|
|
1200
|
-
static define(
|
|
1201
|
-
const { name:
|
|
1202
|
-
if (
|
|
1203
|
-
throw new
|
|
1204
|
-
const s = new v(
|
|
1205
|
-
if (
|
|
1206
|
-
throw new
|
|
1207
|
-
return
|
|
1220
|
+
static define(t) {
|
|
1221
|
+
const { name: n, source: i, options: r } = t;
|
|
1222
|
+
if (n === "sandbox" || n.startsWith("sandbox/"))
|
|
1223
|
+
throw new J(n);
|
|
1224
|
+
const s = new v(n, i, r);
|
|
1225
|
+
if (w.has(n))
|
|
1226
|
+
throw new Z(n);
|
|
1227
|
+
return w.register(n, s), s;
|
|
1208
1228
|
}
|
|
1209
1229
|
/**
|
|
1210
1230
|
* Resolve a module by name from the registry, throwing an error if not found
|
|
1211
1231
|
*/
|
|
1212
|
-
static resolve(
|
|
1213
|
-
return
|
|
1232
|
+
static resolve(t) {
|
|
1233
|
+
return w.resolve(t);
|
|
1214
1234
|
}
|
|
1215
1235
|
/**
|
|
1216
1236
|
* Create a copy of the module. To unplug references to the original object.
|
|
1217
1237
|
* Used when copying module to the runtime registry to allow independent runtime changes to options without affecting the original module definition.
|
|
1218
1238
|
*/
|
|
1219
|
-
copy(
|
|
1239
|
+
copy(t = "original") {
|
|
1220
1240
|
return new v(
|
|
1221
1241
|
this.name,
|
|
1222
|
-
this[
|
|
1242
|
+
this[t].source,
|
|
1223
1243
|
JSON.parse(JSON.stringify(this.options))
|
|
1224
1244
|
);
|
|
1225
1245
|
}
|
|
@@ -1227,14 +1247,14 @@ class v extends F {
|
|
|
1227
1247
|
* Merge options from another module into this one, without affecting the original module definition.
|
|
1228
1248
|
* Used when merging imported modules into the runtime registry.
|
|
1229
1249
|
*/
|
|
1230
|
-
merge(
|
|
1250
|
+
merge(t) {
|
|
1231
1251
|
this.options = this.options || {};
|
|
1232
|
-
const
|
|
1233
|
-
for (const [i, r] of Object.entries(
|
|
1252
|
+
const n = this.getDefinition().uniforms.map((i) => i.name);
|
|
1253
|
+
for (const [i, r] of Object.entries(t.options ?? {}))
|
|
1234
1254
|
if (!this.options[i]) this.options[i] = r;
|
|
1235
1255
|
else
|
|
1236
|
-
for (const [s,
|
|
1237
|
-
|
|
1256
|
+
for (const [s, a] of Object.entries(r))
|
|
1257
|
+
n.includes(a.uniform) || (this.options[i][s] = a);
|
|
1238
1258
|
}
|
|
1239
1259
|
/**
|
|
1240
1260
|
* Get the module definition
|
|
@@ -1242,34 +1262,34 @@ class v extends F {
|
|
|
1242
1262
|
getDefinition() {
|
|
1243
1263
|
return this.compile(), {
|
|
1244
1264
|
name: this.name,
|
|
1245
|
-
methods: this.compiled.parse().functions.map((
|
|
1246
|
-
uniforms: this.compiled.parse().uniforms.map((
|
|
1265
|
+
methods: this.compiled.parse().functions.map((t) => t.name).filter((t) => t !== "main" && t !== "default"),
|
|
1266
|
+
uniforms: this.compiled.parse().uniforms.map((t) => ({ name: t.name, type: t.type })),
|
|
1247
1267
|
options: this.options
|
|
1248
1268
|
};
|
|
1249
1269
|
}
|
|
1250
1270
|
/**
|
|
1251
1271
|
* Extract a method with all its dependencies
|
|
1252
1272
|
*/
|
|
1253
|
-
extract(
|
|
1254
|
-
if (this.compile(),
|
|
1273
|
+
extract(t) {
|
|
1274
|
+
if (this.compile(), t === "main")
|
|
1255
1275
|
throw new K(this.name);
|
|
1256
|
-
if (
|
|
1257
|
-
throw new
|
|
1258
|
-
const
|
|
1276
|
+
if (t === "default")
|
|
1277
|
+
throw new Q(this.name);
|
|
1278
|
+
const n = this.compiled.parse(), i = n.functions.find((a) => a.name === t);
|
|
1259
1279
|
if (!i)
|
|
1260
|
-
throw new Y(this.name,
|
|
1280
|
+
throw new Y(this.name, t);
|
|
1261
1281
|
const r = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map();
|
|
1262
1282
|
return this.collectDependencies({
|
|
1263
1283
|
current: i,
|
|
1264
1284
|
scope: {
|
|
1265
|
-
functions:
|
|
1266
|
-
uniforms:
|
|
1285
|
+
functions: n.functions,
|
|
1286
|
+
uniforms: n.uniforms
|
|
1267
1287
|
},
|
|
1268
1288
|
collected: {
|
|
1269
1289
|
functions: r,
|
|
1270
1290
|
uniforms: s
|
|
1271
1291
|
},
|
|
1272
|
-
visited: /* @__PURE__ */ new Set([
|
|
1292
|
+
visited: /* @__PURE__ */ new Set([t])
|
|
1273
1293
|
}), {
|
|
1274
1294
|
function: i,
|
|
1275
1295
|
dependencies: {
|
|
@@ -1281,36 +1301,36 @@ class v extends F {
|
|
|
1281
1301
|
/**
|
|
1282
1302
|
* Recursively collect all function and uniform dependencies
|
|
1283
1303
|
*/
|
|
1284
|
-
collectDependencies(
|
|
1285
|
-
for (const
|
|
1286
|
-
if (
|
|
1287
|
-
if (
|
|
1288
|
-
const i =
|
|
1289
|
-
i && (
|
|
1304
|
+
collectDependencies(t) {
|
|
1305
|
+
for (const n of t.current.dependencies)
|
|
1306
|
+
if (n.type === "function") {
|
|
1307
|
+
if (t.visited.has(n.name)) continue;
|
|
1308
|
+
const i = t.scope.functions.find((r) => r.name === n.name);
|
|
1309
|
+
i && (t.visited.add(n.name), t.collected.functions.set(n.name, i), this.collectDependencies({
|
|
1290
1310
|
current: i,
|
|
1291
1311
|
scope: {
|
|
1292
|
-
functions:
|
|
1293
|
-
uniforms:
|
|
1312
|
+
functions: t.scope.functions,
|
|
1313
|
+
uniforms: t.scope.uniforms
|
|
1294
1314
|
},
|
|
1295
1315
|
collected: {
|
|
1296
|
-
functions:
|
|
1297
|
-
uniforms:
|
|
1316
|
+
functions: t.collected.functions,
|
|
1317
|
+
uniforms: t.collected.uniforms
|
|
1298
1318
|
},
|
|
1299
|
-
visited:
|
|
1319
|
+
visited: t.visited
|
|
1300
1320
|
}));
|
|
1301
|
-
} else if (
|
|
1302
|
-
const i =
|
|
1303
|
-
(r) => r.name ===
|
|
1321
|
+
} else if (n.type === "uniform") {
|
|
1322
|
+
const i = t.scope.uniforms.find(
|
|
1323
|
+
(r) => r.name === n.name
|
|
1304
1324
|
);
|
|
1305
|
-
i && !
|
|
1325
|
+
i && !t.collected.uniforms.has(n.name) && t.collected.uniforms.set(n.name, i);
|
|
1306
1326
|
}
|
|
1307
1327
|
}
|
|
1308
1328
|
}
|
|
1309
1329
|
class V {
|
|
1310
1330
|
constructor(e = []) {
|
|
1311
|
-
|
|
1312
|
-
e.forEach((
|
|
1313
|
-
this.register(
|
|
1331
|
+
o(this, "modules", /* @__PURE__ */ new Map());
|
|
1332
|
+
e.forEach((t) => {
|
|
1333
|
+
this.register(t.name, t);
|
|
1314
1334
|
});
|
|
1315
1335
|
}
|
|
1316
1336
|
/**
|
|
@@ -1335,14 +1355,14 @@ class V {
|
|
|
1335
1355
|
*/
|
|
1336
1356
|
defaults() {
|
|
1337
1357
|
const e = {};
|
|
1338
|
-
return this.modules.forEach((
|
|
1339
|
-
const
|
|
1340
|
-
if (
|
|
1341
|
-
for (const i in
|
|
1342
|
-
const r =
|
|
1358
|
+
return this.modules.forEach((t) => {
|
|
1359
|
+
const n = t.getDefinition();
|
|
1360
|
+
if (n.options)
|
|
1361
|
+
for (const i in n.options) {
|
|
1362
|
+
const r = n.options[i];
|
|
1343
1363
|
for (const s in r) {
|
|
1344
|
-
const
|
|
1345
|
-
|
|
1364
|
+
const a = r[s];
|
|
1365
|
+
a.default !== void 0 && !n.uniforms.map((l) => l.name).includes(a.uniform) && (e[a.uniform] = a.default);
|
|
1346
1366
|
}
|
|
1347
1367
|
}
|
|
1348
1368
|
}), e;
|
|
@@ -1351,33 +1371,33 @@ class V {
|
|
|
1351
1371
|
* Resolve the options from the module definitions for a given function name.
|
|
1352
1372
|
*/
|
|
1353
1373
|
resolveOptions(e) {
|
|
1354
|
-
for (const
|
|
1355
|
-
if (
|
|
1356
|
-
return
|
|
1374
|
+
for (const t of this.modules.values())
|
|
1375
|
+
if (t.options && t.options[e])
|
|
1376
|
+
return t.options[e];
|
|
1357
1377
|
return null;
|
|
1358
1378
|
}
|
|
1359
1379
|
/**
|
|
1360
1380
|
* Register a new module in the registry.
|
|
1361
1381
|
*/
|
|
1362
|
-
register(e,
|
|
1363
|
-
this.modules.set(e,
|
|
1382
|
+
register(e, t) {
|
|
1383
|
+
this.modules.set(e, t);
|
|
1364
1384
|
}
|
|
1365
1385
|
/**
|
|
1366
1386
|
* Merge a module into the registry. If a module with the same name already exists, options will be merged together.
|
|
1367
1387
|
*/
|
|
1368
|
-
merge(e,
|
|
1369
|
-
if (!this.modules.has(e)) return this.register(e,
|
|
1370
|
-
const
|
|
1371
|
-
|
|
1388
|
+
merge(e, t) {
|
|
1389
|
+
if (!this.modules.has(e)) return this.register(e, t);
|
|
1390
|
+
const n = this.modules.get(e);
|
|
1391
|
+
n.merge(t), this.modules.set(e, n);
|
|
1372
1392
|
}
|
|
1373
1393
|
/**
|
|
1374
1394
|
* Resolve a module by name. Throws an error if the module is not found.
|
|
1375
1395
|
*/
|
|
1376
1396
|
resolve(e) {
|
|
1377
|
-
const
|
|
1378
|
-
if (!
|
|
1379
|
-
throw new
|
|
1380
|
-
return
|
|
1397
|
+
const t = this.modules.get(e);
|
|
1398
|
+
if (!t)
|
|
1399
|
+
throw new X(e);
|
|
1400
|
+
return t;
|
|
1381
1401
|
}
|
|
1382
1402
|
/**
|
|
1383
1403
|
* Check if a module exists in the registry by name.
|
|
@@ -1401,8 +1421,8 @@ class V {
|
|
|
1401
1421
|
* Load multiple modules into the registry at once.
|
|
1402
1422
|
*/
|
|
1403
1423
|
load(e) {
|
|
1404
|
-
e.forEach((
|
|
1405
|
-
this.register(
|
|
1424
|
+
e.forEach((t) => {
|
|
1425
|
+
this.register(t.name, t);
|
|
1406
1426
|
});
|
|
1407
1427
|
}
|
|
1408
1428
|
/**
|
|
@@ -1412,7 +1432,7 @@ class V {
|
|
|
1412
1432
|
this.modules.clear();
|
|
1413
1433
|
}
|
|
1414
1434
|
}
|
|
1415
|
-
const
|
|
1435
|
+
const ae = `// ─── Constants ──────────────────────────────────────────────
|
|
1416
1436
|
|
|
1417
1437
|
const float PI = 3.14159265359;
|
|
1418
1438
|
const float TAU = 6.28318530718;
|
|
@@ -1621,7 +1641,7 @@ vec2 voronoi(vec2 p) {
|
|
|
1621
1641
|
}
|
|
1622
1642
|
|
|
1623
1643
|
void main() {}
|
|
1624
|
-
`,
|
|
1644
|
+
`, le = `/**
|
|
1625
1645
|
* Hex integer to RGB.
|
|
1626
1646
|
* Usage: hex(0xFF6600) → orange
|
|
1627
1647
|
*/
|
|
@@ -1720,7 +1740,7 @@ vec3 iridescent(vec2 uv, float time, float speed) {
|
|
|
1720
1740
|
}
|
|
1721
1741
|
|
|
1722
1742
|
void main() {}
|
|
1723
|
-
`,
|
|
1743
|
+
`, ce = `// ─── Time Shapers ──────────────────────────────────────────
|
|
1724
1744
|
// Convert raw time (u_time) to normalized 0–1 range.
|
|
1725
1745
|
// Output feeds directly into easing functions.
|
|
1726
1746
|
|
|
@@ -1842,7 +1862,7 @@ float teleport(float t) {
|
|
|
1842
1862
|
}
|
|
1843
1863
|
|
|
1844
1864
|
void main() {}
|
|
1845
|
-
`,
|
|
1865
|
+
`, ue = `#import hash from 'sandbox'
|
|
1846
1866
|
#import noise from 'sandbox'
|
|
1847
1867
|
#import fbm from 'sandbox'
|
|
1848
1868
|
#import voronoi from 'sandbox'
|
|
@@ -2037,7 +2057,7 @@ vec2 cells(vec2 uv, float intensity) {
|
|
|
2037
2057
|
}
|
|
2038
2058
|
|
|
2039
2059
|
void main() {}
|
|
2040
|
-
`,
|
|
2060
|
+
`, fe = `#import hash from 'sandbox'
|
|
2041
2061
|
|
|
2042
2062
|
uniform float u_intensity;
|
|
2043
2063
|
|
|
@@ -2224,11 +2244,11 @@ vec3 arcade(vec3 color, vec2 uv, float intensity) {
|
|
|
2224
2244
|
}
|
|
2225
2245
|
|
|
2226
2246
|
void main() {}
|
|
2227
|
-
`,
|
|
2228
|
-
new v("sandbox",
|
|
2229
|
-
new v("sandbox/colors",
|
|
2230
|
-
new v("sandbox/time",
|
|
2231
|
-
new v("sandbox/effects",
|
|
2247
|
+
`, w = new V([
|
|
2248
|
+
new v("sandbox", ae),
|
|
2249
|
+
new v("sandbox/colors", le),
|
|
2250
|
+
new v("sandbox/time", ce),
|
|
2251
|
+
new v("sandbox/effects", ue, {
|
|
2232
2252
|
default: {
|
|
2233
2253
|
intensity: { uniform: "u_intensity", default: 1 }
|
|
2234
2254
|
},
|
|
@@ -2278,7 +2298,7 @@ void main() {}
|
|
|
2278
2298
|
intensity: { uniform: "u_intensity", default: 1 }
|
|
2279
2299
|
}
|
|
2280
2300
|
}),
|
|
2281
|
-
new v("sandbox/filters",
|
|
2301
|
+
new v("sandbox/filters", fe, {
|
|
2282
2302
|
default: {
|
|
2283
2303
|
intensity: { uniform: "u_intensity", default: 1 }
|
|
2284
2304
|
},
|
|
@@ -2307,18 +2327,18 @@ void main() {}
|
|
|
2307
2327
|
intensity: { uniform: "u_intensity", default: 0.5 }
|
|
2308
2328
|
}
|
|
2309
2329
|
})
|
|
2310
|
-
]), y = new V(),
|
|
2330
|
+
]), y = new V(), R = /* @__PURE__ */ new Map([
|
|
2311
2331
|
["u_resolution", "vec2"],
|
|
2312
2332
|
["u_time", "float"],
|
|
2313
2333
|
["u_delta", "float"],
|
|
2314
2334
|
["u_mouse", "vec2"],
|
|
2315
2335
|
["u_frame", "int"]
|
|
2316
2336
|
]);
|
|
2317
|
-
class
|
|
2337
|
+
class he {
|
|
2318
2338
|
constructor(e) {
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2339
|
+
o(this, "gl");
|
|
2340
|
+
o(this, "program", null);
|
|
2341
|
+
o(this, "uniforms", /* @__PURE__ */ new Map());
|
|
2322
2342
|
this.gl = e;
|
|
2323
2343
|
}
|
|
2324
2344
|
/**
|
|
@@ -2327,32 +2347,32 @@ class fe {
|
|
|
2327
2347
|
*/
|
|
2328
2348
|
attachProgram(e) {
|
|
2329
2349
|
this.program = e;
|
|
2330
|
-
for (const
|
|
2331
|
-
|
|
2350
|
+
for (const t of this.uniforms.values())
|
|
2351
|
+
t.invalidateLocation();
|
|
2332
2352
|
return this;
|
|
2333
2353
|
}
|
|
2334
2354
|
/**
|
|
2335
2355
|
* Set a uniform value.
|
|
2336
2356
|
* Creates the uniform if it doesn't exist, updates if it does.
|
|
2337
2357
|
*/
|
|
2338
|
-
set(e,
|
|
2339
|
-
const
|
|
2340
|
-
return
|
|
2358
|
+
set(e, t) {
|
|
2359
|
+
const n = this.uniforms.get(e);
|
|
2360
|
+
return n ? n.setValue(t) : this.uniforms.set(e, new M(e, t)), this;
|
|
2341
2361
|
}
|
|
2342
2362
|
/**
|
|
2343
2363
|
* Set multiple uniforms at once.
|
|
2344
2364
|
*/
|
|
2345
2365
|
setMany(e) {
|
|
2346
|
-
for (const [
|
|
2347
|
-
this.set(
|
|
2366
|
+
for (const [t, n] of Object.entries(e))
|
|
2367
|
+
this.set(t, n);
|
|
2348
2368
|
return this;
|
|
2349
2369
|
}
|
|
2350
2370
|
/**
|
|
2351
2371
|
* Get current uniform value.
|
|
2352
2372
|
*/
|
|
2353
2373
|
get(e) {
|
|
2354
|
-
var
|
|
2355
|
-
return (
|
|
2374
|
+
var t;
|
|
2375
|
+
return (t = this.uniforms.get(e)) == null ? void 0 : t.getValue();
|
|
2356
2376
|
}
|
|
2357
2377
|
/**
|
|
2358
2378
|
* Check if uniform exists.
|
|
@@ -2381,10 +2401,10 @@ class fe {
|
|
|
2381
2401
|
* Upload only built-in uniforms (u_resolution, u_time, u_delta, u_mouse, u_frame).
|
|
2382
2402
|
* Call this every frame with current values.
|
|
2383
2403
|
*/
|
|
2384
|
-
uploadBuiltIns(e,
|
|
2385
|
-
if (this.set("u_resolution",
|
|
2404
|
+
uploadBuiltIns(e, t, n) {
|
|
2405
|
+
if (this.set("u_resolution", t), this.set("u_time", e.time), this.set("u_delta", e.delta), this.set("u_mouse", n), this.set("u_frame", e.frame), !this.program)
|
|
2386
2406
|
return this;
|
|
2387
|
-
for (const i of
|
|
2407
|
+
for (const i of R.keys()) {
|
|
2388
2408
|
const r = this.uniforms.get(i);
|
|
2389
2409
|
r && r.upload(this.gl, this.program);
|
|
2390
2410
|
}
|
|
@@ -2415,17 +2435,217 @@ class fe {
|
|
|
2415
2435
|
return this.uniforms.size;
|
|
2416
2436
|
}
|
|
2417
2437
|
}
|
|
2418
|
-
class
|
|
2438
|
+
class x {
|
|
2439
|
+
constructor(e, t, n, i) {
|
|
2440
|
+
o(this, "name");
|
|
2441
|
+
o(this, "gl");
|
|
2442
|
+
o(this, "texture", null);
|
|
2443
|
+
o(this, "location", null);
|
|
2444
|
+
o(this, "locationResolved", !1);
|
|
2445
|
+
o(this, "source");
|
|
2446
|
+
o(this, "options");
|
|
2447
|
+
o(this, "dynamicOverride");
|
|
2448
|
+
o(this, "needsUpload", !0);
|
|
2449
|
+
o(this, "needsReupload", !1);
|
|
2450
|
+
this.gl = e, this.name = t, this.source = n, this.dynamicOverride = i == null ? void 0 : i.dynamic, this.options = x.resolveOptions(n, i), this.needsReupload = this.options.dynamic;
|
|
2451
|
+
}
|
|
2452
|
+
/**
|
|
2453
|
+
* Update the texture source.
|
|
2454
|
+
* Marks texture for re-upload on next bind.
|
|
2455
|
+
* Respects the original `dynamic` option if explicitly set, otherwise re-infers from source type.
|
|
2456
|
+
*/
|
|
2457
|
+
setSource(e) {
|
|
2458
|
+
this.source = e, this.needsUpload = !0, this.needsReupload = this.dynamicOverride ?? x.isDynamicSource(e);
|
|
2459
|
+
}
|
|
2460
|
+
/**
|
|
2461
|
+
* Resolve and cache uniform location from program.
|
|
2462
|
+
* Returns null if the sampler uniform doesn't exist in the shader.
|
|
2463
|
+
*/
|
|
2464
|
+
resolveLocation(e, t) {
|
|
2465
|
+
return this.locationResolved || (this.location = e.getUniformLocation(t, this.name), this.locationResolved = !0), this.location;
|
|
2466
|
+
}
|
|
2467
|
+
/**
|
|
2468
|
+
* Invalidate cached location (call when program changes).
|
|
2469
|
+
*/
|
|
2470
|
+
invalidateLocation() {
|
|
2471
|
+
this.location = null, this.locationResolved = !1;
|
|
2472
|
+
}
|
|
2473
|
+
/**
|
|
2474
|
+
* Bind texture to a texture unit and set the sampler uniform.
|
|
2475
|
+
* @param program - Current WebGL program (for location resolution)
|
|
2476
|
+
* @param unit - Texture unit index (0, 1, 2, ...)
|
|
2477
|
+
*/
|
|
2478
|
+
upload(e, t) {
|
|
2479
|
+
const n = this.gl, i = this.resolveLocation(n, e);
|
|
2480
|
+
if (i !== null) {
|
|
2481
|
+
if (!this.texture) {
|
|
2482
|
+
if (this.texture = n.createTexture(), !this.texture) return;
|
|
2483
|
+
this.needsUpload = !0;
|
|
2484
|
+
}
|
|
2485
|
+
n.activeTexture(n.TEXTURE0 + t), n.bindTexture(n.TEXTURE_2D, this.texture), (this.needsUpload || this.needsReupload) && (this.uploadPixels(), this.needsUpload = !1), n.uniform1i(i, t);
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
/**
|
|
2489
|
+
* Cleanup WebGL texture resource.
|
|
2490
|
+
*/
|
|
2491
|
+
destroy() {
|
|
2492
|
+
this.texture && (this.gl.deleteTexture(this.texture), this.texture = null), this.location = null, this.locationResolved = !1;
|
|
2493
|
+
}
|
|
2494
|
+
/**
|
|
2495
|
+
* Upload pixel data from source and apply texture parameters.
|
|
2496
|
+
*/
|
|
2497
|
+
uploadPixels() {
|
|
2498
|
+
const e = this.gl;
|
|
2499
|
+
e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL, this.options.flipY), e.texImage2D(
|
|
2500
|
+
e.TEXTURE_2D,
|
|
2501
|
+
0,
|
|
2502
|
+
e.RGBA,
|
|
2503
|
+
e.RGBA,
|
|
2504
|
+
e.UNSIGNED_BYTE,
|
|
2505
|
+
this.source
|
|
2506
|
+
), this.applyParameters();
|
|
2507
|
+
}
|
|
2508
|
+
/**
|
|
2509
|
+
* Apply texture wrap and filter parameters.
|
|
2510
|
+
*/
|
|
2511
|
+
applyParameters() {
|
|
2512
|
+
const e = this.gl;
|
|
2513
|
+
e.texParameteri(
|
|
2514
|
+
e.TEXTURE_2D,
|
|
2515
|
+
e.TEXTURE_WRAP_S,
|
|
2516
|
+
x.resolveWrap(e, this.options.wrapS)
|
|
2517
|
+
), e.texParameteri(
|
|
2518
|
+
e.TEXTURE_2D,
|
|
2519
|
+
e.TEXTURE_WRAP_T,
|
|
2520
|
+
x.resolveWrap(e, this.options.wrapT)
|
|
2521
|
+
), e.texParameteri(
|
|
2522
|
+
e.TEXTURE_2D,
|
|
2523
|
+
e.TEXTURE_MIN_FILTER,
|
|
2524
|
+
this.options.minFilter === "nearest" ? e.NEAREST : e.LINEAR
|
|
2525
|
+
), e.texParameteri(
|
|
2526
|
+
e.TEXTURE_2D,
|
|
2527
|
+
e.TEXTURE_MAG_FILTER,
|
|
2528
|
+
this.options.magFilter === "nearest" ? e.NEAREST : e.LINEAR
|
|
2529
|
+
);
|
|
2530
|
+
}
|
|
2531
|
+
/**
|
|
2532
|
+
* Resolve wrap mode string to WebGL constant.
|
|
2533
|
+
*/
|
|
2534
|
+
static resolveWrap(e, t) {
|
|
2535
|
+
switch (t) {
|
|
2536
|
+
case "repeat":
|
|
2537
|
+
return e.REPEAT;
|
|
2538
|
+
case "mirror":
|
|
2539
|
+
return e.MIRRORED_REPEAT;
|
|
2540
|
+
case "clamp":
|
|
2541
|
+
default:
|
|
2542
|
+
return e.CLAMP_TO_EDGE;
|
|
2543
|
+
}
|
|
2544
|
+
}
|
|
2545
|
+
/**
|
|
2546
|
+
* Resolve texture options with defaults.
|
|
2547
|
+
*/
|
|
2548
|
+
static resolveOptions(e, t) {
|
|
2549
|
+
const n = (t == null ? void 0 : t.wrap) ?? "clamp";
|
|
2550
|
+
return {
|
|
2551
|
+
wrap: n,
|
|
2552
|
+
wrapS: (t == null ? void 0 : t.wrapS) ?? n,
|
|
2553
|
+
wrapT: (t == null ? void 0 : t.wrapT) ?? n,
|
|
2554
|
+
minFilter: (t == null ? void 0 : t.minFilter) ?? "linear",
|
|
2555
|
+
magFilter: (t == null ? void 0 : t.magFilter) ?? "linear",
|
|
2556
|
+
flipY: (t == null ? void 0 : t.flipY) ?? !0,
|
|
2557
|
+
dynamic: (t == null ? void 0 : t.dynamic) ?? x.isDynamicSource(e)
|
|
2558
|
+
};
|
|
2559
|
+
}
|
|
2560
|
+
/**
|
|
2561
|
+
* Check if a source is dynamic (needs re-upload every frame).
|
|
2562
|
+
*/
|
|
2563
|
+
static isDynamicSource(e) {
|
|
2564
|
+
return e instanceof HTMLVideoElement;
|
|
2565
|
+
}
|
|
2566
|
+
}
|
|
2567
|
+
class me {
|
|
2568
|
+
constructor(e) {
|
|
2569
|
+
o(this, "gl");
|
|
2570
|
+
o(this, "program", null);
|
|
2571
|
+
o(this, "textures", /* @__PURE__ */ new Map());
|
|
2572
|
+
this.gl = e;
|
|
2573
|
+
}
|
|
2574
|
+
/**
|
|
2575
|
+
* Attach to a WebGL program.
|
|
2576
|
+
* Invalidates all cached locations since they're program-specific.
|
|
2577
|
+
*/
|
|
2578
|
+
attachProgram(e) {
|
|
2579
|
+
this.program = e;
|
|
2580
|
+
for (const t of this.textures.values())
|
|
2581
|
+
t.invalidateLocation();
|
|
2582
|
+
return this;
|
|
2583
|
+
}
|
|
2584
|
+
/**
|
|
2585
|
+
* Set a texture.
|
|
2586
|
+
* Creates the texture entry if it doesn't exist, updates source if it does.
|
|
2587
|
+
*/
|
|
2588
|
+
set(e, t, n) {
|
|
2589
|
+
const i = this.textures.get(e);
|
|
2590
|
+
return i ? i.setSource(t) : this.textures.set(e, new x(this.gl, e, t, n)), this;
|
|
2591
|
+
}
|
|
2592
|
+
/**
|
|
2593
|
+
* Get a texture by name.
|
|
2594
|
+
*/
|
|
2595
|
+
get(e) {
|
|
2596
|
+
return this.textures.get(e);
|
|
2597
|
+
}
|
|
2598
|
+
/**
|
|
2599
|
+
* Check if a texture exists.
|
|
2600
|
+
*/
|
|
2601
|
+
has(e) {
|
|
2602
|
+
return this.textures.has(e);
|
|
2603
|
+
}
|
|
2604
|
+
/**
|
|
2605
|
+
* Remove a texture and free its GPU resources.
|
|
2606
|
+
*/
|
|
2607
|
+
delete(e) {
|
|
2608
|
+
const t = this.textures.get(e);
|
|
2609
|
+
return t ? (t.destroy(), this.textures.delete(e)) : !1;
|
|
2610
|
+
}
|
|
2611
|
+
/**
|
|
2612
|
+
* Upload all textures to their respective texture units.
|
|
2613
|
+
* Units are assigned sequentially (0, 1, 2, ...).
|
|
2614
|
+
*/
|
|
2615
|
+
uploadAll() {
|
|
2616
|
+
if (!this.program)
|
|
2617
|
+
return this;
|
|
2618
|
+
let e = 0;
|
|
2619
|
+
for (const t of this.textures.values())
|
|
2620
|
+
t.upload(this.program, e), e++;
|
|
2621
|
+
return this;
|
|
2622
|
+
}
|
|
2623
|
+
/**
|
|
2624
|
+
* Get texture count.
|
|
2625
|
+
*/
|
|
2626
|
+
get size() {
|
|
2627
|
+
return this.textures.size;
|
|
2628
|
+
}
|
|
2629
|
+
/**
|
|
2630
|
+
* Cleanup all textures.
|
|
2631
|
+
*/
|
|
2632
|
+
destroy() {
|
|
2633
|
+
for (const e of this.textures.values())
|
|
2634
|
+
e.destroy();
|
|
2635
|
+
this.textures.clear(), this.program = null;
|
|
2636
|
+
}
|
|
2637
|
+
}
|
|
2638
|
+
class L {
|
|
2419
2639
|
constructor() {
|
|
2420
|
-
|
|
2640
|
+
o(this, "hooks", /* @__PURE__ */ new Map());
|
|
2421
2641
|
}
|
|
2422
2642
|
id() {
|
|
2423
2643
|
return Math.random().toString(36).substring(2, 10);
|
|
2424
2644
|
}
|
|
2425
2645
|
/** Add a new hook, returns a removal function */
|
|
2426
2646
|
add(e) {
|
|
2427
|
-
const
|
|
2428
|
-
return this.hooks.set(
|
|
2647
|
+
const t = this.id();
|
|
2648
|
+
return this.hooks.set(t, e), () => this.remove(t);
|
|
2429
2649
|
}
|
|
2430
2650
|
/** Remove a hook by its ID */
|
|
2431
2651
|
remove(e) {
|
|
@@ -2433,12 +2653,12 @@ class O {
|
|
|
2433
2653
|
}
|
|
2434
2654
|
/** Run all hooks with the given state */
|
|
2435
2655
|
run(e) {
|
|
2436
|
-
for (const [
|
|
2656
|
+
for (const [t, n] of this.hooks)
|
|
2437
2657
|
try {
|
|
2438
|
-
|
|
2658
|
+
n(e) === !1 && this.remove(t);
|
|
2439
2659
|
} catch (i) {
|
|
2440
|
-
throw new
|
|
2441
|
-
|
|
2660
|
+
throw new re(
|
|
2661
|
+
t,
|
|
2442
2662
|
i instanceof Error ? i.message : String(i)
|
|
2443
2663
|
);
|
|
2444
2664
|
}
|
|
@@ -2447,29 +2667,30 @@ class O {
|
|
|
2447
2667
|
this.hooks.clear();
|
|
2448
2668
|
}
|
|
2449
2669
|
}
|
|
2450
|
-
class
|
|
2451
|
-
constructor(e,
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2670
|
+
class T {
|
|
2671
|
+
constructor(e, t) {
|
|
2672
|
+
o(this, "canvas");
|
|
2673
|
+
o(this, "gl");
|
|
2674
|
+
o(this, "options");
|
|
2675
|
+
o(this, "onBeforeHooks", new L());
|
|
2676
|
+
o(this, "onAfterHooks", new L());
|
|
2677
|
+
o(this, "_program");
|
|
2678
|
+
o(this, "_geometry");
|
|
2679
|
+
o(this, "_uniforms");
|
|
2680
|
+
o(this, "_textures");
|
|
2681
|
+
o(this, "_clock");
|
|
2682
|
+
o(this, "_resolution", [1, 1]);
|
|
2683
|
+
o(this, "_mouse", [0, 0]);
|
|
2684
|
+
o(this, "_version", 1);
|
|
2685
|
+
o(this, "playing", !1);
|
|
2686
|
+
this.canvas = e, this.options = t, this.gl = this.initContext(), this.enableExtensions(), this._program = new oe(this.gl), this._geometry = k.fullscreenQuad(this.gl), this._uniforms = new he(this.gl), this._textures = new me(this.gl), this._clock = new se(), this.options.fps && this._clock.setMaxFps(this.options.fps), this.options.onBeforeRender && this.onBeforeHooks.add(this.options.onBeforeRender), this.options.onAfterRender && this.onAfterHooks.add(this.options.onAfterRender), this.onRender = this.onRender.bind(this);
|
|
2466
2687
|
}
|
|
2467
2688
|
/**
|
|
2468
2689
|
* Factory method to create and setup WebGL instance.
|
|
2469
2690
|
*/
|
|
2470
|
-
static setup(e,
|
|
2471
|
-
const
|
|
2472
|
-
return
|
|
2691
|
+
static setup(e, t) {
|
|
2692
|
+
const n = new T(e, t);
|
|
2693
|
+
return t.vertex && t.fragment && n.shader(t.vertex, t.fragment), t.uniforms && n._uniforms.setMany(t.uniforms), t.textures && n.texturesFromSchema(t.textures), y.isEmpty() || n._uniforms.setMany(y.defaults()), n;
|
|
2473
2694
|
}
|
|
2474
2695
|
/**
|
|
2475
2696
|
* Initialize WebGL context.
|
|
@@ -2483,13 +2704,13 @@ class M {
|
|
|
2483
2704
|
alpha: !0,
|
|
2484
2705
|
depth: !1,
|
|
2485
2706
|
stencil: !1
|
|
2486
|
-
},
|
|
2487
|
-
if (n)
|
|
2488
|
-
return this._version = 2, n;
|
|
2489
|
-
const t = this.canvas.getContext("webgl", e);
|
|
2707
|
+
}, t = this.canvas.getContext("webgl2", e);
|
|
2490
2708
|
if (t)
|
|
2491
|
-
return this._version =
|
|
2492
|
-
const
|
|
2709
|
+
return this._version = 2, t;
|
|
2710
|
+
const n = this.canvas.getContext("webgl", e);
|
|
2711
|
+
if (n)
|
|
2712
|
+
return this._version = 1, n;
|
|
2713
|
+
const i = new W();
|
|
2493
2714
|
throw this.options.onError(i), i;
|
|
2494
2715
|
}
|
|
2495
2716
|
/**
|
|
@@ -2501,8 +2722,8 @@ class M {
|
|
|
2501
2722
|
/**
|
|
2502
2723
|
* Set viewport dimensions.
|
|
2503
2724
|
*/
|
|
2504
|
-
viewport(e,
|
|
2505
|
-
return this.canvas.width =
|
|
2725
|
+
viewport(e, t, n, i) {
|
|
2726
|
+
return this.canvas.width = n, this.canvas.height = i, this.gl.viewport(e, t, n, i), this._resolution = [n, i], this;
|
|
2506
2727
|
}
|
|
2507
2728
|
/**
|
|
2508
2729
|
* Set the clock time
|
|
@@ -2513,14 +2734,14 @@ class M {
|
|
|
2513
2734
|
/**
|
|
2514
2735
|
* Update mouse position.
|
|
2515
2736
|
*/
|
|
2516
|
-
mouse(e,
|
|
2517
|
-
return this._mouse = [e,
|
|
2737
|
+
mouse(e, t) {
|
|
2738
|
+
return this._mouse = [e, t], this;
|
|
2518
2739
|
}
|
|
2519
2740
|
/**
|
|
2520
2741
|
* Set a uniform value.
|
|
2521
2742
|
*/
|
|
2522
|
-
uniform(e,
|
|
2523
|
-
return this._uniforms.set(e,
|
|
2743
|
+
uniform(e, t) {
|
|
2744
|
+
return this._uniforms.set(e, t), this;
|
|
2524
2745
|
}
|
|
2525
2746
|
/**
|
|
2526
2747
|
* Set multiple uniforms.
|
|
@@ -2534,29 +2755,54 @@ class M {
|
|
|
2534
2755
|
getUniform(e) {
|
|
2535
2756
|
return this._uniforms.get(e);
|
|
2536
2757
|
}
|
|
2758
|
+
/**
|
|
2759
|
+
* Set a texture.
|
|
2760
|
+
*/
|
|
2761
|
+
texture(e, t, n) {
|
|
2762
|
+
return this._textures.set(e, t, n), this;
|
|
2763
|
+
}
|
|
2764
|
+
/**
|
|
2765
|
+
* Set multiple textures from a schema.
|
|
2766
|
+
*/
|
|
2767
|
+
texturesFromSchema(e) {
|
|
2768
|
+
for (const [t, n] of Object.entries(e))
|
|
2769
|
+
if (n instanceof HTMLImageElement || n instanceof HTMLCanvasElement || n instanceof HTMLVideoElement || n instanceof ImageBitmap || n instanceof ImageData || n instanceof OffscreenCanvas)
|
|
2770
|
+
this._textures.set(t, n);
|
|
2771
|
+
else {
|
|
2772
|
+
const { source: i, ...r } = n;
|
|
2773
|
+
this._textures.set(t, i, r);
|
|
2774
|
+
}
|
|
2775
|
+
return this;
|
|
2776
|
+
}
|
|
2777
|
+
/**
|
|
2778
|
+
* Remove a texture.
|
|
2779
|
+
*/
|
|
2780
|
+
removeTexture(e) {
|
|
2781
|
+
return this._textures.delete(e), this;
|
|
2782
|
+
}
|
|
2537
2783
|
/**
|
|
2538
2784
|
* Compile and link shaders.
|
|
2539
2785
|
* Errors are handled via onError callback, never thrown.
|
|
2540
2786
|
*/
|
|
2541
|
-
shader(e,
|
|
2787
|
+
shader(e, t) {
|
|
2542
2788
|
try {
|
|
2543
|
-
if (y.clear(), e.version() !==
|
|
2544
|
-
throw new
|
|
2789
|
+
if (y.clear(), e.version() !== t.version())
|
|
2790
|
+
throw new z(
|
|
2545
2791
|
e.version(),
|
|
2546
|
-
|
|
2792
|
+
t.version()
|
|
2547
2793
|
);
|
|
2548
|
-
this._program.compile(e.source(),
|
|
2549
|
-
const
|
|
2550
|
-
|
|
2794
|
+
this._program.compile(e.source(), t.compile()), this._version = t.version(), this._geometry.linkAttributes(this._program);
|
|
2795
|
+
const n = this._program.getProgram();
|
|
2796
|
+
n && (this._uniforms.attachProgram(n), this._textures.attachProgram(n));
|
|
2551
2797
|
try {
|
|
2552
2798
|
this.options.onLoad();
|
|
2553
2799
|
} catch (i) {
|
|
2554
|
-
throw new
|
|
2800
|
+
throw new ie(
|
|
2555
2801
|
i instanceof Error ? i.message : String(i)
|
|
2556
2802
|
);
|
|
2557
2803
|
}
|
|
2558
|
-
} catch (
|
|
2559
|
-
|
|
2804
|
+
} catch (n) {
|
|
2805
|
+
n instanceof h && this.options.onError(n);
|
|
2560
2806
|
}
|
|
2561
2807
|
return this;
|
|
2562
2808
|
}
|
|
@@ -2574,14 +2820,14 @@ class M {
|
|
|
2574
2820
|
const e = this._clock.getState();
|
|
2575
2821
|
try {
|
|
2576
2822
|
this.onBeforeHooks.run(e);
|
|
2577
|
-
} catch (
|
|
2578
|
-
|
|
2823
|
+
} catch (t) {
|
|
2824
|
+
t instanceof h && this.options.onError(t);
|
|
2579
2825
|
}
|
|
2580
2826
|
this.playing = !1, this._clock.stop();
|
|
2581
2827
|
try {
|
|
2582
2828
|
this.onAfterHooks.run(e);
|
|
2583
|
-
} catch (
|
|
2584
|
-
|
|
2829
|
+
} catch (t) {
|
|
2830
|
+
t instanceof h && this.options.onError(t);
|
|
2585
2831
|
}
|
|
2586
2832
|
return this;
|
|
2587
2833
|
}
|
|
@@ -2613,34 +2859,34 @@ class M {
|
|
|
2613
2859
|
* Cleanup all resources.
|
|
2614
2860
|
*/
|
|
2615
2861
|
destroy() {
|
|
2616
|
-
this.pause(), this._clock.destroy(), this._geometry.destroy(), this._program.destroy(), this._uniforms.destroy(), this.onAfterHooks.destroy(), this.onBeforeHooks.destroy(), y.clear();
|
|
2862
|
+
this.pause(), this._clock.destroy(), this._geometry.destroy(), this._program.destroy(), this._uniforms.destroy(), this._textures.destroy(), this.onAfterHooks.destroy(), this.onBeforeHooks.destroy(), y.clear();
|
|
2617
2863
|
}
|
|
2618
2864
|
/**
|
|
2619
2865
|
* Internal render callback.
|
|
2620
2866
|
*/
|
|
2621
2867
|
onRender(e) {
|
|
2622
|
-
const
|
|
2868
|
+
const t = this.gl;
|
|
2623
2869
|
try {
|
|
2624
2870
|
this.onBeforeHooks.run(e);
|
|
2625
|
-
} catch (
|
|
2626
|
-
|
|
2871
|
+
} catch (n) {
|
|
2872
|
+
n instanceof h && this.options.onError(n);
|
|
2627
2873
|
}
|
|
2628
|
-
|
|
2874
|
+
t.clearColor(0, 0, 0, 0), t.clear(t.COLOR_BUFFER_BIT), this._program.use(), this._uniforms.uploadBuiltIns(e, this._resolution, this._mouse), this._uniforms.uploadAll(), this._textures.uploadAll(), this._geometry.bind(), this._geometry.draw();
|
|
2629
2875
|
try {
|
|
2630
2876
|
this.onAfterHooks.run(e);
|
|
2631
|
-
} catch (
|
|
2632
|
-
|
|
2877
|
+
} catch (n) {
|
|
2878
|
+
n instanceof h && this.options.onError(n);
|
|
2633
2879
|
}
|
|
2634
2880
|
}
|
|
2635
2881
|
}
|
|
2636
2882
|
class d extends F {
|
|
2637
2883
|
constructor(e) {
|
|
2638
|
-
super(e),
|
|
2639
|
-
this.requirements.uniforms.set(
|
|
2884
|
+
super(e), R.forEach((t, n) => {
|
|
2885
|
+
this.requirements.uniforms.set(n, { name: n, type: t, line: 0 });
|
|
2640
2886
|
});
|
|
2641
2887
|
}
|
|
2642
2888
|
}
|
|
2643
|
-
const
|
|
2889
|
+
const A = `#ifdef GL_ES
|
|
2644
2890
|
precision mediump float;
|
|
2645
2891
|
#endif
|
|
2646
2892
|
|
|
@@ -2653,7 +2899,7 @@ void main() {
|
|
|
2653
2899
|
v_texcoord = a_texcoord;
|
|
2654
2900
|
gl_Position = vec4(a_position, 0.0, 1.0);
|
|
2655
2901
|
}
|
|
2656
|
-
`,
|
|
2902
|
+
`, O = `#ifdef GL_ES
|
|
2657
2903
|
precision mediump float;
|
|
2658
2904
|
#endif
|
|
2659
2905
|
|
|
@@ -2667,7 +2913,7 @@ void main() {
|
|
|
2667
2913
|
vec3 color = vec3(uv.x, uv.y, 0.5 + 0.5 * sin(u_time));
|
|
2668
2914
|
gl_FragColor = vec4(color, 1.0);
|
|
2669
2915
|
}
|
|
2670
|
-
`,
|
|
2916
|
+
`, C = `#version 300 es
|
|
2671
2917
|
|
|
2672
2918
|
in vec2 a_position;
|
|
2673
2919
|
in vec2 a_texcoord;
|
|
@@ -2677,7 +2923,7 @@ out vec2 v_texcoord;
|
|
|
2677
2923
|
void main() {
|
|
2678
2924
|
v_texcoord = a_texcoord;
|
|
2679
2925
|
gl_Position = vec4(a_position, 0.0, 1.0);
|
|
2680
|
-
}`,
|
|
2926
|
+
}`, de = `#version 300 es
|
|
2681
2927
|
precision highp float;
|
|
2682
2928
|
|
|
2683
2929
|
uniform vec2 u_resolution;
|
|
@@ -2692,21 +2938,21 @@ void main() {
|
|
|
2692
2938
|
vec3 color = vec3(uv.x, uv.y, 0.5 + 0.5 * sin(u_time));
|
|
2693
2939
|
fragColor = vec4(color, 1.0);
|
|
2694
2940
|
}`;
|
|
2695
|
-
class
|
|
2696
|
-
constructor(e,
|
|
2941
|
+
class I {
|
|
2942
|
+
constructor(e, t) {
|
|
2697
2943
|
/** Active event listeners */
|
|
2698
|
-
|
|
2944
|
+
o(this, "listeners", []);
|
|
2699
2945
|
/** HTML canvas element */
|
|
2700
|
-
|
|
2946
|
+
o(this, "canvasEl");
|
|
2701
2947
|
/** Resolved options */
|
|
2702
|
-
|
|
2948
|
+
o(this, "options");
|
|
2703
2949
|
/** WebGL engine */
|
|
2704
|
-
|
|
2950
|
+
o(this, "engine");
|
|
2705
2951
|
/** User sets custom vertex shader */
|
|
2706
|
-
|
|
2707
|
-
if (this.canvasEl = e, this.options = this.resolveOptions(
|
|
2708
|
-
for (const [
|
|
2709
|
-
this.module(
|
|
2952
|
+
o(this, "usingCustomVertex", !1);
|
|
2953
|
+
if (this.canvasEl = e, this.options = this.resolveOptions(t), this.engine = T.setup(this.canvasEl, this.options), this.setupListeners(), this.setViewport(), this.options.modules)
|
|
2954
|
+
for (const [n, i] of Object.entries(this.options.modules))
|
|
2955
|
+
this.module(n, i);
|
|
2710
2956
|
this.options.autoplay && this.play();
|
|
2711
2957
|
}
|
|
2712
2958
|
/**
|
|
@@ -2727,8 +2973,8 @@ class $ {
|
|
|
2727
2973
|
* autoplay: true,
|
|
2728
2974
|
* });
|
|
2729
2975
|
*/
|
|
2730
|
-
static create(e,
|
|
2731
|
-
return new
|
|
2976
|
+
static create(e, t) {
|
|
2977
|
+
return new I(e, t);
|
|
2732
2978
|
}
|
|
2733
2979
|
/**
|
|
2734
2980
|
* Define a shader module that can be imported in shader source with `#import <function> from "module_name"`.
|
|
@@ -2740,14 +2986,14 @@ class $ {
|
|
|
2740
2986
|
* // myFunc();
|
|
2741
2987
|
* // }
|
|
2742
2988
|
*/
|
|
2743
|
-
static defineModule(e,
|
|
2744
|
-
v.define({ name: e, source:
|
|
2989
|
+
static defineModule(e, t, n = {}) {
|
|
2990
|
+
v.define({ name: e, source: t, options: n });
|
|
2745
2991
|
}
|
|
2746
2992
|
/**
|
|
2747
2993
|
* Get the list of available shader modules that can be used with `#import` in shader source.
|
|
2748
2994
|
*/
|
|
2749
2995
|
static availableModules() {
|
|
2750
|
-
return
|
|
2996
|
+
return w.available();
|
|
2751
2997
|
}
|
|
2752
2998
|
/**
|
|
2753
2999
|
* Compile a shader source with Sandbox's shader preprocessor and return the final GLSL code.
|
|
@@ -2757,9 +3003,9 @@ class $ {
|
|
|
2757
3003
|
return new d(e).compile();
|
|
2758
3004
|
}
|
|
2759
3005
|
resolveOptions(e) {
|
|
2760
|
-
const
|
|
2761
|
-
vertex: new d(
|
|
2762
|
-
fragment: new d(
|
|
3006
|
+
const t = {
|
|
3007
|
+
vertex: new d(A),
|
|
3008
|
+
fragment: new d(O),
|
|
2763
3009
|
autoplay: !0,
|
|
2764
3010
|
pauseWhenHidden: !0,
|
|
2765
3011
|
dpr: "auto",
|
|
@@ -2779,45 +3025,46 @@ You can handle errors programmatically by providing an onError callback to suppr
|
|
|
2779
3025
|
onBeforeRender: null,
|
|
2780
3026
|
onAfterRender: null,
|
|
2781
3027
|
uniforms: {},
|
|
2782
|
-
modules: {}
|
|
3028
|
+
modules: {},
|
|
3029
|
+
textures: {}
|
|
2783
3030
|
};
|
|
2784
3031
|
if (e != null && e.vertex && (this.usingCustomVertex = !0), e != null && e.vertex && !(e != null && e.fragment)) {
|
|
2785
|
-
|
|
2786
|
-
const s =
|
|
2787
|
-
|
|
3032
|
+
t.vertex = new d(e.vertex);
|
|
3033
|
+
const s = t.vertex.version();
|
|
3034
|
+
t.fragment = new d(s === 2 ? de : O);
|
|
2788
3035
|
}
|
|
2789
3036
|
if (e != null && e.fragment && !(e != null && e.vertex)) {
|
|
2790
|
-
|
|
2791
|
-
const s =
|
|
2792
|
-
|
|
3037
|
+
t.fragment = new d(e.fragment);
|
|
3038
|
+
const s = t.fragment.version();
|
|
3039
|
+
t.vertex = new d(s === 2 ? C : A);
|
|
2793
3040
|
}
|
|
2794
|
-
e != null && e.vertex && (e != null && e.fragment) && (
|
|
2795
|
-
const { vertex:
|
|
2796
|
-
return { ...
|
|
3041
|
+
e != null && e.vertex && (e != null && e.fragment) && (t.vertex = new d(e.vertex), t.fragment = new d(e.fragment));
|
|
3042
|
+
const { vertex: n, fragment: i, ...r } = e || {};
|
|
3043
|
+
return { ...t, ...r };
|
|
2797
3044
|
}
|
|
2798
3045
|
setupListeners() {
|
|
2799
3046
|
this.listeners.push(
|
|
2800
3047
|
// Window resize
|
|
2801
|
-
|
|
3048
|
+
b.on(window, "resize", () => {
|
|
2802
3049
|
this.setViewport();
|
|
2803
3050
|
}),
|
|
2804
3051
|
// Canvas resize
|
|
2805
|
-
|
|
3052
|
+
b.on(this.canvasEl, "resize", () => {
|
|
2806
3053
|
this.setViewport();
|
|
2807
3054
|
}),
|
|
2808
3055
|
// Visibility check on scroll
|
|
2809
3056
|
(() => {
|
|
2810
3057
|
let e = !1;
|
|
2811
|
-
return
|
|
3058
|
+
return b.on(document, "scroll", (t) => {
|
|
2812
3059
|
this.options.pauseWhenHidden && (this.isInViewport() ? e && !this.isPlaying() && (this.play(), e = !1) : this.isPlaying() && (this.pause(), e = !0));
|
|
2813
3060
|
});
|
|
2814
3061
|
})(),
|
|
2815
3062
|
// Mouse tracking
|
|
2816
|
-
|
|
3063
|
+
b.on(document, "mousemove", (e) => {
|
|
2817
3064
|
this.setMouse(e.clientX || e.pageX, e.clientY || e.pageY);
|
|
2818
3065
|
}),
|
|
2819
3066
|
// Touch tracking
|
|
2820
|
-
|
|
3067
|
+
b.on(document, "touchmove", (e) => {
|
|
2821
3068
|
e.touches.length > 0 && this.setMouse(e.touches[0].clientX, e.touches[0].clientY);
|
|
2822
3069
|
})
|
|
2823
3070
|
);
|
|
@@ -2826,21 +3073,21 @@ You can handle errors programmatically by providing an onError callback to suppr
|
|
|
2826
3073
|
this.listeners.forEach((e) => e()), this.listeners = [];
|
|
2827
3074
|
}
|
|
2828
3075
|
setViewport() {
|
|
2829
|
-
const e = this.options.dpr === "auto" ? Math.min(2, window.devicePixelRatio || 1) : this.options.dpr,
|
|
3076
|
+
const e = this.options.dpr === "auto" ? Math.min(2, window.devicePixelRatio || 1) : this.options.dpr, t = this.canvasEl.clientWidth || this.canvasEl.width || 1, n = this.canvasEl.clientHeight || this.canvasEl.height || 1;
|
|
2830
3077
|
this.engine.viewport(
|
|
2831
3078
|
0,
|
|
2832
3079
|
0,
|
|
2833
|
-
Math.max(1, Math.floor(
|
|
2834
|
-
Math.max(1, Math.floor(
|
|
3080
|
+
Math.max(1, Math.floor(t * e)),
|
|
3081
|
+
Math.max(1, Math.floor(n * e))
|
|
2835
3082
|
);
|
|
2836
3083
|
}
|
|
2837
3084
|
isInViewport() {
|
|
2838
3085
|
const e = this.canvasEl.getBoundingClientRect();
|
|
2839
3086
|
return e.bottom >= 0 && e.right >= 0 && e.top <= (window.innerHeight || document.documentElement.clientHeight) && e.left <= (window.innerWidth || document.documentElement.clientWidth);
|
|
2840
3087
|
}
|
|
2841
|
-
setMouse(e,
|
|
2842
|
-
const
|
|
2843
|
-
e >=
|
|
3088
|
+
setMouse(e, t) {
|
|
3089
|
+
const n = this.canvasEl.getBoundingClientRect();
|
|
3090
|
+
e >= n.left && e <= n.right && t >= n.top && t <= n.bottom && this.engine.mouse(e - n.left, t - n.top);
|
|
2844
3091
|
}
|
|
2845
3092
|
/**
|
|
2846
3093
|
* Set a single uniform value with type checking.
|
|
@@ -2849,8 +3096,8 @@ You can handle errors programmatically by providing an onError callback to suppr
|
|
|
2849
3096
|
* sandbox.setUniform<number>("u_time", 1.5);
|
|
2850
3097
|
* sandbox.setUniform<Vec3[]>("u_colors", [[1, 0, 0], [0, 1, 0]]);
|
|
2851
3098
|
*/
|
|
2852
|
-
setUniform(e,
|
|
2853
|
-
return this.engine.uniform(e,
|
|
3099
|
+
setUniform(e, t) {
|
|
3100
|
+
return this.engine.uniform(e, t), this;
|
|
2854
3101
|
}
|
|
2855
3102
|
/**
|
|
2856
3103
|
* Set multiple uniforms at once with type checking.
|
|
@@ -2875,13 +3122,41 @@ You can handle errors programmatically by providing an onError callback to suppr
|
|
|
2875
3122
|
getUniform(e) {
|
|
2876
3123
|
return this.engine.getUniform(e);
|
|
2877
3124
|
}
|
|
3125
|
+
/**
|
|
3126
|
+
* Set a texture for a sampler2D uniform.
|
|
3127
|
+
* @example
|
|
3128
|
+
* sandbox.setTexture("u_texture", imageElement);
|
|
3129
|
+
* sandbox.setTexture("u_texture", imageElement, { wrap: "repeat" });
|
|
3130
|
+
*/
|
|
3131
|
+
setTexture(e, t, n) {
|
|
3132
|
+
return this.engine.texture(e, t, n), this;
|
|
3133
|
+
}
|
|
3134
|
+
/**
|
|
3135
|
+
* Set multiple textures at once.
|
|
3136
|
+
* @example
|
|
3137
|
+
* sandbox.setTextures({
|
|
3138
|
+
* u_texture: imageElement,
|
|
3139
|
+
* u_detail: { source: detailImg, wrap: "repeat" },
|
|
3140
|
+
* });
|
|
3141
|
+
*/
|
|
3142
|
+
setTextures(e) {
|
|
3143
|
+
return this.engine.texturesFromSchema(e), this;
|
|
3144
|
+
}
|
|
3145
|
+
/**
|
|
3146
|
+
* Remove a texture and free its GPU resources.
|
|
3147
|
+
* @example
|
|
3148
|
+
* sandbox.removeTexture("u_texture");
|
|
3149
|
+
*/
|
|
3150
|
+
removeTexture(e) {
|
|
3151
|
+
return this.engine.removeTexture(e), this;
|
|
3152
|
+
}
|
|
2878
3153
|
/**
|
|
2879
3154
|
* Update shaders.
|
|
2880
3155
|
* @example
|
|
2881
3156
|
* sandbox.setShader(vertexSource, fragmentSource);
|
|
2882
3157
|
*/
|
|
2883
|
-
setShader(e,
|
|
2884
|
-
return this.options.vertex = new d(e), this.options.fragment = new d(
|
|
3158
|
+
setShader(e, t) {
|
|
3159
|
+
return this.options.vertex = new d(e), this.options.fragment = new d(t), this.usingCustomVertex = !0, this.engine.shader(this.options.vertex, this.options.fragment), this;
|
|
2885
3160
|
}
|
|
2886
3161
|
/**
|
|
2887
3162
|
* Update only fragment shader (uses default vertex).
|
|
@@ -2889,9 +3164,9 @@ You can handle errors programmatically by providing an onError callback to suppr
|
|
|
2889
3164
|
* sandbox.setFragment(fragmentSource);
|
|
2890
3165
|
*/
|
|
2891
3166
|
setFragment(e) {
|
|
2892
|
-
const
|
|
2893
|
-
return this.options.fragment =
|
|
2894
|
-
|
|
3167
|
+
const t = new d(e), n = t.version(), i = this.options.vertex.version();
|
|
3168
|
+
return this.options.fragment = t, n !== i && (this.usingCustomVertex || (this.options.vertex = new d(
|
|
3169
|
+
n === 2 ? C : A
|
|
2895
3170
|
))), this.engine.shader(this.options.vertex, this.options.fragment), this;
|
|
2896
3171
|
}
|
|
2897
3172
|
/**
|
|
@@ -2919,22 +3194,22 @@ You can handle errors programmatically by providing an onError callback to suppr
|
|
|
2919
3194
|
/**
|
|
2920
3195
|
* Add a runtime render hook.
|
|
2921
3196
|
*/
|
|
2922
|
-
hook(e,
|
|
2923
|
-
return
|
|
3197
|
+
hook(e, t = "before") {
|
|
3198
|
+
return t === "before" ? this.engine.onBeforeHooks.add(e) : this.engine.onAfterHooks.add(e);
|
|
2924
3199
|
}
|
|
2925
3200
|
/**
|
|
2926
3201
|
* Runtime configure the module behavior
|
|
2927
3202
|
* @example
|
|
2928
3203
|
* sandbox.module("my_module", { intensity: 0.5 });
|
|
2929
3204
|
*/
|
|
2930
|
-
module(e,
|
|
2931
|
-
const
|
|
2932
|
-
if (!
|
|
3205
|
+
module(e, t) {
|
|
3206
|
+
const n = y.resolveOptions(e);
|
|
3207
|
+
if (!n)
|
|
2933
3208
|
return console.warn(
|
|
2934
3209
|
`Sandbox: Counld not find options for '${e}' function. Make sure you used the correct imported name and the module is currently in use by the shader.`
|
|
2935
3210
|
), this;
|
|
2936
|
-
for (const [i, r] of Object.entries(
|
|
2937
|
-
const s =
|
|
3211
|
+
for (const [i, r] of Object.entries(t)) {
|
|
3212
|
+
const s = n[i];
|
|
2938
3213
|
if (!s) {
|
|
2939
3214
|
console.warn(
|
|
2940
3215
|
`Sandbox: Option '${i}' not found for function '${e}'. Make sure to check available options with Sandbox.availableModules() and provide the correct option name.`
|
|
@@ -2967,8 +3242,8 @@ You can handle errors programmatically by providing an onError callback to suppr
|
|
|
2967
3242
|
* Pause animation loop at specific time (in seconds).
|
|
2968
3243
|
*/
|
|
2969
3244
|
pauseAt(e) {
|
|
2970
|
-
const
|
|
2971
|
-
|
|
3245
|
+
const t = this.hook((n) => {
|
|
3246
|
+
n.time >= e && (t(), this.pause());
|
|
2972
3247
|
}, "after");
|
|
2973
3248
|
return this;
|
|
2974
3249
|
}
|
|
@@ -3018,6 +3293,57 @@ You can handle errors programmatically by providing an onError callback to suppr
|
|
|
3018
3293
|
get canvas() {
|
|
3019
3294
|
return this.canvasEl;
|
|
3020
3295
|
}
|
|
3296
|
+
/**
|
|
3297
|
+
* Export current frame as a data URL string.
|
|
3298
|
+
* Requires `preserveDrawingBuffer: true` if called while playing.
|
|
3299
|
+
* @example
|
|
3300
|
+
* const url = sandbox.renderAt(1.5).exportAsURL("image/png");
|
|
3301
|
+
*/
|
|
3302
|
+
exportAsURL(e = "image/png", t) {
|
|
3303
|
+
return this.canvas.toDataURL(e, t);
|
|
3304
|
+
}
|
|
3305
|
+
/**
|
|
3306
|
+
* Export current frame as a Blob.
|
|
3307
|
+
* Requires `preserveDrawingBuffer: true` if called while playing.
|
|
3308
|
+
* @example
|
|
3309
|
+
* const blob = await sandbox.renderAt(1.5).exportAsBlob("image/png");
|
|
3310
|
+
*/
|
|
3311
|
+
exportAsBlob(e = "image/png", t) {
|
|
3312
|
+
return new Promise((n, i) => {
|
|
3313
|
+
this.canvas.toBlob(
|
|
3314
|
+
(r) => {
|
|
3315
|
+
r ? n(r) : i(new Error("Failed to create blob from canvas."));
|
|
3316
|
+
},
|
|
3317
|
+
e,
|
|
3318
|
+
t
|
|
3319
|
+
);
|
|
3320
|
+
});
|
|
3321
|
+
}
|
|
3322
|
+
/**
|
|
3323
|
+
* Export current frame as an HTMLImageElement.
|
|
3324
|
+
* Requires `preserveDrawingBuffer: true` if called while playing.
|
|
3325
|
+
* @example
|
|
3326
|
+
* const img = sandbox.renderAt(1.5).exportAsImage("image/png");
|
|
3327
|
+
* img.onload = () => document.body.appendChild(img);
|
|
3328
|
+
*/
|
|
3329
|
+
exportAsImage(e = "image/png", t) {
|
|
3330
|
+
const n = new Image();
|
|
3331
|
+
return n.src = this.exportAsURL(e, t), n;
|
|
3332
|
+
}
|
|
3333
|
+
/**
|
|
3334
|
+
* Capture the canvas as a MediaStream for video calls or recording.
|
|
3335
|
+
* @example
|
|
3336
|
+
* // WebRTC video call
|
|
3337
|
+
* const stream = sandbox.stream(30);
|
|
3338
|
+
* peerConnection.addTrack(stream.getVideoTracks()[0], stream);
|
|
3339
|
+
*
|
|
3340
|
+
* @example
|
|
3341
|
+
* // Record to video file
|
|
3342
|
+
* const recorder = new MediaRecorder(sandbox.stream(30));
|
|
3343
|
+
*/
|
|
3344
|
+
stream(e) {
|
|
3345
|
+
return this.canvasEl.captureStream(e);
|
|
3346
|
+
}
|
|
3021
3347
|
/**
|
|
3022
3348
|
* Destroy sandbox and release all resources.
|
|
3023
3349
|
* @example
|
|
@@ -3030,26 +3356,28 @@ You can handle errors programmatically by providing an onError callback to suppr
|
|
|
3030
3356
|
}
|
|
3031
3357
|
}
|
|
3032
3358
|
export {
|
|
3033
|
-
|
|
3034
|
-
|
|
3359
|
+
I as Sandbox,
|
|
3360
|
+
Q as SandboxAttemptedToImportDefaultFunctionError,
|
|
3035
3361
|
K as SandboxAttemptedToImportMainFunctionError,
|
|
3036
|
-
|
|
3362
|
+
ve as SandboxContextCreationError,
|
|
3037
3363
|
h as SandboxError,
|
|
3038
|
-
|
|
3364
|
+
J as SandboxForbiddenModuleNameError,
|
|
3039
3365
|
_ as SandboxGLSLShaderCompilationError,
|
|
3040
3366
|
ne as SandboxMentionCouldNotBeReplacedError,
|
|
3041
|
-
|
|
3042
|
-
|
|
3367
|
+
te as SandboxMentionFunctionNotFoundError,
|
|
3368
|
+
ee as SandboxMentionUniformNotFoundError,
|
|
3043
3369
|
Y as SandboxModuleMethodNotFoundError,
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3370
|
+
X as SandboxModuleNotFoundError,
|
|
3371
|
+
re as SandboxOnHookCallbackError,
|
|
3372
|
+
ie as SandboxOnLoadCallbackError,
|
|
3373
|
+
Z as SandboxOverwriteModuleError,
|
|
3374
|
+
S as SandboxProgramError,
|
|
3375
|
+
j as SandboxShaderDuplicateImportNameError,
|
|
3050
3376
|
q as SandboxShaderImportSyntaxError,
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3377
|
+
U as SandboxShaderRequirementMismatchError,
|
|
3378
|
+
z as SandboxShaderVersionMismatchError,
|
|
3379
|
+
H as SandboxShaderWithoutFunctionError,
|
|
3380
|
+
ge as SandboxTextureCreationError,
|
|
3381
|
+
xe as SandboxTextureUnitLimitError,
|
|
3382
|
+
W as SandboxWebGLNotSupportedError
|
|
3055
3383
|
};
|