Bouncing Particles
📖 Introduction
Bouncing Particles is a real-time physics simulation scene: millions of particles are confined inside a circular, elliptical, or arbitrary convex polygonal boundary, moving with elastic collisions and continuing to fly along reflected directions. Initial particle positions can be sampled from a variety of mathematical shapes (spirals, stars, rose curves, Lissajous curves, and more), while initial velocities support uniform, radial, tangential, and other directional modes. Powered by GPU-based collision solving and per-particle coloring, Bouncing delivers silky-smooth, vividly colored particle collision art.
Key Capabilities:
- GPU Real-Time Physics Simulation: Pure GPU two-pass rendering pipeline; particle state (position + velocity) is stored in textures, supporting smooth collisions among millions of particles
- Multiple Boundary Containers: Circle, ellipse, and arbitrary convex polygons (3-64 vertices), with one-click presets and free drag-and-drop editing
- 13 Initial Position Layouts: From box, circle, and heart to Lissajous curves and superellipses, even custom particle layouts via formulas
- 6 Initial Velocity Modes: Uniform direction, radial in/out, tangential CW/CCW, and fully random, shaping diverse flow patterns
- Per-Particle Velocity Coloring: Particle color correlates with speed, producing dynamic, vibrant visuals through the palette
- Elastic Collision Physics: Precise collision solving based on the law of reflection, handling up to 4 consecutive collisions per substep
🧮 Mathematical Background
What is Bouncing Particles?
The core of the Bouncing Particles simulation is the classic particle-boundary collision system from classical mechanics. Large numbers of mutually non-colliding particles move at constant velocity within a closed 2D region. When a particle touches the boundary, its velocity flips according to the specular reflection law:
where is the unit outward normal at the collision point. This seemingly simple rule, combined with circular, elliptical, and polygonal boundaries, produces a rich variety of trajectory patterns.
Particle Motion Model
Each particle's state consists of position and velocity . Each frame advances by the time step :
When exceeds the boundary (still out of bounds after subtracting the particle collision radius ), the system computes the exact intersection point with the boundary, projects the particle back inside, and reflects the velocity along the normal at the hit point.
Boundary Types
| Boundary Type | Mathematical Description | Collision Solving Method |
|---|---|---|
| Circle | Analytically solve the quadratic equation of the ray-circle intersection | |
| Ellipse | Solve in normalized coordinate space (divide by semi-axes) where it reduces to a circle | |
| Convex Polygon | Convex region bounded by vertices | Per-edge scan to detect exit time + nearest-point projection back inside |
Substeps and Consecutive Collisions
To maintain collision accuracy under high speeds, the system subdivides each frame's time step (Substeps, 1-16) and processes up to 4 consecutive collisions per substep (MAX_COLLISIONS_PER_SUBSTEP). This ensures correct results even when a particle bounces multiple times within a single frame (e.g., flying out at high speed near a sharp corner).
🖥️ Interface Overview
All controls are located in the inspector panel on the right, divided into five main sections:
- Simulation: Configure particle count, substeps, time step, and collision parameters
- Initial Position: Select the initial position layout and shape parameters
- Initial Velocity: Select the initial velocity mode and speed parameters
- Boundary: Configure the boundary container shape, color, and polygon vertices
- Gradient: Adjust the gradient palette
Note: Bouncing Particles is a pure real-time physics simulation scene. It does not include equation parameters, camera, or formula display panels. The scene always renders in 2D, and recording stops automatically based on the configured recording duration.
⚙️ Configuration Guide
1. Simulation
The Simulation panel controls the core physics parameters of the particle system:
Particles: Total number of particles in the simulation
- Range: 1 - unlimited (step 1000)
- Default: 2,000,000
- Recommended:
- Quick preview: 100,000 - 500,000
- Real-time interaction: 1,000,000 - 3,000,000
- High-quality rendering: 5,000,000+
- Note: More particles mean a larger state texture, increasing GPU memory usage and computation
Substeps: Number of times each frame's time step is subdivided
- Range: 1 - 16
- Default: 1
- Effect: Splits each frame's motion into smaller steps to improve collision accuracy for fast particles
- Recommended: Increase (e.g., 2-4) when particle speed is high or collisions are frequent for more stable bounce trajectories
Step Size: Physical time step per substep
- Range: 0.0001 - 0.25
- Default: 0.012
- Effect: Controls the per-step displacement of particles. Larger steps move particles farther each frame, increasing collision frequency
Particle Size: Screen-space pixel diameter of each particle
- Range: 0.1 - 20.0
- Default: 1.25
- Effect: Visual only; does not affect collision physics. Larger particles are visually more prominent
Collision Radius: Physical collision radius of each particle
- Range: 0.0 - 0.25
- Default: 0.006
- Effect: The boundary shrinks inward by this radius during collision detection, so particles bounce only when close to the boundary. Increasing it makes particles appear to bounce "earlier"
Tip: Particle Size (visual) and Collision Radius (physical) are independent parameters. If you want larger visuals without affecting collision accuracy, increase only Particle Size.
2. Initial Position
Initial Position determines where particles are distributed at system startup. The system provides 13 layout modes:
| Mode | Description | Specific Parameters |
|---|---|---|
| Box | Uniformly random distribution inside a rectangle | X Min/Max, Y Min/Max |
| Circle | Uniform distribution inside a disk | Shape center, shape radius |
| Heart | Distribution along a heart curve | Shape center, shape radius |
| Infinity | Distribution along an infinity-symbol curve | Shape center, shape radius |
| Ring | Distribution between inner and outer radii | Shape center, shape radius, inner ratio |
| Spiral | Distribution along an Archimedean spiral | Shape center, shape radius, turns, tightness |
| Star | Distribution along a star outline | Shape center, shape radius, points, inner ratio |
| Lissajous | Distribution along a Lissajous curve | Shape center, shape radius, A, B, delta |
| Rose | Distribution along a rose curve | Shape center, shape radius, K |
| Superellipse | Distribution along a superellipse curve | Shape center, shape radius, N |
| Hypocycloid | Distribution along a hypocycloid | Shape center, shape radius, K |
| Epicycloid | Distribution along an epicycloid | Shape center, shape radius, K |
| Formula | Custom layout using a formula | Shape center, shape radius, formula |
Common Shape Parameters
- Shape Center X/Y: Center position of the layout shape in the scene
- Shape Radius: Scaling radius of the layout shape
Shape-Specific Parameters
- Inner Ratio (Ring/Star): Ratio of the inner radius to the outer radius, controlling ring thickness or star indentation
- Points (Star): Number of star points (≥ 3)
- Turns (Spiral): Number of spiral rotations
- Tightness (Spiral): How tightly the spiral spreads from the center
- A / B (Lissajous): Frequency parameters of the Lissajous curve
- Delta (Lissajous): Phase difference of the Lissajous curve (in degrees)
- K (Rose): Number of rose curve petals
- N (Superellipse): Superellipse exponent, transitioning from diamond (N=1) to rounded rectangle (N=2) to square (N→∞)
- K (Hypocycloid/Epicycloid): Number of cusps of the hypocycloid/epicycloid
Formula Mode
- Formula: Write a conditional formula using
x,yvariables and functions such assin,cos,tan,sqrt,abs,pow,log,exp(e.g.,Math.sin(x*5) + Math.cos(y*3) > 0). Points satisfying the condition are sampled as particle initial positions - Uses Java-style function syntax with the
PIconstant andMath.sin-style functions - Changes take effect automatically when the input field loses focus
Fill Mode
Shape layouts other than Box support two fill styles:
Fill: Particles distributed inside the shape's area
Outline: Particles distributed only along the shape's outline
Line Width: Distribution line width in outline mode
Tip: During initial position sampling, the system automatically discards sample points that fall outside the boundary container (up to 512 attempts), ensuring all particles start inside the container.
3. Initial Velocity
Initial Velocity determines the direction and magnitude of particle motion at startup. The system provides 6 modes:
| Mode | Description |
|---|---|
| Uniform | All particles move in the same direction |
| Out | Radiate outward from the velocity center |
| In | Converge inward toward the velocity center |
| CW | Rotate clockwise around the velocity center |
| CCW | Rotate counterclockwise around the velocity center |
| Random | Each particle's direction is fully random |
Velocity Parameters
Speed: Initial particle speed (≥ 0)
- Default: 0.2
- Effect: Higher speeds make particles move faster and collide more frequently
Direction: Available only in Uniform mode
- Range: 0° - 360°
- Effect: The unified motion direction of all particles
Vx / Vy (Velocity Center): Available only in radial/tangential modes
- Effect: Defines the center point for radial emission or rotational motion
Spread: Angular spread of velocity directions
- Range: 0° - 360°
- Effect: Adds random perturbation to velocity directions; 0° means all particles share the same direction
Noise: Velocity direction noise intensity
- Range: 0.0 - 1.0
- Effect: Adds stronger random jitter on top of the angular spread, simulating turbulence
Seed: Random number generator seed
- Effect: The same seed produces the same random distribution, enabling reproducible compositions
4. Boundary
The Boundary panel defines the container shape that confines the particles:
Common Parameters
- Shape Center X/Y: Center position of the boundary container in the scene
- Boundary Color: Color of the boundary stroke (rendered with a semi-transparent effect)
Boundary Shapes
The system provides four preset shapes plus free polygon editing:
- Circle: Circular boundary with adjustable radius
- Ellipse: Elliptical boundary with independently adjustable semi-major and semi-minor axes
- Triangle: Equilateral triangle boundary with adjustable circumradius
- Hex: Regular hexagon boundary with adjustable circumradius
Polygon Editing
Beyond preset shapes, you can freely construct polygonal boundaries on the editing canvas:
- Drag vertices directly on the canvas to reposition them
- Add: Add a new vertex (up to 64)
- Reset: Restore the default hexagon vertices
- Each vertex can be precisely edited via X/Y coordinates, and the delete button removes a vertex (minimum 3 retained)
Note: When the boundary is polygonal, particle collisions are solved for convex polygons. With preset triangle/hexagon shapes, the radius slider scales the whole shape.
5. Gradient
Bouncing Particles uses per-particle palette coloring: each particle samples a color from the palette based on its ID, overlaid with velocity coloring. Three gradient modes are supported:
Manual:
- Manually add, delete, and adjust color stops
- Drag to reorder colors
- Four random strategies: monochrome, analogous, complementary, and split-complementary
Cosine:
- Uses the IQ cosine palette formula:
color(t) = a + b · cos(2π(c·t + d)) - Individually control the offset, amplitude, frequency, and phase of the R/G/B channels
- One-click randomization and apply
- Uses the IQ cosine palette formula:
Curve:
- Control each R/G/B channel through editable Bézier curves
- Offers the most flexible color control
- One-click randomization and apply
Velocity Coloring: Particle brightness varies with instantaneous speed — faster particles appear brighter and slower ones darker, enhancing the sense of motion.
🎬 Animation and Recording
Bouncing Particles is a real-time physics simulation scene and does not support parameter oscillation animation, but it does support video recording:
- Real-Time Evolution: Particles keep moving and colliding without needing a timeline to show dynamic effects
- Recording Duration Control: The scene uses
record_duration(seconds) from the config to control when recording stops; recording ends automatically when the run time reaches the configured duration - Timeline Config: The scene's
timelineusually contains onlywaitentries to let the particle motion evolve
{
"timeline": [
{
"type": "wait",
"duration": 10.0,
"label": "Wait",
"easing": "SINE_IN_OUT",
"enabled": true
}
]
}🚀 Performance and Best Practices
Recommended Configurations
| Goal | Particles | Substeps | Step Size | Collision Radius |
|---|---|---|---|---|
| Quick preview | 100,000 - 500,000 | 1 | 0.01 - 0.02 | 0.001 - 0.005 |
| Real-time interaction | 1,000,000 - 3,000,000 | 1-2 | 0.01 | 0.002 - 0.006 |
| High-quality rendering | 5,000,000+ | 2-4 | 0.008 - 0.012 | 0.001 - 0.004 |
Performance Optimization Tips
Particle count is the most critical performance factor:
- Collision solving for all particles runs in parallel on the GPU each frame, so particle count directly determines the workload
- Use a low particle count (e.g., 200k) during preview to quickly evaluate layouts and colors, then increase it for final rendering
Trade-off between substeps and step size:
- Increasing Substeps or Step Size significantly increases per-frame computation
- For fast particles (high Speed), increase Substeps to ensure collision accuracy, but avoid excessive values
Overhead of polygonal boundaries:
- Polygon collision requires per-edge detection; more vertices mean more overhead
- Circle and ellipse boundaries use analytical intersection, with the lowest cost
Separate visuals from physics:
- Adjusting Particle Size does not affect the physics simulation and is a low-cost way to improve appearance
- Adjust Collision Radius carefully, as it changes the actual particle trajectories
❓ FAQ
Stuttering or dropped frames
Problem: Rendering is not smooth with a very large particle count
Solutions:
- Reduce the Particles count
- Decrease Substeps and Step Size
- Use circle/ellipse boundaries instead of high-vertex polygons
Abnormal trajectories or "tunneling"
Problem: Fast particles occasionally pass through the boundary
Cause: The per-frame displacement is too large for collision solving to capture the exit time
Solutions:
- Increase Substeps (e.g., from 1 to 2-4)
- Decrease Step Size
- Slightly increase Collision Radius for a buffer
Initial positions appear outside the boundary
Problem: Some particles start outside the container
Cause: The initial layout shape exceeds the container boundary
Solutions:
- Reduce Shape Radius so the layout fits inside the container
- Adjust Shape Center to center the layout
- Use an initial layout matching the container (e.g., Circle/Spiral layout with a circle container)
All particles are motionless
Problem: No movement on screen
Cause: Initial speed is zero or the direction is set incorrectly
Solutions:
- Increase Speed (e.g., 0.1 - 0.5)
- Check the initial velocity mode (Random or Uniform + Direction)
- Check whether the time step is too small
Colors are too plain or chaotic
Problem: Particle colors lack depth
Solutions:
- Switch to Cosine or Curve gradient modes for harmonious color schemes
- Adjust the number and distribution of palette stops
- Velocity coloring automatically gives fast and slow particles a brightness contrast
📐 Classic Examples
Spiral Emission (Circle Container)
Container: Circle (radius 0.55)
Initial Position: Spiral (turns 5.5, tightness 0.16)
Initial Velocity: Uniform (speed 0.2)
Particles: 2,000,000, particle size 1.25, collision radius 0.006Star Emission (Circle Container)
Container: Circle (radius 0.55)
Initial Position: Star (points 5, inner ratio 0.62)
Initial Velocity: Radial Out (speed 0.2, noise 0.4)
Particles: 5,000,000, particle size 0.1Rose Blossom (Circle Container)
Container: Circle (radius 0.55)
Initial Position: Rose (K = 7)
Initial Velocity: Radial Out (speed 0.2, noise 0.4)
Particles: 2,000,000, particle size 0.1Hexagon Vortex (Hexagon Container)
Container: Hexagon (radius 0.62)
Initial Position: Circle (radius 0.16)
Initial Velocity: Uniform (speed 0.2)
Particles: 500,000, particle size 0.1Ellipse Vortex Ring (Ellipse Container)
Container: Ellipse (semi-major 0.6, semi-minor 0.55)
Initial Position: Ring (inner ratio 0.57)
Initial Velocity: Uniform (speed 0.2)
Particles: 2,000,000, particle size 1.25🖼️ More Showcase Examples
🔧 Technical Details
GPU Rendering Pipeline
Bouncing Particles uses a pure GPU two-pass rendering pipeline:
Update Pass:
- Reads the current particle state texture (RGBA32F; R/G = position, B/A = velocity)
- Subdivides the time step by Substeps and performs boundary collision solving (circle/ellipse/polygon) for each substep
- Processes up to 4 consecutive collisions per substep (
MAX_COLLISIONS_PER_SUBSTEP) - Uses Ping-Pong double buffering for alternating state texture read/write
Render Pass:
- Transforms particle positions by Scale/Offset and projects them to the screen
- Draws as
GL_POINTS, clipping to circles viagl_PointCoordin the fragment shader - Samples particle color from the palette by particle ID, overlaid with brightness coloring based on instantaneous speed
- Particle size (Point Size) is specified in screen pixels
Particle State Texture
Particle positions and velocities are packed into a single texSize × texSize RGBA32F texture:
Each texel stores a particle's full state (4 floats, 16 bytes). The vertex shader decodes the particle's texture coordinates via gl_VertexID.
Collision Solving Algorithms
| Boundary | Algorithm |
|---|---|
| Circle | Treat particle motion as a ray and analytically solve the quadratic equation of the ray-circle intersection (radius minus collision radius) to obtain the exact hit time and normal |
| Ellipse | Normalize coordinates and displacement by the semi-axes to reduce to a unit-circle intersection, then un-normalize to obtain the normal |
| Convex Polygon | Compute the exit time against each edge, take the earliest hit edge; if the particle has already crossed the boundary, project it onto the nearest edge and reflect along the normal |
Elastic Reflection
All collisions follow the specular reflection formula:
Speed magnitude is preserved before and after collisions (fully elastic), so particle energy is conserved and motion never decays.
🎨 Creative Tips
Layout Exploration
- Start with preset shapes: Try basic layouts such as Circle, Spiral, and Star in a circle container first
- Match container and layout: Let the layout shape echo the container (e.g., hexagon container + star layout)
- Use formula layouts: After mastering the basics, write formulas like
Math.sin(x*5) + Math.cos(y*3) > 0to craft one-of-a-kind particle patterns
Dynamic Expression
- Velocity modes shape motion: Radial Out produces radial bursts, CW/CCW produces vortex rotation, and Uniform produces orderly flow
- Velocity center changes the focus: Offsetting the velocity center from the container center creates an eccentric rotating dynamic beauty
- Noise and spread: Increase Spread/Noise for wilder motion; keep them at 0 for clean, orderly trajectories
Visual Tuning
- Particle size and density: Small particles (0.1) + high particle count produce a fine sand-like texture; larger particles (1.25+) are more prominent
- Velocity coloring: Use the brightness differences from particle speed to emphasize the direction of motion
- Boundary color: A dark background, bright boundary, and high-saturation palette is a classic combination
⚠️ Notes
GPU memory:
- The particle state texture is ⌈√N⌉ × ⌈√N⌉ using the RGBA32F format, with each particle occupying 16 bytes
- For example, 5 million particles require roughly 80 MB of VRAM for the state texture
Substeps and performance:
- Each doubling of Substeps roughly doubles the Update Pass computation
- For high particle counts, keep Substeps at 1-2
Polygonal boundary limits:
- Vertex count is limited to 3-64
- The boundary must be convex; concave polygons cause incorrect collisions
Particles do not collide with each other:
- Particles only collide with the boundary, not with one another
- This is intentional, keeping the system deterministic and focusing on the visual effect of boundary interactions
📚 References
Mathematical Theory
- Wikipedia: Specular Reflection — mathematical basis of mirror reflection
- Wikipedia: Elastic Collision — elastic collision
- Wikipedia: Lissajous Curve — Lissajous curves
- Wikipedia: Rose (mathematics) — rose curves
Computer Graphics
- Ray–sphere intersection — ray-sphere (circle) intersection
- Point-in-polygon — point-in-polygon test
- OpenGL Shading Language Guide
- GLSL Language Specification
