暫無描述
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.

FullScreenPassRendererFeature.cs 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. using System;
  2. using UnityEngine;
  3. using UnityEngine.Experimental.Rendering;
  4. using UnityEngine.Rendering.RenderGraphModule;
  5. using UnityEngine.Rendering;
  6. using UnityEngine.Rendering.Universal;
  7. /// <summary>
  8. /// This renderer feature lets you create single-pass full screen post processing effects without needing to write code.
  9. /// </summary>
  10. [URPHelpURL("renderer-features/renderer-feature-full-screen-pass")]
  11. public partial class FullScreenPassRendererFeature : ScriptableRendererFeature
  12. {
  13. /// <summary>
  14. /// An injection point for the full screen pass. This is similar to the RenderPassEvent enum but limited to only supported events.
  15. /// </summary>
  16. public enum InjectionPoint
  17. {
  18. /// <summary>
  19. /// Inject a full screen pass before transparents are rendered.
  20. /// </summary>
  21. BeforeRenderingTransparents = RenderPassEvent.BeforeRenderingTransparents,
  22. /// <summary>
  23. /// Inject a full screen pass before post processing is rendered.
  24. /// </summary>
  25. BeforeRenderingPostProcessing = RenderPassEvent.BeforeRenderingPostProcessing,
  26. /// <summary>
  27. /// Inject a full screen pass after post processing is rendered.
  28. /// </summary>
  29. AfterRenderingPostProcessing = RenderPassEvent.AfterRenderingPostProcessing
  30. }
  31. /// <summary>
  32. /// Specifies at which injection point the pass will be rendered.
  33. /// </summary>
  34. public InjectionPoint injectionPoint = InjectionPoint.AfterRenderingPostProcessing;
  35. /// <summary>
  36. /// Specifies whether the assigned material will need to use the current screen contents as an input texture.
  37. /// Disable this to optimize away an extra color copy pass when you know that the assigned material will only need
  38. /// to write on top of or hardware blend with the contents of the active color target.
  39. /// </summary>
  40. public bool fetchColorBuffer = true;
  41. /// <summary>
  42. /// A mask of URP textures that the assigned material will need access to. Requesting unused requirements can degrade
  43. /// performance unnecessarily as URP might need to run additional rendering passes to generate them.
  44. /// </summary>
  45. public ScriptableRenderPassInput requirements = ScriptableRenderPassInput.None;
  46. /// <summary>
  47. /// The material used to render the full screen pass (typically based on the Fullscreen Shader Graph target).
  48. /// </summary>
  49. public Material passMaterial;
  50. /// <summary>
  51. /// The shader pass index that should be used when rendering the assigned material.
  52. /// </summary>
  53. public int passIndex = 0;
  54. /// <summary>
  55. /// Specifies if the active camera's depth-stencil buffer should be bound when rendering the full screen pass.
  56. /// Disabling this will ensure that the material's depth and stencil commands will have no effect (this could also have a slight performance benefit).
  57. /// </summary>
  58. public bool bindDepthStencilAttachment = false;
  59. private FullScreenRenderPass m_FullScreenPass;
  60. /// <inheritdoc/>
  61. public override void Create()
  62. {
  63. m_FullScreenPass = new FullScreenRenderPass(name);
  64. }
  65. internal override bool RequireRenderingLayers(bool isDeferred, bool needsGBufferAccurateNormals, out RenderingLayerUtils.Event atEvent, out RenderingLayerUtils.MaskSize maskSize)
  66. {
  67. atEvent = RenderingLayerUtils.Event.Opaque;
  68. maskSize = RenderingLayerUtils.MaskSize.Bits8;
  69. return false;
  70. }
  71. /// <inheritdoc/>
  72. public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
  73. {
  74. if (renderingData.cameraData.cameraType == CameraType.Preview
  75. || renderingData.cameraData.cameraType == CameraType.Reflection
  76. || UniversalRenderer.IsOffscreenDepthTexture(ref renderingData.cameraData))
  77. return;
  78. if (passMaterial == null)
  79. {
  80. Debug.LogWarningFormat("The full screen feature \"{0}\" will not execute - no material is assigned. Please make sure a material is assigned for this feature on the renderer asset.", name);
  81. return;
  82. }
  83. if (passIndex < 0 || passIndex >= passMaterial.passCount)
  84. {
  85. Debug.LogWarningFormat("The full screen feature \"{0}\" will not execute - the pass index is out of bounds for the material.", name);
  86. return;
  87. }
  88. m_FullScreenPass.renderPassEvent = (RenderPassEvent)injectionPoint;
  89. m_FullScreenPass.ConfigureInput(requirements);
  90. m_FullScreenPass.SetupMembers(passMaterial, passIndex, fetchColorBuffer, bindDepthStencilAttachment);
  91. m_FullScreenPass.requiresIntermediateTexture = fetchColorBuffer;
  92. renderer.EnqueuePass(m_FullScreenPass);
  93. }
  94. /// <inheritdoc/>
  95. protected override void Dispose(bool disposing)
  96. {
  97. m_FullScreenPass.Dispose();
  98. }
  99. internal class FullScreenRenderPass : ScriptableRenderPass
  100. {
  101. private Material m_Material;
  102. private int m_PassIndex;
  103. private bool m_CopyActiveColor;
  104. private bool m_BindDepthStencilAttachment;
  105. private RTHandle m_CopiedColor;
  106. private static MaterialPropertyBlock s_SharedPropertyBlock = new MaterialPropertyBlock();
  107. public FullScreenRenderPass(string passName)
  108. {
  109. profilingSampler = new ProfilingSampler(passName);
  110. }
  111. public void SetupMembers(Material material, int passIndex, bool copyActiveColor, bool bindDepthStencilAttachment)
  112. {
  113. m_Material = material;
  114. m_PassIndex = passIndex;
  115. m_CopyActiveColor = copyActiveColor;
  116. m_BindDepthStencilAttachment = bindDepthStencilAttachment;
  117. }
  118. [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)]
  119. public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
  120. {
  121. // Disable obsolete warning for internal usage
  122. #pragma warning disable CS0618
  123. // FullScreenPass manages its own RenderTarget.
  124. // ResetTarget here so that ScriptableRenderer's active attachement can be invalidated when processing this ScriptableRenderPass.
  125. ResetTarget();
  126. #pragma warning restore CS0618
  127. if (m_CopyActiveColor)
  128. ReAllocate(renderingData.cameraData.cameraTargetDescriptor);
  129. }
  130. internal void ReAllocate(RenderTextureDescriptor desc)
  131. {
  132. desc.msaaSamples = 1;
  133. desc.depthBufferBits = (int)DepthBits.None;
  134. RenderingUtils.ReAllocateHandleIfNeeded(ref m_CopiedColor, desc, name: "_FullscreenPassColorCopy");
  135. }
  136. public void Dispose()
  137. {
  138. m_CopiedColor?.Release();
  139. }
  140. private static void ExecuteCopyColorPass(RasterCommandBuffer cmd, RTHandle sourceTexture)
  141. {
  142. Blitter.BlitTexture(cmd, sourceTexture, new Vector4(1, 1, 0, 0), 0.0f, false);
  143. }
  144. private static void ExecuteMainPass(RasterCommandBuffer cmd, RTHandle sourceTexture, Material material, int passIndex)
  145. {
  146. s_SharedPropertyBlock.Clear();
  147. if (sourceTexture != null)
  148. s_SharedPropertyBlock.SetTexture(ShaderPropertyId.blitTexture, sourceTexture);
  149. // We need to set the "_BlitScaleBias" uniform for user materials with shaders relying on core Blit.hlsl to work
  150. s_SharedPropertyBlock.SetVector(ShaderPropertyId.blitScaleBias, new Vector4(1, 1, 0, 0));
  151. cmd.DrawProcedural(Matrix4x4.identity, material, passIndex, MeshTopology.Triangles, 3, 1, s_SharedPropertyBlock);
  152. }
  153. [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)]
  154. public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
  155. {
  156. ref var cameraData = ref renderingData.cameraData;
  157. var cmd = renderingData.commandBuffer;
  158. using (new ProfilingScope(cmd, profilingSampler))
  159. {
  160. RasterCommandBuffer rasterCmd = CommandBufferHelpers.GetRasterCommandBuffer(cmd);
  161. if (m_CopyActiveColor)
  162. {
  163. CoreUtils.SetRenderTarget(cmd, m_CopiedColor);
  164. ExecuteCopyColorPass(rasterCmd, cameraData.renderer.cameraColorTargetHandle);
  165. }
  166. if (m_BindDepthStencilAttachment)
  167. CoreUtils.SetRenderTarget(cmd, cameraData.renderer.cameraColorTargetHandle, cameraData.renderer.cameraDepthTargetHandle);
  168. else
  169. CoreUtils.SetRenderTarget(cmd, cameraData.renderer.cameraColorTargetHandle);
  170. ExecuteMainPass(rasterCmd, m_CopyActiveColor ? m_CopiedColor : null, m_Material, m_PassIndex);
  171. }
  172. }
  173. public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
  174. {
  175. UniversalResourceData resourcesData = frameData.Get<UniversalResourceData>();
  176. UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
  177. var colorCopyDescriptor = cameraData.cameraTargetDescriptor;
  178. colorCopyDescriptor.msaaSamples = 1;
  179. colorCopyDescriptor.depthBufferBits = (int)DepthBits.None;
  180. TextureHandle copiedColor = TextureHandle.nullHandle;
  181. if (m_CopyActiveColor)
  182. {
  183. copiedColor = UniversalRenderer.CreateRenderGraphTexture(renderGraph, colorCopyDescriptor, "_FullscreenPassColorCopy", false);
  184. using (var builder = renderGraph.AddRasterRenderPass<CopyPassData>("FullScreenPass_CopyColor", out var passData, profilingSampler))
  185. {
  186. passData.inputTexture = resourcesData.activeColorTexture;
  187. builder.UseTexture(resourcesData.activeColorTexture, AccessFlags.Read);
  188. builder.SetRenderAttachment(copiedColor, 0, AccessFlags.Write);
  189. builder.SetRenderFunc((CopyPassData data, RasterGraphContext rgContext) =>
  190. {
  191. ExecuteCopyColorPass(rgContext.cmd, data.inputTexture);
  192. });
  193. }
  194. }
  195. using (var builder = renderGraph.AddRasterRenderPass<MainPassData>("FullScreenPass", out var passData, profilingSampler))
  196. {
  197. builder.UseAllGlobalTextures(true);
  198. passData.material = m_Material;
  199. passData.passIndex = m_PassIndex;
  200. if (m_CopyActiveColor)
  201. {
  202. passData.inputTexture = copiedColor;
  203. builder.UseTexture(copiedColor, AccessFlags.Read);
  204. }
  205. builder.SetRenderAttachment(resourcesData.activeColorTexture, 0, AccessFlags.Write);
  206. if (m_BindDepthStencilAttachment)
  207. builder.SetRenderAttachmentDepth(resourcesData.activeDepthTexture, AccessFlags.Write);
  208. builder.SetRenderFunc((MainPassData data, RasterGraphContext rgContext) =>
  209. {
  210. ExecuteMainPass(rgContext.cmd, data.inputTexture.IsValid() ? data.inputTexture : null, data.material, data.passIndex);
  211. });
  212. }
  213. }
  214. private class CopyPassData
  215. {
  216. internal TextureHandle inputTexture;
  217. }
  218. private class MainPassData
  219. {
  220. internal Material material;
  221. internal int passIndex;
  222. internal TextureHandle inputTexture;
  223. }
  224. }
  225. }