Skip to content

Shader Interface

The operators, their uniforms and the built-in uniforms supplied to every shader are in the std/visuals reference.

A shader is a .glsl file loaded with gfx.load_shader(name, path), or the same source given as a string to gfx.Visual(name, source). It is a GLSL-ES 3.00 fragment shader:

  • It starts with #version 300 es and declares a default precision.
  • It writes its colour to an out vec4.
  • It reads its inputs as uniform sampler2D iChannel0;, iChannel1, …: the node fed in with >> is always iChannel0, and nodes bound to named inputs take the channels after it, in the order they were first bound.
  • Every sampler2D it declares must be bound. A graph with a shader that reads an input nothing is bound to is not drawn: routing it is an error, and the picture on screen stays.

It is compiled by the renderer when something draws it — an open visuals window, render(screen) or screen.snap() — not when it is loaded.

v.parameter(name) << value arrives in the shader as:

ValueGLSL declaration
a number, a signal, a meter feed (.rms, .peak, .fft.band(…))uniform float name;
an array of 2, 3 or 4 numbersuniform vec2 name;, vec3, vec4
a spectrum feed (.fft, .fft.smooth(…))uniform sampler2D name;
a table: an array of rows, each an array of numbers, all one lengthuniform sampler2D name;
a visual nodea texture input (iChannel1, …)

Binding a name again replaces what it was bound to. The built-in uniforms and the samplers iChannel0, iChannel1, … are supplied by the engine; binding one is an error.

PropertyValue
Size512 bins × 1 row, from a 1024-point FFT
Layoutread it at vec2(x, 0.5); x is 0 at the lowest bin and near 1 at the highest, linear in frequency
Valuethe bin’s magnitude in .r; a full-scale sine reads about 0.5 at its bin
Filteringnearest — no interpolation between bins

A table is a list of rows, such as the keys of a ramp: #[#[0, 0, 0, 0, 1], #[1, 1, 1, 1, 1]]. It holds 1 to 8192 rows, and every row has the same number of values.

PropertyValue
Sizeone texel across per row; one texel down per four values of a row
LayouttexelFetch(name, ivec2(i, 0), 0) is values 0 to 3 of row i, ivec2(i, 1) values 4 to 7, …; a value past the end of the row reads 0
RowstextureSize(name, 0).x
Value32-bit float, as bound

The texture is uploaded when the table is bound, not on each frame.