@newkrok/three-particles 2.11.2 → 2.13.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.
package/dist/index.js CHANGED
@@ -173,6 +173,8 @@ var ForceFieldType = /* @__PURE__ */ ((ForceFieldType2) => {
173
173
  var RendererType = /* @__PURE__ */ ((RendererType2) => {
174
174
  RendererType2["POINTS"] = "POINTS";
175
175
  RendererType2["INSTANCED"] = "INSTANCED";
176
+ RendererType2["TRAIL"] = "TRAIL";
177
+ RendererType2["MESH"] = "MESH";
176
178
  return RendererType2;
177
179
  })(RendererType || {});
178
180
  var ForceFieldFalloff = /* @__PURE__ */ ((ForceFieldFalloff2) => {
@@ -309,6 +311,24 @@ var calculateRandomPositionAndVelocityOnRectangle = (position, quaternion, veloc
309
311
  velocity.set(0, 0, speed);
310
312
  velocity.applyQuaternion(quaternion);
311
313
  };
314
+ var createDefaultMeshTexture = () => {
315
+ try {
316
+ const canvas = document.createElement("canvas");
317
+ canvas.width = 1;
318
+ canvas.height = 1;
319
+ const context = canvas.getContext("2d");
320
+ if (context) {
321
+ context.fillStyle = "white";
322
+ context.fillRect(0, 0, 1, 1);
323
+ const texture = new THREE4.CanvasTexture(canvas);
324
+ texture.needsUpdate = true;
325
+ return texture;
326
+ }
327
+ return null;
328
+ } catch {
329
+ return null;
330
+ }
331
+ };
312
332
  var createDefaultParticleTexture = () => {
313
333
  try {
314
334
  const canvas = document.createElement("canvas");
@@ -493,6 +513,16 @@ var applyModifiers = ({
493
513
  positionArr[positionIndex + 2] += noiseOnPosition * noisePower * positionAmount;
494
514
  attributes.position.needsUpdate = true;
495
515
  }
516
+ if (attributes.quat) {
517
+ const rotZ = attributes.rotation.array[particleIndex];
518
+ const halfZ = rotZ * 0.5;
519
+ const qi = particleIndex * 4;
520
+ attributes.quat.array[qi] = 0;
521
+ attributes.quat.array[qi + 1] = 0;
522
+ attributes.quat.array[qi + 2] = Math.sin(halfZ);
523
+ attributes.quat.array[qi + 3] = Math.cos(halfZ);
524
+ attributes.quat.needsUpdate = true;
525
+ }
496
526
  };
497
527
 
498
528
  // src/js/effects/three-particles/shaders/instanced-particle-fragment-shader.glsl.ts
@@ -629,6 +659,129 @@ var InstancedParticleVertexShader = `
629
659
  `;
630
660
  var instanced_particle_vertex_shader_glsl_default = InstancedParticleVertexShader;
631
661
 
662
+ // src/js/effects/three-particles/shaders/mesh-particle-fragment-shader.glsl.ts
663
+ var MeshParticleFragmentShader = `
664
+ uniform sampler2D map;
665
+ uniform float elapsed;
666
+ uniform float fps;
667
+ uniform bool useFPSForFrameIndex;
668
+ uniform vec2 tiles;
669
+ uniform bool discardBackgroundColor;
670
+ uniform vec3 backgroundColor;
671
+ uniform float backgroundColorTolerance;
672
+
673
+ varying vec4 vColor;
674
+ varying float vLifetime;
675
+ varying float vStartLifetime;
676
+ varying float vStartFrame;
677
+ varying float vRotation;
678
+ varying vec3 vNormal;
679
+ varying vec2 vUv;
680
+
681
+ #include <common>
682
+ #include <logdepthbuf_pars_fragment>
683
+
684
+ void main()
685
+ {
686
+ gl_FragColor = vColor;
687
+
688
+ // Use mesh UVs directly for texture sampling
689
+ vec2 uvPoint = vUv;
690
+
691
+ // Apply texture sheet animation if tiles > 1x1
692
+ if (tiles.x > 1.0 || tiles.y > 1.0) {
693
+ float frameIndex = round(vStartFrame) + (
694
+ useFPSForFrameIndex == true
695
+ ? fps == 0.0
696
+ ? 0.0
697
+ : max((vLifetime / 1000.0) * fps, 0.0)
698
+ : max(min(floor(min(vLifetime / vStartLifetime, 1.0) * (tiles.x * tiles.y)), tiles.x * tiles.y - 1.0), 0.0)
699
+ );
700
+
701
+ float spriteXIndex = floor(mod(frameIndex, tiles.x));
702
+ float spriteYIndex = floor(mod(frameIndex / tiles.x, tiles.y));
703
+
704
+ uvPoint = vec2(
705
+ vUv.x / tiles.x + spriteXIndex / tiles.x,
706
+ vUv.y / tiles.y + spriteYIndex / tiles.y
707
+ );
708
+ }
709
+
710
+ vec4 texColor = texture2D(map, uvPoint);
711
+ gl_FragColor = gl_FragColor * texColor;
712
+
713
+ if (discardBackgroundColor && abs(length(texColor.rgb - backgroundColor.rgb)) < backgroundColorTolerance) discard;
714
+
715
+ // Simple directional lighting from camera direction
716
+ float lightIntensity = 0.5 + 0.5 * max(dot(vNormal, vec3(0.0, 0.0, 1.0)), 0.0);
717
+ gl_FragColor.rgb *= lightIntensity;
718
+
719
+ #include <logdepthbuf_fragment>
720
+ }
721
+ `;
722
+ var mesh_particle_fragment_shader_glsl_default = MeshParticleFragmentShader;
723
+
724
+ // src/js/effects/three-particles/shaders/mesh-particle-vertex-shader.glsl.ts
725
+ var MeshParticleVertexShader = `
726
+ attribute float instanceSize;
727
+ attribute float instanceColorR;
728
+ attribute float instanceColorG;
729
+ attribute float instanceColorB;
730
+ attribute float instanceColorA;
731
+ attribute float instanceLifetime;
732
+ attribute float instanceStartLifetime;
733
+ attribute float instanceRotation;
734
+ attribute float instanceStartFrame;
735
+ attribute vec3 instanceOffset;
736
+ attribute vec4 instanceQuat;
737
+
738
+ varying vec4 vColor;
739
+ varying float vLifetime;
740
+ varying float vStartLifetime;
741
+ varying float vStartFrame;
742
+ varying float vRotation;
743
+ varying vec3 vNormal;
744
+ varying vec2 vUv;
745
+
746
+ #include <common>
747
+ #include <logdepthbuf_pars_vertex>
748
+
749
+ vec3 applyQuaternion(vec3 v, vec4 q) {
750
+ vec3 t = 2.0 * cross(q.xyz, v);
751
+ return v + q.w * t + cross(q.xyz, t);
752
+ }
753
+
754
+ void main()
755
+ {
756
+ vColor = vec4(instanceColorR, instanceColorG, instanceColorB, instanceColorA);
757
+ vLifetime = instanceLifetime;
758
+ vStartLifetime = instanceStartLifetime;
759
+ vStartFrame = instanceStartFrame;
760
+ vRotation = instanceRotation;
761
+
762
+ // Apply quaternion rotation to the mesh vertex position
763
+ vec3 rotatedPosition = applyQuaternion(position, instanceQuat);
764
+
765
+ // Scale mesh by particle size
766
+ vec3 scaledPosition = rotatedPosition * instanceSize;
767
+
768
+ // Apply instance offset (particle world position)
769
+ vec3 worldPos = scaledPosition + instanceOffset;
770
+
771
+ vec4 mvPosition = modelViewMatrix * vec4(worldPos, 1.0);
772
+ gl_Position = projectionMatrix * mvPosition;
773
+
774
+ // Transform normal by quaternion for lighting
775
+ vNormal = normalize((modelViewMatrix * vec4(applyQuaternion(normal, instanceQuat), 0.0)).xyz);
776
+
777
+ // Pass through UVs from the mesh geometry
778
+ vUv = uv;
779
+
780
+ #include <logdepthbuf_vertex>
781
+ }
782
+ `;
783
+ var mesh_particle_vertex_shader_glsl_default = MeshParticleVertexShader;
784
+
632
785
  // src/js/effects/three-particles/shaders/particle-system-fragment-shader.glsl.ts
633
786
  var ParticleSystemFragmentShader = `
634
787
  uniform sampler2D map;
@@ -740,6 +893,115 @@ var ParticleSystemVertexShader = `
740
893
  }
741
894
  `;
742
895
  var particle_system_vertex_shader_glsl_default = ParticleSystemVertexShader;
896
+
897
+ // src/js/effects/three-particles/shaders/trail-fragment-shader.glsl.ts
898
+ var TrailFragmentShader = `
899
+ uniform sampler2D map;
900
+ uniform bool useMap;
901
+ uniform bool discardBackgroundColor;
902
+ uniform vec3 backgroundColor;
903
+ uniform float backgroundColorTolerance;
904
+
905
+ varying float vAlpha;
906
+ varying vec4 vColor;
907
+ varying vec2 vUv;
908
+
909
+ #include <common>
910
+ #include <logdepthbuf_pars_fragment>
911
+
912
+ void main()
913
+ {
914
+ // Soft edge: always fade near ribbon edges
915
+ float edgeDist = 1.0 - abs(vUv.x * 2.0 - 1.0);
916
+ float softEdge = smoothstep(0.0, 0.4, edgeDist);
917
+
918
+ gl_FragColor = vColor;
919
+
920
+ if (useMap) {
921
+ // Use texture luminance as brightness modulation on top of soft edge
922
+ vec4 texColor = texture2D(map, vUv);
923
+ float texBrightness = dot(texColor.rgb, vec3(0.299, 0.587, 0.114));
924
+ gl_FragColor.rgb *= (0.5 + texBrightness * 0.5);
925
+ gl_FragColor.a *= texColor.a;
926
+ }
927
+
928
+ gl_FragColor.a *= vAlpha * softEdge;
929
+
930
+ if (gl_FragColor.a < 0.001) discard;
931
+
932
+ if (discardBackgroundColor && abs(length(gl_FragColor.rgb - backgroundColor.rgb)) < backgroundColorTolerance) discard;
933
+
934
+ #include <logdepthbuf_fragment>
935
+ }
936
+ `;
937
+ var trail_fragment_shader_glsl_default = TrailFragmentShader;
938
+
939
+ // src/js/effects/three-particles/shaders/trail-vertex-shader.glsl.ts
940
+ var TrailVertexShader = `
941
+ attribute float trailAlpha;
942
+ attribute vec4 trailColor;
943
+ attribute float trailOffset;
944
+ attribute float trailHalfWidth;
945
+ attribute vec3 trailNext;
946
+ attribute vec2 trailUV;
947
+
948
+ varying float vAlpha;
949
+ varying vec4 vColor;
950
+ varying vec2 vUv;
951
+
952
+ #include <common>
953
+ #include <logdepthbuf_pars_vertex>
954
+
955
+ void main()
956
+ {
957
+ vAlpha = trailAlpha;
958
+ vColor = trailColor;
959
+ vUv = trailUV;
960
+
961
+ // Compute tangent from current position to next sample
962
+ vec3 tangent = trailNext - position;
963
+ float tangentLen = length(tangent);
964
+ if (tangentLen < 0.0001) {
965
+ tangent = vec3(0.0, 1.0, 0.0);
966
+ } else {
967
+ tangent = tangent / tangentLen;
968
+ }
969
+
970
+ // Billboard: perpendicular = cross(tangent, viewDirection)
971
+ vec3 worldPos = (modelMatrix * vec4(position, 1.0)).xyz;
972
+ vec3 viewDir = normalize(cameraPosition - worldPos);
973
+ vec3 perp = cross(tangent, viewDir);
974
+ float perpLen = length(perp);
975
+
976
+ // When tangent is nearly parallel to view direction, the cross product
977
+ // collapses and the ribbon becomes edge-on (invisible). Use a secondary
978
+ // perpendicular from cross(tangent, up) and blend it in to guarantee
979
+ // a minimum visible width.
980
+ vec3 upPerp = cross(tangent, vec3(0.0, 1.0, 0.0));
981
+ float upPerpLen = length(upPerp);
982
+ if (upPerpLen < 0.0001) {
983
+ upPerp = cross(tangent, vec3(1.0, 0.0, 0.0));
984
+ upPerpLen = length(upPerp);
985
+ }
986
+ upPerp = upPerp / max(upPerpLen, 0.0001);
987
+
988
+ if (perpLen < 0.0001) {
989
+ perp = upPerp;
990
+ } else {
991
+ perp = perp / perpLen;
992
+ // Blend in the secondary perp when billboard perp gets weak
993
+ float blendFactor = smoothstep(0.0, 0.5, perpLen);
994
+ perp = normalize(mix(upPerp, perp, blendFactor));
995
+ }
996
+
997
+ vec3 offsetPos = position + perp * trailOffset * trailHalfWidth;
998
+ vec4 mvPosition = modelViewMatrix * vec4(offsetPos, 1.0);
999
+ gl_Position = projectionMatrix * mvPosition;
1000
+
1001
+ #include <logdepthbuf_vertex>
1002
+ }
1003
+ `;
1004
+ var trail_vertex_shader_glsl_default = TrailVertexShader;
743
1005
  var _forceDirection = new THREE4.Vector3();
744
1006
  var applyPointForce = (field, strength, velocity, positionArr, positionIndex, delta) => {
745
1007
  _forceDirection.set(
@@ -811,10 +1073,21 @@ var applyForceFields = ({
811
1073
  };
812
1074
 
813
1075
  // src/js/effects/three-particles/three-particles.ts
1076
+ var normalizeTrailCurve = (curve, defaultCurve) => {
1077
+ if (!curve) return defaultCurve;
1078
+ const raw = curve;
1079
+ if (!raw.type && Array.isArray(raw.bezierPoints)) {
1080
+ return { type: "BEZIER" /* BEZIER */, ...raw };
1081
+ }
1082
+ return curve;
1083
+ };
814
1084
  var _particleSystemId = 0;
815
1085
  var createdParticleSystems = [];
816
1086
  var _subEmitterPosition = new THREE4.Vector3();
817
1087
  var _lastWorldPositionSnapshot = new THREE4.Vector3();
1088
+ new THREE4.Vector3();
1089
+ new THREE4.Vector3();
1090
+ new THREE4.Vector3();
818
1091
  var _distanceStep = { x: 0, y: 0, z: 0 };
819
1092
  var _tempPosition = { x: 0, y: 0, z: 0 };
820
1093
  var _modifierParams = {
@@ -1059,12 +1332,20 @@ var destroyParticleSystem = (particleSystem) => {
1059
1332
  ({
1060
1333
  particleSystem: savedParticleSystem,
1061
1334
  wrapper,
1335
+ trailMesh,
1062
1336
  generalData: { particleSystemId }
1063
1337
  }) => {
1064
1338
  if (savedParticleSystem !== particleSystem && wrapper !== particleSystem) {
1065
1339
  return true;
1066
1340
  }
1067
1341
  removeBezierCurveFunction(particleSystemId);
1342
+ if (trailMesh) {
1343
+ trailMesh.geometry.dispose();
1344
+ if (Array.isArray(trailMesh.material))
1345
+ trailMesh.material.forEach((m) => m.dispose());
1346
+ else trailMesh.material.dispose();
1347
+ if (trailMesh.parent) trailMesh.parent.remove(trailMesh);
1348
+ }
1068
1349
  savedParticleSystem.geometry.dispose();
1069
1350
  if (Array.isArray(savedParticleSystem.material))
1070
1351
  savedParticleSystem.material.forEach((material) => material.dispose());
@@ -1110,7 +1391,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
1110
1391
  config,
1111
1392
  { applyToFirstObject: false, skippedProperties: [] }
1112
1393
  );
1113
- let particleMap = normalizedConfig.map || createDefaultParticleTexture();
1394
+ let particleMap = normalizedConfig.map || (normalizedConfig.renderer.rendererType === "MESH" /* MESH */ ? createDefaultMeshTexture() : createDefaultParticleTexture());
1114
1395
  const {
1115
1396
  transform,
1116
1397
  duration,
@@ -1294,9 +1575,42 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
1294
1575
  probabilityPassed: false
1295
1576
  }));
1296
1577
  }
1297
- const useInstancing = renderer.rendererType === "INSTANCED" /* INSTANCED */;
1298
- const attr = (name) => useInstancing ? `instance${name.charAt(0).toUpperCase()}${name.slice(1)}` : name;
1299
- const posAttr = useInstancing ? "instanceOffset" : "position";
1578
+ const useTrail = renderer.rendererType === "TRAIL" /* TRAIL */;
1579
+ const useMesh = renderer.rendererType === "MESH" /* MESH */;
1580
+ const useInstancing = !useTrail && !useMesh && renderer.rendererType === "INSTANCED" /* INSTANCED */;
1581
+ const useInstancedAttributes = useInstancing || useMesh;
1582
+ const defaultTrailCurve = {
1583
+ type: "BEZIER" /* BEZIER */,
1584
+ scale: 1,
1585
+ bezierPoints: [
1586
+ { x: 0, y: 1, percentage: 0 },
1587
+ { x: 1, y: 0, percentage: 1 }
1588
+ ]
1589
+ };
1590
+ const trailConfig = useTrail ? {
1591
+ length: renderer.trail?.length ?? 20,
1592
+ width: renderer.trail?.width ?? 1,
1593
+ widthOverTrail: normalizeTrailCurve(
1594
+ renderer.trail?.widthOverTrail,
1595
+ defaultTrailCurve
1596
+ ),
1597
+ opacityOverTrail: normalizeTrailCurve(
1598
+ renderer.trail?.opacityOverTrail,
1599
+ defaultTrailCurve
1600
+ ),
1601
+ colorOverTrail: renderer.trail?.colorOverTrail
1602
+ } : void 0;
1603
+ if (useTrail && trailConfig) {
1604
+ const trailLength = trailConfig.length;
1605
+ generalData.trailLength = trailLength;
1606
+ generalData.positionHistory = new Float32Array(
1607
+ maxParticles * trailLength * 3
1608
+ );
1609
+ generalData.positionHistoryIndex = new Uint16Array(maxParticles);
1610
+ generalData.positionHistoryCount = new Uint16Array(maxParticles);
1611
+ }
1612
+ const attr = (name) => useInstancedAttributes ? `instance${name.charAt(0).toUpperCase()}${name.slice(1)}` : name;
1613
+ const posAttr = useInstancedAttributes ? "instanceOffset" : "position";
1300
1614
  const sharedUniforms = {
1301
1615
  elapsed: { value: 0 },
1302
1616
  map: { value: particleMap },
@@ -1310,17 +1624,46 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
1310
1624
  backgroundColorTolerance: { value: renderer.backgroundColorTolerance },
1311
1625
  ...useInstancing ? { viewportHeight: { value: 1 } } : {}
1312
1626
  };
1627
+ const getVertexShader = () => {
1628
+ if (useMesh) return mesh_particle_vertex_shader_glsl_default;
1629
+ if (useInstancing) return instanced_particle_vertex_shader_glsl_default;
1630
+ return particle_system_vertex_shader_glsl_default;
1631
+ };
1632
+ const getFragmentShader = () => {
1633
+ if (useMesh) return mesh_particle_fragment_shader_glsl_default;
1634
+ if (useInstancing) return instanced_particle_fragment_shader_glsl_default;
1635
+ return particle_system_fragment_shader_glsl_default;
1636
+ };
1313
1637
  const material = new THREE4.ShaderMaterial({
1314
1638
  uniforms: sharedUniforms,
1315
- vertexShader: useInstancing ? instanced_particle_vertex_shader_glsl_default : particle_system_vertex_shader_glsl_default,
1316
- fragmentShader: useInstancing ? instanced_particle_fragment_shader_glsl_default : particle_system_fragment_shader_glsl_default,
1639
+ vertexShader: getVertexShader(),
1640
+ fragmentShader: getFragmentShader(),
1317
1641
  transparent: renderer.transparent,
1318
1642
  blending: renderer.blending,
1319
1643
  depthTest: renderer.depthTest,
1320
1644
  depthWrite: renderer.depthWrite
1321
1645
  });
1322
1646
  let geometry;
1323
- if (useInstancing) {
1647
+ if (useMesh) {
1648
+ const meshConfig = renderer.mesh;
1649
+ if (!meshConfig?.geometry) {
1650
+ throw new Error(
1651
+ "RendererType.MESH requires a mesh configuration with a geometry. Set renderer.mesh.geometry to a THREE.BufferGeometry instance."
1652
+ );
1653
+ }
1654
+ const instancedGeometry = new THREE4.InstancedBufferGeometry();
1655
+ const sourceGeom = meshConfig.geometry;
1656
+ const srcPos = sourceGeom.getAttribute("position");
1657
+ if (srcPos) instancedGeometry.setAttribute("position", srcPos);
1658
+ const srcNormal = sourceGeom.getAttribute("normal");
1659
+ if (srcNormal) instancedGeometry.setAttribute("normal", srcNormal);
1660
+ const srcUv = sourceGeom.getAttribute("uv");
1661
+ if (srcUv) instancedGeometry.setAttribute("uv", srcUv);
1662
+ const srcIndex = sourceGeom.getIndex();
1663
+ if (srcIndex) instancedGeometry.setIndex(srcIndex);
1664
+ instancedGeometry.instanceCount = maxParticles;
1665
+ geometry = instancedGeometry;
1666
+ } else if (useInstancing) {
1324
1667
  const instancedGeometry = new THREE4.InstancedBufferGeometry();
1325
1668
  const quadPositions = new Float32Array([
1326
1669
  -0.5,
@@ -1361,28 +1704,28 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
1361
1704
  positionArray[i * 3 + 1] = startPositions[i].y;
1362
1705
  positionArray[i * 3 + 2] = startPositions[i].z;
1363
1706
  }
1364
- const positionAttribute = useInstancing ? new THREE4.InstancedBufferAttribute(positionArray, 3) : new THREE4.BufferAttribute(positionArray, 3);
1707
+ const positionAttribute = useInstancedAttributes ? new THREE4.InstancedBufferAttribute(positionArray, 3) : new THREE4.BufferAttribute(positionArray, 3);
1365
1708
  geometry.setAttribute(posAttr, positionAttribute);
1366
1709
  createFloat32Attributes({
1367
1710
  geometry,
1368
1711
  propertyName: attr("isActive"),
1369
1712
  maxParticles,
1370
1713
  factory: 0,
1371
- instanced: useInstancing
1714
+ instanced: useInstancedAttributes
1372
1715
  });
1373
1716
  createFloat32Attributes({
1374
1717
  geometry,
1375
1718
  propertyName: attr("lifetime"),
1376
1719
  maxParticles,
1377
1720
  factory: 0,
1378
- instanced: useInstancing
1721
+ instanced: useInstancedAttributes
1379
1722
  });
1380
1723
  createFloat32Attributes({
1381
1724
  geometry,
1382
1725
  propertyName: attr("startLifetime"),
1383
1726
  maxParticles,
1384
1727
  factory: () => calculateValue(generalData.particleSystemId, startLifetime, 0) * 1e3,
1385
- instanced: useInstancing
1728
+ instanced: useInstancedAttributes
1386
1729
  });
1387
1730
  createFloat32Attributes({
1388
1731
  geometry,
@@ -1393,21 +1736,21 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
1393
1736
  textureSheetAnimation.startFrame,
1394
1737
  0
1395
1738
  ) : 0,
1396
- instanced: useInstancing
1739
+ instanced: useInstancedAttributes
1397
1740
  });
1398
1741
  createFloat32Attributes({
1399
1742
  geometry,
1400
1743
  propertyName: attr("size"),
1401
1744
  maxParticles,
1402
1745
  factory: (_, index) => generalData.startValues.startSize[index],
1403
- instanced: useInstancing
1746
+ instanced: useInstancedAttributes
1404
1747
  });
1405
1748
  createFloat32Attributes({
1406
1749
  geometry,
1407
1750
  propertyName: attr("rotation"),
1408
1751
  maxParticles,
1409
1752
  factory: 0,
1410
- instanced: useInstancing
1753
+ instanced: useInstancedAttributes
1411
1754
  });
1412
1755
  const colorRandomRatio = Math.random();
1413
1756
  createFloat32Attributes({
@@ -1415,29 +1758,39 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
1415
1758
  propertyName: attr("colorR"),
1416
1759
  maxParticles,
1417
1760
  factory: () => startColor.min.r + colorRandomRatio * (startColor.max.r - startColor.min.r),
1418
- instanced: useInstancing
1761
+ instanced: useInstancedAttributes
1419
1762
  });
1420
1763
  createFloat32Attributes({
1421
1764
  geometry,
1422
1765
  propertyName: attr("colorG"),
1423
1766
  maxParticles,
1424
1767
  factory: () => startColor.min.g + colorRandomRatio * (startColor.max.g - startColor.min.g),
1425
- instanced: useInstancing
1768
+ instanced: useInstancedAttributes
1426
1769
  });
1427
1770
  createFloat32Attributes({
1428
1771
  geometry,
1429
1772
  propertyName: attr("colorB"),
1430
1773
  maxParticles,
1431
1774
  factory: () => startColor.min.b + colorRandomRatio * (startColor.max.b - startColor.min.b),
1432
- instanced: useInstancing
1775
+ instanced: useInstancedAttributes
1433
1776
  });
1434
1777
  createFloat32Attributes({
1435
1778
  geometry,
1436
1779
  propertyName: attr("colorA"),
1437
1780
  maxParticles,
1438
1781
  factory: 0,
1439
- instanced: useInstancing
1782
+ instanced: useInstancedAttributes
1440
1783
  });
1784
+ if (useMesh) {
1785
+ const quatArray = new Float32Array(maxParticles * 4);
1786
+ for (let i = 0; i < maxParticles; i++) {
1787
+ quatArray[i * 4 + 3] = 1;
1788
+ }
1789
+ geometry.setAttribute(
1790
+ attr("quat"),
1791
+ new THREE4.InstancedBufferAttribute(quatArray, 4)
1792
+ );
1793
+ }
1441
1794
  const a = geometry.attributes;
1442
1795
  const aIsActive = a[attr("isActive")];
1443
1796
  const aColorR = a[attr("colorR")];
@@ -1450,6 +1803,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
1450
1803
  const aRotation = a[attr("rotation")];
1451
1804
  const aLifetime = a[attr("lifetime")];
1452
1805
  const aPosition = a[posAttr];
1806
+ const aQuat = useMesh ? a[attr("quat")] : void 0;
1453
1807
  const deactivateParticle = (particleIndex) => {
1454
1808
  aIsActive.array[particleIndex] = 0;
1455
1809
  aColorA.array[particleIndex] = 0;
@@ -1463,6 +1817,10 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
1463
1817
  }) => {
1464
1818
  aIsActive.array[particleIndex] = 1;
1465
1819
  generalData.creationTimes[particleIndex] = activationTime;
1820
+ if (generalData.positionHistoryCount) {
1821
+ generalData.positionHistoryCount[particleIndex] = 0;
1822
+ generalData.positionHistoryIndex[particleIndex] = 0;
1823
+ }
1466
1824
  if (generalData.noise.offsets)
1467
1825
  generalData.noise.offsets[particleIndex] = Math.random() * 100;
1468
1826
  const colorRandomRatio2 = Math.random();
@@ -1507,6 +1865,16 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
1507
1865
  generalData.normalizedLifetimePercentage
1508
1866
  );
1509
1867
  aRotation.needsUpdate = true;
1868
+ if (aQuat) {
1869
+ const rotZ = aRotation.array[particleIndex];
1870
+ const halfZ = rotZ * 0.5;
1871
+ const qi = particleIndex * 4;
1872
+ aQuat.array[qi] = 0;
1873
+ aQuat.array[qi + 1] = 0;
1874
+ aQuat.array[qi + 2] = Math.sin(halfZ);
1875
+ aQuat.array[qi + 3] = Math.cos(halfZ);
1876
+ aQuat.needsUpdate = true;
1877
+ }
1510
1878
  if (normalizedConfig.rotationOverLifetime.isActive)
1511
1879
  generalData.lifetimeValues.rotationOverLifetime[particleIndex] = THREE4.MathUtils.randFloat(
1512
1880
  normalizedConfig.rotationOverLifetime.min,
@@ -1632,7 +2000,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
1632
2000
  },
1633
2001
  renderer: {
1634
2002
  ...subConfig.config.renderer ?? {},
1635
- rendererType: renderer.rendererType
2003
+ ...subConfig.config.renderer?.rendererType ? {} : renderer.rendererType === "MESH" /* MESH */ || renderer.rendererType === "TRAIL" /* TRAIL */ ? {} : { rendererType: renderer.rendererType }
1636
2004
  },
1637
2005
  ...inheritVelocity > 0 ? {
1638
2006
  startSpeed: (typeof subConfig.config.startSpeed === "number" ? subConfig.config.startSpeed : typeof subConfig.config.startSpeed === "object" && subConfig.config.startSpeed !== null && "min" in subConfig.config.startSpeed ? subConfig.config.startSpeed.min ?? 0 : 0) + velocity.length() * inheritVelocity
@@ -1645,13 +2013,131 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
1645
2013
  instances.push(subSystem);
1646
2014
  }
1647
2015
  };
1648
- let particleSystem = useInstancing ? new THREE4.Mesh(geometry, material) : new THREE4.Points(geometry, material);
2016
+ let trailMesh;
2017
+ let trailGeometry;
2018
+ let trailPositionAttr;
2019
+ let trailAlphaAttr;
2020
+ let trailColorAttr;
2021
+ let trailIndexAttr;
2022
+ let trailWidthCurveFn;
2023
+ let trailOpacityCurveFn;
2024
+ let trailColorOverTrailFns;
2025
+ if (useTrail && trailConfig) {
2026
+ const trailLength = trailConfig.length;
2027
+ const verticesPerParticle = trailLength * 2;
2028
+ const totalVertices = maxParticles * verticesPerParticle;
2029
+ const indicesPerParticle = (trailLength - 1) * 6;
2030
+ const totalIndices = maxParticles * indicesPerParticle;
2031
+ trailGeometry = new THREE4.BufferGeometry();
2032
+ const trailPositions = new Float32Array(totalVertices * 3);
2033
+ const trailNextPositions = new Float32Array(totalVertices * 3);
2034
+ const trailAlphas = new Float32Array(totalVertices);
2035
+ const trailColors = new Float32Array(totalVertices * 4);
2036
+ const trailOffsets = new Float32Array(totalVertices);
2037
+ const trailHalfWidths = new Float32Array(totalVertices);
2038
+ const trailUVs = new Float32Array(totalVertices * 2);
2039
+ const trailIndices = new Uint32Array(totalIndices);
2040
+ for (let p = 0; p < maxParticles; p++) {
2041
+ const vertBase = p * verticesPerParticle;
2042
+ const idxBase = p * indicesPerParticle;
2043
+ for (let s = 0; s < trailLength; s++) {
2044
+ trailOffsets[vertBase + s * 2] = -1;
2045
+ trailOffsets[vertBase + s * 2 + 1] = 1;
2046
+ }
2047
+ for (let s = 0; s < trailLength - 1; s++) {
2048
+ const i = idxBase + s * 6;
2049
+ const v = vertBase + s * 2;
2050
+ trailIndices[i] = v;
2051
+ trailIndices[i + 1] = v + 1;
2052
+ trailIndices[i + 2] = v + 2;
2053
+ trailIndices[i + 3] = v + 1;
2054
+ trailIndices[i + 4] = v + 3;
2055
+ trailIndices[i + 5] = v + 2;
2056
+ }
2057
+ }
2058
+ trailPositionAttr = new THREE4.BufferAttribute(trailPositions, 3);
2059
+ trailPositionAttr.setUsage(THREE4.DynamicDrawUsage);
2060
+ const trailNextAttr = new THREE4.BufferAttribute(trailNextPositions, 3);
2061
+ trailNextAttr.setUsage(THREE4.DynamicDrawUsage);
2062
+ trailAlphaAttr = new THREE4.BufferAttribute(trailAlphas, 1);
2063
+ trailAlphaAttr.setUsage(THREE4.DynamicDrawUsage);
2064
+ trailColorAttr = new THREE4.BufferAttribute(trailColors, 4);
2065
+ trailColorAttr.setUsage(THREE4.DynamicDrawUsage);
2066
+ const trailHalfWidthAttr = new THREE4.BufferAttribute(trailHalfWidths, 1);
2067
+ trailHalfWidthAttr.setUsage(THREE4.DynamicDrawUsage);
2068
+ const trailUVAttr = new THREE4.BufferAttribute(trailUVs, 2);
2069
+ trailUVAttr.setUsage(THREE4.DynamicDrawUsage);
2070
+ trailIndexAttr = new THREE4.BufferAttribute(trailIndices, 1);
2071
+ trailGeometry.setAttribute("position", trailPositionAttr);
2072
+ trailGeometry.setAttribute("trailNext", trailNextAttr);
2073
+ trailGeometry.setAttribute("trailAlpha", trailAlphaAttr);
2074
+ trailGeometry.setAttribute("trailColor", trailColorAttr);
2075
+ trailGeometry.setAttribute(
2076
+ "trailOffset",
2077
+ new THREE4.BufferAttribute(trailOffsets, 1)
2078
+ );
2079
+ trailGeometry.setAttribute("trailHalfWidth", trailHalfWidthAttr);
2080
+ trailGeometry.setAttribute("trailUV", trailUVAttr);
2081
+ trailGeometry.setIndex(trailIndexAttr);
2082
+ const trailMaterial = new THREE4.ShaderMaterial({
2083
+ uniforms: {
2084
+ map: { value: particleMap },
2085
+ useMap: { value: !!particleMap },
2086
+ discardBackgroundColor: { value: renderer.discardBackgroundColor },
2087
+ backgroundColor: { value: renderer.backgroundColor },
2088
+ backgroundColorTolerance: { value: renderer.backgroundColorTolerance }
2089
+ },
2090
+ vertexShader: trail_vertex_shader_glsl_default,
2091
+ fragmentShader: trail_fragment_shader_glsl_default,
2092
+ transparent: renderer.transparent,
2093
+ blending: renderer.blending,
2094
+ depthTest: renderer.depthTest,
2095
+ depthWrite: renderer.depthWrite,
2096
+ side: THREE4.DoubleSide
2097
+ });
2098
+ trailMesh = new THREE4.Mesh(trailGeometry, trailMaterial);
2099
+ trailMesh.frustumCulled = false;
2100
+ const trailCameraPos = new THREE4.Vector3();
2101
+ trailMesh.onBeforeRender = (_renderer, _scene, camera) => {
2102
+ camera.getWorldPosition(trailCameraPos);
2103
+ };
2104
+ generalData.trailCameraPosition = trailCameraPos;
2105
+ trailWidthCurveFn = getCurveFunctionFromConfig(
2106
+ generalData.particleSystemId,
2107
+ trailConfig.widthOverTrail
2108
+ );
2109
+ trailOpacityCurveFn = getCurveFunctionFromConfig(
2110
+ generalData.particleSystemId,
2111
+ trailConfig.opacityOverTrail
2112
+ );
2113
+ if (trailConfig.colorOverTrail?.isActive) {
2114
+ trailColorOverTrailFns = {
2115
+ r: getCurveFunctionFromConfig(
2116
+ generalData.particleSystemId,
2117
+ normalizeTrailCurve(trailConfig.colorOverTrail.r, defaultTrailCurve)
2118
+ ),
2119
+ g: getCurveFunctionFromConfig(
2120
+ generalData.particleSystemId,
2121
+ normalizeTrailCurve(trailConfig.colorOverTrail.g, defaultTrailCurve)
2122
+ ),
2123
+ b: getCurveFunctionFromConfig(
2124
+ generalData.particleSystemId,
2125
+ normalizeTrailCurve(trailConfig.colorOverTrail.b, defaultTrailCurve)
2126
+ )
2127
+ };
2128
+ }
2129
+ }
2130
+ let particleSystem = useInstancing || useMesh ? new THREE4.Mesh(geometry, material) : new THREE4.Points(geometry, material);
1649
2131
  if (useInstancing) {
1650
2132
  particleSystem.onBeforeRender = (glRenderer) => {
1651
2133
  const size = glRenderer.getSize(new THREE4.Vector2());
1652
2134
  sharedUniforms.viewportHeight.value = size.y * glRenderer.getPixelRatio();
1653
2135
  };
1654
2136
  }
2137
+ if (useTrail && trailMesh) {
2138
+ material.visible = false;
2139
+ particleSystem.add(trailMesh);
2140
+ }
1655
2141
  particleSystem.position.copy(transform.position);
1656
2142
  particleSystem.rotation.x = THREE4.MathUtils.degToRad(transform.rotation.x);
1657
2143
  particleSystem.rotation.y = THREE4.MathUtils.degToRad(transform.rotation.y);
@@ -1668,7 +2154,8 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
1668
2154
  colorR: aColorR,
1669
2155
  colorG: aColorG,
1670
2156
  colorB: aColorB,
1671
- colorA: aColorA
2157
+ colorA: aColorA,
2158
+ ...useMesh ? { quat: aQuat } : {}
1672
2159
  };
1673
2160
  const calculatedCreationTime = now + calculateValue(generalData.particleSystemId, startDelay) * 1e3;
1674
2161
  let wrapper;
@@ -1729,7 +2216,20 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
1729
2216
  deactivateParticle,
1730
2217
  activateParticle,
1731
2218
  onParticleDeath,
1732
- onParticleBirth
2219
+ onParticleBirth,
2220
+ ...useTrail ? {
2221
+ trailMesh,
2222
+ trailPositionAttr,
2223
+ trailAlphaAttr,
2224
+ trailColorAttr,
2225
+ trailWidthCurveFn,
2226
+ trailOpacityCurveFn,
2227
+ trailColorOverTrailFns,
2228
+ trailConfig: {
2229
+ length: trailConfig.length,
2230
+ width: trailConfig.width
2231
+ }
2232
+ } : {}
1733
2233
  };
1734
2234
  createdParticleSystems.push(instanceData);
1735
2235
  const resumeEmitter = () => generalData.isEnabled = true;
@@ -1988,6 +2488,207 @@ var updateParticleSystemInstance = (props, { now, delta, elapsed }) => {
1988
2488
  onComplete({
1989
2489
  particleSystem
1990
2490
  });
2491
+ if (props.trailMesh) {
2492
+ updateTrailGeometry(props);
2493
+ }
2494
+ };
2495
+ var updateTrailGeometry = (props) => {
2496
+ const {
2497
+ generalData,
2498
+ trailPositionAttr,
2499
+ trailAlphaAttr,
2500
+ trailColorAttr,
2501
+ trailWidthCurveFn,
2502
+ trailOpacityCurveFn,
2503
+ trailColorOverTrailFns,
2504
+ trailConfig,
2505
+ mappedAttributes: ma
2506
+ } = props;
2507
+ if (!trailPositionAttr || !trailAlphaAttr || !trailColorAttr || !trailWidthCurveFn || !trailOpacityCurveFn || !trailConfig || !generalData.positionHistory || !generalData.positionHistoryIndex || !generalData.positionHistoryCount)
2508
+ return;
2509
+ const trailLength = trailConfig.length;
2510
+ const positionHistory = generalData.positionHistory;
2511
+ const historyIndex = generalData.positionHistoryIndex;
2512
+ const historyCount = generalData.positionHistoryCount;
2513
+ const isActiveArr = ma.isActive.array;
2514
+ const positionArr = ma.position.array;
2515
+ const colorRArr = ma.colorR.array;
2516
+ const colorGArr = ma.colorG.array;
2517
+ const colorBArr = ma.colorB.array;
2518
+ const colorAArr = ma.colorA.array;
2519
+ ma.size.array;
2520
+ const trailPosArr = trailPositionAttr.array;
2521
+ const trailAlphaArr = trailAlphaAttr.array;
2522
+ const trailColorArr = trailColorAttr.array;
2523
+ const trailMesh = props.trailMesh;
2524
+ const trailNextArr = trailMesh.geometry.getAttribute("trailNext").array;
2525
+ const trailUVArr = trailMesh.geometry.getAttribute("trailUV").array;
2526
+ const trailHalfWidthArr = trailMesh.geometry.getAttribute("trailHalfWidth").array;
2527
+ const verticesPerParticle = trailLength * 2;
2528
+ const creationTimesLength = generalData.creationTimes.length;
2529
+ let hasUpdates = false;
2530
+ for (let index = 0; index < creationTimesLength; index++) {
2531
+ const vertBase = index * verticesPerParticle;
2532
+ if (isActiveArr[index]) {
2533
+ hasUpdates = true;
2534
+ const posIdx = index * 3;
2535
+ const px = positionArr[posIdx];
2536
+ const py = positionArr[posIdx + 1];
2537
+ const pz = positionArr[posIdx + 2];
2538
+ const histBase = (index * trailLength + historyIndex[index]) * 3;
2539
+ positionHistory[histBase] = px;
2540
+ positionHistory[histBase + 1] = py;
2541
+ positionHistory[histBase + 2] = pz;
2542
+ historyIndex[index] = (historyIndex[index] + 1) % trailLength;
2543
+ if (historyCount[index] < trailLength) historyCount[index]++;
2544
+ const count = historyCount[index];
2545
+ const ribbonWidth = trailConfig.width;
2546
+ const cr = colorRArr[index];
2547
+ const cg = colorGArr[index];
2548
+ const cb = colorBArr[index];
2549
+ const ca = colorAArr[index];
2550
+ const ringOff = index * trailLength * 3;
2551
+ for (let s = 0; s < trailLength; s++) {
2552
+ const vIdx = (vertBase + s * 2) * 3;
2553
+ const cIdx = (vertBase + s * 2) * 4;
2554
+ const aIdx = vertBase + s * 2;
2555
+ if (s >= count) {
2556
+ trailPosArr[vIdx] = px;
2557
+ trailPosArr[vIdx + 1] = py;
2558
+ trailPosArr[vIdx + 2] = pz;
2559
+ trailPosArr[vIdx + 3] = px;
2560
+ trailPosArr[vIdx + 4] = py;
2561
+ trailPosArr[vIdx + 5] = pz;
2562
+ trailNextArr[vIdx] = px;
2563
+ trailNextArr[vIdx + 1] = py;
2564
+ trailNextArr[vIdx + 2] = pz;
2565
+ trailNextArr[vIdx + 3] = px;
2566
+ trailNextArr[vIdx + 4] = py;
2567
+ trailNextArr[vIdx + 5] = pz;
2568
+ trailHalfWidthArr[aIdx] = 0;
2569
+ trailHalfWidthArr[aIdx + 1] = 0;
2570
+ const uvIdx2 = (vertBase + s * 2) * 2;
2571
+ trailUVArr[uvIdx2] = 0;
2572
+ trailUVArr[uvIdx2 + 1] = 0;
2573
+ trailUVArr[uvIdx2 + 2] = 0;
2574
+ trailUVArr[uvIdx2 + 3] = 0;
2575
+ trailAlphaArr[aIdx] = 0;
2576
+ trailAlphaArr[aIdx + 1] = 0;
2577
+ trailColorArr[cIdx] = 0;
2578
+ trailColorArr[cIdx + 1] = 0;
2579
+ trailColorArr[cIdx + 2] = 0;
2580
+ trailColorArr[cIdx + 3] = 0;
2581
+ trailColorArr[cIdx + 4] = 0;
2582
+ trailColorArr[cIdx + 5] = 0;
2583
+ trailColorArr[cIdx + 6] = 0;
2584
+ trailColorArr[cIdx + 7] = 0;
2585
+ continue;
2586
+ }
2587
+ const histIdx = (historyIndex[index] - 1 - s + trailLength * 2) % trailLength * 3 + ringOff;
2588
+ const hx = positionHistory[histIdx];
2589
+ const hy = positionHistory[histIdx + 1];
2590
+ const hz = positionHistory[histIdx + 2];
2591
+ let nx, ny, nz;
2592
+ if (s < count - 1) {
2593
+ const ni = (historyIndex[index] - 2 - s + trailLength * 2) % trailLength * 3 + ringOff;
2594
+ nx = positionHistory[ni];
2595
+ ny = positionHistory[ni + 1];
2596
+ nz = positionHistory[ni + 2];
2597
+ } else {
2598
+ nx = hx;
2599
+ ny = hy + 1e-3;
2600
+ nz = hz;
2601
+ }
2602
+ const t = count > 1 ? s / (count - 1) : 0;
2603
+ const widthScale = trailWidthCurveFn(t);
2604
+ const opacityScale = trailOpacityCurveFn(t);
2605
+ const halfWidth = ribbonWidth * widthScale * 0.5;
2606
+ trailPosArr[vIdx] = hx;
2607
+ trailPosArr[vIdx + 1] = hy;
2608
+ trailPosArr[vIdx + 2] = hz;
2609
+ trailPosArr[vIdx + 3] = hx;
2610
+ trailPosArr[vIdx + 4] = hy;
2611
+ trailPosArr[vIdx + 5] = hz;
2612
+ trailNextArr[vIdx] = nx;
2613
+ trailNextArr[vIdx + 1] = ny;
2614
+ trailNextArr[vIdx + 2] = nz;
2615
+ trailNextArr[vIdx + 3] = nx;
2616
+ trailNextArr[vIdx + 4] = ny;
2617
+ trailNextArr[vIdx + 5] = nz;
2618
+ trailHalfWidthArr[aIdx] = halfWidth;
2619
+ trailHalfWidthArr[aIdx + 1] = halfWidth;
2620
+ const uvIdx = (vertBase + s * 2) * 2;
2621
+ trailUVArr[uvIdx] = 0;
2622
+ trailUVArr[uvIdx + 1] = t;
2623
+ trailUVArr[uvIdx + 2] = 1;
2624
+ trailUVArr[uvIdx + 3] = t;
2625
+ const alpha = ca * opacityScale;
2626
+ trailAlphaArr[aIdx] = alpha;
2627
+ trailAlphaArr[aIdx + 1] = alpha;
2628
+ const fr = trailColorOverTrailFns ? cr * trailColorOverTrailFns.r(t) : cr;
2629
+ const fg = trailColorOverTrailFns ? cg * trailColorOverTrailFns.g(t) : cg;
2630
+ const fb = trailColorOverTrailFns ? cb * trailColorOverTrailFns.b(t) : cb;
2631
+ trailColorArr[cIdx] = fr;
2632
+ trailColorArr[cIdx + 1] = fg;
2633
+ trailColorArr[cIdx + 2] = fb;
2634
+ trailColorArr[cIdx + 3] = ca;
2635
+ trailColorArr[cIdx + 4] = fr;
2636
+ trailColorArr[cIdx + 5] = fg;
2637
+ trailColorArr[cIdx + 6] = fb;
2638
+ trailColorArr[cIdx + 7] = ca;
2639
+ }
2640
+ } else if (historyCount[index] > 0) {
2641
+ hasUpdates = true;
2642
+ historyCount[index] = 0;
2643
+ historyIndex[index] = 0;
2644
+ for (let s = 0; s < trailLength; s++) {
2645
+ const vIdx = (vertBase + s * 2) * 3;
2646
+ const cIdx = (vertBase + s * 2) * 4;
2647
+ const aIdx = vertBase + s * 2;
2648
+ trailPosArr[vIdx] = 0;
2649
+ trailPosArr[vIdx + 1] = 0;
2650
+ trailPosArr[vIdx + 2] = 0;
2651
+ trailPosArr[vIdx + 3] = 0;
2652
+ trailPosArr[vIdx + 4] = 0;
2653
+ trailPosArr[vIdx + 5] = 0;
2654
+ trailNextArr[vIdx] = 0;
2655
+ trailNextArr[vIdx + 1] = 0;
2656
+ trailNextArr[vIdx + 2] = 0;
2657
+ trailNextArr[vIdx + 3] = 0;
2658
+ trailNextArr[vIdx + 4] = 0;
2659
+ trailNextArr[vIdx + 5] = 0;
2660
+ trailHalfWidthArr[aIdx] = 0;
2661
+ trailHalfWidthArr[aIdx + 1] = 0;
2662
+ trailAlphaArr[aIdx] = 0;
2663
+ trailAlphaArr[aIdx + 1] = 0;
2664
+ trailColorArr[cIdx] = 0;
2665
+ trailColorArr[cIdx + 1] = 0;
2666
+ trailColorArr[cIdx + 2] = 0;
2667
+ trailColorArr[cIdx + 3] = 0;
2668
+ trailColorArr[cIdx + 4] = 0;
2669
+ trailColorArr[cIdx + 5] = 0;
2670
+ trailColorArr[cIdx + 6] = 0;
2671
+ trailColorArr[cIdx + 7] = 0;
2672
+ }
2673
+ }
2674
+ }
2675
+ if (hasUpdates) {
2676
+ trailPositionAttr.needsUpdate = true;
2677
+ trailAlphaAttr.needsUpdate = true;
2678
+ trailColorAttr.needsUpdate = true;
2679
+ const nextAttr = trailMesh.geometry.getAttribute(
2680
+ "trailNext"
2681
+ );
2682
+ const hwAttr = trailMesh.geometry.getAttribute(
2683
+ "trailHalfWidth"
2684
+ );
2685
+ nextAttr.needsUpdate = true;
2686
+ hwAttr.needsUpdate = true;
2687
+ const uvAttr = trailMesh.geometry.getAttribute(
2688
+ "trailUV"
2689
+ );
2690
+ uvAttr.needsUpdate = true;
2691
+ }
1991
2692
  };
1992
2693
  var updateParticleSystems = (cycleData) => {
1993
2694
  createdParticleSystems.forEach(
@@ -1995,6 +2696,6 @@ var updateParticleSystems = (cycleData) => {
1995
2696
  );
1996
2697
  };
1997
2698
 
1998
- export { CurveFunctionId, EmitFrom, ForceFieldFalloff, ForceFieldType, LifeTimeCurve, RendererType, Shape, SimulationSpace, SubEmitterTrigger, TimeMode, applyModifiers, blendingMap, calculateRandomPositionAndVelocityOnBox, calculateRandomPositionAndVelocityOnCircle, calculateRandomPositionAndVelocityOnCone, calculateRandomPositionAndVelocityOnRectangle, calculateRandomPositionAndVelocityOnSphere, calculateValue, createBezierCurveFunction, createDefaultParticleTexture, createParticleSystem, curveFunctionIdMap, getBezierCacheSize, getCurveFunction, getCurveFunctionFromConfig, getDefaultParticleSystemConfig, isLifeTimeCurve, removeBezierCurveFunction, updateParticleSystems };
2699
+ export { CurveFunctionId, EmitFrom, ForceFieldFalloff, ForceFieldType, LifeTimeCurve, RendererType, Shape, SimulationSpace, SubEmitterTrigger, TimeMode, applyModifiers, blendingMap, calculateRandomPositionAndVelocityOnBox, calculateRandomPositionAndVelocityOnCircle, calculateRandomPositionAndVelocityOnCone, calculateRandomPositionAndVelocityOnRectangle, calculateRandomPositionAndVelocityOnSphere, calculateValue, createBezierCurveFunction, createDefaultMeshTexture, createDefaultParticleTexture, createParticleSystem, curveFunctionIdMap, getBezierCacheSize, getCurveFunction, getCurveFunctionFromConfig, getDefaultParticleSystemConfig, isLifeTimeCurve, removeBezierCurveFunction, updateParticleSystems };
1999
2700
  //# sourceMappingURL=index.js.map
2000
2701
  //# sourceMappingURL=index.js.map