Pytanie dot. "filozofii" OpenGL

0

Witam wszystkich.

Mam pewne pytanie dotyczące... powiedzmy, że sposobu działania OpenGL.

Programowaniem zajmuję się od dawna, natomiast jakoś wcześniej nigdy nie miałem ani potrzeby, ani ochoty ruszać tematów związanych z grafiką. (Nie)stety tak się złożyło, że muszę obecnie napisać coś z użyciem OpenGL - stąd mój post.

Ogólnie sobie radzę z tematem, ogarniam rysowanie, określanie bryły obcinania, skalowanie itp, ale zastanawia mnie jedna rzecz - i właśnie o opinię w tej sprawie chciałem Was prosić.

Zawsze wcześniej (zanim zacząłem wgryzać się w szczegóły GL'a) byłem przekonany, że (pisząc w dużym uproszczeniu) korzystanie z OpenGL'a wygląda mniej-więcej tak:

  1. opisuję "coś", co chcę narysować - np.dom. Określam wierzchołki tworzące powierzchnie, podaję ich kolory, nakładam tekstury itp.
  2. OpenGL sobie "pamięta" to, co ja narysowałem
  3. Wszelkie animacje (przesunięcia, przybliżenia, rotacje itp.) są wykonywane bez ponownego rysowania modelu - po prostu daję polecenie, że teraz proszę przesunąć "kamerę" o 50 jednostek w lewo albo wykonać obrót w pionie o 30 stopni.

Niestety - podczas uczenia się OpenGL'a zauważyłem, że to, co jest w kursach i książkach mija się z moją (opisaną powyżej) wizją. Za każdym razem trzeba wszystko rysować od nowa, klatka po klatce. Sam OpenGL "niczego nie pamięta". Nawet jak okno z renderem zostanie chwilowo przesłonięte - mimo faktu, że nic się nie zmieniło w rysowanej scenie, trzeba ją odmalować ponownie.

I teraz moje pytanie - czy tak jest naprawdę, muszę "ręcznie" klatka po klatce odrysowywać to, co chcę pokazać, czy może jest jakiś sposób / mechanizm który działa zgodnie z podanymi powyżej punktami 1-3, ale gdzieś go przeoczyłem? Bardzo proszę albo o odpowiedź w stylu "tak ziom, musisz sobie sam rysować", albo o skierowanie w odpowiednim kierunku, udzielenie jakiejś wskazówki do dalszych poszukiwań / podrzucenie punktu zaczepienia ;)

2

To co chciałbyś mieć to: Retained mode
OpenGL, Direct3D, Vulkan itd działają w Immediate mode

Te dwa podejścia się jedna nie wykluczają, bo można mieć np command buffer, vertex buffer, pixel buffer, itp itd W Vulkanie jest mocny nacisk na budowanie buforów poleceń, które można potem wielokrotnie używać.

Sam OpenGL "niczego nie pamięta". Nawet jak okno z renderem zostanie chwilowo przesłonięte - mimo faktu, że nic się nie zmieniło w rysowanej scenie, trzeba ją odmalować ponownie.

Sam możesz zaimplementować taką optymalizację. Renderuj do bufora pikseli tylko w reakcji na zmiany, natomiast podczas cyklicznego malowania kopiuj dane z tego bufora na ekran. Kopiowanie między buforami jest super tanie, nawet jeśli odmalowujesz 100x na sekundę, a bufor ma 10 megabajtów to wychodzi 1 GB/s przepustowości - to malutki ułamek tego co oferują karty graficzne, nawet w trybie oszczędzania energii.

Chociaż w sumie to nawet nie jestem pewien czy taki dodatkowy bufor jest potrzebny. Masz przecież kontrolę nad tym, kiedy zmieniasz zawartości buforów. Musisz tylko reagować na zdarzenia z OpenGLa, który może sobie sam wyzerować bufory (z jakichkolwiek powodów).

0

Dzięki za odpowiedź.

