@luma.gl/engine 9.1.0-beta.8 → 9.2.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/README.md +5 -0
- package/dist/animation-loop/animation-loop.d.ts +11 -11
- package/dist/animation-loop/animation-loop.d.ts.map +1 -1
- package/dist/animation-loop/animation-loop.js +25 -49
- package/dist/animation-loop/animation-loop.js.map +1 -1
- package/dist/animation-loop/animation-props.d.ts +3 -4
- package/dist/animation-loop/animation-props.d.ts.map +1 -1
- package/dist/async-texture/async-texture.d.ts +106 -2
- package/dist/async-texture/async-texture.d.ts.map +1 -1
- package/dist/async-texture/async-texture.js +278 -5
- package/dist/async-texture/async-texture.js.map +1 -1
- package/dist/compute/computation.d.ts +1 -1
- package/dist/compute/computation.d.ts.map +1 -1
- package/dist/compute/swap.d.ts.map +1 -1
- package/dist/compute/swap.js +6 -2
- package/dist/compute/swap.js.map +1 -1
- package/dist/compute/texture-transform.d.ts.map +1 -1
- package/dist/compute/texture-transform.js +1 -0
- package/dist/compute/texture-transform.js.map +1 -1
- package/dist/debug/copy-texture-to-image.d.ts +23 -1
- package/dist/debug/copy-texture-to-image.d.ts.map +1 -1
- package/dist/debug/copy-texture-to-image.js +37 -1
- package/dist/debug/copy-texture-to-image.js.map +1 -1
- package/dist/dist.dev.js +316 -153
- package/dist/dist.min.js +23 -23
- package/dist/index.cjs +334 -172
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/model/model.d.ts +4 -19
- package/dist/model/model.d.ts.map +1 -1
- package/dist/model/model.js +1 -44
- package/dist/model/model.js.map +1 -1
- package/dist/models/billboard-texture-model.d.ts.map +1 -1
- package/dist/models/billboard-texture-model.js +6 -4
- package/dist/models/billboard-texture-model.js.map +1 -1
- package/dist/modules/picking/legacy-picking-manager.d.ts +1 -1
- package/dist/modules/picking/legacy-picking-manager.d.ts.map +1 -1
- package/dist/modules/picking/legacy-picking-manager.js +1 -1
- package/dist/modules/picking/legacy-picking-manager.js.map +1 -1
- package/dist/modules/picking/picking-manager.d.ts +1 -1
- package/dist/modules/picking/picking-manager.d.ts.map +1 -1
- package/dist/modules/picking/picking-manager.js +1 -1
- package/dist/modules/picking/picking-manager.js.map +1 -1
- package/dist/passes/get-fragment-shader.js +2 -2
- package/dist/passes/shader-pass-renderer.d.ts +4 -4
- package/dist/passes/shader-pass-renderer.d.ts.map +1 -1
- package/dist/passes/shader-pass-renderer.js +15 -5
- package/dist/passes/shader-pass-renderer.js.map +1 -1
- package/dist/shader-inputs.js +1 -1
- package/dist/shader-inputs.js.map +1 -1
- package/package.json +4 -4
- package/src/animation-loop/animation-loop.ts +30 -58
- package/src/animation-loop/animation-props.ts +3 -5
- package/src/async-texture/async-texture.ts +382 -16
- package/src/async-texture/texture-setters.ts.disabled +296 -0
- package/src/compute/computation.ts +1 -1
- package/src/compute/swap.ts +7 -2
- package/src/compute/texture-transform.ts +1 -0
- package/src/debug/copy-texture-to-image.ts +52 -2
- package/src/index.ts +12 -0
- package/src/model/model.ts +4 -55
- package/src/models/billboard-texture-model.ts +6 -4
- package/src/modules/picking/legacy-picking-manager.ts +2 -2
- package/src/modules/picking/picking-manager.ts +2 -2
- package/src/passes/get-fragment-shader.ts +2 -2
- package/src/passes/shader-pass-renderer.ts +18 -8
- package/src/shader-inputs.ts +1 -1
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
// luma.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
import type {Texture, TypedArray, TextureFormat, ExternalImage} from '@luma.gl/core';
|
|
6
|
+
import {isExternalImage, getExternalImageSize} from '@luma.gl/core';
|
|
7
|
+
|
|
8
|
+
/** Names of cube texture faces */
|
|
9
|
+
export type TextureCubeFace = '+X' | '-X' | '+Y' | '-Y' | '+Z' | '-Z';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* One mip level
|
|
13
|
+
* Basic data structure is similar to `ImageData`
|
|
14
|
+
* additional optional fields can describe compressed texture data.
|
|
15
|
+
*/
|
|
16
|
+
export type TextureLevelData = {
|
|
17
|
+
/** WebGPU style format string. Defaults to 'rgba8unorm' */
|
|
18
|
+
format?: TextureFormat;
|
|
19
|
+
data: TypedArray;
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
|
|
23
|
+
compressed?: boolean;
|
|
24
|
+
byteLength?: number;
|
|
25
|
+
hasAlpha?: boolean;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type TextureLevelSource = TextureLevelData | ExternalImage;
|
|
29
|
+
|
|
30
|
+
/** Texture data can be one or more mip levels */
|
|
31
|
+
export type TextureData = TextureLevelData | ExternalImage | (TextureLevelData | ExternalImage)[];
|
|
32
|
+
|
|
33
|
+
/** @todo - define what data type is supported for 1D textures */
|
|
34
|
+
export type Texture1DData = TypedArray | TextureLevelData;
|
|
35
|
+
|
|
36
|
+
/** Texture data can be one or more mip levels */
|
|
37
|
+
export type Texture2DData =
|
|
38
|
+
| TypedArray
|
|
39
|
+
| TextureLevelData
|
|
40
|
+
| ExternalImage
|
|
41
|
+
| (TextureLevelData | ExternalImage)[];
|
|
42
|
+
|
|
43
|
+
/** Array of textures */
|
|
44
|
+
export type Texture3DData = TypedArray | TextureData[];
|
|
45
|
+
|
|
46
|
+
/** 6 face textures */
|
|
47
|
+
export type TextureCubeData = Record<TextureCubeFace, Texture2DData>;
|
|
48
|
+
|
|
49
|
+
/** Array of textures */
|
|
50
|
+
export type TextureArrayData = TextureData[];
|
|
51
|
+
|
|
52
|
+
/** Array of 6 face textures */
|
|
53
|
+
export type TextureCubeArrayData = Record<TextureCubeFace, TextureData>[];
|
|
54
|
+
|
|
55
|
+
export type TextureDataProps =
|
|
56
|
+
| Texture1DProps
|
|
57
|
+
| Texture2DProps
|
|
58
|
+
| Texture3DProps
|
|
59
|
+
| TextureArrayProps
|
|
60
|
+
| TextureCubeProps
|
|
61
|
+
| TextureCubeArrayProps;
|
|
62
|
+
|
|
63
|
+
export type Texture1DProps = {dimension: '1d'; data?: Texture1DData | null};
|
|
64
|
+
export type Texture2DProps = {dimension?: '2d'; data?: Texture2DData | null};
|
|
65
|
+
export type Texture3DProps = {dimension: '3d'; data?: Texture3DData | null};
|
|
66
|
+
export type TextureArrayProps = {dimension: '2d-array'; data?: TextureArrayData | null};
|
|
67
|
+
export type TextureCubeProps = {dimension: 'cube'; data?: TextureCubeData | null};
|
|
68
|
+
export type TextureCubeArrayProps = {dimension: 'cube-array'; data: TextureCubeArrayData | null};
|
|
69
|
+
|
|
70
|
+
export const CubeFaces: TextureCubeFace[] = ['+X', '-X', '+Y', '-Y', '+Z', '-Z'];
|
|
71
|
+
|
|
72
|
+
/** Check if texture data is a typed array */
|
|
73
|
+
export function isTextureLevelData(data: TextureData): data is TextureLevelData {
|
|
74
|
+
const typedArray = (data as TextureLevelData)?.data;
|
|
75
|
+
return ArrayBuffer.isView(typedArray);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Get the size of the texture described by the provided TextureData */
|
|
79
|
+
export function getTextureDataSize(
|
|
80
|
+
data: TextureData | TextureCubeData | TextureArrayData | TextureCubeArrayData | TypedArray
|
|
81
|
+
): {width: number; height: number} | null {
|
|
82
|
+
if (!data) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
if (ArrayBuffer.isView(data)) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
// Recurse into arrays (array of miplevels)
|
|
89
|
+
if (Array.isArray(data)) {
|
|
90
|
+
return getTextureDataSize(data[0]);
|
|
91
|
+
}
|
|
92
|
+
if (isExternalImage(data)) {
|
|
93
|
+
return getExternalImageSize(data);
|
|
94
|
+
}
|
|
95
|
+
if (data && typeof data === 'object' && data.constructor === Object) {
|
|
96
|
+
const textureDataArray = Object.values(data) as Texture2DData[];
|
|
97
|
+
const untypedData = textureDataArray[0] as any;
|
|
98
|
+
return {width: untypedData.width, height: untypedData.height};
|
|
99
|
+
}
|
|
100
|
+
throw new Error('texture size deduction failed');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Normalize TextureData to an array of TextureLevelData / ExternalImages
|
|
105
|
+
* @param data
|
|
106
|
+
* @param options
|
|
107
|
+
* @returns array of TextureLevelData / ExternalImages
|
|
108
|
+
*/
|
|
109
|
+
export function normalizeTextureData(
|
|
110
|
+
data: Texture2DData,
|
|
111
|
+
options: {width: number; height: number; depth: number}
|
|
112
|
+
): (TextureLevelData | ExternalImage)[] {
|
|
113
|
+
let lodArray: (TextureLevelData | ExternalImage)[];
|
|
114
|
+
if (ArrayBuffer.isView(data)) {
|
|
115
|
+
lodArray = [
|
|
116
|
+
{
|
|
117
|
+
// ts-expect-error does data really need to be Uint8ClampedArray?
|
|
118
|
+
data,
|
|
119
|
+
width: options.width,
|
|
120
|
+
height: options.height
|
|
121
|
+
// depth: options.depth
|
|
122
|
+
}
|
|
123
|
+
];
|
|
124
|
+
} else if (!Array.isArray(data)) {
|
|
125
|
+
lodArray = [data];
|
|
126
|
+
} else {
|
|
127
|
+
lodArray = data;
|
|
128
|
+
}
|
|
129
|
+
return lodArray;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Convert luma.gl cubemap face constants to depth index */
|
|
133
|
+
export function getCubeFaceDepth(face: TextureCubeFace): number {
|
|
134
|
+
// prettier-ignore
|
|
135
|
+
switch (face) {
|
|
136
|
+
case '+X': return 0;
|
|
137
|
+
case '-X': return 1;
|
|
138
|
+
case '+Y': return 2;
|
|
139
|
+
case '-Y': return 3;
|
|
140
|
+
case '+Z': return 4;
|
|
141
|
+
case '-Z': return 5;
|
|
142
|
+
default: throw new Error(face);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// EXPERIMENTAL
|
|
147
|
+
|
|
148
|
+
/** Set multiple mip levels */
|
|
149
|
+
export function setTexture1DData(texture: Texture, data: Texture1DData): void {
|
|
150
|
+
throw new Error('setTexture1DData not supported in WebGL.');
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** Set multiple mip levels */
|
|
154
|
+
export function setTexture2DData(texture: Texture, lodData: Texture2DData, depth = 0): void {
|
|
155
|
+
this.bind();
|
|
156
|
+
|
|
157
|
+
const lodArray = Texture.normalizeTextureData(lodData, this);
|
|
158
|
+
|
|
159
|
+
// If the user provides multiple LODs, then automatic mipmap
|
|
160
|
+
// generation generateMipmap() should be disabled to avoid overwriting them.
|
|
161
|
+
if (lodArray.length > 1 && this.props.mipmaps !== false) {
|
|
162
|
+
log.warn(`Texture ${this.id} mipmap and multiple LODs.`)();
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
for (let lodLevel = 0; lodLevel < lodArray.length; lodLevel++) {
|
|
166
|
+
const imageData = lodArray[lodLevel];
|
|
167
|
+
this._setMipLevel(depth, lodLevel, imageData);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
this.unbind();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Sets 3D texture data: multiple depth slices, multiple mip levels
|
|
175
|
+
* @param data
|
|
176
|
+
*/
|
|
177
|
+
export function setTexture3DData(texture: Texture, data: Texture3DData): void {
|
|
178
|
+
if (this.props.dimension !== '3d') {
|
|
179
|
+
throw new Error(this.id);
|
|
180
|
+
}
|
|
181
|
+
if (ArrayBuffer.isView(data)) {
|
|
182
|
+
this.bind();
|
|
183
|
+
copyCPUDataToMipLevel(this.device.gl, data, this);
|
|
184
|
+
this.unbind();
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Set Cube texture data, multiple faces, multiple mip levels
|
|
190
|
+
* @todo - could support TextureCubeArray with depth
|
|
191
|
+
* @param data
|
|
192
|
+
* @param index
|
|
193
|
+
*/
|
|
194
|
+
export function setTextureCubeData(texture: Texture, data: TextureCubeData): void {
|
|
195
|
+
if (this.props.dimension !== 'cube') {
|
|
196
|
+
throw new Error(this.id);
|
|
197
|
+
}
|
|
198
|
+
for (const face of Texture.CubeFaces) {
|
|
199
|
+
this.setTextureCubeFaceData(data[face], face);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Sets texture array data, multiple levels, multiple depth slices
|
|
205
|
+
* @param data
|
|
206
|
+
*/
|
|
207
|
+
export function setTextureArrayData(texture: Texture, data: TextureArrayData): void {
|
|
208
|
+
if (this.props.dimension !== '2d-array') {
|
|
209
|
+
throw new Error(this.id);
|
|
210
|
+
}
|
|
211
|
+
throw new Error('setTextureArrayData not implemented.');
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Sets texture cube array, multiple faces, multiple levels, multiple mip levels
|
|
216
|
+
* @param data
|
|
217
|
+
*/
|
|
218
|
+
export function setTextureCubeArrayData(texture: Texture, data: TextureCubeArrayData): void {
|
|
219
|
+
throw new Error('setTextureCubeArrayData not supported in WebGL2.');
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export function setTextureCubeFaceData(
|
|
223
|
+
texture: Texture,
|
|
224
|
+
lodData: Texture2DData,
|
|
225
|
+
face: TextureCubeFace,
|
|
226
|
+
depth: number = 0
|
|
227
|
+
): void {
|
|
228
|
+
// assert(this.props.dimension === 'cube');
|
|
229
|
+
|
|
230
|
+
// If the user provides multiple LODs, then automatic mipmap
|
|
231
|
+
// generation generateMipmap() should be disabled to avoid overwriting them.
|
|
232
|
+
if (Array.isArray(lodData) && lodData.length > 1 && this.props.mipmaps !== false) {
|
|
233
|
+
log.warn(`${this.id} has mipmap and multiple LODs.`)();
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const faceDepth = Texture.CubeFaces.indexOf(face);
|
|
237
|
+
|
|
238
|
+
this.setTexture2DData(lodData, faceDepth);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// TODO - Remove when texture refactor is complete
|
|
242
|
+
|
|
243
|
+
/*
|
|
244
|
+
setCubeMapData(options: {
|
|
245
|
+
width: number;
|
|
246
|
+
height: number;
|
|
247
|
+
data: Record<GL, Texture2DData> | Record<TextureCubeFace, Texture2DData>;
|
|
248
|
+
format?: any;
|
|
249
|
+
type?: any;
|
|
250
|
+
/** @deprecated Use .data *
|
|
251
|
+
pixels: any;
|
|
252
|
+
}): void {
|
|
253
|
+
const {gl} = this;
|
|
254
|
+
|
|
255
|
+
const {width, height, pixels, data, format = GL.RGBA, type = GL.UNSIGNED_BYTE} = options;
|
|
256
|
+
|
|
257
|
+
// pixel data (imageDataMap) is an Object from Face to Image or Promise.
|
|
258
|
+
// For example:
|
|
259
|
+
// {
|
|
260
|
+
// GL.TEXTURE_CUBE_MAP_POSITIVE_X : Image-or-Promise,
|
|
261
|
+
// GL.TEXTURE_CUBE_MAP_NEGATIVE_X : Image-or-Promise,
|
|
262
|
+
// ... }
|
|
263
|
+
// To provide multiple level-of-details (LODs) this can be Face to Array
|
|
264
|
+
// of Image or Promise, like this
|
|
265
|
+
// {
|
|
266
|
+
// GL.TEXTURE_CUBE_MAP_POSITIVE_X : [Image-or-Promise-LOD-0, Image-or-Promise-LOD-1],
|
|
267
|
+
// GL.TEXTURE_CUBE_MAP_NEGATIVE_X : [Image-or-Promise-LOD-0, Image-or-Promise-LOD-1],
|
|
268
|
+
// ... }
|
|
269
|
+
|
|
270
|
+
const imageDataMap = this._getImageDataMap(pixels || data);
|
|
271
|
+
|
|
272
|
+
const resolvedFaces = WEBGLTexture.FACES.map(face => {
|
|
273
|
+
const facePixels = imageDataMap[face];
|
|
274
|
+
return Array.isArray(facePixels) ? facePixels : [facePixels];
|
|
275
|
+
});
|
|
276
|
+
this.bind();
|
|
277
|
+
|
|
278
|
+
WEBGLTexture.FACES.forEach((face, index) => {
|
|
279
|
+
if (resolvedFaces[index].length > 1 && this.props.mipmaps !== false) {
|
|
280
|
+
// If the user provides multiple LODs, then automatic mipmap
|
|
281
|
+
// generation generateMipmaps() should be disabled to avoid overwritting them.
|
|
282
|
+
log.warn(`${this.id} has mipmap and multiple LODs.`)();
|
|
283
|
+
}
|
|
284
|
+
resolvedFaces[index].forEach((image, lodLevel) => {
|
|
285
|
+
// TODO: adjust width & height for LOD!
|
|
286
|
+
if (width && height) {
|
|
287
|
+
gl.texImage2D(face, lodLevel, format, width, height, 0 /* border*, format, type, image);
|
|
288
|
+
} else {
|
|
289
|
+
gl.texImage2D(face, lodLevel, format, format, type, image);
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
this.unbind();
|
|
295
|
+
}
|
|
296
|
+
*/
|
|
@@ -30,7 +30,7 @@ export type ComputationProps = Omit<ComputePipelineProps, 'shader'> & {
|
|
|
30
30
|
/** shadertool shader modules (added to shader code) */
|
|
31
31
|
modules?: ShaderModule[];
|
|
32
32
|
/** Shadertool module defines (configures shader code)*/
|
|
33
|
-
defines?: Record<string,
|
|
33
|
+
defines?: Record<string, boolean>;
|
|
34
34
|
// TODO - injections, hooks etc?
|
|
35
35
|
|
|
36
36
|
/** Shader inputs, used to generated uniform buffers and bindings */
|
package/src/compute/swap.ts
CHANGED
|
@@ -46,7 +46,9 @@ export class SwapFramebuffers extends Swap<Framebuffer> {
|
|
|
46
46
|
? colorAttachment
|
|
47
47
|
: device.createTexture({
|
|
48
48
|
format: colorAttachment,
|
|
49
|
-
usage: Texture.
|
|
49
|
+
usage: Texture.SAMPLE | Texture.RENDER | Texture.COPY_SRC | Texture.COPY_DST,
|
|
50
|
+
width: 1,
|
|
51
|
+
height: 1
|
|
50
52
|
})
|
|
51
53
|
);
|
|
52
54
|
|
|
@@ -57,7 +59,10 @@ export class SwapFramebuffers extends Swap<Framebuffer> {
|
|
|
57
59
|
? colorAttachment
|
|
58
60
|
: device.createTexture({
|
|
59
61
|
format: colorAttachment,
|
|
60
|
-
usage:
|
|
62
|
+
usage:
|
|
63
|
+
Texture.TEXTURE | Texture.COPY_SRC | Texture.COPY_DST | Texture.RENDER_ATTACHMENT,
|
|
64
|
+
width: 1,
|
|
65
|
+
height: 1
|
|
61
66
|
})
|
|
62
67
|
);
|
|
63
68
|
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
|
-
import {Texture, Framebuffer} from '@luma.gl/core';
|
|
6
|
-
import {flipRows, scalePixels} from './pixel-data-utils';
|
|
5
|
+
import {Texture, Framebuffer, TypedArray} from '@luma.gl/core';
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* Options for copying texture pixels to image
|
|
@@ -71,3 +70,54 @@ export function copyTextureToDataUrl(
|
|
|
71
70
|
|
|
72
71
|
return canvas.toDataURL('image/png');
|
|
73
72
|
}
|
|
73
|
+
|
|
74
|
+
// HELPERS
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Flip rows (can be used on arrays returned from `Framebuffer.readPixels`)
|
|
78
|
+
* https: *stackoverflow.com/questions/41969562/
|
|
79
|
+
* how-can-i-flip-the-result-of-webglrenderingcontext-readpixels
|
|
80
|
+
* @param param0
|
|
81
|
+
*/
|
|
82
|
+
export function flipRows(options: {
|
|
83
|
+
data: TypedArray;
|
|
84
|
+
width: number;
|
|
85
|
+
height: number;
|
|
86
|
+
bytesPerPixel?: number;
|
|
87
|
+
temp?: Uint8Array;
|
|
88
|
+
}): void {
|
|
89
|
+
const {data, width, height, bytesPerPixel = 4, temp} = options;
|
|
90
|
+
const bytesPerRow = width * bytesPerPixel;
|
|
91
|
+
|
|
92
|
+
// make a temp buffer to hold one row
|
|
93
|
+
const tempBuffer = temp || new Uint8Array(bytesPerRow);
|
|
94
|
+
for (let y = 0; y < height / 2; ++y) {
|
|
95
|
+
const topOffset = y * bytesPerRow;
|
|
96
|
+
const bottomOffset = (height - y - 1) * bytesPerRow;
|
|
97
|
+
// make copy of a row on the top half
|
|
98
|
+
tempBuffer.set(data.subarray(topOffset, topOffset + bytesPerRow));
|
|
99
|
+
// copy a row from the bottom half to the top
|
|
100
|
+
data.copyWithin(topOffset, bottomOffset, bottomOffset + bytesPerRow);
|
|
101
|
+
// copy the copy of the top half row to the bottom half
|
|
102
|
+
data.set(tempBuffer, bottomOffset);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function scalePixels(options: {data: TypedArray; width: number; height: number}): {
|
|
107
|
+
data: Uint8Array;
|
|
108
|
+
width: number;
|
|
109
|
+
height: number;
|
|
110
|
+
} {
|
|
111
|
+
const {data, width, height} = options;
|
|
112
|
+
const newWidth = Math.round(width / 2);
|
|
113
|
+
const newHeight = Math.round(height / 2);
|
|
114
|
+
const newData = new Uint8Array(newWidth * newHeight * 4);
|
|
115
|
+
for (let y = 0; y < newHeight; y++) {
|
|
116
|
+
for (let x = 0; x < newWidth; x++) {
|
|
117
|
+
for (let c = 0; c < 4; c++) {
|
|
118
|
+
newData[(y * newWidth + x) * 4 + c] = data[(y * 2 * width + x * 2) * 4 + c];
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return {data: newData, width: newWidth, height: newHeight};
|
|
123
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -80,6 +80,18 @@ export {SwapFramebuffers} from './compute/swap';
|
|
|
80
80
|
export type {ComputationProps} from './compute/computation';
|
|
81
81
|
export {Computation} from './compute/computation';
|
|
82
82
|
|
|
83
|
+
export type {
|
|
84
|
+
TextureCubeFace,
|
|
85
|
+
TextureImageData,
|
|
86
|
+
TextureData,
|
|
87
|
+
Texture1DData,
|
|
88
|
+
Texture2DData,
|
|
89
|
+
Texture3DData,
|
|
90
|
+
TextureCubeData,
|
|
91
|
+
TextureArrayData,
|
|
92
|
+
TextureCubeArrayData
|
|
93
|
+
} from './async-texture/async-texture';
|
|
94
|
+
|
|
83
95
|
export type {AsyncTextureProps} from './async-texture/async-texture';
|
|
84
96
|
export {AsyncTexture} from './async-texture/async-texture';
|
|
85
97
|
|
package/src/model/model.ts
CHANGED
|
@@ -13,7 +13,6 @@ import type {
|
|
|
13
13
|
TransformFeedback,
|
|
14
14
|
AttributeInfo,
|
|
15
15
|
Binding,
|
|
16
|
-
UniformValue,
|
|
17
16
|
PrimitiveTopology
|
|
18
17
|
} from '@luma.gl/core';
|
|
19
18
|
import {
|
|
@@ -44,23 +43,20 @@ import {debugFramebuffer} from '../debug/debug-framebuffer';
|
|
|
44
43
|
import {deepEqual} from '../utils/deep-equal';
|
|
45
44
|
import {uid} from '../utils/uid';
|
|
46
45
|
import {ShaderInputs} from '../shader-inputs';
|
|
47
|
-
// import type {AsyncTextureProps} from '../async-texture/async-texture';
|
|
48
46
|
import {AsyncTexture} from '../async-texture/async-texture';
|
|
49
47
|
|
|
50
|
-
import {splitUniformsAndBindings} from './split-uniforms-and-bindings';
|
|
51
|
-
|
|
52
48
|
const LOG_DRAW_PRIORITY = 2;
|
|
53
49
|
const LOG_DRAW_TIMEOUT = 10000;
|
|
54
50
|
|
|
55
51
|
export type ModelProps = Omit<RenderPipelineProps, 'vs' | 'fs' | 'bindings'> & {
|
|
56
52
|
source?: string;
|
|
57
|
-
vs
|
|
58
|
-
fs
|
|
53
|
+
vs?: string | null;
|
|
54
|
+
fs?: string | null;
|
|
59
55
|
|
|
60
56
|
/** shadertool shader modules (added to shader code) */
|
|
61
57
|
modules?: ShaderModule[];
|
|
62
58
|
/** Shadertool module defines (configures shader code)*/
|
|
63
|
-
defines?: Record<string,
|
|
59
|
+
defines?: Record<string, boolean>;
|
|
64
60
|
// TODO - injections, hooks etc?
|
|
65
61
|
|
|
66
62
|
/** Shader inputs, used to generated uniform buffers and bindings */
|
|
@@ -94,9 +90,6 @@ export type ModelProps = Omit<RenderPipelineProps, 'vs' | 'fs' | 'bindings'> & {
|
|
|
94
90
|
|
|
95
91
|
transformFeedback?: TransformFeedback;
|
|
96
92
|
|
|
97
|
-
/** Mapped uniforms for shadertool modules */
|
|
98
|
-
moduleSettings?: Record<string, Record<string, any>>;
|
|
99
|
-
|
|
100
93
|
/** Show shader source in browser? */
|
|
101
94
|
debugShaders?: 'never' | 'errors' | 'warnings' | 'always';
|
|
102
95
|
|
|
@@ -127,7 +120,6 @@ export class Model {
|
|
|
127
120
|
userData: {},
|
|
128
121
|
defines: {},
|
|
129
122
|
modules: [],
|
|
130
|
-
moduleSettings: undefined!,
|
|
131
123
|
geometry: null,
|
|
132
124
|
indexBuffer: null,
|
|
133
125
|
attributes: {},
|
|
@@ -187,8 +179,6 @@ export class Model {
|
|
|
187
179
|
constantAttributes: Record<string, TypedArray> = {};
|
|
188
180
|
/** Bindings (textures, samplers, uniform buffers) */
|
|
189
181
|
bindings: Record<string, Binding | AsyncTexture> = {};
|
|
190
|
-
/** Sets uniforms @deprecated Use uniform buffers and setBindings() for portability*/
|
|
191
|
-
uniforms: Record<string, UniformValue> = {};
|
|
192
182
|
|
|
193
183
|
/**
|
|
194
184
|
* VertexArray
|
|
@@ -211,7 +201,6 @@ export class Model {
|
|
|
211
201
|
|
|
212
202
|
_attributeInfos: Record<string, AttributeInfo> = {};
|
|
213
203
|
_gpuGeometry: GPUGeometry | null = null;
|
|
214
|
-
private _getModuleUniforms: (props?: Record<string, Record<string, any>>) => Record<string, any>;
|
|
215
204
|
private props: Required<ModelProps>;
|
|
216
205
|
|
|
217
206
|
_pipelineNeedsUpdate: string | false = 'newly created';
|
|
@@ -335,13 +324,6 @@ export class Model {
|
|
|
335
324
|
if (props.bindings) {
|
|
336
325
|
this.setBindings(props.bindings);
|
|
337
326
|
}
|
|
338
|
-
if (props.uniforms) {
|
|
339
|
-
this.setUniformsWebGL(props.uniforms);
|
|
340
|
-
}
|
|
341
|
-
if (props.moduleSettings) {
|
|
342
|
-
// log.warn('Model.props.moduleSettings is deprecated. Use Model.shaderInputs.setProps()')();
|
|
343
|
-
this.updateModuleSettingsWebGL(props.moduleSettings);
|
|
344
|
-
}
|
|
345
327
|
if (props.transformFeedback) {
|
|
346
328
|
this.transformFeedback = props.transformFeedback;
|
|
347
329
|
}
|
|
@@ -423,9 +405,6 @@ export class Model {
|
|
|
423
405
|
this.pipeline.setBindings(syncBindings, {
|
|
424
406
|
disableWarnings: this.props.disableWarnings
|
|
425
407
|
});
|
|
426
|
-
if (!isObjectEmpty(this.uniforms)) {
|
|
427
|
-
this.pipeline.setUniformsWebGL(this.uniforms);
|
|
428
|
-
}
|
|
429
408
|
|
|
430
409
|
const {indexBuffer} = this.vertexArray;
|
|
431
410
|
const indexCount = indexBuffer
|
|
@@ -676,33 +655,7 @@ export class Model {
|
|
|
676
655
|
this.setNeedsRedraw('constants');
|
|
677
656
|
}
|
|
678
657
|
|
|
679
|
-
//
|
|
680
|
-
|
|
681
|
-
/**
|
|
682
|
-
* Sets individual uniforms
|
|
683
|
-
* @deprecated WebGL only, use uniform buffers for portability
|
|
684
|
-
* @param uniforms
|
|
685
|
-
*/
|
|
686
|
-
setUniformsWebGL(uniforms: Record<string, UniformValue>): void {
|
|
687
|
-
if (!isObjectEmpty(uniforms)) {
|
|
688
|
-
this.pipeline.setUniformsWebGL(uniforms);
|
|
689
|
-
Object.assign(this.uniforms, uniforms);
|
|
690
|
-
}
|
|
691
|
-
this.setNeedsRedraw('uniforms');
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
/**
|
|
695
|
-
* @deprecated Updates shader module settings (which results in uniforms being set)
|
|
696
|
-
*/
|
|
697
|
-
updateModuleSettingsWebGL(props: Record<string, any>): void {
|
|
698
|
-
// log.warn('Model.updateModuleSettings is deprecated. Use Model.shaderInputs.setProps()')();
|
|
699
|
-
const {bindings, uniforms} = splitUniformsAndBindings(this._getModuleUniforms(props));
|
|
700
|
-
Object.assign(this.bindings, bindings);
|
|
701
|
-
Object.assign(this.uniforms, uniforms);
|
|
702
|
-
this.setNeedsRedraw('moduleSettings');
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
// Internal methods
|
|
658
|
+
// INTERNAL METHODS
|
|
706
659
|
|
|
707
660
|
/** Check that bindings are loaded. Returns id of first binding that is still loading. */
|
|
708
661
|
_areBindingsLoading(): string | false {
|
|
@@ -868,10 +821,6 @@ export class Model {
|
|
|
868
821
|
log.table(LOG_DRAW_PRIORITY, shaderLayoutTable)();
|
|
869
822
|
|
|
870
823
|
const uniformTable = this.shaderInputs.getDebugTable();
|
|
871
|
-
// Add any global uniforms
|
|
872
|
-
for (const [name, value] of Object.entries(this.uniforms)) {
|
|
873
|
-
uniformTable[name] = {value};
|
|
874
|
-
}
|
|
875
824
|
log.table(LOG_DRAW_PRIORITY, uniformTable)();
|
|
876
825
|
|
|
877
826
|
const attributeTable = this._getAttributeDebugTable();
|
|
@@ -11,7 +11,7 @@ const BACKGROUND_FS_WGSL = /* wgsl */ `\
|
|
|
11
11
|
@group(0) @binding(1) var backgroundTextureSampler: sampler;
|
|
12
12
|
|
|
13
13
|
fn billboardTexture_getTextureUV(coordinates: vec2<f32>) -> vec2<f32> {
|
|
14
|
-
let iTexSize: vec2<u32> = textureDimensions(backgroundTexture, 0)
|
|
14
|
+
let iTexSize: vec2<u32> = textureDimensions(backgroundTexture, 0);
|
|
15
15
|
let texSize: vec2<f32> = vec2<f32>(f32(iTexSize.x), f32(iTexSize.y));
|
|
16
16
|
var position: vec2<f32> = coordinates.xy / texSize;
|
|
17
17
|
return position;
|
|
@@ -32,7 +32,7 @@ uniform sampler2D backgroundTexture;
|
|
|
32
32
|
out vec4 fragColor;
|
|
33
33
|
|
|
34
34
|
vec2 billboardTexture_getTextureUV() {
|
|
35
|
-
ivec2 iTexSize =
|
|
35
|
+
ivec2 iTexSize = textureSize(backgroundTexture, 0);
|
|
36
36
|
vec2 texSize = vec2(float(iTexSize.x), float(iTexSize.y));
|
|
37
37
|
vec2 position = gl_FragCoord.xy / texSize;
|
|
38
38
|
return position;
|
|
@@ -67,14 +67,13 @@ export class BackgroundTextureModel extends ClipSpace {
|
|
|
67
67
|
fs: BACKGROUND_FS,
|
|
68
68
|
parameters: {
|
|
69
69
|
depthWriteEnabled: false,
|
|
70
|
-
depthCompare: 'always',
|
|
71
70
|
...(props.blend
|
|
72
71
|
? {
|
|
73
72
|
blend: true,
|
|
74
73
|
blendColorOperation: 'add',
|
|
75
74
|
blendAlphaOperation: 'add',
|
|
76
75
|
blendColorSrcFactor: 'one',
|
|
77
|
-
blendColorDstFactor: 'one-minus-src
|
|
76
|
+
blendColorDstFactor: 'one-minus-src',
|
|
78
77
|
blendAlphaSrcFactor: 'one',
|
|
79
78
|
blendAlphaDstFactor: 'one-minus-src-alpha'
|
|
80
79
|
}
|
|
@@ -82,6 +81,9 @@ export class BackgroundTextureModel extends ClipSpace {
|
|
|
82
81
|
}
|
|
83
82
|
});
|
|
84
83
|
|
|
84
|
+
if (!props.backgroundTexture) {
|
|
85
|
+
throw new Error('BackgroundTextureModel requires a backgroundTexture prop');
|
|
86
|
+
}
|
|
85
87
|
this.setTexture(props.backgroundTexture);
|
|
86
88
|
}
|
|
87
89
|
|
|
@@ -42,7 +42,7 @@ export class LegacyPickingManager {
|
|
|
42
42
|
/** Prepare for rendering picking colors */
|
|
43
43
|
beginRenderPass() {
|
|
44
44
|
const framebuffer = this.getFramebuffer();
|
|
45
|
-
framebuffer.resize(this.device.getCanvasContext().
|
|
45
|
+
framebuffer.resize(this.device.getCanvasContext().getDevicePixelSize());
|
|
46
46
|
|
|
47
47
|
this.shaderInputs.setProps({picking: {isActive: true}});
|
|
48
48
|
|
|
@@ -90,7 +90,7 @@ export class LegacyPickingManager {
|
|
|
90
90
|
* Get pick position in device pixel range
|
|
91
91
|
* use the center pixel location in device pixel range
|
|
92
92
|
*/
|
|
93
|
-
getPickPosition(mousePosition: number
|
|
93
|
+
getPickPosition(mousePosition: [number, number]): [number, number] {
|
|
94
94
|
const devicePixels = this.device.getCanvasContext().cssToDevicePixels(mousePosition);
|
|
95
95
|
const pickX = devicePixels.x + Math.floor(devicePixels.width / 2);
|
|
96
96
|
const pickY = devicePixels.y + Math.floor(devicePixels.height / 2);
|
|
@@ -67,7 +67,7 @@ export class PickingManager {
|
|
|
67
67
|
/** Prepare for rendering picking colors */
|
|
68
68
|
beginRenderPass() {
|
|
69
69
|
const framebuffer = this.getFramebuffer();
|
|
70
|
-
framebuffer.resize(this.device.getDefaultCanvasContext().
|
|
70
|
+
framebuffer.resize(this.device.getDefaultCanvasContext().getDevicePixelSize());
|
|
71
71
|
|
|
72
72
|
this.props.shaderInputs?.setProps({picking: {isActive: true}});
|
|
73
73
|
|
|
@@ -128,7 +128,7 @@ export class PickingManager {
|
|
|
128
128
|
* Get pick position in device pixel range
|
|
129
129
|
* use the center pixel location in device pixel range
|
|
130
130
|
*/
|
|
131
|
-
getPickPosition(mousePosition: number
|
|
131
|
+
getPickPosition(mousePosition: [number, number]): [number, number] {
|
|
132
132
|
const devicePixels = this.device.getDefaultCanvasContext().cssToDevicePixels(mousePosition);
|
|
133
133
|
const pickX = devicePixels.x + Math.floor(devicePixels.width / 2);
|
|
134
134
|
const pickY = devicePixels.y + Math.floor(devicePixels.height / 2);
|
|
@@ -37,11 +37,11 @@ export function getFragmentShaderForRenderPass(options: {
|
|
|
37
37
|
function getFilterShaderWGSL(func: string) {
|
|
38
38
|
return /* wgsl */ `\
|
|
39
39
|
// Binding 0:1 is reserved for shader passes
|
|
40
|
-
@group(0) @binding(0) var<uniform> brightnessContrast : brightnessContrastUniforms;
|
|
40
|
+
// @group(0) @binding(0) var<uniform> brightnessContrast : brightnessContrastUniforms;
|
|
41
41
|
@group(0) @binding(1) var texture: texture_2d<f32>;
|
|
42
42
|
@group(0) @binding(2) var sampler: sampler;
|
|
43
43
|
|
|
44
|
-
struct FragmentInputs
|
|
44
|
+
struct FragmentInputs {
|
|
45
45
|
@location(0) fragUV: vec2f,
|
|
46
46
|
@location(1) fragPosition: vec4f,
|
|
47
47
|
@location(2) fragCoordinate: vec4f
|