Delen via


Vertraagde fase van het project

LSR (Late Stage Reprojection) is een hardwarefunctie waarmee hologrammen worden gestabiliseerd wanneer de gebruiker wordt verplaatst.

Statische modellen behouden hun positie naar verwachting visueel wanneer u er omheen navigeert. Als ze instabiel lijken te zijn, kan dit gedrag wijzen op LSR-problemen. Houd er rekening mee dat extra dynamische transformaties, zoals animaties of explosieweergaven, dit gedrag kunnen maskeren.

U kunt kiezen uit twee verschillende LSR-modi, namelijk Planar LSR of Depth LSR. Beide LSR-modi verbeteren de stabiliteit van hologrammen, hoewel ze hun afzonderlijke beperkingen hebben. Begin met het uitproberen van Depth LSR, omdat het waarschijnlijk betere resultaten geeft in de meeste gevallen.

De LSR-modus instellen

Welke van de LSR-modi wordt gebruikt, wordt bepaald door of de clienttoepassing een dieptebuffer verzendt. Als de dieptebuffer wordt verzonden, wordt anders diepte-LSR en Planar LSR gebruikt.

In de volgende alinea's wordt uitgelegd hoe het indienen van de dieptebuffer wordt uitgevoerd in respectievelijk Unity en systeemeigen toepassingen.

Unity

Ga in de Unity-editor naar File > Build Settings. Selecteer Player Settings in de linkerbenedenhoek en controleer vervolgens of Player > XR Settings > Virtual Reality SDKs > Windows Mixed Reality Enable Depth Buffer Sharing deze optie is ingeschakeld:

Markering Dieptebuffer delen ingeschakeld

Als dat zo is, gebruikt uw app Depth LSR, anders wordt Planar LSR gebruikt.

Wanneer u OpenXR gebruikt, moet de dieptebuffer altijd worden verzonden. De instelling vindt u in XR Plug-in Management > OpenXR. De reprojectiemodus kan vervolgens worden gewijzigd via een extensie in de OpenXR-invoegtoepassing:

using Microsoft.MixedReality.OpenXR;

public class OverrideReprojection : MonoBehaviour
{
    void OnEnable()
    {
        RenderPipelineManager.endCameraRendering += RenderPipelineManager_endCameraRendering;
    }
    void OnDisable()
    {
        RenderPipelineManager.endCameraRendering -= RenderPipelineManager_endCameraRendering;
    }

    // When using the Universal Render Pipeline, OnPostRender has to be called manually.
    private void RenderPipelineManager_endCameraRendering(ScriptableRenderContext context, Camera camera)
    {
        OnPostRender();
    }

    // Called directly when using Unity's legacy renderer.
    private void OnPostRender()
    {
        ReprojectionSettings reprojectionSettings = default;
        reprojectionSettings.ReprojectionMode = ReprojectionMode.PlanarManual; // Or your favorite reprojection mode.
        
        // In case of PlanarManual you also need to provide a focus point here.
        reprojectionSettings.ReprojectionPlaneOverridePosition = ...;
        reprojectionSettings.ReprojectionPlaneOverrideNormal = ...;
        reprojectionSettings.ReprojectionPlaneOverrideVelocity = ...;

        foreach (ViewConfiguration viewConfiguration in ViewConfiguration.EnabledViewConfigurations)
        {
            if (viewConfiguration.IsActive && viewConfiguration.SupportedReprojectionModes.Contains(reprojectionSettings.ReprojectionMode))
            {
                viewConfiguration.SetReprojectionSettings(reprojectionSettings);
            }
        }
    }
}

Systeemeigen C++-toepassingen

Het indienen van de dieptebuffer is volledig onder controle van de systeemeigen C++-bindingscode, onafhankelijk van de WMR- of OpenXR-versie. De enige voorwaarde waaraan moet worden voldaan, is dat op het moment dat GraphicsBinding::BlitRemoteFrame wordt aangeroepen, een dieptebuffer moet worden gebonden aan de grafische API.