Tak dopytam, żebyśmy mieli 100% pewności, że dobrze się rozumiemy:

  1. tryb retained nie jest dostępny w OpenGL? (bo w mojej ocenie posiadanie dodatkowego bufora, który można przerzucić na ekran to nie do końca "pamiętanie" sceny przez bibliotekę do rysowania grafiki)
  2. przerzucanie bufora może jedynie się przydać w sytuacji odmalowania zasłoniętego okna - zgadza się? Przy skalowaniu czy obrocie i tak trzeba wszystko rysować od nowa - prawda?
  3. tak ogólnie podsumowując - wyszło na to, że wizja której się obawiałem jest prawdziwa - sam muszę się zajmować rysowaniem klatka po klatce... prawda? :(
1
  1. tryb retained nie jest dostępny w OpenGL? (bo w mojej ocenie posiadanie dodatkowego bufora, który można przerzucić na ekran to nie do końca "pamiętanie" sceny przez bibliotekę do rysowania grafiki)

Nie jest dostępny. Aczkolwiek (jak już napisałem) są pewne elementy retained mode, jak np https://en.wikipedia.org/wiki/Vertex_buffer_object gdzie można przechować na karcie graficznej bufor wierzchołków do późniejszego i/ lub ponownego wykorzystania.

  1. przerzucanie bufora może jedynie się przydać w sytuacji odmalowania zasłoniętego okna - zgadza się? Przy skalowaniu czy obrocie i tak trzeba wszystko rysować od nowa - prawda?

Tak. Optymalizacja z dodatkowym buforem zadziała tylko w przypadku zupełnie nieruchomych scen. Nie ma opcji, by OpenGL/ Direct3D/ Vulkan czy cokolwiek wygenerowało scenę z innej perspektywy mając tylko bitmapę ze starą perspektywą.

  1. tak ogólnie podsumowując - wyszło na to, że wizja której się obawiałem jest prawdziwa - sam muszę się zajmować rysowaniem klatka po klatce... prawda? :(

A co za różnica czy odpalasz metodę mniej czy więcej razy? Kodu tyle samo. W zasadzie to nawet rysowanie klatka po klatce jest prostsze, bo nie trzeba obliczać kiedy trzeba aktualizować bufory - aktualizuje się je ciągle.

I jeszcze artykuł jako ciekawostka: Direct3D Retained Mode removed from Windows Vista

Direct3D Retained Mode is a technology introduced in DirectX 3. Ongoing development for this component has ceased, and it has since been deprecated. It was removed from Windows Vista and later due to security concerns.

Retained mode w ogólności się nie sprawdziło. Jedna ZTCP to chyba są API które nadal to implementują. Wydaje mi się, że JavaFX 3D implementuje retained mode.

0

W sumie to niby masz rację - skoro mam jakąś procedurę, która tworzy rysowany obiekt, to moge ją uruchomić wiele razy i niby nic się nie stanie. Jedyne (pomijając kwestię wygody) czego się obawiam to zwyczajnie wydajność. Jestem więcej niż pewien, że mój kod tworzący rysowany obiekt będzie o wiele wolniejszy, niż w przypadku robienia tego przez specjalistyczną bibliotekę (w oparciu o wcześniej okreslone przeze mnie wytyczne). Zwłaszcza, jak będzie konieczność rysowania tego kilka/kilkanaście albo i dziesiąt razy na sekundę (gdy np. użytkownik zacznie sobie obracać obiekt na ekranie).
No ale w sumie, skoro i tak nie ma alternatywy, to nie ma sensu dalej tego roztrząsać ;)
Jeszcze raz dzięki za szybką i rzeczową odpowiedź.

1

Przecież napisałem, że możesz wykorzystać bufor wierzchołków i wrzucić tam wszelakie figury geometryczne jakie chcesz. Potem np 100x na sekundę będziesz odpalał metodę w OpenGLu, która weźmie ten bufor wierzchołków i wyrenderuje oteksturowane trójkąty. 100 draw calli na sekundę to nie jest dużo.

Obracanie obiektów na ekranie robi się za pomocą vertex shaderów, które np wykonują operacje na macierzach (potrzebne do obracania punktów trójwymiarowych) na samej karcie graficznej. Na GPU masz vertex buffery, pixel buffery, vertex shadery, pixel shadery i inne bajery, więc nie musisz wcale dużo liczyć na CPU.

Możliwe, że masz jakiś stary kurs OpenGLa, w którym masę obliczeń przeprowadza się na GPU, ale obecny stan jest taki, że to na GPU przerzuca się zdecydowaną większość obliczeń związanych z grafiką trójwymiarową.

0

Pewnie masz rację.
Póki co wierzę na słowo - na razie jestem na etapie poznawania i uczenia się, jeszcze chwile potrwa zanim dojdę do skomplikowanych i złożonych modeli. i mam nadzieję, że tak, jak napisałeś - nie będzie problemów z wydajnością.
Jeszcze raz dzięki za pomoc :)

0

