123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- #if ENABLE_VR && ENABLE_XR_MODULE
- using System;
- using UnityEngine.Experimental.Rendering;
- using UnityEngine.Rendering.RenderGraphModule;
-
- namespace UnityEngine.Rendering.Universal
- {
- /// <summary>
- /// Render all objects that have a 'XRMotionVectors' pass into the given depth buffer and motionvec buffer.
- /// </summary>
- public class XRDepthMotionPass : ScriptableRenderPass
- {
- private static readonly ShaderTagId k_MotionOnlyShaderTagId = new ShaderTagId("XRMotionVectors");
- private PassData m_PassData;
- private RTHandle m_XRMotionVectorColor;
- private TextureHandle xrMotionVectorColor;
- private RTHandle m_XRMotionVectorDepth;
- private TextureHandle xrMotionVectorDepth;
-
- /// <summary>
- /// Creates a new <c>XRDepthMotionPass</c> instance.
- /// </summary>
- /// <param name="evt">The <c>RenderPassEvent</c> to use.</param>
- /// <param name="xrMotionVector">The Shader used for rendering XR camera motion vector.</param>
- /// <seealso cref="RenderPassEvent"/>
- public XRDepthMotionPass(RenderPassEvent evt, Shader xrMotionVector)
- {
- base.profilingSampler = new ProfilingSampler(nameof(XRDepthMotionPass));
- m_PassData = new PassData();
- renderPassEvent = evt;
- ResetMotionData();
- m_XRMotionVectorMaterial = CoreUtils.CreateEngineMaterial(xrMotionVector);
- xrMotionVectorColor = TextureHandle.nullHandle;
- m_XRMotionVectorColor = null;
- xrMotionVectorDepth = TextureHandle.nullHandle;
- m_XRMotionVectorDepth = null;
- }
-
- private class PassData
- {
- internal RendererListHandle objMotionRendererList;
- internal Matrix4x4[] previousViewProjectionStereo = new Matrix4x4[k_XRViewCount];
- internal Matrix4x4[] viewProjectionStereo = new Matrix4x4[k_XRViewCount];
- internal Material xrMotionVector;
- }
-
- /// View projection data
- private const int k_XRViewCount = 2;
- private Matrix4x4[] m_ViewProjection = new Matrix4x4[k_XRViewCount];
- private Matrix4x4[] m_PreviousViewProjection = new Matrix4x4[k_XRViewCount];
- private int m_LastFrameIndex;
-
- // Motion Vector
- private Material m_XRMotionVectorMaterial;
-
- private static DrawingSettings GetObjectMotionDrawingSettings(Camera camera)
- {
- var sortingSettings = new SortingSettings(camera) { criteria = SortingCriteria.CommonOpaque };
- // Notes: Usually, PerObjectData.MotionVectors will filter the renderer nodes to only draw moving objects.
- // In our case, we use forceAllMotionVectorObjects in the filteringSettings to draw idle objects as well to populate depth.
- var drawingSettings = new DrawingSettings(k_MotionOnlyShaderTagId, sortingSettings)
- {
- perObjectData = PerObjectData.MotionVectors,
- enableDynamicBatching = false,
- enableInstancing = true,
- };
- drawingSettings.SetShaderPassName(0, k_MotionOnlyShaderTagId);
-
- return drawingSettings;
- }
-
- private void InitObjectMotionRendererLists(ref PassData passData, ref CullingResults cullResults, RenderGraph renderGraph, Camera camera)
- {
- var objectMotionDrawingSettings = GetObjectMotionDrawingSettings(camera);
-
- // XRTODO: Extend RenderQueueRange.all to support transparent objects?
- // URP current' doesn't support this, missing motion override for transparent materials.
- var filteringSettings = new FilteringSettings(RenderQueueRange.opaque, camera.cullingMask);
- // Also render game objects that are not moved since last frame to save depth prepass requirement for camera motion.
- filteringSettings.forceAllMotionVectorObjects = true;
- var renderStateBlock = new RenderStateBlock(RenderStateMask.Nothing);
-
- RenderingUtils.CreateRendererListWithRenderStateBlock(renderGraph, ref cullResults, objectMotionDrawingSettings, filteringSettings, renderStateBlock, ref passData.objMotionRendererList);
- }
-
- /// <summary>
- /// Initialize the RenderGraph pass data.
- /// </summary>
- /// <param name="passData"></param>
- private void InitPassData(ref PassData passData, UniversalCameraData cameraData)
- {
- // XRTODO: Use XRSystem prevViewMatrix that is compatible with late latching. Currently blocked due to late latching engine side issue.
- //var gpuP0 = GL.GetGPUProjectionMatrix(cameraData.xr.GetProjMatrix(0), false);
- //var gpuP1 = GL.GetGPUProjectionMatrix(cameraData.xr.GetProjMatrix(1), false);
- //passData.viewProjectionStereo[0] = gpuP0 * cameraData.xr.GetViewMatrix(0);
- //passData.viewProjectionStereo[1] = gpuP1 * cameraData.xr.GetViewMatrix(1);
- //passData.previousViewProjectionStereo[0] = gpuP0 * cameraData.xr.GetPrevViewMatrix(0);
- //passData.previousViewProjectionStereo[1] = gpuP0 * cameraData.xr.GetPrevViewMatrix(1);
-
- // Setup matrices and shader
- passData.previousViewProjectionStereo = m_PreviousViewProjection;
- passData.viewProjectionStereo = m_ViewProjection;
-
- // Setup camera motion material
- passData.xrMotionVector = m_XRMotionVectorMaterial;
- }
-
- /// <summary>
- /// Import the XR motion color and depth targets into the RenderGraph.
- /// </summary>
- /// <param name="cameraData"> UniversalCameraData that holds XR pass data. </param>
- private void ImportXRMotionColorAndDepth(RenderGraph renderGraph, UniversalCameraData cameraData)
- {
- var rtMotionId = cameraData.xr.motionVectorRenderTarget;
- if (m_XRMotionVectorColor == null)
- {
- m_XRMotionVectorColor = RTHandles.Alloc(rtMotionId);
- }
- else if (m_XRMotionVectorColor.nameID != rtMotionId)
- {
- RTHandleStaticHelpers.SetRTHandleUserManagedWrapper(ref m_XRMotionVectorColor, rtMotionId);
- }
-
- // ID is the same since a RenderTexture encapsulates all the attachments, including both color+depth.
- var depthId = cameraData.xr.motionVectorRenderTarget;
- if (m_XRMotionVectorDepth == null)
- {
- m_XRMotionVectorDepth = RTHandles.Alloc(depthId);
- }
- else if (m_XRMotionVectorDepth.nameID != depthId)
- {
- RTHandleStaticHelpers.SetRTHandleUserManagedWrapper(ref m_XRMotionVectorDepth, depthId);
- }
-
- // Import motion color and depth into the render graph.
- RenderTargetInfo importInfo = new RenderTargetInfo();
- importInfo.width = cameraData.xr.motionVectorRenderTargetDesc.width;
- importInfo.height = cameraData.xr.motionVectorRenderTargetDesc.height;
- importInfo.volumeDepth = cameraData.xr.motionVectorRenderTargetDesc.volumeDepth;
- importInfo.msaaSamples = cameraData.xr.motionVectorRenderTargetDesc.msaaSamples;
- importInfo.format = cameraData.xr.motionVectorRenderTargetDesc.graphicsFormat;
-
- RenderTargetInfo importInfoDepth = new RenderTargetInfo();
- importInfoDepth = importInfo;
- importInfoDepth.format = cameraData.xr.motionVectorRenderTargetDesc.depthStencilFormat;
-
- ImportResourceParams importMotionColorParams = new ImportResourceParams();
- importMotionColorParams.clearOnFirstUse = true;
- importMotionColorParams.clearColor = Color.black;
- importMotionColorParams.discardOnLastUse = false;
-
- ImportResourceParams importMotionDepthParams = new ImportResourceParams();
- importMotionDepthParams.clearOnFirstUse = true;
- importMotionDepthParams.clearColor = Color.black;
- importMotionDepthParams.discardOnLastUse = false;
-
- xrMotionVectorColor = renderGraph.ImportTexture(m_XRMotionVectorColor, importInfo, importMotionColorParams);
- xrMotionVectorDepth = renderGraph.ImportTexture(m_XRMotionVectorDepth, importInfoDepth, importMotionDepthParams);
- }
-
- #region Recording
- internal void Render(RenderGraph renderGraph, ContextContainer frameData)
- {
- UniversalRenderingData renderingData = frameData.Get<UniversalRenderingData>();
- UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
-
- // XR should be enabled and single pass should be enabled.
- if (!cameraData.xr.enabled || !cameraData.xr.singlePassEnabled)
- {
- Debug.LogWarning("XRDepthMotionPass::Render is skipped because either XR is not enabled or singlepass rendering is not enabled.");
- return;
- }
-
- // XR motion vector pass should be enabled.
- if (!cameraData.xr.hasMotionVectorPass)
- {
- Debug.LogWarning("XRDepthMotionPass::Render is skipped because XR motion vector is not enabled for the current XRPass.");
- return;
- }
-
- // First, import XR motion color and depth targets into the RenderGraph
- ImportXRMotionColorAndDepth(renderGraph, cameraData);
-
- // 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.
- cameraData.camera.depthTextureMode |= DepthTextureMode.MotionVectors | DepthTextureMode.Depth;
-
- // Start recording the pass
- using (var builder = renderGraph.AddRasterRenderPass<PassData>("XR Motion Pass", out var passData, base.profilingSampler))
- {
- builder.EnableFoveatedRasterization(cameraData.xr.supportsFoveatedRendering);
- // Setup Color and Depth attachments
- builder.SetRenderAttachment(xrMotionVectorColor, 0, AccessFlags.Write);
- builder.SetRenderAttachmentDepth(xrMotionVectorDepth, AccessFlags.Write);
-
- // Setup RendererList
- InitObjectMotionRendererLists(ref passData, ref renderingData.cullResults, renderGraph, cameraData.camera);
- builder.UseRendererList(passData.objMotionRendererList);
-
- // Allow setting up global matrix array
- builder.AllowGlobalStateModification(true);
- // Setup rest of the passData
- InitPassData(ref passData, cameraData);
-
- builder.SetRenderFunc((PassData data, RasterGraphContext context) =>
- {
- // Setup camera stereo buffer
- context.cmd.SetGlobalMatrixArray(ShaderPropertyId.previousViewProjectionNoJitterStereo, data.previousViewProjectionStereo);
- context.cmd.SetGlobalMatrixArray(ShaderPropertyId.viewProjectionNoJitterStereo, data.viewProjectionStereo);
-
- // Object Motion for both static and dynamic objects, fill stencil for mv filled pixels.
- context.cmd.DrawRendererList(passData.objMotionRendererList);
-
- // Fill mv texturew with camera motion for pixels that don't have mv stencil bit.
- context.cmd.DrawProcedural(Matrix4x4.identity, data.xrMotionVector, 0, MeshTopology.Triangles, 3, 1);
- });
- }
- }
- #endregion
-
- private void ResetMotionData()
- {
- for (int i = 0; i < k_XRViewCount; i++)
- {
- m_ViewProjection[i] = Matrix4x4.identity;
- m_PreviousViewProjection[i] = Matrix4x4.identity;
- }
- m_LastFrameIndex = -1;
- }
-
- /// <summary>
- /// Update XRDepthMotionPass to use camera's view and projection matrix for motion vector calculation.
- /// </summary>
- /// <param name="cameraData"> The cameraData used for rendering to XR moition textures. </param>
- public void Update(ref UniversalCameraData cameraData)
- {
- if (!cameraData.xr.enabled || !cameraData.xr.singlePassEnabled)
- {
- Debug.LogWarning("XRDepthMotionPass::Update is skipped because either XR is not enabled or singlepass rendering is not enabled.");
- return;
- }
-
- if (m_LastFrameIndex != Time.frameCount)
- {
- {
- var gpuVP0 = GL.GetGPUProjectionMatrix(cameraData.GetProjectionMatrixNoJitter(0), renderIntoTexture: false) * cameraData.GetViewMatrix(0);
- var gpuVP1 = GL.GetGPUProjectionMatrix(cameraData.GetProjectionMatrixNoJitter(1), renderIntoTexture: false) * cameraData.GetViewMatrix(1);
- m_PreviousViewProjection[0] = m_ViewProjection[0];
- m_PreviousViewProjection[1] = m_ViewProjection[1];
- m_ViewProjection[0] = gpuVP0;
- m_ViewProjection[1] = gpuVP1;
- }
- m_LastFrameIndex = Time.frameCount;
- }
- }
-
- /// <summary>
- /// Cleans up resources used by the pass.
- /// </summary>
- public void Dispose()
- {
- m_XRMotionVectorColor?.Release();
- m_XRMotionVectorDepth?.Release();
- CoreUtils.Destroy(m_XRMotionVectorMaterial);
- }
- }
- }
- #endif
|