import * as THREE from 'three'; let dustParticles = null; let dustPositions = null; let dustVelocities = null; const DUST_COUNT = 600; export function initEffects(scene) { initDustMotes(scene); } function initDustMotes(scene) { const geo = new THREE.BufferGeometry(); const positions = new Float32Array(DUST_COUNT * 3); const colors = new Float32Array(DUST_COUNT * 3); const velocities = new Float32Array(DUST_COUNT); for (let i = 0; i < DUST_COUNT; i++) { positions[i * 3] = (Math.random() - 0.5) * 22; positions[i * 3 + 1] = Math.random() * 10; positions[i * 3 + 2] = (Math.random() - 0.5) * 16 - 2; velocities[i] = 0.008 + Math.random() * 0.012; const roll = Math.random(); if (roll < 0.6) { colors[i * 3] = 0.9 + Math.random() * 0.1; colors[i * 3 + 1] = 0.7 + Math.random() * 0.2; colors[i * 3 + 2] = 0.3 + Math.random() * 0.3; } else { const b = 0.3 + Math.random() * 0.5; colors[i * 3] = 0; colors[i * 3 + 1] = b; colors[i * 3 + 2] = 0; } } geo.setAttribute('position', new THREE.BufferAttribute(positions, 3)); geo.setAttribute('color', new THREE.BufferAttribute(colors, 3)); dustPositions = positions; dustVelocities = velocities; const mat = new THREE.PointsMaterial({ size: 0.06, vertexColors: true, transparent: true, opacity: 0.55, sizeAttenuation: true, }); dustParticles = new THREE.Points(geo, mat); scene.add(dustParticles); } export function updateEffects(time) { if (!dustParticles) return; const t = time * 0.001; for (let i = 0; i < DUST_COUNT; i++) { dustPositions[i * 3 + 1] += dustVelocities[i]; dustPositions[i * 3] += Math.sin(t * 0.5 + i * 0.1) * 0.002; if (dustPositions[i * 3 + 1] > 10) { dustPositions[i * 3 + 1] = 0; dustPositions[i * 3] = (Math.random() - 0.5) * 22; dustPositions[i * 3 + 2] = (Math.random() - 0.5) * 16 - 2; } } dustParticles.geometry.attributes.position.needsUpdate = true; } export function disposeEffects() { if (dustParticles) { dustParticles.geometry.dispose(); dustParticles.material.dispose(); dustParticles = null; } dustPositions = null; dustVelocities = null; }