Grafik bağlama
Azure Remote Rendering'i özel bir uygulamada kullanabilmek için uygulamanın işleme işlem hattıyla tümleştirilmesi gerekir. Bu tümleştirme grafik bağlamasının sorumluluğundadır.
Grafik bağlaması ayarlandıktan sonra, işlenen görüntüyü etkileyen çeşitli işlevlere erişim verir. Bu işlevler iki kategoriye ayrılabilir: her zaman kullanılabilen genel işlevler ve yalnızca seçilen Microsoft.Azure.RemoteRendering.GraphicsApiType
için uygun olan belirli işlevler.
Unity'de grafik bağlama
Unity'de bağlamanın tamamı içine RemoteManagerUnity.InitializeManager
geçirilen yapısı tarafından RemoteUnityClientInit
işlenir. Grafik modunu ayarlamak için alanın GraphicsApiType
seçilen bağlamaya ayarlanması gerekir. Alan, bir XRDevice olup olmadığına bağlı olarak otomatik olarak doldurulur. Davranış, aşağıdaki davranışlarla el ile geçersiz kılınabilir:
- HoloLens 2: Etkin Unity XR eklentisine bağlı olarak OpenXR veya Windows Karma Gerçeklik grafik bağlaması kullanılır.
- Düz UWP masaüstü uygulaması: Simülasyon her zaman kullanılır.
- Unity düzenleyicisi: Bir WMR VR başlığı bağlı olmadığı sürece simülasyon her zaman kullanılır ve bu durumda ARR, uygulamanın ARR ile ilgili olmayan bölümlerinde hata ayıklamaya izin verecek şekilde devre dışı bırakılır. Ayrıca bkz. holografik uzaktan iletişim.
Unity için tek ilgili bölüm temel bağlamaya erişmektir, aşağıdaki diğer tüm bölümler atlanabilir.
Özel uygulamalarda grafik bağlama kurulumu
Grafik bağlaması seçmek için aşağıdaki iki adımı uygulayın: İlk olarak, program başlatıldığında grafik bağlamasının statik olarak başlatılması gerekir:
RemoteRenderingInitialization managerInit = new RemoteRenderingInitialization();
managerInit.GraphicsApi = GraphicsApiType.OpenXrD3D11;
managerInit.ConnectionType = ConnectionType.General;
managerInit.Right = ///...
RemoteManagerStatic.StartupRemoteRendering(managerInit);
RemoteRenderingInitialization managerInit;
managerInit.GraphicsApi = GraphicsApiType::OpenXrD3D11;
managerInit.ConnectionType = ConnectionType::General;
managerInit.Right = ///...
StartupRemoteRendering(managerInit); // static function in namespace Microsoft::Azure::RemoteRendering
Yukarıdaki çağrı, diğer Uzaktan İşleme API'lerine erişilmeden önce çağrılmalıdır.
Benzer şekilde, diğer tüm Uzaktan İşleme nesneleri zaten yok edildikten sonra ilgili de-init işlevi RemoteManagerStatic.ShutdownRemoteRendering();
çağrılmalıdır.
Herhangi bir holografik API çağrılmadan önce WMR'nin StartupRemoteRendering
de çağrılması gerekir. OpenXR için aynı durum OpenXR ile ilgili tüm API'ler için de geçerlidir.
Grafik bağlamaya erişme
İstemci ayarlandıktan sonra, temel grafik bağlamaya RenderingSession.GraphicsBinding
getter ile erişilebilir. Örneğin, son kare istatistikleri aşağıdaki gibi alınabilir:
RenderingSession currentSession = ...;
if (currentSession.GraphicsBinding != null)
{
FrameStatistics frameStatistics;
if (currentSession.GraphicsBinding.GetLastFrameStatistics(out frameStatistics) == Result.Success)
{
...
}
}
ApiHandle<RenderingSession> currentSession = ...;
if (ApiHandle<GraphicsBinding> binding = currentSession->GetGraphicsBinding())
{
FrameStatistics frameStatistics;
if (binding->GetLastFrameStatistics(&frameStatistics) == Result::Success)
{
...
}
}
Grafik API'leri
Şu anda seçilebilen üç grafik API'si vardır: OpenXrD3D11
ve WmrD3D11
SimD3D11
. Dördüncü bir tane Headless
var ancak istemci tarafında henüz desteklenmiyor.
OpenXR
GraphicsApiType.OpenXrD3D11
HoloLens 2'de çalıştırılacak varsayılan bağlamadır. Bağlamayı GraphicsBindingOpenXrD3d11
oluşturur. Bu modda Azure Uzaktan İşleme, kendisini OpenXR çalışma zamanıyla tümleştirmek için bir OpenXR API katmanı oluşturur.
Türetilmiş grafik bağlamalarına erişmek için tabanın GraphicsBinding
yayınlanması gerekir.
OpenXR bağlamasını kullanmak için yapılması gereken üç şey vardır:
Özel OpenXR katman json'larını paketleme
OpenXR ile Uzaktan İşleme'yi kullanmak için özel OpenXR API katmanının etkinleştirilmesi gerekir. Bu işlem, önceki bölümde bahsedilen çağrılarak StartupRemoteRendering
yapılır. Ancak, önkoşul XrApiLayer_msft_holographic_remoting.json
olarak yüklenebilmesi için uygulamayla birlikte paketlenmesi gerekir. Bir projeye "Microsoft.Azure.RemoteRendering.Cpp" NuGet paketi eklendiğinde bu işlem otomatik olarak yapılır.
Kullanılan XR Alanını Uzaktan İşlemeye Bildirme
Bu, uzak ve yerel olarak işlenmiş içeriği hizalamak için gereklidir.
RenderingSession currentSession = ...;
ulong space = ...; // XrSpace cast to ulong
GraphicsBindingOpenXrD3d11 openXrBinding = (currentSession.GraphicsBinding as GraphicsBindingOpenXrD3d11);
if (openXrBinding.UpdateAppSpace(space) == Result.Success)
{
...
}
ApiHandle<RenderingSession> currentSession = ...;
XrSpace space = ...;
ApiHandle<GraphicsBindingOpenXrD3d11> openXrBinding = currentSession->GetGraphicsBinding().as<GraphicsBindingOpenXrD3d11>();
#ifdef _M_ARM64
if (openXrBinding->UpdateAppSpace(reinterpret_cast<uint64_t>(space)) == Result::Success)
#else
if (openXrBinding->UpdateAppSpace(space) == Result::Success)
#endif
{
...
}
Yukarıdaki XrSpace
, API'deki koordinatların ifade edildiği dünya uzay koordinat sistemini tanımlayan uygulama tarafından kullanılan yerdir.
Uzak görüntüyü işleme (OpenXR)
Her çerçevenin başında uzak çerçevenin arka arabellekte işlenmesi gerekir. Bu, her iki gözün renk ve derinlik bilgilerini şu anda bağlı olan işleme hedefine dolduracak olan çağrısıyla BlitRemoteFrame
yapılır. Bu nedenle, tam geri arabelleği bir işleme hedefi olarak bağladıktan sonra bunu yapmak önemlidir.
Uyarı
Uzak görüntü arka bölmeye bölündükten sonra, yerel içerik tek geçişli stereo işleme tekniği kullanılarak (örneğin, SV_RenderTargetArrayIndex kullanılarak) işlenmelidir. Her gözü ayrı bir geçişte işleme gibi diğer stereo işleme tekniklerinin kullanılması, önemli performans düşüşlerine veya grafik yapıtlara neden olabilir ve bundan kaçınılmalıdır.
RenderingSession currentSession = ...;
GraphicsBindingOpenXrD3d11 openXrBinding = (currentSession.GraphicsBinding as GraphicsBindingOpenXrD3d11);
openXrBinding.BlitRemoteFrame();
ApiHandle<RenderingSession> currentSession = ...;
ApiHandle<GraphicsBindingOpenXrD3d11> openXrBinding = currentSession->GetGraphicsBinding().as<GraphicsBindingOpenXrD3d11>();
openXrBinding->BlitRemoteFrame();
Windows Mixed Reality
GraphicsApiType.WmrD3D11
, HoloLens 2'de çalıştırmak için daha önce kullanılan grafik bağlamasıdır. Bağlamayı GraphicsBindingWmrD3d11
oluşturur. Bu modda Azure Uzaktan İşleme doğrudan holografik API'lere bağlanıyor.
Türetilmiş grafik bağlamalarına erişmek için tabanın GraphicsBinding
yayınlanması gerekir.
WMR bağlamasını kullanmak için yapılması gereken iki şey vardır:
Kullanılan koordinat sistemini Uzaktan İşleme'ye bildirme
Bu, uzak ve yerel olarak işlenmiş içeriği hizalamak için gereklidir.
RenderingSession currentSession = ...;
IntPtr ptr = ...; // native pointer to ISpatialCoordinateSystem
GraphicsBindingWmrD3d11 wmrBinding = (currentSession.GraphicsBinding as GraphicsBindingWmrD3d11);
if (wmrBinding.UpdateUserCoordinateSystem(ptr) == Result.Success)
{
...
}
ApiHandle<RenderingSession> currentSession = ...;
void* ptr = ...; // native pointer to ISpatialCoordinateSystem
ApiHandle<GraphicsBindingWmrD3d11> wmrBinding = currentSession->GetGraphicsBinding().as<GraphicsBindingWmrD3d11>();
if (wmrBinding->UpdateUserCoordinateSystem(ptr) == Result::Success)
{
...
}
Burada yukarıdaki ptr
, API'deki koordinatların ifade edildiği dünya uzay koordinat sistemini tanımlayan yerel ABI::Windows::Perception::Spatial::ISpatialCoordinateSystem
bir nesnenin işaretçisi olmalıdır.
Uzak görüntüyü işleme (WMR)
Yukarıdaki OpenXR örneğinde dikkat edilmesi gerekenler burada da geçerlidir. API çağrıları şöyle görünür:
RenderingSession currentSession = ...;
GraphicsBindingWmrD3d11 wmrBinding = (currentSession.GraphicsBinding as GraphicsBindingWmrD3d11);
wmrBinding.BlitRemoteFrame();
ApiHandle<RenderingSession> currentSession = ...;
ApiHandle<GraphicsBindingWmrD3d11> wmrBinding = currentSession->GetGraphicsBinding().as<GraphicsBindingWmrD3d11>();
wmrBinding->BlitRemoteFrame();
Simülasyon
GraphicsApiType.SimD3D11
benzetimi bağlamadır ve seçilirse grafik bağlamasını GraphicsBindingSimD3d11
oluşturur. Bu arabirim, örneğin bir masaüstü uygulamasında baş hareketini simüle etmek için kullanılır ve monoskopik bir görüntü işler.
Simülasyon bağlamasını uygulamak için, yerel kamera ile uzak çerçeve arasındaki farkı kamera sayfasında açıklandığı gibi anlamak önemlidir.
İki kamera gerekir:
- Yerel kamera: Bu kamera, uygulama mantığı tarafından yönetilen geçerli kamera konumunu temsil eder.
- Ara kamera: Bu kamera, sunucu tarafından gönderilen geçerli Uzak Çerçeve ile eşleşir. Çerçeve isteyen istemci ile gelmesi arasında bir süre gecikme olduğundan, Uzak Çerçeve her zaman yerel kameranın hareketinin biraz gerisindedir.
Buradaki temel yaklaşım, hem uzak görüntünün hem de yerel içeriğin proxy kamera kullanılarak ekran dışı bir hedefe işlenmesidir. Ara sunucu görüntüsü daha sonra yerel kamera alanına yeniden oluşturulur ve bu da geç aşama yeniden oluşturmada daha ayrıntılı bir şekilde açıklanır.
GraphicsApiType.SimD3D11
ayrıca aşağıdaki kurulum çağrısı sırasında etkinleştirilmesi gereken stereoskopik işlemeyi InitSimulation
de destekler. Kurulum biraz daha karmaşıktır ve aşağıdaki gibi çalışır:
Ara sunucu işleme hedefi oluşturma
Uzak ve yerel içeriğin işlev tarafından sağlanan ara sunucu kamera verileri kullanılarak 'proxy' olarak adlandırılan ekran dışı bir renk / derinlik işleme hedefine GraphicsBindingSimD3d11.Update
işlenmesi gerekir.
Ara sunucu, arka arabelleğin çözünürlüğüyle eşleşmeli ve DXGI_FORMAT_R8G8B8A8_UNORM veya DXGI_FORMAT_B8G8R8A8_UNORM biçiminde olmalıdır. Stereoskopik işleme söz konusu olduğunda hem renk ara sunucusu dokusu hem de derinlik kullanılırsa derinlik ara sunucusu dokusunun bir yerine iki dizi katmanı olması gerekir. Oturum hazır olduğunda, GraphicsBindingSimD3d11.InitSimulation
oturuma bağlanmadan önce çağrılmaları gerekir:
RenderingSession currentSession = ...;
IntPtr d3dDevice = ...; // native pointer to ID3D11Device
IntPtr color = ...; // native pointer to ID3D11Texture2D
IntPtr depth = ...; // native pointer to ID3D11Texture2D
float refreshRate = 60.0f; // Monitor refresh rate up to 60hz.
bool flipBlitRemoteFrameTextureVertically = false;
bool flipReprojectTextureVertically = false;
bool stereoscopicRendering = false;
GraphicsBindingSimD3d11 simBinding = (currentSession.GraphicsBinding as GraphicsBindingSimD3d11);
simBinding.InitSimulation(d3dDevice, depth, color, refreshRate, flipBlitRemoteFrameTextureVertically, flipReprojectTextureVertically, stereoscopicRendering);
ApiHandle<RenderingSession> currentSession = ...;
void* d3dDevice = ...; // native pointer to ID3D11Device
void* color = ...; // native pointer to ID3D11Texture2D
void* depth = ...; // native pointer to ID3D11Texture2D
float refreshRate = 60.0f; // Monitor refresh rate up to 60hz.
bool flipBlitRemoteFrameTextureVertically = false;
bool flipReprojectTextureVertically = false;
bool stereoscopicRendering = false;
ApiHandle<GraphicsBindingSimD3d11> simBinding = currentSession->GetGraphicsBinding().as<GraphicsBindingSimD3d11>();
simBinding->InitSimulation(d3dDevice, depth, color, refreshRate, flipBlitRemoteFrameTextureVertically, flipReprojectTextureVertically, stereoscopicRendering);
Init işlevinin yerel d3d cihazının yanı sıra ara sunucu işleme hedefinin renk ve derinlik dokusuna yönelik işaretçilerle sağlanması gerekir. Başlatıldıktan RenderingSession.ConnectAsync
sonra ve Disconnect
birden çok kez çağrılabilir, ancak farklı bir oturuma geçildiğinde, GraphicsBindingSimD3d11.DeinitSimulation
başka bir oturumda çağrılmadan önce GraphicsBindingSimD3d11.InitSimulation
eski oturumda çağrılmaları gerekir.
İşleme döngüsü güncelleştirmesi
İşleme döngüsü güncelleştirmesi birden çok adımdan oluşur:
- Herhangi bir işleme gerçekleşmeden önce her kare,
GraphicsBindingSimD3d11.Update
işlenecek sunucuya gönderilen geçerli kamera dönüşümüyle çağrılır. Aynı zamanda, proxy işleme hedefine işlemek için proxy kameraya döndürülen ara sunucu dönüşümü uygulanmalıdır. Döndürülen proxy güncelleştirmesiSimulationUpdate.frameId
null ise, henüz uzak veri yoktur. Bu durumda, ara sunucu işleme hedefinde işlemek yerine, tüm yerel içerik geçerli kamera verileri kullanılarak doğrudan arka arabelleğe işlenmelidir ve sonraki iki adım atlanır. - Uygulama artık ara sunucu işleme hedefini bağlamalı ve çağırmalıdır
GraphicsBindingSimD3d11.BlitRemoteFrameToProxy
. Bu, uzak renk ve derinlik bilgilerini ara sunucu işleme hedefine doldurur. Artık tüm yerel içerikler ara sunucu kamera dönüşümü kullanılarak ara sunucuya işlenebilir. - Ardından, arka arabelleğin bir işleme hedefi olarak bağlanması ve
GraphicsBindingSimD3d11.ReprojectProxy
bu noktada arka arabelleğin sunulabilmesi için çağrılması gerekir.
RenderingSession currentSession = ...;
GraphicsBindingSimD3d11 simBinding = (currentSession.GraphicsBinding as GraphicsBindingSimD3d11);
SimulationUpdateParameters updateParameters = new SimulationUpdateParameters();
// Fill out camera data with current camera data
// (see "Simulation Update structures" section below)
...
SimulationUpdateResult updateResult = new SimulationUpdateResult();
simBinding.Update(updateParameters, out updateResult);
// Is the frame data valid?
if (updateResult.FrameId != 0)
{
// Bind proxy render target
simBinding.BlitRemoteFrameToProxy();
// Use proxy camera data to render local content
...
// Bind back buffer
simBinding.ReprojectProxy();
}
else
{
// Bind back buffer
// Use current camera data to render local content
...
}
ApiHandle<RenderingSession> currentSession;
ApiHandle<GraphicsBindingSimD3d11> simBinding = currentSession->GetGraphicsBinding().as<GraphicsBindingSimD3d11>();
SimulationUpdateParameters updateParameters;
// Fill out camera data with current camera data
// (see "Simulation Update structures" section below)
...
SimulationUpdateResult updateResult;
simBinding->Update(updateParameters, &updateResult);
// Is the frame data valid?
if (updateResult.FrameId != 0)
{
// Bind proxy render target
simBinding->BlitRemoteFrameToProxy();
// Use proxy camera data to render local content
...
// Bind back buffer
simBinding->ReprojectProxy();
}
else
{
// Bind back buffer
// Use current camera data to render local content
...
}
Benzetim Güncelleştirme yapıları
Önceki bölümde yer alan İşleme döngüsü güncelleştirmesi , yerel kameraya karşılık gelen bir dizi kamera parametresini girmenizi gerektirir ve kullanılabilir bir sonraki karenin kamerasına karşılık gelen bir dizi kamera parametresi döndürür. Bu iki küme sırasıyla ve SimulationUpdateResult
yapılarında SimulationUpdateParameters
yakalanır:
public struct SimulationUpdateParameters
{
public int FrameId;
public StereoMatrix4x4 ViewTransform;
public StereoCameraFov FieldOfView;
};
public struct SimulationUpdateResult
{
public int FrameId;
public float NearPlaneDistance;
public float FarPlaneDistance;
public StereoMatrix4x4 ViewTransform;
public StereoCameraFov FieldOfView;
};
Yapı üyeleri şu anlama sahiptir:
Stereo-çiftler ViewTransform
ve FieldOfView
stereoskopik işlemenin etkinleştirilmesi durumunda her iki göz kamerası değerinin ayarlanmasına izin verir. Aksi takdirde, Right
üyeler yoksayılır. Gördüğünüz gibi yalnızca kameranın dönüşümü düz 4x4 dönüştürme matrisleri olarak geçirilirken projeksiyon matrisleri belirtilmez. Gerçek matrisler Azure Uzaktan İşleme tarafından, belirtilen görünüm alanları ve Kamera Ayarlar API'sinde geçerli yakın düzlem ve uzak düzlem kümesi kullanılarak dahili olarak hesaplanır.
Çalışma zamanı sırasında Kamera Ayarlar yakın düzlemi ve uzak düzlemi istediğiniz gibi değiştirebileceğinizden ve hizmet bu ayarları zaman uyumsuz olarak uyguladığından, her SimulationUpdateResult ilgili çerçevenin işlenmesi sırasında kullanılan belirli bir yakın düzlemi ve uzak düzlemi de taşır. Bu düzlem değerlerini kullanarak yerel nesneleri işlemek için projeksiyon matrislerinizi uzak çerçeve işlemeyle eşleşecek şekilde uyarlayabilirsiniz.
Son olarak, Simülasyon Güncelleştirmesi çağrısı OpenXR kuralında görüntüleme alanını gerektirirken, standartlaştırma ve algoritmik güvenlik nedenleriyle, aşağıdaki yapı popülasyon örneklerinde gösterilen dönüştürme işlevlerini kullanabilirsiniz:
public SimulationUpdateParameters CreateSimulationUpdateParameters(int frameId, Matrix4x4 viewTransform, Matrix4x4 projectionMatrix)
{
SimulationUpdateParameters parameters = default;
parameters.FrameId = frameId;
parameters.ViewTransform.Left = viewTransform;
if (parameters.FieldOfView.Left.FromProjectionMatrix(projectionMatrix) != Result.Success)
{
// Invalid projection matrix
throw new ArgumentException("Invalid projection settings");
}
return parameters;
}
public void GetCameraSettingsFromSimulationUpdateResult(SimulationUpdateResult result, out Matrix4x4 projectionMatrix, out Matrix4x4 viewTransform, out int frameId)
{
projectionMatrix = default;
viewTransform = default;
frameId = 0;
if (result.FrameId == 0)
{
// Invalid frame data
return;
}
// Use the screenspace depth convention you expect for your projection matrix locally
if (result.FieldOfView.Left.ToProjectionMatrix(result.NearPlaneDistance, result.FarPlaneDistance, DepthConvention.ZeroToOne, out projectionMatrix) != Result.Success)
{
// Invalid field-of-view
return;
}
viewTransform = result.ViewTransform.Left;
frameId = result.FrameId;
}
SimulationUpdateParameters CreateSimulationUpdateParameters(uint32_t frameId, Matrix4x4 viewTransform, Matrix4x4 projectionMatrix)
{
SimulationUpdateParameters parameters;
parameters.FrameId = frameId;
parameters.ViewTransform.Left = viewTransform;
if (FovFromProjectionMatrix(projectionMatrix, parameters.FieldOfView.Left) != Result::Success)
{
// Invalid projection matrix
return {};
}
return parameters;
}
void GetCameraSettingsFromSimulationUpdateResult(const SimulationUpdateResult& result, Matrix4x4& projectionMatrix, Matrix4x4& viewTransform, uint32_t& frameId)
{
if (result.FrameId == 0)
{
// Invalid frame data
return;
}
// Use the screenspace depth convention you expect for your projection matrix locally
if (FovToProjectionMatrix(result.FieldOfView.Left, result.NearPlaneDistance, result.FarPlaneDistance, DepthConvention::ZeroToOne, projectionMatrix) != Result::Success)
{
// Invalid field-of-view
return;
}
viewTransform = result.ViewTransform.Left;
frameId = result.FrameId;
}
Bu dönüştürme işlevleri, yerel işleme gereksinimlerinize bağlı olarak görünüm alanı belirtimi ile düz 4x4 perspektif projeksiyon matrisi arasında hızlı geçişe olanak sağlar. Bu dönüştürme işlevleri doğrulama mantığı içerir ve giriş projeksiyon matrislerinin veya giriş görünüm alanlarının geçersiz olması durumunda geçerli bir sonuç ayarlamadan hatalar döndürür.
API belgeleri
- C# RemoteManagerStatic.StartupRemoteRendering()
- C# GraphicsBinding sınıfı
- C# GraphicsBindingWmrD3d11 sınıfı
- C# GraphicsBindingSimD3d11 sınıfı
- C++ RemoteRenderingInitialization yapısı
- C++ GraphicsBinding sınıfı
- C++ GraphicsBindingWmrD3d11 sınıfı
- C++ GraphicsBindingSimD3d11 sınıfı