Pracuję na silniku 2d. Działa już całkiem nieźle, ale ciągle dostaję błędy pikseli.Opengl pixel idealny rysunek 2D
Na przykład moje okno ma 960 x 540 pikseli, rysuję linię od (0, 0) do (959, 0). Spodziewam się, że każdy piksel na linii zerowej 0 zostanie ustawiony na kolor, ale nie: piksel o wartości maksymalnie prawej nie zostanie narysowany. Ten sam problem, gdy rysuję pionowo do piksela 539. Naprawdę muszę narysować (960, 0) lub (0, 540), aby go narysować.
Ponieważ urodziłem się w erze pikseli, jestem przekonany, że to nie jest właściwy wynik. Gdy mój ekran miał wielkość 320x200 pikseli, mogłem rysować od 0 do 319 i od 0 do 199, a mój ekran byłby pełny. Teraz kończę z ekranem, którego piksel prawy/dolny nie jest narysowany.
To może być spowodowane różnymi rzeczami: gdzie mogę się spodziewać, że prymityw linii prostej OpenGL zostanie narysowany od piksela do piksela włącznie, że ostatni piksel jest tak naprawdę wyłączny? Czy to to? Moja macierz projekcji jest niepoprawna? Jestem pod fałszywym założeniem, że kiedy mam backbuffer z 960x540, to faktycznie ma jeden piksel więcej? Coś jeszcze?
Czy ktoś może mi pomóc? Od dawna zajmowałem się tym problemem i za każdym razem, gdy myślałem, że wszystko jest w porządku, po pewnym czasie zobaczyłem, że tak naprawdę nie było.
Oto niektóre z mojego kodu, starałem się rozebrać go tak bardzo, jak to możliwe. Kiedy zadzwonię do mojej funkcji liniowej, każda współrzędna jest dodawana z 0.375, 0.375, aby była poprawna zarówno dla adapterów ATI, jak i 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;
}
Zaczynam myśleć, że to jest "punkt wyłączności" o czym mówię. Jeśli używasz QT lub C++ Builder/Delphi lub nawet Windows API do rysowania linii, piksele są rysowane z wyłączeniem punktu końcowego. Więc możliwe, że to samo dzieje się w opengl, a prawdopodobnie także podczas rysowania trójkątów? Gdy narysujesz prostokąt z QT, konstruktorem, ..., wykluczony zostanie również prawy dolny róg ... – scippie
Poniższy test pokazuje zgodność z tym, co powiedziałem powyżej: kiedy używam GL_POINT do wypełnienia pikseli we wszystkich rogach okna, te współrzędne są takie, jak się spodziewam: (0,0), (szerokość-1, wysokość -1). To pokazuje mi, że mój sposób rysowania jest poprawny i że linia (i ewentualnie trójkąt) po prostu nie będzie zawierała punktu końcowego. Czy ktoś może się zgodzić? – scippie
powiązane http://stackoverflow.com/questions/5467218/opengl-2d-hud-over-3d –