Fragment Shader — это программируемый этап графического конвейера, определяющий итоговый цвет каждого фрагмента (пикселя) изображения. По данным Khronos Group, 2025, фрагментный шейдер получает интерполированные данные от Vertex Shader и выполняет расчёты освещения, текстурирования и цветовых эффектов. Fragment Shader вызывается для каждого пикселя, что делает его самой ресурсоёмкой стадией графического конвейера.
Главное
Fragment Shader (фрагментный или пиксельный шейдер) — это программируемая стадия графического конвейера, которая вычисляет итоговый цвет каждого фрагмента изображения. Фрагмент — это потенциальный пиксель, который после прохождения тестов глубины и трафарета становится видимым пикселем на экране.
Fragment Shader выполняется после растеризации, когда трёхмерные примитивы (треугольники) уже преобразованы в набор фрагментов. На вход шейдер получает интерполированные атрибуты — текстурные координаты, нормали, цвета, которые были рассчитаны в Vertex Shader для вершин треугольника и линейно интерполированы для каждого пикселя внутри него.
До появления программируемых шейдеров (до DirectX 8 / OpenGL 2.0) расчёт цвета пикселя выполнялся фиксированным конвейером с ограниченным набором операций. Программируемый Fragment Shader появился в 2001 году и радикально расширил возможности графики: разработчики получили полный контроль над цветом каждого пикселя, что позволило реализовать фотореалистичное освещение, сложные материалы и пост-эффекты.
Fragment Shader запускается GPU для каждого фрагмента, сгенерированного растеризатором. Каждый вызов шейдера обрабатывает один фрагмент, читает его входные данные, выполняет пользовательский код и записывает выходное значение — цвет фрагмента в формате RGBA.
Входные данные Fragment Shader включают интерполированные атрибуты от Vertex Shader (текстурные координаты, нормали, цвета), uniform-переменные (источники света, матрицы) и текстурные сэмплеры. Выходные данные — вектор цвета (gl_FragColor в OpenGL ES 2.0 или пользовательская переменная в ES 3.0), который записывается в цветовой буфер.
#version 300 es
precision mediump float;
in vec2 vTexCoord;
uniform sampler2D uTexture;
out vec4 fragColor;
void main() {
fragColor = texture(uTexture, vTexCoord);
}
Fragment Shader отвечает за визуальное качество изображения. Все эффекты, которые видит пользователь на экране — цвет, тени, отражения, прозрачность — рассчитываются именно в этой стадии графического конвейера.
Наиболее частая операция — выборка цвета из текстуры по интерполированным UV-координатам. Sampler2D и функция texture() позволяют получить цвет пикселя из текстурного атласа. Фильтрация (bilinear, trilinear, anisotropic) контролируется через параметры сэмплера и влияет на чёткость изображения при разных углах обзора.
Модель освещения Фонга (Phong shading) рассчитывается во Fragment Shader для каждого пикселя, что даёт более гладкие блики, чем вершинное освещение (Gouraud shading). Phong lighting включает три компонента: ambient (фоновое), diffuse (рассеянное) и specular (зеркальное отражение).
// 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 позволяет накладывать пост-обработку: цветокоррекцию через lookup-таблицы (LUT), размытие (blur), эффект свечения (bloom) и tonemapping для HDR-рендеринга. Все эти эффекты работают на уровне пикселей и выполняются в реальном времени.
Производительность Fragment Shader — главный фактор, ограничивающий FPS в современных мобильных играх. Поскольку шейдер вызывается для каждого пикселя, даже небольшое увеличение сложности кода может привести к заметному падению частоты кадров.
Для мобильных GPU (Qualcomm Adreno, ARM Mali) рекомендуется: использовать mediump precision для float-переменных, объединять текстурные выборки, применять early-z тесты для отбраковки невидимых фрагментов до выполнения шейдера.
| Метод | Описание | Выигрыш |
|---|---|---|
| Mediump precision | 16-битная точность вместо 32-битной | До 2x скорости |
| Early-Z | Тест глубины перед шейдером | Сокращение вызовов |
| Texture atlasing | Одна текстура вместо нескольких | Меньше переключений |
Оба типа шейдеров программируются разработчиком, но работают на разных этапах конвейера и решают разные задачи. Fragment Shader существенно более ресурсоёмкий из-за количества вызовов.
| Параметр | Fragment Shader | Vertex Shader |
|---|---|---|
| Количество вызовов | Миллионы (разрешение экрана) | Тысячи (количество вершин) |
| Входные данные | Интерполированные атрибуты | Атрибуты вершин |
| Основная функция | Расчёт цвета фрагмента | Трансформация геометрии |
| Доступ к текстурам | Полный (множество сэмплеров) | Ограниченный |
| Влияние на производительность | Высокое (зависит от разрешения) | Умеренное (зависит от геометрии) |
Fragment Shader может быть простым (выборка из текстуры) или сложным (многослойное освещение). Рассмотрим два практических примера: базовое текстурирование и эффект градиента с использованием времени.
#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;
}
Часто задаваемые вопросы
Fragment Shader — это мини-программа на GPU, которая определяет, какого цвета будет каждый пиксель на экране. Если Vertex Shader определяет форму объекта, то Fragment Shader определяет, как этот объект выглядит — текстура, освещение, цвет.
Fragment Shader вызывается для каждого пикселя на экране. На устройстве с разрешением 2532x1170 (iPhone) это почти 3 миллиона вызовов за кадр. При 60 FPS шейдер выполняется 180 миллионов раз в секунду, что требует огромной вычислительной мощности.
Во Fragment Shader реализуются: текстурирование, освещение (Phong, PBR), тени, отражения, преломления, bloom, глубина резкости, цветокоррекция, LUT-фильтры и процедурная генерация текстур.
Используйте mediump precision для float, сократите количество текстурных выборок, применяйте early-z отбраковку, объединяйте шейдерные операции и избегайте условных переходов внутри шейдера.
Это одно и то же. Термин Fragment Shader используется в OpenGL / Vulkan, а Pixel Shader — в терминологии Direct3D (Microsoft). Функционально они идентичны: оба вычисляют цвет каждого фрагмента/пикселя.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также