Escrevendo uma app personalizada do jogador holográfico remoting

Se é novo no Remoting Holográfico, pode querer ler a nossa visão geral.

Importante

Este documento descreve a criação de uma aplicação personalizada do jogador para HoloLens 2. Os jogadores personalizados escritos para HoloLens 2 não são compatíveis com aplicações remotas escritas para HoloLens 1. Isto implica que ambas as aplicações devem utilizar a versão 2.x.x.do pacote NuGet .

Ao criar uma aplicação personalizada do leitor holográfico, pode criar uma aplicação personalizada capaz de exibir vistas imersivas de uma máquina remota no seu HoloLens 2. Todos os códigos desta página e projetos de trabalho podem ser encontrados no repositório de amostras holográficas de github.

Um leitor holográfico de remoting permite que a sua aplicação exiba conteúdo holográfico renderizado num pc de secretária ou dispositivo UWP como o Xbox One com acesso a mais recursos do sistema. Uma aplicação holográfica do jogador remoting transmite dados de entrada para uma aplicação remota Holographic Remoting e recebe de volta uma visão imersiva como fluxo de vídeo e áudio. A ligação é feita com Wi-Fi padrão. Para criar uma aplicação para jogadores, utilize um pacote NuGet para adicionar o Remoting Holográfico à sua aplicação UWP. Em seguida, escreva código para manusear a ligação e para exibir uma visão imersiva.

Pré-requisitos

Um bom ponto de partida é uma aplicação UWP baseada em DirectX que já tem como alvo a API Windows Mixed Reality. Para mais detalhes consulte a visão geral do desenvolvimento do DirectX. Se você não tem uma aplicação existente e quer começar do zero o modelo de projeto holográfico C++ é um bom ponto de partida.

Importante

Qualquer aplicação que utilize o Remoting Holográfico deve ser da autoria de utilizar um apartamento com vários fios. O uso de um apartamento com fio único é suportado, mas levará a um desempenho sub-ideal e possivelmente gagueja durante a reprodução. Ao utilizar o winrt C++/WinRT::init_apartment um apartamento com vários fios é o padrão.

Obtenha o pacote Holographic Remoting NuGet

São necessários os seguintes passos para adicionar o pacote NuGet a um projeto em Visual Studio.

  1. Abra o projeto no Visual Studio.
  2. Clique com o botão direito no nó do projeto e selecione Gerir pacotes NuGet...
  3. No painel que aparece, selecione Procurar por "Remoing Holográfico".
  4. Selecione Microsoft.Holographic.Remoting, certifique-se de escolher a versão mais recente 2.x.x e selecione Instalar.
  5. Se aparecer o diálogo de pré-visualização, selecione OK.
  6. Selecione Aceito quando o diálogo do contrato de licença aparecer.

Importante

O build\native\include\HolographicAppRemoting\Microsoft.Holographic.AppRemoting.idl pacote NuGet contém documentação detalhada para a API exposta por Holographic Remoting.

Modificar o Pacote.appxmanifest da aplicação

Para dar conhecimento da aplicação ao Microsoft.Holographic.AppRemoting.dll adicionado pelo pacote NuGet, devem ser tomadas as seguintes medidas no projeto:

  1. No Solution Explorer, clique à direita no ficheiro Package.appxmanifest e selecione Abrir Com...
  2. Selecione XML (Texto) Editor e selecione OK
  3. Adicione as seguintes linhas ao ficheiro e guarde
  </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>

Criar o contexto do jogador

Como primeiro passo, a aplicação deve criar um contexto de jogador.

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

Aviso

O remoing holográfico funciona substituindo o tempo de execução Windows Mixed Reality que faz parte do Windows por um tempo de funcionamento específico de remoagem. Isto é feito durante a criação do contexto do jogador. Por essa razão, qualquer chamada em qualquer Windows Mixed Reality API antes de criar o contexto do jogador pode resultar em comportamento inesperado. A abordagem recomendada é criar o contexto do jogador o mais cedo possível antes da interação com qualquer API de Realidade Mista. Nunca misture objetos criados ou recuperados através de qualquer Windows Mixed Reality API antes da chamada PlayerContext::Create com objetos criados ou recuperados posteriormente.

Em seguida, o HolographicSpace pode ser criado, chamando HolographicSpace.CreateForCoreWindow.

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

Ligação para a aplicação remota

Uma vez que a aplicação do jogador esteja pronta para renderizar conteúdo, pode ser estabelecida uma ligação à aplicação remota.

