@babylonjs/core 8.38.0 → 8.39.0

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 (109) hide show
  1. package/Animations/animation.d.ts +2 -1
  2. package/Animations/animation.js +3 -2
  3. package/Animations/animation.js.map +1 -1
  4. package/Behaviors/Cameras/autoRotationBehavior.d.ts +4 -0
  5. package/Behaviors/Cameras/autoRotationBehavior.js +7 -0
  6. package/Behaviors/Cameras/autoRotationBehavior.js.map +1 -1
  7. package/Behaviors/Cameras/bouncingBehavior.d.ts +5 -0
  8. package/Behaviors/Cameras/bouncingBehavior.js +8 -0
  9. package/Behaviors/Cameras/bouncingBehavior.js.map +1 -1
  10. package/Behaviors/Cameras/framingBehavior.d.ts +4 -0
  11. package/Behaviors/Cameras/framingBehavior.js +7 -0
  12. package/Behaviors/Cameras/framingBehavior.js.map +1 -1
  13. package/Behaviors/Cameras/interpolatingBehavior.d.ts +7 -1
  14. package/Behaviors/Cameras/interpolatingBehavior.js +11 -3
  15. package/Behaviors/Cameras/interpolatingBehavior.js.map +1 -1
  16. package/Behaviors/Meshes/attachToBoxBehavior.d.ts +5 -0
  17. package/Behaviors/Meshes/attachToBoxBehavior.js +8 -1
  18. package/Behaviors/Meshes/attachToBoxBehavior.js.map +1 -1
  19. package/Behaviors/Meshes/baseSixDofDragBehavior.d.ts +5 -2
  20. package/Behaviors/Meshes/baseSixDofDragBehavior.js +8 -0
  21. package/Behaviors/Meshes/baseSixDofDragBehavior.js.map +1 -1
  22. package/Behaviors/Meshes/fadeInOutBehavior.d.ts +5 -0
  23. package/Behaviors/Meshes/fadeInOutBehavior.js +6 -0
  24. package/Behaviors/Meshes/fadeInOutBehavior.js.map +1 -1
  25. package/Behaviors/Meshes/handConstraintBehavior.d.ts +5 -0
  26. package/Behaviors/Meshes/handConstraintBehavior.js +8 -0
  27. package/Behaviors/Meshes/handConstraintBehavior.js.map +1 -1
  28. package/Behaviors/Meshes/multiPointerScaleBehavior.d.ts +5 -0
  29. package/Behaviors/Meshes/multiPointerScaleBehavior.js +8 -0
  30. package/Behaviors/Meshes/multiPointerScaleBehavior.js.map +1 -1
  31. package/Behaviors/Meshes/sixDofDragBehavior.js +1 -1
  32. package/Behaviors/Meshes/sixDofDragBehavior.js.map +1 -1
  33. package/Behaviors/Meshes/surfaceMagnetismBehavior.d.ts +5 -0
  34. package/Behaviors/Meshes/surfaceMagnetismBehavior.js +7 -0
  35. package/Behaviors/Meshes/surfaceMagnetismBehavior.js.map +1 -1
  36. package/Behaviors/behavior.d.ts +4 -0
  37. package/Behaviors/behavior.js.map +1 -1
  38. package/Cameras/geospatialCamera.d.ts +11 -3
  39. package/Cameras/geospatialCamera.js +103 -36
  40. package/Cameras/geospatialCamera.js.map +1 -1
  41. package/Cameras/geospatialCameraMovement.d.ts +6 -2
  42. package/Cameras/geospatialCameraMovement.js +11 -11
  43. package/Cameras/geospatialCameraMovement.js.map +1 -1
  44. package/Engines/WebGPU/Extensions/engine.multiRender.d.ts +2 -1
  45. package/Engines/WebGPU/Extensions/engine.multiRender.js +5 -2
  46. package/Engines/WebGPU/Extensions/engine.multiRender.js.map +1 -1
  47. package/Engines/WebGPU/webgpuTextureHelper.d.ts +1 -0
  48. package/Engines/WebGPU/webgpuTextureHelper.js +11 -0
  49. package/Engines/WebGPU/webgpuTextureHelper.js.map +1 -1
  50. package/Engines/WebGPU/webgpuTextureManager.d.ts +1 -0
  51. package/Engines/WebGPU/webgpuTextureManager.js +100 -9
  52. package/Engines/WebGPU/webgpuTextureManager.js.map +1 -1
  53. package/Engines/abstractEngine.js +2 -2
  54. package/Engines/abstractEngine.js.map +1 -1
  55. package/Engines/renderTargetWrapper.js +6 -1
  56. package/Engines/renderTargetWrapper.js.map +1 -1
  57. package/Engines/thinEngine.js +1 -1
  58. package/Engines/thinEngine.js.map +1 -1
  59. package/Engines/webgpuEngine.d.ts +7 -4
  60. package/Engines/webgpuEngine.js +45 -16
  61. package/Engines/webgpuEngine.js.map +1 -1
  62. package/FrameGraph/Node/nodeRenderGraph.d.ts +22 -5
  63. package/FrameGraph/Node/nodeRenderGraph.js +39 -18
  64. package/FrameGraph/Node/nodeRenderGraph.js.map +1 -1
  65. package/FrameGraph/Passes/pass.d.ts +2 -0
  66. package/FrameGraph/Passes/pass.js +2 -0
  67. package/FrameGraph/Passes/pass.js.map +1 -1
  68. package/FrameGraph/Passes/renderPass.d.ts +2 -0
  69. package/FrameGraph/Passes/renderPass.js +4 -0
  70. package/FrameGraph/Passes/renderPass.js.map +1 -1
  71. package/FrameGraph/frameGraph.d.ts +13 -4
  72. package/FrameGraph/frameGraph.js +45 -5
  73. package/FrameGraph/frameGraph.js.map +1 -1
  74. package/FrameGraph/frameGraphRenderTarget.d.ts +1 -0
  75. package/FrameGraph/frameGraphRenderTarget.js +3 -0
  76. package/FrameGraph/frameGraphRenderTarget.js.map +1 -1
  77. package/FrameGraph/frameGraphTask.d.ts +6 -0
  78. package/FrameGraph/frameGraphTask.js +15 -0
  79. package/FrameGraph/frameGraphTask.js.map +1 -1
  80. package/FrameGraph/frameGraphTypes.d.ts +2 -0
  81. package/FrameGraph/frameGraphTypes.js.map +1 -1
  82. package/Helpers/sceneHelpers.js +1 -1
  83. package/Helpers/sceneHelpers.js.map +1 -1
  84. package/Lights/index.d.ts +1 -0
  85. package/Lights/index.js +1 -0
  86. package/Lights/index.js.map +1 -1
  87. package/Lights/lightingVolume.d.ts +89 -0
  88. package/Lights/lightingVolume.js +426 -0
  89. package/Lights/lightingVolume.js.map +1 -0
  90. package/Materials/Node/nodeMaterial.js +8 -2
  91. package/Materials/Node/nodeMaterial.js.map +1 -1
  92. package/Materials/floatingOriginMatrixOverrides.js +6 -5
  93. package/Materials/floatingOriginMatrixOverrides.js.map +1 -1
  94. package/Meshes/mesh.js +1 -1
  95. package/Meshes/mesh.js.map +1 -1
  96. package/Misc/screenshotTools.js +2 -8
  97. package/Misc/screenshotTools.js.map +1 -1
  98. package/Particles/solidParticle.d.ts +9 -0
  99. package/Particles/solidParticle.js +11 -0
  100. package/Particles/solidParticle.js.map +1 -1
  101. package/Particles/solidParticleSystem.d.ts +28 -0
  102. package/Particles/solidParticleSystem.js +75 -0
  103. package/Particles/solidParticleSystem.js.map +1 -1
  104. package/ShadersWGSL/lightingVolume.compute.d.ts +5 -0
  105. package/ShadersWGSL/lightingVolume.compute.js +27 -0
  106. package/ShadersWGSL/lightingVolume.compute.js.map +1 -0
  107. package/package.json +1 -1
  108. package/scene.js +6 -4
  109. package/scene.js.map +1 -1
