177 lines
6.3 KiB
C#
177 lines
6.3 KiB
C#
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
using UnityEngine.Rendering.Universal;
|
|
using UnityEngine.Rendering.RenderGraphModule;
|
|
|
|
public class BlurRendererFeature : ScriptableRendererFeature
|
|
{
|
|
[System.Serializable]
|
|
public class Settings
|
|
{
|
|
[Range(0f, 0.2f)] public float blurRadius = 0.02f;
|
|
[Range(0f, 1f)] public float glowThreshold = 0.6f;
|
|
[Range(0f, 2f)] public float glowIntensity = 0f;
|
|
public Material blurHorizontal;
|
|
public Material blurVertical;
|
|
}
|
|
|
|
public Settings settings = new Settings();
|
|
|
|
BlurPass horizontalPass;
|
|
BlurPass verticalPass;
|
|
CopyToRTPass copyPass;
|
|
|
|
RenderTexture blurRT;
|
|
RTHandle blurRTHandle;
|
|
|
|
static readonly int BlurTexID = Shader.PropertyToID("_BlurredTexture");
|
|
static readonly int BlurRadiusID = Shader.PropertyToID("_BlurRadius");
|
|
static readonly int GlowThresholdID = Shader.PropertyToID("_GlowThreshold");
|
|
static readonly int GlowIntensityID = Shader.PropertyToID("_GlowIntensity");
|
|
static readonly int BlurSourceID = Shader.PropertyToID("_BlurSource");
|
|
|
|
public override void Create()
|
|
{
|
|
horizontalPass = new BlurPass("Blur Horizontal", RenderPassEvent.BeforeRenderingPostProcessing);
|
|
verticalPass = new BlurPass("Blur Vertical", RenderPassEvent.BeforeRenderingPostProcessing);
|
|
copyPass = new CopyToRTPass(RenderPassEvent.BeforeRenderingPostProcessing);
|
|
}
|
|
|
|
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
|
|
{
|
|
if (settings.blurHorizontal == null || settings.blurVertical == null) return;
|
|
|
|
var desc = renderingData.cameraData.cameraTargetDescriptor;
|
|
|
|
if (blurRT != null && (blurRT.width != desc.width / 2 || blurRT.height != desc.height / 2))
|
|
{
|
|
blurRT.Release();
|
|
blurRTHandle?.Release();
|
|
blurRT = null;
|
|
blurRTHandle = null;
|
|
}
|
|
|
|
if (blurRT == null)
|
|
{
|
|
blurRT = new RenderTexture(desc.width / 4, desc.height / 4, 0, RenderTextureFormat.DefaultHDR);
|
|
blurRT.Create();
|
|
blurRTHandle = RTHandles.Alloc(blurRT);
|
|
Shader.SetGlobalTexture(BlurTexID, blurRT);
|
|
}
|
|
|
|
Shader.SetGlobalFloat(BlurRadiusID, settings.blurRadius);
|
|
Shader.SetGlobalFloat(GlowThresholdID, settings.glowThreshold);
|
|
Shader.SetGlobalFloat(GlowIntensityID, settings.glowIntensity);
|
|
|
|
horizontalPass.Setup(settings.blurHorizontal);
|
|
renderer.EnqueuePass(horizontalPass);
|
|
|
|
verticalPass.Setup(settings.blurVertical);
|
|
renderer.EnqueuePass(verticalPass);
|
|
|
|
copyPass.Setup(blurRTHandle);
|
|
renderer.EnqueuePass(copyPass);
|
|
}
|
|
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
if (blurRT != null)
|
|
{
|
|
blurRT.Release();
|
|
blurRT = null;
|
|
}
|
|
blurRTHandle?.Release();
|
|
blurRTHandle = null;
|
|
}
|
|
|
|
class BlurPass : ScriptableRenderPass
|
|
{
|
|
string passName;
|
|
Material material;
|
|
|
|
static readonly int BlurSourceID = Shader.PropertyToID("_BlurSource");
|
|
|
|
public BlurPass(string name, RenderPassEvent evt)
|
|
{
|
|
passName = name;
|
|
renderPassEvent = evt;
|
|
}
|
|
|
|
public void Setup(Material mat) => material = mat;
|
|
|
|
class PassData
|
|
{
|
|
public TextureHandle source;
|
|
public Material material;
|
|
}
|
|
|
|
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
|
|
{
|
|
var resourceData = frameData.Get<UniversalResourceData>();
|
|
|
|
var srcDesc = renderGraph.GetTextureDesc(resourceData.activeColorTexture);
|
|
srcDesc.name = passName + " Temp";
|
|
srcDesc.clearBuffer = false;
|
|
var tempHandle = renderGraph.CreateTexture(srcDesc);
|
|
|
|
using (var builder = renderGraph.AddRasterRenderPass<PassData>(passName + " Blit", out var passData))
|
|
{
|
|
passData.source = resourceData.activeColorTexture;
|
|
passData.material = material;
|
|
|
|
builder.UseTexture(passData.source, AccessFlags.Read);
|
|
builder.SetRenderAttachment(tempHandle, 0, AccessFlags.Write);
|
|
builder.AllowGlobalStateModification(true);
|
|
|
|
builder.SetRenderFunc((PassData data, RasterGraphContext ctx) =>
|
|
{
|
|
ctx.cmd.SetGlobalTexture(BlurSourceID, data.source);
|
|
Blitter.BlitTexture(ctx.cmd, data.source, new Vector4(1, 1, 0, 0), data.material, 0);
|
|
});
|
|
}
|
|
|
|
using (var builder = renderGraph.AddRasterRenderPass<PassData>(passName + " Restore", out var passData))
|
|
{
|
|
passData.source = tempHandle;
|
|
|
|
builder.UseTexture(passData.source, AccessFlags.Read);
|
|
builder.SetRenderAttachment(resourceData.activeColorTexture, 0, AccessFlags.Write);
|
|
|
|
builder.SetRenderFunc((PassData data, RasterGraphContext ctx) =>
|
|
{
|
|
Blitter.BlitTexture(ctx.cmd, data.source, new Vector4(1, 1, 0, 0), 0, false);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
class CopyToRTPass : ScriptableRenderPass
|
|
{
|
|
RTHandle targetHandle;
|
|
|
|
public CopyToRTPass(RenderPassEvent evt) => renderPassEvent = evt;
|
|
|
|
public void Setup(RTHandle handle) => targetHandle = handle;
|
|
|
|
class CopyPassData { public TextureHandle source; }
|
|
|
|
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
|
|
{
|
|
var resourceData = frameData.Get<UniversalResourceData>();
|
|
var destHandle = renderGraph.ImportTexture(targetHandle);
|
|
|
|
using (var builder = renderGraph.AddRasterRenderPass<CopyPassData>("Copy Blur To RT", out var passData))
|
|
{
|
|
passData.source = resourceData.activeColorTexture;
|
|
|
|
builder.UseTexture(passData.source, AccessFlags.Read);
|
|
builder.SetRenderAttachment(destHandle, 0, AccessFlags.Write);
|
|
|
|
builder.SetRenderFunc((CopyPassData data, RasterGraphContext ctx) =>
|
|
{
|
|
Blitter.BlitTexture(ctx.cmd, data.source, new Vector4(1, 1, 0, 0), 0, false);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
} |