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.