Skip to content

Repository files navigation

Emberweft

A native macOS, Apple-Silicon-GPU fractal-flame dream machine.

License: PolyForm Noncommercial Status Platform

Status: pre-alpha · v0.4.0: CPU + Metal renderers, animation + realtime playback, motion-blurred real-genome parity, seamless boundaries, a full native SwiftUI studio (sidebar browser, multi-select, tri-state sentiment, search/filter, drag-drop import, collections, non-modal playback with configurable preview presets + live FPS, distinct preview/export quality settings), and video export to MP4/MOV via the emberweft export CLI (H.264 + HEVC, long-form, batch; GUI export sheet pending) are working · source-available (PolyForm Noncommercial)

What is it?

Emberweft is an independent re-implementation of Scott Draves' fractal flame algorithm — the math behind the famous Electric Sheep screensaver — built natively for Apple Silicon and Metal. It turns flame genomes (standard .flam3 parameter files) into morphing, endlessly-evolving animations called sheep, and is designed to grow into a full generative-video studio: realtime playback, long-form export, audio-reactive music videos, a macOS screensaver, and multi-resolution output from vertical social clips to 4K.

It reads the standard .flam3 genome format while remaining entirely independent of the Electric Sheep / Infinidream codebase and servers.

Features

Works now (M0–M4 + M6 complete, v0.4.0):

  • emberweft CLI — render, validate, info, animate, curate — parses standard .flam3 genomes into stills and animation sequences
  • CPU reference renderer, a faithful port of flam3 (near-byte-exact parity on synthetic goldens; 49–52 dB on real ES genomes)
  • Metal compute renderer — a faithful twin of the CPU path, 12–18× faster at 1080p
  • --backend cpu|metal switch; byte-deterministic within each backend
  • Realtime playback engine — adaptive-quality PlaybackDispatcher + FlameUI (≥ 58 fps @ 1080p, M2 Max)
  • Animation: seamless sheep loops (pure affine rotation) + smooth transitions between genomes, alternating endlessly — the Electric Sheep sequence
  • Motion blur — faithful temporal_samples port (--temporal-samples N); box / gaussian / exp temporal filters
  • Complete flam3 variation coverage — all 99 of 99 variations ported to CPU + Metal and validated ≥38 dB vs flam3 (the classic set, the 16 special-sauce variations, the trig family, and the parametric/RNG remainder through pre_blur)
  • Native SwiftUI studio (emberweft-gui): a NavigationSplitView sidebar browser (All / Library / ★ Liked / Imported / Folders), multi-select with bulk actions, tri-state sentiment (👍/○/👎), search + filter (sentiment / category / palette), drag-and-drop import, collections/playlists with drag reorder, and a non-modal click-to-play playback window. Thumbnails render on a background Metal queue (off-main, no UI freeze); settings persist.
  • Video export (emberweft export): render flame animations directly to MP4/MOV (H.264 + HEVC) via AVFoundation, with progress, cancellation, long-form segment+concat, and batch (--jobs). Frames are byte-identical to animate (--frame N --png mastering path).

Planned (M5, M7+):

  • macOS screensaver bundle
  • Music-video mode: offline + realtime audio-reactive

Why native Metal?

Apple Silicon's unified memory lets Metal compute shaders read and write the renderer's histogram buffers with no CPU–GPU copies, so a data-parallel fractal-flame pipeline runs at interactive framerates for far less energy than a CPU-only renderer. Emberweft is also built test-first: a portable CPU reference renderer is validated against the original flam3, and the Metal path is validated against the CPU one — see development-approach.md.

Status & Roadmap

