Relict Engine: Шейдеры. Часть 1. Теория и вопросы
Начнем, пожалуй, с теории.
Шейдеры и модель затенения
пример работы отложенного затенения (иллюстрация https://learnopengl.com/)
Шейдер это программа, написанная на одном из специализированных языков программирования, например GLSL, и выполняемая на GPU.
Шейдеры бывают разных видов: вершинные, фрагментные, геометрические и компьют. Каждый создан для своей задачи и работают чуть по разному.
Например, вершинный шейдер работает исключительно с вершинами (или набором точек) 3д модели, а фрагментный (или, как его еще называют, пиксельный), только с пикселями экрана или текстуры.
Для вывода графики на экран нам нужен как минимум вершинный и фрагментный шейдеры. Они будут исполнятся на каждый отдельно взятый объект. В случае вершинного для каждой вершины модели; в случае фрагментного для каждого пикселя экрана, занятого объемом результата вершинного шейдера.
А так-же есть две модели шейдинга (шейдинг ("затенение") - процесс в компьютерной графике, который придает объектам реалистичный вид, определяя их цвет и внешний вид в зависимости от освещения, текстур и материалов):
Forward (или прямое затенение) - при этой модели каждый отдельный объект обрабатывается самостоятельно. Свет и тени будут считаться отдельно для каждого объекта.
Deffered (или отложенное затенение) - отрисовка сцены происходит в несколько проходов с сохранением промежуточных данных в специальные текстуры, которые имеют общее название G-Buffer. А потом, отдельным проходом, единоразово будет просчитан свет и тень.
И у первой и у второй модели затенения есть свои плюсы и минусы. Так например, для разряженной сцены, где много "пустых" мест быстрее будет работать прямое затенение. Когда как для нагруженной сцены, особенно если есть много перекрывающихся объектов, отложенное наоборот покажет себя лучше.
Шейдеры в Relict Engine
Таким образом, в первую очередь нам нужно выбрать, какую модель затенения использовать в движке. Т.к. проект, для которого Relict Engine создается, связан с космосом, то логично предположить, что прямое затенение даст больше производительности, нежели отложенное. И это будет верно, пока мы говорим о "сферическом космосе в вакууме". Как только появляются туманности, низкие орбиты и нагруженные космопорты на этих орбитах, все становится менее очевидно. Поэтому, несмотря на кажущуюся простоту этого вопроса , ответить на него не так уж и просто.
Следующие вопросы, который надо решить, и которые не связаны с моделью затенения напрямую, а больше относятся к архитектуре движка, является: А как хранить шейдеры? Как передавать в них параметры?
В спецификации OpenGL 4.5 появилась возможность использовать бинарные шейдеры Spir-V, которые являются основным форматом шейдеров для Vulkan. И это удобно, мы сможем использовать один и тот-же шейдер как для OpenGL, так и для Vulkan без модификации. Но это касается "статичных" шейдеров. Их нельзя изменять, можно добавить только заранее известные переменные, которые можно будет передать в шейдер через функции движка или скрипта, а если мы хотим чего-то более сложного? Например передать не текстуру, а некую математическую функцию, которая будет определять цвет пикселя по своим собственным законам?
Таким образом, нам понадобится система, которая будет компоновать наши кастомные навороты, а так-же вводные данные, в виде переданных параметров с набором функций базовых шейдеров в некую отдельную сущность, которая будет представлять из-себя скомпонованный шейдер из множества отдельно взятых функций и точки входа. И желательно, все это все равно сохранить в Spir-V формат для удобства дальнейшего перехода на Vulkan.
Более того, в зависимости от выбранной модели затенения, выходной результат так-же должен отличаться. Так например, если мы для Основного цвета (Diffuse Color) не будем использовать текстуру, а некую мат. функцию, то нам нужно будет скомпоновать эту функцию с шейдером G-Buffer, в случае использования отложенного затенения, когда как в случае прямого затенения, с итоговым фрагментным шейдером.
Иными словами только для подготовки шейдера к компиляции в кэш нам потребуется целый промежуточный комбайн. Этот комбайн будет работать с текстом, компонуя и генерируя исходный glsl код из пред написанных сниппетов и нашего материала. А на выходе должен быть Asset, уже в формате Spir-V, который и будет использоваться для компиляции уже в машинный код и исполнения на GPU.

































