Введение

Тип программы в графическом процессоре (GPU)

В компьютерной графике шейдер — это компьютерная программа, которая вычисляет соответствующие уровни света, темноты и цвета при рендеринге 3D-сцены — процесс, известный как затенение. Шейдеры развивались для выполнения разнообразных специализированных функций в компьютерной графике, специальных эффектах и видеопост-обработке, а также для вычислений общего назначения на графических процессорах. Традиционные шейдеры вычисляют эффекты рендеринга на графическом оборудовании с высокой степенью гибкости. Большинство шейдеров кодируются для (и выполняются на) графического процессора (GPU), хотя это не является строгим требованием. Языки затенения используются для программирования конвейера рендеринга графического процессора, который в значительной степени заменил фиксированный функциональный конвейер прошлого, который позволял только общие функции преобразования геометрии и затенения пикселей; с помощью шейдеров можно использовать настраиваемые эффекты. Положение и цвет (тон, насыщенность, яркость и контраст) всех пикселей, вершин и/или текстур, используемых для построения финального отрендеренного изображения, могут быть изменены с использованием алгоритмов, определенных в шейдере, и могут быть модифицированы внешними переменными или текстурами, передаваемыми компьютерной программой, вызывающей шейдер. Шейдеры широко используются в кинопост-обработке, компьютерной графике и видеоиграх для создания широкого спектра эффектов. Помимо простых моделей освещения, более сложные применения шейдеров включают в себя: изменение тона, насыщенности, яркости (HSL/HSV) или контраста изображения; создание размытия, свечения, объемного освещения, нормального отображения (для эффектов глубины), боке, шейдинга в стиле cel-shading, постеризации, рельефного отображения, искажения, цветового ключа (для так называемых эффектов "синий экран/зеленый экран"), обнаружения краев и движения, а также психоделических эффектов, таких как те, что можно увидеть в демосцене.

История

Это использование термина "шейдер" было представлено публике компанией Pixar в версии 3.0 их спецификации интерфейса RenderMan, впервые опубликованной в мае 1988 года. С развитием графических процессоров, основные библиотеки графического программного обеспечения, такие как OpenGL и Direct3D, начали поддерживать шейдеры. Первые графические процессоры, поддерживающие шейдеры, умели выполнять только пиксельное затенение, но шейдеры вершин были быстро добавлены, как только разработчики оценили возможности шейдеров. Первой видеокартой с программируемым пиксельным шейдером стала Nvidia GeForce 3 (NV20), выпущенная в 2001 году. Геометрические шейдеры появились с Direct3D 10 и OpenGL 3.2. В конечном итоге графическое оборудование эволюционировало к единой модели шейдеров.

Типы

Существует три основных типа шейдеров (пиксельные, вершинные и геометрические), и несколько новых типов были добавлены позднее. Если старые графические карты используют отдельные вычислительные блоки для каждого типа шейдера, то новые карты оснащены унифицированными шейдерами, способными выполнять шейдеры любого типа. Это позволяет графическим картам более эффективно использовать вычислительные ресурсы.

2D-шэджеры

2D-шейдеры воздействуют на цифровые изображения, также называемые текстурами в компьютерной графике. Они изменяют атрибуты пикселей. 2D-шейдеры могут участвовать в рендеринге 3D-геометрии. В настоящее время существует только один тип 2D-шейдера – пиксельный шейдер.

Шейдеры пикселей

