@bigmistqke/view.gl 0.1.7 → 0.1.9

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.
@@ -280,7 +280,7 @@ interface AttributeMethods<T = AttributeKind> {
280
280
  dispose(): void;
281
281
  }
282
282
  type AttributeView<T extends AttributeSchema> = {
283
- [K in keyof T]: AttributeMethods<T[K]['kind']>;
283
+ [K in keyof T]: Prettify<AttributeMethods<T[K]['kind']>>;
284
284
  };
285
285
  /**********************************************************************************/
286
286
  /**********************************************************************************/
@@ -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']>> : {};
393
+ interleavedAttributes: T['interleavedAttributes'] extends InterleavedAttributeSchema ? Prettify<InterleavedAttributeView<T['interleavedAttributes']>> : {};
394
+ buffers: T['buffers'] extends BufferSchema ? Prettify<BufferView<T['buffers']>> : {};
395
+ uniforms: T['uniforms'] extends UniformSchema ? Prettify<UniformView<T['uniforms']>> : {};
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,59 +419,66 @@ 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
- instanced: TInstanced;
429
+ instanced: TInstanced extends boolean ? boolean : false;
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>] : [];
457
- type MergeGLSLSchema<TVertex extends ViewSchema, TFragment extends ViewSchema, TOverrides extends ViewSchemaPartial = {}> = {
458
- uniforms: DeepMerge<[
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>] : [];
458
+ type MergeGLSLSchema<TVertex extends ViewSchema, TFragment extends ViewSchema, TOverrides extends ViewSchemaPartial | undefined = {}> = TOverrides extends ViewSchemaPartial ? {
459
+ uniforms: Prettify<DeepMerge<[
459
460
  ShallowMerge<[TVertex['uniforms'], TFragment['uniforms']]>,
460
461
  TOverrides['uniforms']
461
- ]>;
462
- attributes: DeepMerge<[
462
+ ]>>;
463
+ attributes: Prettify<DeepMerge<[
463
464
  ShallowMerge<[TVertex['attributes'], TFragment['attributes']]>,
464
465
  TOverrides['attributes']
465
- ]>;
466
- interleavedAttributes: DeepMerge<[
466
+ ]>>;
467
+ interleavedAttributes: Prettify<DeepMerge<[
467
468
  ShallowMerge<[TVertex['interleavedAttributes'], TFragment['interleavedAttributes']]>,
468
469
  TOverrides['interleavedAttributes']
469
- ]>;
470
+ ]>>;
471
+ } : {
472
+ uniforms: Prettify<ShallowMerge<[TVertex['uniforms'], TFragment['uniforms']]>>;
473
+ attributes: Prettify<ShallowMerge<[TVertex['attributes'], TFragment['attributes']]>>;
474
+ interleavedAttributes: Prettify<ShallowMerge<[TVertex['interleavedAttributes'], TFragment['interleavedAttributes']]>>;
470
475
  };
471
- type CompileResult<TVertex extends GLSLTag, TFragment extends GLSLTag, TOverrides extends ViewSchemaPartial> = MergeGLSLSchema<GLSLTagToSchema<TVertex>, GLSLTagToSchema<TFragment>, TOverrides> extends infer TSchema extends ViewSchema ? {
476
+ type CompileResult<TVertex extends GLSL, TFragment extends GLSL, TOverrideSchema extends ViewSchemaPartial | undefined> = MergeGLSLSchema<GLSLToSchema<TVertex>, GLSLToSchema<TFragment>, TOverrideSchema> extends infer TSchema extends ViewSchema ? {
472
477
  program: WebGLProgram;
473
478
  schema: TSchema;
474
- view: View<TSchema>;
479
+ view: Prettify<View<TSchema>>;
480
+ vertex: string;
481
+ fragment: string;
475
482
  } : never;
476
483
 
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 };
484
+ 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.9",
4
4
  "description": "👀 Utilities for managing WebGL resources.",
