URP | 后处理-模糊算法总结
内容偏多

目的
URP管线下怎么计算后期模糊效果。
模糊算法的学习使用。
都有那些模糊算法,都有哪些优点。
模糊介绍
目前看到大佬总结的十种模糊的方式,实现经常使用的几种。
高品质后处理:十种图像模糊算法的总结与实现 - 知乎 (zhihu.com)
主要模糊方式
10种模糊方式对比

性能测试
不同模糊性能对比。

思路
URP后处理主要有4部分组成

主要是由3个文件组成,
Shader文件
Volume 脚本
这个是暴露给后处理使用的脚本、
RenderFeature 脚本
这个脚本主要包含 RenderFeature模块和 ScriptableRenderPass模块 俩部分。主要是处理渲染逻辑的。

Gaussian Blur | 高斯模糊
高斯模糊主要分为横模糊和纵模糊,俩次模糊以后就可以得到结果了。
对图像处理的矩阵称之为高斯核(Gaussian Kernel)

详细 参考
高品质后处理:十种图像模糊算法的总结与实现 - 知乎 (zhihu.com)
Shader处理
创建一个Shader,在创建一个函数库,命名Blur.hlsl

Shader内导入函数库就可以了,
函数库里增加计算
定义我们的片元着色器(Gaussianfrag),
注意:因为我们要制作不同的模糊效果使用一个hlsl.函数库,调用不同的片元着色器,执行不同的效果。
扩展 卷积核是什么?
三分钟彻底理解图像高斯模糊 - 知乎 (zhihu.com)
卷积究竟卷了啥?——17分钟了解什么是卷积_哔哩哔哩_bilibili
游戏 Bloom 实现方法 - 哔哩哔哩 (bilibili.com)
Volume
创建一个脚本在后处理里控制属性
后处理效果

RendererFeature 类
创建一个脚本,命名 GaussianBlurRenderFeature
RenderFeature是处理渲染逻辑,设置Shader
设置渲染事件
同步渲染事件
执行函数,传入Volume,传入Command
渲染Render函数,后处理逻辑。
公开设置
外部可以设置渲染层级,指定Shader,
URP | 后处理-自定义后处理 - 哔哩哔哩 (bilibili.com)
定义Pass我们创建的Pass 开始同步渲染方式。
PASS部分
渲染事件
我们开始处理Pass阶段的渲染内容,
创建一个类, 创建构造函数。
就是上面调用的构造函数设置的层级和Shader
我们现在定义一些变量,比如Shader的材质,控制模糊的变量等。
我们回到到构造函数,判断Shader是否为什么空,如果不为空创建一个材质。
初始化渲染
定义一个Setup函数 ,初始化渲染目标
回到RendererFeature 初始化
初始化完成,
执行
主要是判断 材质,摄像机, 组件是否准备好,准备好执行渲染。
注意:这里的 Render 函数还没有定义
接下来定义渲染部分。
渲染
渲染
执行渲染渲染计算,
注意:GetTemporaryRT 是括号括号括号,这样处理是为了看的清楚。
计算完,传入材质
我们使用 BlurTimes 控制迭代次数。
扩展 Blit 函数的使用用法、
这个表示 后面是表示使用的Shader中第几个Pass 。
Blit函数的使用
官方函数介绍

最简单的作用就是把一张纹理绘制到另一张纹理中,可以使用材质对纹理进行处理。
效果
处理效果

注意:迭代次数越多越费。
代码
shader
hlsl
Volume
Feature

Box Blur | 方框模糊
Box模糊和 上面的 高斯模糊差不多,

主要是他们的计算 高斯核不一样。
注意:方框模型和高斯模糊都使用同样的渲染管线就可以,只需要修改Shader就可以,他们指定不同的Shader就可以。

Shader
Shader阶段需要注意的是,定义新的片元着色器,指定我们调用的函数库的位置。

调用 Box Frag 片元着色器
hlsl
主要是定义一个新的 片元着色器,命名— Box Frag.
扩展 俩种模糊方式的对比效果。
方框模糊
Blur Times 6 Blur Range 2 RT Down Sampling 3

高斯模糊

第二步 实现同样类似的模糊,看俩种模糊的算法对比。
这是俩种差不多的模糊,


