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

5 OpenGL unter Microsoft Windows

5.010 Wo finde ich am besten Informationen zum Programmieren mit OpenGL unter MS Windows ?

Samuel Paik hat eine grosse Sammlung an Links zu OpenGL-Informationen bei Microsoft angelegt.

Weitere Tipps findet ihr z.B. auf Blaine Hodge's Webseite. Allerdings wird in Teilen der Beispiele die veraltete AUX Bibliothek verwendet. Bisher wurde deshalb immer auf den GLUT Quelltext mit Beispielprogrammen oder die reinen WIN32 Programme des SGI OpenGL SDK verwiesen.

5.020 Ich suche eine geeignete Grafikkarte. Vorschläge ?

Das Angebot an 3D Grafikkarten für den Heimanwender ändert sich so schnell, dass die Informationen einer FAQ bald veraltet wären.

Hier ist besser, in geeigneten Newsgroups (z.B. comp.graphics.api.opengl oder einer Wintel 3D Spiele Newsgroup) nachzufragen oder im Web nach Informationen zu suchen.

Tom's Hardware Guide oder Fast Graphics bieten solche Informationen in englisch. Auf den Seiten der Computerzeitschriften sollte man aber ebenso fündig werden (z.B. c't oder chip).

5.030 Wie kann ich die Hardwarebeschleunigung meiner Karte (de-)aktivieren ?

Derzeit bietet OpenGL keinen Schalter, um die Hardwareunterstützung an- oder abzuschalten. Es kann allerdings sein, dass der Hersteller einer Grafikkarte dieses über eine Umgebungsvariable oder die Einstellungen der Treibersoftware ermöglicht.

Falls im System zwar eine OpenGL Karte eingebaut ist, allerdings die Programme scheinbar im Softwaremodus laufen, sollte man folgendes überprüfen:

  • Ist der passende Gerätetreiber / OpenGL Installable Client Driver (ICD) installiert ? (Wie geht das ?)
  • Ist eine geeignete Farbtiefe eingestellt ? (normalerweise 16 oder 32 Bit, also 65.000 bzw. 16 Millionen Farben)
  • Wurde im Programm die OpenGL mit einem beschleunigten Pixelformat initialisiert ? ( mit ChoosePixelFormat(winDeviceContext, &pixelFormat); )

Eine Multi-Monitor Konfiguration kann ebenfalls Einschränkungen in der Hardwarebeschleunigung verursachen. OpenGL in Hardware kann eventuell nur an einem oder auch gar keinem Monitor unterstützt werden.

Um die Hardwarebeschleunigung zeitweise zu deaktivieren, kann z.B. ein Pixelformat gewählt werden, dass keine Beschleunigung bietet (geht nicht über ChoosePixelFormat(), sondern nur mit DescribePixelFormat(), wobei eine fehlende Hardware-Unterstützung durch das Attribut PFD_GENERIC_FORMAT gekennzeichnet ist). Ein Quelltext-Beispiel von Ron Fosner ist weight.cpp, die Möglichkeit zur Auswahl eines Pixelformats ist hier demonstriert.

Eine weniger elegante Lösung stellt das Verschieben oder Umbenennen des ICD (also die Datei des Hardwaretreibers) dar. Man sollte vorher einen Blick auf die Treibereinstellungen bzw. Dokumentation werfen; manchmal lässt sich die Beschleunigung auch in einer Dialogbox ausschalten.

5.040 Woher weiss ich, ob mein Programm die Hardwarebeschleunigung nutzt ?

OpenGL bietet zwar keine direkte Abfrage, der Status der Hardwarebeschleunigung kann allerdings indirekt ermittelt werden.

Falls ihr die Win32 Schnittstelle direkt (also ohne GLUT) nutzt, kann man die Funktion DescribePixelFormat() aufrufen. Ist im dwFlags Bitfeld der Eintrag PFD_GENERIC_ACCELERATED leer und PFD_GENERIC_FORMAT gesetzt, dann läuft das Programm im reinen Softwaremodus. Für eine Hardwareunterstützung muss ein anderes Pixelformat gewählt werden.

