GrabDuck

Как мы делали мод под Oculus Rift для World of Tanks

:

image

Предыстория


Примерно полтора года назад в руки разработчиков минской студии Wargaming попал DK1. Спустя месяц, когда все наигрались в Team Fortress и Quake в Full 3D, возникла идея заделать что-нибудь с Oculus в самих «Танках». О процессе, результатах и подводных камнях работы с Oculus — читайте ниже.

В World of Tanks мы поддерживаем некоторое количество игровой периферии, которое расширяет UX игрока (вибронакидку, например). Однако c появлением двухмиллиардного Oculus Rift мы решили, что пора бы порадовать не только седалище игроков, но и дать им новую «eye candy».

Честно говоря, никто не знал, как это должно выглядеть, как помогать игроку. Задачу по разработке мода поставили, как говорится, «just for lulz». Не спеша, когда над основными задачами мозг отказывается думать, мы приступили к интеграции: скачали Oculus SDK, установили и начали разбираться с исходниками примеров.

Работы начались с использованием первого девкита, что было несколько опасно для психики. Дело в том, что первый девкит имел весьма низкое разрешение экранов. К счастью, достаточно быстро мы заполучили в свои руки HD-версию, с которой работать веселее.

SDK


Разработку мы начали с версии SDK 0.2.4 для DK1. Затем при получении HD Prototype новой версии SDK не потребовалось. Поэтому 90% времени мы провели используя достаточно старую, но, тем не менее, удовлетворяющую наши потребности версию SDK. Затем, когда работы над Oculus-модом были практически завершены, к нам пришел DK2. И оказалось, что старый SDK для него уже не подходит. Но разве это проблема? Скачали новый SDK, уже версии 0.4.2. Внезапно оказалось, что он переписан чуть более чем полностью. Пришлось менять практически всю обертку над девайсом, вносить различные правки. Но самое интересное случилось с рендерингом. Если раньше пиксельный шейдер был достаточно прост, то в новой версии его изменили и усложнили. А виной всему линзы. Уж не знаю, почему такое решение было принято, но побочный эффект от линз — ужаснейшие хроматические аберрации, уменьшающиеся от края области видимости к центру. Для исправления этого дефекта и был переписан пиксельный шейдер. Решение как минимум странное: ухудшать производительность приложения из-за странного инженерного решения. Но! Пытливый ум и находчивость спасут галактику: оказалось, что линзы от DK1 и HD P отлично подходят и для DK2. И никаких сайд-эффектов у них нет. Вот так.

Инициализация


Процесс инициализации самого девайса, получения контекста полностью перенесен из примера – Ctrl+C Ctrl+V в действии. Никаких подводных камней здесь нет.

Рендеринг


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

В соответствии с этим наш первоначальный алгоритм построения стереоскопического изображения выглядел следующим образом:

1. Установка матриц

Поскольку для каждого глаза необходимо производить рендер с небольшим смещением, сначала нужно модифицировать оригинальную view-матрицу. Необходимые матрицы трансформаций для каждого глаза предоставляет Oculus Rift SDK. Модификация выглядит следующим образом:

• Получить матрицу дополнительной трансформации.
• Транспонировать ее (Oculus Rift использует иную систему координат).
• Умножить слева полученную матрицу на оригинальную.

2. Рендер два раза со сменой матрицы

После модификации view-матрицы для левого глаза и установки ее в рендер-контекст, делаем отрисовку как обычно. После этого модифицируем view-матрицу еще раз для правого глаза, выставляем ее в рендер-контексте и рисуем еще раз.

3. Пост-эффект искажения от линз

Для более полного заполнения зоны зрительного восприятия Oculus использует линзы, которые дают побочный эффект в виде искажения геометрии объектов. Для того чтобы подавить этот эффект, на итоговый рендер применяют дополнительный пост-эффект, искажающий изображение в обратную сторону.

4. Вывод окончательного изображения

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

Вызовы


В ходе разработки мы быстро обнаружили, что на текущий момент четких, стопроцентно работающих гайдлайнов для работы OR в играх не существует. Если запустить несколько разных игр с поддержкой OR, то в каждой из них будут разные реализации интерфейсов и управления в окулусе. Насколько нам известно, разработчики Oculus Rift специально не делают жестких требований и правил. Идея их состоит в том, чтобы разработчики игр сами ставили эксперименты. По этой причине в процессе разработки приходилось не раз переделывать нашу интеграцию c Oculus: казалось бы, вот уже готово, но в некоторых моментах что-то не то, что-то раздражает, и в итоге половину логики приходится выкидывать.

Добавляет веселости еще парочка наших особенностей. Во-первых, в World of Tanks камера в основном висит над танком, и повороты головы в окулусе в таком режиме by design не соответствуют вашему опыту из реального мира. Вы же не можете в жизни зависнуть над техникой, которую ведете (а ведь иногда это могло бы быть так полезно…).

