The Attractor
The story behind The Attractor
Inspired by Chaos machine on Wikipedia
Built with Three.js · ShaderMaterial · EffectComposer · RK4 Integration
Techniques Lorenz Attractor · Ring-Buffer Trail Rendering · Additive Blending · Bloom + Vignette + Grain
Direction The most perfect randomness comes from perfect rules
Result A living strange attractor you can sculpt by moving — chaos that always finds its shape
The Story
In 1963, meteorologist Edward Lorenz was running a simplified weather simulation on a Royal McBee LGP-30 computer at MIT. To save time, he re-entered a value from a printout — 0.506 instead of the full 0.506127. The weather diverged completely. That rounding error launched an entire field of mathematics.
The Lorenz system is three equations. No randomness. No noise. No dice. The system follows its own rules with absolute precision. And yet the behavior is so unpredictable that these same chaotic maps now secure cryptographic systems — a class of algorithms called “chaos machines” that turn deterministic equations into pseudo-random oracles indistinguishable from true randomness.
The deep paradox: perfect rules create perfect unpredictability. Control is the mother of chaos.
The Take
The experience makes the Lorenz attractor physical. Ten thousand particles integrate the three equations simultaneously, each tracing its own trajectory through 3D space. None of them know where they’re going. All of them arrive at the same invisible shape — the strange attractor, a geometric ghost that governs motion but can never be drawn directly. You only see it through the density and flow of particles orbiting it.
Your cursor warps the attractor’s parameters in real-time. Mouse X controls rho (chaos intensity: 20–36), mouse Y controls sigma (coupling speed: 6–14). Gentle movement creates tight, calm orbits. Fast sweeps scatter the particle cloud — and then the attractor pulls everything back. The key moment isn’t the scatter. It’s the reassembly. Watching 10,000 particles find invisible order after you’ve blown them apart.
The Tech
Lorenz Integration: RK4 at 10,000 Particles
Each particle independently integrates the Lorenz system using 4th-order Runge-Kutta. The standard equations — dx/dt = σ(y-x), dy/dt = x(ρ-z)-y, dz/dt = xy-βz — run with a timestep of 0.003 and adaptive parameters. RK4 requires four derivative evaluations per particle per frame, totaling 40,000 vector operations. This runs comfortably on CPU because the operations are simple arithmetic — no spatial queries, no neighbor lookups.
Particles are initialized by settling a seed point onto the attractor (5,000 integration steps), then spawning all particles with micro-perturbations and running each forward a random number of steps (0–3,000) to spread them across the attractor’s surface. This avoids the “all particles start at one point” problem — from frame one, the full butterfly wing structure is visible.
Trail Rendering: 590,000 Line Segments in One Draw Call
Each particle stores a ring buffer of its last 50 positions (25 on mobile). These 50 positions produce 49 line segments per particle. At 10,000 particles, that’s 490,000 line segments — rendered as a single THREE.LineSegments with a pre-allocated BufferGeometry. Two vertices per segment, each with position (vec3) and color (vec4, including alpha).
The ring buffer head advances each frame, overwriting the oldest position. When building line segments, we walk from oldest to newest, so the alpha naturally fades: a quadratic curve from 0 at the tail to 0.35 at the head. This creates the luminous trail effect — dense at the tip, ghosting away behind.
Additive blending (THREE.AdditiveBlending) is deliberate here: where trails overlap, brightness accumulates. The attractor’s shape emerges through luminance — dense orbital paths glow brighter, revealing the geometry that individual particles can’t show.
Color Mapping: Z-Height to Warm Spectrum
Particle color is mapped from Z position on the attractor (which ranges roughly 5–45). Low Z produces deep amber (#D4720A), mid-range gives bright gold (#E8B030), and high Z shifts to hot crimson (#D43030). Since particles oscillate between the two lobes (alternating Z), each trail contains the full color gradient. The visual reads as wings of flame.
Cursor Interaction: Parameter Warping + Velocity Scatter
Cursor position maps smoothly to attractor parameters via lerp (factor 0.04 per frame for stability). Cursor velocity, smoothed over 8 frames, drives a radial perturbation force: particles within 8 units of the cursor’s projected 3D position receive a velocity kick proportional to speed and inversely proportional to distance. This creates the scatter/reassembly dynamic — fast sweeps blow the cloud apart, and the attractor’s mathematical gravity pulls everything home.
When idle for 8+ seconds, the parameters gently oscillate with sine waves at prime-related periods (0.21 and 0.27 radians/second for rho and sigma), ensuring the idle attractor never exactly repeats. Beta breathes slowly (period ~45s, amplitude ±0.15) to subtly change the attractor’s proportions.
Post-Processing: Bloom + Vignette + Grain
UnrealBloomPass at threshold 0.7, strength 0.4, radius 0.5 — tuned to make the brightest trail segments glow without washing out the subtler tails. A custom ShaderPass applies vignette (darkness 0.45, smooth falloff from center) and film grain (intensity 0.03, animated by time). Tone mapping is THREE.ReinhardToneMapping at exposure 1.8 — preserving the warm ambers without crushing the dark background, a lesson learned from previous builds where ACES destroyed dark scene visibility.
Mobile Adaptation
On screens under 768px: particle count drops to 5,000, trail length to 25, camera pulls back to distance 30, and auto-rotation speeds up to 0.04 rad/s. Bloom strength reduces to 0.3. Touch position maps to the same parameter controls as cursor. The experience remains fully interactive on touch devices.
This blog post was AI generated with Claude Code. Authored by Artificial Noodles.