-
March 19, 2026
2026-03-19 What happened Spent the day porting fast-vj to WebAssembly via Emscripten. It works — video clips play, shaders run, OSC arrives over a WebSocket bridge — but there's an unresolved slowdown over time that I never tracked down. The port lives on the wasm-port branch and isn't merged into main. Phase 1 — build scaffolding : The CMakeLists.txt gained…
-
March 18, 2026
2026-03-18 What happened Hardening for the Pi 4 target: Texture rescaling : The Pi 4 GPU caps texture dimensions at 4096×4096. Images wider or taller than that upload silently as blank. Added a check at clip load time — if either dimension exceeds the GPU limit, stb_image_resize2 downscales the image to fit before upload, with a log message showing the…
-
March 17, 2026
2026-03-17 What happened First working build. The core render loop is up: Sokol window, OpenGL context, vsync'd frame callback. Media clips scan from a directory at startup and are indexed alphabetically by type — audio .wav files, .png / .jpg images, and video either as .avi (MJPEG, mmap'd) or a directory of sequentially numbered JPEGs. OSC listener runs on a…
-
March 17, 2026
2026-03-17 What happened Added LuaJIT (with Lua 5.4 fallback). A patch is a plain .lua file loaded at startup with -s patch.lua . The engine calls on_frame(dt) every render frame and on_osc(addr, arg) for each incoming OSC event. The vj.* API exposed to Lua covers everything: vj.audio(i) , vj.image(i) , vj.video(i) , vj.gain(f) , vj.stop() for playback; vj.sample(i) and vj.fft(i)…
-
March 17, 2026
2026-03-17 What happened Pulled shader logic into its own module ( shaders.c ). Shaders load from a directory at startup, indexed alphabetically. Each file is just a void main() body — the engine prepends a standard header that injects the uniforms: image_tex , audio_tex , fft_tex , uv , u_time , and u_p[15] for user parameters. Three initial shaders beyond…
-
March 17, 2026
2026-03-17 What happened Three additions in the late session: Mic input ( -m [device] flag): ALSA capture thread feeds live microphone audio into the same waveform and FFT ring buffer as clip playback. This means every audio-reactive patch works with either a playing clip or a live mic — no code change needed. The -m flag accepts an optional ALSA…