原理
采样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博客
标签:Material,RenderTexture,MainTex,模糊,half2,后处理,source,BlurOffset,高斯 From: https://www.cnblogs.com/sailJs/p/18102276