@luma.gl/engine 9.2.6 → 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
package/dist/index.cjs
CHANGED
|
@@ -35,22 +35,26 @@ __export(dist_exports, {
|
|
|
35
35
|
ConeGeometry: () => ConeGeometry,
|
|
36
36
|
CubeGeometry: () => CubeGeometry,
|
|
37
37
|
CylinderGeometry: () => CylinderGeometry,
|
|
38
|
+
DirectionalLightModel: () => DirectionalLightModel,
|
|
39
|
+
DynamicTexture: () => DynamicTexture,
|
|
38
40
|
GPUGeometry: () => GPUGeometry,
|
|
39
41
|
Geometry: () => Geometry,
|
|
40
42
|
GroupNode: () => GroupNode,
|
|
41
43
|
IcoSphereGeometry: () => IcoSphereGeometry,
|
|
42
44
|
KeyFrames: () => KeyFrames,
|
|
43
45
|
LegacyPickingManager: () => LegacyPickingManager,
|
|
46
|
+
Material: () => Material,
|
|
47
|
+
MaterialFactory: () => MaterialFactory,
|
|
44
48
|
Model: () => Model,
|
|
45
49
|
ModelNode: () => ModelNode,
|
|
46
50
|
PickingManager: () => PickingManager,
|
|
47
|
-
PipelineFactory: () => PipelineFactory,
|
|
48
51
|
PlaneGeometry: () => PlaneGeometry,
|
|
52
|
+
PointLightModel: () => PointLightModel,
|
|
49
53
|
ScenegraphNode: () => ScenegraphNode,
|
|
50
|
-
ShaderFactory: () => ShaderFactory,
|
|
51
54
|
ShaderInputs: () => ShaderInputs,
|
|
52
55
|
ShaderPassRenderer: () => ShaderPassRenderer,
|
|
53
56
|
SphereGeometry: () => SphereGeometry,
|
|
57
|
+
SpotLightModel: () => SpotLightModel,
|
|
54
58
|
Swap: () => Swap,
|
|
55
59
|
SwapBuffers: () => SwapBuffers,
|
|
56
60
|
SwapFramebuffers: () => SwapFramebuffers,
|
|
@@ -58,14 +62,19 @@ __export(dist_exports, {
|
|
|
58
62
|
Timeline: () => Timeline,
|
|
59
63
|
TruncatedConeGeometry: () => TruncatedConeGeometry,
|
|
60
64
|
cancelAnimationFramePolyfill: () => cancelAnimationFramePolyfill,
|
|
61
|
-
colorPicking: () =>
|
|
62
|
-
indexPicking: () =>
|
|
65
|
+
colorPicking: () => picking,
|
|
66
|
+
indexPicking: () => picking2,
|
|
67
|
+
legacyColorPicking: () => legacyColorPicking,
|
|
63
68
|
loadImage: () => loadImage,
|
|
64
69
|
loadImageBitmap: () => loadImageBitmap,
|
|
65
70
|
makeAnimationLoop: () => makeAnimationLoop,
|
|
66
71
|
makeRandomGenerator: () => makeRandomGenerator,
|
|
72
|
+
picking: () => picking3,
|
|
67
73
|
requestAnimationFramePolyfill: () => requestAnimationFramePolyfill,
|
|
68
|
-
|
|
74
|
+
resolvePickingBackend: () => resolvePickingBackend,
|
|
75
|
+
resolvePickingMode: () => resolvePickingMode,
|
|
76
|
+
setPathPrefix: () => setPathPrefix,
|
|
77
|
+
supportsIndexPicking: () => supportsIndexPicking
|
|
69
78
|
});
|
|
70
79
|
module.exports = __toCommonJS(dist_exports);
|
|
71
80
|
|
|
@@ -245,15 +254,25 @@ var import_core = require("@luma.gl/core");
|
|
|
245
254
|
|
|
246
255
|
// dist/animation-loop/request-animation-frame.js
|
|
247
256
|
function requestAnimationFramePolyfill(callback) {
|
|
248
|
-
|
|
257
|
+
const browserRequestAnimationFrame = typeof window !== "undefined" ? window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame : null;
|
|
258
|
+
if (browserRequestAnimationFrame) {
|
|
259
|
+
return browserRequestAnimationFrame.call(window, callback);
|
|
260
|
+
}
|
|
261
|
+
return setTimeout(() => callback(typeof performance !== "undefined" ? performance.now() : Date.now()), 1e3 / 60);
|
|
249
262
|
}
|
|
250
263
|
function cancelAnimationFramePolyfill(timerId) {
|
|
251
|
-
|
|
264
|
+
const browserCancelAnimationFrame = typeof window !== "undefined" ? window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame : null;
|
|
265
|
+
if (browserCancelAnimationFrame) {
|
|
266
|
+
browserCancelAnimationFrame.call(window, timerId);
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
clearTimeout(timerId);
|
|
252
270
|
}
|
|
253
271
|
|
|
254
272
|
// dist/animation-loop/animation-loop.js
|
|
255
273
|
var import_stats = require("@probe.gl/stats");
|
|
256
274
|
var statIdCounter = 0;
|
|
275
|
+
var ANIMATION_LOOP_STATS = "Animation Loop";
|
|
257
276
|
var _AnimationLoop = class {
|
|
258
277
|
device = null;
|
|
259
278
|
canvas = null;
|
|
@@ -261,11 +280,12 @@ var _AnimationLoop = class {
|
|
|
261
280
|
animationProps = null;
|
|
262
281
|
timeline = null;
|
|
263
282
|
stats;
|
|
283
|
+
sharedStats;
|
|
264
284
|
cpuTime;
|
|
265
285
|
gpuTime;
|
|
266
286
|
frameRate;
|
|
267
287
|
display;
|
|
268
|
-
|
|
288
|
+
_needsRedraw = "initialized";
|
|
269
289
|
_initialized = false;
|
|
270
290
|
_running = false;
|
|
271
291
|
_animationFrameId = null;
|
|
@@ -273,7 +293,7 @@ var _AnimationLoop = class {
|
|
|
273
293
|
_resolveNextFrame = null;
|
|
274
294
|
_cpuStartTime = 0;
|
|
275
295
|
_error = null;
|
|
276
|
-
|
|
296
|
+
_lastFrameTime = 0;
|
|
277
297
|
/*
|
|
278
298
|
* @param {HTMLCanvasElement} canvas - if provided, width and height will be passed to context
|
|
279
299
|
*/
|
|
@@ -283,10 +303,12 @@ var _AnimationLoop = class {
|
|
|
283
303
|
if (!props.device) {
|
|
284
304
|
throw new Error("No device provided");
|
|
285
305
|
}
|
|
286
|
-
this.stats = props.stats || new import_stats.Stats({ id:
|
|
306
|
+
this.stats = props.stats || new import_stats.Stats({ id: `animation-loop-${statIdCounter++}` });
|
|
307
|
+
this.sharedStats = import_core.luma.stats.get(ANIMATION_LOOP_STATS);
|
|
308
|
+
this.frameRate = this.stats.get("Frame Rate");
|
|
309
|
+
this.frameRate.setSampleSize(1);
|
|
287
310
|
this.cpuTime = this.stats.get("CPU Time");
|
|
288
311
|
this.gpuTime = this.stats.get("GPU Time");
|
|
289
|
-
this.frameRate = this.stats.get("Frame Rate");
|
|
290
312
|
this.setProps({ autoResizeViewport: props.autoResizeViewport });
|
|
291
313
|
this.start = this.start.bind(this);
|
|
292
314
|
this.stop = this.stop.bind(this);
|
|
@@ -294,8 +316,10 @@ var _AnimationLoop = class {
|
|
|
294
316
|
this._onMouseleave = this._onMouseleave.bind(this);
|
|
295
317
|
}
|
|
296
318
|
destroy() {
|
|
319
|
+
var _a;
|
|
297
320
|
this.stop();
|
|
298
321
|
this._setDisplay(null);
|
|
322
|
+
(_a = this.device) == null ? void 0 : _a._disableDebugGPUTime();
|
|
299
323
|
}
|
|
300
324
|
/** @deprecated Use .destroy() */
|
|
301
325
|
delete() {
|
|
@@ -307,9 +331,15 @@ var _AnimationLoop = class {
|
|
|
307
331
|
}
|
|
308
332
|
/** Flags this animation loop as needing redraw */
|
|
309
333
|
setNeedsRedraw(reason) {
|
|
310
|
-
this.
|
|
334
|
+
this._needsRedraw = this._needsRedraw || reason;
|
|
311
335
|
return this;
|
|
312
336
|
}
|
|
337
|
+
/** Query redraw status. Clears the flag. */
|
|
338
|
+
needsRedraw() {
|
|
339
|
+
const reason = this._needsRedraw;
|
|
340
|
+
this._needsRedraw = false;
|
|
341
|
+
return reason;
|
|
342
|
+
}
|
|
313
343
|
setProps(props) {
|
|
314
344
|
if ("autoResizeViewport" in props) {
|
|
315
345
|
this.props.autoResizeViewport = props.autoResizeViewport || false;
|
|
@@ -328,6 +358,9 @@ var _AnimationLoop = class {
|
|
|
328
358
|
this._initialized = true;
|
|
329
359
|
await this._initDevice();
|
|
330
360
|
this._initialize();
|
|
361
|
+
if (!this._running) {
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
331
364
|
await this.props.onInitialize(this._getAnimationProps());
|
|
332
365
|
}
|
|
333
366
|
if (!this._running) {
|
|
@@ -354,16 +387,17 @@ var _AnimationLoop = class {
|
|
|
354
387
|
this._nextFramePromise = null;
|
|
355
388
|
this._resolveNextFrame = null;
|
|
356
389
|
this._running = false;
|
|
390
|
+
this._lastFrameTime = 0;
|
|
357
391
|
}
|
|
358
392
|
return this;
|
|
359
393
|
}
|
|
360
394
|
/** Explicitly draw a frame */
|
|
361
|
-
redraw() {
|
|
395
|
+
redraw(time) {
|
|
362
396
|
var _a;
|
|
363
397
|
if (((_a = this.device) == null ? void 0 : _a.isLost) || this._error) {
|
|
364
398
|
return this;
|
|
365
399
|
}
|
|
366
|
-
this._beginFrameTimers();
|
|
400
|
+
this._beginFrameTimers(time);
|
|
367
401
|
this._setupFrame();
|
|
368
402
|
this._updateAnimationProps();
|
|
369
403
|
this._renderFrame(this._getAnimationProps());
|
|
@@ -406,10 +440,12 @@ var _AnimationLoop = class {
|
|
|
406
440
|
}
|
|
407
441
|
// PRIVATE METHODS
|
|
408
442
|
_initialize() {
|
|
443
|
+
var _a;
|
|
409
444
|
this._startEventHandling();
|
|
410
445
|
this._initializeAnimationProps();
|
|
411
446
|
this._updateAnimationProps();
|
|
412
447
|
this._resizeViewport();
|
|
448
|
+
(_a = this.device) == null ? void 0 : _a._enableDebugGPUTime();
|
|
413
449
|
}
|
|
414
450
|
_setDisplay(display) {
|
|
415
451
|
if (this.display) {
|
|
@@ -434,11 +470,11 @@ var _AnimationLoop = class {
|
|
|
434
470
|
cancelAnimationFramePolyfill(this._animationFrameId);
|
|
435
471
|
this._animationFrameId = null;
|
|
436
472
|
}
|
|
437
|
-
_animationFrame() {
|
|
473
|
+
_animationFrame(time) {
|
|
438
474
|
if (!this._running) {
|
|
439
475
|
return;
|
|
440
476
|
}
|
|
441
|
-
this.redraw();
|
|
477
|
+
this.redraw(time);
|
|
442
478
|
this._requestAnimationFrame();
|
|
443
479
|
}
|
|
444
480
|
// Called on each frame, can be overridden to call onRender multiple times
|
|
@@ -453,7 +489,7 @@ var _AnimationLoop = class {
|
|
|
453
489
|
(_a = this.device) == null ? void 0 : _a.submit();
|
|
454
490
|
}
|
|
455
491
|
_clearNeedsRedraw() {
|
|
456
|
-
this.
|
|
492
|
+
this._needsRedraw = false;
|
|
457
493
|
}
|
|
458
494
|
_setupFrame() {
|
|
459
495
|
this._resizeViewport();
|
|
@@ -512,7 +548,7 @@ var _AnimationLoop = class {
|
|
|
512
548
|
this.animationProps.width = width;
|
|
513
549
|
this.animationProps.height = height;
|
|
514
550
|
this.animationProps.aspect = aspect;
|
|
515
|
-
this.animationProps.needsRedraw = this.
|
|
551
|
+
this.animationProps.needsRedraw = this._needsRedraw;
|
|
516
552
|
this.animationProps.engineTime = Date.now() - this.animationProps.startTime;
|
|
517
553
|
if (this.timeline) {
|
|
518
554
|
this.timeline.update(this.animationProps.engineTime);
|
|
@@ -551,18 +587,11 @@ var _AnimationLoop = class {
|
|
|
551
587
|
}
|
|
552
588
|
}
|
|
553
589
|
_getSizeAndAspect() {
|
|
554
|
-
var _a, _b;
|
|
555
590
|
if (!this.device) {
|
|
556
591
|
return { width: 1, height: 1, aspect: 1 };
|
|
557
592
|
}
|
|
558
|
-
const [width, height] =
|
|
559
|
-
|
|
560
|
-
const canvas2 = (_b = this.device) == null ? void 0 : _b.getDefaultCanvasContext().canvas;
|
|
561
|
-
if (canvas2 && canvas2.clientHeight) {
|
|
562
|
-
aspect = canvas2.clientWidth / canvas2.clientHeight;
|
|
563
|
-
} else if (width > 0 && height > 0) {
|
|
564
|
-
aspect = width / height;
|
|
565
|
-
}
|
|
593
|
+
const [width, height] = this.device.getDefaultCanvasContext().getDrawingBufferSize();
|
|
594
|
+
const aspect = width > 0 && height > 0 ? width / height : 1;
|
|
566
595
|
return { width, height, aspect };
|
|
567
596
|
}
|
|
568
597
|
/** @deprecated Default viewport setup */
|
|
@@ -578,13 +607,63 @@ var _AnimationLoop = class {
|
|
|
578
607
|
);
|
|
579
608
|
}
|
|
580
609
|
}
|
|
581
|
-
_beginFrameTimers() {
|
|
582
|
-
|
|
583
|
-
|
|
610
|
+
_beginFrameTimers(time) {
|
|
611
|
+
var _a;
|
|
612
|
+
const now = time ?? (typeof performance !== "undefined" ? performance.now() : Date.now());
|
|
613
|
+
if (this._lastFrameTime) {
|
|
614
|
+
const frameTime = now - this._lastFrameTime;
|
|
615
|
+
if (frameTime > 0) {
|
|
616
|
+
this.frameRate.addTime(frameTime);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
this._lastFrameTime = now;
|
|
620
|
+
if ((_a = this.device) == null ? void 0 : _a._isDebugGPUTimeEnabled()) {
|
|
621
|
+
this._consumeEncodedGpuTime();
|
|
622
|
+
}
|
|
584
623
|
this.cpuTime.timeStart();
|
|
585
624
|
}
|
|
586
625
|
_endFrameTimers() {
|
|
626
|
+
var _a;
|
|
627
|
+
if ((_a = this.device) == null ? void 0 : _a._isDebugGPUTimeEnabled()) {
|
|
628
|
+
this._consumeEncodedGpuTime();
|
|
629
|
+
}
|
|
587
630
|
this.cpuTime.timeEnd();
|
|
631
|
+
this._updateSharedStats();
|
|
632
|
+
}
|
|
633
|
+
_consumeEncodedGpuTime() {
|
|
634
|
+
if (!this.device) {
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
const gpuTimeMs = this.device.commandEncoder._gpuTimeMs;
|
|
638
|
+
if (gpuTimeMs !== void 0) {
|
|
639
|
+
this.gpuTime.addTime(gpuTimeMs);
|
|
640
|
+
this.device.commandEncoder._gpuTimeMs = void 0;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
_updateSharedStats() {
|
|
644
|
+
if (this.stats === this.sharedStats) {
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
for (const name of Object.keys(this.sharedStats.stats)) {
|
|
648
|
+
if (!this.stats.stats[name]) {
|
|
649
|
+
delete this.sharedStats.stats[name];
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
this.stats.forEach((sourceStat) => {
|
|
653
|
+
const targetStat = this.sharedStats.get(sourceStat.name, sourceStat.type);
|
|
654
|
+
targetStat.sampleSize = sourceStat.sampleSize;
|
|
655
|
+
targetStat.time = sourceStat.time;
|
|
656
|
+
targetStat.count = sourceStat.count;
|
|
657
|
+
targetStat.samples = sourceStat.samples;
|
|
658
|
+
targetStat.lastTiming = sourceStat.lastTiming;
|
|
659
|
+
targetStat.lastSampleTime = sourceStat.lastSampleTime;
|
|
660
|
+
targetStat.lastSampleCount = sourceStat.lastSampleCount;
|
|
661
|
+
targetStat._count = sourceStat._count;
|
|
662
|
+
targetStat._time = sourceStat._time;
|
|
663
|
+
targetStat._samples = sourceStat._samples;
|
|
664
|
+
targetStat._startTime = sourceStat._startTime;
|
|
665
|
+
targetStat._timerPending = sourceStat._timerPending;
|
|
666
|
+
});
|
|
588
667
|
}
|
|
589
668
|
// Event handling
|
|
590
669
|
_startEventHandling() {
|
|
@@ -613,7 +692,7 @@ __publicField(AnimationLoop, "defaultAnimationLoopProps", {
|
|
|
613
692
|
},
|
|
614
693
|
onError: (error) => console.error(error),
|
|
615
694
|
// eslint-disable-line no-console
|
|
616
|
-
stats:
|
|
695
|
+
stats: void 0,
|
|
617
696
|
// view parameters
|
|
618
697
|
autoResizeViewport: false
|
|
619
698
|
});
|
|
@@ -646,7 +725,10 @@ function makeAnimationLoop(AnimationLoopTemplateCtor, props) {
|
|
|
646
725
|
}
|
|
647
726
|
function setError(device, error) {
|
|
648
727
|
var _a;
|
|
649
|
-
|
|
728
|
+
if (!device) {
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
const canvas2 = device.getDefaultCanvasContext().canvas;
|
|
650
732
|
if (canvas2 instanceof HTMLCanvasElement) {
|
|
651
733
|
canvas2.style.overflow = "visible";
|
|
652
734
|
let errorDiv = document.getElementById("animation-loop-error");
|
|
@@ -663,6 +745,9 @@ function setError(device, error) {
|
|
|
663
745
|
}
|
|
664
746
|
}
|
|
665
747
|
function clearError(device) {
|
|
748
|
+
if (!device) {
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
666
751
|
const errorDiv = document.getElementById("animation-loop-error");
|
|
667
752
|
if (errorDiv) {
|
|
668
753
|
errorDiv.remove();
|
|
@@ -670,7 +755,7 @@ function clearError(device) {
|
|
|
670
755
|
}
|
|
671
756
|
|
|
672
757
|
// dist/model/model.js
|
|
673
|
-
var
|
|
758
|
+
var import_core8 = require("@luma.gl/core");
|
|
674
759
|
var import_shadertools2 = require("@luma.gl/shadertools");
|
|
675
760
|
|
|
676
761
|
// dist/geometry/gpu-geometry.js
|
|
@@ -774,262 +859,19 @@ function getAttributeBuffersFromGeometry(device, geometry) {
|
|
|
774
859
|
id: `${attributeName}-buffer`
|
|
775
860
|
});
|
|
776
861
|
const { value, size, normalized } = attribute;
|
|
777
|
-
|
|
862
|
+
if (size === void 0) {
|
|
863
|
+
throw new Error(`Attribute ${attributeName} is missing a size`);
|
|
864
|
+
}
|
|
865
|
+
bufferLayout.push({
|
|
866
|
+
name,
|
|
867
|
+
format: import_core3.vertexFormatDecoder.getVertexFormatFromAttribute(value, size, normalized)
|
|
868
|
+
});
|
|
778
869
|
}
|
|
779
870
|
}
|
|
780
871
|
const vertexCount = geometry._calculateVertexCount(geometry.attributes, geometry.indices);
|
|
781
872
|
return { attributes, bufferLayout, vertexCount };
|
|
782
873
|
}
|
|
783
874
|
|
|
784
|
-
// dist/factories/pipeline-factory.js
|
|
785
|
-
var import_core4 = require("@luma.gl/core");
|
|
786
|
-
var _PipelineFactory = class {
|
|
787
|
-
/** Get the singleton default pipeline factory for the specified device */
|
|
788
|
-
static getDefaultPipelineFactory(device) {
|
|
789
|
-
device._lumaData["defaultPipelineFactory"] = device._lumaData["defaultPipelineFactory"] || new _PipelineFactory(device);
|
|
790
|
-
return device._lumaData["defaultPipelineFactory"];
|
|
791
|
-
}
|
|
792
|
-
device;
|
|
793
|
-
cachingEnabled;
|
|
794
|
-
destroyPolicy;
|
|
795
|
-
debug;
|
|
796
|
-
_hashCounter = 0;
|
|
797
|
-
_hashes = {};
|
|
798
|
-
_renderPipelineCache = {};
|
|
799
|
-
_computePipelineCache = {};
|
|
800
|
-
get [Symbol.toStringTag]() {
|
|
801
|
-
return "PipelineFactory";
|
|
802
|
-
}
|
|
803
|
-
toString() {
|
|
804
|
-
return `PipelineFactory(${this.device.id})`;
|
|
805
|
-
}
|
|
806
|
-
constructor(device) {
|
|
807
|
-
this.device = device;
|
|
808
|
-
this.cachingEnabled = device.props._cachePipelines;
|
|
809
|
-
this.destroyPolicy = device.props._cacheDestroyPolicy;
|
|
810
|
-
this.debug = device.props.debugFactories;
|
|
811
|
-
}
|
|
812
|
-
/** Return a RenderPipeline matching supplied props. Reuses an equivalent pipeline if already created. */
|
|
813
|
-
createRenderPipeline(props) {
|
|
814
|
-
var _a;
|
|
815
|
-
if (!this.cachingEnabled) {
|
|
816
|
-
return this.device.createRenderPipeline(props);
|
|
817
|
-
}
|
|
818
|
-
const allProps = { ...import_core4.RenderPipeline.defaultProps, ...props };
|
|
819
|
-
const cache = this._renderPipelineCache;
|
|
820
|
-
const hash = this._hashRenderPipeline(allProps);
|
|
821
|
-
let pipeline = (_a = cache[hash]) == null ? void 0 : _a.pipeline;
|
|
822
|
-
if (!pipeline) {
|
|
823
|
-
pipeline = this.device.createRenderPipeline({
|
|
824
|
-
...allProps,
|
|
825
|
-
id: allProps.id ? `${allProps.id}-cached` : uid("unnamed-cached")
|
|
826
|
-
});
|
|
827
|
-
pipeline.hash = hash;
|
|
828
|
-
cache[hash] = { pipeline, useCount: 1 };
|
|
829
|
-
if (this.debug) {
|
|
830
|
-
import_core4.log.log(3, `${this}: ${pipeline} created, count=${cache[hash].useCount}`)();
|
|
831
|
-
}
|
|
832
|
-
} else {
|
|
833
|
-
cache[hash].useCount++;
|
|
834
|
-
if (this.debug) {
|
|
835
|
-
import_core4.log.log(3, `${this}: ${cache[hash].pipeline} reused, count=${cache[hash].useCount}, (id=${props.id})`)();
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
return pipeline;
|
|
839
|
-
}
|
|
840
|
-
/** Return a ComputePipeline matching supplied props. Reuses an equivalent pipeline if already created. */
|
|
841
|
-
createComputePipeline(props) {
|
|
842
|
-
var _a;
|
|
843
|
-
if (!this.cachingEnabled) {
|
|
844
|
-
return this.device.createComputePipeline(props);
|
|
845
|
-
}
|
|
846
|
-
const allProps = { ...import_core4.ComputePipeline.defaultProps, ...props };
|
|
847
|
-
const cache = this._computePipelineCache;
|
|
848
|
-
const hash = this._hashComputePipeline(allProps);
|
|
849
|
-
let pipeline = (_a = cache[hash]) == null ? void 0 : _a.pipeline;
|
|
850
|
-
if (!pipeline) {
|
|
851
|
-
pipeline = this.device.createComputePipeline({
|
|
852
|
-
...allProps,
|
|
853
|
-
id: allProps.id ? `${allProps.id}-cached` : void 0
|
|
854
|
-
});
|
|
855
|
-
pipeline.hash = hash;
|
|
856
|
-
cache[hash] = { pipeline, useCount: 1 };
|
|
857
|
-
if (this.debug) {
|
|
858
|
-
import_core4.log.log(3, `${this}: ${pipeline} created, count=${cache[hash].useCount}`)();
|
|
859
|
-
}
|
|
860
|
-
} else {
|
|
861
|
-
cache[hash].useCount++;
|
|
862
|
-
if (this.debug) {
|
|
863
|
-
import_core4.log.log(3, `${this}: ${cache[hash].pipeline} reused, count=${cache[hash].useCount}, (id=${props.id})`)();
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
return pipeline;
|
|
867
|
-
}
|
|
868
|
-
release(pipeline) {
|
|
869
|
-
if (!this.cachingEnabled) {
|
|
870
|
-
pipeline.destroy();
|
|
871
|
-
return;
|
|
872
|
-
}
|
|
873
|
-
const cache = this._getCache(pipeline);
|
|
874
|
-
const hash = pipeline.hash;
|
|
875
|
-
cache[hash].useCount--;
|
|
876
|
-
if (cache[hash].useCount === 0) {
|
|
877
|
-
this._destroyPipeline(pipeline);
|
|
878
|
-
if (this.debug) {
|
|
879
|
-
import_core4.log.log(3, `${this}: ${pipeline} released and destroyed`)();
|
|
880
|
-
}
|
|
881
|
-
} else if (cache[hash].useCount < 0) {
|
|
882
|
-
import_core4.log.error(`${this}: ${pipeline} released, useCount < 0, resetting`)();
|
|
883
|
-
cache[hash].useCount = 0;
|
|
884
|
-
} else if (this.debug) {
|
|
885
|
-
import_core4.log.log(3, `${this}: ${pipeline} released, count=${cache[hash].useCount}`)();
|
|
886
|
-
}
|
|
887
|
-
}
|
|
888
|
-
// PRIVATE
|
|
889
|
-
/** Destroy a cached pipeline, removing it from the cache (depending on destroy policy) */
|
|
890
|
-
_destroyPipeline(pipeline) {
|
|
891
|
-
const cache = this._getCache(pipeline);
|
|
892
|
-
switch (this.destroyPolicy) {
|
|
893
|
-
case "never":
|
|
894
|
-
return false;
|
|
895
|
-
case "unused":
|
|
896
|
-
delete cache[pipeline.hash];
|
|
897
|
-
pipeline.destroy();
|
|
898
|
-
return true;
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
/** Get the appropriate cache for the type of pipeline */
|
|
902
|
-
_getCache(pipeline) {
|
|
903
|
-
let cache;
|
|
904
|
-
if (pipeline instanceof import_core4.ComputePipeline) {
|
|
905
|
-
cache = this._computePipelineCache;
|
|
906
|
-
}
|
|
907
|
-
if (pipeline instanceof import_core4.RenderPipeline) {
|
|
908
|
-
cache = this._renderPipelineCache;
|
|
909
|
-
}
|
|
910
|
-
if (!cache) {
|
|
911
|
-
throw new Error(`${this}`);
|
|
912
|
-
}
|
|
913
|
-
if (!cache[pipeline.hash]) {
|
|
914
|
-
throw new Error(`${this}: ${pipeline} matched incorrect entry`);
|
|
915
|
-
}
|
|
916
|
-
return cache;
|
|
917
|
-
}
|
|
918
|
-
/** Calculate a hash based on all the inputs for a compute pipeline */
|
|
919
|
-
_hashComputePipeline(props) {
|
|
920
|
-
const { type } = this.device;
|
|
921
|
-
const shaderHash = this._getHash(props.shader.source);
|
|
922
|
-
return `${type}/C/${shaderHash}`;
|
|
923
|
-
}
|
|
924
|
-
/** Calculate a hash based on all the inputs for a render pipeline */
|
|
925
|
-
_hashRenderPipeline(props) {
|
|
926
|
-
const vsHash = props.vs ? this._getHash(props.vs.source) : 0;
|
|
927
|
-
const fsHash = props.fs ? this._getHash(props.fs.source) : 0;
|
|
928
|
-
const varyingHash = "-";
|
|
929
|
-
const bufferLayoutHash = this._getHash(JSON.stringify(props.bufferLayout));
|
|
930
|
-
const { type } = this.device;
|
|
931
|
-
switch (type) {
|
|
932
|
-
case "webgl":
|
|
933
|
-
return `${type}/R/${vsHash}/${fsHash}V${varyingHash}BL${bufferLayoutHash}`;
|
|
934
|
-
case "webgpu":
|
|
935
|
-
default:
|
|
936
|
-
const parameterHash = this._getHash(JSON.stringify(props.parameters));
|
|
937
|
-
return `${type}/R/${vsHash}/${fsHash}V${varyingHash}T${props.topology}P${parameterHash}BL${bufferLayoutHash}`;
|
|
938
|
-
}
|
|
939
|
-
}
|
|
940
|
-
_getHash(key) {
|
|
941
|
-
if (this._hashes[key] === void 0) {
|
|
942
|
-
this._hashes[key] = this._hashCounter++;
|
|
943
|
-
}
|
|
944
|
-
return this._hashes[key];
|
|
945
|
-
}
|
|
946
|
-
};
|
|
947
|
-
var PipelineFactory = _PipelineFactory;
|
|
948
|
-
__publicField(PipelineFactory, "defaultProps", { ...import_core4.RenderPipeline.defaultProps });
|
|
949
|
-
|
|
950
|
-
// dist/factories/shader-factory.js
|
|
951
|
-
var import_core5 = require("@luma.gl/core");
|
|
952
|
-
var _ShaderFactory = class {
|
|
953
|
-
/** Returns the default ShaderFactory for the given {@link Device}, creating one if necessary. */
|
|
954
|
-
static getDefaultShaderFactory(device) {
|
|
955
|
-
device._lumaData["defaultShaderFactory"] ||= new _ShaderFactory(device);
|
|
956
|
-
return device._lumaData["defaultShaderFactory"];
|
|
957
|
-
}
|
|
958
|
-
device;
|
|
959
|
-
cachingEnabled;
|
|
960
|
-
destroyPolicy;
|
|
961
|
-
debug;
|
|
962
|
-
_cache = {};
|
|
963
|
-
get [Symbol.toStringTag]() {
|
|
964
|
-
return "ShaderFactory";
|
|
965
|
-
}
|
|
966
|
-
toString() {
|
|
967
|
-
return `${this[Symbol.toStringTag]}(${this.device.id})`;
|
|
968
|
-
}
|
|
969
|
-
/** @internal */
|
|
970
|
-
constructor(device) {
|
|
971
|
-
this.device = device;
|
|
972
|
-
this.cachingEnabled = device.props._cacheShaders;
|
|
973
|
-
this.destroyPolicy = device.props._cacheDestroyPolicy;
|
|
974
|
-
this.debug = true;
|
|
975
|
-
}
|
|
976
|
-
/** Requests a {@link Shader} from the cache, creating a new Shader only if necessary. */
|
|
977
|
-
createShader(props) {
|
|
978
|
-
if (!this.cachingEnabled) {
|
|
979
|
-
return this.device.createShader(props);
|
|
980
|
-
}
|
|
981
|
-
const key = this._hashShader(props);
|
|
982
|
-
let cacheEntry = this._cache[key];
|
|
983
|
-
if (!cacheEntry) {
|
|
984
|
-
const shader = this.device.createShader({
|
|
985
|
-
...props,
|
|
986
|
-
id: props.id ? `${props.id}-cached` : void 0
|
|
987
|
-
});
|
|
988
|
-
this._cache[key] = cacheEntry = { shader, useCount: 1 };
|
|
989
|
-
if (this.debug) {
|
|
990
|
-
import_core5.log.log(3, `${this}: Created new shader ${shader.id}`)();
|
|
991
|
-
}
|
|
992
|
-
} else {
|
|
993
|
-
cacheEntry.useCount++;
|
|
994
|
-
if (this.debug) {
|
|
995
|
-
import_core5.log.log(3, `${this}: Reusing shader ${cacheEntry.shader.id} count=${cacheEntry.useCount}`)();
|
|
996
|
-
}
|
|
997
|
-
}
|
|
998
|
-
return cacheEntry.shader;
|
|
999
|
-
}
|
|
1000
|
-
/** Releases a previously-requested {@link Shader}, destroying it if no users remain. */
|
|
1001
|
-
release(shader) {
|
|
1002
|
-
if (!this.cachingEnabled) {
|
|
1003
|
-
shader.destroy();
|
|
1004
|
-
return;
|
|
1005
|
-
}
|
|
1006
|
-
const key = this._hashShader(shader);
|
|
1007
|
-
const cacheEntry = this._cache[key];
|
|
1008
|
-
if (cacheEntry) {
|
|
1009
|
-
cacheEntry.useCount--;
|
|
1010
|
-
if (cacheEntry.useCount === 0) {
|
|
1011
|
-
if (this.destroyPolicy === "unused") {
|
|
1012
|
-
delete this._cache[key];
|
|
1013
|
-
cacheEntry.shader.destroy();
|
|
1014
|
-
if (this.debug) {
|
|
1015
|
-
import_core5.log.log(3, `${this}: Releasing shader ${shader.id}, destroyed`)();
|
|
1016
|
-
}
|
|
1017
|
-
}
|
|
1018
|
-
} else if (cacheEntry.useCount < 0) {
|
|
1019
|
-
throw new Error(`ShaderFactory: Shader ${shader.id} released too many times`);
|
|
1020
|
-
} else if (this.debug) {
|
|
1021
|
-
import_core5.log.log(3, `${this}: Releasing shader ${shader.id} count=${cacheEntry.useCount}`)();
|
|
1022
|
-
}
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
// PRIVATE
|
|
1026
|
-
_hashShader(value) {
|
|
1027
|
-
return `${value.stage}:${value.source}`;
|
|
1028
|
-
}
|
|
1029
|
-
};
|
|
1030
|
-
var ShaderFactory = _ShaderFactory;
|
|
1031
|
-
__publicField(ShaderFactory, "defaultProps", { ...import_core5.Shader.defaultProps });
|
|
1032
|
-
|
|
1033
875
|
// dist/debug/debug-shader-layout.js
|
|
1034
876
|
function getDebugTableForShaderLayout(layout, name) {
|
|
1035
877
|
var _a;
|
|
@@ -1130,7 +972,7 @@ function deepEqual(a, b, depth) {
|
|
|
1130
972
|
}
|
|
1131
973
|
|
|
1132
974
|
// dist/utils/buffer-layout-helper.js
|
|
1133
|
-
var
|
|
975
|
+
var import_core4 = require("@luma.gl/core");
|
|
1134
976
|
var BufferLayoutHelper = class {
|
|
1135
977
|
bufferLayouts;
|
|
1136
978
|
constructor(bufferLayouts) {
|
|
@@ -1159,28 +1001,82 @@ var BufferLayoutHelper = class {
|
|
|
1159
1001
|
getBufferIndex(bufferName) {
|
|
1160
1002
|
const bufferIndex = this.bufferLayouts.findIndex((layout) => layout.name === bufferName);
|
|
1161
1003
|
if (bufferIndex === -1) {
|
|
1162
|
-
|
|
1004
|
+
import_core4.log.warn(`BufferLayout: Missing buffer for "${bufferName}".`)();
|
|
1163
1005
|
}
|
|
1164
1006
|
return bufferIndex;
|
|
1165
1007
|
}
|
|
1166
1008
|
};
|
|
1167
1009
|
|
|
1168
1010
|
// dist/utils/buffer-layout-order.js
|
|
1011
|
+
function getMinLocation(attributeNames, shaderLayoutMap) {
|
|
1012
|
+
let minLocation = Infinity;
|
|
1013
|
+
for (const name of attributeNames) {
|
|
1014
|
+
const location = shaderLayoutMap[name];
|
|
1015
|
+
if (location !== void 0) {
|
|
1016
|
+
minLocation = Math.min(minLocation, location);
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
return minLocation;
|
|
1020
|
+
}
|
|
1169
1021
|
function sortedBufferLayoutByShaderSourceLocations(shaderLayout, bufferLayout) {
|
|
1170
1022
|
const shaderLayoutMap = Object.fromEntries(shaderLayout.attributes.map((attr) => [attr.name, attr.location]));
|
|
1171
1023
|
const sortedLayout = bufferLayout.slice();
|
|
1172
1024
|
sortedLayout.sort((a, b) => {
|
|
1173
1025
|
const attributeNamesA = a.attributes ? a.attributes.map((attr) => attr.attribute) : [a.name];
|
|
1174
1026
|
const attributeNamesB = b.attributes ? b.attributes.map((attr) => attr.attribute) : [b.name];
|
|
1175
|
-
const minLocationA =
|
|
1176
|
-
const minLocationB =
|
|
1027
|
+
const minLocationA = getMinLocation(attributeNamesA, shaderLayoutMap);
|
|
1028
|
+
const minLocationB = getMinLocation(attributeNamesB, shaderLayoutMap);
|
|
1177
1029
|
return minLocationA - minLocationB;
|
|
1178
1030
|
});
|
|
1179
1031
|
return sortedLayout;
|
|
1180
1032
|
}
|
|
1181
1033
|
|
|
1034
|
+
// dist/utils/shader-module-utils.js
|
|
1035
|
+
function mergeShaderModuleBindingsIntoLayout(shaderLayout, modules) {
|
|
1036
|
+
if (!shaderLayout || !modules.some((module2) => {
|
|
1037
|
+
var _a;
|
|
1038
|
+
return (_a = module2.bindingLayout) == null ? void 0 : _a.length;
|
|
1039
|
+
})) {
|
|
1040
|
+
return shaderLayout;
|
|
1041
|
+
}
|
|
1042
|
+
const mergedLayout = {
|
|
1043
|
+
...shaderLayout,
|
|
1044
|
+
bindings: shaderLayout.bindings.map((binding) => ({ ...binding }))
|
|
1045
|
+
};
|
|
1046
|
+
if ("attributes" in (shaderLayout || {})) {
|
|
1047
|
+
mergedLayout.attributes = (shaderLayout == null ? void 0 : shaderLayout.attributes) || [];
|
|
1048
|
+
}
|
|
1049
|
+
for (const module2 of modules) {
|
|
1050
|
+
for (const bindingLayout of module2.bindingLayout || []) {
|
|
1051
|
+
for (const relatedBindingName of getRelatedBindingNames(bindingLayout.name)) {
|
|
1052
|
+
const binding = mergedLayout.bindings.find((candidate) => candidate.name === relatedBindingName);
|
|
1053
|
+
if ((binding == null ? void 0 : binding.group) === 0) {
|
|
1054
|
+
binding.group = bindingLayout.group;
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
return mergedLayout;
|
|
1060
|
+
}
|
|
1061
|
+
function shaderModuleHasUniforms(module2) {
|
|
1062
|
+
return Boolean(module2.uniformTypes && !isObjectEmpty(module2.uniformTypes));
|
|
1063
|
+
}
|
|
1064
|
+
function getRelatedBindingNames(bindingName) {
|
|
1065
|
+
const bindingNames = /* @__PURE__ */ new Set([bindingName, `${bindingName}Uniforms`]);
|
|
1066
|
+
if (!bindingName.endsWith("Uniforms")) {
|
|
1067
|
+
bindingNames.add(`${bindingName}Sampler`);
|
|
1068
|
+
}
|
|
1069
|
+
return [...bindingNames];
|
|
1070
|
+
}
|
|
1071
|
+
function isObjectEmpty(obj) {
|
|
1072
|
+
for (const key in obj) {
|
|
1073
|
+
return false;
|
|
1074
|
+
}
|
|
1075
|
+
return true;
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1182
1078
|
// dist/shader-inputs.js
|
|
1183
|
-
var
|
|
1079
|
+
var import_core5 = require("@luma.gl/core");
|
|
1184
1080
|
var import_shadertools = require("@luma.gl/shadertools");
|
|
1185
1081
|
|
|
1186
1082
|
// dist/model/split-uniforms-and-bindings.js
|
|
@@ -1188,11 +1084,11 @@ var import_types = require("@math.gl/types");
|
|
|
1188
1084
|
function isUniformValue(value) {
|
|
1189
1085
|
return (0, import_types.isNumericArray)(value) || typeof value === "number" || typeof value === "boolean";
|
|
1190
1086
|
}
|
|
1191
|
-
function splitUniformsAndBindings(uniforms) {
|
|
1087
|
+
function splitUniformsAndBindings(uniforms, uniformTypes2 = {}) {
|
|
1192
1088
|
const result = { bindings: {}, uniforms: {} };
|
|
1193
1089
|
Object.keys(uniforms).forEach((name) => {
|
|
1194
1090
|
const uniform = uniforms[name];
|
|
1195
|
-
if (isUniformValue(uniform)) {
|
|
1091
|
+
if (Object.prototype.hasOwnProperty.call(uniformTypes2, name) || isUniformValue(uniform)) {
|
|
1196
1092
|
result.uniforms[name] = uniform;
|
|
1197
1093
|
} else {
|
|
1198
1094
|
result.bindings[name] = uniform;
|
|
@@ -1224,18 +1120,21 @@ var ShaderInputs = class {
|
|
|
1224
1120
|
*/
|
|
1225
1121
|
constructor(modules, options) {
|
|
1226
1122
|
Object.assign(this.options, options);
|
|
1227
|
-
const resolvedModules = (0, import_shadertools.getShaderModuleDependencies)(Object.values(modules).filter(
|
|
1123
|
+
const resolvedModules = (0, import_shadertools.getShaderModuleDependencies)(Object.values(modules).filter(isShaderInputsModuleWithDependencies));
|
|
1228
1124
|
for (const resolvedModule of resolvedModules) {
|
|
1229
1125
|
modules[resolvedModule.name] = resolvedModule;
|
|
1230
1126
|
}
|
|
1231
|
-
|
|
1127
|
+
import_core5.log.log(1, "Creating ShaderInputs with modules", Object.keys(modules))();
|
|
1232
1128
|
this.modules = modules;
|
|
1233
1129
|
this.moduleUniforms = {};
|
|
1234
1130
|
this.moduleBindings = {};
|
|
1235
1131
|
for (const [name, module2] of Object.entries(modules)) {
|
|
1132
|
+
if (!module2) {
|
|
1133
|
+
continue;
|
|
1134
|
+
}
|
|
1236
1135
|
this._addModule(module2);
|
|
1237
1136
|
if (module2.name && name !== module2.name && !this.options.disableWarnings) {
|
|
1238
|
-
|
|
1137
|
+
import_core5.log.warn(`Module name: ${name} vs ${module2.name}`)();
|
|
1239
1138
|
}
|
|
1240
1139
|
}
|
|
1241
1140
|
}
|
|
@@ -1253,15 +1152,15 @@ var ShaderInputs = class {
|
|
|
1253
1152
|
const module2 = this.modules[moduleName];
|
|
1254
1153
|
if (!module2) {
|
|
1255
1154
|
if (!this.options.disableWarnings) {
|
|
1256
|
-
|
|
1155
|
+
import_core5.log.warn(`Module ${name} not found`)();
|
|
1257
1156
|
}
|
|
1258
1157
|
continue;
|
|
1259
1158
|
}
|
|
1260
1159
|
const oldUniforms = this.moduleUniforms[moduleName];
|
|
1261
1160
|
const oldBindings = this.moduleBindings[moduleName];
|
|
1262
1161
|
const uniformsAndBindings = ((_a = module2.getUniforms) == null ? void 0 : _a.call(module2, moduleProps, oldUniforms)) || moduleProps;
|
|
1263
|
-
const { uniforms, bindings } = splitUniformsAndBindings(uniformsAndBindings);
|
|
1264
|
-
this.moduleUniforms[moduleName] =
|
|
1162
|
+
const { uniforms, bindings } = splitUniformsAndBindings(uniformsAndBindings, module2.uniformTypes);
|
|
1163
|
+
this.moduleUniforms[moduleName] = mergeModuleUniforms(oldUniforms, uniforms, module2.uniformTypes);
|
|
1265
1164
|
this.moduleBindings[moduleName] = { ...oldBindings, ...bindings };
|
|
1266
1165
|
}
|
|
1267
1166
|
}
|
|
@@ -1301,54 +1200,260 @@ var ShaderInputs = class {
|
|
|
1301
1200
|
}
|
|
1302
1201
|
_addModule(module2) {
|
|
1303
1202
|
const moduleName = module2.name;
|
|
1304
|
-
this.moduleUniforms[moduleName] = module2.defaultUniforms || {};
|
|
1203
|
+
this.moduleUniforms[moduleName] = mergeModuleUniforms({}, module2.defaultUniforms || {}, module2.uniformTypes);
|
|
1305
1204
|
this.moduleBindings[moduleName] = {};
|
|
1306
1205
|
}
|
|
1307
1206
|
};
|
|
1207
|
+
function mergeModuleUniforms(currentUniforms = {}, nextUniforms = {}, uniformTypes2 = {}) {
|
|
1208
|
+
const mergedUniforms = { ...currentUniforms };
|
|
1209
|
+
for (const [key, value] of Object.entries(nextUniforms)) {
|
|
1210
|
+
if (value === void 0) {
|
|
1211
|
+
continue;
|
|
1212
|
+
}
|
|
1213
|
+
mergedUniforms[key] = mergeModuleUniformValue(currentUniforms[key], value, uniformTypes2[key]);
|
|
1214
|
+
}
|
|
1215
|
+
return mergedUniforms;
|
|
1216
|
+
}
|
|
1217
|
+
function mergeModuleUniformValue(currentValue, nextValue, uniformType) {
|
|
1218
|
+
if (!uniformType || typeof uniformType === "string") {
|
|
1219
|
+
return cloneModuleUniformValue(nextValue);
|
|
1220
|
+
}
|
|
1221
|
+
if (Array.isArray(uniformType)) {
|
|
1222
|
+
if (isPackedUniformArrayValue(nextValue) || !Array.isArray(nextValue)) {
|
|
1223
|
+
return cloneModuleUniformValue(nextValue);
|
|
1224
|
+
}
|
|
1225
|
+
const currentArray = Array.isArray(currentValue) && !isPackedUniformArrayValue(currentValue) ? [...currentValue] : [];
|
|
1226
|
+
const mergedArray = currentArray.slice();
|
|
1227
|
+
for (let index = 0; index < nextValue.length; index++) {
|
|
1228
|
+
const elementValue = nextValue[index];
|
|
1229
|
+
if (elementValue === void 0) {
|
|
1230
|
+
continue;
|
|
1231
|
+
}
|
|
1232
|
+
mergedArray[index] = mergeModuleUniformValue(currentArray[index], elementValue, uniformType[0]);
|
|
1233
|
+
}
|
|
1234
|
+
return mergedArray;
|
|
1235
|
+
}
|
|
1236
|
+
if (!isPlainUniformObject(nextValue)) {
|
|
1237
|
+
return cloneModuleUniformValue(nextValue);
|
|
1238
|
+
}
|
|
1239
|
+
const uniformStruct = uniformType;
|
|
1240
|
+
const currentObject = isPlainUniformObject(currentValue) ? currentValue : {};
|
|
1241
|
+
const mergedObject = { ...currentObject };
|
|
1242
|
+
for (const [key, value] of Object.entries(nextValue)) {
|
|
1243
|
+
if (value === void 0) {
|
|
1244
|
+
continue;
|
|
1245
|
+
}
|
|
1246
|
+
mergedObject[key] = mergeModuleUniformValue(currentObject[key], value, uniformStruct[key]);
|
|
1247
|
+
}
|
|
1248
|
+
return mergedObject;
|
|
1249
|
+
}
|
|
1250
|
+
function cloneModuleUniformValue(value) {
|
|
1251
|
+
if (ArrayBuffer.isView(value)) {
|
|
1252
|
+
return Array.prototype.slice.call(value);
|
|
1253
|
+
}
|
|
1254
|
+
if (Array.isArray(value)) {
|
|
1255
|
+
if (isPackedUniformArrayValue(value)) {
|
|
1256
|
+
return value.slice();
|
|
1257
|
+
}
|
|
1258
|
+
const compositeArray = value;
|
|
1259
|
+
return compositeArray.map((element) => element === void 0 ? void 0 : cloneModuleUniformValue(element));
|
|
1260
|
+
}
|
|
1261
|
+
if (isPlainUniformObject(value)) {
|
|
1262
|
+
return Object.fromEntries(Object.entries(value).map(([key, nestedValue]) => [
|
|
1263
|
+
key,
|
|
1264
|
+
nestedValue === void 0 ? void 0 : cloneModuleUniformValue(nestedValue)
|
|
1265
|
+
]));
|
|
1266
|
+
}
|
|
1267
|
+
return value;
|
|
1268
|
+
}
|
|
1269
|
+
function isPackedUniformArrayValue(value) {
|
|
1270
|
+
return ArrayBuffer.isView(value) || Array.isArray(value) && (value.length === 0 || typeof value[0] === "number");
|
|
1271
|
+
}
|
|
1272
|
+
function isPlainUniformObject(value) {
|
|
1273
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value) && !ArrayBuffer.isView(value);
|
|
1274
|
+
}
|
|
1275
|
+
function isShaderInputsModuleWithDependencies(module2) {
|
|
1276
|
+
return Boolean(module2 == null ? void 0 : module2.dependencies);
|
|
1277
|
+
}
|
|
1308
1278
|
|
|
1309
|
-
// dist/
|
|
1310
|
-
var
|
|
1279
|
+
// dist/dynamic-texture/dynamic-texture.js
|
|
1280
|
+
var import_core7 = require("@luma.gl/core");
|
|
1311
1281
|
|
|
1312
|
-
// dist/
|
|
1313
|
-
var
|
|
1314
|
-
|
|
1315
|
-
|
|
1282
|
+
// dist/dynamic-texture/texture-data.js
|
|
1283
|
+
var import_core6 = require("@luma.gl/core");
|
|
1284
|
+
var TEXTURE_CUBE_FACE_MAP = { "+X": 0, "-X": 1, "+Y": 2, "-Y": 3, "+Z": 4, "-Z": 5 };
|
|
1285
|
+
function getFirstMipLevel(layer) {
|
|
1286
|
+
if (!layer)
|
|
1287
|
+
return null;
|
|
1288
|
+
return Array.isArray(layer) ? layer[0] ?? null : layer;
|
|
1316
1289
|
}
|
|
1317
|
-
|
|
1318
|
-
const
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1290
|
+
function getTextureSizeFromData(props) {
|
|
1291
|
+
const { dimension, data } = props;
|
|
1292
|
+
if (!data) {
|
|
1293
|
+
return null;
|
|
1294
|
+
}
|
|
1295
|
+
switch (dimension) {
|
|
1296
|
+
case "1d": {
|
|
1297
|
+
const mipLevel = getFirstMipLevel(data);
|
|
1298
|
+
if (!mipLevel)
|
|
1299
|
+
return null;
|
|
1300
|
+
const { width } = getTextureMipLevelSize(mipLevel);
|
|
1301
|
+
return { width, height: 1 };
|
|
1302
|
+
}
|
|
1303
|
+
case "2d": {
|
|
1304
|
+
const mipLevel = getFirstMipLevel(data);
|
|
1305
|
+
return mipLevel ? getTextureMipLevelSize(mipLevel) : null;
|
|
1306
|
+
}
|
|
1307
|
+
case "3d":
|
|
1308
|
+
case "2d-array": {
|
|
1309
|
+
if (!Array.isArray(data) || data.length === 0)
|
|
1310
|
+
return null;
|
|
1311
|
+
const mipLevel = getFirstMipLevel(data[0]);
|
|
1312
|
+
return mipLevel ? getTextureMipLevelSize(mipLevel) : null;
|
|
1313
|
+
}
|
|
1314
|
+
case "cube": {
|
|
1315
|
+
const face = Object.keys(data)[0] ?? null;
|
|
1316
|
+
if (!face)
|
|
1317
|
+
return null;
|
|
1318
|
+
const faceData = data[face];
|
|
1319
|
+
const mipLevel = getFirstMipLevel(faceData);
|
|
1320
|
+
return mipLevel ? getTextureMipLevelSize(mipLevel) : null;
|
|
1321
|
+
}
|
|
1322
|
+
case "cube-array": {
|
|
1323
|
+
if (!Array.isArray(data) || data.length === 0)
|
|
1324
|
+
return null;
|
|
1325
|
+
const firstCube = data[0];
|
|
1326
|
+
const face = Object.keys(firstCube)[0] ?? null;
|
|
1327
|
+
if (!face)
|
|
1328
|
+
return null;
|
|
1329
|
+
const mipLevel = getFirstMipLevel(firstCube[face]);
|
|
1330
|
+
return mipLevel ? getTextureMipLevelSize(mipLevel) : null;
|
|
1331
|
+
}
|
|
1332
|
+
default:
|
|
1333
|
+
return null;
|
|
1334
|
+
}
|
|
1323
1335
|
}
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1336
|
+
function getTextureMipLevelSize(data) {
|
|
1337
|
+
if ((0, import_core6.isExternalImage)(data)) {
|
|
1338
|
+
return (0, import_core6.getExternalImageSize)(data);
|
|
1339
|
+
}
|
|
1340
|
+
if (typeof data === "object" && "width" in data && "height" in data) {
|
|
1341
|
+
return { width: data.width, height: data.height };
|
|
1342
|
+
}
|
|
1343
|
+
throw new Error("Unsupported mip-level data");
|
|
1344
|
+
}
|
|
1345
|
+
function isTextureImageData(data) {
|
|
1346
|
+
return typeof data === "object" && data !== null && "data" in data && "width" in data && "height" in data;
|
|
1347
|
+
}
|
|
1348
|
+
function isTypedArrayMipLevelData(data) {
|
|
1349
|
+
return ArrayBuffer.isView(data);
|
|
1350
|
+
}
|
|
1351
|
+
function resolveTextureImageFormat(data) {
|
|
1352
|
+
const { textureFormat, format } = data;
|
|
1353
|
+
if (textureFormat && format && textureFormat !== format) {
|
|
1354
|
+
throw new Error(`Conflicting texture formats "${textureFormat}" and "${format}" provided for the same mip level`);
|
|
1355
|
+
}
|
|
1356
|
+
return textureFormat ?? format;
|
|
1357
|
+
}
|
|
1358
|
+
function getCubeFaceIndex(face) {
|
|
1359
|
+
const idx = TEXTURE_CUBE_FACE_MAP[face];
|
|
1360
|
+
if (idx === void 0)
|
|
1361
|
+
throw new Error(`Invalid cube face: ${face}`);
|
|
1362
|
+
return idx;
|
|
1363
|
+
}
|
|
1364
|
+
function getCubeArrayFaceIndex(cubeIndex, face) {
|
|
1365
|
+
return 6 * cubeIndex + getCubeFaceIndex(face);
|
|
1366
|
+
}
|
|
1367
|
+
function getTexture1DSubresources(data) {
|
|
1368
|
+
throw new Error("setTexture1DData not supported in WebGL.");
|
|
1369
|
+
}
|
|
1370
|
+
function _normalizeTexture2DData(data) {
|
|
1371
|
+
return Array.isArray(data) ? data : [data];
|
|
1372
|
+
}
|
|
1373
|
+
function getTexture2DSubresources(slice, lodData, baseLevelSize, textureFormat) {
|
|
1374
|
+
const lodArray = _normalizeTexture2DData(lodData);
|
|
1375
|
+
const z = slice;
|
|
1376
|
+
const subresources = [];
|
|
1377
|
+
for (let mipLevel = 0; mipLevel < lodArray.length; mipLevel++) {
|
|
1378
|
+
const imageData = lodArray[mipLevel];
|
|
1379
|
+
if ((0, import_core6.isExternalImage)(imageData)) {
|
|
1380
|
+
subresources.push({
|
|
1381
|
+
type: "external-image",
|
|
1382
|
+
image: imageData,
|
|
1383
|
+
z,
|
|
1384
|
+
mipLevel
|
|
1385
|
+
});
|
|
1386
|
+
} else if (isTextureImageData(imageData)) {
|
|
1387
|
+
subresources.push({
|
|
1388
|
+
type: "texture-data",
|
|
1389
|
+
data: imageData,
|
|
1390
|
+
textureFormat: resolveTextureImageFormat(imageData),
|
|
1391
|
+
z,
|
|
1392
|
+
mipLevel
|
|
1393
|
+
});
|
|
1394
|
+
} else if (isTypedArrayMipLevelData(imageData) && baseLevelSize) {
|
|
1395
|
+
subresources.push({
|
|
1396
|
+
type: "texture-data",
|
|
1397
|
+
data: {
|
|
1398
|
+
data: imageData,
|
|
1399
|
+
width: Math.max(1, baseLevelSize.width >> mipLevel),
|
|
1400
|
+
height: Math.max(1, baseLevelSize.height >> mipLevel),
|
|
1401
|
+
...textureFormat ? { format: textureFormat } : {}
|
|
1402
|
+
},
|
|
1403
|
+
textureFormat,
|
|
1404
|
+
z,
|
|
1405
|
+
mipLevel
|
|
1406
|
+
});
|
|
1407
|
+
} else {
|
|
1408
|
+
throw new Error("Unsupported 2D mip-level payload");
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
return subresources;
|
|
1412
|
+
}
|
|
1413
|
+
function getTexture3DSubresources(data) {
|
|
1414
|
+
const subresources = [];
|
|
1415
|
+
for (let depth = 0; depth < data.length; depth++) {
|
|
1416
|
+
subresources.push(...getTexture2DSubresources(depth, data[depth]));
|
|
1417
|
+
}
|
|
1418
|
+
return subresources;
|
|
1419
|
+
}
|
|
1420
|
+
function getTextureArraySubresources(data) {
|
|
1421
|
+
const subresources = [];
|
|
1422
|
+
for (let layer = 0; layer < data.length; layer++) {
|
|
1423
|
+
subresources.push(...getTexture2DSubresources(layer, data[layer]));
|
|
1424
|
+
}
|
|
1425
|
+
return subresources;
|
|
1426
|
+
}
|
|
1427
|
+
function getTextureCubeSubresources(data) {
|
|
1428
|
+
const subresources = [];
|
|
1429
|
+
for (const [face, faceData] of Object.entries(data)) {
|
|
1430
|
+
const faceDepth = getCubeFaceIndex(face);
|
|
1431
|
+
subresources.push(...getTexture2DSubresources(faceDepth, faceData));
|
|
1432
|
+
}
|
|
1433
|
+
return subresources;
|
|
1434
|
+
}
|
|
1435
|
+
function getTextureCubeArraySubresources(data) {
|
|
1436
|
+
const subresources = [];
|
|
1437
|
+
data.forEach((cubeData, cubeIndex) => {
|
|
1438
|
+
for (const [face, faceData] of Object.entries(cubeData)) {
|
|
1439
|
+
const faceDepth = getCubeArrayFaceIndex(cubeIndex, face);
|
|
1440
|
+
subresources.push(...getTexture2DSubresources(faceDepth, faceData));
|
|
1334
1441
|
}
|
|
1335
1442
|
});
|
|
1443
|
+
return subresources;
|
|
1336
1444
|
}
|
|
1337
1445
|
|
|
1338
|
-
// dist/
|
|
1339
|
-
var
|
|
1340
|
-
var CubeFaces = ["+X", "-X", "+Y", "-Y", "+Z", "-Z"];
|
|
1341
|
-
var _AsyncTexture = class {
|
|
1446
|
+
// dist/dynamic-texture/dynamic-texture.js
|
|
1447
|
+
var _DynamicTexture = class {
|
|
1342
1448
|
device;
|
|
1343
1449
|
id;
|
|
1450
|
+
/** Props with defaults resolved (except `data` which is processed separately) */
|
|
1344
1451
|
props;
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
// @ts-expect-error
|
|
1351
|
-
view;
|
|
1452
|
+
/** Created resources */
|
|
1453
|
+
_texture = null;
|
|
1454
|
+
_sampler = null;
|
|
1455
|
+
_view = null;
|
|
1456
|
+
/** Ready when GPU texture has been created and data (if any) uploaded */
|
|
1352
1457
|
ready;
|
|
1353
1458
|
isReady = false;
|
|
1354
1459
|
destroyed = false;
|
|
@@ -1356,272 +1461,437 @@ var _AsyncTexture = class {
|
|
|
1356
1461
|
};
|
|
1357
1462
|
rejectReady = () => {
|
|
1358
1463
|
};
|
|
1464
|
+
get texture() {
|
|
1465
|
+
if (!this._texture)
|
|
1466
|
+
throw new Error("Texture not initialized yet");
|
|
1467
|
+
return this._texture;
|
|
1468
|
+
}
|
|
1469
|
+
get sampler() {
|
|
1470
|
+
if (!this._sampler)
|
|
1471
|
+
throw new Error("Sampler not initialized yet");
|
|
1472
|
+
return this._sampler;
|
|
1473
|
+
}
|
|
1474
|
+
get view() {
|
|
1475
|
+
if (!this._view)
|
|
1476
|
+
throw new Error("View not initialized yet");
|
|
1477
|
+
return this._view;
|
|
1478
|
+
}
|
|
1359
1479
|
get [Symbol.toStringTag]() {
|
|
1360
|
-
return "
|
|
1480
|
+
return "DynamicTexture";
|
|
1361
1481
|
}
|
|
1362
1482
|
toString() {
|
|
1363
|
-
return `
|
|
1483
|
+
return `DynamicTexture:"${this.id}":${this.texture.width}x${this.texture.height}px:(${this.isReady ? "ready" : "loading..."})`;
|
|
1364
1484
|
}
|
|
1365
1485
|
constructor(device, props) {
|
|
1366
1486
|
this.device = device;
|
|
1367
|
-
const id = uid("
|
|
1368
|
-
|
|
1487
|
+
const id = uid("dynamic-texture");
|
|
1488
|
+
const originalPropsWithAsyncData = props;
|
|
1489
|
+
this.props = { ..._DynamicTexture.defaultProps, id, ...props, data: null };
|
|
1369
1490
|
this.id = this.props.id;
|
|
1370
|
-
props = { ...props };
|
|
1371
|
-
if (typeof (props == null ? void 0 : props.data) === "string" && props.dimension === "2d") {
|
|
1372
|
-
props.data = loadImageBitmap(props.data);
|
|
1373
|
-
}
|
|
1374
|
-
if (props.mipmaps) {
|
|
1375
|
-
props.mipLevels = "auto";
|
|
1376
|
-
}
|
|
1377
1491
|
this.ready = new Promise((resolve, reject) => {
|
|
1378
|
-
this.resolveReady =
|
|
1379
|
-
this.isReady = true;
|
|
1380
|
-
resolve();
|
|
1381
|
-
};
|
|
1492
|
+
this.resolveReady = resolve;
|
|
1382
1493
|
this.rejectReady = reject;
|
|
1383
1494
|
});
|
|
1384
|
-
this.initAsync(
|
|
1495
|
+
this.initAsync(originalPropsWithAsyncData);
|
|
1385
1496
|
}
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
break;
|
|
1413
|
-
case "2d-array":
|
|
1414
|
-
this._setTextureArrayData(this.texture, data);
|
|
1415
|
-
break;
|
|
1416
|
-
case "cube":
|
|
1417
|
-
this._setTextureCubeData(this.texture, data);
|
|
1418
|
-
break;
|
|
1419
|
-
case "cube-array":
|
|
1420
|
-
this._setTextureCubeArrayData(this.texture, data);
|
|
1421
|
-
break;
|
|
1497
|
+
/** @note Fire and forget; caller can await `ready` */
|
|
1498
|
+
async initAsync(originalPropsWithAsyncData) {
|
|
1499
|
+
try {
|
|
1500
|
+
const propsWithSyncData = await this._loadAllData(originalPropsWithAsyncData);
|
|
1501
|
+
this._checkNotDestroyed();
|
|
1502
|
+
const subresources = propsWithSyncData.data ? getTextureSubresources({
|
|
1503
|
+
...propsWithSyncData,
|
|
1504
|
+
width: originalPropsWithAsyncData.width,
|
|
1505
|
+
height: originalPropsWithAsyncData.height,
|
|
1506
|
+
format: originalPropsWithAsyncData.format
|
|
1507
|
+
}) : [];
|
|
1508
|
+
const userProvidedFormat = "format" in originalPropsWithAsyncData && originalPropsWithAsyncData.format !== void 0;
|
|
1509
|
+
const userProvidedUsage = "usage" in originalPropsWithAsyncData && originalPropsWithAsyncData.usage !== void 0;
|
|
1510
|
+
const deduceSize = () => {
|
|
1511
|
+
if (this.props.width && this.props.height) {
|
|
1512
|
+
return { width: this.props.width, height: this.props.height };
|
|
1513
|
+
}
|
|
1514
|
+
const size2 = getTextureSizeFromData(propsWithSyncData);
|
|
1515
|
+
if (size2) {
|
|
1516
|
+
return size2;
|
|
1517
|
+
}
|
|
1518
|
+
return { width: this.props.width || 1, height: this.props.height || 1 };
|
|
1519
|
+
};
|
|
1520
|
+
const size = deduceSize();
|
|
1521
|
+
if (!size || size.width <= 0 || size.height <= 0) {
|
|
1522
|
+
throw new Error(`${this} size could not be determined or was zero`);
|
|
1422
1523
|
}
|
|
1524
|
+
const textureData = analyzeTextureSubresources(this.device, subresources, size, {
|
|
1525
|
+
format: userProvidedFormat ? originalPropsWithAsyncData.format : void 0
|
|
1526
|
+
});
|
|
1527
|
+
const resolvedFormat = textureData.format ?? this.props.format;
|
|
1528
|
+
const baseTextureProps = {
|
|
1529
|
+
...this.props,
|
|
1530
|
+
...size,
|
|
1531
|
+
format: resolvedFormat,
|
|
1532
|
+
mipLevels: 1,
|
|
1533
|
+
// temporary; updated below
|
|
1534
|
+
data: void 0
|
|
1535
|
+
};
|
|
1536
|
+
if (this.device.isTextureFormatCompressed(resolvedFormat) && !userProvidedUsage) {
|
|
1537
|
+
baseTextureProps.usage = import_core7.Texture.SAMPLE | import_core7.Texture.COPY_DST;
|
|
1538
|
+
}
|
|
1539
|
+
const shouldGenerateMipmaps = this.props.mipmaps && !textureData.hasExplicitMipChain && !this.device.isTextureFormatCompressed(resolvedFormat);
|
|
1540
|
+
if (this.device.type === "webgpu" && shouldGenerateMipmaps) {
|
|
1541
|
+
const requiredUsage = this.props.dimension === "3d" ? import_core7.Texture.SAMPLE | import_core7.Texture.STORAGE | import_core7.Texture.COPY_DST | import_core7.Texture.COPY_SRC : import_core7.Texture.SAMPLE | import_core7.Texture.RENDER | import_core7.Texture.COPY_DST | import_core7.Texture.COPY_SRC;
|
|
1542
|
+
baseTextureProps.usage |= requiredUsage;
|
|
1543
|
+
}
|
|
1544
|
+
const maxMips = this.device.getMipLevelCount(baseTextureProps.width, baseTextureProps.height);
|
|
1545
|
+
const desired = textureData.hasExplicitMipChain ? textureData.mipLevels : this.props.mipLevels === "auto" ? maxMips : Math.max(1, Math.min(maxMips, this.props.mipLevels ?? 1));
|
|
1546
|
+
const finalTextureProps = { ...baseTextureProps, mipLevels: desired };
|
|
1547
|
+
this._texture = this.device.createTexture(finalTextureProps);
|
|
1548
|
+
this._sampler = this.texture.sampler;
|
|
1549
|
+
this._view = this.texture.view;
|
|
1550
|
+
if (textureData.subresources.length) {
|
|
1551
|
+
this._setTextureSubresources(textureData.subresources);
|
|
1552
|
+
}
|
|
1553
|
+
if (this.props.mipmaps && !textureData.hasExplicitMipChain && !shouldGenerateMipmaps) {
|
|
1554
|
+
import_core7.log.warn(`${this} skipping auto-generated mipmaps for compressed texture format`)();
|
|
1555
|
+
}
|
|
1556
|
+
if (shouldGenerateMipmaps) {
|
|
1557
|
+
this.generateMipmaps();
|
|
1558
|
+
}
|
|
1559
|
+
this.isReady = true;
|
|
1560
|
+
this.resolveReady(this.texture);
|
|
1561
|
+
import_core7.log.info(0, `${this} created`)();
|
|
1562
|
+
} catch (e) {
|
|
1563
|
+
const err = e instanceof Error ? e : new Error(String(e));
|
|
1564
|
+
this.rejectReady(err);
|
|
1423
1565
|
}
|
|
1424
|
-
if (this.props.mipmaps) {
|
|
1425
|
-
this.generateMipmaps();
|
|
1426
|
-
}
|
|
1427
|
-
import_core8.log.info(1, `${this} loaded`);
|
|
1428
|
-
this.resolveReady();
|
|
1429
1566
|
}
|
|
1430
1567
|
destroy() {
|
|
1431
|
-
if (this.
|
|
1432
|
-
this.
|
|
1433
|
-
this.
|
|
1568
|
+
if (this._texture) {
|
|
1569
|
+
this._texture.destroy();
|
|
1570
|
+
this._texture = null;
|
|
1571
|
+
this._sampler = null;
|
|
1572
|
+
this._view = null;
|
|
1434
1573
|
}
|
|
1435
1574
|
this.destroyed = true;
|
|
1436
1575
|
}
|
|
1437
1576
|
generateMipmaps() {
|
|
1438
|
-
this.
|
|
1577
|
+
if (this.device.type === "webgl") {
|
|
1578
|
+
this.texture.generateMipmapsWebGL();
|
|
1579
|
+
} else if (this.device.type === "webgpu") {
|
|
1580
|
+
this.device.generateMipmapsWebGPU(this.texture);
|
|
1581
|
+
} else {
|
|
1582
|
+
import_core7.log.warn(`${this} mipmaps not supported on ${this.device.type}`);
|
|
1583
|
+
}
|
|
1439
1584
|
}
|
|
1440
|
-
/** Set sampler or create
|
|
1585
|
+
/** Set sampler or create one from props */
|
|
1441
1586
|
setSampler(sampler = {}) {
|
|
1442
|
-
this.
|
|
1587
|
+
this._checkReady();
|
|
1588
|
+
const s = sampler instanceof import_core7.Sampler ? sampler : this.device.createSampler(sampler);
|
|
1589
|
+
this.texture.setSampler(s);
|
|
1590
|
+
this._sampler = s;
|
|
1443
1591
|
}
|
|
1444
1592
|
/**
|
|
1445
|
-
*
|
|
1446
|
-
*
|
|
1447
|
-
* @note Does not copy contents of the texture
|
|
1448
|
-
* @note Mipmaps may need to be regenerated after resizing / setting new data
|
|
1449
|
-
* @todo Abort pending promise and create a texture with the new size?
|
|
1593
|
+
* Copies texture contents into a GPU buffer and waits until the copy is complete.
|
|
1594
|
+
* The caller owns the returned buffer and must destroy it when finished.
|
|
1450
1595
|
*/
|
|
1451
|
-
|
|
1596
|
+
async readBuffer(options = {}) {
|
|
1597
|
+
if (!this.isReady) {
|
|
1598
|
+
await this.ready;
|
|
1599
|
+
}
|
|
1600
|
+
const width = options.width ?? this.texture.width;
|
|
1601
|
+
const height = options.height ?? this.texture.height;
|
|
1602
|
+
const depthOrArrayLayers = options.depthOrArrayLayers ?? this.texture.depth;
|
|
1603
|
+
const layout = this.texture.computeMemoryLayout({ width, height, depthOrArrayLayers });
|
|
1604
|
+
const buffer = this.device.createBuffer({
|
|
1605
|
+
byteLength: layout.byteLength,
|
|
1606
|
+
usage: import_core7.Buffer.COPY_DST | import_core7.Buffer.MAP_READ
|
|
1607
|
+
});
|
|
1608
|
+
this.texture.readBuffer({
|
|
1609
|
+
...options,
|
|
1610
|
+
width,
|
|
1611
|
+
height,
|
|
1612
|
+
depthOrArrayLayers
|
|
1613
|
+
}, buffer);
|
|
1614
|
+
const fence = this.device.createFence();
|
|
1615
|
+
await fence.signaled;
|
|
1616
|
+
fence.destroy();
|
|
1617
|
+
return buffer;
|
|
1618
|
+
}
|
|
1619
|
+
/** Reads texture contents back to CPU memory. */
|
|
1620
|
+
async readAsync(options = {}) {
|
|
1452
1621
|
if (!this.isReady) {
|
|
1453
|
-
|
|
1622
|
+
await this.ready;
|
|
1454
1623
|
}
|
|
1624
|
+
const width = options.width ?? this.texture.width;
|
|
1625
|
+
const height = options.height ?? this.texture.height;
|
|
1626
|
+
const depthOrArrayLayers = options.depthOrArrayLayers ?? this.texture.depth;
|
|
1627
|
+
const layout = this.texture.computeMemoryLayout({ width, height, depthOrArrayLayers });
|
|
1628
|
+
const buffer = await this.readBuffer(options);
|
|
1629
|
+
const data = await buffer.readAsync(0, layout.byteLength);
|
|
1630
|
+
buffer.destroy();
|
|
1631
|
+
return data.buffer;
|
|
1632
|
+
}
|
|
1633
|
+
/**
|
|
1634
|
+
* Resize by cloning the underlying immutable texture.
|
|
1635
|
+
* Does not copy contents; caller may need to re-upload and/or regenerate mips.
|
|
1636
|
+
*/
|
|
1637
|
+
resize(size) {
|
|
1638
|
+
this._checkReady();
|
|
1455
1639
|
if (size.width === this.texture.width && size.height === this.texture.height) {
|
|
1456
1640
|
return false;
|
|
1457
1641
|
}
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1642
|
+
const prev = this.texture;
|
|
1643
|
+
this._texture = prev.clone(size);
|
|
1644
|
+
this._sampler = this.texture.sampler;
|
|
1645
|
+
this._view = this.texture.view;
|
|
1646
|
+
prev.destroy();
|
|
1647
|
+
import_core7.log.info(`${this} resized`);
|
|
1463
1648
|
return true;
|
|
1464
1649
|
}
|
|
1465
|
-
/**
|
|
1466
|
-
|
|
1467
|
-
const
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
}
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1650
|
+
/** Convert cube face label to texture slice index. Index can be used with `setTexture2DData()`. */
|
|
1651
|
+
getCubeFaceIndex(face) {
|
|
1652
|
+
const index = TEXTURE_CUBE_FACE_MAP[face];
|
|
1653
|
+
if (index === void 0)
|
|
1654
|
+
throw new Error(`Invalid cube face: ${face}`);
|
|
1655
|
+
return index;
|
|
1656
|
+
}
|
|
1657
|
+
/** Convert cube face label to texture slice index. Index can be used with `setTexture2DData()`. */
|
|
1658
|
+
getCubeArrayFaceIndex(cubeIndex, face) {
|
|
1659
|
+
return 6 * cubeIndex + this.getCubeFaceIndex(face);
|
|
1660
|
+
}
|
|
1661
|
+
/** @note experimental: Set multiple mip levels (1D) */
|
|
1662
|
+
setTexture1DData(data) {
|
|
1663
|
+
this._checkReady();
|
|
1664
|
+
if (this.texture.props.dimension !== "1d") {
|
|
1665
|
+
throw new Error(`${this} is not 1d`);
|
|
1666
|
+
}
|
|
1667
|
+
const subresources = getTexture1DSubresources(data);
|
|
1668
|
+
this._setTextureSubresources(subresources);
|
|
1669
|
+
}
|
|
1670
|
+
/** @note experimental: Set multiple mip levels (2D), optionally at `z`, slice (depth/array level) index */
|
|
1671
|
+
setTexture2DData(lodData, z = 0) {
|
|
1672
|
+
this._checkReady();
|
|
1673
|
+
if (this.texture.props.dimension !== "2d") {
|
|
1674
|
+
throw new Error(`${this} is not 2d`);
|
|
1675
|
+
}
|
|
1676
|
+
const subresources = getTexture2DSubresources(z, lodData);
|
|
1677
|
+
this._setTextureSubresources(subresources);
|
|
1678
|
+
}
|
|
1679
|
+
/** 3D: multiple depth slices, each may carry multiple mip levels */
|
|
1680
|
+
setTexture3DData(data) {
|
|
1681
|
+
if (this.texture.props.dimension !== "3d") {
|
|
1682
|
+
throw new Error(`${this} is not 3d`);
|
|
1683
|
+
}
|
|
1684
|
+
const subresources = getTexture3DSubresources(data);
|
|
1685
|
+
this._setTextureSubresources(subresources);
|
|
1686
|
+
}
|
|
1687
|
+
/** 2D array: multiple layers, each may carry multiple mip levels */
|
|
1688
|
+
setTextureArrayData(data) {
|
|
1689
|
+
if (this.texture.props.dimension !== "2d-array") {
|
|
1690
|
+
throw new Error(`${this} is not 2d-array`);
|
|
1691
|
+
}
|
|
1692
|
+
const subresources = getTextureArraySubresources(data);
|
|
1693
|
+
this._setTextureSubresources(subresources);
|
|
1694
|
+
}
|
|
1695
|
+
/** Cube: 6 faces, each may carry multiple mip levels */
|
|
1696
|
+
setTextureCubeData(data) {
|
|
1697
|
+
if (this.texture.props.dimension !== "cube") {
|
|
1698
|
+
throw new Error(`${this} is not cube`);
|
|
1699
|
+
}
|
|
1700
|
+
const subresources = getTextureCubeSubresources(data);
|
|
1701
|
+
this._setTextureSubresources(subresources);
|
|
1702
|
+
}
|
|
1703
|
+
/** Cube array: multiple cubes (faces×layers), each face may carry multiple mips */
|
|
1704
|
+
setTextureCubeArrayData(data) {
|
|
1705
|
+
if (this.texture.props.dimension !== "cube-array") {
|
|
1706
|
+
throw new Error(`${this} is not cube-array`);
|
|
1707
|
+
}
|
|
1708
|
+
const subresources = getTextureCubeArraySubresources(data);
|
|
1709
|
+
this._setTextureSubresources(subresources);
|
|
1710
|
+
}
|
|
1711
|
+
/** Sets multiple mip levels on different `z` slices (depth/array index) */
|
|
1712
|
+
_setTextureSubresources(subresources) {
|
|
1713
|
+
for (const subresource of subresources) {
|
|
1714
|
+
const { z, mipLevel } = subresource;
|
|
1715
|
+
switch (subresource.type) {
|
|
1716
|
+
case "external-image":
|
|
1717
|
+
const { image, flipY } = subresource;
|
|
1718
|
+
this.texture.copyExternalImage({ image, z, mipLevel, flipY });
|
|
1719
|
+
break;
|
|
1720
|
+
case "texture-data":
|
|
1721
|
+
const { data, textureFormat } = subresource;
|
|
1722
|
+
if (textureFormat && textureFormat !== this.texture.format) {
|
|
1723
|
+
throw new Error(`${this} mip level ${mipLevel} uses format "${textureFormat}" but texture format is "${this.texture.format}"`);
|
|
1724
|
+
}
|
|
1725
|
+
this.texture.writeData(data.data, {
|
|
1726
|
+
x: 0,
|
|
1727
|
+
y: 0,
|
|
1728
|
+
z,
|
|
1729
|
+
width: data.width,
|
|
1730
|
+
height: data.height,
|
|
1731
|
+
depthOrArrayLayers: 1,
|
|
1732
|
+
mipLevel
|
|
1733
|
+
});
|
|
1734
|
+
break;
|
|
1735
|
+
default:
|
|
1736
|
+
throw new Error("Unsupported 2D mip-level payload");
|
|
1532
1737
|
}
|
|
1533
1738
|
}
|
|
1534
1739
|
}
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
if (((_a = this.texture) == null ? void 0 : _a.props.dimension) !== "3d") {
|
|
1542
|
-
throw new Error(this.id);
|
|
1543
|
-
}
|
|
1544
|
-
for (let depth = 0; depth < data.length; depth++) {
|
|
1545
|
-
this._setTexture2DData(data[depth], depth);
|
|
1546
|
-
}
|
|
1740
|
+
// ------------------ helpers ------------------
|
|
1741
|
+
/** Recursively resolve all promises in data structures */
|
|
1742
|
+
async _loadAllData(props) {
|
|
1743
|
+
const syncData = await awaitAllPromises(props.data);
|
|
1744
|
+
const dimension = props.dimension ?? "2d";
|
|
1745
|
+
return { dimension, data: syncData ?? null };
|
|
1547
1746
|
}
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
* @param data
|
|
1552
|
-
* @param index
|
|
1553
|
-
*/
|
|
1554
|
-
_setTextureCubeData(texture, data) {
|
|
1555
|
-
var _a;
|
|
1556
|
-
if (((_a = this.texture) == null ? void 0 : _a.props.dimension) !== "cube") {
|
|
1557
|
-
throw new Error(this.id);
|
|
1558
|
-
}
|
|
1559
|
-
for (const [face, faceData] of Object.entries(data)) {
|
|
1560
|
-
const faceDepth = CubeFaces.indexOf(face);
|
|
1561
|
-
this._setTexture2DData(faceData, faceDepth);
|
|
1747
|
+
_checkNotDestroyed() {
|
|
1748
|
+
if (this.destroyed) {
|
|
1749
|
+
import_core7.log.warn(`${this} already destroyed`);
|
|
1562
1750
|
}
|
|
1563
1751
|
}
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
*/
|
|
1568
|
-
_setTextureArrayData(texture, data) {
|
|
1569
|
-
var _a;
|
|
1570
|
-
if (((_a = this.texture) == null ? void 0 : _a.props.dimension) !== "2d-array") {
|
|
1571
|
-
throw new Error(this.id);
|
|
1572
|
-
}
|
|
1573
|
-
for (let depth = 0; depth < data.length; depth++) {
|
|
1574
|
-
this._setTexture2DData(data[depth], depth);
|
|
1752
|
+
_checkReady() {
|
|
1753
|
+
if (!this.isReady) {
|
|
1754
|
+
import_core7.log.warn(`${this} Cannot perform this operation before ready`);
|
|
1575
1755
|
}
|
|
1576
1756
|
}
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1757
|
+
};
|
|
1758
|
+
var DynamicTexture = _DynamicTexture;
|
|
1759
|
+
__publicField(DynamicTexture, "defaultProps", {
|
|
1760
|
+
...import_core7.Texture.defaultProps,
|
|
1761
|
+
dimension: "2d",
|
|
1762
|
+
data: null,
|
|
1763
|
+
mipmaps: false
|
|
1764
|
+
});
|
|
1765
|
+
function getTextureSubresources(props) {
|
|
1766
|
+
if (!props.data) {
|
|
1767
|
+
return [];
|
|
1768
|
+
}
|
|
1769
|
+
const baseLevelSize = props.width && props.height ? { width: props.width, height: props.height } : void 0;
|
|
1770
|
+
const textureFormat = "format" in props ? props.format : void 0;
|
|
1771
|
+
switch (props.dimension) {
|
|
1772
|
+
case "1d":
|
|
1773
|
+
return getTexture1DSubresources(props.data);
|
|
1774
|
+
case "2d":
|
|
1775
|
+
return getTexture2DSubresources(0, props.data, baseLevelSize, textureFormat);
|
|
1776
|
+
case "3d":
|
|
1777
|
+
return getTexture3DSubresources(props.data);
|
|
1778
|
+
case "2d-array":
|
|
1779
|
+
return getTextureArraySubresources(props.data);
|
|
1780
|
+
case "cube":
|
|
1781
|
+
return getTextureCubeSubresources(props.data);
|
|
1782
|
+
case "cube-array":
|
|
1783
|
+
return getTextureCubeArraySubresources(props.data);
|
|
1784
|
+
default:
|
|
1785
|
+
throw new Error(`Unhandled dimension ${props.dimension}`);
|
|
1583
1786
|
}
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1787
|
+
}
|
|
1788
|
+
function analyzeTextureSubresources(device, subresources, size, options) {
|
|
1789
|
+
if (subresources.length === 0) {
|
|
1790
|
+
return {
|
|
1791
|
+
subresources,
|
|
1792
|
+
mipLevels: 1,
|
|
1793
|
+
format: options.format,
|
|
1794
|
+
hasExplicitMipChain: false
|
|
1795
|
+
};
|
|
1591
1796
|
}
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1797
|
+
const groupedSubresources = /* @__PURE__ */ new Map();
|
|
1798
|
+
for (const subresource of subresources) {
|
|
1799
|
+
const group = groupedSubresources.get(subresource.z) ?? [];
|
|
1800
|
+
group.push(subresource);
|
|
1801
|
+
groupedSubresources.set(subresource.z, group);
|
|
1802
|
+
}
|
|
1803
|
+
const hasExplicitMipChain = subresources.some((subresource) => subresource.mipLevel > 0);
|
|
1804
|
+
let resolvedFormat = options.format;
|
|
1805
|
+
let resolvedMipLevels = Number.POSITIVE_INFINITY;
|
|
1806
|
+
const validSubresources = [];
|
|
1807
|
+
for (const [z, sliceSubresources] of groupedSubresources) {
|
|
1808
|
+
const sortedSubresources = [...sliceSubresources].sort((left, right) => left.mipLevel - right.mipLevel);
|
|
1809
|
+
const baseLevel = sortedSubresources[0];
|
|
1810
|
+
if (!baseLevel || baseLevel.mipLevel !== 0) {
|
|
1811
|
+
throw new Error(`DynamicTexture: slice ${z} is missing mip level 0`);
|
|
1812
|
+
}
|
|
1813
|
+
const baseSize = getTextureSubresourceSize(device, baseLevel);
|
|
1814
|
+
if (baseSize.width !== size.width || baseSize.height !== size.height) {
|
|
1815
|
+
throw new Error(`DynamicTexture: slice ${z} base level dimensions ${baseSize.width}x${baseSize.height} do not match expected ${size.width}x${size.height}`);
|
|
1816
|
+
}
|
|
1817
|
+
const baseFormat = getTextureSubresourceFormat(baseLevel);
|
|
1818
|
+
if (baseFormat) {
|
|
1819
|
+
if (resolvedFormat && resolvedFormat !== baseFormat) {
|
|
1820
|
+
throw new Error(`DynamicTexture: slice ${z} base level format "${baseFormat}" does not match texture format "${resolvedFormat}"`);
|
|
1821
|
+
}
|
|
1822
|
+
resolvedFormat = baseFormat;
|
|
1823
|
+
}
|
|
1824
|
+
const mipLevelLimit = resolvedFormat && device.isTextureFormatCompressed(resolvedFormat) ? (
|
|
1825
|
+
// Block-compressed formats cannot have mips smaller than a single compression block.
|
|
1826
|
+
getMaxCompressedMipLevels(device, baseSize.width, baseSize.height, resolvedFormat)
|
|
1827
|
+
) : device.getMipLevelCount(baseSize.width, baseSize.height);
|
|
1828
|
+
let validMipLevelsForSlice = 0;
|
|
1829
|
+
for (let expectedMipLevel = 0; expectedMipLevel < sortedSubresources.length; expectedMipLevel++) {
|
|
1830
|
+
const subresource = sortedSubresources[expectedMipLevel];
|
|
1831
|
+
if (!subresource || subresource.mipLevel !== expectedMipLevel) {
|
|
1832
|
+
break;
|
|
1833
|
+
}
|
|
1834
|
+
if (expectedMipLevel >= mipLevelLimit) {
|
|
1835
|
+
break;
|
|
1836
|
+
}
|
|
1837
|
+
const subresourceSize = getTextureSubresourceSize(device, subresource);
|
|
1838
|
+
const expectedWidth = Math.max(1, baseSize.width >> expectedMipLevel);
|
|
1839
|
+
const expectedHeight = Math.max(1, baseSize.height >> expectedMipLevel);
|
|
1840
|
+
if (subresourceSize.width !== expectedWidth || subresourceSize.height !== expectedHeight) {
|
|
1841
|
+
break;
|
|
1842
|
+
}
|
|
1843
|
+
const subresourceFormat = getTextureSubresourceFormat(subresource);
|
|
1844
|
+
if (subresourceFormat) {
|
|
1845
|
+
if (!resolvedFormat) {
|
|
1846
|
+
resolvedFormat = subresourceFormat;
|
|
1609
1847
|
}
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1848
|
+
if (subresourceFormat !== resolvedFormat) {
|
|
1849
|
+
break;
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1852
|
+
validMipLevelsForSlice++;
|
|
1853
|
+
validSubresources.push(subresource);
|
|
1615
1854
|
}
|
|
1616
|
-
|
|
1855
|
+
resolvedMipLevels = Math.min(resolvedMipLevels, validMipLevelsForSlice);
|
|
1617
1856
|
}
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1857
|
+
const mipLevels = Number.isFinite(resolvedMipLevels) ? Math.max(1, resolvedMipLevels) : 1;
|
|
1858
|
+
return {
|
|
1859
|
+
// Keep every slice trimmed to the same mip count so the texture shape stays internally consistent.
|
|
1860
|
+
subresources: validSubresources.filter((subresource) => subresource.mipLevel < mipLevels),
|
|
1861
|
+
mipLevels,
|
|
1862
|
+
format: resolvedFormat,
|
|
1863
|
+
hasExplicitMipChain
|
|
1864
|
+
};
|
|
1865
|
+
}
|
|
1866
|
+
function getTextureSubresourceFormat(subresource) {
|
|
1867
|
+
if (subresource.type !== "texture-data") {
|
|
1868
|
+
return void 0;
|
|
1869
|
+
}
|
|
1870
|
+
return subresource.textureFormat ?? resolveTextureImageFormat(subresource.data);
|
|
1871
|
+
}
|
|
1872
|
+
function getTextureSubresourceSize(device, subresource) {
|
|
1873
|
+
switch (subresource.type) {
|
|
1874
|
+
case "external-image":
|
|
1875
|
+
return device.getExternalImageSize(subresource.image);
|
|
1876
|
+
case "texture-data":
|
|
1877
|
+
return { width: subresource.data.width, height: subresource.data.height };
|
|
1878
|
+
default:
|
|
1879
|
+
throw new Error("Unsupported texture subresource");
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
function getMaxCompressedMipLevels(device, baseWidth, baseHeight, format) {
|
|
1883
|
+
const { blockWidth = 1, blockHeight = 1 } = device.getTextureFormatInfo(format);
|
|
1884
|
+
let mipLevels = 1;
|
|
1885
|
+
for (let mipLevel = 1; ; mipLevel++) {
|
|
1886
|
+
const width = Math.max(1, baseWidth >> mipLevel);
|
|
1887
|
+
const height = Math.max(1, baseHeight >> mipLevel);
|
|
1888
|
+
if (width < blockWidth || height < blockHeight) {
|
|
1889
|
+
break;
|
|
1890
|
+
}
|
|
1891
|
+
mipLevels++;
|
|
1892
|
+
}
|
|
1893
|
+
return mipLevels;
|
|
1894
|
+
}
|
|
1625
1895
|
async function awaitAllPromises(x) {
|
|
1626
1896
|
x = await x;
|
|
1627
1897
|
if (Array.isArray(x)) {
|
|
@@ -1629,7 +1899,7 @@ async function awaitAllPromises(x) {
|
|
|
1629
1899
|
}
|
|
1630
1900
|
if (x && typeof x === "object" && x.constructor === Object) {
|
|
1631
1901
|
const object = x;
|
|
1632
|
-
const values = await Promise.all(Object.values(object));
|
|
1902
|
+
const values = await Promise.all(Object.values(object).map(awaitAllPromises));
|
|
1633
1903
|
const keys = Object.keys(object);
|
|
1634
1904
|
const resolvedObject = {};
|
|
1635
1905
|
for (let i = 0; i < keys.length; i++) {
|
|
@@ -1644,16 +1914,24 @@ async function awaitAllPromises(x) {
|
|
|
1644
1914
|
var LOG_DRAW_PRIORITY = 2;
|
|
1645
1915
|
var LOG_DRAW_TIMEOUT = 1e4;
|
|
1646
1916
|
var _Model = class {
|
|
1917
|
+
/** Device that created this model */
|
|
1647
1918
|
device;
|
|
1919
|
+
/** Application provided identifier */
|
|
1648
1920
|
id;
|
|
1921
|
+
/** WGSL shader source when using unified shader */
|
|
1649
1922
|
// @ts-expect-error assigned in function called from constructor
|
|
1650
1923
|
source;
|
|
1924
|
+
/** GLSL vertex shader source */
|
|
1651
1925
|
// @ts-expect-error assigned in function called from constructor
|
|
1652
1926
|
vs;
|
|
1927
|
+
/** GLSL fragment shader source */
|
|
1653
1928
|
// @ts-expect-error assigned in function called from constructor
|
|
1654
1929
|
fs;
|
|
1930
|
+
/** Factory used to create render pipelines */
|
|
1655
1931
|
pipelineFactory;
|
|
1932
|
+
/** Factory used to create shaders */
|
|
1656
1933
|
shaderFactory;
|
|
1934
|
+
/** User-supplied per-model data */
|
|
1657
1935
|
userData = {};
|
|
1658
1936
|
// Fixed properties (change can trigger pipeline rebuild)
|
|
1659
1937
|
/** The render pipeline GPU parameters, depth testing etc */
|
|
@@ -1690,6 +1968,7 @@ var _Model = class {
|
|
|
1690
1968
|
/** ShaderInputs instance */
|
|
1691
1969
|
// @ts-expect-error Assigned in function called by constructor
|
|
1692
1970
|
shaderInputs;
|
|
1971
|
+
material = null;
|
|
1693
1972
|
// @ts-expect-error Assigned in function called by constructor
|
|
1694
1973
|
_uniformStore;
|
|
1695
1974
|
_attributeInfos = {};
|
|
@@ -1700,6 +1979,7 @@ var _Model = class {
|
|
|
1700
1979
|
_destroyed = false;
|
|
1701
1980
|
/** "Time" of last draw. Monotonically increasing timestamp */
|
|
1702
1981
|
_lastDrawTimestamp = -1;
|
|
1982
|
+
_bindingTable = [];
|
|
1703
1983
|
get [Symbol.toStringTag]() {
|
|
1704
1984
|
return "Model";
|
|
1705
1985
|
}
|
|
@@ -1707,12 +1987,13 @@ var _Model = class {
|
|
|
1707
1987
|
return `Model(${this.id})`;
|
|
1708
1988
|
}
|
|
1709
1989
|
constructor(device, props) {
|
|
1710
|
-
var _a, _b, _c;
|
|
1990
|
+
var _a, _b, _c, _d;
|
|
1711
1991
|
this.props = { ..._Model.defaultProps, ...props };
|
|
1712
1992
|
props = this.props;
|
|
1713
1993
|
this.id = props.id || uid("model");
|
|
1714
1994
|
this.device = device;
|
|
1715
1995
|
Object.assign(this.userData, props.userData);
|
|
1996
|
+
this.material = props.material || null;
|
|
1716
1997
|
const moduleMap = Object.fromEntries(((_a = this.props.modules) == null ? void 0 : _a.map((module2) => [module2.name, module2])) || []);
|
|
1717
1998
|
const shaderInputs = props.shaderInputs || new ShaderInputs(moduleMap, { disableWarnings: this.props.disableWarnings });
|
|
1718
1999
|
this.setShaderInputs(shaderInputs);
|
|
@@ -1721,16 +2002,19 @@ var _Model = class {
|
|
|
1721
2002
|
// @ts-ignore shaderInputs is assigned in setShaderInputs above.
|
|
1722
2003
|
(((_b = this.props.modules) == null ? void 0 : _b.length) > 0 ? this.props.modules : (_c = this.shaderInputs) == null ? void 0 : _c.getModules()) || []
|
|
1723
2004
|
);
|
|
2005
|
+
this.props.shaderLayout = mergeShaderModuleBindingsIntoLayout(this.props.shaderLayout, modules) || null;
|
|
1724
2006
|
const isWebGPU = this.device.type === "webgpu";
|
|
1725
2007
|
if (isWebGPU && this.props.source) {
|
|
1726
|
-
const { source: source3, getUniforms: getUniforms2 } = this.props.shaderAssembler.assembleWGSLShader({
|
|
2008
|
+
const { source: source3, getUniforms: getUniforms2, bindingTable } = this.props.shaderAssembler.assembleWGSLShader({
|
|
1727
2009
|
platformInfo,
|
|
1728
2010
|
...this.props,
|
|
1729
2011
|
modules
|
|
1730
2012
|
});
|
|
1731
2013
|
this.source = source3;
|
|
1732
2014
|
this._getModuleUniforms = getUniforms2;
|
|
1733
|
-
this.
|
|
2015
|
+
this._bindingTable = bindingTable;
|
|
2016
|
+
const inferredShaderLayout = (_d = device.getShaderLayout) == null ? void 0 : _d.call(device, this.source);
|
|
2017
|
+
this.props.shaderLayout = mergeShaderModuleBindingsIntoLayout(this.props.shaderLayout || inferredShaderLayout || null, modules) || null;
|
|
1734
2018
|
} else {
|
|
1735
2019
|
const { vs: vs3, fs: fs3, getUniforms: getUniforms2 } = this.props.shaderAssembler.assembleGLSLShaderPair({
|
|
1736
2020
|
platformInfo,
|
|
@@ -1740,6 +2024,7 @@ var _Model = class {
|
|
|
1740
2024
|
this.vs = vs3;
|
|
1741
2025
|
this.fs = fs3;
|
|
1742
2026
|
this._getModuleUniforms = getUniforms2;
|
|
2027
|
+
this._bindingTable = [];
|
|
1743
2028
|
}
|
|
1744
2029
|
this.vertexCount = this.props.vertexCount;
|
|
1745
2030
|
this.instanceCount = this.props.instanceCount;
|
|
@@ -1749,8 +2034,8 @@ var _Model = class {
|
|
|
1749
2034
|
if (props.geometry) {
|
|
1750
2035
|
this.setGeometry(props.geometry);
|
|
1751
2036
|
}
|
|
1752
|
-
this.pipelineFactory = props.pipelineFactory || PipelineFactory.getDefaultPipelineFactory(this.device);
|
|
1753
|
-
this.shaderFactory = props.shaderFactory || ShaderFactory.getDefaultShaderFactory(this.device);
|
|
2037
|
+
this.pipelineFactory = props.pipelineFactory || import_core8.PipelineFactory.getDefaultPipelineFactory(this.device);
|
|
2038
|
+
this.shaderFactory = props.shaderFactory || import_core8.ShaderFactory.getDefaultShaderFactory(this.device);
|
|
1754
2039
|
this.pipeline = this._updatePipeline();
|
|
1755
2040
|
this.vertexArray = device.createVertexArray({
|
|
1756
2041
|
shaderLayout: this.pipeline.shaderLayout,
|
|
@@ -1783,14 +2068,13 @@ var _Model = class {
|
|
|
1783
2068
|
if (props.transformFeedback) {
|
|
1784
2069
|
this.transformFeedback = props.transformFeedback;
|
|
1785
2070
|
}
|
|
1786
|
-
Object.seal(this);
|
|
1787
2071
|
}
|
|
1788
2072
|
destroy() {
|
|
1789
2073
|
var _a;
|
|
1790
2074
|
if (!this._destroyed) {
|
|
1791
2075
|
this.pipelineFactory.release(this.pipeline);
|
|
1792
2076
|
this.shaderFactory.release(this.pipeline.vs);
|
|
1793
|
-
if (this.pipeline.fs) {
|
|
2077
|
+
if (this.pipeline.fs && this.pipeline.fs !== this.pipeline.vs) {
|
|
1794
2078
|
this.shaderFactory.release(this.pipeline.fs);
|
|
1795
2079
|
}
|
|
1796
2080
|
this._uniformStore.destroy();
|
|
@@ -1812,14 +2096,24 @@ var _Model = class {
|
|
|
1812
2096
|
setNeedsRedraw(reason) {
|
|
1813
2097
|
this._needsRedraw ||= reason;
|
|
1814
2098
|
}
|
|
2099
|
+
/** Returns WGSL binding debug rows for the assembled shader. Returns an empty array for GLSL models. */
|
|
2100
|
+
getBindingDebugTable() {
|
|
2101
|
+
return this._bindingTable;
|
|
2102
|
+
}
|
|
2103
|
+
/** Update uniforms and pipeline state prior to drawing. */
|
|
1815
2104
|
predraw() {
|
|
1816
2105
|
this.updateShaderInputs();
|
|
1817
2106
|
this.pipeline = this._updatePipeline();
|
|
1818
2107
|
}
|
|
2108
|
+
/**
|
|
2109
|
+
* Issue one draw call.
|
|
2110
|
+
* @param renderPass - render pass to draw into
|
|
2111
|
+
* @returns `true` if the draw call was executed, `false` if resources were not ready.
|
|
2112
|
+
*/
|
|
1819
2113
|
draw(renderPass) {
|
|
1820
2114
|
const loadingBinding = this._areBindingsLoading();
|
|
1821
2115
|
if (loadingBinding) {
|
|
1822
|
-
|
|
2116
|
+
import_core8.log.info(LOG_DRAW_PRIORITY, `>>> DRAWING ABORTED ${this.id}: ${loadingBinding} not loaded`)();
|
|
1823
2117
|
return false;
|
|
1824
2118
|
}
|
|
1825
2119
|
try {
|
|
@@ -1834,9 +2128,7 @@ var _Model = class {
|
|
|
1834
2128
|
this._logDrawCallStart();
|
|
1835
2129
|
this.pipeline = this._updatePipeline();
|
|
1836
2130
|
const syncBindings = this._getBindings();
|
|
1837
|
-
this.
|
|
1838
|
-
disableWarnings: this.props.disableWarnings
|
|
1839
|
-
});
|
|
2131
|
+
const syncBindGroups = this._getBindGroups();
|
|
1840
2132
|
const { indexBuffer } = this.vertexArray;
|
|
1841
2133
|
const indexCount = indexBuffer ? indexBuffer.byteLength / (indexBuffer.indexType === "uint32" ? 4 : 2) : void 0;
|
|
1842
2134
|
drawSuccess = this.pipeline.draw({
|
|
@@ -1847,6 +2139,13 @@ var _Model = class {
|
|
|
1847
2139
|
instanceCount: this.instanceCount,
|
|
1848
2140
|
indexCount,
|
|
1849
2141
|
transformFeedback: this.transformFeedback || void 0,
|
|
2142
|
+
// Pipelines may be shared across models when caching is enabled, so bindings
|
|
2143
|
+
// and WebGL uniforms must be supplied on every draw instead of being stored
|
|
2144
|
+
// on the pipeline instance.
|
|
2145
|
+
bindings: syncBindings,
|
|
2146
|
+
bindGroups: syncBindGroups,
|
|
2147
|
+
_bindGroupCacheKeys: this._getBindGroupCacheKeys(),
|
|
2148
|
+
uniforms: this.props.uniforms,
|
|
1850
2149
|
// WebGL shares underlying cached pipelines even for models that have different parameters and topology,
|
|
1851
2150
|
// so we must provide our unique parameters to each draw
|
|
1852
2151
|
// (In WebGPU most parameters are encoded in the pipeline and cannot be changed per draw call)
|
|
@@ -1946,20 +2245,25 @@ var _Model = class {
|
|
|
1946
2245
|
}
|
|
1947
2246
|
/** Set the shader inputs */
|
|
1948
2247
|
setShaderInputs(shaderInputs) {
|
|
2248
|
+
var _a;
|
|
1949
2249
|
this.shaderInputs = shaderInputs;
|
|
1950
|
-
this._uniformStore = new
|
|
2250
|
+
this._uniformStore = new import_core8.UniformStore(this.device, this.shaderInputs.modules);
|
|
1951
2251
|
for (const [moduleName, module2] of Object.entries(this.shaderInputs.modules)) {
|
|
1952
|
-
if (shaderModuleHasUniforms(module2)) {
|
|
1953
|
-
const uniformBuffer = this._uniformStore.getManagedUniformBuffer(
|
|
2252
|
+
if (shaderModuleHasUniforms(module2) && !((_a = this.material) == null ? void 0 : _a.ownsModule(moduleName))) {
|
|
2253
|
+
const uniformBuffer = this._uniformStore.getManagedUniformBuffer(moduleName);
|
|
1954
2254
|
this.bindings[`${moduleName}Uniforms`] = uniformBuffer;
|
|
1955
2255
|
}
|
|
1956
2256
|
}
|
|
1957
2257
|
this.setNeedsRedraw("shaderInputs");
|
|
1958
2258
|
}
|
|
2259
|
+
setMaterial(material) {
|
|
2260
|
+
this.material = material;
|
|
2261
|
+
this.setNeedsRedraw("material");
|
|
2262
|
+
}
|
|
1959
2263
|
/** Update uniform buffers from the model's shader inputs */
|
|
1960
2264
|
updateShaderInputs() {
|
|
1961
2265
|
this._uniformStore.setUniforms(this.shaderInputs.getUniformValues());
|
|
1962
|
-
this.setBindings(this.shaderInputs.getBindingValues());
|
|
2266
|
+
this.setBindings(this._getNonMaterialBindings(this.shaderInputs.getBindingValues()));
|
|
1963
2267
|
this.setNeedsRedraw("shaderInputs");
|
|
1964
2268
|
}
|
|
1965
2269
|
/**
|
|
@@ -1991,7 +2295,7 @@ var _Model = class {
|
|
|
1991
2295
|
setAttributes(buffers, options) {
|
|
1992
2296
|
const disableWarnings = (options == null ? void 0 : options.disableWarnings) ?? this.props.disableWarnings;
|
|
1993
2297
|
if (buffers["indices"]) {
|
|
1994
|
-
|
|
2298
|
+
import_core8.log.warn(`Model:${this.id} setAttributes() - indexBuffer should be set using setIndexBuffer()`)();
|
|
1995
2299
|
}
|
|
1996
2300
|
this.bufferLayout = sortedBufferLayoutByShaderSourceLocations(this.pipeline.shaderLayout, this.bufferLayout);
|
|
1997
2301
|
const bufferLayoutHelper = new BufferLayoutHelper(this.bufferLayout);
|
|
@@ -1999,7 +2303,7 @@ var _Model = class {
|
|
|
1999
2303
|
const bufferLayout = bufferLayoutHelper.getBufferLayout(bufferName);
|
|
2000
2304
|
if (!bufferLayout) {
|
|
2001
2305
|
if (!disableWarnings) {
|
|
2002
|
-
|
|
2306
|
+
import_core8.log.warn(`Model(${this.id}): Missing layout for buffer "${bufferName}".`)();
|
|
2003
2307
|
}
|
|
2004
2308
|
continue;
|
|
2005
2309
|
}
|
|
@@ -2014,7 +2318,7 @@ var _Model = class {
|
|
|
2014
2318
|
}
|
|
2015
2319
|
}
|
|
2016
2320
|
if (!set && !disableWarnings) {
|
|
2017
|
-
|
|
2321
|
+
import_core8.log.warn(`Model(${this.id}): Ignoring buffer "${buffer.id}" for unknown attribute "${bufferName}"`)();
|
|
2018
2322
|
}
|
|
2019
2323
|
}
|
|
2020
2324
|
this.setNeedsRedraw("attributes");
|
|
@@ -2033,7 +2337,7 @@ var _Model = class {
|
|
|
2033
2337
|
if (attributeInfo) {
|
|
2034
2338
|
this.vertexArray.setConstantWebGL(attributeInfo.location, value);
|
|
2035
2339
|
} else if (!((options == null ? void 0 : options.disableWarnings) ?? this.props.disableWarnings)) {
|
|
2036
|
-
|
|
2340
|
+
import_core8.log.warn(`Model "${this.id}: Ignoring constant supplied for unknown attribute "${attributeName}"`)();
|
|
2037
2341
|
}
|
|
2038
2342
|
}
|
|
2039
2343
|
this.setNeedsRedraw("constants");
|
|
@@ -2041,8 +2345,14 @@ var _Model = class {
|
|
|
2041
2345
|
// INTERNAL METHODS
|
|
2042
2346
|
/** Check that bindings are loaded. Returns id of first binding that is still loading. */
|
|
2043
2347
|
_areBindingsLoading() {
|
|
2348
|
+
var _a;
|
|
2044
2349
|
for (const binding of Object.values(this.bindings)) {
|
|
2045
|
-
if (binding instanceof
|
|
2350
|
+
if (binding instanceof DynamicTexture && !binding.isReady) {
|
|
2351
|
+
return binding.id;
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
for (const binding of Object.values(((_a = this.material) == null ? void 0 : _a.bindings) || {})) {
|
|
2355
|
+
if (binding instanceof DynamicTexture && !binding.isReady) {
|
|
2046
2356
|
return binding.id;
|
|
2047
2357
|
}
|
|
2048
2358
|
}
|
|
@@ -2052,7 +2362,7 @@ var _Model = class {
|
|
|
2052
2362
|
_getBindings() {
|
|
2053
2363
|
const validBindings = {};
|
|
2054
2364
|
for (const [name, binding] of Object.entries(this.bindings)) {
|
|
2055
|
-
if (binding instanceof
|
|
2365
|
+
if (binding instanceof DynamicTexture) {
|
|
2056
2366
|
if (binding.isReady) {
|
|
2057
2367
|
validBindings[name] = binding.texture;
|
|
2058
2368
|
}
|
|
@@ -2062,24 +2372,46 @@ var _Model = class {
|
|
|
2062
2372
|
}
|
|
2063
2373
|
return validBindings;
|
|
2064
2374
|
}
|
|
2375
|
+
_getBindGroups() {
|
|
2376
|
+
var _a;
|
|
2377
|
+
const shaderLayout = ((_a = this.pipeline) == null ? void 0 : _a.shaderLayout) || this.props.shaderLayout || { bindings: [] };
|
|
2378
|
+
const bindGroups = shaderLayout.bindings.length ? (0, import_core8.normalizeBindingsByGroup)(shaderLayout, this._getBindings()) : { 0: this._getBindings() };
|
|
2379
|
+
if (!this.material) {
|
|
2380
|
+
return bindGroups;
|
|
2381
|
+
}
|
|
2382
|
+
for (const [groupKey, groupBindings] of Object.entries(this.material.getBindingsByGroup())) {
|
|
2383
|
+
const group = Number(groupKey);
|
|
2384
|
+
bindGroups[group] = {
|
|
2385
|
+
...bindGroups[group] || {},
|
|
2386
|
+
...groupBindings
|
|
2387
|
+
};
|
|
2388
|
+
}
|
|
2389
|
+
return bindGroups;
|
|
2390
|
+
}
|
|
2391
|
+
_getBindGroupCacheKeys() {
|
|
2392
|
+
var _a;
|
|
2393
|
+
const bindGroupCacheKey = (_a = this.material) == null ? void 0 : _a.getBindGroupCacheKey(3);
|
|
2394
|
+
return bindGroupCacheKey ? { 3: bindGroupCacheKey } : {};
|
|
2395
|
+
}
|
|
2065
2396
|
/** Get the timestamp of the latest updated bound GPU memory resource (buffer/texture). */
|
|
2066
2397
|
_getBindingsUpdateTimestamp() {
|
|
2398
|
+
var _a;
|
|
2067
2399
|
let timestamp = 0;
|
|
2068
2400
|
for (const binding of Object.values(this.bindings)) {
|
|
2069
|
-
if (binding instanceof
|
|
2401
|
+
if (binding instanceof import_core8.TextureView) {
|
|
2070
2402
|
timestamp = Math.max(timestamp, binding.texture.updateTimestamp);
|
|
2071
|
-
} else if (binding instanceof
|
|
2403
|
+
} else if (binding instanceof import_core8.Buffer || binding instanceof import_core8.Texture) {
|
|
2072
2404
|
timestamp = Math.max(timestamp, binding.updateTimestamp);
|
|
2073
|
-
} else if (binding instanceof
|
|
2405
|
+
} else if (binding instanceof DynamicTexture) {
|
|
2074
2406
|
timestamp = binding.texture ? Math.max(timestamp, binding.texture.updateTimestamp) : (
|
|
2075
2407
|
// The texture will become available in the future
|
|
2076
2408
|
Infinity
|
|
2077
2409
|
);
|
|
2078
|
-
} else if (!(binding instanceof
|
|
2410
|
+
} else if (!(binding instanceof import_core8.Sampler)) {
|
|
2079
2411
|
timestamp = Math.max(timestamp, binding.buffer.updateTimestamp);
|
|
2080
2412
|
}
|
|
2081
2413
|
}
|
|
2082
|
-
return timestamp;
|
|
2414
|
+
return Math.max(timestamp, ((_a = this.material) == null ? void 0 : _a.getBindingsUpdateTimestamp()) || 0);
|
|
2083
2415
|
}
|
|
2084
2416
|
/**
|
|
2085
2417
|
* Updates the optional geometry attributes
|
|
@@ -2110,7 +2442,7 @@ var _Model = class {
|
|
|
2110
2442
|
let prevShaderVs = null;
|
|
2111
2443
|
let prevShaderFs = null;
|
|
2112
2444
|
if (this.pipeline) {
|
|
2113
|
-
|
|
2445
|
+
import_core8.log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
|
|
2114
2446
|
prevShaderVs = this.pipeline.vs;
|
|
2115
2447
|
prevShaderFs = this.pipeline.fs;
|
|
2116
2448
|
}
|
|
@@ -2134,20 +2466,20 @@ var _Model = class {
|
|
|
2134
2466
|
}
|
|
2135
2467
|
this.pipeline = this.pipelineFactory.createRenderPipeline({
|
|
2136
2468
|
...this.props,
|
|
2469
|
+
bindings: void 0,
|
|
2137
2470
|
bufferLayout: this.bufferLayout,
|
|
2138
2471
|
topology: this.topology,
|
|
2139
2472
|
parameters: this.parameters,
|
|
2140
|
-
|
|
2141
|
-
// Should we expose a BindGroup abstraction?
|
|
2142
|
-
bindings: this._getBindings(),
|
|
2473
|
+
bindGroups: this._getBindGroups(),
|
|
2143
2474
|
vs: vs3,
|
|
2144
2475
|
fs: fs3
|
|
2145
2476
|
});
|
|
2146
|
-
this._attributeInfos = (0,
|
|
2477
|
+
this._attributeInfos = (0, import_core8.getAttributeInfosFromLayouts)(this.pipeline.shaderLayout, this.bufferLayout);
|
|
2147
2478
|
if (prevShaderVs)
|
|
2148
2479
|
this.shaderFactory.release(prevShaderVs);
|
|
2149
|
-
if (prevShaderFs)
|
|
2480
|
+
if (prevShaderFs && prevShaderFs !== prevShaderVs) {
|
|
2150
2481
|
this.shaderFactory.release(prevShaderFs);
|
|
2482
|
+
}
|
|
2151
2483
|
}
|
|
2152
2484
|
return this.pipeline;
|
|
2153
2485
|
}
|
|
@@ -2155,24 +2487,24 @@ var _Model = class {
|
|
|
2155
2487
|
_lastLogTime = 0;
|
|
2156
2488
|
_logOpen = false;
|
|
2157
2489
|
_logDrawCallStart() {
|
|
2158
|
-
const logDrawTimeout =
|
|
2159
|
-
if (
|
|
2490
|
+
const logDrawTimeout = import_core8.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT;
|
|
2491
|
+
if (import_core8.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
|
|
2160
2492
|
return;
|
|
2161
2493
|
}
|
|
2162
2494
|
this._lastLogTime = Date.now();
|
|
2163
2495
|
this._logOpen = true;
|
|
2164
|
-
|
|
2496
|
+
import_core8.log.group(LOG_DRAW_PRIORITY, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core8.log.level <= 2 })();
|
|
2165
2497
|
}
|
|
2166
2498
|
_logDrawCallEnd() {
|
|
2167
2499
|
if (this._logOpen) {
|
|
2168
2500
|
const shaderLayoutTable = getDebugTableForShaderLayout(this.pipeline.shaderLayout, this.id);
|
|
2169
|
-
|
|
2501
|
+
import_core8.log.table(LOG_DRAW_PRIORITY, shaderLayoutTable)();
|
|
2170
2502
|
const uniformTable = this.shaderInputs.getDebugTable();
|
|
2171
|
-
|
|
2503
|
+
import_core8.log.table(LOG_DRAW_PRIORITY, uniformTable)();
|
|
2172
2504
|
const attributeTable = this._getAttributeDebugTable();
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2505
|
+
import_core8.log.table(LOG_DRAW_PRIORITY, this._attributeInfos)();
|
|
2506
|
+
import_core8.log.table(LOG_DRAW_PRIORITY, attributeTable)();
|
|
2507
|
+
import_core8.log.groupEnd(LOG_DRAW_PRIORITY)();
|
|
2176
2508
|
this._logOpen = false;
|
|
2177
2509
|
}
|
|
2178
2510
|
}
|
|
@@ -2211,14 +2543,26 @@ var _Model = class {
|
|
|
2211
2543
|
}
|
|
2212
2544
|
// TODO - fix typing of luma data types
|
|
2213
2545
|
_getBufferOrConstantValues(attribute, dataType) {
|
|
2214
|
-
const TypedArrayConstructor =
|
|
2215
|
-
const typedArray = attribute instanceof
|
|
2546
|
+
const TypedArrayConstructor = import_core8.dataTypeDecoder.getTypedArrayConstructor(dataType);
|
|
2547
|
+
const typedArray = attribute instanceof import_core8.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
|
|
2216
2548
|
return typedArray.toString();
|
|
2217
2549
|
}
|
|
2550
|
+
_getNonMaterialBindings(bindings) {
|
|
2551
|
+
if (!this.material) {
|
|
2552
|
+
return bindings;
|
|
2553
|
+
}
|
|
2554
|
+
const filteredBindings = {};
|
|
2555
|
+
for (const [name, binding] of Object.entries(bindings)) {
|
|
2556
|
+
if (!this.material.ownsBinding(name)) {
|
|
2557
|
+
filteredBindings[name] = binding;
|
|
2558
|
+
}
|
|
2559
|
+
}
|
|
2560
|
+
return filteredBindings;
|
|
2561
|
+
}
|
|
2218
2562
|
};
|
|
2219
2563
|
var Model = _Model;
|
|
2220
2564
|
__publicField(Model, "defaultProps", {
|
|
2221
|
-
...
|
|
2565
|
+
...import_core8.RenderPipeline.defaultProps,
|
|
2222
2566
|
source: void 0,
|
|
2223
2567
|
vs: null,
|
|
2224
2568
|
fs: null,
|
|
@@ -2231,11 +2575,14 @@ __publicField(Model, "defaultProps", {
|
|
|
2231
2575
|
indexBuffer: null,
|
|
2232
2576
|
attributes: {},
|
|
2233
2577
|
constantAttributes: {},
|
|
2578
|
+
bindings: {},
|
|
2579
|
+
uniforms: {},
|
|
2234
2580
|
varyings: [],
|
|
2235
2581
|
isInstanced: void 0,
|
|
2236
2582
|
instanceCount: 0,
|
|
2237
2583
|
vertexCount: 0,
|
|
2238
2584
|
shaderInputs: void 0,
|
|
2585
|
+
material: void 0,
|
|
2239
2586
|
pipelineFactory: void 0,
|
|
2240
2587
|
shaderFactory: void 0,
|
|
2241
2588
|
transformFeedback: void 0,
|
|
@@ -2243,9 +2590,6 @@ __publicField(Model, "defaultProps", {
|
|
|
2243
2590
|
debugShaders: void 0,
|
|
2244
2591
|
disableWarnings: void 0
|
|
2245
2592
|
});
|
|
2246
|
-
function shaderModuleHasUniforms(module2) {
|
|
2247
|
-
return Boolean(module2.uniformTypes && !isObjectEmpty(module2.uniformTypes));
|
|
2248
|
-
}
|
|
2249
2593
|
function getPlatformInfo(device) {
|
|
2250
2594
|
return {
|
|
2251
2595
|
type: device.type,
|
|
@@ -2256,13 +2600,234 @@ function getPlatformInfo(device) {
|
|
|
2256
2600
|
features: device.features
|
|
2257
2601
|
};
|
|
2258
2602
|
}
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2603
|
+
|
|
2604
|
+
// dist/material/material.js
|
|
2605
|
+
var import_core9 = require("@luma.gl/core");
|
|
2606
|
+
|
|
2607
|
+
// dist/material/material-factory.js
|
|
2608
|
+
var MATERIAL_BIND_GROUP = 3;
|
|
2609
|
+
var MaterialFactory = class {
|
|
2610
|
+
/** Device that creates materials for this schema. */
|
|
2611
|
+
device;
|
|
2612
|
+
/** Shader modules that define the material schema. */
|
|
2613
|
+
modules;
|
|
2614
|
+
_materialBindingNames;
|
|
2615
|
+
_materialModuleNames;
|
|
2616
|
+
constructor(device, props = {}) {
|
|
2617
|
+
this.device = device;
|
|
2618
|
+
this.modules = props.modules || [];
|
|
2619
|
+
const shaderInputs = new ShaderInputs(Object.fromEntries(this.modules.map((module2) => [module2.name, module2])));
|
|
2620
|
+
this._materialBindingNames = getMaterialBindingNames(shaderInputs);
|
|
2621
|
+
this._materialModuleNames = getMaterialModuleNames(shaderInputs);
|
|
2622
|
+
}
|
|
2623
|
+
/** Creates one typed material instance for this factory's schema. */
|
|
2624
|
+
createMaterial(props = {}) {
|
|
2625
|
+
return new Material(this.device, {
|
|
2626
|
+
...props,
|
|
2627
|
+
factory: this
|
|
2628
|
+
});
|
|
2262
2629
|
}
|
|
2263
|
-
|
|
2630
|
+
/** Returns the logical material-owned resource binding names. */
|
|
2631
|
+
getBindingNames() {
|
|
2632
|
+
return Array.from(this._materialBindingNames);
|
|
2633
|
+
}
|
|
2634
|
+
/** Returns `true` when the supplied binding belongs to this material schema. */
|
|
2635
|
+
ownsBinding(bindingName) {
|
|
2636
|
+
if (this._materialBindingNames.has(bindingName)) {
|
|
2637
|
+
return true;
|
|
2638
|
+
}
|
|
2639
|
+
const aliasedModuleName = getModuleNameFromUniformBinding(bindingName);
|
|
2640
|
+
return aliasedModuleName ? this._materialModuleNames.has(aliasedModuleName) : false;
|
|
2641
|
+
}
|
|
2642
|
+
/** Returns `true` when the supplied shader module is owned by this material schema. */
|
|
2643
|
+
ownsModule(moduleName) {
|
|
2644
|
+
return this._materialModuleNames.has(moduleName);
|
|
2645
|
+
}
|
|
2646
|
+
/** Packages resolved material bindings into bind group `3`. */
|
|
2647
|
+
getBindingsByGroup(bindings) {
|
|
2648
|
+
return Object.keys(bindings).length > 0 ? { [MATERIAL_BIND_GROUP]: bindings } : {};
|
|
2649
|
+
}
|
|
2650
|
+
};
|
|
2651
|
+
function getModuleNameFromUniformBinding(bindingName) {
|
|
2652
|
+
return bindingName.endsWith("Uniforms") ? bindingName.slice(0, -"Uniforms".length) : null;
|
|
2653
|
+
}
|
|
2654
|
+
function getMaterialBindingNames(shaderInputs) {
|
|
2655
|
+
const bindingNames = /* @__PURE__ */ new Set();
|
|
2656
|
+
for (const module2 of Object.values(shaderInputs.modules)) {
|
|
2657
|
+
for (const binding of module2.bindingLayout || []) {
|
|
2658
|
+
if (binding.group === MATERIAL_BIND_GROUP) {
|
|
2659
|
+
bindingNames.add(binding.name);
|
|
2660
|
+
}
|
|
2661
|
+
}
|
|
2662
|
+
}
|
|
2663
|
+
return bindingNames;
|
|
2664
|
+
}
|
|
2665
|
+
function getMaterialModuleNames(shaderInputs) {
|
|
2666
|
+
var _a;
|
|
2667
|
+
const moduleNames = /* @__PURE__ */ new Set();
|
|
2668
|
+
for (const module2 of Object.values(shaderInputs.modules)) {
|
|
2669
|
+
if (module2.name && ((_a = module2.bindingLayout) == null ? void 0 : _a.some((binding) => binding.group === MATERIAL_BIND_GROUP && binding.name === module2.name))) {
|
|
2670
|
+
moduleNames.add(module2.name);
|
|
2671
|
+
}
|
|
2672
|
+
}
|
|
2673
|
+
return moduleNames;
|
|
2264
2674
|
}
|
|
2265
2675
|
|
|
2676
|
+
// dist/material/material.js
|
|
2677
|
+
var Material = class {
|
|
2678
|
+
/** Application-provided identifier. */
|
|
2679
|
+
id;
|
|
2680
|
+
/** Device that owns the material resources. */
|
|
2681
|
+
device;
|
|
2682
|
+
/** Factory that defines the material schema. */
|
|
2683
|
+
factory;
|
|
2684
|
+
/** Shader inputs for the material-owned modules. */
|
|
2685
|
+
shaderInputs;
|
|
2686
|
+
/** Internal binding store including uniform buffers and resource bindings. */
|
|
2687
|
+
bindings = {};
|
|
2688
|
+
_uniformStore;
|
|
2689
|
+
_bindGroupCacheToken = {};
|
|
2690
|
+
constructor(device, props = {}) {
|
|
2691
|
+
var _a, _b;
|
|
2692
|
+
this.id = props.id || uid("material");
|
|
2693
|
+
this.device = device;
|
|
2694
|
+
this.factory = props.factory || new MaterialFactory(device, {
|
|
2695
|
+
modules: props.modules || ((_a = props.shaderInputs) == null ? void 0 : _a.getModules()) || []
|
|
2696
|
+
});
|
|
2697
|
+
const moduleMap = Object.fromEntries((((_b = props.shaderInputs) == null ? void 0 : _b.getModules()) || this.factory.modules).map((module2) => [
|
|
2698
|
+
module2.name,
|
|
2699
|
+
module2
|
|
2700
|
+
]));
|
|
2701
|
+
this.shaderInputs = props.shaderInputs || new ShaderInputs(moduleMap);
|
|
2702
|
+
this._uniformStore = new import_core9.UniformStore(this.device, this.shaderInputs.modules);
|
|
2703
|
+
for (const [moduleName, module2] of Object.entries(this.shaderInputs.modules)) {
|
|
2704
|
+
if (this.ownsModule(moduleName) && shaderModuleHasUniforms(module2)) {
|
|
2705
|
+
const uniformBuffer = this._uniformStore.getManagedUniformBuffer(moduleName);
|
|
2706
|
+
this.bindings[`${moduleName}Uniforms`] = uniformBuffer;
|
|
2707
|
+
}
|
|
2708
|
+
}
|
|
2709
|
+
this.updateShaderInputs();
|
|
2710
|
+
if (props.bindings) {
|
|
2711
|
+
this._replaceOwnedBindings(props.bindings);
|
|
2712
|
+
}
|
|
2713
|
+
}
|
|
2714
|
+
/** Destroys managed uniform-buffer resources owned by this material. */
|
|
2715
|
+
destroy() {
|
|
2716
|
+
this._uniformStore.destroy();
|
|
2717
|
+
}
|
|
2718
|
+
/** Creates a new material variant with optional structural and uniform overrides. */
|
|
2719
|
+
clone(props = {}) {
|
|
2720
|
+
const material = this.factory.createMaterial({
|
|
2721
|
+
id: props.id,
|
|
2722
|
+
shaderInputs: props.shaderInputs,
|
|
2723
|
+
bindings: {
|
|
2724
|
+
...this.getResourceBindings(),
|
|
2725
|
+
...props.bindings
|
|
2726
|
+
}
|
|
2727
|
+
});
|
|
2728
|
+
if (!props.shaderInputs) {
|
|
2729
|
+
material.setProps(this.shaderInputs.getUniformValues());
|
|
2730
|
+
}
|
|
2731
|
+
if (props.moduleProps) {
|
|
2732
|
+
material.setProps(props.moduleProps);
|
|
2733
|
+
}
|
|
2734
|
+
return material;
|
|
2735
|
+
}
|
|
2736
|
+
/** Returns `true` if this material owns the supplied binding name. */
|
|
2737
|
+
ownsBinding(bindingName) {
|
|
2738
|
+
return this.factory.ownsBinding(bindingName);
|
|
2739
|
+
}
|
|
2740
|
+
/** Returns `true` if this material owns the supplied shader module. */
|
|
2741
|
+
ownsModule(moduleName) {
|
|
2742
|
+
return this.factory.ownsModule(moduleName);
|
|
2743
|
+
}
|
|
2744
|
+
/** Updates material uniform/module props in place without changing material identity. */
|
|
2745
|
+
setProps(props) {
|
|
2746
|
+
this.shaderInputs.setProps(props);
|
|
2747
|
+
this.updateShaderInputs();
|
|
2748
|
+
}
|
|
2749
|
+
/** Updates managed uniform buffers and shader-input-owned bindings. */
|
|
2750
|
+
updateShaderInputs() {
|
|
2751
|
+
this._uniformStore.setUniforms(this.shaderInputs.getUniformValues());
|
|
2752
|
+
const didChange = this._setOwnedBindings(this.shaderInputs.getBindingValues());
|
|
2753
|
+
if (didChange) {
|
|
2754
|
+
this._bindGroupCacheToken = {};
|
|
2755
|
+
}
|
|
2756
|
+
}
|
|
2757
|
+
/** Returns the material-owned resource bindings without internal uniform buffers. */
|
|
2758
|
+
getResourceBindings() {
|
|
2759
|
+
const resourceBindings = {};
|
|
2760
|
+
for (const [name, binding] of Object.entries(this.bindings)) {
|
|
2761
|
+
if (!getModuleNameFromUniformBinding(name)) {
|
|
2762
|
+
resourceBindings[name] = binding;
|
|
2763
|
+
}
|
|
2764
|
+
}
|
|
2765
|
+
return resourceBindings;
|
|
2766
|
+
}
|
|
2767
|
+
/** Returns the resolved bindings, including internal uniform buffers and ready textures. */
|
|
2768
|
+
getBindings() {
|
|
2769
|
+
const validBindings = {};
|
|
2770
|
+
const validBindingsMap = validBindings;
|
|
2771
|
+
for (const [name, binding] of Object.entries(this.bindings)) {
|
|
2772
|
+
if (binding instanceof DynamicTexture) {
|
|
2773
|
+
if (binding.isReady) {
|
|
2774
|
+
validBindingsMap[name] = binding.texture;
|
|
2775
|
+
}
|
|
2776
|
+
} else {
|
|
2777
|
+
validBindingsMap[name] = binding;
|
|
2778
|
+
}
|
|
2779
|
+
}
|
|
2780
|
+
return validBindings;
|
|
2781
|
+
}
|
|
2782
|
+
/** Packages resolved material bindings into logical bind group `3`. */
|
|
2783
|
+
getBindingsByGroup() {
|
|
2784
|
+
return this.factory.getBindingsByGroup(this.getBindings());
|
|
2785
|
+
}
|
|
2786
|
+
/** Returns the stable bind-group cache token for the requested bind group. */
|
|
2787
|
+
getBindGroupCacheKey(group) {
|
|
2788
|
+
return group === MATERIAL_BIND_GROUP ? this._bindGroupCacheToken : null;
|
|
2789
|
+
}
|
|
2790
|
+
/** Returns the latest update timestamp across material-owned resources. */
|
|
2791
|
+
getBindingsUpdateTimestamp() {
|
|
2792
|
+
let timestamp = 0;
|
|
2793
|
+
for (const binding of Object.values(this.bindings)) {
|
|
2794
|
+
if (binding instanceof import_core9.TextureView) {
|
|
2795
|
+
timestamp = Math.max(timestamp, binding.texture.updateTimestamp);
|
|
2796
|
+
} else if (binding instanceof import_core9.Buffer || binding instanceof import_core9.Texture) {
|
|
2797
|
+
timestamp = Math.max(timestamp, binding.updateTimestamp);
|
|
2798
|
+
} else if (binding instanceof DynamicTexture) {
|
|
2799
|
+
timestamp = binding.texture ? Math.max(timestamp, binding.texture.updateTimestamp) : Infinity;
|
|
2800
|
+
} else if (!(binding instanceof import_core9.Sampler)) {
|
|
2801
|
+
timestamp = Math.max(timestamp, binding.buffer.updateTimestamp);
|
|
2802
|
+
}
|
|
2803
|
+
}
|
|
2804
|
+
return timestamp;
|
|
2805
|
+
}
|
|
2806
|
+
/** Replaces owned resource bindings and invalidates the material cache identity when needed. */
|
|
2807
|
+
_replaceOwnedBindings(bindings) {
|
|
2808
|
+
const didChange = this._setOwnedBindings(bindings);
|
|
2809
|
+
if (didChange) {
|
|
2810
|
+
this._bindGroupCacheToken = {};
|
|
2811
|
+
}
|
|
2812
|
+
}
|
|
2813
|
+
_setOwnedBindings(bindings) {
|
|
2814
|
+
let didChange = false;
|
|
2815
|
+
for (const [name, binding] of Object.entries(bindings)) {
|
|
2816
|
+
if (binding === void 0) {
|
|
2817
|
+
continue;
|
|
2818
|
+
}
|
|
2819
|
+
if (!this.ownsBinding(name)) {
|
|
2820
|
+
continue;
|
|
2821
|
+
}
|
|
2822
|
+
if (this.bindings[name] !== binding) {
|
|
2823
|
+
this.bindings[name] = binding;
|
|
2824
|
+
didChange = true;
|
|
2825
|
+
}
|
|
2826
|
+
}
|
|
2827
|
+
return didChange;
|
|
2828
|
+
}
|
|
2829
|
+
};
|
|
2830
|
+
|
|
2266
2831
|
// dist/compute/buffer-transform.js
|
|
2267
2832
|
var import_core10 = require("@luma.gl/core");
|
|
2268
2833
|
var import_shadertools3 = require("@luma.gl/shadertools");
|
|
@@ -2535,9 +3100,9 @@ var Geometry = class {
|
|
|
2535
3100
|
var CLIPSPACE_VERTEX_SHADER_WGSL = (
|
|
2536
3101
|
/* wgsl */
|
|
2537
3102
|
`struct VertexInputs {
|
|
2538
|
-
@location(0)
|
|
2539
|
-
@location(1)
|
|
2540
|
-
@location(2)
|
|
3103
|
+
@location(0) clipSpacePositions: vec2<f32>,
|
|
3104
|
+
@location(1) texCoords: vec2<f32>,
|
|
3105
|
+
@location(2) coordinates: vec2<f32>
|
|
2541
3106
|
}
|
|
2542
3107
|
|
|
2543
3108
|
struct FragmentInputs {
|
|
@@ -2550,10 +3115,10 @@ struct FragmentInputs {
|
|
|
2550
3115
|
@vertex
|
|
2551
3116
|
fn vertexMain(inputs: VertexInputs) -> FragmentInputs {
|
|
2552
3117
|
var outputs: FragmentInputs;
|
|
2553
|
-
outputs.Position = vec4(inputs.
|
|
2554
|
-
outputs.position = inputs.
|
|
2555
|
-
outputs.coordinate = inputs.
|
|
2556
|
-
outputs.uv = inputs.
|
|
3118
|
+
outputs.Position = vec4(inputs.clipSpacePositions, 0., 1.);
|
|
3119
|
+
outputs.position = inputs.clipSpacePositions;
|
|
3120
|
+
outputs.coordinate = inputs.coordinates;
|
|
3121
|
+
outputs.uv = inputs.texCoords;
|
|
2557
3122
|
return outputs;
|
|
2558
3123
|
}
|
|
2559
3124
|
`
|
|
@@ -2604,22 +3169,31 @@ ${props.source}` };
|
|
|
2604
3169
|
};
|
|
2605
3170
|
|
|
2606
3171
|
// dist/models/billboard-texture-model.js
|
|
3172
|
+
var backgroundModule = {
|
|
3173
|
+
name: "background",
|
|
3174
|
+
uniformTypes: {
|
|
3175
|
+
scale: "vec2<f32>"
|
|
3176
|
+
}
|
|
3177
|
+
};
|
|
2607
3178
|
var BACKGROUND_FS_WGSL = (
|
|
2608
3179
|
/* wgsl */
|
|
2609
3180
|
`@group(0) @binding(0) var backgroundTexture: texture_2d<f32>;
|
|
2610
3181
|
@group(0) @binding(1) var backgroundTextureSampler: sampler;
|
|
3182
|
+
struct backgroundUniforms {
|
|
3183
|
+
scale: vec2<f32>,
|
|
3184
|
+
};
|
|
3185
|
+
@group(0) @binding(2) var<uniform> background: backgroundUniforms;
|
|
2611
3186
|
|
|
2612
|
-
fn billboardTexture_getTextureUV(
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
}
|
|
3187
|
+
fn billboardTexture_getTextureUV(uv: vec2<f32>) -> vec2<f32> {
|
|
3188
|
+
let scale: vec2<f32> = background.scale;
|
|
3189
|
+
var position: vec2<f32> = (uv - vec2<f32>(0.5, 0.5)) / scale + vec2<f32>(0.5, 0.5);
|
|
3190
|
+
return position;
|
|
3191
|
+
}
|
|
2618
3192
|
|
|
2619
3193
|
@fragment
|
|
2620
3194
|
fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4<f32> {
|
|
2621
|
-
|
|
2622
|
-
|
|
3195
|
+
let position: vec2<f32> = billboardTexture_getTextureUV(inputs.uv);
|
|
3196
|
+
return textureSample(backgroundTexture, backgroundTextureSampler, position);
|
|
2623
3197
|
}
|
|
2624
3198
|
`
|
|
2625
3199
|
);
|
|
@@ -2629,97 +3203,774 @@ var BACKGROUND_FS = (
|
|
|
2629
3203
|
precision highp float;
|
|
2630
3204
|
|
|
2631
3205
|
uniform sampler2D backgroundTexture;
|
|
3206
|
+
|
|
3207
|
+
layout(std140) uniform backgroundUniforms {
|
|
3208
|
+
vec2 scale;
|
|
3209
|
+
} background;
|
|
3210
|
+
|
|
3211
|
+
in vec2 coordinate;
|
|
2632
3212
|
out vec4 fragColor;
|
|
2633
3213
|
|
|
2634
|
-
vec2 billboardTexture_getTextureUV() {
|
|
2635
|
-
|
|
2636
|
-
vec2 texSize = vec2(float(iTexSize.x), float(iTexSize.y));
|
|
2637
|
-
vec2 position = gl_FragCoord.xy / texSize;
|
|
3214
|
+
vec2 billboardTexture_getTextureUV(vec2 coord) {
|
|
3215
|
+
vec2 position = (coord - 0.5) / background.scale + 0.5;
|
|
2638
3216
|
return position;
|
|
2639
3217
|
}
|
|
2640
3218
|
|
|
2641
3219
|
void main(void) {
|
|
2642
|
-
vec2 position = billboardTexture_getTextureUV();
|
|
3220
|
+
vec2 position = billboardTexture_getTextureUV(coordinate);
|
|
2643
3221
|
fragColor = texture(backgroundTexture, position);
|
|
2644
3222
|
}
|
|
2645
3223
|
`
|
|
2646
3224
|
);
|
|
2647
3225
|
var BackgroundTextureModel = class extends ClipSpace {
|
|
3226
|
+
backgroundTexture = null;
|
|
2648
3227
|
constructor(device, props) {
|
|
2649
3228
|
super(device, {
|
|
3229
|
+
...props,
|
|
2650
3230
|
id: props.id || "background-texture-model",
|
|
2651
3231
|
source: BACKGROUND_FS_WGSL,
|
|
2652
3232
|
fs: BACKGROUND_FS,
|
|
3233
|
+
modules: [...props.modules || [], backgroundModule],
|
|
2653
3234
|
parameters: {
|
|
2654
3235
|
depthWriteEnabled: false,
|
|
3236
|
+
...props.parameters || {},
|
|
2655
3237
|
...props.blend ? {
|
|
2656
3238
|
blend: true,
|
|
2657
3239
|
blendColorOperation: "add",
|
|
2658
3240
|
blendAlphaOperation: "add",
|
|
2659
|
-
blendColorSrcFactor: "one",
|
|
2660
|
-
blendColorDstFactor: "one
|
|
2661
|
-
blendAlphaSrcFactor: "one",
|
|
2662
|
-
blendAlphaDstFactor: "one
|
|
3241
|
+
blendColorSrcFactor: "one-minus-dst-alpha",
|
|
3242
|
+
blendColorDstFactor: "one",
|
|
3243
|
+
blendAlphaSrcFactor: "one-minus-dst-alpha",
|
|
3244
|
+
blendAlphaDstFactor: "one"
|
|
2663
3245
|
} : {}
|
|
2664
3246
|
}
|
|
2665
3247
|
});
|
|
2666
3248
|
if (!props.backgroundTexture) {
|
|
2667
3249
|
throw new Error("BackgroundTextureModel requires a backgroundTexture prop");
|
|
2668
3250
|
}
|
|
2669
|
-
this.
|
|
3251
|
+
this.setProps(props);
|
|
2670
3252
|
}
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
3253
|
+
/** Update the background texture */
|
|
3254
|
+
setProps(props) {
|
|
3255
|
+
const { backgroundTexture } = props;
|
|
3256
|
+
if (backgroundTexture) {
|
|
3257
|
+
this.setBindings({ backgroundTexture });
|
|
3258
|
+
if (backgroundTexture.isReady) {
|
|
3259
|
+
const texture = backgroundTexture instanceof DynamicTexture ? backgroundTexture.texture : backgroundTexture;
|
|
3260
|
+
this.backgroundTexture = texture;
|
|
3261
|
+
this.updateScale(texture);
|
|
3262
|
+
} else {
|
|
3263
|
+
backgroundTexture.ready.then((texture) => {
|
|
3264
|
+
this.backgroundTexture = texture;
|
|
3265
|
+
this.updateScale(texture);
|
|
3266
|
+
});
|
|
3267
|
+
}
|
|
3268
|
+
}
|
|
2675
3269
|
}
|
|
2676
3270
|
predraw() {
|
|
2677
|
-
this.shaderInputs.setProps({});
|
|
2678
3271
|
super.predraw();
|
|
2679
3272
|
}
|
|
3273
|
+
updateScale(texture) {
|
|
3274
|
+
if (!texture) {
|
|
3275
|
+
this.shaderInputs.setProps({ background: { scale: [1, 1] } });
|
|
3276
|
+
return;
|
|
3277
|
+
}
|
|
3278
|
+
const [screenWidth, screenHeight] = this.device.getCanvasContext().getDrawingBufferSize();
|
|
3279
|
+
const textureWidth = texture.width;
|
|
3280
|
+
const textureHeight = texture.height;
|
|
3281
|
+
const screenAspect = screenWidth / screenHeight;
|
|
3282
|
+
const textureAspect = textureWidth / textureHeight;
|
|
3283
|
+
let scaleX = 1;
|
|
3284
|
+
let scaleY = 1;
|
|
3285
|
+
if (screenAspect > textureAspect) {
|
|
3286
|
+
scaleY = screenAspect / textureAspect;
|
|
3287
|
+
} else {
|
|
3288
|
+
scaleX = textureAspect / screenAspect;
|
|
3289
|
+
}
|
|
3290
|
+
this.shaderInputs.setProps({ background: { scale: [scaleX, scaleY] } });
|
|
3291
|
+
}
|
|
2680
3292
|
};
|
|
2681
3293
|
|
|
2682
|
-
// dist/
|
|
2683
|
-
var
|
|
2684
|
-
var ScenegraphNode = class {
|
|
2685
|
-
id;
|
|
2686
|
-
matrix = new import_core11.Matrix4();
|
|
2687
|
-
display = true;
|
|
2688
|
-
position = new import_core11.Vector3();
|
|
2689
|
-
rotation = new import_core11.Vector3();
|
|
2690
|
-
scale = new import_core11.Vector3(1, 1, 1);
|
|
2691
|
-
userData = {};
|
|
2692
|
-
props = {};
|
|
3294
|
+
// dist/geometries/sphere-geometry.js
|
|
3295
|
+
var SphereGeometry = class extends Geometry {
|
|
2693
3296
|
constructor(props = {}) {
|
|
2694
|
-
const { id } = props;
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
}
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
3297
|
+
const { id = uid("sphere-geometry") } = props;
|
|
3298
|
+
const { indices, attributes } = tesselateSphere(props);
|
|
3299
|
+
super({
|
|
3300
|
+
...props,
|
|
3301
|
+
id,
|
|
3302
|
+
topology: "triangle-list",
|
|
3303
|
+
indices,
|
|
3304
|
+
attributes: { ...attributes, ...props.attributes }
|
|
3305
|
+
});
|
|
3306
|
+
}
|
|
3307
|
+
};
|
|
3308
|
+
function tesselateSphere(props) {
|
|
3309
|
+
const { nlat = 10, nlong = 10 } = props;
|
|
3310
|
+
const startLat = 0;
|
|
3311
|
+
const endLat = Math.PI;
|
|
3312
|
+
const latRange = endLat - startLat;
|
|
3313
|
+
const startLong = 0;
|
|
3314
|
+
const endLong = 2 * Math.PI;
|
|
3315
|
+
const longRange = endLong - startLong;
|
|
3316
|
+
const numVertices = (nlat + 1) * (nlong + 1);
|
|
3317
|
+
const radius = (n1, n2, n3, u, v) => props.radius || 1;
|
|
3318
|
+
const positions = new Float32Array(numVertices * 3);
|
|
3319
|
+
const normals = new Float32Array(numVertices * 3);
|
|
3320
|
+
const texCoords = new Float32Array(numVertices * 2);
|
|
3321
|
+
const IndexType = numVertices > 65535 ? Uint32Array : Uint16Array;
|
|
3322
|
+
const indices = new IndexType(nlat * nlong * 6);
|
|
3323
|
+
for (let y = 0; y <= nlat; y++) {
|
|
3324
|
+
for (let x = 0; x <= nlong; x++) {
|
|
3325
|
+
const u = x / nlong;
|
|
3326
|
+
const v = y / nlat;
|
|
3327
|
+
const index = x + y * (nlong + 1);
|
|
3328
|
+
const i2 = index * 2;
|
|
3329
|
+
const i3 = index * 3;
|
|
3330
|
+
const theta = longRange * u;
|
|
3331
|
+
const phi = latRange * v;
|
|
3332
|
+
const sinTheta = Math.sin(theta);
|
|
3333
|
+
const cosTheta = Math.cos(theta);
|
|
3334
|
+
const sinPhi = Math.sin(phi);
|
|
3335
|
+
const cosPhi = Math.cos(phi);
|
|
3336
|
+
const ux = cosTheta * sinPhi;
|
|
3337
|
+
const uy = cosPhi;
|
|
3338
|
+
const uz = sinTheta * sinPhi;
|
|
3339
|
+
const r = radius(ux, uy, uz, u, v);
|
|
3340
|
+
positions[i3 + 0] = r * ux;
|
|
3341
|
+
positions[i3 + 1] = r * uy;
|
|
3342
|
+
positions[i3 + 2] = r * uz;
|
|
3343
|
+
normals[i3 + 0] = ux;
|
|
3344
|
+
normals[i3 + 1] = uy;
|
|
3345
|
+
normals[i3 + 2] = uz;
|
|
3346
|
+
texCoords[i2 + 0] = u;
|
|
3347
|
+
texCoords[i2 + 1] = 1 - v;
|
|
3348
|
+
}
|
|
3349
|
+
}
|
|
3350
|
+
const numVertsAround = nlong + 1;
|
|
3351
|
+
for (let x = 0; x < nlong; x++) {
|
|
3352
|
+
for (let y = 0; y < nlat; y++) {
|
|
3353
|
+
const index = (x * nlat + y) * 6;
|
|
3354
|
+
indices[index + 0] = y * numVertsAround + x;
|
|
3355
|
+
indices[index + 1] = y * numVertsAround + x + 1;
|
|
3356
|
+
indices[index + 2] = (y + 1) * numVertsAround + x;
|
|
3357
|
+
indices[index + 3] = (y + 1) * numVertsAround + x;
|
|
3358
|
+
indices[index + 4] = y * numVertsAround + x + 1;
|
|
3359
|
+
indices[index + 5] = (y + 1) * numVertsAround + x + 1;
|
|
3360
|
+
}
|
|
3361
|
+
}
|
|
3362
|
+
return {
|
|
3363
|
+
indices: { size: 1, value: indices },
|
|
3364
|
+
attributes: {
|
|
3365
|
+
POSITION: { size: 3, value: positions },
|
|
3366
|
+
NORMAL: { size: 3, value: normals },
|
|
3367
|
+
TEXCOORD_0: { size: 2, value: texCoords }
|
|
3368
|
+
}
|
|
3369
|
+
};
|
|
3370
|
+
}
|
|
3371
|
+
|
|
3372
|
+
// dist/models/light-model-utils.js
|
|
3373
|
+
var import_core11 = require("@math.gl/core");
|
|
3374
|
+
var DEFAULT_POINT_LIGHT_RADIUS_FACTOR = 0.02;
|
|
3375
|
+
var DEFAULT_SPOT_LIGHT_LENGTH_FACTOR = 0.12;
|
|
3376
|
+
var DEFAULT_DIRECTIONAL_LIGHT_LENGTH_FACTOR = 0.15;
|
|
3377
|
+
var DEFAULT_DIRECTIONAL_LIGHT_RADIUS_FACTOR = 0.2;
|
|
3378
|
+
var DEFAULT_DIRECTION_FALLBACK = [0, 1, 0];
|
|
3379
|
+
var DEFAULT_LIGHT_COLOR = [255, 255, 255];
|
|
3380
|
+
var DEFAULT_MARKER_SCALE = 1;
|
|
3381
|
+
var DIRECTIONAL_ANCHOR_DISTANCE_FACTOR = 0.35;
|
|
3382
|
+
var LIGHT_COLOR_FACTOR = 255;
|
|
3383
|
+
var MIN_SCENE_SCALE = 1;
|
|
3384
|
+
var SPOTLIGHT_OUTER_CONE_EPSILON = 0.01;
|
|
3385
|
+
var LIGHT_MARKER_PARAMETERS = {
|
|
3386
|
+
depthCompare: "less-equal",
|
|
3387
|
+
depthWriteEnabled: false,
|
|
3388
|
+
cullMode: "none"
|
|
3389
|
+
};
|
|
3390
|
+
var INSTANCE_BUFFER_LAYOUT = [
|
|
3391
|
+
{ name: "instancePosition", format: "float32x3", stepMode: "instance" },
|
|
3392
|
+
{ name: "instanceDirection", format: "float32x3", stepMode: "instance" },
|
|
3393
|
+
{ name: "instanceScale", format: "float32x3", stepMode: "instance" },
|
|
3394
|
+
{ name: "instanceColor", format: "float32x4", stepMode: "instance" }
|
|
3395
|
+
];
|
|
3396
|
+
var lightMarker = {
|
|
3397
|
+
name: "lightMarker",
|
|
3398
|
+
props: {},
|
|
3399
|
+
uniforms: {},
|
|
3400
|
+
uniformTypes: {
|
|
3401
|
+
viewProjectionMatrix: "mat4x4<f32>"
|
|
3402
|
+
}
|
|
3403
|
+
};
|
|
3404
|
+
var CENTERED_LOCAL_POSITION_WGSL = "inputs.positions * inputs.instanceScale";
|
|
3405
|
+
var APEX_LOCAL_POSITION_WGSL = "vec3<f32>(inputs.positions.x * inputs.instanceScale.x, (inputs.positions.y - 0.5) * inputs.instanceScale.y, inputs.positions.z * inputs.instanceScale.z)";
|
|
3406
|
+
var CENTERED_LOCAL_POSITION_GLSL = "positions * instanceScale";
|
|
3407
|
+
var APEX_LOCAL_POSITION_GLSL = "vec3(positions.x * instanceScale.x, (positions.y - 0.5) * instanceScale.y, positions.z * instanceScale.z)";
|
|
3408
|
+
var BaseLightModel = class extends Model {
|
|
3409
|
+
lightModelProps;
|
|
3410
|
+
_instanceData;
|
|
3411
|
+
_managedBuffers;
|
|
3412
|
+
buildInstanceData;
|
|
3413
|
+
sizePropNames;
|
|
3414
|
+
constructor(device, props, options) {
|
|
3415
|
+
const instanceData = options.buildInstanceData(props);
|
|
3416
|
+
const managedBuffers = createManagedInstanceBuffers(device, props.id || options.idPrefix, instanceData);
|
|
3417
|
+
const shaderInputs = new ShaderInputs({ lightMarker });
|
|
3418
|
+
shaderInputs.setProps({
|
|
3419
|
+
lightMarker: { viewProjectionMatrix: createViewProjectionMatrix(props) }
|
|
3420
|
+
});
|
|
3421
|
+
const { source: source3, vs: vs3, fs: fs3 } = getLightMarkerShaders(options.anchorMode);
|
|
3422
|
+
const modelProps = props;
|
|
3423
|
+
super(device, {
|
|
3424
|
+
...modelProps,
|
|
3425
|
+
id: props.id || options.idPrefix,
|
|
3426
|
+
source: source3,
|
|
3427
|
+
vs: vs3,
|
|
3428
|
+
fs: fs3,
|
|
3429
|
+
geometry: options.geometry,
|
|
3430
|
+
shaderInputs,
|
|
3431
|
+
bufferLayout: [...INSTANCE_BUFFER_LAYOUT],
|
|
3432
|
+
attributes: managedBuffers,
|
|
3433
|
+
instanceCount: instanceData.instanceCount,
|
|
3434
|
+
parameters: mergeLightMarkerParameters(props.parameters)
|
|
3435
|
+
});
|
|
3436
|
+
this.lightModelProps = props;
|
|
3437
|
+
this._instanceData = instanceData;
|
|
3438
|
+
this._managedBuffers = managedBuffers;
|
|
3439
|
+
this.buildInstanceData = options.buildInstanceData;
|
|
3440
|
+
this.sizePropNames = options.sizePropNames;
|
|
3441
|
+
}
|
|
3442
|
+
destroy() {
|
|
3443
|
+
super.destroy();
|
|
3444
|
+
destroyManagedInstanceBuffers(this._managedBuffers);
|
|
3445
|
+
this._managedBuffers = {};
|
|
3446
|
+
}
|
|
3447
|
+
draw(renderPass) {
|
|
3448
|
+
if (this.instanceCount === 0) {
|
|
3449
|
+
return true;
|
|
3450
|
+
}
|
|
3451
|
+
return super.draw(renderPass);
|
|
3452
|
+
}
|
|
3453
|
+
setProps(props) {
|
|
3454
|
+
this.lightModelProps = { ...this.lightModelProps, ...props };
|
|
3455
|
+
if (props.parameters) {
|
|
3456
|
+
this.setParameters(mergeLightMarkerParameters(this.lightModelProps.parameters));
|
|
3457
|
+
}
|
|
3458
|
+
if ("viewMatrix" in props || "projectionMatrix" in props) {
|
|
3459
|
+
this.shaderInputs.setProps({
|
|
3460
|
+
lightMarker: { viewProjectionMatrix: createViewProjectionMatrix(this.lightModelProps) }
|
|
3461
|
+
});
|
|
3462
|
+
this.setNeedsRedraw("lightMarker camera");
|
|
3463
|
+
}
|
|
3464
|
+
if (shouldRebuildInstanceData(props, this.sizePropNames)) {
|
|
3465
|
+
this.rebuildInstanceData();
|
|
3466
|
+
}
|
|
3467
|
+
}
|
|
3468
|
+
rebuildInstanceData() {
|
|
3469
|
+
const nextInstanceData = this.buildInstanceData(this.lightModelProps);
|
|
3470
|
+
const nextManagedBuffers = createManagedInstanceBuffers(this.device, this.id, nextInstanceData);
|
|
3471
|
+
this.setAttributes(nextManagedBuffers);
|
|
3472
|
+
this.setInstanceCount(nextInstanceData.instanceCount);
|
|
3473
|
+
destroyManagedInstanceBuffers(this._managedBuffers);
|
|
3474
|
+
this._managedBuffers = nextManagedBuffers;
|
|
3475
|
+
this._instanceData = nextInstanceData;
|
|
3476
|
+
}
|
|
3477
|
+
};
|
|
3478
|
+
function buildPointLightInstanceData(props) {
|
|
3479
|
+
const pointLights = getPointLights(props.lights);
|
|
3480
|
+
const context = getLightMarkerContext(props);
|
|
3481
|
+
const pointLightRadius = props.pointLightRadius ?? DEFAULT_POINT_LIGHT_RADIUS_FACTOR * context.sceneScale * context.markerScale;
|
|
3482
|
+
return createLightMarkerInstanceData(pointLights.length, (light, _index) => ({
|
|
3483
|
+
color: getDisplayColor(light),
|
|
3484
|
+
direction: DEFAULT_DIRECTION_FALLBACK,
|
|
3485
|
+
position: light.position,
|
|
3486
|
+
scale: [pointLightRadius, pointLightRadius, pointLightRadius]
|
|
3487
|
+
}), pointLights);
|
|
3488
|
+
}
|
|
3489
|
+
function buildSpotLightInstanceData(props) {
|
|
3490
|
+
const spotLights = getSpotLights(props.lights);
|
|
3491
|
+
const context = getLightMarkerContext(props);
|
|
3492
|
+
const spotLightLength = props.spotLightLength ?? DEFAULT_SPOT_LIGHT_LENGTH_FACTOR * context.sceneScale * context.markerScale;
|
|
3493
|
+
return createLightMarkerInstanceData(spotLights.length, (light, _index) => {
|
|
3494
|
+
const outerConeAngle = clamp(light.outerConeAngle ?? Math.PI / 4, 0, Math.PI / 2 - SPOTLIGHT_OUTER_CONE_EPSILON);
|
|
3495
|
+
const radius = Math.tan(outerConeAngle) * spotLightLength;
|
|
3496
|
+
return {
|
|
3497
|
+
color: getDisplayColor(light),
|
|
3498
|
+
direction: normalizeDirection(light.direction),
|
|
3499
|
+
position: light.position,
|
|
3500
|
+
scale: [radius, spotLightLength, radius]
|
|
3501
|
+
};
|
|
3502
|
+
}, spotLights);
|
|
3503
|
+
}
|
|
3504
|
+
function buildDirectionalLightInstanceData(props) {
|
|
3505
|
+
const directionalLights = getDirectionalLights(props.lights);
|
|
3506
|
+
const context = getLightMarkerContext(props);
|
|
3507
|
+
const directionalLightLength = props.directionalLightLength ?? DEFAULT_DIRECTIONAL_LIGHT_LENGTH_FACTOR * context.sceneScale * context.markerScale;
|
|
3508
|
+
const directionalLightRadius = directionalLightLength * DEFAULT_DIRECTIONAL_LIGHT_RADIUS_FACTOR;
|
|
3509
|
+
return createLightMarkerInstanceData(directionalLights.length, (light, _index) => {
|
|
3510
|
+
const direction = normalizeDirection(light.direction);
|
|
3511
|
+
const position = [
|
|
3512
|
+
context.sceneCenter[0] - direction[0] * context.sceneScale * DIRECTIONAL_ANCHOR_DISTANCE_FACTOR,
|
|
3513
|
+
context.sceneCenter[1] - direction[1] * context.sceneScale * DIRECTIONAL_ANCHOR_DISTANCE_FACTOR,
|
|
3514
|
+
context.sceneCenter[2] - direction[2] * context.sceneScale * DIRECTIONAL_ANCHOR_DISTANCE_FACTOR
|
|
3515
|
+
];
|
|
3516
|
+
return {
|
|
3517
|
+
color: getDisplayColor(light),
|
|
3518
|
+
direction,
|
|
3519
|
+
position,
|
|
3520
|
+
scale: [directionalLightRadius, directionalLightLength, directionalLightRadius]
|
|
3521
|
+
};
|
|
3522
|
+
}, directionalLights);
|
|
3523
|
+
}
|
|
3524
|
+
function getPointLights(lights) {
|
|
3525
|
+
return lights.filter((light) => light.type === "point");
|
|
3526
|
+
}
|
|
3527
|
+
function getSpotLights(lights) {
|
|
3528
|
+
return lights.filter((light) => light.type === "spot");
|
|
3529
|
+
}
|
|
3530
|
+
function getDirectionalLights(lights) {
|
|
3531
|
+
return lights.filter((light) => light.type === "directional");
|
|
3532
|
+
}
|
|
3533
|
+
function getLightMarkerContext(props) {
|
|
3534
|
+
const bounds = getSceneBounds(props.lights, props.bounds);
|
|
3535
|
+
const sceneCenter = [
|
|
3536
|
+
(bounds[0][0] + bounds[1][0]) / 2,
|
|
3537
|
+
(bounds[0][1] + bounds[1][1]) / 2,
|
|
3538
|
+
(bounds[0][2] + bounds[1][2]) / 2
|
|
3539
|
+
];
|
|
3540
|
+
const sceneScale = Math.max(Math.hypot(bounds[1][0] - bounds[0][0], bounds[1][1] - bounds[0][1], bounds[1][2] - bounds[0][2]), MIN_SCENE_SCALE);
|
|
3541
|
+
return {
|
|
3542
|
+
bounds,
|
|
3543
|
+
markerScale: Math.max(props.markerScale ?? DEFAULT_MARKER_SCALE, 0),
|
|
3544
|
+
sceneCenter,
|
|
3545
|
+
sceneScale
|
|
3546
|
+
};
|
|
3547
|
+
}
|
|
3548
|
+
function getDisplayColor(light) {
|
|
3549
|
+
const color = light.color || DEFAULT_LIGHT_COLOR;
|
|
3550
|
+
const intensity = Math.max(light.intensity ?? 1, 0);
|
|
3551
|
+
const brightness = clamp(0.35 + 0.3 * Math.log10(intensity + 1), 0.35, 1);
|
|
3552
|
+
return [
|
|
3553
|
+
clamp(color[0] / LIGHT_COLOR_FACTOR, 0, 1) * brightness,
|
|
3554
|
+
clamp(color[1] / LIGHT_COLOR_FACTOR, 0, 1) * brightness,
|
|
3555
|
+
clamp(color[2] / LIGHT_COLOR_FACTOR, 0, 1) * brightness,
|
|
3556
|
+
1
|
|
3557
|
+
];
|
|
3558
|
+
}
|
|
3559
|
+
function normalizeDirection(direction) {
|
|
3560
|
+
const [x, y, z] = direction || DEFAULT_DIRECTION_FALLBACK;
|
|
3561
|
+
const length = Math.hypot(x, y, z);
|
|
3562
|
+
if (length === 0) {
|
|
3563
|
+
return [...DEFAULT_DIRECTION_FALLBACK];
|
|
3564
|
+
}
|
|
3565
|
+
return [x / length, y / length, z / length];
|
|
3566
|
+
}
|
|
3567
|
+
function createLightMarkerInstanceData(instanceCount, getInstance, lights = []) {
|
|
3568
|
+
const instancePositions = new Float32Array(instanceCount * 3);
|
|
3569
|
+
const instanceDirections = new Float32Array(instanceCount * 3);
|
|
3570
|
+
const instanceScales = new Float32Array(instanceCount * 3);
|
|
3571
|
+
const instanceColors = new Float32Array(instanceCount * 4);
|
|
3572
|
+
for (const [index, light] of lights.entries()) {
|
|
3573
|
+
const instance = getInstance(light, index);
|
|
3574
|
+
instancePositions.set(instance.position, index * 3);
|
|
3575
|
+
instanceDirections.set(instance.direction, index * 3);
|
|
3576
|
+
instanceScales.set(instance.scale, index * 3);
|
|
3577
|
+
instanceColors.set(instance.color, index * 4);
|
|
3578
|
+
}
|
|
3579
|
+
return {
|
|
3580
|
+
instanceCount,
|
|
3581
|
+
instancePositions,
|
|
3582
|
+
instanceDirections,
|
|
3583
|
+
instanceScales,
|
|
3584
|
+
instanceColors
|
|
3585
|
+
};
|
|
3586
|
+
}
|
|
3587
|
+
function getSceneBounds(lights, bounds) {
|
|
3588
|
+
if (bounds) {
|
|
3589
|
+
return cloneBounds(bounds);
|
|
3590
|
+
}
|
|
3591
|
+
const positions = [
|
|
3592
|
+
...getPointLights(lights).map((light) => light.position),
|
|
3593
|
+
...getSpotLights(lights).map((light) => light.position)
|
|
3594
|
+
];
|
|
3595
|
+
if (positions.length === 0) {
|
|
3596
|
+
return [
|
|
3597
|
+
[-0.5, -0.5, -0.5],
|
|
3598
|
+
[0.5, 0.5, 0.5]
|
|
3599
|
+
];
|
|
3600
|
+
}
|
|
3601
|
+
const minBounds = [...positions[0]];
|
|
3602
|
+
const maxBounds = [...positions[0]];
|
|
3603
|
+
for (const position of positions.slice(1)) {
|
|
3604
|
+
minBounds[0] = Math.min(minBounds[0], position[0]);
|
|
3605
|
+
minBounds[1] = Math.min(minBounds[1], position[1]);
|
|
3606
|
+
minBounds[2] = Math.min(minBounds[2], position[2]);
|
|
3607
|
+
maxBounds[0] = Math.max(maxBounds[0], position[0]);
|
|
3608
|
+
maxBounds[1] = Math.max(maxBounds[1], position[1]);
|
|
3609
|
+
maxBounds[2] = Math.max(maxBounds[2], position[2]);
|
|
3610
|
+
}
|
|
3611
|
+
return [minBounds, maxBounds];
|
|
3612
|
+
}
|
|
3613
|
+
function cloneBounds(bounds) {
|
|
3614
|
+
return [[...bounds[0]], [...bounds[1]]];
|
|
3615
|
+
}
|
|
3616
|
+
function createManagedInstanceBuffers(device, idPrefix, instanceData) {
|
|
3617
|
+
return {
|
|
3618
|
+
instancePosition: device.createBuffer({
|
|
3619
|
+
id: `${idPrefix}-instance-position`,
|
|
3620
|
+
data: getBufferDataOrPlaceholder(instanceData.instancePositions, 3)
|
|
3621
|
+
}),
|
|
3622
|
+
instanceDirection: device.createBuffer({
|
|
3623
|
+
id: `${idPrefix}-instance-direction`,
|
|
3624
|
+
data: getBufferDataOrPlaceholder(instanceData.instanceDirections, 3)
|
|
3625
|
+
}),
|
|
3626
|
+
instanceScale: device.createBuffer({
|
|
3627
|
+
id: `${idPrefix}-instance-scale`,
|
|
3628
|
+
data: getBufferDataOrPlaceholder(instanceData.instanceScales, 3)
|
|
3629
|
+
}),
|
|
3630
|
+
instanceColor: device.createBuffer({
|
|
3631
|
+
id: `${idPrefix}-instance-color`,
|
|
3632
|
+
data: getBufferDataOrPlaceholder(instanceData.instanceColors, 4)
|
|
3633
|
+
})
|
|
3634
|
+
};
|
|
3635
|
+
}
|
|
3636
|
+
function getBufferDataOrPlaceholder(data, size) {
|
|
3637
|
+
return data.length > 0 ? data : new Float32Array(size);
|
|
3638
|
+
}
|
|
3639
|
+
function destroyManagedInstanceBuffers(managedBuffers) {
|
|
3640
|
+
for (const buffer of Object.values(managedBuffers)) {
|
|
3641
|
+
buffer == null ? void 0 : buffer.destroy();
|
|
3642
|
+
}
|
|
3643
|
+
}
|
|
3644
|
+
function createViewProjectionMatrix(props) {
|
|
3645
|
+
return new import_core11.Matrix4(props.projectionMatrix).multiplyRight(props.viewMatrix);
|
|
3646
|
+
}
|
|
3647
|
+
function shouldRebuildInstanceData(props, sizePropNames) {
|
|
3648
|
+
if ("lights" in props || "bounds" in props || "markerScale" in props) {
|
|
3649
|
+
return true;
|
|
3650
|
+
}
|
|
3651
|
+
return sizePropNames.some((sizePropName) => sizePropName in props);
|
|
3652
|
+
}
|
|
3653
|
+
function mergeLightMarkerParameters(parameters) {
|
|
3654
|
+
return {
|
|
3655
|
+
...LIGHT_MARKER_PARAMETERS,
|
|
3656
|
+
...parameters || {}
|
|
3657
|
+
};
|
|
3658
|
+
}
|
|
3659
|
+
function getLightMarkerShaders(anchorMode) {
|
|
3660
|
+
const localPositionWGSL = anchorMode === "apex" ? APEX_LOCAL_POSITION_WGSL : CENTERED_LOCAL_POSITION_WGSL;
|
|
3661
|
+
const localPositionGLSL = anchorMode === "apex" ? APEX_LOCAL_POSITION_GLSL : CENTERED_LOCAL_POSITION_GLSL;
|
|
3662
|
+
return {
|
|
3663
|
+
source: `struct lightMarkerUniforms {
|
|
3664
|
+
viewProjectionMatrix: mat4x4<f32>,
|
|
3665
|
+
};
|
|
3666
|
+
|
|
3667
|
+
@binding(0) @group(0) var<uniform> lightMarker : lightMarkerUniforms;
|
|
3668
|
+
|
|
3669
|
+
struct VertexInputs {
|
|
3670
|
+
@location(0) positions : vec3<f32>,
|
|
3671
|
+
@location(1) instancePosition : vec3<f32>,
|
|
3672
|
+
@location(2) instanceDirection : vec3<f32>,
|
|
3673
|
+
@location(3) instanceScale : vec3<f32>,
|
|
3674
|
+
@location(4) instanceColor : vec4<f32>,
|
|
3675
|
+
};
|
|
3676
|
+
|
|
3677
|
+
struct FragmentInputs {
|
|
3678
|
+
@builtin(position) Position : vec4<f32>,
|
|
3679
|
+
@location(0) color : vec4<f32>,
|
|
3680
|
+
};
|
|
3681
|
+
|
|
3682
|
+
fn lightMarker_rotate(localPosition: vec3<f32>, direction: vec3<f32>) -> vec3<f32> {
|
|
3683
|
+
let forward = normalize(direction);
|
|
3684
|
+
var helperAxis = vec3<f32>(0.0, 1.0, 0.0);
|
|
3685
|
+
if (abs(forward.y) > 0.999) {
|
|
3686
|
+
helperAxis = vec3<f32>(1.0, 0.0, 0.0);
|
|
3687
|
+
}
|
|
3688
|
+
|
|
3689
|
+
let tangent = normalize(cross(helperAxis, forward));
|
|
3690
|
+
let bitangent = cross(forward, tangent);
|
|
3691
|
+
return tangent * localPosition.x + forward * localPosition.y + bitangent * localPosition.z;
|
|
3692
|
+
}
|
|
3693
|
+
|
|
3694
|
+
@vertex
|
|
3695
|
+
fn vertexMain(inputs: VertexInputs) -> FragmentInputs {
|
|
3696
|
+
var outputs : FragmentInputs;
|
|
3697
|
+
let localPosition = ${localPositionWGSL};
|
|
3698
|
+
let worldPosition = inputs.instancePosition + lightMarker_rotate(localPosition, inputs.instanceDirection);
|
|
3699
|
+
outputs.Position = lightMarker.viewProjectionMatrix * vec4<f32>(worldPosition, 1.0);
|
|
3700
|
+
outputs.color = inputs.instanceColor;
|
|
3701
|
+
return outputs;
|
|
3702
|
+
}
|
|
3703
|
+
|
|
3704
|
+
@fragment
|
|
3705
|
+
fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4<f32> {
|
|
3706
|
+
return inputs.color;
|
|
3707
|
+
}
|
|
3708
|
+
`,
|
|
3709
|
+
vs: `#version 300 es
|
|
3710
|
+
|
|
3711
|
+
in vec3 positions;
|
|
3712
|
+
in vec3 instancePosition;
|
|
3713
|
+
in vec3 instanceDirection;
|
|
3714
|
+
in vec3 instanceScale;
|
|
3715
|
+
in vec4 instanceColor;
|
|
3716
|
+
|
|
3717
|
+
layout(std140) uniform lightMarkerUniforms {
|
|
3718
|
+
mat4 viewProjectionMatrix;
|
|
3719
|
+
} lightMarker;
|
|
3720
|
+
|
|
3721
|
+
out vec4 vColor;
|
|
3722
|
+
|
|
3723
|
+
vec3 lightMarker_rotate(vec3 localPosition, vec3 direction) {
|
|
3724
|
+
vec3 forward = normalize(direction);
|
|
3725
|
+
vec3 helperAxis = abs(forward.y) > 0.999 ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0);
|
|
3726
|
+
vec3 tangent = normalize(cross(helperAxis, forward));
|
|
3727
|
+
vec3 bitangent = cross(forward, tangent);
|
|
3728
|
+
return tangent * localPosition.x + forward * localPosition.y + bitangent * localPosition.z;
|
|
3729
|
+
}
|
|
3730
|
+
|
|
3731
|
+
void main(void) {
|
|
3732
|
+
vec3 localPosition = ${localPositionGLSL};
|
|
3733
|
+
vec3 worldPosition = instancePosition + lightMarker_rotate(localPosition, instanceDirection);
|
|
3734
|
+
gl_Position = lightMarker.viewProjectionMatrix * vec4(worldPosition, 1.0);
|
|
3735
|
+
vColor = instanceColor;
|
|
3736
|
+
}
|
|
3737
|
+
`,
|
|
3738
|
+
fs: `#version 300 es
|
|
3739
|
+
precision highp float;
|
|
3740
|
+
|
|
3741
|
+
in vec4 vColor;
|
|
3742
|
+
out vec4 fragColor;
|
|
3743
|
+
|
|
3744
|
+
void main(void) {
|
|
3745
|
+
fragColor = vColor;
|
|
3746
|
+
}
|
|
3747
|
+
`
|
|
3748
|
+
};
|
|
3749
|
+
}
|
|
3750
|
+
function clamp(value, minValue, maxValue) {
|
|
3751
|
+
return Math.min(maxValue, Math.max(minValue, value));
|
|
3752
|
+
}
|
|
3753
|
+
|
|
3754
|
+
// dist/models/point-light-model.js
|
|
3755
|
+
var POINT_LIGHT_GEOMETRY = new SphereGeometry({
|
|
3756
|
+
nlat: 8,
|
|
3757
|
+
nlong: 12,
|
|
3758
|
+
radius: 1
|
|
3759
|
+
});
|
|
3760
|
+
var PointLightModel = class extends BaseLightModel {
|
|
3761
|
+
constructor(device, props) {
|
|
3762
|
+
super(device, props, {
|
|
3763
|
+
anchorMode: "centered",
|
|
3764
|
+
buildInstanceData: buildPointLightInstanceData,
|
|
3765
|
+
geometry: POINT_LIGHT_GEOMETRY,
|
|
3766
|
+
idPrefix: "point-light-model",
|
|
3767
|
+
sizePropNames: ["pointLightRadius"]
|
|
3768
|
+
});
|
|
3769
|
+
}
|
|
3770
|
+
};
|
|
3771
|
+
|
|
3772
|
+
// dist/geometries/truncated-cone-geometry.js
|
|
3773
|
+
var INDEX_OFFSETS = {
|
|
3774
|
+
x: [2, 0, 1],
|
|
3775
|
+
y: [0, 1, 2],
|
|
3776
|
+
z: [1, 2, 0]
|
|
3777
|
+
};
|
|
3778
|
+
var TruncatedConeGeometry = class extends Geometry {
|
|
3779
|
+
constructor(props = {}) {
|
|
3780
|
+
const { id = uid("truncated-code-geometry") } = props;
|
|
3781
|
+
const { indices, attributes } = tesselateTruncatedCone(props);
|
|
3782
|
+
super({
|
|
3783
|
+
...props,
|
|
3784
|
+
id,
|
|
3785
|
+
topology: "triangle-list",
|
|
3786
|
+
indices,
|
|
3787
|
+
attributes: {
|
|
3788
|
+
POSITION: { size: 3, value: attributes.POSITION },
|
|
3789
|
+
NORMAL: { size: 3, value: attributes.NORMAL },
|
|
3790
|
+
TEXCOORD_0: { size: 2, value: attributes.TEXCOORD_0 },
|
|
3791
|
+
...props.attributes
|
|
3792
|
+
}
|
|
3793
|
+
});
|
|
3794
|
+
}
|
|
3795
|
+
};
|
|
3796
|
+
function tesselateTruncatedCone(props = {}) {
|
|
3797
|
+
const { bottomRadius = 0, topRadius = 0, height = 1, nradial = 10, nvertical = 10, verticalAxis = "y", topCap = false, bottomCap = false } = props;
|
|
3798
|
+
const extra = (topCap ? 2 : 0) + (bottomCap ? 2 : 0);
|
|
3799
|
+
const numVertices = (nradial + 1) * (nvertical + 1 + extra);
|
|
3800
|
+
const slant = Math.atan2(bottomRadius - topRadius, height);
|
|
3801
|
+
const msin = Math.sin;
|
|
3802
|
+
const mcos = Math.cos;
|
|
3803
|
+
const mpi = Math.PI;
|
|
3804
|
+
const cosSlant = mcos(slant);
|
|
3805
|
+
const sinSlant = msin(slant);
|
|
3806
|
+
const start = topCap ? -2 : 0;
|
|
3807
|
+
const end = nvertical + (bottomCap ? 2 : 0);
|
|
3808
|
+
const vertsAroundEdge = nradial + 1;
|
|
3809
|
+
const indices = new Uint16Array(nradial * (nvertical + extra) * 6);
|
|
3810
|
+
const indexOffset = INDEX_OFFSETS[verticalAxis];
|
|
3811
|
+
const positions = new Float32Array(numVertices * 3);
|
|
3812
|
+
const normals = new Float32Array(numVertices * 3);
|
|
3813
|
+
const texCoords = new Float32Array(numVertices * 2);
|
|
3814
|
+
let i3 = 0;
|
|
3815
|
+
let i2 = 0;
|
|
3816
|
+
for (let i = start; i <= end; i++) {
|
|
3817
|
+
let v = i / nvertical;
|
|
3818
|
+
let y = height * v;
|
|
3819
|
+
let ringRadius;
|
|
3820
|
+
if (i < 0) {
|
|
3821
|
+
y = 0;
|
|
3822
|
+
v = 1;
|
|
3823
|
+
ringRadius = bottomRadius;
|
|
3824
|
+
} else if (i > nvertical) {
|
|
3825
|
+
y = height;
|
|
3826
|
+
v = 1;
|
|
3827
|
+
ringRadius = topRadius;
|
|
3828
|
+
} else {
|
|
3829
|
+
ringRadius = bottomRadius + (topRadius - bottomRadius) * (i / nvertical);
|
|
3830
|
+
}
|
|
3831
|
+
if (i === -2 || i === nvertical + 2) {
|
|
3832
|
+
ringRadius = 0;
|
|
3833
|
+
v = 0;
|
|
3834
|
+
}
|
|
3835
|
+
y -= height / 2;
|
|
3836
|
+
for (let j = 0; j < vertsAroundEdge; j++) {
|
|
3837
|
+
const sin = msin(j * mpi * 2 / nradial);
|
|
3838
|
+
const cos = mcos(j * mpi * 2 / nradial);
|
|
3839
|
+
positions[i3 + indexOffset[0]] = sin * ringRadius;
|
|
3840
|
+
positions[i3 + indexOffset[1]] = y;
|
|
3841
|
+
positions[i3 + indexOffset[2]] = cos * ringRadius;
|
|
3842
|
+
normals[i3 + indexOffset[0]] = i < 0 || i > nvertical ? 0 : sin * cosSlant;
|
|
3843
|
+
normals[i3 + indexOffset[1]] = i < 0 ? -1 : i > nvertical ? 1 : sinSlant;
|
|
3844
|
+
normals[i3 + indexOffset[2]] = i < 0 || i > nvertical ? 0 : cos * cosSlant;
|
|
3845
|
+
texCoords[i2 + 0] = j / nradial;
|
|
3846
|
+
texCoords[i2 + 1] = v;
|
|
3847
|
+
i2 += 2;
|
|
3848
|
+
i3 += 3;
|
|
3849
|
+
}
|
|
3850
|
+
}
|
|
3851
|
+
for (let i = 0; i < nvertical + extra; i++) {
|
|
3852
|
+
for (let j = 0; j < nradial; j++) {
|
|
3853
|
+
const index = (i * nradial + j) * 6;
|
|
3854
|
+
indices[index + 0] = vertsAroundEdge * (i + 0) + 0 + j;
|
|
3855
|
+
indices[index + 1] = vertsAroundEdge * (i + 0) + 1 + j;
|
|
3856
|
+
indices[index + 2] = vertsAroundEdge * (i + 1) + 1 + j;
|
|
3857
|
+
indices[index + 3] = vertsAroundEdge * (i + 0) + 0 + j;
|
|
3858
|
+
indices[index + 4] = vertsAroundEdge * (i + 1) + 1 + j;
|
|
3859
|
+
indices[index + 5] = vertsAroundEdge * (i + 1) + 0 + j;
|
|
3860
|
+
}
|
|
3861
|
+
}
|
|
3862
|
+
return {
|
|
3863
|
+
indices,
|
|
3864
|
+
attributes: {
|
|
3865
|
+
POSITION: positions,
|
|
3866
|
+
NORMAL: normals,
|
|
3867
|
+
TEXCOORD_0: texCoords
|
|
3868
|
+
}
|
|
3869
|
+
};
|
|
3870
|
+
}
|
|
3871
|
+
|
|
3872
|
+
// dist/geometries/cone-geometry.js
|
|
3873
|
+
var ConeGeometry = class extends TruncatedConeGeometry {
|
|
3874
|
+
constructor(props = {}) {
|
|
3875
|
+
const { id = uid("cone-geometry"), radius = 1, cap = true } = props;
|
|
3876
|
+
super({
|
|
3877
|
+
...props,
|
|
3878
|
+
id,
|
|
3879
|
+
topRadius: 0,
|
|
3880
|
+
topCap: Boolean(cap),
|
|
3881
|
+
bottomCap: Boolean(cap),
|
|
3882
|
+
bottomRadius: radius
|
|
3883
|
+
});
|
|
3884
|
+
}
|
|
3885
|
+
};
|
|
3886
|
+
|
|
3887
|
+
// dist/models/spot-light-model.js
|
|
3888
|
+
var SPOT_LIGHT_GEOMETRY = new ConeGeometry({
|
|
3889
|
+
cap: true,
|
|
3890
|
+
nradial: 16,
|
|
3891
|
+
nvertical: 1,
|
|
3892
|
+
radius: 1
|
|
3893
|
+
});
|
|
3894
|
+
var SpotLightModel = class extends BaseLightModel {
|
|
3895
|
+
constructor(device, props) {
|
|
3896
|
+
super(device, props, {
|
|
3897
|
+
anchorMode: "apex",
|
|
3898
|
+
buildInstanceData: buildSpotLightInstanceData,
|
|
3899
|
+
geometry: SPOT_LIGHT_GEOMETRY,
|
|
3900
|
+
idPrefix: "spot-light-model",
|
|
3901
|
+
sizePropNames: ["spotLightLength"]
|
|
3902
|
+
});
|
|
3903
|
+
}
|
|
3904
|
+
};
|
|
3905
|
+
|
|
3906
|
+
// dist/models/directional-light-model.js
|
|
3907
|
+
var DIRECTIONAL_LIGHT_GEOMETRY = new ConeGeometry({
|
|
3908
|
+
cap: true,
|
|
3909
|
+
nradial: 12,
|
|
3910
|
+
nvertical: 1,
|
|
3911
|
+
radius: 1
|
|
3912
|
+
});
|
|
3913
|
+
var DirectionalLightModel = class extends BaseLightModel {
|
|
3914
|
+
constructor(device, props) {
|
|
3915
|
+
super(device, props, {
|
|
3916
|
+
anchorMode: "apex",
|
|
3917
|
+
buildInstanceData: buildDirectionalLightInstanceData,
|
|
3918
|
+
geometry: DIRECTIONAL_LIGHT_GEOMETRY,
|
|
3919
|
+
idPrefix: "directional-light-model",
|
|
3920
|
+
sizePropNames: ["directionalLightLength"]
|
|
3921
|
+
});
|
|
3922
|
+
}
|
|
3923
|
+
};
|
|
3924
|
+
|
|
3925
|
+
// dist/scenegraph/scenegraph-node.js
|
|
3926
|
+
var import_core12 = require("@math.gl/core");
|
|
3927
|
+
function assert(condition, message) {
|
|
3928
|
+
if (!condition) {
|
|
3929
|
+
throw new Error(message);
|
|
3930
|
+
}
|
|
3931
|
+
}
|
|
3932
|
+
var ScenegraphNode = class {
|
|
3933
|
+
id;
|
|
3934
|
+
matrix = new import_core12.Matrix4();
|
|
3935
|
+
display = true;
|
|
3936
|
+
position = new import_core12.Vector3();
|
|
3937
|
+
rotation = new import_core12.Vector3();
|
|
3938
|
+
scale = new import_core12.Vector3(1, 1, 1);
|
|
3939
|
+
userData = {};
|
|
3940
|
+
props = {};
|
|
3941
|
+
constructor(props = {}) {
|
|
3942
|
+
const { id } = props;
|
|
3943
|
+
this.id = id || uid(this.constructor.name);
|
|
3944
|
+
this._setScenegraphNodeProps(props);
|
|
3945
|
+
}
|
|
3946
|
+
getBounds() {
|
|
3947
|
+
return null;
|
|
3948
|
+
}
|
|
3949
|
+
destroy() {
|
|
3950
|
+
}
|
|
3951
|
+
/** @deprecated use .destroy() */
|
|
3952
|
+
delete() {
|
|
3953
|
+
this.destroy();
|
|
3954
|
+
}
|
|
3955
|
+
setProps(props) {
|
|
3956
|
+
this._setScenegraphNodeProps(props);
|
|
3957
|
+
return this;
|
|
2710
3958
|
}
|
|
2711
3959
|
toString() {
|
|
2712
3960
|
return `{type: ScenegraphNode, id: ${this.id})}`;
|
|
2713
3961
|
}
|
|
2714
3962
|
setPosition(position) {
|
|
3963
|
+
assert(position.length === 3, "setPosition requires vector argument");
|
|
2715
3964
|
this.position = position;
|
|
2716
3965
|
return this;
|
|
2717
3966
|
}
|
|
2718
3967
|
setRotation(rotation) {
|
|
3968
|
+
assert(rotation.length === 3 || rotation.length === 4, "setRotation requires vector argument");
|
|
2719
3969
|
this.rotation = rotation;
|
|
2720
3970
|
return this;
|
|
2721
3971
|
}
|
|
2722
3972
|
setScale(scale) {
|
|
3973
|
+
assert(scale.length === 3, "setScale requires vector argument");
|
|
2723
3974
|
this.scale = scale;
|
|
2724
3975
|
return this;
|
|
2725
3976
|
}
|
|
@@ -2747,17 +3998,18 @@ var ScenegraphNode = class {
|
|
|
2747
3998
|
return this;
|
|
2748
3999
|
}
|
|
2749
4000
|
updateMatrix() {
|
|
2750
|
-
const pos = this.position;
|
|
2751
|
-
const rot = this.rotation;
|
|
2752
|
-
const scale = this.scale;
|
|
2753
4001
|
this.matrix.identity();
|
|
2754
|
-
this.matrix.translate(
|
|
2755
|
-
this.
|
|
2756
|
-
|
|
4002
|
+
this.matrix.translate(this.position);
|
|
4003
|
+
if (this.rotation.length === 4) {
|
|
4004
|
+
const rotationMatrix = new import_core12.Matrix4().fromQuaternion(this.rotation);
|
|
4005
|
+
this.matrix.multiplyRight(rotationMatrix);
|
|
4006
|
+
} else {
|
|
4007
|
+
this.matrix.rotateXYZ(this.rotation);
|
|
4008
|
+
}
|
|
4009
|
+
this.matrix.scale(this.scale);
|
|
2757
4010
|
return this;
|
|
2758
4011
|
}
|
|
2759
|
-
update(
|
|
2760
|
-
const { position, rotation, scale } = options;
|
|
4012
|
+
update({ position, rotation, scale } = {}) {
|
|
2761
4013
|
if (position) {
|
|
2762
4014
|
this.setPosition(position);
|
|
2763
4015
|
}
|
|
@@ -2772,7 +4024,7 @@ var ScenegraphNode = class {
|
|
|
2772
4024
|
}
|
|
2773
4025
|
getCoordinateUniforms(viewMatrix, modelMatrix) {
|
|
2774
4026
|
modelMatrix = modelMatrix || this.matrix;
|
|
2775
|
-
const worldMatrix = new
|
|
4027
|
+
const worldMatrix = new import_core12.Matrix4(viewMatrix).multiplyRight(modelMatrix);
|
|
2776
4028
|
const worldInverse = worldMatrix.invert();
|
|
2777
4029
|
const worldInverseTranspose = worldInverse.transpose();
|
|
2778
4030
|
return {
|
|
@@ -2807,16 +4059,17 @@ var ScenegraphNode = class {
|
|
|
2807
4059
|
}
|
|
2808
4060
|
*/
|
|
2809
4061
|
_setScenegraphNodeProps(props) {
|
|
2810
|
-
if (
|
|
4062
|
+
if (props == null ? void 0 : props.position) {
|
|
2811
4063
|
this.setPosition(props.position);
|
|
2812
4064
|
}
|
|
2813
|
-
if (
|
|
4065
|
+
if (props == null ? void 0 : props.rotation) {
|
|
2814
4066
|
this.setRotation(props.rotation);
|
|
2815
4067
|
}
|
|
2816
|
-
if (
|
|
4068
|
+
if (props == null ? void 0 : props.scale) {
|
|
2817
4069
|
this.setScale(props.scale);
|
|
2818
4070
|
}
|
|
2819
|
-
|
|
4071
|
+
this.updateMatrix();
|
|
4072
|
+
if (props == null ? void 0 : props.matrix) {
|
|
2820
4073
|
this.setMatrix(props.matrix);
|
|
2821
4074
|
}
|
|
2822
4075
|
Object.assign(this.props, props);
|
|
@@ -2824,14 +4077,14 @@ var ScenegraphNode = class {
|
|
|
2824
4077
|
};
|
|
2825
4078
|
|
|
2826
4079
|
// dist/scenegraph/group-node.js
|
|
2827
|
-
var
|
|
2828
|
-
var
|
|
4080
|
+
var import_core13 = require("@math.gl/core");
|
|
4081
|
+
var import_core14 = require("@luma.gl/core");
|
|
2829
4082
|
var GroupNode = class extends ScenegraphNode {
|
|
2830
4083
|
children;
|
|
2831
4084
|
constructor(props = {}) {
|
|
2832
4085
|
props = Array.isArray(props) ? { children: props } : props;
|
|
2833
4086
|
const { children = [] } = props;
|
|
2834
|
-
|
|
4087
|
+
import_core14.log.assert(children.every((child) => child instanceof ScenegraphNode), "every child must an instance of ScenegraphNode");
|
|
2835
4088
|
super(props);
|
|
2836
4089
|
this.children = children;
|
|
2837
4090
|
}
|
|
@@ -2846,12 +4099,12 @@ var GroupNode = class extends ScenegraphNode {
|
|
|
2846
4099
|
return;
|
|
2847
4100
|
}
|
|
2848
4101
|
const [min, max] = bounds;
|
|
2849
|
-
const center = new
|
|
4102
|
+
const center = new import_core13.Vector3(min).add(max).divide([2, 2, 2]);
|
|
2850
4103
|
worldMatrix.transformAsPoint(center, center);
|
|
2851
|
-
const halfSize = new
|
|
4104
|
+
const halfSize = new import_core13.Vector3(max).subtract(min).divide([2, 2, 2]);
|
|
2852
4105
|
worldMatrix.transformAsVector(halfSize, halfSize);
|
|
2853
4106
|
for (let v = 0; v < 8; v++) {
|
|
2854
|
-
const position = new
|
|
4107
|
+
const position = new import_core13.Vector3(v & 1 ? -1 : 1, v & 2 ? -1 : 1, v & 4 ? -1 : 1).multiply(halfSize).add(center);
|
|
2855
4108
|
for (let i = 0; i < 3; i++) {
|
|
2856
4109
|
result[0][i] = Math.min(result[0][i], position[i]);
|
|
2857
4110
|
result[1][i] = Math.max(result[1][i], position[i]);
|
|
@@ -2864,190 +4117,86 @@ var GroupNode = class extends ScenegraphNode {
|
|
|
2864
4117
|
return result;
|
|
2865
4118
|
}
|
|
2866
4119
|
destroy() {
|
|
2867
|
-
this.children.forEach((child) => child.destroy());
|
|
2868
|
-
this.removeAll();
|
|
2869
|
-
super.destroy();
|
|
2870
|
-
}
|
|
2871
|
-
// Unpacks arrays and nested arrays of children
|
|
2872
|
-
add(...children) {
|
|
2873
|
-
for (const child of children) {
|
|
2874
|
-
if (Array.isArray(child)) {
|
|
2875
|
-
this.add(...child);
|
|
2876
|
-
} else {
|
|
2877
|
-
this.children.push(child);
|
|
2878
|
-
}
|
|
2879
|
-
}
|
|
2880
|
-
return this;
|
|
2881
|
-
}
|
|
2882
|
-
remove(child) {
|
|
2883
|
-
const children = this.children;
|
|
2884
|
-
const indexOf = children.indexOf(child);
|
|
2885
|
-
if (indexOf > -1) {
|
|
2886
|
-
children.splice(indexOf, 1);
|
|
2887
|
-
}
|
|
2888
|
-
return this;
|
|
2889
|
-
}
|
|
2890
|
-
removeAll() {
|
|
2891
|
-
this.children = [];
|
|
2892
|
-
return this;
|
|
2893
|
-
}
|
|
2894
|
-
traverse(visitor, { worldMatrix = new import_core12.Matrix4() } = {}) {
|
|
2895
|
-
const modelMatrix = new import_core12.Matrix4(worldMatrix).multiplyRight(this.matrix);
|
|
2896
|
-
for (const child of this.children) {
|
|
2897
|
-
if (child instanceof GroupNode) {
|
|
2898
|
-
child.traverse(visitor, { worldMatrix: modelMatrix });
|
|
2899
|
-
} else {
|
|
2900
|
-
visitor(child, { worldMatrix: modelMatrix });
|
|
2901
|
-
}
|
|
2902
|
-
}
|
|
2903
|
-
}
|
|
2904
|
-
};
|
|
2905
|
-
|
|
2906
|
-
// dist/scenegraph/model-node.js
|
|
2907
|
-
var ModelNode = class extends ScenegraphNode {
|
|
2908
|
-
model;
|
|
2909
|
-
bounds = null;
|
|
2910
|
-
managedResources;
|
|
2911
|
-
// TODO - is this used? override callbacks to make sure we call them with this
|
|
2912
|
-
// onBeforeRender = null;
|
|
2913
|
-
// onAfterRender = null;
|
|
2914
|
-
// AfterRender = null;
|
|
2915
|
-
constructor(props) {
|
|
2916
|
-
super(props);
|
|
2917
|
-
this.model = props.model;
|
|
2918
|
-
this.managedResources = props.managedResources || [];
|
|
2919
|
-
this.bounds = props.bounds || null;
|
|
2920
|
-
this.setProps(props);
|
|
2921
|
-
}
|
|
2922
|
-
destroy() {
|
|
2923
|
-
if (this.model) {
|
|
2924
|
-
this.model.destroy();
|
|
2925
|
-
this.model = null;
|
|
2926
|
-
}
|
|
2927
|
-
this.managedResources.forEach((resource) => resource.destroy());
|
|
2928
|
-
this.managedResources = [];
|
|
2929
|
-
}
|
|
2930
|
-
getBounds() {
|
|
2931
|
-
return this.bounds;
|
|
2932
|
-
}
|
|
2933
|
-
// Expose model methods
|
|
2934
|
-
draw(renderPass) {
|
|
2935
|
-
return this.model.draw(renderPass);
|
|
2936
|
-
}
|
|
2937
|
-
};
|
|
2938
|
-
|
|
2939
|
-
// dist/geometries/truncated-cone-geometry.js
|
|
2940
|
-
var INDEX_OFFSETS = {
|
|
2941
|
-
x: [2, 0, 1],
|
|
2942
|
-
y: [0, 1, 2],
|
|
2943
|
-
z: [1, 2, 0]
|
|
2944
|
-
};
|
|
2945
|
-
var TruncatedConeGeometry = class extends Geometry {
|
|
2946
|
-
constructor(props = {}) {
|
|
2947
|
-
const { id = uid("truncated-code-geometry") } = props;
|
|
2948
|
-
const { indices, attributes } = tesselateTruncatedCone(props);
|
|
2949
|
-
super({
|
|
2950
|
-
...props,
|
|
2951
|
-
id,
|
|
2952
|
-
topology: "triangle-list",
|
|
2953
|
-
indices,
|
|
2954
|
-
attributes: {
|
|
2955
|
-
POSITION: { size: 3, value: attributes.POSITION },
|
|
2956
|
-
NORMAL: { size: 3, value: attributes.NORMAL },
|
|
2957
|
-
TEXCOORD_0: { size: 2, value: attributes.TEXCOORD_0 },
|
|
2958
|
-
...props.attributes
|
|
2959
|
-
}
|
|
2960
|
-
});
|
|
2961
|
-
}
|
|
2962
|
-
};
|
|
2963
|
-
function tesselateTruncatedCone(props = {}) {
|
|
2964
|
-
const { bottomRadius = 0, topRadius = 0, height = 1, nradial = 10, nvertical = 10, verticalAxis = "y", topCap = false, bottomCap = false } = props;
|
|
2965
|
-
const extra = (topCap ? 2 : 0) + (bottomCap ? 2 : 0);
|
|
2966
|
-
const numVertices = (nradial + 1) * (nvertical + 1 + extra);
|
|
2967
|
-
const slant = Math.atan2(bottomRadius - topRadius, height);
|
|
2968
|
-
const msin = Math.sin;
|
|
2969
|
-
const mcos = Math.cos;
|
|
2970
|
-
const mpi = Math.PI;
|
|
2971
|
-
const cosSlant = mcos(slant);
|
|
2972
|
-
const sinSlant = msin(slant);
|
|
2973
|
-
const start = topCap ? -2 : 0;
|
|
2974
|
-
const end = nvertical + (bottomCap ? 2 : 0);
|
|
2975
|
-
const vertsAroundEdge = nradial + 1;
|
|
2976
|
-
const indices = new Uint16Array(nradial * (nvertical + extra) * 6);
|
|
2977
|
-
const indexOffset = INDEX_OFFSETS[verticalAxis];
|
|
2978
|
-
const positions = new Float32Array(numVertices * 3);
|
|
2979
|
-
const normals = new Float32Array(numVertices * 3);
|
|
2980
|
-
const texCoords = new Float32Array(numVertices * 2);
|
|
2981
|
-
let i3 = 0;
|
|
2982
|
-
let i2 = 0;
|
|
2983
|
-
for (let i = start; i <= end; i++) {
|
|
2984
|
-
let v = i / nvertical;
|
|
2985
|
-
let y = height * v;
|
|
2986
|
-
let ringRadius;
|
|
2987
|
-
if (i < 0) {
|
|
2988
|
-
y = 0;
|
|
2989
|
-
v = 1;
|
|
2990
|
-
ringRadius = bottomRadius;
|
|
2991
|
-
} else if (i > nvertical) {
|
|
2992
|
-
y = height;
|
|
2993
|
-
v = 1;
|
|
2994
|
-
ringRadius = topRadius;
|
|
2995
|
-
} else {
|
|
2996
|
-
ringRadius = bottomRadius + (topRadius - bottomRadius) * (i / nvertical);
|
|
2997
|
-
}
|
|
2998
|
-
if (i === -2 || i === nvertical + 2) {
|
|
2999
|
-
ringRadius = 0;
|
|
3000
|
-
v = 0;
|
|
3001
|
-
}
|
|
3002
|
-
y -= height / 2;
|
|
3003
|
-
for (let j = 0; j < vertsAroundEdge; j++) {
|
|
3004
|
-
const sin = msin(j * mpi * 2 / nradial);
|
|
3005
|
-
const cos = mcos(j * mpi * 2 / nradial);
|
|
3006
|
-
positions[i3 + indexOffset[0]] = sin * ringRadius;
|
|
3007
|
-
positions[i3 + indexOffset[1]] = y;
|
|
3008
|
-
positions[i3 + indexOffset[2]] = cos * ringRadius;
|
|
3009
|
-
normals[i3 + indexOffset[0]] = i < 0 || i > nvertical ? 0 : sin * cosSlant;
|
|
3010
|
-
normals[i3 + indexOffset[1]] = i < 0 ? -1 : i > nvertical ? 1 : sinSlant;
|
|
3011
|
-
normals[i3 + indexOffset[2]] = i < 0 || i > nvertical ? 0 : cos * cosSlant;
|
|
3012
|
-
texCoords[i2 + 0] = j / nradial;
|
|
3013
|
-
texCoords[i2 + 1] = v;
|
|
3014
|
-
i2 += 2;
|
|
3015
|
-
i3 += 3;
|
|
4120
|
+
this.children.forEach((child) => child.destroy());
|
|
4121
|
+
this.removeAll();
|
|
4122
|
+
super.destroy();
|
|
4123
|
+
}
|
|
4124
|
+
// Unpacks arrays and nested arrays of children
|
|
4125
|
+
add(...children) {
|
|
4126
|
+
for (const child of children) {
|
|
4127
|
+
if (Array.isArray(child)) {
|
|
4128
|
+
this.add(...child);
|
|
4129
|
+
} else {
|
|
4130
|
+
this.children.push(child);
|
|
4131
|
+
}
|
|
3016
4132
|
}
|
|
4133
|
+
return this;
|
|
3017
4134
|
}
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
indices[index + 2] = vertsAroundEdge * (i + 1) + 1 + j;
|
|
3024
|
-
indices[index + 3] = vertsAroundEdge * (i + 0) + 0 + j;
|
|
3025
|
-
indices[index + 4] = vertsAroundEdge * (i + 1) + 1 + j;
|
|
3026
|
-
indices[index + 5] = vertsAroundEdge * (i + 1) + 0 + j;
|
|
4135
|
+
remove(child) {
|
|
4136
|
+
const children = this.children;
|
|
4137
|
+
const indexOf = children.indexOf(child);
|
|
4138
|
+
if (indexOf > -1) {
|
|
4139
|
+
children.splice(indexOf, 1);
|
|
3027
4140
|
}
|
|
4141
|
+
return this;
|
|
3028
4142
|
}
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
4143
|
+
removeAll() {
|
|
4144
|
+
this.children = [];
|
|
4145
|
+
return this;
|
|
4146
|
+
}
|
|
4147
|
+
traverse(visitor, { worldMatrix = new import_core13.Matrix4() } = {}) {
|
|
4148
|
+
const modelMatrix = new import_core13.Matrix4(worldMatrix).multiplyRight(this.matrix);
|
|
4149
|
+
for (const child of this.children) {
|
|
4150
|
+
if (child instanceof GroupNode) {
|
|
4151
|
+
child.traverse(visitor, { worldMatrix: modelMatrix });
|
|
4152
|
+
} else {
|
|
4153
|
+
visitor(child, { worldMatrix: modelMatrix });
|
|
4154
|
+
}
|
|
3035
4155
|
}
|
|
3036
|
-
}
|
|
3037
|
-
}
|
|
4156
|
+
}
|
|
4157
|
+
preorderTraversal(visitor, { worldMatrix = new import_core13.Matrix4() } = {}) {
|
|
4158
|
+
const modelMatrix = new import_core13.Matrix4(worldMatrix).multiplyRight(this.matrix);
|
|
4159
|
+
visitor(this, { worldMatrix: modelMatrix });
|
|
4160
|
+
for (const child of this.children) {
|
|
4161
|
+
if (child instanceof GroupNode) {
|
|
4162
|
+
child.preorderTraversal(visitor, { worldMatrix: modelMatrix });
|
|
4163
|
+
} else {
|
|
4164
|
+
visitor(child, { worldMatrix: modelMatrix });
|
|
4165
|
+
}
|
|
4166
|
+
}
|
|
4167
|
+
}
|
|
4168
|
+
};
|
|
3038
4169
|
|
|
3039
|
-
// dist/
|
|
3040
|
-
var
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
4170
|
+
// dist/scenegraph/model-node.js
|
|
4171
|
+
var ModelNode = class extends ScenegraphNode {
|
|
4172
|
+
model;
|
|
4173
|
+
bounds = null;
|
|
4174
|
+
managedResources;
|
|
4175
|
+
// TODO - is this used? override callbacks to make sure we call them with this
|
|
4176
|
+
// onBeforeRender = null;
|
|
4177
|
+
// onAfterRender = null;
|
|
4178
|
+
// AfterRender = null;
|
|
4179
|
+
constructor(props) {
|
|
4180
|
+
super(props);
|
|
4181
|
+
this.model = props.model;
|
|
4182
|
+
this.managedResources = props.managedResources || [];
|
|
4183
|
+
this.bounds = props.bounds || null;
|
|
4184
|
+
this.setProps(props);
|
|
4185
|
+
}
|
|
4186
|
+
destroy() {
|
|
4187
|
+
if (this.model) {
|
|
4188
|
+
this.model.destroy();
|
|
4189
|
+
this.model = null;
|
|
4190
|
+
}
|
|
4191
|
+
this.managedResources.forEach((resource) => resource.destroy());
|
|
4192
|
+
this.managedResources = [];
|
|
4193
|
+
}
|
|
4194
|
+
getBounds() {
|
|
4195
|
+
return this.bounds;
|
|
4196
|
+
}
|
|
4197
|
+
// Expose model methods
|
|
4198
|
+
draw(renderPass) {
|
|
4199
|
+
return this.model.draw(renderPass);
|
|
3051
4200
|
}
|
|
3052
4201
|
};
|
|
3053
4202
|
|
|
@@ -3674,7 +4823,7 @@ var CylinderGeometry = class extends TruncatedConeGeometry {
|
|
|
3674
4823
|
};
|
|
3675
4824
|
|
|
3676
4825
|
// dist/geometries/ico-sphere-geometry.js
|
|
3677
|
-
var
|
|
4826
|
+
var import_core15 = require("@math.gl/core");
|
|
3678
4827
|
var ICO_POSITIONS = [-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 1, 0, -1, 0, 1, 0, 0];
|
|
3679
4828
|
var ICO_INDICES = [3, 4, 5, 3, 5, 1, 3, 1, 0, 3, 0, 4, 4, 0, 2, 4, 2, 5, 2, 0, 1, 5, 2, 1];
|
|
3680
4829
|
var IcoSphereGeometry = class extends Geometry {
|
|
@@ -3772,7 +4921,7 @@ function tesselateIcosaHedron(props) {
|
|
|
3772
4921
|
const u3 = 1 - phi3 / PI2;
|
|
3773
4922
|
const vec1 = [x3 - x2, y3 - y2, z3 - z2];
|
|
3774
4923
|
const vec2 = [x1 - x2, y1 - y2, z1 - z2];
|
|
3775
|
-
const normal = new
|
|
4924
|
+
const normal = new import_core15.Vector3(vec1).cross(vec2).normalize();
|
|
3776
4925
|
let newIndex;
|
|
3777
4926
|
if ((u1 === 0 || u2 === 0 || u3 === 0) && (u1 === 0 || u1 > 0.5) && (u2 === 0 || u2 > 0.5) && (u3 === 0 || u3 > 0.5)) {
|
|
3778
4927
|
positions.push(positions[in1 + 0], positions[in1 + 1], positions[in1 + 2]);
|
|
@@ -3940,84 +5089,6 @@ function tesselatePlane(props) {
|
|
|
3940
5089
|
return unpack ? unpackIndexedGeometry(geometry) : geometry;
|
|
3941
5090
|
}
|
|
3942
5091
|
|
|
3943
|
-
// dist/geometries/sphere-geometry.js
|
|
3944
|
-
var SphereGeometry = class extends Geometry {
|
|
3945
|
-
constructor(props = {}) {
|
|
3946
|
-
const { id = uid("sphere-geometry") } = props;
|
|
3947
|
-
const { indices, attributes } = tesselateSphere(props);
|
|
3948
|
-
super({
|
|
3949
|
-
...props,
|
|
3950
|
-
id,
|
|
3951
|
-
topology: "triangle-list",
|
|
3952
|
-
indices,
|
|
3953
|
-
attributes: { ...attributes, ...props.attributes }
|
|
3954
|
-
});
|
|
3955
|
-
}
|
|
3956
|
-
};
|
|
3957
|
-
function tesselateSphere(props) {
|
|
3958
|
-
const { nlat = 10, nlong = 10 } = props;
|
|
3959
|
-
const startLat = 0;
|
|
3960
|
-
const endLat = Math.PI;
|
|
3961
|
-
const latRange = endLat - startLat;
|
|
3962
|
-
const startLong = 0;
|
|
3963
|
-
const endLong = 2 * Math.PI;
|
|
3964
|
-
const longRange = endLong - startLong;
|
|
3965
|
-
const numVertices = (nlat + 1) * (nlong + 1);
|
|
3966
|
-
const radius = (n1, n2, n3, u, v) => props.radius || 1;
|
|
3967
|
-
const positions = new Float32Array(numVertices * 3);
|
|
3968
|
-
const normals = new Float32Array(numVertices * 3);
|
|
3969
|
-
const texCoords = new Float32Array(numVertices * 2);
|
|
3970
|
-
const IndexType = numVertices > 65535 ? Uint32Array : Uint16Array;
|
|
3971
|
-
const indices = new IndexType(nlat * nlong * 6);
|
|
3972
|
-
for (let y = 0; y <= nlat; y++) {
|
|
3973
|
-
for (let x = 0; x <= nlong; x++) {
|
|
3974
|
-
const u = x / nlong;
|
|
3975
|
-
const v = y / nlat;
|
|
3976
|
-
const index = x + y * (nlong + 1);
|
|
3977
|
-
const i2 = index * 2;
|
|
3978
|
-
const i3 = index * 3;
|
|
3979
|
-
const theta = longRange * u;
|
|
3980
|
-
const phi = latRange * v;
|
|
3981
|
-
const sinTheta = Math.sin(theta);
|
|
3982
|
-
const cosTheta = Math.cos(theta);
|
|
3983
|
-
const sinPhi = Math.sin(phi);
|
|
3984
|
-
const cosPhi = Math.cos(phi);
|
|
3985
|
-
const ux = cosTheta * sinPhi;
|
|
3986
|
-
const uy = cosPhi;
|
|
3987
|
-
const uz = sinTheta * sinPhi;
|
|
3988
|
-
const r = radius(ux, uy, uz, u, v);
|
|
3989
|
-
positions[i3 + 0] = r * ux;
|
|
3990
|
-
positions[i3 + 1] = r * uy;
|
|
3991
|
-
positions[i3 + 2] = r * uz;
|
|
3992
|
-
normals[i3 + 0] = ux;
|
|
3993
|
-
normals[i3 + 1] = uy;
|
|
3994
|
-
normals[i3 + 2] = uz;
|
|
3995
|
-
texCoords[i2 + 0] = u;
|
|
3996
|
-
texCoords[i2 + 1] = 1 - v;
|
|
3997
|
-
}
|
|
3998
|
-
}
|
|
3999
|
-
const numVertsAround = nlong + 1;
|
|
4000
|
-
for (let x = 0; x < nlong; x++) {
|
|
4001
|
-
for (let y = 0; y < nlat; y++) {
|
|
4002
|
-
const index = (x * nlat + y) * 6;
|
|
4003
|
-
indices[index + 0] = y * numVertsAround + x;
|
|
4004
|
-
indices[index + 1] = y * numVertsAround + x + 1;
|
|
4005
|
-
indices[index + 2] = (y + 1) * numVertsAround + x;
|
|
4006
|
-
indices[index + 3] = (y + 1) * numVertsAround + x;
|
|
4007
|
-
indices[index + 4] = y * numVertsAround + x + 1;
|
|
4008
|
-
indices[index + 5] = (y + 1) * numVertsAround + x + 1;
|
|
4009
|
-
}
|
|
4010
|
-
}
|
|
4011
|
-
return {
|
|
4012
|
-
indices: { size: 1, value: indices },
|
|
4013
|
-
attributes: {
|
|
4014
|
-
POSITION: { size: 3, value: positions },
|
|
4015
|
-
NORMAL: { size: 3, value: normals },
|
|
4016
|
-
TEXCOORD_0: { size: 2, value: texCoords }
|
|
4017
|
-
}
|
|
4018
|
-
};
|
|
4019
|
-
}
|
|
4020
|
-
|
|
4021
5092
|
// dist/application-utils/random.js
|
|
4022
5093
|
function makeRandomGenerator() {
|
|
4023
5094
|
let s = 1;
|
|
@@ -4032,17 +5103,45 @@ function fract(n) {
|
|
|
4032
5103
|
return n - Math.floor(n);
|
|
4033
5104
|
}
|
|
4034
5105
|
|
|
5106
|
+
// dist/application-utils/load-file.js
|
|
5107
|
+
var pathPrefix = "";
|
|
5108
|
+
function setPathPrefix(prefix) {
|
|
5109
|
+
pathPrefix = prefix;
|
|
5110
|
+
}
|
|
5111
|
+
async function loadImageBitmap(url, opts) {
|
|
5112
|
+
const image = new Image();
|
|
5113
|
+
image.crossOrigin = (opts == null ? void 0 : opts.crossOrigin) || "anonymous";
|
|
5114
|
+
image.src = url.startsWith("http") ? url : pathPrefix + url;
|
|
5115
|
+
await image.decode();
|
|
5116
|
+
return opts ? await createImageBitmap(image, opts) : await createImageBitmap(image);
|
|
5117
|
+
}
|
|
5118
|
+
async function loadImage(url, opts) {
|
|
5119
|
+
return await new Promise((resolve, reject) => {
|
|
5120
|
+
try {
|
|
5121
|
+
const image = new Image();
|
|
5122
|
+
image.onload = () => resolve(image);
|
|
5123
|
+
image.onerror = () => reject(new Error(`Could not load image ${url}.`));
|
|
5124
|
+
image.crossOrigin = (opts == null ? void 0 : opts.crossOrigin) || "anonymous";
|
|
5125
|
+
image.src = url.startsWith("http") ? url : pathPrefix + url;
|
|
5126
|
+
} catch (error) {
|
|
5127
|
+
reject(error);
|
|
5128
|
+
}
|
|
5129
|
+
});
|
|
5130
|
+
}
|
|
5131
|
+
|
|
4035
5132
|
// dist/passes/shader-pass-renderer.js
|
|
4036
5133
|
var import_shadertools5 = require("@luma.gl/shadertools");
|
|
4037
5134
|
|
|
4038
5135
|
// dist/compute/swap.js
|
|
4039
|
-
var
|
|
5136
|
+
var import_core16 = require("@luma.gl/core");
|
|
4040
5137
|
var Swap = class {
|
|
5138
|
+
id;
|
|
4041
5139
|
/** The current resource - usually the source for renders or computations */
|
|
4042
5140
|
current;
|
|
4043
5141
|
/** The next resource - usually the target/destination for transforms / computations */
|
|
4044
5142
|
next;
|
|
4045
5143
|
constructor(props) {
|
|
5144
|
+
this.id = props.id || "swap";
|
|
4046
5145
|
this.current = props.current;
|
|
4047
5146
|
this.next = props.next;
|
|
4048
5147
|
}
|
|
@@ -4063,18 +5162,21 @@ var SwapFramebuffers = class extends Swap {
|
|
|
4063
5162
|
constructor(device, props) {
|
|
4064
5163
|
var _a, _b;
|
|
4065
5164
|
props = { ...props };
|
|
5165
|
+
const { width = 1, height = 1 } = props;
|
|
4066
5166
|
let colorAttachments = (_a = props.colorAttachments) == null ? void 0 : _a.map((colorAttachment) => typeof colorAttachment !== "string" ? colorAttachment : device.createTexture({
|
|
5167
|
+
id: `${props.id}-texture-0`,
|
|
4067
5168
|
format: colorAttachment,
|
|
4068
|
-
usage:
|
|
4069
|
-
width
|
|
4070
|
-
height
|
|
5169
|
+
usage: import_core16.Texture.SAMPLE | import_core16.Texture.RENDER | import_core16.Texture.COPY_SRC | import_core16.Texture.COPY_DST,
|
|
5170
|
+
width,
|
|
5171
|
+
height
|
|
4071
5172
|
}));
|
|
4072
5173
|
const current = device.createFramebuffer({ ...props, colorAttachments });
|
|
4073
5174
|
colorAttachments = (_b = props.colorAttachments) == null ? void 0 : _b.map((colorAttachment) => typeof colorAttachment !== "string" ? colorAttachment : device.createTexture({
|
|
5175
|
+
id: `${props.id}-texture-1`,
|
|
4074
5176
|
format: colorAttachment,
|
|
4075
|
-
usage:
|
|
4076
|
-
width
|
|
4077
|
-
height
|
|
5177
|
+
usage: import_core16.Texture.SAMPLE | import_core16.Texture.RENDER | import_core16.Texture.COPY_SRC | import_core16.Texture.COPY_DST,
|
|
5178
|
+
width,
|
|
5179
|
+
height
|
|
4078
5180
|
}));
|
|
4079
5181
|
const next = device.createFramebuffer({ ...props, colorAttachments });
|
|
4080
5182
|
super({ current, next });
|
|
@@ -4135,22 +5237,16 @@ function getFragmentShaderForRenderPass(options) {
|
|
|
4135
5237
|
function getFilterShaderWGSL(func) {
|
|
4136
5238
|
return (
|
|
4137
5239
|
/* wgsl */
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
@group(0) @binding(1) var texture: texture_2d<f32>;
|
|
4141
|
-
@group(0) @binding(2) var sampler: sampler;
|
|
4142
|
-
|
|
4143
|
-
struct FragmentInputs {
|
|
4144
|
-
@location(0) fragUV: vec2f,
|
|
4145
|
-
@location(1) fragPosition: vec4f,
|
|
4146
|
-
@location(2) fragCoordinate: vec4f
|
|
4147
|
-
};
|
|
5240
|
+
`@group(0) @binding(0) var sourceTexture: texture_2d<f32>;
|
|
5241
|
+
@group(0) @binding(2) var sourceTextureSampler: sampler;
|
|
4148
5242
|
|
|
4149
5243
|
@fragment
|
|
4150
5244
|
fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
|
|
4151
|
-
let
|
|
4152
|
-
|
|
4153
|
-
|
|
5245
|
+
let texCoord = inputs.coordinate;
|
|
5246
|
+
let texSize = vec2f(textureDimensions(sourceTexture));
|
|
5247
|
+
|
|
5248
|
+
var fragColor = textureSample(sourceTexture, sourceTextureSampler, texCoord);
|
|
5249
|
+
fragColor = ${func}(fragColor, texSize, texCoord);
|
|
4154
5250
|
return fragColor;
|
|
4155
5251
|
}
|
|
4156
5252
|
`
|
|
@@ -4159,23 +5255,14 @@ fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
|
|
|
4159
5255
|
function getSamplerShaderWGSL(func) {
|
|
4160
5256
|
return (
|
|
4161
5257
|
/* wgsl */
|
|
4162
|
-
|
|
4163
|
-
@group(0) @binding(
|
|
4164
|
-
@group(0) @binding(1) var texture: texture_2d<f32>;
|
|
4165
|
-
@group(0) @binding(2) var sampler: sampler;
|
|
4166
|
-
|
|
4167
|
-
struct FragmentInputs = {
|
|
4168
|
-
@location(0) fragUV: vec2f,
|
|
4169
|
-
@location(1) fragPosition: vec4f,
|
|
4170
|
-
@location(2) fragCoordinate: vec4f
|
|
4171
|
-
};
|
|
5258
|
+
`@group(0) @binding(0) var sourceTexture: texture_2d<f32>;
|
|
5259
|
+
@group(0) @binding(2) var sourceTextureSampler: sampler;
|
|
4172
5260
|
|
|
4173
5261
|
@fragment
|
|
4174
5262
|
fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
|
|
4175
|
-
let
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
return fragColor;
|
|
5263
|
+
let texCoord = inputs.coordinate;
|
|
5264
|
+
let texSize = vec2f(textureDimensions(sourceTexture));
|
|
5265
|
+
return ${func}(sourceTexture, sourceTextureSampler, texSize, texCoord);
|
|
4179
5266
|
}
|
|
4180
5267
|
`
|
|
4181
5268
|
);
|
|
@@ -4234,8 +5321,6 @@ var ShaderPassRenderer = class {
|
|
|
4234
5321
|
shaderInputs;
|
|
4235
5322
|
passRenderers;
|
|
4236
5323
|
swapFramebuffers;
|
|
4237
|
-
/** For rendering to the screen */
|
|
4238
|
-
clipSpace;
|
|
4239
5324
|
textureModel;
|
|
4240
5325
|
constructor(device, props) {
|
|
4241
5326
|
this.device = device;
|
|
@@ -4251,35 +5336,6 @@ var ShaderPassRenderer = class {
|
|
|
4251
5336
|
this.textureModel = new BackgroundTextureModel(device, {
|
|
4252
5337
|
backgroundTexture: this.swapFramebuffers.current.colorAttachments[0].texture
|
|
4253
5338
|
});
|
|
4254
|
-
this.clipSpace = new ClipSpace(device, {
|
|
4255
|
-
source: (
|
|
4256
|
-
/* wgsl */
|
|
4257
|
-
` @group(0) @binding(0) var sourceTexture: texture_2d<f32>;
|
|
4258
|
-
@group(0) @binding(1) var sourceTextureSampler: sampler;
|
|
4259
|
-
|
|
4260
|
-
@fragment
|
|
4261
|
-
fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4<f32> {
|
|
4262
|
-
let texCoord: vec2<f32> = inputs.coordinate;
|
|
4263
|
-
return textureSample(sourceTexture, sourceTextureSampler, texCoord);
|
|
4264
|
-
}
|
|
4265
|
-
`
|
|
4266
|
-
),
|
|
4267
|
-
fs: (
|
|
4268
|
-
/* glsl */
|
|
4269
|
-
`#version 300 es
|
|
4270
|
-
|
|
4271
|
-
uniform sampler2D sourceTexture;
|
|
4272
|
-
in vec2 uv;
|
|
4273
|
-
in vec2 coordinate;
|
|
4274
|
-
out vec4 fragColor;
|
|
4275
|
-
|
|
4276
|
-
void main() {
|
|
4277
|
-
vec2 texCoord = coordinate;
|
|
4278
|
-
fragColor = texture(sourceTexture, coordinate);
|
|
4279
|
-
}
|
|
4280
|
-
`
|
|
4281
|
-
)
|
|
4282
|
-
});
|
|
4283
5339
|
this.passRenderers = props.shaderPasses.map((shaderPass) => new PassRenderer(device, shaderPass));
|
|
4284
5340
|
}
|
|
4285
5341
|
/** Destroys resources created by this ShaderPassRenderer */
|
|
@@ -4288,25 +5344,26 @@ void main() {
|
|
|
4288
5344
|
subPassRenderer.destroy();
|
|
4289
5345
|
}
|
|
4290
5346
|
this.swapFramebuffers.destroy();
|
|
4291
|
-
this.
|
|
5347
|
+
this.textureModel.destroy();
|
|
4292
5348
|
}
|
|
4293
|
-
resize(
|
|
4294
|
-
this.
|
|
5349
|
+
resize(size) {
|
|
5350
|
+
size ||= this.device.getCanvasContext().getDrawingBufferSize();
|
|
5351
|
+
this.swapFramebuffers.resize({ width: size[0], height: size[1] });
|
|
4295
5352
|
}
|
|
4296
5353
|
renderToScreen(options) {
|
|
4297
5354
|
const outputTexture = this.renderToTexture(options);
|
|
4298
5355
|
if (!outputTexture) {
|
|
4299
5356
|
return false;
|
|
4300
5357
|
}
|
|
4301
|
-
const framebuffer = this.device.getDefaultCanvasContext().getCurrentFramebuffer({
|
|
5358
|
+
const framebuffer = this.device.getDefaultCanvasContext().getCurrentFramebuffer({ depthStencilFormat: false });
|
|
4302
5359
|
const renderPass = this.device.beginRenderPass({
|
|
4303
5360
|
id: "shader-pass-renderer-to-screen",
|
|
4304
5361
|
framebuffer,
|
|
4305
|
-
clearColor: [
|
|
4306
|
-
clearDepth:
|
|
5362
|
+
// clearColor: [1, 1, 0, 1],
|
|
5363
|
+
clearDepth: false
|
|
4307
5364
|
});
|
|
4308
|
-
this.
|
|
4309
|
-
this.
|
|
5365
|
+
this.textureModel.setProps({ backgroundTexture: outputTexture });
|
|
5366
|
+
this.textureModel.draw(renderPass);
|
|
4310
5367
|
renderPass.end();
|
|
4311
5368
|
return true;
|
|
4312
5369
|
}
|
|
@@ -4318,14 +5375,14 @@ void main() {
|
|
|
4318
5375
|
if (!sourceTexture.isReady) {
|
|
4319
5376
|
return null;
|
|
4320
5377
|
}
|
|
4321
|
-
this.
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
});
|
|
5378
|
+
if (this.passRenderers.length === 0) {
|
|
5379
|
+
return sourceTexture.texture;
|
|
5380
|
+
}
|
|
5381
|
+
this.textureModel.setProps({ backgroundTexture: sourceTexture });
|
|
4325
5382
|
const clearTexturePass = this.device.beginRenderPass({
|
|
4326
5383
|
id: "shader-pass-renderer-clear-texture",
|
|
4327
5384
|
framebuffer: this.swapFramebuffers.current,
|
|
4328
|
-
clearColor: [
|
|
5385
|
+
clearColor: [1, 0, 0, 1]
|
|
4329
5386
|
});
|
|
4330
5387
|
this.textureModel.draw(clearTexturePass);
|
|
4331
5388
|
clearTexturePass.end();
|
|
@@ -4412,7 +5469,7 @@ var SubPassRenderer = class {
|
|
|
4412
5469
|
};
|
|
4413
5470
|
|
|
4414
5471
|
// dist/compute/computation.js
|
|
4415
|
-
var
|
|
5472
|
+
var import_core17 = require("@luma.gl/core");
|
|
4416
5473
|
var import_shadertools6 = require("@luma.gl/shadertools");
|
|
4417
5474
|
var import_types2 = require("@math.gl/types");
|
|
4418
5475
|
var LOG_DRAW_PRIORITY2 = 2;
|
|
@@ -4441,7 +5498,7 @@ var _Computation = class {
|
|
|
4441
5498
|
props;
|
|
4442
5499
|
_destroyed = false;
|
|
4443
5500
|
constructor(device, props) {
|
|
4444
|
-
var _a, _b, _c;
|
|
5501
|
+
var _a, _b, _c, _d;
|
|
4445
5502
|
if (device.type !== "webgpu") {
|
|
4446
5503
|
throw new Error("Computation is only supported in WebGPU");
|
|
4447
5504
|
}
|
|
@@ -4453,11 +5510,11 @@ var _Computation = class {
|
|
|
4453
5510
|
const moduleMap = Object.fromEntries(((_a = this.props.modules) == null ? void 0 : _a.map((module2) => [module2.name, module2])) || []);
|
|
4454
5511
|
this.shaderInputs = props.shaderInputs || new ShaderInputs(moduleMap);
|
|
4455
5512
|
this.setShaderInputs(this.shaderInputs);
|
|
4456
|
-
this.props.shaderLayout ||= (0, import_shadertools6.getShaderLayoutFromWGSL)(this.props.source);
|
|
4457
5513
|
const platformInfo = getPlatformInfo2(device);
|
|
4458
5514
|
const modules = (((_b = this.props.modules) == null ? void 0 : _b.length) > 0 ? this.props.modules : (_c = this.shaderInputs) == null ? void 0 : _c.getModules()) || [];
|
|
4459
|
-
this.
|
|
4460
|
-
this.
|
|
5515
|
+
this.props.shaderLayout = mergeShaderModuleBindingsIntoLayout(this.props.shaderLayout, modules) || null;
|
|
5516
|
+
this.pipelineFactory = props.pipelineFactory || import_core17.PipelineFactory.getDefaultPipelineFactory(this.device);
|
|
5517
|
+
this.shaderFactory = props.shaderFactory || import_core17.ShaderFactory.getDefaultShaderFactory(this.device);
|
|
4461
5518
|
const { source: source3, getUniforms: getUniforms2 } = this.props.shaderAssembler.assembleWGSLShader({
|
|
4462
5519
|
platformInfo,
|
|
4463
5520
|
...this.props,
|
|
@@ -4465,6 +5522,8 @@ var _Computation = class {
|
|
|
4465
5522
|
});
|
|
4466
5523
|
this.source = source3;
|
|
4467
5524
|
this._getModuleUniforms = getUniforms2;
|
|
5525
|
+
const inferredShaderLayout = (_d = device.getShaderLayout) == null ? void 0 : _d.call(device, this.source);
|
|
5526
|
+
this.props.shaderLayout = mergeShaderModuleBindingsIntoLayout(this.props.shaderLayout || inferredShaderLayout || null, modules) || null;
|
|
4468
5527
|
this.pipeline = this._updatePipeline();
|
|
4469
5528
|
if (props.bindings) {
|
|
4470
5529
|
this.setBindings(props.bindings);
|
|
@@ -4489,7 +5548,7 @@ var _Computation = class {
|
|
|
4489
5548
|
this.pipeline = this._updatePipeline();
|
|
4490
5549
|
this.pipeline.setBindings(this.bindings);
|
|
4491
5550
|
computePass.setPipeline(this.pipeline);
|
|
4492
|
-
computePass.setBindings(
|
|
5551
|
+
computePass.setBindings({});
|
|
4493
5552
|
computePass.dispatch(x, y, z);
|
|
4494
5553
|
} finally {
|
|
4495
5554
|
this._logDrawCallEnd();
|
|
@@ -4511,10 +5570,12 @@ var _Computation = class {
|
|
|
4511
5570
|
}
|
|
4512
5571
|
setShaderInputs(shaderInputs) {
|
|
4513
5572
|
this.shaderInputs = shaderInputs;
|
|
4514
|
-
this._uniformStore = new
|
|
4515
|
-
for (const moduleName of Object.
|
|
4516
|
-
|
|
4517
|
-
|
|
5573
|
+
this._uniformStore = new import_core17.UniformStore(this.device, this.shaderInputs.modules);
|
|
5574
|
+
for (const [moduleName, module2] of Object.entries(this.shaderInputs.modules)) {
|
|
5575
|
+
if (shaderModuleHasUniforms(module2)) {
|
|
5576
|
+
const uniformBuffer = this._uniformStore.getManagedUniformBuffer(moduleName);
|
|
5577
|
+
this.bindings[`${moduleName}Uniforms`] = uniformBuffer;
|
|
5578
|
+
}
|
|
4518
5579
|
}
|
|
4519
5580
|
}
|
|
4520
5581
|
/**
|
|
@@ -4548,7 +5609,7 @@ var _Computation = class {
|
|
|
4548
5609
|
if (this._pipelineNeedsUpdate) {
|
|
4549
5610
|
let prevShader = null;
|
|
4550
5611
|
if (this.pipeline) {
|
|
4551
|
-
|
|
5612
|
+
import_core17.log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
|
|
4552
5613
|
prevShader = this.shader;
|
|
4553
5614
|
}
|
|
4554
5615
|
this._pipelineNeedsUpdate = false;
|
|
@@ -4572,33 +5633,33 @@ var _Computation = class {
|
|
|
4572
5633
|
_lastLogTime = 0;
|
|
4573
5634
|
_logOpen = false;
|
|
4574
5635
|
_logDrawCallStart() {
|
|
4575
|
-
const logDrawTimeout =
|
|
4576
|
-
if (
|
|
5636
|
+
const logDrawTimeout = import_core17.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT2;
|
|
5637
|
+
if (import_core17.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
|
|
4577
5638
|
return;
|
|
4578
5639
|
}
|
|
4579
5640
|
this._lastLogTime = Date.now();
|
|
4580
5641
|
this._logOpen = true;
|
|
4581
|
-
|
|
5642
|
+
import_core17.log.group(LOG_DRAW_PRIORITY2, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core17.log.level <= 2 })();
|
|
4582
5643
|
}
|
|
4583
5644
|
_logDrawCallEnd() {
|
|
4584
5645
|
if (this._logOpen) {
|
|
4585
5646
|
const uniformTable = this.shaderInputs.getDebugTable();
|
|
4586
|
-
|
|
4587
|
-
|
|
5647
|
+
import_core17.log.table(LOG_DRAW_PRIORITY2, uniformTable)();
|
|
5648
|
+
import_core17.log.groupEnd(LOG_DRAW_PRIORITY2)();
|
|
4588
5649
|
this._logOpen = false;
|
|
4589
5650
|
}
|
|
4590
5651
|
}
|
|
4591
5652
|
_drawCount = 0;
|
|
4592
5653
|
// TODO - fix typing of luma data types
|
|
4593
5654
|
_getBufferOrConstantValues(attribute, dataType) {
|
|
4594
|
-
const TypedArrayConstructor =
|
|
4595
|
-
const typedArray = attribute instanceof
|
|
5655
|
+
const TypedArrayConstructor = import_core17.dataTypeDecoder.getTypedArrayConstructor(dataType);
|
|
5656
|
+
const typedArray = attribute instanceof import_core17.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
|
|
4596
5657
|
return typedArray.toString();
|
|
4597
5658
|
}
|
|
4598
5659
|
};
|
|
4599
5660
|
var Computation = _Computation;
|
|
4600
5661
|
__publicField(Computation, "defaultProps", {
|
|
4601
|
-
...
|
|
5662
|
+
...import_core17.ComputePipeline.defaultProps,
|
|
4602
5663
|
id: "unnamed",
|
|
4603
5664
|
handle: void 0,
|
|
4604
5665
|
userData: {},
|
|
@@ -4623,6 +5684,9 @@ function getPlatformInfo2(device) {
|
|
|
4623
5684
|
};
|
|
4624
5685
|
}
|
|
4625
5686
|
|
|
5687
|
+
// dist/modules/picking/picking-manager.js
|
|
5688
|
+
var import_core18 = require("@luma.gl/core");
|
|
5689
|
+
|
|
4626
5690
|
// dist/modules/picking/picking-uniforms.js
|
|
4627
5691
|
var DEFAULT_HIGHLIGHT_COLOR = [0, 1, 1, 1];
|
|
4628
5692
|
var INVALID_INDEX = -1;
|
|
@@ -4640,7 +5704,7 @@ var GLSL_UNIFORMS = (
|
|
|
4640
5704
|
`precision highp float;
|
|
4641
5705
|
precision highp int;
|
|
4642
5706
|
|
|
4643
|
-
uniform pickingUniforms {
|
|
5707
|
+
layout(std140) uniform pickingUniforms {
|
|
4644
5708
|
int isActive;
|
|
4645
5709
|
int indexMode;
|
|
4646
5710
|
int batchIndex;
|
|
@@ -4655,15 +5719,17 @@ uniform pickingUniforms {
|
|
|
4655
5719
|
var WGSL_UNIFORMS = (
|
|
4656
5720
|
/* wgsl */
|
|
4657
5721
|
`struct pickingUniforms {
|
|
4658
|
-
isActive:
|
|
4659
|
-
indexMode:
|
|
4660
|
-
batchIndex:
|
|
4661
|
-
|
|
4662
|
-
isHighlightActive:
|
|
4663
|
-
highlightedBatchIndex:
|
|
4664
|
-
highlightedObjectIndex:
|
|
4665
|
-
highlightColor: vec4<f32
|
|
4666
|
-
}
|
|
5722
|
+
isActive: i32,
|
|
5723
|
+
indexMode: i32,
|
|
5724
|
+
batchIndex: i32,
|
|
5725
|
+
|
|
5726
|
+
isHighlightActive: i32,
|
|
5727
|
+
highlightedBatchIndex: i32,
|
|
5728
|
+
highlightedObjectIndex: i32,
|
|
5729
|
+
highlightColor: vec4<f32>,
|
|
5730
|
+
};
|
|
5731
|
+
|
|
5732
|
+
@group(0) @binding(auto) var<uniform> picking: pickingUniforms;
|
|
4667
5733
|
`
|
|
4668
5734
|
);
|
|
4669
5735
|
function getUniforms(props = {}, prevUniforms) {
|
|
@@ -4675,25 +5741,36 @@ function getUniforms(props = {}, prevUniforms) {
|
|
|
4675
5741
|
case "instance":
|
|
4676
5742
|
uniforms.indexMode = 0;
|
|
4677
5743
|
break;
|
|
4678
|
-
case "
|
|
5744
|
+
case "attribute":
|
|
4679
5745
|
uniforms.indexMode = 1;
|
|
4680
5746
|
break;
|
|
4681
5747
|
case void 0:
|
|
4682
5748
|
break;
|
|
4683
5749
|
}
|
|
5750
|
+
if (typeof props.batchIndex === "number") {
|
|
5751
|
+
uniforms.batchIndex = props.batchIndex;
|
|
5752
|
+
}
|
|
4684
5753
|
switch (props.highlightedObjectIndex) {
|
|
4685
5754
|
case void 0:
|
|
4686
5755
|
break;
|
|
4687
5756
|
case null:
|
|
4688
5757
|
uniforms.isHighlightActive = false;
|
|
4689
|
-
uniforms.highlightedObjectIndex = INVALID_INDEX;
|
|
5758
|
+
uniforms.highlightedObjectIndex = INVALID_INDEX;
|
|
5759
|
+
break;
|
|
5760
|
+
default:
|
|
5761
|
+
uniforms.isHighlightActive = true;
|
|
5762
|
+
uniforms.highlightedObjectIndex = props.highlightedObjectIndex;
|
|
5763
|
+
}
|
|
5764
|
+
switch (props.highlightedBatchIndex) {
|
|
5765
|
+
case void 0:
|
|
5766
|
+
break;
|
|
5767
|
+
case null:
|
|
5768
|
+
uniforms.isHighlightActive = false;
|
|
5769
|
+
uniforms.highlightedBatchIndex = INVALID_INDEX;
|
|
4690
5770
|
break;
|
|
4691
5771
|
default:
|
|
4692
5772
|
uniforms.isHighlightActive = true;
|
|
4693
|
-
uniforms.
|
|
4694
|
-
}
|
|
4695
|
-
if (typeof props.highlightedBatchIndex === "number") {
|
|
4696
|
-
uniforms.highlightedBatchIndex = props.highlightedBatchIndex;
|
|
5773
|
+
uniforms.highlightedBatchIndex = props.highlightedBatchIndex;
|
|
4697
5774
|
}
|
|
4698
5775
|
if (props.highlightColor) {
|
|
4699
5776
|
uniforms.highlightColor = props.highlightColor;
|
|
@@ -4709,7 +5786,7 @@ var pickingUniforms = {
|
|
|
4709
5786
|
isActive: false,
|
|
4710
5787
|
indexMode: 0,
|
|
4711
5788
|
batchIndex: 0,
|
|
4712
|
-
isHighlightActive:
|
|
5789
|
+
isHighlightActive: false,
|
|
4713
5790
|
highlightedBatchIndex: INVALID_INDEX,
|
|
4714
5791
|
highlightedObjectIndex: INVALID_INDEX,
|
|
4715
5792
|
highlightColor: DEFAULT_HIGHLIGHT_COLOR
|
|
@@ -4718,9 +5795,42 @@ var pickingUniforms = {
|
|
|
4718
5795
|
};
|
|
4719
5796
|
|
|
4720
5797
|
// dist/modules/picking/picking-manager.js
|
|
5798
|
+
var INDEX_PICKING_ATTACHMENT_INDEX = 1;
|
|
5799
|
+
var INDEX_PICKING_CLEAR_COLOR = new Int32Array([INVALID_INDEX, INVALID_INDEX, 0, 0]);
|
|
5800
|
+
function resolvePickingMode(deviceType, mode = "color", indexPickingSupported = deviceType === "webgpu") {
|
|
5801
|
+
if (mode === "auto") {
|
|
5802
|
+
return indexPickingSupported ? "index" : "color";
|
|
5803
|
+
}
|
|
5804
|
+
if (mode === "index" && !indexPickingSupported) {
|
|
5805
|
+
throw new Error(`Picking mode "${mode}" requires WebGPU or a WebGL device that supports renderable rg32sint textures.`);
|
|
5806
|
+
}
|
|
5807
|
+
return mode;
|
|
5808
|
+
}
|
|
5809
|
+
function supportsIndexPicking(device) {
|
|
5810
|
+
return device.type === "webgpu" || device.type === "webgl" && device.isTextureFormatRenderable("rg32sint");
|
|
5811
|
+
}
|
|
5812
|
+
var resolvePickingBackend = resolvePickingMode;
|
|
5813
|
+
function decodeIndexPickInfo(pixelData) {
|
|
5814
|
+
return {
|
|
5815
|
+
objectIndex: pixelData[0] === INVALID_INDEX ? null : pixelData[0],
|
|
5816
|
+
batchIndex: pixelData[1] === INVALID_INDEX ? null : pixelData[1]
|
|
5817
|
+
};
|
|
5818
|
+
}
|
|
5819
|
+
function decodeColorPickInfo(pixelData) {
|
|
5820
|
+
const encodedObjectIndex = pixelData[0] + pixelData[1] * 256 + pixelData[2] * 65536;
|
|
5821
|
+
if (encodedObjectIndex === 0) {
|
|
5822
|
+
return { objectIndex: null, batchIndex: null };
|
|
5823
|
+
}
|
|
5824
|
+
const batchIndex = pixelData[3] > 0 ? pixelData[3] - 1 : 0;
|
|
5825
|
+
return {
|
|
5826
|
+
objectIndex: encodedObjectIndex - 1,
|
|
5827
|
+
batchIndex
|
|
5828
|
+
};
|
|
5829
|
+
}
|
|
4721
5830
|
var _PickingManager = class {
|
|
4722
5831
|
device;
|
|
4723
5832
|
props;
|
|
5833
|
+
mode;
|
|
4724
5834
|
/** Info from latest pick operation */
|
|
4725
5835
|
pickInfo = { batchIndex: null, objectIndex: null };
|
|
4726
5836
|
/** Framebuffer used for picking */
|
|
@@ -4728,6 +5838,10 @@ var _PickingManager = class {
|
|
|
4728
5838
|
constructor(device, props) {
|
|
4729
5839
|
this.device = device;
|
|
4730
5840
|
this.props = { ..._PickingManager.defaultProps, ...props };
|
|
5841
|
+
const requestedMode = props.mode ?? props.backend ?? _PickingManager.defaultProps.mode;
|
|
5842
|
+
this.props.mode = requestedMode;
|
|
5843
|
+
this.props.backend = requestedMode;
|
|
5844
|
+
this.mode = resolvePickingMode(this.device.type, requestedMode, supportsIndexPicking(this.device));
|
|
4731
5845
|
}
|
|
4732
5846
|
destroy() {
|
|
4733
5847
|
var _a;
|
|
@@ -4736,58 +5850,44 @@ var _PickingManager = class {
|
|
|
4736
5850
|
// TODO - Ask for a cached framebuffer? a Framebuffer factory?
|
|
4737
5851
|
getFramebuffer() {
|
|
4738
5852
|
if (!this.framebuffer) {
|
|
4739
|
-
this.framebuffer = this.
|
|
4740
|
-
colorAttachments: ["rgba8unorm", "rg32sint"],
|
|
4741
|
-
depthStencilAttachment: "depth24plus"
|
|
4742
|
-
});
|
|
5853
|
+
this.framebuffer = this.mode === "index" ? this.createIndexFramebuffer() : this.createColorFramebuffer();
|
|
4743
5854
|
}
|
|
4744
5855
|
return this.framebuffer;
|
|
4745
5856
|
}
|
|
4746
5857
|
/** Clear highlighted / picked object */
|
|
4747
5858
|
clearPickState() {
|
|
4748
|
-
this.
|
|
5859
|
+
this.setPickingProps({ highlightedBatchIndex: null, highlightedObjectIndex: null });
|
|
4749
5860
|
}
|
|
4750
5861
|
/** Prepare for rendering picking colors */
|
|
4751
5862
|
beginRenderPass() {
|
|
4752
|
-
var _a;
|
|
4753
5863
|
const framebuffer = this.getFramebuffer();
|
|
4754
5864
|
framebuffer.resize(this.device.getDefaultCanvasContext().getDevicePixelSize());
|
|
4755
|
-
|
|
4756
|
-
|
|
5865
|
+
this.setPickingProps({ isActive: true });
|
|
5866
|
+
return this.mode === "index" ? this.device.beginRenderPass({
|
|
5867
|
+
framebuffer,
|
|
5868
|
+
clearColors: [new Float32Array([0, 0, 0, 0]), INDEX_PICKING_CLEAR_COLOR],
|
|
5869
|
+
clearDepth: 1
|
|
5870
|
+
}) : this.device.beginRenderPass({
|
|
4757
5871
|
framebuffer,
|
|
4758
|
-
|
|
5872
|
+
clearColor: [0, 0, 0, 0],
|
|
4759
5873
|
clearDepth: 1
|
|
4760
5874
|
});
|
|
4761
|
-
return pickingPass;
|
|
4762
5875
|
}
|
|
4763
5876
|
async updatePickInfo(mousePosition) {
|
|
4764
|
-
var _a;
|
|
4765
5877
|
const framebuffer = this.getFramebuffer();
|
|
4766
|
-
const
|
|
4767
|
-
const
|
|
4768
|
-
|
|
4769
|
-
sourceY: pickY,
|
|
4770
|
-
sourceWidth: 1,
|
|
4771
|
-
sourceHeight: 1,
|
|
4772
|
-
sourceAttachment: 1
|
|
4773
|
-
});
|
|
4774
|
-
if (!pixelData) {
|
|
5878
|
+
const pickPosition = this.getPickPosition(mousePosition);
|
|
5879
|
+
const pickInfo = await this.readPickInfo(framebuffer, pickPosition);
|
|
5880
|
+
if (!pickInfo) {
|
|
4775
5881
|
return null;
|
|
4776
5882
|
}
|
|
4777
|
-
|
|
4778
|
-
objectIndex: pixelData[0] === INVALID_INDEX ? null : pixelData[0],
|
|
4779
|
-
batchIndex: pixelData[1] === INVALID_INDEX ? null : pixelData[1]
|
|
4780
|
-
};
|
|
4781
|
-
if (pickInfo.objectIndex !== this.pickInfo.objectIndex || pickInfo.batchIndex !== this.pickInfo.batchIndex) {
|
|
5883
|
+
if (this.hasPickInfoChanged(pickInfo)) {
|
|
4782
5884
|
this.pickInfo = pickInfo;
|
|
4783
5885
|
this.props.onObjectPicked(pickInfo);
|
|
4784
5886
|
}
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
highlightedObjectIndex: pickInfo.objectIndex
|
|
4790
|
-
}
|
|
5887
|
+
this.setPickingProps({
|
|
5888
|
+
isActive: false,
|
|
5889
|
+
highlightedBatchIndex: pickInfo.batchIndex,
|
|
5890
|
+
highlightedObjectIndex: pickInfo.objectIndex
|
|
4791
5891
|
});
|
|
4792
5892
|
return this.pickInfo;
|
|
4793
5893
|
}
|
|
@@ -4796,49 +5896,204 @@ var _PickingManager = class {
|
|
|
4796
5896
|
* use the center pixel location in device pixel range
|
|
4797
5897
|
*/
|
|
4798
5898
|
getPickPosition(mousePosition) {
|
|
4799
|
-
const
|
|
5899
|
+
const yInvert = this.device.type !== "webgpu";
|
|
5900
|
+
const devicePixels = this.device.getDefaultCanvasContext().cssToDevicePixels(mousePosition, yInvert);
|
|
4800
5901
|
const pickX = devicePixels.x + Math.floor(devicePixels.width / 2);
|
|
4801
5902
|
const pickY = devicePixels.y + Math.floor(devicePixels.height / 2);
|
|
4802
5903
|
return [pickX, pickY];
|
|
4803
5904
|
}
|
|
5905
|
+
createIndexFramebuffer() {
|
|
5906
|
+
const colorTexture = this.device.createTexture({
|
|
5907
|
+
format: "rgba8unorm",
|
|
5908
|
+
width: 1,
|
|
5909
|
+
height: 1,
|
|
5910
|
+
usage: import_core18.Texture.RENDER_ATTACHMENT
|
|
5911
|
+
});
|
|
5912
|
+
const pickingTexture = this.device.createTexture({
|
|
5913
|
+
format: "rg32sint",
|
|
5914
|
+
width: 1,
|
|
5915
|
+
height: 1,
|
|
5916
|
+
usage: import_core18.Texture.RENDER_ATTACHMENT | import_core18.Texture.COPY_SRC
|
|
5917
|
+
});
|
|
5918
|
+
return this.device.createFramebuffer({
|
|
5919
|
+
colorAttachments: [colorTexture, pickingTexture],
|
|
5920
|
+
depthStencilAttachment: "depth24plus"
|
|
5921
|
+
});
|
|
5922
|
+
}
|
|
5923
|
+
createColorFramebuffer() {
|
|
5924
|
+
const pickingTexture = this.device.createTexture({
|
|
5925
|
+
format: "rgba8unorm",
|
|
5926
|
+
width: 1,
|
|
5927
|
+
height: 1,
|
|
5928
|
+
usage: import_core18.Texture.RENDER_ATTACHMENT | import_core18.Texture.COPY_SRC
|
|
5929
|
+
});
|
|
5930
|
+
return this.device.createFramebuffer({
|
|
5931
|
+
colorAttachments: [pickingTexture],
|
|
5932
|
+
depthStencilAttachment: "depth24plus"
|
|
5933
|
+
});
|
|
5934
|
+
}
|
|
5935
|
+
setPickingProps(props) {
|
|
5936
|
+
var _a;
|
|
5937
|
+
(_a = this.props.shaderInputs) == null ? void 0 : _a.setProps({ picking: props });
|
|
5938
|
+
}
|
|
5939
|
+
async readPickInfo(framebuffer, pickPosition) {
|
|
5940
|
+
return this.mode === "index" ? this.readIndexPickInfo(framebuffer, pickPosition) : this.readColorPickInfo(framebuffer, pickPosition);
|
|
5941
|
+
}
|
|
5942
|
+
async readIndexPickInfo(framebuffer, [pickX, pickY]) {
|
|
5943
|
+
var _a;
|
|
5944
|
+
if (this.device.type === "webgpu") {
|
|
5945
|
+
const pickTexture = (_a = framebuffer.colorAttachments[INDEX_PICKING_ATTACHMENT_INDEX]) == null ? void 0 : _a.texture;
|
|
5946
|
+
if (!pickTexture) {
|
|
5947
|
+
return null;
|
|
5948
|
+
}
|
|
5949
|
+
const layout = pickTexture.computeMemoryLayout({ width: 1, height: 1 });
|
|
5950
|
+
const readBuffer = this.device.createBuffer({
|
|
5951
|
+
byteLength: layout.byteLength,
|
|
5952
|
+
usage: import_core18.Buffer.COPY_DST | import_core18.Buffer.MAP_READ
|
|
5953
|
+
});
|
|
5954
|
+
try {
|
|
5955
|
+
pickTexture.readBuffer({
|
|
5956
|
+
x: pickX,
|
|
5957
|
+
y: pickY,
|
|
5958
|
+
width: 1,
|
|
5959
|
+
height: 1
|
|
5960
|
+
}, readBuffer);
|
|
5961
|
+
const pickDataView = await readBuffer.readAsync(0, layout.byteLength);
|
|
5962
|
+
return decodeIndexPickInfo(new Int32Array(pickDataView.buffer, pickDataView.byteOffset, 2));
|
|
5963
|
+
} finally {
|
|
5964
|
+
readBuffer.destroy();
|
|
5965
|
+
}
|
|
5966
|
+
}
|
|
5967
|
+
const pixelData = this.device.readPixelsToArrayWebGL(framebuffer, {
|
|
5968
|
+
sourceX: pickX,
|
|
5969
|
+
sourceY: pickY,
|
|
5970
|
+
sourceWidth: 1,
|
|
5971
|
+
sourceHeight: 1,
|
|
5972
|
+
sourceAttachment: INDEX_PICKING_ATTACHMENT_INDEX
|
|
5973
|
+
});
|
|
5974
|
+
return pixelData ? decodeIndexPickInfo(new Int32Array(pixelData.buffer, pixelData.byteOffset, 2)) : null;
|
|
5975
|
+
}
|
|
5976
|
+
async readColorPickInfo(framebuffer, [pickX, pickY]) {
|
|
5977
|
+
var _a;
|
|
5978
|
+
if (this.device.type === "webgpu") {
|
|
5979
|
+
const pickTexture = (_a = framebuffer.colorAttachments[0]) == null ? void 0 : _a.texture;
|
|
5980
|
+
if (!pickTexture) {
|
|
5981
|
+
return null;
|
|
5982
|
+
}
|
|
5983
|
+
const layout = pickTexture.computeMemoryLayout({ width: 1, height: 1 });
|
|
5984
|
+
const readBuffer = this.device.createBuffer({
|
|
5985
|
+
byteLength: layout.byteLength,
|
|
5986
|
+
usage: import_core18.Buffer.COPY_DST | import_core18.Buffer.MAP_READ
|
|
5987
|
+
});
|
|
5988
|
+
try {
|
|
5989
|
+
pickTexture.readBuffer({
|
|
5990
|
+
x: pickX,
|
|
5991
|
+
y: pickY,
|
|
5992
|
+
width: 1,
|
|
5993
|
+
height: 1
|
|
5994
|
+
}, readBuffer);
|
|
5995
|
+
const pickDataView = await readBuffer.readAsync(0, layout.byteLength);
|
|
5996
|
+
return decodeColorPickInfo(new Uint8Array(pickDataView.buffer, pickDataView.byteOffset, 4));
|
|
5997
|
+
} finally {
|
|
5998
|
+
readBuffer.destroy();
|
|
5999
|
+
}
|
|
6000
|
+
}
|
|
6001
|
+
const pixelData = this.device.readPixelsToArrayWebGL(framebuffer, {
|
|
6002
|
+
sourceX: pickX,
|
|
6003
|
+
sourceY: pickY,
|
|
6004
|
+
sourceWidth: 1,
|
|
6005
|
+
sourceHeight: 1,
|
|
6006
|
+
sourceAttachment: 0
|
|
6007
|
+
});
|
|
6008
|
+
return pixelData ? decodeColorPickInfo(new Uint8Array(pixelData.buffer, pixelData.byteOffset, 4)) : null;
|
|
6009
|
+
}
|
|
6010
|
+
hasPickInfoChanged(pickInfo) {
|
|
6011
|
+
return pickInfo.objectIndex !== this.pickInfo.objectIndex || pickInfo.batchIndex !== this.pickInfo.batchIndex;
|
|
6012
|
+
}
|
|
4804
6013
|
};
|
|
4805
6014
|
var PickingManager = _PickingManager;
|
|
4806
6015
|
__publicField(PickingManager, "defaultProps", {
|
|
4807
6016
|
shaderInputs: void 0,
|
|
4808
6017
|
onObjectPicked: () => {
|
|
4809
|
-
}
|
|
6018
|
+
},
|
|
6019
|
+
mode: "color",
|
|
6020
|
+
backend: "color"
|
|
4810
6021
|
});
|
|
4811
6022
|
|
|
4812
|
-
// dist/modules/picking/
|
|
6023
|
+
// dist/modules/picking/color-picking.js
|
|
4813
6024
|
var source = (
|
|
4814
6025
|
/* wgsl */
|
|
4815
6026
|
`${WGSL_UNIFORMS}
|
|
4816
6027
|
|
|
4817
|
-
const
|
|
4818
|
-
const
|
|
4819
|
-
const
|
|
6028
|
+
const COLOR_PICKING_INVALID_INDEX = ${INVALID_INDEX};
|
|
6029
|
+
const COLOR_PICKING_MAX_OBJECT_INDEX = 16777214;
|
|
6030
|
+
const COLOR_PICKING_MAX_BATCH_INDEX = 254;
|
|
4820
6031
|
|
|
4821
|
-
|
|
4822
|
-
objectIndex
|
|
4823
|
-
}
|
|
6032
|
+
fn picking_setObjectIndex(objectIndex: i32) -> i32 {
|
|
6033
|
+
return objectIndex;
|
|
6034
|
+
}
|
|
4824
6035
|
|
|
4825
|
-
|
|
6036
|
+
fn picking_isObjectHighlighted(objectIndex: i32) -> bool {
|
|
6037
|
+
return
|
|
6038
|
+
picking.isHighlightActive != 0 &&
|
|
6039
|
+
picking.highlightedBatchIndex == picking.batchIndex &&
|
|
6040
|
+
picking.highlightedObjectIndex == objectIndex;
|
|
6041
|
+
}
|
|
4826
6042
|
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
|
|
4835
|
-
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
6043
|
+
fn picking_filterHighlightColor(color: vec4<f32>, objectIndex: i32) -> vec4<f32> {
|
|
6044
|
+
if (picking.isActive != 0 || !picking_isObjectHighlighted(objectIndex)) {
|
|
6045
|
+
return color;
|
|
6046
|
+
}
|
|
6047
|
+
|
|
6048
|
+
let highLightAlpha = picking.highlightColor.a;
|
|
6049
|
+
let blendedAlpha = highLightAlpha + color.a * (1.0 - highLightAlpha);
|
|
6050
|
+
if (blendedAlpha == 0.0) {
|
|
6051
|
+
return vec4<f32>(color.rgb, 0.0);
|
|
6052
|
+
}
|
|
6053
|
+
|
|
6054
|
+
let highLightRatio = highLightAlpha / blendedAlpha;
|
|
6055
|
+
let blendedRGB = mix(color.rgb, picking.highlightColor.rgb, highLightRatio);
|
|
6056
|
+
return vec4<f32>(blendedRGB, blendedAlpha);
|
|
6057
|
+
}
|
|
6058
|
+
|
|
6059
|
+
fn picking_canEncodePickInfo(objectIndex: i32) -> bool {
|
|
6060
|
+
return
|
|
6061
|
+
objectIndex != COLOR_PICKING_INVALID_INDEX &&
|
|
6062
|
+
objectIndex >= 0 &&
|
|
6063
|
+
objectIndex <= COLOR_PICKING_MAX_OBJECT_INDEX &&
|
|
6064
|
+
picking.batchIndex >= 0 &&
|
|
6065
|
+
picking.batchIndex <= COLOR_PICKING_MAX_BATCH_INDEX;
|
|
6066
|
+
}
|
|
6067
|
+
|
|
6068
|
+
fn picking_getPickingColor(objectIndex: i32) -> vec4<f32> {
|
|
6069
|
+
if (!picking_canEncodePickInfo(objectIndex)) {
|
|
6070
|
+
return vec4<f32>(0.0, 0.0, 0.0, 0.0);
|
|
4839
6071
|
}
|
|
6072
|
+
|
|
6073
|
+
let encodedObjectIndex = objectIndex + 1;
|
|
6074
|
+
let red = encodedObjectIndex % 256;
|
|
6075
|
+
let green = (encodedObjectIndex / 256) % 256;
|
|
6076
|
+
let blue = (encodedObjectIndex / 65536) % 256;
|
|
6077
|
+
let alpha = picking.batchIndex + 1;
|
|
6078
|
+
|
|
6079
|
+
return vec4<f32>(
|
|
6080
|
+
f32(red) / 255.0,
|
|
6081
|
+
f32(green) / 255.0,
|
|
6082
|
+
f32(blue) / 255.0,
|
|
6083
|
+
f32(alpha) / 255.0
|
|
6084
|
+
);
|
|
4840
6085
|
}
|
|
4841
6086
|
|
|
6087
|
+
fn picking_filterPickingColor(color: vec4<f32>, objectIndex: i32) -> vec4<f32> {
|
|
6088
|
+
if (picking.isActive != 0) {
|
|
6089
|
+
if (!picking_canEncodePickInfo(objectIndex)) {
|
|
6090
|
+
discard;
|
|
6091
|
+
}
|
|
6092
|
+
return picking_getPickingColor(objectIndex);
|
|
6093
|
+
}
|
|
6094
|
+
|
|
6095
|
+
return color;
|
|
6096
|
+
}
|
|
4842
6097
|
`
|
|
4843
6098
|
);
|
|
4844
6099
|
var vs = (
|
|
@@ -4848,14 +6103,10 @@ var vs = (
|
|
|
4848
6103
|
const int INDEX_PICKING_MODE_INSTANCE = 0;
|
|
4849
6104
|
const int INDEX_PICKING_MODE_CUSTOM = 1;
|
|
4850
6105
|
|
|
4851
|
-
const int
|
|
6106
|
+
const int COLOR_PICKING_INVALID_INDEX = ${INVALID_INDEX};
|
|
4852
6107
|
|
|
4853
6108
|
flat out int picking_objectIndex;
|
|
4854
6109
|
|
|
4855
|
-
/**
|
|
4856
|
-
* Vertex shaders should call this function to set the object index.
|
|
4857
|
-
* If using instance or vertex mode, argument will be ignored, 0 can be supplied.
|
|
4858
|
-
*/
|
|
4859
6110
|
void picking_setObjectIndex(int objectIndex) {
|
|
4860
6111
|
switch (picking.indexMode) {
|
|
4861
6112
|
case INDEX_PICKING_MODE_INSTANCE:
|
|
@@ -4872,36 +6123,29 @@ var fs = (
|
|
|
4872
6123
|
/* glsl */
|
|
4873
6124
|
`${GLSL_UNIFORMS}
|
|
4874
6125
|
|
|
4875
|
-
const int
|
|
6126
|
+
const int COLOR_PICKING_INVALID_INDEX = ${INVALID_INDEX};
|
|
6127
|
+
const int COLOR_PICKING_MAX_OBJECT_INDEX = 16777214;
|
|
6128
|
+
const int COLOR_PICKING_MAX_BATCH_INDEX = 254;
|
|
4876
6129
|
|
|
4877
6130
|
flat in int picking_objectIndex;
|
|
4878
6131
|
|
|
4879
|
-
/**
|
|
4880
|
-
* Check if this vertex is highlighted (part of the selected batch and object)
|
|
4881
|
-
*/
|
|
4882
6132
|
bool picking_isFragmentHighlighted() {
|
|
4883
|
-
return
|
|
6133
|
+
return
|
|
4884
6134
|
bool(picking.isHighlightActive) &&
|
|
4885
6135
|
picking.highlightedBatchIndex == picking.batchIndex &&
|
|
4886
6136
|
picking.highlightedObjectIndex == picking_objectIndex
|
|
4887
6137
|
;
|
|
4888
6138
|
}
|
|
4889
6139
|
|
|
4890
|
-
/**
|
|
4891
|
-
* Returns highlight color if this item is selected.
|
|
4892
|
-
*/
|
|
4893
6140
|
vec4 picking_filterHighlightColor(vec4 color) {
|
|
4894
|
-
// If we are still picking, we don't highlight
|
|
4895
6141
|
if (bool(picking.isActive)) {
|
|
4896
6142
|
return color;
|
|
4897
6143
|
}
|
|
4898
6144
|
|
|
4899
|
-
// If we are not highlighted, return color as is
|
|
4900
6145
|
if (!picking_isFragmentHighlighted()) {
|
|
4901
6146
|
return color;
|
|
4902
6147
|
}
|
|
4903
|
-
|
|
4904
|
-
// Blend in highlight color based on its alpha value
|
|
6148
|
+
|
|
4905
6149
|
float highLightAlpha = picking.highlightColor.a;
|
|
4906
6150
|
float blendedAlpha = highLightAlpha + color.a * (1.0 - highLightAlpha);
|
|
4907
6151
|
float highLightRatio = highLightAlpha / blendedAlpha;
|
|
@@ -4910,28 +6154,40 @@ vec4 picking_filterHighlightColor(vec4 color) {
|
|
|
4910
6154
|
return vec4(blendedRGB, blendedAlpha);
|
|
4911
6155
|
}
|
|
4912
6156
|
|
|
4913
|
-
|
|
4914
|
-
|
|
4915
|
-
|
|
4916
|
-
|
|
4917
|
-
|
|
4918
|
-
|
|
4919
|
-
|
|
6157
|
+
bool picking_canEncodePickInfo(int objectIndex) {
|
|
6158
|
+
return
|
|
6159
|
+
objectIndex != COLOR_PICKING_INVALID_INDEX &&
|
|
6160
|
+
objectIndex >= 0 &&
|
|
6161
|
+
objectIndex <= COLOR_PICKING_MAX_OBJECT_INDEX &&
|
|
6162
|
+
picking.batchIndex >= 0 &&
|
|
6163
|
+
picking.batchIndex <= COLOR_PICKING_MAX_BATCH_INDEX;
|
|
6164
|
+
}
|
|
6165
|
+
|
|
6166
|
+
vec4 picking_getPickingColor() {
|
|
6167
|
+
if (!picking_canEncodePickInfo(picking_objectIndex)) {
|
|
6168
|
+
return vec4(0.0);
|
|
6169
|
+
}
|
|
6170
|
+
|
|
6171
|
+
int encodedObjectIndex = picking_objectIndex + 1;
|
|
6172
|
+
int red = encodedObjectIndex % 256;
|
|
6173
|
+
int green = (encodedObjectIndex / 256) % 256;
|
|
6174
|
+
int blue = (encodedObjectIndex / 65536) % 256;
|
|
6175
|
+
int alpha = picking.batchIndex + 1;
|
|
6176
|
+
|
|
6177
|
+
return vec4(float(red), float(green), float(blue), float(alpha)) / 255.0;
|
|
4920
6178
|
}
|
|
4921
6179
|
|
|
4922
6180
|
vec4 picking_filterPickingColor(vec4 color) {
|
|
4923
6181
|
if (bool(picking.isActive)) {
|
|
4924
|
-
if (picking_objectIndex
|
|
6182
|
+
if (!picking_canEncodePickInfo(picking_objectIndex)) {
|
|
4925
6183
|
discard;
|
|
4926
6184
|
}
|
|
6185
|
+
return picking_getPickingColor();
|
|
4927
6186
|
}
|
|
6187
|
+
|
|
4928
6188
|
return color;
|
|
4929
6189
|
}
|
|
4930
6190
|
|
|
4931
|
-
/*
|
|
4932
|
-
* Returns picking color if picking is enabled if not
|
|
4933
|
-
* highlight color if this item is selected, otherwise unmodified argument.
|
|
4934
|
-
*/
|
|
4935
6191
|
vec4 picking_filterColor(vec4 color) {
|
|
4936
6192
|
vec4 outColor = color;
|
|
4937
6193
|
outColor = picking_filterHighlightColor(outColor);
|
|
@@ -4948,87 +6204,81 @@ var picking = {
|
|
|
4948
6204
|
fs
|
|
4949
6205
|
};
|
|
4950
6206
|
|
|
4951
|
-
// dist/modules/picking/
|
|
6207
|
+
// dist/modules/picking/index-picking.js
|
|
4952
6208
|
var source2 = (
|
|
4953
6209
|
/* wgsl */
|
|
4954
6210
|
`${WGSL_UNIFORMS}
|
|
4955
|
-
`
|
|
4956
|
-
);
|
|
4957
|
-
var vs2 = (
|
|
4958
|
-
/* glsl */
|
|
4959
|
-
`${GLSL_UNIFORMS}
|
|
4960
|
-
out vec4 picking_vRGBcolor_Avalid;
|
|
4961
|
-
|
|
4962
|
-
// Normalize unsigned byte color to 0-1 range
|
|
4963
|
-
vec3 picking_normalizeColor(vec3 color) {
|
|
4964
|
-
return picking.useFloatColors > 0.5 ? color : color / 255.0;
|
|
4965
|
-
}
|
|
4966
6211
|
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
}
|
|
4971
|
-
|
|
4972
|
-
bool picking_isColorZero(vec3 color) {
|
|
4973
|
-
return dot(color, vec3(1.0)) < 0.00001;
|
|
4974
|
-
}
|
|
6212
|
+
const INDEX_PICKING_MODE_INSTANCE = 0;
|
|
6213
|
+
const INDEX_PICKING_MODE_CUSTOM = 1;
|
|
6214
|
+
const INDEX_PICKING_INVALID_INDEX = ${INVALID_INDEX}; // 2^32 - 1
|
|
4975
6215
|
|
|
4976
|
-
|
|
4977
|
-
|
|
6216
|
+
/**
|
|
6217
|
+
* WGSL shaders need to carry the returned object index through their own stage outputs.
|
|
6218
|
+
*/
|
|
6219
|
+
fn picking_setObjectIndex(objectIndex: i32) -> i32 {
|
|
6220
|
+
return objectIndex;
|
|
4978
6221
|
}
|
|
4979
6222
|
|
|
4980
|
-
|
|
4981
|
-
bool isVertexHighlighted(vec3 vertexColor) {
|
|
4982
|
-
vec3 highlightedObjectColor = picking_normalizeColor(picking.highlightedObjectColor);
|
|
6223
|
+
fn picking_isObjectHighlighted(objectIndex: i32) -> bool {
|
|
4983
6224
|
return
|
|
4984
|
-
|
|
6225
|
+
picking.isHighlightActive != 0 &&
|
|
6226
|
+
picking.highlightedBatchIndex == picking.batchIndex &&
|
|
6227
|
+
picking.highlightedObjectIndex == objectIndex;
|
|
4985
6228
|
}
|
|
4986
6229
|
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
if (bool(picking.isActive)) {
|
|
4992
|
-
// Use alpha as the validity flag. If pickingColor is [0, 0, 0] fragment is non-pickable
|
|
4993
|
-
picking_vRGBcolor_Avalid.a = float(picking_isColorValid(pickingColor));
|
|
4994
|
-
|
|
4995
|
-
if (!bool(picking.isAttribute)) {
|
|
4996
|
-
// Stores the picking color so that the fragment shader can render it during picking
|
|
4997
|
-
picking_vRGBcolor_Avalid.rgb = pickingColor;
|
|
4998
|
-
}
|
|
4999
|
-
} else {
|
|
5000
|
-
// Do the comparison with selected item color in vertex shader as it should mean fewer compares
|
|
5001
|
-
picking_vRGBcolor_Avalid.a = float(isVertexHighlighted(pickingColor));
|
|
6230
|
+
fn picking_filterHighlightColor(color: vec4<f32>, objectIndex: i32) -> vec4<f32> {
|
|
6231
|
+
if (picking.isActive != 0 || !picking_isObjectHighlighted(objectIndex)) {
|
|
6232
|
+
return color;
|
|
5002
6233
|
}
|
|
5003
|
-
}
|
|
5004
6234
|
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
index = uint(gl_InstanceID);
|
|
5010
|
-
}
|
|
5011
|
-
picking_vRGBcolor_Avalid.r = float(index % 255) / 255.0;
|
|
5012
|
-
picking_vRGBcolor_Avalid.g = float((index / 255) % 255) / 255.0;
|
|
5013
|
-
picking_vRGBcolor_Avalid.b = float((index / 255 / 255) %255) / 255.0;
|
|
6235
|
+
let highLightAlpha = picking.highlightColor.a;
|
|
6236
|
+
let blendedAlpha = highLightAlpha + color.a * (1.0 - highLightAlpha);
|
|
6237
|
+
if (blendedAlpha == 0.0) {
|
|
6238
|
+
return vec4<f32>(color.rgb, 0.0);
|
|
5014
6239
|
}
|
|
6240
|
+
|
|
6241
|
+
let highLightRatio = highLightAlpha / blendedAlpha;
|
|
6242
|
+
let blendedRGB = mix(color.rgb, picking.highlightColor.rgb, highLightRatio);
|
|
6243
|
+
return vec4<f32>(blendedRGB, blendedAlpha);
|
|
5015
6244
|
}
|
|
5016
6245
|
|
|
5017
|
-
|
|
5018
|
-
if (
|
|
5019
|
-
|
|
6246
|
+
fn picking_filterPickingColor(color: vec4<f32>, objectIndex: i32) -> vec4<f32> {
|
|
6247
|
+
if (picking.isActive != 0 && objectIndex == INDEX_PICKING_INVALID_INDEX) {
|
|
6248
|
+
discard;
|
|
5020
6249
|
}
|
|
6250
|
+
return color;
|
|
5021
6251
|
}
|
|
5022
6252
|
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
picking_vRGBcolor_Avalid.rg = value;
|
|
5026
|
-
}
|
|
6253
|
+
fn picking_getPickingColor(objectIndex: i32) -> vec2<i32> {
|
|
6254
|
+
return vec2<i32>(objectIndex, picking.batchIndex);
|
|
5027
6255
|
}
|
|
5028
6256
|
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
|
|
6257
|
+
`
|
|
6258
|
+
);
|
|
6259
|
+
var vs2 = (
|
|
6260
|
+
/* glsl */
|
|
6261
|
+
`${GLSL_UNIFORMS}
|
|
6262
|
+
|
|
6263
|
+
const int INDEX_PICKING_MODE_INSTANCE = 0;
|
|
6264
|
+
const int INDEX_PICKING_MODE_CUSTOM = 1;
|
|
6265
|
+
|
|
6266
|
+
const int INDEX_PICKING_INVALID_INDEX = ${INVALID_INDEX}; // 2^32 - 1
|
|
6267
|
+
|
|
6268
|
+
flat out int picking_objectIndex;
|
|
6269
|
+
|
|
6270
|
+
/**
|
|
6271
|
+
* Vertex shaders should call this function to set the object index.
|
|
6272
|
+
* If using instance or vertex mode, argument will be ignored, 0 can be supplied.
|
|
6273
|
+
*/
|
|
6274
|
+
void picking_setObjectIndex(int objectIndex) {
|
|
6275
|
+
switch (picking.indexMode) {
|
|
6276
|
+
case INDEX_PICKING_MODE_INSTANCE:
|
|
6277
|
+
picking_objectIndex = gl_InstanceID;
|
|
6278
|
+
break;
|
|
6279
|
+
case INDEX_PICKING_MODE_CUSTOM:
|
|
6280
|
+
picking_objectIndex = objectIndex;
|
|
6281
|
+
break;
|
|
5032
6282
|
}
|
|
5033
6283
|
}
|
|
5034
6284
|
`
|
|
@@ -5037,41 +6287,58 @@ var fs2 = (
|
|
|
5037
6287
|
/* glsl */
|
|
5038
6288
|
`${GLSL_UNIFORMS}
|
|
5039
6289
|
|
|
5040
|
-
|
|
6290
|
+
const int INDEX_PICKING_INVALID_INDEX = ${INVALID_INDEX}; // 2^32 - 1
|
|
5041
6291
|
|
|
5042
|
-
|
|
6292
|
+
flat in int picking_objectIndex;
|
|
6293
|
+
|
|
6294
|
+
/**
|
|
6295
|
+
* Check if this vertex is highlighted (part of the selected batch and object)
|
|
6296
|
+
*/
|
|
6297
|
+
bool picking_isFragmentHighlighted() {
|
|
6298
|
+
return
|
|
6299
|
+
bool(picking.isHighlightActive) &&
|
|
6300
|
+
picking.highlightedBatchIndex == picking.batchIndex &&
|
|
6301
|
+
picking.highlightedObjectIndex == picking_objectIndex
|
|
6302
|
+
;
|
|
6303
|
+
}
|
|
6304
|
+
|
|
6305
|
+
/**
|
|
5043
6306
|
* Returns highlight color if this item is selected.
|
|
5044
6307
|
*/
|
|
5045
6308
|
vec4 picking_filterHighlightColor(vec4 color) {
|
|
5046
6309
|
// If we are still picking, we don't highlight
|
|
5047
|
-
if (picking.isActive
|
|
6310
|
+
if (bool(picking.isActive)) {
|
|
5048
6311
|
return color;
|
|
5049
6312
|
}
|
|
5050
6313
|
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
if (selected) {
|
|
5054
|
-
// Blend in highlight color based on its alpha value
|
|
5055
|
-
float highLightAlpha = picking.highlightColor.a;
|
|
5056
|
-
float blendedAlpha = highLightAlpha + color.a * (1.0 - highLightAlpha);
|
|
5057
|
-
float highLightRatio = highLightAlpha / blendedAlpha;
|
|
5058
|
-
|
|
5059
|
-
vec3 blendedRGB = mix(color.rgb, picking.highlightColor.rgb, highLightRatio);
|
|
5060
|
-
return vec4(blendedRGB, blendedAlpha);
|
|
5061
|
-
} else {
|
|
6314
|
+
// If we are not highlighted, return color as is
|
|
6315
|
+
if (!picking_isFragmentHighlighted()) {
|
|
5062
6316
|
return color;
|
|
5063
6317
|
}
|
|
6318
|
+
|
|
6319
|
+
// Blend in highlight color based on its alpha value
|
|
6320
|
+
float highLightAlpha = picking.highlightColor.a;
|
|
6321
|
+
float blendedAlpha = highLightAlpha + color.a * (1.0 - highLightAlpha);
|
|
6322
|
+
float highLightRatio = highLightAlpha / blendedAlpha;
|
|
6323
|
+
|
|
6324
|
+
vec3 blendedRGB = mix(color.rgb, picking.highlightColor.rgb, highLightRatio);
|
|
6325
|
+
return vec4(blendedRGB, blendedAlpha);
|
|
5064
6326
|
}
|
|
5065
6327
|
|
|
5066
6328
|
/*
|
|
5067
6329
|
* Returns picking color if picking enabled else unmodified argument.
|
|
5068
6330
|
*/
|
|
6331
|
+
ivec4 picking_getPickingColor() {
|
|
6332
|
+
// Assumes that colorAttachment0 is rg32int
|
|
6333
|
+
// TODO? - we could render indices into a second color attachment and not mess with fragColor
|
|
6334
|
+
return ivec4(picking_objectIndex, picking.batchIndex, 0u, 0u);
|
|
6335
|
+
}
|
|
6336
|
+
|
|
5069
6337
|
vec4 picking_filterPickingColor(vec4 color) {
|
|
5070
6338
|
if (bool(picking.isActive)) {
|
|
5071
|
-
if (
|
|
6339
|
+
if (picking_objectIndex == INDEX_PICKING_INVALID_INDEX) {
|
|
5072
6340
|
discard;
|
|
5073
6341
|
}
|
|
5074
|
-
return picking_vRGBcolor_Avalid;
|
|
5075
6342
|
}
|
|
5076
6343
|
return color;
|
|
5077
6344
|
}
|
|
@@ -5081,8 +6348,10 @@ vec4 picking_filterPickingColor(vec4 color) {
|
|
|
5081
6348
|
* highlight color if this item is selected, otherwise unmodified argument.
|
|
5082
6349
|
*/
|
|
5083
6350
|
vec4 picking_filterColor(vec4 color) {
|
|
5084
|
-
vec4
|
|
5085
|
-
|
|
6351
|
+
vec4 outColor = color;
|
|
6352
|
+
outColor = picking_filterHighlightColor(outColor);
|
|
6353
|
+
outColor = picking_filterPickingColor(outColor);
|
|
6354
|
+
return outColor;
|
|
5086
6355
|
}
|
|
5087
6356
|
`
|
|
5088
6357
|
);
|
|
@@ -5094,6 +6363,15 @@ var picking2 = {
|
|
|
5094
6363
|
fs: fs2
|
|
5095
6364
|
};
|
|
5096
6365
|
|
|
6366
|
+
// dist/modules/picking/picking.js
|
|
6367
|
+
var picking3 = {
|
|
6368
|
+
...pickingUniforms,
|
|
6369
|
+
name: "picking",
|
|
6370
|
+
source: picking2.source,
|
|
6371
|
+
vs: picking.vs,
|
|
6372
|
+
fs: picking.fs
|
|
6373
|
+
};
|
|
6374
|
+
|
|
5097
6375
|
// dist/modules/picking/legacy-picking-manager.js
|
|
5098
6376
|
var LegacyPickingManager = class {
|
|
5099
6377
|
device;
|
|
@@ -5161,4 +6439,11 @@ var LegacyPickingManager = class {
|
|
|
5161
6439
|
return [pickX, pickY];
|
|
5162
6440
|
}
|
|
5163
6441
|
};
|
|
6442
|
+
|
|
6443
|
+
// dist/modules/picking/legacy-color-picking.js
|
|
6444
|
+
var import_shadertools7 = require("@luma.gl/shadertools");
|
|
6445
|
+
var legacyColorPicking = import_shadertools7.picking;
|
|
6446
|
+
|
|
6447
|
+
// dist/index.js
|
|
6448
|
+
var AsyncTexture = DynamicTexture;
|
|
5164
6449
|
//# sourceMappingURL=index.cjs.map
|