Как совершать ошибки. 2011г
Как следует из названия, в далеком 2011 году мы совершили третью ошибку, выбрав в качестве основы для игрового движка Ogre3D. Третью, потому что первой ошибкой было решение делать игру, а второй — делать ее на своем движке. К счастью, это были те самые ошибки, с которых начинается увлекательная история. Это приключение, в котором мы прошли почти весь путь развития игровых движков, как зародыш проходит все этапы эволюции.
Конечно же, как и все начинающие разработчики, мы слабо представляли себе, что и зачем мы собираемся делать. Нами двигало желание рассказать свою историю, создать свой вымышленный мир, свою вселенную, и на волне популярности ММО, естественным позывом было сделать свою ММО с блекджеком и всем причитающимся. Позыв случился еще в 2010, а к 2011 была готова первая версия диздока. Земля же была безвидна и пуста, и тьма над бездною, и Дух Фоллаута витал над нами.
Мы шли путем проб и ошибок, собирая по пути все косяки и грабли. Как и большинство проектов, мы начали с самого простого. В плане графики (а я буду рассказывать только о графической части) первая версия движка позволяла использовать только диффузную карту и стенсильные тени.
2011г. Один из первых скриншотов
В технологическом плане по графике мы тогда сильно ориентировались на игры типа Торчлайт. Но душе требовала большего, ведь параллельно с развитием графической части движка шел и художественный поиск.
К осени 2012 года в плане графики мы доросли до использования карт нормалей и спекуляров. Влияние DOOM 3 было сильно на неокрепшие умы начинающих разработчиков.
2012г. До DOOM 3 как до Марса.
Как выбрать между дудочкой и кувшинчиком. 2013г.
Зимой 2013 года команда приросла красивым трехмерщиком и обаятельным программистом графики. Фантазии ведущего художника нашли точку опоры, и движок стал прирастать графическими нововведениями. Появились текстура глянцевитости (она же карта степенного коэффициента спекуляра, она же glossiness, она же shininess), каскадные текстурные тени, DoF(эффект глубины резкости), RIM-освещение и куча глюков. В этот период стали особенно явно всплывать проблемы коммуникаций разных специалистов. Одни и те же вещи для разработчиков с разным бэкграундом назывались совершенно по-разному, и требовали многократного проговаривания.
Все чаще стали затеваться жаркие баталии о траектории развитии движка. В условиях ограниченных бюджета и времени приходилось выбирать между программированием геймплейной части и визуальной. Так, RIM появился как компромисс между желанием художника видеть более явный метал, желанием трехмерщика иметь для этого отражения и текущими возможностями движка. Все более остро стал вставать вопрос о переходе на готовый движок: Unity3D становился все более функциональным и популярным, стали появляться слухи о человеческих схемах лицензирования UDK.
Начало 2013г. Картинка стала чуть веселей, но ненамного.
Конец 2013г. Картинка стала еще веселей.
Как нарваться на неприятности. 2013г.
Осенью 2013г. мы в первый раз вышли на кикстартер. Свидетельства этому печальному опыту мелькали даже на Хабре. Кампанию мы прикрыли в течение первой же недели, поскольку стало очевидно, что «не взлетит». ММО к этому моменту начали раздражать игроманов, очередной «клон ВоВ» (коим игра ни в коей мере не планировалась, но убедить в этом геймеров не удавалось) никого не интересовал. В качестве работы над ошибками было решено, что мы отныне делаем РПГ синглу с кооперативным прохождением.
Конец 2013г. Скриншот из презентационной сцены..
Как обрести свободу. 2014г.
Фантазия ведущего художника требовала больших и сложных пространств. Реализация этих фантазий и ведущий трехмерщик требовали возможности оперировать не пятью источниками света, а гораздо большим их количеством.
Ограничение в 5 (на самом деле 8, но фпс проседал уже на пятом) источников света было обусловлено применением forward render (прямого рендера)
Прямой рендер — стандартный способ рендера, который используют большинство движков. Каждый объект, полученный видеокартой проходит полный путь рендеринга. При этом вертексный и пиксельный шейдеры считаются для каждого источника света отдельно даже для тех пикселей, которые могут впоследствии перекрыться другими. Каждый дополнительный источник света создаёт дополнительную итерацию рассчётов по всей геометрии. И при восьми источниках света в сцене из 1 миллиона видимых треугольников рисуется уже около 9 миллионов треугольников. Это приводило к очень низкому FPS на сколько-нибудь сложных локациях…
Призрак Крузиса с его сотнями лампочек не давал спать по ночам. Было решено перейти на deferred render (отложенный рендер или отложенное освещение). При отложенном рендере формируется набор «конечных» изображений без расчета теней: изображение цвета, изображение глубины и изображение нормалей. Зная положение источников света, глубину пикселей и нормали можно рассчитать затенение.
По сравнению с forward-rendering мы получили несколько плюшек:
1) Повышение фпс за счёт того, что геометрия рендерится только один раз
2) Возможность работать со множеством источников света: добавление нового источника света слабо сказывается на производительности.
3) Ускорение некоторых видов пост-обработки, более эффективная реализации мягких частиц и возможность добавления обработки screen-space reflection. Мягкие частицы, а также эффекты пост-обработки (DOF, SSR, SSAO) требуют карты глубины и нормалей. Прямой рендер не даёт эти карты, и их приходится рендерить отдельно. При отложенном освещении эти карты нам подаются на блюдечке с голубой каёмочкой.
Недостатки:
1) Полупрозрачность. Полупрозрачные объекты нельзя рисовать в отложенном освещении, т.к. потребуется, чтобы один пиксел каждой текстуры (нормаль, диффуз и т.д.) содержал информацию о нескольких перекрывающихся объектах. Есть множество различных способов решения проблемы, но чаще всего используется один — все полупрозрачные объекты рендерятся отдельно с помощью прямого рендера.
2) Алиасинг. При отложенном освещении fsaa отключается и все треугольники рисуются с явно выраженным алиасингом. Для решения этой проблемы используют различные методы, например FXAA
3) Повышенное требование к пропускной способности памяти видеокарты.
Мы рассматривали три варианта реализации отложенного освещения:
Вариант А:
Расчет освещения делится на два этапа:
1. На первом этапе рисуется вся непрозрачная геометрия в 4 текстуры. (диффуз, спекуляр, глянцевитость, нормаль, карта глубины и карта свечения)
-диффуз, спекуляр, глянцевитость берутся напрямую из текстур геометрии,
-нормали добываются из карты нормалей натянутых на геометрию и преобразованных в координаты пространства камеры.
-карта свечения получается путем сложения карт самосвечения, RIM освещения, амбиентного диффузного освещения +слабой подсветки со стороны камеры.
2. Используя карты нормалей, глубины, диффуза, спекуляра и глянцевитости рассчитывается диффузное и спекулярное свечение каждой точки для каждого источника света и инкрементно суммируется с картой свечения. В этом же пассе проверяется попадание каждой точки экрана в теневые карты.
Это стандартный вариант отложенного освещения, реализуемый в большинстве игр.
Вариант Б:
Рассчет освещения делится на 3 этапа:
1. На первом вся непрозрачная геометрия рендерится в 1 текстуру (рендерятся карты нормалей, глубины и глянцевитости)
2. По картам нормалей, глубины и глянцевитости рендерятся две карты: диффузного и спекулярного освещения для каждого источника света.
3. На третьем этапе рендерится финальное изображение: рисуется вся непрозрачная геометрия ещё раз, но с диффузом и спекуляром и вычисляется освещенность каждой точки путем умножения диффузного освещения на диффузную карту+произведения спекулярного освещения на спекулярную карту+рим-освещение+карту самосвечения+свет от камеры.
Преимущества этого метода:
1) Меньше требований к пропускной способности видеопамяти видеокарты.
2) Меньше вычислительных операций на каждый источник света, т.к. часть операций переходит из второго этапа в третий.
3) Третий этап уже может редерится со включенным fsaa, что увеличивает качество картинки.
Недостаток этого метода один — два раза рендерится вся геометрия. Однако второй раз можно рендерить по готовому z-буферу, подготовленному на первом этапе.
Вариант В:
Рассчет освещения делится на 3 этапа:
1. На первом этапе рисуется вся непрозрачная геометрия в 4 текстуры (диффуз, спекуляр, глянцевитость, нормаль, карта глубины и карта свечения (как сумма от сложения карт самосвечения, RIM освещения, амбиентного диффузного освещения +слабой подсветки со стороны камеры)).
2. По картам нормалей, глубины и глянцевитости рендерятся две карты: диффузного и спекулярного освещения для каждого источника света.
3. На третьем этапе рендерится финальное изображение: вычисляется освещенность каждой точки путем умножения диффузного освещения на диффузную карту+произведения спекулярного освещения на спекулярную карту карту самосвечения…
Этот вариант — смесь первых двух вариантов. По сравнению с вариантом A мы получаем выигрыш в скорости за счет особенности варианта Б: вместо четырёх выборок из текстуры идёт только одна.
Сейчас у нас реализован первый вариант отложенного совещения. Все каналы которые используются для отрисовки финальной картинки можно выводить в отладочном режиме.
После рендера финальной картинки делается постообработка: здесь у нас создается эффект глубины резкости и делается цветокоррекция. На этом же этапе рисуются отражения по технологии SSR.
SSR (Screen Space Reflection) — это алогоритм создания в сцене реалистичных отражений с использованием данных, которые уже отрендерены на экране. Кратко: от камеры пускается луч до пересечения со сценой. Используя нормаль в точке пересечения, считается отражение. По этому лучу отражения происходит трассировка карты глубины пока до попадания в какую-либо геометрию, в качестве результата берётся светимость найденой точки и умножается на спекуляр отражающей точки и записывается в светимость отражающей точки.
Сейчас реализовано два алгоритма Screen Space Reflections:
1) Трассировка происходит в координатах камеры — медленная, но дающая правильную картинку.
2) Трассировка происходит в координатах текстуры — быстрая но даёт погрешность при малых углах.
2014г. Презентационная диорама с включенными отражениями.
2014г. Презентационная диорама с включенными отражениями.
Мы используем свой игровой и сетевой движок. Графический движок — Ogre3D, Физический — Bullet. Скриптинг: Lua, C# (Mono). Во время разработки пришлось сильно допиливать Ogre3D и отлаживать его связку с Blender… В планах связаться с разработчиками Огра и предложить включить свои доработки в следующие сборки Огра.
Используемые языки программирования: C++, PHP, Lua, C#, Python, Java, Groovy, Cg, GLSL, HLSL.