2 patterns-earthbound-Moire-Interference
Balazs Horvath edited this page 2026-04-18 11:13:12 +02:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Moiré Interference

Creates interference patterns through overlapping wave patterns, a common technique in retro psychedelic effects.

Mathematical Formula


I = \sin(k_1 x + \omega_1 t) \times \sin(k_2 y + \omega_2 t) \times \sin(k_3 (x+y) + \omega_3 t)

Where:

  • k_1, k_2, k_3 are spatial frequencies
  • \omega_1, \omega_2, \omega_3 are temporal frequencies
  • Multiplication creates interference (not addition)
flowchart TD
    A[Create coordinate grids] --> B[Generate wave 1]
    A --> C[Generate wave 2]
    A --> D[Generate wave 3]
    B --> E[Multiply all waves]
    C --> E
    D --> E
    E --> F[High contrast interference]
    F --> G[Roll for color separation]
    G --> H[RGB channels with phase shifts]
    H --> I[Output animation]

How It Works

Moiré patterns occur when two or more regular patterns overlap. Unlike additive superposition (which averages waves), multiplicative interference creates:

  • High contrast where waves align
  • Dark regions where waves cancel
  • Complex geometric patterns

Implementation

import torch

width, height = 512, 512
frames = []

for t in range(30):
    x = torch.linspace(0, 10*torch.pi, width)
    y = torch.linspace(0, 10*torch.pi, height)
    X, Y = torch.meshgrid(x, y, indexing='ij')
    
    # Create two overlapping wave patterns
    wave1 = torch.sin(X * 2 + t/5)
    wave2 = torch.sin(Y * 2 + t/4)
    wave3 = torch.sin((X + Y) * 2 + t/6)
    
    # Interference creates moiré pattern
    interference = wave1 * wave2 * wave3
    
    # High-contrast psychedelic palette
    r = torch.abs(interference)
    g = torch.abs(torch.roll(interference, 1, dims=0))
    b = torch.abs(torch.roll(interference, 1, dims=1))
    
    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

x = torch.linspace(0, 10*torch.pi, width)
y = torch.linspace(0, 10*torch.pi, height)

Coordinates range from 0 to 10π, creating 5 full cycles of sine waves across the image.

wave1 = torch.sin(X * 2 + t/5)

Horizontal wave with frequency 2 (2 cycles per π units).

wave2 = torch.sin(Y * 2 + t/4)

Vertical wave with same frequency but different temporal speed.

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

Diagonal wave (sum of coordinates) with its own temporal speed.

interference = wave1 * wave2 * wave3

Multiplication creates interference. Unlike addition, this creates high-contrast patterns:

  • Where all three are positive: bright
  • Where any is negative: dark
  • Complex geometric regions form
r = torch.abs(interference)

Red channel shows absolute interference (all positive).

g = torch.abs(torch.roll(interference, 1, dims=0))

Green channel shows interference shifted down by 1 pixel. This creates color separation.

b = torch.abs(torch.roll(interference, 1, dims=1))

Blue channel shows interference shifted right by 1 pixel. Different shift direction creates more color variation.

Mathematical Insight

Multiplication vs Addition

Additive superposition:

I = sin(x) + sin(y)
  • Range: [-2, 2]
  • Smooth transitions
  • Averages values

Multiplicative interference:

I = sin(x) × sin(y)
  • Range: [-1, 1]
  • Sharp transitions
  • High contrast regions

Multiplication creates moiré patterns because the product of oscillating functions has complex zero-crossings.

Why Roll for Color?

g = torch.abs(torch.roll(interference, 1, dims=0))

Shifting the interference pattern by 1 pixel before taking the absolute value creates phase differences between color channels. This:

  • Separates colors spatially
  • Creates rainbow-like effects
  • Adds visual interest

Customization

More Waves

wave4 = torch.sin((X - Y) * 2 + t/7)
interference = wave1 * wave2 * wave3 * wave4

Different Frequencies

wave1 = torch.sin(X * 3 + t/5)  # Tighter pattern
wave2 = torch.sin(Y * 2 + t/4)

Additive Instead of Multiplicative

interference = wave1 + wave2 + wave3  # Softer, less contrast

No Color Shifting

r = torch.abs(interference)
g = torch.abs(interference)
b = torch.abs(interference)

Performance Notes

  • All operations are vectorized
  • torch.roll() is efficient
  • No expensive filtering

References