Tutorial OpenGL3 Zeichenkontext: Unterschied zwischen den Versionen
K (→Verwaltung der veralteten und neuen Funktionen: => Transform-Feedback korrekt verlinkt) |
K (Rechtschreibung, Zeichensetzung...) |
||
Zeile 1: | Zeile 1: | ||
==Der Grafikcontext== | ==Der Grafikcontext== | ||
Der Grafikcontext (GC) ist die Basis von OpenGL, man kann mehrere GCs in einem Prozess haben, was aber selten Sinn macht. | Der Grafikcontext (GC) ist die Basis von OpenGL, man kann mehrere GCs in einem Prozess haben, was aber selten Sinn macht. | ||
− | Im GC werden alle notwendigen Informationen gehalten, um mit der GPU zu arbeiten | + | Im GC werden alle notwendigen Informationen gehalten, um mit der GPU zu arbeiten. Dabei werden Identifier (ID) verwendet, um Resourcen nach außen verfügbar zu machen. Zu solchen Ressourcen gehören z.B. Texturen, Shader, diverse Buffer Objects und alle werden durch IDs zur Verfügung gestellt. |
− | Neben den ID-Listen werden noch sogenannte States | + | Neben den ID-Listen werden noch sogenannte States - Informationen für die Bildausgabe - und diverse unbekannte treiberspezifische Daten gespeichert. |
===Profil=== | ===Profil=== | ||
− | Um die einzelnen Befehlssätze zu | + | Um die einzelnen Befehlssätze zu verwalten, hat man sogenannte Profile eingeführt. |
− | OpenGL3 ist z.B. ein Profil, es gibt noch weitere | + | OpenGL3 ist z.B. ein Profil, es gibt noch weitere wie z.B. OpenGL3.1 oder OpenGL3.1 Debug. |
− | Die Profile werden vom ARB | + | Die Profile werden vom ARB festgelegt und es gibt in der Regel 2 Versionen: Einmal mit Funktionen, die als "deprecated" eingestuft wurden, und einmal ohne diese. |
===Forward compatible context und Full context=== | ===Forward compatible context und Full context=== | ||
− | Es gibt 2 Varianten eines Context, der Full context | + | Es gibt 2 Varianten eines Context, der ''Full context'' enthält alle Funktionen, auch die als deprecated markierten. Der ''Forward compatible context'' enthält nur die nicht als deprecated markierten Funktionen des OpenGL-Kerns. Bis zur Version 3.1 gab es immer eine Abwärtskompatibilität und der Treiber hatte entschieden, welche OpenGL-Version verwendet werden darf. Mit OpenGL 3.1 gibt es keine Abwärtskompatibilität mehr und man kann festlegen, was für einen GC man haben möchte. |
===Verwaltung der veralteten und neuen Funktionen=== | ===Verwaltung der veralteten und neuen Funktionen=== | ||
− | Das | + | Das Hinzukommen und das Entfernen von OpenGL-Funktionen unterliegt dem Deprecation- und Extension-Mechanismus. |
Diese funktionieren wie folgt. | Diese funktionieren wie folgt. | ||
'''Deprecation Path''': Core->ARB->Vendor/Extension | '''Deprecation Path''': Core->ARB->Vendor/Extension | ||
− | Die Funktion wird erst aus den Bereich der Kernfunktionen entfernt und als ARB zur | + | Die Funktion wird erst aus den Bereich der Kernfunktionen entfernt und als ARB zur Verfügung gestellt. |
Dann wird sie aus dem ARB entfernt und als Vendor oder Extension weiter geführt. | Dann wird sie aus dem ARB entfernt und als Vendor oder Extension weiter geführt. | ||
Der Kern wird von der Khronos Group verwaltet, das ARB wird von einer Gruppe bestehend aus AMD/ATI, Nvidia, SGI, Sun, Intel, IBM, Apple, 3DLabs und einigen weiteren zusammen verwaltet und Vendor sowie Extension werden von Firmen wie AMD, Nvidia, SIS und so weiter einzeln verwaltet. | Der Kern wird von der Khronos Group verwaltet, das ARB wird von einer Gruppe bestehend aus AMD/ATI, Nvidia, SGI, Sun, Intel, IBM, Apple, 3DLabs und einigen weiteren zusammen verwaltet und Vendor sowie Extension werden von Firmen wie AMD, Nvidia, SIS und so weiter einzeln verwaltet. | ||
Zeile 24: | Zeile 24: | ||
'''Extension Path''': Vendor/Extension->ARB->Core | '''Extension Path''': Vendor/Extension->ARB->Core | ||
− | Wenn eine Extension | + | Wenn eine Extension von einer Firma, vom ARB als sinnvoll angesehen wird, dann wird diese mit aufgenommen. |
− | Funktionen, die vom ARB aufgenommen wurden, werden in der Regel mit der kommenden OpenGL Version in den Kern aufgenommen. | + | Funktionen, die vom ARB aufgenommen wurden, werden in der Regel mit der kommenden OpenGL-Version in den Kern aufgenommen. |
− | OpenGL3 macht regen Gebrauch von diesen Mechanismen, da viele Kernfunktionen als deprecated markiert wurden und nun über die einzelnen Updates aus dem Kern verschwinden. Da sich der Stand der Technik | + | OpenGL3 macht regen Gebrauch von diesen Mechanismen, da viele Kernfunktionen als deprecated markiert wurden und nun über die einzelnen Updates aus dem Kern verschwinden. Da sich der Stand der Technik weiterentwickelt kommen natürlich auch neue Funktionalitäten hinzu, so z.B. [[Transform-Feedback]], [[Instancing]] oder GLSlang 1.4. |
=Der erste Schritt (OpenGL Context)= | =Der erste Schritt (OpenGL Context)= | ||
− | Als erstes wird ein Fenster benötigt, um an dieses unseren GC zu binden. Ich will nicht näher auf die Erstellung eines Fensters eingehen, da dies nicht das Thema dieses Artikels ist und verweise auf den Democode am Ende des Artikels. Sobald das Fenster erstellt ist, können wir uns darum kümmern einen passenden GC zu erstellen. Hierzu brauchen wir erstmal Informationen | + | Als erstes wird ein Fenster benötigt, um an dieses unseren GC zu binden. Ich will nicht näher auf die Erstellung eines Fensters eingehen, da dies nicht das Thema dieses Artikels ist und verweise auf den Democode am Ende des Artikels. Sobald das Fenster erstellt ist, können wir uns darum kümmern, einen passenden GC zu erstellen. Hierzu brauchen wir erstmal Informationen vom Desktop Manager, welche Möglichkeiten wir überhaupt zur Auswahl haben. Es wird ein [[Doppelpufferung|Double Buffer]] benötigt und man muss die Farbtiefe sowie Genauigkeit des [[Tiefenpuffer]]s festlegen. Dies wird von den Desktop Managern unterschiedlich gehandhabt, so hat Windows z.B. ein DeviceContext und ein Pixelformat und X11 nennt dies VisualInfo bzw. GLXFBConfig. |
− | Ist dieser Schritt getan kann man nun einen alten OpenGL Context erstellen, prüfen ob die ARB Funktion vorhanden ist und dann versuchen einen OpenGL3.x Context zu erstellen. | + | Ist dieser Schritt getan, kann man nun einen alten OpenGL Context erstellen, prüfen ob die ARB Funktion vorhanden ist und dann versuchen einen OpenGL3.x Context zu erstellen. |
==Erstellung eines OpenGL3.x GC== | ==Erstellung eines OpenGL3.x GC== | ||
− | Um | + | Um einen GC ertellen zu können, wird eine weitere API benötigt, welche plattformabhängig und durch wgl[Funktionsname]/glX[Funktionsname] erkennbar ist. Mit diesen Befehlen kann man mit den Windows und X11 Desktop Manager zusammenarbeiten. So werden Funktionen für das Erstellen, Wechseln, Zerstören eines GC, Laden von Extensions, Wechseln des Fensterpuffers und Synchronisieren von CPU und GPU ermöglicht. Bisher gibt es noch keine Möglichkeit, einen OpenGL3 fähigen GC zu erstellen, ohne dafür eine Funktion vom ARB zu verwenden. Der Nachteil von ARB Funktionen ist, dass man einen gültigen GC benötigt, um den Zeiger auf diese zu erhalten. Um einen OpenGL 3.0 oder 3.1 GC zu erstellen, benötigt man einen OpenGL1-2 GC und die Kernfunktion [[wglGetProcAddress]]/[[glxGetProcAddress]]. Einen gültigen OpenGL1 bzw. OpenGL2 GC bekommt man über den Befehl [[wglCreateContext]]/[[glxCreateContext]] und zwischen mehreren GC kann man mit dem Befehl [[wglMakeCurrent]]/[[glxMakeCurrent]] wechseln. |
− | Der Befehl für die Erstellung eines OpenGL3 fähigen GC | + | Der Befehl für die Erstellung eines OpenGL3-fähigen GC heißt [[wglCreateContextAttribsARB]]/[[glxCreateContextAttribsARB]]. |
− | Mit OpenGL3.2 soll eine Funktion in den OpenGL Kern kommen, welcher es erlaubt einen OpenGL3 und aufwärts fähigen GC zu erstellen, ohne einen älteren GC vorher zu erstellen. Dies wird erreicht, | + | Mit OpenGL3.2 soll eine Funktion in den OpenGL Kern kommen, welcher es erlaubt einen OpenGL3 und aufwärts fähigen GC zu erstellen, ohne einen älteren GC vorher zu erstellen. Dies wird erreicht, indem man die noch jetzige ARB Funktion in den OpenGL-Kern mit aufnimmt und somit das Erfragen der ARB Funktion, über ein OpenGL1-2GC, unnötig macht. |
'''Windows''' | '''Windows''' | ||
Zeile 85: | Zeile 85: | ||
}</source> | }</source> | ||
− | Mac OS erlaubt die nachträgliche Installation von X11 und kann somit über | + | Mac OS erlaubt die nachträgliche Installation von X11 und kann somit über den folgenden Code ebenfalls einen OpenGL Context erstellen. Alternativ bietet Mac OS mehrere OpenGL Schnittstellen, welche sich in der Einfachheit der API unterscheiden. Wenn man nicht den Nutzer zwingen will X11 zu installieren, dann sollte man zu den entsprechenden Schnittstellen AGL, CGL oder NSOpenGL greifen. |
'''X11(Linux/Mac OS)''' | '''X11(Linux/Mac OS)''' |
Version vom 27. November 2013, 22:55 Uhr
Inhaltsverzeichnis
Der Grafikcontext
Der Grafikcontext (GC) ist die Basis von OpenGL, man kann mehrere GCs in einem Prozess haben, was aber selten Sinn macht. Im GC werden alle notwendigen Informationen gehalten, um mit der GPU zu arbeiten. Dabei werden Identifier (ID) verwendet, um Resourcen nach außen verfügbar zu machen. Zu solchen Ressourcen gehören z.B. Texturen, Shader, diverse Buffer Objects und alle werden durch IDs zur Verfügung gestellt. Neben den ID-Listen werden noch sogenannte States - Informationen für die Bildausgabe - und diverse unbekannte treiberspezifische Daten gespeichert.
Profil
Um die einzelnen Befehlssätze zu verwalten, hat man sogenannte Profile eingeführt. OpenGL3 ist z.B. ein Profil, es gibt noch weitere wie z.B. OpenGL3.1 oder OpenGL3.1 Debug. Die Profile werden vom ARB festgelegt und es gibt in der Regel 2 Versionen: Einmal mit Funktionen, die als "deprecated" eingestuft wurden, und einmal ohne diese.
Forward compatible context und Full context
Es gibt 2 Varianten eines Context, der Full context enthält alle Funktionen, auch die als deprecated markierten. Der Forward compatible context enthält nur die nicht als deprecated markierten Funktionen des OpenGL-Kerns. Bis zur Version 3.1 gab es immer eine Abwärtskompatibilität und der Treiber hatte entschieden, welche OpenGL-Version verwendet werden darf. Mit OpenGL 3.1 gibt es keine Abwärtskompatibilität mehr und man kann festlegen, was für einen GC man haben möchte.
Verwaltung der veralteten und neuen Funktionen
Das Hinzukommen und das Entfernen von OpenGL-Funktionen unterliegt dem Deprecation- und Extension-Mechanismus. Diese funktionieren wie folgt.
Deprecation Path: Core->ARB->Vendor/Extension
Die Funktion wird erst aus den Bereich der Kernfunktionen entfernt und als ARB zur Verfügung gestellt. Dann wird sie aus dem ARB entfernt und als Vendor oder Extension weiter geführt. Der Kern wird von der Khronos Group verwaltet, das ARB wird von einer Gruppe bestehend aus AMD/ATI, Nvidia, SGI, Sun, Intel, IBM, Apple, 3DLabs und einigen weiteren zusammen verwaltet und Vendor sowie Extension werden von Firmen wie AMD, Nvidia, SIS und so weiter einzeln verwaltet.
Extension Path: Vendor/Extension->ARB->Core
Wenn eine Extension von einer Firma, vom ARB als sinnvoll angesehen wird, dann wird diese mit aufgenommen. Funktionen, die vom ARB aufgenommen wurden, werden in der Regel mit der kommenden OpenGL-Version in den Kern aufgenommen.
OpenGL3 macht regen Gebrauch von diesen Mechanismen, da viele Kernfunktionen als deprecated markiert wurden und nun über die einzelnen Updates aus dem Kern verschwinden. Da sich der Stand der Technik weiterentwickelt kommen natürlich auch neue Funktionalitäten hinzu, so z.B. Transform-Feedback, Instancing oder GLSlang 1.4.
Der erste Schritt (OpenGL Context)
Als erstes wird ein Fenster benötigt, um an dieses unseren GC zu binden. Ich will nicht näher auf die Erstellung eines Fensters eingehen, da dies nicht das Thema dieses Artikels ist und verweise auf den Democode am Ende des Artikels. Sobald das Fenster erstellt ist, können wir uns darum kümmern, einen passenden GC zu erstellen. Hierzu brauchen wir erstmal Informationen vom Desktop Manager, welche Möglichkeiten wir überhaupt zur Auswahl haben. Es wird ein Double Buffer benötigt und man muss die Farbtiefe sowie Genauigkeit des Tiefenpuffers festlegen. Dies wird von den Desktop Managern unterschiedlich gehandhabt, so hat Windows z.B. ein DeviceContext und ein Pixelformat und X11 nennt dies VisualInfo bzw. GLXFBConfig. Ist dieser Schritt getan, kann man nun einen alten OpenGL Context erstellen, prüfen ob die ARB Funktion vorhanden ist und dann versuchen einen OpenGL3.x Context zu erstellen.
Erstellung eines OpenGL3.x GC
Um einen GC ertellen zu können, wird eine weitere API benötigt, welche plattformabhängig und durch wgl[Funktionsname]/glX[Funktionsname] erkennbar ist. Mit diesen Befehlen kann man mit den Windows und X11 Desktop Manager zusammenarbeiten. So werden Funktionen für das Erstellen, Wechseln, Zerstören eines GC, Laden von Extensions, Wechseln des Fensterpuffers und Synchronisieren von CPU und GPU ermöglicht. Bisher gibt es noch keine Möglichkeit, einen OpenGL3 fähigen GC zu erstellen, ohne dafür eine Funktion vom ARB zu verwenden. Der Nachteil von ARB Funktionen ist, dass man einen gültigen GC benötigt, um den Zeiger auf diese zu erhalten. Um einen OpenGL 3.0 oder 3.1 GC zu erstellen, benötigt man einen OpenGL1-2 GC und die Kernfunktion wglGetProcAddress/glxGetProcAddress. Einen gültigen OpenGL1 bzw. OpenGL2 GC bekommt man über den Befehl wglCreateContext/glxCreateContext und zwischen mehreren GC kann man mit dem Befehl wglMakeCurrent/glxMakeCurrent wechseln. Der Befehl für die Erstellung eines OpenGL3-fähigen GC heißt wglCreateContextAttribsARB/glxCreateContextAttribsARB. Mit OpenGL3.2 soll eine Funktion in den OpenGL Kern kommen, welcher es erlaubt einen OpenGL3 und aufwärts fähigen GC zu erstellen, ohne einen älteren GC vorher zu erstellen. Dies wird erreicht, indem man die noch jetzige ARB Funktion in den OpenGL-Kern mit aufnimmt und somit das Erfragen der ARB Funktion, über ein OpenGL1-2GC, unnötig macht.
Windows
void CreateOpenGL3Context()
{
HGLRC TempContext=wglCreateContext(DeviceContext);//erstellt ein alten OpenGL Context
if (TempContext==NULL)
{
cerr<<"Error: Could not create an OpenGL rendering context"<<endl;
return;//beenden
}
wglMakeCurrent(DeviceContext,TempContext);//setzt den erstellten GC als aktuellen GC
//Typdefinition von wglCreateContextAttribsARB
typedef HGLRC (APIENTRY * PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hDC, HGLRC hShareContext, const int *attribList);
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;
//abfragen, ob die Funktion existiert
wglCreateContextAttribsARB=(PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
if(wglCreateContextAttribsARB == NULL)//wenn es diese Funktion nicht gibt, dann hat der -->Treiber<-- keinen OpenGL3 support
{
wglDeleteContext(TempContext);
cerr<<"Error: There is no OpenGL3 context support."<<endl;
return;
}
int attribs[]={WGL_CONTEXT_MAJOR_VERSION_ARB,3,WGL_CONTEXT_MINOR_VERSION_ARB,1,WGL_CONTEXT_FLAGS_ARB,WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,0};
if (!(Context=wglCreateContextAttribsARB(DeviceContext,0, attribs)))//versuche ein OpenGL3.1 fähigen Context zu erstellen
{
//Entweder hat der Treiber noch keinen OpenGL3.1 support oder die Grafikkarte beherrscht kein OpenGL3.1.
cerr<<"Error: Couldn't create OpenGL3.1 context. Try now OpenGL3.0 context"<<endl;
return;
attribs[3]=0;//Setze minor version auf 0 um ein OpenGL3.0 context zu erstellen.
if (!(Context=wglCreateContextAttribsARB(Win->GetDeviceContext(),0, attribs)))
{
//Die -->Grafikkarte<-- beherrscht kein OpenGL3.
wglDeleteContext(TempContext);//aufräumen und beenden
cerr<<"Error: Couldn't create OpenGL3 context."<<endl;
return;
}
}
wglMakeCurrent(DeviceContext,Context);//wechsel auf den OpenGL3.x context
wglDeleteContext(TempContext);//Zerstöre den temporären Context, denn er wird nicht länger benötigt.
}
Mac OS erlaubt die nachträgliche Installation von X11 und kann somit über den folgenden Code ebenfalls einen OpenGL Context erstellen. Alternativ bietet Mac OS mehrere OpenGL Schnittstellen, welche sich in der Einfachheit der API unterscheiden. Wenn man nicht den Nutzer zwingen will X11 zu installieren, dann sollte man zu den entsprechenden Schnittstellen AGL, CGL oder NSOpenGL greifen.
X11(Linux/Mac OS)
bool OpenGLWindow::CreateOpenGL3Context()
{
GLXContext TempContext=glXCreateContext(m_Display,m_VisualInfo,0,GL_TRUE);//erstellt ein alten OpenGL Context
if(TempContext==0)
{
cerr<<"Error: Could not create an OpenGL rendering context."<<endl;
return false;
}
glXMakeCurrent(m_Display,m_Window,TempContext);
//Typdefinition von wglCreateContextAttribsARB
typedef GLXContext (* GLXCREATECONTEXTATTRIBSARBPROC)(Display *dpy,GLXFBConfig config,GLXContext share_context,Bool direct,const int *attrib_list);
//abfragen, ob die Funktion existiert
GLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (GLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB");
if(glXCreateContextAttribsARB == NULL)//wenn es diese Funktion nicht gibt, dann hat der -->Treiber<-- keinen OpenGL3 support
{
cerr<<"Error: There is no OpenGL3 context support."<<endl;
return false;
}
int minor=0;
int major=0;
glGetIntegerv(GL_MAJOR_VERSION,&major);
glGetIntegerv(GL_MINOR_VERSION,&minor);
int attribs[]={GLX_CONTEXT_MAJOR_VERSION_ARB,major,GLX_CONTEXT_MINOR_VERSION_ARB,minor,GLX_CONTEXT_FLAGS_ARB,GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,0};
for (int i=minor; i>=0;i--)
{
attribs[3]=i;//Setze minor version auf 0 um ein OpenGL3.0 context zu erstellen.
m_Context=glXCreateContextAttribsARB(m_Display, m_FBConfig[0], NULL, true, attribs);
if (!m_Context)//versuche ein OpenGL3.i fähigen Context zu erstellen
{
if (i>0)
{
//Entweder hat der Treiber noch keinen OpenGL3.i support oder die Grafikkarte beherrscht kein OpenGL3.i.
cerr<<"Error: Couldn't create OpenGL3."<<i<<" context. Try now OpenGL3."<<i-1<<" context"<<endl;
continue;
}
else
{
//Die -->Grafikkarte<-- beherrscht kein OpenGL3.
glXDestroyContext(m_Display,TempContext);//aufräumen und beenden
cerr<<"Error: Couldn't create OpenGL3 context."<<endl;
return false;
}
}
break;
}
glXMakeCurrent(m_Display,m_Window,m_Context);//wechsel auf den OpenGL3.x context
glXDestroyContext(m_Display,TempContext);
return true;
}
}