@luma.gl/engine 9.3.0-alpha.4 → 9.3.0-alpha.8
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 +8 -4
- package/dist/animation-loop/animation-loop.d.ts.map +1 -1
- package/dist/animation-loop/animation-loop.js +73 -43
- 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 +14 -12
- package/dist/compute/computation.js.map +1 -1
- package/dist/dist.dev.js +2310 -1638
- package/dist/dist.min.js +307 -360
- package/dist/dynamic-texture/dynamic-texture.d.ts +12 -5
- package/dist/dynamic-texture/dynamic-texture.d.ts.map +1 -1
- package/dist/dynamic-texture/dynamic-texture.js +222 -55
- package/dist/dynamic-texture/dynamic-texture.js.map +1 -1
- package/dist/dynamic-texture/texture-data.d.ts +8 -1
- package/dist/dynamic-texture/texture-data.d.ts.map +1 -1
- package/dist/dynamic-texture/texture-data.js +27 -2
- package/dist/dynamic-texture/texture-data.js.map +1 -1
- 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 +2897 -2272
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +12 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -3
- 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 +17 -7
- package/dist/model/model.d.ts.map +1 -1
- package/dist/model/model.js +80 -34
- 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.map +1 -1
- package/dist/models/billboard-texture-model.js +10 -8
- package/dist/models/billboard-texture-model.js.map +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 +2 -2
- 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 +12 -11
- package/dist/modules/picking/picking-uniforms.d.ts.map +1 -1
- package/dist/modules/picking/picking-uniforms.js +26 -13
- 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 +11 -30
- package/dist/passes/get-fragment-shader.js.map +1 -1
- package/dist/passes/shader-pass-renderer.d.ts +0 -2
- package/dist/passes/shader-pass-renderer.d.ts.map +1 -1
- package/dist/passes/shader-pass-renderer.js +4 -31
- 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/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 +4 -4
- package/src/animation-loop/animation-loop.ts +78 -46
- 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 +31 -17
- package/src/dynamic-texture/dynamic-texture.ts +301 -68
- package/src/dynamic-texture/texture-data.ts +39 -4
- 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 +29 -4
- package/src/material/material-factory.ts +157 -0
- package/src/material/material.ts +254 -0
- package/src/model/model.ts +122 -50
- package/src/model/split-uniforms-and-bindings.ts +8 -6
- package/src/models/billboard-texture-model.ts +10 -8
- 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 +38 -23
- package/src/modules/picking/picking.ts +22 -0
- package/src/passes/get-fragment-shader.ts +11 -30
- package/src/passes/shader-pass-renderer.ts +4 -33
- 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/shader-module-utils.ts +65 -0
- package/dist/dynamic-texture/mipmaps.d.ts +0 -6
- package/dist/dynamic-texture/mipmaps.d.ts.map +0 -1
- package/dist/dynamic-texture/mipmaps.js +0 -441
- package/dist/dynamic-texture/mipmaps.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 -89
- package/dist/factories/shader-factory.js.map +0 -1
- package/dist/types.d.ts +0 -7
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -5
- package/dist/types.js.map +0 -1
- package/src/dynamic-texture/mipmaps.ts +0 -517
- package/src/factories/pipeline-factory.ts +0 -225
- package/src/factories/shader-factory.ts +0 -105
- package/src/types.ts +0 -11
package/src/model/model.ts
CHANGED
|
@@ -3,19 +3,18 @@
|
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
5
|
// A lot of imports, but then Model is where it all comes together...
|
|
6
|
-
import type
|
|
7
|
-
import type {
|
|
8
|
-
RenderPipelineProps,
|
|
9
|
-
RenderPipelineParameters,
|
|
10
|
-
BufferLayout,
|
|
11
|
-
Shader,
|
|
12
|
-
VertexArray,
|
|
13
|
-
TransformFeedback,
|
|
14
|
-
AttributeInfo,
|
|
15
|
-
Binding,
|
|
16
|
-
PrimitiveTopology
|
|
17
|
-
} from '@luma.gl/core';
|
|
6
|
+
import {type TypedArray} from '@math.gl/types';
|
|
18
7
|
import {
|
|
8
|
+
type RenderPipelineProps,
|
|
9
|
+
type RenderPipelineParameters,
|
|
10
|
+
type BufferLayout,
|
|
11
|
+
type Shader,
|
|
12
|
+
type VertexArray,
|
|
13
|
+
type TransformFeedback,
|
|
14
|
+
type AttributeInfo,
|
|
15
|
+
type Binding,
|
|
16
|
+
type BindingsByGroup,
|
|
17
|
+
type PrimitiveTopology,
|
|
19
18
|
Device,
|
|
20
19
|
DeviceFeature,
|
|
21
20
|
Buffer,
|
|
@@ -24,27 +23,33 @@ import {
|
|
|
24
23
|
Sampler,
|
|
25
24
|
RenderPipeline,
|
|
26
25
|
RenderPass,
|
|
26
|
+
PipelineFactory,
|
|
27
|
+
ShaderFactory,
|
|
27
28
|
UniformStore,
|
|
28
29
|
log,
|
|
29
|
-
|
|
30
|
-
getAttributeInfosFromLayouts
|
|
30
|
+
dataTypeDecoder,
|
|
31
|
+
getAttributeInfosFromLayouts,
|
|
32
|
+
normalizeBindingsByGroup
|
|
31
33
|
} from '@luma.gl/core';
|
|
32
34
|
|
|
33
|
-
import type {ShaderModule, PlatformInfo} from '@luma.gl/shadertools';
|
|
35
|
+
import type {ShaderBindingDebugRow, ShaderModule, PlatformInfo} from '@luma.gl/shadertools';
|
|
34
36
|
import {ShaderAssembler} from '@luma.gl/shadertools';
|
|
35
37
|
|
|
36
38
|
import type {Geometry} from '../geometry/geometry';
|
|
37
39
|
import {GPUGeometry, makeGPUGeometry} from '../geometry/gpu-geometry';
|
|
38
|
-
import {PipelineFactory} from '../factories/pipeline-factory';
|
|
39
|
-
import {ShaderFactory} from '../factories/shader-factory';
|
|
40
40
|
import {getDebugTableForShaderLayout} from '../debug/debug-shader-layout';
|
|
41
41
|
import {debugFramebuffer} from '../debug/debug-framebuffer';
|
|
42
42
|
import {deepEqual} from '../utils/deep-equal';
|
|
43
43
|
import {BufferLayoutHelper} from '../utils/buffer-layout-helper';
|
|
44
44
|
import {sortedBufferLayoutByShaderSourceLocations} from '../utils/buffer-layout-order';
|
|
45
|
+
import {
|
|
46
|
+
mergeShaderModuleBindingsIntoLayout,
|
|
47
|
+
shaderModuleHasUniforms
|
|
48
|
+
} from '../utils/shader-module-utils';
|
|
45
49
|
import {uid} from '../utils/uid';
|
|
46
50
|
import {ShaderInputs} from '../shader-inputs';
|
|
47
51
|
import {DynamicTexture} from '../dynamic-texture/dynamic-texture';
|
|
52
|
+
import {Material} from '../material/material';
|
|
48
53
|
|
|
49
54
|
const LOG_DRAW_PRIORITY = 2;
|
|
50
55
|
const LOG_DRAW_TIMEOUT = 10000;
|
|
@@ -62,8 +67,12 @@ export type ModelProps = Omit<RenderPipelineProps, 'vs' | 'fs' | 'bindings'> & {
|
|
|
62
67
|
|
|
63
68
|
/** Shader inputs, used to generated uniform buffers and bindings */
|
|
64
69
|
shaderInputs?: ShaderInputs;
|
|
70
|
+
/** Material-owned group-3 bindings */
|
|
71
|
+
material?: Material;
|
|
65
72
|
/** Bindings */
|
|
66
73
|
bindings?: Record<string, Binding | DynamicTexture>;
|
|
74
|
+
/** WebGL-only uniforms */
|
|
75
|
+
uniforms?: Record<string, unknown>;
|
|
67
76
|
/** Parameters that are built into the pipeline */
|
|
68
77
|
parameters?: RenderPipelineParameters;
|
|
69
78
|
|
|
@@ -114,7 +123,7 @@ export type ModelProps = Omit<RenderPipelineProps, 'vs' | 'fs' | 'bindings'> & {
|
|
|
114
123
|
* - Reuses and lazily recompiles {@link RenderPipeline | pipelines} as needed.
|
|
115
124
|
* - Integrates with `@luma.gl/shadertools` to assemble GLSL or WGSL from shader modules.
|
|
116
125
|
* - Manages geometry attributes and buffer bindings.
|
|
117
|
-
* - Accepts textures, samplers and uniform buffers as bindings, including `
|
|
126
|
+
* - Accepts textures, samplers and uniform buffers as bindings, including `DynamicTexture`.
|
|
118
127
|
* - Provides detailed debug logging and optional shader source inspection.
|
|
119
128
|
*/
|
|
120
129
|
export class Model {
|
|
@@ -132,6 +141,8 @@ export class Model {
|
|
|
132
141
|
indexBuffer: null,
|
|
133
142
|
attributes: {},
|
|
134
143
|
constantAttributes: {},
|
|
144
|
+
bindings: {},
|
|
145
|
+
uniforms: {},
|
|
135
146
|
varyings: [],
|
|
136
147
|
|
|
137
148
|
isInstanced: undefined!,
|
|
@@ -139,6 +150,7 @@ export class Model {
|
|
|
139
150
|
vertexCount: 0,
|
|
140
151
|
|
|
141
152
|
shaderInputs: undefined!,
|
|
153
|
+
material: undefined!,
|
|
142
154
|
pipelineFactory: undefined!,
|
|
143
155
|
shaderFactory: undefined!,
|
|
144
156
|
transformFeedback: undefined!,
|
|
@@ -212,6 +224,7 @@ export class Model {
|
|
|
212
224
|
/** ShaderInputs instance */
|
|
213
225
|
// @ts-expect-error Assigned in function called by constructor
|
|
214
226
|
shaderInputs: ShaderInputs;
|
|
227
|
+
material: Material | null = null;
|
|
215
228
|
// @ts-expect-error Assigned in function called by constructor
|
|
216
229
|
_uniformStore: UniformStore;
|
|
217
230
|
|
|
@@ -225,6 +238,7 @@ export class Model {
|
|
|
225
238
|
|
|
226
239
|
/** "Time" of last draw. Monotonically increasing timestamp */
|
|
227
240
|
_lastDrawTimestamp: number = -1;
|
|
241
|
+
private _bindingTable: ShaderBindingDebugRow[] = [];
|
|
228
242
|
|
|
229
243
|
get [Symbol.toStringTag](): string {
|
|
230
244
|
return 'Model';
|
|
@@ -242,6 +256,8 @@ export class Model {
|
|
|
242
256
|
|
|
243
257
|
Object.assign(this.userData, props.userData);
|
|
244
258
|
|
|
259
|
+
this.material = props.material || null;
|
|
260
|
+
|
|
245
261
|
// Setup shader module inputs
|
|
246
262
|
const moduleMap = Object.fromEntries(
|
|
247
263
|
this.props.modules?.map(module => [module.name, module]) || []
|
|
@@ -261,6 +277,9 @@ export class Model {
|
|
|
261
277
|
// @ts-ignore shaderInputs is assigned in setShaderInputs above.
|
|
262
278
|
(this.props.modules?.length > 0 ? this.props.modules : this.shaderInputs?.getModules()) || [];
|
|
263
279
|
|
|
280
|
+
this.props.shaderLayout =
|
|
281
|
+
mergeShaderModuleBindingsIntoLayout(this.props.shaderLayout, modules) || null;
|
|
282
|
+
|
|
264
283
|
const isWebGPU = this.device.type === 'webgpu';
|
|
265
284
|
|
|
266
285
|
// WebGPU
|
|
@@ -268,7 +287,7 @@ export class Model {
|
|
|
268
287
|
// TODO - this is wrong, compile a single shader
|
|
269
288
|
if (isWebGPU && this.props.source) {
|
|
270
289
|
// WGSL
|
|
271
|
-
const {source, getUniforms} = this.props.shaderAssembler.assembleWGSLShader({
|
|
290
|
+
const {source, getUniforms, bindingTable} = this.props.shaderAssembler.assembleWGSLShader({
|
|
272
291
|
platformInfo,
|
|
273
292
|
...this.props,
|
|
274
293
|
modules
|
|
@@ -276,9 +295,16 @@ export class Model {
|
|
|
276
295
|
this.source = source;
|
|
277
296
|
// @ts-expect-error
|
|
278
297
|
this._getModuleUniforms = getUniforms;
|
|
298
|
+
this._bindingTable = bindingTable;
|
|
279
299
|
// Extract shader layout after modules have been added to WGSL source, to include any bindings added by modules
|
|
280
|
-
|
|
281
|
-
|
|
300
|
+
const inferredShaderLayout = (
|
|
301
|
+
device as Device & {getShaderLayout?: (source: string) => any}
|
|
302
|
+
).getShaderLayout?.(this.source);
|
|
303
|
+
this.props.shaderLayout =
|
|
304
|
+
mergeShaderModuleBindingsIntoLayout(
|
|
305
|
+
this.props.shaderLayout || inferredShaderLayout || null,
|
|
306
|
+
modules
|
|
307
|
+
) || null;
|
|
282
308
|
} else {
|
|
283
309
|
// GLSL
|
|
284
310
|
const {vs, fs, getUniforms} = this.props.shaderAssembler.assembleGLSLShaderPair({
|
|
@@ -291,6 +317,7 @@ export class Model {
|
|
|
291
317
|
this.fs = fs;
|
|
292
318
|
// @ts-expect-error
|
|
293
319
|
this._getModuleUniforms = getUniforms;
|
|
320
|
+
this._bindingTable = [];
|
|
294
321
|
}
|
|
295
322
|
|
|
296
323
|
this.vertexCount = this.props.vertexCount;
|
|
@@ -357,7 +384,7 @@ export class Model {
|
|
|
357
384
|
this.pipelineFactory.release(this.pipeline);
|
|
358
385
|
// Release the shaders
|
|
359
386
|
this.shaderFactory.release(this.pipeline.vs);
|
|
360
|
-
if (this.pipeline.fs) {
|
|
387
|
+
if (this.pipeline.fs && this.pipeline.fs !== this.pipeline.vs) {
|
|
361
388
|
this.shaderFactory.release(this.pipeline.fs);
|
|
362
389
|
}
|
|
363
390
|
this._uniformStore.destroy();
|
|
@@ -385,6 +412,11 @@ export class Model {
|
|
|
385
412
|
this._needsRedraw ||= reason;
|
|
386
413
|
}
|
|
387
414
|
|
|
415
|
+
/** Returns WGSL binding debug rows for the assembled shader. Returns an empty array for GLSL models. */
|
|
416
|
+
getBindingDebugTable(): readonly ShaderBindingDebugRow[] {
|
|
417
|
+
return this._bindingTable;
|
|
418
|
+
}
|
|
419
|
+
|
|
388
420
|
/** Update uniforms and pipeline state prior to drawing. */
|
|
389
421
|
predraw(): void {
|
|
390
422
|
// Update uniform buffers if needed
|
|
@@ -422,14 +454,8 @@ export class Model {
|
|
|
422
454
|
// Application can call Model.predraw() to avoid this.
|
|
423
455
|
this.pipeline = this._updatePipeline();
|
|
424
456
|
|
|
425
|
-
// Set pipeline state, we may be sharing a pipeline so we need to set all state on every draw
|
|
426
|
-
// Any caching needs to be done inside the pipeline functions
|
|
427
|
-
// TODO this is a busy initialized check for all bindings every frame
|
|
428
|
-
|
|
429
457
|
const syncBindings = this._getBindings();
|
|
430
|
-
this.
|
|
431
|
-
disableWarnings: this.props.disableWarnings
|
|
432
|
-
});
|
|
458
|
+
const syncBindGroups = this._getBindGroups();
|
|
433
459
|
|
|
434
460
|
const {indexBuffer} = this.vertexArray;
|
|
435
461
|
const indexCount = indexBuffer
|
|
@@ -444,6 +470,13 @@ export class Model {
|
|
|
444
470
|
instanceCount: this.instanceCount,
|
|
445
471
|
indexCount,
|
|
446
472
|
transformFeedback: this.transformFeedback || undefined,
|
|
473
|
+
// Pipelines may be shared across models when caching is enabled, so bindings
|
|
474
|
+
// and WebGL uniforms must be supplied on every draw instead of being stored
|
|
475
|
+
// on the pipeline instance.
|
|
476
|
+
bindings: syncBindings,
|
|
477
|
+
bindGroups: syncBindGroups,
|
|
478
|
+
_bindGroupCacheKeys: this._getBindGroupCacheKeys(),
|
|
479
|
+
uniforms: this.props.uniforms,
|
|
447
480
|
// WebGL shares underlying cached pipelines even for models that have different parameters and topology,
|
|
448
481
|
// so we must provide our unique parameters to each draw
|
|
449
482
|
// (In WebGPU most parameters are encoded in the pipeline and cannot be changed per draw call)
|
|
@@ -571,7 +604,7 @@ export class Model {
|
|
|
571
604
|
this._uniformStore = new UniformStore(this.shaderInputs.modules);
|
|
572
605
|
// Create uniform buffer bindings for all modules that actually have uniforms
|
|
573
606
|
for (const [moduleName, module] of Object.entries(this.shaderInputs.modules)) {
|
|
574
|
-
if (shaderModuleHasUniforms(module)) {
|
|
607
|
+
if (shaderModuleHasUniforms(module) && !this.material?.ownsModule(moduleName)) {
|
|
575
608
|
const uniformBuffer = this._uniformStore.getManagedUniformBuffer(this.device, moduleName);
|
|
576
609
|
this.bindings[`${moduleName}Uniforms`] = uniformBuffer;
|
|
577
610
|
}
|
|
@@ -579,10 +612,15 @@ export class Model {
|
|
|
579
612
|
this.setNeedsRedraw('shaderInputs');
|
|
580
613
|
}
|
|
581
614
|
|
|
615
|
+
setMaterial(material: Material | null): void {
|
|
616
|
+
this.material = material;
|
|
617
|
+
this.setNeedsRedraw('material');
|
|
618
|
+
}
|
|
619
|
+
|
|
582
620
|
/** Update uniform buffers from the model's shader inputs */
|
|
583
621
|
updateShaderInputs(): void {
|
|
584
622
|
this._uniformStore.setUniforms(this.shaderInputs.getUniformValues());
|
|
585
|
-
this.setBindings(this.shaderInputs.getBindingValues());
|
|
623
|
+
this.setBindings(this._getNonMaterialBindings(this.shaderInputs.getBindingValues()));
|
|
586
624
|
// TODO - this is already tracked through buffer/texture update times?
|
|
587
625
|
this.setNeedsRedraw('shaderInputs');
|
|
588
626
|
}
|
|
@@ -701,6 +739,11 @@ export class Model {
|
|
|
701
739
|
return binding.id;
|
|
702
740
|
}
|
|
703
741
|
}
|
|
742
|
+
for (const binding of Object.values(this.material?.bindings || {})) {
|
|
743
|
+
if (binding instanceof DynamicTexture && !binding.isReady) {
|
|
744
|
+
return binding.id;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
704
747
|
return false;
|
|
705
748
|
}
|
|
706
749
|
|
|
@@ -722,6 +765,32 @@ export class Model {
|
|
|
722
765
|
return validBindings;
|
|
723
766
|
}
|
|
724
767
|
|
|
768
|
+
_getBindGroups(): BindingsByGroup {
|
|
769
|
+
const shaderLayout = this.pipeline?.shaderLayout || this.props.shaderLayout || {bindings: []};
|
|
770
|
+
const bindGroups = shaderLayout.bindings.length
|
|
771
|
+
? normalizeBindingsByGroup(shaderLayout, this._getBindings())
|
|
772
|
+
: {0: this._getBindings()};
|
|
773
|
+
|
|
774
|
+
if (!this.material) {
|
|
775
|
+
return bindGroups;
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
for (const [groupKey, groupBindings] of Object.entries(this.material.getBindingsByGroup())) {
|
|
779
|
+
const group = Number(groupKey);
|
|
780
|
+
bindGroups[group] = {
|
|
781
|
+
...(bindGroups[group] || {}),
|
|
782
|
+
...groupBindings
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
return bindGroups;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
_getBindGroupCacheKeys(): Partial<Record<number, object>> {
|
|
790
|
+
const bindGroupCacheKey = this.material?.getBindGroupCacheKey(3);
|
|
791
|
+
return bindGroupCacheKey ? {3: bindGroupCacheKey} : {};
|
|
792
|
+
}
|
|
793
|
+
|
|
725
794
|
/** Get the timestamp of the latest updated bound GPU memory resource (buffer/texture). */
|
|
726
795
|
_getBindingsUpdateTimestamp(): number {
|
|
727
796
|
let timestamp = 0;
|
|
@@ -739,7 +808,7 @@ export class Model {
|
|
|
739
808
|
timestamp = Math.max(timestamp, binding.buffer.updateTimestamp);
|
|
740
809
|
}
|
|
741
810
|
}
|
|
742
|
-
return timestamp;
|
|
811
|
+
return Math.max(timestamp, this.material?.getBindingsUpdateTimestamp() || 0);
|
|
743
812
|
}
|
|
744
813
|
|
|
745
814
|
/**
|
|
@@ -811,12 +880,11 @@ export class Model {
|
|
|
811
880
|
|
|
812
881
|
this.pipeline = this.pipelineFactory.createRenderPipeline({
|
|
813
882
|
...this.props,
|
|
883
|
+
bindings: undefined,
|
|
814
884
|
bufferLayout: this.bufferLayout,
|
|
815
885
|
topology: this.topology,
|
|
816
886
|
parameters: this.parameters,
|
|
817
|
-
|
|
818
|
-
// Should we expose a BindGroup abstraction?
|
|
819
|
-
bindings: this._getBindings(),
|
|
887
|
+
bindGroups: this._getBindGroups(),
|
|
820
888
|
vs,
|
|
821
889
|
fs
|
|
822
890
|
});
|
|
@@ -827,7 +895,9 @@ export class Model {
|
|
|
827
895
|
);
|
|
828
896
|
|
|
829
897
|
if (prevShaderVs) this.shaderFactory.release(prevShaderVs);
|
|
830
|
-
if (prevShaderFs
|
|
898
|
+
if (prevShaderFs && prevShaderFs !== prevShaderVs) {
|
|
899
|
+
this.shaderFactory.release(prevShaderFs);
|
|
900
|
+
}
|
|
831
901
|
}
|
|
832
902
|
return this.pipeline;
|
|
833
903
|
}
|
|
@@ -915,15 +985,27 @@ export class Model {
|
|
|
915
985
|
|
|
916
986
|
// TODO - fix typing of luma data types
|
|
917
987
|
_getBufferOrConstantValues(attribute: Buffer | TypedArray, dataType: any): string {
|
|
918
|
-
const TypedArrayConstructor = getTypedArrayConstructor(dataType);
|
|
988
|
+
const TypedArrayConstructor = dataTypeDecoder.getTypedArrayConstructor(dataType);
|
|
919
989
|
const typedArray =
|
|
920
990
|
attribute instanceof Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
|
|
921
991
|
return typedArray.toString();
|
|
922
992
|
}
|
|
923
|
-
}
|
|
924
993
|
|
|
925
|
-
|
|
926
|
-
|
|
994
|
+
private _getNonMaterialBindings(
|
|
995
|
+
bindings: Record<string, Binding | DynamicTexture>
|
|
996
|
+
): Record<string, Binding | DynamicTexture> {
|
|
997
|
+
if (!this.material) {
|
|
998
|
+
return bindings;
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
const filteredBindings: Record<string, Binding | DynamicTexture> = {};
|
|
1002
|
+
for (const [name, binding] of Object.entries(bindings)) {
|
|
1003
|
+
if (!this.material.ownsBinding(name)) {
|
|
1004
|
+
filteredBindings[name] = binding;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
return filteredBindings;
|
|
1008
|
+
}
|
|
927
1009
|
}
|
|
928
1010
|
|
|
929
1011
|
// HELPERS
|
|
@@ -939,13 +1021,3 @@ export function getPlatformInfo(device: Device): PlatformInfo {
|
|
|
939
1021
|
features: device.features as unknown as Set<DeviceFeature>
|
|
940
1022
|
};
|
|
941
1023
|
}
|
|
942
|
-
|
|
943
|
-
/** Returns true if given object is empty, false otherwise. */
|
|
944
|
-
function isObjectEmpty(obj: object): boolean {
|
|
945
|
-
// @ts-ignore key is unused
|
|
946
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
947
|
-
for (const key in obj) {
|
|
948
|
-
return false;
|
|
949
|
-
}
|
|
950
|
-
return true;
|
|
951
|
-
}
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
|
-
import type {
|
|
5
|
+
import type {Binding, CompositeShaderType, UniformValue} from '@luma.gl/core';
|
|
6
|
+
import type {ShaderModuleUniformValue} from '@luma.gl/shadertools';
|
|
6
7
|
import {isNumericArray} from '@math.gl/types';
|
|
7
8
|
|
|
8
9
|
export function isUniformValue(value: unknown): value is UniformValue {
|
|
@@ -11,19 +12,20 @@ export function isUniformValue(value: unknown): value is UniformValue {
|
|
|
11
12
|
|
|
12
13
|
type UniformsAndBindings = {
|
|
13
14
|
bindings: Record<string, Binding>;
|
|
14
|
-
uniforms: Record<string,
|
|
15
|
+
uniforms: Record<string, ShaderModuleUniformValue>;
|
|
15
16
|
};
|
|
16
17
|
|
|
17
18
|
export function splitUniformsAndBindings(
|
|
18
|
-
uniforms: Record<string, Binding |
|
|
19
|
+
uniforms: Record<string, Binding | ShaderModuleUniformValue>,
|
|
20
|
+
uniformTypes: Readonly<Record<string, CompositeShaderType>> = {}
|
|
19
21
|
): UniformsAndBindings {
|
|
20
22
|
const result: UniformsAndBindings = {bindings: {}, uniforms: {}};
|
|
21
23
|
Object.keys(uniforms).forEach(name => {
|
|
22
24
|
const uniform = uniforms[name];
|
|
23
|
-
if (isUniformValue(uniform)) {
|
|
24
|
-
result.uniforms[name] = uniform;
|
|
25
|
+
if (Object.prototype.hasOwnProperty.call(uniformTypes, name) || isUniformValue(uniform)) {
|
|
26
|
+
result.uniforms[name] = uniform as ShaderModuleUniformValue;
|
|
25
27
|
} else {
|
|
26
|
-
result.bindings[name] = uniform;
|
|
28
|
+
result.bindings[name] = uniform as Binding;
|
|
27
29
|
}
|
|
28
30
|
});
|
|
29
31
|
|
|
@@ -22,15 +22,15 @@ struct backgroundUniforms {
|
|
|
22
22
|
};
|
|
23
23
|
@group(0) @binding(2) var<uniform> background: backgroundUniforms;
|
|
24
24
|
|
|
25
|
-
fn billboardTexture_getTextureUV(
|
|
25
|
+
fn billboardTexture_getTextureUV(uv: vec2<f32>) -> vec2<f32> {
|
|
26
26
|
let scale: vec2<f32> = background.scale;
|
|
27
|
-
var position: vec2<f32> = (
|
|
27
|
+
var position: vec2<f32> = (uv - vec2<f32>(0.5, 0.5)) / scale + vec2<f32>(0.5, 0.5);
|
|
28
28
|
return position;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
@fragment
|
|
32
32
|
fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4<f32> {
|
|
33
|
-
let position: vec2<f32> = billboardTexture_getTextureUV(inputs.
|
|
33
|
+
let position: vec2<f32> = billboardTexture_getTextureUV(inputs.uv);
|
|
34
34
|
return textureSample(backgroundTexture, backgroundTextureSampler, position);
|
|
35
35
|
}
|
|
36
36
|
`;
|
|
@@ -79,21 +79,23 @@ export class BackgroundTextureModel extends ClipSpace {
|
|
|
79
79
|
|
|
80
80
|
constructor(device: Device, props: BackgroundTextureModelProps) {
|
|
81
81
|
super(device, {
|
|
82
|
+
...props,
|
|
82
83
|
id: props.id || 'background-texture-model',
|
|
83
84
|
source: BACKGROUND_FS_WGSL,
|
|
84
85
|
fs: BACKGROUND_FS,
|
|
85
|
-
modules: [backgroundModule],
|
|
86
|
+
modules: [...(props.modules || []), backgroundModule],
|
|
86
87
|
parameters: {
|
|
87
88
|
depthWriteEnabled: false,
|
|
89
|
+
...(props.parameters || {}),
|
|
88
90
|
...(props.blend
|
|
89
91
|
? {
|
|
90
92
|
blend: true,
|
|
91
93
|
blendColorOperation: 'add',
|
|
92
94
|
blendAlphaOperation: 'add',
|
|
93
|
-
blendColorSrcFactor: 'one',
|
|
94
|
-
blendColorDstFactor: 'one
|
|
95
|
-
blendAlphaSrcFactor: 'one',
|
|
96
|
-
blendAlphaDstFactor: 'one
|
|
95
|
+
blendColorSrcFactor: 'one-minus-dst-alpha',
|
|
96
|
+
blendColorDstFactor: 'one',
|
|
97
|
+
blendAlphaSrcFactor: 'one-minus-dst-alpha',
|
|
98
|
+
blendAlphaDstFactor: 'one'
|
|
97
99
|
}
|
|
98
100
|
: {})
|
|
99
101
|
}
|
package/src/models/clip-space.ts
CHANGED
|
@@ -10,9 +10,9 @@ import {uid} from '../utils/uid';
|
|
|
10
10
|
|
|
11
11
|
const CLIPSPACE_VERTEX_SHADER_WGSL = /* wgsl */ `\
|
|
12
12
|
struct VertexInputs {
|
|
13
|
-
@location(0)
|
|
14
|
-
@location(1)
|
|
15
|
-
@location(2)
|
|
13
|
+
@location(0) clipSpacePositions: vec2<f32>,
|
|
14
|
+
@location(1) texCoords: vec2<f32>,
|
|
15
|
+
@location(2) coordinates: vec2<f32>
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
struct FragmentInputs {
|
|
@@ -25,10 +25,10 @@ struct FragmentInputs {
|
|
|
25
25
|
@vertex
|
|
26
26
|
fn vertexMain(inputs: VertexInputs) -> FragmentInputs {
|
|
27
27
|
var outputs: FragmentInputs;
|
|
28
|
-
outputs.Position = vec4(inputs.
|
|
29
|
-
outputs.position = inputs.
|
|
30
|
-
outputs.coordinate = inputs.
|
|
31
|
-
outputs.uv = inputs.
|
|
28
|
+
outputs.Position = vec4(inputs.clipSpacePositions, 0., 1.);
|
|
29
|
+
outputs.position = inputs.clipSpacePositions;
|
|
30
|
+
outputs.coordinate = inputs.coordinates;
|
|
31
|
+
outputs.uv = inputs.texCoords;
|
|
32
32
|
return outputs;
|
|
33
33
|
}
|
|
34
34
|
`;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// luma.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
import {Device} from '@luma.gl/core';
|
|
6
|
+
import {ConeGeometry} from '../geometries/cone-geometry';
|
|
7
|
+
import {
|
|
8
|
+
BaseLightModel,
|
|
9
|
+
buildDirectionalLightInstanceData,
|
|
10
|
+
type DirectionalLightModelProps
|
|
11
|
+
} from './light-model-utils';
|
|
12
|
+
|
|
13
|
+
const DIRECTIONAL_LIGHT_GEOMETRY = new ConeGeometry({
|
|
14
|
+
cap: true,
|
|
15
|
+
nradial: 12,
|
|
16
|
+
nvertical: 1,
|
|
17
|
+
radius: 1
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export type {DirectionalLightModelProps} from './light-model-utils';
|
|
21
|
+
|
|
22
|
+
export class DirectionalLightModel extends BaseLightModel<DirectionalLightModelProps> {
|
|
23
|
+
constructor(device: Device, props: DirectionalLightModelProps) {
|
|
24
|
+
super(device, props, {
|
|
25
|
+
anchorMode: 'apex',
|
|
26
|
+
buildInstanceData: buildDirectionalLightInstanceData,
|
|
27
|
+
geometry: DIRECTIONAL_LIGHT_GEOMETRY,
|
|
28
|
+
idPrefix: 'directional-light-model',
|
|
29
|
+
sizePropNames: ['directionalLightLength']
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|