reckfellENGINE

visionOS: immersive rendering and tracking

Application role, Metal/Mobile, tracking authorization, near plane and export limitations.

On this page

visionOS: immersive rendering and tracking

Reckfell has a native visionOS XR module using Metal, Compositor Services and ARKit. It is a platform-specific integration, separate from OpenXR and browser WebXR. Its registered interface name is visionOS, with that exact casing.

Current C# limitation: the C# exporter in 1.0.0 does not implement visionOS as a target. The VisionOSXRInterface reference is source-only in the installed Windows SDK. A native visionOS exporter/module in source does not establish a working C# export, signed application or device build. Validate your template, scripting configuration and Apple toolchain before committing to this target.

Configure the application mode first

The export preset contains application/app_role: Window=0 or Immersive=1. The default is Window. Adding an XROrigin3D does not turn a windowed application into a Compositor Services application.

For the immersive path, select Immersive and configure application/immersion_style: Full=0, Mixed=1 or Progressive=2; the preset default is Mixed. The Swift layer and export metadata must agree with the intended application role. Full replaces the surroundings; Mixed blends virtual content with them. Progressive is a separate immersion choice, not dynamic render quality.

The current Compositor Services path requires the Metal driver. Display-server code changes Forward+ to Mobile in this mode. Configure and assess the scene with Mobile rather than relying on desktop-only Forward+ effects. A simulator or desktop preview is not evidence of device rendering.

The Swift compositor config selects rgba16Float color, depth32Float_stencil8 depth and layered layout. It enables foveation if the device capabilities support it; a missing layered layout is a fatal configuration condition. These are platform decisions, not instructions to create and free the compositor's textures yourself.

Scene and startup

Use the XR scene setup for the origin/camera hierarchy and XR shaders. The minimal hierarchy is:

Text
XROrigin3D
└── XRCamera3D

On the native visionOS target, find the registered visionOS interface through XRServer. Keep one owner for initialization and viewport state; do not initialize OpenXR alongside it. Retain the original viewport configuration so it can be restored on a failed start or exit.

For the immersive viewport, configure UseXR, UseHdr2D and XR VRS deliberately. The platform exposes a rasterization-rate-map VRS format, not a hand-authored ordinary shading-rate texture. Use the active XRCamera3D for projection and verify it is the viewport's current camera.

Initialize returning true does not prove granted tracking permissions, a valid pose or a displayed stereo frame. Current initialization starts ARKit and requests hand/accessory authorization asynchronously. It also calls CompositorServicesData.initialize without checking that function's boolean result. Inspect native errors and actual frame/tracking readiness; do not use Initialize alone as an acceptance test. This is a source observation, not an engine fix or reproduced device failure.

Hand and controller tracking

Both project settings default to false:

Project settingExport privacy text
xr/visionos/enable_hand_trackingprivacy/hand_tracking_usage_description → NSHandsTrackingUsageDescription
xr/visionos/enable_controller_trackingprivacy/accessory_tracking_usage_description → NSAccessoryTrackingUsageDescription

Enable only the tracking your application uses and explain its purpose in the corresponding export field. A checked setting and a created tracker do not establish authorization: providers become active only when enabled and allowed. Denial is reported in native logs; offer an input fallback instead of leaving the user unable to continue.

Hand trackers use /user/hand_tracker/left and /user/hand_tracker/right. Bind XRHandModifier3D to the intended hand and check current tracking/joint validity before driving gameplay. A modifier or visible hand mesh is not proof of current ARKit data. Controllers use a separate accessory-tracking path; do not treat any connected gamepad as a tracked spatial controller automatically. Borrowed provider trackers must not be Free/Dispose'd by gameplay.

Near plane and world scale

The engine reads supportedMinimumNearPlaneDistance from layer capabilities. Its projection guard checks:

camera Near / XRServer.WorldScale >= platform minimum

Choose a positive world scale and allow a small numerical margin. For a platform minimum of 0.1 m and WorldScale=2, Near=0.201 satisfies the condition; Near=0.1 does not. The 0.1 value is an example, not a universal capability constant. Check the actual current camera: changing an unused camera will not fix projection errors.

Mixed immersion: alpha and depth together

Compositor Services combines color and depth, using premultiplied alpha and reverse-Z conventions. For a transparent mixed background, begin with black RGB and alpha 0; colored RGB at alpha 0 is not a safe transparent-background recipe. Opaque virtual surfaces need valid depth. See Apple's Metal passthrough explanation.

Do not repair missing content by forcing every transparent particle or invisible surface to write opaque depth: that can produce incorrect composition and occlusion. Isolate the problem with an opaque object, then test the material's color, alpha, depth write and background together.

The old depth-only full-screen shader was incomplete without mesh, priority and culling configuration and was not validated on this target. This guide does not present it as a ready fix. If an opaque virtual sky is needed, assess its depth-producing background on the actual device; black transparent background and a visible virtual sky are different requirements.

Quality and diagnosis

xr/visionos/dynamic_render_quality/enable defaults to false; maximum_quality defaults to 0.38. Runtime CurrentRenderQuality requires dynamic quality enabled and must not exceed that configured maximum. It is not a promise of FPS, antialiasing or acceptable image quality. Raise quality only after measuring device frame time and inspecting both eyes.

SymptomFirst check
No visionOS interface on WindowsPlatform-gated module and source-only reference; not a missing project Entity.
C# export rejectedCurrent C# target support; a native export preset does not add managed runtime support.
App opens in a windowapplication/app_role and exported application metadata.
Startup errors or no immersive frameMetal driver, layer renderer/capabilities, native errors and actual current camera.
Projection rejectedNear divided by WorldScale against the reported minimum.
Hands remain static or absentBoth enable setting and authorization, current provider data and modifier binding.
Halos, missing sky or particlesPremultiplied color/alpha, depth and the actual immersion style.
Runtime quality setter failsDynamic quality enabled and requested value within the configured maximum.
Freeze or termination during loadingDevice logs and frame stalls, resource/shader preparation and a launch without a debugger; do not assume one universal timeout.

Verification scope

This guide was reviewed against current module, export, compositor, projection, authorization and C# exporter source. Platform build-gate truth cases were executed as Python configuration logic only. No visionOS native code, Apple toolchain, simulator, signing, C# export, headset, permissions, render output or frame performance was executed here. No ready-to-run device sample or illustrative capture is claimed. Engine Source, Runtime 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.