Написание голографического удаленного приложения удаленного взаимодействия с помощью API OpenXR

Если вы не знакомы с голографическим удаленным взаимодействием, ознакомьтесь с нашим обзором.

Важно!

В этом документе описывается создание удаленного приложения для HoloLens 2 и Windows Mixed Reality гарнитур с помощью API OpenXR. Удаленные приложения для HoloLens (1-го поколения) должны использовать пакет NuGet версии 1.x.x. Это означает, что удаленные приложения, написанные для HoloLens 2, несовместимы с HoloLens 1 и наоборот. Документацию по HoloLens 1 можно найти здесь.

Голографические приложения удаленного взаимодействия могут передавать удаленно отрисованное содержимое в HoloLens 2 и Windows Mixed Reality иммерсивные гарнитуры. Вы также можете получить доступ к дополнительным системным ресурсам и интегрировать удаленные иммерсивные представления в существующее программное обеспечение для настольных компьютеров. Удаленное приложение получает поток входных данных из HoloLens 2, отрисовывает содержимое в виртуальном иммерсивном представлении и передает кадры содержимого обратно в HoloLens 2. Подключение осуществляется с помощью стандартной сети Wi-Fi. Голографическое удаленное взаимодействие добавляется в классическое приложение или приложение UWP с помощью пакета NuGet. Требуется дополнительный код, который обрабатывает подключение и отрисовывается в иммерсивном представлении. Обычное удаленное подключение будет иметь низкую задержку в 50 мс. Приложение проигрывателя может сообщать о задержке в режиме реального времени.

Весь код на этой странице и рабочие проекты можно найти в репозитории примеров голографического удаленного взаимодействия GitHub.

Предварительные требования

Хорошей отправной точкой является работающее классическое приложение или приложение UWP на основе OpenXR. Дополнительные сведения см. в статье Начало работы с OpenXR.

Важно!

Любое приложение, использующе голографическое удаленное взаимодействие, должно быть создано для использования многопотокового подразделения. Использование однопотокового подразделения поддерживается, но приведет к неоптимальной производительности и, возможно, заикание во время воспроизведения. При использовании C++/WinRT winrt::init_apartment по умолчанию используется многопоточное подразделение.

Получение пакета NuGet для голографического удаленного взаимодействия

Чтобы добавить пакет NuGet в проект в Visual Studio, необходимо выполнить следующие действия.

  1. Откройте проект в Visual Studio.
  2. Щелкните правой кнопкой мыши узел проекта и выберите Управление пакетами NuGet...
  3. На появиющейся панели выберите Обзор и выполните поиск по запросу "Голографическое удаленное взаимодействие".
  4. Выберите Microsoft.Holographic.Remoting.OpenXr, убедитесь, что выбрана последняя версия 2.x.x , а затем нажмите кнопку Установить.
  5. Если появится диалоговое окно Предварительный просмотр , нажмите кнопку ОК.
  6. Выберите Я принимаю , когда откроется диалоговое окно лицензионного соглашения.
  7. Повторите шаги 3–6 для следующих пакетов NuGet: OpenXR.Headers, OpenXR.Loader.

Примечание

Версия 1.x.x пакета NuGet по-прежнему доступна для разработчиков, которые хотят использовать HoloLens 1. Дополнительные сведения см. в разделе Добавление голографического удаленного взаимодействия (HoloLens (1-го поколения)).

Выбор среды выполнения OpenXR для голографического удаленного взаимодействия

Первым шагом, который необходимо выполнить в удаленном приложении, является выбор среды выполнения OpenXR для голографического удаленного взаимодействия, которая является частью пакета NuGet Microsoft.Holographic.Remoting.OpenXr. Это можно сделать, задав для переменной XR_RUNTIME_JSON среды путь к файлу RemotingXR.json в приложении. Эта переменная среды используется загрузчиком OpenXR, чтобы не использовать системную среду выполнения OpenXR по умолчанию, а для перенаправления в среду выполнения OpenXR для голографического удаленного взаимодействия. При использовании пакета NuGet Microsoft.Holographic.Remoting.OpenXr файл RemotingXR.json автоматически копируется во время компиляции в папку output, выбор среды выполнения OpenXR обычно выглядит следующим образом.

