Поделиться через


Перепроецирование на позднем этапе

Перепроецирование на позднем этапе (LSR) — это аппаратная функция, которая помогает стабилизировать голограммы при движении пользователя.

Ожидается, что статические модели будут визуально сохранять свое положение при перемещении вокруг них. Если они кажутся нестабильными, это может указывать на проблемы с LSR. Помните, что дополнительные динамические преобразования, такие как анимации или представления взрывов, могут маскировки этого поведения.

Вы можете выбирать между двумя различными режимами LSR, а именно Плоская LSR или LSR глубины. Оба режима LSR улучшают стабильность голограммы, хотя имеют свои определенные ограничения. Начните с попытки глубины LSR, так как это, возможно, дает лучшие результаты в большинстве случаев.

Настройка режима LSR

Какой из режимов LSR используется, определяется, отправляет ли клиентское приложение буфер глубины. Если буфер глубины отправлен, он использует глубину LSR и Planar LSR в противном случае.

В следующих абзацах объясняется, как отправка буфера глубины выполняется в Unity и собственных приложениях соответственно.

Unity

В редакторе Unity перейдите к File > Build Settings. Выберите Player Settings в левом нижнем углу, затем проверьте под Player > XR Settings > Virtual Reality SDKs > Windows Mixed Reality, отмечен ли Enable Depth Buffer Sharing:

Флаг включения совместного использования буфера глубины

Если это так, ваше приложение будет использовать LSR глубины, в противном случае оно будет использовать Плоскую LSR.

При использовании OpenXR буфер глубины всегда должен быть отправлен. Параметр можно найти в XR Plug-in Management > OpenXR. Затем режим повторной подготовки можно изменить с помощью расширения в подключаемом модуле 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);
            }
        }
    }
}

Собственные приложения C++

Отправка буфера глубины полностью контролирует собственный код привязки C++ независимо от версии WMR или OpenXR. Единственное условие, которое необходимо выполнить, заключается в том, что во время GraphicsBinding::BlitRemoteFrame вызова буфер глубины должен быть привязан к ГРАФИЧЕСКОМУ API.

LSR глубины

Для работы LSR глубины клиентское приложение должно предоставить действующий буфер глубины, который содержит всю релевантную геометрию для рассмотрения во время LSR.

LSR глубины пытается стабилизировать видеокадр на основе содержимого предоставленного буфера глубины. Как следствие, контент, который не был отображен для него, например прозрачные объекты, не может быть скорректирован LSR и может показывать нестабильность и артефакты перепроецирования.

Чтобы уменьшить нестабильность репроецирования для прозрачных объектов, вы можете принудительно записать буфер глубины. См. флаг материала TransparencyWritesDepth для материалов Цвета и PBR. Однако обратите внимание, что визуальное качество взаимодействия прозрачных/непрозрачных объектов может пострадать при включении этого флага.

Плоская LSR

Planar LSR не содержит сведений о глубине пикселя, так как глубина LSR делает. Вместо этого он перепроецирует все содержимое на основе плоскости, которую вы должны предоставить для каждого кадра.

Плоская LSR лучше всего воспроизводит те объекты, которые расположены близко к поставляемой плоскости. Чем дальше находится объект, тем более неустойчивым он будет выглядеть. В то время как LSR глубины лучше воспроизводит объекты на разной глубине, Плоская LSR может лучше работать для хорошего выравнивания содержимого с плоскостью.

Настройка плоской LSR в Unity

Параметры плоскости являются производными от так называемой точки фокуса. При использовании WMR фокус-точка должна быть задана для каждого кадра UnityEngine.XR.WSA.HolographicSettings.SetFocusPointForFrame. См. подробности в API точки фокусировки Unity. Для OpenXR необходимо задать точку фокуса с помощью показанной ReprojectionSettings в предыдущем разделе. Если вы не установите точку фокусировки, для вас будет выбран запасной вариант. Однако этот автоматический откат часто приводит к неоптимальным результатам.

Вы можете рассчитать точку фокусировки самостоятельно, хотя может иметь смысл основывать ее на точке, вычисленной узлом удаленной отрисовки. Вызовите RemoteManagerUnity.CurrentSession.GraphicsBinding.GetRemoteFocusPoint, чтобы это получить.

Обычно и клиент, и хост визуализируют контент, о котором другая сторона не знает, например элементы пользовательского интерфейса на клиенте. Следовательно, имеет смысл объединить удаленную точку фокусировки с рассчитанной локально.

Точки фокуса, вычисляемые в двух последовательных кадрах, могут сильно отличаться. Простое использование их как есть может привести к тому, что голограммы будут прыгать. Чтобы предотвратить такое поведение, рекомендуется интерполировать предыдущую и текущую точки фокусировки.

Режимы повторной подготовки

Общая область проблемы с гибридной отрисовкой может быть указана следующим образом: удаленное и локальное содержимое находятся в разных позах (то есть в пространствах координат), так как удаленная поза прогнозируется сервером, а локальная поза является фактической текущей. Однако в конце кадра отрисовки необходимо выровнять и выровнять локальное содержимое. На следующем рисунке показан пример преобразования локальных и удаленных поз по сравнению с окном просмотра отображения:

Схема, демонстрирующая удаленную и локальную позу в отношении целевого окна просмотра.

В зависимости от используемого GraphicsBinding режима ARR предоставляет до трех режимов повторного создания, которые работают в режиме LSR, описанном выше. Эти режимы называются Remote pose mode, Local pose modeи Passthrough pose mode. В отличие от режима LSR, режимы поз определяют, как объединяется удаленное и локальное содержимое. Выбор режима торгует визуальным качеством локального содержимого для производительности среды выполнения, поэтому приложения должны тщательно учитывать, какой вариант подходит. Ознакомьтесь с приведенными ниже рекомендациями.

