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):
- gl_FragCoord.x: The horizontal window coordinate of
the fragment in pixels, ranging from
0.0to the viewport width. - gl_FragCoord.y: The vertical window coordinate of
the fragment in pixels, ranging from
0.0to the viewport height. - gl_FragCoord.z: The fragment's depth value mapped
to the range
[0.0, 1.0], representing the value written to the depth buffer during standard depth-testing operations. - gl_FragCoord.w: The reciprocal of the clip-space \(W\) coordinate (\(1/w_c\)), which is derived from the interpolation of the primitive's vertices during perspective division.
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.