【发布时间】:2012-04-06 08:25:15
【问题描述】:
我正在开发 2d 引擎。它已经很好用了,但我不断收到像素错误。
例如,我的窗口是 960x540 像素,我画了一条从 (0, 0) 到 (959, 0) 的线。我希望扫描线 0 上的每个像素都将设置为一种颜色,但不是:最右边的像素没有被绘制。当我垂直绘制到像素 539 时出现同样的问题。我真的需要绘制到 (960, 0) 或 (0, 540) 才能绘制它。
由于我出生在像素时代,我坚信这不是正确的结果。当我的屏幕为 320x200 像素大时,我可以从 0 到 319 以及从 0 到 199 进行绘制,我的屏幕将是满的。现在我最终得到了一个未绘制右/下像素的屏幕。
这可能是由于不同的原因: 我希望opengl线原语是从一个像素到一个像素(包括)绘制的,最后一个像素实际上是独占的?是这样吗? 我的投影矩阵不正确? 我有一个错误的假设,即当我有一个 960x540 的后备缓冲区时,实际上还有一个像素? 还有什么?
有人可以帮帮我吗?这个问题我研究了很久,每次觉得没问题的时候发现其实不行。
这是我的一些代码,我试图尽可能地精简它。当我调用我的 line-function 时,每个坐标都添加了 0.375、0.375 以使其在 ATI 和 nvidia 适配器上都正确。
int width = resX();
int height = resY();
for (int i = 0; i < height; i += 2)
rm->line(0, i, width - 1, i, vec4f(1, 0, 0, 1));
for (int i = 1; i < height; i += 2)
rm->line(0, i, width - 1, i, vec4f(0, 1, 0, 1));
// when I do this, one pixel to the right remains undrawn
void rendermachine::line(int x1, int y1, int x2, int y2, const vec4f &color)
{
... some code to decide what std::vector the coordinates should be pushed into
// m_z is a z-coordinate, I use z-buffering to preserve correct drawing orders
// vec2f(0, 0) is a texture-coordinate, the line is drawn without texturing
target->push_back(vertex(vec3f((float)x1 + 0.375f, (float)y1 + 0.375f, m_z), color, vec2f(0, 0)));
target->push_back(vertex(vec3f((float)x2 + 0.375f, (float)y2 + 0.375f, m_z), color, vec2f(0, 0)));
}
void rendermachine::update(...)
{
... render target object is queried for width and height, in my test it is just the back buffer so the window client resolution is returned
mat4f mP;
mP.setOrthographic(0, (float)width, (float)height, 0, 0, 8000000);
... all vertices are copied to video memory
... drawing
if (there are lines to draw)
glDrawArrays(GL_LINES, (int)offset, (int)lines.size());
...
}
// And the (very simple) shader to draw these lines
// Vertex shader
#version 120
attribute vec3 aVertexPosition;
attribute vec4 aVertexColor;
uniform mat4 mP;
varying vec4 vColor;
void main(void) {
gl_Position = mP * vec4(aVertexPosition, 1.0);
vColor = aVertexColor;
}
// Fragment shader
#version 120
#ifdef GL_ES
precision highp float;
#endif
varying vec4 vColor;
void main(void) {
gl_FragColor = vColor.rgb;
}
【问题讨论】:
-
我开始认为这是我所说的“点独占”的东西。如果您使用 QT 或 C++ Builder/Delphi 甚至 windows API 绘制线条,则绘制的像素不包括端点。所以在opengl中可能会这样做,并且可能在绘制三角形时也是如此?当您使用 QT、builder、...绘制一个矩形时,您还会将右下角排除在外...
-
以下测试与我上面所说的一致:当我使用 GL_POINT 填充窗口所有角落的像素时,这些坐标与我预期的一样:(0,0) ,(宽度-1,高度-1)。这表明我的绘制方式是正确的,这条线(可能还有三角形)将不包括终点。有人可以同意吗?
标签: opengl drawing pixel-perfect