5
5
  "exports": {
6
6
  ".": {
package/src/tag.ts CHANGED
@@ -3,25 +3,26 @@ 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
+ GL,
10
+ GLSL,
9
11
  GLSLSlot,
10
- GLSLTag,
11
- GLSLTagToSchema,
12
- InterleaveTag,
12
+ GLSLToSchema,
13
+ InterleaveToken,
13
14
  UniformDefinition,
14
15
  UniformKind,
15
- UniformTagFn as UniformTagMethod,
16
+ UniformTokenFn as UniformTagMethod,
16
17
  ViewSchema,
17
18
  ViewSchemaPartial,
18
19
  } from './types'
19
- import { createProgram } from './utils'
20
+ import { createProgram, createUpsertMap } from './utils'
20
21
 
21
22
  export function glsl<TSlot extends GLSLSlot, TSlots extends TSlot[]>(
22
23
  template: TemplateStringsArray,
23
24
  ...slots: [...TSlots]
24
- ): GLSLTag<TSlots> {
25
+ ): GLSL<TSlots> {
25
26
  return { template, slots, type: 'glsl' }
26
27
  }
27
28
 
@@ -63,16 +64,16 @@ export const attribute = new Proxy(
63
64
 
64
65
  export function interleave<
65
66
  const TKey extends string | symbol,
66
- const TLayout extends Array<AttributeTag<string | symbol, AttributeKind, undefined>>,
67
+ const TLayout extends Array<AttributeToken<string | symbol, AttributeKind, undefined>>,
67
68
  const TOptions extends Omit<AttributeDefinition, 'kind'>,
68
- >(key: TKey, layout: TLayout, instanced: TOptions): InterleaveTag<TKey, TLayout, TOptions>
69
+ >(key: TKey, layout: TLayout, instanced: TOptions): InterleaveToken<TKey, TLayout, TOptions>
69
70
  export function interleave<
70
71
  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 }>
72
+ const TLayout extends Array<AttributeToken<string | symbol, AttributeKind, undefined>>,
73
+ >(key: TKey, layout: TLayout): InterleaveToken<TKey, TLayout, { instanced: false }>
73
74
  export function interleave<
74
75
  const TKey extends string | symbol,
75
- const TLayout extends Array<AttributeTag<string | symbol, AttributeKind, undefined>>,
76
+ const TLayout extends Array<AttributeToken<string | symbol, AttributeKind, undefined>>,
76
77
  const TOptions extends Omit<AttributeDefinition, 'kind'>,
77
78
  >(key: TKey, layout: TLayout, { instanced, buffer }: Partial<TOptions> = {}) {
78
79
  return {
@@ -85,7 +86,7 @@ export function interleave<
85
86
  })),
86
87
  instanced: !!instanced,
87
88
  buffer,
88
- } as unknown as InterleaveTag<TKey, TLayout, TOptions>
89
+ } as unknown as InterleaveToken<TKey, TLayout, TOptions>
89
90
  }
90
91
 
91
92
  /**********************************************************************************/
@@ -94,13 +95,23 @@ export function interleave<
94
95
  /* */
95
96
  /**********************************************************************************/
96
97
 
98
+ export interface CompileOptions<TSchema extends ViewSchemaPartial> {
99
+ schema?: TSchema
100
+ webgl2?: boolean
101
+ }
102
+
97
103
  export function compile<
