TouchDesigner

Making Plugins

Author your own sources, effects, system plugins, and feeds for Lightpath as TouchDesigner .tox files.

Plugins are how you extend Lightpath with content and behavior that isn't in the box. They're regular TouchDesigner .tox files that follow a small contract: expose the right parameters, plug into the right slot in your project, and Lightpath will load them and surface them in the UI.

The four types

TypeWhat it doesLook paramsConfig paramsStatus paramsFeed params
SourceProduces a look's visual signal — a texture, or a colour for each LED or pixel✓✓——
EffectTransforms a texture source's output✓✓——
SystemA singleton that reads, computes, or holds data other plugins can use—✓✓—
FeedStreams video that operators watch in the browser—✓—✓

Sources and effects are the visual building blocks of every look. System plugins are the supporting cast — they don't render anything themselves, but they make data available (sensor reads, audio analysis, MIDI input, computed state) for sources and effects to react to. Feeds don't touch looks at all; they exist to put live video in front of an operator.

See Making an Output for the per-output equivalent. Outputs follow the same parameter contract; they just sit at the end of the chain rather than inside it.


Sources

There are two kinds, and they are built differently.

A texture source is a .tox whose output is a texture — generative patterns, audio-reactive visuals, media playback, camera feeds. If it produces pixels, it is a texture source. It runs through the look's palette and effects like any image.

A shader source produces a colour for a point rather than an image: you write one GLSL function and Lightpath runs it at each LED or pixel of the output, with no texture in between. That is what lets it read where a fixture actually is. It applies the palette itself, and the only effect it takes is Color.

The rest of this section is for texture sources. Shader sources have their own contract, palette handling and parameters — see Shader Sources.

The texture source contract

A texture source takes in a palette (as a texture input) and outputs a texture. That's the shape Lightpath expects:

  • Input 1: a palette texture. Lightpath wires the active look's palette TOP into this input automatically. When the operator hasn't picked a palette, Lightpath leaves the input disconnected.
  • Output 1: the source's rendered texture — whatever your component produces, colorized however it likes with the palette.

Don't depend on anything outside the project folder — see the accessing project files note in the outputs guide; it applies here too.

Working with the palette

The palette is a horizontal gradient TOP: pixel x-coordinate maps to the position along the palette, RGB at that x is the color at that stop. Most sources sample it via a Lookup TOP, using the luminance of some internally-generated pattern as the lookup index — white in your pattern picks the rightmost palette color, black picks the leftmost, mids pick the in-between gradient.

You don't have to use a Lookup TOP, though. The palette is just a texture — multiply with it, sample at specific x positions, drive a particle recolor, feed it to a shader. What you do with it inside the source is up to you.

Set a default palette as the second fallback input to your In TOP, pointing it at a built-in fallback (a ramp TOP, a hand-tuned gradient, whatever you like). When Lightpath disconnects the external input — because the operator hasn't picked a palette in the look — TouchDesigner uses this default automatically.

Custom parameters

Texture sources support Look, Config, and Managed parameter pages. Use Look for things operators dial in per-look (pattern speed, scale, density, audio reactivity threshold, style toggles). Use Config for install-level settings (an expensive post-process toggle, a path to an external LUT). Use Managed for the params Lightpath drives rather than the operator — and always put your source's resolution there as Resolution1 and Resolution2 Int parameters. Add a Thumbnail Toggle on Managed too if your source needs special parameter values to look good in the source picker. See TouchDesigner Overview → Custom parameters for the full rules.


Effects

An effect is a .tox that takes one texture in and emits a (usually different) texture out. Color shifts, blurs, mirrors, masks, geometric distortions, time-warps — anything that transforms an incoming signal.

Effects apply to texture sources. A shader source has no texture to transform, so the one effect it accepts is the built-in Color, whose adjustments the shader applies directly; an effect you author never reaches it.

The contract

  • Accept the incoming texture on the component's first input.
  • Output the transformed texture on the first output.
  • Effects should be self-contained — Lightpath stacks multiple effects on one source, so each effect must work standalone.

Custom parameters

Effects support Look, Config, and Managed parameter pages. Look is the bread and butter — strength, blend amount, hue shift, blur radius, mask threshold — every per-look knob an operator expects. Config is rarer on effects (quality preset, mask image path, expensive-feature toggle) but available when you need it. Managed holds the params Lightpath drives rather than the operator; in particular, expose a Thumbnail Toggle there if your effect is pass-through at default values (most are) so the picker thumbnail shows something interesting. See TouchDesigner Overview → Custom parameters for the full rules.

Category tags

Effects can declare one or more category tags that surface as filter chips in the effect picker. The built-in categories are color, distort, mask, and transform; you can use these or declare your own. Group several effects under the same tag and an operator can find them all in one click in a long list.

Tags are optional — an untagged effect still works, it just lands in the "all" bucket in the picker.


System plugins

System plugins are singletons — one instance per type, mounted at a known op shortcut so other plugins can find them. They don't participate in the render chain. Instead, they hold and expose data that sources, effects, outputs, and actions can read.