Diepte LSR

Diepte LSR werkt alleen als de clienttoepassing een geldige dieptebuffer levert die alle relevante geometrie bevat die tijdens LSR moet worden overwogen.

Diepte LSR probeert het videoframe te stabiliseren op basis van de inhoud van de opgegeven dieptebuffer. Als gevolg hiervan kan inhoud die niet is weergegeven, zoals transparante objecten, niet worden aangepast door LSR en kunnen instabiliteit en reprojectieartefacten worden weergegeven.

Als u de instabiliteit van reprojectie voor transparante objecten wilt beperken, kunt u het schrijven van dieptebuffers afdwingen. Zie de materiaalvlag TransparencyWritesDepth voor de materialen Color en PBR . Houd er echter rekening mee dat visuele kwaliteit van transparante/ondoorzichtige objectinteractie kan lijden bij het inschakelen van deze vlag.

Planar LSR

Planar LSR heeft geen informatie per pixel, zoals diepte-LSR wel doet. In plaats daarvan projecteert het alle inhoud opnieuw op basis van een vlak dat u elk frame moet opgeven.

Planar LSR projecteert de objecten die het beste dicht bij het meegeleverde vliegtuig liggen. Hoe verder weg een object is, hoe onstabieler het eruitziet. Hoewel Diepte-LSR beter is bij het opnieuw projecteren van objecten op verschillende diepten, werkt Planar LSR mogelijk beter voor inhoud die goed is afgestemd op een vlak.

Planar LSR configureren in Unity

De vlakparameters zijn afgeleid van een zogenaamde focuspunt. Wanneer u WMR gebruikt, moet het focuspunt elk frame door UnityEngine.XR.WSA.HolographicSettings.SetFocusPointForFrameworden ingesteld. Zie de Unity Focus Point-API voor meer informatie. Voor OpenXR moet het focuspunt worden ingesteld via de ReprojectionSettings vorige sectie. Als u geen focuspunt instelt, wordt een terugval voor u gekozen. Automatische terugval leidt echter vaak tot suboptimale resultaten.

U kunt het focuspunt zelf berekenen, maar het kan zinvol zijn om het te baseren op het punt dat wordt berekend door de Remote Rendering-host. Bel RemoteManagerUnity.CurrentSession.GraphicsBinding.GetRemoteFocusPoint om dat te verkrijgen.

Meestal worden zowel de client als de host inhoud weergegeven waarvan de andere kant zich niet bewust is, zoals UI-elementen op de client. Daarom kan het zinvol zijn om het externe focuspunt te combineren met een lokaal berekend punt.

De focuspunten die in twee opeenvolgende frames worden berekend, kunnen veel verschillen. Als u ze gewoon als zodanig gebruikt, kan dit ertoe leiden dat hologrammen rondspringen. Om dit gedrag te voorkomen, is interpolatie tussen de vorige en huidige focuspunten raadzaam.

Posemodi voor opnieuw projecteren

Het algemene probleembereik met hybride rendering kan als volgt worden aangegeven: Externe en lokale inhoud bevinden zich binnen verschillende poses (dat wil zeggen coördinaatruimten) omdat de externe pose wordt voorspeld door de server, terwijl de lokale pose de werkelijke huidige is. Aan het einde van een renderingframe moeten echter zowel externe als lokale inhoud worden uitgelijnd en naar het scherm worden gebracht. In de volgende afbeelding ziet u een voorbeeld waarin lokale en externe poses worden vertaald in vergelijking met de weergave-viewport:

Diagram met een externe en lokale houding ten opzichte van de doel-viewport.

