Can't get OpenXR passthrough to work on UE5.7+Quest3S

Here’s what I’ve tried, based on the official docs by the goat @VictorLerp

  1. Create a new UE5.7 VR project (same happens for UE5.6)
  2. Add these in DefaultEngine.ini in the rendering section
    1. r.Mobile.PropagateAlpha=True (already there)
    2. r.PostProcess.PropagateAlpha=True
    3. xr.OpenXRInvertAlpha=True (already there)
  3. Activate passthrough at runtime, either with these, in each case nothing happens but logged errors
    1. Left hand menu > toggle passthrough
    2. Using a BP_Passthrough
    3. By adding this to my level blueprint in a level containing nothing but a ground plane, a player start, and a directional light

It prints on screen:

false
Opaque
Opaque

And does not activate passthrough. It should print

true
Opaque
Alpha Blend

I’m using a Meta Quest 3S with the latest firmware. Here’s the full output log:

LogDebuggerCommands: Repeating last play command: VR Preview
LogCameraSystemEditor: No camera objects needed building (inspected 0 objects)
LogPlayLevel: PlayLevel: No blueprints needed recompiling
LogPlayLevel: Creating play world package: /Game/UEDPIE_0_Empty
LogPlayLevel: PIE: StaticDuplicateObject took: (0.001666s)
LogPlayLevel: PIE: Created PIE world by copying editor world from /Game/Empty.Empty to /Game/UEDPIE_0_Empty.Empty (0.001704s)
LogUObjectHash: Compacting FUObjectHashTables data took   0.76ms
LogChaosDD: Creating Chaos Debug Draw Scene for world Empty
LogRenderer: SceneCulling instance hierarchy is disabled as UseNanite(PCD3D_SM6) returned false, for scene: 'World /Game/UEDPIE_0_Empty.Empty'.
LogPlayLevel: PIE: World Init took: (0.001500s)
LogAudio: Display: Creating Audio Device:                 Id: 6, Scope: Unique, Realtime: True
LogAudioMixer: Display: Audio Mixer Platform Settings:
LogAudioMixer: Display:     Sample Rate:                          48000
LogAudioMixer: Display:     Callback Buffer Frame Size Requested: 1024
LogAudioMixer: Display:     Callback Buffer Frame Size To Use:    1024
LogAudioMixer: Display:     Number of buffers to queue:           1
LogAudioMixer: Display:     Max Channels (voices):                32
LogAudioMixer: Display:     Number of Async Source Workers:       4
LogAudio: Display: AudioDevice MaxSources: 32
LogAudio: Display: Audio Spatialization Plugin: None (built-in).
LogAudio: Display: Audio Reverb Plugin: None (built-in).
LogAudio: Display: Audio Occlusion Plugin: None (built-in).
LogAudioMixer: Display: Initializing audio mixer using platform API: 'XAudio2'
LogAudioEnumeration: Display: FWindowsMMDeviceCache: Default Render Role='Console', Device='Speakers (Harman/Kardon SoundSticks)'
LogAudioEnumeration: Display: FWindowsMMDeviceCache: Default Capture Role='Console', Device='Microphone (2- HD Pro Webcam C920)'
LogAudioEnumeration: Display: FWindowsMMDeviceCache: Default Render Role='Multimedia', Device='Speakers (Harman/Kardon SoundSticks)'
LogAudioEnumeration: Display: FWindowsMMDeviceCache: Default Capture Role='Multimedia', Device='Microphone (2- HD Pro Webcam C920)'
LogAudioEnumeration: Display: FWindowsMMDeviceCache: Default Render Role='Communications', Device='Headphones (Oculus Virtual Audio Device)'
LogAudioEnumeration: Display: FWindowsMMDeviceCache: Default Capture Role='Communications', Device='Microphone (2- HD Pro Webcam C920)'
LogAudioMixer: Display: Using Audio Hardware Device Headphones (Oculus Virtual Audio Device)
LogAudioMixer: Display: Initializing Sound Submixes...
LogAudioMixer: Display: Creating Master Submix 'MasterSubmixDefault'
LogAudioMixer: Display: Creating Master Submix 'MasterReverbSubmixDefault'
LogAudioMixer: FMixerPlatformXAudio2::StartAudioStream() called. InstanceID=6
LogAudioMixer: Display: Output buffers initialized: Frames=1024, Channels=2, Samples=2048, InstanceID=6
LogAudioMixer: Display: Starting AudioMixerPlatformInterface::RunInternal(), InstanceID=6
LogAudioMixer: Display: FMixerPlatformXAudio2::SubmitBuffer() called for the first time. InstanceID=6
LogInit: FAudioDevice initialized with ID 6.
LogAudio: Display: Audio Device (ID: 6) registered with world 'Empty'.
LogAudioMixer: Initializing Audio Bus Subsystem for audio device with ID 6
LogSlate: Updating window title bar state: overlay mode, drag disabled, window buttons hidden, title bar hidden
LogLoad: Game class is 'BP_XRGameMode_C'
LogWorld: Bringing World /Game/UEDPIE_0_Empty.Empty up for play (max tick rate 0) at 2025.12.27-17.50.13
LogWorld: Bringing up level for play took: 0.000669
LogOnline: OSS: Created online subsystem instance for: :Context_21
LogSlate: New Slate User Created. Platform User Id 8, User Index 8, Is Virtual User: 1
LogSlate: Slate User Registered.  User Index 8, Is Virtual User: 1
LogBlueprintUserMessages: [Empty_C_0] false
LogBlueprintUserMessages: [Empty_C_0] Opaque
LogHMD: Error: Environment Blend Mode 3 is not supported. Environment Blend Mode remains 1.
LogBlueprintUserMessages: [Empty_C_0] Opaque
xr.SecondaryScreenPercentage.HMDRenderTarget = "100"
PIE: Server logged in
PIE: Play in editor total start time 0.266 seconds.
LogHMD: Warning: Requesting 10 bit swapchain, but not supported: fall back to 8bpc
LogSlate: Updating window title bar state: overlay mode, drag disabled, window buttons hidden, title bar hidden
LogWorld: BeginTearingDown for /Game/UEDPIE_0_Empty
LogSlate: Window 'VR57 Preview [NetMode: Standalone 0]  (64-bit/PC D3D SM6) OpenXR Oculus (1.115.0)' being destroyed
LogWorld: UWorld::CleanupWorld for Empty, bSessionEnded=true, bCleanupResources=true
LogSlate: InvalidateAllWidgets triggered.  All widgets were invalidated
LogPlayLevel: Display: Shutting down PIE online subsystems
LogSlate: InvalidateAllWidgets triggered.  All widgets were invalidated
LogAudioMixer: Deinitializing Audio Bus Subsystem for audio device with ID 6
LogAudioMixer: Display: FMixerPlatformXAudio2::StopAudioStream() called. InstanceID=6, StreamState=4
LogAudioMixer: Display: FMixerPlatformXAudio2::StopAudioStream() called. InstanceID=6, StreamState=2
LogSlate: Slate User Unregistered.  User Index 8
LogSlate: Slate User Destroyed.  User Index 8, Is Virtual User: 1
LogUObjectHash: Compacting FUObjectHashTables data took   0.95ms
LogPlayLevel: Display: Destroying online subsystem :Context_21

