http://www.sdltutorials.com/sdl-opengl-tutorial-basics
http://www.opengl-tutorial.org/beginners-tutorials/tutorial-2-the-first-triangle/
Diese beiden Tutorials verwenden völlig unterschiedliche Ansätze, um fast das gleiche Ergebnis zu erzielen. Der erste verwendet Dinge wie glBegin(GL_QUADS)
. Der zweite verwendet Sachen wie vertexBufferObjects
Shader, die auf GLEW basieren. Das Ergebnis ist jedoch dasselbe: Sie erhalten Grundformen.
Warum gibt es diese Unterschiede?
Der erste Ansatz scheint viel einfacher zu verstehen. Was ist der Vorteil des komplizierten zweiten Ansatzes?
opengl
architecture
reynmar
quelle
quelle
glBegin
undglEnd
wurden veraltet, weil sie für die aktuellen Grafikarchitekturen extrem ineffizient sindAntworten:
OpenGL hat vier verschiedene Hauptversionen, wobei die Versionen für mobile Geräte und eingebettete Systeme (OpenGL | ES) und das Web über JavaScript (WebGL) nicht berücksichtigt werden. Genau wie Direct3D 11 eine andere Vorgehensweise als Direct3D 8 hat, hat OpenGL 3 eine andere Vorgehensweise als OpenGL 1. Der große Unterschied ist, dass OpenGL-Versionen meist nur Add-Ons zu den älteren Versionen sind (aber nicht völlig).
Zusätzlich zu den verschiedenen Editionen und Versionen von OpenGL hat das Haupt-OpenGL auch das Konzept von Profilen hinzugefügt. Nämlich das Kompatibilitätsprofil (das die Unterstützung für APIs älterer Versionen aktiviert) und das Kernprofil (das diese alten APIs deaktiviert). Dinge wie
glBegin
funktionieren einfach nicht, wenn Sie das Core-Profil verwenden, sondern, wenn Sie das Kompatibilitätsprofil verwenden (das die Standardeinstellung ist).Als eine weitere große Komplikation werden einige Implementierungen von OpenGL (wie unter anderem von Apple) neuere OpenGL-Funktionen nur dann aktivieren, wenn Sie das Core-Profil verwenden. Dies bedeutet , dass Sie müssen mit älteren APIs stoppen , um zu neueren APIs zu verwenden.
Sie haben dann einige sehr verwirrende Szenarien für Tutorials:
Dinge wie
glBegin
sind Teil dessen, was manchmal als Sofortmodus-API bezeichnet wird. Dies ist auch sehr verwirrend, da es in OpenGL keinen beibehaltenen Modus gibt und der "unmittelbare Modus" in Grafiken bereits eine andere Definition hatte. Es ist viel besser, diese APIs nur als OpenGL 1.x-APIs zu bezeichnen, da sie seit OpenGL 2.1 veraltet sind.Die 1.x-API von OpenGL übermittelte Scheitelpunkte sofort an die Grafik-Pipeline in früheren Zeiten. Dies funktionierte gut, wenn die Geschwindigkeit der Hardware, mit der Scheitelpunkte gerendert wurden, in etwa der Geschwindigkeit der CPU entsprach, die die Scheitelpunktdaten erzeugte. OpenGL hat damals nur die Dreiecksrasterung und nicht viel mehr ausgelagert.
Heutzutage kann die GPU eine große Anzahl von Scheitelpunkten mit sehr hoher Geschwindigkeit durchkauen und gleichzeitig eine erweiterte Scheitelpunkt- und Pixel-Transformation durchführen, und die CPU kann einfach nicht einmal aus der Ferne mithalten. Darüber hinaus wurde die Schnittstelle zwischen der CPU und der GPU auf diesen Geschwindigkeitsunterschied ausgelegt, sodass es nicht einmal mehr möglich ist, Scheitelpunkte einzeln an die GPU zu senden.
Alle GL-Treiber müssen emulieren,
glBegin
indem sie intern einen Scheitelpunktpuffer zuweisen, die mitglVertex
in diesen Puffer gesendeten Scheitelpunkte einfügen und dann den gesamten Puffer in einem einzelnen Zeichenaufruf senden, wenn dieserglEnd
aufgerufen wird. Der Aufwand für diese Funktionen ist weitaus größer als wenn Sie den Vertex-Puffer selbst aktualisiert haben. Aus diesem Grund wird in einigen Dokumentationen (aus Versehen!) Der Vertex-Puffer als "Optimierung" bezeichnet (dies ist keine Optimierung; dies ist der einzige Weg, dies tatsächlich zu tun) mit der GPU sprechen).Es gibt verschiedene andere APIs, die in OpenGL im Laufe der Jahre veraltet oder veraltet sind. Die sogenannte Festfunktionspipeline ist ein weiteres solches Stück. In einigen Dokumentationen wird diese Pipeline möglicherweise noch verwendet oder mit der programmierbaren Pipeline gemischt. Die Pipeline mit festen Funktionen stammt aus früheren Zeiten, als Grafikkarten die gesamte Mathematik fest codierten, die zum Rendern von 3D-Szenen verwendet wurde, und die OpenGL-API darauf beschränkt war, einige Konfigurationswerte für diese Mathematik festzulegen. Heutzutage hat die Hardware sehr wenig hartcodierte Mathematik und führt (genau wie Ihre CPU) stattdessen vom Benutzer bereitgestellte Programme (oft als Shader bezeichnet) aus.
Wieder müssen die Treiber die alte API emulieren, da die Funktionen mit festen Funktionen auf der Hardware einfach nicht mehr vorhanden sind. Dies bedeutet, dass in den Treiber eine Reihe von Kompatibilitätsshadern eingebettet sind, die die alte Mathematik aus den Tagen mit festen Funktionen ausführen, die verwendet wird, wenn Sie keine eigenen Shader bereitstellen. Die alten OpenGL-Funktionen, die diesen alten Status mit festen Funktionen ändern (wie die alte OpenGL-Beleuchtungs-API), verwenden derzeit moderne OpenGL-Funktionen wie einheitliche Puffer, um diese Werte den Kompatibilitätsshadern des Treibers zuzuführen.
Treiber, die Kompatibilität unterstützen, müssen viel hinter den Kulissen arbeiten, um herauszufinden, wann Sie diese veralteten Funktionen verwenden, und um sicherzustellen, dass Sie sie reibungslos mit modernen Funktionen kombinieren können, was den Aufwand erhöht und den Treiber erheblich verkompliziert. Dies ist einer der Gründe, warum Sie von einigen Treibern dazu gezwungen werden, das Core-Profil auf neuere Funktionen umzustellen. Dies vereinfacht die Einbindung der Treiber erheblich, da die alte und die neue API, die gleichzeitig verwendet werden, nicht unterstützt werden müssen.
In vielen Dokumentationen wird möglicherweise empfohlen, mit den alten APIs zu beginnen, da diese einfacher zu handhaben sind. Direct3D löste dieses Problem für Anfänger, indem es eine Begleitbibliothek ( DirectX Tool Kit ) anbot , die einfachere Zeichnungs-APIs und vorab geschriebene Shader bietet, die mit der Verwendung von Direct3D 11 frei gemischt werden können, wenn Ihr Fachwissen wächst. Die breitere OpenGL-Community hat sich leider größtenteils an das Kompatibilitätsprofil für Anfänger gehalten, was problematisch ist, da es wieder Systeme gibt, mit denen Sie alte OpenGL-APIs nicht mit den neueren mischen können. Es gibt inoffizielle Bibliotheken und Tools für ein einfacheres Rendern in der neuen OpenGL mit unterschiedlichen Funktionen und Anwendungsfällen und Sprachen ( MonoGame zum Beispiel für .NET-Benutzer), aber nichts, was offiziell gebilligt oder weitestgehend vereinbart wurde.
Die Dokumentation, die Sie finden, ist möglicherweise nicht für OpenGL, sondern für eine der anderen ähnlichen APIs. OpenGL | ES 1.x hatte ein Rendering mit festen Funktionen, verfügte jedoch nicht über die OpenGL 1.x-APIs für die Übermittlung von Scheitelpunkten. OpenGL | ES 2.x + und WebGL 1+ haben überhaupt keine Funktionen mit festen Funktionen, und für diese APIs gibt es keine Abwärtskompatibilitätsmodi.
Diese APIs sehen dem OpenGL-Hauptprogramm sehr ähnlich. Sie sind nicht ganz kompatibel, aber es gibt offizielle Erweiterungen für OpenGL, die einige (nicht alle) Treiber unterstützen, um mit OpenGL | ES (auf dem WebGL basiert) kompatibel zu werden. Weil die Dinge vorher nicht verwirrend genug waren.
quelle
Der Hauptunterschied ist, wie aktuell die Strategien sind. Der im ersten Tutorial verwendete Sofortmodus:
Ist veraltet und wird in neueren Versionen nicht unterstützt.
Die Verwendung von Vertex-Puffern und Shadern ist die aktuelle Methode zum Rendern mit OpenGL. Es mag komplizierter erscheinen, ist aber wesentlich leistungsfähiger. Darüber hinaus werden die Unterschiede größtenteils abstrahiert, sobald Sie den unterstützenden Code haben, der das OpenGL-Zeug einschließt.
quelle
Nur um den anderen hervorragenden Antworten etwas mehr Kontext hinzuzufügen.
Der Sofortmodus, wie er im ersten Link beschrieben wurde, ist, wie andere bereits gesagt haben, Legacy-Code aus den frühesten Versionen von OpenGL (1.1). Es wurde verwendet, als GPUs nur Dreieck-Rasterizer waren und die Idee von programmierbaren Pipelines nicht existierte. Wenn Sie sich den Quellcode einiger früherer hardwarebeschleunigter Spiele wie GLQuake und Quake 2 ansehen, werden Sie feststellen, dass der Sofortmodus verwendet wird. In einfachen Worten, die CPU sendet nacheinander Anweisungen für Scheitelpunkte an die GPU, um mit dem Zeichnen von Dreiecken auf dem Bildschirm zu beginnen. Für den Datensatz hat GL_QUADS das gleiche Ergebnis wie GL_TRIANGLES, außer dass die GPU diese Quads im laufenden Betrieb selbst in Dreiecke verwandeln muss.
Modernes (3.2+) OpenGL verfolgt einen anderen Ansatz. Die Vertex-Daten werden für den schnellen Zugriff im GPU-Speicher zwischengespeichert. Anschließend können Sie Zeichnungsanweisungen entweder mit glDrawArrays oder glDrawElements senden. Sie haben auch die programmierbare Pipeline (glUseProgram), mit der Sie anpassen können, wie die GPU die Scheitelpunkte positioniert und färbt.
Es gibt einige Gründe, warum der Sofortmodus veraltet ist, vor allem wegen der Leistung. Wie Sean in seiner Antwort sagte, können heutzutage GPUs die Daten schneller zerkleinern als die CPU sie hochladen kann, so dass Sie die GPU-Leistung beeinträchtigen würden. Für jeden von Ihnen getätigten Aufruf von OpenGL ist ein geringer Aufwand erforderlich, der jedoch winzig ist. Wenn Sie jedoch in jedem Frame Zehntausende von Anrufen tätigen, beginnt die Stapelung. Einfach ausgedrückt, um ein texturiertes Modell im Sofortmodus zu zeichnen, benötigen Sie mindestens 2 Aufrufe pro Scheitelpunkt (glTexCoord2f und glVertex3f) pro Frame. Mit modernem OpenGL verwenden Sie zu Beginn einige Aufrufe, um die Daten zu puffern. Anschließend können Sie das gesamte Modell unabhängig von der Anzahl der darin enthaltenen Scheitelpunkte mit nur wenigen Aufrufen zum Binden des Scheitelpunktarrayobjekts zeichnen und einige Attributzeiger aktivieren dann ein einzelner Aufruf von glDrawElements oder glDrawArrays.
Welche Technik ist richtig? Nun, das hängt davon ab, was Sie versuchen. Ein einfaches 2D-Spiel, das keine ausgefallenen Nachbearbeitungstechniken oder Shader erfordert, funktioniert im Sofortmodus einwandfrei und es wird wahrscheinlich einfacher sein, den Code zu schreiben. Ein moderneres 3D-Spiel würde sich jedoch wirklich schwer tun, und wenn Sie GLSL (Shader Language) lernen möchten, sollten Sie die moderne Technik auf jeden Fall erlernen.
quelle