Inadéquation de la traduction des unités orthographiques sur la grille (par exemple, 64 pixels ne se traduisent pas correctement)

14

Je cherche un aperçu d'un petit problème avec les traductions d'unité sur une grille.

Mise à jour et résolu

J'ai résolu mon propre problème. Voir ci-dessous pour plus de détails. Tout dans cette partie du post s'est avéré être correct. Si quoi que ce soit, il peut servir de tutoriel / exemple / aide miniature pour la prochaine personne.

Installer

  • FBO, VAO, VBO
  • Fenêtre 512x448
  • Grille 64x64
  • gl_Position = projection * world * position;
  • projectionest défini par ortho(-w/2.0f, w/2.0f, -h/2.0f, h/2.0f);Ceci est une fonction de projection orthogonale classique.
  • world est défini par une position fixe de la caméra à (0, 0)
  • position est défini par la position du sprite.

Problème

Dans la capture d'écran ci-dessous (échelle 1: 1), l'espacement de la grille est de 64x64 et je dessine l'unité à (64, 64), mais l'unité dessine environ ~ 10px dans la mauvaise position. J'ai essayé des dimensions de fenêtre uniformes pour éviter toute distorsion sur la taille des pixels, mais maintenant je suis un peu perdu de la bonne façon en fournissant une projection de 1: 1 pixel à unité mondiale. Quoi qu'il en soit, voici quelques images rapides pour aider à résoudre le problème.

Tuiles 64x64 sur une fenêtre 512x448

J'ai décidé de super-imposer un tas de sprites à ce que le moteur croit être des décalages 64x.

64 décalages superposés

Lorsque cela semblait hors de propos, je me suis déplacé et j'ai fait le cas de base d'une unité. Ce qui semblait s'aligner comme prévu. Le jaune montre une différence de 1px dans le mouvement.

Cas de base de 1 unité

Ce que je veux

Idéalement, le déplacement dans n'importe quelle direction 64 unités produirait les éléments suivants (unités superposées):

Sortie désirée

Sommets

Il semblerait que les sommets entrant dans le vertex shader soient corrects. Par exemple, en référence à la première image, les données ressemblent à ceci dans le 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

Par souci d'exhaustivité, voici le tableau réel correspondant aux mouvements ci-dessus:

      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.

Matrice de projection

La matrice de projection pour la fenêtre 512x448 ressemble à ceci:

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

et est construit avec une fonction de projection orthogonale classique:

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;
}

Matrice de vision du monde

La position de la caméra n'est qu'une matrice de translation que dans ce cas je viens de décaler de -w / 2 et -h / 2 pour être nulle par rapport au centre.

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

Solutions que j'ai essayées

  1. player.moveRight()déplacerait 1 unité avec le rapport d'aspect pris en compte dans l'équation. Donc: gridWidth = 64 / 1.14f. Le mouvement ne rentre pas dans la grille.

  2. Forcé une fenêtre 512x512 avec une projection orthogonale correspondante.

  3. J'ai essayé différents nombres magiques et essayé de faire des corrélations entre les deux.

Cela dit, tout ce qu'il me reste à croire, c'est que je munging ma projection réelle. Donc, je cherche des informations sur le maintien de la projection 1: 1 pixel-à-monde.

Justin Van Horne
la source
5
Question bien construite, mais peut-être pourrions-nous voir vos matrices de projection et de monde. Vous les avez mentionnés ci-dessus, mais vous n'avez pas inclus leur contenu. Le problème sera avec l'une de ces matrices.
Ken
@Ken Aucun problème. J'ai ajouté mes matrices de projection et de vision du monde. J'ai également inclus la sortie souhaitée et mes propres tentatives de résolution du problème.
Justin Van Horne
Vos matrices ont l'air bien (je les ai comparées à celles produites par glOrtho et glTranslate. Grapsing aux pailles ici, mais opengl s'attend à ce que ses matrices soient disposées dans l'ordre des colonnes, faites-vous la même chose?
Ken
Hm, ils sont stockés dans l'ordre des colonnes.
Justin Van Horne

Réponses:

5

J'ai résolu mon propre problème - et plutôt que de simplement l'exploser comme une explication simple, je veux décrire les étapes que j'ai prises pour déboguer le problème. J'ai omis d'utiliser un seul FBO pour les effets spéciaux.

Tout d'abord, il s'avère que tout ce qui précède est en fait correct et une étape que j'ai laissée de côté était le problème.

  • J'ai vérifié mes matrices orthogonales de part en part.
  • Vérifié l'ordre des octets de tout.
  • Créé une texture carrée. <- Voici la magie
  • Lorsque j'ai créé une texture carrée, j'ai remarqué qu'elle n'était pas carrée à l'écran, mais carrée dans le vertex shader.
  • C'était mon premier indice que quelque chose n'allait pas. Les dimensions de mes textures à l'écran ne correspondaient pas aux dimensions qui allaient au vertex shader.
  • J'ai oublié que j'utilisais un FBO (voici la bêtise).
  • La taille de texture FBO ne correspondait pas à la taille de texture de ma fenêtre pour une raison stupide.
  • Désactivé le FBO et les résultats correspondent.
  • Correction de la logique avec la définition de ma taille de texture et de wah-lah.

Sillyness

Je suis désolé si cela a pris du temps à qui que ce soit. Je vais laisser la question autour comme une bonne mesure pour toute personne qui pourrait rencontrer le même problème sans le savoir.

Justin Van Horne
la source