- 音视频
- 图形学
- 桌面应用
【免费下载链接】t3
TiXL is an open source software to create realtime motion graphics.
FastBlur 是 TiXL 实时运动图形引擎(Lib.image.fx.blur 算子库)中面向性能优先场景的模糊算子,它基于 Marius Bjørge / Masaki Kawase 的双滤波(dual-filtering)方法,通过递归降采样与上采样实现近似高斯平滑的散景光散射效果。本文将从算子用法、输入参数、算法原理到 HLSL 着色器与 C# 执行内核的源码级实现,全面解读 FastBlur 的工作机制,帮助你在后处理管线中正确选型、调参并理解其性能收益。
一、FastBlur 是什么:与 Blur 算子的定位差异
在 TiXL 的Lib.image.fx.blur类别中,官方文档对 FastBlur 的定位非常明确:"Provides better quality and much faster speed that the Blur but does only allow radius control."(相比 Blur,它在提供更好质量与更快速度的同时,只允许控制模糊层级半径。)
这一描述揭示了两个核心定位:
- 速度与质量优先:传统 Blur 算子通过
Size(模糊半径)、Samples(迭代次数)等多个参数组合来控制模糊强度,质量随采样数线性上升、开销也随之上升;FastBlur 则用固定的金字塔式多级滤波换取"高斯级"平滑度,其开销与模糊强度基本解耦,强度越高优势越明显。 - 接口极简:FastBlur 对外只暴露两个输入(
Image与MaxLevels),而 Blur 算子则有 Size、Samples、Offset、Opacity、Resolution、Wrap 六个可调参数。FastBlur 的"少参数"正是其算法特征的外在表现——模糊强度由金字塔层级数决定,而非由逐像素采样半径决定。
同类别中还包含 Bloom(更通用快速的辉光)、DirectionalBlur(方向性模糊)与 Sharpen(锐化),完整算子清单见 Lib.image.fx.blur 类别索引。
二、算法原理:Marius Bjørge / Masaki Kawase 双滤波方法
FastBlur 的技术核心是业界著名的Dual Kawase(Kawase++)模糊方案,它源自 Marius Bjørge 的 Dual Filtering 演讲与 Masaki Kawase 的 Kawase Blur(RenderTargets 技术报告)。官方文档概括其流程为:
通过递归降采样(recursively downsampling)然后上采样(upsampling)图像,并使用 9-tap 帐篷形核(tent kernel),产生电影感的、高质量的光散射(light scatter);针对移动端与 VR 级别性能做了优化,同时提供"高斯级别"的平滑度。
其核心思想是:在图像金字塔的每一层执行一次固定开销的小核模糊,降采样到底后再逐层上采样合并。由于每一层处理的是上一层的半分辨率图像,最终等效模糊半径随层级数指数增长,而每层像素着色器成本恒定(仅 4~9 次纹理采样),因此"模糊范围越大,相对普通逐像素大半径模糊越划算"。
从仓库实现看,这一流程被拆解为两个阶段(实现在 _ExecuteFastBlurPasses.cs 中):
- 降采样 + 模糊阶段(Downsample + blur):从原始分辨率开始,逐级向 1/2、1/4、1/8……分辨率渲染,每级执行一次 Kawase 风格的双线性 4-tap 降采样模糊。
- 上采样 + 模糊阶段(Upsample + blur):从最小的一级开始,逐级向更高分辨率回写,每级执行一次 9-tap 帐篷形核模糊,最终把结果合并回原始分辨率输出。
整个渲染使用一个全屏三角形(3 个顶点)完成,顶点着色器见 FastBlur-FullscreenVS.hlsl(SV_VertexID直接推导 UV,无顶点缓冲)。
2.1 降采样阶段:Kawase 风格 4-tap 模糊
FastBlur-DownsamplePS.hlsl 实现了经典 Kawase 双线性 4-tap:
float4 c = Src.SampleLevel(LinearSampler, i.uv + float2(-d.x, -d.y), 0) + Src.SampleLevel(LinearSampler, i.uv + float2( d.x, -d.y), 0) + Src.SampleLevel(LinearSampler, i.uv + float2(-d.x, d.y), 0) + Src.SampleLevel(LinearSampler, i.uv + float2( d.x, d.y), 0); return c * 0.25f; // weights sum to 1注释明确标注"DC gain = 1.0"(直流增益为 1,即整体亮度不因滤波而偏移),d = InvSrcSize * OffsetPx,其中OffsetPx在 C# 执行内核中被设为 1.0 像素(见 _ExecuteFastBlurPasses.cs)。每个采样点利用线性过滤的硬件双线性插值,实际覆盖了比 4 个点更广的邻域,是 Kawase 方案"低采样数、宽覆盖"的关键技巧。
2.2 上采样阶段:9-tap 帐篷形核
FastBlur-UpsampleAcculuatePS.hlsl 实现了 9-tap tent 形核:1 个中心采样 + 4 个正交(cardinal)采样 + 4 个对角(diagonal)采样,权重通过常量缓冲区WCenter / WCard / WDiag传入,且保证归一化(权重和为 1)。
这些权重并非固定值,而是由 C# 端FillUpsampleKernel方法按"阶段进度"动态插值生成(见 _ExecuteFastBlurPasses.cs):
- 宽(wide)核:
center=2, card=2, diag=2—— 从深层 mip 向上采样时,能量分布均匀,用于铺开大面积光晕; - 紧(tight)核:
center=8, card=2, diag=1—— 接近最终全分辨率时,中心权重显著提高,保留细节轮廓。
用t = stageIndex / (stageCount - 1)(0 表示最深 mip,1 表示最终上采样)在宽、紧两组权重之间线性插值,再做归一化。这正对应文档所说的"cinematic, high-quality light scatter":浅层铺光、深层收边,从而在强模糊下仍保持物体边缘的识别度。
2.3 附加说明:FastBlur-BlurPS.hlsl 的可切换核
仓库的 FastBlur-BlurPS.hlsl 提供了一套单遍 2D 模糊着色器,通过编译期宏FASTBLUR_KERNEL切换 4 种核(默认FASTBLUR_KERNEL 1):
| 宏值 | 核类型 | 采样数 | 特点 |
|---|---|---|---|
| 1 | 5-tap 对角梅花形(diagonal quincunx) | 5 | 中心 0.50 + 四对角各 0.125 |
| 2 | 9-tap 帐篷形(3×3,默认推荐) | 9 | 中心 4/16、正交 2/16、对角 1/16 |
| 3 | 9-tap 类散景(中心 + 8 环) | 9 | 能量集中在八角环上 |
| 4 | 13-tap 类散景(中心 + 内 6 环 + 外 6 环) | 13 | 六边形光圈感,外环半径 1.5× |
该文件同时还通过Clamp01常量控制是否对结果做saturate钳制,并支持以RadiusPx指定当前层级像素空间的半径。可以看出 FastBlur 体系把"核形状"作为可扩展的设计维度,而 FastBlur 算子当前默认走 9-tap tent 的 Dual Kawase++ 路线。
三、输入参数详解
FastBlur 仅有两个输入参数,官方文档的参数表如下,并结合源码补充实现细节:
| 名称(相关性与类型) | 说明 |
|---|---|
| Image(Texture2D,必需) | 待模糊的输入纹理。在 TiXL 中通过节点图连接任意Texture2D输出即可。 |
| MaxLevels(Int32) | 应用的模糊层级数量,最大为 12(对大多数分辨率已足够)。大多数场景无需调整;在边缘场景中,调整它有助于优化性能或塑造特殊外观。 |
3.1 MaxLevels 的默认值与取值语义
从算子定义文件 FastBlur.t3 可以看到,MaxLevels的默认值为 5。其实际语义在底层执行节点_ExecuteFastBlurPasses的ResolveSteps方法中有更细致的定义(见 _ExecuteFastBlurPasses.cs):
- 当
MaxLevels > 0时,层级数被钳制在[1, 12]区间——这与文档中"最大为 12"一致; - 当
MaxLevels = 0时启用自动模式:按floor(log2(min(宽, 高))) - 2自动计算层级数(例如 1080p 输入约得到 8 层),并同样钳制到[1, 12]。自动模式刻意保留余量,避免在 1×1 的尾部 mip 上浪费计算。
由此可以总结出 MaxLevels 的调参直觉:
- 层级越多,模糊范围越大、光晕越柔和,同时渲染目标数量与上采样遍数也越多;
- 层级越少,模糊越弱、开销越低,适合只需要轻微柔化或性能极度受限的场景;
- 该参数只控制"模糊层级数"而非逐像素半径,这正是文档所说"只允许 radius 控制"的含义——但层级数在感知上等价于模糊半径的粗粒度调节。
3.2 输出
| 名称 | 类型 |
|---|---|
| Result | T3.Core.DataTypes.Texture2D |
输出为与输入同分辨率、同格式的模糊结果纹理。从 FastBlur.cs 可见,输出槽Result直接连接到底层_ExecuteFastBlurPasses的输出纹理。若输入为空或资源创建失败,执行内核会回退输出原始输入纹理(pass-through),保证节点图不会因异常而中断(见 _ExecuteFastBlurPasses.cs)。
四、源码级实现:从算子声明到 GPU 执行
4.1 算子外壳(FastBlur.cs)
FastBlur.cs 采用 TiXL 标准的声明式算子写法:
namespace Lib.image.fx.blur; [Guid("1112d3ea-fef0-4d7c-a265-a067030256a1")] internal sealed class FastBlur : Instance<FastBlur> { [Output(Guid = "e0a77e1e-d60f-4e37-987d-80fba2468497")] public readonly Slot<T3.Core.DataTypes.Texture2D> Result = new(); [Input(Guid = "c1a630e8-2d0b-412d-b2c2-c26e79befae2")] public readonly InputSlot<T3.Core.DataTypes.Texture2D> Image = new(); [Input(Guid = "01d8a4a8-56ca-4e6d-a6c9-8092e4153963")] public readonly InputSlot<int> MaxLevels = new(); }可见算子本身不包含任何渲染逻辑,所有输入通过节点图(见 FastBlur.t3 的连接表)转发给子节点_ExecuteFastBlurPasses(SymbolId: 46ce6fad-87fe-4d1f-b236-ae644dd1f76c),后者才是 Dual Kawase++ 的真正执行者。FastBlur.t3还表明它内建了一个线性采样器(LinearSampler,三轴寻址模式均为Clamp),因此 FastBlur 的采样不会越过图像边缘回绕。
4.2 GPU 执行内核(_ExecuteFastBlurPasses.cs)
_ExecuteFastBlurPasses.cs 是整条管线的心脏,其UpdateSafe方法按以下步骤驱动 GPU:
- 校验输入:任一必要资源(源纹理、SRV、顶点着色器、两个像素着色器、线性采样器)缺失即回退直通;
- 解析层级数:调用
ResolveSteps确定实际金字塔深度(见上文 3.1); - 按需重建资源:
InitializeOrUpdateResources以输入分辨率/格式为基准,创建全分辨率输出目标,以及steps个逐级减半(Math.Max(1, w/2))的中间渲染目标(RTV + SRV 成对创建),并在分辨率、格式或步数变化时自动重建、释放旧资源; - 设置渲染状态:禁用混合与深度测试(
DisabledBlendState/DisabledDepthStencilState),三角形列表拓扑,像素着色器阶段绑定线性采样器; - 降采样循环:
for level = 0 .. steps-1,以DownParams{ InvSrcSize, OffsetPx=1.0 }为常量缓冲区参数运行FastBlur-DownsamplePS.hlsl,逐级写入减半目标; - 上采样循环:
for level = steps-2 .. 0,每次以低一级的 SRV 为输入、当前级为输出运行FastBlur-UpsampleAcculuatePS.hlsl,并通过FillUpsampleKernel按阶段进度填充 9-tap 归一化权重; - 最终合并:最后一级上采样直接写入全分辨率输出目标
_fullResOutput,作为Result槽的值; - 状态恢复:借助
D3D11StateBackup保存/恢复拓扑、着色器、SRV、采样器、视口与混合状态,保证算子对渲染管线的侵入最小化,可安全嵌入任意后处理链。
值得注意的是,执行循环中的异常会被捕获并通过Log.Warning记录("Failed to execute Dual Kawase++ blur"),同时回退输出源纹理,体现了 TiXL 算子库对实时演出场景下"故障不黑屏"的稳健性设计。
五、实战使用建议
结合文档定位与源码行为,给出以下使用指引:
- 默认即最佳:
MaxLevels默认 5,对多数 1080p~4K 素材已能提供柔和的"高斯级"模糊。官方建议大多数场景无需调整该参数。 - 性能调优:若目标是移动端、VR 或高分辨率多实例渲染,可尝试将
MaxLevels降到 3~4;层级每减少一级,金字塔尾部 1~2 遍全屏 pass 的开销随之消失。注意自动模式(0)已按log2(最小边) - 2预留了余量,属于保守选择。 - 特殊视觉塑造:提高层级数(上限 12)可获得更宽广、更电影感的光晕铺散;配合高亮输入(如先做 Threshold),可把 FastBlur 用作柔光、辉光或散景基底。
- 作为后处理链一环:FastBlur 输出与输入同格式同分辨率,且渲染状态被完整备份/恢复,可直接插入 Blur、Bloom、Sharpen 等后处理序列之间;需要方向性模糊时改用 DirectionalBlur。
- 对比选型:需要同时控制模糊半径、采样数、透明度、分辨率重定义或边缘回绕行为时,选用参数更丰富的 Blur;只关心"又快又好的模糊"且可接受粗粒度强度控制时,FastBlur 是更优解。
六、参考资源
- 算子文档:FastBlur 官方文档、Lib.image.fx.blur 类别索引、Blur 算子文档
- 算子定义:FastBlur.cs、FastBlur.t3 节点图配置
- 执行内核:Dual Kawase++ 执行实现 _ExecuteFastBlurPasses.cs
- 着色器源码:降采样 4-tap 模糊、上采样 9-tap 帐篷核、可切换核模糊、全屏三角形顶点着色器
- 音视频
- 图形学
- 桌面应用
【免费下载链接】t3
TiXL is an open source software to create realtime motion graphics.
相关推荐
TiXL 图像模糊效果算子完全指南:Lib.image.fx.blur 家族(Blur、FastBlur、DirectionalBlur、Bloom、Sharpen)
TiXL 图像模糊效果算子完全指南:Lib.image.fx.blur 家族(Blur、FastBlur、DirectionalBlur、Bloom、Sharp
音视频图形学桌面应用Playdoh模板系统入门:构建响应式Web界面的实用教程
Playdoh模板系统入门:构建响应式Web界面的实用教程 Playdoh是Mozilla开发的Web应用基础模板,融合了Django框架的强大功能与现代Web
音视频图形学桌面应用TiXL 图像分析算子 WaveForm 完全指南:波形示波器与矢量示波器叠加可视化
TiXL 图像分析算子 WaveForm 完全指南:波形示波器与矢量示波器叠加可视化 WaveForm 是 TiXL(Lib.image.analyze 库)中
音视频图形学桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考