Share via


Reprojection en phase tardive

La reprojection en phase tardive (LSR) est une fonctionnalité matérielle qui permet de stabiliser les hologrammes lorsque l’utilisateur est en mouvement.

Les modèles statiques sont censés conserver visuellement leur position lorsque vous les contournez. S’ils semblent instables, ce comportement peut indiquer des problèmes LSR. Gardez à l’esprit que des transformations dynamiques supplémentaires, comme des animations ou des vues d’explosion, risquent de masquer ce comportement.

Vous pouvez choisir entre deux modes LSR différents : Planar LSR ou Depth LSR. Les deux modes LSR améliorent la stabilité des hologrammes, bien qu’ils aient chacun leurs propres limitations. Commencez par essayer Depth LSR, car il permet assurément d’obtenir de meilleurs résultats dans la plupart des cas.

Définition du mode LSR

Le mode LSR à utiliser n’est pas le même selon que l’application cliente envoie ou non un tampon de profondeur. Elle opte pour le mode Depth LSR si elle envoie le tampon de profondeur, et pour le mode Planar LSR dans le cas contraire.

Les paragraphes suivants expliquent comment l’envoi du tampon de profondeur s’effectue respectivement dans les applications Unity et natives.

Unity

Dans l’éditeur Unity, accédez à File > Build Settings. Sélectionnez Player Settings en bas à gauche, puis vérifiez sous Player > XR Settings > Virtual Reality SDKs > Windows Mixed Reality si la case Enable Depth Buffer Sharing est cochée :

Depth Buffer Sharing Enabled flag

Si c’est le cas, votre application utilisera Depth LSR, sinon, elle utilisera Planar LSR.

Quand vous utilisez OpenXR, le tampon de profondeur doit toujours être envoyé. Le paramètre se trouve dans XR Plug-in Management > OpenXR. Le mode de reprojection peut ensuite être modifié via une extension dans le plug-in OpenXR :

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

Applications C++ natives

L’envoi du tampon de profondeur est entièrement sous le contrôle du code de liaison C++ natif, indépendamment de la version de WMR et d’OpenXR. La seule condition à remplir est qu’un tampon de profondeur doit être lié à l’API de graphismes au moment de l’appel de GraphicsBinding::BlitRemoteFrame.

Depth LSR

Pour que Depth LSR fonctionne, l’application cliente doit fournir un tampon de profondeur valide qui contient toutes les géométries appropriées à prendre en compte pendant la reprojection en phase tardive.

Depth LSR tente de stabiliser la trame vidéo en fonction du contenu du tampon de profondeur fourni. Ainsi, le contenu qui n’y a pas été rendu, tel que les objets transparents, ne peut pas être ajusté par LSR mais présenter une instabilité et des artefacts de reprojection.

Pour atténuer l’instabilité de la reprojection pour les objets transparents, vous pouvez forcer l’écriture dans le tampon de profondeur. Consultez l’indicateur de matériau TransparencyWritesDepth pour les matériaux Couleur et PBR. Notez toutefois que la qualité visuelle de l’interaction entre l’objet transparent et l’objet opaque peut souffrir de cet indicateur.

Planar LSR

Planar LSR ne dispose pas d’informations de profondeur par pixel, à l’instar de Depth LSR. Au lieu de cela, il reprojette tout le contenu en fonction d’un plan que vous devez fournir à chaque trame.

Planar LSR reprojette de façon optimale les objets qui se trouvent le plus près du plan fourni. Plus un objet est éloigné, plus son apparence est instable. Si Depth LSR convient mieux pour la reprojection d’objets à différentes profondeurs, Planar LSR obtient de meilleurs résultats dans l’alignement de contenu par rapport à un plan.

Configurer Planar LSR dans Unity

Les paramètres de plan sont dérivés de ce qu’on appelle un point de focus. Lors de l’utilisation de WMR, le point de focus doit être défini pour chaque image via UnityEngine.XR.WSA.HolographicSettings.SetFocusPointForFrame. Pour plus d’informations, consultez API Unity Focus Point. Pour OpenXR, le point de focus doit être défini via les ReprojectionSettings indiqués dans la section précédente. Si vous ne définissez pas de zone de focus, une solution de secours sera choisie pour vous. Pour autant, ce point de secours automatique aboutit souvent à des résultats inférieurs.

