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
- Unity CIL Linker fails on Player build when persistent listeners have "<" and ">" in their XML attribute names
- ”Lighting data asset ‘LightingData’ is incompatible with the current Unity version…” warnings are thrown when saving Indoors (URP) and Outdoors (URP) Scenes as Scene Templates
- [iOS] The screen blinks when transitioning from custom to Unity splash screen
- [macOS] ”Ignoring depth surface load action as it is memoryless” warnings are thrown when taking Game View Snapshot
- UI Builder Inspector scrolls back up when changes on an expanded but not fully displayed Inspector tab are saved
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!