@luma.gl/engine 9.2.5 → 9.3.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/animation-loop/animation-loop.d.ts +11 -5
- package/dist/animation-loop/animation-loop.d.ts.map +1 -1
- package/dist/animation-loop/animation-loop.js +83 -47
- package/dist/animation-loop/animation-loop.js.map +1 -1
- package/dist/animation-loop/make-animation-loop.js +7 -1
- package/dist/animation-loop/make-animation-loop.js.map +1 -1
- package/dist/animation-loop/request-animation-frame.d.ts.map +1 -1
- package/dist/animation-loop/request-animation-frame.js +23 -6
- package/dist/animation-loop/request-animation-frame.js.map +1 -1
- package/dist/compute/computation.d.ts +3 -7
- package/dist/compute/computation.d.ts.map +1 -1
- package/dist/compute/computation.js +16 -13
- package/dist/compute/computation.js.map +1 -1
- package/dist/compute/swap.d.ts +2 -0
- package/dist/compute/swap.d.ts.map +1 -1
- package/dist/compute/swap.js +10 -5
- package/dist/compute/swap.js.map +1 -1
- package/dist/dist.dev.js +2639 -1290
- package/dist/dist.min.js +325 -210
- package/dist/dynamic-texture/dynamic-texture.d.ts +102 -0
- package/dist/dynamic-texture/dynamic-texture.d.ts.map +1 -0
- package/dist/dynamic-texture/dynamic-texture.js +556 -0
- package/dist/dynamic-texture/dynamic-texture.js.map +1 -0
- package/dist/dynamic-texture/texture-data.d.ts +144 -0
- package/dist/dynamic-texture/texture-data.d.ts.map +1 -0
- package/dist/dynamic-texture/texture-data.js +208 -0
- package/dist/dynamic-texture/texture-data.js.map +1 -0
- package/dist/geometries/cone-geometry.d.ts +3 -1
- package/dist/geometries/cone-geometry.d.ts.map +1 -1
- package/dist/geometries/cone-geometry.js.map +1 -1
- package/dist/geometries/cylinder-geometry.d.ts +2 -1
- package/dist/geometries/cylinder-geometry.d.ts.map +1 -1
- package/dist/geometries/cylinder-geometry.js.map +1 -1
- package/dist/geometry/gpu-geometry.d.ts.map +1 -1
- package/dist/geometry/gpu-geometry.js +8 -3
- package/dist/geometry/gpu-geometry.js.map +1 -1
- package/dist/index.cjs +2497 -1212
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +20 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -4
- package/dist/index.js.map +1 -1
- package/dist/material/material-factory.d.ts +73 -0
- package/dist/material/material-factory.d.ts.map +1 -0
- package/dist/material/material-factory.js +111 -0
- package/dist/material/material-factory.js.map +1 -0
- package/dist/material/material.d.ts +84 -0
- package/dist/material/material.d.ts.map +1 -0
- package/dist/material/material.js +176 -0
- package/dist/material/material.js.map +1 -0
- package/dist/model/model.d.ts +47 -16
- package/dist/model/model.d.ts.map +1 -1
- package/dist/model/model.js +113 -47
- package/dist/model/model.js.map +1 -1
- package/dist/model/split-uniforms-and-bindings.d.ts +4 -3
- package/dist/model/split-uniforms-and-bindings.d.ts.map +1 -1
- package/dist/model/split-uniforms-and-bindings.js +2 -2
- package/dist/model/split-uniforms-and-bindings.js.map +1 -1
- package/dist/models/billboard-texture-model.d.ts +8 -5
- package/dist/models/billboard-texture-model.d.ts.map +1 -1
- package/dist/models/billboard-texture-model.js +77 -23
- package/dist/models/billboard-texture-model.js.map +1 -1
- package/dist/models/billboard-texture-module.d.ts +1 -1
- package/dist/models/billboard-texture-module.js +1 -1
- package/dist/models/clip-space.js +7 -7
- package/dist/models/directional-light-model.d.ts +7 -0
- package/dist/models/directional-light-model.d.ts.map +1 -0
- package/dist/models/directional-light-model.js +23 -0
- package/dist/models/directional-light-model.js.map +1 -0
- package/dist/models/light-model-utils.d.ts +69 -0
- package/dist/models/light-model-utils.d.ts.map +1 -0
- package/dist/models/light-model-utils.js +395 -0
- package/dist/models/light-model-utils.js.map +1 -0
- package/dist/models/point-light-model.d.ts +7 -0
- package/dist/models/point-light-model.d.ts.map +1 -0
- package/dist/models/point-light-model.js +22 -0
- package/dist/models/point-light-model.js.map +1 -0
- package/dist/models/spot-light-model.d.ts +7 -0
- package/dist/models/spot-light-model.d.ts.map +1 -0
- package/dist/models/spot-light-model.js +23 -0
- package/dist/models/spot-light-model.js.map +1 -0
- package/dist/modules/picking/color-picking.d.ts +5 -9
- package/dist/modules/picking/color-picking.d.ts.map +1 -1
- package/dist/modules/picking/color-picking.js +122 -115
- package/dist/modules/picking/color-picking.js.map +1 -1
- package/dist/modules/picking/index-picking.d.ts +4 -4
- package/dist/modules/picking/index-picking.d.ts.map +1 -1
- package/dist/modules/picking/index-picking.js +36 -16
- package/dist/modules/picking/index-picking.js.map +1 -1
- package/dist/modules/picking/legacy-color-picking.d.ts +26 -0
- package/dist/modules/picking/legacy-color-picking.d.ts.map +1 -0
- package/dist/modules/picking/legacy-color-picking.js +7 -0
- package/dist/modules/picking/legacy-color-picking.js.map +1 -0
- package/dist/modules/picking/picking-manager.d.ts +29 -3
- package/dist/modules/picking/picking-manager.d.ts.map +1 -1
- package/dist/modules/picking/picking-manager.js +188 -41
- package/dist/modules/picking/picking-manager.js.map +1 -1
- package/dist/modules/picking/picking-uniforms.d.ts +13 -12
- package/dist/modules/picking/picking-uniforms.d.ts.map +1 -1
- package/dist/modules/picking/picking-uniforms.js +27 -14
- package/dist/modules/picking/picking-uniforms.js.map +1 -1
- package/dist/modules/picking/picking.d.ts +25 -0
- package/dist/modules/picking/picking.d.ts.map +1 -0
- package/dist/modules/picking/picking.js +18 -0
- package/dist/modules/picking/picking.js.map +1 -0
- package/dist/passes/get-fragment-shader.js +12 -27
- package/dist/passes/get-fragment-shader.js.map +1 -1
- package/dist/passes/shader-pass-renderer.d.ts +5 -7
- package/dist/passes/shader-pass-renderer.d.ts.map +1 -1
- package/dist/passes/shader-pass-renderer.js +16 -42
- package/dist/passes/shader-pass-renderer.js.map +1 -1
- package/dist/scenegraph/group-node.d.ts +5 -0
- package/dist/scenegraph/group-node.d.ts.map +1 -1
- package/dist/scenegraph/group-node.js +12 -0
- package/dist/scenegraph/group-node.js.map +1 -1
- package/dist/scenegraph/model-node.d.ts +2 -2
- package/dist/scenegraph/model-node.d.ts.map +1 -1
- package/dist/scenegraph/model-node.js.map +1 -1
- package/dist/scenegraph/scenegraph-node.d.ts +1 -1
- package/dist/scenegraph/scenegraph-node.d.ts.map +1 -1
- package/dist/scenegraph/scenegraph-node.js +23 -15
- package/dist/scenegraph/scenegraph-node.js.map +1 -1
- package/dist/shader-inputs.d.ts +9 -7
- package/dist/shader-inputs.d.ts.map +1 -1
- package/dist/shader-inputs.js +84 -4
- package/dist/shader-inputs.js.map +1 -1
- package/dist/utils/buffer-layout-order.d.ts.map +1 -1
- package/dist/utils/buffer-layout-order.js +12 -2
- package/dist/utils/buffer-layout-order.js.map +1 -1
- package/dist/utils/shader-module-utils.d.ts +7 -0
- package/dist/utils/shader-module-utils.d.ts.map +1 -0
- package/dist/utils/shader-module-utils.js +46 -0
- package/dist/utils/shader-module-utils.js.map +1 -0
- package/package.json +6 -6
- package/src/animation-loop/animation-loop.ts +89 -50
- package/src/animation-loop/make-animation-loop.ts +13 -5
- package/src/animation-loop/request-animation-frame.ts +32 -6
- package/src/compute/computation.ts +32 -17
- package/src/compute/swap.ts +13 -7
- package/src/dynamic-texture/dynamic-texture.ts +732 -0
- package/src/dynamic-texture/texture-data.ts +336 -0
- package/src/geometries/cone-geometry.ts +6 -1
- package/src/geometries/cylinder-geometry.ts +5 -1
- package/src/geometry/gpu-geometry.ts +8 -3
- package/src/index.ts +38 -8
- package/src/material/material-factory.ts +157 -0
- package/src/material/material.ts +254 -0
- package/src/model/model.ts +158 -67
- package/src/model/split-uniforms-and-bindings.ts +8 -6
- package/src/models/billboard-texture-model.ts +88 -27
- package/src/models/billboard-texture-module.ts +1 -1
- package/src/models/clip-space.ts +7 -7
- package/src/models/directional-light-model.ts +32 -0
- package/src/models/light-model-utils.ts +587 -0
- package/src/models/point-light-model.ts +31 -0
- package/src/models/spot-light-model.ts +32 -0
- package/src/modules/picking/color-picking.ts +123 -122
- package/src/modules/picking/index-picking.ts +36 -16
- package/src/modules/picking/legacy-color-picking.ts +8 -0
- package/src/modules/picking/picking-manager.ts +252 -50
- package/src/modules/picking/picking-uniforms.ts +39 -24
- package/src/modules/picking/picking.ts +22 -0
- package/src/passes/get-fragment-shader.ts +12 -27
- package/src/passes/shader-pass-renderer.ts +25 -48
- package/src/scenegraph/group-node.ts +16 -0
- package/src/scenegraph/model-node.ts +2 -2
- package/src/scenegraph/scenegraph-node.ts +27 -16
- package/src/shader-inputs.ts +165 -15
- package/src/utils/buffer-layout-order.ts +18 -2
- package/src/utils/shader-module-utils.ts +65 -0
- package/dist/async-texture/async-texture.d.ts +0 -166
- package/dist/async-texture/async-texture.d.ts.map +0 -1
- package/dist/async-texture/async-texture.js +0 -386
- package/dist/async-texture/async-texture.js.map +0 -1
- package/dist/factories/pipeline-factory.d.ts +0 -37
- package/dist/factories/pipeline-factory.d.ts.map +0 -1
- package/dist/factories/pipeline-factory.js +0 -181
- package/dist/factories/pipeline-factory.js.map +0 -1
- package/dist/factories/shader-factory.d.ts +0 -22
- package/dist/factories/shader-factory.d.ts.map +0 -1
- package/dist/factories/shader-factory.js +0 -88
- package/dist/factories/shader-factory.js.map +0 -1
- package/src/async-texture/async-texture.ts +0 -551
- package/src/factories/pipeline-factory.ts +0 -224
- package/src/factories/shader-factory.ts +0 -103
- /package/src/{async-texture/texture-setters.ts.disabled → dynamic-texture/texture-data.ts.disabled} +0 -0
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import type {TypedArray, TextureFormat, ExternalImage} from '@luma.gl/core';
|
|
2
|
+
import {isExternalImage, getExternalImageSize} from '@luma.gl/core';
|
|
3
|
+
|
|
4
|
+
export type TextureImageSource = ExternalImage;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* One mip level
|
|
8
|
+
* Basic data structure is similar to `ImageData`
|
|
9
|
+
* additional optional fields can describe compressed texture data.
|
|
10
|
+
*/
|
|
11
|
+
export type TextureImageData = {
|
|
12
|
+
/** Preferred WebGPU style format string. */
|
|
13
|
+
textureFormat?: TextureFormat;
|
|
14
|
+
/** WebGPU style format string. Defaults to 'rgba8unorm' */
|
|
15
|
+
format?: TextureFormat;
|
|
16
|
+
/** Typed Array with the bytes of the image. @note beware row byte alignment requirements */
|
|
17
|
+
data: TypedArray;
|
|
18
|
+
/** Width of the image, in pixels, @note beware row byte alignment requirements */
|
|
19
|
+
width: number;
|
|
20
|
+
/** Height of the image, in rows */
|
|
21
|
+
height: number;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* A single mip-level can be initialized by data or an ImageBitmap etc
|
|
26
|
+
* @note in the WebGPU spec a mip-level is called a subresource
|
|
27
|
+
*/
|
|
28
|
+
export type TextureMipLevelData = TextureImageData | TextureImageSource;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Texture data for one image "slice" (which can consist of multiple miplevels)
|
|
32
|
+
* Thus data for one slice be a single mip level or an array of miplevels
|
|
33
|
+
* @note in the WebGPU spec each cross-section image in a 3D texture is called a "slice",
|
|
34
|
+
* in a array texture each image in the array is called an array "layer"
|
|
35
|
+
* luma.gl calls one image in a GPU texture a "slice" regardless of context.
|
|
36
|
+
*/
|
|
37
|
+
export type TextureSliceData = TextureMipLevelData | TextureMipLevelData[];
|
|
38
|
+
|
|
39
|
+
/** Names of cube texture faces */
|
|
40
|
+
export type TextureCubeFace = '+X' | '-X' | '+Y' | '-Y' | '+Z' | '-Z';
|
|
41
|
+
|
|
42
|
+
/** Array of cube texture faces. @note: index in array is the face index */
|
|
43
|
+
// prettier-ignore
|
|
44
|
+
export const TEXTURE_CUBE_FACES = ['+X', '-X', '+Y', '-Y', '+Z', '-Z'] as const satisfies readonly TextureCubeFace[];
|
|
45
|
+
|
|
46
|
+
/** Map of cube texture face names to face indexes */
|
|
47
|
+
// prettier-ignore
|
|
48
|
+
export const TEXTURE_CUBE_FACE_MAP = {'+X': 0, '-X': 1, '+Y': 2, '-Y': 3, '+Z': 4, '-Z': 5} as const satisfies Record<TextureCubeFace, number>;
|
|
49
|
+
|
|
50
|
+
/** @todo - Define what data type is supported for 1D textures. TextureImageData with height = 1 */
|
|
51
|
+
export type Texture1DData = TextureSliceData;
|
|
52
|
+
|
|
53
|
+
/** Texture data can be one or more mip levels */
|
|
54
|
+
export type Texture2DData = TextureSliceData;
|
|
55
|
+
|
|
56
|
+
/** 6 face textures */
|
|
57
|
+
export type TextureCubeData = Record<TextureCubeFace, TextureSliceData>;
|
|
58
|
+
|
|
59
|
+
/** Array of textures */
|
|
60
|
+
export type Texture3DData = TextureSliceData[];
|
|
61
|
+
|
|
62
|
+
/** Array of textures */
|
|
63
|
+
export type TextureArrayData = TextureSliceData[];
|
|
64
|
+
|
|
65
|
+
/** Array of 6 face textures */
|
|
66
|
+
export type TextureCubeArrayData = Record<TextureCubeFace, TextureSliceData>[];
|
|
67
|
+
|
|
68
|
+
type TextureData =
|
|
69
|
+
| Texture1DData
|
|
70
|
+
| Texture3DData
|
|
71
|
+
| TextureArrayData
|
|
72
|
+
| TextureCubeArrayData
|
|
73
|
+
| TextureCubeData;
|
|
74
|
+
|
|
75
|
+
/** Sync data props */
|
|
76
|
+
export type TextureDataProps =
|
|
77
|
+
| {dimension: '1d'; data: Texture1DData | null}
|
|
78
|
+
| {dimension?: '2d'; data: Texture2DData | null}
|
|
79
|
+
| {dimension: '3d'; data: Texture3DData | null}
|
|
80
|
+
| {dimension: '2d-array'; data: TextureArrayData | null}
|
|
81
|
+
| {dimension: 'cube'; data: TextureCubeData | null}
|
|
82
|
+
| {dimension: 'cube-array'; data: TextureCubeArrayData | null};
|
|
83
|
+
|
|
84
|
+
/** Async data props */
|
|
85
|
+
export type TextureDataAsyncProps =
|
|
86
|
+
| {dimension: '1d'; data?: Promise<Texture1DData> | Texture1DData | null}
|
|
87
|
+
| {dimension?: '2d'; data?: Promise<Texture2DData> | Texture2DData | null}
|
|
88
|
+
| {dimension: '3d'; data?: Promise<Texture3DData> | Texture3DData | null}
|
|
89
|
+
| {dimension: '2d-array'; data?: Promise<TextureArrayData> | TextureArrayData | null}
|
|
90
|
+
| {dimension: 'cube'; data?: Promise<TextureCubeData> | TextureCubeData | null}
|
|
91
|
+
| {dimension: 'cube-array'; data?: Promise<TextureCubeArrayData> | TextureCubeArrayData | null};
|
|
92
|
+
|
|
93
|
+
/** Describes data for one sub resource (one mip level of one slice (depth or array layer)) */
|
|
94
|
+
export type TextureSubresource = {
|
|
95
|
+
/** slice (depth or array layer)) */
|
|
96
|
+
z: number;
|
|
97
|
+
/** mip level (0 - max mip levels) */
|
|
98
|
+
mipLevel: number;
|
|
99
|
+
} & (
|
|
100
|
+
| {
|
|
101
|
+
type: 'external-image';
|
|
102
|
+
image: ExternalImage;
|
|
103
|
+
/** @deprecated is this an appropriate place for this flag? */
|
|
104
|
+
flipY?: boolean;
|
|
105
|
+
}
|
|
106
|
+
| {
|
|
107
|
+
type: 'texture-data';
|
|
108
|
+
data: TextureImageData;
|
|
109
|
+
textureFormat?: TextureFormat;
|
|
110
|
+
}
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
/** Check if texture data is a typed array */
|
|
114
|
+
export function isTextureSliceData(data: TextureData): data is TextureImageData {
|
|
115
|
+
const typedArray = (data as TextureImageData)?.data;
|
|
116
|
+
return ArrayBuffer.isView(typedArray);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function getFirstMipLevel(layer: TextureSliceData | null): TextureMipLevelData | null {
|
|
120
|
+
if (!layer) return null;
|
|
121
|
+
return Array.isArray(layer) ? (layer[0] ?? null) : layer;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function getTextureSizeFromData(
|
|
125
|
+
props: TextureDataProps
|
|
126
|
+
): {width: number; height: number} | null {
|
|
127
|
+
const {dimension, data} = props;
|
|
128
|
+
if (!data) {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
switch (dimension) {
|
|
133
|
+
case '1d': {
|
|
134
|
+
const mipLevel = getFirstMipLevel(data);
|
|
135
|
+
if (!mipLevel) return null;
|
|
136
|
+
const {width} = getTextureMipLevelSize(mipLevel);
|
|
137
|
+
return {width, height: 1};
|
|
138
|
+
}
|
|
139
|
+
case '2d': {
|
|
140
|
+
const mipLevel = getFirstMipLevel(data);
|
|
141
|
+
return mipLevel ? getTextureMipLevelSize(mipLevel) : null;
|
|
142
|
+
}
|
|
143
|
+
case '3d':
|
|
144
|
+
case '2d-array': {
|
|
145
|
+
if (!Array.isArray(data) || data.length === 0) return null;
|
|
146
|
+
const mipLevel = getFirstMipLevel(data[0]);
|
|
147
|
+
return mipLevel ? getTextureMipLevelSize(mipLevel) : null;
|
|
148
|
+
}
|
|
149
|
+
case 'cube': {
|
|
150
|
+
const face = (Object.keys(data)[0] as TextureCubeFace) ?? null;
|
|
151
|
+
if (!face) return null;
|
|
152
|
+
const faceData = (data as Record<TextureCubeFace, TextureSliceData>)[face];
|
|
153
|
+
const mipLevel = getFirstMipLevel(faceData);
|
|
154
|
+
return mipLevel ? getTextureMipLevelSize(mipLevel) : null;
|
|
155
|
+
}
|
|
156
|
+
case 'cube-array': {
|
|
157
|
+
if (!Array.isArray(data) || data.length === 0) return null;
|
|
158
|
+
const firstCube = data[0];
|
|
159
|
+
const face = (Object.keys(firstCube)[0] as TextureCubeFace) ?? null;
|
|
160
|
+
if (!face) return null;
|
|
161
|
+
const mipLevel = getFirstMipLevel(firstCube[face]);
|
|
162
|
+
return mipLevel ? getTextureMipLevelSize(mipLevel) : null;
|
|
163
|
+
}
|
|
164
|
+
default:
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function getTextureMipLevelSize(data: TextureMipLevelData): {width: number; height: number} {
|
|
170
|
+
if (isExternalImage(data)) {
|
|
171
|
+
return getExternalImageSize(data);
|
|
172
|
+
}
|
|
173
|
+
if (typeof data === 'object' && 'width' in data && 'height' in data) {
|
|
174
|
+
return {width: data.width, height: data.height};
|
|
175
|
+
}
|
|
176
|
+
throw new Error('Unsupported mip-level data');
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** Type guard: is a mip-level `TextureImageData` (vs ExternalImage or bare typed array) */
|
|
180
|
+
function isTextureImageData(data: unknown): data is TextureImageData {
|
|
181
|
+
return (
|
|
182
|
+
typeof data === 'object' &&
|
|
183
|
+
data !== null &&
|
|
184
|
+
'data' in data &&
|
|
185
|
+
'width' in data &&
|
|
186
|
+
'height' in data
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function isTypedArrayMipLevelData(data: unknown): data is TypedArray {
|
|
191
|
+
return ArrayBuffer.isView(data);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export function resolveTextureImageFormat(data: TextureImageData): TextureFormat | undefined {
|
|
195
|
+
const {textureFormat, format} = data;
|
|
196
|
+
if (textureFormat && format && textureFormat !== format) {
|
|
197
|
+
throw new Error(
|
|
198
|
+
`Conflicting texture formats "${textureFormat}" and "${format}" provided for the same mip level`
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
return textureFormat ?? format;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** Resolve size for a single mip-level datum */
|
|
205
|
+
// function getTextureMipLevelSizeFromData(data: TextureMipLevelData): {
|
|
206
|
+
// width: number;
|
|
207
|
+
// height: number;
|
|
208
|
+
// } {
|
|
209
|
+
// if (this.device.isExternalImage(data)) {
|
|
210
|
+
// return this.device.getExternalImageSize(data);
|
|
211
|
+
// }
|
|
212
|
+
// if (this.isTextureImageData(data)) {
|
|
213
|
+
// return {width: data.width, height: data.height};
|
|
214
|
+
// }
|
|
215
|
+
// // Fallback (should not happen with current types)
|
|
216
|
+
// throw new Error('Unsupported mip-level data');
|
|
217
|
+
// }
|
|
218
|
+
|
|
219
|
+
/** Convert cube face label to depth index */
|
|
220
|
+
export function getCubeFaceIndex(face: TextureCubeFace): number {
|
|
221
|
+
const idx = TEXTURE_CUBE_FACE_MAP[face];
|
|
222
|
+
if (idx === undefined) throw new Error(`Invalid cube face: ${face}`);
|
|
223
|
+
return idx;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** Convert cube face label to texture slice index. Index can be used with `setTexture2DData()`. */
|
|
227
|
+
export function getCubeArrayFaceIndex(cubeIndex: number, face: TextureCubeFace): number {
|
|
228
|
+
return 6 * cubeIndex + getCubeFaceIndex(face);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// ------------------ Upload helpers ------------------
|
|
232
|
+
|
|
233
|
+
/** Experimental: Set multiple mip levels (1D) */
|
|
234
|
+
export function getTexture1DSubresources(data: Texture1DData): TextureSubresource[] {
|
|
235
|
+
// Not supported in WebGL; left explicit
|
|
236
|
+
throw new Error('setTexture1DData not supported in WebGL.');
|
|
237
|
+
// const subresources: TextureSubresource[] = [];
|
|
238
|
+
// return subresources;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** Normalize 2D layer payload into an array of mip-level items */
|
|
242
|
+
function _normalizeTexture2DData(
|
|
243
|
+
data: Texture2DData
|
|
244
|
+
): (TextureImageData | ExternalImage | TypedArray)[] {
|
|
245
|
+
return Array.isArray(data) ? data : [data];
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/** Experimental: Set multiple mip levels (2D), optionally at `z` (depth/array index) */
|
|
249
|
+
export function getTexture2DSubresources(
|
|
250
|
+
slice: number,
|
|
251
|
+
lodData: Texture2DData,
|
|
252
|
+
baseLevelSize?: {width: number; height: number},
|
|
253
|
+
textureFormat?: TextureFormat
|
|
254
|
+
): TextureSubresource[] {
|
|
255
|
+
const lodArray = _normalizeTexture2DData(lodData);
|
|
256
|
+
const z = slice;
|
|
257
|
+
|
|
258
|
+
const subresources: TextureSubresource[] = [];
|
|
259
|
+
|
|
260
|
+
for (let mipLevel = 0; mipLevel < lodArray.length; mipLevel++) {
|
|
261
|
+
const imageData = lodArray[mipLevel];
|
|
262
|
+
if (isExternalImage(imageData)) {
|
|
263
|
+
subresources.push({
|
|
264
|
+
type: 'external-image',
|
|
265
|
+
image: imageData,
|
|
266
|
+
z,
|
|
267
|
+
mipLevel
|
|
268
|
+
});
|
|
269
|
+
} else if (isTextureImageData(imageData)) {
|
|
270
|
+
subresources.push({
|
|
271
|
+
type: 'texture-data',
|
|
272
|
+
data: imageData,
|
|
273
|
+
textureFormat: resolveTextureImageFormat(imageData),
|
|
274
|
+
z,
|
|
275
|
+
mipLevel
|
|
276
|
+
});
|
|
277
|
+
} else if (isTypedArrayMipLevelData(imageData) && baseLevelSize) {
|
|
278
|
+
subresources.push({
|
|
279
|
+
type: 'texture-data',
|
|
280
|
+
data: {
|
|
281
|
+
data: imageData,
|
|
282
|
+
width: Math.max(1, baseLevelSize.width >> mipLevel),
|
|
283
|
+
height: Math.max(1, baseLevelSize.height >> mipLevel),
|
|
284
|
+
...(textureFormat ? {format: textureFormat} : {})
|
|
285
|
+
},
|
|
286
|
+
textureFormat,
|
|
287
|
+
z,
|
|
288
|
+
mipLevel
|
|
289
|
+
});
|
|
290
|
+
} else {
|
|
291
|
+
throw new Error('Unsupported 2D mip-level payload');
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return subresources;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/** 3D: multiple depth slices, each may carry multiple mip levels */
|
|
299
|
+
export function getTexture3DSubresources(data: Texture3DData): TextureSubresource[] {
|
|
300
|
+
const subresources: TextureSubresource[] = [];
|
|
301
|
+
for (let depth = 0; depth < data.length; depth++) {
|
|
302
|
+
subresources.push(...getTexture2DSubresources(depth, data[depth]));
|
|
303
|
+
}
|
|
304
|
+
return subresources;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/** 2D array: multiple layers, each may carry multiple mip levels */
|
|
308
|
+
export function getTextureArraySubresources(data: TextureArrayData): TextureSubresource[] {
|
|
309
|
+
const subresources: TextureSubresource[] = [];
|
|
310
|
+
for (let layer = 0; layer < data.length; layer++) {
|
|
311
|
+
subresources.push(...getTexture2DSubresources(layer, data[layer]));
|
|
312
|
+
}
|
|
313
|
+
return subresources;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/** Cube: 6 faces, each may carry multiple mip levels */
|
|
317
|
+
export function getTextureCubeSubresources(data: TextureCubeData): TextureSubresource[] {
|
|
318
|
+
const subresources: TextureSubresource[] = [];
|
|
319
|
+
for (const [face, faceData] of Object.entries(data) as [TextureCubeFace, TextureSliceData][]) {
|
|
320
|
+
const faceDepth = getCubeFaceIndex(face);
|
|
321
|
+
subresources.push(...getTexture2DSubresources(faceDepth, faceData));
|
|
322
|
+
}
|
|
323
|
+
return subresources;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/** Cube array: multiple cubes (faces×layers), each face may carry multiple mips */
|
|
327
|
+
export function getTextureCubeArraySubresources(data: TextureCubeArrayData): TextureSubresource[] {
|
|
328
|
+
const subresources: TextureSubresource[] = [];
|
|
329
|
+
data.forEach((cubeData, cubeIndex) => {
|
|
330
|
+
for (const [face, faceData] of Object.entries(cubeData)) {
|
|
331
|
+
const faceDepth = getCubeArrayFaceIndex(cubeIndex, face as TextureCubeFace);
|
|
332
|
+
subresources.push(...getTexture2DSubresources(faceDepth, faceData));
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
return subresources;
|
|
336
|
+
}
|
|
@@ -2,13 +2,18 @@
|
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
|
+
import type {TruncatedConeGeometryProps} from './truncated-cone-geometry';
|
|
5
6
|
import {TruncatedConeGeometry} from './truncated-cone-geometry';
|
|
6
7
|
import {uid} from '../utils/uid';
|
|
7
8
|
|
|
8
|
-
export type ConeGeometryProps =
|
|
9
|
+
export type ConeGeometryProps = Omit<
|
|
10
|
+
TruncatedConeGeometryProps,
|
|
11
|
+
'topRadius' | 'bottomRadius' | 'topCap' | 'bottomCap'
|
|
12
|
+
> & {
|
|
9
13
|
id?: string;
|
|
10
14
|
radius?: number;
|
|
11
15
|
cap?: boolean;
|
|
16
|
+
attributes?: any;
|
|
12
17
|
};
|
|
13
18
|
|
|
14
19
|
export class ConeGeometry extends TruncatedConeGeometry {
|
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
|
+
import type {TruncatedConeGeometryProps} from './truncated-cone-geometry';
|
|
5
6
|
import {TruncatedConeGeometry} from './truncated-cone-geometry';
|
|
6
7
|
import {uid} from '../utils/uid';
|
|
7
8
|
|
|
8
|
-
export type CylinderGeometryProps =
|
|
9
|
+
export type CylinderGeometryProps = Omit<
|
|
10
|
+
TruncatedConeGeometryProps,
|
|
11
|
+
'topRadius' | 'bottomRadius'
|
|
12
|
+
> & {
|
|
9
13
|
id?: string;
|
|
10
14
|
radius?: number;
|
|
11
15
|
attributes?: any;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
5
|
import type {PrimitiveTopology, BufferLayout} from '@luma.gl/core';
|
|
6
|
-
import {Device, Buffer,
|
|
6
|
+
import {Device, Buffer, vertexFormatDecoder} from '@luma.gl/core';
|
|
7
7
|
import type {Geometry} from '../geometry/geometry';
|
|
8
8
|
import {uid} from '../utils/uid';
|
|
9
9
|
|
|
@@ -127,8 +127,13 @@ export function getAttributeBuffersFromGeometry(
|
|
|
127
127
|
id: `${attributeName}-buffer`
|
|
128
128
|
});
|
|
129
129
|
const {value, size, normalized} = attribute;
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
if (size === undefined) {
|
|
131
|
+
throw new Error(`Attribute ${attributeName} is missing a size`);
|
|
132
|
+
}
|
|
133
|
+
bufferLayout.push({
|
|
134
|
+
name,
|
|
135
|
+
format: vertexFormatDecoder.getVertexFormatFromAttribute(value, size, normalized)
|
|
136
|
+
});
|
|
132
137
|
}
|
|
133
138
|
}
|
|
134
139
|
|
package/src/index.ts
CHANGED
|
@@ -19,6 +19,10 @@ export {makeAnimationLoop} from './animation-loop/make-animation-loop';
|
|
|
19
19
|
|
|
20
20
|
export type {ModelProps} from './model/model';
|
|
21
21
|
export {Model} from './model/model';
|
|
22
|
+
export type {MaterialProps} from './material/material';
|
|
23
|
+
export {Material} from './material/material';
|
|
24
|
+
export type {MaterialFactoryProps} from './material/material-factory';
|
|
25
|
+
export {MaterialFactory} from './material/material-factory';
|
|
22
26
|
|
|
23
27
|
// Transforms
|
|
24
28
|
export type {BufferTransformProps} from './compute/buffer-transform';
|
|
@@ -26,14 +30,20 @@ export {BufferTransform} from './compute/buffer-transform';
|
|
|
26
30
|
export type {TextureTransformProps} from './compute/texture-transform';
|
|
27
31
|
export {TextureTransform} from './compute/texture-transform';
|
|
28
32
|
|
|
29
|
-
export {PipelineFactory} from './factories/pipeline-factory';
|
|
30
|
-
export {ShaderFactory} from './factories/shader-factory';
|
|
31
|
-
|
|
32
33
|
// Models
|
|
33
34
|
export type {ClipSpaceProps} from './models/clip-space';
|
|
34
35
|
export {ClipSpace} from './models/clip-space';
|
|
35
36
|
export type {BackgroundTextureModelProps} from './models/billboard-texture-model';
|
|
36
37
|
export {BackgroundTextureModel} from './models/billboard-texture-model';
|
|
38
|
+
export type {
|
|
39
|
+
BaseLightModelProps,
|
|
40
|
+
PointLightModelProps,
|
|
41
|
+
SpotLightModelProps,
|
|
42
|
+
DirectionalLightModelProps
|
|
43
|
+
} from './models/light-model-utils';
|
|
44
|
+
export {PointLightModel} from './models/point-light-model';
|
|
45
|
+
export {SpotLightModel} from './models/spot-light-model';
|
|
46
|
+
export {DirectionalLightModel} from './models/directional-light-model';
|
|
37
47
|
|
|
38
48
|
// Scenegraph Core nodes
|
|
39
49
|
export {ScenegraphNode} from './scenegraph/scenegraph-node';
|
|
@@ -83,19 +93,32 @@ export {Computation} from './compute/computation';
|
|
|
83
93
|
export type {
|
|
84
94
|
TextureCubeFace,
|
|
85
95
|
TextureImageData,
|
|
86
|
-
TextureData,
|
|
87
96
|
Texture1DData,
|
|
88
97
|
Texture2DData,
|
|
89
98
|
Texture3DData,
|
|
90
99
|
TextureCubeData,
|
|
91
100
|
TextureArrayData,
|
|
92
101
|
TextureCubeArrayData
|
|
93
|
-
} from './
|
|
102
|
+
} from './dynamic-texture/texture-data';
|
|
94
103
|
|
|
95
|
-
export type {
|
|
96
|
-
export {
|
|
104
|
+
export type {DynamicTextureProps} from './dynamic-texture/dynamic-texture';
|
|
105
|
+
export {DynamicTexture} from './dynamic-texture/dynamic-texture';
|
|
97
106
|
|
|
98
|
-
export {
|
|
107
|
+
export type {
|
|
108
|
+
PickInfo,
|
|
109
|
+
PickingMode,
|
|
110
|
+
ResolvedPickingMode,
|
|
111
|
+
PickingBackend,
|
|
112
|
+
PickingManagerProps,
|
|
113
|
+
ResolvedPickingBackend
|
|
114
|
+
} from './modules/picking/picking-manager';
|
|
115
|
+
export {
|
|
116
|
+
PickingManager,
|
|
117
|
+
supportsIndexPicking,
|
|
118
|
+
resolvePickingMode,
|
|
119
|
+
resolvePickingBackend
|
|
120
|
+
} from './modules/picking/picking-manager';
|
|
121
|
+
export {picking} from './modules/picking/picking';
|
|
99
122
|
export {picking as indexPicking} from './modules/picking/index-picking';
|
|
100
123
|
export {picking as colorPicking} from './modules/picking/color-picking';
|
|
101
124
|
|
|
@@ -107,3 +130,10 @@ export {
|
|
|
107
130
|
// DEPRECATED
|
|
108
131
|
|
|
109
132
|
export {LegacyPickingManager} from './modules/picking/legacy-picking-manager';
|
|
133
|
+
export {legacyColorPicking} from './modules/picking/legacy-color-picking';
|
|
134
|
+
|
|
135
|
+
import {DynamicTexture, type DynamicTextureProps} from './dynamic-texture/dynamic-texture';
|
|
136
|
+
/** @deprecated use DynamicTexture */
|
|
137
|
+
export const AsyncTexture = DynamicTexture;
|
|
138
|
+
/** @deprecated use DynamicTextureProps */
|
|
139
|
+
export type AsyncTextureProps = DynamicTextureProps;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
// luma.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
import type {Binding, BindingsByGroup, Device} from '@luma.gl/core';
|
|
6
|
+
import type {ShaderModule} from '@luma.gl/shadertools';
|
|
7
|
+
import {ShaderInputs} from '../shader-inputs';
|
|
8
|
+
import type {Material, MaterialProps} from './material';
|
|
9
|
+
import {Material as MaterialClass} from './material';
|
|
10
|
+
|
|
11
|
+
type MaterialModuleProps = Partial<Record<string, Record<string, unknown>>>;
|
|
12
|
+
type MaterialBindings = Record<
|
|
13
|
+
string,
|
|
14
|
+
Binding | import('../dynamic-texture/dynamic-texture').DynamicTexture
|
|
15
|
+
>;
|
|
16
|
+
|
|
17
|
+
/** Logical bind-group slot reserved for material-owned bindings. */
|
|
18
|
+
export const MATERIAL_BIND_GROUP = 3;
|
|
19
|
+
|
|
20
|
+
/** Construction props for {@link MaterialFactory}. */
|
|
21
|
+
export type MaterialFactoryProps = {
|
|
22
|
+
/** Shader modules that define the material schema for bind group `3`. */
|
|
23
|
+
modules?: ShaderModule[];
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Creates typed {@link Material} instances for a stable material binding schema.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* const pbrFactory = new MaterialFactory<
|
|
32
|
+
* {pbrMaterial: PBRMaterialUniforms},
|
|
33
|
+
* PBRMaterialBindings
|
|
34
|
+
* >(device, {modules: [pbrMaterial]});
|
|
35
|
+
* const pbr = pbrFactory.createMaterial();
|
|
36
|
+
* pbr.setProps({pbrMaterial: {baseColorFactor: [1, 0, 0, 1]}});
|
|
37
|
+
* const pbrVariant = pbr.clone({bindings: {pbr_baseColorSampler: texture}});
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* const phongFactory = new MaterialFactory<
|
|
43
|
+
* {phongMaterial: PhongMaterialProps},
|
|
44
|
+
* {}
|
|
45
|
+
* >(device, {modules: [phongMaterial]});
|
|
46
|
+
* const phong = phongFactory.createMaterial();
|
|
47
|
+
* phong.setProps({phongMaterial: {ambient: 0.4, diffuse: 0.7}});
|
|
48
|
+
* const phongVariant = phong.clone({moduleProps: {phongMaterial: {shininess: 64}}});
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* const gouraudFactory = new MaterialFactory<
|
|
54
|
+
* {gouraudMaterial: GouraudMaterialProps},
|
|
55
|
+
* {}
|
|
56
|
+
* >(device, {modules: [gouraudMaterial]});
|
|
57
|
+
* const gouraud = gouraudFactory.createMaterial();
|
|
58
|
+
* gouraud.setProps({gouraudMaterial: {ambient: 0.25}});
|
|
59
|
+
* const gouraudVariant = gouraud.clone({moduleProps: {gouraudMaterial: {diffuse: 0.8}}});
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export class MaterialFactory<
|
|
63
|
+
TModuleProps extends MaterialModuleProps = MaterialModuleProps,
|
|
64
|
+
TBindings extends MaterialBindings = MaterialBindings
|
|
65
|
+
> {
|
|
66
|
+
/** Device that creates materials for this schema. */
|
|
67
|
+
readonly device: Device;
|
|
68
|
+
/** Shader modules that define the material schema. */
|
|
69
|
+
readonly modules: ShaderModule[];
|
|
70
|
+
|
|
71
|
+
private _materialBindingNames: Set<string>;
|
|
72
|
+
private _materialModuleNames: Set<string>;
|
|
73
|
+
|
|
74
|
+
constructor(device: Device, props: MaterialFactoryProps = {}) {
|
|
75
|
+
this.device = device;
|
|
76
|
+
this.modules = props.modules || [];
|
|
77
|
+
|
|
78
|
+
const shaderInputs = new ShaderInputs(
|
|
79
|
+
Object.fromEntries(this.modules.map(module => [module.name, module]))
|
|
80
|
+
);
|
|
81
|
+
this._materialBindingNames = getMaterialBindingNames(shaderInputs);
|
|
82
|
+
this._materialModuleNames = getMaterialModuleNames(shaderInputs);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Creates one typed material instance for this factory's schema. */
|
|
86
|
+
createMaterial(
|
|
87
|
+
props: Omit<MaterialProps<TModuleProps, TBindings>, 'factory' | 'modules'> = {}
|
|
88
|
+
): Material<TModuleProps, TBindings> {
|
|
89
|
+
return new MaterialClass<TModuleProps, TBindings>(this.device, {
|
|
90
|
+
...props,
|
|
91
|
+
factory: this
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Returns the logical material-owned resource binding names. */
|
|
96
|
+
getBindingNames(): string[] {
|
|
97
|
+
return Array.from(this._materialBindingNames);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Returns `true` when the supplied binding belongs to this material schema. */
|
|
101
|
+
ownsBinding(bindingName: string): boolean {
|
|
102
|
+
if (this._materialBindingNames.has(bindingName)) {
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const aliasedModuleName = getModuleNameFromUniformBinding(bindingName);
|
|
107
|
+
return aliasedModuleName ? this._materialModuleNames.has(aliasedModuleName) : false;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** Returns `true` when the supplied shader module is owned by this material schema. */
|
|
111
|
+
ownsModule(moduleName: string): boolean {
|
|
112
|
+
return this._materialModuleNames.has(moduleName);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Packages resolved material bindings into bind group `3`. */
|
|
116
|
+
getBindingsByGroup(
|
|
117
|
+
bindings: Partial<{[K in keyof TBindings]: Binding}> & Record<string, Binding>
|
|
118
|
+
): BindingsByGroup {
|
|
119
|
+
return Object.keys(bindings).length > 0 ? {[MATERIAL_BIND_GROUP]: bindings} : {};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Returns the module name corresponding to an auto-generated `*Uniforms` binding. */
|
|
124
|
+
export function getModuleNameFromUniformBinding(bindingName: string): string | null {
|
|
125
|
+
return bindingName.endsWith('Uniforms') ? bindingName.slice(0, -'Uniforms'.length) : null;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function getMaterialBindingNames(shaderInputs: ShaderInputs): Set<string> {
|
|
129
|
+
const bindingNames = new Set<string>();
|
|
130
|
+
|
|
131
|
+
for (const module of Object.values(shaderInputs.modules)) {
|
|
132
|
+
for (const binding of module.bindingLayout || []) {
|
|
133
|
+
if (binding.group === MATERIAL_BIND_GROUP) {
|
|
134
|
+
bindingNames.add(binding.name);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return bindingNames;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function getMaterialModuleNames(shaderInputs: ShaderInputs): Set<string> {
|
|
143
|
+
const moduleNames = new Set<string>();
|
|
144
|
+
|
|
145
|
+
for (const module of Object.values(shaderInputs.modules)) {
|
|
146
|
+
if (
|
|
147
|
+
module.name &&
|
|
148
|
+
module.bindingLayout?.some(
|
|
149
|
+
binding => binding.group === MATERIAL_BIND_GROUP && binding.name === module.name
|
|
150
|
+
)
|
|
151
|
+
) {
|
|
152
|
+
moduleNames.add(module.name);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return moduleNames;
|
|
157
|
+
}
|