@luma.gl/webgl 9.1.0-alpha.16 → 9.1.0-alpha.17

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.
Files changed (55) hide show
  1. package/dist/adapter/converters/sampler-parameters.js +6 -4
  2. package/dist/adapter/converters/texture-formats.d.ts +49 -11
  3. package/dist/adapter/converters/texture-formats.d.ts.map +1 -1
  4. package/dist/adapter/converters/texture-formats.js +150 -160
  5. package/dist/adapter/helpers/format-utils.d.ts.map +1 -1
  6. package/dist/adapter/helpers/format-utils.js +6 -0
  7. package/dist/adapter/helpers/webgl-texture-utils.d.ts +10 -8
  8. package/dist/adapter/helpers/webgl-texture-utils.d.ts.map +1 -1
  9. package/dist/adapter/helpers/webgl-texture-utils.js +46 -32
  10. package/dist/adapter/resources/webgl-command-buffer.d.ts +59 -2
  11. package/dist/adapter/resources/webgl-command-buffer.d.ts.map +1 -1
  12. package/dist/adapter/resources/webgl-command-buffer.js +72 -16
  13. package/dist/adapter/resources/webgl-command-encoder.d.ts.map +1 -1
  14. package/dist/adapter/resources/webgl-command-encoder.js +3 -0
  15. package/dist/adapter/resources/webgl-external-texture.js +14 -0
  16. package/dist/adapter/resources/webgl-framebuffer.d.ts.map +1 -1
  17. package/dist/adapter/resources/webgl-framebuffer.js +1 -2
  18. package/dist/adapter/resources/webgl-render-pass.d.ts.map +1 -1
  19. package/dist/adapter/resources/webgl-render-pass.js +38 -20
  20. package/dist/adapter/resources/webgl-render-pipeline.d.ts.map +1 -1
  21. package/dist/adapter/resources/webgl-render-pipeline.js +6 -5
  22. package/dist/adapter/resources/webgl-shader.js +1 -1
  23. package/dist/adapter/resources/webgl-texture.d.ts +8 -14
  24. package/dist/adapter/resources/webgl-texture.d.ts.map +1 -1
  25. package/dist/adapter/resources/webgl-texture.js +119 -208
  26. package/dist/adapter/webgl-adapter.js +1 -1
  27. package/dist/adapter/webgl-device.d.ts +7 -1
  28. package/dist/adapter/webgl-device.d.ts.map +1 -1
  29. package/dist/adapter/webgl-device.js +22 -10
  30. package/dist/context/debug/webgl-developer-tools.d.ts +1 -0
  31. package/dist/context/debug/webgl-developer-tools.d.ts.map +1 -1
  32. package/dist/context/debug/webgl-developer-tools.js +4 -2
  33. package/dist/context/helpers/create-browser-context.d.ts.map +1 -1
  34. package/dist/context/helpers/create-browser-context.js +17 -3
  35. package/dist/dist.dev.js +226 -272
  36. package/dist/dist.min.js +2 -2
  37. package/dist/index.cjs +220 -269
  38. package/dist/index.cjs.map +3 -3
  39. package/package.json +4 -4
  40. package/src/adapter/converters/sampler-parameters.ts +6 -4
  41. package/src/adapter/converters/texture-formats.ts +171 -177
  42. package/src/adapter/helpers/format-utils.ts +6 -0
  43. package/src/adapter/helpers/webgl-texture-utils.ts +66 -45
  44. package/src/adapter/resources/webgl-command-buffer.ts +108 -24
  45. package/src/adapter/resources/webgl-command-encoder.ts +6 -0
  46. package/src/adapter/resources/webgl-external-texture.ts +14 -0
  47. package/src/adapter/resources/webgl-framebuffer.ts +1 -2
  48. package/src/adapter/resources/webgl-render-pass.ts +44 -23
  49. package/src/adapter/resources/webgl-render-pipeline.ts +6 -5
  50. package/src/adapter/resources/webgl-shader.ts +1 -1
  51. package/src/adapter/resources/webgl-texture.ts +126 -235
  52. package/src/adapter/webgl-adapter.ts +1 -1
  53. package/src/adapter/webgl-device.ts +23 -10
  54. package/src/context/debug/webgl-developer-tools.ts +5 -2
  55. package/src/context/helpers/create-browser-context.ts +18 -3
