尝试为屏幕的每个像素着色时出现线条?

时间:2019-09-05 18:32:41

标签: c++ opengl glm-math opengl-3

我试图在屏幕上的每个像素处绘制一个点,但是却出现了一个怪异的异常:两条红线,一条垂直线,一条水平线:

我的设置是这样的:

我有一个像这样的正交投影矩阵:

glm::mat4 projection=glm::ortho(0.f, screen_width-1.f, 0.f, screen_height-1.f, 1.f, -1.f);

只是将opengl坐标系设置为与屏幕像素尺寸相同的大小。

然后,我正在创建将数据填充到这样的向量中:

for (int i=0; i<screen_height; ++i){
    for (int j=0; j<screen_width; ++j){
        idata.push_back(j);
        idata.push_back(i);
        idata.push_back(1);
    }
}

我正在使用以下方法将整数上传到VBO:

glBufferData(GL_ARRAY_BUFFER, sizeof(GLint)*idata.size(), &idata[0], GL_DYNAMIC_DRAW);

像这样设置属性:

glVertexAttribIPointer(0, 3, GL_INT, 3*sizeof(GLint), (void *)(0*sizeof(GLint)));
glEnableVertexAttribArray(0);

这是我的着色器的布局:

layout (location=0) in ivec3 position;

这是我的抽奖电话:

glDrawArrays(GL_POINTS, 0, idata.size()/3);

1 个答案:

答案 0 :(得分:2)

这是一个四舍五入的问题,因为您确实以非常奇怪的方式设置了投影:

glm::ortho(0.f,screen_width-1.f,0.f,screen_height-1.f,1.f,-1.f)

在OpenGL的窗口空间中,像素是实际区域(大小为1x1的正方形)。

因此,如果您的屏幕例如是4像素宽,这就是您获得的像素值

+--+--+--+--+
|0 |1 |2 |3 |  integer pixel coors
...

但是,您工作的空间是连续的(至少在原则上是这样),OpenGL的窗口空间将从0变为 4 (不是3),这很合理,因为有四个像素,每个像素为一个单位宽:

0  1  2  3  4  OpenGL window space
+--+--+--+--+
|0 |1 |2 |3 |  integer pixel coords
....

使用OpenGL的窗口空间约定,像素中心位于半整数坐标上。

现在,您不是直接在OpenGL窗口空间中绘制,而是可以设置变换以基本上撤消视口变换(从NDC到窗口空间)以获得像素精确的映射。但是你没有那样做。相反,您所做的是:

  3/4   9/4
0    6/4    3  your coordinate system
+--+--+--+--+
|0 |1 |2 |3 |  integer pixel coords
....

在这个怪异的系统中,您将绘制完整整数,但这并不能很好地映射到实际像素。

所以你应该做

glm::ortho(0.f,screen_width,0,screen_height,1.f,-1.f)

但是,由于您似乎是在整数位置进行绘制,因此最终只能在像素角处进行绘制,并且仍然可能会遇到一些舍入问题(根据规范,舍入方向将取决于实现)。

因此,最好将其移动,以使整数坐标位于像素中心

glm::ortho(-0.5f, screen_width-0.5f, -0.5f, screen_height-0.5f, 1.f, -1.f)


    0.5   2.5
-0.5   1.5   3.5  your coordinate system
  +--+--+--+--+
  |0 |1 |2 |3 |  integer pixel coords
  ....