How Does Vector Swizzling Work in GLSL?

Vector component swizzling in OpenGL Shading Language (GLSL) is a syntax feature that allows developers to access, reorder, duplicate, and construct vector components using concise dot-notation. This article explores how swizzle operators work, the distinct component naming sets available, rules for using swizzles as r-values and l-values, and common practical use cases in shader development.

Vector Component Sets

GLSL provides built-in vector types (vec2, vec3, vec4) for floating-point values, as well as integer (ivec), unsigned integer (uvec), and boolean (bvec) variants. To access the internal components of these vectors, GLSL defines three interchangeable naming sets:

Each set corresponds to indices 0, 1, 2, and 3 in the vector array. For example, in a vec4, v.x, v.r, and v.s all access the first component.

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

float first  = data.x; // 1.0
float second = data.g; // 2.0
float third  = data.p; // 3.0

GLSL requires that you do not mix different naming sets within a single swizzle expression. For instance, data.xy is valid, but data.xg will cause a compile-time error.

Reading and Reordering Components

When reading from a vector (using swizzle as an r-value), components can be extracted in any order, repeated, or truncated to produce a new vector of matching length.

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

// Selecting and reordering
vec3 reversed = original.zyx;      // vec3(3.0, 2.0, 1.0)

// Duplicating components
vec4 repeated = original.xxxx;     // vec4(1.0, 1.0, 1.0, 1.0)

// Creating subsets
vec2 coords   = original.xy;       // vec2(1.0, 2.0)
vec3 rgb      = original.rgb;      // vec3(1.0, 2.0, 3.0)

The resulting type depends strictly on the number of swizzled fields: one field yields a scalar (float), two yield a vec2, three yield a vec3, and four yield a vec4.

Writing to Components

Swizzling can also be used on the left-hand side of an assignment (as an l-value) to modify specific channels of a target vector.

vec4 color = vec4(0.0);

color.rgb = vec3(1.0, 0.5, 0.2); // color is now (1.0, 0.5, 0.2, 0.0)
color.a = 1.0;                   // color is now (1.0, 0.5, 0.2, 1.0)
color.ba = vec2(0.8, 0.9);       // color is now (1.0, 0.5, 0.8, 0.9)

When swizzling as an l-value, two primary restrictions apply:

  1. No Duplicates: You cannot repeat components on the left side of an assignment. An expression like color.xx = vec2(1.0, 2.0); is invalid because the compiler cannot determine which value should be written to the x component.
  2. Dimension Matching: The number of components in the swizzle selector must match the dimensions of the expression on the right side.

Practical Applications

Swizzling reduces boilerplate code and improves performance by minimizing intermediate variable declarations in shader pipelines: