@newkrok/three-particles 2.16.0 → 3.0.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 +20 -0
- package/dist/index.d.ts +58 -6
- package/dist/index.js +187 -84
- 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/dist/webgpu.js +261 -255
- package/dist/webgpu.js.map +1 -1
- package/llms-full.txt +16 -1
- package/llms.txt +3 -1
- package/package.json +1 -1
package/dist/webgpu.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { registerTSLMaterialFactory } from '@newkrok/three-particles';
|
|
2
|
-
import { Fn, mod, float, floor, dot, vec3, step, min, max, vec4, vec2, abs, round, If, texture, screenUV, smoothstep,
|
|
2
|
+
import { Fn, mod, float, floor, dot, vec3, step, min, max, vec4, vec2, abs, round, If, texture, screenUV, smoothstep, cross, attribute, modelViewMatrix, positionLocal, length, varyingProperty, pointUV, cos, sin, Discard, normalLocal, cameraProjectionMatrix, uv, uniform, normalize, cameraPosition, cameraViewMatrix, mix, storage, instanceIndex, compute, fract, Loop, Continue } from 'three/tsl';
|
|
3
3
|
import * as THREE from 'three';
|
|
4
|
-
import { DoubleSide, Vector3,
|
|
4
|
+
import { DoubleSide, Vector3, DataTexture } from 'three';
|
|
5
5
|
import { PointsNodeMaterial, MeshBasicNodeMaterial, StorageBufferAttribute, StorageInstancedBufferAttribute } from 'three/webgpu';
|
|
6
6
|
|
|
7
7
|
// src/webgpu.ts
|
|
@@ -76,15 +76,13 @@ function createCollisionPlaneTSL(sCurveData, collisionPlaneOffset, collisionPlan
|
|
|
76
76
|
If(signedDist.lessThan(0), () => {
|
|
77
77
|
If(mode.lessThan(0.5), () => {
|
|
78
78
|
ps.x.assign(startLife.add(float(1)));
|
|
79
|
-
})
|
|
80
|
-
If(mode.greaterThanEqual(0.5).and(mode.lessThan(1.5)), () => {
|
|
79
|
+
}).ElseIf(mode.lessThan(1.5), () => {
|
|
81
80
|
pos.assign(pos.sub(planeNormal.mul(signedDist)));
|
|
82
81
|
const velDotN = dot(vel, planeNormal);
|
|
83
82
|
If(velDotN.lessThan(0), () => {
|
|
84
83
|
vel.assign(vel.sub(planeNormal.mul(velDotN)));
|
|
85
84
|
});
|
|
86
|
-
})
|
|
87
|
-
If(mode.greaterThanEqual(1.5), () => {
|
|
85
|
+
}).Else(() => {
|
|
88
86
|
pos.assign(pos.sub(planeNormal.mul(signedDist)));
|
|
89
87
|
const vDotN = dot(vel, planeNormal);
|
|
90
88
|
const reflected = vel.sub(planeNormal.mul(vDotN.mul(2)));
|
|
@@ -658,11 +656,19 @@ function flushEmitQueue(buffers) {
|
|
|
658
656
|
const flagOffset = curveLen + p * INIT_STRIDE + 3;
|
|
659
657
|
if (arr[flagOffset] > 0.5) {
|
|
660
658
|
arr[flagOffset] = 0;
|
|
659
|
+
buffers.curveData.addUpdateRange(flagOffset, 1);
|
|
661
660
|
clearedAny = true;
|
|
662
661
|
}
|
|
663
662
|
}
|
|
664
663
|
}
|
|
665
664
|
}
|
|
665
|
+
if (current && current.length > 0) {
|
|
666
|
+
for (let i = 0; i < current.length; i++) {
|
|
667
|
+
const p = current[i];
|
|
668
|
+
const slotStart = curveLen + p * INIT_STRIDE;
|
|
669
|
+
buffers.curveData.addUpdateRange(slotStart, INIT_STRIDE);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
666
672
|
if (count > 0 || clearedAny) {
|
|
667
673
|
buffers.curveData.needsUpdate = true;
|
|
668
674
|
}
|
|
@@ -685,7 +691,21 @@ function flushEmitQueue(buffers) {
|
|
|
685
691
|
_emitCounts.set(buffers.curveData, 0);
|
|
686
692
|
return count;
|
|
687
693
|
}
|
|
688
|
-
function deactivateParticleInModifierBuffers(
|
|
694
|
+
function deactivateParticleInModifierBuffers(buffers, index) {
|
|
695
|
+
const oiaArr = buffers.orbitalIsActive.array;
|
|
696
|
+
const oiaWOffset = index * 4 + 3;
|
|
697
|
+
if (oiaArr[oiaWOffset] !== 0) {
|
|
698
|
+
oiaArr[oiaWOffset] = 0;
|
|
699
|
+
buffers.orbitalIsActive.addUpdateRange(oiaWOffset, 1);
|
|
700
|
+
buffers.orbitalIsActive.needsUpdate = true;
|
|
701
|
+
}
|
|
702
|
+
const colorArr = buffers.color.array;
|
|
703
|
+
const colorAOffset = index * 4 + 3;
|
|
704
|
+
if (colorArr[colorAOffset] !== 0) {
|
|
705
|
+
colorArr[colorAOffset] = 0;
|
|
706
|
+
buffers.color.addUpdateRange(colorAOffset, 1);
|
|
707
|
+
buffers.color.needsUpdate = true;
|
|
708
|
+
}
|
|
689
709
|
}
|
|
690
710
|
function createCurveLookup(sCurveData) {
|
|
691
711
|
return Fn(
|
|
@@ -710,8 +730,6 @@ function createModifierComputeUpdate(buffers, maxParticles, curveMap, flags, for
|
|
|
710
730
|
const uDelta = uniform(float(0));
|
|
711
731
|
const uDeltaMs = uniform(float(0));
|
|
712
732
|
const uGravityVelocity = uniform(new Vector3(0, 0, 0));
|
|
713
|
-
const uWorldPositionChange = uniform(new Vector3(0, 0, 0));
|
|
714
|
-
const uSimSpaceWorld = uniform(float(0));
|
|
715
733
|
const uNoiseStrength = uniform(float(0));
|
|
716
734
|
const uNoisePower = uniform(float(0));
|
|
717
735
|
const uNoiseFrequency = uniform(float(1));
|
|
@@ -747,228 +765,229 @@ function createModifierComputeUpdate(buffers, maxParticles, curveMap, flags, for
|
|
|
747
765
|
) : null;
|
|
748
766
|
const computeKernel = Fn(() => {
|
|
749
767
|
const i = instanceIndex;
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
const oiaVec = sOrbitalIsActive.element(i).toVar();
|
|
812
|
-
If(oiaVec.w.greaterThanEqual(float(0.5)), () => {
|
|
813
|
-
const pos = sPosition.element(i).xyz.toVar();
|
|
814
|
-
const vel = sVelocity.element(i).xyz.toVar();
|
|
815
|
-
const ps = sParticleState.element(i).toVar();
|
|
816
|
-
const sv = sStartValues.element(i);
|
|
817
|
-
ps.x;
|
|
818
|
-
const startLife = sv.x;
|
|
819
|
-
vel.assign(vel.sub(vec3(uGravityVelocity).mul(uDelta)));
|
|
820
|
-
if (forceFieldNodes) {
|
|
821
|
-
forceFieldNodes.apply({ pos, vel, delta: uDelta });
|
|
822
|
-
}
|
|
823
|
-
If(uSimSpaceWorld.greaterThan(0.5), () => {
|
|
824
|
-
pos.assign(pos.sub(vec3(uWorldPositionChange)));
|
|
768
|
+
If(i.lessThan(float(maxParticles)), () => {
|
|
769
|
+
const initBase = i.mul(INIT_STRIDE).add(curveLen);
|
|
770
|
+
const initFlag = sCurveData.element(initBase.add(3));
|
|
771
|
+
If(initFlag.greaterThan(0.5), () => {
|
|
772
|
+
sPosition.element(i).assign(
|
|
773
|
+
vec4(
|
|
774
|
+
sCurveData.element(initBase),
|
|
775
|
+
sCurveData.element(initBase.add(1)),
|
|
776
|
+
sCurveData.element(initBase.add(2)),
|
|
777
|
+
0
|
|
778
|
+
)
|
|
779
|
+
);
|
|
780
|
+
sVelocity.element(i).assign(
|
|
781
|
+
vec4(
|
|
782
|
+
sCurveData.element(initBase.add(4)),
|
|
783
|
+
sCurveData.element(initBase.add(5)),
|
|
784
|
+
sCurveData.element(initBase.add(6)),
|
|
785
|
+
0
|
|
786
|
+
)
|
|
787
|
+
);
|
|
788
|
+
sColor.element(i).assign(
|
|
789
|
+
vec4(
|
|
790
|
+
sCurveData.element(initBase.add(8)),
|
|
791
|
+
sCurveData.element(initBase.add(9)),
|
|
792
|
+
sCurveData.element(initBase.add(10)),
|
|
793
|
+
sCurveData.element(initBase.add(11))
|
|
794
|
+
)
|
|
795
|
+
);
|
|
796
|
+
sParticleState.element(i).assign(
|
|
797
|
+
vec4(
|
|
798
|
+
sCurveData.element(initBase.add(12)),
|
|
799
|
+
sCurveData.element(initBase.add(13)),
|
|
800
|
+
sCurveData.element(initBase.add(14)),
|
|
801
|
+
sCurveData.element(initBase.add(15))
|
|
802
|
+
)
|
|
803
|
+
);
|
|
804
|
+
sOrbitalIsActive.element(i).assign(
|
|
805
|
+
vec4(
|
|
806
|
+
sCurveData.element(initBase.add(16)),
|
|
807
|
+
sCurveData.element(initBase.add(17)),
|
|
808
|
+
sCurveData.element(initBase.add(18)),
|
|
809
|
+
sCurveData.element(initBase.add(19))
|
|
810
|
+
)
|
|
811
|
+
);
|
|
812
|
+
sStartValues.element(i).assign(
|
|
813
|
+
vec4(
|
|
814
|
+
sCurveData.element(initBase.add(20)),
|
|
815
|
+
sCurveData.element(initBase.add(21)),
|
|
816
|
+
sCurveData.element(initBase.add(22)),
|
|
817
|
+
sCurveData.element(initBase.add(23))
|
|
818
|
+
)
|
|
819
|
+
);
|
|
820
|
+
sStartColorsExt.element(i).assign(
|
|
821
|
+
vec4(
|
|
822
|
+
sCurveData.element(initBase.add(24)),
|
|
823
|
+
sCurveData.element(initBase.add(25)),
|
|
824
|
+
sCurveData.element(initBase.add(26)),
|
|
825
|
+
sCurveData.element(initBase.add(27))
|
|
826
|
+
)
|
|
827
|
+
);
|
|
828
|
+
sCurveData.element(initBase.add(3)).assign(float(0));
|
|
825
829
|
});
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
}) : float(0);
|
|
850
|
-
const lvz = curveMap.linearVelZ >= 0 ? lookupCurve({
|
|
851
|
-
curveIndex: float(curveMap.linearVelZ),
|
|
852
|
-
t: lifePct
|
|
853
|
-
}) : float(0);
|
|
854
|
-
pos.assign(pos.add(vec3(lvx, lvy, lvz).mul(uDelta)));
|
|
855
|
-
}
|
|
856
|
-
if (flags.orbitalVelocity) {
|
|
857
|
-
const offset = vec3(oiaVec.x, oiaVec.y, oiaVec.z).toVar();
|
|
858
|
-
pos.assign(pos.sub(offset));
|
|
859
|
-
const ovx = curveMap.orbitalVelX >= 0 ? lookupCurve({
|
|
860
|
-
curveIndex: float(curveMap.orbitalVelX),
|
|
861
|
-
t: lifePct
|
|
862
|
-
}) : float(0);
|
|
863
|
-
const ovy = curveMap.orbitalVelY >= 0 ? lookupCurve({
|
|
864
|
-
curveIndex: float(curveMap.orbitalVelY),
|
|
865
|
-
t: lifePct
|
|
866
|
-
}) : float(0);
|
|
867
|
-
const ovz = curveMap.orbitalVelZ >= 0 ? lookupCurve({
|
|
868
|
-
curveIndex: float(curveMap.orbitalVelZ),
|
|
869
|
-
t: lifePct
|
|
870
|
-
}) : float(0);
|
|
871
|
-
const ax = ovx.mul(uDelta);
|
|
872
|
-
const ay = ovz.mul(uDelta);
|
|
873
|
-
const az = ovy.mul(uDelta);
|
|
874
|
-
const cosAz = cos(az);
|
|
875
|
-
const sinAz = sin(az);
|
|
876
|
-
const zx = offset.x.mul(cosAz).sub(offset.y.mul(sinAz));
|
|
877
|
-
const zy = offset.x.mul(sinAz).add(offset.y.mul(cosAz));
|
|
878
|
-
const zz = offset.z;
|
|
879
|
-
const cosAy = cos(ay);
|
|
880
|
-
const sinAy = sin(ay);
|
|
881
|
-
const yx = zx.mul(cosAy).add(zz.mul(sinAy));
|
|
882
|
-
const yy = zy;
|
|
883
|
-
const yz = zx.negate().mul(sinAy).add(zz.mul(cosAy));
|
|
884
|
-
const cosAx = cos(ax);
|
|
885
|
-
const sinAx = sin(ax);
|
|
886
|
-
const fx = yx;
|
|
887
|
-
const fy = yy.mul(cosAx).sub(yz.mul(sinAx));
|
|
888
|
-
const fz = yy.mul(sinAx).add(yz.mul(cosAx));
|
|
889
|
-
offset.assign(vec3(fx, fy, fz));
|
|
890
|
-
oiaVec.x.assign(offset.x);
|
|
891
|
-
oiaVec.y.assign(offset.y);
|
|
892
|
-
oiaVec.z.assign(offset.z);
|
|
893
|
-
pos.assign(pos.add(offset));
|
|
894
|
-
}
|
|
895
|
-
if (flags.sizeOverLifetime && curveMap.sizeOverLifetime >= 0) {
|
|
896
|
-
const multiplier = lookupCurve({
|
|
897
|
-
curveIndex: float(curveMap.sizeOverLifetime),
|
|
898
|
-
t: lifePct
|
|
899
|
-
});
|
|
900
|
-
ps.y.assign(sv.y.mul(multiplier));
|
|
901
|
-
}
|
|
902
|
-
if (flags.opacityOverLifetime && curveMap.opacityOverLifetime >= 0) {
|
|
903
|
-
const multiplier = lookupCurve({
|
|
904
|
-
curveIndex: float(curveMap.opacityOverLifetime),
|
|
905
|
-
t: lifePct
|
|
906
|
-
});
|
|
907
|
-
const col = sColor.element(i).toVar();
|
|
908
|
-
col.w.assign(sv.z.mul(multiplier));
|
|
909
|
-
sColor.element(i).assign(col);
|
|
910
|
-
}
|
|
911
|
-
if (flags.colorOverLifetime) {
|
|
912
|
-
const col = sColor.element(i).toVar();
|
|
913
|
-
const sce = sStartColorsExt.element(i);
|
|
914
|
-
if (curveMap.colorR >= 0) {
|
|
915
|
-
const rMul = lookupCurve({
|
|
916
|
-
curveIndex: float(curveMap.colorR),
|
|
917
|
-
t: lifePct
|
|
830
|
+
const oiaVec = sOrbitalIsActive.element(i).toVar();
|
|
831
|
+
If(oiaVec.w.greaterThanEqual(float(0.5)), () => {
|
|
832
|
+
const pos = sPosition.element(i).xyz.toVar();
|
|
833
|
+
const vel = sVelocity.element(i).xyz.toVar();
|
|
834
|
+
const ps = sParticleState.element(i).toVar();
|
|
835
|
+
const sv = sStartValues.element(i);
|
|
836
|
+
ps.x;
|
|
837
|
+
const startLife = sv.x;
|
|
838
|
+
vel.assign(vel.sub(vec3(uGravityVelocity).mul(uDelta)));
|
|
839
|
+
if (forceFieldNodes) {
|
|
840
|
+
forceFieldNodes.apply({ pos, vel, delta: uDelta });
|
|
841
|
+
}
|
|
842
|
+
pos.assign(pos.add(vel.mul(uDelta)));
|
|
843
|
+
if (collisionPlaneNodes) {
|
|
844
|
+
collisionPlaneNodes.apply({
|
|
845
|
+
pos,
|
|
846
|
+
vel,
|
|
847
|
+
oiaVec,
|
|
848
|
+
sColorNode: sColor,
|
|
849
|
+
ps,
|
|
850
|
+
startLife,
|
|
851
|
+
particleIdx: i,
|
|
852
|
+
sOrbitalIsActiveNode: sOrbitalIsActive
|
|
918
853
|
});
|
|
919
|
-
col.x.assign(sv.w.mul(rMul));
|
|
920
854
|
}
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
855
|
+
const lifePct = min(ps.x.div(startLife), float(1));
|
|
856
|
+
ps.x.assign(ps.x.add(uDeltaMs));
|
|
857
|
+
if (flags.linearVelocity) {
|
|
858
|
+
const lvx = curveMap.linearVelX >= 0 ? lookupCurve({
|
|
859
|
+
curveIndex: float(curveMap.linearVelX),
|
|
860
|
+
t: lifePct
|
|
861
|
+
}) : float(0);
|
|
862
|
+
const lvy = curveMap.linearVelY >= 0 ? lookupCurve({
|
|
863
|
+
curveIndex: float(curveMap.linearVelY),
|
|
864
|
+
t: lifePct
|
|
865
|
+
}) : float(0);
|
|
866
|
+
const lvz = curveMap.linearVelZ >= 0 ? lookupCurve({
|
|
867
|
+
curveIndex: float(curveMap.linearVelZ),
|
|
868
|
+
t: lifePct
|
|
869
|
+
}) : float(0);
|
|
870
|
+
pos.assign(pos.add(vec3(lvx, lvy, lvz).mul(uDelta)));
|
|
871
|
+
}
|
|
872
|
+
if (flags.orbitalVelocity) {
|
|
873
|
+
const offset = vec3(oiaVec.x, oiaVec.y, oiaVec.z).toVar();
|
|
874
|
+
pos.assign(pos.sub(offset));
|
|
875
|
+
const ovx = curveMap.orbitalVelX >= 0 ? lookupCurve({
|
|
876
|
+
curveIndex: float(curveMap.orbitalVelX),
|
|
877
|
+
t: lifePct
|
|
878
|
+
}) : float(0);
|
|
879
|
+
const ovy = curveMap.orbitalVelY >= 0 ? lookupCurve({
|
|
880
|
+
curveIndex: float(curveMap.orbitalVelY),
|
|
881
|
+
t: lifePct
|
|
882
|
+
}) : float(0);
|
|
883
|
+
const ovz = curveMap.orbitalVelZ >= 0 ? lookupCurve({
|
|
884
|
+
curveIndex: float(curveMap.orbitalVelZ),
|
|
885
|
+
t: lifePct
|
|
886
|
+
}) : float(0);
|
|
887
|
+
const ax = ovx.mul(uDelta);
|
|
888
|
+
const ay = ovz.mul(uDelta);
|
|
889
|
+
const az = ovy.mul(uDelta);
|
|
890
|
+
const cosAz = cos(az);
|
|
891
|
+
const sinAz = sin(az);
|
|
892
|
+
const zx = offset.x.mul(cosAz).sub(offset.y.mul(sinAz));
|
|
893
|
+
const zy = offset.x.mul(sinAz).add(offset.y.mul(cosAz));
|
|
894
|
+
const zz = offset.z;
|
|
895
|
+
const cosAy = cos(ay);
|
|
896
|
+
const sinAy = sin(ay);
|
|
897
|
+
const yx = zx.mul(cosAy).add(zz.mul(sinAy));
|
|
898
|
+
const yy = zy;
|
|
899
|
+
const yz = zx.negate().mul(sinAy).add(zz.mul(cosAy));
|
|
900
|
+
const cosAx = cos(ax);
|
|
901
|
+
const sinAx = sin(ax);
|
|
902
|
+
const fx = yx;
|
|
903
|
+
const fy = yy.mul(cosAx).sub(yz.mul(sinAx));
|
|
904
|
+
const fz = yy.mul(sinAx).add(yz.mul(cosAx));
|
|
905
|
+
offset.assign(vec3(fx, fy, fz));
|
|
906
|
+
oiaVec.x.assign(offset.x);
|
|
907
|
+
oiaVec.y.assign(offset.y);
|
|
908
|
+
oiaVec.z.assign(offset.z);
|
|
909
|
+
pos.assign(pos.add(offset));
|
|
910
|
+
}
|
|
911
|
+
if (flags.sizeOverLifetime && curveMap.sizeOverLifetime >= 0) {
|
|
912
|
+
const multiplier = lookupCurve({
|
|
913
|
+
curveIndex: float(curveMap.sizeOverLifetime),
|
|
924
914
|
t: lifePct
|
|
925
915
|
});
|
|
926
|
-
|
|
916
|
+
ps.y.assign(sv.y.mul(multiplier));
|
|
927
917
|
}
|
|
928
|
-
if (curveMap.
|
|
929
|
-
const
|
|
930
|
-
curveIndex: float(curveMap.
|
|
918
|
+
if (flags.opacityOverLifetime && curveMap.opacityOverLifetime >= 0) {
|
|
919
|
+
const multiplier = lookupCurve({
|
|
920
|
+
curveIndex: float(curveMap.opacityOverLifetime),
|
|
931
921
|
t: lifePct
|
|
932
922
|
});
|
|
933
|
-
col.
|
|
923
|
+
const col = sColor.element(i).toVar();
|
|
924
|
+
col.w.assign(sv.z.mul(multiplier));
|
|
925
|
+
sColor.element(i).assign(col);
|
|
934
926
|
}
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
927
|
+
if (flags.colorOverLifetime) {
|
|
928
|
+
const col = sColor.element(i).toVar();
|
|
929
|
+
const sce = sStartColorsExt.element(i);
|
|
930
|
+
if (curveMap.colorR >= 0) {
|
|
931
|
+
const rMul = lookupCurve({
|
|
932
|
+
curveIndex: float(curveMap.colorR),
|
|
933
|
+
t: lifePct
|
|
934
|
+
});
|
|
935
|
+
col.x.assign(sv.w.mul(rMul));
|
|
936
|
+
}
|
|
937
|
+
if (curveMap.colorG >= 0) {
|
|
938
|
+
const gMul = lookupCurve({
|
|
939
|
+
curveIndex: float(curveMap.colorG),
|
|
940
|
+
t: lifePct
|
|
941
|
+
});
|
|
942
|
+
col.y.assign(sce.x.mul(gMul));
|
|
943
|
+
}
|
|
944
|
+
if (curveMap.colorB >= 0) {
|
|
945
|
+
const bMul = lookupCurve({
|
|
946
|
+
curveIndex: float(curveMap.colorB),
|
|
947
|
+
t: lifePct
|
|
948
|
+
});
|
|
949
|
+
col.z.assign(sce.y.mul(bMul));
|
|
950
|
+
}
|
|
951
|
+
sColor.element(i).assign(col);
|
|
952
|
+
}
|
|
953
|
+
if (flags.rotationOverLifetime) {
|
|
954
|
+
const sce = sStartColorsExt.element(i);
|
|
955
|
+
ps.z.assign(ps.z.add(sce.z.mul(uDelta).mul(float(0.02))));
|
|
956
|
+
}
|
|
957
|
+
if (flags.noise) {
|
|
958
|
+
const sce = sStartColorsExt.element(i);
|
|
959
|
+
const noisePos = lifePct.add(sce.w).mul(10).mul(uNoiseStrength).mul(uNoiseFrequency);
|
|
960
|
+
const noiseX = snoise3D({ v: vec3(noisePos, float(0), float(0)) });
|
|
961
|
+
const noiseY = snoise3D({
|
|
962
|
+
v: vec3(noisePos, noisePos, float(0))
|
|
963
|
+
});
|
|
964
|
+
const noiseZ = snoise3D({
|
|
965
|
+
v: vec3(noisePos, noisePos, noisePos)
|
|
966
|
+
});
|
|
967
|
+
pos.assign(
|
|
968
|
+
pos.add(
|
|
969
|
+
vec3(noiseX, noiseY, noiseZ).mul(uNoisePower).mul(uNoisePosAmount)
|
|
970
|
+
)
|
|
971
|
+
);
|
|
972
|
+
If(uNoiseRotAmount.greaterThan(1e-3), () => {
|
|
973
|
+
ps.z.assign(ps.z.add(noiseX.mul(uNoisePower).mul(uNoiseRotAmount)));
|
|
974
|
+
});
|
|
975
|
+
If(uNoiseSizeAmount.greaterThan(1e-3), () => {
|
|
976
|
+
ps.y.assign(
|
|
977
|
+
ps.y.add(noiseX.mul(uNoisePower).mul(uNoiseSizeAmount))
|
|
978
|
+
);
|
|
979
|
+
});
|
|
980
|
+
}
|
|
981
|
+
sPosition.element(i).assign(vec4(pos, 0));
|
|
982
|
+
sVelocity.element(i).assign(vec4(vel, 0));
|
|
983
|
+
sParticleState.element(i).assign(ps);
|
|
984
|
+
sOrbitalIsActive.element(i).assign(oiaVec);
|
|
985
|
+
If(ps.x.greaterThan(startLife), () => {
|
|
986
|
+
const deadOia = sOrbitalIsActive.element(i).toVar();
|
|
987
|
+
deadOia.w.assign(float(0));
|
|
988
|
+
sOrbitalIsActive.element(i).assign(deadOia);
|
|
989
|
+
sColor.element(i).assign(vec4(0));
|
|
961
990
|
});
|
|
962
|
-
}
|
|
963
|
-
sPosition.element(i).assign(vec4(pos, 0));
|
|
964
|
-
sVelocity.element(i).assign(vec4(vel, 0));
|
|
965
|
-
sParticleState.element(i).assign(ps);
|
|
966
|
-
sOrbitalIsActive.element(i).assign(oiaVec);
|
|
967
|
-
If(ps.x.greaterThan(startLife), () => {
|
|
968
|
-
const deadOia = sOrbitalIsActive.element(i).toVar();
|
|
969
|
-
deadOia.w.assign(float(0));
|
|
970
|
-
sOrbitalIsActive.element(i).assign(deadOia);
|
|
971
|
-
sColor.element(i).assign(vec4(0));
|
|
972
991
|
});
|
|
973
992
|
});
|
|
974
993
|
});
|
|
@@ -979,8 +998,6 @@ function createModifierComputeUpdate(buffers, maxParticles, curveMap, flags, for
|
|
|
979
998
|
delta: uDelta,
|
|
980
999
|
deltaMs: uDeltaMs,
|
|
981
1000
|
gravityVelocity: uGravityVelocity,
|
|
982
|
-
worldPositionChange: uWorldPositionChange,
|
|
983
|
-
simulationSpaceWorld: uSimSpaceWorld,
|
|
984
1001
|
noiseStrength: uNoiseStrength,
|
|
985
1002
|
noisePower: uNoisePower,
|
|
986
1003
|
noiseFrequency: uNoiseFrequency,
|
|
@@ -1017,7 +1034,6 @@ function getDummyTexture() {
|
|
|
1017
1034
|
function createParticleUniforms(sharedUniforms) {
|
|
1018
1035
|
const dummy = getDummyTexture();
|
|
1019
1036
|
const map = sharedUniforms.map.value ?? dummy;
|
|
1020
|
-
if (map) map.colorSpace = NoColorSpace;
|
|
1021
1037
|
return {
|
|
1022
1038
|
uMap: map,
|
|
1023
1039
|
uElapsed: uniform(float(sharedUniforms.elapsed.value)),
|
|
@@ -1104,30 +1120,21 @@ var computeSoftParticleFade = Fn(
|
|
|
1104
1120
|
return softFade;
|
|
1105
1121
|
}
|
|
1106
1122
|
);
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
});
|
|
1123
|
-
});
|
|
1124
|
-
}
|
|
1125
|
-
);
|
|
1126
|
-
var compensateOutputSRGB = Fn(
|
|
1127
|
-
({ color }) => {
|
|
1128
|
-
return vec4(sRGBTransferEOTF(color.rgb), color.a);
|
|
1129
|
-
}
|
|
1130
|
-
);
|
|
1123
|
+
function applyBackgroundDiscard({
|
|
1124
|
+
texColor,
|
|
1125
|
+
uDiscardBg,
|
|
1126
|
+
uBgColor,
|
|
1127
|
+
uBgTolerance
|
|
1128
|
+
}) {
|
|
1129
|
+
const diff = vec3(
|
|
1130
|
+
texColor.x.sub(uBgColor.x),
|
|
1131
|
+
texColor.y.sub(uBgColor.y),
|
|
1132
|
+
texColor.z.sub(uBgColor.z)
|
|
1133
|
+
);
|
|
1134
|
+
Discard(
|
|
1135
|
+
uDiscardBg.greaterThan(0.5).and(abs(length(diff)).lessThan(uBgTolerance))
|
|
1136
|
+
);
|
|
1137
|
+
}
|
|
1131
1138
|
|
|
1132
1139
|
// src/js/effects/three-particles/webgpu/tsl-instanced-billboard-material.ts
|
|
1133
1140
|
function createInstancedBillboardTSLMaterial(sharedUniforms, rendererConfig, gpuCompute = false) {
|
|
@@ -1153,7 +1160,7 @@ function createInstancedBillboardTSLMaterial(sharedUniforms, rendererConfig, gpu
|
|
|
1153
1160
|
const vUv = varyingProperty("vec2", "vUv");
|
|
1154
1161
|
const vViewZ = varyingProperty("float", "vViewZ");
|
|
1155
1162
|
const vertexNode = Fn(() => {
|
|
1156
|
-
const clipPos = vec4(0, 0, 0,
|
|
1163
|
+
const clipPos = vec4(0, 0, 0, -1).toVar();
|
|
1157
1164
|
If(aColor.w.greaterThan(0), () => {
|
|
1158
1165
|
vColor.assign(aColor.toVar());
|
|
1159
1166
|
if (gpuCompute) {
|
|
@@ -1228,7 +1235,7 @@ function createInstancedBillboardTSLMaterial(sharedUniforms, rendererConfig, gpu
|
|
|
1228
1235
|
});
|
|
1229
1236
|
outColor.assign(vec4(outColor.xyz, outColor.w.mul(softFade)));
|
|
1230
1237
|
Discard(outColor.w.lessThan(ALPHA_DISCARD_THRESHOLD));
|
|
1231
|
-
return
|
|
1238
|
+
return outColor;
|
|
1232
1239
|
})();
|
|
1233
1240
|
const material = new MeshBasicNodeMaterial();
|
|
1234
1241
|
material.transparent = rendererConfig.transparent;
|
|
@@ -1267,7 +1274,7 @@ function createMeshParticleTSLMaterial(sharedUniforms, rendererConfig, gpuComput
|
|
|
1267
1274
|
const vNormal = varyingProperty("vec3", "vNormal");
|
|
1268
1275
|
const vViewZ = varyingProperty("float", "vViewZ");
|
|
1269
1276
|
const vertexSetup = Fn(() => {
|
|
1270
|
-
const clipPos = vec4(0, 0, 0,
|
|
1277
|
+
const clipPos = vec4(0, 0, 0, -1).toVar();
|
|
1271
1278
|
If(aColor.w.greaterThan(0), () => {
|
|
1272
1279
|
vColor.assign(aColor.toVar());
|
|
1273
1280
|
if (gpuCompute) {
|
|
@@ -1347,7 +1354,7 @@ function createMeshParticleTSLMaterial(sharedUniforms, rendererConfig, gpuComput
|
|
|
1347
1354
|
});
|
|
1348
1355
|
outColor.assign(vec4(outColor.xyz, outColor.w.mul(softFade)));
|
|
1349
1356
|
Discard(outColor.w.lessThan(ALPHA_DISCARD_THRESHOLD));
|
|
1350
|
-
return
|
|
1357
|
+
return outColor;
|
|
1351
1358
|
})();
|
|
1352
1359
|
const material = new MeshBasicNodeMaterial();
|
|
1353
1360
|
material.transparent = rendererConfig.transparent;
|
|
@@ -1440,7 +1447,7 @@ function createPointSpriteTSLMaterial(sharedUniforms, rendererConfig, gpuCompute
|
|
|
1440
1447
|
});
|
|
1441
1448
|
outColor.assign(vec4(outColor.xyz, outColor.w.mul(softFade)));
|
|
1442
1449
|
Discard(outColor.w.lessThan(ALPHA_DISCARD_THRESHOLD));
|
|
1443
|
-
return
|
|
1450
|
+
return outColor;
|
|
1444
1451
|
})();
|
|
1445
1452
|
const material = new PointsNodeMaterial();
|
|
1446
1453
|
material.transparent = rendererConfig.transparent;
|
|
@@ -1457,7 +1464,6 @@ function createPointSpriteTSLMaterial(sharedUniforms, rendererConfig, gpuCompute
|
|
|
1457
1464
|
function createTrailUniforms(trailUniforms) {
|
|
1458
1465
|
const dummy = getDummyTexture();
|
|
1459
1466
|
const map = trailUniforms.map.value ?? dummy;
|
|
1460
|
-
if (map) map.colorSpace = NoColorSpace;
|
|
1461
1467
|
return {
|
|
1462
1468
|
uMap: map,
|
|
1463
1469
|
uUseMap: uniform(float(trailUniforms.useMap.value ? 1 : 0)),
|
|
@@ -1567,7 +1573,7 @@ function createTrailRibbonTSLMaterial(trailUniforms, rendererConfig) {
|
|
|
1567
1573
|
Discard(
|
|
1568
1574
|
u.uDiscardBg.greaterThan(0.5).and(abs(length(diff)).lessThan(u.uBgTolerance))
|
|
1569
1575
|
);
|
|
1570
|
-
return
|
|
1576
|
+
return outColor;
|
|
1571
1577
|
})();
|
|
1572
1578
|
const material = new MeshBasicNodeMaterial();
|
|
1573
1579
|
material.transparent = rendererConfig.transparent;
|