原理
取樣5x5範圍的畫素(即25個畫素),然後按中間往外減少的權重值,計算出最終顏色值。
效果
c#程式碼
using UnityEngine; public class GaussianBlurEff : MonoBehaviour { public Shader m_Shader; public Material m_Material; [Range(-3, 3)] public float m_BlurOffset = 1; public bool m_DoubleBlur; //是否啟用雙重模糊 private int m_SrcRTWidth; private int m_SrcRTHeight; private RenderTexture m_RTHalfSize; //一半大小 private RenderTexture m_RTQuarterSize; //1/4大小 void Start() { if (false == SystemInfo.supportsImageEffects) { Debug.LogWarning("This platform does not support image effects or render textures."); this.enabled = false; return; } InitMaterial(ref m_Shader, ref m_Material); if (null != m_Material) m_Material.SetFloat("_BlurOffset", m_BlurOffset); } private static void InitMaterial(ref Shader s, ref Material mat) { if (null == mat) { if (null != s && s.isSupported) { mat = new Material(s); mat.hideFlags = HideFlags.DontSave; } } else if (null != s && mat.shader != s) { if (s.isSupported) //優先shader { mat = new Material(s); mat.hideFlags = HideFlags.DontSave; } else { mat = null; } } } private void OnRenderImage(RenderTexture source, RenderTexture destination) { if (null == m_Material) { Graphics.Blit(source, destination); } else { #if UNITY_EDITOR m_Material.SetFloat("_BlurOffset", m_BlurOffset); #endif if (m_DoubleBlur) DoubleBlur(source, destination); else Graphics.Blit(source, destination, m_Material, 0); } } private void DoubleBlur(RenderTexture source, RenderTexture destination) { if (m_SrcRTWidth != source.width || m_SrcRTHeight != source.height) { m_SrcRTWidth = source.width; m_SrcRTHeight = source.height; m_RTHalfSize = RenderTexture.GetTemporary((int)(m_SrcRTWidth * 0.5f), (int)(m_SrcRTHeight * 0.5f)); m_RTQuarterSize = RenderTexture.GetTemporary((int)(m_SrcRTWidth * 0.25f), (int)(m_SrcRTHeight * 0.25f)); } //降取樣 Graphics.Blit(source, m_RTHalfSize, m_Material, 0); Graphics.Blit(m_RTHalfSize, m_RTQuarterSize, m_Material, 1); //升取樣 Graphics.Blit(m_RTQuarterSize, m_RTHalfSize, m_Material, 0); Graphics.Blit(m_RTHalfSize, destination, m_Material, 1); } void OnDestroy() { if (null != m_RTHalfSize) { RenderTexture.ReleaseTemporary(m_RTHalfSize); RenderTexture.ReleaseTemporary(m_RTQuarterSize); m_RTHalfSize = null; m_RTQuarterSize = null; } } }
shader
Shader "My/PostEff/GaussianBlur" { CGINCLUDE #include "UnityCG.cginc" sampler2D _MainTex; float4 _MainTex_TexelSize; //貼圖大小資訊, 1/width, 1/height, width, height float _BlurOffset; //高斯模糊橫向 half4 frag_HorizontalBlur(v2f_img i) : SV_Target { half2 uv1 = i.uv + _MainTex_TexelSize.xy* half2(1, 0)*_BlurOffset * -2.0; //-2/width * _BlurOffset half2 uv2 = i.uv + _MainTex_TexelSize.xy* half2(1, 0)*_BlurOffset * -1.0; //-1/width * _BlurOffset half2 uv3 = i.uv; half2 uv4 = i.uv + _MainTex_TexelSize.xy* half2(1, 0)*_BlurOffset * 1.0; //1/width * _BlurOffset half2 uv5 = i.uv + _MainTex_TexelSize.xy* half2(1, 0)*_BlurOffset * 2.0; //2/width * _BlurOffset half4 s = 0; //權重從中間外往減少 s += tex2D(_MainTex, uv1) * 0.05; s += tex2D(_MainTex, uv2) * 0.25; s += tex2D(_MainTex, uv3) * 0.40; //中間權重 s += tex2D(_MainTex, uv4) * 0.25; s += tex2D(_MainTex, uv5) * 0.05; return s; } //高斯模糊縱向 half4 frag_VerticalBlur(v2f_img i) : SV_Target { half2 uv1 = i.uv + _MainTex_TexelSize.xy* half2(0, 1)*_BlurOffset * -2.0; //-2/height * _BlurOffset half2 uv2 = i.uv + _MainTex_TexelSize.xy* half2(0, 1)*_BlurOffset * -1.0; //-1/height * _BlurOffset half2 uv3 = i.uv; half2 uv4 = i.uv + _MainTex_TexelSize.xy* half2(0, 1)*_BlurOffset * 1.0; //1/height * _BlurOffset half2 uv5 = i.uv + _MainTex_TexelSize.xy* half2(0, 1)*_BlurOffset * 2.0; //2/height * _BlurOffset half4 s = 0; //權重從中間外往減少 s += tex2D(_MainTex, uv1) * 0.05; s += tex2D(_MainTex, uv2) * 0.25; s += tex2D(_MainTex, uv3) * 0.40; //中間權重 s += tex2D(_MainTex, uv4) * 0.25; s += tex2D(_MainTex, uv5) * 0.05; return s; } ENDCG Properties { _MainTex("Texture", 2D) = "white" {} //主貼圖 _BlurOffset("BlurOffset", Float) = 1 } SubShader { Cull Off //剔除關閉 ZWrite Off //寫入深度buff關閉 ZTest Always //深度測試啟用 Pass //Pass0 { CGPROGRAM #pragma vertex vert_img #pragma fragment frag_HorizontalBlur ENDCG } Pass //Pass1 { CGPROGRAM #pragma vertex vert_img #pragma fragment frag_VerticalBlur ENDCG } } }
參考
Unity自定義後處理——模糊效果_unity圖片模糊效果-CSDN部落格