Без опису
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

XRDepthMotionPass.cs 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. #if ENABLE_VR && ENABLE_XR_MODULE
  2. using System;
  3. using UnityEngine.Experimental.Rendering;
  4. using UnityEngine.Rendering.RenderGraphModule;
  5. namespace UnityEngine.Rendering.Universal
  6. {
  7. /// <summary>
  8. /// Render all objects that have a 'XRMotionVectors' pass into the given depth buffer and motionvec buffer.
  9. /// </summary>
  10. public class XRDepthMotionPass : ScriptableRenderPass
  11. {
  12. private static readonly ShaderTagId k_MotionOnlyShaderTagId = new ShaderTagId("XRMotionVectors");
  13. private PassData m_PassData;
  14. private RTHandle m_XRMotionVectorColor;
  15. private TextureHandle xrMotionVectorColor;
  16. private RTHandle m_XRMotionVectorDepth;
  17. private TextureHandle xrMotionVectorDepth;
  18. /// <summary>
  19. /// Creates a new <c>XRDepthMotionPass</c> instance.
  20. /// </summary>
  21. /// <param name="evt">The <c>RenderPassEvent</c> to use.</param>
  22. /// <param name="xrMotionVector">The Shader used for rendering XR camera motion vector.</param>
  23. /// <seealso cref="RenderPassEvent"/>
  24. public XRDepthMotionPass(RenderPassEvent evt, Shader xrMotionVector)
  25. {
  26. base.profilingSampler = new ProfilingSampler(nameof(XRDepthMotionPass));
  27. m_PassData = new PassData();
  28. renderPassEvent = evt;
  29. ResetMotionData();
  30. m_XRMotionVectorMaterial = CoreUtils.CreateEngineMaterial(xrMotionVector);
  31. xrMotionVectorColor = TextureHandle.nullHandle;
  32. m_XRMotionVectorColor = null;
  33. xrMotionVectorDepth = TextureHandle.nullHandle;
  34. m_XRMotionVectorDepth = null;
  35. }
  36. private class PassData
  37. {
  38. internal RendererListHandle objMotionRendererList;
  39. internal Matrix4x4[] previousViewProjectionStereo = new Matrix4x4[k_XRViewCount];
  40. internal Matrix4x4[] viewProjectionStereo = new Matrix4x4[k_XRViewCount];
  41. internal Material xrMotionVector;
  42. }
  43. /// View projection data
  44. private const int k_XRViewCount = 2;
  45. private Matrix4x4[] m_ViewProjection = new Matrix4x4[k_XRViewCount];
  46. private Matrix4x4[] m_PreviousViewProjection = new Matrix4x4[k_XRViewCount];
  47. private int m_LastFrameIndex;
  48. // Motion Vector
  49. private Material m_XRMotionVectorMaterial;
  50. private static DrawingSettings GetObjectMotionDrawingSettings(Camera camera)
  51. {
  52. var sortingSettings = new SortingSettings(camera) { criteria = SortingCriteria.CommonOpaque };
  53. // Notes: Usually, PerObjectData.MotionVectors will filter the renderer nodes to only draw moving objects.
  54. // In our case, we use forceAllMotionVectorObjects in the filteringSettings to draw idle objects as well to populate depth.
  55. var drawingSettings = new DrawingSettings(k_MotionOnlyShaderTagId, sortingSettings)
  56. {
  57. perObjectData = PerObjectData.MotionVectors,
  58. enableDynamicBatching = false,
  59. enableInstancing = true,
  60. };
  61. drawingSettings.SetShaderPassName(0, k_MotionOnlyShaderTagId);
  62. return drawingSettings;
  63. }
  64. private void InitObjectMotionRendererLists(ref PassData passData, ref CullingResults cullResults, RenderGraph renderGraph, Camera camera)
  65. {
  66. var objectMotionDrawingSettings = GetObjectMotionDrawingSettings(camera);
  67. // XRTODO: Extend RenderQueueRange.all to support transparent objects?
  68. // URP current' doesn't support this, missing motion override for transparent materials.
  69. var filteringSettings = new FilteringSettings(RenderQueueRange.opaque, camera.cullingMask);
  70. // Also render game objects that are not moved since last frame to save depth prepass requirement for camera motion.
  71. filteringSettings.forceAllMotionVectorObjects = true;
  72. var renderStateBlock = new RenderStateBlock(RenderStateMask.Nothing);
  73. RenderingUtils.CreateRendererListWithRenderStateBlock(renderGraph, ref cullResults, objectMotionDrawingSettings, filteringSettings, renderStateBlock, ref passData.objMotionRendererList);
  74. }
  75. /// <summary>
  76. /// Initialize the RenderGraph pass data.
  77. /// </summary>
  78. /// <param name="passData"></param>
  79. private void InitPassData(ref PassData passData, UniversalCameraData cameraData)
  80. {
  81. // XRTODO: Use XRSystem prevViewMatrix that is compatible with late latching. Currently blocked due to late latching engine side issue.
  82. //var gpuP0 = GL.GetGPUProjectionMatrix(cameraData.xr.GetProjMatrix(0), false);
  83. //var gpuP1 = GL.GetGPUProjectionMatrix(cameraData.xr.GetProjMatrix(1), false);
  84. //passData.viewProjectionStereo[0] = gpuP0 * cameraData.xr.GetViewMatrix(0);
  85. //passData.viewProjectionStereo[1] = gpuP1 * cameraData.xr.GetViewMatrix(1);
  86. //passData.previousViewProjectionStereo[0] = gpuP0 * cameraData.xr.GetPrevViewMatrix(0);
  87. //passData.previousViewProjectionStereo[1] = gpuP0 * cameraData.xr.GetPrevViewMatrix(1);
  88. // Setup matrices and shader
  89. passData.previousViewProjectionStereo = m_PreviousViewProjection;
  90. passData.viewProjectionStereo = m_ViewProjection;
  91. // Setup camera motion material
  92. passData.xrMotionVector = m_XRMotionVectorMaterial;
  93. }
  94. /// <summary>
  95. /// Import the XR motion color and depth targets into the RenderGraph.
  96. /// </summary>
  97. /// <param name="cameraData"> UniversalCameraData that holds XR pass data. </param>
  98. private void ImportXRMotionColorAndDepth(RenderGraph renderGraph, UniversalCameraData cameraData)
  99. {
  100. var rtMotionId = cameraData.xr.motionVectorRenderTarget;
  101. if (m_XRMotionVectorColor == null)
  102. {
  103. m_XRMotionVectorColor = RTHandles.Alloc(rtMotionId);
  104. }
  105. else if (m_XRMotionVectorColor.nameID != rtMotionId)
  106. {
  107. RTHandleStaticHelpers.SetRTHandleUserManagedWrapper(ref m_XRMotionVectorColor, rtMotionId);
  108. }
  109. // ID is the same since a RenderTexture encapsulates all the attachments, including both color+depth.
  110. var depthId = cameraData.xr.motionVectorRenderTarget;
  111. if (m_XRMotionVectorDepth == null)
  112. {
  113. m_XRMotionVectorDepth = RTHandles.Alloc(depthId);
  114. }
  115. else if (m_XRMotionVectorDepth.nameID != depthId)
  116. {
  117. RTHandleStaticHelpers.SetRTHandleUserManagedWrapper(ref m_XRMotionVectorDepth, depthId);
  118. }
  119. // Import motion color and depth into the render graph.
  120. RenderTargetInfo importInfo = new RenderTargetInfo();
  121. importInfo.width = cameraData.xr.motionVectorRenderTargetDesc.width;
  122. importInfo.height = cameraData.xr.motionVectorRenderTargetDesc.height;
  123. importInfo.volumeDepth = cameraData.xr.motionVectorRenderTargetDesc.volumeDepth;
  124. importInfo.msaaSamples = cameraData.xr.motionVectorRenderTargetDesc.msaaSamples;
  125. importInfo.format = cameraData.xr.motionVectorRenderTargetDesc.graphicsFormat;
  126. RenderTargetInfo importInfoDepth = new RenderTargetInfo();
  127. importInfoDepth = importInfo;
  128. importInfoDepth.format = cameraData.xr.motionVectorRenderTargetDesc.depthStencilFormat;
  129. ImportResourceParams importMotionColorParams = new ImportResourceParams();
  130. importMotionColorParams.clearOnFirstUse = true;
  131. importMotionColorParams.clearColor = Color.black;
  132. importMotionColorParams.discardOnLastUse = false;
  133. ImportResourceParams importMotionDepthParams = new ImportResourceParams();
  134. importMotionDepthParams.clearOnFirstUse = true;
  135. importMotionDepthParams.clearColor = Color.black;
  136. importMotionDepthParams.discardOnLastUse = false;
  137. xrMotionVectorColor = renderGraph.ImportTexture(m_XRMotionVectorColor, importInfo, importMotionColorParams);
  138. xrMotionVectorDepth = renderGraph.ImportTexture(m_XRMotionVectorDepth, importInfoDepth, importMotionDepthParams);
  139. }
  140. #region Recording
  141. internal void Render(RenderGraph renderGraph, ContextContainer frameData)
  142. {
  143. UniversalRenderingData renderingData = frameData.Get<UniversalRenderingData>();
  144. UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
  145. // XR should be enabled and single pass should be enabled.
  146. if (!cameraData.xr.enabled || !cameraData.xr.singlePassEnabled)
  147. {
  148. Debug.LogWarning("XRDepthMotionPass::Render is skipped because either XR is not enabled or singlepass rendering is not enabled.");
  149. return;
  150. }
  151. // XR motion vector pass should be enabled.
  152. if (!cameraData.xr.hasMotionVectorPass)
  153. {
  154. Debug.LogWarning("XRDepthMotionPass::Render is skipped because XR motion vector is not enabled for the current XRPass.");
  155. return;
  156. }
  157. // First, import XR motion color and depth targets into the RenderGraph
  158. ImportXRMotionColorAndDepth(renderGraph, cameraData);
  159. // These flags are still required in SRP or the engine won't compute previous model matrices...
  160. // If the flag hasn't been set yet on this camera, motion vectors will skip a frame.
  161. cameraData.camera.depthTextureMode |= DepthTextureMode.MotionVectors | DepthTextureMode.Depth;
  162. // Start recording the pass
  163. using (var builder = renderGraph.AddRasterRenderPass<PassData>("XR Motion Pass", out var passData, base.profilingSampler))
  164. {
  165. builder.EnableFoveatedRasterization(cameraData.xr.supportsFoveatedRendering);
  166. // Setup Color and Depth attachments
  167. builder.SetRenderAttachment(xrMotionVectorColor, 0, AccessFlags.Write);
  168. builder.SetRenderAttachmentDepth(xrMotionVectorDepth, AccessFlags.Write);
  169. // Setup RendererList
  170. InitObjectMotionRendererLists(ref passData, ref renderingData.cullResults, renderGraph, cameraData.camera);
  171. builder.UseRendererList(passData.objMotionRendererList);
  172. // Allow setting up global matrix array
  173. builder.AllowGlobalStateModification(true);
  174. // Setup rest of the passData
  175. InitPassData(ref passData, cameraData);
  176. builder.SetRenderFunc((PassData data, RasterGraphContext context) =>
  177. {
  178. // Setup camera stereo buffer
  179. context.cmd.SetGlobalMatrixArray(ShaderPropertyId.previousViewProjectionNoJitterStereo, data.previousViewProjectionStereo);
  180. context.cmd.SetGlobalMatrixArray(ShaderPropertyId.viewProjectionNoJitterStereo, data.viewProjectionStereo);
  181. // Object Motion for both static and dynamic objects, fill stencil for mv filled pixels.
  182. context.cmd.DrawRendererList(passData.objMotionRendererList);
  183. // Fill mv texturew with camera motion for pixels that don't have mv stencil bit.
  184. context.cmd.DrawProcedural(Matrix4x4.identity, data.xrMotionVector, 0, MeshTopology.Triangles, 3, 1);
  185. });
  186. }
  187. }
  188. #endregion
  189. private void ResetMotionData()
  190. {
  191. for (int i = 0; i < k_XRViewCount; i++)
  192. {
  193. m_ViewProjection[i] = Matrix4x4.identity;
  194. m_PreviousViewProjection[i] = Matrix4x4.identity;
  195. }
  196. m_LastFrameIndex = -1;
  197. }
  198. /// <summary>
  199. /// Update XRDepthMotionPass to use camera's view and projection matrix for motion vector calculation.
  200. /// </summary>
  201. /// <param name="cameraData"> The cameraData used for rendering to XR moition textures. </param>
  202. public void Update(ref UniversalCameraData cameraData)
  203. {
  204. if (!cameraData.xr.enabled || !cameraData.xr.singlePassEnabled)
  205. {
  206. Debug.LogWarning("XRDepthMotionPass::Update is skipped because either XR is not enabled or singlepass rendering is not enabled.");
  207. return;
  208. }
  209. if (m_LastFrameIndex != Time.frameCount)
  210. {
  211. {
  212. var gpuVP0 = GL.GetGPUProjectionMatrix(cameraData.GetProjectionMatrixNoJitter(0), renderIntoTexture: false) * cameraData.GetViewMatrix(0);
  213. var gpuVP1 = GL.GetGPUProjectionMatrix(cameraData.GetProjectionMatrixNoJitter(1), renderIntoTexture: false) * cameraData.GetViewMatrix(1);
  214. m_PreviousViewProjection[0] = m_ViewProjection[0];
  215. m_PreviousViewProjection[1] = m_ViewProjection[1];
  216. m_ViewProjection[0] = gpuVP0;
  217. m_ViewProjection[1] = gpuVP1;
  218. }
  219. m_LastFrameIndex = Time.frameCount;
  220. }
  221. }
  222. /// <summary>
  223. /// Cleans up resources used by the pass.
  224. /// </summary>
  225. public void Dispose()
  226. {
  227. m_XRMotionVectorColor?.Release();
  228. m_XRMotionVectorDepth?.Release();
  229. CoreUtils.Destroy(m_XRMotionVectorMaterial);
  230. }
  231. }
  232. }
  233. #endif