How gl_SampleID Identifies Samples in GLSL

This article explains how the built-in gl_SampleID input variable operates within OpenGL Shading Language (GLSL) to identify specific sub-pixel samples. It covers the transition from standard pixel-frequency shading to per-sample frequency shading, the zero-based indexing mechanism used by the graphics pipeline, and how gl_SampleID interacts with related sample-rate built-ins during multisample anti-aliasing (MSAA) rendering.

The Role of gl_SampleID

In GLSL, gl_SampleID is a built-in fragment shader input variable defined as a signed integer (in int gl_SampleID;). Its primary role is to serve as an integer index that uniquely identifies the sub-pixel sample currently being processed by the fragment shader instance.

In standard rendering workflows using Multisample Anti-Aliasing (MSAA), the fragment shader executes only once per pixel covered by a geometric primitive, and the resulting color is shared across all covered sub-pixel sample points. However, when sample-specific operations or custom anti-aliasing algorithms are required, the fragment shader must evaluate each sub-pixel sample point individually. The gl_SampleID variable provides the shader with direct knowledge of which distinct sample point within the pixel grid is being shaded.

How Identification Works

When a multisample framebuffer is bound, each pixel is divided into a fixed number of sub-pixel sample positions, determined by the total sample count (accessible in GLSL via the gl_NumSamples built-in variable).

  1. Zero-Based Indexing: The graphics hardware assigns an integer index to each sample point, starting at 0 and ending at gl_NumSamples - 1. If an 8x MSAA configuration is active, the samples are indexed sequentially from 0 through 7.
  2. Sub-Pixel Assignment: Each integer index corresponds to a specific fixed sub-pixel offset within the bounds of the pixel. When the GPU schedules a fragment thread to evaluate a specific sample location, it loads that sample's index directly into the gl_SampleID register for that invocation.
  3. Execution Context: The current execution thread can then use this integer directly to index into arrays, determine sample-specific parameters, or fetch data from multisample textures via the texelFetch function.

Implicit Activation of Sample-Rate Shading

Using gl_SampleID modifies the execution frequency of the fragment shader:

  • Triggering Per-Sample Execution: Simply reading from gl_SampleID anywhere inside the fragment shader implicitly forces the GPU to execute the fragment shader at sample frequency rather than pixel frequency.
  • Invocation Multiplicity: Instead of running once per covered pixel, the shader automatically runs once per covered sample. For a 4x MSAA buffer where all four samples are covered by a triangle, the fragment shader executes four separate times for that single pixel, with gl_SampleID sequentially resolving to 0, 1, 2, and 3.
  • Performance Impact: Because this increases the total fragment shader invocations up to the number of samples per pixel, relying on gl_SampleID substantially increases GPU workload compared to standard MSAA.

Relationship with gl_SamplePosition

While gl_SampleID identifies which sample is being evaluated by index, it does not directly convey the geometric coordinates of that sample. To obtain the physical sub-pixel offset, gl_SampleID is often used alongside gl_SamplePosition, a vec2 containing the two-dimensional sub-pixel coordinates of the current sample scaled to the range [0.0, 1.0], where (0.5, 0.5) represents the exact center of the pixel. Together, these variables allow shaders to perform precise procedural filtering, custom anti-aliasing resolves, and sample-correct lighting evaluations.