Поделиться через


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

Если вы не знакомы с Holographic Remoting, вы можете ознакомиться с нашим обзором.

Внимание

В этом документе описывается создание пользовательского приложения проигрывателя для HoloLens 2. Пользовательские игроки, написанные для HoloLens 2, несовместимы с удаленными приложениями, написанными для HoloLens 1. Это означает, что оба приложения должны использовать пакет NuGet версии 2.x.x.

Создав пользовательское приложение проигрывателя holographic Remoting, вы можете создать пользовательское приложение, которое может отображать иммерсивные представления на удаленном компьютере на устройстве HoloLens 2. Весь код на этой странице и рабочих проектах можно найти в репозитории Github для holographic Remoting.

Проигрыватель голографического удаленного взаимодействия позволяет приложению отображать голографическое содержимое , отображаемое на настольном компьютере или устройстве UWP, например Xbox One с доступом к дополнительным системным ресурсам. Приложение проигрывателя Голографического удаленного взаимодействия передает входные данные в удаленное приложение Holographic Remoting и получает иммерсивное представление в виде видео и аудиопотока. Подключение выполняется с помощью стандартного Wi-Fi. Чтобы создать приложение проигрывателя, используйте пакет NuGet для добавления Holographic Remoting в приложение UWP. Затем напишите код для обработки соединения и отображения иммерсивного представления.

Необходимые компоненты

Хорошая отправная точка — это рабочее приложение UWP на основе DirectX, которое уже предназначено для API windows Смешанная реальность. Дополнительные сведения см. в обзоре разработки DirectX. Если у вас нет существующего приложения и вы хотите начать с нуля шаблон голографического проекта C++ является хорошей отправной точкой.

Внимание

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

Получение пакета NuGet для holographic Remoting

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

  1. Откройте проект в Visual Studio.
  2. Щелкните правой кнопкой мыши узел проекта и выберите пункт "Управление пакетами NuGet...
  3. На появившемся панели нажмите кнопку "Обзор" , а затем найдите "Holographic Remoting".
  4. Выберите Microsoft.Holographic.Remoting, убедитесь, что выбрана последняя версия 2.x.x и выберите "Установить".
  5. Если появится диалоговое окно предварительного просмотра , нажмите кнопку "ОК".
  6. Нажмите кнопку "Принять" , когда появится диалоговое окно лицензионного соглашения.

Внимание

Внутри build\native\include\HolographicAppRemoting\Microsoft.Holographic.AppRemoting.idl пакета NuGet содержится подробная документация по API, предоставляемому Holographic Remoting.

Изменение package.appxmanifest приложения

Чтобы приложение знало о Microsoft.Holographic.AppRemoting.dll, добавленном пакетом NuGet, необходимо выполнить следующие действия в проекте:

  1. В Обозреватель решений щелкните правой кнопкой мыши файл Package.appxmanifest и выберите "Открыть с...
  2. Выберите редактор XML (текст) и нажмите кнопку "ОК"
  3. Добавьте следующие строки в файл и сохраните
  </Capabilities>

  <!--Add lines below -->
  <Extensions>
    <Extension Category="windows.activatableClass.inProcessServer">
      <InProcessServer>
        <Path>Microsoft.Holographic.AppRemoting.dll</Path>
        <ActivatableClass ActivatableClassId="Microsoft.Holographic.AppRemoting.PlayerContext" ThreadingModel="both" />
      </InProcessServer>
    </Extension>
  </Extensions>
  <!--Add lines above -->

</Package>

Создание контекста проигрывателя

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

// class declaration:

#include <winrt/Microsoft.Holographic.AppRemoting.h>

...

private:
// PlayerContext used to connect with a Holographic Remoting remote app and display remotely rendered frames
winrt::Microsoft::Holographic::AppRemoting::PlayerContext m_playerContext = nullptr;
// class implementation:

// Create the player context
// IMPORTANT: This must be done before creating the HolographicSpace (or any other call to the Holographic API).
m_playerContext = winrt::Microsoft::Holographic::AppRemoting::PlayerContext::Create();

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

Пользовательский проигрыватель внедряет промежуточный уровень между приложением проигрывателя и средой выполнения Windows Смешанная реальность, поставляемой с Windows. Это делается во время создания контекста проигрывателя. По этой причине любой вызов в любом API Windows Смешанная реальность перед созданием контекста проигрывателя может привести к неожиданному поведению. Рекомендуемый подход — создать контекст проигрывателя как можно раньше, прежде чем взаимодействовать с любым api Смешанная реальность. Никогда не смешайте объекты, созданные или полученные через любой API Windows Смешанная реальность до вызова PlayerContext::Create с объектами, созданными или извлеченными после этого.

Далее можно создать HolographicSpace, вызвав HolographicSpace.CreateForCoreWindow.

m_holographicSpace = winrt::Windows::Graphics::Holographic::HolographicSpace::CreateForCoreWindow(window);

Подключение к удаленному приложению

После готовности приложения проигрывателя к просмотру содержимого можно установить подключение к удаленному приложению.

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

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

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

try
{
    m_playerContext.Connect(m_hostname, m_port);
}
catch(winrt::hresult_error& e)
{
    // Failed to connect. Get an error details via e.code() and e.message()
}

Внимание

Как и в случае с любым API Connect C++/WinRT, может вызвать winrt::hresult_error, который необходимо обрабатывать.

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

try
{
    m_playerContext.Listen(L"0.0.0.0", m_port, m_port + 1);
}
catch(winrt::hresult_error& e)
{
    // Failed to listen. Get an error details via e.code() and e.message()
}

Предоставляет PlayerContext три события для мониторинга состояния подключения.

  1. OnConnected: активируется при успешном установке подключения к удаленному приложению.
m_onConnectedEventToken = m_playerContext.OnConnected([]() 
{
    // Handle connection successfully established
});
  1. OnDisconnected: активируется, если установленное соединение завершается или не удалось установить подключение.
m_onDisconnectedEventToken = m_playerContext.OnDisconnected([](ConnectionFailureReason failureReason)
{
    switch (failureReason)
    {
        // Handle connection failed or terminated.
        // See ConnectionFailureReason for possible reasons.
    }
}

Примечание.

Возможные ConnectionFailureReason значения документируются в Microsoft.Holographic.AppRemoting.idl файле.

  1. OnListening: при прослушивании входящих подключений начинается.
m_onListeningEventToken = m_playerContext.OnListening([]()
{
    // Handle start listening for incoming connections
});

Кроме того, состояние подключения можно запрашивать с помощью ConnectionState свойства в контексте проигрывателя.

winrt::Microsoft::Holographic::AppRemoting::ConnectionState state = m_playerContext.ConnectionState();

Отображение удаленно отрисованного кадра

Чтобы отобразить удаленно отрисованное содержимое, вызовите PlayerContext::BlitRemoteFrame при отрисовке HolographicFrame.

BlitRemoteFrame требует, чтобы задний буфер для текущего Голографического кадра был привязан к целевому объекту отрисовки. Обратный буфер можно получить от HolographicCameraRenderingParameters через свойство Direct3D11BackBuffer .

При вызове BlitRemoteFrame копирует последний полученный кадр из удаленного приложения в BackBuffer HolographicFrame. Кроме того, задан набор точек фокуса, если удаленное приложение указало точку фокуса во время отрисовки удаленного кадра.

// Blit the remote frame into the backbuffer for the HolographicFrame.
winrt::Microsoft::Holographic::AppRemoting::BlitResult result = m_playerContext.BlitRemoteFrame();

Примечание.

PlayerContext::BlitRemoteFrame потенциально перезаписывает точку фокуса для текущего кадра.

При успешном выполнении BlitRemoteFrame возвращается BlitResult::Success_Color. В противном случае возвращается причина сбоя:

  • BlitResult::Failed_NoRemoteFrameAvailable: не удалось, так как удаленный кадр недоступен.
  • BlitResult::Failed_NoCamera: Не удалось, потому что камера отсутствует.
  • BlitResult::Failed_RemoteFrameTooOld: не удалось, так как удаленный кадр слишком старый (см. свойство PlayerContext::BlitRemoteFrameTimeout).

Внимание

Начиная с версии 2.1.0 , можно использовать пользовательский проигрыватель для использования глубины перепроектирования через Holographic Remoting.

BlitResult также может возвращаться BlitResult::Success_Color_Depth в следующих условиях:

  • Удаленное приложение зафиксировало буфер глубины через HolographicCameraRenderingParameters.CommitDirect3D11DepthBuffer.
  • Пользовательское приложение проигрывателя привязывает допустимый буфер глубины перед вызовом BlitRemoteFrame.

Если эти условия выполнены, BlitRemoteFrame будет перерезать удаленную глубину в буфер локальной глубины, привязанный в данный момент. Затем можно отобразить дополнительное локальное содержимое, которое будет иметь пересечение глубины с удаленным отрисованным содержимым. Кроме того, вы можете зафиксировать локальный буфер глубины с помощью HolographicCameraRenderingParameters.CommitDirect3D1DepthBuffer в пользовательском проигрывателе для удаленного и локального отрисованного содержимого.

Режим преобразования проекции

Одна из проблем, которая возникает при использовании повторной подготовки глубины через Holographic Remoting, заключается в том, что удаленное содержимое может быть отрисовано с помощью преобразования проекции, отличного от локального содержимого, отрисованного пользовательским приложением проигрывателя. Распространенный вариант использования заключается в указании различных значений для близкого и далекого плоскости (через HolographicCamera::SetNearPlaneDistance и HolographicCamera::SetFarPlaneDistance) на стороне игрока и удаленной стороне. В этом случае не ясно, если преобразование проекции на стороне игрока должно отражать удаленные расстояния близкого или далекого плоскости или локальные.

Начиная с версии 2.1.0 можно управлять режимом преобразования проекции с помощью PlayerContext::ProjectionTransformConfig. Поддерживаются значения:

  • Local - HolographicCameraPose::P rojectionTransform возвращает преобразование проекции, которое отражает расстояния близкого или далекого плоскости, заданные пользовательским приложением проигрывателя в HolographicCamera.
  • Remote — Преобразование проекции отражает расстояние близкого или далекого плоскости, указанное удаленным приложением.
  • Merged — Расстояние между удаленным приложением и пользовательским приложением проигрывателя объединяются. По умолчанию это делается, принимая минимальное расстояние близкого самолета и максимальное расстояние от далекой плоскости. В случае, если удаленные или локальные стороны перевернуты, скажем, далеко < близко, удаленные расстояния вблизи или далеко от плоскости перевернуты.

Необязательный: Set BlitRemoteFrameTimeout

Внимание

PlayerContext::BlitRemoteFrameTimeout поддерживается начиная с версии 2.0.9.

Свойство PlayerContext::BlitRemoteFrameTimeout указывает время повторного использования удаленного кадра, если новый удаленный кадр не получен.

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

Чтобы включить время ожидания, задайте для свойства значение длительности, равное или больше 100 мс. Чтобы отключить время ожидания, задайте для свойства значение нулевой длительности. Если время ожидания включено, а удаленный кадр не получен в течение заданной длительности, BlitRemoteFrame завершится ошибкой и возвратится Failed_RemoteFrameTooOld до получения нового удаленного кадра.

using namespace std::chrono_literals;

// Set the BlitRemoteFrame timeout to 0.5s
m_playerContext.BlitRemoteFrameTimeout(500ms);

Необязательно. Получение статистики о последнем удаленном кадре

Чтобы диагностировать проблемы с производительностью или сетью, статистику о последнем удаленном кадре можно получить через PlayerContext::LastFrameStatistics свойство. Статистика обновляется во время вызова HolographicFrame::P resentUsingCurrentPrediction.

// Get statistics for the last presented frame.
winrt::Microsoft::Holographic::AppRemoting::PlayerFrameStatistics statistics = m_playerContext.LastFrameStatistics();

Дополнительные сведения см PlayerFrameStatistics . в документации в Microsoft.Holographic.AppRemoting.idl файле.

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

Пользовательские каналы данных можно использовать для отправки пользовательских данных через уже установленное подключение к удаленному взаимодействию. Дополнительные сведения см . в разделе "Пользовательские каналы данных".

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

Голографическое удаленное взаимодействие прогнозирует, где голова пользователя будет находиться во время отображения отрисованных изображений на дисплеях. Однако это приближение прогноза. Таким образом, прогнозируемый порт просмотра в удаленном приложении и более поздний фактический вид в приложении проигрывателя может отличаться. Более сильные отклонения (например, из-за непредсказуемого движения) могут привести к черным регионам на границах просмотра frustum. Начиная с версии 2.6.0 вы можете использовать перерисовку для уменьшения черных регионов и повышения качества визуального элемента, искусственно увеличивая окно просмотра за пределами визуального элемента frustum.

Перерисовка может быть включена с помощью PlayerContext::ConfigureOverRendering.

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

struct OverRenderingConfig
{
    float HorizontalViewportIncrease; // The fractional horizontal viewport increase. (e.g. 10% -> 0.1).
    float VerticalViewportIncrease; // The fractional vertical viewport increase. (e.g. 10% -> 0.1).
                
    float HorizontalResolutionIncrease; // The fractional horizontal resolution increase. (e.g. 10% -> 0.1).
    float VerticalResolutionIncrease; // The fractional vertical resolution increase. (e.g. 10% -> 0.1).
};

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

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

См. также