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 } }