@luma.gl/webgl 9.1.0-alpha.1 → 9.1.0-alpha.10

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 (82) hide show
  1. package/dist/adapter/converters/device-parameters.d.ts.map +1 -1
  2. package/dist/adapter/converters/device-parameters.js +18 -11
  3. package/dist/adapter/converters/texture-formats.d.ts +1 -1
  4. package/dist/adapter/converters/texture-formats.d.ts.map +1 -1
  5. package/dist/adapter/converters/texture-formats.js +9 -16
  6. package/dist/adapter/device-helpers/webgl-device-features.d.ts.map +1 -1
  7. package/dist/adapter/device-helpers/webgl-device-features.js +0 -1
  8. package/dist/adapter/helpers/webgl-texture-utils.d.ts +4 -4
  9. package/dist/adapter/helpers/webgl-texture-utils.d.ts.map +1 -1
  10. package/dist/adapter/helpers/webgl-texture-utils.js +11 -9
  11. package/dist/adapter/resources/webgl-framebuffer.js +1 -1
  12. package/dist/adapter/resources/webgl-render-pass.d.ts.map +1 -1
  13. package/dist/adapter/resources/webgl-render-pass.js +17 -4
  14. package/dist/adapter/resources/webgl-render-pipeline.d.ts.map +1 -1
  15. package/dist/adapter/resources/webgl-render-pipeline.js +1 -1
  16. package/dist/adapter/resources/webgl-shader.js +1 -1
  17. package/dist/adapter/resources/webgl-texture.d.ts +21 -3
  18. package/dist/adapter/resources/webgl-texture.d.ts.map +1 -1
  19. package/dist/adapter/resources/webgl-texture.js +23 -29
  20. package/dist/adapter/resources/webgl-transform-feedback.js +1 -1
  21. package/dist/adapter/resources/webgl-vertex-array.d.ts.map +1 -1
  22. package/dist/adapter/resources/webgl-vertex-array.js +3 -0
  23. package/dist/adapter/webgl-adapter.d.ts +21 -0
  24. package/dist/adapter/webgl-adapter.d.ts.map +1 -0
  25. package/dist/adapter/webgl-adapter.js +91 -0
  26. package/dist/adapter/webgl-device.d.ts +15 -27
  27. package/dist/adapter/webgl-device.d.ts.map +1 -1
  28. package/dist/adapter/webgl-device.js +32 -112
  29. package/dist/classic/copy-and-blit.d.ts +1 -0
  30. package/dist/classic/copy-and-blit.d.ts.map +1 -1
  31. package/dist/classic/copy-and-blit.js +11 -10
  32. package/dist/context/debug/spector-types.d.ts +1108 -0
  33. package/dist/context/debug/spector-types.d.ts.map +1 -0
  34. package/dist/context/debug/spector-types.js +697 -0
  35. package/dist/context/debug/spector.d.ts +12 -8
  36. package/dist/context/debug/spector.d.ts.map +1 -1
  37. package/dist/context/debug/spector.js +23 -17
  38. package/dist/context/polyfills/polyfill-webgl1-extensions.d.ts +9 -0
  39. package/dist/context/polyfills/polyfill-webgl1-extensions.d.ts.map +1 -0
  40. package/dist/context/polyfills/polyfill-webgl1-extensions.js +181 -0
  41. package/dist/context/state-tracker/webgl-state-tracker.d.ts +43 -0
  42. package/dist/context/state-tracker/webgl-state-tracker.d.ts.map +1 -0
  43. package/dist/context/state-tracker/{track-context-state.js → webgl-state-tracker.js} +44 -74
  44. package/dist/context/state-tracker/with-parameters.d.ts.map +1 -1
  45. package/dist/context/state-tracker/with-parameters.js +5 -4
  46. package/dist/dist.dev.js +352 -236
  47. package/dist/dist.min.js +2 -2
  48. package/dist/index.cjs +355 -238
  49. package/dist/index.cjs.map +4 -4
  50. package/dist/index.d.ts +3 -1
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +3 -2
  53. package/dist/utils/split-uniforms-and-bindings.d.ts +1 -1
  54. package/dist/utils/split-uniforms-and-bindings.d.ts.map +1 -1
  55. package/dist/utils/uid.d.ts +7 -0
  56. package/dist/utils/uid.d.ts.map +1 -0
  57. package/dist/utils/uid.js +14 -0
  58. package/package.json +3 -3
  59. package/src/adapter/converters/device-parameters.ts +18 -12
  60. package/src/adapter/converters/texture-formats.ts +12 -20
  61. package/src/adapter/device-helpers/webgl-device-features.ts +0 -1
  62. package/src/adapter/helpers/webgl-texture-utils.ts +12 -9
  63. package/src/adapter/resources/webgl-framebuffer.ts +1 -1
  64. package/src/adapter/resources/webgl-render-pass.ts +17 -4
  65. package/src/adapter/resources/webgl-render-pipeline.ts +2 -1
  66. package/src/adapter/resources/webgl-shader.ts +1 -1
  67. package/src/adapter/resources/webgl-texture.ts +42 -29
  68. package/src/adapter/resources/webgl-transform-feedback.ts +1 -1
  69. package/src/adapter/resources/webgl-vertex-array.ts +3 -0
  70. package/src/adapter/webgl-adapter.ts +113 -0
  71. package/src/adapter/webgl-device.ts +32 -135
  72. package/src/classic/copy-and-blit.ts +14 -9
  73. package/src/context/debug/spector-types.ts +1154 -0
  74. package/src/context/debug/spector.ts +38 -29
  75. package/src/context/polyfills/polyfill-webgl1-extensions.ts +202 -0
  76. package/src/context/state-tracker/{track-context-state.ts → webgl-state-tracker.ts} +55 -94
  77. package/src/context/state-tracker/with-parameters.ts +5 -4
  78. package/src/index.ts +5 -7
  79. package/src/utils/split-uniforms-and-bindings.ts +3 -3
  80. package/src/utils/uid.ts +16 -0
  81. package/dist/context/state-tracker/track-context-state.d.ts +0 -22
  82. package/dist/context/state-tracker/track-context-state.d.ts.map +0 -1
