Singularity/Library/PackageCache/com.unity.render-pipelines..../Runtime/Passes/MotionVectorRenderPass.cs

174 lines
6.6 KiB
C#
Raw Permalink Normal View History

2024-05-06 14:45:45 -04:00
using System;
using UnityEngine.Experimental.Rendering;
namespace UnityEngine.Rendering.Universal.Internal
{
sealed class MotionVectorRenderPass : ScriptableRenderPass
{
#region Fields
const string kPreviousViewProjectionMatrix = "_PrevViewProjMatrix";
#if ENABLE_VR && ENABLE_XR_MODULE
const string kPreviousViewProjectionMatrixStero = "_PrevViewProjMStereo";
#endif
const string kMotionVectorTexture = "_MotionVectorTexture";
const GraphicsFormat m_TargetFormat = GraphicsFormat.R16G16_SFloat;
static readonly string[] s_ShaderTags = new string[] { "MotionVectors" };
RenderTargetHandle m_MotionVectorHandle; //Move to UniversalRenderer like other passes?
readonly Material m_CameraMaterial;
readonly Material m_ObjectMaterial;
PreviousFrameData m_MotionData;
ProfilingSampler m_ProfilingSampler = ProfilingSampler.Get(URPProfileId.MotionVectors);
#endregion
#region Constructors
internal MotionVectorRenderPass(Material cameraMaterial, Material objectMaterial)
{
renderPassEvent = RenderPassEvent.AfterRenderingSkybox;
m_CameraMaterial = cameraMaterial;
m_ObjectMaterial = objectMaterial;
}
#endregion
#region State
internal void Setup(PreviousFrameData frameData)
{
m_MotionData = frameData;
}
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
{
var rtd = cameraTextureDescriptor;
rtd.graphicsFormat = m_TargetFormat;
// Configure Render Target
m_MotionVectorHandle.Init(kMotionVectorTexture);
cmd.GetTemporaryRT(m_MotionVectorHandle.id, rtd, FilterMode.Point);
ConfigureTarget(m_MotionVectorHandle.Identifier(), m_MotionVectorHandle.Identifier());
}
#endregion
#region Execution
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
if (m_CameraMaterial == null || m_ObjectMaterial == null)
return;
// Get data
ref var cameraData = ref renderingData.cameraData;
Camera camera = cameraData.camera;
MotionVectorsPersistentData motionData = null;
if (camera.TryGetComponent<UniversalAdditionalCameraData>(out var additionalCameraData))
motionData = additionalCameraData.motionVectorsPersistentData;
if (motionData == null)
return;
// Never draw in Preview
if (camera.cameraType == CameraType.Preview)
return;
// Profiling command
CommandBuffer cmd = CommandBufferPool.Get();
using (new ProfilingScope(cmd, m_ProfilingSampler))
{
int passID = motionData.GetXRMultiPassId(ref cameraData);
ExecuteCommand(context, cmd);
#if ENABLE_VR && ENABLE_XR_MODULE
if (cameraData.xr.enabled && cameraData.xr.singlePassEnabled)
{
m_CameraMaterial.SetMatrixArray(kPreviousViewProjectionMatrixStero, m_MotionData.previousViewProjectionMatrixStereo);
m_ObjectMaterial.SetMatrixArray(kPreviousViewProjectionMatrixStero, m_MotionData.previousViewProjectionMatrixStereo);
}
else
#endif
{
Shader.SetGlobalMatrix(kPreviousViewProjectionMatrix, m_MotionData.previousViewProjectionMatrix);
}
// These flags are still required in SRP or the engine won't compute previous model matrices...
// If the flag hasn't been set yet on this camera, motion vectors will skip a frame.
camera.depthTextureMode |= DepthTextureMode.MotionVectors | DepthTextureMode.Depth;
// TODO: add option to only draw either one?
DrawCameraMotionVectors(context, cmd, camera);
DrawObjectMotionVectors(context, ref renderingData, camera);
}
ExecuteCommand(context, cmd);
CommandBufferPool.Release(cmd);
}
DrawingSettings GetDrawingSettings(ref RenderingData renderingData)
{
var camera = renderingData.cameraData.camera;
var sortingSettings = new SortingSettings(camera) { criteria = SortingCriteria.CommonOpaque };
var drawingSettings = new DrawingSettings(ShaderTagId.none, sortingSettings)
{
perObjectData = PerObjectData.MotionVectors,
enableDynamicBatching = renderingData.supportsDynamicBatching,
enableInstancing = true,
};
for (int i = 0; i < s_ShaderTags.Length; ++i)
{
drawingSettings.SetShaderPassName(i, new ShaderTagId(s_ShaderTags[i]));
}
// Material that will be used if shader tags cannot be found
drawingSettings.fallbackMaterial = m_ObjectMaterial;
return drawingSettings;
}
void DrawCameraMotionVectors(ScriptableRenderContext context, CommandBuffer cmd, Camera camera)
{
// Draw fullscreen quad
cmd.DrawProcedural(Matrix4x4.identity, m_CameraMaterial, 0, MeshTopology.Triangles, 3, 1);
ExecuteCommand(context, cmd);
}
void DrawObjectMotionVectors(ScriptableRenderContext context, ref RenderingData renderingData, Camera camera)
{
var drawingSettings = GetDrawingSettings(ref renderingData);
var filteringSettings = new FilteringSettings(RenderQueueRange.opaque, camera.cullingMask);
var renderStateBlock = new RenderStateBlock(RenderStateMask.Nothing);
// Draw Renderers
context.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref filteringSettings, ref renderStateBlock);
}
#endregion
#region Cleanup
public override void FrameCleanup(CommandBuffer cmd)
{
if (cmd == null)
throw new ArgumentNullException("cmd");
// Reset Render Target
if (m_MotionVectorHandle != RenderTargetHandle.CameraTarget)
{
cmd.ReleaseTemporaryRT(m_MotionVectorHandle.id);
m_MotionVectorHandle = RenderTargetHandle.CameraTarget;
}
}
#endregion
#region CommandBufer
void ExecuteCommand(ScriptableRenderContext context, CommandBuffer cmd)
{
context.ExecuteCommandBuffer(cmd);
cmd.Clear();
}
#endregion
}
}