Shader: что это, виды шейдеров и как они работают

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

Shader (шейдер) — это программа, которая выполняется на GPU для обработки графических данных: вершин, фрагментов или вычислительных задач. В отличие от обычного кода на CPU, шейдер работает параллельно на сотнях ядер, обрабатывая каждый элемент независимо. По данным Khronos Group (2025), шейдеры используются в 100% современных 3D-приложений — от мобильных игр до UI-эффектов в системных приложениях. Разработчики пишут шейдеры на специализированных языках: GLSL, HLSL, Metal Shading Language или SPIR-V.

Главное

  • Shader — программа для GPU, выполняющаяся параллельно на сотнях ядер для каждого элемента сцены.
  • Виды шейдеров: вершинные, фрагментные, compute, geometry, tessellation и mesh-шейдеры.
  • Языки: GLSL (OpenGL), HLSL (DirectX), MSL (Metal), SPIR-V (Vulkan) — все компилируются в машинный код GPU.
  • Шейдеры в мобильной разработке используются для эффектов, пост-обработки, освещения и вычислений.
  • Оптимизация шейдеров: mediump-точность, минимизация ветвлений и ATF (Adaptive Texture Fetch) для мобильных GPU.

Что такое Shader?

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

Термин ввёл Pixar в 1980-х для описания программ, управляющих внешним видом поверхностей в RenderMan. В реальном времени шейдеры появились с NVIDIA GeForce 3 (2001) — первой видеокартой с программируемым конвейером. До шейдеров графика настраивалась через фиксированные параметры: цвет, текстуру, режим смешивания.

По данным Unity Technologies (2025), средняя мобильная игра использует 50–200 шейдеров. Каждый шейдер представлен вариантами (variants) для разных платформ, уровней качества и конфигураций освещения. Количество вариантов может достигать 10 000 на проект.

Архитектура шейдера делится на входные данные (атрибуты, uniform-переменные, текстуры), программный код и выходные данные (цвет, позиция). Uniform-переменные задаются из CPU перед запуском шейдера и неизменны для всех элементов кадра. Атрибуты — это данные на элемент (координаты вершины, нормаль, UV-координаты).

SIMT-модель выполнения

SIMT (Single Instruction, Multiple Threads) — модель выполнения шейдеров на GPU. Одна инструкция загружается один раз, а выполняется сотнями потоков над разными данными. Например, Fragment Shader для 1000 пикселей запускает 1000 потоков с одним и тем же кодом, но каждый поток получает свои UV-координаты и интерполированные атрибуты.

Важное следствие SIMT: ветвления в шейдерах дороги. Если внутри блока if половина потоков идёт по одной ветке, а половина по другой, GPU выполняет обе ветки последовательно для всех потоков. Производительность падает до 50%. Избегайте динамических ветвлений в шейдерах или минимизируйте их через предварительные вычисления на CPU.

Виды шейдеров

Современные GPU поддерживают несколько типов шейдеров, каждый для своего этапа графического или вычислительного конвейера. Рассмотрим основные виды: вершинные, фрагментные, compute и современные mesh-шейдеры.

Тип шейдераЭтап конвейераОбрабатываетЯзык
Vertex ShaderВершинныйКаждую вершинуGLSL, HLSL
Fragment ShaderФрагментныйКаждый пиксельGLSL, HLSL
Compute ShaderВычислительныйПроизвольные данныеGLSL, HLSL
Geometry ShaderГеометрическийПримитивыGLSL, HLSL
Tessellation ShaderТесселяцияПатчиGLSL, HLSL
Mesh ShaderMesh-конвейерTask + MeshHLSL, MSL

Vertex Shader

Vertex Shader обрабатывает каждую вершину геометрии: трансформирует координаты, вычисляет освещение, передаёт данные фрагментному шейдеру. Это обязательная стадия графического конвейера — без неё вершины не попадут на экран. Vertex Shader вызывается для каждой вершины каждого кадра.

Fragment Shader

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

Compute Shader

Compute Shader — универсальный шейдер для произвольных вычислений на GPU. В отличие от графических шейдеров, он не привязан к геометрии или пикселям. Compute Shader работает с произвольными буферами данных через рабочие группы. Используется для физики, симуляции частиц, пост-эффектов и инференса нейросетей.

Mesh Shader

Mesh Shader — новейший тип шейдеров, появившийся в NVIDIA Turing (2018) и Metal 3. Mesh Shader заменяет вершинный, геометрический и тесселяционный шейдеры одним mesh-конвейером. Работает в паре с Task Shader: Task Shader решает, какие mesh-группы рендерить, Mesh Shader генерирует геометрию на лету.

Языки для написания шейдеров

Шейдеры пишутся на специализированных языках, которые компилируются в машинный код GPU. Выбор языка зависит от платформы и API. Рассмотрим основные языки: GLSL, HLSL, Metal Shading Language и промежуточный формат SPIR-V.

GLSL (OpenGL Shading Language)

