@babylonjs/core 9.2.1 → 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/geospatialCameraMovement.js +19 -19
- 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/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/Layers/thinEffectLayer.js +8 -1
- package/Layers/thinEffectLayer.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/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 +276 -26
- package/Meshes/GaussianSplatting/gaussianSplattingMesh.js.map +1 -1
- package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.d.ts +39 -4
- package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.js +113 -22
- 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/tools.js +1 -1
- package/Misc/tools.js.map +1 -1
- package/Particles/baseParticleSystem.d.ts +14 -0
- package/Particles/baseParticleSystem.js +23 -0
- package/Particles/baseParticleSystem.js.map +1 -1
- package/Particles/computeShaderParticleSystem.js +6 -0
- package/Particles/computeShaderParticleSystem.js.map +1 -1
- package/Particles/gpuParticleSystem.d.ts +37 -19
- package/Particles/gpuParticleSystem.js +164 -39
- package/Particles/gpuParticleSystem.js.map +1 -1
- package/Particles/thinParticleSystem.d.ts +0 -14
- package/Particles/thinParticleSystem.js +0 -23
- package/Particles/thinParticleSystem.js.map +1 -1
- package/Particles/webgl2ParticleSystem.d.ts +1 -0
- package/Particles/webgl2ParticleSystem.js +11 -2
- package/Particles/webgl2ParticleSystem.js.map +1 -1
- package/Rendering/IBLShadows/iblShadowsVoxelRenderer.js.map +1 -1
- package/Shaders/ShadersInclude/gaussianSplatting.js +25 -4
- package/Shaders/ShadersInclude/gaussianSplatting.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 +12 -0
- package/Shaders/gpuUpdateParticles.vertex.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/gaussianSplatting.js +37 -5
- package/ShadersWGSL/ShadersInclude/gaussianSplatting.js.map +1 -1
- package/ShadersWGSL/gaussianSplatting.vertex.js +3 -0
- package/ShadersWGSL/gaussianSplatting.vertex.js.map +1 -1
- package/ShadersWGSL/gpuUpdateParticles.compute.js +15 -1
- package/ShadersWGSL/gpuUpdateParticles.compute.js.map +1 -1
- package/package.json +1 -1
|
@@ -30,6 +30,15 @@ import { CreateConeEmitter, CreateCylinderEmitter, CreateDirectedCylinderEmitter
|
|
|
30
30
|
* @see https://www.babylonjs-playground.com/#PU4WYI#4
|
|
31
31
|
*/
|
|
32
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
|
+
}
|
|
33
42
|
/**
|
|
34
43
|
* Gets a boolean indicating if the GPU particles can be rendered on current browser
|
|
35
44
|
*/
|
|
@@ -286,6 +295,28 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
286
295
|
this._stopped = false;
|
|
287
296
|
this._actualFrame = 0;
|
|
288
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
|
+
}
|
|
289
320
|
// Animations
|
|
290
321
|
if (this.beginAnimationOnStart && this.animations && this.animations.length > 0 && this._scene) {
|
|
291
322
|
this._scene.beginAnimation(this, this.beginAnimationFrom, this.beginAnimationTo, this.beginAnimationLoop);
|
|
@@ -584,35 +615,34 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
584
615
|
return this;
|
|
585
616
|
}
|
|
586
617
|
/**
|
|
587
|
-
*
|
|
588
|
-
* @
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
// Do nothing as emit rate is not supported by GPUParticleSystem
|
|
592
|
-
return this;
|
|
593
|
-
}
|
|
594
|
-
/**
|
|
595
|
-
* Not supported by GPUParticleSystem
|
|
596
|
-
* @returns the current particle system
|
|
597
|
-
*/
|
|
598
|
-
removeEmitRateGradient() {
|
|
599
|
-
// Do nothing as emit rate is not supported by GPUParticleSystem
|
|
600
|
-
return this;
|
|
601
|
-
}
|
|
602
|
-
/**
|
|
603
|
-
* 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
|
|
604
622
|
* @returns the current particle system
|
|
605
623
|
*/
|
|
606
|
-
addStartSizeGradient() {
|
|
607
|
-
|
|
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
|
+
}
|
|
608
633
|
return this;
|
|
609
634
|
}
|
|
610
635
|
/**
|
|
611
|
-
*
|
|
636
|
+
* Remove a specific start size gradient
|
|
637
|
+
* @param gradient defines the gradient to remove
|
|
612
638
|
* @returns the current particle system
|
|
613
639
|
*/
|
|
614
|
-
removeStartSizeGradient() {
|
|
615
|
-
|
|
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
|
+
}
|
|
616
646
|
return this;
|
|
617
647
|
}
|
|
618
648
|
/**
|
|
@@ -683,19 +713,34 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
683
713
|
//Not supported by GPUParticleSystem
|
|
684
714
|
}
|
|
685
715
|
/**
|
|
686
|
-
*
|
|
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
|
|
687
720
|
* @returns the current particle system
|
|
688
721
|
*/
|
|
689
|
-
addLifeTimeGradient() {
|
|
690
|
-
|
|
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
|
+
}
|
|
691
731
|
return this;
|
|
692
732
|
}
|
|
693
733
|
/**
|
|
694
|
-
*
|
|
734
|
+
* Remove a specific life time gradient
|
|
735
|
+
* @param gradient defines the gradient to remove
|
|
695
736
|
* @returns the current particle system
|
|
696
737
|
*/
|
|
697
|
-
removeLifeTimeGradient() {
|
|
698
|
-
|
|
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
|
+
}
|
|
699
744
|
return this;
|
|
700
745
|
}
|
|
701
746
|
/**
|
|
@@ -729,6 +774,18 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
729
774
|
this._actualFrame = 0;
|
|
730
775
|
this._rawTextureWidth = 256;
|
|
731
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;
|
|
732
789
|
/**
|
|
733
790
|
* Specifies if the particle system should be serialized
|
|
734
791
|
*/
|
|
@@ -861,7 +918,7 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
861
918
|
renderVertexBuffers["life"] = renderBuffer.createVertexBuffer("life", offset, 1, this._attributesStrideSize, true);
|
|
862
919
|
offset += 1;
|
|
863
920
|
offset += 4; // seed
|
|
864
|
-
if (this.billboardMode === ParticleSystem.BILLBOARDMODE_STRETCHED) {
|
|
921
|
+
if (this.billboardMode === ParticleSystem.BILLBOARDMODE_STRETCHED || this.billboardMode === ParticleSystem.BILLBOARDMODE_STRETCHED_LOCAL) {
|
|
865
922
|
renderVertexBuffers["direction"] = renderBuffer.createVertexBuffer("direction", offset, 3, this._attributesStrideSize, true);
|
|
866
923
|
}
|
|
867
924
|
offset += 3; // direction
|
|
@@ -878,7 +935,7 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
878
935
|
renderVertexBuffers["color"] = renderBuffer.createVertexBuffer("color", offset, 4, this._attributesStrideSize, true);
|
|
879
936
|
offset += 4;
|
|
880
937
|
}
|
|
881
|
-
if (
|
|
938
|
+
if (this._needsInitialDirection) {
|
|
882
939
|
renderVertexBuffers["initialDirection"] = renderBuffer.createVertexBuffer("initialDirection", offset, 3, this._attributesStrideSize, true);
|
|
883
940
|
offset += 3;
|
|
884
941
|
if (this._platform.alignDataInBuffer) {
|
|
@@ -934,7 +991,7 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
934
991
|
this._attributesStrideSize += 1;
|
|
935
992
|
}
|
|
936
993
|
}
|
|
937
|
-
if (
|
|
994
|
+
if (this._needsInitialDirection) {
|
|
938
995
|
this._attributesStrideSize += 3;
|
|
939
996
|
if (this._platform.alignDataInBuffer) {
|
|
940
997
|
this._attributesStrideSize += 1;
|
|
@@ -1016,7 +1073,7 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1016
1073
|
data.push(0.0);
|
|
1017
1074
|
offset += 4;
|
|
1018
1075
|
}
|
|
1019
|
-
if (
|
|
1076
|
+
if (this._needsInitialDirection) {
|
|
1020
1077
|
// initialDirection
|
|
1021
1078
|
data.push(0.0);
|
|
1022
1079
|
data.push(0.0);
|
|
@@ -1081,6 +1138,12 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1081
1138
|
this._sourceBuffer = this._buffer0;
|
|
1082
1139
|
this._targetBuffer = this._buffer1;
|
|
1083
1140
|
}
|
|
1141
|
+
/**
|
|
1142
|
+
* Forces the update effect to be recreated on the next render.
|
|
1143
|
+
*/
|
|
1144
|
+
_resetEffect() {
|
|
1145
|
+
this._cachedUpdateDefines = "";
|
|
1146
|
+
}
|
|
1084
1147
|
/** @internal */
|
|
1085
1148
|
_recreateUpdateEffect() {
|
|
1086
1149
|
this._createColorGradientTexture();
|
|
@@ -1091,7 +1154,11 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1091
1154
|
this._createDragGradientTexture();
|
|
1092
1155
|
let defines = this.particleEmitterType ? this.particleEmitterType.getEffectDefines() : "";
|
|
1093
1156
|
if (this._isBillboardBased) {
|
|
1094
|
-
|
|
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
|
+
}
|
|
1095
1162
|
}
|
|
1096
1163
|
if (this._colorGradientsTexture) {
|
|
1097
1164
|
defines += "\n#define COLORGRADIENTS";
|
|
@@ -1133,6 +1200,12 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1133
1200
|
if (this._emitRateControl) {
|
|
1134
1201
|
defines += "\n#define EMITRATECTRL";
|
|
1135
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
|
+
}
|
|
1136
1209
|
if (this._platform.isUpdateBufferCreated() && this._cachedUpdateDefines === defines) {
|
|
1137
1210
|
return this._platform.isUpdateBufferReady();
|
|
1138
1211
|
}
|
|
@@ -1172,7 +1245,7 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1172
1245
|
/**
|
|
1173
1246
|
* @internal
|
|
1174
1247
|
*/
|
|
1175
|
-
static _GetAttributeNamesOrOptions(hasColorGradients = false, isAnimationSheetEnabled = false, isBillboardBased = false, isBillboardStretched = false) {
|
|
1248
|
+
static _GetAttributeNamesOrOptions(hasColorGradients = false, isAnimationSheetEnabled = false, isBillboardBased = false, isBillboardStretched = false, isBillboardStretchedLocal = false) {
|
|
1176
1249
|
const attributeNamesOrOptions = [VertexBuffer.PositionKind, "age", "life", "size", "angle"];
|
|
1177
1250
|
if (!hasColorGradients) {
|
|
1178
1251
|
attributeNamesOrOptions.push(VertexBuffer.ColorKind);
|
|
@@ -1180,7 +1253,7 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1180
1253
|
if (isAnimationSheetEnabled) {
|
|
1181
1254
|
attributeNamesOrOptions.push("cellIndex");
|
|
1182
1255
|
}
|
|
1183
|
-
if (!isBillboardBased) {
|
|
1256
|
+
if (!isBillboardBased || isBillboardStretchedLocal) {
|
|
1184
1257
|
attributeNamesOrOptions.push("initialDirection");
|
|
1185
1258
|
}
|
|
1186
1259
|
if (isBillboardStretched) {
|
|
@@ -1238,6 +1311,10 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1238
1311
|
case ParticleSystem.BILLBOARDMODE_STRETCHED:
|
|
1239
1312
|
defines.push("#define BILLBOARDSTRETCHED");
|
|
1240
1313
|
break;
|
|
1314
|
+
case ParticleSystem.BILLBOARDMODE_STRETCHED_LOCAL:
|
|
1315
|
+
defines.push("#define BILLBOARDSTRETCHED");
|
|
1316
|
+
defines.push("#define BILLBOARDSTRETCHED_LOCAL");
|
|
1317
|
+
break;
|
|
1241
1318
|
case ParticleSystem.BILLBOARDMODE_ALL:
|
|
1242
1319
|
defines.push("#define BILLBOARDMODE_ALL");
|
|
1243
1320
|
break;
|
|
@@ -1266,7 +1343,7 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1266
1343
|
* @param samplers Samplers array to fill
|
|
1267
1344
|
*/
|
|
1268
1345
|
fillUniformsAttributesAndSamplerNames(uniforms, attributes, samplers) {
|
|
1269
|
-
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));
|
|
1270
1347
|
uniforms.push(...GPUParticleSystem._GetEffectCreationOptions(this._isAnimationSheetEnabled, this.useLogarithmicDepth, this.applyFog));
|
|
1271
1348
|
samplers.push("diffuseSampler", "colorGradientSampler");
|
|
1272
1349
|
if (this._imageProcessingConfiguration) {
|
|
@@ -1491,6 +1568,12 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1491
1568
|
}
|
|
1492
1569
|
}
|
|
1493
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
|
+
}
|
|
1494
1577
|
this._platform.updateParticleBuffer(this._targetIndex, this._targetBuffer, this._currentActiveCount);
|
|
1495
1578
|
// Switch VAOs
|
|
1496
1579
|
this._targetIndex++;
|
|
@@ -1535,6 +1618,48 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1535
1618
|
}
|
|
1536
1619
|
// Get everything ready to render
|
|
1537
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
|
+
}
|
|
1538
1663
|
if (this._emitRateControl) {
|
|
1539
1664
|
// Emit-rate-controlled mode: limits active particles to ~emitRate * maxLifeTime,
|
|
1540
1665
|
// matching CPU particle behavior with circular buffer recycling.
|
|
@@ -1544,7 +1669,7 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1544
1669
|
this.manualEmitCount = 0;
|
|
1545
1670
|
}
|
|
1546
1671
|
else if (!this._stopped) {
|
|
1547
|
-
this._accumulatedCount +=
|
|
1672
|
+
this._accumulatedCount += effectiveEmitRate * this._timeDelta;
|
|
1548
1673
|
}
|
|
1549
1674
|
// Convert accumulated fractional count into whole particles to emit this frame.
|
|
1550
1675
|
// The fractional remainder carries over to the next frame.
|
|
@@ -1559,7 +1684,7 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1559
1684
|
// When emitRate is 0 but manualEmitCount is used, the rate-based steady state
|
|
1560
1685
|
// would be 0, blocking buffer growth. Use newParticles as a floor so manual
|
|
1561
1686
|
// emissions can always allocate slots.
|
|
1562
|
-
const steadyStateCount = Math.min(Math.max(Math.ceil(
|
|
1687
|
+
const steadyStateCount = Math.min(Math.max(Math.ceil(effectiveEmitRate * this.maxLifeTime), newParticles), this._maxActiveParticleCount);
|
|
1563
1688
|
// During ramp-up, grow the active buffer size by adding new slots.
|
|
1564
1689
|
// Once _currentActiveCount reaches steadyStateCount, no new slots are added —
|
|
1565
1690
|
// existing slots are recycled instead (handled by _emitIndex below).
|
|
@@ -1588,7 +1713,7 @@ export class GPUParticleSystem extends BaseParticleSystem {
|
|
|
1588
1713
|
this.manualEmitCount = 0;
|
|
1589
1714
|
}
|
|
1590
1715
|
else {
|
|
1591
|
-
this._accumulatedCount +=
|
|
1716
|
+
this._accumulatedCount += effectiveEmitRate * this._timeDelta;
|
|
1592
1717
|
}
|
|
1593
1718
|
if (this._accumulatedCount >= 1) {
|
|
1594
1719
|
const intPart = this._accumulatedCount | 0;
|