Шейдеры 3d-игр для начинающих

Создание скрипта подсветки

RW/ScriptsC#Highlighter

  1. Скрипт может быть применён только к объекту, содержащему компоненты и . Это контролируется добавлением атрибутов в начало скрипта.
  2. Это ссылки на , и . Материалы помечены атрибутом , что позволяет назначать их из инспектора.
  3. В методе мы автоматически заполняем при помощи .
  4. Вызывается . Это гарантирует, что по умолчанию будет отображаться неподсвеченный материал. Ниже находится публичный метод , переключающий материал рендерера. Он получает булев параметр , определяющий состояние подсветки.
  5. Предотвращаем все ошибки NullReference
  6. Для экономии пространства используем тернарный оператор.

Continuum Shaders

Шейдеры 3d-игр для начинающих

Когда ты уже повидал множество шейдеров, перестаёшь их различать. Даже самые зоркие из нас могут путать Chocapics и Cyboxes. Но Continuum Shaders можно отличить даже при шейдерной слепоте. Этот шейдер добавляет в Minecraft все возможные эффекты освещения уровня ААА, и всё это впечатляет: колыхание растений, рябь и отражение солнца на воде. Если брать количество изменений, которые может дать один единственный пак шейдеров, Continuum вас точно не разочарует. Он ещё и сделан профессиональнее, чем многие из этого списка, заходя на сайт невольно спрашиваешь себя “погоди, а это точно Minecraft?”

Настройка окружения

Цель
этого раздела — настроить наш проект PlayCanvas и разместить некоторые объекты
окружения, чтобы протестировать воду.

Если
у вас еще нет учетной записи в PlayCanvas, зарегистрируйтесь и
создайте новый пустой проект. По умолчанию в вашей сцене должна быть пара объектов,
камера и источник света.

Вставка моделей

Проект Google Poly — это действительно отличный ресурс 3D моделей для Web. Вот модель лодки, которую я использовал. Как только вы загрузите и разархивируете ее, вы должны найти файлы .obj и .png.

  1. Перетащите оба файла в окно ресурсов в своем проекте PlayCanvas.
  2. Выберите материал, который был автоматически создан, и установите его диффузную карту в файл .png.

Теперь
вы можете перетащить Tugboat.json в вашу сцену и удалить объекты Box и Plane. Вы можете
масштабировать лодку, если она выглядит слишком маленькой (я установил на 50).

Аналогичным
образом вы можете добавить в свою сцену любые другие модели.

Орбитальная камера

Чтобы настроить орбитальную камеру, мы скопируем скрипт из этого примера PlayCanvas. Перейдите ссылке и нажмите на Editor, чтобы войти в проект.

  1. Скопируйте содержимое mouse-input.js и orbit-camera.js из того туториала в файлы с таким же именем в вашем проекте.
  2. Добавьте компонент Script к своей камере.
  3. Прикрепите два скрипта к камере.

Совет:
Вы можете создавать папки в окне ресурсов, чтобы все упорядочить. Я поместил
эти два сценария для камеры в Scripts/Camera/, свою модель —
в Models/, а мой материал — в Materials/.

Теперь,
когда вы запускаете игру (кнопка воспроизведения в правом верхнем углу экрана),
вы должны видеть свою лодку и вращаться вокруг нее с помощью мыши.

Создание PBR Graph

