You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
173 lines
6.6 KiB
173 lines
6.6 KiB
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 |
|
} |
|
}
|
|
|