@bigmistqke/view.gl 0.8.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -3
- package/dist/{chunk-BDNRC4WD.mjs → chunk-IAM2SWJK.mjs} +10 -68
- package/dist/chunk-IAM2SWJK.mjs.map +1 -0
- package/dist/{chunk-6UTWQ36A.mjs → chunk-NRCBGOZB.mjs} +43 -29
- package/dist/chunk-NRCBGOZB.mjs.map +1 -0
- package/dist/chunk-UVDTF5P3.mjs +51 -0
- package/dist/chunk-UVDTF5P3.mjs.map +1 -0
- package/dist/gl.d.mts +2 -18
- package/dist/gl.mjs +4 -7
- package/dist/index.d.mts +9 -3
- package/dist/index.mjs +4 -2
- package/dist/tag.d.mts +2 -2
- package/dist/tag.mjs +5 -3
- package/dist/tag.mjs.map +1 -1
- package/dist/{types-Cy9u5YKs.d.mts → types-Z2s1zsZz.d.mts} +24 -2
- package/package.json +1 -1
- package/src/errors.ts +9 -0
- package/src/gl.ts +0 -46
- package/src/index.ts +59 -30
- package/src/tag.ts +1 -6
- package/src/types.ts +114 -1
- package/test/index.test.ts +43 -76
- package/test/mocks/webgl.ts +4 -18
- package/dist/chunk-6UTWQ36A.mjs.map +0 -1
- package/dist/chunk-BDNRC4WD.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -6,19 +6,21 @@ import {
|
|
|
6
6
|
uniformView,
|
|
7
7
|
vaoView,
|
|
8
8
|
view
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-NRCBGOZB.mjs";
|
|
10
10
|
import {
|
|
11
11
|
AttributeNotFoundError,
|
|
12
12
|
GLCreateError,
|
|
13
|
+
InstancingUnavailableError,
|
|
13
14
|
ProgramLinkError,
|
|
14
15
|
ShaderCompileError,
|
|
15
16
|
createFramebuffer,
|
|
16
17
|
createTexture,
|
|
17
18
|
created
|
|
18
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-IAM2SWJK.mjs";
|
|
19
20
|
export {
|
|
20
21
|
AttributeNotFoundError,
|
|
21
22
|
GLCreateError,
|
|
23
|
+
InstancingUnavailableError,
|
|
22
24
|
ProgramLinkError,
|
|
23
25
|
ShaderCompileError,
|
|
24
26
|
attributeView,
|
package/dist/tag.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a9 as GLSLSlot, aa as GLSL, ac as UniformTokenFn, ae as AttributeTokenFn, ad as AttributeToken, D as AttributeKind, H as AttributeDefinition, af as InterleaveToken, a7 as ViewSchemaPartial, G as GL, al as CompileResult, am as Prettify, ag as GLSLToSchema } from './types-Z2s1zsZz.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: {
|
|
@@ -81,7 +81,7 @@ interface CompileOptions<TSchema extends ViewSchemaPartial> {
|
|
|
81
81
|
*/
|
|
82
82
|
signal?: AbortSignal;
|
|
83
83
|
}
|
|
84
|
-
declare function compile<TVertex extends GLSL, TFragment extends GLSL, TSchema extends ViewSchemaPartial>(gl:
|
|
84
|
+
declare function compile<TVertex extends GLSL, TFragment extends GLSL, TSchema extends ViewSchemaPartial>(gl: GL, vertex: TVertex, fragment: TFragment, options?: CompileOptions<TSchema> | undefined): CompileResult<TVertex, TFragment, TSchema> extends infer T ? { [K in keyof T]: CompileResult<TVertex, TFragment, TSchema>[K]; } : never;
|
|
85
85
|
declare namespace compile {
|
|
86
86
|
var toSchema: <TTag extends GLSL>(tag: TTag) => Prettify<GLSLToSchema<TTag>>;
|
|
87
87
|
var toString: <TTag extends GLSL>({ template: [initial, ...rest], slots }: TTag, config?: {
|
package/dist/tag.mjs
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createProgram
|
|
3
|
+
} from "./chunk-UVDTF5P3.mjs";
|
|
1
4
|
import {
|
|
2
5
|
toID,
|
|
3
6
|
view
|
|
4
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-NRCBGOZB.mjs";
|
|
5
8
|
import {
|
|
6
|
-
createProgram,
|
|
7
9
|
once
|
|
8
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-IAM2SWJK.mjs";
|
|
9
11
|
|
|
10
12
|
// src/tag.ts
|
|
11
13
|
function glsl(template, ...slots) {
|
package/dist/tag.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/tag.ts"],"sourcesContent":["import { toID, view } from '.'\nimport { createProgram } from './gl'\nimport type { Prettify } from './type-utils'\nimport type {\n AttributeDefinition,\n AttributeKind,\n AttributeTokenFn as AttributeTagMethod,\n AttributeToken,\n CompileResult,\n GL,\n GLSL,\n GLSLSlot,\n GLSLToSchema,\n InterleaveToken,\n UniformDefinition,\n UniformKind,\n UniformTokenFn as UniformTagMethod,\n ViewSchema,\n ViewSchemaPartial,\n} from './types'\nimport { once } from './utils'\n\nexport function glsl<TSlot extends GLSLSlot, const TSlots extends TSlot[]>(\n template: TemplateStringsArray,\n ...slots: [...TSlots]\n): GLSL<TSlots> {\n return { template, slots, type: 'glsl' }\n}\n\nexport const uniform = new Proxy(\n {} as {\n [TKey in UniformKind]: UniformTagMethod<TKey>\n },\n {\n get(target, property) {\n // @ts-expect-error\n if (typeof property === 'symbol') return target[property]\n return (key: string, options?: Omit<UniformDefinition, 'kind'>) => ({\n type: 'uniform',\n key,\n kind: property,\n ...options,\n })\n },\n },\n)\n\nexport const attribute = new Proxy(\n {} as {\n [TKey in AttributeKind]: AttributeTagMethod<TKey>\n },\n {\n get(target, property) {\n // @ts-expect-error\n if (typeof property === 'symbol') return target[property]\n return (key: string, options?: Omit<AttributeDefinition, 'kind'>) => ({\n type: 'attribute',\n key,\n kind: property,\n ...options,\n })\n },\n },\n)\n\nexport function interleave<\n const TKey extends string | symbol,\n const TLayout extends Array<AttributeToken<string | symbol, AttributeKind, undefined>>,\n const TOptions extends Omit<AttributeDefinition, 'kind'>,\n>(key: TKey, layout: TLayout, instanced: TOptions): InterleaveToken<TKey, TLayout, TOptions>\nexport function interleave<\n const TKey extends string | symbol,\n const TLayout extends Array<AttributeToken<string | symbol, AttributeKind, undefined>>,\n>(key: TKey, layout: TLayout): InterleaveToken<TKey, TLayout, { instanced: false }>\nexport function interleave<\n const TKey extends string | symbol,\n const TLayout extends Array<AttributeToken<string | symbol, AttributeKind, undefined>>,\n const TOptions extends Omit<AttributeDefinition, 'kind'>,\n>(key: TKey, layout: TLayout, { instanced, buffer }: Partial<TOptions> = {}) {\n return {\n type: 'interleavedAttribute',\n key,\n // remove instanced- and type-property\n layout: layout.map(({ key, kind }) => ({\n key,\n kind,\n })),\n instanced: !!instanced,\n buffer,\n } as unknown as InterleaveToken<TKey, TLayout, TOptions>\n}\n\n/**********************************************************************************/\n/* */\n/* Compile */\n/* */\n/**********************************************************************************/\n\nexport interface CompileOptions<TSchema extends ViewSchemaPartial> {\n schema?: TSchema\n webgl2?: boolean\n /**\n * Disposes what `compile` made: the program, and the buffers the view created\n * for itself. Buffers named by the schema belong to whoever made them.\n */\n signal?: AbortSignal\n}\n\nexport function compile<\n TVertex extends GLSL,\n TFragment extends GLSL,\n TSchema extends ViewSchemaPartial,\n>(\n gl: WebGLRenderingContext,\n vertex: TVertex,\n fragment: TFragment,\n options?: CompileOptions<TSchema> | undefined,\n) {\n const _vertex = resolveGLSLTag(vertex, options) as { template: string; schema: ViewSchema }\n const _fragment = resolveGLSLTag(fragment, options) as { template: string; schema: ViewSchema }\n\n const schema = {\n uniforms: {\n ..._vertex.schema.uniforms,\n ..._fragment.schema.uniforms,\n },\n attributes: {\n ..._vertex.schema.attributes,\n ..._fragment.schema.attributes,\n },\n interleavedAttributes: {\n ..._vertex.schema.interleavedAttributes,\n ..._fragment.schema.interleavedAttributes,\n },\n // Never produced by a tag — a buffer has no name in the source to be\n // parsed out of one — but `options.schema` may name buffers for the view to\n // own, and the deep merge below indexes this object by every key it finds\n // there. Missing, that threw.\n buffers: {} as NonNullable<ViewSchema['buffers']>,\n }\n\n // Deep merge options.schema with generated schema\n for (const kind in options?.schema) {\n const schemaKind = schema[kind as keyof typeof schema]\n const configSchemaKind = options?.schema[kind]\n\n for (const key in configSchemaKind) {\n schemaKind[key] = {\n ...schemaKind[key],\n ...configSchemaKind[key],\n }\n }\n }\n\n try {\n const program = createProgram(gl, _vertex.template, _fragment.template)\n\n // The same rule the views follow: `compile` made this program, so `compile`\n // is what deletes it. A program handed in from outside would not be ours to\n // delete, and there is no way to hand one in.\n const resolvedView = view(gl, program, schema)\n const dispose = once(() => {\n resolvedView.dispose()\n gl.deleteProgram(program)\n })\n options?.signal?.addEventListener('abort', dispose)\n\n return {\n program,\n schema,\n view: resolvedView,\n dispose,\n vertex: _vertex.template,\n fragment: _fragment.template,\n } as unknown as Prettify<CompileResult<TVertex, TFragment, TSchema>>\n } catch (error) {\n console.error('Error while creating WebGLProgram - vertex\\n\\n', _vertex.template)\n console.error('Error while creating WebGLProgram - fragment\\n\\n', _fragment.template)\n\n throw error\n }\n}\n\nfunction resolveGLSLTag<TTag extends GLSL>(tag: TTag, options?: { webgl2?: boolean }) {\n return {\n template: compile.toString(tag, options),\n schema: compile.toSchema(tag),\n }\n}\n\ncompile.toSchema = function <TTag extends GLSL>(tag: TTag) {\n const result = {\n uniforms: {},\n attributes: {},\n interleavedAttributes: {},\n }\n\n tag.slots.forEach(function handleSlot(slot: GLSLSlot) {\n if (typeof slot !== 'object') {\n return\n }\n\n if (Array.isArray(slot)) {\n slot.forEach(handleSlot)\n return\n }\n\n if (slot.type === 'glsl') {\n const { uniforms, attributes, interleavedAttributes } = compile.toSchema(slot)\n\n result.uniforms = {\n ...result.uniforms,\n ...uniforms,\n }\n result.attributes = {\n ...result.attributes,\n ...attributes,\n }\n result.interleavedAttributes = {\n ...result.interleavedAttributes,\n ...interleavedAttributes,\n }\n\n return\n }\n\n const { key: name, type, ...rest } = slot\n\n // @ts-expect-error\n result[`${type}s`][name] = rest\n })\n\n return result as unknown as Prettify<GLSLToSchema<TTag>>\n}\n\ncompile.toString = function <TTag extends GLSL>(\n { template: [initial, ...rest], slots }: TTag,\n config?: { webgl2?: boolean },\n) {\n const v300 = config?.webgl2 ?? !!initial?.startsWith('#version 300 es')\n\n let template = initial ?? ''\n\n for (let i = 0; i < rest.length; i++) {\n template += `${resolveGlslSlotToString(slots[i]!, v300)}${rest[i]}`\n }\n\n return template\n}\n\nfunction resolveGlslSlotToString(slot: GLSLSlot, v300: boolean): string {\n if (typeof slot !== 'object') {\n return toID(slot)\n }\n\n if (Array.isArray(slot)) {\n return slot.map(slot => resolveGlslSlotToString(slot, v300)).join('')\n }\n\n switch (slot.type) {\n case 'glsl':\n return compile.toString(slot)\n case 'interleavedAttribute':\n return slot.layout.reduce(\n (a, v) =>\n v300 ? `${a}in ${v.kind} ${toID(v.key)};\\n` : `${a}attribute ${v.kind} ${toID(v.key)};\\n`,\n '',\n )\n case 'uniform':\n if ('size' in slot) {\n return `${slot.type} ${slot.kind} ${toID(slot.key)}[${slot.size}];`\n }\n return `${slot.type} ${slot.kind} ${toID(slot.key)};`\n }\n\n if (slot.type === 'attribute') {\n return `${v300 ? 'in' : slot.type} ${slot.kind} ${toID(slot.key)};`\n }\n\n throw new Error(`Unexpected slot: ${JSON.stringify(slot)}`)\n}\n\nconst QUAD_FLOAT_ARRAY = new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1])\n\ncompile.toQuad = function <TFragment extends GLSL, TSchema extends ViewSchemaPartial>(\n gl: GL,\n fragment: TFragment,\n options?: CompileOptions<TSchema>,\n) {\n const webgl2 = options?.webgl2 ?? fragment.template[0]?.startsWith('#version 300 es')\n\n const vertex = webgl2\n ? glsl`#version 300 es\nprecision mediump float;\n\n${attribute.vec2('a_quad')}\n\nout vec2 v_uv;\n\nvoid main() {\n v_uv = a_quad;\n gl_Position = vec4(v_uv, 0.0, 1.0);\n}`\n : glsl`precision mediump float;\n\n${attribute.vec2('a_quad')}\n\nvarying vec2 v_uv;\n\nvoid main() {\n v_uv = a_quad;\n gl_Position = vec4(v_uv, 0.0, 1.0);\n}`\n\n const result = compile(gl, vertex, fragment, options)\n\n // @ts-expect-error\n result.view.attributes.a_quad.set(QUAD_FLOAT_ARRAY)\n\n return result\n}\n"],"mappings":";;;;;;;;;;AAsBO,SAAS,KACd,aACG,OACW;AACd,SAAO,EAAE,UAAU,OAAO,MAAM,OAAO;AACzC;AAEO,IAAM,UAAU,IAAI;AAAA,EACzB,CAAC;AAAA,EAGD;AAAA,IACE,IAAI,QAAQ,UAAU;AAEpB,UAAI,OAAO,aAAa,SAAU,QAAO,OAAO,QAAQ;AACxD,aAAO,CAAC,KAAa,aAA+C;AAAA,QAClE,MAAM;AAAA,QACN;AAAA,QACA,MAAM;AAAA,QACN,GAAG;AAAA,MACL;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,YAAY,IAAI;AAAA,EAC3B,CAAC;AAAA,EAGD;AAAA,IACE,IAAI,QAAQ,UAAU;AAEpB,UAAI,OAAO,aAAa,SAAU,QAAO,OAAO,QAAQ;AACxD,aAAO,CAAC,KAAa,aAAiD;AAAA,QACpE,MAAM;AAAA,QACN;AAAA,QACA,MAAM;AAAA,QACN,GAAG;AAAA,MACL;AAAA,IACF;AAAA,EACF;AACF;AAWO,SAAS,WAId,KAAW,QAAiB,EAAE,WAAW,OAAO,IAAuB,CAAC,GAAG;AAC3E,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA;AAAA,IAEA,QAAQ,OAAO,IAAI,CAAC,EAAE,KAAAA,MAAK,KAAK,OAAO;AAAA,MACrC,KAAAA;AAAA,MACA;AAAA,IACF,EAAE;AAAA,IACF,WAAW,CAAC,CAAC;AAAA,IACb;AAAA,EACF;AACF;AAkBO,SAAS,QAKd,IACA,QACA,UACA,SACA;AACA,QAAM,UAAU,eAAe,QAAQ,OAAO;AAC9C,QAAM,YAAY,eAAe,UAAU,OAAO;AAElD,QAAM,SAAS;AAAA,IACb,UAAU;AAAA,MACR,GAAG,QAAQ,OAAO;AAAA,MAClB,GAAG,UAAU,OAAO;AAAA,IACtB;AAAA,IACA,YAAY;AAAA,MACV,GAAG,QAAQ,OAAO;AAAA,MAClB,GAAG,UAAU,OAAO;AAAA,IACtB;AAAA,IACA,uBAAuB;AAAA,MACrB,GAAG,QAAQ,OAAO;AAAA,MAClB,GAAG,UAAU,OAAO;AAAA,IACtB;AAAA;AAAA;AAAA;AAAA;AAAA,IAKA,SAAS,CAAC;AAAA,EACZ;AAGA,aAAW,QAAQ,SAAS,QAAQ;AAClC,UAAM,aAAa,OAAO,IAA2B;AACrD,UAAM,mBAAmB,SAAS,OAAO,IAAI;AAE7C,eAAW,OAAO,kBAAkB;AAClC,iBAAW,GAAG,IAAI;AAAA,QAChB,GAAG,WAAW,GAAG;AAAA,QACjB,GAAG,iBAAiB,GAAG;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAEA,MAAI;AACF,UAAM,UAAU,cAAc,IAAI,QAAQ,UAAU,UAAU,QAAQ;AAKtE,UAAM,eAAe,KAAK,IAAI,SAAS,MAAM;AAC7C,UAAM,UAAU,KAAK,MAAM;AACzB,mBAAa,QAAQ;AACrB,SAAG,cAAc,OAAO;AAAA,IAC1B,CAAC;AACD,aAAS,QAAQ,iBAAiB,SAAS,OAAO;AAElD,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,QAAQ,QAAQ;AAAA,MAChB,UAAU,UAAU;AAAA,IACtB;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,kDAAkD,QAAQ,QAAQ;AAChF,YAAQ,MAAM,oDAAoD,UAAU,QAAQ;AAEpF,UAAM;AAAA,EACR;AACF;AAEA,SAAS,eAAkC,KAAW,SAAgC;AACpF,SAAO;AAAA,IACL,UAAU,QAAQ,SAAS,KAAK,OAAO;AAAA,IACvC,QAAQ,QAAQ,SAAS,GAAG;AAAA,EAC9B;AACF;AAEA,QAAQ,WAAW,SAA6B,KAAW;AACzD,QAAM,SAAS;AAAA,IACb,UAAU,CAAC;AAAA,IACX,YAAY,CAAC;AAAA,IACb,uBAAuB,CAAC;AAAA,EAC1B;AAEA,MAAI,MAAM,QAAQ,SAAS,WAAW,MAAgB;AACpD,QAAI,OAAO,SAAS,UAAU;AAC5B;AAAA,IACF;AAEA,QAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,WAAK,QAAQ,UAAU;AACvB;AAAA,IACF;AAEA,QAAI,KAAK,SAAS,QAAQ;AACxB,YAAM,EAAE,UAAU,YAAY,sBAAsB,IAAI,QAAQ,SAAS,IAAI;AAE7E,aAAO,WAAW;AAAA,QAChB,GAAG,OAAO;AAAA,QACV,GAAG;AAAA,MACL;AACA,aAAO,aAAa;AAAA,QAClB,GAAG,OAAO;AAAA,QACV,GAAG;AAAA,MACL;AACA,aAAO,wBAAwB;AAAA,QAC7B,GAAG,OAAO;AAAA,QACV,GAAG;AAAA,MACL;AAEA;AAAA,IACF;AAEA,UAAM,EAAE,KAAK,MAAM,MAAM,GAAG,KAAK,IAAI;AAGrC,WAAO,GAAG,IAAI,GAAG,EAAE,IAAI,IAAI;AAAA,EAC7B,CAAC;AAED,SAAO;AACT;AAEA,QAAQ,WAAW,SACjB,EAAE,UAAU,CAAC,SAAS,GAAG,IAAI,GAAG,MAAM,GACtC,QACA;AACA,QAAM,OAAO,QAAQ,UAAU,CAAC,CAAC,SAAS,WAAW,iBAAiB;AAEtE,MAAI,WAAW,WAAW;AAE1B,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,gBAAY,GAAG,wBAAwB,MAAM,CAAC,GAAI,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;AAAA,EACnE;AAEA,SAAO;AACT;AAEA,SAAS,wBAAwB,MAAgB,MAAuB;AACtE,MAAI,OAAO,SAAS,UAAU;AAC5B,WAAO,KAAK,IAAI;AAAA,EAClB;AAEA,MAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,WAAO,KAAK,IAAI,CAAAC,UAAQ,wBAAwBA,OAAM,IAAI,CAAC,EAAE,KAAK,EAAE;AAAA,EACtE;AAEA,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAK;AACH,aAAO,QAAQ,SAAS,IAAI;AAAA,IAC9B,KAAK;AACH,aAAO,KAAK,OAAO;AAAA,QACjB,CAAC,GAAG,MACF,OAAO,GAAG,CAAC,MAAM,EAAE,IAAI,IAAI,KAAK,EAAE,GAAG,CAAC;AAAA,IAAQ,GAAG,CAAC,aAAa,EAAE,IAAI,IAAI,KAAK,EAAE,GAAG,CAAC;AAAA;AAAA,QACtF;AAAA,MACF;AAAA,IACF,KAAK;AACH,UAAI,UAAU,MAAM;AAClB,eAAO,GAAG,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI;AAAA,MACjE;AACA,aAAO,GAAG,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,KAAK,GAAG,CAAC;AAAA,EACtD;AAEA,MAAI,KAAK,SAAS,aAAa;AAC7B,WAAO,GAAG,OAAO,OAAO,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,KAAK,GAAG,CAAC;AAAA,EAClE;AAEA,QAAM,IAAI,MAAM,oBAAoB,KAAK,UAAU,IAAI,CAAC,EAAE;AAC5D;AAEA,IAAM,mBAAmB,IAAI,aAAa,CAAC,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,GAAG,CAAC,CAAC;AAEpF,QAAQ,SAAS,SACf,IACA,UACA,SACA;AACA,QAAM,SAAS,SAAS,UAAU,SAAS,SAAS,CAAC,GAAG,WAAW,iBAAiB;AAEpF,QAAM,SAAS,SACX;AAAA;AAAA;AAAA,EAGJ,UAAU,KAAK,QAAQ,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAQpB;AAAA;AAAA,EAEJ,UAAU,KAAK,QAAQ,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASxB,QAAM,SAAS,QAAQ,IAAI,QAAQ,UAAU,OAAO;AAGpD,SAAO,KAAK,WAAW,OAAO,IAAI,gBAAgB;AAElD,SAAO;AACT;","names":["key","slot"]}
|
|
1
|
+
{"version":3,"sources":["../src/tag.ts"],"sourcesContent":["import { toID, view } from '.'\nimport { createProgram } from './gl'\nimport type { Prettify } from './type-utils'\nimport type {\n AttributeDefinition,\n AttributeKind,\n AttributeTokenFn as AttributeTagMethod,\n AttributeToken,\n CompileResult,\n GL,\n GLSL,\n GLSLSlot,\n GLSLToSchema,\n InterleaveToken,\n UniformDefinition,\n UniformKind,\n UniformTokenFn as UniformTagMethod,\n ViewSchema,\n ViewSchemaPartial,\n} from './types'\nimport { once } from './utils'\n\nexport function glsl<TSlot extends GLSLSlot, const TSlots extends TSlot[]>(\n template: TemplateStringsArray,\n ...slots: [...TSlots]\n): GLSL<TSlots> {\n return { template, slots, type: 'glsl' }\n}\n\nexport const uniform = new Proxy(\n {} as {\n [TKey in UniformKind]: UniformTagMethod<TKey>\n },\n {\n get(target, property) {\n // @ts-expect-error\n if (typeof property === 'symbol') return target[property]\n return (key: string, options?: Omit<UniformDefinition, 'kind'>) => ({\n type: 'uniform',\n key,\n kind: property,\n ...options,\n })\n },\n },\n)\n\nexport const attribute = new Proxy(\n {} as {\n [TKey in AttributeKind]: AttributeTagMethod<TKey>\n },\n {\n get(target, property) {\n // @ts-expect-error\n if (typeof property === 'symbol') return target[property]\n return (key: string, options?: Omit<AttributeDefinition, 'kind'>) => ({\n type: 'attribute',\n key,\n kind: property,\n ...options,\n })\n },\n },\n)\n\nexport function interleave<\n const TKey extends string | symbol,\n const TLayout extends Array<AttributeToken<string | symbol, AttributeKind, undefined>>,\n const TOptions extends Omit<AttributeDefinition, 'kind'>,\n>(key: TKey, layout: TLayout, instanced: TOptions): InterleaveToken<TKey, TLayout, TOptions>\nexport function interleave<\n const TKey extends string | symbol,\n const TLayout extends Array<AttributeToken<string | symbol, AttributeKind, undefined>>,\n>(key: TKey, layout: TLayout): InterleaveToken<TKey, TLayout, { instanced: false }>\nexport function interleave<\n const TKey extends string | symbol,\n const TLayout extends Array<AttributeToken<string | symbol, AttributeKind, undefined>>,\n const TOptions extends Omit<AttributeDefinition, 'kind'>,\n>(key: TKey, layout: TLayout, { instanced, buffer }: Partial<TOptions> = {}) {\n return {\n type: 'interleavedAttribute',\n key,\n // remove instanced- and type-property\n layout: layout.map(({ key, kind }) => ({\n key,\n kind,\n })),\n instanced: !!instanced,\n buffer,\n } as unknown as InterleaveToken<TKey, TLayout, TOptions>\n}\n\n/**********************************************************************************/\n/* */\n/* Compile */\n/* */\n/**********************************************************************************/\n\nexport interface CompileOptions<TSchema extends ViewSchemaPartial> {\n schema?: TSchema\n webgl2?: boolean\n /**\n * Disposes what `compile` made: the program, and the buffers the view created\n * for itself. Buffers named by the schema belong to whoever made them.\n */\n signal?: AbortSignal\n}\n\nexport function compile<\n TVertex extends GLSL,\n TFragment extends GLSL,\n TSchema extends ViewSchemaPartial,\n>(gl: GL, vertex: TVertex, fragment: TFragment, options?: CompileOptions<TSchema> | undefined) {\n const _vertex = resolveGLSLTag(vertex, options) as { template: string; schema: ViewSchema }\n const _fragment = resolveGLSLTag(fragment, options) as { template: string; schema: ViewSchema }\n\n const schema = {\n uniforms: {\n ..._vertex.schema.uniforms,\n ..._fragment.schema.uniforms,\n },\n attributes: {\n ..._vertex.schema.attributes,\n ..._fragment.schema.attributes,\n },\n interleavedAttributes: {\n ..._vertex.schema.interleavedAttributes,\n ..._fragment.schema.interleavedAttributes,\n },\n // Never produced by a tag — a buffer has no name in the source to be\n // parsed out of one — but `options.schema` may name buffers for the view to\n // own, and the deep merge below indexes this object by every key it finds\n // there. Missing, that threw.\n buffers: {} as NonNullable<ViewSchema['buffers']>,\n }\n\n // Deep merge options.schema with generated schema\n for (const kind in options?.schema) {\n const schemaKind = schema[kind as keyof typeof schema]\n const configSchemaKind = options?.schema[kind]\n\n for (const key in configSchemaKind) {\n schemaKind[key] = {\n ...schemaKind[key],\n ...configSchemaKind[key],\n }\n }\n }\n\n try {\n const program = createProgram(gl, _vertex.template, _fragment.template)\n\n // The same rule the views follow: `compile` made this program, so `compile`\n // is what deletes it. A program handed in from outside would not be ours to\n // delete, and there is no way to hand one in.\n const resolvedView = view(gl, program, schema)\n const dispose = once(() => {\n resolvedView.dispose()\n gl.deleteProgram(program)\n })\n options?.signal?.addEventListener('abort', dispose)\n\n return {\n program,\n schema,\n view: resolvedView,\n dispose,\n vertex: _vertex.template,\n fragment: _fragment.template,\n } as unknown as Prettify<CompileResult<TVertex, TFragment, TSchema>>\n } catch (error) {\n console.error('Error while creating WebGLProgram - vertex\\n\\n', _vertex.template)\n console.error('Error while creating WebGLProgram - fragment\\n\\n', _fragment.template)\n\n throw error\n }\n}\n\nfunction resolveGLSLTag<TTag extends GLSL>(tag: TTag, options?: { webgl2?: boolean }) {\n return {\n template: compile.toString(tag, options),\n schema: compile.toSchema(tag),\n }\n}\n\ncompile.toSchema = function <TTag extends GLSL>(tag: TTag) {\n const result = {\n uniforms: {},\n attributes: {},\n interleavedAttributes: {},\n }\n\n tag.slots.forEach(function handleSlot(slot: GLSLSlot) {\n if (typeof slot !== 'object') {\n return\n }\n\n if (Array.isArray(slot)) {\n slot.forEach(handleSlot)\n return\n }\n\n if (slot.type === 'glsl') {\n const { uniforms, attributes, interleavedAttributes } = compile.toSchema(slot)\n\n result.uniforms = {\n ...result.uniforms,\n ...uniforms,\n }\n result.attributes = {\n ...result.attributes,\n ...attributes,\n }\n result.interleavedAttributes = {\n ...result.interleavedAttributes,\n ...interleavedAttributes,\n }\n\n return\n }\n\n const { key: name, type, ...rest } = slot\n\n // @ts-expect-error\n result[`${type}s`][name] = rest\n })\n\n return result as unknown as Prettify<GLSLToSchema<TTag>>\n}\n\ncompile.toString = function <TTag extends GLSL>(\n { template: [initial, ...rest], slots }: TTag,\n config?: { webgl2?: boolean },\n) {\n const v300 = config?.webgl2 ?? !!initial?.startsWith('#version 300 es')\n\n let template = initial ?? ''\n\n for (let i = 0; i < rest.length; i++) {\n template += `${resolveGlslSlotToString(slots[i]!, v300)}${rest[i]}`\n }\n\n return template\n}\n\nfunction resolveGlslSlotToString(slot: GLSLSlot, v300: boolean): string {\n if (typeof slot !== 'object') {\n return toID(slot)\n }\n\n if (Array.isArray(slot)) {\n return slot.map(slot => resolveGlslSlotToString(slot, v300)).join('')\n }\n\n switch (slot.type) {\n case 'glsl':\n return compile.toString(slot)\n case 'interleavedAttribute':\n return slot.layout.reduce(\n (a, v) =>\n v300 ? `${a}in ${v.kind} ${toID(v.key)};\\n` : `${a}attribute ${v.kind} ${toID(v.key)};\\n`,\n '',\n )\n case 'uniform':\n if ('size' in slot) {\n return `${slot.type} ${slot.kind} ${toID(slot.key)}[${slot.size}];`\n }\n return `${slot.type} ${slot.kind} ${toID(slot.key)};`\n }\n\n if (slot.type === 'attribute') {\n return `${v300 ? 'in' : slot.type} ${slot.kind} ${toID(slot.key)};`\n }\n\n throw new Error(`Unexpected slot: ${JSON.stringify(slot)}`)\n}\n\nconst QUAD_FLOAT_ARRAY = new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1])\n\ncompile.toQuad = function <TFragment extends GLSL, TSchema extends ViewSchemaPartial>(\n gl: GL,\n fragment: TFragment,\n options?: CompileOptions<TSchema>,\n) {\n const webgl2 = options?.webgl2 ?? fragment.template[0]?.startsWith('#version 300 es')\n\n const vertex = webgl2\n ? glsl`#version 300 es\nprecision mediump float;\n\n${attribute.vec2('a_quad')}\n\nout vec2 v_uv;\n\nvoid main() {\n v_uv = a_quad;\n gl_Position = vec4(v_uv, 0.0, 1.0);\n}`\n : glsl`precision mediump float;\n\n${attribute.vec2('a_quad')}\n\nvarying vec2 v_uv;\n\nvoid main() {\n v_uv = a_quad;\n gl_Position = vec4(v_uv, 0.0, 1.0);\n}`\n\n const result = compile(gl, vertex, fragment, options)\n\n // @ts-expect-error\n result.view.attributes.a_quad.set(QUAD_FLOAT_ARRAY)\n\n return result\n}\n"],"mappings":"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","names":["key","slot"]}
|
|
@@ -21,7 +21,29 @@ type ShallowMergeTwo<L, R> = Id<Pick<L, Exclude<keyof L, keyof R>> & Pick<R, Exc
|
|
|
21
21
|
|
|
22
22
|
/**********************************************************************************/
|
|
23
23
|
/**********************************************************************************/
|
|
24
|
-
type
|
|
24
|
+
type NumericKeys<T> = {
|
|
25
|
+
[K in keyof T]: T[K] extends number ? K : never;
|
|
26
|
+
}[keyof T];
|
|
27
|
+
/** What a WebGL1 context has and view.gl calls. */
|
|
28
|
+
type WebGL1Core = Pick<WebGLRenderingContext, 'activeTexture' | 'attachShader' | 'bindBuffer' | 'bindFramebuffer' | 'bindTexture' | 'bufferData' | 'bufferSubData' | 'checkFramebufferStatus' | 'compileShader' | 'createBuffer' | 'createFramebuffer' | 'createProgram' | 'createShader' | 'createTexture' | 'deleteBuffer' | 'deleteFramebuffer' | 'deleteProgram' | 'deleteShader' | 'deleteTexture' | 'disableVertexAttribArray' | 'enableVertexAttribArray' | 'framebufferTexture2D' | 'getAttribLocation' | 'getError' | 'getParameter' | 'getProgramInfoLog' | 'getProgramParameter' | 'getShaderInfoLog' | 'getShaderParameter' | 'getUniformLocation' | 'getVertexAttrib' | 'linkProgram' | 'shaderSource' | 'texImage2D' | 'texParameteri' | 'uniform1f' | 'uniform1fv' | 'uniform1i' | 'uniform1iv' | 'uniform2f' | 'uniform2fv' | 'uniform2i' | 'uniform2iv' | 'uniform3f' | 'uniform3fv' | 'uniform3i' | 'uniform3iv' | 'uniform4f' | 'uniform4fv' | 'uniform4i' | 'uniform4iv' | 'uniformMatrix2fv' | 'uniformMatrix3fv' | 'uniformMatrix4fv' | 'vertexAttrib1f' | 'vertexAttrib2f' | 'vertexAttrib3f' | 'vertexAttrib4f' | 'vertexAttribPointer'> & Readonly<Record<NumericKeys<WebGLRenderingContext>, number>>;
|
|
29
|
+
/** Instancing: a WebGL2 context's own, or a wrapper's, under the WebGL2 names. */
|
|
30
|
+
type Instancing = Pick<WebGL2RenderingContext, 'vertexAttribDivisor' | 'drawArraysInstanced' | 'drawElementsInstanced'> & {
|
|
31
|
+
readonly VERTEX_ATTRIB_ARRAY_DIVISOR: number;
|
|
32
|
+
};
|
|
33
|
+
/** Vertex arrays: a WebGL2 context's own, or a wrapper's, under the WebGL2 names. */
|
|
34
|
+
type VertexArrays = Pick<WebGL2RenderingContext, 'createVertexArray' | 'bindVertexArray' | 'deleteVertexArray'> & {
|
|
35
|
+
readonly VERTEX_ARRAY_BINDING: number;
|
|
36
|
+
};
|
|
37
|
+
/** WebGL2-only members view.gl reaches for where a schema asks for them. */
|
|
38
|
+
type WebGL2Only = Pick<WebGL2RenderingContext, 'vertexAttribIPointer' | 'uniform1ui' | 'uniform1uiv' | 'uniform2ui' | 'uniform2uiv' | 'uniform3ui' | 'uniform3uiv' | 'uniform4ui' | 'uniform4uiv' | 'uniformMatrix2x3fv' | 'uniformMatrix2x4fv' | 'uniformMatrix3x2fv' | 'uniformMatrix3x4fv' | 'uniformMatrix4x2fv' | 'uniformMatrix4x3fv' | 'RGBA32F' | 'RGB32F' | 'RGBA16F' | 'RGB16F' | 'HALF_FLOAT'>;
|
|
39
|
+
/**
|
|
40
|
+
* The context view.gl draws with: what a WebGL1 context has, plus each WebGL2
|
|
41
|
+
* feature as optional members under its WebGL2 names. A WebGL2 context is one
|
|
42
|
+
* as it is. A WebGL1 context with the extensions is one once a wrapper puts
|
|
43
|
+
* the extension's calls on it under the WebGL2 names; view.gl asks the context
|
|
44
|
+
* nothing and looks no extension up.
|
|
45
|
+
*/
|
|
46
|
+
type GL = WebGL1Core & Partial<Instancing> & Partial<VertexArrays> & Partial<WebGL2Only>;
|
|
25
47
|
type GLTarget = 'ARRAY_BUFFER' | 'ELEMENT_ARRAY_BUFFER';
|
|
26
48
|
type GLUsage = 'STATIC_DRAW' | 'DYNAMIC_DRAW' | 'STREAM_DRAW';
|
|
27
49
|
type GLTextureTarget = 'TEXTURE_2D' | 'TEXTURE_CUBE_MAP';
|
|
@@ -592,4 +614,4 @@ type CompileResult<TVertex extends GLSL, TFragment extends GLSL, TOverrideSchema
|
|
|
592
614
|
dispose(): void;
|
|
593
615
|
} : never;
|
|
594
616
|
|
|
595
|
-
export type {
|
|
617
|
+
export type { TextureView as $, AttributeSchema as A, BufferSchema as B, AttributeShortHand as C, AttributeKind as D, AttributeFormat as E, FramebufferDefinition as F, GL as G, AttributeDefinition as H, InterleavedAttributeSchema as I, AttributeMethods as J, KIND_TO_UNIFORM_FN_NAME_MAP as K, InterleavedAttributeLayout as L, InterleavedAttributeDefinition as M, BufferSource as N, ConstantAttributeMethods as O, ConstantSource as P, InterleavedAttributeMethods as Q, BufferDefinition as R, Source as S, TextureDefinition as T, UniformSchema as U, ViewOptions as V, BufferMethods as W, Framebuffer as X, TextureTarget as Y, TextureSchema as Z, TextureMethods as _, ViewSchema as a, TextureParameterName as a0, TextureParameterValue as a1, TextureParameters as a2, InternalFormat as a3, Format as a4, PixelType as a5, TexImage2DOptions as a6, ViewSchemaPartial as a7, GLSLResult as a8, GLSLSlot as a9, GLSL as aa, UniformToken as ab, UniformTokenFn as ac, AttributeToken as ad, AttributeTokenFn as ae, InterleaveToken as af, GLSLToSchema as ag, GLSLToView as ah, GLSLSlotsToSchema as ai, FlattenSlots as aj, MergeGLSLSchema as ak, CompileResult as al, Prettify as am, View as b, VertexArrayParticipant as c, VertexArrayMethods as d, UniformView as e, AttributeView as f, InterleavedAttributeView as g, BufferView as h, Instancing as i, VertexArrays as j, GLTarget as k, GLUsage as l, GLTextureTarget as m, GLTextureFormat as n, GLTextureType as o, GLTextureFilter as p, GLTextureWrap as q, KIND_TO_SIZE_MAP as r, UniformFnName as s, UniformKind as t, UniformKindMap as u, UniformDefinition as v, UniformElementMethods as w, UniformArrayMethods as x, UniformMethods as y, UniformValue as z };
|
package/package.json
CHANGED
package/src/errors.ts
CHANGED
|
@@ -49,6 +49,15 @@ export class AttributeNotFoundError extends Error {
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
/** A divisor of 1 asked of a context without `vertexAttribDivisor`: the draw cannot instance. */
|
|
53
|
+
export class InstancingUnavailableError extends Error {
|
|
54
|
+
override name = 'InstancingUnavailableError'
|
|
55
|
+
|
|
56
|
+
constructor(readonly attribute: string) {
|
|
57
|
+
super(`Attribute '${attribute}' is instanced, but the context has no instancing`)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
52
61
|
/** Throws a {@link GLCreateError} for a `create*` that answered `null`. */
|
|
53
62
|
export function created<T>(value: T | null, resource: GLResource): T {
|
|
54
63
|
if (value === null) {
|
package/src/gl.ts
CHANGED
|
@@ -2,12 +2,6 @@ import type { GL, ViewOptions } from './types'
|
|
|
2
2
|
import { created, ProgramLinkError, ShaderCompileError } from './errors'
|
|
3
3
|
import { once } from './utils'
|
|
4
4
|
|
|
5
|
-
function isWebGL2RenderingContext(
|
|
6
|
-
gl: WebGLRenderingContext | WebGL2RenderingContext,
|
|
7
|
-
): gl is WebGL2RenderingContext {
|
|
8
|
-
return typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext
|
|
9
|
-
}
|
|
10
|
-
|
|
11
5
|
/**********************************************************************************/
|
|
12
6
|
/* */
|
|
13
7
|
/* Create Shader */
|
|
@@ -73,43 +67,3 @@ export function createProgram(
|
|
|
73
67
|
|
|
74
68
|
return program
|
|
75
69
|
}
|
|
76
|
-
|
|
77
|
-
/**********************************************************************************/
|
|
78
|
-
/* */
|
|
79
|
-
/* Get Instanced Arrays */
|
|
80
|
-
/* */
|
|
81
|
-
/**********************************************************************************/
|
|
82
|
-
|
|
83
|
-
/** Instancing on `gl`: the context on WebGL2, `ANGLE_instanced_arrays` on WebGL1, else `undefined`. */
|
|
84
|
-
export function getInstancedArrays(gl: GL) {
|
|
85
|
-
if (isWebGL2RenderingContext(gl)) return gl
|
|
86
|
-
|
|
87
|
-
const ext = gl.getExtension('ANGLE_instanced_arrays')
|
|
88
|
-
if (!ext) return undefined
|
|
89
|
-
|
|
90
|
-
return {
|
|
91
|
-
drawArraysInstanced: ext.drawArraysInstancedANGLE.bind(ext),
|
|
92
|
-
drawElementsInstanced: ext.drawElementsInstancedANGLE.bind(ext),
|
|
93
|
-
vertexAttribDivisor: ext.vertexAttribDivisorANGLE.bind(ext),
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**********************************************************************************/
|
|
98
|
-
/* */
|
|
99
|
-
/* Get Vertex Array Object */
|
|
100
|
-
/* */
|
|
101
|
-
/**********************************************************************************/
|
|
102
|
-
|
|
103
|
-
/** Vertex arrays on `gl`: the context on WebGL2, `OES_vertex_array_object` on WebGL1, else `null`. */
|
|
104
|
-
export function getVertexArrayObject(gl: GL) {
|
|
105
|
-
if (isWebGL2RenderingContext(gl)) return gl
|
|
106
|
-
|
|
107
|
-
const ext = gl.getExtension('OES_vertex_array_object')
|
|
108
|
-
if (!ext) return null
|
|
109
|
-
|
|
110
|
-
return {
|
|
111
|
-
bindVertexArray: ext.bindVertexArrayOES.bind(ext),
|
|
112
|
-
createVertexArray: ext.createVertexArrayOES.bind(ext),
|
|
113
|
-
deleteVertexArray: ext.deleteVertexArrayOES.bind(ext),
|
|
114
|
-
}
|
|
115
|
-
}
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { AttributeNotFoundError, created } from './errors'
|
|
2
|
-
import { getInstancedArrays, getVertexArrayObject } from './gl'
|
|
1
|
+
import { AttributeNotFoundError, InstancingUnavailableError, created } from './errors'
|
|
3
2
|
import type {
|
|
4
3
|
AttributeFormat,
|
|
5
4
|
AttributeKind,
|
|
@@ -9,6 +8,7 @@ import type {
|
|
|
9
8
|
BufferSchema,
|
|
10
9
|
BufferView,
|
|
11
10
|
GL,
|
|
11
|
+
Instancing,
|
|
12
12
|
UniformView as InferUniformView,
|
|
13
13
|
GLUsage,
|
|
14
14
|
InterleavedAttributeLayout,
|
|
@@ -18,6 +18,7 @@ import type {
|
|
|
18
18
|
UniformSchema,
|
|
19
19
|
VertexArrayMethods,
|
|
20
20
|
VertexArrayParticipant,
|
|
21
|
+
VertexArrays,
|
|
21
22
|
View,
|
|
22
23
|
ViewOptions,
|
|
23
24
|
ViewSchema,
|
|
@@ -146,13 +147,32 @@ export function view<TSchema extends ViewSchema>(
|
|
|
146
147
|
* outlive the call that did it.
|
|
147
148
|
*/
|
|
148
149
|
function bindDefaultVertexArray(gl: GL): () => void {
|
|
149
|
-
|
|
150
|
-
if (!feature) {
|
|
150
|
+
if (!hasVertexArrays(gl)) {
|
|
151
151
|
return () => {}
|
|
152
152
|
}
|
|
153
153
|
const previous = readVertexArrayBinding(gl)
|
|
154
|
-
|
|
155
|
-
return () =>
|
|
154
|
+
gl.bindVertexArray(null)
|
|
155
|
+
return () => gl.bindVertexArray(previous)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** Whether `gl` carries the vertex-array feature, every member of it. */
|
|
159
|
+
function hasVertexArrays(gl: GL): gl is GL & VertexArrays {
|
|
160
|
+
return (
|
|
161
|
+
typeof gl.createVertexArray === 'function' &&
|
|
162
|
+
typeof gl.bindVertexArray === 'function' &&
|
|
163
|
+
typeof gl.deleteVertexArray === 'function' &&
|
|
164
|
+
typeof gl.VERTEX_ARRAY_BINDING === 'number'
|
|
165
|
+
)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** Whether `gl` carries the instancing feature, every member of it. */
|
|
169
|
+
function hasInstancing(gl: GL): gl is GL & Instancing {
|
|
170
|
+
return (
|
|
171
|
+
typeof gl.vertexAttribDivisor === 'function' &&
|
|
172
|
+
typeof gl.drawArraysInstanced === 'function' &&
|
|
173
|
+
typeof gl.drawElementsInstanced === 'function' &&
|
|
174
|
+
typeof gl.VERTEX_ATTRIB_ARRAY_DIVISOR === 'number'
|
|
175
|
+
)
|
|
156
176
|
}
|
|
157
177
|
|
|
158
178
|
/**
|
|
@@ -169,7 +189,7 @@ export function vaoView(
|
|
|
169
189
|
participants: VertexArrayParticipant[],
|
|
170
190
|
{ signal }: ViewOptions = {},
|
|
171
191
|
): VertexArrayMethods {
|
|
172
|
-
const feature =
|
|
192
|
+
const feature = hasVertexArrays(gl) ? gl : null
|
|
173
193
|
|
|
174
194
|
const methods: VertexArrayMethods = !feature
|
|
175
195
|
? {
|
|
@@ -183,7 +203,7 @@ export function vaoView(
|
|
|
183
203
|
}
|
|
184
204
|
: (() => {
|
|
185
205
|
const vertexArray = created(feature.createVertexArray(), 'vertexArray')
|
|
186
|
-
const previous = readVertexArrayBinding(
|
|
206
|
+
const previous = readVertexArrayBinding(feature)
|
|
187
207
|
feature.bindVertexArray(vertexArray)
|
|
188
208
|
// Discarding the restorers is the point: the state lives in this array
|
|
189
209
|
// now, and the array is thrown away whole.
|
|
@@ -194,7 +214,7 @@ export function vaoView(
|
|
|
194
214
|
|
|
195
215
|
return {
|
|
196
216
|
bind() {
|
|
197
|
-
const previousVertexArray = readVertexArrayBinding(
|
|
217
|
+
const previousVertexArray = readVertexArrayBinding(feature)
|
|
198
218
|
feature.bindVertexArray(vertexArray)
|
|
199
219
|
// Context state the array cannot hold — see applyToContext.
|
|
200
220
|
participants.forEach(participant => participant.applyToContext?.())
|
|
@@ -341,11 +361,19 @@ function handleAttribute(
|
|
|
341
361
|
glType: GLType,
|
|
342
362
|
isIntegerKind: boolean,
|
|
343
363
|
normalized: boolean,
|
|
344
|
-
instanced
|
|
364
|
+
instanced: boolean | undefined,
|
|
365
|
+
name: string,
|
|
345
366
|
) {
|
|
346
367
|
gl.enableVertexAttribArray(location)
|
|
347
368
|
if (isIntegerKind) {
|
|
348
|
-
|
|
369
|
+
assertedNotNullish(gl.vertexAttribIPointer, 'the context has no vertexAttribIPointer').call(
|
|
370
|
+
gl,
|
|
371
|
+
location,
|
|
372
|
+
size,
|
|
373
|
+
gl[glType],
|
|
374
|
+
stride,
|
|
375
|
+
offset,
|
|
376
|
+
)
|
|
349
377
|
} else {
|
|
350
378
|
gl.vertexAttribPointer(location, size, gl[glType], normalized, stride, offset)
|
|
351
379
|
}
|
|
@@ -353,30 +381,27 @@ function handleAttribute(
|
|
|
353
381
|
// Always stated, never inherited: the divisor belongs to the location rather
|
|
354
382
|
// than to the program, so a location left at 1 by an earlier instanced
|
|
355
383
|
// attribute would feed one value to every vertex here.
|
|
356
|
-
// Get instanced-arrays-feature: extension if webgl, gl if webgl2
|
|
357
|
-
const instancedArrays = getInstancedArrays(gl)
|
|
358
384
|
if (instanced) {
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
385
|
+
if (!hasInstancing(gl)) {
|
|
386
|
+
throw new InstancingUnavailableError(name)
|
|
387
|
+
}
|
|
388
|
+
gl.vertexAttribDivisor(location, 1)
|
|
389
|
+
} else if (hasInstancing(gl)) {
|
|
390
|
+
gl.vertexAttribDivisor(location, 0)
|
|
362
391
|
}
|
|
363
392
|
}
|
|
364
393
|
|
|
365
|
-
// Same enum in webgl2 and in the webgl1 extensions, which expose no constants
|
|
366
|
-
const VERTEX_ATTRIB_ARRAY_DIVISOR = 0x88fe
|
|
367
|
-
const VERTEX_ARRAY_BINDING = 0x85b5
|
|
368
|
-
|
|
369
394
|
// Anything but an array or null would make the restore throw a TypeError.
|
|
370
|
-
function readVertexArrayBinding(gl: GL): WebGLVertexArrayObject | null {
|
|
371
|
-
const bound: unknown = gl.getParameter(VERTEX_ARRAY_BINDING)
|
|
395
|
+
function readVertexArrayBinding(gl: GL & VertexArrays): WebGLVertexArrayObject | null {
|
|
396
|
+
const bound: unknown = gl.getParameter(gl.VERTEX_ARRAY_BINDING)
|
|
372
397
|
return typeof bound === 'object' ? (bound as WebGLVertexArrayObject | null) : null
|
|
373
398
|
}
|
|
374
399
|
|
|
375
400
|
// Reads the divisor currently attached to a location, 0 where instancing is
|
|
376
401
|
// unavailable and nothing can have set one
|
|
377
402
|
function readDivisor(gl: GL, location: number): number {
|
|
378
|
-
return
|
|
379
|
-
? (gl.getVertexAttrib(location, VERTEX_ATTRIB_ARRAY_DIVISOR) as number)
|
|
403
|
+
return hasInstancing(gl)
|
|
404
|
+
? (gl.getVertexAttrib(location, gl.VERTEX_ATTRIB_ARRAY_DIVISOR) as number)
|
|
380
405
|
: 0
|
|
381
406
|
}
|
|
382
407
|
|
|
@@ -416,9 +441,11 @@ export function attributeView<T extends AttributeSchema>(
|
|
|
416
441
|
// it runs, so this binding is the setup for the pointer, not a lasting
|
|
417
442
|
// part of the vertex array's state.
|
|
418
443
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
|
|
419
|
-
handleAttribute(gl, location, size, 0, 0, glType, isIntKind, normalized, instanced)
|
|
444
|
+
handleAttribute(gl, location, size, 0, 0, glType, isIntKind, normalized, instanced, name)
|
|
420
445
|
return once(() => {
|
|
421
|
-
|
|
446
|
+
if (hasInstancing(gl)) {
|
|
447
|
+
gl.vertexAttribDivisor(location, previousDivisor)
|
|
448
|
+
}
|
|
422
449
|
})
|
|
423
450
|
}
|
|
424
451
|
|
|
@@ -580,6 +607,7 @@ export function interleavedAttributeView<T extends InterleavedAttributeSchema>(
|
|
|
580
607
|
isIntKind,
|
|
581
608
|
normalized,
|
|
582
609
|
divisor === 1,
|
|
610
|
+
name,
|
|
583
611
|
)
|
|
584
612
|
})
|
|
585
613
|
|
|
@@ -602,10 +630,11 @@ export function interleavedAttributeView<T extends InterleavedAttributeSchema>(
|
|
|
602
630
|
handle(divisor)
|
|
603
631
|
}
|
|
604
632
|
return once(() => {
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
633
|
+
if (hasInstancing(gl)) {
|
|
634
|
+
previousDivisors.forEach(([location, previous]) => {
|
|
635
|
+
gl.vertexAttribDivisor(location, previous)
|
|
636
|
+
})
|
|
637
|
+
}
|
|
609
638
|
})
|
|
610
639
|
}
|
|
611
640
|
|
package/src/tag.ts
CHANGED
|
@@ -110,12 +110,7 @@ export function compile<
|
|
|
110
110
|
TVertex extends GLSL,
|
|
111
111
|
TFragment extends GLSL,
|
|
112
112
|
TSchema extends ViewSchemaPartial,
|
|
113
|
-
>(
|
|
114
|
-
gl: WebGLRenderingContext,
|
|
115
|
-
vertex: TVertex,
|
|
116
|
-
fragment: TFragment,
|
|
117
|
-
options?: CompileOptions<TSchema> | undefined,
|
|
118
|
-
) {
|
|
113
|
+
>(gl: GL, vertex: TVertex, fragment: TFragment, options?: CompileOptions<TSchema> | undefined) {
|
|
119
114
|
const _vertex = resolveGLSLTag(vertex, options) as { template: string; schema: ViewSchema }
|
|
120
115
|
const _fragment = resolveGLSLTag(fragment, options) as { template: string; schema: ViewSchema }
|
|
121
116
|
|
package/src/types.ts
CHANGED
|
@@ -6,7 +6,120 @@ import { DeepMerge, Prettify, ShallowMerge } from './type-utils'
|
|
|
6
6
|
/* */
|
|
7
7
|
/**********************************************************************************/
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
type NumericKeys<T> = {
|
|
10
|
+
[K in keyof T]: T[K] extends number ? K : never
|
|
11
|
+
}[keyof T]
|
|
12
|
+
|
|
13
|
+
/** What a WebGL1 context has and view.gl calls. */
|
|
14
|
+
type WebGL1Core = Pick<
|
|
15
|
+
WebGLRenderingContext,
|
|
16
|
+
| 'activeTexture'
|
|
17
|
+
| 'attachShader'
|
|
18
|
+
| 'bindBuffer'
|
|
19
|
+
| 'bindFramebuffer'
|
|
20
|
+
| 'bindTexture'
|
|
21
|
+
| 'bufferData'
|
|
22
|
+
| 'bufferSubData'
|
|
23
|
+
| 'checkFramebufferStatus'
|
|
24
|
+
| 'compileShader'
|
|
25
|
+
| 'createBuffer'
|
|
26
|
+
| 'createFramebuffer'
|
|
27
|
+
| 'createProgram'
|
|
28
|
+
| 'createShader'
|
|
29
|
+
| 'createTexture'
|
|
30
|
+
| 'deleteBuffer'
|
|
31
|
+
| 'deleteFramebuffer'
|
|
32
|
+
| 'deleteProgram'
|
|
33
|
+
| 'deleteShader'
|
|
34
|
+
| 'deleteTexture'
|
|
35
|
+
| 'disableVertexAttribArray'
|
|
36
|
+
| 'enableVertexAttribArray'
|
|
37
|
+
| 'framebufferTexture2D'
|
|
38
|
+
| 'getAttribLocation'
|
|
39
|
+
| 'getError'
|
|
40
|
+
| 'getParameter'
|
|
41
|
+
| 'getProgramInfoLog'
|
|
42
|
+
| 'getProgramParameter'
|
|
43
|
+
| 'getShaderInfoLog'
|
|
44
|
+
| 'getShaderParameter'
|
|
45
|
+
| 'getUniformLocation'
|
|
46
|
+
| 'getVertexAttrib'
|
|
47
|
+
| 'linkProgram'
|
|
48
|
+
| 'shaderSource'
|
|
49
|
+
| 'texImage2D'
|
|
50
|
+
| 'texParameteri'
|
|
51
|
+
| 'uniform1f'
|
|
52
|
+
| 'uniform1fv'
|
|
53
|
+
| 'uniform1i'
|
|
54
|
+
| 'uniform1iv'
|
|
55
|
+
| 'uniform2f'
|
|
56
|
+
| 'uniform2fv'
|
|
57
|
+
| 'uniform2i'
|
|
58
|
+
| 'uniform2iv'
|
|
59
|
+
| 'uniform3f'
|
|
60
|
+
| 'uniform3fv'
|
|
61
|
+
| 'uniform3i'
|
|
62
|
+
| 'uniform3iv'
|
|
63
|
+
| 'uniform4f'
|
|
64
|
+
| 'uniform4fv'
|
|
65
|
+
| 'uniform4i'
|
|
66
|
+
| 'uniform4iv'
|
|
67
|
+
| 'uniformMatrix2fv'
|
|
68
|
+
| 'uniformMatrix3fv'
|
|
69
|
+
| 'uniformMatrix4fv'
|
|
70
|
+
| 'vertexAttrib1f'
|
|
71
|
+
| 'vertexAttrib2f'
|
|
72
|
+
| 'vertexAttrib3f'
|
|
73
|
+
| 'vertexAttrib4f'
|
|
74
|
+
| 'vertexAttribPointer'
|
|
75
|
+
> &
|
|
76
|
+
Readonly<Record<NumericKeys<WebGLRenderingContext>, number>>
|
|
77
|
+
|
|
78
|
+
/** Instancing: a WebGL2 context's own, or a wrapper's, under the WebGL2 names. */
|
|
79
|
+
export type Instancing = Pick<
|
|
80
|
+
WebGL2RenderingContext,
|
|
81
|
+
'vertexAttribDivisor' | 'drawArraysInstanced' | 'drawElementsInstanced'
|
|
82
|
+
> & { readonly VERTEX_ATTRIB_ARRAY_DIVISOR: number }
|
|
83
|
+
|
|
84
|
+
/** Vertex arrays: a WebGL2 context's own, or a wrapper's, under the WebGL2 names. */
|
|
85
|
+
export type VertexArrays = Pick<
|
|
86
|
+
WebGL2RenderingContext,
|
|
87
|
+
'createVertexArray' | 'bindVertexArray' | 'deleteVertexArray'
|
|
88
|
+
> & { readonly VERTEX_ARRAY_BINDING: number }
|
|
89
|
+
|
|
90
|
+
/** WebGL2-only members view.gl reaches for where a schema asks for them. */
|
|
91
|
+
type WebGL2Only = Pick<
|
|
92
|
+
WebGL2RenderingContext,
|
|
93
|
+
| 'vertexAttribIPointer'
|
|
94
|
+
| 'uniform1ui'
|
|
95
|
+
| 'uniform1uiv'
|
|
96
|
+
| 'uniform2ui'
|
|
97
|
+
| 'uniform2uiv'
|
|
98
|
+
| 'uniform3ui'
|
|
99
|
+
| 'uniform3uiv'
|
|
100
|
+
| 'uniform4ui'
|
|
101
|
+
| 'uniform4uiv'
|
|
102
|
+
| 'uniformMatrix2x3fv'
|
|
103
|
+
| 'uniformMatrix2x4fv'
|
|
104
|
+
| 'uniformMatrix3x2fv'
|
|
105
|
+
| 'uniformMatrix3x4fv'
|
|
106
|
+
| 'uniformMatrix4x2fv'
|
|
107
|
+
| 'uniformMatrix4x3fv'
|
|
108
|
+
| 'RGBA32F'
|
|
109
|
+
| 'RGB32F'
|
|
110
|
+
| 'RGBA16F'
|
|
111
|
+
| 'RGB16F'
|
|
112
|
+
| 'HALF_FLOAT'
|
|
113
|
+
>
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* The context view.gl draws with: what a WebGL1 context has, plus each WebGL2
|
|
117
|
+
* feature as optional members under its WebGL2 names. A WebGL2 context is one
|
|
118
|
+
* as it is. A WebGL1 context with the extensions is one once a wrapper puts
|
|
119
|
+
* the extension's calls on it under the WebGL2 names; view.gl asks the context
|
|
120
|
+
* nothing and looks no extension up.
|
|
121
|
+
*/
|
|
122
|
+
export type GL = WebGL1Core & Partial<Instancing> & Partial<VertexArrays> & Partial<WebGL2Only>
|
|
10
123
|
|
|
11
124
|
export type GLTarget = 'ARRAY_BUFFER' | 'ELEMENT_ARRAY_BUFFER'
|
|
12
125
|
export type GLUsage = 'STATIC_DRAW' | 'DYNAMIC_DRAW' | 'STREAM_DRAW'
|