高斯模糊,见 百度百科。

也使用卷积来实现,每个卷积元素的公式为:

其中б是标准方差,一般取值为1。

x和y分别对应当前位置到卷积中心的整数距离。

由于需要对高斯核中的权重进行归一化,即使所有权重相加为1,因此e前面的系数实际不会对结果产生任何影响。

转载请注明出处:http://www.cnblogs.com/jietian331/p/7238032.html

综上,公式简化为:

G(x,y) = e-(x*x+y*y)/2

因此,高斯核计算代码如下:

  1 using System;
  2
  3 namespace TestShell
  4 {
  5     class Program
  6     {
  7         static void Main(string[] args)
  8         {
  9             Console.WriteLine("输入需要得到的高斯卷积核的维数(如3,5,7...):");
 10
 11             string input = Console.ReadLine();
 12             int size;
 13
 14             if (!int.TryParse(input, out size))
 15             {
 16                 Console.WriteLine("不是数字...");
 17                 return;
 18             }
 19
 20             // 计算
 21             double[] r2 = null;
 22             double[,] r = null;
 23             try
 24             {
 25                 r = CalcGaussianBlur(size, out r2);
 26             }
 27             catch (Exception ex)
 28             {
 29                 Console.WriteLine("错误: " + ex.Message);
 30             }
 31
 32             if (r != null && r2 != null)
 33             {
 34                 // 卷积如下:
 35                 Console.WriteLine();
 36                 Console.WriteLine("{0}x{0}的高斯卷积核如下:", size);
 37                 for (int i = 0; i < r.GetLongLength(0); i++)
 38                 {
 39                     for (int j = 0; j < r.GetLongLength(1); j++)
 40                     {
 41                         Console.Write("{0:f4}\t", r[i, j]);
 42                     }
 43                     Console.WriteLine();
 44                 }
 45                 Console.WriteLine();
 46
 47                 Console.WriteLine("可拆成2个一维的数组:");
 48                 for (int i = 0; i < r2.Length; i++)
 49                 {
 50                     Console.Write("{0:f4}\t", r2[i]);
 51                 }
 52                 Console.WriteLine();
 53                 Console.WriteLine();
 54
 55                 Console.WriteLine("验证,使用这2个一维的数组也可以得到同样的结果:");
 56                 for (int i = 0; i < size; i++)
 57                 {
 58                     for (int j = 0; j < size; j++)
 59                     {
 60                         Console.Write("{0:f4}\t", r2[i] * r2[j]);
 61
 62                     }
 63                     Console.WriteLine();
 64                 }
 65             }
 66
 67             Console.WriteLine();
 68             Console.WriteLine("按任意键结束...");
 69             Console.ReadKey();
 70         }
 71
 72         static double[,] CalcGaussianBlur(int size, out double[] r2)
 73         {
 74             if (size < 3)
 75                 throw new ArgumentException("size < 3");
 76             if (size % 2 != 1)
 77                 throw new ArgumentException("size % 2 != 1");
 78
 79             double[,] r = new double[size, size];
 80             r2 = new double[size];
 81             int center = (int)Math.Floor(size / 2f);
 82             double sum = 0;
 83
 84             for (int i = 0; i < size; i++)
 85             {
 86                 for (int j = 0; j < size; j++)
 87                 {
 88                     int x = Math.Abs(i - center);
 89                     int y = Math.Abs(j - center);
 90                     double d = CalcItem(x, y);
 91                     r[i, j] = d;
 92                     sum += d;
 93                 }
 94             }
 95
 96             for (int i = 0; i < size; i++)
 97             {
 98                 for (int j = 0; j < size; j++)
 99                 {
100                     r[i, j] /= sum;
101                     if (i == j)
102                         r2[i] = Math.Sqrt(r[i, i]);
103                 }
104             }
105
106             return r;
107         }
108
109         static double CalcItem(int x, int y)
110         {
111             return Math.Pow(Math.E, -(x * x + y * y) / 2d);
112         }
113     }
114 }

View Code

工具在: http://files.cnblogs.com/files/jietian331/CalcGaussianBlur.zip

一个5 x 5的高斯核如下:

使用2个一维数组可简化计算量,提高性能,通过观察可知,只需要计3个数:

使用unity shader屏幕后期处理来实现高斯模糊,代码如下。

子类:

 1 using UnityEngine;
 2
 3 public class GaussianBlurRenderer : PostEffectRenderer
 4 {
 5     [Range(1, 8)]
 6     [SerializeField]
 7     public int m_downSample = 2;      // 降采样率
 8     [Range(0, 4)]
 9     [SerializeField]
10     public int m_iterations = 3;        // 迭代次数
11     [Range(0.2f, 3f)]
12     [SerializeField]
13     public float m_blurSpread = 0.6f;        // 模糊扩散量
14
15     protected override void OnRenderImage(RenderTexture src, RenderTexture dest)
16     {
17         int w = (int)(src.width / m_downSample);
18         int h = (int)(src.height / m_downSample);
19         RenderTexture buffer0 = RenderTexture.GetTemporary(w, h);
20         RenderTexture buffer1 = RenderTexture.GetTemporary(w, h);
21         buffer0.filterMode = FilterMode.Bilinear;
22         buffer1.filterMode = FilterMode.Bilinear;
23         Graphics.Blit(src, buffer0);
24
25         for (int i = 0; i < m_iterations; i++)
26         {
27             Mat.SetFloat("_BlurSpread", 1 + i * m_blurSpread);
28
29             Graphics.Blit(buffer0, buffer1, Mat, 0);
30             Graphics.Blit(buffer1, buffer0, Mat, 1);
31         }
32
33         Graphics.Blit(buffer0, dest);
34         RenderTexture.ReleaseTemporary(buffer0);
35         RenderTexture.ReleaseTemporary(buffer1);
36     }
37
38     protected override string ShaderName
39     {
40         get { return "Custom/Gaussian Blur"; }
41     }
42 }

GaussianBlurRenderer

shader:

 1 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 2
 3 Shader "Custom/Gaussian Blur"
 4 {
 5     Properties
 6     {
 7         _MainTex("Main Texture", 2D) = "white" {}
 8         _BlurSpread("Blur Spread", float) = 1
 9     }
10
11     SubShader
12     {
13         CGINCLUDE
14
15         sampler2D _MainTex;
16         float4 _MainTex_TexelSize;
17         uniform float _BlurSpread;
18
19         struct appdata
20         {
21             float4 vertex : POSITION;
22             float2 uv : TEXCOORD0;
23         };
24
25         struct v2f
26         {
27             float4 pos : SV_POSITION;
28             float2 uv[5] : TEXCOORD0;
29         };
30
31         v2f vertHorizontal(appdata v)
32         {
33             v2f o;
34             o.pos = UnityObjectToClipPos(v.vertex);
35             float tsx = _MainTex_TexelSize.x * _BlurSpread;
36             o.uv[0] = v.uv + float2(tsx * -2, 0);
37             o.uv[1] = v.uv + float2(tsx * -1, 0);
38             o.uv[2] = v.uv;
39             o.uv[3] = v.uv + float2(tsx * 1, 0);
40             o.uv[4] = v.uv + float2(tsx * 2, 0);
41             return o;
42         }
43
44         v2f vertVertical(appdata v)
45         {
46             v2f o;
47             o.pos = UnityObjectToClipPos(v.vertex);
48             float tsy = _MainTex_TexelSize.y * _BlurSpread;
49             o.uv[0] = v.uv + float2(0, tsy * -2);
50             o.uv[1] = v.uv + float2(0, tsy * -1);
51             o.uv[2] = v.uv;
52             o.uv[3] = v.uv + float2(0, tsy * 1);
53             o.uv[4] = v.uv + float2(0, tsy * 2);
54             return o;
55         }
56
57         fixed4 frag(v2f i) : SV_TARGET
58         {
59             float g[3] = {0.0545, 0.2442, 0.4026};
60             fixed4 col = tex2D(_MainTex, i.uv[2]) * g[2];
61             for(int k = 0; k < 2; k++)
62             {
63                 col += tex2D(_MainTex, i.uv[k]) * g[k];
64                 col += tex2D(_MainTex, i.uv[4 - k]) * g[k];
65             }
66             return col;
67         }
68
69         ENDCG
70
71         Pass
72         {
73             Name "HORIZONTAL"
74             ZTest Always
75             ZWrite Off
76             Cull Off
77
78             CGPROGRAM
79             #pragma vertex vertHorizontal
80             #pragma fragment frag
81             ENDCG
82         }
83
84         Pass
85         {
86             Name "VERTICAL"
87             ZTest Always
88             ZWrite Off
89             Cull Off
90
91             CGPROGRAM
92             #pragma vertex vertVertical
93             #pragma fragment frag
94             ENDCG
95         }
96     }
97
98     Fallback Off
99 }

Custom/Gaussian Blur

调整参数:

DownSample,即降采样率,越大性能越好,图像越模糊,但过大可能会使图像像素化。

Iteraitions, 即迭代次数,越大图像模糊效果越好,但性能也会下降。

BlurSpread,即模糊扩散量,越大图像越模糊,但过大会造成虚影。

