Unity 屏幕后处理及原理
后处理原理及过程
后处理是在渲染完后对图像进行处理,unity使用的是 C#
脚本
就是渲染完后不显示,多走一步,经由脚本处理后再显示到屏幕上,以实现诸如各种模糊效果、Bloom、描边等等
后处理一般过程
获取当前屏幕图像,利用C#
脚本调用shader
对图像进行处理,在将处理后的图像显示到屏幕上
原理
创建了一个同屏幕宽高完全一样的面,将之前的渲染结果作为渲染纹理传入脚本,调用shader
对纹理采样渲染回面片
所以在后处理时需要关闭深度写入等,防止渲染纹理覆盖了特殊情况下最后渲染的半透明物体
Unity提供了OnRenderImage()
函数获取屏幕图像
MonoBehaviour.OnRenderImage (RenderTexture src, RenderTexture dest)
1 | /*OnRenderImage中利用Graphics.Blit实现处理*/ |
Blit
函数获取屏幕图像后调用shader
,将源图像src
作为一张渲染纹理赋值给shader
中_MainTex
边缘检测(描边)
梯度的本意是一个向量(矢量),表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度的方向)变化最快,变化率最大(为该梯度的模)
二维空间下的偏微分方程
$$
\frac{∂f(x,y)}{∂x}=\lim_{\epsilon->0}\frac{f(x+\epsilon,y)-f(x,y)}{\epsilon}
$$
$$
\frac{∂f(x,y)}{∂y}=\lim_{\epsilon->0}\frac{f(x,y+\epsilon)-f(x,y)}{\epsilon}
$$
由于像素不是连续的,只要计算当前像素沿偏微分方向的差值,ε=1,所以只需进行简单的加减运算
在xy得到的值经过勾股定理后就得到,二维空间下灰度的变化率
边缘检测算子
注意:图中后两个算子是错的,xy方向反了!!!
一般不采用 Roberts 这样偶数的算子,因为结果对原像素存在偏移
Prewitt:$Gx = f(x+1) + 0 * f(x)-f(x-1)$,提取系数就是[-1, 0, 1]
1 | 所以该算子Gx就是: 同理Gy: |
Sobel就是prewitt
的基础上,加强了对直线上像素的检测
高斯模糊和 Bloom 效果
均值模糊
卷积核的各元素值相同,n*n
的核每个的值就是1/n^2
高斯模糊
高斯模糊的卷积核又叫高斯核
高斯模糊的名字来源于高斯分布(正态分布),其概率密度函数所表示的就是均值与样本值之间的关系,所以高斯模糊就是一种权值按距离减少的方法
$$
G(x,y)=\frac{1}{2\pi\sigma^2}e^{-\frac{x^2+y^2}{2\sigma^2}}
$$
$\mu$就是0,因为当前像素的原点距离为0,方差$\sigma$取标准方差1
n*n
的高斯核可以使用两个一维的高斯核替换
而且由于概率密度函数是对称的,所以存储上可以优化
1 | /*Shader*/ |
Bloom效果
步骤:提取图像中的亮部(像素的亮度可由rgb
通过一定比例的计算获得),对提取的亮部进行高斯模糊,混合原图和Bloom
luminance = 0.2125 * r + 0.7154 * g + 0.0721 * b
,可以看出绿色对亮度的贡献最大,红色次之,蓝色最小
运动模糊
方法:累计缓存(混合多张图像),速度缓存(按照像素的运动速度来模糊处理)
脚本
1 | /*一般格式*/ |