Главная » Хабрахабр » [Перевод] Как было реализовано пламя в Doom на Playstation

[Перевод] Как было реализовано пламя в Doom на Playstation

Целая глава моей книги Game Engine Black Book: DOOM посвящена консольным портам DOOM и сложностям, с которыми сталкивались их разработчики. Можно долго рассказывать о полном провале на 3DO, о сложностях на Saturn из-за аффинного наложения текстур и о потрясающем «реверс-инжиниринге с нуля», выполненном Рэнди Линденом для Super Nintendo.

Final DOOM был первым истинным портом, сравнимым с PC-версией. Изначально двинувшись в направлении, ведущем к катастрофе[1], разработчики порта под Playstation 1 (PSX) в дальнейшем сменить курс и создать порт, завоевавший успех у критиков и рынка. Также благодаря эффектам реверберации Audio Processing Unit консоли PSX был улучшен звук. Цветовые сектора с альфа-смешением не только усовершенствовали визуальное качество, но и улучшили геймплей благодаря индикации ключа нужного цвета.

Меня это настолько привело в благоговейный трепет, что я решил разобраться, как был реализован эффект. Команда разработчиков выполнила настолько качественную работу, что у неё осталось ещё немного свободных циклов ЦП, которые они решили использовать для генерации анимированного огня в интро и геймплее. Мне достаточно было просто немного её подчистить, упростить и оптимизировать.
Было интересно заново обнаружить этот классический эффект демосцены; лежащая в его основе идея похожа на первую водную рябь, которая входила в обязательный набор программ многих разработчиков 90-х. Когда первые поиски не дали ответа, я приготовился уже сдувать пыль с книги по MIPS для взлома исполняемого файла, но Сэмюэль Вильяреал вовремя ответил в Twitter, что он уже выполнил обратную разработку версии для Nintendo 64[2]. Эффект огня стал живым свидетелем того времени, когда тому, что сочетание тщательно подобранной цветовой палитры и простого трюка были единственным способом добиться желаемого.

Базовая идея

В своей основе эффект огня использует простую карту высот. Массив размером с экран заполняется 37 значениями в интервале от 0 до 36. Каждое значение связывается с цветом от белого до чёрного, и захватывает по дороге между ними жёлтый, оранжевый и красный. Идея заключается в моделировании температуры частицы пламени, которая поднимается вверх и постепенно охлаждается.

Буфер кадра инициализируется полностью чёрным (заполненным нулями) с единственной белой строкой белых пикселей внизу (36), которая является «источником» пламени.

При каждом обновлении экрана «тепло» поднимается вверх. Для каждого пикселя в буфере кадра вычисляется новое значение. Каждый пиксель обновляется с учётом значения, расположенного непосредственно под ним. В коде нижний левый угол это нулевой индекс массива, а верхний правый угол имеет индекс FIRE_HEIGHT * FIRE_WIDTH — 1.

function doFire() } } function spreadFire(src) { firePixels[src - FIRE_WIDTH] = firePixels[src] - 1; }

Заметьте, что строка 0 никогда не обновляется (итерация по y начинается не с 0, а с 1). Эта заполненная нулями строка является «генератором» огня. Простая версия с линейным охлаждением (-=1) даёт нам скучные равномерные выходные данные.

Мы можем немного изменить функцию spreadFire() и модифицировать скорость затухания значений теплоты. Вполне подойдёт добавление случайности.

function spreadFire(src) { var rand = Math.round(Math.random() * 3.0) & 3; firePixels[src - FIRE_WIDTH ] = pixel - (rand & 1); }


Так уже лучше. Чтобы усовершенствовать иллюзию, можно случайным образом распространять не только вверх, но также влево и вправо.

function spreadFire(src) { var rand = Math.round(Math.random() * 3.0) & 3; var dst = src - rand + 1; firePixels[dst - FIRE_WIDTH ] = firePixels[src] - (rand & 1); }

[Прим. пер.: Youtube ужасно пережимает видео, лучше смотреть демо на Javascript в оригинале статьи.]

Заметьте, что изменяя процесс распространения пламени можно также симулировать ветер. Вуаля! Я оставлю это в качестве упражнения для читателей, которым удалось дочитать статью.

Полный исходный код

Версия Сэмюэля (логически) выглядела больше похожей на ассемблерную. Если хотите взглянуть на неё, то здесь есть подчищенная и упрощённая версия.

Справочные материалы

[1] Источник: Полная история подробно рассказана в книге Game Engine Black Book: DOOM

[2] Источник: пост в Twitter за 25 марта 2018 года


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

Внедряйте статический анализ в процесс, а не ищите с его помощью баги

Написать эту статью меня сподвигло большое количество материалов о статическом анализе, всё чаще попадающихся на глаза. Во-первых, это блог PVS-studio, который активно продвигает себя на Хабре при помощи обзоров ошибок, найденных их инструментом в проектах с открытым кодом. Недавно PVS-studio ...

[Перевод] Как рендерится кадр Rise of the Tomb Raider

Rise of the Tomb Raider (2015 год) — это сиквел превосходного перезапуска Tomb Raider (2013 год). Лично я нахожу обе части интересными, потому что они отошли от стагнирующей оригинальной серии и рассказали историю Лары заново. В этой игре, как и ...