Skip to content

OpenXR: Meta passthrough, environment depth occlusion, and frame state refactor#63

Merged
lassoan merged 3 commits into
Slicer:slicer-v9.6.2-2026-05-15-f49a1dbaffrom
Sunderlandkyl:openxr_passthrough_slicer-v9.6.2-2026-05-15-f49a1dbaf
Jun 23, 2026
Merged

OpenXR: Meta passthrough, environment depth occlusion, and frame state refactor#63
lassoan merged 3 commits into
Slicer:slicer-v9.6.2-2026-05-15-f49a1dbaffrom
Sunderlandkyl:openxr_passthrough_slicer-v9.6.2-2026-05-15-f49a1dbaf

Conversation

@Sunderlandkyl

Copy link
Copy Markdown
Member

ENH: Add Meta passthrough and environment depth occlusion support

Adds support for XR_FB_passthrough and XR_META_environment_depth (requires OpenXR SDK 1.1.36).

New API on vtkOpenXRRenderWindow:

  • UsePassthrough / PassthroughOn / PassthroughOff — request mixed reality via standard alpha-blend or Meta-specific composition layer
  • OccludedOpacity [0,1] — control real-world occlusion strength via depth pre-pass
  • ShowEnvDepthDebugVisualization — false-colour depth overlay
  • CaptureEnvironmentDepth — force depth capture even at full opacity
  • IsPassthroughActive() — query live passthrough state

New class vtkOpenXREnvironmentDepthOcclusionPrePass: fullscreen-triangle pass that reads the META environment depth swapchain and composites real-world occlusion or a debug overlay onto each eye's frame.

New API on vtkOpenXRManager: StartFBPassthrough, StopFBPassthrough, StartEnvironmentDepth, StopEnvironmentDepth, AcquireEnvironmentDepthImage, and related query/accessor methods.


ENH: Streamline frame state management into a single pathway

Consolidates per-frame XR state into a single vtkOpenXRFrameContext struct, removing now-redundant standalone members.

Processing loop fixes:

  • WaitAndBeginFrame() called at the start of DoOneEvent() so PredictedDisplayTime is valid before PollXrActions()
  • SyncActions() moved to just before LocateViews() to ensure action data is always synced before poses are located
  • FrameBegan guard prevents double xrWaitFrame/xrBeginFrame calls
  • LocateViews() extracted from WaitAndBeginFrame() for clarity

Other fixes:

  • Guard hand-pose updates with XR_SPACE_LOCATION_POSITION_VALID_BIT
  • Cache last valid view state and fall back on tracking loss (avoids black frames on startup)
  • Defer pose-space creation to CreateActionPoseSpaces() after AttachSessionActionSets()
  • Fix memory leak: missing delete[] for controller model buffer

Consolidate per-frame XR state (ShouldRender, PredictedDisplayTime,
ViewState, Views, PoseValid) into a single vtkOpenXRFrameContext struct
and remove the now-redundant standalone members.

Processing loop fixes:
- Call WaitAndBeginFrame() at the start of DoOneEvent() so that
  PredictedDisplayTime is valid before PollXrActions() uses it for
  action-space location.
- Move SyncActions() from PollXrActions() to just before LocateViews()
  so action data is always synced before poses are located.
- Add FrameBegan guard to prevent double xrWaitFrame/xrBeginFrame calls.
- Extract LocateViews() from WaitAndBeginFrame() for clarity.

Other fixes:
- Use XR_SPACE_LOCATION_POSITION_VALID_BIT to guard hand-pose updates.
- Cache the last valid view state / views and fall back to them when
  xrLocateViews returns invalid flags (avoids black frames on startup
  or during brief tracking loss).
- Defer pose-space creation to a new CreateActionPoseSpaces() step
  called after AttachSessionActionSets().
- Fix memory leak: add missing delete[] for the controller model buffer.
Add support for the Meta OpenXR extensions XR_FB_passthrough and
XR_META_environment_depth (requires OpenXR SDK 1.1.36).

New public API on vtkOpenXRRenderWindow:
- UsePassthrough / PassthroughOn / PassthroughOff: request mixed
  reality mode via XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND (standard AR
  path) or XR_FB_passthrough (Meta-specific composition layer path).
- OccludedOpacity [0,1]: control how strongly real-world surfaces
  occlude virtual geometry via the depth pre-pass.
- ShowEnvDepthDebugVisualization: enable a false-colour depth overlay.
- CaptureEnvironmentDepth: force environment depth even at opacity 1.
- IsPassthroughActive(): query whether passthrough is actually active.

New class vtkOpenXREnvironmentDepthOcclusionPrePass:
  Fullscreen-triangle pass that reads the META environment depth
  swapchain and composites real-world occlusion onto each eye's frame
  (ApplyOcclusionPostPass) or renders a debug false-colour overlay
  (DebugVisualize).

New API on vtkOpenXRManager:
- StartFBPassthrough / StopFBPassthrough
- StartEnvironmentDepth / StopEnvironmentDepth / AcquireEnvironmentDepthImage
- IsFBPassthroughSupported / IsFBPassthroughActive
- IsEnvironmentDepthActive / GetEnvDepthTextureId / GetEnvDepthViews
- SetPreferredEnvironmentBlendMode / GetEnvironmentBlendMode
@lassoan

