// Changelog
Every release, documented.
Newest → oldest · curated from CI
Ghost Arcade ships fast. Every release here was signed by CI (Windows installer + notarized macOS DMGs) and pushed to ghost-arcade-releases. The in-app auto-updater catches every existing install on next launch.
Keyboard control, VJ sequencer, and release UI polish
- ▸Keyboard control joins MIDI and OSC as a first-class control surface: key combinations persist per project and dispatch through the shared mapping router for VJ, mapping, and performance workflows.
- ▸VJ Layer Sequencer adds a BPM-synced step grid for opacity gating, with the sequenced output wired through live output, offline rendering, and Stage 3D recording paths.
- ▸VJ mode now has a vertical A/B crossfader and a Plugins tab that mirrors the editor Media Library, making performer-mode browsing and deck blending line up with the main editor.
- ▸Long recording exports are safer: segmented JPEG encoding plus concat output reduces ffmpeg memory pressure during bigger renders.
- ▸Release UI polish tightens the responsive VJ header, scales macro bank controls cleanly, and moves snapshots into the clip-grid toolbar.
- v1.9.3GitHub release ↗
FM Lines effect, SVG 3D level-up, and fixed-size Stage 3D recording
- ▸FM Lines joins the Stylize catalog as a luminance-driven line-displacement effect: bright areas push scanlines off baseline and modulate sine frequency and amplitude for an FM-portrait look, with horizontal, vertical, and concentric modes.
- ▸SVG layers now support 3D extrude mode with beveled solids, perspective camera controls, PBR-style material presets, light rigs, auto-spin, and floating motion while preserving the classic flat default for existing projects.
- ▸SVG rendering adds fluid and flow fills, volumetric particle fill, dashed / gradient / double / tapered / glow-pulse outlines, electric / orbital / beaded / gravity / dataflow connectors, and organic warp / breathe / growth motion.
- ▸Stage 3D recording is decoupled from project output resolution: the recorder renders a dedicated fixed-16:9 pass at 1080p or 4K through its own bloom composer, so captured venue footage stays clean and predictable.
- v1.9.2GitHub release ↗
Show director, ModTray modulation, camera flight + premium venues
- ▸Show director runs designed lighting looks (unison, alternate, fan, chase, punch, searchlight) and advances cues on 16-beat musical phrases; the palette derives live from the LED screens, so firing a new clip re-colors the whole rig and calls a new cue.
- ▸Atmosphere FX toggles per scene — volumetric mover beams with real pan/tilt drive, truss laser fans, hazer-style fog ease, and segmented pixel-strips on every truss. New parametric LED Strip library element (length, pixel count, fill/chase/pulse/solid, glow, palette sync).
- ▸ModTray modulation popover replaces the cramped inline controls on every parameter surface: audio bands and onsets, LFOs with free-Hz or BPM-synced musical divisions (tap tempo, MIDI clock and Ableton Link all drive it), invert, live signal meter. Fixed depth/speed writes that were silently dropped for clip-keyed and mapping-keyed modulations.
- ▸3D stage camera flight: vertical pan and truck on the arrow keys, FOV slider + Shift-scroll (15-120°) — frame the whole Sphere dome from inside. Arena, club and nightclub venues rebuilt with raked seating bowls, bars, mezzanines, DJ booth and per-piece selectable scenery; floor z-fighting fixed.
- ▸MilkDrop-style smoothed audio response now covers the last raw paths (stage-effect evaluators), and range-slider fills track programmatic value changes everywhere.
- v1.9.0GitHub release ↗
Multi-slice atlas fan-out, Ableton Link, Demo Reel + Sphere venue
- ▸Multi-slice zero-copy atlas fan-out — one hidden compositor renders every Spout/Syphon sender slice into a single atlas texture; a native fan-out class (SpoutAtlasOutput on Windows, SyphonAtlasOutput on macOS) sub-blits each tile into its own named texture-share sender every paint. Cost is one shared-resource open + N GPU sub-copies — flat per slice, zero CPU pixels. Verified end-to-end against Spout receivers on Windows and MadMapper on Apple Silicon.
- ▸Ableton Link — bidirectional LAN tempo sync. Ghost Arcade joins any Link-enabled session (Ableton Live, Resolume, Rekordbox, etc.) and both follows and broadcasts beat/phase, so the visuals lock to whatever drives the room without manual BPM setup.
- ▸Stage 3D Demo Reel — shot-based offline MP4 sizzle-reel recorder. Sequence camera shots through the stage, hit record, and Ghost Arcade ticks the scene at fixed timestep into an offline canvas, encoding a clean MP4 without dropping a single frame at runtime — polished pitch reels straight from the editor.
- ▸Sphere venue — true 3/4-sphere dome screen + stadium bowl geometry joins the existing flat / arena / stage venues, so projection-mapping previsualization covers dome installs and immersive room formats.
- ▸Performance: async PBO slice readback (render thread no longer stalls on GPU readback), async LED glow readback, OSC IPC batching, render-loop allocation diet (cached VJ→layer injection, memoized id parse), VJ modulation hot path with no per-tick grid clones (was 120-240 store clones/sec), and a memory-leak batch covering video element release on clip overwrite, bounded shader-input cache, ISF image-input texture disposal, and thumbnail cleanup.
- ▸Stage 3D polish: venue defaults are now fully editable + listed in the inspector tree; drag persists for scenery pieces (was snapping back every frame via a broken target lookup); unified Y-corner convention across 2D mapping and Stage 3D so LED placement matches the warp; LED glow upgraded from a hard spotlight to a soft area light that tracks panel color; multi-select layers now actually highlight in the tray; Stage 3D dev-mode window loads from the Vite dev server; Gravity Wells shader output fix.
- v1.8.1GitHub release ↗
Stage-scene recording, Syphon validation, clean desktop installers
- ▸Stage 3D now records the whole rendered scene instead of only the flat output, so proposal videos can show screens, stage geometry, and live visuals together.
- ▸Mac Syphon input from MadMapper and Syphon output to MadMapper/Resolume were validated on Apple Silicon, with the bundled universal Syphon.framework preserved for release packaging.
- ▸The native iOS/Android app now builds through its own `native-mobile` workspace, `native-mobile.html` entry, Vite config, and type-check target. Desktop builds exclude Capacitor-only entrypoints while the browser-based desktop mobile companion remains in the main app.
- ▸Release packaging drops tracked iOS DerivedData/build output and ignores regenerated mobile artifacts, reducing installer risk on Windows/macOS CI while keeping the mobile project available for dedicated app work.
- v1.7.2GitHub release ↗
Linux build (AppImage + .deb) + MediaPipe desktop fix
- ▸Linux AppImage (single-file portable) and .deb (native Ubuntu/Debian package) added to the release pipeline. Same artifact-name template as Win/Mac (Ghost-Arcade-${version}.AppImage / ghost-arcade_${version}_amd64.deb) so the website's download URL templating stays predictable.
- ▸CI gains a build-linux job on ubuntu-latest mirroring the Win/Mac pattern: native-addon build, NDI Advanced SDK install from private storage URL, Vite frontend build, electron-builder packaging, upload to ghost-arcade-releases. NDI works on Linux (Spout is Windows-only, Syphon is macOS-only; the CMake branch silently no-ops for those on Linux).
- ▸MediaPipe WASM URL fix — production Electron builds load via file:// where window.location.origin is "null", which broke the WASM loader's URL resolution and silently disabled the hand-tracking pipeline on every shipped desktop binary since v1.7.0. Bug was masked by dev-server testing (where origin is a valid http://localhost). Fixed by resolving against document.baseURI instead, which inherits vite.config.ts's base: "./" Electron path. If you tried MediaPipe gesture binding on a desktop build and it didn't work, update to v1.7.2.
- ▸No signing on Linux (no Authenticode/notarization equivalent in mainstream distros). MediaPipe / WebGPU / Web Audio all run under Chromium on Linux without code changes — the GPU shader layers, HandFX visualizer, MediaPipe gesture pipeline, and every binding flow work identically to the other platforms.
- v1.7.1GitHub release ↗
MediaPipe gesture input, HandFX visualizer, plugin tier expansion
- ▸MediaPipe hand-tracking pipeline — off-thread WebGPU hand-landmarker worker with adaptive per-landmark smoothing + forward prediction for low-latency tracking, anti-backlog frame pacing so inference can't snowball into stale frames, and a handedness-swap fix so palm.right.x actually follows your right hand under selfie mirror. Bindings live in a project-file-persisted bus that routes any signal (palm position, pinch, intra-hand finger spread, hands distance, gestures) to any param via the shared MIDI path scheme — bind once, controls every layer the path resolves to.
- ▸HandFX visualizer with five modes: paint (velocity-driven brushstrokes + curl-noise sparks that linger), ink (drifting smoke blobs additive-blended at fingertips), skeleton (neon bone overlay with halo fingertips), pinch-spray (continuous particle spray from the pinch point), and panel (white rectangle between palms — pair with Difference blend for the inverted-world look). Optional camera-feed background, mirror-aware compositing, zero on-canvas help text so projection stays clean.
- ▸Floating MediaPipe Learn modal with a sticky signal picker and orange-outlined param overlay (hit-tested with elementFromPoint so covered UI doesn't bleed through). Multi-bind workflow — pick a signal once and tap N params to wire them all to the same gesture. "Load defaults" maps four signals to Macros 1-4 so any project gets a hand-driven mixer for free.
- ▸Plugin tier expansion: AudioMotion (spectrum analyzer), Wave.js (waveform visualizer), Hydra (live-coded video synth with preset library + on-the-fly editing), Milkdrop (Butterchurn preset playback + per-stem audio routing), GhostFX (original WebGPU drift), and AnalyzerLab (audio signal explorer). Every new plugin is full-stack: param schema, modulation-aware UI row, project-file persistence.
- ▸GPU shader-layer params reached parity with effect and shader params for binding + modulation: MIDI / MediaPipe / OSC dispatch via map:gpu:*, manual/audio/auto source dropdown on every slider, auto-mode sweep with slipper handles, ranges registered per shader so audio modulation scales to native span. Bonus: a Background Opacity slider per GPU layer that luminance-keys the dark areas transparent so the layer below shows through.
- ▸Repo hygiene: stripped ~180 MB of unreferenced sample / marketing / model directories from the source tree (flow, TestModels, PLY, brand-assets, 30pack, and a dozen smaller dirs) without touching anything the desktop build actually ships. Removed marketing PDFs, old logos, internal handoff docs, and stale diagnostic captures.
- v1.7.0GitHub release ↗
Zero-copy master warp + dome reprojection + per-screen WebGPU output
- ▸Master warp inside the WebGPU present shader — the corner-warp + mesh-warp pipeline that previously ran a GPU→CPU→GPU readback now executes in the same fragment shader as the editor's final composite. The captured canvas is already the warped output, so every downstream consumer (Fullscreen output, per-screen displays, Spout/Syphon/NDI senders) inherits the warp without any additional pass. Degenerate-quad and NaN-mesh fallbacks bail to passthrough instead of total blackout, so a wild drag is recoverable instead of going dark.
- ▸Dome projection moved into the WGSL master pass. Four reprojection modes are exposed (equidistant fisheye, stereographic, orthographic, equirectangular panorama) with rotation, tilt, FOV, curvature, and edge-fade controls. The Three.js engine's dome path is automatically disabled when the WebGPU bridge owns reprojection, so dome is applied exactly once per frame.
- ▸Multi-target output presenter — the editor's captureStream now fan-outs each VideoFrame to N attached output windows via VideoFrame.clone (refcount bump, still zero-copy on the underlying GPU buffer). Fullscreen and an arbitrary number of "Open on display" projector windows can be open simultaneously, each receiving the editor's already-warped frames. Per-port failures detach that target without affecting the others.
- ▸Per-screen slice display rewritten as a same-process WebGPU receiver. When the slice window is opened via window.open from the editor it shares the renderer process, runs the same MessagePort handshake as Fullscreen, and renders the received frame through its own WGSL pipeline that crops to the slice's region in a single GPU sample — no fragile hidden-canvas texture upload, no readback. A createImageBitmap fallback covers the case where the slice's WebGPU init fails.
- ▸Output screen setup (Screens, master canvas size, master warp) saves and restores with the .gha project file, so a complete projection-mapping rig — slice rectangles, edge blend, rotation, warp geometry — travels with the show file. Per-launch defaults stay clean (empty Screens + identity warp) so opening an unrelated project doesn't inherit yesterday's rig.
- v1.6.0GitHub release ↗
VJ-layer effects in map-mode + WLED output + grouped Settings nav
- ▸VJ-layer effects in map-mode — when a mapping preset references a VJ clip, that clip's effect chain (color, distortion, audio-reactive modifiers) now applies on the map-mode render path the same way it does in performer mode. Previously the effects were stripped during the preset clone, so map-mode showed the raw clip without its tuned look. Also caches the cloned preset layers across frames so videos referenced inside presets no longer rewind/freeze on every render.
- ▸WLED output transport — Ghost Arcade can now drive networked WLED strips directly. Map output pixel rows to LED segments; brightness and color sampling track the projector output in real time. Lets one show drive both a projector / wall + an ambient LED rig from the same composite.
- ▸Settings sidebar refactored into grouped categories — the flat settings list became unwieldy at this scale, so it's now a left-side category nav (Output, Performance, Mobile, Experimental, etc.) with the active group rendered to the right. Cuts the time-to-find-a-setting from "scroll-and-scan" to one click.
- ▸Fixes — Syphon/Spout zero-copy vs CPU-fallback state now logs visibly so you can spot a driver-level fallback at a glance; MIDI mapping-preset + stage-preset trigger routes were silently dead and are now wired up; the recorder warms up captureStream before MediaRecorder.start so the first second of recordings is no longer empty; missing IPC handlers added to the preload allowlist that were rejecting at the bridge layer.
- v1.5.0GitHub release ↗
Magpie Bloom ISF + light-painting composite & freeze fixes
- ▸Magpie Bloom — new ISF generator inspired by Andy Thomas's Visual Magpie reel. Domain-warped SDF coral body with 80 procedural particle orbs (deterministic seeds, wrapping vertical drift so they flow through the form continuously), screen-space lightning bursts (turbulence threshold + time-quantized jitter so flashes look like discrete bursts not continuous static), and a body emission glow that lights the form from within on bass. Audio channels are independently gated: bass → emission + form pulse, mids → lightning amplitude, highs → particle brightness. All bands graceful-no-op without audio.
- ▸Magpie Bloom perf pass — 2-3× faster than the first cut. Body raymarch 56 → 40 steps, normals 6-tap central diff → 4-tap tetrahedral (33% fewer SDF calls per normal), domain-warp fbm4 → fbm2 (4× fewer noise samples per warp call, and there are 3 warps per SDF), bounding-sphere early-out so periphery pixels skip the body entirely, plume raymarch 26 → 16 steps. Net body SDF hot-path cost dropped from ~6944 hash calls/pixel to ~2464, with the bounding-sphere roughly halving the average again. Browser preview also gains mic input via Web Audio for live driving all three audio channels.
- ▸GPU light-paint brushes (spiral / firefly / sap-flow / water / smoke / galaxy / nebula / sparkle / vortex / plasma / flame / electric / ribbon / particle) now composite at the layer's z-slot. Previously they were painted as a final overlay on top of the fully-composited bridge frame inside WebGPUCanvas, so any layer stacked above the light-painting layer got covered by the brushes. The brushes now render into an offscreen, transparent-cleared WebGPU canvas and are handed to the engine as a THREE.CanvasTexture, composited additively at the layer's z — so layers above light-paint now occlude the glow exactly like any other content. As a bonus, brushes now also inherit the layer's composite opacity (hiding/fading the light-paint layer affects them too).
- ▸GPU brushes now honor the output Freeze button. The top-toolbar Freeze (and mobile pause pill) sets outputFrozen, and Canvas.svelte's WebGL animate() loop already gated on it — but WebGPUCanvas's own RAF (which drives the GPU compute brushes) never checked the store, so brushes kept simulating over a frozen background. WebGPUCanvas now skips presentFrame() entirely while frozen, so the present canvas retains its last composited frame — total-freeze parity with the WebGL path. RAF keeps rescheduling so unfreeze resumes instantly.
- v1.4.0GitHub release ↗
Auto playhead everywhere + VJ effect parity
- ▸Auto playhead everywhere — the LFO-style "Auto" source that sweeps a parameter between a min/max sub-range is now selectable on every numeric param across the app: mapping + VJ effect params (both deck banks, per-clip routing), edge effect params (stroke / fill / animation), mapping-mode shader inputs, and VJ clip shader values. Auto sits at position 2 in the source dropdown (under Manual) on all three editor surfaces.
- ▸Automation re-architected to live ON the data it animates (effect.paramAuto, edgeEffect.paramAuto, source.shaderValueAuto, clip.shaderValueAuto) rather than in a side modulation map keyed by layer index. The old index-keyed design broke on layer reorder/delete and produced cross-mode collisions; the new design means save / load / reorder / mode-switch all round-trip for free. A single autoEngine RAF walks every layer's paramAuto each frame and writes resolved values directly into the params.
- ▸VJ effect parity — the "No adjustable parameters" dead-end in performer mode is fixed. VJModePanel now mirrors LayerPanel's param-lookup chain, so the 41 newer effects render their full slider grids in VJ mode the same as they do in mapping mode.
- ▸Fixes along the way: per-layer Auto now runs independently on as many layers as you activate it on (was previously stopping on all but the most-recently-activated layer); VJ ↔ mapping parameter ranges are namespaced so switching modes no longer freezes the other mode's running playheads; effect mods route through the correct mapping vs VJ path (this had quietly broken audio modulation on mapping-mode effects too, not just Auto); macro knob fill arc no longer bleeds outside its ring between 50–67% travel.
- v1.3.5GitHub release ↗
Render to Video, loop creator solidified, update checker fix
- ▸New File → Render to Video pipeline. Pick filename, duration, fps (24/30/60), resolution (720p/1080p/1440p/4K/square/vertical/custom), and quality tier. Deterministic frame-by-frame render: engine iTime, ISF shader TIME, stage-effects tick, keyframe timeline, and sequencer all step by exactly 1/fps per virtual frame. No drops, exact timing, any resolution.
- ▸JPEG-per-frame intermediate (q=0.92) keeps ffmpeg.wasm under its 2GB heap — raw RGBA OOM'd at 1080p past a few seconds. Final encode is libx264 + yuv420p MP4; output lands in the media library AND auto-downloads.
- ▸Video Loop Creator solidified: FFmpeg core now vendored locally via Vite ?url imports (the CDN-fetch path was failing under Electron's renderer CSP / file:// origin), per-call progress handler binding (the old handler closed over the first caller's callback forever), phase-aware monotonic progress bar (load → probe → render → read, no jumping back to 0%), FFmpeg-log time= parsing for smooth xfade progress, strict clamping at every external-data ingest (no more >100% or NaN readings), 60s watchdog so silent hangs throw a clear error instead of waiting forever.
- ▸Update-checker fix: users on v1.3.1 were seeing "v1.1.3 is available" because getCachedVersionResult returned a stale cache from a previous install. Cache now invalidates when stored current ≠ runtime version, and hasUpdate is re-derived from compareVersions(latest, runtime) at every read so a corrupted cache can't fake an upgrade prompt.
Windows build fix (v1.3.0 fast-follow)
- ▸Fixes the v1.3.0 Windows installer build — the Syphon install_name_tool POST_BUILD step was orphaned into the NDI SDK-not-found branch when NDI bundling was added, blowing up Windows CI (which doesn't have the SDK). Mac users on v1.3.0 are unaffected.
- ▸If you grabbed v1.3.0 on Windows in the ~11-minute window between releases, re-download the installer.
Stage Designer, Stage Effects, OSC + NDI, mapping precision
- ▸New Stage Designer — full-screen workspace for polygon slice layouts with pen tool, bezier-vertex editing, SVG import, scale + rotate handles, 8 one-click templates (Wall of Circles, Triptych, Hexagon Wall, Concert Stage, Pillar Array, Diamond Grid, more). Apply Stage spits out Screen (VJ Output) mapping layers wired to vjLayerIndex, so VJ clips flow through the slice geometry.
- ▸Stage Effects — dedicated VJ tab with a 16-effect catalog (Still, Radial Pulse, Chase, Strobe, Twinkle, Sine Wave, Beat Pulse, Spiral, Cascade, Random Hits, Breathing, Checker, Inverse Pulse, Split Flash, more). Single-active radio mode + BPM-synced auto-cycle scheduler so the rig walks through your effect set in time with the music. Stage presets capture the full effects bundle alongside the slice layout.
- ▸OSC integration — UDP listener in Electron main with a pure-JS parser (no native deps). Settings → OSC tab gives you enable / port / live status + a bindings table with Learn mode. Routes through midiRouter.dispatchPath, so every MIDI-mappable parameter is OSC-reachable out of the box (TouchOSC, Lemur, Vezér, your DAW).
- ▸NDI integration — native addon (sender + receiver) for cross-platform network video streaming. macOS bundles libndi.dylib into Frameworks with ad-hoc codesign; Windows ships Processing.NDI.Lib.x64.dll alongside the addon. VJ tray gets an NDI button → discovers network senders via mDNS → drag onto a clip cell → live frames render through the engine. The addon only builds + ships when the NDI Advanced SDK is present at compile time; installs without the SDK keep working unchanged.
- ▸Mapping precision — pixel-grid snap (free / sub / 1px / 5px / 10px) in PROJECT pixels (consistent across editor zoom). Arrow-key nudge respects the same granularity; Shift = 10× for gross positioning. Double-tap a corner on touch (or double-click on desktop) for an on-canvas arrow pad with 44px hit targets. Polygon mask cap raised 64 → 256 and the engine now budgets bezier tessellation, so dense SVG paths render without mask truncation; SVG `<circle>` and `<ellipse>` primitives import as exact 4-cubic-bezier polygons instead of faceted polylines.
- v1.2.0GitHub release ↗
VJ MAP sub-mode, continuous sequencer rows, preset resume
- ▸New MAP sub-mode in the VJ launcher (third option next to MIX / STAGE): firing a saved composition swaps the mapping topology and occupies a VJ-layer slot — multiple mapping presets stack with per-layer opacity + blend mode.
- ▸Composition save now snapshots transport state. If the sequencer or keyframe timeline was playing at save time, the playhead resets to 0 and auto-resumes on load.
- ▸Per-layer continuous mode (∞) on the sequencer. The cell gates the layer’s composite alpha instead of its opacity, so shader uniforms keep advancing across off→on transitions.
- ▸Preset cards get an explicit Update button + right-click menu (Update / Load / Rename / Delete) — overwrite is no longer reachable by muscle memory.
- ▸Fixes: Delete key removes the selected keyframe (not the whole layer); dragging a corner past its opposite now mirrors instead of going black; shape masks re-apply after effects so blur/glow bleed gets clipped to the shape.
- v1.1.3GitHub release ↗
Mapping grid under WebGPU, light-paint edit mode, planet shader perf
- ▸Mapping grid renders correctly when the experimental WebGPU editor is on — the overlay used to silently render into the void.
- ▸Light-painting path-edit toolbox: Move / Delete / Insert tools, marquee select, group translate, keyboard delete, white-halo handle visibility against bright glow strokes.
- ▸Recent files: clicking a recent entry now loads directly (absolute path captured on save) instead of re-prompting the picker.
- ▸Settings: experimental GPU toggles show a "Restart required" banner with an in-app restart IPC, so toggling no longer leaves the app bricked silently.
- ▸Planet shader: cloud raymarch ~2.5–3× faster, surface pass ~2.5× faster on Apple Silicon — invisible visual delta, ~5–7× total lift on default Earth.
Older releases and the full git history live on GitHub. Ghost Arcade is AGPL-3.0 — fork, modify, ship.