К тому же World of Tanks является PvP игрой, где вам в каждом бою противостоит 29 15 других игроков. Как следствие, Oculus не должен сильно бить по боевым навыкам пользователя. Этот нюанс добавляет дополнительной мороки при разработке. Если немного отвлечься и рассмотреть применимость Oculus Rift в мультиплеерных играх вообще, то это устройство подойдет далеко не каждому классу игр. В проектах с динамикой уровня Quake 3 и Team Fortress 2 окулус может принести больше вреда, чем пользы. В Oculus вы вроде бы смотрите на мир глазами человека, но динамика перемещения в таких играх совершенно отличается от реальности. Как уже упоминалось, если игра использует не first-person-камеры, то возникают проблемы с ориентированием в пространстве, и вообще не совсем понятно, а чем это мы крутим, когда оглядываемся по сторонам. Сложилось впечатление, что, в первую очередь, Oculus Rift применим к синглплеерным играм, где во главу угла поставлено погружение игрока, а также допустимо управление с «неудобствами».

Общая проблема UI


В нашей игре — впрочем, как и в большинстве других — практически весь UI (как в ангаре, так и в бою) расположен по сторонам экрана. И если производить вывод UI без каких-либо дополнительных модификаций, то возникает следующая проблема. Из-за конструктивных особенностей Oculus в область видимости попадает только центральная часть изображения. А UI в свою очередь в эту часть не попадает (или попадает частично).

image

image

Вот какие способы решения этой проблемы мы испробовали.

1. Уменьшить интерфейс и сделать так, чтобы он выводился в центре экрана, попадая в область видимости. Для этого необходимо производить его вывод в отдельный рендер таргет и потом накладывать при постпроцессинге.

Такой способ решает проблему видимости UI, но катастрофически снижает информативность и читабельность.

2. Использовать матрицу ориентации Oculus для позиционирования UI, то есть, дать возможность пользователю осматривать не только 3D-сцену, но и UI.

Этот способ лишен недостатков первого: информативность и читабельность ограничиваются только разрешением девайса. Но у него есть свои минусы: для выполнения привычных действий (просмотр танков в карусели; проверка баланса «серебра» и т.д.) требуется много движений головы и — что вытекает из предыдущего — трудно синхронизировать движения UI и камеры для 3D-сцены.

3. Объединить предыдущие методы, т.е. «скейлить» интерфейс и вместе с тем давать возможность осматривать его. Главной проблемой является подбор такого параметр скейла, который сохранил бы читабельность текста и позволил избавиться от большого количества движений головой.

Сначала мы не делали разделения между интерфейсами в ангаре и в бою. Более того, использование матрицы ориентации Oculus для осмотра UI было навеяно боевым интерфейсом. Практически всю видимую область занимала 3D-сцена, и это казалось правильным, но отсутствие возможности узнать количество «единиц прочности» собственного танка или расположение союзников/противников по миникарте никак не способствовало получению фана от бодрого танкового рубилова в полном 3D. Тогда-то мы и подумали об «осматриваемом» UI: для просмотра, например, миникарты нужно было немного повернуть и наклонить голову — вполне естественное движение для знающего интерфейс нашей игры человека. И тут мы столкнулись с проблемой, которую я описывал: уже через пять минут постоянного вращения головой в поисках миникарты, куклы танка и количества снарядов шея начинала болеть.

Эволюцией, как указано выше, стало использование гибридного варианта: теперь часть интерфейса была видима изначально и для полного осмотра требовалась лишь небольшая «доводка» головой.

Казалось бы, проблема решена, но после просмотра ребята из нашего паблишера отмели и этот вариант.

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

В том же HD Prototype из-за возросшего разрешения в видимую область стало помещаться больше 3D-сцены. Мы приняли решение прекратить опыты с боевым UI и сделать его статическим, но кастомизируемым, позволяющим прямо в рантайме изменять положение и размер его элементов.

Одновременно с решением этих проблем пришлось подумать над еще одним пунктом: некоторые элементы UI не должны скейлиться вместе с другими (например, индикаторы направления попадания, маркеры техники, прицелы). Пришлось внести коррективы в порядок рендеринга: часть элементов интерфейса теперь стала рисоваться вместе с 3D-сценой.

Управление камерами


Oculus является не только устройством вывода изображения, но и устройством ввода. Вводом служит кватернион ориентации (в DK1 и HD P — матрица) девайса в пространстве. Поэтому мы хотели использовать эти данные не только для позиционирования UI, но и для управления камерами.
Ангар

В ангаре схему управления камерами сделали такой: мышью управляется угол наклона и длина «палки для сэлфи» танка. На конце этой «палки» висит камера, направлением которой можно управлять с помощью Oculus: озираться по сторонам, осматривать не только танк, но и окружающее пространство.

image

Аркадный режим

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

image

Снайперский режим

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

Затем попробовали сделать какое-то подобие системы прицеливания Team Fortress: камера контролируется движениями головы, но есть некоторое пространство по центру видимой области, в котором прицел можно двигать только мышью для более прицельной стрельбы. Прототип был неплох, но трудности использования оставались.

