using System.Collections.Generic; using System.Linq; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; namespace SLSFramework.Rendering.PostProcessing { public class ScriptablePostProcessorFeature : ScriptableRendererFeature { private List postProcessorVolumes; private ScriptablePostProcessorPass afterTransparentPass; private ScriptablePostProcessorPass beforePostProcessPass; private ScriptablePostProcessorPass afterPostProcessPass; public override void Create() { var stack = VolumeManager.instance.stack; postProcessorVolumes = VolumeManager.instance.baseComponentTypeArray .Where(t => t.IsSubclassOf(typeof(ScriptablePostProcessorVolume))) .Select(t => stack.GetComponent(t) as ScriptablePostProcessorVolume) .ToList(); var afterTransparentPostProcessors = postProcessorVolumes .Where(c => c.InjectionPoint == CustomPostProcessInjectionPoint.AfterTransparent) .OrderBy(c => c.OrderInInjectionPoint) .ToList(); afterTransparentPass = new ScriptablePostProcessorPass("Custom PostProcessor - after Transparent", afterTransparentPostProcessors) { renderPassEvent = RenderPassEvent.AfterRenderingTransparents }; var beforePostProcessPostProcessors = postProcessorVolumes .Where(c => c.InjectionPoint == CustomPostProcessInjectionPoint.BeforePostProcess) .OrderBy(c => c.OrderInInjectionPoint) .ToList(); beforePostProcessPass = new ScriptablePostProcessorPass("Custom PostProcessor - before PostProcessing", beforePostProcessPostProcessors) { renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing }; var afterPostProcessPostProcessors = postProcessorVolumes .Where(c => c.InjectionPoint == CustomPostProcessInjectionPoint.AfterPostProcess) .OrderBy(c => c.OrderInInjectionPoint) .ToList(); afterPostProcessPass = new ScriptablePostProcessorPass("Custom PostProcessor - after PostProcessing", afterPostProcessPostProcessors) { renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing }; } public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) { if (renderingData.cameraData.postProcessEnabled) { if (afterTransparentPass.Setup(ref renderingData)) { afterTransparentPass.ConfigureInput(ScriptableRenderPassInput.Color); renderer.EnqueuePass(afterTransparentPass); } if (beforePostProcessPass.Setup(ref renderingData)) { beforePostProcessPass.ConfigureInput(ScriptableRenderPassInput.Color); renderer.EnqueuePass(beforePostProcessPass); } if (afterPostProcessPass.Setup(ref renderingData)) { afterPostProcessPass.ConfigureInput(ScriptableRenderPassInput.Color); renderer.EnqueuePass(afterPostProcessPass); } } } protected override void Dispose(bool disposing) { if (disposing) { // 关键点:调用 Pass 的清理函数,销毁缓存池中的材质 afterTransparentPass?.Cleanup(); beforePostProcessPass?.Cleanup(); afterPostProcessPass?.Cleanup(); afterTransparentPass = null; beforePostProcessPass = null; afterPostProcessPass = null; postProcessorVolumes = null; } base.Dispose(disposing); } } }