Unity shader学习之屏幕后期处理效果之高斯模糊
高斯模糊,见 百度百科。
也使用卷积来实现,每个卷积元素的公式为:
其中б是标准方差,一般取值为1。
x和y分别对应当前位置到卷积中心的整数距离。
由于需要对高斯核中的权重进行归一化,即使所有权重相加为1,因此e前面的系数实际不会对结果产生任何影响。
转载请注明出处:http://www.cnblogs.com/jietian331/p/7238032.html
综上,公式简化为:
G(x,y) = e-(x*x+y*y)/2
因此,高斯核计算代码如下:
using System; namespace TestShell
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("输入需要得到的高斯卷积核的维数(如3,5,7...):"); string input = Console.ReadLine();
int size; if (!int.TryParse(input, out size))
{
Console.WriteLine("不是数字...");
return;
} // 计算
double[] r2 = null;
double[,] r = null;
try
{
r = CalcGaussianBlur(size, out r2);
}
catch (Exception ex)
{
Console.WriteLine("错误: " + ex.Message);
} if (r != null && r2 != null)
{
// 卷积如下:
Console.WriteLine();
Console.WriteLine("{0}x{0}的高斯卷积核如下:", size);
for (int i = ; i < r.GetLongLength(); i++)
{
for (int j = ; j < r.GetLongLength(); j++)
{
Console.Write("{0:f4}\t", r[i, j]);
}
Console.WriteLine();
}
Console.WriteLine(); Console.WriteLine("可拆成2个一维的数组:");
for (int i = ; i < r2.Length; i++)
{
Console.Write("{0:f4}\t", r2[i]);
}
Console.WriteLine();
Console.WriteLine(); Console.WriteLine("验证,使用这2个一维的数组也可以得到同样的结果:");
for (int i = ; i < size; i++)
{
for (int j = ; j < size; j++)
{
Console.Write("{0:f4}\t", r2[i] * r2[j]); }
Console.WriteLine();
}
} Console.WriteLine();
Console.WriteLine("按任意键结束...");
Console.ReadKey();
} static double[,] CalcGaussianBlur(int size, out double[] r2)
{
if (size < )
throw new ArgumentException("size < 3");
if (size % != )
throw new ArgumentException("size % 2 != 1"); double[,] r = new double[size, size];
r2 = new double[size];
int center = (int)Math.Floor(size / 2f);
double sum = ; for (int i = ; i < size; i++)
{
for (int j = ; j < size; j++)
{
int x = Math.Abs(i - center);
int y = Math.Abs(j - center);
double d = CalcItem(x, y);
r[i, j] = d;
sum += d;
}
} for (int i = ; i < size; i++)
{
for (int j = ; j < size; j++)
{
r[i, j] /= sum;
if (i == j)
r2[i] = Math.Sqrt(r[i, i]);
}
} return r;
} static double CalcItem(int x, int y)
{
return Math.Pow(Math.E, -(x * x + y * y) / 2d);
}
}
}
工具在:http://files.cnblogs.com/files/jietian331/CalcGaussianBlur.zip
一个5 x 5的高斯核如下:

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

