How Do vec2, vec3, and vec4 Work in GLSL?

In the OpenGL Shading Language (GLSL), vec2, vec3, and vec4 are core floating-point vector types designed for high-performance graphics operations, representing data with two, three, and four components respectively. These vector types provide built-in hardware acceleration for geometric transformations, color manipulation, and spatial coordinates. Understanding how they handle initialization, arithmetic operations, and flexible component access is fundamental to writing efficient vertex and fragment shaders.

Vector Declarations and Initialization

GLSL vectors are strongly typed arrays of floating-point values. They can be instantiated with single values, combinations of scalars and smaller vectors, or fully defined component lists. When a single scalar is passed to a vector constructor, that value is broadcast to all components.

// Broadcasting a single scalar
vec3 white = vec3(1.0); // Equivalent to vec3(1.0, 1.0, 1.0)

// Explicit component assignment
vec2 uv = vec2(0.5, 0.5);
vec4 color = vec4(1.0, 0.0, 0.0, 1.0);

// Composite construction from smaller vectors
vec3 position3D = vec3(uv, 0.0);
vec4 position4D = vec4(position3D, 1.0);

Component Access and Swizzling

GLSL provides three interchangeable naming sets for accessing vector components: spatial coordinates ({x, y, z, w}), color channels ({r, g, b, a}), and texture coordinates ({s, t, p, q}). Each set corresponds to the identical underlying index (index 0, 1, 2, and 3).

Vector Type Valid Index Sets Example Components
vec2 x, y / r, g / s, t vec.x, vec.r, vec[0]
vec3 x, y, z / r, g, b / s, t, p vec.z, vec.b, vec[2]
vec4 x, y, z, w / r, g, b, a / s, t, p, q vec.w, vec.a, vec[3]

Swizzling allows you to rearrange, duplicate, or slice vector components directly via field selection:

vec4 rgba = vec4(0.2, 0.4, 0.6, 1.0);

// Reordering and duplicating components
vec3 bgr = rgba.bgr;       // vec3(0.6, 0.4, 0.2)
vec2 redundant = rgba.xx;   // vec2(0.2, 0.2)

// Writing to swizzled components (l-value swizzling)
vec3 pos = vec3(1.0, 2.0, 3.0);
pos.xy = vec2(5.0, 6.0);    // pos is now vec3(5.0, 6.0, 3.0)

Swizzling within an l-value (the left side of an assignment) requires that each component name appears only once.

Arithmetic and Built-in Operations

Vector operations in GLSL execute on a component-wise basis by default. When an operation occurs between two vectors of the same size, each corresponding pair of components is evaluated independently. When operating between a vector and a scalar, the scalar applies across every component.

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

vec3 sum = a + b;           // vec3(3.0, 5.0, 7.0)
vec3 scaled = a * 2.0;      // vec3(2.0, 4.0, 6.0)
vec3 modulated = a * b;     // vec3(2.0, 6.0, 12.0)

GLSL includes standard geometric functions designed specifically for these vector types: