Skip to content

Commit 608bfed

Browse files
committed
perf(3d): P3-15 粒子系统按 tier 跳帧更新(降 sin/cos 逐粒子开销)
1 parent dd2d66d commit 608bfed

1 file changed

Lines changed: 15 additions & 4 deletions

File tree

‎client/src/lib/3d/objects/ParticleSystem.tsx‎

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
* 使用 THREE.Points + AdditiveBlending 实现高性能粒子渲染
44
*
55
* @ai-context: 3D 场景对象:ParticleSystem。
6+
* @ai-context: P3-15 降更新频率——按 tier 跳帧更新(high 每帧/medium 隔 1/low 隔 2),
7+
* 水平漂移基于绝对时钟相位(跳帧仍平滑),增量位移乘以 step 补偿以保持运动速度一致。
68
*/
79
import { useRef, useMemo } from 'react';
810
import { useFrame } from '@react-three/fiber';
@@ -25,10 +27,14 @@ export function ParticleSystem({
2527
speed = 1,
2628
}: ParticleSystemProps) {
2729
const pointsRef = useRef<THREE.Points>(null);
30+
// P3-15 跳帧计数器
31+
const frameRef = useRef(0);
2832
// 有效 tier(自动 tier 受用户性能模式上限约束)
2933
const tier = useEffectiveTier();
3034

3135
const particleCount = tier === 'low' ? 500 : tier === 'medium' ? 1200 : count;
36+
// 更新频率分档:high 每帧、medium 隔 1 帧、low 隔 2 帧(粒子运动缓慢,跳帧视觉无感)
37+
const frameSkip = tier === 'low' ? 3 : tier === 'medium' ? 2 : 1;
3238

3339
const { positions, velocities, colors, sizes } = useMemo(() => {
3440
const pos = new Float32Array(particleCount * 3);
@@ -67,19 +73,24 @@ export function ParticleSystem({
6773

6874
useFrame(({ clock }) => {
6975
if (!pointsRef.current) return;
76+
// P3-15 跳帧:非更新帧直接返回,减少 sin/cos 逐粒子计算开销
77+
frameRef.current += 1;
78+
if (frameRef.current % frameSkip !== 0) return;
79+
const step = frameSkip; // 补偿跳过帧,保持运动速度一致
80+
7081
const posAttr = pointsRef.current.geometry.attributes.position as THREE.BufferAttribute;
7182
const posArray = posAttr.array as Float32Array;
7283
const time = clock.getElapsedTime();
7384

7485
for (let i = 0; i < particleCount; i++) {
7586
const i3 = i * 3;
7687

77-
// Horizontal drift using sin/cos
78-
posArray[i3] += Math.sin(time * 0.5 + i * 0.1) * velocities[i3] * speed * 0.001;
79-
posArray[i3 + 2] += Math.cos(time * 0.4 + i * 0.1) * velocities[i3 + 2] * speed * 0.001;
88+
// Horizontal drift using sin/cos(基于绝对时钟相位,跳帧仍平滑)
89+
posArray[i3] += Math.sin(time * 0.5 + i * 0.1) * velocities[i3] * speed * 0.001 * step;
90+
posArray[i3 + 2] += Math.cos(time * 0.4 + i * 0.1) * velocities[i3 + 2] * speed * 0.001 * step;
8091

8192
// Float upward
82-
posArray[i3 + 1] += velocities[i3 + 1] * speed;
93+
posArray[i3 + 1] += velocities[i3 + 1] * speed * step;
8394

8495
// Reset particle to bottom when reaching top
8596
if (posArray[i3 + 1] > bounds.y[1]) {

0 commit comments

Comments
 (0)