总结:方框模糊比高斯模糊迭代次数少, 优点就是比高斯模糊省。

Kawase Blur
Kawase Blur于Masaki Kawase 在GDC2003的分享《Frame Buffer Postprocessing Effects in DOUBLE-S.T.E.A.L (Wreckless)》中提出。
Kawase Blur最初用于Bloom后处理特效,但其可以推广作为专门的模糊算法使用,且在模糊外观表现上与高斯模糊非常接近。
Kawase Blur的思路是对距离当前像素越来越远的地方对四个角进行采样,且在两个大小相等的纹理之间进行乒乓式的blit。
创新点在于,采用了随迭代次数移动的blur kernel,而不是类似高斯模糊,或box blur一样从头到尾固定的blur kernel。

优点:Kawase Blur比经过优化的高斯模糊的性能约快1.5倍到3倍。
Shader
我们前在blur.hlsl计算片元着色器
对像素斜四角像素进行采样,然后取平均值。
注意:第一个是主像素的位置,剩下4个是4个点的像素。
Shader
RenderFeature 类
我们前创建渲染流程
这个阶段是把 destination的效果输出到屏幕,降采样和 模糊起作用了,我接下来处理核心代码。
创建2个RT 我们需要来回切换。
这个阶段主要是注意,2个RT来回切换。
在模糊迭代开始,材质我们需要使用迭代次数来控制模糊次数

来回Blit处理

当前迭代次数,对每次模糊的半径进行设置

效果

属性数值

这样迭代2次就有一个不错的模糊效果。
KawaseBulrRenderFeature

Dual Kawase Blur | 双重模糊
上面这些模糊算法我们可以看出,一旦模糊距离增大,必须得加大迭代次数来消除方格感。
Dual Blur 是利用降采样和升采样,解决方格感,还有Dual Blur方式在顶点着色器阶段对UV进偏移。这样可以减少计算量。
一个降采样,一个升采样。


Shader
Shader部分,我们是使用俩个Pass完成,
为了带来更好的性能表现,可以将uv的偏移放在Vert Shader中进行,而Fragment Shader中基本上仅进行采样即可。
DualKawaseBlur.hlsl
需要重新定义顶点结构体,
我们准备俩个输出结构体,一个降采样,一个升采样。
降采样 第一个UV 一个是定义 5 的数组
升采样 第二个UV需要定义8个的 数组。

降采样
顶点着色器是对UV进行偏移。
升采样
顶点着色器
Shader部分
定义2个Pass
RendererFeature 类
因为我们都是使用的一个 Volume,所以我们调用同一个 组件,
这里只是 设置好渲染内容,
我们要定义 Pass 设置渲染逻辑
Pass
Render
这个部分是我们的算法核心,
渲染效果


全代码
扩展 RT是什么?
URP源码学习(七)一些细节和理解 - 知乎 (zhihu.com)
首先rt是一张特殊贴图,这张贴图对应的是GPU上的FrameBuffer.
FrameBuffer 缓存区储存2种缓存
颜色缓存,
深度缓存

到这里4种模糊算法算完事,
扩展:怎么查看Frame Debug
我们看到渲染结果,

这个是原图要输出的显示效果,
这个是没有增加后处理的原图备份。

这些是计算模糊的过程阶段图。

最后输出到屏幕处理结果图。

总结
高速模糊最简单,Box模型也只是在Shader阶段进行处理,最复杂的是 Dual 和Kawase 模糊方式, 相对Dual 性能更好。
从细节梳理了后处理渲染流程,创建成模板,好维护处理。
对RT的类整理学习,经常使用的类型
Blit 函数
一个纹理复制到另一个纹理。

GetTemporaryRT
设置RT的属性

RenderTargetIdentifier
临时纹理的一些属性

RenderTextureDescriptor
RT的一个类包含RT的所有属性

资料
URP Gaussian/Box/Kawase/Dual Blur 实现 - 知乎 (zhihu.com)
Unity URP DualKawaseBlur TA (tajourney.games)
高品质后处理:十种图像模糊算法的总结与实现 - 知乎 (zhihu.com)
【Free Bird/URP教学】7.URP后处理--高斯模糊 - 知乎 (zhihu.com)
【Unity ShaderGraph UI模糊特效教程】_哔哩哔哩_bilibili