Using rayQueryGetIntersectionTypeEXT in GLSL

The rayQueryGetIntersectionTypeEXT function is an intrinsic defined in the GL_EXT_ray_query extension for GLSL, enabling developers to determine the status and geometry type of an intersection encountered during inline ray tracing. It allows shaders to inspect whether a candidate or committed hit represents a triangle primitive, a custom procedural primitive (AABB), or no hit at all. By classifying intersections during ray traversal or after traversal finishes, this function provides the branching logic necessary to handle visibility testing, custom intersection shaders, and shading calculations directly within compute or fragment shaders.

Function Signature and Parameters

The signature of the function is defined as follows:

uint rayQueryGetIntersectionTypeEXT(rayQueryEXT rayQuery, bool committed);
  • rayQuery: The inline ray query object initialized via rayQueryInitializeEXT that tracks the current ray traversal state.
  • committed: A boolean flag determining which stage of intersection evaluation is being inspected. Passing false inspects the active candidate intersection currently being evaluated within the traversal loop. Passing true inspects the final committed intersection, representing the closest or confirmed hit accepted by the ray query.

Return Values

The function returns an unsigned integer representing the intersection classification, corresponding to one of three built-in GLSL constants:

  • gl_RayQueryIntersectionNoneEXT (0): Indicates that no intersection has occurred. For candidate hits, this means traversal is ongoing without an active candidate. For committed hits, it indicates the ray missed all geometry.
  • gl_RayQueryIntersectionTriangleEXT (1): Indicates that the intersection occurred with built-in hardware triangle geometry.
  • gl_RayQueryIntersectionGeneratedEXT (2): Indicates that the intersection occurred with an axis-aligned bounding box (AABB) defining procedural geometry, requiring the shader to perform manual intersection testing.

Candidate vs. Committed Intersection Querying

Inline ray tracing does not rely on separate pipeline stages like Any-Hit or Intersection shaders. Instead, it handles traversal logic imperatively:

  1. Candidate Intersections (committed = false): Inside the rayQueryProceedEXT(rayQuery) traversal loop, the ray pauses when it encounters a potential hit that requires shader intervention—such as an opaque procedural primitive or non-opaque triangle. Invoking rayQueryGetIntersectionTypeEXT(rayQuery, false) lets the shader determine whether to perform alpha-testing on a triangle (using rayQueryConfirmIntersectionEXT) or evaluate an analytical shape inside an AABB (using rayQueryGenerateIntersectionEXT).
  2. Committed Intersections (committed = true): Once rayQueryProceedEXT returns false, ray traversal is complete. Calling rayQueryGetIntersectionTypeEXT(rayQuery, true) determines if the ray hit any surface. If the result is not gl_RayQueryIntersectionNoneEXT, the shader proceeds to retrieve hit attributes (such as barycentrics, instance ID, or hit distance) and calculate final lighting.

Typical Implementation Pattern

rayQueryEXT rayQuery;
rayQueryInitializeEXT(rayQuery, topLevelAS, gl_RayFlagsOpaqueEXT, 0xFF, origin, tMin, direction, tMax);

// Traversal loop
while (rayQueryProceedEXT(rayQuery)) {
    // Check candidate intersection type if non-opaque flags are used
    if (rayQueryGetIntersectionTypeEXT(rayQuery, false) == gl_RayQueryIntersectionTriangleEXT) {
        // Evaluate custom candidate logic if needed
        rayQueryConfirmIntersectionEXT(rayQuery);
    }
}

// Final evaluation
if (rayQueryGetIntersectionTypeEXT(rayQuery, true) != gl_RayQueryIntersectionNoneEXT) {
    // Ray hit a valid surface; proceed with shading
} else {
    // Ray missed all geometry; execute background or miss logic
}