@bigmistqke/view.gl 0.1.7 → 0.1.8

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 CHANGED
@@ -1,56 +1,61 @@
1
1
  # 👁️ @bigmistqke/view.gl
2
2
 
3
- 🔧 Minimal library for managing WebGL uniforms / (interleaved) attributes / buffers / ...
3
+ 🔧 Utilities for managing WebGL resources: uniforms, (interleaved) attributes and buffers.
4
4
 
5
5
  - schema-based resource management [`view-gl`](#️-viewgl)
6
- - type-safe GLSL template literals to compose schemas [`view-gl/tag`](#️-viewgltag)
6
+ - compose schema and shader simultaneously via a tag template literal [`view-gl/tag`](#️-viewgltag)
7
7
 
8
8
  ## Table of Contents
9
9
 
10
- - [📦 Install](#-install)
11
- - [👁️ view.gl](#️-viewgl)
12
- - [🚀 Basic Usage](#-basic-usage)
13
- - [👁️ view](#️-view)
14
- - [📋 ViewSchema](#-viewschema)
15
- - [👀 Resource Views](#-resource-views)
16
- - [🎯 uniformView](#-uniformview)
17
- - [📋 UniformSchema](#-uniformschema)
18
- - [📝 attributeView](#-attributeview)
19
- - [📋 AttributeSchema](#-attributeschema)
20
- - [🔗 interleavedAttributeView](#-interleavedattributeview)
21
- - [📋 InterleavedAttributeSchema](#-interleavedattributeschema)
22
- - [🗂️ bufferView](#-bufferview)
23
- - [📋 BufferSchema](#-bufferschema)
24
- - [🏷️ view.gl/tag](#️-viewgltag)
25
- - [🚀 Basic Usage](#-basic-usage-1)
26
- - [📝 glsl](#-glsl)
27
- - [🧩 GLSL Fragment](#-glsl-fragment)
28
- - [🔒 Symbol Variables](#-symbol-variables)
10
+ - 📦 [Install](#-install)
11
+ - 👁️ [view.gl](#️-viewgl)
12
+ - 🚀 [Basic Usage](#-basic-usage)
13
+ - 👁️ [view](#️-view)
14
+ - 📋 [ViewSchema](#-viewschema)
15
+ - 👀 [Resource Views](#-resource-views)
16
+ - 🎯 [uniformView](#-uniformview)
17
+ - 📋 [UniformSchema](#-uniformschema)
18
+ - 📝 [attributeView](#-attributeview)
19
+ - 📋 [AttributeSchema](#-attributeschema)
20
+ - 🔗 [interleavedAttributeView](#-interleavedattributeview)
21
+ - 📋 [InterleavedAttributeSchema](#-interleavedattributeschema)
22
+ - 🗂️ [bufferView](#-bufferview)
23
+ - 📋 [BufferSchema](#-bufferschema)
24
+ - 🏷️ [view.gl/tag](#️-viewgltag)
25
+ - 🚀 [Basic Usage](#-basic-usage-1)
26
+ - 📝 [glsl](#-glsl)
27
+ - 🧩 [GLSL Fragment](#-glsl-fragment)
28
+ - 🔒 [Symbol Variables](#-symbol-variables)
29
29
  - [WebGL Version Support](#webgl-version-support)
30
- - [⚙️ Resource Tags](#️-resource-tags)
31
- - [🎯 uniform[kind](name, options?)](#-uniformkindname-options)
32
- - [📝 attribute[kind](name, options?)](#-attributekindname-options)
33
- - [🔗 interleave(name, layout, options?)](#-interleavename-layout-options)
34
- - [⚙️ compile(gl, vertex, fragment)](#️-compilegl-vertex-fragment)
35
- - [🔍 compile.toString(shader)](#-compiletostringshader)
36
- - [📋 compile.toSchema(shader)](#-compiletoschemaschader)
37
- - [🛠️ Utils](#️-utils)
38
- - [🏗️ createProgram](#️-createprogram)
39
- - [🖼️ createTexture](#️-createtexture)
40
- - [🖥️ createFramebuffer](#️-createframebuffer)
41
- - [🔍 WebGL Type Compatibility](#-webgl-type-compatibility)
42
- - [🎯 Uniform Types](#-uniform-types)
43
- - [📝 Attribute Types](#-attribute-types)
30
+ - 🏷️ [Resource Tokens](#️-resource-tokens)
31
+ - 🎯 [uniform[kind](name, options?)](#-uniformkindname-options)
32
+ - 📝 [attribute[kind](name, options?)](#-attributekindname-options)
33
+ - 🔗 [interleave(name, layout, options?)](#-interleavename-layout-options)
34
+ - ⚙️ [compile(gl, vertex, fragment)](#️-compilegl-vertex-fragment)
35
+ - 🔍 [compile.toString(shader)](#-compiletostringshader)
36
+ - 📋 [compile.toSchema(shader)](#-compiletoschemaschader)
37
+ - 🛠️ [Utils](#️-utils)
38
+ - 🏗️ [createProgram](#️-createprogram)
39
+ - 🖼️ [createTexture](#️-createtexture)
40
+ - 🖥️ [createFramebuffer](#️-createframebuffer)
41
+ - 🔍 [WebGL Type Compatibility](#-webgl-type-compatibility)
42
+ - 🎯 [Uniform Types](#-uniform-types)
43
+ - 📝 [Attribute Types](#-attribute-types)
44
44
 
45
45
  ## 📦 Install
46
46
 
47
47
  ```shell
48
48
  npm install @bigmistqke/view.gl
49
- # or
49
+ ```
50
+ ```shell
50
51
  pnpm add @bigmistqke/view.gl
51
- # or
52
+ ```
53
+ ```shell
52
54
  yarn add @bigmistqke/view.gl
53
55
  ```
56
+ ```shell
57
+ bun add @bigmistqke/view.gl
58
+ ```
54
59
 
55
60
  ## 👁️ view.gl
56
61
 
@@ -314,7 +319,7 @@ type BufferSchema = Record<string | symbol, BufferDefinition>
314
319
 
315
320
  ## 🏷️ view.gl/tag
316
321
 
317
- Type-safe GLSL template literals with automatic schema extraction.
322
+ Type-safe GLSL template literals with automatic schema extraction and view creation.
318
323
 
319
324
  - **Embedded Resources**: Define uniforms, attributes, and interleaved layouts directly in GLSL
320
325
  - **Type Inference**: Automatically infers schema types and creates type-safe view
@@ -448,9 +453,9 @@ const shader = glsl`#version 300 es
448
453
  `
449
454
  ```
450
455
 
451
- ### ⚙️ Resource Tags
456
+ ### 🏷️ Resource Tokens
452
457
 
453
- Functions for defining WebGL resources directly in GLSL templates. These tags generate GLSL declarations and automatically extract type-safe schemas for use with the view system.
458
+ Utilities for defining WebGL resources directly in GLSL templates. These create metadata that the [`compile`](#️-compilegl-vertex-fragment-overrideschema) consumes to generate the typesafe schema and view.
454
459
 
455
460
  #### 🎯 uniform[kind](name, options?)
456
461
 
@@ -543,15 +548,19 @@ const vertexShader = glsl`
543
548
 
544
549
  ### ⚙️ compile(gl, vertex, fragment, overrideSchema?)
545
550
 
546
- Compiles shaders and extracts schema from embedded resources. Returns both the compiled program and a ready-to-use view.
551
+ Compiles shaders to a `WebGLProgram` and extracts typesafe schema and view.
547
552
 
548
553
  ```typescript
549
- const { program, schema, view } = compile(gl, vertexShader, fragmentShader)
554
+ const { program, schema, view, vertex, fragment } = compile(gl, vertexShader, fragmentShader)
550
555
 
551
556
  // Use the view directly
552
557
  view.uniforms.time.set(performance.now())
553
558
  view.attributes.position.set(vertexData).bind()
554
559
 
560
+ // Access the compiled shader strings
561
+ console.log(vertex) // Compiled vertex shader GLSL
562
+ console.log(fragment) // Compiled fragment shader GLSL
563
+
555
564
  // Or access the extracted schema
556
565
  console.log(schema.uniforms) // { time: { kind: 'float' }, ... }
557
566
  console.log(schema.attributes) // { position: { kind: 'vec3' }, ... }
@@ -583,6 +592,8 @@ view.buffers.indices.set(indexData).bind()
583
592
  - `program`: Compiled WebGL program
584
593
  - `schema`: Merged schema (extracted + override)
585
594
  - `view`: Ready-to-use view with type-safe resource access
595
+ - `vertex`: Compiled vertex shader GLSL string
596
+ - `fragment`: Compiled fragment shader GLSL string
586
597
 
587
598
  #### 🔍 compile.toString(shader)
588
599
 
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-C4TRuvYh.mjs';
2
- export { v as AttributeDefinition, u as AttributeKind, w as AttributeMethods, t as AttributeShortHand, a1 as AttributeTag, a2 as AttributeTagFn, C as BufferDefinition, D as BufferMethods, a7 as CompileResult, R as Format, E as Framebuffer, F as FramebufferDefinition, Y as GLSLResult, Z as GLSLSlot, a5 as GLSLSlotsToSchema, _ as GLSLTag, a4 as GLSLTagToSchema, g as GLTarget, l as GLTextureFilter, j as GLTextureFormat, i as GLTextureTarget, k as GLTextureType, m as GLTextureWrap, h as GLUsage, a3 as InterleaveTag, y as InterleavedAttributeDefinition, x as InterleavedAttributeLayout, z as InterleavedAttributeMethods, Q as InternalFormat, n as KIND_TO_SIZE_MAP, K as KIND_TO_UNIFORM_FN_NAME_MAP, a6 as MergeGLSLSchema, S as PixelType, W as TexImage2DOptions, T as TextureDefinition, L as TextureMethods, N as TextureParameterName, O as TextureParameterValue, P as TextureParameters, J as TextureSchema, H as TextureTarget, M as TextureView, q as UniformDefinition, o as UniformFnName, p as UniformKind, s as UniformMethods, r as UniformSchemaPartial, $ as UniformTag, a0 as UniformTagFn, X as ViewSchemaPartial } from './types-C4TRuvYh.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-Bp9VAVe3.mjs';
2
+ export { v as AttributeDefinition, u as AttributeKind, w as AttributeMethods, t as AttributeShortHand, a1 as AttributeToken, a2 as AttributeTokenFn, C as BufferDefinition, D as BufferMethods, a8 as CompileResult, R as Format, E as Framebuffer, F as FramebufferDefinition, _ as GLSL, Y as GLSLResult, Z as GLSLSlot, a6 as GLSLSlotsToSchema, a4 as GLSLToSchema, a5 as GLSLToView, g as GLTarget, l as GLTextureFilter, j as GLTextureFormat, i as GLTextureTarget, k as GLTextureType, m as GLTextureWrap, h as GLUsage, a3 as InterleaveToken, y as InterleavedAttributeDefinition, x as InterleavedAttributeLayout, z as InterleavedAttributeMethods, Q as InternalFormat, n as KIND_TO_SIZE_MAP, K as KIND_TO_UNIFORM_FN_NAME_MAP, a7 as MergeGLSLSchema, S as PixelType, W as TexImage2DOptions, T as TextureDefinition, L as TextureMethods, N as TextureParameterName, O as TextureParameterValue, P as TextureParameters, J as TextureSchema, H as TextureTarget, M as TextureView, q as UniformDefinition, o as UniformFnName, p as UniformKind, s as UniformMethods, r as UniformSchemaPartial, $ as UniformToken, a0 as UniformTokenFn, X as ViewSchemaPartial } from './types-Bp9VAVe3.mjs';
3
3
 
4
4
  declare function toID(key: string | number | symbol): any;
5
5
  /**********************************************************************************/
package/dist/tag.d.mts CHANGED
@@ -1,81 +1,81 @@
1
- import { Z as GLSLSlot, _ as GLSLTag, a0 as UniformTagFn, a2 as AttributeTagFn, a1 as AttributeTag, u as AttributeKind, v as AttributeDefinition, a3 as InterleaveTag, X as ViewSchemaPartial, a8 as Prettify, a7 as CompileResult, a4 as GLSLTagToSchema } from './types-C4TRuvYh.mjs';
1
+ import { Z as GLSLSlot, _ as GLSL, a0 as UniformTokenFn, a2 as AttributeTokenFn, a1 as AttributeToken, u as AttributeKind, v as AttributeDefinition, a3 as InterleaveToken, X as ViewSchemaPartial, a9 as Prettify, a8 as CompileResult, a4 as GLSLToSchema } from './types-Bp9VAVe3.mjs';
2
2
 
3
- declare function glsl<TSlot extends GLSLSlot, TSlots extends TSlot[]>(template: TemplateStringsArray, ...slots: [...TSlots]): GLSLTag<TSlots>;
3
+ declare function glsl<TSlot extends GLSLSlot, TSlots extends TSlot[]>(template: TemplateStringsArray, ...slots: [...TSlots]): GLSL<TSlots>;
4
4
  declare const uniform: {
5
- float: UniformTagFn<"float">;
6
- vec2: UniformTagFn<"vec2">;
7
- vec3: UniformTagFn<"vec3">;
8
- vec4: UniformTagFn<"vec4">;
9
- int: UniformTagFn<"int">;
10
- ivec2: UniformTagFn<"ivec2">;
11
- ivec3: UniformTagFn<"ivec3">;
12
- ivec4: UniformTagFn<"ivec4">;
13
- bool: UniformTagFn<"bool">;
14
- bvec2: UniformTagFn<"bvec2">;
15
- bvec3: UniformTagFn<"bvec3">;
16
- bvec4: UniformTagFn<"bvec4">;
17
- mat2: UniformTagFn<"mat2">;
18
- mat3: UniformTagFn<"mat3">;
19
- mat4: UniformTagFn<"mat4">;
20
- sampler2D: UniformTagFn<"sampler2D">;
21
- samplerCube: UniformTagFn<"samplerCube">;
22
- uint: UniformTagFn<"uint">;
23
- uvec2: UniformTagFn<"uvec2">;
24
- uvec3: UniformTagFn<"uvec3">;
25
- uvec4: UniformTagFn<"uvec4">;
26
- mat2x3: UniformTagFn<"mat2x3">;
27
- mat2x4: UniformTagFn<"mat2x4">;
28
- mat3x2: UniformTagFn<"mat3x2">;
29
- mat3x4: UniformTagFn<"mat3x4">;
30
- mat4x2: UniformTagFn<"mat4x2">;
31
- mat4x3: UniformTagFn<"mat4x3">;
32
- sampler3D: UniformTagFn<"sampler3D">;
33
- sampler2DArray: UniformTagFn<"sampler2DArray">;
34
- sampler2DShadow: UniformTagFn<"sampler2DShadow">;
35
- samplerCubeShadow: UniformTagFn<"samplerCubeShadow">;
36
- sampler2DArrayShadow: UniformTagFn<"sampler2DArrayShadow">;
37
- isampler2D: UniformTagFn<"isampler2D">;
38
- isampler3D: UniformTagFn<"isampler3D">;
39
- isamplerCube: UniformTagFn<"isamplerCube">;
40
- isampler2DArray: UniformTagFn<"isampler2DArray">;
41
- usampler2D: UniformTagFn<"usampler2D">;
42
- usampler3D: UniformTagFn<"usampler3D">;
43
- usamplerCube: UniformTagFn<"usamplerCube">;
44
- usampler2DArray: UniformTagFn<"usampler2DArray">;
5
+ float: UniformTokenFn<"float">;
6
+ vec2: UniformTokenFn<"vec2">;
7
+ vec3: UniformTokenFn<"vec3">;
8
+ vec4: UniformTokenFn<"vec4">;
9
+ int: UniformTokenFn<"int">;
10
+ ivec2: UniformTokenFn<"ivec2">;
11
+ ivec3: UniformTokenFn<"ivec3">;
12
+ ivec4: UniformTokenFn<"ivec4">;
13
+ bool: UniformTokenFn<"bool">;
14
+ bvec2: UniformTokenFn<"bvec2">;
15
+ bvec3: UniformTokenFn<"bvec3">;
16
+ bvec4: UniformTokenFn<"bvec4">;
17
+ mat2: UniformTokenFn<"mat2">;
18
+ mat3: UniformTokenFn<"mat3">;
19
+ mat4: UniformTokenFn<"mat4">;
20
+ sampler2D: UniformTokenFn<"sampler2D">;
21
+ samplerCube: UniformTokenFn<"samplerCube">;
22
+ uint: UniformTokenFn<"uint">;
23
+ uvec2: UniformTokenFn<"uvec2">;
24
+ uvec3: UniformTokenFn<"uvec3">;
25
+ uvec4: UniformTokenFn<"uvec4">;
26
+ mat2x3: UniformTokenFn<"mat2x3">;
27
+ mat2x4: UniformTokenFn<"mat2x4">;
28
+ mat3x2: UniformTokenFn<"mat3x2">;
29
+ mat3x4: UniformTokenFn<"mat3x4">;
30
+ mat4x2: UniformTokenFn<"mat4x2">;
31
+ mat4x3: UniformTokenFn<"mat4x3">;
32
+ sampler3D: UniformTokenFn<"sampler3D">;
33
+ sampler2DArray: UniformTokenFn<"sampler2DArray">;
34
+ sampler2DShadow: UniformTokenFn<"sampler2DShadow">;
35
+ samplerCubeShadow: UniformTokenFn<"samplerCubeShadow">;
36
+ sampler2DArrayShadow: UniformTokenFn<"sampler2DArrayShadow">;
37
+ isampler2D: UniformTokenFn<"isampler2D">;
38
+ isampler3D: UniformTokenFn<"isampler3D">;
39
+ isamplerCube: UniformTokenFn<"isamplerCube">;
40
+ isampler2DArray: UniformTokenFn<"isampler2DArray">;
41
+ usampler2D: UniformTokenFn<"usampler2D">;
42
+ usampler3D: UniformTokenFn<"usampler3D">;
43
+ usamplerCube: UniformTokenFn<"usamplerCube">;
44
+ usampler2DArray: UniformTokenFn<"usampler2DArray">;
45
45
  };
46
46
  declare const attribute: {
47
- float: AttributeTagFn<"float">;
48
- vec2: AttributeTagFn<"vec2">;
49
- vec3: AttributeTagFn<"vec3">;
50
- vec4: AttributeTagFn<"vec4">;
51
- int: AttributeTagFn<"int">;
52
- ivec2: AttributeTagFn<"ivec2">;
53
- ivec3: AttributeTagFn<"ivec3">;
54
- ivec4: AttributeTagFn<"ivec4">;
55
- mat2: AttributeTagFn<"mat2">;
56
- mat3: AttributeTagFn<"mat3">;
57
- mat4: AttributeTagFn<"mat4">;
58
- uint: AttributeTagFn<"uint">;
59
- uvec2: AttributeTagFn<"uvec2">;
60
- uvec3: AttributeTagFn<"uvec3">;
61
- uvec4: AttributeTagFn<"uvec4">;
62
- mat2x3: AttributeTagFn<"mat2x3">;
63
- mat2x4: AttributeTagFn<"mat2x4">;
64
- mat3x2: AttributeTagFn<"mat3x2">;
65
- mat3x4: AttributeTagFn<"mat3x4">;
66
- mat4x2: AttributeTagFn<"mat4x2">;
67
- mat4x3: AttributeTagFn<"mat4x3">;
47
+ float: AttributeTokenFn<"float">;
48
+ vec2: AttributeTokenFn<"vec2">;
49
+ vec3: AttributeTokenFn<"vec3">;
50
+ vec4: AttributeTokenFn<"vec4">;
51
+ int: AttributeTokenFn<"int">;
52
+ ivec2: AttributeTokenFn<"ivec2">;
53
+ ivec3: AttributeTokenFn<"ivec3">;
54
+ ivec4: AttributeTokenFn<"ivec4">;
55
+ mat2: AttributeTokenFn<"mat2">;
56
+ mat3: AttributeTokenFn<"mat3">;
57
+ mat4: AttributeTokenFn<"mat4">;
58
+ uint: AttributeTokenFn<"uint">;
59
+ uvec2: AttributeTokenFn<"uvec2">;
60
+ uvec3: AttributeTokenFn<"uvec3">;
61
+ uvec4: AttributeTokenFn<"uvec4">;
62
+ mat2x3: AttributeTokenFn<"mat2x3">;
63
+ mat2x4: AttributeTokenFn<"mat2x4">;
64
+ mat3x2: AttributeTokenFn<"mat3x2">;
65
+ mat3x4: AttributeTokenFn<"mat3x4">;
66
+ mat4x2: AttributeTokenFn<"mat4x2">;
67
+ mat4x3: AttributeTokenFn<"mat4x3">;
68
68
  };
69
- declare function interleave<const TKey extends string | symbol, const TLayout extends Array<AttributeTag<string | symbol, AttributeKind, undefined>>, const TOptions extends Omit<AttributeDefinition, 'kind'>>(key: TKey, layout: TLayout, instanced: TOptions): InterleaveTag<TKey, TLayout, TOptions>;
70
- declare function interleave<const TKey extends string | symbol, const TLayout extends Array<AttributeTag<string | symbol, AttributeKind, undefined>>>(key: TKey, layout: TLayout): InterleaveTag<TKey, TLayout, {
69
+ declare function interleave<const TKey extends string | symbol, const TLayout extends Array<AttributeToken<string | symbol, AttributeKind, undefined>>, const TOptions extends Omit<AttributeDefinition, 'kind'>>(key: TKey, layout: TLayout, instanced: TOptions): InterleaveToken<TKey, TLayout, TOptions>;
70
+ declare function interleave<const TKey extends string | symbol, const TLayout extends Array<AttributeToken<string | symbol, AttributeKind, undefined>>>(key: TKey, layout: TLayout): InterleaveToken<TKey, TLayout, {
71
71
  instanced: false;
72
72
  }>;
73
73
  /**********************************************************************************/
74
74
  /**********************************************************************************/
75
- declare function compile<TVertex extends GLSLTag, TFragment extends GLSLTag, TOverride extends ViewSchemaPartial>(gl: WebGLRenderingContext, vertex: TVertex, fragment: TFragment, overrideSchema?: TOverride): Prettify<CompileResult<TVertex, TFragment, TOverride>>;
75
+ declare function compile<TVertex extends GLSL, TFragment extends GLSL, TOverride extends ViewSchemaPartial>(gl: WebGLRenderingContext, vertex: TVertex, fragment: TFragment, overrideSchema?: TOverride): Prettify<CompileResult<TVertex, TFragment, TOverride>>;
76
76
  declare namespace compile {
77
- var toSchema: <TTag extends GLSLTag>(tag: TTag) => Prettify<GLSLTagToSchema<TTag>>;
78
- var toString: <TTag extends GLSLTag>({ template: [initial, ...rest], slots }: TTag) => string;
77
+ var toSchema: <TTag extends GLSL>(tag: TTag) => Prettify<GLSLToSchema<TTag>>;
78
+ var toString: <TTag extends GLSL>({ template: [initial, ...rest], slots }: TTag) => string;
79
79
  }
80
80
 
81
81
  export { attribute, compile, glsl, interleave, uniform };
package/dist/tag.mjs CHANGED
@@ -424,7 +424,9 @@ function compile(gl, vertex, fragment, overrideSchema) {
424
424
  return {
425
425
  program,
426
426
  schema,
427
- view: view(gl, program, schema)
427
+ view: view(gl, program, schema),
428
+ vertex: _vertex.template,
429
+ fragment: _fragment.template
428
430
  };
429
431
  }
430
432
  function resolveGLSLTag(tag) {
package/dist/tag.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/features.ts","../src/utils/object.ts","../src/utils/index.ts","../src/index.ts","../src/tag.ts"],"sourcesContent":["import { RemoveSuffix } from './type-utils'\nimport type { GL } from './types'\n\nconst INSTANCED_ARRAYS_WRAPPER_MAP = new WeakMap<\n GL,\n RemoveSuffix<\n Pick<\n ANGLE_instanced_arrays,\n 'drawArraysInstancedANGLE' | 'drawElementsInstancedANGLE' | 'vertexAttribDivisorANGLE'\n >,\n 'ANGLE'\n > | null\n>()\nexport function getInstancedArrays(gl: GL) {\n if (gl instanceof WebGL2RenderingContext) return gl\n\n const cached = INSTANCED_ARRAYS_WRAPPER_MAP.get(gl)\n if (cached) return cached\n\n const ext = gl.getExtension('ANGLE_instanced_arrays')\n if (!ext) return undefined\n\n const wrapper = {\n drawArraysInstanced: ext.drawArraysInstancedANGLE.bind(ext),\n drawElementsInstanced: ext.drawElementsInstancedANGLE.bind(ext),\n vertexAttribDivisor: ext.vertexAttribDivisorANGLE.bind(ext),\n }\n INSTANCED_ARRAYS_WRAPPER_MAP.set(gl, wrapper)\n\n return wrapper\n}\n\nconst VERTEX_ARRAY_OBJECT_WRAPPER_MAP = new WeakMap<\n GL,\n RemoveSuffix<\n Pick<\n OES_vertex_array_object,\n 'bindVertexArrayOES' | 'createVertexArrayOES' | 'deleteVertexArrayOES'\n >,\n 'OES'\n > | null\n>()\nexport function getVertexArrayObject(gl: GL) {\n if (gl instanceof WebGL2RenderingContext) return gl\n\n const cached = VERTEX_ARRAY_OBJECT_WRAPPER_MAP.get(gl)\n if (cached) return cached\n\n const ext = gl.getExtension('OES_vertex_array_object')\n if (!ext) return null\n\n const wrapper = {\n bindVertexArray: ext.bindVertexArrayOES.bind(ext),\n createVertexArray: ext.createVertexArrayOES.bind(ext),\n deleteVertexArray: ext.deleteVertexArrayOES.bind(ext),\n }\n VERTEX_ARRAY_OBJECT_WRAPPER_MAP.set(gl, wrapper)\n\n return wrapper\n}\n","export function forEach<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 map<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 forEach(value, (value, key, index) => {\n result[key] = callback(value, key, index)\n })\n\n return result\n}\n","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 * as ObjectUtils from './object'\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\nfunction createGLShader(gl: GL, type: number, source: string): WebGLShader {\n const shader = gl.createShader(type)\n if (!shader) throw new Error('Failed to create shader')\n\n gl.shaderSource(shader, source)\n gl.compileShader(shader)\n\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const info = gl.getShaderInfoLog(shader)\n gl.deleteShader(shader)\n throw new Error(\n `Failed to compile ${type === gl.VERTEX_SHADER ? 'vertex' : 'fragment'} shader: ${info}`,\n )\n }\n\n return shader\n}\n\nexport function createProgram(gl: GL, vertexSource: string, fragmentSource: string): WebGLProgram {\n const program = gl.createProgram()\n if (!program) throw new Error('Failed to create WebGL program')\n\n const vertexShader = createGLShader(gl, gl.VERTEX_SHADER, vertexSource)\n const fragmentShader = createGLShader(gl, gl.FRAGMENT_SHADER, fragmentSource)\n\n gl.attachShader(program, vertexShader)\n gl.attachShader(program, fragmentShader)\n gl.linkProgram(program)\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n const info = gl.getProgramInfoLog(program)\n gl.deleteProgram(program)\n gl.deleteShader(vertexShader)\n gl.deleteShader(fragmentShader)\n throw new Error(`Failed to link program: ${info}`)\n }\n\n // Clean up shaders after linking\n gl.deleteShader(vertexShader)\n gl.deleteShader(fragmentShader)\n\n return program\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","import { getInstancedArrays, getVertexArrayObject } from './features'\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 assertedNotNullish,\n createUpsertMap,\n isMatKind,\n isSamplerKind,\n kindToSize,\n kindToUniformFnName,\n ObjectUtils,\n} from './utils'\nexport * from './types'\n\n/**********************************************************************************/\n/* */\n/* To ID */\n/* */\n/**********************************************************************************/\n\nlet index = 0\nconst PREFIX = 'VIEW_GL_ALIAS'\nconst IS_FIREFOX = navigator.userAgent.toLowerCase().indexOf('firefox') >= 0\n\n// NOTE: using symbol as key for WeakMap is currently broken in firefox\n// see https://bugzilla.mozilla.org/show_bug.cgi?id=1710433\n// fallback to Map will currently cause a memory leak.\nconst SYMBOL_MAP = createUpsertMap(IS_FIREFOX ? Map<symbol, string> : WeakMap<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 return ObjectUtils.map(schema, ({ kind, size }, key) => {\n const name = toID(key)\n\n const location = gl.getUniformLocation(program, name)\n\n if (isSamplerKind(kind)) {\n return {\n set(arg: number) {\n gl.uniform1i(location, arg)\n },\n }\n }\n\n const fnName = `uniform${kindToUniformFnName(kind)}${size ? 'v' : ''}`\n\n // @ts-ignore FIX WEBGL/WEBGL2 TYPES\n const fn = gl[fnName].bind(gl)\n\n if (isMatKind(kind)) {\n return {\n set(...args: any[]) {\n fn(location, false, args[0])\n },\n }\n }\n\n return {\n set(...args: any[]) {\n fn(location, ...args)\n },\n }\n })\n}\n\n/**********************************************************************************/\n/* */\n/* Attribute View */\n/* */\n/**********************************************************************************/\n\n// Shared attribute helper functions\n// between attributeView and interleavedAttributeView\nfunction handleAttribute(\n gl: GL,\n location: number,\n size: number,\n stride: number,\n offset: number,\n type: 'FLOAT' | 'INT',\n instanced?: boolean,\n) {\n gl.enableVertexAttribArray(location)\n gl.vertexAttribPointer(location, size, gl[type], false, stride, offset)\n\n if (instanced) {\n // Get instanced-arrays-feature: extension if webgl, gl if webgl2\n assertedNotNullish(getInstancedArrays(gl)).vertexAttribDivisor(location, 1)\n }\n}\n\nexport function attributeView<T extends AttributeSchema>(\n gl: GL,\n program: WebGLProgram,\n schema: T,\n { signal }: ViewOptions = {},\n): AttributeView<T> {\n const attributes = ObjectUtils.map(\n schema,\n (\n { kind, instanced, buffer = assertedNotNullish(gl.createBuffer()) },\n key,\n ): AttributeMethods => {\n const name = toID(key)\n\n const location = gl.getAttribLocation(program, name)\n if (location < 0) {\n throw new Error(`Attribute '${name}' not found`)\n }\n\n const size = kindToSize(kind)\n const type = kind.startsWith('i') ? 'INT' : 'FLOAT'\n\n return {\n buffer,\n bind() {\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n handleAttribute(gl, location, size, 0, 0, type, instanced)\n },\n dispose() {\n gl.deleteBuffer(buffer)\n },\n set(data, usage = 'STATIC_DRAW') {\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n gl.bufferData(gl.ARRAY_BUFFER, data, gl[usage])\n return this\n },\n }\n },\n )\n\n signal?.addEventListener('abort', function dispose() {\n ObjectUtils.forEach(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 = ObjectUtils.map(schema, ({ layout, instanced }) => {\n // Increment number to keep track of offset\n let index = 0\n\n // Calculate layout information\n const handles = layout.map(layout => {\n const name = toID(layout.key)\n\n const location = gl.getAttribLocation(program, name)\n\n if (location < 0) {\n throw new Error(`Attribute '${name}' not found`)\n }\n\n const size = kindToSize(layout.kind)\n const offset = index\n const type = layout.kind.startsWith('i') ? 'INT' : 'FLOAT'\n index += size * 4\n\n return () => handleAttribute(gl, location, size, stride, offset, type, instanced)\n })\n\n // Set stride to final index\n const stride = index\n\n // Create a buffer\n const buffer = assertedNotNullish(gl.createBuffer())\n\n // Create VAO to cache attribute state\n let vao: { unbind(): void; bind(): void; dispose(): void } | undefined = undefined\n\n // Get VAO-feature: extension if webgl1, gl if webgl2\n const feature = getVertexArrayObject(gl)\n if (feature) {\n const vertexArray = feature.createVertexArray()\n feature.bindVertexArray(vertexArray)\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n for (const handle of handles) {\n handle()\n }\n feature.bindVertexArray(null)\n vao = {\n unbind() {\n feature.bindVertexArray(null)\n },\n bind() {\n feature.bindVertexArray(vertexArray)\n },\n dispose() {\n feature.deleteVertexArray(vertexArray)\n },\n }\n }\n\n return {\n bind() {\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n if (vao) {\n vao.bind()\n } else {\n // Fallback: manual attribute setup\n for (const handle of handles) {\n handle()\n }\n }\n },\n unbind() {\n if (vao) {\n vao.unbind()\n }\n },\n dispose() {\n gl.deleteBuffer(buffer)\n if (vao) {\n vao.dispose()\n }\n },\n set(value, usage = 'STATIC_DRAW') {\n if (vao) {\n vao.bind()\n } else {\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n }\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 ObjectUtils.forEach(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 = ObjectUtils.map(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 ObjectUtils.forEach(buffers, value => value.dispose())\n })\n\n return buffers\n}\n","import { toID, view } from '.'\nimport type { Prettify } from './type-utils'\nimport type {\n AttributeDefinition,\n AttributeKind,\n AttributeTag,\n AttributeTagFn as AttributeTagMethod,\n CompileResult,\n GLSLSlot,\n GLSLTag,\n GLSLTagToSchema,\n InterleaveTag,\n UniformDefinition,\n UniformKind,\n UniformTagFn as UniformTagMethod,\n ViewSchema,\n ViewSchemaPartial,\n} from './types'\nimport { createProgram } from './utils'\n\nexport function glsl<TSlot extends GLSLSlot, TSlots extends TSlot[]>(\n template: TemplateStringsArray,\n ...slots: [...TSlots]\n): GLSLTag<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<AttributeTag<string | symbol, AttributeKind, undefined>>,\n const TOptions extends Omit<AttributeDefinition, 'kind'>,\n>(key: TKey, layout: TLayout, instanced: TOptions): InterleaveTag<TKey, TLayout, TOptions>\nexport function interleave<\n const TKey extends string | symbol,\n const TLayout extends Array<AttributeTag<string | symbol, AttributeKind, undefined>>,\n>(key: TKey, layout: TLayout): InterleaveTag<TKey, TLayout, { instanced: false }>\nexport function interleave<\n const TKey extends string | symbol,\n const TLayout extends Array<AttributeTag<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 InterleaveTag<TKey, TLayout, TOptions>\n}\n\n/**********************************************************************************/\n/* */\n/* Compile */\n/* */\n/**********************************************************************************/\n\nexport function compile<\n TVertex extends GLSLTag,\n TFragment extends GLSLTag,\n TOverride extends ViewSchemaPartial,\n>(gl: WebGLRenderingContext, vertex: TVertex, fragment: TFragment, overrideSchema?: TOverride) {\n const _vertex = resolveGLSLTag(vertex) as { template: string; schema: ViewSchema }\n const _fragment = resolveGLSLTag(fragment) 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 }\n\n for (const kind in overrideSchema) {\n const schemaKind = schema[kind as keyof typeof schema]\n const overrideSchemaKind = overrideSchema[kind]\n\n for (const key in overrideSchemaKind) {\n schemaKind[key] = {\n ...schemaKind[key],\n ...overrideSchemaKind[key],\n }\n }\n }\n\n const program = createProgram(gl, _vertex.template, _fragment.template)\n\n return {\n program,\n schema,\n view: view(gl, program, schema),\n } as Prettify<CompileResult<TVertex, TFragment, TOverride>>\n}\n\nfunction resolveGLSLTag<TTag extends GLSLTag>(tag: TTag) {\n return {\n template: compile.toString(tag),\n schema: compile.toSchema(tag),\n }\n}\n\ncompile.toSchema = function <TTag extends GLSLTag>(tag: TTag) {\n const result = {\n uniforms: {},\n attributes: {},\n interleavedAttributes: {},\n }\n\n function handleSlot(slot: GLSLSlot) {\n if (Array.isArray(slot)) {\n slot.forEach(handleSlot)\n return\n }\n\n if (typeof slot !== 'object') {\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 tag.slots.forEach(handleSlot)\n\n return result as unknown as Prettify<GLSLTagToSchema<TTag>>\n}\n\ncompile.toString = function <TTag extends GLSLTag>({ template: [initial, ...rest], slots }: TTag) {\n const v300 = !!initial?.startsWith('#version 300 es')\n\n let template = initial ?? ''\n\n for (let i = 0; i < rest.length; i++) {\n template += `${glslSlotToString(slots[i]!, v300)}${rest[i]}`\n }\n\n return template\n}\n\nfunction glslSlotToString(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 => glslSlotToString(slot, v300)).join('')\n }\n\n if (slot.type === 'glsl') {\n return compile.toString(slot)\n }\n\n if (slot.type === '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 }\n\n if (slot.type === 'uniform' && 'size' in slot) {\n return `${slot.type} ${slot.kind} ${toID(slot.key)}[${slot.size}];`\n }\n\n return `${slot.type === 'attribute' && v300 ? 'in' : slot.type} ${slot.kind} ${toID(slot.key)};`\n}\n"],"mappings":"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","names":["index","value","map","name","index","layout","key","name","slot"]}
1
+ {"version":3,"sources":["../src/features.ts","../src/utils/object.ts","../src/utils/index.ts","../src/index.ts","../src/tag.ts"],"sourcesContent":["import { RemoveSuffix } from './type-utils'\nimport type { GL } from './types'\n\nconst INSTANCED_ARRAYS_WRAPPER_MAP = new WeakMap<\n GL,\n RemoveSuffix<\n Pick<\n ANGLE_instanced_arrays,\n 'drawArraysInstancedANGLE' | 'drawElementsInstancedANGLE' | 'vertexAttribDivisorANGLE'\n >,\n 'ANGLE'\n > | null\n>()\nexport function getInstancedArrays(gl: GL) {\n if (gl instanceof WebGL2RenderingContext) return gl\n\n const cached = INSTANCED_ARRAYS_WRAPPER_MAP.get(gl)\n if (cached) return cached\n\n const ext = gl.getExtension('ANGLE_instanced_arrays')\n if (!ext) return undefined\n\n const wrapper = {\n drawArraysInstanced: ext.drawArraysInstancedANGLE.bind(ext),\n drawElementsInstanced: ext.drawElementsInstancedANGLE.bind(ext),\n vertexAttribDivisor: ext.vertexAttribDivisorANGLE.bind(ext),\n }\n INSTANCED_ARRAYS_WRAPPER_MAP.set(gl, wrapper)\n\n return wrapper\n}\n\nconst VERTEX_ARRAY_OBJECT_WRAPPER_MAP = new WeakMap<\n GL,\n RemoveSuffix<\n Pick<\n OES_vertex_array_object,\n 'bindVertexArrayOES' | 'createVertexArrayOES' | 'deleteVertexArrayOES'\n >,\n 'OES'\n > | null\n>()\nexport function getVertexArrayObject(gl: GL) {\n if (gl instanceof WebGL2RenderingContext) return gl\n\n const cached = VERTEX_ARRAY_OBJECT_WRAPPER_MAP.get(gl)\n if (cached) return cached\n\n const ext = gl.getExtension('OES_vertex_array_object')\n if (!ext) return null\n\n const wrapper = {\n bindVertexArray: ext.bindVertexArrayOES.bind(ext),\n createVertexArray: ext.createVertexArrayOES.bind(ext),\n deleteVertexArray: ext.deleteVertexArrayOES.bind(ext),\n }\n VERTEX_ARRAY_OBJECT_WRAPPER_MAP.set(gl, wrapper)\n\n return wrapper\n}\n","export function forEach<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 map<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 forEach(value, (value, key, index) => {\n result[key] = callback(value, key, index)\n })\n\n return result\n}\n","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 * as ObjectUtils from './object'\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\nfunction createGLShader(gl: GL, type: number, source: string): WebGLShader {\n const shader = gl.createShader(type)\n if (!shader) throw new Error('Failed to create shader')\n\n gl.shaderSource(shader, source)\n gl.compileShader(shader)\n\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const info = gl.getShaderInfoLog(shader)\n gl.deleteShader(shader)\n throw new Error(\n `Failed to compile ${type === gl.VERTEX_SHADER ? 'vertex' : 'fragment'} shader: ${info}`,\n )\n }\n\n return shader\n}\n\nexport function createProgram(gl: GL, vertexSource: string, fragmentSource: string): WebGLProgram {\n const program = gl.createProgram()\n if (!program) throw new Error('Failed to create WebGL program')\n\n const vertexShader = createGLShader(gl, gl.VERTEX_SHADER, vertexSource)\n const fragmentShader = createGLShader(gl, gl.FRAGMENT_SHADER, fragmentSource)\n\n gl.attachShader(program, vertexShader)\n gl.attachShader(program, fragmentShader)\n gl.linkProgram(program)\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n const info = gl.getProgramInfoLog(program)\n gl.deleteProgram(program)\n gl.deleteShader(vertexShader)\n gl.deleteShader(fragmentShader)\n throw new Error(`Failed to link program: ${info}`)\n }\n\n // Clean up shaders after linking\n gl.deleteShader(vertexShader)\n gl.deleteShader(fragmentShader)\n\n return program\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","import { getInstancedArrays, getVertexArrayObject } from './features'\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 assertedNotNullish,\n createUpsertMap,\n isMatKind,\n isSamplerKind,\n kindToSize,\n kindToUniformFnName,\n ObjectUtils,\n} from './utils'\nexport * from './types'\n\n/**********************************************************************************/\n/* */\n/* To ID */\n/* */\n/**********************************************************************************/\n\nlet index = 0\nconst PREFIX = 'VIEW_GL_ALIAS'\nconst IS_FIREFOX = navigator.userAgent.toLowerCase().indexOf('firefox') >= 0\n\n// NOTE: using symbol as key for WeakMap is currently broken in firefox\n// see https://bugzilla.mozilla.org/show_bug.cgi?id=1710433\n// fallback to Map will currently cause a memory leak.\nconst SYMBOL_MAP = createUpsertMap(IS_FIREFOX ? Map<symbol, string> : WeakMap<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 return ObjectUtils.map(schema, ({ kind, size }, key) => {\n const name = toID(key)\n\n const location = gl.getUniformLocation(program, name)\n\n if (isSamplerKind(kind)) {\n return {\n set(arg: number) {\n gl.uniform1i(location, arg)\n },\n }\n }\n\n const fnName = `uniform${kindToUniformFnName(kind)}${size ? 'v' : ''}`\n\n // @ts-ignore FIX WEBGL/WEBGL2 TYPES\n const fn = gl[fnName].bind(gl)\n\n if (isMatKind(kind)) {\n return {\n set(...args: any[]) {\n fn(location, false, args[0])\n },\n }\n }\n\n return {\n set(...args: any[]) {\n fn(location, ...args)\n },\n }\n })\n}\n\n/**********************************************************************************/\n/* */\n/* Attribute View */\n/* */\n/**********************************************************************************/\n\n// Shared attribute helper functions\n// between attributeView and interleavedAttributeView\nfunction handleAttribute(\n gl: GL,\n location: number,\n size: number,\n stride: number,\n offset: number,\n type: 'FLOAT' | 'INT',\n instanced?: boolean,\n) {\n gl.enableVertexAttribArray(location)\n gl.vertexAttribPointer(location, size, gl[type], false, stride, offset)\n\n if (instanced) {\n // Get instanced-arrays-feature: extension if webgl, gl if webgl2\n assertedNotNullish(getInstancedArrays(gl)).vertexAttribDivisor(location, 1)\n }\n}\n\nexport function attributeView<T extends AttributeSchema>(\n gl: GL,\n program: WebGLProgram,\n schema: T,\n { signal }: ViewOptions = {},\n): AttributeView<T> {\n const attributes = ObjectUtils.map(\n schema,\n (\n { kind, instanced, buffer = assertedNotNullish(gl.createBuffer()) },\n key,\n ): AttributeMethods => {\n const name = toID(key)\n\n const location = gl.getAttribLocation(program, name)\n if (location < 0) {\n throw new Error(`Attribute '${name}' not found`)\n }\n\n const size = kindToSize(kind)\n const type = kind.startsWith('i') ? 'INT' : 'FLOAT'\n\n return {\n buffer,\n bind() {\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n handleAttribute(gl, location, size, 0, 0, type, instanced)\n },\n dispose() {\n gl.deleteBuffer(buffer)\n },\n set(data, usage = 'STATIC_DRAW') {\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n gl.bufferData(gl.ARRAY_BUFFER, data, gl[usage])\n return this\n },\n }\n },\n )\n\n signal?.addEventListener('abort', function dispose() {\n ObjectUtils.forEach(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 = ObjectUtils.map(schema, ({ layout, instanced }) => {\n // Increment number to keep track of offset\n let index = 0\n\n // Calculate layout information\n const handles = layout.map(layout => {\n const name = toID(layout.key)\n\n const location = gl.getAttribLocation(program, name)\n\n if (location < 0) {\n throw new Error(`Attribute '${name}' not found`)\n }\n\n const size = kindToSize(layout.kind)\n const offset = index\n const type = layout.kind.startsWith('i') ? 'INT' : 'FLOAT'\n index += size * 4\n\n return () => handleAttribute(gl, location, size, stride, offset, type, instanced)\n })\n\n // Set stride to final index\n const stride = index\n\n // Create a buffer\n const buffer = assertedNotNullish(gl.createBuffer())\n\n // Create VAO to cache attribute state\n let vao: { unbind(): void; bind(): void; dispose(): void } | undefined = undefined\n\n // Get VAO-feature: extension if webgl1, gl if webgl2\n const feature = getVertexArrayObject(gl)\n if (feature) {\n const vertexArray = feature.createVertexArray()\n feature.bindVertexArray(vertexArray)\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n for (const handle of handles) {\n handle()\n }\n feature.bindVertexArray(null)\n vao = {\n unbind() {\n feature.bindVertexArray(null)\n },\n bind() {\n feature.bindVertexArray(vertexArray)\n },\n dispose() {\n feature.deleteVertexArray(vertexArray)\n },\n }\n }\n\n return {\n bind() {\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n if (vao) {\n vao.bind()\n } else {\n // Fallback: manual attribute setup\n for (const handle of handles) {\n handle()\n }\n }\n },\n unbind() {\n if (vao) {\n vao.unbind()\n }\n },\n dispose() {\n gl.deleteBuffer(buffer)\n if (vao) {\n vao.dispose()\n }\n },\n set(value, usage = 'STATIC_DRAW') {\n if (vao) {\n vao.bind()\n } else {\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n }\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 ObjectUtils.forEach(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 = ObjectUtils.map(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 ObjectUtils.forEach(buffers, value => value.dispose())\n })\n\n return buffers\n}\n","import { toID, view } from '.'\nimport type { Prettify } from './type-utils'\nimport type {\n AttributeDefinition,\n AttributeKind,\n AttributeTokenFn as AttributeTagMethod,\n AttributeToken,\n CompileResult,\n GLSL,\n GLSLSlot,\n GLSLToSchema,\n InterleaveToken,\n UniformDefinition,\n UniformKind,\n UniformTokenFn as UniformTagMethod,\n ViewSchema,\n ViewSchemaPartial,\n} from './types'\nimport { createProgram } from './utils'\n\nexport function glsl<TSlot extends GLSLSlot, 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 function compile<\n TVertex extends GLSL,\n TFragment extends GLSL,\n TOverride extends ViewSchemaPartial,\n>(gl: WebGLRenderingContext, vertex: TVertex, fragment: TFragment, overrideSchema?: TOverride) {\n const _vertex = resolveGLSLTag(vertex) as { template: string; schema: ViewSchema }\n const _fragment = resolveGLSLTag(fragment) 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 }\n\n for (const kind in overrideSchema) {\n const schemaKind = schema[kind as keyof typeof schema]\n const overrideSchemaKind = overrideSchema[kind]\n\n for (const key in overrideSchemaKind) {\n schemaKind[key] = {\n ...schemaKind[key],\n ...overrideSchemaKind[key],\n }\n }\n }\n\n const program = createProgram(gl, _vertex.template, _fragment.template)\n\n return {\n program,\n schema,\n view: view(gl, program, schema),\n vertex: _vertex.template,\n fragment: _fragment.template,\n } as unknown as Prettify<CompileResult<TVertex, TFragment, TOverride>>\n}\n\nfunction resolveGLSLTag<TTag extends GLSL>(tag: TTag) {\n return {\n template: compile.toString(tag),\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 function handleSlot(slot: GLSLSlot) {\n if (Array.isArray(slot)) {\n slot.forEach(handleSlot)\n return\n }\n\n if (typeof slot !== 'object') {\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 tag.slots.forEach(handleSlot)\n\n return result as unknown as Prettify<GLSLToSchema<TTag>>\n}\n\ncompile.toString = function <TTag extends GLSL>({ template: [initial, ...rest], slots }: TTag) {\n const v300 = !!initial?.startsWith('#version 300 es')\n\n let template = initial ?? ''\n\n for (let i = 0; i < rest.length; i++) {\n template += `${glslSlotToString(slots[i]!, v300)}${rest[i]}`\n }\n\n return template\n}\n\nfunction glslSlotToString(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 => glslSlotToString(slot, v300)).join('')\n }\n\n if (slot.type === 'glsl') {\n return compile.toString(slot)\n }\n\n if (slot.type === '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 }\n\n if (slot.type === 'uniform' && 'size' in slot) {\n return `${slot.type} ${slot.kind} ${toID(slot.key)}[${slot.size}];`\n }\n\n return `${slot.type === 'attribute' && v300 ? 'in' : slot.type} ${slot.kind} ${toID(slot.key)};`\n}\n"],"mappings":";;;;;;;AAGA,IAAM,+BAA+B,oBAAI,QASvC;AACK,SAAS,mBAAmB,IAAQ;AACzC,MAAI,cAAc,uBAAwB,QAAO;AAEjD,QAAM,SAAS,6BAA6B,IAAI,EAAE;AAClD,MAAI,OAAQ,QAAO;AAEnB,QAAM,MAAM,GAAG,aAAa,wBAAwB;AACpD,MAAI,CAAC,IAAK,QAAO;AAEjB,QAAM,UAAU;AAAA,IACd,qBAAqB,IAAI,yBAAyB,KAAK,GAAG;AAAA,IAC1D,uBAAuB,IAAI,2BAA2B,KAAK,GAAG;AAAA,IAC9D,qBAAqB,IAAI,yBAAyB,KAAK,GAAG;AAAA,EAC5D;AACA,+BAA6B,IAAI,IAAI,OAAO;AAE5C,SAAO;AACT;AAEA,IAAM,kCAAkC,oBAAI,QAS1C;AACK,SAAS,qBAAqB,IAAQ;AAC3C,MAAI,cAAc,uBAAwB,QAAO;AAEjD,QAAM,SAAS,gCAAgC,IAAI,EAAE;AACrD,MAAI,OAAQ,QAAO;AAEnB,QAAM,MAAM,GAAG,aAAa,yBAAyB;AACrD,MAAI,CAAC,IAAK,QAAO;AAEjB,QAAM,UAAU;AAAA,IACd,iBAAiB,IAAI,mBAAmB,KAAK,GAAG;AAAA,IAChD,mBAAmB,IAAI,qBAAqB,KAAK,GAAG;AAAA,IACpD,mBAAmB,IAAI,qBAAqB,KAAK,GAAG;AAAA,EACtD;AACA,kCAAgC,IAAI,IAAI,OAAO;AAE/C,SAAO;AACT;;;AC3DA;AAAA;AAAA;AAAA;AAAA;AAAO,SAAS,QACd,OACA,UACA;AACA,MAAIA,SAAQ;AACZ,aAAW,OAAO,OAAO;AACvB,aAAS,MAAM,GAAG,GAAG,KAAKA,MAAK;AAC/B,IAAAA;AAAA,EACF;AACA,aAAW,OAAO,OAAO,sBAAsB,KAAK,GAAG;AACrD,aAAS,MAAM,GAAc,GAAG,KAAgBA,MAAK;AACrD,IAAAA;AAAA,EACF;AACF;AAEO,SAAS,IACd,OACA,UACgC;AAChC,QAAM,SAAS,CAAC;AAEhB,UAAQ,OAAO,CAACC,QAAO,KAAKD,WAAU;AACpC,WAAO,GAAG,IAAI,SAASC,QAAO,KAAKD,MAAK;AAAA,EAC1C,CAAC;AAED,SAAO;AACT;;;ACdO,SAAS,mBAAsB,OAAU,SAAkC;AAChF,MAAI,UAAU,UAAa,UAAU,KAAM,OAAM,IAAI,MAAM,OAAO;AAClE,SAAO;AACT;AAEA,SAAS,eAAe,IAAQ,MAAc,QAA6B;AACzE,QAAM,SAAS,GAAG,aAAa,IAAI;AACnC,MAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,yBAAyB;AAEtD,KAAG,aAAa,QAAQ,MAAM;AAC9B,KAAG,cAAc,MAAM;AAEvB,MAAI,CAAC,GAAG,mBAAmB,QAAQ,GAAG,cAAc,GAAG;AACrD,UAAM,OAAO,GAAG,iBAAiB,MAAM;AACvC,OAAG,aAAa,MAAM;AACtB,UAAM,IAAI;AAAA,MACR,qBAAqB,SAAS,GAAG,gBAAgB,WAAW,UAAU,YAAY,IAAI;AAAA,IACxF;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,cAAc,IAAQ,cAAsB,gBAAsC;AAChG,QAAM,UAAU,GAAG,cAAc;AACjC,MAAI,CAAC,QAAS,OAAM,IAAI,MAAM,gCAAgC;AAE9D,QAAM,eAAe,eAAe,IAAI,GAAG,eAAe,YAAY;AACtE,QAAM,iBAAiB,eAAe,IAAI,GAAG,iBAAiB,cAAc;AAE5E,KAAG,aAAa,SAAS,YAAY;AACrC,KAAG,aAAa,SAAS,cAAc;AACvC,KAAG,YAAY,OAAO;AAEtB,MAAI,CAAC,GAAG,oBAAoB,SAAS,GAAG,WAAW,GAAG;AACpD,UAAM,OAAO,GAAG,kBAAkB,OAAO;AACzC,OAAG,cAAc,OAAO;AACxB,OAAG,aAAa,YAAY;AAC5B,OAAG,aAAa,cAAc;AAC9B,UAAM,IAAI,MAAM,2BAA2B,IAAI,EAAE;AAAA,EACnD;AAGA,KAAG,aAAa,YAAY;AAC5B,KAAG,aAAa,cAAc;AAE9B,SAAO;AACT;AAQO,IAAM,sBAAsB,CACjC,SACmC;AACnC,UAAQ,KAAK,CAAC,GAAG;AAAA;AAAA,IAEf,KAAK;AACH,aAAQ,WAAW,KAAK,MAAM,CAAC,IAAI;AAAA;AAAA,IAErC,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,cAAS,KAAK,MAAM,IAAI,IAAI,CAAC,KAAK,OAAO;AAAA;AAAA,IAE3C,KAAK;AACH,cAAS,KAAK,CAAC,KAAK,OAAO;AAAA;AAAA,IAE7B,KAAK;AACH,aAAQ,KAAK,CAAC,IAAI;AAAA,IACpB;AACE,cAAQ,MAAM;AAAA,QACZ,KAAK;AACH,iBAAO;AAAA,QACT,KAAK;AACH,iBAAO;AAAA,QACT;AACE,iBAAO;AAAA,MACX;AAAA,EACJ;AACF;AAQO,IAAM,aAAa,CAAwB,SAAiC;AACjF,UAAQ,KAAK,CAAC,GAAG;AAAA,IACf,KAAK;AACH,YAAM,CAAC,GAAG,CAAC,IAAI,KAAK,MAAM,MAAM,EAAG,IAAI,MAAM;AAC7C,aAAQ,KAAK,KAAK;AAAA,IACpB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,YAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,aAAQ,QAAQ,CAAC,MAAM,CAAC,IAAI;AAAA,IAC9B;AACE,aAAO;AAAA,EACX;AACF;AAQO,IAAM,YAAY,CAKvB,SAC2C,KAAK,SAAS,KAAK;AAEzD,IAAM,gBAAgB,CAC3B,SACyD,KAAK,SAAS,SAAS;AA4I3E,SAAS,gBACd,aACA;AACA,QAAME,OAAM,KAAK,eAAe,KAAK;AACrC,SAAO,OAAO,OAAOA,MAAK;AAAA,IACxB,YACE,KACA,OACA;AACA,UAAI,SAASA,KAAI,IAAI,GAAG;AACxB,UAAI,QAAQ;AACV,eAAO;AAAA,MACT;AACA,eAAS,MAAM;AACf,MAAAA,KAAI,IAAI,KAAK,MAAM;AACnB,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACH;;;ACnQA,IAAI,QAAQ;AACZ,IAAM,SAAS;AACf,IAAM,aAAa,UAAU,UAAU,YAAY,EAAE,QAAQ,SAAS,KAAK;AAK3E,IAAM,aAAa,gBAAgB,aAAa,MAAsB,OAAuB;AAEtF,SAAS,KAAK,KAA+B;AAClD,MAAI,OAAO,QAAQ,UAAU;AAC3B,WAAO;AAAA,EACT;AACA,MAAI,OAAO,QAAQ,UAAU;AAC3B,WAAO,WAAW,YAAY,KAAK,MAAM,GAAG,MAAM,IAAI,OAAO,EAAE;AAAA,EACjE;AACA,SAAO,IAAI,SAAS;AACtB;AAQO,SAAS,KACd,IACA,SACA,QACA,SACe;AACf,SAAO;AAAA,IACL,UAAU,CAAC,OAAO,WAAW,SAAY,YAAY,IAAI,SAAS,OAAO,QAAQ;AAAA,IACjF,YAAY,CAAC,OAAO,aAChB,SACA,cAAc,IAAI,SAAS,OAAO,YAAY,OAAO;AAAA,IACzD,uBAAuB,CAAC,OAAO,wBAC3B,SACA,yBAAyB,IAAI,SAAS,OAAO,uBAAuB,OAAO;AAAA,IAC/E,SAAS,CAAC,OAAO,UAAU,SAAY,WAAW,IAAI,OAAO,OAAO;AAAA,EACtE;AACF;AAQO,SAAS,YACd,IACA,SACA,QACqB;AACrB,SAAO,eAAY,IAAI,QAAQ,CAAC,EAAE,MAAM,KAAK,GAAG,QAAQ;AACtD,UAAMC,QAAO,KAAK,GAAG;AAErB,UAAM,WAAW,GAAG,mBAAmB,SAASA,KAAI;AAEpD,QAAI,cAAc,IAAI,GAAG;AACvB,aAAO;AAAA,QACL,IAAI,KAAa;AACf,aAAG,UAAU,UAAU,GAAG;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AAEA,UAAM,SAAS,UAAU,oBAAoB,IAAI,CAAC,GAAG,OAAO,MAAM,EAAE;AAGpE,UAAM,KAAK,GAAG,MAAM,EAAE,KAAK,EAAE;AAE7B,QAAI,UAAU,IAAI,GAAG;AACnB,aAAO;AAAA,QACL,OAAO,MAAa;AAClB,aAAG,UAAU,OAAO,KAAK,CAAC,CAAC;AAAA,QAC7B;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,OAAO,MAAa;AAClB,WAAG,UAAU,GAAG,IAAI;AAAA,MACtB;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAUA,SAAS,gBACP,IACA,UACA,MACA,QACA,QACA,MACA,WACA;AACA,KAAG,wBAAwB,QAAQ;AACnC,KAAG,oBAAoB,UAAU,MAAM,GAAG,IAAI,GAAG,OAAO,QAAQ,MAAM;AAEtE,MAAI,WAAW;AAEb,uBAAmB,mBAAmB,EAAE,CAAC,EAAE,oBAAoB,UAAU,CAAC;AAAA,EAC5E;AACF;AAEO,SAAS,cACd,IACA,SACA,QACA,EAAE,OAAO,IAAiB,CAAC,GACT;AAClB,QAAM,aAAa,eAAY;AAAA,IAC7B;AAAA,IACA,CACE,EAAE,MAAM,WAAW,SAAS,mBAAmB,GAAG,aAAa,CAAC,EAAE,GAClE,QACqB;AACrB,YAAMA,QAAO,KAAK,GAAG;AAErB,YAAM,WAAW,GAAG,kBAAkB,SAASA,KAAI;AACnD,UAAI,WAAW,GAAG;AAChB,cAAM,IAAI,MAAM,cAAcA,KAAI,aAAa;AAAA,MACjD;AAEA,YAAM,OAAO,WAAW,IAAI;AAC5B,YAAM,OAAO,KAAK,WAAW,GAAG,IAAI,QAAQ;AAE5C,aAAO;AAAA,QACL;AAAA,QACA,OAAO;AACL,aAAG,WAAW,GAAG,cAAc,MAAM;AACrC,0BAAgB,IAAI,UAAU,MAAM,GAAG,GAAG,MAAM,SAAS;AAAA,QAC3D;AAAA,QACA,UAAU;AACR,aAAG,aAAa,MAAM;AAAA,QACxB;AAAA,QACA,IAAI,MAAM,QAAQ,eAAe;AAC/B,aAAG,WAAW,GAAG,cAAc,MAAM;AACrC,aAAG,WAAW,GAAG,cAAc,MAAM,GAAG,KAAK,CAAC;AAC9C,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,UAAQ,iBAAiB,SAAS,SAAS,UAAU;AACnD,mBAAY,QAAQ,YAAY,WAAS,MAAM,QAAQ,CAAC;AAAA,EAC1D,CAAC;AAED,SAAO;AACT;AAQO,SAAS,yBACd,IACA,SACA,QACA,EAAE,OAAO,IAAiB,CAAC,GACE;AAE7B,QAAM,wBAAwB,eAAY,IAAI,QAAQ,CAAC,EAAE,QAAQ,UAAU,MAAM;AAE/E,QAAIC,SAAQ;AAGZ,UAAM,UAAU,OAAO,IAAI,CAAAC,YAAU;AACnC,YAAMF,QAAO,KAAKE,QAAO,GAAG;AAE5B,YAAM,WAAW,GAAG,kBAAkB,SAASF,KAAI;AAEnD,UAAI,WAAW,GAAG;AAChB,cAAM,IAAI,MAAM,cAAcA,KAAI,aAAa;AAAA,MACjD;AAEA,YAAM,OAAO,WAAWE,QAAO,IAAI;AACnC,YAAM,SAASD;AACf,YAAM,OAAOC,QAAO,KAAK,WAAW,GAAG,IAAI,QAAQ;AACnD,MAAAD,UAAS,OAAO;AAEhB,aAAO,MAAM,gBAAgB,IAAI,UAAU,MAAM,QAAQ,QAAQ,MAAM,SAAS;AAAA,IAClF,CAAC;AAGD,UAAM,SAASA;AAGf,UAAM,SAAS,mBAAmB,GAAG,aAAa,CAAC;AAGnD,QAAI,MAAqE;AAGzE,UAAM,UAAU,qBAAqB,EAAE;AACvC,QAAI,SAAS;AACX,YAAM,cAAc,QAAQ,kBAAkB;AAC9C,cAAQ,gBAAgB,WAAW;AACnC,SAAG,WAAW,GAAG,cAAc,MAAM;AACrC,iBAAW,UAAU,SAAS;AAC5B,eAAO;AAAA,MACT;AACA,cAAQ,gBAAgB,IAAI;AAC5B,YAAM;AAAA,QACJ,SAAS;AACP,kBAAQ,gBAAgB,IAAI;AAAA,QAC9B;AAAA,QACA,OAAO;AACL,kBAAQ,gBAAgB,WAAW;AAAA,QACrC;AAAA,QACA,UAAU;AACR,kBAAQ,kBAAkB,WAAW;AAAA,QACvC;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,OAAO;AACL,WAAG,WAAW,GAAG,cAAc,MAAM;AACrC,YAAI,KAAK;AACP,cAAI,KAAK;AAAA,QACX,OAAO;AAEL,qBAAW,UAAU,SAAS;AAC5B,mBAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAAA,MACA,SAAS;AACP,YAAI,KAAK;AACP,cAAI,OAAO;AAAA,QACb;AAAA,MACF;AAAA,MACA,UAAU;AACR,WAAG,aAAa,MAAM;AACtB,YAAI,KAAK;AACP,cAAI,QAAQ;AAAA,QACd;AAAA,MACF;AAAA,MACA,IAAI,OAAO,QAAQ,eAAe;AAChC,YAAI,KAAK;AACP,cAAI,KAAK;AAAA,QACX,OAAO;AACL,aAAG,WAAW,GAAG,cAAc,MAAM;AAAA,QACvC;AACA,WAAG,WAAW,GAAG,cAAc,OAAO,GAAG,KAAK,CAAC;AAC/C,YAAI,KAAK;AACP,cAAI,OAAO;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAED,UAAQ,iBAAiB,SAAS,SAAS,UAAU;AACnD,mBAAY,QAAQ,uBAAuB,WAAS,MAAM,QAAQ,CAAC;AAAA,EACrE,CAAC;AAED,SAAO;AACT;AAQO,SAAS,WACd,IACA,QACA,EAAE,OAAO,IAAiB,CAAC,GACZ;AAEf,QAAM,UAAU,eAAY,IAAI,QAAQ,CAAC,EAAE,SAAS,gBAAgB,QAAQ,cAAc,MAAM;AAC9F,UAAM,SAAS,mBAAmB,GAAG,aAAa,CAAC;AACnD,WAAO;AAAA,MACL,OAAO;AACL,WAAG,WAAW,GAAG,MAAM,GAAG,MAAM;AAAA,MAClC;AAAA,MACA,UAAU;AACR,WAAG,aAAa,MAAM;AAAA,MACxB;AAAA,MACA,IAAI,MAAoB;AACtB,WAAG,WAAW,GAAG,MAAM,GAAG,MAAM;AAChC,WAAG,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAAA,MAC3C;AAAA,IACF;AAAA,EACF,CAAC;AAED,UAAQ,iBAAiB,SAAS,SAAS,UAAU;AACnD,mBAAY,QAAQ,SAAS,WAAS,MAAM,QAAQ,CAAC;AAAA,EACvD,CAAC;AAED,SAAO;AACT;;;AC/TO,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,KAAAE,MAAK,KAAK,OAAO;AAAA,MACrC,KAAAA;AAAA,MACA;AAAA,IACF,EAAE;AAAA,IACF,WAAW,CAAC,CAAC;AAAA,IACb;AAAA,EACF;AACF;AAQO,SAAS,QAId,IAA2B,QAAiB,UAAqB,gBAA4B;AAC7F,QAAM,UAAU,eAAe,MAAM;AACrC,QAAM,YAAY,eAAe,QAAQ;AAEzC,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,EACF;AAEA,aAAW,QAAQ,gBAAgB;AACjC,UAAM,aAAa,OAAO,IAA2B;AACrD,UAAM,qBAAqB,eAAe,IAAI;AAE9C,eAAW,OAAO,oBAAoB;AACpC,iBAAW,GAAG,IAAI;AAAA,QAChB,GAAG,WAAW,GAAG;AAAA,QACjB,GAAG,mBAAmB,GAAG;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU,cAAc,IAAI,QAAQ,UAAU,UAAU,QAAQ;AAEtE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,MAAM,KAAK,IAAI,SAAS,MAAM;AAAA,IAC9B,QAAQ,QAAQ;AAAA,IAChB,UAAU,UAAU;AAAA,EACtB;AACF;AAEA,SAAS,eAAkC,KAAW;AACpD,SAAO;AAAA,IACL,UAAU,QAAQ,SAAS,GAAG;AAAA,IAC9B,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,WAAS,WAAW,MAAgB;AAClC,QAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,WAAK,QAAQ,UAAU;AACvB;AAAA,IACF;AAEA,QAAI,OAAO,SAAS,UAAU;AAC5B;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,KAAKC,OAAM,MAAM,GAAG,KAAK,IAAI;AAGrC,WAAO,GAAG,IAAI,GAAG,EAAEA,KAAI,IAAI;AAAA,EAC7B;AAEA,MAAI,MAAM,QAAQ,UAAU;AAE5B,SAAO;AACT;AAEA,QAAQ,WAAW,SAA6B,EAAE,UAAU,CAAC,SAAS,GAAG,IAAI,GAAG,MAAM,GAAS;AAC7F,QAAM,OAAO,CAAC,CAAC,SAAS,WAAW,iBAAiB;AAEpD,MAAI,WAAW,WAAW;AAE1B,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,gBAAY,GAAG,iBAAiB,MAAM,CAAC,GAAI,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;AAAA,EAC5D;AAEA,SAAO;AACT;AAEA,SAAS,iBAAiB,MAAgB,MAAuB;AAC/D,MAAI,OAAO,SAAS,UAAU;AAC5B,WAAO,KAAK,IAAI;AAAA,EAClB;AAEA,MAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,WAAO,KAAK,IAAI,CAAAC,UAAQ,iBAAiBA,OAAM,IAAI,CAAC,EAAE,KAAK,EAAE;AAAA,EAC/D;AAEA,MAAI,KAAK,SAAS,QAAQ;AACxB,WAAO,QAAQ,SAAS,IAAI;AAAA,EAC9B;AAEA,MAAI,KAAK,SAAS,wBAAwB;AACxC,WAAO,KAAK,OAAO;AAAA,MACjB,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,MACtF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,KAAK,SAAS,aAAa,UAAU,MAAM;AAC7C,WAAO,GAAG,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI;AAAA,EACjE;AAEA,SAAO,GAAG,KAAK,SAAS,eAAe,OAAO,OAAO,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,KAAK,GAAG,CAAC;AAC/F;","names":["index","value","map","name","index","layout","key","name","slot"]}
@@ -389,10 +389,10 @@ interface ViewSchemaPartial {
389
389
  buffers?: Record<string | symbol, Partial<BufferDefinition>>;
390
390
  }
391
391
  type View<T extends ViewSchema = ViewSchema> = {
392
- attributes: T['attributes'] extends AttributeSchema ? AttributeView<T['attributes']> : undefined;
393
- interleavedAttributes: T['interleavedAttributes'] extends InterleavedAttributeSchema ? InterleavedAttributeView<T['interleavedAttributes']> : undefined;
394
- buffers: T['buffers'] extends BufferSchema ? BufferView<T['buffers']> : undefined;
395
- uniforms: T['uniforms'] extends UniformSchema ? UniformView<T['uniforms']> : never;
392
+ attributes: T['attributes'] extends AttributeSchema ? Prettify<AttributeView<T['attributes']>> : never;
393
+ interleavedAttributes: T['interleavedAttributes'] extends InterleavedAttributeSchema ? Prettify<InterleavedAttributeView<T['interleavedAttributes']>> : never;
394
+ buffers: T['buffers'] extends BufferSchema ? Prettify<BufferView<T['buffers']>> : never;
395
+ uniforms: T['uniforms'] extends UniformSchema ? Prettify<UniformView<T['uniforms']>> : never;
396
396
  };
397
397
  /**********************************************************************************/
398
398
  /**********************************************************************************/
@@ -400,14 +400,14 @@ interface GLSLResult {
400
400
  program: WebGLProgram;
401
401
  schema: ViewSchema;
402
402
  }
403
- type GLSLSlotItem = GLSLTag | UniformTag | AttributeTag | InterleaveTag | string | number | symbol;
403
+ type GLSLSlotItem = GLSL | UniformToken | AttributeToken | InterleaveToken | string | number | symbol;
404
404
  type GLSLSlot = GLSLSlotItem | Array<GLSLSlotItem>;
405
- interface GLSLTag<TSlots extends GLSLSlot[] = GLSLSlot[]> {
405
+ interface GLSL<TSlots extends GLSLSlot[] = GLSLSlot[]> {
406
406
  type: 'glsl';
407
407
  template: TemplateStringsArray;
408
408
  slots: TSlots;
409
409
  }
410
- type UniformTag<TKey extends string | symbol = string | symbol, TKind extends UniformKind = UniformKind, TDefinition extends Partial<UniformDefinition> = UniformDefinition> = TDefinition extends {
410
+ type UniformToken<TKey extends string | symbol = string | symbol, TKind extends UniformKind = UniformKind, TDefinition extends Partial<UniformDefinition> = UniformDefinition> = TDefinition extends {
411
411
  size: infer TSize;
412
412
  } ? {
413
413
  type: 'uniform';
@@ -419,41 +419,42 @@ type UniformTag<TKey extends string | symbol = string | symbol, TKind extends Un
419
419
  kind: TKind;
420
420
  key: TKey;
421
421
  };
422
- interface UniformTagFn<TKind extends UniformKind> {
423
- <const TKey extends string | symbol, const TDefinition extends Omit<UniformDefinition, 'kind'>>(key: TKey, TDefinition: TDefinition): Prettify<UniformTag<TKey, TKind, TDefinition>>;
424
- <const TName extends string | symbol>(key: TName): Prettify<UniformTag<TName, TKind>>;
422
+ interface UniformTokenFn<TKind extends UniformKind> {
423
+ <const TKey extends string | symbol, const TDefinition extends Omit<UniformDefinition, 'kind'>>(key: TKey, TDefinition: TDefinition): Prettify<UniformToken<TKey, TKind, TDefinition>>;
424
+ <const TName extends string | symbol>(key: TName): Prettify<UniformToken<TName, TKind>>;
425
425
  }
426
- interface AttributeTag<TKey extends string | symbol = string | symbol, TKind extends AttributeKind = AttributeKind, TInstanced extends boolean | undefined = boolean | undefined> {
426
+ interface AttributeToken<TKey extends string | symbol = string | symbol, TKind extends AttributeKind = AttributeKind, TInstanced extends boolean | undefined = boolean | undefined> {
427
427
  type: 'attribute';
428
428
  kind: TKind;
429
429
  instanced: TInstanced;
430
430
  key: TKey;
431
431
  }
432
- interface AttributeTagFn<TKey extends AttributeKind> {
433
- <TName extends string | symbol, TDefinition extends Omit<AttributeDefinition, 'kind'>>(key: TName, options: TDefinition): Prettify<AttributeTag<TName, TKey, TDefinition['instanced']>>;
434
- <TName extends string | symbol>(key: TName): Prettify<AttributeTag<TName, TKey, undefined>>;
432
+ interface AttributeTokenFn<TKey extends AttributeKind> {
433
+ <TName extends string | symbol, TDefinition extends Omit<AttributeDefinition, 'kind'>>(key: TName, options: TDefinition): Prettify<AttributeToken<TName, TKey, TDefinition['instanced']>>;
434
+ <TName extends string | symbol>(key: TName): Prettify<AttributeToken<TName, TKey, undefined>>;
435
435
  }
436
- type InterleaveTag<TKey extends string | symbol = string | symbol, TLayout extends Array<AttributeTag<string | symbol, AttributeKind, undefined>> = Array<AttributeTag<string | symbol, AttributeKind, undefined>>, TDefinition extends Omit<AttributeDefinition, 'kind'> = Omit<AttributeDefinition, 'kind'>> = TDefinition & {
436
+ type InterleaveToken<TKey extends string | symbol = string | symbol, TLayout extends Array<AttributeToken<string | symbol, AttributeKind, undefined>> = Array<AttributeToken<string | symbol, AttributeKind, undefined>>, TDefinition extends Omit<AttributeDefinition, 'kind'> = Omit<AttributeDefinition, 'kind'>> = TDefinition & {
437
437
  key: TKey;
438
438
  type: 'interleavedAttribute';
439
439
  layout: {
440
440
  [TKey in keyof TLayout]: Prettify<Pick<TLayout[TKey], 'kind' | 'key'>>;
441
441
  };
442
442
  };
443
- type GLSLTagToSchema<TTag extends GLSLTag> = FlattenSlots<TTag> extends infer TSlots ? TSlots extends Array<any> ? GLSLSlotsToSchema<TSlots> : never : never;
443
+ type GLSLToSchema<T extends GLSL> = FlattenSlots<T> extends infer TSlots ? TSlots extends Array<any> ? GLSLSlotsToSchema<TSlots> : never : never;
444
+ type GLSLToView<T extends GLSL> = View<GLSLToSchema<T>>;
444
445
  type GLSLSlotsToSchema<TSlots extends Array<GLSLSlot>> = {
445
446
  uniforms: {
446
- [K in Extract<TSlots[number], UniformTag> as K['key']]: Prettify<Omit<K, 'name' | 'type'>>;
447
+ [K in Extract<TSlots[number], UniformToken> as K['key']]: Prettify<Omit<K, 'name' | 'type'>>;
447
448
  };
448
449
  attributes: {
449
- [K in Extract<TSlots[number], AttributeTag> as K['key']]: Prettify<Omit<K, 'name' | 'type'>>;
450
+ [K in Extract<TSlots[number], AttributeToken> as K['key']]: Prettify<Omit<K, 'name' | 'type'>>;
450
451
  };
451
452
  interleavedAttributes: {
452
- [K in Extract<TSlots[number], InterleaveTag> as K['key']]: Prettify<Omit<K, 'name' | 'type'>>;
453
+ [K in Extract<TSlots[number], InterleaveToken> as K['key']]: Prettify<Omit<K, 'name' | 'type'>>;
453
454
  };
454
455
  };
455
- type FlattenSlots<T> = T extends GLSLTag<infer TSlots> ? _FlattenSlots<TSlots> : T extends Array<GLSLSlot> ? _FlattenSlots<T> : never;
456
- type _FlattenSlots<T extends Array<GLSLSlot>> = T extends [infer First, ...infer Rest] ? First extends GLSLTag ? [...FlattenSlots<First>, ...FlattenSlots<Rest>] : First extends unknown[] ? [...FlattenSlots<First>, ...FlattenSlots<Rest>] : [First, ...FlattenSlots<Rest>] : [];
456
+ type FlattenSlots<T> = T extends GLSL<infer TSlots> ? _FlattenSlots<TSlots> : T extends Array<GLSLSlot> ? _FlattenSlots<T> : never;
457
+ type _FlattenSlots<T extends Array<GLSLSlot>> = T extends [infer First, ...infer Rest] ? First extends GLSL ? [...FlattenSlots<First>, ...FlattenSlots<Rest>] : First extends unknown[] ? [...FlattenSlots<First>, ...FlattenSlots<Rest>] : [First, ...FlattenSlots<Rest>] : [];
457
458
  type MergeGLSLSchema<TVertex extends ViewSchema, TFragment extends ViewSchema, TOverrides extends ViewSchemaPartial = {}> = {
458
459
  uniforms: DeepMerge<[
459
460
  ShallowMerge<[TVertex['uniforms'], TFragment['uniforms']]>,
@@ -468,10 +469,12 @@ type MergeGLSLSchema<TVertex extends ViewSchema, TFragment extends ViewSchema, T
468
469
  TOverrides['interleavedAttributes']
469
470
  ]>;
470
471
  };
471
- type CompileResult<TVertex extends GLSLTag, TFragment extends GLSLTag, TOverrides extends ViewSchemaPartial> = MergeGLSLSchema<GLSLTagToSchema<TVertex>, GLSLTagToSchema<TFragment>, TOverrides> extends infer TSchema extends ViewSchema ? {
472
+ type CompileResult<TVertex extends GLSL, TFragment extends GLSL, TOverrideSchema extends ViewSchemaPartial> = MergeGLSLSchema<GLSLToSchema<TVertex>, GLSLToSchema<TFragment>, TOverrideSchema> extends infer TSchema extends ViewSchema ? {
472
473
  program: WebGLProgram;
473
474
  schema: TSchema;
474
- view: View<TSchema>;
475
+ view: Prettify<View<TSchema>>;
476
+ vertex: string;
477
+ fragment: string;
475
478
  } : never;
476
479
 
477
- export type { UniformTag as $, AttributeSchema as A, BufferSchema as B, BufferDefinition as C, BufferMethods as D, Framebuffer as E, FramebufferDefinition as F, GL as G, TextureTarget as H, InterleavedAttributeSchema as I, TextureSchema as J, KIND_TO_UNIFORM_FN_NAME_MAP as K, TextureMethods as L, TextureView as M, TextureParameterName as N, TextureParameterValue as O, TextureParameters as P, InternalFormat as Q, Format as R, PixelType as S, TextureDefinition as T, UniformSchema as U, ViewSchema as V, TexImage2DOptions as W, ViewSchemaPartial as X, GLSLResult as Y, GLSLSlot as Z, GLSLTag as _, ViewOptions as a, UniformTagFn as a0, AttributeTag as a1, AttributeTagFn as a2, InterleaveTag as a3, GLSLTagToSchema as a4, GLSLSlotsToSchema as a5, MergeGLSLSchema as a6, CompileResult as a7, Prettify as a8, 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, UniformDefinition as q, UniformSchemaPartial as r, UniformMethods as s, AttributeShortHand as t, AttributeKind as u, AttributeDefinition as v, AttributeMethods as w, InterleavedAttributeLayout as x, InterleavedAttributeDefinition as y, InterleavedAttributeMethods as z };
480
+ export type { UniformToken as $, AttributeSchema as A, BufferSchema as B, BufferDefinition as C, BufferMethods as D, Framebuffer as E, FramebufferDefinition as F, GL as G, TextureTarget as H, InterleavedAttributeSchema as I, TextureSchema as J, KIND_TO_UNIFORM_FN_NAME_MAP as K, TextureMethods as L, TextureView as M, TextureParameterName as N, TextureParameterValue as O, TextureParameters as P, InternalFormat as Q, Format as R, PixelType as S, TextureDefinition as T, UniformSchema as U, ViewSchema as V, TexImage2DOptions as W, ViewSchemaPartial as X, GLSLResult as Y, GLSLSlot as Z, GLSL as _, ViewOptions as a, UniformTokenFn as a0, AttributeToken as a1, AttributeTokenFn as a2, InterleaveToken as a3, GLSLToSchema as a4, GLSLToView as a5, GLSLSlotsToSchema as a6, MergeGLSLSchema as a7, CompileResult as a8, Prettify as a9, 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, UniformDefinition as q, UniformSchemaPartial as r, UniformMethods as s, AttributeShortHand as t, AttributeKind as u, AttributeDefinition as v, AttributeMethods as w, InterleavedAttributeLayout as x, InterleavedAttributeDefinition as y, InterleavedAttributeMethods as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bigmistqke/view.gl",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "👀 Utilities for managing WebGL resources.",
5
5
  "exports": {
6
6
  ".": {
package/src/tag.ts CHANGED
@@ -3,16 +3,16 @@ import type { Prettify } from './type-utils'
3
3
  import type {
4
4
  AttributeDefinition,
5
5
  AttributeKind,
6
- AttributeTag,
7
- AttributeTagFn as AttributeTagMethod,
6
+ AttributeTokenFn as AttributeTagMethod,
7
+ AttributeToken,
8
8
  CompileResult,
9
+ GLSL,
9
10
  GLSLSlot,
10
- GLSLTag,
11
- GLSLTagToSchema,
12
- InterleaveTag,
11
+ GLSLToSchema,
12
+ InterleaveToken,
13
13
  UniformDefinition,
14
14
  UniformKind,
15
- UniformTagFn as UniformTagMethod,
15
+ UniformTokenFn as UniformTagMethod,
16
16
  ViewSchema,
17
17
  ViewSchemaPartial,
18
18
  } from './types'
@@ -21,7 +21,7 @@ import { createProgram } from './utils'
21
21
  export function glsl<TSlot extends GLSLSlot, TSlots extends TSlot[]>(
22
22
  template: TemplateStringsArray,
23
23
  ...slots: [...TSlots]
24
- ): GLSLTag<TSlots> {
24
+ ): GLSL<TSlots> {
25
25
  return { template, slots, type: 'glsl' }
26
26
  }
27
27
 
@@ -63,16 +63,16 @@ export const attribute = new Proxy(
63
63
 
64
64
  export function interleave<
65
65
  const TKey extends string | symbol,
66
- const TLayout extends Array<AttributeTag<string | symbol, AttributeKind, undefined>>,
66
+ const TLayout extends Array<AttributeToken<string | symbol, AttributeKind, undefined>>,
67
67
  const TOptions extends Omit<AttributeDefinition, 'kind'>,
68
- >(key: TKey, layout: TLayout, instanced: TOptions): InterleaveTag<TKey, TLayout, TOptions>
68
+ >(key: TKey, layout: TLayout, instanced: TOptions): InterleaveToken<TKey, TLayout, TOptions>
69
69
  export function interleave<
70
70
  const TKey extends string | symbol,
71
- const TLayout extends Array<AttributeTag<string | symbol, AttributeKind, undefined>>,
72
- >(key: TKey, layout: TLayout): InterleaveTag<TKey, TLayout, { instanced: false }>
71
+ const TLayout extends Array<AttributeToken<string | symbol, AttributeKind, undefined>>,
72
+ >(key: TKey, layout: TLayout): InterleaveToken<TKey, TLayout, { instanced: false }>
73
73
  export function interleave<
74
74
  const TKey extends string | symbol,
75
- const TLayout extends Array<AttributeTag<string | symbol, AttributeKind, undefined>>,
75
+ const TLayout extends Array<AttributeToken<string | symbol, AttributeKind, undefined>>,
76
76
  const TOptions extends Omit<AttributeDefinition, 'kind'>,
77
77
  >(key: TKey, layout: TLayout, { instanced, buffer }: Partial<TOptions> = {}) {
78
78
  return {
@@ -85,7 +85,7 @@ export function interleave<
85
85
  })),
86
86
  instanced: !!instanced,
87
87
  buffer,
88
- } as unknown as InterleaveTag<TKey, TLayout, TOptions>
88
+ } as unknown as InterleaveToken<TKey, TLayout, TOptions>
89
89
  }
90
90
 
91
91
  /**********************************************************************************/
@@ -95,8 +95,8 @@ export function interleave<
95
95
  /**********************************************************************************/
96
96
 
97
97
  export function compile<
98
- TVertex extends GLSLTag,
99
- TFragment extends GLSLTag,
98
+ TVertex extends GLSL,
99
+ TFragment extends GLSL,
100
100
  TOverride extends ViewSchemaPartial,
101
101
  >(gl: WebGLRenderingContext, vertex: TVertex, fragment: TFragment, overrideSchema?: TOverride) {
102
102
  const _vertex = resolveGLSLTag(vertex) as { template: string; schema: ViewSchema }
@@ -135,17 +135,19 @@ export function compile<
135
135
  program,
136
136
  schema,
137
137
  view: view(gl, program, schema),
138
- } as Prettify<CompileResult<TVertex, TFragment, TOverride>>
138
+ vertex: _vertex.template,
139
+ fragment: _fragment.template,
140
+ } as unknown as Prettify<CompileResult<TVertex, TFragment, TOverride>>
139
141
  }
140
142
 
141
- function resolveGLSLTag<TTag extends GLSLTag>(tag: TTag) {
143
+ function resolveGLSLTag<TTag extends GLSL>(tag: TTag) {
142
144
  return {
143
145
  template: compile.toString(tag),
144
146
  schema: compile.toSchema(tag),
145
147
  }
146
148
  }
147
149
 
148
- compile.toSchema = function <TTag extends GLSLTag>(tag: TTag) {
150
+ compile.toSchema = function <TTag extends GLSL>(tag: TTag) {
149
151
  const result = {
150
152
  uniforms: {},
151
153
  attributes: {},
@@ -189,10 +191,10 @@ compile.toSchema = function <TTag extends GLSLTag>(tag: TTag) {
189
191
 
190
192
  tag.slots.forEach(handleSlot)
191
193
 
192
- return result as unknown as Prettify<GLSLTagToSchema<TTag>>
194
+ return result as unknown as Prettify<GLSLToSchema<TTag>>
193
195
  }
194
196
 
195
- compile.toString = function <TTag extends GLSLTag>({ template: [initial, ...rest], slots }: TTag) {
197
+ compile.toString = function <TTag extends GLSL>({ template: [initial, ...rest], slots }: TTag) {
196
198
  const v300 = !!initial?.startsWith('#version 300 es')
197
199
 
198
200
  let template = initial ?? ''
package/src/types.ts CHANGED
@@ -633,12 +633,14 @@ export interface ViewSchemaPartial {
633
633
  }
634
634
 
635
635
  export type View<T extends ViewSchema = ViewSchema> = {
636
- attributes: T['attributes'] extends AttributeSchema ? AttributeView<T['attributes']> : undefined
636
+ attributes: T['attributes'] extends AttributeSchema
637
+ ? Prettify<AttributeView<T['attributes']>>
638
+ : never
637
639
  interleavedAttributes: T['interleavedAttributes'] extends InterleavedAttributeSchema
638
- ? InterleavedAttributeView<T['interleavedAttributes']>
639
- : undefined
640
- buffers: T['buffers'] extends BufferSchema ? BufferView<T['buffers']> : undefined
641
- uniforms: T['uniforms'] extends UniformSchema ? UniformView<T['uniforms']> : never
640
+ ? Prettify<InterleavedAttributeView<T['interleavedAttributes']>>
641
+ : never
642
+ buffers: T['buffers'] extends BufferSchema ? Prettify<BufferView<T['buffers']>> : never
643
+ uniforms: T['uniforms'] extends UniformSchema ? Prettify<UniformView<T['uniforms']>> : never
642
644
  }
643
645
 
644
646
  /**********************************************************************************/
@@ -652,17 +654,24 @@ export interface GLSLResult {
652
654
  schema: ViewSchema
653
655
  }
654
656
 
655
- type GLSLSlotItem = GLSLTag | UniformTag | AttributeTag | InterleaveTag | string | number | symbol
657
+ type GLSLSlotItem =
658
+ | GLSL
659
+ | UniformToken
660
+ | AttributeToken
661
+ | InterleaveToken
662
+ | string
663
+ | number
664
+ | symbol
656
665
 
657
666
  export type GLSLSlot = GLSLSlotItem | Array<GLSLSlotItem>
658
667
 
659
- export interface GLSLTag<TSlots extends GLSLSlot[] = GLSLSlot[]> {
668
+ export interface GLSL<TSlots extends GLSLSlot[] = GLSLSlot[]> {
660
669
  type: 'glsl'
661
670
  template: TemplateStringsArray
662
671
  slots: TSlots
663
672
  }
664
673
 
665
- export type UniformTag<
674
+ export type UniformToken<
666
675
  TKey extends string | symbol = string | symbol,
667
676
  TKind extends UniformKind = UniformKind,
668
677
  TDefinition extends Partial<UniformDefinition> = UniformDefinition,
@@ -679,15 +688,15 @@ export type UniformTag<
679
688
  key: TKey
680
689
  }
681
690
 
682
- export interface UniformTagFn<TKind extends UniformKind> {
691
+ export interface UniformTokenFn<TKind extends UniformKind> {
683
692
  <const TKey extends string | symbol, const TDefinition extends Omit<UniformDefinition, 'kind'>>(
684
693
  key: TKey,
685
694
  TDefinition: TDefinition,
686
- ): Prettify<UniformTag<TKey, TKind, TDefinition>>
687
- <const TName extends string | symbol>(key: TName): Prettify<UniformTag<TName, TKind>>
695
+ ): Prettify<UniformToken<TKey, TKind, TDefinition>>
696
+ <const TName extends string | symbol>(key: TName): Prettify<UniformToken<TName, TKind>>
688
697
  }
689
698
 
690
- export interface AttributeTag<
699
+ export interface AttributeToken<
691
700
  TKey extends string | symbol = string | symbol,
692
701
  TKind extends AttributeKind = AttributeKind,
693
702
  TInstanced extends boolean | undefined = boolean | undefined,
@@ -698,18 +707,18 @@ export interface AttributeTag<
698
707
  key: TKey
699
708
  }
700
709
 
701
- export interface AttributeTagFn<TKey extends AttributeKind> {
710
+ export interface AttributeTokenFn<TKey extends AttributeKind> {
702
711
  <TName extends string | symbol, TDefinition extends Omit<AttributeDefinition, 'kind'>>(
703
712
  key: TName,
704
713
  options: TDefinition,
705
- ): Prettify<AttributeTag<TName, TKey, TDefinition['instanced']>>
706
- <TName extends string | symbol>(key: TName): Prettify<AttributeTag<TName, TKey, undefined>>
714
+ ): Prettify<AttributeToken<TName, TKey, TDefinition['instanced']>>
715
+ <TName extends string | symbol>(key: TName): Prettify<AttributeToken<TName, TKey, undefined>>
707
716
  }
708
717
 
709
- export type InterleaveTag<
718
+ export type InterleaveToken<
710
719
  TKey extends string | symbol = string | symbol,
711
- TLayout extends Array<AttributeTag<string | symbol, AttributeKind, undefined>> = Array<
712
- AttributeTag<string | symbol, AttributeKind, undefined>
720
+ TLayout extends Array<AttributeToken<string | symbol, AttributeKind, undefined>> = Array<
721
+ AttributeToken<string | symbol, AttributeKind, undefined>
713
722
  >,
714
723
  TDefinition extends Omit<AttributeDefinition, 'kind'> = Omit<AttributeDefinition, 'kind'>,
715
724
  > = TDefinition & {
@@ -720,34 +729,36 @@ export type InterleaveTag<
720
729
  }
721
730
  }
722
731
 
723
- export type GLSLTagToSchema<TTag extends GLSLTag> =
724
- FlattenSlots<TTag> extends infer TSlots
732
+ export type GLSLToSchema<T extends GLSL> =
733
+ FlattenSlots<T> extends infer TSlots
725
734
  ? TSlots extends Array<any>
726
735
  ? GLSLSlotsToSchema<TSlots>
727
736
  : never
728
737
  : never
729
738
 
739
+ export type GLSLToView<T extends GLSL> = View<GLSLToSchema<T>>
740
+
730
741
  export type GLSLSlotsToSchema<TSlots extends Array<GLSLSlot>> = {
731
742
  uniforms: {
732
- [K in Extract<TSlots[number], UniformTag> as K['key']]: Prettify<Omit<K, 'name' | 'type'>>
743
+ [K in Extract<TSlots[number], UniformToken> as K['key']]: Prettify<Omit<K, 'name' | 'type'>>
733
744
  }
734
745
  attributes: {
735
- [K in Extract<TSlots[number], AttributeTag> as K['key']]: Prettify<Omit<K, 'name' | 'type'>>
746
+ [K in Extract<TSlots[number], AttributeToken> as K['key']]: Prettify<Omit<K, 'name' | 'type'>>
736
747
  }
737
748
  interleavedAttributes: {
738
- [K in Extract<TSlots[number], InterleaveTag> as K['key']]: Prettify<Omit<K, 'name' | 'type'>>
749
+ [K in Extract<TSlots[number], InterleaveToken> as K['key']]: Prettify<Omit<K, 'name' | 'type'>>
739
750
  }
740
751
  }
741
752
 
742
753
  type FlattenSlots<T> =
743
- T extends GLSLTag<infer TSlots>
754
+ T extends GLSL<infer TSlots>
744
755
  ? _FlattenSlots<TSlots>
745
756
  : T extends Array<GLSLSlot>
746
757
  ? _FlattenSlots<T>
747
758
  : never
748
759
 
749
760
  type _FlattenSlots<T extends Array<GLSLSlot>> = T extends [infer First, ...infer Rest]
750
- ? First extends GLSLTag
761
+ ? First extends GLSL
751
762
  ? [...FlattenSlots<First>, ...FlattenSlots<Rest>]
752
763
  : First extends unknown[]
753
764
  ? [...FlattenSlots<First>, ...FlattenSlots<Rest>]
@@ -774,18 +785,20 @@ export type MergeGLSLSchema<
774
785
  }
775
786
 
776
787
  export type CompileResult<
777
- TVertex extends GLSLTag,
778
- TFragment extends GLSLTag,
779
- TOverrides extends ViewSchemaPartial,
788
+ TVertex extends GLSL,
789
+ TFragment extends GLSL,
790
+ TOverrideSchema extends ViewSchemaPartial,
780
791
  > =
781
792
  MergeGLSLSchema<
782
- GLSLTagToSchema<TVertex>,
783
- GLSLTagToSchema<TFragment>,
784
- TOverrides
793
+ GLSLToSchema<TVertex>,
794
+ GLSLToSchema<TFragment>,
795
+ TOverrideSchema
785
796
  > extends infer TSchema extends ViewSchema
786
797
  ? {
787
798
  program: WebGLProgram
788
799
  schema: TSchema
789
- view: View<TSchema>
800
+ view: Prettify<View<TSchema>>
801
+ vertex: string
802
+ fragment: string
790
803
  }
791
804
  : never
package/test/tag.test.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { beforeEach, describe, expect, it, vi } from 'vitest'
2
+ import { toID } from '../src'
2
3
  import { attribute, compile, glsl, interleave, uniform } from '../src/tag'
3
4
  import type { GL } from '../src/types'
4
5
  import { createMockGL } from './mocks/webgl'
@@ -628,13 +629,15 @@ void main() { gl_FragColor = vec4(0.5); }`
628
629
 
629
630
  compile(gl, glsl``, fragment)
630
631
 
631
- // Check that shaderSource was called with symbol aliases in template
632
+ const colorAlias = toID(color_symbol)
633
+
634
+ // Check that shaderSource was called with exact symbol alias
632
635
  const fragmentShaderSource = (gl.shaderSource as any).mock.calls.find(
633
- (call: any[]) => call[1].includes('vec3') && call[1].includes('VIEW_GL_ALIAS_')
636
+ (call: any[]) => call[1].includes(`vec3 ${colorAlias}`)
634
637
  )?.[1]
635
638
 
636
- expect(fragmentShaderSource).toMatch(/vec3 VIEW_GL_ALIAS_\d+ = vec3/)
637
- expect(fragmentShaderSource).toMatch(/vec4\(VIEW_GL_ALIAS_\d+, 1\.0\)/)
639
+ expect(fragmentShaderSource).toContain(`vec3 ${colorAlias} = vec3(1.0, 0.0, 0.0);`)
640
+ expect(fragmentShaderSource).toContain(`gl_FragColor = vec4(${colorAlias}, 1.0);`)
638
641
  })
639
642
  })
640
643
 
@@ -1485,6 +1488,231 @@ describe('compile', () => {
1485
1488
  expect(schema.uniforms[u_vertex_only]).toEqual({ kind: 'vec2' })
1486
1489
  expect(schema.uniforms[u_fragment_only]).toEqual({ kind: 'vec3' })
1487
1490
  })
1491
+
1492
+ it('should return compiled vertex and fragment shader strings', () => {
1493
+ const vertex = glsl`
1494
+ ${attribute.vec2('a_position')}
1495
+ ${uniform.mat4('u_mvpMatrix')}
1496
+
1497
+ void main() {
1498
+ gl_Position = u_mvpMatrix * vec4(a_position, 0.0, 1.0);
1499
+ }
1500
+ `
1501
+
1502
+ const fragment = glsl`
1503
+ precision mediump float;
1504
+ ${uniform.vec4('u_color')}
1505
+
1506
+ void main() {
1507
+ gl_FragColor = u_color;
1508
+ }
1509
+ `
1510
+
1511
+ const result = compile(gl, vertex, fragment)
1512
+
1513
+ // Check vertex shader string
1514
+ expect(result.vertex).toContain('attribute vec2 a_position;')
1515
+ expect(result.vertex).toContain('uniform mat4 u_mvpMatrix;')
1516
+ expect(result.vertex).toContain('gl_Position = u_mvpMatrix * vec4(a_position, 0.0, 1.0);')
1517
+
1518
+ // Check fragment shader string
1519
+ expect(result.fragment).toContain('precision mediump float;')
1520
+ expect(result.fragment).toContain('uniform vec4 u_color;')
1521
+ expect(result.fragment).toContain('gl_FragColor = u_color;')
1522
+ })
1523
+
1524
+ it('should return WebGL2 shader strings with proper syntax', () => {
1525
+ const vertex = glsl`#version 300 es
1526
+ ${attribute.vec3('a_position')}
1527
+ ${attribute.vec3('a_normal')}
1528
+ out vec3 v_normal;
1529
+
1530
+ void main() {
1531
+ v_normal = a_normal;
1532
+ gl_Position = vec4(a_position, 1.0);
1533
+ }
1534
+ `
1535
+
1536
+ const fragment = glsl`#version 300 es
1537
+ precision mediump float;
1538
+ ${uniform.vec3('u_lightDir')}
1539
+ in vec3 v_normal;
1540
+ out vec4 fragColor;
1541
+
1542
+ void main() {
1543
+ float light = dot(v_normal, u_lightDir);
1544
+ fragColor = vec4(vec3(light), 1.0);
1545
+ }
1546
+ `
1547
+
1548
+ const result = compile(gl, vertex, fragment)
1549
+
1550
+ // Check vertex uses 'in' for attributes in WebGL2
1551
+ expect(result.vertex).toContain('in vec3 a_position;')
1552
+ expect(result.vertex).toContain('in vec3 a_normal;')
1553
+ expect(result.vertex).toContain('out vec3 v_normal;')
1554
+
1555
+ // Check fragment shader WebGL2 syntax
1556
+ expect(result.fragment).toContain('#version 300 es')
1557
+ expect(result.fragment).toContain('in vec3 v_normal;')
1558
+ expect(result.fragment).toContain('out vec4 fragColor;')
1559
+ })
1560
+
1561
+ it('should return shader strings with resolved symbols', () => {
1562
+ const u_time_symbol = Symbol('u_time')
1563
+ const a_pos_symbol = Symbol('a_position')
1564
+
1565
+ const vertex = glsl`
1566
+ ${attribute.vec3(a_pos_symbol)}
1567
+ ${uniform.float(u_time_symbol)}
1568
+
1569
+ void main() {
1570
+ gl_Position = vec4(${a_pos_symbol}, ${u_time_symbol});
1571
+ }
1572
+ `
1573
+
1574
+ const fragment = glsl`
1575
+ precision mediump float;
1576
+ ${uniform.float(u_time_symbol)}
1577
+
1578
+ void main() {
1579
+ gl_FragColor = vec4(${u_time_symbol});
1580
+ }
1581
+ `
1582
+
1583
+ const result = compile(gl, vertex, fragment)
1584
+
1585
+ // Get exact symbol aliases
1586
+ const posAlias = toID(a_pos_symbol)
1587
+ const timeAlias = toID(u_time_symbol)
1588
+
1589
+ // Check vertex shader contains expected exact strings
1590
+ expect(result.vertex).toContain(`attribute vec3 ${posAlias};`)
1591
+ expect(result.vertex).toContain(`uniform float ${timeAlias};`)
1592
+ expect(result.vertex).toContain(`gl_Position = vec4(${posAlias}, ${timeAlias});`)
1593
+
1594
+ // Check fragment shader contains expected exact strings
1595
+ expect(result.fragment).toContain(`uniform float ${timeAlias};`)
1596
+ expect(result.fragment).toContain(`gl_FragColor = vec4(${timeAlias});`)
1597
+ expect(result.fragment).toContain('precision mediump float;')
1598
+ })
1599
+
1600
+ it('should return shader strings with interleaved attributes', () => {
1601
+ const vertex = glsl`
1602
+ ${interleave('vertexData', [
1603
+ attribute.vec3('a_position'),
1604
+ attribute.vec2('a_uv'),
1605
+ attribute.vec3('a_normal')
1606
+ ])}
1607
+
1608
+ void main() {
1609
+ gl_Position = vec4(a_position + a_normal, 0.0, 1.0);
1610
+ }
1611
+ `
1612
+
1613
+ const fragment = glsl`
1614
+ precision mediump float;
1615
+
1616
+ void main() {
1617
+ gl_FragColor = vec4(1.0);
1618
+ }
1619
+ `
1620
+
1621
+ const result = compile(gl, vertex, fragment)
1622
+
1623
+ // Check all interleaved attributes are expanded in vertex shader
1624
+ expect(result.vertex).toContain('attribute vec3 a_position;')
1625
+ expect(result.vertex).toContain('attribute vec2 a_uv;')
1626
+ expect(result.vertex).toContain('attribute vec3 a_normal;')
1627
+ expect(result.vertex).toContain('gl_Position = vec4(a_position + a_normal, 0.0, 1.0);')
1628
+
1629
+ // Fragment shader should be returned as-is
1630
+ expect(result.fragment).toContain('precision mediump float;')
1631
+ expect(result.fragment).toContain('gl_FragColor = vec4(1.0);')
1632
+ })
1633
+
1634
+ it('should return shader strings with composed GLSL fragments', () => {
1635
+ const sharedUniforms = glsl`
1636
+ ${uniform.float('u_time')}
1637
+ ${uniform.vec2('u_resolution')}
1638
+ `
1639
+
1640
+ const utils = glsl`
1641
+ float rand(vec2 co) {
1642
+ return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);
1643
+ }
1644
+ `
1645
+
1646
+ const vertex = glsl`
1647
+ ${sharedUniforms}
1648
+ ${attribute.vec2('a_position')}
1649
+
1650
+ void main() {
1651
+ gl_Position = vec4(a_position * u_resolution, 0.0, 1.0);
1652
+ }
1653
+ `
1654
+
1655
+ const fragment = glsl`
1656
+ precision mediump float;
1657
+ ${sharedUniforms}
1658
+ ${utils}
1659
+
1660
+ void main() {
1661
+ float r = rand(gl_FragCoord.xy * u_time);
1662
+ gl_FragColor = vec4(r);
1663
+ }
1664
+ `
1665
+
1666
+ const result = compile(gl, vertex, fragment)
1667
+
1668
+ // Check vertex shader includes composed uniforms
1669
+ expect(result.vertex).toContain('uniform float u_time;')
1670
+ expect(result.vertex).toContain('uniform vec2 u_resolution;')
1671
+ expect(result.vertex).toContain('attribute vec2 a_position;')
1672
+
1673
+ // Check fragment shader includes both uniforms and utils
1674
+ expect(result.fragment).toContain('uniform float u_time;')
1675
+ expect(result.fragment).toContain('uniform vec2 u_resolution;')
1676
+ expect(result.fragment).toContain('float rand(vec2 co)')
1677
+ expect(result.fragment).toContain('return fract(sin(dot(co.xy')
1678
+ })
1679
+
1680
+ it('should return shader strings with array interpolations', () => {
1681
+ const vertex = glsl`
1682
+ ${[
1683
+ uniform.mat4('u_model'),
1684
+ uniform.mat4('u_view'),
1685
+ uniform.mat4('u_projection')
1686
+ ]}
1687
+ ${[attribute.vec3('a_position'), attribute.vec3('a_normal')]}
1688
+
1689
+ void main() {
1690
+ gl_Position = u_projection * u_view * u_model * vec4(a_position, 1.0);
1691
+ }
1692
+ `
1693
+
1694
+ const fragment = glsl`
1695
+ precision mediump float;
1696
+ ${[uniform.vec3('u_color'), uniform.float('u_alpha')]}
1697
+
1698
+ void main() {
1699
+ gl_FragColor = vec4(u_color, u_alpha);
1700
+ }
1701
+ `
1702
+
1703
+ const result = compile(gl, vertex, fragment)
1704
+
1705
+ // Check vertex shader has all uniforms and attributes from arrays
1706
+ expect(result.vertex).toContain('uniform mat4 u_model;')
1707
+ expect(result.vertex).toContain('uniform mat4 u_view;')
1708
+ expect(result.vertex).toContain('uniform mat4 u_projection;')
1709
+ expect(result.vertex).toContain('attribute vec3 a_position;')
1710
+ expect(result.vertex).toContain('attribute vec3 a_normal;')
1711
+
1712
+ // Check fragment shader
1713
+ expect(result.fragment).toContain('uniform vec3 u_color;')
1714
+ expect(result.fragment).toContain('uniform float u_alpha;')
1715
+ })
1488
1716
  })
1489
1717
 
1490
1718
  describe('compile.toString', () => {
@@ -1544,9 +1772,10 @@ describe('compile.toString', () => {
1544
1772
  }`
1545
1773
 
1546
1774
  const result = compile.toString(shader)
1775
+ const timeAlias = toID(u_time_symbol)
1547
1776
 
1548
- expect(result).toMatch(/uniform float VIEW_GL_ALIAS_\d+;/)
1549
- expect(result).toMatch(/vec4\(VIEW_GL_ALIAS_\d+\)/)
1777
+ expect(result).toContain(`uniform float ${timeAlias};`)
1778
+ expect(result).toContain(`gl_FragColor = vec4(${timeAlias});`)
1550
1779
  })
1551
1780
 
1552
1781
  it('should handle interleaved attributes', () => {