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 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

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