From 0182ca75b8851be31251a810092988abec3ff090 Mon Sep 17 00:00:00 2001 From: Yetman Date: Sat, 7 May 2022 04:23:39 +0200 Subject: [PATCH 1/4] Quick fix for URP12 --- Runtime/RenderFeatures/CustomPostProcess.cs | 34 ++++++++++++++++++--- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/Runtime/RenderFeatures/CustomPostProcess.cs b/Runtime/RenderFeatures/CustomPostProcess.cs index eb3e7f9..ec968e5 100644 --- a/Runtime/RenderFeatures/CustomPostProcess.cs +++ b/Runtime/RenderFeatures/CustomPostProcess.cs @@ -49,7 +49,7 @@ public CustomPostProcessSettings(){ /// /// A handle to the "_AfterPostProcessTexture" used as the target for the builtin post processing pass in the last camera in the camera stack /// - private RenderTargetHandle m_AfterPostProcessColor; + private RenderTargetHandle m_AfterPostProcessColor, m_BeforePostProcessColor; /// /// Injects the custom post-processing render passes. @@ -58,15 +58,25 @@ public CustomPostProcessSettings(){ /// Rendering state. Use this to setup render passes. public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) { + UniversalRenderer u_renderer = renderer as UniversalRenderer; + if(u_renderer == null) { + Debug.LogWarning("The CustomPostProcess renderer feature supports the UniversalRenderer only"); + return; + } + // Only inject passes if post processing is enabled if(renderingData.cameraData.postProcessEnabled) { // For each pass, only inject if there is at least one custom post-processing renderer class in it. if(m_AfterOpaqueAndSky.HasPostProcessRenderers && m_AfterOpaqueAndSky.PrepareRenderers(ref renderingData)){ - m_AfterOpaqueAndSky.Setup(renderer.cameraColorTarget, renderer.cameraColorTarget); + //m_AfterOpaqueAndSky.Setup(renderer.cameraColorTarget, renderer.cameraColorTarget); + //For URP 12 + m_AfterOpaqueAndSky.Setup(m_BeforePostProcessColor.Identifier(), m_BeforePostProcessColor.Identifier()); renderer.EnqueuePass(m_AfterOpaqueAndSky); } if(m_BeforePostProcess.HasPostProcessRenderers && m_BeforePostProcess.PrepareRenderers(ref renderingData)){ - m_BeforePostProcess.Setup(renderer.cameraColorTarget, renderer.cameraColorTarget); + //m_BeforePostProcess.Setup(renderer.cameraColorTarget, renderer.cameraColorTarget); + //For URP 12 + m_BeforePostProcess.Setup(m_BeforePostProcessColor.Identifier(), m_BeforePostProcessColor.Identifier()); renderer.EnqueuePass(m_BeforePostProcess); } if(m_AfterPostProcess.HasPostProcessRenderers && m_AfterPostProcess.PrepareRenderers(ref renderingData)){ @@ -84,7 +94,10 @@ public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingD public override void Create() { // This is copied from the forward renderer - m_AfterPostProcessColor.Init("_AfterPostProcessTexture"); + //m_AfterPostProcessColor.Init("_AfterPostProcessTexture"); + //For URP 12 + m_AfterPostProcessColor.Init("_CameraColorAttachmentB"); + m_BeforePostProcessColor.Init("_CameraColorAttachmentA"); // Create the three render passes and send the custom post-processing renderer classes to each Dictionary shared = new Dictionary(); m_AfterOpaqueAndSky = new CustomPostProcessRenderPass(CustomPostProcessInjectionPoint.AfterOpaqueAndSky, InstantiateRenderers(settings.renderersAfterOpaqueAndSky, shared)); @@ -208,7 +221,8 @@ public CustomPostProcessRenderPass(CustomPostProcessInjectionPoint injectionPoin break; case CustomPostProcessInjectionPoint.AfterPostProcess: // NOTE: This was initially "AfterRenderingPostProcessing" but it made the builtin post-processing to blit directly to the camera target. - renderPassEvent = RenderPassEvent.AfterRendering; + // NOTE: For URP 12, we are back to using "AfterRenderingPostProcessing" + renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing; m_PassName = "Custom PostProcess after PostProcess"; break; } @@ -258,6 +272,16 @@ public void Setup(RenderTargetIdentifier source, RenderTargetIdentifier destinat this.m_Destination = destination; } + public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) + { + base.OnCameraSetup(cmd, ref renderingData); + } + + public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) + { + base.Configure(cmd, cameraTextureDescriptor); + } + /// /// Prepares the renderer for executing on this frame and checks if any of them actually requires rendering /// From b47b92212c97f6ea87eb945e3503031e70a336bc Mon Sep 17 00:00:00 2001 From: Yetman Date: Sat, 7 May 2022 04:30:35 +0200 Subject: [PATCH 2/4] Updated readme and package.json --- README.md | 6 +++--- package.json | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 046d976..2e767f3 100644 --- a/README.md +++ b/README.md @@ -29,10 +29,10 @@ Other custom effects in samples but not used in screenshots: ## Compatibility -* Unity 2020.2 -* URP 10.2.2 +This branch is under development and it targets: -**Note:** There is a branch with support for URP 8.2.0 (Unity 2020.1) which you can find [here](https://github.com/yahiaetman/URPCustomPostProcessingStack/tree/URP-8.2.0). +* Unity 2021.2 & 2021.3 +* URP 12.1 ## Features diff --git a/package.json b/package.json index 6dcbaec..c44822d 100644 --- a/package.json +++ b/package.json @@ -3,11 +3,11 @@ "version": "2.0.0", "displayName": "Universal RP Post-Processing Stack", "description": "A post-processing stack for Universal RP", - "unity": "2020.2", + "unity": "2021.2", "unityRelease": "0f1", "dependencies": { - "com.unity.render-pipelines.universal": "10.2.2", - "com.unity.render-pipelines.core": "10.2.2" + "com.unity.render-pipelines.universal": "12.1.0", + "com.unity.render-pipelines.core": "12.1.0" }, "keywords": [ "graphics", From d1e7d6001977cc261d8caa4627fc55f0ba758afc Mon Sep 17 00:00:00 2001 From: Yetman Date: Tue, 10 May 2022 22:29:40 +0200 Subject: [PATCH 3/4] Change passes to use renderer.cameraColorTarget. --- Runtime/RenderFeatures/CustomPostProcess.cs | 71 ++++----------------- 1 file changed, 14 insertions(+), 57 deletions(-) diff --git a/Runtime/RenderFeatures/CustomPostProcess.cs b/Runtime/RenderFeatures/CustomPostProcess.cs index ec968e5..ba63445 100644 --- a/Runtime/RenderFeatures/CustomPostProcess.cs +++ b/Runtime/RenderFeatures/CustomPostProcess.cs @@ -46,11 +46,6 @@ public CustomPostProcessSettings(){ /// private CustomPostProcessRenderPass m_AfterOpaqueAndSky, m_BeforePostProcess, m_AfterPostProcess; - /// - /// A handle to the "_AfterPostProcessTexture" used as the target for the builtin post processing pass in the last camera in the camera stack - /// - private RenderTargetHandle m_AfterPostProcessColor, m_BeforePostProcessColor; - /// /// Injects the custom post-processing render passes. /// @@ -58,31 +53,22 @@ public CustomPostProcessSettings(){ /// Rendering state. Use this to setup render passes. public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) { - UniversalRenderer u_renderer = renderer as UniversalRenderer; - if(u_renderer == null) { - Debug.LogWarning("The CustomPostProcess renderer feature supports the UniversalRenderer only"); - return; - } + // UniversalRenderer u_renderer = renderer as UniversalRenderer; + // if(u_renderer == null) { + // Debug.LogWarning("The CustomPostProcess renderer feature supports the UniversalRenderer only"); + // return; + // } // Only inject passes if post processing is enabled if(renderingData.cameraData.postProcessEnabled) { // For each pass, only inject if there is at least one custom post-processing renderer class in it. if(m_AfterOpaqueAndSky.HasPostProcessRenderers && m_AfterOpaqueAndSky.PrepareRenderers(ref renderingData)){ - //m_AfterOpaqueAndSky.Setup(renderer.cameraColorTarget, renderer.cameraColorTarget); - //For URP 12 - m_AfterOpaqueAndSky.Setup(m_BeforePostProcessColor.Identifier(), m_BeforePostProcessColor.Identifier()); renderer.EnqueuePass(m_AfterOpaqueAndSky); } if(m_BeforePostProcess.HasPostProcessRenderers && m_BeforePostProcess.PrepareRenderers(ref renderingData)){ - //m_BeforePostProcess.Setup(renderer.cameraColorTarget, renderer.cameraColorTarget); - //For URP 12 - m_BeforePostProcess.Setup(m_BeforePostProcessColor.Identifier(), m_BeforePostProcessColor.Identifier()); renderer.EnqueuePass(m_BeforePostProcess); } if(m_AfterPostProcess.HasPostProcessRenderers && m_AfterPostProcess.PrepareRenderers(ref renderingData)){ - // If this camera resolve to the final target, then both the source & destination will be "_AfterPostProcessTexture" (Note: a final blit/post pass is added by the renderer). - var source = renderingData.cameraData.resolveFinalTarget ? m_AfterPostProcessColor.Identifier() : renderer.cameraColorTarget; - m_AfterPostProcess.Setup(source, source); renderer.EnqueuePass(m_AfterPostProcess); } } @@ -93,11 +79,6 @@ public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingD /// public override void Create() { - // This is copied from the forward renderer - //m_AfterPostProcessColor.Init("_AfterPostProcessTexture"); - //For URP 12 - m_AfterPostProcessColor.Init("_CameraColorAttachmentB"); - m_BeforePostProcessColor.Init("_CameraColorAttachmentA"); // Create the three render passes and send the custom post-processing renderer classes to each Dictionary shared = new Dictionary(); m_AfterOpaqueAndSky = new CustomPostProcessRenderPass(CustomPostProcessInjectionPoint.AfterOpaqueAndSky, InstantiateRenderers(settings.renderersAfterOpaqueAndSky, shared)); @@ -173,16 +154,6 @@ public class CustomPostProcessRenderPass : ScriptableRenderPass /// private RenderTextureDescriptor m_IntermediateDesc; - /// - /// The source of the color data for the render pass - /// - private RenderTargetIdentifier m_Source; - - /// - /// The destination of the color data for the render pass - /// - private RenderTargetIdentifier m_Destination; - /// /// A list of profiling samplers, one for each post process renderer /// @@ -262,16 +233,6 @@ private void CleanupIntermediate(CommandBuffer cmd){ } } - /// - /// Setup the source and destination render targets - /// - /// Source render target - /// Destination render target - public void Setup(RenderTargetIdentifier source, RenderTargetIdentifier destination){ - this.m_Source = source; - this.m_Destination = destination; - } - public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) { base.OnCameraSetup(cmd, ref renderingData); @@ -312,7 +273,7 @@ public bool PrepareRenderers(ref RenderingData renderingData){ // return if no renderers are active return m_ActivePostProcessRenderers.Count != 0; - } + } /// /// Execute the custom post processing renderers @@ -321,6 +282,8 @@ public bool PrepareRenderers(ref RenderingData renderingData){ /// Current rendering data public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { + RenderTargetIdentifier target = renderingData.cameraData.renderer.cameraColorTarget; + // Copy camera target description for intermediate RTs. Disable multisampling and depth buffer for the intermediate targets. m_IntermediateDesc = renderingData.cameraData.cameraTargetDescriptor; m_IntermediateDesc.msaaSamples = 1; @@ -348,18 +311,12 @@ public override void Execute(ScriptableRenderContext context, ref RenderingData RenderTargetIdentifier source, destination; if(index == 0){ // If this is the first renderers then the source will be the external source (not intermediate). - source = m_Source; + source = target; if(m_ActivePostProcessRenderers.Count == 1){ - // There is only one renderer, check if the source is the same as the destination - if(m_Source == m_Destination){ // Since we can't bind the same RT as a texture and a render target at the same time, we will blit to an intermediate RT. - destination = GetIntermediate(cmd, 0); - // Then we will blit back to the destination. - requireBlitBack = true; - } else { - // Otherwise, we can directly blit from source to destination. - destination = m_Destination; - } + destination = GetIntermediate(cmd, 0); + // Then we will blit back to the destination. + requireBlitBack = true; } else { // If there is more than one renderer, we will need to the intermediate RT anyway. destination = GetIntermediate(cmd, intermediateIndex); @@ -369,7 +326,7 @@ public override void Execute(ScriptableRenderContext context, ref RenderingData source = GetIntermediate(cmd, intermediateIndex); if(index == m_ActivePostProcessRenderers.Count - 1){ // If this is the last renderer, blit to the destination directly. - destination = m_Destination; + destination = target; } else { // Otherwise, flip the intermediate RT index and set as destination. // This will act as a ping pong process between the 2 RT where color data keeps moving back and forth while being processed on each pass. @@ -391,7 +348,7 @@ public override void Execute(ScriptableRenderContext context, ref RenderingData // If blit back is needed, blit from the intermediate RT to the destination (see above for explanation) if(requireBlitBack) - Blit(cmd, m_Intermediate[0].Identifier(), m_Destination); + Blit(cmd, m_Intermediate[0].Identifier(), target); // Release allocated Intermediate RTs. CleanupIntermediate(cmd); From 67b901dc67e35ed586afe9291e8856ac805f1283 Mon Sep 17 00:00:00 2001 From: JohnManna Date: Thu, 15 Sep 2022 03:14:23 -0400 Subject: [PATCH 4/4] swapped RenderTargetHandles for RTHandles --- Runtime/RenderFeatures/CustomPostProcess.cs | 195 ++++++++++---------- 1 file changed, 97 insertions(+), 98 deletions(-) diff --git a/Runtime/RenderFeatures/CustomPostProcess.cs b/Runtime/RenderFeatures/CustomPostProcess.cs index ba63445..63e3eeb 100644 --- a/Runtime/RenderFeatures/CustomPostProcess.cs +++ b/Runtime/RenderFeatures/CustomPostProcess.cs @@ -1,7 +1,8 @@ using System; using System.Collections.Generic; -namespace UnityEngine.Rendering.Universal.PostProcessing { +namespace UnityEngine.Rendering.Universal.PostProcessing +{ /// /// This render feature is responsible for: @@ -21,7 +22,8 @@ public class CustomPostProcess : ScriptableRendererFeature /// The settings for the custom post processing render feature. /// [Serializable] - public class CustomPostProcessSettings { + public class CustomPostProcessSettings + { /// /// Three list (one for each injection point) that holds the custom post processing renderers in order of execution during the render pass @@ -29,7 +31,8 @@ public class CustomPostProcessSettings { [SerializeField] public List renderersAfterOpaqueAndSky, renderersBeforePostProcess, renderersAfterPostProcess; - public CustomPostProcessSettings(){ + public CustomPostProcessSettings() + { renderersAfterOpaqueAndSky = new List(); renderersBeforePostProcess = new List(); renderersAfterPostProcess = new List(); @@ -58,17 +61,21 @@ public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingD // Debug.LogWarning("The CustomPostProcess renderer feature supports the UniversalRenderer only"); // return; // } - + // Only inject passes if post processing is enabled - if(renderingData.cameraData.postProcessEnabled) { + if (renderingData.cameraData.postProcessEnabled) + { // For each pass, only inject if there is at least one custom post-processing renderer class in it. - if(m_AfterOpaqueAndSky.HasPostProcessRenderers && m_AfterOpaqueAndSky.PrepareRenderers(ref renderingData)){ + if (m_AfterOpaqueAndSky.HasPostProcessRenderers && m_AfterOpaqueAndSky.PrepareRenderers(ref renderingData)) + { renderer.EnqueuePass(m_AfterOpaqueAndSky); } - if(m_BeforePostProcess.HasPostProcessRenderers && m_BeforePostProcess.PrepareRenderers(ref renderingData)){ + if (m_BeforePostProcess.HasPostProcessRenderers && m_BeforePostProcess.PrepareRenderers(ref renderingData)) + { renderer.EnqueuePass(m_BeforePostProcess); } - if(m_AfterPostProcess.HasPostProcessRenderers && m_AfterPostProcess.PrepareRenderers(ref renderingData)){ + if (m_AfterPostProcess.HasPostProcessRenderers && m_AfterPostProcess.PrepareRenderers(ref renderingData)) + { renderer.EnqueuePass(m_AfterPostProcess); } } @@ -85,28 +92,33 @@ public override void Create() m_BeforePostProcess = new CustomPostProcessRenderPass(CustomPostProcessInjectionPoint.BeforePostProcess, InstantiateRenderers(settings.renderersBeforePostProcess, shared)); m_AfterPostProcess = new CustomPostProcessRenderPass(CustomPostProcessInjectionPoint.AfterPostProcess, InstantiateRenderers(settings.renderersAfterPostProcess, shared)); } - + /// /// Converts the class name (AssemblyQualifiedName) to an instance. Filters out types that don't exist or don't match the requirements. /// /// The list of assembly-qualified class names /// Dictionary of shared instances keyed by class name /// List of renderers - private List InstantiateRenderers(List names, Dictionary shared){ + private List InstantiateRenderers(List names, Dictionary shared) + { var renderers = new List(names.Count); - foreach(var name in names){ - if(shared.TryGetValue(name, out var renderer)){ + foreach (var name in names) + { + if (shared.TryGetValue(name, out var renderer)) + { renderers.Add(renderer); - } else { + } + else + { var type = Type.GetType(name); - if(type == null || !type.IsSubclassOf(typeof(CustomPostProcessRenderer))) continue; + if (type == null || !type.IsSubclassOf(typeof(CustomPostProcessRenderer))) continue; var attribute = CustomPostProcessAttribute.GetAttribute(type); - if(attribute == null) continue; + if (attribute == null) continue; renderer = Activator.CreateInstance(type) as CustomPostProcessRenderer; renderers.Add(renderer); - - if(attribute.ShareInstance) + + if (attribute.ShareInstance) shared.Add(name, renderer); } } @@ -142,12 +154,7 @@ public class CustomPostProcessRenderPass : ScriptableRenderPass /// /// Array of 2 intermediate render targets used to hold intermediate results. /// - private RenderTargetHandle[] m_Intermediate; - - /// - /// Indentifies whether the intermediate render targets are allocated or not. - /// - private bool[] m_IntermediateAllocated; + private RTHandle[] m_Intermediate; /// /// The texture descriptor for the intermediate render targets. @@ -164,16 +171,20 @@ public class CustomPostProcessRenderPass : ScriptableRenderPass /// public bool HasPostProcessRenderers => m_PostProcessRenderers.Count != 0; + private readonly string[] _IntermediateRTNames = new string[2] { "_IntermediateRT0", "_IntermediateRT1" }; + /// /// Construct the custom post-processing render pass /// /// The post processing injection point /// The list of classes for the renderers to be executed by this render pass - public CustomPostProcessRenderPass(CustomPostProcessInjectionPoint injectionPoint, List renderers){ + public CustomPostProcessRenderPass(CustomPostProcessInjectionPoint injectionPoint, List renderers) + { this.injectionPoint = injectionPoint; this.m_ProfilingSamplers = new List(renderers.Count); this.m_PostProcessRenderers = renderers; - foreach(var renderer in renderers){ + foreach (var renderer in renderers) + { // Get renderer name and add it to the names list var attribute = CustomPostProcessAttribute.GetAttribute(renderer.GetType()); m_ProfilingSamplers.Add(new ProfilingSampler(attribute?.Name)); @@ -181,12 +192,13 @@ public CustomPostProcessRenderPass(CustomPostProcessInjectionPoint injectionPoin // Pre-allocate a list for active renderers this.m_ActivePostProcessRenderers = new List(renderers.Count); // Set render pass event and name based on the injection point. - switch(injectionPoint){ - case CustomPostProcessInjectionPoint.AfterOpaqueAndSky: - renderPassEvent = RenderPassEvent.AfterRenderingSkybox; + switch (injectionPoint) + { + case CustomPostProcessInjectionPoint.AfterOpaqueAndSky: + renderPassEvent = RenderPassEvent.AfterRenderingSkybox; m_PassName = "Custom PostProcess after Opaque & Sky"; break; - case CustomPostProcessInjectionPoint.BeforePostProcess: + case CustomPostProcessInjectionPoint.BeforePostProcess: renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing; m_PassName = "Custom PostProcess before PostProcess"; break; @@ -198,44 +210,27 @@ public CustomPostProcessRenderPass(CustomPostProcessInjectionPoint injectionPoin break; } // Initialize the IDs and allocation state of the intermediate render targets - m_Intermediate = new RenderTargetHandle[2]; - m_Intermediate[0].Init("_IntermediateRT0"); - m_Intermediate[1].Init("_IntermediateRT1"); - m_IntermediateAllocated = new bool[2]; - m_IntermediateAllocated[0] = false; - m_IntermediateAllocated[1] = false; - } - - /// - /// Gets the corresponding intermediate RT and allocates it if not already allocated - /// - /// The command buffer to use for allocation - /// The intermediate RT index - /// - private RenderTargetIdentifier GetIntermediate(CommandBuffer cmd, int index){ - if(!m_IntermediateAllocated[index]){ - cmd.GetTemporaryRT(m_Intermediate[index].id, m_IntermediateDesc); - m_IntermediateAllocated[index] = true; - } - return m_Intermediate[index].Identifier(); - } - - /// - /// Release allocated intermediate RTs - /// - /// The command buffer to use for deallocation - private void CleanupIntermediate(CommandBuffer cmd){ - for(int index = 0; index < 2; ++index){ - if(m_IntermediateAllocated[index]){ - cmd.ReleaseTemporaryRT(m_Intermediate[index].id); - m_IntermediateAllocated[index] = false; - } - } + m_Intermediate = new RTHandle[2]; } public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) { base.OnCameraSetup(cmd, ref renderingData); + // Copy camera target description for intermediate RTs. Disable multisampling and depth buffer for the intermediate targets. + m_IntermediateDesc = renderingData.cameraData.cameraTargetDescriptor; + m_IntermediateDesc.msaaSamples = 1; + m_IntermediateDesc.depthBufferBits = 0; + m_Intermediate[0] = RTHandles.Alloc(m_IntermediateDesc, FilterMode.Point, TextureWrapMode.Clamp, name: _IntermediateRTNames[0]); + m_Intermediate[1] = RTHandles.Alloc(m_IntermediateDesc, FilterMode.Point, TextureWrapMode.Clamp, name: _IntermediateRTNames[1]); + } + + public override void OnCameraCleanup(CommandBuffer cmd) + { + base.OnCameraCleanup(cmd); + for (int i = 0; i < m_Intermediate.Length; i++) + { + m_Intermediate[i].Release(); + } } public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) @@ -248,7 +243,8 @@ public override void Configure(CommandBuffer cmd, RenderTextureDescriptor camera /// /// Current rendering data /// True if any renderer will be executed for the given camera. False Otherwise. - public bool PrepareRenderers(ref RenderingData renderingData){ + public bool PrepareRenderers(ref RenderingData renderingData) + { // See if current camera is a scene view camera to skip renderers with "visibleInSceneView" = false. bool isSceneView = renderingData.cameraData.cameraType == CameraType.SceneView; @@ -257,12 +253,14 @@ public bool PrepareRenderers(ref RenderingData renderingData){ // Collect the active renderers m_ActivePostProcessRenderers.Clear(); - for(int index = 0; index < m_PostProcessRenderers.Count; index++){ + for (int index = 0; index < m_PostProcessRenderers.Count; index++) + { var ppRenderer = m_PostProcessRenderers[index]; // Skips current renderer if "visibleInSceneView" = false and the current camera is a scene view camera. - if(isSceneView && !ppRenderer.visibleInSceneView) continue; + if (isSceneView && !ppRenderer.visibleInSceneView) continue; // Setup the camera for the renderer and if it will render anything, add to active renderers and get its required inputs - if(ppRenderer.Setup(ref renderingData, injectionPoint)){ + if (ppRenderer.Setup(ref renderingData, injectionPoint)) + { m_ActivePostProcessRenderers.Add(index); passInput |= ppRenderer.input; } @@ -282,76 +280,77 @@ public bool PrepareRenderers(ref RenderingData renderingData){ /// Current rendering data public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { - RenderTargetIdentifier target = renderingData.cameraData.renderer.cameraColorTarget; - - // Copy camera target description for intermediate RTs. Disable multisampling and depth buffer for the intermediate targets. - m_IntermediateDesc = renderingData.cameraData.cameraTargetDescriptor; - m_IntermediateDesc.msaaSamples = 1; - m_IntermediateDesc.depthBufferBits = 0; - + RTHandle target = renderingData.cameraData.renderer.cameraColorTargetHandle; CommandBuffer cmd = CommandBufferPool.Get(m_PassName); - + context.ExecuteCommandBuffer(cmd); cmd.Clear(); int width = m_IntermediateDesc.width; int height = m_IntermediateDesc.height; - cmd.SetGlobalVector("_ScreenSize", new Vector4(width, height, 1.0f/width, 1.0f/height)); - + cmd.SetGlobalVector("_ScreenSize", new Vector4(width, height, 1.0f / width, 1.0f / height)); + // The variable will be true if the last renderer couldn't blit to destination. // This happens if there is only 1 renderer and the source is the same as the destination. bool requireBlitBack = false; // The current intermediate RT to use as a source. int intermediateIndex = 0; - for(int index = 0; index < m_ActivePostProcessRenderers.Count; ++index){ + for (int index = 0; index < m_ActivePostProcessRenderers.Count; ++index) + { var rendererIndex = m_ActivePostProcessRenderers[index]; var renderer = m_PostProcessRenderers[rendererIndex]; - - RenderTargetIdentifier source, destination; - if(index == 0){ + + RTHandle source, destination; + if (index == 0) + { // If this is the first renderers then the source will be the external source (not intermediate). source = target; - if(m_ActivePostProcessRenderers.Count == 1){ - // Since we can't bind the same RT as a texture and a render target at the same time, we will blit to an intermediate RT. - destination = GetIntermediate(cmd, 0); + if (m_ActivePostProcessRenderers.Count == 1) + { + // Since we can't bind the same RT as a texture and a render target at the same time, we will blit to an intermediate RT. + destination = m_Intermediate[0]; // Then we will blit back to the destination. requireBlitBack = true; - } else { + } + else + { // If there is more than one renderer, we will need to the intermediate RT anyway. - destination = GetIntermediate(cmd, intermediateIndex); + destination = m_Intermediate[intermediateIndex]; } - } else { + } + else + { // If this is not the first renderer, we will want to the read from the intermediate RT. - source = GetIntermediate(cmd, intermediateIndex); - if(index == m_ActivePostProcessRenderers.Count - 1){ + source = m_Intermediate[intermediateIndex]; + if (index == m_ActivePostProcessRenderers.Count - 1) + { // If this is the last renderer, blit to the destination directly. destination = target; - } else { + } + else + { // Otherwise, flip the intermediate RT index and set as destination. // This will act as a ping pong process between the 2 RT where color data keeps moving back and forth while being processed on each pass. intermediateIndex = 1 - intermediateIndex; - destination = GetIntermediate(cmd, intermediateIndex); + destination = m_Intermediate[intermediateIndex]; } } - using(new ProfilingScope(cmd, m_ProfilingSamplers[rendererIndex])) + using (new ProfilingScope(cmd, m_ProfilingSamplers[rendererIndex])) { // If the renderer was not already initialized, initialize it. - if(!renderer.Initialized) + if (!renderer.Initialized) renderer.InitializeInternal(); // Execute the renderer. renderer.Render(cmd, source, destination, ref renderingData, injectionPoint); } - + } // If blit back is needed, blit from the intermediate RT to the destination (see above for explanation) - if(requireBlitBack) - Blit(cmd, m_Intermediate[0].Identifier(), target); - - // Release allocated Intermediate RTs. - CleanupIntermediate(cmd); + if (requireBlitBack) + Blit(cmd, m_Intermediate[0], target); // Send command buffer for execution, then release it. context.ExecuteCommandBuffer(cmd);