Passthrough и прозрачный фон XR
Режимы композиции, проверка поддержки, отказ без изменения фона и возврат состояния.
Passthrough и прозрачный фон XR
Passthrough позволяет компоновать виртуальное изображение с окружением, которое предоставляет XR runtime. На видео-устройстве это может быть изображение камер; на see-through устройстве — оптическое окружение. Реализация и разрешения зависят от платформы. Этот режим сам по себе не даёт игре доступ к кадрам камер, геометрии комнаты или освещению реального мира.
Сначала настройте запуск XR и проверьте инициализацию интерфейса. Наличие OpenXRInterface и сохранённый параметр проекта не означают, что сессия началась или passthrough доступен.
Выбрать способ композиции
| Режим C# | Результат |
|---|---|
XRInterface.EnvironmentBlendModeEnum.Opaque | Непрозрачный виртуальный вывод. Используйте только если режим поддерживается. |
XRInterface.EnvironmentBlendModeEnum.Additive | Виртуальный свет добавляется к окружению. Чёрный не добавляет света; это не эквивалент непрозрачного чёрного покрытия. |
XRInterface.EnvironmentBlendModeEnum.AlphaBlend | Прозрачность вывода участвует в композиции. Для видимого окружения нужен прозрачный фон Viewport и подходящие материалы. |
Получайте список через GetSupportedEnvironmentBlendModes(), проверяйте наличие нужного значения и результат SetEnvironmentBlendMode(). Setter свойства EnvironmentBlendMode не возвращает успех; метод позволяет обработать отказ.
В текущей сборке не используйте IsPassthroughSupported как проверку доступности. Этот C#-метод уже помечен obsolete. Реализация OpenXR возвращает индекс Array.find как bool: пустой список даёт −1, который становится true, а найденный элемент с индексом 0 становится false. На установленной сборке воспроизведён ответ true при пустом списке без инициализации. Ошибка движка не исправлялась; пример ниже обходит её проверкой содержимого списка. Остальные устаревшие IsPassthroughEnabled, StartPassthrough и StopPassthrough также не нужны для нового кода.
Переключить режим без прозрачного окна при отказе
using System;
using Reckfell;
public static class BlendModeSwitch
{
public static bool Contains(Reckfell.Collections.Array modes,
XRInterface.EnvironmentBlendModeEnum mode)
{
ArgumentNullException.ThrowIfNull(modes);
return modes.Contains((int)mode);
}
// Run on the main thread. Both objects are borrowed; neither is disposed here.
public static bool TryApply(XRInterface xr, Viewport viewport,
XRInterface.EnvironmentBlendModeEnum mode, bool transparentBackground)
{
ArgumentNullException.ThrowIfNull(xr);
ArgumentNullException.ThrowIfNull(viewport);
if (!xr.IsInitialized()) return false;
using var modes = xr.GetSupportedEnvironmentBlendModes();
if (!Contains(modes, mode) || !xr.SetEnvironmentBlendMode(mode))
return false;
viewport.TransparentBg = transparentBackground;
return true;
}
}Вызывайте helper в основном потоке после успешного запуска XR. Передайте заимствованный интерфейс из XRServer.FindInterface("OpenXR") и именно тот Viewport, который выводит XR. Для alpha выберите AlphaBlend и transparentBackground=true. Возвращённый false означает отказ: не скрывайте обычный фон и не сообщайте игроку, что MR включён.
До переключения сохраните xr.GetEnvironmentBlendMode() и viewport.TransparentBg. Для возврата передайте эти значения в TryApply. Проверяйте и результат возврата: если интерфейс уже деинициализирован, helper ничего не меняет. Для перехода именно в VR запросите Opaque и false, предварительно убедившись, что режим поддерживается. Не вызывайте StopPassthrough вслепую: его реализация просто запрашивает Opaque и не сообщает об отказе.
Helper не инициализирует устройство, не включает Viewport.UseXR, не выдаёт разрешения и не изменяет Environment. IsInitialized не заменяет проверку session focus/running; обрабатывайте события состояния отдельно. Он освобождает только возвращённый контейнер режимов. Не Dispose интерфейс, Viewport или другие заимствованные объекты. Владельцем переходов должен быть один компонент: конкурирующие переключатели могут перезаписывать режим и состояние фона.
Настроить сцену
- Для AlphaBlend включайте TransparentBg после принятого запроса режима. Непрозрачная геометрия и материалы всё ещё закрывают окружение: alpha фона не делает прозрачным весь мир.
- Для Additive используйте чёрный фон, если он не должен добавлять свет. Значение прозрачности для alpha не является универсальной настройкой additive-вывода.
- Настройте свет виртуальных объектов отдельно: WorldEnvironment, ambient light, IBL и источники света. Видеофон не становится автоматически sky, источником освещения или отражений.
- Проверьте CanvasLayer, UI и fullscreen-материалы. Непрозрачный overlay может закрывать окружение даже при корректном blend mode.
У OpenXR стартовый запрос находится в xr/openxr/environment_blend_mode. При отсутствии поддержки код может выбрать первый доступный режим; проверяйте результат после запуска. См. таблицу настроек. Платформенная реализация также может эмулировать alpha через отдельный passthrough-слой при другом внутреннем режиме композиции. Getter интерфейса показывает запрошенный режим, а не доказательство получения кадров камеры.
Если устройству нужна дополнительная платформенная интеграция, настройте её по документации именно используемой реализации: разрешения, manifest/export options и поддержку passthrough. Здесь не предполагается установленный vendor plugin и не обещается совместимость произвольной версии. Не отключайте системную границу ради демонстрации: passthrough не заменяет физическую безопасность и обработку потери tracking.
Тени и перекрытие реального окружения
Режим spatial-шейдера shadow_to_opacity предусмотрен для AR-материалов. Сам режим не обнаруживает стол, стену или руку: для совмещения нужна геометрия и её корректное положение относительно tracking space. Источник этой геометрии — отдельная задача.
При настройке материала учитывайте не только цвет/alpha, но и запись глубины: визуально прозрачная поверхность может закрывать виртуальную геометрию за собой. Отдельно проверьте нужный renderer, свет, shadow map и оба глаза. Здесь не приводится непроверенная демонстрация теней на реальном столе; физическая композиция и качество shadow_to_opacity этим прогоном не проверены.
Диагностика
| Симптом | Проверить |
|---|---|
| Проверка сообщает поддержку, но список пуст | Не используйте legacy IsPassthroughSupported; нужны IsInitialized и наличие AlphaBlend в списке. |
| Вместо окружения чёрный фон | Фактический режим, успешность SetEnvironmentBlendMode, TransparentBg нужного Viewport, runtime и платформенную интеграцию. |
| Окружение закрыто частью сцены | Непрозрачные материалы, небо/overlay/UI и порядок композиции. |
| Виртуальные объекты тёмные | Свет и WorldEnvironment; фон камеры не даёт автоматического IBL. |
| Выключение не возвращает прежний вид | Сохранённый режим и TransparentBg, активность сессии, результат обратного TryApply. |
| Виртуальная поверхность не совпадает с реальной | Пространство origin, масштаб, tracking и источник геометрии; blend mode этого не исправляет. |
Что проверено
На установленном Reckfell 1.0.0, Windows, headless и XR off выполнены 17 наблюдений: membership пустого/неподходящего списка и alpha на разных индексах, проверки null, реальный неинициализированный OpenXRInterface и сохранение обоих состояний TransparentBg при отказе. Воспроизведён дефект legacy support flag; поэтому его отдельная приёмка остаётся неуспешной. Это не скрывается успешными проверками helper.
Успешное аппаратное включение и возврат, видео/оптика, permissions, vendor plugin, alpha-композиция, тени, качество изображения и экспорт не проверены. На целевой гарнитуре проверьте эти переходы, фокус и оба глаза. Исходники движка и SDK не изменялись.