@@ -0,0 +1,113 @@
1
+ // luma.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ import {Adapter, Device, DeviceProps, CanvasContext, log} from '@luma.gl/core';
6
+ import {WebGLDevice} from './webgl-device';
7
+ import {enforceWebGL2} from '../context/polyfills/polyfill-webgl1-extensions';
8
+ import {loadSpectorJS, DEFAULT_SPECTOR_PROPS} from '../context/debug/spector';
9
+ import {loadWebGLDeveloperTools} from '../context/debug/webgl-developer-tools';
10
+
11
+ const LOG_LEVEL = 1;
12
+
13
+ export class WebGLAdapter extends Adapter {
14
+ /** type of device's created by this adapter */
15
+ readonly type: Device['type'] = 'webgl';
16
+
17
+ constructor() {
18
+ super();
19
+
20
+ // Add spector default props to device default props, so that runtime settings are observed
21
+ Device.defaultProps = {...Device.defaultProps, ...DEFAULT_SPECTOR_PROPS};
22
+
23
+ // @ts-ignore DEPRECATED For backwards compatibility luma.registerDevices
24
+ WebGLDevice.adapter = this;
25
+ }
26
+
27
+ /** Check if WebGL 2 is available */
28
+ isSupported(): boolean {
29
+ return typeof WebGL2RenderingContext !== 'undefined';
30
+ }
31
+
32
+ /** Force any created WebGL contexts to be WebGL2 contexts, polyfilled with WebGL1 extensions */
33
+ enforceWebGL2(enable: boolean): void {
34
+ enforceWebGL2(enable);
35
+ }
36
+
37
+ /**
38
+ * Get a device instance from a GL context
39
+ * Creates and instruments the device if not already created
40
+ * @param gl
41
+ * @returns
42
+ */
43
+ async attach(gl: Device | WebGL2RenderingContext): Promise<WebGLDevice> {
44
+ if (gl instanceof WebGLDevice) {
45
+ return gl;
46
+ }
47
+ // @ts-expect-error
48
+ if (gl?.device instanceof Device) {
49
+ // @ts-expect-error
50
+ return gl.device as WebGLDevice;
51
+ }
52
+ if (!isWebGL(gl)) {
53
+ throw new Error('Invalid WebGL2RenderingContext');
54
+ }
55
+ return new WebGLDevice({gl: gl as WebGL2RenderingContext});
56
+ }
57
+
58
+ async create(props: DeviceProps = {}): Promise<WebGLDevice> {
59
+ log.groupCollapsed(LOG_LEVEL, 'WebGLDevice created')();
60
+
61
+ const promises: Promise<unknown>[] = [];
62
+
63
+ // Load webgl and spector debug scripts from CDN if requested
64
+ if (props.debug) {
65
+ promises.push(loadWebGLDeveloperTools());
66
+ }
67
+
68
+ if (props.debugWithSpectorJS) {
69
+ promises.push(loadSpectorJS(props));
70
+ }
71
+
72
+ // Wait for page to load: if canvas is a string we need to query the DOM for the canvas element.
73
+ // We only wait when props.canvas is string to avoids setting the global page onload callback unless necessary.
74
+ if (typeof props.canvas === 'string') {
75
+ promises.push(CanvasContext.pageLoaded);
76
+ }
77
+
78
+ // Wait for all the loads to settle before creating the context.
79
+ // The Device.create() functions are async, so in contrast to the constructor, we can `await` here.
80
+ const results = await Promise.allSettled(promises);
81
+ for (const result of results) {
82
+ if (result.status === 'rejected') {
83
+ log.error(`Failed to initialize debug libraries ${result.reason}`)();
84
+ }
85
+ }
86
+
87
+ log.probe(LOG_LEVEL + 1, 'DOM is loaded')();
88
+
89
+ const device = new WebGLDevice(props);
90
+
91
+ // Log some debug info about the newly created context
92
+ const message = `\
93
+ Created ${device.type}${device.debug ? ' debug' : ''} context: \
94
+ ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContext.id}`;
95
+ log.probe(LOG_LEVEL, message)();
96
+ log.table(LOG_LEVEL, device.info)();
97
+
98
+ log.groupEnd(LOG_LEVEL)();
99
+
100
+ return device;
101
+ }
102
+ }
103
+
104
+ /** Check if supplied parameter is a WebGL2RenderingContext */
105
+ function isWebGL(gl: any): boolean {
106
+ if (typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext) {
107
+ return true;
108
+ }
109
+ // Look for debug contexts, headless gl etc
110
+ return Boolean(gl && Number.isFinite(gl._version));
111
+ }
112
+
113
+ export const webgl2Adapter = new WebGLAdapter();
@@ -7,23 +7,21 @@ import type {DeviceProps, DeviceInfo, CanvasContextProps, TextureFormat} from '@
7
7
  import type {Buffer, Texture, Framebuffer, VertexArray, VertexArrayProps} from '@luma.gl/core';
