2.4 帧缓冲输出:逐片元测试与混合


2.4 帧缓冲输出:逐片元测试与混合

本节摘要:片元着色器输出颜色后,还要依次闯过裁剪测试、模板测试、深度测试与混合这串固定功能关卡,通过者才写入帧缓冲成为像素。本节按数据流顺序解剖整个关卡序列,重点讲深度测试的「写入与比较分离」、z-fighting 闪烁的病理与三种修法、alpha 混合的顺序依赖,以及双缓冲与垂直同步的呈现机制。管线四阶段解剖至此闭环。

关卡序列:片元的最终审判

先给全景。一个带着颜色与深度的片元到达输出合并阶段,按固定顺序过下列关卡,任何一关失败即被丢弃(个别关卡失败还可能触发别的动作):

图 2-4 逐片元测试关卡序列与各关失败的命运

图 2-4 逐片元测试关卡序列与各关失败的命运

两个设计要点藏在序列里。第一,深度测试的「比较」与「写入」是两个独立开关:GL_DEPTH_TEST 控制要不要比,glDepthMask 控制胜者要不要登记。多数场景两个都开;但渲染影子贴图(第 5 章)时只需要比较结果驱动颜色、不需要污染深度缓冲,就关写入保比较。透明物体也是「只比不写」的常客(本节混合部分展开)。第二,早深度测试(2.3 节提过):硬件会在安全的前提下把深度测试提前到片元着色器之前,遮挡密集的场景因此受益巨大——这也是为什么「先画近处再画远处」的手动排序有时反而更慢:先画近的,远的片元全被提前淘汰,收益远超排序成本。

z-fighting:发病率最高的管线疾病

两个共面或几乎共面的表面,深度值经投影映射后精度不足,谁胜出取决于微小的浮点差异,逐帧抖动——症状是表面交界处条纹状闪烁。解剖病因要从深度缓冲的精度分布说起:透视投影把深度值压进 0 到 1 区间时,非线性映射让大部分精度堆在近平面附近,远处只剩寥寥几个可分辨的台阶。近平面 0.1、远平面 100 的配置下,距离 50 以外的深度分辨率可能粗糙到分不清相隔半米的前后关系。

深度精度的分布可以手感受一次:取近平面 0.1、远平面 100 的透视矩阵,把深度 5 与深度 50 的两个点各自过一遍变换链,算出各自的深度缓冲值——前者大约落在 0.9 附近、后者大约落在 0.995 附近。整个「近处五米」吃掉了 0.9 的值域,「远处九十五米」挤在最后 0.05 里——每 0.001 的深度台阶在远处对应好几米的物理距离。这就是为什么远处共面的两片地砖打得天翻地覆,近处的却相安无事:不是冲突变了,是裁判的分辨率变了

修法按代价从低到高列三种。其一,拉开间隙:把共面几何略微错开(贴花抬高 0.001 之类),建模层面的粗修。其二,调对数分布:近平面从 0.1 推到 1.0,近处的浪费精度让渡给远处,深山远景类场景立竿见影;近平面绝不是越小越好。其三,换对数深度:在对数深度缓冲扩展或着色器里手工写 gl_FragDepth 用对数分布,代价是关掉早深度测试(你动了深度输出),大面积植被远山类场景值得。诊断口诀:条纹闪烁查共面、远处闪烁查近平面

alpha 混合:顺序才是灵魂

混合阶段把片元颜色与缓冲里已有的颜色按 alpha 加权掺和。固定功能公式由 glBlendFunc 配置,标准 alpha 混合是「源色乘源 alpha 加目标色乘 1 减源 alpha」。机制本身三行代码,难点全在顺序:掺色是不可交换运算,先画 A 再画 B 与反过来结果不同——半透明物体必须从远到近画,掺色才符合物理直觉(近的东西叠在远的东西上)。

工程默认骨架因此固定:第一遍关混合画全部不透明物体(顺序无所谓,深度测试兜底);第二遍开混合、开深度比较、关深度写入,把半透明物体按摄像机距离从远到近排序后逐个画。两处易错:忘了关深度写入,第一个透明物体挡住后面的透明物体(深度登记了,后来者测试失败);忘了排序或排序粒度太粗(只按物体不按三角形),掺色次序错乱、玻璃后面颜色怪异。逐三角形的精确排序成本高昂,业界常用折中是按物体排序 + 接受少数artifact,或者干脆改用顺序无关透明技术(进阶话题,第 5 章路标)。

呈现:双缓冲与垂直同步

通过全部关卡的像素躺进后缓冲。1.3 节提过的交换缓冲调用此刻登场:把前后缓冲整体对调,画完的一帧上屏。不加双缓冲的旧时代,用户会看到一帧画到一半的撕裂画面;有了双缓冲,还剩「交换时机」问题——交换发生在扫描周期中途会横向撕裂画面,垂直同步让交换等待回扫描隙,撕裂消失但帧率被锁到显示器刷新率的整数分频。这些机制属于呈现层,OpenGL 把细节交给窗口系统,但排错时你要能区分「管线慢」和「等垂直同步」:帧率稳定卡在 30、60 这类整数上的,先怀疑同步策略而不是着色器。

呈现层还有一个工程旋钮值得知道:交换间隔(swap interval)。设为零等于关掉垂直同步——帧率上限解除,但撕裂回来且 GPU 功耗飙升;设为一即标准垂直同步;设为二则每两次扫描交换一次,适合「稳 30 帧」优先于「尽量快」的场合。竞技向应用常选零加自动限制帧率的折中,影视感应用常选一或二。这个旋钮不属于管线解剖学,但它决定了你对「帧率数字」的解读方式——第 7 章诊断框架的第一步就要先排除它。

管线闭环与解剖台一的收官

至此,管线四站全部剖完:顶点处理变形几何、图元装配与光栅化离散成片元、片元着色器算出颜色、逐片元测试决定生死并混合入帧缓冲。这条解剖主线是后面五章的脊椎——第 3 章供血(数据从哪来),第 4 章语言(两个可编程插槽里写什么),第 5 章成色(光照在片元站怎么做),第 6 章提速(每一站的成本优化),第 7 章诊断(工具如何给这条流拍 X 光片)。

本节要点回顾

  • 关卡序列固定:裁剪 → 模板 → 深度 → 混合 → 写入,失败即出局
  • 深度比较与写入分离:影子贴图第二遍「只比不写」是这个分离的经典应用
  • z-fighting 三修法:错开几何、推远近平面、对数深度,按代价递增选
  • 透明两遍骨架:不透明先(无序)、半透明后(远到近、关深度写入)
  • 撕裂与锁帧查呈现层:整数帧率卡顿先查垂直同步,别冤枉着色器

第一个解剖台完工。下一章往下挖供血系统:VBO、VAO、纹理、帧缓冲对象——管线每个工位吃的数据,都从这套资源体系里来。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U