GLSL Vector Swizzle Concatenation Explained

In OpenGL Shading Language (GLSL), vector constructors provide a flexible mechanism for creating new vectors by assembling components from existing vectors, matrices, and scalars. This article explains how vector constructors use swizzling to extract, rearrange, and concatenate components from multiple sources to instantiate a target vector, covering syntax, component-order mechanics, and compiler rules.

The Mechanics of Vector Constructors

GLSL vector constructors are polymorphic functions that accept an arbitrary combination of scalar values and vector types, as long as the total number of provided components meets the requirements of the vector being instantiated. The constructor consumes arguments from left to right, flattening each argument into its individual scalar components and placing them sequentially into the target vector's internal memory layout.

For example, constructing a vec4 requires four floating-point components. These can be supplied as four separate scalars, two vec2 instances, a vec3 and a float, or a single vec4.

Swizzling as Constructor Arguments

Swizzling allows you to access vector components out of order, duplicate them, or select a specific subset using coordinate namespaces:

  • Position: x, y, z, w
  • Color: r, g, b, a
  • Texture coordinates: s, t, p, q

When a swizzle operator is applied to a vector within a constructor argument, it produces an intermediate vector or scalar consisting only of the selected components in the specified order.

vec3 original = vec3(1.0, 2.0, 3.0);
vec2 subset = original.zx; // Yields vec2(3.0, 1.0)

Concatenating Swizzled Components

Vector swizzle concatenation occurs when multiple swizzled expressions (or a mix of swizzles and scalars) are passed as separate arguments to a constructor. The constructor evaluates each swizzle expression, determines its component count, and appends those components in sequence.

Consider this example:

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

// Concatenating swizzles to form a vec4
vec4 combined = vec4(a.zy, b.yx);

The constructor processes the arguments in the following order:

  1. a.zy is evaluated into a 2-component vector containing (3.0, 2.0).
  2. b.yx is evaluated into a 2-component vector containing (5.0, 4.0).
  3. The components are concatenated sequentially: index 0 receives 3.0, index 1 receives 2.0, index 2 receives 5.0, and index 3 receives 4.0.
  4. The result is vec4(3.0, 2.0, 5.0, 4.0).

You can freely mix scalars and arbitrary swizzle lengths:

vec4 v = vec4(10.0, 20.0, 30.0, 40.0);

// Concatenating a single component, a swizzled pair, and a scalar literal
vec4 reordered = vec4(v.w, v.yy, 0.5); 
// Results in vec4(40.0, 20.0, 20.0, 0.5)

Compiler Rules and Constraints

To ensure valid concatenation within constructors, specific GLSL rules must be observed:

  • Total Component Count: The sum of all components from the swizzled arguments and scalars must equal the size of the vector being constructed. Providing fewer components results in a compile-time error. Passing more components than required is permitted only when downcasting from a single vector (e.g., vec3(someVec4)), not when chaining multiple arguments.
  • Type Homogeneity: All components fed into the constructor must match the base data type of the target vector (e.g., float for vecN, int for ivecN, bool for bvecN), unless explicitly cast.
  • Namespace Consistency per Swizzle: While you can use different namespaces across separate arguments (e.g., vec4(color.rg, position.xy)), you cannot mix namespaces within a single swizzle operator (e.g., color.rx is invalid).