大修
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace Echovoid.Runtime.Behavior.Rendering
|
||||
{
|
||||
public static class InternalShaderHelpers
|
||||
{
|
||||
public static Material GenerateTransientMaterial(string shaderName)
|
||||
{
|
||||
var shader = Shader.Find(shaderName);
|
||||
return CoreUtils.CreateEngineMaterial(shader);
|
||||
}
|
||||
|
||||
public static class ID
|
||||
{
|
||||
// RGB Split Glitch
|
||||
public static readonly int _RGBSplitGlitchParams = Shader.PropertyToID("_RGBSplitGlitchParams");
|
||||
public static readonly int _RGBSplitGlitchIntensity = Shader.PropertyToID("_RGBSplitGlitchIntensity");
|
||||
|
||||
// Radial Blur
|
||||
public static readonly int _RadialBlurParams = Shader.PropertyToID("_RadialBlurParams");
|
||||
public static readonly int _BlurRadius = Shader.PropertyToID("_BlurRadius");
|
||||
public static readonly int _RadialCenterX = Shader.PropertyToID("_RadialCenterX");
|
||||
public static readonly int _RadialCenterY = Shader.PropertyToID("_RadialCenterY");
|
||||
|
||||
// Speed Lines
|
||||
public static readonly int _SpeedLinesColour = Shader.PropertyToID("_Colour");
|
||||
public static readonly int _SpeedLinesTiling = Shader.PropertyToID("_SpeedLinesTiling");
|
||||
public static readonly int _SpeedLinesRadialScale = Shader.PropertyToID("_SpeedLinesRadialScale");
|
||||
public static readonly int _SpeedLinesPower = Shader.PropertyToID("_SpeedLinesPower");
|
||||
public static readonly int _SpeedLinesRemap = Shader.PropertyToID("_SpeedLinesRemap");
|
||||
public static readonly int _SpeedLinesAnimation = Shader.PropertyToID("_SpeedLinesAnimation");
|
||||
public static readonly int _MaskScale = Shader.PropertyToID("_MaskScale");
|
||||
public static readonly int _MaskHardness = Shader.PropertyToID("_MaskHardness");
|
||||
public static readonly int _MaskPower = Shader.PropertyToID("_MaskPower");
|
||||
|
||||
// --- Strobe Flash ---
|
||||
public static readonly int _StrobeColorHigh = Shader.PropertyToID("_StrobeColorHigh");
|
||||
public static readonly int _StrobeColorLow = Shader.PropertyToID("_StrobeColorLow");
|
||||
public static readonly int _StrobeParams = Shader.PropertyToID("_StrobeParams");
|
||||
public static readonly int _StrobeAdvParams = Shader.PropertyToID("_StrobeAdvParams");
|
||||
public static readonly int _LuminanceWeights = Shader.PropertyToID("_LuminanceWeights");
|
||||
|
||||
// --- Sharpen ---
|
||||
public static readonly int _SharpnessParams = Shader.PropertyToID("_SharpnessParams");
|
||||
|
||||
// --- Advanced Chromatic Aberration ---
|
||||
public static readonly int _ACA_Params1 = Shader.PropertyToID("_ACA_Params1");
|
||||
public static readonly int _ACA_Params2 = Shader.PropertyToID("_ACA_Params2");
|
||||
public static readonly int _ACA_Split = Shader.PropertyToID("_ACA_Split");
|
||||
public static readonly int _DispersionMap = Shader.PropertyToID("_DispersionMap");
|
||||
|
||||
// --- Advanced Vignette ---
|
||||
public static readonly int _ColorInner = Shader.PropertyToID("_ColorInner");
|
||||
public static readonly int _ColorOuter = Shader.PropertyToID("_ColorOuter");
|
||||
public static readonly int _VignetteParams1 = Shader.PropertyToID("_VignetteParams1");
|
||||
public static readonly int _VignetteCenter = Shader.PropertyToID("_VignetteCenter");
|
||||
|
||||
// --- Anime Bloom ---
|
||||
public static readonly int _BloomParams = Shader.PropertyToID("_BloomParams");
|
||||
public static readonly int _BloomTint = Shader.PropertyToID("_BloomTint");
|
||||
public static readonly int _AnimeBloom_BlurRadius = Shader.PropertyToID("_BlurRadius");
|
||||
public static readonly int _BloomTex = Shader.PropertyToID("_BloomTex");
|
||||
|
||||
// --- Anime ACES ---
|
||||
public static readonly int _TonemapParams = Shader.PropertyToID("_TonemapParams");
|
||||
public static readonly int _ACESCoeffs = Shader.PropertyToID("_ACESCoeffs");
|
||||
public static readonly int _ACES_E = Shader.PropertyToID("_ACES_E");
|
||||
public static readonly int _ColorFilter = Shader.PropertyToID("_ColorFilter");
|
||||
|
||||
// --- Pixelate ---
|
||||
public static readonly int _PixelateStrengthX = Shader.PropertyToID("_PixelateStrengthX");
|
||||
public static readonly int _PixelateStrengthY = Shader.PropertyToID("_PixelateStrengthY");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e46d8eed8c36ac84caf7ea20f2a0b134
|
||||
@@ -0,0 +1,94 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace SLSUtilities.Rendering.PostProcessing
|
||||
{
|
||||
public class ScriptablePostProcessorFeature : ScriptableRendererFeature
|
||||
{
|
||||
private List<ScriptablePostProcessorVolume> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 278f6128b25bcd644b3e798a37d9827b
|
||||
@@ -0,0 +1,159 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.RenderGraphModule;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace SLSUtilities.Rendering.PostProcessing
|
||||
{
|
||||
public class ScriptablePostProcessorPass : ScriptableRenderPass
|
||||
{
|
||||
private List<ScriptablePostProcessorVolume> postProcessors;
|
||||
private List<int> activePostProcessorIndex;
|
||||
|
||||
private string profilerTag;
|
||||
private List<ProfilingSampler> profilingSamplers;
|
||||
|
||||
// 核心:材质缓存池,确保每个 Shader 只对应一个材质实例
|
||||
private Dictionary<string, Material> m_MaterialCache = new Dictionary<string, Material>();
|
||||
|
||||
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;
|
||||
|
||||
// 清理函数,由 Feature.Dispose 调用
|
||||
public void Cleanup()
|
||||
{
|
||||
foreach (var mat in m_MaterialCache.Values)
|
||||
{
|
||||
if (mat != null) CoreUtils.Destroy(mat);
|
||||
}
|
||||
m_MaterialCache.Clear();
|
||||
}
|
||||
|
||||
private Material GetOrCreateMaterial(string shaderName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(shaderName)) return null;
|
||||
if (m_MaterialCache.TryGetValue(shaderName, out var mat) && mat != null) return mat;
|
||||
|
||||
// 调用你的静态工具类创建材质
|
||||
var shader = Shader.Find(shaderName);
|
||||
if (shader == null) return null;
|
||||
|
||||
mat = CoreUtils.CreateEngineMaterial(shader);
|
||||
m_MaterialCache[shaderName] = mat;
|
||||
return mat;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public bool Setup(ref RenderingData renderingData)
|
||||
{
|
||||
this.m_RenderingData = renderingData;
|
||||
|
||||
activePostProcessorIndex.Clear();
|
||||
for (int i = 0; i < postProcessors.Count; i++)
|
||||
{
|
||||
var volume = postProcessors[i];
|
||||
// 关键修复:从 Pass 的缓存池获取材质并注入给 Volume
|
||||
var mat = GetOrCreateMaterial(volume.GetShaderName());
|
||||
volume.SetMaterial(mat);
|
||||
|
||||
volume.Setup();
|
||||
if (volume.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;
|
||||
|
||||
var cameraDesc = cameraData.cameraTargetDescriptor;
|
||||
var rgDesc = new TextureDesc(cameraDesc.width, cameraDesc.height);
|
||||
rgDesc.colorFormat = cameraDesc.graphicsFormat;
|
||||
rgDesc.depthBufferBits = DepthBits.None;
|
||||
rgDesc.msaaSamples = MSAASamples.None;
|
||||
|
||||
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;
|
||||
passData.RenderingData = m_RenderingData;
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c198108d8fe5ea4fad878bf9623c573
|
||||
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using Echovoid.Runtime.Behavior.Rendering;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace SLSUtilities.Rendering.PostProcessing
|
||||
{
|
||||
public enum CustomPostProcessInjectionPoint
|
||||
{
|
||||
AfterTransparent,
|
||||
BeforePostProcess,
|
||||
AfterPostProcess
|
||||
}
|
||||
|
||||
public abstract class ScriptablePostProcessorVolume : VolumeComponent, IPostProcessComponent
|
||||
{
|
||||
public virtual CustomPostProcessInjectionPoint InjectionPoint =>
|
||||
CustomPostProcessInjectionPoint.AfterPostProcess;
|
||||
|
||||
public virtual int OrderInInjectionPoint => 0;
|
||||
|
||||
protected Material material;
|
||||
|
||||
// 注入材质的句柄,由 Pass 调用
|
||||
public void SetMaterial(Material mat) => material = mat;
|
||||
|
||||
public abstract string GetShaderName();
|
||||
|
||||
public virtual void Setup()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public abstract void Render(CommandBuffer cmd, ref RenderingData renderingData, RTHandle source, RTHandle destination);
|
||||
|
||||
public abstract bool IsActive();
|
||||
|
||||
public bool IsTileCompatible() => false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: da1ac4541bff9ba4980b8e18d53bb76e
|
||||
Reference in New Issue
Block a user