bool EnableRemotingXR() {
    wchar_t executablePath[MAX_PATH];
    if (GetModuleFileNameW(NULL, executablePath, ARRAYSIZE(executablePath)) == 0) {
        return false;
    }
    
    std::filesystem::path filename(executablePath);
    filename = filename.replace_filename("RemotingXR.json");

    if (std::filesystem::exists(filename)) {
        SetEnvironmentVariableW(L"XR_RUNTIME_JSON", filename.c_str());
            return true;
        }

    return false;
}

Создание XrInstance с расширением голографического удаленного взаимодействия

Первые действия, которые следует предпринять типичному приложению OpenXR, — это выбор расширений OpenXR и создание экземпляра XrInstance. Базовая спецификация OpenXR не предоставляет api удаленного взаимодействия. По этой причине в голографическом удаленном взаимодействии представлено собственное расширение OpenXR с именем XR_MSFT_holographic_remoting. Убедитесь, что XR_MSFT_HOLOGRAPHIC_REMOTING_EXTENSION_NAME включен в XrInstanceCreateInfo вызова xrCreateInstance.

Совет

По умолчанию отрисованное содержимое приложения передается только в голографический проигрыватель удаленного взаимодействия, работающий на HoloLens 2 или на гарнитурах Windows Mixed Reality. Чтобы также отобразить отрисованное содержимое на удаленном компьютере, например, через цепочку буферов окна, Голографическое удаленное взаимодействие предоставляет второе расширение OpenXR с именем XR_MSFT_holographic_remoting_frame_mirroring. Убедитесь, что вы также включите это расширение с помощью XR_MSFT_HOLOGRAPHIC_REMOTING_FRAME_MIRRORING_EXTENSION_NAME , если вы хотите использовать эту функцию.

Важно!

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

Подключение к устройству

После того как удаленное приложение создаст экземпляр XrInstance и запросит XrSystemId через xrGetSystem, можно установить подключение к устройству проигрывателя.

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

Среда выполнения OpenXR для голографического удаленного взаимодействия может предоставлять данные для конкретных устройств, такие как конфигурации представлений или режимы наложения среды, только после установки подключения. xrEnumerateViewConfigurations, xrEnumerateViewConfigurationViews, xrGetViewConfigurationProperties, xrEnumerateEnvironmentBlendModesи xrGetSystemProperties предоставляют значения по умолчанию, соответствующие тем, которые обычно получаются при подключении к проигрывателю, работающему на HoloLens 2, до полного подключения. Настоятельно рекомендуется не вызывать эти методы до установки подключения. Предложение используется после успешного создания XrSession и состояния сеанса по крайней мере XR_SESSION_STATE_READY.

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

XrRemotingRemoteContextPropertiesMSFT contextProperties;
contextProperties = XrRemotingRemoteContextPropertiesMSFT{static_cast<XrStructureType>(XR_TYPE_REMOTING_REMOTE_CONTEXT_PROPERTIES_MSFT)};
contextProperties.enableAudio = false;
contextProperties.maxBitrateKbps = 20000;
contextProperties.videoCodec = XR_REMOTING_VIDEO_CODEC_H265_MSFT;
contextProperties.depthBufferStreamResolution = XR_REMOTING_DEPTH_BUFFER_STREAM_RESOLUTION_HALF_MSFT;
xrRemotingSetContextPropertiesMSFT(m_instance.Get(), m_systemId, &contextProperties);

Подключение можно выполнить одним из двух способов.

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

Чтобы установить подключение из удаленного приложения к устройству проигрывателя, вызовите xrRemotingConnectMSFT метод , указав имя узла и порт через структуру XrRemotingConnectInfoMSFT . Порт, используемый голографическим проигрывателем удаленного взаимодействия, — 8265.

XrRemotingConnectInfoMSFT connectInfo{static_cast<XrStructureType>(XR_TYPE_REMOTING_CONNECT_INFO_MSFT)};
connectInfo.remoteHostName = "192.168.x.x";
connectInfo.remotePort = 8265;
connectInfo.secureConnection = false;
xrRemotingConnectMSFT(m_instance.Get(), m_systemId, &connectInfo);

