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:
- Samouczek jest stary i używa tylko przestarzałych interfejsów API.
- Samouczek jest nowy i dobrze napisany i korzysta wyłącznie z interfejsów API zgodnych z Core.
- Samouczek jest nowy, ale popełnia błąd, zakładając, że pracujesz ze sterownikiem, który włącza wszystkie interfejsy API w trybie zgodności i swobodnie miesza zarówno nowe, jak i stare interfejsy API.
- Samouczek dotyczy innej edycji OpenGL, takiej jak OpenGL | ES, która nie obsługuje żadnego ze starych interfejsów API w żadnej wersji.
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ów glVertex
w tym buforze, a następnie przesłanie całego bufora w jednym wywołaniu losowania, gdy glEnd
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.