Touchdesigner - Shadertoy GLSL Integration

We are not going to teach you how to code GLSL shaders in Touchdesigner(in this post anyway!).

Instead - we are going to show you a great method to bring shaders into Touchdesigner, and begin learning the processes that went into making them!

In this tutorial we take a number of complex existing shaders from the popular website and utilise them (aka their code) directly in touchdesigner.

In this blog we are going to look at the more direct method of taking a single buffer shader as is quicker and more direct, subsequent buffer shaders simply require additional GLSL nodes in touch! ('buffer' is the term for collection or output of coloured (or not) pixels, in Touchdesigner outputting a fragColor is essentially one buffer.)

So have a wee look at 1:30 - 8:30 or so as that is the section of the video we are going to focus on.

The principle of converting a shader is fairly straight forward. The code is all there ready to go in the website, we need to load it into a GLSL TOP inside touch and convert a bunch of shadertoy specific parameters into some touchdesigner specific ones.

For those keen to learn: this is a great reference to go on when working with GLSL inside touchdesigner.

GLSL is simply the method of running and compiling normally short programs to be executed solely by the GPU. There are a number of advantages to this but the main ones cited are the speed and power of GPU's are far the multiple of a CPU's power.

Most GLSL programs (called shaders) are made off two operations, calculations on a pixel level, calculations on a vertex level.

The normal processing being Vertex > pixel > output. This allows for the creation of 3d geometry, the calculation of the colour of pixels to display and then actually outputting them to display. This is a trivial description but it serves the purpose. Go explore yourself!

To the tutorial:

We are going to take: This shadertoy shader, and get it to work correctly in Touchdesigner.

Like any programming language, GLSL shaders use variables and references to operate and calculate outcomes. These are normally called 'Uniforms' - globally accessible variables. In shadertoy a number of uniforms are given by default and we will need to think of ways to recreate and pass them into the code via Touchdesigner.

For reference, shadertoy provides global uniforms for:

  • uniform vec3 iResolution; // viewport resolution (in pixels)

  • uniform float iTime; // shader playback time (in seconds)

  • uniform float iTimeDelta; // render time (in seconds)

  • uniform int iFrame; // shader playback frame

  • uniform float iChannelTime[4]; // channel playback time (in seconds)

  • uniform vec3 iChannelResolution[4]; // channel resolution (in pixels)

  • uniform vec4 iMouse; // mouse pixel coords. xy: current (if MLB down), zw: click

  • uniform samplerXX iChannel0..3; // input channel. XX = 2D/Cube

  • uniform vec4 iDate; // (year, month, day, time in seconds)

To recreate these in touchdesigner we have two options:

A: we use the handy uniform variable page on the GLSL top to pass values into out code,

B: we utilise Touchdesigner GLSLTD references to access variables without the need for a hard reference to the network (Here is a Link to the TD specific uniforms)

1: swapping out the main render function

We start exploring this at the 2:55 mark in the video.

First thing we need to swap out is the rendering function. In shadertoy it will be something like 'void mainImage(out vec4 fragColor){}'

but Touchdesigner only listens for a blank 'void main(){}' function to make the final render calculation.

2: Setting up the fragColor output texture.

both TD and shadertoy use fragColor to define the final output of the shader. This is given in shadertoy but we will need to globally declare the variable to make it work in Touchdesigner.

We add 'layout (location = 0) out vec4 fragColor;' to the top of the GLSL code. word for word it tells the GPU to set memory aside and hold it at the very beginning for a 4 index vector that will be used as an output variable.

3: Setup all the other required variables being utilised.

If you attached an info dat to your GLSL top you can access a whole pile of compiled data from your shader, mainly this is a great way to tell whats broken and what needs fixed. We use it to tell which variables were hard coded in shadertoy, and we will need to add.

Jump to 4:52 in the video. We add the 'iResolution' uniform in the GLSL TOP menu, then reference it in the top of our GLSL pixel code.

We add 'iResolution' as a named uniform and give the first three varibles in the TOP form values based on the input images' resolution as we would with any touchdesigner reference.

We then define the variable at the top of the shader code using the name and correct vector size that we want. In this case:

'uniform vec3 iResolution;'

This is a simply process of getting data from your touchdesigner network into GLSL code as a variable. MAGIC!

We then do the same for 'iTime' as well.

4: Swap out all of the TD specific shader references.

This jumps back to the list I linked earlier on TD specific uniforms. Shadertoy and GLSL use references such as 'iChannel[0]' to reference data from the inputs in shadertoy, wether it be another buffer, image or music etc. in TD to reference the first input on the GLSL TOP we use the reference 'TD2DInput[0]' - this means we need to go and swap all of these out in the code.

The second important language difference is 'fragCoord' references in shadertoy need to be changed to 'gl_fragCoord' in touchdesigner as it uses a slightly more up-to-date version of the openGL language.

5: Other little things

Jump to 7:00 in the video. Here we deal with a couple of little formatting and language issues picked up by the info DAT attached to our GLSL (great example of its use). The specific issue we face in this video is that we swap fragCoord for gl_fragCoord that 2 and 4 vec variables respectively.

To address this we tell the shader to only look at the first two index of the variables by adding '.xy' to the 'gl_fragCoord.xy' reference.

The video does the implementation a lot of justice, so this blog should serve as supporting document for those that get lost, wanting a more general rule of thumb for shadertoy -> TD conversion!

Join the PfP mailing list