Vous pouvez calculer vous-même la zone de focus, bien qu’il puisse paraître judicieux de la baser sur celle qui est calculée par l’hôte Remote Rendering. Appelez RemoteManagerUnity.CurrentSession.GraphicsBinding.GetRemoteFocusPoint pour l’obtenir.

En général, le client et l’hôte affichent chacun le contenu qui n’est pas pris en charge par l’autre, par exemple des éléments d’interface utilisateur sur le client. Ainsi, il peut s’avérer opportun de combiner la zone de focus à distance avec un point calculé localement.

Les zones de focus calculées dans deux trames successives peuvent varier considérablement. Leur utilisation telle quelle peut donner aux hologrammes une apparence sautillante. Pour éviter ce comportement, il est conseillé d’interpoler entre la zone de focus précédente et la zone actuelle.

Modes de pose de reprojection

L’étendue du problème général avec un rendu hybride peut être formulée comme suit : le contenu local et le contenu distant se trouvent dans des poses distinctes (c’est-à-dire des espaces de coordonnées), car la pose distante est prédite par le serveur, tandis que la pose locale correspond à la pose actuelle réelle. Toutefois, à la fin d’une trame de rendu, le contenu distant et le contenu local doivent être alignés et mis à l’écran. L’illustration suivante montre un exemple dans lequel la pose locale et la pose distante sont traduites par rapport à la fenêtre d’affichage :

Diagram that illustrates remote and local pose in relation to target viewport.

En fonction de l’utilisation GraphicsBinding , ARR fournit jusqu’à trois modes de reprojection qui fonctionnent orthogonalement vers le mode LSR décrit ci-dessus. Ces modes sont appelés Remote pose mode, Local pose mode et Passthrough pose mode. Contrairement au mode LSR, les modes de pose définissent la façon dont le contenu distant et le contenu local sont combinés. Le choix du mode demande un compromis entre la qualité visuelle du contenu local et le niveau de performance d’exécution. Il faut donc réfléchir soigneusement à l’option appropriée pour les applications. Considérez les points ci-dessous.

Remote pose mode

Le mode Remote pose mode constitue le mode par défaut dans ARR. Dans ce mode, le contenu local est affiché en haut du flux d’image distante entrant à l’aide de la pose distante de la trame distante. Le résultat combiné est ensuite transféré au système d’exploitation pour la reprojection finale. Bien que cette approche n’utilise qu’une seule reprojection, la correction finale se base sur l’intervalle aller-retour afin que l’erreur de reprojection complète soit également appliquée au contenu local. Par conséquent, un delta de correction important peut entraîner des distorsions significatives de la géométrie locale, et notamment des éléments d’interface utilisateur.

Si l’on reprend l’illustration ci-dessus, la transformation suivante est appliquée dans le mode Remote pose mode :

Reprojection steps in remote pose mode.

Local pose mode

Dans ce mode, la reprojection est divisée en deux étapes distinctes : lors de la première étape, le contenu distant est reprojeté dans l’espace de pose local, c’est-à-dire l’espace avec lequel le contenu local est restitué par défaut sur les appareils de réalité virtuelle ou augmentée. Ensuite, le contenu local est affiché en haut de cette image prétransformée à l’aide de la pose locale habituelle. Au cours de la deuxième étape, le résultat combiné est transféré au système d’exploitation pour la reprojection finale. Dans la mesure où cette deuxième reprojection n’implique qu’un petit delta (le même que si ARR n’était pas présent), les artefacts de distorsion sont sensiblement atténués sur le contenu local.

En conséquence, l’illustration se présente ainsi :

Reprojection steps in local pose mode.

Passthrough pose mode

Ce mode pose se comporte essentiellement de la même façon que , ce qui signifie que Remote pose modele contenu local et distant est combiné dans l’espace distant. Toutefois, le contenu ne sera pas reprojeté après combinaison, mais restera dans l’espace de pose à distance. L’avantage principal de ce mode est que l’image résultante ne sera pas affectée par les artefacts de reprojection.

