hermes-agent/optional-skills/creative/touchdesigner-mcp/references/operator-tips.md
kshitijk4poor be5a2ee5d3 feat(skills): expand touchdesigner-mcp with GLSL, post-FX, audio, geometry references
Add 6 new reference files with generic reusable patterns:
- glsl.md: uniforms, built-in functions, shader templates, Bayer dither
- postfx.md: bloom, CRT scanlines, chromatic aberration, feedback glow
- layout-compositor.md: layoutTOP, overTOP grids, panel dividers
- operator-tips.md: wireframe rendering, feedback TOP setup
- geometry-comp.md: instancing, POP vs SOP rendering, shape morphing
- audio-reactive.md: band extraction (audiofilterCHOP), beat detection, MIDI

Expand SKILL.md with:
- TD 2025 API quirks (connection syntax, GLSL TOP rules, expression gotchas)
- Trimmed param name table (8 known LLM traps, defers to td_get_par_info)
- Slider-to-shader wiring (td_execute_python + ParMode.EXPRESSION)
- Frame capture with run()/delayFrames (TOP.save() timing fix)
- TD 099 POP vs SOP rendering rules
- Incremental build strategy for large scripts
- Remote TD setup (PC over Ethernet)
- Audio synthesis via CHOPs (LFO-driven envelope pattern)

Expand pitfalls.md (#46-63):
- Connection syntax, moviefileoutTOP bug, batch frame capture
- TOP.save() time advancement, feedback masking, incremental builds
- MCP reconnection after project.load(), TOX reverse-engineering
- sliderCOMP naming, create() suffix requirement
- COMP reparenting (copyOPs), expressionCHOP crash

All content is generic — no session-specific paths, hardware, aesthetics,
or param-name-only entries (those belong in td_get_par_info).
Bumps version 1.0.0 → 2.0.0.
2026-04-22 01:49:49 +05:30

3.5 KiB

Operator Tips

Wireframe Rendering Pattern

Reusable setup for wireframe geometry on black background:

# 1. Material
mat = root.create(wireframeMAT, 'wire_mat')
mat.par.colorr = 1.0; mat.par.colorg = 0.0; mat.par.colorb = 0.0
mat.par.linewidth = 3

# 2. Geometry COMP
geo = root.create(geometryCOMP, 'my_geo')
geo.par.rx.expr = 'absTime.seconds * 30'
geo.par.ry.expr = 'absTime.seconds * 45'
geo.par.material = mat.path  # NOTE: 'material' not 'mat'

# 3. Shape inside the geo
box = geo.create(boxSOP, 'cube')
box.par.sizex = 1.5; box.par.sizey = 1.5; box.par.sizez = 1.5

# 4. Camera
cam = root.create(cameraCOMP, 'cam1')
cam.par.tx = 0; cam.par.ty = 0; cam.par.tz = 4; cam.par.fov = 45

# 5. Render TOP
render = root.create(renderTOP, 'render1')
render.par.outputresolution = 'custom'
render.par.resolutionw = 1280; render.par.resolutionh = 720
render.par.bgcolorr = 0; render.par.bgcolorg = 0; render.par.bgcolorb = 0
render.par.camera = cam.path
render.par.geometry = geo.path

# 6. Output null
out = root.create(nullTOP, 'out1')
out.inputConnectors[0].connect(render.outputConnectors[0])

Key rules:

  • Class names: wireframeMAT not wireframeMat (all-caps suffix)
  • Geometry SOPs/POPs go INSIDE the geo comp
  • Material: geo.par.material not geo.par.mat
  • Render geometry: render.par.geometry = geo.path (string path)
  • wireframeMAT.par.wireframemode = 'topology' for clean wireframe (vs 'tesselated' for triangle edges)
  • Alternative: Use renderTOP.par.overridemat instead of per-geo material

Feedback TOP

Basic Structure

input (initial state) ──┐
                        ├──→ feedback_top ──→ processing ──→ null_out
                        │                                        ↑
                        └── par.top = 'null_out' ────────────────┘

Setup Pattern

# 1. Processing chain
glsl = root.create(glslTOP, 'sim')
null_out = root.create(nullTOP, 'null_out')
glsl.outputConnectors[0].connect(null_out.inputConnectors[0])

# 2. Feedback referencing null_out
feedback = root.create(feedbackTOP, 'feedback')
feedback.par.top = 'null_out'

# 3. Black initial state
const_init = root.create(constantTOP, 'const_init')
const_init.par.colorr = 0; const_init.par.colorg = 0; const_init.par.colorb = 0

# 4. Wire: initial → feedback, feedback → processing
feedback.inputConnectors[0].connect(const_init)
glsl.inputConnectors[0].connect(feedback)

# 5. Reset to apply initial state
feedback.par.resetpulse.pulse()

Common Errors

Error Cause Solution
"Not enough sources specified" No input connected Connect initial state TOP
Unexpected initial pattern Wrong initial state Use Constant TOP (black)

Tips

  1. Use float format for simulations: glsl.par.format = 'rgba32float'
  2. Reset after setup: feedback.par.resetpulse.pulse()
  3. Match resolutions — feedback, processing, and initial state must match
  4. Soft boundary prevents edge artifacts:
    float edge = 3.0 * texel.x;
    float bx = smoothstep(0.0, edge, uv.x) * smoothstep(0.0, edge, 1.0 - uv.x);
    float by = smoothstep(0.0, edge, uv.y) * smoothstep(0.0, edge, 1.0 - uv.y);
    value *= bx * by;
    

Use Cases

  • Wave Simulation — R=height, G=velocity, black initial state
  • Cellular Automata — white=alive, black=dead, random noise initial state
  • Trail / Motion Blur — blend current frame with feedback, black initial