Система материалов, часть 4
Я изначально ставил перед собой задачу дать пользователю возможность организовать рендер по собственному усмотрению, разумеется в пределах тех инструментов что предоставляет движок. Но с прицелом на возможную доработку рендера в любой момент, на случай если в движке появятся какие-то новые инструменты и возможности.
Иными словами - движок не загружает никаких шейдеров самостоятельно, равно как и не требует чтобы эти шейдеры были написаны только так и никак иначе. Если пользователю не нужны лайтмапы - он их просто не использует. Если пользователю не нужны динамические источники света - аналогично. Пользователь сам пишет убершейдер и сам решает какие данные ему использовать. Роль движка сводится лишь к предоставлению этих актуальных данных.
Однако, как вы понимаете, даже при таком подходе абстракций не избежать. У сцены есть лайтмапа, у NPC есть кости. Т.е. разделение проходит на уровне форматов моделей и выведено в систему материалов. У каждого формата моделей есть свой базовый блок описания - для сцены один, для моделей с вершинной анимацией другой, для моделей со скелетной анимацией третий, четвертый для спрайтов, для партиклей, для декалей, наконец. При этом возможность запросить из движка произвольные данные ограничена естественным образом лишь наличием этих данных в самой модели.
Понятное дело что для NPC мы не можем запросить лайтмапы - их там попросту нет. А вот любые глобальные данные - очень даже можем. Ещё раз подчеркну - это не движок даёт нам набор данных, строго определённых программистом. Пользователь сам запрашивает то что ему требуется, а движок на основании запрошенного лишь пытается соптимизировать конечные структуры и ресурсы.
Так например идёт динамическая перестройка VBO, если какие-то атрибуты не были использованы в шейдере. Это позволяет уменьшить потребление видеопамяти. Аналогично и с текстурами - то что пользователь не запрашивал загружено не будет.
Здесь следует отметить ещё вот какой момент - несмотря на вышеупомянутое разделение на абстрактные модели, которое служит в первую очередь для удобства пользователей, внутреннее представление самих материалов приведено к общему знаменателю. Это абстрактные data-driven структуры, которые внутри проходят через такой же абстрактный конвейер, имеющий в своём составе лишь две универсальные фазы:
При таком подходе достигается абсолютный пользовательский контроль над визуализацией и попутно решается проблема сортировки полупрозрачных объектов в достаточной степени (полностью эта проблема не решается на стороне рендерера, т.к. там невозможна попиксельная сортировка).
Второй позитивный момент - мы можем динамически переносить рендеринг из непрозрачного списка в полупрозрачный, если нам вдруг это понадобится по ходу игры.
Динамическое освещение рассчитывается в один проход отрисовки, движок предоставляет списки видимых источников для каждого участка геометрии. Для теней используется альтернативный материал, который так же может быть использован для early-Z теста. Возможно в дальнейшем эта организация рендера получит ещё одно усложнение, когда я начну имплементировать реалтайм-радиосити, но в целом каких-то противоречий или принципиальных ограничений тут не просматривается. В принципе вышеописанный подход к рендерингу уже сам по себе является достаточно инновационным, но в моей системе материалов это лишь малая часть тех возможностей, которые она предоставляет. Подробнее об этом - уже в следующих постах.