using UnityEngine; using UnityEngine.Rendering; namespace Rendering { [ExecuteAlways] [DisallowMultipleComponent] [RequireComponent(typeof(Camera))] public sealed class SpaceWarpShaderGlobals : MonoBehaviour { private static readonly int SpaceWarpCameraPositionId = Shader.PropertyToID("_SpaceWarpCameraPosition"); private static readonly int SpaceWarpPreviousCameraPositionId = Shader.PropertyToID("_SpaceWarpPreviousCameraPosition"); private static readonly int SpaceWarpCameraForwardId = Shader.PropertyToID("_SpaceWarpCameraForward"); private static readonly int SpaceWarpFrameTimeId = Shader.PropertyToID("_SpaceWarpFrameTime"); private static readonly int SpaceWarpTimeId = Shader.PropertyToID("_SpaceWarpTime"); [SerializeField] private bool _useUnscaledTime = true; private Camera _camera; private Vector3 _previousPosition; private bool _initialized; private void OnEnable() { _camera = GetComponent(); RenderPipelineManager.beginCameraRendering += HandleBeginCameraRendering; PushGlobals(true); } private void OnDisable() { RenderPipelineManager.beginCameraRendering -= HandleBeginCameraRendering; Shader.SetGlobalVector(SpaceWarpCameraPositionId, Vector4.zero); Shader.SetGlobalVector(SpaceWarpPreviousCameraPositionId, Vector4.zero); Shader.SetGlobalVector(SpaceWarpCameraForwardId, Vector4.zero); Shader.SetGlobalFloat(SpaceWarpFrameTimeId, 0f); Shader.SetGlobalFloat(SpaceWarpTimeId, 0f); _initialized = false; } private void HandleBeginCameraRendering(ScriptableRenderContext context, Camera camera) { if (camera != _camera) { return; } PushGlobals(false); } private void PushGlobals(bool resetPreviousPosition) { if (_camera == null) { _camera = GetComponent(); if (_camera == null) { return; } } Transform cameraTransform = _camera.transform; Vector3 currentPosition = cameraTransform.position; if (resetPreviousPosition || !_initialized) { _previousPosition = currentPosition; } float frameTime = Application.isPlaying ? (_useUnscaledTime ? Time.unscaledDeltaTime : Time.deltaTime) : Mathf.Max(Time.deltaTime, 1f / 60f); float timeValue = Application.isPlaying ? (_useUnscaledTime ? Time.unscaledTime : Time.time) : Time.realtimeSinceStartup; Vector3 forward = cameraTransform.forward; Shader.SetGlobalVector(SpaceWarpCameraPositionId, new Vector4(currentPosition.x, currentPosition.y, currentPosition.z, 1f)); Shader.SetGlobalVector(SpaceWarpPreviousCameraPositionId, new Vector4(_previousPosition.x, _previousPosition.y, _previousPosition.z, 1f)); Shader.SetGlobalVector(SpaceWarpCameraForwardId, new Vector4(forward.x, forward.y, forward.z, 1f)); Shader.SetGlobalFloat(SpaceWarpFrameTimeId, Mathf.Max(frameTime, 0.0001f)); Shader.SetGlobalFloat(SpaceWarpTimeId, timeValue); _previousPosition = currentPosition; _initialized = true; } } }