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:
a.zyis evaluated into a 2-component vector containing(3.0, 2.0).b.yxis evaluated into a 2-component vector containing(5.0, 4.0).- The components are concatenated sequentially: index 0 receives
3.0, index 1 receives2.0, index 2 receives5.0, and index 3 receives4.0. - 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.,
floatforvecN,intforivecN,boolforbvecN), 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.rxis invalid).