Пиксельные шейдеры, также известные как фрагментные шейдеры, вычисляют цвет и другие атрибуты каждого "фрагмента": единицы работы рендеринга, влияющей максимум на один выходной пиксель. Самые простые пиксельные шейдеры выводят один пиксель экрана в виде цветового значения; возможны также более сложные шейдеры с несколькими входами и выходами. Пиксельные шейдеры могут выполнять задачи от простого вывода одного и того же цвета до применения значений освещения, создания карт нормалей, теней, зеркальных бликов, полупрозрачности и других эффектов. Они могут изменять глубину фрагмента (для Z-буферизации) или выводить более одного цвета, если активны несколько буферов рендеринга. В 3D-графике один пиксельный шейдер не способен создавать некоторые сложные эффекты, поскольку он работает только с одним фрагментом, не имея информации о геометрии сцены (то есть данных вершин). Однако пиксельные шейдеры знают координаты экрана, на котором выполняется отрисовка, и могут считывать значения с экрана и соседних пикселей, если содержимое всего экрана передается шейдеру в виде текстуры. Эта техника позволяет реализовать широкий спектр двухмерных эффектов постобработки, таких как размытие или обнаружение/усиление границ для шейдеров, имитирующих рисованную графику. Пиксельные шейдеры также могут применяться на промежуточных этапах к любым двумерным изображениям – спрайтам или текстурам – в графическом конвейере, в то время как вершинные шейдеры всегда требуют 3D-сцены. Например, пиксельный шейдер – единственный тип шейдера, который может выступать в качестве постпроцессора или фильтра для видеопотока после его растрирования.

3D-шэджеры

3D-шейдеры воздействуют на 3D-модели или другую геометрию, но также могут обращаться к цветам и текстурам, используемым для отрисовки модели или сетки. Вершинные шейдеры – это старейший тип 3D-шейдеров, обычно вносящих изменения для каждой вершины в отдельности. Геометрические шейдеры нового поколения могут генерировать новые вершины непосредственно внутри шейдера. Тесселяционные шейдеры – самые новые 3D-шейдеры; они обрабатывают группы вершин одновременно для добавления детализации, например, разбивая модель на более мелкие группы треугольников или других примитивов во время выполнения, чтобы улучшить отображение кривых и неровностей или изменить другие атрибуты.

Шейдеры вершин

Вертексные шейдеры — наиболее устоявшийся и распространенный тип 3D-шейдера, который выполняется один раз для каждой вершины, передаваемой графическому процессору. Их задача — преобразовать трехмерную позицию каждой вершины в виртуальном пространстве в двухмерные координаты на экране (а также вычислить значение глубины для Z-буфера). Вертексные шейдеры могут изменять свойства, такие как положение, цвет и текстурные координаты, но не могут создавать новые вершины. Результат работы вертексного шейдера передается на следующую стадию графического конвейера — шейдер геометрии (если он присутствует) или растризатор. Вертексные шейдеры обеспечивают мощное управление деталями положения, движения, освещения и цвета в любой сцене, использующей 3D-модели.

Шейдеры геометрические

Геометрические шейдеры были введены в Direct3D 10 и OpenGL 3.2; ранее доступны в OpenGL 2.0+ с использованием расширений. Этот тип шейдера может генерировать новые графические примитивы, такие как точки, линии и треугольники, из примитивов, отправленных в начало графического конвейера. Программы геометрических шейдеров выполняются после вершинных шейдеров. Они принимают на вход целый примитив, возможно, с информацией о смежности. Например, при работе с треугольниками, три вершины являются входными данными для геометрического шейдера. Затем шейдер может выдать ноль или более примитивов, которые растрируются, а их фрагменты в конечном итоге передаются в пиксельный шейдер. Типичные области применения геометрических шейдеров включают генерацию точечных спрайтов, геометрическую тесселяцию, выдавливание объемов теней и однопроходный рендеринг в карту куба. Типичным примером преимуществ геометрических шейдеров в реальных задачах является автоматическое изменение сложности сетки. Серия линейных полос, представляющих контрольные точки для кривой, передается геометрическому шейдеру, и в зависимости от требуемой сложности шейдер может автоматически генерировать дополнительные линии, каждая из которых обеспечивает более точное приближение кривой.

Шейдеры для тесселяции

С версий OpenGL 4.0 и Direct3D 11 был добавлен новый класс шейдеров, называемый шейдерами тесселяции. Он добавляет две новые стадии обработки в традиционную модель: шейдеры управления тесселяцией (также известные как hull-шейдеры) и шейдеры оценки тесселяции (также известные как domain-шейдеры), которые вместе позволяют упрощенным моделям подразделяться на более детализированные во время выполнения в соответствии с математической функцией. Эта функция может зависеть от различных параметров, в частности, от расстояния до камеры наблюдения, что позволяет динамически изменять уровень детализации. Это позволяет объектам, находящимся близко к камере, иметь высокую детализацию, а более удаленным – более грубую сетку, при этом сохраняя визуальное качество на сопоставимом уровне. Также это может значительно снизить требования к пропускной способности памяти, позволяя детализировать модели непосредственно в шейдерных блоках, вместо того чтобы загружать из памяти очень сложные модели и уменьшать их детализацию. Некоторые алгоритмы могут детализировать любую произвольную модель, в то время как другие позволяют использовать "подсказки" в моделях для определения наиболее важных вершин и ребер.

