Tutorial OpenGL3: Unterschied zwischen den Versionen

Aus DGL Wiki
Wechseln zu: Navigation, Suche
(Der Grafikcontext)
K (Übersichten: Kategorie hinzugefügt)
 
(9 dazwischenliegende Versionen von 4 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
 
=Vorwort=
 
=Vorwort=
 
Willkommen zur Einführung in OpenGL3.x.
 
Willkommen zur Einführung in OpenGL3.x.
Im Rahmen, dieses Artikels, werde ich versuchen die Grundlagen für die Nutzung von OpenGL3 zu legen und durch Pseudo Code die Verwendung von der API aufzeigen. Mit OpenGL Version 3 hat sich vieles, im Vergleich zu den Vorversionen, verändert und entsprechend ist der Umstieg von OpenGL1-2 auf 3 sehr zeitaufwändig. Dieser Artikel richtet sich mehr an Anfänger als an Programmierer, die von der Vorversion umsteigen wollen.
+
Im Rahmen dieses Artikels werde ich versuchen, die Grundlagen für die Nutzung von OpenGL3 zu legen und durch Pseudocode die Verwendung von der [[OpenGL3.x_API|API]] aufzeigen. Mit OpenGL Version 3 hat sich vieles im Vergleich zu den Vorversionen verändert und entsprechend ist der Umstieg von OpenGL1-2 auf 3 sehr zeitaufwändig. Diese Artikelreihe richtet sich mehr an Anfänger als an Programmierer, die von der Vorversion umsteigen wollen.
  
=Grundlagen=
 
 
==OpenGL3 und die Vorgeschichte==
 
==OpenGL3 und die Vorgeschichte==
OpenGL ist viele Jahre alt und entsprechend gab es immer wieder neue Versionen und Änderungen. Doch entfernte sich OpenGL mit der Zeit vom aktuellen Stand der Technik und veraltete immer mehr. Die API wurde größer und größer, alte nicht mehr gebrauchte Funktionen wurden aus Kompatibilitätsgründen nicht entfernt und die Treiber wuchsen zu riesigen und komplexen Codewerken. Darunter hat entsprechend die Leistung und Qualität stark gelitten. Es musste ein radikaler Schnitt gemacht werden und man beschloss dies mit OpenGL Version 3 zu tun. So hat man sämtlichen Balast von früher raus gestrichen und eine Hand voll neuer Funktionen hinzugefügt.  
+
OpenGL ist viele Jahre alt und entsprechend gab es immer wieder neue Versionen und Änderungen. Doch entfernte sich OpenGL mit der Zeit vom aktuellen Stand der Technik und veraltete immer mehr. Die API wurde größer und größer, alte nicht mehr gebrauchte Funktionen wurden aus Kompatibilitätsgründen nicht entfernt und die Treiber wuchsen zu riesigen und komplexen Codewerken. Darunter hat entsprechend die Leistung und Qualität stark gelitten. Es musste ein radikaler Schnitt gemacht werden und man beschloss, dies mit OpenGL Version 3 zu tun. So hat man sämtlichen Ballast von früher rausgestrichen und eine Hand voll neuer Funktionen hinzugefügt.  
  
Um die Umstellung für Software leichter zu machen, beschloss man 2 verschiedene Profile zu unterstützen. Das erste Profil ist ein OpenGL3 fähiger Grafik Context, welcher auch die alten Befehle ausführen kann und somit die Umstellung schrittweise ermöglicht. Das zweite Profil ist ein OpenGL3 fähiger Grafik Context, welcher nur die als nicht veraltet(deprecated) makierten Funktionen ausführen kann und für neue Software gedacht ist. Sollte man mit dem 2ten Profil arbeiten und ruft dennoch eine alte Funktion auf, dann wirft diese ein Fehler und wird nicht ausgeführt.  
+
Um die Umstellung für Software leichter zu machen, beschloss man, zwei verschiedene Profile zu unterstützen. Das erste Profil ist ein OpenGL3-fähiger Grafikkontext, welcher auch die alten Befehle ausführen kann und somit die Umstellung schrittweise ermöglicht. Das zweite Profil ist ein OpenGL3-fähiger Grafikkontext, welcher nur die als nicht veraltet (deprecated) makierten Funktionen ausführen kann und für neue Software gedacht ist. Sollte man mit dem zweiten Profil arbeiten und ruft dennoch eine alte Funktion auf, dann wirft diese ein Fehler und wird nicht ausgeführt.  
  
Mit den neuen Fähigkeiten der Grafikkarten entstanden parallel zu den OpenGL Versionen auch neue Shader Update. OpenGL verwendet Shader, um die Darstellung von 3D Modelle manipulieren zu können. So hat man anfangs mit Assembler ähnlichen Code und später mit C ähnlichen Code mini Programme geschrieben, welche auf dem Grafikprozessor lauffähig waren. Man hatte zwischen Vertice- und Fragment-Shadern/Programmen unterschieden. Mit dem Shader Modell 4 kam eine weitere Shader Kategorie hinzu, und zwar der Geometrie Shader. Wärend Vertice-Shader einzelne Punkte eines Drahtgitters manipulieren konnte, hat der Fragment-Shader das ausfüllen des Drahtgitters übernommen(shading) und die Geometrie-Shader erlauben die Manipulation des Drahtgitters. Während Shader in OpenGL1-2 nicht notwendig waren, kann man in OpenGL3 nicht ohne auskommen, da ein Vertex-/Fragment-Shader zum zeichnen benötigt wird.  
+
Mit den neuen Fähigkeiten der Grafikkarten entstanden parallel zu den OpenGL-Versionen auch Updates der Shadersprache GLSL. OpenGL verwendet Shader, um die Darstellung von 3D Modellen manipulieren zu können. So hat man anfangs mit Assembler ähnlichen Code und später mit C ähnlichen Code Mini-Programme geschrieben, welche auf dem Grafikprozessor lauffähig waren. Man hatte zwischen Vertex- und Fragment-Shadern/Programmen unterschieden. Mit dem Shader Model 4 kam eine weitere Shader-Kategorie hinzu, und zwar der Geometry-Shader. Während der Vertexshader einzelne Punkte eines Drahtgitters manipulieren konnte, hat der Fragment-Shader das Ausfüllen des Drahtgitters übernommen (shading) und die Geometry-Shader erlauben die Manipulation des Drahtgitters. Während Shader in OpenGL1-2 nicht notwendig waren, kann man in OpenGL3 nicht ohne auskommen, da ein Vertex-/Fragment-Shader zum Zeichnen benötigt wird.  
  
Ein sehr beliebtes Werkzeug, in OpenGL1-2, war der immidate mode, welcher das einfache zeichnen von 3D Daten erlaubte. Dieser wurde durch ein glBegin eingeleitet, ein glEnd beendet und alles was dazwischen stand wurde gezeichnet. Dies hatte allerdings auch seinen Preis, so war der Treibercode dadurch enorm komplexer geworden und es mussten aufgrund der vielen möglichen Variationen(gesetzte Flags) viele Prüfungen durchgeführt werden, um einen gültigen Rendercode zu erzeugen. Dieser wurde ebenfalls in OpenGL3 gestrichen und man muss nun sogenannte Vertex Buffer Objects(untermenge von Buffer Objects) verwenden. Diese haben den Vorteil, dass sie wesentlich schneller und recht einfach zu bedienen sind.
+
Ein sehr beliebtes Werkzeug in OpenGL1-2, war der Immediate Mode, welcher das sehr einfache Zeichnen von 3D Daten erlaubte. Dieser wurde durch ein [[glBegin]] eingeleitet, ein glEnd beendet und alles was dazwischen stand wurde gezeichnet. Dies hatte allerdings auch seinen Preis: So war der Treibercode dadurch enorm komplexer geworden und es mussten aufgrund der vielen möglichen Variationen(gesetzte Flags) viele Prüfungen durchgeführt werden, um einen gültigen Rendercode zu erzeugen. Dieser wurde ebenfalls in OpenGL3 gestrichen und man muss nun sogenannte Vertex Buffer Objects (untermenge von Buffer Objects) verwenden. Diese haben den Vorteil, dass sie wesentlich schneller und ebenfalls recht einfach zu bedienen sind.
  
In OpenGL1-2 war es möglich die Modelview und Projectionview Matrizen durch bestimmte API Befehle zu manipulieren. Die Modelview Matrix hat die Position eines Objektes so manipuliert, dass es den gewollten Platz in der 3D Welt eingenommen hat und die Projectionview Matrix hat dann die 3D Weltkoordinaten auf 2D Bildschirmkoordinaten transformiert. Mit OpenGL3 sind ist diese Möglichkeit entfernt worden, da nun der Vertexshader diese Arbeit übernommen hat und diese Funktionalität mehr in den Anwendercode als in die Bibliothek gehört.
+
In OpenGL1-2 war es möglich, die Modelview- und Projection-Matrizen durch bestimmte API-Befehle zu manipulieren. Die Modelview-Matrix hat die Position eines Objektes so manipuliert, dass es den gewollten Platz in der 3D Welt eingenommen hat und die Projection-Matrix hat dann die 3D Weltkoordinaten auf 2D Bildschirmkoordinaten transformiert. Mit OpenGL3 sind ist diese Möglichkeit entfernt worden, da nun der Vertexshader diese Arbeit übernommen hat und diese Funktionalität mehr in den Anwendercode als in die Bibliothek gehört.
  
Die letzten 3 angesprochenen Punkte (Shader,immedate mode und Matrizen) haben großen Einfluss auf den Basis Code einer OpenGL3 Anwendung. Dieser fällt größer und umfangreicher aus als ein Basis Code für OpenGL1-2 aber wird später kaum größer, aufgrund der Schlankheit der neuen API.
+
Die letzten 3 angesprochenen Punkte (Shader, Immediate Mode und Matrizen) haben großen Einfluss auf den Basis-Quellcode einer OpenGL3-Anwendung. Dieser fällt größer und umfangreicher aus, als ein Basis-Code für OpenGL1-2, wird aber später kaum größer aufgrund der Schlankheit der neuen API.
  
==Die Render Pipeline==
+
==Inhaltsverzeichnis==
{{Hinweis|Dieser Abschnitt ist für Erfahrende OpenGL Entwickler gedacht, die nochmal Nachschlagen wollen oder ein schnellen Einstieg in OpenGL3 suchen. Es wird ein hoher Grad an Vorwissen vorraus gesetzt, erklärt aber dafür wesentlich kompakter und tiefgehender die Funktionalität von OpenGL3. Wer noch keine oder wenig Erfahrung mit OpenGL hat, der sollte dieses Punkt überspringen und am Ende des Artikel dann hier rein schauen.}}
+
===Grundlagen===
 +
Artikel in diesem Bereich sind für OpenGL wichtig aber haben nicht direkt mit OpenGL zu tun.
  
OpenGL 3 sieht folgende Pipeline vor.
+
Man kann diese Artikel überspringen und später bei aufkommenden Fragen in diese hinein lesen.
  
[[Datei:OGL3Pipeline.png]]
+
[[Tutorial_OpenGL3_Lineare_Algebra|Lineare Algebra]]
 +
===Artikelreihe===
 +
[[Tutorial_OpenGL3_dead|Vorschau auf das kommende]]
  
Diese Darstellung ist noch weiter zerlegbar aber momentan reicht dieser Grad an Genauigkeit aus.
+
[[Tutorial_OpenGL3_Zeichenkontext|Erstellen eines Grafik Kontext]]
Am Anfang der Pipeline stehen die Vertexdaten, diese werden über ein Vertex Buffer Object(VBO) oder über ein Vertex Array(VA) übergeben.
 
Ein VBO ist ein Stück Speicher, in den Daten hinterlegt werden können, egal ob Vertice, Normalen oder Userdaten.
 
Man weist dann Teile des Buffers Variablen, im Vertex/Fragment Shader, zu und kann somit eine Interpretation der Daten realisieren.
 
Die zuweisung, auf ein Shader Attribut wird über VA realisiert, es bildet hierbei die Brücke.
 
Bei einem VBO gibt es 2 Typen, einmal Element und einmal Vertice, es kann nur ein Element Buffer verwendet werden aber mehrere Vertice Buffer.
 
Der Element Buffer enhält Indices und unterliegt im vergelich zum Vertex Buffer keiner besonderen Regel.
 
Die Vertex Buffer hingegen müssen die gleiche länge besitzen, was bedeutet, wenn im einen Vertex Buffer 4 Dateneinheiten stehen, dann müssen auch im anderen Buffer 4 Dateneinheiten vorhanden sein.
 
Dies lässt sich recht einfach erklären, denn man Geometrie zeichnen will, dann benötigt man N Punkte und zu jeden Punkt gibt es auch eine Normale, Farbinformation, Texturkoordinate und so weiter.
 
Wenn OpenGL also nun die Geometrie zeichnet, ruft es in allen gebundenen Buffern immer das I. Element auf und würde ein Vertex Buffer nicht entsprechend viele Elemente enthalten, dann gibt es Zeichenfehler.
 
  
Es gibt noch Geometrie Shader, welche in der Abbildung nicht mit eingearbeitet sind, diese sind aktuell nicht im OpenGL Kern implementiert aber über ARB zugreifbar.
+
[[Tutorial_OpenGL3_Das_Objekt_System_von_OpenGL3|Das Objekt System von OpenGL3]]
  
Am Ende der Pipeline erhalten wir die Pixelinformationen für das Endgültige Bild.
+
[[Tutorial_OpenGL3_dead|Vertex Buffer Object]]
  
==Viewport==
+
[[Tutorial_OpenGL3_dead|Verfügbare Geometrie]]
Da die Matrizen in OpenGL3 vom Entwickler verwaltet wird, hat man entsprechend nur noch wenig Einstellungen an OpenGL zu tätigen.
 
OpenGL benötigt Informationen über den Zeichenbereich, damit der Framebuffer korrekt verwaltet wird.
 
Um dies zu ermöglichen, stellt OpenGL die [[glViewport]] Funktion zur verfügung.
 
Diese Funktion wird z.B. verwendet, wenn man mehrere Ansichten einer Szene in einem Framebuffer zeichnen möchte(z.B 3D Grafik Tools wie Blender).
 
Wenn man z.B. glViewport(0,0,320,240); ausführt und eine Fenstergröße von 640x480 hat, dann wird die ganze Szene auf ein Bereich von 320x240 Pixel gezeichnet und an der Unteren, Linken Ecke des Fensters gezeichnet. Nun kann man noch mit glViewport(0,240,320,240); und noch einmal mit glViewport(320,0,320,480); die Szene zeichnen und wir hätten 3 mal die Szene auf unserem Fenster gezeichnet.
 
  
 +
[[Tutorial_OpenGL3_dead|GLSLang]]
  
==Scissor==
+
[[Tutorial_OpenGL3_dead|Geometryshader]]
Neben dieser Funktion gibt es noch eine Scissor Funktionalität, welche den Rasterisierungsprozess beeinflusst.
 
Die Scissor Funktionalität wird durch [[glEnable]](GL_SCISSOR_TEST), [[glDisable]](GL_SCISSOR_TEST) und [[glScissor]](Links,Unten,Breite,Höhe) realisiert.
 
Dabei werden alle Pixel, die ausserhalb des Bereiches liegen, nicht gezeichnet. Hierzu ist zu sagen, dass nur der Shading Prozess abgebrochen wird aber nicht die davor liegende berechnung. Dies benötigt man z.B. bei dem zeichnen des User Interfaces und Schriften, damit diese nicht über ein Editfeld hinaus ragen oder Komponenten nicht ausserhalb einer Übergeordneten Komponente gezeichnet wird.
 
  
=Der vierte Schritt(Zeichnen mit VertexBufferObjects und VertexArrayObject)=
+
[[Tutorial_OpenGL3_dead|Transform Feedback]]
Der Grafik Kontext ist erstellt und bereit seine Arbeit zu verrichten.
 
OpenGL3 benötigt zum zeichnen von Primitiven einen Defaultshader und die Primitivendaten.
 
Die Primitivendaten können über ein Vertex Buffer Object(VBO) oder Vertex Array Object(VAO) erzeugt und bereit gestellt werden.
 
VBO's sind sehr einfach zu handhaben, wie folgender Code zeigen wird.
 
  
<source lang="cpp">//Erstellungsphase:
+
[[Tutorial_OpenGL3_dead|Texturen]]
glGenBuffers(1,&VBOID);//Erstelle ein Buffer Object.
 
glBindBuffer(GL_ARRAY_BUFFER,VBOID);//Das Buffer Object soll als ein VBO gebunden werden.
 
glBufferData(GL_ARRAY_BUFFER,ElementCount*ElementSize,Data,GL_STATIC_DRAW);//Lade die Daten vom Data Pointer in den Grafikspeicher, dabei werden ElementSize*ElementCount Bytes kopiert.
 
  
//Zeichenphase:
+
[[Tutorial_OpenGL3_dead|Frame Buffer Object]]
glBindBuffer(GL_ARRAY_BUFFER,VBOID);
 
glDrawArrays(GL_POINTS,0,ElementCount);//Zeichne aus dem aktuell gebundenen VBO ElementCount Punkte, von Element 0 beginnend.
 
glBindBuffer(GL_ARRAY_BUFFER,0);//Binde das Objekt mit der ID 0, welches immer als Leeres Objekt definiert ist.</source>
 
  
Dies reicht allerdings noch nicht aus, um unsere Punkte zu zeichnen, da aktuell weder ein Vertexshader noch ein Fragmentshader gebunden ist, der die verarbeitung der Daten übernimmt.
+
[[Tutorial_OpenGL3_Scissor_Clipping_DepthTest|Clipping/Scissor/Tiefen-Test]]
In OpenGL 1 bis 2 gab es eine Fixed Function Pipeline bzw. später eine automatisch anpassende Render Pipeline, bestehend aus einen generierten Vertex- und Fragment-Shader sowie den Fixed Function Teil.
 
OpenGL3 geht keinen der beiden Wege, sondern beschreitet einen neuen und legt fest, dass der Entwickler diese beiden Shader selber liefern muss und stellt den rest über Fixed Function bereit.
 
Der Vertex- und Fragment-Shader werden über eine extra Shadersprache implementiert, welche sich OpenGL Shader Language oder kurz GLSL nennt.
 
OpenGL3.1 bietet die GLSL Version 1.4 an, die nähere Behandlung dieses Themas würde aber den Rahmen des Artikels sprengen und wäre auch nicht mehr Einsteigerfreundlich.
 
Ich will daher die API zum verwalten von Shader Objekten näher erläutern und einfach ein fertigen Shadercode liefern.
 
  
<source lang="cpp">//Erstellungsphase:
+
[[Tutorial_OpenGL3_dead|Instancing]]
VSO=glCreateShader(GL_VERTEX_SHADER);//Erstellt ein Vertex Shader Objekt.
 
FSO=glCreateShader(GL_FRAGMENT_SHADER);//Erstellt ein Fragment Shader Objekt.
 
  
glShaderSource(VSO,1,&VertexShaderSourcecode,0);//Man übergibt 1 Text, der den Shadercode enthält, mit dem letzten Parameter 0(alle übergebenen Strings sind 0 terminiert).
+
[[Tutorial_OpenGL3_dead|Oclussion Query]]
glShaderSource(FSO,1,&FragmentShaderSourcecode,0);
 
  
glCompileShader(VSO);//Compiliert den Shadercode.
+
[[Tutorial_OpenGL3_dead|Conditional Rendering]]
//glGetShaderiv(VSO,GL_COMPILE_STATUS,&compiled);//Sollte der Shadercode nicht korrekt sein, dann liefert compiled GL_FALSE zurück, sonnst GL_TRUE.
 
glCompileShader(FSO);
 
  
ShaderID=glCreateProgram();//Erstellt ein Shader Programm Objekt, welches aus einen compilierten Vertex- und Fragment-Shader besteht.
+
===Übersichten===
glAttachShader(ShaderID,VSO);//Fügt den Vertexshader hinzu.
+
[[OpenGL3.x_API|OpenGL3-Funktionen nacht Kategorie sortiert]]<br>
glAttachShader(ShaderID,FSO);//Fügt den Fragmentshader hinzu.
+
[[OpenGL3-Funktionsübersicht|OpenGL3-Funktionen alphabetisch sortiert]]
  
glLinkProgram(ShaderID);//Wie bei einer Programmiersprache üblich, wird nach dem compilieren des Sourcode, die entstandenen Codesegmente zu einem Machienencode gelinkt und somit Referenzen aufgelöst.
+
[[Kategorie:Tutorial|OpenGL3]]
//glGetProgramiv(ShaderID,GL_LINK_STATUS,&compiled);//Verhält sich wie bei den vorher compilierten Shader.
 
glEnableVertexAttribArray(glGetAttribLocation(ShaderID,Name));//Finde die Speicheradresse vom Attribute, mit entsprechendem Name und aktiviere das Attribute.
 
glVertexAttribPointer(glGetAttribLocation(ShaderID,Name),3,GL_FLOAT,GL_FALSE,0,0);//glVertexAttribPointer(Speicheradresse,Vektordimension,Vektortyp,Normalisieren,Datenoffset,Datenpointer)Wenn Datenpointer 0 ist, dann wird das aktuell gebundene Buffer Object verwendet, sonnst die Speicheradresse, auf die Datenpointer zeigt.
 
 
 
Zeichenphase:
 
glUseProgram(ShaderID);//Binde das zuvor erstellte Programm als aktuell zu nutzendes Program.
 
glUniformMatrix4fv(glGetUniformLocation(ShaderID,VariableName),1,GL_FALSE,&ProjectionMatrix);//Sucht die Speicheradresse von VariableName, im Shader Program, übergibt diese dann einer weiteren Funktion, um an dieser Speicheradresse unsere ProjectionMatrix zu kopieren(2. Parameter gibt die Anzahl der Matrizen an und der 3. ob die Matrix Transponiert werden soll).
 
//zeichenaufruf
 
glUseProgram(0);//Binde das Program Objekt mit der ID 0, welches als Leerer Shader(kein Shader aktiv) implementiert ist.</source>
 
Wir müssen dem Shader die VBO Daten verfügbar machen, dies geschieht über die VertexAttrib Funktionen.
 
Als erste muss ein Attribut, im Shader, lokalisiert und aktiviert werden, dazu wird glGetAttribLocation und glEnableVertexAttribArray verwendet.
 
Der zweite Schritt wäre dann das binden von unserem VBO an dieses Attribut, indem glGetAttribLocation,glVertexAttribPointer sowie glBindBuffer verwendet wird.
 
Bevor man das VertexAttrib setzen kann, muss das entsprechende VBO vorher gebunden werden, da immer nur ein BO aktiv sein kann.
 
Wenn man mehrere VBO verwenden will, um z.B. noch Farben oder Texturkoordinaten zu binden, dann bindet man erst den ersten Buffer, setzt das VertexAttribut, bindet den zweiten Buffer, setzt das VertexAttribut und so weiter. Das ganze muss nicht jeden Renderdurchgang neu machen, sondern kann es nach dem erstellen der Resourcen einmal machen.
 
Allerdings sind IndexBuffer und/oder einer der Vertexbuffer zu binden, damit der Shader die richtigen Buffer Objects nutzt.
 
Das ganze kann noch weiter vereinfacht werden, indem man ein VAO verwendet, dabei wird ein VAO erstellt, gebunden, dann alle VBO's erstellt, die Vertex Attribute gesetzt und das VAO wieder ausgebunden. Wenn man nun statt der VBO's und so weiter das VAO bindet, wird dieses alle anderen Resourcen(VBO, Vertexbassierte Flags), automatisch binden und setzen.
 
 
 
VertexShader:
 
<source lang="glsl">#version 140
 
 
 
uniform mat4 ProjectionMatrix;
 
 
 
in vec4 Vertex;
 
 
 
void main(void)
 
{
 
  gl_Position=ProjectionMatrix*Vertex;
 
  gl_FrontColor=vec4(1.0f,0.0f,0.0f,1.0f);
 
}</source>
 
 
 
FragmentShader:
 
<source lang="glsl">#version 140
 
 
 
out vec4 gl_FragColor;
 
 
 
void main(void)
 
{
 
  gl_FragColor=gl_Color;
 
}</source>
 

Aktuelle Version vom 9. März 2014, 12:06 Uhr

Vorwort

Willkommen zur Einführung in OpenGL3.x. Im Rahmen dieses Artikels werde ich versuchen, die Grundlagen für die Nutzung von OpenGL3 zu legen und durch Pseudocode die Verwendung von der API aufzeigen. Mit OpenGL Version 3 hat sich vieles im Vergleich zu den Vorversionen verändert und entsprechend ist der Umstieg von OpenGL1-2 auf 3 sehr zeitaufwändig. Diese Artikelreihe richtet sich mehr an Anfänger als an Programmierer, die von der Vorversion umsteigen wollen.

OpenGL3 und die Vorgeschichte

OpenGL ist viele Jahre alt und entsprechend gab es immer wieder neue Versionen und Änderungen. Doch entfernte sich OpenGL mit der Zeit vom aktuellen Stand der Technik und veraltete immer mehr. Die API wurde größer und größer, alte nicht mehr gebrauchte Funktionen wurden aus Kompatibilitätsgründen nicht entfernt und die Treiber wuchsen zu riesigen und komplexen Codewerken. Darunter hat entsprechend die Leistung und Qualität stark gelitten. Es musste ein radikaler Schnitt gemacht werden und man beschloss, dies mit OpenGL Version 3 zu tun. So hat man sämtlichen Ballast von früher rausgestrichen und eine Hand voll neuer Funktionen hinzugefügt.

Um die Umstellung für Software leichter zu machen, beschloss man, zwei verschiedene Profile zu unterstützen. Das erste Profil ist ein OpenGL3-fähiger Grafikkontext, welcher auch die alten Befehle ausführen kann und somit die Umstellung schrittweise ermöglicht. Das zweite Profil ist ein OpenGL3-fähiger Grafikkontext, welcher nur die als nicht veraltet (deprecated) makierten Funktionen ausführen kann und für neue Software gedacht ist. Sollte man mit dem zweiten Profil arbeiten und ruft dennoch eine alte Funktion auf, dann wirft diese ein Fehler und wird nicht ausgeführt.

Mit den neuen Fähigkeiten der Grafikkarten entstanden parallel zu den OpenGL-Versionen auch Updates der Shadersprache GLSL. OpenGL verwendet Shader, um die Darstellung von 3D Modellen manipulieren zu können. So hat man anfangs mit Assembler ähnlichen Code und später mit C ähnlichen Code Mini-Programme geschrieben, welche auf dem Grafikprozessor lauffähig waren. Man hatte zwischen Vertex- und Fragment-Shadern/Programmen unterschieden. Mit dem Shader Model 4 kam eine weitere Shader-Kategorie hinzu, und zwar der Geometry-Shader. Während der Vertexshader einzelne Punkte eines Drahtgitters manipulieren konnte, hat der Fragment-Shader das Ausfüllen des Drahtgitters übernommen (shading) und die Geometry-Shader erlauben die Manipulation des Drahtgitters. Während Shader in OpenGL1-2 nicht notwendig waren, kann man in OpenGL3 nicht ohne auskommen, da ein Vertex-/Fragment-Shader zum Zeichnen benötigt wird.

Ein sehr beliebtes Werkzeug in OpenGL1-2, war der Immediate Mode, welcher das sehr einfache Zeichnen von 3D Daten erlaubte. Dieser wurde durch ein glBegin eingeleitet, ein glEnd beendet und alles was dazwischen stand wurde gezeichnet. Dies hatte allerdings auch seinen Preis: So war der Treibercode dadurch enorm komplexer geworden und es mussten aufgrund der vielen möglichen Variationen(gesetzte Flags) viele Prüfungen durchgeführt werden, um einen gültigen Rendercode zu erzeugen. Dieser wurde ebenfalls in OpenGL3 gestrichen und man muss nun sogenannte Vertex Buffer Objects (untermenge von Buffer Objects) verwenden. Diese haben den Vorteil, dass sie wesentlich schneller und ebenfalls recht einfach zu bedienen sind.

In OpenGL1-2 war es möglich, die Modelview- und Projection-Matrizen durch bestimmte API-Befehle zu manipulieren. Die Modelview-Matrix hat die Position eines Objektes so manipuliert, dass es den gewollten Platz in der 3D Welt eingenommen hat und die Projection-Matrix hat dann die 3D Weltkoordinaten auf 2D Bildschirmkoordinaten transformiert. Mit OpenGL3 sind ist diese Möglichkeit entfernt worden, da nun der Vertexshader diese Arbeit übernommen hat und diese Funktionalität mehr in den Anwendercode als in die Bibliothek gehört.

Die letzten 3 angesprochenen Punkte (Shader, Immediate Mode und Matrizen) haben großen Einfluss auf den Basis-Quellcode einer OpenGL3-Anwendung. Dieser fällt größer und umfangreicher aus, als ein Basis-Code für OpenGL1-2, wird aber später kaum größer aufgrund der Schlankheit der neuen API.

Inhaltsverzeichnis

Grundlagen

Artikel in diesem Bereich sind für OpenGL wichtig aber haben nicht direkt mit OpenGL zu tun.

Man kann diese Artikel überspringen und später bei aufkommenden Fragen in diese hinein lesen.

Lineare Algebra

Artikelreihe

Vorschau auf das kommende

Erstellen eines Grafik Kontext

Das Objekt System von OpenGL3

Vertex Buffer Object

Verfügbare Geometrie

GLSLang

Geometryshader

Transform Feedback

Texturen

Frame Buffer Object

Clipping/Scissor/Tiefen-Test

Instancing

Oclussion Query

Conditional Rendering

Übersichten

OpenGL3-Funktionen nacht Kategorie sortiert
OpenGL3-Funktionen alphabetisch sortiert