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

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 +29 -17
  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 +219 -269
  36. package/dist/dist.min.js +2 -2
  37. package/dist/index.cjs +213 -266
  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 +33 -20
  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
  }
@@ -138,16 +142,24 @@ export class WEBGLRenderPass extends RenderPass {
138
142
 
139
143
  let clearMask = 0;
140
144
 
141
- if (this.props.clearColor !== false) {
142
- clearMask |= GL_COLOR_BUFFER_BIT;
145
+ if (this.props.clearColors) {
146
+ this.props.clearColors.forEach((color, drawBufferIndex) => {
147
+ if (color) {
148
+ this.clearColorBuffer(drawBufferIndex, color);
149
+ }
150
+ });
151
+ }
152
+
153
+ if (this.props.clearColor !== false && this.props.clearColors === undefined) {
154
+ clearMask |= GL.COLOR_BUFFER_BIT;
143
155
  glParameters.clearColor = this.props.clearColor;
144
156
  }
145
157
  if (this.props.clearDepth !== false) {
146
- clearMask |= GL_DEPTH_BUFFER_BIT;
158
+ clearMask |= GL.DEPTH_BUFFER_BIT;
147
159
  glParameters.clearDepth = this.props.clearDepth;
148
160
  }
149
161
  if (this.props.clearStencil !== false) {
150
- clearMask |= GL_STENCIL_BUFFER_BIT;
162
+ clearMask |= GL.STENCIL_BUFFER_BIT;
151
163
  glParameters.clearStencil = this.props.clearStencil;
152
164
  }
153
165
 
@@ -156,11 +168,6 @@ export class WEBGLRenderPass extends RenderPass {
156
168
  withGLParameters(this.device.gl, glParameters, () => {
157
169
  this.device.gl.clear(clearMask);
158
170
  });
159
-
160
- // TODO - clear multiple color attachments
161
- // for (attachment of this.framebuffer.colorAttachments) {
162
- // this.clearColorBuffer
163
- // }
164
171
  }
165
172
  }
166
173
 
@@ -171,22 +178,28 @@ export class WEBGLRenderPass extends RenderPass {
171
178
  withGLParameters(this.device.gl, {framebuffer: this.props.framebuffer}, () => {
172
179
  // Method selection per OpenGL ES 3 docs
173
180
  switch (value.constructor) {
181
+ case Int8Array:
182
+ case Int16Array:
174
183
  case Int32Array:
175
- this.device.gl.clearBufferiv(GL_COLOR, drawBuffer, value);
184
+ this.device.gl.clearBufferiv(GL.COLOR, drawBuffer, value);
176
185
  break;
186
+ case Uint8Array:
187
+ case Uint8ClampedArray:
188
+ case Uint16Array:
177
189
  case Uint32Array:
178
- this.device.gl.clearBufferuiv(GL_COLOR, drawBuffer, value);
190
+ this.device.gl.clearBufferuiv(GL.COLOR, drawBuffer, value);
179
191
  break;
180
192
  case Float32Array:
181
- default:
182
- this.device.gl.clearBufferfv(GL_COLOR, drawBuffer, value);
193
+ this.device.gl.clearBufferfv(GL.COLOR, drawBuffer, value);
183
194
  break;
195
+ default:
196
+ throw new Error('clearColorBuffer: color must be typed array');
184
197
  }
185
198
  });
186
199
  }
187
200
 
188
201
  // clearDepthStencil() {
189
- // const GL_DEPTH = 0x1801;
202
+ // const GL.DEPTH = 0x1801;
190
203
  // const GL_STENCIL = 0x1802;
191
204
  // const GL_DEPTH_STENCIL = 0x84f9;
192
205
 
@@ -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
  }