@bigmistqke/view.gl 0.1.17 → 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.
@@ -164,13 +164,36 @@ function uniformView(gl, program, schema) {
164
164
  };
165
165
  });
166
166
  }
167
- function handleAttribute(gl, location, size, stride, offset, type, instanced) {
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
- if (type === "INT" || type === "UNSIGNED_INT") {
192
+ if (isIntegerKind) {
170
193
  ;
171
- gl.vertexAttribIPointer(location, size, gl[type], stride, offset);
194
+ gl.vertexAttribIPointer(location, size, gl[glType], stride, offset);
172
195
  } else {
173
- gl.vertexAttribPointer(location, size, gl[type], false, stride, offset);
196
+ gl.vertexAttribPointer(location, size, gl[glType], normalized, stride, offset);
174
197
  }
175
198
  if (instanced) {
176
199
  assertedNotNullish(getInstancedArrays(gl)).vertexAttribDivisor(location, 1);
@@ -179,19 +202,21 @@ function handleAttribute(gl, location, size, stride, offset, type, instanced) {
179
202
  function attributeView(gl, program, schema, { signal } = {}) {
180
203
  const attributes = mapObject(
181
204
  schema,
182
- ({ kind, instanced, buffer = assertedNotNullish(gl.createBuffer()) }, key) => {
205
+ ({ kind, format, normalized = false, instanced, buffer = assertedNotNullish(gl.createBuffer()) }, key) => {
183
206
  const name2 = toID(key);
184
207
  const location = gl.getAttribLocation(program, name2);
185
208
  if (location < 0) {
186
209
  throw new Error(`Attribute '${name2}' not found`);
187
210
  }
188
211
  const size = kindToSize(kind);
189
- const type = kind.startsWith("u") ? "UNSIGNED_INT" : kind.startsWith("i") ? "INT" : "FLOAT";
212
+ const resolvedFormat = format ?? defaultFormat(kind);
213
+ const glType = FORMAT_TO_GL_TYPE[resolvedFormat];
214
+ const isIntKind = kind.startsWith("i") || kind.startsWith("u");
190
215
  return {
191
216
  buffer,
192
217
  bind() {
193
218
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
194
- handleAttribute(gl, location, size, 0, 0, type, instanced);
219
+ handleAttribute(gl, location, size, 0, 0, glType, isIntKind, normalized, instanced);
195
220
  },
196
221
  dispose() {
197
222
  gl.deleteBuffer(buffer);
@@ -220,9 +245,12 @@ function interleavedAttributeView(gl, program, schema, { signal } = {}) {
220
245
  }
221
246
  const size = kindToSize(layout2.kind);
222
247
  const offset = index2;
223
- const type = layout2.kind.startsWith("u") ? "UNSIGNED_INT" : layout2.kind.startsWith("i") ? "INT" : "FLOAT";
224
- index2 += size * 4;
225
- return () => handleAttribute(gl, location, size, stride, offset, type, instanced);
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);
226
254
  });
227
255
  const stride = index2;
228
256
  const buffer = assertedNotNullish(gl.createBuffer());
@@ -318,4 +346,4 @@ export {
318
346
  interleavedAttributeView,
319
347
  bufferView
320
348
  };
321
- //# sourceMappingURL=chunk-EBMXKCOV.mjs.map
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-lm9fTTy8.mjs';
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-lm9fTTy8.mjs';
2
- export { y as AttributeDefinition, x as AttributeKind, z as AttributeMethods, w as AttributeShortHand, a5 as AttributeToken, a6 as AttributeTokenFn, F as BufferDefinition, H as BufferMethods, ad as CompileResult, ab as FlattenSlots, Y as Format, L as Framebuffer, J as FramebufferDefinition, a2 as GLSL, a0 as GLSLResult, a1 as GLSLSlot, aa as GLSLSlotsToSchema, a8 as GLSLToSchema, a9 as GLSLToView, g as GLTarget, l as GLTextureFilter, j as GLTextureFormat, i as GLTextureTarget, k as GLTextureType, m as GLTextureWrap, h as GLUsage, a7 as InterleaveToken, D as InterleavedAttributeDefinition, C as InterleavedAttributeLayout, E as InterleavedAttributeMethods, X as InternalFormat, n as KIND_TO_SIZE_MAP, K as KIND_TO_UNIFORM_FN_NAME_MAP, ac as MergeGLSLSchema, Z as PixelType, _ as TexImage2DOptions, T as TextureDefinition, O as TextureMethods, Q as TextureParameterName, S as TextureParameterValue, W as TextureParameters, N as TextureSchema, M as TextureTarget, P as TextureView, t as UniformArrayMethods, r as UniformDefinition, s as UniformElementMethods, o as UniformFnName, p as UniformKind, q as UniformKindMap, u as UniformMethods, a3 as UniformToken, a4 as UniformTokenFn, v as UniformValue, $ as ViewSchemaPartial } from './types-lm9fTTy8.mjs';
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
@@ -5,7 +5,7 @@ import {
5
5
  toID,
6
6
  uniformView,
7
7
  view
8
- } from "./chunk-EBMXKCOV.mjs";
8
+ } from "./chunk-CLMGHUTT.mjs";
9
9
  import "./chunk-WSNE4JVQ.mjs";
10
10
  export {
11
11
  attributeView,
package/dist/tag.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a1 as GLSLSlot, a2 as GLSL, a4 as UniformTokenFn, a6 as AttributeTokenFn, a5 as AttributeToken, x as AttributeKind, y as AttributeDefinition, a7 as InterleaveToken, $ as ViewSchemaPartial, ad as CompileResult, ae as Prettify, a8 as GLSLToSchema, G as GL } from './types-lm9fTTy8.mjs';
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
@@ -2,7 +2,7 @@ import {
2
2
  createUpsertMap,
3
3
  toID,
4
4
  view
5
- } from "./chunk-EBMXKCOV.mjs";
5
+ } from "./chunk-CLMGHUTT.mjs";
6
6
  import {
7
7
  createProgram
8
8
  } from "./chunk-WSNE4JVQ.mjs";
@@ -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
- interface AttributeMethods<T = AttributeKind> {
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: Float32Array, usage?: GLUsage): {
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]['kind']>>;
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 { ViewSchemaPartial as $, AttributeSchema as A, BufferSchema as B, InterleavedAttributeLayout as C, InterleavedAttributeDefinition as D, InterleavedAttributeMethods as E, BufferDefinition as F, GL as G, BufferMethods as H, InterleavedAttributeSchema as I, FramebufferDefinition as J, KIND_TO_UNIFORM_FN_NAME_MAP as K, Framebuffer as L, TextureTarget as M, TextureSchema as N, TextureMethods as O, TextureView as P, TextureParameterName as Q, RemoveSuffix as R, TextureParameterValue as S, TextureDefinition as T, UniformSchema as U, ViewSchema as V, TextureParameters as W, InternalFormat as X, Format as Y, PixelType as Z, TexImage2DOptions as _, ViewOptions as a, GLSLResult as a0, GLSLSlot as a1, GLSL as a2, UniformToken as a3, UniformTokenFn as a4, AttributeToken as a5, AttributeTokenFn as a6, InterleaveToken as a7, GLSLToSchema as a8, GLSLToView as a9, GLSLSlotsToSchema as aa, FlattenSlots as ab, MergeGLSLSchema as ac, CompileResult as ad, Prettify as ae, 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, AttributeDefinition as y, AttributeMethods as z };
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bigmistqke/view.gl",
3
- "version": "0.1.17",
3
+ "version": "0.1.18",
4
4
  "description": "👀 Utilities for managing WebGL resources.",
5
5
  "exports": {
6
6
  ".": {
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,14 +210,16 @@ function handleAttribute(
173
210
  size: number,
174
211
  stride: number,
175
212
  offset: number,
176
- type: 'FLOAT' | 'INT' | 'UNSIGNED_INT',
213
+ glType: GLType,
214
+ isIntegerKind: boolean,
215
+ normalized: boolean,
177
216
  instanced?: boolean,
178
217
  ) {
179
218
  gl.enableVertexAttribArray(location)
180
- if (type === 'INT' || type === 'UNSIGNED_INT') {
181
- ;(gl as WebGL2RenderingContext).vertexAttribIPointer(location, size, gl[type], stride, offset)
219
+ if (isIntegerKind) {
220
+ ;(gl as WebGL2RenderingContext).vertexAttribIPointer(location, size, gl[glType], stride, offset)
182
221
  } else {
183
- gl.vertexAttribPointer(location, size, gl[type], false, stride, offset)
222
+ gl.vertexAttribPointer(location, size, gl[glType], normalized, stride, offset)
184
223
  }
185
224
 
186
225
  if (instanced) {
@@ -198,7 +237,7 @@ export function attributeView<T extends AttributeSchema>(
198
237
  const attributes = mapObject(
199
238
  schema,
200
239
  (
201
- { kind, instanced, buffer = assertedNotNullish(gl.createBuffer()) },
240
+ { kind, format, normalized = false, instanced, buffer = assertedNotNullish(gl.createBuffer()) },
202
241
  key,
203
242
  ): AttributeMethods => {
204
243
  const name = toID(key)
@@ -209,13 +248,15 @@ export function attributeView<T extends AttributeSchema>(
209
248
  }
210
249
 
211
250
  const size = kindToSize(kind)
212
- const type = kind.startsWith('u') ? 'UNSIGNED_INT' : kind.startsWith('i') ? 'INT' : 'FLOAT'
251
+ const resolvedFormat = format ?? defaultFormat(kind)
252
+ const glType = FORMAT_TO_GL_TYPE[resolvedFormat]
253
+ const isIntKind = kind.startsWith('i') || kind.startsWith('u')
213
254
 
214
255
  return {
215
256
  buffer,
216
257
  bind() {
217
258
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
218
- handleAttribute(gl, location, size, 0, 0, type, instanced)
259
+ handleAttribute(gl, location, size, 0, 0, glType, isIntKind, normalized, instanced)
219
260
  },
220
261
  dispose() {
221
262
  gl.deleteBuffer(buffer)
@@ -265,14 +306,13 @@ export function interleavedAttributeView<T extends InterleavedAttributeSchema>(
265
306
 
266
307
  const size = kindToSize(layout.kind)
267
308
  const offset = index
268
- const type = layout.kind.startsWith('u')
269
- ? 'UNSIGNED_INT'
270
- : layout.kind.startsWith('i')
271
- ? 'INT'
272
- : 'FLOAT'
273
- index += size * 4
274
-
275
- return () => handleAttribute(gl, location, size, stride, offset, type, instanced)
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]
314
+
315
+ return () => handleAttribute(gl, location, size, stride, offset, glType, isIntKind, normalized, instanced)
276
316
  })
277
317
 
278
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
- export interface AttributeMethods<T = AttributeKind> {
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: Float32Array, usage?: GLUsage): { bind(): void }
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]['kind']>>
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 {
@@ -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
  )
@@ -742,6 +809,43 @@ describe('interleavedAttributeView', () => {
742
809
  expect(intCalls[1][2]).toBe(gl.INT) // ivec2
743
810
  })
744
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
823
+
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)
847
+ })
848
+
745
849
  it('should set buffer data', () => {
746
850
  const schema = {
747
851
  vertexData: {
@@ -43,6 +43,9 @@ export function createMockGL() {
43
43
  FLOAT: 0x1406,
44
44
  INT: 0x1404,
45
45
  UNSIGNED_INT: 0x1405,
46
+ BYTE: 0x1400,
47
+ SHORT: 0x1402,
48
+ UNSIGNED_SHORT: 0x1403,
46
49
  UNSIGNED_BYTE: 0x1401,
47
50
  TRIANGLES: 0x0004,
48
51
  LINES: 0x0001,
@@ -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' | 'UNSIGNED_INT',\n instanced?: boolean,\n) {\n gl.enableVertexAttribArray(location)\n if (type === 'INT' || type === 'UNSIGNED_INT') {\n ;(gl as WebGL2RenderingContext).vertexAttribIPointer(location, size, gl[type], stride, offset)\n } else {\n gl.vertexAttribPointer(location, size, gl[type], false, 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, 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('u') ? 'UNSIGNED_INT' : 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('u')\n ? 'UNSIGNED_INT'\n : layout.kind.startsWith('i')\n ? 'INT'\n : '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"]}