#include <math.h>
#include <GL/glut.h>
#pragma comment(lib, "opengl32")
#include <gl/gl.h>
#include <gl/glu.h>
//Initialize OpenGL
void init(void) {
glClearColor(0, 0, 0, 0);
glViewport(0, 0, 500, 500);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 500, 0, 500, 1, -1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void drawLines(void) {
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0,1.0,1.0);
glBegin(GL_LINES);
glVertex3d(0.5, 0.999, 0.0f);
glVertex3d(499.501, 0.999, 0.0f);
glEnd();
glFlush();
}
int _tmain(int argc, _TCHAR* argv[])
{
glutInit(&argc, argv);
glutInitWindowPosition(10,10);
glutInitWindowSize(500,500);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutCreateWindow("Example");
init();
glutDisplayFunc(drawLines);
glutMainLoop();
return 0;
}
问题描述:
上面的代码会将窗口客户区域的整个底部行像素设置为白色。
如果我从
glVertex3d(0.5, 0.999, 0.0f);glVertex3d(499.501, 0.999, 0.0f);
到glVertex3d(499.501, 0.999, 0.0f);glVertex3d(0.5, 0.999, 0.0f);
交换命令顺序,则仅不会绘制左下像素。我的理解:
两个顶点最终将转换为2D像素中心坐标,分别是(0.0,0.499)和(499.001,0.499)。
画线算法仅接受像素中心整数点作为输入。
所以这两个顶点顶点将使用int(x + 0.5),分别为(0,0)和(499,0)。这符合第一个结果,但与输入顺序更改时的结果相矛盾。为什么?
#1 楼
根据顶点顺序覆盖像素的差异与光栅化规则有关。它们是GPU硬件用来确切确定基本像素覆盖哪些像素的规则。栅格化规则有些微妙。他们的目标之一是确保每当绘制多个水密连接的图元时,栅格化都不会在它们之间产生任何裂纹,也不会覆盖任何像素两次(这对于混合很重要)。为此,规则有一些非常具体的边角情况。从字面上看...它们与原始边和角有关。 :)
对于行,它的工作方式如下。每个像素中心周围都有一个菱形区域,如上面链接的MSDN文章中的该图的片段所示。
规则是像素是从行的起点到终点跟踪时,如果线退出菱形,则覆盖。请注意,如果线条进入但不退出菱形,则像素不会被覆盖。这样可以确保如果有两个线段首尾相连,则它们共享端点处的像素仅属于其中一个线段,因此不会被两次光栅化。
您还可以在上图显示了更改顶点顺序如何影响覆盖哪些像素(三角形不会发生这种情况,BTW)。该图显示了两个线段,除了交换端点顺序外,它们是相同的,您可以看到它对覆盖哪个像素有所不同。
您的线段与此类似。左端(0.5,0.999)在(0,0)像素的菱形内部,因此当它是第一个顶点时(线开始于菱形内部,然后退出它),而不是第二个顶点时,它被覆盖顶点(线进入菱形,并在菱形内结束,因此它永远不会退出)。实际上,在栅格化之前,将顶点用8个子像素位捕捉到固定点,因此该顶点最终舍入为(0.5,1.0),恰好在菱形的顶角。根据光栅化规则,在钻石内部可能会考虑这一点,也可能不会考虑。好像在您的GPU上考虑了它一样,但这在不同的实现中可能会有所不同,因为GL规范并未完全确定规则。