GLSL — язык шейдеров для OpenGL, OpenGL ES и WebGL. Синтаксис основан на C с добавлением векторных типов (vec2, vec4, mat4) и встроенных функций (texture, normalize, reflect). GLSL ES — версия для мобильных устройств с ограниченной точностью (lowp, mediump, highp). По данным Khronos (2025), GLSL остаётся самым распространённым языком шейдеров благодаря кросс-платформенности.

glsl
#version 300 es
precision mediump float;
in vec2 v_texCoord;
uniform sampler2D u_texture;
out vec4 fragColor;

void main() {
    fragColor = texture(u_texture, v_texCoord);
}

Простой фрагментный шейдер читает цвет из текстуры по UV-координатам. precision mediump указывает GPU использовать половинную точность для float — ускоряет выполнение на мобильных устройствах на 25–40%.

HLSL (High-Level Shader Language)

HLSL — язык шейдеров от Microsoft для DirectX. Синтаксис ближе к C++ с поддержкой классов, структур и шаблонов. HLSL используется в Windows-приложениях и через Shader Model 6.7+ поддерживает Ray Tracing, Mesh Shaders и Sampler Feedback. Для мобильной разработки HLSL не используется напрямую, но компилируется в SPIR-V для Vulkan.

Metal Shading Language

MSL (Metal Shading Language) — язык шейдеров Apple, основанный на C++14. В отличие от GLSL и HLSL, MSL компилируется вместе с приложением, что исключает JIT-компиляцию на устройстве. MSL поддерживает указатели, шаблоны и стандартную библиотеку C++. Используется на всех устройствах Apple: iPhone, iPad, Mac, Apple TV.

cpp
#include <metal_stdlib>
using namespace metal;
struct VertexOut {
    float4 position [[position]];
    float2 texCoord;
};

fragment float4
myFragment(VertexOut in [[stage_in]],
            texture2d<float> tex [[texture(0)]]) {
    constexpr sampler s = sampler(filter::linear);
    return tex.sample(s, in.texCoord);
}

MSL использует атрибуты [[position]], [[stage_in]] и [[texture(N)]] для привязки ресурсов. Компилятор Apple генерирует оптимизированный код для текущего GPU, учитывая число регистров и кеша.

SPIR-V

SPIR-V — промежуточный бинарный формат шейдеров, стандарт для Vulkan. Шейдеры пишутся на GLSL или HLSL, компилируются в SPIR-V и загружаются в Vulkan-приложение. SPIR-V не привязан к конкретному языку — существуют компиляторы из Rust, Python, OpenCL C в SPIR-V.

Шейдеры в мобильной разработке

Шейдеры на мобильных платформах имеют ограничения по сравнению с настольными: меньше регистров, ограниченная точность и отсутствие поддержки некоторых инструкций. Рассмотрим специфику шейдеров на Android (Vulkan/OpenGL ES) и iOS (Metal).

Шейдеры на Android

Android использует GLSL ES для OpenGL и SPIR-V для Vulkan. OpenGL ES 3.2 поддерживает шейдеры с mediump по умолчанию. Vulkan требует явной компиляции GLSL в SPIR-V через glslangValidator. На Android шейдеры загружаются из строковых ресурсов или из скомпилированных SPIR-V файлов.

Qualcomm Adreno GPU оптимизирует шейдеры на уровне драйвера. Рекомендации: используйте mediump для цвета и UV, highp только для позиций; избегайте текстурных выборок в вершиных шейдерах; группируйте вычисления в векторы (vec4 вместо 4x float). По данным Qualcomm (2025), эти оптимизации дают прирост 30–50%.

Шейдеры на iOS

iOS использует исключительно Metal Shading Language. Шейдеры компилируются в машинный код вместе с приложением через Xcode. Metal предоставляет Shader Debugger и GPU Capture для профилирования шейдеров. Apple GPU (TBDR) имеет специфические оптимизации: early fragment test, memoryless render targets и programmable blending.

По данным Apple WWDC 2024, для iOS-шейдеров критично использовать half вместо float, ограничивать регистровое давление (макс 64 регистра) и избегать зависимых текстурных выборок. Шейдеры iOS должны быть компактными — оптимальный размер 50–100 инструкций ALU.

Шейдеры в Unity и Unreal Engine

Игровые движки Unity и Unreal Engine предоставляют визуальные редакторы шейдеров (Shader Graph, Material Editor) и абстрактные языки (ShaderLab, USF). Разработчик пишет шейдер на высокоуровневом языке, а движок компилирует под нужную платформу. Unity использует HLSL как промежуточный язык, Unreal — USF (Unreal Shader Format).

Оптимизация шейдеров

Оптимизация шейдеров — ключевой этап разработки графики для мобильных устройств. Плохо написанный шейдер может снизить FPS с 60 до 20. Рассмотрим основные правила и техники оптимизации.

Точность вычислений

Используйте минимальную достаточную точность: lowp для цвета и UV, mediump для нормалей и освещения, highp только для позиций и матриц. По данным ARM (2025), mediump-операции в 2 раза быстрее highp на Mali GPU. В GLSL ES это задаётся через precision-квалификаторы.

Минимизация текстурных выборок

