Files
Cielonos/Assets/Shaders/ScriptablePostProcessor/Base/ScriptablePostProcessorPass.cs
2025-12-22 18:36:29 -05:00

146 lines
6.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<ScriptablePostProcessorVolume> postProcessors;
private List<int> activePostProcessorIndex;
private string profilerTag;
private List<ProfilingSampler> profilingSamplers;
public ScriptablePostProcessorPass(string profilerTag, List<ScriptablePostProcessorVolume> postProcessors)
{
this.profilerTag = profilerTag;
this.postProcessors = postProcessors;
activePostProcessorIndex = new List<int>(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<int> ActiveIndices;
public List<ScriptablePostProcessorVolume> Volumes;
public List<ProfilingSampler> 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<UniversalResourceData>();
var cameraData = frameData.Get<UniversalCameraData>();
// 如果没有激活的后处理,直接跳过
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<PassData>(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);
}
});
}
}
}
}