Что такое шейдер

Шейдер — это короткая программа, которую GPU запускает миллионы раз: по разу на каждую вершину или каждый пиксель.

Шейдер — программа, исполняемая на GPU на программируемых стадиях конвейера; определяет, как преобразуются вершины и какой цвет получают пиксели.

Зачем это знать

Раньше графический конвейер был полностью «зашит» в железо (fixed-function). Шейдеры дали программисту контроль над двумя стадиями — и именно благодаря им возможны вода, огонь, реалистичный свет, стилизация. Шейдер — это ваша точка вмешательства в конвейер.

Главные типы шейдеров

ШейдерЗапускаетсяЗадача
Вершинный (vertex)на каждую вершинупреобразовать позицию в clip space
Фрагментный (fragment)на каждый фрагмент/пиксельвычислить цвет
Геометрический (geometry)на каждый примитивсоздавать/менять примитивы
Вычислительный (compute)на сетку потоковлюбые параллельные вычисления

Два базовых и обязательных — вершинный и фрагментный. С них начинают все.

Простейший шейдер — мысленно

Вершинный шейдер по сути делает одно: gl_Position = MVP * vec4(position, 1.0);. Фрагментный задаёт цвет: fragColor = vec4(1.0, 0.0, 0.0, 1.0); — красный. Это уже рабочий минимум: красный треугольник на экране.

// Вершинный шейдер (GLSL) — преобразование позиции
attribute vec3 position;
uniform mat4 MVP;
void main() {
    gl_Position = MVP * vec4(position, 1.0);
}

// Фрагментный шейдер — постоянный красный цвет
void main() {
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

Этот GLSL показан как language-text: он исполняется на GPU, а не в браузере, поэтому без кнопки «Запустить».

Откуда шейдер берёт данные

Шейдер сам по себе беспомощен — ему скармливают данные: позиции вершин, матрицы, текстуры, время. Эти каналы данных (attribute, uniform, varying) разберём в разделе про GLSL. Сейчас важно: шейдер — чистая функция, превращающая входные данные в выход (позицию или цвет).

Как работает под капотом

Исходник шейдера на GLSL компилируется драйвером в машинный код конкретной видеокарты при запуске программы. Затем GPU грузит эту скомпилированную программу в свои ядра и исполняет её для всех элементов параллельно. Один и тот же код бежит на тысячах ядер — отсюда требование: шейдер должен быть быстрым и без зависимостей от соседей.

Частые ошибки

  • Думать, что шейдер запускается один раз — он запускается на каждую вершину/пиксель.
  • Пытаться внутри фрагментного шейдера «посмотреть» на соседний пиксель — потоки независимы (кроме спец-функций производных).
  • Забывать, что шейдер компилируется на лету и ошибка компиляции уронит весь рендер.

Итоги

  • Шейдер — программа на GPU для программируемых стадий конвейера.
  • Базовые типы: вершинный (позиция) и фрагментный (цвет).
  • Минимум: vertex задаёт gl_Position, fragment задаёт цвет.
  • GLSL компилируется в машинный код GPU при запуске.
Проверьте себя
1. Какие два типа шейдеров обязательны и базовы?
AГеометрический и вычислительный
BВершинный и фрагментный
CТеневой и световой
DРастровый и векторный
2. Что вычисляет вершинный шейдер в минимальном виде?
AЦвет пикселя
Bgl_Position — позицию вершины в clip space
CТекстуру
DТени
3. Почему GLSL-код показан как language-text, а не language-javascript?
AОн неправильный
BОн исполняется на GPU, а не в браузере, поэтому без кнопки запуска
CGLSL устарел
DТак короче