1 高斯模糊原理

边缘检测特效中使用了卷积运算进行了边缘检测,本文实现的高斯模糊特效同样使用了卷积运算,关于卷积核和卷积运算的概念,读者可以参考边缘检测特效

​ 本文完整资源见→Unity3D高斯模糊特效

​ 我们将用于模糊处理的卷积核称为模糊算子,它一般满足以下条件:

  • 卷积核中权值上下对称、左右对称;
  • 卷积核中每个权值大于或等于 0,小于 1;
  • 卷积核中所有权值之和为 1。

​ 我们将所有权值都为 1 / n(n 为权值个数)的卷积核称为平均模糊算子;将权值随位置变化且符合高斯分布(或正太分布)的卷积核称为高斯模糊算子(或高斯核),它较好地模拟了邻域中每个像素对当前处理像素的影响程度(距离越近,影响越大)。高斯方程如下:

​ σ 是标准差,其值越大,高斯分布函数的图像越矮胖,一般取值为 1,x、y 为当前位置到卷积核中心的整数距离。要构建一个高斯核,我们只需要计算高斯核中各个位置对应的高斯值。为了保证模糊处理后的图像不会变暗,我们需要对高斯核中的元素进行归一化,即将所有元素都除以它们的权值和,从而保证归一化后的权值和为 1。因此,高斯函数中 e 前面的系数不会对高斯核产生任何影响,在计算高斯核的过程中可以省去。

​ 高斯核的维数越高,模糊程度越大。使用一个 n * n 的卷积核,需要进行 n * n * w * h 次纹理采样(w、h 分别为图像的宽高),为节省性能,我们将二维高斯核拆分为 2 个一维高斯核,采样次数只需要 2 * n * w * h 次。进一步观察到,2 个高斯核中包含了很多重复权重。对于一个大小为 5 的一维高斯核,实际只需记录 3 个权值即可。

2 代码实现

​ GaussianBlur.cs

using UnityEngine;

[ExecuteInEditMode] // 编辑态可以查看脚本运行效果
[RequireComponent(typeof(Camera))] // 需要相机组件
public class GaussianBlur : MonoBehaviour {
[Range(0, 4)]
public int iterations = 3; // 高斯模糊迭代次数
[Range(0.2f, 3.0f)]
public float blurSpread = 0.6f; // 每次迭代纹理坐标偏移的速度
[Range(1, 8)]
public int downSample = 2; // 降采样比率
private Material material = null; // 材质 private void Start() {
material = new Material(Shader.Find("MyShader/GaussianBlur"));
material.hideFlags = HideFlags.DontSave;
} void OnRenderImage(RenderTexture src, RenderTexture dest) {
if (material != null) {
int rtW = src.width / downSample; // 降采样的纹理宽度
int rtH = src.height / downSample; // 降采样的纹理高度
RenderTexture buffer0 = RenderTexture.GetTemporary(rtW, rtH, 0);
buffer0.filterMode = FilterMode.Bilinear; // 滤波模式设置为双线性
Graphics.Blit(src, buffer0);
for (int i = 0; i < iterations; i++) {
material.SetFloat("_BlurSize", 1.0f + i * blurSpread); // 设置模糊尺寸(纹理坐标的偏移量)
RenderTexture buffer1 = RenderTexture.GetTemporary(rtW, rtH, 0);
Graphics.Blit(buffer0, buffer1, material, 0); // 渲染垂直的Pass
RenderTexture.ReleaseTemporary(buffer0);
buffer0 = buffer1;
buffer1 = RenderTexture.GetTemporary(rtW, rtH, 0);
Graphics.Blit(buffer0, buffer1, material, 1); // 渲染水平的Pass
RenderTexture.ReleaseTemporary(buffer0);
buffer0 = buffer1;
}
Graphics.Blit(buffer0, dest);
RenderTexture.ReleaseTemporary(buffer0);
} else {
Graphics.Blit(src, dest);
}
}
}

​ GaussianBlur.shader