Afhankelijk van het GraphicsBinding gebruikte, biedt ARR maximaal drie reprojectiemodi die orthogonaal werken in de LSR-modus die hierboven wordt besproken. Deze modi worden aangeduid als Remote pose mode, Local pose modeen Passthrough pose mode. In tegenstelling tot de LSR-modus definiëren de posemodi hoe externe en lokale inhoud wordt gecombineerd. De keuze van de modus ruilt visuele kwaliteit van lokale inhoud voor runtimeprestaties, dus toepassingen moeten zorgvuldig overwegen welke optie geschikt is. Zie de overwegingen hieronder.

Remote pose mode

Remote pose mode is de standaardmodus in ARR. In deze modus wordt de lokale inhoud weergegeven boven op de binnenkomende externe afbeeldingsstroom met behulp van de externe pose van het externe frame. Vervolgens wordt het gecombineerde resultaat doorgestuurd naar het besturingssysteem voor de uiteindelijke herprojectie. Hoewel deze benadering slechts één reprojectie gebruikt, is de uiteindelijke correctie gebaseerd op het retourinterval, zodat de volledige reprojectiefout ook wordt toegepast op de lokale inhoud. Als gevolg hiervan kan de grote correctie-delta leiden tot aanzienlijke vervormingen van lokale geometrie, waaronder UI-elementen.

In de bovenstaande afbeelding wordt de volgende transformatie toegepast in Remote pose mode:

Stappen voor opnieuw projecteren in de modus voor externe pose.

Local pose mode

In deze modus wordt de herprojectie gesplitst in twee afzonderlijke stappen: In de eerste stap wordt de externe inhoud opnieuw geprojecteerd in de lokale poseruimte, dat wil gezegd, de ruimte waarmee de lokale inhoud standaard wordt weergegeven op VR/AR-apparaten. Daarna wordt de lokale inhoud weergegeven boven op deze vooraf getransformeerde afbeelding met behulp van de gebruikelijke lokale pose. In de tweede stap wordt het gecombineerde resultaat doorgestuurd naar het besturingssysteem voor de definitieve herprojectie. Omdat deze tweede herprojectie slechts een kleine delta veroorzaakt, in feite dezelfde delta die zou worden gebruikt als ARR niet aanwezig was, worden de vervormingsartefacten op lokale inhoud aanzienlijk beperkt.

De afbeelding ziet er als volgt uit:

Stappen voor opnieuw projecteren in de lokale posemodus.

Passthrough pose mode

Deze houdingsmodus gedraagt zich in wezen hetzelfde als Remote pose mode, wat betekent dat de lokale en externe inhoud worden gecombineerd in externe ruimte. De inhoud wordt echter niet opnieuw geprojecteerd na combinatie, maar blijft in ruimte voor externe poses. Het belangrijkste voordeel van deze modus is dat de resulterende installatiekopie niet wordt beïnvloed door artefacten voor opnieuw projecteren.

Conceptueel gezien kan deze modus worden vergeleken met conventionele cloudstreamingtoepassingen. Vanwege de hoge latentie is het niet geschikt voor op hoofd gemonteerde scenario's, maar is het een geschikt alternatief voor Desktop- en andere flat-screen-toepassingen waarbij een hogere beeldkwaliteit gewenst is. Het is dus voorlopig alleen beschikbaar GraphicsBindingSimD3D11 .

Overwegingen voor prestaties en kwaliteit

De keuze van de posemodus heeft gevolgen voor visuele kwaliteit en prestaties. De extra runtimekosten aan de clientzijde voor het uitvoeren van de extra reprojectie op Local pose mode een HoloLens 2-apparaat bedragen ongeveer 1 milliseconden per frame van GPU-tijd. Deze extra kosten moeten in overweging worden genomen als de clienttoepassing al dicht bij het framebudget van 16 milliseconden ligt. Aan de andere kant zijn er soorten toepassingen zonder lokale inhoud of lokale inhoud die niet gevoelig is voor vervormingsartefacten. In die gevallen Local pose mode krijgt u geen visueel voordeel omdat de kwaliteit van de externe inhoudsherprojectie niet wordt beïnvloed.