@@ -0,0 +1,89 @@
1
+ import type { Scene, ShadowGenerator } from "../index.js";
2
+ import { Mesh } from "../Meshes/mesh.js";
3
+ import "../ShadersWGSL/lightingVolume.compute.js";
4
+ /**
5
+ * Class used to create a lighting volume from a directional light's shadow generator.
6
+ */
7
+ export declare class LightingVolume {
8
+ private readonly _engine;
9
+ private readonly _scene;
10
+ private readonly _mesh;
11
+ private readonly _copyTexture?;
12
+ private readonly _uBuffer?;
13
+ private _name;
14
+ private _cs?;
15
+ private _light?;
16
+ private _fallbackTexture?;
17
+ private _storageBuffer?;
18
+ private _depthCopy?;
19
+ private _readPixelPromise;
20
+ private _readPixelAbortController;
21
+ private _numFrames;
22
+ private _firstUpdate;
23
+ private _shadowGenerator?;
24
+ /**
25
+ * The shadow generator used to create the lighting volume.
26
+ */
27
+ get shadowGenerator(): ShadowGenerator;
28
+ set shadowGenerator(sg: ShadowGenerator);
29
+ private _tesselation;
30
+ /**
31
+ * The tesselation level of the lighting volume.
32
+ */
33
+ get tesselation(): number;
34
+ set tesselation(n: number);
35
+ private _buildFullVolume;
36
+ /**
37
+ * Indicates whether to build the full volume (true) or only the far plane (false). Default is false.
38
+ */
39
+ get buildFullVolume(): boolean;
40
+ set buildFullVolume(value: boolean);
41
+ /**
42
+ * The mesh used as a support for the lighting volume.
43
+ * Note that this mesh is not automatically added to the scene's mesh array.
44
+ * If you want to render it, you need to add it manually.
45
+ */
46
+ get mesh(): Mesh;
47
+ private _frequency;
48
+ /**
49
+ * The frequency (in number of times you call updateMesh) at which the lighting volume is updated.
50
+ */
51
+ get frequency(): number;
52
+ set frequency(value: number);
53
+ /**
54
+ * The name of the lighting volume.
55
+ */
56
+ get name(): string;
57
+ set name(name: string);
58
+ /**
59
+ * Indicates whether this is the first update of the lighting volume.
60
+ * If true, the volume has not yet been updated for the first time.
61
+ */
62
+ get firstUpdate(): boolean;
63
+ /**
64
+ * Creates a new LightingVolume.
65
+ * @param name The name of the lighting volume.
66
+ * @param scene The scene the lighting volume belongs to.
67
+ * @param shadowGenerator The shadow generator used to create the lighting volume. This is optional in the constructor, but must be set before calling updateMesh.
68
+ * @param tesselation The tesselation level of the lighting volume (default: 64).
69
+ */
70
+ constructor(name: string, scene: Scene, shadowGenerator?: ShadowGenerator, tesselation?: number);
71
+ /**
72
+ * Checks if the lighting volume is ready to be updated.
73
+ * @returns True if the volume is ready to be updated.
74
+ */
75
+ isReady(): boolean;
76
+ /**
77
+ * Updates the lighting volume mesh.
78
+ * @param forceUpdate If true, forces the update even if the frequency condition is not met.
79
+ */
80
+ update(forceUpdate?: boolean): void;
81
+ /**
82
+ * Disposes the lighting volume and associated resources.
83
+ */
84
+ dispose(): void;
85
+ private _createComputeShader;
86
+ private _createFallbackTextures;
87
+ private _fallbackReadPixelAsync;
88
+ private _createGeometry;
89
+ }
@@ -0,0 +1,426 @@
1
+ import { AbortError } from "../Misc/error.js";
2
+
3
+ import { Matrix, Vector3 } from "../Maths/math.vector.js";
4
+ import { DirectionalLight } from "./directionalLight.js";
5
+ import { Mesh } from "../Meshes/mesh.js";
6
+ import { ComputeShader } from "../Compute/computeShader.js";
7
+ import { CopyTextureToTexture } from "../Misc/copyTextureToTexture.js";
8
+ import { UniformBuffer } from "../Materials/uniformBuffer.js";
9
+ import { StorageBuffer } from "../Buffers/storageBuffer.js";
10
+ import { BaseTexture } from "../Materials/Textures/baseTexture.js";
11
+ import { VertexBuffer } from "../Buffers/buffer.js";
12
+ import "../ShadersWGSL/lightingVolume.compute.js";
13
+ const InvViewProjMatrix = new Matrix();
14
+ const TmpVec3 = new Vector3();
15
+ /**
16
+ * Class used to create a lighting volume from a directional light's shadow generator.
17
+ */
18
+ export class LightingVolume {
19
+ /**
20
+ * The shadow generator used to create the lighting volume.
21
+ */
22
+ get shadowGenerator() {
23
+ return this._shadowGenerator;
24
+ }
25
+ set shadowGenerator(sg) {
26
+ const light = sg.getLight();
27
+ if (!(light instanceof DirectionalLight)) {
28
+ throw new Error(`LightingVolumeMesh ${this._name}: light must be a directional light`);
29
+ }
30
+ this._shadowGenerator = sg;
31
+ this._light = light;
32
+ this._createGeometry();
33
+ if (!this._engine.isWebGPU) {
34
+ this._createFallbackTextures();
35
+ }
36
+ const depthTexture = this._shadowGenerator.getShadowMap()?.depthStencilTexture;
37
+ if (this._cs && depthTexture) {
38
+ this._cs.setInternalTexture("shadowMap", depthTexture);
39
+ }
40
+ }
41
+ /**
42
+ * The tesselation level of the lighting volume.
43
+ */
44
+ get tesselation() {
45
+ return this._tesselation;
46
+ }
47
+ set tesselation(n) {
48
+ this._tesselation = n;
49
+ this._createGeometry();
50
+ }
51
+ /**
52
+ * Indicates whether to build the full volume (true) or only the far plane (false). Default is false.
53
+ */
54
+ get buildFullVolume() {
55
+ return this._buildFullVolume;
56
+ }
57
+ set buildFullVolume(value) {
58
+ if (this._buildFullVolume === value) {
59
+ return;
60
+ }
61
+ this._buildFullVolume = value;
62
+ this._createGeometry();
63
+ this._createComputeShader();
64
+ }
65
+ /**
66
+ * The mesh used as a support for the lighting volume.
67
+ * Note that this mesh is not automatically added to the scene's mesh array.
68
+ * If you want to render it, you need to add it manually.
69
+ */
70
+ get mesh() {
71
+ return this._mesh;
72
+ }
73
+ /**
74
+ * The frequency (in number of times you call updateMesh) at which the lighting volume is updated.
75
+ */
76
+ get frequency() {
77
+ return this._frequency;
78
+ }
79
+ set frequency(value) {
80
+ this._frequency = value;
81
+ this._firstUpdate = true;
82
+ }
83
+ /**
84
+ * The name of the lighting volume.
85
+ */
86
+ get name() {
87
+ return this._name;
88
+ }
89
+ set name(name) {
90
+ this._name = name;
91
+ if (this._mesh) {
92
+ this._mesh.name = name;
93
+ }
94
+ }
95
+ /**
96
+ * Indicates whether this is the first update of the lighting volume.
97
+ * If true, the volume has not yet been updated for the first time.
98
+ */
99
+ get firstUpdate() {
100
+ return this._firstUpdate;
101
+ }
102
+ /**
103
+ * Creates a new LightingVolume.
104
+ * @param name The name of the lighting volume.
105
+ * @param scene The scene the lighting volume belongs to.
106
+ * @param shadowGenerator The shadow generator used to create the lighting volume. This is optional in the constructor, but must be set before calling updateMesh.
107
+ * @param tesselation The tesselation level of the lighting volume (default: 64).
108
+ */
109
+ constructor(name, scene, shadowGenerator, tesselation = 64) {
110
+ this._readPixelPromise = null;
111
+ this._readPixelAbortController = null;
112
+ this._numFrames = 0;
113
+ this._firstUpdate = true;
114
+ this._tesselation = 0;
115
+ this._buildFullVolume = false;
116
+ this._frequency = 1;
117
+ const light = shadowGenerator ? shadowGenerator.getLight() : undefined;
118
+ if (light && !(light instanceof DirectionalLight)) {
119
+ throw new Error(`LightingVolumeMesh ${name}: light must be a directional light`);
120
+ }
121
+ this._name = name;
122
+ this._shadowGenerator = shadowGenerator;
123
+ this._light = light;
124
+ this._engine = scene.getEngine();
125
+ this._scene = scene;
126
+ this._mesh = new Mesh(name, this._scene);
127
+ scene.meshes.splice(scene.meshes.indexOf(this._mesh), 1);
128
+ if (this._engine.isWebGPU) {
129
+ this._uBuffer = new UniformBuffer(this._engine);
130
+ this._uBuffer.addUniform("invViewProjMatrix", 16);
131
+ this._uBuffer.addUniform("startVertexIndex", 1);
132
+ this._uBuffer.addUniform("step", 1);
133
+ this._uBuffer.addUniform("tesselation", 1);
134
+ this._uBuffer.update();
135
+ this._createComputeShader();
136
+ }
137
+ else {
138
+ this._copyTexture = new CopyTextureToTexture(this._engine, false, true);
139
+ this._createFallbackTextures();
140
+ }
141
+ this._tesselation = tesselation;
142
+ this._createGeometry();
143
+ }
144
+ /**
145
+ * Checks if the lighting volume is ready to be updated.
146
+ * @returns True if the volume is ready to be updated.
147
+ */
148
+ isReady() {
149
+ let isReady = this._mesh.isReady(true);
150
+ if (this._cs) {
151
+ isReady = this._cs.isReady() && isReady;
152
+ }
153
+ return isReady;
154
+ }
155
+ /**
156
+ * Updates the lighting volume mesh.
157
+ * @param forceUpdate If true, forces the update even if the frequency condition is not met.
158
+ */
159
+ update(forceUpdate = false) {
160
+ if (this._tesselation === 0 || !this._shadowGenerator) {
161
+ return;
162
+ }
163
+ if (!forceUpdate && !this._firstUpdate && (this.frequency === 0 || ++this._numFrames < this.frequency)) {
164
+ return;
165
+ }
166
+ this._numFrames = 0;
167
+ if (this._cs && this._uBuffer) {
168
+ const dispatchSize = Math.ceil((this._tesselation + 1) / 8);
169
+ const viewProjMatrix = this._shadowGenerator.getTransformMatrix();
170
+ viewProjMatrix.invertToRef(InvViewProjMatrix);
171
+ this._uBuffer.updateMatrix("invViewProjMatrix", InvViewProjMatrix);
172
+ this._uBuffer.update();
173
+ this._engine._debugPushGroup?.(`Generate lighting volume (${this._name})`);
174
+ this._cs.dispatch(dispatchSize, dispatchSize, 1);
175
+ this._engine._debugPopGroup?.();
176
+ this._firstUpdate = false;
177
+ }
178
+ else {
179
+ try {
180
+ void this._fallbackReadPixelAsync();
181
+ }
182
+ catch {
183
+ this._readPixelPromise = null;
184
+ }
185
+ }
186
+ }
187
+ /**
188
+ * Disposes the lighting volume and associated resources.
189
+ */
190
+ dispose() {
191
+ this._readPixelAbortController?.abort(new AbortError("LightingVolume is disposed"));
192
+ this._readPixelAbortController = null;
193
+ this._mesh.dispose();
194
+ if (this._fallbackTexture) {
195
+ this._fallbackTexture._texture = null;
196
+ }
197
+ this._fallbackTexture?.dispose();
198
+ this._copyTexture?.dispose();
199
+ this._storageBuffer?.dispose();
200
+ this._uBuffer?.dispose();
201
+ this._depthCopy?.dispose();
202
+ }
203
+ _createComputeShader() {
204
+ this._cs = new ComputeShader("createLightVolume", this._engine, "lightingVolume", {
205
+ bindingsMapping: {
206
+ shadowMap: { group: 0, binding: 0 },
207
+ params: { group: 0, binding: 1 },
208
+ positions: { group: 0, binding: 2 },
209
+ },
210
+ defines: !this._buildFullVolume ? ["#define KEEP_EDGES", "#define MOVE_FAR_DEPTH_TO_NEAR"] : undefined,
211
+ });
212
+ if (this._shadowGenerator) {
213
+ const depthTexture = this._shadowGenerator.getShadowMap()?.depthStencilTexture;
214
+ if (depthTexture) {
215
+ this._cs.setInternalTexture("shadowMap", depthTexture);
216
+ }
217
+ }
218
+ if (this._uBuffer) {
219
+ this._cs.setUniformBuffer("params", this._uBuffer);
220
+ }
221
+ if (this._storageBuffer) {
222
+ this._cs.setStorageBuffer("positions", this._storageBuffer);
223
+ }
224
+ }
225
+ _createFallbackTextures() {
226
+ if (!this._shadowGenerator) {
227
+ return;
228
+ }
229
+ this._readPixelAbortController?.abort(new AbortError("Fallback textures are being (re)created"));
230
+ this._readPixelAbortController = new AbortController();
231
+ const mapSize = this._shadowGenerator.mapSize;
232
+ this._depthCopy?.dispose();
233
+ this._depthCopy = this._engine.createRenderTargetTexture({ width: mapSize, height: mapSize }, {
234
+ type: 1,
235
+ format: 6,
236
+ samples: 1,
237
+ label: `${this._name} - fallback internal texture`,
238
+ generateDepthBuffer: false,
239
+ });
240
+ this._fallbackTexture?.dispose();
241
+ this._fallbackTexture = new BaseTexture(this._scene, this._depthCopy.texture);
242
+ this._fallbackTexture.name = `${this._name} - fallback texture`;
243
+ }
244
+ async _fallbackReadPixelAsync() {
245
+ if (this._readPixelPromise || !this._fallbackTexture || !this._copyTexture) {
246
+ return;
247
+ }
248
+ const abortController = this._readPixelAbortController;
249
+ abortController?.signal.throwIfAborted();
250
+ const engine = this._engine;
251
+ const shadowGenerator = this._shadowGenerator;
252
+ const shadowMapDepthTexture = shadowGenerator?.getShadowMap()?.depthStencilTexture;
253
+ if (!shadowMapDepthTexture) {
254
+ return;
255
+ }
256
+ // Copies the shadow map of the shadow generator into _depthCopy
257
+ // That's because we can't read from a depth attachment texture in WebGL. We must first copy it to a regular texture.
258
+ engine.updateTextureSamplingMode(1, shadowMapDepthTexture);
259
+ engine.updateTextureComparisonFunction(shadowMapDepthTexture, 0);
260
+ this._copyTexture.copy(shadowMapDepthTexture, this._depthCopy);
261
+ engine.updateTextureComparisonFunction(shadowMapDepthTexture, 513);
262
+ // Gets the texture from GPU to CPU
263
+ this._readPixelPromise = this._fallbackTexture.readPixels(0, 0, undefined, true, false);
264
+ if (!this._readPixelPromise) {
265
+ return;
266
+ }
267
+ const buffer = await this._readPixelPromise;
268
+ abortController?.signal.throwIfAborted();
269
+ const depthValues = buffer;
270
+ const positions = this._mesh.getVerticesData("position");
271
+ const numTesselation = this._tesselation;
272
+ const startPos = this._buildFullVolume ? (numTesselation + 1) * 4 * 3 : 4 * 3;
273
+ const mapSize = shadowGenerator.mapSize;
274
+ const step = (mapSize - 1) / numTesselation;
275
+ if (!positions) {
276
+ this._readPixelPromise = null;
277
+ return;
278
+ }
279
+ const halfTesselation = numTesselation / 2;
280
+ const invViewProjMatrix = shadowGenerator.getTransformMatrix().clone();
281
+ invViewProjMatrix.invertToRef(invViewProjMatrix);
282
+ const factor = 4;
283
+ let posIndex = startPos;
284
+ let stepY = 0;
285
+ for (let y = 0; y < numTesselation + 1; ++y) {
286
+ for (let x = 0; x < numTesselation + 1; ++x) {
287
+ let depth = depthValues[Math.floor(mapSize * Math.floor(stepY) + x * step) * factor];
288
+ if (!this._buildFullVolume && (depth === 1 || y === 0 || x === 0 || y === numTesselation || x === numTesselation)) {
289
+ depth = 0;
290
+ }
291
+ TmpVec3.set((x - halfTesselation) / halfTesselation, (y - halfTesselation) / halfTesselation, -1 + 2 * depth);
292
+ Vector3.TransformCoordinatesToRef(TmpVec3, invViewProjMatrix, TmpVec3);
293
+ positions[posIndex] = TmpVec3.x;
294
+ positions[posIndex + 1] = TmpVec3.y;
295
+ positions[posIndex + 2] = TmpVec3.z;
296
+ posIndex += 3;
297
+ }
298
+ stepY += step;
299
+ }
300
+ this._mesh.setVerticesData("position", positions);
301
+ this._readPixelPromise = null;
302
+ this._firstUpdate = false;
303
+ }
304
+ _createGeometry() {
305
+ if (!this._light) {
306
+ return;
307
+ }
308
+ this._tesselation = Math.max(Math.ceil(this._tesselation) & ~1, 2);
309
+ const light = this._light;
310
+ const min = new Vector3(light.orthoLeft, light.orthoBottom, light.shadowMinZ ?? 0);
311
+ const max = new Vector3(light.orthoRight, light.orthoTop, light.shadowMaxZ ?? 10000);
312
+ const invViewMatrix = Matrix.LookAtLH(light.position, light.position.add(light.direction), Vector3.UpReadOnly);
313
+ invViewMatrix.invertToRef(invViewMatrix);
314
+ const positions = [];
315
+ const indices = [];
316
+ const numTesselation = this._tesselation;
317
+ const stepX = (max.x - min.x) / numTesselation;
318
+ const stepY = (max.y - min.y) / numTesselation;
319
+ const v = new Vector3();
320
+ const startFarIndices = this._buildFullVolume ? (numTesselation + 1) * 4 : 4;
321
+ if (this._buildFullVolume) {
322
+ let startIndices = 0;
323
+ // Right faces of the frustum
324
+ for (let i = 0; i <= numTesselation; ++i) {
325
+ v.set(max.x, min.y + i * stepY, min.z);
326
+ const p = Vector3.TransformCoordinates(v, invViewMatrix);
327
+ positions.push(p.x, p.y, p.z);
328
+ if (i < numTesselation) {
329
+ indices.push(startIndices + i, startFarIndices + numTesselation + (i + 1) * (numTesselation + 1), startFarIndices + numTesselation + i * (numTesselation + 1));
330
+ indices.push(startIndices + i, startIndices + i + 1, startFarIndices + numTesselation + (i + 1) * (numTesselation + 1));
331
+ }
332
+ }
333
+ const n0 = 0;
334
+ const n1 = positions.length / 3 - 1;
335
+ const n2 = n1 + 1;
336
+ startIndices = positions.length / 3;
337
+ // Left faces of the frustum
338
+ for (let i = 0; i <= numTesselation; ++i) {
339
+ v.set(min.x, min.y + i * stepY, min.z);
340
+ const p = Vector3.TransformCoordinates(v, invViewMatrix);
341
+ positions.push(p.x, p.y, p.z);
342
+ if (i < numTesselation) {
343
+ indices.push(startIndices + i, startFarIndices + 0 + i * (numTesselation + 1), startFarIndices + 0 + (i + 1) * (numTesselation + 1));
344
+ indices.push(startIndices + i, startFarIndices + 0 + (i + 1) * (numTesselation + 1), startIndices + i + 1);
345
+ }
346
+ }
347
+ const n3 = positions.length / 3 - 1;
348
+ startIndices = positions.length / 3;
349
+ // Bottom faces of the frustum
350
+ for (let i = 0; i <= numTesselation; ++i) {
351
+ v.set(min.x + i * stepX, min.y, min.z);
352
+ const p = Vector3.TransformCoordinates(v, invViewMatrix);
353
+ positions.push(p.x, p.y, p.z);
354
+ if (i < numTesselation) {
355
+ indices.push(startIndices + i, startIndices + i + 1, startFarIndices + i + 0 * (numTesselation + 1));
356
+ indices.push(startIndices + i + 1, startFarIndices + i + 1 + 0 * (numTesselation + 1), startFarIndices + i + 0 * (numTesselation + 1));
357
+ }
358
+ }
359
+ startIndices = positions.length / 3;
360
+ // Top faces of the frustum
361
+ for (let i = 0; i <= numTesselation; ++i) {
362
+ v.set(min.x + i * stepX, max.y, min.z);
363
+ const p = Vector3.TransformCoordinates(v, invViewMatrix);
364
+ positions.push(p.x, p.y, p.z);
365
+ if (i < numTesselation) {
366
+ indices.push(startIndices + i, startFarIndices + i + numTesselation * (numTesselation + 1), startIndices + i + 1);
367
+ indices.push(startIndices + i + 1, startFarIndices + i + numTesselation * (numTesselation + 1), startFarIndices + i + 1 + numTesselation * (numTesselation + 1));
368
+ }
369
+ }
370
+ startIndices = positions.length / 3;
371
+ // Near faces of the frustum
372
+ indices.push(n0, n2, n1);
373
+ indices.push(n2, n3, n1);
374
+ }
375
+ else {
376
+ let p;
377
+ v.set(max.x, min.y, min.z);
378
+ p = Vector3.TransformCoordinates(v, invViewMatrix);
379
+ positions.push(p.x, p.y, p.z);
380
+ v.set(max.x, max.y, min.z);
381
+ p = Vector3.TransformCoordinates(v, invViewMatrix);
382
+ positions.push(p.x, p.y, p.z);
383
+ v.set(min.x, min.y, min.z);
384
+ p = Vector3.TransformCoordinates(v, invViewMatrix);
385
+ positions.push(p.x, p.y, p.z);
386
+ v.set(min.x, max.y, min.z);
387
+ p = Vector3.TransformCoordinates(v, invViewMatrix);
388
+ positions.push(p.x, p.y, p.z);
389
+ indices.push(0, 2, 1);
390
+ indices.push(2, 3, 1);
391
+ }
392
+ // Tesselate the far plane
393
+ let y = min.y;
394
+ for (let iy = 0; iy <= numTesselation; ++iy) {
395
+ let x = min.x;
396
+ for (let ix = 0; ix <= numTesselation; ++ix) {
397
+ v.set(x, y, min.z);
398
+ const p = Vector3.TransformCoordinates(v, invViewMatrix);
399
+ positions.push(p.x, p.y, p.z);
400
+ if (ix < numTesselation && iy < numTesselation) {
401
+ indices.push(startFarIndices + ix + iy * (numTesselation + 1), startFarIndices + ix + 1 + iy * (numTesselation + 1), startFarIndices + ix + 1 + (iy + 1) * (numTesselation + 1));
402
+ indices.push(startFarIndices + ix + iy * (numTesselation + 1), startFarIndices + ix + 1 + (iy + 1) * (numTesselation + 1), startFarIndices + ix + (iy + 1) * (numTesselation + 1));
403
+ }
404
+ x += stepX;
405
+ }
406
+ y += stepY;
407
+ }
408
+ if (this._uBuffer && this._cs) {
409
+ const webGPUEngine = this._engine;
410
+ this._storageBuffer?.dispose();
411
+ this._storageBuffer = new StorageBuffer(webGPUEngine, positions.length * 4, 8 | 3);
412
+ this._storageBuffer.update(positions);
413
+ const vertexBuffer = new VertexBuffer(webGPUEngine, this._storageBuffer.getBuffer(), "position");
414
+ this._mesh.setVerticesBuffer(vertexBuffer);
415
+ this._cs.setStorageBuffer("positions", this._storageBuffer);
416
+ this._uBuffer.updateUInt("startVertexIndex", this._buildFullVolume ? (numTesselation + 1) * 4 * 3 : 4 * 3);
417
+ this._uBuffer.updateFloat("step", ((this._shadowGenerator?.mapSize ?? 128) - 1) / numTesselation);
418
+ this._uBuffer.updateUInt("tesselation", numTesselation);
419
+ }
420
+ else {
421
+ this._mesh.setVerticesData("position", positions);
422
+ }
423
+ this._mesh.setIndices(indices, positions.length / 3);
424
+ }
425
+ }
426
+ //# sourceMappingURL=lightingVolume.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lightingVolume.js","sourceRoot":"","sources":["../../../../dev/core/src/Lights/lightingVolume.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AbstractEngine, Engine, Nullable, RenderTargetWrapper, Scene, ShadowGenerator, WebGPUEngine } from \"core/index\";\r\nimport { AbortError } from \"core/Misc/error\";\r\nimport { Constants } from \"core/Engines/constants\";\r\nimport { Matrix, Vector3 } from \"core/Maths/math.vector\";\r\nimport { DirectionalLight } from \"core/Lights/directionalLight\";\r\nimport { Mesh } from \"core/Meshes/mesh\";\r\nimport { ComputeShader } from \"core/Compute/computeShader\";\r\nimport { CopyTextureToTexture } from \"core/Misc/copyTextureToTexture\";\r\nimport { UniformBuffer } from \"core/Materials/uniformBuffer\";\r\nimport { StorageBuffer } from \"core/Buffers/storageBuffer\";\r\nimport { BaseTexture } from \"core/Materials/Textures/baseTexture\";\r\nimport { VertexBuffer } from \"core/Buffers/buffer\";\r\n\r\nimport \"core/ShadersWGSL/lightingVolume.compute\";\r\n\r\nconst InvViewProjMatrix = new Matrix();\r\nconst TmpVec3 = new Vector3();\r\n\r\n/**\r\n * Class used to create a lighting volume from a directional light's shadow generator.\r\n */\r\nexport class LightingVolume {\r\n private readonly _engine: AbstractEngine;\r\n private readonly _scene: Scene;\r\n private readonly _mesh: Mesh;\r\n private readonly _copyTexture?: CopyTextureToTexture;\r\n private readonly _uBuffer?: UniformBuffer;\r\n private _name: string;\r\n private _cs?: ComputeShader;\r\n private _light?: DirectionalLight;\r\n private _fallbackTexture?: BaseTexture;\r\n private _storageBuffer?: StorageBuffer;\r\n private _depthCopy?: RenderTargetWrapper;\r\n private _readPixelPromise: Nullable<Promise<ArrayBufferView>> = null;\r\n private _readPixelAbortController: Nullable<AbortController> = null;\r\n private _numFrames = 0;\r\n private _firstUpdate = true;\r\n\r\n private _shadowGenerator?: ShadowGenerator;\r\n /**\r\n * The shadow generator used to create the lighting volume.\r\n */\r\n public get shadowGenerator() {\r\n return this._shadowGenerator!;\r\n }\r\n\r\n public set shadowGenerator(sg: ShadowGenerator) {\r\n const light = sg.getLight();\r\n\r\n if (!(light instanceof DirectionalLight)) {\r\n throw new Error(`LightingVolumeMesh ${this._name}: light must be a directional light`);\r\n }\r\n\r\n this._shadowGenerator = sg;\r\n this._light = light;\r\n\r\n this._createGeometry();\r\n\r\n if (!this._engine.isWebGPU) {\r\n this._createFallbackTextures();\r\n }\r\n\r\n const depthTexture = this._shadowGenerator.getShadowMap()?.depthStencilTexture;\r\n if (this._cs && depthTexture) {\r\n this._cs.setInternalTexture(\"shadowMap\", depthTexture);\r\n }\r\n }\r\n\r\n private _tesselation = 0;\r\n /**\r\n * The tesselation level of the lighting volume.\r\n */\r\n public get tesselation() {\r\n return this._tesselation;\r\n }\r\n\r\n public set tesselation(n: number) {\r\n this._tesselation = n;\r\n this._createGeometry();\r\n }\r\n\r\n private _buildFullVolume = false;\r\n /**\r\n * Indicates whether to build the full volume (true) or only the far plane (false). Default is false.\r\n */\r\n public get buildFullVolume() {\r\n return this._buildFullVolume;\r\n }\r\n\r\n public set buildFullVolume(value: boolean) {\r\n if (this._buildFullVolume === value) {\r\n return;\r\n }\r\n this._buildFullVolume = value;\r\n this._createGeometry();\r\n this._createComputeShader();\r\n }\r\n\r\n /**\r\n * The mesh used as a support for the lighting volume.\r\n * Note that this mesh is not automatically added to the scene's mesh array.\r\n * If you want to render it, you need to add it manually.\r\n */\r\n public get mesh() {\r\n return this._mesh;\r\n }\r\n\r\n private _frequency = 1;\r\n\r\n /**\r\n * The frequency (in number of times you call updateMesh) at which the lighting volume is updated.\r\n */\r\n public get frequency() {\r\n return this._frequency;\r\n }\r\n\r\n public set frequency(value: number) {\r\n this._frequency = value;\r\n this._firstUpdate = true;\r\n }\r\n\r\n /**\r\n * The name of the lighting volume.\r\n */\r\n public get name() {\r\n return this._name;\r\n }\r\n\r\n public set name(name: string) {\r\n this._name = name;\r\n if (this._mesh) {\r\n this._mesh.name = name;\r\n }\r\n }\r\n\r\n /**\r\n * Indicates whether this is the first update of the lighting volume.\r\n * If true, the volume has not yet been updated for the first time.\r\n */\r\n public get firstUpdate() {\r\n return this._firstUpdate;\r\n }\r\n\r\n /**\r\n * Creates a new LightingVolume.\r\n * @param name The name of the lighting volume.\r\n * @param scene The scene the lighting volume belongs to.\r\n * @param shadowGenerator The shadow generator used to create the lighting volume. This is optional in the constructor, but must be set before calling updateMesh.\r\n * @param tesselation The tesselation level of the lighting volume (default: 64).\r\n */\r\n constructor(name: string, scene: Scene, shadowGenerator?: ShadowGenerator, tesselation = 64) {\r\n const light = shadowGenerator ? shadowGenerator.getLight() : undefined;\r\n\r\n if (light && !(light instanceof DirectionalLight)) {\r\n throw new Error(`LightingVolumeMesh ${name}: light must be a directional light`);\r\n }\r\n\r\n this._name = name;\r\n this._shadowGenerator = shadowGenerator;\r\n this._light = light as DirectionalLight;\r\n\r\n this._engine = scene.getEngine();\r\n this._scene = scene;\r\n\r\n this._mesh = new Mesh(name, this._scene);\r\n scene.meshes.splice(scene.meshes.indexOf(this._mesh), 1);\r\n\r\n if (this._engine.isWebGPU) {\r\n this._uBuffer = new UniformBuffer(this._engine);\r\n\r\n this._uBuffer.addUniform(\"invViewProjMatrix\", 16);\r\n this._uBuffer.addUniform(\"startVertexIndex\", 1);\r\n this._uBuffer.addUniform(\"step\", 1);\r\n this._uBuffer.addUniform(\"tesselation\", 1);\r\n this._uBuffer.update();\r\n\r\n this._createComputeShader();\r\n } else {\r\n this._copyTexture = new CopyTextureToTexture(this._engine, false, true);\r\n this._createFallbackTextures();\r\n }\r\n\r\n this._tesselation = tesselation;\r\n this._createGeometry();\r\n }\r\n\r\n /**\r\n * Checks if the lighting volume is ready to be updated.\r\n * @returns True if the volume is ready to be updated.\r\n */\r\n public isReady() {\r\n let isReady = this._mesh.isReady(true);\r\n if (this._cs) {\r\n isReady = this._cs.isReady() && isReady;\r\n }\r\n return isReady;\r\n }\r\n\r\n /**\r\n * Updates the lighting volume mesh.\r\n * @param forceUpdate If true, forces the update even if the frequency condition is not met.\r\n */\r\n public update(forceUpdate = false) {\r\n if (this._tesselation === 0 || !this._shadowGenerator) {\r\n return;\r\n }\r\n\r\n if (!forceUpdate && !this._firstUpdate && (this.frequency === 0 || ++this._numFrames < this.frequency)) {\r\n return;\r\n }\r\n\r\n this._numFrames = 0;\r\n\r\n if (this._cs && this._uBuffer) {\r\n const dispatchSize = Math.ceil((this._tesselation + 1) / 8);\r\n\r\n const viewProjMatrix = this._shadowGenerator.getTransformMatrix();\r\n viewProjMatrix.invertToRef(InvViewProjMatrix);\r\n\r\n this._uBuffer.updateMatrix(\"invViewProjMatrix\", InvViewProjMatrix);\r\n this._uBuffer.update();\r\n\r\n this._engine._debugPushGroup?.(`Generate lighting volume (${this._name})`);\r\n this._cs.dispatch(dispatchSize, dispatchSize, 1);\r\n this._engine._debugPopGroup?.();\r\n\r\n this._firstUpdate = false;\r\n } else {\r\n try {\r\n void this._fallbackReadPixelAsync();\r\n } catch {\r\n this._readPixelPromise = null;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Disposes the lighting volume and associated resources.\r\n */\r\n public dispose() {\r\n this._readPixelAbortController?.abort(new AbortError(\"LightingVolume is disposed\"));\r\n this._readPixelAbortController = null;\r\n this._mesh.dispose();\r\n if (this._fallbackTexture) {\r\n this._fallbackTexture._texture = null;\r\n }\r\n this._fallbackTexture?.dispose();\r\n this._copyTexture?.dispose();\r\n this._storageBuffer?.dispose();\r\n this._uBuffer?.dispose();\r\n this._depthCopy?.dispose();\r\n }\r\n\r\n private _createComputeShader() {\r\n this._cs = new ComputeShader(\"createLightVolume\", this._engine, \"lightingVolume\", {\r\n bindingsMapping: {\r\n shadowMap: { group: 0, binding: 0 },\r\n params: { group: 0, binding: 1 },\r\n positions: { group: 0, binding: 2 },\r\n },\r\n defines: !this._buildFullVolume ? [\"#define KEEP_EDGES\", \"#define MOVE_FAR_DEPTH_TO_NEAR\"] : undefined,\r\n });\r\n\r\n if (this._shadowGenerator) {\r\n const depthTexture = this._shadowGenerator.getShadowMap()?.depthStencilTexture;\r\n if (depthTexture) {\r\n this._cs.setInternalTexture(\"shadowMap\", depthTexture);\r\n }\r\n }\r\n\r\n if (this._uBuffer) {\r\n this._cs.setUniformBuffer(\"params\", this._uBuffer);\r\n }\r\n if (this._storageBuffer) {\r\n this._cs.setStorageBuffer(\"positions\", this._storageBuffer);\r\n }\r\n }\r\n\r\n private _createFallbackTextures() {\r\n if (!this._shadowGenerator) {\r\n return;\r\n }\r\n\r\n this._readPixelAbortController?.abort(new AbortError(\"Fallback textures are being (re)created\"));\r\n this._readPixelAbortController = new AbortController();\r\n\r\n const mapSize = this._shadowGenerator.mapSize;\r\n\r\n this._depthCopy?.dispose();\r\n this._depthCopy = this._engine.createRenderTargetTexture(\r\n { width: mapSize, height: mapSize },\r\n {\r\n type: Constants.TEXTURETYPE_FLOAT,\r\n format: Constants.TEXTUREFORMAT_RED,\r\n samples: 1,\r\n label: `${this._name} - fallback internal texture`,\r\n generateDepthBuffer: false,\r\n }\r\n );\r\n\r\n this._fallbackTexture?.dispose();\r\n this._fallbackTexture = new BaseTexture(this._scene, this._depthCopy.texture);\r\n this._fallbackTexture.name = `${this._name} - fallback texture`;\r\n }\r\n\r\n private async _fallbackReadPixelAsync() {\r\n if (this._readPixelPromise || !this._fallbackTexture || !this._copyTexture) {\r\n return;\r\n }\r\n\r\n const abortController = this._readPixelAbortController;\r\n\r\n abortController?.signal.throwIfAborted();\r\n\r\n const engine = this._engine as Engine;\r\n\r\n const shadowGenerator = this._shadowGenerator;\r\n const shadowMapDepthTexture = shadowGenerator?.getShadowMap()?.depthStencilTexture;\r\n\r\n if (!shadowMapDepthTexture) {\r\n return;\r\n }\r\n\r\n // Copies the shadow map of the shadow generator into _depthCopy\r\n // That's because we can't read from a depth attachment texture in WebGL. We must first copy it to a regular texture.\r\n engine.updateTextureSamplingMode(Constants.TEXTURE_NEAREST_SAMPLINGMODE, shadowMapDepthTexture);\r\n engine.updateTextureComparisonFunction(shadowMapDepthTexture, 0);\r\n\r\n this._copyTexture.copy(shadowMapDepthTexture, this._depthCopy);\r\n\r\n engine.updateTextureComparisonFunction(shadowMapDepthTexture, Constants.LESS);\r\n\r\n // Gets the texture from GPU to CPU\r\n this._readPixelPromise = this._fallbackTexture.readPixels(0, 0, undefined, true, false);\r\n if (!this._readPixelPromise) {\r\n return;\r\n }\r\n\r\n const buffer = await this._readPixelPromise;\r\n\r\n abortController?.signal.throwIfAborted();\r\n\r\n const depthValues = buffer as Float32Array;\r\n const positions = this._mesh.getVerticesData(\"position\");\r\n const numTesselation = this._tesselation;\r\n const startPos = this._buildFullVolume ? (numTesselation + 1) * 4 * 3 : 4 * 3;\r\n const mapSize = shadowGenerator.mapSize;\r\n const step = (mapSize - 1) / numTesselation;\r\n\r\n if (!positions) {\r\n this._readPixelPromise = null;\r\n return;\r\n }\r\n\r\n const halfTesselation = numTesselation / 2;\r\n\r\n const invViewProjMatrix = shadowGenerator.getTransformMatrix().clone();\r\n invViewProjMatrix.invertToRef(invViewProjMatrix);\r\n\r\n const factor = 4;\r\n\r\n let posIndex = startPos;\r\n let stepY = 0;\r\n for (let y = 0; y < numTesselation + 1; ++y) {\r\n for (let x = 0; x < numTesselation + 1; ++x) {\r\n let depth = depthValues[Math.floor(mapSize * Math.floor(stepY) + x * step) * factor];\r\n if (!this._buildFullVolume && (depth === 1 || y === 0 || x === 0 || y === numTesselation || x === numTesselation)) {\r\n depth = 0;\r\n }\r\n\r\n TmpVec3.set((x - halfTesselation) / halfTesselation, (y - halfTesselation) / halfTesselation, -1 + 2 * depth);\r\n\r\n Vector3.TransformCoordinatesToRef(TmpVec3, invViewProjMatrix, TmpVec3);\r\n\r\n positions[posIndex] = TmpVec3.x;\r\n positions[posIndex + 1] = TmpVec3.y;\r\n positions[posIndex + 2] = TmpVec3.z;\r\n posIndex += 3;\r\n }\r\n stepY += step;\r\n }\r\n\r\n this._mesh.setVerticesData(\"position\", positions);\r\n\r\n this._readPixelPromise = null;\r\n this._firstUpdate = false;\r\n }\r\n\r\n private _createGeometry() {\r\n if (!this._light) {\r\n return;\r\n }\r\n\r\n this._tesselation = Math.max(Math.ceil(this._tesselation) & ~1, 2);\r\n\r\n const light = this._light;\r\n\r\n const min = new Vector3(light.orthoLeft, light.orthoBottom, light.shadowMinZ ?? Constants.ShadowMinZ);\r\n const max = new Vector3(light.orthoRight, light.orthoTop, light.shadowMaxZ ?? Constants.ShadowMaxZ);\r\n\r\n const invViewMatrix = Matrix.LookAtLH(light.position, light.position.add(light.direction), Vector3.UpReadOnly);\r\n invViewMatrix.invertToRef(invViewMatrix);\r\n\r\n const positions: number[] = [];\r\n const indices: number[] = [];\r\n\r\n const numTesselation = this._tesselation;\r\n const stepX = (max.x - min.x) / numTesselation;\r\n const stepY = (max.y - min.y) / numTesselation;\r\n const v = new Vector3();\r\n\r\n const startFarIndices = this._buildFullVolume ? (numTesselation + 1) * 4 : 4;\r\n\r\n if (this._buildFullVolume) {\r\n let startIndices = 0;\r\n\r\n // Right faces of the frustum\r\n for (let i = 0; i <= numTesselation; ++i) {\r\n v.set(max.x, min.y + i * stepY, min.z);\r\n\r\n const p = Vector3.TransformCoordinates(v, invViewMatrix);\r\n positions.push(p.x, p.y, p.z);\r\n\r\n if (i < numTesselation) {\r\n indices.push(startIndices + i, startFarIndices + numTesselation + (i + 1) * (numTesselation + 1), startFarIndices + numTesselation + i * (numTesselation + 1));\r\n indices.push(startIndices + i, startIndices + i + 1, startFarIndices + numTesselation + (i + 1) * (numTesselation + 1));\r\n }\r\n }\r\n\r\n const n0 = 0;\r\n const n1 = positions.length / 3 - 1;\r\n const n2 = n1 + 1;\r\n\r\n startIndices = positions.length / 3;\r\n\r\n // Left faces of the frustum\r\n for (let i = 0; i <= numTesselation; ++i) {\r\n v.set(min.x, min.y + i * stepY, min.z);\r\n\r\n const p = Vector3.TransformCoordinates(v, invViewMatrix);\r\n positions.push(p.x, p.y, p.z);\r\n\r\n if (i < numTesselation) {\r\n indices.push(startIndices + i, startFarIndices + 0 + i * (numTesselation + 1), startFarIndices + 0 + (i + 1) * (numTesselation + 1));\r\n indices.push(startIndices + i, startFarIndices + 0 + (i + 1) * (numTesselation + 1), startIndices + i + 1);\r\n }\r\n }\r\n\r\n const n3 = positions.length / 3 - 1;\r\n\r\n startIndices = positions.length / 3;\r\n\r\n // Bottom faces of the frustum\r\n for (let i = 0; i <= numTesselation; ++i) {\r\n v.set(min.x + i * stepX, min.y, min.z);\r\n\r\n const p = Vector3.TransformCoordinates(v, invViewMatrix);\r\n positions.push(p.x, p.y, p.z);\r\n\r\n if (i < numTesselation) {\r\n indices.push(startIndices + i, startIndices + i + 1, startFarIndices + i + 0 * (numTesselation + 1));\r\n indices.push(startIndices + i + 1, startFarIndices + i + 1 + 0 * (numTesselation + 1), startFarIndices + i + 0 * (numTesselation + 1));\r\n }\r\n }\r\n\r\n startIndices = positions.length / 3;\r\n\r\n // Top faces of the frustum\r\n for (let i = 0; i <= numTesselation; ++i) {\r\n v.set(min.x + i * stepX, max.y, min.z);\r\n\r\n const p = Vector3.TransformCoordinates(v, invViewMatrix);\r\n positions.push(p.x, p.y, p.z);\r\n\r\n if (i < numTesselation) {\r\n indices.push(startIndices + i, startFarIndices + i + numTesselation * (numTesselation + 1), startIndices + i + 1);\r\n indices.push(\r\n startIndices + i + 1,\r\n startFarIndices + i + numTesselation * (numTesselation + 1),\r\n startFarIndices + i + 1 + numTesselation * (numTesselation + 1)\r\n );\r\n }\r\n }\r\n\r\n startIndices = positions.length / 3;\r\n\r\n // Near faces of the frustum\r\n indices.push(n0, n2, n1);\r\n indices.push(n2, n3, n1);\r\n } else {\r\n let p: Vector3;\r\n\r\n v.set(max.x, min.y, min.z);\r\n p = Vector3.TransformCoordinates(v, invViewMatrix);\r\n positions.push(p.x, p.y, p.z);\r\n\r\n v.set(max.x, max.y, min.z);\r\n p = Vector3.TransformCoordinates(v, invViewMatrix);\r\n positions.push(p.x, p.y, p.z);\r\n\r\n v.set(min.x, min.y, min.z);\r\n p = Vector3.TransformCoordinates(v, invViewMatrix);\r\n positions.push(p.x, p.y, p.z);\r\n\r\n v.set(min.x, max.y, min.z);\r\n p = Vector3.TransformCoordinates(v, invViewMatrix);\r\n positions.push(p.x, p.y, p.z);\r\n\r\n indices.push(0, 2, 1);\r\n indices.push(2, 3, 1);\r\n }\r\n\r\n // Tesselate the far plane\r\n let y = min.y;\r\n for (let iy = 0; iy <= numTesselation; ++iy) {\r\n let x = min.x;\r\n for (let ix = 0; ix <= numTesselation; ++ix) {\r\n v.set(x, y, min.z);\r\n\r\n const p = Vector3.TransformCoordinates(v, invViewMatrix);\r\n positions.push(p.x, p.y, p.z);\r\n\r\n if (ix < numTesselation && iy < numTesselation) {\r\n indices.push(\r\n startFarIndices + ix + iy * (numTesselation + 1),\r\n startFarIndices + ix + 1 + iy * (numTesselation + 1),\r\n startFarIndices + ix + 1 + (iy + 1) * (numTesselation + 1)\r\n );\r\n indices.push(\r\n startFarIndices + ix + iy * (numTesselation + 1),\r\n startFarIndices + ix + 1 + (iy + 1) * (numTesselation + 1),\r\n startFarIndices + ix + (iy + 1) * (numTesselation + 1)\r\n );\r\n }\r\n x += stepX;\r\n }\r\n y += stepY;\r\n }\r\n\r\n if (this._uBuffer && this._cs) {\r\n const webGPUEngine = this._engine as WebGPUEngine;\r\n\r\n this._storageBuffer?.dispose();\r\n this._storageBuffer = new StorageBuffer(webGPUEngine, positions.length * 4, Constants.BUFFER_CREATIONFLAG_VERTEX | Constants.BUFFER_CREATIONFLAG_READWRITE);\r\n\r\n this._storageBuffer.update(positions);\r\n\r\n const vertexBuffer = new VertexBuffer(webGPUEngine, this._storageBuffer.getBuffer(), \"position\");\r\n\r\n this._mesh.setVerticesBuffer(vertexBuffer);\r\n\r\n this._cs.setStorageBuffer(\"positions\", this._storageBuffer);\r\n\r\n this._uBuffer.updateUInt(\"startVertexIndex\", this._buildFullVolume ? (numTesselation + 1) * 4 * 3 : 4 * 3);\r\n this._uBuffer.updateFloat(\"step\", ((this._shadowGenerator?.mapSize ?? 128) - 1) / numTesselation);\r\n this._uBuffer.updateUInt(\"tesselation\", numTesselation);\r\n } else {\r\n this._mesh.setVerticesData(\"position\", positions);\r\n }\r\n\r\n this._mesh.setIndices(indices, positions.length / 3);\r\n }\r\n}\r\n"]}
@@ -1747,6 +1747,11 @@ export class NodeMaterial extends NodeMaterialBase {
1747
1747
  if (!merge) {
1748
1748
  this.clear();
1749
1749
  }
1750
+ const id = this.id;
1751
+ const uniqueId = this.uniqueId;
1752
+ SerializationHelper.ParseProperties(source, this, this.getScene(), rootUrl);
1753
+ this.id = id;
1754
+ this.uniqueId = uniqueId;
1750
1755
  const map = {};
1751
1756
  // Create blocks
1752
1757
  for (const parsedBlock of source.blocks) {
@@ -1826,7 +1831,6 @@ export class NodeMaterial extends NodeMaterialBase {
1826
1831
  * @deprecated Please use the parseSerializedObject method instead
1827
1832
  */
1828
1833
  loadFromSerialization(source, rootUrl = "", merge = false) {
1829
- SerializationHelper.ParseProperties(source, this, this.getScene(), rootUrl);
1830
1834
  this.parseSerializedObject(source, rootUrl, merge);
1831
1835
  }
1832
1836
  /**
@@ -1838,9 +1842,9 @@ export class NodeMaterial extends NodeMaterialBase {
1838
1842
  clone(name, shareEffect = false) {
1839
1843
  const serializationObject = this.serialize();
1840
1844
  const clone = SerializationHelper.Clone(() => new NodeMaterial(name, this.getScene(), this.options), this);
1845
+ clone.parseSerializedObject(serializationObject);
1841
1846
  clone.id = name;
1842
1847
  clone.name = name;
1843
- clone.parseSerializedObject(serializationObject);
1844
1848
  clone._buildId = this._buildId;
1845
1849
  clone.build(false, !shareEffect);
1846
1850
  return clone;
@@ -1898,9 +1902,11 @@ export class NodeMaterial extends NodeMaterialBase {
1898
1902
  */
1899
1903
  static async ParseFromFileAsync(name, url, scene, rootUrl = "", skipBuild = false, targetMaterial, urlRewriter, options) {
1900
1904
  const material = targetMaterial ?? new NodeMaterial(name, scene, options);
1905
+ const finalName = material.name;
1901
1906
  const data = await scene._loadFileAsync(url);
1902
1907
  const serializationObject = JSON.parse(data);
1903
1908
  material.parseSerializedObject(serializationObject, rootUrl, undefined, urlRewriter);
1909
+ material.name = finalName; // in case it was changed during parse
1904
1910
  if (!skipBuild) {
1905
1911
  material.build();
1906
1912
  }