@luma.gl/engine 9.3.0-alpha.6 → 9.3.0-alpha.9
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.map +1 -1
- package/dist/animation-loop/animation-loop.js +3 -0
- package/dist/animation-loop/animation-loop.js.map +1 -1
- package/dist/compute/computation.d.ts +3 -7
- package/dist/compute/computation.d.ts.map +1 -1
- package/dist/compute/computation.js +14 -12
- package/dist/compute/computation.js.map +1 -1
- package/dist/dist.dev.js +1751 -831
- package/dist/dist.min.js +296 -148
- package/dist/dynamic-texture/dynamic-texture.d.ts +9 -2
- package/dist/dynamic-texture/dynamic-texture.d.ts.map +1 -1
- package/dist/dynamic-texture/dynamic-texture.js +54 -5
- package/dist/dynamic-texture/dynamic-texture.js.map +1 -1
- package/dist/dynamic-texture/texture-data.d.ts +4 -1
- package/dist/dynamic-texture/texture-data.d.ts.map +1 -1
- package/dist/dynamic-texture/texture-data.js +19 -2
- package/dist/dynamic-texture/texture-data.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 +1711 -847
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +12 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -3
- package/dist/index.js.map +1 -1
- package/dist/material/material-factory.d.ts +73 -0
- package/dist/material/material-factory.d.ts.map +1 -0
- package/dist/material/material-factory.js +111 -0
- package/dist/material/material-factory.js.map +1 -0
- package/dist/material/material.d.ts +84 -0
- package/dist/material/material.d.ts.map +1 -0
- package/dist/material/material.js +176 -0
- package/dist/material/material.js.map +1 -0
- package/dist/model/model.d.ts +14 -6
- package/dist/model/model.d.ts.map +1 -1
- package/dist/model/model.js +69 -25
- 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/directional-light-model.d.ts +7 -0
- package/dist/models/directional-light-model.d.ts.map +1 -0
- package/dist/models/directional-light-model.js +23 -0
- package/dist/models/directional-light-model.js.map +1 -0
- package/dist/models/light-model-utils.d.ts +69 -0
- package/dist/models/light-model-utils.d.ts.map +1 -0
- package/dist/models/light-model-utils.js +395 -0
- package/dist/models/light-model-utils.js.map +1 -0
- package/dist/models/point-light-model.d.ts +7 -0
- package/dist/models/point-light-model.d.ts.map +1 -0
- package/dist/models/point-light-model.js +22 -0
- package/dist/models/point-light-model.js.map +1 -0
- package/dist/models/spot-light-model.d.ts +7 -0
- package/dist/models/spot-light-model.d.ts.map +1 -0
- package/dist/models/spot-light-model.js +23 -0
- package/dist/models/spot-light-model.js.map +1 -0
- package/dist/modules/picking/color-picking.d.ts +5 -9
- package/dist/modules/picking/color-picking.d.ts.map +1 -1
- package/dist/modules/picking/color-picking.js +122 -115
- package/dist/modules/picking/color-picking.js.map +1 -1
- package/dist/modules/picking/index-picking.d.ts +2 -2
- package/dist/modules/picking/index-picking.d.ts.map +1 -1
- package/dist/modules/picking/index-picking.js +36 -10
- package/dist/modules/picking/index-picking.js.map +1 -1
- package/dist/modules/picking/legacy-color-picking.d.ts +26 -0
- package/dist/modules/picking/legacy-color-picking.d.ts.map +1 -0
- package/dist/modules/picking/legacy-color-picking.js +7 -0
- package/dist/modules/picking/legacy-color-picking.js.map +1 -0
- package/dist/modules/picking/picking-manager.d.ts +29 -3
- package/dist/modules/picking/picking-manager.d.ts.map +1 -1
- package/dist/modules/picking/picking-manager.js +188 -41
- package/dist/modules/picking/picking-manager.js.map +1 -1
- package/dist/modules/picking/picking-uniforms.d.ts +12 -11
- package/dist/modules/picking/picking-uniforms.d.ts.map +1 -1
- package/dist/modules/picking/picking-uniforms.js +26 -13
- package/dist/modules/picking/picking-uniforms.js.map +1 -1
- package/dist/modules/picking/picking.d.ts +25 -0
- package/dist/modules/picking/picking.d.ts.map +1 -0
- package/dist/modules/picking/picking.js +18 -0
- package/dist/modules/picking/picking.js.map +1 -0
- package/dist/shader-inputs.d.ts +9 -7
- package/dist/shader-inputs.d.ts.map +1 -1
- package/dist/shader-inputs.js +84 -4
- package/dist/shader-inputs.js.map +1 -1
- package/dist/utils/shader-module-utils.d.ts +7 -0
- package/dist/utils/shader-module-utils.d.ts.map +1 -0
- package/dist/utils/shader-module-utils.js +46 -0
- package/dist/utils/shader-module-utils.js.map +1 -0
- package/package.json +4 -4
- package/src/animation-loop/animation-loop.ts +3 -0
- package/src/compute/computation.ts +31 -17
- package/src/dynamic-texture/dynamic-texture.ts +79 -7
- package/src/dynamic-texture/texture-data.ts +25 -4
- package/src/geometry/gpu-geometry.ts +8 -3
- package/src/index.ts +29 -4
- package/src/material/material-factory.ts +157 -0
- package/src/material/material.ts +254 -0
- package/src/model/model.ts +108 -40
- package/src/model/split-uniforms-and-bindings.ts +8 -6
- 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 -10
- package/src/modules/picking/legacy-color-picking.ts +8 -0
- package/src/modules/picking/picking-manager.ts +252 -50
- package/src/modules/picking/picking-uniforms.ts +38 -23
- package/src/modules/picking/picking.ts +22 -0
- package/src/shader-inputs.ts +165 -15
- package/src/utils/shader-module-utils.ts +65 -0
- package/dist/factories/pipeline-factory.d.ts +0 -39
- package/dist/factories/pipeline-factory.d.ts.map +0 -1
- package/dist/factories/pipeline-factory.js +0 -216
- package/dist/factories/pipeline-factory.js.map +0 -1
- package/dist/factories/shader-factory.d.ts +0 -19
- package/dist/factories/shader-factory.d.ts.map +0 -1
- package/dist/factories/shader-factory.js +0 -83
- package/dist/factories/shader-factory.js.map +0 -1
- package/dist/types.d.ts +0 -7
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -5
- package/dist/types.js.map +0 -1
- package/src/factories/pipeline-factory.ts +0 -266
- package/src/factories/shader-factory.ts +0 -101
- package/src/types.ts +0 -11
package/dist/index.cjs
CHANGED
|
@@ -35,6 +35,7 @@ __export(dist_exports, {
|
|
|
35
35
|
ConeGeometry: () => ConeGeometry,
|
|
36
36
|
CubeGeometry: () => CubeGeometry,
|
|
37
37
|
CylinderGeometry: () => CylinderGeometry,
|
|
38
|
+
DirectionalLightModel: () => DirectionalLightModel,
|
|
38
39
|
DynamicTexture: () => DynamicTexture,
|
|
39
40
|
GPUGeometry: () => GPUGeometry,
|
|
40
41
|
Geometry: () => Geometry,
|
|
@@ -42,16 +43,18 @@ __export(dist_exports, {
|
|
|
42
43
|
IcoSphereGeometry: () => IcoSphereGeometry,
|
|
43
44
|
KeyFrames: () => KeyFrames,
|
|
44
45
|
LegacyPickingManager: () => LegacyPickingManager,
|
|
46
|
+
Material: () => Material,
|
|
47
|
+
MaterialFactory: () => MaterialFactory,
|
|
45
48
|
Model: () => Model,
|
|
46
49
|
ModelNode: () => ModelNode,
|
|
47
50
|
PickingManager: () => PickingManager,
|
|
48
|
-
PipelineFactory: () => PipelineFactory,
|
|
49
51
|
PlaneGeometry: () => PlaneGeometry,
|
|
52
|
+
PointLightModel: () => PointLightModel,
|
|
50
53
|
ScenegraphNode: () => ScenegraphNode,
|
|
51
|
-
ShaderFactory: () => ShaderFactory,
|
|
52
54
|
ShaderInputs: () => ShaderInputs,
|
|
53
55
|
ShaderPassRenderer: () => ShaderPassRenderer,
|
|
54
56
|
SphereGeometry: () => SphereGeometry,
|
|
57
|
+
SpotLightModel: () => SpotLightModel,
|
|
55
58
|
Swap: () => Swap,
|
|
56
59
|
SwapBuffers: () => SwapBuffers,
|
|
57
60
|
SwapFramebuffers: () => SwapFramebuffers,
|
|
@@ -59,14 +62,19 @@ __export(dist_exports, {
|
|
|
59
62
|
Timeline: () => Timeline,
|
|
60
63
|
TruncatedConeGeometry: () => TruncatedConeGeometry,
|
|
61
64
|
cancelAnimationFramePolyfill: () => cancelAnimationFramePolyfill,
|
|
62
|
-
colorPicking: () =>
|
|
63
|
-
indexPicking: () =>
|
|
65
|
+
colorPicking: () => picking,
|
|
66
|
+
indexPicking: () => picking2,
|
|
67
|
+
legacyColorPicking: () => legacyColorPicking,
|
|
64
68
|
loadImage: () => loadImage,
|
|
65
69
|
loadImageBitmap: () => loadImageBitmap,
|
|
66
70
|
makeAnimationLoop: () => makeAnimationLoop,
|
|
67
71
|
makeRandomGenerator: () => makeRandomGenerator,
|
|
72
|
+
picking: () => picking3,
|
|
68
73
|
requestAnimationFramePolyfill: () => requestAnimationFramePolyfill,
|
|
69
|
-
|
|
74
|
+
resolvePickingBackend: () => resolvePickingBackend,
|
|
75
|
+
resolvePickingMode: () => resolvePickingMode,
|
|
76
|
+
setPathPrefix: () => setPathPrefix,
|
|
77
|
+
supportsIndexPicking: () => supportsIndexPicking
|
|
70
78
|
});
|
|
71
79
|
module.exports = __toCommonJS(dist_exports);
|
|
72
80
|
|
|
@@ -350,6 +358,9 @@ var _AnimationLoop = class {
|
|
|
350
358
|
this._initialized = true;
|
|
351
359
|
await this._initDevice();
|
|
352
360
|
this._initialize();
|
|
361
|
+
if (!this._running) {
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
353
364
|
await this.props.onInitialize(this._getAnimationProps());
|
|
354
365
|
}
|
|
355
366
|
if (!this._running) {
|
|
@@ -744,7 +755,7 @@ function clearError(device) {
|
|
|
744
755
|
}
|
|
745
756
|
|
|
746
757
|
// dist/model/model.js
|
|
747
|
-
var
|
|
758
|
+
var import_core8 = require("@luma.gl/core");
|
|
748
759
|
var import_shadertools2 = require("@luma.gl/shadertools");
|
|
749
760
|
|
|
750
761
|
// dist/geometry/gpu-geometry.js
|
|
@@ -848,293 +859,19 @@ function getAttributeBuffersFromGeometry(device, geometry) {
|
|
|
848
859
|
id: `${attributeName}-buffer`
|
|
849
860
|
});
|
|
850
861
|
const { value, size, normalized } = attribute;
|
|
851
|
-
|
|
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
|
+
});
|
|
852
869
|
}
|
|
853
870
|
}
|
|
854
871
|
const vertexCount = geometry._calculateVertexCount(geometry.attributes, geometry.indices);
|
|
855
872
|
return { attributes, bufferLayout, vertexCount };
|
|
856
873
|
}
|
|
857
874
|
|
|
858
|
-
// dist/factories/pipeline-factory.js
|
|
859
|
-
var import_core4 = require("@luma.gl/core");
|
|
860
|
-
var _PipelineFactory = class {
|
|
861
|
-
/** Get the singleton default pipeline factory for the specified device */
|
|
862
|
-
static getDefaultPipelineFactory(device) {
|
|
863
|
-
const moduleData = device.getModuleData("@luma.gl/engine");
|
|
864
|
-
moduleData.defaultPipelineFactory ||= new _PipelineFactory(device);
|
|
865
|
-
return moduleData.defaultPipelineFactory;
|
|
866
|
-
}
|
|
867
|
-
device;
|
|
868
|
-
_hashCounter = 0;
|
|
869
|
-
_hashes = {};
|
|
870
|
-
_renderPipelineCache = {};
|
|
871
|
-
_computePipelineCache = {};
|
|
872
|
-
_sharedRenderPipelineCache = {};
|
|
873
|
-
get [Symbol.toStringTag]() {
|
|
874
|
-
return "PipelineFactory";
|
|
875
|
-
}
|
|
876
|
-
toString() {
|
|
877
|
-
return `PipelineFactory(${this.device.id})`;
|
|
878
|
-
}
|
|
879
|
-
constructor(device) {
|
|
880
|
-
this.device = device;
|
|
881
|
-
}
|
|
882
|
-
/** Return a RenderPipeline matching supplied props. Reuses an equivalent pipeline if already created. */
|
|
883
|
-
createRenderPipeline(props) {
|
|
884
|
-
var _a;
|
|
885
|
-
if (!this.device.props._cachePipelines) {
|
|
886
|
-
return this.device.createRenderPipeline(props);
|
|
887
|
-
}
|
|
888
|
-
const allProps = { ...import_core4.RenderPipeline.defaultProps, ...props };
|
|
889
|
-
const cache = this._renderPipelineCache;
|
|
890
|
-
const hash = this._hashRenderPipeline(allProps);
|
|
891
|
-
let pipeline = (_a = cache[hash]) == null ? void 0 : _a.resource;
|
|
892
|
-
if (!pipeline) {
|
|
893
|
-
const sharedRenderPipeline = this.device.type === "webgl" && this.device.props._sharePipelines ? this.createSharedRenderPipeline(allProps) : void 0;
|
|
894
|
-
pipeline = this.device.createRenderPipeline({
|
|
895
|
-
...allProps,
|
|
896
|
-
id: allProps.id ? `${allProps.id}-cached` : uid("unnamed-cached"),
|
|
897
|
-
_sharedRenderPipeline: sharedRenderPipeline
|
|
898
|
-
});
|
|
899
|
-
pipeline.hash = hash;
|
|
900
|
-
cache[hash] = { resource: pipeline, useCount: 1 };
|
|
901
|
-
if (this.device.props.debugFactories) {
|
|
902
|
-
import_core4.log.log(3, `${this}: ${pipeline} created, count=${cache[hash].useCount}`)();
|
|
903
|
-
}
|
|
904
|
-
} else {
|
|
905
|
-
cache[hash].useCount++;
|
|
906
|
-
if (this.device.props.debugFactories) {
|
|
907
|
-
import_core4.log.log(3, `${this}: ${cache[hash].resource} reused, count=${cache[hash].useCount}, (id=${props.id})`)();
|
|
908
|
-
}
|
|
909
|
-
}
|
|
910
|
-
return pipeline;
|
|
911
|
-
}
|
|
912
|
-
/** Return a ComputePipeline matching supplied props. Reuses an equivalent pipeline if already created. */
|
|
913
|
-
createComputePipeline(props) {
|
|
914
|
-
var _a;
|
|
915
|
-
if (!this.device.props._cachePipelines) {
|
|
916
|
-
return this.device.createComputePipeline(props);
|
|
917
|
-
}
|
|
918
|
-
const allProps = { ...import_core4.ComputePipeline.defaultProps, ...props };
|
|
919
|
-
const cache = this._computePipelineCache;
|
|
920
|
-
const hash = this._hashComputePipeline(allProps);
|
|
921
|
-
let pipeline = (_a = cache[hash]) == null ? void 0 : _a.resource;
|
|
922
|
-
if (!pipeline) {
|
|
923
|
-
pipeline = this.device.createComputePipeline({
|
|
924
|
-
...allProps,
|
|
925
|
-
id: allProps.id ? `${allProps.id}-cached` : void 0
|
|
926
|
-
});
|
|
927
|
-
pipeline.hash = hash;
|
|
928
|
-
cache[hash] = { resource: pipeline, useCount: 1 };
|
|
929
|
-
if (this.device.props.debugFactories) {
|
|
930
|
-
import_core4.log.log(3, `${this}: ${pipeline} created, count=${cache[hash].useCount}`)();
|
|
931
|
-
}
|
|
932
|
-
} else {
|
|
933
|
-
cache[hash].useCount++;
|
|
934
|
-
if (this.device.props.debugFactories) {
|
|
935
|
-
import_core4.log.log(3, `${this}: ${cache[hash].resource} reused, count=${cache[hash].useCount}, (id=${props.id})`)();
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
|
-
return pipeline;
|
|
939
|
-
}
|
|
940
|
-
release(pipeline) {
|
|
941
|
-
if (!this.device.props._cachePipelines) {
|
|
942
|
-
pipeline.destroy();
|
|
943
|
-
return;
|
|
944
|
-
}
|
|
945
|
-
const cache = this._getCache(pipeline);
|
|
946
|
-
const hash = pipeline.hash;
|
|
947
|
-
cache[hash].useCount--;
|
|
948
|
-
if (cache[hash].useCount === 0) {
|
|
949
|
-
this._destroyPipeline(pipeline);
|
|
950
|
-
if (this.device.props.debugFactories) {
|
|
951
|
-
import_core4.log.log(3, `${this}: ${pipeline} released and destroyed`)();
|
|
952
|
-
}
|
|
953
|
-
} else if (cache[hash].useCount < 0) {
|
|
954
|
-
import_core4.log.error(`${this}: ${pipeline} released, useCount < 0, resetting`)();
|
|
955
|
-
cache[hash].useCount = 0;
|
|
956
|
-
} else if (this.device.props.debugFactories) {
|
|
957
|
-
import_core4.log.log(3, `${this}: ${pipeline} released, count=${cache[hash].useCount}`)();
|
|
958
|
-
}
|
|
959
|
-
}
|
|
960
|
-
createSharedRenderPipeline(props) {
|
|
961
|
-
const sharedPipelineHash = this._hashSharedRenderPipeline(props);
|
|
962
|
-
let sharedCacheItem = this._sharedRenderPipelineCache[sharedPipelineHash];
|
|
963
|
-
if (!sharedCacheItem) {
|
|
964
|
-
const sharedRenderPipeline = this.device._createSharedRenderPipelineWebGL(props);
|
|
965
|
-
sharedCacheItem = { resource: sharedRenderPipeline, useCount: 0 };
|
|
966
|
-
this._sharedRenderPipelineCache[sharedPipelineHash] = sharedCacheItem;
|
|
967
|
-
}
|
|
968
|
-
sharedCacheItem.useCount++;
|
|
969
|
-
return sharedCacheItem.resource;
|
|
970
|
-
}
|
|
971
|
-
releaseSharedRenderPipeline(pipeline) {
|
|
972
|
-
if (!pipeline.sharedRenderPipeline) {
|
|
973
|
-
return;
|
|
974
|
-
}
|
|
975
|
-
const sharedPipelineHash = this._hashSharedRenderPipeline(pipeline.sharedRenderPipeline.props);
|
|
976
|
-
const sharedCacheItem = this._sharedRenderPipelineCache[sharedPipelineHash];
|
|
977
|
-
if (!sharedCacheItem) {
|
|
978
|
-
return;
|
|
979
|
-
}
|
|
980
|
-
sharedCacheItem.useCount--;
|
|
981
|
-
if (sharedCacheItem.useCount === 0) {
|
|
982
|
-
sharedCacheItem.resource.destroy();
|
|
983
|
-
delete this._sharedRenderPipelineCache[sharedPipelineHash];
|
|
984
|
-
}
|
|
985
|
-
}
|
|
986
|
-
// PRIVATE
|
|
987
|
-
/** Destroy a cached pipeline, removing it from the cache if configured to do so. */
|
|
988
|
-
_destroyPipeline(pipeline) {
|
|
989
|
-
const cache = this._getCache(pipeline);
|
|
990
|
-
if (!this.device.props._destroyPipelines) {
|
|
991
|
-
return false;
|
|
992
|
-
}
|
|
993
|
-
delete cache[pipeline.hash];
|
|
994
|
-
pipeline.destroy();
|
|
995
|
-
if (pipeline instanceof import_core4.RenderPipeline) {
|
|
996
|
-
this.releaseSharedRenderPipeline(pipeline);
|
|
997
|
-
}
|
|
998
|
-
return true;
|
|
999
|
-
}
|
|
1000
|
-
/** Get the appropriate cache for the type of pipeline */
|
|
1001
|
-
_getCache(pipeline) {
|
|
1002
|
-
let cache;
|
|
1003
|
-
if (pipeline instanceof import_core4.ComputePipeline) {
|
|
1004
|
-
cache = this._computePipelineCache;
|
|
1005
|
-
}
|
|
1006
|
-
if (pipeline instanceof import_core4.RenderPipeline) {
|
|
1007
|
-
cache = this._renderPipelineCache;
|
|
1008
|
-
}
|
|
1009
|
-
if (!cache) {
|
|
1010
|
-
throw new Error(`${this}`);
|
|
1011
|
-
}
|
|
1012
|
-
if (!cache[pipeline.hash]) {
|
|
1013
|
-
throw new Error(`${this}: ${pipeline} matched incorrect entry`);
|
|
1014
|
-
}
|
|
1015
|
-
return cache;
|
|
1016
|
-
}
|
|
1017
|
-
/** Calculate a hash based on all the inputs for a compute pipeline */
|
|
1018
|
-
_hashComputePipeline(props) {
|
|
1019
|
-
const { type } = this.device;
|
|
1020
|
-
const shaderHash = this._getHash(props.shader.source);
|
|
1021
|
-
return `${type}/C/${shaderHash}`;
|
|
1022
|
-
}
|
|
1023
|
-
/** Calculate a hash based on all the inputs for a render pipeline */
|
|
1024
|
-
_hashRenderPipeline(props) {
|
|
1025
|
-
const vsHash = props.vs ? this._getHash(props.vs.source) : 0;
|
|
1026
|
-
const fsHash = props.fs ? this._getHash(props.fs.source) : 0;
|
|
1027
|
-
const varyingHash = this._getWebGLVaryingHash(props);
|
|
1028
|
-
const bufferLayoutHash = this._getHash(JSON.stringify(props.bufferLayout));
|
|
1029
|
-
const { type } = this.device;
|
|
1030
|
-
switch (type) {
|
|
1031
|
-
case "webgl":
|
|
1032
|
-
const webglParameterHash = this._getHash(JSON.stringify(props.parameters));
|
|
1033
|
-
return `${type}/R/${vsHash}/${fsHash}V${varyingHash}T${props.topology}P${webglParameterHash}BL${bufferLayoutHash}`;
|
|
1034
|
-
case "webgpu":
|
|
1035
|
-
default:
|
|
1036
|
-
const parameterHash = this._getHash(JSON.stringify(props.parameters));
|
|
1037
|
-
return `${type}/R/${vsHash}/${fsHash}V${varyingHash}T${props.topology}P${parameterHash}BL${bufferLayoutHash}`;
|
|
1038
|
-
}
|
|
1039
|
-
}
|
|
1040
|
-
_hashSharedRenderPipeline(props) {
|
|
1041
|
-
const vsHash = props.vs ? this._getHash(props.vs.source) : 0;
|
|
1042
|
-
const fsHash = props.fs ? this._getHash(props.fs.source) : 0;
|
|
1043
|
-
const varyingHash = this._getWebGLVaryingHash(props);
|
|
1044
|
-
return `webgl/S/${vsHash}/${fsHash}V${varyingHash}`;
|
|
1045
|
-
}
|
|
1046
|
-
_getHash(key) {
|
|
1047
|
-
if (this._hashes[key] === void 0) {
|
|
1048
|
-
this._hashes[key] = this._hashCounter++;
|
|
1049
|
-
}
|
|
1050
|
-
return this._hashes[key];
|
|
1051
|
-
}
|
|
1052
|
-
_getWebGLVaryingHash(props) {
|
|
1053
|
-
const { varyings = [], bufferMode = null } = props;
|
|
1054
|
-
return this._getHash(JSON.stringify({ varyings, bufferMode }));
|
|
1055
|
-
}
|
|
1056
|
-
};
|
|
1057
|
-
var PipelineFactory = _PipelineFactory;
|
|
1058
|
-
__publicField(PipelineFactory, "defaultProps", { ...import_core4.RenderPipeline.defaultProps });
|
|
1059
|
-
|
|
1060
|
-
// dist/factories/shader-factory.js
|
|
1061
|
-
var import_core5 = require("@luma.gl/core");
|
|
1062
|
-
var _ShaderFactory = class {
|
|
1063
|
-
/** Returns the default ShaderFactory for the given {@link Device}, creating one if necessary. */
|
|
1064
|
-
static getDefaultShaderFactory(device) {
|
|
1065
|
-
const moduleData = device.getModuleData("@luma.gl/engine");
|
|
1066
|
-
moduleData.defaultShaderFactory ||= new _ShaderFactory(device);
|
|
1067
|
-
return moduleData.defaultShaderFactory;
|
|
1068
|
-
}
|
|
1069
|
-
device;
|
|
1070
|
-
_cache = {};
|
|
1071
|
-
get [Symbol.toStringTag]() {
|
|
1072
|
-
return "ShaderFactory";
|
|
1073
|
-
}
|
|
1074
|
-
toString() {
|
|
1075
|
-
return `${this[Symbol.toStringTag]}(${this.device.id})`;
|
|
1076
|
-
}
|
|
1077
|
-
/** @internal */
|
|
1078
|
-
constructor(device) {
|
|
1079
|
-
this.device = device;
|
|
1080
|
-
}
|
|
1081
|
-
/** Requests a {@link Shader} from the cache, creating a new Shader only if necessary. */
|
|
1082
|
-
createShader(props) {
|
|
1083
|
-
if (!this.device.props._cacheShaders) {
|
|
1084
|
-
return this.device.createShader(props);
|
|
1085
|
-
}
|
|
1086
|
-
const key = this._hashShader(props);
|
|
1087
|
-
let cacheEntry = this._cache[key];
|
|
1088
|
-
if (!cacheEntry) {
|
|
1089
|
-
const resource = this.device.createShader({
|
|
1090
|
-
...props,
|
|
1091
|
-
id: props.id ? `${props.id}-cached` : void 0
|
|
1092
|
-
});
|
|
1093
|
-
this._cache[key] = cacheEntry = { resource, useCount: 1 };
|
|
1094
|
-
if (this.device.props.debugFactories) {
|
|
1095
|
-
import_core5.log.log(3, `${this}: Created new shader ${resource.id}`)();
|
|
1096
|
-
}
|
|
1097
|
-
} else {
|
|
1098
|
-
cacheEntry.useCount++;
|
|
1099
|
-
if (this.device.props.debugFactories) {
|
|
1100
|
-
import_core5.log.log(3, `${this}: Reusing shader ${cacheEntry.resource.id} count=${cacheEntry.useCount}`)();
|
|
1101
|
-
}
|
|
1102
|
-
}
|
|
1103
|
-
return cacheEntry.resource;
|
|
1104
|
-
}
|
|
1105
|
-
/** Releases a previously-requested {@link Shader}, destroying it if no users remain. */
|
|
1106
|
-
release(shader) {
|
|
1107
|
-
if (!this.device.props._cacheShaders) {
|
|
1108
|
-
shader.destroy();
|
|
1109
|
-
return;
|
|
1110
|
-
}
|
|
1111
|
-
const key = this._hashShader(shader);
|
|
1112
|
-
const cacheEntry = this._cache[key];
|
|
1113
|
-
if (cacheEntry) {
|
|
1114
|
-
cacheEntry.useCount--;
|
|
1115
|
-
if (cacheEntry.useCount === 0) {
|
|
1116
|
-
if (this.device.props._destroyShaders) {
|
|
1117
|
-
delete this._cache[key];
|
|
1118
|
-
cacheEntry.resource.destroy();
|
|
1119
|
-
if (this.device.props.debugFactories) {
|
|
1120
|
-
import_core5.log.log(3, `${this}: Releasing shader ${shader.id}, destroyed`)();
|
|
1121
|
-
}
|
|
1122
|
-
}
|
|
1123
|
-
} else if (cacheEntry.useCount < 0) {
|
|
1124
|
-
throw new Error(`ShaderFactory: Shader ${shader.id} released too many times`);
|
|
1125
|
-
} else if (this.device.props.debugFactories) {
|
|
1126
|
-
import_core5.log.log(3, `${this}: Releasing shader ${shader.id} count=${cacheEntry.useCount}`)();
|
|
1127
|
-
}
|
|
1128
|
-
}
|
|
1129
|
-
}
|
|
1130
|
-
// PRIVATE
|
|
1131
|
-
_hashShader(value) {
|
|
1132
|
-
return `${value.stage}:${value.source}`;
|
|
1133
|
-
}
|
|
1134
|
-
};
|
|
1135
|
-
var ShaderFactory = _ShaderFactory;
|
|
1136
|
-
__publicField(ShaderFactory, "defaultProps", { ...import_core5.Shader.defaultProps });
|
|
1137
|
-
|
|
1138
875
|
// dist/debug/debug-shader-layout.js
|
|
1139
876
|
function getDebugTableForShaderLayout(layout, name) {
|
|
1140
877
|
var _a;
|
|
@@ -1235,7 +972,7 @@ function deepEqual(a, b, depth) {
|
|
|
1235
972
|
}
|
|
1236
973
|
|
|
1237
974
|
// dist/utils/buffer-layout-helper.js
|
|
1238
|
-
var
|
|
975
|
+
var import_core4 = require("@luma.gl/core");
|
|
1239
976
|
var BufferLayoutHelper = class {
|
|
1240
977
|
bufferLayouts;
|
|
1241
978
|
constructor(bufferLayouts) {
|
|
@@ -1264,7 +1001,7 @@ var BufferLayoutHelper = class {
|
|
|
1264
1001
|
getBufferIndex(bufferName) {
|
|
1265
1002
|
const bufferIndex = this.bufferLayouts.findIndex((layout) => layout.name === bufferName);
|
|
1266
1003
|
if (bufferIndex === -1) {
|
|
1267
|
-
|
|
1004
|
+
import_core4.log.warn(`BufferLayout: Missing buffer for "${bufferName}".`)();
|
|
1268
1005
|
}
|
|
1269
1006
|
return bufferIndex;
|
|
1270
1007
|
}
|
|
@@ -1294,8 +1031,52 @@ function sortedBufferLayoutByShaderSourceLocations(shaderLayout, bufferLayout) {
|
|
|
1294
1031
|
return sortedLayout;
|
|
1295
1032
|
}
|
|
1296
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
|
+
|
|
1297
1078
|
// dist/shader-inputs.js
|
|
1298
|
-
var
|
|
1079
|
+
var import_core5 = require("@luma.gl/core");
|
|
1299
1080
|
var import_shadertools = require("@luma.gl/shadertools");
|
|
1300
1081
|
|
|
1301
1082
|
// dist/model/split-uniforms-and-bindings.js
|
|
@@ -1303,11 +1084,11 @@ var import_types = require("@math.gl/types");
|
|
|
1303
1084
|
function isUniformValue(value) {
|
|
1304
1085
|
return (0, import_types.isNumericArray)(value) || typeof value === "number" || typeof value === "boolean";
|
|
1305
1086
|
}
|
|
1306
|
-
function splitUniformsAndBindings(uniforms) {
|
|
1087
|
+
function splitUniformsAndBindings(uniforms, uniformTypes2 = {}) {
|
|
1307
1088
|
const result = { bindings: {}, uniforms: {} };
|
|
1308
1089
|
Object.keys(uniforms).forEach((name) => {
|
|
1309
1090
|
const uniform = uniforms[name];
|
|
1310
|
-
if (isUniformValue(uniform)) {
|
|
1091
|
+
if (Object.prototype.hasOwnProperty.call(uniformTypes2, name) || isUniformValue(uniform)) {
|
|
1311
1092
|
result.uniforms[name] = uniform;
|
|
1312
1093
|
} else {
|
|
1313
1094
|
result.bindings[name] = uniform;
|
|
@@ -1339,18 +1120,21 @@ var ShaderInputs = class {
|
|
|
1339
1120
|
*/
|
|
1340
1121
|
constructor(modules, options) {
|
|
1341
1122
|
Object.assign(this.options, options);
|
|
1342
|
-
const resolvedModules = (0, import_shadertools.getShaderModuleDependencies)(Object.values(modules).filter(
|
|
1123
|
+
const resolvedModules = (0, import_shadertools.getShaderModuleDependencies)(Object.values(modules).filter(isShaderInputsModuleWithDependencies));
|
|
1343
1124
|
for (const resolvedModule of resolvedModules) {
|
|
1344
1125
|
modules[resolvedModule.name] = resolvedModule;
|
|
1345
1126
|
}
|
|
1346
|
-
|
|
1127
|
+
import_core5.log.log(1, "Creating ShaderInputs with modules", Object.keys(modules))();
|
|
1347
1128
|
this.modules = modules;
|
|
1348
1129
|
this.moduleUniforms = {};
|
|
1349
1130
|
this.moduleBindings = {};
|
|
1350
1131
|
for (const [name, module2] of Object.entries(modules)) {
|
|
1132
|
+
if (!module2) {
|
|
1133
|
+
continue;
|
|
1134
|
+
}
|
|
1351
1135
|
this._addModule(module2);
|
|
1352
1136
|
if (module2.name && name !== module2.name && !this.options.disableWarnings) {
|
|
1353
|
-
|
|
1137
|
+
import_core5.log.warn(`Module name: ${name} vs ${module2.name}`)();
|
|
1354
1138
|
}
|
|
1355
1139
|
}
|
|
1356
1140
|
}
|
|
@@ -1368,15 +1152,15 @@ var ShaderInputs = class {
|
|
|
1368
1152
|
const module2 = this.modules[moduleName];
|
|
1369
1153
|
if (!module2) {
|
|
1370
1154
|
if (!this.options.disableWarnings) {
|
|
1371
|
-
|
|
1155
|
+
import_core5.log.warn(`Module ${name} not found`)();
|
|
1372
1156
|
}
|
|
1373
1157
|
continue;
|
|
1374
1158
|
}
|
|
1375
1159
|
const oldUniforms = this.moduleUniforms[moduleName];
|
|
1376
1160
|
const oldBindings = this.moduleBindings[moduleName];
|
|
1377
1161
|
const uniformsAndBindings = ((_a = module2.getUniforms) == null ? void 0 : _a.call(module2, moduleProps, oldUniforms)) || moduleProps;
|
|
1378
|
-
const { uniforms, bindings } = splitUniformsAndBindings(uniformsAndBindings);
|
|
1379
|
-
this.moduleUniforms[moduleName] =
|
|
1162
|
+
const { uniforms, bindings } = splitUniformsAndBindings(uniformsAndBindings, module2.uniformTypes);
|
|
1163
|
+
this.moduleUniforms[moduleName] = mergeModuleUniforms(oldUniforms, uniforms, module2.uniformTypes);
|
|
1380
1164
|
this.moduleBindings[moduleName] = { ...oldBindings, ...bindings };
|
|
1381
1165
|
}
|
|
1382
1166
|
}
|
|
@@ -1416,16 +1200,87 @@ var ShaderInputs = class {
|
|
|
1416
1200
|
}
|
|
1417
1201
|
_addModule(module2) {
|
|
1418
1202
|
const moduleName = module2.name;
|
|
1419
|
-
this.moduleUniforms[moduleName] = module2.defaultUniforms || {};
|
|
1203
|
+
this.moduleUniforms[moduleName] = mergeModuleUniforms({}, module2.defaultUniforms || {}, module2.uniformTypes);
|
|
1420
1204
|
this.moduleBindings[moduleName] = {};
|
|
1421
1205
|
}
|
|
1422
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
|
+
}
|
|
1423
1278
|
|
|
1424
1279
|
// dist/dynamic-texture/dynamic-texture.js
|
|
1425
|
-
var
|
|
1280
|
+
var import_core7 = require("@luma.gl/core");
|
|
1426
1281
|
|
|
1427
1282
|
// dist/dynamic-texture/texture-data.js
|
|
1428
|
-
var
|
|
1283
|
+
var import_core6 = require("@luma.gl/core");
|
|
1429
1284
|
var TEXTURE_CUBE_FACE_MAP = { "+X": 0, "-X": 1, "+Y": 2, "-Y": 3, "+Z": 4, "-Z": 5 };
|
|
1430
1285
|
function getFirstMipLevel(layer) {
|
|
1431
1286
|
if (!layer)
|
|
@@ -1479,8 +1334,8 @@ function getTextureSizeFromData(props) {
|
|
|
1479
1334
|
}
|
|
1480
1335
|
}
|
|
1481
1336
|
function getTextureMipLevelSize(data) {
|
|
1482
|
-
if ((0,
|
|
1483
|
-
return (0,
|
|
1337
|
+
if ((0, import_core6.isExternalImage)(data)) {
|
|
1338
|
+
return (0, import_core6.getExternalImageSize)(data);
|
|
1484
1339
|
}
|
|
1485
1340
|
if (typeof data === "object" && "width" in data && "height" in data) {
|
|
1486
1341
|
return { width: data.width, height: data.height };
|
|
@@ -1490,6 +1345,9 @@ function getTextureMipLevelSize(data) {
|
|
|
1490
1345
|
function isTextureImageData(data) {
|
|
1491
1346
|
return typeof data === "object" && data !== null && "data" in data && "width" in data && "height" in data;
|
|
1492
1347
|
}
|
|
1348
|
+
function isTypedArrayMipLevelData(data) {
|
|
1349
|
+
return ArrayBuffer.isView(data);
|
|
1350
|
+
}
|
|
1493
1351
|
function resolveTextureImageFormat(data) {
|
|
1494
1352
|
const { textureFormat, format } = data;
|
|
1495
1353
|
if (textureFormat && format && textureFormat !== format) {
|
|
@@ -1512,13 +1370,13 @@ function getTexture1DSubresources(data) {
|
|
|
1512
1370
|
function _normalizeTexture2DData(data) {
|
|
1513
1371
|
return Array.isArray(data) ? data : [data];
|
|
1514
1372
|
}
|
|
1515
|
-
function getTexture2DSubresources(slice, lodData) {
|
|
1373
|
+
function getTexture2DSubresources(slice, lodData, baseLevelSize, textureFormat) {
|
|
1516
1374
|
const lodArray = _normalizeTexture2DData(lodData);
|
|
1517
1375
|
const z = slice;
|
|
1518
1376
|
const subresources = [];
|
|
1519
1377
|
for (let mipLevel = 0; mipLevel < lodArray.length; mipLevel++) {
|
|
1520
1378
|
const imageData = lodArray[mipLevel];
|
|
1521
|
-
if ((0,
|
|
1379
|
+
if ((0, import_core6.isExternalImage)(imageData)) {
|
|
1522
1380
|
subresources.push({
|
|
1523
1381
|
type: "external-image",
|
|
1524
1382
|
image: imageData,
|
|
@@ -1533,6 +1391,19 @@ function getTexture2DSubresources(slice, lodData) {
|
|
|
1533
1391
|
z,
|
|
1534
1392
|
mipLevel
|
|
1535
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
|
+
});
|
|
1536
1407
|
} else {
|
|
1537
1408
|
throw new Error("Unsupported 2D mip-level payload");
|
|
1538
1409
|
}
|
|
@@ -1628,7 +1499,12 @@ var _DynamicTexture = class {
|
|
|
1628
1499
|
try {
|
|
1629
1500
|
const propsWithSyncData = await this._loadAllData(originalPropsWithAsyncData);
|
|
1630
1501
|
this._checkNotDestroyed();
|
|
1631
|
-
const subresources = propsWithSyncData.data ? getTextureSubresources(
|
|
1502
|
+
const subresources = propsWithSyncData.data ? getTextureSubresources({
|
|
1503
|
+
...propsWithSyncData,
|
|
1504
|
+
width: originalPropsWithAsyncData.width,
|
|
1505
|
+
height: originalPropsWithAsyncData.height,
|
|
1506
|
+
format: originalPropsWithAsyncData.format
|
|
1507
|
+
}) : [];
|
|
1632
1508
|
const userProvidedFormat = "format" in originalPropsWithAsyncData && originalPropsWithAsyncData.format !== void 0;
|
|
1633
1509
|
const userProvidedUsage = "usage" in originalPropsWithAsyncData && originalPropsWithAsyncData.usage !== void 0;
|
|
1634
1510
|
const deduceSize = () => {
|
|
@@ -1658,11 +1534,11 @@ var _DynamicTexture = class {
|
|
|
1658
1534
|
data: void 0
|
|
1659
1535
|
};
|
|
1660
1536
|
if (this.device.isTextureFormatCompressed(resolvedFormat) && !userProvidedUsage) {
|
|
1661
|
-
baseTextureProps.usage =
|
|
1537
|
+
baseTextureProps.usage = import_core7.Texture.SAMPLE | import_core7.Texture.COPY_DST;
|
|
1662
1538
|
}
|
|
1663
1539
|
const shouldGenerateMipmaps = this.props.mipmaps && !textureData.hasExplicitMipChain && !this.device.isTextureFormatCompressed(resolvedFormat);
|
|
1664
1540
|
if (this.device.type === "webgpu" && shouldGenerateMipmaps) {
|
|
1665
|
-
const requiredUsage = this.props.dimension === "3d" ?
|
|
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;
|
|
1666
1542
|
baseTextureProps.usage |= requiredUsage;
|
|
1667
1543
|
}
|
|
1668
1544
|
const maxMips = this.device.getMipLevelCount(baseTextureProps.width, baseTextureProps.height);
|
|
@@ -1675,18 +1551,17 @@ var _DynamicTexture = class {
|
|
|
1675
1551
|
this._setTextureSubresources(textureData.subresources);
|
|
1676
1552
|
}
|
|
1677
1553
|
if (this.props.mipmaps && !textureData.hasExplicitMipChain && !shouldGenerateMipmaps) {
|
|
1678
|
-
|
|
1554
|
+
import_core7.log.warn(`${this} skipping auto-generated mipmaps for compressed texture format`)();
|
|
1679
1555
|
}
|
|
1680
1556
|
if (shouldGenerateMipmaps) {
|
|
1681
1557
|
this.generateMipmaps();
|
|
1682
1558
|
}
|
|
1683
1559
|
this.isReady = true;
|
|
1684
1560
|
this.resolveReady(this.texture);
|
|
1685
|
-
|
|
1561
|
+
import_core7.log.info(0, `${this} created`)();
|
|
1686
1562
|
} catch (e) {
|
|
1687
1563
|
const err = e instanceof Error ? e : new Error(String(e));
|
|
1688
1564
|
this.rejectReady(err);
|
|
1689
|
-
throw err;
|
|
1690
1565
|
}
|
|
1691
1566
|
}
|
|
1692
1567
|
destroy() {
|
|
@@ -1704,16 +1579,57 @@ var _DynamicTexture = class {
|
|
|
1704
1579
|
} else if (this.device.type === "webgpu") {
|
|
1705
1580
|
this.device.generateMipmapsWebGPU(this.texture);
|
|
1706
1581
|
} else {
|
|
1707
|
-
|
|
1582
|
+
import_core7.log.warn(`${this} mipmaps not supported on ${this.device.type}`);
|
|
1708
1583
|
}
|
|
1709
1584
|
}
|
|
1710
1585
|
/** Set sampler or create one from props */
|
|
1711
1586
|
setSampler(sampler = {}) {
|
|
1712
1587
|
this._checkReady();
|
|
1713
|
-
const s = sampler instanceof
|
|
1588
|
+
const s = sampler instanceof import_core7.Sampler ? sampler : this.device.createSampler(sampler);
|
|
1714
1589
|
this.texture.setSampler(s);
|
|
1715
1590
|
this._sampler = s;
|
|
1716
1591
|
}
|
|
1592
|
+
/**
|
|
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.
|
|
1595
|
+
*/
|
|
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 = {}) {
|
|
1621
|
+
if (!this.isReady) {
|
|
1622
|
+
await this.ready;
|
|
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
|
+
}
|
|
1717
1633
|
/**
|
|
1718
1634
|
* Resize by cloning the underlying immutable texture.
|
|
1719
1635
|
* Does not copy contents; caller may need to re-upload and/or regenerate mips.
|
|
@@ -1728,7 +1644,7 @@ var _DynamicTexture = class {
|
|
|
1728
1644
|
this._sampler = this.texture.sampler;
|
|
1729
1645
|
this._view = this.texture.view;
|
|
1730
1646
|
prev.destroy();
|
|
1731
|
-
|
|
1647
|
+
import_core7.log.info(`${this} resized`);
|
|
1732
1648
|
return true;
|
|
1733
1649
|
}
|
|
1734
1650
|
/** Convert cube face label to texture slice index. Index can be used with `setTexture2DData()`. */
|
|
@@ -1830,18 +1746,18 @@ var _DynamicTexture = class {
|
|
|
1830
1746
|
}
|
|
1831
1747
|
_checkNotDestroyed() {
|
|
1832
1748
|
if (this.destroyed) {
|
|
1833
|
-
|
|
1749
|
+
import_core7.log.warn(`${this} already destroyed`);
|
|
1834
1750
|
}
|
|
1835
1751
|
}
|
|
1836
1752
|
_checkReady() {
|
|
1837
1753
|
if (!this.isReady) {
|
|
1838
|
-
|
|
1754
|
+
import_core7.log.warn(`${this} Cannot perform this operation before ready`);
|
|
1839
1755
|
}
|
|
1840
1756
|
}
|
|
1841
1757
|
};
|
|
1842
1758
|
var DynamicTexture = _DynamicTexture;
|
|
1843
1759
|
__publicField(DynamicTexture, "defaultProps", {
|
|
1844
|
-
...
|
|
1760
|
+
...import_core7.Texture.defaultProps,
|
|
1845
1761
|
dimension: "2d",
|
|
1846
1762
|
data: null,
|
|
1847
1763
|
mipmaps: false
|
|
@@ -1850,11 +1766,13 @@ function getTextureSubresources(props) {
|
|
|
1850
1766
|
if (!props.data) {
|
|
1851
1767
|
return [];
|
|
1852
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;
|
|
1853
1771
|
switch (props.dimension) {
|
|
1854
1772
|
case "1d":
|
|
1855
1773
|
return getTexture1DSubresources(props.data);
|
|
1856
1774
|
case "2d":
|
|
1857
|
-
return getTexture2DSubresources(0, props.data);
|
|
1775
|
+
return getTexture2DSubresources(0, props.data, baseLevelSize, textureFormat);
|
|
1858
1776
|
case "3d":
|
|
1859
1777
|
return getTexture3DSubresources(props.data);
|
|
1860
1778
|
case "2d-array":
|
|
@@ -1981,7 +1899,7 @@ async function awaitAllPromises(x) {
|
|
|
1981
1899
|
}
|
|
1982
1900
|
if (x && typeof x === "object" && x.constructor === Object) {
|
|
1983
1901
|
const object = x;
|
|
1984
|
-
const values = await Promise.all(Object.values(object));
|
|
1902
|
+
const values = await Promise.all(Object.values(object).map(awaitAllPromises));
|
|
1985
1903
|
const keys = Object.keys(object);
|
|
1986
1904
|
const resolvedObject = {};
|
|
1987
1905
|
for (let i = 0; i < keys.length; i++) {
|
|
@@ -2050,6 +1968,7 @@ var _Model = class {
|
|
|
2050
1968
|
/** ShaderInputs instance */
|
|
2051
1969
|
// @ts-expect-error Assigned in function called by constructor
|
|
2052
1970
|
shaderInputs;
|
|
1971
|
+
material = null;
|
|
2053
1972
|
// @ts-expect-error Assigned in function called by constructor
|
|
2054
1973
|
_uniformStore;
|
|
2055
1974
|
_attributeInfos = {};
|
|
@@ -2060,6 +1979,7 @@ var _Model = class {
|
|
|
2060
1979
|
_destroyed = false;
|
|
2061
1980
|
/** "Time" of last draw. Monotonically increasing timestamp */
|
|
2062
1981
|
_lastDrawTimestamp = -1;
|
|
1982
|
+
_bindingTable = [];
|
|
2063
1983
|
get [Symbol.toStringTag]() {
|
|
2064
1984
|
return "Model";
|
|
2065
1985
|
}
|
|
@@ -2067,12 +1987,13 @@ var _Model = class {
|
|
|
2067
1987
|
return `Model(${this.id})`;
|
|
2068
1988
|
}
|
|
2069
1989
|
constructor(device, props) {
|
|
2070
|
-
var _a, _b, _c;
|
|
1990
|
+
var _a, _b, _c, _d;
|
|
2071
1991
|
this.props = { ..._Model.defaultProps, ...props };
|
|
2072
1992
|
props = this.props;
|
|
2073
1993
|
this.id = props.id || uid("model");
|
|
2074
1994
|
this.device = device;
|
|
2075
1995
|
Object.assign(this.userData, props.userData);
|
|
1996
|
+
this.material = props.material || null;
|
|
2076
1997
|
const moduleMap = Object.fromEntries(((_a = this.props.modules) == null ? void 0 : _a.map((module2) => [module2.name, module2])) || []);
|
|
2077
1998
|
const shaderInputs = props.shaderInputs || new ShaderInputs(moduleMap, { disableWarnings: this.props.disableWarnings });
|
|
2078
1999
|
this.setShaderInputs(shaderInputs);
|
|
@@ -2081,16 +2002,19 @@ var _Model = class {
|
|
|
2081
2002
|
// @ts-ignore shaderInputs is assigned in setShaderInputs above.
|
|
2082
2003
|
(((_b = this.props.modules) == null ? void 0 : _b.length) > 0 ? this.props.modules : (_c = this.shaderInputs) == null ? void 0 : _c.getModules()) || []
|
|
2083
2004
|
);
|
|
2005
|
+
this.props.shaderLayout = mergeShaderModuleBindingsIntoLayout(this.props.shaderLayout, modules) || null;
|
|
2084
2006
|
const isWebGPU = this.device.type === "webgpu";
|
|
2085
2007
|
if (isWebGPU && this.props.source) {
|
|
2086
|
-
const { source: source3, getUniforms: getUniforms2 } = this.props.shaderAssembler.assembleWGSLShader({
|
|
2008
|
+
const { source: source3, getUniforms: getUniforms2, bindingTable } = this.props.shaderAssembler.assembleWGSLShader({
|
|
2087
2009
|
platformInfo,
|
|
2088
2010
|
...this.props,
|
|
2089
2011
|
modules
|
|
2090
2012
|
});
|
|
2091
2013
|
this.source = source3;
|
|
2092
2014
|
this._getModuleUniforms = getUniforms2;
|
|
2093
|
-
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;
|
|
2094
2018
|
} else {
|
|
2095
2019
|
const { vs: vs3, fs: fs3, getUniforms: getUniforms2 } = this.props.shaderAssembler.assembleGLSLShaderPair({
|
|
2096
2020
|
platformInfo,
|
|
@@ -2100,6 +2024,7 @@ var _Model = class {
|
|
|
2100
2024
|
this.vs = vs3;
|
|
2101
2025
|
this.fs = fs3;
|
|
2102
2026
|
this._getModuleUniforms = getUniforms2;
|
|
2027
|
+
this._bindingTable = [];
|
|
2103
2028
|
}
|
|
2104
2029
|
this.vertexCount = this.props.vertexCount;
|
|
2105
2030
|
this.instanceCount = this.props.instanceCount;
|
|
@@ -2109,8 +2034,8 @@ var _Model = class {
|
|
|
2109
2034
|
if (props.geometry) {
|
|
2110
2035
|
this.setGeometry(props.geometry);
|
|
2111
2036
|
}
|
|
2112
|
-
this.pipelineFactory = props.pipelineFactory || PipelineFactory.getDefaultPipelineFactory(this.device);
|
|
2113
|
-
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);
|
|
2114
2039
|
this.pipeline = this._updatePipeline();
|
|
2115
2040
|
this.vertexArray = device.createVertexArray({
|
|
2116
2041
|
shaderLayout: this.pipeline.shaderLayout,
|
|
@@ -2171,6 +2096,10 @@ var _Model = class {
|
|
|
2171
2096
|
setNeedsRedraw(reason) {
|
|
2172
2097
|
this._needsRedraw ||= reason;
|
|
2173
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
|
+
}
|
|
2174
2103
|
/** Update uniforms and pipeline state prior to drawing. */
|
|
2175
2104
|
predraw() {
|
|
2176
2105
|
this.updateShaderInputs();
|
|
@@ -2184,7 +2113,7 @@ var _Model = class {
|
|
|
2184
2113
|
draw(renderPass) {
|
|
2185
2114
|
const loadingBinding = this._areBindingsLoading();
|
|
2186
2115
|
if (loadingBinding) {
|
|
2187
|
-
|
|
2116
|
+
import_core8.log.info(LOG_DRAW_PRIORITY, `>>> DRAWING ABORTED ${this.id}: ${loadingBinding} not loaded`)();
|
|
2188
2117
|
return false;
|
|
2189
2118
|
}
|
|
2190
2119
|
try {
|
|
@@ -2199,6 +2128,7 @@ var _Model = class {
|
|
|
2199
2128
|
this._logDrawCallStart();
|
|
2200
2129
|
this.pipeline = this._updatePipeline();
|
|
2201
2130
|
const syncBindings = this._getBindings();
|
|
2131
|
+
const syncBindGroups = this._getBindGroups();
|
|
2202
2132
|
const { indexBuffer } = this.vertexArray;
|
|
2203
2133
|
const indexCount = indexBuffer ? indexBuffer.byteLength / (indexBuffer.indexType === "uint32" ? 4 : 2) : void 0;
|
|
2204
2134
|
drawSuccess = this.pipeline.draw({
|
|
@@ -2213,6 +2143,8 @@ var _Model = class {
|
|
|
2213
2143
|
// and WebGL uniforms must be supplied on every draw instead of being stored
|
|
2214
2144
|
// on the pipeline instance.
|
|
2215
2145
|
bindings: syncBindings,
|
|
2146
|
+
bindGroups: syncBindGroups,
|
|
2147
|
+
_bindGroupCacheKeys: this._getBindGroupCacheKeys(),
|
|
2216
2148
|
uniforms: this.props.uniforms,
|
|
2217
2149
|
// WebGL shares underlying cached pipelines even for models that have different parameters and topology,
|
|
2218
2150
|
// so we must provide our unique parameters to each draw
|
|
@@ -2313,20 +2245,25 @@ var _Model = class {
|
|
|
2313
2245
|
}
|
|
2314
2246
|
/** Set the shader inputs */
|
|
2315
2247
|
setShaderInputs(shaderInputs) {
|
|
2248
|
+
var _a;
|
|
2316
2249
|
this.shaderInputs = shaderInputs;
|
|
2317
|
-
this._uniformStore = new
|
|
2250
|
+
this._uniformStore = new import_core8.UniformStore(this.shaderInputs.modules);
|
|
2318
2251
|
for (const [moduleName, module2] of Object.entries(this.shaderInputs.modules)) {
|
|
2319
|
-
if (shaderModuleHasUniforms(module2)) {
|
|
2252
|
+
if (shaderModuleHasUniforms(module2) && !((_a = this.material) == null ? void 0 : _a.ownsModule(moduleName))) {
|
|
2320
2253
|
const uniformBuffer = this._uniformStore.getManagedUniformBuffer(this.device, moduleName);
|
|
2321
2254
|
this.bindings[`${moduleName}Uniforms`] = uniformBuffer;
|
|
2322
2255
|
}
|
|
2323
2256
|
}
|
|
2324
2257
|
this.setNeedsRedraw("shaderInputs");
|
|
2325
2258
|
}
|
|
2259
|
+
setMaterial(material) {
|
|
2260
|
+
this.material = material;
|
|
2261
|
+
this.setNeedsRedraw("material");
|
|
2262
|
+
}
|
|
2326
2263
|
/** Update uniform buffers from the model's shader inputs */
|
|
2327
2264
|
updateShaderInputs() {
|
|
2328
2265
|
this._uniformStore.setUniforms(this.shaderInputs.getUniformValues());
|
|
2329
|
-
this.setBindings(this.shaderInputs.getBindingValues());
|
|
2266
|
+
this.setBindings(this._getNonMaterialBindings(this.shaderInputs.getBindingValues()));
|
|
2330
2267
|
this.setNeedsRedraw("shaderInputs");
|
|
2331
2268
|
}
|
|
2332
2269
|
/**
|
|
@@ -2358,7 +2295,7 @@ var _Model = class {
|
|
|
2358
2295
|
setAttributes(buffers, options) {
|
|
2359
2296
|
const disableWarnings = (options == null ? void 0 : options.disableWarnings) ?? this.props.disableWarnings;
|
|
2360
2297
|
if (buffers["indices"]) {
|
|
2361
|
-
|
|
2298
|
+
import_core8.log.warn(`Model:${this.id} setAttributes() - indexBuffer should be set using setIndexBuffer()`)();
|
|
2362
2299
|
}
|
|
2363
2300
|
this.bufferLayout = sortedBufferLayoutByShaderSourceLocations(this.pipeline.shaderLayout, this.bufferLayout);
|
|
2364
2301
|
const bufferLayoutHelper = new BufferLayoutHelper(this.bufferLayout);
|
|
@@ -2366,7 +2303,7 @@ var _Model = class {
|
|
|
2366
2303
|
const bufferLayout = bufferLayoutHelper.getBufferLayout(bufferName);
|
|
2367
2304
|
if (!bufferLayout) {
|
|
2368
2305
|
if (!disableWarnings) {
|
|
2369
|
-
|
|
2306
|
+
import_core8.log.warn(`Model(${this.id}): Missing layout for buffer "${bufferName}".`)();
|
|
2370
2307
|
}
|
|
2371
2308
|
continue;
|
|
2372
2309
|
}
|
|
@@ -2381,7 +2318,7 @@ var _Model = class {
|
|
|
2381
2318
|
}
|
|
2382
2319
|
}
|
|
2383
2320
|
if (!set && !disableWarnings) {
|
|
2384
|
-
|
|
2321
|
+
import_core8.log.warn(`Model(${this.id}): Ignoring buffer "${buffer.id}" for unknown attribute "${bufferName}"`)();
|
|
2385
2322
|
}
|
|
2386
2323
|
}
|
|
2387
2324
|
this.setNeedsRedraw("attributes");
|
|
@@ -2400,7 +2337,7 @@ var _Model = class {
|
|
|
2400
2337
|
if (attributeInfo) {
|
|
2401
2338
|
this.vertexArray.setConstantWebGL(attributeInfo.location, value);
|
|
2402
2339
|
} else if (!((options == null ? void 0 : options.disableWarnings) ?? this.props.disableWarnings)) {
|
|
2403
|
-
|
|
2340
|
+
import_core8.log.warn(`Model "${this.id}: Ignoring constant supplied for unknown attribute "${attributeName}"`)();
|
|
2404
2341
|
}
|
|
2405
2342
|
}
|
|
2406
2343
|
this.setNeedsRedraw("constants");
|
|
@@ -2408,11 +2345,17 @@ var _Model = class {
|
|
|
2408
2345
|
// INTERNAL METHODS
|
|
2409
2346
|
/** Check that bindings are loaded. Returns id of first binding that is still loading. */
|
|
2410
2347
|
_areBindingsLoading() {
|
|
2348
|
+
var _a;
|
|
2411
2349
|
for (const binding of Object.values(this.bindings)) {
|
|
2412
2350
|
if (binding instanceof DynamicTexture && !binding.isReady) {
|
|
2413
2351
|
return binding.id;
|
|
2414
2352
|
}
|
|
2415
2353
|
}
|
|
2354
|
+
for (const binding of Object.values(((_a = this.material) == null ? void 0 : _a.bindings) || {})) {
|
|
2355
|
+
if (binding instanceof DynamicTexture && !binding.isReady) {
|
|
2356
|
+
return binding.id;
|
|
2357
|
+
}
|
|
2358
|
+
}
|
|
2416
2359
|
return false;
|
|
2417
2360
|
}
|
|
2418
2361
|
/** Extracts texture view from loaded async textures. Returns null if any textures have not yet been loaded. */
|
|
@@ -2429,24 +2372,46 @@ var _Model = class {
|
|
|
2429
2372
|
}
|
|
2430
2373
|
return validBindings;
|
|
2431
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
|
+
}
|
|
2432
2396
|
/** Get the timestamp of the latest updated bound GPU memory resource (buffer/texture). */
|
|
2433
2397
|
_getBindingsUpdateTimestamp() {
|
|
2398
|
+
var _a;
|
|
2434
2399
|
let timestamp = 0;
|
|
2435
2400
|
for (const binding of Object.values(this.bindings)) {
|
|
2436
|
-
if (binding instanceof
|
|
2401
|
+
if (binding instanceof import_core8.TextureView) {
|
|
2437
2402
|
timestamp = Math.max(timestamp, binding.texture.updateTimestamp);
|
|
2438
|
-
} else if (binding instanceof
|
|
2403
|
+
} else if (binding instanceof import_core8.Buffer || binding instanceof import_core8.Texture) {
|
|
2439
2404
|
timestamp = Math.max(timestamp, binding.updateTimestamp);
|
|
2440
2405
|
} else if (binding instanceof DynamicTexture) {
|
|
2441
2406
|
timestamp = binding.texture ? Math.max(timestamp, binding.texture.updateTimestamp) : (
|
|
2442
2407
|
// The texture will become available in the future
|
|
2443
2408
|
Infinity
|
|
2444
2409
|
);
|
|
2445
|
-
} else if (!(binding instanceof
|
|
2410
|
+
} else if (!(binding instanceof import_core8.Sampler)) {
|
|
2446
2411
|
timestamp = Math.max(timestamp, binding.buffer.updateTimestamp);
|
|
2447
2412
|
}
|
|
2448
2413
|
}
|
|
2449
|
-
return timestamp;
|
|
2414
|
+
return Math.max(timestamp, ((_a = this.material) == null ? void 0 : _a.getBindingsUpdateTimestamp()) || 0);
|
|
2450
2415
|
}
|
|
2451
2416
|
/**
|
|
2452
2417
|
* Updates the optional geometry attributes
|
|
@@ -2477,7 +2442,7 @@ var _Model = class {
|
|
|
2477
2442
|
let prevShaderVs = null;
|
|
2478
2443
|
let prevShaderFs = null;
|
|
2479
2444
|
if (this.pipeline) {
|
|
2480
|
-
|
|
2445
|
+
import_core8.log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
|
|
2481
2446
|
prevShaderVs = this.pipeline.vs;
|
|
2482
2447
|
prevShaderFs = this.pipeline.fs;
|
|
2483
2448
|
}
|
|
@@ -2501,16 +2466,15 @@ var _Model = class {
|
|
|
2501
2466
|
}
|
|
2502
2467
|
this.pipeline = this.pipelineFactory.createRenderPipeline({
|
|
2503
2468
|
...this.props,
|
|
2469
|
+
bindings: void 0,
|
|
2504
2470
|
bufferLayout: this.bufferLayout,
|
|
2505
2471
|
topology: this.topology,
|
|
2506
2472
|
parameters: this.parameters,
|
|
2507
|
-
|
|
2508
|
-
// Should we expose a BindGroup abstraction?
|
|
2509
|
-
bindings: this._getBindings(),
|
|
2473
|
+
bindGroups: this._getBindGroups(),
|
|
2510
2474
|
vs: vs3,
|
|
2511
2475
|
fs: fs3
|
|
2512
2476
|
});
|
|
2513
|
-
this._attributeInfos = (0,
|
|
2477
|
+
this._attributeInfos = (0, import_core8.getAttributeInfosFromLayouts)(this.pipeline.shaderLayout, this.bufferLayout);
|
|
2514
2478
|
if (prevShaderVs)
|
|
2515
2479
|
this.shaderFactory.release(prevShaderVs);
|
|
2516
2480
|
if (prevShaderFs && prevShaderFs !== prevShaderVs) {
|
|
@@ -2523,24 +2487,24 @@ var _Model = class {
|
|
|
2523
2487
|
_lastLogTime = 0;
|
|
2524
2488
|
_logOpen = false;
|
|
2525
2489
|
_logDrawCallStart() {
|
|
2526
|
-
const logDrawTimeout =
|
|
2527
|
-
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) {
|
|
2528
2492
|
return;
|
|
2529
2493
|
}
|
|
2530
2494
|
this._lastLogTime = Date.now();
|
|
2531
2495
|
this._logOpen = true;
|
|
2532
|
-
|
|
2496
|
+
import_core8.log.group(LOG_DRAW_PRIORITY, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core8.log.level <= 2 })();
|
|
2533
2497
|
}
|
|
2534
2498
|
_logDrawCallEnd() {
|
|
2535
2499
|
if (this._logOpen) {
|
|
2536
2500
|
const shaderLayoutTable = getDebugTableForShaderLayout(this.pipeline.shaderLayout, this.id);
|
|
2537
|
-
|
|
2501
|
+
import_core8.log.table(LOG_DRAW_PRIORITY, shaderLayoutTable)();
|
|
2538
2502
|
const uniformTable = this.shaderInputs.getDebugTable();
|
|
2539
|
-
|
|
2503
|
+
import_core8.log.table(LOG_DRAW_PRIORITY, uniformTable)();
|
|
2540
2504
|
const attributeTable = this._getAttributeDebugTable();
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
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)();
|
|
2544
2508
|
this._logOpen = false;
|
|
2545
2509
|
}
|
|
2546
2510
|
}
|
|
@@ -2579,14 +2543,26 @@ var _Model = class {
|
|
|
2579
2543
|
}
|
|
2580
2544
|
// TODO - fix typing of luma data types
|
|
2581
2545
|
_getBufferOrConstantValues(attribute, dataType) {
|
|
2582
|
-
const TypedArrayConstructor =
|
|
2583
|
-
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;
|
|
2584
2548
|
return typedArray.toString();
|
|
2585
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
|
+
}
|
|
2586
2562
|
};
|
|
2587
2563
|
var Model = _Model;
|
|
2588
2564
|
__publicField(Model, "defaultProps", {
|
|
2589
|
-
...
|
|
2565
|
+
...import_core8.RenderPipeline.defaultProps,
|
|
2590
2566
|
source: void 0,
|
|
2591
2567
|
vs: null,
|
|
2592
2568
|
fs: null,
|
|
@@ -2606,6 +2582,7 @@ __publicField(Model, "defaultProps", {
|
|
|
2606
2582
|
instanceCount: 0,
|
|
2607
2583
|
vertexCount: 0,
|
|
2608
2584
|
shaderInputs: void 0,
|
|
2585
|
+
material: void 0,
|
|
2609
2586
|
pipelineFactory: void 0,
|
|
2610
2587
|
shaderFactory: void 0,
|
|
2611
2588
|
transformFeedback: void 0,
|
|
@@ -2613,9 +2590,6 @@ __publicField(Model, "defaultProps", {
|
|
|
2613
2590
|
debugShaders: void 0,
|
|
2614
2591
|
disableWarnings: void 0
|
|
2615
2592
|
});
|
|
2616
|
-
function shaderModuleHasUniforms(module2) {
|
|
2617
|
-
return Boolean(module2.uniformTypes && !isObjectEmpty(module2.uniformTypes));
|
|
2618
|
-
}
|
|
2619
2593
|
function getPlatformInfo(device) {
|
|
2620
2594
|
return {
|
|
2621
2595
|
type: device.type,
|
|
@@ -2626,101 +2600,322 @@ function getPlatformInfo(device) {
|
|
|
2626
2600
|
features: device.features
|
|
2627
2601
|
};
|
|
2628
2602
|
}
|
|
2629
|
-
function isObjectEmpty(obj) {
|
|
2630
|
-
for (const key in obj) {
|
|
2631
|
-
return false;
|
|
2632
|
-
}
|
|
2633
|
-
return true;
|
|
2634
|
-
}
|
|
2635
2603
|
|
|
2636
|
-
// dist/
|
|
2637
|
-
var
|
|
2638
|
-
|
|
2639
|
-
|
|
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. */
|
|
2640
2611
|
device;
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
}
|
|
2647
|
-
constructor(device, props = _BufferTransform.defaultProps) {
|
|
2648
|
-
if (!_BufferTransform.isSupported(device)) {
|
|
2649
|
-
throw new Error("BufferTransform not yet implemented on WebGPU");
|
|
2650
|
-
}
|
|
2612
|
+
/** Shader modules that define the material schema. */
|
|
2613
|
+
modules;
|
|
2614
|
+
_materialBindingNames;
|
|
2615
|
+
_materialModuleNames;
|
|
2616
|
+
constructor(device, props = {}) {
|
|
2651
2617
|
this.device = device;
|
|
2652
|
-
this.
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
buffers: props.feedbackBuffers
|
|
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
|
|
2663
2628
|
});
|
|
2664
|
-
this.model.setTransformFeedback(this.transformFeedback);
|
|
2665
|
-
Object.seal(this);
|
|
2666
2629
|
}
|
|
2667
|
-
/**
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
this.model.destroy();
|
|
2671
|
-
}
|
|
2672
|
-
}
|
|
2673
|
-
/** @deprecated Use {@link destroy}. */
|
|
2674
|
-
delete() {
|
|
2675
|
-
this.destroy();
|
|
2630
|
+
/** Returns the logical material-owned resource binding names. */
|
|
2631
|
+
getBindingNames() {
|
|
2632
|
+
return Array.from(this._materialBindingNames);
|
|
2676
2633
|
}
|
|
2677
|
-
/**
|
|
2678
|
-
|
|
2679
|
-
if (
|
|
2680
|
-
|
|
2681
|
-
}
|
|
2682
|
-
if (options == null ? void 0 : options.outputBuffers) {
|
|
2683
|
-
this.transformFeedback.setBuffers(options.outputBuffers);
|
|
2634
|
+
/** Returns `true` when the supplied binding belongs to this material schema. */
|
|
2635
|
+
ownsBinding(bindingName) {
|
|
2636
|
+
if (this._materialBindingNames.has(bindingName)) {
|
|
2637
|
+
return true;
|
|
2684
2638
|
}
|
|
2685
|
-
const
|
|
2686
|
-
this.
|
|
2687
|
-
renderPass.end();
|
|
2639
|
+
const aliasedModuleName = getModuleNameFromUniformBinding(bindingName);
|
|
2640
|
+
return aliasedModuleName ? this._materialModuleNames.has(aliasedModuleName) : false;
|
|
2688
2641
|
}
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
return this.transformFeedback.getBuffer(varyingName);
|
|
2642
|
+
/** Returns `true` when the supplied shader module is owned by this material schema. */
|
|
2643
|
+
ownsModule(moduleName) {
|
|
2644
|
+
return this._materialModuleNames.has(moduleName);
|
|
2693
2645
|
}
|
|
2694
|
-
/**
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
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
|
+
}
|
|
2699
2661
|
}
|
|
2700
|
-
|
|
2701
|
-
|
|
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);
|
|
2702
2671
|
}
|
|
2703
|
-
const { buffer, byteOffset = 0, byteLength = buffer.byteLength } = result;
|
|
2704
|
-
return buffer.readAsync(byteOffset, byteLength);
|
|
2705
2672
|
}
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
__publicField(BufferTransform, "defaultProps", {
|
|
2709
|
-
...Model.defaultProps,
|
|
2710
|
-
outputs: void 0,
|
|
2711
|
-
feedbackBuffers: void 0
|
|
2712
|
-
});
|
|
2673
|
+
return moduleNames;
|
|
2674
|
+
}
|
|
2713
2675
|
|
|
2714
|
-
// dist/
|
|
2715
|
-
var
|
|
2716
|
-
|
|
2717
|
-
|
|
2676
|
+
// dist/material/material.js
|
|
2677
|
+
var Material = class {
|
|
2678
|
+
/** Application-provided identifier. */
|
|
2679
|
+
id;
|
|
2680
|
+
/** Device that owns the material resources. */
|
|
2718
2681
|
device;
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
bindings
|
|
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.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(this.device, 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
|
+
|
|
2831
|
+
// dist/compute/buffer-transform.js
|
|
2832
|
+
var import_core10 = require("@luma.gl/core");
|
|
2833
|
+
var import_shadertools3 = require("@luma.gl/shadertools");
|
|
2834
|
+
var _BufferTransform = class {
|
|
2835
|
+
device;
|
|
2836
|
+
model;
|
|
2837
|
+
transformFeedback;
|
|
2838
|
+
static isSupported(device) {
|
|
2839
|
+
var _a;
|
|
2840
|
+
return ((_a = device == null ? void 0 : device.info) == null ? void 0 : _a.type) === "webgl";
|
|
2841
|
+
}
|
|
2842
|
+
constructor(device, props = _BufferTransform.defaultProps) {
|
|
2843
|
+
if (!_BufferTransform.isSupported(device)) {
|
|
2844
|
+
throw new Error("BufferTransform not yet implemented on WebGPU");
|
|
2845
|
+
}
|
|
2846
|
+
this.device = device;
|
|
2847
|
+
this.model = new Model(this.device, {
|
|
2848
|
+
id: props.id || "buffer-transform-model",
|
|
2849
|
+
fs: props.fs || (0, import_shadertools3.getPassthroughFS)(),
|
|
2850
|
+
topology: props.topology || "point-list",
|
|
2851
|
+
varyings: props.outputs || props.varyings,
|
|
2852
|
+
...props
|
|
2853
|
+
});
|
|
2854
|
+
this.transformFeedback = this.device.createTransformFeedback({
|
|
2855
|
+
layout: this.model.pipeline.shaderLayout,
|
|
2856
|
+
// @ts-expect-error TODO
|
|
2857
|
+
buffers: props.feedbackBuffers
|
|
2858
|
+
});
|
|
2859
|
+
this.model.setTransformFeedback(this.transformFeedback);
|
|
2860
|
+
Object.seal(this);
|
|
2861
|
+
}
|
|
2862
|
+
/** Destroy owned resources. */
|
|
2863
|
+
destroy() {
|
|
2864
|
+
if (this.model) {
|
|
2865
|
+
this.model.destroy();
|
|
2866
|
+
}
|
|
2867
|
+
}
|
|
2868
|
+
/** @deprecated Use {@link destroy}. */
|
|
2869
|
+
delete() {
|
|
2870
|
+
this.destroy();
|
|
2871
|
+
}
|
|
2872
|
+
/** Run one transform loop. */
|
|
2873
|
+
run(options) {
|
|
2874
|
+
if (options == null ? void 0 : options.inputBuffers) {
|
|
2875
|
+
this.model.setAttributes(options.inputBuffers);
|
|
2876
|
+
}
|
|
2877
|
+
if (options == null ? void 0 : options.outputBuffers) {
|
|
2878
|
+
this.transformFeedback.setBuffers(options.outputBuffers);
|
|
2879
|
+
}
|
|
2880
|
+
const renderPass = this.device.beginRenderPass(options);
|
|
2881
|
+
this.model.draw(renderPass);
|
|
2882
|
+
renderPass.end();
|
|
2883
|
+
}
|
|
2884
|
+
// DEPRECATED METHODS
|
|
2885
|
+
/** @deprecated App knows what buffers it is passing in - Returns the {@link Buffer} or {@link BufferRange} for given varying name. */
|
|
2886
|
+
getBuffer(varyingName) {
|
|
2887
|
+
return this.transformFeedback.getBuffer(varyingName);
|
|
2888
|
+
}
|
|
2889
|
+
/** @deprecated App knows what buffers it is passing in - Reads the {@link Buffer} or {@link BufferRange} for given varying name. */
|
|
2890
|
+
readAsync(varyingName) {
|
|
2891
|
+
const result = this.getBuffer(varyingName);
|
|
2892
|
+
if (!result) {
|
|
2893
|
+
throw new Error("BufferTransform#getBuffer");
|
|
2894
|
+
}
|
|
2895
|
+
if (result instanceof import_core10.Buffer) {
|
|
2896
|
+
return result.readAsync();
|
|
2897
|
+
}
|
|
2898
|
+
const { buffer, byteOffset = 0, byteLength = buffer.byteLength } = result;
|
|
2899
|
+
return buffer.readAsync(byteOffset, byteLength);
|
|
2900
|
+
}
|
|
2901
|
+
};
|
|
2902
|
+
var BufferTransform = _BufferTransform;
|
|
2903
|
+
__publicField(BufferTransform, "defaultProps", {
|
|
2904
|
+
...Model.defaultProps,
|
|
2905
|
+
outputs: void 0,
|
|
2906
|
+
feedbackBuffers: void 0
|
|
2907
|
+
});
|
|
2908
|
+
|
|
2909
|
+
// dist/compute/texture-transform.js
|
|
2910
|
+
var import_shadertools4 = require("@luma.gl/shadertools");
|
|
2911
|
+
var FS_OUTPUT_VARIABLE = "transform_output";
|
|
2912
|
+
var TextureTransform = class {
|
|
2913
|
+
device;
|
|
2914
|
+
model;
|
|
2915
|
+
sampler;
|
|
2916
|
+
currentIndex = 0;
|
|
2917
|
+
samplerTextureMap = null;
|
|
2918
|
+
bindings = [];
|
|
2724
2919
|
// each element is an object : {sourceTextures, targetTexture, framebuffer}
|
|
2725
2920
|
resources = {};
|
|
2726
2921
|
// resources to be deleted
|
|
@@ -3096,45 +3291,676 @@ var BackgroundTextureModel = class extends ClipSpace {
|
|
|
3096
3291
|
}
|
|
3097
3292
|
};
|
|
3098
3293
|
|
|
3099
|
-
// dist/
|
|
3100
|
-
var
|
|
3101
|
-
function assert(condition, message) {
|
|
3102
|
-
if (!condition) {
|
|
3103
|
-
throw new Error(message);
|
|
3104
|
-
}
|
|
3105
|
-
}
|
|
3106
|
-
var ScenegraphNode = class {
|
|
3107
|
-
id;
|
|
3108
|
-
matrix = new import_core12.Matrix4();
|
|
3109
|
-
display = true;
|
|
3110
|
-
position = new import_core12.Vector3();
|
|
3111
|
-
rotation = new import_core12.Vector3();
|
|
3112
|
-
scale = new import_core12.Vector3(1, 1, 1);
|
|
3113
|
-
userData = {};
|
|
3114
|
-
props = {};
|
|
3294
|
+
// dist/geometries/sphere-geometry.js
|
|
3295
|
+
var SphereGeometry = class extends Geometry {
|
|
3115
3296
|
constructor(props = {}) {
|
|
3116
|
-
const { id } = props;
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
/** @deprecated use .destroy() */
|
|
3126
|
-
delete() {
|
|
3127
|
-
this.destroy();
|
|
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
|
+
});
|
|
3128
3306
|
}
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
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
|
+
}
|
|
3132
3349
|
}
|
|
3133
|
-
|
|
3134
|
-
|
|
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
|
+
}
|
|
3135
3361
|
}
|
|
3136
|
-
|
|
3137
|
-
|
|
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
|
+
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;
|
|
3958
|
+
}
|
|
3959
|
+
toString() {
|
|
3960
|
+
return `{type: ScenegraphNode, id: ${this.id})}`;
|
|
3961
|
+
}
|
|
3962
|
+
setPosition(position) {
|
|
3963
|
+
assert(position.length === 3, "setPosition requires vector argument");
|
|
3138
3964
|
this.position = position;
|
|
3139
3965
|
return this;
|
|
3140
3966
|
}
|
|
@@ -3374,121 +4200,6 @@ var ModelNode = class extends ScenegraphNode {
|
|
|
3374
4200
|
}
|
|
3375
4201
|
};
|
|
3376
4202
|
|
|
3377
|
-
// dist/geometries/truncated-cone-geometry.js
|
|
3378
|
-
var INDEX_OFFSETS = {
|
|
3379
|
-
x: [2, 0, 1],
|
|
3380
|
-
y: [0, 1, 2],
|
|
3381
|
-
z: [1, 2, 0]
|
|
3382
|
-
};
|
|
3383
|
-
var TruncatedConeGeometry = class extends Geometry {
|
|
3384
|
-
constructor(props = {}) {
|
|
3385
|
-
const { id = uid("truncated-code-geometry") } = props;
|
|
3386
|
-
const { indices, attributes } = tesselateTruncatedCone(props);
|
|
3387
|
-
super({
|
|
3388
|
-
...props,
|
|
3389
|
-
id,
|
|
3390
|
-
topology: "triangle-list",
|
|
3391
|
-
indices,
|
|
3392
|
-
attributes: {
|
|
3393
|
-
POSITION: { size: 3, value: attributes.POSITION },
|
|
3394
|
-
NORMAL: { size: 3, value: attributes.NORMAL },
|
|
3395
|
-
TEXCOORD_0: { size: 2, value: attributes.TEXCOORD_0 },
|
|
3396
|
-
...props.attributes
|
|
3397
|
-
}
|
|
3398
|
-
});
|
|
3399
|
-
}
|
|
3400
|
-
};
|
|
3401
|
-
function tesselateTruncatedCone(props = {}) {
|
|
3402
|
-
const { bottomRadius = 0, topRadius = 0, height = 1, nradial = 10, nvertical = 10, verticalAxis = "y", topCap = false, bottomCap = false } = props;
|
|
3403
|
-
const extra = (topCap ? 2 : 0) + (bottomCap ? 2 : 0);
|
|
3404
|
-
const numVertices = (nradial + 1) * (nvertical + 1 + extra);
|
|
3405
|
-
const slant = Math.atan2(bottomRadius - topRadius, height);
|
|
3406
|
-
const msin = Math.sin;
|
|
3407
|
-
const mcos = Math.cos;
|
|
3408
|
-
const mpi = Math.PI;
|
|
3409
|
-
const cosSlant = mcos(slant);
|
|
3410
|
-
const sinSlant = msin(slant);
|
|
3411
|
-
const start = topCap ? -2 : 0;
|
|
3412
|
-
const end = nvertical + (bottomCap ? 2 : 0);
|
|
3413
|
-
const vertsAroundEdge = nradial + 1;
|
|
3414
|
-
const indices = new Uint16Array(nradial * (nvertical + extra) * 6);
|
|
3415
|
-
const indexOffset = INDEX_OFFSETS[verticalAxis];
|
|
3416
|
-
const positions = new Float32Array(numVertices * 3);
|
|
3417
|
-
const normals = new Float32Array(numVertices * 3);
|
|
3418
|
-
const texCoords = new Float32Array(numVertices * 2);
|
|
3419
|
-
let i3 = 0;
|
|
3420
|
-
let i2 = 0;
|
|
3421
|
-
for (let i = start; i <= end; i++) {
|
|
3422
|
-
let v = i / nvertical;
|
|
3423
|
-
let y = height * v;
|
|
3424
|
-
let ringRadius;
|
|
3425
|
-
if (i < 0) {
|
|
3426
|
-
y = 0;
|
|
3427
|
-
v = 1;
|
|
3428
|
-
ringRadius = bottomRadius;
|
|
3429
|
-
} else if (i > nvertical) {
|
|
3430
|
-
y = height;
|
|
3431
|
-
v = 1;
|
|
3432
|
-
ringRadius = topRadius;
|
|
3433
|
-
} else {
|
|
3434
|
-
ringRadius = bottomRadius + (topRadius - bottomRadius) * (i / nvertical);
|
|
3435
|
-
}
|
|
3436
|
-
if (i === -2 || i === nvertical + 2) {
|
|
3437
|
-
ringRadius = 0;
|
|
3438
|
-
v = 0;
|
|
3439
|
-
}
|
|
3440
|
-
y -= height / 2;
|
|
3441
|
-
for (let j = 0; j < vertsAroundEdge; j++) {
|
|
3442
|
-
const sin = msin(j * mpi * 2 / nradial);
|
|
3443
|
-
const cos = mcos(j * mpi * 2 / nradial);
|
|
3444
|
-
positions[i3 + indexOffset[0]] = sin * ringRadius;
|
|
3445
|
-
positions[i3 + indexOffset[1]] = y;
|
|
3446
|
-
positions[i3 + indexOffset[2]] = cos * ringRadius;
|
|
3447
|
-
normals[i3 + indexOffset[0]] = i < 0 || i > nvertical ? 0 : sin * cosSlant;
|
|
3448
|
-
normals[i3 + indexOffset[1]] = i < 0 ? -1 : i > nvertical ? 1 : sinSlant;
|
|
3449
|
-
normals[i3 + indexOffset[2]] = i < 0 || i > nvertical ? 0 : cos * cosSlant;
|
|
3450
|
-
texCoords[i2 + 0] = j / nradial;
|
|
3451
|
-
texCoords[i2 + 1] = v;
|
|
3452
|
-
i2 += 2;
|
|
3453
|
-
i3 += 3;
|
|
3454
|
-
}
|
|
3455
|
-
}
|
|
3456
|
-
for (let i = 0; i < nvertical + extra; i++) {
|
|
3457
|
-
for (let j = 0; j < nradial; j++) {
|
|
3458
|
-
const index = (i * nradial + j) * 6;
|
|
3459
|
-
indices[index + 0] = vertsAroundEdge * (i + 0) + 0 + j;
|
|
3460
|
-
indices[index + 1] = vertsAroundEdge * (i + 0) + 1 + j;
|
|
3461
|
-
indices[index + 2] = vertsAroundEdge * (i + 1) + 1 + j;
|
|
3462
|
-
indices[index + 3] = vertsAroundEdge * (i + 0) + 0 + j;
|
|
3463
|
-
indices[index + 4] = vertsAroundEdge * (i + 1) + 1 + j;
|
|
3464
|
-
indices[index + 5] = vertsAroundEdge * (i + 1) + 0 + j;
|
|
3465
|
-
}
|
|
3466
|
-
}
|
|
3467
|
-
return {
|
|
3468
|
-
indices,
|
|
3469
|
-
attributes: {
|
|
3470
|
-
POSITION: positions,
|
|
3471
|
-
NORMAL: normals,
|
|
3472
|
-
TEXCOORD_0: texCoords
|
|
3473
|
-
}
|
|
3474
|
-
};
|
|
3475
|
-
}
|
|
3476
|
-
|
|
3477
|
-
// dist/geometries/cone-geometry.js
|
|
3478
|
-
var ConeGeometry = class extends TruncatedConeGeometry {
|
|
3479
|
-
constructor(props = {}) {
|
|
3480
|
-
const { id = uid("cone-geometry"), radius = 1, cap = true } = props;
|
|
3481
|
-
super({
|
|
3482
|
-
...props,
|
|
3483
|
-
id,
|
|
3484
|
-
topRadius: 0,
|
|
3485
|
-
topCap: Boolean(cap),
|
|
3486
|
-
bottomCap: Boolean(cap),
|
|
3487
|
-
bottomRadius: radius
|
|
3488
|
-
});
|
|
3489
|
-
}
|
|
3490
|
-
};
|
|
3491
|
-
|
|
3492
4203
|
// dist/geometries/cube-geometry.js
|
|
3493
4204
|
var CubeGeometry = class extends Geometry {
|
|
3494
4205
|
constructor(props = {}) {
|
|
@@ -4378,84 +5089,6 @@ function tesselatePlane(props) {
|
|
|
4378
5089
|
return unpack ? unpackIndexedGeometry(geometry) : geometry;
|
|
4379
5090
|
}
|
|
4380
5091
|
|
|
4381
|
-
// dist/geometries/sphere-geometry.js
|
|
4382
|
-
var SphereGeometry = class extends Geometry {
|
|
4383
|
-
constructor(props = {}) {
|
|
4384
|
-
const { id = uid("sphere-geometry") } = props;
|
|
4385
|
-
const { indices, attributes } = tesselateSphere(props);
|
|
4386
|
-
super({
|
|
4387
|
-
...props,
|
|
4388
|
-
id,
|
|
4389
|
-
topology: "triangle-list",
|
|
4390
|
-
indices,
|
|
4391
|
-
attributes: { ...attributes, ...props.attributes }
|
|
4392
|
-
});
|
|
4393
|
-
}
|
|
4394
|
-
};
|
|
4395
|
-
function tesselateSphere(props) {
|
|
4396
|
-
const { nlat = 10, nlong = 10 } = props;
|
|
4397
|
-
const startLat = 0;
|
|
4398
|
-
const endLat = Math.PI;
|
|
4399
|
-
const latRange = endLat - startLat;
|
|
4400
|
-
const startLong = 0;
|
|
4401
|
-
const endLong = 2 * Math.PI;
|
|
4402
|
-
const longRange = endLong - startLong;
|
|
4403
|
-
const numVertices = (nlat + 1) * (nlong + 1);
|
|
4404
|
-
const radius = (n1, n2, n3, u, v) => props.radius || 1;
|
|
4405
|
-
const positions = new Float32Array(numVertices * 3);
|
|
4406
|
-
const normals = new Float32Array(numVertices * 3);
|
|
4407
|
-
const texCoords = new Float32Array(numVertices * 2);
|
|
4408
|
-
const IndexType = numVertices > 65535 ? Uint32Array : Uint16Array;
|
|
4409
|
-
const indices = new IndexType(nlat * nlong * 6);
|
|
4410
|
-
for (let y = 0; y <= nlat; y++) {
|
|
4411
|
-
for (let x = 0; x <= nlong; x++) {
|
|
4412
|
-
const u = x / nlong;
|
|
4413
|
-
const v = y / nlat;
|
|
4414
|
-
const index = x + y * (nlong + 1);
|
|
4415
|
-
const i2 = index * 2;
|
|
4416
|
-
const i3 = index * 3;
|
|
4417
|
-
const theta = longRange * u;
|
|
4418
|
-
const phi = latRange * v;
|
|
4419
|
-
const sinTheta = Math.sin(theta);
|
|
4420
|
-
const cosTheta = Math.cos(theta);
|
|
4421
|
-
const sinPhi = Math.sin(phi);
|
|
4422
|
-
const cosPhi = Math.cos(phi);
|
|
4423
|
-
const ux = cosTheta * sinPhi;
|
|
4424
|
-
const uy = cosPhi;
|
|
4425
|
-
const uz = sinTheta * sinPhi;
|
|
4426
|
-
const r = radius(ux, uy, uz, u, v);
|
|
4427
|
-
positions[i3 + 0] = r * ux;
|
|
4428
|
-
positions[i3 + 1] = r * uy;
|
|
4429
|
-
positions[i3 + 2] = r * uz;
|
|
4430
|
-
normals[i3 + 0] = ux;
|
|
4431
|
-
normals[i3 + 1] = uy;
|
|
4432
|
-
normals[i3 + 2] = uz;
|
|
4433
|
-
texCoords[i2 + 0] = u;
|
|
4434
|
-
texCoords[i2 + 1] = 1 - v;
|
|
4435
|
-
}
|
|
4436
|
-
}
|
|
4437
|
-
const numVertsAround = nlong + 1;
|
|
4438
|
-
for (let x = 0; x < nlong; x++) {
|
|
4439
|
-
for (let y = 0; y < nlat; y++) {
|
|
4440
|
-
const index = (x * nlat + y) * 6;
|
|
4441
|
-
indices[index + 0] = y * numVertsAround + x;
|
|
4442
|
-
indices[index + 1] = y * numVertsAround + x + 1;
|
|
4443
|
-
indices[index + 2] = (y + 1) * numVertsAround + x;
|
|
4444
|
-
indices[index + 3] = (y + 1) * numVertsAround + x;
|
|
4445
|
-
indices[index + 4] = y * numVertsAround + x + 1;
|
|
4446
|
-
indices[index + 5] = (y + 1) * numVertsAround + x + 1;
|
|
4447
|
-
}
|
|
4448
|
-
}
|
|
4449
|
-
return {
|
|
4450
|
-
indices: { size: 1, value: indices },
|
|
4451
|
-
attributes: {
|
|
4452
|
-
POSITION: { size: 3, value: positions },
|
|
4453
|
-
NORMAL: { size: 3, value: normals },
|
|
4454
|
-
TEXCOORD_0: { size: 2, value: texCoords }
|
|
4455
|
-
}
|
|
4456
|
-
};
|
|
4457
|
-
}
|
|
4458
|
-
|
|
4459
5092
|
// dist/application-utils/random.js
|
|
4460
5093
|
function makeRandomGenerator() {
|
|
4461
5094
|
let s = 1;
|
|
@@ -4865,7 +5498,7 @@ var _Computation = class {
|
|
|
4865
5498
|
props;
|
|
4866
5499
|
_destroyed = false;
|
|
4867
5500
|
constructor(device, props) {
|
|
4868
|
-
var _a, _b, _c;
|
|
5501
|
+
var _a, _b, _c, _d;
|
|
4869
5502
|
if (device.type !== "webgpu") {
|
|
4870
5503
|
throw new Error("Computation is only supported in WebGPU");
|
|
4871
5504
|
}
|
|
@@ -4877,11 +5510,11 @@ var _Computation = class {
|
|
|
4877
5510
|
const moduleMap = Object.fromEntries(((_a = this.props.modules) == null ? void 0 : _a.map((module2) => [module2.name, module2])) || []);
|
|
4878
5511
|
this.shaderInputs = props.shaderInputs || new ShaderInputs(moduleMap);
|
|
4879
5512
|
this.setShaderInputs(this.shaderInputs);
|
|
4880
|
-
this.props.shaderLayout ||= device.getShaderLayout(this.props.source);
|
|
4881
5513
|
const platformInfo = getPlatformInfo2(device);
|
|
4882
5514
|
const modules = (((_b = this.props.modules) == null ? void 0 : _b.length) > 0 ? this.props.modules : (_c = this.shaderInputs) == null ? void 0 : _c.getModules()) || [];
|
|
4883
|
-
this.
|
|
4884
|
-
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);
|
|
4885
5518
|
const { source: source3, getUniforms: getUniforms2 } = this.props.shaderAssembler.assembleWGSLShader({
|
|
4886
5519
|
platformInfo,
|
|
4887
5520
|
...this.props,
|
|
@@ -4889,6 +5522,8 @@ var _Computation = class {
|
|
|
4889
5522
|
});
|
|
4890
5523
|
this.source = source3;
|
|
4891
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;
|
|
4892
5527
|
this.pipeline = this._updatePipeline();
|
|
4893
5528
|
if (props.bindings) {
|
|
4894
5529
|
this.setBindings(props.bindings);
|
|
@@ -4913,7 +5548,7 @@ var _Computation = class {
|
|
|
4913
5548
|
this.pipeline = this._updatePipeline();
|
|
4914
5549
|
this.pipeline.setBindings(this.bindings);
|
|
4915
5550
|
computePass.setPipeline(this.pipeline);
|
|
4916
|
-
computePass.setBindings(
|
|
5551
|
+
computePass.setBindings({});
|
|
4917
5552
|
computePass.dispatch(x, y, z);
|
|
4918
5553
|
} finally {
|
|
4919
5554
|
this._logDrawCallEnd();
|
|
@@ -4936,9 +5571,11 @@ var _Computation = class {
|
|
|
4936
5571
|
setShaderInputs(shaderInputs) {
|
|
4937
5572
|
this.shaderInputs = shaderInputs;
|
|
4938
5573
|
this._uniformStore = new import_core17.UniformStore(this.shaderInputs.modules);
|
|
4939
|
-
for (const moduleName of Object.
|
|
4940
|
-
|
|
4941
|
-
|
|
5574
|
+
for (const [moduleName, module2] of Object.entries(this.shaderInputs.modules)) {
|
|
5575
|
+
if (shaderModuleHasUniforms(module2)) {
|
|
5576
|
+
const uniformBuffer = this._uniformStore.getManagedUniformBuffer(this.device, moduleName);
|
|
5577
|
+
this.bindings[`${moduleName}Uniforms`] = uniformBuffer;
|
|
5578
|
+
}
|
|
4942
5579
|
}
|
|
4943
5580
|
}
|
|
4944
5581
|
/**
|
|
@@ -5015,7 +5652,7 @@ var _Computation = class {
|
|
|
5015
5652
|
_drawCount = 0;
|
|
5016
5653
|
// TODO - fix typing of luma data types
|
|
5017
5654
|
_getBufferOrConstantValues(attribute, dataType) {
|
|
5018
|
-
const TypedArrayConstructor =
|
|
5655
|
+
const TypedArrayConstructor = import_core17.dataTypeDecoder.getTypedArrayConstructor(dataType);
|
|
5019
5656
|
const typedArray = attribute instanceof import_core17.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
|
|
5020
5657
|
return typedArray.toString();
|
|
5021
5658
|
}
|
|
@@ -5047,6 +5684,9 @@ function getPlatformInfo2(device) {
|
|
|
5047
5684
|
};
|
|
5048
5685
|
}
|
|
5049
5686
|
|
|
5687
|
+
// dist/modules/picking/picking-manager.js
|
|
5688
|
+
var import_core18 = require("@luma.gl/core");
|
|
5689
|
+
|
|
5050
5690
|
// dist/modules/picking/picking-uniforms.js
|
|
5051
5691
|
var DEFAULT_HIGHLIGHT_COLOR = [0, 1, 1, 1];
|
|
5052
5692
|
var INVALID_INDEX = -1;
|
|
@@ -5079,15 +5719,17 @@ uniform pickingUniforms {
|
|
|
5079
5719
|
var WGSL_UNIFORMS = (
|
|
5080
5720
|
/* wgsl */
|
|
5081
5721
|
`struct pickingUniforms {
|
|
5082
|
-
isActive:
|
|
5083
|
-
indexMode:
|
|
5084
|
-
batchIndex:
|
|
5085
|
-
|
|
5086
|
-
isHighlightActive:
|
|
5087
|
-
highlightedBatchIndex:
|
|
5088
|
-
highlightedObjectIndex:
|
|
5089
|
-
highlightColor: vec4<f32
|
|
5090
|
-
}
|
|
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;
|
|
5091
5733
|
`
|
|
5092
5734
|
);
|
|
5093
5735
|
function getUniforms(props = {}, prevUniforms) {
|
|
@@ -5099,25 +5741,36 @@ function getUniforms(props = {}, prevUniforms) {
|
|
|
5099
5741
|
case "instance":
|
|
5100
5742
|
uniforms.indexMode = 0;
|
|
5101
5743
|
break;
|
|
5102
|
-
case "
|
|
5744
|
+
case "attribute":
|
|
5103
5745
|
uniforms.indexMode = 1;
|
|
5104
5746
|
break;
|
|
5105
5747
|
case void 0:
|
|
5106
5748
|
break;
|
|
5107
5749
|
}
|
|
5108
|
-
|
|
5750
|
+
if (typeof props.batchIndex === "number") {
|
|
5751
|
+
uniforms.batchIndex = props.batchIndex;
|
|
5752
|
+
}
|
|
5753
|
+
switch (props.highlightedObjectIndex) {
|
|
5754
|
+
case void 0:
|
|
5755
|
+
break;
|
|
5756
|
+
case null:
|
|
5757
|
+
uniforms.isHighlightActive = false;
|
|
5758
|
+
uniforms.highlightedObjectIndex = INVALID_INDEX;
|
|
5759
|
+
break;
|
|
5760
|
+
default:
|
|
5761
|
+
uniforms.isHighlightActive = true;
|
|
5762
|
+
uniforms.highlightedObjectIndex = props.highlightedObjectIndex;
|
|
5763
|
+
}
|
|
5764
|
+
switch (props.highlightedBatchIndex) {
|
|
5109
5765
|
case void 0:
|
|
5110
5766
|
break;
|
|
5111
5767
|
case null:
|
|
5112
5768
|
uniforms.isHighlightActive = false;
|
|
5113
|
-
uniforms.
|
|
5769
|
+
uniforms.highlightedBatchIndex = INVALID_INDEX;
|
|
5114
5770
|
break;
|
|
5115
5771
|
default:
|
|
5116
5772
|
uniforms.isHighlightActive = true;
|
|
5117
|
-
uniforms.
|
|
5118
|
-
}
|
|
5119
|
-
if (typeof props.highlightedBatchIndex === "number") {
|
|
5120
|
-
uniforms.highlightedBatchIndex = props.highlightedBatchIndex;
|
|
5773
|
+
uniforms.highlightedBatchIndex = props.highlightedBatchIndex;
|
|
5121
5774
|
}
|
|
5122
5775
|
if (props.highlightColor) {
|
|
5123
5776
|
uniforms.highlightColor = props.highlightColor;
|
|
@@ -5133,7 +5786,7 @@ var pickingUniforms = {
|
|
|
5133
5786
|
isActive: false,
|
|
5134
5787
|
indexMode: 0,
|
|
5135
5788
|
batchIndex: 0,
|
|
5136
|
-
isHighlightActive:
|
|
5789
|
+
isHighlightActive: false,
|
|
5137
5790
|
highlightedBatchIndex: INVALID_INDEX,
|
|
5138
5791
|
highlightedObjectIndex: INVALID_INDEX,
|
|
5139
5792
|
highlightColor: DEFAULT_HIGHLIGHT_COLOR
|
|
@@ -5142,9 +5795,42 @@ var pickingUniforms = {
|
|
|
5142
5795
|
};
|
|
5143
5796
|
|
|
5144
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
|
+
}
|
|
5145
5830
|
var _PickingManager = class {
|
|
5146
5831
|
device;
|
|
5147
5832
|
props;
|
|
5833
|
+
mode;
|
|
5148
5834
|
/** Info from latest pick operation */
|
|
5149
5835
|
pickInfo = { batchIndex: null, objectIndex: null };
|
|
5150
5836
|
/** Framebuffer used for picking */
|
|
@@ -5152,6 +5838,10 @@ var _PickingManager = class {
|
|
|
5152
5838
|
constructor(device, props) {
|
|
5153
5839
|
this.device = device;
|
|
5154
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));
|
|
5155
5845
|
}
|
|
5156
5846
|
destroy() {
|
|
5157
5847
|
var _a;
|
|
@@ -5160,58 +5850,44 @@ var _PickingManager = class {
|
|
|
5160
5850
|
// TODO - Ask for a cached framebuffer? a Framebuffer factory?
|
|
5161
5851
|
getFramebuffer() {
|
|
5162
5852
|
if (!this.framebuffer) {
|
|
5163
|
-
this.framebuffer = this.
|
|
5164
|
-
colorAttachments: ["rgba8unorm", "rg32sint"],
|
|
5165
|
-
depthStencilAttachment: "depth24plus"
|
|
5166
|
-
});
|
|
5853
|
+
this.framebuffer = this.mode === "index" ? this.createIndexFramebuffer() : this.createColorFramebuffer();
|
|
5167
5854
|
}
|
|
5168
5855
|
return this.framebuffer;
|
|
5169
5856
|
}
|
|
5170
5857
|
/** Clear highlighted / picked object */
|
|
5171
5858
|
clearPickState() {
|
|
5172
|
-
this.
|
|
5859
|
+
this.setPickingProps({ highlightedBatchIndex: null, highlightedObjectIndex: null });
|
|
5173
5860
|
}
|
|
5174
5861
|
/** Prepare for rendering picking colors */
|
|
5175
5862
|
beginRenderPass() {
|
|
5176
|
-
var _a;
|
|
5177
5863
|
const framebuffer = this.getFramebuffer();
|
|
5178
5864
|
framebuffer.resize(this.device.getDefaultCanvasContext().getDevicePixelSize());
|
|
5179
|
-
|
|
5180
|
-
|
|
5865
|
+
this.setPickingProps({ isActive: true });
|
|
5866
|
+
return this.mode === "index" ? this.device.beginRenderPass({
|
|
5181
5867
|
framebuffer,
|
|
5182
|
-
clearColors: [new Float32Array([0, 0, 0, 0]),
|
|
5868
|
+
clearColors: [new Float32Array([0, 0, 0, 0]), INDEX_PICKING_CLEAR_COLOR],
|
|
5869
|
+
clearDepth: 1
|
|
5870
|
+
}) : this.device.beginRenderPass({
|
|
5871
|
+
framebuffer,
|
|
5872
|
+
clearColor: [0, 0, 0, 0],
|
|
5183
5873
|
clearDepth: 1
|
|
5184
5874
|
});
|
|
5185
|
-
return pickingPass;
|
|
5186
5875
|
}
|
|
5187
5876
|
async updatePickInfo(mousePosition) {
|
|
5188
|
-
var _a;
|
|
5189
5877
|
const framebuffer = this.getFramebuffer();
|
|
5190
|
-
const
|
|
5191
|
-
const
|
|
5192
|
-
|
|
5193
|
-
sourceY: pickY,
|
|
5194
|
-
sourceWidth: 1,
|
|
5195
|
-
sourceHeight: 1,
|
|
5196
|
-
sourceAttachment: 1
|
|
5197
|
-
});
|
|
5198
|
-
if (!pixelData) {
|
|
5878
|
+
const pickPosition = this.getPickPosition(mousePosition);
|
|
5879
|
+
const pickInfo = await this.readPickInfo(framebuffer, pickPosition);
|
|
5880
|
+
if (!pickInfo) {
|
|
5199
5881
|
return null;
|
|
5200
5882
|
}
|
|
5201
|
-
|
|
5202
|
-
objectIndex: pixelData[0] === INVALID_INDEX ? null : pixelData[0],
|
|
5203
|
-
batchIndex: pixelData[1] === INVALID_INDEX ? null : pixelData[1]
|
|
5204
|
-
};
|
|
5205
|
-
if (pickInfo.objectIndex !== this.pickInfo.objectIndex || pickInfo.batchIndex !== this.pickInfo.batchIndex) {
|
|
5883
|
+
if (this.hasPickInfoChanged(pickInfo)) {
|
|
5206
5884
|
this.pickInfo = pickInfo;
|
|
5207
5885
|
this.props.onObjectPicked(pickInfo);
|
|
5208
5886
|
}
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
|
|
5212
|
-
|
|
5213
|
-
highlightedObjectIndex: pickInfo.objectIndex
|
|
5214
|
-
}
|
|
5887
|
+
this.setPickingProps({
|
|
5888
|
+
isActive: false,
|
|
5889
|
+
highlightedBatchIndex: pickInfo.batchIndex,
|
|
5890
|
+
highlightedObjectIndex: pickInfo.objectIndex
|
|
5215
5891
|
});
|
|
5216
5892
|
return this.pickInfo;
|
|
5217
5893
|
}
|
|
@@ -5220,43 +5896,204 @@ var _PickingManager = class {
|
|
|
5220
5896
|
* use the center pixel location in device pixel range
|
|
5221
5897
|
*/
|
|
5222
5898
|
getPickPosition(mousePosition) {
|
|
5223
|
-
const
|
|
5899
|
+
const yInvert = this.device.type !== "webgpu";
|
|
5900
|
+
const devicePixels = this.device.getDefaultCanvasContext().cssToDevicePixels(mousePosition, yInvert);
|
|
5224
5901
|
const pickX = devicePixels.x + Math.floor(devicePixels.width / 2);
|
|
5225
5902
|
const pickY = devicePixels.y + Math.floor(devicePixels.height / 2);
|
|
5226
5903
|
return [pickX, pickY];
|
|
5227
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
|
+
}
|
|
5228
6013
|
};
|
|
5229
6014
|
var PickingManager = _PickingManager;
|
|
5230
6015
|
__publicField(PickingManager, "defaultProps", {
|
|
5231
6016
|
shaderInputs: void 0,
|
|
5232
6017
|
onObjectPicked: () => {
|
|
5233
|
-
}
|
|
6018
|
+
},
|
|
6019
|
+
mode: "color",
|
|
6020
|
+
backend: "color"
|
|
5234
6021
|
});
|
|
5235
6022
|
|
|
5236
|
-
// dist/modules/picking/
|
|
6023
|
+
// dist/modules/picking/color-picking.js
|
|
5237
6024
|
var source = (
|
|
5238
6025
|
/* wgsl */
|
|
5239
6026
|
`${WGSL_UNIFORMS}
|
|
5240
6027
|
|
|
5241
|
-
const
|
|
5242
|
-
const
|
|
5243
|
-
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;
|
|
5244
6031
|
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
fn
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
6032
|
+
fn picking_setObjectIndex(objectIndex: i32) -> i32 {
|
|
6033
|
+
return objectIndex;
|
|
6034
|
+
}
|
|
6035
|
+
|
|
6036
|
+
fn picking_isObjectHighlighted(objectIndex: i32) -> bool {
|
|
6037
|
+
return
|
|
6038
|
+
picking.isHighlightActive != 0 &&
|
|
6039
|
+
picking.highlightedBatchIndex == picking.batchIndex &&
|
|
6040
|
+
picking.highlightedObjectIndex == objectIndex;
|
|
6041
|
+
}
|
|
6042
|
+
|
|
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);
|
|
5257
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
|
+
);
|
|
5258
6085
|
}
|
|
5259
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
|
+
}
|
|
5260
6097
|
`
|
|
5261
6098
|
);
|
|
5262
6099
|
var vs = (
|
|
@@ -5266,14 +6103,10 @@ var vs = (
|
|
|
5266
6103
|
const int INDEX_PICKING_MODE_INSTANCE = 0;
|
|
5267
6104
|
const int INDEX_PICKING_MODE_CUSTOM = 1;
|
|
5268
6105
|
|
|
5269
|
-
const int
|
|
6106
|
+
const int COLOR_PICKING_INVALID_INDEX = ${INVALID_INDEX};
|
|
5270
6107
|
|
|
5271
6108
|
flat out int picking_objectIndex;
|
|
5272
6109
|
|
|
5273
|
-
/**
|
|
5274
|
-
* Vertex shaders should call this function to set the object index.
|
|
5275
|
-
* If using instance or vertex mode, argument will be ignored, 0 can be supplied.
|
|
5276
|
-
*/
|
|
5277
6110
|
void picking_setObjectIndex(int objectIndex) {
|
|
5278
6111
|
switch (picking.indexMode) {
|
|
5279
6112
|
case INDEX_PICKING_MODE_INSTANCE:
|
|
@@ -5290,36 +6123,29 @@ var fs = (
|
|
|
5290
6123
|
/* glsl */
|
|
5291
6124
|
`${GLSL_UNIFORMS}
|
|
5292
6125
|
|
|
5293
|
-
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;
|
|
5294
6129
|
|
|
5295
6130
|
flat in int picking_objectIndex;
|
|
5296
6131
|
|
|
5297
|
-
/**
|
|
5298
|
-
* Check if this vertex is highlighted (part of the selected batch and object)
|
|
5299
|
-
*/
|
|
5300
6132
|
bool picking_isFragmentHighlighted() {
|
|
5301
|
-
return
|
|
6133
|
+
return
|
|
5302
6134
|
bool(picking.isHighlightActive) &&
|
|
5303
6135
|
picking.highlightedBatchIndex == picking.batchIndex &&
|
|
5304
6136
|
picking.highlightedObjectIndex == picking_objectIndex
|
|
5305
6137
|
;
|
|
5306
6138
|
}
|
|
5307
6139
|
|
|
5308
|
-
/**
|
|
5309
|
-
* Returns highlight color if this item is selected.
|
|
5310
|
-
*/
|
|
5311
6140
|
vec4 picking_filterHighlightColor(vec4 color) {
|
|
5312
|
-
// If we are still picking, we don't highlight
|
|
5313
6141
|
if (bool(picking.isActive)) {
|
|
5314
6142
|
return color;
|
|
5315
6143
|
}
|
|
5316
6144
|
|
|
5317
|
-
// If we are not highlighted, return color as is
|
|
5318
6145
|
if (!picking_isFragmentHighlighted()) {
|
|
5319
6146
|
return color;
|
|
5320
6147
|
}
|
|
5321
|
-
|
|
5322
|
-
// Blend in highlight color based on its alpha value
|
|
6148
|
+
|
|
5323
6149
|
float highLightAlpha = picking.highlightColor.a;
|
|
5324
6150
|
float blendedAlpha = highLightAlpha + color.a * (1.0 - highLightAlpha);
|
|
5325
6151
|
float highLightRatio = highLightAlpha / blendedAlpha;
|
|
@@ -5328,28 +6154,40 @@ vec4 picking_filterHighlightColor(vec4 color) {
|
|
|
5328
6154
|
return vec4(blendedRGB, blendedAlpha);
|
|
5329
6155
|
}
|
|
5330
6156
|
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
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;
|
|
5338
6178
|
}
|
|
5339
6179
|
|
|
5340
6180
|
vec4 picking_filterPickingColor(vec4 color) {
|
|
5341
6181
|
if (bool(picking.isActive)) {
|
|
5342
|
-
if (picking_objectIndex
|
|
6182
|
+
if (!picking_canEncodePickInfo(picking_objectIndex)) {
|
|
5343
6183
|
discard;
|
|
5344
6184
|
}
|
|
6185
|
+
return picking_getPickingColor();
|
|
5345
6186
|
}
|
|
6187
|
+
|
|
5346
6188
|
return color;
|
|
5347
6189
|
}
|
|
5348
6190
|
|
|
5349
|
-
/*
|
|
5350
|
-
* Returns picking color if picking is enabled if not
|
|
5351
|
-
* highlight color if this item is selected, otherwise unmodified argument.
|
|
5352
|
-
*/
|
|
5353
6191
|
vec4 picking_filterColor(vec4 color) {
|
|
5354
6192
|
vec4 outColor = color;
|
|
5355
6193
|
outColor = picking_filterHighlightColor(outColor);
|
|
@@ -5366,87 +6204,81 @@ var picking = {
|
|
|
5366
6204
|
fs
|
|
5367
6205
|
};
|
|
5368
6206
|
|
|
5369
|
-
// dist/modules/picking/
|
|
6207
|
+
// dist/modules/picking/index-picking.js
|
|
5370
6208
|
var source2 = (
|
|
5371
6209
|
/* wgsl */
|
|
5372
6210
|
`${WGSL_UNIFORMS}
|
|
5373
|
-
`
|
|
5374
|
-
);
|
|
5375
|
-
var vs2 = (
|
|
5376
|
-
/* glsl */
|
|
5377
|
-
`${GLSL_UNIFORMS}
|
|
5378
|
-
out vec4 picking_vRGBcolor_Avalid;
|
|
5379
|
-
|
|
5380
|
-
// Normalize unsigned byte color to 0-1 range
|
|
5381
|
-
vec3 picking_normalizeColor(vec3 color) {
|
|
5382
|
-
return picking.useFloatColors > 0.5 ? color : color / 255.0;
|
|
5383
|
-
}
|
|
5384
|
-
|
|
5385
|
-
// Normalize unsigned byte color to 0-1 range
|
|
5386
|
-
vec4 picking_normalizeColor(vec4 color) {
|
|
5387
|
-
return picking.useFloatColors > 0.5 ? color : color / 255.0;
|
|
5388
|
-
}
|
|
5389
6211
|
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
}
|
|
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
|
|
5393
6215
|
|
|
5394
|
-
|
|
5395
|
-
|
|
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;
|
|
5396
6221
|
}
|
|
5397
6222
|
|
|
5398
|
-
|
|
5399
|
-
bool isVertexHighlighted(vec3 vertexColor) {
|
|
5400
|
-
vec3 highlightedObjectColor = picking_normalizeColor(picking.highlightedObjectColor);
|
|
6223
|
+
fn picking_isObjectHighlighted(objectIndex: i32) -> bool {
|
|
5401
6224
|
return
|
|
5402
|
-
|
|
6225
|
+
picking.isHighlightActive != 0 &&
|
|
6226
|
+
picking.highlightedBatchIndex == picking.batchIndex &&
|
|
6227
|
+
picking.highlightedObjectIndex == objectIndex;
|
|
5403
6228
|
}
|
|
5404
6229
|
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
if (bool(picking.isActive)) {
|
|
5410
|
-
// Use alpha as the validity flag. If pickingColor is [0, 0, 0] fragment is non-pickable
|
|
5411
|
-
picking_vRGBcolor_Avalid.a = float(picking_isColorValid(pickingColor));
|
|
5412
|
-
|
|
5413
|
-
if (!bool(picking.isAttribute)) {
|
|
5414
|
-
// Stores the picking color so that the fragment shader can render it during picking
|
|
5415
|
-
picking_vRGBcolor_Avalid.rgb = pickingColor;
|
|
5416
|
-
}
|
|
5417
|
-
} else {
|
|
5418
|
-
// Do the comparison with selected item color in vertex shader as it should mean fewer compares
|
|
5419
|
-
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;
|
|
5420
6233
|
}
|
|
5421
|
-
}
|
|
5422
6234
|
|
|
5423
|
-
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
|
|
5427
|
-
index = uint(gl_InstanceID);
|
|
5428
|
-
}
|
|
5429
|
-
picking_vRGBcolor_Avalid.r = float(index % 255) / 255.0;
|
|
5430
|
-
picking_vRGBcolor_Avalid.g = float((index / 255) % 255) / 255.0;
|
|
5431
|
-
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);
|
|
5432
6239
|
}
|
|
6240
|
+
|
|
6241
|
+
let highLightRatio = highLightAlpha / blendedAlpha;
|
|
6242
|
+
let blendedRGB = mix(color.rgb, picking.highlightColor.rgb, highLightRatio);
|
|
6243
|
+
return vec4<f32>(blendedRGB, blendedAlpha);
|
|
5433
6244
|
}
|
|
5434
6245
|
|
|
5435
|
-
|
|
5436
|
-
if (
|
|
5437
|
-
|
|
6246
|
+
fn picking_filterPickingColor(color: vec4<f32>, objectIndex: i32) -> vec4<f32> {
|
|
6247
|
+
if (picking.isActive != 0 && objectIndex == INDEX_PICKING_INVALID_INDEX) {
|
|
6248
|
+
discard;
|
|
5438
6249
|
}
|
|
6250
|
+
return color;
|
|
5439
6251
|
}
|
|
5440
6252
|
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
picking_vRGBcolor_Avalid.rg = value;
|
|
5444
|
-
}
|
|
6253
|
+
fn picking_getPickingColor(objectIndex: i32) -> vec2<i32> {
|
|
6254
|
+
return vec2<i32>(objectIndex, picking.batchIndex);
|
|
5445
6255
|
}
|
|
5446
6256
|
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
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;
|
|
5450
6282
|
}
|
|
5451
6283
|
}
|
|
5452
6284
|
`
|
|
@@ -5455,41 +6287,58 @@ var fs2 = (
|
|
|
5455
6287
|
/* glsl */
|
|
5456
6288
|
`${GLSL_UNIFORMS}
|
|
5457
6289
|
|
|
5458
|
-
|
|
6290
|
+
const int INDEX_PICKING_INVALID_INDEX = ${INVALID_INDEX}; // 2^32 - 1
|
|
6291
|
+
|
|
6292
|
+
flat in int picking_objectIndex;
|
|
5459
6293
|
|
|
5460
|
-
|
|
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
|
+
/**
|
|
5461
6306
|
* Returns highlight color if this item is selected.
|
|
5462
6307
|
*/
|
|
5463
6308
|
vec4 picking_filterHighlightColor(vec4 color) {
|
|
5464
6309
|
// If we are still picking, we don't highlight
|
|
5465
|
-
if (picking.isActive
|
|
6310
|
+
if (bool(picking.isActive)) {
|
|
5466
6311
|
return color;
|
|
5467
6312
|
}
|
|
5468
6313
|
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
if (selected) {
|
|
5472
|
-
// Blend in highlight color based on its alpha value
|
|
5473
|
-
float highLightAlpha = picking.highlightColor.a;
|
|
5474
|
-
float blendedAlpha = highLightAlpha + color.a * (1.0 - highLightAlpha);
|
|
5475
|
-
float highLightRatio = highLightAlpha / blendedAlpha;
|
|
5476
|
-
|
|
5477
|
-
vec3 blendedRGB = mix(color.rgb, picking.highlightColor.rgb, highLightRatio);
|
|
5478
|
-
return vec4(blendedRGB, blendedAlpha);
|
|
5479
|
-
} else {
|
|
6314
|
+
// If we are not highlighted, return color as is
|
|
6315
|
+
if (!picking_isFragmentHighlighted()) {
|
|
5480
6316
|
return color;
|
|
5481
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);
|
|
5482
6326
|
}
|
|
5483
6327
|
|
|
5484
6328
|
/*
|
|
5485
6329
|
* Returns picking color if picking enabled else unmodified argument.
|
|
5486
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
|
+
|
|
5487
6337
|
vec4 picking_filterPickingColor(vec4 color) {
|
|
5488
6338
|
if (bool(picking.isActive)) {
|
|
5489
|
-
if (
|
|
6339
|
+
if (picking_objectIndex == INDEX_PICKING_INVALID_INDEX) {
|
|
5490
6340
|
discard;
|
|
5491
6341
|
}
|
|
5492
|
-
return picking_vRGBcolor_Avalid;
|
|
5493
6342
|
}
|
|
5494
6343
|
return color;
|
|
5495
6344
|
}
|
|
@@ -5499,8 +6348,10 @@ vec4 picking_filterPickingColor(vec4 color) {
|
|
|
5499
6348
|
* highlight color if this item is selected, otherwise unmodified argument.
|
|
5500
6349
|
*/
|
|
5501
6350
|
vec4 picking_filterColor(vec4 color) {
|
|
5502
|
-
vec4
|
|
5503
|
-
|
|
6351
|
+
vec4 outColor = color;
|
|
6352
|
+
outColor = picking_filterHighlightColor(outColor);
|
|
6353
|
+
outColor = picking_filterPickingColor(outColor);
|
|
6354
|
+
return outColor;
|
|
5504
6355
|
}
|
|
5505
6356
|
`
|
|
5506
6357
|
);
|
|
@@ -5512,6 +6363,15 @@ var picking2 = {
|
|
|
5512
6363
|
fs: fs2
|
|
5513
6364
|
};
|
|
5514
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
|
+
|
|
5515
6375
|
// dist/modules/picking/legacy-picking-manager.js
|
|
5516
6376
|
var LegacyPickingManager = class {
|
|
5517
6377
|
device;
|
|
@@ -5580,6 +6440,10 @@ var LegacyPickingManager = class {
|
|
|
5580
6440
|
}
|
|
5581
6441
|
};
|
|
5582
6442
|
|
|
6443
|
+
// dist/modules/picking/legacy-color-picking.js
|
|
6444
|
+
var import_shadertools7 = require("@luma.gl/shadertools");
|
|
6445
|
+
var legacyColorPicking = import_shadertools7.picking;
|
|
6446
|
+
|
|
5583
6447
|
// dist/index.js
|
|
5584
6448
|
var AsyncTexture = DynamicTexture;
|
|
5585
6449
|
//# sourceMappingURL=index.cjs.map
|