A ligação pode ser estabelecida de uma das seguintes formas:

  1. A aplicação do jogador em execução no HoloLens 2 liga-se à aplicação remota.
  2. A aplicação remota liga-se à aplicação do jogador em execução no HoloLens 2.

Para ligar da aplicação do jogador à aplicação remota, ligue para o Connect método no contexto do jogador especificando o nome e a porta do anfitrião. A porta padrão é 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()
}

Importante

Tal como qualquer API C++/WinRT Connect pode lançar um winrt::hresult_error que precisa de ser manuseado.

Ouvir as ligações recebidas na aplicação do jogador pode ser feito ligando para o Listen método. Tanto o porto de aperto de mão como o porto de transporte podem ser especificados durante esta chamada. A porta de aperto de mão é utilizada para o aperto de mão inicial. Os dados são então enviados para o porto de transporte. Por defeito, são utilizados os números 8265 e 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()
}

O PlayerContext expõe três eventos para monitorizar o estado da ligação

  1. OnConnected: Desencadeado quando uma ligação à aplicação remota foi estabelecida com sucesso.
m_onConnectedEventToken = m_playerContext.OnConnected([]() 
{
    // Handle connection successfully established
});
  1. OnDis ligado: Desencadeado se uma ligação estabelecida for terminada ou se não for estabelecida uma ligação.
