What Does Noperspective Interpolation Do in GLSL?

In OpenGL Shading Language (GLSL), the noperspective interpolation qualifier forces values passed from a vertex shader to a fragment shader to interpolate linearly in 2D screen space rather than using standard perspective-correct interpolation. By disabling depth-aware weighting during primitive rasterization, noperspective causes attributes like colors or texture coordinates to distribute evenly across screen pixels regardless of a surface's tilt or distance from the camera. This behavior is essential for rendering screen-aligned graphics, HUDs, flat UI elements, or achieving specialized non-photorealistic visual effects.

Understanding Interpolation in the Graphics Pipeline

When a triangle or line passes through the fixed-function rasterization stage, hardware calculates the values of varying attributes for every fragment inside the primitive. In 3D rendering, objects undergo perspective projection, meaning that equal distances in world space compress as they recede into the distance.

By default, GLSL applies standard perspective-correct interpolation (the smooth qualifier). To account for depth distortion, the rasterizer divides the attribute values by the homogeneous coordinate \(w\) at each vertex, linearly interpolates \(attribute / w\) and \(1 / w\) across the screen-space primitive, and then reconstructs the correct value at each fragment.

Standard (smooth):    Linear in 3D world space (perspective-correct)
noperspective:        Linear in 2D screen space (ignores depth differences)
flat:                 No interpolation (uses the provoking vertex value)

The Exact Effect of Noperspective

When a varying variable is declared with the noperspective keyword, the hardware completely skips the perspective division steps during rasterization:

// Vertex Shader
#version 330 core
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec2 inTexCoord;

noperspective out vec2 vTexCoord;

void main() {
    vTexCoord = inTexCoord;
    gl_Position = projectionMatrix * viewMatrix * vec4(inPosition, 1.0);
}

// Fragment Shader
#version 330 core
noperspective in vec2 vTexCoord;
out vec4 fragColor;

uniform sampler2D uTexture;

void main() {
    fragColor = texture(uTexture, vTexCoord);
}

When to Use Noperspective

While standard perspective interpolation is required for realistic 3D environments, noperspective serves several specific technical purposes:

1. Screen-Space Visual Effects

Post-processing passes, screen-aligned quads, and UI elements projected with complex matrices often require uniform pixel-level gradients. Applying noperspective prevents unintentional distortions caused by arbitrary vertex depth values.

2. Specialized Wireframe and Anti-Aliased Line Rendering

Single-pass wireframe algorithms compute barycentric coordinates or distance vectors to triangle edges. To calculate screen-space line widths and anti-aliased margins accurately, these distance metrics must change linearly across screen pixels rather than warping with camera distance.

3. Emulating Retro Graphics Hardware

Early 3D gaming consoles and hardware accelerators (such as the original Sony PlayStation) lacked hardware support for perspective-correct texturing. Using noperspective allows developers to recreate the distinctive texture-warping and shearing artifacts found in classic 1990s 3D titles.