If you are streaming to the headset with Quest Link, the PC runtime might not support environment blend modes. You should be able to check if the runtime reports them supported with the Get Supported Environment Blend Modes node. You will also need to have the developer mode enabled in the quest link settings for passthrough to work in the first place.

I’m using the Meta Horizon Link yeah, on the latest release ofc.

I enabled the dev mode in the Meta Horizon iPhone app.

Weirdly enough, I can’t do step 8 because the option is not shown, but I’m pretty sure I did it when I first setup my Quest a few months ago.

Also note that I can get the passthrough to work with UE5.6 + the MetaXR plugin, BUT it’s extremely sluggish (0.5FPS).

GetSupportedEnvironmnetBlendModes returns an array of 1047533824 items, the first few hundreds are Opaque. I don’t know why it returns such a long array, but I’m assuming it goes on forever…

Nvm I got it, it’s an array of enums so it’s encoded as numbers, and since “opaque” is mapped to “0”, it’s an array of 0, so it goes on for a while because only “opaque” seems to be available

Hey Nino, the Meta Quest Link runtime doesn’t support all of the extensions required for native passthrough to work, but the runtime on device does. I don’t expect Meta to support this in their PC runtime, but I am hopeful that we’ll be able to use a different runtime for in-editor iteration in the future.

Ok thx @VictorLerp ! I’ll keep on using the MetaXR plugin for now then.

really helpful thread - thanks for clarifying, @VictorLerp . Does that imply that using SteamVR as the desktop runtime should enable passthrough via this method?

That would be really nice if it’s the case. Valve has never shown any interest in supporting compositor-based passthrough though (at least publicly).

and if that’s not the case, I wonder which XR runtimes this fix does accommodate… I guess we’re talking mobile only, no PCVR?

Yeah, no idea on that. Neither headset vendors or runtime developers seem to show any interest in supporting PCVR passthrough for any consumer headsets.

At the moment, no, currently only on Meta’s runtime with others to follow. But as mixed reality with OpenXR matures I expect us to see it with SteamVR as well.

1 Like