Примитивные и сетчатые теневые устройства

Примерно в 2017 году микроархитектура AMD Vega добавила поддержку новой стадии шейдера — примитивных шейдеров, во многом схожих с вычислительными шейдерами, имеющими доступ к данным, необходимым для обработки геометрии. В 2018 году Nvidia представила шейдеры мешей и задач в своей микроархитектуре Turing, которые также созданы по образу вычислительных шейдеров. Nvidia Turing — первая в мире микроархитектура GPU, поддерживающая шейдинг мешей через API DirectX 12 Ultimate, за несколько месяцев до выхода серии Ampere RTX 30. В 2020 году AMD и Nvidia выпустили микроархитектуры RDNA 2 и Ampere, обе из которых поддерживают шейдинг мешей через DirectX 12 Ultimate. Эти шейдеры мешей позволяют GPU обрабатывать более сложные алгоритмы, перенося большую нагрузку с CPU на GPU, и в алгоритмически интенсивном рендеринге увеличивать частоту кадров или количество треугольников в сцене на порядок. Intel объявила, что графические процессоры Intel Arc Alchemist, поставляемые в первом квартале 2022 года, будут поддерживать шейдеры мешей.

Шейдеры для отслеживания лучей

Шейдеры трассировки лучей поддерживаются Microsoft посредством DirectX Raytracing, Khronos Group посредством Vulkan, GLSL и SPIR-V, Apple посредством Metal.

Вычислительные шейдеры

Вычислительные шейдеры не ограничиваются графическими приложениями, но используют те же вычислительные ресурсы для GPGPU. Их можно использовать в графических конвейерах, например, для дополнительных этапов в алгоритмах анимации или освещения (например, при использовании тайловой прямой визуализации). Некоторые графические API позволяют вычислительным шейдерам легко обмениваться данными с графическим конвейером.

Параллельная обработка

Шейдеры создаются для одновременного применения преобразований к большому количеству элементов, например, к каждому пикселю на участке экрана или к каждой вершине модели. Это идеально подходит для параллельной обработки, и большинство современных графических процессоров (GPU) имеют несколько шейдерных конвейеров для этого, что значительно повышает скорость вычислений. Модель программирования с использованием шейдеров аналогична функции высшего порядка для рендеринга: она принимает шейдеры в качестве аргументов и обеспечивает определенный поток данных между промежуточными результатами, что позволяет реализовать как параллелизм данных (для пикселей, вершин и т.п.), так и конвейерный параллелизм (между этапами). (см. также map reduce).

Программирование

Язык, на котором программируются шейдеры, зависит от целевой платформы. Официальным языком шейдеров OpenGL и OpenGL ES является OpenGL Shading Language, также известный как GLSL, а официальным языком шейдеров Direct3D — High Level Shader Language, также известный как HLSL. Cg, сторонний язык шейдеров, генерирующий код как для OpenGL, так и для Direct3D, был разработан компанией Nvidia, однако с 2012 года его поддержка прекращена. Apple выпустила собственный язык шейдеров под названием Metal Shading Language в составе фреймворка Metal.

Редакторы GUI-шэдеров

Современные платформы разработки видеоигр, такие как Unity, Unreal Engine и Godot, всё чаще включают в себя редаторы, основанные на узлах, позволяющие создавать шейдеры без написания кода. Вместо этого пользователю представляется ориентированный граф соединенных узлов, который позволяет направлять различные текстуры, карты и математические функции на выходные параметры, такие как диффузный цвет, цвет блика и его интенсивность, шероховатость/металличность, высота, карта нормалей и так далее. Автоматическая компиляция затем преобразует этот граф в готовый, скомпилированный шейдер.