OpenGL线段光栅化规范

时间:2017-12-28 17:50:42

标签: algorithm opengl language-agnostic rendering

最新的OpenGL规范(4.6核心),第14.5.1节(基本线段光栅化)(可在https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf找到)指定如何栅格化别名行(由2个浮点端点指定)。

  

理想情况下,GL使用“钻石退出”规则来确定那些碎片   是通过光栅化线段产生的。对于中心位于窗口坐标x_f和y_f的每个片段f,定义一个菱形区域,它是四个半平面的交点:

Diamond region formula

  

本质上,从p_a开始到p_b结束的线段产生片段与R_f相交的片段f,除非p_包含在R_f中。

但是,请考虑这种情况:

corner case

当被绘制的线正好穿过2个相邻钻石的角时,如上面的公式所述,两个片段都不应该被光栅化。表达式|x - x_f| + |y - y_f|的最小值为1/21/2不小于1/2,因此不是R_f的一部分,并且该行永远不会与R_f相交。由于优化,我的软件光栅化算法在这种情况下或多或少地有利于正确的像素。

显然,这不是预期的行为。事实上,进一步下来,规范说

  

由于钻石退出规则的初始条件和最终条件可能难以实现,因此允许使用其他线段栅格化算法,但须遵守以下规则:

,接下来是一系列规则,基本上让实现者几乎按原样使用Bresenham的算法。此外,主题14.6.1(基本多边形光栅化)明确消除了多边形光栅化的类似情况:

  

对中心位于多边形边缘的片段进行特殊处理。在这种情况下,我们要求如果两个多边形位于片段中心所在的公共边(具有相同端点)的两侧,则在光栅化过程中,其中一个多边形会导致片段的生成。

此外,根据我的搜索,这个角落的情况似乎被耸了耸肩。我在规范中遗漏了什么吗?在上面提到的模糊情况下,哪个片段是光栅化的正确片段?什么算法(或如何定义算法),以便正确和一致地处理这种情况?

1 个答案:

答案 0 :(得分:3)

  

此外,根据我的搜索,这个角落的情况似乎被耸了耸肩。我在规范中遗漏了什么吗?在上面提到的模糊情况下,哪个片段是光栅化的正确片段?

GL不会强制执行像素精确行为(常见的3D渲染API都不会)。根据规范中给出的条件,实际上是由实现来实现适当的光栅化规则。没有正确或错误的决定,只需要为此场景中的一个基元生成片段,并且不同的实现可以(并且将)生成不同的输出。

对于三角形光栅化的情况,GPU通常使用一些打破平局规则,例如"左上角"规则:您可以将三角形的每个边分类为左或右(如果它们具有非零垂直范围)或顶部或底部(如果边的两个端点位于相同的y)。退化的三角形(零区域)永远不会产生任何碎片。栅格化。

如果像素中心(或使用多重采样时的任何其他采样点)在一条(或多条)边缘上完全,则该像素/样本被视为"内部"当且仅当所述像素中心完全部分"左"或" top"边缘。

Direct3D传统enforces the top-left rule in the specification,而OpenGL完全打开了这些细节。 OpenGL实现的用户可以确定当共享两个共享这样的commmon边缘的三角形时,将没有双重片段和没有空洞,并且实现者只需使用一些算法来实现这一点。

此外,GL规范还要求实现以实现一些不变性规则,这通常强制执行可重复性,因此实现不能仅在不同时间点的不同打破平局规则之间随机选择。您应该查看规范的附录A,了解有关确切要求和保证的详细信息。

此实现者自由也适用于行光栅化期间的角落情况。我认为你的结论

  

当被绘制的线完全穿过上面公式所描述的2个相邻钻石的角落时,两个碎片都不应该被光栅化。

完全正确。在我看来,规范的描述至少是非常不幸的。将钻石定义为<= 1/2可能更好,并添加特殊规则,即如果一次可以交叉多个钻石,则只生产一个碎片。这样的公式至少与多边形光栅化的描述一致。