사용자 지정 홀로그램 원격 플레이어 앱 작성

Holographic Remoting을 사용하는 경우 개요를 읽을 수 있습니다.

중요

이 문서에서는 HoloLens 2 위한 사용자 지정 플레이어 애플리케이션의 생성에 대해 설명합니다. HoloLens 2 위해 작성된 사용자 지정 플레이어는 HoloLens 1용으로 작성된 원격 애플리케이션과 호환되지 않습니다. 즉, 두 애플리케이션 모두 NuGet 패키지 버전 2.x.x를 사용해야 합니다.

사용자 지정 홀로그램 원격 플레이어 앱을 만들면 HoloLens 2 원격 머신에서 몰입형 보기를 표시할 수 있는 사용자 지정 애플리케이션을 만들 수 있습니다. 이 페이지의 모든 코드와 작업 중인 프로젝트는 Holographic Remoting 샘플 github 리포지토리에서 찾을 수 있습니다.

홀로그램 원격 플레이어를 사용하면 앱이 더 많은 시스템 리소스에 액세스할 수 있는 Xbox One과 같은 데스크톱 PC 또는 UWP 장치에서 렌더링된 홀로그램 콘텐츠를 표시할 수 있습니다. 홀로그램 원격 플레이어 앱은 입력 데이터를 홀로그램 원격 원격 애플리케이션으로 스트리밍하고 몰입형 보기를 비디오 및 오디오 스트림으로 다시 받습니다. 연결은 표준 Wi-Fi를 사용하여 이루어집니다. 플레이어 앱을 만들려면 NuGet 패키지를 사용하여 UWP 앱에 홀로그램 원격을 추가합니다. 그런 다음, 연결을 처리하고 몰입형 보기를 표시하는 코드를 작성합니다.

필수 구성 요소

좋은 시작점은 이미 Windows Mixed Reality API를 대상으로 하는 작동하는 DirectX 기반 UWP 앱입니다. 자세한 내용은 DirectX 개발 개요를 참조하세요. 기존 앱이 없고 처음부터 시작하려는 경우 C++ 홀로그램 프로젝트 템플릿 이 좋은 시작점입니다.

중요

홀로그램 원격을 사용하는 모든 앱은 다중 스레드 아파트를 사용하도록 작성해야 합니다. 단일 스레드 아파트의 사용은 지원되지만 최적이 아닌 성능과 재생 중에 더듬거리는 것으로 이어질 수 있습니다. C++/WinRT winrt::init_apartment 사용하는 경우 다중 스레드 아파트가 기본값입니다.

홀로그램 원격 NuGet 패키지 가져오기

Visual Studio의 프로젝트에 NuGet 패키지를 추가하려면 다음 단계가 필요합니다.

  1. Visual Studio에서 프로젝트를 엽니다.
  2. 프로젝트 노드를 마우스 오른쪽 단추로 클릭하고 NuGet 패키지 관리...를 선택합니다.
  3. 표시되는 패널에서 찾아보기를 선택한 다음, "홀로그램 원격"을 검색합니다.
  4. Microsoft.Holographic.Remoting을 선택하고 최신 2.x.x 버전을 선택하고 설치를 선택합니다.
  5. 미리 보기 대화 상자가 나타나면 확인을 선택합니다.
  6. 사용권 계약 대화 상자가 나타나면 동의 를 선택합니다.

중요

NuGet 패키지 내부에는 build\native\include\HolographicAppRemoting\Microsoft.Holographic.AppRemoting.idl 홀로그램 원격에서 노출하는 API에 대한 자세한 설명서가 포함되어 있습니다.

애플리케이션의 Package.appxmanifest 수정

애플리케이션이 NuGet 패키지에서 추가한 Microsoft.Holographic.AppRemoting.dll 인식하도록 하려면 프로젝트에서 다음 단계를 수행해야 합니다.

  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 Mixed Reality 런타임 사이에 중간 계층을 삽입합니다. 이 작업은 플레이어 컨텍스트를 만드는 동안 수행됩니다. 따라서 플레이어 컨텍스트를 만들기 전에 Windows Mixed Reality API를 호출하면 예기치 않은 동작이 발생할 수 있습니다. 권장되는 방법은 Mixed Reality API와 상호 작용하기 전에 가능한 한 빨리 플레이어 컨텍스트를 만드는 것입니다. 호출 PlayerContext::Create 하기 전에 Windows Mixed Reality API를 통해 생성되거나 검색된 개체를 나중에 만들거나 검색된 개체와 혼합하지 마세요.

다음으로 HolographicSpace.CreateForCoreWindow를 호출하여 HolographicSpace를 만들 수 있습니다.

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()
}

중요

C++/WinRT API Connect 와 마찬가지로 처리해야 하는 winrt::hresult_error throw할 수 있습니다.

메서드를 호출 Listen 하여 플레이어 앱에서 들어오는 연결을 수신 대기할 수 있습니다. 이 호출 중에 핸드셰이크 포트와 전송 포트를 모두 지정할 수 있습니다. 핸드셰이크 포트는 초기 핸드셰이크에 사용됩니다. 그런 다음 전송 포트를 통해 데이터가 전송됩니다. 기본적으로 포트 번호 82658266 이 사용됩니다.

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();

원격으로 렌더링된 프레임 표시

원격으로 렌더링된 콘텐츠를 표시하려면 HolographicFrame을 렌더링하는 동안 를 호출 PlayerContext::BlitRemoteFrame 합니다.

