OpenGL线段光栅化规范

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenGL线段光栅化规范相关的知识,希望对你有一定的参考价值。

最新的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(基本多边形光栅化)明确消除了多边形光栅化的类似情况:

对中心位于多边形边缘的碎片给予特殊处理。在这种情况下,我们要求如果两个多边形位于片段中心所在的公共边(具有相同的端点)的任一侧,则在光栅化期间恰好一个多边形导致片段的产生。

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

答案

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

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

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

如果像素中心(或使用多重采样时的任何其他采样点)恰好位于一个(或几个)边缘上,则当且仅当所述像素中心仅为“左”的一部分时,该像素/样本才被视为基元的“内部”或“顶部”边缘。

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

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

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

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

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

以上是关于OpenGL线段光栅化规范的主要内容,如果未能解决你的问题,请参考以下文章

计算光栅化片段的数量

光栅化插值方法

我的OpenGL学习进阶之旅OpenGL ES 3.0实现了具有可编程着色功能的图形管线

我的OpenGL学习进阶之旅OpenGL ES 3.0实现了具有可编程着色功能的图形管线

为啥保守光栅化无法为某些三角形调用片段着色器?

OpenGL中着色器,渲染管线,光栅化