CreateRW/MaterialsCreate ► MaterialGlow_MatRW/ShadersPBR GraphCreate ► Shader ► PBR Graphфизически точный рендерингHighlightShaderGraphLightweightRenderPipelineLightweightRenderPipeline/Lit
Glow_MatShaderShader Graphs ► HighlightShaderGraphHighlightShaderGraphOpen Shader EditorShader Graph

  • Основное рабочее пространство — это тёмно-серая область, в которой будут храниться операции графа. Можно нажать на рабочем пространстве правой клавишей мыши, чтобы открыть контекстное меню.
  • Нод (node) — это единичный элемент графа. Каждый нод имеет вход, выход или операцию, в зависимости от его портов. Ноды соединяются друг с другом при помощи рёбер.
  • Master node — это последний выходной нод графа. В этом примере мы используем вариант для физически точного рендеринга, также называемый нодом PBR Master. Вы можете заметить в нём отдельные свойства, например, Albedo, Normal, Emission и Metallic, которые используются в Standard Shader.
  • Blackboard может предоставлять доступ к определённым частям графа в инспекторе. Это позволяет пользователю настраивать параметры без непосредственного редактирования самого графа.
  • Main Preview интерактивно отображает текущие выходные данные шейдера в виде сферы.

граф шейдера

Приступаем к работе: наша исходная сцена

Задача:

Шаг 1: добавление источника света

положениярадиуса

сделаем так, чтобы каждый пиксель в пределах радиуса источника света был видимым, а остальные были чёрными

  • Объявили uniform-переменную источника света.
  • Использовали встроенную функцию для вычисления расстояния между источником света и текущим пикселем.
  • Проверили, больше ли это расстояние (в пикселях) 20% ширины экрана; если это так, то возвращаем цвет пикселя, в противном случае возвращаем чёрный.

Задача:

Добавление градиента

На этом рисунке вычисляется для произвольного пикселя. меняется в зависимости от того, в каком пикселе мы находимся, а значение постоянно.

Шаг 2: добавляем глубину

плоскимдолжнаABCрасстояние на плоскости xyABCDADDBCнаправление, в котором повёрнута поверхностьнормалью поверхностимассивомтекстурой

Шаг 3: применение модели освещения

реализовать модель освещениямодель Фонга

  1. Получаем вектор нормали текущего пикселя.
  2. Получаем вектор направления света.
  3. Нормализуем векторы.
  4. Вычисляем угол между ними.
  5. Умножаем конечный цвет на этот коэффициент.

5. Умножаем конечный цвет на этот коэффициент

Задача:в текстуре в качестве значений цвета нельзя хранить отрицательные значения
косинус

репозитории этого туториала на GitHubздесь

Сокрытие латентности и как писать код

Теперь, когда мы понимаем, как выглядят аппаратное обеспечение и модель программирования, как реально программировать это? До сих пор, похоже, мы писали обычный код. Мы обрабатываем в нем рабочий элемент, потенциально обмениваясь информацией между соседями на одном SIMD, с другими через локальную память и, наконец, читаем и пишем через глобальную память. Проблема в том, что «нормальный» код не очень хорош, так как нам нужно скрыть латентность.

Способ, которым GPU скрывает латентность тем, что у него больше работы в полете. Намного больше работы, например, у той же GCN каждый вычислительный блок может иметь в полете до 40 подгрупп. Каждый раз, когда подгруппа обращается к памяти, другая получает назначение в планировщике. Учитывая, что только четыре могут выполняться одновременно, это означает, что мы можем переключиться до 10 раз, прежде чем вернемся в подгруппу, которая начала исходный запрос.

Первая подгруппа попадает в инструкцию памяти и приостанавливается. Вычислительный блок немедленно планирует следующую подгруппу, которая также приостанавливается. После того, как четвертая подгруппа выдала инструкцию, подсистема памяти вернется, и обработка первой подгруппы может возобновиться. Таким образом, вычислительный блок выполняет работу в каждом цикле.

Однако здесь есть проблема. Переключение подгрупп должно быть мгновенным, чтобы сделать подобное возможным. Это означает, что вы не можете записать состояние программы в память и прочитать его обратно. Вместо этого все состояния всех программ постоянно хранятся в регистрах. Для этого требуется огромное количество регистров. Единичный вычислительный блок GCN имеет 256 кб регистров. При этом мы можем использовать до (256 кб/40/4/64 б) = 24 регистра для одного элемента, прежде чем потребуется уменьшить их занятость. Для нашего стиля программирования это означает, что мы должны попытаться свести к минимуму количество состояний, которых приходится поддерживать как можно больше хотя бы пока есть доступ к памяти. Если мы не получаем доступ к памяти, один вейвфронт может держать SIMD на 100% занятым. Мы также должны быть уверены, что используем эту локальную память и кэш-память L1 насколько это возможно, поскольку они имеют пропускную способность больше и задержку меньше, чем внешняя память.

