Vectors, Matrices & Swizzling
Swizzle sets: xyzw or rgba (don't mix within one swizzle).
8.1 Construction & swizzles
Swizzle sets: xyzw or rgba (don't mix within one swizzle).
float4 v = float4(1, 2, 3, 4);
float3 a = float3(v.xy, 5); // (1, 2, 5)
float4 b = float4(a, 1);
float2 c = v.zw; // (3, 4)
float4 d = v.wzyx; // reversed
float3 e = v.rrr; // color names: r g b a
v.xy = float2(0, 0); // write mask
// v.xx = 1; // error: duplicate components in an l-value
float s = v[2]; // indexing → 38.2 Component-wise arithmetic
float3 p = float3(1, 2, 3), q = float3(4, 5, 6);
float3 sum = p + q; // (5, 7, 9)
float3 prod = p * q; // (4, 10, 18) — component-wise!
float3 sc = p * 2.0; // scalar broadcast
bool3 lt = p < q; // component-wise comparison → bool3
bool allLt = all(p < q);
float d = dot(p, q); // 32
float3 x = cross(p, q); // (-3, 6, -3)8.3 Matrices
HLSL has no inverse() intrinsic. Compute inverses on the CPU (DirectXMath XMMatrixInverse) and upload them, or write your own adjugate-based function.
float4x4 M = {
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
5, 6, 7, 1 // fourth ROW
};
float m23 = M[1][2]; // row 1, column 2 (zero-based)
float4 row = M[3]; // (5, 6, 7, 1)
float e = M._m31; // zero-based member: row 3, column 1 → 6
float e1 = M._42; // one-based member: row 4, column 2 → 6
float4 v = float4(1, 1, 1, 1);
float4 r1 = mul(v, M); // row vector × matrix (v treated as 1×4)
float4 r2 = mul(M, v); // matrix × column vector (v treated as 4×1)
float4x4 C = mul(A, B); // matrix product
float4x4 W = A * B; // component-wise product — NOT matrix multiplication!
float4x4 T = transpose(M);
float det = determinant(M);
float3x3 R = (float3x3)M; // upper-left 3×38.4 Row-major vs column-major (the #1 source of confusion)
Two independent things:
Math convention — row vectors mul(v, M) (classic D3DX/DirectXMath style: v * World * View * Proj) vs column vectors mul(M, v). mul(v, M) == mul(transpose(M), v).
Memory packing — how matrices are stored in cbuffers. HLSL's default is column_major packing (each register holds a column), while DirectXMath stores row-major in memory.
DirectXMath, no transpose on upload default (column_major) mul(M, v) (the matrix appears transposed, which flips the convention)
DirectXMath, XMMatrixTranspose before upload mul(v, M) — the classic D3D sample convention DirectXMath, no transpose row_major float4x4 M; or -Zpr GLM (column-major, column vectors)
Pick one convention for the whole project and document it. Control packing with row_major/column_major keywords, #pragma pack_matrix(row_major), or dxc -Zpr / -Zpc.