Поэтому решили остановиться на самом простом и действенном варианте: камера управляется головой и мышью. То есть, при движении головы точка прицеливания не изменяется — только направление камеры. А при движении мыши меняется и точка прицеливания, и направление камеры.

Стратегический режим

Изначально не планировалось использовать Oculus для игры на арте, поэтому в стратегическом режиме никаких доработок нет.
Режим наводчика

Однажды, исчерпав идеи, каким бы еще интересным образом заюзать Oculus как устройство ввода, мы обсуждали плюсы и минусы девайса и предположили, что игроку легче будет представить себя в виртуальном 3D-мире виртуальным человеком, нежели виртуальным танком. И решили выделить роль в танке, которую игроку будет интересно примерить: такой ролью оказалась роль наводчика. Камера, которую можно закрепить на каком-нибудь узле танка, у нас уже была, поэтому оставалось только настроить позиционирование и ограничить область обзора, чтобы игрок не смог посмотреть внутрь танка или через ствол. Для теста мы выбрали два танка — ИС и Tiger I — из-за их популярности и наличия на момент разработки их моделей в HD. Реализация заняла всего несколько дней, а в итоге режим получился самым интересным и необычным в плане геймплея.

Название режима пока «плавает»: кто-то его называет «камерой наводчика», кто-то — «камерой из командирской башенки». Главная особенность режима состоит в том, что камера в нем висит в координатной системе реальной башни танка, и при этом допускаются повороты головы с помощью Oculus Rift. Весь танк игрока при этом не прячется, так что можно окинуть взглядом всю громаду своей машины. А ведь в таком ракурсе танк воспринимается гораздо внушительнее, чем через камеру, удаленную на пару десятков метров. При этом возник вопрос, к какой точке башни крепить камеру в таком режиме. Для ИС и Tiger I мы сделали хардкодный вариант: камера в нем крепится рядом со стволом. Генерацию точек для остальных сотен наших танков в автоматическом режиме осуществить непросто, а ручная обработка займет слишком много времени. По этой причине в моде оставлена возможность ручной подгонки клавишами положения камеры.

image

Выводы


Oculus Rift — весьма интересное устройство, которое добавляет массу новых ощущений в игры. Однако, как это часто бывает, создание production-ready-интеграции такого устройства отнюдь не дело пары дней. Если вы решили встроить его поддержку в уже существующую игру (не такую, которая изначально делалась под VR), то вам потребуется:

1. Частичная переделка внутриигрового меню. Даже если вы откажетесь от полной интеграции его в виртуальное пространство (проецирование элементов на игровые объекты, расположение по реальным мировым координатам и т.д.), отображение меню нужно будет корректировать.

2. Сильная, возможно радикальная переделка непосредственно геймплейного UI. Oculus Rift обладает не самым большим разрешением, и если просто взять HUD из игры и повесить его перед глазами в Oculus, то элементы интерфейса будут занимать слишком много места. Вдобавок, будет не покидать ощущение «мух перед глазами». Значит, придется резать UI, что-то выносить на глаза, что-то второстепенное уносить дальше, а это требует от UI реакций на вращения головы. Спроецированный на игровые объекты (кабина, шлем и подобное) боевой UI при этом потенциально займет слишком мало пикселей на экране при отрисовке, и информативности от него не будет никакой.

3. Архитектура игровых камер должна допускать расширяемость. Oculus — это не только устройство вывода картинки на его экраны, но и устройство ввода ориентации головы. Следовательно, эти данные нужно как-то по-человечески «пропихнуть» в игровые камеры. А если нужна возможность озираться по сторонам, то система прицеливания в игре должна быть независимой от ориентации камеры. В нашем случае камера наводчика, например, получена композицией логик снайперского и аркадного режимов. Также разделение логики обзора и логики прицеливания облегчает интеграцию Oculus с уже существующими режимами управления, не заставляя оверрайдить их.

4. И последнее, но столь же важное: Oculus требует создания системы управления, специфичной для него. Реализация, в которой движения окулусом — это то же самое, что движение мышью, вполне может не подойти (этот вариант, пожалуй, сходу хорошо ложится только на авиасимуляторы, где логика поворота головой пилота обычно все равно реализована, а вид из кабины – основной режим обзора).

Если вкратце, то к плюсам Oculus можно отнести:
• достаточную открытость для сотрудничества;
• развитие SDK;
• пиар;
• Джон Кармак (лол).

Минусы:
• отсутствие общих рекомендаций по геймплейной интеграции;
• странность с хроматической аберрацией в 0.4.2;
• сложность восприятия в third-person-играх (особенно если герой танк, а не гуманоид);
• общие проблемы для всех шлемов:

  • фокусировка;
  • разрешение экранов (даже в HD версии (sic!));
  • дискомфорт при длительном использовании (шея + головная боль).

Сам мод можно скачать вот по этой ссылке.