m_onDisconnectedEventToken = m_playerContext.OnDisconnected([](ConnectionFailureReason failureReason)
{
    switch (failureReason)
    {
        // Handle connection failed or terminated.
        // See ConnectionFailureReason for possible reasons.
    }
}

Nota

Os valores possíveis ConnectionFailureReason estão documentados no Microsoft.Holographic.AppRemoting.idlConnectionFailureReason

  1. OnListening: Ao ouvir as ligações recebidas começa.
m_onListeningEventToken = m_playerContext.OnListening([]()
{
    // Handle start listening for incoming connections
});

Além disso, o estado de ligação pode ser consultado usando a ConnectionState propriedade no contexto do jogador.

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

Mostrar o quadro prestado remotamente

Para exibir o conteúdo prestado remotamente, ligue PlayerContext::BlitRemoteFrame enquanto presta um PlayerContext::BlitRemoteFrame.

BlitRemoteFrame requer que o tampão traseiro para o atual HolographicFrame esteja ligado como alvo de renderização. O tampão traseiro pode ser recebido a partir dos Parametros HolográficosCameraRendering através da propriedade Direct3D11BackBuffer.

Quando chamado, BlitRemoteFrame copia o quadro mais recente recebido da aplicação remota para o BackBuffer do HolographicFrame. Adicionalmente, o conjunto de pontos de focagem é definido, se a aplicação remota tiver especificado um ponto de focagem durante a renderização do quadro remoto.

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

Nota

PlayerContext::BlitRemoteFrame potencialmente substitui o ponto de foco para o quadro atual.

No sucesso, BlitRemoteFrameBlitResult::Success_Color regressa. Caso contrário, devolve a razão de falha:

  • BlitResult::Failed_NoRemoteFrameAvailable: Falhou porque não existe uma moldura remota disponível.
  • BlitResult::Failed_NoCamera: Falhou porque não há câmara presente.
  • BlitResult::Failed_RemoteFrameTooOld: Falha porque a moldura remota é demasiado antiga (ver playerContext:::BlitRemoteFrameTimeout).

Importante

Começando pela versão 2.1.0 é possível com um jogador personalizado usar a reprojecção de profundidade através do Remoting Holográfico.

BlitResult pode igualmente regressar BlitResult::Success_Color_Depth nas seguintes condições:

Se estas condições forem satisfeitas, BlitRemoteFrame irá cortar a profundidade remota no tampão de profundidade local atualmente ligado. Em seguida, pode renderizar conteúdo local adicional, que terá uma intersecção de profundidade com o conteúdo remoto renderizado. Além disso, pode comprometer o tampão de profundidade local através de HolographicCameraRenderingParameters.CommitDirect3D11DepthBuffer no seu leitor personalizado para ter reprojecção de profundidade para conteúdo renderizado remoto e local.

Modo de transformação de projeção

Um problema, que surge ao utilizar a reprojecção de profundidade através do Remoting Holográfico é que o conteúdo remoto pode ser renderizado com uma transformação de projeção diferente do conteúdo local diretamente renderizado pela sua aplicação personalizada do jogador. Um caso de uso comum é especificar valores diferentes para o plano próximo e distante (via HolographicCamera::SetNearPlaneDistance e HolographicCamera:::SetFarPlaneDistance)no lado do jogador e no lado remoto. Neste caso, não é claro se a transformação de projeção no lado do jogador deve refletir as distâncias remotas de avião próximo/distante ou as locais.

A partir da versão 2.1.0 pode controlar o modo de transformação de projeção via . Os valores suportados são:

  • Local - Local devolve uma transformação de projeção, que reflete as distâncias de plano próximo/distante definidas pela sua aplicação personalizada de jogador na HolographicCamera.
  • Remote - A transformação da projeção reflete as distâncias de plano próximo/distante especificadas pela aplicação remota.
  • Merged - Distâncias de avião próximas/distantes da sua aplicação remota e da sua aplicação personalizada para o jogador são fundidas. Por defeito, isto é feito tomando o mínimo das distâncias próximas do avião e o máximo das distâncias de avião distantes. No caso de o lado remoto ou local ser invertido, < digamos, muito perto, as distâncias remotas perto/distantes do avião são invertidas.

Opcional: Definir BlitRemoteFrameTimeout

Importante

PlayerContext::BlitRemoteFrameTimeout é suportado a partir da versão PlayerContext::BlitRemoteFrameTimeout.

A PlayerContext::BlitRemoteFrameTimeout propriedade especifica a quantidade de tempo que um quadro remoto é reutilizado se não for recebida nenhuma nova moldura remota.

Uma caixa de utilização comum é permitir que o tempo limite do BlitRemoteFrame apresente um ecrã em branco se não forem recebidos novos quadros durante um determinado período de tempo. Quando ativado, o tipo de devolução do BlitRemoteFrame método também pode ser utilizado para mudar para um conteúdo de retorno prestado localmente.

Para ativar o tempo limite, desa um valor de propriedade igual ou superior a 100 ms. Para desativar o tempo limite, desloe a propriedade a uma duração zero. Se o tempo limite estiver ativado e não for recebida nenhuma moldura remota durante a duração definida, o BlitRemoteFrame falhará e regressará Failed_RemoteFrameTooOld até que seja recebido um novo quadro remoto.

using namespace std::chrono_literals;

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

Opcional: Obtenha estatísticas sobre o último quadro remoto

Para diagnosticar problemas de desempenho ou de rede, as estatísticas sobre o último quadro remoto podem ser recuperadas através da PlayerContext::LastFrameStatistics propriedade. As estatísticas são atualizadas durante a chamada para HolographicFrame::P resentUsingPrerentPrediction.

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

Para mais informações, consulte a PlayerFrameStatistics documentação no Microsoft.Holographic.AppRemoting.idlPlayerFrameStatistics

Opcional: Canais de dados personalizados

Os canais de dados personalizados podem ser utilizados para enviar dados do utilizador sobre a ligação de remoização já estabelecida. Para mais informações, consulte os canais de dados personalizados.

Opcional: Over-Rendering

O Remoting Holográfico prevê onde estará a cabeça do utilizador no momento em que as imagens renderizadas aparecerem nos ecrãs. No entanto, esta previsão é uma aproximação. Por isso, o viewport previsto na aplicação remota e o viewport posterior na aplicação do jogador podem diferir. Desvios mais fortes (por exemplo, devido a movimentos imprevisíveis) podem causar regiões negras nas fronteiras do frustum de visualização. A partir da versão 2.6.0 pode utilizar Over-Rendering para reduzir as regiões negras e melhorar a qualidade visual, aumentando artificialmente o viewport para além do frustum de visualização.

Over-Rendering pode ser ativado através de PlayerContext::ConfigureOverRendering .

O OverRenderingConfig especia um aumento de tamanho fracional para o porto de visualização real, de modo que o viewport previsto se torna maior e menos corte ocorre. Com um tamanho de vista aumentado, a densidade de pixels diminui, pelo que o OverRenderingConfig permite-lhe aumentar a resolução também. Se o aumento do viewport for igual à resolução, a densidade do pixel permanece a mesma. OverRenderingConfig é definido como:

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).
};

Opcional: Coordenar a Sincronização do Sistema

A partir da versão 2.7.0 pode ser utilizada sincronização do sistema de coordenadas 2.7.0 para alinhar dados espaciais entre o jogador e a aplicação remota. Para obter mais informações, consulte a Sincronização do Sistema de Coordenadas com a Visão Geral de Remoting Holográfica.

Consulte também