GLim User Manual

For GLim 0.9.0-beta.3

GLim plays GLSL shaders live and turns them into plugins for your VJ software. It reads fragment shaders written in the ISF, Shadertoy and GLSL Sandbox formats, and plain GLSL.

GLim comes with 18 shaders you can use however you like. Shaders written by other people keep their authors' licenses, including in the plugins and ISF files you make from them: see Shaders from other people before you use one.

Play shaders live

All of these keep running as you switch shaders, so a queue of shaders can drive a whole show.

Convert shaders


What's in the package

File What it is
GLim.exe (Windows) or GLim.app (macOS) The app. There's no installer: it runs from wherever you put it.
touchosc TouchOSC layouts for remote control (see Remote control below)
original-shaders 18 ISF shaders made for GLim, to try it with. They're public domain (CC0): use them however you like. Fourteen are psychedelic patterns that evolve over time, each with sliders to play with; three of them use feedback buffers and build up over a few seconds (feedbackSwirl, reactionBloom, inkMarble). The other four are building blocks to layer into your own looks (see Building blocks below).
USER_MANUAL.html This manual
LICENSE.txt GLim's license (MIT)
THIRD_PARTY_NOTICES.txt The terms for the NDI software inside GLim, and the licenses of the other software by others inside it

System requirements

Windows

macOS

For the plugins you make: Resolume 7.21.3 or later, or another FFGL 2 host. Mac plugins are universal: they also run on Intel Macs (macOS 10.15+).

Installing on Windows

  1. Right-click the zip, choose Extract All…, and extract it to a folder you can write to, such as Documents or the Desktop.
    • Don't start GLim.exe from inside the zip: Windows would run it from a temporary folder, and the plugins it builds would be lost.
    • Don't put it in Program Files: GLim saves each shader's settings next to the shader, including the shaders that come with it.
  2. Double-click GLim.exe. It isn't code-signed yet, so Windows may say Windows protected your PC: click More info, then Run anyway. Windows asks only once. Some antivirus apps also scan it the first time, which can take a while.
  3. GLim takes a few seconds to start (it unpacks itself each time).
  4. Windows Firewall asks whether GLim may use the network. Allow it on private networks: remote control and NDI need it. Everything else works without it.

To build FFGL plugins (optional: the preview, Export ISF, Spout, NDI and remote control work without it):

  1. Download the free Build Tools for Visual Studio from visualstudio.microsoft.com/visual-cpp-build-tools and run it. If you already have Visual Studio 2022 or later, open the Visual Studio Installer and modify your installation instead.
  2. Tick the Desktop development with C++ workload and click Install. Its default parts are all GLim needs (they include CMake). The download is several GB.
  3. If GLim was running, restart it.

Without them, Build FFGL says what's missing and where to get it.

Installing on macOS

  1. Double-click the zip to unpack it, and drag GLim.app to your Applications folder (or wherever you like).
  2. The app isn't notarized by Apple yet, so macOS blocks it the first time. Double-click it, and click Done (or OK) when macOS says it can't verify it. Then open System Settings → Privacy & Security, scroll down to the message about GLim, click Open Anyway, and confirm with your password. macOS asks only once.
    • On macOS 14 you can instead right-click the app and choose Open.
    • Or, in Terminal: xattr -dr com.apple.quarantine /Applications/GLim.app
  3. When GLim first uses the network (remote control or NDI), macOS asks whether it may find devices on your local network: click Allow.
  4. When you first build a plugin, macOS may ask once for access to your Documents folder (GLim looks there for Resolume's Extra Effects folder): click Allow.

To build FFGL plugins (optional: the preview, Export ISF, Syphon, NDI and remote control work without it):

  1. Install the Xcode Command Line Tools: open Terminal, type xcode-select --install, press Return, and click Install. The full Xcode app isn't needed (if you have it, this step is already done).
  2. Install CMake: download the macOS .dmg from cmake.org/download and drag CMake.app to Applications. If you use Homebrew, brew install cmake works too.
  3. If GLim was running, restart it.

Without CMake, Build FFGL says what's missing.

First launch

GLim opens with two tabs, Queue and Studio, and the Log at the bottom, which reports everything GLim does. Its first lines include GLim's version, the graphics card GLim uses (GPU: …) and the address for remote control (OSC remote control: …). If it says GPU validation unavailable instead, see Troubleshooting.

A first tour, with the shaders that come with GLim:

  1. Drag the original-shaders folder onto the Queue tab (or click 📁 and choose it). Each shader becomes a row in the queue.
  2. Press Shift+Tab (or click Studio). The first shader in the queue plays in the preview, with a slider, switch or menu for each of its parameters.
  3. Press → and ← to step through the queue, or click Auto to play it as a slideshow. Move a slider to change the shader as it plays.
  4. Click ⧉ to open an output window. Drag it to a second monitor and double-click it to make it fullscreen; Esc brings it back.
  5. Click Build FFGL to make a plugin of the shader that's showing (this needs the build tools above). GLim asks where to put the plugin (.dll on Windows, .bundle on macOS): choose Documents\Resolume Arena\Extra Effects (macOS: ~/Documents/Resolume Arena/Extra Effects), which Resolume scans by default (more folders can be added in Resolume's Preferences → Video). The first time, the dialog opens there if that folder exists. The first build takes about a minute, because it sets up a build workspace and compiles the FFGL SDK; after that, a plugin takes a couple of seconds.
  6. Restart Resolume. A shader that makes its own picture appears under Sources, one that changes a clip under Effects.
  7. Export ISF saves the shader as an .fs file for MadMapper, VDMX, Millumin and other ISF hosts.

GLim saves each shader's settings (slider values, ranges, names) in a <shader>.glim.json file next to the shader, so keep your shaders in a folder you can write to.

Updating and uninstalling

To update, replace GLim.exe (or GLim.app) with the new one. Your shaders' settings stay, since they're next to the shaders. If the TouchOSC layouts changed, copy them to your phone or tablet again: TouchOSC keeps its own copy.

To uninstall, delete GLim.exe (or GLim.app). GLim installs nothing else, but it leaves:

The Build Tools, Command Line Tools and CMake are uninstalled separately, if you installed them for GLim.

Shaders from other people

Shaders you find online belong to the people who wrote them. GLim converts the code but doesn't change who owns it: a shader's license also covers the plugins and ISF files you make from it, and performing with them.

Before you use someone else's shader in a show, or share what you build from it:

What you make with GLim is yours, apart from what belongs to the shader's author. The shaders that come with GLim are public domain (CC0), so the plugins and ISF files you make from them are free to use and share.

Plugins that GLim builds also contain code from the FFGL SDK (and on Windows, GLEW). Their licenses, in THIRD_PARTY_NOTICES.txt, ask that their notices go with any plugins you share.


Using GLim

Whenever GLim writes files (Build FFGL, Export ISF, or saving shader code), it asks where. Each dialog opens in the folder you chose last time for that kind of file (plugins, ISF files or shader code), also after you restart GLim, and the Queue and Studio tabs share these folders.

Queue tab

The queue is the list of shaders to build, export or play.

  1. Drop shader files or folders onto the Queue (or use + to add files and 📁 to add a folder).
  2. Click Build FFGL to make FFGL plugins, or Export ISF to make .fs files. Each asks for a folder.
  3. If you built plugins into a folder Resolume scans (see First launch), restart Resolume. Otherwise, copy them to one first.

In the queue, select rows with a click (Shift/Ctrl-click for several), or press Ctrl+A (⌘A on macOS) to select them all. Ctrl+A works anywhere on the Queue tab; in text fields it keeps its usual meaning.

Studio tab

Open a shader with + (or paste one) and click Analyze (or press Ctrl+Enter; ⌘+Enter on macOS): it processes the code, loads it into the preview and measures its GPU load. After editing the code, Analyze processes it again; with the code unchanged it only measures. Build FFGL (.dll) (.bundle on macOS) then makes the plugin and Export ISF (.fs) the ISF file, as on the Queue tab. The disk button next to + saves the code as a .txt or .fs file. You get:


Supported inputs

Format Detected by Becomes
ISF (.fs) /*{ JSON }*/ header Source, Effect (1 image input), or Mixer (Transition category with 2 images)
Shadertoy mainImage() Source; or Effect if it reads iChannel0
GLSL Sandbox / plain GLSL main() Source (or Effect if it declares a sampler2D uniform)

Supported features:

Shadertoy channels

By default every iChannel reads the clip, which makes the plugin an effect. Choose a different source with a comment line anywhere in the shader:

// glim: iChannel1 = textures/rock.jpg   (image file, relative to the shader; embedded in the plugin)
// glim: iChannel2 = noise                (generated RGBA noise texture)
// glim: iChannel3 = audio                (live audio spectrum from the host)
// glim: iChannel0 = input                (the clip; the default)

If an image file is missing, a noise texture is used and GLim warns you.

Sampler settings

Like Shadertoy's per-channel settings, add filter, wrap and vflip after the source:

// glim: iChannel1 = textures/pixels.png filter=nearest wrap=clamp
// glim: iChannel2 = textures/rock.jpg vflip=false
Setting Values Default
filter nearest (sharp pixels), linear, mipmap (smooth when shrunk) images: mipmap; buffers and the clip: linear
wrap clamp, repeat (tiles) images: repeat; buffers and the clip: clamp
vflip true, false (image upside down, as on Shadertoy) true

Shadertoy JSON exports carry these settings already. In multi-buffer shaders each pass can read the same buffer with different settings. The clip can't be mipmapped, so mipmap acts like linear there.

