|
using UnityEngine; |
|
using UnityEngine.Rendering; |
|
using UnityEngine.Rendering.Universal; |
|
|
|
public class UIBlurFeature : ScriptableRendererFeature |
|
{ |
|
public enum BlurType |
|
{ |
|
Gaussian, |
|
Box, |
|
} |
|
|
|
const string TextureName = "_UIBlurTexture"; |
|
static int DownscaleKernelID = -1; |
|
static int GaussianBlurKernelID = -1; |
|
static int BoxBlurKernelID = -1; |
|
|
|
[System.Serializable] |
|
public class Settings |
|
{ |
|
[Range(1, 16)] public int DownscaleAmount = 2; |
|
|
|
public BlurType BlurType; |
|
[Range(0, 16)] public int BlurIterations = 4; |
|
|
|
public ComputeShader EffectCompute; |
|
} |
|
|
|
class BlurSceneColorPass : ScriptableRenderPass |
|
{ |
|
RenderTargetHandle tempColorTarget; |
|
Settings settings; |
|
|
|
RenderTargetIdentifier cameraTarget; |
|
|
|
Vector2Int scale; |
|
Vector2Int groupSizes; |
|
|
|
public BlurSceneColorPass(Settings s) |
|
{ |
|
settings = s; |
|
renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing; |
|
tempColorTarget.Init(TextureName); |
|
} |
|
|
|
public void Setup(RenderTargetIdentifier cameraTarget) |
|
{ |
|
this.cameraTarget = cameraTarget; |
|
} |
|
|
|
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) |
|
{ |
|
var downscaleDesc = cameraTextureDescriptor; |
|
downscaleDesc.width = (int) ((float) downscaleDesc.width / (float) settings.DownscaleAmount); |
|
downscaleDesc.height = (int) ((float) downscaleDesc.height / (float) settings.DownscaleAmount); |
|
downscaleDesc.enableRandomWrite = true; |
|
|
|
scale = new Vector2Int(downscaleDesc.width, downscaleDesc.height); |
|
groupSizes = new Vector2Int(Mathf.CeilToInt(scale.x / 32f), Mathf.CeilToInt(scale.y / 32f)); |
|
|
|
cmd.GetTemporaryRT(tempColorTarget.id, downscaleDesc); |
|
|
|
cmd.SetGlobalTexture(TextureName, tempColorTarget.Identifier()); |
|
} |
|
|
|
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) |
|
{ |
|
CommandBuffer cmd = CommandBufferPool.Get(); |
|
context.ExecuteCommandBuffer(cmd); |
|
cmd.Clear(); |
|
|
|
// Shared parameters between compute kernels |
|
cmd.SetComputeVectorParam(settings.EffectCompute, "_Size", new Vector2(scale.x, scale.y)); |
|
cmd.SetComputeFloatParam(settings.EffectCompute, "_Amount", settings.DownscaleAmount); |
|
|
|
// Blit/Downscale scene color texture |
|
{ |
|
cmd.SetComputeTextureParam(settings.EffectCompute, DownscaleKernelID, "_Source", cameraTarget); |
|
cmd.SetComputeTextureParam(settings.EffectCompute, DownscaleKernelID, "_Dest", |
|
tempColorTarget.Identifier()); |
|
cmd.DispatchCompute(settings.EffectCompute, DownscaleKernelID, groupSizes.x, groupSizes.y, 1); |
|
} |
|
|
|
// Apply iterative blur |
|
{ |
|
int blurKernelID = settings.BlurType switch |
|
{ |
|
BlurType.Box => BoxBlurKernelID, |
|
BlurType.Gaussian => GaussianBlurKernelID, |
|
}; |
|
|
|
cmd.SetComputeTextureParam(settings.EffectCompute, blurKernelID, "_Dest", tempColorTarget.Identifier()); |
|
cmd.SetComputeTextureParam(settings.EffectCompute, blurKernelID + 1, "_Dest", tempColorTarget.Identifier()); |
|
|
|
for (int i = 0; i < settings.BlurIterations; i++) |
|
{ |
|
cmd.DispatchCompute(settings.EffectCompute, blurKernelID, groupSizes.x, groupSizes.y, 1); |
|
if (settings.BlurType == BlurType.Gaussian) |
|
{ |
|
cmd.DispatchCompute(settings.EffectCompute, blurKernelID + 1, groupSizes.x, groupSizes.y, 1); |
|
} |
|
} |
|
} |
|
|
|
context.ExecuteCommandBuffer(cmd); |
|
CommandBufferPool.Release(cmd); |
|
} |
|
|
|
public override void FrameCleanup(CommandBuffer cmd) |
|
{ |
|
cmd.ReleaseTemporaryRT(tempColorTarget.id); |
|
} |
|
} |
|
|
|
BlurSceneColorPass blurSceneColorPass; |
|
[SerializeField] Settings settings; |
|
|
|
public override void Create() |
|
{ |
|
blurSceneColorPass = new BlurSceneColorPass(settings); |
|
|
|
FindKernels(); |
|
} |
|
|
|
void FindKernels() |
|
{ |
|
if (settings.EffectCompute != null) |
|
{ |
|
DownscaleKernelID = settings.EffectCompute.FindKernel("Downscale"); |
|
GaussianBlurKernelID = settings.EffectCompute.FindKernel("GaussianBlurVertical"); |
|
BoxBlurKernelID = settings.EffectCompute.FindKernel("BoxBlur"); |
|
} |
|
} |
|
|
|
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) |
|
{ |
|
if (settings.EffectCompute == null) |
|
{ |
|
return; |
|
} |
|
|
|
if (DownscaleKernelID == -1 || GaussianBlurKernelID == -1) |
|
{ |
|
FindKernels(); |
|
} |
|
|
|
blurSceneColorPass.Setup(renderer.cameraColorTarget); |
|
renderer.EnqueuePass(blurSceneColorPass); |
|
} |
|
} |