第 3 章 · 状态机与输出目标对照 章节摘要:着色公式在可编程阶段,但像素最终能否留下、如何与旧像素合并,仍由一套固定功能状态决定:深度测试、面剔除、混合、帧缓冲绑定。本章对照 CPU 算矩阵与 GPU 做乘法、覆盖写与混合写、深度测试与面剔除、默认屏幕与离屏目标。读完你应能解释:为什么半透明必须改混合而不能只改着色器,为什么后处理必须换绑定而不能只加一行 FS。 先说结论 阅读完本章,你应当能够: 对照模型、视图、投影三个空间,并说明乘法顺序写在 CPU 还是 VS 区分清屏覆盖、不透明覆盖与混合写三种写颜色方式 说明深度测试与面剔除各自砍掉什么,以及顺序如何影响结果 画出默认画布帧缓冲与用户 FBO 的绑定切换 指出后处理、阴影贴图、拾取为何都必须离屏 核心概念速览
章节摘要:着色公式在可编程阶段,但像素最终能否留下、如何与旧像素合并,仍由一套固定功能状态决定:深度测试、面剔除、混合、帧缓冲绑定。本章对照 CPU 算矩阵与 GPU 做乘法、覆盖写与混合写、深度测试与面剔除、默认屏幕与离屏目标。读完你应能解释:为什么半透明必须改混合而不能只改着色器,为什么后处理必须换绑定而不能只加一行 FS。
阅读完本章,你应当能够:
金句:着色器决定“想写成什么颜色”,状态机决定“这块像素还让不让你写、怎么跟旧值合成”。
| 旋钮 | 双方 | 典型用途 |
|---|---|---|
| 空间 | CPU 算矩阵对 GPU 做乘法 | 整物体运动对每顶点变形 |
| 合成 | 覆盖写对混合写 | 不透明对半透明 |
| 丢弃 | 面剔除对深度测试 | 省背面对遮挡 |
| 房间 | 默认屏对离屏 FBO | 呈现对后处理阴影 |
MVP 链把模型空间送到裁剪空间。矩阵可以在 CPU 乘好只传一个 Uniform,也可以分传让 VS 乘。对照带宽、精度与骨骼动画需求。
不透明物体是覆盖;半透明是混合函数。预乘与非预乘是合同。只改 FS 的 alpha 却不改 blendFunc,结果仍像不透明。
剔除按绕序扔背面,深度按 z 决定遮挡。透明物体常要关深度写入。对照两者砍的是几何还是片元。
默认 FBO 连着 canvas。用户 FBO 把颜色与深度画到纹理,供下一趟采样。阴影、Bloom、延迟着色都走这条对照。
先把顶点放到正确空间,再决定怎么写颜色、谁被挡住、写到哪块记忆体。后处理不是第 4 章才突然出现的魔法,它是 3.4 的绑定切换加上第 2 章的纹理采样。
3.1 空间对了 └► 3.2 颜色怎么合成 ─► 3.3 谁被丢弃 └► 3.4 写到屏还是写到纹理
状态机没有作用域。一个 pass 关掉深度写入,下一个 pass 会继承,除非你恢复。本章建议你在脑子里维护一份“不透明默认表”:剔除开、深度测开、深度写开、混合关、FBO 为默认。每个特例 pass 进出都回到这张表。引擎通常每对象设置;裸写漏恢复,会表现为“隔一帧才错”的幽灵。
离屏不是高级技巧,是换房间画画。后处理、阴影、拾取只是房间用途不同。先学会换房间,再往房间里摆滤镜。
本章四节对应四个旋钮:空间、合成、丢弃、房间。旋钮会互相影响。投影 near 太近,深度打架;混合开着却当不透明排序;剔除开着资产绕序反;离屏尺寸与视口不一致。调试时只拧一个旋钮。同时拧会让你以为 WebGL 随机。状态机其实极其听话,听话到把你泄漏的状态精确执行到下一帧。
建议在编辑器里放一份状态快照打印:混合是否开、深度掩码、当前 FBO、viewport。出幽灵 bug 先看快照。这比改公式快。引擎有 debug 面板;裸写十行就能打出快照。第 1.3 节说封装藏状态,本章说藏了也要能掀开。
默认状态表建议抄下来贴在编辑器旁:剔除开、深度测开写开、混合关、FBO 默认、viewport 等于 drawingBuffer。每个特例 pass 结束回到这张表。表比记忆可靠,也比“引擎会处理”可靠。混用裸调用时尤其如此。
把默认状态表提交进仓库。代码审查看到临时改状态却不恢复,直接打回。状态泄漏的 bug 会表现为隔帧、隔物体、隔 pass 才错,最耗人。表是便宜的预防。离屏注册表同理,放在第 3.4 节落地。本章是状态机的纪律章,纪律比新效果值钱。
状态机纪律比新效果值钱,因为泄漏会把对的公式画成错的顺序。恢复默认表、离屏注册表、near far 门禁,这三件写进仓库就能少一半幽灵 bug。幽灵 bug 看起来像驱动问题,其实是上一 pass 的掩码。审查临时改状态而不恢复的补丁,直接打回。打回一次,省一夜。
四节的旋钮一次只拧一个。拧完看默认表是否恢复。恢复了再拧下一个。这是状态机的礼貌,也是调试的速度。把默认表提交进仓库,审查看到临时改状态却不恢复就打回。打回一次,少一夜幽灵。