123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- using System;
- using UnityEngine.Experimental.GlobalIllumination;
- using UnityEngine.Experimental.Rendering;
- using UnityEngine.Profiling;
- using Unity.Collections;
- using UnityEngine.Rendering.RenderGraphModule;
-
- namespace UnityEngine.Rendering.Universal.Internal
- {
- // Render all tiled-based deferred lights.
- internal class GBufferPass : ScriptableRenderPass
- {
- internal static readonly int s_CameraNormalsTextureID = Shader.PropertyToID("_CameraNormalsTexture");
- static ShaderTagId s_ShaderTagLit = new ShaderTagId("Lit");
- static ShaderTagId s_ShaderTagSimpleLit = new ShaderTagId("SimpleLit");
- static ShaderTagId s_ShaderTagUnlit = new ShaderTagId("Unlit");
- static ShaderTagId s_ShaderTagComplexLit = new ShaderTagId("ComplexLit");
- static ShaderTagId s_ShaderTagUniversalGBuffer = new ShaderTagId("UniversalGBuffer");
- static ShaderTagId s_ShaderTagUniversalMaterialType = new ShaderTagId("UniversalMaterialType");
-
- DeferredLights m_DeferredLights;
-
- static ShaderTagId[] s_ShaderTagValues;
- static RenderStateBlock[] s_RenderStateBlocks;
-
- FilteringSettings m_FilteringSettings;
- RenderStateBlock m_RenderStateBlock;
- private PassData m_PassData;
-
- public GBufferPass(RenderPassEvent evt, RenderQueueRange renderQueueRange, LayerMask layerMask, StencilState stencilState, int stencilReference, DeferredLights deferredLights)
- {
- base.profilingSampler = new ProfilingSampler("Draw GBuffer");
- base.renderPassEvent = evt;
- m_PassData = new PassData();
-
- m_DeferredLights = deferredLights;
- m_FilteringSettings = new FilteringSettings(renderQueueRange, layerMask);
- m_RenderStateBlock = new RenderStateBlock(RenderStateMask.Nothing);
-
- m_RenderStateBlock.stencilState = stencilState;
- m_RenderStateBlock.stencilReference = stencilReference;
- m_RenderStateBlock.mask = RenderStateMask.Stencil;
-
- if (s_ShaderTagValues == null)
- {
- s_ShaderTagValues = new ShaderTagId[5];
- s_ShaderTagValues[0] = s_ShaderTagLit;
- s_ShaderTagValues[1] = s_ShaderTagSimpleLit;
- s_ShaderTagValues[2] = s_ShaderTagUnlit;
- s_ShaderTagValues[3] = s_ShaderTagComplexLit;
- s_ShaderTagValues[4] = new ShaderTagId(); // Special catch all case for materials where UniversalMaterialType is not defined or the tag value doesn't match anything we know.
- }
-
- if (s_RenderStateBlocks == null)
- {
- s_RenderStateBlocks = new RenderStateBlock[5];
- s_RenderStateBlocks[0] = DeferredLights.OverwriteStencil(m_RenderStateBlock, (int)StencilUsage.MaterialMask, (int)StencilUsage.MaterialLit);
- s_RenderStateBlocks[1] = DeferredLights.OverwriteStencil(m_RenderStateBlock, (int)StencilUsage.MaterialMask, (int)StencilUsage.MaterialSimpleLit);
- s_RenderStateBlocks[2] = DeferredLights.OverwriteStencil(m_RenderStateBlock, (int)StencilUsage.MaterialMask, (int)StencilUsage.MaterialUnlit);
- s_RenderStateBlocks[3] = DeferredLights.OverwriteStencil(m_RenderStateBlock, (int)StencilUsage.MaterialMask, (int)StencilUsage.MaterialUnlit); // Fill GBuffer, but skip lighting pass for ComplexLit
- s_RenderStateBlocks[4] = s_RenderStateBlocks[0];
- }
- }
-
- public void Dispose()
- {
- m_DeferredLights?.ReleaseGbufferResources();
- }
-
- [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)]
- public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
- {
- RTHandle[] gbufferAttachments = m_DeferredLights.GbufferAttachments;
-
- if (cmd != null)
- {
- var allocateGbufferDepth = true;
- if (m_DeferredLights.UseFramebufferFetch && (m_DeferredLights.DepthCopyTexture != null && m_DeferredLights.DepthCopyTexture.rt != null))
- {
- m_DeferredLights.GbufferAttachments[m_DeferredLights.GbufferDepthIndex] = m_DeferredLights.DepthCopyTexture;
- allocateGbufferDepth = false;
- }
- // Create and declare the render targets used in the pass
- for (int i = 0; i < gbufferAttachments.Length; ++i)
- {
- // Lighting buffer has already been declared with line ConfigureCameraTarget(m_ActiveCameraColorAttachment.Identifier(), ...) in DeferredRenderer.Setup
- if (i == m_DeferredLights.GBufferLightingIndex)
- continue;
-
- // Normal buffer may have already been created if there was a depthNormal prepass before.
- // DepthNormal prepass is needed for forward-only materials when SSAO is generated between gbuffer and deferred lighting pass.
- if (i == m_DeferredLights.GBufferNormalSmoothnessIndex && m_DeferredLights.HasNormalPrepass)
- continue;
-
- if (i == m_DeferredLights.GbufferDepthIndex && !allocateGbufferDepth)
- continue;
-
- // No need to setup temporaryRTs if we are using input attachments as they will be Memoryless
- if (m_DeferredLights.UseFramebufferFetch && (i != m_DeferredLights.GbufferDepthIndex && !m_DeferredLights.HasDepthPrepass))
- continue;
-
- m_DeferredLights.ReAllocateGBufferIfNeeded(cameraTextureDescriptor, i);
-
- cmd.SetGlobalTexture(m_DeferredLights.GbufferAttachments[i].name, m_DeferredLights.GbufferAttachments[i].nameID);
- }
- }
-
- if (m_DeferredLights.UseFramebufferFetch)
- m_DeferredLights.UpdateDeferredInputAttachments();
-
- // Disable obsolete warning for internal usage
- #pragma warning disable CS0618
- ConfigureTarget(m_DeferredLights.GbufferAttachments, m_DeferredLights.DepthAttachment, m_DeferredLights.GbufferFormats);
-
- // We must explicitly specify we don't want any clear to avoid unwanted side-effects.
- // ScriptableRenderer will implicitly force a clear the first time the camera color/depth targets are bound.
- ConfigureClear(ClearFlag.None, Color.black);
- #pragma warning restore CS0618
- }
-
- [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)]
- public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
- {
- ContextContainer frameData = renderingData.frameData;
- UniversalRenderingData universalRenderingData = frameData.Get<UniversalRenderingData>();
- UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
- UniversalLightData lightData = frameData.Get<UniversalLightData>();
-
- m_PassData.deferredLights = m_DeferredLights;
- InitRendererLists(ref m_PassData, context, default(RenderGraph), universalRenderingData, cameraData, lightData, false);
-
- var cmd = renderingData.commandBuffer;
- using (new ProfilingScope(cmd, profilingSampler))
- {
- #if UNITY_EDITOR
- // Need to clear the bounded targets to get scene-view filtering working.
- if (CoreUtils.IsSceneFilteringEnabled() && cameraData.camera.sceneViewFilterMode == Camera.SceneViewFilterMode.ShowFiltered)
- cmd.ClearRenderTarget(RTClearFlags.Color, Color.clear);
- #endif
-
- ExecutePass(CommandBufferHelpers.GetRasterCommandBuffer(cmd), m_PassData, m_PassData.rendererList, m_PassData.objectsWithErrorRendererList);
-
- // If any sub-system needs camera normal texture, make it available.
- // Input attachments will only be used when this is not needed so safe to skip in that case
- if (!m_DeferredLights.UseFramebufferFetch)
- renderingData.commandBuffer.SetGlobalTexture(s_CameraNormalsTextureID, m_DeferredLights.GbufferAttachments[m_DeferredLights.GBufferNormalSmoothnessIndex]);
- }
- }
-
- static void ExecutePass(RasterCommandBuffer cmd, PassData data, RendererList rendererList, RendererList errorRendererList)
- {
- bool usesRenderingLayers = data.deferredLights.UseRenderingLayers && !data.deferredLights.HasRenderingLayerPrepass;
- if (usesRenderingLayers)
- cmd.SetKeyword(ShaderGlobalKeywords.WriteRenderingLayers, true);
-
- if (data.deferredLights.IsOverlay)
- data.deferredLights.ClearStencilPartial(cmd);
-
- cmd.DrawRendererList(rendererList);
-
- // Render objects that did not match any shader pass with error shader
- RenderingUtils.DrawRendererListObjectsWithError(cmd, ref errorRendererList);
-
- // Clean up
- if (usesRenderingLayers)
- cmd.SetKeyword(ShaderGlobalKeywords.WriteRenderingLayers, false);
- }
-
- /// <summary>
- /// Shared pass data
- /// </summary>
- private class PassData
- {
- internal TextureHandle[] gbuffer;
- internal TextureHandle depth;
-
- internal DeferredLights deferredLights;
-
- internal RendererListHandle rendererListHdl;
- internal RendererListHandle objectsWithErrorRendererListHdl;
-
- // Required for code sharing purpose between RG and non-RG.
- internal RendererList rendererList;
- internal RendererList objectsWithErrorRendererList;
- }
-
-
- private void InitRendererLists( ref PassData passData, ScriptableRenderContext context, RenderGraph renderGraph, UniversalRenderingData renderingData, UniversalCameraData cameraData, UniversalLightData lightData, bool useRenderGraph)
- {
- // User can stack several scriptable renderers during rendering but deferred renderer should only lit pixels added by this gbuffer pass.
- // 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
- // mark what pixel to shade during deferred pass. Gbuffer will always mark pixels using their material types.
- ShaderTagId lightModeTag = s_ShaderTagUniversalGBuffer;
- var drawingSettings = CreateDrawingSettings(lightModeTag, renderingData, cameraData, lightData, cameraData.defaultOpaqueSortFlags);
- var filterSettings = m_FilteringSettings;
- NativeArray<ShaderTagId> tagValues = new NativeArray<ShaderTagId>(s_ShaderTagValues, Allocator.Temp);
- NativeArray<RenderStateBlock> stateBlocks = new NativeArray<RenderStateBlock>(s_RenderStateBlocks, Allocator.Temp);
- var param = new RendererListParams(renderingData.cullResults, drawingSettings, filterSettings)
- {
- tagValues = tagValues,
- stateBlocks = stateBlocks,
- tagName = s_ShaderTagUniversalMaterialType,
- isPassTagName = false
- };
- if (useRenderGraph)
- {
- passData.rendererListHdl = renderGraph.CreateRendererList(param);
- }
- else
- {
- passData.rendererList = context.CreateRendererList(ref param);
- }
- tagValues.Dispose();
- stateBlocks.Dispose();
-
- if (useRenderGraph)
- {
- RenderingUtils.CreateRendererListObjectsWithError(renderGraph, ref renderingData.cullResults, cameraData.camera, filterSettings, SortingCriteria.None, ref passData.objectsWithErrorRendererListHdl);
- }
- else
- {
- RenderingUtils.CreateRendererListObjectsWithError(context, ref renderingData.cullResults, cameraData.camera, filterSettings, SortingCriteria.None, ref passData.objectsWithErrorRendererList);
- }
- }
-
- internal void Render(RenderGraph renderGraph, ContextContainer frameData, TextureHandle cameraColor, TextureHandle cameraDepth)
- {
- UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
- UniversalRenderingData renderingData = frameData.Get<UniversalRenderingData>();
- UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
- UniversalLightData lightData = frameData.Get<UniversalLightData>();
-
- TextureHandle[] gbuffer;
-
- using (var builder = renderGraph.AddRasterRenderPass<PassData>(profilingSampler.name, out var passData,profilingSampler))
- {
- // Note: This code is pretty confusing as passData.gbuffer[i] and gbuffer[i] actually point to the same array but seem to be mixed in this code.
- passData.gbuffer = gbuffer = m_DeferredLights.GbufferTextureHandles;
- for (int i = 0; i < m_DeferredLights.GBufferSliceCount; i++)
- {
- var gbufferSlice = cameraData.cameraTargetDescriptor;
- gbufferSlice.depthBufferBits = 0; // make sure no depth surface is actually created
- gbufferSlice.stencilFormat = GraphicsFormat.None;
-
- if (i == m_DeferredLights.GBufferNormalSmoothnessIndex && m_DeferredLights.HasNormalPrepass)
- gbuffer[i] = resourceData.cameraNormalsTexture;
- else if (m_DeferredLights.UseRenderingLayers && i == m_DeferredLights.GBufferRenderingLayers && !m_DeferredLights.UseLightLayers)
- gbuffer[i] = resourceData.renderingLayersTexture;
- else if (i != m_DeferredLights.GBufferLightingIndex)
- {
- gbufferSlice.graphicsFormat = m_DeferredLights.GetGBufferFormat(i);
- gbuffer[i] = UniversalRenderer.CreateRenderGraphTexture(renderGraph, gbufferSlice, DeferredLights.k_GBufferNames[i], true);
- }
- else
- gbuffer[i] = cameraColor;
-
- // Note: We don't store the returned handle here it is a versioned handle.
- // In general it should be fine to use unversioned handles anyway especially unversioned resources
- // should be registered in the frame data
- builder.SetRenderAttachment(gbuffer[i], i, AccessFlags.Write);
- }
-
- RenderGraphUtils.UseDBufferIfValid(builder, resourceData);
- resourceData.gBuffer = gbuffer;
-
- passData.depth = cameraDepth;
- builder.SetRenderAttachmentDepth(cameraDepth, AccessFlags.Write);
- passData.deferredLights = m_DeferredLights;
-
- InitRendererLists(ref passData, default(ScriptableRenderContext), renderGraph, renderingData, cameraData, lightData, true);
- builder.UseRendererList(passData.rendererListHdl);
- builder.UseRendererList(passData.objectsWithErrorRendererListHdl);
-
- builder.AllowPassCulling(false);
- builder.AllowGlobalStateModification(true);
-
- builder.SetRenderFunc((PassData data, RasterGraphContext context) =>
- {
- ExecutePass(context.cmd, data, data.rendererListHdl, data.objectsWithErrorRendererListHdl);
- });
- }
- }
- }
- }
|