@bigmistqke/view.gl 0.1.16 → 0.1.18
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/dist/{chunk-4EAUCYDP.mjs → chunk-CLMGHUTT.mjs} +42 -9
- package/dist/chunk-CLMGHUTT.mjs.map +1 -0
- package/dist/gl.d.mts +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +1 -1
- package/dist/tag.d.mts +1 -1
- package/dist/tag.mjs +1 -1
- package/dist/{types-lm9fTTy8.d.mts → types-CXqYX05f.d.mts} +24 -4
- package/package.json +1 -1
- package/src/index.ts +56 -8
- package/src/types.ts +39 -3
- package/test/index.test.ts +161 -10
- package/test/mocks/webgl.ts +5 -0
- package/dist/chunk-4EAUCYDP.mjs.map +0 -1
|
@@ -164,9 +164,37 @@ function uniformView(gl, program, schema) {
|
|
|
164
164
|
};
|
|
165
165
|
});
|
|
166
166
|
}
|
|
167
|
-
|
|
167
|
+
var FORMAT_TO_GL_TYPE = {
|
|
168
|
+
float32: "FLOAT",
|
|
169
|
+
int32: "INT",
|
|
170
|
+
uint32: "UNSIGNED_INT",
|
|
171
|
+
int16: "SHORT",
|
|
172
|
+
uint16: "UNSIGNED_SHORT",
|
|
173
|
+
int8: "BYTE",
|
|
174
|
+
uint8: "UNSIGNED_BYTE"
|
|
175
|
+
};
|
|
176
|
+
var FORMAT_BYTE_SIZE = {
|
|
177
|
+
float32: 4,
|
|
178
|
+
int32: 4,
|
|
179
|
+
uint32: 4,
|
|
180
|
+
int16: 2,
|
|
181
|
+
uint16: 2,
|
|
182
|
+
int8: 1,
|
|
183
|
+
uint8: 1
|
|
184
|
+
};
|
|
185
|
+
function defaultFormat(kind) {
|
|
186
|
+
if (kind.startsWith("u")) return "uint32";
|
|
187
|
+
if (kind.startsWith("i")) return "int32";
|
|
188
|
+
return "float32";
|
|
189
|
+
}
|
|
190
|
+
function handleAttribute(gl, location, size, stride, offset, glType, isIntegerKind, normalized, instanced) {
|
|
168
191
|
gl.enableVertexAttribArray(location);
|
|
169
|
-
|
|
192
|
+
if (isIntegerKind) {
|
|
193
|
+
;
|
|
194
|
+
gl.vertexAttribIPointer(location, size, gl[glType], stride, offset);
|
|
195
|
+
} else {
|
|
196
|
+
gl.vertexAttribPointer(location, size, gl[glType], normalized, stride, offset);
|
|
197
|
+
}
|
|
170
198
|
if (instanced) {
|
|
171
199
|
assertedNotNullish(getInstancedArrays(gl)).vertexAttribDivisor(location, 1);
|
|
172
200
|
}
|
|
@@ -174,19 +202,21 @@ function handleAttribute(gl, location, size, stride, offset, type, instanced) {
|
|
|
174
202
|
function attributeView(gl, program, schema, { signal } = {}) {
|
|
175
203
|
const attributes = mapObject(
|
|
176
204
|
schema,
|
|
177
|
-
({ kind, instanced, buffer = assertedNotNullish(gl.createBuffer()) }, key) => {
|
|
205
|
+
({ kind, format, normalized = false, instanced, buffer = assertedNotNullish(gl.createBuffer()) }, key) => {
|
|
178
206
|
const name2 = toID(key);
|
|
179
207
|
const location = gl.getAttribLocation(program, name2);
|
|
180
208
|
if (location < 0) {
|
|
181
209
|
throw new Error(`Attribute '${name2}' not found`);
|
|
182
210
|
}
|
|
183
211
|
const size = kindToSize(kind);
|
|
184
|
-
const
|
|
212
|
+
const resolvedFormat = format ?? defaultFormat(kind);
|
|
213
|
+
const glType = FORMAT_TO_GL_TYPE[resolvedFormat];
|
|
214
|
+
const isIntKind = kind.startsWith("i") || kind.startsWith("u");
|
|
185
215
|
return {
|
|
186
216
|
buffer,
|
|
187
217
|
bind() {
|
|
188
218
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
189
|
-
handleAttribute(gl, location, size, 0, 0,
|
|
219
|
+
handleAttribute(gl, location, size, 0, 0, glType, isIntKind, normalized, instanced);
|
|
190
220
|
},
|
|
191
221
|
dispose() {
|
|
192
222
|
gl.deleteBuffer(buffer);
|
|
@@ -215,9 +245,12 @@ function interleavedAttributeView(gl, program, schema, { signal } = {}) {
|
|
|
215
245
|
}
|
|
216
246
|
const size = kindToSize(layout2.kind);
|
|
217
247
|
const offset = index2;
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
248
|
+
const resolvedFormat = layout2.format ?? defaultFormat(layout2.kind);
|
|
249
|
+
const glType = FORMAT_TO_GL_TYPE[resolvedFormat];
|
|
250
|
+
const isIntKind = layout2.kind.startsWith("i") || layout2.kind.startsWith("u");
|
|
251
|
+
const normalized = layout2.normalized ?? false;
|
|
252
|
+
index2 += size * FORMAT_BYTE_SIZE[resolvedFormat];
|
|
253
|
+
return () => handleAttribute(gl, location, size, stride, offset, glType, isIntKind, normalized, instanced);
|
|
221
254
|
});
|
|
222
255
|
const stride = index2;
|
|
223
256
|
const buffer = assertedNotNullish(gl.createBuffer());
|
|
@@ -313,4 +346,4 @@ export {
|
|
|
313
346
|
interleavedAttributeView,
|
|
314
347
|
bufferView
|
|
315
348
|
};
|
|
316
|
-
//# sourceMappingURL=chunk-
|
|
349
|
+
//# sourceMappingURL=chunk-CLMGHUTT.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts","../src/index.ts"],"sourcesContent":["import type {\n AttributeKind,\n FramebufferDefinition,\n GL,\n KIND_TO_SIZE_MAP,\n KIND_TO_UNIFORM_FN_NAME_MAP,\n TextureDefinition,\n UniformKind,\n} 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/* */\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): WebGLTexture {\n const texture = gl.createTexture()\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 console.log(minFilter)\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 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 '${name}' 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, ...options }: FramebufferDefinition,\n) {\n // Create texture for the framebuffer\n texture ??= createTexture(gl, options)\n\n // Create framebuffer\n const framebuffer = assertedNotNullish(\n gl.createFramebuffer(),\n `Failed to create framebuffer: ${name}`,\n )\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 return {\n texture,\n framebuffer,\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 { 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 InterleavedAttributeMethods,\n InterleavedAttributeSchema,\n InterleavedAttributeView,\n UniformSchema,\n View,\n ViewOptions,\n ViewSchema,\n} from './types'\nimport {\n isSamplerKind,\n kindToUniformFnName,\n isMatKind,\n assertedNotNullish,\n kindToSize,\n forEachObject,\n} from './utils'\nimport { createUpsertMap, mapObject } from './utils'\nexport * from './types'\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 options?: ViewOptions,\n): View<TSchema> {\n return {\n uniforms: !schema.uniforms ? undefined : uniformView(gl, program, schema.uniforms),\n attributes: !schema.attributes\n ? undefined\n : attributeView(gl, program, schema.attributes, options),\n interleavedAttributes: !schema.interleavedAttributes\n ? undefined\n : interleavedAttributeView(gl, program, schema.interleavedAttributes, options),\n buffers: !schema.buffers ? undefined : bufferView(gl, schema.buffers),\n } as View<TSchema>\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 if (instanced) {\n // Get instanced-arrays-feature: extension if webgl, gl if webgl2\n assertedNotNullish(getInstancedArrays(gl)).vertexAttribDivisor(location, 1)\n }\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 = assertedNotNullish(gl.createBuffer()) },\n key,\n ): AttributeMethods => {\n const name = toID(key)\n\n const location = gl.getAttribLocation(program, name)\n if (location < 0) {\n throw new Error(`Attribute '${name}' not found`)\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 return {\n buffer,\n bind() {\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n handleAttribute(gl, location, size, 0, 0, glType, isIntKind, normalized, instanced)\n },\n dispose() {\n gl.deleteBuffer(buffer)\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 }\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\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, instanced }) => {\n // Increment number to keep track of offset\n let index = 0\n\n // Calculate layout information\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 Error(`Attribute '${name}' not found`)\n }\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 () => handleAttribute(gl, location, size, stride, offset, glType, isIntKind, normalized, instanced)\n })\n\n // Set stride to final index\n const stride = index\n\n // Create a buffer\n const buffer = assertedNotNullish(gl.createBuffer())\n\n // Create VAO to cache attribute state\n let vao: { unbind(): void; bind(): void; dispose(): void } | undefined = undefined\n\n // Get VAO-feature: extension if webgl1, gl if webgl2\n const feature = getVertexArrayObject(gl)\n if (feature) {\n const vertexArray = feature.createVertexArray()\n feature.bindVertexArray(vertexArray)\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n for (const handle of handles) {\n handle()\n }\n feature.bindVertexArray(null)\n vao = {\n unbind() {\n feature.bindVertexArray(null)\n },\n bind() {\n feature.bindVertexArray(vertexArray)\n },\n dispose() {\n feature.deleteVertexArray(vertexArray)\n },\n }\n }\n\n return {\n bind() {\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n if (vao) {\n vao.bind()\n } else {\n // Fallback: manual attribute setup\n for (const handle of handles) {\n handle()\n }\n }\n },\n unbind() {\n if (vao) {\n vao.unbind()\n }\n },\n dispose() {\n gl.deleteBuffer(buffer)\n if (vao) {\n vao.dispose()\n }\n },\n set(value, usage = 'STATIC_DRAW') {\n if (vao) {\n vao.bind()\n }\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n gl.bufferData(gl.ARRAY_BUFFER, value, gl[usage])\n if (vao) {\n vao.unbind()\n }\n },\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 = assertedNotNullish(gl.createBuffer())\n return {\n bind() {\n gl.bindBuffer(gl[target], buffer)\n },\n dispose() {\n gl.deleteBuffer(buffer)\n },\n set(data: Float32Array) {\n gl.bindBuffer(gl[target], buffer)\n gl.bufferData(gl[target], data, gl[usage])\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":["index","value","name","location","index","layout"]}
|
package/dist/gl.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { G as GL, R as RemoveSuffix } from './types-
|
|
1
|
+
import { G as GL, R as RemoveSuffix } from './types-CXqYX05f.mjs';
|
|
2
2
|
|
|
3
3
|
/**********************************************************************************/
|
|
4
4
|
/**********************************************************************************/
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { V as ViewSchema, G as GL, a as ViewOptions, b as View, U as UniformSchema, c as UniformView, A as AttributeSchema, d as AttributeView, I as InterleavedAttributeSchema, e as InterleavedAttributeView, B as BufferSchema, f as BufferView } from './types-
|
|
2
|
-
export {
|
|
1
|
+
import { V as ViewSchema, G as GL, a as ViewOptions, b as View, U as UniformSchema, c as UniformView, A as AttributeSchema, d as AttributeView, I as InterleavedAttributeSchema, e as InterleavedAttributeView, B as BufferSchema, f as BufferView } from './types-CXqYX05f.mjs';
|
|
2
|
+
export { z as AttributeDefinition, y as AttributeFormat, x as AttributeKind, C as AttributeMethods, w as AttributeShortHand, a6 as AttributeToken, a7 as AttributeTokenFn, H as BufferDefinition, J as BufferMethods, ae as CompileResult, ac as FlattenSlots, Z as Format, M as Framebuffer, L as FramebufferDefinition, a3 as GLSL, a1 as GLSLResult, a2 as GLSLSlot, ab as GLSLSlotsToSchema, a9 as GLSLToSchema, aa as GLSLToView, g as GLTarget, l as GLTextureFilter, j as GLTextureFormat, i as GLTextureTarget, k as GLTextureType, m as GLTextureWrap, h as GLUsage, a8 as InterleaveToken, E as InterleavedAttributeDefinition, D as InterleavedAttributeLayout, F as InterleavedAttributeMethods, Y as InternalFormat, n as KIND_TO_SIZE_MAP, K as KIND_TO_UNIFORM_FN_NAME_MAP, ad as MergeGLSLSchema, _ as PixelType, $ as TexImage2DOptions, T as TextureDefinition, P as TextureMethods, S as TextureParameterName, W as TextureParameterValue, X as TextureParameters, O as TextureSchema, N as TextureTarget, Q as TextureView, t as UniformArrayMethods, r as UniformDefinition, s as UniformElementMethods, o as UniformFnName, p as UniformKind, q as UniformKindMap, u as UniformMethods, a4 as UniformToken, a5 as UniformTokenFn, v as UniformValue, a0 as ViewSchemaPartial } from './types-CXqYX05f.mjs';
|
|
3
3
|
|
|
4
4
|
declare function toID(key: string | number | symbol): any;
|
|
5
5
|
/**********************************************************************************/
|
package/dist/index.mjs
CHANGED
package/dist/tag.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a2 as GLSLSlot, a3 as GLSL, a5 as UniformTokenFn, a7 as AttributeTokenFn, a6 as AttributeToken, x as AttributeKind, z as AttributeDefinition, a8 as InterleaveToken, a0 as ViewSchemaPartial, ae as CompileResult, af as Prettify, a9 as GLSLToSchema, G as GL } from './types-CXqYX05f.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
|
@@ -186,28 +186,48 @@ type UniformValue = UniformKindMap[UniformKind];
|
|
|
186
186
|
/**********************************************************************************/
|
|
187
187
|
type AttributeShortHand = '1f' | '2f' | '3f' | '4f' | '1i' | '2i' | '3i' | '4i' | '1ui' | '2ui' | '3ui' | '4ui';
|
|
188
188
|
type AttributeKind = 'float' | 'vec2' | 'vec3' | 'vec4' | 'mat2' | 'mat3' | 'mat4' | 'mat2x3' | 'mat2x4' | 'mat3x2' | 'mat3x4' | 'mat4x2' | 'mat4x3' | 'int' | 'ivec2' | 'ivec3' | 'ivec4' | 'uint' | 'uvec2' | 'uvec3' | 'uvec4';
|
|
189
|
+
type AttributeFormat = 'float32' | 'int32' | 'uint32' | 'int16' | 'uint16' | 'int8' | 'uint8';
|
|
189
190
|
interface AttributeDefinition {
|
|
190
191
|
kind: AttributeKind;
|
|
192
|
+
format?: AttributeFormat;
|
|
193
|
+
normalized?: boolean;
|
|
191
194
|
instanced?: boolean;
|
|
192
195
|
buffer?: WebGLBuffer;
|
|
193
196
|
}
|
|
194
197
|
type AttributeSchema = Record<string | symbol, AttributeDefinition>;
|
|
195
|
-
|
|
198
|
+
type IntKind = 'int' | 'ivec2' | 'ivec3' | 'ivec4';
|
|
199
|
+
type UintKind = 'uint' | 'uvec2' | 'uvec3' | 'uvec4';
|
|
200
|
+
type DefaultFormat<K extends AttributeKind> = K extends IntKind ? 'int32' : K extends UintKind ? 'uint32' : 'float32';
|
|
201
|
+
type ResolvedFormat<T extends AttributeDefinition> = T extends {
|
|
202
|
+
format: infer F extends AttributeFormat;
|
|
203
|
+
} ? F : DefaultFormat<T['kind']>;
|
|
204
|
+
type FormatToArray = {
|
|
205
|
+
float32: Float32Array;
|
|
206
|
+
int32: Int32Array;
|
|
207
|
+
uint32: Uint32Array;
|
|
208
|
+
int16: Int16Array;
|
|
209
|
+
uint16: Uint16Array;
|
|
210
|
+
int8: Int8Array;
|
|
211
|
+
uint8: Uint8Array;
|
|
212
|
+
};
|
|
213
|
+
interface AttributeMethods<T extends AttributeDefinition = AttributeDefinition> {
|
|
196
214
|
buffer: WebGLBuffer;
|
|
197
215
|
bind(): void;
|
|
198
|
-
set(data:
|
|
216
|
+
set(data: FormatToArray[ResolvedFormat<T>], usage?: GLUsage): {
|
|
199
217
|
bind(): void;
|
|
200
218
|
};
|
|
201
219
|
dispose(): void;
|
|
202
220
|
}
|
|
203
221
|
type AttributeView<T extends AttributeSchema> = {
|
|
204
|
-
[K in keyof T]: Prettify<AttributeMethods<T[K]
|
|
222
|
+
[K in keyof T]: Prettify<AttributeMethods<T[K]>>;
|
|
205
223
|
};
|
|
206
224
|
/**********************************************************************************/
|
|
207
225
|
/**********************************************************************************/
|
|
208
226
|
interface InterleavedAttributeLayout {
|
|
209
227
|
key: string | symbol;
|
|
210
228
|
kind: AttributeKind;
|
|
229
|
+
format?: AttributeFormat;
|
|
230
|
+
normalized?: boolean;
|
|
211
231
|
}
|
|
212
232
|
interface InterleavedAttributeDefinition {
|
|
213
233
|
layout: InterleavedAttributeLayout[];
|
|
@@ -416,4 +436,4 @@ type CompileResult<TVertex extends GLSL, TFragment extends GLSL, TOverrideSchema
|
|
|
416
436
|
fragment: string;
|
|
417
437
|
} : never;
|
|
418
438
|
|
|
419
|
-
export type {
|
|
439
|
+
export type { TexImage2DOptions as $, AttributeSchema as A, BufferSchema as B, AttributeMethods as C, InterleavedAttributeLayout as D, InterleavedAttributeDefinition as E, InterleavedAttributeMethods as F, GL as G, BufferDefinition as H, InterleavedAttributeSchema as I, BufferMethods as J, KIND_TO_UNIFORM_FN_NAME_MAP as K, FramebufferDefinition as L, Framebuffer as M, TextureTarget as N, TextureSchema as O, TextureMethods as P, TextureView as Q, RemoveSuffix as R, TextureParameterName as S, TextureDefinition as T, UniformSchema as U, ViewSchema as V, TextureParameterValue as W, TextureParameters as X, InternalFormat as Y, Format as Z, PixelType as _, ViewOptions as a, ViewSchemaPartial as a0, GLSLResult as a1, GLSLSlot as a2, GLSL as a3, UniformToken as a4, UniformTokenFn as a5, AttributeToken as a6, AttributeTokenFn as a7, InterleaveToken as a8, GLSLToSchema as a9, GLSLToView as aa, GLSLSlotsToSchema as ab, FlattenSlots as ac, MergeGLSLSchema as ad, CompileResult as ae, Prettify as af, View as b, UniformView as c, AttributeView as d, InterleavedAttributeView as e, BufferView as f, GLTarget as g, GLUsage as h, GLTextureTarget as i, GLTextureFormat as j, GLTextureType as k, GLTextureFilter as l, GLTextureWrap as m, KIND_TO_SIZE_MAP as n, UniformFnName as o, UniformKind as p, UniformKindMap as q, UniformDefinition as r, UniformElementMethods as s, UniformArrayMethods as t, UniformMethods as u, UniformValue as v, AttributeShortHand as w, AttributeKind as x, AttributeFormat as y, AttributeDefinition as z };
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { getInstancedArrays, getVertexArrayObject } from './gl'
|
|
2
2
|
import type {
|
|
3
|
+
AttributeFormat,
|
|
4
|
+
AttributeKind,
|
|
3
5
|
AttributeMethods,
|
|
4
6
|
AttributeSchema,
|
|
5
7
|
AttributeView,
|
|
@@ -165,6 +167,41 @@ export function uniformView<T extends UniformSchema>(
|
|
|
165
167
|
/* */
|
|
166
168
|
/**********************************************************************************/
|
|
167
169
|
|
|
170
|
+
type GLType =
|
|
171
|
+
| 'FLOAT'
|
|
172
|
+
| 'INT'
|
|
173
|
+
| 'UNSIGNED_INT'
|
|
174
|
+
| 'SHORT'
|
|
175
|
+
| 'UNSIGNED_SHORT'
|
|
176
|
+
| 'BYTE'
|
|
177
|
+
| 'UNSIGNED_BYTE'
|
|
178
|
+
|
|
179
|
+
const FORMAT_TO_GL_TYPE: Record<AttributeFormat, GLType> = {
|
|
180
|
+
float32: 'FLOAT',
|
|
181
|
+
int32: 'INT',
|
|
182
|
+
uint32: 'UNSIGNED_INT',
|
|
183
|
+
int16: 'SHORT',
|
|
184
|
+
uint16: 'UNSIGNED_SHORT',
|
|
185
|
+
int8: 'BYTE',
|
|
186
|
+
uint8: 'UNSIGNED_BYTE',
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const FORMAT_BYTE_SIZE: Record<AttributeFormat, number> = {
|
|
190
|
+
float32: 4,
|
|
191
|
+
int32: 4,
|
|
192
|
+
uint32: 4,
|
|
193
|
+
int16: 2,
|
|
194
|
+
uint16: 2,
|
|
195
|
+
int8: 1,
|
|
196
|
+
uint8: 1,
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function defaultFormat(kind: AttributeKind): AttributeFormat {
|
|
200
|
+
if (kind.startsWith('u')) return 'uint32'
|
|
201
|
+
if (kind.startsWith('i')) return 'int32'
|
|
202
|
+
return 'float32'
|
|
203
|
+
}
|
|
204
|
+
|
|
168
205
|
// Shared attribute helper functions
|
|
169
206
|
// between attributeView and interleavedAttributeView
|
|
170
207
|
function handleAttribute(
|
|
@@ -173,11 +210,17 @@ function handleAttribute(
|
|
|
173
210
|
size: number,
|
|
174
211
|
stride: number,
|
|
175
212
|
offset: number,
|
|
176
|
-
|
|
213
|
+
glType: GLType,
|
|
214
|
+
isIntegerKind: boolean,
|
|
215
|
+
normalized: boolean,
|
|
177
216
|
instanced?: boolean,
|
|
178
217
|
) {
|
|
179
218
|
gl.enableVertexAttribArray(location)
|
|
180
|
-
|
|
219
|
+
if (isIntegerKind) {
|
|
220
|
+
;(gl as WebGL2RenderingContext).vertexAttribIPointer(location, size, gl[glType], stride, offset)
|
|
221
|
+
} else {
|
|
222
|
+
gl.vertexAttribPointer(location, size, gl[glType], normalized, stride, offset)
|
|
223
|
+
}
|
|
181
224
|
|
|
182
225
|
if (instanced) {
|
|
183
226
|
// Get instanced-arrays-feature: extension if webgl, gl if webgl2
|
|
@@ -194,7 +237,7 @@ export function attributeView<T extends AttributeSchema>(
|
|
|
194
237
|
const attributes = mapObject(
|
|
195
238
|
schema,
|
|
196
239
|
(
|
|
197
|
-
{ kind, instanced, buffer = assertedNotNullish(gl.createBuffer()) },
|
|
240
|
+
{ kind, format, normalized = false, instanced, buffer = assertedNotNullish(gl.createBuffer()) },
|
|
198
241
|
key,
|
|
199
242
|
): AttributeMethods => {
|
|
200
243
|
const name = toID(key)
|
|
@@ -205,13 +248,15 @@ export function attributeView<T extends AttributeSchema>(
|
|
|
205
248
|
}
|
|
206
249
|
|
|
207
250
|
const size = kindToSize(kind)
|
|
208
|
-
const
|
|
251
|
+
const resolvedFormat = format ?? defaultFormat(kind)
|
|
252
|
+
const glType = FORMAT_TO_GL_TYPE[resolvedFormat]
|
|
253
|
+
const isIntKind = kind.startsWith('i') || kind.startsWith('u')
|
|
209
254
|
|
|
210
255
|
return {
|
|
211
256
|
buffer,
|
|
212
257
|
bind() {
|
|
213
258
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
|
|
214
|
-
handleAttribute(gl, location, size, 0, 0,
|
|
259
|
+
handleAttribute(gl, location, size, 0, 0, glType, isIntKind, normalized, instanced)
|
|
215
260
|
},
|
|
216
261
|
dispose() {
|
|
217
262
|
gl.deleteBuffer(buffer)
|
|
@@ -261,10 +306,13 @@ export function interleavedAttributeView<T extends InterleavedAttributeSchema>(
|
|
|
261
306
|
|
|
262
307
|
const size = kindToSize(layout.kind)
|
|
263
308
|
const offset = index
|
|
264
|
-
const
|
|
265
|
-
|
|
309
|
+
const resolvedFormat = layout.format ?? defaultFormat(layout.kind)
|
|
310
|
+
const glType = FORMAT_TO_GL_TYPE[resolvedFormat]
|
|
311
|
+
const isIntKind = layout.kind.startsWith('i') || layout.kind.startsWith('u')
|
|
312
|
+
const normalized = layout.normalized ?? false
|
|
313
|
+
index += size * FORMAT_BYTE_SIZE[resolvedFormat]
|
|
266
314
|
|
|
267
|
-
return () => handleAttribute(gl, location, size, stride, offset,
|
|
315
|
+
return () => handleAttribute(gl, location, size, stride, offset, glType, isIntKind, normalized, instanced)
|
|
268
316
|
})
|
|
269
317
|
|
|
270
318
|
// Set stride to final index
|
package/src/types.ts
CHANGED
|
@@ -285,23 +285,57 @@ export type AttributeKind =
|
|
|
285
285
|
| 'uvec3'
|
|
286
286
|
| 'uvec4'
|
|
287
287
|
|
|
288
|
+
export type AttributeFormat =
|
|
289
|
+
| 'float32'
|
|
290
|
+
| 'int32'
|
|
291
|
+
| 'uint32'
|
|
292
|
+
| 'int16'
|
|
293
|
+
| 'uint16'
|
|
294
|
+
| 'int8'
|
|
295
|
+
| 'uint8'
|
|
296
|
+
|
|
288
297
|
export interface AttributeDefinition {
|
|
289
298
|
kind: AttributeKind
|
|
299
|
+
format?: AttributeFormat
|
|
300
|
+
normalized?: boolean
|
|
290
301
|
instanced?: boolean
|
|
291
302
|
buffer?: WebGLBuffer
|
|
292
303
|
}
|
|
293
304
|
|
|
294
305
|
export type AttributeSchema = Record<string | symbol, AttributeDefinition>
|
|
295
306
|
|
|
296
|
-
|
|
307
|
+
type IntKind = 'int' | 'ivec2' | 'ivec3' | 'ivec4'
|
|
308
|
+
type UintKind = 'uint' | 'uvec2' | 'uvec3' | 'uvec4'
|
|
309
|
+
|
|
310
|
+
type DefaultFormat<K extends AttributeKind> = K extends IntKind
|
|
311
|
+
? 'int32'
|
|
312
|
+
: K extends UintKind
|
|
313
|
+
? 'uint32'
|
|
314
|
+
: 'float32'
|
|
315
|
+
|
|
316
|
+
type ResolvedFormat<T extends AttributeDefinition> = T extends { format: infer F extends AttributeFormat }
|
|
317
|
+
? F
|
|
318
|
+
: DefaultFormat<T['kind']>
|
|
319
|
+
|
|
320
|
+
type FormatToArray = {
|
|
321
|
+
float32: Float32Array
|
|
322
|
+
int32: Int32Array
|
|
323
|
+
uint32: Uint32Array
|
|
324
|
+
int16: Int16Array
|
|
325
|
+
uint16: Uint16Array
|
|
326
|
+
int8: Int8Array
|
|
327
|
+
uint8: Uint8Array
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
export interface AttributeMethods<T extends AttributeDefinition = AttributeDefinition> {
|
|
297
331
|
buffer: WebGLBuffer
|
|
298
332
|
bind(): void
|
|
299
|
-
set(data:
|
|
333
|
+
set(data: FormatToArray[ResolvedFormat<T>], usage?: GLUsage): { bind(): void }
|
|
300
334
|
dispose(): void
|
|
301
335
|
}
|
|
302
336
|
|
|
303
337
|
export type AttributeView<T extends AttributeSchema> = {
|
|
304
|
-
[K in keyof T]: Prettify<AttributeMethods<T[K]
|
|
338
|
+
[K in keyof T]: Prettify<AttributeMethods<T[K]>>
|
|
305
339
|
}
|
|
306
340
|
|
|
307
341
|
/**********************************************************************************/
|
|
@@ -313,6 +347,8 @@ export type AttributeView<T extends AttributeSchema> = {
|
|
|
313
347
|
export interface InterleavedAttributeLayout {
|
|
314
348
|
key: string | symbol
|
|
315
349
|
kind: AttributeKind
|
|
350
|
+
format?: AttributeFormat
|
|
351
|
+
normalized?: boolean
|
|
316
352
|
}
|
|
317
353
|
|
|
318
354
|
export interface InterleavedAttributeDefinition {
|
package/test/index.test.ts
CHANGED
|
@@ -434,7 +434,74 @@ describe('attributeView', () => {
|
|
|
434
434
|
expect.any(Number),
|
|
435
435
|
1, // size for float
|
|
436
436
|
gl.FLOAT,
|
|
437
|
-
false,
|
|
437
|
+
false, // normalized
|
|
438
|
+
0,
|
|
439
|
+
0,
|
|
440
|
+
)
|
|
441
|
+
})
|
|
442
|
+
|
|
443
|
+
it('should use format to override the GL buffer type', () => {
|
|
444
|
+
const schema = {
|
|
445
|
+
a_color: { kind: 'vec4', format: 'uint8', normalized: true },
|
|
446
|
+
a_normal: { kind: 'vec3', format: 'int8', normalized: true },
|
|
447
|
+
a_uv: { kind: 'vec2', format: 'uint16', normalized: true },
|
|
448
|
+
} satisfies AttributeSchema
|
|
449
|
+
|
|
450
|
+
const attributes = attributeView(gl, program, schema)
|
|
451
|
+
|
|
452
|
+
attributes.a_color.bind()
|
|
453
|
+
expect(gl.vertexAttribPointer).toHaveBeenCalledWith(
|
|
454
|
+
expect.any(Number),
|
|
455
|
+
4,
|
|
456
|
+
gl.UNSIGNED_BYTE,
|
|
457
|
+
true,
|
|
458
|
+
0,
|
|
459
|
+
0,
|
|
460
|
+
)
|
|
461
|
+
|
|
462
|
+
attributes.a_normal.bind()
|
|
463
|
+
expect(gl.vertexAttribPointer).toHaveBeenCalledWith(
|
|
464
|
+
expect.any(Number),
|
|
465
|
+
3,
|
|
466
|
+
gl.BYTE,
|
|
467
|
+
true,
|
|
468
|
+
0,
|
|
469
|
+
0,
|
|
470
|
+
)
|
|
471
|
+
|
|
472
|
+
attributes.a_uv.bind()
|
|
473
|
+
expect(gl.vertexAttribPointer).toHaveBeenCalledWith(
|
|
474
|
+
expect.any(Number),
|
|
475
|
+
2,
|
|
476
|
+
gl.UNSIGNED_SHORT,
|
|
477
|
+
true,
|
|
478
|
+
0,
|
|
479
|
+
0,
|
|
480
|
+
)
|
|
481
|
+
})
|
|
482
|
+
|
|
483
|
+
it('should use int16/uint16 format for integer attribute kinds', () => {
|
|
484
|
+
const schema = {
|
|
485
|
+
a_index: { kind: 'int', format: 'int16' },
|
|
486
|
+
a_flags: { kind: 'uint', format: 'uint8' },
|
|
487
|
+
} satisfies AttributeSchema
|
|
488
|
+
|
|
489
|
+
const attributes = attributeView(gl, program, schema)
|
|
490
|
+
|
|
491
|
+
attributes.a_index.bind()
|
|
492
|
+
expect(gl.vertexAttribIPointer).toHaveBeenCalledWith(
|
|
493
|
+
expect.any(Number),
|
|
494
|
+
1,
|
|
495
|
+
gl.SHORT,
|
|
496
|
+
0,
|
|
497
|
+
0,
|
|
498
|
+
)
|
|
499
|
+
|
|
500
|
+
attributes.a_flags.bind()
|
|
501
|
+
expect(gl.vertexAttribIPointer).toHaveBeenCalledWith(
|
|
502
|
+
expect.any(Number),
|
|
503
|
+
1,
|
|
504
|
+
gl.UNSIGNED_BYTE,
|
|
438
505
|
0,
|
|
439
506
|
0,
|
|
440
507
|
)
|
|
@@ -449,21 +516,66 @@ describe('attributeView', () => {
|
|
|
449
516
|
const attributes = attributeView(gl, program, schema)
|
|
450
517
|
|
|
451
518
|
attributes.a_index.bind()
|
|
452
|
-
expect(gl.
|
|
519
|
+
expect(gl.vertexAttribIPointer).toHaveBeenCalledWith(
|
|
453
520
|
expect.any(Number),
|
|
454
521
|
1, // size for int
|
|
455
522
|
gl.INT,
|
|
456
|
-
false,
|
|
457
523
|
0,
|
|
458
524
|
0,
|
|
459
525
|
)
|
|
460
526
|
|
|
461
527
|
attributes.a_indices.bind()
|
|
462
|
-
expect(gl.
|
|
528
|
+
expect(gl.vertexAttribIPointer).toHaveBeenCalledWith(
|
|
463
529
|
expect.any(Number),
|
|
464
530
|
2, // size for ivec2
|
|
465
531
|
gl.INT,
|
|
466
|
-
|
|
532
|
+
0,
|
|
533
|
+
0,
|
|
534
|
+
)
|
|
535
|
+
})
|
|
536
|
+
|
|
537
|
+
it('should handle unsigned integer attributes', () => {
|
|
538
|
+
const schema = {
|
|
539
|
+
a_sorted_index: { kind: 'uint' },
|
|
540
|
+
a_uindices2: { kind: 'uvec2' },
|
|
541
|
+
a_uindices3: { kind: 'uvec3' },
|
|
542
|
+
a_uindices4: { kind: 'uvec4' },
|
|
543
|
+
} satisfies AttributeSchema
|
|
544
|
+
|
|
545
|
+
const attributes = attributeView(gl, program, schema)
|
|
546
|
+
|
|
547
|
+
attributes.a_sorted_index.bind()
|
|
548
|
+
expect(gl.vertexAttribIPointer).toHaveBeenCalledWith(
|
|
549
|
+
expect.any(Number),
|
|
550
|
+
1, // size for uint
|
|
551
|
+
gl.UNSIGNED_INT,
|
|
552
|
+
0,
|
|
553
|
+
0,
|
|
554
|
+
)
|
|
555
|
+
|
|
556
|
+
attributes.a_uindices2.bind()
|
|
557
|
+
expect(gl.vertexAttribIPointer).toHaveBeenCalledWith(
|
|
558
|
+
expect.any(Number),
|
|
559
|
+
2, // size for uvec2
|
|
560
|
+
gl.UNSIGNED_INT,
|
|
561
|
+
0,
|
|
562
|
+
0,
|
|
563
|
+
)
|
|
564
|
+
|
|
565
|
+
attributes.a_uindices3.bind()
|
|
566
|
+
expect(gl.vertexAttribIPointer).toHaveBeenCalledWith(
|
|
567
|
+
expect.any(Number),
|
|
568
|
+
3, // size for uvec3
|
|
569
|
+
gl.UNSIGNED_INT,
|
|
570
|
+
0,
|
|
571
|
+
0,
|
|
572
|
+
)
|
|
573
|
+
|
|
574
|
+
attributes.a_uindices4.bind()
|
|
575
|
+
expect(gl.vertexAttribIPointer).toHaveBeenCalledWith(
|
|
576
|
+
expect.any(Number),
|
|
577
|
+
4, // size for uvec4
|
|
578
|
+
gl.UNSIGNED_INT,
|
|
467
579
|
0,
|
|
468
580
|
0,
|
|
469
581
|
)
|
|
@@ -687,12 +799,51 @@ describe('interleavedAttributeView', () => {
|
|
|
687
799
|
|
|
688
800
|
interleavedAttributes.data.bind()
|
|
689
801
|
|
|
690
|
-
const
|
|
802
|
+
const floatCalls = (gl.vertexAttribPointer as any).mock.calls
|
|
803
|
+
const intCalls = (gl.vertexAttribIPointer as any).mock.calls
|
|
804
|
+
|
|
805
|
+
// Float attributes use vertexAttribPointer
|
|
806
|
+
expect(floatCalls[0][2]).toBe(gl.FLOAT) // vec2
|
|
807
|
+
// Integer attributes use vertexAttribIPointer
|
|
808
|
+
expect(intCalls[0][2]).toBe(gl.INT) // int
|
|
809
|
+
expect(intCalls[1][2]).toBe(gl.INT) // ivec2
|
|
810
|
+
})
|
|
811
|
+
|
|
812
|
+
it('should use format byte size for stride and use normalized flag', () => {
|
|
813
|
+
const schema = {
|
|
814
|
+
data: {
|
|
815
|
+
layout: [
|
|
816
|
+
{ key: 'a_position', kind: 'vec2' }, // 2 * 4 = 8 bytes
|
|
817
|
+
{ key: 'a_color', kind: 'vec4', format: 'uint8', normalized: true }, // 4 * 1 = 4 bytes
|
|
818
|
+
{ key: 'a_normal', kind: 'vec2', format: 'int16', normalized: true }, // 2 * 2 = 4 bytes
|
|
819
|
+
],
|
|
820
|
+
instanced: false,
|
|
821
|
+
},
|
|
822
|
+
} satisfies InterleavedAttributeSchema
|
|
691
823
|
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
824
|
+
const interleavedAttributes = interleavedAttributeView(gl, program, schema)
|
|
825
|
+
interleavedAttributes.data.bind()
|
|
826
|
+
|
|
827
|
+
const calls = (gl.vertexAttribPointer as any).mock.calls
|
|
828
|
+
const stride = 16 // 8 + 4 + 4
|
|
829
|
+
|
|
830
|
+
// a_position: float32, not normalized
|
|
831
|
+
expect(calls[0][2]).toBe(gl.FLOAT)
|
|
832
|
+
expect(calls[0][3]).toBe(false)
|
|
833
|
+
expect(calls[0][4]).toBe(stride)
|
|
834
|
+
expect(calls[0][5]).toBe(0)
|
|
835
|
+
|
|
836
|
+
// a_color: uint8, normalized
|
|
837
|
+
expect(calls[1][2]).toBe(gl.UNSIGNED_BYTE)
|
|
838
|
+
expect(calls[1][3]).toBe(true)
|
|
839
|
+
expect(calls[1][4]).toBe(stride)
|
|
840
|
+
expect(calls[1][5]).toBe(8)
|
|
841
|
+
|
|
842
|
+
// a_normal: int16, normalized
|
|
843
|
+
expect(calls[2][2]).toBe(gl.SHORT)
|
|
844
|
+
expect(calls[2][3]).toBe(true)
|
|
845
|
+
expect(calls[2][4]).toBe(stride)
|
|
846
|
+
expect(calls[2][5]).toBe(12)
|
|
696
847
|
})
|
|
697
848
|
|
|
698
849
|
it('should set buffer data', () => {
|
package/test/mocks/webgl.ts
CHANGED
|
@@ -42,6 +42,10 @@ export function createMockGL() {
|
|
|
42
42
|
DYNAMIC_DRAW: 0x88e8,
|
|
43
43
|
FLOAT: 0x1406,
|
|
44
44
|
INT: 0x1404,
|
|
45
|
+
UNSIGNED_INT: 0x1405,
|
|
46
|
+
BYTE: 0x1400,
|
|
47
|
+
SHORT: 0x1402,
|
|
48
|
+
UNSIGNED_SHORT: 0x1403,
|
|
45
49
|
UNSIGNED_BYTE: 0x1401,
|
|
46
50
|
TRIANGLES: 0x0004,
|
|
47
51
|
LINES: 0x0001,
|
|
@@ -120,6 +124,7 @@ export function createMockGL() {
|
|
|
120
124
|
|
|
121
125
|
enableVertexAttribArray: vi.fn(),
|
|
122
126
|
vertexAttribPointer: vi.fn(),
|
|
127
|
+
vertexAttribIPointer: vi.fn(),
|
|
123
128
|
vertexAttribDivisor: vi.fn(),
|
|
124
129
|
|
|
125
130
|
// Uniform methods
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils.ts","../src/index.ts"],"sourcesContent":["import type {\n AttributeKind,\n FramebufferDefinition,\n GL,\n KIND_TO_SIZE_MAP,\n KIND_TO_UNIFORM_FN_NAME_MAP,\n TextureDefinition,\n UniformKind,\n} 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/* */\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): WebGLTexture {\n const texture = gl.createTexture()\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 console.log(minFilter)\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 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 '${name}' 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, ...options }: FramebufferDefinition,\n) {\n // Create texture for the framebuffer\n texture ??= createTexture(gl, options)\n\n // Create framebuffer\n const framebuffer = assertedNotNullish(\n gl.createFramebuffer(),\n `Failed to create framebuffer: ${name}`,\n )\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 return {\n texture,\n framebuffer,\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 { getInstancedArrays, getVertexArrayObject } from './gl'\nimport type {\n AttributeMethods,\n AttributeSchema,\n AttributeView,\n BufferSchema,\n BufferView,\n GL,\n UniformView as InferUniformView,\n InterleavedAttributeMethods,\n InterleavedAttributeSchema,\n InterleavedAttributeView,\n UniformSchema,\n View,\n ViewOptions,\n ViewSchema,\n} from './types'\nimport {\n isSamplerKind,\n kindToUniformFnName,\n isMatKind,\n assertedNotNullish,\n kindToSize,\n forEachObject,\n} from './utils'\nimport { createUpsertMap, mapObject } from './utils'\nexport * from './types'\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 options?: ViewOptions,\n): View<TSchema> {\n return {\n uniforms: !schema.uniforms ? undefined : uniformView(gl, program, schema.uniforms),\n attributes: !schema.attributes\n ? undefined\n : attributeView(gl, program, schema.attributes, options),\n interleavedAttributes: !schema.interleavedAttributes\n ? undefined\n : interleavedAttributeView(gl, program, schema.interleavedAttributes, options),\n buffers: !schema.buffers ? undefined : bufferView(gl, schema.buffers),\n } as View<TSchema>\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\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 type: 'FLOAT' | 'INT',\n instanced?: boolean,\n) {\n gl.enableVertexAttribArray(location)\n gl.vertexAttribPointer(location, size, gl[type], false, stride, offset)\n\n if (instanced) {\n // Get instanced-arrays-feature: extension if webgl, gl if webgl2\n assertedNotNullish(getInstancedArrays(gl)).vertexAttribDivisor(location, 1)\n }\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, instanced, buffer = assertedNotNullish(gl.createBuffer()) },\n key,\n ): AttributeMethods => {\n const name = toID(key)\n\n const location = gl.getAttribLocation(program, name)\n if (location < 0) {\n throw new Error(`Attribute '${name}' not found`)\n }\n\n const size = kindToSize(kind)\n const type = kind.startsWith('i') ? 'INT' : 'FLOAT'\n\n return {\n buffer,\n bind() {\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n handleAttribute(gl, location, size, 0, 0, type, instanced)\n },\n dispose() {\n gl.deleteBuffer(buffer)\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 }\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\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, instanced }) => {\n // Increment number to keep track of offset\n let index = 0\n\n // Calculate layout information\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 Error(`Attribute '${name}' not found`)\n }\n\n const size = kindToSize(layout.kind)\n const offset = index\n const type = layout.kind.startsWith('i') ? 'INT' : 'FLOAT'\n index += size * 4\n\n return () => handleAttribute(gl, location, size, stride, offset, type, instanced)\n })\n\n // Set stride to final index\n const stride = index\n\n // Create a buffer\n const buffer = assertedNotNullish(gl.createBuffer())\n\n // Create VAO to cache attribute state\n let vao: { unbind(): void; bind(): void; dispose(): void } | undefined = undefined\n\n // Get VAO-feature: extension if webgl1, gl if webgl2\n const feature = getVertexArrayObject(gl)\n if (feature) {\n const vertexArray = feature.createVertexArray()\n feature.bindVertexArray(vertexArray)\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n for (const handle of handles) {\n handle()\n }\n feature.bindVertexArray(null)\n vao = {\n unbind() {\n feature.bindVertexArray(null)\n },\n bind() {\n feature.bindVertexArray(vertexArray)\n },\n dispose() {\n feature.deleteVertexArray(vertexArray)\n },\n }\n }\n\n return {\n bind() {\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n if (vao) {\n vao.bind()\n } else {\n // Fallback: manual attribute setup\n for (const handle of handles) {\n handle()\n }\n }\n },\n unbind() {\n if (vao) {\n vao.unbind()\n }\n },\n dispose() {\n gl.deleteBuffer(buffer)\n if (vao) {\n vao.dispose()\n }\n },\n set(value, usage = 'STATIC_DRAW') {\n if (vao) {\n vao.bind()\n }\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n gl.bufferData(gl.ARRAY_BUFFER, value, gl[usage])\n if (vao) {\n vao.unbind()\n }\n },\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 = assertedNotNullish(gl.createBuffer())\n return {\n bind() {\n gl.bindBuffer(gl[target], buffer)\n },\n dispose() {\n gl.deleteBuffer(buffer)\n },\n set(data: Float32Array) {\n gl.bindBuffer(gl[target], buffer)\n gl.bufferData(gl[target], data, gl[usage])\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":["index","value","name","location","index","layout"]}
|