161 lines
6.1 KiB
C#
161 lines
6.1 KiB
C#
using System;
|
||
using UnityEngine;
|
||
using UnityEngine.Rendering;
|
||
using UnityEngine.Rendering.Universal;
|
||
using UnityEngine.SceneManagement;
|
||
|
||
public class FullBlurRPF : ScriptableRendererFeature
|
||
{
|
||
|
||
[Serializable] //序列化 会在ForwardRenderer下创建Blur时看到m_Data就是它
|
||
public class BlurData
|
||
{
|
||
// 模糊材质
|
||
public Material blurMat;
|
||
// 叠加材质
|
||
public Material overlayMat;
|
||
|
||
public RenderPassEvent renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
|
||
|
||
[Tooltip("渲染次数,次数越多越模糊,但是性能消耗也越大")]
|
||
[Range(0, 4)]
|
||
public int iterations = 3;
|
||
|
||
[Tooltip("采样间距X,值越大越模糊")]
|
||
[Range(0, 2f)]
|
||
public float blurSizeX = 0.5f;
|
||
[Tooltip("采样间距Y,值越大越模糊")]
|
||
[Range(0, 2f)]
|
||
public float blurSizeY = 0.5f;
|
||
|
||
[Tooltip("降采样,值越小越模糊,性能越好")]
|
||
[Range(0.1f, 1f)]
|
||
public float downScale = 0.5f;
|
||
|
||
[Tooltip("模糊混合进度")]
|
||
[Range(0f, 1f)]
|
||
public float blurBlendProgress = 0.5f;
|
||
|
||
[Tooltip("叠加颜色")]
|
||
public Color overlayColor;
|
||
}
|
||
|
||
public class BlurRenderPass : ScriptableRenderPass
|
||
{
|
||
private BlurData _data;
|
||
private RenderTexture _rt0;
|
||
private RenderTexture _rt1;
|
||
private RenderTargetIdentifier _buffer0Id;
|
||
private RenderTargetIdentifier _buffer1Id;
|
||
|
||
private int _blurSizeX = Shader.PropertyToID("_BlurSizeX");
|
||
private int _blurSizeY = Shader.PropertyToID("_BlurSizeY");
|
||
private int _overlayColor = Shader.PropertyToID("_OverlayColor");
|
||
private int _blurTex = Shader.PropertyToID("_BlurTex");
|
||
private int _blurBlendProgress = Shader.PropertyToID("_BlurBlendProgress");
|
||
|
||
public BlurRenderPass(BlurData data)
|
||
{
|
||
_data = data;
|
||
}
|
||
public void Setup()
|
||
{
|
||
_buffer0Id = Shader.PropertyToID("_BlurBuffer0");
|
||
_buffer1Id = Shader.PropertyToID("_BlurBuffer1");
|
||
}
|
||
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
|
||
{
|
||
var width = Mathf.FloorToInt(cameraTextureDescriptor.width * _data.downScale);
|
||
var height = Mathf.FloorToInt(cameraTextureDescriptor.height * _data.downScale);
|
||
|
||
var rt0 = RenderTexture.GetTemporary(width, height, 0, RenderTextureFormat.ARGB32);
|
||
rt0.filterMode = FilterMode.Bilinear;
|
||
rt0.wrapMode = TextureWrapMode.Clamp;
|
||
_buffer0Id = rt0;
|
||
_rt0 = rt0;
|
||
|
||
var rt1 = RenderTexture.GetTemporary(width, height, 0, RenderTextureFormat.ARGB32);
|
||
rt1.filterMode = FilterMode.Bilinear;
|
||
rt1.wrapMode = TextureWrapMode.Clamp;
|
||
_buffer1Id = rt1;
|
||
_rt1 = rt1;
|
||
|
||
// cmd.GetTemporaryRT(_buffer0Id, width, height, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32);
|
||
// cmd.GetTemporaryRT(_buffer1Id, width, height, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32);
|
||
}
|
||
|
||
public override void FrameCleanup(CommandBuffer cmd)
|
||
{
|
||
RenderTexture.ReleaseTemporary(_rt0);
|
||
RenderTexture.ReleaseTemporary(_rt1);
|
||
// cmd.ReleaseTemporaryRT(_buffer0Id);
|
||
// cmd.ReleaseTemporaryRT(_buffer1Id);
|
||
}
|
||
|
||
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
|
||
{
|
||
|
||
//TODO: 临时处理
|
||
#if UNITY_EDITOR
|
||
var currentSceneName = SceneManager.GetActiveScene().name;
|
||
if (currentSceneName.StartsWith("story")) return;
|
||
#endif
|
||
|
||
if (renderingData.cameraData.camera != Camera.main) return; //只对主摄像机进行处理
|
||
|
||
var mat = _data.blurMat;
|
||
if (mat == null) return;
|
||
|
||
//renderingData.cameraData.camera 可获取摄像机判定哪个摄像机才进行处理渲染(每个摄像机都会进一遍pass 如果摄像机有多个且都有这个Blur(ScriptableRendererFeature资源)
|
||
CommandBuffer cmd = CommandBufferPool.Get("FullBlur"); //从池获取一个cmd 命名为MyBlurCmd 能在FrameDebugger看到
|
||
var cameraRt = renderingData.cameraData.renderer.cameraColorTargetHandle.nameID; //获取摄像机主纹理
|
||
|
||
// 模糊
|
||
cmd.Blit(cameraRt, _buffer0Id);//将摄像机图渲染至buffer0
|
||
//开始iterations次渲染,每次都会进行2次Pass操作:横向、纵向(谁先谁后都无所谓
|
||
for (int i = 0; i < _data.iterations; i++)
|
||
{
|
||
//指定采样间距,逐级递增的形式
|
||
mat.SetFloat(_blurSizeX, 1.0f + i * _data.blurSizeX);
|
||
mat.SetFloat(_blurSizeY, 1.0f + i * _data.blurSizeY);
|
||
cmd.Blit(_buffer0Id, _buffer1Id, mat);
|
||
(_buffer0Id, _buffer1Id) = (_buffer1Id, _buffer0Id);
|
||
}
|
||
|
||
// 叠色
|
||
mat = _data.overlayMat;
|
||
if (mat == null) return;
|
||
|
||
mat.SetColor(_overlayColor, _data.overlayColor);
|
||
// var blurTex =
|
||
mat.SetTexture(_blurTex, _rt0);
|
||
mat.SetFloat(_blurBlendProgress, _data.blurBlendProgress);
|
||
cmd.Blit(cameraRt, cameraRt, mat);
|
||
|
||
// cmd.Blit(_buffer1Id, cameraRt); //将最终结果渲染到摄像机上
|
||
//执行cmd
|
||
context.ExecuteCommandBuffer(cmd);
|
||
//清空回收cmd
|
||
cmd.Clear();
|
||
CommandBufferPool.Release(cmd);
|
||
}
|
||
}
|
||
|
||
public BlurData data = new BlurData();
|
||
|
||
private BlurRenderPass _blurPass;
|
||
|
||
public override void Create()
|
||
{
|
||
_blurPass = new BlurRenderPass(data); //创建一个pass
|
||
_blurPass.renderPassEvent = data.renderPassEvent;
|
||
}
|
||
|
||
public override void AddRenderPasses(ScriptableRenderer renderer,
|
||
ref RenderingData renderingData)
|
||
{
|
||
_blurPass.Setup();
|
||
renderer.EnqueuePass(_blurPass); //入队渲染pass
|
||
}
|
||
}
|