OpenGL 线段光栅化规范

OpenGL line segment rasterization specification

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

Ideally, the GL uses a “diamond-exit” rule to determine those fragments that are produced by rasterizing a line segment. For each fragment f with center at window coordinates x_f and y_f, define a diamond-shaped region that is the intersection of four half planes:

Essentially, a line segment starting at p_a and ending at p_b produces those fragments f for which the segment intersects R_f, except if p_b is contained in R_f.

但是,考虑这种情况:

如上式所述,当所绘制的线恰好穿过 2 个相邻菱形的角时,不应光栅化任何片段。表达式|x - x_f| + |y - y_f|的最小值是1/2,而1/2不小于1/2,因此不属于R_f,直线永不相交R_f。由于优化,我的软件光栅化算法在这种情况下或多或少地偏爱正确的像素。

显然这不是预期的行为。事实上,再往下看,规范说

Because the initial and final conditions of the diamond-exit rule may be difficult to implement, other line segment rasterization algorithms are allowed, subject to the following rules:

,后面跟着一堆规则,这些规则基本上可以让实现者几乎按原样使用 Bresenham 的算法。此外,主题 14.6.1(基本多边形光栅化)明确消除了多边形光栅化的类似情况:

Special treatment is given to a fragment whose center lies on a polygon edge. In such a case we require that if two polygons lie on either side of a common edge (with identical endpoints) on which a fragment center lies, then exactly one of the polygons results in the production of the fragment during rasterization.

另外,根据我的搜索,这个极端案例似乎被忽略了。我在规范中遗漏了什么吗?在上面给出的模棱两可的情况下,哪个片段是正确的光栅化片段?什么算法(或如何定义算法)能够正确且一致地处理这种情况?

Also, this corner case seems to be shrugged off according to my searches. Am I missing something in the specification? Which fragment is the correct one to rasterize in the ambiguous case presented above?

GL 不强制执行像素精确行为(none 常见 3D 渲染 API 强制执行)。根据规范中给出的条件,实际上留给实施来实施适当的光栅化规则。没有正确或错误的决定,只是要求在这种情况下只为其中一个基元生成片段,不同的实现可以(并且将会)产生不同的输出。

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

如果像素中心(或使用多重采样时的任何其他采样点)恰好位于一个(或多个)边缘上,则pixel/sample被认为是"inside" 当且仅当所述像素中心是 exclusively 部分 "left" 或 "top" edges.

Direct3D 传统上 enforces the top-left rule in the specification,而 OpenGL 则完全不公开此类细节。 OpenGL 实现的用户可以确定,在渲染共享这样一条公共边的两个三角形时,不会有双片段和空洞,并且实现者只需使用某种算法来实现这一点。

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

此实现者的自由度也适用于线栅格化过程中的极端情况。我认为你的结论

When the line being drawn passes exactly through the corners of 2 adjacent diamonds as described by the formula above, neither fragment should be rasterized.

完全正确。在我看来,规范的描述至少是非常不幸的。最好将菱形定义为<= 1/2,并添加特殊规则,即在一次可能与多个菱形相交的情况下,只产生一个碎片。这样的表述至少与多边形光栅化的描述一致。