TouchDesigner Intermediate Article 3

GPU Instancing in TouchDesigner

Draw thousands of geometry copies in a single draw call by feeding per-instance transform and colour data through Instance CHOPs and Instance TOPs.

⏱ 22 min instancing gpu geometry performance

GPU instancing lets you render the same piece of geometry thousands of times in a single draw call, with each copy positioned, rotated, scaled, and coloured independently. The GPU handles the repetition; your job is to provide the per-instance data. In TouchDesigner, that data lives in CHOPs (for transforms) and TOPs (for colours or UV offsets), and a few toggles on a Geo COMP wire everything together.

Enabling Instancing on a Geo COMP

Select your Geo COMP and go to the Instancing page in its parameters. Toggle Instancing to On. Two fields appear:

  • Instance CHOP — path to a CHOP whose channels define per-instance transforms
  • Instance TOP — path to a TOP whose pixels define per-instance colour or UV data

The Geo COMP now renders one copy of its geometry per sample in the Instance CHOP (or per pixel row in the Instance TOP, if no CHOP is set).

Instance CHOP Channel Conventions

The CHOP you assign to the Instance CHOP field must contain channels with specific names. TouchDesigner recognizes:

Channel name Meaning
tx, ty, tz Translation
rx, ry, rz Rotation (degrees)
sx, sy, sz Scale
cr, cg, cb, ca Per-instance colour (0–1)

The number of samples in the CHOP equals the number of instances drawn. A CHOP with 10,000 samples produces 10,000 copies.

Building the Instance Data

Noise CHOP for Position

The fastest way to scatter instances organically is a Noise CHOP:

  1. Add a Noise CHOP. Set Channel Name to tx ty tz (space-separated, or one per row in the Channels field).
  2. Set Length to the number of instances you want, e.g. 10000.
  3. Set Amplitude to 200 on each axis to spread instances across a 400-unit cube.
  4. Set Seed to different values per channel so X, Y, Z are uncorrelated.

The three channels — tx, ty, tz — are read as per-instance translation automatically.

Math CHOP and Shuffle CHOP

When you need to combine data from multiple sources, use a Math CHOP to scale or offset channel ranges, and a Shuffle CHOP to interleave or reorder channels. A typical pipeline:

Noise CHOP (tx) ──┐
Noise CHOP (ty) ──┼─→ Merge CHOP → Shuffle CHOP → Instance CHOP input
Noise CHOP (tz) ──┘

In the Merge CHOP set Match By to Extend so all three CHOPs are merged to the same sample length. The Shuffle CHOP with mode “Interleave” rearranges them into the tx ty tz tx ty tz ... layout if needed, though TD reads named channels so order rarely matters.

Adding Rotation and Scale

To animate instance rotation, add a second Noise CHOP with channels named ry and connect it into a second input of the Merge CHOP. For random uniform scale, generate a Noise CHOP with one channel, rename it via a Rename CHOP to sx, then Copy CHOP it to sy sz — or use a Math CHOP with Copy Inputs mode to duplicate the channel under new names.

Instance TOP for Per-Instance Colour

For colour instancing, point the Geo COMP’s Instance TOP field at a TOP. TouchDesigner reads each pixel in the TOP as a per-instance RGBA colour. The TOP is sampled left-to-right, top-to-bottom, so a 100×100 TOP gives you 10,000 colours.

A Ramp TOP set to Linear, horizontal, gives a smooth colour gradient across all instances. A Noise TOP gives random per-instance colours. The Instance TOP and Instance CHOP work simultaneously — you can have both.

Full Example: 10,000 Instances with 3D Noise and Ramp Colour

Here is the complete network:

SOPs:

  • sphere1 — Sphere SOP, Radius 0.5, Polygons, inside a Geo COMP named geo_instances

CHOPs:

  • noise_pos — Noise CHOP, 3 channels (tx ty tz), Length 10000, Amplitude 300, Period 5, each channel a different seed
  • noise_rot — Noise CHOP, 1 channel (ry), Length 10000, Amplitude 180
  • noise_scale — Noise CHOP, 1 channel (base_scale), Length 10000, Amplitude 0.8, Offset 1.0
  • rename_scale — Rename CHOP after noise_scale; rename base_scalesx
  • copy_scale — Copy CHOP after rename_scale; copy sx to sy and sz
  • merge_all — Merge CHOP merging noise_pos, noise_rot, copy_scale; Match By: Extend

TOPs:

  • ramp1 — Ramp TOP, 10000×1, Type: Linear, Phase driven by a LFO CHOP exported to the Phase parameter so the colours cycle

Geo COMP settings:

  • Instancing: On
  • Instance CHOP: merge_all
  • Instance TOP: ramp1

Render setup:

  • camera1 — Camera COMP looking at origin, translate Z = 800
  • light1 — Light COMP
  • render1 — Render TOP with geo_instances, camera1, light1

At 60fps on a modern GPU this runs comfortably above budget. Most of the cost is in the vertex shader, not the instance upload.

Animating Instance Data Over Time

To animate the positions over time, connect the Noise CHOP’s Time Slice parameter to On or bind its offset parameter to absTime.seconds * speed. Every cook the Noise CHOP produces a new set of 10,000 samples, and the GPU receives fresh instance data each frame.

For physics-based animation, use a Particle SOP and export its point positions to a SOP to CHOP node (CHOP > SOP to CHOP), which reads point attributes as CHOP channels — one sample per point. Rename those channels tx ty tz and feed them to the Instance CHOP.

Combining Instance CHOP and Instance TOP

When Instance CHOP provides the cr cg cb channels, the Geo COMP uses those for colour and ignores the Instance TOP. If the CHOP does not include colour channels, the Instance TOP is used. You can also declare a custom GLSL MAT and access TDInstanceID() in the vertex shader to sample any texture manually, giving you complete control over per-instance data.

Performance Ceiling

On a mid-range GPU (RTX 3060 or equivalent), expect to comfortably render:

  • 500k instances of a single-triangle Sprite SOP at 60fps
  • 100k instances of a 256-polygon Sphere SOP at 60fps
  • 10k instances of a 2000-polygon mesh at 60fps

The bottleneck shifts from GPU vertex throughput to the CHOP cook as instance counts rise. Profile with the Performance Monitor (Dialogs > Performance Monitor) to confirm where time is spent.