Fragment Shader — что это, задачи и принцип работы

Автор: IT Sectr Опубликовано: 2026-06-11 Время чтения: 10 мин

Fragment Shader — это программируемый этап графического конвейера, определяющий итоговый цвет каждого фрагмента (пикселя) изображения. По данным Khronos Group, 2025, фрагментный шейдер получает интерполированные данные от Vertex Shader и выполняет расчёты освещения, текстурирования и цветовых эффектов. Fragment Shader вызывается для каждого пикселя, что делает его самой ресурсоёмкой стадией графического конвейера.

Главное

  • Fragment Shader — программируемая стадия GPU, определяющая цвет каждого пикселя на экране.
  • Количество вызовов равно разрешению экрана, что делает его основной вычислительной нагрузкой рендеринга.
  • Текстурирование и освещение по Фонгу — типовые задачи, реализуемые во фрагментном шейдере.
  • GLSL и Metal Shading Language предоставляют стандартные средства для написания Fragment Shader.
  • Производительность Fragment Shader критична для достижения 60 FPS в мобильных приложениях.

Что такое Fragment Shader?

Fragment Shader (фрагментный или пиксельный шейдер) — это программируемая стадия графического конвейера, которая вычисляет итоговый цвет каждого фрагмента изображения. Фрагмент — это потенциальный пиксель, который после прохождения тестов глубины и трафарета становится видимым пикселем на экране.

Fragment Shader выполняется после растеризации, когда трёхмерные примитивы (треугольники) уже преобразованы в набор фрагментов. На вход шейдер получает интерполированные атрибуты — текстурные координаты, нормали, цвета, которые были рассчитаны в Vertex Shader для вершин треугольника и линейно интерполированы для каждого пикселя внутри него.

История эволюции Fragment Shader

До появления программируемых шейдеров (до DirectX 8 / OpenGL 2.0) расчёт цвета пикселя выполнялся фиксированным конвейером с ограниченным набором операций. Программируемый Fragment Shader появился в 2001 году и радикально расширил возможности графики: разработчики получили полный контроль над цветом каждого пикселя, что позволило реализовать фотореалистичное освещение, сложные материалы и пост-эффекты.

Как работает Fragment Shader?

Fragment Shader запускается GPU для каждого фрагмента, сгенерированного растеризатором. Каждый вызов шейдера обрабатывает один фрагмент, читает его входные данные, выполняет пользовательский код и записывает выходное значение — цвет фрагмента в формате RGBA.

Входные и выходные данные

Входные данные Fragment Shader включают интерполированные атрибуты от Vertex Shader (текстурные координаты, нормали, цвета), uniform-переменные (источники света, матрицы) и текстурные сэмплеры. Выходные данные — вектор цвета (gl_FragColor в OpenGL ES 2.0 или пользовательская переменная в ES 3.0), который записывается в цветовой буфер.

glsl
#version 300 es
precision mediump float;

in vec2 vTexCoord;
uniform sampler2D uTexture;
out vec4 fragColor;

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

Основные задачи Fragment Shader

Fragment Shader отвечает за визуальное качество изображения. Все эффекты, которые видит пользователь на экране — цвет, тени, отражения, прозрачность — рассчитываются именно в этой стадии графического конвейера.

Текстурирование

Наиболее частая операция — выборка цвета из текстуры по интерполированным UV-координатам. Sampler2D и функция texture() позволяют получить цвет пикселя из текстурного атласа. Фильтрация (bilinear, trilinear, anisotropic) контролируется через параметры сэмплера и влияет на чёткость изображения при разных углах обзора.

Освещение по Фонгу

Модель освещения Фонга (Phong shading) рассчитывается во Fragment Shader для каждого пикселя, что даёт более гладкие блики, чем вершинное освещение (Gouraud shading). Phong lighting включает три компонента: ambient (фоновое), diffuse (рассеянное) и specular (зеркальное отражение).

glsl
// 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);
}

Пост-эффекты и blending

Fragment Shader позволяет накладывать пост-обработку: цветокоррекцию через lookup-таблицы (LUT), размытие (blur), эффект свечения (bloom) и tonemapping для HDR-рендеринга. Все эти эффекты работают на уровне пикселей и выполняются в реальном времени.

Производительность Fragment Shader и оптимизация