Прослушивание входящих подключений в удаленном приложении можно выполнить, вызвав xrRemotingListenMSFT метод . Порт подтверждения и транспортный порт можно указать с помощью XrRemotingListenInfoMSFT структуры . Порт подтверждения используется для начального подтверждения. Затем данные отправляются через транспортный порт. По умолчанию используются 8265 и 8266 .

XrRemotingListenInfoMSFT listenInfo{static_cast<XrStructureType>(XR_TYPE_REMOTING_LISTEN_INFO_MSFT)};
listenInfo.listenInterface = "0.0.0.0";
listenInfo.handshakeListenPort = 8265;
listenInfo.transportListenPort = 8266;
listenInfo.secureConnection = false;
xrRemotingListenMSFT(m_instance.Get(), m_systemId, &listenInfo);

Состояние подключения должно быть отключено при вызове xrRemotingConnectMSFT или xrRemotingListenMSFT. Состояние подключения можно получить в любой момент после создания экземпляра XrInstance и запроса XrSystemId через xrRemotingGetConnectionStateMSFT.

XrRemotingConnectionStateMSFT connectionState;
xrRemotingGetConnectionStateMSFT(m_instance.Get(), m_systemId, &connectionState, nullptr);

Доступные состояния подключения:

  • XR_REMOTING_CONNECTION_STATE_DISCONNECTED_MSFT
  • XR_REMOTING_CONNECTION_STATE_CONNECTING_MSFT
  • XR_REMOTING_CONNECTION_STATE_CONNECTED_MSFT

Важно!

xrRemotingConnectMSFT Или xrRemotingListenMSFT необходимо вызвать перед попыткой создать XrSession с помощью xrCreateSession. Если вы попытаетесь создать XrSession в состоянии подключения, создание сеанса завершится XR_REMOTING_CONNECTION_STATE_DISCONNECTED_MSFT успешно, но состояние сеанса сразу же перейдет на XR_SESSION_STATE_LOSS_PENDING.

Реализация голографического удаленного xrCreateSession взаимодействия поддерживает ожидание установки подключения. Вы можете вызвать xrRemotingConnectMSFT или xrRemotingListenMSFT сразу после вызова xrCreateSession, который будет блокировать и ждать установки подключения. Время ожидания с xrRemotingConnectMSFT фиксированным значением равно 10 секундам и не ограничено с xrRemotingListenMSFTпомощью . Если подключение может быть установлено в течение этого времени, создание XrSession завершится успешно, а состояние сеанса перейдет на XR_SESSION_STATE_READY. Если подключение не удается установить, создание сеанса также завершается успешно, но сразу же переходит на XR_SESSION_STATE_LOSS_PENDING.

Как правило, состояние подключения связано с состоянием XrSession. Любое изменение состояния подключения также влияет на состояние сеанса. Например, если состояние подключения переключится с XR_REMOTING_CONNECTION_STATE_CONNECTED_MSFTXR_REMOTING_CONNECTION_STATE_DISCONNECTED_MSFT на состояние сеанса, также будет переходить на XR_SESSION_STATE_LOSS_PENDING.

Обработка определенных событий удаленного взаимодействия

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

  1. XR_TYPE_REMOTING_EVENT_DATA_CONNECTED_MSFT: активируется при успешном подключении к устройству.
  2. XR_TYPE_REMOTING_EVENT_DATA_DISCONNECTED_MSFT: активируется, если установленное соединение закрыто или не удается установить соединение.
  3. XR_TYPE_REMOTING_EVENT_DATA_LISTENING_MSFT: при прослушивании входящих подключений запускается.

Эти события помещаются в очередь, и удаленное приложение должно регулярно считывать данные из очереди через xrPollEvent.

auto pollEvent = [&](XrEventDataBuffer& eventData) -> bool {
	eventData.type = XR_TYPE_EVENT_DATA_BUFFER;
	eventData.next = nullptr;
	return CHECK_XRCMD(xrPollEvent(m_instance.Get(), &eventData)) == XR_SUCCESS;
};

XrEventDataBuffer eventData{};
while (pollEvent(eventData)) {
	switch (eventData.type) {
	
	...
	
	case XR_TYPE_REMOTING_EVENT_DATA_LISTENING_MSFT: {
		DEBUG_PRINT("Holographic Remoting: Listening on port %d",
					reinterpret_cast<const XrRemotingEventDataListeningMSFT*>(&eventData)->listeningPort);
		break;
	}
	case XR_TYPE_REMOTING_EVENT_DATA_CONNECTED_MSFT: {
		DEBUG_PRINT("Holographic Remoting: Connected.");
		break;
	}
	case XR_TYPE_REMOTING_EVENT_DATA_DISCONNECTED_MSFT: {
		DEBUG_PRINT("Holographic Remoting: Disconnected - Reason: %d",
					reinterpret_cast<const XrRemotingEventDataDisconnectedMSFT*>(&eventData)->disconnectReason);
		break;
	}
}

Локальный просмотр потокового содержимого

Для отображения того же содержимого в удаленном приложении, которое отправляется на устройство, XR_MSFT_holographic_remoting_frame_mirroring можно использовать расширение . С помощью этого расширения можно отправить текстуру в xrEndFrame с помощью XrRemotingFrameMirrorImageInfoMSFT , которая не связана с XrFrameEndInfo, как показано ниже.

XrFrameEndInfo frameEndInfo{XR_TYPE_FRAME_END_INFO};
...

XrRemotingFrameMirrorImageD3D11MSFT mirrorImageD3D11{
    static_cast<XrStructureType>(XR_TYPE_REMOTING_FRAME_MIRROR_IMAGE_D3D11_MSFT)};
mirrorImageD3D11.texture = m_window->GetNextSwapchainTexture();

XrRemotingFrameMirrorImageInfoMSFT mirrorImageEndInfo{
    static_cast<XrStructureType>(XR_TYPE_REMOTING_FRAME_MIRROR_IMAGE_INFO_MSFT)};
mirrorImageEndInfo.image = reinterpret_cast<const XrRemotingFrameMirrorImageBaseHeaderMSFT*>(&mirrorImageD3D11);

frameEndInfo.next = &mirrorImageEndInfo;

xrEndFrame(m_session.Get(), &frameEndInfo);

m_window->PresentSwapchain();

В приведенном выше примере используется текстура цепочки буферов DX11 и отображается окно сразу после вызова xrEndFrame. Использование не ограничивается текстурами цепочки буферов. Кроме того, дополнительная синхронизация GPU не требуется. Дополнительные сведения об использовании и ограничениях проверка спецификацию расширения. Если удаленное приложение использует DX12, используйте XrRemotingFrameMirrorImageD3D12MSFT вместо XrRemotingFrameMirrorImageD3D11MSFT.

Необязательно. Пользовательские каналы данных

Начиная с версии 2.5.0 пользовательские каналы данных можно использовать с API OpenXR для отправки пользовательских данных через уже установленное удаленное подключение. Дополнительные сведения см. в статье Пользовательские каналы данных с помощью API OpenXR.

Необязательно: речь

Начиная с версии 2.6.0, расширение позволяет удаленному приложению реагировать на голосовые команды, XR_MSFT_holographic_remoting_speech обнаруженные приложением проигрывателя с помощью API OpenXR.

[! ВАЖНО. Подробную спецификацию можно найти в репозитории примеров голографического удаленного взаимодействия на GitHub.

Чтобы инициализировать распознаватель речи в приложении проигрывателя, удаленное приложение может вызвать .xrInitializeRemotingSpeechMSFT Этот вызов передает параметры инициализации речи, которые состоят из языка, словаря фраз и содержимого файла грамматики, в приложение проигрывателя.

Примечание

До версии 2.6.1 распознаватель речи должен быть инициализирован только один раз на .XrSession

Если создание распознавателя речи выполнено успешно, как указано в событии XR_TYPE_EVENT_DATA_REMOTING_SPEECH_RECOGNIZER_STATE_CHANGED_MSFT , удаленное приложение получит уведомление о создании результата распознавания речи в приложении проигрывателя. Структура XrEventDataRemotingSpeechRecognizerStateChangedMSFT событий помещается в очередь событий при изменении состояния распознавателя речи на стороне игрока.

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

Примечание

XrRemotingSpeechRecognitionConfidenceMSFT— это прямое сопоставление перечисления SpeechRecognitionConfidence, возвращаемого с результатом распознавания речи API распознавания речи Windows.

Необязательно: синхронизация системы координат

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

См. также: