6 · GLSL Reference
Chapter 6

GLSL Reference

A quick reference for the GLSL shading language as used in Shadertoy.


6.1Types

6.1.1Scalars

float x = 1.0;      // floating point (always use decimal)
int i = 5;          // integer
bool b = true;      // boolean

6.1.2Vectors

Vectors hold 2, 3, or 4 components of the same type:

vec2 p = vec2(1.0, 2.0);          // 2 floats
vec3 color = vec3(1.0, 0.5, 0.0); // 3 floats
vec4 rgba = vec4(1.0, 0.5, 0.0, 1.0); // 4 floats

ivec2 pixel = ivec2(10, 20);      // 2 ints
ivec3 coords = ivec3(1, 2, 3);    // 3 ints

bvec2 flags = bvec2(true, false); // 2 bools

6.1.3Matrices

Matrices are column-major (columns are listed first):

mat2 m2;  // 2×2 matrix
mat3 m3;  // 3×3 matrix
mat4 m4;  // 4×4 matrix

A mat2 holds 4 floats, a mat3 holds 9, a mat4 holds 16.

6.1.4Samplers

Used to read from textures and buffers:

sampler2D tex;  // 2D texture (you won't declare these yourself in Shadertoy)

6.2Components and Constructors

6.2.1Component Access

Vectors have named components. Two naming conventions exist — use whichever fits your context:

vec4 v = vec4(1.0, 2.0, 3.0, 4.0);

// Position names
v.x, v.y, v.z, v.w  // 1.0, 2.0, 3.0, 4.0

// Color names (equivalent)
v.r, v.g, v.b, v.a  // 1.0, 2.0, 3.0, 4.0

For vec2, only .xy or .rg are available. For vec3, .xyz or .rgb.

6.2.2Rearranging Components

You can read multiple components at once, in any order:

vec3 v = vec3(1.0, 2.0, 3.0);

vec2 a = v.xy;   // (1.0, 2.0)
vec2 b = v.yx;   // (2.0, 1.0)
vec3 c = v.zyx;  // (3.0, 2.0, 1.0)
vec3 d = v.xxx;  // (1.0, 1.0, 1.0)

This also works for assignment:

v.xy = v.yx;  // swap x and y

6.2.3Constructors

Vectors can be built from scalars, smaller vectors, or combinations:

vec3 a = vec3(1.0);              // (1.0, 1.0, 1.0)
vec3 b = vec3(1.0, 2.0, 3.0);    // (1.0, 2.0, 3.0)

vec2 p = vec2(1.0, 2.0);
vec3 c = vec3(p, 3.0);           // (1.0, 2.0, 3.0)
vec4 d = vec4(p, p);             // (1.0, 2.0, 1.0, 2.0)

vec3 color = vec3(0.5, 0.7, 1.0);
vec4 rgba = vec4(color, 1.0);    // (0.5, 0.7, 1.0, 1.0)

6.3Operators

6.3.1Arithmetic on Vectors

Arithmetic operators work component-wise:

vec3 a = vec3(1.0, 2.0, 3.0);
vec3 b = vec3(4.0, 5.0, 6.0);

a + b   // (5.0, 7.0, 9.0)
a - b   // (-3.0, -3.0, -3.0)
a * b   // (4.0, 10.0, 18.0)  — component-wise, NOT dot product
a / b   // (0.25, 0.4, 0.5)

6.3.2Scalar-Vector Operations

A scalar operates on each component:

vec3 v = vec3(1.0, 2.0, 3.0);

v * 2.0   // (2.0, 4.0, 6.0)
v + 1.0   // (2.0, 3.0, 4.0)
1.0 / v   // (1.0, 0.5, 0.333...)

6.3.3Matrix-Vector Multiplication

Matrix times vector applies the linear transformation:

mat2 m = mat2(cos(a), sin(a), -sin(a), cos(a));  // rotation matrix
vec2 v = vec2(1.0, 0.0);
vec2 rotated = m * v;  // matrix on the left

For mat3 * vec3 and mat4 * vec4, same pattern.


6.4Built-in Functions

6.4.1Trigonometric

All angles are in radians.

FunctionDescription
sin(x)Sine
cos(x)Cosine
tan(x)Tangent
asin(x)Arc sine, returns [ 𝜋/2,𝜋/2]
acos(x)Arc cosine, returns [0,𝜋]
atan(y, x)Arc tangent of y/x, returns [ 𝜋,𝜋]
atan(y_over_x)Arc tangent, returns [ 𝜋/2,𝜋/2]

6.4.2Exponential

FunctionDescription
pow(x, y)𝑥𝑦
exp(x)𝑒𝑥
log(x)ln(𝑥)
exp2(x)2𝑥
log2(x)log2(𝑥)
sqrt(x)𝑥
inversesqrt(x)1/𝑥

6.4.3Common

FunctionDescription
abs(x)Absolute value
sign(x)Returns 1, 0, or 1
floor(x)Largest integer 𝑥
ceil(x)Smallest integer 𝑥
fract(x)𝑥 floor(𝑥), the fractional part
mod(x, y)𝑥 𝑦 floor(𝑥/𝑦)
min(x, y)Minimum
max(x, y)Maximum
clamp(x, lo, hi)Clamps x to [lo,hi]
mix(a, b, t)Linear interpolation: 𝑎(1 𝑡) +𝑏𝑡
step(edge, x)0 if 𝑥 <edge, else 1
smoothstep(e0, e1, x)Smooth transition from 0 to 1

6.4.4Geometric

FunctionDescription
length(v)Euclidean length 𝑣
distance(a, b)Distance 𝑎 𝑏
dot(a, b)Dot product 𝑎 𝑏
cross(a, b)Cross product (vec3 only)
normalize(v)Unit vector 𝑣/𝑣
reflect(I, N)Reflection of I about normal N
refract(I, N, eta)Refraction with index ratio eta

6.4.5Gotchas

atan(y, x) not atan(x, y) — The two-argument arctangent takes y first:

float angle = atan(p.y, p.x);  // correct
float angle = atan(p.x, p.y);  // wrong — rotated 90°

mod on negatives — The result has the same sign as the divisor:

mod(-0.5, 1.0)   // returns 0.5, not -0.5
mod(-1.5, 1.0)   // returns 0.5

This is usually what you want for wrapping coordinates, but can surprise you.

pow with negative base — Undefined for non-integer exponents:

pow(-2.0, 2.0)   // undefined (may return NaN or 0)
pow(abs(x), y)   // safe alternative

6.5Shadertoy Uniforms

Shadertoy provides these global variables:

6.5.1Resolution and Time

UniformTypeDescription
iResolutionvec3Viewport resolution in pixels (.xy is width, height)
iTimefloatSeconds since shader started
iTimeDeltafloatSeconds since last frame
iFrameintFrame number (starts at 0)

6.5.2Mouse

iMouse is a vec4:

ComponentDescription
iMouse.xyCurrent mouse position (pixels) while button held, else last click position
iMouse.zwPosition where button was pressed (positive if currently held, negative after release)

Common patterns:

// Normalize mouse to [0, 1]
vec2 mouse = iMouse.xy / iResolution.xy;

// Check if mouse button is held
bool mouseDown = iMouse.z > 0.0;

6.5.3Channels

UniformTypeDescription
iChannel0iChannel3sampler2DTexture or buffer inputs
iChannelResolution[0–3]vec3Resolution of each channel

6.5.4Date

UniformTypeDescription
iDatevec4(year, month, day, seconds since midnight)

6.6Textures & Buffers

6.6.1Reading Textures

Interpolated sampling — UV coordinates in [0,1]:

vec4 color = texture(iChannel0, uv);

The texture wraps or clamps depending on Shadertoy settings for that channel.

Exact pixel fetch — integer coordinates:

vec4 color = texelFetch(iChannel0, ivec2(x, y), 0);

The third argument (0) is the mipmap level; always use 0 in Shadertoy.

6.6.2Buffers

Shadertoy provides four buffers: Buf A, Buf B, Buf C, Buf D. Each runs its own shader and outputs to a texture you can read from other tabs.

Reading the previous frame (for simulations):

  1. In Buf A, set iChannel0 to point to Buf A itself

  2. Read with texelFetch(iChannel0, ivec2(fragCoord), 0)

  3. Write new state to fragColor

// In Buffer A
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    ivec2 px = ivec2(fragCoord);
    vec4 prev = texelFetch(iChannel0, px, 0);  // previous frame
    
    // ... compute new state ...
    
    fragColor = newState;
}

Reading a buffer in Image:

Set iChannel0 (or any channel) to the buffer, then sample it:

// In Image
vec4 state = texelFetch(iChannel0, ivec2(fragCoord), 0);

6.6.3The Common Tab

Code in the Common tab is included in all other tabs. Use it for:

  • Shared constants (const float PI = 3.14159;)

  • Shared functions (vec3 hsv2rgb(...))

  • Shared struct definitions

// In Common
const float PI = 3.14159265359;
const float TAU = 6.28318530718;

vec3 hsv2rgb(vec3 c) {
    vec3 p = abs(fract(c.xxx + vec3(0.0, 2.0/3.0, 1.0/3.0)) * 6.0 - 3.0);
    return c.z * mix(vec3(1.0), clamp(p - 1.0, 0.0, 1.0), c.y);
}

6.7Syntax Pitfalls

6.7.1Floats Need Decimals

float x = 1;    // ERROR
float x = 1.0;  // correct

vec3 v = vec3(1, 2, 3);      // ERROR (in some contexts)
vec3 v = vec3(1.0, 2.0, 3.0); // correct

6.7.2Functions Must Be Declared Before Use

Unlike C, there are no forward declarations. Define helper functions above mainImage:

// This must come first
float sdf(vec3 p) {
    return length(p) - 1.0;
}

// Then this can call it
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    // ... sdf(p) works here ...
}

6.7.3No Overloading by Return Type

You can overload by parameter types, but not by return type alone:

float foo(float x) { return x; }
vec3 foo(float x) { return vec3(x); }  // ERROR — conflicts with above

6.7.4Constants

Use const for compile-time constants:

const float PI = 3.14159265359;
const int MAX_STEPS = 100;
const vec3 LIGHT_DIR = normalize(vec3(1.0, 1.0, 1.0));

These can be used in loop bounds and array sizes (unlike regular variables).

6.7.5Integer Division

Division between integers is integer division:

int a = 5 / 2;    // a = 2, not 2.5
float b = 5 / 2;  // b = 2.0 (still integer division, then converted)
float c = 5.0 / 2.0;  // c = 2.5 (correct)