Falls glGetString(GL_VENDOR) einen anderen Eintrag als "Microsoft Corporation" zurückgibt, dann wird der ICD der Grafikkarte genutzt. Anderenfalls wird das aktuelle Pixelformat durch den ICD nicht unterstützt. Ein MCD (nur in Teilen der OpenGL entsprechender Treiber) gibt allerdings auch nur "Microsoft Corporation" zurück und unterstützt die Hardwarebeschleunigung trotzdem.

Eine andere Idee ist es, den ICD zeitweise umzubenennen oder zu verschieben, um so eine Änderung in der Performance des Programms festzustellen (falls der Dateiname unbekannt ist, mittels "regedit" nach dem Eintrag "OpenGLdrivers" suchen).

Es ist auch möglich, die Performance beim Zeichnen in den Back Buffer mit den Technischen Daten der Grafikkarte zu vergleichen. Diese Methode eignet sich aber hauptsächlich für Karten, die in bestimmten Situationen (z.B. zuviele Lichtquellen) in den Softwaremodus zurückschalten. Der Performance Abschnitt bietet noch einige Informationen hierzu.

5.050 Woher kann ich einen vollständigen OpenGL-Treiber (ICD) für meine Karte bekommen ?

Falls die Karte OpenGL unterstützt, liefert der Hersteller meist einen Treiber/ICD mit bzw. stellt ihn auf der Webseite zur Verfügung. Nach der Installation sollte das Programm auf die Hardwarebeschleunigung zurückgreifen.

Da diese Treiber oft überarbeitet werden, lohnt sich der Blick auf die Webseite des Herstellers ohnehin. Dort stehen wahrscheinlich auch die Installationsanweisungen und weitere Updates zur Verfügung.

Reactor Critical bietet Treiber für nVidia Karten, die oft schneller und aktueller als die originalen Treiber von der nVidia Webseite sind.

GLsetup, ein freies Programm, erkennt die installierte Grafikkarte und installiert laut deren Webseite auch gleich die aktuellsten Treiber. Es kann aber sein, dass Windows 2000 und XP nicht richtig unterstützt werden.

5.060 Meine Grafikkarte stellt nicht alle Funktionen der OpenGL richtig dar. Was ist los ?

Es kann z.B. ein einfacher Fehler im eigenen Programm sein. Arbeitet der Code mit anderen OpenGL Implementationen allerdings korrekt, liegt die Ursache vermutlich im Treiber/ICD der Karte. Die vorhergehende Frage bietet weitere Informationen zum ICD.

5.070 Kann ich OpenGL und DirectDraw gleichzeitig in einem Programm nutzen ?

Diese Kombination wird mit einigen Treibern nicht arbeiten, ist unportabel und deshalb nicht empfehlenswert.

5.080 Geht es, dass ich DirectDraw zum Ändern der Bildschirmauflösung nutze ?

Man kann durchaus ein Fenster erzeugen, dann mittels DirectDraw dessen Auflösung und Farbtiefe ändern und zum Schluss den Device Context des Fensters an OpenGL übergeben. Zumindest bei einigen Geräten scheint es zu funktionieren.

Microsoft gibt allerdings keine Garantie, dass man mit OpenGL in ein DirectDraw Fenster zeichnen kann. Deshalb sollte man diese Möglichkeit nicht voraussetzen und auf entsprechende Fehlermeldungen bei Erzeugen oder Aktivieren eines Contexts achten.

5.090 Meine Karte soll OpenGL-Funktionen unterstützen, aber ich erkenne keine Beschleunigung, egal welche Auflösung und Farbtiefe ich nutze.

Es gibt nur wenige 3D Karten, die bei 8 Bit (256 Farben) Farbtiefe eine 3D Beschleunigung bieten. Mit 16 oder 32 Bit (65.000 bzw. 16Mio Farben) sollte es aber gehen. Mehr Informationen bietet z.B. Abschnitt 5.040.

