The Interactive & Immersive HQ

How To Use Uniforms in the GLSL TOP in TouchDesigner

In TouchDesigner, the integration of native operators with advanced scripting and shading languages significantly enhances its functionality. In this article, we’ll delve into the specifics of how to use uniforms in GLSL in TouchDesigner to integrate values coming from CHOPs and Table DATs into our real-time GLSL shaders. By understanding and utilizing uniforms, is possible to efficiently pass dynamic data into shaders, facilitating more complex and responsive visual effects in projects.

THE GLSL TOP

GLSL (OpenGL Shading Language) is a powerful, low-level shading language used extensively for graphics rendering. In TouchDesigner, the GLSL TOP allows you to write custom shaders directly within the platform. This feature unlocks the ability to create highly customized visual effects and dynamic graphics that are not possible with standard Operators alone. GLSL TOPs operate by compiling and executing GLSL code, rendering the results in real-time.

What are Uniforms

Uniforms in GLSL are a type of variable used to pass data from TouchDesigner into the shaders. They serve as parameters that users can manipulate to influence shader behavior. This is done without altering the underlying shader code, but rather through the integration with TouchDesigner’s operators, such as CHOPs, TOPs, and DATs. For instance, you can pass a Constant CHOP Channel value as a uniform to change the lighting in a scene, or input sound levels to modify visual elements dynamically.

  • Types of Uniforms: You can pass various types of data through uniforms, including:
    • Single values: Such as floats or integers (e.g., a volume level or a toggle switch).
    • Vectors: To represent positions, colors, or other multi-dimensional data.
    • Matrices: Often used for transformations or to pass complex camera information.
    • Atomic Counters: are type of buffer object that supports thread-safe atomic operations on a shared unsigned integer, enabling concurrent modifications.

Using Uniforms in TouchDesigner

To effectively use uniforms in your GLSL shaders within TouchDesigner, you’ll typically follow these steps:

  1. Make sure your Data is on the right format: Because Uniforms can be Scalar or Vector values, you want to make sure your data is in the correct format. Sometimes that means using a TOP to CHOP operator, for examples, before moving to referencing your Uniforms.
  2. Reference the Uniform in your GLSL Top Page: Depending on the type of uniform you are declaring you can reference your Data as Arrays, Vectors, Matrices, Atomic Counters
  3. Declare the uniform in your shader code: To Declare a Uniform start by saying is a uniform followed by the type of uniform and finally by the name. For example, uniform float time; allows you to pass a floating-point value representing time into your shader. In the case of vector uniforms, you declare how many components make part of your vector.
  4. Use your uniform in your shader: Once a Uniform is declared at the top of an GLSL TOP you can use it.

Example 1: Using a Color Constant TOP in our GLSL TOP

For this first example, we will start with something quite simple: using the Values of a Constant TOP as our Uniform to render a single complementary color.

1. Create our constant Top. Because GLSL Uniforms can only be either scalar or vector values, we need to pass our constant through a TOP to CHOP followed by an Analyze CHOP. We use a Null at the end for organization.

2. Reference the Analyze CHOP in out GLSL TOP. There’s two ways we can do this:

  • Through the Arrays Page of the GLSL TOP, by specifying is a vector 4, and bringing in the Null
Use Uniforms in the GLSL TOP in TouchDesigner
  • Through the Vector Page of the GLSL TOP, referencing each Channel of our CHOP. While the Arrays Page forces you to use one CHOP per vector, using the Vector Page is possible to reference different CHOPS and parameters to create a vector.
Use Uniforms in the GLSL TOP in TouchDesigner

3. Declare your Uniforms: For this example, I declared both my Uniforms as Vector 4. If instead of using Vec4 I had used Vec2, the shader would only reference the first 2 values. To Declare a Uniform start by saying is a uniform followed by the type of uniform and finally by the name. Once uniforms are declared they can be referenced in functions. In this case we want to invert the color using a one minus operation.

// Start by declaring your uniforms.
uniform vec4 color1; //uniform referenced in the Vectors Page 
uniform vec4 color2; //uniform referenced in the Arrays Page
out vec4 fragColor;


void main()
{
	
	fragColor = 1-color2;
}

