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.

  1. 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!

Add comment

Log in to post comment

All about bugs

View bugs we have successfully reproduced, and vote for the bugs you want to see fixed most urgently.