8
8
  import {Device, CanvasContext, log} from '@luma.gl/core';
9
9
  import type {GLExtensions} from '@luma.gl/constants';
10
- import {
11
- popContextState,
12
- pushContextState,
13
- trackContextState
14
- } from '../context/state-tracker/track-context-state';
10
+ import {WebGLStateTracker} from '../context/state-tracker/webgl-state-tracker';
15
11
  import {createBrowserContext} from '../context/helpers/create-browser-context';
16
12
  import {getDeviceInfo} from './device-helpers/webgl-device-info';
17
13
  import {WebGLDeviceFeatures} from './device-helpers/webgl-device-features';
18
14
  import {WebGLDeviceLimits} from './device-helpers/webgl-device-limits';
19
15
  import {WebGLCanvasContext} from './webgl-canvas-context';
20
- import {loadSpectorJS, initializeSpectorJS} from '../context/debug/spector';
21
- import {loadWebGLDeveloperTools, makeDebugContext} from '../context/debug/webgl-developer-tools';
16
+ import type {Spector} from '../context/debug/spector-types';
17
+ import {initializeSpectorJS} from '../context/debug/spector';
18
+ import {makeDebugContext} from '../context/debug/webgl-developer-tools';
22
19
  import {
23
20
  isTextureFormatSupported,
24
21
  isTextureFormatRenderable,
25
22
  isTextureFormatFilterable
26
23
  } from './converters/texture-formats';
24
+ import {uid} from '../utils/uid';
27
25
 
28
26
  // WebGL classes