Het algemene advies zou dus zijn om de modi per use-case te testen en te zien of de winst in visuele kwaliteit de extra prestatieoverhead rechtvaardigt. Het is ook mogelijk om de modus dynamisch in te schakelen, bijvoorbeeld om de lokale modus alleen in te schakelen wanneer belangrijke UIS's worden weergegeven.

De Pose mode at runtime wijzigen

De volgende client-API kan worden gebruikt om de modus tijdens runtime te wijzigen:

RenderingSession session = ...;
session.GraphicsBinding.SetPoseMode(PoseMode.Local); // set local pose mode
ApiHandle<RenderingSession> session = ...;
session->GetGraphicsBinding()->SetPoseMode(PoseMode::Local); // set local pose mode

Over het algemeen kan de modus worden gewijzigd wanneer het grafische bindingsobject beschikbaar is. Er is een belangrijk onderscheid voor GraphicsBindingSimD3D11: de posemodus kan alleen worden gewijzigd PoseMode.Remotein , als deze is geïnitialiseerd met proxypatroon. Als dit niet het geval is, kan de posemodus alleen tussen PoseMode.Local en PoseMode.Passthrough totdat de grafische binding opnieuw wordt geïnitialiseerd. Bekijk de twee overbelastingen van GraphicsBindingSimD3d11.InitSimulation, die systeemeigen aanwijzers naar ID3D11Texture2D-objecten (proxypad) of de width gewenste height gebruikersweergavepoort (niet-proxypad) nemen.

Overwegingen voor Desktop Unity-runtime

Vanwege de technische achtergrond van GraphicsBindingSimD3D11 en het feit hoe offscreen-rendering werkt in Unity, vereist de ARR Unity-runtime dat de gebruiker de gewenste posemodus opgeeft bij het opstarten van RemoteManagerUnity als volgt:

public static void InitRemoteManager(Camera camera)
{
    RemoteUnityClientInit clientInit = new RemoteUnityClientInit(camera, PoseMode.Remote);
    RemoteManagerUnity.InitializeManager(clientInit);
}

Als PoseMode.Remote dit is opgegeven, wordt de grafische binding geïnitialiseerd met patronen voor offscreenproxy's en wordt alle rendering omgeleid van de hoofdcamera van de Unity-scène naar een proxycamera. Dit codepad wordt alleen aanbevolen voor gebruik als de runtimehoudingsmodus wordt PoseMode.Remote gewijzigd. Als er geen posemodus is opgegeven, selecteert de ARR Unity-runtime een geschikte standaardinstelling, afhankelijk van het huidige platform.

Waarschuwing

De proxycameraomleiding is mogelijk niet compatibel met andere Unity-extensies, die verwachten dat scènerendering plaatsvindt met de hoofdcamera. De proxycamera kan worden opgehaald via de RemoteManagerUnity.ProxyCamera eigenschap als deze ergens anders moet worden opgevraagd of geregistreerd. Raadpleeg deze vermelding voor probleemoplossing specifiek voor de Cinemachine invoegtoepassing: de Unity-invoegtoepassing Cinemachine werkt niet in de modus Remote pose.

Als PoseMode.Local of PoseMode.Passthrough in plaats daarvan wordt gebruikt, wordt de grafische binding niet geïnitialiseerd met proxypatroon voor offscreen en wordt een snel pad gebruikt met behulp van de hoofdcamera van de Unity-scène om weer te geven. Als voor de respectieve use case de modus voor externe pose tijdens runtime is vereist, PoseMode.Remote moet u bij initialisatie opgeven RemoteManagerUnity . Direct renderen met de hoofdcamera van Unity is efficiënter en kan problemen met andere Unity-extensies voorkomen. Daarom is het raadzaam om het niet-proxyrenderingspad te gebruiken.

Volgende stappen