Unity Shader-后处理:高斯模糊
一.简介
二.概念介绍
1.正态分布
2.卷积
如果你每天都到地下去打台球,那么老板每天都要扇你一巴掌,不过当老板打你一巴掌后,你5分钟就消肿了,所以时间长了,你甚至就适应这种生活了……如果有一天,老板忍无可忍,以0.5秒的间隔开始不间断的扇你的过程,这样问题就来了,第一次扇你鼓起来的包还没消肿,第二个巴掌就来了,你脸上的包就可能鼓起来两倍高,老板不断扇你,脉冲不断作用在你脸上,效果不断叠加了,这样这些效果就可以求和了,结果就是你脸上的包的高度随时间变化的一个函数了(注意理解);如果老板再狠一点,频率越来越高,以至于你都辨别不清时间间隔了,那么,求和就变成积分了。可以这样理解,在这个过程中的某一固定的时刻,你的脸上的包的鼓起程度和什么有关呢?和之前每次打你都有关!但是各次的贡献是不一样的,越早打的巴掌,贡献越小,所以这就是说,某一时刻的输出是之前很多次输入乘以各自的衰减系数之后的叠加而形成某一点的输出,然后再把不同时刻的输出点放在一起,形成一个函数,这就是卷积,卷积之后的函数就是你脸上的包的大小随时间变化的函数。本来你的包几分钟就可以消肿,可是如果连续打,几个小时也消不了肿了,这难道不是一种平滑过程么?反映到剑桥大学的公式上,f(a)就是第a个巴掌,g(x-a)就是第a个巴掌在x时刻的作用程度,乘起来再叠加就ok了
三.高斯模糊的实现
- Shader "Custom/GaussianBlur"
- {
- Properties
- {
- _MainTex("Base (RGB)", 2D) = "white" {}
- }
- //通过CGINCLUDE我们可以预定义一些下面在Pass中用到的struct以及函数,
- //这样在pass中只需要设置渲染状态以及调用函数,shader更加简洁明了
- CGINCLUDE
- #include "UnityCG.cginc"
- //blur结构体,从blur的vert函数传递到frag函数的参数
- struct v2f_blur
- {
- float4 pos : SV_POSITION; //顶点位置
- float2 uv : TEXCOORD0; //纹理坐标
- float4 uv01 : TEXCOORD1; //一个vector4存储两个纹理坐标
- float4 uv23 : TEXCOORD2; //一个vector4存储两个纹理坐标
- float4 uv45 : TEXCOORD3; //一个vector4存储两个纹理坐标
- };
- //shader中用到的参数
- sampler2D _MainTex;
- //XX_TexelSize,XX纹理的像素相关大小width,height对应纹理的分辨率,x = 1/width, y = 1/height, z = width, w = height
- float4 _MainTex_TexelSize;
- //给一个offset,这个offset可以在外面设置,是我们设置横向和竖向blur的关键参数
- float4 _offsets;
- //vertex shader
- v2f_blur vert_blur(appdata_img v)
- {
- v2f_blur o;
- o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
- //uv坐标
- o.uv = v.texcoord.xy;
- //计算一个偏移值,offset可能是(0,1,0,0)也可能是(1,0,0,0)这样就表示了横向或者竖向取像素周围的点
- _offsets *= _MainTex_TexelSize.xyxy;
- //由于uv可以存储4个值,所以一个uv保存两个vector坐标,_offsets.xyxy * float4(1,1,-1,-1)可能表示(0,1,0-1),表示像素上下两个
- //坐标,也可能是(1,0,-1,0),表示像素左右两个像素点的坐标,下面*2.0,*3.0同理
- o.uv01 = v.texcoord.xyxy + _offsets.xyxy * float4(1, 1, -1, -1);
- o.uv23 = v.texcoord.xyxy + _offsets.xyxy * float4(1, 1, -1, -1) * 2.0;
- o.uv45 = v.texcoord.xyxy + _offsets.xyxy * float4(1, 1, -1, -1) * 3.0;
- return o;
- }
- //fragment shader
- fixed4 frag_blur(v2f_blur i) : SV_Target
- {
- fixed4 color = fixed4(0,0,0,0);
- //将像素本身以及像素左右(或者上下,取决于vertex shader传进来的uv坐标)像素值的加权平均
- color += 0.4 * tex2D(_MainTex, i.uv);
- color += 0.15 * tex2D(_MainTex, i.uv01.xy);
- color += 0.15 * tex2D(_MainTex, i.uv01.zw);
- color += 0.10 * tex2D(_MainTex, i.uv23.xy);
- color += 0.10 * tex2D(_MainTex, i.uv23.zw);
- color += 0.05 * tex2D(_MainTex, i.uv45.xy);
- color += 0.05 * tex2D(_MainTex, i.uv45.zw);
- return color;
- }
- ENDCG
- //开始SubShader
- SubShader
- {
- //开始一个Pass
- Pass
- {
- //后处理效果一般都是这几个状态
- ZTest Always
- Cull Off
- ZWrite Off
- Fog{ Mode Off }
- //使用上面定义的vertex和fragment shader
- CGPROGRAM
- #pragma vertex vert_blur
- #pragma fragment frag_blur
- ENDCG
- }
- }
- //后处理效果一般不给fallback,如果不支持,不显示后处理即可
- }
- using UnityEngine;
- using System.Collections;
- //编辑状态下也运行
- [ExecuteInEditMode]
- //继承自PostEffectBase
- public class GaussianBlur : PostEffectBase
- {
- //模糊半径
- public float BlurRadius = 1.0f;
- //降分辨率
- public int downSample = 2;
- //迭代次数
- public int iteration = 1;
- void OnRenderImage(RenderTexture source, RenderTexture destination)
- {
- if (_Material)
- {
- //申请RenderTexture,RT的分辨率按照downSample降低
- RenderTexture rt1 = RenderTexture.GetTemporary(source.width >> downSample, source.height >> downSample, 0, source.format);
- RenderTexture rt2 = RenderTexture.GetTemporary(source.width >> downSample, source.height >> downSample, 0, source.format);
- //直接将原图拷贝到降分辨率的RT上
- Graphics.Blit(source, rt1);
- //进行迭代高斯模糊
- for(int i = 0; i < iteration; i++)
- {
- //第一次高斯模糊,设置offsets,竖向模糊
- _Material.SetVector("_offsets", new Vector4(0, BlurRadius, 0, 0));
- Graphics.Blit(rt1, rt2, _Material);
- //第二次高斯模糊,设置offsets,横向模糊
- _Material.SetVector("_offsets", new Vector4(BlurRadius, 0, 0, 0));
- Graphics.Blit(rt2, rt1, _Material);
- }
- //将结果输出
- Graphics.Blit(rt1, destination);
- //释放申请的两块RenderBuffer内容
- RenderTexture.ReleaseTemporary(rt1);
- RenderTexture.ReleaseTemporary(rt2);
- }
- }
- }
四.效果展示
Unity Shader-后处理:高斯模糊的更多相关文章
- Unity Shader后处理-搜索灰度效果
如U3D中Hierarchy面板下的搜索效果: 讲解分析: 1.这种PostEffect效果其实就是指Unity shader的后处理,即游戏中实现屏幕特效的常见方法.顾名思义屏幕后处理就是指在渲染完 ...
- Unity Shader入门精要学习笔记 - 第12章 屏幕后处理效果
建立一个基本的屏幕后处理脚本系统 屏幕后处理,顾名思义,通常指的是在渲染完整个场景得到屏幕图像后,再对这个图像进行一系列操作,实现各种屏幕特效.使用这种技术,可以为游戏画面添加更多艺术效果,例如景深. ...
- Unity shader学习之屏幕后期处理效果之高斯模糊
高斯模糊,见 百度百科. 也使用卷积来实现,每个卷积元素的公式为: 其中б是标准方差,一般取值为1. x和y分别对应当前位置到卷积中心的整数距离. 由于需要对高斯核中的权重进行归一化,即使所有权重相加 ...
- 【我的书】Unity Shader的书 — 文件夹(2015.12.21更新)
写在前面 感谢全部点进来看的朋友.没错.我眼下打算写一本关于Unity Shader的书. 出书的目的有以下几个: 总结我接触Unity Shader以来的历程,给其它人一个借鉴.我非常明确学Shad ...
- 【我的书】Unity Shader的书 — 目录(2016.5.19最后一次更新)
写在前面 感谢所有点进来看的朋友.没错,我目前打算写一本关于Unity Shader的书. 出书的目的有下面几个: 总结我接触Unity Shader以来的历程,给其他人一个借鉴.我非常明白学Shad ...
- Unity Shader 阶段性反思与总结(一)
Unity Shader 阶段性反思与总结(一) 最近在写Shader的时候,总是感觉力不从心,感觉自己已经看了蛮久的书了,也有一定的积累了,但是一想写什么效果,完完全全就是脑袋一团空白.典型的例子就 ...
- 【转】《Unity Shader入门精要》冯乐乐著 书中彩图
为方便个人手机学习时候查阅,从网上转来这些彩图. 如属过当行为,联系本人删除. 勘错表 http://candycat1992.github.io/unity_shaders_book/unity_s ...
- Unity Shader 知识点总结(二)
紧接着上一篇文章的shader入门知识的总结,本文主要总结shader中的纹理贴图.透明度混合.顶点动画.后期特效处理等操作.如果有什么地方有错,请指出更正,谢谢.本文的代码主要来自开源书:unity ...
- Unity Shader入门精要之 screen post-processing effect
本篇记录了学习Unity Shader入门精要的屏幕后处理的一些知识点. OnRenderImage(RenderTexture src, RenderTexture dest) 以上函数是Unity ...
- Unity Shader 入门精要学习 (冯乐乐 著)
第1篇 基础篇 第1章 欢迎来到Shader的世界 第2章 渲染流水线 第3章 Unity Shader 基础 第4章 学习Shader所需的数学基础 第2篇 初级篇 第5章 开始Unity Shad ...
随机推荐
- ajax相关知识点
AJAX的概念,即“Asynchronous Javascript And XML” 通过在后台(浏览器的后台)与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着可以在不重新加载整个 ...
- 红包外挂史及AccessibilityService分析与防御
最近在做一个有趣的外挂的小玩意,前提我们要了解一个重要的类AccessibilityService 转载请注明出处:https://lizhaoxuan.github.io 前言 提起Accessib ...
- java中一个Map要找到值Value最小的那个元素的方法
import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Map ...
- PHP获取数组最后一个元素的键和值
<?php /** * PHP获取数组中最后一个元素下标和值 */ $arr = ['1' => 'name', '3' => 2, 5 => 6, 'name' => ...
- pychrame更换默认以unittest执行或取消单元测试框架执行
选择某个测试框架运行脚本 File-> Settings -> Tools -> Python Integrated Tools -> Default test runner ...
- 步步为营-56-JQuery基础
jQuery本质还是封装好的js,只不过代码更简洁,而做的更好 使用JQuery选择器会返回一个jQuery对象,其本质是dom数组,jQuery对象可以调用JQuery方法. 1 选择器 1.1 基 ...
- Javascript中类的实现机制(四)
一: 理解类的实现机制 在JavaScript中可以使用function关键字来定义一个“类”,如何为类添加成员.在函数内通过this指针引用的变量或者方法都会成为类的成员,例如:function ...
- CentOS 用挂了dev/sda1:UNEXPECTED INCONSISTENCY;RUN fsck MANUALLY .
dev/sda1:UNEXPECTED INCONSISTENCY;RUN fsck MANUALLY .(i.e. ,without -a or -p options)fsck died with ...
- jquery数组(sort() 排序)
HTML: <h3>字符串数组排序前</h3> <div id="show5"></div> <h3>排序后</h ...
- Phone List HDU1671
字典树的包含与不包含关系 #include<bits/stdc++.h> using namespace std; ][]; ]; ; bool insert1( char *word ) ...