No Description
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.

MrtRendererFeature.cs 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. using System;
  2. using UnityEngine;
  3. using UnityEngine.Rendering.RenderGraphModule;
  4. using UnityEngine.Rendering;
  5. using UnityEngine.Rendering.Universal;
  6. // In this example it is shown how to use Multiple Render Targets (MRT) in RenderGraph using URP. This is useful when more than 4 channels of data (a single RGBA texture) needs to be written by a pass.
  7. public class MrtRendererFeature : ScriptableRendererFeature
  8. {
  9. // This pass is using MRT and will output to 3 different Render Targets.
  10. class MrtPass : ScriptableRenderPass
  11. {
  12. // The data we want to transfer to the render function after recording.
  13. class PassData
  14. {
  15. // Texture handle for the color input.
  16. public TextureHandle color;
  17. // Input texture name for the material.
  18. public string texName;
  19. // Material used for the MRT Pass.
  20. public Material material;
  21. }
  22. // Input texture name for the material.
  23. string m_texName;
  24. // Material used for the MRT Pass.
  25. Material m_Material;
  26. // RTHandle outputs for the MRT destinations.
  27. RTHandle[] m_RTs = new RTHandle[3];
  28. RenderTargetInfo[] m_RTInfos = new RenderTargetInfo[3];
  29. // Function used to transfer the material from the renderer feature to the render pass.
  30. public void Setup(string texName, Material material, RenderTexture[] renderTextures)
  31. {
  32. m_Material = material;
  33. m_texName = String.IsNullOrEmpty(texName) ? "_ColorTexture" : texName;
  34. //Create RTHandles from the RenderTextures if they have changed.
  35. for (int i = 0; i < 3; i++)
  36. {
  37. if (m_RTs[i] == null || m_RTs[i].rt != renderTextures[i])
  38. {
  39. m_RTs[i]?.Release();
  40. m_RTs[i] = RTHandles.Alloc(renderTextures[i], $"ChannelTexture[{i}]");
  41. m_RTInfos[i] = new RenderTargetInfo()
  42. {
  43. format = renderTextures[i].graphicsFormat,
  44. height = renderTextures[i].height,
  45. width = renderTextures[i].width,
  46. bindMS = renderTextures[i].bindTextureMS,
  47. msaaSamples = 1,
  48. volumeDepth = renderTextures[i].volumeDepth,
  49. };
  50. }
  51. }
  52. }
  53. // This function blits the whole screen for a given material.
  54. public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
  55. {
  56. var handles = new TextureHandle[3];
  57. // Imports the texture handles them in RenderGraph.
  58. for (int i = 0; i < 3; i++)
  59. {
  60. handles[i] = renderGraph.ImportTexture(m_RTs[i], m_RTInfos[i]);
  61. }
  62. // Starts the recording of the render graph pass given the name of the pass
  63. // and outputting the data used to pass data to the execution of the render function.
  64. using (var builder = renderGraph.AddRasterRenderPass<PassData>("MRT Pass", out var passData))
  65. {
  66. // Fetch the universal resource data to exstract the camera's color attachment.
  67. var resourceData = frameData.Get<UniversalResourceData>();
  68. // Fill in the pass data using by the render function.
  69. // Use the camera's color attachment as input.
  70. passData.color = resourceData.activeColorTexture;
  71. // Input Texture name for the material.
  72. passData.texName = m_texName;
  73. // Material used in the pass.
  74. passData.material = m_Material;
  75. // Sets input attachment.
  76. builder.UseTexture(passData.color);
  77. // Sets color attachments.
  78. for (int i = 0; i < 3; i++)
  79. {
  80. builder.SetRenderAttachment(handles[i], i);
  81. }
  82. // Sets the render function.
  83. builder.SetRenderFunc((PassData data, RasterGraphContext rgContext) => ExecutePass(data, rgContext));
  84. }
  85. }
  86. // ExecutePass is the render function for each of the blit render graph recordings.
  87. // This is good practice to avoid using variables outside of the lambda it is called from.
  88. // It is static to avoid using member variables which could cause unintended behaviour.
  89. static void ExecutePass(PassData data, RasterGraphContext rgContext)
  90. {
  91. // Sets the input color texture to the name used in the MRTPass
  92. data.material.SetTexture(data.texName, data.color);
  93. // Draw the fullscreen triangle with the MRT shader.
  94. rgContext.cmd.DrawProcedural(Matrix4x4.identity, data.material, 0, MeshTopology.Triangles, 3);
  95. }
  96. }
  97. [Tooltip("The material used when making the MRT pass.")]
  98. public Material mrtMaterial;
  99. [Tooltip("Name to apply the camera's color attachment to for the given material.")]
  100. public string textureName = "_ColorTexture";
  101. [Tooltip("Render Textures to output the result to. Is has to have the size of 3.")]
  102. public RenderTexture[] renderTextures = new RenderTexture[3];
  103. MrtPass m_MrtPass;
  104. // Here you can create passes and do the initialization of them. This is called everytime serialization happens.
  105. public override void Create()
  106. {
  107. m_MrtPass = new MrtPass();
  108. // Configures where the render pass should be injected.
  109. m_MrtPass.renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
  110. }
  111. // Here you can inject one or multiple render passes in the renderer.
  112. // This method is called when setting up the renderer once per-camera.
  113. public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
  114. {
  115. // Since they have the same RenderPassEvent the order matters when enqueueing them.
  116. // Early exit if there are no materials.
  117. if (mrtMaterial == null || renderTextures.Length != 3)
  118. {
  119. Debug.LogWarning("Skipping MRTPass because the material is null or render textures doesn't have a size of 3.");
  120. return;
  121. }
  122. foreach (var rt in renderTextures)
  123. {
  124. if (rt == null)
  125. {
  126. Debug.LogWarning("Skipping MRTPass because one of the render textures is null.");
  127. return;
  128. }
  129. }
  130. // Call the pass Setup function to transfer the RendererFeature settings to the RenderPass.
  131. m_MrtPass.Setup(textureName, mrtMaterial, renderTextures);
  132. renderer.EnqueuePass(m_MrtPass);
  133. }
  134. }