@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/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, length, Discard, sRGBTransferEOTF, cross, attribute, modelViewMatrix, positionLocal, varyingProperty, pointUV, cos, sin, normalLocal, cameraProjectionMatrix, uv, uniform, normalize, cameraPosition, cameraViewMatrix, mix, storage, instanceIndex, compute, fract, Loop, Continue } from 'three/tsl';
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, NoColorSpace, DataTexture } from 'three';
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(_buffers, _index) {
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
- const initBase = i.mul(INIT_STRIDE).add(curveLen);
751
- const initFlag = sCurveData.element(initBase.add(3));
752
- If(initFlag.greaterThan(0.5), () => {
753
- sPosition.element(i).assign(
754
- vec4(
755
- sCurveData.element(initBase),
756
- sCurveData.element(initBase.add(1)),
757
- sCurveData.element(initBase.add(2)),
758
- 0
759
- )
760
- );
761
- sVelocity.element(i).assign(
762
- vec4(
763
- sCurveData.element(initBase.add(4)),
764
- sCurveData.element(initBase.add(5)),
765
- sCurveData.element(initBase.add(6)),
766
- 0
767
- )
768
- );
769
- sColor.element(i).assign(
770
- vec4(
771
- sCurveData.element(initBase.add(8)),
772
- sCurveData.element(initBase.add(9)),
773
- sCurveData.element(initBase.add(10)),
774
- sCurveData.element(initBase.add(11))
775
- )
776
- );
777
- sParticleState.element(i).assign(
778
- vec4(
779
- sCurveData.element(initBase.add(12)),
780
- sCurveData.element(initBase.add(13)),
781
- sCurveData.element(initBase.add(14)),
782
- sCurveData.element(initBase.add(15))
783
- )
784
- );
785
- sOrbitalIsActive.element(i).assign(
786
- vec4(
787
- sCurveData.element(initBase.add(16)),
788
- sCurveData.element(initBase.add(17)),
789
- sCurveData.element(initBase.add(18)),
790
- sCurveData.element(initBase.add(19))
791
- )
792
- );
793
- sStartValues.element(i).assign(
794
- vec4(
795
- sCurveData.element(initBase.add(20)),
796
- sCurveData.element(initBase.add(21)),
797
- sCurveData.element(initBase.add(22)),
798
- sCurveData.element(initBase.add(23))
799
- )
800
- );
801
- sStartColorsExt.element(i).assign(
802
- vec4(
803
- sCurveData.element(initBase.add(24)),
804
- sCurveData.element(initBase.add(25)),
805
- sCurveData.element(initBase.add(26)),
806
- sCurveData.element(initBase.add(27))
807
- )
808
- );
809
- sCurveData.element(initBase.add(3)).assign(float(0));
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
- pos.assign(pos.add(vel.mul(uDelta)));
827
- if (collisionPlaneNodes) {
828
- collisionPlaneNodes.apply({
829
- pos,
830
- vel,
831
- oiaVec,
832
- sColorNode: sColor,
833
- ps,
834
- startLife,
835
- particleIdx: i,
836
- sOrbitalIsActiveNode: sOrbitalIsActive
837
- });
838
- }
839
- const lifePct = min(ps.x.div(startLife), float(1));
840
- ps.x.assign(ps.x.add(uDeltaMs));
841
- if (flags.linearVelocity) {
842
- const lvx = curveMap.linearVelX >= 0 ? lookupCurve({
843
- curveIndex: float(curveMap.linearVelX),
844
- t: lifePct
845
- }) : float(0);
846
- const lvy = curveMap.linearVelY >= 0 ? lookupCurve({
847
- curveIndex: float(curveMap.linearVelY),
848
- t: lifePct
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
- if (curveMap.colorG >= 0) {
922
- const gMul = lookupCurve({
923
- curveIndex: float(curveMap.colorG),
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
- col.y.assign(sce.x.mul(gMul));
916
+ ps.y.assign(sv.y.mul(multiplier));
927
917
  }
928
- if (curveMap.colorB >= 0) {
929
- const bMul = lookupCurve({
930
- curveIndex: float(curveMap.colorB),
918
+ if (flags.opacityOverLifetime && curveMap.opacityOverLifetime >= 0) {
919
+ const multiplier = lookupCurve({
920
+ curveIndex: float(curveMap.opacityOverLifetime),
931
921
  t: lifePct
932
922
  });
933
- col.z.assign(sce.y.mul(bMul));
923
+ const col = sColor.element(i).toVar();
924
+ col.w.assign(sv.z.mul(multiplier));
925
+ sColor.element(i).assign(col);
934
926
  }
935
- sColor.element(i).assign(col);
936
- }
937
- if (flags.rotationOverLifetime) {
938
- const sce = sStartColorsExt.element(i);
939
- ps.z.assign(ps.z.add(sce.z.mul(uDelta).mul(float(0.02))));
940
- }
941
- if (flags.noise) {
942
- const sce = sStartColorsExt.element(i);
943
- const noisePos = lifePct.add(sce.w).mul(10).mul(uNoiseStrength).mul(uNoiseFrequency);
944
- const noiseX = snoise3D({ v: vec3(noisePos, float(0), float(0)) });
945
- const noiseY = snoise3D({
946
- v: vec3(noisePos, noisePos, float(0))
947
- });
948
- const noiseZ = snoise3D({
949
- v: vec3(noisePos, noisePos, noisePos)
950
- });
951
- pos.assign(
952
- pos.add(
953
- vec3(noiseX, noiseY, noiseZ).mul(uNoisePower).mul(uNoisePosAmount)
954
- )
955
- );
956
- If(uNoiseRotAmount.greaterThan(1e-3), () => {
957
- ps.z.assign(ps.z.add(noiseX.mul(uNoisePower).mul(uNoiseRotAmount)));
958
- });
959
- If(uNoiseSizeAmount.greaterThan(1e-3), () => {
960
- ps.y.assign(ps.y.add(noiseX.mul(uNoisePower).mul(uNoiseSizeAmount)));
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
- var applyBackgroundDiscard = Fn(
1108
- ({
1109
- texColor,
1110
- uDiscardBg,
1111
- uBgColor,
1112
- uBgTolerance
1113
- }) => {
1114
- If(uDiscardBg.greaterThan(0.5), () => {
1115
- const diff = vec3(
1116
- texColor.x.sub(uBgColor.x),
1117
- texColor.y.sub(uBgColor.y),
1118
- texColor.z.sub(uBgColor.z)
1119
- );
1120
- If(abs(length(diff)).lessThan(uBgTolerance), () => {
1121
- Discard();
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, 0).toVar();
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 compensateOutputSRGB({ color: outColor });
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, 0).toVar();
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 compensateOutputSRGB({ color: outColor });
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 compensateOutputSRGB({ color: outColor });
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 compensateOutputSRGB({ color: outColor });
1576
+ return outColor;
1571
1577
  })();
1572
1578
  const material = new MeshBasicNodeMaterial();
1573
1579
  material.transparent = rendererConfig.transparent;