Duży bufor wierzchołków a wielokrotne wywołania losowania

14

Właśnie zaczynam pracę z OpenGL i próbuję go użyć do stworzenia gry 2D. W tej grze mam sześciokątną siatkę złożoną z bardzo dużej różnorodności różnokolorowych sześciokątów. Jako początkujący programista OpenGL widzę dwa sposoby rysowania tej siatki:

  1. Użycie bufora wierzchołków z danymi dla pojedynczego sześciokąta, następnie użycie jednolitej wartości przesunięcia i iteracja na CPU, aby narysować ten sam program wiele razy, aż będę miał siatkę.
  2. Tworzenie pojedynczego bardzo dużego wstępnie obliczonego bufora wierzchołków, który rysuje wszystkie sześciokąty w jednym wywołaniu.

Jaka jest najbardziej wydajna metoda? Czy jest na to lepszy sposób?

Alexis King
źródło
Twój wstępnie obliczony bufor wierzchołków musi tylko przejść poza ekran o jeden sześciokąt, możesz go następnie sfałszować, płynnie przewijając, aż przejdziesz do pełnego sześciokąta, a następnie „wypaczam” z powrotem, jak w przypadku kolorów w tym scenariuszu, możesz zachować Tekstury 2D na GPU, przeczytaj w module cieniującym wierzchołki i interpoluj je płasko w module cieniującym fragmenty.
MickLH,
Przepustki zwykle odnoszą się do sytuacji, w której jedna operacja renderowania opiera się na wynikach poprzedniej operacji. To, o co pytasz w tym pytaniu, w rzeczywistości wiąże się ze zmniejszeniem liczby połączeń losujących w ciągu jednego przejścia. Wiem, że to brzmi pedantycznie, ale bardzo ważne jest, aby zrozumieć różnicę, w przeciwnym razie algorytmy wieloprzebiegowe nie będą miały większego sensu;)
Andon M. Coleman,
@ AndonM.Coleman Hmm, dzięki, wyraźnie nie znam terminologii graficznej. Więc w tym przypadku, jak bym to opisał? Wiele wywołań programu cieniującego / programu?
Alexis King
Możesz natychmiast stwierdzić, że jest to algorytm jednoprzebiegowy, ponieważ nie ma zależności od kolejności; możesz narysować te sześciokąty w dowolnej kolejności i nadal uzyskać ten sam wynik. Możesz odebrać wiele wywołań losowania w celu dostarczenia OpenGL danych wymaganych do ich renderowania, ale OpenGL może skutecznie rysować je wszystkie równolegle, ponieważ nie ma żadnych zależności. Jeśli byłby wieloprzebiegowy , sześciokąt B może wymagać wyniku sześciokąta A, zanim będzie można go narysować, lub może być konieczne wielokrotne narysowanie tego samego sześciokąta i połączenie wyniku.
Andon M. Coleman,

Odpowiedzi:

9

Istnieje kilka sposobów na stworzenie takiej siatki.

Najbardziej efektywnym sposobem byłoby wystąpienie. W ten sposób wykonujesz swój sześciokąt tylko raz w VBO i renderujesz go sto, tysiąc lub milion razy. Możesz to zrobić ręcznie, używając shaderów z mundurami, jak wspomniano w punkcie 1, ale jest też wbudowana funkcja OpenGL. W tym celu spójrz na glDrawElementsInstanced .

Zauważ, że instancja jest szybsza niż inne metody, jeśli narysujesz więcej niż pewną liczbę instancji obiektów. Na przykład rysunek 300 może być szybszy przy użyciu 1 dużego VBO, ale rysunek 2 miliony może być szybszy, jeśli użyjesz renderowania instancji.

Jeśli używasz renderowania instancji, możesz wysyłać dane dla poszczególnych obiektów za pomocą dzielników atrybutów . W twoim przypadku chciałbyś wysłać pozycję i kolor.

Dobry samouczek dotyczący renderowania instancji: kliknij

Naprawdę najlepszym sposobem jest wypróbowanie obu metod i sprawdzenie ilości milisekund potrzebnych do narysowania 1 klatki. W ten sposób uczysz się także na dwa sposoby, co zawsze jest dobre.

Zauważ też, że renderowanie instancji jest nowoczesną funkcją OpenGL i że będziesz musiał użyć shaderów, aby z niego korzystać. Ale zawsze najlepiej jest nauczyć się tego od samego początku.

Basaa
źródło
2
Instancja niekoniecznie jest najbardziej wydajna; w wielu implementacjach, które widziałem profile, obsługa instancji była wprowadzana w celu zapewnienia zgodności, ale wolniej niż w przypadku indywidualnego rysowania wielu obiektów (w rzeczywistości była to prawdopodobnie tylko słabo zaimplementowana pętla w sterowniku, która właśnie to robi). Jest to opcja dobra i dobra, ale należy uważnie profilować i testować docelowy system operacyjny / sprzęt przed przyjęciem jakichkolwiek założeń dotyczących „najbardziej wydajnej”.
Sean Middleditch,
Zgoda. Widziałem na przykład różne wyniki w systemach Windows / Linux i Ati / nVidia. Dzięki za dodanie.
Basaa
1
W rzeczywistości. Jeśli narysujesz wiele połączonych siatek w ramach jednego vbo (które dzielą to samo miejsce). W żaden sposób instancja nie może być szybsza. Problem z wystąpieniem polega na tym, że wierzchołki nie są obliczonymi równolegle wystąpieniami krzyżowymi. To tylko eliminuje synchronizację / drawc GPU / CPU / GPU. Szybsze jest więc narysowanie jednego bufora wierzchołków zawierającego 1000 kulek niż narysowanie 1000 kulek za pomocą instancji sprzętowej. (nie wymaga zbijania fragmentów / optymalizacji szczegółów odległości od obiektu)
Jeroen van Langen
3

Metoda 1 jest łatwiejsza do kodowania i będzie w porządku, o ile nie będzie widocznych zbyt wielu sześciokątów na raz. Możesz trzymać się tego, ponieważ jesteś nowy w OpenGL, aby uniknąć nadmiernego komplikowania na raz.

Jeśli widoczna jest jednocześnie duża liczba sześciokątów (na przykład kilkaset lub ponad tysiąc), konieczne byłoby zastosowanie metody niższego obciążenia, aby uniknąć obciążenia procesora tak wieloma pojedynczymi losowaniami. Metoda 2 zadziałałaby w przypadku tego, a nawet lepiej, użycia instancji. Spodziewałbym się, że instancja będzie szybsza niż metoda 2, a na pewno nie gorsza, ponieważ wystarczy zaktualizować bufor danych dla poszczególnych instancji zamiast (znacznie większego) bufora danych wierzchołków dla wszystkich instancji.

Nathan Reed
źródło