How Does gl_FragCoord Work in GLSL?

In OpenGL Shading Language (GLSL), gl_FragCoord is a built-in input variable available exclusively within fragment shaders that provides the screen-space window coordinates of the current fragment being processed. Stored as a four-component vector (vec4), gl_FragCoord contains the fragment's pixel position, its interpolated depth value, and a perspective divisor factor. This article breaks down the individual components of gl_FragCoord, explains how OpenGL sets its coordinate origin and pixel centers, and illustrates how developers use it to implement screen-space effects, procedural patterns, and custom rendering techniques.

Component Breakdown of gl_FragCoord

The gl_FragCoord vector contains four floating-point components, denoted as (x, y, z, w):

Coordinate Space and Pixel Centers

By default in standard OpenGL, the screen-space origin (0.0, 0.0) is located at the bottom-left corner of the viewport window. The X coordinate increases toward the right, and the Y coordinate increases toward the top.

OpenGL evaluates fragments at pixel centers rather than integer grid intersections. This means that a fragment representing the bottom-leftmost pixel has an xy coordinate of (0.5, 0.5). The neighboring pixel to the right has coordinates (1.5, 0.5).

GLSL layout qualifiers can modify this behavior when needed. For instance, declaring layout(origin_upper_left) in vec4 gl_FragCoord; shifts the origin to the top-left corner, aligning it with conventions used in systems like Direct3D or Vulkan. Similarly, layout(pixel_center_integer) in vec4 gl_FragCoord; shifts the sample locations to whole integer values like (0.0, 0.0).

Typical Use Cases in Fragment Shaders

1. Generating Screen-Space UV Coordinates

When creating post-processing effects, screen wipes, or full-screen overlays, shaders frequently need normalized texture coordinates across the display. Dividing gl_FragCoord.xy by a uniform representing the total viewport resolution produces a normalized range from 0.0 to 1.0:

#version 330 core
out vec4 FragColor;
uniform vec2 u_resolution;

void main() {
    vec2 screenUV = gl_FragCoord.xy / u_resolution;
    FragColor = vec4(screenUV, 0.0, 1.0);
}

2. Screen-Space Patterns and Dithering

Because gl_FragCoord.xy reflects absolute screen pixels regardless of the 3D model's geometry or perspective, it is ideal for generating static dithering matrices, crosshatch shading, or pixelation masks:

#version 330 core
out vec4 FragColor;

void main() {
    // Alternate black and white stripes every 4 pixels horizontally
    float stripe = mod(floor(gl_FragCoord.x / 4.0), 2.0);
    FragColor = vec4(vec3(stripe), 1.0);
}

3. Screen-Space Clipping and Cutouts

gl_FragCoord can be used alongside the discard keyword to eliminate fragments based on window-space boundaries or stipple patterns, creating screen-door transparency or rectangular view splits without altering geometry:

#version 330 core
out vec4 FragColor;

void main() {
    // Discard any fragment on the left half of a 1920-wide display
    if (gl_FragCoord.x < 960.0) {
        discard;
    }
    FragColor = vec4(1.0, 0.5, 0.2, 1.0);
}

4. Reading and Linearizing Depth

The gl_FragCoord.z value contains non-linear depth resulting from perspective projection. In techniques such as soft particles, fog, or deferred rendering, shaders transform gl_FragCoord.z back into linear view-space distance to perform accurate depth-based comparisons against neighboring geometry or depth textures.