Milestone Status Description
M0 ✅ Done Docs + repo scaffold
M1 ✅ Done CPU reference renderer + emberweft CLI (validated vs flam3)
M2 ✅ Done Metal compute renderer + Metal↔CPU parity
M3 ✅ Done Animation (loops + transitions) + realtime adaptive pipeline
v0.1.0 ✅ Done Real-genome parity (highlight_power / filter), motion blur, 4 more variations
v0.1.1 ✅ Done Corpus-variation coverage (57/99 — 100% of ES-corpus-used variations)
v0.1.2 ✅ Done Full flam3 variation coverage (99/99) — all validated ≥38 dB vs flam3 + Metal↔CPU
v0.1.3 ✅ Done Fix: Metal empty-frame regression on fragile multi-xform animations (const-ref GPUXform in kernels)
v0.1.4 ✅ Done Fix: Metal Float-overflow collapses in 15 hyperbolic/trig/exp variations (clamp args to ±88)
v0.1.5 ✅ Done Fix: transition endpoint faithfulness — Transition(A,B,1.0) now = B (mergeLog per-param INTERP + padding-final fields + propagate paletteMode)
v0.1.6 ✅ Done Fix: transition smoothness — Quality field interpolation + .log det guard + endpoint padding-final drop
v0.1.7 ✅ Done Transition-faithfulness audit (no remaining INTERP gaps) + Camera.scale log-space (perceptual, Weber-Fechner)
v0.1.8–v0.1.9 ✅ Done Loop→transition boundary: port flam3's seqflag shortcut (v0.1.8), revert the offline sharp-frame regression (v0.1.9)
v0.1.10 ✅ Done Fix: seamless boundaries — clip one-sided variation "leaks" (the blur-invariant over-bright at loop↔transition boundaries)
v0.2.0 ✅ Done M4 (part 1): SwiftUI app first slice: library browser + click-to-play (off-main Metal thumbnails); curate CLI
v0.3.0 ✅ Done M4 complete: sidebar browser, multi-select, tri-state sentiment, search/filter, drag-drop import, collections + reorder, non-modal playback window
v0.3.1 ✅ Done M4 polish: configurable preview presets + live FPS readout (both playback windows); testFiniteDeterministicRenders crash fix (intTrunc guard)
v0.3.2 ✅ Done M4 polish: distinct preview/export quality in Settings, per-parameter help tooltips, ⌘, shortcut-collision fix, make dist target
v0.4.0 ✅ Done M6: emberweft export to MP4/MOV (H.264 + HEVC), long-form concat, batch; FramePlan extraction; ThreadSeedBudget acceleration
M4 ✅ Done Native SwiftUI generative-flame studio
M5 Current macOS screensaver bundle
M6 In progress Export pipeline + codecs: engine + CLI shipped v0.4.0; GUI export sheet + progress UI pending
M7 Planned Music-video / audio-reactive (offline + realtime VJ)
M8 Planned 4K/HDR, vertical/social presets, local genetics/breeding

See full details in docs/engineering/roadmap.md.

Build & run

Requires macOS 26 on Apple Silicon (M1+) and Swift 6.2.

swift build                  # build
swift run emberweft render Tests/Goldens/genomes/sierpinski.flam3 -o out.png
swift run emberweft render Tests/Goldens/genomes/sierpinski.flam3 -o out.png --backend metal --size 160x100
swift run emberweft animate --frames 480 --segments 4 --backend metal --out seq/   # PNG sequence + manifest.json
swift run emberweft --list-backends

The app (M4)

swift run emberweft-gui      # launch the SwiftUI app

The sidebar switches between All (unified), Library (curated 24-genome bundle), ★ Liked, Imported, and each folder you open (Open Directory… → point at genomes/electric-sheep/sheep/ for the full flock; open several at once). Drag-and-drop .flam3 files in to import them. Click a thumbnail to open a non-modal realtime playback window (browse and rate while it plays); filter by name / sentiment / category / palette; multi-select (/shift/⌘A) for bulk Like/Dislike or to Save as Collection; mark each genome with a tri-state sentiment (👍/○/👎). Collections play as a loop+transition sequence in their own window. Keyboard: Space, Esc, +/0/, ⌘1–4, ⌘?. Thumbnails render off-main (Metal background queue) so the UI never freezes; settings persist across launches.