Один SIMD может обрабатывать несколько рабочих элементов за один такт, на этом рисунке он имеет ширину 8. Если ветка короткая, мы не тратим много усилий. Длинные ветки, которые отключают большинство SIMD-полос, могут значительно снизить пропускную способность.

Другая проблема, с которой мы столкнемся: как обрабатываются ветви. SIMD обрабатывают все вместе, поэтому они не могут выполнять переходы. Вместо этого отдельные полосы маскируются, т.е. не участвуют в работе. Это также подразумевает, что если все рабочие элементы не занимают одну и ту же ветвь. GPU, как правило, выполняет обе стороны ветки.

Это означает, что для SIMD длины N мы можем получить наихудшее использование как 1/N. На процессорах N обычно  от 1 до 8, поэтому катастрофы нет

Но на графическом процессоре N может достигать 64, а это уже важно. Как мы можем убедиться, что так не происходит? Во-первых, мы можем воспользоваться выполнением подгруппы

Если у нас есть ветка, где надо выбрать между дешевой и дорогой версией, а некоторые рабочие элементы занимаются дорогой, мы могли бы отправить на дорогую все из них. Это снижает стоимость ветки с дорогая + дешевая до просто дорогой. Другая часть — просто избежать чрезмерного ветвления. По мере расширения CPU это становится все более важным, и методы, такие как сортировка всех данных и обработка становятся более интересными, чем интенсивное ветвление на отдельных рабочих элементах. Например, если вы пишете механизм моделирования частиц, гораздо быстрее сортировать частицы по типу и запускать специализированную программу моделирования для каждой, а не все возможные.

Что мы узнали? Нам нужно:

  • Большая область задач — чем больше самостоятельных рабочих элементов, тем лучше.
  • Код с интенсивным использованием памяти должен минимизировать количество состояний, чтобы обеспечить высокую загрузку.
  • Мы должны избегать ветвей, которые выводят из работы большую часть подгруппы.

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

Добавляем свойства Blackboard

Fresnel Effect PowerPropertiesBlackboardBlackboardBlackboard

Добавление свойств Base Texture и Normal Map

+BlackboardTexture 2DBlackboardBaseTextureexposedSample Texture 2DBaseTextureTextureSampleTexture 2DNormal Map+Texture 2DNormal MapSample Texture 2DSave AssetGlow_MatBase TextureNormal MapBaseTextureNormalMapWoodAlbedoWoodNormal

Добавляем свойства Glow Size и Glow Color

+BlackboardVector1GlowSizeползунокModeSliderMin0.05Max6Default5GlowSizeFresnel Effect PowerColorправой клавишей мышиConvert to PropertyColorBlackboardGlowColorSave AssetGlow_MatGlowSizeGlowColor
Play

История

Ранее разработчики игр реализовывали алгоритм создания изображений из геометрических объектов (рендеринг) вручную: составляли алгоритм определения видимых частей сцены, составляли алгоритм наложения текстур, составляли алгоритмы, создающие нестандартные видеоэффекты. Для ускорения рисования некоторые алгоритмы рендеринга были реализованы на аппаратном уровне — с помощью видеокарты. Разработчики игр могли использовать алгоритмы, реализуемые видеокартой, но не могли заставить видеокарту исполнять их собственные алгоритмы, например, для создания нестандартных эффектов. Нестандартные алгоритмы исполнялись на центральном процессоре, более медленном (для задач обработки графики) по сравнению с процессорами видеокарты. Рассмотрим два примера.

  • Вода в игре Quake 2 на программном и на OpenGL-рендеринге. При всём качестве аппаратно ускоренной картинки, вода там — просто синий светофильтр, в то время как в программном есть эффект плеска воды.
  • В игре Counter-Strike 1.6 эффект ослепления от светошумовой гранаты на аппаратном рендеринге — белая вспышка, на программном — белая вспышка и пикселизированный экран.