@@ -6,24 +6,24 @@
6
6
  // WebGL... the texture API from hell... hopefully made simpler
7
7
  //
8
8
 
9
+ import {TypedArray} from '@math.gl/types';
9
10
  import type {ExternalImage} from '@luma.gl/core';
10
11
  import {Buffer, Texture, Framebuffer, FramebufferProps} from '@luma.gl/core';
11
-
12
12
  import {
13
13
  GL,
14
14
  GLTextureTarget,
15
15
  GLTextureCubeMapTarget,
16
16
  GLTexelDataFormat,
17
- GLPixelType
17
+ GLPixelType,
18
+ GLDataType
18
19
  } from '@luma.gl/constants';
19
20
 
20
- import {TypedArray} from '@math.gl/types';
21
-
22
21
  import {WEBGLFramebuffer} from '../resources/webgl-framebuffer';
23
22
  import {getGLTypeFromTypedArray, getTypedArrayFromGLType} from './typed-array-utils';
24
23
  import {glFormatToComponents, glTypeToBytes} from './format-utils';
25
24
  import {WEBGLBuffer} from '../resources/webgl-buffer';
26
25
  import {WEBGLTexture} from '../resources/webgl-texture';
26
+ import {withGLParameters} from '../../context/state-tracker/with-parameters';
27
27
 
28
28
  /** A "border" parameter is required in many WebGL texture APIs, but must always be 0... */
29
29
  const BORDER = 0;
@@ -120,7 +120,7 @@ export function copyExternalImageToMipLevel(
120
120
  gl: WebGL2RenderingContext,
121
121
  handle: WebGLTexture,
122
122
  image: ExternalImage,
123
- options: WebGLCopyTextureOptions
123
+ options: WebGLCopyTextureOptions & {flipY?: boolean}
124
124
  ): void {
125
125
  const {width, height} = options;
126
126
  const {dimension, depth = 0, mipLevel = 0} = options;
@@ -129,26 +129,29 @@ export function copyExternalImageToMipLevel(
129
129
 
130
130
  const glTarget = getWebGLCubeFaceTarget(options.glTarget, dimension, depth);
131
131
 
132
- switch (dimension) {
133
- case '2d-array':
134
- case '3d':
135
- gl.bindTexture(glTarget, handle);
136
- // prettier-ignore
137
- gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, image);
138
- gl.bindTexture(glTarget, null);
139
- break;
132
+ const glParameters = options.flipY ? {[GL.UNPACK_FLIP_Y_WEBGL]: true} : {};
133
+ withGLParameters(gl, glParameters, () => {
134
+ switch (dimension) {
135
+ case '2d-array':
136
+ case '3d':
137
+ gl.bindTexture(glTarget, handle);
138
+ // prettier-ignore
139
+ gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, image);
140
+ gl.bindTexture(glTarget, null);
141
+ break;
140
142
 
141
- case '2d':
142
- case 'cube':
143
- gl.bindTexture(glTarget, handle);
144
- // prettier-ignore
145
- gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, image);
146
- gl.bindTexture(glTarget, null);
147
- break;
143
+ case '2d':
144
+ case 'cube':
145
+ gl.bindTexture(glTarget, handle);
146
+ // prettier-ignore
147
+ gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, image);
148
+ gl.bindTexture(glTarget, null);
149
+ break;
148
150
 
149
- default:
150
- throw new Error(dimension);
151
- }
151
+ default:
152
+ throw new Error(dimension);
153
+ }
154
+ });
152
155
  }
153
156
 
