DepthNormalOnlyPass.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine.Experimental.Rendering;
  4. namespace UnityEngine.Rendering.Universal.Internal
  5. {
  6. public class DepthNormalOnlyPass : ScriptableRenderPass
  7. {
  8. internal RenderTextureDescriptor normalDescriptor { get; set; }
  9. internal RenderTextureDescriptor depthDescriptor { get; set; }
  10. internal bool allocateDepth { get; set; } = true;
  11. internal bool allocateNormal { get; set; } = true;
  12. internal List<ShaderTagId> shaderTagIds { get; set; }
  13. private RenderTargetHandle depthHandle { get; set; }
  14. private RenderTargetHandle normalHandle { get; set; }
  15. private FilteringSettings m_FilteringSettings;
  16. private int m_RendererMSAASamples = 1;
  17. // Constants
  18. private const int k_DepthBufferBits = 32;
  19. private static readonly List<ShaderTagId> k_DepthNormals = new List<ShaderTagId> { new ShaderTagId("DepthNormals"), new ShaderTagId("DepthNormalsOnly") };
  20. /// <summary>
  21. /// Create the DepthNormalOnlyPass
  22. /// </summary>
  23. public DepthNormalOnlyPass(RenderPassEvent evt, RenderQueueRange renderQueueRange, LayerMask layerMask)
  24. {
  25. base.profilingSampler = new ProfilingSampler(nameof(DepthNormalOnlyPass));
  26. m_FilteringSettings = new FilteringSettings(renderQueueRange, layerMask);
  27. renderPassEvent = evt;
  28. useNativeRenderPass = false;
  29. }
  30. /// <summary>
  31. /// Configure the pass
  32. /// </summary>
  33. public void Setup(RenderTextureDescriptor baseDescriptor, RenderTargetHandle depthHandle, RenderTargetHandle normalHandle)
  34. {
  35. // Find compatible render-target format for storing normals.
  36. // Shader code outputs normals in signed format to be compatible with deferred gbuffer layout.
  37. // Deferred gbuffer format is signed so that normals can be blended for terrain geometry.
  38. GraphicsFormat normalsFormat;
  39. if (RenderingUtils.SupportsGraphicsFormat(GraphicsFormat.R8G8B8A8_SNorm, FormatUsage.Render))
  40. normalsFormat = GraphicsFormat.R8G8B8A8_SNorm; // Preferred format
  41. else if (RenderingUtils.SupportsGraphicsFormat(GraphicsFormat.R16G16B16A16_SFloat, FormatUsage.Render))
  42. normalsFormat = GraphicsFormat.R16G16B16A16_SFloat; // fallback
  43. else
  44. normalsFormat = GraphicsFormat.R32G32B32A32_SFloat; // fallback
  45. this.depthHandle = depthHandle;
  46. m_RendererMSAASamples = baseDescriptor.msaaSamples;
  47. baseDescriptor.colorFormat = RenderTextureFormat.Depth;
  48. baseDescriptor.depthBufferBits = k_DepthBufferBits;
  49. // Never have MSAA on this depth texture. When doing MSAA depth priming this is the texture that is resolved to and used for post-processing.
  50. baseDescriptor.msaaSamples = 1;// Depth-Only pass don't use MSAA
  51. depthDescriptor = baseDescriptor;
  52. this.normalHandle = normalHandle;
  53. baseDescriptor.graphicsFormat = normalsFormat;
  54. baseDescriptor.depthBufferBits = 0;
  55. normalDescriptor = baseDescriptor;
  56. this.allocateDepth = true;
  57. this.allocateNormal = true;
  58. this.shaderTagIds = k_DepthNormals;
  59. }
  60. /// <inheritdoc/>
  61. public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
  62. {
  63. if (this.allocateNormal)
  64. {
  65. RenderTextureDescriptor desc = normalDescriptor;
  66. desc.msaaSamples = renderingData.cameraData.renderer.useDepthPriming ? m_RendererMSAASamples : 1;
  67. cmd.GetTemporaryRT(normalHandle.id, desc, FilterMode.Point);
  68. }
  69. if (this.allocateDepth)
  70. cmd.GetTemporaryRT(depthHandle.id, depthDescriptor, FilterMode.Point);
  71. if (renderingData.cameraData.renderer.useDepthPriming && (renderingData.cameraData.renderType == CameraRenderType.Base || renderingData.cameraData.clearDepth))
  72. {
  73. ConfigureTarget(
  74. new RenderTargetIdentifier(normalHandle.Identifier(), 0, CubemapFace.Unknown, -1),
  75. new RenderTargetIdentifier(renderingData.cameraData.renderer.cameraDepthTarget, 0, CubemapFace.Unknown, -1)
  76. );
  77. }
  78. else
  79. {
  80. ConfigureTarget(
  81. new RenderTargetIdentifier(normalHandle.Identifier(), 0, CubemapFace.Unknown, -1),
  82. new RenderTargetIdentifier(depthHandle.Identifier(), 0, CubemapFace.Unknown, -1)
  83. );
  84. }
  85. ConfigureClear(ClearFlag.All, Color.black);
  86. }
  87. /// <inheritdoc/>
  88. public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
  89. {
  90. // NOTE: Do NOT mix ProfilingScope with named CommandBuffers i.e. CommandBufferPool.Get("name").
  91. // Currently there's an issue which results in mismatched markers.
  92. CommandBuffer cmd = CommandBufferPool.Get();
  93. using (new ProfilingScope(cmd, ProfilingSampler.Get(URPProfileId.DepthNormalPrepass)))
  94. {
  95. context.ExecuteCommandBuffer(cmd);
  96. cmd.Clear();
  97. var sortFlags = renderingData.cameraData.defaultOpaqueSortFlags;
  98. var drawSettings = CreateDrawingSettings(this.shaderTagIds, ref renderingData, sortFlags);
  99. drawSettings.perObjectData = PerObjectData.None;
  100. ref CameraData cameraData = ref renderingData.cameraData;
  101. Camera camera = cameraData.camera;
  102. context.DrawRenderers(renderingData.cullResults, ref drawSettings, ref m_FilteringSettings);
  103. }
  104. context.ExecuteCommandBuffer(cmd);
  105. CommandBufferPool.Release(cmd);
  106. }
  107. /// <inheritdoc/>
  108. public override void OnCameraCleanup(CommandBuffer cmd)
  109. {
  110. if (cmd == null)
  111. {
  112. throw new ArgumentNullException("cmd");
  113. }
  114. if (depthHandle != RenderTargetHandle.CameraTarget)
  115. {
  116. if (this.allocateNormal)
  117. cmd.ReleaseTemporaryRT(normalHandle.id);
  118. if (this.allocateDepth)
  119. cmd.ReleaseTemporaryRT(depthHandle.id);
  120. normalHandle = RenderTargetHandle.CameraTarget;
  121. depthHandle = RenderTargetHandle.CameraTarget;
  122. }
  123. }
  124. }
  125. }