Fragment Shader is a programmable stage of the graphics pipeline that determines the final color of each fragment (pixel) of an image. According to Khronos Group, 2025, the fragment shader receives interpolated data from the Vertex Shader and performs lighting calculations, texturing and color effects. Fragment Shader is invoked for each pixel, making it the most resource-intensive stage of the graphics pipeline.
Key Takeaways
Fragment Shader (fragment or pixel shader) is a programmable stage of the graphics pipeline that computes the final color of each image fragment. A fragment is a potential pixel that becomes a visible pixel on the screen after passing depth and stencil tests.
Fragment Shader executes after rasterization, when 3D primitives (triangles) have already been converted into a set of fragments. The shader receives interpolated attributes — texture coordinates, normals, colors that were calculated in the Vertex Shader for triangle vertices and linearly interpolated for each pixel inside the triangle.
Before the advent of programmable shaders (before DirectX 8 / OpenGL 2.0), pixel color calculation was performed by a fixed pipeline with a limited set of operations. The programmable Fragment Shader appeared in 2001 and radically expanded graphics capabilities: developers gained full control over the color of each pixel, enabling photorealistic lighting, complex materials and post-effects.
Fragment Shader is launched by the GPU for each fragment generated by the rasterizer. Each shader invocation processes one fragment, reads its input data, executes user code and writes the output value — the fragment color in RGBA format.
Fragment Shader input data includes interpolated attributes from the Vertex Shader (texture coordinates, normals, colors), uniform variables (light sources, matrices) and texture samplers. Output data is the color vector (gl_FragColor in OpenGL ES 2.0 or a user-defined variable in ES 3.0), which is written to the color buffer.
#version 300 es
precision mediump float;
in vec2 vTexCoord;
uniform sampler2D uTexture;
out vec4 fragColor;
void main() {
fragColor = texture(uTexture, vTexCoord);
}
Fragment Shader is responsible for the visual quality of the image. All effects that the user sees on the screen — color, shadows, reflections, transparency — are calculated at this stage of the graphics pipeline.
The most frequent operation is sampling color from a texture using interpolated UV coordinates. Sampler2D and the texture() function allow retrieving pixel color from a texture atlas. Filtering (bilinear, trilinear, anisotropic) is controlled through sampler parameters and affects image sharpness at different viewing angles.
The Phong shading model is calculated in the Fragment Shader per pixel, providing smoother highlights than vertex lighting (Gouraud shading). Phong lighting includes three components: ambient, diffuse and specular reflection.
// Fragment shader with Phong lighting
in vec3 vNormal;
in vec3 vPosition;
uniform vec3 uLightDir;
uniform vec3 uLightColor;
void main() {
vec3 norm = normalize(vNormal);
float diff = max(dot(norm, uLightDir), 0.0);
fragColor = vec4(uLightColor * diff, 1.0);
}
Fragment Shader allows applying post-processing: color correction through lookup tables (LUT), blur, bloom effect and tonemapping for HDR rendering. All these effects work at the pixel level and execute in real time.
Fragment Shader performance is the main factor limiting FPS in modern mobile games. Since the shader is invoked for each pixel, even a small increase in code complexity can lead to a noticeable drop in frame rate.
For mobile GPUs (Qualcomm Adreno, ARM Mali) it is recommended to: use mediump precision for float variables, combine texture lookups, apply early-z tests to discard invisible fragments before shader execution.
| Method | Description | Gain |
|---|---|---|
| Mediump precision | 16-bit precision instead of 32-bit | Up to 2x speed |
| Early-Z | Depth test before shader | Reduced invocations |
| Texture atlasing | One texture instead of several | Fewer switches |
Both types of shaders are programmable by the developer, but they work at different pipeline stages and solve different tasks. Fragment Shader is significantly more resource-intensive due to the number of invocations.
| Parameter | Fragment Shader | Vertex Shader |
|---|---|---|
| Number of invocations | Millions (screen resolution) | Thousands (number of vertices) |
| Input data | Interpolated attributes | Vertex attributes |
| Main function | Fragment color calculation | Geometry transformation |
| Texture access | Full (multiple samplers) | Limited |
| Performance impact | High (depends on resolution) | Moderate (depends on geometry) |
Fragment Shader can be simple (texture sampling) or complex (multi-layer lighting). Let us consider two practical examples: basic texturing and a gradient effect using time.
#version 300 es
precision mediump float;
in vec2 vTexCoord;
in vec3 vColor;
uniform sampler2D uDiffuseMap;
out vec4 fragColor;
void main() {
vec4 texColor = texture(uDiffuseMap, vTexCoord);
fragColor = texColor * vec4(vColor, 1.0);
}
#include <metal_stdlib>
using namespace metal;
struct FragmentIn {
float2 texCoord;
float3 normal;
};
fragment float4
fragmentMain(FragmentIn in [[stage_in]],
texture2d<float> tex [[texture(0)]]) {
constexpr sampler s(filter = linear);
float4 color = tex.sample(s, in.texCoord);
return color;
}
Frequently Asked Questions
Fragment Shader is a mini-program on the GPU that determines what color each pixel on the screen will be. If Vertex Shader determines the shape of an object, then Fragment Shader determines how that object looks — texture, lighting, color.
Fragment Shader is invoked for every pixel on the screen. On a device with a resolution of 2532x1170 (iPhone) this is almost 3 million invocations per frame. At 60 FPS the shader runs 180 million times per second, requiring enormous computational power.
Fragment Shader implements: texturing, lighting (Phong, PBR), shadows, reflections, refractions, bloom, depth of field, color correction, LUT filters and procedural texture generation.
Use mediump precision for float, reduce the number of texture lookups, apply early-z culling, combine shader operations and avoid conditional branches inside the shader.
They are the same thing. The term Fragment Shader is used in OpenGL / Vulkan, while Pixel Shader is used in Direct3D (Microsoft) terminology. Functionally they are identical: both compute the color of each fragment/pixel.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also