Для решения проблемы в видеокарты стали добавлять (аппаратно) алгоритмы, востребованные разработчиками. Вскоре стало ясно, что реализовать все алгоритмы невозможно и нецелесообразно; решили дать разработчикам доступ к видеокарте — позволить собирать блоки графического процессора в произвольные конвейеры, реализующие разные алгоритмы. Программы, предназначенные для выполнения на процессорах видеокарты, получили название «шейдеры». Были разработаны специальные языки для составления шейдеров. Теперь в видеокарты загружались не только данные о геометрических объектах («геометрия»), текстуры и другие данные, необходимые для рисования (формировании изображения), но и инструкции для GPU.

До начала применения шейдеров использовались процедурная генерация текстур (например, применялась в игре Unreal для создания анимированных текстур воды и огня) и мультитекстурирование (на нём был основан язык шейдеров, применявшийся в игре Quake 3). Эти механизмы не обеспечивали такой же гибкости, как шейдеры.

С появлением перенастраиваемых графических конвейеров появилась возможность проводить на GPU математические расчёты (GPGPU). Наиболее известные механизмы GPGPU — nVidia CUDA, Microsoft DirectCompute и открытые OpenCL, Vulkan от консорциума Khronos Group.

Немного истории

Давным-давно, когда мониторы были большими и пузатыми, а компьютеры маленькими в плане производительности, графику обрабатывал центральный процессор. Этих возможностей хватало, так как и графика была на зачаточном уровне: пиксельные схематические изображения, объекты на которых не всегда можно было узнать.

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

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

Простыми словами я рассказываю именно об играх, так как это — прикладная область, которая в полной мере позволяет реализовать 3D технологии. Следующим этапом можно считать унификацию «полномочий» различных игровых компонентов. Так, в отдельный элемент «откололся» так называемый движок — структура, которая отвечает за взаимодействие всех игровых компонентов.

Любой 3D объект состоит из так называемых полигонов, которые имеют треугольную форму. Детализация объекта будет зависеть от количества таких полигонов: чем их больше, тем четче нарисована каждая мелочь. При выводе изображения на экран полигоны нужно растеризовать, то есть перевести их из трехмерного пространства на плоский экран с сохранением пропорций.Шейдеры 3d-игр для начинающихИнженеры пришли к выводу, что это слишком рутинная задача, чтобы нагружать ею центральный процессор. В результате «эволюции» после ряда экспериментов появились видеокарты, которые мы видим сегодня: отдельный графический чип, который через специальную шину связывается с видеопамятью.

Следующие шаги

  • Попробуйте изменять высоту (значение ) вектора освещения, чтобы понаблюдать за его воздействием
  • Поэкспериментируйте с интенсивностью освещения. (Можно сделать это, умножая значение diffuse на коэффициент.)
  • Добавьте в уравнение вычисления освещения значение ambient (окружающего освещения). (Это значит, что мы присваиваем минимальное значение, то есть даже в тёмных областях цвет не будет полностью чёрным. Такое освещение позволяет сделать сцену реалистичной, потому что объекты в реальной жизни всегда освещены, даже если на них не падает прямой свет)
  • Попробуйте реализовать шейдеры из этого туториала по WebGL. Он сделан в Babylon.js, а не в Three.js, но вы можете читать только части, относящиеся к GLSL. В частности, вас могут заинтересовать сэл-шейдинг и затенение по Фонгу.
  • Вдохновляйтесь демо из GLSL Sandbox и ShaderToy

Языки программирования

Для удовлетворения различных потребностей рынка (компьютерная графика имеет множество сфер применения) было создано большое количество языков программирования шейдеров.

Обычно, языки для написания шейдеров предоставляют программисту специальные типы данных (матрицы, семплеры, векторы и др.), набор встроенных переменных и констант (для взаимодействия со стандартной функциональностью 3D API).

Профессиональный рендеринг

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

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

RenderMan 
Язык программирования шейдеров, реализованный в ПО RenderMan фирмы Pixar, стал первым языком программирования шейдеров. API RenderMan разработано Робом Куком и описано в спецификации интерфейса RenderMan, является фактическим стандартом для профессионального рендеринга, используется во всех работах студии Pixar.
OSL 
OSL — англ. Open Shading Language — язык программирования шейдеров, разработанный фирмой и напоминающий язык C. Используется в проприетарной программе «Arnold», разработанной фирмой «Sony Pictures Imageworks» и предназначенной для рендеринга, и в свободной программе Blender, предназначенной для создания трёхмерной компьютерной графики.
Рендеринг в реальном времени
GLSL 
GLSL (англ. the OpenGL Shading Language) — язык программирования шейдеров, описанный в стандарте OpenGL и основанный на версии языка C, описанной в стандарте ANSI C. Язык поддерживает большинство возможностей ANSI C, поддерживает типы данных, часто применяемые при работе с трехмёрной графикой (векторы, матрицы). Словом «шейдер» в языке GLSL называется независимо компилируемая единица, написанная на этом языке. Словом «программа» называется набор скомпилированных шейдеров, связанных вместе.
Cg 
Cg (англ. C for graphics) — язык программирования шейдеров, разработанный фирмой nVidia совместно с фирмой Microsoft. Язык похож на язык C и на язык HLSL, разработанный фирмой Microsoft и входящий в состав DirectX 9. В языке используются типы «int», «float», «half» (число с плавающей запятой размером 16 бит). Язык поддерживает функции и структуры. Язык обладает своеобразными оптимизациями в виде «упакованных массивов» (англ. packed arrays): объявления типа «float a» и «float4 a» соответствуют разным типам; второе объявление создаёт «упакованный массив»; операции с «упакованным массивом» выполняются быстрее, чем с обычным. Несмотря на то, что язык разработан фирмой nVidia, исходный код может компилироваться в инструкции и для GPU видеокарт фирмы ATI. Следует учесть, что все шейдерные программы обладают своими особенностями, узнать о которых можно из специализированных источников.
Языки программирования шейдеров для DirectX
DirectX ASM 
DirectX ASM — низкоуровневый язык программирования шейдеров, разработанный для DirectX. Синтаксис языка схож с синтаксисом языка ассемблера для процессоров x86. Существует несколько версий языка, отличающихся друг от друга наборами поддерживаемых инструкций GPU и требованиями к оборудованию. Вершинный шейдер может состоять из 100—200 инструкций. Количество инструкций пиксельного шейдера более ограничено; например, в языке версии 1.4 пиксельный шейдер не может включать более 32-х инструкций.
HLSL 
HLSL (англ. High Level Shader Language) — высокоуровневый язык программирования шейдеров, разработанный для DirectX и похожий на язык C. Представляет собой надстройку над языком . Позволяет использовать структуры, процедуры и функции.

В чем польза подхода с шейдерами?

Шейдеры 3d-игр для начинающих

С шейдерами есть некая неразбериха, так как существуют различные стандарты языков программирования под разные библиотеки (GLSL — OpenGL, HLSL — DirectX и так далее), и это не считая того, что сами производители видеокарт могут поддерживать различные возможности. Однако, плюс их использования легко можно оценить, взглянув на картинку выше с примером разницы отображения между DirectX 9 и DirectX 10.

Таким образом, если вы используете шейдеры известной библиотеки, то достаточно выхода следующей версии, чтобы качество повысилось само собой. Конечно, тут есть нюансы, такие как совместимость, поддержка появившихся специализированных команд и прочее, но все же.

Кроме графики, подход с шейдерами полезен обычным пользователям следующими вещами:

1. Повышается скорость и производительность компьютера (ведь центральному процессору нет необходимости производить расчет графики вместо GPU).

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

Теперь, вы знаете что такое шейдеры, зачем они нужны и какая от них польза.

  • Что такое спрайт?
  • Что такое лайфхак?

Прозрачность

Задача
этой части сделать поверхность воды прозрачной.

Вы
могли заметить, что цвет, который мы возвращаем в Water.frag, имеет
значение прозрачности 0.5, но поверхность по-прежнему полностью
непрозрачна. Прозрачность во многих отношениях остается открытой проблемой
в компьютерной графике. Один из дешевых способов добиться ее — использовать
смешивание.

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

При смешивании вместо простого отбрасывания или перезаписи мы можем комбинировать цвет уже нарисованного пикселя с пикселем, который должен быть нарисован. Вы можете увидеть .

Чтобы
заставить прозрачность работать так, как мы ожидаем, нам надо, чтобы
комбинированный цвет результата был source, умноженным на альфу,
плюс destination, умноженный на единицу минус альфа. Другими словами, если
альфа равна 0.4, окончательный цвет должен быть:

finalColor = source * 0.4 + destination * 0.6;

1 finalColor=source *0.4+destination *0.6;

В PlayCanvas опция  делает именно это.

Чтобы включить это, просто установите свойство для материала внутри CreateWaterMaterial:

material.blendType = pc.BLEND_NORMAL;

1 material.blendType=pc.BLEND_NORMAL;

Если
вы запустите игру сейчас, вода будет прозрачной! Но все еще не идеально.
Проблема возникает, если полупрозрачная поверхность перекрывается сама собой,
как показано ниже.

Мы
можем исправить это, используя alpha
to coverage, который является
методом множественной выборки для достижения прозрачности вместо смешивания:

//material.blendType = pc.BLEND_NORMAL;
material.alphaToCoverage = true;

1
2

//material.blendType = pc.BLEND_NORMAL;

material.alphaToCoverage=true;

Но
это доступно только в WebGL 2. В оставшейся части этого туториала я буду
использовать смешивание, чтобы все упростить.

Что такое shedar

Shader переводится с английского как «оттеняющий». Это специальная программа, которая обрабатывает объекты, содержащиеся в игровом коде, и придает им окончательный вид.

По сути, это один из элементов унификации. Если совсем упростить, то разработчик игры попросту задает расположение и форму объекта, а также его текстуру. За отрисовку отвечают уже шейдеры, которые для этого и написаны.

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

Sildur’s Vibrant Shaders

Шейдеры 3d-игр для начинающих

Если предыдущий пак был Кеном, то Sildur’s Vibrant Shaders это точно Рю и я обещаю, что это последняя аналогия со Street Fighter в этом списке. Это расширение для шейдера GLSL, который полностью преображает систему освещения в Minecraft. При отличной производительности, всё выглядит аккуратно и жизнерадостно, будто полной грудью вдыхаешь чистый воздух с ароматом соснового леса. Эээээх!

Есть и другие преимущества. Регулярные апдейты, поддержка версии 1.14. И для скачивания доступны разные версии, даже для старых ПК. То есть насладиться отражениями, тенями и сумеречными лучами можно даже если вы играете в Minecraft на валенке.

Типы шейдеров

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

  • (англ. vertex shader);
  • (англ. geometry shader);
  • (англ. pixel shader, fragment shader).

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

Вершинные шейдеры

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

Пример кода для вершинного шейдера на языке :

vs.2.0
dcl_position v0
dcl_texcoord v3
m4x4 oPos, v0, c0
mov oT0, v3
Геометрические шейдеры

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

Геометрические шейдеры впервые стали использоваться на видеокартах Nvidia серии 8.

Пиксельные (фрагментные) шейдеры

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

Пример кода для пиксельного шейдера на языке :

ps.1.4
texld r0, t0
mul r0, r0, v0