效果如下:

 

转载于:https://www.cnblogs.com/jietian331/p/7238032.html

Unity shader学习之屏幕后期处理效果之高斯模糊相关推荐

  1. Unity Shader学习:Dissolve消融效果

    Unity Shader学习:Dissolve消融效果 消融效果在游戏里非常常用,这里简单的实现下,代码里用到了if分支在shader里可能会费一点,如果想直接用puppet_master大佬版本的话 ...

  2. 【Unity Shader学习】边缘泛光效果

    Shader "Sbin/Rim" {Properties{_Scale("Scale",Range(1,8)) = 1}SubShader{// 通过标签对透 ...

  3. Unity Shader学习:油画效果

    Unity Shader学习:油画效果 油画效果在学习浅墨大神的文章时看到的比较有趣,但是原文中也没详细的算法介绍如何实现,这里就先直接拿来用吧,UI和屏幕后处理都可以用,算法也看的不是很明白,好像是 ...

  4. Unity Shader学习:SSAO屏幕环境光遮蔽

    Unity Shader学习:SSAO屏幕环境光遮蔽 主要思路:1.随机采样像素法线半球周围的像素,平均对比与该像素深度是否处在暗处.2.双边滤波去噪点.3.后期AO图与原图混合. 原文链接:http ...

  5. Unity Shader学习:SSR屏幕空间反射

    Unity Shader学习:SSR屏幕空间反射 本文在前向渲染模式下实现,延迟渲染更适合SSR,这里只简单的实现下,未作更深入的优化. 思路:沿视线和法线的反射向量步进光线,判断打到物体(这里用的是 ...

  6. Unity Shader 学习笔记(33) 全局光照(GI)、反射探针、线性空间和伽马空间、高动态范围(HDR)

    Unity Shader 学习笔记(33) 全局光照(GI).反射探针.线性空间和伽马空间.高动态范围(HDR) 参考书籍:<Unity Shader 入门精要> [<Real-Ti ...

  7. Unity Shader学习:动态模糊(shutter angle方式)

    Unity Shader学习:动态模糊 动态模糊一般有帧混合和motion vector两种,这里主要介绍motion vector的方法. Keijiro源码:https://github.com/ ...

  8. Unity Shader学习:水墨效果

    Unity Shader学习:水墨效果 偶然在网上看到9级铁甲蛹大神的水墨风格后处理觉得挺有意思,参照着实现一下,还是涉及到之前油画效果的算法,叫什么滤波暂时不清楚,应该用来处理手绘效果挺多的. 水墨 ...

  9. 《Unity Shader入门精要》学习笔记第5章 开始Unity Shader学习之旅

    本文章用于帮助自己学习,因此只记录一些个人认为比较重要或者还不够熟悉的内容. 原作者:http://blog.csdn.net/candycat1992/article/ 第五章 开始Unity Sh ...

最新文章

  1. linux oracle目录权限不够,Linux 目录权限不足导致ORA-39070错误 | 信春哥,系统稳,闭眼上线不回滚!...
  2. 【Linux网络编程】网络协议入门
  3. [嵌入式][分享][交流]发布一个消息地图的模块
  4. 集群服务负载均衡------LVS
  5. Docker工具箱继续增加
  6. 如何通过直接复制frm文件以实现恢复/复制innodb数据表?
  7. Leetcode-树
  8. 《项目经验》静态页面图片找不到
  9. sybase数据库与oracle,Oracle访问Sybase数据库的方法
  10. 大型医院his系统源码 医院信息管理系统源码 C/S架构
  11. c语言加油站仿真实验报告,c程序队列实现模拟加油站研讨.ppt
  12. UITableView在iOS15中显示混乱的问题
  13. 关于pr的一些实用小知识
  14. 将自己的app加入到分享列表中,并适配锤子的one step功能
  15. EPICS教程1 -- 在Linux/UNIX/DARWIN(MAC)上安装
  16. 运放的 零点和极点快速找到
  17. Protocol “https“ not supported or disabled in libcurl
  18. python蓝牙的使用
  19. Oracle建表及添加数据
  20. LBG 矢量量化算法

热门文章

  1. SpringBoot自定义转换器(Convert)
  2. 一文搞定C语言本地变量和全局变量
  3. hdu-2544(简单djikstra)
  4. Android mediaRecorder框架简述(二)
  5. 数据存储之 SQLite 数据库操作(二)
  6. python自学行_怎么自学python?
  7. python 任务计划_使用Python添加计划任务
  8. QML和C++混合编程--(一)
  9. Qt 互斥锁 QMutex 的简单应用
  10. android uri转drawable,Glide4(URL转File,URL转Drawable)