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
- Error “Shader error in 'YSCloudCover': call to 'tex3D' is ambiguous at Assets/YSCloudCoverText.shader(606) (on d3d11)“ is present when compiling tex3D shader with DXC
- Placeholder asset is not loaded with Advertisement Legacy sample when using the latest version of the package
- Addressables content build fails but the Player build is successful when building a development build
- Out-of-bounds memory access with multiple CanvasRenderers under a Canvas when using Mesh API
- Inspector tries to access file after it was deleted when the file was locked in Inspector window
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!