TiXL FastBlur 算子全解析:基于 Dual Kawase 双滤波的高质量快速模糊
2026/9/19 19:55:09 网站建设 项目流程
  • 音视频
  • 图形学
  • 桌面应用

【免费下载链接】t3

TiXL is an open source software to create realtime motion graphics.

项目地址:https://gitcode.com/GitHub_Trending/t3/t3
点击查看免费下载

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 对外只暴露两个输入(ImageMaxLevels),而 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 中):

  1. 降采样 + 模糊阶段(Downsample + blur):从原始分辨率开始,逐级向 1/2、1/4、1/8……分辨率渲染,每级执行一次 Kawase 风格的双线性 4-tap 降采样模糊。
  2. 上采样 + 模糊阶段(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):

宏值核类型采样数特点
15-tap 对角梅花形(diagonal quincunx)5中心 0.50 + 四对角各 0.125
29-tap 帐篷形(3×3,默认推荐)9中心 4/16、正交 2/16、对角 1/16
39-tap 类散景(中心 + 8 环)9能量集中在八角环上
413-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。其实际语义在底层执行节点_ExecuteFastBlurPassesResolveSteps方法中有更细致的定义(见 _ExecuteFastBlurPasses.cs):

  • MaxLevels > 0时,层级数被钳制在[1, 12]区间——这与文档中"最大为 12"一致;
  • MaxLevels = 0时启用自动模式:按floor(log2(min(宽, 高))) - 2自动计算层级数(例如 1080p 输入约得到 8 层),并同样钳制到[1, 12]。自动模式刻意保留余量,避免在 1×1 的尾部 mip 上浪费计算。

由此可以总结出 MaxLevels 的调参直觉:

  • 层级越多,模糊范围越大、光晕越柔和,同时渲染目标数量与上采样遍数也越多;
  • 层级越少,模糊越弱、开销越低,适合只需要轻微柔化或性能极度受限的场景;
  • 该参数只控制"模糊层级数"而非逐像素半径,这正是文档所说"只允许 radius 控制"的含义——但层级数在感知上等价于模糊半径的粗粒度调节。

3.2 输出

名称类型
ResultT3.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 的连接表)转发给子节点_ExecuteFastBlurPassesSymbolId: 46ce6fad-87fe-4d1f-b236-ae644dd1f76c),后者才是 Dual Kawase++ 的真正执行者。FastBlur.t3还表明它内建了一个线性采样器(LinearSampler,三轴寻址模式均为Clamp),因此 FastBlur 的采样不会越过图像边缘回绕。

4.2 GPU 执行内核(_ExecuteFastBlurPasses.cs)

_ExecuteFastBlurPasses.cs 是整条管线的心脏,其UpdateSafe方法按以下步骤驱动 GPU:

  1. 校验输入:任一必要资源(源纹理、SRV、顶点着色器、两个像素着色器、线性采样器)缺失即回退直通;
  2. 解析层级数:调用ResolveSteps确定实际金字塔深度(见上文 3.1);
  3. 按需重建资源InitializeOrUpdateResources以输入分辨率/格式为基准,创建全分辨率输出目标,以及steps个逐级减半(Math.Max(1, w/2))的中间渲染目标(RTV + SRV 成对创建),并在分辨率、格式或步数变化时自动重建、释放旧资源;
  4. 设置渲染状态:禁用混合与深度测试(DisabledBlendState/DisabledDepthStencilState),三角形列表拓扑,像素着色器阶段绑定线性采样器;
  5. 降采样循环for level = 0 .. steps-1,以DownParams{ InvSrcSize, OffsetPx=1.0 }为常量缓冲区参数运行FastBlur-DownsamplePS.hlsl,逐级写入减半目标;
  6. 上采样循环for level = steps-2 .. 0,每次以低一级的 SRV 为输入、当前级为输出运行FastBlur-UpsampleAcculuatePS.hlsl,并通过FillUpsampleKernel按阶段进度填充 9-tap 归一化权重;
  7. 最终合并:最后一级上采样直接写入全分辨率输出目标_fullResOutput,作为Result槽的值;
  8. 状态恢复:借助D3D11StateBackup保存/恢复拓扑、着色器、SRV、采样器、视口与混合状态,保证算子对渲染管线的侵入最小化,可安全嵌入任意后处理链。

值得注意的是,执行循环中的异常会被捕获并通过Log.Warning记录("Failed to execute Dual Kawase++ blur"),同时回退输出源纹理,体现了 TiXL 算子库对实时演出场景下"故障不黑屏"的稳健性设计。

五、实战使用建议

结合文档定位与源码行为,给出以下使用指引:

  1. 默认即最佳MaxLevels默认 5,对多数 1080p~4K 素材已能提供柔和的"高斯级"模糊。官方建议大多数场景无需调整该参数。
  2. 性能调优:若目标是移动端、VR 或高分辨率多实例渲染,可尝试将MaxLevels降到 3~4;层级每减少一级,金字塔尾部 1~2 遍全屏 pass 的开销随之消失。注意自动模式(0)已按log2(最小边) - 2预留了余量,属于保守选择。
  3. 特殊视觉塑造:提高层级数(上限 12)可获得更宽广、更电影感的光晕铺散;配合高亮输入(如先做 Threshold),可把 FastBlur 用作柔光、辉光或散景基底。
  4. 作为后处理链一环:FastBlur 输出与输入同格式同分辨率,且渲染状态被完整备份/恢复,可直接插入 Blur、Bloom、Sharpen 等后处理序列之间;需要方向性模糊时改用 DirectionalBlur。
  5. 对比选型:需要同时控制模糊半径、采样数、透明度、分辨率重定义或边缘回绕行为时,选用参数更丰富的 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.

项目地址:https://gitcode.com/GitHub_Trending/t3/t3
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询