lassoan commented Jun 10, 2026

Copy link
Copy Markdown

Thanks a lot @Sunderlandkyl, the changes look good at a high level, I'll build and test locally and review it more.

In the meantime, could you please also submit these changes to https://gitlab.kitware.com/vtk/vtk? We don't need to wait for the upstream pull requests to be merged to get these integrated in this repository but in the commit comments we'll need to refer to the upstream pull request(s).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enhances VTK’s OpenXR backend by adding Meta passthrough (XR_FB_passthrough) and environment depth occlusion (XR_META_environment_depth) support, and by refactoring the per-frame OpenXR state flow to be managed through a unified frame context.

Changes:

  • Add Meta passthrough and META environment-depth acquisition/compositing pathways, including a new GL fullscreen-pass helper for occlusion/debug overlays.
  • Refactor frame timing/view state handling into vtkOpenXRFrameContext, moving frame begin/end responsibilities into a single per-frame pathway.
  • Bump the required OpenXR SDK version to 1.1.36 and register new extension function dispatch entries.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
Rendering/OpenXR/XrExtensions.h Registers new extension dispatch-table entries for XR_FB_passthrough and XR_META_environment_depth.
Rendering/OpenXR/vtkOpenXRRenderWindowInteractor.cxx Moves frame begin/sync/locate/end into the interactor’s per-event loop and adds pose-validity guarding.
Rendering/OpenXR/vtkOpenXRRenderWindow.h Adds new public API knobs for passthrough and environment-depth occlusion/debugging/capture.
Rendering/OpenXR/vtkOpenXRRenderWindow.cxx Integrates passthrough startup, updates frame finalization ordering, and hooks environment-depth post-pass into stereo callbacks.
Rendering/OpenXR/vtkOpenXRManager.h Introduces vtkOpenXRFrameContext and adds FB passthrough + environment depth APIs/accessors and blend-mode preference controls.
Rendering/OpenXR/vtkOpenXRManager.cxx Implements FB passthrough + environment depth lifecycle, view-location caching, and frame-loop refactor.
Rendering/OpenXR/vtkOpenXREnvironmentDepthOcclusionPrePass.h Adds new helper class interface for environment-depth occlusion and debug visualization passes.
Rendering/OpenXR/vtkOpenXREnvironmentDepthOcclusionPrePass.cxx Implements GLSL programs and GL state management for occlusion/debug post-passes.
Rendering/OpenXR/CMakeLists.txt Requires OpenXR 1.1.36 and adds the new pre-pass class to the module build.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Rendering/OpenXR/vtkOpenXRRenderWindowInteractor.cxx
Comment thread Rendering/OpenXR/vtkOpenXRManager.cxx Outdated
Comment thread Rendering/OpenXR/vtkOpenXRManager.h Outdated
Comment thread Rendering/OpenXR/vtkOpenXRManager.cxx
Comment thread Rendering/OpenXR/vtkOpenXREnvironmentDepthOcclusionPrePass.cxx
Comment thread Rendering/OpenXR/vtkOpenXREnvironmentDepthOcclusionPrePass.cxx
Comment thread Rendering/OpenXR/vtkOpenXRRenderWindow.h Outdated
Comment thread Rendering/OpenXR/vtkOpenXRRenderWindow.h Outdated
Comment thread Rendering/OpenXR/vtkOpenXRManager.cxx

@lassoan lassoan left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Sunderlandkyl this will be great, but some of the Copilot findings seem to be valid. Please review them and update the code if needed. Thank you!

@Sunderlandkyl

Copy link
Copy Markdown
Member Author

Thanks @lassoan, I will take a look at them today.

@Sunderlandkyl

Copy link
Copy Markdown
Member Author

I added the fixes from the review. For some reason when passthrough is enabled, only the back-faces of the mesh seem to be visible. I'm looking into it.

@Sunderlandkyl

Copy link
Copy Markdown
Member Author

Some more context with the issue:

  • If rendering is enabled with occlusion occluded opacity 1.0, then the front-faces are rendered correctly, however the slider doesn't change the occluded opacity anymore.
  • If rendering is enabled with occluded opacity < 1.0, then only the back-faces are visible, and the slider works as expected.

@lassoan

lassoan commented Jun 21, 2026

Copy link
Copy Markdown

@Sunderlandkyl is this ready to be merged?

@Sunderlandkyl

Copy link
Copy Markdown
Member Author

Couple of things.

  1. I haven't been able to fix the occlusion issue yet. If we don't enable occlusion from the GUI then pass-through still works as intended.
  2. I created a build on a different computer (laptop) and ran into a crash when enabling VR. This seems to happen with the latest nightly build as well however so it doesn't seem to be connected.

@Sunderlandkyl

Copy link
Copy Markdown
Member Author

@lassoan To actually answer your question, yes it can be merged on the understanding that the environmental occlusion support will need to be fixed later.

Should this PR be moved on a new branch, or integrated onto this one?

@lassoan lassoan left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks good to me, AR works well on Meta Quest 3 (except depth-based occlusion), so this is ready to go. Please also submit these commits to VTK upstream, too.

@lassoan lassoan merged commit 6181bb1 into Slicer:slicer-v9.6.2-2026-05-15-f49a1dbaf Jun 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants