2 patterns-earthbound-Multi-Layer-Plasma
Balazs Horvath edited this page 2026-04-18 11:13:15 +02:00

Multi-Layer Plasma

Classic plasma effect combining multiple sine waves with color cycling. This is a foundational demoscene technique that creates smooth, flowing patterns through wave superposition.

Mathematical Formula


P(x, y, t) = \frac{\sin(x + \omega_1 t) + \sin(y + \omega_2 t) + \sin(\frac{x+y}{2} + \omega_3 t) + \sin(\frac{x-y}{2} + \omega_4 t)}{4}

Where:

  • x, y are spatial coordinates (0 to 2\pi)
  • t is time
  • \omega_1, \omega_2, \omega_3, \omega_4 are temporal frequencies
  • Division by 4 normalizes the sum

How It Works

Plasma effects rely on the principle of superposition: adding multiple simple waves creates complex patterns. Each sine wave contributes a different spatial and temporal frequency, and their sum creates interference patterns that appear to flow smoothly.

Implementation

import torch

width, height = 512, 512
frames = []

for t in range(30):
    x = torch.linspace(0, 2*torch.pi, width)
    y = torch.linspace(0, 2*torch.pi, height)
    X, Y = torch.meshgrid(x, y, indexing='ij')
    
    # Multi-layer plasma based on demoscene techniques
    p1 = torch.sin(X + t/5)
    p2 = torch.sin(Y + t/4)
    p3 = torch.sin((X + Y) / 2 + t/6)
    p4 = torch.sin((X - Y) / 2 + t/7)
    
    plasma = (p1 + p2 + p3 + p4) / 4
    
    # Earthbound-style warm sunset palette
    r = plasma * 0.8 + 0.2
    g = plasma * 0.4 + 0.3
    b = plasma * 0.2 + 0.6
    
    rgb = torch.stack([r, g, b], dim=-1).clamp(0, 1)
    frames.append(rgb)

output_image = torch.stack(frames, dim=0)

Line-by-Line Explanation

p1 = torch.sin(X + t/5)

Horizontal wave moving right over time. t/5 controls speed.

p2 = torch.sin(Y + t/4)

Vertical wave moving down over time. Different speed (t/4) creates variation.

p3 = torch.sin((X + Y) / 2 + t/6)

Diagonal wave (sum of coordinates) moving at different speed.

p4 = torch.sin((X - Y) / 2 + t/7)

Anti-diagonal wave (difference of coordinates) for additional complexity.

plasma = (p1 + p2 + p3 + p4) / 4

Average of all four waves. Division by 4 normalizes to [-1, 1] range.

r = plasma * 0.8 + 0.2
g = plasma * 0.4 + 0.3
b = plasma * 0.2 + 0.6

Linear color mapping to warm sunset palette. Each channel has different scaling and offset for color variation.

Customization

More Waves

p5 = torch.sin(X * 2 + t/8)
p6 = torch.sin(Y * 2 + t/9)
plasma = (p1 + p2 + p3 + p4 + p5 + p6) / 6

Different Frequencies

p1 = torch.sin(2*X + t/5)  # Tighter horizontal waves
p2 = torch.sin(3*Y + t/4)  # Tighter vertical waves

Color Cycling

r = torch.sin(plasma * torch.pi + t/10)
g = torch.sin(plasma * torch.pi + t/10 + 2*torch.pi/3)
b = torch.sin(plasma * torch.pi + t/10 + 4*torch.pi/3)
rgb = ((rgb + 1) / 2).clamp(0, 1)

Mathematical Insight

Wave Superposition

When you add sine waves:

  • Constructive interference: Peaks align → brighter regions
  • Destructive interference: Peak meets trough → darker regions
  • Partial interference: Intermediate brightness

The four waves with different spatial orientations create a complex interference pattern that appears to flow in multiple directions simultaneously.

Why Division by 4?

Each sine wave ranges from -1 to 1. Summing four waves gives a range of -4 to 4. Dividing by 4 normalizes back to [-1, 1], which is convenient for color mapping.

Performance Notes

  • All operations are vectorized (fast on GPU)
  • Precompute coordinate grids for efficiency
  • Fewer waves = faster, more waves = more complex

References