La traducción de la unidad ortográfica no coincide en la cuadrícula (por ejemplo, 64 píxeles se traducen incorrectamente)

14

Estoy buscando una idea de un pequeño problema con las traducciones de unidades en una cuadrícula.

Actualización y resuelto

Resolví mi propio problema. Ver abajo para más detalles. Todo en esta parte de la publicación resultó ser correcto. En todo caso, puede actuar como un tutorial / ejemplo / ayuda en miniatura para la siguiente persona.

Preparar

  • FBO, VAO, VBO
  • Ventana 512x448
  • Cuadrícula 64x64
  • gl_Position = projection * world * position;
  • projectionse define por ortho(-w/2.0f, w/2.0f, -h/2.0f, h/2.0f);Esta es una función de proyección ortogonal de libro de texto.
  • world se define por una posición fija de la cámara en (0, 0)
  • position se define por la posición del sprite.

Problema

En la captura de pantalla a continuación (escala 1: 1) el espaciado de la cuadrícula es 64x64 y estoy dibujando la unidad en (64, 64), sin embargo, la unidad dibuja aproximadamente ~ 10px en la posición incorrecta. He intentado dimensiones de ventana uniformes para evitar cualquier distorsión en el tamaño de píxel, pero ahora estoy un poco perdido en la forma correcta de proporcionar una proyección 1: 1 de píxel a unidad de mundo. De todos modos, aquí hay algunas imágenes rápidas para ayudar en el problema.

Azulejos de 64x64 en una ventana de 512x448

Decidí superimponer un montón de sprites en lo que el motor cree que son compensaciones de 64x.

64 compensaciones superpuestas

Cuando esto parecía fuera de lugar, fui e hice el caso base de 1 unidad. Lo cual parecía alinearse como se esperaba. El amarillo muestra una diferencia de 1 px en el movimiento.

Estuche base de 1 unidad

Lo que quiero

Idealmente, moverse en cualquier dirección de 64 unidades generaría lo siguiente (unidades superpuestas):

Salida deseada

Vértices

Parece que los vértices que van al sombreador de vértices son correctos. Por ejemplo, en referencia a la primera imagen, los datos se ven así en el VBO:

      x    y           x    y
    ----------------------------    
tl | 0.0  24.0        64.0 24.0
bl | 0.0  0.0    ->   64.0 0.0
tr | 16.0 0.0         80.0 0.0
br | 16.0 24.0        80.0 24.0

En aras de la exhaustividad aquí está la matriz real correspondiente a los movimientos anteriores:

      x     y    z   w   r   g   b   a      s          t
-------------------------------------------------------------
tl | 0.0   23.0 0.0 1.0 0.0 0.0 0.0 1.0 0.14210527 0.62650603 
bl | 0.0   0.0  0.0 1.0 0.0 0.0 0.0 1.0 0.14210527 0.76506025 
tr | 16.0  0.0  0.0 1.0 0.0 0.0 0.0 1.0 0.2263158  0.76506025 
br | 16.0  23.0 0.0 1.0 0.0 0.0 0.0 1.0 0.2263158  0.62650603 
-------------------------------------------------------------
-------------------------------------------------------------
tl | 64.0  24.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0        0.21084337 
bl | 64.0  0.0  0.0 1.0 0.0 0.0 0.0 1.0 0.0        0.3554217 
tr | 80.0  0.0  0.0 1.0 0.0 0.0 0.0 1.0 0.08421053 0.3554217 
br | 80.0  24.0 0.0 1.0 0.0 0.0 0.0 1.0 0.08421053 0.21084337

// side bar: I know that I have unnecessary data with having a z-axis.
//           The engine flips between perspective and orthogonal and I
//           haven't selectively started pruning data.

Matriz de proyección

La matriz de proyección para la ventana 512x448 se ve así:

0.00390625 0.0         0.0  0.0
0.0        0.004464286 0.0  0.0
0.0        0.0        -1.0  0.0
0.0        0.0         0.0  1.0

y está construido con una función de proyección ortogonal de libro de texto:

ortho(-w/2.0f, w/2.0f, -h/2.0f, h/2.0f);
// explicitly: ortho(-512/2.0f, 512/2.0f, -448/2.0f, 448.0f

ortho(float left, float right, float bottom, float top)
{
    projection.setIdentity();
    projection.m00 = 2.0f / (right - left);
    projection.m11 = 2.0f / (top - bottom);
    projection.m22 = -1;
    projection.m30 = -(right + left) / (right - left);
    projection.m31 = -(top + bottom) / (top - bottom);
    projection.m32 = 0;
}

Matriz de visión del mundo

La posición de la cámara es solo una matriz de traducción que en este caso simplemente compensé con -w / 2 y -h / 2 para que sea cero en relación con el centro.

1.0 0.0 0.0 -256.0
0.0 1.0 0.0 -224.0
0.0 0.0 1.0 0.0
0.0 0.0 0.0 1.0

Soluciones que he intentado

  1. player.moveRight()se movería 1 unidad con la relación de aspecto factorizada en la ecuación. Por lo tanto: gridWidth = 64 / 1.14f. El movimiento no encajaba dentro de la cuadrícula.

  2. Forzó una ventana de 512x512 con una proyección ortogonal a juego.

  3. Intenté varios números mágicos e intenté establecer correlaciones entre los dos.

Dicho esto, todo lo que me queda por creer es que estoy mezclando mi proyección real. Por lo tanto, estoy buscando alguna idea para mantener la proyección 1: 1 de píxel a unidad mundial.

Justin Van Horne
fuente
55
Pregunta bien construida, pero tal vez podríamos ver su proyección y matrices mundiales. Los mencionaste anteriormente, pero no incluiste sus contenidos. El problema será con una de esas matrices.
Ken
@Ken No hay problema en absoluto. He agregado mi proyección y matrices de vista del espacio mundial. También he incluido mi salida deseada y mis propios intentos de resolver el problema.
Justin Van Horne
Ustedes matrices se ven bien (las comparé con las producidas por glOrtho y glTranslate. Aferrándose a las pajillas aquí, pero opengl espera que sus matrices estén ordenadas en orden de columnas, ¿está haciendo lo mismo?
Ken
Hm, se están almacenando en orden de columna mayor.
Justin Van Horne

Respuestas:

5

Resolví mi propio problema, y ​​en lugar de simplemente explicarlo como una explicación simple, quiero describir los pasos que tomé para depurar el problema. Dejé de lado que estaba usando un solo FBO para efectos especiales.

Primero, resulta que todo lo anterior es de hecho correcto y un paso que omití fue el problema.

  • Verifiqué mis matrices ortogonales de principio a fin.
  • Verificó el orden de bytes de todo.
  • Creó una textura cuadrada. <- Aquí está la magia
  • Cuando creé una textura cuadrada, noté que no era cuadrada en la pantalla, sino cuadrada al entrar en el sombreador de vértices.
  • Esta fue mi primera pista de que algo andaba mal. Las dimensiones de mis texturas en la pantalla no coincidían con las dimensiones que iban al sombreador de vértices.
  • Olvidé que estaba usando un FBO (aquí viene la tontería).
  • El tamaño de la textura FBO no coincidía con el tamaño de la textura de mi ventana gráfica por cualquier razón estúpida.
  • Inhabilitó el FBO y los resultados coincidieron.
  • Se corrigió la lógica con la definición de mi tamaño de textura y wah-lah.

Tontería

Lo siento si esto tomó el tiempo de alguien. Dejaré la pregunta como una buena medida para cualquiera que pueda tener el mismo problema sin saberlo.

Justin Van Horne
fuente