Remote pose mode

Remote pose mode — это режим по умолчанию в ARR. В этом режиме локальное содержимое отрисовывается поверх входящего потока удаленного изображения с помощью удаленного позирования из удаленного кадра. Затем объединенный результат пересылается в ОС для окончательного повторного выполнения. В то время как этот подход использует только один репроецирование, окончательное исправление основано на интервале кругового пути, поэтому полная ошибка репроецирования применяется к локальному содержимому, а также. В результате большая разностная коррекция может привести к значительным искажениям локальной геометрии, включая элементы пользовательского интерфейса.

На приведенном выше рисунке применяется Remote pose modeследующее преобразование:

Шаги повторного развертывания в удаленном режиме позирования.

Local pose mode

В этом режиме репроецирование разделено на два отдельных шага: на первом шаге удаленный контент перепроектирован в локальное пространство поз, то есть пространство, которое локальное содержимое отображается на устройствах VR/AR по умолчанию. После этого локальное содержимое отображается поверх этого предварительно преобразованного изображения с помощью обычной локальной позы. Во втором шаге объединенный результат пересылается в ОС для окончательного повторного создания. Так как эта вторая репроекция вызывает только небольшую дельту - на самом деле ту же дельту, которая будет использоваться, если ARR не присутствовала - артефакты искажений на локальном содержимом значительно смягчаются.

Соответственно, рисунок выглядит следующим образом:

Шаги повторного развертывания в локальном режиме позирования.

Passthrough pose mode

Этот режим позирования ведет себя по сути так же, как Remote pose modeи локальное и удаленное содержимое в удаленном пространстве. Однако содержимое не будет перепроецировано после сочетания, но остается в удаленном пространстве поз. Основное преимущество этого режима заключается в том, что результирующий образ не будет влиять на артефакты повторной подготовки.

Концептуально этот режим можно сравнить с обычными облачными приложениями потоковой передачи. Из-за высокой задержки он вызывает, он не подходит для сценариев, подключенных к голове, но является жизнеспособной альтернативой для классических и других приложений с плоским экраном, где требуется более высокое качество изображения. Таким образом, он доступен GraphicsBindingSimD3D11 только в течение времени.

Рекомендации по производительности и качеству

Выбор режима позирования влияет на качество и производительность. Дополнительная стоимость среды выполнения на стороне клиента для выполнения дополнительной повторной подготовки на Local pose mode устройстве HoloLens 2 составляет около 1 миллисекунда за кадр времени GPU. Эти дополнительные затраты необходимо учитывать, если клиентское приложение уже близко к бюджету кадра в 16 миллисекундах. С другой стороны, существуют типы приложений без локального содержимого или локального содержимого, которые не подвержены искажениям артефактов. В этих случаях Local pose mode не получает никакого визуального преимущества, так как качество удаленного репроецирования содержимого не влияет.

Таким образом, общие советы будут проверять режимы на основе каждого варианта использования и видеть, является ли повышение качества визуального элемента оправдывает дополнительные затраты на производительность. Кроме того, можно динамически переключать режим, например включить локальный режим только при отображении важных UIS.

Pose mode Изменение среды выполнения

Для изменения режима во время выполнения можно использовать следующий клиентский API:

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

Как правило, режим можно изменить в любое время, когда объект графической привязки доступен. Существует важное различие для GraphicsBindingSimD3D11: режим представления можно изменить PoseMode.Remoteтолько в том случае, если он был инициализирован с помощью текстур прокси-сервера. Если это не так, режим позирования можно переключать только между PoseMode.Local и PoseMode.Passthrough до повторной инициализации графической привязки. См. две перегрузкиGraphicsBindingSimD3d11.InitSimulation, которые принимают собственные указатели на объекты ID3D11Texture2D (путь к прокси-серверу) или height width нужный пользовательский интерфейс просмотра (не-прокси-путь).

Рекомендации по среде выполнения Unity для настольных компьютеров

Из-за технического GraphicsBindingSimD3D11 фона и того, как работает внеэкранная отрисовка в Unity, среда выполнения ARR Unity требует, чтобы пользователь указал нужный режим поз при запуске RemoteManagerUnity следующим образом:

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

Если PoseMode.Remote задано, графическая привязка будет инициализирована с помощью текстур прокси-сервера вне экрана, а все отрисовки будут перенаправлены с основной камеры сцены Unity на прокси-камеру. Этот путь кода рекомендуется использовать только в том случае, если требуется изменение PoseMode.Remote режима выполнения. Если режим поз не указан, среда выполнения ARR Unity выберет соответствующее значение по умолчанию в зависимости от текущей платформы.

Предупреждение

Перенаправление прокси-камеры может быть несовместимо с другими расширениями Unity, которые ожидают отрисовки сцен с основной камерой. Прокси-камера может быть получена через RemoteManagerUnity.ProxyCamera свойство, если его необходимо запросить или зарегистрировать в другом месте. В частности, для подключаемого модуля обратитесь к этой записи по устранению неполадок: подключаемый Cinemachine модуль Unity Cinemachine не работает в режиме удаленного позирования.

Если PoseMode.Local или PoseMode.Passthrough используется вместо этого, привязка графики не будет инициализирована с помощью текстур прокси-сервера вне экрана, а также быстрый путь с помощью основной камеры сцены Unity для отрисовки будет использоваться. Если для соответствующего варианта использования требуется режим удаленного позирования во время выполнения, PoseMode.Remote следует указать при RemoteManagerUnity инициализации. Прямая отрисовка с помощью основной камеры Unity более эффективна и может предотвратить проблемы с другими расширениями Unity. Поэтому рекомендуется использовать путь отрисовки, отличный от прокси-сервера.

Следующие шаги