
Часть 2: Многопоточность
Часть 3: Рендеринг (Прим. пер. — в процессе перевода)
Часть 4: Doom classic — интеграция (Прим. пер. — в процессе перевода)
26 ноября 2012 ID Software выпустила исходный код Doom 3 BFG edition (всего через месяц после появления игры на прилавках магазинов). Движок idTech4, которому уже почти 10 лет, был обновлен решениями, используемыми в idTech 5 (Rage — первая игра на этом движке), и с его исходным кодом ознакомиться было очень интересно.
Я бы назвал движок «idTech4 улучшенный», т.к. по сути это idTech4, но с использованием элементов idTech5:
- Систему управления потоками (Threading system)
- Звуковую систему (Sound system)
- Систему управления ресурсами (Resources system)
До сих пор наиболее привлекательным аспектом является система управления потоками: Doom 3 была разработана на заре эпохи многоядерных систем, когда немногие компьютеры еще использовали SMP. Теперь правила изменились, даже телефоны оснащены несколькими ядрами и игровой движкок должен быть многопоточным, чтобы использовать весь потенциал машины.
Я надеюсь, что это вдохновит людей разбираться в исходном коде, улучшать свои навыки и становиться лучшими инженерами.
Первый контакт

- Получить исходники, расположенные на GitHub:
git clone https://github.com/id-Software/DOOM-3-BFG
- Открыть Visual Studio 2010 Express и нажать F8 для компиляции. Готово!
Примечание: Если Direct3D SDK установлен, полный проект компилируется менее чем за минуту, выдав 5 минимальных предупреждений.
Режим отладки
Всего 3 шага необходимо, чтобы начать мастерить в Visual Studio 2010 Express:
- В комадной строке отладки указать базовый путь:
+set fs_basepath "C:\Program Files\Steam\SteamApps\common\DOOM 3 BFG Edition" +set r_fullscreen 0
- Открыть проект «Doom3BFG».
- Нажать F5

