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:
dot(vecA, vecB): Computes the scalar dot product.cross(vec3A, vec3B): Computes the cross product (defined only forvec3).length(vecA): Calculates the Euclidean norm of the vector.normalize(vecA): Scales the vector to unit length (\(1.0\)).reflect(incident, normal): Calculates reflection direction against a surface normal.