BlitRemoteFrame 에서는 현재 HolographicFrame의 백 버퍼가 렌더링 대상으로 바인딩되어야 합니다. Direct3D11BackBuffer 속성을 통해 HolographicCameraRenderingParameters에서 백 버퍼를 받을 수 있습니다.

호출 BlitRemoteFrame 되면 원격 애플리케이션에서 받은 최신 프레임을 HolographicFrame의 BackBuffer로 복사합니다. 또한 원격 애플리케이션이 원격 프레임을 렌더링하는 동안 포커스 포인트를 지정한 경우 포커스 포인트 집합이 설정됩니다.

// 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 부터는 사용자 지정 플레이어가 홀로그램 원격을 통해 깊이 다시 프로젝션을 사용할 수 있습니다.

BlitResult 는 다음 조건에서 를 반환 BlitResult::Success_Color_Depth 할 수도 있습니다.

이러한 조건이 충족 BlitRemoteFrame 되면 원격 깊이를 현재 바인딩된 로컬 깊이 버퍼에 블릿합니다. 그런 다음, 원격 렌더링된 콘텐츠와 깊이가 교차하는 추가 로컬 콘텐츠를 렌더링할 수 있습니다. 또한 사용자 지정 플레이어의 HolographicCameraRenderingParameters.CommitDirect3D11DepthBuffer 를 통해 로컬 깊이 버퍼를 커밋하여 원격 및 로컬 렌더링된 콘텐츠에 대한 깊이 다시 프로젝션을 수행할 수 있습니다.

프로젝션 변환 모드

홀로그램 원격을 통해 깊이 다시 프로젝션을 사용할 때 나타나는 한 가지 문제는 원격 콘텐츠를 사용자 지정 플레이어 앱에서 직접 렌더링하는 로컬 콘텐츠와 다른 프로젝션 변환으로 렌더링할 수 있다는 것입니다. 일반적인 사용 사례는 플레이어 쪽과 원격 쪽에서 근거리 및 원거리 평면( HolographicCamera::SetNearPlaneDistanceHolographicCamera::SetFarPlaneDistance를 통해)에 대해 서로 다른 값을 지정하는 것입니다. 이 경우 플레이어 쪽의 프로젝션 변환이 원격 근거리/원거리 평면 거리 또는 로컬 거리를 반영해야 하는지는 명확하지 않습니다.

버전 2.1.0 부터 를 통해 PlayerContext::ProjectionTransformConfig프로젝션 변환 모드를 제어할 수 있습니다. 지원되는 값은 다음과 같습니다.

  • Local - HolographicCameraPose::P rojectionTransform 은 HolographicCamera에서 사용자 지정 플레이어 앱이 설정한 근거리/먼 평면 거리를 반영하는 프로젝션 변환을 반환합니다.
  • Remote - 프로젝션 변환은 원격 앱에서 지정한 근거리/먼 평면 거리를 반영합니다.
  • Merged - 원격 앱과 사용자 지정 플레이어 앱의 근거리/먼 평면 거리가 병합됩니다. 기본적으로 이 작업은 가까운 평면 거리와 최대 원거리 평면 거리를 사용하여 수행됩니다. 원격 또는 로컬 쪽이 반전되는 경우 멀리 < 떨어진 원격 평면 거리가 대칭 이동됩니다.

선택 사항: BlitRemoteFrameTimeout 설정

중요

PlayerContext::BlitRemoteFrameTimeout 는 버전 2.0.9부터 지원됩니다.

속성은 PlayerContext::BlitRemoteFrameTimeout 새 원격 프레임이 수신되지 않은 경우 원격 프레임이 다시 사용되는 시간을 지정합니다.

일반적인 사용 사례는 특정 시간 동안 새 프레임이 수신되지 않은 경우 BlitRemoteFrame 시간 제한을 사용하여 빈 화면을 표시할 수 있도록 하는 것입니다. 사용하도록 설정된 경우 메서드의 반환 형식을 BlitRemoteFrame 사용하여 로컬로 렌더링된 대체 콘텐츠로 전환할 수도 있습니다.

시간 제한을 사용하도록 설정하려면 속성 값을 100ms보다 크거나 같은 기간으로 설정합니다. 시간 제한을 사용하지 않도록 설정하려면 속성을 0 기간으로 설정합니다. 시간 제한을 사용하도록 설정하고 설정된 기간 동안 원격 프레임을 수신하지 않으면 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 참조하세요.

선택 사항: 사용자 지정 데이터 채널

사용자 지정 데이터 채널을 사용하여 이미 설정된 원격 연결을 통해 사용자 데이터를 보낼 수 있습니다. 자세한 내용은 사용자 지정 데이터 채널을 참조하세요.

선택 사항: Over-Rendering

홀로그램 원격은 렌더링된 이미지가 디스플레이에 표시될 때 사용자의 머리가 어디에 있을지 예측합니다. 그러나 이 예측은 근사치입니다. 따라서 원격 앱의 예측 뷰포트와 플레이어 앱의 이후 실제 뷰포트는 다를 수 있습니다. 더 강한 편차(예: 예측할 수 없는 움직임으로 인해)는 보기 frustum의 테두리에서 검은 색 영역을 일으킬 수 있습니다. 버전 2.6.0 부터 Over-Rendering 사용하여 검은색 영역을 줄이고 보기 절두체를 넘어 인위적으로 뷰포트를 늘려 시각적 품질을 향상시킬 수 있습니다.

Over-Rendering 을 통해 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 부터 좌표계 동기화를 사용하여 플레이어와 원격 앱 간에 공간 데이터를 정렬할 수 있습니다. 자세한 내용은 홀로그램 원격 개요를 사용하여 좌표계 동기화를 참조하세요.

참고 항목