В этой небольшой статье мы на базовом уровне разберем несколько тесно взаимосвязанных между собой понятий: HLSL, CGfx и Compute Shaders.
Compute Shaders (вычислительные шейдеры) – это программы, которые выполняются отдельно от основного конвейера рендеринга на GPU. Они используются для выполнения тяжелых вычислений в параллельном формате. Например, обработки физических столкновений, симуляций и трассировки лучей в реальном времени.
Представим себе ситуацию: мы пишем шейдер для воды. Статичное и безжизненное движение волн на воде нас не устраивает, и мы хотим создать алгоритмы для обработки столкновений воды с игровыми объектами. Compute Shaders идеально подходят для такой задачи.
Может возникнуть вопрос: «Почему мы не можем писать отдельные классы для взаимодействия с шейдером, передавая ему параметры через скрипты в Unity?» Дело в том, что скрипты с расширением .cs выполняются на CPU, и написание алгоритмов обработки столкновений в таком формате добавит нагрузку на центральный процессор.
Видеокарты имеют сотни и тысячи ядер, предназначенные для расчетов, связанных с графикой. Использование Compute Shaders на GPU – более правильное решение для ресурсоемких операций. Это снижает нагрузку на центральный процессор и ускоряет отрисовку шейдера. Подход GPGPU (General-Purpose computing on Graphics Processing Units) позволяет использовать параллельные вычислительные мощности видеокарты для выполнения различных вычислений.
В Unity такие шейдеры хранятся в виде ассетов с расширением .compute
Теперь рассмотрим, как писать вычислительные шейдеры для проекта.
HLSL (High-level Shaders Language) – это высокоуровневый язык программирования, предназначенный для написания Compute Shaders. Он был разработан Microsoft и совместим с DirectX 11.
Существенный недостаток Compute Shaders на сегодняшний день – невозможность их работы на MacOS, так как он не поддерживает Direct3D и HLSL.
HLSL предлагает нам возможность работы с 4 основными видами шейдеров:
- Пиксельные шейдеры: говоря простым языком, пиксельные шейдеры определяют цвет каждого пикселя определенного объекта.
- Геометрические шейдеры: используются для создание новых форм и примитивов в реалтайме во время игрового процесса.
- Вершинные шейдеры: используются для переопределения положений вершин уже существующих примитивов (Фактически работает по принципу морфинга).
- Шейдеры трассировки: используется для имитации реалистичного поведения лучей света.
Поскольку в качестве подробного примера мы уже чуть раньше разбирали задачу для написания реалистичной воды, разбор основных вариантов шейдеров в HLSL продолжим на примере этой же задачи.
Где мы можем использовать пиксельные шейдеры? Представим, что нашей воде нужно добавить реалистичные блики, которые будут появляться и исчезать в различных местах на поверхности воды в зависимости от положения и активности источников света. Пиксельные шейдеры могут учитывать положение и активность конкретных источников света, рисуя блики на поверхности воды.
Где мы можем использовать геометрические шейдеры? Представим, что у нас есть задача создания эффекта всплеска от воды в реалтайме сразу после падения в воду какого-либо предмета. Здесь нам помогут геометрические шейдеры, которые будут создавать примитивы капель воды в реальном времени
Где мы можем использовать вершинные шейдеры? Помним, что наша вода должна быть крайне реалистична, поэтому теперь нам нужно, чтобы волны на воде также зависели от многих факторов, которые бы влияли на размер и направление каждой волны. Используем вершинный шейдер, который по принципу морфинга будет изменять положение вершин нашей воды, симулируя волны.
А теперь перейдем к последнему варианту шейдера из нашего списка. Шейдеры трассировки мы можем использовать для того, чтобы симулировать реалистичное падение лучей на воду, а далее просчитывать их преломление под водой.
В Unity код для вычислительных шейдеров лежит в виде ассета с расширением .hlsl
Крайне важно понимать, что HLSL - это далеко не единственный существующий язык шейдерного программирования. Из основных языков можно также выделить CGfx, GLSL, MSL и многие другие языки, каждый из которых имеет свои собственные ключевые особенности, определяющие область их использования.
Поскольку данная статья имеет некоторый уклон в Unity, то стоит отметить, что движок поддерживает только CGfx, HLSL и не поддерживает никаких более шейдерных языков программирования. А факт того, что Unity поддерживает работу с CGfx, наделяет смыслом более подробное описание данного шейдерного языка.
Cg (C for Graphics) или CGfx (C Graphics Language) — это высокоуровневый язык программирования шейдеров, разработанный компанией NVIDIA.
Было бы верным сказать, что HLSL - это улучшенная версия CGfx, поскольку язык шейдерного программирования High-Level Shader Language создавался по подобию CGfx. Это является причиной, по которой синтаксис написания шейдеров на двух приведенных раннее языках крайне схож, а многие и вовсе любят выражаться, говоря, что во многом это одно и то же.
Для того, чтобы обеспечить связь Unity с HLSL, CGfx и предоставить разработчикам комфортную работу, в движке существует свой язык программирования-обертка, называемый Shader Lab.
Немного ранее, в этой же статье, уже упоминалась совокупность видов шейдеров, с которыми мы можем работать с контексте HLSL. Так вот CGfx поддерживает схожий спектр видов шейдера:
- Пиксельные шейдеры.
- Геометрические шейдеры.
- Вершинные шейдеры.
То есть, говоря иными словами, предок поддерживает все те же виды шейдеров, за исключением шейдера для трассировки лучей.
В завершение хотелось бы отметить еще одну немаловажную деталь: в отличие от HLSL, который работает на основе DirectX, CGfx способен работать и с OpenGL, и с DirectX, что делает его более совершенным.
Подводя итоги, можно сказать, что Compute Shaders и HLSL – два тесно связанных между собой инструмента, использование которых позволяет нам оптимизировать проект, снижать нагрузку на центральный процессор и ускорять рендеринг отдельных шейдеров.