Search Issue Tracker
By Design
Votes
0
Found in
6000.0.37f1
6000.1.0b5
6000.2.0a2
6000.3.0a1
Issue ID
UUM-96466
Regression
No
[XR] XR View Matrix in URP Has a One Frame Lag due to world-space transform deltas to leaking into the tracking-space computation
Steps to reproduce:
1. Open the attached user's project "TestURPTrackingSpaceShader.zip"
2. Open the "Assets/main.unity" Scene
3. Enter Play Mode
4. Notice that the white dots on the floor oscillate (See attached video URP_Repro.mov)
Expected Result: the white dots are stable
Actual Result: View Matrix has a misalignment with the camera, allowing world-space transform deltas to leak into the tracking-space computation, appearing like a one-frame lag
Reproducible with: 6000.0.37f1, 6000.1.0b5, 6000.2.0a2
Could not test 2021.3.48f1 and 2022.3.57f1 due to project errors after downgrading
Testing Environment: Windows 11
Not reproducible on: No other environment tested
Notes:
-To view how it works on Built-In RP, set the default render pipeline to None in Project Settings > Graphics. URP will be automatically set again on runtime every few seconds in MoveCam.cs.
-In BiRP, the customer is able to compute a correctly locked view matrix easily during LateUpdate (in the attached project, it’s in OverlayFx.cs:136)
-In URP, neither calling Camera.main.GetStereoViewMatrix from RenderPipelineManager.beginContextRendering nor cameraData.xr.GetViewMatrix using a custom pass on BeforeRenderingTransparents results in a stable view matrix.
Add comment
All about bugs
View bugs we have successfully reproduced, and vote for the bugs you want to see fixed most urgently.
Latest issues
- Crash on RaiseException when opening a specific project
- DownloadHandlerScript.CompleteContent is called twice when building for WebGL
- Scene view has Y coordinates of the Screen Position node flipped when some of the URP features are disabled
- Volumetric fog shader variants are missing from build when "Strict Shader Variant Matching" is disabled
- Unnecessary modifications clutter the Scene when using a RectTransform driven by a LayoutGroup in a Prefab
Resolution Note:
After the thorough investigation, we concluded that this case should be closed as by-design.
The `renderer.SetPropertyBlock` API sets up the custom properties that are synchronized with render node data during the culling phase. The current user code calls the API after the culling phase, so it would apply in the next frame.
I suggest using workarounds to either move the `renderer.SetPropertyBlock` before the culling step, or use command buffer APIs to set up the data(either global or local to drawcall).
Example of a command buffer workaround to set global custom properties:
// Add this function to OverlayFX.cs
public void RecordCmd(ref RasterCommandBuffer cmd, Matrix4x4 matViewLeft, Matrix4x4 matViewRight)
{
Vector3 leftEyeTracking = OverlayFx.Instance.GetEyePositionFromViewMatrixTracking(ref matViewLeft);
Vector3 rightEyeTracking = OverlayFx.Instance.GetEyePositionFromViewMatrixTracking(ref matViewRight);
Vector4[] _cameraInUnityTracking = new Vector4[2];
for (int i = 0; i < 2; ++i)
{
Vector3 eyePositionTracking = i == 0 ? leftEyeTracking : rightEyeTracking;
_cameraInUnityTracking[i] = new Vector4(eyePositionTracking.x, eyePositionTracking.y,
eyePositionTracking.z, 1.0f);
}
cmd.SetGlobalVectorArray(_trackingSpaceCameraPos, _cameraInUnityTracking);
cmd.SetGlobalMatrix(_unityTrackingFromUnityWorld, originTransform.worldToLocalMatrix);
}
// Update the code in OverlayFxPass.cs to call recordCmd function above
static void ExecutePass(PassData data, RasterGraphContext context)
{
UniversalCameraData cameraData = data.cameraData;
if (!cameraData.xr.enabled)
{
Debug.LogWarning("XR is not enabled, not rendering");
return;
}
Matrix4x4 matViewLeft = cameraData.xr.GetViewMatrix(0);
Matrix4x4 matViewRight;
if (cameraData.xr.viewCount > 1)
{
matViewRight = cameraData.xr.GetViewMatrix(1);
}
else
{
matViewRight = matViewLeft;
}
OverlayFx.Instance.UpdateVisualsWithViewMats(matViewLeft, matViewRight);
// calls the new cmd buffer code
OverlayFx.Instance.RecordCmd(ref context.cmd, matViewLeft, matViewRight);
}
If you have any further questions, please don't hesitate to let us know!