Sto lavorando a un motore 2D. Funziona già abbastanza bene, ma continuo ad avere errori di pixel.Opengl pixel disegno 2D perfetto
Ad esempio, la mia finestra è di 960x540 pixel, disegno una linea da (0, 0) a (959, 0). Mi aspetto che ogni pixel su scan-line 0 sia impostato su un colore, ma no: il pixel più a destra non viene disegnato. Lo stesso problema quando disegno verticalmente sul pixel 539. Ho davvero bisogno di disegnare su (960, 0) o (0, 540) per disegnarlo.
Come sono nato nell'era dei pixel, sono convinto che questo non è il risultato corretto. Quando il mio schermo era grande 320x200 pixel, potevo disegnare da 0 a 319 e da 0 a 199, e il mio schermo sarebbe pieno. Ora finisco con uno schermo con un pixel a destra/in basso non disegnato.
Questo può essere dovuto a cose diverse: dove mi aspetto che la linea primitiva opengl sia disegnata da un pixel a un pixel incluso, che l'ultimo pixel sia effettivamente esclusivo? È così? la mia matrice di proiezione non è corretta? Sono sotto falso presupposto che quando ho un backbuffer di 960x540, che in realtà ha un pixel in più? Qualcos'altro?
Qualcuno può aiutarmi? Ho esaminato questo problema da molto tempo, e ogni volta che pensavo fosse ok, ho visto dopo un po 'che in realtà non lo era.
Ecco un po 'del mio codice, ho provato a eliminarlo il più possibile. Quando chiamo la mia funzione di linea, ogni coordinata viene aggiunta con 0.375, 0.375 per renderla corretta su entrambi gli adattatori ATI e 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;
}
Sto iniziando a pensare che sia la cosa "esclusiva esclusiva" di cui sto parlando. Se si utilizza QT o C++ Builder/Delphi o anche Windows API per disegnare linee, i pixel vengono disegnati escludendo il punto finale. Quindi è possibile che lo stesso sia fatto in opengl, e probabilmente anche quando si disegnano triangoli? Quando si disegna un rettangolo con QT, builder, ..., si ottiene anche l'angolo in basso a destra escluso ... – scippie
Il seguente test mostra un accordo con quello che ho detto sopra: quando uso GL_POINT per riempire i pixel in tutti gli angoli della finestra, queste coordinate sono come mi aspetto che siano: (0,0), (larghezza-1, altezza -1). Questo mi mostra che il mio modo di disegnare è corretto e che la linea (e probabilmente il triangolo) non includerà semplicemente il punto finale. Qualcuno può concordare? – scippie
correlati http://stackoverflow.com/questions/5467218/opengl-2d-hud-over-3d –