Shader "MyShader/GaussianBlur" { // 高斯模糊
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {} // 主纹理
_BlurSize ("Blur Size", Float) = 1.0 // 模糊尺寸(纹理坐标的偏移量)
} SubShader {
CGINCLUDE #include "UnityCG.cginc" sampler2D _MainTex; // 主纹理
half4 _MainTex_TexelSize; // _MainTex的像素尺寸大小, float4(1/width, 1/height, width, height)
float _BlurSize; // 模糊尺寸(纹理坐标的偏移量) struct v2f {
float4 pos : SV_POSITION; // 模型空间顶点坐标
half2 uv[5]: TEXCOORD0; // 5个邻域的纹理坐标
}; v2f vertBlurVertical(appdata_img v) { // 垂直模糊顶点着色器
v2f o;
o.pos = UnityObjectToClipPos(v.vertex); // 模型空间顶点坐标变换到裁剪空间, 等价于: mul(UNITY_MATRIX_MVP, v.vertex)
half2 uv = v.texcoord;
o.uv[0] = uv;
o.uv[1] = uv + float2(0.0, _MainTex_TexelSize.y * 1.0) * _BlurSize;
o.uv[2] = uv - float2(0.0, _MainTex_TexelSize.y * 1.0) * _BlurSize;
o.uv[3] = uv + float2(0.0, _MainTex_TexelSize.y * 2.0) * _BlurSize;
o.uv[4] = uv - float2(0.0, _MainTex_TexelSize.y * 2.0) * _BlurSize;
return o;
} v2f vertBlurHorizontal(appdata_img v) { // 水平模糊顶点着色器
v2f o;
o.pos = UnityObjectToClipPos(v.vertex); // 模型空间顶点坐标变换到裁剪空间, 等价于: mul(UNITY_MATRIX_MVP, v.vertex)
half2 uv = v.texcoord;
o.uv[0] = uv;
o.uv[1] = uv + float2(_MainTex_TexelSize.x * 1.0, 0.0) * _BlurSize;
o.uv[2] = uv - float2(_MainTex_TexelSize.x * 1.0, 0.0) * _BlurSize;
o.uv[3] = uv + float2(_MainTex_TexelSize.x * 2.0, 0.0) * _BlurSize;
o.uv[4] = uv - float2(_MainTex_TexelSize.x * 2.0, 0.0) * _BlurSize;
return o;
} fixed4 fragBlur(v2f i) : SV_Target {
float weight[3] = {0.4026, 0.2442, 0.0545}; // 大小为5的一维高斯核,实际只需记录3个权值
fixed3 sum = tex2D(_MainTex, i.uv[0]).rgb * weight[0];
for (int j = 1; j < 3; j++) {
sum += tex2D(_MainTex, i.uv[j * 2 - 1]).rgb * weight[j]; // 中心右侧或下侧的纹理*权值
sum += tex2D(_MainTex, i.uv[j * 2]).rgb * weight[j]; // 中心左侧或上侧的纹理*权值
}
return fixed4(sum, 1.0);
} ENDCG ZTest Always Cull Off ZWrite Off Pass {
NAME "GAUSSIAN_BLUR_VERTICAL" CGPROGRAM #pragma vertex vertBlurVertical
#pragma fragment fragBlur ENDCG
} Pass {
NAME "GAUSSIAN_BLUR_HORIZONTAL" CGPROGRAM #pragma vertex vertBlurHorizontal
#pragma fragment fragBlur ENDCG
}
} FallBack "Diffuse"
}

3 运行效果

1)原图

2)模糊处理

​ 调整模糊迭代次数 iterations 由 0 ~ 4 变化,效果如下:

​ 声明:本文转自【Unity3D】高斯模糊特效

