@newkrok/three-particles 2.11.1 → 2.12.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/README.md +1 -0
- package/dist/index.d.ts +108 -2
- package/dist/index.js +498 -2
- package/dist/index.js.map +1 -1
- package/dist/three-particles.min.js +1 -1
- package/dist/three-particles.min.js.map +1 -1
- package/llms-full.txt +58 -0
- package/llms.txt +27 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -173,6 +173,7 @@ var ForceFieldType = /* @__PURE__ */ ((ForceFieldType2) => {
|
|
|
173
173
|
var RendererType = /* @__PURE__ */ ((RendererType2) => {
|
|
174
174
|
RendererType2["POINTS"] = "POINTS";
|
|
175
175
|
RendererType2["INSTANCED"] = "INSTANCED";
|
|
176
|
+
RendererType2["TRAIL"] = "TRAIL";
|
|
176
177
|
return RendererType2;
|
|
177
178
|
})(RendererType || {});
|
|
178
179
|
var ForceFieldFalloff = /* @__PURE__ */ ((ForceFieldFalloff2) => {
|
|
@@ -740,6 +741,115 @@ var ParticleSystemVertexShader = `
|
|
|
740
741
|
}
|
|
741
742
|
`;
|
|
742
743
|
var particle_system_vertex_shader_glsl_default = ParticleSystemVertexShader;
|
|
744
|
+
|
|
745
|
+
// src/js/effects/three-particles/shaders/trail-fragment-shader.glsl.ts
|
|
746
|
+
var TrailFragmentShader = `
|
|
747
|
+
uniform sampler2D map;
|
|
748
|
+
uniform bool useMap;
|
|
749
|
+
uniform bool discardBackgroundColor;
|
|
750
|
+
uniform vec3 backgroundColor;
|
|
751
|
+
uniform float backgroundColorTolerance;
|
|
752
|
+
|
|
753
|
+
varying float vAlpha;
|
|
754
|
+
varying vec4 vColor;
|
|
755
|
+
varying vec2 vUv;
|
|
756
|
+
|
|
757
|
+
#include <common>
|
|
758
|
+
#include <logdepthbuf_pars_fragment>
|
|
759
|
+
|
|
760
|
+
void main()
|
|
761
|
+
{
|
|
762
|
+
// Soft edge: always fade near ribbon edges
|
|
763
|
+
float edgeDist = 1.0 - abs(vUv.x * 2.0 - 1.0);
|
|
764
|
+
float softEdge = smoothstep(0.0, 0.4, edgeDist);
|
|
765
|
+
|
|
766
|
+
gl_FragColor = vColor;
|
|
767
|
+
|
|
768
|
+
if (useMap) {
|
|
769
|
+
// Use texture luminance as brightness modulation on top of soft edge
|
|
770
|
+
vec4 texColor = texture2D(map, vUv);
|
|
771
|
+
float texBrightness = dot(texColor.rgb, vec3(0.299, 0.587, 0.114));
|
|
772
|
+
gl_FragColor.rgb *= (0.5 + texBrightness * 0.5);
|
|
773
|
+
gl_FragColor.a *= texColor.a;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
gl_FragColor.a *= vAlpha * softEdge;
|
|
777
|
+
|
|
778
|
+
if (gl_FragColor.a < 0.001) discard;
|
|
779
|
+
|
|
780
|
+
if (discardBackgroundColor && abs(length(gl_FragColor.rgb - backgroundColor.rgb)) < backgroundColorTolerance) discard;
|
|
781
|
+
|
|
782
|
+
#include <logdepthbuf_fragment>
|
|
783
|
+
}
|
|
784
|
+
`;
|
|
785
|
+
var trail_fragment_shader_glsl_default = TrailFragmentShader;
|
|
786
|
+
|
|
787
|
+
// src/js/effects/three-particles/shaders/trail-vertex-shader.glsl.ts
|
|
788
|
+
var TrailVertexShader = `
|
|
789
|
+
attribute float trailAlpha;
|
|
790
|
+
attribute vec4 trailColor;
|
|
791
|
+
attribute float trailOffset;
|
|
792
|
+
attribute float trailHalfWidth;
|
|
793
|
+
attribute vec3 trailNext;
|
|
794
|
+
attribute vec2 trailUV;
|
|
795
|
+
|
|
796
|
+
varying float vAlpha;
|
|
797
|
+
varying vec4 vColor;
|
|
798
|
+
varying vec2 vUv;
|
|
799
|
+
|
|
800
|
+
#include <common>
|
|
801
|
+
#include <logdepthbuf_pars_vertex>
|
|
802
|
+
|
|
803
|
+
void main()
|
|
804
|
+
{
|
|
805
|
+
vAlpha = trailAlpha;
|
|
806
|
+
vColor = trailColor;
|
|
807
|
+
vUv = trailUV;
|
|
808
|
+
|
|
809
|
+
// Compute tangent from current position to next sample
|
|
810
|
+
vec3 tangent = trailNext - position;
|
|
811
|
+
float tangentLen = length(tangent);
|
|
812
|
+
if (tangentLen < 0.0001) {
|
|
813
|
+
tangent = vec3(0.0, 1.0, 0.0);
|
|
814
|
+
} else {
|
|
815
|
+
tangent = tangent / tangentLen;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
// Billboard: perpendicular = cross(tangent, viewDirection)
|
|
819
|
+
vec3 worldPos = (modelMatrix * vec4(position, 1.0)).xyz;
|
|
820
|
+
vec3 viewDir = normalize(cameraPosition - worldPos);
|
|
821
|
+
vec3 perp = cross(tangent, viewDir);
|
|
822
|
+
float perpLen = length(perp);
|
|
823
|
+
|
|
824
|
+
// When tangent is nearly parallel to view direction, the cross product
|
|
825
|
+
// collapses and the ribbon becomes edge-on (invisible). Use a secondary
|
|
826
|
+
// perpendicular from cross(tangent, up) and blend it in to guarantee
|
|
827
|
+
// a minimum visible width.
|
|
828
|
+
vec3 upPerp = cross(tangent, vec3(0.0, 1.0, 0.0));
|
|
829
|
+
float upPerpLen = length(upPerp);
|
|
830
|
+
if (upPerpLen < 0.0001) {
|
|
831
|
+
upPerp = cross(tangent, vec3(1.0, 0.0, 0.0));
|
|
832
|
+
upPerpLen = length(upPerp);
|
|
833
|
+
}
|
|
834
|
+
upPerp = upPerp / max(upPerpLen, 0.0001);
|
|
835
|
+
|
|
836
|
+
if (perpLen < 0.0001) {
|
|
837
|
+
perp = upPerp;
|
|
838
|
+
} else {
|
|
839
|
+
perp = perp / perpLen;
|
|
840
|
+
// Blend in the secondary perp when billboard perp gets weak
|
|
841
|
+
float blendFactor = smoothstep(0.0, 0.5, perpLen);
|
|
842
|
+
perp = normalize(mix(upPerp, perp, blendFactor));
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
vec3 offsetPos = position + perp * trailOffset * trailHalfWidth;
|
|
846
|
+
vec4 mvPosition = modelViewMatrix * vec4(offsetPos, 1.0);
|
|
847
|
+
gl_Position = projectionMatrix * mvPosition;
|
|
848
|
+
|
|
849
|
+
#include <logdepthbuf_vertex>
|
|
850
|
+
}
|
|
851
|
+
`;
|
|
852
|
+
var trail_vertex_shader_glsl_default = TrailVertexShader;
|
|
743
853
|
var _forceDirection = new THREE4.Vector3();
|
|
744
854
|
var applyPointForce = (field, strength, velocity, positionArr, positionIndex, delta) => {
|
|
745
855
|
_forceDirection.set(
|
|
@@ -811,10 +921,21 @@ var applyForceFields = ({
|
|
|
811
921
|
};
|
|
812
922
|
|
|
813
923
|
// src/js/effects/three-particles/three-particles.ts
|
|
924
|
+
var normalizeTrailCurve = (curve, defaultCurve) => {
|
|
925
|
+
if (!curve) return defaultCurve;
|
|
926
|
+
const raw = curve;
|
|
927
|
+
if (!raw.type && Array.isArray(raw.bezierPoints)) {
|
|
928
|
+
return { type: "BEZIER" /* BEZIER */, ...raw };
|
|
929
|
+
}
|
|
930
|
+
return curve;
|
|
931
|
+
};
|
|
814
932
|
var _particleSystemId = 0;
|
|
815
933
|
var createdParticleSystems = [];
|
|
816
934
|
var _subEmitterPosition = new THREE4.Vector3();
|
|
817
935
|
var _lastWorldPositionSnapshot = new THREE4.Vector3();
|
|
936
|
+
new THREE4.Vector3();
|
|
937
|
+
new THREE4.Vector3();
|
|
938
|
+
new THREE4.Vector3();
|
|
818
939
|
var _distanceStep = { x: 0, y: 0, z: 0 };
|
|
819
940
|
var _tempPosition = { x: 0, y: 0, z: 0 };
|
|
820
941
|
var _modifierParams = {
|
|
@@ -1059,12 +1180,20 @@ var destroyParticleSystem = (particleSystem) => {
|
|
|
1059
1180
|
({
|
|
1060
1181
|
particleSystem: savedParticleSystem,
|
|
1061
1182
|
wrapper,
|
|
1183
|
+
trailMesh,
|
|
1062
1184
|
generalData: { particleSystemId }
|
|
1063
1185
|
}) => {
|
|
1064
1186
|
if (savedParticleSystem !== particleSystem && wrapper !== particleSystem) {
|
|
1065
1187
|
return true;
|
|
1066
1188
|
}
|
|
1067
1189
|
removeBezierCurveFunction(particleSystemId);
|
|
1190
|
+
if (trailMesh) {
|
|
1191
|
+
trailMesh.geometry.dispose();
|
|
1192
|
+
if (Array.isArray(trailMesh.material))
|
|
1193
|
+
trailMesh.material.forEach((m) => m.dispose());
|
|
1194
|
+
else trailMesh.material.dispose();
|
|
1195
|
+
if (trailMesh.parent) trailMesh.parent.remove(trailMesh);
|
|
1196
|
+
}
|
|
1068
1197
|
savedParticleSystem.geometry.dispose();
|
|
1069
1198
|
if (Array.isArray(savedParticleSystem.material))
|
|
1070
1199
|
savedParticleSystem.material.forEach((material) => material.dispose());
|
|
@@ -1294,7 +1423,38 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1294
1423
|
probabilityPassed: false
|
|
1295
1424
|
}));
|
|
1296
1425
|
}
|
|
1297
|
-
const
|
|
1426
|
+
const useTrail = renderer.rendererType === "TRAIL" /* TRAIL */;
|
|
1427
|
+
const useInstancing = !useTrail && renderer.rendererType === "INSTANCED" /* INSTANCED */;
|
|
1428
|
+
const defaultTrailCurve = {
|
|
1429
|
+
type: "BEZIER" /* BEZIER */,
|
|
1430
|
+
scale: 1,
|
|
1431
|
+
bezierPoints: [
|
|
1432
|
+
{ x: 0, y: 1, percentage: 0 },
|
|
1433
|
+
{ x: 1, y: 0, percentage: 1 }
|
|
1434
|
+
]
|
|
1435
|
+
};
|
|
1436
|
+
const trailConfig = useTrail ? {
|
|
1437
|
+
length: renderer.trail?.length ?? 20,
|
|
1438
|
+
width: renderer.trail?.width ?? 1,
|
|
1439
|
+
widthOverTrail: normalizeTrailCurve(
|
|
1440
|
+
renderer.trail?.widthOverTrail,
|
|
1441
|
+
defaultTrailCurve
|
|
1442
|
+
),
|
|
1443
|
+
opacityOverTrail: normalizeTrailCurve(
|
|
1444
|
+
renderer.trail?.opacityOverTrail,
|
|
1445
|
+
defaultTrailCurve
|
|
1446
|
+
),
|
|
1447
|
+
colorOverTrail: renderer.trail?.colorOverTrail
|
|
1448
|
+
} : void 0;
|
|
1449
|
+
if (useTrail && trailConfig) {
|
|
1450
|
+
const trailLength = trailConfig.length;
|
|
1451
|
+
generalData.trailLength = trailLength;
|
|
1452
|
+
generalData.positionHistory = new Float32Array(
|
|
1453
|
+
maxParticles * trailLength * 3
|
|
1454
|
+
);
|
|
1455
|
+
generalData.positionHistoryIndex = new Uint16Array(maxParticles);
|
|
1456
|
+
generalData.positionHistoryCount = new Uint16Array(maxParticles);
|
|
1457
|
+
}
|
|
1298
1458
|
const attr = (name) => useInstancing ? `instance${name.charAt(0).toUpperCase()}${name.slice(1)}` : name;
|
|
1299
1459
|
const posAttr = useInstancing ? "instanceOffset" : "position";
|
|
1300
1460
|
const sharedUniforms = {
|
|
@@ -1463,6 +1623,10 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1463
1623
|
}) => {
|
|
1464
1624
|
aIsActive.array[particleIndex] = 1;
|
|
1465
1625
|
generalData.creationTimes[particleIndex] = activationTime;
|
|
1626
|
+
if (generalData.positionHistoryCount) {
|
|
1627
|
+
generalData.positionHistoryCount[particleIndex] = 0;
|
|
1628
|
+
generalData.positionHistoryIndex[particleIndex] = 0;
|
|
1629
|
+
}
|
|
1466
1630
|
if (generalData.noise.offsets)
|
|
1467
1631
|
generalData.noise.offsets[particleIndex] = Math.random() * 100;
|
|
1468
1632
|
const colorRandomRatio2 = Math.random();
|
|
@@ -1645,6 +1809,120 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1645
1809
|
instances.push(subSystem);
|
|
1646
1810
|
}
|
|
1647
1811
|
};
|
|
1812
|
+
let trailMesh;
|
|
1813
|
+
let trailGeometry;
|
|
1814
|
+
let trailPositionAttr;
|
|
1815
|
+
let trailAlphaAttr;
|
|
1816
|
+
let trailColorAttr;
|
|
1817
|
+
let trailIndexAttr;
|
|
1818
|
+
let trailWidthCurveFn;
|
|
1819
|
+
let trailOpacityCurveFn;
|
|
1820
|
+
let trailColorOverTrailFns;
|
|
1821
|
+
if (useTrail && trailConfig) {
|
|
1822
|
+
const trailLength = trailConfig.length;
|
|
1823
|
+
const verticesPerParticle = trailLength * 2;
|
|
1824
|
+
const totalVertices = maxParticles * verticesPerParticle;
|
|
1825
|
+
const indicesPerParticle = (trailLength - 1) * 6;
|
|
1826
|
+
const totalIndices = maxParticles * indicesPerParticle;
|
|
1827
|
+
trailGeometry = new THREE4.BufferGeometry();
|
|
1828
|
+
const trailPositions = new Float32Array(totalVertices * 3);
|
|
1829
|
+
const trailNextPositions = new Float32Array(totalVertices * 3);
|
|
1830
|
+
const trailAlphas = new Float32Array(totalVertices);
|
|
1831
|
+
const trailColors = new Float32Array(totalVertices * 4);
|
|
1832
|
+
const trailOffsets = new Float32Array(totalVertices);
|
|
1833
|
+
const trailHalfWidths = new Float32Array(totalVertices);
|
|
1834
|
+
const trailUVs = new Float32Array(totalVertices * 2);
|
|
1835
|
+
const trailIndices = new Uint32Array(totalIndices);
|
|
1836
|
+
for (let p = 0; p < maxParticles; p++) {
|
|
1837
|
+
const vertBase = p * verticesPerParticle;
|
|
1838
|
+
const idxBase = p * indicesPerParticle;
|
|
1839
|
+
for (let s = 0; s < trailLength; s++) {
|
|
1840
|
+
trailOffsets[vertBase + s * 2] = -1;
|
|
1841
|
+
trailOffsets[vertBase + s * 2 + 1] = 1;
|
|
1842
|
+
}
|
|
1843
|
+
for (let s = 0; s < trailLength - 1; s++) {
|
|
1844
|
+
const i = idxBase + s * 6;
|
|
1845
|
+
const v = vertBase + s * 2;
|
|
1846
|
+
trailIndices[i] = v;
|
|
1847
|
+
trailIndices[i + 1] = v + 1;
|
|
1848
|
+
trailIndices[i + 2] = v + 2;
|
|
1849
|
+
trailIndices[i + 3] = v + 1;
|
|
1850
|
+
trailIndices[i + 4] = v + 3;
|
|
1851
|
+
trailIndices[i + 5] = v + 2;
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
trailPositionAttr = new THREE4.BufferAttribute(trailPositions, 3);
|
|
1855
|
+
trailPositionAttr.setUsage(THREE4.DynamicDrawUsage);
|
|
1856
|
+
const trailNextAttr = new THREE4.BufferAttribute(trailNextPositions, 3);
|
|
1857
|
+
trailNextAttr.setUsage(THREE4.DynamicDrawUsage);
|
|
1858
|
+
trailAlphaAttr = new THREE4.BufferAttribute(trailAlphas, 1);
|
|
1859
|
+
trailAlphaAttr.setUsage(THREE4.DynamicDrawUsage);
|
|
1860
|
+
trailColorAttr = new THREE4.BufferAttribute(trailColors, 4);
|
|
1861
|
+
trailColorAttr.setUsage(THREE4.DynamicDrawUsage);
|
|
1862
|
+
const trailHalfWidthAttr = new THREE4.BufferAttribute(trailHalfWidths, 1);
|
|
1863
|
+
trailHalfWidthAttr.setUsage(THREE4.DynamicDrawUsage);
|
|
1864
|
+
const trailUVAttr = new THREE4.BufferAttribute(trailUVs, 2);
|
|
1865
|
+
trailUVAttr.setUsage(THREE4.DynamicDrawUsage);
|
|
1866
|
+
trailIndexAttr = new THREE4.BufferAttribute(trailIndices, 1);
|
|
1867
|
+
trailGeometry.setAttribute("position", trailPositionAttr);
|
|
1868
|
+
trailGeometry.setAttribute("trailNext", trailNextAttr);
|
|
1869
|
+
trailGeometry.setAttribute("trailAlpha", trailAlphaAttr);
|
|
1870
|
+
trailGeometry.setAttribute("trailColor", trailColorAttr);
|
|
1871
|
+
trailGeometry.setAttribute(
|
|
1872
|
+
"trailOffset",
|
|
1873
|
+
new THREE4.BufferAttribute(trailOffsets, 1)
|
|
1874
|
+
);
|
|
1875
|
+
trailGeometry.setAttribute("trailHalfWidth", trailHalfWidthAttr);
|
|
1876
|
+
trailGeometry.setAttribute("trailUV", trailUVAttr);
|
|
1877
|
+
trailGeometry.setIndex(trailIndexAttr);
|
|
1878
|
+
const trailMaterial = new THREE4.ShaderMaterial({
|
|
1879
|
+
uniforms: {
|
|
1880
|
+
map: { value: particleMap },
|
|
1881
|
+
useMap: { value: !!particleMap },
|
|
1882
|
+
discardBackgroundColor: { value: renderer.discardBackgroundColor },
|
|
1883
|
+
backgroundColor: { value: renderer.backgroundColor },
|
|
1884
|
+
backgroundColorTolerance: { value: renderer.backgroundColorTolerance }
|
|
1885
|
+
},
|
|
1886
|
+
vertexShader: trail_vertex_shader_glsl_default,
|
|
1887
|
+
fragmentShader: trail_fragment_shader_glsl_default,
|
|
1888
|
+
transparent: renderer.transparent,
|
|
1889
|
+
blending: renderer.blending,
|
|
1890
|
+
depthTest: renderer.depthTest,
|
|
1891
|
+
depthWrite: renderer.depthWrite,
|
|
1892
|
+
side: THREE4.DoubleSide
|
|
1893
|
+
});
|
|
1894
|
+
trailMesh = new THREE4.Mesh(trailGeometry, trailMaterial);
|
|
1895
|
+
trailMesh.frustumCulled = false;
|
|
1896
|
+
const trailCameraPos = new THREE4.Vector3();
|
|
1897
|
+
trailMesh.onBeforeRender = (_renderer, _scene, camera) => {
|
|
1898
|
+
camera.getWorldPosition(trailCameraPos);
|
|
1899
|
+
};
|
|
1900
|
+
generalData.trailCameraPosition = trailCameraPos;
|
|
1901
|
+
trailWidthCurveFn = getCurveFunctionFromConfig(
|
|
1902
|
+
generalData.particleSystemId,
|
|
1903
|
+
trailConfig.widthOverTrail
|
|
1904
|
+
);
|
|
1905
|
+
trailOpacityCurveFn = getCurveFunctionFromConfig(
|
|
1906
|
+
generalData.particleSystemId,
|
|
1907
|
+
trailConfig.opacityOverTrail
|
|
1908
|
+
);
|
|
1909
|
+
if (trailConfig.colorOverTrail?.isActive) {
|
|
1910
|
+
trailColorOverTrailFns = {
|
|
1911
|
+
r: getCurveFunctionFromConfig(
|
|
1912
|
+
generalData.particleSystemId,
|
|
1913
|
+
normalizeTrailCurve(trailConfig.colorOverTrail.r, defaultTrailCurve)
|
|
1914
|
+
),
|
|
1915
|
+
g: getCurveFunctionFromConfig(
|
|
1916
|
+
generalData.particleSystemId,
|
|
1917
|
+
normalizeTrailCurve(trailConfig.colorOverTrail.g, defaultTrailCurve)
|
|
1918
|
+
),
|
|
1919
|
+
b: getCurveFunctionFromConfig(
|
|
1920
|
+
generalData.particleSystemId,
|
|
1921
|
+
normalizeTrailCurve(trailConfig.colorOverTrail.b, defaultTrailCurve)
|
|
1922
|
+
)
|
|
1923
|
+
};
|
|
1924
|
+
}
|
|
1925
|
+
}
|
|
1648
1926
|
let particleSystem = useInstancing ? new THREE4.Mesh(geometry, material) : new THREE4.Points(geometry, material);
|
|
1649
1927
|
if (useInstancing) {
|
|
1650
1928
|
particleSystem.onBeforeRender = (glRenderer) => {
|
|
@@ -1652,6 +1930,10 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1652
1930
|
sharedUniforms.viewportHeight.value = size.y * glRenderer.getPixelRatio();
|
|
1653
1931
|
};
|
|
1654
1932
|
}
|
|
1933
|
+
if (useTrail && trailMesh) {
|
|
1934
|
+
material.visible = false;
|
|
1935
|
+
particleSystem.add(trailMesh);
|
|
1936
|
+
}
|
|
1655
1937
|
particleSystem.position.copy(transform.position);
|
|
1656
1938
|
particleSystem.rotation.x = THREE4.MathUtils.degToRad(transform.rotation.x);
|
|
1657
1939
|
particleSystem.rotation.y = THREE4.MathUtils.degToRad(transform.rotation.y);
|
|
@@ -1729,7 +2011,20 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1729
2011
|
deactivateParticle,
|
|
1730
2012
|
activateParticle,
|
|
1731
2013
|
onParticleDeath,
|
|
1732
|
-
onParticleBirth
|
|
2014
|
+
onParticleBirth,
|
|
2015
|
+
...useTrail ? {
|
|
2016
|
+
trailMesh,
|
|
2017
|
+
trailPositionAttr,
|
|
2018
|
+
trailAlphaAttr,
|
|
2019
|
+
trailColorAttr,
|
|
2020
|
+
trailWidthCurveFn,
|
|
2021
|
+
trailOpacityCurveFn,
|
|
2022
|
+
trailColorOverTrailFns,
|
|
2023
|
+
trailConfig: {
|
|
2024
|
+
length: trailConfig.length,
|
|
2025
|
+
width: trailConfig.width
|
|
2026
|
+
}
|
|
2027
|
+
} : {}
|
|
1733
2028
|
};
|
|
1734
2029
|
createdParticleSystems.push(instanceData);
|
|
1735
2030
|
const resumeEmitter = () => generalData.isEnabled = true;
|
|
@@ -1988,6 +2283,207 @@ var updateParticleSystemInstance = (props, { now, delta, elapsed }) => {
|
|
|
1988
2283
|
onComplete({
|
|
1989
2284
|
particleSystem
|
|
1990
2285
|
});
|
|
2286
|
+
if (props.trailMesh) {
|
|
2287
|
+
updateTrailGeometry(props);
|
|
2288
|
+
}
|
|
2289
|
+
};
|
|
2290
|
+
var updateTrailGeometry = (props) => {
|
|
2291
|
+
const {
|
|
2292
|
+
generalData,
|
|
2293
|
+
trailPositionAttr,
|
|
2294
|
+
trailAlphaAttr,
|
|
2295
|
+
trailColorAttr,
|
|
2296
|
+
trailWidthCurveFn,
|
|
2297
|
+
trailOpacityCurveFn,
|
|
2298
|
+
trailColorOverTrailFns,
|
|
2299
|
+
trailConfig,
|
|
2300
|
+
mappedAttributes: ma
|
|
2301
|
+
} = props;
|
|
2302
|
+
if (!trailPositionAttr || !trailAlphaAttr || !trailColorAttr || !trailWidthCurveFn || !trailOpacityCurveFn || !trailConfig || !generalData.positionHistory || !generalData.positionHistoryIndex || !generalData.positionHistoryCount)
|
|
2303
|
+
return;
|
|
2304
|
+
const trailLength = trailConfig.length;
|
|
2305
|
+
const positionHistory = generalData.positionHistory;
|
|
2306
|
+
const historyIndex = generalData.positionHistoryIndex;
|
|
2307
|
+
const historyCount = generalData.positionHistoryCount;
|
|
2308
|
+
const isActiveArr = ma.isActive.array;
|
|
2309
|
+
const positionArr = ma.position.array;
|
|
2310
|
+
const colorRArr = ma.colorR.array;
|
|
2311
|
+
const colorGArr = ma.colorG.array;
|
|
2312
|
+
const colorBArr = ma.colorB.array;
|
|
2313
|
+
const colorAArr = ma.colorA.array;
|
|
2314
|
+
ma.size.array;
|
|
2315
|
+
const trailPosArr = trailPositionAttr.array;
|
|
2316
|
+
const trailAlphaArr = trailAlphaAttr.array;
|
|
2317
|
+
const trailColorArr = trailColorAttr.array;
|
|
2318
|
+
const trailMesh = props.trailMesh;
|
|
2319
|
+
const trailNextArr = trailMesh.geometry.getAttribute("trailNext").array;
|
|
2320
|
+
const trailUVArr = trailMesh.geometry.getAttribute("trailUV").array;
|
|
2321
|
+
const trailHalfWidthArr = trailMesh.geometry.getAttribute("trailHalfWidth").array;
|
|
2322
|
+
const verticesPerParticle = trailLength * 2;
|
|
2323
|
+
const creationTimesLength = generalData.creationTimes.length;
|
|
2324
|
+
let hasUpdates = false;
|
|
2325
|
+
for (let index = 0; index < creationTimesLength; index++) {
|
|
2326
|
+
const vertBase = index * verticesPerParticle;
|
|
2327
|
+
if (isActiveArr[index]) {
|
|
2328
|
+
hasUpdates = true;
|
|
2329
|
+
const posIdx = index * 3;
|
|
2330
|
+
const px = positionArr[posIdx];
|
|
2331
|
+
const py = positionArr[posIdx + 1];
|
|
2332
|
+
const pz = positionArr[posIdx + 2];
|
|
2333
|
+
const histBase = (index * trailLength + historyIndex[index]) * 3;
|
|
2334
|
+
positionHistory[histBase] = px;
|
|
2335
|
+
positionHistory[histBase + 1] = py;
|
|
2336
|
+
positionHistory[histBase + 2] = pz;
|
|
2337
|
+
historyIndex[index] = (historyIndex[index] + 1) % trailLength;
|
|
2338
|
+
if (historyCount[index] < trailLength) historyCount[index]++;
|
|
2339
|
+
const count = historyCount[index];
|
|
2340
|
+
const ribbonWidth = trailConfig.width;
|
|
2341
|
+
const cr = colorRArr[index];
|
|
2342
|
+
const cg = colorGArr[index];
|
|
2343
|
+
const cb = colorBArr[index];
|
|
2344
|
+
const ca = colorAArr[index];
|
|
2345
|
+
const ringOff = index * trailLength * 3;
|
|
2346
|
+
for (let s = 0; s < trailLength; s++) {
|
|
2347
|
+
const vIdx = (vertBase + s * 2) * 3;
|
|
2348
|
+
const cIdx = (vertBase + s * 2) * 4;
|
|
2349
|
+
const aIdx = vertBase + s * 2;
|
|
2350
|
+
if (s >= count) {
|
|
2351
|
+
trailPosArr[vIdx] = px;
|
|
2352
|
+
trailPosArr[vIdx + 1] = py;
|
|
2353
|
+
trailPosArr[vIdx + 2] = pz;
|
|
2354
|
+
trailPosArr[vIdx + 3] = px;
|
|
2355
|
+
trailPosArr[vIdx + 4] = py;
|
|
2356
|
+
trailPosArr[vIdx + 5] = pz;
|
|
2357
|
+
trailNextArr[vIdx] = px;
|
|
2358
|
+
trailNextArr[vIdx + 1] = py;
|
|
2359
|
+
trailNextArr[vIdx + 2] = pz;
|
|
2360
|
+
trailNextArr[vIdx + 3] = px;
|
|
2361
|
+
trailNextArr[vIdx + 4] = py;
|
|
2362
|
+
trailNextArr[vIdx + 5] = pz;
|
|
2363
|
+
trailHalfWidthArr[aIdx] = 0;
|
|
2364
|
+
trailHalfWidthArr[aIdx + 1] = 0;
|
|
2365
|
+
const uvIdx2 = (vertBase + s * 2) * 2;
|
|
2366
|
+
trailUVArr[uvIdx2] = 0;
|
|
2367
|
+
trailUVArr[uvIdx2 + 1] = 0;
|
|
2368
|
+
trailUVArr[uvIdx2 + 2] = 0;
|
|
2369
|
+
trailUVArr[uvIdx2 + 3] = 0;
|
|
2370
|
+
trailAlphaArr[aIdx] = 0;
|
|
2371
|
+
trailAlphaArr[aIdx + 1] = 0;
|
|
2372
|
+
trailColorArr[cIdx] = 0;
|
|
2373
|
+
trailColorArr[cIdx + 1] = 0;
|
|
2374
|
+
trailColorArr[cIdx + 2] = 0;
|
|
2375
|
+
trailColorArr[cIdx + 3] = 0;
|
|
2376
|
+
trailColorArr[cIdx + 4] = 0;
|
|
2377
|
+
trailColorArr[cIdx + 5] = 0;
|
|
2378
|
+
trailColorArr[cIdx + 6] = 0;
|
|
2379
|
+
trailColorArr[cIdx + 7] = 0;
|
|
2380
|
+
continue;
|
|
2381
|
+
}
|
|
2382
|
+
const histIdx = (historyIndex[index] - 1 - s + trailLength * 2) % trailLength * 3 + ringOff;
|
|
2383
|
+
const hx = positionHistory[histIdx];
|
|
2384
|
+
const hy = positionHistory[histIdx + 1];
|
|
2385
|
+
const hz = positionHistory[histIdx + 2];
|
|
2386
|
+
let nx, ny, nz;
|
|
2387
|
+
if (s < count - 1) {
|
|
2388
|
+
const ni = (historyIndex[index] - 2 - s + trailLength * 2) % trailLength * 3 + ringOff;
|
|
2389
|
+
nx = positionHistory[ni];
|
|
2390
|
+
ny = positionHistory[ni + 1];
|
|
2391
|
+
nz = positionHistory[ni + 2];
|
|
2392
|
+
} else {
|
|
2393
|
+
nx = hx;
|
|
2394
|
+
ny = hy + 1e-3;
|
|
2395
|
+
nz = hz;
|
|
2396
|
+
}
|
|
2397
|
+
const t = count > 1 ? s / (count - 1) : 0;
|
|
2398
|
+
const widthScale = trailWidthCurveFn(t);
|
|
2399
|
+
const opacityScale = trailOpacityCurveFn(t);
|
|
2400
|
+
const halfWidth = ribbonWidth * widthScale * 0.5;
|
|
2401
|
+
trailPosArr[vIdx] = hx;
|
|
2402
|
+
trailPosArr[vIdx + 1] = hy;
|
|
2403
|
+
trailPosArr[vIdx + 2] = hz;
|
|
2404
|
+
trailPosArr[vIdx + 3] = hx;
|
|
2405
|
+
trailPosArr[vIdx + 4] = hy;
|
|
2406
|
+
trailPosArr[vIdx + 5] = hz;
|
|
2407
|
+
trailNextArr[vIdx] = nx;
|
|
2408
|
+
trailNextArr[vIdx + 1] = ny;
|
|
2409
|
+
trailNextArr[vIdx + 2] = nz;
|
|
2410
|
+
trailNextArr[vIdx + 3] = nx;
|
|
2411
|
+
trailNextArr[vIdx + 4] = ny;
|
|
2412
|
+
trailNextArr[vIdx + 5] = nz;
|
|
2413
|
+
trailHalfWidthArr[aIdx] = halfWidth;
|
|
2414
|
+
trailHalfWidthArr[aIdx + 1] = halfWidth;
|
|
2415
|
+
const uvIdx = (vertBase + s * 2) * 2;
|
|
2416
|
+
trailUVArr[uvIdx] = 0;
|
|
2417
|
+
trailUVArr[uvIdx + 1] = t;
|
|
2418
|
+
trailUVArr[uvIdx + 2] = 1;
|
|
2419
|
+
trailUVArr[uvIdx + 3] = t;
|
|
2420
|
+
const alpha = ca * opacityScale;
|
|
2421
|
+
trailAlphaArr[aIdx] = alpha;
|
|
2422
|
+
trailAlphaArr[aIdx + 1] = alpha;
|
|
2423
|
+
const fr = trailColorOverTrailFns ? cr * trailColorOverTrailFns.r(t) : cr;
|
|
2424
|
+
const fg = trailColorOverTrailFns ? cg * trailColorOverTrailFns.g(t) : cg;
|
|
2425
|
+
const fb = trailColorOverTrailFns ? cb * trailColorOverTrailFns.b(t) : cb;
|
|
2426
|
+
trailColorArr[cIdx] = fr;
|
|
2427
|
+
trailColorArr[cIdx + 1] = fg;
|
|
2428
|
+
trailColorArr[cIdx + 2] = fb;
|
|
2429
|
+
trailColorArr[cIdx + 3] = ca;
|
|
2430
|
+
trailColorArr[cIdx + 4] = fr;
|
|
2431
|
+
trailColorArr[cIdx + 5] = fg;
|
|
2432
|
+
trailColorArr[cIdx + 6] = fb;
|
|
2433
|
+
trailColorArr[cIdx + 7] = ca;
|
|
2434
|
+
}
|
|
2435
|
+
} else if (historyCount[index] > 0) {
|
|
2436
|
+
hasUpdates = true;
|
|
2437
|
+
historyCount[index] = 0;
|
|
2438
|
+
historyIndex[index] = 0;
|
|
2439
|
+
for (let s = 0; s < trailLength; s++) {
|
|
2440
|
+
const vIdx = (vertBase + s * 2) * 3;
|
|
2441
|
+
const cIdx = (vertBase + s * 2) * 4;
|
|
2442
|
+
const aIdx = vertBase + s * 2;
|
|
2443
|
+
trailPosArr[vIdx] = 0;
|
|
2444
|
+
trailPosArr[vIdx + 1] = 0;
|
|
2445
|
+
trailPosArr[vIdx + 2] = 0;
|
|
2446
|
+
trailPosArr[vIdx + 3] = 0;
|
|
2447
|
+
trailPosArr[vIdx + 4] = 0;
|
|
2448
|
+
trailPosArr[vIdx + 5] = 0;
|
|
2449
|
+
trailNextArr[vIdx] = 0;
|
|
2450
|
+
trailNextArr[vIdx + 1] = 0;
|
|
2451
|
+
trailNextArr[vIdx + 2] = 0;
|
|
2452
|
+
trailNextArr[vIdx + 3] = 0;
|
|
2453
|
+
trailNextArr[vIdx + 4] = 0;
|
|
2454
|
+
trailNextArr[vIdx + 5] = 0;
|
|
2455
|
+
trailHalfWidthArr[aIdx] = 0;
|
|
2456
|
+
trailHalfWidthArr[aIdx + 1] = 0;
|
|
2457
|
+
trailAlphaArr[aIdx] = 0;
|
|
2458
|
+
trailAlphaArr[aIdx + 1] = 0;
|
|
2459
|
+
trailColorArr[cIdx] = 0;
|
|
2460
|
+
trailColorArr[cIdx + 1] = 0;
|
|
2461
|
+
trailColorArr[cIdx + 2] = 0;
|
|
2462
|
+
trailColorArr[cIdx + 3] = 0;
|
|
2463
|
+
trailColorArr[cIdx + 4] = 0;
|
|
2464
|
+
trailColorArr[cIdx + 5] = 0;
|
|
2465
|
+
trailColorArr[cIdx + 6] = 0;
|
|
2466
|
+
trailColorArr[cIdx + 7] = 0;
|
|
2467
|
+
}
|
|
2468
|
+
}
|
|
2469
|
+
}
|
|
2470
|
+
if (hasUpdates) {
|
|
2471
|
+
trailPositionAttr.needsUpdate = true;
|
|
2472
|
+
trailAlphaAttr.needsUpdate = true;
|
|
2473
|
+
trailColorAttr.needsUpdate = true;
|
|
2474
|
+
const nextAttr = trailMesh.geometry.getAttribute(
|
|
2475
|
+
"trailNext"
|
|
2476
|
+
);
|
|
2477
|
+
const hwAttr = trailMesh.geometry.getAttribute(
|
|
2478
|
+
"trailHalfWidth"
|
|
2479
|
+
);
|
|
2480
|
+
nextAttr.needsUpdate = true;
|
|
2481
|
+
hwAttr.needsUpdate = true;
|
|
2482
|
+
const uvAttr = trailMesh.geometry.getAttribute(
|
|
2483
|
+
"trailUV"
|
|
2484
|
+
);
|
|
2485
|
+
uvAttr.needsUpdate = true;
|
|
2486
|
+
}
|
|
1991
2487
|
};
|
|
1992
2488
|
var updateParticleSystems = (cycleData) => {
|
|
1993
2489
|
createdParticleSystems.forEach(
|