@luma.gl/webgl 9.0.11 → 9.1.0-alpha.1
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/LICENSE +34 -0
- package/dist/adapter/converters/device-parameters.d.ts.map +1 -1
- package/dist/adapter/converters/device-parameters.js +12 -1
- 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 +31 -32
- package/dist/adapter/device-helpers/webgl-device-features.js +1 -1
- 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 +368 -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 +1 -3
- package/dist/adapter/resources/webgl-render-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-render-pipeline.js +45 -20
- package/dist/adapter/resources/webgl-shader.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-shader.js +2 -2
- 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 +58 -172
- package/dist/adapter/resources/webgl-texture.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-texture.js +402 -510
- 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-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 +4 -3
- package/dist/adapter/webgl-device.d.ts.map +1 -1
- package/dist/adapter/webgl-device.js +6 -5
- 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 +2 -1
- package/dist/classic/copy-and-blit.d.ts.map +1 -1
- package/dist/classic/copy-and-blit.js +11 -9
- 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.d.ts.map +1 -1
- package/dist/context/debug/spector.js +2 -1
- 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/state-tracker/track-context-state.d.ts.map +1 -1
- package/dist/context/state-tracker/track-context-state.js +5 -6
- package/dist/dist.dev.js +870 -1261
- package/dist/dist.min.js +2 -2
- package/dist/index.cjs +859 -1137
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +0 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -3
- 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/package.json +6 -5
- package/src/adapter/converters/device-parameters.ts +13 -1
- package/src/adapter/converters/texture-formats.ts +45 -42
- package/src/adapter/device-helpers/webgl-device-features.ts +1 -1
- package/src/adapter/device-helpers/webgl-device-limits.ts +1 -1
- package/src/adapter/helpers/webgl-texture-utils.ts +481 -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 +4 -5
- package/src/adapter/resources/webgl-render-pipeline.ts +48 -23
- package/src/adapter/resources/webgl-shader.ts +3 -3
- package/src/adapter/resources/webgl-texture-view.ts +1 -3
- package/src/adapter/resources/webgl-texture.ts +432 -784
- package/src/adapter/resources/webgl-vertex-array.ts +8 -7
- package/src/adapter/webgl-canvas-context.ts +4 -1
- package/src/adapter/webgl-device.ts +10 -18
- package/src/classic/accessor.ts +31 -11
- package/src/classic/clear.ts +3 -6
- package/src/classic/copy-and-blit.ts +19 -19
- package/src/classic/format-utils.ts +0 -3
- package/src/classic/typed-array-utils.ts +1 -1
- package/src/context/debug/spector.ts +2 -1
- package/src/context/debug/webgl-developer-tools.ts +3 -7
- package/src/context/parameters/webgl-parameter-tables.ts +3 -3
- package/src/context/state-tracker/track-context-state.ts +5 -6
- package/src/index.ts +0 -6
- 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/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/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 = this.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
|
+
}
|
|
339
227
|
}
|
|
340
228
|
|
|
341
|
-
|
|
229
|
+
this.mipmaps = Boolean(props.mipmaps);
|
|
230
|
+
|
|
231
|
+
if (this.mipmaps) {
|
|
232
|
+
this.generateMipmap();
|
|
233
|
+
}
|
|
234
|
+
|
|
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
|
-
|
|
267
|
+
}
|
|
268
|
+
*/
|
|
269
|
+
|
|
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})`;
|
|
364
282
|
}
|
|
365
283
|
|
|
366
|
-
|
|
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,253 @@ 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
|
-
* Allocates storage
|
|
433
|
-
* @param {*} pixels -
|
|
434
|
-
* null - create empty texture of specified format
|
|
435
|
-
* Typed array - init from image data in typed array
|
|
436
|
-
* Buffer|WebGLBuffer - (WEBGL2) init from image data in WebGLBuffer
|
|
437
|
-
* HTMLImageElement|Image - Inits with content of image. Auto width/height
|
|
438
|
-
* HTMLCanvasElement - Inits with contents of canvas. Auto width/height
|
|
439
|
-
* HTMLVideoElement - Creates video texture. Auto width/height
|
|
440
|
-
*
|
|
441
|
-
* @param width -
|
|
442
|
-
* @param height -
|
|
443
|
-
* @param mipMapLevel -
|
|
444
|
-
* @param {GLenum} format - format of image data.
|
|
445
|
-
* @param {GLenum} type
|
|
446
|
-
* - format of array (autodetect from type) or
|
|
447
|
-
* - (WEBGL2) format of buffer
|
|
448
|
-
* @param {Number} offset - (WEBGL2) offset from start of buffer
|
|
449
|
-
* @parameters - temporary settings to be applied, can be used to supply pixel store settings.
|
|
450
|
-
*/
|
|
451
|
-
// eslint-disable-next-line max-statements, complexity
|
|
452
|
-
setImageData(options: SetImageDataOptions) {
|
|
453
|
-
if (this.props.dimension === '3d' || this.props.dimension === '2d-array') {
|
|
454
|
-
return this.setImageData3D(options);
|
|
455
|
-
}
|
|
335
|
+
// Image Data Setters
|
|
456
336
|
|
|
457
|
-
|
|
337
|
+
setTexture1DData(data: Texture1DData): void {
|
|
338
|
+
throw new Error('setTexture1DData not supported in WebGL.');
|
|
339
|
+
}
|
|
458
340
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
level = 0,
|
|
463
|
-
glFormat = this.glFormat,
|
|
464
|
-
offset = 0,
|
|
465
|
-
parameters = {} as Record<GL, any>
|
|
466
|
-
} = options;
|
|
341
|
+
/** Set a simple texture */
|
|
342
|
+
setTexture2DData(lodData: Texture2DData, depth = 0, glTarget = this.glTarget): void {
|
|
343
|
+
this.bind();
|
|
467
344
|
|
|
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;
|
|
345
|
+
const lodArray = normalizeTextureData(lodData, this);
|
|
476
346
|
|
|
477
|
-
//
|
|
478
|
-
|
|
479
|
-
|
|
347
|
+
// If the user provides multiple LODs, then automatic mipmap
|
|
348
|
+
// generation generateMipmap() should be disabled to avoid overwriting them.
|
|
349
|
+
if (lodArray.length > 1 && this.props.mipmaps !== false) {
|
|
350
|
+
log.warn(`Texture ${this.id} mipmap and multiple LODs.`)();
|
|
480
351
|
}
|
|
481
352
|
|
|
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');
|
|
353
|
+
for (let lodLevel = 0; lodLevel < lodArray.length; lodLevel++) {
|
|
354
|
+
const imageData = lodArray[lodLevel];
|
|
355
|
+
this._setMipLevel(depth, lodLevel, imageData);
|
|
580
356
|
}
|
|
581
357
|
|
|
582
|
-
this.
|
|
583
|
-
|
|
584
|
-
return this;
|
|
358
|
+
this.unbind();
|
|
585
359
|
}
|
|
586
360
|
|
|
587
361
|
/**
|
|
588
|
-
*
|
|
589
|
-
*
|
|
590
|
-
* Redefines an area of an existing texture
|
|
362
|
+
* Sets a 3D texture
|
|
363
|
+
* @param data
|
|
591
364
|
*/
|
|
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;
|
|
365
|
+
setTexture3DData(data: Texture3DData): void {
|
|
366
|
+
if (this.props.dimension !== '3d') {
|
|
367
|
+
throw new Error(this.id);
|
|
623
368
|
}
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
if (data && data.data) {
|
|
627
|
-
const ndarray = data;
|
|
628
|
-
data = ndarray.data;
|
|
629
|
-
width = ndarray.shape[0];
|
|
630
|
-
height = ndarray.shape[1];
|
|
369
|
+
if (ArrayBuffer.isView(data)) {
|
|
370
|
+
copyCPUDataToMipLevel(this.device.gl, data, this);
|
|
631
371
|
}
|
|
372
|
+
}
|
|
632
373
|
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
374
|
+
/**
|
|
375
|
+
* Set a Texture Cube Data
|
|
376
|
+
* @todo - could support TextureCubeArray with depth
|
|
377
|
+
* @param data
|
|
378
|
+
* @param index
|
|
379
|
+
*/
|
|
380
|
+
setTextureCubeData(data: TextureCubeData, depth: number = 0): void {
|
|
381
|
+
if (this.props.dimension !== 'cube') {
|
|
382
|
+
throw new Error(this.id);
|
|
636
383
|
}
|
|
637
|
-
|
|
638
|
-
this.
|
|
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);
|
|
384
|
+
// for (const face of Texture.CubeFaces) {
|
|
385
|
+
// // this.setTextureCubeFaceData(face, data[face]);
|
|
386
|
+
// }
|
|
661
387
|
}
|
|
662
388
|
|
|
663
389
|
/**
|
|
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.
|
|
390
|
+
* Sets an entire texture array
|
|
391
|
+
* @param data
|
|
670
392
|
*/
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
393
|
+
setTextureArrayData(data: TextureArrayData): void {
|
|
394
|
+
if (this.props.dimension !== '2d-array') {
|
|
395
|
+
throw new Error(this.id);
|
|
396
|
+
}
|
|
397
|
+
throw new Error('setTextureArrayData not implemented.');
|
|
676
398
|
}
|
|
677
399
|
|
|
678
|
-
|
|
679
|
-
|
|
400
|
+
/**
|
|
401
|
+
* Sets an entire texture cube array
|
|
402
|
+
* @param data
|
|
403
|
+
*/
|
|
404
|
+
setTextureCubeArrayData(data: TextureCubeArrayData): void {
|
|
405
|
+
throw new Error('setTextureCubeArrayData not supported in WebGL2.');
|
|
680
406
|
}
|
|
681
407
|
|
|
682
|
-
|
|
683
|
-
|
|
408
|
+
setTextureCubeFaceData(lodData: Texture2DData, face: TextureCubeFace, depth: number = 0): void {
|
|
409
|
+
// assert(this.props.dimension === 'cube');
|
|
684
410
|
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
411
|
+
// If the user provides multiple LODs, then automatic mipmap
|
|
412
|
+
// generation generateMipmap() should be disabled to avoid overwriting them.
|
|
413
|
+
if (Array.isArray(lodData) && lodData.length > 1 && this.props.mipmaps !== false) {
|
|
414
|
+
log.warn(`${this.id} has mipmap and multiple LODs.`)();
|
|
688
415
|
}
|
|
689
416
|
|
|
690
|
-
|
|
691
|
-
|
|
417
|
+
// const glFace = GL.TEXTURE_CUBE_MAP_POSITIVE_X + Texture.CubeFaces.indexOf(face);
|
|
418
|
+
// const glType = GL.UNSIGNED_BYTE;
|
|
419
|
+
// const {width, height, format = GL.RGBA, type = GL.UNSIGNED_BYTE} = this;
|
|
420
|
+
// const {width, height, format = GL.RGBA, type = GL.UNSIGNED_BYTE} = this;
|
|
421
|
+
|
|
422
|
+
this.bind();
|
|
423
|
+
// for (let lodLevel = 0; lodLevel < lodData.length; lodLevel++) {
|
|
424
|
+
// const imageData = lodData[lodLevel];
|
|
425
|
+
// if (imageData instanceof ArrayBuffer) {
|
|
426
|
+
// // const imageData = image instanceof ArrayBuffer ? new ImageData(new Uint8ClampedArray(image), this.width) : image;
|
|
427
|
+
// this.device.gl.texImage2D?.(
|
|
428
|
+
// glFace,
|
|
429
|
+
// lodLevel,
|
|
430
|
+
// this.glInternalFormat,
|
|
431
|
+
// this.glInternalFormat,
|
|
432
|
+
// glType,
|
|
433
|
+
// imageData
|
|
434
|
+
// );
|
|
435
|
+
// }
|
|
436
|
+
// }
|
|
437
|
+
this.unbind();
|
|
692
438
|
}
|
|
693
439
|
|
|
694
|
-
|
|
695
|
-
const {gl} = this;
|
|
440
|
+
// INTERNAL METHODS
|
|
696
441
|
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
442
|
+
/** @todo update this method to accept LODs */
|
|
443
|
+
setImageDataForFace(options): void {
|
|
444
|
+
const {
|
|
445
|
+
face,
|
|
446
|
+
width,
|
|
447
|
+
height,
|
|
448
|
+
pixels,
|
|
449
|
+
data,
|
|
450
|
+
format = GL.RGBA,
|
|
451
|
+
type = GL.UNSIGNED_BYTE
|
|
452
|
+
// generateMipmap = false // TODO
|
|
453
|
+
} = options;
|
|
701
454
|
|
|
702
|
-
gl
|
|
703
|
-
return textureUnit;
|
|
704
|
-
}
|
|
455
|
+
const {gl} = this;
|
|
705
456
|
|
|
706
|
-
|
|
457
|
+
const imageData = pixels || data;
|
|
707
458
|
|
|
708
|
-
|
|
709
|
-
if (
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
459
|
+
this.bind();
|
|
460
|
+
if (imageData instanceof Promise) {
|
|
461
|
+
imageData.then(resolvedImageData =>
|
|
462
|
+
this.setImageDataForFace(
|
|
463
|
+
Object.assign({}, options, {
|
|
464
|
+
face,
|
|
465
|
+
data: resolvedImageData,
|
|
466
|
+
pixels: resolvedImageData
|
|
467
|
+
})
|
|
468
|
+
)
|
|
469
|
+
);
|
|
470
|
+
} else if (this.width || this.height) {
|
|
471
|
+
gl.texImage2D(face, 0, format, width, height, 0 /* border*/, format, type, imageData);
|
|
472
|
+
} else {
|
|
473
|
+
gl.texImage2D(face, 0, format, format, type, imageData);
|
|
720
474
|
}
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
_getImageDataMap(faceData: Record<string | GL, any>): Record<GL, any> {
|
|
478
|
+
for (let i = 0; i < Texture.CubeFaces.length; ++i) {
|
|
479
|
+
const faceName = Texture.CubeFaces[i];
|
|
480
|
+
if (faceData[faceName]) {
|
|
481
|
+
faceData[GL.TEXTURE_CUBE_MAP_POSITIVE_X + i] = faceData[faceName];
|
|
482
|
+
delete faceData[faceName];
|
|
483
|
+
}
|
|
724
484
|
}
|
|
725
|
-
|
|
726
|
-
return {data, dataType: 'browser-object'};
|
|
485
|
+
return faceData;
|
|
727
486
|
}
|
|
728
487
|
|
|
729
|
-
//
|
|
488
|
+
// RESOURCE METHODS
|
|
730
489
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
490
|
+
/**
|
|
491
|
+
* Sets sampler parameters on texture
|
|
492
|
+
*/
|
|
493
|
+
_setSamplerParameters(parameters: GLSamplerParameters): void {
|
|
494
|
+
log.log(1, 'texture sampler parameters', parameters)();
|
|
734
495
|
|
|
735
|
-
|
|
736
|
-
const
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
compressed = compressed || parameters.compressed;
|
|
496
|
+
this.gl.bindTexture(this.glTarget, this.handle);
|
|
497
|
+
for (const [pname, pvalue] of Object.entries(parameters)) {
|
|
498
|
+
const param = Number(pname) as keyof GLSamplerParameters;
|
|
499
|
+
const value = pvalue;
|
|
740
500
|
|
|
741
|
-
|
|
501
|
+
// Apparently integer/float issues require two different texture parameter setting functions in JavaScript.
|
|
502
|
+
// For now, pick the float version for parameters specified as GLfloat.
|
|
503
|
+
switch (param) {
|
|
504
|
+
case GL.TEXTURE_MIN_LOD:
|
|
505
|
+
case GL.TEXTURE_MAX_LOD:
|
|
506
|
+
this.gl.texParameterf(this.glTarget, param, value);
|
|
507
|
+
break;
|
|
742
508
|
|
|
743
|
-
|
|
744
|
-
|
|
509
|
+
case GL.TEXTURE_MIN_FILTER:
|
|
510
|
+
this.gl.texParameteri(this.glTarget, param, value);
|
|
511
|
+
break;
|
|
745
512
|
|
|
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};
|
|
513
|
+
case GL.TEXTURE_WRAP_S:
|
|
514
|
+
case GL.TEXTURE_WRAP_T:
|
|
515
|
+
this.gl.texParameteri(this.glTarget, param, value);
|
|
516
|
+
break;
|
|
517
|
+
case GL.TEXTURE_MAX_ANISOTROPY_EXT:
|
|
518
|
+
// We have to query feature before using it
|
|
519
|
+
if (this.device.features.has('texture-filterable-anisotropic-webgl')) {
|
|
520
|
+
this.gl.texParameteri(this.glTarget, param, value);
|
|
521
|
+
}
|
|
522
|
+
break;
|
|
523
|
+
default:
|
|
524
|
+
this.gl.texParameteri(this.glTarget, param, value);
|
|
525
|
+
break;
|
|
526
|
+
}
|
|
764
527
|
}
|
|
765
528
|
|
|
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;
|
|
529
|
+
this.gl.bindTexture(this.glTarget, null);
|
|
777
530
|
}
|
|
778
531
|
|
|
779
|
-
//
|
|
532
|
+
// CLASSIC
|
|
780
533
|
|
|
781
|
-
/*
|
|
782
|
-
|
|
783
|
-
width:
|
|
784
|
-
height:
|
|
785
|
-
|
|
786
|
-
data: any;
|
|
534
|
+
/*
|
|
535
|
+
setCubeMapData(options: {
|
|
536
|
+
width: number;
|
|
537
|
+
height: number;
|
|
538
|
+
data: Record<GL, Texture2DData> | Record<TextureCubeFace, Texture2DData>;
|
|
787
539
|
format?: any;
|
|
788
540
|
type?: any;
|
|
789
|
-
|
|
541
|
+
/** @deprecated Use .data *
|
|
542
|
+
pixels: any;
|
|
543
|
+
}): void {
|
|
790
544
|
const {gl} = this;
|
|
791
545
|
|
|
792
546
|
const {width, height, pixels, data, format = GL.RGBA, type = GL.UNSIGNED_BYTE} = options;
|
|
793
|
-
const imageDataMap = pixels || data;
|
|
794
547
|
|
|
795
548
|
// pixel data (imageDataMap) is an Object from Face to Image or Promise.
|
|
796
549
|
// For example:
|
|
@@ -805,13 +558,12 @@ export class WEBGLTexture extends Texture<WEBGLTextureProps> {
|
|
|
805
558
|
// GL.TEXTURE_CUBE_MAP_NEGATIVE_X : [Image-or-Promise-LOD-0, Image-or-Promise-LOD-1],
|
|
806
559
|
// ... }
|
|
807
560
|
|
|
808
|
-
const
|
|
809
|
-
WEBGLTexture.FACES.map(face => {
|
|
810
|
-
const facePixels = imageDataMap[face];
|
|
811
|
-
return Promise.all(Array.isArray(facePixels) ? facePixels : [facePixels]);
|
|
812
|
-
})
|
|
813
|
-
);
|
|
561
|
+
const imageDataMap = this._getImageDataMap(pixels || data);
|
|
814
562
|
|
|
563
|
+
const resolvedFaces = WEBGLTexture.FACES.map(face => {
|
|
564
|
+
const facePixels = imageDataMap[face];
|
|
565
|
+
return Array.isArray(facePixels) ? facePixels : [facePixels];
|
|
566
|
+
});
|
|
815
567
|
this.bind();
|
|
816
568
|
|
|
817
569
|
WEBGLTexture.FACES.forEach((face, index) => {
|
|
@@ -823,7 +575,7 @@ export class WEBGLTexture extends Texture<WEBGLTextureProps> {
|
|
|
823
575
|
resolvedFaces[index].forEach((image, lodLevel) => {
|
|
824
576
|
// TODO: adjust width & height for LOD!
|
|
825
577
|
if (width && height) {
|
|
826
|
-
gl.texImage2D(face, lodLevel, format, width, height, 0 /* border
|
|
578
|
+
gl.texImage2D(face, lodLevel, format, width, height, 0 /* border*, format, type, image);
|
|
827
579
|
} else {
|
|
828
580
|
gl.texImage2D(face, lodLevel, format, format, type, image);
|
|
829
581
|
}
|
|
@@ -832,168 +584,64 @@ export class WEBGLTexture extends Texture<WEBGLTextureProps> {
|
|
|
832
584
|
|
|
833
585
|
this.unbind();
|
|
834
586
|
}
|
|
587
|
+
*/
|
|
835
588
|
|
|
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;
|
|
848
|
-
|
|
849
|
-
const {gl} = this;
|
|
589
|
+
// INTERNAL SETTERS
|
|
850
590
|
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
} else if (this.width || this.height) {
|
|
865
|
-
gl.texImage2D(face, 0, format, width, height, 0 /* border*/, format, type, imageData);
|
|
866
|
-
} else {
|
|
867
|
-
gl.texImage2D(face, 0, format, format, type, imageData);
|
|
591
|
+
/**
|
|
592
|
+
* Copy a region of data from a CPU memory buffer into this texture.
|
|
593
|
+
* @todo - GLUnpackParameters parameters
|
|
594
|
+
*/
|
|
595
|
+
protected _setMipLevel(depth: number, level: number, textureData: Texture2DData, offset = 0) {
|
|
596
|
+
// if (!textureData) {
|
|
597
|
+
// clearMipLevel(this.device.gl, {...this, depth, level});
|
|
598
|
+
// return;
|
|
599
|
+
// }
|
|
600
|
+
|
|
601
|
+
if (Texture.isExternalImage(textureData)) {
|
|
602
|
+
copyCPUImageToMipLevel(this.device.gl, textureData, {...this, depth, level});
|
|
603
|
+
return;
|
|
868
604
|
}
|
|
869
605
|
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
format,
|
|
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');
|
|
606
|
+
// @ts-expect-error
|
|
607
|
+
if (this.isTextureLevelData(textureData)) {
|
|
608
|
+
copyCPUDataToMipLevel(this.device.gl, textureData.data, {
|
|
609
|
+
...this,
|
|
610
|
+
depth,
|
|
611
|
+
level
|
|
612
|
+
});
|
|
613
|
+
return;
|
|
932
614
|
}
|
|
933
615
|
|
|
934
|
-
|
|
616
|
+
throw new Error('Texture: invalid image data');
|
|
617
|
+
}
|
|
618
|
+
// HELPERS
|
|
935
619
|
|
|
936
|
-
|
|
620
|
+
getActiveUnit(): number {
|
|
621
|
+
return this.gl.getParameter(GL.ACTIVE_TEXTURE) - GL.TEXTURE0;
|
|
937
622
|
}
|
|
938
623
|
|
|
939
|
-
|
|
624
|
+
bind(textureUnit?: number): number {
|
|
625
|
+
const {gl} = this;
|
|
940
626
|
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
_setSamplerParameters(parameters: GLSamplerParameters): void {
|
|
945
|
-
// NPOT parameters may populate an empty object
|
|
946
|
-
if (isObjectEmpty(parameters)) {
|
|
947
|
-
return;
|
|
627
|
+
if (textureUnit !== undefined) {
|
|
628
|
+
this.textureUnit = textureUnit;
|
|
629
|
+
gl.activeTexture(gl.TEXTURE0 + textureUnit);
|
|
948
630
|
}
|
|
949
631
|
|
|
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;
|
|
632
|
+
gl.bindTexture(this.glTarget, this.handle);
|
|
633
|
+
return textureUnit;
|
|
634
|
+
}
|
|
956
635
|
|
|
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;
|
|
636
|
+
unbind(textureUnit?: number): number | undefined {
|
|
637
|
+
const {gl} = this;
|
|
964
638
|
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
}
|
|
639
|
+
if (textureUnit !== undefined) {
|
|
640
|
+
this.textureUnit = textureUnit;
|
|
641
|
+
gl.activeTexture(gl.TEXTURE0 + textureUnit);
|
|
969
642
|
}
|
|
970
|
-
this.gl.bindTexture(this.target, null);
|
|
971
|
-
return;
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
643
|
|
|
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);
|
|
644
|
+
gl.bindTexture(this.glTarget, null);
|
|
645
|
+
return textureUnit;
|
|
994
646
|
}
|
|
995
647
|
}
|
|
996
|
-
|
|
997
|
-
function logParameters(parameters: Record<number, GL | number>) {
|
|
998
|
-
log.log(1, 'texture sampler parameters', parameters)();
|
|
999
|
-
}
|