Wszelakie nowoczesne i efektowne gry opierają się na mechanizmach opisanych tutaj przeze mnie, więc wiesz czego można się po tym spodziewać. Uważaj tylko na to, by nie uczyć się starożytnych wersji OpenGLa, które polegały na mechanizmach mocno obciążających CPU. Z wersji na wersję w OpenGLu jest coraz więcej funkcjonalności dzięki którym można odciążyć CPU. Największy nacisk na odciążenie CPU jest w Vulkanie, ale to API jest akurat podobno znacznie trudniejsze od OpenGLa.

2

Niestety - podczas uczenia się OpenGL'a zauważyłem, że to, co jest w kursach i książkach mija się z moją (opisaną powyżej) wizją.

Nie wiem jak książki, ale to co jest w kursach online często mija się nawet ze specyfikacją OpenGL-a.

Za każdym razem trzeba wszystko rysować od nowa, klatka po klatce.

I tak, i nie. 100% (w zaokrągleniu) tutoriali zakłada ten sam model aplikacji:

  • viewport OpenGL-a na całe okno
  • włączony double buffering
  • włączony depth test
  • okno odrysowywane od zera tak szybko jak tylko komputer zdoła, nawet jeśli nic się nie zmienia.

Jest to zrozumiałe, bo zwykle właśnie tego chcemy (choć vsync by się przydało – nie renderować na darmo klatek których i tak monitor nie wyświetli).

OpenGL to potok (“pipeline”). Wrzucasz coś do rysowania, i po glFlush zostanie to narysowane. Jeśli chcemy mieć animację, to chcemy mieć double buffering.
Jeśli chcemy mieć double buffering, to znaczy że rysujemy na ekranie nawet nie ostatnim, tylko przedostatnim, a jego zawartość jest już praktycznie bezużyteczna. Musimy najpierw ekran wyczyścić (glClear) i narysować wszystko od nowa i po nowemu (rysujemy animację). OpenGL nie pamięta co rysował w poprzedniej klatce czy dwie klatki temu (nie ma “retained mode”).

W OpenGL-u nawet nie ma takiego pojęcia jak „klatka”. Po prostu wrzucamy kolejne komendy rysujące i będą w tej kolejności renderowane jako piksele na framebufferze.
Chcemy mieć klatki to trzeba rysować ekran w pętli, robić glClear i SwapBuffers.

Nikt ci jednak nie broni narysować jednego, statycznego obrazka, bez pętli rysującej i bez podwójnego buforowania. Pod Windows rysujemy jako odpowiedź na systemowy komunikat WM_PAINT. Tam trzeba narysować, zrobić glFlush() (inaczej OpenGL może nigdy nie zacząć rysować) i ValidateRect() (inaczej Windows natychmiast wyśle nowe WM_PAINT) i już. Jeśli okno zostanie przesłonięte to Windows automatycznie wyśle nam nowe WM_PAINT.

Bufory w OpenGL-u to inna sprawa: ich zawartość sama nie zniknie tak samo jak same nie znikają np. tekstury.

  1. przerzucanie bufora może jedynie się przydać w sytuacji odmalowania zasłoniętego okna - zgadza się? Przy skalowaniu czy obrocie i tak trzeba wszystko rysować od nowa - prawda?

Tak. Optymalizacja z dodatkowym buforem zadziała tylko w przypadku zupełnie nieruchomych scen. Nie ma opcji, by OpenGL/ Direct3D/ Vulkan czy cokolwiek wygenerowało scenę z innej perspektywy mając tylko bitmapę ze starą perspektywą.

Ale można użyć tego samego bufora z nowymi macierzami przekształceń.

0

chcialbym zrobic gre / swiat 3D / tylko na takiej zasadzie jak sie rysuje w AutoCAD

czyli rysuje sobie wielokaty a pozniej tapetuje teksturami

da sie tak ?

jaki program polecacie ?

0
Trzeźwy Kot napisał(a):

chcialbym zrobic gre / swiat 3D / tylko na takiej zasadzie jak sie rysuje w AutoCAD

czyli rysuje sobie wielokaty a pozniej tapetuje teksturami

da sie tak ?

jaki program polecacie ?

Shadery na GPU, w dowolnym programie ładujesz teksturę przekazujesz ją shaderowi, a potem przy wypełnianiu przez pixele lub wierzchołki nakładasz teksturę, gdzie możesz nałożyć światło, cienie, od lewej do prawej lub odwrotnie nawet do góry nogami, ogólnie wszystko możesz i wkładasz to na ten pixel i tyle.

0

Chyba na dzisiaj starczy siedzenia przed kompem... właśnie widze, że "Trzeźwemu kotowi" udzielił odpowiedzi "Mistrzowski Karp". Czas odpocząć ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1