5.100 Wie kann ich die Hardwarebeschleunigung aktivieren ?

Das gewählte Pixelformat bestimmt über die Hardwarebeschleunigung. Entscheidend sind dabei die Flags GENERIC_FORMAT und GENERIC_ACCELERATED, die bei 3D-DDI oder MCD beide gesetzt sind, bei einem ICD aber keines von beiden gesetzt sein darf. Um den gewünschten Zustand der Flags zu erhalten, kann mit DescribePixelFormat() das Pixelformat schrittweise verändert werden.

5.110 Warum arbeitet die Hardwarebeschleunigung nicht mit mehreren Monitoren ?

Unter Win98 hat Microsoft die Hardwarebeschleunigung deaktiviert, wenn mehrere Monitore angeschlossen sind. Unter Windows NT 4.0 kann die Beschleunigung aber funktionieren, wenn annähernd gleiche 3D-Karten im System sind. Mit passenden Treibern für Windows 2000 sollte es ähnlich wie bei Windows NT aussehen.

5.120 Warum flackert mein MFC-Fenster, obwohl ich das Double-Buffering nutze ?

Die View Klasse sollte einen OnEraseBackground() Callback haben, der nur die Funktion hat, TRUE zurückzugeben. Das sagt dem Betriebssystem, dass das Fenster gelöscht wurde. In Wirklichkeit wurde das Fenster aber nicht gelöscht, allerdings versucht so Windows nicht, das Fenster selbst neu zu zeichnen und somit kann das Flackern verhindert werden.

5.121 Warum erscheint mein OPenGL-Fenster trotz Double Buffer unvollstänstig oder enthält schwarze Streifen ?

Das ist ein Problem von Microsoft-OpenGL. Der Fehler scheint in der (Software-)OpenGL-DLL oder sogar im Windows-Code selbst zu stecken, da es auch ohne aktvierte Hardwarebeschleunigung auftreten kann.

Microsoft's Supportseiten enthalten Informationen zu diesem Problem: Clipping Problems with Generic Implementation of OpenGL for Windows 2000

Um die fehlerhafte Darstellung zu vermeiden, kann man z.B. folgende Work Arounds nutzen:

  • Zuerst das OpenGL-Fenster erzeugen, aber noch nicht anzeigen lassen. Dann die Bildschirmauflösung ermitteln und die Fenstergrösse des OpenGL-Fensters damit gleich setzen. Nun kann das Pixelformat festgelegt und der HGLRC (OpenGL Rendering Context) erzeugt werden. Jetzt kann man die Grösse des OpenGL-Fensters auf den eigentlich beabsichtigten Wert setzen und das Fenster zur Anzeige bringen. Dieser Hack ist zwar unsichtbar für den Anwender, führt aber nicht jedem Fall zum Erfolg.
  • Wenn die Fenstergrösse nach dem Programmstart vergrössert wird, kann man es vor der Grössenänderung schliessen (damit also komplett löschen) und dann neu erzeugen. Dieser Hack ist eigentlich keine gute Programmier-Methode und sichtbar für den Anwender, scheint aber immer zu funktionieren.

5.130 Was ist der Unterschied zwischen opengl.dll und opengl32.dll ?

Dave Shreiner, der Bearbeiter der OpenGL Reference Manual, sagt dazu:

Unabhängig davon, dass ich dringend die Nutzung der opengl32.dll/lib empfehle, gibt es auch einen objektiven Grund, auf den alten SGI SDK (opengl.dll) zu verzichten.

"opengl.dll ist im seit längeren nicht mehr unterstützten SGI OpenGL für Win32 SDK enthalten. Der Support wurde vor über zwei Jahren eingestellt, es wurden also auch keinerlei Veränderungen am Quelltext mehr vorgenommen.

