using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.RenderGraphModule; using UnityEngine.Rendering.Universal; namespace SLSFramework.Rendering.PostProcessing { public class ScriptablePostProcessorPass : ScriptableRenderPass { private List postProcessors; private List activePostProcessorIndex; private string profilerTag; private List profilingSamplers; public ScriptablePostProcessorPass(string profilerTag, List postProcessors) { this.profilerTag = profilerTag; this.postProcessors = postProcessors; activePostProcessorIndex = new List(postProcessors.Count); profilingSamplers = postProcessors.Select(c => new ProfilingSampler(c.ToString())).ToList(); } private RenderingData m_RenderingData; private class PassData { public TextureHandle SourceTexture; public TextureHandle TargetTexture; public TextureHandle TempTextureA; public TextureHandle TempTextureB; public List ActiveIndices; public List Volumes; public List Profilers; public RenderingData RenderingData; // 数据结构保持不变 } // 修改 Setup:接收 RenderingData 并保存 // 注意:这里的 Setup 需要在 AddRenderPasses 中调用 public bool Setup(ref RenderingData renderingData) { this.m_RenderingData = renderingData; // 捕获数据 activePostProcessorIndex.Clear(); for (int i = 0; i < postProcessors.Count; i++) { postProcessors[i].Setup(); if (postProcessors[i].IsActive()) { activePostProcessorIndex.Add(i); } } return activePostProcessorIndex.Count != 0; } public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) { var resourceData = frameData.Get(); var cameraData = frameData.Get(); // 如果没有激活的后处理,直接跳过 if (activePostProcessorIndex.Count == 0) return; // 1. 获取相机的基础描述符 (这是旧的 RenderTextureDescriptor) var cameraDesc = cameraData.cameraTargetDescriptor; // 2. 【核心修正】创建一个新的 RenderGraph 专用描述符 (TextureDesc) // 只有 TextureDesc 才能设置 name,也不能直接把 cameraDesc 强转过去,必须手动赋值 var rgDesc = new TextureDesc(cameraDesc.width, cameraDesc.height); rgDesc.colorFormat = cameraDesc.graphicsFormat; rgDesc.depthBufferBits = DepthBits.None; // 后处理不需要深度 rgDesc.msaaSamples = MSAASamples.None; // 后处理通常不需要 MSAA using (var builder = renderGraph.AddUnsafePass(profilerTag, out var passData)) { // 填充数据 passData.SourceTexture = resourceData.activeColorTexture; passData.TargetTexture = resourceData.activeColorTexture; passData.ActiveIndices = activePostProcessorIndex; passData.Volumes = postProcessors; passData.Profilers = profilingSamplers; // 使用我们在 Setup 中缓存的旧版数据 (解决 UniversalRenderingData 找不到的问题) passData.RenderingData = m_RenderingData; // 3. 【核心修正】设置名字并创建纹理 // 这里使用的是 rgDesc (TextureDesc 类型),它有 name 属性 rgDesc.name = "_TemporaryRenderTextureA"; passData.TempTextureA = renderGraph.CreateTexture(rgDesc); rgDesc.name = "_TemporaryRenderTextureB"; passData.TempTextureB = renderGraph.CreateTexture(rgDesc); // 声明依赖关系 (保持不变) builder.UseTexture(passData.SourceTexture, AccessFlags.Read); builder.UseTexture(passData.TempTextureA, AccessFlags.ReadWrite); builder.UseTexture(passData.TempTextureB, AccessFlags.ReadWrite); builder.UseTexture(passData.TargetTexture, AccessFlags.ReadWrite); // 设置执行逻辑 (保持不变) builder.SetRenderFunc((PassData data, UnsafeGraphContext context) => { var cmd = CommandBufferHelpers.GetNativeCommandBuffer(context.cmd); var source = data.SourceTexture; var target = data.TargetTexture; var tempA = data.TempTextureA; var tempB = data.TempTextureB; if (data.ActiveIndices.Count == 1) { int index = data.ActiveIndices[0]; using (new ProfilingScope(cmd, data.Profilers[index])) { data.Volumes[index].Render(cmd, ref data.RenderingData, source, tempA); } Blitter.BlitCameraTexture(cmd, tempA, target); } else { Blitter.BlitCameraTexture(cmd, source, tempA); var currSource = tempA; var currDest = tempB; foreach (int index in data.ActiveIndices) { var postProcessor = data.Volumes[index]; using (new ProfilingScope(cmd, data.Profilers[index])) { postProcessor.Render(cmd, ref data.RenderingData, currSource, currDest); } CoreUtils.Swap(ref currSource, ref currDest); } Blitter.BlitCameraTexture(cmd, currSource, target); } }); } } } }