@luma.gl/webgl 9.0.17 → 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.
- package/dist/adapter/converters/device-parameters.d.ts.map +1 -1
- package/dist/adapter/converters/device-parameters.js +30 -12
- package/dist/adapter/converters/texture-formats.d.ts +22 -16
- package/dist/adapter/converters/texture-formats.d.ts.map +1 -1
- package/dist/adapter/converters/texture-formats.js +39 -47
- package/dist/adapter/device-helpers/webgl-device-features.d.ts.map +1 -1
- package/dist/adapter/device-helpers/webgl-device-features.js +1 -2
- package/dist/adapter/device-helpers/webgl-device-limits.js +1 -1
- package/dist/adapter/helpers/webgl-texture-utils.d.ts +300 -0
- package/dist/adapter/helpers/webgl-texture-utils.d.ts.map +1 -0
- package/dist/adapter/helpers/webgl-texture-utils.js +370 -0
- package/dist/adapter/helpers/webgl-topology-utils.d.ts.map +1 -1
- package/dist/adapter/helpers/webgl-topology-utils.js +0 -4
- package/dist/adapter/resources/webgl-buffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-buffer.js +2 -2
- package/dist/adapter/resources/webgl-command-buffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-command-buffer.js +6 -9
- package/dist/adapter/resources/webgl-framebuffer.d.ts +32 -5
- package/dist/adapter/resources/webgl-framebuffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-framebuffer.js +42 -60
- package/dist/adapter/resources/webgl-render-pass.d.ts +3 -2
- package/dist/adapter/resources/webgl-render-pass.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-render-pass.js +18 -7
- package/dist/adapter/resources/webgl-render-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-render-pipeline.js +46 -21
- package/dist/adapter/resources/webgl-shader.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-shader.js +3 -3
- package/dist/adapter/resources/webgl-texture-view.d.ts +1 -1
- package/dist/adapter/resources/webgl-texture-view.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-texture-view.js +1 -1
- package/dist/adapter/resources/webgl-texture.d.ts +76 -172
- package/dist/adapter/resources/webgl-texture.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-texture.js +397 -511
- package/dist/adapter/resources/webgl-vertex-array.d.ts +3 -2
- package/dist/adapter/resources/webgl-vertex-array.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-vertex-array.js +2 -2
- package/dist/adapter/webgl-adapter.d.ts +21 -0
- package/dist/adapter/webgl-adapter.d.ts.map +1 -0
- package/dist/adapter/webgl-adapter.js +91 -0
- package/dist/adapter/webgl-canvas-context.d.ts +3 -1
- package/dist/adapter/webgl-canvas-context.d.ts.map +1 -1
- package/dist/adapter/webgl-canvas-context.js +2 -0
- package/dist/adapter/webgl-device.d.ts +19 -30
- package/dist/adapter/webgl-device.d.ts.map +1 -1
- package/dist/adapter/webgl-device.js +35 -114
- package/dist/classic/accessor.d.ts +22 -1
- package/dist/classic/accessor.d.ts.map +1 -1
- package/dist/classic/accessor.js +1 -9
- package/dist/classic/clear.d.ts.map +1 -1
- package/dist/classic/clear.js +2 -5
- package/dist/classic/copy-and-blit.d.ts +3 -1
- package/dist/classic/copy-and-blit.d.ts.map +1 -1
- package/dist/classic/copy-and-blit.js +21 -18
- package/dist/classic/format-utils.d.ts.map +1 -1
- package/dist/classic/format-utils.js +0 -3
- package/dist/classic/typed-array-utils.d.ts +1 -1
- package/dist/classic/typed-array-utils.d.ts.map +1 -1
- package/dist/context/debug/spector-types.d.ts +1108 -0
- package/dist/context/debug/spector-types.d.ts.map +1 -0
- package/dist/context/debug/spector-types.js +697 -0
- package/dist/context/debug/spector.d.ts +12 -8
- package/dist/context/debug/spector.d.ts.map +1 -1
- package/dist/context/debug/spector.js +25 -18
- package/dist/context/debug/webgl-developer-tools.d.ts +1 -1
- package/dist/context/debug/webgl-developer-tools.d.ts.map +1 -1
- package/dist/context/debug/webgl-developer-tools.js +2 -5
- package/dist/context/parameters/webgl-parameter-tables.js +1 -1
- package/dist/context/polyfills/polyfill-webgl1-extensions.d.ts +9 -0
- package/dist/context/polyfills/polyfill-webgl1-extensions.d.ts.map +1 -0
- package/dist/context/polyfills/polyfill-webgl1-extensions.js +181 -0
- package/dist/context/state-tracker/webgl-state-tracker.d.ts +43 -0
- package/dist/context/state-tracker/webgl-state-tracker.d.ts.map +1 -0
- package/dist/context/state-tracker/{track-context-state.js → webgl-state-tracker.js} +46 -77
- package/dist/context/state-tracker/with-parameters.d.ts.map +1 -1
- package/dist/context/state-tracker/with-parameters.js +5 -4
- package/dist/dist.dev.js +1112 -1380
- package/dist/dist.min.js +2 -2
- package/dist/index.cjs +1122 -1284
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +3 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -5
- package/dist/utils/fill-array.d.ts +8 -0
- package/dist/utils/fill-array.d.ts.map +1 -0
- package/dist/utils/fill-array.js +26 -0
- package/dist/utils/load-script.d.ts +8 -0
- package/dist/utils/load-script.d.ts.map +1 -0
- package/dist/utils/load-script.js +26 -0
- package/dist/utils/split-uniforms-and-bindings.d.ts +9 -0
- package/dist/utils/split-uniforms-and-bindings.d.ts.map +1 -0
- package/dist/utils/split-uniforms-and-bindings.js +20 -0
- package/dist/utils/uid.d.ts +7 -0
- package/dist/utils/uid.d.ts.map +1 -0
- package/dist/utils/uid.js +14 -0
- package/package.json +6 -5
- package/src/adapter/converters/device-parameters.ts +31 -13
- package/src/adapter/converters/texture-formats.ts +51 -56
- package/src/adapter/device-helpers/webgl-device-features.ts +1 -2
- package/src/adapter/device-helpers/webgl-device-limits.ts +1 -1
- package/src/adapter/helpers/webgl-texture-utils.ts +484 -0
- package/src/adapter/helpers/webgl-topology-utils.ts +0 -4
- package/src/adapter/resources/webgl-buffer.ts +2 -2
- package/src/adapter/resources/webgl-command-buffer.ts +8 -10
- package/src/adapter/resources/webgl-framebuffer.ts +22 -56
- package/src/adapter/resources/webgl-render-pass.ts +21 -9
- package/src/adapter/resources/webgl-render-pipeline.ts +50 -24
- package/src/adapter/resources/webgl-shader.ts +4 -4
- package/src/adapter/resources/webgl-texture-view.ts +1 -3
- package/src/adapter/resources/webgl-texture.ts +445 -784
- package/src/adapter/resources/webgl-vertex-array.ts +8 -7
- package/src/adapter/webgl-adapter.ts +113 -0
- package/src/adapter/webgl-canvas-context.ts +4 -1
- package/src/adapter/webgl-device.ts +40 -151
- package/src/classic/accessor.ts +31 -11
- package/src/classic/clear.ts +3 -6
- package/src/classic/copy-and-blit.ts +32 -27
- package/src/classic/format-utils.ts +0 -3
- package/src/classic/typed-array-utils.ts +1 -1
- package/src/context/debug/spector-types.ts +1154 -0
- package/src/context/debug/spector.ts +40 -30
- package/src/context/debug/webgl-developer-tools.ts +3 -7
- package/src/context/parameters/webgl-parameter-tables.ts +3 -3
- package/src/context/polyfills/polyfill-webgl1-extensions.ts +202 -0
- package/src/context/state-tracker/{track-context-state.ts → webgl-state-tracker.ts} +57 -97
- package/src/context/state-tracker/with-parameters.ts +5 -4
- package/src/index.ts +5 -13
- package/src/utils/fill-array.ts +35 -0
- package/src/utils/load-script.ts +30 -0
- package/src/utils/split-uniforms-and-bindings.ts +31 -0
- package/src/utils/uid.ts +16 -0
- package/dist/adapter/objects/constants-to-keys.d.ts +0 -3
- package/dist/adapter/objects/constants-to-keys.d.ts.map +0 -1
- package/dist/adapter/objects/constants-to-keys.js +0 -22
- package/dist/adapter/objects/webgl-renderbuffer.d.ts +0 -43
- package/dist/adapter/objects/webgl-renderbuffer.d.ts.map +0 -1
- package/dist/adapter/objects/webgl-renderbuffer.js +0 -95
- package/dist/adapter/objects/webgl-resource.d.ts +0 -32
- package/dist/adapter/objects/webgl-resource.d.ts.map +0 -1
- package/dist/adapter/objects/webgl-resource.js +0 -114
- package/dist/context/state-tracker/track-context-state.d.ts +0 -22
- package/dist/context/state-tracker/track-context-state.d.ts.map +0 -1
- package/src/adapter/objects/constants-to-keys.ts +0 -27
- package/src/adapter/objects/webgl-renderbuffer.ts +0 -132
- package/src/adapter/objects/webgl-resource.ts +0 -183
|
@@ -2,355 +2,256 @@
|
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// - [ ]
|
|
5
|
+
// @todo texture refactor
|
|
6
|
+
// - [ ] cube texture init params P1
|
|
7
|
+
// - [ ] 3d texture init params P1
|
|
8
|
+
// - [ ] GPU memory tracking
|
|
9
|
+
// - [ ] raw data inputs
|
|
8
10
|
// - [ ] video (external) textures
|
|
9
11
|
|
|
10
|
-
import {
|
|
12
|
+
// import {TypedArray} from '@math.gl/types';
|
|
13
|
+
import type {
|
|
11
14
|
Device,
|
|
12
15
|
TextureProps,
|
|
13
16
|
TextureViewProps,
|
|
14
17
|
Sampler,
|
|
15
18
|
SamplerProps,
|
|
16
19
|
SamplerParameters,
|
|
17
|
-
|
|
20
|
+
// TextureFormat,
|
|
21
|
+
TextureCubeFace,
|
|
22
|
+
ExternalImage,
|
|
23
|
+
TextureLevelData,
|
|
24
|
+
Texture1DData,
|
|
25
|
+
Texture2DData,
|
|
26
|
+
Texture3DData,
|
|
27
|
+
TextureCubeData,
|
|
28
|
+
TextureArrayData,
|
|
29
|
+
TextureCubeArrayData
|
|
18
30
|
} from '@luma.gl/core';
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
31
|
+
// import {decodeTextureFormat} from '@luma.gl/core';
|
|
32
|
+
// import {Buffer, Texture, log} from '@luma.gl/core';
|
|
33
|
+
import {Texture, log} from '@luma.gl/core';
|
|
22
34
|
import {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
35
|
+
GL,
|
|
36
|
+
GLPixelType,
|
|
37
|
+
GLSamplerParameters,
|
|
38
|
+
GLTexelDataFormat,
|
|
39
|
+
GLTextureTarget
|
|
40
|
+
} from '@luma.gl/constants';
|
|
41
|
+
// import {GLPixelDataType} from '@luma.gl/constants';
|
|
42
|
+
import {withGLParameters} from '../../context/state-tracker/with-parameters';
|
|
43
|
+
// getTextureFormatBytesPerPixel
|
|
44
|
+
import {getTextureFormatWebGL} from '../converters/texture-formats';
|
|
27
45
|
import {convertSamplerParametersToWebGL} from '../converters/sampler-parameters';
|
|
28
46
|
import {WebGLDevice} from '../webgl-device';
|
|
29
|
-
import {WEBGLBuffer} from './webgl-buffer';
|
|
47
|
+
// import {WEBGLBuffer} from './webgl-buffer';
|
|
30
48
|
import {WEBGLSampler} from './webgl-sampler';
|
|
31
49
|
import {WEBGLTextureView} from './webgl-texture-view';
|
|
32
50
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
/** @deprecated WebGL only. */
|
|
45
|
-
textureUnit?: number;
|
|
46
|
-
/** @deprecated WebGL only. Use dimension. */
|
|
47
|
-
target?: number;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
export const DEFAULT_WEBGL_TEXTURE_PROPS = {
|
|
51
|
-
// deprecated
|
|
52
|
-
parameters: {},
|
|
53
|
-
pixelStore: {},
|
|
54
|
-
pixels: null,
|
|
55
|
-
border: 0,
|
|
56
|
-
dataFormat: undefined!,
|
|
57
|
-
textureUnit: undefined!,
|
|
58
|
-
target: undefined!
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
export type TextureSourceData =
|
|
62
|
-
| TypedArray
|
|
63
|
-
| ImageData
|
|
64
|
-
| HTMLImageElement
|
|
65
|
-
| HTMLCanvasElement
|
|
66
|
-
| ImageBitmap
|
|
67
|
-
| HTMLVideoElement;
|
|
68
|
-
|
|
69
|
-
type SetImageDataOptions = {
|
|
70
|
-
target?: number;
|
|
71
|
-
level?: number;
|
|
72
|
-
dataFormat?: any;
|
|
73
|
-
width?: number;
|
|
74
|
-
height?: number;
|
|
75
|
-
depth?: number;
|
|
76
|
-
glFormat?: GL;
|
|
77
|
-
type?: any;
|
|
78
|
-
offset?: number;
|
|
79
|
-
data: any; // TextureSourceData;
|
|
80
|
-
compressed?: boolean;
|
|
81
|
-
parameters?: Record<GL, any>;
|
|
82
|
-
/** @deprecated */
|
|
83
|
-
pixels?: any;
|
|
84
|
-
};
|
|
51
|
+
// import type {WebGLSetTextureOptions, WebGLCopyTextureOptions} from '../helpers/webgl-texture-utils';
|
|
52
|
+
import {
|
|
53
|
+
initializeTextureStorage,
|
|
54
|
+
// clearMipLevel,
|
|
55
|
+
copyCPUImageToMipLevel,
|
|
56
|
+
copyCPUDataToMipLevel,
|
|
57
|
+
// copyGPUBufferToMipLevel,
|
|
58
|
+
getWebGLTextureTarget
|
|
59
|
+
} from '../helpers/webgl-texture-utils';
|
|
60
|
+
|
|
61
|
+
// PORTABLE HELPERS (Move to methods on Texture?)
|
|
85
62
|
|
|
86
63
|
/**
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
* HTMLImageElement|Image - Inits with content of image. Auto width/height
|
|
92
|
-
* HTMLCanvasElement - Inits with contents of canvas. Auto width/height
|
|
93
|
-
* HTMLVideoElement - Creates video texture. Auto width/height
|
|
94
|
-
*
|
|
95
|
-
* @param x - xOffset from where texture to be updated
|
|
96
|
-
* @param y - yOffset from where texture to be updated
|
|
97
|
-
* @param width - width of the sub image to be updated
|
|
98
|
-
* @param height - height of the sub image to be updated
|
|
99
|
-
* @param level - mip level to be updated
|
|
100
|
-
* @param {GLenum} format - internal format of image data.
|
|
101
|
-
* @param {GLenum} type
|
|
102
|
-
* - format of array (autodetect from type) or
|
|
103
|
-
* - (WEBGL2) format of buffer or ArrayBufferView
|
|
104
|
-
* @param {GLenum} dataFormat - format of image data.
|
|
105
|
-
* @param {Number} offset - (WEBGL2) offset from start of buffer
|
|
106
|
-
* @parameters - temporary settings to be applied, can be used to supply pixel store settings.
|
|
64
|
+
* Normalize TextureData to an array of TextureLevelData / ExternalImages
|
|
65
|
+
* @param data
|
|
66
|
+
* @param options
|
|
67
|
+
* @returns array of TextureLevelData / ExternalImages
|
|
107
68
|
*/
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
width?: number;
|
|
131
|
-
height?: number;
|
|
132
|
-
depth?: number;
|
|
133
|
-
format?: any;
|
|
134
|
-
type?: any;
|
|
135
|
-
offset?: number;
|
|
136
|
-
data: any;
|
|
137
|
-
parameters?: Record<GL, any>;
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
// Polyfill
|
|
141
|
-
export class WEBGLTexture extends Texture<WEBGLTextureProps> {
|
|
142
|
-
// TODO - remove?
|
|
143
|
-
static FACES: number[] = [
|
|
144
|
-
GL.TEXTURE_CUBE_MAP_POSITIVE_X,
|
|
145
|
-
GL.TEXTURE_CUBE_MAP_NEGATIVE_X,
|
|
146
|
-
GL.TEXTURE_CUBE_MAP_POSITIVE_Y,
|
|
147
|
-
GL.TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
|
148
|
-
GL.TEXTURE_CUBE_MAP_POSITIVE_Z,
|
|
149
|
-
GL.TEXTURE_CUBE_MAP_NEGATIVE_Z
|
|
150
|
-
];
|
|
69
|
+
function normalizeTextureData(
|
|
70
|
+
data: Texture2DData,
|
|
71
|
+
options: {width: number; height: number; depth: number}
|
|
72
|
+
): (TextureLevelData | ExternalImage)[] {
|
|
73
|
+
let lodArray: (TextureLevelData | ExternalImage)[];
|
|
74
|
+
if (ArrayBuffer.isView(data)) {
|
|
75
|
+
lodArray = [
|
|
76
|
+
{
|
|
77
|
+
// ts-expect-error does data really need to be Uint8ClampedArray?
|
|
78
|
+
data,
|
|
79
|
+
width: options.width,
|
|
80
|
+
height: options.height
|
|
81
|
+
// depth: options.depth
|
|
82
|
+
}
|
|
83
|
+
];
|
|
84
|
+
} else if (!Array.isArray(data)) {
|
|
85
|
+
lodArray = [data];
|
|
86
|
+
} else {
|
|
87
|
+
lodArray = data;
|
|
88
|
+
}
|
|
89
|
+
return lodArray;
|
|
90
|
+
}
|
|
151
91
|
|
|
92
|
+
/**
|
|
93
|
+
* WebGL... the texture API from hell... hopefully made simpler
|
|
94
|
+
*/
|
|
95
|
+
export class WEBGLTexture extends Texture {
|
|
152
96
|
readonly MAX_ATTRIBUTES: number;
|
|
153
97
|
readonly device: WebGLDevice;
|
|
154
98
|
readonly gl: WebGL2RenderingContext;
|
|
155
|
-
|
|
99
|
+
handle: WebGLTexture;
|
|
156
100
|
|
|
157
|
-
//
|
|
158
|
-
|
|
101
|
+
sampler: WEBGLSampler = undefined; // TODO - currently unused in WebGL. Create dummy sampler?
|
|
102
|
+
view: WEBGLTextureView = undefined; // TODO - currently unused in WebGL. Create dummy view?
|
|
159
103
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
// data;
|
|
163
|
-
|
|
164
|
-
glFormat: GL = undefined;
|
|
165
|
-
type: GL = undefined;
|
|
166
|
-
dataFormat: GL = undefined;
|
|
167
|
-
mipmaps: boolean = undefined;
|
|
104
|
+
mipmaps: boolean = false;
|
|
168
105
|
|
|
169
106
|
/**
|
|
170
107
|
* @note `target` cannot be modified by bind:
|
|
171
108
|
* textures are special because when you first bind them to a target,
|
|
172
|
-
*
|
|
173
|
-
* GL_TEXTURE_2D, you are saying that this texture is a 2D texture.
|
|
109
|
+
* When you first bind a texture as a GL_TEXTURE_2D, you are saying that this texture is a 2D texture.
|
|
174
110
|
* And it will always be a 2D texture; this state cannot be changed ever.
|
|
175
111
|
* A texture that was first bound as a GL_TEXTURE_2D, must always be bound as a GL_TEXTURE_2D;
|
|
176
112
|
* attempting to bind it as GL_TEXTURE_3D will give rise to a run-time error
|
|
177
|
-
* */
|
|
178
|
-
target: GL;
|
|
179
|
-
textureUnit: number = undefined;
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Program.draw() checks the loaded flag of all textures to avoid
|
|
183
|
-
* Textures that are still loading from promises
|
|
184
|
-
* Set to true as soon as texture has been initialized with valid data
|
|
185
113
|
*/
|
|
186
|
-
|
|
114
|
+
glTarget: GLTextureTarget;
|
|
115
|
+
|
|
116
|
+
// Texture type
|
|
117
|
+
|
|
118
|
+
/** The WebGL format - essentially channel structure */
|
|
119
|
+
glFormat: GLTexelDataFormat;
|
|
120
|
+
/** The WebGL data format - the type of each channel */
|
|
121
|
+
glType: GLPixelType;
|
|
122
|
+
/** The WebGL constant corresponding to the WebGPU style constant in format */
|
|
123
|
+
glInternalFormat: GL;
|
|
124
|
+
/** Whether the internal format is compressed */
|
|
125
|
+
compressed: boolean;
|
|
126
|
+
|
|
127
|
+
// data;
|
|
128
|
+
// inherited props
|
|
129
|
+
// dimension: ...
|
|
130
|
+
// format: GLTextureTarget;
|
|
131
|
+
// width: number = undefined;
|
|
132
|
+
// height: number = undefined;
|
|
133
|
+
// depth: number = undefined;
|
|
134
|
+
|
|
135
|
+
// state
|
|
136
|
+
/** Texture binding slot */
|
|
137
|
+
textureUnit: number = 0;
|
|
138
|
+
/** For automatically updating video */
|
|
187
139
|
_video: {
|
|
188
140
|
video: HTMLVideoElement;
|
|
189
141
|
parameters: any;
|
|
190
142
|
lastTime: number;
|
|
191
|
-
};
|
|
143
|
+
} | null = null;
|
|
192
144
|
|
|
193
|
-
constructor(device: Device, props:
|
|
194
|
-
|
|
145
|
+
constructor(device: Device, props: TextureProps) {
|
|
146
|
+
// Note: Clear out `props.data` so that we don't hold a reference to any big memory chunks
|
|
147
|
+
super(device, {...Texture.defaultProps, ...props, data: undefined!});
|
|
195
148
|
|
|
196
149
|
this.device = device as WebGLDevice;
|
|
197
150
|
this.gl = this.device.gl;
|
|
198
|
-
this.handle = this.props.handle || this.gl.createTexture();
|
|
199
|
-
this.device.setSpectorMetadata(this.handle, {...this.props, data: typeof this.props.data}); // {name: this.props.id};
|
|
200
151
|
|
|
201
|
-
|
|
202
|
-
this.
|
|
152
|
+
// Note: In WebGL the texture target defines the type of texture on first bind.
|
|
153
|
+
this.glTarget = getWebGLTextureTarget(this.props.dimension);
|
|
203
154
|
|
|
204
|
-
//
|
|
205
|
-
|
|
155
|
+
// The target format of this texture
|
|
156
|
+
const format = getTextureFormatWebGL(this.props.format);
|
|
157
|
+
this.glInternalFormat = format.internalFormat;
|
|
158
|
+
this.glFormat = format.format;
|
|
159
|
+
this.glType = format.type;
|
|
160
|
+
this.compressed = format.compressed;
|
|
206
161
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
162
|
+
if (
|
|
163
|
+
typeof HTMLVideoElement !== 'undefined' &&
|
|
164
|
+
props.data instanceof HTMLVideoElement &&
|
|
165
|
+
// @ts-expect-error
|
|
166
|
+
props.data.readyState < HTMLVideoElement.HAVE_METADATA
|
|
167
|
+
) {
|
|
168
|
+
const video = props.data;
|
|
169
|
+
this._video = null; // Declare member before the object is sealed
|
|
170
|
+
video.addEventListener('loadeddata', () => this.initialize(props));
|
|
210
171
|
}
|
|
211
172
|
|
|
212
|
-
|
|
173
|
+
// We removed data, we need to add it again.
|
|
174
|
+
// @ts-expect-error
|
|
175
|
+
this.initialize({...this.props, data: props.data});
|
|
213
176
|
|
|
214
177
|
Object.seal(this);
|
|
215
178
|
}
|
|
216
179
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
this.removeStats();
|
|
221
|
-
this.trackDeallocatedMemory('Texture');
|
|
222
|
-
// this.handle = null;
|
|
223
|
-
this.destroyed = true;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
override toString(): string {
|
|
228
|
-
return `Texture(${this.id},${this.width}x${this.height})`;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
createView(props: TextureViewProps): WEBGLTextureView {
|
|
232
|
-
return new WEBGLTextureView(this.device, {...props, texture: this});
|
|
233
|
-
}
|
|
234
|
-
|
|
180
|
+
/**
|
|
181
|
+
* Initialize texture with supplied props
|
|
182
|
+
*/
|
|
235
183
|
// eslint-disable-next-line max-statements
|
|
236
|
-
initialize(props:
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
return this.initializeCube(props);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
let data = props.data;
|
|
243
|
-
|
|
244
|
-
if (data instanceof Promise) {
|
|
245
|
-
data.then(resolvedImageData =>
|
|
246
|
-
this.initialize(
|
|
247
|
-
Object.assign({}, props, {
|
|
248
|
-
pixels: resolvedImageData,
|
|
249
|
-
data: resolvedImageData
|
|
250
|
-
})
|
|
251
|
-
)
|
|
252
|
-
);
|
|
253
|
-
return this;
|
|
254
|
-
}
|
|
184
|
+
initialize(props: TextureProps = {}): void {
|
|
185
|
+
this.handle = this.props.handle || this.gl.createTexture();
|
|
186
|
+
this.device.setSpectorMetadata(this.handle, {...this.props, data: typeof this.props.data});
|
|
255
187
|
|
|
256
|
-
const
|
|
257
|
-
// @ts-expect-error
|
|
258
|
-
if (isVideo && data.readyState < HTMLVideoElement.HAVE_METADATA) {
|
|
259
|
-
this._video = null; // Declare member before the object is sealed
|
|
260
|
-
// @ts-expect-error
|
|
261
|
-
data.addEventListener('loadeddata', () => this.initialize(props));
|
|
262
|
-
return this;
|
|
263
|
-
}
|
|
188
|
+
const data = props.data;
|
|
264
189
|
|
|
265
|
-
const {parameters = {}
|
|
190
|
+
// const {parameters = {} as Record<GL, any>} = props;
|
|
266
191
|
|
|
267
|
-
|
|
192
|
+
let {width, height} = props;
|
|
268
193
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
// log.deprecated('data', 'pixels')();
|
|
274
|
-
data = pixels;
|
|
194
|
+
if (!width || !height) {
|
|
195
|
+
const textureSize = Texture.getTextureDataSize(data);
|
|
196
|
+
width = textureSize?.width || 1;
|
|
197
|
+
height = textureSize?.height || 1;
|
|
275
198
|
}
|
|
276
199
|
|
|
277
|
-
let {width, height, dataFormat, type, compressed = false} = props;
|
|
278
|
-
const {depth = 0} = props;
|
|
279
|
-
|
|
280
|
-
const glFormat = convertTextureFormatToGL(props.format);
|
|
281
|
-
|
|
282
|
-
// Deduce width and height
|
|
283
|
-
({width, height, compressed, dataFormat, type} = this._deduceParameters({
|
|
284
|
-
format: props.format,
|
|
285
|
-
type,
|
|
286
|
-
dataFormat,
|
|
287
|
-
compressed,
|
|
288
|
-
data,
|
|
289
|
-
width,
|
|
290
|
-
height
|
|
291
|
-
}));
|
|
292
|
-
|
|
293
200
|
// Store opts for accessors
|
|
294
201
|
this.width = width;
|
|
295
202
|
this.height = height;
|
|
296
|
-
|
|
297
|
-
this.glFormat = glFormat;
|
|
298
|
-
this.type = type;
|
|
299
|
-
this.dataFormat = dataFormat;
|
|
300
|
-
this.textureUnit = textureUnit;
|
|
301
|
-
|
|
302
|
-
if (Number.isFinite(this.textureUnit)) {
|
|
303
|
-
this.gl.activeTexture(GL.TEXTURE0 + this.textureUnit);
|
|
304
|
-
this.gl.bindTexture(this.target, this.handle);
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
this.mipmaps = mipmaps;
|
|
308
|
-
|
|
309
|
-
this.setImageData({
|
|
310
|
-
data,
|
|
311
|
-
width,
|
|
312
|
-
height,
|
|
313
|
-
depth,
|
|
314
|
-
format: glFormat,
|
|
315
|
-
type,
|
|
316
|
-
dataFormat,
|
|
317
|
-
// @ts-expect-error
|
|
318
|
-
parameters: pixelStore,
|
|
319
|
-
compressed
|
|
320
|
-
});
|
|
203
|
+
this.depth = props.depth;
|
|
321
204
|
|
|
322
205
|
// Set texture sampler parameters
|
|
323
206
|
this.setSampler(props.sampler);
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
this.view = this.createView({...this.props, mipLevelCount: 1, arrayLayerCount: 1});
|
|
207
|
+
// @ts-ignore
|
|
208
|
+
this.view = new WEBGLTextureView(this.device, {...this.props, texture: this});
|
|
327
209
|
|
|
328
|
-
|
|
329
|
-
|
|
210
|
+
this.bind();
|
|
211
|
+
if (!this.props.data) {
|
|
212
|
+
initializeTextureStorage(this.gl, this.mipLevels, this);
|
|
330
213
|
}
|
|
331
214
|
|
|
332
|
-
if (
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
215
|
+
if (props.data) {
|
|
216
|
+
// prettier-ignore
|
|
217
|
+
switch (props.dimension) {
|
|
218
|
+
case '1d': this.setTexture1DData(props.data); break;
|
|
219
|
+
case '2d': this.setTexture2DData(props.data); break;
|
|
220
|
+
case '3d': this.setTexture3DData(props.data); break;
|
|
221
|
+
case 'cube': this.setTextureCubeData(props.data); break;
|
|
222
|
+
case '2d-array': this.setTextureArrayData(props.data); break;
|
|
223
|
+
case 'cube-array': this.setTextureCubeArrayData(props.data); break;
|
|
336
224
|
// @ts-expect-error
|
|
337
|
-
|
|
338
|
-
}
|
|
225
|
+
default: throw new Error(props.dimension);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
this.mipmaps = Boolean(props.mipmaps);
|
|
230
|
+
|
|
231
|
+
if (this.mipmaps) {
|
|
232
|
+
this.generateMipmap();
|
|
339
233
|
}
|
|
340
234
|
|
|
341
|
-
|
|
235
|
+
// if (isVideo) {
|
|
236
|
+
// this._video = {
|
|
237
|
+
// video: data,
|
|
238
|
+
// // TODO - should we be using the sampler parameters here?
|
|
239
|
+
// parameters: {},
|
|
240
|
+
// // @ts-expect-error HTMLVideoElement.HAVE_CURRENT_DATA is not declared
|
|
241
|
+
// lastTime: data.readyState >= HTMLVideoElement.HAVE_CURRENT_DATA ? data.currentTime : -1
|
|
242
|
+
// };
|
|
243
|
+
// }
|
|
342
244
|
}
|
|
343
245
|
|
|
344
|
-
|
|
345
|
-
|
|
246
|
+
/*
|
|
247
|
+
initializeCube(props?: TextureProps): void {
|
|
248
|
+
const {mipmaps = true} = props; // , parameters = {} as Record<GL, any>} = props;
|
|
346
249
|
|
|
347
250
|
// Store props for accessors
|
|
348
251
|
// this.props = props;
|
|
349
252
|
|
|
350
253
|
// @ts-expect-error
|
|
351
|
-
this.
|
|
352
|
-
this.loaded = true;
|
|
353
|
-
|
|
254
|
+
this.setCubeMapData(props).then(() => {
|
|
354
255
|
// TODO - should genMipmap() be called on the cubemap or on the faces?
|
|
355
256
|
// TODO - without generateMipmap() cube textures do not work at all!!! Why?
|
|
356
257
|
if (mipmaps) {
|
|
@@ -358,12 +259,33 @@ export class WEBGLTexture extends Texture<WEBGLTextureProps> {
|
|
|
358
259
|
}
|
|
359
260
|
|
|
360
261
|
this.setSampler(props.sampler);
|
|
361
|
-
|
|
262
|
+
|
|
263
|
+
// v8 compatibility?
|
|
264
|
+
// const {parameters = {} as Record<GL, any>} = props;
|
|
265
|
+
// this._setSamplerParameters(parameters);
|
|
362
266
|
});
|
|
363
|
-
return this;
|
|
364
267
|
}
|
|
268
|
+
*/
|
|
365
269
|
|
|
366
|
-
|
|
270
|
+
override destroy(): void {
|
|
271
|
+
if (this.handle) {
|
|
272
|
+
this.gl.deleteTexture(this.handle);
|
|
273
|
+
this.removeStats();
|
|
274
|
+
this.trackDeallocatedMemory('Texture');
|
|
275
|
+
// this.handle = null;
|
|
276
|
+
this.destroyed = true;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
override toString(): string {
|
|
281
|
+
return `Texture(${this.id},${this.width}x${this.height})`;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
createView(props: TextureViewProps): WEBGLTextureView {
|
|
285
|
+
return new WEBGLTextureView(this.device, {...props, texture: this});
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
setSampler(sampler: Sampler | SamplerProps = {}): void {
|
|
367
289
|
let samplerProps: SamplerParameters;
|
|
368
290
|
if (sampler instanceof WEBGLSampler) {
|
|
369
291
|
this.sampler = sampler;
|
|
@@ -375,422 +297,260 @@ export class WEBGLTexture extends Texture<WEBGLTextureProps> {
|
|
|
375
297
|
|
|
376
298
|
const parameters = convertSamplerParametersToWebGL(samplerProps);
|
|
377
299
|
this._setSamplerParameters(parameters);
|
|
378
|
-
return this;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
/**
|
|
382
|
-
* If size has changed, reinitializes with current format
|
|
383
|
-
* @note note clears image and mipmaps
|
|
384
|
-
*/
|
|
385
|
-
resize(options: {height: number; width: number; mipmaps?: boolean}): this {
|
|
386
|
-
const {height, width, mipmaps = false} = options;
|
|
387
|
-
if (width !== this.width || height !== this.height) {
|
|
388
|
-
return this.initialize({
|
|
389
|
-
width,
|
|
390
|
-
height,
|
|
391
|
-
format: this.format,
|
|
392
|
-
type: this.type,
|
|
393
|
-
dataFormat: this.dataFormat,
|
|
394
|
-
mipmaps
|
|
395
|
-
});
|
|
396
|
-
}
|
|
397
|
-
return this;
|
|
398
300
|
}
|
|
399
301
|
|
|
400
|
-
/** Update external texture (video frame) */
|
|
302
|
+
/** Update external texture (video frame or canvas) */
|
|
401
303
|
update(): void {
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
304
|
+
log.warn('Texture.update() not implemented');
|
|
305
|
+
// if (this._video) {
|
|
306
|
+
// const {video, parameters, lastTime} = this._video;
|
|
307
|
+
// // @ts-expect-error
|
|
308
|
+
// if (lastTime === video.currentTime || video.readyState < HTMLVideoElement.HAVE_CURRENT_DATA) {
|
|
309
|
+
// return;
|
|
310
|
+
// }
|
|
311
|
+
// this.setSubImageData({
|
|
312
|
+
// data: video,
|
|
313
|
+
// parameters
|
|
314
|
+
// });
|
|
315
|
+
// if (this.mipmaps) {
|
|
316
|
+
// this.generateMipmap();
|
|
317
|
+
// }
|
|
318
|
+
// this._video.lastTime = video.currentTime;
|
|
319
|
+
// }
|
|
417
320
|
}
|
|
418
321
|
|
|
419
322
|
// Call to regenerate mipmaps after modifying texture(s)
|
|
420
|
-
generateMipmap(params = {}):
|
|
323
|
+
generateMipmap(params = {}): void {
|
|
324
|
+
if (!this.props.data) {
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
421
327
|
this.mipmaps = true;
|
|
422
|
-
|
|
423
|
-
this.gl.bindTexture(this.target, this.handle);
|
|
328
|
+
this.gl.bindTexture(this.glTarget, this.handle);
|
|
424
329
|
withGLParameters(this.gl, params, () => {
|
|
425
|
-
this.gl.generateMipmap(this.
|
|
330
|
+
this.gl.generateMipmap(this.glTarget);
|
|
426
331
|
});
|
|
427
|
-
this.gl.bindTexture(this.
|
|
428
|
-
return this;
|
|
332
|
+
this.gl.bindTexture(this.glTarget, null);
|
|
429
333
|
}
|
|
430
334
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
}
|
|
335
|
+
// Image Data Setters
|
|
336
|
+
copyExternalImage(options: {
|
|
337
|
+
image: ExternalImage;
|
|
338
|
+
sourceX?: number;
|
|
339
|
+
sourceY?: number;
|
|
340
|
+
width?: number;
|
|
341
|
+
height?: number;
|
|
342
|
+
depth?: number;
|
|
343
|
+
mipLevel?: number;
|
|
344
|
+
x?: number;
|
|
345
|
+
y?: number;
|
|
346
|
+
z?: number;
|
|
347
|
+
aspect?: 'all' | 'stencil-only' | 'depth-only';
|
|
348
|
+
colorSpace?: 'srgb';
|
|
349
|
+
premultipliedAlpha?: boolean;
|
|
350
|
+
}): {width: number; height: number} {
|
|
351
|
+
const size = Texture.getExternalImageSize(options.image);
|
|
352
|
+
const opts = {...Texture.defaultCopyExternalImageOptions, ...size, ...options};
|
|
353
|
+
const {depth, mipLevel: lodLevel, image} = opts;
|
|
354
|
+
this.bind();
|
|
355
|
+
this._setMipLevel(depth, lodLevel, image);
|
|
356
|
+
this.unbind();
|
|
357
|
+
return {width: opts.width, height: opts.height};
|
|
358
|
+
}
|
|
456
359
|
|
|
457
|
-
|
|
360
|
+
setTexture1DData(data: Texture1DData): void {
|
|
361
|
+
throw new Error('setTexture1DData not supported in WebGL.');
|
|
362
|
+
}
|
|
458
363
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
level = 0,
|
|
463
|
-
glFormat = this.glFormat,
|
|
464
|
-
offset = 0,
|
|
465
|
-
parameters = {} as Record<GL, any>
|
|
466
|
-
} = options;
|
|
364
|
+
/** Set a simple texture */
|
|
365
|
+
setTexture2DData(lodData: Texture2DData, depth = 0): void {
|
|
366
|
+
this.bind();
|
|
467
367
|
|
|
468
|
-
|
|
469
|
-
data = null,
|
|
470
|
-
type = this.type,
|
|
471
|
-
width = this.width,
|
|
472
|
-
height = this.height,
|
|
473
|
-
dataFormat = this.dataFormat,
|
|
474
|
-
compressed = false
|
|
475
|
-
} = options;
|
|
368
|
+
const lodArray = normalizeTextureData(lodData, this);
|
|
476
369
|
|
|
477
|
-
//
|
|
478
|
-
|
|
479
|
-
|
|
370
|
+
// If the user provides multiple LODs, then automatic mipmap
|
|
371
|
+
// generation generateMipmap() should be disabled to avoid overwriting them.
|
|
372
|
+
if (lodArray.length > 1 && this.props.mipmaps !== false) {
|
|
373
|
+
log.warn(`Texture ${this.id} mipmap and multiple LODs.`)();
|
|
480
374
|
}
|
|
481
375
|
|
|
482
|
-
(
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
dataFormat,
|
|
486
|
-
compressed,
|
|
487
|
-
data,
|
|
488
|
-
width,
|
|
489
|
-
height
|
|
490
|
-
}));
|
|
491
|
-
|
|
492
|
-
const {gl} = this;
|
|
493
|
-
gl.bindTexture(this.target, this.handle);
|
|
494
|
-
|
|
495
|
-
let dataType = null;
|
|
496
|
-
({data, dataType} = this._getDataType({data, compressed}));
|
|
497
|
-
|
|
498
|
-
withGLParameters(this.gl, parameters, () => {
|
|
499
|
-
switch (dataType) {
|
|
500
|
-
case 'null':
|
|
501
|
-
gl.texImage2D(
|
|
502
|
-
target,
|
|
503
|
-
level,
|
|
504
|
-
glFormat,
|
|
505
|
-
width,
|
|
506
|
-
height,
|
|
507
|
-
0 /* border*/,
|
|
508
|
-
dataFormat,
|
|
509
|
-
type,
|
|
510
|
-
data
|
|
511
|
-
);
|
|
512
|
-
break;
|
|
513
|
-
case 'typed-array':
|
|
514
|
-
gl.texImage2D(
|
|
515
|
-
target,
|
|
516
|
-
level,
|
|
517
|
-
glFormat,
|
|
518
|
-
width,
|
|
519
|
-
height,
|
|
520
|
-
0, // border (must be 0)
|
|
521
|
-
dataFormat,
|
|
522
|
-
type,
|
|
523
|
-
data,
|
|
524
|
-
offset
|
|
525
|
-
);
|
|
526
|
-
break;
|
|
527
|
-
case 'buffer':
|
|
528
|
-
// WebGL2 enables creating textures directly from a WebGL buffer
|
|
529
|
-
this.device.gl.bindBuffer(GL.PIXEL_UNPACK_BUFFER, data.handle || data);
|
|
530
|
-
this.device.gl.texImage2D(
|
|
531
|
-
target,
|
|
532
|
-
level,
|
|
533
|
-
glFormat,
|
|
534
|
-
width,
|
|
535
|
-
height,
|
|
536
|
-
0 /* border*/,
|
|
537
|
-
dataFormat,
|
|
538
|
-
type,
|
|
539
|
-
offset
|
|
540
|
-
);
|
|
541
|
-
this.device.gl.bindBuffer(GL.PIXEL_UNPACK_BUFFER, null);
|
|
542
|
-
break;
|
|
543
|
-
case 'browser-object':
|
|
544
|
-
gl.texImage2D(
|
|
545
|
-
target,
|
|
546
|
-
level,
|
|
547
|
-
glFormat,
|
|
548
|
-
width,
|
|
549
|
-
height,
|
|
550
|
-
0 /* border*/,
|
|
551
|
-
dataFormat,
|
|
552
|
-
type,
|
|
553
|
-
data
|
|
554
|
-
);
|
|
555
|
-
break;
|
|
556
|
-
case 'compressed':
|
|
557
|
-
for (const [levelIndex, levelData] of data.entries()) {
|
|
558
|
-
gl.compressedTexImage2D(
|
|
559
|
-
target,
|
|
560
|
-
levelIndex,
|
|
561
|
-
levelData.format,
|
|
562
|
-
levelData.width,
|
|
563
|
-
levelData.height,
|
|
564
|
-
0 /* border, must be 0 */,
|
|
565
|
-
levelData.data
|
|
566
|
-
);
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
break;
|
|
570
|
-
default:
|
|
571
|
-
assert(false, 'Unknown image data type');
|
|
572
|
-
}
|
|
573
|
-
});
|
|
574
|
-
|
|
575
|
-
if (data && data.byteLength) {
|
|
576
|
-
this.trackAllocatedMemory(data.byteLength, 'Texture');
|
|
577
|
-
} else {
|
|
578
|
-
const bytesPerPixel = getTextureFormatBytesPerPixel(this.props.format);
|
|
579
|
-
this.trackAllocatedMemory(this.width * this.height * bytesPerPixel, 'Texture');
|
|
376
|
+
for (let lodLevel = 0; lodLevel < lodArray.length; lodLevel++) {
|
|
377
|
+
const imageData = lodArray[lodLevel];
|
|
378
|
+
this._setMipLevel(depth, lodLevel, imageData);
|
|
580
379
|
}
|
|
581
380
|
|
|
582
|
-
this.
|
|
583
|
-
|
|
584
|
-
return this;
|
|
381
|
+
this.unbind();
|
|
585
382
|
}
|
|
586
383
|
|
|
587
384
|
/**
|
|
588
|
-
*
|
|
589
|
-
*
|
|
590
|
-
* Redefines an area of an existing texture
|
|
385
|
+
* Sets a 3D texture
|
|
386
|
+
* @param data
|
|
591
387
|
*/
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
data = null,
|
|
596
|
-
x = 0,
|
|
597
|
-
y = 0,
|
|
598
|
-
width = this.width,
|
|
599
|
-
height = this.height,
|
|
600
|
-
level = 0,
|
|
601
|
-
glFormat = this.glFormat,
|
|
602
|
-
type = this.type,
|
|
603
|
-
dataFormat = this.dataFormat,
|
|
604
|
-
compressed = false,
|
|
605
|
-
offset = 0,
|
|
606
|
-
parameters = {} as Record<GL, any>
|
|
607
|
-
}: SetSubImageDataOptions) {
|
|
608
|
-
({type, dataFormat, compressed, width, height} = this._deduceParameters({
|
|
609
|
-
format: this.props.format,
|
|
610
|
-
type,
|
|
611
|
-
dataFormat,
|
|
612
|
-
compressed,
|
|
613
|
-
data,
|
|
614
|
-
width,
|
|
615
|
-
height
|
|
616
|
-
}));
|
|
617
|
-
|
|
618
|
-
assert(this.depth === 1, 'texSubImage not supported for 3D textures');
|
|
619
|
-
|
|
620
|
-
// pixels variable is for API compatibility purpose
|
|
621
|
-
if (!data) {
|
|
622
|
-
data = pixels;
|
|
388
|
+
setTexture3DData(data: Texture3DData): void {
|
|
389
|
+
if (this.props.dimension !== '3d') {
|
|
390
|
+
throw new Error(this.id);
|
|
623
391
|
}
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
data = ndarray.data;
|
|
629
|
-
width = ndarray.shape[0];
|
|
630
|
-
height = ndarray.shape[1];
|
|
392
|
+
if (ArrayBuffer.isView(data)) {
|
|
393
|
+
this.bind();
|
|
394
|
+
copyCPUDataToMipLevel(this.device.gl, data, this);
|
|
395
|
+
this.unbind();
|
|
631
396
|
}
|
|
397
|
+
}
|
|
632
398
|
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
399
|
+
/**
|
|
400
|
+
* Set a Texture Cube Data
|
|
401
|
+
* @todo - could support TextureCubeArray with depth
|
|
402
|
+
* @param data
|
|
403
|
+
* @param index
|
|
404
|
+
*/
|
|
405
|
+
setTextureCubeData(data: TextureCubeData, depth: number = 0): void {
|
|
406
|
+
if (this.props.dimension !== 'cube') {
|
|
407
|
+
throw new Error(this.id);
|
|
408
|
+
}
|
|
409
|
+
for (const face of Texture.CubeFaces) {
|
|
410
|
+
this.setTextureCubeFaceData(data[face], face);
|
|
636
411
|
}
|
|
637
|
-
|
|
638
|
-
this.gl.bindTexture(this.target, this.handle);
|
|
639
|
-
|
|
640
|
-
withGLParameters(this.gl, parameters, () => {
|
|
641
|
-
// TODO - x,y parameters
|
|
642
|
-
if (compressed) {
|
|
643
|
-
this.gl.compressedTexSubImage2D(target, level, x, y, width, height, glFormat, data);
|
|
644
|
-
} else if (data === null) {
|
|
645
|
-
this.gl.texSubImage2D(target, level, x, y, width, height, dataFormat, type, null);
|
|
646
|
-
} else if (ArrayBuffer.isView(data)) {
|
|
647
|
-
this.gl.texSubImage2D(target, level, x, y, width, height, dataFormat, type, data, offset);
|
|
648
|
-
} else if (typeof WebGLBuffer !== 'undefined' && data instanceof WebGLBuffer) {
|
|
649
|
-
// WebGL2 allows us to create texture directly from a WebGL buffer
|
|
650
|
-
// This texImage2D signature uses currently bound GL.PIXEL_UNPACK_BUFFER
|
|
651
|
-
this.device.gl.bindBuffer(GL.PIXEL_UNPACK_BUFFER, data);
|
|
652
|
-
this.device.gl.texSubImage2D(target, level, x, y, width, height, dataFormat, type, offset);
|
|
653
|
-
this.device.gl.bindBuffer(GL.PIXEL_UNPACK_BUFFER, null);
|
|
654
|
-
} else {
|
|
655
|
-
// Assume data is a browser supported object (ImageData, Canvas, ...)
|
|
656
|
-
this.device.gl.texSubImage2D(target, level, x, y, width, height, dataFormat, type, data);
|
|
657
|
-
}
|
|
658
|
-
});
|
|
659
|
-
|
|
660
|
-
this.gl.bindTexture(this.target, null);
|
|
661
412
|
}
|
|
662
413
|
|
|
663
414
|
/**
|
|
664
|
-
*
|
|
665
|
-
*
|
|
666
|
-
* (gl.copyTexImage2D wrapper)
|
|
667
|
-
*
|
|
668
|
-
* Note that binding a texture into a Framebuffer's color buffer and
|
|
669
|
-
* rendering can be faster.
|
|
415
|
+
* Sets an entire texture array
|
|
416
|
+
* @param data
|
|
670
417
|
*/
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
418
|
+
setTextureArrayData(data: TextureArrayData): void {
|
|
419
|
+
if (this.props.dimension !== '2d-array') {
|
|
420
|
+
throw new Error(this.id);
|
|
421
|
+
}
|
|
422
|
+
throw new Error('setTextureArrayData not implemented.');
|
|
676
423
|
}
|
|
677
424
|
|
|
678
|
-
|
|
679
|
-
|
|
425
|
+
/**
|
|
426
|
+
* Sets an entire texture cube array
|
|
427
|
+
* @param data
|
|
428
|
+
*/
|
|
429
|
+
setTextureCubeArrayData(data: TextureCubeArrayData): void {
|
|
430
|
+
throw new Error('setTextureCubeArrayData not supported in WebGL2.');
|
|
680
431
|
}
|
|
681
432
|
|
|
682
|
-
|
|
683
|
-
|
|
433
|
+
setTextureCubeFaceData(lodData: Texture2DData, face: TextureCubeFace, depth: number = 0): void {
|
|
434
|
+
// assert(this.props.dimension === 'cube');
|
|
684
435
|
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
436
|
+
// If the user provides multiple LODs, then automatic mipmap
|
|
437
|
+
// generation generateMipmap() should be disabled to avoid overwriting them.
|
|
438
|
+
if (Array.isArray(lodData) && lodData.length > 1 && this.props.mipmaps !== false) {
|
|
439
|
+
log.warn(`${this.id} has mipmap and multiple LODs.`)();
|
|
688
440
|
}
|
|
689
441
|
|
|
690
|
-
|
|
691
|
-
|
|
442
|
+
const faceDepth = Texture.CubeFaces.indexOf(face);
|
|
443
|
+
|
|
444
|
+
this.setTexture2DData(lodData, faceDepth);
|
|
692
445
|
}
|
|
693
446
|
|
|
694
|
-
|
|
695
|
-
const {gl} = this;
|
|
447
|
+
// INTERNAL METHODS
|
|
696
448
|
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
449
|
+
/** @todo update this method to accept LODs */
|
|
450
|
+
setImageDataForFace(options): void {
|
|
451
|
+
const {
|
|
452
|
+
face,
|
|
453
|
+
width,
|
|
454
|
+
height,
|
|
455
|
+
pixels,
|
|
456
|
+
data,
|
|
457
|
+
format = GL.RGBA,
|
|
458
|
+
type = GL.UNSIGNED_BYTE
|
|
459
|
+
// generateMipmap = false // TODO
|
|
460
|
+
} = options;
|
|
701
461
|
|
|
702
|
-
gl
|
|
703
|
-
return textureUnit;
|
|
704
|
-
}
|
|
462
|
+
const {gl} = this;
|
|
705
463
|
|
|
706
|
-
|
|
464
|
+
const imageData = pixels || data;
|
|
707
465
|
|
|
708
|
-
|
|
709
|
-
if (
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
466
|
+
this.bind();
|
|
467
|
+
if (imageData instanceof Promise) {
|
|
468
|
+
imageData.then(resolvedImageData =>
|
|
469
|
+
this.setImageDataForFace(
|
|
470
|
+
Object.assign({}, options, {
|
|
471
|
+
face,
|
|
472
|
+
data: resolvedImageData,
|
|
473
|
+
pixels: resolvedImageData
|
|
474
|
+
})
|
|
475
|
+
)
|
|
476
|
+
);
|
|
477
|
+
} else if (this.width || this.height) {
|
|
478
|
+
gl.texImage2D(face, 0, format, width, height, 0 /* border*/, format, type, imageData);
|
|
479
|
+
} else {
|
|
480
|
+
gl.texImage2D(face, 0, format, format, type, imageData);
|
|
720
481
|
}
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
_getImageDataMap(faceData: Record<string | GL, any>): Record<GL, any> {
|
|
485
|
+
for (let i = 0; i < Texture.CubeFaces.length; ++i) {
|
|
486
|
+
const faceName = Texture.CubeFaces[i];
|
|
487
|
+
if (faceData[faceName]) {
|
|
488
|
+
faceData[GL.TEXTURE_CUBE_MAP_POSITIVE_X + i] = faceData[faceName];
|
|
489
|
+
delete faceData[faceName];
|
|
490
|
+
}
|
|
724
491
|
}
|
|
725
|
-
|
|
726
|
-
return {data, dataType: 'browser-object'};
|
|
492
|
+
return faceData;
|
|
727
493
|
}
|
|
728
494
|
|
|
729
|
-
//
|
|
495
|
+
// RESOURCE METHODS
|
|
730
496
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
497
|
+
/**
|
|
498
|
+
* Sets sampler parameters on texture
|
|
499
|
+
*/
|
|
500
|
+
_setSamplerParameters(parameters: GLSamplerParameters): void {
|
|
501
|
+
log.log(1, 'texture sampler parameters', parameters)();
|
|
734
502
|
|
|
735
|
-
|
|
736
|
-
const
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
compressed = compressed || parameters.compressed;
|
|
503
|
+
this.gl.bindTexture(this.glTarget, this.handle);
|
|
504
|
+
for (const [pname, pvalue] of Object.entries(parameters)) {
|
|
505
|
+
const param = Number(pname) as keyof GLSamplerParameters;
|
|
506
|
+
const value = pvalue;
|
|
740
507
|
|
|
741
|
-
|
|
508
|
+
// Apparently integer/float issues require two different texture parameter setting functions in JavaScript.
|
|
509
|
+
// For now, pick the float version for parameters specified as GLfloat.
|
|
510
|
+
switch (param) {
|
|
511
|
+
case GL.TEXTURE_MIN_LOD:
|
|
512
|
+
case GL.TEXTURE_MAX_LOD:
|
|
513
|
+
this.gl.texParameterf(this.glTarget, param, value);
|
|
514
|
+
break;
|
|
742
515
|
|
|
743
|
-
|
|
744
|
-
|
|
516
|
+
case GL.TEXTURE_MIN_FILTER:
|
|
517
|
+
this.gl.texParameteri(this.glTarget, param, value);
|
|
518
|
+
break;
|
|
745
519
|
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
} else if (!data) {
|
|
761
|
-
size = {width: width >= 0 ? width : 1, height: height >= 0 ? height : 1};
|
|
762
|
-
} else {
|
|
763
|
-
size = {width, height};
|
|
520
|
+
case GL.TEXTURE_WRAP_S:
|
|
521
|
+
case GL.TEXTURE_WRAP_T:
|
|
522
|
+
this.gl.texParameteri(this.glTarget, param, value);
|
|
523
|
+
break;
|
|
524
|
+
case GL.TEXTURE_MAX_ANISOTROPY_EXT:
|
|
525
|
+
// We have to query feature before using it
|
|
526
|
+
if (this.device.features.has('texture-filterable-anisotropic-webgl')) {
|
|
527
|
+
this.gl.texParameteri(this.glTarget, param, value);
|
|
528
|
+
}
|
|
529
|
+
break;
|
|
530
|
+
default:
|
|
531
|
+
this.gl.texParameteri(this.glTarget, param, value);
|
|
532
|
+
break;
|
|
533
|
+
}
|
|
764
534
|
}
|
|
765
535
|
|
|
766
|
-
|
|
767
|
-
assert(
|
|
768
|
-
width === undefined || size.width === width,
|
|
769
|
-
'Deduced texture width does not match supplied width'
|
|
770
|
-
);
|
|
771
|
-
assert(
|
|
772
|
-
height === undefined || size.height === height,
|
|
773
|
-
'Deduced texture height does not match supplied height'
|
|
774
|
-
);
|
|
775
|
-
|
|
776
|
-
return size;
|
|
536
|
+
this.gl.bindTexture(this.glTarget, null);
|
|
777
537
|
}
|
|
778
538
|
|
|
779
|
-
//
|
|
539
|
+
// CLASSIC
|
|
780
540
|
|
|
781
|
-
/*
|
|
782
|
-
|
|
783
|
-
width:
|
|
784
|
-
height:
|
|
785
|
-
|
|
786
|
-
data: any;
|
|
541
|
+
/*
|
|
542
|
+
setCubeMapData(options: {
|
|
543
|
+
width: number;
|
|
544
|
+
height: number;
|
|
545
|
+
data: Record<GL, Texture2DData> | Record<TextureCubeFace, Texture2DData>;
|
|
787
546
|
format?: any;
|
|
788
547
|
type?: any;
|
|
789
|
-
|
|
548
|
+
/** @deprecated Use .data *
|
|
549
|
+
pixels: any;
|
|
550
|
+
}): void {
|
|
790
551
|
const {gl} = this;
|
|
791
552
|
|
|
792
553
|
const {width, height, pixels, data, format = GL.RGBA, type = GL.UNSIGNED_BYTE} = options;
|
|
793
|
-
const imageDataMap = pixels || data;
|
|
794
554
|
|
|
795
555
|
// pixel data (imageDataMap) is an Object from Face to Image or Promise.
|
|
796
556
|
// For example:
|
|
@@ -805,13 +565,12 @@ export class WEBGLTexture extends Texture<WEBGLTextureProps> {
|
|
|
805
565
|
// GL.TEXTURE_CUBE_MAP_NEGATIVE_X : [Image-or-Promise-LOD-0, Image-or-Promise-LOD-1],
|
|
806
566
|
// ... }
|
|
807
567
|
|
|
808
|
-
const
|
|
809
|
-
WEBGLTexture.FACES.map(face => {
|
|
810
|
-
const facePixels = imageDataMap[face];
|
|
811
|
-
return Promise.all(Array.isArray(facePixels) ? facePixels : [facePixels]);
|
|
812
|
-
})
|
|
813
|
-
);
|
|
568
|
+
const imageDataMap = this._getImageDataMap(pixels || data);
|
|
814
569
|
|
|
570
|
+
const resolvedFaces = WEBGLTexture.FACES.map(face => {
|
|
571
|
+
const facePixels = imageDataMap[face];
|
|
572
|
+
return Array.isArray(facePixels) ? facePixels : [facePixels];
|
|
573
|
+
});
|
|
815
574
|
this.bind();
|
|
816
575
|
|
|
817
576
|
WEBGLTexture.FACES.forEach((face, index) => {
|
|
@@ -823,7 +582,7 @@ export class WEBGLTexture extends Texture<WEBGLTextureProps> {
|
|
|
823
582
|
resolvedFaces[index].forEach((image, lodLevel) => {
|
|
824
583
|
// TODO: adjust width & height for LOD!
|
|
825
584
|
if (width && height) {
|
|
826
|
-
gl.texImage2D(face, lodLevel, format, width, height, 0 /* border
|
|
585
|
+
gl.texImage2D(face, lodLevel, format, width, height, 0 /* border*, format, type, image);
|
|
827
586
|
} else {
|
|
828
587
|
gl.texImage2D(face, lodLevel, format, format, type, image);
|
|
829
588
|
}
|
|
@@ -832,168 +591,70 @@ export class WEBGLTexture extends Texture<WEBGLTextureProps> {
|
|
|
832
591
|
|
|
833
592
|
this.unbind();
|
|
834
593
|
}
|
|
594
|
+
*/
|
|
835
595
|
|
|
836
|
-
|
|
837
|
-
setImageDataForFace(options) {
|
|
838
|
-
const {
|
|
839
|
-
face,
|
|
840
|
-
width,
|
|
841
|
-
height,
|
|
842
|
-
pixels,
|
|
843
|
-
data,
|
|
844
|
-
format = GL.RGBA,
|
|
845
|
-
type = GL.UNSIGNED_BYTE
|
|
846
|
-
// generateMipmap = false // TODO
|
|
847
|
-
} = options;
|
|
596
|
+
// INTERNAL SETTERS
|
|
848
597
|
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
gl
|
|
866
|
-
|
|
867
|
-
gl.texImage2D(face, 0, format, format, type, imageData);
|
|
598
|
+
/**
|
|
599
|
+
* Copy a region of data from a CPU memory buffer into this texture.
|
|
600
|
+
* @todo - GLUnpackParameters parameters
|
|
601
|
+
*/
|
|
602
|
+
protected _setMipLevel(
|
|
603
|
+
depth: number,
|
|
604
|
+
level: number,
|
|
605
|
+
textureData: Texture2DData,
|
|
606
|
+
glTarget: GL = this.glTarget
|
|
607
|
+
) {
|
|
608
|
+
// if (!textureData) {
|
|
609
|
+
// clearMipLevel(this.device.gl, {...this, depth, level});
|
|
610
|
+
// return;
|
|
611
|
+
// }
|
|
612
|
+
|
|
613
|
+
if (Texture.isExternalImage(textureData)) {
|
|
614
|
+
copyCPUImageToMipLevel(this.device.gl, textureData, {...this, depth, level, glTarget});
|
|
615
|
+
return;
|
|
868
616
|
}
|
|
869
617
|
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
type, // = GL.UNSIGNED_BYTE,
|
|
880
|
-
width,
|
|
881
|
-
height,
|
|
882
|
-
depth = 1,
|
|
883
|
-
offset = 0,
|
|
884
|
-
data,
|
|
885
|
-
parameters = {}
|
|
886
|
-
} = options;
|
|
887
|
-
|
|
888
|
-
this.trackDeallocatedMemory('Texture');
|
|
889
|
-
|
|
890
|
-
this.gl.bindTexture(this.target, this.handle);
|
|
891
|
-
|
|
892
|
-
const webglTextureFormat = getWebGLTextureParameters(format);
|
|
893
|
-
|
|
894
|
-
withGLParameters(this.gl, parameters, () => {
|
|
895
|
-
if (ArrayBuffer.isView(data)) {
|
|
896
|
-
this.gl.texImage3D(
|
|
897
|
-
this.target,
|
|
898
|
-
level,
|
|
899
|
-
webglTextureFormat.format,
|
|
900
|
-
width,
|
|
901
|
-
height,
|
|
902
|
-
depth,
|
|
903
|
-
0 /* border, must be 0 */,
|
|
904
|
-
webglTextureFormat.dataFormat,
|
|
905
|
-
webglTextureFormat.type, // dataType: getWebGL,
|
|
906
|
-
data
|
|
907
|
-
);
|
|
908
|
-
}
|
|
909
|
-
|
|
910
|
-
if (data instanceof WEBGLBuffer) {
|
|
911
|
-
this.gl.bindBuffer(GL.PIXEL_UNPACK_BUFFER, data.handle);
|
|
912
|
-
this.gl.texImage3D(
|
|
913
|
-
this.target,
|
|
914
|
-
level,
|
|
915
|
-
dataFormat,
|
|
916
|
-
width,
|
|
917
|
-
height,
|
|
918
|
-
depth,
|
|
919
|
-
0 /* border, must be 0 */,
|
|
920
|
-
format,
|
|
921
|
-
type,
|
|
922
|
-
offset
|
|
923
|
-
);
|
|
924
|
-
}
|
|
925
|
-
});
|
|
926
|
-
|
|
927
|
-
if (data && data.byteLength) {
|
|
928
|
-
this.trackAllocatedMemory(data.byteLength, 'Texture');
|
|
929
|
-
} else {
|
|
930
|
-
const bytesPerPixel = getTextureFormatBytesPerPixel(this.props.format);
|
|
931
|
-
this.trackAllocatedMemory(this.width * this.height * this.depth * bytesPerPixel, 'Texture');
|
|
618
|
+
// @ts-expect-error
|
|
619
|
+
if (Texture.isTextureLevelData(textureData)) {
|
|
620
|
+
copyCPUDataToMipLevel(this.device.gl, textureData.data, {
|
|
621
|
+
...this,
|
|
622
|
+
depth,
|
|
623
|
+
level,
|
|
624
|
+
glTarget
|
|
625
|
+
});
|
|
626
|
+
return;
|
|
932
627
|
}
|
|
933
628
|
|
|
934
|
-
|
|
629
|
+
throw new Error('Texture: invalid image data');
|
|
630
|
+
}
|
|
631
|
+
// HELPERS
|
|
935
632
|
|
|
936
|
-
|
|
633
|
+
getActiveUnit(): number {
|
|
634
|
+
return this.gl.getParameter(GL.ACTIVE_TEXTURE) - GL.TEXTURE0;
|
|
937
635
|
}
|
|
938
636
|
|
|
939
|
-
|
|
637
|
+
bind(textureUnit?: number): number {
|
|
638
|
+
const {gl} = this;
|
|
940
639
|
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
_setSamplerParameters(parameters: GLSamplerParameters): void {
|
|
945
|
-
// NPOT parameters may populate an empty object
|
|
946
|
-
if (isObjectEmpty(parameters)) {
|
|
947
|
-
return;
|
|
640
|
+
if (textureUnit !== undefined) {
|
|
641
|
+
this.textureUnit = textureUnit;
|
|
642
|
+
gl.activeTexture(gl.TEXTURE0 + textureUnit);
|
|
948
643
|
}
|
|
949
644
|
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
for (const [pname, pvalue] of Object.entries(parameters)) {
|
|
954
|
-
const param = Number(pname) as GL.TEXTURE_MIN_LOD | GL.TEXTURE_MAX_LOD;
|
|
955
|
-
const value = pvalue;
|
|
645
|
+
gl.bindTexture(this.glTarget, this.handle);
|
|
646
|
+
return textureUnit;
|
|
647
|
+
}
|
|
956
648
|
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
switch (param) {
|
|
960
|
-
case GL.TEXTURE_MIN_LOD:
|
|
961
|
-
case GL.TEXTURE_MAX_LOD:
|
|
962
|
-
this.gl.texParameterf(this.target, param, value);
|
|
963
|
-
break;
|
|
649
|
+
unbind(textureUnit?: number): number | undefined {
|
|
650
|
+
const {gl} = this;
|
|
964
651
|
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
}
|
|
652
|
+
if (textureUnit !== undefined) {
|
|
653
|
+
this.textureUnit = textureUnit;
|
|
654
|
+
gl.activeTexture(gl.TEXTURE0 + textureUnit);
|
|
969
655
|
}
|
|
970
|
-
this.gl.bindTexture(this.target, null);
|
|
971
|
-
return;
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
656
|
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
function getWebGLTextureTarget(props: TextureProps) {
|
|
978
|
-
switch (props.dimension) {
|
|
979
|
-
// supported in WebGL
|
|
980
|
-
case '2d':
|
|
981
|
-
return GL.TEXTURE_2D;
|
|
982
|
-
case 'cube':
|
|
983
|
-
return GL.TEXTURE_CUBE_MAP;
|
|
984
|
-
// supported in WebGL2
|
|
985
|
-
case '2d-array':
|
|
986
|
-
return GL.TEXTURE_2D_ARRAY;
|
|
987
|
-
case '3d':
|
|
988
|
-
return GL.TEXTURE_3D;
|
|
989
|
-
// not supported in any WebGL version
|
|
990
|
-
case '1d':
|
|
991
|
-
case 'cube-array':
|
|
992
|
-
default:
|
|
993
|
-
throw new Error(props.dimension);
|
|
657
|
+
gl.bindTexture(this.glTarget, null);
|
|
658
|
+
return textureUnit;
|
|
994
659
|
}
|
|
995
660
|
}
|
|
996
|
-
|
|
997
|
-
function logParameters(parameters: Record<number, GL | number>) {
|
|
998
|
-
log.log(1, 'texture sampler parameters', parameters)();
|
|
999
|
-
}
|