SGI hat für Microsoft den ICD Kit und die OpenGL Implementation in den meisten Teilen entwickelt. Es ist also die gleiche Codebasis (mit Fehlerbereinigung und neuen Funktionen) wie die für opengl.dll, nur das Microsoft den Vertrieb und Support leistet."

Mehr Informationen zur Nutzung der dlls im eigenen Programm gibt es hier.

5.140 Sollte ich Direct3D oder OpenGL nutzen ?

Diese Seite bietet einen guten Vergleich.

5.150 Was muss ich wissen, um OpenGL mit der MFC nutzen zu können ?

Man sollte Funktionen der OpenGL und der MFC (Microsoft Foundation Class) schon kennen und damit gearbeitet haben. Eine Online-Referenz für die MFC findet man in der MFC FAQ. Um ein OpenGL-Fenster mit der MFC zu erzeugen, muss man allerdings kein Experte sein. Je mehr Erfahrung man aber im Umgang mit C++ und der MFC hat, desto mehr kann man sich auch auf den eigentlichen OpenGL-Code konzentrieren. Wenn man die MFC nur oberflächlich kennt, sollte man sich das Beispiel herunterladen und sich die notwendigen Schritte ansehen.

Auch Joel Parris' OpenGL/MFC Webseite enthält eine Menge an Informationen.

In Samuel Paik's Sammlung zu OpenGL Informationen auf Microsoft Webseiten sind ebenfalls Informationen zur MFC enthalten.

Hier ist noch eine Liste von Büchern zum Thema:

OpenGL Programming for Windows 95 and Windows NT von Ron Fosner (das White Book). Es enthält nützliche Informationen zur Verwendung von OpenGL unter Microsoft Windows. Die meisten der Informationen findet man zwar auch auf den MS Webseiten, im Buch sind sie aber besser strukturiert, leichter verständlich und mit Beispielprogrammen abgedruckt.

Opengl Superbible: The Complete Guide to Opengl Programming for Windows NT and Windows 95 von Richard S. Wright und Michael Sweet. Dieses Buch enthält ein Kapitel zur OpenGL mit MFC.

MFC Programming with Visual C++ 6 Unleashed von David White et al. Dieses Buch enthält nur ein kurzes Kapitel zur OpenGL und konzetriert sich überwiegend auf DirectX.

5.160 Wie kann ich OpenGL mit der MFC nutzen ?

Um OpenGL in einer MFC-Anwendung nutzen zu können, muss man zumindest folgende Schritte abarbeiten:

  • Die Dateien glu32.lib und opengl32.lib sind in die Liste der benötigten Module/Bibliotheken des Projekts aufzunehmen und zu linken.
  • Beim Aufruf der View-Class Funktion OnInitialUpdate() ist das Pixelformat festzulegen und der Rendering Context genauso wie bei einer normalen Win32-OpenGL-Anwendung zu erzeugen.
  • Das Neuzeichnen der OpenGL-Ansicht kann an ein Neuzeichnen des MFC-Fensters gekoppelt werden. Man kann aber auch einen geeigneten Message-Handler (Callback) definieren, der das Neuzeichnen der OpenGL-Ansicht an eine Idle-Funktion koppelt.

Man kann mit OpenGL grundsätzlich in jedes CWnd Objekt einschliesslich Frame-Fenster, Dialogboxen und Kontrollelemente (Schalter etc.) zeichnen.

