@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.
- package/dist/adapter/converters/sampler-parameters.js +6 -4
- package/dist/adapter/converters/texture-formats.d.ts +49 -11
- package/dist/adapter/converters/texture-formats.d.ts.map +1 -1
- package/dist/adapter/converters/texture-formats.js +150 -160
- package/dist/adapter/helpers/format-utils.d.ts.map +1 -1
- package/dist/adapter/helpers/format-utils.js +6 -0
- package/dist/adapter/helpers/webgl-texture-utils.d.ts +10 -8
- package/dist/adapter/helpers/webgl-texture-utils.d.ts.map +1 -1
- package/dist/adapter/helpers/webgl-texture-utils.js +46 -32
- package/dist/adapter/resources/webgl-command-buffer.d.ts +59 -2
- package/dist/adapter/resources/webgl-command-buffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-command-buffer.js +72 -16
- package/dist/adapter/resources/webgl-command-encoder.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-command-encoder.js +3 -0
- package/dist/adapter/resources/webgl-external-texture.js +14 -0
- package/dist/adapter/resources/webgl-framebuffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-framebuffer.js +1 -2
- package/dist/adapter/resources/webgl-render-pass.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-render-pass.js +38 -20
- package/dist/adapter/resources/webgl-render-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-render-pipeline.js +6 -5
- package/dist/adapter/resources/webgl-shader.js +1 -1
- package/dist/adapter/resources/webgl-texture.d.ts +8 -14
- package/dist/adapter/resources/webgl-texture.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-texture.js +119 -208
- package/dist/adapter/webgl-adapter.js +1 -1
- package/dist/adapter/webgl-device.d.ts +7 -1
- package/dist/adapter/webgl-device.d.ts.map +1 -1
- package/dist/adapter/webgl-device.js +22 -10
- package/dist/context/debug/webgl-developer-tools.d.ts +1 -0
- package/dist/context/debug/webgl-developer-tools.d.ts.map +1 -1
- package/dist/context/debug/webgl-developer-tools.js +4 -2
- package/dist/context/helpers/create-browser-context.d.ts.map +1 -1
- package/dist/context/helpers/create-browser-context.js +17 -3
- package/dist/dist.dev.js +226 -272
- package/dist/dist.min.js +2 -2
- package/dist/index.cjs +220 -269
- package/dist/index.cjs.map +3 -3
- package/package.json +4 -4
- package/src/adapter/converters/sampler-parameters.ts +6 -4
- package/src/adapter/converters/texture-formats.ts +171 -177
- package/src/adapter/helpers/format-utils.ts +6 -0
- package/src/adapter/helpers/webgl-texture-utils.ts +66 -45
- package/src/adapter/resources/webgl-command-buffer.ts +108 -24
- package/src/adapter/resources/webgl-command-encoder.ts +6 -0
- package/src/adapter/resources/webgl-external-texture.ts +14 -0
- package/src/adapter/resources/webgl-framebuffer.ts +1 -2
- package/src/adapter/resources/webgl-render-pass.ts +44 -23
- package/src/adapter/resources/webgl-render-pipeline.ts +6 -5
- package/src/adapter/resources/webgl-shader.ts +1 -1
- package/src/adapter/resources/webgl-texture.ts +126 -235
- package/src/adapter/webgl-adapter.ts +1 -1
- package/src/adapter/webgl-device.ts +23 -10
- package/src/context/debug/webgl-developer-tools.ts +5 -2
- 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
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|
-
|
|
150
|
-
|
|
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,
|
|
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,
|
|
293
|
+
gl.compressedTexImage3D(glTarget, mipLevel, glInternalFormat, width, height, depth, BORDER, null);
|
|
291
294
|
} else {
|
|
292
295
|
// prettier-ignore
|
|
293
|
-
gl.texImage3D( glTarget,
|
|
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,
|
|
304
|
+
gl.compressedTexImage2D(glTarget, mipLevel, glInternalFormat, width, height, BORDER, null);
|
|
302
305
|
} else {
|
|
303
306
|
// prettier-ignore
|
|
304
|
-
gl.texImage2D(glTarget,
|
|
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 =
|
|
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
|
-
|
|
557
|
-
|
|
558
|
-
|
|
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 ||=
|
|
565
|
+
sourceFormat ||= texture?.glFormat || GL.RGBA;
|
|
564
566
|
// Deduce the type from color attachment if not provided.
|
|
565
|
-
sourceType ||=
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
792
|
-
|
|
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
|
-
|
|
802
|
-
const ArrayType = getTypedArrayFromGLType(
|
|
803
|
-
const components = glFormatToComponents(
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
142
|
-
|
|
143
|
-
|
|
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 |=
|
|
147
|
-
glParameters.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 |=
|
|
151
|
-
glParameters.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(
|
|
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(
|
|
198
|
+
this.device.gl.clearBufferuiv(GL.COLOR, drawBuffer, value);
|
|
179
199
|
break;
|
|
180
200
|
case Float32Array:
|
|
181
|
-
|
|
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
|
|
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
|
-
|
|
418
|
-
|
|
419
|
-
|
|
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 (
|
|
73
|
+
if (!this.device.props.debug) {
|
|
74
74
|
this.compilationStatus = 'pending';
|
|
75
75
|
return;
|
|
76
76
|
}
|