跳转到内容

GLSL 编程/光栅化

来自维基教科书,开放世界中的开放书籍

光栅化是 OpenGL(ES)2.0 管线 的一个阶段,它确定由一个图元(例如三角形)覆盖的像素,并为每个覆盖的像素插值顶点着色器的输出变量(即变化变量和深度)。这些插值的变化变量和插值深度随后传递给片段着色器。(从更广泛的意义上说,“光栅化”还包括执行片段着色器和 每个片段操作。)

通常,GLSL 程序员不需要了解光栅化阶段的更多细节,而只需要了解上一段描述的这些内容。然而,了解一些细节对于理解透视正确插值等功能以及顶点着色器计算的顶点位置第四个分量的作用很有帮助。对于计算机图形学中的一些高级算法,也需要了解光栅化过程的一些细节。

光栅化的主要两个部分是

  • 确定被一个图元(例如三角形)覆盖的像素
  • 对所有覆盖的像素进行变化变量和深度的线性插值
被三角形覆盖的像素。

确定覆盖的像素

[编辑 | 编辑源代码]

在 OpenGL(ES)中,帧缓冲区的一个像素被定义为被一个图元覆盖,如果像素的中心被该图元覆盖,如右图所示。

当一个像素的中心恰好在图元边界上时,有一些特定的规则。这些规则确保两个相邻三角形(即共享一条边的三角形)永远不会共享任何像素(除非它们实际上重叠),并且不会漏掉边上的任何像素;也就是说,边上每个像素都被这两个相邻三角形中的一个覆盖,而不是同时被两个覆盖。这对于避免孔洞和(在半透明三角形的情况下)对同一个像素进行多次光栅化非常重要。但是,这些规则是特定于 GPU 实现的,因此在这里不做讨论。

用于插值变化变量的三角形区域。

变化变量的线性插值

[编辑 | 编辑源代码]

一旦确定了所有覆盖的像素,就需要为每个像素插值变化变量。为了简单起见,我们只讨论三角形的情况。(一条线就像一个有两个顶点位于相同位置的三角形。)

对于每个三角形,顶点着色器计算三个顶点的位置。在右图中,这些位置被标记为 ,和 。顶点着色器还计算每个顶点上变化变量的值。我们把其中一个变量表示为 ,和 。请注意,这些值指的是在不同顶点计算的同一个变化变量。我们要插值变化变量的像素中心的坐标在图中用 表示。

我们想从三个顶点上的值 ,和 计算像素中心 的一个新的插值值 。有多种方法可以做到这一点。一种方法是使用重心坐标 ,和 ,它们以这种方式计算

三角形面积 , , 也在图中显示。在三维空间(或二维空间加上一个额外的第三维)中,三个点 , , 之间的三角形面积可以计算为向量叉积长度的一半

使用重心坐标 ,在点 进行插值,根据三个顶点上的值 是很容易的。

通过这种方式,所有变化的变量都可以对所有覆盖的像素进行线性插值。

透视不正确纹理坐标插值(标记为“仿射”)和透视正确插值(标记为“正确”)的比较。

透视正确插值变化的变量

[edit | edit source]

如果将上一节中描述的插值应用于使用透视投影的场景,可能会导致某些失真。为了透视正确插值,视点到距离放在三个顶点位置的第四个分量中 (),并且使用以下公式进行插值

因此,顶点位置的第四个分量对于透视正确插值变化的变量很重要。因此,透视除法(将第四个分量设置为 1)在顶点着色器中不执行也很重要,否则在透视投影的情况下插值将不正确。(此外,在某些情况下剪裁会失败。)

需要注意的是,实际的 OpenGL 实现不太可能实现完全相同的过程,因为存在更有效的技术。但是,所有透视正确的线性插值方法都会得出相同的插值结果。

进一步阅读

[编辑 | 编辑源代码]

有关 OpenGL ES 光栅化的所有详细信息,在“Khronos OpenGL ES API 注册表”中的“OpenGL ES 2.0.x 规范”第 3 章中进行了完整详细的定义。 “Khronos OpenGL ES API 注册表”


< GLSL 编程

除非另有说明,否则本页上的所有示例源代码均归属公共领域。
华夏公益教科书