【Unity3D】高斯模糊特效的更多相关文章

  1. Unity3d粒子特效:制作火焰效果

    效果 分析 真实的火焰效果,通常包括:火.火光.火星等组成部分,而火焰对周围环境的烘焙,可以通过灯光实现,如点光源. 针对火焰组成部分,我们可以创建对应的粒子系统组件,实现相应的效果,如下图所示: 1 ...

  2. 【Unity3D】基于粒子系统实现烟花特效

    1 需求实现 ​ 粒子系统ParticleSystem 中介绍了粒子初始化.粒子发射.发射器形状.渲染器.碰撞.子发射器.拖尾等粒子系统的基本用法,本节将基于粒子系统实现烟花特效. ​ 实现需求如下( ...

  3. C# 使用 Direct2D 实现斜角效果

    Direct2D 是微软新的二维图形 API,可为二维几何图形.位图和文本提供高性能和高质量的呈现.Direct2D 支持硬件加速,无论是绘制速度还是绘制质量,Direct2D 都要比 GDI 和 G ...

  4. Unity塔防游戏开发

    Unity3D塔防开发流程 配置环境及场景搭建编程语言:C#,略懂些许设计模式,如果不了解设计模式,BUG More开发工具:Unity3D编辑器.Visual Studio编译器开发建议:了解Uni ...

  5. 简单3D翻页相册制作教程

    3D效果看起来总是要比平面的图形看起来视觉效果要好的多,今天来教大家制作简单的3D翻页效果的视频. 视频预览链接:https://v.youku.com/v_show/id_XMzgxOTY5NzQz ...

  6. Unity3D特效-场景淡入淡出

    最近公司开始搞Unity3D..整个游戏..特效需求还是比较多的.关于UI部分的特效淡入淡出.看网上用的方法都是用个黑东东遮挡然后设置alpha这么搞....本大神感觉非常的low.而且很渣.故奋笔疾 ...

  7. unity3d 游戏插件 溶解特效插件 - Dissolve Shader

    unity3d 游戏插件 溶解特效插件 - Dissolve Shader   链接: https://pan.baidu.com/s/1hr7w39U 密码: 3ed2

  8. Unity3D之挥动武器产生的剑痕特效

    网维教程网 观看很多其它教程 眼下已知3种方法能够做这样的剑痕特效 1.尾随特效 2.程序实现动态面来处理剑痕动画. 3.美术实现剑痕动画,直接坐在模型动画里面 (由于我不会美术所以这个忽略 嘿嘿) ...

  9. [Unity3D]Unity3D游戏开发之刀光剑影特效的实现

    大家好,我是秦元培,欢迎大家关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei. 我实在不明确有的人为什么不喜欢武侠/仙侠类游戏,也许是因为武侠/仙侠类游戏身上被永远烙上的国 ...

  10. Unity3D学习笔记——组件之Effects(效果/特效)——Particle System(粒子系统)

    Effects:效果/特效. Particle System:粒子系统.可用于创建烟雾.气流.火焰.涟漪等效果. 在Unity3D 3.5版本之后退出了新的shuriken粒子系统:   添加组件之后 ...

随机推荐

  1. 2022-06-15:薯队长最近在参加了一个活动,主办方提供了N个礼物以供挑选, 每个礼物有一个价值,范围在0 ~ 10^9之间, 薯队长可以从中挑选k个礼物。 返回:其中价值最接近的两件礼物之间相差

    2022-06-15:薯队长最近在参加了一个活动,主办方提供了N个礼物以供挑选, 每个礼物有一个价值,范围在0 ~ 10^9之间, 薯队长可以从中挑选k个礼物. 返回:其中价值最接近的两件礼物之间相差 ...

  2. <form>表单中的action和method使用方法

    <form action="" method="post"> form是表单   里面的内容是要提交出去的. action 是链接   点击浏览选择 ...

  3. Can't uninstall 'Pillow'. No files were found to uninstall.

    Can't uninstall 'Pillow'. No files were found to uninstall. Pillow卸载不掉的解决办法 1.进入python所在路径,进入scripts ...

  4. 使用 React Three Fiber 和 GSAP 实现 WebGL 轮播动画

    参考:Building a WebGL Carousel with React Three Fiber and GSAP 在线 demo github 源码 效果来源于由 Eum Ray 创建的网站 ...

  5. Python基础 - 解释性语言和编译性语言

    什么是机器语言 计算机是不能理解高级语言,当然也就不能直接执行高级语言了.计算机只能直接理解机器语言,所以任何语言,都必须将其翻译成机器语言,计算机才能运行高级语言编写的程序.   如何把我们写的代码 ...

  6. 代码随想录算法训练营Day5 数组、链表复习

    数组部分 数组最重要的思维方式是双指针的使用. 快慢指针 在进行元素移除和元素操作时会使用两个for循环嵌套,此时时间复杂度为O(n²).在for循环中通过双指针(快慢指针)的使用可以使时间复杂度将为 ...

  7. 06、HSMS协议介绍

    本章的内容主要参考了 SECS半导体设备通讯-2 HSMS通信标准 ,外加上自己看的一些其他的文档.也加上了一些自己的理解,特此记录.若有侵权,请联系删除,谢谢. 再次特别感谢 SECS半导体设备通讯 ...

  8. 发布自己的项目到Maven中央仓库中

    注册账号和生成GPG生成密钥教程 主要看注册账号和生成GPG密匙部分就行了,出现问题可以先在这两个地方找 gpg加密发布jar包到maven中央仓库详细过程以及踩的坑_佛系猿秦大昊的博客-CSDN博客 ...

  9. Simple Date Format类到底为啥不是线程安全的?

    摘要:我们就一起看下在高并发下Simple Date Format类为何会出现安全问题,以及如何解决Simple Date Format类的安全问题. 本文分享自华为云社区<[高并发]Simpl ...

  10. Framework 中使用 Toolkit.Mvvm 的生成器功能

    .NET Standard是.NET APIs的正式规范,可在多个.NET实现中使用..NET Standard的动机是为了在.NET生态系统中建立更大的统一性..NET 5及更高版本采用了不同的方法 ...