Develop

Surface Projected Passthrough

Updated: Apr 15, 2026
Surface-projected passthrough allows apps to specify the geometry onto which the passthrough images are projected (instead of an automatic environment depth reconstruction). For surface-projected passthrough layers, passthrough is only visible within the specified surface geometries, the rest of the layer is transparent.
Surface-projected passthrough can be used when the exact locations of real-world features are known (for example, a desk marked by the user using controllers) to avoid visual artifacts that may arise from the dynamic environment reconstruction used by regular passthrough layers. The surface geometries provided by the app should match real-world surfaces as closely as possible. If they differ significantly, users will receive conflicting depth cues, and objects may appear too small or large. On Quest Pro, such mismatches also lead to a shift between the color and luminance images, making colored objects appear in the wrong location.
There is no depth testing between the passthrough projection surface and the objects rendered in VR. This leads to surface-projected passthrough rendering either as an underlay (always occluded by virtual objects) or overlay (always occludes virtual objects).
:::caution Deprecated API
UOculusXRPassthroughLayerComponent, UOculusXRStereoLayerShapeUserDefined, and the AddSurfaceGeometry Blueprint are all deprecated as of Unreal Engine 5.6. The replacement methods AddStaticSurfaceGeometry and AddProceduralSurfaceGeometry exist but are only accessible through the deprecated UOculusXRPassthroughLayerComponent. The persistent passthrough system (UOculusXRPersistentPassthroughInstance) does not currently support surface-projected passthrough.
For non-surface-projected use cases, use persistent passthrough instead.
:::

Add surface geometry

Add a static mesh component to the passthrough layer with the Add Surface Geometry Blueprint.
Add Surface Geometry Blueprint
The original AddSurfaceGeometry method accepted an AStaticMeshActor* and is now deprecated. Use the replacement methods instead:
  • AddStaticSurfaceGeometry(UStaticMeshComponent*, bool updateTransform) for static meshes.
  • AddProceduralSurfaceGeometry(UProceduralMeshComponent*, bool updateTransform) for procedural meshes.
To remove a mesh component from the passthrough layer, use the corresponding removal methods:
  • RemoveStaticSurfaceGeometry(UStaticMeshComponent*) for static meshes.
  • RemoveProceduralSurfaceGeometry(UProceduralMeshComponent*) for procedural meshes.
Both replacement methods accept a mesh component (UStaticMeshComponent* or UProceduralMeshComponent*) rather than an Actor.
If updateTransform is false, the geometry of the mesh is assumed to be static and updates to either the geometry or the transformation are not reflected. If updateTransform is true, the transformation is updated every frame. Since this has a small overhead, set it to true only when needed. Changes to the mesh geometry itself are not reflected. The mesh component needs to be removed from the passthrough layer and re-added for such changes to take effect.

Configure underlay or overlay rendering

Control whether a surface-projected passthrough layer renders as underlay or overlay by setting the layer order on UOculusXRPassthroughLayerComponent:
  • Set the layer to underlay if virtual objects should appear on top of passthrough surfaces. Passthrough renders behind all virtual content.
  • Set the layer to overlay if the passthrough surface should occlude virtual content. Passthrough renders in front of all virtual objects.
There is no depth testing between the passthrough projection surface and objects rendered in VR. The layer order determines the rendering mode entirely.