146 lines
6.3 KiB
C#
146 lines
6.3 KiB
C#
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);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
}
|
||
} |