05-primitive-assembly-clipping-viewport

第 5 篇:图元装配、裁剪、投影与视口变换

原文:Part 5

一句话定位

顶点着色完成后,硬件先把顶点组成完整图元,再用齐次裁剪、剔除、透视除法和视口变换,把图元变成适合屏幕空间光栅化的形式。

数据路径

VS 输出
  → 按拓扑装配点/线/三角形
  → 面朝向与用户/视锥剔除
  → 必要时做齐次裁剪并生成新顶点
  → 透视除法 (x,y,z)/w
  → 视口与深度范围变换
  → 屏幕空间图元

实际次序可因优化而调整,但任何调整都必须保持 API 可观察结果。

图元装配

PA 根据 primitive topology 和索引关系读取完整图元。点需要一个顶点、线两个、三角形三个,strip/fan 还要处理复用和绕序。这里体现了为什么 VS 结果要保留足够的标签或顺序信息:着色可乱序完成,图元关系不能丢。

剔除与裁剪不是一回事

  • 剔除(cull):整个图元无需继续处理,例如背面剔除或完全落在同一裁剪平面外。
  • 裁剪(clip):图元与边界相交,需要计算交点并生成一个或多个新图元。
  • 视口/裁剪矩形测试可以提前拒绝明显不可能贡献像素的图元,但不能改变规范要求的覆盖结果。

裁剪比拒绝昂贵,因为它会产生新顶点并插值属性。Guard band 的思路是扩大硬件可安全表示的屏幕区域:大多数越出视口但仍在 guard band 内的图元不必真正裁剪,留给后续视口/剪裁测试拒绝即可;只有超出安全数值范围且仍可能影响视口的图元才进入裁剪器。

齐次空间为什么重要

在透视除法前,裁剪条件可写成关于 x, y, z, w 的线性不等式。先在齐次空间裁剪,再除以 w,能正确处理穿过近裁剪面的图元。若先除法,w 接近零或符号变化会带来巨大坐标和错误拓扑。

裁剪器最难的不是公式本身,而是一致性:共享边必须按完全兼容的规则产生相同交点,否则相邻三角形可能出现裂缝。有限精度、平面顺序、交点方向和舍入选择都可能影响水密性。

透视除法与视口变换

顶点从 clip space 经过 (x/w, y/w, z/w) 到 NDC,再按 viewport 的缩放与偏移映射到屏幕坐标和深度范围。这里的 w 还会在后续透视正确插值中出现,因此不要把它只看作“做一次除法后就丢弃的分量”。

术语对照

英文 中文 区分
primitive assembly 图元装配 按拓扑组合顶点
culling 剔除 整体丢弃,不生成新图元
clipping 裁剪 与边界求交,可能生成新顶点
guard band 保护带 减少真正裁剪次数的扩大区域
clip space 裁剪空间/齐次裁剪空间 透视除法之前
NDC 规范化设备坐标 透视除法之后
viewport transform 视口变换 NDC 到屏幕/深度范围

面向 UMD/KMD 的阅读提示

  • UMD 需要把 front-face、cull mode、clip depth convention、viewport 和 scissor 编进状态。
  • 查找硬件不原生支持某种裁剪语义时,驱动是否插入 shader lowering 或额外 pass。
  • 关注 Vulkan/OpenGL/D3D 在 NDC 的 Y 方向、深度范围和坐标约定上的差异由哪层消解。
  • KMD 基本不理解几何语义;若在 KMD 中寻找裁剪算法,通常找错层了。

自测

  • 为什么“完全在视口外”通常可直接拒绝,而“跨过近裁剪面”不能只依赖 scissor?
  • 为什么相邻三角形分别裁剪时必须保证公共边生成同一个交点?
  • API 坐标约定与硬件原生约定不同时,可由矩阵、viewport 状态或 shader 修正;各方案会影响哪些状态?

本篇总结

这一段流水线的任务是把“合法的齐次几何”稳健地变成“数值范围可控、拓扑一致、可做屏幕覆盖测试的图元”。

posted @ 2026-10-26 21:57  Sailxiv  阅读(3)  评论(0)    收藏  举报