Организация шейдеров материалов
Некоторые функции, описанные в настоящем документе, более не поддерживаются, либо начнут поддерживаться в будущем.
Данная статья описывает организацию шейдеров для материалов. Некоторые моменты являются обязательными к исполнению, другие - рекомендательные. Однако настоятельно рекомендуется следовать всем моментам, дабы все шейдеры материалов были единообразны в плане исполнения, это является требованием при контрибуции в общественный репозиторий движка.
Шейдерное API
Общее
Каждый шейдер материала должен использовать предоставляемое API для единообразного согласования операций, это API находится в mtrl.h и предоставляет некоторые функции для решения частых задач при построении материалов.
Частное
Частное API используют разные нетривиальные сущности:
- Растительность, файл green.h (организацию расчетов смотреть в mtrlgreen_tree_base.vs для деревьев и кустов, в mtrlgreen_grass_base.vs для травы);
- Анимационные модели, файл skin.h (организацию расчетов смотреть в mtrlskin_base.vs).
Частное API выделено в отдельные компоненты шейдерной системы с целью единообразной обработки сущностей.
Константы
Общие
Пересылаемые в шейдер константы заранее известны и переопределены, их имена строго фиксированы и не подлежат изменениям, так как пересылка из движка в шейдер осуществляется по имени констант.
Самое главное чтобы их пересылка из движка и использование в шейдере было согласова но, иными словами движок должен отправлять константу, а шейдер должен принимать и использовать. Если движок будет пытаться переслать данные, которые не объявлены (не используются) то графическое ядро будет выдавать предупреждения, а если шейдер будет использовать неинициализированные данные, то результат непредсказуем.
Список возможных данных аналогичен списку в редакторе материалов. Имена данных:
- g_mW - матрица мира;
- g_mV - матрица вида;
- g_mP - матрица проекции;
- g_mWV - комбинированная матрица мира и вида;
- g_mWVP - комбинированная матрица мира, вида и проекции;
- g_vPosCam - float3 позиция камеры;
- g_vTimeDelta - float2 вектор, x – общее время рендера в миллисекундах, y – текущее время рендера кадра в миллисекундах;
- g_vWinSize - float4 вектор размеров окна рендера в пикселях, x – ширина, y - высота, z - размер одного пикселя по ширине (1 / ширина), w - размер одного пикселя по высоте (1 / высота).
Во всех случаях g_mW (трансформация нормали) и g_mWVP (трансформация позиции) являются обязательными для вершинного шейдера.
Список обязательных (пересылаемых по умолчанию) констант для пиксельного шейдера:
- g_vNearFarLayers - float4 вектор, x - ближняя плоскость отсечения, y - дальняя плоскость отсечения, z - тип поверхности (MTLTYPE_LAYER_), w - идентификатор поверхности.
Константы растительности
В каждый вершинный шейдер растительности отправляются константы по регистрам, значения регистров определены в файле gdefines.h в дефайнах вида GREEN_R_.
Константы по регистрам:
- GREEN_R_LESSENING регистр, константа half2 g_vDistLessening - дистанции начала и окончания уменьшения растительности (для травы);
- GREEN_R_VIEWPOS регистр, константа half3 g_vViewPos - позиция наблюдателя;
- GREEN_R_BSPHERE регистр, константа half4 g_vBoundSphere - сфера, xyz - центр, w - радиус;
- GREEN_R_BBMAX регистр, константа half3 g_vBoundMax - максимум ограничивающего объема объекта;
- GREEN_R_BBMIN регистр, константа half3 g_vBoundMin - минимум ограничивающего объема объекта.
Перечисленные константы необходимо объя влять непосредственно в вершинном шейдере растительности (травы или листвы деревьев/кустов) так:
half2 g_vDistLessening : register(GREEN_R_LESSENING);
half3 g_vViewPos : register(GREEN_R_VIEWPOS);
half4 g_vBoundSphere : register(GREEN_R_BSPHERE);
half3 g_vBoundMax : register(GREEN_R_BBMAX);
half3 g_vBoundMin : register(GREEN_R_BBMIN);
Константы анимационных моделей
Вершинный шейдер анимационной модели принимает массив данных в одной константе по регистру ANIM_R_DATA (gdefines.h):
half4 g_BufferBoneWorld[128] : register(ANIM_R_DATA);
На каждую кость идёт две компоненты, смещение и вращение(кватернион), то есть, 128 регистров - 64 кости.
Объявления данная константа не требует, так как объявлена в подключаемом файле skin.h, которые долже быть подключен в каждый вершинный шейдер анимационной модели.
Сэмплеры
Все семплеры распределены по регистрам и именование большинства из них не является обязательным правилом, однако должно иметь приоритет. Список текстур по регистрам:
- 0 - g_sColor, цвет, albedo текстура;
- 1 - g_sMask, маска;
- 2 - g_sDetails0, детальная текстура r канала;
- 3 - g_sDetails1, детальная текстура g канала;
- 4 - g_sDetails2, детальная текстура b канала;
- 5 - g_sDetails3, детальная текстура a канала;
- 6 - g_sNormals0, микрорельефная текстура r канала;
- 7 - g_sNormals1, микрорельефная текстура g канала;
- 8 - g_sNormals2, микрорельефная текстура b канала;
- 9 - g_sNormals3, микрорельефная текстура a канала;
- 10 - g_sParameters, параметры освещения поверхности;
- 12 - g_sReflection, отражения, может быть 2d или cube;
- 13 - g_sDepth, глубина, использовать только для полупрозрачных материалов.
Общая структура шейдеров
Данный раздел является рекомендательным, и каждый вправе самостоятельно определять правила структуры, однако, шейдеры в общем репозиторий движка должен соответствовать данной структуре.
Для примера будет приведен базовый шейдер геометрии.
В качестве разделителя используется:
//##########################################################################
Первым элементом файла шейдера является его описание, которое до и после отделено новыми строками. Здесь необходимо привести название файла и краткое описание. Пример:
/*
mtrlgeom_base.vs
Базовый рендер геометрии
*/
Далее следуют подключаемые файлы:
#include <../struct.h>
Затем разделитель и принимаемые из движка константы (сюда же можно отнести статические данные и дефайны для данного шейдера):
half4x4 g_mWVP;
half4x4 g_mW;
Далее разделитель и сэмплеры:
sampler2D g_sColor:register(s0);
sampler2D g_sNormals0:register(s6);
sampler2D g_sParameters:register(s10);
Затем разделитель и main функция шейдера:
VSO_SceneCommon main(VSI_Geometry IN)
{
VSO_SceneCommon OUT;
OUT.vPosition = mul(half4(IN.vPosition,1.f),g_mWVP);
OUT.vNormal = mul(IN.vNormal,g_mW);
OUT.vTexUV = IN.vTexUV;
OUT.vPos = OUT.vPosition;
return OUT;
}
Если необходимы дополнительные функции то они должны находиться до main функции и отделяться сверху и снизу разделителями.
Функция main
Данный раздел содержит информацию о необходимых элементах функции main компилируемых шейдеров.
Вершинный шейдер
Так как разные абстрактные сущности геометрии игрового мира могут быть представлены различными структурам и вершин (struct.h) (например простая сущность, вода и т.д.), то в первую очередь необходимо объявление объекта структуры (приведен пример общей структуры):
VSO_SceneCommon OUT;
Затем трансформация вершины WVP матрицей и трансформация нормали W матрицей:
OUT.vPosition = mul(half4(IN.vPosition, 1.f), g_mWVP);
OUT.vNormal = mul(IN.vNormal, g_mW);
И заполнение текстурных координат и трансформированной WVP позиции:
OUT.vTexUV = IN.vTexUV;
OUT.vPos = OUT.vPosition;
В конце функции необходим возврат объекта структуры:
return(OUT);