@bigmistqke/view.gl 0.8.0 → 0.9.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 +48 -6
- package/dist/{chunk-TQWPUDQI.mjs → chunk-IAM2SWJK.mjs} +10 -78
- package/dist/chunk-IAM2SWJK.mjs.map +1 -0
- package/dist/{chunk-7Z5UULAB.mjs → chunk-NRCBGOZB.mjs} +43 -29
- package/dist/chunk-NRCBGOZB.mjs.map +1 -0
- package/dist/chunk-UVDTF5P3.mjs +51 -0
- package/dist/chunk-UVDTF5P3.mjs.map +1 -0
- package/dist/gl.d.mts +2 -4
- package/dist/gl.mjs +4 -7
- package/dist/index.d.mts +9 -3
- package/dist/index.mjs +4 -2
- package/dist/tag.d.mts +2 -2
- package/dist/tag.mjs +7 -8
- package/dist/tag.mjs.map +1 -1
- package/dist/{types-DZbMcty2.d.mts → types-Z2s1zsZz.d.mts} +27 -9
- package/package.json +15 -17
- package/src/errors.ts +9 -0
- package/src/gl.ts +0 -77
- package/src/index.ts +60 -32
- package/src/tag.ts +4 -12
- package/src/types.ts +117 -5
- package/test/index.test.ts +50 -5
- package/test/mocks/webgl.ts +4 -18
- package/test/tag.test.ts +34 -10
- package/dist/chunk-7Z5UULAB.mjs.map +0 -1
- package/dist/chunk-TQWPUDQI.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
- 📦 [Install](#-install)
|
|
11
11
|
- 👁️ [view.gl](#️-viewgl)
|
|
12
12
|
- 🚀 [Basic Usage](#-basic-usage)
|
|
13
|
+
- 🧩 [The GL](#-the-gl)
|
|
13
14
|
- 👁️ [view](#️-view)
|
|
14
15
|
- 📋 [ViewSchema](#-viewschema)
|
|
15
16
|
- 👀 [Resource Views](#-resource-views)
|
|
@@ -86,6 +87,46 @@ attributes.position.set(positionData)
|
|
|
86
87
|
attributes.position.bind()
|
|
87
88
|
```
|
|
88
89
|
|
|
90
|
+
### 🧩 The GL
|
|
91
|
+
|
|
92
|
+
Everything here takes `gl`, a `GL`: what a WebGL1 context has, plus each WebGL2 feature as optional members under its WebGL2 names — instancing (`vertexAttribDivisor`, `drawArraysInstanced`, `drawElementsInstanced`, `VERTEX_ATTRIB_ARRAY_DIVISOR`) and vertex arrays (`createVertexArray`, `bindVertexArray`, `deleteVertexArray`, `VERTEX_ARRAY_BINDING`). A WebGL2 context is a `GL` as it is. view.gl asks the context nothing — no `instanceof`, no `getExtension`: a feature is on when its members are there and off when they are not.
|
|
93
|
+
|
|
94
|
+
On WebGL1 you wrap: a plain object whose core methods call the context, and whose feature members call `ANGLE_instanced_arrays` and `OES_vertex_array_object` under the WebGL2 names, left off where the context has no such extension. The enums are copied, since the extension objects spell them with a suffix. Look the extensions up again after a context restore — on Chrome 95–133 their objects die with the context — so the wrapper is a function, run once more on `webglcontextrestored`:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
import type { GL } from '@bigmistqke/view.gl'
|
|
98
|
+
|
|
99
|
+
function wrap(context: WebGLRenderingContext): GL {
|
|
100
|
+
const gl: Record<string, unknown> = {}
|
|
101
|
+
for (const key of Object.getOwnPropertyNames(WebGLRenderingContext.prototype)) {
|
|
102
|
+
const member = context[key as keyof WebGLRenderingContext]
|
|
103
|
+
gl[key] = typeof member === 'function' ? member.bind(context) : member
|
|
104
|
+
}
|
|
105
|
+
const instancing = context.getExtension('ANGLE_instanced_arrays')
|
|
106
|
+
if (instancing) {
|
|
107
|
+
gl.vertexAttribDivisor = instancing.vertexAttribDivisorANGLE.bind(instancing)
|
|
108
|
+
gl.drawArraysInstanced = instancing.drawArraysInstancedANGLE.bind(instancing)
|
|
109
|
+
gl.drawElementsInstanced = instancing.drawElementsInstancedANGLE.bind(instancing)
|
|
110
|
+
gl.VERTEX_ATTRIB_ARRAY_DIVISOR = 0x88fe
|
|
111
|
+
}
|
|
112
|
+
const vertexArrays = context.getExtension('OES_vertex_array_object')
|
|
113
|
+
if (vertexArrays) {
|
|
114
|
+
gl.createVertexArray = vertexArrays.createVertexArrayOES.bind(vertexArrays)
|
|
115
|
+
gl.bindVertexArray = vertexArrays.bindVertexArrayOES.bind(vertexArrays)
|
|
116
|
+
gl.deleteVertexArray = vertexArrays.deleteVertexArrayOES.bind(vertexArrays)
|
|
117
|
+
gl.VERTEX_ARRAY_BINDING = 0x85b5
|
|
118
|
+
}
|
|
119
|
+
return gl as GL
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
let gl = wrap(context)
|
|
123
|
+
canvas.addEventListener('webglcontextrestored', () => {
|
|
124
|
+
gl = wrap(context)
|
|
125
|
+
})
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Where vertex arrays are off, `vao()` re-applies its participants on every bind. Where instancing is off, an `instanced: true` attribute, or a layout bound `.perInstance`, throws [`InstancingUnavailableError`](#-errors), naming the attribute.
|
|
129
|
+
|
|
89
130
|
### 👁️ view
|
|
90
131
|
|
|
91
132
|
The `view()` function creates type-safe WebGL resource managers from a schema.
|
|
@@ -96,7 +137,7 @@ const { uniforms, attributes } = view(gl, program, schema)
|
|
|
96
137
|
|
|
97
138
|
**Parameters:**
|
|
98
139
|
|
|
99
|
-
- `gl`:
|
|
140
|
+
- `gl`: a [`GL`](#-the-gl) — a WebGL2 context as it is, or a WebGL1 context wrapped
|
|
100
141
|
- `program`: Compiled WebGL program
|
|
101
142
|
- `schema`: see [`ViewSchema`](#viewschema)
|
|
102
143
|
|
|
@@ -125,8 +166,8 @@ is a label for the reader. What putting it in the schema decides is its
|
|
|
125
166
|
| belongs to somebody else | name it on an attribute | nobody — it is borrowed |
|
|
126
167
|
|
|
127
168
|
An index buffer whose lifetime is its program's belongs in the schema, beside
|
|
128
|
-
the attributes it is drawn with, on the one signal. A
|
|
129
|
-
|
|
169
|
+
the attributes it is drawn with, on the one signal. A buffer handed from one
|
|
170
|
+
program's view to another's is its own thing.
|
|
130
171
|
|
|
131
172
|
<details>
|
|
132
173
|
<summary>TypeScript Types</summary>
|
|
@@ -681,7 +722,7 @@ gl.drawArrays(gl.TRIANGLES, 0, 6)
|
|
|
681
722
|
- Sets up clip-space quad covering the entire screen
|
|
682
723
|
|
|
683
724
|
**Parameters:**
|
|
684
|
-
- `gl`:
|
|
725
|
+
- `gl`: a [`GL`](#-the-gl)
|
|
685
726
|
- `fragment`: Fragment shader with embedded resources
|
|
686
727
|
- `options`: Optional compilation options (same as `compile()`)
|
|
687
728
|
|
|
@@ -884,7 +925,7 @@ const texture = createTexture(
|
|
|
884
925
|
)
|
|
885
926
|
```
|
|
886
927
|
|
|
887
|
-
|
|
928
|
+
A WebGL2-only format or type (`RGBA32F`, `HALF_FLOAT`, …) is read off the [`GL`](#-the-gl) by name; where the object has no such member, `createTexture` throws.
|
|
888
929
|
|
|
889
930
|
### 🖥️ createFramebuffer
|
|
890
931
|
|
|
@@ -921,8 +962,9 @@ Every error view.gl throws for a GL call that failed is a class exported from `@
|
|
|
921
962
|
| `ProgramLinkError` | a program does not link | `infoLog` (`string \| null`), `glError` |
|
|
922
963
|
| `GLCreateError` | a `create*` call answers `null` | `resource`: `'shader'`, `'program'`, `'buffer'`, `'vertexArray'`, `'texture'` or `'framebuffer'` |
|
|
923
964
|
| `AttributeNotFoundError` | `getAttribLocation` answers -1 | `attribute` |
|
|
965
|
+
| `InstancingUnavailableError` | an `instanced` attribute, or a layout bound `.perInstance`, on a [`GL`](#-the-gl) with instancing off | `attribute` |
|
|
924
966
|
|
|
925
|
-
A lost WebGL context answers
|
|
967
|
+
A lost WebGL context answers calls with defaults: -1 for an attribute, `false` with an empty or `null` log for a compile or link, and `null` from a `create*` in engines that predate infallible object creation (current ones hand out an object, and the loss shows up at the compile or link). So an empty `infoLog` or a `GLCreateError` carries no cause, where a non-empty `infoLog` is the driver's own reason.
|
|
926
968
|
|
|
927
969
|
```typescript
|
|
928
970
|
import { createProgram } from '@bigmistqke/view.gl/gl'
|
|
@@ -30,6 +30,13 @@ var AttributeNotFoundError = class extends Error {
|
|
|
30
30
|
}
|
|
31
31
|
name = "AttributeNotFoundError";
|
|
32
32
|
};
|
|
33
|
+
var InstancingUnavailableError = class extends Error {
|
|
34
|
+
constructor(attribute) {
|
|
35
|
+
super(`Attribute '${attribute}' is instanced, but the context has no instancing`);
|
|
36
|
+
this.attribute = attribute;
|
|
37
|
+
}
|
|
38
|
+
name = "InstancingUnavailableError";
|
|
39
|
+
};
|
|
33
40
|
function created(value, resource) {
|
|
34
41
|
if (value === null) {
|
|
35
42
|
throw new GLCreateError(resource);
|
|
@@ -225,83 +232,12 @@ function mapObject(value, callback) {
|
|
|
225
232
|
return result;
|
|
226
233
|
}
|
|
227
234
|
|
|
228
|
-
// src/gl.ts
|
|
229
|
-
function isWebGL2RenderingContext(gl) {
|
|
230
|
-
return typeof WebGL2RenderingContext !== "undefined" && gl instanceof WebGL2RenderingContext;
|
|
231
|
-
}
|
|
232
|
-
function createShader(gl, type, source) {
|
|
233
|
-
const shader = created(gl.createShader(type), "shader");
|
|
234
|
-
gl.shaderSource(shader, source);
|
|
235
|
-
gl.compileShader(shader);
|
|
236
|
-
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
237
|
-
const error = new ShaderCompileError(
|
|
238
|
-
type === gl.VERTEX_SHADER ? "vertex" : "fragment",
|
|
239
|
-
gl.getShaderInfoLog(shader),
|
|
240
|
-
gl.getError()
|
|
241
|
-
);
|
|
242
|
-
gl.deleteShader(shader);
|
|
243
|
-
throw error;
|
|
244
|
-
}
|
|
245
|
-
return shader;
|
|
246
|
-
}
|
|
247
|
-
function createProgram(gl, vertexSource, fragmentSource, { signal } = {}) {
|
|
248
|
-
const program = created(gl.createProgram(), "program");
|
|
249
|
-
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexSource);
|
|
250
|
-
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentSource);
|
|
251
|
-
gl.attachShader(program, vertexShader);
|
|
252
|
-
gl.attachShader(program, fragmentShader);
|
|
253
|
-
gl.linkProgram(program);
|
|
254
|
-
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
255
|
-
const error = new ProgramLinkError(gl.getProgramInfoLog(program), gl.getError());
|
|
256
|
-
gl.deleteProgram(program);
|
|
257
|
-
gl.deleteShader(vertexShader);
|
|
258
|
-
gl.deleteShader(fragmentShader);
|
|
259
|
-
throw error;
|
|
260
|
-
}
|
|
261
|
-
gl.deleteShader(vertexShader);
|
|
262
|
-
gl.deleteShader(fragmentShader);
|
|
263
|
-
signal?.addEventListener(
|
|
264
|
-
"abort",
|
|
265
|
-
once(() => gl.deleteProgram(program))
|
|
266
|
-
);
|
|
267
|
-
return program;
|
|
268
|
-
}
|
|
269
|
-
var INSTANCED_ARRAYS_WRAPPER_MAP = /* @__PURE__ */ new WeakMap();
|
|
270
|
-
function getInstancedArrays(gl) {
|
|
271
|
-
if (isWebGL2RenderingContext(gl)) return gl;
|
|
272
|
-
const cached = INSTANCED_ARRAYS_WRAPPER_MAP.get(gl);
|
|
273
|
-
if (cached) return cached;
|
|
274
|
-
const ext = gl.getExtension("ANGLE_instanced_arrays");
|
|
275
|
-
if (!ext) return void 0;
|
|
276
|
-
const wrapper = {
|
|
277
|
-
drawArraysInstanced: ext.drawArraysInstancedANGLE.bind(ext),
|
|
278
|
-
drawElementsInstanced: ext.drawElementsInstancedANGLE.bind(ext),
|
|
279
|
-
vertexAttribDivisor: ext.vertexAttribDivisorANGLE.bind(ext)
|
|
280
|
-
};
|
|
281
|
-
INSTANCED_ARRAYS_WRAPPER_MAP.set(gl, wrapper);
|
|
282
|
-
return wrapper;
|
|
283
|
-
}
|
|
284
|
-
var VERTEX_ARRAY_OBJECT_WRAPPER_MAP = /* @__PURE__ */ new WeakMap();
|
|
285
|
-
function getVertexArrayObject(gl) {
|
|
286
|
-
if (isWebGL2RenderingContext(gl)) return gl;
|
|
287
|
-
const cached = VERTEX_ARRAY_OBJECT_WRAPPER_MAP.get(gl);
|
|
288
|
-
if (cached) return cached;
|
|
289
|
-
const ext = gl.getExtension("OES_vertex_array_object");
|
|
290
|
-
if (!ext) return null;
|
|
291
|
-
const wrapper = {
|
|
292
|
-
bindVertexArray: ext.bindVertexArrayOES.bind(ext),
|
|
293
|
-
createVertexArray: ext.createVertexArrayOES.bind(ext),
|
|
294
|
-
deleteVertexArray: ext.deleteVertexArrayOES.bind(ext)
|
|
295
|
-
};
|
|
296
|
-
VERTEX_ARRAY_OBJECT_WRAPPER_MAP.set(gl, wrapper);
|
|
297
|
-
return wrapper;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
235
|
export {
|
|
301
236
|
ShaderCompileError,
|
|
302
237
|
ProgramLinkError,
|
|
303
238
|
GLCreateError,
|
|
304
239
|
AttributeNotFoundError,
|
|
240
|
+
InstancingUnavailableError,
|
|
305
241
|
created,
|
|
306
242
|
assertedNotNullish,
|
|
307
243
|
once,
|
|
@@ -313,10 +249,6 @@ export {
|
|
|
313
249
|
createFramebuffer,
|
|
314
250
|
createUpsertMap,
|
|
315
251
|
forEachObject,
|
|
316
|
-
mapObject
|
|
317
|
-
createShader,
|
|
318
|
-
createProgram,
|
|
319
|
-
getInstancedArrays,
|
|
320
|
-
getVertexArrayObject
|
|
252
|
+
mapObject
|
|
321
253
|
};
|
|
322
|
-
//# sourceMappingURL=chunk-
|
|
254
|
+
//# sourceMappingURL=chunk-IAM2SWJK.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/utils.ts"],"sourcesContent":["/**\n * A shader that did not compile. `infoLog` is what the driver answered, `null`\n * and `''` kept apart; `glError` is `getError()` read at the failure.\n */\nexport class ShaderCompileError extends Error {\n override name = 'ShaderCompileError'\n\n constructor(\n readonly stage: 'vertex' | 'fragment',\n readonly infoLog: string | null,\n readonly glError: number,\n ) {\n super(`Failed to compile ${stage} shader: ${infoLog}`)\n }\n}\n\n/**\n * A program that did not link. `infoLog` is what the driver answered, `null`\n * and `''` kept apart; `glError` is `getError()` read at the failure.\n */\nexport class ProgramLinkError extends Error {\n override name = 'ProgramLinkError'\n\n constructor(\n readonly infoLog: string | null,\n readonly glError: number,\n ) {\n super(`Failed to link program: ${infoLog}`)\n }\n}\n\nexport type GLResource = 'shader' | 'program' | 'buffer' | 'vertexArray' | 'texture' | 'framebuffer'\n\n/** A `create*` call that answered `null`. */\nexport class GLCreateError extends Error {\n override name = 'GLCreateError'\n\n constructor(readonly resource: GLResource) {\n super(`Failed to create ${resource}`)\n }\n}\n\n/** A program with no active attribute of that name: `getAttribLocation` answered -1. */\nexport class AttributeNotFoundError extends Error {\n override name = 'AttributeNotFoundError'\n\n constructor(readonly attribute: string) {\n super(`Attribute '${attribute}' not found`)\n }\n}\n\n/** A divisor of 1 asked of a context without `vertexAttribDivisor`: the draw cannot instance. */\nexport class InstancingUnavailableError extends Error {\n override name = 'InstancingUnavailableError'\n\n constructor(readonly attribute: string) {\n super(`Attribute '${attribute}' is instanced, but the context has no instancing`)\n }\n}\n\n/** Throws a {@link GLCreateError} for a `create*` that answered `null`. */\nexport function created<T>(value: T | null, resource: GLResource): T {\n if (value === null) {\n throw new GLCreateError(resource)\n }\n return value\n}\n","import { created } from './errors'\nimport 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 = created(gl.createTexture(), '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 = created(gl.createFramebuffer(), '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"],"mappings":"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","names":["value"]}
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AttributeNotFoundError,
|
|
3
|
+
InstancingUnavailableError,
|
|
3
4
|
assertedNotNullish,
|
|
4
5
|
createUpsertMap,
|
|
5
6
|
created,
|
|
6
7
|
forEachObject,
|
|
7
|
-
getInstancedArrays,
|
|
8
|
-
getVertexArrayObject,
|
|
9
8
|
isMatKind,
|
|
10
9
|
isSamplerKind,
|
|
11
10
|
kindToSize,
|
|
12
11
|
kindToUniformFnName,
|
|
13
12
|
mapObject,
|
|
14
13
|
once
|
|
15
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-IAM2SWJK.mjs";
|
|
16
15
|
|
|
17
16
|
// src/index.ts
|
|
18
17
|
var index = 0;
|
|
@@ -69,17 +68,22 @@ function view(gl, program, schema, { signal } = {}) {
|
|
|
69
68
|
};
|
|
70
69
|
}
|
|
71
70
|
function bindDefaultVertexArray(gl) {
|
|
72
|
-
|
|
73
|
-
if (!feature) {
|
|
71
|
+
if (!hasVertexArrays(gl)) {
|
|
74
72
|
return () => {
|
|
75
73
|
};
|
|
76
74
|
}
|
|
77
75
|
const previous = readVertexArrayBinding(gl);
|
|
78
|
-
|
|
79
|
-
return () =>
|
|
76
|
+
gl.bindVertexArray(null);
|
|
77
|
+
return () => gl.bindVertexArray(previous);
|
|
78
|
+
}
|
|
79
|
+
function hasVertexArrays(gl) {
|
|
80
|
+
return typeof gl.createVertexArray === "function" && typeof gl.bindVertexArray === "function" && typeof gl.deleteVertexArray === "function" && typeof gl.VERTEX_ARRAY_BINDING === "number";
|
|
81
|
+
}
|
|
82
|
+
function hasInstancing(gl) {
|
|
83
|
+
return typeof gl.vertexAttribDivisor === "function" && typeof gl.drawArraysInstanced === "function" && typeof gl.drawElementsInstanced === "function" && typeof gl.VERTEX_ATTRIB_ARRAY_DIVISOR === "number";
|
|
80
84
|
}
|
|
81
85
|
function vaoView(gl, participants, { signal } = {}) {
|
|
82
|
-
const feature =
|
|
86
|
+
const feature = hasVertexArrays(gl) ? gl : null;
|
|
83
87
|
const methods = !feature ? {
|
|
84
88
|
bind() {
|
|
85
89
|
const restores = participants.map((participant) => participant.applyToVertexArray());
|
|
@@ -92,7 +96,7 @@ function vaoView(gl, participants, { signal } = {}) {
|
|
|
92
96
|
}
|
|
93
97
|
} : (() => {
|
|
94
98
|
const vertexArray = created(feature.createVertexArray(), "vertexArray");
|
|
95
|
-
const previous = readVertexArrayBinding(
|
|
99
|
+
const previous = readVertexArrayBinding(feature);
|
|
96
100
|
feature.bindVertexArray(vertexArray);
|
|
97
101
|
for (const participant of participants) {
|
|
98
102
|
participant.applyToVertexArray();
|
|
@@ -100,7 +104,7 @@ function vaoView(gl, participants, { signal } = {}) {
|
|
|
100
104
|
feature.bindVertexArray(previous);
|
|
101
105
|
return {
|
|
102
106
|
bind() {
|
|
103
|
-
const previousVertexArray = readVertexArrayBinding(
|
|
107
|
+
const previousVertexArray = readVertexArrayBinding(feature);
|
|
104
108
|
feature.bindVertexArray(vertexArray);
|
|
105
109
|
participants.forEach((participant) => participant.applyToContext?.());
|
|
106
110
|
return once(() => feature.bindVertexArray(previousVertexArray));
|
|
@@ -186,29 +190,35 @@ function defaultFormat(kind) {
|
|
|
186
190
|
if (kind.startsWith("i")) return "int32";
|
|
187
191
|
return "float32";
|
|
188
192
|
}
|
|
189
|
-
function handleAttribute(gl, location, size, stride, offset, glType, isIntegerKind, normalized, instanced) {
|
|
193
|
+
function handleAttribute(gl, location, size, stride, offset, glType, isIntegerKind, normalized, instanced, name) {
|
|
190
194
|
gl.enableVertexAttribArray(location);
|
|
191
195
|
if (isIntegerKind) {
|
|
192
|
-
|
|
193
|
-
|
|
196
|
+
assertedNotNullish(gl.vertexAttribIPointer, "the context has no vertexAttribIPointer").call(
|
|
197
|
+
gl,
|
|
198
|
+
location,
|
|
199
|
+
size,
|
|
200
|
+
gl[glType],
|
|
201
|
+
stride,
|
|
202
|
+
offset
|
|
203
|
+
);
|
|
194
204
|
} else {
|
|
195
205
|
gl.vertexAttribPointer(location, size, gl[glType], normalized, stride, offset);
|
|
196
206
|
}
|
|
197
|
-
const instancedArrays = getInstancedArrays(gl);
|
|
198
207
|
if (instanced) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
208
|
+
if (!hasInstancing(gl)) {
|
|
209
|
+
throw new InstancingUnavailableError(name);
|
|
210
|
+
}
|
|
211
|
+
gl.vertexAttribDivisor(location, 1);
|
|
212
|
+
} else if (hasInstancing(gl)) {
|
|
213
|
+
gl.vertexAttribDivisor(location, 0);
|
|
202
214
|
}
|
|
203
215
|
}
|
|
204
|
-
var VERTEX_ATTRIB_ARRAY_DIVISOR = 35070;
|
|
205
|
-
var VERTEX_ARRAY_BINDING = 34229;
|
|
206
216
|
function readVertexArrayBinding(gl) {
|
|
207
|
-
const bound = gl.getParameter(VERTEX_ARRAY_BINDING);
|
|
217
|
+
const bound = gl.getParameter(gl.VERTEX_ARRAY_BINDING);
|
|
208
218
|
return typeof bound === "object" ? bound : null;
|
|
209
219
|
}
|
|
210
220
|
function readDivisor(gl, location) {
|
|
211
|
-
return
|
|
221
|
+
return hasInstancing(gl) ? gl.getVertexAttrib(location, gl.VERTEX_ATTRIB_ARRAY_DIVISOR) : 0;
|
|
212
222
|
}
|
|
213
223
|
function attributeView(gl, program, schema, { signal } = {}) {
|
|
214
224
|
const attributes = mapObject(
|
|
@@ -227,9 +237,11 @@ function attributeView(gl, program, schema, { signal } = {}) {
|
|
|
227
237
|
function applyToVertexArray() {
|
|
228
238
|
const previousDivisor = readDivisor(gl, location);
|
|
229
239
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
230
|
-
handleAttribute(gl, location, size, 0, 0, glType, isIntKind, normalized, instanced);
|
|
240
|
+
handleAttribute(gl, location, size, 0, 0, glType, isIntKind, normalized, instanced, name);
|
|
231
241
|
return once(() => {
|
|
232
|
-
|
|
242
|
+
if (hasInstancing(gl)) {
|
|
243
|
+
gl.vertexAttribDivisor(location, previousDivisor);
|
|
244
|
+
}
|
|
233
245
|
});
|
|
234
246
|
}
|
|
235
247
|
return {
|
|
@@ -348,7 +360,8 @@ function interleavedAttributeView(gl, program, schema, { signal } = {}) {
|
|
|
348
360
|
glType,
|
|
349
361
|
isIntKind,
|
|
350
362
|
normalized,
|
|
351
|
-
divisor === 1
|
|
363
|
+
divisor === 1,
|
|
364
|
+
name
|
|
352
365
|
);
|
|
353
366
|
});
|
|
354
367
|
const stride = index2;
|
|
@@ -362,10 +375,11 @@ function interleavedAttributeView(gl, program, schema, { signal } = {}) {
|
|
|
362
375
|
handle(divisor);
|
|
363
376
|
}
|
|
364
377
|
return once(() => {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
378
|
+
if (hasInstancing(gl)) {
|
|
379
|
+
previousDivisors.forEach(([location, previous]) => {
|
|
380
|
+
gl.vertexAttribDivisor(location, previous);
|
|
381
|
+
});
|
|
382
|
+
}
|
|
369
383
|
});
|
|
370
384
|
}
|
|
371
385
|
let constant;
|
|
@@ -463,4 +477,4 @@ export {
|
|
|
463
477
|
interleavedAttributeView,
|
|
464
478
|
bufferView
|
|
465
479
|
};
|
|
466
|
-
//# sourceMappingURL=chunk-
|
|
480
|
+
//# sourceMappingURL=chunk-NRCBGOZB.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { AttributeNotFoundError, InstancingUnavailableError, created } from './errors'\nimport type {\n AttributeFormat,\n AttributeKind,\n AttributeMethods,\n AttributeSchema,\n AttributeView,\n BufferSchema,\n BufferView,\n GL,\n Instancing,\n UniformView as InferUniformView,\n GLUsage,\n InterleavedAttributeLayout,\n InterleavedAttributeMethods,\n InterleavedAttributeSchema,\n InterleavedAttributeView,\n UniformSchema,\n VertexArrayMethods,\n VertexArrayParticipant,\n VertexArrays,\n View,\n ViewOptions,\n ViewSchema,\n} from './types'\nimport {\n isSamplerKind,\n kindToUniformFnName,\n isMatKind,\n assertedNotNullish,\n kindToSize,\n forEachObject,\n once,\n} from './utils'\nimport { createUpsertMap, mapObject } from './utils'\nexport * from './errors'\nexport * from './types'\n// Documented under Utils but reachable from nowhere until now: utils is not a\n// build entry, and named rather than star so the internal helpers stay internal.\nexport { createFramebuffer, createTexture } from './utils'\n\n/**********************************************************************************/\n/* */\n/* To ID */\n/* */\n/**********************************************************************************/\n\nlet index = 0\nconst PREFIX = 'VIEW_GL_ALIAS'\n// Firefox has currently a bug where it can not handle symbol as WeakRef / key for WeakMap\n// see https://bugzilla.mozilla.org/show_bug.cgi?id=1710433\nconst HAS_WEAK_SYMBOL = (() => {\n try {\n const symbol = Symbol()\n new WeakMap().set(symbol, '')\n return true\n } catch {\n return false\n }\n})()\n// NOTE: fallback to Map will currently cause a minor memory leak.\nconst SYMBOL_MAP = createUpsertMap(HAS_WEAK_SYMBOL ? WeakMap<symbol, string> : Map<symbol, string>)\n\nexport function toID(key: string | number | symbol) {\n if (typeof key === 'string') {\n return key\n }\n if (typeof key === 'symbol') {\n return SYMBOL_MAP.getOrInsert(key, () => `${PREFIX}_${index++}`)\n }\n return key.toString()\n}\n\n/**********************************************************************************/\n/* */\n/* View */\n/* */\n/**********************************************************************************/\n\nexport function view<TSchema extends ViewSchema>(\n gl: GL,\n program: WebGLProgram,\n schema: TSchema,\n { signal }: ViewOptions = {},\n): View<TSchema> {\n // The sub-views are built without the signal and the view wires disposal\n // once, so that `dispose()` and aborting do the same thing rather than each\n // doing half of it.\n const attributes = !schema.attributes ? undefined : attributeView(gl, program, schema.attributes)\n const interleavedAttributes = !schema.interleavedAttributes\n ? undefined\n : interleavedAttributeView(gl, program, schema.interleavedAttributes)\n // Owned by the view, on the view's signal. This is the line the split was\n // really about: it used to read `bufferView(gl, schema.buffers)` with the\n // options dropped, so a view's buffers were the only resources that still\n // needed disposing by hand. That was a missing argument rather than a wrong\n // model — a buffer whose lifetime IS the view's belongs with it.\n const buffers = !schema.buffers ? undefined : bufferView(gl, schema.buffers)\n\n // Vertex arrays are made on demand rather than declared, so they are the one\n // thing the view cannot dispose from the schema alone. Held until disposed —\n // by the view or by the caller — and dropped either way, so a view that hands\n // out an array per frame does not accumulate them.\n const vertexArrays = new Set<VertexArrayMethods>()\n\n const dispose = once(() => {\n if (attributes) forEachObject(attributes, value => value.dispose())\n if (interleavedAttributes) forEachObject(interleavedAttributes, value => value.dispose())\n if (buffers) forEachObject(buffers, value => value.dispose())\n vertexArrays.forEach(vertexArray => vertexArray.dispose())\n vertexArrays.clear()\n })\n\n signal?.addEventListener('abort', dispose)\n\n return {\n uniforms: !schema.uniforms ? undefined : uniformView(gl, program, schema.uniforms),\n attributes,\n interleavedAttributes,\n buffers,\n vao(participants: VertexArrayParticipant[]) {\n const vertexArray = vaoView(gl, participants)\n vertexArrays.add(vertexArray)\n return {\n ...vertexArray,\n dispose: once(() => {\n vertexArrays.delete(vertexArray)\n vertexArray.dispose()\n }),\n }\n },\n dispose,\n } as View<TSchema>\n}\n\n/**********************************************************************************/\n/* */\n/* Vertex Array */\n/* */\n/**********************************************************************************/\n\n/**\n * Bind the default vertex array, returning a disposer that puts the previous\n * one back. The pointer calls name no destination, so anything applied without\n * a vertex array of its own has to say which one it means — and a vertex array\n * keeps what it is given, so writing into a caller's array by accident would\n * outlive the call that did it.\n */\nfunction bindDefaultVertexArray(gl: GL): () => void {\n if (!hasVertexArrays(gl)) {\n return () => {}\n }\n const previous = readVertexArrayBinding(gl)\n gl.bindVertexArray(null)\n return () => gl.bindVertexArray(previous)\n}\n\n/** Whether `gl` carries the vertex-array feature, every member of it. */\nfunction hasVertexArrays(gl: GL): gl is GL & VertexArrays {\n return (\n typeof gl.createVertexArray === 'function' &&\n typeof gl.bindVertexArray === 'function' &&\n typeof gl.deleteVertexArray === 'function' &&\n typeof gl.VERTEX_ARRAY_BINDING === 'number'\n )\n}\n\n/** Whether `gl` carries the instancing feature, every member of it. */\nfunction hasInstancing(gl: GL): gl is GL & Instancing {\n return (\n typeof gl.vertexAttribDivisor === 'function' &&\n typeof gl.drawArraysInstanced === 'function' &&\n typeof gl.drawElementsInstanced === 'function' &&\n typeof gl.VERTEX_ATTRIB_ARRAY_DIVISOR === 'number'\n )\n}\n\n/**\n * A vertex array over the participants one draw needs.\n *\n * Where the context has vertex arrays, each participant writes itself in once,\n * here, and `bind()` is a single `bindVertexArray`. Where it does not — WebGL1\n * without `OES_vertex_array_object` — there is nowhere to keep the state, so\n * `bind()` re-applies every participant and the disposer puts back what they\n * displaced. Same contract, and the emulation is why the name still fits.\n */\nexport function vaoView(\n gl: GL,\n participants: VertexArrayParticipant[],\n { signal }: ViewOptions = {},\n): VertexArrayMethods {\n const feature = hasVertexArrays(gl) ? gl : null\n\n const methods: VertexArrayMethods = !feature\n ? {\n bind() {\n const restores = participants.map(participant => participant.applyToVertexArray())\n participants.forEach(participant => participant.applyToContext?.())\n return once(() => restores.forEach(restore => restore()))\n },\n unbind() {},\n dispose() {},\n }\n : (() => {\n const vertexArray = created(feature.createVertexArray(), 'vertexArray')\n const previous = readVertexArrayBinding(feature)\n feature.bindVertexArray(vertexArray)\n // Discarding the restorers is the point: the state lives in this array\n // now, and the array is thrown away whole.\n for (const participant of participants) {\n participant.applyToVertexArray()\n }\n feature.bindVertexArray(previous)\n\n return {\n bind() {\n const previousVertexArray = readVertexArrayBinding(feature)\n feature.bindVertexArray(vertexArray)\n // Context state the array cannot hold — see applyToContext.\n participants.forEach(participant => participant.applyToContext?.())\n return once(() => feature.bindVertexArray(previousVertexArray))\n },\n unbind() {\n feature.bindVertexArray(null)\n },\n dispose: once(() => feature.deleteVertexArray(vertexArray)),\n }\n })()\n\n signal?.addEventListener('abort', () => methods.dispose())\n\n return methods\n}\n\n/**********************************************************************************/\n/* */\n/* Uniform View */\n/* */\n/**********************************************************************************/\n\nexport function uniformView<T extends UniformSchema>(\n gl: GL,\n program: WebGLProgram,\n schema: T,\n): InferUniformView<T> {\n // @ts-expect-error - conditional return type based on size is hard to infer\n return mapObject(schema, ({ kind, size }, key) => {\n const name = toID(key)\n\n if (isSamplerKind(kind)) {\n const location = gl.getUniformLocation(program, name)\n return {\n set(arg: number) {\n gl.uniform1i(location, arg)\n },\n }\n }\n\n // Array uniform - support both bulk set and indexed access\n if (size) {\n const bulkFnName = `uniform${kindToUniformFnName(kind)}v`\n // @ts-ignore FIX WEBGL/WEBGL2 TYPES\n const bulkFn = gl[bulkFnName].bind(gl)\n const bulkLocation = gl.getUniformLocation(program, name)\n\n const elementFnName = `uniform${kindToUniformFnName(kind)}`\n // @ts-ignore FIX WEBGL/WEBGL2 TYPES\n const elementFn = gl[elementFnName].bind(gl)\n\n // Build array of element setters\n const elements: Array<{ set(...args: any[]): void }> = []\n for (let i = 0; i < size; i++) {\n const location = gl.getUniformLocation(program, `${name}[${i}]`)\n elements[i] = {\n set(...args: any[]) {\n elementFn(location, ...args)\n },\n }\n }\n\n // Return array-like object with bulk set\n return Object.assign(elements, {\n set(arg: Float32Array) {\n bulkFn(bulkLocation, arg)\n },\n })\n }\n\n // Non-array uniform\n const location = gl.getUniformLocation(program, name)\n const fnName = `uniform${kindToUniformFnName(kind)}`\n\n // @ts-ignore FIX WEBGL/WEBGL2 TYPES\n const fn = gl[fnName].bind(gl)\n\n if (isMatKind(kind)) {\n return {\n set(...args: any[]) {\n fn(location, false, args[0])\n },\n }\n }\n\n return {\n set(...args: any[]) {\n fn(location, ...args)\n },\n }\n })\n}\n\n/**********************************************************************************/\n/* */\n/* Attribute View */\n/* */\n/**********************************************************************************/\n\ntype GLType =\n | 'FLOAT'\n | 'INT'\n | 'UNSIGNED_INT'\n | 'SHORT'\n | 'UNSIGNED_SHORT'\n | 'BYTE'\n | 'UNSIGNED_BYTE'\n\nconst FORMAT_TO_GL_TYPE: Record<AttributeFormat, GLType> = {\n float32: 'FLOAT',\n int32: 'INT',\n uint32: 'UNSIGNED_INT',\n int16: 'SHORT',\n uint16: 'UNSIGNED_SHORT',\n int8: 'BYTE',\n uint8: 'UNSIGNED_BYTE',\n}\n\nconst FORMAT_BYTE_SIZE: Record<AttributeFormat, number> = {\n float32: 4,\n int32: 4,\n uint32: 4,\n int16: 2,\n uint16: 2,\n int8: 1,\n uint8: 1,\n}\n\nfunction defaultFormat(kind: AttributeKind): AttributeFormat {\n if (kind.startsWith('u')) return 'uint32'\n if (kind.startsWith('i')) return 'int32'\n return 'float32'\n}\n\n// Shared attribute helper functions\n// between attributeView and interleavedAttributeView\nfunction handleAttribute(\n gl: GL,\n location: number,\n size: number,\n stride: number,\n offset: number,\n glType: GLType,\n isIntegerKind: boolean,\n normalized: boolean,\n instanced: boolean | undefined,\n name: string,\n) {\n gl.enableVertexAttribArray(location)\n if (isIntegerKind) {\n assertedNotNullish(gl.vertexAttribIPointer, 'the context has no vertexAttribIPointer').call(\n gl,\n location,\n size,\n gl[glType],\n stride,\n offset,\n )\n } else {\n gl.vertexAttribPointer(location, size, gl[glType], normalized, stride, offset)\n }\n\n // Always stated, never inherited: the divisor belongs to the location rather\n // than to the program, so a location left at 1 by an earlier instanced\n // attribute would feed one value to every vertex here.\n if (instanced) {\n if (!hasInstancing(gl)) {\n throw new InstancingUnavailableError(name)\n }\n gl.vertexAttribDivisor(location, 1)\n } else if (hasInstancing(gl)) {\n gl.vertexAttribDivisor(location, 0)\n }\n}\n\n// Anything but an array or null would make the restore throw a TypeError.\nfunction readVertexArrayBinding(gl: GL & VertexArrays): WebGLVertexArrayObject | null {\n const bound: unknown = gl.getParameter(gl.VERTEX_ARRAY_BINDING)\n return typeof bound === 'object' ? (bound as WebGLVertexArrayObject | null) : null\n}\n\n// Reads the divisor currently attached to a location, 0 where instancing is\n// unavailable and nothing can have set one\nfunction readDivisor(gl: GL, location: number): number {\n return hasInstancing(gl)\n ? (gl.getVertexAttrib(location, gl.VERTEX_ATTRIB_ARRAY_DIVISOR) as number)\n : 0\n}\n\nexport function attributeView<T extends AttributeSchema>(\n gl: GL,\n program: WebGLProgram,\n schema: T,\n { signal }: ViewOptions = {},\n): AttributeView<T> {\n const attributes = mapObject(\n schema,\n (\n { kind, format, normalized = false, instanced, buffer: providedBuffer },\n key,\n ): AttributeMethods => {\n const name = toID(key)\n\n // Whoever made the buffer deletes it. A schema can name a buffer that\n // belongs to another view — an attribute two programs step over — and\n // deleting one of those would take it out from under its owner.\n const buffer = providedBuffer ?? created(gl.createBuffer(), 'buffer')\n\n const location = gl.getAttribLocation(program, name)\n if (location < 0) {\n throw new AttributeNotFoundError(name)\n }\n\n const size = kindToSize(kind)\n const resolvedFormat = format ?? defaultFormat(kind)\n const glType = FORMAT_TO_GL_TYPE[resolvedFormat]\n const isIntKind = kind.startsWith('i') || kind.startsWith('u')\n\n function applyToVertexArray() {\n // Snapshot before the change, restore in the disposer\n const previousDivisor = readDivisor(gl, location)\n // vertexAttribPointer captures whatever is bound to ARRAY_BUFFER when\n // it runs, so this binding is the setup for the pointer, not a lasting\n // part of the vertex array's state.\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n handleAttribute(gl, location, size, 0, 0, glType, isIntKind, normalized, instanced, name)\n return once(() => {\n if (hasInstancing(gl)) {\n gl.vertexAttribDivisor(location, previousDivisor)\n }\n })\n }\n\n return {\n buffer,\n applyToVertexArray,\n bind() {\n const restoreVertexArray = bindDefaultVertexArray(gl)\n const restore = applyToVertexArray()\n return once(() => {\n restore()\n restoreVertexArray()\n })\n },\n dispose: once(() => {\n if (!providedBuffer) {\n gl.deleteBuffer(buffer)\n }\n }),\n set(data, usage = 'STATIC_DRAW') {\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n gl.bufferData(gl.ARRAY_BUFFER, data, gl[usage])\n return this\n },\n allocate(length, usage = 'STATIC_DRAW') {\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n gl.bufferData(gl.ARRAY_BUFFER, length * FORMAT_BYTE_SIZE[resolvedFormat], gl[usage])\n return this\n },\n write(data, offset) {\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n gl.bufferSubData(gl.ARRAY_BUFFER, offset * FORMAT_BYTE_SIZE[resolvedFormat], data)\n return this\n },\n }\n },\n )\n\n signal?.addEventListener('abort', function dispose() {\n forEachObject(attributes, value => value.dispose())\n })\n\n return attributes\n}\n\n/**********************************************************************************/\n/* */\n/* Interleaved Attribute View */\n/* */\n/**********************************************************************************/\n\n/**\n * The other place an attribute's value can come from: not a buffer, but the\n * context's current generic vertex attribute values, which an attribute reads\n * for every vertex when its array is disabled.\n *\n * A constant is a uniform in all but name — one value for the whole draw, set\n * by a function chosen from the kind — so it gets the setters a uniform gets,\n * off the same layout the buffer source uses.\n *\n * `vertexAttrib*` tops out at four floats and has no matrix form, so a layout\n * key that is fine in a buffer can be impossible as a constant. That is a hard\n * limit of the API rather than a choice, and it is worth saying so out loud at\n * the point someone reaches for it.\n */\nfunction constantSource(gl: GL, layout: InterleavedAttributeLayout[], locations: number[]) {\n const setters = layout.map((entry, index) => {\n const size = kindToSize(entry.kind)\n const name = toID(entry.key)\n if (isMatKind(entry.kind) || size > 4) {\n throw new Error(\n `'${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.`,\n )\n }\n // The values are context state, not vertex-array state, so they are held\n // here and written again on every bind — see applyToContext.\n let values: number[] = []\n const fn = gl[`vertexAttrib${size as 1 | 2 | 3 | 4}f`].bind(gl)\n return {\n name,\n location: locations[index]!,\n write: () => {\n if (values.length) {\n ;(fn as (location: number, ...args: number[]) => void)(locations[index]!, ...values)\n }\n },\n methods: {\n set(...args: number[]) {\n values = args\n },\n },\n }\n })\n\n return Object.assign(Object.fromEntries(setters.map(setter => [setter.name, setter.methods])), {\n applyToVertexArray() {\n const restores = setters.map(({ location }) => {\n const wasEnabled = gl.getVertexAttrib(location, gl.VERTEX_ATTRIB_ARRAY_ENABLED) as boolean\n gl.disableVertexAttribArray(location)\n return () => (wasEnabled ? gl.enableVertexAttribArray(location) : undefined)\n })\n return once(() => restores.forEach(restore => restore()))\n },\n applyToContext() {\n setters.forEach(setter => setter.write())\n },\n bind() {\n const restoreVertexArray = bindDefaultVertexArray(gl)\n const restore = this.applyToVertexArray()\n this.applyToContext()\n return once(() => {\n restore()\n restoreVertexArray()\n })\n },\n })\n}\n\nexport function interleavedAttributeView<T extends InterleavedAttributeSchema>(\n gl: GL,\n program: WebGLProgram,\n schema: T,\n { signal }: ViewOptions = {},\n): InterleavedAttributeView<T> {\n // Initialize interleaved attributes\n const interleavedAttributes = mapObject(schema, ({ layout }) => {\n // Increment number to keep track of offset\n let index = 0\n\n // Calculate layout information\n const locations: number[] = []\n const handles = layout.map(layout => {\n const name = toID(layout.key)\n\n const location = gl.getAttribLocation(program, name)\n\n if (location < 0) {\n throw new AttributeNotFoundError(name)\n }\n\n locations.push(location)\n\n const size = kindToSize(layout.kind)\n const offset = index\n const resolvedFormat = layout.format ?? defaultFormat(layout.kind)\n const glType = FORMAT_TO_GL_TYPE[resolvedFormat]\n const isIntKind = layout.kind.startsWith('i') || layout.kind.startsWith('u')\n const normalized = layout.normalized ?? false\n index += size * FORMAT_BYTE_SIZE[resolvedFormat]\n\n return (divisor: 0 | 1) =>\n handleAttribute(\n gl,\n location,\n size,\n stride,\n offset,\n glType,\n isIntKind,\n normalized,\n divisor === 1,\n name,\n )\n })\n\n // Set stride to final index\n const stride = index\n\n // Create a buffer\n const buffer = created(gl.createBuffer(), 'buffer')\n\n // This layout used to create a vertex array of its own, here, which is why\n // the other participants in a draw had to be bound after it to be included\n // — the array they landed in was whichever one happened to be current.\n // Arrays are `vao()`'s job now; a layout is a layout and a buffer.\n function applyToVertexArray(divisor: 0 | 1) {\n const previousDivisors = locations.map(\n location => [location, readDivisor(gl, location)] as const,\n )\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n for (const handle of handles) {\n handle(divisor)\n }\n return once(() => {\n if (hasInstancing(gl)) {\n previousDivisors.forEach(([location, previous]) => {\n gl.vertexAttribDivisor(location, previous)\n })\n }\n })\n }\n\n let constant: ReturnType<typeof constantSource> | undefined\n\n /** One layout, one buffer, but a divisor per draw rather than per schema. */\n function bufferSource(divisor: 0 | 1) {\n const apply = () => applyToVertexArray(divisor)\n return {\n applyToVertexArray: apply,\n bind() {\n const restoreVertexArray = bindDefaultVertexArray(gl)\n const restore = apply()\n return once(() => {\n restore()\n restoreVertexArray()\n })\n },\n }\n }\n\n return {\n buffer: Object.assign(bufferSource(0), {\n /** The same buffer, stepped once per instance instead of once per vertex. */\n perInstance: bufferSource(1),\n set(value: Float32Array, usage: GLUsage = 'STATIC_DRAW') {\n // Uploading is storage, not binding: ARRAY_BUFFER is not vertex-array\n // state, so this touches no array, whichever one is bound.\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n gl.bufferData(gl.ARRAY_BUFFER, value, gl[usage])\n },\n allocate(length: number, usage: GLUsage = 'STATIC_DRAW') {\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n gl.bufferData(gl.ARRAY_BUFFER, length * Float32Array.BYTES_PER_ELEMENT, gl[usage])\n },\n write(data: Float32Array, offset: number) {\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n gl.bufferSubData(gl.ARRAY_BUFFER, offset * Float32Array.BYTES_PER_ELEMENT, data)\n },\n }),\n // Lazy: a layout key can be perfectly good in a buffer and impossible as\n // a constant, and finding that out should wait until someone asks for one.\n get constant() {\n return (constant ??= constantSource(gl, layout, locations))\n },\n dispose: once(() => gl.deleteBuffer(buffer)),\n } satisfies InterleavedAttributeMethods\n })\n\n signal?.addEventListener('abort', function dispose() {\n forEachObject(interleavedAttributes, value => value.dispose())\n })\n\n return interleavedAttributes\n}\n\n/**********************************************************************************/\n/* */\n/* Buffer View */\n/* */\n/**********************************************************************************/\n\nexport function bufferView<T extends BufferSchema>(\n gl: GL,\n schema: T,\n { signal }: ViewOptions = {},\n): BufferView<T> {\n // Initialize buffers\n const buffers = mapObject(schema, ({ target = 'ARRAY_BUFFER', usage = 'STATIC_DRAW' }) => {\n const buffer = created(gl.createBuffer(), 'buffer')\n\n function applyToVertexArray() {\n // Snapshot before the change, restore in the disposer. Restoring the\n // previous buffer rather than null matters for ELEMENT_ARRAY_BUFFER,\n // whose binding is recorded in the bound vertex array: clearing it\n // would strip the index buffer from an array the caller may not own.\n const previousBuffer = gl.getParameter(gl[`${target}_BINDING`]) as WebGLBuffer | null\n gl.bindBuffer(gl[target], buffer)\n return once(() => {\n gl.bindBuffer(gl[target], previousBuffer)\n })\n }\n\n return {\n applyToVertexArray,\n bind() {\n // ELEMENT_ARRAY_BUFFER's binding belongs to the bound vertex array, so\n // like the attributes this has to say which array it means. ARRAY_BUFFER\n // is context state and unaffected either way.\n const restoreVertexArray = bindDefaultVertexArray(gl)\n const restore = applyToVertexArray()\n return once(() => {\n restore()\n restoreVertexArray()\n })\n },\n dispose: once(() => gl.deleteBuffer(buffer)),\n set(data: Float32Array) {\n gl.bindBuffer(gl[target], buffer)\n gl.bufferData(gl[target], data, gl[usage])\n },\n allocate(byteLength: number) {\n gl.bindBuffer(gl[target], buffer)\n gl.bufferData(gl[target], byteLength, gl[usage])\n },\n write(data: Float32Array | Uint16Array | Uint32Array, byteOffset: number) {\n gl.bindBuffer(gl[target], buffer)\n gl.bufferSubData(gl[target], byteOffset, data)\n },\n }\n })\n\n signal?.addEventListener('abort', function dispose() {\n forEachObject(buffers, value => value.dispose())\n })\n\n return buffers\n}\n"],"mappings":"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","names":["location","index","layout"]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ProgramLinkError,
|
|
3
|
+
ShaderCompileError,
|
|
4
|
+
created,
|
|
5
|
+
once
|
|
6
|
+
} from "./chunk-IAM2SWJK.mjs";
|
|
7
|
+
|
|
8
|
+
// src/gl.ts
|
|
9
|
+
function createShader(gl, type, source) {
|
|
10
|
+
const shader = created(gl.createShader(type), "shader");
|
|
11
|
+
gl.shaderSource(shader, source);
|
|
12
|
+
gl.compileShader(shader);
|
|
13
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
14
|
+
const error = new ShaderCompileError(
|
|
15
|
+
type === gl.VERTEX_SHADER ? "vertex" : "fragment",
|
|
16
|
+
gl.getShaderInfoLog(shader),
|
|
17
|
+
gl.getError()
|
|
18
|
+
);
|
|
19
|
+
gl.deleteShader(shader);
|
|
20
|
+
throw error;
|
|
21
|
+
}
|
|
22
|
+
return shader;
|
|
23
|
+
}
|
|
24
|
+
function createProgram(gl, vertexSource, fragmentSource, { signal } = {}) {
|
|
25
|
+
const program = created(gl.createProgram(), "program");
|
|
26
|
+
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexSource);
|
|
27
|
+
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentSource);
|
|
28
|
+
gl.attachShader(program, vertexShader);
|
|
29
|
+
gl.attachShader(program, fragmentShader);
|
|
30
|
+
gl.linkProgram(program);
|
|
31
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
32
|
+
const error = new ProgramLinkError(gl.getProgramInfoLog(program), gl.getError());
|
|
33
|
+
gl.deleteProgram(program);
|
|
34
|
+
gl.deleteShader(vertexShader);
|
|
35
|
+
gl.deleteShader(fragmentShader);
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
gl.deleteShader(vertexShader);
|
|
39
|
+
gl.deleteShader(fragmentShader);
|
|
40
|
+
signal?.addEventListener(
|
|
41
|
+
"abort",
|
|
42
|
+
once(() => gl.deleteProgram(program))
|
|
43
|
+
);
|
|
44
|
+
return program;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export {
|
|
48
|
+
createShader,
|
|
49
|
+
createProgram
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=chunk-UVDTF5P3.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/gl.ts"],"sourcesContent":["import type { GL, ViewOptions } from './types'\nimport { created, ProgramLinkError, ShaderCompileError } from './errors'\nimport { once } from './utils'\n\n/**********************************************************************************/\n/* */\n/* Create Shader */\n/* */\n/**********************************************************************************/\n\nexport function createShader(gl: GL, type: number, source: string): WebGLShader {\n const shader = created(gl.createShader(type), 'shader')\n\n gl.shaderSource(shader, source)\n gl.compileShader(shader)\n\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const error = new ShaderCompileError(\n type === gl.VERTEX_SHADER ? 'vertex' : 'fragment',\n gl.getShaderInfoLog(shader),\n gl.getError(),\n )\n gl.deleteShader(shader)\n throw error\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 = created(gl.createProgram(), '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 error = new ProgramLinkError(gl.getProgramInfoLog(program), gl.getError())\n gl.deleteProgram(program)\n gl.deleteShader(vertexShader)\n gl.deleteShader(fragmentShader)\n throw error\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"],"mappings":";;;;;;;;AAUO,SAAS,aAAa,IAAQ,MAAc,QAA6B;AAC9E,QAAM,SAAS,QAAQ,GAAG,aAAa,IAAI,GAAG,QAAQ;AAEtD,KAAG,aAAa,QAAQ,MAAM;AAC9B,KAAG,cAAc,MAAM;AAEvB,MAAI,CAAC,GAAG,mBAAmB,QAAQ,GAAG,cAAc,GAAG;AACrD,UAAM,QAAQ,IAAI;AAAA,MAChB,SAAS,GAAG,gBAAgB,WAAW;AAAA,MACvC,GAAG,iBAAiB,MAAM;AAAA,MAC1B,GAAG,SAAS;AAAA,IACd;AACA,OAAG,aAAa,MAAM;AACtB,UAAM;AAAA,EACR;AAEA,SAAO;AACT;AAQO,SAAS,cACd,IACA,cACA,gBACA,EAAE,OAAO,IAAiB,CAAC,GACb;AACd,QAAM,UAAU,QAAQ,GAAG,cAAc,GAAG,SAAS;AAErD,QAAM,eAAe,aAAa,IAAI,GAAG,eAAe,YAAY;AACpE,QAAM,iBAAiB,aAAa,IAAI,GAAG,iBAAiB,cAAc;AAE1E,KAAG,aAAa,SAAS,YAAY;AACrC,KAAG,aAAa,SAAS,cAAc;AACvC,KAAG,YAAY,OAAO;AAEtB,MAAI,CAAC,GAAG,oBAAoB,SAAS,GAAG,WAAW,GAAG;AACpD,UAAM,QAAQ,IAAI,iBAAiB,GAAG,kBAAkB,OAAO,GAAG,GAAG,SAAS,CAAC;AAC/E,OAAG,cAAc,OAAO;AACxB,OAAG,aAAa,YAAY;AAC5B,OAAG,aAAa,cAAc;AAC9B,UAAM;AAAA,EACR;AAGA,KAAG,aAAa,YAAY;AAC5B,KAAG,aAAa,cAAc;AAE9B,UAAQ;AAAA,IACN;AAAA,IACA,KAAK,MAAM,GAAG,cAAc,OAAO,CAAC;AAAA,EACtC;AAEA,SAAO;AACT;","names":[]}
|
package/dist/gl.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { G as GL, V as ViewOptions
|
|
1
|
+
import { G as GL, V as ViewOptions } from './types-Z2s1zsZz.mjs';
|
|
2
2
|
|
|
3
3
|
/**********************************************************************************/
|
|
4
4
|
/**********************************************************************************/
|
|
@@ -6,7 +6,5 @@ declare function createShader(gl: GL, type: number, source: string): WebGLShader
|
|
|
6
6
|
/**********************************************************************************/
|
|
7
7
|
/**********************************************************************************/
|
|
8
8
|
declare function createProgram(gl: GL, vertexSource: string, fragmentSource: string, { signal }?: ViewOptions): WebGLProgram;
|
|
9
|
-
declare function getInstancedArrays(gl: GL): RemoveSuffix<Pick<ANGLE_instanced_arrays, "drawArraysInstancedANGLE" | "drawElementsInstancedANGLE" | "vertexAttribDivisorANGLE">, "ANGLE"> | undefined;
|
|
10
|
-
declare function getVertexArrayObject(gl: GL): RemoveSuffix<Pick<OES_vertex_array_object, "bindVertexArrayOES" | "createVertexArrayOES" | "deleteVertexArrayOES">, "OES"> | null;
|
|
11
9
|
|
|
12
|
-
export { createProgram, createShader
|
|
10
|
+
export { createProgram, createShader };
|
package/dist/gl.mjs
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createProgram,
|
|
3
|
-
createShader
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} from "./chunk-TQWPUDQI.mjs";
|
|
3
|
+
createShader
|
|
4
|
+
} from "./chunk-UVDTF5P3.mjs";
|
|
5
|
+
import "./chunk-IAM2SWJK.mjs";
|
|
7
6
|
export {
|
|
8
7
|
createProgram,
|
|
9
|
-
createShader
|
|
10
|
-
getInstancedArrays,
|
|
11
|
-
getVertexArrayObject
|
|
8
|
+
createShader
|
|
12
9
|
};
|
|
13
10
|
//# sourceMappingURL=gl.mjs.map
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { G as GL, F as FramebufferDefinition, V as ViewOptions, T as TextureDefinition, a as ViewSchema, b as View, c as VertexArrayParticipant, d as VertexArrayMethods, U as UniformSchema, e as UniformView, A as AttributeSchema, f as AttributeView, I as InterleavedAttributeSchema, g as InterleavedAttributeView, B as BufferSchema, h as BufferView } from './types-
|
|
2
|
-
export {
|
|
1
|
+
import { G as GL, F as FramebufferDefinition, V as ViewOptions, T as TextureDefinition, a as ViewSchema, b as View, c as VertexArrayParticipant, d as VertexArrayMethods, U as UniformSchema, e as UniformView, A as AttributeSchema, f as AttributeView, I as InterleavedAttributeSchema, g as InterleavedAttributeView, B as BufferSchema, h as BufferView } from './types-Z2s1zsZz.mjs';
|
|
2
|
+
export { H as AttributeDefinition, E as AttributeFormat, D as AttributeKind, J as AttributeMethods, C as AttributeShortHand, ad as AttributeToken, ae as AttributeTokenFn, R as BufferDefinition, W as BufferMethods, N as BufferSource, al as CompileResult, O as ConstantAttributeMethods, P as ConstantSource, aj as FlattenSlots, a4 as Format, X as Framebuffer, aa as GLSL, a8 as GLSLResult, a9 as GLSLSlot, ai as GLSLSlotsToSchema, ag as GLSLToSchema, ah as GLSLToView, k as GLTarget, p as GLTextureFilter, n as GLTextureFormat, m as GLTextureTarget, o as GLTextureType, q as GLTextureWrap, l as GLUsage, i as Instancing, af as InterleaveToken, M as InterleavedAttributeDefinition, L as InterleavedAttributeLayout, Q as InterleavedAttributeMethods, a3 as InternalFormat, r as KIND_TO_SIZE_MAP, K as KIND_TO_UNIFORM_FN_NAME_MAP, ak as MergeGLSLSchema, a5 as PixelType, S as Source, a6 as TexImage2DOptions, _ as TextureMethods, a0 as TextureParameterName, a1 as TextureParameterValue, a2 as TextureParameters, Z as TextureSchema, Y as TextureTarget, $ as TextureView, x as UniformArrayMethods, v as UniformDefinition, w as UniformElementMethods, s as UniformFnName, t as UniformKind, u as UniformKindMap, y as UniformMethods, ab as UniformToken, ac as UniformTokenFn, z as UniformValue, j as VertexArrays, a7 as ViewSchemaPartial } from './types-Z2s1zsZz.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* A shader that did not compile. `infoLog` is what the driver answered, `null`
|
|
@@ -35,6 +35,12 @@ declare class AttributeNotFoundError extends Error {
|
|
|
35
35
|
name: string;
|
|
36
36
|
constructor(attribute: string);
|
|
37
37
|
}
|
|
38
|
+
/** A divisor of 1 asked of a context without `vertexAttribDivisor`: the draw cannot instance. */
|
|
39
|
+
declare class InstancingUnavailableError extends Error {
|
|
40
|
+
readonly attribute: string;
|
|
41
|
+
name: string;
|
|
42
|
+
constructor(attribute: string);
|
|
43
|
+
}
|
|
38
44
|
/** Throws a {@link GLCreateError} for a `create*` that answered `null`. */
|
|
39
45
|
declare function created<T>(value: T | null, resource: GLResource): T;
|
|
40
46
|
|
|
@@ -70,4 +76,4 @@ declare function interleavedAttributeView<T extends InterleavedAttributeSchema>(
|
|
|
70
76
|
/**********************************************************************************/
|
|
71
77
|
declare function bufferView<T extends BufferSchema>(gl: GL, schema: T, { signal }?: ViewOptions): BufferView<T>;
|
|
72
78
|
|
|
73
|
-
export { AttributeNotFoundError, AttributeSchema, AttributeView, BufferSchema, BufferView, FramebufferDefinition, GL, GLCreateError, type GLResource, InterleavedAttributeSchema, InterleavedAttributeView, ProgramLinkError, ShaderCompileError, TextureDefinition, UniformSchema, UniformView, VertexArrayMethods, VertexArrayParticipant, View, ViewOptions, ViewSchema, attributeView, bufferView, createFramebuffer, createTexture, created, interleavedAttributeView, toID, uniformView, vaoView, view };
|
|
79
|
+
export { AttributeNotFoundError, AttributeSchema, AttributeView, BufferSchema, BufferView, FramebufferDefinition, GL, GLCreateError, type GLResource, InstancingUnavailableError, InterleavedAttributeSchema, InterleavedAttributeView, ProgramLinkError, ShaderCompileError, TextureDefinition, UniformSchema, UniformView, VertexArrayMethods, VertexArrayParticipant, View, ViewOptions, ViewSchema, attributeView, bufferView, createFramebuffer, createTexture, created, interleavedAttributeView, toID, uniformView, vaoView, view };
|