Conceptuellement, ce mode peut être comparé aux applications de streaming cloud conventionnelles. En raison de la latence élevée qu’elle entraîne, elle n’est pas adaptée aux scénarios montés en tête, mais constitue une alternative viable pour les applications de bureau et d’autres applications à écran plat où une meilleure qualité d’image est souhaitée. Il n’est donc disponible GraphicsBindingSimD3D11 que pour le moment.

Considérations relatives au niveau de performance et à la qualité

Le choix du mode de pose présente des implications en matière de qualité visuelle et de niveau de performance. Le coût d’exécution supplémentaire côté client pour effectuer la reprojection supplémentaire dans le mode Local pose mode sur un appareil HoloLens 2 s’élève à environ 1 milliseconde par image en temps du GPU. Il doit être pris en considération si l’application cliente est déjà proche du budget de trame de 16 millisecondes. En revanche, il existe des types d’applications sans contenu local et d’autres dont le contenu local n’est pas sujet à des artefacts de distorsion. Dans ce cas, le mode Local pose mode n’offre aucun avantage visuel, car la qualité de la reprojection du contenu distant n’est pas affectée.

Le conseil général serait donc de tester les modes selon le cas d’usage et de déterminer si le gain en termes de qualité visuelle justifie la surcharge de performances supplémentaire. Il est également possible de basculer dynamiquement entre les modes, par exemple en n’activant le mode local que lorsque des interfaces utilisateur importantes s’affichent.

Modification du mode Pose mode à l’exécution

L’API cliente suivante permet de changer de mode à l’exécution :

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

En général, le mode peut être modifié chaque fois que l’objet de liaison de graphismes est disponible. Il existe une distinction importante pour GraphicsBindingSimD3D11 : le mode pose peut uniquement être remplacé par PoseMode.Remote s’il a été initialisé avec des textures de proxy. Si ce n’est pas le cas, le mode pose ne peut être basculé qu’entre PoseMode.Local et PoseMode.Passthrough jusqu’à ce que la liaison graphique soit réinitialisée. Consultez les deux surcharges de GraphicsBindingSimD3d11.InitSimulation, qui prennent soit des pointeurs natifs vers des objets ID3D11Texture2D (chemin de proxy), soit width et height de la fenêtre d’affichage utilisateur souhaitée (chemin non proxy).

Considérations sur l’exécution de Desktop Unity

En raison du contexte technique de GraphicsBindingSimD3D11 et de la façon dont le rendu hors écran fonctionne dans Unity, le moteur d’exécution ARR Unity exige que l’utilisateur spécifie le mode de pose souhaité au démarrage de RemoteManagerUnity, comme suit :

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

Si PoseMode.Remote est spécifié, la liaison graphique est initialisée avec des textures de proxy hors écran et tout le rendu est redirigé de la caméra principale de la scène Unity vers une caméra proxy. Ce chemin de code est recommandé uniquement si des modifications du mode de pose du PoseMode.Remote sont requises. Si aucun mode pose n’est spécifié, le runtime ARR Unity sélectionne une valeur par défaut appropriée en fonction de la plateforme actuelle.

Avertissement

La redirection de caméra de proxy peut être incompatible avec d’autres extensions Unity, qui s’attendent à avoir un rendu de scène avec la caméra principale. La caméra proxy peut être récupérée via la propriété RemoteManagerUnity.ProxyCamera si elle doit être interrogée ou inscrite ailleurs. Pour le plug-in Cinemachine, reportez-vous à cette entrée de résolution des problèmes : Le plug-in Unity Cinemachine ne fonctionne pas en mode de pose distante.

Si PoseMode.Local ou PoseMode.Passthrough est utilisé à la place, la liaison graphique ne sera pas initialisée avec des textures proxy hors écran et un chemin rapide utilisant la caméra principale de la scène Unity sera utilisé pour effectuer le rendu. Si le cas d’utilisation en question exige des changements de mode de pose au moment de l’exécution, PoseMode.Remote doit être spécifié lors de l’initialisation de RemoteManagerUnity. Le rendu direct avec la caméra principale d’Unity est plus efficace et peut empêcher les problèmes liés à d’autres extensions Unity. Par conséquent, il est recommandé d’utiliser le chemin d’accès de rendu non proxy.

Étapes suivantes