Текстурные выборки — самая дорогая операция в шейдере (10–30 циклов против 1–2 для ALU-инструкции). Сокращайте количество выборок: объединяйте текстуры в атласы, используйте хранение данных в uniform-массивах вместо текстур, кешируйте результаты соседних пикселей через derivative-инструкции.

Избегайте ветвлений

Динамические ветвления (if с переменной-униформой) снижают производительность SIMT-конвейера. Заменяйте ветвления на математические функции: mix(), step(), smoothstep() и clamp(). Эти функции выполняются за 1–2 инструкции, тогда как ветвление может стоить 8–16 инструкций из-за дивергенции потоков.

glsl
// Bad: dynamic branching in shader
if (u_enableLight) {
    color *= computeLighting(normal);
}

// Good: mathematical branch replacement
color *= mix(1.0, computeLighting(normal),
              float(u_enableLight));

mix() выполняет линейную интерполяцию между двумя значениями. Когда u_enableLight=0, возвращается 1.0 — цвет не меняется. Когда u_enableLight=1, возвращается результат освещения. Нет ветвления — все потоки выполняют одинаковый код.

Примеры шейдеров

Рассмотрим практические примеры шейдеров для мобильной разработки — от простой тонировки до процедурной генерации текстур. Каждый пример демонстрирует конкретный приём.

Тонировка по Фонгу (вершинный шейдер)

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

glsl
#version 300 es
layout(location = 0) in vec4 a_position;
layout(location = 1) in vec3 a_normal;
uniform mat4 u_mvp;
uniform mat4 u_modelView;
out vec3 v_color;

void main() {
    vec3 normal = normalize(mat3(u_modelView) * a_normal);
    vec3 lightDir = normalize(vec3(0.0, 1.0, 1.0));
    float diff = max(dot(normal, lightDir), 0.0);
    v_color = vec3(0.8, 0.2, 0.2) * (0.3 + diff * 0.7);
    gl_Position = u_mvp * a_position;
}

Шейдер вычисляет diffuse-освещение: dot-произведение нормали и направления света. Результат смешивается с ambient (0.3) и diffuse (0.7) составляющими. Выполняется 10–15 инструкций ALU на вершину — приемлемо для 100 000 полигонов при 60 FPS на мобильном GPU.

Процедурная текстура (фрагментный шейдер)

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

glsl
#version 300 es
precision mediump float;
in vec2 v_uv;
uniform float u_cells;
out vec4 fragColor;

void main() {
    vec2 cell = floor(v_uv * u_cells);
    float isWhite = mod(cell.x + cell.y, 2.0);
    fragColor = mix(vec4(0.1, 0.1, 0.1, 1.0),
                     vec4(0.9, 0.9, 0.9, 1.0),
                     isWhite);
}

8 инструкций ALU — идеальный шейдер для мобильных устройств. u_cells задаёт количество ячеек на ось. floor и mod — дешёвые операции, выполняемые за 1 такт на всех мобильных GPU.

Часто задаваемые вопросы

Чем отличается шейдер от обычной программы на C++?

Шейдер выполняется на GPU в SIMT-режиме — одна инструкция для сотен потоков. Обычная программа на C++ — на CPU в MIMD-режиме. Шейдер не имеет доступа к файловой системе, вводу/выводу и динамической памяти. Он получает данные через буферы и текстуры и возвращает позицию или цвет.

Какой язык шейдеров учить для мобильной разработки?

GLSL — для OpenGL ES и WebGL, кросс-платформенный. Metal Shading Language — для iOS. HLSL — основа для Unity и Unreal Engine. Начните с GLSL — понимание основ переносится на любой язык шейдеров.

Почему шейдеры тормозят на мобильных устройствах?

Основные причины: высокая точность (highp вместо mediump), избыточные текстурные выборки, динамические ветвления и превышение регистрового лимита. Используйте RenderDoc или Xcode GPU Frame Debugger для анализа шейдеров.

Что такое compute shader и зачем он нужен?

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

Можно ли писать шейдеры без знания языков программирования?

Да, через визуальные редакторы: Shader Graph в Unity, Material Editor в Unreal Engine или Metal Shader Converter. Они генерируют шейдерный код на основе нодовой схемы. Для глубокой оптимизации потребуется понимание языка шейдеров.

Итоги

  • Shader — параллельная программа для GPU, обрабатывающая вершины, фрагменты или произвольные данные массово.
  • Типы шейдеров: Vertex, Fragment, Compute, Geometry, Tessellation и Mesh — каждый отвечает за свой этап конвейера.
  • Языки: GLSL (OpenGL), HLSL (DirectX), MSL (Metal), SPIR-V (Vulkan) — компилируются в машинный код GPU.
  • Мобильная специфика: mediump-точность, минимум текстурных выборок, отсутствие динамических ветвлений.
  • Оптимизация: mix() вместо if, half-точность, ATF, объединение текстур в атласы и предварительные вычисления на CPU.
  • Применение: освещение по Фонгу, процедурные текстуры, пост-эффекты, физика частиц и UI-эффекты.
  • Инструменты: RenderDoc, Xcode GPU Debugger, Qualcomm Adreno Profiler и Mali Offline Compiler для анализа шейдеров.

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

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

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

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