计算机图形学渲染基础

最后更新: 2021-07-31 18:25:07 +0800 +0800
tags: Graphics | Webgl | Gpu
原文以英文撰写。您正在阅读AI翻译版本。

渲染将抽象几何体转换为像素。GPU 流水线接收顶点,对其进行变换和裁剪,栅格化可见形状, 并为生成的片段着色。

流水线 #

典型的渲染流水线包含以下阶段:

  1. 顶点处理;
  2. 图元装配;
  3. 裁剪和视口变换;
  4. 栅格化;
  5. 片段着色;
  6. 深度和混合;
  7. 帧缓冲写回。

上述顺序很重要,因为每个阶段都会将问题从几何体逐步缩小到像素。

顶点数据 #

输入通常以顶点列表和索引缓冲区开始。

  • 顶点包含位置以及颜色、法线或纹理坐标等可选属性;
  • 索引会在三角形之间复用顶点;
  • 图元通常是三角形,因为三角形始终是平面的。

顶点着色器对每个顶点运行一次。它的任务是将位置变换到裁剪空间,并将每顶点数据向后传递。传统变换会将每个对象空间位置依次乘以模型、视图和投影矩阵:

text
clip_position = projection * view * model * object_position

模型矩阵将对象放置到世界空间,视图矩阵表示相对于摄像机的世界,投影矩阵将摄像机空间的视锥体映射到齐次裁剪空间。矩阵顺序取决于 API 和向量约定;着色器和主机代码必须保持一致。

裁剪空间和裁剪 #

几何体在栅格化之前会裁剪掉裁剪空间之外的部分。在 OpenGL 和 WebGL 中,当 -w <= x, y, z <= w 时,裁剪空间顶点位于内部。如果三角形跨越边界,GPU 会创建可见多边形并丢弃外部部分。

裁剪后,透视除法将归一化设备坐标(NDC)计算为 (x/w, y/w, z/w)。视口变换随后将 NDC 映射到窗口坐标。透视相关属性的插值会使用齐次 w 值,因此纹理坐标不会像仿射屏幕空间值那样发生变形。

栅格化 #

栅格化将三角形转换为片段,即候选像素。栅格化器决定哪些采样位置位于三角形内部,并在表面上插值属性。

插值的值包括:

  • 颜色;
  • 深度;
  • 纹理坐标;
  • 法线或其他 varying。

正因为存在这种插值,即使输入只指定了角点处的值,三角形上也能出现渐变。

片段着色 #

片段着色器对每个片段运行一次,并计算最终颜色或丢弃决定。

典型的片段处理包括:

  • 纹理采样;
  • 光照近似;
  • alpha 测试或丢弃;
  • 颜色校正;
  • 程序化图案。

许多视觉上重要的效果发生在这一阶段,因为着色器可以将插值属性与纹理和 uniform 结合起来。

深度、混合和帧缓冲区 #

深度缓冲区解决重叠图元之间的可见性。如果一个片段比另一个更近,通常由更近的片段胜出。

混合会为半透明表面组合源颜色和目标颜色。它适用于透明效果、粒子和 UI 效果,但依赖绘制顺序。通常先启用深度写入绘制不透明几何体,再使用谨慎选择的混合因子从后向前绘制半透明几何体。

最终颜色会写入帧缓冲区,然后呈现到屏幕或图像目标。

WebGL 视角 #

WebGL 通过 JavaScript 暴露这条流水线。画布提供绘制表面,着色器以源字符串形式提供,浏览器将工作交给 GPU。WebGL 继承 OpenGL ES 的裁剪空间约定:三个轴上的 NDC 都跨越 [-1, 1],而窗口坐标将视口原点放在左下角。浏览器图像源通常从上到下排列,因此纹理上传或坐标可能需要显式垂直翻转。

思维模型仍然相同:

  • 上传缓冲区;
  • 配置顶点属性;
  • 编译着色器;
  • 绑定程序、帧缓冲区和其他所需状态;
  • 绘制三角形;
  • 呈现生成的帧。

实用规则 #

WebGL 是状态机。绘制调用会使用当前绑定的程序、顶点数组和缓冲区绑定、纹理、帧缓冲区、视口、深度状态以及混合状态。当输出错误时,应检查绘制调用处的完整状态,而不只是着色器源代码。

评论

在 GitHub 上阅读或评论(发表评论需要登录)