@onerjs/core 8.37.7 → 8.37.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.
Files changed (77) hide show
  1. package/Animations/animationGroup.d.ts +2 -3
  2. package/Animations/animationGroup.js +10 -15
  3. package/Animations/animationGroup.js.map +1 -1
  4. package/Bones/bone.d.ts +2 -0
  5. package/Bones/bone.js +2 -0
  6. package/Bones/bone.js.map +1 -1
  7. package/Bones/skeleton.js +7 -0
  8. package/Bones/skeleton.js.map +1 -1
  9. package/FrameGraph/Tasks/PostProcesses/bloomTask.js +3 -1
  10. package/FrameGraph/Tasks/PostProcesses/bloomTask.js.map +1 -1
  11. package/FrameGraph/Tasks/PostProcesses/depthOfFieldTask.js +3 -1
  12. package/FrameGraph/Tasks/PostProcesses/depthOfFieldTask.js.map +1 -1
  13. package/FrameGraph/Tasks/PostProcesses/postProcessTask.js +1 -1
  14. package/FrameGraph/Tasks/PostProcesses/postProcessTask.js.map +1 -1
  15. package/FrameGraph/Tasks/PostProcesses/ssao2RenderingPipelineTask.js +3 -1
  16. package/FrameGraph/Tasks/PostProcesses/ssao2RenderingPipelineTask.js.map +1 -1
  17. package/FrameGraph/Tasks/PostProcesses/ssrRenderingPipelineTask.js +3 -1
  18. package/FrameGraph/Tasks/PostProcesses/ssrRenderingPipelineTask.js.map +1 -1
  19. package/Layers/effectLayer.d.ts +4 -0
  20. package/Layers/effectLayer.js +2 -0
  21. package/Layers/effectLayer.js.map +1 -1
  22. package/Layers/highlightLayer.js +1 -0
  23. package/Layers/highlightLayer.js.map +1 -1
  24. package/Layers/index.d.ts +2 -0
  25. package/Layers/index.js +2 -0
  26. package/Layers/index.js.map +1 -1
  27. package/Layers/selectionOutlineLayer.d.ts +185 -0
  28. package/Layers/selectionOutlineLayer.js +326 -0
  29. package/Layers/selectionOutlineLayer.js.map +1 -0
  30. package/Layers/thinEffectLayer.d.ts +5 -1
  31. package/Layers/thinEffectLayer.js +21 -16
  32. package/Layers/thinEffectLayer.js.map +1 -1
  33. package/Layers/thinGlowLayer.js +1 -0
  34. package/Layers/thinGlowLayer.js.map +1 -1
  35. package/Layers/thinHighlightLayer.js +1 -0
  36. package/Layers/thinHighlightLayer.js.map +1 -1
  37. package/Layers/thinSelectionOutlineLayer.d.ts +154 -0
  38. package/Layers/thinSelectionOutlineLayer.js +611 -0
  39. package/Layers/thinSelectionOutlineLayer.js.map +1 -0
  40. package/Loading/Plugins/babylonFileLoader.js +136 -48
  41. package/Loading/Plugins/babylonFileLoader.js.map +1 -1
  42. package/Maths/math.vector.functions.d.ts +8 -0
  43. package/Maths/math.vector.functions.js +10 -0
  44. package/Maths/math.vector.functions.js.map +1 -1
  45. package/Meshes/abstractMesh.d.ts +4 -0
  46. package/Meshes/abstractMesh.js +4 -0
  47. package/Meshes/abstractMesh.js.map +1 -1
  48. package/Meshes/csg2.js +9 -1
  49. package/Meshes/csg2.js.map +1 -1
  50. package/Meshes/instancedMesh.js +2 -2
  51. package/Meshes/instancedMesh.js.map +1 -1
  52. package/Meshes/mesh.js +6 -1
  53. package/Meshes/mesh.js.map +1 -1
  54. package/Morph/morphTarget.js +2 -1
  55. package/Morph/morphTarget.js.map +1 -1
  56. package/Shaders/selection.fragment.d.ts +7 -0
  57. package/Shaders/selection.fragment.js +47 -0
  58. package/Shaders/selection.fragment.js.map +1 -0
  59. package/Shaders/selection.vertex.d.ts +17 -0
  60. package/Shaders/selection.vertex.js +95 -0
  61. package/Shaders/selection.vertex.js.map +1 -0
  62. package/Shaders/selectionOutline.fragment.d.ts +5 -0
  63. package/Shaders/selectionOutline.fragment.js +23 -0
  64. package/Shaders/selectionOutline.fragment.js.map +1 -0
  65. package/ShadersWGSL/selection.fragment.d.ts +7 -0
  66. package/ShadersWGSL/selection.fragment.js +47 -0
  67. package/ShadersWGSL/selection.fragment.js.map +1 -0
  68. package/ShadersWGSL/selection.vertex.d.ts +17 -0
  69. package/ShadersWGSL/selection.vertex.js +96 -0
  70. package/ShadersWGSL/selection.vertex.js.map +1 -0
  71. package/ShadersWGSL/selectionOutline.fragment.d.ts +5 -0
  72. package/ShadersWGSL/selectionOutline.fragment.js +24 -0
  73. package/ShadersWGSL/selectionOutline.fragment.js.map +1 -0
  74. package/package.json +1 -1
  75. package/scene.d.ts +2 -2
  76. package/scene.js +10 -2
  77. package/scene.js.map +1 -1
