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难写的原因之一--如果发现得到的效果不对,我们 ...
随机推荐
- vuex的小demo
效果图: vue的app.vue <template> <div> <p>click {{count}} times,count is {{evenOrOdd}}& ...
- java使用DateUtils对日期进行运算
最近在写数据上传的程序,需要对Date进行一些数学运算,个人感觉在java中,日期的数学运算还是比较常用的,所以把Date的数学运算都玩了一下.试了一下,发现DateUtils这个工具类对于Date的 ...
- finecms如何批量替换文章中的关键词?
Finecms批量替换文章关键词要怎么操作呢,比如把关键词A换为B?Finecms是免费开源无商业限制的内容管理系统,个人在维护,但二次开发很灵活,我们可以通过开发插件或数据库sql语句来操作,下面就 ...
- 限制SSH用户访问Linux中指定的目录
限制SSH用户访问Linux中指定的目录 http://os.51cto.com/art/201703/534895.htm#topx http://www.cnblogs.com/lykyl/arc ...
- 20180820 JS 片段
$.post异步发送容易引起后台没有处理完,就提示错误异常.在不必要的情况下,请采用.同步的方式 $.ajaxSetup({ async: false }); 但在$.post结束后记得恢复系统默认的 ...
- 20170731 培训Bootstrap
Bootstrap使用 涉及培训内容框架:--1 html html为标记语言,可以理解为容器,就是用来承载你想要展示到网页的内容的容器.版本也有很多,不同版本表示不同的标记的新增或者取代. Boot ...
- Python中使用SMTP发送邮件以及POP收取邮件
假设我们自己的电子邮件地址是from@163.com,对方的电子邮件地址是to@sina.com(这里的地址虚拟的),现在我们用Outlook或者Foxmail之类的软件写好邮件,填上对方的Email ...
- Python3学习之路~5.6 shutil & zipfile & tarfile模块
高级的 文件.文件夹.压缩包 处理模块 shutil.copyfileobj(fsrc, fdst[, length])#将文件内容拷贝到另一个文件中,可以部分内容 shutil.copyfile(s ...
- Python统计日志中每个IP出现次数
介绍了Python统计日志中每个IP出现次数的方法,实例分析了Python基于正则表达式解析日志文件的相关技巧,需要的朋友可以参考下 本脚本可用于多种日志类型 #-*- coding:utf-8 -* ...
- 【剑指offer】把数组排成最小的数
一.题目: 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323. 二.思路: ...