Skip to content
Sample of Saturn Rings (orbital resonance)

hodgin_iquilezles · SaturnRings

Saturn Rings (orbital resonance)

Thousands of particles are initialized in an annulus between inner_radius and outer_radius around a central mass, with circular orbital velocities v = sqrt(M/r). Each frame the central inverse-square gravity pulls them inward, a small tangential drift adds ring shimmer, and unstable particles are recycled. The accumulated low-alpha trail builds the layered concentric-ring structure reminiscent of Hodgin's Saturn studies.

Original: https://flight404.com

▶ Try the live demo (JS port) ▶ Run reference.py via Pyodide 10 formulas have instant JS ports. The Pyodide path runs the actual Python in your browser — first load is ~6 MB, then instant.

Family
hodgin_iquilezles
Source
hodgin × iquilezles
Evolution
physics
Render
path_tracing
Complexity
medium
Agents
4000
Year
2007
Author
Robert Hodgin (flight404)

Math essence

Each particle obeys a_central = -M * r_hat / r^2 plus a tangential kick t_drift perpendicular to r_hat. Velocity is integrated and clamped to max_speed; position updates, with particles that leave the annulus being reborn on a fresh circular orbit at a new random radius. The integration preserves stable nearly-circular orbits while the per-particle tangential drift slowly smears each ring into a thin luminous band.

Parameters

Name Type Default Range Description
dim int 500 200–1000 Square canvas side length in pixels.
num int 4000 500–12000 Number of orbital particles.
inner_radius float 90 20–200 Inner edge of the allowed annulus.
outer_radius float 230 100–480 Outer edge of the allowed annulus.
central_mass float 1.6 0.2–6 Gravitational mass of the central body.
tangential_boost float 1 0.5–2 Multiplier on the theoretical circular velocity sqrt(M/r).
eccentricity float 0.06 0–0.4 Initial radial jitter as a fraction of orbital velocity.
radial_drift float 0.0006 0–0.01 Standard deviation of the per-frame tangential kick.
ring_jitter float 0.08 0–0.5 Initial relative scatter of orbital velocities.
max_speed float 12 4–30 Speed clamp (px/frame).
trail_alpha int 18 4–80 Stroke alpha (0-255).

Reference

First 60 lines of reference.py. Full source: library_external/hodgin_iquilezles/SaturnRings/reference.py

from __future__ import annotations

from typing import ClassVar

import numpy as np


class SaturnRings:
    """Saturn Rings — Robert Hodgin (flight404), inspired by *Saturn* / orbital systems.

    Hodgin built several orbital-resonance studies; the most famous is the
    *Saturn* sketch in which thousands of particles orbit a central mass in
    concentric rings, each ring at a slightly different resonance.  Particles
    are subject to inverse-square gravitational attraction toward a central
    mass plus a tangential impulse that keeps them in roughly circular
    orbits; small perturbations (drift + jitter) keep each ring shimmering.

    The "interesting" particles are the ones whose initial radius lies
    inside an allowed stable annulus.  Particles outside the annulus either
    spiral in or escape.
    """

    family: ClassVar[str] = "hodgin_iquilezles"
    sketch: ClassVar[str] = "saturnrings"

    def __init__(
        self,
        dim: int = 500,
        num: int = 4000,
        inner_radius: float = 90.0,
        outer_radius: float = 230.0,
        central_mass: float = 1.6,
        tangential_boost: float = 1.0,
        eccentricity: float = 0.06,
        radial_drift: float = 0.0006,
        ring_jitter: float = 0.08,
        max_speed: float = 12.0,
        trail_alpha: int = 18,
        ink_color: tuple[int, int, int] = (255, 240, 220),
        background: tuple[int, int, int] = (4, 4, 10),
        **_,
    ) -> None:
        self.dim = dim
        self.num = num
        self.inner_radius = inner_radius
        self.outer_radius = outer_radius
        self.central_mass = central_mass
        self.tangential_boost = tangential_boost
        self.eccentricity = eccentricity
        self.radial_drift = radial_drift
        self.ring_jitter = ring_jitter
        self.max_speed = max_speed
        self.trail_alpha = trail_alpha
        self.ink_color = np.array(ink_color, dtype=np.float32)
        self.bg_color = np.array(background, dtype=np.float32)
        self.reset()

    def reset(self, seed: int | None = None) -> None:
        self.rng = np.random.default_rng(seed)
        cx = self.dim * 0.5

Try running it locally

The reference implementation is self-contained Python with numpy. Install the package and run:

python library_external/hodgin_iquilezles/SaturnRings/reference.py

Need help? See Learn for the standard environment setup, or Playground for an in-browser sketchbook.

More from hodgin × iquilezles

Sample of Boids Flock (Hodgin Murmuration)

Boids Flock (Hodgin Murmuration)

hodgin_iquilezles · BoidsFlock

A 2D flock of boids steered by Craig Reynolds' three classic rules (separation, alignment, cohesion) over a coarse spatial-hash neighbor query.

View →
Sample of Fractional Brownian Motion noise

Fractional Brownian Motion noise

hodgin_iquilezles · FBMNoise

Quilez's canonical fBM: a 2D value-noise base summed over N octaves whose frequency doubles and amplitude is multiplied by G = exp2(-H) per octave.

View →
Sample of Magneto Particles (Hodgin Magnetosphere)

Magneto Particles (Hodgin Magnetosphere)

hodgin_iquilezles · MagnetoParticles

Particles pulled and pushed by N orbiting magnetic anchors whose charges flip sign over time.

View →
Sample of Mulberry32 PRNG (stratified scatter)

Mulberry32 PRNG (stratified scatter)

hodgin_iquilezles · Mulberry32RNG

Mulberry32 is a tiny 32-bit-state pseudo-random number generator popularised in the demoscene and used pervasively by Quilez and other graphics programmers as the RNG inside procedural sketches.

View →
Sample of Smooth-Minimum SDF field

Smooth-Minimum SDF field

hodgin_iquilezles · SmoothMinSDF

Two animated 2D SDF primitives (a moving circle and a translating slab) are blended with Quilez's quadratic-polynomial smooth-minimum and rendered as a scalar field.

View →
Sample of Worley / Cellular Noise

Worley / Cellular Noise

hodgin_iquilezles · WorleyNoise

Quilez's classic 2D Worley noise: a unit grid of cells, each containing one pseudo-random feature point placed by a 2D integer hash.

View →

See all hodgin_iquilezles artworks →