@@ -0,0 +1,611 @@
1
+ import { VertexBuffer } from "../Buffers/buffer.js";
2
+ import { Camera } from "../Cameras/camera.js";
3
+
4
+ import { AddClipPlaneUniforms, BindClipPlane, PrepareStringDefinesForClipPlanes } from "../Materials/clipPlaneMaterialHelper.js";
5
+ import { EffectFallbacks } from "../Materials/effectFallbacks.js";
6
+ import { Material } from "../Materials/material.js";
7
+ import { BindBonesParameters, BindMorphTargetParameters, PrepareDefinesAndAttributesForMorphTargets, PushAttributesForInstances } from "../Materials/materialHelper.functions.js";
8
+ import { Color3, Color4 } from "../Maths/math.color.js";
9
+ import { ThinEffectLayer } from "./thinEffectLayer.js";
10
+ /**
11
+ * @internal
12
+ */
13
+ export class ThinSelectionOutlineLayer extends ThinEffectLayer {
14
+ /**
15
+ * Instantiates a new selection outline Layer and references it to the scene..
16
+ * @param name The name of the layer
17
+ * @param scene The scene to use the layer in
18
+ * @param options Sets of none mandatory options to use with the layer (see IThinSelectionOutlineLayerOptions for more information)
19
+ * @param dontCheckIfReady Specifies if the layer should disable checking whether all the post processes are ready (default: false). To save performance, this should be set to true and you should call `isReady` manually before rendering to the layer.
20
+ */
21
+ constructor(name, scene, options, dontCheckIfReady = false) {
22
+ super(name, scene, options !== undefined ? !!options.forceGLSL : false);
23
+ /**
24
+ * The outline color
25
+ */
26
+ this.outlineColor = new Color3(1, 0.5, 0);
27
+ /**
28
+ * The thickness of the edges
29
+ */
30
+ this.outlineThickness = 2.0;
31
+ /**
32
+ * The strength of the occlusion effect (default: 0.8)
33
+ */
34
+ this.occlusionStrength = 0.8;
35
+ /**
36
+ * The occlusion threshold (default: 0.0001)
37
+ */
38
+ this.occlusionThreshold = 0.0001;
39
+ /**
40
+ * The width of the source texture
41
+ */
42
+ this.textureWidth = 0;
43
+ /**
44
+ * The height of the source texture
45
+ */
46
+ this.textureHeight = 0;
47
+ /** @internal */
48
+ this._meshUniqueIdToSelectionId = [];
49
+ /** @internal */
50
+ this._selection = [];
51
+ this._nextSelectionId = 1;
52
+ // Adapt options
53
+ this._options = {
54
+ mainTextureRatio: 1.0,
55
+ mainTextureFixedSize: 0,
56
+ alphaBlendingMode: 2,
57
+ camera: null,
58
+ renderingGroupId: -1,
59
+ forceGLSL: false,
60
+ mainTextureType: 1,
61
+ mainTextureFormat: 7,
62
+ storeCameraSpaceZ: false,
63
+ ...options,
64
+ };
65
+ // set clear color
66
+ this.neutralColor = new Color4(0.0, this._options.storeCameraSpaceZ ? 0.0 : 1.0, 0.0, 1.0);
67
+ // Initialize the layer
68
+ this._init(this._options);
69
+ // Do not render as long as no meshes have been added
70
+ this._shouldRender = false;
71
+ if (dontCheckIfReady) {
72
+ // When dontCheckIfReady is true, we are in the new ThinXXX layer mode, so we must call _createTextureAndPostProcesses ourselves (it is called by EffectLayer otherwise)
73
+ this._createTextureAndPostProcesses();
74
+ }
75
+ }
76
+ /**
77
+ * Gets the class name of the effect layer
78
+ * @returns the string with the class name of the effect layer
79
+ */
80
+ getClassName() {
81
+ return "SelectionOutlineLayer";
82
+ }
83
+ /** @internal */
84
+ _internalIsSubMeshReady(subMesh, useInstances, _emissiveTexture) {
85
+ const engine = this._scene.getEngine();
86
+ const mesh = subMesh.getMesh();
87
+ const renderingMaterial = mesh._internalAbstractMeshDataInfo._materialForRenderPass?.[engine.currentRenderPassId];
88
+ if (renderingMaterial) {
89
+ return renderingMaterial.isReadyForSubMesh(mesh, subMesh, useInstances);
90
+ }
91
+ const material = subMesh.getMaterial();
92
+ if (!material) {
93
+ return false;
94
+ }
95
+ // selection outline layer is not compatible with custom materials
96
+ // if (this._useMeshMaterial(subMesh.getRenderingMesh())) {
97
+ // return material.isReadyForSubMesh(subMesh.getMesh(), subMesh, useInstances);
98
+ // }
99
+ const defines = [];
100
+ const attribs = [VertexBuffer.PositionKind];
101
+ let uv1 = false;
102
+ let uv2 = false;
103
+ const color = false;
104
+ // Alpha test
105
+ if (material.needAlphaTestingForMesh(mesh)) {
106
+ defines.push("#define ALPHATEST");
107
+ if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
108
+ attribs.push(VertexBuffer.UVKind);
109
+ defines.push("#define UV1");
110
+ uv1 = true;
111
+ }
112
+ if (mesh.isVerticesDataPresent(VertexBuffer.UV2Kind)) {
113
+ attribs.push(VertexBuffer.UV2Kind);
114
+ defines.push("#define UV2");
115
+ uv2 = true;
116
+ }
117
+ }
118
+ // Bones
119
+ const fallbacks = new EffectFallbacks();
120
+ if (mesh.useBones && mesh.computeBonesUsingShaders) {
121
+ attribs.push(VertexBuffer.MatricesIndicesKind);
122
+ attribs.push(VertexBuffer.MatricesWeightsKind);
123
+ if (mesh.numBoneInfluencers > 4) {
124
+ attribs.push(VertexBuffer.MatricesIndicesExtraKind);
125
+ attribs.push(VertexBuffer.MatricesWeightsExtraKind);
126
+ }
127
+ defines.push("#define NUM_BONE_INFLUENCERS " + mesh.numBoneInfluencers);
128
+ const skeleton = mesh.skeleton;
129
+ if (skeleton && skeleton.isUsingTextureForMatrices) {
130
+ defines.push("#define BONETEXTURE");
131
+ }
132
+ else {
133
+ defines.push("#define BonesPerMesh " + (skeleton ? skeleton.bones.length + 1 : 0));
134
+ }
135
+ if (mesh.numBoneInfluencers > 0) {
136
+ fallbacks.addCPUSkinningFallback(0, mesh);
137
+ }
138
+ }
139
+ else {
140
+ defines.push("#define NUM_BONE_INFLUENCERS 0");
141
+ }
142
+ // Morph targets
143
+ const numMorphInfluencers = mesh.morphTargetManager
144
+ ? PrepareDefinesAndAttributesForMorphTargets(mesh.morphTargetManager, defines, attribs, mesh, true, // usePositionMorph
145
+ false, // useNormalMorph
146
+ false, // useTangentMorph
147
+ uv1, // useUVMorph
148
+ uv2, // useUV2Morph
149
+ color // useColorMorph
150
+ )
151
+ : 0;
152
+ // Instances
153
+ if (useInstances) {
154
+ defines.push("#define INSTANCES");
155
+ PushAttributesForInstances(attribs);
156
+ if (subMesh.getRenderingMesh().hasThinInstances) {
157
+ defines.push("#define THIN_INSTANCES");
158
+ }
159
+ }
160
+ // Baked vertex animations
161
+ const bvaManager = mesh.bakedVertexAnimationManager;
162
+ if (bvaManager && bvaManager.isEnabled) {
163
+ defines.push("#define BAKED_VERTEX_ANIMATION_TEXTURE");
164
+ if (useInstances) {
165
+ attribs.push("bakedVertexAnimationSettingsInstanced");
166
+ }
167
+ }
168
+ // ClipPlanes
169
+ PrepareStringDefinesForClipPlanes(material, this._scene, defines);
170
+ // Selection ID
171
+ if (useInstances) {
172
+ attribs.push(ThinSelectionOutlineLayer.InstanceSelectionIdAttributeName);
173
+ }
174
+ this._addCustomEffectDefines(defines);
175
+ // Get correct effect
176
+ const drawWrapper = subMesh._getDrawWrapper(undefined, true);
177
+ const cachedDefines = drawWrapper.defines;
178
+ const join = defines.join("\n");
179
+ if (cachedDefines !== join) {
180
+ const uniforms = [
181
+ "world",
182
+ "mBones",
183
+ "viewProjection",
184
+ "view",
185
+ "morphTargetInfluences",
186
+ "morphTargetCount",
187
+ "boneTextureWidth",
188
+ "diffuseMatrix",
189
+ "morphTargetTextureInfo",
190
+ "morphTargetTextureIndices",
191
+ "bakedVertexAnimationSettings",
192
+ "bakedVertexAnimationTextureSizeInverted",
193
+ "bakedVertexAnimationTime",
194
+ "bakedVertexAnimationTexture",
195
+ "depthValues",
196
+ "selectionId",
197
+ ];
198
+ AddClipPlaneUniforms(uniforms);
199
+ drawWrapper.setEffect(this._engine.createEffect("selection", {
200
+ attributes: attribs,
201
+ uniformsNames: uniforms,
202
+ uniformBuffersNames: [],
203
+ samplers: ["diffuseSampler", "boneSampler", "morphTargets", "bakedVertexAnimationTexture"],
204
+ defines: join,
205
+ fallbacks: fallbacks,
206
+ onCompiled: null,
207
+ onError: null,
208
+ indexParameters: { maxSimultaneousMorphTargets: numMorphInfluencers },
209
+ shaderLanguage: this._shaderLanguage,
210
+ extraInitializationsAsync: this._shadersLoaded
211
+ ? undefined
212
+ : async () => {
213
+ await this._importShadersAsync();
214
+ this._shadersLoaded = true;
215
+ },
216
+ }, this._engine), join);
217
+ }
218
+ const effectIsReady = drawWrapper.effect.isReady();
219
+ return effectIsReady && (this._dontCheckIfReady || (!this._dontCheckIfReady && this.isLayerReady()));
220
+ }
221
+ async _importShadersAsync() {
222
+ if (this._shaderLanguage === 1 /* ShaderLanguage.WGSL */) {
223
+ await Promise.all([
224
+ import("../ShadersWGSL/selection.vertex.js"),
225
+ import("../ShadersWGSL/selection.fragment.js"),
226
+ import("../ShadersWGSL/glowMapMerge.vertex.js"),
227
+ import("../ShadersWGSL/selectionOutline.fragment.js"),
228
+ ]);
229
+ }
230
+ else {
231
+ await Promise.all([
232
+ import("../Shaders/selection.vertex.js"),
233
+ import("../Shaders/selection.fragment.js"),
234
+ import("../Shaders/glowMapMerge.vertex.js"),
235
+ import("../Shaders/selectionOutline.fragment.js"),
236
+ ]);
237
+ }
238
+ await super._importShadersAsync();
239
+ }
240
+ /**
241
+ * Get the effect name of the layer.
242
+ * @returns The effect name
243
+ */
244
+ getEffectName() {
245
+ return ThinSelectionOutlineLayer.EffectName;
246
+ }
247
+ /** @internal */
248
+ _createMergeEffect() {
249
+ return this._engine.createEffect({
250
+ // glowMapMerge vertex is just a basic vertex shader for drawing a quad. so we reuse it here
251
+ vertex: "glowMapMerge",
252
+ // selection outline fragment does computation of outline with alpha channel for blending
253
+ fragment: "selectionOutline",
254
+ }, {
255
+ attributes: [VertexBuffer.PositionKind],
256
+ uniformsNames: ["screenSize", "outlineColor", "outlineThickness", "occlusionStrength", "occlusionThreshold"],
257
+ samplers: ["maskSampler", "depthSampler"],
258
+ defines: "",
259
+ fallbacks: null,
260
+ onCompiled: null,
261
+ onError: null,
262
+ shaderLanguage: this._shaderLanguage,
263
+ extraInitializationsAsync: this._shadersLoaded
264
+ ? undefined
265
+ : async () => {
266
+ await this._importShadersAsync();
267
+ this._shadersLoaded = true;
268
+ },
269
+ }, this._engine);
270
+ }
271
+ /** @internal */
272
+ _createTextureAndPostProcesses() {
273
+ // we don't need to create a texture for this layer. since all computation is done in the merge effect
274
+ }
275
+ /**
276
+ * Checks for the readiness of the element composing the layer.
277
+ * @param subMesh the mesh to check for
278
+ * @param useInstances specify whether or not to use instances to render the mesh
279
+ * @returns true if ready otherwise, false
280
+ */
281
+ isReady(subMesh, useInstances) {
282
+ const material = subMesh.getMaterial();
283
+ const mesh = subMesh.getRenderingMesh();
284
+ if (!material || !mesh || !this._selection) {
285
+ return false;
286
+ }
287
+ return super._isSubMeshReady(subMesh, useInstances, null);
288
+ }
289
+ /** @internal */
290
+ _canRenderMesh(_mesh, _material) {
291
+ return true;
292
+ }
293
+ _renderSubMesh(subMesh, enableAlphaMode = false) {
294
+ if (!this._internalShouldRender()) {
295
+ return;
296
+ }
297
+ const material = subMesh.getMaterial();
298
+ const ownerMesh = subMesh.getMesh();
299
+ const replacementMesh = subMesh.getReplacementMesh();
300
+ const renderingMesh = subMesh.getRenderingMesh();
301
+ const effectiveMesh = subMesh.getEffectiveMesh();
302
+ const scene = this._scene;
303
+ const engine = scene.getEngine();
304
+ effectiveMesh._internalAbstractMeshDataInfo._isActiveIntermediate = false;
305
+ if (!material) {
306
+ return;
307
+ }
308
+ // Do not block in blend mode.
309
+ if (!this._canRenderMesh(renderingMesh, material)) {
310
+ return;
311
+ }
312
+ // Culling
313
+ let sideOrientation = material._getEffectiveOrientation(renderingMesh);
314
+ const mainDeterminant = effectiveMesh._getWorldMatrixDeterminant();
315
+ if (mainDeterminant < 0) {
316
+ sideOrientation = sideOrientation === Material.ClockWiseSideOrientation ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation;
317
+ }
318
+ const reverse = sideOrientation === Material.ClockWiseSideOrientation;
319
+ engine.setState(material.backFaceCulling, material.zOffset, undefined, reverse, material.cullBackFaces, undefined, material.zOffsetUnits);
320
+ // Managing instances
321
+ const batch = renderingMesh._getInstancesRenderList(subMesh._id, !!replacementMesh);
322
+ if (batch.mustReturn) {
323
+ return;
324
+ }
325
+ // Early Exit per mesh
326
+ if (!this._shouldRenderMesh(renderingMesh)) {
327
+ return;
328
+ }
329
+ const hardwareInstancedRendering = batch.hardwareInstancedRendering[subMesh._id] || renderingMesh.hasThinInstances || !!renderingMesh._userInstancedBuffersStorage;
330
+ this._setEmissiveTextureAndColor(renderingMesh, subMesh, material);
331
+ this.onBeforeRenderMeshToEffect.notifyObservers(ownerMesh);
332
+ // selection outline layer is not compatible with custom materials
333
+ // if (this._useMeshMaterial(renderingMesh)) {
334
+ // subMesh.getMaterial()!._glowModeEnabled = true;
335
+ // renderingMesh.render(subMesh, enableAlphaMode, replacementMesh || undefined);
336
+ // subMesh.getMaterial()!._glowModeEnabled = false;
337
+ // } else
338
+ if (this._isSubMeshReady(subMesh, hardwareInstancedRendering, this._emissiveTextureAndColor.texture)) {
339
+ const renderingMaterial = effectiveMesh._internalAbstractMeshDataInfo._materialForRenderPass?.[engine.currentRenderPassId];
340
+ let drawWrapper = subMesh._getDrawWrapper();
341
+ if (!drawWrapper && renderingMaterial) {
342
+ drawWrapper = renderingMaterial._getDrawWrapper();
343
+ }
344
+ if (!drawWrapper) {
345
+ return;
346
+ }
347
+ const effect = drawWrapper.effect;
348
+ engine.enableEffect(drawWrapper);
349
+ if (!hardwareInstancedRendering) {
350
+ renderingMesh._bind(subMesh, effect, material.fillMode);
351
+ }
352
+ if (!renderingMaterial) {
353
+ effect.setMatrix("viewProjection", scene.getTransformMatrix());
354
+ if (this._options.storeCameraSpaceZ) {
355
+ effect.setMatrix("view", scene.getViewMatrix());
356
+ }
357
+ else {
358
+ const camera = this.camera || scene.activeCamera;
359
+ if (camera) {
360
+ const cameraIsOrtho = camera.mode === Camera.ORTHOGRAPHIC_CAMERA;
361
+ let minZ, maxZ;
362
+ if (cameraIsOrtho) {
363
+ minZ = !engine.useReverseDepthBuffer && engine.isNDCHalfZRange ? 0 : 1;
364
+ maxZ = engine.useReverseDepthBuffer && engine.isNDCHalfZRange ? 0 : 1;
365
+ }
366
+ else {
367
+ minZ = engine.useReverseDepthBuffer && engine.isNDCHalfZRange ? camera.minZ : engine.isNDCHalfZRange ? 0 : camera.minZ;
368
+ maxZ = engine.useReverseDepthBuffer && engine.isNDCHalfZRange ? 0 : camera.maxZ;
369
+ }
370
+ effect.setFloat2("depthValues", minZ, minZ + maxZ);
371
+ }
372
+ }
373
+ effect.setMatrix("world", effectiveMesh.getWorldMatrix());
374
+ }
375
+ else {
376
+ renderingMaterial.bindForSubMesh(effectiveMesh.getWorldMatrix(), effectiveMesh, subMesh);
377
+ }
378
+ if (!renderingMaterial) {
379
+ // Alpha test
380
+ if (material && material.needAlphaTestingForMesh(effectiveMesh)) {
381
+ const alphaTexture = material.getAlphaTestTexture();
382
+ if (alphaTexture) {
383
+ effect.setTexture("diffuseSampler", alphaTexture);
384
+ effect.setMatrix("diffuseMatrix", alphaTexture.getTextureMatrix());
385
+ }
386
+ }
387
+ // Bones
388
+ BindBonesParameters(renderingMesh, effect);
389
+ // Morph targets
390
+ BindMorphTargetParameters(renderingMesh, effect);
391
+ if (renderingMesh.morphTargetManager && renderingMesh.morphTargetManager.isUsingTextureForTargets) {
392
+ renderingMesh.morphTargetManager._bind(effect);
393
+ }
394
+ // Baked vertex animations
395
+ const bvaManager = subMesh.getMesh().bakedVertexAnimationManager;
396
+ if (bvaManager && bvaManager.isEnabled) {
397
+ bvaManager.bind(effect, hardwareInstancedRendering);
398
+ }
399
+ // Alpha mode
400
+ if (enableAlphaMode) {
401
+ engine.setAlphaMode(material.alphaMode);
402
+ }
403
+ // Clip planes
404
+ BindClipPlane(effect, material, scene);
405
+ // Selection ID
406
+ const selectionId = this._meshUniqueIdToSelectionId[renderingMesh.uniqueId];
407
+ if (!renderingMesh.hasInstances && !renderingMesh.isAnInstance && selectionId !== undefined) {
408
+ effect.setFloat("selectionId", selectionId);
409
+ }
410
+ }
411
+ // Draw
412
+ renderingMesh._processRendering(effectiveMesh, subMesh, effect, material.fillMode, batch, hardwareInstancedRendering, (isInstance, world) => effect.setMatrix("world", world));
413
+ }
414
+ else {
415
+ // Need to reset refresh rate of the main map
416
+ this._objectRenderer.resetRefreshCounter();
417
+ }
418
+ this.onAfterRenderMeshToEffect.notifyObservers(ownerMesh);
419
+ }
420
+ /** @internal */
421
+ _internalCompose(effect, _renderIndex) {
422
+ // Texture
423
+ this.bindTexturesForCompose(effect);
424
+ effect.setFloat2("screenSize", this.textureWidth, this.textureHeight);
425
+ effect.setColor3("outlineColor", this.outlineColor);
426
+ effect.setFloat("outlineThickness", this.outlineThickness);
427
+ effect.setFloat("occlusionStrength", this.occlusionStrength);
428
+ effect.setFloat("occlusionThreshold", this.occlusionThreshold);
429
+ // Cache
430
+ const engine = this._engine;
431
+ const previousStencilBuffer = engine.getStencilBuffer();
432
+ // Draw order
433
+ engine.setStencilBuffer(false);
434
+ engine.drawElementsType(Material.TriangleFillMode, 0, 6);
435
+ // Draw order
436
+ engine.setStencilBuffer(previousStencilBuffer);
437
+ }
438
+ /** @internal */
439
+ _setEmissiveTextureAndColor(_mesh, _subMesh, _material) {
440
+ // we don't use emissive texture or color for this layer
441
+ }
442
+ /**
443
+ * Returns true if the layer contains information to display, otherwise false.
444
+ * @returns true if the glow layer should be rendered
445
+ */
446
+ shouldRender() {
447
+ return this._selection && super.shouldRender() ? true : false;
448
+ }
449
+ /** @internal */
450
+ _shouldRenderMesh(mesh) {
451
+ return this.hasMesh(mesh);
452
+ }
453
+ /** @internal */
454
+ _addCustomEffectDefines(defines) {
455
+ if (this._options.storeCameraSpaceZ) {
456
+ defines.push("#define STORE_CAMERASPACE_Z");
457
+ }
458
+ }
459
+ /**
460
+ * Determine if a given mesh will be used in the current effect.
461
+ * @param mesh mesh to test
462
+ * @returns true if the mesh will be used
463
+ */
464
+ hasMesh(mesh) {
465
+ // we control selection as RTT render list
466
+ return super.hasMesh(mesh);
467
+ }
468
+ /** @internal */
469
+ _useMeshMaterial(_mesh) {
470
+ return false;
471
+ }
472
+ _clearMeshSelection(mesh) {
473
+ if (mesh._userInstancedBuffersStorage) {
474
+ const kind = ThinSelectionOutlineLayer.InstanceSelectionIdAttributeName;
475
+ mesh._userInstancedBuffersStorage.vertexBuffers[kind]?.dispose();
476
+ const vao = mesh._userInstancedBuffersStorage.vertexArrayObjects?.[kind];
477
+ if (vao) {
478
+ // invalidate VAO is very important to keep sync between VAO and vertex buffers
479
+ this._engine.releaseVertexArrayObject(vao);
480
+ delete mesh._userInstancedBuffersStorage.vertexArrayObjects[kind];
481
+ }
482
+ delete mesh._userInstancedBuffersStorage.data[kind];
483
+ delete mesh._userInstancedBuffersStorage.vertexBuffers[kind];
484
+ delete mesh._userInstancedBuffersStorage.strides[kind];
485
+ delete mesh._userInstancedBuffersStorage.sizes[kind];
486
+ if (Object.keys(mesh._userInstancedBuffersStorage.vertexBuffers).length === 0) {
487
+ mesh._userInstancedBuffersStorage = undefined;
488
+ }
489
+ }
490
+ if (mesh.instancedBuffers?.[ThinSelectionOutlineLayer.InstanceSelectionIdAttributeName] !== undefined) {
491
+ delete mesh.instancedBuffers[ThinSelectionOutlineLayer.InstanceSelectionIdAttributeName];
492
+ }
493
+ if (this._selection) {
494
+ const index = this._selection.indexOf(mesh);
495
+ if (~index) {
496
+ this._selection.splice(index, 1);
497
+ }
498
+ }
499
+ }
500
+ /**
501
+ * Remove all the meshes currently referenced in the selection outline layer
502
+ */
503
+ clearSelection() {
504
+ if (!this._selection) {
505
+ return;
506
+ }
507
+ for (let index = 0; index < this._selection.length; ++index) {
508
+ const mesh = this._selection[index];
509
+ this._clearMeshSelection(mesh);
510
+ }
511
+ this._selection = [];
512
+ this._meshUniqueIdToSelectionId.length = 0;
513
+ this._nextSelectionId = 1;
514
+ this._shouldRender = false;
515
+ }
516
+ /**
517
+ * Adds mesh or group of mesh to the current selection
518
+ * @param meshOrGroup Meshes to remove from the selection
519
+ */
520
+ removeSelection(meshOrGroup) {
521
+ if (!this._selection) {
522
+ return;
523
+ }
524
+ const group = Array.isArray(meshOrGroup) ? meshOrGroup : [meshOrGroup];
525
+ if (group.length === 0) {
526
+ return;
527
+ }
528
+ for (let i = 0; i < group.length; i++) {
529
+ const mesh = group[i];
530
+ this._clearMeshSelection(mesh);
531
+ delete this._meshUniqueIdToSelectionId[mesh.uniqueId];
532
+ }
533
+ if (!this._selection || !this._selection.length) {
534
+ this._meshUniqueIdToSelectionId.length = 0;
535
+ this._nextSelectionId = 1;
536
+ this._shouldRender = false;
537
+ }
538
+ }
539
+ /**
540
+ * Adds mesh or group of mesh to the current selection
541
+ *
542
+ * If a group of meshes is provided, they will outline as a single unit
543
+ * @param meshOrGroup Meshes to add to the selection
544
+ */
545
+ addSelection(meshOrGroup) {
546
+ if (!this._selection) {
547
+ return;
548
+ }
549
+ const nextId = this._nextSelectionId;
550
+ const group = Array.isArray(meshOrGroup) ? meshOrGroup : [meshOrGroup];
551
+ if (group.length === 0) {
552
+ return;
553
+ }
554
+ for (let meshIndex = 0; meshIndex < group.length; ++meshIndex) {
555
+ const mesh = group[meshIndex];
556
+ this._selection.push(mesh); // add to render list
557
+ if (mesh.hasInstances || mesh.isAnInstance) {
558
+ const sourceMesh = mesh.sourceMesh ?? mesh;
559
+ if (sourceMesh.instancedBuffers?.[ThinSelectionOutlineLayer.InstanceSelectionIdAttributeName] === undefined) {
560
+ sourceMesh.registerInstancedBuffer(ThinSelectionOutlineLayer.InstanceSelectionIdAttributeName, 1);
561
+ }
562
+ mesh.instancedBuffers[ThinSelectionOutlineLayer.InstanceSelectionIdAttributeName] = nextId;
563
+ }
564
+ else {
565
+ this._meshUniqueIdToSelectionId[mesh.uniqueId] = nextId;
566
+ }
567
+ }
568
+ this._nextSelectionId += 1;
569
+ this._shouldRender = true;
570
+ }
571
+ /**
572
+ * Free any resources and references associated to a mesh.
573
+ * Internal use
574
+ * @param mesh The mesh to free.
575
+ * @internal
576
+ */
577
+ _disposeMesh(mesh) {
578
+ const selection = this._selection;
579
+ if (!selection) {
580
+ return;
581
+ }
582
+ const index = selection.indexOf(mesh);
583
+ if (index !== -1) {
584
+ selection.splice(index, 1);
585
+ if (mesh.hasInstances) {
586
+ mesh.removeVerticesData(ThinSelectionOutlineLayer.InstanceSelectionIdAttributeName);
587
+ }
588
+ if (selection.length === 0) {
589
+ this._shouldRender = false;
590
+ }
591
+ }
592
+ }
593
+ /**
594
+ * Dispose the effect layer and free resources.
595
+ */
596
+ dispose() {
597
+ this.clearSelection();
598
+ this._selection = null;
599
+ super.dispose();
600
+ }
601
+ }
602
+ /**
603
+ * Effect Name of the layer.
604
+ */
605
+ ThinSelectionOutlineLayer.EffectName = "SelectionOutlineLayer";
606
+ /**
607
+ * Name of the instance selection ID attribute
608
+ * @internal
609
+ */
610
+ ThinSelectionOutlineLayer.InstanceSelectionIdAttributeName = "instanceSelectionId";
611
+ //# sourceMappingURL=thinSelectionOutlineLayer.js.map