acidcam-gpu is a high-performance, real-time video manipulation engine designed to push the boundaries of psychedelic glitch art. Part of the ACMX2 and libmx2 ecosystem, it uses an OpenGL/GLSL shader pipeline as its core, with an optional CUDA GPU-filter path that can be enabled at compile time on NVIDIA hardware for additional accelerated effects.
NVIDIA GPUs are no longer required. ACMX2 builds and runs on AMD, Intel, and Apple GPUs using the OpenGL/SDL2 path (
-DWITH_CUDA=OFF). On NVIDIA systems with the CUDA toolkit and an OpenCV build that includes CUDA support, you can opt in to the CUDA GPU-filter stack and FFmpeg CUDA hardware decode by configuring with-DWITH_CUDA=ON(the default when CUDA is detected).
The original project brought a massive library of "glitch" filters to digital artists. However, as resolutions climbed to 4K and filter stacks became more complex, CPU-based processing hit a bottleneck.
acidcam-gpu solves this by:
- Parallelizing the Chaos: Running effects on the GPU — GLSL shaders for the core pipeline, with optional CUDA kernels for additional GPU filters on NVIDIA hardware.
- Language: C++20
- Graphics API: OpenGL / SDL2 (cross-vendor, hardware-accelerated rendering — works on NVIDIA, AMD, Intel, and Apple GPUs)
- Optional Parallel Computing: NVIDIA CUDA (compile-time opt-in via
-DWITH_CUDA=ON; tested on RTX 2070 and newer) - Format Support: Native MX2 MXMOD 3D model parsing for real-time geometry glitching.
When built with -DWITH_CUDA=ON on a system with an NVIDIA GPU and CUDA-enabled OpenCV, ACMX2 can additionally leverage:
- Shared Memory: Fast on-chip memory to speed up neighborhood-based CUDA filters.
- Massive Throughput: Thousands of CUDA cores to apply multiple glitch layers in a single pass.
- CUDA/OpenGL Zero-Copy Interop: High-speed texture sharing between CUDA and OpenGL.
- FFmpeg CUDA Hardware Decode: Direct hardware-accelerated decoding for video files.
Without CUDA, all shader-based features continue to work — only the CUDA GPU-filter stack and CUDA-specific decode/encode paths are omitted.
- Zero-Copy Interop: High-speed texture sharing between CUDA and OpenGL.
- FFmpeg CUDA Decode Path: Prefer direct FFmpeg/CUDA hardware decode for video files, with automatic software/OpenCV fallback.
- Hardware-First Encoding: Prefer
h264_nvencwhen available, with automatic software H.264 fallback. - HDR Video Pipeline: Detect BT.2020 PQ/HLG sources, process them in HDR, and write HEVC Main10 output with HDR signaling preserved.
- Encoding Quality Controls: Preset, tune, CRF, codec mode, and realtime low-latency flags are available for recording.
- Visual User Interface Simple to use User interface
- Command line tool Command line tool
From the latest acidcam-gpu commits, current focus areas include:
- Audio spectrum history buffers: new
--enable-audio-buffers <N>option (1..22) binds rolling FFT textures asspectrum0..spectrumN-1for temporal audio-reactive shaders. - Audio startup warmup envelope: new
--audio-warm-rate <value>option fades audio-reactive uniforms/spectrum from 0 to full strength at startup (default0.51/sec, about 2 seconds). - Camera/file A/V startup sync hardening: cache and writer paths now include a startup warmup window so loading-screen frames are not pushed into
samp1..samp8, and early audio/file processing is held until warmup completes. - Texture cache behavior update:
--texture-cachenow works in camera, video, and graphic input modes (not video-only). - Shader time wrap stability fix:
time_fwrap/reset behavior now uses a large2*PImultiple to preserve long-running shader phase continuity. - Qt camera FPS persistence improvement: preferred camera FPS is now saved/restored and retained across resolution/device repopulation when supported.
- Headless and terminal workflow updates: improved silent/headless processing behavior, terminal color-coded output, and related CLI flow refinements.
- HDR pipeline refinements: recent HLG-to-HDR10 conversion work and continued HDR + silent mode stabilization.
- Startup logo splash:
data/logo.pngis displayed on launch before the shader pipeline begins, with a smooth fade-out. - Watermark overlay: embed a custom text watermark (color-configurable via RGB) in recorded video using
--use-watermarkand--use-watermark-color; also accessible from the Qt Playback menu with a live color preview. - Display-filter overlay:
--display-filterrenders the active shader name, multipass stack, and GPU filter list in the upper-left corner of both the live window and the recorded output. - Autopilot random interval mode:
--autopilot-random <N>randomizes the frame interval between auto-switches (range 4..N) for more organic live performance variation. - Sequential autopilot mode: Y key cycles the playlist in strict order rather than randomly when autopilot is active.
- Post-multipass shader navigation: Shift+Up / Shift+Down changes the shader that runs after the multipass chain without altering the playlist position.
- Qt interface improvements: Watermark Settings dialog with text input and color picker; Display Filter toggle in the Playback menu; autopilot random interval persisted in Qt session settings; YUV format options refresh automatically when the camera device changes.
- Editor and shader workflow improvements: shader reload support, shader cache rebuild path, and safer editor close behavior with save prompts.
- Qt interface productivity features: metadata viewer integration, settings text/scaling tweaks, and command edit/copy/run improvements.
- Playlist and live-control workflow: shuffle/concat/clear playlist actions, combined playlist updates, and keyboard/autopilot navigation improvements.
- Output and recording path updates: MKV output support, additional format handling, no-drop frame path work, and SDR TIFF/WebP snapshot behavior updates.
- Audio-file recording behavior hardening: explicit opt-in handling for file-mode audio recording/mux behavior.
This project is developed and tested on Bazzite Linux using Arch Linux containers via Distrobox, but it builds on any modern Linux distribution as well as macOS.
- GPU: Any GPU with working OpenGL 3.3+ drivers (NVIDIA, AMD, Intel, or Apple Silicon). NVIDIA hardware is optional and only required if you want to enable the CUDA GPU-filter stack at compile time.
- Drivers: Up-to-date GPU drivers for your platform. NVIDIA proprietary drivers (v535+) are required only when building with
-DWITH_CUDA=ON. - Environment: Arch Linux (or compatible). Install all dependencies via
pacman:
Build Tools:
sudo pacman -S --needed base-devel git cmake ninja pkg-config curl unzipNVIDIA & CUDA (optional — only needed for -DWITH_CUDA=ON):
sudo pacman -S --needed nvidia-utils cudaOpenCV:
# Stock OpenCV (works for the default OpenGL-only build):
sudo pacman -S --needed opencv hdf5 vtk fmt glew
# Or, if you want CUDA GPU filters, install the CUDA-enabled build instead:
sudo pacman -S --needed opencv-cuda hdf5 vtk fmt glewSDL2 & Qt6:
sudo pacman -S --needed sdl2 sdl2_ttf sdl2_mixer sdl2_image qt6-base qt6-tools qt6-multimediaGraphics, Audio & Media Libraries:
sudo pacman -S --needed glm mesa libglvnd ffmpeg rtaudio pulseaudio libpulse libjpeg-turbo libpnglibmx2 (built from source):
git clone https://github.com/lostjared/libmx2.git
cd libmx2/libmx
mkdir build && cd build
cmake .. -DEXAMPLES=OFF -DOPENGL=ON
make -j$(nproc)
sudo make installFonts:
sudo pacman -S --needed ttf-dejavu ttf-liberation noto-fontsOr install everything at once using the provided script:
sudo bash build-script/install-deps-arch.sh| Short | Long | Value | Description |
|---|---|---|---|
-v |
--help |
Display help message and exit | |
-p |
--path |
<dir> |
Assets path |
-r |
--resolution |
WxH |
Window resolution (e.g. 1920x1080) |
-d |
--device |
<index> |
Camera device index |
-c |
--camera-res |
WxH |
Camera capture resolution |
-i |
--input |
<file> |
Input video file |
-g |
--graphic |
<file> |
Input image file |
-o |
--output |
<file> |
Output video file |
-b |
--bitrate |
<crf> |
Output bitrate in CRF |
-u |
--fps |
<fps> |
Frames per second |
-e |
--prefix |
<path> |
Snapshot save prefix |
-a |
--repeat |
Loop/repeat video playback | |
-n / -N |
--fullscreen |
Fullscreen window (Escape to quit) | |
-m |
--cuda-device |
<index> |
CUDA device index |
--duration |
<seconds> |
Recording duration limit in seconds (float); stop recording and exit after elapsed | |
--encode-preset |
<name> |
Encoder preset: ultrafast..veryslow |
|
--encode-tune |
<name> |
Encoder tune: none, film, animation, grain, stillimage, psnr, ssim, fastdecode, zerolatency |
|
--encode-crf |
<0-51> |
Encoder CRF quality override (default: 18) |
|
--encode-codec |
<mode> |
Encoder codec mode: auto, software, or nvenc |
|
--encode-realtime |
Enable low-latency realtime encoding flags | ||
--no-drop |
Video-file processing: never drop frames; block when the encoder queue is full | ||
--use-watermark |
<text> |
Embed a text watermark (upper-left) into recorded video | |
--use-watermark-color |
<r,g,b> |
Watermark text color as 0-255 RGB components (default: 255,0,150) |
|
--display-filter |
Show active shader/stack/GPU filter in upper-left corner of window and recording |
| Short | Long | Value | Description |
|---|---|---|---|
-s |
--shaders |
<file> |
Shader library index file |
-f |
--fragment |
<file> |
Single fragment shader file |
-h |
--shader |
<index> |
Initial shader index in library |
--shader-pass |
<indices> |
Shader pass indices (comma-separated, e.g. 0,1,2) |
|
--playlist |
<file> |
Shader playlist text file (one shader name per line) | |
--autopilot-frames |
<N> |
Auto-switch to a random playlist node every N rendered frames (minimum 4) | |
--autopilot-timeout |
<N> |
Alias for --autopilot-frames |
|
--autopilot-random |
<N> |
Randomize autopilot interval to a value in the range 4..N frames for each auto-switch | |
--build |
<path> |
Build shader cache for specified library path and exit | |
--no-cache |
Disable shader caching (always recompile shaders) | ||
--time-speed |
<float> |
Constant time_f speed multiplier (default: 1.0) |
|
--cross-fade |
<seconds> |
Crossfade duration in seconds when switching playlist shaders (default: 0.5) |
| Long | Value | Description |
|---|---|---|
--gpu-filter |
<indices> |
GPU filter indices (comma-separated) |
--gpu-buffer |
<size> |
GPU frame buffer size (4–32) |
--list-filters |
List available GPU filters and exit | |
--list-cuda-devices |
List available CUDA devices and exit | |
--enumerate-device |
<index> |
List supported resolutions and frame rates for a camera device (Linux only) |
--disable-counter |
Disable timer and FPS counter overlay | |
--silent |
Process video without window. Only valid with -i/--input video files and requires -o/--output; camera and image input are rejected. |
| Long | Value | Description |
|---|---|---|
--texture-cache |
Enable texture cache (camera, video, and graphic modes) | |
--cache-delay |
<frames> |
Texture cache delay in frames |
--copy-audio |
Copy audio track from input to output | |
--enable-3d |
Enable 3D cube rendering | |
--model |
<file> |
3D model file (.mxmod) |
| Short | Long | Value | Description |
|---|---|---|---|
-w |
--enable-audio |
Enable audio reactivity | |
-l |
--channels |
<num> |
Audio channels |
-q |
--sense |
<float> |
Audio sensitivity |
-y |
--pass-through |
Enable audio pass-through | |
--audio-input |
<index> |
Audio input device (default or index) |
|
--audio-output |
<index> |
Audio output device (default or index) |
|
--list-devices |
List audio devices and exit | ||
--record-audio |
<file> |
Record captured audio to WAV file (used for mux, then removed after successful mux) | |
--record-gain |
<float> |
Recording volume gain 0.0–2.0 (default: 1.0) |
|
--audio-warm-rate |
<float> |
Startup audio warmup rate in 1/sec (default: 0.5; 0 disables warmup) |
|
--enable-audio-buffers |
<N> |
Allocate N FFT history textures (1..22) exposed as spectrum0..spectrumN-1 |
| Long | Value | Description |
|---|---|---|
--midi-map |
<file> |
MIDI config file (.midi_cfg) |
--midi-device |
<index> |
MIDI input device index |
--list-midi |
List available MIDI input devices and exit |
ACMX2 automatically switches to its HDR pipeline when the input stream is tagged as BT.2020 with PQ (SMPTE ST.2084) or HLG (ARIB STD-B67) transfer characteristics, or when the decoded source is a 10-bit BT.2020 format such as yuv420p10le or p010le.
On ingest, the program preserves the source HDR code values long enough to upload each frame into a 16-bit RGBA working texture. A dedicated HDR decode shader converts PQ or HLG into linear BT.2020 before your GLSL shader passes and does not run the CUDA filters since they are tied to 8 bit RGBA. After processing, a matching HDR encode shader converts the result back into the same HDR transfer family as the source.
HDR exports use HEVC Main10 rather than the standard H.264 path. MXWrite receives BT.2020 HDR frames and writes a 10-bit P010 HEVC stream with BT.2020 primaries and the original PQ or HLG transfer preserved. When the source includes mastering-display or content-light metadata, ACMX2 forwards that HDR metadata to the output stream as well.
In practice, SDR jobs still follow the H.264-first path, while HDR jobs are written as HDR HEVC so compatible players and editors continue to recognize the output as HDR. Startup logs report this explicitly with lines such as HDR output mode enabled: HEVC Main10 + BT.2020 + HLG.
--silent is the headless batch-processing mode for video files. It creates an off-screen OpenGL context, suppresses the visible SDL window, and skips display pacing so the file is processed as fast as decode, effects, and encode allow.
- Use it only with
-i/--inputvideo files. - Always pair it with
-o/--output. - Do not use it with camera capture or
-g/--graphicimage input. - Audio copy and mux steps still run after frame processing when you use options such as
--copy-audio,--audio-file, or--record-audio.
Typical terminal usage:
./acmx2 -p ./data -i input.mp4 -s ./shaders -h 12 --silent -o output.mp4Silent HDR processing uses the same flag and keeps HDR active automatically:
./acmx2 -p ./data -i hdr_input.mp4 -s ./shaders --gpu-filter 0,5 --silent -o hdr_output.mp4 --copy-audioBecause headless mode writes newline-delimited progress updates to stdout, it works well with terminal logging:
./acmx2 -p ./data -i input.mp4 -s ./shaders --silent -o output.mp4 | tee batch.log| Key | Action |
|---|---|
Up |
Previous shader (or previous playlist tree node if playlist enabled) |
Down |
Next shader (or next playlist tree node if playlist enabled) |
Shift+Up |
In playlist/autopilot mode: step the post-multipass shader backward without moving the playlist position |
Shift+Down |
In playlist/autopilot mode: step the post-multipass shader forward without moving the playlist position |
J |
Toggle autopilot mode (requires playlist; randomly auto-advances through playlist nodes at the configured frame interval) |
Y |
Toggle sequential autopilot (cycles playlist in order instead of randomly; requires playlist and autopilot active) |
R |
Toggle random multipass mode (generates random 1–5 shader chain with crossfade; press again to restore previous state) |
G |
Generate a new random shader chain (while in random multipass mode) |
Left |
Previous GPU filter (if GPU filters enabled) |
Right |
Next GPU filter (if GPU filters enabled) |
Space |
Toggle shader processing bypass |
P |
Toggle playlist mode / Pause video (Video/Image modes) |
L |
Toggle video freeze (Video/Image modes) |
Z |
Take snapshot |
4 |
Take 16-bit HDR TIFF snapshot (HDR input only; requires ACMX2_WITH_TIFF build) |
5 |
Take HDR snapshot — lossless RGBA WebP if built with ACMX2_WITH_WEBP, otherwise 16-bit RGBA PNG (HDR input only) |
6 |
Take raw RGBA snapshot — 16-bit RGBA (8 bytes/pixel) in HDR mode, 8-bit RGBA (4 bytes/pixel) otherwise |
M |
Toggle multi-shader pass (if --shader-pass set) |
3 |
Toggle 2D/3D mode (if --enable-3d active) |
E |
Toggle watermark |
F9 |
Toggle overlay (timer/FPS counter) visibility |
| Key | Action |
|---|---|
U (hold) |
Increase time step |
I (hold) |
Decrease time step |
T |
Toggle time on/off (Audio build) |
Q |
Toggle audio-reactive time (Audio build) |
Home |
Toggle audio delta time scaling (Audio build) |
Page Up/Down |
Increase/Decrease Time Speed |
| Key | Action |
|---|---|
Insert |
Increase audio sensitivity |
Delete |
Decrease audio sensitivity |
| Key | Action |
|---|---|
W / A / S / D |
Look around |
V |
Toggle view rotation |
O |
Toggle scale oscillation |
X |
Reset camera distance |
+ / - |
Increase / decrease camera distance |
B |
Increase movement speed |
N |
Decrease movement speed |
C |
Toggle wave effect |
The 6 key writes a headerless RGBA byte stream. The pixel layout depends on
whether the input is HDR. Use the dimensions embedded in the snapshot's
filename (ACMX2 always writes WxH into the name):
# HDR raw: 16-bit RGBA (8 bytes/pixel), BT.2020 PQ/HLG
ffplay -f rawvideo -pixel_format rgba64le -video_size 1920x1080 \
ACMX2.HDR.Snapshot-YYYY.MM.DD-HH.MM.SS-1920x1080-1.raw
# SDR raw: 8-bit RGBA (4 bytes/pixel)
ffplay -f rawvideo -pixel_format rgba -video_size 1920x1080 \
ACMX2.Raw-YYYY.MM.DD-HH.MM.SS-1920x1080-1.rawNote: ffplay shows raw PQ/HLG values without HDR tone-mapping, so colors may look saturated/clipped on SDR monitors.
ACMX2 now supports a random multipass mode for spontaneous creative exploration.
- R key — Toggle random multipass mode. On entry, the current shader state is saved and a random chain of 1–5 shaders is generated with a crossfade transition. Press R again to crossfade back to the previous state.
- G key — While in random mode, generate a new random shader chain with crossfade.
- Up/Down keys — While in random mode, change the main (post-processing) shader with crossfade while keeping the random pass list intact.
- Shift+Up/Down keys — In playlist or autopilot mode, cycle the post-multipass shader backward/forward independently of the playlist position, with crossfade.
- MIDI support — R (code 82) and G (code 71) are available as MIDI-mappable actions in the MIDI Map Tool.
ACMX2 now supports smooth crossfade transitions when switching shaders during playlist playback.
- Command line: Use
--cross-fade <seconds>to set the transition duration (default:0.5seconds). - How it works: When the active shader changes (via playlist navigation or keyboard controls), the previous frame is captured and linearly blended with the new shader output over the configured duration using a dedicated GLSL crossfade shader.
- Qt Interface: The Settings dialog includes a "Crossfade Duration" spin box (0.0–10.0 seconds, step 0.1).
- Implementation: A separate FBO and shader program (
crossfade.glsl) perform the blend. Thefade_alphauniform ramps from 0 to 1 over the configured duration, mixing the previous and current textures viamix(prev, curr, fade_alpha).
Recording now exposes more detailed encoder controls in both the command line and Qt launcher.
- Command line options:
--encode-preset <name>— preset fromultrafastthroughveryslow--encode-tune <name>— tune fromnone,film,animation,grain,stillimage,psnr,ssim,fastdecode, orzerolatency--encode-crf <0-51>— explicit CRF quality control (default:18)--encode-codec <auto|software|nvenc>— choose automatic selection, software encode, or NVENC explicitly--encode-realtime— enable low-latency realtime encoding flags for live capture
- Qt Interface: The Settings dialog now includes an Encoding Quality group with preset, tune, CRF, codec, and realtime controls.
- Persistence: Encoding selections are stored and restored for later sessions.
The ACMX2 Qt interface now restores the last-used values when key dialogs are closed and reopened.
- Persistent dialogs: Settings, Audio Settings, GPU Filter Settings, and MIDI Settings now save their visible state through
QSettings. - Reopen workflow: Closing a dialog with either OK or Cancel preserves the current values so you can reopen it and continue adjusting from where you left off.
- Startup defaults: When no saved preference exists yet, the Settings dialog now defaults the camera capture resolution to
1280x720and the display/output resolution toDefault. - Device-aware restore: Camera, CUDA, audio, and MIDI selectors restore by stored values where possible, which keeps the selected device stable even if combo-box ordering changes.
ACMX2 now supports MIDI input devices for real-time control of shaders and parameters via hardware knobs and buttons.
- Command line options:
--midi-map <file.midi_cfg>— Load a MIDI mapping configuration file--midi-device <index>— Select MIDI input device by index--list-midi— List available MIDI input devices
- MIDI Map Tool: New standalone
midi-mapapplication for creating MIDI controller mappings:- Live MIDI message monitor
- Capture button/knob assignments to ACMX2 actions (shader navigation, time control, pitch, yaw, speed, etc.)
- Updated action descriptions matching actual ACMX2 keybindings (playlist toggle, freeze frame, shader bypass, 3D camera controls, etc.)
- Save/load
.midi_cfgconfiguration files
- Qt Interface: New MIDI Settings dialog with:
- Enable/disable MIDI
- Browse for config file or launch the MIDI Map Tool directly
- Select MIDI device from detected inputs
- Velocity-sensitive knobs: Knob turn speed controls the rate of action firing
- MIDI Overlay: Real-time on-screen display showing MIDI status, knob states, and button presses with fade animation
- F9 key: Toggle overlay visibility on/off
The built-in GLSL shader editor has been significantly enhanced:
- Line number gutter
- Current line highlighting
- Bracket matching
- Auto-indentation on new lines
- Duplicate line (Ctrl+D)
- Move line up/down (Alt+Up/Down)
- Toggle comment (Ctrl+/)
- Smart Home key behavior
- Block indent/unindent (Tab/Shift+Tab with selection)
- Video-file decode now prefers direct FFmpeg decode with CUDA hardware acceleration when available.
- Automatic decode fallback path retained for software/OpenCV FFmpeg decode.
- Startup pipeline status line added, reporting active decode and encode modes.
- Recording path now starts WAV capture as soon as writer opens in file/image/camera modes.
- Recorded-audio mux flow hardened (skip mux if recorded WAV is missing).
- Temporary recorded WAV is automatically removed after successful mux.
- Version bump to 2.7.0
- Updated build scripts and Podman container configuration
- Audio muxing fix: uses video duration for precise audio/video sync
- Audio track copy fix for finished recordings
ACMX2 now supports shader playlists organized into named tree nodes, allowing you to group shaders and cycle through node groups during playback.
- Command line: Use
--playlist <file.txt>to load a playlist file. Supports the new[NodeName]section format as well as flat shader-per-line files. - Runtime controls:
- P — Toggle playlist mode on/off (loads first node's shaders into multi-pass pipeline)
- Up/Down arrows — Navigate to the previous/next tree node and load its shaders into multi-pass
- Shift+Up/Down arrows — Change the post-multipass shader (the shader that runs after the node's multi-pass chain) without altering the current playlist position
- Qt Interface: The Shader Playlist Settings dialog features a tree widget with named nodes:
- Add, rename, and remove node groups
- Add shaders to specific nodes via search
- Each node's shaders are loaded as a multi-pass chain when selected at runtime
- Save List... / Load List... buttons persist playlists using
[NodeName]section format
- File format: Playlist files use
[NodeName]headers to group shaders:[Ambient] glow.glsl blur.glsl [Intense] fractal.glsl distort.glsl
A script is provided to export ACMX2 applications from a Distrobox container to the host desktop:
bash scripts/export-distrobox.shThis installs the application icon, creates .desktop files for both acmx2_interface and midi-map, and registers them with the host application menu.
The Multipass Shader Settings dialog now includes Save List... and Load List... buttons, allowing you to save and restore your multipass shader chain as a text file.
- Command line: Use
--enumerate-device <index>to list all supported resolutions and frame rates for a V4L2 camera device (Linux only). - Qt Interface: The Settings dialog now automatically queries the selected camera device for its supported resolutions and frame rates. The resolution and FPS dropdowns are dynamically populated based on the device capabilities. Changing the camera device re-enumerates, and changing the resolution updates the available frame rates. In graphics file mode the FPS options default to 24, 30, and 60.
- FPS preference persistence: The selected camera FPS is now saved as a preferred value and restored when available after dialog reopen, app restart, or resolution list repopulation.
The GPU Filter Settings dialog now includes Save List... and Load List... buttons, allowing you to save and restore your GPU filter chain as a text file.
- All MIDI overlay text is now rendered in green for better readability
- When GPU filters are enabled, the overlay now displays the active GPU filter names in a comma-separated list (e.g.,
GPU: Filter1, Filter2, Filter3)
ACMX2 can also be built locally using a Podman container via the included Containerfile.arch.
This avoids dependency issues and produces a self-contained image. The provided container recipe is the CUDA-enabled variant and therefore requires an NVIDIA GPU; if you do not have one, use the native build below with -DWITH_CUDA=OFF instead.
The Podman container build below targets the optional CUDA path. For that specific path your system must have:
- Linux (x86_64)
- NVIDIA GPU
- NVIDIA proprietary drivers installed on the host
- Podman
- NVIDIA Container Toolkit (for Podman)
- X11 or XWayland
- Webcam device (
/dev/video0) for camera input - Audio input device (microphone)
- Shader/Model files: https://lostsidedead.biz/packs/
⚠️ Important The container recipe inpodman/Containerfile.archis the CUDA build and will only run on NVIDIA GPUs. For AMD, Intel, or Apple hardware, use the native build with-DWITH_CUDA=OFF(see below).
From the repository root, build the image using the Arch Linux Containerfile:
cd podman
podman build -t acmx2-arch:latest -f Containerfile.arch .Note: The default CUDA architecture is
75(Turing / RTX 20xx / GTX 16xx). EditContainerfile.archif your GPU differs:
- RTX 30xx (Ampere):
86- RTX 40xx (Ada Lovelace):
89
podman images | grep acmx2-archcd podman
chmod +x run-acmx2-arch.sh
./run-acmx2-arch.shThe script:
- Detects all
/dev/video*webcam devices - Enables NVIDIA GPU acceleration
- Mounts PulseAudio for audio input
- Passes
--device nvidia.com/gpu=allfor GPU access - Mounts
~/container_shareat/root/sharefor file exchange - Opens the ACMX2 interface window on your desktop
You can also build directly on Arch Linux using the scripts in build-script/:
# Install all dependencies
sudo bash build-script/install-deps-arch.sh
# Build and install ACMX2
sudo bash build-script/acidcam-gpu-arch.shWhen built with -DWITH_CUDA=ON, this project uses NVIDIA CUDA libraries.
Use of CUDA is subject to the NVIDIA Deep Learning Container License: https://developer.nvidia.com/ngc/nvidia-deep-learning-container-license
By building or running the CUDA-enabled variant of this project (including the provided NVIDIA container), you agree to NVIDIA’s license terms. The default OpenGL-only build (-DWITH_CUDA=OFF) does not link any CUDA libraries and is not subject to this notice.
Verify:
nvidia-smicd podman
podman build -t acmx2-arch:latest -f Containerfile.arch .
chmod +x run-acmx2-arch.sh
./run-acmx2-arch.sh#!/bin/sh
git clone https://github.com/lostjared/libmx2.git
cd libmx2/libmx
mkdir build && cd build
cmake .. -DEXAMPLES=OFF -DOPENGL=ON
make -j$(nproc)
sudo make install
cd ../../../
git clone https://github.com/lostjared/acidcam-gpu.git
cd acidcam-gpu
mkdir build && cd build
cmake ..
make -j$(nproc) && sudo make install
cd ../../
cd ACMX2
mkdir build && cd build
cmake .. -DAUDIO=ON
make -j$(nproc) && sudo make install
cd ../interface
mkdir build && cd build
cmake ..
make -j $(nproc)
cp -rf ../data/ .
cd ../midi-map
mkdir build && cd build
cmake .. && make -j$(nproc)
cd ../../../
echo "completed..."Each of the major optional subsystems is toggled by a CMake flag on ACMX2:
| Flag | Default | Effect when OFF |
|---|---|---|
-DWITH_CUDA=ON/OFF |
ON |
Skips all CUDA GPU-filter paths and CUDA/OpenGL zero-copy interop; OpenCV cudaimgproc is no longer required; FFmpeg CUDA hw-decode is disabled; --gpu-filter, --gpu-buffer, --cuda-device, --list-cuda-devices are not available |
-DAUDIO=ON/OFF |
OFF |
No RtAudio / audio reactivity |
-DMIDI=ON/OFF |
OFF |
No RtMidi / MIDI control |
If you do not have an NVIDIA GPU, cannot install the CUDA toolkit, or want to
build against a stock OpenCV (no CUDA modules), configure ACMX2 with
-DWITH_CUDA=OFF. The engine falls back to the OpenGL/SDL2 shader path — all
shader-based features continue to work; only the CUDA GPU filter stack is
omitted.
# libmx2 (built from source, same as above)
git clone https://github.com/lostjared/libmx2.git
cd libmx2/libmx
mkdir build && cd build
cmake .. -DEXAMPLES=OFF -DOPENGL=ON
make -j$(nproc) && sudo make install
cd ../../../
# ACMX2 without CUDA
git clone https://github.com/lostjared/acidcam-gpu.git
cd acidcam-gpu/ACMX2
mkdir build && cd build
cmake .. -DWITH_CUDA=OFF
make -j$(nproc) && sudo make install
# Qt6 GUI (unchanged)
cd ../interface
mkdir build && cd build
cmake .. && make -j$(nproc) && sudo make installNote: when WITH_CUDA=OFF you do not need opencv-cuda or the NVIDIA
CUDA toolkit — stock opencv is sufficient, and the top-level acidcam-gpu
CUDA library does not need to be installed.
You can combine flags freely — for example an OpenGL-only build with audio:
cmake .. -DWITH_CUDA=OFF -DAUDIO=ONAt startup the Qt6 interface probes the installed acmx2 binary with
--check-cuda, --check-audio, and --check-midi, and automatically disables
the menu entries (GPU Filter Settings, Audio Settings, MIDI Settings), the
Session-Properties CUDA device selector, and the corresponding CLI arguments
for any feature that is not compiled in. You can also run the probes directly:
acmx2 --check-cuda # "CUDA: enabled" or "CUDA: disabled"
acmx2 --check-audio # "AUDIO: enabled" or "AUDIO: disabled"
acmx2 --check-midi # "MIDI: enabled" or "MIDI: disabled"Early Example (as a GIF)
https://lostsidedead.biz/acmx2/shaders.zip
https://lostsidedead.biz/acmx2/models.zip
https://lostsidedead.biz/packs
This guide covers the setup and usage of the ACMX2 / Acidcam-GPU development environment on Bazzite. It details how to build the container, manage file paths, and ensure full hardware access (NVIDIA GPU, Webcam, and X11 Display).
Before launching the container, you must establish a specific folder structure on your Bazzite host. This ensures your code is persistent and files can be easily transferred.
Open a terminal on your host and run:
# Create a "scratch pad" for transferring files (videos, models, loose shaders)
mkdir -p ~/container_shareFolder purposes:
~/container_share
Shared volume. Files placed here are visible to both the host and the container.
- Run
./acmx2_interface
-
External assets (models, videos)
- Copy files to
~/container_shareon the host. - Access them in the container from:
/root/share/test_video.mp4
- Copy files to
- Binaries / render output
Copy output files to/root/shareinside the container.
They will appear in~/container_shareon the host.
Error:
Could not open camera index: 0
Fix:
Check available devices:
ls /dev/video*If your camera is /dev/video2, update the --device flag in run.sh.
Error:
qt.qpa.xcb: could not connect to display
Fix:
Ensure the following line exists in run.sh:
xhost +local:Re-run ./run-acmx2.sh to refresh permissions.
Files created inside the container are owned by root.
Fix ownership on the host:
sudo chown -R $USER:$USER ~/ACMX2All fragment shaders receive the following uniforms automatically. Uniforms that are not declared in your shader are silently ignored.
| Uniform | Type | Description |
|---|---|---|
samp |
sampler2D |
Main video/camera texture |
alpha |
float |
Alpha value (oscillates 0.0–1.0) |
iTime |
float |
Elapsed time in seconds since start |
time_f |
float |
Time multiplier (adjustable with U/I keys and --time-speed) |
iFrame |
int |
Frame counter |
iTimeDelta |
float |
Time since last frame (seconds) |
iResolution |
vec2 |
Window resolution (width, height) |
iMouse |
vec4 |
Mouse position (x, y, clickStartX, clickStartY) |
iMouseClick |
vec2 |
Last mouse click position |
iDate |
vec4 |
Current date/time (year, month, day, secondsOfDay) |
iFrameRate |
float |
Frame rate |
iChannelTime[0..3] |
float |
Per-channel time |
iChannelResolution[0..3] |
vec3 |
Per-channel resolution |
| Uniform | Type | Description |
|---|---|---|
samp1–samp8 |
sampler2D |
Cached frame textures from the texture cache ring buffer |
| Uniform | Type | Description |
|---|---|---|
value_alpha_r |
float |
Oscillating red color alpha |
value_alpha_g |
float |
Oscillating green color alpha |
value_alpha_b |
float |
Oscillating blue color alpha |
alpha_r |
float |
Red color alpha (same as value_alpha_r) |
alpha_g |
float |
Green color alpha (same as value_alpha_g) |
alpha_b |
float |
Blue color alpha (same as value_alpha_b) |
alpha_value |
float |
Current alpha value |
index_value |
float |
Current shader index in the library |
optx |
vec4 |
Option vector (0.5, 0.5, 0.5, 0.5) |
random_var |
vec4 |
Random variable vector |
restore_black |
float |
Restore black flag (0.0 or 1.0) |
inc_value |
vec4 |
Incrementing value vector |
inc_valuex |
vec4 |
Secondary incrementing value vector |
| Uniform | Type | Description |
|---|---|---|
amp |
float |
Amplitude scaled by sensitivity |
uamp |
float |
Raw untouched amplitude |
iamp |
float |
Estimated dominant frequency (Hz) |
amp_peak |
float |
Highest sample value in the buffer |
amp_rms |
float |
Root mean square energy |
amp_smooth |
float |
Exponentially smoothed amplitude |
amp_low |
float |
Low-frequency energy (<300 Hz) |
amp_mid |
float |
Mid-frequency energy (300–3000 Hz) |
amp_high |
float |
High-frequency energy (>3000 Hz) |
iSampleRate |
float |
Audio sample rate (44100.0) |
spectrum |
sampler1D |
FFT frequency-magnitude spectrum for the current frame (256 bins, GL_TEXTURE9) |
spectrum0-spectrumN-1 |
sampler1D |
Audio FFT history textures (newest to oldest) enabled by --enable-audio-buffers <N> |
This setup is designed to keep your development workflow fast and reproducible while maintaining full access to GPU acceleration, camera devices, and graphical output.
Related Videos YouTube Channel Contact me: Contact


