opengl drawing pixel-perfect

Diagrama de Opengl pixel perfecto 2D



drawing pixel-perfect (2)

En OpenGL, las líneas se rasterizan usando la regla "Diamond Exit". Esto es casi lo mismo que decir que la coordenada final es exclusiva, pero no del todo ...

Esto es lo que la especificación de OpenGL tiene que decir: http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node47.html

También eche un vistazo a las preguntas frecuentes de OpenGL, http://www.opengl.org/archives/resources/faq/technical/rasterization.htm , elemento "14.090 ¿Cómo obtengo la pixelización exacta de las líneas?". Dice: "La especificación OpenGL permite una amplia gama de hardware de renderizado de línea, por lo que la pixelización exacta puede no ser posible en absoluto".

Muchos argumentarán que no debes usar líneas en OpenGL en absoluto. Su comportamiento se basa en cómo funcionó el antiguo hardware de SGI, no en lo que tiene sentido. (¡Y las líneas con anchos> 1 son casi imposibles de usar de una manera que se ve bien!)

Estoy trabajando en un motor 2d. Ya funciona bastante bien, pero sigo recibiendo errores de píxeles.

Por ejemplo, mi ventana tiene 960x540 píxeles, dibujo 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 la 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 es en realidad tiene un píxel más? ¿Algo más?

¿Puede alguien 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 tanto como sea posible. 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; }


Tenga en cuenta que el espacio de coordenadas de OpenGL no tiene noción de enteros, todo es un flotante y el "centro" de un píxel de OpenGL está realmente en 0.5.0.5 en lugar de su esquina superior izquierda. Por lo tanto, si desea una línea de 1px de 0,0 a 10,10 inclusive, realmente debe trazar una línea de 0.5,0.5 a 10.5,10.5.

Esto será especialmente evidente si activa el anti-aliasing, si tiene anti-aliasing e intenta dibujar de 50,0 a 50,100, puede ver una línea borrosa de 2px de ancho porque la línea cayó entre dos píxeles.