Настройка XR

Введение в систему XR в Godot

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

Каждая поддерживаемая XR-платформа реализована как XRInterface. Список поддерживаемых платформ можно найти на странице возможностей here. Поддерживаемые интерфейсы регистрируются в XRServer, и их можно запросить с помощью метода find_interface на XRServer. Когда нужный интерфейс найден, его можно инициализировать, вызвав для него initialize.

Предупреждение

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

Из-за особых требований к выводу в XR, особенно для наголовных устройств, которые подают разные изображения на каждый глаз, XRServer в Godot переопределяет различные функции системы рендеринга. Для автономных устройств это означает, что финальный вывод обрабатывается XRInterface, а обычная система вывода Godot отключается. Для настольных XR-устройств, работающих как второй экран, можно выделить отдельный Viewport для обработки вывода XR, оставляя главное окно Godot доступным для отображения альтернативного контента.

Примечание

Примечание: только один интерфейс может отвечать за обработку вывода на XR-устройство; он называется основным интерфейсом и по умолчанию инициализируется первым. Поэтому в настоящее время Godot поддерживает только реализации с одной гарнитурой. Существует возможность (хотя она используется всё реже) иметь вторичный интерфейс, например, для добавления отслеживания к устройству, которое в противном случае имело бы только 3DOF.

Существует три специальных типа узлов для XR, которые встречаются почти во всех XR-приложениях:

  • XROrigin3D, по сути, представляет собой центральную точку вашего игрового пространства. Это слишком упрощенное утверждение, но мы рассмотрим его подробнее позже. Все объекты, отслеживаемые XR-платформой в физическом пространстве, позиционируются относительно этой точки.

  • XRCamera3D представляет собой (стерео) камеру, которая используется при рендеринге вывода для XR-устройства. Позиционирование этого узла контролируется XR-системой и автоматически обновляется на основе информации отслеживания, предоставляемой XR-платформой.

  • XRController3D представляет собой контроллер, используемый игроком; обычно их два, по одному в каждой руке. Эти узлы предоставляют доступ к различным состояниям этих контроллеров и посылают сигналы, когда игрок нажимает на них кнопки. Позиционирование этого узла контролируется XR-системой и автоматически обновляется на основе информации отслеживания, предоставляемой XR-платформой.

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

Какой рендерер использовать

В Godot есть 3 варианта отрисовщика для проектов: Compatibility, Mobile и Forward+. Текущая рекомендация — использовать отрисовщик Mobile для любых VR-проектов для настольных ПК и отрисовщик Compatibility для любых проектов, запускаемых на автономной гарнитуре, такой как Meta Quest 3. XR-проекты будут запускаться с отрисовщиком Forward+, но на данный момент он не очень хорошо оптимизирован для XR по сравнению с двумя другими.

OpenXR

OpenXR is a new industry standard that allows different XR platforms to present themselves through a standardized API to XR applications. This standard is an open standard maintained by the Khronos Group and thus aligns very well with Godot's interests.

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

Это также означает, что OpenXR должен быть включен при запуске Godot для корректной настройки. Проверьте настройку Enabled в настройках вашего проекта в разделе XR > OpenXR.

../../_images/openxr_enabled.webp

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

Вам также нужно будет зайти в XR > Shaders в настройках проекта и установить флажок Enabled, чтобы включить их. После этого нажмите кнопку Save & Restart.

../../_images/xr_shaders.webp

Предупреждение

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

Подготовка сцены XR

Каждому XR-приложению требуется как минимум узел XROrigin3D и узел XRCamera3D. В большинстве случаев также будет два узла XRController3D: один для левой руки и один для правой. Имейте в виду, что узлы камеры и контроллеров должны быть дочерними по отношению к узлу origin. Добавьте эти узлы в новую сцену и переименуйте узлы контроллеров в LeftHand и RightHand; ваша сцена должна выглядеть примерно так:

../../_images/xr_basic_scene.webp

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

../../_images/xr_left_hand.webp

И правая рука:

../../_images/xr_right_hand.webp

Сейчас все эти узлы находятся на полу и будут правильно позиционированы во время выполнения. Для упрощения разработки может быть полезно переместить камеру вверх, установив её координату y на 1.7, а также переместить узлы контроллера в координаты -0.5, 1.0, -0.5 и 0.5, 1.0, -0.5 для левой и правой руки соответственно.

Далее нам нужно добавить скрипт к нашему корневому узлу. Добавьте в него следующий код:

extends Node3D

var xr_interface: XRInterface

func _ready():
    xr_interface = XRServer.find_interface("OpenXR")
    if xr_interface and xr_interface.is_initialized():
        print("OpenXR initialized successfully")

        # Turn off v-sync!
        DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED)

        # Change our main viewport to output to the HMD
        get_viewport().use_xr = true
    else:
        print("OpenXR not initialized, please check if your headset is connected")

В этом фрагменте кода предполагается, что мы используем OpenXR. Если вы хотите использовать любой другой интерфейс, вы можете изменить вызов find_interface.

Предупреждение

Как видно из фрагмента кода выше, мы отключаем вертикальную синхронизацию. При использовании OpenXR результаты рендеринга выводятся на шлем виртуальной реальности, который часто требует частоты обновления 90 Гц или выше. Если ваш монитор имеет частоту обновления 60 Гц и вертикальная синхронизация включена, вывод будет ограничен 60 кадрами в секунду.

Интерфейсы XR, такие как OpenXR, выполняют собственную синхронизацию.

Также обратите внимание, что по умолчанию физический движок работает на частоте 60 Гц, что может привести к прерывистой физике. Вам следует установить более высокое значение параметра Engine.physics_ticks_per_second.

Если вы запустите проект на этом этапе, всё будет работать, но вы окажетесь в тёмном мире. Поэтому, чтобы завершить нашу отправную точку, добавьте в сцену узлы DirectionalLight3D и WorldEnvironment. Вы также можете добавить экземпляр сетки в качестве дочернего элемента к каждому узлу контроллера, чтобы временно визуализировать их. Убедитесь, что вы настроили небо в своей среде мира.

Теперь запустите свой проект, вы должны парить где-то в космосе и иметь возможность осмотреться.

Примечание

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

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