Incompatibilidade de conversão de unidade ortográfica na grade (por exemplo, conversão de 64 pixels incorretamente)

14

Estou procurando algumas dicas sobre um pequeno problema com traduções de unidades em uma grade.

Atualização e solução

Eu resolvi meu próprio problema. Veja abaixo para detalhes. Tudo nesta parte da postagem estava correto. Se alguma coisa pode funcionar como um tutorial em miniatura / exemplo / ajuda para a próxima pessoa.

Configuração

  • FBO, VAO, VBO
  • Janela de 512x448
  • Grade 64x64
  • gl_Position = projection * world * position;
  • projectioné definido por ortho(-w/2.0f, w/2.0f, -h/2.0f, h/2.0f);Esta é uma função de projeção ortogonal do livro.
  • world é definido por uma posição fixa da câmera em (0, 0)
  • position é definido pela posição do sprite.

Problema

Na captura de tela abaixo (escala 1: 1), o espaçamento da grade é 64x64 e estou desenhando a unidade em (64, 64); no entanto, a unidade desenha aproximadamente ~ 10px na posição errada. Tentei dimensões uniformes da janela para evitar distorções no tamanho do pixel, mas agora estou um pouco perdido da maneira correta ao fornecer uma projeção de 1: 1 pixel para a unidade mundial. De qualquer forma, aqui estão algumas imagens rápidas para ajudar no problema.

Ladrilhos de 64x64 em uma janela de 512x448

Decidi super-impor um monte de sprites ao que o mecanismo acredita serem compensações de 64x.

64 compensações superimpostas

Quando isso parecia fora de lugar, eu fui e fiz o caso base de 1 unidade. O que parecia alinhar como esperado. O amarelo mostra uma diferença de 1px no movimento.

Caixa base de 1 unidade

O que eu quero

O movimento ideal em qualquer direção de 64 unidades produziria o seguinte (unidades superimpostas):

Saída desejada

Vértices

Parece que os vértices que entram no sombreador de vértices estão corretos. Por exemplo, em referência à primeira imagem, os dados são assim no 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

Por uma questão de completude, aqui está a matriz real correspondente aos movimentos acima:

      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 projeção

A matriz de projeção para a janela de 512x448 é assim:

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

e é construído com uma função de projeção ortogonal do livro:

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 visão de mundo

A posição da câmera é apenas uma matriz de translação que, neste caso, apenas compenso por -w / 2 e -h / 2 como zero em relação ao 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

Soluções que tentei

  1. player.moveRight()moveria 1 unidade com a relação de aspecto fatorada na equação. Assim: gridWidth = 64 / 1.14f. O movimento não se encaixava na grade.

  2. Forçou uma janela de 512x512 com uma projeção ortogonal correspondente.

  3. Tentei vários números mágicos e tentei correlacionar os dois.

Com isso dito, tudo que me resta a acreditar é que estou alterando minha projeção real. Portanto, estou procurando qualquer insight sobre como manter a projeção 1: 1 de pixel para unidade mundial.

Justin Van Horne
fonte
5
Pergunta bem construída, mas talvez pudéssemos ver sua projeção e matrizes mundiais. Você os mencionou acima, mas não incluiu o conteúdo deles. O problema será com uma dessas matrizes.
Ken
@ Ken Não há problema algum. Adicionei minhas matrizes de projeção e visão do espaço mundial. Também incluí minha saída desejada e minhas próprias tentativas de resolver o problema.
Justin Van Horne
Você matrizes olhar bom (I comparou-os produz por glOrtho e glTranslate Grapsing em palhas aqui, mas opengl espera que suas matrizes para dispostos em ordem coluna-major, você está fazendo o mesmo.?
Ken
Hm, eles estão sendo armazenados na ordem principal da coluna.
Justin Van Horne

Respostas:

5

Solucionei meu próprio problema - e, em vez de apenas expor uma explicação simples, quero descrever as etapas que eu tomei para depurar o problema. Eu deixei de fora que estava usando um único FBO para efeitos especiais.

Primeiro, acontece que tudo acima está de fato correto e um passo que deixei de fora foi o problema.

  • Eu verifiquei minhas matrizes ortogonais completamente.
  • Verificou a ordem dos bytes de tudo.
  • Criou uma textura quadrada. <- Aqui está a mágica
  • Quando criei uma textura quadrada, notei que não era quadrada na tela, mas sim entrando no shader de vértice.
  • Esta foi a minha primeira pista de que algo estava errado. As dimensões das minhas texturas na tela não correspondiam às dimensões que estavam indo para o shader de vértice.
  • Eu esqueci que estava usando um FBO (aqui vem a bobagem).
  • O tamanho da textura do FBO não corresponde ao tamanho da textura da janela de visualização por qualquer motivo estúpido.
  • Desabilitou o FBO e os resultados foram correspondentes.
  • Corrigida a lógica com a definição do tamanho da minha textura e wah-lah.

Sillyness

Lamento se isso levou o tempo de alguém. Deixarei a pergunta em torno de uma boa medida para qualquer um que possa ter o mesmo problema sem saber.

Justin Van Horne
fonte