154
157
  /**
@@ -278,7 +281,7 @@ export function getWebGLCubeFaceTarget(
278
281
  * Wrapper for the messy WebGL texture API
279
282
  *
280
283
  export function clearMipLevel(gl: WebGL2RenderingContext, options: WebGLSetTextureOptions): void {
281
- const {dimension, width, height, depth = 0, level = 0} = options;
284
+ const {dimension, width, height, depth = 0, mipLevel = 0} = options;
282
285
  const {glInternalFormat, glFormat, glType, compressed} = options;
283
286
  const glTarget = getWebGLCubeFaceTarget(options.glTarget, dimension, depth);
284
287
 
@@ -287,10 +290,10 @@ export function clearMipLevel(gl: WebGL2RenderingContext, options: WebGLSetTextu
287
290
  case '3d':
288
291
  if (compressed) {
289
292
  // prettier-ignore
290
- gl.compressedTexImage3D(glTarget, level, glInternalFormat, width, height, depth, BORDER, null);
293
+ gl.compressedTexImage3D(glTarget, mipLevel, glInternalFormat, width, height, depth, BORDER, null);
291
294
  } else {
292
295
  // prettier-ignore
293
- gl.texImage3D( glTarget, level, glInternalFormat, width, height, depth, BORDER, glFormat, glType, null);
296
+ gl.texImage3D( glTarget, mipLevel, glInternalFormat, width, height, depth, BORDER, glFormat, glType, null);
294
297
  }
295
298
  break;
296
299
 
@@ -298,10 +301,10 @@ export function clearMipLevel(gl: WebGL2RenderingContext, options: WebGLSetTextu
298
301
  case 'cube':
299
302
  if (compressed) {
300
303
  // prettier-ignore
301
- gl.compressedTexImage2D(glTarget, level, glInternalFormat, width, height, BORDER, null);
304
+ gl.compressedTexImage2D(glTarget, mipLevel, glInternalFormat, width, height, BORDER, null);
302
305
  } else {
303
306
  // prettier-ignore
304
- gl.texImage2D(glTarget, level, glInternalFormat, width, height, BORDER, glFormat, glType, null);
307
+ gl.texImage2D(glTarget, mipLevel, glInternalFormat, width, height, BORDER, glFormat, glType, null);
305
308
  }
306
309
  break;
307
310
 
@@ -309,6 +312,7 @@ export function clearMipLevel(gl: WebGL2RenderingContext, options: WebGLSetTextu
309
312
  throw new Error(dimension);
310
313
  }
311
314
  }
315
+ */
312
316
 
