Niezgodność translacji jednostek ortograficznych na siatce (np. 64 piksele tłumaczą niepoprawnie)

14

Szukam wglądu w mały problem z tłumaczeniami jednostkowymi na siatce.

Aktualizacja i rozwiązanie

Rozwiązałem własny problem. Szczegóły poniżej. Wszystko w tej części postu okazało się prawidłowe. Jeśli tak, może działać jako miniaturowy samouczek / przykład / pomoc dla następnej osoby.

Ustawiać

  • FBO, VAO, VBO
  • Okno 512x448
  • Siatka 64x64
  • gl_Position = projection * world * position;
  • projectionjest zdefiniowany przez ortho(-w/2.0f, w/2.0f, -h/2.0f, h/2.0f);To jest podręcznikowa funkcja projekcji ortogonalnej.
  • world jest zdefiniowany przez stałą pozycję kamery w (0, 0)
  • position jest zdefiniowany przez pozycję duszka.

Problem

Na poniższym zrzucie ekranu (skalowanie 1: 1) odstępy siatki wynoszą 64 x 64, a ja rysuję jednostkę w (64, 64), jednak jednostka rysuje w przybliżeniu ~ 10px w niewłaściwej pozycji. Próbowałem ujednolicić wymiary okna, aby zapobiec zniekształceniu rozmiaru piksela, ale teraz jestem trochę zagubiony we właściwy sposób, zapewniając projekcję 1: 1 piksel na jednostkę świata. Tak czy inaczej, oto kilka krótkich zdjęć, które mogą pomóc w rozwiązaniu problemu.

Kafelki 64x64 w oknie 512x448

Zdecydowałem się narzucić kilka duszków według tego, co silnik uważa za przesunięcie 64x.

64 nałożone nałożone na siebie

Kiedy wydawało się to nie na miejscu, poszedłem i zrobiłem podstawową skrzynkę z 1 jednostką. Które wydawało się zgodne z oczekiwaniami. Żółty pokazuje różnicę 1px w ruchu.

Podstawa 1 jednostki

Czego chcę

Idealnie poruszając się w dowolnym kierunku 64 jednostki wygenerowałyby następujące (jednostki nałożone):

Pożądane wyjście

Wierzchołki

Wydaje się, że wierzchołki wchodzące w moduł cieniujący wierzchołki są poprawne. Na przykład w odniesieniu do pierwszego obrazu dane w VBO wyglądają tak:

      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

Dla kompletności tutaj jest rzeczywista tablica odpowiadająca powyższym ruchom:

      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.

Matryca projekcyjna

Macierz projekcji dla okna 512x448 wygląda następująco:

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

i jest zbudowany z podręcznej funkcji projekcji ortogonalnej:

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

Matryca światopoglądu

Pozycja kamery jest tylko macierzą translacji, która w tym przypadku po prostu przesunęła się o -w / 2 i -h / 2, aby była równa zero względem środka.

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

Rozwiązania, które próbowałem

  1. player.moveRight()przesuwałby się o 1 jednostkę przy uwzględnionym współczynniku kształtu w równaniu. Tak: gridWidth = 64 / 1.14f. Ruch nie mieścił się w siatce.

  2. Wymuszono okno 512x512 z pasującym rzutem ortogonalnym.

  3. Próbowałem różnych magicznych liczb i próbowałem narysować korelacje między nimi.

Powiedziawszy to, pozostało mi tylko wierzyć, że wzmacniam moją rzeczywistą projekcję. Tak więc szukam jakiegokolwiek wglądu w utrzymywanie projekcji piksel na jednostkę świata 1: 1.

Justin Van Horne
źródło
5
Dobrze skonstruowane pytanie, ale może moglibyśmy zobaczyć twoje macierze projekcji i świata. Wspomniałeś o nich powyżej, ale nie uwzględniłeś ich treści. Problem będzie związany z jedną z tych matryc.
Ken
@ Ken W ogóle nie ma problemu. Dodałem matryce do rzutowania i widoku przestrzeni kosmicznej. Podałem również pożądaną wydajność i własne próby rozwiązania problemu.
Justin Van Horne
Twoje macierze wyglądają dobrze (porównałem je z tymi produkowanymi przez glOrtho i glTranslate. Grapując tutaj na słomkach, ale Opengl oczekuje, że ich matryce ułożą się w porządku według kolumny, czy robisz to samo?
Ken
Hm, są przechowywane w porządku głównym kolumny.
Justin Van Horne

Odpowiedzi:

5

Rozwiązałem swój własny problem - zamiast opisywać go jako proste wyjaśnienie, chcę opisać kroki, które podjąłem, aby rozwiązać problem. Pominąłem, że korzystałem z jednego FBO do efektów specjalnych.

Po pierwsze, okazuje się, że wszystko powyżej jest w rzeczywistości poprawne, a problemem był krok, który pominąłem.

  • Weryfikowałem moje ortogonalne matryce na wskroś.
  • Zweryfikowano kolejność bajtów wszystkiego.
  • Utworzono kwadratową teksturę. <- Oto magia
  • Kiedy stworzyłem kwadratową teksturę, zauważyłem, że nie była kwadratowa na ekranie, ale kwadratowa wchodząca w moduł cieniujący wierzchołki.
  • To była moja pierwsza wskazówka, że ​​coś jest nie tak. Wymiary moich tekstur na ekranie nie pasowały do ​​wymiarów, które były skierowane do modułu cieniującego wierzchołki.
  • Zapomniałem, że używałem FBO (tutaj pojawia się głupota).
  • Rozmiar tekstury FBO nie zgadzał się z moim rozmiarem tekstury z jakiegokolwiek głupiego powodu.
  • Wyłączono FBO i wyniki się zgadzały.
  • Naprawiono logikę definiowania mojego rozmiaru tekstury i wah-lah.

Głupota

Przykro mi, jeśli zajęło to komuś czas. Pozostawię to pytanie jako dobrą miarę dla każdego, kto może napotkać ten sam problem, nie wiedząc o tym.

Justin Van Horne
źródło