原理
這個shader姑且是根據自己的理解寫的,如果有什么不對的評論區提醒一下咯,一般來說模糊和邊緣檢測這種效果是用卷積來實現的,可以通過使用不同的卷積核來獲得圖像的特征,模糊其實就是將計算的像素附近的像素乘上一定的權重加起來實現的效果,要保證這些權重的合為1,所以在計算出每個位置的權重后還要除以他們的平均值,用高斯函數的目的就是獲得一個合理的權重,根據二維高斯函數的公式
可以把x^2 + y^2視為采樣像素到中心像素的距離,所以代公式很容易可以得到二維高斯函數的值。
Shader "Hidden/Blurry"
{
Properties
{
_MainTex("Base (RGB)", 2D) = "white" {}
_Sigma("Sigma", Range(1.0, 5.0)) = 1.5
_BlurRadius("BlurRadius", Range(1.0, 5.0)) = 3.0
}
CGINCLUDE
#include "UnityCG.cginc"
struct v2f_blur
{
float4 pos : SV_POSITION; //頂點位置
float2 uv : TEXCOORD0; //紋理坐標
};
//用到的變量
sampler2D _MainTex;
float4 _MainTex_TexelSize;
//模糊半徑
float _BlurRadius;
// σ
float _Sigma;
//vertex shader
v2f_blur vert_blur(appdata_img v)
{
v2f_blur o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.texcoord.xy;
return o;
}
//fragment shader
fixed4 frag_blur(v2f_blur i) : SV_Target
{
fixed4 color = fixed4(0,0,0,0);
// 采樣的9個像素點的偏移量
float2 offsets[9] =
{
float2(-1, 1), float2(0, 1), float2(1, 1),
float2(-1, 0), float2(0, 0), float2(1, 0),
float2(-1, -1), float2(0, -1), float2(1, -1),
};
float pi = 3.1415; // 圓周率
float e = 2.7182; // 數學常數
float sum = 0;
float weight[9];
// 卷積
for (int j = 0; j < 9; j++)
{
float l = length(_BlurRadius * _MainTex_TexelSize * offsets[j]); // 求距離
float g = (1.0 / (2.0 * pi * pow(_Sigma, 2.0))) * pow(e, (-(l * l) / (2.0 * pow(_Sigma, 2.0)))); // 高斯函數值
weight[j] = g;
sum += g;
}
for (int j = 0; j < 9; j++)
weight[j] /= sum;
for (int j = 0; j < 9; j++)
{
color += tex2D(_MainTex, i.uv + _BlurRadius * _MainTex_TexelSize * offsets[j]) * weight[j];
}
return color;
}
ENDCG
SubShader
{
Pass
{
ZTest Always
Cull Off
ZWrite Off
Fog{ Mode Off }
CGPROGRAM
#pragma vertex vert_blur
#pragma fragment frag_blur
ENDCG
}
}
}
將這個Shader作為后處理的Shader使用,可以得到效果:
Unity使用后處理相關的代碼可以看這里