--backend cpu is the default for the CLI. metal is used when a Metal device is available (check with --list-backends). animate honors --temporal-samples N for motion blur (defaults to the genome's value on CPU; capped at 64 on Metal).

Generating animations (loops & transitions)

emberweft animate writes a PNG sequence + manifest.json to --out; mux to MP4 with ffmpeg. Segments alternate loop → transition → loop → … (even segments loop one sheep, odd segments morph between two). Motion blur is --temporal-samples N.

A single sheep loopsheep_loop: the genome rotates one full turn over the segment:

swift run -c release emberweft animate sheep.flam3 \
  --segments 1 --frames 160 --loop-cycles 1 \
  --backend metal --size 1280x720 --quality 500 --temporal-samples 32 --out loop/
ffmpeg -framerate 30 -i loop/%06d.png -c:v libx264 -pix_fmt yuv420p -movflags +faststart loop.mp4

An edge / transition between two sheepsheep_edge: loop A → morph A→B → loop B:

swift run -c release emberweft animate a.flam3 b.flam3 \
  --segments 3 --frames 160 --loop-cycles 1 --selector sequential \
  --backend metal --size 1280x720 --quality 500 --temporal-samples 32 --out edge/
ffmpeg -framerate 30 -i edge/%06d.png -c:v libx264 -pix_fmt yuv420p -movflags +faststart edge.mp4

A sequence of many sheep — the Electric Sheep model (long-form video). Pass N genomes with --segments 2N−1; loops and transitions alternate over all of them:

swift run -c release emberweft animate s1.flam3 s2.flam3 s3.flam3 s4.flam3 \
  --segments 7 --frames 160 --loop-cycles 1 --selector sequential \
  --backend metal --size 1280x720 --quality 1000 --temporal-samples 32 --out flock/
ffmpeg -framerate 30 -i flock/%06d.png -c:v libx264 -pix_fmt yuv420p -movflags +faststart flock.mp4
  • --segments 1 = loop only (one sheep); --segments 3 = loop + transition + loop (needs ≥2 genomes). For N genomes use --segments 2N−1. Default --segments 3.
  • --frames N = frames per segment (one loop revolution over N frames; 160 @ 30 fps ≈ 5.3 s). --loop-cycles N = N revolutions per loop segment.
  • --temporal-samples N = motion-blur sub-passes (defaults to the genome's temporal_samples on CPU; capped at 64 on Metal). Omit or set 1 for sharp frames.
  • --selector sequential walks the library in order (similarity does ε-greedy pairing; needs --library <dir>).
  • Use --backend cpu for byte-deterministic offline renders (uncapped temporal samples); metal for speed.
  • Seamless transitions need --temporal-samples ≥ 16 (motion blur). Lower reads as a hard cut. Since v0.1.10, one-sided variation "leaks" are clipped so loop↔transition boundaries match the loops (see CHANGELOG).
  • Re-render a single frame after a change with --frame N (writes only 00000N.png, skips the rest): render it, copy it over the old PNG in the sequence, re-mux.

Full flag reference + the sheep_loop/sheep_edge mapping: docs/rendering/animation.md.

Exporting video (M6)

emberweft export renders flame animations directly to MP4/MOV via AVFoundation. It reuses the same deterministic renderers as animate, so exported frames are byte-identical to animate --frame N (the --frame N --png path is the byte-exact mastering pin). The encoded file is NOT byte-stable across machines/OS versions; for byte-exact mastering use animate to PNG + ffmpeg.

# A single sheep loop to MP4
swift run -c release emberweft export sheep.flam3 --segments 1 --frames 160 \
  --backend metal --resolution 1080p --fps 30 --quality genome \
  --temporal-samples 32 --out loop.mp4

# An edge (loop A -> morph A->B -> loop B)
swift run -c release emberweft export a.flam3 b.flam3 --segments 3 --frames 160 \
  --backend metal --resolution 1080p --temporal-samples 32 --out edge.mp4

# Long-form (chunked + passthrough concat) and batch
swift run -c release emberweft export flock/*.flam3 --segment-frames 1600 --out long.mp4
swift run -c release emberweft export --jobs manifest.json --out /tmp/batch/ --fail-fast
  • --codec h264|hevc (default h264; HEVC falls back to H.264 on unsupported hardware, or errors with --strict-backend).
  • --quality genome (faithful default, byte-matches animate) or --quality N (samples-per-pixel).
  • --temporal-samples N for motion blur (defaults to the genome's value; essential for seamless transitions).
  • --segment-frames N enables long-form (chunked render + passthrough concat, no re-encode).
  • --jobs manifest.json runs a batch serially (continue-on-failure by default, or --fail-fast); each out is path-sanitized under --out.

Validation

Emberweft is built test-first against two oracles: the CPU reference matches flam3, and Metal matches the CPU reference.

Gate Result
CPU reference vs flam3 goldens 51–72 dB PSNR, SSIM ≈ 1.0
Real ES genomes vs flam3 (v0.1.0) 49–52 dB PSNR across 7 gen-248 fixtures (≥ 38 gate)
Metal vs CPU (end-to-end) 39–60 dB / SSIM ≥ 0.95 over 6 frozen genomes + fuzz
Metal display vs CPU tone-map (same histogram) byte-exact (inf dB)
Metal chaos histogram vs CPU count correlation > 0.999
MSL ISAAC vs Swift ISAAC byte-identical stream
Animation vs flam3-animate (loops + transitions) 43–58 dB PSNR
Realtime capability (M3 gate) ≥ 58 fps sustained @ 1080p (M2 Max)
Within-backend determinism byte-identical output across runs
Metal speedup vs single-threaded CPU (1080p) 12–18×

The local test suite is the source of truth (320+ tests, all green). GitHub is a plain git mirror; see testing.md.

Documentation

Overview

Architecture

Rendering

Playback

  • Playback Modes — real-time, cached, and screensaver modes
  • Formats — resolutions, aspect ratios, and output containers

Export

  • Export Pipeline — encoding, quality settings, and batch rendering
  • Music Video — audio-reactive rendering and offline processing

Platform

  • Screensaver — macOS ScreenSaver.framework integration
  • App UI — SwiftUI/AppKit interface and controls

Library

  • Seed Library — curated genome collection and metadata
  • Genetics — mutation, crossover, and evolution

Engineering

  • Development Approach — methodology, build order, GPU strategy, testing
  • Testing — test methodology, oracles, and the local pre-merge gate
  • Tech Stack — Swift 6, Metal 4, AVFoundation, dependencies
  • Project Layout — source organization and conventions
  • Performance — benchmarks, profiling, and optimization targets
  • Roadmap — milestones and timeline
  • Glossary — domain terminology

License

Tech Stack

Swift 6 · Metal 4 (compute) · SwiftUI/AppKit · AVFoundation · Accelerate · macOS 26 · Apple Silicon (M1 or later)

Contributing

Emberweft is source-available under PolyForm Noncommercial — free to study, use, and modify for noncommercial purposes; commercial use requires a commercial license.

  • Contributions are welcome once the project's Contributor License Agreement (CLA) is in place (added at the M0 bootstrap). The CLA preserves the maintainer's commercial option — a necessity under a noncommercial license. See CONTRIBUTING.md.
  • By contributing you acknowledge the noncommercial license terms and the CLA requirement.
  • Questions or ideas? Open a GitHub Issue, or pick a slice from the roadmap.

License, Credit & Trademarks

Code: PolyForm Noncommercial 1.0.0source-available, free for noncommercial use; commercial use requires a commercial license. Curated seed library: CC-BY-NC 4.0. Emberweft is not "open source" (OSI); it is source-available.

The fractal flame algorithm was created by Scott Draves in 1992. "Electric Sheep" and "Infinidream" are trademarks of Scott Draves / e-dream, inc. Emberweft is an independent re-implementation, format-compatible with .flam3, and is not affiliated with, endorsed by, or derived from the Electric Sheep or Infinidream source code or servers.

Full details: docs/license-and-attribution.md.

References

Algorithm & primary sources

Related clients (study, not bundled)

Content ecosystem (commercial precedents for long-form / 4K / relaxation use cases)


M0–M4 are complete; M6's export engine + CLI shipped (v0.4.0): the CPU reference renderer, the Metal compute renderer, animation + realtime playback, motion-blurred real-genome parity, the full native SwiftUI studio (sidebar browser, multi-select, tri-state sentiment, search/filter, drag-drop import, collections, non-modal playback with configurable preview presets + live FPS), and video export to MP4/MOV (emberweft export, H.264 + HEVC, long-form, batch) all work today. The M6 GUI export sheet, and M5 (the macOS screensaver bundle), are next: see the roadmap.

About

A native macOS, Apple-Silicon-GPU fractal-flame dream machine, with Metal acceleration.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages