OpenGL.org 3Dsource.de: Infos rund um 3D-Computergrafik, OpenGL und VRML
space Telefon-Tarife space VDI - Arbeitskreis Fahrzeugtechnik space Beschallungsanlagen und Elektroakustik space Heise-News space

2 Erste Schritte 

2.005 Wo kann ich Informationen zur 3D-Grafik bekommen ?

Die comp.graphics.algorithms FAQ enthält jede Menge Informationen zur 3D Grafik, die nicht nur speziell auf OpenGL zugeschnitten sind.

Für allgemeine Informationen zur OpenGL und 3D Computergrafik bietet sich der Zugriff auf die Siggraph Kurse, insbesondere Advanced Graphics Programming Techniques Using OpenGL an. Diese Kurse bieten jede Menge an Informationen, die auch Lösungen zu spezielleren Problemen aufzeigen.

Ein sehr gutes Buch für den Einstieg in die Computergrafik ist Computer Graphics: Principles and Practice, Second Edition, by James Foley, et al. ISBN 0-201-12110-7. Dieses Buch scheint derzeit vergriffen zu sein. Man kann aber nach Restbeständen bei den Online-Händlern suchen (Amazon oder Boysen und Maasch, ISBN eingeben). Eine Neuauflage ist für 2003 geplant.

Hier gibt es Delphi Code für grundlegende Vektor-, Matrix- und Quaternionberechnungen.

Hier gibt es eine C++ 3D Mathe-Bibliotehk und weitere Quellen zur linearen Algebra.

2.010 Wo kann ich Beispielprogramme, Tutorials, Unterlagen und anderes zu OpenGL finden ?

OpenGL stellt die derzeit am umfangreichsten dokumentierte 3D-API dar, deren Unterlagen nicht nur im Web, sondern auch gedruckt bezogen werden können. Allerdings ist es wohl unmöglich, alle Quellen aufzulisten. Diese FAQ bietet daher Links zu zentralen OpenGL Webseiten und anderen Anbietern, die weitere Quellen aufzeigen und die Links pflegen.

OpenGL Organization Web Page

SGI's OpenGL FTP Archiv und SGI's OpenGL Webseite.

HP's OpenGL Index-Seite.

OpenGL Basics FAQ

OpenGL Game Developer's FAQ
Zusätzlich zu OpenGL bietet die OpenGL Game Developer's FAQ auch Informationen über die OpenGL Game Developer's mailing list.

The EFnet OpenGL FAQ

Samuel Paik hat eine Sammlung von Links zu OpenGL für Microsoftzusammengestellt.

Die OpenGL.org Webseite bietet Zugriff auf die aktuellen Spezifikationen und Hilfetexte.

Dieses hier ist eine Fundgrube für die Nutzung von OpenGL auf verschiedensten Plattformen.

Der GLUT Quelltext enthält viele lehrreiche Beispielprogramme.

Codeguru bietet eine derzeit zwar noch kleine, aber ständig wachsende Liste von OpenGL Beispielprogrammen mit Quelltext.

Lucian Wischik's Webseite bietet sehr gute Informationen zu OpenGL auf MS Windows Systemen, insbesondere im Zusammenhang mit 3Dfx Karten.

Die NeHe Webseite bietet viele Links zu anderen Seiten und jede Menge nützliche Demos. Diese Seite wird von vielen als erste Anlaufstelle benannt.

Blaine Hodge's Webseite bietet viele Infos zur Programmierung auf Win32.

Hier findet ihr ein interaktives OpenGL Tutorial.

gamedev.net bietet viele Tutorials und Artikel.

2.020 Welche Bücher zu OpenGL gibt es ?

Es gibt zwar sehr viele Bücher zum Thema OpenGL, aber am häufigsten werden das "Red Book" und "Blue Book" referenziert:

OpenGL Programming Guide, Third Edition, Mason Woo et al.
ISBN 0-201-60458-2 (das Red Book)

OpenGL Reference Manual, Third Edition, Dave Shreiner (Editor), et al.
ISBN 0-201-65765-1 (das Blue Book)

Dabei behandelt die jeweils 3.Auflage OpenGL 1.2, die zweite OpenGL 1.1 und die erste OpenGL 1.0.

Einen Link zur Online-Version vom Red Book (2. Auflage) findet ihr hier.

Für das Blue Book gibt es zwei Online Quellen:

einmal bei HP OpenGL Reference Manual, Second Edition (for OpenGL 1.1),
und zum zweiten die ManPages, welche vergleichbar zum Buch sind.

Das Green Book konzentriert sich auf X Windows (Unix), das White Book auf MS Windows Programmierung. Andere Bücher sind auf der OpenGL.org Webseite aufgelistet.

2.030 Welche OpenGL Chats und Newsgroups gibt es ?

Für OpenGL gibt es die comp.graphics.api.opengl newsgroup.

Der #OpenGL IRC Channel steht für den OpenGL Chat.

2.040 Gibt es OpenGL auch mit Quelltext ?

Die Mesa Bibliothek ist eine freie, der OpenGL Spezifikation entsprechende, allerdings aus Kostengründen nicht vom OpenGL ARB lizensierte Implementation.

Ebenfalls verfügbar ist die OpenGL Beispielimplementation von SGI.

2.050 Welche Compiler kann ich für OpenGL nutzen ?

OpenGL Programme sind überwiegend in C und C++ geschrieben. Es ist aber genauso möglich, Delphi (eine von Pascal abgeleitete IDE), Basic, Fortran, Ada und andere zu nutzen.

Borland

Programmieren mit den Borland Compilern geht eigentlich genauso wie mit jedem anderen Compiler auch. Es gibt allerdings eine Ausnahme: OpenGL Programme können während der Laufzeit Fliesskomma-Ausnahmefehler (floating point exceptions) verursachen. Um diesen an sich harmlosen Fehler zu vermeiden, ist folgende Zeile vor dem ersten OpenGL-Aufruf in den Quelltext einzubinden:

_control87(MCW_EM, MCW_EM);

Borland-Nutzer sollten wissen, dass alle Versionen bis 4.0 von Haus aus nur OpenGL 1.0 unterstützen. Man kann allerdings auf OpenGL 1.1/1.2 updaten, indem man den OpenGL SDK bei Microsoft runterlädt bzw. bestellt.

Schneller geht es eventuell, wenn man mittels Borlands "implib.exe" aus vorhandenen "*.dll" die passenden "*.lib" selbst erzeugt. Die Header sollten über die Links bei Frage 2.040 bzw. bei mir zu finden sein.
Wenn man versehentlich die .LIB's im Microsoft-Format (z.B. von Visual C) nutzt, erscheint folgende Fehlermeldung:

C:\BORLAND\BCC55\LIB\GLUT32.LIB' contains invalis OMF record, type 0x21 (possibly COOF)

Der Usenet News-Server "bornews.borland.com" enthält zwei Gruppen für Grafik: borland.public.delphi.graphics und borland.public.cppbuilder.graphics.

Die Borland Community ist eine gute Online-Quelle für typische Fragen zu Borland Compilern.

Informationen zur Nutzung von OpenGL mit dem Borland C++ Builder findet man auf Scott Heiman's Webseite, zum Teil bei mir oder auch hier.

Für Delphi-Nutzer gibt es einmal das Buch Delphi Developer's Guide to OpenGL von Jon Jacobs, aber auch Online-Quellen bei Lischke-Online und auf der Delphi3D Webseite. Code und Utilities findet hier.

Visual Basic

Hier sind drei Seiten, die sich mit OpenGL und Visual Basic beschäftigen:

http://www.softoholic.bc.ca/opengl/down.htm
http://www.weihenstephan.de/~syring/ActiveX/
http://www.ieighty.net/~davepamn/colorcube.html.

2.060 Was brauche ich, um OpenGL Programme übersetzen und ausführen zu können ?

Das Folgende beschäftigt sich mit C/C++.

Um eigene OpenGL Programme übersetzen und linken zu können, werden Header (*.h*) und Bibliotheken (*.lib) benötigt. Um Programme auszuführen, darüber hinaus auch Shared Libraries (*.so) oder Dynamical Loaded Libraries (*.dll) oder auch hardwarespezifische Bibliotheken (ICD, Installable Client Driver). Das betrifft die Basisheader (gl.h, glu.h und eventuell glut.h) genauso wie die passenden Bibliotheken, deren Bezeichnung vom verwendeten Betriebssystem abhängt. Welche Dateien man nutzen kann und woher diese bezogen werden können, kann daher nicht allgemein beantwortet werden.

Die OpenGL.org Webseite hält entsprechende Links bzw. die erforderlichen Dateien bereit.

Unter Microsoft Windows 9x, NT, und 2000:

Nach der Installation von Visual C++ sind die Header und Libraries für OpenGL und GLU bereits auf dem System vorhanden.

Um GLUT nutzen zu können, müssen diese Dateien allerdings noch aus dem Netz geladen werden. Dabei ist es zweckmässig, glut.h nach include/GL und glut32.lib nach lib/ zu kopieren. Die glut32.dll sollte nach Windows/system bzw. winnt/system32 kopiert werden.

Letztendlich sollte eine voll installiertes OpenGL Entwicklungsumgebung etwa so aussehen:

Datei gespeichert in
gl.h
glut.h
glu.h
[compiler]\include\gl
Opengl32.lib
glut32.lib
glu32.lib
[compiler]\lib
Opengl32.dll
glut32.dll
glu32.dll
[system]

wobei [compiler] das Compiler-Verzeichnis (z.B. C:\Programme\Microsoft Visual Studio\VC98) und [system] das Windows Systemverzeichnis darstellt (9x: windows\system, NT/2000: winnt\system32).

Um ein hardwarebeschleunigtes OpenGL mit einer geeigneten 3D-Grafikkarte zu erhalten, muss zusätzlich zu den standardmässig installierten Dateien (opengl32.dll, glu32.dll) auch ein ICD installiert werden. Dieser besteht im Regelfall aus kartenspezifischen dll's, die über einen Eintrag in der Registry mit opengl32.dll/glu32.dll verknüpft sind. Dieser ICD ist entweder bei der gekauften Karte dabei oder kann auf der Webseite des Herstellers bezogen werden. Es ist möglich, dass hierdurch auch andere Dateien ersetzt werden, z.B. die Header für hardwareabhängige Extensions. Mehr Informationen über Extensions gibt es auch hier.

Falls euch mal Dateien ohne dass übliche 32 (also opengl.dll und glu.dll) auffallen, das sind Dateien des älteren SDK (Software Development Kit) von SGI für MS Windows. Diese sollte man nicht mehr nutzen, da sie zum einen nur der OpenGL 1.0 Spec entsprechen und zum zweiten auch nicht mehr unterstützt werden. Für hardwarebeschleunigtes OpenGL sollte man auf die MS Bibliotheken zurückgreifen, obwohl auch SGI's Dateien über die 32er MS Dateien auf die 3D-Karte zugreifen können. Mehr Informationen über die SGI Dateien gibt es hier.
Auf keinen Fall dürfen die verwendeten Dateien (MS oder SGI) miteinander zu einem Programm gelinkt werden. Die parallel Installation auf einem System ist aber problemlos möglich (MS = opengl32.lib/dll, glu32.lib/dll, SGI: opengl.lib/dll, glu.lib/dll).

Die für OpenGL benötigten Bibliotheken müssen zum Projekt hinzugefügt werden. Bei Visual C++ 6.0 geht das über Projekt -> Einstellungen -> Linker -> Module. Dort sind glut32.lib, glu32.lib und opengl32.lib einzugeben.

Für UNIX und UNIX-ähnliche Systeme:

Falls die benötigten Header und Libraries nicht in den Standardpfaden des Systems installiert sind, müssen diese mit den üblichen Parametern beim compilieren/linken angegeben werden (-I, -L für die zusätzlichen Pfade, -lglut -lGLU -lGL -lXmu -lX11 in dieser Reihenfolge für die Bibliotheken).

Um GLUT nutzen zu können, findet sich im Netz der Quelltext, teilweise auch vorkompilierte Bibliotheken. Das Übersetzen ist aufgrund des nutzbaren imake Tools im Regelfall problemlos möglich (die README's enthalten meist entsprechende Informationen).

Linux, Macintosh und andere Systeme:

Mesa ist eine frei verfügbare OpenGL-ähnliche Bibliothek, die auf vielen Plattformen genutzt werden kann. Auch die Developer Section auf OpenGL.org bietet Informationen für verschiedene Plattformen.

Anmerkung: Da z.B. Nvidia auch Linux-Treiber für seine Grafikkarten anbietet, macht OpenGL unter Linux mittlerweile richtig Spass. Installationsanleitung und die notwendigen Dateien findet man hier. Falls es Probleme gibt, schaut unbedingt nach den Log-Dateien in /var/logs (X11 und errors), z.B. findet man in diesen auch Hinweise auf ungeeignete BIOS-Einstellungen.

2.070 Warum erhalte ich Fehlermeldungen beim Compilieren, Linken und während des Programmlaufs ?

Die meisten Fehlermeldungen beim Compilieren und Linken resultieren daraus, dass das System entweder über keine Unterstützung der OpenGL Programmierung verfügt oder aber der Compiler/Linker die benötigten Dateien (header, libs) nicht finden kann.

Treten diese Fehler unter MS Windows auf, bitte mal bei Frage 2.060 weiter oben nachschauen, um sicher zu gehen, dass die Dateien in den richtigen Verzeichnissen gespeichert wurden.

Wichtig ist, dass vor jedem #include<GL/gl*.h> zunächst ein #include <windows.h> eingefügt werden muss. Das liegt an Microsofts Sonderweg, der die System-dll's anders als die meisten Win32 C Compiler aufruft. Über die von windows.h eingebundenen anderen Header werden die Standard C Aufrufe aus den gl-Headern über Makros in die MS Syntax umgewandelt.

Ein weiterer Hinweis für Win32 Entwickler: Bei Visual C++ (und den meisten anderen Win32 C Compilern) werden die Standardprojekte mit der Hauptfunktion WinMain(4 Parameter) und nicht mit der unter Unix üblichen main(2 Parameter) angelegt. Nicht nur VC++ bietet aber die Möglichkeit, diesen WinMain() Aufruf zu kapseln, so dass eine normale main() Funktion genutzt werden kann. Hierfür ist eine Konsolenanwendung zu wählen. Dies ist einer der Hauptgründe für Fehlermeldungen, die beim Ausprobieren von Beispielen aus dem Netz auftreten. Die Konsolenapplikation kann entweder über die Linkeroptionen oder über sogenannte pragmas ausgewählt werden:

    // Eins dieser pragmas sollte funktionieren:
    #pragma comment (linker, "/ENTRY:mainCRTStartup")
    #pragma comment (linker, "/ENTRY:wmainCRTStartup")
    #pragma comment (linker, "/ENTRY:WinMainCRTStartup")
    #pragma comment (linker, "/ENTRY:wWinMainCRTStartup")
    // bzw.:
    #pragma comment (linker, "/SUBSYSTEM:WINDOWS")
    #pragma comment (linker, "/SUBSYSTEM:CONSOLE")
      

Die folgende Tabelle enthält eine Liste der häfigen Fehler und deren mögliche Ursachen. Es ist zwar primär auf Visual C++ zugeschnitten, sollte aber prinzipiell auf jeder Plattform gelten.

Fehlermeldung mögliche Ursache und Lösung
d:\c++\file.c(20) : warning C4013: 'glutDestroyWindow' undefined; assuming extern returning int
(Prototype für 'glutDestroyWindow' unbekannt)
d:\c++\file.c(71) : warning C4013: 'glMatrixMode' undefined; assuming extern returning int
(Prototype für 'glMatrixMode' unbekannt)
d:\c++\file.c(71) : error C2065: 'GL_MODELVIEW' : undeclared identifier
(Konstante 'GL_MODELVIEW' unbekannt)
Es wurden nicht alle notwendigen Header eingebunden.
glutDestroyWindow => #include<GL/glut.h>
glMatrixMode => #include<GL/gl.h>

Für OpenGL Programme werden immer diese Header benötigt:
#include <GL/glu.h>
#include <GL/gl.h>
Wird GLUT verwendet, ist ein #include <GL/glut.h>
ausreichend.

c:\program files\microsoft visual studio\vc98\include\gl\gl.h(1152) : error C2054: expected '(' to follow 'WINGDIAPI'
c:\program files\microsoft visual studio\vc98\include\gl\gl.h(1152) : error C2085: 'APIENTRY' : not in formal parameter list
windows.h wurde nicht oder nicht vor den gl-Headern eingebunden.

Wird GLUT oder MFC nicht genutzt:
#include <windows.h>
#include <GL/gl.h>

d:c++\file.c(231) : warning C4305: 'initializing' : truncation from 'const double ' to 'float ' (Double statt Float erwartet) Harmlose Warnung, die in VC++ durch folgenden Eintrag am Anfang der Datei unterbunden werden kann:
#ifdef WIN32
#pragma warning( disable : 4305)
#endif
file.obj : error LNK2001: unresolved external symbol __imp__glMatrixMode@4
file.obj : error LNK2001: unresolved external symbol __imp__glViewport@16
Das Projekt wurde nicht mit opengl32.lib gelinkt. (ähnliche Meldungen gibt es auch bei vergessener glu32.lib, glut32.lib etc.)

Siehe auch Frage 2.060 weiter oben.

The dynamic link library OPENGL.dll could not be found in the specified path. (opengl.dll nicht gefunden) Diese Datei wurde nicht richtig installiert.
Weiteres in Frage 2.060.
Es wird nichts gezeichnet, der Bildschirm bleibt leer. MS (*32.lib) und SGI (*.lib) Bibliotheken wurde parallel gelinkt (Frage 2.060). Immer nur eine der beiden Libraries verwenden. Kann auch auftreten, wenn die Farbtiefe des Bildschirms weniger als 16K beträgt.
LIBCD.lib(wincrt0.obj) : error LNK2001: unresolved external symbol _WinMain@16
Debug/test.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
Der Quellcode enthält nur eine main() Funktion. Damit dieses Programm richtig übersetzt werden kann, ist eine Konsolenanwendung einzustellen (Frage 2.070).
Mehrere Zugriffsverletzungen treten auf, wenn ich mit der OpenGL mit der MFC nutze. Der CS_OWNDC style muss in der PreCreate*() Funktion in der View Class eingestellt werden.
Floating-Point Ausnahmen treten während der Laufzeit auf. Ich habe die Anwendung mit Borland C erstellt. Vor dem Aufruf von OpenGL Funktionen sollte folgende Zeile eingefügt werden:

_control87(MCW_EM, MCW_EM);

Entnommen aus der Borland FAQ article #17197.

2.080 Wie initialisiere ich mein Fenster richtig ? Was gehört noch zum fehlerfreien OpenGL-Fenster dazu ?

Grundsätzlich hängt das vom verwendeten Betriebssystem ab. Hier gibt es zwar ein paar allgemeine Informationen, allerdings bietet sich für Details der Zugriff auf die Dokumentation der jeweiligen grafischen Oberfläche oder eine passende Newsgroup an.

GLUT

Der Basiscode zum Erstellen eines RGB Fensters mit einem Z-Buffer und einem Rendering Context sieht so aus:

    #include <GL/glut.h>
    int main(int argc, char** argv)
    {
      glutInit(&argc,argv);
      glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH);
      glutInitWindowSize(500,500);
      glutInitWindowPosition(0,0);
      glutCreateWindow("Simple");
      /* eigene Funktionen */
    }
Der Aufruf für Grösse und Position des Fensters ist dabei optional und wird beim Weglasssen durch Standardwerte ersetzt.
X Windows

Mit dem folgenden Code (aus OpenGL Reference Manual) kann man ein RGB Fenster mit Z-Buffer erzeugen:

  #include <GL/gl.h>
  main (int argc, char **argv)
  {
    Display display;
    XVisualInfo *vinfo;
    XSetWindowAttributes swattr;
    int attrList[20];
    int indx=0;
    Window wid;
    GLXContext util_glctx;

    if (!(display = XOpenDisplay ("")))
        exit ();

    attrList[indx] = GLX_USE_GL; indx++;
    attrList[indx] = GLX_DEPTH_SIZE; indx++;
    attrList[indx] = 1; indx++;
    attrList[indx] = GLX_RGBA; indx++;
    attrList[indx] = GLX_RED_SIZE; indx++;
    attrList[indx] = 1; indx++;
    attrList[indx] = GLX_GREEN_SIZE; indx++;
    attrList[indx] = 1; indx++;
    attrList[indx] = GLX_BLUE_SIZE; indx++;
    attrList[indx] = 1; indx++;
    attrList[indx] = None;

    vinfo = glXChooseVisual(display, DefaultScreen(dpy), attrList);
    if (vinfo == NULL) {
        printf ("ERROR: Can't open window\n");
        exit (1);
    }

    swattr.colormap=XCreateColormap (display ,RootWindow (display,vinfo->screen), vinfo->visual, AllocNone);
    swattr.background_pixel = BlackPixel (display, vinfo->screen);
    swattr.border_pixel = BlackPixel (display, vinfo->screen);

    wid = XCreateWindow(display,RootWindow(display, vinfo->screen),
                        30, 30, width, height, 0, vinfo->depth, CopyFromParent,
                        vinfo->visual,CWBackPixel | CWBorderPixel | CWColormap, &swattr);

    util_glctx = glXCreateContext(display, vinfo, NULL, True);
    if (util_glctx == NULL) {
        printf("glXCreateContext failed \n");
        return(-1);
    }
    if (!glXMakeCurrent(display, wid, util_glctx)) {
        printf("glXMakeCurrent failed \n");
        return(-1);
    }
  }
Microsoft Windows 9x/NT/2000

Das Fenster muss mit folgenden, per ODER verknüpften Bits erzeugt werden: WS_CLIPCHILDREN | WS_CLIPSIBLINGS. Das kann man entweder typisch in der CreateWindow() Funktion erledigen oder bei MFC in der PreCreateWindow() Funktion.

Sobald das Fenster erzeugt wurde, also die WM_CREATE Message ausgelöst wurde, kann der folgende Code zum Setzen des Pixelformats und Erzeugen des Rendering Contexts genutzt werden:

      // Voraussetzung / Annahme:
      // HWND hWnd;

      HDC hDC = GetDC (hWnd);
      PIXELFORMATDESCRIPTOR pfd;

      memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
      pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
      pfd.nVersion = 1;
      pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
      pfd.iPixelType = PFD_TYPE_RGBA;
      pfd.cColorBits = 24;
      pfd.cDepthBits = 32;
      pfd.iLayerType = PFD_MAIN_PLANE;

      int pixelFormat = ChoosePixelFormat(hDC, &pfd);
      if (pixelFormat == 0) {
        // Handle error here
      }

      BOOL err = SetPixelFormat (hDC, pixelFormat, &pfd);
      if (!err) {
        // Handle error here
      }

      hRC = wglCreateContext(hDC);
      if (!hRC) {
        // Handle error here
      }

      err = wglMakeCurrent (hDC, hRC);
      if (!err) {
        // Handle error here
      }

Zum Freigeben des Contexts dienen die folgenden Funktionen:

      WglMakeCurrent(NULL,NULL);
      ReleaseDC (hWnd, hDC);

2.090 Wie gelange ich in den Vollbildmodus ?

Mit GLUT Versionen älter als 3.7 konnte man ein Vollbild mit dem Aufruf von glutFullScreen(void) erzeugen. Seit GLUT 3.7 ist es möglich, dieses wesentlich flexibler zu erledigen.

Mit der Funktion glutGameModeString() kann ein Programm eine bestimmte Auflösung, die Farbtiefe und Refresh Rate anfordern. Dieses kann mit den ASCII Strings [Breite]x[Höhe]:[Farbtiefe]@[Hertz] erfolgen. Ein Programm kann es bei Verfügbarkeit gemäss diesem Beispiel realisieren:

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutGameModeString("640x480:16@60");
    glutEnterGameMode();

Es lohnt sich auch, in der "Full Screen Rendering" Section in der OpenGL game developer's FAQ vorbeizuschauen.

2.100 Wie sieht ein OpenGL-Programm grundsätzlich aus ?

Es gibt hierfür keine festen Regeln. Der folgende Pseudocode beschreibt eine geeignete Form:

      program_entrypoint
      {
        // Feststellen, welches Pixelformat bzw. Farbtiefe geeignet ist
        // Fenster mit dem gewünschten Format generieren
        // Rendering Context erzeugen und mit dem Fenster verbinden
        // OpenGL initialisieren
        // Callbacks für Resize und Refresh setzen
      }

      handle_resize
      {
        glViewport(...);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        //Projektion mit glOrtho, glFrustum, gluOrtho2D, gluPerspective, etc. festlegen
      }

      handle_refresh
      {
        glClear(...);

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        // Viewing Transformation mit gluLookAt etc. festlegen

        // Für jedes in der Szene anzuzeigende Objekt (i)
        // Stacks sichern (glPushMatrix, glPushAttrib)
        // OpenGL Status festlegen
        // Modelltransformation durchführen (glTranslatef, glScalef, glRotatef)
        // Zeichenkommandos ausführen
        // Stacks reaktivieren (glPopMatrix, glPopAttrib)
        // Schleife für nächstes Objekt

        // Swap buffers.
      }

2.110 Mein Fenster bleibt schwarz. Was kann ich tun ?

Es kann mehrere Ursachen für dafür geben, dass OpenGL scheinbar keinen Zeichenbefehl ausführt (hier vereinfacht als schwarzer Bildschirm bzw. Blank Screen bezeichnet). Meistens liegt die Ursache alllerdings in unzureichenden Kenntnissen der 3D Computergrafik oder einfach einem Denk-/Tippfehler im Code.

Bücher zum Nachlesen gibts auch ;-)

Hier folgt eine Liste der häufiger auftretenden Ursachen für den gefürchteten Blank Screen sowie Lösungsvorschläge.

  • Das Programm könnte einen fehlerhaften OpenGL Aufruf beinhalten. Durch ausreichend viele Abfragen mit glGetError() lässt sich das Problem vielleicht einkreisen. Man kannn dafür ein Makro der folgenden Art verwenden:
      {
        GLint err = glGetError();
        if (err != GL_NO_ERROR)
          DisplayErrorMessage();
      }

Diesen Block am besten nach allen eventuell fehlerhaften OpenGL Befehlen (oder nach einer Gruppe von Befehlen) plazieren. Um nach dem Debuggen ein einfaches Ausblenden zu ermöglichen, kann der Code auch durch ein #ifdef DEBUG...#endif eingeschlossen werden.

glGetError() ist der einzige Weg, um herauszufinden ob eine OpenGL Funktion fehlerhaft aufgerufen wurde. In diesem Fall wird OpenGL den Befehl gar nicht erst ausführen, so dass auch ein Blank Screen die Folge sein kann.

  • Ein andere Ursache sind ungünstig gewählte Werte für die vordere bzw. hintere Clipping Ebene zNear und zFar. Grade bei einem neu erstellten Programm ist es leicht möglich, dass die Objekte ausserhalb der Clipping Ebenen liegen und deshalb nichts auf dem Bildschirm zu sehen ist. zNear und zFar sind Parameter der Funktionen glOrtho(), gluOrtho2D(), glFrustum() und gluPerspective(), wobei für die Zentralprojektion mit glFrustum()/gluPerspective() die Werte von zNear und zFar vom Augpunkt an im positiven Abstand rechnen.
    Als Beispiel: Der Augpunkt liegt mit den Standardwerten der OpenGL bei (0,0,0). Legt man jetzt zNear = 2.0 und zFar = 20.0 fest und zeichnet einen Einheitswürfel mit Kantenlänge = 1.0 um den Koordinatenursprung, so kann nichts im Blickfeld liegen. Eine Abhilfe ist es in diesem Fall, das Modellkoordinatensystem mit glTranslate (0,0,-3) so zu verschieben, dass dessen Ursprung im Viewing Volumen liegt.

Die richtig gewählten Grenzen des Viewing Volumens sind für zNear genauso wie für zFar entscheidend (bei zFar = 10.0 werden Objekte mit einem grösseren Abstand als 10.0 nicht mehr gerendert).

  • Fehler während der Objekttransformation verursachen im allgemeinen auch vergleichbare Fehler. Wenn zwar das Viewing Volumen richtig gesetzt ist, aber aus irgendwelchen Gründen die Transformationen die Objekte ausserhalb plazieren, wird auch nichts angezeigt werden. Die Ursache kann entweder in einem Fehler werden des Programmierens oder Verständnisproblemen der OpenGL Transformationen liegen.

Es ist immer am besten, mit einem einfachen Code zu starten und erst bei Erfolg zu komplexen Transformationen überzugehen. Sinnvollerweise ändert man die Transformationen Schritt für Schritt und überprüft die Zwischenergebnisse ausreichend oft.

  • Eine weitere Ursache für einen Blank Screen kann auch ein Fehler im Aufruf von glBegin() bzw. glEnd() sein. Alle Geometriebeschreibungen müssen innerhalb eines glBegin()/glEnd() Blocks liegen, um überhaupt von der OpenGL ausgeführt zu werden. Eine Fehlermeldung wird trotzdem nicht auftreten.

Falls zu einem glBegin() kein glEnd() existiert, ist das Verhalten von OpenGL undefiniert. Es kann also auf einem System etwas angezeigt werden, auf einem anderen dagegen nicht. Da z.B. glFlush() nicht innerhalb eines glBegin()/glEnd() Blocks stehen darf, wird dieser Fall eine Fehlermeldung mit glGetError() erzeugen. Falls ein glEnd() ohne das zugehörige glBegin() aufgerufen wird, wird in jedem Fall eine Fehlermeldung auftreten. Es ist also immer eine gute Idee, das eigene Programm mit glGetError() auf (versteckte) Fehler zu überprüfen.

  • In einem Double Buffer Fenster wird das Bild zuerst im Back Buffer gerendert und dann mit dem Befehl SwapBuffers (glXSwapBuffers, glutSwapBuffers) in den Front Buffer kopiert und somit angezeigt. Wird der Aufruf von SwapBuffers vergessen kann also auch nichts angezeigt werden, da sich die fertige Szene noch im nicht sichtbaren Back Buffer befindet. Es ist deshalb im Double Buffer Modus zwingend notwendig, am Ende jedes Frames (jedes Durchlaufens der Zeichenfunktion im Programm) SwapBuffers aufzurufen.
  • Genauso kann das Vergessen von glClear() zu Beginn jedes neuen Frames, insbesondere das Löschen des Z-Buffers, einen Blank Screen bewirken.
  • Einige OpenGL Implementationen sind nicht ganz fehlerfrei und verursachen dadurch einen Blank Screen oder eine fehlerhafte Darstellung. Man sollte sein Programm bei einer entsprechender Vermutung zunächst mit einer anderen OpenGL Implementation ausprobieren. Läuft es dort und auch auf anderen fehlerfrei, ist die erste Implementation aller Wahrscheinlichkeit nach fehlerhaft.

2.120 Das erste Frame wird richtig angezeigt, aber danach bekomme ich ein fehlerhaftes oder gar kein Bild mehr. Warum ?

Dieses Verhalten tritt oftmals dann auf, wenn man die Arbeitsweise der OpenGL nicht berücksichtigt. Jede Matrixoperation (glTranslate, glRotate, glScale usw.) wird mit dem aktiven Matrixstack multipliziert, nimmt also das Ergebnis aller vorhergehenden Transformationen als Ausgangsbasis.

Die meisten OpenGL Programme beginnen in ihrer Zeichenroutine zunächst, den ModellView Matrixstack mit glLoadIdentity() als Einheitsmatrix zu setzen. Dann wird die Ansichtstransformation mit dieser Einheitsmatrix multipliziert, z.B. mit gluLookAt(). Dabei initialisiert gluLookAt() die ModelView Matrix nicht, es werden nur einige Matrixmultiplikationen zur Positionierung des Augpunkts vorgenommen. Ein Vergessen des glLoadIdentity() wird also dazu führen, dass sich alle Transformationen überlagern und nicht das gewünschte Bild entsteht. Beispielcode:

    void glutdisplay()
    {
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      glLoadIdentity();
      gluLookAt(Kamera[x], Kamera[y], Kamera[z],
                 Blick[x],  Blick[y],  Blick[z],
                  oben[x],   oben[y],   oben[z] );
      // Objekte zeichnen
      glutSwapBuffers();
    }

2.130 Was ist die AUX Bibliothek ?

Diese Bibliothek bietet gegenüber GLUT nur Nachteile und sollte grade von Einsteigern keinesfalls genutzt werden.

Die AUX Bibliothek wurde von SGI in der Frühzeit von OpenGL entwickelt, um damit ein paar einfache Beispielprogramme erzeugen zu können. AUX wird schon seit längerer Zeit weder unterstützt noch weiterentwickelt. Es sollten deshalb keine Programme mehr mit AUX entwickelt werden, GLUT bietet mehr Funktionen, wird von vielen verwendet und ist sehr gut dokumentiert. Darüber hinaus ist es auf vielen Plattformen verfügbar.

Weitere Informationen sind im Bereich GLUT, weitere Links in der Frage zur Verfügbarkeit vorhanden.

2.140 Welche Unterstützung für OpenGL bieten {Open,Net,Free}BSD oder Linux ?

Diese Betriebssysteme nutzen als grafische Oberfläche X Windows mit einem geeigneten X Server, meistens XFree86.
Die X Windows Version XFree86 4.0 unterstützt OpenGL über die Mesa bzw. die OpenGL Sample Implementation von SGI. XFree86 unterliegt der (freizügigen) XFree86 Lizenz.

SGI hat die OpenGL Sample Implementation (also eine kaum optimierte Demonstration, wie man eine OpenGL Bibliothek realisieren kann) als Open Source im Quellcode verfügbar gemacht. Sie kann als X Server mit GLX (OpenGL für X Windows Netzprotokoll) Unterstützung compiliert werden. Die zugrunde liegende Lizenz ist die SGI Free Software License B.

Die Mesa 3D Graphics Library ist eine OpenGL ähnliche Bibliothek, die auf vielen Systemen funktioniert (u.a. DOS, MS Win, *BSD, Linux). Mesa kann so konfiguriert werden, dass es GGI oder X Windows unterstützt oder als GLX Implementation für der X Server arbeitet. Diese Bibliothek bietet eine Hardwarebeschleunigung für einige 3D Grafikkarten (insbesondere 3Dfx und Nvidia Karten), und ist seit der Version 3.1 unter einer XFree86 ähnlichen Lizenz verfügbar.

Utah-GLX ist eine hardwarebeschleunigte GLX Implementation für Matrox MGA-G200 und G-400, ATI 3D RAGE PRO, Intel i810, NVIDIA RIVA und S3 ViRGE.  Utah-GLX basiert auf Mesa.  Die Lizenzbedingungen sind allerdings unklar.

Metro Link OpenGL und Extreme 3D sind GLX Erweiterungen für die Metro Link X Server. Metro Link OpenGL ist zwar eine OpenGL Software Implementation, allerdings nutzt sie die 2D Beschleunigung des X Servers gut aus und ist damit schneller als eine reine Softwarelösung. Extreme 3D stellt eine echte Hardwarebeschleunigung für folgende Karten zur Verfügung: REALimage, GLINT GMX 1000, 2000, GLINT DMX, GLINT MX, GLINT TX und Permedia 2/3.

Xi Graphics 3D Accelerated-X ist ein X Server mit GLX Unterstützung für folgende Karten: ATI Xpert 2000, ATI Rage Fury Pro, ATI Rage Fury, ATI Rage Magnum, ATI All-in-Wonder 128 (alle ATI RAGE 128 ?!), 3Dlabs Oxygen VX1, 3Dlabs Permedia 3 Create! (Permedia 3), Diamond Stealth III S540, Diamond Stealth III S540 Extreme, Creative Labs 3D Blaster Savage4 (S3 Savage4), Number Nine SR9, 3Dfx Voodoo 3000, 3Dfx Voodoo 3500 software.

2.150 Wo finde ich OpenGL 1.2 ?

Zum Zeitpunkt, als diese FAQ aufgestellt wurde (Anfang 2000) waren einige OpenGL 1.2 konforme Bibliotheken verfügbar: von Sun und IBM sowie Mesa und die OpenGL Sample Implementation.

Microsoft hat noch keine OpenGL 1.2 Bibliothek zustande gebracht ;-). Angeblich soll es mal in einem Service Pack für Win 2000 kommen. Unabhängig davon müssen die Treiber der Grafikkarte auch in der Lage sein, die Hardwarebeschleunigung für die neuen Funktionen auszunutzen.

Das Grundprinzip der OpenGL besteht aber in den Extensions, die bei entsprechender Zweckmässigkeit auch in die Folgeversionen der OpenGL als Standard aufgenommen werden. Mit anderen Worten sind über Extensions auch schon jetzt viele Karten in der Lage, die Funktionalität der OpenGL 1.2 zu nutzen.

Auf allen anderen Plattformen können die Kartenhersteller OpenGL 1.2 nach eigenem Zeitplan auf den Markt bringen.

Die OpenGL 1.2 Spezifikation ist auf http://www.opengl.org verfügbar. Auch das Red und Blue Book sind vor einiger Zeit mit einer Anpassung an OpenGL 1.2 erschienen.

2.160 Was ist der OpenGL Conformance Test?

Bevor eine Bibliothek offiziell den Namen "OpenGL" tragen darf, sind einige Hürden zu nehmen:
Erfolgreiches Durchlaufen des OpenGL Conformance Test (eine Sammlung an Testprogrammen, von der OpenGL ARB vorgegeben) und Zahlung einer Lizenzgebühr. Den Quelltext des Conformance Test kann man ebenfalls bei der ARB lizensieren.

Der Conformance Test wird einige Zeit nach Festlegung einer neuen Spezifikation an die Funktionalität der aktuellen OpenGL Version angepasst (d.h. mit Stand Mitte 2002 der 1.3). Extensions (d.h. genormte "kann"-Erweiterungen) werden hierbei nicht geprüft, sondern nur aufgelistet.

"covogl" ist ein spezielles Testprogramm des Conformance Test, das alle Standard-Funktionen prüft. Hier werden alle Funktionen aufgerufen und auf absturzfreien Ablauf getestet. Die anderen Tests prüfen, ob die von der Spec vorgeschriebene Funktionalität eingehalten wird:

"mustpass.c" definiert die Kern-Funktionalität, die von allen OpenGL Implementationen beherrscht werden muss (Linien etc.). Anbieter, die andere Funktionen noch nicht korrekt umgesetzt haben, erhalten die OpenGL-Konformität bescheinigt, wenn sie glaubhaft machen könenn, dass

Die Fähigkeit zum sichern und retten des OpenGL-Status mittels push/pop wird vollständig getestet. Jeder dieser Tests hat folgende Form:

push state (Status sichern)
change state (Status verändern)
run test (Test durchlaufen)
pop state (alten Status wiederherstellen)
Jetzt werden alle Status-Variablen mittels "glGet*()" abgerufen und mit den Startwerten verglichen.

Einige Tests haben eine eingebaute Fehlertoleranz, die gewisse Abweichungen von der OpenGL Spezifikation zulässt. Zum Beispiel beim Zeichnen eines Dreiecks: Gemäss der Spec muss jedes Pixel innerhalb der mathematischen Grenzen des Dreiecks liegen. Hier wird eine Abweichung von bis zu einem halben Pixel zugelassen, ohen dass es als Fehler bemängelt wird.

Andererseits gibt es Tests, die mehr abverlangen, als durch die Spec vorgegeben ist. Zum Beispiel fordert der Alpha-Test eine 10-Prozent Präzision (zwischen 4 und 5 bits), die Spec fordert nur die 1-Bit Präzision.

Einige Tests scheinen keinen Sinn zu ergeben, wenn man die Spec nicht genau kennt. Zum Beispiel kann eine Implementation auch dann auf das Antialiasing verzichten, wenn der Nutzer dieses explizit für ein Polygon angefordert hat. Dementsprechend erlaubt auch der Test das Ignorieren. Ein anderes Beispiel ist das Dithering (Farb-Emulation, wenn das Display über keine ausreichende Farbtiefe verfügt). Die Spec erlaubt hier eine solche Abweichung (von gar nicht bis voll), dass diese Funktion zwar getestet, aber ein Fehlen nicht beanstandet wird.

Alle Tests unterstützen sogenannte Path Levels, d.h. es werden verschiedene Befehlsvariationen geprüft, die alle das gleiche Resultat ergeben müssen. Zum Beispiel muss das Zeichnen eines Dreiecks mit "polygon stipple disabled" (also durchgezogene Linien) genauso dargestellt werden wie ein Dreieck, dass mit aktiviertem "polygon stipple" und Strichmuster mit nur "Bit 1" (zwar gestrichelte Linie, aber ohne tatsächliche Unterbrechung mit "Bit 0") gezeichnet wird. Das wiederum muss gleich aussehen zum Zeichnen mit aktiviertem Blending und einer Blend-Funktion von (GL_ONE,GL_ZERO).
Es gibt zahlreiche dieser Path Levels, die sehr viele komplexe Kombinationen der Status-Variablen testen.

Alle Tests werden mit allen verfügbaren Pixelformaten und Visual-Typen (einschl. Color Index) durchgeführt.

Alle Tests prüfen das korrekte Rendering mit glReadPixels(). Manche Tests lesen dazu das gesamte Testfenster aus, während andere nur Teilbereiche prüfen. Grundsätzlich nutzen die Tests GL_RGBA and GL_FLOAT als Typ und Format. Der Test "readpix.c" prüft dagegen alle Kombinationen von Typ und Format. Versagt glReadPixels(), versagen normalerweise auch alle Tests.

Ist glReadPixels() sehr langsam, benötigen die Tests eine sehr lange Zeit (bis hin zu Tagen).

Der gesamte Conformance Test kann sehr viele Fehler aufdecken. Eine Garantie, dass alle Fehler erkannt werden, besteht allerdings nicht. Damit kann eine Implementation, die alle Tests fehlerfrei durchlaufen hat, bei bestimmten Anwendungen trotzdem nicht funktionieren.

Seite durchsuchen nach:

Fragen oder Ideen an:
Thomas.Kern@3Dsource.de
Linux-Counter
(C) Thomas Kern