@bigmistqke/view.gl 0.8.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/{chunk-7Z5UULAB.mjs → chunk-6UTWQ36A.mjs} +2 -2
- package/dist/chunk-6UTWQ36A.mjs.map +1 -0
- package/dist/{chunk-TQWPUDQI.mjs → chunk-BDNRC4WD.mjs} +3 -13
- package/dist/{chunk-TQWPUDQI.mjs.map → chunk-BDNRC4WD.mjs.map} +1 -1
- package/dist/gl.d.mts +17 -3
- package/dist/gl.mjs +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/tag.d.mts +1 -1
- package/dist/tag.mjs +4 -7
- package/dist/tag.mjs.map +1 -1
- package/dist/{types-DZbMcty2.d.mts → types-Cy9u5YKs.d.mts} +4 -8
- package/package.json +15 -17
- package/src/gl.ts +4 -35
- package/src/index.ts +1 -2
- package/src/tag.ts +3 -6
- package/src/types.ts +3 -4
- package/test/index.test.ts +78 -0
- package/test/tag.test.ts +34 -10
- package/dist/chunk-7Z5UULAB.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -125,8 +125,8 @@ is a label for the reader. What putting it in the schema decides is its
|
|
|
125
125
|
| belongs to somebody else | name it on an attribute | nobody — it is borrowed |
|
|
126
126
|
|
|
127
127
|
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
|
-
|
|
128
|
+
the attributes it is drawn with, on the one signal. A buffer handed from one
|
|
129
|
+
program's view to another's is its own thing.
|
|
130
130
|
|
|
131
131
|
<details>
|
|
132
132
|
<summary>TypeScript Types</summary>
|
|
@@ -922,7 +922,7 @@ Every error view.gl throws for a GL call that failed is a class exported from `@
|
|
|
922
922
|
| `GLCreateError` | a `create*` call answers `null` | `resource`: `'shader'`, `'program'`, `'buffer'`, `'vertexArray'`, `'texture'` or `'framebuffer'` |
|
|
923
923
|
| `AttributeNotFoundError` | `getAttribLocation` answers -1 | `attribute` |
|
|
924
924
|
|
|
925
|
-
A lost WebGL context answers
|
|
925
|
+
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
926
|
|
|
927
927
|
```typescript
|
|
928
928
|
import { createProgram } from '@bigmistqke/view.gl/gl'
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
kindToUniformFnName,
|
|
13
13
|
mapObject,
|
|
14
14
|
once
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-BDNRC4WD.mjs";
|
|
16
16
|
|
|
17
17
|
// src/index.ts
|
|
18
18
|
var index = 0;
|
|
@@ -463,4 +463,4 @@ export {
|
|
|
463
463
|
interleavedAttributeView,
|
|
464
464
|
bufferView
|
|
465
465
|
};
|
|
466
|
-
//# sourceMappingURL=chunk-
|
|
466
|
+
//# sourceMappingURL=chunk-6UTWQ36A.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { AttributeNotFoundError, created } from './errors'\nimport { getInstancedArrays, getVertexArrayObject } from './gl'\nimport type {\n AttributeFormat,\n AttributeKind,\n AttributeMethods,\n AttributeSchema,\n AttributeView,\n BufferSchema,\n BufferView,\n GL,\n UniformView as InferUniformView,\n GLUsage,\n InterleavedAttributeLayout,\n InterleavedAttributeMethods,\n InterleavedAttributeSchema,\n InterleavedAttributeView,\n UniformSchema,\n VertexArrayMethods,\n VertexArrayParticipant,\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 const feature = getVertexArrayObject(gl)\n if (!feature) {\n return () => {}\n }\n const previous = readVertexArrayBinding(gl)\n feature.bindVertexArray(null)\n return () => feature.bindVertexArray(previous)\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 = getVertexArrayObject(gl)\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(gl)\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(gl)\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,\n) {\n gl.enableVertexAttribArray(location)\n if (isIntegerKind) {\n ;(gl as WebGL2RenderingContext).vertexAttribIPointer(location, size, gl[glType], stride, offset)\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 // Get instanced-arrays-feature: extension if webgl, gl if webgl2\n const instancedArrays = getInstancedArrays(gl)\n if (instanced) {\n assertedNotNullish(instancedArrays).vertexAttribDivisor(location, 1)\n } else if (instancedArrays) {\n instancedArrays.vertexAttribDivisor(location, 0)\n }\n}\n\n// Same enum in webgl2 and in the webgl1 extensions, which expose no constants\nconst VERTEX_ATTRIB_ARRAY_DIVISOR = 0x88fe\nconst VERTEX_ARRAY_BINDING = 0x85b5\n\n// Anything but an array or null would make the restore throw a TypeError.\nfunction readVertexArrayBinding(gl: GL): WebGLVertexArrayObject | null {\n const bound: unknown = gl.getParameter(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 getInstancedArrays(gl)\n ? (gl.getVertexAttrib(location, 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)\n return once(() => {\n getInstancedArrays(gl)?.vertexAttribDivisor(location, previousDivisor)\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 )\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 const instancedArrays = getInstancedArrays(gl)\n previousDivisors.forEach(([location, previous]) => {\n instancedArrays?.vertexAttribDivisor(location, previous)\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"]}
|
|
@@ -266,35 +266,25 @@ function createProgram(gl, vertexSource, fragmentSource, { signal } = {}) {
|
|
|
266
266
|
);
|
|
267
267
|
return program;
|
|
268
268
|
}
|
|
269
|
-
var INSTANCED_ARRAYS_WRAPPER_MAP = /* @__PURE__ */ new WeakMap();
|
|
270
269
|
function getInstancedArrays(gl) {
|
|
271
270
|
if (isWebGL2RenderingContext(gl)) return gl;
|
|
272
|
-
const cached = INSTANCED_ARRAYS_WRAPPER_MAP.get(gl);
|
|
273
|
-
if (cached) return cached;
|
|
274
271
|
const ext = gl.getExtension("ANGLE_instanced_arrays");
|
|
275
272
|
if (!ext) return void 0;
|
|
276
|
-
|
|
273
|
+
return {
|
|
277
274
|
drawArraysInstanced: ext.drawArraysInstancedANGLE.bind(ext),
|
|
278
275
|
drawElementsInstanced: ext.drawElementsInstancedANGLE.bind(ext),
|
|
279
276
|
vertexAttribDivisor: ext.vertexAttribDivisorANGLE.bind(ext)
|
|
280
277
|
};
|
|
281
|
-
INSTANCED_ARRAYS_WRAPPER_MAP.set(gl, wrapper);
|
|
282
|
-
return wrapper;
|
|
283
278
|
}
|
|
284
|
-
var VERTEX_ARRAY_OBJECT_WRAPPER_MAP = /* @__PURE__ */ new WeakMap();
|
|
285
279
|
function getVertexArrayObject(gl) {
|
|
286
280
|
if (isWebGL2RenderingContext(gl)) return gl;
|
|
287
|
-
const cached = VERTEX_ARRAY_OBJECT_WRAPPER_MAP.get(gl);
|
|
288
|
-
if (cached) return cached;
|
|
289
281
|
const ext = gl.getExtension("OES_vertex_array_object");
|
|
290
282
|
if (!ext) return null;
|
|
291
|
-
|
|
283
|
+
return {
|
|
292
284
|
bindVertexArray: ext.bindVertexArrayOES.bind(ext),
|
|
293
285
|
createVertexArray: ext.createVertexArrayOES.bind(ext),
|
|
294
286
|
deleteVertexArray: ext.deleteVertexArrayOES.bind(ext)
|
|
295
287
|
};
|
|
296
|
-
VERTEX_ARRAY_OBJECT_WRAPPER_MAP.set(gl, wrapper);
|
|
297
|
-
return wrapper;
|
|
298
288
|
}
|
|
299
289
|
|
|
300
290
|
export {
|
|
@@ -319,4 +309,4 @@ export {
|
|
|
319
309
|
getInstancedArrays,
|
|
320
310
|
getVertexArrayObject
|
|
321
311
|
};
|
|
322
|
-
//# sourceMappingURL=chunk-
|
|
312
|
+
//# sourceMappingURL=chunk-BDNRC4WD.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/utils.ts","../src/gl.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/** 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","import { RemoveSuffix } from './type-utils'\nimport type { GL, ViewOptions } from './types'\nimport { created, ProgramLinkError, ShaderCompileError } from './errors'\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 = 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\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
|
+
{"version":3,"sources":["../src/errors.ts","../src/utils.ts","../src/gl.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/** 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","import type { GL, ViewOptions } from './types'\nimport { created, ProgramLinkError, ShaderCompileError } from './errors'\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 = 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\n/**********************************************************************************/\n/* */\n/* Get Instanced Arrays */\n/* */\n/**********************************************************************************/\n\n/** Instancing on `gl`: the context on WebGL2, `ANGLE_instanced_arrays` on WebGL1, else `undefined`. */\nexport function getInstancedArrays(gl: GL) {\n if (isWebGL2RenderingContext(gl)) return gl\n\n const ext = gl.getExtension('ANGLE_instanced_arrays')\n if (!ext) return undefined\n\n return {\n drawArraysInstanced: ext.drawArraysInstancedANGLE.bind(ext),\n drawElementsInstanced: ext.drawElementsInstancedANGLE.bind(ext),\n vertexAttribDivisor: ext.vertexAttribDivisorANGLE.bind(ext),\n }\n}\n\n/**********************************************************************************/\n/* */\n/* Get Vertex Array Object */\n/* */\n/**********************************************************************************/\n\n/** Vertex arrays on `gl`: the context on WebGL2, `OES_vertex_array_object` on WebGL1, else `null`. */\nexport function getVertexArrayObject(gl: GL) {\n if (isWebGL2RenderingContext(gl)) return gl\n\n const ext = gl.getExtension('OES_vertex_array_object')\n if (!ext) return null\n\n return {\n bindVertexArray: ext.bindVertexArrayOES.bind(ext),\n createVertexArray: ext.createVertexArrayOES.bind(ext),\n deleteVertexArray: ext.deleteVertexArrayOES.bind(ext),\n }\n}\n"],"mappings":"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","names":["value"]}
|
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-Cy9u5YKs.mjs';
|
|
2
2
|
|
|
3
3
|
/**********************************************************************************/
|
|
4
4
|
/**********************************************************************************/
|
|
@@ -6,7 +6,21 @@ 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
|
-
|
|
10
|
-
|
|
9
|
+
/**********************************************************************************/
|
|
10
|
+
/**********************************************************************************/
|
|
11
|
+
/** Instancing on `gl`: the context on WebGL2, `ANGLE_instanced_arrays` on WebGL1, else `undefined`. */
|
|
12
|
+
declare function getInstancedArrays(gl: GL): WebGL2RenderingContext | {
|
|
13
|
+
drawArraysInstanced: (mode: GLenum, first: GLint, count: GLsizei, primcount: GLsizei) => void;
|
|
14
|
+
drawElementsInstanced: (mode: GLenum, count: GLsizei, type: GLenum, offset: GLintptr, primcount: GLsizei) => void;
|
|
15
|
+
vertexAttribDivisor: (index: GLuint, divisor: GLuint) => void;
|
|
16
|
+
} | undefined;
|
|
17
|
+
/**********************************************************************************/
|
|
18
|
+
/**********************************************************************************/
|
|
19
|
+
/** Vertex arrays on `gl`: the context on WebGL2, `OES_vertex_array_object` on WebGL1, else `null`. */
|
|
20
|
+
declare function getVertexArrayObject(gl: GL): WebGL2RenderingContext | {
|
|
21
|
+
bindVertexArray: (arrayObject: WebGLVertexArrayObjectOES | null) => void;
|
|
22
|
+
createVertexArray: () => WebGLVertexArrayObjectOES;
|
|
23
|
+
deleteVertexArray: (arrayObject: WebGLVertexArrayObjectOES | null) => void;
|
|
24
|
+
} | null;
|
|
11
25
|
|
|
12
26
|
export { createProgram, createShader, getInstancedArrays, getVertexArrayObject };
|
package/dist/gl.mjs
CHANGED
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 { D as AttributeDefinition, C as AttributeFormat, z as AttributeKind, E as AttributeMethods, y as AttributeShortHand,
|
|
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-Cy9u5YKs.mjs';
|
|
2
|
+
export { D as AttributeDefinition, C as AttributeFormat, z as AttributeKind, E as AttributeMethods, y as AttributeShortHand, ab as AttributeToken, ac as AttributeTokenFn, P as BufferDefinition, Q as BufferMethods, L as BufferSource, aj as CompileResult, M as ConstantAttributeMethods, N as ConstantSource, ah as FlattenSlots, a2 as Format, R as Framebuffer, a8 as GLSL, a6 as GLSLResult, a7 as GLSLSlot, ag as GLSLSlotsToSchema, ae as GLSLToSchema, af as GLSLToView, i as GLTarget, n as GLTextureFilter, l as GLTextureFormat, k as GLTextureTarget, m as GLTextureType, o as GLTextureWrap, j as GLUsage, ad as InterleaveToken, J as InterleavedAttributeDefinition, H as InterleavedAttributeLayout, O as InterleavedAttributeMethods, a1 as InternalFormat, p as KIND_TO_SIZE_MAP, K as KIND_TO_UNIFORM_FN_NAME_MAP, ai as MergeGLSLSchema, a3 as PixelType, S as Source, a4 as TexImage2DOptions, Y as TextureMethods, _ as TextureParameterName, $ as TextureParameterValue, a0 as TextureParameters, X as TextureSchema, W as TextureTarget, Z as TextureView, v as UniformArrayMethods, t as UniformDefinition, u as UniformElementMethods, q as UniformFnName, r as UniformKind, s as UniformKindMap, w as UniformMethods, a9 as UniformToken, aa as UniformTokenFn, x as UniformValue, a5 as ViewSchemaPartial } from './types-Cy9u5YKs.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* A shader that did not compile. `infoLog` is what the driver answered, `null`
|
package/dist/index.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
uniformView,
|
|
7
7
|
vaoView,
|
|
8
8
|
view
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-6UTWQ36A.mjs";
|
|
10
10
|
import {
|
|
11
11
|
AttributeNotFoundError,
|
|
12
12
|
GLCreateError,
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
createFramebuffer,
|
|
16
16
|
createTexture,
|
|
17
17
|
created
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-BDNRC4WD.mjs";
|
|
19
19
|
export {
|
|
20
20
|
AttributeNotFoundError,
|
|
21
21
|
GLCreateError,
|
package/dist/tag.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a7 as GLSLSlot, a8 as GLSL, aa as UniformTokenFn, ac as AttributeTokenFn, ab as AttributeToken, z as AttributeKind, D as AttributeDefinition, ad as InterleaveToken, a5 as ViewSchemaPartial, aj as CompileResult, ak as Prettify, ae as GLSLToSchema, G as GL } from './types-Cy9u5YKs.mjs';
|
|
2
2
|
|
|
3
3
|
declare function glsl<TSlot extends GLSLSlot, const TSlots extends TSlot[]>(template: TemplateStringsArray, ...slots: [...TSlots]): GLSL<TSlots>;
|
|
4
4
|
declare const uniform: {
|
package/dist/tag.mjs
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
toID,
|
|
3
3
|
view
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-6UTWQ36A.mjs";
|
|
5
5
|
import {
|
|
6
6
|
createProgram,
|
|
7
|
-
createUpsertMap,
|
|
8
7
|
once
|
|
9
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-BDNRC4WD.mjs";
|
|
10
9
|
|
|
11
10
|
// src/tag.ts
|
|
12
11
|
function glsl(template, ...slots) {
|
|
@@ -185,14 +184,12 @@ function resolveGlslSlotToString(slot, v300) {
|
|
|
185
184
|
throw new Error(`Unexpected slot: ${JSON.stringify(slot)}`);
|
|
186
185
|
}
|
|
187
186
|
var QUAD_FLOAT_ARRAY = new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]);
|
|
188
|
-
var QUAD_BUFFER_MAP = createUpsertMap(WeakMap);
|
|
189
187
|
compile.toQuad = function(gl, fragment, options) {
|
|
190
|
-
const buffer = QUAD_BUFFER_MAP.getOrInsert(gl, gl.createBuffer.bind(gl));
|
|
191
188
|
const webgl2 = options?.webgl2 ?? fragment.template[0]?.startsWith("#version 300 es");
|
|
192
189
|
const vertex = webgl2 ? glsl`#version 300 es
|
|
193
190
|
precision mediump float;
|
|
194
191
|
|
|
195
|
-
${attribute.vec2("a_quad"
|
|
192
|
+
${attribute.vec2("a_quad")}
|
|
196
193
|
|
|
197
194
|
out vec2 v_uv;
|
|
198
195
|
|
|
@@ -201,7 +198,7 @@ void main() {
|
|
|
201
198
|
gl_Position = vec4(v_uv, 0.0, 1.0);
|
|
202
199
|
}` : glsl`precision mediump float;
|
|
203
200
|
|
|
204
|
-
${attribute.vec2("a_quad"
|
|
201
|
+
${attribute.vec2("a_quad")}
|
|
205
202
|
|
|
206
203
|
varying vec2 v_uv;
|
|
207
204
|
|
package/dist/tag.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/tag.ts"],"sourcesContent":["import { toID, view } from '.'\nimport { createProgram } from './gl'\nimport type { Prettify } from './type-utils'\nimport type {\n AttributeDefinition,\n AttributeKind,\n AttributeTokenFn as AttributeTagMethod,\n AttributeToken,\n CompileResult,\n GL,\n GLSL,\n GLSLSlot,\n GLSLToSchema,\n InterleaveToken,\n UniformDefinition,\n UniformKind,\n UniformTokenFn as UniformTagMethod,\n ViewSchema,\n ViewSchemaPartial,\n} from './types'\nimport { createUpsertMap, once } from './utils'\n\nexport function glsl<TSlot extends GLSLSlot, const TSlots extends TSlot[]>(\n template: TemplateStringsArray,\n ...slots: [...TSlots]\n): GLSL<TSlots> {\n return { template, slots, type: 'glsl' }\n}\n\nexport const uniform = new Proxy(\n {} as {\n [TKey in UniformKind]: UniformTagMethod<TKey>\n },\n {\n get(target, property) {\n // @ts-expect-error\n if (typeof property === 'symbol') return target[property]\n return (key: string, options?: Omit<UniformDefinition, 'kind'>) => ({\n type: 'uniform',\n key,\n kind: property,\n ...options,\n })\n },\n },\n)\n\nexport const attribute = new Proxy(\n {} as {\n [TKey in AttributeKind]: AttributeTagMethod<TKey>\n },\n {\n get(target, property) {\n // @ts-expect-error\n if (typeof property === 'symbol') return target[property]\n return (key: string, options?: Omit<AttributeDefinition, 'kind'>) => ({\n type: 'attribute',\n key,\n kind: property,\n ...options,\n })\n },\n },\n)\n\nexport function interleave<\n const TKey extends string | symbol,\n const TLayout extends Array<AttributeToken<string | symbol, AttributeKind, undefined>>,\n const TOptions extends Omit<AttributeDefinition, 'kind'>,\n>(key: TKey, layout: TLayout, instanced: TOptions): InterleaveToken<TKey, TLayout, TOptions>\nexport function interleave<\n const TKey extends string | symbol,\n const TLayout extends Array<AttributeToken<string | symbol, AttributeKind, undefined>>,\n>(key: TKey, layout: TLayout): InterleaveToken<TKey, TLayout, { instanced: false }>\nexport function interleave<\n const TKey extends string | symbol,\n const TLayout extends Array<AttributeToken<string | symbol, AttributeKind, undefined>>,\n const TOptions extends Omit<AttributeDefinition, 'kind'>,\n>(key: TKey, layout: TLayout, { instanced, buffer }: Partial<TOptions> = {}) {\n return {\n type: 'interleavedAttribute',\n key,\n // remove instanced- and type-property\n layout: layout.map(({ key, kind }) => ({\n key,\n kind,\n })),\n instanced: !!instanced,\n buffer,\n } as unknown as InterleaveToken<TKey, TLayout, TOptions>\n}\n\n/**********************************************************************************/\n/* */\n/* Compile */\n/* */\n/**********************************************************************************/\n\nexport interface CompileOptions<TSchema extends ViewSchemaPartial> {\n schema?: TSchema\n webgl2?: boolean\n /**\n * Disposes what `compile` made: the program, and the buffers the view created\n * for itself. Buffers named by the schema belong to whoever made them.\n */\n signal?: AbortSignal\n}\n\nexport function compile<\n TVertex extends GLSL,\n TFragment extends GLSL,\n TSchema extends ViewSchemaPartial,\n>(\n gl: WebGLRenderingContext,\n vertex: TVertex,\n fragment: TFragment,\n options?: CompileOptions<TSchema> | undefined,\n) {\n const _vertex = resolveGLSLTag(vertex, options) as { template: string; schema: ViewSchema }\n const _fragment = resolveGLSLTag(fragment, options) as { template: string; schema: ViewSchema }\n\n const schema = {\n uniforms: {\n ..._vertex.schema.uniforms,\n ..._fragment.schema.uniforms,\n },\n attributes: {\n ..._vertex.schema.attributes,\n ..._fragment.schema.attributes,\n },\n interleavedAttributes: {\n ..._vertex.schema.interleavedAttributes,\n ..._fragment.schema.interleavedAttributes,\n },\n // Never produced by a tag — a buffer has no name in the source to be\n // parsed out of one — but `options.schema` may name buffers for the view to\n // own, and the deep merge below indexes this object by every key it finds\n // there. Missing, that threw.\n buffers: {} as NonNullable<ViewSchema['buffers']>,\n }\n\n // Deep merge options.schema with generated schema\n for (const kind in options?.schema) {\n const schemaKind = schema[kind as keyof typeof schema]\n const configSchemaKind = options?.schema[kind]\n\n for (const key in configSchemaKind) {\n schemaKind[key] = {\n ...schemaKind[key],\n ...configSchemaKind[key],\n }\n }\n }\n\n try {\n const program = createProgram(gl, _vertex.template, _fragment.template)\n\n // The same rule the views follow: `compile` made this program, so `compile`\n // is what deletes it. A program handed in from outside would not be ours to\n // delete, and there is no way to hand one in.\n const resolvedView = view(gl, program, schema)\n const dispose = once(() => {\n resolvedView.dispose()\n gl.deleteProgram(program)\n })\n options?.signal?.addEventListener('abort', dispose)\n\n return {\n program,\n schema,\n view: resolvedView,\n dispose,\n vertex: _vertex.template,\n fragment: _fragment.template,\n } as unknown as Prettify<CompileResult<TVertex, TFragment, TSchema>>\n } catch (error) {\n console.error('Error while creating WebGLProgram - vertex\\n\\n', _vertex.template)\n console.error('Error while creating WebGLProgram - fragment\\n\\n', _fragment.template)\n\n throw error\n }\n}\n\nfunction resolveGLSLTag<TTag extends GLSL>(tag: TTag, options?: { webgl2?: boolean }) {\n return {\n template: compile.toString(tag, options),\n schema: compile.toSchema(tag),\n }\n}\n\ncompile.toSchema = function <TTag extends GLSL>(tag: TTag) {\n const result = {\n uniforms: {},\n attributes: {},\n interleavedAttributes: {},\n }\n\n tag.slots.forEach(function handleSlot(slot: GLSLSlot) {\n if (typeof slot !== 'object') {\n return\n }\n\n if (Array.isArray(slot)) {\n slot.forEach(handleSlot)\n return\n }\n\n if (slot.type === 'glsl') {\n const { uniforms, attributes, interleavedAttributes } = compile.toSchema(slot)\n\n result.uniforms = {\n ...result.uniforms,\n ...uniforms,\n }\n result.attributes = {\n ...result.attributes,\n ...attributes,\n }\n result.interleavedAttributes = {\n ...result.interleavedAttributes,\n ...interleavedAttributes,\n }\n\n return\n }\n\n const { key: name, type, ...rest } = slot\n\n // @ts-expect-error\n result[`${type}s`][name] = rest\n })\n\n return result as unknown as Prettify<GLSLToSchema<TTag>>\n}\n\ncompile.toString = function <TTag extends GLSL>(\n { template: [initial, ...rest], slots }: TTag,\n config?: { webgl2?: boolean },\n) {\n const v300 = config?.webgl2 ?? !!initial?.startsWith('#version 300 es')\n\n let template = initial ?? ''\n\n for (let i = 0; i < rest.length; i++) {\n template += `${resolveGlslSlotToString(slots[i]!, v300)}${rest[i]}`\n }\n\n return template\n}\n\nfunction resolveGlslSlotToString(slot: GLSLSlot, v300: boolean): string {\n if (typeof slot !== 'object') {\n return toID(slot)\n }\n\n if (Array.isArray(slot)) {\n return slot.map(slot => resolveGlslSlotToString(slot, v300)).join('')\n }\n\n switch (slot.type) {\n case 'glsl':\n return compile.toString(slot)\n case 'interleavedAttribute':\n return slot.layout.reduce(\n (a, v) =>\n v300 ? `${a}in ${v.kind} ${toID(v.key)};\\n` : `${a}attribute ${v.kind} ${toID(v.key)};\\n`,\n '',\n )\n case 'uniform':\n if ('size' in slot) {\n return `${slot.type} ${slot.kind} ${toID(slot.key)}[${slot.size}];`\n }\n return `${slot.type} ${slot.kind} ${toID(slot.key)};`\n }\n\n if (slot.type === 'attribute') {\n return `${v300 ? 'in' : slot.type} ${slot.kind} ${toID(slot.key)};`\n }\n\n throw new Error(`Unexpected slot: ${JSON.stringify(slot)}`)\n}\n\nconst QUAD_FLOAT_ARRAY = new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1])\nconst QUAD_BUFFER_MAP = createUpsertMap(WeakMap<GL, WebGLBuffer>)\n\ncompile.toQuad = function <TFragment extends GLSL, TSchema extends ViewSchemaPartial>(\n gl: GL,\n fragment: TFragment,\n options?: CompileOptions<TSchema>,\n) {\n const buffer = QUAD_BUFFER_MAP.getOrInsert(gl, gl.createBuffer.bind(gl))\n\n const webgl2 = options?.webgl2 ?? fragment.template[0]?.startsWith('#version 300 es')\n\n const vertex = webgl2\n ? glsl`#version 300 es\nprecision mediump float;\n\n${attribute.vec2('a_quad', { buffer })}\n\nout vec2 v_uv;\n\nvoid main() {\n v_uv = a_quad;\n gl_Position = vec4(v_uv, 0.0, 1.0);\n}`\n : glsl`precision mediump float;\n\n${attribute.vec2('a_quad', { buffer })}\n\nvarying vec2 v_uv;\n\nvoid main() {\n v_uv = a_quad;\n gl_Position = vec4(v_uv, 0.0, 1.0);\n}`\n\n const result = compile(gl, vertex, fragment, options)\n\n // @ts-expect-error\n result.view.attributes.a_quad.set(QUAD_FLOAT_ARRAY)\n\n return result\n}\n"],"mappings":"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","names":["key","slot"]}
|
|
1
|
+
{"version":3,"sources":["../src/tag.ts"],"sourcesContent":["import { toID, view } from '.'\nimport { createProgram } from './gl'\nimport type { Prettify } from './type-utils'\nimport type {\n AttributeDefinition,\n AttributeKind,\n AttributeTokenFn as AttributeTagMethod,\n AttributeToken,\n CompileResult,\n GL,\n GLSL,\n GLSLSlot,\n GLSLToSchema,\n InterleaveToken,\n UniformDefinition,\n UniformKind,\n UniformTokenFn as UniformTagMethod,\n ViewSchema,\n ViewSchemaPartial,\n} from './types'\nimport { once } from './utils'\n\nexport function glsl<TSlot extends GLSLSlot, const TSlots extends TSlot[]>(\n template: TemplateStringsArray,\n ...slots: [...TSlots]\n): GLSL<TSlots> {\n return { template, slots, type: 'glsl' }\n}\n\nexport const uniform = new Proxy(\n {} as {\n [TKey in UniformKind]: UniformTagMethod<TKey>\n },\n {\n get(target, property) {\n // @ts-expect-error\n if (typeof property === 'symbol') return target[property]\n return (key: string, options?: Omit<UniformDefinition, 'kind'>) => ({\n type: 'uniform',\n key,\n kind: property,\n ...options,\n })\n },\n },\n)\n\nexport const attribute = new Proxy(\n {} as {\n [TKey in AttributeKind]: AttributeTagMethod<TKey>\n },\n {\n get(target, property) {\n // @ts-expect-error\n if (typeof property === 'symbol') return target[property]\n return (key: string, options?: Omit<AttributeDefinition, 'kind'>) => ({\n type: 'attribute',\n key,\n kind: property,\n ...options,\n })\n },\n },\n)\n\nexport function interleave<\n const TKey extends string | symbol,\n const TLayout extends Array<AttributeToken<string | symbol, AttributeKind, undefined>>,\n const TOptions extends Omit<AttributeDefinition, 'kind'>,\n>(key: TKey, layout: TLayout, instanced: TOptions): InterleaveToken<TKey, TLayout, TOptions>\nexport function interleave<\n const TKey extends string | symbol,\n const TLayout extends Array<AttributeToken<string | symbol, AttributeKind, undefined>>,\n>(key: TKey, layout: TLayout): InterleaveToken<TKey, TLayout, { instanced: false }>\nexport function interleave<\n const TKey extends string | symbol,\n const TLayout extends Array<AttributeToken<string | symbol, AttributeKind, undefined>>,\n const TOptions extends Omit<AttributeDefinition, 'kind'>,\n>(key: TKey, layout: TLayout, { instanced, buffer }: Partial<TOptions> = {}) {\n return {\n type: 'interleavedAttribute',\n key,\n // remove instanced- and type-property\n layout: layout.map(({ key, kind }) => ({\n key,\n kind,\n })),\n instanced: !!instanced,\n buffer,\n } as unknown as InterleaveToken<TKey, TLayout, TOptions>\n}\n\n/**********************************************************************************/\n/* */\n/* Compile */\n/* */\n/**********************************************************************************/\n\nexport interface CompileOptions<TSchema extends ViewSchemaPartial> {\n schema?: TSchema\n webgl2?: boolean\n /**\n * Disposes what `compile` made: the program, and the buffers the view created\n * for itself. Buffers named by the schema belong to whoever made them.\n */\n signal?: AbortSignal\n}\n\nexport function compile<\n TVertex extends GLSL,\n TFragment extends GLSL,\n TSchema extends ViewSchemaPartial,\n>(\n gl: WebGLRenderingContext,\n vertex: TVertex,\n fragment: TFragment,\n options?: CompileOptions<TSchema> | undefined,\n) {\n const _vertex = resolveGLSLTag(vertex, options) as { template: string; schema: ViewSchema }\n const _fragment = resolveGLSLTag(fragment, options) as { template: string; schema: ViewSchema }\n\n const schema = {\n uniforms: {\n ..._vertex.schema.uniforms,\n ..._fragment.schema.uniforms,\n },\n attributes: {\n ..._vertex.schema.attributes,\n ..._fragment.schema.attributes,\n },\n interleavedAttributes: {\n ..._vertex.schema.interleavedAttributes,\n ..._fragment.schema.interleavedAttributes,\n },\n // Never produced by a tag — a buffer has no name in the source to be\n // parsed out of one — but `options.schema` may name buffers for the view to\n // own, and the deep merge below indexes this object by every key it finds\n // there. Missing, that threw.\n buffers: {} as NonNullable<ViewSchema['buffers']>,\n }\n\n // Deep merge options.schema with generated schema\n for (const kind in options?.schema) {\n const schemaKind = schema[kind as keyof typeof schema]\n const configSchemaKind = options?.schema[kind]\n\n for (const key in configSchemaKind) {\n schemaKind[key] = {\n ...schemaKind[key],\n ...configSchemaKind[key],\n }\n }\n }\n\n try {\n const program = createProgram(gl, _vertex.template, _fragment.template)\n\n // The same rule the views follow: `compile` made this program, so `compile`\n // is what deletes it. A program handed in from outside would not be ours to\n // delete, and there is no way to hand one in.\n const resolvedView = view(gl, program, schema)\n const dispose = once(() => {\n resolvedView.dispose()\n gl.deleteProgram(program)\n })\n options?.signal?.addEventListener('abort', dispose)\n\n return {\n program,\n schema,\n view: resolvedView,\n dispose,\n vertex: _vertex.template,\n fragment: _fragment.template,\n } as unknown as Prettify<CompileResult<TVertex, TFragment, TSchema>>\n } catch (error) {\n console.error('Error while creating WebGLProgram - vertex\\n\\n', _vertex.template)\n console.error('Error while creating WebGLProgram - fragment\\n\\n', _fragment.template)\n\n throw error\n }\n}\n\nfunction resolveGLSLTag<TTag extends GLSL>(tag: TTag, options?: { webgl2?: boolean }) {\n return {\n template: compile.toString(tag, options),\n schema: compile.toSchema(tag),\n }\n}\n\ncompile.toSchema = function <TTag extends GLSL>(tag: TTag) {\n const result = {\n uniforms: {},\n attributes: {},\n interleavedAttributes: {},\n }\n\n tag.slots.forEach(function handleSlot(slot: GLSLSlot) {\n if (typeof slot !== 'object') {\n return\n }\n\n if (Array.isArray(slot)) {\n slot.forEach(handleSlot)\n return\n }\n\n if (slot.type === 'glsl') {\n const { uniforms, attributes, interleavedAttributes } = compile.toSchema(slot)\n\n result.uniforms = {\n ...result.uniforms,\n ...uniforms,\n }\n result.attributes = {\n ...result.attributes,\n ...attributes,\n }\n result.interleavedAttributes = {\n ...result.interleavedAttributes,\n ...interleavedAttributes,\n }\n\n return\n }\n\n const { key: name, type, ...rest } = slot\n\n // @ts-expect-error\n result[`${type}s`][name] = rest\n })\n\n return result as unknown as Prettify<GLSLToSchema<TTag>>\n}\n\ncompile.toString = function <TTag extends GLSL>(\n { template: [initial, ...rest], slots }: TTag,\n config?: { webgl2?: boolean },\n) {\n const v300 = config?.webgl2 ?? !!initial?.startsWith('#version 300 es')\n\n let template = initial ?? ''\n\n for (let i = 0; i < rest.length; i++) {\n template += `${resolveGlslSlotToString(slots[i]!, v300)}${rest[i]}`\n }\n\n return template\n}\n\nfunction resolveGlslSlotToString(slot: GLSLSlot, v300: boolean): string {\n if (typeof slot !== 'object') {\n return toID(slot)\n }\n\n if (Array.isArray(slot)) {\n return slot.map(slot => resolveGlslSlotToString(slot, v300)).join('')\n }\n\n switch (slot.type) {\n case 'glsl':\n return compile.toString(slot)\n case 'interleavedAttribute':\n return slot.layout.reduce(\n (a, v) =>\n v300 ? `${a}in ${v.kind} ${toID(v.key)};\\n` : `${a}attribute ${v.kind} ${toID(v.key)};\\n`,\n '',\n )\n case 'uniform':\n if ('size' in slot) {\n return `${slot.type} ${slot.kind} ${toID(slot.key)}[${slot.size}];`\n }\n return `${slot.type} ${slot.kind} ${toID(slot.key)};`\n }\n\n if (slot.type === 'attribute') {\n return `${v300 ? 'in' : slot.type} ${slot.kind} ${toID(slot.key)};`\n }\n\n throw new Error(`Unexpected slot: ${JSON.stringify(slot)}`)\n}\n\nconst QUAD_FLOAT_ARRAY = new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1])\n\ncompile.toQuad = function <TFragment extends GLSL, TSchema extends ViewSchemaPartial>(\n gl: GL,\n fragment: TFragment,\n options?: CompileOptions<TSchema>,\n) {\n const webgl2 = options?.webgl2 ?? fragment.template[0]?.startsWith('#version 300 es')\n\n const vertex = webgl2\n ? glsl`#version 300 es\nprecision mediump float;\n\n${attribute.vec2('a_quad')}\n\nout vec2 v_uv;\n\nvoid main() {\n v_uv = a_quad;\n gl_Position = vec4(v_uv, 0.0, 1.0);\n}`\n : glsl`precision mediump float;\n\n${attribute.vec2('a_quad')}\n\nvarying vec2 v_uv;\n\nvoid main() {\n v_uv = a_quad;\n gl_Position = vec4(v_uv, 0.0, 1.0);\n}`\n\n const result = compile(gl, vertex, fragment, options)\n\n // @ts-expect-error\n result.view.attributes.a_quad.set(QUAD_FLOAT_ARRAY)\n\n return result\n}\n"],"mappings":"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","names":["key","slot"]}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
type Prettify<T> = {
|
|
2
2
|
[K in keyof T]: T[K];
|
|
3
3
|
} & {};
|
|
4
|
-
type RemoveSuffix<T, S extends string> = {
|
|
5
|
-
[K in keyof T as K extends `${infer Prefix}${S}` ? Prefix : K]: T[K];
|
|
6
|
-
};
|
|
7
4
|
type DeepMerge<A extends readonly [...any]> = A extends [infer L, ...infer R] ? DeepMergeTwo<L, DeepMerge<R>> : unknown;
|
|
8
5
|
type DeepMergeTwo<TBase, TOverride> = {
|
|
9
6
|
[K in keyof TBase | keyof TOverride]: K extends keyof TOverride ? K extends keyof TBase ? ShallowMerge<[TBase[K], TOverride[K]]> : TOverride[K] : K extends keyof TBase ? TBase[K] : never;
|
|
@@ -450,10 +447,9 @@ interface ViewOptions {
|
|
|
450
447
|
*
|
|
451
448
|
* The other two lifetimes have their own spellings, and neither is this one. A
|
|
452
449
|
* buffer that outlives the view, or is shared between views, is a standalone
|
|
453
|
-
* `bufferView` —
|
|
454
|
-
*
|
|
455
|
-
*
|
|
456
|
-
* it.
|
|
450
|
+
* `bufferView` — a buffer handed from one program's view to another's. A
|
|
451
|
+
* buffer that belongs to somebody else is NAMED by an attribute schema, and is
|
|
452
|
+
* borrowed: the view uses it and never deletes it.
|
|
457
453
|
*/
|
|
458
454
|
interface ViewSchema {
|
|
459
455
|
uniforms?: UniformSchema;
|
|
@@ -596,4 +592,4 @@ type CompileResult<TVertex extends GLSL, TFragment extends GLSL, TOverrideSchema
|
|
|
596
592
|
dispose(): void;
|
|
597
593
|
} : never;
|
|
598
594
|
|
|
599
|
-
export type {
|
|
595
|
+
export type { TextureParameterValue as $, AttributeSchema as A, BufferSchema as B, AttributeFormat as C, AttributeDefinition as D, AttributeMethods as E, FramebufferDefinition as F, GL as G, InterleavedAttributeLayout as H, InterleavedAttributeSchema as I, InterleavedAttributeDefinition as J, KIND_TO_UNIFORM_FN_NAME_MAP as K, BufferSource as L, ConstantAttributeMethods as M, ConstantSource as N, InterleavedAttributeMethods as O, BufferDefinition as P, BufferMethods as Q, Framebuffer as R, Source as S, TextureDefinition as T, UniformSchema as U, ViewOptions as V, TextureTarget as W, TextureSchema as X, TextureMethods as Y, TextureView as Z, TextureParameterName as _, ViewSchema as a, TextureParameters as a0, InternalFormat as a1, Format as a2, PixelType as a3, TexImage2DOptions as a4, ViewSchemaPartial as a5, GLSLResult as a6, GLSLSlot as a7, GLSL as a8, UniformToken as a9, UniformTokenFn as aa, AttributeToken as ab, AttributeTokenFn as ac, InterleaveToken as ad, GLSLToSchema as ae, GLSLToView as af, GLSLSlotsToSchema as ag, FlattenSlots as ah, MergeGLSLSchema as ai, CompileResult as aj, Prettify as ak, View as b, VertexArrayParticipant as c, VertexArrayMethods as d, UniformView as e, AttributeView as f, InterleavedAttributeView as g, BufferView as h, GLTarget as i, GLUsage as j, GLTextureTarget as k, GLTextureFormat as l, GLTextureType as m, GLTextureFilter as n, GLTextureWrap as o, KIND_TO_SIZE_MAP as p, UniformFnName as q, UniformKind as r, UniformKindMap as s, UniformDefinition as t, UniformElementMethods as u, UniformArrayMethods as v, UniformMethods as w, UniformValue as x, AttributeShortHand as y, AttributeKind as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bigmistqke/view.gl",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "👀 Utilities for managing WebGL resources.",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -16,26 +16,11 @@
|
|
|
16
16
|
"types": "./dist/gl.d.mts"
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
|
-
"scripts": {
|
|
20
|
-
"build": "tsup",
|
|
21
|
-
"bump": "bumpp",
|
|
22
|
-
"dev:build": "vite build dev",
|
|
23
|
-
"dev:preview": "vite preview dev",
|
|
24
|
-
"dev:watch": "concurrently \"pnpm dev:preview\" \"vite dev:build --watch\"",
|
|
25
|
-
"dev": "vite serve dev",
|
|
26
|
-
"format": "prettier -w \"src/**/*.{js,ts,json,css,tsx,jsx}\" \"dev/**/*.{js,ts,json,css,tsx,jsx}\"",
|
|
27
|
-
"lint:types": "tsc --noEmit",
|
|
28
|
-
"prepublishOnly": "pnpm test && pnpm build",
|
|
29
|
-
"test:coverage": "vitest run --coverage",
|
|
30
|
-
"test:ui": "vitest --ui",
|
|
31
|
-
"test": "vitest --run"
|
|
32
|
-
},
|
|
33
19
|
"keywords": [
|
|
34
20
|
"WebGL"
|
|
35
21
|
],
|
|
36
22
|
"author": "",
|
|
37
23
|
"license": "ISC",
|
|
38
|
-
"packageManager": "pnpm@10.5.1",
|
|
39
24
|
"devDependencies": {
|
|
40
25
|
"@vitest/ui": "^3.2.4",
|
|
41
26
|
"bumpp": "^10.4.0",
|
|
@@ -47,5 +32,18 @@
|
|
|
47
32
|
"vite": "^7.0.2",
|
|
48
33
|
"vite-tsconfig-paths": "^5.1.4",
|
|
49
34
|
"vitest": "^3.2.4"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsup",
|
|
38
|
+
"bump": "bumpp",
|
|
39
|
+
"dev:build": "vite build dev",
|
|
40
|
+
"dev:preview": "vite preview dev",
|
|
41
|
+
"dev:watch": "concurrently \"pnpm dev:preview\" \"vite dev:build --watch\"",
|
|
42
|
+
"dev": "vite serve dev",
|
|
43
|
+
"format": "prettier -w \"src/**/*.{js,ts,json,css,tsx,jsx}\" \"dev/**/*.{js,ts,json,css,tsx,jsx}\"",
|
|
44
|
+
"lint:types": "tsc --noEmit",
|
|
45
|
+
"test:coverage": "vitest run --coverage",
|
|
46
|
+
"test:ui": "vitest --ui",
|
|
47
|
+
"test": "vitest --run"
|
|
50
48
|
}
|
|
51
|
-
}
|
|
49
|
+
}
|
package/src/gl.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { RemoveSuffix } from './type-utils'
|
|
2
1
|
import type { GL, ViewOptions } from './types'
|
|
3
2
|
import { created, ProgramLinkError, ShaderCompileError } from './errors'
|
|
4
3
|
import { once } from './utils'
|
|
@@ -81,33 +80,18 @@ export function createProgram(
|
|
|
81
80
|
/* */
|
|
82
81
|
/**********************************************************************************/
|
|
83
82
|
|
|
84
|
-
|
|
85
|
-
GL,
|
|
86
|
-
RemoveSuffix<
|
|
87
|
-
Pick<
|
|
88
|
-
ANGLE_instanced_arrays,
|
|
89
|
-
'drawArraysInstancedANGLE' | 'drawElementsInstancedANGLE' | 'vertexAttribDivisorANGLE'
|
|
90
|
-
>,
|
|
91
|
-
'ANGLE'
|
|
92
|
-
> | null
|
|
93
|
-
>()
|
|
83
|
+
/** Instancing on `gl`: the context on WebGL2, `ANGLE_instanced_arrays` on WebGL1, else `undefined`. */
|
|
94
84
|
export function getInstancedArrays(gl: GL) {
|
|
95
85
|
if (isWebGL2RenderingContext(gl)) return gl
|
|
96
86
|
|
|
97
|
-
const cached = INSTANCED_ARRAYS_WRAPPER_MAP.get(gl)
|
|
98
|
-
if (cached) return cached
|
|
99
|
-
|
|
100
87
|
const ext = gl.getExtension('ANGLE_instanced_arrays')
|
|
101
88
|
if (!ext) return undefined
|
|
102
89
|
|
|
103
|
-
|
|
90
|
+
return {
|
|
104
91
|
drawArraysInstanced: ext.drawArraysInstancedANGLE.bind(ext),
|
|
105
92
|
drawElementsInstanced: ext.drawElementsInstancedANGLE.bind(ext),
|
|
106
93
|
vertexAttribDivisor: ext.vertexAttribDivisorANGLE.bind(ext),
|
|
107
94
|
}
|
|
108
|
-
INSTANCED_ARRAYS_WRAPPER_MAP.set(gl, wrapper)
|
|
109
|
-
|
|
110
|
-
return wrapper
|
|
111
95
|
}
|
|
112
96
|
|
|
113
97
|
/**********************************************************************************/
|
|
@@ -116,31 +100,16 @@ export function getInstancedArrays(gl: GL) {
|
|
|
116
100
|
/* */
|
|
117
101
|
/**********************************************************************************/
|
|
118
102
|
|
|
119
|
-
|
|
120
|
-
GL,
|
|
121
|
-
RemoveSuffix<
|
|
122
|
-
Pick<
|
|
123
|
-
OES_vertex_array_object,
|
|
124
|
-
'bindVertexArrayOES' | 'createVertexArrayOES' | 'deleteVertexArrayOES'
|
|
125
|
-
>,
|
|
126
|
-
'OES'
|
|
127
|
-
> | null
|
|
128
|
-
>()
|
|
103
|
+
/** Vertex arrays on `gl`: the context on WebGL2, `OES_vertex_array_object` on WebGL1, else `null`. */
|
|
129
104
|
export function getVertexArrayObject(gl: GL) {
|
|
130
105
|
if (isWebGL2RenderingContext(gl)) return gl
|
|
131
106
|
|
|
132
|
-
const cached = VERTEX_ARRAY_OBJECT_WRAPPER_MAP.get(gl)
|
|
133
|
-
if (cached) return cached
|
|
134
|
-
|
|
135
107
|
const ext = gl.getExtension('OES_vertex_array_object')
|
|
136
108
|
if (!ext) return null
|
|
137
109
|
|
|
138
|
-
|
|
110
|
+
return {
|
|
139
111
|
bindVertexArray: ext.bindVertexArrayOES.bind(ext),
|
|
140
112
|
createVertexArray: ext.createVertexArrayOES.bind(ext),
|
|
141
113
|
deleteVertexArray: ext.deleteVertexArrayOES.bind(ext),
|
|
142
114
|
}
|
|
143
|
-
VERTEX_ARRAY_OBJECT_WRAPPER_MAP.set(gl, wrapper)
|
|
144
|
-
|
|
145
|
-
return wrapper
|
|
146
115
|
}
|
package/src/index.ts
CHANGED
|
@@ -395,8 +395,7 @@ export function attributeView<T extends AttributeSchema>(
|
|
|
395
395
|
const name = toID(key)
|
|
396
396
|
|
|
397
397
|
// Whoever made the buffer deletes it. A schema can name a buffer that
|
|
398
|
-
// belongs to another view —
|
|
399
|
-
// program on a context, an attribute two programs step over — and
|
|
398
|
+
// belongs to another view — an attribute two programs step over — and
|
|
400
399
|
// deleting one of those would take it out from under its owner.
|
|
401
400
|
const buffer = providedBuffer ?? created(gl.createBuffer(), 'buffer')
|
|
402
401
|
|
package/src/tag.ts
CHANGED
|
@@ -18,7 +18,7 @@ import type {
|
|
|
18
18
|
ViewSchema,
|
|
19
19
|
ViewSchemaPartial,
|
|
20
20
|
} from './types'
|
|
21
|
-
import {
|
|
21
|
+
import { once } from './utils'
|
|
22
22
|
|
|
23
23
|
export function glsl<TSlot extends GLSLSlot, const TSlots extends TSlot[]>(
|
|
24
24
|
template: TemplateStringsArray,
|
|
@@ -281,22 +281,19 @@ function resolveGlslSlotToString(slot: GLSLSlot, v300: boolean): string {
|
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
const QUAD_FLOAT_ARRAY = new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1])
|
|
284
|
-
const QUAD_BUFFER_MAP = createUpsertMap(WeakMap<GL, WebGLBuffer>)
|
|
285
284
|
|
|
286
285
|
compile.toQuad = function <TFragment extends GLSL, TSchema extends ViewSchemaPartial>(
|
|
287
286
|
gl: GL,
|
|
288
287
|
fragment: TFragment,
|
|
289
288
|
options?: CompileOptions<TSchema>,
|
|
290
289
|
) {
|
|
291
|
-
const buffer = QUAD_BUFFER_MAP.getOrInsert(gl, gl.createBuffer.bind(gl))
|
|
292
|
-
|
|
293
290
|
const webgl2 = options?.webgl2 ?? fragment.template[0]?.startsWith('#version 300 es')
|
|
294
291
|
|
|
295
292
|
const vertex = webgl2
|
|
296
293
|
? glsl`#version 300 es
|
|
297
294
|
precision mediump float;
|
|
298
295
|
|
|
299
|
-
${attribute.vec2('a_quad'
|
|
296
|
+
${attribute.vec2('a_quad')}
|
|
300
297
|
|
|
301
298
|
out vec2 v_uv;
|
|
302
299
|
|
|
@@ -306,7 +303,7 @@ void main() {
|
|
|
306
303
|
}`
|
|
307
304
|
: glsl`precision mediump float;
|
|
308
305
|
|
|
309
|
-
${attribute.vec2('a_quad'
|
|
306
|
+
${attribute.vec2('a_quad')}
|
|
310
307
|
|
|
311
308
|
varying vec2 v_uv;
|
|
312
309
|
|
package/src/types.ts
CHANGED
|
@@ -670,10 +670,9 @@ export interface ViewOptions {
|
|
|
670
670
|
*
|
|
671
671
|
* The other two lifetimes have their own spellings, and neither is this one. A
|
|
672
672
|
* buffer that outlives the view, or is shared between views, is a standalone
|
|
673
|
-
* `bufferView` —
|
|
674
|
-
*
|
|
675
|
-
*
|
|
676
|
-
* it.
|
|
673
|
+
* `bufferView` — a buffer handed from one program's view to another's. A
|
|
674
|
+
* buffer that belongs to somebody else is NAMED by an attribute schema, and is
|
|
675
|
+
* borrowed: the view uses it and never deletes it.
|
|
677
676
|
*/
|
|
678
677
|
export interface ViewSchema {
|
|
679
678
|
uniforms?: UniformSchema
|
package/test/index.test.ts
CHANGED
|
@@ -1491,6 +1491,84 @@ describe('vaoView', () => {
|
|
|
1491
1491
|
})
|
|
1492
1492
|
})
|
|
1493
1493
|
|
|
1494
|
+
describe('a context lost and restored between two builds', () => {
|
|
1495
|
+
/**
|
|
1496
|
+
* A WebGL1 context whose extension objects die with the context, as on
|
|
1497
|
+
* Chrome 109 and 119: an object from before the loss creates nothing and
|
|
1498
|
+
* sets no divisor after the restore, while a fresh `getExtension` works.
|
|
1499
|
+
*/
|
|
1500
|
+
function losableGL() {
|
|
1501
|
+
const gl = createMockGL() as any
|
|
1502
|
+
let generation = 0
|
|
1503
|
+
const divisors: Array<{ generation: number; location: number; divisor: number }> = []
|
|
1504
|
+
gl.getExtension = vi.fn((name: string) => {
|
|
1505
|
+
const born = generation
|
|
1506
|
+
const alive = () => born === generation
|
|
1507
|
+
if (name === 'OES_vertex_array_object') {
|
|
1508
|
+
return {
|
|
1509
|
+
createVertexArrayOES: () => (alive() ? { generation: born } : null),
|
|
1510
|
+
bindVertexArrayOES: () => {},
|
|
1511
|
+
deleteVertexArrayOES: () => {},
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
if (name === 'ANGLE_instanced_arrays') {
|
|
1515
|
+
return {
|
|
1516
|
+
vertexAttribDivisorANGLE: (location: number, divisor: number) => {
|
|
1517
|
+
if (alive()) {
|
|
1518
|
+
divisors.push({ generation: born, location, divisor })
|
|
1519
|
+
}
|
|
1520
|
+
},
|
|
1521
|
+
drawArraysInstancedANGLE: () => {},
|
|
1522
|
+
drawElementsInstancedANGLE: () => {},
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
return null
|
|
1526
|
+
})
|
|
1527
|
+
return {
|
|
1528
|
+
gl,
|
|
1529
|
+
divisors,
|
|
1530
|
+
loseAndRestore() {
|
|
1531
|
+
generation++
|
|
1532
|
+
},
|
|
1533
|
+
get generation() {
|
|
1534
|
+
return generation
|
|
1535
|
+
},
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
it('creates a vertex array on the second build', () => {
|
|
1540
|
+
const context = losableGL()
|
|
1541
|
+
const program = context.gl.createProgram()
|
|
1542
|
+
const build = () =>
|
|
1543
|
+
vaoView(context.gl, [
|
|
1544
|
+
attributeView(context.gl, program, { a_corner: { kind: 'vec2' } } satisfies AttributeSchema)
|
|
1545
|
+
.a_corner,
|
|
1546
|
+
])
|
|
1547
|
+
|
|
1548
|
+
build()
|
|
1549
|
+
context.loseAndRestore()
|
|
1550
|
+
expect(build).not.toThrow()
|
|
1551
|
+
})
|
|
1552
|
+
|
|
1553
|
+
it('sets an instanced divisor on the second build', () => {
|
|
1554
|
+
const context = losableGL()
|
|
1555
|
+
const program = context.gl.createProgram()
|
|
1556
|
+
const build = () =>
|
|
1557
|
+
vaoView(context.gl, [
|
|
1558
|
+
attributeView(context.gl, program, {
|
|
1559
|
+
a_offset: { kind: 'vec2', instanced: true },
|
|
1560
|
+
} satisfies AttributeSchema).a_offset,
|
|
1561
|
+
])
|
|
1562
|
+
|
|
1563
|
+
build()
|
|
1564
|
+
context.loseAndRestore()
|
|
1565
|
+
build()
|
|
1566
|
+
expect(context.divisors).toContainEqual(
|
|
1567
|
+
expect.objectContaining({ generation: context.generation, divisor: 1 }),
|
|
1568
|
+
)
|
|
1569
|
+
})
|
|
1570
|
+
})
|
|
1571
|
+
|
|
1494
1572
|
describe('binding a participant on its own', () => {
|
|
1495
1573
|
let gl: WebGL2RenderingContext
|
|
1496
1574
|
let program: WebGLProgram
|
package/test/tag.test.ts
CHANGED
|
@@ -1800,7 +1800,7 @@ describe('compile.toQuad', () => {
|
|
|
1800
1800
|
|
|
1801
1801
|
// Should have quad attribute in schema
|
|
1802
1802
|
expect(result.schema.attributes).toEqual({
|
|
1803
|
-
a_quad: { kind: 'vec2'
|
|
1803
|
+
a_quad: { kind: 'vec2' }
|
|
1804
1804
|
})
|
|
1805
1805
|
|
|
1806
1806
|
// Should have fragment uniforms
|
|
@@ -1810,6 +1810,27 @@ describe('compile.toQuad', () => {
|
|
|
1810
1810
|
})
|
|
1811
1811
|
})
|
|
1812
1812
|
|
|
1813
|
+
it('uploads the quad into a live buffer after a context is lost and restored', () => {
|
|
1814
|
+
let generation = 0
|
|
1815
|
+
gl.createBuffer = vi.fn(() => ({ generation }) as unknown as WebGLBuffer)
|
|
1816
|
+
let bound: { generation: number } | null = null
|
|
1817
|
+
gl.bindBuffer = vi.fn((_target, buffer) => {
|
|
1818
|
+
bound = buffer as unknown as { generation: number } | null
|
|
1819
|
+
})
|
|
1820
|
+
const uploadedInto: Array<{ generation: number } | null> = []
|
|
1821
|
+
gl.bufferData = vi.fn(() => {
|
|
1822
|
+
uploadedInto.push(bound)
|
|
1823
|
+
}) as any
|
|
1824
|
+
const fragment = glsl`precision mediump float;
|
|
1825
|
+
void main() { gl_FragColor = vec4(1.0); }`
|
|
1826
|
+
|
|
1827
|
+
compile.toQuad(gl, fragment)
|
|
1828
|
+
generation++
|
|
1829
|
+
compile.toQuad(gl, fragment)
|
|
1830
|
+
|
|
1831
|
+
expect(uploadedInto.at(-1)).toEqual({ generation })
|
|
1832
|
+
})
|
|
1833
|
+
|
|
1813
1834
|
it('should generate vertex shader with correct uv output', () => {
|
|
1814
1835
|
const fragment = glsl`#version 300 es
|
|
1815
1836
|
precision mediump float;
|
|
@@ -1862,7 +1883,7 @@ describe('compile.toQuad', () => {
|
|
|
1862
1883
|
})
|
|
1863
1884
|
|
|
1864
1885
|
expect(result.schema.attributes).toEqual({
|
|
1865
|
-
a_quad: { kind: 'vec2'
|
|
1886
|
+
a_quad: { kind: 'vec2' }
|
|
1866
1887
|
})
|
|
1867
1888
|
})
|
|
1868
1889
|
|
|
@@ -2028,20 +2049,23 @@ describe('compile.toQuad', () => {
|
|
|
2028
2049
|
|
|
2029
2050
|
expect(result.schema.uniforms).toEqual({})
|
|
2030
2051
|
expect(result.schema.attributes).toEqual({
|
|
2031
|
-
a_quad: { kind: 'vec2'
|
|
2052
|
+
a_quad: { kind: 'vec2' }
|
|
2032
2053
|
})
|
|
2033
2054
|
expect(result.program).toBe(mockProgram)
|
|
2034
2055
|
})
|
|
2035
2056
|
|
|
2036
|
-
it('
|
|
2037
|
-
const
|
|
2038
|
-
|
|
2057
|
+
it('owns its quad buffer and deletes it on abort', () => {
|
|
2058
|
+
const quad = { id: 'quad' } as WebGLBuffer
|
|
2059
|
+
gl.createBuffer = vi.fn(() => quad)
|
|
2060
|
+
gl.deleteBuffer = vi.fn()
|
|
2061
|
+
const controller = new AbortController()
|
|
2039
2062
|
|
|
2040
|
-
compile.toQuad(gl,
|
|
2041
|
-
|
|
2063
|
+
compile.toQuad(gl, glsl`void main() { gl_FragColor = vec4(1.0); }`, {
|
|
2064
|
+
signal: controller.signal,
|
|
2065
|
+
})
|
|
2066
|
+
controller.abort()
|
|
2042
2067
|
|
|
2043
|
-
|
|
2044
|
-
expect(gl.createBuffer).toHaveBeenCalledTimes(1)
|
|
2068
|
+
expect(gl.deleteBuffer).toHaveBeenCalledWith(quad)
|
|
2045
2069
|
})
|
|
2046
2070
|
|
|
2047
2071
|
it('should expose quad attribute in view for binding', () => {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { AttributeNotFoundError, created } from './errors'\nimport { getInstancedArrays, getVertexArrayObject } from './gl'\nimport type {\n AttributeFormat,\n AttributeKind,\n AttributeMethods,\n AttributeSchema,\n AttributeView,\n BufferSchema,\n BufferView,\n GL,\n UniformView as InferUniformView,\n GLUsage,\n InterleavedAttributeLayout,\n InterleavedAttributeMethods,\n InterleavedAttributeSchema,\n InterleavedAttributeView,\n UniformSchema,\n VertexArrayMethods,\n VertexArrayParticipant,\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 const feature = getVertexArrayObject(gl)\n if (!feature) {\n return () => {}\n }\n const previous = readVertexArrayBinding(gl)\n feature.bindVertexArray(null)\n return () => feature.bindVertexArray(previous)\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 = getVertexArrayObject(gl)\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(gl)\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(gl)\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,\n) {\n gl.enableVertexAttribArray(location)\n if (isIntegerKind) {\n ;(gl as WebGL2RenderingContext).vertexAttribIPointer(location, size, gl[glType], stride, offset)\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 // Get instanced-arrays-feature: extension if webgl, gl if webgl2\n const instancedArrays = getInstancedArrays(gl)\n if (instanced) {\n assertedNotNullish(instancedArrays).vertexAttribDivisor(location, 1)\n } else if (instancedArrays) {\n instancedArrays.vertexAttribDivisor(location, 0)\n }\n}\n\n// Same enum in webgl2 and in the webgl1 extensions, which expose no constants\nconst VERTEX_ATTRIB_ARRAY_DIVISOR = 0x88fe\nconst VERTEX_ARRAY_BINDING = 0x85b5\n\n// Anything but an array or null would make the restore throw a TypeError.\nfunction readVertexArrayBinding(gl: GL): WebGLVertexArrayObject | null {\n const bound: unknown = gl.getParameter(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 getInstancedArrays(gl)\n ? (gl.getVertexAttrib(location, 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 — the quad `compile.toQuad` shares across every\n // program on a context, 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)\n return once(() => {\n getInstancedArrays(gl)?.vertexAttribDivisor(location, previousDivisor)\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 )\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 const instancedArrays = getInstancedArrays(gl)\n previousDivisors.forEach(([location, previous]) => {\n instancedArrays?.vertexAttribDivisor(location, previous)\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"]}
|