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

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

Important

이 문서에서는 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++ 홀로그램 프로젝트 템플릿 이 좋은 시작점입니다.

Important

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

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

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

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

Important

NuGet 패키지 내부에는 build\native\include\HolographicAppRemoting\Microsoft.Holographic.AppRemoting.idl Holographic Remoting에서 노출하는 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();

Warning

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

다음으로 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()
}

Important

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 는 현재 프레임의 포커스 지점을 덮어쓸 수 있습니다.

  • 대체 포커스 지점을 지정하려면 먼저 HolographicCameraRenderingParameters::SetFocusPointPlayerContext::BlitRemoteFrame를 호출합니다.
  • 원격 포커스 지점을 덮어쓰려면 다음 후 PlayerContext::BlitRemoteFrameHolographicCameraRenderingParameters::SetFocusPoint를 호출합니다.

성공하면 .를 BlitRemoteFrame 반환합니다 BlitResult::Success_Color. 그렇지 않으면 실패 이유를 반환합니다.

  • BlitResult::Failed_NoRemoteFrameAvailable: 사용할 수 있는 원격 프레임이 없으므로 실패했습니다.
  • BlitResult::Failed_NoCamera: 카메라가 없으므로 실패했습니다.
  • BlitResult::Failed_RemoteFrameTooOld: 원격 프레임이 너무 오래되어 실패했습니다(PlayerContext::BlitRemoteFrameTimeout 속성 참조).

Important

버전 2.1.0 부터는 사용자 지정 플레이어가 홀로그램 원격을 통해 깊이 다시 보호를 사용할 수 있습니다.

BlitResult 은 다음과 같은 조건에서 반환 BlitResult::Success_Color_Depth 할 수도 있습니다.

  • 원격 앱은 HolographicCameraRenderingParameters.CommitDirect3D11DepthBuffer를 통해 깊이 버퍼를 커밋했습니다.
  • 사용자 지정 플레이어 앱은 호출 BlitRemoteFrame하기 전에 유효한 깊이 버퍼를 바인딩했습니다.

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

프로젝션 변환 모드

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

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

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

선택 사항: BlitRemoteFrameTimeout 설정

Important

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 .

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

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

선택 사항: 오버 렌더링

홀로그램 원격은 렌더링된 이미지가 디스플레이에 표시될 때 사용자의 머리가 있는 위치를 예측합니다. 그러나 이 예측은 근사치입니다. 따라서 원격 앱의 예측 뷰포트와 플레이어 앱의 이후 실제 뷰포트는 다를 수 있습니다. 더 강한 편차(예: 예측할 수 없는 동작으로 인해)는 보기 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 부터 좌표계 동기화를 사용하여 플레이어와 원격 앱 간에 공간 데이터를 정렬할 수 있습니다. 자세한 내용은 Holographic Remoting 개요를 사용하여 좌표계 동기화를 참조하세요.

참고 항목