Single Scalar Matrix Construction in GLSL

In the OpenGL Shading Language (GLSL), constructing a matrix using a single scalar value generates a diagonal matrix where the scalar is assigned to every component along the main diagonal, while all off-diagonal elements are set to zero. This article covers the exact mechanics of single-scalar matrix constructors, illustrates how they are used for identity and scaling transformations, and explains their behavior with both square and non-square matrices.

Diagonal Initialization Rule

When you pass a single scalar (such as a float) into any GLSL matrix constructor, the language assigns that value to all positions where the row index equals the column index (\(M_{i,i}\)). Every other entry (\(M_{i,j}\) where \(i \neq j\)) is initialized to 0.0.

Mathematically, passing a scalar \(s\) into a constructor creates:

\[ M_{i,j} = \begin{cases} s & \text{if } i = j \\ 0.0 & \text{if } i \neq j \end{cases} \]

Constructing Identity Matrices

The most common application of this behavior is generating an identity matrix. Passing 1.0 into a square matrix constructor places ones along the main diagonal and zeros everywhere else.

// Creates a 4x4 identity matrix
mat4 identity = mat4(1.0);

The resulting identity matrix evaluates to:

\[ \begin{bmatrix} 1.0 & 0.0 & 0.0 & 0.0 \\ 0.0 & 1.0 & 0.0 & 0.0 \\ 0.0 & 0.0 & 1.0 & 0.0 \\ 0.0 & 0.0 & 0.0 & 1.0 \end{bmatrix} \]

Non-Unit Scalar Matrices

If a value other than 1.0 is provided, that value populates the entire diagonal. This is useful for uniform scaling transformations.

// Creates a 3x3 diagonal scale matrix
mat3 scaleMatrix = mat3(2.5);

This constructor produces:

\[ \begin{bmatrix} 2.5 & 0.0 & 0.0 \\ 0.0 & 2.5 & 0.0 \\ 0.0 & 0.0 & 2.5 \end{bmatrix} \]

Behavior with Non-Square Matrices

GLSL supports non-square matrices (such as mat2x3, mat4x2, and mat3x4). When initialized with a single scalar, the same rule applies: elements where the row index equals the column index receive the scalar, while all remaining elements are set to zero.

For example, initializing a mat2x4 (2 columns, 4 rows) with a scalar:

mat2x4 m = mat2x4(3.0);

Because there are only two columns, the diagonal only covers indices [0][0] and [1][1]:

\[ \begin{bmatrix} 3.0 & 0.0 \\ 0.0 & 3.0 \\ 0.0 & 0.0 \\ 0.0 & 0.0 \end{bmatrix} \]

Type Requirements

The scalar passed to standard floating-point matrices (mat2, mat3, mat4, etc.) must match the underlying component type of the matrix or be implicitly convertible. In standard GLSL:

  • Use floating-point literals (e.g., mat4(1.0)) instead of integers (mat4(1)), as older GLSL versions or strict profiles do not implicitly cast int to float.
  • For double-precision matrices (dmat2, dmat3, dmat4), pass a double literal (e.g., dmat4(1.0lf)).