hitAttributeEXT Barycentric Coordinates in GLSL

This article explains the role of the hitAttributeEXT storage qualifier in GLSL ray tracing pipelines, focusing on how it captures barycentric coordinates during ray-primitive intersections. You will learn how these coordinates are passed from intersection testing to hit shaders and how they are applied mathematically to interpolate per-vertex attributes such as normals, texture coordinates, and colors across a hit triangle.

In hardware-accelerated ray tracing via Vulkan and the GL_EXT_ray_tracing extension, the hitAttributeEXT qualifier declares user-defined or built-in variables that communicate intersection data between shader stages. When a ray intersects geometry, the intersection pipeline calculates the exact contact point. For standard built-in triangle geometry, the fixed-function ray tracing hardware calculates the barycentric coordinates of the hit point and writes them into a variable declared with hitAttributeEXT.

In GLSL, this variable is typically declared in an any-hit or closest-hit shader as:

hitAttributeEXT vec2 attribs;

The primary function of hitAttributeEXT in this context is to provide the two floating-point values—commonly denoted as \(u\) and \(v\)—that define the location of the intersection relative to the triangle's vertices. Because the sum of barycentric weights equals \(1.0\), the hardware only needs to output two components. The third weight, \(w\), is implicitly calculated in the shader:

\[w = 1.0 - attribs.x - attribs.y\]

Once these weights are available, the shader uses them to perform linear interpolation of arbitrary vertex data. In a rasterization pipeline, the GPU rasterizer automatically interpolates vertex attributes before executing the fragment shader. In a ray tracing pipeline, the developer must manually fetch the three vertices of the intersected primitive from memory buffers and perform this interpolation using the barycentric weights supplied by hitAttributeEXT:

\[\text{InterpolatedValue} = (w \cdot \text{Vertex}_0) + (attribs.x \cdot \text{Vertex}_1) + (attribs.y \cdot \text{Vertex}_2)\]

This manual reconstruction is necessary for:

  • Surface Normals: Producing smooth shading by interpolating per-vertex normal vectors rather than relying on a single flat geometric normal.
  • Texture Coordinates (UVs): Sampling material textures at the precise ray hit position for albedo, roughness, and normal maps.
  • Vertex Colors and Tangents: Blending multi-vertex properties required for tangent-space calculations and custom per-vertex shading effects.

Without hitAttributeEXT, closest-hit and any-hit shaders would have access to the identity of the hit primitive (via gl_PrimitiveID), but lack the sub-primitive spatial precision required to calculate smooth surface details and accurate material properties at the ray impact site.