• 【Unity】URP屏幕后处理UI模糊效果实现


     这里Canvas(1)设置为Overlay能渲染出指定UI高清,其他UI模糊,然而这做法非常不好,如果此时再打开UI 以及 关闭模糊效果 要将这些置顶UI 恢复到原本Canvas里,也就是要管理2套Canvas

    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using UnityEngine.Rendering;
    6. using UnityEngine.Rendering.Universal;
    7. public class Blur : ScriptableRendererFeature
    8. {
    9. [Serializable] //序列化 会在ForwardRenderer下创建Blur时看到m_Data就是它
    10. public class BlurData
    11. {
    12. //blur材质
    13. public Material material;
    14. public RenderPassEvent renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
    15. //渲染次数,次数越大图像会越模糊
    16. [Range(0, 4)]
    17. public int iterations = 3;
    18. //模糊采样间距,越大越模糊
    19. [Range(0.2f, 3.0f)]
    20. public float blurSpread = 0.6f;
    21. //缩小比例(2代表缩小1/2) 越大越模糊,性能越好,但是会逐渐像素化!
    22. [Range(1, 8)]
    23. public int downSample = 2;
    24. }
    25. public class BlurRenderPass : ScriptableRenderPass
    26. {
    27. private BlurData m_Data; //ForwardRenderer下Blur(ScriptableRendererFeature)资源的序列化参数数据
    28. private RenderTargetIdentifier m_Source;//屏幕图
    29. private RenderTargetHandle m_Buffer0;//缓冲区1
    30. private RenderTargetHandle m_Buffer1;//缓冲区2
    31. private int m_BlurSize = Shader.PropertyToID("_BlurSize");
    32. public BlurRenderPass(BlurData data)
    33. {
    34. this.m_Data = data;
    35. }
    36. public void Setup(RenderTargetIdentifier cameraColorTarget)
    37. {
    38. m_Buffer0.Init("_Buffer0");
    39. m_Buffer1.Init("_Buffer1");
    40. this.m_Source = cameraColorTarget;//该pass所在管线 ForwardRenderer 所处的摄像机主纹理
    41. }
    42. public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
    43. {
    44. var width = cameraTextureDescriptor.width / m_Data.downSample;
    45. var height = cameraTextureDescriptor.height / m_Data.downSample;
    46. cmd.GetTemporaryRT(m_Buffer0.id, width, height, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32);
    47. cmd.GetTemporaryRT(m_Buffer1.id, width, height, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32);
    48. }
    49. public override void FrameCleanup(CommandBuffer cmd)
    50. {
    51. cmd.ReleaseTemporaryRT(m_Buffer0.id);
    52. cmd.ReleaseTemporaryRT(m_Buffer1.id);
    53. }
    54. public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    55. {
    56. var mat = m_Data.material;
    57. if (mat == null) return;
    58. //renderingData.cameraData.camera 可获取摄像机判定哪个摄像机才进行处理渲染(每个摄像机都会进一遍pass 如果摄像机有多个且都有这个Blur(ScriptableRendererFeature资源)
    59. CommandBuffer cmd = CommandBufferPool.Get("MyBlurCmd"); //从池获取一个cmd 命名为MyBlurCmd 能在FrameDebugger看到
    60. cmd.Blit(m_Source, m_Buffer0.Identifier());//将摄像机图渲染至buffer0
    61. //开始iterations次渲染,每次都会进行2次Pass操作:横向、纵向(谁先谁后都无所谓
    62. for (int i = 0; i < m_Data.iterations; i++)
    63. {
    64. mat.SetFloat(m_BlurSize, 1.0f + i * m_Data.blurSpread);//指定采样间距,逐级递增的形式
    65. cmd.Blit(m_Buffer0.Identifier(), m_Buffer1.Identifier(), mat, 0);
    66. var tmp = m_Buffer0;
    67. m_Buffer0 = m_Buffer1; //注意最终都会将渲染结果输出到m_Buffer0
    68. m_Buffer1 = tmp;
    69. }
    70. cmd.Blit(m_Buffer0.Identifier(), m_Source); //将最终结果渲染到摄像机上
    71. //执行cmd
    72. context.ExecuteCommandBuffer(cmd);
    73. //清空回收cmd
    74. cmd.Clear();
    75. CommandBufferPool.Release(cmd);
    76. }
    77. }
    78. public BlurData data = new BlurData();
    79. private BlurRenderPass m_Pass;
    80. public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    81. {
    82. var src = renderer.cameraColorTarget;
    83. m_Pass.Setup(src); //设置摄像机输出的颜色纹理
    84. renderer.EnqueuePass(m_Pass); //入队渲染pass
    85. }
    86. public override void Create()
    87. {
    88. m_Pass = new BlurRenderPass(data); //创建一个pass
    89. m_Pass.renderPassEvent = data.renderPassEvent; //设置pass的渲染时机在某个节点后(导致问题,无法类似grab一样在某一个UI渲染时进行渲染 而必须等到所有UI渲染完成才进行渲染。。
    90. //无法做到置顶UI高清,底下UI模糊的效果.
    91. //所以下一步是思考如何实现这个吧..
    92. }
    93. }

    Shader代码实现模糊 

    1. //注意 注释掉的CGINCLUDE CDEND UnityCG.cginc 等一系列带cg或注释的方法都是传统CG管线的内容
    2. // 新内容会是HLSLxxx字眼形式出现 (目的是演示如何将CG代码改为URP管线代码)
    3. Shader "MilkShader/Twently/G_GaussianBlur"
    4. {
    5. Properties
    6. {
    7. _MainTex("Texture", 2D) = "white" {}
    8. //采样间距系数
    9. _BlurSize("Blur Size", Float) = 1.0
    10. }
    11. SubShader
    12. {
    13. Tags { "RenderType" = "Opaque" }
    14. LOD 100
    15. //CGINCLUDE ... ENDCG 是一种组织结构,放在它里面的方法可以被任意Pass直接使用..相当于所有Pass都会有这些内容
    16. //CGINCLUDE //CG
    17. HLSLINCLUDE
    18. //#include "UnityCG.cginc" //CG
    19. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    20. sampler2D _MainTex;
    21. half4 _MainTex_TexelSize;
    22. float _BlurSize;
    23. //URP下没有appdata_img结构 要自定义
    24. struct a2v
    25. {
    26. float4 vertex : POSITION;
    27. float2 texcoord : TEXCOORD0;
    28. };
    29. struct v2f
    30. {
    31. float4 pos : SV_POSITION;
    32. half2 uv[5] : TEXCOORD0;
    33. };
    34. //我们只需要appdata_img内置结构的数据传入即可(有顶点、纹理坐标)
    35. v2f vertBlurVertical(a2v v) {
    36. v2f o;
    37. //o.pos = UnityObjectToClipPos(v.vertex); //CG
    38. VertexPositionInputs vertexInputs = GetVertexPositionInputs(v.vertex.xyz);
    39. o.pos = vertexInputs.positionCS;
    40. half2 uv = v.texcoord;
    41. //纵向的5个像素点纹理坐标
    42. o.uv[0] = uv;
    43. o.uv[1] = uv + float2(0.0, _MainTex_TexelSize.y * 1.0) * _BlurSize;
    44. o.uv[2] = uv - float2(0.0, _MainTex_TexelSize.y * 1.0) * _BlurSize;
    45. o.uv[3] = uv + float2(0.0, _MainTex_TexelSize.y * 2.0) * _BlurSize;
    46. o.uv[4] = uv - float2(0.0, _MainTex_TexelSize.y * 2.0) * _BlurSize;
    47. return o;
    48. }
    49. v2f vertBlurHorizontal(a2v v) {
    50. v2f o;
    51. //o.pos = UnityObjectToClipPos(v.vertex); //CG
    52. VertexPositionInputs vertexInputs = GetVertexPositionInputs(v.vertex.xyz);
    53. o.pos = vertexInputs.positionCS;
    54. half2 uv = v.texcoord;
    55. //横向的5个像素点纹理坐标
    56. o.uv[0] = uv;
    57. o.uv[1] = uv + float2(_MainTex_TexelSize.x * 1.0, 0.0) * _BlurSize;
    58. o.uv[2] = uv - float2(_MainTex_TexelSize.x * 1.0, 0.0) * _BlurSize;
    59. o.uv[3] = uv + float2(_MainTex_TexelSize.x * 2.0, 0.0) * _BlurSize;
    60. o.uv[4] = uv - float2(_MainTex_TexelSize.x * 2.0, 0.0) * _BlurSize;
    61. return o;
    62. }
    63. //无论是纵向还是横向,它们都会使用这个片元着色器,处理手法一样
    64. half4 fragBlur(v2f i) : SV_Target{
    65. float weight[3] = {0.4026, 0.2442, 0.0545};
    66. //采样RGB然后进行乘以对应的权重累加到sum
    67. half3 sum = tex2D(_MainTex, i.uv[0]).rgb * weight[0];
    68. for (int it = 1; it < 3; it++) {
    69. sum += tex2D(_MainTex, i.uv[it * 2 - 1]).rgb * weight[it];
    70. sum += tex2D(_MainTex, i.uv[it * 2]).rgb * weight[it];
    71. }
    72. //是的这样就完成了,模糊。。。。
    73. return half4(sum, 1.0);
    74. }
    75. //ENDCG //CG
    76. ENDHLSL
    77. //上面都是INCLUDE内容即下面Pass都可使用的内容
    78. //标配写法
    79. ZTest Always Cull Off ZWrite Off
    80. //第一个PASS,纵向模糊处理
    81. Pass
    82. {
    83. NAME "GAUSSIAN_BLUR_VERTICAL"
    84. //CGPROGRAM //CG
    85. HLSLPROGRAM
    86. //纵向的顶点着色器
    87. #pragma vertex vertBlurVertical
    88. //片元着色器
    89. #pragma fragment fragBlur
    90. //ENDCG //CG
    91. ENDHLSL
    92. }
    93. //第二个Pass 横向模糊处理
    94. Pass
    95. {
    96. NAME "GAUSSIAN_BLUR_HORIZONTAL"
    97. //CGPROGRAM
    98. HLSLPROGRAM
    99. //横向的顶点着色器
    100. #pragma vertex vertBlurHorizontal
    101. //片元着色器
    102. #pragma fragment fragBlur
    103. //ENDCG
    104. ENDHLSL
    105. }
    106. }//完成SubShader
    107. Fallback Off
    108. }

    1个Canvas和2个摄像机

    主要以上内容,实际上就是因为Render Pass Event是只能After Rendering Transpanrets在透明物体渲染完成后进行屏幕后处理模糊,导致无法实现置顶UI高清,底下UI模糊的需求,如果可以控制这个后处理时机是在置顶UI渲染之前进行后处理,等后处理完成后再渲染指定UI 那就可以,然而...

    TODO!!!

  • 相关阅读:
    Python中正整数
    工业控制系统的安全研究与实践引言
    Spark系列—spark简介
    662. 二叉树最大宽度(难度:中等)
    低代码与国产化部署:软件开发的未来趋势与应用实践
    Metasploit——后渗透测试阶段
    C#学习相关系列之Linq用法---where和select用法(二)
    校友在美团 Android 岗的四面分享~
    flink1.10中三种数据处理方式的连接器说明
    从入门开始手把手搭建千万级Java算法测试-快速化排序与随机化查找第k大数
  • 原文地址:https://blog.csdn.net/qq_39574690/article/details/132625411