http://www.sdltutorials.com/sdl-opengl-tutorial-basics
http://www.opengl-tutorial.org/beginners-tutorials/tutorial-2-the-first-triangle/
Te dwa samouczki wykorzystują zupełnie inne podejścia, aby uzyskać prawie taki sam wynik. Pierwszy używa rzeczy takich jak glBegin(GL_QUADS)
. Drugi wykorzystuje rzeczy takie jak vertexBufferObjects
shadery oparte na GLEW. Ale wynik jest taki sam: otrzymujesz podstawowe kształty.
Dlaczego te różnice istnieją?
Pierwsze podejście wydaje się dużo łatwiejsze do zrozumienia. Jaka jest zaleta skomplikowanego drugiego podejścia?
opengl
architecture
Reynmar
źródło
źródło
glBegin
iglEnd
są przestarzałe, ponieważ są niezwykle nieefektywne w obecnych architekturach graficznychOdpowiedzi:
OpenGL ma cztery różne główne wersje, nie licząc wersji na urządzenia mobilne i systemy wbudowane (OpenGL | ES) oraz Internet przez JavaScript (WebGL). Podobnie jak Direct3D 11 ma inny sposób robienia rzeczy niż Direct3D 8, tak też OpenGL 3 ma inny sposób robienia rzeczy niż OpenGL 1. Duża różnica polega na tym, że wersje OpenGL są głównie dodatkami do starszych wersji (ale nie całkowicie).
Oprócz różnych edycji i wersji OpenGL główny OpenGL dodał także koncepcję profili. Mianowicie profil zgodności (który umożliwia obsługę interfejsów API starszych wersji) i profil podstawowy (który wyłącza te stare interfejsy API). Rzeczy takie jak
glBegin
po prostu nie działają, gdy korzystasz z profilu podstawowego, ale działają, gdy używasz profilu zgodności (który jest domyślny).Jako kolejna poważna komplikacja, niektóre implementacje OpenGL (między innymi Apple) umożliwią nowsze funkcje OpenGL tylko podczas korzystania z profilu podstawowego. Oznacza to, że musisz przestać używać starszych interfejsów API, aby korzystać z nowszych interfejsów API.
W efekcie powstaje kilka bardzo mylących scenariuszy samouczków:
Takie rzeczy
glBegin
są częścią tak zwanego interfejsu API trybu natychmiastowego. Jest to również bardzo mylące, ponieważ nie ma czegoś takiego jak tryb zachowany w OpenGL, a „tryb natychmiastowy” miał już inną definicję w grafice. O wiele lepiej jest po prostu nazywać je API OpenGL 1.x, ponieważ są one przestarzałe od OpenGL 2.1.Interfejs API OpenGL 1.x natychmiast przesyłałby wierzchołki do potoku graficznego w dawnych czasach. Działało to dobrze, gdy szybkość sprzętu renderującego wierzchołki była w przybliżeniu równa prędkości procesora generującego dane wierzchołków. Wtedy OpenGL po prostu odciążył rasteryzację trójkąta i niewiele więcej.
Obecnie GPU może przeżuwać ogromną liczbę wierzchołków z bardzo dużymi prędkościami, wykonując zaawansowaną transformację wierzchołków i pikseli, a procesor po prostu nie może nawet zdalnie nadążyć. Co więcej, interfejs między CPU a GPU został zaprojektowany wokół tej różnicy prędkości, co oznacza, że nie jest nawet możliwe przesyłanie wierzchołków do GPU pojedynczo.
Wszystkie sterowniki GL muszą emulować
glBegin
poprzez wewnętrzne przydzielenie bufora wierzchołków, umieszczenie przesłanych wierzchołkówglVertex
w tym buforze, a następnie przesłanie całego bufora w jednym wywołaniu losowania, gdyglEnd
jest wywoływane. Narzut związany z tymi funkcjami jest o wiele większy niż gdybyś sam zaktualizował bufor bufora wierzchołków, dlatego niektóre dokumenty (bardzo błędnie!) Odnoszą się do buforów wierzchołków jako „optymalizacji” (nie jest to optymalizacja; to jedyny sposób na faktyczne porozmawiaj z GPU).Istnieje wiele innych interfejsów API, które były przestarzałe lub przestarzałe w OpenGL na przestrzeni lat. Kolejnym tego rodzaju elementem jest tak zwany rurociąg o stałej funkcji. Niektóre dokumenty mogą nadal korzystać z tego potoku lub mieszać się z potokiem programowalnym. Potok o stałej funkcji pochodzi z dawnych czasów, kiedy karty graficzne zapisały na stałe całą matematykę używaną do renderowania scen 3D, a interfejs API OpenGL był ograniczony do ustawiania pewnych wartości konfiguracyjnych dla tej matematyki. W dzisiejszych czasach sprzęt ma bardzo mało zakodowanej matematyki i (podobnie jak procesor) uruchamia programy dostarczane przez użytkowników (często nazywane programami cieniującymi).
Ponownie sterowniki muszą emulować stary interfejs API, ponieważ funkcje o ustalonej funkcji po prostu nie są już dostępne na sprzęcie. Oznacza to, że sterownik ma wbudowane kilka modułów cieniujących zgodność, które wykonują starą matematykę z dni o stałej funkcji, które są używane, gdy nie dostarczasz własnych modułów cieniujących. Stare funkcje OpenGL, które modyfikują ten stary stan stałej funkcji (jak stary interfejs API oświetlenia OpenGL), w rzeczywistości wykorzystują nowoczesne funkcje OpenGL, takie jak jednolite bufory, do dostarczania tych wartości do modułów cieniujących zgodność sterownika.
Sterowniki obsługujące zgodność muszą wykonywać wiele zakulisowych prac, aby dowiedzieć się, kiedy korzystasz z tych przestarzałych funkcji i upewnić się, że możesz je łączyć z nowoczesnymi funkcjami płynnie, co powoduje dodatkowe obciążenie i znacznie komplikuje sterownik. Jest to jeden z powodów, dla których niektórzy kierowcy zmuszają cię do włączenia profilu podstawowego w celu uzyskania nowszych funkcji; znacznie upraszcza to wewnętrzne elementy sterowników, ponieważ nie muszą obsługiwać jednocześnie starych i nowych interfejsów API.
Wiele dokumentacji może zalecać rozpoczęcie korzystania ze starych interfejsów API, ponieważ łatwiej jest zacząć. Direct3D rozwiązał ten problem dla początkujących, oferując bibliotekę towarzyszącą ( zestaw narzędzi DirectX ), która zapewnia prostsze interfejsy API do rysowania i wstępnie napisane moduły cieniujące, które można dowolnie mieszać z surowym użyciem Direct3D 11 w miarę zdobywania doświadczenia. Szersza społeczność OpenGL w większości utknęła z Profilem kompatybilności dla początkujących, co jest niestety problematyczne, ponieważ znów istnieją systemy, które nie pozwalają mieszać starych API OpenGL z nowszymi. Istnieją nieoficjalne biblioteki i narzędzia do prostszego renderowania w nowym OpenGL z różnymi poziomami funkcji oraz przypadków użycia i języków docelowych ( MonoGame na przykład dla użytkowników .NET), ale nic oficjalnie nie zostało poparte ani powszechnie uzgodnione.
Dokumentacja, którą znajdziesz, może nawet nie dotyczyć OpenGL, ale może dotyczyć jednego z innych podobnych interfejsów API. OpenGL | ES 1.x miał renderowanie z funkcjami stałymi, ale nie miał API OpenGL 1.x do przesyłania wierzchołków. OpenGL | ES 2.x + i WebGL 1+ nie mają żadnych funkcji o stałej funkcji i nie ma trybów zgodności wstecznej dla tych interfejsów API.
Te interfejsy API wyglądają bardzo bardzo podobnie do głównego OpenGL; nie są do końca kompatybilne, ale istnieją oficjalne rozszerzenia OpenGL, które obsługiwane są przez niektóre (nie wszystkie) sterowniki z OpenGL | ES (na których oparty jest WebGL). Ponieważ rzeczy nie były wystarczająco mylące.
źródło
Podstawową różnicą jest aktualność strategii. Tryb natychmiastowy użyty w pierwszym samouczku:
Jest nieaktualny i nie jest obsługiwany w nowszych wersjach.
Używanie buforów i shaderów wierzchołków jest obecną metodą renderowania w OpenGL. Może się to wydawać bardziej skomplikowane, ale działa znacznie lepiej. Ponadto, gdy masz już kod pomocniczy podsumowujący OpenGL, różnice są w większości abstrakcyjne.
źródło
Aby dodać więcej kontekstu do innych doskonałych odpowiedzi.
Tryb natychmiastowy opisany w pierwszym linku to, jak powiedzieli inni, starszy kod z najwcześniejszych wersji OpenGL (1.1). Użyto go, gdy procesory graficzne były niewiele więcej niż rasteryzatorami trójkątnymi, a pomysł programowalnych potoków nie istniał. Jeśli spojrzysz na kod źródłowy niektórych wczesnych gier z akceleracją sprzętową, takich jak na przykład GLQuake i Quake 2, zobaczysz tryb natychmiastowy w użyciu. Mówiąc najprościej, procesor wysyła instrukcje dla wierzchołków pojedynczo do GPU, aby rozpocząć rysowanie trójkątów na ekranie. Dla przypomnienia, GL_QUADS ma taki sam wynik jak GL_TRIANGLES, z tym wyjątkiem, że GPU musi na bieżąco zamieniać te kwadraty w trójkąty.
Nowoczesne (3.2+) OpenGL ma inne podejście. Buforuje dane wierzchołków do pamięci GPU w celu szybkiego dostępu, a następnie możesz wysyłać instrukcje rysowania za pomocą glDrawArrays lub glDrawElements. Masz również programowalny potok (glUseProgram), który pozwala dostosować sposób, w jaki GPU pozycjonuje i koloruje wierzchołki.
Istnieje kilka powodów, dla których tryb natychmiastowy został wycofany, a głównym powodem jest wydajność. Jak powiedział Sean w swojej odpowiedzi, obecnie układy GPU mogą przeskakiwać dane szybciej niż procesor może je przesłać, więc ograniczymy wydajność GPU. Każde wywołanie OpenGL, które wykonujesz, wiąże się z niewielkim narzutem, jest bardzo małe, ale gdy wykonujesz dziesiątki tysięcy połączeń przy każdej ramce, zaczyna się on gromadzić. Mówiąc najprościej, aby narysować teksturowany model w trybie natychmiastowym, potrzebujesz co najmniej 2 wywołań na wierzchołek (glTexCoord2f i glVertex3f) na ramkę. W nowoczesnym OpenGL używasz na początku kilku wywołań do buforowania danych, a następnie możesz narysować cały model, bez względu na to, ile zawiera on wierzchołków, używając tylko kilku wywołań do powiązania obiektu tablicy wierzchołków, włącz niektóre wskaźniki atrybutów i następnie pojedyncze wywołanie glDrawElements lub glDrawArrays.
Która technika jest odpowiednia? To zależy od tego, co próbujesz zrobić. Prosta gra 2D, która nie wymaga żadnych wymyślnych technik przetwarzania końcowego ani shaderów, będzie działać dobrze w trybie natychmiastowym i prawdopodobnie łatwiej będzie napisać kod. Jednak bardziej nowoczesna gra 3D naprawdę miałaby problemy, a jeśli planujesz uczyć się GLSL (język shaderów), zdecydowanie naucz się nowoczesnej techniki.
źródło