When to author one

  • Reading external data — lidar, depth cameras, audio analysis, MIDI controllers, OSC ingestion, MQTT subscriptions.
  • Computing shared state — beat tracking from audio, presence detection from a sensor stack, smoothing filters on noisy input.
  • Coordinating between plugins — a "show clock" that multiple visuals reference, a global tempo, an environmental mode flag.

If two sources want to react to the same audio analysis, that analysis belongs in a system plugin — not duplicated inside each source.

The contract

  • No render input or output. The plugin doesn't sit in the texture chain.
  • Expose data via custom parameters, CHOPs, DATs, or your preferred TouchDesigner mechanism.
  • Set up a global op shortcut on the COMP so other plugins can resolve it from anywhere in the project — see below.

Surfacing status to Lightpath

System plugins (alongside outputs) support a Status parameter page. Any parameter you put on a page named Status shows up live in the TouchDesigner device on the Integrations page, and is available as a target in the Alerts rule editor. See TouchDesigner Overview → Status parameters for the full rules.

This is what makes system plugins observable from the rest of Lightpath — operators can see connection state, error counts, and last-message timestamps without ever opening TouchDesigner.

The op shortcut

The op shortcut is what makes a system plugin reachable from elsewhere. Set the COMP's Common → Global OP Shortcut parameter to a name, and op.NAME resolves to the COMP from anywhere in the project — no path traversal, no parent() walks, no fragile relative references.

Convention: ALL_CAPS_UNDERSCORE. Lightpath's system plugins use this form (AUDIO_ANALYSIS, PRESENCE_TRACKER, SHOW_CLOCK) so they read as constants at the call site and don't collide with component or extension names. Stick to it for any plugin you author.

From a source's, effect's, or output's Python:

# Read a custom parameter
bpm = op.AUDIO_ANALYSIS.par.Bpm.eval()

# Read a CHOP / DAT / TOP inside the plugin
beat = op.AUDIO_ANALYSIS.op('out1')['beat'].eval()

Or wire it into a parameter expression in the editor:

op.AUDIO_ANALYSIS.par.Bpm

System plugins are the only TD components in Lightpath that other plugins should reach into directly. Sources and effects must stay self-contained — referencing one source or effect from another makes the look editor unpredictable when the referenced plugin isn't loaded. If two visual plugins need shared data, put the data in a system plugin and have each reach into it from there.


Feeds

A feed plugin is a .tox that streams video to operators in the browser. Lightpath ingests NDI on its own; anything else — a capture card, video from another application, a commissioning test pattern, a generative patch that isn't a look — is a feed plugin.

The contract

Output a texture on the component's first output. There's no input to accept, no extension to write, and no naming convention. Put an Out TOP inside the component and wire your video into it.

Creating one

On the TD Plugins page: New Plugin, type Feed, name it, Create plugin. Lightpath copies a template into the project's plugins/feeds/ folder and loads it — open it in TouchDesigner and replace the placeholder.

Dropping a .tox into plugins/feeds/ works too (see Registering a plugin). Deleting the .tox deletes the feed.

Where it shows up

Feed plugins appear on the Feeds page alongside NDI feeds. Scope decides where else, and is set from either the Feeds page or the plugin's row on the TD Plugins page:

  • An output — that output's monitor gains an entry, so an operator can switch its tile between the output's previs and your video.
  • All outputs — shows wherever all outputs are in view.
  • An area — stored, but areas don't surface feeds yet.
  • Not scoped — still pickable for a kiosk or panel monitor, but won't appear anywhere on its own.

Size and framing

A feed plugin publishes whatever it renders, at whatever size it renders it. Do framing, cropping, and scaling in TouchDesigner — nothing on the Lightpath side will resize the video for you.

Parameters

Config params are install-time setup — which device to open, a network address — and appear on the TD Plugins page.

Feed params appear beside the stream, on the expanded view of a monitor tile: camera choice, zoom, an overlay toggle. Operator changes are saved and restored, so give each one a sensible default. See Feed parameters for the full rules.

Look and Status params don't apply to feeds.

A feed only encodes while somebody is watching it. Lightpath handles that — you don't need a start/stop control of your own.

Registering a plugin

Plugins are discovered from the project's plugins/ folder. Drop a .tox into the subfolder for its type — sources, effects, system, or feeds — and Lightpath picks it up on the next project load, or immediately when you click Rescan on the TD Plugins page. The folder is the categorization; there is no separate "add plugin" step and no type to declare.

Deleting a .tox removes the plugin. Moving or renaming one is a delete plus an add — any settings attached to the old entry (associated output, saved parameter defaults, feed scope) don't follow it.


Accessing project files

Same pattern as outputs — see TouchDesigner Overview → Accessing project files for the project/... shortcut.


Lifecycle hooks (advanced)

Sources, effects, and system plugins can react to being loaded or torn down — either with a capitalized extension method or a pulse parameter. See TouchDesigner Overview → Lifecycle hooks for more information.

On this page