【Unity Shader编程】之十五 屏幕高斯模糊 Gaussian Blur 后期特效的实现

               



 本系列文章由@浅墨_毛星云 出品,转载请注明出处。  
 文章链接: http://blog.csdn.net/poem_qianmo/article/details/51871531
 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442 
 本文工程使用的Unity3D版本: 5.2.1 


 

本篇文章将分析如何在Unity中基于Shader实现高斯模糊屏幕后期特效。

首先放出最终的实现效果。如下几幅图,是在Unity中使用本文所实现的Shader得到的高斯模糊屏幕后期特效与原始图的效果对比图。

 

 

卡通风格的效果测试:



 


写实风格的效果测试:






OK,下面我们开始分析如何在Unity中实现上述的高斯模糊特效。

 




 

一、降采样与高斯模糊的原理


 

首先梳理一下在Unity中实现高斯模糊效果需用到的几个图像处理的知识点,说起来也很巧,正好和之前我写过一个关于OpenCV的系列博客里的这篇文章(http://blog.csdn.net/poem_qianmo/article/details/22745559)涉及的知识点类似。

 

 



1.1 关于图像的降采样

 


降采样(Downsample)也称下采样(Subsample),按字面意思理解即是降低采样频率。对于一幅N*M的图像来说,如果降采样系数为k,则降采样即是在原图中每行每列每隔k个点取一个点组成一幅图像的一个过程。

不难得出,降采样系数K值越大,则需要处理的像素点越少,运行速度越快。




1.2 高斯模糊的原理

 


高斯模糊(Gaussian Blur),也叫高斯平滑,高斯滤波,其通常用它来减少图像噪声以及降低细节层次,常常也被用于对图像进行模糊。

通俗的讲,高斯模糊就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。高斯模糊的具体操作是:用一个模板(或称卷积、掩模)扫描图像中的每一个像素,用模板确定的邻域内像素的加权平均灰度值去替代模板中心像素点的值。

高斯分布的数学表示如下:

其中,x为到像素中心的距离,σ为标准差。

 

 

高斯分布(正态分布曲线)

分条来说明一下高斯模糊的几个要点:

  • 从数学的角度来看,图像的高斯模糊过程就是图像与正态分布做卷积。
  • 由于正态分布又叫作高斯分布,所以这项技术就叫作高斯模糊。
  • 高斯模糊能够把某一点周围的像素色值按高斯曲线统计起来,采用数学上加权平均的计算方法得到这条曲线的色值
  • 所谓"模糊",可以理解成每一个像素都取周边像素的平均值。
  • 图像与圆形方框模糊做卷积将会生成更加精确的焦外成像效果。由于高斯函数的傅立叶变换是另外一个高斯函数,所以高斯模糊对于图像来说就是一个低通滤波器。

高斯模糊的原理大致如此。若各位还想进一步了解,可以参考高斯模糊的wiki,以及《Real-Time Rendering 3rd》,或各种图像处理的书籍。相关参考内容见附录中的reference。

下面主要来一起看一下高斯模糊特效在Unity中的实现。


 




二、高斯模糊特效在Unity中的实现





Unity中的屏幕特效,通常分为两部分来实现:

    • Shader代码实现部分
    • C#/javascript代码实现部分

 上述两者结合起来,便可以在Unity中实现具有很强可控性和灵活性的屏幕后期特效。

下面即是从这两个方面对高斯模糊的特效进行实现。其实现思路类似Standard Assets/Image Effect中的Blur,但是本文的实现更简洁,有更大的可控性。

 

 


2.1 Shader代码部分



本次的高斯模糊Shader包含逐行注释后约200多行。

书写思路方面,采用了3个通道(Pass)各司其职,他们分别是:

  • 通道0:降采样通道。
  • 通道1:垂直方向模糊处理通道。
  • 通道2:水平方向模糊处理通道。

而三个通道中共用的变量、函数和结构体的代码位于CGINCLUDE和ENDCG之间。

以下贴出经过详细注释的Shader源码:

 

Shader "Learning Unity Shader/Lecture 15/RapidBlurEffect"//-----------------------------------【属性 || Properties】------------------------------------------   Properties {  //主纹理  _MainTex("Base (RGB)", 2D) = "white" {} } //----------------------------------【子着色器 || SubShader】---------------------------------------   SubShader {  ZWrite Off  Blend Off  //---------------------------------------【通道0 || Pass 0】------------------------------------  //通道0:降采样通道 ||Pass 0: Down Sample Pass  Pass  {   ZTest Off   Cull Off   CGPROGRAM   //指定此通道的顶点着色器为vert_DownSmpl   #pragma vertex vert_DownSmpl   //指定此通道的像素着色器为frag_DownSmpl 

你可能感兴趣的:(【Unity Shader编程】之十五 屏幕高斯模糊 Gaussian Blur 后期特效的实现)