Example 2: Using two Uniforms to Mix 2D Inputs

For the second example we will use two different Uniforms inputs: One Uniform is a Vector 2 that will define the output resolution of our GLSL TOP, while the second Uniform is a float value that uses the position of our mouse to mix two image inputs in the GLSL TOP.

1. Create the CHOPs that will carry the data our Uniforms will use. In this case I have two CHOPs. One is a resolution CHOP that has a resx and a resy value. The second one is a uMix CHOP. This CHOP is the result of processing my mouse position in the X axis.

2. Reference the Resolution CHOP and the uMix CHOP: The resolution CHOP is referenced as Vector 2 Uniform, while the uMix as a Float Array

Use Uniforms in the GLSL TOP in TouchDesigner
Use Uniforms in the GLSL TOP in TouchDesigner

3. Declare your uniforms in the GLSL TOP: Just like last time, we start by declaring our Uniforms. Following the same structure, uniform followed by type followed by name.

4. Connect your source images: Images sources can be directly connected to the GLSL TOP inputs. The way we reference them in the Shader code is using sTD2DInputs[Number_of_input] For example, an image in the first input would be: sTD2DInputs[0].

//Declare your Uniforms
uniform vec2 resolution;
uniform float uMix;
out vec4 fragColor;

void main()
{
    vec2 uv = gl_FragCoord.xy / resolution;  // Normalized pixel coordinates
    vec4 noiseColor = texture(sTD2DInputs[0], uv.st);     // Fetch the noise texture
    vec4 imageColor = texture(sTD2DInputs[1], uv.st);     // Fetch the second image texture

    // Use the noise to modify the image color or any other effect
    float mixFactor = noiseColor.r*uMix;  // Use the red channel of the noiseColor to determine mix factor and multiply it by uMix
    fragColor = mix(imageColor, noiseColor, mixFactor);  // Blend the two textures
}

Get Our 7 Core TouchDesigner Templates, FREE

We’re making our 7 core project file templates available – for free.

These templates shed light into the most useful and sometimes obtuse features of TouchDesigner.

They’re designed to be immediately applicable for the complete TouchDesigner beginner, while also providing inspiration for the advanced user.

Example 3: Using Uniforms in GLSL Multi TOP

For this third example we will be using Uniforms to control the cut-out distance of our depth sensing camera using the GLSL Multi TOP. To take a deeper look on how we are using GLSL to control the depth cut-out distance of our camera, refer to this great tutorial by Elburz where he goes into detail on what’s happening in our GLSL code.

1. Start by setting up our CHOPs. In this case, I want to use a Table DAT as a data source for the changes I want to do in my GLSL Multi TOP. I also have a Kinect Point Cloud Image as source for my GLSL Multi Top

2. Reference Uniform Values: There’s two ways I could pass my values as a Uniform:

  • Use a DAT to CHOP operator and use those values either as float Arrays or as a Vector value.
  • Directly reference my table values in the Vector Page of my GLSL Multi TOP. I’ll be using this method.
Use Uniforms in the GLSL TOP in TouchDesigner

3. Declare your Uniforms: Even though we declared our Uniform as a Vector 2, is possible to access each component of the vector individually using r, g, b, a or x, y, z, w annotation. In this case we are telling our GLSL Multi TOP to take the first component of our bValue vector 2 Uniform and compare it to color.b (another component of a color vector) and whenever the color.b is less than b.Valuesx, make the pixels color =0.

//Declare your Uniforms
uniform vec2 bValues;
out vec4 fragColor;

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

	if (color.b < bValues.x) { //Uses only the first value of the Vec2
	color = vec4(0.);
	}
	
	if (color.b > bValues.y) { //Uses only the second value of the Vec2
	color = vec4(0.);
	}
	
	fragColor = TDOutputSwizzle(color);
}

Conclusion

The integration of uniforms in the GLSL TOP in TouchDesigner not only simplifies the process of creating and manipulating shaders but also significantly enhances the flexibility and interactivity of visual projects. By effectively utilizing these powerful tools, you can push the boundaries of what’s possible in real-time graphics and interactive installations. These examples are just a starting point to the full potential of uniforms in your TouchDesigner projects.