我试图在屏幕上的每个像素处绘制一个点,但是却出现了一个怪异的异常:两条红线,一条垂直线,一条水平线:
我的设置是这样的:
我有一个像这样的正交投影矩阵:
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);
答案 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
....