@bigmistqke/view.gl 0.2.0 → 0.4.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 +94 -27
- package/dev/dist/404.html +19 -0
- package/dev/dist/assets/bezier-DrA4cU_H.js +292 -0
- package/dev/dist/assets/game-of-life-BYlzWhEL.js +186 -0
- package/dev/dist/assets/glsl-composition-D_BaFFij.js +97 -0
- package/dev/dist/assets/grid-DfXHNLBm.js +181 -0
- package/dev/dist/assets/index-C2N3u8wj.css +12 -0
- package/dev/dist/assets/index-D-N0FDYs.js +110 -0
- package/dev/dist/assets/main-CSE2fki3.js +32 -0
- package/dev/dist/assets/overview-IeUhUflE.js +80 -0
- package/dev/dist/assets/pix-sim-DMJJA_WO.js +500 -0
- package/dev/dist/assets/ray-casting-DTQetDPd.js +411 -0
- package/dev/dist/assets/ray-casting-modules-Dkfw4tdc.js +765 -0
- package/dev/dist/assets/sdf-CS0uBonx.js +66 -0
- package/dev/dist/assets/symbol-BL_7GJ0M.js +67 -0
- package/dev/dist/assets/tag-C0Vskpp8.js +833 -0
- package/dev/dist/assets/tetris-D8mokodr.js +344 -0
- package/dev/dist/assets/utils-2dzuv_bW.js +62 -0
- package/dev/dist/index.html +51 -0
- package/dist/chunk-BZDGEIOT.mjs +278 -0
- package/dist/chunk-BZDGEIOT.mjs.map +1 -0
- package/dist/{chunk-EYXOSM7B.mjs → chunk-H56LJYS5.mjs} +63 -133
- package/dist/chunk-H56LJYS5.mjs.map +1 -0
- package/dist/gl.d.mts +2 -2
- package/dist/gl.mjs +1 -1
- package/dist/index.d.mts +13 -4
- package/dist/index.mjs +7 -2
- package/dist/tag.d.mts +6 -1
- package/dist/tag.mjs +19 -6
- package/dist/tag.mjs.map +1 -1
- package/dist/{types-CyGyGi18.d.mts → types-k1Xz1iO3.d.mts} +44 -2
- package/package.json +1 -1
- package/src/gl.ts +13 -2
- package/src/index.ts +63 -39
- package/src/tag.ts +23 -2
- package/src/types.ts +43 -1
- package/src/utils.ts +45 -10
- package/test/index.test.ts +145 -29
- package/test/mocks/webgl.ts +14 -0
- package/test/tag.test.ts +41 -0
- package/dist/chunk-CJTT7WPV.mjs +0 -75
- package/dist/chunk-CJTT7WPV.mjs.map +0 -1
- package/dist/chunk-EYXOSM7B.mjs.map +0 -1
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
// src/utils.ts
|
|
2
|
+
function assertedNotNullish(value, message) {
|
|
3
|
+
if (value === void 0 || value === null) throw new Error(message);
|
|
4
|
+
return value;
|
|
5
|
+
}
|
|
6
|
+
function once(teardown) {
|
|
7
|
+
let done = false;
|
|
8
|
+
return () => {
|
|
9
|
+
if (done) return;
|
|
10
|
+
done = true;
|
|
11
|
+
teardown();
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
var kindToUniformFnName = (kind) => {
|
|
15
|
+
switch (kind[0]) {
|
|
16
|
+
// mat
|
|
17
|
+
case "m":
|
|
18
|
+
return "Matrix" + kind.slice(3) + "fv";
|
|
19
|
+
// sampler/booleans/integer
|
|
20
|
+
case "s":
|
|
21
|
+
case "b":
|
|
22
|
+
case "i":
|
|
23
|
+
return (kind.match(/\d/)?.[0] ?? "1") + "i";
|
|
24
|
+
// unsigned integers
|
|
25
|
+
case "u":
|
|
26
|
+
return (kind[4] || "1") + "ui";
|
|
27
|
+
// vec
|
|
28
|
+
case "v":
|
|
29
|
+
return kind[3] + "f";
|
|
30
|
+
default:
|
|
31
|
+
switch (kind) {
|
|
32
|
+
case "float":
|
|
33
|
+
return "1f";
|
|
34
|
+
case "uint":
|
|
35
|
+
return "1ui";
|
|
36
|
+
default:
|
|
37
|
+
return "1i";
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
var kindToSize = (kind) => {
|
|
42
|
+
switch (kind[0]) {
|
|
43
|
+
case "m":
|
|
44
|
+
const [a, b] = kind.match(/\d+/g).map(Number);
|
|
45
|
+
return a * (b ?? a);
|
|
46
|
+
case "v":
|
|
47
|
+
case "i":
|
|
48
|
+
case "b":
|
|
49
|
+
case "u":
|
|
50
|
+
const match = kind.match(/\d/);
|
|
51
|
+
return match ? +match[0] : 1;
|
|
52
|
+
default:
|
|
53
|
+
return 1;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
var isMatKind = (kind) => kind.includes("mat");
|
|
57
|
+
var isSamplerKind = (kind) => kind.includes("sampler");
|
|
58
|
+
function createTexture(gl, {
|
|
59
|
+
target = "TEXTURE_2D",
|
|
60
|
+
internalFormat = "RGBA",
|
|
61
|
+
format = "RGBA",
|
|
62
|
+
type = "UNSIGNED_BYTE",
|
|
63
|
+
minFilter = "NEAREST",
|
|
64
|
+
magFilter = "NEAREST",
|
|
65
|
+
wrapS = "CLAMP_TO_EDGE",
|
|
66
|
+
wrapT = "CLAMP_TO_EDGE",
|
|
67
|
+
width,
|
|
68
|
+
height
|
|
69
|
+
}, data, { signal } = {}) {
|
|
70
|
+
const texture = assertedNotNullish(gl.createTexture(), "Failed to create texture");
|
|
71
|
+
function getTextureConstant(name) {
|
|
72
|
+
if (!(name in gl)) {
|
|
73
|
+
throw new Error(`Attempted to create webgl2-only texture (${name}) in webgl1`);
|
|
74
|
+
}
|
|
75
|
+
return gl[name];
|
|
76
|
+
}
|
|
77
|
+
gl.bindTexture(gl[target], texture);
|
|
78
|
+
gl.texImage2D(
|
|
79
|
+
gl[target],
|
|
80
|
+
0,
|
|
81
|
+
getTextureConstant(internalFormat),
|
|
82
|
+
width,
|
|
83
|
+
height,
|
|
84
|
+
0,
|
|
85
|
+
getTextureConstant(format),
|
|
86
|
+
getTextureConstant(type),
|
|
87
|
+
data ?? null
|
|
88
|
+
);
|
|
89
|
+
gl.texParameteri(gl[target], gl.TEXTURE_MIN_FILTER, gl[minFilter]);
|
|
90
|
+
gl.texParameteri(gl[target], gl.TEXTURE_MAG_FILTER, gl[magFilter]);
|
|
91
|
+
gl.texParameteri(gl[target], gl.TEXTURE_WRAP_S, gl[wrapS]);
|
|
92
|
+
gl.texParameteri(gl[target], gl.TEXTURE_WRAP_T, gl[wrapT]);
|
|
93
|
+
signal?.addEventListener(
|
|
94
|
+
"abort",
|
|
95
|
+
once(() => gl.deleteTexture(texture))
|
|
96
|
+
);
|
|
97
|
+
return texture;
|
|
98
|
+
}
|
|
99
|
+
var FRAMEBUFFER_ATTACHMENT_MAP = {
|
|
100
|
+
color: "COLOR_ATTACHMENT0",
|
|
101
|
+
depth: "DEPTH_ATTACHMENT",
|
|
102
|
+
stencil: "STENCIL_ATTACHMENT",
|
|
103
|
+
depthStencil: "DEPTH_STENCIL_ATTACHMENT"
|
|
104
|
+
};
|
|
105
|
+
var FramebufferError = class extends Error {
|
|
106
|
+
constructor(gl, status) {
|
|
107
|
+
let errorMessage = "Framebuffer not complete. Status: ";
|
|
108
|
+
switch (status) {
|
|
109
|
+
case gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
|
|
110
|
+
errorMessage += "FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
|
|
111
|
+
break;
|
|
112
|
+
case gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
|
|
113
|
+
errorMessage += "FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
|
|
114
|
+
break;
|
|
115
|
+
case gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
|
|
116
|
+
errorMessage += "FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
|
|
117
|
+
break;
|
|
118
|
+
case gl.FRAMEBUFFER_UNSUPPORTED:
|
|
119
|
+
errorMessage += "FRAMEBUFFER_UNSUPPORTED";
|
|
120
|
+
break;
|
|
121
|
+
default:
|
|
122
|
+
errorMessage += `Unknown (${status})`;
|
|
123
|
+
}
|
|
124
|
+
super(errorMessage);
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
function createFramebuffer(gl, { attachment, texture: providedTexture, ...definition }, { signal } = {}) {
|
|
128
|
+
const texture = providedTexture ?? createTexture(gl, definition);
|
|
129
|
+
const framebuffer = assertedNotNullish(gl.createFramebuffer(), "Failed to create framebuffer");
|
|
130
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
|
|
131
|
+
gl.framebufferTexture2D(
|
|
132
|
+
gl.FRAMEBUFFER,
|
|
133
|
+
// Determine attachment point based on attachment kind
|
|
134
|
+
gl[FRAMEBUFFER_ATTACHMENT_MAP[attachment]],
|
|
135
|
+
gl.TEXTURE_2D,
|
|
136
|
+
texture,
|
|
137
|
+
0
|
|
138
|
+
);
|
|
139
|
+
const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
|
|
140
|
+
if (status !== gl.FRAMEBUFFER_COMPLETE) {
|
|
141
|
+
throw new FramebufferError(gl, status);
|
|
142
|
+
}
|
|
143
|
+
const dispose = once(() => {
|
|
144
|
+
gl.deleteFramebuffer(framebuffer);
|
|
145
|
+
if (!providedTexture) {
|
|
146
|
+
gl.deleteTexture(texture);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
signal?.addEventListener("abort", dispose);
|
|
150
|
+
return {
|
|
151
|
+
texture,
|
|
152
|
+
framebuffer,
|
|
153
|
+
dispose
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
function createUpsertMap(constructor) {
|
|
157
|
+
const map = new (constructor ?? Map)();
|
|
158
|
+
return Object.assign(map, {
|
|
159
|
+
getOrInsert(key, value) {
|
|
160
|
+
let result = map.get(key);
|
|
161
|
+
if (result) {
|
|
162
|
+
return result;
|
|
163
|
+
}
|
|
164
|
+
result = value();
|
|
165
|
+
map.set(key, result);
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
function forEachObject(value, callback) {
|
|
171
|
+
let index = 0;
|
|
172
|
+
for (const key in value) {
|
|
173
|
+
callback(value[key], key, index);
|
|
174
|
+
index++;
|
|
175
|
+
}
|
|
176
|
+
for (const key of Object.getOwnPropertySymbols(value)) {
|
|
177
|
+
callback(value[key], key, index);
|
|
178
|
+
index++;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
function mapObject(value, callback) {
|
|
182
|
+
const result = {};
|
|
183
|
+
forEachObject(value, (value2, key, index) => {
|
|
184
|
+
result[key] = callback(value2, key, index);
|
|
185
|
+
});
|
|
186
|
+
return result;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// src/gl.ts
|
|
190
|
+
function isWebGL2RenderingContext(gl) {
|
|
191
|
+
return typeof WebGL2RenderingContext !== "undefined" && gl instanceof WebGL2RenderingContext;
|
|
192
|
+
}
|
|
193
|
+
function createShader(gl, type, source) {
|
|
194
|
+
const shader = gl.createShader(type);
|
|
195
|
+
if (!shader) throw new Error("Failed to create shader");
|
|
196
|
+
gl.shaderSource(shader, source);
|
|
197
|
+
gl.compileShader(shader);
|
|
198
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
199
|
+
const info = gl.getShaderInfoLog(shader);
|
|
200
|
+
gl.deleteShader(shader);
|
|
201
|
+
throw new Error(
|
|
202
|
+
`Failed to compile ${type === gl.VERTEX_SHADER ? "vertex" : "fragment"} shader: ${info}`
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
return shader;
|
|
206
|
+
}
|
|
207
|
+
function createProgram(gl, vertexSource, fragmentSource, { signal } = {}) {
|
|
208
|
+
const program = gl.createProgram();
|
|
209
|
+
if (!program) throw new Error("Failed to create WebGL program");
|
|
210
|
+
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexSource);
|
|
211
|
+
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentSource);
|
|
212
|
+
gl.attachShader(program, vertexShader);
|
|
213
|
+
gl.attachShader(program, fragmentShader);
|
|
214
|
+
gl.linkProgram(program);
|
|
215
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
216
|
+
const info = gl.getProgramInfoLog(program);
|
|
217
|
+
gl.deleteProgram(program);
|
|
218
|
+
gl.deleteShader(vertexShader);
|
|
219
|
+
gl.deleteShader(fragmentShader);
|
|
220
|
+
throw new Error(`Failed to link program: ${info}`);
|
|
221
|
+
}
|
|
222
|
+
gl.deleteShader(vertexShader);
|
|
223
|
+
gl.deleteShader(fragmentShader);
|
|
224
|
+
signal?.addEventListener(
|
|
225
|
+
"abort",
|
|
226
|
+
once(() => gl.deleteProgram(program))
|
|
227
|
+
);
|
|
228
|
+
return program;
|
|
229
|
+
}
|
|
230
|
+
var INSTANCED_ARRAYS_WRAPPER_MAP = /* @__PURE__ */ new WeakMap();
|
|
231
|
+
function getInstancedArrays(gl) {
|
|
232
|
+
if (isWebGL2RenderingContext(gl)) return gl;
|
|
233
|
+
const cached = INSTANCED_ARRAYS_WRAPPER_MAP.get(gl);
|
|
234
|
+
if (cached) return cached;
|
|
235
|
+
const ext = gl.getExtension("ANGLE_instanced_arrays");
|
|
236
|
+
if (!ext) return void 0;
|
|
237
|
+
const wrapper = {
|
|
238
|
+
drawArraysInstanced: ext.drawArraysInstancedANGLE.bind(ext),
|
|
239
|
+
drawElementsInstanced: ext.drawElementsInstancedANGLE.bind(ext),
|
|
240
|
+
vertexAttribDivisor: ext.vertexAttribDivisorANGLE.bind(ext)
|
|
241
|
+
};
|
|
242
|
+
INSTANCED_ARRAYS_WRAPPER_MAP.set(gl, wrapper);
|
|
243
|
+
return wrapper;
|
|
244
|
+
}
|
|
245
|
+
var VERTEX_ARRAY_OBJECT_WRAPPER_MAP = /* @__PURE__ */ new WeakMap();
|
|
246
|
+
function getVertexArrayObject(gl) {
|
|
247
|
+
if (isWebGL2RenderingContext(gl)) return gl;
|
|
248
|
+
const cached = VERTEX_ARRAY_OBJECT_WRAPPER_MAP.get(gl);
|
|
249
|
+
if (cached) return cached;
|
|
250
|
+
const ext = gl.getExtension("OES_vertex_array_object");
|
|
251
|
+
if (!ext) return null;
|
|
252
|
+
const wrapper = {
|
|
253
|
+
bindVertexArray: ext.bindVertexArrayOES.bind(ext),
|
|
254
|
+
createVertexArray: ext.createVertexArrayOES.bind(ext),
|
|
255
|
+
deleteVertexArray: ext.deleteVertexArrayOES.bind(ext)
|
|
256
|
+
};
|
|
257
|
+
VERTEX_ARRAY_OBJECT_WRAPPER_MAP.set(gl, wrapper);
|
|
258
|
+
return wrapper;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export {
|
|
262
|
+
assertedNotNullish,
|
|
263
|
+
once,
|
|
264
|
+
kindToUniformFnName,
|
|
265
|
+
kindToSize,
|
|
266
|
+
isMatKind,
|
|
267
|
+
isSamplerKind,
|
|
268
|
+
createTexture,
|
|
269
|
+
createFramebuffer,
|
|
270
|
+
createUpsertMap,
|
|
271
|
+
forEachObject,
|
|
272
|
+
mapObject,
|
|
273
|
+
createShader,
|
|
274
|
+
createProgram,
|
|
275
|
+
getInstancedArrays,
|
|
276
|
+
getVertexArrayObject
|
|
277
|
+
};
|
|
278
|
+
//# sourceMappingURL=chunk-BZDGEIOT.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts","../src/gl.ts"],"sourcesContent":["import type {\n AttributeKind,\n FramebufferDefinition,\n GL,\n KIND_TO_SIZE_MAP,\n KIND_TO_UNIFORM_FN_NAME_MAP,\n TextureDefinition,\n UniformKind,\n ViewOptions,\n} from './types'\n\nexport function assertedNotNullish<T>(value: T, message?: string): NonNullable<T> {\n if (value === undefined || value === null) throw new Error(message)\n return value\n}\n\n/**\n * Wraps a teardown so it runs once.\n *\n * Two reasons, and both bite. A disposer is per `bind()`, and undoing twice\n * would put back state a later `bind()` is relying on. And a `dispose()` that\n * deletes twice invalidates a handle someone else may still be holding — the\n * object survives while it is bound, so the fault surfaces later, somewhere\n * else. Idempotent is the only safe shape for either.\n */\nexport function once(teardown: () => void): () => void {\n let done = false\n return () => {\n if (done) return\n done = true\n teardown()\n }\n}\n\n/**********************************************************************************/\n/* */\n/* Kind To Uniform Name */\n/* */\n/**********************************************************************************/\n\nexport const kindToUniformFnName = <T extends UniformKind>(\n kind: T,\n): KIND_TO_UNIFORM_FN_NAME_MAP[T] => {\n switch (kind[0]) {\n // mat\n case 'm':\n return ('Matrix' + kind.slice(3) + 'fv') as KIND_TO_UNIFORM_FN_NAME_MAP[T]\n // sampler/booleans/integer\n case 's':\n case 'b':\n case 'i':\n return ((kind.match(/\\d/)?.[0] ?? '1') + 'i') as KIND_TO_UNIFORM_FN_NAME_MAP[T]\n // unsigned integers\n case 'u':\n return ((kind[4] || '1') + 'ui') as KIND_TO_UNIFORM_FN_NAME_MAP[T]\n // vec\n case 'v':\n return (kind[3] + 'f') as KIND_TO_UNIFORM_FN_NAME_MAP[T]\n default:\n switch (kind) {\n case 'float':\n return '1f' as KIND_TO_UNIFORM_FN_NAME_MAP[T]\n case 'uint':\n return '1ui' as KIND_TO_UNIFORM_FN_NAME_MAP[T]\n default:\n return '1i' as KIND_TO_UNIFORM_FN_NAME_MAP[T]\n }\n }\n}\n\n/**********************************************************************************/\n/* */\n/* Kind To Size */\n/* */\n/**********************************************************************************/\n\nexport const kindToSize = <T extends UniformKind>(kind: T): KIND_TO_SIZE_MAP[T] => {\n switch (kind[0]) {\n case 'm':\n const [a, b] = kind.match(/\\d+/g)!.map(Number) as [number, number?]\n return (a * (b ?? a)) as KIND_TO_SIZE_MAP[T]\n case 'v':\n case 'i':\n case 'b':\n case 'u':\n const match = kind.match(/\\d/) as [string] | undefined\n return (match ? +match[0] : 1) as KIND_TO_SIZE_MAP[T]\n default:\n return 1 as KIND_TO_SIZE_MAP[T]\n }\n}\n\n/**********************************************************************************/\n/* */\n/* Guards */\n/* */\n/**********************************************************************************/\n\nexport const isMatKind = <\n T extends UniformKind | AttributeKind,\n TPrefix extends string,\n TPostfix extends string,\n>(\n kind: T,\n): kind is T & `${TPrefix}mat${TPostfix}` => kind.includes('mat')\n\nexport const isSamplerKind = <TPrefix extends string, TPostfix extends string>(\n kind: UniformKind,\n): kind is UniformKind & `${TPrefix}sampler${TPostfix}` => kind.includes('sampler')\n\nexport const isVecKind = <TPrefix extends string, TPostfix extends string>(\n kind: UniformKind,\n): kind is UniformKind & `${TPrefix}vec${TPostfix}` => kind.includes('vec')\n\n/**********************************************************************************/\n/* */\n/* Create Texture */\n/* */\n/**********************************************************************************/\n\nexport function createTexture(\n gl: GL,\n {\n target = 'TEXTURE_2D',\n internalFormat = 'RGBA',\n format = 'RGBA',\n type = 'UNSIGNED_BYTE',\n minFilter = 'NEAREST',\n magFilter = 'NEAREST',\n wrapS = 'CLAMP_TO_EDGE',\n wrapT = 'CLAMP_TO_EDGE',\n width,\n height,\n }: TextureDefinition,\n data?: ArrayBufferView | null,\n { signal }: ViewOptions = {},\n): WebGLTexture {\n const texture = assertedNotNullish(gl.createTexture(), 'Failed to create texture')\n\n function getTextureConstant(name: string) {\n if (!(name in gl)) {\n throw new Error(`Attempted to create webgl2-only texture (${name}) in webgl1`)\n }\n return gl[name as keyof typeof gl] as any\n }\n\n gl.bindTexture(gl[target], texture)\n gl.texImage2D(\n gl[target],\n 0,\n getTextureConstant(internalFormat),\n width,\n height,\n 0,\n getTextureConstant(format),\n getTextureConstant(type),\n data ?? null,\n )\n\n // Set texture parameters\n gl.texParameteri(gl[target], gl.TEXTURE_MIN_FILTER, gl[minFilter])\n gl.texParameteri(gl[target], gl.TEXTURE_MAG_FILTER, gl[magFilter])\n gl.texParameteri(gl[target], gl.TEXTURE_WRAP_S, gl[wrapS])\n gl.texParameteri(gl[target], gl.TEXTURE_WRAP_T, gl[wrapT])\n\n signal?.addEventListener(\n 'abort',\n once(() => gl.deleteTexture(texture)),\n )\n\n return texture\n}\n\n/**********************************************************************************/\n/* */\n/* Create Framebuffer */\n/* */\n/**********************************************************************************/\n\nconst FRAMEBUFFER_ATTACHMENT_MAP = {\n color: 'COLOR_ATTACHMENT0',\n depth: 'DEPTH_ATTACHMENT',\n stencil: 'STENCIL_ATTACHMENT',\n depthStencil: 'DEPTH_STENCIL_ATTACHMENT',\n} as const\n\nclass FramebufferError extends Error {\n constructor(gl: GL, status: number) {\n let errorMessage = 'Framebuffer not complete. Status: '\n switch (status) {\n case gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:\n errorMessage += 'FRAMEBUFFER_INCOMPLETE_ATTACHMENT'\n break\n case gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:\n errorMessage += 'FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT'\n break\n case gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:\n errorMessage += 'FRAMEBUFFER_INCOMPLETE_DIMENSIONS'\n break\n case gl.FRAMEBUFFER_UNSUPPORTED:\n errorMessage += 'FRAMEBUFFER_UNSUPPORTED'\n break\n default:\n errorMessage += `Unknown (${status})`\n }\n super(errorMessage)\n }\n}\n\nexport function createFramebuffer(\n gl: GL,\n { attachment, texture: providedTexture, ...definition }: FramebufferDefinition,\n { signal }: ViewOptions = {},\n) {\n // Create texture for the framebuffer, unless one was handed in. Which one it\n // is decides who deletes it below — the same rule the attribute buffers follow.\n const texture = providedTexture ?? createTexture(gl, definition)\n\n // Create framebuffer\n const framebuffer = assertedNotNullish(gl.createFramebuffer(), 'Failed to create framebuffer')\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer)\n\n gl.framebufferTexture2D(\n gl.FRAMEBUFFER,\n // Determine attachment point based on attachment kind\n gl[FRAMEBUFFER_ATTACHMENT_MAP[attachment]],\n gl.TEXTURE_2D,\n texture,\n 0,\n )\n\n // Check framebuffer completeness\n const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER)\n if (status !== gl.FRAMEBUFFER_COMPLETE) {\n throw new FramebufferError(gl, status)\n }\n\n const dispose = once(() => {\n gl.deleteFramebuffer(framebuffer)\n // A texture handed in belongs to whoever made it — it commonly outlives the\n // framebuffer, ping-ponged between two of them.\n if (!providedTexture) {\n gl.deleteTexture(texture)\n }\n })\n\n signal?.addEventListener('abort', dispose)\n\n return {\n texture,\n framebuffer,\n dispose,\n }\n}\n\n/**********************************************************************************/\n/* */\n/* Create Upsert */\n/* */\n/**********************************************************************************/\n\ntype UpsertMapKind<T, U> = Map<T, U> | (T extends WeakKey ? WeakMap<T, U> : never)\n\nexport function createUpsertMap<T extends UpsertMapKind<any, any> = Map<any, any>>(\n constructor?: new () => T,\n) {\n const map = new (constructor ?? Map)() as T\n return Object.assign(map, {\n getOrInsert(\n key: T extends UpsertMapKind<infer U, any> ? U : never,\n value: T extends UpsertMapKind<any, infer U> ? () => U : never,\n ) {\n let result = map.get(key)\n if (result) {\n return result\n }\n result = value()\n map.set(key, result)\n return result\n },\n })\n}\n\nexport function forEachObject<T extends Record<string, any>>(\n value: T,\n callback: (value: T[keyof T], key: keyof T, index: number) => void,\n) {\n let index = 0\n for (const key in value) {\n callback(value[key], key, index)\n index++\n }\n for (const key of Object.getOwnPropertySymbols(value)) {\n callback(value[key as keyof T], key as keyof T, index)\n index++\n }\n}\n\nexport function mapObject<T extends Record<string, any>, TReturn>(\n value: T,\n callback: (value: T[keyof T], key: keyof T, index: number) => TReturn,\n): { [TKey in keyof T]: TReturn } {\n const result = {} as { [TKey in keyof T]: TReturn }\n\n forEachObject(value, (value, key, index) => {\n result[key] = callback(value, key, index)\n })\n\n return result\n}\n","import { RemoveSuffix } from './type-utils'\nimport type { GL, ViewOptions } from './types'\nimport { once } from './utils'\n\nfunction isWebGL2RenderingContext(\n gl: WebGLRenderingContext | WebGL2RenderingContext,\n): gl is WebGL2RenderingContext {\n return typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext\n}\n\n/**********************************************************************************/\n/* */\n/* Create Shader */\n/* */\n/**********************************************************************************/\n\nexport function createShader(gl: GL, type: number, source: string): WebGLShader {\n const shader = gl.createShader(type)\n if (!shader) throw new Error('Failed to create shader')\n\n gl.shaderSource(shader, source)\n gl.compileShader(shader)\n\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const info = gl.getShaderInfoLog(shader)\n gl.deleteShader(shader)\n throw new Error(\n `Failed to compile ${type === gl.VERTEX_SHADER ? 'vertex' : 'fragment'} shader: ${info}`,\n )\n }\n\n return shader\n}\n\n/**********************************************************************************/\n/* */\n/* Create Program */\n/* */\n/**********************************************************************************/\n\nexport function createProgram(\n gl: GL,\n vertexSource: string,\n fragmentSource: string,\n { signal }: ViewOptions = {},\n): WebGLProgram {\n const program = gl.createProgram()\n if (!program) throw new Error('Failed to create WebGL program')\n\n const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexSource)\n const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentSource)\n\n gl.attachShader(program, vertexShader)\n gl.attachShader(program, fragmentShader)\n gl.linkProgram(program)\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n const info = gl.getProgramInfoLog(program)\n gl.deleteProgram(program)\n gl.deleteShader(vertexShader)\n gl.deleteShader(fragmentShader)\n throw new Error(`Failed to link program: ${info}`)\n }\n\n // Clean up shaders after linking\n gl.deleteShader(vertexShader)\n gl.deleteShader(fragmentShader)\n\n signal?.addEventListener(\n 'abort',\n once(() => gl.deleteProgram(program)),\n )\n\n return program\n}\n\n/**********************************************************************************/\n/* */\n/* Get Instanced Arrays */\n/* */\n/**********************************************************************************/\n\nconst INSTANCED_ARRAYS_WRAPPER_MAP = new WeakMap<\n GL,\n RemoveSuffix<\n Pick<\n ANGLE_instanced_arrays,\n 'drawArraysInstancedANGLE' | 'drawElementsInstancedANGLE' | 'vertexAttribDivisorANGLE'\n >,\n 'ANGLE'\n > | null\n>()\nexport function getInstancedArrays(gl: GL) {\n if (isWebGL2RenderingContext(gl)) return gl\n\n const cached = INSTANCED_ARRAYS_WRAPPER_MAP.get(gl)\n if (cached) return cached\n\n const ext = gl.getExtension('ANGLE_instanced_arrays')\n if (!ext) return undefined\n\n const wrapper = {\n drawArraysInstanced: ext.drawArraysInstancedANGLE.bind(ext),\n drawElementsInstanced: ext.drawElementsInstancedANGLE.bind(ext),\n vertexAttribDivisor: ext.vertexAttribDivisorANGLE.bind(ext),\n }\n INSTANCED_ARRAYS_WRAPPER_MAP.set(gl, wrapper)\n\n return wrapper\n}\n\n/**********************************************************************************/\n/* */\n/* Get Vertex Array Object */\n/* */\n/**********************************************************************************/\n\nconst VERTEX_ARRAY_OBJECT_WRAPPER_MAP = new WeakMap<\n GL,\n RemoveSuffix<\n Pick<\n OES_vertex_array_object,\n 'bindVertexArrayOES' | 'createVertexArrayOES' | 'deleteVertexArrayOES'\n >,\n 'OES'\n > | null\n>()\nexport function getVertexArrayObject(gl: GL) {\n if (isWebGL2RenderingContext(gl)) return gl\n\n const cached = VERTEX_ARRAY_OBJECT_WRAPPER_MAP.get(gl)\n if (cached) return cached\n\n const ext = gl.getExtension('OES_vertex_array_object')\n if (!ext) return null\n\n const wrapper = {\n bindVertexArray: ext.bindVertexArrayOES.bind(ext),\n createVertexArray: ext.createVertexArrayOES.bind(ext),\n deleteVertexArray: ext.deleteVertexArrayOES.bind(ext),\n }\n VERTEX_ARRAY_OBJECT_WRAPPER_MAP.set(gl, wrapper)\n\n return wrapper\n}\n"],"mappings":"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","names":["value"]}
|
|
@@ -1,89 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
|
+
assertedNotNullish,
|
|
3
|
+
createUpsertMap,
|
|
4
|
+
forEachObject,
|
|
2
5
|
getInstancedArrays,
|
|
3
|
-
getVertexArrayObject
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
var kindToUniformFnName = (kind) => {
|
|
12
|
-
switch (kind[0]) {
|
|
13
|
-
// mat
|
|
14
|
-
case "m":
|
|
15
|
-
return "Matrix" + kind.slice(3) + "fv";
|
|
16
|
-
// sampler/booleans/integer
|
|
17
|
-
case "s":
|
|
18
|
-
case "b":
|
|
19
|
-
case "i":
|
|
20
|
-
return (kind.match(/\d/)?.[0] ?? "1") + "i";
|
|
21
|
-
// unsigned integers
|
|
22
|
-
case "u":
|
|
23
|
-
return (kind[4] || "1") + "ui";
|
|
24
|
-
// vec
|
|
25
|
-
case "v":
|
|
26
|
-
return kind[3] + "f";
|
|
27
|
-
default:
|
|
28
|
-
switch (kind) {
|
|
29
|
-
case "float":
|
|
30
|
-
return "1f";
|
|
31
|
-
case "uint":
|
|
32
|
-
return "1ui";
|
|
33
|
-
default:
|
|
34
|
-
return "1i";
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
var kindToSize = (kind) => {
|
|
39
|
-
switch (kind[0]) {
|
|
40
|
-
case "m":
|
|
41
|
-
const [a, b] = kind.match(/\d+/g).map(Number);
|
|
42
|
-
return a * (b ?? a);
|
|
43
|
-
case "v":
|
|
44
|
-
case "i":
|
|
45
|
-
case "b":
|
|
46
|
-
case "u":
|
|
47
|
-
const match = kind.match(/\d/);
|
|
48
|
-
return match ? +match[0] : 1;
|
|
49
|
-
default:
|
|
50
|
-
return 1;
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
var isMatKind = (kind) => kind.includes("mat");
|
|
54
|
-
var isSamplerKind = (kind) => kind.includes("sampler");
|
|
55
|
-
function createUpsertMap(constructor) {
|
|
56
|
-
const map = new (constructor ?? Map)();
|
|
57
|
-
return Object.assign(map, {
|
|
58
|
-
getOrInsert(key, value) {
|
|
59
|
-
let result = map.get(key);
|
|
60
|
-
if (result) {
|
|
61
|
-
return result;
|
|
62
|
-
}
|
|
63
|
-
result = value();
|
|
64
|
-
map.set(key, result);
|
|
65
|
-
return result;
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
function forEachObject(value, callback) {
|
|
70
|
-
let index2 = 0;
|
|
71
|
-
for (const key in value) {
|
|
72
|
-
callback(value[key], key, index2);
|
|
73
|
-
index2++;
|
|
74
|
-
}
|
|
75
|
-
for (const key of Object.getOwnPropertySymbols(value)) {
|
|
76
|
-
callback(value[key], key, index2);
|
|
77
|
-
index2++;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
function mapObject(value, callback) {
|
|
81
|
-
const result = {};
|
|
82
|
-
forEachObject(value, (value2, key, index2) => {
|
|
83
|
-
result[key] = callback(value2, key, index2);
|
|
84
|
-
});
|
|
85
|
-
return result;
|
|
86
|
-
}
|
|
6
|
+
getVertexArrayObject,
|
|
7
|
+
isMatKind,
|
|
8
|
+
isSamplerKind,
|
|
9
|
+
kindToSize,
|
|
10
|
+
kindToUniformFnName,
|
|
11
|
+
mapObject,
|
|
12
|
+
once
|
|
13
|
+
} from "./chunk-BZDGEIOT.mjs";
|
|
87
14
|
|
|
88
15
|
// src/index.ts
|
|
89
16
|
var index = 0;
|
|
@@ -107,15 +34,36 @@ function toID(key) {
|
|
|
107
34
|
}
|
|
108
35
|
return key.toString();
|
|
109
36
|
}
|
|
110
|
-
function view(gl, program, schema,
|
|
37
|
+
function view(gl, program, schema, { signal } = {}) {
|
|
38
|
+
const attributes = !schema.attributes ? void 0 : attributeView(gl, program, schema.attributes);
|
|
39
|
+
const interleavedAttributes = !schema.interleavedAttributes ? void 0 : interleavedAttributeView(gl, program, schema.interleavedAttributes);
|
|
40
|
+
const buffers = !schema.buffers ? void 0 : bufferView(gl, schema.buffers);
|
|
41
|
+
const vertexArrays = /* @__PURE__ */ new Set();
|
|
42
|
+
const dispose = once(() => {
|
|
43
|
+
if (attributes) forEachObject(attributes, (value) => value.dispose());
|
|
44
|
+
if (interleavedAttributes) forEachObject(interleavedAttributes, (value) => value.dispose());
|
|
45
|
+
if (buffers) forEachObject(buffers, (value) => value.dispose());
|
|
46
|
+
vertexArrays.forEach((vertexArray) => vertexArray.dispose());
|
|
47
|
+
vertexArrays.clear();
|
|
48
|
+
});
|
|
49
|
+
signal?.addEventListener("abort", dispose);
|
|
111
50
|
return {
|
|
112
51
|
uniforms: !schema.uniforms ? void 0 : uniformView(gl, program, schema.uniforms),
|
|
113
|
-
attributes
|
|
114
|
-
interleavedAttributes
|
|
115
|
-
buffers
|
|
52
|
+
attributes,
|
|
53
|
+
interleavedAttributes,
|
|
54
|
+
buffers,
|
|
116
55
|
vao(participants) {
|
|
117
|
-
|
|
118
|
-
|
|
56
|
+
const vertexArray = vaoView(gl, participants);
|
|
57
|
+
vertexArrays.add(vertexArray);
|
|
58
|
+
return {
|
|
59
|
+
...vertexArray,
|
|
60
|
+
dispose: once(() => {
|
|
61
|
+
vertexArrays.delete(vertexArray);
|
|
62
|
+
vertexArray.dispose();
|
|
63
|
+
})
|
|
64
|
+
};
|
|
65
|
+
},
|
|
66
|
+
dispose
|
|
119
67
|
};
|
|
120
68
|
}
|
|
121
69
|
function bindDefaultVertexArray(gl) {
|
|
@@ -160,9 +108,7 @@ function vaoView(gl, participants, { signal } = {}) {
|
|
|
160
108
|
unbind() {
|
|
161
109
|
feature.bindVertexArray(null);
|
|
162
110
|
},
|
|
163
|
-
dispose()
|
|
164
|
-
feature.deleteVertexArray(vertexArray);
|
|
165
|
-
}
|
|
111
|
+
dispose: once(() => feature.deleteVertexArray(vertexArray))
|
|
166
112
|
};
|
|
167
113
|
})();
|
|
168
114
|
signal?.addEventListener("abort", () => methods.dispose());
|
|
@@ -170,9 +116,9 @@ function vaoView(gl, participants, { signal } = {}) {
|
|
|
170
116
|
}
|
|
171
117
|
function uniformView(gl, program, schema) {
|
|
172
118
|
return mapObject(schema, ({ kind, size }, key) => {
|
|
173
|
-
const
|
|
119
|
+
const name = toID(key);
|
|
174
120
|
if (isSamplerKind(kind)) {
|
|
175
|
-
const location2 = gl.getUniformLocation(program,
|
|
121
|
+
const location2 = gl.getUniformLocation(program, name);
|
|
176
122
|
return {
|
|
177
123
|
set(arg) {
|
|
178
124
|
gl.uniform1i(location2, arg);
|
|
@@ -182,12 +128,12 @@ function uniformView(gl, program, schema) {
|
|
|
182
128
|
if (size) {
|
|
183
129
|
const bulkFnName = `uniform${kindToUniformFnName(kind)}v`;
|
|
184
130
|
const bulkFn = gl[bulkFnName].bind(gl);
|
|
185
|
-
const bulkLocation = gl.getUniformLocation(program,
|
|
131
|
+
const bulkLocation = gl.getUniformLocation(program, name);
|
|
186
132
|
const elementFnName = `uniform${kindToUniformFnName(kind)}`;
|
|
187
133
|
const elementFn = gl[elementFnName].bind(gl);
|
|
188
134
|
const elements = [];
|
|
189
135
|
for (let i = 0; i < size; i++) {
|
|
190
|
-
const location2 = gl.getUniformLocation(program, `${
|
|
136
|
+
const location2 = gl.getUniformLocation(program, `${name}[${i}]`);
|
|
191
137
|
elements[i] = {
|
|
192
138
|
set(...args) {
|
|
193
139
|
elementFn(location2, ...args);
|
|
@@ -200,7 +146,7 @@ function uniformView(gl, program, schema) {
|
|
|
200
146
|
}
|
|
201
147
|
});
|
|
202
148
|
}
|
|
203
|
-
const location = gl.getUniformLocation(program,
|
|
149
|
+
const location = gl.getUniformLocation(program, name);
|
|
204
150
|
const fnName = `uniform${kindToUniformFnName(kind)}`;
|
|
205
151
|
const fn = gl[fnName].bind(gl);
|
|
206
152
|
if (isMatKind(kind)) {
|
|
@@ -260,28 +206,15 @@ var VERTEX_ARRAY_BINDING = 34229;
|
|
|
260
206
|
function readDivisor(gl, location) {
|
|
261
207
|
return getInstancedArrays(gl) ? gl.getVertexAttrib(location, VERTEX_ATTRIB_ARRAY_DIVISOR) : 0;
|
|
262
208
|
}
|
|
263
|
-
function once(restore) {
|
|
264
|
-
let done = false;
|
|
265
|
-
return () => {
|
|
266
|
-
if (done) return;
|
|
267
|
-
done = true;
|
|
268
|
-
restore();
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
209
|
function attributeView(gl, program, schema, { signal } = {}) {
|
|
272
210
|
const attributes = mapObject(
|
|
273
211
|
schema,
|
|
274
|
-
({
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
instanced,
|
|
279
|
-
buffer = assertedNotNullish(gl.createBuffer())
|
|
280
|
-
}, key) => {
|
|
281
|
-
const name2 = toID(key);
|
|
282
|
-
const location = gl.getAttribLocation(program, name2);
|
|
212
|
+
({ kind, format, normalized = false, instanced, buffer: providedBuffer }, key) => {
|
|
213
|
+
const name = toID(key);
|
|
214
|
+
const buffer = providedBuffer ?? assertedNotNullish(gl.createBuffer());
|
|
215
|
+
const location = gl.getAttribLocation(program, name);
|
|
283
216
|
if (location < 0) {
|
|
284
|
-
throw new Error(`Attribute '${
|
|
217
|
+
throw new Error(`Attribute '${name}' not found`);
|
|
285
218
|
}
|
|
286
219
|
const size = kindToSize(kind);
|
|
287
220
|
const resolvedFormat = format ?? defaultFormat(kind);
|
|
@@ -306,9 +239,11 @@ function attributeView(gl, program, schema, { signal } = {}) {
|
|
|
306
239
|
restoreVertexArray();
|
|
307
240
|
});
|
|
308
241
|
},
|
|
309
|
-
dispose() {
|
|
310
|
-
|
|
311
|
-
|
|
242
|
+
dispose: once(() => {
|
|
243
|
+
if (!providedBuffer) {
|
|
244
|
+
gl.deleteBuffer(buffer);
|
|
245
|
+
}
|
|
246
|
+
}),
|
|
312
247
|
set(data, usage = "STATIC_DRAW") {
|
|
313
248
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
314
249
|
gl.bufferData(gl.ARRAY_BUFFER, data, gl[usage]);
|
|
@@ -325,16 +260,16 @@ function attributeView(gl, program, schema, { signal } = {}) {
|
|
|
325
260
|
function constantSource(gl, layout, locations) {
|
|
326
261
|
const setters = layout.map((entry, index2) => {
|
|
327
262
|
const size = kindToSize(entry.kind);
|
|
328
|
-
const
|
|
263
|
+
const name = toID(entry.key);
|
|
329
264
|
if (isMatKind(entry.kind) || size > 4) {
|
|
330
265
|
throw new Error(
|
|
331
|
-
`'${
|
|
266
|
+
`'${name}' is a ${entry.kind}, which cannot be a constant attribute: vertexAttrib* takes at most 4 floats and has no matrix form. Use the buffer source for it.`
|
|
332
267
|
);
|
|
333
268
|
}
|
|
334
269
|
let values = [];
|
|
335
270
|
const fn = gl[`vertexAttrib${size}f`].bind(gl);
|
|
336
271
|
return {
|
|
337
|
-
name
|
|
272
|
+
name,
|
|
338
273
|
location: locations[index2],
|
|
339
274
|
write: () => {
|
|
340
275
|
if (values.length) {
|
|
@@ -377,10 +312,10 @@ function interleavedAttributeView(gl, program, schema, { signal } = {}) {
|
|
|
377
312
|
let index2 = 0;
|
|
378
313
|
const locations = [];
|
|
379
314
|
const handles = layout.map((layout2) => {
|
|
380
|
-
const
|
|
381
|
-
const location = gl.getAttribLocation(program,
|
|
315
|
+
const name = toID(layout2.key);
|
|
316
|
+
const location = gl.getAttribLocation(program, name);
|
|
382
317
|
if (location < 0) {
|
|
383
|
-
throw new Error(`Attribute '${
|
|
318
|
+
throw new Error(`Attribute '${name}' not found`);
|
|
384
319
|
}
|
|
385
320
|
locations.push(location);
|
|
386
321
|
const size = kindToSize(layout2.kind);
|
|
@@ -448,9 +383,7 @@ function interleavedAttributeView(gl, program, schema, { signal } = {}) {
|
|
|
448
383
|
get constant() {
|
|
449
384
|
return constant ??= constantSource(gl, layout, locations);
|
|
450
385
|
},
|
|
451
|
-
dispose()
|
|
452
|
-
gl.deleteBuffer(buffer);
|
|
453
|
-
}
|
|
386
|
+
dispose: once(() => gl.deleteBuffer(buffer))
|
|
454
387
|
};
|
|
455
388
|
});
|
|
456
389
|
signal?.addEventListener("abort", function dispose() {
|
|
@@ -478,9 +411,7 @@ function bufferView(gl, schema, { signal } = {}) {
|
|
|
478
411
|
restoreVertexArray();
|
|
479
412
|
});
|
|
480
413
|
},
|
|
481
|
-
dispose()
|
|
482
|
-
gl.deleteBuffer(buffer);
|
|
483
|
-
},
|
|
414
|
+
dispose: once(() => gl.deleteBuffer(buffer)),
|
|
484
415
|
set(data) {
|
|
485
416
|
gl.bindBuffer(gl[target], buffer);
|
|
486
417
|
gl.bufferData(gl[target], data, gl[usage]);
|
|
@@ -494,7 +425,6 @@ function bufferView(gl, schema, { signal } = {}) {
|
|
|
494
425
|
}
|
|
495
426
|
|
|
496
427
|
export {
|
|
497
|
-
createUpsertMap,
|
|
498
428
|
toID,
|
|
499
429
|
view,
|
|
500
430
|
vaoView,
|
|
@@ -503,4 +433,4 @@ export {
|
|
|
503
433
|
interleavedAttributeView,
|
|
504
434
|
bufferView
|
|
505
435
|
};
|
|
506
|
-
//# sourceMappingURL=chunk-
|
|
436
|
+
//# sourceMappingURL=chunk-H56LJYS5.mjs.map
|