Z góry
Ok, więc zebrałem do tej pory:
- nie używaj stałego potoku (przestarzałe lub będzie przestarzałe)
- vbos przechowują „modele obiektowe” (głównie n danych danych wierzchołków)
- vaos opisują, jak układane są dane, aby rysowanie wywołań wiedziało, jaka część każdego vbo jest dla jakiego rodzaju informacji o wierzchołku (jedno vao może odnosić się do wielu vbos, przeciwnie jest trochę trudne)
- każde wywołanie losowania wysyła również dane wierzchołków do shaderów
Jak widzę 3D (opcjonalnie)
Biorąc pod uwagę te informacje, widzę, jak rysowanie skomplikowanych obiektów 3D jest bardzo przyjemne w nowoczesnym OpenGL. Zasadniczo ładujesz kilka modeli obiektów (prawdopodobnie z Blendera lub innego podobnego oprogramowania) do VBO z lokalnymi współrzędnymi, a następnie po prostu podajesz dla każdego wystąpienia obiektu inny parametr shadera (przesunięcie), aby rysować w przestrzeni świata.
Problem / pytanie
W 2D problemy i priorytety są jednak zupełnie inne. Nie rysujesz zbyt skomplikowanych obiektów, nie potrzebujesz skomplikowanych matryc projekcyjnych, a whatnot i shadery są znacznie prostsze.
Jaki byłby najlepszy sposób rysowania często (naprawdę często, zasadniczo każdej ramki) zmieniającej się geometrii za pomocą nowoczesnego OpenGL?
W następnym akapicie możesz zobaczyć kilka pomysłów na problemy (problem z okręgiem i prostokątem), które lepiej identyfikują zmiany, którymi jestem zainteresowany.
Moje próby (opcjonalnie)
Zacząłem więc zastanawiać się, jak poradzić sobie z rysowaniem podstawowej geometrii 2D na ekranie:
- kwadrat: załaduj
[(1, 0), (1, 1), (0, 1), (0, 0)]
VBO dla geometrii kwadratu w przestrzeni lokalnej, a następnie podaj modułowi cieniującemu rzeczywistą szerokość kwadratu oraz współrzędne świata i informacje o kolorze
chłodzi, wygląda łatwo. Przejdźmy do kręgu:
- koło: wachlarz trójkąta z ... eh. ile precyzji (liczba wierzchołków)? dla małych kół precyzja musi być mała, a dla błędnych kół precyzja musi być wysoka. Wyraźne załadowanie 1 VBO prawdopodobnie nie pasuje do wszystkich przypadków. Co się stanie, jeśli będę musiał dodać precyzję, ponieważ rozmiar okręgu jest większy?
Mniej fajne. Przejdźmy do czegoś nieco prostszego, prostokąta:
- prostokąt: eh. nie ma „ogólnej geometrii prostokąta”. Po prostu masz proporcje szerokość / wysokość i to wszystko, ale każdy prostokąt jest prawdopodobnie inny, jeśli zmienia się rozmiar.
Jak widać, stamtąd wszystko idzie w dół. Zwłaszcza ze złożonymi wielokątami i tak dalej.
Brak zasad kodu: P
Potrzebuję tylko przeglądu tego pomysłu, nie jest potrzebny żaden kod, zwłaszcza kod C lub C ++. Po prostu powiedz coś takiego: „utwórz VBO z tymi danymi wierzchołków, a następnie powiąż go, ...”.
Odpowiedzi:
Twoim głównym pytaniem wydaje się:
W większości przypadków nie ma dużej różnicy między 2d a 3d OpenGL. Rurociąg graficzny ma jedną dodatkową współrzędną Z, która nie będzie używana tak często w 2D, ale o to chodzi.
Istnieje kilka sposobów zmiany geometrii przy każdym losowaniu.
Możesz przesuwać nowe wierzchołki dostarczone przez CPU w każdej ramce. (Zobacz /programming/14155615/opengl-updating-vertex-buffer-with-glbufferdata, aby uzyskać uwagi na temat ponownego użycia buforów.)
Możesz narysować różne części istniejącego bufora za pomocą
glDrawArrays(mode, first, count)
. Jeśli animacja zapętla się, być może możesz umieścić wstępnie obliczone klatki z różnymi listami wierzchołków w jednym dużym buforze i narysować odpowiednią część bufora dla każdej klatki.Możesz wpływać na listę wierzchołków za pomocą innych danych, takich jak jednolita tablica lub tekstura. W shaderze wierzchołków przeczytaj te dane i zastosuj je odpowiednio. To tylko inne idiomy do prezentacji danych na GPU i prawdopodobnie nie będą miały dużej różnicy w wydajności.
Jeśli masz wiele wystąpień o tej samej geometrii (prawdopodobnie pod wpływem atrybutów),
glDrawElementsInstanced()
może to być przydatneMożesz algorytmicznie wpływać na listę wierzchołków w modułach cieniujących wierzchołki, geometrię lub teselację. Jeśli animację można opisać matematycznie, być może uda Ci się zachować tę samą listę wierzchołków i zmienić tylko kilka mundurów modułu cieniującego w każdej klatce.
Być może twoja animacja może być wyrażona jako czyste tekstury, a wszystkie animacje są wykonywane piksel po pikselu przez procesor lub wstępnie renderowane z dysku.
Ogólnie rzecz biorąc, powiedziałbym: „Komputery są szybkie, spraw, aby działało to najłatwiej, jak to możliwe, prawdopodobnie poprzez ustawienie w każdej klatce świeżych wierzchołków wykonanych przez procesor. Następnie sprawdź, czy to wystarcza. Profil użycia baterii / procesora po pierwsze, ślad po pamięci ”.
Twoje drugie pytanie , sparafrazowane: „Jaki jest dobry sposób rysowania okręgów i prostokątów?”
Koła
Z shaderów teselacji (lub shaderów geometrycznych), które mogłyby dokonać geometria dynamiczna.
Możesz rysować kwadraty, a w module cieniującym fragmenty tylko nieprzezroczyste (alfa = 1,0) w promieniu i przezroczyste (alfa = 0,0) poza promieniem. Wtedy za każdym razem jest idealnie pikselowy. (Ustaw kwadratowe wierzchołki od -1 do +1, a w shaderze fragmentów coś w stylu:.
outColor.a = dot(coord.xy, coord.xy) < 1.0 ? 1.0 : 0.0;
Może również nieco wygładzić krawędź, wyglądałby tam ładnie ...)Zawsze możesz użyć, powiedzmy, wentylatora 120-trójkątnego. Prawdopodobnie wystarczająco dobry.
Prostokąty
źródło
Nie mogę powiedzieć, że jestem ekspertem w tej dziedzinie, aw swoich projektach gry bardziej skoncentrowałem się na stronie 3D, więc moja strona 2D jest dość prosta, ogólnie rzecz biorąc, używając rzeczy stworzonych dla strony 3D; i oczywiście moja perspektywa jest po stronie gier, więc moja grafika 2D bardziej dotyczy blitowania duszków niż geometrii. Z tej perspektywy
1) Kwadraty i prostokąty są dość łatwe. Mam tylko jedno pudełko 1x1 w VBO, którego używam do blitowania wszystkiego. Przekazuję macierze MVP do modułu cieniującego za pomocą tego „pola jednostki” i połączyłem go z dodatkowym skalowaniem, aby przeskalować pole do odpowiednich wymiarów - jak wiesz, możesz mieć inną skalę xiy.
Dla moich celów zastanawiałem się nad przejściem z „skrzynki jednostkowej” na silnik cząsteczek, aby połączyć duszki 2D, ale to już inna historia.
2) Nie pracowałem dużo z okręgami, po prostu używam stałych VBO z określoną liczbą wierzchołków. Ale mogłem sobie wyobrazić, że mógłbym zrobić pewne postępy, aby wpłynąć na liczbę wierzchołków narysowanych dla koła.
Podczas łączenia danych VBO z atrybutami modułu cieniującego używam glVertexAttribPointer. Ma parametr kroku przeznaczony do przeplatania danych (których używam). Ale może być możliwe użycie go w następujący sposób:
... aby wybrać co n-ty wierzchołek z bufora, wpływając w ten sposób na liczbę wierzchołków narysowanych dla koła. Mógłbym stworzyć kilka VAO o tym samym VBO z różnym krokiem wpływającym na liczbę wierzchołków narysowanych dla okręgu. Nie próbowałem tego, pomyślałem.
Ogólnie rzecz biorąc, tak, praca z VBO i takie sprawiają, że podkręcanie po stronie procesora jest nieco bardziej skomplikowane, dlatego badałem różne rzeczy, aby ulepszyć po stronie GPU (shadery). Jednak zgodnie z tym artykułem korzystanie z VBO jest bardziej wydajne na nowoczesnym sprzęcie, nawet jeśli potrzebujesz dużo „interwencji” po stronie procesora:
http://www.quelsolaar.com/opengl_performance.txt
Mam nadzieję, że to pomoże ci trochę zaprojektować i zdecydować o twoich kierunkach.
źródło