屏幕后处理效果
建立一个基本的屏幕后处理脚本系统
- 屏幕后处理,通常指的是在渲染完整个场景得到屏幕图像后,再对这个图像进行一系列操作,实现各种屏幕特效。可以为游戏画面添加更多的艺术效果,例如景深、运动模糊。
- 要实现屏幕后处理的基础在于得到渲染后的屏幕图像吗,即抓取平屏幕,Unity为我们提供了这样一个函数:
MonoBehaviour.OnRenderImage(RenderTexture src,RenderTexture dest) - 声明此函数后,unity会将屏幕图像存储在第一个参数对应的源渲染纹理中,通过函数一系列操作后,再把第二个参数对应的渲染纹理显示到屏幕上。
- 我们通常是利用Graphics.Blit函数来完成对渲染纹理的处理,函数的3中声明:
public static void Blit(Texture src,RenderTexture dest);
public static void Blit(Texture src,RenderTexture dest,Material mat,int pass = -1);
public static void Blit(Texture src,Material,int pass = -1); - src:原纹理,通常是当前屏幕的渲染纹理或者上一步处理后得到的渲染纹理。
- dst:目标渲染纹理,值为null就会直接渲染到屏幕上。
- mat:是我们使用的材质,这个材质使用的Unity Shader将会进行各种屏幕后处理操作,src会被传递给Shader中名为_MainTex的纹理属性。
- pass:默认为-1,表示会依次调用shader中的所有pass。否则调用指定索引的pass。
- 默认情况下,OnRenderImage会在所有透明、不透明物体渲染之后调用,以便渲染所有物体
- 通常后处理的步骤:
- 在摄像机中添加一个屏幕后处理脚本。
- 脚本中实现OnRenderImage函数来获取当前的屏幕渲染纹理。
- 调用Graphics.Blit函数使用特定的Unity Shader来对当前图像进行处理,再将返回的渲染纹理显示到屏幕上。
- 一些复杂的屏幕特效可能多次调用Graphics.Blit函数对上一步的输出结果进行下一次处理。
- 屏幕后处理之前,需要进行检查。例如当前平台是否支持纹理渲染和屏幕特效,或者是否支持使用Unity Shader。因此我们要创建一个用于屏幕后处理效果的基类。
边缘检测
- 边缘检测的原理是利用一些边缘检测算子对图像进行卷积操作。
- 图像处理中,卷积操作指的就是使用一个卷积核对一张图像中的每个像素进行一系列操作。卷积核通常是一个四方形网格结构,该区域每个方格都有一个权重值。当对图像中某个像素进行卷积时,我们会把卷积核的中心放置于这个像素上,翻转核之后再依次计算核中每个元素和其覆盖的图像像素值的乘积并求和,得到的结果就是该位置的新像素值。
常见的边缘检测算子
- 用于边缘检测的卷积核也被称为边缘检测算子。
- 如果相邻像素之间存在差别明显的颜色、亮度、纹理等属性,我们就会认为它们之间应该有一条边界。这种相邻像素之间的插值可以用梯度来表示。
- 它们都包含了两个方向的卷积核,分别用于检测水平方向和竖直方向上的边缘信息。在进行边缘检测时,我们需要对每个像素进行一次卷积计算,得到两个方向上的梯度值Gx和Gy,而整体的梯度按照下面公式计算:
高斯模糊
- 卷积的另一个常见应用就是高斯模糊。模糊实现的方法有很多,例如均值模糊和中值模糊。
- 均值模糊:卷积核中的各个元素都相等,并且相加等于1,也就是卷积后的像素值是其邻域内像素值得和。
- 中值模糊:选择邻域内对所有像素排序后的中值替换原颜色。
- 高斯模糊是一个更高级的模糊方法。
高斯滤波
- 高斯模糊使用的卷积核名为高斯核。
- 高斯核是一个正方形大小的滤波核,其中每个元素都基于下面的高斯方程:
- σ是标准方差(一般取1)
- x和y分别对应了当前位置到卷积核中心的整数距离。
- 我们需要对高斯核中的权重进行归一化,这样图像才不会变暗。因此e前面的系数不会对实际结果有任何影响。
- 高斯方程很好地模拟了邻域每个像素对当前像素的影响程度——距离越近,影响越大。高斯核的维数越高,模糊程度越大。使用NxN的高斯核,就需要NxNxWxH(W和H为图像的宽和高)次纹理采样。
- 但我们可以把二维的高斯核拆成两个一维的高斯核,得到的结果是一样的,采样次数大大减少。
- 我们会使用先后两个Pass,第一个Pass将会使用竖直方向的一维高斯核对图像进行滤波,第二个Pass再使用水平方向的一维高斯核对图像进行滤波,得到最终的目标图像。
- 在实现中,我们还将利用图像缩放进一步提高性能,并通过高斯滤波的应用次数来控制模糊程度。(次数越多图像越模糊)
Bloom效果
- 游戏中一种常见特效
- 模拟真实摄像机的一种图像效果,让画面中比较亮的区域“扩散”到周围的区域中,造成朦胧的效果。
- 原理:首先根据一个阈值提取出图像中的较亮区域,把它们存储在一张渲染纹理中,利用高斯模糊对这张渲染纹理进行模糊处理,模拟光线的扩散效果,最后将其与原图混合,得到最终效果。
运动模糊
- 模拟真实世界中的摄像机的一种效果。如果在摄像机曝光时,拍摄场景发生了变化,就会产生模糊画面。
- 运动模糊效果可以让物体运动看起来更加真实平滑。
- 运动模糊有多种实现方法:
- 一种实现方法是利用一块累计缓存来混合多张连续的图像。物体快速移动产生多张图像后,我们取它们之间的平均值作为最后的运动模糊图像。缺点是性能消耗大,想要获取多张帧图像意味着需要在同一帧里渲染多次场景。
- 另一种广泛的方法是使用速度缓存,这个缓存中存储了各个像素当前的运动速度,然后利用该值来决定模糊的方向和大小。