как мы рожали death track

Прошло уже некоторое время с момента выхода наших гоночек ( http://deathtrack.ru/), предрелизные страсти улеглись, патч выпущен и, говорят, как раз самое время собрать камни. В связи с чем попробую рассказать немного про то, как мы тот Death Track делали. Расскажу выборочно и в основном про картинку ну или про то что с этой картинкой связано.

Одна из первых проблем, с которой мы столкнулись практически в самом начале разработки, это то, что геометрия трасс не помещалась в видеопамять. Точнее в 256 мегабайт помещалась фактически только она одна, и занимала порядка 170-180 мб. Потратив некоторое время на эксперименты, проанализировав количество отрисовываемой в кадре геометрии, количество вершин в дипах, пришли в итоге к созданию геометрического кеша, представляющего собой пул из Н элементов, каждый из которых содержит по М вершин ( Н и М настраиваются для каждой трассы ). Каждый элемент кеша живет не менее К кадров, причем цпу убегает вперед тоже не более чем на К кадров. Выполнение последнего условия позволяет при заливки геометрии лочить буфер с флажком нооверайт и никогда не делать дискард. В итоге такая схема вполне себе зажила, в кадр в зависимости от динамичности действий в игре заливалось от 0 до сотен килобайт геометрии, при этом использовалось 25-40 мегабайт видеопамяти, что вполне нас устраивало. Нам в редакцию приходило письмо с вопросом – а зачем было не сделать просто managed vertex buffer и не мучатся. С помощью такого кеша мы делаем микроменеджмент – заливаем только ту геометрию, которая нужна нам в этом кадре и не байтом больше. В случае же управляемого ресурса, если бы он оказывался высвоплен то при использовании его при отрисовке происходила бы заливка всего его содержимого в видеопамять, что вообщемто нежелательно.

Далее, трассы получились с одной стороны достаточно высокодетализированными а с другой – топология их такова, что строения/ландшафт расположенный по обочине трассы отлично закрывает отдаленные её кусочки. Порешили делать мегасистему геометрических оклудеров. Специально обученные дизайнеры в редакторе расставляют OBB. Оклудер из такого обб получается очень просто – силуэт вытягивается в бесконечность, по фронтфейсам строится ближние плоскости и в итоге получаем что наш оклудер это на самом деле фрустум. Можно кстате наверное было и двухсторонней плоскостью было обойтись заместо обб, чуть проще местами было бы, но мы всё же сделали боксы. Соответственно в рантайме из активных обб вытягиваются фрустумы, оклудят друг друга и получается финальный список активных оклюдеров ( типично 10-20 в кадре ). Далее оклюдим непосредственно геометрию трассы. Тут видимо стоит рассказать как у нас хранится геометрия трассы. Геометрия трассы – это один мегомеш, побитый на тайлы (128х128 метров), как горизонтально, так и вертикально. В каждом тайле хранятся фрагменты, на которые в общем случае назначаются свои уникальные материалы. Баундинг бокс каждого тайла разбивается на 4х2х4 бокса и на этапе экспорта считается статическая масочка – в каких из этих кусочков есть геометрия. Кроме того, для каждого фрагмента также считается масочка – в каких из маленьких боксов тайла этот фрагмент находится. Затем в рантайме для каждого тайла каждый кадр строится динамическая 4х2х4 масочка которая потом тестится против статической предрасчитаной для каждого и фрагмента и таким образом отсекается заоклюденная геометрия. Такой кулинг позволил существенно сократить кол-во отрисовываемой геометрии ( процентов 30-50 ) а также уменьшить размер геометрического кеша. Сразу скажу что растеризовать оклудеры мы не пробывали, но говорят тоже вполне может взлететь особенно если тех оклудеров много.

Следующая трудность с которой мы столкнулись было количество дипов. Изза всё тойже детализации и наполненности трасс на них присутствует множество мелких и не очень одинаковых объектов расставленных здесь и там. Раньше у нас жил статический инстансинг константами но он позволял группировать очень ограниченное число объектов, увеличивал потребление видеопамяти ну и желательно было чтобы они находились рядом. Было принято решение отказатся от статического инстансинга и инстансить прямо в рантайме по мере рисования геометрии. В результате, при добавлении мешей на отрисовку уникальные фрагменты кешируются и при добавлении уже закешированного фрагмента сохраняется только перинстанс информация. Далее перед отрисовкой все данные инстансов заливаются в специальный буфер. При отрисовке инстансенным мешам ставится специальный пин про инстансинг, и меш берёт трансформацию и цвет из вершинных атрибутов а не из констант. Данная техника такаже позволила существенно сократить количество дипов ( в некоторых кадрах кол-во дипов уменьшилось на 1500 )

Cледующим пунктом идут патиклы. В оригинальном тбм было сравнительно небольшое количество патиклов, что позволяло процесить их полностиью на ЦПУ, делая на ЦПУ не только апдейты но и расчеты ориентации, размеров и т.д. необходимые для отрисовки. В дестреке артисты хотели бОльшее количество патиклов, плюс был уже 2007 год на дворе и просилась отрисовка патиклов хардварным инстансингом. Зеух както писал про рендеринг патиклов, вот у нас всё както так и получилась. Несколько видов ориентации патиклов ( билборды, выравненые по осям, фиксированная ориентация и т.д. ), текстурная анимация и ещё некоторое количество расчетов производите полностью на ГПУ. Выигрыш по скорости получился весьма ощутимым – в 4-5 раз, фактически всё время на ЦПУ занимает заливка данных в буфер. Ещё одним пунктом для радости артистов была реализация так называемых мягких патиклов.

Ещё пробывали сделать чтото типа GI посредством гармоник сферических. Над дорогой расставляли лайтпробы ( автоматически по колмешу на заданной высоте от полотна и заданном расстоянии друг от друга ) в которых потом рисовали кубемапу которую затем раскладывали по гармоникам. Получается в какомто там приближение чтото типа глобального амбиентного освещения. Мы хранили 9 коэффициентов гармоник для каждого из ргб каналов. Далее, в четвертую компоненту вектора положили коэффициенты позволяющие затенять машинки в тоннелях и т.д. Для этого также рисовали в лайтпробах кубемапы уровень черным а небо белым, после чего раскладывали по гармоникам. В рантайме затем выбираются ближайшие к машине лайтпробы, интерполируются на ЦПУ и уже проинтерполированные коеффициенты передаются в шейдер. В итоге получаем что машинка с одной стороны подцвечивается окружающим фоном и затеняется при заезде в тоннели, под мосты и т.д. с другой.

Ну и, наконец, расскажу про отражения в асфальте и несколько постэффектов. Т.к. были дождливые и жаркие трассы, захотелось делать отражения всякого в асфальте. Для этого отражаемые объекты специальным образом помечались в редакторе ( мешы, патиклы ) и затем при отрисовке их позиция отражалась относительно дорожного полотна и кроме того переварачивался сам объект. После этого при отрисовке дороги этот буфер самплится с шумом и получается желаемый эффект. Артисты очень просили цветокорекцию чтобы делать уровни ещё атмосферней в итоге они имею возможность регулировать цветовые уровни отдельно по каждому каналу ( график задаётся кусочно линейно 5ью точками), яркость и контраст. Ещё хотелось чтобы на большой скорости присутствовал некий радиальный блур позволяющий усугубить ощущение того что едешь действительно быстро. В итоге к обычному радиальному блуру была добавлена область (овал) в котором изображение было незаблуренным и начиная с границ этого овала с заданными параметрами радиальный блур нарастал.

В целом всё было плюс минус както так. Отличный движок оставленный шоданом, подпиленный при активном содействии look4awhile. Может чуть не хватило времени и не допилили как могли бы но в целом считаю получилось вполне прилично.

P.S. а динамического освещения в этой игре нет

  • CEMEH

    Жжошь напалмом. Касег, пеши исчо, рассказ отличный.

  • Tagvard

    Рассказ интересный.
    Про лайтинг спрошу. Стат геометрия трассы лайтмэпом освещается? Судя по шотам (http://games.1c.ru/death_track/gallery/death_track7.jpg) нормальмэп там присутствует и спекуляр какой-то. В лайтмэпе там у вас что за данные? Также на шотах кое-где что-то вроде теней видно. Тоже расскажи.
    Еще про мягкие патиклы спрошу. Глубину доп проходом рендерили в r32f или забили на МСАА и юзали всякие платформенно-зависимые depth textures?

  • http://gaijin.ru todace

    Спасибо, интересно.
    в Адреналине1 и LRC такое же освещение машин. Только вместо окклюдеров – порталы, но близко довольно. Думаю на трассах ДТ порталы бы даже лучше подошли бы, чем в ладе. Окклюдеры впрочем тоже хорошо. В ладе еще с диска грузились кусочки, стримингом. Для каких кусков какие грузить а какие выгружать делалось автоматически, плюс возможность ручного указание (пользовалось для лендмарков, типа МГУ и РАН)
    Инстансинг понятно юзать нельзя было – должно было работать на GF2 и MX. Давно было. Динамическое освещение было – фары. Остальное статическое.

    PS В А2 уже не так почти все, но местами еще похоже. Там и с инстансингом и с дин.светом и еще всякое, а свет на машинке уже по другому делается, как и тени. Хотя тоже с ГИ.
    В следующем уже совсем все не так.

  • kas

    статическая геометрия лайтмапами, да. часть в текстурах часть в вертексколоре. нормалмапы тоже есть, от солнца освещение. в лайтмапе цветная освещенность. тени от машинок только – либо усм либо псм, рендица в цвет и разблуриваеца до нужной кондиции. глубину рендим таки отдельным проходом без аа и всякого, в меньший рт. платформозависимые юзать не стали с зпрепасом совмещать тоже изза аа того

  • http://www.creative-assembly.com.au/ Loyso

    Отличный дебют, Вадим! Еще заметок давай! :)

  • Dmitry Tyurev

    Несколько окклюдеров могут совместно загораживать один объект?

  • kas

    только для тайлов тайлмеша – те самые масочки как раз про ето

  • Dmitry Tyurev

    Возьмём общий случай. Имеется произвольный бокс, часть которого в данном кадре загораживается одним оклюдером, а часть вторым оклюдером. В сумме бокс загораживается целиком. Может ли тест определить, что данный бокс невидим?

  • kas

    если соответствующие части бубокса образующие масочку заоклюдяца то да, иначе нет