313
317
  /**
314
318
  * Set a texture mip level to the contents of an external image.
@@ -533,7 +537,7 @@ export function readPixelsToArray(
533
537
  const {
534
538
  sourceX = 0,
535
539
  sourceY = 0,
536
- sourceAttachment = GL.COLOR_ATTACHMENT0 // TODO - support gl.readBuffer
540
+ sourceAttachment = 0 // TODO - support gl.readBuffer
537
541
  } = options || {};
538
542
  let {
539
543
  target = null,
@@ -548,21 +552,19 @@ export function readPixelsToArray(
548
552
  const {framebuffer, deleteFramebuffer} = getFramebuffer(source);
549
553
  // assert(framebuffer);
550
554
  const {gl, handle} = framebuffer;
551
- const attachment = sourceAttachment - GL.COLOR_ATTACHMENT0;
552
555
 
553
556
  sourceWidth ||= framebuffer.width;
554
557
  sourceHeight ||= framebuffer.height;
555
558
 
556
- // TODO - Set and unset gl.readBuffer
557
- // if (sourceAttachment === GL.COLOR_ATTACHMENT0 && handle === null) {
558
- // sourceAttachment = GL.FRONT;
559
- // }
560
-
561
- sourceDepth = framebuffer.colorAttachments[attachment]?.texture?.depth || 1;
559
+ const texture = framebuffer.colorAttachments[sourceAttachment]?.texture;
560
+ if (!texture) {
561
+ throw new Error(`Invalid framebuffer attachment ${sourceAttachment}`);
562
+ }
563
+ sourceDepth = texture?.depth || 1;
562
564
 
563
- sourceFormat ||= framebuffer.colorAttachments[attachment]?.texture?.glFormat || GL.RGBA;
565
+ sourceFormat ||= texture?.glFormat || GL.RGBA;
564
566
  // Deduce the type from color attachment if not provided.
565
- sourceType ||= framebuffer.colorAttachments[attachment]?.texture?.glType || GL.UNSIGNED_BYTE;
567
+ sourceType ||= texture?.glType || GL.UNSIGNED_BYTE;
566
568
 
567
569
  // Deduce type and allocated pixelArray if needed
568
570
  target = getPixelArray(target, sourceType, sourceFormat, sourceWidth, sourceHeight, sourceDepth);
@@ -570,13 +572,31 @@ export function readPixelsToArray(
570
572
  // Pixel array available, if necessary, deduce type from it.
571
573
  sourceType = sourceType || getGLTypeFromTypedArray(target);
572
574
 
573
- const prevHandle = gl.bindFramebuffer(GL.FRAMEBUFFER, handle);
575
+ // Note: luma.gl overrides bindFramebuffer so that we can reliably restore the previous framebuffer (this is the only function for which we do that)
576
+ const prevHandle = gl.bindFramebuffer(
577
+ GL.FRAMEBUFFER,
578
+ handle
579
+ ) as unknown as WebGLFramebuffer | null;
580
+
581
+ // Select the color attachment to read from
582
+ gl.readBuffer(gl.COLOR_ATTACHMENT0 + sourceAttachment);
583
+
584
+ // There is a lot of hedging in the WebGL2 spec about what formats are guaranteed to be readable
585
+ // (It should always be possible to read RGBA/UNSIGNED_BYTE, but most other combinations are not guaranteed)
586
+ // Querying is possible but expensive:
587
+ // const {device} = framebuffer;
588
+ // texture.glReadFormat ||= gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT);
589
+ // texture.glReadType ||= gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE);
590
+ // console.log('params', device.getGLKey(texture.glReadFormat), device.getGLKey(texture.glReadType));
591
+
574
592
  gl.readPixels(sourceX, sourceY, sourceWidth, sourceHeight, sourceFormat, sourceType, target);
575
- // @ts-expect-error
593
+ gl.readBuffer(gl.COLOR_ATTACHMENT0);
576
594
  gl.bindFramebuffer(GL.FRAMEBUFFER, prevHandle || null);
595
+
577
596
  if (deleteFramebuffer) {
578
597
  framebuffer.destroy();
579
598
  }
599
+
580
600
  return target;
581
601
  }
582
602
 
@@ -788,8 +808,8 @@ export function toFramebuffer(texture: Texture, props?: FramebufferProps): WEBGL
788
808
  // eslint-disable-next-line max-params
789
809
  function getPixelArray(
790
810
  pixelArray,
791
- type,
792
- format,
811
+ glType: GLDataType | GLPixelType,
812
+ glFormat: GL,
793
813
  width: number,
794
814
  height: number,
795
815
  depth?: number
@@ -797,10 +817,11 @@ function getPixelArray(
797
817
  if (pixelArray) {
798
818
  return pixelArray;
799
819
  }
820
+ // const formatInfo = decodeTextureFormat(format);
800
821
  // Allocate pixel array if not already available, using supplied type
801
- type = type || GL.UNSIGNED_BYTE;
802
- const ArrayType = getTypedArrayFromGLType(type, {clamped: false});
803
- const components = glFormatToComponents(format);
822
+ glType ||= GL.UNSIGNED_BYTE;
823
+ const ArrayType = getTypedArrayFromGLType(glType, {clamped: false});
824
+ const components = glFormatToComponents(glFormat);
804
825
  // TODO - check for composite type (components = 1).
805
826
  return new ArrayType(width * height * components) as Uint8Array | Uint16Array | Float32Array;
806
827
  }
@@ -7,9 +7,18 @@ import type {
7
7
  CopyBufferToTextureOptions,
8
8
  CopyTextureToBufferOptions,
9
9
  CopyTextureToTextureOptions
10
+ // ClearTextureOptions,
11
+ // ReadTextureOptions
10
12
  } from '@luma.gl/core';
11
13
  import {CommandBuffer, Texture, Framebuffer} from '@luma.gl/core';
12
- import {GL} from '@luma.gl/constants';
14
+ import {
15
+ GL,
16
+ GLTextureTarget,
17
+ GLTextureCubeMapTarget
18
+ // GLTexelDataFormat,
19
+ // GLPixelType,
20
+ // GLDataType
21
+ } from '@luma.gl/constants';
13
22
 
14
23
  import {WebGLDevice} from '../webgl-device';
15
24
  import {WEBGLBuffer} from './webgl-buffer';
@@ -37,11 +46,23 @@ type CopyTextureToTextureCommand = {
37
46
  options: CopyTextureToTextureOptions;
38
47
  };
39
48
 
49
+ type ClearTextureCommand = {
50
+ name: 'clear-texture';
51
+ options: {}; // ClearTextureOptions;
52
+ };
53
+
54
+ type ReadTextureCommand = {
55
+ name: 'read-texture';
56
+ options: {}; // ReadTextureOptions;
57
+ };
58
+
40
59
  type Command =
41
60
  | CopyBufferToBufferCommand
42
61
  | CopyBufferToTextureCommand
43
62
  | CopyTextureToBufferCommand
44
- | CopyTextureToTextureCommand;
63
+ | CopyTextureToTextureCommand
64
+ | ClearTextureCommand
65
+ | ReadTextureCommand;
45
66
 
46
67
  export class WEBGLCommandBuffer extends CommandBuffer {
47
68
  device: WebGLDevice;
@@ -67,6 +88,11 @@ export class WEBGLCommandBuffer extends CommandBuffer {
67
88
  case 'copy-texture-to-texture':
68
89
  _copyTextureToTexture(this.device, command.options);
69
90
  break;
91
+ // case 'clear-texture':
92
+ // _clearTexture(this.device, command.options);
93
+ // break;
94
+ default:
95
+ throw new Error(command.name);
70
96
  }
71
97
  }
72
98
  }
@@ -311,7 +337,82 @@ function _copyTextureToTexture(device: WebGLDevice, options: CopyTextureToTextur
311
337
  }
312
338
  }
313
339
 
314
- // Returns number of components in a specific readPixels WebGL format
340
+ /** Clear one mip level of a texture *
341
+ function _clearTexture(device: WebGLDevice, options: ClearTextureOptions) {
342
+ const BORDER = 0;
343
+ const {dimension, width, height, depth = 0, mipLevel = 0} = options;
344
+ const {glInternalFormat, glFormat, glType, compressed} = options;
345
+ const glTarget = getWebGLCubeFaceTarget(options.glTarget, dimension, depth);
346
+
347
+ switch (dimension) {
348
+ case '2d-array':
349
+ case '3d':
350
+ if (compressed) {
351
+ // prettier-ignore
352
+ device.gl.compressedTexImage3D(glTarget, mipLevel, glInternalFormat, width, height, depth, BORDER, null);
353
+ } else {
354
+ // prettier-ignore
355
+ device.gl.texImage3D( glTarget, mipLevel, glInternalFormat, width, height, depth, BORDER, glFormat, glType, null);
356
+ }
357
+ break;
358
+
359
+ case '2d':
360
+ case 'cube':
361
+ if (compressed) {
362
+ // prettier-ignore
363
+ device.gl.compressedTexImage2D(glTarget, mipLevel, glInternalFormat, width, height, BORDER, null);
364
+ } else {
365
+ // prettier-ignore
366
+ device.gl.texImage2D(glTarget, mipLevel, glInternalFormat, width, height, BORDER, glFormat, glType, null);
367
+ }
368
+ break;
369
+
370
+ default:
371
+ throw new Error(dimension);
372
+ }
373
+ }
374
+ */
375
+
376
+ // function _readTexture(device: WebGLDevice, options: CopyTextureToBufferOptions) {}
377
+
378
+ // HELPERS
379
+
380
+ /**
381
+ * In WebGL, cube maps specify faces by overriding target instead of using the depth parameter.
382
+ * @note We still bind the texture using GL.TEXTURE_CUBE_MAP, but we need to use the face-specific target when setting mip levels.
383
+ * @returns glTarget unchanged, if dimension !== 'cube'.
384
+ */
385
+ export function getWebGLCubeFaceTarget(
386
+ glTarget: GLTextureTarget,
387
+ dimension: '1d' | '2d' | '2d-array' | 'cube' | 'cube-array' | '3d',
388
+ level: number
389
+ ): GLTextureTarget | GLTextureCubeMapTarget {
390
+ return dimension === 'cube' ? GL.TEXTURE_CUBE_MAP_POSITIVE_X + level : glTarget;
391
+ }
392
+
393
+ /** Wrap a texture in a framebuffer so that we can use WebGL APIs that work on framebuffers */
394
+ function getFramebuffer(source: Texture | Framebuffer): {
395
+ framebuffer: WEBGLFramebuffer;
396
+ destroyFramebuffer: boolean;
397
+ } {
398
+ if (source instanceof Texture) {
399
+ const {width, height, id} = source;
400
+ const framebuffer = source.device.createFramebuffer({
401
+ id: `framebuffer-for-${id}`,
402
+ width,
403
+ height,
404
+ colorAttachments: [source]
405
+ }) as unknown as WEBGLFramebuffer;
406
+
407
+ return {framebuffer, destroyFramebuffer: true};
408
+ }
409
+ return {framebuffer: source as unknown as WEBGLFramebuffer, destroyFramebuffer: false};
410
+ }
411
+
412
+ /**
413
+ * Returns number of components in a specific readPixels WebGL format
414
+ * @todo use shadertypes utils instead?
415
+ */
315
416
  export function glFormatToComponents(format): 1 | 2 | 3 | 4 {
316
417
  switch (format) {
317
418
  case GL.ALPHA:
@@ -333,7 +434,10 @@ export function glFormatToComponents(format): 1 | 2 | 3 | 4 {
333
434
  }
334
435
  }
335
436
 
336
- // Return byte count for given readPixels WebGL type
437
+ /**
438
+ * Return byte count for given readPixels WebGL type
439
+ * @todo use shadertypes utils instead?
440
+ */
337
441
  export function glTypeToBytes(type: GL): 1 | 2 | 4 {
338
442
  switch (type) {
339
443
  case GL.UNSIGNED_BYTE:
@@ -349,23 +453,3 @@ export function glTypeToBytes(type: GL): 1 | 2 | 4 {
349
453
  throw new Error('GLType');
350
454
  }
351
455
  }
352
-
353
- // Helper methods
354
-
355
- function getFramebuffer(source: Texture | Framebuffer): {
356
- framebuffer: WEBGLFramebuffer;
357
- destroyFramebuffer: boolean;
358
- } {
359
- if (source instanceof Texture) {
360
- const {width, height, id} = source;
361
- const framebuffer = source.device.createFramebuffer({
362
- id: `framebuffer-for-${id}`,
363
- width,
364
- height,
365
- colorAttachments: [source]
366
- }) as unknown as WEBGLFramebuffer;
367
-
368
- return {framebuffer, destroyFramebuffer: true};
369
- }
370
- return {framebuffer: source as unknown as WEBGLFramebuffer, destroyFramebuffer: false};
371
- }
@@ -8,6 +8,8 @@ import type {
8
8
  CopyBufferToTextureOptions,
9
9
  CopyTextureToBufferOptions,
10
10
  CopyTextureToTextureOptions,
11
+ // ClearTextureOptions,
12
+ // ReadTextureOptions,
11
13
  QuerySet,
12
14
  Buffer
13
15
  } from '@luma.gl/core';
@@ -52,6 +54,10 @@ export class WEBGLCommandEncoder extends CommandEncoder {
52
54
  this.commandBuffer.commands.push({name: 'copy-texture-to-texture', options});
53
55
  }
54
56
 
57
+ // clearTexture(options: ClearTextureOptions): void {
58
+ // this.commandBuffer.commands.push({name: 'copy-texture-to-texture', options});
59
+ // }
60
+
55
61
  override pushDebugGroup(groupLabel: string): void {}
56
62
  override popDebugGroup() {}
57
63
 
@@ -72,6 +72,20 @@ export class WEBGLExternalTexture extends WEBGLTexture {
72
72
  data.addEventListener('loadeddata', () => this.initialize(props));
73
73
  return this;
74
74
  }
75
+ }
76
+
77
+ initialize() {
78
+ // TODO - Video handling, move to ExternalTexture?
79
+ // if (isVideo) {
80
+ // this._video = {
81
+ // video: data,
82
+ // // TODO - should we be using the sampler parameters here?
83
+ // parameters: {},
84
+ // // @ts-expect-error HTMLVideoElement.HAVE_CURRENT_DATA is not declared
85
+ // lastTime: data.readyState >= HTMLVideoElement.HAVE_CURRENT_DATA ? data.currentTime : -1
86
+ // };
87
+ // }
88
+ }
75
89
 
76
90
  update(): this {
77
91
  if (this._video) {
@@ -77,8 +77,7 @@ export class WEBGLFramebuffer extends Framebuffer {
77
77
  }
78
78
 
79
79
  /** Check the status */
80
- // @ts-expect-error
81
- if (this.props.check !== false) {
80
+ if (this.device.props.debug) {
82
81
  const status = this.gl.checkFramebufferStatus(GL.FRAMEBUFFER) as GL;
83
82
  if (status !== GL.FRAMEBUFFER_COMPLETE) {
84
83
  throw new Error(`Framebuffer ${_getFrameBufferStatus(status)}`);
@@ -10,12 +10,6 @@ import {withGLParameters} from '../../context/state-tracker/with-parameters';
10
10
  import {setGLParameters} from '../../context/parameters/unified-parameter-api';
11
11
  import {WEBGLQuerySet} from './webgl-query-set';
12
12
 
13
- // Should collapse during minification
14
- const GL_DEPTH_BUFFER_BIT = 0x00000100;
15
- const GL_STENCIL_BUFFER_BIT = 0x00000400;
16
- const GL_COLOR_BUFFER_BIT = 0x00004000;
17
-
18
- const GL_COLOR = 0x1800;
19
13
  const COLOR_CHANNELS = [0x1, 0x2, 0x4, 0x8]; // GPUColorWrite RED, GREEN, BLUE, ALPHA
20
14
 
21
15
  export class WEBGLRenderPass extends RenderPass {
@@ -46,6 +40,16 @@ export class WEBGLRenderPass extends RenderPass {
46
40
  this.device.pushState();
47
41
  this.setParameters({viewport, ...this.props.parameters});
48
42
 
43
+ // Specify mapping of draw buffer locations to color attachments
44
+ if (this.props.framebuffer) {
45
+ const drawBuffers = this.props.framebuffer.colorAttachments.map(
46
+ (_, i) => GL.COLOR_ATTACHMENT0 + i
47
+ );
48
+ this.device.gl.drawBuffers(drawBuffers);
49
+ } else {
50
+ this.device.gl.drawBuffers([GL.BACK]);
51
+ }
52
+
49
53
  // Hack - for now WebGL draws in "immediate mode" (instead of queueing the operations)...
50
54
  this.clear();
51
55
  }
@@ -134,21 +138,37 @@ export class WEBGLRenderPass extends RenderPass {
134
138
  * Optionally clears depth, color and stencil buffers based on parameters
135
139
  */
136
140
  protected clear(): void {
141
+ const DEFAULT_CLEAR_COLOR: [number, number, number, number] = [0, 0, 0, 1];
142
+ const DEFAULT_CLEAR_DEPTH = 1;
143
+ const DEFAULT_CLEAR_STENCIL = 0;
144
+
137
145
  const glParameters: GLParameters = {...this.glParameters};
138
146
 
139
147
  let clearMask = 0;
140
148
 
141
- if (this.props.clearColor !== false) {
142
- clearMask |= GL_COLOR_BUFFER_BIT;
143
- glParameters.clearColor = this.props.clearColor;
149
+ if (this.props.clearColors) {
150
+ this.props.clearColors.forEach((color, drawBufferIndex) => {
151
+ if (color) {
152
+ this.clearColorBuffer(drawBufferIndex, color);
153
+ }
154
+ });
155
+ }
156
+
157
+ if (this.props.clearColor !== false && this.props.clearColors === undefined) {
158
+ clearMask |= GL.COLOR_BUFFER_BIT;
159
+ const clearColor =
160
+ this.props.clearColor === true ? DEFAULT_CLEAR_COLOR : this.props.clearColor;
161
+ glParameters.clearColor = clearColor;
144
162
  }
145
163
  if (this.props.clearDepth !== false) {
146
- clearMask |= GL_DEPTH_BUFFER_BIT;
147
- glParameters.clearDepth = this.props.clearDepth;
164
+ clearMask |= GL.DEPTH_BUFFER_BIT;
165
+ glParameters.clearDepth =
166
+ this.props.clearDepth === true ? DEFAULT_CLEAR_DEPTH : this.props.clearDepth;
148
167
  }
149
168
  if (this.props.clearStencil !== false) {
150
- clearMask |= GL_STENCIL_BUFFER_BIT;
151
- glParameters.clearStencil = this.props.clearStencil;
169
+ clearMask |= GL.STENCIL_BUFFER_BIT;
170
+ glParameters.clearStencil =
171
+ this.props.clearStencil === true ? DEFAULT_CLEAR_STENCIL : this.props.clearStencil;
152
172
  }
153
173
 
154
174
  if (clearMask !== 0) {
@@ -156,11 +176,6 @@ export class WEBGLRenderPass extends RenderPass {
156
176
  withGLParameters(this.device.gl, glParameters, () => {
157
177
  this.device.gl.clear(clearMask);
158
178
  });
159
-
160
- // TODO - clear multiple color attachments
161
- // for (attachment of this.framebuffer.colorAttachments) {
162
- // this.clearColorBuffer
163
- // }
164
179
  }
165
180
  }
166
181
 
@@ -171,22 +186,28 @@ export class WEBGLRenderPass extends RenderPass {
171
186
  withGLParameters(this.device.gl, {framebuffer: this.props.framebuffer}, () => {
172
187
  // Method selection per OpenGL ES 3 docs
173
188
  switch (value.constructor) {
189
+ case Int8Array:
190
+ case Int16Array:
174
191
  case Int32Array:
175
- this.device.gl.clearBufferiv(GL_COLOR, drawBuffer, value);
192
+ this.device.gl.clearBufferiv(GL.COLOR, drawBuffer, value);
176
193
  break;
194
+ case Uint8Array:
195
+ case Uint8ClampedArray:
196
+ case Uint16Array:
177
197
  case Uint32Array:
178
- this.device.gl.clearBufferuiv(GL_COLOR, drawBuffer, value);
198
+ this.device.gl.clearBufferuiv(GL.COLOR, drawBuffer, value);
179
199
  break;
180
200
  case Float32Array:
181
- default:
182
- this.device.gl.clearBufferfv(GL_COLOR, drawBuffer, value);
201
+ this.device.gl.clearBufferfv(GL.COLOR, drawBuffer, value);
183
202
  break;
203
+ default:
204
+ throw new Error('clearColorBuffer: color must be typed array');
184
205
  }
185
206
  });
186
207
  }
187
208
 
188
209
  // clearDepthStencil() {
189
- // const GL_DEPTH = 0x1801;
210
+ // const GL.DEPTH = 0x1801;
190
211
  // const GL_STENCIL = 0x1802;
191
212
  // const GL_DEPTH_STENCIL = 0x84f9;
192
213
 
@@ -414,11 +414,12 @@ export class WEBGLRenderPipeline extends RenderPipeline {
414
414
  }
415
415
  }
416
416
 
417
- for (const [, texture] of Object.entries(this.bindings)) {
418
- if (texture instanceof WEBGLTexture) {
419
- texture.update();
420
- }
421
- }
417
+ // TODO - remove this should be handled by ExternalTexture
418
+ // for (const [, texture] of Object.entries(this.bindings)) {
419
+ // if (texture instanceof WEBGLTexture) {
420
+ // texture.update();
421
+ // }
422
+ // }
422
423
 
423
424
  return texturesRenderable;
424
425
  }
@@ -70,7 +70,7 @@ export class WEBGLShader extends Shader {
70
70
  gl.compileShader(this.handle);
71
71
 
72
72
  // For performance reasons, avoid checking shader compilation errors on production
73
- if (log.level === 0) {
73
+ if (!this.device.props.debug) {
74
74
  this.compilationStatus = 'pending';
75
75
  return;
76
76
  }