12-tessellation
第 12 篇:曲面细分(Tessellation)
原文:Part 12
一句话定位
硬件曲面细分把“如何决定细分密度”“如何生成参数域拓扑”“如何把参数点映射到真实表面”拆给 HS/TCS、固定功能 Tessellator 和 DS/TES 三段。
Patch 管线
flowchart LR
P[输入 Patch 控制点] --> H[Hull / Tessellation Control Shader]
H --> F[细分因子与 Patch 常量]
F --> T[固定功能 Tessellator<br/>生成参数坐标与连接关系]
H --> D[Domain / Tessellation Evaluation Shader]
T --> D
D --> O[细分后的顶点]
O --> G[可选 GS / Rasterization]
固定功能 tessellator 不理解 Bézier、B-spline 或位移贴图的具体曲面公式;它根据 outer/inner tessellation factors 和 domain/topology 生成参数域中的点及连接关系。DS/TES 再结合控制点和 patch 常量,求出最终位置与属性。
为什么这样拆分
- 细分拓扑生成包含许多严格边界规则,固定功能能以较小面积和高吞吐实现一致结果。
- 曲面求值高度可编程,交给通用 shader 更灵活。
- Patch 常量只需每个 patch 计算一次,可与每控制点工作分离。
这是一种典型 GPU 设计:把规则稳定、数据量大的机械工作专用化,把算法多变部分留给可编程核心。
细分因子与裂缝
相邻 patch 的共享边若使用不同细分级别,生成的边界顶点不一致,就可能出现裂缝。应用通常要保证共享边因子一致,或采用能衔接不同 LOD 的方案。fractional spacing 等模式使连续变化更平滑,但并不自动解决所有跨 patch 一致性问题。
极高细分因子会迅速放大顶点数量,随后 DS、GS、光栅化和属性带宽都可能成为瓶颈。动态 LOD 的目标不是“尽量细”,而是在屏幕误差、位移细节和成本之间平衡。
缓冲与调度
一个 patch 的输出数量取决于细分因子,因而与 GS 类似存在可变放大。硬件可分块生成参数点并调度 DS,不必把整个巨大 patch 一次性物化;但中间队列、顺序与后续 primitive assembly 仍需协作。
术语对照
| D3D 术语 | OpenGL/Vulkan 术语 | 中文理解 |
|---|---|---|
| Hull Shader (HS) | Tessellation Control Shader (TCS) | 处理控制点并给出细分因子/patch 常量 |
| Tessellator | Tessellator | 固定功能参数域细分器 |
| Domain Shader (DS) | Tessellation Evaluation Shader (TES) | 求值每个生成点的最终属性 |
| patch | patch | 一组控制点构成的输入图元 |
| tessellation factor | 细分因子 | 控制边界与内部密度 |
| domain | 参数域 | triangle/quad/isoline 等 |
面向 UMD/KMD 的阅读提示
- 编译器区分 per-vertex output 与 per-patch output,匹配 HS/TCS 和 DS/TES 的接口布局。
- UMD 配置 patch control points、domain、partition/spacing、output topology 及阶段间 ring。
- 注意 API 的细分因子范围、舍入和特殊值规则;驱动可能需要 clamp 或 lowering。
- KMD 一般看不到 patch 语义,只维护相关代码、状态和中间缓冲的地址与执行。
自测与实验
- 为什么固定功能 tessellator 输出参数坐标,而不是直接输出曲面上的三维坐标?
- 相邻 patch 共享边因子不一致时,裂缝从何而来?
- 逐步提高细分因子,观察瓶颈如何从 HS/TCS 转向 DS/TES、设置或像素端。
本篇总结
曲面细分是“可编程决策 + 固定功能拓扑生成 + 可编程求值”的协作流水线,理解职责边界比记阶段名称更重要。

浙公网安备 33010602011771号