29
27
  import type {
@@ -71,17 +69,12 @@ import {withGLParameters} from '../context/state-tracker/with-parameters';
71
69
  import {clear} from '../classic/clear';
72
70
  import {getWebGLExtension} from '../context/helpers/webgl-extensions';
73
71
 
74
- const LOG_LEVEL = 1;
75
-
76
72
  /** WebGPU style Device API for a WebGL context */
77
73
  export class WebGLDevice extends Device {
78
74
  //
79
75
  // Public `Device` API
80
76
  //
81
77
 
82
- /** type of this device */
83
- static readonly type: string = 'webgl';
84
-
85
78
  /** type of this device */
86
79
  readonly type = 'webgl';
87
80
 
@@ -97,93 +90,26 @@ export class WebGLDevice extends Device {
97
90
 
98
91
  private _resolveContextLost?: (value: {reason: 'destroyed'; message: string}) => void;
99
92
 
100
- //
101
- // Static methods, expected to be present by `luma.createDevice()`
102
- //
103
-
104
- /** Check if WebGL 2 is available */
105
- static isSupported(): boolean {
106
- return typeof WebGL2RenderingContext !== 'undefined';
107
- }
108
-
109
- /**
110
- * Get a device instance from a GL context
111
- * Creates and instruments the device if not already created
112
- * @param gl
113
- * @returns
114
- */
115
- static attach(gl: Device | WebGL2RenderingContext): WebGLDevice {
116
- if (gl instanceof WebGLDevice) {
117
- return gl;
118
- }
119
- // @ts-expect-error
120
- if (gl?.device instanceof Device) {
121
- // @ts-expect-error
122
- return gl.device as WebGLDevice;
123
- }
124
- if (!isWebGL(gl)) {
125
- throw new Error('Invalid WebGL2RenderingContext');
126
- }
127
- return new WebGLDevice({gl: gl as WebGL2RenderingContext});
128
- }
129
-
130
- static async create(props: DeviceProps = {}): Promise<WebGLDevice> {
131
- log.groupCollapsed(LOG_LEVEL, 'WebGLDevice created')();
132
-
133
- const promises: Promise<unknown>[] = [];
134
-
135
- // Load webgl and spector debug scripts from CDN if requested
136
- if (props.debug) {
137
- promises.push(loadWebGLDeveloperTools());
138
- }
139
-
140
- if (props.spector) {
141
- promises.push(loadSpectorJS());
142
- }
143
-
144
- // Wait for page to load: if canvas is a string we need to query the DOM for the canvas element.
145
- // We only wait when props.canvas is string to avoids setting the global page onload callback unless necessary.
146
- if (typeof props.canvas === 'string') {
147
- promises.push(CanvasContext.pageLoaded);
148
- }
149
-
150
- // Wait for all the loads to settle before creating the context.
151
- // The Device.create() functions are async, so in contrast to the constructor, we can `await` here.
152
- const results = await Promise.allSettled(promises);
153
- for (const result of results) {
154
- if (result.status === 'rejected') {
155
- log.error(`Failed to initialize debug libraries ${result.reason}`)();
156
- }
157
- }
158
-
159
- log.probe(LOG_LEVEL + 1, 'DOM is loaded')();
160
-
161
- // @ts-expect-error
162
- if (props.gl?.device) {
163
- log.warn('reattaching existing device')();
164
- return WebGLDevice.attach(props.gl);
165
- }
166
-
167
- const device = new WebGLDevice(props);
93
+ /** WebGL2 context. */
94
+ readonly gl: WebGL2RenderingContext;
95
+ readonly debug: boolean = false;
168
96
 
169
- // Log some debug info about the newly created context
170
- const message = `\
171
- Created ${device.type}${device.debug ? ' debug' : ''} context: \
172
- ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContext.id}`;
173
- log.probe(LOG_LEVEL, message)();
174
- log.table(LOG_LEVEL, device.info)();
97
+ /** State used by luma.gl classes: TODO - move to canvasContext*/
98
+ readonly _canvasSizeInfo = {clientWidth: 0, clientHeight: 0, devicePixelRatio: 1};
175
99
 
176
- log.groupEnd(LOG_LEVEL)();
100
+ /** State used by luma.gl classes - TODO - not used? */
101
+ readonly _extensions: GLExtensions = {};
102
+ _polyfilled: boolean = false;
177
103
 
178
- return device;
179
- }
104
+ /** Instance of Spector.js (if initialized) */
105
+ spectorJS: Spector;
180
106
 
181
107
  //
182
108
  // Public API
183
109
  //
184
110
 
185
111
  constructor(props: DeviceProps) {
186
- super({...props, id: props.id || 'webgl-device'});
112
+ super({...props, id: props.id || uid('webgl-device')});
187
113
 
188
114
  // If attaching to an already attached context, return the attached device
189
115
  // @ts-expect-error device is attached to context
@@ -200,8 +126,7 @@ ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContex
200
126
  this._resolveContextLost = resolve;
201
127
  });
202
128
 
203
- let gl: WebGL2RenderingContext | null = props.gl || null;
204
- gl ||= createBrowserContext(this.canvasContext.canvas, {
129
+ this.handle = createBrowserContext(this.canvasContext.canvas, {
205
130
  ...props,
206
131
  onContextLost: (event: Event) =>
207
132
  this._resolveContextLost?.({
@@ -209,18 +134,22 @@ ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContex
209
134
  message: 'Entered sleep mode, or too many apps or browser tabs are using the GPU.'
210
135
  })
211
136
  });
137
+ this.gl = this.handle;
212
138
 
213
- if (!gl) {
139
+ if (!this.handle) {
214
140
  throw new Error('WebGL context creation failed');
215
141
  }
216
142
 
217
- this.handle = gl;
218
- this.gl = gl;
143
+ // Add spector debug instrumentation to context
144
+ // We need to trust spector integration to decide if spector should be initialized
145
+ // We also run spector instrumentation first, otherwise spector can clobber luma instrumentation.
146
+ this.spectorJS = initializeSpectorJS({...this.props, gl: this.handle});
219
147
 
148
+ // Instrument context
220
149
  (this.gl as any).device = this; // Update GL context: Link webgl context back to device
221
150
  (this.gl as any)._version = 2; // Update GL context: Store WebGL version field on gl context (HACK to identify debug contexts)
222
151
 
223
- // luma Device fields
152
+ // initialize luma Device fields
224
153
  this.info = getDeviceInfo(this.gl, this._extensions);
225
154
  this.limits = new WebGLDeviceLimits(this.gl);
226
155
  this.features = new WebGLDeviceFeatures(this.gl, this._extensions, this.props.disabledFeatures);
@@ -231,25 +160,18 @@ ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContex
231
160
  this.canvasContext.resize();
232
161
 
233
162
  // Install context state tracking
234
- // @ts-expect-error - hidden parameters
235
- const {enable = true, copyState = false} = props;
236
- trackContextState(this.gl, {
237
- enable,
238
- copyState,
163
+ const glState = new WebGLStateTracker(this.gl, {
239
164
  log: (...args: any[]) => log.log(1, ...args)()
240
165
  });
166
+ glState.trackState(this.gl, {copyState: false});
241
167
 
242
- // DEBUG contexts: Add debug instrumentation to the context, force log level to at least 1
168
+ // DEBUG contexts: Add luma debug instrumentation to the context, force log level to at least 1
243
169
  if (props.debug) {
244
170
  this.gl = makeDebugContext(this.gl, {...props, throwOnError: true});
245
171
  this.debug = true;
246
172
  log.level = Math.max(log.level, 1);
247
173
  log.warn('WebGL debug mode activated. Performance reduced.')();
248
174
  }
249
-
250
- if (props.spector) {
251
- this.spectorJS = initializeSpectorJS({...this.props, canvas: this.handle.canvas});
252
- }
253
175
  }
254
176
 
255
177
  /**
@@ -262,10 +184,6 @@ ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContex
262
184
  return this.gl.isContextLost();
263
185
  }
264
186
 
265
- getSize(): [number, number] {
266
- return [this.gl.drawingBufferWidth, this.gl.drawingBufferHeight];
267
- }
268
-
269
187
  isTextureFormatSupported(format: TextureFormat): boolean {
270
188
  return isTextureFormatSupported(this.gl, format, this._extensions);
271
189
  }
@@ -425,20 +343,6 @@ ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContex
425
343
  // WebGL-only API (not part of `Device` API)
426
344
  //
427
345
 
428
- /** WebGL2 context. */
429
- readonly gl: WebGL2RenderingContext;
430
- readonly debug: boolean = false;
431
-
432
- /** State used by luma.gl classes: TODO - move to canvasContext*/
433
- readonly _canvasSizeInfo = {clientWidth: 0, clientHeight: 0, devicePixelRatio: 1};
434
-
435
- /** State used by luma.gl classes - TODO - not used? */
436
- readonly _extensions: GLExtensions = {};
437
- _polyfilled: boolean = false;
438
-
439
- /** Instance of Spector.js (if initialized) */
440
- spectorJS: unknown;
441
-
442
346
  /**
443
347
  * Triggers device (or WebGL context) loss.
444
348
  * @note primarily intended for testing how application reacts to device loss
@@ -461,12 +365,14 @@ ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContex
461
365
 
462
366
  /** Save current WebGL context state onto an internal stack */
463
367
  pushState(): void {
464
- pushContextState(this.gl);
368
+ const webglState = WebGLStateTracker.get(this.gl);
369
+ webglState.push();
465
370
  }
466
371
 
467
372
  /** Restores previously saved context state */
468
373
  popState(): void {
469
- popContextState(this.gl);
374
+ const webglState = WebGLStateTracker.get(this.gl);
375
+ webglState.pop();
470
376
  }
471
377
 
472
378
  /**
@@ -541,15 +447,6 @@ ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContex
541
447
  }
542
448
  }
543
449
 
544
- /** Check if supplied parameter is a WebGL2RenderingContext */
545
- function isWebGL(gl: any): boolean {
546
- if (typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext) {
547
- return true;
548
- }
549
- // Look for debug contexts, headless gl etc
550
- return Boolean(gl && Number.isFinite(gl._version));
551
- }
552
-
553
450
  /** Set constant float array attribute */
554
451
  function setConstantFloatArray(device: WebGLDevice, location: number, array: Float32Array): void {
555
452
  switch (array.length) {
@@ -33,13 +33,13 @@ export function readPixelsToArray(
33
33
  // following parameters are auto deduced if not provided
34
34
  sourceWidth?: number;
35
35
  sourceHeight?: number;
36
+ sourceDepth?: number;
36
37
  sourceType?: number;
37
38
  }
38
39
  ): Uint8Array | Uint16Array | Float32Array {
39
40
  const {
40
41
  sourceX = 0,
41
42
  sourceY = 0,
42
- sourceFormat = GL.RGBA,
43
43
  sourceAttachment = GL.COLOR_ATTACHMENT0 // TODO - support gl.readBuffer
44
44
  } = options || {};
45
45
  let {
@@ -47,29 +47,32 @@ export function readPixelsToArray(
47
47
  // following parameters are auto deduced if not provided
48
48
  sourceWidth,
49
49
  sourceHeight,
50
+ sourceDepth,
51
+ sourceFormat,
50
52
  sourceType
51
53
  } = options || {};
52
54
 
53
55
  const {framebuffer, deleteFramebuffer} = getFramebuffer(source);
54
56
  // assert(framebuffer);
55
57
  const {gl, handle} = framebuffer;
56
- sourceWidth = sourceWidth || framebuffer.width;
57
- sourceHeight = sourceHeight || framebuffer.height;
58
+ const attachment = sourceAttachment - GL.COLOR_ATTACHMENT0;
59
+
60
+ sourceWidth ||= framebuffer.width;
61
+ sourceHeight ||= framebuffer.height;
58
62
 
59
63
  // TODO - Set and unset gl.readBuffer
60
64
  // if (sourceAttachment === GL.COLOR_ATTACHMENT0 && handle === null) {
61
65
  // sourceAttachment = GL.FRONT;
62
66
  // }
63
67
 
64
- const attachment = sourceAttachment - GL.COLOR_ATTACHMENT0;
65
- // assert(attachments[sourceAttachment]);
68
+ sourceDepth = framebuffer.colorAttachments[attachment]?.texture?.depth || 1;
66
69
 
70
+ sourceFormat ||= framebuffer.colorAttachments[attachment]?.texture?.glFormat || GL.RGBA;
67
71
  // Deduce the type from color attachment if not provided.
68
- sourceType =
69
- sourceType || framebuffer.colorAttachments[attachment]?.texture?.glType || GL.UNSIGNED_BYTE;
72
+ sourceType ||= framebuffer.colorAttachments[attachment]?.texture?.glType || GL.UNSIGNED_BYTE;
70
73
 
71
74
  // Deduce type and allocated pixelArray if needed
72
- target = getPixelArray(target, sourceType, sourceFormat, sourceWidth, sourceHeight);
75
+ target = getPixelArray(target, sourceType, sourceFormat, sourceWidth, sourceHeight, sourceDepth);
73
76
 
74
77
  // Pixel array available, if necessary, deduce type from it.
75
78
  sourceType = sourceType || getGLTypeFromTypedArray(target);
@@ -299,12 +302,14 @@ export function toFramebuffer(texture: Texture, props?: FramebufferProps): WEBGL
299
302
  return framebuffer as WEBGLFramebuffer;
300
303
  }
301
304
 
305
+ // eslint-disable-next-line max-params
302
306
  function getPixelArray(
303
307
  pixelArray,
304
308
  type,
305
309
  format,
306
310
  width: number,
307
- height: number
311
+ height: number,
312
+ depth?: number
308
313
  ): Uint8Array | Uint16Array | Float32Array {
309
314
  if (pixelArray) {
310
315
  return pixelArray;