Производительность Fragment Shader — главный фактор, ограничивающий FPS в современных мобильных играх. Поскольку шейдер вызывается для каждого пикселя, даже небольшое увеличение сложности кода может привести к заметному падению частоты кадров.

Основные проблемы производительности

  • Overdraw — повторная отрисовка одного и того же пикселя из-за перекрытия объектов. Особенно критичен для полупрозрачных объектов.
  • Условные переходы — ветвления в Fragment Shader снижают эффективность SIMD-исполнения, так как GPU вынужден выполнять обе ветки.
  • Выборки из текстур — каждая текстурная выборка (texture lookup) имеет задержку в десятки тактов GPU. Минимизация числа сэмплеров ускоряет шейдер.

Методы оптимизации Fragment Shader

Для мобильных GPU (Qualcomm Adreno, ARM Mali) рекомендуется: использовать mediump precision для float-переменных, объединять текстурные выборки, применять early-z тесты для отбраковки невидимых фрагментов до выполнения шейдера.

МетодОписаниеВыигрыш
Mediump precision16-битная точность вместо 32-битнойДо 2x скорости
Early-ZТест глубины перед шейдеромСокращение вызовов
Texture atlasingОдна текстура вместо несколькихМеньше переключений

Fragment Shader vs Vertex Shader: сравнение

Оба типа шейдеров программируются разработчиком, но работают на разных этапах конвейера и решают разные задачи. Fragment Shader существенно более ресурсоёмкий из-за количества вызовов.

ПараметрFragment ShaderVertex Shader
Количество вызововМиллионы (разрешение экрана)Тысячи (количество вершин)
Входные данныеИнтерполированные атрибутыАтрибуты вершин
Основная функцияРасчёт цвета фрагментаТрансформация геометрии
Доступ к текстурамПолный (множество сэмплеров)Ограниченный
Влияние на производительностьВысокое (зависит от разрешения)Умеренное (зависит от геометрии)

Примеры кода Fragment Shader

Fragment Shader может быть простым (выборка из текстуры) или сложным (многослойное освещение). Рассмотрим два практических примера: базовое текстурирование и эффект градиента с использованием времени.

Базовое текстурирование на GLSL

glsl
#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);
}

Пример на Metal Shading Language

cpp
#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 простыми словами?

Fragment Shader — это мини-программа на GPU, которая определяет, какого цвета будет каждый пиксель на экране. Если Vertex Shader определяет форму объекта, то Fragment Shader определяет, как этот объект выглядит — текстура, освещение, цвет.

Почему Fragment Shader такой ресурсоёмкий?

Fragment Shader вызывается для каждого пикселя на экране. На устройстве с разрешением 2532x1170 (iPhone) это почти 3 миллиона вызовов за кадр. При 60 FPS шейдер выполняется 180 миллионов раз в секунду, что требует огромной вычислительной мощности.

Какие эффекты можно сделать в Fragment Shader?

Во Fragment Shader реализуются: текстурирование, освещение (Phong, PBR), тени, отражения, преломления, bloom, глубина резкости, цветокоррекция, LUT-фильтры и процедурная генерация текстур.

Как оптимизировать Fragment Shader на мобильных устройствах?

Используйте mediump precision для float, сократите количество текстурных выборок, применяйте early-z отбраковку, объединяйте шейдерные операции и избегайте условных переходов внутри шейдера.

Чем отличается Fragment Shader от Pixel Shader?

Это одно и то же. Термин Fragment Shader используется в OpenGL / Vulkan, а Pixel Shader — в терминологии Direct3D (Microsoft). Функционально они идентичны: оба вычисляют цвет каждого фрагмента/пикселя.

Итоги

  • Fragment Shader — программируемая стадия GPU, вычисляющая цвет каждого пикселя изображения.
  • Количество вызовов равно разрешению экрана, что делает его самой ресурсоёмкой стадией рендеринга.
  • Текстурирование, освещение по Фонгу и пост-эффекты — основные задачи фрагментного шейдера.
  • Производительность напрямую зависит от числа текстурных выборок и использования highp precision.
  • Mediump precision и early-z тесты — ключевые приёмы оптимизации для мобильных GPU.
  • OpenGL ES использует термин Fragment Shader, Direct3D — Pixel Shader, суть одинакова.
  • GLSL и Metal Shading Language — основные языки для написания Fragment Shader в мобильной разработке.

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также