Позвольте мне рассказать вам историю о моём друге Бобе. Недавно окончив университет, он решил создать MMO-игру с собственной физикой, глобальным освещением в реальном времени и процедурно генерируемыми ламами в шляпах. Три года спустя его «движок» едва может отобразить вращающийся куб, не перегружая GPU. Не будьте как Боб.
Обольщение собственного движка
Мы все были в такой ситуации — смотрели на 12 миллионов строк кода Unreal Engine на C++ и думали:
// Их способ
GetWorld()->SpawnActor<AAwesomeCharacter>(SpawnLocation);
// Мой гипотетически лучший способ
SpawnCoolDude(x, y, z, swagLevel);
Но прежде чем начать переписывать mathematics.lib, потому что «вы можете сделать это лучше», давайте поговорим о реальности.
Проверка реальности (сейчас уже не 1999 год)
Современное рендеринг включает в себя больше слоёв, чем луковица в тренче:
Теперь представьте, что вы поддерживаете это, одновременно внедряя:
- 14 различных техник теневого картирования
- 3 системы пространственного разбиения
- Тот странный баг, который появляется только на мобильных GPU NVIDIA 2018 года
Время: тихий убийца
Средний современный игровой движок состоит из:
- более 1,2 млн строк графического кода
- более 300 вариаций шейдеров
- 4,7 метрических тонн обходных путей для драйверов Вот как выглядит рендеринг треугольника в сыром OpenGL:
// Всего 57 шагов для отрисовки треугольника!
GLuint VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
Сравните с Unity:
// Шаг 1: Создать треугольник
// Шаг 2: Посмотреть на треугольник
// Шаг 3: Получить прибыль
Ловушка экспертизы
Вам нужно будет освоить:
- Линейную алгебру (веселье никогда не заканчивается!)
- Оптимизацию SIMD
- Системы материалов PBR
- Управление памятью в Vulkan/DirectX12
- Примерно 37 различных координатных пространств Однажды я потратил три недели на отладку проблем с z-буфером, только чтобы обнаружить, что перепутал нормали пространства просмотра и мирового пространства. Это реальная история.
Когда это может иметь смысл
Допустимые причины напоминают мои привычки по стирке белья — редкие, но иногда необходимые:
- Вы разрабатываете экспериментальное оборудование (квантовый игровой компьютер?)
- Вам нужен идеальный контроль для архивных проектов
- Вы пишете кандидатскую диссертацию о временном апсэмплинге
- Вы наслаждаетесь болью как стилем жизни
Кошмар обслуживания
Каждое обновление движка ощущается как:
- Обновление драйверов графики
- Всё ломается
- Проклинаете существование
- Откатываете драйверы
- Повторяете до выхода на пенсию Современные движки уже обрабатывают:
- Кроссплатформенную компиляцию
- Обходные пути для драйверов
- Пиплайны компиляции шейдеров
- Колдовство выравнивания памяти Как сказала разработчик Unity Джессика: «Я бы скорее научила своего кота C++, чем снова занималась поддержкой нашего внутреннего стека рендеринга».
Парадокс продуктивности
Давайте подсчитаем:
Задача | Собственный движок | Unreal Engine |
---|---|---|
Базовый PBR материал | 2 недели | 2 минуты |
Отложенный рендеринг | 1 месяц | 1 флажок |
Отладка сбоев GPU | 3 недели | 3 эспрессо |
Пока вы заняты реализацией очередного метода теней, кто-то, использующий существующий движок, занимается:
- Оттачиванием игровой механики
- Созданием контента
- Реальным выпуском своей игры
- Имеет жизнь
Лучший путь вперёд
Вместо полноценной разработки движка рассмотрите:
// Настраивайте, а не переделывайте
void MyAwesomeRenderer::ApplyBlackMagic(RenderPass pass) {
if (Engine->GetSettings()->UseDarkSorcery) {
// Ваш особый соус здесь
CastVoodooSpell(pass);
InvokeCthulhu();
} else {
Engine->DefaultRender(pass);
}
}
Современные движки более расширяемы, чем мои оправдания пропущенных сроков. Доступ к исходному коду Unreal Engine от Epic стоит примерно столько же, сколько зарплата одного разработчика за месяц.
Заключение: будьте шеф-поваром, а не фермером
Если вы не занимаетесь разработкой движков (в противном случае, зачем вы читаете это?), сосредоточьтесь на том, что действительно важно — создании удивительных впечатлений. Миру не нужен ещё один недоделанный обёртки OpenGL — ему нужны ваши уникальные игровые идеи.
Теперь, если вы меня извините, мне нужно пойти извиниться перед моим GPU за то, что я с ним делал в 2017 году. Он до сих пор мигает предупреждающими знаками, когда я открываю редакторы шейдеров.