In ISF exports, nearest and repeat are emulated in the shader, because ISF hosts always sample images smoothly and clamped. Two small differences remain: mipmap acts like linear, and with linear + repeat, the half texel at each tile edge clamps instead of blending with the opposite edge (only visible on very low-resolution images).

Multi-buffer Shadertoy shaders (Buffer A–D)

Either:

// ==== Common ====
...
// ==== Buffer A ====
// glim: iChannel0 = Buffer A     (feedback: reads its own previous frame)
void mainImage(...) { ... }
// ==== Image ====
// glim: iChannel0 = Buffer A
void mainImage(...) { ... }

Buffers become float feedback buffers in the FFGL plugin and PASSES in ISF exports. Errors are reported as [Buffer A] line N.

Not yet supported


Parameters

ISF inputs

These become native FFGL parameters:

ISF input FFGL parameter
float Slider with the real MIN/MAX range
long Dropdown with the ISF labels
bool Toggle
event Trigger button
color Color picker
point2D X and Y sliders

Shadertoy / GLSL constants

Top-level const float/bool/vec3 values and #define NAME 1.5 lines become sliders, toggles or color pickers. To leave one out, untick it in the Studio tab: it's compiled in as a constant at its current value. (The command line's --no-params still turns this off for a whole run.)

Built-in controls

Tempo

Shaders in any dialect can use the host's tempo by reading these names (no declaration needed):

Name Value
iBPM Tempo in beats per minute
iBeat Beats elapsed, in step with the host's bars (fract(iBeat) pulses every beat)
iBarPhase 0 to 1 through the current bar

Resolume sends its tempo to FFGL plugins. Until a host sends any, and in the preview, the plugin runs at 120 BPM. ISF hosts have no tempo input, so ISF exports get a BPM slider (default 120) and count beats from TIME.

Alpha

Shadertoy and GLSL Sandbox ignore output alpha, so GLim makes those plugins opaque. ISF shaders keep their alpha.

Building blocks

Four of the shaders in original-shaders are simple pieces to combine into your own looks, for example a shapeForge star over spiralling rays from radialBurst, masked by noiseField. Build them as plugins and stack them as layers in Resolume.

Each draws one element and has a Transparent switch: on, the background is see-through (alpha), so the layer sits over the ones below without a blend mode.

Shader What it draws Main controls
shapeForge A polygon, star or circle, as outline, fill and glow, in concentric copies Sides, Star, Roundness, Copies, Spacing, Spin, Twist, Pulse, Position
gridMatrix A grid of dots, squares, crosses, rings or diamonds, sized by a travelling wave Shape, Wave, Columns, Wave Amount / Freq / Speed, Cell Spin, Grid Spin
radialBurst Rays from a point, straight or spiralling Rays, Width, Spin, Twist, Breathe, Length Jitter, Inner Radius, Position
noiseField Smooth, ridged, turbulent or cellular noise; with Threshold it becomes a mask Type, Scale, Detail, Warp, Drift, Evolve, Contrast, Threshold

Every moving part has its own rate slider (Spin, Scroll, Pulse Rate …), and in the plugins moving a rate slider changes the speed without the motion jumping. The jitter controls change in steps on purpose, for strobing.

Remote control (OSC, TouchOSC)

GLim's Studio tab can be controlled from a phone, a tablet or another computer over the network, with OSC. It's always on: GLim listens on UDP port 8000 and sends what it's doing back on port 8001. The log says so when GLim starts, with this computer's address: OSC remote control: 192.168.1.20, port 8000 (feedback to port 8001). The first time, Windows Firewall asks whether GLim may use the network: allow it on private networks, or other devices can't reach it. macOS asks for Local Network access.

It controls what's under the preview: play / pause, restart, ← / →, the slideshow (Auto and its time), the output window and fullscreen, Spout (Syphon on macOS), NDI and its size, and the loaded shader's parameters. Not the queue, Build FFGL, Export ISF or Analyze.

You need TouchOSC (by hexler, for Windows, macOS, iOS and Android). TouchOSC layouts are in the touchosc folder:

To use one:

  1. In TouchOSC, open Connections → OSC and set up any connection (the layouts send and receive on all of them; other enabled connections get GLim's messages too, which other apps ignore): UDP, Host = the GLim computer's address (from the log; 127.0.0.1 when TouchOSC runs on the same computer), Send Port 8000, Receive Port 8001.
  2. Open the layout in TouchOSC and start the control surface (▶). To get it onto a phone or tablet, copy the .tosc file there (by cloud drive, email or USB) and open it from TouchOSC. TouchOSC keeps its own copy of a layout on each device: after a new version of GLim's layouts, copy the file to the phone or tablet again.
  3. The status line (under the shader name on the desktop layout, at the bottom on the phone) changes to connected: GLim on COMPUTERNAME within a couple of seconds. If it stays at not connected, check the address and ports, that both are on the same network, and the firewall.

On a Mac with tap to click turned on, TouchOSC on that Mac misses some taps on the trackpad (GLim never receives them; other macOS apps have the same problem). Press the trackpad down instead, or use a mouse.

The layout follows GLim: the switches light up as things are turned on (from the layout, in GLim or by the slideshow), and loading another shader fills in its parameter names, values and faders.

Parameters take up to 24 slots, in the order of the Studio tab's list (without those kept as constants). Each value has a slot: a colour takes one per channel (R, G, B and, if it has one, A) and a point one per axis (X, Y). Unused slots are hidden. A fader covers the parameter's range (as set in the Studio tab); for a menu it steps through the options; a switch is on past the middle, and a trigger fires at the right-hand end. Moving a fader changes the value as the Studio tab's slider does, so it's saved with the shader's settings too. A shader with more than 24 values (rare) shows the first 24; the layout says e.g. 28 parameters: the first 24 are here.

From other OSC apps (Open Stage Control, Max, Lemur, …): send to UDP port 8000 at the GLim computer's address. Switches take 1 or 0 (no argument toggles); buttons act on a message with no argument or 1 (not on the 0 a button sends when it's released).

Address Argument What it does
/glim/play 1 / 0 Play / pause
/glim/restart Restart the shader
/glim/prev, /glim/next Previous / next shader in the queue (as ← / →)
/glim/auto 1 / 0 Slideshow on / off
/glim/auto/seconds seconds Slideshow time (minimum 1)
/glim/auto/seconds/up, /down Slideshow time one step longer / shorter (… 8, 10, 12, 15, 20 …)
/glim/output 1 / 0 Output window open / closed (closing works even when it's fullscreen)
/glim/fullscreen 1 / 0 Fullscreen, as ⛶ (the output window's, if it's open)
/glim/spout 1 / 0 Spout (Syphon on macOS) on / off
/glim/ndi 1 / 0 NDI on / off
/glim/ndi/720p 1 / 0 NDI at 1280×720 / 1920×1080
/glim/param/1 … /24 0 … 1 Parameter slot (as above)
/glim/ping Answered with /glim/pong and the computer's name
/glim/sync Send the whole state again

GLim sends its state to every address that has sent it a message in the last 30 seconds (send /glim/ping now and then to keep it coming; the TouchOSC layouts do, every second), on port 8001 and on the port the message came from. The switches come back on their own addresses as 1 / 0, each parameter slot as its 0 … 1 value, and these as text: /glim/shader (the shader's name), /glim/queue (e.g. 3 / 12 · next in 4s), /glim/time, /glim/auto/label (e.g. 10 s), /glim/spout/name (Spout or Syphon), /glim/params (how many parameters), /glim/param/<n>/name and /glim/param/<n>/value (both empty for an unused slot). Only what changes is sent again.


Troubleshooting

Starting GLim

Shaders and plugins

Network (NDI and remote control)

Reporting problems

Report problems, ask questions and suggest ideas on GitHub: github.com/bzsqrl/GLim/issues (a free GitHub account is needed). Please check first whether someone has already reported the same thing.

When something goes wrong, please include:

If GLim won't start at all, its self-test can show why. It converts and builds one shader and checks Spout or Syphon, NDI and remote control, without opening the window, and writes selftest.log:

Attach the selftest.log from the selftest folder (the plugin it builds there can be deleted).


Running from source (developers)

Prerequisites (Windows)

Prerequisites (macOS)

Running and packaging

Command line

venv\Scripts\python -m glim <files or folders> --to ffgl|isf|both|check [--out DIR] [--no-params] [--test]

The command line runs from source only, not from GLim.exe or GLim.app.


About GLim

GLim is made by Busy Squirrel and released under the MIT license.

Made with AI. GLim was built with AI coding tools, Claude Code (by Anthropic) and Google Antigravity. Most of its code, the 18 shaders that come with it and this manual were written by AI, directed by a person who decided what GLim should do and tested each version on Windows and macOS, in Resolume and MadMapper. If something doesn't work as this manual says, please report it (see Reporting problems).

NDI

NDI® is a registered trademark of Vizrt NDI AB. GLim uses the NDI® SDK (through the cyndilib library) to send video; it isn't made or endorsed by Vizrt NDI AB. NDI runtime: Copyright © 2023–2026 Vizrt NDI AB, all rights reserved; its license notices ship with GLim (cyndilib/wrapper/bin/*licenses*.txt), and the terms NDI asks users to agree to are at the top of THIRD_PARTY_NOTICES.txt. More about NDI: ndi.video.

Privacy

GLim doesn't collect any data and doesn't connect to the internet. It uses your local network only for NDI output and for remote control (OSC on UDP port 8000).