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

OutputTextureRendererFeature.cs 8.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. using System;
  2. using UnityEngine;
  3. using UnityEngine.Rendering.RenderGraphModule;
  4. using UnityEngine.Rendering;
  5. using UnityEngine.Rendering.Universal;
  6. // MERGING: This pass can be merged with Draw Objects Pass and Draw Skybox pass if you set the m_PassEvent in
  7. // the inspector to After Rendering Opagues and set the texture type to Normal.
  8. // Your can observe this merging in the Render Graph Visualizer. If set to After Rendering Post Processing we
  9. // can now see that the pass isn't merged with any thing.
  10. // About MERGING: To merge two RG passes they need to be recorded within the same RecordRenderGraph function.
  11. // The Graph will automatically determine when to break render passes as well as the load and
  12. // store actions to apply to these render passes. To do this, the graph will analyze the use of
  13. // textures. E.g. when a texture is used twice in a row as a active render target, the two render
  14. // graph passes will be merged in a single render pass with two surpasses. On the other hand if a
  15. // render target is sampled as a texture in a later pass this render target will be stored
  16. // (and possibly resolved) and the render pass will be broken up.
  17. // This RenderFeature shows how to used RenderGraph to output a specific texture used in URP, how a texture
  18. // can be attached by name to a material and how two render passes can be merged if executed in the correct order.
  19. public class OutputTextureRendererFeature : ScriptableRendererFeature
  20. {
  21. // Enum used to select which texture you want to output.
  22. [Serializable]
  23. enum TextureType
  24. {
  25. OpaqueColor,
  26. Depth,
  27. Normal,
  28. MotionVector,
  29. }
  30. // Function to fetch the texture given the resource data and the texture type you want.
  31. static TextureHandle GetTextureHandleFromType(UniversalResourceData resourceData, TextureType textureType)
  32. {
  33. switch (textureType)
  34. {
  35. case TextureType.OpaqueColor:
  36. return resourceData.cameraOpaqueTexture;
  37. case TextureType.Depth:
  38. return resourceData.cameraDepthTexture;
  39. case TextureType.Normal:
  40. return resourceData.cameraNormalsTexture;
  41. case TextureType.MotionVector:
  42. return resourceData.motionVectorColor;
  43. default:
  44. return TextureHandle.nullHandle;
  45. }
  46. }
  47. // Pass which outputs a texture from rendering to inspect a texture
  48. class OutputTexturePass : ScriptableRenderPass
  49. {
  50. // The texture name you wish to bind the texture handle to for a given material.
  51. string m_TextureName;
  52. // The texture type you want to retrive from URP.
  53. TextureType m_TextureType;
  54. // The material used for blitting to the color output.
  55. Material m_Material;
  56. // Function set setup the ConfigureInput() and transfer the renderer feature settings to the render pass.
  57. public void Setup(string textureName, TextureType textureType, Material material)
  58. {
  59. // Setup code to trigger each corrspoinding texture is ready for use one the pass is run.
  60. if (textureType == TextureType.OpaqueColor)
  61. ConfigureInput(ScriptableRenderPassInput.Color);
  62. else if (textureType == TextureType.Depth)
  63. ConfigureInput(ScriptableRenderPassInput.Depth);
  64. else if (textureType == TextureType.Normal)
  65. ConfigureInput(ScriptableRenderPassInput.Normal);
  66. else if (textureType == TextureType.MotionVector)
  67. ConfigureInput(ScriptableRenderPassInput.Motion);
  68. // Setup the texture name, type and material used when blitting.
  69. // In this example we will use a mateial using a custom name for the input texture name when blitting.
  70. // This texture name has to match the material texture input you are using.
  71. m_TextureName = String.IsNullOrEmpty(textureName) ? "_InputTexture" : textureName;
  72. // Texture type selects which input we would like to retrive from the camera.
  73. m_TextureType = textureType;
  74. // The material is used to blit the texture to the cameras color attachment.
  75. m_Material = material;
  76. }
  77. // PassData is used to pass data when recording to the execution of the pass.
  78. class PassData
  79. {
  80. // Texture name used for the material.
  81. public string textureName;
  82. // Texture handle to blit from.
  83. public TextureHandle input;
  84. // Material used for blitting.
  85. public Material material;
  86. }
  87. // Records a render graph render pass which blits the BlitData's active texture back to the camera's color attachment.
  88. public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
  89. {
  90. // Starts the recording of the render graph pass given the name of the pass
  91. // and outputting the data used to pass data to the execution of the render function.
  92. using (var builder = renderGraph.AddRasterRenderPass("OutputTexturePass", out PassData passData))
  93. {
  94. // Fetch UniversalResourceData from frameData to retrive the URP's texture handles.
  95. var resourceData = frameData.Get<UniversalResourceData>();
  96. // Sets the texture name for the data which carries the data to the render function.
  97. passData.textureName = m_TextureName;
  98. // Sets the texture handle input using the helper function to fetch the correct handle from resourceData.
  99. passData.input = GetTextureHandleFromType(resourceData, m_TextureType);
  100. // Checks if the texture handle used as input is valid.
  101. if (!passData.input.IsValid()) {
  102. Debug.Log("Input texture is not created, skipping OutputTexturePass.");
  103. return;
  104. }
  105. // Sets the material for the render function data.
  106. passData.material = m_Material;
  107. // Sets input attachment to the texture handle retrived before.
  108. builder.UseTexture(passData.input);
  109. // Sets output attachment 0 to the cameras active color texture.
  110. builder.SetRenderAttachment(resourceData.activeColorTexture, 0);
  111. // Sets the render function which is called after the recording is done and the pass is executed.
  112. builder.SetRenderFunc((PassData data, RasterGraphContext rgContext) => ExecutePass(data, rgContext));
  113. }
  114. }
  115. // ExecutePass is the render function set in the render graph recordings.
  116. // This is good practice to avoid using variables outside of the lambda it is called from.
  117. // It is static to avoid using member variables which could cause unintended behaviour.
  118. static void ExecutePass(PassData data, RasterGraphContext rgContext)
  119. {
  120. // We need to set the texture for the material using the texture handle and the texture name.
  121. data.material.SetTexture(data.textureName, data.input);
  122. // Draw procedural
  123. rgContext.cmd.DrawProcedural(Matrix4x4.identity, data.material, 0, MeshTopology.Triangles, 3);
  124. }
  125. }
  126. // Inputs in the inspector to change the settings for the renderer feature.
  127. [SerializeField]
  128. RenderPassEvent m_PassEvent;
  129. [SerializeField]
  130. string m_TextureName = "_InputTexture";
  131. [SerializeField]
  132. TextureType m_TextureType;
  133. [SerializeField]
  134. Material m_Material;
  135. OutputTexturePass m_ScriptablePass;
  136. /// <inheritdoc/>
  137. public override void Create()
  138. {
  139. m_ScriptablePass = new OutputTexturePass();
  140. // Configures where the render pass should be injected.
  141. m_ScriptablePass.renderPassEvent = m_PassEvent;
  142. }
  143. // Here you can inject one or multiple render passes in the renderer.
  144. // This method is called when setting up the renderer once per-camera.
  145. public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
  146. {
  147. // Setup the correct data for the render pass, and transfers the data from the renderer feature to the render pass.
  148. m_ScriptablePass.Setup(m_TextureName, m_TextureType, m_Material);
  149. renderer.EnqueuePass(m_ScriptablePass);
  150. }
  151. }