reckfellENGINE

XR passthrough and transparent backgrounds

Composition modes, capability checks, rejection without background changes and state restoration.

On this page

XR passthrough and transparent backgrounds

Passthrough allows virtual output to be composited with an environment provided by the XR runtime. On a video device this can be camera imagery; on a see-through device it is the optical environment. Implementation and permissions depend on the platform. This mode itself gives the game no camera frames, room geometry or real-world lighting data.

First configure XR startup and check interface initialization. An OpenXRInterface and a saved project setting do not establish an active session or passthrough availability.

Choose the composition mode

C# modeResult
XRInterface.EnvironmentBlendModeEnum.OpaqueOpaque virtual output. Use only if supported.
XRInterface.EnvironmentBlendModeEnum.AdditiveVirtual light is added to the environment. Black adds no light; it is not equivalent to opaque black coverage.
XRInterface.EnvironmentBlendModeEnum.AlphaBlendOutput transparency participates in composition. A visible environment requires a transparent Viewport background and suitable materials.

Obtain the list through GetSupportedEnvironmentBlendModes(), test membership of the requested value and check SetEnvironmentBlendMode() success. The EnvironmentBlendMode property setter returns no success result; the method lets you handle rejection.

Do not use IsPassthroughSupported as an availability check in the current build. This C# method is already obsolete. The OpenXR implementation returns an Array.find index as bool: an empty list yields −1, which becomes true, while a match at index 0 becomes false. Installed-runtime testing reproduced true for an empty list without initialization. The engine defect was not fixed; the example below avoids it by checking list membership. Other obsolete methods IsPassthroughEnabled, StartPassthrough and StopPassthrough are unnecessary for new code too.

Switch without making the window transparent on rejection

C#
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;
    }
}

Call the helper on the main thread after successful XR startup. Supply the borrowed interface from XRServer.FindInterface("OpenXR") and the actual XR-rendering Viewport. For alpha, select AlphaBlend and transparentBackground=true. A false return means rejection: do not hide the normal background or report that MR is active.

Before switching, retain xr.GetEnvironmentBlendMode() and viewport.TransparentBg. To restore, pass those values to TryApply. Check restoration success too: if the interface is already uninitialized, the helper changes nothing. To switch specifically to VR, request Opaque and false after checking support. Do not blindly call StopPassthrough: its implementation simply requests Opaque without reporting rejection.

The helper neither initializes a device, enables Viewport.UseXR, grants permissions nor edits Environment. IsInitialized does not replace session focus/running checks; handle state events separately. It disposes only the returned mode-list container. Do not Dispose the interface, Viewport or other borrowed objects. One component should own transitions: competing switches can overwrite the mode and background state.

Configure the scene

  1. For AlphaBlend, enable TransparentBg after the mode request is accepted. Opaque geometry and materials still cover the environment: background alpha does not make the whole world transparent.
  2. For Additive, use a black background when it should contribute no light. Alpha transparency is not a universal additive-output setting.
  3. Light virtual objects separately through WorldEnvironment, ambient light, IBL and lights. Camera imagery does not automatically become a sky, light source or reflection environment.
  4. Inspect CanvasLayer, UI and fullscreen materials. An opaque overlay can obscure the environment even with the correct blend mode.

OpenXR's startup request is xr/openxr/environment_blend_mode. If unsupported, code can select the first available mode; check the result after startup. See the settings reference. A platform implementation can also emulate alpha through a separate passthrough layer with another internal composition mode. The interface getter reports the requested mode, not proof of camera-image delivery.

If the device needs additional platform integration, configure the implementation you actually use: permissions, manifest/export options and passthrough support. This guide assumes no installed vendor plugin and promises no arbitrary-version compatibility. Do not disable the system boundary for a demonstration: passthrough replaces neither physical safety nor tracking-loss handling.

Shadows and real-environment occlusion

The spatial-shader mode shadow_to_opacity exists for AR materials. The mode itself detects no table, wall or hand: alignment needs geometry correctly positioned in tracking space. Obtaining that geometry is a separate task.

Account for depth writes as well as color/alpha when configuring the material: a visually transparent surface can still occlude virtual geometry behind it. Check the renderer, lighting, shadow map and both eyes separately. This guide supplies no unverified real-table shadow demonstration; physical composition and shadow_to_opacity quality were not tested in this run.

Diagnosis

SymptomCheck
Support is reported but the list is emptyAvoid legacy IsPassthroughSupported; require IsInitialized and AlphaBlend membership.
Black background instead of the environmentActual mode, SetEnvironmentBlendMode success, TransparentBg on the correct Viewport, runtime and platform integration.
Part of the scene obscures the environmentOpaque materials, sky/overlay/UI and composition order.
Virtual objects are darkLights and WorldEnvironment; camera imagery provides no automatic IBL.
Disabling does not restore the prior viewSaved mode and TransparentBg, session state and reverse TryApply result.
A virtual surface does not align with the real oneOrigin space, scale, tracking and geometry source; blend mode does not fix these.

Verification scope

Installed Reckfell 1.0.0, Windows, headless with XR off ran 17 observations: empty/nonmatching mode lists, alpha at different indices, null checks, a real uninitialized OpenXRInterface and preservation of both TransparentBg states on rejection. The legacy support-flag defect was reproduced, so its separate acceptance remains unsuccessful. Passing helper checks do not conceal it.

Successful hardware enabling/restoration, video/optics, permissions, vendor plugins, alpha composition, shadows, image quality and export were not tested. Check those transitions, focus and both eyes on the target headset. Engine source and SDK were unchanged.

Reckfell Engine documentationBack to top ↑
QUICK LINKSGetting startedEntity hierarchyC# & .NET 10Scenes and prefabs
Reckfell guides and full API K
reckfellENGINE
RECKFELL ACCOUNT

Sign in

Sign in to your Reckfell account.

One account for the entire Reckfell platform.