URP Application Spacewarp is an optimization for OpenXR that helps applications maintain a high frame rate. Spacewarp synthesizes every other frame, which can reduce computational power and energy use considerably. The technique uses reprojection when synthesizing frames to reduce latency between the user’s movements and display updates.
Spacewarp can cause display artifacts and might require changes to your application for acceptable results.
Refer to the following topics for information about how to use spacewarp in your Unity project:
Topics | Description |
---|---|
Prerequisites | Lists the technical requirements needed to utilize spacewarp in Unity projects, including specific versions of Unity, OpenXR, URP, and other necessary components. |
Understand URP Application Spacewarp | Explains how spacewarp works by interpolating frames and describes associated buffers, limitations, and potential visual artifacts you might encounter. |
Application spacewarp workflow | Provides an overview of how to enable and configure spacewarp in Unity projects. |
Enable the OpenXR spacewarp feature in the Editor | Describes methods to enable spacewarp in Unity, either using the Meta SDK for Meta devices or a manual OpenXR feature configuration. |
Control spacewarp at runtime | Details how to control and manage the spacewarp feature at runtime. |
Choose shaders compatible with spacewarp | Lists the types of shadersA program that runs on the GPU. More info See in Glossary that are compatible with spacewarp. |
Modify custom shaders to support spacewarp | How to modify custom shaders to support spacewarp. |
Configure Materials for spacewarp | How to apply the spacewarp feature to specific Materials by toggling the XRAn umbrella term encompassing Virtual Reality (VR), Augmented Reality (AR) and Mixed Reality (MR) applications. Devices supporting these forms of interactive applications can be referred to as XR devices. More info See in Glossary Motion Vectors Pass (Space Warp) property. |
To use URP Application Spacewarp, your project must meet the following prerequisites:
Note: Refer to your device’s documentation and specifications to determine whether it supports the OpenXR XR_FB_space_warp extension. (You can also look at the Android logs from a device to make sure that the extension is enabled successfully when you test your app.)
URP Application Spacewarp synthesizes every other frame using data from previous frames. In addition to the standard eye buffer for the rendered sceneA Scene contains the environments and menus of your game. Think of each unique Scene file as a unique level. In each Scene, you place your environments, obstacles, and decorations, essentially designing and building your game in pieces. More info
See in Glossary, spacewarp requires a motion vector buffer and a depth bufferA memory store that holds the z-value depth of each pixel in an image, where the z-value is the depth for each rendered pixel from the projection plane. More info
See in Glossary. The URP XR Pass renders these to low resolution motion vector and depth buffers.
To synthesize a frame, spacewarp shifts pixelsThe smallest unit in a computer image. Pixel size depends on your screen resolution. Pixel lighting is calculated at every screen pixel. More info
See in Glossary from the previous rendered frame to a new, extrapolated position based on the motion vectors and depth. To decrease latency, the frame is reprojected using positional timewarp based on the latest available input pose.
Note: Positional timewarp is a more effective form of reprojection that uses the update pose along with depth information to both translate and rotate the final frame. Technically, positional timewarp is a different feature than application spacewarp. Meta headsets automatically turn on positional timewarp when application spacewarp is active. Other headsets might not.
For additional information about Application Spacewarp on Meta devices, refer to Application Spacewarp Developer Guide (Meta).
Application spacewarp can cause visual artifacts. You should evaluate whether the benefits of spacewarp outweigh observed problems.
If a moving object does not have motion vectors, then it can appear to stutter as it moves because its position is only updated in the rendered frames, not the synthesized frames. Still, there might be cases where things look better without spacewarp.
You can apply spacewarp to specific objects by changing the XR Motion Vectors Pass (Space Warp) property of their assigned Material. Objects with XR Motion Vectors Pass (Space Warp) disabled are not warped. Refer to Configure Materials for spacewarp for more information.
Unity also does not apply spacewarp to:
Spacewarp can cause artifacts when applied to transparent objects because the movement of objects behind a transparent object isn’t captured in the motion vector and depth buffers. The artifacts can be more obvious when close to the cameraA component which creates an image of a particular viewpoint in your scene. The output is either drawn to the screen or captured as a texture. More info
See in Glossary.
In some cases, you can mitigate artifacts related to transparency by rendering such content to a composition layer. However, spacewarp is not applied to composition layers, so animation within a layer might appear choppy.
Objects moving with a high apparent velocity can create noticeable artifacts. When spacewarp moves the pixels rendered for an object, the algorithm distorts the background to fill any empty areas left in the object’s wake. The more area an object covers and the farther it moves across the screen, the more likely this distortion will be noticeable. The characteristics of the background behind the object can also make a difference. For example a regular grid with straight lines might show the effects of the distortion more readily than a noisy texture. Objects that you “teleport” from one location to another can cause visual artifacts in the same manner.
In particular, you should evaluate the appearance of controller or hand graphics in your app. These are always close to the user, take up a large portion of the screen, and move at a high apparent velocity, all of which can accentuate spacewarp-related artifacts.
To enable and use URP Application Spacewarp in your project, complete the following steps:
You can enable URP Application Spacewarp in two ways:
If you are developing for the Meta platform and using Meta’s SDK packages already, use the Meta SDK to enable Application Spacewarp also.
If you are developing for a non-Meta headset that supports spacewarp or don’t want to add the Meta SDK packages and assets to your project, then you should use the manual method to add the OpenXR feature descriptor.
To enable Application Spacewarp when using the Meta SDK package:
Note: You must also enable the feature at runtime and for some XR platforms, including Meta, you must update the camera position and rotation every frame.
Note: In the past, a customized fork of URP was required to support the XR motion vector buffer required by Spacewarp. You no longer need to use this modified version as of URP 17.0.3.
To manually enable the URP Application Spacewarp feature, you must:
MetaSetSpaceWarp
, MetaSetAppSpacePosition
, and MetaSetAppSpaceRotation
functions from the UnityOpenXR dll library. (This library is part of the OpenXR package.)The example script performs the first two steps. When you include the script in your project, it adds the URP Application Spacewarp option to the OpenXR settings page.
The following script adds the feature descriptor and imports the required functions from the UnityOpenXR library:
using System.Runtime.InteropServices;
using UnityEditor;
using UnityEngine;
using UnityEngine.XR.OpenXR;
using UnityEngine.XR.OpenXR.Features;
#if UNITY_EDITOR
// OpenXR feature declaration.
[UnityEditor.XR.OpenXR.Features.OpenXRFeature(UiName = "URP Application Spacewarp",
Desc=@"URP Application Spacewarp feature",
Company = "Unity",
DocumentationLink = "",
OpenxrExtensionStrings = "XR_FB_space_warp",
Version = "1.0.0",
BuildTargetGroups = new []{BuildTargetGroup.Android},
FeatureId = featureId)]
#endif
public class SpacewarpFeature : OpenXRFeature
{
// The feature id string. This is used to give the feature a well known id for reference.
public const string featureId = "com.unity.openxr.feature.Spacewarp";
// Turn spacewarp on or off.
public static bool SetSpacewarp(bool enabled)
{
return MetaSetSpaceWarp(enabled);
}
// Update spacewarp for camera movement.
public static bool SetAppSpaceTransform(Vector3 position, Quaternion rotation)
{
return MetaSetAppSpacePosition(
position.x,
position.y,
position.z)
&&
MetaSetAppSpaceRotation(
rotation.x,
rotation.y,
rotation.z,
rotation.w);
}
// Import functions from the UnityOpenXR dll.
[DllImport("UnityOpenXR", EntryPoint = "MetaSetSpaceWarp")]
private static extern bool MetaSetSpaceWarp(bool enabled);
[DllImport("UnityOpenXR", EntryPoint = "MetaSetAppSpacePosition")]
private static extern bool MetaSetAppSpacePosition(float x, float y, float z);
[DllImport("UnityOpenXR", EntryPoint = "MetaSetAppSpaceRotation")]
private static extern bool MetaSetAppSpaceRotation(float x, float y, float z, float w);
}
Note: In the future, this technique of manually adding the spacewarp feature descriptor and importing the related functions from the OpenXR package libraries might be superseded in an update to the Unity OpenXR packages. You should keep your version of the SpacewarpFeature
class as simple as possible to make it easy to replace when this happens.
Once you have added this script to your project, enable spacewarp by adding a script to your scene that calls SetSpacewarp(true)
. Depending on your headset, you might need to also update Position and Rotation via the other two functions with the main camera’s position and rotation. Refer to your headset’s specifications to see whether it’s required.
In addition to enabling URP Application Spacewarp in your XR settings for the project, you must also turn spacewarp on at runtime.
To turn spacewarp on, call the SpacewarpFeature.SetSpacewarp
function defined in the SpacewarpFeature example script. Pass true
to enable spacewarp and false
to turn it off.
Note: If you’re using the Meta SDK, call OVRManager.SetSpaceWarp(true)
to turn on the spacewarp feature.
On Meta headsets, you must call functions to update the position and rotation of the main camera every frame. (See the documentation for your headset for other devices or if you are using the Meta SDK.)
If you are using the SpacewarpFeature example script, you can enable and control spacewarp by adding the following MonoBehaviour to your scene’s main Camera object:
using UnityEngine;
// Add to main scene camera
public class SpacewarpController : MonoBehaviour
{
void Start()
{
// Enable spacewarp when scene loads
SpacewarpFeature.SetSpacewarp(true);
}
void Update()
{
// Update spacewarp with camera position and rotation
SpacewarpFeature.SetAppSpaceTransform(transform.position, transform.rotation);
}
}
URP Application Spacewarp requires shaders that record XR motion vectors, which are used to predict the position of pixels in the extrapolated frames. If you use a shader that doesn’t record XR motion vectors, rendered objects that use it won’t update in the synthesized frames. These objects might appear to stutter because they are effectively rendered at half the framerate. Refer to Understand URP Application Spacewarp for information about how spacewarp works. The following URP base shaders are spacewarp compatible:
For Shadergraph, the following Material options for the Universal Graph Target are spacewarp compatible:
To enable your custom shaders to work with URP Application Spacewarp, you must add support for the XRMotionVectors render pass.
First, add the _XRMotionVectorsPass
property to your shader. This property allows you to enable spacewarp on a per-material basis. (Refer to Configure Materials for spacewarp for information about how it works with the URP shaders that support spacewarp.)
[HideInInspector] _XRMotionVectorsPass("_XRMotionVectorsPass", Float) = 1.0
Next, add the following shader subpass declaration:
Pass
{
Name "XRMotionVectors"
Tags { "LightMode" = "XRMotionVectors" }
ColorMask RGBA
// Stencil write for obj motion pixels
Stencil
{
WriteMask 1
Ref 1
Comp Always
Pass Replace
}
HLSLPROGRAM
#pragma shader_feature_local _ALPHATEST_ON
#pragma multi_compile _ LOD_FADE_CROSSFADE
#pragma shader_feature_local_vertex _ADD_PRECOMPUTED_VELOCITY
#define APPLICATION_SPACE_WARP_MOTION 1
#include "Packages/com.unity.render-pipelines.universal/Shaders/BakedLitInput.hlsl"
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ObjectMotionVectors.hlsl"
ENDHLSL
}
You can apply URP Application Spacewarp to specific objects by changing the XR Motion Vectors Pass (Space Warp) property of their assigned Material. You can find the XR Motion Vectors Pass (Space Warp) property in the Advanced Options section of the InspectorA Unity window that displays information about the currently selected GameObject, asset or project settings, allowing you to inspect and edit the values. More info
See in Glossary window for a Material. Objects with XR Motion Vectors Pass (Space Warp) disabled are not warped.
Tip: If the XR Motion Vectors Pass (Space Warp) option is disabled or missing, make sure that your Unity project meets the Prerequisites for using URP Application Spacewarp.