hermes-agent/optional-skills/creative/touchdesigner-mcp/references/glsl.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

GLSL Reference

Uniforms

TouchDesigner          GLSL
─────────────────────────────
vec0name = 'uTime'  →  uniform float uTime;
vec0valuex = 1.0    →  uTime value

Pass Time

glsl_op.par.vec0name = 'uTime'
glsl_op.par.vec0valuex.mode = ParMode.EXPRESSION
glsl_op.par.vec0valuex.expr = 'absTime.seconds'
uniform float uTime;
void main() { float t = uTime * 0.5; }

Built-in Uniforms (TOP)

// Output resolution (always available)
vec2 res = uTDOutputInfo.res.zw;

// Input texture (only when inputs connected)
vec2 inputRes = uTD2DInfos[0].res.zw;
vec4 color = texture(sTD2DInputs[0], vUV.st);

// UV coordinates
vUV.st  // 0-1 texture coords

IMPORTANT: uTD2DInfos requires input textures. For standalone shaders use uTDOutputInfo.

Built-in Utility Functions

// Noise
float TDPerlinNoise(vec2/vec3/vec4 v);
float TDSimplexNoise(vec2/vec3/vec4 v);

// Color conversion
vec3 TDHSVToRGB(vec3 c);
vec3 TDRGBToHSV(vec3 c);

// Matrix transforms
mat4 TDTranslate(float x, float y, float z);
mat3 TDRotateX/Y/Z(float radians);
mat3 TDRotateOnAxis(float radians, vec3 axis);
mat3 TDScale(float x, float y, float z);
mat3 TDRotateToVector(vec3 forward, vec3 up);
mat3 TDCreateRotMatrix(vec3 from, vec3 to);  // vectors must be normalized

// Resolution struct
struct TDTexInfo {
  vec4 res;   // (1/width, 1/height, width, height)
  vec4 depth;
};

// Output (always use this — handles sRGB correctly)
fragColor = TDOutputSwizzle(color);

// Instancing (MAT only)
int TDInstanceID();

glslTOP

Docked DATs created automatically:

  • glsl1_pixel — Pixel shader
  • glsl1_compute — Compute shader
  • glsl1_info — Compile info

Pixel Shader Template

out vec4 fragColor;
void main() {
    vec4 color = texture(sTD2DInputs[0], vUV.st);
    fragColor = TDOutputSwizzle(color);
}

Compute Shader Template

layout (local_size_x = 8, local_size_y = 8) in;
void main() {
    vec4 color = texelFetch(sTD2DInputs[0], ivec2(gl_GlobalInvocationID.xy), 0);
    TDImageStoreOutput(0, gl_GlobalInvocationID, color);
}

Update Shader

op('/project1/glsl1_pixel').text = shader_code
op('/project1/glsl1').cook(force=True)
# Check errors:
print(op('/project1/glsl1_info').text)

glslMAT

Docked DATs:

  • glslmat1_vertex — Vertex shader (param: vdat)
  • glslmat1_pixel — Pixel shader (param: pdat)
  • glslmat1_info — Compile info

Note: MAT uses vdat/pdat, TOP uses vertexdat/pixeldat.

Vertex Shader Template

uniform float uTime;
void main() {
    vec3 pos = TDPos();
    pos.z += sin(pos.x * 3.0 + uTime) * 0.2;
    vec4 worldSpacePos = TDDeform(pos);
    gl_Position = TDWorldToProj(worldSpacePos);
}

Bayer 8x8 Dither Matrix

Reusable ordered dither function for retro/print aesthetics:

float bayer8(vec2 pos) {
    int x = int(mod(pos.x, 8.0)), y = int(mod(pos.y, 8.0)), idx = x + y * 8;
    int b[64] = int[64](
        0,32,8,40,2,34,10,42,48,16,56,24,50,18,58,26,
        12,44,4,36,14,46,6,38,60,28,52,20,62,30,54,22,
        3,35,11,43,1,33,9,41,51,19,59,27,49,17,57,25,
        15,47,7,39,13,45,5,37,63,31,55,23,61,29,53,21
    );
    return float(b[idx]) / 64.0;
}

glslPOP / glsladvancedPOP / glslcopyPOP

All use compute shaders. Docked DATs follow naming convention:

  • glsl1_compute / glsladv1_compute
  • glslcopy1_ptCompute / glslcopy1_vertCompute / glslcopy1_primCompute