GBufferPass.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. using UnityEngine.Experimental.GlobalIllumination;
  2. using UnityEngine.Experimental.Rendering;
  3. using UnityEngine.Profiling;
  4. using Unity.Collections;
  5. namespace UnityEngine.Rendering.Universal.Internal
  6. {
  7. // Render all tiled-based deferred lights.
  8. internal class GBufferPass : ScriptableRenderPass
  9. {
  10. static readonly int s_CameraNormalsTextureID = Shader.PropertyToID("_CameraNormalsTexture");
  11. static ShaderTagId s_ShaderTagLit = new ShaderTagId("Lit");
  12. static ShaderTagId s_ShaderTagSimpleLit = new ShaderTagId("SimpleLit");
  13. static ShaderTagId s_ShaderTagUnlit = new ShaderTagId("Unlit");
  14. static ShaderTagId s_ShaderTagUniversalGBuffer = new ShaderTagId("UniversalGBuffer");
  15. static ShaderTagId s_ShaderTagUniversalMaterialType = new ShaderTagId("UniversalMaterialType");
  16. ProfilingSampler m_ProfilingSampler = new ProfilingSampler("Render GBuffer");
  17. DeferredLights m_DeferredLights;
  18. ShaderTagId[] m_ShaderTagValues;
  19. RenderStateBlock[] m_RenderStateBlocks;
  20. FilteringSettings m_FilteringSettings;
  21. RenderStateBlock m_RenderStateBlock;
  22. public GBufferPass(RenderPassEvent evt, RenderQueueRange renderQueueRange, LayerMask layerMask, StencilState stencilState, int stencilReference, DeferredLights deferredLights)
  23. {
  24. base.profilingSampler = new ProfilingSampler(nameof(GBufferPass));
  25. base.renderPassEvent = evt;
  26. m_DeferredLights = deferredLights;
  27. m_FilteringSettings = new FilteringSettings(renderQueueRange, layerMask);
  28. m_RenderStateBlock = new RenderStateBlock(RenderStateMask.Nothing);
  29. m_RenderStateBlock.stencilState = stencilState;
  30. m_RenderStateBlock.stencilReference = stencilReference;
  31. m_RenderStateBlock.mask = RenderStateMask.Stencil;
  32. m_ShaderTagValues = new ShaderTagId[4];
  33. m_ShaderTagValues[0] = s_ShaderTagLit;
  34. m_ShaderTagValues[1] = s_ShaderTagSimpleLit;
  35. m_ShaderTagValues[2] = s_ShaderTagUnlit;
  36. m_ShaderTagValues[3] = new ShaderTagId(); // Special catch all case for materials where UniversalMaterialType is not defined or the tag value doesn't match anything we know.
  37. m_RenderStateBlocks = new RenderStateBlock[4];
  38. m_RenderStateBlocks[0] = DeferredLights.OverwriteStencil(m_RenderStateBlock, (int)StencilUsage.MaterialMask, (int)StencilUsage.MaterialLit);
  39. m_RenderStateBlocks[1] = DeferredLights.OverwriteStencil(m_RenderStateBlock, (int)StencilUsage.MaterialMask, (int)StencilUsage.MaterialSimpleLit);
  40. m_RenderStateBlocks[2] = DeferredLights.OverwriteStencil(m_RenderStateBlock, (int)StencilUsage.MaterialMask, (int)StencilUsage.MaterialUnlit);
  41. m_RenderStateBlocks[3] = m_RenderStateBlocks[0];
  42. }
  43. public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
  44. {
  45. RenderTargetHandle[] gbufferAttachments = m_DeferredLights.GbufferAttachments;
  46. if (cmd != null)
  47. {
  48. // Create and declare the render targets used in the pass
  49. for (int i = 0; i < gbufferAttachments.Length; ++i)
  50. {
  51. // Lighting buffer has already been declared with line ConfigureCameraTarget(m_ActiveCameraColorAttachment.Identifier(), ...) in DeferredRenderer.Setup
  52. if (i == m_DeferredLights.GBufferLightingIndex)
  53. continue;
  54. // Normal buffer may have already been created if there was a depthNormal prepass before.
  55. // DepthNormal prepass is needed for forward-only materials when SSAO is generated between gbuffer and deferred lighting pass.
  56. if (i == m_DeferredLights.GBufferNormalSmoothnessIndex && m_DeferredLights.HasNormalPrepass)
  57. {
  58. if (m_DeferredLights.UseRenderPass)
  59. m_DeferredLights.DeferredInputIsTransient[i] = false;
  60. continue;
  61. }
  62. // No need to setup temporaryRTs if we are using input attachments as they will be Memoryless
  63. if (m_DeferredLights.UseRenderPass && i != m_DeferredLights.GBufferShadowMask && i != m_DeferredLights.GBufferRenderingLayers && (i != m_DeferredLights.GbufferDepthIndex && !m_DeferredLights.HasDepthPrepass))
  64. continue;
  65. RenderTextureDescriptor gbufferSlice = cameraTextureDescriptor;
  66. gbufferSlice.depthBufferBits = 0; // make sure no depth surface is actually created
  67. gbufferSlice.stencilFormat = GraphicsFormat.None;
  68. gbufferSlice.graphicsFormat = m_DeferredLights.GetGBufferFormat(i);
  69. cmd.GetTemporaryRT(m_DeferredLights.GbufferAttachments[i].id, gbufferSlice);
  70. }
  71. }
  72. ConfigureTarget(m_DeferredLights.GbufferAttachmentIdentifiers, m_DeferredLights.DepthAttachmentIdentifier, m_DeferredLights.GbufferFormats);
  73. // We must explicitely specify we don't want any clear to avoid unwanted side-effects.
  74. // ScriptableRenderer will implicitely force a clear the first time the camera color/depth targets are bound.
  75. ConfigureClear(ClearFlag.None, Color.black);
  76. }
  77. public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
  78. {
  79. CommandBuffer gbufferCommands = CommandBufferPool.Get();
  80. using (new ProfilingScope(gbufferCommands, m_ProfilingSampler))
  81. {
  82. context.ExecuteCommandBuffer(gbufferCommands);
  83. gbufferCommands.Clear();
  84. // User can stack several scriptable renderers during rendering but deferred renderer should only lit pixels added by this gbuffer pass.
  85. // If we detect we are in such case (camera is in overlay mode), we clear the highest bits of stencil we have control of and use them to
  86. // mark what pixel to shade during deferred pass. Gbuffer will always mark pixels using their material types.
  87. if (m_DeferredLights.IsOverlay)
  88. {
  89. m_DeferredLights.ClearStencilPartial(gbufferCommands);
  90. context.ExecuteCommandBuffer(gbufferCommands);
  91. gbufferCommands.Clear();
  92. }
  93. ref CameraData cameraData = ref renderingData.cameraData;
  94. Camera camera = cameraData.camera;
  95. ShaderTagId lightModeTag = s_ShaderTagUniversalGBuffer;
  96. DrawingSettings drawingSettings = CreateDrawingSettings(lightModeTag, ref renderingData, renderingData.cameraData.defaultOpaqueSortFlags);
  97. ShaderTagId universalMaterialTypeTag = s_ShaderTagUniversalMaterialType;
  98. NativeArray<ShaderTagId> tagValues = new NativeArray<ShaderTagId>(m_ShaderTagValues, Allocator.Temp);
  99. NativeArray<RenderStateBlock> stateBlocks = new NativeArray<RenderStateBlock>(m_RenderStateBlocks, Allocator.Temp);
  100. context.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref m_FilteringSettings, universalMaterialTypeTag, false, tagValues, stateBlocks);
  101. tagValues.Dispose();
  102. stateBlocks.Dispose();
  103. // Render objects that did not match any shader pass with error shader
  104. RenderingUtils.RenderObjectsWithError(context, ref renderingData.cullResults, camera, m_FilteringSettings, SortingCriteria.None);
  105. // If any sub-system needs camera normal texture, make it available.
  106. gbufferCommands.SetGlobalTexture(s_CameraNormalsTextureID, m_DeferredLights.GbufferAttachmentIdentifiers[m_DeferredLights.GBufferNormalSmoothnessIndex]);
  107. }
  108. context.ExecuteCommandBuffer(gbufferCommands);
  109. CommandBufferPool.Release(gbufferCommands);
  110. }
  111. public override void OnCameraCleanup(CommandBuffer cmd)
  112. {
  113. RenderTargetHandle[] gbufferAttachments = m_DeferredLights.GbufferAttachments;
  114. for (int i = 0; i < gbufferAttachments.Length; ++i)
  115. {
  116. if (i == m_DeferredLights.GBufferLightingIndex)
  117. continue;
  118. if (i == m_DeferredLights.GBufferNormalSmoothnessIndex && m_DeferredLights.HasNormalPrepass)
  119. continue;
  120. cmd.ReleaseTemporaryRT(gbufferAttachments[i].id);
  121. }
  122. }
  123. }
  124. }