particle-effects
Generate master-level particle effects for web projects using Three.js, Canvas 2D, WebGL, or WebGPU. Translates visual intent into precise, production-quality implementations with correct physics, ren
SKILL.mdparticle-effects/SKILL.md
GitHubParticle Effects
Generate particle effects that belong on an Awwwards-winning site, not a CodePen demo.
The gap between amateur and master is not the algorithm — it is the details: color harmony, motion weight, layered depth, and restrained post-processing. This skill encodes the judgment of studios like Lusion and artists like Robert Hodgin (flight404), Inigo Quilez, and Yuri Artiukh directly into the workflow so every output meets a professional bar.
Before writing any code, read references/mastery.md — it contains the quality principles that
govern every decision below. Internalize those principles; they are not optional polish.
Workflow
Step 1: Identify the Pattern
Match the user's intent to one of 10 proven interaction patterns:
| # | Pattern | One-liner | Key Tech |
|---|---|---|---|
| 01 | Ambient Background | Slow-drifting atmospheric particles | simplex noise + point sprites + additive blending |
| 02 | Mouse Trail | Cursor leaves a particle wake | emitter at cursor + velocity inheritance + alpha decay |
| 03 | Image/Text Morph | Image or text dissolves into / assembles from particles | canvas sampling + spring physics + noise scatter |
| 04 | Hover Burst | Particles explode from a button on hover | radial velocity + gravity + short lifetime |
| 05 | Scroll Reveal | Elements materialize via particles on scroll | IntersectionObserver + spring interpolation |
| 06 | Radial Pulse | Concentric rings of particles breathing outward | ring emitter + sin modulation + alpha falloff |
| 07 | Galaxy / Spiral | Rotating spiral arms of particles | log-spiral distribution + vortex + FBM noise |
| 08 | Fluid / Smoke | Organic flowing wisps | curl noise velocity field + soft blending + narrow color ramp |
| 09 | Dissolve | Object crumbles into drifting particles | mesh vertices + noise threshold + bloom edge |
| 10 | Physics Playground | Particles with real collisions & forces | N-body / spatial hashing + collision detection |
For full pattern details (parameters, variants, prompt examples), read references/patterns.md.
Step 2: Choose the Tech Stack
| Scale | Recommended Stack | Why |
|---|---|---|
| < 1,000 particles | Canvas 2D | Simple, no deps, good for trails & bursts |
| 1,000 – 50,000 | Three.js + Points/InstancedMesh | Battle-tested, great ecosystem |
| 50,000 – 500,000 | Three.js + GPGPU (FBO ping-pong) | GPU-computed positions, CPU just renders |
| 500,000+ | WebGPU compute shaders | Native GPU compute, highest ceiling |
| React project | React Three Fiber | Three.js with React integration |
Step 3: Design the Color
Color is the #1 amateur tell. Before writing physics, decide the palette.
Never use pure colors. No
#ffffff,#ff0000,#000000. Tint everything. Background:#08080for#0a0a1a(dark navy, not pure black). Whites:#f0e6ffor#e8f4ff(tinted, not stark).Build a 5-7 color palette with weighted distribution:
- 60% dominant mood color
- 25% secondary color
- 10% accent (contrasting temperature)
- 5% highlight (near-white, tinted)
Warm-cool contrast. The best effects mix temperatures: cool blue base + warm gold accents, or warm orange flames + cool dark edges. Single-temperature palettes look flat.
Color over lifetime. Particles should shift color as they age — bright at birth, muted at death (or vice versa). This one technique adds more visual richness than any physics change. See
references/mastery.mdSection 1 for code patterns.
Step 4: Build the Motion
Every particle should move as if it has mass. Weightless motion looks fake.
Spring physics, not lerp. Use
vel += (target - pos) * stiffness; vel *= dampinginstead ofpos += (target - pos) * factor. Springs have overshoot, settle, and weight.Multi-octave noise. Never use a single noise layer — it looks mechanical. Layer 2-3 octaves with irrational frequency multipliers (2.13x, 4.37x) to avoid repetition:
v += noise(p * freq, t) * amp v += noise(p * freq * 2.13, t * 1.37) * amp * 0.35 v += noise(p * freq * 4.37, t * 1.71) * amp * 0.15Velocity inheritance. When spawning from a moving source (cursor, scroll), particles must inherit the source's momentum. Without this, trails look placed, not emitted.
Graceful birth and death. Particles fade in over the first ~15% of life and fade out over the last ~30%. No popping.
Choose damping to match weight:
- 0.85–0.90: heavy, viscous (underwater, thick smoke)
- 0.91–0.95: natural, weighted (most effects — the sweet spot)
- 0.96–0.99: light, floaty (space, zero-gravity, ambient)
Never use Math.random() per frame for motion. Use curl/simplex noise for organic flow. Random jitter ≠ organic movement.
For noise type selection, see references/terminology.md (Noise Types section).
Step 5: Compose with Depth
The space between particles is as important as the particles themselves.
Layer at multiple scales. Use 2-3 layers, not one uniform field:
- Background (15%): tiny, dim, slow — creates atmosphere
- Mid (80%): standard — the main effect
- Foreground (5%): large, bright, fast — creates depth illusion
Size variation. Never uniform. Use a distribution skewed toward small:
size = Math.exp(Math.random() * 1.2 - 0.3)gives many small, few large.Respect negative space. Professional work never fills the screen uniformly. Dense regions draw the eye; empty regions give it rest. Aim for 30-40% coverage on ambient effects; focal effects should have dense centers and sparse edges.
Step 6: Apply Post-Processing
Post-processing is not optional. It separates WebGL demo from shipped product.
Bloom (UnrealBloomPass): Always include, but with restraint:
- strength: 0.2–0.5 (not 1.0+)
- threshold: 0.3–0.6 (only bright particles glow, not everything)
- radius: 0.3–0.7 (tight, focused, not giant halos)
Additive blending opacity rules (the most common mistake):
- Dense effects (smoke, galaxy): 0.05–0.15
- Medium effects (ambient, morph): 0.15–0.35
- Sparse effects (trails, bursts): 0.3–0.6
- If the output looks washed out / white, opacity is too high.
Optional enhancements for premium effects:
- Depth of Field: blur distant particles
- Chromatic aberration: subtle RGB offset at edges
- Vignette: darken screen edges to focus attention
Step 7: Wire the Controls
lil-gui is a design tool, not a debug panel.
- Always include lil-gui (unless the user explicitly declines).
- Group parameters into semantic folders: Emitter, Physics, Mouse, Rendering.
- Name controls for the user, not the code: "Wind Strength" not "noiseAmplitude".
- Include presets if the effect supports multiple moods:
const presets = { dreamy: { noiseSpeed: 0.08, damping: 0.97, bloomStrength: 0.4 }, energetic: { noiseSpeed: 0.3, damping: 0.90, bloomStrength: 0.2 }, minimal: { noiseSpeed: 0.05, damping: 0.98, bloomStrength: 0.1 }, }; - Parameter changes must take effect immediately — no restart required.
Step 8: Quality Gate
Before delivering, verify against these anti-patterns (the "deadly sins" of particle effects):
| Check | What to look for | Fix |
|---|---|---|
| White-out | Dense areas burn to pure white | Lower opacity, raise bloom threshold |
| Uniform soup | All particles same size/speed/color | Add size variation, layering, palette weights |
| Linear motion | Constant speed, no acceleration | Use spring physics, easing, damping |
| Hard edges | Particles pop in/out instantly | Add fade in/out over first/last 15% of life |
| Noise jitter | Shaking instead of flowing | Use curl/simplex noise, not Math.random() |
| Screen stuffing | Particles everywhere, no rest | Reduce count, add negative space |
| Dead calm | Assembled particles perfectly still | Add very subtle noise idle drift (amp 0.002-0.005) |
| Missing GUI | Hard-coded magic numbers | Add lil-gui with grouped, named parameters |
The bar is not "does it work." The bar is: would this look at home on a Lusion project page?
Quick Reference
- Full terminology dictionary (40+ terms):
references/terminology.md - All 10 patterns with parameters & prompt examples:
references/patterns.md - Libraries, tools, websites & classic cases:
references/resources.md - Master-level principles & anti-patterns:
references/mastery.md← read this first
Universal Prompt Template
When the user's request is vague, fill in this brief before coding:
Pattern: [from the 10 patterns above]
Tech stack: [Three.js / Canvas 2D / WebGPU / R3F]
Particle count: [5K / 50K / 500K]
Interaction: [mouse repel / attract / trail / scroll / none]
Visual style: [dreamy soft / hard sci-fi / organic natural / minimal geometric]
Palette: [5-7 specific hex values with warm-cool contrast]
Noise: [curl / simplex / FBM / none] × [octave count]
Post-processing: [bloom settings + optional DOF/vignette]
GUI presets: [mood names and their parameter values]