Cg 编程/光栅化
光栅化是图形管道中确定由图元(例如三角形)覆盖的像素并为每个覆盖像素插值顶点着色器输出参数(尤其是深度)的阶段。然后将插值后的输出参数传递给片段着色器。(从更广泛的意义上讲,“光栅化”也包括片段着色器的执行和每片段操作。)
通常,Cg 程序员不需要比上一段中描述的更多地了解光栅化阶段。但是,了解一些细节有助于理解透视正确插值等特性以及由顶点着色器计算的顶点位置的第四个分量的作用。对于计算机图形学中的一些高级算法,也需要了解光栅化过程的一些细节。
光栅化的两个主要部分是
- 确定由图元(例如三角形)覆盖的像素
- 对所有覆盖像素进行顶点着色器输出参数和深度的线性插值
在 OpenGL(ES)中,帧缓冲区的像素被定义为如果像素的中心被图元覆盖,则被图元覆盖,如右侧的图所示。
当像素的中心恰好在图元的边界上时,有一些规则。这些规则确保两个相邻的三角形(即共享一条边的三角形)从不共享任何像素(除非它们实际上重叠)并且从不漏掉沿边的任何像素;即,沿两个相邻三角形之间边的每个像素都被其中一个三角形覆盖,但不会被两个三角形覆盖。这对于避免孔洞和(在半透明三角形的情况下)对同一像素进行多次光栅化非常重要。但是,这些规则是特定于 GPU 实现的。此外,除 OpenGL 之外的其他 API 可能会指定不同的规则。因此,它们在这里不会被讨论。
一旦确定了所有覆盖像素,就会为每个像素插值顶点着色器的输出参数。为简单起见,我们只讨论三角形的情况。(一条线就像一个顶点位置相同的三角形。)
对于每个三角形,顶点着色器计算三个顶点的位置。在右侧的图中,这些位置标记为 ,,和 。顶点着色器还计算每个顶点的输出参数值。我们将其中一个表示为 ,,和 。注意,这些值指的是在不同顶点计算的同一个输出参数。我们要插值输出参数的像素中心的坐标在图中用 表示。
我们希望计算一个新的插值值 在像素中心 ,从三个顶点的值 ,,和 中进行插值。有多种方法可以做到这一点。一种是使用重心坐标 ,,和 ,它们是以这种方式计算的
三角形区域 ,, 和 也在图中显示。在三维空间(或二维空间加一个额外维度)中,三个点 ,, 之间的三角形的面积,可以计算为向量叉积长度的一半
使用重心坐标 , 和 ,在点 处对 进行插值,使用三个顶点上的值 , 和 ,非常容易
这样,所有输出参数都可以对所有覆盖的像素进行线性插值。
参数的透视正确插值
[edit | edit source]如果将上一节中描述的插值应用于使用透视投影的场景,可能会导致某些失真。对于透视正确的插值,视点到顶点的距离被放在三个顶点位置的第四个分量(,和)中,并使用以下公式进行插值
因此,顶点位置的第四个分量对于输出参数的透视正确插值非常重要。因此,在顶点着色器中不执行透视除法(将此第四个分量设置为 1)也很重要,否则在透视投影的情况下插值将不正确。(此外,在某些情况下,裁剪也会失败。)
需要注意的是,图形管道实际实现不太可能实现完全相同的过程,因为存在更有效的技术。但是,所有透视正确的线性插值方法都会导致相同的插值结果。
有关 OpenGL ES 光栅化的所有详细信息在“Khronos OpenGL ES API 注册表”“Khronos OpenGL ES API Registry”上提供的“OpenGL ES 2.0.x 规范”的第 3 章中完整定义。
< Cg 编程