@@ -18,6 +18,8 @@ interface PulseMarker {
1818 core: THREE .Mesh ;
1919 aura: THREE .Mesh ;
2020 phase: number ;
21+ flashRate: number ;
22+ flashPhase: number ;
2123}
2224
2325interface CircuitLine {
@@ -246,38 +248,46 @@ function createCircuitFlow() {
246248 }
247249
248250 const pulses: PulseMarker [] = [];
249- const pulseCount = 2 + Math .floor (Math .random () * 2 );
250-
251- for (let j = 0 ; j < pulseCount ; j += 1 ) {
252- const core = new THREE .Mesh (
253- new THREE .SphereGeometry (rand (0.2 , 0.42 ), 14 , 14 ),
254- new THREE .MeshBasicMaterial ({
255- color: 0x8ff8ff ,
256- transparent: true ,
257- opacity: rand (0.55 , 0.82 ),
258- depthWrite: false ,
259- blending: THREE .AdditiveBlending ,
260- }),
261- );
262-
263- const aura = new THREE .Mesh (
264- new THREE .SphereGeometry (rand (0.55 , 1.0 ), 14 , 14 ),
265- new THREE .MeshBasicMaterial ({
266- color: 0x34b6ff ,
267- transparent: true ,
268- opacity: rand (0.16 , 0.3 ),
269- depthWrite: false ,
270- blending: THREE .AdditiveBlending ,
271- }),
272- );
273-
274- group .add (core );
275- group .add (aura );
276- pulses .push ({
277- core ,
278- aura ,
279- phase: j / pulseCount + Math .random () * 0.12 ,
280- });
251+ const pulseHeadCount = 1 + Math .floor (Math .random () * 3 );
252+
253+ for (let j = 0 ; j < pulseHeadCount ; j += 1 ) {
254+ const headPhase = j / pulseHeadCount + Math .random () * 0.18 ;
255+ const sequenceCount = Math .random () < 0.5 ? Math .floor (rand (2 , 9 )) : 1 ;
256+ const sequenceGap = rand (0.018 , 0.05 );
257+
258+ for (let k = 0 ; k < sequenceCount ; k += 1 ) {
259+ const core = new THREE .Mesh (
260+ new THREE .SphereGeometry (rand (0.2 , 0.42 ), 14 , 14 ),
261+ new THREE .MeshBasicMaterial ({
262+ color: 0x8ff8ff ,
263+ transparent: true ,
264+ opacity: rand (0.55 , 0.82 ),
265+ depthWrite: false ,
266+ blending: THREE .AdditiveBlending ,
267+ }),
268+ );
269+
270+ const aura = new THREE .Mesh (
271+ new THREE .SphereGeometry (rand (0.55 , 1.0 ), 14 , 14 ),
272+ new THREE .MeshBasicMaterial ({
273+ color: 0x34b6ff ,
274+ transparent: true ,
275+ opacity: rand (0.16 , 0.3 ),
276+ depthWrite: false ,
277+ blending: THREE .AdditiveBlending ,
278+ }),
279+ );
280+
281+ group .add (core );
282+ group .add (aura );
283+ pulses .push ({
284+ core ,
285+ aura ,
286+ phase: headPhase - k * sequenceGap ,
287+ flashRate: rand (5.2 , 13.8 ),
288+ flashPhase: rand (0 , Math .PI * 2 ),
289+ });
290+ }
281291 }
282292
283293 const depthOffset = rand (0 , FLOW_DEPTH_SPAN );
@@ -369,23 +379,27 @@ function animate() {
369379 const linePulseSpeed = (PULSE_SPEED_BASE + flowSpeed * PULSE_SPEED_FLOW_GAIN ) * circuit .speedFactor ;
370380 for (const pulse of circuit .pulses ) {
371381 let progress = (elapsed * linePulseSpeed + pulse .phase ) % 1 ;
382+ if (progress < 0 ) progress += 1 ;
372383 if (proximity > 0.58 ) {
373384 const jumpStep = THREE .MathUtils .lerp (0.028 , 0.11 , (proximity - 0.58 ) / 0.42 );
374385 progress = Math .round (progress / jumpStep ) * jumpStep ;
386+ if (progress < 0 ) progress += 1 ;
387+ if (progress > 1 ) progress -= 1 ;
375388 }
376389 const flowT = Math .pow (progress , 0.82 );
377390 const position = samplePath (circuit .sampler , flowT );
378391 pulse .core .position .copy (position );
379392 pulse .aura .position .copy (position );
380393
381394 const distanceFade = Math .max (0.06 , 1 - flowT );
395+ const flash = 0.45 + 0.55 * (0.5 + 0.5 * Math .sin (elapsed * pulse .flashRate + pulse .flashPhase ));
382396 const pulseWave = 0.88 + Math .sin ((elapsed + pulse .phase ) * 9 ) * 0.12 ;
383397 const coreMaterial = pulse .core .material as THREE .MeshBasicMaterial ;
384398 const auraMaterial = pulse .aura .material as THREE .MeshBasicMaterial ;
385- coreMaterial .opacity = 0.08 + proximity * 0.42 + distanceFade * 0.46 ;
386- auraMaterial .opacity = 0.04 + proximity * 0.19 + distanceFade * 0.16 ;
387- pulse .core .scale .setScalar ((0.76 + proximity * 0.36 ) * pulseWave );
388- pulse .aura .scale .setScalar ((0.84 + proximity * 0.38 ) + pulseWave * 0.22 );
399+ coreMaterial .opacity = ( 0.08 + proximity * 0.42 + distanceFade * 0.46 ) * flash ;
400+ auraMaterial .opacity = ( 0.04 + proximity * 0.19 + distanceFade * 0.16 ) * flash ;
401+ pulse .core .scale .setScalar ((0.72 + proximity * 0.34 ) * pulseWave * ( 0.85 + flash * 0.25 ) );
402+ pulse .aura .scale .setScalar ((0.8 + proximity * 0.34 ) + pulseWave * 0.2 * ( 0.8 + flash * 0.35 ) );
389403 }
390404 }
391405
0 commit comments