Particle Systems
Points + BufferGeometry = thousands of particles with minimal overhead. Store positions in a Float32Array and update them on the CPU each frame.
Creating 5k Particles
const count = 5000;
const positions = new Float32Array(count * 3);
for (let i = 0; i < count; i++) {
positions[i * 3] = (Math.random() - 0.5) * 10;
positions[i * 3 + 1] = (Math.random() - 0.5) * 10;
positions[i * 3 + 2] = (Math.random() - 0.5) * 10;
}
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({ size: 0.02, color: 0xffffff });
const particles = new THREE.Points(geometry, material);
scene.add(particles);
Updating Positions Each Frame
const posAttr = geometry.attributes.position;
// In animate():
const t = clock.getElapsedTime();
for (let i = 0; i < count; i++) {
const ix = i * 3;
posAttr.array[ix + 1] += Math.sin(t + posAttr.array[ix] * 0.5) * 0.001;
}
posAttr.needsUpdate = true; // required after CPU mutation
What to Experiment With
- Scale
PointsMaterial.sizebydevicePixelRatiofor consistent look - Use a circular texture (white circle on transparent) for soft particles
- Add a slow
particles.rotation.y += 0.0003for global drift
Points + BufferGeometry = 최소한의 오버헤드로 수천 개의 파티클. 위치를 Float32Array에 저장하고 매 프레임 CPU에서 업데이트합니다.
파티클 5000개 생성
const count = 5000;
const positions = new Float32Array(count * 3);
for (let i = 0; i < count; i++) {
positions[i * 3] = (Math.random() - 0.5) * 10;
positions[i * 3 + 1] = (Math.random() - 0.5) * 10;
positions[i * 3 + 2] = (Math.random() - 0.5) * 10;
}
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({ size: 0.02, color: 0xffffff });
const particles = new THREE.Points(geometry, material);
scene.add(particles);
매 프레임 위치 업데이트
const posAttr = geometry.attributes.position;
// animate() 내부:
const t = clock.getElapsedTime();
for (let i = 0; i < count; i++) {
const ix = i * 3;
posAttr.array[ix + 1] += Math.sin(t + posAttr.array[ix] * 0.5) * 0.001;
}
posAttr.needsUpdate = true; // CPU 변경 후 반드시 필요
실험해보기
PointsMaterial.size를devicePixelRatio로 스케일해 일관된 모양- 원형 텍스처(투명 배경에 흰색 원)로 부드러운 파티클
particles.rotation.y += 0.0003으로 느린 전체 회전