Understanding Sample In Interpolation in GLSL
This article examines the sample in interpolation
qualifier in GLSL fragment shaders, detailing how it alters variable
interpolation and fragment shader execution during multisample
anti-aliasing (MSAA). It covers the default behavior of MSAA shading,
how the sample qualifier forces per-sample evaluation, the
syntactic usage, and the associated performance implications.
Default MSAA vs. Sample Interpolation
In standard OpenGL multisample anti-aliasing (MSAA), depth and
coverage tests occur at individual subpixel sample locations, but the
fragment shader typically executes only once per pixel. By default,
inputs qualified with smooth or evaluated without an
explicit qualifier are interpolated at the pixel's center. If the pixel
center lies outside the geometry boundary, this can produce
extrapolation artifacts. While the centroid qualifier
restricts interpolation to the center of the covered samples within the
pixel, it still executes the fragment shader once per primitive per
pixel.
The Behavior of the
sample Qualifier
The sample qualifier modifies this pipeline behavior
entirely. When applied to an input variable, it mandates that the
variable must be interpolated independently at each individual sample
location rather than at the pixel center or centroid.
Key behaviors include:
- Forced Per-Sample Shading: Declaring any fragment
input with
sample incauses the GPU to execute the fragment shader at sample frequency rather than pixel frequency for covered samples. If a pixel has 4x MSAA enabled and all four samples are covered, the fragment shader runs four separate times for that pixel. - Exact Sample Locations: For each invocation, inputs
marked with
sample inare evaluated directly at the specific subpixel coordinate of the corresponding sample point, eliminating geometric interpolation artifacts and edge aliasing caused by center evaluation. - Interaction with Built-in Variables: Using
sample inhas an effect equivalent to referencinggl_SampleIDorgl_SamplePosition. Either condition requires the pipeline to switch from per-pixel shading to per-sample shading.
Syntax and Usage
The sample keyword acts as an auxiliary storage
qualifier and can be combined with interpolation qualifiers such as
smooth (perspective-correct, default) or
flat.
#version 450 core
// Evaluated independently at each sample position
sample in vec2 v_TexCoord;
sample smooth in vec4 v_Color;
out vec4 fragColor;
void main()
{
fragColor = texture(u_Texture, v_TexCoord) * v_Color;
}If an input is declared as flat, the sample
qualifier has no effect on the value itself (since flat values are not
interpolated), but declaring it as sample flat in will
still trigger per-sample fragment shader execution.
Performance Considerations
Using sample in significantly increases the
computational load on the GPU. Because the fragment shader executes once
for every covered sample rather than once per pixel, fragment processing
costs scale directly with the MSAA sample count (e.g., up to 4x or 8x
the arithmetic and texture fetch load). Consequently,
sample in should only be used when high-frequency
variations inside a primitive—such as alpha testing, procedural
patterns, or subpixel shading details—require true supersampling quality
at geometry edges.