2010-12-13 15 views
5

Ludzie ciągle mówią mi, żebym używał przynajmniej tablic wierzchołków. Ale myślę, że nie jest to dobry pomysł, ponieważ używam glPushMatrix() z glTranslatef/glRotatef do pozycjonowania obiektu w świecie 3d.OpenGL: Jak zaprojektować wydajny system renderowania za pomocą tablic vertex z sortowaniem głębokości?

Więc, powinienem przestać używać i obliczyć obrócone/przesunięte pozycje wierzchołków w świecie "ręcznie", a następnie wypchnąć ich dane werteksów do tablicy wierzchołków, a następnie renderować je wszystkie naraz?

Ale wszystko to jeszcze bardziej popsuje się, gdy używam różnych powierzchni teksturowych dla wszystkich obiektów na ekranie, które są również sortowane głębiej.

Więc:

  1. musiałbym zapisać każdy obiekt z identyfikatorem teksturę powierzchni, jak również.
  2. Służy do sortowania wszystkich widocznych obiektów po ich pozycji Z (gra jest wyświetlana tylko z góry na dół, a wszystkie obiekty są płaskie).
  3. chciałbym przejść przez ten posortowanej tablicy:
  4. Utwórz nowy bufor i skopiować tylko wierzchołek/texcoord/kolor/normalny do tego bufora:
  5. Za każdym razem identyfikator tekstury powierzchnia uległa zmianie od poprzedniego ID, będzie wiążę do poprawnego tekstury ID:
  6. Prześlij zebrane dane wierzchołków.
  7. Uwolnij bufor używany do tymczasowej tablicy wierzchołków.
  8. Powtarzaj kroki 4-7, aż przejdę przez wszystkie dane posortowane na pierwszym miejscu.
  9. Uwolnij moje posortowane dane z tablicy i powtórz kroki 1-9.

Czy robię to dobrze?

Ponadto, jak powinienem zaprojektować strukturę danych dla obiektów, które posortuję? Na przykład, czy dobrze jest użyć std::vector do przechowywania danych wierzchołków dla każdego obiektu? Czy istnieje lepsza alternatywa? Myślałam, że std::vector przechowywać wszystkie te dane będą wyglądać następująco:

struct GameObject { 
    int TexID; 
    float z; // we will sort by this 
    vector<VTCNStruct> VertexData; // store each point of the object here (including color/normal/texcoord points). 
}; 

vector<GameObject> GameObjectBuffer; // push all sortable objects here 

Również w kroku 4: czy jest to możliwe do wykorzystania już istniejącego std::vector w tym przypadku? Wpadłem na pomysł, że muszę używać surowych tablic, takich jak new float[100] do wysyłania tablicy wierzchołków do mojego GPU, lub czy w jakiś sposób mogę użyć mojego już sortowanego std::vector tutaj (wydajnie) bez tworzenia nowego bufora za każdym razem, gdy zmienia się ID tekstury ?

Odpowiedz

2

Powinieneś przechowywać jedną tablicę punktów na obiekt. Nie używaj glTranslatef/glRotatef, itp. Zamiast tego zwiń przekształcenia samodzielnie w jedną macierz. Użyj tej macierzy do dokładnego sortowania obiektów. Następnie narysuj obiekty od przodu do tyłu, naciskając macierz transformacji obiektów, rysując tablicę wierzchołków, a następnie otwierając macierz transformacji.

Takie podejście oznacza, że ​​nie są stale tworzenia i uwalniając tablic do przechowywania danych wierzchołków w.

Jak do korzystania z std :: vector, większość implementacji użyć surowego C tablicę wewnątrz, co można zrobić & myVec [0], aby dostać się do tej tablicy. Jednak nie próbuj utrzymywać tego wskaźnika, ponieważ std :: vector może zmienić ponownie tablicę, a następnie utrwalony wskaźnik przestanie być poprawny.

+0

"Należy zachować jedną tablicę wierzchołków za obiekt" - jest to mądry w ogóle? ponieważ większość moich obiektów to po prostu quady, a to nie wykorzystuje większej przepustowości teraz, kiedy nie tylko wysyłam więcej danych do GPU (w postaci kolorów/normalnych tablic), ale także musiałbym wysyłać polecenia wysyłania tablicy wierzchołków pomiędzy każdym obiektem . – Newbie

+0

Jak zawalić moje transformacje w jedną macierz? Co więcej, nie masz na myśli, od tyłu do przodu? Więc zasadniczo sugerujesz, że zachowam 'glPushMatrix()', ale zamiast 'glBegin/glEnd' używałbym tablic wierzchołków? JEŚLI CHCEMY SIĘ użyć VBO, czy powinienem zachować to samo podejście, które zasugerowałeś? – Newbie

+0

Nowicjusz - nie jestem programistą OpenGL, ale uważam, że Josh oznacza, że ​​najpierw należy przesunąć obiekty znajdujące się najwyżej (na przykład w szafie na ekranie), najdalej na końcu. EDYCJA - Po zwijaniu przekształca się w jedną macierz, wierzę, że można użyć sztuczek matematycznych, aby uzyskać jedną transformację zarówno do poruszania/obracania/etc. za jednym zamachem. – ZachS

11

Pleae porzuć glBegin/glEnd teraz, jest przestarzałe i zostało usunięte z OpenGL-4. Powinieneś zdecydowanie używać tablic wierzchołków, nawet lepiej, jeśli korzystasz z obiektów bufora wierzchołków.

W trybie natychmiastowym (glBegin/glEnd) sterownik OpenGL musi zbudować tablicę wierzchołków z wywołań funkcji. Ponieważ nie jest jasne, ile dojdzie do pojawienia się pionków, w końcu ponownie przydzielą pamięć wiele razy (czasy, w których procesory graficzne bezpośrednio wykonują połączenia między glBegin/glEnd są już dawno zakończone).

Korzystanie z tablicy wierzchołków nigdy nie będzie mniej wydajne niż tryb natychmiastowy. Można umieścić geometrię wielu obiektów w jednej tablicy wierzchołków, można je rozdzielić za pomocą list indeksu wierzchołków. Listy indeksu Vertex mogą być również przechowywane w obiektach buforowych.

Następnie między rysowaniem obiektów dopasuj matrycę widoku modelu.

kolejność sortowania powinna być jak followig:

  1. podzielić na nieprzezroczystych i przezroczystych obiektów. Sortowanie nieprzezroczystego
  2. Sortowanie obiektów przez obiekty GL (teksturę, cieniowanie, materiały itp.), Ponieważ przełączanie obiektów GL jest najdroższe.
  3. dla każdej odrębnej grupy obiektów GL sortowania blisko daleko i wyciągnąć w tej kolejności
  4. Sortuj Translucents największej do najmniejszej i wyciągnąć w tej kolejności

Nie należy próbować błahy wokół buforem górę/Downloads. Po prostu prześlij dane wierzchołków, a następnie dostosuj tablice indeksów i kolejność ich przesyłania. Nie musisz martwić się o dostępną pamięć OpenGL, nie ma ograniczeń. Jeśli twoje dane nie pasują do pamięci RAM GPU, sterownik jest odpowiedzialny za zamianę jej na pamięć systemową - dlatego też najpierw należy sortować według obiektów OpenGL, ponieważ za każdym razem, gdy przełączasz obiekty OpenGL (glBindTexture, glBindBuffer itp.), Sterownik może trzeba zamienić, więc chcesz ograniczyć te operacje wymiany do minimum. Ilość danych wysyłanych do GPU w postaci tablic indeks będzie znacznie mniej, niż to, co jest wysyłane przez trybie natychmiastowym wymaga co najmniej:

  • tablica Index: 16 bit na wierzchołku (16 indeksy wielkości bitowe są najbardziej wykonawca).

  • Natychmiastowe wezwanie mode: 4 * 32 bit na wierzchołku

+0

'Tablica indeksów: 16 bitów na wierzchołek' VS. Wywołanie trybu natychmiastowego: 4 * 32 bity na wierzchołek "Czy nie ma błędu w obliczeniach, ponieważ w przypadku macierzy wierzchołków trzeba również wysłać dane wierzchołków.Powiedzmy, że wysyłam glVertex3f (1,1,1) zajmie 3 * 32 bit + 32bit dla adresu funkcji? ale z tablicami wierzchołków, muszę również wysłać x, y, z, który zajmuje 3 * 32 bit + indeks, który zajmuje 16 bitów, łącznie zapisane bity = 16? A może tęskniłem? O ile wiem, nie możesz przechowywać macierzy wierzchołków w GPU, więc musisz wysyłać dane werteksów raz na jakiś czas, nawet jeśli to się nie zmieniło ...? – Newbie

+0

Użycie tablic wierzchołków obiektów Vertex Object Point jest rzeczywiście przechowywane w pamięci GPU. Bez użycia VBO wyraźnie większość współczesnych kierowców ma tendencję do tworzenia ich na miejscu, ponieważ tak działają współczesne układy GPU. – datenwolf

+0

in-situ? co masz na myśli, że nowoczesne GPU przekształca wszystkie tablice wertykalne w VBO automatycznie? – Newbie

Powiązane problemy