Bei Paul Martz findet ihr ein Beispiel, dass die Verwendung von OpenGL in einem Kontrollelement (CStatic form control) demonstriert. Das Beispiel verwendet eine CGLView-Klasse, die ein beliebiges CWnd als Parameter annimmt. Statt eine Fenster-Klasse von CFormView abzuleiten, kann eine Anwendung wie gewohnt erzeugt werden, indem der Konstruktor der CGLView-Klasse als normaler Parameter für das Fenster übergeben wird. Folgende Schritte sind abzuarbeiten, um den Beispiel-Code mit Visual C++ zu nutzen:

  1. Das Beispiel aus dem Netz laden. Dann bestimmte Teile des Beispiel-Codes in das eigene Programm gemäss der nächsten Schritte einbinden.
  2. Eine MFC-Klasse mit dem AppWizard erzeugen (MFC-.exe). Die Voreinstellungen können verwendet werden, lediglich die View-Klasse ist von CFormView abzuleiten. Das Projekt öffnet jetzt den Resource-Editor. Hier ist eine CStatic FORM control zu der vereinbarten CFormView hinzuzufügen und als IDC_OPENGLWIN zu bezeichnen.
  3. In den Projekteinstellungen sind die Dateien glu32.lib und opengl32.lib als zu linkende Bibliotheken aufzunehmen.
  4. Zum Projekt ist noch die Datei CGlView.cpp aus dem heruntergeladenen Beispiel hinzuzufügen.
  5. In der Klassen-Ansicht muss man noch eine Member-Variable zur View class hinzufügen (Rechtsklick mit der Maus) und deren Typ auf CGlView *, deren Name auf m_pclGLView festlegen sowie den Zugriff auf den "private-Teil" der Klasse erlauben.
  6. Im View class Header ist #include "CGlView.h" vor der Klassendefinition einzutragen.
  7. Jetzt ist nach der globalen Deklaration von "theApp" zu suchen (im Klassenfenster unter Global die gleichnamige Datei öffnen). Dahinter sind folgende globale Variablen einzutragen:
    CGlView *g_pclGLView = NULL;
    MSG msg;
  8. In der Wizard-Menüleiste ist die View class der Anwendung auszuwählen, der Filter auf "alle Klassenelemente" zu setzen und die Funktion "OnInitialUpdate" auszuwählen.
  9. Damit die CGlView class funktioniert, braucht man ein CWnd zur Initialisierung von OpenGL für das Fenster. In diesem Beispiel ist unser CWnd das CStatic FORM control, welches am Anfang hinzugefügt wurde. Anschliessend an den existierenden Code dieser Funktion ist folgendes hinzuzufügen:
    CStatic pclStatic = (CStatic *)GetDlgItem(IDC_OPENGLWIN);
    m_pclGLView = new CGlView(pclStatic);
  10. Jetzt kann mittels dem Wizard weitergearbeitet werden (mit Ansicht->Klassenassistent öffnen). Im Bereich Nachrichten ist die App-Klasse auszuwählen und im Feld "Nachrichten" dem Run-Eintrag eine Funktionsdefinition hinzuzufügen. Der notwendige Code kann dem heruntergeladenen Beispiel entnommen werden.

5.170 Ist OpenGL eigentlich merklich langsamer, wenn ich es mit der MFC nutze ?

Grundsätzlich verlangsamt die MFC den OpenGL-Code nicht. Allerdings können schlecht programmierte MFC-Anwendungen durchaus langsamer als reiner Win32-Code laufen. Das ist aber ein generelles Problem und hat wenig mit OpenGL zu tun. Hier sind noch ein paar Hinweise, die man beachten sollte:

  1. Die Anwendung ist als Release- und nicht als Debug-Version zu erzeugen. Die Debug-Funktion TRACE ist abzuschalten.
  2. MFC-Klassen wie CArray, CMap und CList sind zu vermeiden, da sie ineffizient mit Kopieroperationen umgehen.
  3. Eine Beschleunigung erhält man bei Vermeidung der WM_PAINT-Nachricht. Am besten mal in den Beispiel-Code hereinschauen.
  4. MFC-Klassen stellen alle möglichen Funktionen bereit. Zum gezielten Tuning sollte man eine eigene, speziell auf die Zielstellung ausgerichtete MFC-Klasse programmieren.
  5. Die üblichen Programmiertechniken sollte man ebenfalls beachten (unsinnige Mehrfachaufrufe vermeiden etc.)

5.180 Wo kann ich MFC-Beispiele finden ?

Diese FAQ enthält ein Beispiel.