98
- TVertex extends GLSLTag,
99
- TFragment extends GLSLTag,
100
- TOverride extends ViewSchemaPartial,
101
- >(gl: WebGLRenderingContext, vertex: TVertex, fragment: TFragment, overrideSchema?: TOverride) {
102
- const _vertex = resolveGLSLTag(vertex) as { template: string; schema: ViewSchema }
103
- const _fragment = resolveGLSLTag(fragment) as { template: string; schema: ViewSchema }
104
+ TVertex extends GLSL,
105
+ TFragment extends GLSL,
106
+ TSchema extends ViewSchemaPartial,
107
+ >(
108
+ gl: WebGLRenderingContext,
109
+ vertex: TVertex,
110
+ fragment: TFragment,
111
+ options?: CompileOptions<TSchema> | undefined,
112
+ ) {
113
+ const _vertex = resolveGLSLTag(vertex, options) as { template: string; schema: ViewSchema }
114
+ const _fragment = resolveGLSLTag(fragment, options) as { template: string; schema: ViewSchema }
104
115
 
105
116
  const schema = {
106
117
  uniforms: {
@@ -117,48 +128,58 @@ export function compile<
117
128
  },
118
129
  }
119
130
 
120
- for (const kind in overrideSchema) {
131
+ // Deep merge options.schema with generated schema
132
+ for (const kind in options?.schema) {
121
133
  const schemaKind = schema[kind as keyof typeof schema]
122
- const overrideSchemaKind = overrideSchema[kind]
134
+ const configSchemaKind = options?.schema[kind]
123
135
 
124
- for (const key in overrideSchemaKind) {
136
+ for (const key in configSchemaKind) {
125
137
  schemaKind[key] = {
126
138
  ...schemaKind[key],
127
- ...overrideSchemaKind[key],
139
+ ...configSchemaKind[key],
128
140
  }
129
141
  }
130
142
  }
131
143
 
132
- const program = createProgram(gl, _vertex.template, _fragment.template)
133
-
134
- return {
135
- program,
136
- schema,
137
- view: view(gl, program, schema),
138
- } as Prettify<CompileResult<TVertex, TFragment, TOverride>>
144
+ try {
145
+ const program = createProgram(gl, _vertex.template, _fragment.template)
146
+
147
+ return {
148
+ program,
149
+ schema,
150
+ view: view(gl, program, schema),
151
+ vertex: _vertex.template,
152
+ fragment: _fragment.template,
153
+ } as unknown as Prettify<CompileResult<TVertex, TFragment, TSchema>>
154
+ } catch (error) {
155
+ console.error('Error while creating WebGLProgram - vertex\n\n', _vertex.template)
156
+ console.error('Error while creating WebGLProgram - fragment\n\n', _fragment.template)
157
+
158
+ throw error
159
+ }
139
160
  }
140
161
 
141
- function resolveGLSLTag<TTag extends GLSLTag>(tag: TTag) {
162
+ function resolveGLSLTag<TTag extends GLSL>(tag: TTag, options?: { webgl2?: boolean }) {
142
163
  return {
143
- template: compile.toString(tag),
164
+ template: compile.toString(tag, options),
144
165
  schema: compile.toSchema(tag),
145
166
  }
146
167
  }
147
168
 
148
- compile.toSchema = function <TTag extends GLSLTag>(tag: TTag) {
169
+ compile.toSchema = function <TTag extends GLSL>(tag: TTag) {
149
170
  const result = {
150
171
  uniforms: {},
151
172
  attributes: {},
152
173
  interleavedAttributes: {},
153
174
  }
154
175
 
155
- function handleSlot(slot: GLSLSlot) {
156
- if (Array.isArray(slot)) {
157
- slot.forEach(handleSlot)
176
+ tag.slots.forEach(function handleSlot(slot: GLSLSlot) {
177
+ if (typeof slot !== 'object') {
158
178
  return
159
179
  }
160
180
 
161
- if (typeof slot !== 'object') {
181
+ if (Array.isArray(slot)) {
182
+ slot.forEach(handleSlot)
162
183
  return
163
184
  }
164
185
 
@@ -185,49 +206,97 @@ compile.toSchema = function <TTag extends GLSLTag>(tag: TTag) {
185
206
 
186
207
  // @ts-expect-error
187
208
  result[`${type}s`][name] = rest
188
- }
189
-
190
- tag.slots.forEach(handleSlot)
209
+ })
191
210
 
192
- return result as unknown as Prettify<GLSLTagToSchema<TTag>>
211
+ return result as unknown as Prettify<GLSLToSchema<TTag>>
193
212
  }
194
213
 
195
- compile.toString = function <TTag extends GLSLTag>({ template: [initial, ...rest], slots }: TTag) {
196
- const v300 = !!initial?.startsWith('#version 300 es')
214
+ compile.toString = function <TTag extends GLSL>(
215
+ { template: [initial, ...rest], slots }: TTag,
216
+ config?: { webgl2?: boolean },
217
+ ) {
218
+ const v300 = config?.webgl2 ?? !!initial?.startsWith('#version 300 es')
197
219
 
198
220
  let template = initial ?? ''
199
221
 
200
222
  for (let i = 0; i < rest.length; i++) {
201
- template += `${glslSlotToString(slots[i]!, v300)}${rest[i]}`
223
+ template += `${resolveGlslSlotToString(slots[i]!, v300)}${rest[i]}`
202
224
  }
203
225
 
204
226
  return template
205
227
  }
206
228
 
207
- function glslSlotToString(slot: GLSLSlot, v300: boolean): string {
229
+ function resolveGlslSlotToString(slot: GLSLSlot, v300: boolean): string {
208
230
  if (typeof slot !== 'object') {
209
231
  return toID(slot)
210
232
  }
211
233
 
212
234
  if (Array.isArray(slot)) {
213
- return slot.map(slot => glslSlotToString(slot, v300)).join('')
235
+ return slot.map(slot => resolveGlslSlotToString(slot, v300)).join('')
214
236
  }
215
237
 
216
- if (slot.type === 'glsl') {
217
- return compile.toString(slot)
238
+ switch (slot.type) {
239
+ case 'glsl':
240
+ return compile.toString(slot)
241
+ case 'interleavedAttribute':
242
+ return slot.layout.reduce(
243
+ (a, v) =>
244
+ v300 ? `${a}in ${v.kind} ${toID(v.key)};\n` : `${a}attribute ${v.kind} ${toID(v.key)};\n`,
245
+ '',
246
+ )
247
+ case 'uniform':
248
+ if ('size' in slot) {
249
+ return `${slot.type} ${slot.kind} ${toID(slot.key)}[${slot.size}];`
250
+ }
251
+ return `${slot.type} ${slot.kind} ${toID(slot.key)};`
218
252
  }
219
253
 
220
- if (slot.type === 'interleavedAttribute') {
221
- return slot.layout.reduce(
222
- (a, v) =>
223
- v300 ? `${a}in ${v.kind} ${toID(v.key)};\n` : `${a}attribute ${v.kind} ${toID(v.key)};\n`,
224
- '',
225
- )
254
+ if (slot.type === 'attribute') {
255
+ return `${v300 ? 'in' : slot.type} ${slot.kind} ${toID(slot.key)};`
226
256
  }
227
257
 
228
- if (slot.type === 'uniform' && 'size' in slot) {
229
- return `${slot.type} ${slot.kind} ${toID(slot.key)}[${slot.size}];`
230
- }
258
+ throw new Error(`Unexpected slot: ${JSON.stringify(slot)}`)
259
+ }
260
+
261
+ const QUAD_FLOAT_ARRAY = new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1])
262
+ const QUAD_BUFFER_MAP = createUpsertMap(WeakMap<GL, WebGLBuffer>)
263
+
264
+ compile.toQuad = function <TFragment extends GLSL, TSchema extends ViewSchemaPartial>(
265
+ gl: GL,
266
+ fragment: TFragment,
267
+ options?: CompileOptions<TSchema>,
268
+ ) {
269
+ const buffer = QUAD_BUFFER_MAP.getOrInsert(gl, gl.createBuffer.bind(gl))
270
+
271
+ const webgl2 = options?.webgl2 ?? fragment.template[0]?.startsWith('#version 300 es')
272
+
273
+ const vertex = webgl2
274
+ ? glsl`#version 300 es
275
+ precision mediump float;
276
+
277
+ ${attribute.vec2('a_quad', { buffer })}
278
+
279
+ out vec2 v_uv;
280
+
281
+ void main() {
282
+ v_uv = a_quad;
283
+ gl_Position = vec4(v_uv, 0.0, 1.0);
284
+ }`
285
+ : glsl`precision mediump float;
286
+
287
+ ${attribute.vec2('a_quad', { buffer })}
288
+
289
+ varying vec2 v_uv;
290
+
291
+ void main() {
292
+ v_uv = a_quad;
293
+ gl_Position = vec4(v_uv, 0.0, 1.0);
294
+ }`
295
+
296
+ const result = compile(gl, vertex, fragment, options)
297
+
298
+ // @ts-expect-error
299
+ result.view.attributes.a_quad.set(QUAD_FLOAT_ARRAY)
231
300
 
232
- return `${slot.type === 'attribute' && v300 ? 'in' : slot.type} ${slot.kind} ${toID(slot.key)};`
301
+ return result
233
302
  }