Estoy trabajando en un motor 2d. Ya funciona bastante bien, pero sigo recibiendo errores de píxeles.Opengl pixel perfect 2D drawing
Por ejemplo, mi ventana es de 960x540 píxeles, trazo una línea de (0, 0) a (959, 0). Esperaría que cada píxel en la línea de escaneo 0 se establezca en un color, pero no: el píxel que está más a la derecha no se dibuja. El mismo problema cuando dibujo verticalmente al píxel 539. Realmente necesito dibujar a (960, 0) o (0, 540) para dibujarlo.
Como nací en la era de los píxeles, estoy convencido de que este no es el resultado correcto. Cuando mi pantalla tenía 320x200 píxeles, podía dibujar de 0 a 319 y de 0 a 199, y mi pantalla estaría llena. Ahora termino con una pantalla con un pixel derecho/inferior no dibujado.
Esto puede deberse a cosas diferentes: donde espero que la primitiva de línea OpenGL se extraiga de un píxel a un píxel incluido, ¿ese último píxel es realmente exclusivo? ¿Es asi? mi matriz de proyección es incorrecta? Estoy bajo la falsa suposición de que cuando tengo un backbuffer de 960x540, ¿eso realmente tiene un píxel más? ¿Algo más?
¿Alguien puede ayudarme? He estado investigando este problema desde hace mucho tiempo, y cada vez que pensaba que estaba bien, después de un tiempo vi que en realidad no era así.
Aquí está algo de mi código, traté de quitarlo todo lo que pude. Cuando llamo a mi función de línea, cada coordenada se agrega con 0.375, 0.375 para corregirla en los adaptadores ATI y 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;
}
Estoy empezando a pensar que es el punto "exclusivo" del que estoy hablando. Si usa QT o C++ Builder/Delphi o incluso API de Windows para dibujar líneas, los píxeles se dibujan excluyendo el punto final. Entonces, ¿es posible que lo mismo se haga en OpenGL, y probablemente también al dibujar triángulos? Cuando dibuja un rectángulo con QT, constructor, ..., también obtiene la esquina inferior derecha excluida ... – scippie
La siguiente prueba muestra que estoy de acuerdo con lo que dije antes: cuando uso GL_POINT para llenar los píxeles en todas las esquinas de la ventana, estas coordenadas son las que espero sean: (0,0), (ancho-1, altura) -1). Esto me muestra que mi forma de dibujar es correcta y que la línea (y posiblemente el triángulo) simplemente no incluirá el punto final. ¿Puede alguien estar de acuerdo? – scippie
relacionado http://stackoverflow.com/questions/5467218/opengl-2d-hud-over-3d –