Search Issue Tracker

Won't Fix

Votes

2

Found in

2022.3.55f1

6000.0.34f1

6000.1.0b2

6000.2.0a1

Issue ID

UUM-92586

Regression

No

Global shader variables _Time and _TimeParameters do not reset when a Scene is loaded in URP

-

Reproduction steps:
1. Open the attached “BugShaderTime.zip” project
2. Open the “Assets/Scenes/SampleScene.unity“ Scene
3. Enter the Play Mode
4. Observe than _Time.y, _TimeParameters.x and Time.timeSinceLevelLoad have identical values
5. Press the "Reload Scene" button in the Game view
6. Observe the Game view

Expected result: _Time.y, _TimeParameters.x and Time.timeSinceLevelLoad have identical values
Actual result: _Time.y, _TimeParameters.x and Time.timeSinceLevelLoad do not have identical values

Reproducible with: 2022.3.55f1, 6000.0.34f1, 6000.1.0b2

Reproducible on: Windows 11
Not reproducible on: No other environment tested

Notes:

* Reproducible in the Player
* Not reproducible when using built-in RP
* Link to discussions: [https://discussions.unity.com/t/in-92796-global-shader-variables-time-and-timeparameters-appear-to-be-wrong/1582822/2|https://discussions.unity.com/t/in-92796-global-shader-variables-time-and-timeparameters-appear-to-be-wrong/1582822/2|smart-link]

  1. Resolution Note:

    Hello.

    It is correct that _Time is not Time.timeSinceLevelLoad but instead Time.time in URP/HDRP and that the documentation does not reflect this. We will update the documentation, but unfortunately we cannot change the behavior at this point, because it would be a breaking change for users that rely on the current behavior.

    However I can provide you with this ScriptableRendererFeature that use can use in your project to override the variables, so it behaves like it does in the built in render pipeline:

    ```
    using Unity.Mathematics;
    using UnityEngine;
    using UnityEngine.Rendering;
    using UnityEngine.Rendering.Universal;
    using UnityEngine.Rendering.RenderGraphModule;

    public class ShaderTimeOverride : ScriptableRendererFeature
    {
    ShaderTimeOverridePass m_ScriptablePass;

    public override void Create()
    {
    m_ScriptablePass = new ShaderTimeOverridePass
    {
    renderPassEvent = RenderPassEvent.BeforeRenderingPrePasses
    };
    }

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
    renderer.EnqueuePass(m_ScriptablePass);
    }

    class ShaderTimeOverridePass : ScriptableRenderPass
    {
    // Shader properties:
    static readonly int timeNameID = Shader.PropertyToID("_Time");
    static readonly int sinTimeNameID = Shader.PropertyToID("_SinTime");
    static readonly int cosTimeNameID = Shader.PropertyToID("_CosTime");
    static readonly int deltaTimeNameID = Shader.PropertyToID("unity_DeltaTime");
    static readonly int timeParametersNameID = Shader.PropertyToID("_TimeParameters");
    static readonly int lastTimeParametersNameID = Shader.PropertyToID("_LastTimeParameters");

    float savedTimeLastFrame;

    private class PassData
    {
    public Vector4 timeVector;
    public Vector4 sinTimeVector;
    public Vector4 cosTimeVector;
    public Vector4 deltaTimeVector;
    public Vector4 timeParametersVector;
    public Vector4 lastTimeParametersVector;
    }

    static void Execute(PassData data, UnsafeGraphContext rgContext)
    {
    UnsafeCommandBuffer cmd = rgContext.cmd;

    cmd.SetGlobalVector(timeNameID, data.timeVector);
    cmd.SetGlobalVector(sinTimeNameID, data.sinTimeVector);
    cmd.SetGlobalVector(cosTimeNameID, data.cosTimeVector);
    cmd.SetGlobalVector(deltaTimeNameID, data.deltaTimeVector);
    cmd.SetGlobalVector(timeParametersNameID, data.timeParametersVector);
    cmd.SetGlobalVector(lastTimeParametersNameID, data.lastTimeParametersVector);
    }

    public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
    {
    const string passName = "Override Shader Time";

    using (var builder = renderGraph.AddUnsafePass<PassData>(passName, out var passData))
    {
    builder.AllowPassCulling(false);

    float time = Time.timeSinceLevelLoad; // <-- Uses Time.timeSinceLevelLoad instead of Time.time!
    float deltaTime = Time.deltaTime;
    float smoothDeltaTime = Time.smoothDeltaTime;
    float timeLastFrame = savedTimeLastFrame;

    float timeEights = time / 8f;
    float timeFourth = time / 4f;
    float timeHalf = time / 2f;

    float sinTime = math.sin(time);
    float cosTime = math.cos(time);

    passData.timeVector = time * new Vector4(1f / 20f, 1f, 2f, 3f);
    passData.sinTimeVector = new Vector4(math.sin(timeEights), math.sin(timeFourth), math.sin(timeHalf), sinTime);
    passData.cosTimeVector = new Vector4(math.cos(timeEights), math.cos(timeFourth), math.cos(timeHalf), cosTime);
    passData.deltaTimeVector = new Vector4(deltaTime, 1f / deltaTime, smoothDeltaTime, 1f / smoothDeltaTime);
    passData.timeParametersVector = new Vector4(time, sinTime, cosTime, 0.0f);
    passData.lastTimeParametersVector = new Vector4(timeLastFrame, math.sin(timeLastFrame), math.cos(timeLastFrame), 0.0f);

    savedTimeLastFrame = time;

    builder.SetRenderFunc((PassData data, UnsafeGraphContext rgContext) => Execute(data, rgContext));
    }
    }
    }
    }
    ```

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.