Understanding gl_WorldToObjectEXT in GLSL

In GLSL ray tracing pipelines using the GL_EXT_ray_tracing extension, gl_WorldToObjectEXT is a built-in matrix uniform that transforms spatial data from world coordinate space into the local object coordinate space of the current geometry instance. This article breaks down the mathematical definition of this 4x3 matrix, its role in intersection and hit shaders, and how to use it to transform ray origins, directions, and arbitrary points for geometric calculations.

Definition and Structure

The variable gl_WorldToObjectEXT is defined as a mat4x3 in GLSL. In standard mathematical notation, it represents an affine transformation matrix consisting of 3 rows and 4 columns, which drops the conventional fourth row [0, 0, 0, 1]. In GLSL column-major notation, a mat4x3 consists of four column vectors of three components each.

This matrix is the exact inverse of the current instance's transformation matrix (gl_ObjectToWorldEXT). When instances are placed into a Top-Level Acceleration Structure (TLAS) referencing a Bottom-Level Acceleration Structure (BLAS), each instance is assigned a 4x3 affine transformation. During traversal, the ray tracing hardware or driver inverts this instance transform to yield gl_WorldToObjectEXT.

Function in Intersection Shaders

Ray generation and scene-level traversal occur in world space. Consequently, rays entering an intersection shader are defined by world-space origins and directions:

  • gl_WorldRayOriginEXT: The ray origin in world coordinates.
  • gl_WorldRayDirectionEXT: The ray direction vector in world coordinates.

Intersection shaders are responsible for determining whether a ray intersects custom procedural geometry (such as an analytical sphere, capsule, or bounding volume). Evaluating intersections in world space requires deforming the geometric formulas according to instance rotation, scaling, and translation.

Instead of complicating the intersection logic, the standard practice is to transform the incoming world-space ray into the object's local coordinate space, where the geometry is defined in its canonical, undeformed form.

Applying the Matrix

Because gl_WorldToObjectEXT is a 4x3 affine transform, it applies both linear operations (rotation and scale) and translations.

To transform a world-space point or ray origin:

vec3 objectRayOrigin = gl_WorldToObjectEXT * vec4(gl_WorldRayOriginEXT, 1.0);

Using 1.0 as the \(w\)-component enables the translation component of the matrix.

To transform a direction vector (such as the ray direction):

vec3 objectRayDirection = gl_WorldToObjectEXT * vec4(gl_WorldRayDirectionEXT, 0.0);

Using 0.0 as the \(w\)-component ignores the translation component, preserving only rotation and scaling. Note that non-uniform scaling will alter the length of the transformed direction vector, meaning objectRayDirection may need to be normalized if your intersection test assumes a unit-length ray direction.

Alternatively, the GLSL ray tracing extension provides gl_ObjectRayOriginEXT and gl_ObjectRayDirectionEXT, which are precomputed values derived directly from multiplying the world-space ray parameters by gl_WorldToObjectEXT.

Transforming Surface Normals

gl_WorldToObjectEXT is also useful outside intersection shaders, such as in closest-hit shaders, when mapping vectors in reverse. Because the transpose of the inverse matrix transforms normal vectors across affine spaces, the transpose of gl_WorldToObjectEXT acts directly as the forward transformation matrix for converting object-space normal vectors into world-space normal vectors:

vec3 worldNormal = normalize(transpose(mat3(gl_WorldToObjectEXT)) * objectNormal);

Using gl_WorldToObjectEXT ensures custom intersection algorithms remain decoupled from world-space placement, maintaining performance and numerical stability across arbitrary instance transformations.