WuhuIslandTesting/Library/PackageCache/com.unity.render-pipelines.universal@8148.0.7-4/Runtime/PreviousFrameMatrices.cs
2025-01-07 02:06:59 +01:00

153 lines
5.4 KiB
C#

using System.Collections.Generic;
using UnityEngine;
namespace UnityEngine.Rendering.Universal.Internal
{
class PreviousFrameMatricies
{
#region Fields
static PreviousFrameMatricies s_Instance;
Dictionary<Camera, PreviousFrameData> m_CameraFrameData;
uint m_FrameCount;
float m_LastTime;
float m_Time;
#endregion
#region Constructors
private PreviousFrameMatricies()
{
m_CameraFrameData = new Dictionary<Camera, PreviousFrameData>();
}
public static PreviousFrameMatricies instance
{
get
{
if (s_Instance == null)
s_Instance = new PreviousFrameMatricies();
return s_Instance;
}
}
#endregion
#region RenderPass
public void Clear()
{
m_CameraFrameData.Clear();
}
public void SetPrevFrameGlobalsForCamera(Camera camera, CameraData camData)
{
// Get MotionData
PreviousFrameData motionData;
if (!m_CameraFrameData.TryGetValue(camera, out motionData))
{
motionData = new PreviousFrameData();
m_CameraFrameData.Add(camera, motionData);
//Debug.Log("New Camera");
}
// Calculate motion data
// CalculateTime();
UpdateMotionData(camera, camData, m_CameraFrameData[camera]);
}
#endregion
void CalculateTime()
{
// Get data
float t = Time.realtimeSinceStartup;
// SRP.Render() can be called several times per frame.
// Also, most Time variables do not consistently update in the Scene View.
// This makes reliable detection of the start of the new frame VERY hard.
// One of the exceptions is 'Time.realtimeSinceStartup'.
// Therefore, outside of the Play Mode we update the time at 60 fps,
// and in the Play Mode we rely on 'Time.frameCount'.
bool newFrame;
#if UNITY_EDITOR
if (!Application.isPlaying)
{
newFrame = (t - m_Time) > 0.0166f;
m_FrameCount += newFrame ? 1u : 0u;
}
else
#endif
{
uint frameCount = (uint)Time.frameCount;
newFrame = m_FrameCount != frameCount;
m_FrameCount = frameCount;
}
if (newFrame)
{
// Make sure both are never 0.
m_LastTime = (m_Time > 0) ? m_Time : t;
m_Time = t;
}
}
void UpdateMotionData(Camera camera, CameraData cameraData, PreviousFrameData motionData)
{
// The actual projection matrix used in shaders is actually massaged a bit to work across all platforms
// (different Z value ranges etc.)
// A camera could be rendered multiple times per frame, only updates the previous view proj & pos if needed
//bool update = motionData.lastFrameActive != Time.frameCount;
#if ENABLE_VR && ENABLE_XR_MODULE
if (cameraData.xr.enabled)
{
Matrix4x4 gpuProj0 = GL.GetGPUProjectionMatrix(cameraData.GetProjectionMatrix(0), true);
Matrix4x4 gpuProj1 = GL.GetGPUProjectionMatrix(cameraData.GetProjectionMatrix(1), true);
Matrix4x4 gpuView0 = cameraData.GetViewMatrix(0);
Matrix4x4 gpuView1 = cameraData.GetViewMatrix(1);
Matrix4x4 gpuVP0 = gpuProj0 * gpuView0;
Matrix4x4 gpuVP1 = gpuProj1 * gpuView1;
// Last frame data
//if (update)
{
bool firstFrame = motionData.isFirstFrame;
var prevViewProjStereo = motionData.previousViewProjectionMatrixStereo;
prevViewProjStereo[0] = firstFrame ? gpuVP0 : motionData.viewProjectionMatrixStereo[0];
prevViewProjStereo[1] = firstFrame ? gpuVP1 : motionData.viewProjectionMatrixStereo[1];
motionData.isFirstFrame = false;
}
// Current frame data
var viewProjStereo = motionData.viewProjectionMatrixStereo;
viewProjStereo[0] = gpuVP0;
viewProjStereo[1] = gpuVP1;
Shader.SetGlobalMatrixArray(ShaderPropertyId.prevViewMatStereoProp, motionData.previousViewProjectionMatrixStereo);
}
else
#endif
{
var gpuProj = GL.GetGPUProjectionMatrix(camera.projectionMatrix, true); // Had to change this from 'false'
var gpuView = camera.worldToCameraMatrix;
var gpuVP = gpuProj * gpuView;
// Last frame data
//if (update)
{
motionData.previousViewProjectionMatrix = motionData.isFirstFrame ? gpuVP : motionData.viewProjectionMatrix;
motionData.isFirstFrame = false;
}
// Current frame data
motionData.viewProjectionMatrix = gpuVP;
Shader.SetGlobalMatrix(ShaderPropertyId.prevViewMatProp, motionData.previousViewProjectionMatrix);
}
motionData.lastFrameActive = Time.frameCount;
}
}
}