@bigmistqke/view.gl 0.1.19 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,6 +4,7 @@ import {
4
4
  bufferView,
5
5
  interleavedAttributeView,
6
6
  uniformView,
7
+ vaoView,
7
8
  view,
8
9
  } from '../src/index'
9
10
  import type {
@@ -83,10 +84,11 @@ describe('view', () => {
83
84
 
84
85
  expect(result.interleavedAttributes).toBeDefined()
85
86
  expect(result.interleavedAttributes!.data).toBeDefined()
86
- expect(result.interleavedAttributes!.data.bind).toBeInstanceOf(Function)
87
- expect(result.interleavedAttributes!.data.unbind).toBeInstanceOf(Function)
87
+ expect(result.interleavedAttributes!.data.buffer.bind).toBeInstanceOf(Function)
88
+ expect(result.interleavedAttributes!.data.buffer.perInstance.bind).toBeInstanceOf(Function)
89
+ expect(result.interleavedAttributes!.data.constant.bind).toBeInstanceOf(Function)
88
90
  expect(result.interleavedAttributes!.data.dispose).toBeInstanceOf(Function)
89
- expect(result.interleavedAttributes!.data.set).toBeInstanceOf(Function)
91
+ expect(result.interleavedAttributes!.data.buffer.set).toBeInstanceOf(Function)
90
92
  })
91
93
 
92
94
  it('should create a view with buffers', () => {
@@ -166,7 +168,7 @@ describe('view', () => {
166
168
  expect(result.attributes![a_position_symbol].bind).toBeInstanceOf(Function)
167
169
 
168
170
  expect(result.interleavedAttributes![data_symbol]).toBeDefined()
169
- expect(result.interleavedAttributes![data_symbol].bind).toBeInstanceOf(Function)
171
+ expect(result.interleavedAttributes![data_symbol].buffer.bind).toBeInstanceOf(Function)
170
172
 
171
173
  expect(result.buffers![vertices_symbol]).toBeDefined()
172
174
  expect(result.buffers![vertices_symbol].bind).toBeInstanceOf(Function)
@@ -778,10 +780,10 @@ describe('interleavedAttributeView', () => {
778
780
  const interleavedAttributes = interleavedAttributeView(gl, program, schema)
779
781
 
780
782
  expect(interleavedAttributes.vertexData).toBeDefined()
781
- expect(interleavedAttributes.vertexData.bind).toBeInstanceOf(Function)
782
- expect(interleavedAttributes.vertexData.unbind).toBeInstanceOf(Function)
783
+ expect(interleavedAttributes.vertexData.buffer.bind).toBeInstanceOf(Function)
784
+ expect(interleavedAttributes.vertexData.buffer.perInstance.bind).toBeInstanceOf(Function)
783
785
  expect(interleavedAttributes.vertexData.dispose).toBeInstanceOf(Function)
784
- expect(interleavedAttributes.vertexData.set).toBeInstanceOf(Function)
786
+ expect(interleavedAttributes.vertexData.buffer.set).toBeInstanceOf(Function)
785
787
  })
786
788
 
787
789
  it('should return a disposer from bind that restores the default vertex array', () => {
@@ -804,7 +806,7 @@ describe('interleavedAttributeView', () => {
804
806
  const previous = { id: 'previously-bound-vao' }
805
807
  ;(gl.getParameter as any).mockReturnValue(previous)
806
808
 
807
- const unbind = interleavedAttributes.vertexData.bind()
809
+ const unbind = interleavedAttributes.vertexData.buffer.bind()
808
810
  expect(unbind).toBeInstanceOf(Function)
809
811
 
810
812
  ;(gl.bindVertexArray as any).mockClear()
@@ -826,7 +828,7 @@ describe('interleavedAttributeView', () => {
826
828
 
827
829
  const interleavedAttributes = interleavedAttributeView(gl, program, schema)
828
830
 
829
- interleavedAttributes.vertexData.bind()
831
+ interleavedAttributes.vertexData.buffer.bind()
830
832
 
831
833
  // Check vertexAttribPointer calls
832
834
  const calls = (gl.vertexAttribPointer as any).mock.calls
@@ -850,23 +852,28 @@ describe('interleavedAttributeView', () => {
850
852
  expect(calls[2][5]).toBe(24) // offset
851
853
  })
852
854
 
853
- it('should handle instanced interleaved attributes', () => {
855
+ it('steps per instance or per vertex from the same buffer', () => {
856
+ // A divisor is a property of the draw, not of the data, so it is chosen
857
+ // here rather than declared in the schema.
854
858
  const schema = {
855
859
  instanceData: {
856
860
  layout: [
857
861
  { key: 'a_instancePos', kind: 'vec3' },
858
862
  { key: 'a_instanceScale', kind: 'float' },
859
863
  ],
860
- instanced: true,
861
864
  },
862
865
  } satisfies InterleavedAttributeSchema
863
866
 
864
867
  const interleavedAttributes = interleavedAttributeView(gl, program, schema)
865
868
 
866
- interleavedAttributes.instanceData.bind()
867
-
869
+ interleavedAttributes.instanceData.buffer.perInstance.bind()
868
870
  expect(gl.vertexAttribDivisor).toHaveBeenCalledTimes(2)
869
871
  expect(gl.vertexAttribDivisor).toHaveBeenCalledWith(expect.any(Number), 1)
872
+
873
+ vi.mocked(gl.vertexAttribDivisor).mockClear()
874
+
875
+ interleavedAttributes.instanceData.buffer.bind()
876
+ expect(gl.vertexAttribDivisor).toHaveBeenCalledWith(expect.any(Number), 0)
870
877
  })
871
878
 
872
879
  it('should handle integer attributes in layout', () => {
@@ -883,7 +890,7 @@ describe('interleavedAttributeView', () => {
883
890
 
884
891
  const interleavedAttributes = interleavedAttributeView(gl, program, schema)
885
892
 
886
- interleavedAttributes.data.bind()
893
+ interleavedAttributes.data.buffer.bind()
887
894
 
888
895
  const floatCalls = (gl.vertexAttribPointer as any).mock.calls
889
896
  const intCalls = (gl.vertexAttribIPointer as any).mock.calls
@@ -908,7 +915,7 @@ describe('interleavedAttributeView', () => {
908
915
  } satisfies InterleavedAttributeSchema
909
916
 
910
917
  const interleavedAttributes = interleavedAttributeView(gl, program, schema)
911
- interleavedAttributes.data.bind()
918
+ interleavedAttributes.data.buffer.bind()
912
919
 
913
920
  const calls = (gl.vertexAttribPointer as any).mock.calls
914
921
  const stride = 16 // 8 + 4 + 4
@@ -961,25 +968,13 @@ describe('interleavedAttributeView', () => {
961
968
  1, // color
962
969
  ])
963
970
 
964
- interleavedAttributes.vertexData.set(data)
971
+ interleavedAttributes.vertexData.buffer.set(data)
965
972
  expect(gl.bufferData).toHaveBeenCalledWith(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW)
966
973
  })
967
974
 
968
- it('should use VAO when available', () => {
969
- const vertexArray = { id: 1 }
970
- const vaoExt = {
971
- createVertexArrayOES: vi.fn(() => vertexArray),
972
- bindVertexArrayOES: vi.fn(),
973
- deleteVertexArrayOES: vi.fn(),
974
- }
975
-
976
- // Override the getExtension method for this test
977
- const originalGetExtension = gl.getExtension
978
- gl.getExtension = vi.fn((name: string) => {
979
- if (name === 'OES_vertex_array_object') return vaoExt as any
980
- return originalGetExtension.call(gl, name)
981
- }) as any
982
-
975
+ it('does not create a vertex array of its own', () => {
976
+ // A layout used to make one here, which is why the other participants in a
977
+ // draw had to be bound after it to be included. Arrays are vao()'s job.
983
978
  const schema = {
984
979
  vertexData: {
985
980
  layout: [{ key: 'a_position', kind: 'vec2' }],
@@ -987,26 +982,9 @@ describe('interleavedAttributeView', () => {
987
982
  },
988
983
  } satisfies InterleavedAttributeSchema
989
984
 
990
- const interleavedAttributes = interleavedAttributeView(gl as any, program, schema)
991
-
992
- expect(vaoExt.createVertexArrayOES).toHaveBeenCalled()
993
- expect(vaoExt.bindVertexArrayOES).toHaveBeenCalledWith(vertexArray)
994
- expect(vaoExt.bindVertexArrayOES).toHaveBeenCalledWith(null) // unbind after setup
995
-
996
- // Test bind
997
- interleavedAttributes.vertexData.bind()
998
- expect(vaoExt.bindVertexArrayOES).toHaveBeenCalledWith(vertexArray)
999
-
1000
- // Test unbind
1001
- interleavedAttributes.vertexData.unbind()
1002
- expect(vaoExt.bindVertexArrayOES).toHaveBeenCalledWith(null)
1003
-
1004
- // Test dispose
1005
- interleavedAttributes.vertexData.dispose()
1006
- expect(vaoExt.deleteVertexArrayOES).toHaveBeenCalledWith(vertexArray)
985
+ interleavedAttributeView(gl as any, program, schema)
1007
986
 
1008
- // Restore original method
1009
- gl.getExtension = originalGetExtension
987
+ expect(gl.createVertexArray).not.toHaveBeenCalled()
1010
988
  })
1011
989
 
1012
990
  it('should dispose buffers', () => {
@@ -1085,13 +1063,13 @@ describe('interleavedAttributeView', () => {
1085
1063
  const interleavedAttributes = interleavedAttributeView(gl, program, schema)
1086
1064
 
1087
1065
  expect(interleavedAttributes[data_symbol]).toBeDefined()
1088
- expect(interleavedAttributes[data_symbol].bind).toBeInstanceOf(Function)
1089
- expect(interleavedAttributes[data_symbol].unbind).toBeInstanceOf(Function)
1066
+ expect(interleavedAttributes[data_symbol].buffer.bind).toBeInstanceOf(Function)
1067
+ expect(interleavedAttributes[data_symbol].buffer.perInstance.bind).toBeInstanceOf(Function)
1090
1068
  expect(interleavedAttributes[data_symbol].dispose).toBeInstanceOf(Function)
1091
- expect(interleavedAttributes[data_symbol].set).toBeInstanceOf(Function)
1069
+ expect(interleavedAttributes[data_symbol].buffer.set).toBeInstanceOf(Function)
1092
1070
 
1093
1071
  // Test binding
1094
- interleavedAttributes[data_symbol].bind()
1072
+ interleavedAttributes[data_symbol].buffer.bind()
1095
1073
 
1096
1074
  // Should bind buffer and set up attributes
1097
1075
  expect(gl.bindBuffer).toHaveBeenCalled()
@@ -1119,7 +1097,7 @@ describe('interleavedAttributeView', () => {
1119
1097
  expect(interleavedAttributes[vertexData]).toBeDefined()
1120
1098
 
1121
1099
  // Test that it correctly calculates stride
1122
- interleavedAttributes[vertexData].bind()
1100
+ interleavedAttributes[vertexData].buffer.bind()
1123
1101
 
1124
1102
  const calls = (gl.vertexAttribPointer as any).mock.calls
1125
1103
  // All calls should have the same stride (3+3+2)*4 = 32 bytes
@@ -1272,3 +1250,198 @@ describe('bufferView', () => {
1272
1250
  expect(gl.bufferData).toHaveBeenCalledWith(gl.ARRAY_BUFFER, data, gl.DYNAMIC_DRAW)
1273
1251
  })
1274
1252
  })
1253
+
1254
+ describe('vaoView', () => {
1255
+ let gl: WebGL2RenderingContext
1256
+ let program: WebGLProgram
1257
+ beforeEach(() => {
1258
+ const mock = createMockCanvas()
1259
+ gl = mock.gl
1260
+ program = gl.createProgram()!
1261
+ })
1262
+
1263
+ function participants() {
1264
+ const attributes = attributeView(gl as any, program, {
1265
+ a_corner: { kind: 'vec2' },
1266
+ } satisfies AttributeSchema)
1267
+ const interleaved = interleavedAttributeView(gl as any, program, {
1268
+ a_instance: {
1269
+ layout: [{ key: 'a_position', kind: 'vec2' }],
1270
+ },
1271
+ } satisfies InterleavedAttributeSchema)
1272
+ const buffers = bufferView(gl as any, {
1273
+ b_index: { target: 'ELEMENT_ARRAY_BUFFER' },
1274
+ } satisfies BufferSchema)
1275
+ return { attributes, interleaved, buffers }
1276
+ }
1277
+
1278
+ it('writes every participant into one array, at construction', () => {
1279
+ const { attributes, interleaved, buffers } = participants()
1280
+ const vertexArray = { id: 'vao' } as unknown as WebGLVertexArrayObject
1281
+ gl.createVertexArray = vi.fn(() => vertexArray) as any
1282
+
1283
+ const calls: string[] = []
1284
+ gl.bindVertexArray = vi.fn(v => calls.push(v === vertexArray ? 'bind' : 'unbind')) as any
1285
+ gl.vertexAttribPointer = vi.fn(() => calls.push('pointer')) as any
1286
+ gl.bindBuffer = vi.fn((target: number) =>
1287
+ calls.push(target === gl.ELEMENT_ARRAY_BUFFER ? 'indices' : 'array'),
1288
+ ) as any
1289
+
1290
+ vaoView(gl as any, [
1291
+ attributes.a_corner,
1292
+ interleaved.a_instance.buffer.perInstance,
1293
+ buffers.b_index,
1294
+ ])
1295
+
1296
+ // Every participant's state is written while the new array is bound —
1297
+ // that is the whole contract, and what call order used to decide.
1298
+ const bound = calls.indexOf('bind')
1299
+ const unbound = calls.lastIndexOf('unbind')
1300
+ expect(bound).toBeGreaterThanOrEqual(0)
1301
+ expect(calls.indexOf('pointer')).toBeGreaterThan(bound)
1302
+ expect(calls.indexOf('indices')).toBeGreaterThan(bound)
1303
+ expect(unbound).toBeGreaterThan(calls.lastIndexOf('indices'))
1304
+ })
1305
+
1306
+ it('binds and restores, and disposes the array', () => {
1307
+ const { attributes } = participants()
1308
+ const vertexArray = { id: 'vao' } as unknown as WebGLVertexArrayObject
1309
+ const foreign = { id: 'foreign' } as unknown as WebGLVertexArrayObject
1310
+ // Swapped before the first getVertexArrayObject call: on a context without
1311
+ // native vertex arrays the extension wrapper binds these once, up front.
1312
+ gl.createVertexArray = vi.fn(() => vertexArray) as any
1313
+ const bindVertexArray = vi.fn()
1314
+ gl.bindVertexArray = bindVertexArray as any
1315
+ gl.getParameter = vi.fn(() => foreign) as any
1316
+
1317
+ const vao = vaoView(gl as any, [attributes.a_corner])
1318
+ bindVertexArray.mockClear()
1319
+
1320
+ const restore = vao.bind()
1321
+ expect(bindVertexArray).toHaveBeenLastCalledWith(vertexArray)
1322
+ restore()
1323
+ expect(bindVertexArray).toHaveBeenLastCalledWith(foreign)
1324
+
1325
+ vao.dispose()
1326
+ expect(gl.deleteVertexArray).toHaveBeenCalledWith(vertexArray)
1327
+ })
1328
+
1329
+ it('re-applies each participant per bind when the context has no vertex arrays', () => {
1330
+ // WebGL1 without OES_vertex_array_object: nowhere to keep the state, so
1331
+ // the array is emulated by doing the work again on every bind.
1332
+ const mock = createMockGL()
1333
+ const gl1 = mock as any
1334
+ gl1.createVertexArray = undefined
1335
+ gl1.getExtension = vi.fn(() => null)
1336
+ const program1 = gl1.createProgram()
1337
+
1338
+ const attributes = attributeView(gl1, program1, {
1339
+ a_corner: { kind: 'vec2' },
1340
+ } satisfies AttributeSchema)
1341
+
1342
+ const vao = vaoView(gl1, [attributes.a_corner])
1343
+ expect(gl1.vertexAttribPointer).not.toHaveBeenCalled()
1344
+
1345
+ vao.bind()
1346
+ expect(gl1.vertexAttribPointer).toHaveBeenCalledTimes(1)
1347
+ vao.bind()
1348
+ expect(gl1.vertexAttribPointer).toHaveBeenCalledTimes(2)
1349
+ })
1350
+ })
1351
+
1352
+ describe('binding a participant on its own', () => {
1353
+ let gl: WebGL2RenderingContext
1354
+ let program: WebGLProgram
1355
+ beforeEach(() => {
1356
+ const mock = createMockCanvas()
1357
+ gl = mock.gl
1358
+ program = gl.createProgram()!
1359
+ })
1360
+
1361
+ it('targets the default vertex array, not whichever one is current', () => {
1362
+ // The pointer calls name no destination. Without binding first, this would
1363
+ // edit a caller's array — and an array keeps what it is given, so the
1364
+ // damage would outlive the call.
1365
+ const foreign = { id: 'foreign' } as unknown as WebGLVertexArrayObject
1366
+ gl.getParameter = vi.fn(() => foreign) as any
1367
+ const bindVertexArray = vi.fn()
1368
+ gl.bindVertexArray = bindVertexArray as any
1369
+
1370
+ const attributes = attributeView(gl as any, program, {
1371
+ a_corner: { kind: 'vec2' },
1372
+ } satisfies AttributeSchema)
1373
+
1374
+ const restore = attributes.a_corner.bind()
1375
+ expect(bindVertexArray).toHaveBeenCalledWith(null)
1376
+ restore()
1377
+ expect(bindVertexArray).toHaveBeenLastCalledWith(foreign)
1378
+ })
1379
+ })
1380
+
1381
+ describe('the constant source', () => {
1382
+ let gl: WebGL2RenderingContext
1383
+ let program: WebGLProgram
1384
+ beforeEach(() => {
1385
+ const mock = createMockCanvas()
1386
+ gl = mock.gl
1387
+ program = gl.createProgram()!
1388
+ })
1389
+
1390
+ const schema = {
1391
+ a_instance: {
1392
+ layout: [
1393
+ { key: 'a_pos', kind: 'vec2' },
1394
+ { key: 'a_size', kind: 'float' },
1395
+ ],
1396
+ },
1397
+ } satisfies InterleavedAttributeSchema
1398
+
1399
+ it('gives the layout per-key setters, like a uniform', () => {
1400
+ const { a_instance } = interleavedAttributeView(gl as any, program, schema)
1401
+
1402
+ expect(a_instance.constant.a_pos.set).toBeInstanceOf(Function)
1403
+ expect(a_instance.constant.a_size.set).toBeInstanceOf(Function)
1404
+ })
1405
+
1406
+ it('disables the arrays, so the attributes read the constants', () => {
1407
+ const { a_instance } = interleavedAttributeView(gl as any, program, schema)
1408
+
1409
+ a_instance.constant.applyToVertexArray()
1410
+
1411
+ expect(gl.disableVertexAttribArray).toHaveBeenCalledTimes(2)
1412
+ })
1413
+
1414
+ it('writes the values on every bind, not once into the array', () => {
1415
+ // The enable flag is vertex-array state; the values are context state, and
1416
+ // no array can keep them. Applying them once at construction would leave a
1417
+ // later draw showing whatever the previous one set.
1418
+ const { a_instance } = interleavedAttributeView(gl as any, program, schema)
1419
+ a_instance.constant.a_pos.set(1, 2)
1420
+ a_instance.constant.a_size.set(4)
1421
+
1422
+ const vao = vaoView(gl as any, [a_instance.constant])
1423
+ expect(gl.vertexAttrib2f).not.toHaveBeenCalled()
1424
+
1425
+ vao.bind()
1426
+ expect(gl.vertexAttrib2f).toHaveBeenCalledWith(expect.any(Number), 1, 2)
1427
+ expect(gl.vertexAttrib1f).toHaveBeenCalledWith(expect.any(Number), 4)
1428
+
1429
+ a_instance.constant.a_pos.set(7, 8)
1430
+ vao.bind()
1431
+ expect(gl.vertexAttrib2f).toHaveBeenLastCalledWith(expect.any(Number), 7, 8)
1432
+ })
1433
+
1434
+ it('refuses a kind vertexAttrib* cannot express, when asked for one', () => {
1435
+ // A hard limit of the API, not a choice: vertexAttrib* takes at most four
1436
+ // floats and has no matrix form. The buffer source handles it fine, so the
1437
+ // complaint waits until someone reaches for a constant.
1438
+ const matrix = {
1439
+ a_instance: { layout: [{ key: 'a_model', kind: 'mat4' }] },
1440
+ } satisfies InterleavedAttributeSchema
1441
+
1442
+ const { a_instance } = interleavedAttributeView(gl as any, program, matrix)
1443
+
1444
+ expect(() => a_instance.buffer.bind()).not.toThrow()
1445
+ expect(() => a_instance.constant).toThrow(/cannot be a constant attribute/)
1446
+ })
1447
+ })
@@ -134,6 +134,12 @@ export function createMockGL() {
134
134
  // which tests override where the previous value is what is under test.
135
135
  getParameter: vi.fn(() => null),
136
136
  getVertexAttrib: vi.fn(() => 0),
137
+ disableVertexAttribArray: vi.fn(),
138
+ vertexAttrib1f: vi.fn(),
139
+ vertexAttrib2f: vi.fn(),
140
+ vertexAttrib3f: vi.fn(),
141
+ vertexAttrib4f: vi.fn(),
142
+ VERTEX_ATTRIB_ARRAY_ENABLED: 0x8622,
137
143
 
138
144
  // Uniform methods
139
145
  getUniformLocation: vi.fn((program: MockWebGLProgram, name: string) => {
@@ -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 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 // Always stated, never inherited: the divisor belongs to the location rather\n // than to the program, so a location left at 1 by an earlier instanced\n // attribute would feed one value to every vertex here.\n // Get instanced-arrays-feature: extension if webgl, gl if webgl2\n const instancedArrays = getInstancedArrays(gl)\n if (instanced) {\n assertedNotNullish(instancedArrays).vertexAttribDivisor(location, 1)\n } else if (instancedArrays) {\n instancedArrays.vertexAttribDivisor(location, 0)\n }\n}\n\n// Same enum in webgl2 and in the webgl1 extensions, which expose no constants\nconst VERTEX_ATTRIB_ARRAY_DIVISOR = 0x88fe\nconst VERTEX_ARRAY_BINDING = 0x85b5\n\n// Reads the divisor currently attached to a location, 0 where instancing is\n// unavailable and nothing can have set one\nfunction readDivisor(gl: GL, location: number): number {\n return getInstancedArrays(gl)\n ? (gl.getVertexAttrib(location, VERTEX_ATTRIB_ARRAY_DIVISOR) as number)\n : 0\n}\n\n// Wraps a restore so it runs once: a disposer is per bind() and undoing twice\n// would put back state a later bind() is relying on\nfunction once(restore: () => void): () => void {\n let done = false\n return () => {\n if (done) return\n done = true\n restore()\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 {\n kind,\n format,\n normalized = false,\n instanced,\n buffer = assertedNotNullish(gl.createBuffer()),\n },\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 // Snapshot before the change, restore in the disposer\n const previousDivisor = readDivisor(gl, location)\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n handleAttribute(gl, location, size, 0, 0, glType, isIntKind, normalized, instanced)\n return once(() => {\n getInstancedArrays(gl)?.vertexAttribDivisor(location, previousDivisor)\n })\n },\n 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 locations: number[] = []\n const handles = layout.map(layout => {\n const name = toID(layout.key)\n\n const location = gl.getAttribLocation(program, name)\n\n if (location < 0) {\n throw new Error(`Attribute '${name}' not found`)\n }\n\n locations.push(location)\n\n const size = kindToSize(layout.kind)\n const offset = index\n const resolvedFormat = layout.format ?? defaultFormat(layout.kind)\n const glType = FORMAT_TO_GL_TYPE[resolvedFormat]\n const isIntKind = layout.kind.startsWith('i') || layout.kind.startsWith('u')\n const normalized = layout.normalized ?? false\n index += size * FORMAT_BYTE_SIZE[resolvedFormat]\n\n return () =>\n handleAttribute(\n gl,\n location,\n size,\n stride,\n offset,\n glType,\n isIntKind,\n normalized,\n instanced,\n )\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 // A selected vertex array stays selected for every later draw, which would\n // then write its own attributes into this one\n const unbind = () => {\n if (vao) {\n vao.unbind()\n }\n }\n\n return {\n bind() {\n // Snapshot before the change, restore in the disposer\n const previousVertexArray = feature\n ? (gl.getParameter(VERTEX_ARRAY_BINDING) as WebGLVertexArrayObject | null)\n : null\n const previousDivisors = vao\n ? []\n : locations.map(location => [location, readDivisor(gl, location)] as const)\n\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 return once(() => {\n if (feature) {\n feature.bindVertexArray(previousVertexArray)\n }\n // Without a vertex array the manual setup wrote divisors straight to\n // the locations, so they are ours to put back\n if (!vao) {\n const instancedArrays = getInstancedArrays(gl)\n previousDivisors.forEach(([location, divisor]) => {\n instancedArrays?.vertexAttribDivisor(location, divisor)\n })\n }\n })\n },\n unbind,\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\n return {\n bind() {\n // Snapshot before the change, restore in the disposer. Restoring the\n // previous buffer rather than null matters for ELEMENT_ARRAY_BUFFER,\n // whose binding is recorded in the bound vertex array: clearing it\n // would strip the index buffer from an array the caller may not own.\n const previousBuffer = gl.getParameter(gl[`${target}_BINDING`]) as WebGLBuffer | null\n gl.bindBuffer(gl[target], buffer)\n return once(() => {\n gl.bindBuffer(gl[target], previousBuffer)\n })\n },\n 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"]}