Удобочитаемость исходного кода
Подмножество C++:
Doom 3 BFG написана на C++, языке настолько великом, что он может быть использован как для создания великолепного кода, так и для такой мерзости, от которой ваши глаза будут кровоточить. К счастью ID Software использовало подмножество языка С++, близкое к «С с классами», которое будет не таким сложным для восприятия:
- Отсутствуют исключения
- Нет ссылок (используются указатели)
- Минимальное использование шаблонов
- Константы повсюду
- Классы
- Полиморфизм
- Наследование
И несмотря на многопоточность, в коде не используются смарт-указатели или Boost. Какое облегчение (ведь это то, что обычно делает код нечитаемым).
Комментарии
Комментариев много и они довольно полезны, так как они, как правило, одним предложением описывают то, что просходит в наиболее важных местах следующего блока. Вот пример из
ParallelJobList.cpp
: int idJobThread::Run() {
threadJobListState_t threadJobListState[MAX_JOBLISTS];
int numJobLists = 0;
int lastStalledJobList = -1;
while ( !IsTerminating() ) {
// fetch any new job lists and add them to the local list
if ( numJobLists < MAX_JOBLISTS && firstJobList < lastJobList ) {
threadJobListState[numJobLists].jobList = jobLists[firstJobList & ( MAX_JOBLISTS - 1 )].jobList;
threadJobListState[numJobLists].version = jobLists[firstJobList & ( MAX_JOBLISTS - 1 )].version;
threadJobListState[numJobLists].signalIndex = 0;
threadJobListState[numJobLists].lastJobIndex = 0;
threadJobListState[numJobLists].nextJobIndex = -1;
numJobLists++;
firstJobList++;
}
// if the priority is high then try to run through the whole list to reduce the overhead
// otherwise run a single job and re-evaluate priorities for the next job
bool singleJob = ( priority == JOBLIST_PRIORITY_HIGH ) ? false : jobs_prioritize.GetBool();
// try running one or more jobs from the current job list
int result = threadJobListState[currentJobList].jobList->RunJobs( threadNum, threadJobListState[currentJobList], singleJob );
В общем читатель получает непосредственное понимание каждой части алгоритма, и я надеюсь, что это вдохновит людей писать лучший код: ведь сейчас разрабатывая ПО, не главное быть большим асом чем другие. Не менее важно уметь работать в команде, создавая код:
- Изящно спроектированный
- Легко читаемый, с использованием комментариев где это нужно
Doom 3 BFG имеет высокие показатели по обоим этим позициям.
Что изменилось?
- 2 проекта «Game» (Doom III classic и Ressurection) объединены в один проект
- Убран cUrl
- Убрано глупое название DoomDLL… Это было на самом деле генерации DOOM3.EXE
- Убраны устаревшие инструменты Maya для экспорта md5 модели, анимации и пути камеры.
- Убран TypeInfo, взамен добавлен RTTI/Introspection.
Обозреватель решений (solution explorer) в Visual Studio стал заметно чище (до и после):


Подпроекты Doom 3 BFG
Projects |
Builds |
Observations |
Amplitude | Amplitude.lib | Используется в Doom Classic: Инструмент для регулировки амплитуды WAV. |
Doom3BFG | Doom3BFG.exe | Движок Doom 3 BFG. |
doomclassic | doomclassic.lib | Серьезно переработанный движок Doom1/2. |
external | external.lib | Исходники jpeg-6 и zlib. |
Game-d3xp | Game-d3xp.lib | Единая библиотека игры, включающая оригинальную игру + расширения + новые уровни. Обратите внимание, что теперь она собирается в статическую библиотеку вместо DLL. |
idLib | idLib.lib | Пакет инструментов id software для работы с файловой системой. |
timidity | timidity.lib | Используется вДум Classic для преобразования MIDI-файлов в формат WAV. |
Новая архитектура

- Консоли, такие как PS3/Xbox360 не лучшим образом поддерживают динамические библиотеки.
- Ускорить скорость разработки. При использовании библиотеки dll возникают проблемы с выделением памяти. Это порождает ошибки которые трудно отследить.
Изменения связанные с разработкой для консолей:
Ориентация на Xbox 360 и PS3 в проекте, изначально ориентированном на ПК привело ко многим важным обновлениям:
- Как упоминалось ранее вся игра содержится в одном исполняемом файле.
- В игре для хранения различных частей используются файлы PAK (являющтеся ZIP архивами). Высокая латентность DVD приводов толкнуло ID Software к следующему распределению ресурсов: один файл, содержит всё необходимое для одной загрузки уровня.
- Игровые активы были текстовыми, но для того, чтобы снизить время загрузки, некоторые из активов, таких как модели и анимация теперь двоичные ( .bmd5mesh и .bmd5anim ).
- Doom 3 разрабатывался для работы с разрешением 640x480 с соотношением сторон 4:3. В настоящее время телевизоры и мониторы чаще всего имеют соотношение сторон 16:9, поэтому все меню были сделаны заново. Вероятно, в целях ускорения разработки, она реализуются на Adobe Flash. Doom 3 BFG использует собственный интерпретатор Flash (/neo/swf/ ). И снова Flash используется для того, чтобы ускорить разработку.
- Рендеринг шейдеров был переписан с использованием GLSL 1.5. HLSL шейдеры могут преобразовываться на лету.
- Для получения приемлимой частоты кадров фонарик нельзя было использовать вместе с оружием. (Прим. пер. — в оригинале есть фраза «Now with Doom 3 BFG it can be duck taped on weapons but for performances reason it won't cast any shadows. » Вероятнее всего имеется ввиду не «duck taped», а «duct taped» — скотч, т.е. «Теперь же, в Doom 3 BFG он может быть прикреплен к оружию...»)
- Т.к. меню теперь кросплатформенно PC во многом утратило настройки рендеринга: мы получаем простую версию, которая используется как в ПК, так и консолях.
Многопоточность
За 10 лет, прошедших между разработкой старого и нового движка произошел сдвиг парадигмы: «бесплатный сыр» закончился, и игровые движки должны быть разработаны с использованием многопоточности. Поэтому наиболее привлекательной вещью для чтения в Doom III BFG является idTech5 Threading архитектура. (Подробный обзор во 2ой части перевода).
Рендеринг
Тут 2 главных изменения:
- Работает на Open GL 3.2 Совместимость профиля с использованием GLSL шейдеров 1.5.
- Использование многопоточности (до четырех потоков, работающих одновременно).
Doom classic
Doom III BFG позволяет играть в Doom 1 и Doom 2. На первый взгляд простая задача интегрировать старый движок Doom1 в новый Doom 3 BFG: просто перенаправить все входы / выходы! Но с учетом режима разделенного экрана на PS3 и Xbox360 это реализуемо не так-то просто. (Подробный обзор в 4ой части перевода)

Пост является переводом, но т.к. публикуюсь из песочницы — не могу изменить тип поста. Последующие части будут оформлены правильно. Ошибки перевода, опечатки с радостью исправлю, пишите в лс.
Оригинал первой части — Fabien Sanglard