使用unity shader屏幕后期处理来实现高斯模糊,代码如下。
子类:
using UnityEngine; public class GaussianBlurRenderer : PostEffectRenderer
{
[Range(, )]
[SerializeField]
public int m_downSample = ; // 降采样率
[Range(, )]
[SerializeField]
public int m_iterations = ; // 迭代次数
[Range(0.2f, 3f)]
[SerializeField]
public float m_blurSpread = 0.6f; // 模糊扩散量 protected override void OnRenderImage(RenderTexture src, RenderTexture dest)
{
int w = (int)(src.width / m_downSample);
int h = (int)(src.height / m_downSample);
RenderTexture buffer0 = RenderTexture.GetTemporary(w, h);
RenderTexture buffer1 = RenderTexture.GetTemporary(w, h);
buffer0.filterMode = FilterMode.Bilinear;
buffer1.filterMode = FilterMode.Bilinear;
Graphics.Blit(src, buffer0); for (int i = ; i < m_iterations; i++)
{
Mat.SetFloat("_BlurSpread", + i * m_blurSpread); Graphics.Blit(buffer0, buffer1, Mat, );
Graphics.Blit(buffer1, buffer0, Mat, );
} Graphics.Blit(buffer0, dest);
RenderTexture.ReleaseTemporary(buffer0);
RenderTexture.ReleaseTemporary(buffer1);
} protected override string ShaderName
{
get { return "Custom/Gaussian Blur"; }
}
}
GaussianBlurRenderer
shader:
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/Gaussian Blur"
{
Properties
{
_MainTex("Main Texture", 2D) = "white" {}
_BlurSpread("Blur Spread", float) =
} SubShader
{
CGINCLUDE sampler2D _MainTex;
float4 _MainTex_TexelSize;
uniform float _BlurSpread; struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
}; struct v2f
{
float4 pos : SV_POSITION;
float2 uv[] : TEXCOORD0;
}; v2f vertHorizontal(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
float tsx = _MainTex_TexelSize.x * _BlurSpread;
o.uv[] = v.uv + float2(tsx * -, );
o.uv[] = v.uv + float2(tsx * -, );
o.uv[] = v.uv;
o.uv[] = v.uv + float2(tsx * , );
o.uv[] = v.uv + float2(tsx * , );
return o;
} v2f vertVertical(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
float tsy = _MainTex_TexelSize.y * _BlurSpread;
o.uv[] = v.uv + float2(, tsy * -);
o.uv[] = v.uv + float2(, tsy * -);
o.uv[] = v.uv;
o.uv[] = v.uv + float2(, tsy * );
o.uv[] = v.uv + float2(, tsy * );
return o;
} fixed4 frag(v2f i) : SV_TARGET
{
float g[] = {0.0545, 0.2442, 0.4026};
fixed4 col = tex2D(_MainTex, i.uv[]) * g[];
for(int k = ; k < ; k++)
{
col += tex2D(_MainTex, i.uv[k]) * g[k];
col += tex2D(_MainTex, i.uv[ - k]) * g[k];
}
return col;
} ENDCG Pass
{
Name "HORIZONTAL"
ZTest Always
ZWrite Off
Cull Off CGPROGRAM
#pragma vertex vertHorizontal
#pragma fragment frag
ENDCG
} Pass
{
Name "VERTICAL"
ZTest Always
ZWrite Off
Cull Off CGPROGRAM
#pragma vertex vertVertical
#pragma fragment frag
ENDCG
}
} Fallback Off
}
Custom/Gaussian Blur
调整参数:

DownSample,即降采样率,越大性能越好,图像越模糊,但过大可能会使图像像素化。
Iteraitions, 即迭代次数,越大图像模糊效果越好,但性能也会下降。
BlurSpread,即模糊扩散量,越大图像越模糊,但过大会造成虚影。
效果如下:

Unity shader学习之屏幕后期处理效果之高斯模糊的更多相关文章
- Unity shader学习之屏幕后期处理效果之Bloom效果
Bloom特效是游戏中常见的一种屏幕效果.这种特效可以模拟真实摄像机的一种图像效果,它让画面中较亮的区域“扩散”到周围的区域中,造成一种朦胧的效果. Bloom的实现原理很简单,首先根据一个阈值提取出 ...
- Unity shader学习之屏幕后期处理效果之运动模糊
运动模糊,代码如下: using UnityEngine; public class MotionBlurRenderer : PostEffectRenderer { [Range(0.1f, 0. ...
- Unity shader学习之屏幕后期处理效果之均值模糊
均值模糊,也使用卷积来实现,之不过卷积中每个值均相等,且相加等于1. 代码如下, 子类: using UnityEngine; public class MeanBlurRenderer : Post ...
- Unity shader学习之屏幕后期处理效果之边缘检测
边缘检测的原理是利用一些边缘检测算子对图像进行卷积操作. 转载请注明出处:http://www.cnblogs.com/jietian331/p/7232707.html 例如: 代码如下: usin ...
- Unity shader学习之屏幕后期处理效果之高度雾,重建world pos方法2
这里使用一种更高效地从深度纹理中重建世界坐标的方法. 首先计算摄像机的视锥体的四条射线向量进行线性插值,插值后的值便是该像素在世界空间坐标下到摄像机的方向. 然后通过与深度值相乘即可得到摄像机位置到该 ...
- Unity shader学习之屏幕后期效果之调整屏幕亮度,饱和度,对比度
Unity的屏幕后期处理效果,使用MonoBehaviour.OnRenderImage来实现. 转载请注明出处:http://www.cnblogs.com/jietian331/p/7228063 ...
- Unity Shader 学习之旅
Unity Shader 学习之旅 unityshader图形图像 纸上学来终觉浅,绝知此事要躬行 美丽的梦和美丽的诗一样 都是可遇而不可求的——席慕蓉 一.渲染流水线 示例图 Tips:什么是 GP ...
- Unity Shader 学习之旅之SurfaceShader
Unity Shader 学习之旅之SurfaceShader unity shader 图形图像 如果大地的每个角落都充满了光明 谁还需要星星,谁还会 在夜里凝望 寻找遥远的安慰——江河 官方文档 ...
- 第四章 开始Unity Shader学习之旅(3)
1. 程序员的烦恼:Debug 调试(debug),大概是所有程序员的噩梦.而不幸的是,对一个Shader进行调试更是噩梦中的噩梦.这也是造成Shader难写的原因之一--如果发现得到的效果不对,我们 ...
随机推荐
- shell 文件描述符
/tmp/test.sh > /tmp/test.log 2>&1 这个命令的意思是 前半部分是将shell的输出重定向到/tmp/test/log.默认是标准输出(stdout文 ...
- [Day1]常用Dos命令,Java相关描述及基础
1.常用的DOS命令 (1)返回上一级目录:cd.. (2)返回盘符根目录:cd\ (3)切换当前盘符: 盘符: (4)进入文件夹: cd 文件路径 (5)展示当前目录下的所有内容:D ...
- Xcode 编辑器之Workspace,Project,Scheme,Target
一,前言 最近老是突然对Workspace,Project,Scheme,Target四者的关系有些疑惑,所以查阅资料总结一下. 二,Workspace,Project,Scheme,Target四者 ...
- [git] 关闭 git branch 的pager
高版本的git做了pager的调整. git diff git log git branch 等命令都用了pager, 默认的pager用了less 在我的应用里, 通常branch只有那么3,5个. ...
- [ovs] openvswitch 入门
https://www.sdnlab.com/sdn-guide/14747.html http://sdnhub.cn/index.php/openv-switch-full-guide/ http ...
- odoo 权限设置
*权限管理的四个层次 # 菜单级别:不属于指定菜单所包含组的用户看不到该菜单,不客全,只是隐藏 菜单,若知道菜单ID,仍然可以通过指定URL访问 # 对象级 ...
- LeetCode 427 Construct Quad Tree 解题报告
题目要求 We want to use quad trees to store an N x N boolean grid. Each cell in the grid can only be tru ...
- 20165336 2017-2018-2 《Java程序设计》第7周学习总结
20165336 2016-2017-2 <Java程序设计>第7周学习总结 教材学习内容总结 查询操作:向数据库发送SQL查询语句,处理查询结果,关闭连接. 顺序查询:next()方法向 ...
- 递归、嵌套for循环、map集合方式实现树形结构菜单列表查询
有时候, 我们需要用到菜单列表,但是怎么样去实现一个菜单列表的编写呢,这是一重要的问题. 比如我们需要编写一个树形结构的菜单,那么我们可以使用JQuery的zTree插件:http://www.tre ...
- 003-hive安装
http://www.aboutyun.com/thread-6902-1-1.html http://www.aboutyun.com/thread-7374-1-1.html