@babylonjs/core 9.2.0 → 9.2.2
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/Animations/animation.d.ts +9 -0
- package/Animations/animation.js +9 -0
- package/Animations/animation.js.map +1 -1
- package/Animations/runtimeAnimation.js +28 -0
- package/Animations/runtimeAnimation.js.map +1 -1
- package/Cameras/Inputs/geospatialCameraPointersInput.js +10 -8
- package/Cameras/Inputs/geospatialCameraPointersInput.js.map +1 -1
- package/Cameras/geospatialCameraMovement.js +21 -21
- package/Cameras/geospatialCameraMovement.js.map +1 -1
- package/Debug/physicsViewer.js +2 -12
- package/Debug/physicsViewer.js.map +1 -1
- package/Engines/abstractEngine.js +2 -2
- package/Engines/abstractEngine.js.map +1 -1
- package/Engines/webgpuEngine.js +2 -0
- package/Engines/webgpuEngine.js.map +1 -1
- package/FlowGraph/Blocks/flowGraphBlockFactory.js +14 -1
- package/FlowGraph/Blocks/flowGraphBlockFactory.js.map +1 -1
- package/FlowGraph/flowGraph.js +6 -0
- package/FlowGraph/flowGraph.js.map +1 -1
- package/FlowGraph/flowGraphEventBlock.d.ts +10 -0
- package/FlowGraph/flowGraphEventBlock.js +24 -0
- package/FlowGraph/flowGraphEventBlock.js.map +1 -1
- package/FlowGraph/flowGraphParser.js +23 -4
- package/FlowGraph/flowGraphParser.js.map +1 -1
- package/FlowGraph/serialization.js +36 -14
- package/FlowGraph/serialization.js.map +1 -1
- package/FrameGraph/Node/Blocks/Rendering/iblShadowsRendererBlock.d.ts +105 -0
- package/FrameGraph/Node/Blocks/Rendering/iblShadowsRendererBlock.js +318 -0
- package/FrameGraph/Node/Blocks/Rendering/iblShadowsRendererBlock.js.map +1 -0
- package/FrameGraph/Node/Blocks/index.d.ts +1 -0
- package/FrameGraph/Node/Blocks/index.js +1 -0
- package/FrameGraph/Node/Blocks/index.js.map +1 -1
- package/FrameGraph/Tasks/Rendering/iblShadows/iblShadowsAccumulationTask.d.ts +34 -0
- package/FrameGraph/Tasks/Rendering/iblShadows/iblShadowsAccumulationTask.js +144 -0
- package/FrameGraph/Tasks/Rendering/iblShadows/iblShadowsAccumulationTask.js.map +1 -0
- package/FrameGraph/Tasks/Rendering/iblShadows/iblShadowsSpatialBlurTask.d.ts +26 -0
- package/FrameGraph/Tasks/Rendering/iblShadows/iblShadowsSpatialBlurTask.js +82 -0
- package/FrameGraph/Tasks/Rendering/iblShadows/iblShadowsSpatialBlurTask.js.map +1 -0
- package/FrameGraph/Tasks/Rendering/iblShadows/iblShadowsTracingTask.d.ts +61 -0
- package/FrameGraph/Tasks/Rendering/iblShadows/iblShadowsTracingTask.js +207 -0
- package/FrameGraph/Tasks/Rendering/iblShadows/iblShadowsTracingTask.js.map +1 -0
- package/FrameGraph/Tasks/Rendering/iblShadows/iblShadowsVoxelizationTask.d.ts +104 -0
- package/FrameGraph/Tasks/Rendering/iblShadows/iblShadowsVoxelizationTask.js +218 -0
- package/FrameGraph/Tasks/Rendering/iblShadows/iblShadowsVoxelizationTask.js.map +1 -0
- package/FrameGraph/Tasks/Rendering/iblShadowsRendererTask.d.ts +217 -0
- package/FrameGraph/Tasks/Rendering/iblShadowsRendererTask.js +640 -0
- package/FrameGraph/Tasks/Rendering/iblShadowsRendererTask.js.map +1 -0
- package/FrameGraph/frameGraph.js +1 -0
- package/FrameGraph/frameGraph.js.map +1 -1
- package/FrameGraph/index.d.ts +1 -0
- package/FrameGraph/index.js +1 -0
- package/FrameGraph/index.js.map +1 -1
- package/Gizmos/boundingBoxGizmo.js +4 -0
- package/Gizmos/boundingBoxGizmo.js.map +1 -1
- package/Layers/thinEffectLayer.js +8 -1
- package/Layers/thinEffectLayer.js.map +1 -1
- package/Lights/Clustered/clusteredLightContainer.js +8 -5
- package/Lights/Clustered/clusteredLightContainer.js.map +1 -1
- package/Loading/Plugins/babylonFileLoader.js +26 -0
- package/Loading/Plugins/babylonFileLoader.js.map +1 -1
- package/Materials/GaussianSplatting/gaussianSplattingMaterial.js +15 -2
- package/Materials/GaussianSplatting/gaussianSplattingMaterial.js.map +1 -1
- package/Materials/Node/Blocks/Fragment/fragmentOutputBlock.js +3 -1
- package/Materials/Node/Blocks/Fragment/fragmentOutputBlock.js.map +1 -1
- package/Materials/PBR/openpbrMaterial.d.ts +13 -2
- package/Materials/PBR/openpbrMaterial.js +47 -16
- package/Materials/PBR/openpbrMaterial.js.map +1 -1
- package/Materials/PBR/pbrBRDFConfiguration.js +1 -1
- package/Materials/PBR/pbrBRDFConfiguration.js.map +1 -1
- package/Materials/Textures/Filtering/hdrFiltering.js +6 -0
- package/Materials/Textures/Filtering/hdrFiltering.js.map +1 -1
- package/Materials/Textures/envCubeTexture.js +13 -13
- package/Materials/Textures/envCubeTexture.js.map +1 -1
- package/Materials/materialHelper.functions.js +1 -1
- package/Materials/materialHelper.functions.js.map +1 -1
- package/Meshes/GaussianSplatting/gaussianSplattingCompoundMesh.d.ts +18 -4
- package/Meshes/GaussianSplatting/gaussianSplattingCompoundMesh.js +29 -4
- package/Meshes/GaussianSplatting/gaussianSplattingCompoundMesh.js.map +1 -1
- package/Meshes/GaussianSplatting/gaussianSplattingMesh.d.ts +48 -8
- package/Meshes/GaussianSplatting/gaussianSplattingMesh.js +373 -84
- package/Meshes/GaussianSplatting/gaussianSplattingMesh.js.map +1 -1
- package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.d.ts +39 -4
- package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.js +152 -47
- package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.js.map +1 -1
- package/Meshes/GaussianSplatting/gaussianSplattingPartProxyMesh.d.ts +61 -7
- package/Meshes/GaussianSplatting/gaussianSplattingPartProxyMesh.js +94 -11
- package/Meshes/GaussianSplatting/gaussianSplattingPartProxyMesh.js.map +1 -1
- package/Meshes/mesh.d.ts +15 -0
- package/Meshes/mesh.js +40 -1
- package/Meshes/mesh.js.map +1 -1
- package/Meshes/transformNode.js +2 -2
- package/Meshes/transformNode.js.map +1 -1
- package/Misc/sceneSerializer.js +2 -1
- package/Misc/sceneSerializer.js.map +1 -1
- package/Misc/textureTools.d.ts +3 -1
- package/Misc/textureTools.js +74 -13
- package/Misc/textureTools.js.map +1 -1
- package/Misc/tools.js +1 -1
- package/Misc/tools.js.map +1 -1
- package/Particles/baseParticleSystem.d.ts +47 -1
- package/Particles/baseParticleSystem.js +88 -0
- package/Particles/baseParticleSystem.js.map +1 -1
- package/Particles/computeShaderParticleSystem.js +12 -0
- package/Particles/computeShaderParticleSystem.js.map +1 -1
- package/Particles/gpuParticleSystem.d.ts +61 -25
- package/Particles/gpuParticleSystem.js +249 -75
- package/Particles/gpuParticleSystem.js.map +1 -1
- package/Particles/particleSystem.d.ts +0 -6
- package/Particles/particleSystem.js +3 -14
- package/Particles/particleSystem.js.map +1 -1
- package/Particles/thinParticleSystem.d.ts +1 -17
- package/Particles/thinParticleSystem.js +1 -50
- package/Particles/thinParticleSystem.js.map +1 -1
- package/Particles/webgl2ParticleSystem.d.ts +1 -0
- package/Particles/webgl2ParticleSystem.js +18 -2
- package/Particles/webgl2ParticleSystem.js.map +1 -1
- package/Rendering/IBLShadows/iblShadowsAccumulationPass.js +1 -1
- package/Rendering/IBLShadows/iblShadowsAccumulationPass.js.map +1 -1
- package/Rendering/IBLShadows/iblShadowsPluginMaterial.d.ts +3 -1
- package/Rendering/IBLShadows/iblShadowsPluginMaterial.js +11 -1
- package/Rendering/IBLShadows/iblShadowsPluginMaterial.js.map +1 -1
- package/Rendering/IBLShadows/iblShadowsRenderPipeline.d.ts +0 -19
- package/Rendering/IBLShadows/iblShadowsRenderPipeline.js +21 -65
- package/Rendering/IBLShadows/iblShadowsRenderPipeline.js.map +1 -1
- package/Rendering/IBLShadows/iblShadowsVoxelRenderer.d.ts +15 -52
- package/Rendering/IBLShadows/iblShadowsVoxelRenderer.js +129 -220
- package/Rendering/IBLShadows/iblShadowsVoxelRenderer.js.map +1 -1
- package/Rendering/IBLShadows/iblShadowsVoxelTracingPass.js +3 -0
- package/Rendering/IBLShadows/iblShadowsVoxelTracingPass.js.map +1 -1
- package/Rendering/depthRenderer.js +6 -0
- package/Rendering/depthRenderer.js.map +1 -1
- package/Rendering/geometryBufferRenderer.d.ts +14 -5
- package/Rendering/geometryBufferRenderer.js +6 -2
- package/Rendering/geometryBufferRenderer.js.map +1 -1
- package/Rendering/geometryBufferRendererSceneComponent.d.ts +4 -6
- package/Rendering/geometryBufferRendererSceneComponent.js.map +1 -1
- package/Rendering/iblCdfGenerator.d.ts +10 -0
- package/Rendering/iblCdfGenerator.js +52 -17
- package/Rendering/iblCdfGenerator.js.map +1 -1
- package/Rendering/index.d.ts +0 -6
- package/Rendering/index.js +0 -6
- package/Rendering/index.js.map +1 -1
- package/Shaders/ShadersInclude/gaussianSplatting.js +25 -4
- package/Shaders/ShadersInclude/gaussianSplatting.js.map +1 -1
- package/Shaders/ShadersInclude/openpbrDirectLighting.js +6 -1
- package/Shaders/ShadersInclude/openpbrDirectLighting.js.map +1 -1
- package/Shaders/ShadersInclude/openpbrEnvironmentLighting.js +1 -1
- package/Shaders/ShadersInclude/openpbrEnvironmentLighting.js.map +1 -1
- package/Shaders/gaussianSplatting.vertex.js +3 -0
- package/Shaders/gaussianSplatting.vertex.js.map +1 -1
- package/Shaders/gpuRenderParticles.vertex.js +14 -2
- package/Shaders/gpuRenderParticles.vertex.js.map +1 -1
- package/Shaders/gpuUpdateParticles.vertex.js +24 -6
- package/Shaders/gpuUpdateParticles.vertex.js.map +1 -1
- package/Shaders/iblShadowVoxelTracing.fragment.js +5 -1
- package/Shaders/iblShadowVoxelTracing.fragment.js.map +1 -1
- package/Shaders/iblVoxelGrid.fragment.d.ts +1 -0
- package/Shaders/iblVoxelGrid.fragment.js +33 -5
- package/Shaders/iblVoxelGrid.fragment.js.map +1 -1
- package/Shaders/{iblVoxelSlabDebug.fragment.d.ts → lod3D.fragment.d.ts} +1 -1
- package/Shaders/lod3D.fragment.js +13 -0
- package/Shaders/lod3D.fragment.js.map +1 -0
- package/Shaders/openpbr.fragment.js +5 -0
- package/Shaders/openpbr.fragment.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/gaussianSplatting.js +37 -5
- package/ShadersWGSL/ShadersInclude/gaussianSplatting.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/openpbrDirectLighting.js +6 -1
- package/ShadersWGSL/ShadersInclude/openpbrDirectLighting.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/openpbrEnvironmentLighting.js +1 -1
- package/ShadersWGSL/ShadersInclude/openpbrEnvironmentLighting.js.map +1 -1
- package/ShadersWGSL/gaussianSplatting.vertex.js +3 -0
- package/ShadersWGSL/gaussianSplatting.vertex.js.map +1 -1
- package/ShadersWGSL/gpuUpdateParticles.compute.js +29 -8
- package/ShadersWGSL/gpuUpdateParticles.compute.js.map +1 -1
- package/ShadersWGSL/iblShadowVoxelTracing.fragment.js +5 -1
- package/ShadersWGSL/iblShadowVoxelTracing.fragment.js.map +1 -1
- package/ShadersWGSL/iblVoxelGrid.fragment.js +1 -1
- package/ShadersWGSL/iblVoxelGrid.fragment.js.map +1 -1
- package/{Shaders/iblVoxelSlabDebug.vertex.d.ts → ShadersWGSL/lod3D.fragment.d.ts} +1 -1
- package/ShadersWGSL/lod3D.fragment.js +13 -0
- package/ShadersWGSL/lod3D.fragment.js.map +1 -0
- package/ShadersWGSL/openpbr.fragment.js +5 -0
- package/ShadersWGSL/openpbr.fragment.js.map +1 -1
- package/package.json +1 -1
- package/Shaders/iblVoxelGrid3dDebug.fragment.d.ts +0 -5
- package/Shaders/iblVoxelGrid3dDebug.fragment.js +0 -24
- package/Shaders/iblVoxelGrid3dDebug.fragment.js.map +0 -1
- package/Shaders/iblVoxelSlabDebug.fragment.js +0 -13
- package/Shaders/iblVoxelSlabDebug.fragment.js.map +0 -1
- package/Shaders/iblVoxelSlabDebug.vertex.js +0 -11
- package/Shaders/iblVoxelSlabDebug.vertex.js.map +0 -1
- package/ShadersWGSL/iblVoxelGrid3dDebug.fragment.d.ts +0 -5
- package/ShadersWGSL/iblVoxelGrid3dDebug.fragment.js +0 -23
- package/ShadersWGSL/iblVoxelGrid3dDebug.fragment.js.map +0 -1
- package/ShadersWGSL/iblVoxelSlabDebug.fragment.d.ts +0 -5
- package/ShadersWGSL/iblVoxelSlabDebug.fragment.js +0 -14
- package/ShadersWGSL/iblVoxelSlabDebug.fragment.js.map +0 -1
- package/ShadersWGSL/iblVoxelSlabDebug.vertex.d.ts +0 -5
- package/ShadersWGSL/iblVoxelSlabDebug.vertex.js +0 -12
- package/ShadersWGSL/iblVoxelSlabDebug.vertex.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ColorGradient, GradientHelper } from "../Misc/gradients.js";
|
|
2
2
|
import { Observable } from "../Misc/observable.js";
|
|
3
3
|
import { Vector3, Matrix, TmpVectors } from "../Maths/math.vector.js";
|
|
4
4
|
import { Color4, TmpColors } from "../Maths/math.color.js";
|
|
@@ -6,6 +6,8 @@ import { Lerp } from "../Maths/math.scalar.functions.js";
|
|
|
6
6
|
import { VertexBuffer, Buffer } from "../Buffers/buffer.js";
|
|
7
7
|
import { BaseParticleSystem } from "./baseParticleSystem.js";
|
|
8
8
|
import { ParticleSystem } from "./particleSystem.js";
|
|
9
|
+
import { Attractor } from "./attractor.js";
|
|
10
|
+
import { Logger } from "../Misc/logger.js";
|
|
9
11
|
import { BoxParticleEmitter } from "../Particles/EmitterTypes/boxParticleEmitter.js";
|
|
10
12
|
import { Scene } from "../scene.js";
|
|
11
13
|
import { ImageProcessingConfiguration } from "../Materials/imageProcessingConfiguration.js";
|
|
@@ -28,6 +30,15 @@ import { CreateConeEmitter, CreateCylinderEmitter, CreateDirectedCylinderEmitter
|
|
|
28
30
|
* @see https://www.babylonjs-playground.com/#PU4WYI#4
|
|
29
31
|
*/
|
|
30
32
|
export class GPUParticleSystem extends BaseParticleSystem {
|
|
33
|
+
/**
|
|
34
|
+
* Whether the particle buffer needs to store the initial emission direction.
|
|
35
|
+
* True when particles are not billboarded (they orient by direction) or when
|
|
36
|
+
* using stretched-local billboard mode (stretches along initial direction).
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
39
|
+
get _needsInitialDirection() {
|
|
40
|
+
return !this._isBillboardBased || this.billboardMode === ParticleSystem.BILLBOARDMODE_STRETCHED_LOCAL;
|
|
41
|
+
}
|
|
31
42
|
/**
|
|
32
43
|
* Gets a boolean indicating if the GPU particles can be rendered on current browser
|
|
33
44
|
*/
|
|
@@ -79,6 +90,17 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
79
90
|
set activeParticleCount(value) {
|
|
80
91
|
this.maxActiveParticleCount = value;
|
|
81
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Add an attractor to the particle system. Attractors are used to change the direction of the particles in the system.
|
|
95
|
+
* @param attractor - The attractor to add to the particle system
|
|
96
|
+
*/
|
|
97
|
+
addAttractor(attractor) {
|
|
98
|
+
if (this._attractors.length >= this.maxAttractors) {
|
|
99
|
+
Logger.Warn(`GPU particle system supports a maximum of ${this.maxAttractors} attractors. Ignoring additional attractor.`);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
super.addAttractor(attractor);
|
|
103
|
+
}
|
|
82
104
|
/**
|
|
83
105
|
* Creates a Point Emitter for the particle system (emits directly from the emitter position)
|
|
84
106
|
* @param direction1 Particles are emitted between the direction1 and direction2 from within the box
|
|
@@ -273,6 +295,28 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
273
295
|
this._stopped = false;
|
|
274
296
|
this._actualFrame = 0;
|
|
275
297
|
this._preWarmDone = false;
|
|
298
|
+
// Reset emit gradient so it acts the same on every start
|
|
299
|
+
if (this._emitRateGradients) {
|
|
300
|
+
if (this._emitRateGradients.length > 0) {
|
|
301
|
+
this._currentEmitRateGradient = this._emitRateGradients[0];
|
|
302
|
+
this._currentEmitRate1 = this._currentEmitRateGradient.getFactor();
|
|
303
|
+
this._currentEmitRate2 = this._currentEmitRate1;
|
|
304
|
+
}
|
|
305
|
+
if (this._emitRateGradients.length > 1) {
|
|
306
|
+
this._currentEmitRate2 = this._emitRateGradients[1].getFactor();
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
// Reset start size gradient so it acts the same on every start
|
|
310
|
+
if (this._startSizeGradients) {
|
|
311
|
+
if (this._startSizeGradients.length > 0) {
|
|
312
|
+
this._currentStartSizeGradient = this._startSizeGradients[0];
|
|
313
|
+
this._currentStartSize1 = this._currentStartSizeGradient.getFactor();
|
|
314
|
+
this._currentStartSize2 = this._currentStartSize1;
|
|
315
|
+
}
|
|
316
|
+
if (this._startSizeGradients.length > 1) {
|
|
317
|
+
this._currentStartSize2 = this._startSizeGradients[1].getFactor();
|
|
318
|
+
}
|
|
319
|
+
}
|
|
276
320
|
// Animations
|
|
277
321
|
if (this.beginAnimationOnStart && this.animations && this.animations.length > 0 && this._scene) {
|
|
278
322
|
this._scene.beginAnimation(this, this.beginAnimationFrom, this.beginAnimationTo, this.beginAnimationLoop);
|
|
@@ -430,23 +474,19 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
430
474
|
drawWrapper.drawContext?.reset();
|
|
431
475
|
}
|
|
432
476
|
}
|
|
433
|
-
_addFactorGradient(factorGradients, gradient, factor) {
|
|
434
|
-
const valueGradient = new FactorGradient(gradient, factor);
|
|
435
|
-
factorGradients.push(valueGradient);
|
|
436
|
-
this._releaseBuffers();
|
|
437
|
-
}
|
|
438
477
|
/**
|
|
439
478
|
* Adds a new size gradient
|
|
440
479
|
* @param gradient defines the gradient to use (between 0 and 1)
|
|
441
480
|
* @param factor defines the size factor to affect to the specified gradient
|
|
481
|
+
* @param factor2 defines an additional factor used to define a range ([factor, factor2]) with main value to pick the final value from
|
|
442
482
|
* @returns the current particle system
|
|
443
483
|
*/
|
|
444
|
-
addSizeGradient(gradient, factor) {
|
|
484
|
+
addSizeGradient(gradient, factor, factor2) {
|
|
445
485
|
if (!this._sizeGradients) {
|
|
446
486
|
this._sizeGradients = [];
|
|
447
487
|
}
|
|
448
|
-
this._addFactorGradient(this._sizeGradients, gradient, factor);
|
|
449
|
-
this._refreshFactorGradient(this._sizeGradients, "_sizeGradientsTexture"
|
|
488
|
+
this._addFactorGradient(this._sizeGradients, gradient, factor, factor2);
|
|
489
|
+
this._refreshFactorGradient(this._sizeGradients, "_sizeGradientsTexture");
|
|
450
490
|
this._releaseBuffers();
|
|
451
491
|
return this;
|
|
452
492
|
}
|
|
@@ -460,21 +500,10 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
460
500
|
this._sizeGradientsTexture = null;
|
|
461
501
|
return this;
|
|
462
502
|
}
|
|
463
|
-
_refreshFactorGradient(factorGradients, textureName
|
|
503
|
+
_refreshFactorGradient(factorGradients, textureName) {
|
|
464
504
|
if (!factorGradients) {
|
|
465
505
|
return;
|
|
466
506
|
}
|
|
467
|
-
if (reorder) {
|
|
468
|
-
factorGradients.sort((a, b) => {
|
|
469
|
-
if (a.gradient < b.gradient) {
|
|
470
|
-
return -1;
|
|
471
|
-
}
|
|
472
|
-
else if (a.gradient > b.gradient) {
|
|
473
|
-
return 1;
|
|
474
|
-
}
|
|
475
|
-
return 0;
|
|
476
|
-
});
|
|
477
|
-
}
|
|
478
507
|
const that = this;
|
|
479
508
|
if (that[textureName]) {
|
|
480
509
|
that[textureName].dispose();
|
|
@@ -485,14 +514,15 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
485
514
|
* Adds a new angular speed gradient
|
|
486
515
|
* @param gradient defines the gradient to use (between 0 and 1)
|
|
487
516
|
* @param factor defines the angular speed to affect to the specified gradient
|
|
517
|
+
* @param factor2 defines an additional factor used to define a range ([factor, factor2]) with main value to pick the final value from
|
|
488
518
|
* @returns the current particle system
|
|
489
519
|
*/
|
|
490
|
-
addAngularSpeedGradient(gradient, factor) {
|
|
520
|
+
addAngularSpeedGradient(gradient, factor, factor2) {
|
|
491
521
|
if (!this._angularSpeedGradients) {
|
|
492
522
|
this._angularSpeedGradients = [];
|
|
493
523
|
}
|
|
494
|
-
this._addFactorGradient(this._angularSpeedGradients, gradient, factor);
|
|
495
|
-
this._refreshFactorGradient(this._angularSpeedGradients, "_angularSpeedGradientsTexture"
|
|
524
|
+
this._addFactorGradient(this._angularSpeedGradients, gradient, factor, factor2);
|
|
525
|
+
this._refreshFactorGradient(this._angularSpeedGradients, "_angularSpeedGradientsTexture");
|
|
496
526
|
this._releaseBuffers();
|
|
497
527
|
return this;
|
|
498
528
|
}
|
|
@@ -510,14 +540,15 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
510
540
|
* Adds a new velocity gradient
|
|
511
541
|
* @param gradient defines the gradient to use (between 0 and 1)
|
|
512
542
|
* @param factor defines the velocity to affect to the specified gradient
|
|
543
|
+
* @param factor2 defines an additional factor used to define a range ([factor, factor2]) with main value to pick the final value from
|
|
513
544
|
* @returns the current particle system
|
|
514
545
|
*/
|
|
515
|
-
addVelocityGradient(gradient, factor) {
|
|
546
|
+
addVelocityGradient(gradient, factor, factor2) {
|
|
516
547
|
if (!this._velocityGradients) {
|
|
517
548
|
this._velocityGradients = [];
|
|
518
549
|
}
|
|
519
|
-
this._addFactorGradient(this._velocityGradients, gradient, factor);
|
|
520
|
-
this._refreshFactorGradient(this._velocityGradients, "_velocityGradientsTexture"
|
|
550
|
+
this._addFactorGradient(this._velocityGradients, gradient, factor, factor2);
|
|
551
|
+
this._refreshFactorGradient(this._velocityGradients, "_velocityGradientsTexture");
|
|
521
552
|
this._releaseBuffers();
|
|
522
553
|
return this;
|
|
523
554
|
}
|
|
@@ -535,14 +566,15 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
535
566
|
* Adds a new limit velocity gradient
|
|
536
567
|
* @param gradient defines the gradient to use (between 0 and 1)
|
|
537
568
|
* @param factor defines the limit velocity value to affect to the specified gradient
|
|
569
|
+
* @param factor2 defines an additional factor used to define a range ([factor, factor2]) with main value to pick the final value from
|
|
538
570
|
* @returns the current particle system
|
|
539
571
|
*/
|
|
540
|
-
addLimitVelocityGradient(gradient, factor) {
|
|
572
|
+
addLimitVelocityGradient(gradient, factor, factor2) {
|
|
541
573
|
if (!this._limitVelocityGradients) {
|
|
542
574
|
this._limitVelocityGradients = [];
|
|
543
575
|
}
|
|
544
|
-
this._addFactorGradient(this._limitVelocityGradients, gradient, factor);
|
|
545
|
-
this._refreshFactorGradient(this._limitVelocityGradients, "_limitVelocityGradientsTexture"
|
|
576
|
+
this._addFactorGradient(this._limitVelocityGradients, gradient, factor, factor2);
|
|
577
|
+
this._refreshFactorGradient(this._limitVelocityGradients, "_limitVelocityGradientsTexture");
|
|
546
578
|
this._releaseBuffers();
|
|
547
579
|
return this;
|
|
548
580
|
}
|
|
@@ -560,14 +592,15 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
560
592
|
* Adds a new drag gradient
|
|
561
593
|
* @param gradient defines the gradient to use (between 0 and 1)
|
|
562
594
|
* @param factor defines the drag value to affect to the specified gradient
|
|
595
|
+
* @param factor2 defines an additional factor used to define a range ([factor, factor2]) with main value to pick the final value from
|
|
563
596
|
* @returns the current particle system
|
|
564
597
|
*/
|
|
565
|
-
addDragGradient(gradient, factor) {
|
|
598
|
+
addDragGradient(gradient, factor, factor2) {
|
|
566
599
|
if (!this._dragGradients) {
|
|
567
600
|
this._dragGradients = [];
|
|
568
601
|
}
|
|
569
|
-
this._addFactorGradient(this._dragGradients, gradient, factor);
|
|
570
|
-
this._refreshFactorGradient(this._dragGradients, "_dragGradientsTexture"
|
|
602
|
+
this._addFactorGradient(this._dragGradients, gradient, factor, factor2);
|
|
603
|
+
this._refreshFactorGradient(this._dragGradients, "_dragGradientsTexture");
|
|
571
604
|
this._releaseBuffers();
|
|
572
605
|
return this;
|
|
573
606
|
}
|
|
@@ -582,35 +615,34 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
582
615
|
return this;
|
|
583
616
|
}
|
|
584
617
|
/**
|
|
585
|
-
*
|
|
586
|
-
* @
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
// Do nothing as emit rate is not supported by GPUParticleSystem
|
|
590
|
-
return this;
|
|
591
|
-
}
|
|
592
|
-
/**
|
|
593
|
-
* Not supported by GPUParticleSystem
|
|
594
|
-
* @returns the current particle system
|
|
595
|
-
*/
|
|
596
|
-
removeEmitRateGradient() {
|
|
597
|
-
// Do nothing as emit rate is not supported by GPUParticleSystem
|
|
598
|
-
return this;
|
|
599
|
-
}
|
|
600
|
-
/**
|
|
601
|
-
* Not supported by GPUParticleSystem
|
|
618
|
+
* Adds a new start size gradient (please note that this will only work if you set the targetStopDuration property)
|
|
619
|
+
* @param gradient defines the gradient to use (between 0 and 1)
|
|
620
|
+
* @param factor defines the start size factor to affect to the specified gradient
|
|
621
|
+
* @param factor2 defines an additional factor used to define a range ([factor, factor2]) with main value to pick the final value from
|
|
602
622
|
* @returns the current particle system
|
|
603
623
|
*/
|
|
604
|
-
addStartSizeGradient() {
|
|
605
|
-
|
|
624
|
+
addStartSizeGradient(gradient, factor, factor2) {
|
|
625
|
+
if (!this._startSizeGradients) {
|
|
626
|
+
this._startSizeGradients = [];
|
|
627
|
+
}
|
|
628
|
+
const hadGradients = this._startSizeGradients.length > 0;
|
|
629
|
+
this._addFactorGradient(this._startSizeGradients, gradient, factor, factor2);
|
|
630
|
+
if (!hadGradients) {
|
|
631
|
+
this._resetEffect();
|
|
632
|
+
}
|
|
606
633
|
return this;
|
|
607
634
|
}
|
|
608
635
|
/**
|
|
609
|
-
*
|
|
636
|
+
* Remove a specific start size gradient
|
|
637
|
+
* @param gradient defines the gradient to remove
|
|
610
638
|
* @returns the current particle system
|
|
611
639
|
*/
|
|
612
|
-
removeStartSizeGradient() {
|
|
613
|
-
|
|
640
|
+
removeStartSizeGradient(gradient) {
|
|
641
|
+
const hadGradients = this._startSizeGradients && this._startSizeGradients.length > 0;
|
|
642
|
+
this._removeFactorGradient(this._startSizeGradients, gradient);
|
|
643
|
+
if (hadGradients && (!this._startSizeGradients || this._startSizeGradients.length === 0)) {
|
|
644
|
+
this._resetEffect();
|
|
645
|
+
}
|
|
614
646
|
return this;
|
|
615
647
|
}
|
|
616
648
|
/**
|
|
@@ -681,19 +713,34 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
681
713
|
//Not supported by GPUParticleSystem
|
|
682
714
|
}
|
|
683
715
|
/**
|
|
684
|
-
*
|
|
716
|
+
* Adds a new life time gradient (please note that this will only work if you set the targetStopDuration property)
|
|
717
|
+
* @param gradient defines the gradient to use (between 0 and 1)
|
|
718
|
+
* @param factor defines the life time factor to affect to the specified gradient
|
|
719
|
+
* @param factor2 defines an additional factor used to define a range ([factor, factor2]) with main value to pick the final value from
|
|
685
720
|
* @returns the current particle system
|
|
686
721
|
*/
|
|
687
|
-
addLifeTimeGradient() {
|
|
688
|
-
|
|
722
|
+
addLifeTimeGradient(gradient, factor, factor2) {
|
|
723
|
+
if (!this._lifeTimeGradients) {
|
|
724
|
+
this._lifeTimeGradients = [];
|
|
725
|
+
}
|
|
726
|
+
const hadGradients = this._lifeTimeGradients.length > 0;
|
|
727
|
+
this._addFactorGradient(this._lifeTimeGradients, gradient, factor, factor2);
|
|
728
|
+
if (!hadGradients) {
|
|
729
|
+
this._resetEffect();
|
|
730
|
+
}
|
|
689
731
|
return this;
|
|
690
732
|
}
|
|
691
733
|
/**
|
|
692
|
-
*
|
|
734
|
+
* Remove a specific life time gradient
|
|
735
|
+
* @param gradient defines the gradient to remove
|
|
693
736
|
* @returns the current particle system
|
|
694
737
|
*/
|
|
695
|
-
removeLifeTimeGradient() {
|
|
696
|
-
|
|
738
|
+
removeLifeTimeGradient(gradient) {
|
|
739
|
+
const hadGradients = this._lifeTimeGradients && this._lifeTimeGradients.length > 0;
|
|
740
|
+
this._removeFactorGradient(this._lifeTimeGradients, gradient);
|
|
741
|
+
if (hadGradients && (!this._lifeTimeGradients || this._lifeTimeGradients.length === 0)) {
|
|
742
|
+
this._resetEffect();
|
|
743
|
+
}
|
|
697
744
|
return this;
|
|
698
745
|
}
|
|
699
746
|
/**
|
|
@@ -727,6 +774,18 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
727
774
|
this._actualFrame = 0;
|
|
728
775
|
this._rawTextureWidth = 256;
|
|
729
776
|
this._rebuildingAfterContextLost = false;
|
|
777
|
+
// Emit rate gradient caching (mirrors ThinParticleSystem)
|
|
778
|
+
this._currentEmitRateGradient = null;
|
|
779
|
+
this._currentEmitRate1 = 0;
|
|
780
|
+
this._currentEmitRate2 = 0;
|
|
781
|
+
// Start size gradient caching (mirrors ThinParticleSystem)
|
|
782
|
+
this._currentStartSizeGradient = null;
|
|
783
|
+
this._currentStartSize1 = 0;
|
|
784
|
+
this._currentStartSize2 = 0;
|
|
785
|
+
this._startSizeGradientFactor = 1.0;
|
|
786
|
+
// Life time gradient factor range for per-particle randomization in shader
|
|
787
|
+
this._lifeTimeGradientMin = 1.0;
|
|
788
|
+
this._lifeTimeGradientMax = 1.0;
|
|
730
789
|
/**
|
|
731
790
|
* Specifies if the particle system should be serialized
|
|
732
791
|
*/
|
|
@@ -817,6 +876,7 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
817
876
|
this._currentActiveCount = 0;
|
|
818
877
|
this._isAnimationSheetEnabled = isAnimationSheetEnabled;
|
|
819
878
|
this._emitRateControl = !!options.emitRateControl;
|
|
879
|
+
this.maxAttractors = options.maxAttractors ?? 8;
|
|
820
880
|
this.particleEmitterType = new BoxParticleEmitter();
|
|
821
881
|
// Random data
|
|
822
882
|
const maxTextureSize = Math.min(this._engine.getCaps().maxTextureSize, fullOptions.randomTextureSize);
|
|
@@ -858,7 +918,7 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
858
918
|
renderVertexBuffers["life"] = renderBuffer.createVertexBuffer("life", offset, 1, this._attributesStrideSize, true);
|
|
859
919
|
offset += 1;
|
|
860
920
|
offset += 4; // seed
|
|
861
|
-
if (this.billboardMode === ParticleSystem.BILLBOARDMODE_STRETCHED) {
|
|
921
|
+
if (this.billboardMode === ParticleSystem.BILLBOARDMODE_STRETCHED || this.billboardMode === ParticleSystem.BILLBOARDMODE_STRETCHED_LOCAL) {
|
|
862
922
|
renderVertexBuffers["direction"] = renderBuffer.createVertexBuffer("direction", offset, 3, this._attributesStrideSize, true);
|
|
863
923
|
}
|
|
864
924
|
offset += 3; // direction
|
|
@@ -875,7 +935,7 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
875
935
|
renderVertexBuffers["color"] = renderBuffer.createVertexBuffer("color", offset, 4, this._attributesStrideSize, true);
|
|
876
936
|
offset += 4;
|
|
877
937
|
}
|
|
878
|
-
if (
|
|
938
|
+
if (this._needsInitialDirection) {
|
|
879
939
|
renderVertexBuffers["initialDirection"] = renderBuffer.createVertexBuffer("initialDirection", offset, 3, this._attributesStrideSize, true);
|
|
880
940
|
offset += 3;
|
|
881
941
|
if (this._platform.alignDataInBuffer) {
|
|
@@ -931,7 +991,7 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
931
991
|
this._attributesStrideSize += 1;
|
|
932
992
|
}
|
|
933
993
|
}
|
|
934
|
-
if (
|
|
994
|
+
if (this._needsInitialDirection) {
|
|
935
995
|
this._attributesStrideSize += 3;
|
|
936
996
|
if (this._platform.alignDataInBuffer) {
|
|
937
997
|
this._attributesStrideSize += 1;
|
|
@@ -1013,7 +1073,7 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1013
1073
|
data.push(0.0);
|
|
1014
1074
|
offset += 4;
|
|
1015
1075
|
}
|
|
1016
|
-
if (
|
|
1076
|
+
if (this._needsInitialDirection) {
|
|
1017
1077
|
// initialDirection
|
|
1018
1078
|
data.push(0.0);
|
|
1019
1079
|
data.push(0.0);
|
|
@@ -1078,6 +1138,12 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1078
1138
|
this._sourceBuffer = this._buffer0;
|
|
1079
1139
|
this._targetBuffer = this._buffer1;
|
|
1080
1140
|
}
|
|
1141
|
+
/**
|
|
1142
|
+
* Forces the update effect to be recreated on the next render.
|
|
1143
|
+
*/
|
|
1144
|
+
_resetEffect() {
|
|
1145
|
+
this._cachedUpdateDefines = "";
|
|
1146
|
+
}
|
|
1081
1147
|
/** @internal */
|
|
1082
1148
|
_recreateUpdateEffect() {
|
|
1083
1149
|
this._createColorGradientTexture();
|
|
@@ -1088,7 +1154,11 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1088
1154
|
this._createDragGradientTexture();
|
|
1089
1155
|
let defines = this.particleEmitterType ? this.particleEmitterType.getEffectDefines() : "";
|
|
1090
1156
|
if (this._isBillboardBased) {
|
|
1091
|
-
|
|
1157
|
+
// Stretched local needs initialDirection in the buffer, which requires !BILLBOARD in the update shader.
|
|
1158
|
+
// The render shader still uses BILLBOARD — that's handled separately in fillDefines().
|
|
1159
|
+
if (this.billboardMode !== ParticleSystem.BILLBOARDMODE_STRETCHED_LOCAL) {
|
|
1160
|
+
defines += "\n#define BILLBOARD";
|
|
1161
|
+
}
|
|
1092
1162
|
}
|
|
1093
1163
|
if (this._colorGradientsTexture) {
|
|
1094
1164
|
defines += "\n#define COLORGRADIENTS";
|
|
@@ -1123,9 +1193,19 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1123
1193
|
if (this.isLocal) {
|
|
1124
1194
|
defines += "\n#define LOCAL";
|
|
1125
1195
|
}
|
|
1196
|
+
if (this._attractors.length > 0) {
|
|
1197
|
+
defines += "\n#define ATTRACTORS";
|
|
1198
|
+
defines += "\n#define MAX_ATTRACTORS " + this.maxAttractors;
|
|
1199
|
+
}
|
|
1126
1200
|
if (this._emitRateControl) {
|
|
1127
1201
|
defines += "\n#define EMITRATECTRL";
|
|
1128
1202
|
}
|
|
1203
|
+
if (this._startSizeGradients && this._startSizeGradients.length > 0) {
|
|
1204
|
+
defines += "\n#define STARTSIZEGRADIENTS";
|
|
1205
|
+
}
|
|
1206
|
+
if (this._lifeTimeGradients && this._lifeTimeGradients.length > 0) {
|
|
1207
|
+
defines += "\n#define LIFETIMEGRADIENTS";
|
|
1208
|
+
}
|
|
1129
1209
|
if (this._platform.isUpdateBufferCreated() && this._cachedUpdateDefines === defines) {
|
|
1130
1210
|
return this._platform.isUpdateBufferReady();
|
|
1131
1211
|
}
|
|
@@ -1165,7 +1245,7 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1165
1245
|
/**
|
|
1166
1246
|
* @internal
|
|
1167
1247
|
*/
|
|
1168
|
-
static _GetAttributeNamesOrOptions(hasColorGradients = false, isAnimationSheetEnabled = false, isBillboardBased = false, isBillboardStretched = false) {
|
|
1248
|
+
static _GetAttributeNamesOrOptions(hasColorGradients = false, isAnimationSheetEnabled = false, isBillboardBased = false, isBillboardStretched = false, isBillboardStretchedLocal = false) {
|
|
1169
1249
|
const attributeNamesOrOptions = [VertexBuffer.PositionKind, "age", "life", "size", "angle"];
|
|
1170
1250
|
if (!hasColorGradients) {
|
|
1171
1251
|
attributeNamesOrOptions.push(VertexBuffer.ColorKind);
|
|
@@ -1173,7 +1253,7 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1173
1253
|
if (isAnimationSheetEnabled) {
|
|
1174
1254
|
attributeNamesOrOptions.push("cellIndex");
|
|
1175
1255
|
}
|
|
1176
|
-
if (!isBillboardBased) {
|
|
1256
|
+
if (!isBillboardBased || isBillboardStretchedLocal) {
|
|
1177
1257
|
attributeNamesOrOptions.push("initialDirection");
|
|
1178
1258
|
}
|
|
1179
1259
|
if (isBillboardStretched) {
|
|
@@ -1231,6 +1311,10 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1231
1311
|
case ParticleSystem.BILLBOARDMODE_STRETCHED:
|
|
1232
1312
|
defines.push("#define BILLBOARDSTRETCHED");
|
|
1233
1313
|
break;
|
|
1314
|
+
case ParticleSystem.BILLBOARDMODE_STRETCHED_LOCAL:
|
|
1315
|
+
defines.push("#define BILLBOARDSTRETCHED");
|
|
1316
|
+
defines.push("#define BILLBOARDSTRETCHED_LOCAL");
|
|
1317
|
+
break;
|
|
1234
1318
|
case ParticleSystem.BILLBOARDMODE_ALL:
|
|
1235
1319
|
defines.push("#define BILLBOARDMODE_ALL");
|
|
1236
1320
|
break;
|
|
@@ -1259,7 +1343,7 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1259
1343
|
* @param samplers Samplers array to fill
|
|
1260
1344
|
*/
|
|
1261
1345
|
fillUniformsAttributesAndSamplerNames(uniforms, attributes, samplers) {
|
|
1262
|
-
attributes.push(...GPUParticleSystem._GetAttributeNamesOrOptions(!!this._colorGradientsTexture, this._isAnimationSheetEnabled, this._isBillboardBased, this._isBillboardBased && this.billboardMode === ParticleSystem.BILLBOARDMODE_STRETCHED));
|
|
1346
|
+
attributes.push(...GPUParticleSystem._GetAttributeNamesOrOptions(!!this._colorGradientsTexture, this._isAnimationSheetEnabled, this._isBillboardBased, this._isBillboardBased && (this.billboardMode === ParticleSystem.BILLBOARDMODE_STRETCHED || this.billboardMode === ParticleSystem.BILLBOARDMODE_STRETCHED_LOCAL), this.billboardMode === ParticleSystem.BILLBOARDMODE_STRETCHED_LOCAL));
|
|
1263
1347
|
uniforms.push(...GPUParticleSystem._GetEffectCreationOptions(this._isAnimationSheetEnabled, this.useLogarithmicDepth, this.applyFog));
|
|
1264
1348
|
samplers.push("diffuseSampler", "colorGradientSampler");
|
|
1265
1349
|
if (this._imageProcessingConfiguration) {
|
|
@@ -1288,14 +1372,17 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1288
1372
|
if (!factorGradients || !factorGradients.length || texture) {
|
|
1289
1373
|
return;
|
|
1290
1374
|
}
|
|
1291
|
-
const data = new Float32Array(this._rawTextureWidth);
|
|
1375
|
+
const data = new Float32Array(this._rawTextureWidth * 2);
|
|
1292
1376
|
for (let x = 0; x < this._rawTextureWidth; x++) {
|
|
1293
1377
|
const ratio = x / this._rawTextureWidth;
|
|
1294
1378
|
GradientHelper.GetCurrentGradient(ratio, factorGradients, (currentGradient, nextGradient, scale) => {
|
|
1295
|
-
|
|
1379
|
+
const cg = currentGradient;
|
|
1380
|
+
const ng = nextGradient;
|
|
1381
|
+
data[x * 2] = Lerp(cg.factor1, ng.factor1, scale);
|
|
1382
|
+
data[x * 2 + 1] = Lerp(cg.factor2 ?? cg.factor1, ng.factor2 ?? ng.factor1, scale);
|
|
1296
1383
|
});
|
|
1297
1384
|
}
|
|
1298
|
-
this[textureName] = RawTexture
|
|
1385
|
+
this[textureName] = new RawTexture(data, this._rawTextureWidth, 1, 7, this._scene || this._engine, false, false, 1, 1);
|
|
1299
1386
|
this[textureName].name = textureName.substring(1);
|
|
1300
1387
|
}
|
|
1301
1388
|
_createSizeGradientTexture() {
|
|
@@ -1460,6 +1547,33 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1460
1547
|
if (!this.isLocal) {
|
|
1461
1548
|
this._updateBuffer.setMatrix("emitterWM", emitterWM);
|
|
1462
1549
|
}
|
|
1550
|
+
if (this._attractors.length > 0) {
|
|
1551
|
+
this._updateBuffer.setInt("attractorCount", this._attractors.length);
|
|
1552
|
+
// Compute inverse world matrix once for all attractors when in local space
|
|
1553
|
+
let invWorld;
|
|
1554
|
+
if (this.isLocal) {
|
|
1555
|
+
invWorld = TmpVectors.Matrix[1];
|
|
1556
|
+
emitterWM.invertToRef(invWorld);
|
|
1557
|
+
}
|
|
1558
|
+
for (let i = 0; i < this._attractors.length; i++) {
|
|
1559
|
+
const attractor = this._attractors[i];
|
|
1560
|
+
const name = "attractorPositionAndStrength[" + i + "]";
|
|
1561
|
+
if (invWorld) {
|
|
1562
|
+
const localPos = TmpVectors.Vector3[0];
|
|
1563
|
+
Vector3.TransformCoordinatesToRef(attractor.position, invWorld, localPos);
|
|
1564
|
+
this._updateBuffer.setFloat4(name, localPos.x, localPos.y, localPos.z, attractor.strength);
|
|
1565
|
+
}
|
|
1566
|
+
else {
|
|
1567
|
+
this._updateBuffer.setFloat4(name, attractor.position.x, attractor.position.y, attractor.position.z, attractor.strength);
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
if (this._startSizeGradients && this._startSizeGradients.length > 0) {
|
|
1572
|
+
this._updateBuffer.setFloat("startSizeGradientFactor", this._startSizeGradientFactor);
|
|
1573
|
+
}
|
|
1574
|
+
if (this._lifeTimeGradients && this._lifeTimeGradients.length > 0) {
|
|
1575
|
+
this._updateBuffer.setFloat2("lifeTimeGradientRange", this._lifeTimeGradientMin, this._lifeTimeGradientMax);
|
|
1576
|
+
}
|
|
1463
1577
|
this._platform.updateParticleBuffer(this._targetIndex, this._targetBuffer, this._currentActiveCount);
|
|
1464
1578
|
// Switch VAOs
|
|
1465
1579
|
this._targetIndex++;
|
|
@@ -1504,6 +1618,48 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1504
1618
|
}
|
|
1505
1619
|
// Get everything ready to render
|
|
1506
1620
|
this._initialize();
|
|
1621
|
+
// Compute effective emit rate, applying emit rate gradients if set
|
|
1622
|
+
let effectiveEmitRate = this.emitRate;
|
|
1623
|
+
if (this._emitRateGradients && this._emitRateGradients.length > 0 && this.targetStopDuration) {
|
|
1624
|
+
const ratio = this._actualFrame / this.targetStopDuration;
|
|
1625
|
+
GradientHelper.GetCurrentGradient(ratio, this._emitRateGradients, (currentGradient, nextGradient, scale) => {
|
|
1626
|
+
if (currentGradient !== this._currentEmitRateGradient) {
|
|
1627
|
+
this._currentEmitRate1 = this._currentEmitRate2;
|
|
1628
|
+
this._currentEmitRate2 = nextGradient.getFactor();
|
|
1629
|
+
this._currentEmitRateGradient = currentGradient;
|
|
1630
|
+
}
|
|
1631
|
+
effectiveEmitRate = Lerp(this._currentEmitRate1, this._currentEmitRate2, scale);
|
|
1632
|
+
});
|
|
1633
|
+
}
|
|
1634
|
+
// Compute start size and life time gradient factors for shader uniforms
|
|
1635
|
+
if (this.targetStopDuration) {
|
|
1636
|
+
const ratio = this._actualFrame / this.targetStopDuration;
|
|
1637
|
+
if (this._startSizeGradients && this._startSizeGradients.length > 0) {
|
|
1638
|
+
GradientHelper.GetCurrentGradient(ratio, this._startSizeGradients, (currentGradient, nextGradient, scale) => {
|
|
1639
|
+
if (currentGradient !== this._currentStartSizeGradient) {
|
|
1640
|
+
this._currentStartSize1 = this._currentStartSize2;
|
|
1641
|
+
this._currentStartSize2 = nextGradient.getFactor();
|
|
1642
|
+
this._currentStartSizeGradient = currentGradient;
|
|
1643
|
+
}
|
|
1644
|
+
this._startSizeGradientFactor = Lerp(this._currentStartSize1, this._currentStartSize2, scale);
|
|
1645
|
+
});
|
|
1646
|
+
}
|
|
1647
|
+
else {
|
|
1648
|
+
this._startSizeGradientFactor = 1.0;
|
|
1649
|
+
}
|
|
1650
|
+
if (this._lifeTimeGradients && this._lifeTimeGradients.length > 0) {
|
|
1651
|
+
GradientHelper.GetCurrentGradient(ratio, this._lifeTimeGradients, (currentGradient, nextGradient, scale) => {
|
|
1652
|
+
const current = currentGradient;
|
|
1653
|
+
const next = nextGradient;
|
|
1654
|
+
this._lifeTimeGradientMin = Lerp(current.factor1, next.factor1, scale);
|
|
1655
|
+
this._lifeTimeGradientMax = Lerp(current.factor2 ?? current.factor1, next.factor2 ?? next.factor1, scale);
|
|
1656
|
+
});
|
|
1657
|
+
}
|
|
1658
|
+
else {
|
|
1659
|
+
this._lifeTimeGradientMin = 1.0;
|
|
1660
|
+
this._lifeTimeGradientMax = 1.0;
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1507
1663
|
if (this._emitRateControl) {
|
|
1508
1664
|
// Emit-rate-controlled mode: limits active particles to ~emitRate * maxLifeTime,
|
|
1509
1665
|
// matching CPU particle behavior with circular buffer recycling.
|
|
@@ -1513,7 +1669,7 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1513
1669
|
this.manualEmitCount = 0;
|
|
1514
1670
|
}
|
|
1515
1671
|
else if (!this._stopped) {
|
|
1516
|
-
this._accumulatedCount +=
|
|
1672
|
+
this._accumulatedCount += effectiveEmitRate * this._timeDelta;
|
|
1517
1673
|
}
|
|
1518
1674
|
// Convert accumulated fractional count into whole particles to emit this frame.
|
|
1519
1675
|
// The fractional remainder carries over to the next frame.
|
|
@@ -1528,7 +1684,7 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1528
1684
|
// When emitRate is 0 but manualEmitCount is used, the rate-based steady state
|
|
1529
1685
|
// would be 0, blocking buffer growth. Use newParticles as a floor so manual
|
|
1530
1686
|
// emissions can always allocate slots.
|
|
1531
|
-
const steadyStateCount = Math.min(Math.max(Math.ceil(
|
|
1687
|
+
const steadyStateCount = Math.min(Math.max(Math.ceil(effectiveEmitRate * this.maxLifeTime), newParticles), this._maxActiveParticleCount);
|
|
1532
1688
|
// During ramp-up, grow the active buffer size by adding new slots.
|
|
1533
1689
|
// Once _currentActiveCount reaches steadyStateCount, no new slots are added —
|
|
1534
1690
|
// existing slots are recycled instead (handled by _emitIndex below).
|
|
@@ -1557,7 +1713,7 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1557
1713
|
this.manualEmitCount = 0;
|
|
1558
1714
|
}
|
|
1559
1715
|
else {
|
|
1560
|
-
this._accumulatedCount +=
|
|
1716
|
+
this._accumulatedCount += effectiveEmitRate * this._timeDelta;
|
|
1561
1717
|
}
|
|
1562
1718
|
if (this._accumulatedCount >= 1) {
|
|
1563
1719
|
const intPart = this._accumulatedCount | 0;
|
|
@@ -1749,12 +1905,20 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1749
1905
|
serializationObject.activeParticleCount = this.activeParticleCount;
|
|
1750
1906
|
serializationObject.randomTextureSize = this._randomTextureSize;
|
|
1751
1907
|
serializationObject.emitRateControl = this._emitRateControl;
|
|
1908
|
+
serializationObject.maxAttractors = this.maxAttractors;
|
|
1752
1909
|
serializationObject.customShader = this.customShader;
|
|
1753
1910
|
serializationObject.preventAutoStart = this.preventAutoStart;
|
|
1754
1911
|
serializationObject.worldOffset = this.worldOffset.asArray();
|
|
1755
1912
|
if (this.metadata) {
|
|
1756
1913
|
serializationObject.metadata = this.metadata;
|
|
1757
1914
|
}
|
|
1915
|
+
// Attractors
|
|
1916
|
+
if (this._attractors.length > 0) {
|
|
1917
|
+
serializationObject.attractors = [];
|
|
1918
|
+
for (const attractor of this._attractors) {
|
|
1919
|
+
serializationObject.attractors.push(attractor.serialize());
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1758
1922
|
return serializationObject;
|
|
1759
1923
|
}
|
|
1760
1924
|
/**
|
|
@@ -1781,6 +1945,7 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1781
1945
|
capacity: capacity || parsedParticleSystem.capacity,
|
|
1782
1946
|
randomTextureSize: parsedParticleSystem.randomTextureSize,
|
|
1783
1947
|
emitRateControl: parsedParticleSystem.emitRateControl,
|
|
1948
|
+
maxAttractors: parsedParticleSystem.maxAttractors,
|
|
1784
1949
|
}, sceneOrEngine, null, parsedParticleSystem.isAnimationSheetEnabled);
|
|
1785
1950
|
particleSystem._rootUrl = rootUrl;
|
|
1786
1951
|
if (parsedParticleSystem.customShader && engine.createEffectForParticles) {
|
|
@@ -1807,6 +1972,15 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1807
1972
|
if (parsedParticleSystem.metadata) {
|
|
1808
1973
|
particleSystem.metadata = parsedParticleSystem.metadata;
|
|
1809
1974
|
}
|
|
1975
|
+
// Attractors
|
|
1976
|
+
if (parsedParticleSystem.attractors) {
|
|
1977
|
+
for (const attractorData of parsedParticleSystem.attractors) {
|
|
1978
|
+
const attractor = new Attractor();
|
|
1979
|
+
attractor.position = Vector3.FromArray(attractorData.position);
|
|
1980
|
+
attractor.strength = attractorData.strength;
|
|
1981
|
+
particleSystem.addAttractor(attractor);
|
|
1982
|
+
}
|
|
1983
|
+
}
|
|
1810
1984
|
if (!doNotStart && !particleSystem.preventAutoStart) {
|
|
1811
1985
|
particleSystem.start();
|
|
1812
1986
|
}
|