Ein gutes, aber leicht veraltetes Beispiel von Alan Oursland, Using OpenGL in Visual C++ Version 4.x, DevCentral Learning Center, findet ihr hier. Zum Start mit der MFC-Programmierung ist es in jedem Fall hilfreich.

Dann gibt es noch Mahesh Venkitachalam's OpenGL Code. Mahesh zeigt die Verwendung von OpenGL mit einem MFC-Wizard bei wenigen Zugriffen auf die MFC-Funktionen für OpenGL-Techniken.

Roman Podobedov's Skeleton of OpenGL program for Windows (MFC) zeigt eine minimale MFC-Applikation ohne zusätzliche Kontrollen und ohne Verwendung des Wizards.

Paul Martz's Generating Random Fractal Terrain demonstriert ebenfalls das MFC-Verfahren. Das Hauptaugenmerk liegt aber bei der Terrain-Darstellung, für die MFC und OpenGL genutzt werden.

Pierre Alliez hat folgende Beispiele ins Netz gestellt: Starting OpenGL in a Dialog, Starting Rendering Modes (mit mehreren Dokumentenfenstern), How to snap an OpenGL client and send it to the clipboard und A small VRML viewer using OpenGL and MFC.

Uwe Kotyczka's OpenGLSample ist eine grössere und beeindruckende MFC-Anwendung, die verschiedene OpenGL-Techniken wie "multiple OpenGL views, rubber banding, color ramp, mouse trackball type control und OpenGL printing" nutzt. Programmiert wurde mit VC++ 6.0 (SP4).

5.190 Was muss ich über das Mischen von WGL und GDI Aufrufen wissen ?

Unter Win32 sind einige plattformspezifische Funktionen im OpenGL ICD und in den GDI-Funktionen (Graphics Device Interface) enthalten. Das kann zu etwas Verwirrung führen, da die Funktionen bis auf das Präfix wgl gleich erscheinen. Um sicherzustellen, dass OpenGL korekt arbeitet, sollte man die Funktionen "ChoosePixelformat, DescribePixelformat, GetPixelformat, SetPixelformat und SwapBuffers" anstatt der gleichnamigen wgl-Funktionen (wglChoosePixelformat, wglDescribePixelformat, wglGetPixelformat, wglSetPixelformat und wglSwapBuffers) verwenden. Alle anderen wgl-Funktionen kann man aber nutzen.
Die Nutzung der 5 genannten "normalen" Funktionen sichert die Lauffähigkeit des Programms auf verschiedenen MS-Betriebssystemen: Nutzt man die wgl-Funktionen, kann ein problemlos unter Win9x laufendes Programm unter Windows NT/2000 ein schwarzes OpenGL-Fenster verursachen.

5.200 Warum verursacht mein Programm unter Windows NT/2000 einen Black Screen, obwohl es unter Win 9x problemlos läft ?

Werden gleichnamige GDI- und WGL-Funktionen in einer Anwendung unkontrolliert gemixt, kann das beschriebene Verhalten auftreten. Mehr dazu in Frage 5.0190.

5.210 Wie nutze ich die WGL-Funktionen richtig ?

Wie in Frage 5.0190 beschrieben, wird der Aufruf von "ChoosePixelformat, DescribePixelformat, GetPixelformat, SetPixelformat und SwapBuffers" durch den OpenGL ICD abgearbeitet. Die entsprechenden WGL-Funktionen arbeiten nicht in jedem Fall problemlos, wenn die Anwendung mit anderen Treibern/Betriebssystemen gestartet wird.

Charles E. Hardwidge hat auf seiner Webseite einen (englischsprachigen) Artikel zur Nutzung der wgl*Font-Funktionen gespeichert. Hier wird demonstriert, wie man die OpenGL-Bibliothek dynamisch einbinden kann und was dazu beachtet werden muss. Der originale FAQ-Beitrag ist an dieser Stelle zwar etwas länger, erscheint mir aber noch nicht so ganz ausgegoren...

Seite durchsuchen nach:

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