Einführung Shader Programmierung OpenGL 2.0

Transcription

Einführung Shader Programmierung OpenGL 2.0
Einführung
in die
Shader Programmierung
unter
OpenGL 2.0
Einführung in die Shader Programmierung unter OpenGL 2.0
Projektdaten
Projektdaten
Projektbezeichnung
Einführung in die Shader Programmierung unter
OpenGL 2.0
Projektbetrauter:
Ronny Rösler
[email protected]
II
Einführung in die Shader Programmierung unter OpenGL 2.0
Vorwort
Vorwort
Hallo werter Leser.
Mein Name ist Ronny Rösler und ich freue mich, dass Sie sich für das Thema dieser
Arbeit interessieren. Obwohl ich mich während meines Studiums der Angewandten
Informatik für den Studienschwerpunkt Telekommunikation entschieden habe und
eigentlich weniger mit Grafikverarbeitung zu tun habe, sehe ich dieses Projekt
trotzdem als eine weitere Bereicherung an Wissen.
Bevor ich mit dieser Ausarbeitung und dem eigentlichen Programmieren begonnen
habe, hatte ich keine Vorstellung was Shader sind. Sicher, durch die Basiskenntnisse
in Grafikverarbeitung weis ich was flat-, Geraud-, und Phong-Shading ist, was jedoch
Vertex- und Fragment-Shader-Programme im Einzelnen sind und wie man mit deren
Neu-Implementierung Einfluss auf die Grafikszene nehmen kann, war mir neu.
Im Laufe dieses Projekts hat sich mein Interesse an der Grafikprogrammierung
erheblich gesteigert. Zumindest ansatzweise kann ich jetzt erahnen, wie die
Entwickler von Echtzeit-Grafiken und nicht zuletzt die Computer-Spiele-Branche ihre
immer realistischeren Grafikszenen auf den Bildschirm bringen.
Ich bin der Meinung, dass Shader-Programmierung, zumindest die Grundlagen, zum
Wissensschatz eines jeden Informatik-Interessierten gehört. Die Shader-Entwicklung
hat in den vergangen Jahren viel an Bedeutung zugenommen. Das wird sich in
Zukunft weiter verstärken. Um im Bereich der Grafikprogrammierung auf dem
neusten Stand zu sein, ist eine Auseinandersetzung mit dem Thema unausweichlich.
Nicht nur, aber gerade als Student der Informatik sollte man auf Fragen bezüglich
dieser Thematik seinem Gegenüber nicht völlig ahnungslos begegnen. Die
Dokumentation und die zugehörigen Programme sind so an gelegt, dass eine leichtverständliche und übersichtliche Einführung und Einarbeitung möglich ist.
Ich hoffe, dass Ihnen diese Ausarbeitung hilft den Sachverhalt zu verstehen und viel
mehr noch Ihre Neugier an der Shader-Programmierung weckt, ebenso wie in
meinem Fall.
Ronny Rösler
III
Einführung in die Shader Programmierung unter OpenGL 2.0
Inhaltsverzeichnis
Inhaltsverzeichnis
1. Einleitung
1.1 Projektbeschreibung
1.2 Zielsetzung
1
1
1
2.
2.1
2.2
2.3
2.4
2.5
2.6
2.7
2.8
Theorie
Geschichtliche Entwicklung von OpenGL
Was sind Shader ?
Welche Möglichkeiten bieten Shader ?
Wo werden Shader in der OpenGL-Pipeline eingesetzt ?
Was ist GLSL ?
GLSL oder HLSL ?
Grundoperationen zur Verwendung von Shader
Vor- und Nachteile von Shader
2
2
3
3
5
6
7
8
10
3.
3.1
3.2
3.3
3.4
3.5
3.6
3.7
3.8
Praxis
Aufbau von Shader
Variablentypen und Qualifiers
Kommunikation Anwendung zu Shader
Shader IDE's
Umgebungseinrichtung unter Windows mit DEV-C++ 5 IDE
Umgebungseinrichtung unter Solaris und Linux
Basis Programm in C
Beispiel: „Toon“-Shader
12
12
13
15
16
17
18
19
21
A
Glossar
23
B
Quellen
24
C
C.1
C.2
C.3
C.4
C.5
C.6
C.7
C.8
Anlagen
Übersicht: Dateisystem Projektdatenträger
Bedienungsanleitung: „Shader Demo“-Programm
Programmstrukturdiagramm: „OpenGL 2.0 Shader Demo“ Programm
Arbeitsumgebungen: „OpenGL 2.0 Shader Demo“-Programm
Fehler-Codes: „OpenGL 2.0 Shader Demo“-Programm
Quellcode: „OpenGL 2.0 Shader Demo“-Programm
Quellcode: Basis-Programm
Folien: Präsentation
25
25
26
28
30
31
32
33
34
IV
Einführung in die Shader Programmierung unter OpenGL 2.0
Einleitung
1. Einleitung
1.1 Projektbeschreibung
Im Rahmen der Lehrveranstaltung Systemprogrammierung ist das Projekt als Teil
der Grafikprogrammierung entstanden. Es beschäftigt sich mit der Programmierung
von Shader auf Basis des OpenGL 2.0 – Standard. Auf Grund einer möglichen
Integration des Themas in die Lehrveranstaltung Grafikprogrammierung wird der
Stoff aufgearbeitet. Diese Ausarbeitung bietet einen Überblick und ermöglicht den
Einstieg in die Thematik der programmierbaren Shader. Es wird sowohl
theoretisches Hintergrundwissen, wie auch praktische Umsetzung anhand von
Beispielen und Programmen geboten. Das Wissen wird klar strukturiert und
verständlich abgehandelt.
1.2 Zielsetzung
Dieses Projekt soll einen Einstieg in die Verwendung selbst-definierter ShaderProgramme bieten. Mit einfachen und verständlichen Erklärungen sollen
Basiswissen, sowie nötige praktische Vorgehensweisen vermittelt werden. Ziel ist es
weiterhin, Studenten für das Thema zu sensibilisieren und Interesse zu wecken in
diesem Bereich selbst kreativ zu werden. Neben der Ausarbeitung an sich, soll das
praktische Programmieren dem Leser und nicht zuletzt dem Projektbetrauten die
Funktionsweise verdeutlichen.
1
Einführung in die Shader Programmierung unter OpenGL 2.0
Theorie
2. Theorie
2.1 Geschichtliche Entwicklung von OpenGL
Um zu Verstehen wie bedeutend das Erscheinen der OpenGL Version 2.0 war,
machen wir uns noch einmal mit der Historie der „Open Graphics Library“ vertraut.
Als Urvater dieser plattform- und programmiersprachenunabhängigen API für 3DComputergrafiken gilt das IRIS GL von der Firma Silicon Graphics, Inc. (SGI). Anfang
der 90er Jahre versuchten die Firmen SGI und Microsoft ihre 3D-Grafikstandards zu
vereinheitlichen. Bedingt durch finanzielle Probleme auf Seiten von SGI wurde das
Projekt jedoch aufgegeben. Seit 1992 wird der OpenGL-Standard von dem so
genannten ARB verwaltet. ARB steht für Architecture Review Board, einem
Firmenkonsortium, in dem unter anderem die Firmen 3Dlabs, NVidia, ATI, SGI, IBM,
Intel, Sun, Dell und Matrox. 2003 hat Microsoft, einer der Gründer, das Team
verlassen.
Zu der grundlegenden Vorgehensweise bei der Weiterentwicklung des OpenGLStandards zählt die Verwendung von spezifischen Herstellererweiterung, mit denen
es möglich ist frühzeitig neue Funktionen zu verwenden. Das ARB macht aus diesen
herstellerabhängigen Erweiterungen unabhängige ARB-Erweiterungen. Erst dann
gehen Neuerungen in den Kern-Standard über. Dieses System gewährt OpenGL
zum einen immer auf dem neusten Stand zu sein und gleichzeitig die Grundidee der
Portabilität und Plattformunabhängigkeit weiter zu verfolgen. In den letzten Jahren
hat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht
zuletzt ist dies auf die frühere Einführung von programmierbaren Shader bei
Microsofts Direct3D-Grafikstandard zurückzuführen. Um nicht völlig den Anschluss
zu verlieren, wurden ARB-Erweiterungen für die Shader-Programmierung dem
Standard beigefügt. Jedoch erst jetzt, ab der aktuellen OpenGL Version 2.0 ist eine
eigene Sprache für die Shader-Programmierung direkt im Kern-Standard verfügbar.
Daher auch der Versionssprung von 1.5 auf 2.0.
Version
Zeitraum
Technische Neuerungen
1.0
07 / 1992
Erste Veröffentlichung
1.1
1997
Vertex Arrays, Texture Objects, Polygon Offset
1.2
03 / 1998
3D-Texturen, BGRA-, Packed-Pixelformat, Level-Of-Detail-Texturen
1.2.1
10 / 1998
Einführung der ARB-Erweiterungen, ARB-Multitexture
1.3
08 / 2001
Komprimierte Texturen, Cube-Maps, Multitexturing
1.4
07 / 2002
Tiefentexturen, Automatische MipMap-Erzeugung, Nebelkoordinaten
1.5
07 / 2003
Pufferobjekte, Occlusion Queries
2.0
09 / 2004
Einführung der GL Shading Language (GLSL / GLslang)
Multiple Render Targets, variable Texturgrössen
Abb. 2.1-1 – Übersicht OpenGL-Historie
Seit Mitte 2005 bieten die grossen Grafikkartenhersteller und ARB-Mitglieder NVidia,
ATI und 3Dlabs die ersten OpenGL 2.0 – Treiber mit ihren Produkten an.
2
Einführung in die Shader Programmierung unter OpenGL 2.0
Theorie
2.2 Was sind Shader ?
Shader zu deutsch Schattierer können sowohl in Hardware, als auch als
Softwarekomponenten realisiert sein. Shader sind mathematische Algorithmen,
welche die Aufgabe haben, bestimmte Effekte beim Berechnen einer
dreidimensionalen Computergrafik zu erzeugen. Dazu gehört auch die
Farbberechnung von Objekten in der dreidimensionalen Szene. Neue HardwareLösungen sind auf modernen Grafikkarten als programmierbare Module von
Hardware-Einheiten implementiert. Früher wurden Grafiken vollständig per Software
von der CPU berechnet. Will man jedoch viele „Frames“, also Bilder pro Sekunde
erreichen, so geht dies nur über den Einsatz von spezieller Hardware, dem
Grafikprozessor (GPU). Er ist erheblich schneller bei der Berechnung von
dreidimensionalen Echtzeit-Grafiken. Die Software-Lösungen werden oft von der
Filmindustrie bei aufwendigen Computeranimationen verwendet. Hierbei handelt es
sich jedoch nicht um Echtzeitberechnung.
Die Hardware-Schattierer lassen sich in zwei Kategorien einteilen, in Vertex- und
Pixel- (in OpenGL-Terminologie „Fragment“-) Shader. Der Vertex-Shader ist
pysikalisch in der „Transforming & Lighting“ (T&L)-Einheit untergebracht. Zusammen
mit dem Vertex-Shader-Programm ist er für geometrische Berechnungen im 3DRaum zuständig. Ausgeführt wird er für jeden Raumpunkt (Vertex) einmal pro Bild. In
der auf der GPU liegenden „Combiner“-Einheit ist der Hardware Pixel-Shader
integriert. Mit seiner Programmierung ist er für die Farb-Berechnung, bzw.
Texturierung der Bildpunkte verantwortlich. Pro Bild läuft er für jedes Fragment
einmal ab. Zusammen kann mit einem Shader-Programm, bestehend aus Vertexund Fragment-Shader eine Vielzahl von optischen Effekten erzeugt werden.
Beispieleffekte sind Wasseroberflächen, Chromglanz, aber auch Tiefentextur-Effekte
(Bump-Mapping) und verschiedenste Beleuchtungseffekte. Die feste Funktionalität
bei der Berechnung der Transformationen und Farbinformationen wird aufgehoben.
Shader bieten damit ein hohes Mass an Flexibilität.
2.3 Welche Möglichkeiten bieten Shader ?
Wie wir schon wissen, hat man mit der Implementierung von Shader-Programmen
eine Möglichkeit direkten Einfluss auf die Grafikberechnung zu nehmen. Mit den
Operationen in den Algorithmen lassen sich durch Vertex- und Pixelmanipulationen
eine Vielzahl von grafischen Effekten erzeugen. Das Ziel bei der Entwicklung einer
modernen „graphic engine“ ist eine orginalgetreue Nachbildung von Eigenschaften
der realen Welt. Eine „graphic engine“ ist ein Programmteil, der für die Darstellung
von Echtzeit-3D-Grafik, oft in Computerspielen bzw. –simulationen, zuständig ist. Bei
all den Bemühungen um mehr Realismus muss immer der erreichte Detailgrad bei
den Effekten und der dafür nötige Berechnungsaufwand abgewogen werden. Diese
Abhängigkeit ist besonders bei der Echtzeitberechnung von Computergrafiken zu
spüren. Bei komplexen Szenen mit vielen Objekten und aufwendigen Effekten
können, abhängig von der vorhandenen Hardware, oft nur wenige Bilder pro
Sekunde berechnet werden. Das macht sich dann mit einer stockenden Ausgabe
bemerkbar.
3
Einführung in die Shader Programmierung unter OpenGL 2.0
Theorie
Seit Hochsprachen für die Shader-Programmierung verfügbar sind, haben sich den
Entwicklern neue Möglichkeiten eröffnet. Die Hochsprache bietet gegenüber der
Maschinensprache den Vorteil der besseren Übersichtlichkeit. Dadurch ist es
möglich immer komplexere Algorithmen zu entwerfen. Natürlich ist die enorme
Leistungssteigerung der Grafik-Hardware in den letzten Jahren einer der
Hauptgründe für die wachsende Qualität von Grafikeffekten. Ohne genügend
Leistungskapazität sind aufwendige Shader-Algorithmen eine zu hohe Belastung für
die Hardware. Die neuste Grafik-Hardware lässt jedoch schon jetzt die vor nicht all
zu langer Zeit deutlich sichtbare Grenze zwischen Software- und Echtzeit-Rendering
verschwinden.
Am Beispiel des Wasseroberflächeneffekts lässt sich das Potential der Shader
verdeutlichen. In den Anfängen wurden Wasseroberflächen als Ebene aus gefärbten
Flächen dargestellt. Bei der nächsten Generation wurden die Flächen mit Texturen
belegt, was die Wasseroberfläche nicht mehr so plastisch erscheinen lies. Heute wird
„Bump-Mapping“ und „Dynamic Bump-Mapping“ eingesetzt. Damit ist es möglich
Konturen auf der texturierten Fläche vorzutäuschen. Das Verfahren bietet gute
Resultate bei annehmbarem Berechnungsaufand. Durch die immer leistungsfähigere
Grafik-Hardware ist auch die Verwendung von „Vertex Texturing“ mit dem so
genannten „Displacement-Mapping“ möglich. Hierbei wird nicht nur die Farbe der
Pixel für die Effekterzeugung benutzt, sondern bereits auf der Stufe der VertexTransformationen eingegriffen. Die Manipulation der Vertices beeinflusst somit direkt
die Ebene mit ihren Flächen und erzeugt damit eine Oberflächenkontur. Die
Wasseroberfläche wirkt realistischer als beim „Bump-Mapping“, jedoch wird dieser
Effekt mit viel höherem Berechnungsaufwand „bezahlt“. Die dabei eingesetzten
Shader-Algorithmen beinhalten weit mehr als 100 Operationen.
Die Abbildungen 2.3-1 und 2.3-2 zeigen 3D-Szenenausschnitte aus einem
Computerspiel. Im Vergleich ist deutlich der Unterschied zwischen dem „BumpMapping“ und dem „Displacement-Mapping“, bzw. „Vertex Texturing“ zu erkennen.
Abb. 2.3-1 – Dynamic Bump-Mapping
Abb. 2.3-2 – Displacement Mapping
(Bilder: Pacific Fighters von 1C:Maddox Games)
Durch die direkte Kontrolle beim Berechnen der Grafikszene bieten Shader eine
Vielzahl weiterer Effektmöglichkeiten. Seit dem Erscheinen von Shader-IDE's können
komplexe Shader mit Hilfe der Entwicklungsumgebungen per Maus-Klick zusammen
gestellt werden, ohne den gesamten Quellcode schreiben zu müssen.
4
Einführung in die Shader Programmierung unter OpenGL 2.0
Theorie
2.4 Wo werden Shader in der OpenGL-Pipeline eingesetzt ?
Um die Funktion von Shader im Berechnungsprozess einer 3D-Szene besser zu
verstehen ist es wichtig zu wissen an welcher Stelle in der OpenGL-Grafik-Pipeline
die Schattierer-Programme zum Einsatz kommen. Es ist nicht nötig die komplette
Rendering-Pipeline mit all ihren einzelnen Stufen darzustellen. Die Abbildung 2.3-1
zeigt grob den Ausschnitt der Berechnungsstrecke, wo Vertex- und Fragment-Shader
integriert werden. Wie in der Grafik zu erkennen, fliessen die Raumpunkte oder auch
Vertices genannt, in die Transformationseinheit. Dort finden Rotations-, Skalierungs-,
Translations-, sowie Lichtberechnungen, usw. statt. Mittels des programmierbaren
Vertex-Shaders können wir somit direkt Einfluss auf diesen geometrischen Prozess
nehmen.
Vertices
Vertex-Connectivity
(1.0, 2.5, 3.4, 1.0)
…
(GL LINE, GL POLYGON, …)
Vertex-Transformation
Transformed Vertices
Primitive Assembly / Rasterization
Vertex-Shader
Fragments
Pixel Positions
Fragment Texturing /
Coloring
Fragment-Shader
Colored Fragments
Raster Operations
Pixel Updates
Abb. 2.4-1 – Ausschnitt der OpenGL-Pipeline (abstrakt, in Anlehnung an Quelle 1)
Sind die Raumpunkte transformiert, werden sie mit den „VertexZusammengehörigkeitsinformationen“ zu den so genannten Primitiven zusammen
gesetzt. Auf dieser Stufe entstehen dann Linien-, Polygon-, Quads-Primitive, usw.,
wie wir sie in der Angabe der Geometriedaten im OpenGL-Programm definiert
haben. Weiterhin wird in diesem Prozess die Rasterung durchgeführt. Bei der die
OpenGL-Fragmente entstehen. Der Übergang vom 3D-Raum zum 2D-Bildschirm
findet statt.
5
Einführung in die Shader Programmierung unter OpenGL 2.0
Theorie
Die Pixelpositionen stehen nun fest, jedoch muss noch die Farbe berechnet werden.
Die Fragmente wandern dazu in die „Texturing and Coloring Unit“. Hier werden in
Abhängigkeit zu den berechneten Vektoren aus der Transformationseinheit die
Fragmente mit Farben oder Texturen versehen. Im letzten Schritt unserer Abbildung
werden die Pixel-Positionen zusammen mit den Farb- und Tiefeninformationen der
Fragmente an die „Raster Operations“-Stufe übergeben. Hier finden unter anderem
der „Scissor“-, „Alpha“-, „Stencil“- und „Depth“-Test statt. Es ist zwar möglich im
Fragment-Shader einen eigenen „Blending“-Algorithmus zu implementieren, jedoch
muss dabei auch auf den „Frame Buffer“ zugegriffen werden. Dieses vorgezogene
„Blending“ macht sich jedoch durch einen hohen Performance-Verlust bemerkbar.
Die Nutzung der in OpenGL standardmässig verwendeten „Alpha-Blending“-Funktion
ist somit vorzuziehen.
2.5 Was ist GLSL ?
GLSL, oder auch GLslang ist die Bezeichnung der „OpenGL Shading Language“.
Hierbei handelt es sich um eine Hochsprache zur Erstellung von ShaderProgrammen für Echtzeit-Rendering. Eingeführt wurde diese Sprachspezifikation mit
dem Erscheinen der OpenGL-Version 2.0. Sie ist nicht als eine der vielen
Erweiterung, sondern als fester Bestandteil des OpenGL-Kernsystems realisiert und
somit voll standardisiert. Der GLSL-Programmcode wird üblicherweise aus separaten
Dateien geladen, dann übersetzt und direkt auf der Grafikkarte ausgeführt. Was
einen erheblichen Geschwindigkeitsvorteil mit sich bringt. Programmiersprachen zum
Entwickeln von Shader gab es schon vor der OpenGL Version 2.0, jedoch waren
diese von Hersteller zu Hersteller verschieden. Neben GLSL ist die Sprache Cg (C
for graphics) von NVidia sehr verbreitet. Sie läuft jedoch nur mit Erweiterungen für
NVidia-Grafikkarten. Bevor Hochsprachen zur Shader-Entwicklung zur Verfügung
standen, wurden die Programme üblicherweise in „Assembly“, einem
Maschinensprache ähnlichem Code geschrieben. Diese Sprache ist jedoch sehr
unübersichtlich und schwer zu verstehen bei grösseren Aufgaben, daher war es nur
möglich relative kleine Shader-Algorithmen zu implementieren.
Die „GL Shading Language“ basiert auf den Programmiersprachen C und C++,
jedoch mit Einschränkungen. Es gibt unter anderem keine automatische
Typenkonvertierung. Zum Initialisieren von Variablen werden dem C++ ähnliche
Konstruktor-Aufrufe benutzt, usw. Es sind weiterhin spezielle Datentypen zum
Verwalten von Grafikdaten integriert. Dazu sind einige Funktionen zum Manipulieren
von Geometriedaten bereits definiert.
Die GLSL wird von allen ARB-Mitgliedern in ihren OpenGL 2.0 - Treibern unterstützt.
Damit ist ein universeller und herstellerunabhängiger Einsatz der Shader-Programme
möglich.
6
Einführung in die Shader Programmierung unter OpenGL 2.0
Theorie
2.6 GLSL oder HLSL ?
Im Grossen und Ganzen gibt es zwei Shader-Programmiersprachen, die mit
einander konkurrieren. Die „GL Shading Language“ (GLSL / GLslang) von OpenGL
2.0 und die „High Level Shading Language“ von Microsofts Direct3D. DirectX 9.0
samt Direct3D ist als eigenständige API-Sammlung unter Windows realisiert. Das
heisst, dass auch der HLSL-Übersetzer nicht wie bei OpenGL im Treiber vorhanden
ist. Die Hersteller der Grafikkarten müssen dadurch nicht für die Integration des
Übersetzers sorgen, was sich jedoch im Zusammenhang mit der Optimierung des
Shader-Codes als negativ auswirkt. Durch die getrennte Lösung kann der HLSLÜbersetzer nicht auf eventuelle treiberspezifische Optimierungseigenschaften
Rücksicht nehmen. Der Shader-Code wird erst nach dem Übersetzen aus dem
Direct3D-System an den Treiber der Grafikkarte geschickt. Dadurch entsteht ein
Performance-Problem was nicht einfach zu beseitigen ist. GLSL und HLSL
unterscheiden sich zudem in der Art der Kommunikation. Die Datenübergabe
zwischen der Applikation und den Shadern und den Shader-Programmen
untereinander sind sehr verschieden realisiert. HLSL ähnelt im allgemeinen mehr
dem C++.
Zum Vergleich hier ein Ausschnitt aus einem GLSL- und einem HLSL-Shader:
Abb. 2.6-1 – GLSL-Quellcode
Abb. 2.6-2 – HLSL-Quellcode
Da GLSL nur mit OpenGL und HLSL nur in Verbindung mit Direct3D funktioniert, ist
es bei einer Entscheidung zwischen den beiden Sprachen jedoch eher eine Frage
der API, die man für seine Anwendung benutzen möchte.
7
Einführung in die Shader Programmierung unter OpenGL 2.0
Theorie
2.7 Grundoperationen zur Verwendung von Shader
Damit selbst-entwickelte Shader-Programme auf der Grafikkarte installiert werden
können, ist eine Folge von Grundoperationen nötig. Unter anderem muss der
Shader-Quellcode aus den externen Dateien in die Applikation geladen werden. Er
muss dann übersetzt und gebunden werden, bevor er auf der Grafikkarte ausgeführt
werden kann. Unter OpenGL 2.0 lassen sich die notwendigen Operationen wie in der
Abbildung 2.7-1 dargestellt, unterteilen.
Schritt
Operation
OpenGL 2.0
1
Erstellen der Shader Container
glCreateShader
2
Shader Quellcode aus Dateien laden
3
Shader Quellcode in Shader
Container laden
glShaderSource
4
Shader Quellcode übersetzen
glCompileShader
5
Shader Programm Container
erstellen
glCreateProgram
6
Übersetzte Shader in Shader
Programm Container laden
glAttachShader
7
Shader Programm binden
glLinkProgram
8
Shader Programm installieren
glUseProgram
Abb. 2.7-1 – Notwendige Grundoperationen, OpenGL 2.0
8
Einführung in die Shader Programmierung unter OpenGL 2.0
Theorie
Es ist wichtig die einzelnen Operation und die dazugehörigen OpenGL 2.0
Anweisungen zu kennen. Unabhängig von den Shader-Programmen ist die Abfolge
für eine korrekte Installation vorgegeben.
Gehen wir die Schritte im Einzelnen durch:
Schritt 1: Erstellen der Shader Container.
Um mit den Shader-Programmen in unserer Applikation um gehen zu können,
brauchen wir „Handle“-Variablen. In den folgenden Operationen greifen wir über
diese auf die Shader zu.
Schritt 2: Shader Quellcode aus Dateien laden.
Da der Quellcode für die Shader in externen Dateien vorliegt, müssen wir diese in
unsere Applikation laden. Im Gegensatz zu den anderen Schritten muss das
Auslesen der Dateien selbst implementiert werden. OpenGL bietet keine Funktion
dafür. Der Dateiinhalt wird als Zeichenfolgenfeld, bzw. String-Array importiert.
Schritt 3: Shader Quellcode in Shader Container laden.
Der ausgelesene Shader-Algorithmus wird mit dieser Operation an die „Handler“Variable gebunden, bzw. in den Container laden. Erst nach diesem Schritt können
weitere OpenGL-Operationen auf den Shader-Quellcode angewendet werden.
Schritt 4: Shader Quellcode übersetzen.
Liegt der Quellcode im Shader-Container vor, wird er mit diesem Schritt vom GLSLÜbersetzer verarbeitet.
Schritt 5: Shader Programm Container erstellen.
Mit dieser Operation wird eine „Handle“-Variable für das Shader-Programm erstellt.
Ein Container für die Vertex- und Fragment-Shader. Zur Erinnerung: Nur ein Paar
aus Vertex- und Fragment-Shader kann als Programm auf die Grafikkarte geladen
werden.
Schritt 6: Übersetzte Shader in Shader Programm Container laden.
Mit diesem Schritt werden die fertig-übersetzten Vertex- und Fragment-Shader an die
Shader-Programm-Variable gebunden. Damit sind sie fortan über diesen „Handle“
erreichbar. Es ist möglich mehr als ein Vertex- oder Fragment-Shader in einen
Programm-Container zuladen, jedoch nur mit Einschränkungen. Mehr dazu im
Praxisteil.
Schritt 7: Shader Programm binden.
Mit einer expliziten Operation wird das OpenGL-System zum Binden des ShaderProgramms veranlasst. Erst nach diesem Schritt ist das Programm bereit auf die
Grafikkarte geladen und installiert zu werden.
Schritt 8: Shader Programm installieren.
Dies ist der letzte Schritt. Das fertig-gebundene Shader-Programm wird mit dieser
Operation auf die Grafikkarte geladen und vom OpenGL-Treiber zur Ausführung
gebracht.
9
Einführung in die Shader Programmierung unter OpenGL 2.0
Theorie
Neben diesen Grundoperationen zum Installieren der Shader gibt es weitere
Funktionen, mit denen die Kommunikation zwischen Shader-Programm und
Anwendung ermöglicht wird. Wie diese Schritte unter OpenGL 2.0 umgesetzt, bzw. in
„C“ codiert werden, sehen wir im Praxisteil Kapitel 3.
2.8 Vor- und Nachteile von Shader
Im Allgemeinen ist es immer von Vorteil, wenn statische Implementierungen durch
eine flexible Methode ersetzt werden können. Beim Einsatz von Shader-Programmen
wird die feste Funktionalität des OpenGL-Systems in Bezug auf die Transformation
und Farbberechnung aufgehoben. Das breite Spektrum an Implementierungsmöglichkeiten bietet dem Grafikentwickler die Chance seine kreativen Ideen
umzusetzen. In Bezug auf OpenGL, war die Shader-Programmierung vor dem
Erscheinen der Version 2.0 und der GL Shading Language kompliziert. Der
Programmcode musste in „Assmbly“, Maschinensprache verfasst werden, was selbst
bei gutem Wissen die Komplexität stark einschränkte. Zwar gab es schon
Hochsprachen für die Shader-Entwicklung, jedoch waren diese meist abhängig von
der Herstellererweiterung und der Hardware. Mit der Shader-Sprache in OpenGL 2.0
sind diese Nachteile nicht mehr vorhanden. Durch die Hochsprache GLSL ist auch
der Entwurf längerer und komplexerer Algorithmen machbar. Mit der Aufnahme in
den OpenGL-Kernstandard wird die Shader-Sprache von allen OpenGL 2.0-Treibern
unterstützt, unabhängig von Erweiterungen. Die Hersteller müssen die ShaderProgrammierbarkeit ihrer Hardware gewährleisten, wenn sie einen OpenGL 2.0kompatiblen Treiber anbieten wollen. Die Nutzung von Shader ist demnach abhängig
davon, ob die verbaute Grafikkarte das Programmieren durch Shader erlaubt.
Trotz der vielen Möglichkeiten, die Shader dem Entwickler bieten, ist der Einfluss auf
das „Alpha-Blending“ leider nur durch inakzeptabel hohe Leistungseinbussen
realisierbar. Bedingt durch den Aufbau der OpenGL-Pipeline sind vorgezogene
Funktionen aus erst später folgenden Stufen nur schlecht umsetzbar. Bei der
Shader-Entwicklung selbst, stehen dem Programmierer heute zahlreiche ShaderIDE's zur Seite. Ohne aufwendig direkt in GLSL oder HLSL Algorithmen zu
verfassen, wird von diesen Programmen der Shader-Code automatisch generiert, je
nach vorher visuell definiertem Effekt. Dadurch ist es auch mit nicht so gutem
mathematischen Wissen möglich schnell gewünschte Shader zu entwerfen. Und
nicht
zuletzt
wird
der
Zeitaufwand
die
Nutzung
von
ShaderEntwicklungsumgebungen erheblich reduziert.
Neben dem OpenGL-Standard ist die Shader-Programmierung auch mit HLSL in
Microsoft’s Direct3D möglich. Als eigene API kommuniziert DirectX jedoch nur mit
kompatiblen Treibern, was zwar die Entkopplung in Bezug auf Herstellerunterschiede
erhöht, aber nicht die Performance. Zudem ist HLSL in Direct3D ausschliesslich
unter Microsoft’s Windows-Betriebssystem verwendbar, was die Sache für den
Profibereich uninteressant macht. Nichts desto trotz plant Microsoft bei der nächsten
Version ihres Shader-Standards, „Shader Model 4.0“, die Vereinheitlichung von
Vertex- und Fragment-Shader zu einem Shader, was sicherlich interessante Vorteile
bieten wird.
10
Einführung in die Shader Programmierung unter OpenGL 2.0
Theorie
Vorteile
Nachteile
Flexible Lösung für Manipulation von
Echtzeit-Grafikberechnung
Hardware muss Programmierung mit
Shader unterstützen
Dank Hochsprachen, komplexe
Algorithmen realisierbar
Vertex- und Fragment-Shader müssen
als Paar installiert werden
Nutzung von Shader-IDE's vereinfachen OpenGL: „Alpha-Blending“ im
Entwicklung
Fragment-Shader nur mit schlechter
Performance
Realitätsnahe Effekte, wenn genügend
Direct3D: API ist nur unter Windows
Hardwareleistung
verfügbar
Technische Zukunftssicherheit in Bezug
auf Weiterentwicklung und Potential
Direct3D: HLSL-Übersetzer nicht im
Grafikkartentreiber, folglich schlechte
Optimierungsmöglichkeiten
Abb. 2.8-1 – Vor- und Nachteile von Shader
11
Einführung in die Shader Programmierung unter OpenGL 2.0
Praxis
3. Praxis
3.1 Aufbau von Shader
Nachdem wir uns in Kapitel 2 mit dem nötigen Hintergrundwissen vertraut gemacht
haben, betrachten wir jetzt den Shader-Aufbau genauer. Wie bereits in vorherigen
Kapiteln erwähnt, ist die „GL Shading Language“ aus OpenGL 2.0 stark an die
Programmiersprache „C“ angelehnt. Es ist daher nicht überraschend, das viele
semantische und syntaktische Eigenschaften in beiden Sprachen gleich sind.
Ebenso wie in „C“ ist der Einstiegspunkt die „main“-Funktion. Sie darf nur einmal je
Shader-Typ deklariert werden. Im Gegensatz zu „C“ hat sie aber keinen
Rückgabewert. Ein Set an Standard- und an Spezialvariablentypen steht dem
Entwickler zur Verfügung. Mehr dazu im folgenden Kapitel.
Die GLSL beinhaltet neben den mathematischen Grundoperationen auch einen
Vorrat an vordefinierten („Build-In“-) Funktionen, die das Arbeiten im geometrischen
Raum unterstützen. Als Beispiel sei hier die oft verwendete Funktion „normalize“
genannt, die zum Normalisieren von Vektoren verwendet wird. Auch die „dot“Funktion ist in vielen Shader-Algorithmen anzutreffen. Mit ihr kann das Punktprodukt
zweier Vektoren berechnet werden. Shader-Programme können je nach Komplexität
auch aus mehreren Dateien bestehen, die dann zu einem Vertex- oder FragmentShader zusammengefügt werden. Jedoch wie schon erwähnt, darf je Shader nur
einmal die „main“-Funktion definiert sein.
Shaderstruktur:
// Globale Variablendeklaration
varying vec4 vektor1, vektor2;
varying float fvariable1;
uniform float fvariable2;
/* Funktion mit einem float Parameter */
vec4 berechneVektor (in float parameter1)
{
vec4 vektor;
…
return (vektor);
}
/* Main-Funktion fuer diesen Shader */
void main ()
{
// Lokale Variablendeklaration
vec4 cVektor;
// Operationen und Anweisungen
vektor1 = vec4 (1.0, 2.2, 3.8, 1.0);
vektor2 = vec4 (vektor1.xy, 0.35, 1.0);
fvariable1 = dot (vec3 (vektor1), vec3 (vektor2));
cVektor = berechneVektor (fvariable2);
…
}
12
Einführung in die Shader Programmierung unter OpenGL 2.0
Praxis
Die oben gezeigte Shaderstruktur stellt den grundlegenden Aufbau eines ShaderProgramms da. Aus der Sprache „C“ sind zusätzlich die Strukturen „if“, „while“, „do
while“ und „for“ in der üblichen Notation verfügbar.
Die komplette Liste aller benutzbaren Konstrukte und „Build-In“-Funktionen ist in der
„GLSLang“-Spezifikation zu finden. Diese befindet sich als PDF-Dokument auf dem
Projekt-Datentraeger.
3.2 Variablentypen und Qualifiers
Die Deklaration der Variablen und der Zugriff auf diese ist in OpenGL 2.0-ShaderProgrammen zwar ähnlich wie in der Sprache „C“, jedoch gibt es einige
Erweiterungen. Neben den bekannten Datentypen „float“, „int“ und „bool“ sind auch
komplexere Typen verwendbar. Vektoren mit variierender Komponentenanzahl und
in unterschiedlichen Typen, sowie quadratische Matrizen als 2x2, 3x3 und 4x4.
Vektoren können aus den drei Basistypen „float“, „int“ und „bool“ bestehen. Neben
diesen Datentypen sind auch spezielle „Sampler“-Typen verfügbar, um den Zugriff
auf Texturen unterschiedlicher Dimension zu ermöglichen. Identisch zur „C“-Notation
sind auch „struct“-Strukturen deklarierbar. Bei der Initialisierung der Variablen ist im
Gegensatz zu „C“ kein „Typcast“ vorhanden. Statt dessen ist die Benutzung eines
konstruktor-ähnlichem Aufrufs vorgesehen.
Als Beispiel:
float a = 10; // falsch
a = (float) 10; // falsch
float a = float (10); // richtig
Die einzelnen Komponenten komplexerer Datentypen sind direkt über vordefinierte
Buchstaben ansprechbar. Bei Vektoren sind dies „x“, „y“, „z“, „w“, bei Farben „r“, „g“,
„b“, „a“. Dies gilt auch für Kombinationen.
Als Beispiel für Vektoren:
vec3 vektor3d = vec3 (2.1, 3.3, 2.7);
vec2 vektor2d = vektor3d.xy; // vektor2d hat die Werte {2.1, 3.3}
Qualifiers
Um die Variablen in „GLSL“-Programmen mit bestimmten Eigenschaften zu
versehen, können diese in bestimmte Gruppen eingeteilt werden. Dies geschieht
über die Verwendung von „Qualifiers“. Durch ein vorangestelltes Schlüsselwort
werden nachstehende Variablen speziell vordefiniert. Als Qualifier stehen vier
Kategorien zur Auswahl: „const“, „varying“, „uniform“ und „attribute“.
const
Dieser Qualifier definiert eine Variable, die bei der Programmübersetzung einen
festen Wert bekommt. Identisch zu „C“.
13
Einführung in die Shader Programmierung unter OpenGL 2.0
Praxis
varying
Variablen mit diesem Schlüsselwort sind für die Kommunikation zwischen Vertexund Fragment-Shader nötig. Die Deklaration muss in beiden Shader-Programmen
vorgenommen werden. Der Zugriff ist je Shader-Typ unterschiedlich. Im VertexShader sind „varying“-Variablen les- und beschreibbar. Im Fragment-Shader können
sie nur ausgelesen werden.
uniform
„uniform“-Variablen sind globale Variablen, die sowohl im Vertex- als auch im
Fragment-Shader deklariert werden können. In beiden Shader-Typen sind sie nur
les- und nicht beschreibbar. „uniform“-Variablen werden zur Kommunikation
zwischen Anwendung und Shader verwendet. Sie können jedoch nur je Primitiv
gesetzt werden. Innerhalb der „glBegin“/“glEnd“-Anweisungen, durch die ein Primitiv
deklariert wird, sollte demnach keine Änderung an der Variable erfolgen. Es sind
auch vordefinierte „Build-In“-„uniform“-Variablen verfügbar.
Mit den Operationen, die für den Zugriff auf „uniforms“ nötig sind, befassen wir uns
im nächsten Kapitel.
attribute
Der Qualifier „attribute“ kennzeichnet globale Variablen, die nur im Vertex-Shader
verfügbar sind. Sie sind nur les- und nicht beschreibbar. Im Gegensatz zu den
„uniform“-Variablen sind diese jedoch je Vertex setzbar. Sie können demnach an
jeder Stelle verändert werden, auch innerhalb der Primitiv-Deklaration. Neben selbstdefinierten Variablen sind ebenso wie bei „uniform“-Variablen auch „Build-In“„attribute“-Variablen im Shader lesbar.
Anwendung
„Build-In“„uniform“-Variable
„Build-In“„attribute“-Variable
„Build-In“„varying“-Variable
Vertex-Shader
„attribute“-Variable
„varying“-Variable
„uniform“-Variable
Fragment-Shader
Abb. 3.2-1 – Schaubild „Qualifier“-Verfügbarkeit
14
Einführung in die Shader Programmierung unter OpenGL 2.0
Praxis
3.3 Kommunikation Anwendung zu Shader
Neben den Basisoperationen zum Laden, Übersetzten, Binden und Installieren von
Shader-Programmen, sind bei der Kommunikation von Anwendung zu Shader
weitere Schritte nötig. Zwei Variablen-Qualifiertypen stehen uns zur Kommunikation
mit den Shader-Programmen zur Verfügung, „Uniforms“ und „Attributes“. Um Zugriff
auf die im Shader-Code definierten Variablen zu bekommen, muss das ShaderProgramm
gebunden
und
installiert
sein.
Durch
die
Funktionen
„glGetUniformLocation (…)“ und „glGetAttribLocation (…)“ werden die Variablen an
einen „Handler“ gebunden. Als Parameter werden das Shader-Programm, sowie der
Name der Variable übergeben. Mit den Funktionen „glUniform* (…)“ und
„glVertexAttrib* (…)“ lassen sich die Shader-Variablen setzen. Als Parameter wird
der Variablen-Handler und die zu setzenden Werte, je nach Funktion, übergeben.
Beispiel:
…
varHandler = glGetUniformLocation (shadProgHandle, „fVariable2“);
…
glUniform1f (varHandler, 9.81);
…
Mit dieser Kommunikationsmöglichkeit kann zum Beispiel die Position und die Farbe
einer Lichtquelle dem Shader-Programm mitgeteilt werden. Benutzt man das
OpenGL-Lichtmodell zur Definierung von Lichtquellen, können im Shader auch
spezielle „Build-In“-Variablen ausgelesen werden, um an die Informationen zu
kommen. Die manuelle Kommunikation muss in diesem Fall nicht aufgebaut werden.
Eine Übersicht und Beschreibung der „Build-In“-Uniforms und –Attribute ist in der
„GLSL“-Spezifikation enthalten.
Schritt
9
Operation
OpenGL 2.0
Variable an Handler binden
glGetUniformLocation
glGetAttribLocation
10
glUniform*
Variable setzen
glVertexAttrib*
Abb. 3.3-1 – Operationen zum Setzen von Shader-Variablen, OpenGL 2.0
15
Einführung in die Shader Programmierung unter OpenGL 2.0
Praxis
3.4 Shader IDE's
Wie wir bereits wissen ist der Entwurf von Shader-Algorithmen eine knifflige Sache.
Neben programmiertechnischen Kenntnissen ist vor allem Mathematikwissen
erforderlich. Einfache Shader sind noch ohne grössere Probleme realisierbar. Sollen
jedoch komplexe Manipulationen in den Shader-Programmen stattfinden, ist trotz der
Hochsprachen „GLSL“ und „HLSL“ der Aufwand sehr hoch. Mit dem Voranschreiten
der Shader-Programmierung sind auch Shader-Entwicklungsumgebungen entwickelt
worden, die dem Grafikprogrammierer das Erstellen von Shader-Algorithmen
erheblich vereinfachen. Per Maus-Klick können meist viele tausend mitgelieferter
Shader angepasst und kombiniert werden. Die Oberflächen ermöglichen es dem
Entwickler schnell und effizient Shader-Effekte zu kreieren. Der generierte ShaderCode kann dann mit der eigentlichen Anwendung geladen werden. Ob der erzeugte
Code auch optimale Leistung bringt sei dahingestellt. Jedoch beschleunigt die
Benutzung derartiger Hilfsmittel die Entwicklung von Grafikanwendungen, wie
Computerspiele erheblich. Eine der bekanntesten Shader IDE's ist „Rendermonkey“
von der Firma ATI, die auch ARB-Mitglied ist. Das Programm unterstützt sowohl
OpenGL- als auch DirectX-Shader bei der Codegenerierung.
Abb. 3.4-1 – Shader IDE: RenderMonkey
Weitere bekannte IDE's sind ShaderWorks, ShaderDesigner, FX Compose und Mad
F/X. Einige unterstützen jedoch noch nicht die Shader-Sprachen GLSL und HLSL.
Auf die Bedienung von Shader-Entwicklungsumgebungen soll hier nicht eingegangen
werden. Die Erstellung eines Tutorials dazu, bietet genug Stoff für eine separate
Ausarbeitung.
16
Einführung in die Shader Programmierung unter OpenGL 2.0
Praxis
3.5 Umgebungseinrichtung unter Windows mit DEV-C++ 5 IDE
Die korrekte Einrichtung der Entwicklungsumgebung ist ein wichtiges Thema auf
dem Weg zum lauffähigen Programm. Ohne einige zusätzliche Anpassungen lassen
sich OpenGL 2.0-Shader-Anwendungen nicht übersetzen. Im folgenden soll dies für
die DEV-C++-Umgebung der Version 5 unter Windows XP erläutert werden. Warum
DEV-C++ ? Neben vielen anderen C/C++ Entwicklungsumgebungen ist sie kostenlos
über die Internetseite „www.bloodshed.net“ zu bekommen. Zudem ist sie leicht zu
handhaben und allseits bekannt. Eine einfache Installation und ein Online-UpdateService zum Einspielen zusätzlicher Module wird ebenfalls angeboten. Nach der
Standard-Installation von DEV-C++ 5 unter Windows XP ist die Erstellung eines
OpenGL-Programms bereits möglich, jedoch nur eingeschränkt. Es fehlen die
„Header“-Dateien und Bibliotheken der „GLUT“ und „GLEW“. Diese müssen wir jetzt
nachträglich installieren. Die „GL utilities“ beinhalten unter anderem Funktionen zum
Erstellen von OpenGL-Fenstern. Der „GL extension wrangler“ stellt die nötigen
Funktionen zur Shader-Programmierung zur Verfügung. Die GLEW-Dateien sollten
von der neusten Version sein, bzw. OpenGL 2.0 unterstützen. Also mindestens
GLEW-Version 1.3.0. Entweder „googeln“, oder von „glew.sourceforge.net“ laden.
Die „Header“-Dateien (*.h) nach „…\Dev-Cpp\include\GL“ und die Bibliothek(en) mit
„*.a“ nach „…\Dev-Cpp\lib“ kopieren. Die „Dynamic-Link-Library“ (*.dll) nach
„…\WINDOWS\system32“ transferieren. Die „GLEW“-Bibliothek ist jetzt verfügbar.
Um „GLUT“-System einzurichten reicht es nicht eine beliebige Version aus dem
Internet zu laden. Bedingt durch den bei DEV-C++ mitgelieferten C/C++ Übersetzer
„mingw32“, muss ein spezielles GLUT-Paket installiert werden. Entweder „googeln“
oder das Paket von der Projekt-CD (Verzeichnis siehe Anhang). Die „*.h“-, „*.a“- und
„*.dll“-Dateien wie schon beim GLEW-Paket in die dafür vorgesehenen
Unterverzeichnisse legen. Sind diese Dateien korrekt platziert, müssen wir nur noch
dem „mingw32“-Binder mitteilen, dass er die „Dynamic-Link-Libraries“ beim Erstellen
des Programms einbinden soll. Dafür gehen wir über das Menü „Projekt“>“Projekt
Optionen“ zu den Binder(Linker)-Parametern. Hier fügen wir die Einträge „lopengl32“, „-lglu32“, „-lglut32“, „-lglew32“ ein. Die Dev-C++ 5-Version liegt derzeit
nur als Beta-Version vor, was hier und da für Fehler sorgt. Bei auf meinem Rechner
installierten Version lassen sich die Projektoptionen nicht über die Oberfläche
ändern. Ich bekomme statt dessen einen Ausnahmefehler gemeldet. Jedoch kann
man das Problem über die manuelle Modifikation der Dev-C-Projektdatei umgehen,
wie in Abbildung 3.5-1 gezeigt.
Abb. 3.5-1 – Dev-C++ Projektdatei
Abb. 3.5-2 – Dev-C++ Konsolenprojekt
17
Einführung in die Shader Programmierung unter OpenGL 2.0
Praxis
Damit ist das Entwicklungssystem vorbereitet. Zusätzlich muss der vorhandene
Grafikkarten Treiber OpenGL 2.0 unterstützen. Dies ist bei allen neuen nVidia und
ATI-Produkten der Fall. Natürlich ist die hardwareseitige Unterstützung ebenso
Pflicht. Schliesslich wollen wir ja mittels Shader die Hardware programmieren. Bei
nVidia-Karten sollte da schon mindestens eine „GeForce3“-Grafikkarte im Rechner
sein. Das DEV-C++ Projekt selber kann als Konsolen- oder Windowsanwendung
definiert werden. Wollen wir über „printf“ Ausgaben machen, müssen wir das Projekt
als Konsolenanwendung wählen (Abb. 3.5-2).
3.6 Umgebungseinrichtung unter Solaris und Linux
Anders als bei der Verwendung von HLSL-Shader-Programmen für Direct3D ist
OpenGL als professionelles Grafiksystem nicht nur unter Microsoft Windows
verwendbar. Die Shader-Programmierung mit „GLSL“ ist auch unter UNIX- und
Macintosh-Systemen möglich. Die Systemeinrichtung unter Linux und Solaris verläuft
ähnlich wie für Windows. Die OpenGL-Systemkomponenten „GLUT“ und „GLEW“
werden hier ebenfalls nachinstalliert. Die Pakete für die jeweiligen Systeme können
als „vorübersetzten“, oder als reineren Quellcode aus dem Internet geladen werden.
Die Anleitung zur Übersetzung des Quellcodes wird hier nicht behandelt.
Üblicherweise ist sie jedoch in den Paketen enthalten oder kann im Internet
gefunden werden. Für Solaris können GLUT-Pakete als 32bit- oder 64bit-Versionen
von der OpenGL-Internetseite „www.opengl.org“ geladen werden. Für Linux ist das
„GLUT“-System je nach Distribution als einspielbare Pakete zu bekommen.
Der „GL extension wrangler“ (GLEW) kann analog zur Umgebungseinrichtung unter
Windows von der Internetwebsite „glew.sourceforge.net“ geladen werden. Für die
„vorübersetzten“-Versionen gilt: Nach dem Entpacken die „Header“-Dateien (*.h)
unter „/usr/local/include/GL“ bei den bereits vorhandenen OpenGL-„Header“-Dateien
ablegen. Die dynamsichen Bibliotheken (*.so), sowie die „symblischen Links“ ins
Verzeichnis „/usr/local/lib“. Sollte man keine Administratorrechte auf dem System
besitzen, kann man die Dateien auch im „home“-Verzeichnis ablegen und die Pfade
für den Übersetzer anpassen, bzw. erweitern. Ebenso erlauben die Übersetzer auch
eine Pfadangabe als Parameter beim Aufruf. Beim Binden muss wie auch unter
Windows die Benutzung der dynamischen Bibliotheken explizit angegeben werden.
Der Binder muss dafür mit den zusätzlichen Parametern „-lGL“, „-lGLU“, „-lglut“, „lGLEW“ aufgerufen werden. Je nach den vorliegenden „symbolischen Links“ ist die
Gross- und Kleinschreibung anzupassen.
Wie wir wissen, ist das OpenGL-Kernsystem ein Bestandteil der Grafikkartentreiber.
Das heisst auch unter Linux und Solaris muss ein OpenGL 2.0-kompatibler Treiber
installiert sein. Gerade unter Solaris für Sparc-Systeme ist die Unterstützung solcher
Treiber nicht selbstverständlich, da die Shader-Programmierung auch Shaderprogrammierbare Grafikkarten voraussetzt. Unter Linux und Solaris x86 sollten die
nötigen Treiber erhältlich sein. Eine spezielle Oberfläche für die Programmierung
wird hier nicht vorgegeben. Die Verwendung von „Xemacs“ als Editor ist möglich. Die
Übersetzung kann per Kommandozeilenskript erfolgen.
18
Einführung in die Shader Programmierung unter OpenGL 2.0
Praxis
3.7 Basis Programm in C
In diesem Kapitel schauen wir uns an, wie ein grundlegendes Programm zur
Installation von OpenGl 2.0 – Shader aufgebaut ist. Wir beschäftigen uns im
Folgenden mit der „C“-Variante. Neben der Implementierung in der Sprache „C“ gibt
es auch die Möglichkeit über Java ein Ladeprogramm zu erstellen. Jedoch ist erstere
Lösung gerade für die grundlegende Vorgehensweise oft einfacher und klarer
verständlich. Ein OpenGL-Minimalprogramm mit Einbindung der „GLUT“-Bibliothek
muss neben der Initialisierung die Implementierung der „display“- und der „resize“Funktion umfassen. Wollen wir nun zusätzlich Shader-Programme benutzen, müssen
wir, wie schon im Kapitel 2 erläutert, eine Menge an Grundoperationen, bzw.
Anweisungen durchführen. Diese können in einer eigenen Prozedur abgearbeitet
werden. Denn nicht zuletzt entscheidet die Lesbarkeit eines Programmcodes über
dessen Verständlichkeit. Aus Platzgründen gehen wir hier ausschliesslich den
Shader-betreffenden Teil durch. Das betreffende Programm „ogl2test“ ist auf dem
Projektdatenträger zu finden. Der Quellcode ist auch im Anhang dieses Dokuments
enthalten. Des weiteren ist das Basisprogramm ohne Fehlerkontrolle implementiert,
um die Übersichtlichkeit nicht unnötig zu verschlechtern. Die zuvor erwähnte
Prozedur zum Installieren der Shader, heisst in diesem Programm „installShaders“.
Die in Kapitel 2.7 beschriebenen Operationen werden dort wie folgt in „C“ umgesetzt.
void installShaders (void)
{
Zunächst müssen wir die Handler-Variablen vom Typ „GLint“, sowie die Zeiger auf
den Quellcodespeicher der Shader deklarieren.
GLuint vsHandle, fsHandle, ShaderProgramHandle;
char *vsSource, *fsSource;
Wir beginnen mit Schritt 1, der Erstellung der Container für die Shader.
vsHandle = glCreateShader (GL_VERTEX_SHADER);
fsHandle = glCreateShader (GL_FRAGMENT_SHADER);
Im zweiten Schritt laden wir den Quellcode des Shaderpaares aus ihren Dateien als
Zeichenkettenfeld. Die Funktion „readTextFile“ bewerkstelligt dies.
vsSource = readTextFile ("toon.vs");
fsSource = readTextFile ("toon.fs");
Die geladen Quellcodes müssen jetzt in den betreffenden Container geladen werden.
Über die dafür deklarierten Konstanten „vv“ und „ff“ kann die Operation durchgeführt
werden. Dannach wird der Speicher für die Zeichenkettenfelder wieder freigegeben.
const char * vv = vsSource;
const char * ff = fsSource;
glShaderSource (vsHandle, 1, &vv, NULL);
glShaderSource (fsHandle, 1, &ff, NULL);
free (vsSource);
free (fsSource);
In diesem Schritt wird der Quellcode für beide Shader übersetzt. Die Fehlerabfrage
zu dieser Operation ist hier nicht implementiert. Sie kann jedoch im „Shader Demo“Programm an selber Stelle nachvollzogen werden.
glCompileShader (vsHandle);
glCompileShader (fsHandle);
19
Einführung in die Shader Programmierung unter OpenGL 2.0
Praxis
Wie schon in den vorherigen Kapiteln angesprochen, können Shader nur als Paar
aus Vertex- und Fragment-Shader geladen werden. Deutlich wird dies durch die
Erstellung des Shader-Programms in diesem Vorgang.
ShaderProgramHandle = glCreateProgram ();
Die übersetzten Shader werden in diesem Schritt zum Shader-Programm
hinzugefügt.
glAttachShader (ShaderProgramHandle, vsHandle);
glAttachShader (ShaderProgramHandle, fsHandle);
Die vorletzte Anweisung startet das Binden des Shader-Programms. An dieser Stelle
sei noch ein Mal daran erinnert, dass sowohl der Übersetzer als auch Binder
Bestandteile des OpenGL 2.0 Kernsystems sind und nicht extern vorliegen.
glLinkProgram (ShaderProgramHandle);
Der letzte Schritt veranlasst das OpenGL-System das „fertige“ Shader-Programm auf
der Grafikkarte zu installieren. Um das Shader-Paar wieder zu entfernen, wird die
Anweisung „glUseProgram (0);“ benutzt. Dies ist wichtig, möchte man
unterschiedliche Shader für unterschiedliche Objekte in der Szene benutzen. Dann
sollte man die Aktivierung der Shader direkt in der „Display“-Funktion durchführen.
Andernfalls wird der Shader auf alle Objekte nach dem Aufruf dieser Prozedur
angewandt.
glUseProgram (ShaderProgramHandle);
}
Die Prozedur installiert uns das Shader-Paar „toon.vs“ und „toon.fs“, das Objekte in
der Szene als Zeichentrickgrafik darstellt. Beide Shader-Teile benötigen keine
Kommunikation mit der Anwendung, daher werden auch keine „Uniform“- oder
„Attribute“-Variablen mit den Shader-Programm verbunden. Erfordert ein ShaderPaar Daten aus der Applikation, so muss die Verbindung wie in Kapitel 3.3 behandelt
aufgebaut werden.
20
Einführung in die Shader Programmierung unter OpenGL 2.0
Praxis
3.8 Beispiel: „Toon“-Shader
Nachdem wir uns mit dem nötigen Hintergrundwissen und der dazugehörigen Praxis
zum Laden und Installieren von Shader-Paaren vertraut gemacht haben,
beschäftigen wir uns mit den Shader-Algorithmen selbst. Auch wenn der Einsatz von
Shader-Entwicklungsumgebungen immer mehr zum Standard wird, ist es dennoch
von Vorteil sich mit GLSL-Code auseinander zu setzen. Analysieren wir im folgenden
einen Beispiel-Shader, der noch ohne grossen Aufwand verständlich wird. Shader für
„Displacement-Mapping“ zu analysieren, setzt erheblichen Sachverstand in
Mathematik und Grafikprogrammierung voraus und ist zur Einführung in GLSL nicht
geeignet. Zudem sind Shader dieser Art oft „Know-How“ von Firmen und werden
nicht oder sehr selten als Quellcode veröffentlicht.
Als relativ simpler Shader, aber dennoch einen
bekannten Effekt erzeugend, gilt der „Toon“Shader. Er stuft die Farben eines Objektes je nach
Einfallwinkel der Lichtquelle grob ab. Dadurch
entsteht die bekannte „Zeichentrickgrafik“. Der
„Toon“-Shader als Beispiel für GLSL wird im
Internet oft verwendet und ist unter anderem auch
im „Lighthouse3D“-Tutorial (Quellenangabe 1)
anzufinden. Gehen wir den GLSL-Code für beide
Shader-Teile durch.
Abb. 3.8-1 – Toon-Shader
Vertex-Shader:
Deklarierung eines dreidimensionalen Vektors zur Kommunikation mit dem
Fragment-Shader. Zur Erinnerung „varying“-Variablen können im Fragment-Shader
gelesen werden.
varying vec3 normalVec;
void main ()
{
Der Normalenvektor des Vertex „gl_Normal“ (Build-In-Vertex-Attribute) wird durch
Multiplikation mit der Normalmatrix (Build-In-Uniform) transformiert und
anschliessend per „Build-In“-Funktion normalisiert.
normalVec = normalize (gl_NormalMatrix * gl_Normal);
Das Setzen der „Build-In-varying“-Variable des Vertex-Shaders „gl_Position“ ist in
jedem Vertex-Shader Pflicht. Andernfalls wird die OpenGL-Pipeline nicht korrekt
geschlossen. Die hier verwendete „Build-In“-Funktion „ftransform“ macht nichts
anderes als die Vertex-Position mit der „ModelViewProjectionMatrix“ zu
multiplizieren. In diesem Shader wird an der Vertex-Position keine Manipulation
durchgeführt.
gl_Position = ftransform ();
}
21
Einführung in die Shader Programmierung unter OpenGL 2.0
Praxis
Fragment-Shader:
Wie in GLSL erforderlich, wird die „Input“-Variable aus dem Vertex-Shader hier
nochmals deklariert, damit sie gelesen werden kann.
varying vec3 normalVec;
void main ()
{
Deklarierung zweier lokaler Variablen, die für den „Toon“-Algorithmus benötigt
werden.
float intensity;
vec4 color;
Diese Anweisung berechnet die Intensität des einfallenden Lichts über das
Skalarprodukt zwischen dem Positionsvektor der Lichtquelle „0“ („Build-In-Uniform“Variable „gl_LightSource“) und dem im Vertex-Shader normalisierten und
transformierten Normalenvektor des Vertex. Die Lichtquelle muss in der Anwendung
definiert werden, damit sie über diese „eingebaute“ Variable ausgelesen werden
kann. Zur Erinnerung: Durch das Skalarprodukt zweier Vektoren kann deren Position
zueinander bestimmt werden. Ist das Ergebnis null, so stehen sie senkrecht im 90°Winkel zueinander. Beim Wert von eins, sind sie parallel.
intensity = dot (vec3 (gl_LightSource [0].position), normalVec);
Die ermittelte Intensität des einfallenden Lichts wird in vier Bereiche abgestuft. Je
Bereich wird eine Farbe definiert und der lokalen Variablen „color“ zugewiesen.
if (intensity > 0.90)
{
color = vec4 (1.0, 0.56, 0.0, 1.0);
}
else if (intensity > 0.60)
{
color = vec4 (0.64, 0.35, 0.0, 1.0);
}
else if (intensity > 0.30)
{
color = vec4 (0.37, 0.17, 0.0, 1.0);
}
else
{
color = vec4 (0.12, 0.07, 0.0, 1.0);
};
Der Farbwert wird der „Build-In-varying“-Variable zugewiesen.
gl_FragColor = color;
}
Das Shader-Paar und weitere Beispiel-Shader sind auf dem Projektdatenträger
vorhanden.
22
Einführung in die Shader Programmierung unter OpenGL 2.0
Glossar
A Glossar
Begriff
Erklärung
API
Application Programming Interface, eine Software
Schnittstelle.
Ein Verfahren zum Vortäuschen von Tiefeneindruck
auf texturierten Flächen.
Ein Modul des DirectX-API, das für die 3DGrafikberechnung zuständig ist.
auch Vertex-Texturing, Im Gegensatz zum
Bump-Mapping wird hier auch die Geometrie in
Abhängigkeit zur Textur verändert.
Wie „Bump-Mapping“ jedoch mit verschieben der
Höhentextur(en).
In der Computer-Grafik ein „potentielles Pixel“.
Bump-Mapping
Direct3D
Displacement-Mapping
Dynamic Bump-Mapping
Fragment
GLSL
Highmap
HLSL
IDE
IRIS GL
OpenGL
OpenGL-Pipeline
Shader
Vertex
auch GLslang, „C“-ähnliche Hochsprache
zur Shader-Programmierung unter OpenGL 2.0.
Eine spezielle Textur die Höheninformationen für
Bump-Mapping enthält.
Steht für „High Level Shading Language“. Ist die
Hochsprache für Direct3D-Shader.
„Integrated Development Environment“. Eine
Oberfläche für die Programmentwicklung.
Eine von der Firma Silicon Graphics Inc. entwickelte
Grafik-API. Vorläufer des OpenGL.
Eine hardwarehersteller-unabhänge
Programmierschnittstelle für Grafikanwendungen
konstruiert als Zustandsautomat. Verfügbar unter
vielen Betriebssystemumgebungen.
auch „OpenGL-Rendering-Pipeline“ genannt. Der Weg
den eine mathematische Vektorgrafik im OpenGLSystem durchläuft bis sie am Bildschirm ausgegeben
wird.
Ein mathematischer Algorithmus zur Manipulation von
Grafikberechnungen.
Ein Raumpunkt mit drei Koordinaten und optional
einem Tiefenwert.
23
Einführung in die Shader Programmierung unter OpenGL 2.0
Quellen
B Quellen
Internet
1.
Tutorial zu GLSL, engl., sehr gut strukturiert, empfehlenswert
- http://www.lighthouse3d.com/opengl/glsl/index.php
2.
NeHe Productions Artikel 21, engl., empfehlenswert
- http://nehe.gamedev.net/data/articles/article.asp?article=21
- \quellen\nehe_productions\nehe_productions_article_#21.pdf
3.
GLSL Specification 1.10
- http://oss.sgi.com/projects/ogl-sample/registry/ARB/GLSLangSpec.Full.1.10.59.pdf
- \quellen\glsl_specification\glslangspec.full.1.10.59.pdf
4.
Tutorial zu OpenGL und Shader, deu., nur ARB-Shader
- http://nightspawn.com/files/gltut/html/index.html
5.
Wikipedia Online-Bibliothek
- http://www.wikipedia.de
24
Einführung in die Shader Programmierung unter OpenGL 2.0
Anlagen
C Anlagen
C.1 Übersicht: Dateisystem Projektdatenträger
Auf dem Projektdatenträger befinden sich in kategorisierten Verzeichnissen und
Unterverzeichnissen die Projektdaten. Die Struktur sieht wie folgt aus:
Verzeichnisse
Inhalt
bilder
Alle in der Ausarbeitung und Präsentation
verwendeten Bilder in unterschiedlichen
Dateitypen.
dokumentation
Das Ausarbeitungsdokument als Microsoft
Word- und Adobe PDF-Dokument.
praesentation
Die Präsentationsfolien im Microsoft
Powerpoint-Format. Auch als selbst-laufende
Version.
programme
ogl2test
Das Basisprogramm „ogl2test“:
Quellcodedateien, Objektdateien,
„Toon“-Shader-Paar, Makefile f. Win.,
DEV-C++ 5 – Projektdateien,
ausführbare Windowsdatei.
programmierrichtlinien
Richtlinien für „C“-Programmierung von
Prof. Dr. S. Groß als PDF-Dokument.
resourcen
GLEW-Paket für Windows-Umgebung, sowie
das GLUT-Paket für den „ming“-Übersetzter
der DEV-C++ 5 – IDE.
shaddemo
Das Shader-Test-Programm „OpenGL
2.0 Shader Demo“: Quellcodedateien,
Objektdateien, Makefile f. Win.,
DEV-C++ 5 – Projektdateien,
ausführbare Windowsdatei.
shader
quellen
Eine Auswahl an Shader-Paaren aus
dem Internet. Auch teilweise modifiziert.
Die Quellen Nr. 2 und 3 als PDF-Dokumente.
25
Einführung in die Shader Programmierung unter OpenGL 2.0
Anlagen
C.2 Bedienungsanleitung: „Shader Demo“-Programm
Das Programm „OpenGL 2.0 Shader Demo“ ist aus der Kommandozeile aufzurufen.
Hierfür steht eine Auswahl an Aufrufparameter zur Verfügung. Einige müssen
verwendet werden, andere sind optional. Für eine Übersicht kann das Programm mit
dem Parameter „-help“ gestartet werden. Die definierten Argumente, sowie die mit
Funktion belegten Tasten im aktiven Grafikfenster, werden beschrieben. Dannach
werden Beispielaufrufe aufgeführt.
Kommandozeilenparameter (nötig):
-vs <Dateiname>
„Dateiname“ ist die zu verwendende Vertex-ShaderQuellcodedatei
-fs <Dateiname>
„Dateiname“ ist die zu verwendende Fragment-ShaderQuellcodedatei
Kommandozeilenparameter (optional):
-debug <1, 2, 3>
Legt die Menge der Konsolenausgaben des Programms
fest. Gültige Werte sind: 1 = normal; 2 = detail; 3 = alles;
0 = aus. Standard ist 0,bzw. ausgeschalten. Stufe 3 gibt
u. a. aktuelle Variablenwerte aus.
-fps
Aktiviert die Berechnung und Anzeige der „Frames per
Second“ (FPS). Neben der ermittelten Bildrate pro
Sekunde (‚fps’), werden auch die Gesamtsumme der
berechneten Bilder (‚frames’) und die Anzahl der FPSBerechnungen (‚calcs’) angezeigt.
-fullscr
Aktiviert den Vollbildmodus des Grafikfensters.
-help; -h
Zeigt die Aufrufvorschrift und die verfügbaren
Kommandozeilenparameter an.
-polygonmode <1, 2, 3>
Setzt den OpenGL-Rendering-Polygon-Modus. Zur
Auswahl stehen drei Modis:
1: „Full filled“: Alle Polygone werden vollständigausgefüllt dargestellt (standard).
2: „Wireframe“: Nur die Kanten werden als Drahtgittermodell gezeigt.
3: „Vertex“: Zeigt nur die Vertices an.
-win <Breite> <Höhe>
Legt die Grösse des Grafikfensters beim Programmstart fest. Es existiert ein zulässiger Bereich. Für
exakte Werte das Programm mit Parameter „-help“
aufrufen.
26
Einführung in die Shader Programmierung unter OpenGL 2.0
Anlagen
Alle hier nicht aufgeführten Argumente werden als Fehler deklariert und abgelehnt.
Ebenso wenn die Argumente mit nicht zulässigen Werten verwendet werden. Die
weiterführende Fehlerkontrolle, z. B. ob die Shader-Quellcodedateien tatsächlich am
angegebenen Ort geöffnet werden können, findet in später folgenden
Programmteilen statt.
Steuerungstasten im Grafikfenster:
Esc, q, Q
Diese Tasten beenden das Programm mit
vorhergehendem definierten Verlassen des Grafiksystems.
f, F
Wechselt den Zustand der FPS-Anzeige im
Grafikfenster und die damit verbundene Berechnung.
u, U
Wechselt zwischen Fenster- und Vollbildmodus.
1
Polygon-Modus 1: „Full filled“
2
Polygon-Modus 2: „Wireframe“
3
Polygon-Modus 3: „Vertex“
Beispielaufrufe:
shaddemo -vs shader\plppixel.vs -fs shader\plppixel.fs
shaddemo -vs shader\ivory.vs -fs shader\ivory.fs -fullscr -polygonmode 2
shaddemo -vs shader\toon.vs -fs shader\toon.fs -fps -debug 1
shaddemo -vs shader\ivory.vs -fs shader\ivory.fs -win 600 300 -debug 2 -fps -polygonmode 3
27
Einführung in die Shader Programmierung unter OpenGL 2.0
Anlagen
C.3 Programmstrukturdiagramm: „OpenGL 2.0 Shader Demo“ Programm
Dateimodule
Das Programm ist auf verschiedene Dateien aufgeteilt. Drei „Header“-Dateien und
zwei „C“-Standard-Quellcodedateien, die im folgenden näher beschrieben werder.
Wie in der Strukturübersicht dargestellt, werden alle „Header“-Dateien in jede
Standard-Quellcodedatei eingebunden.
sdtypdef.h
sdmacro.h
shaddemo.c
sdglobal.h
sdshader.c
Abb. C.3-1 – Dateimodulstruktur
Datei
Inhalt
sdtypdef.h
Alle Typendefinitionen, die im Programm verwendet
werden.
sdmacro.h
Alle Macro’s, die im Programm verwendet werden.
sdglobal.h
Die Datei stellt ein Interface für die beiden „*.c“-Dateien
da. Die globale Struktur-Variable „myProg“ ist dafür
hierher ausgegliedert worden. Sie wird in Zusammenhang mit den Debug-Ausgaben in allen Programmteilen
benötigt.
sdshader.c
Programmmodul, das die Shader-betreffenden
Funktionen beinhaltet. Modularisiert nach Zugehörigkeit.
shaddemo.c
Hauptprogrammmodul. Beinhaltet die „main“-Funktion,
alle definierten GLUT-„Callback“-Funktionen und
sonstige.
28
Einführung in die Shader Programmierung unter OpenGL 2.0
Anlagen
Programm-Ablauf-Plan (PAP)
Aufrufende Shell
Programm
initialisieren
Aufrufargumente
parsen
Ja
Fehler
Nein
GLut-System
initialisieren
Ja
Fehler
GLew-System
initialisieren
Nein
GL-System
initialisieren
Ja
Fehler
Shader-Programm
erstellen (laden,
übersetzen, binden)
Nein
System starten /
Funktionen aktivieren
Ja
Fehler
Nein
GLut-Hauptschleife
Endetaste
gedrückt
Taste
gedrückt
Nein
Ja
Ja
Nein
Funktion aktivieren /
deaktivieren
Aufrufende Shell
Fehlerbehandlung
System beenden
Abb. C.3-2 – Programm-Ablauf-Plan „Shader Demo“-Programm
29
Einführung in die Shader Programmierung unter OpenGL 2.0
Anlagen
C.4 Arbeitsumgebungen: „OpenGL 2.0 Shader Demo“-Programm
Das „OpenGL 2.0 Shader Demo“-Programm wurde auf verschiedenen Systemen
getestet. Die Resultate sind in nachfolgender Tabelle ersichtlich. Für die
Übersetzung und das Binden sind folgende Notationen beim Aufruf in der Konsole
benutzt worden:
Übersetzung (Windows/Unix)
<Übersetzer> -c *.c -I<’Header’-Dateien-Verzeichnis>
Binden (Windows)
<Übersetzer> *.o -o <Programmname>.exe -L<Bibliothek-Verzeichnis>
-lopengl32 -lglu32 -lglut32 -lglew32
Binden (Unix)
<Übersetzer> *.o -o <Programmname> -L<Bibliothek-Verzeichnis> -lGL -lGLU -lglut -lGLEW
Umgebung 1
Plattform: x86
Betriebssystem: Windows XP
Übersetzen (gcc 3.4.2 mingw): erfolgreich
Binden: erfolgreich (gcc 3.4.2 mingw): erfolgreich
Ausführen: erfolgreich
Umgebung 2
Plattform: x86
Betriebssystem: Linux (SuSe)
Übersetzen (cc 4.0.2): erfolgreich
Übersetzen (gcc 4.1.0): erfolgreich
Binden (cc 4.0.2): erfolgreich
Binden (gcc 4.1.0): erfolgreich
Ausführen: nicht erfolgreich (Speicherschutzverletzung, möglicherweise auf Grund
von inkompatibler Hardware)
Umgebung 3
Plattform: Sparc 64bit
Betriebssystem: Solaris 10
Übersetzen (cc): erfolgreich (zwei Warnungen in glu.h u. glew.h)
Übersetzen (gcc 4.1.0): erfolgreich
Binden (cc): erfolgreich
Binden (gcc 4.1.0): erfolgreich
Ausführen: erfolgreich (jedoch definierter Abbruch auf Grund von OpenGL 2.0Inkompatibilität)
30
Einführung in die Shader Programmierung unter OpenGL 2.0
Anlagen
C.5 Fehler-Codes: „OpenGL 2.0 Shader Demo“-Programm
In der nachstehend aufgeführten Tabelle sind alle möglichen Fehler mit Code,
Beschreibung und Rückgabewert an die aufrufende Shell, aufgelistet.
Fehlerkategorien:
Interne Fehler
IO-Fehler (Ein-/Ausgabefehler)
GL-Fehler (Grafik / Shader)
Parser-Fehler (Aufruffehler)
-1
-101
-201
-301
bis -99
bis -199
bis -299
bis -399
Code
Beschreibung
Rückgabewert
Interne Fehler
SHDE-001
SHDE-011
SHDE-021
SHDE-022
SHDE-023
SHDE-031
SHDE-032
Unbekannter Fehler
Variable für Dateiname hat keinen Wert (‚NULL’)
Unbekannter FPS-Modus
Unbekannter Anzeige-Modus
Unbekannter Polygon-Modus
Keine Shader-InfoLog-Nachricht vorhanden
Keine Shader-Programm-InfoLog-Nachricht vorhanden
-1
-11
-21
-22
-23
-31
-32
IO-Fehler(Ein-/Ausgabefehler)
SHDE-101
Datei kann nicht geöffnet werden
SHDE-102
Datei ist leer
-101
-102
GL-Fehler (Grafik-/Shader-Fehler)
SHDE-201
OpenGL 2.0 'extension wrangler' nicht verfügbar
SHDE-211
Vertex-Shader-Quellcode kann nicht übersetzt werden
SHDE-212
Fragment-Shader-Quellcode kann nicht übersetzt werden
SHDE-213
Shader-Programm kann nicht gebunden werden
-201
-211
-212
-213
Parser-Fehler
SHDE-301
SHDE-302
SHDE-303
SHDE-304
SHDE-305
SHDE-306
SHDE-307
SHDE-311
SHDE-312
SHDE-313
-301
-302
-303
-304
-305
-306
-307
-311
-312
-313
Unbekannter Parameter
Debug-Stufe wurde nicht angegeben
Debug-Stufe nicht im zulässigen Bereich
Fenstergrösse wurde nicht angegeben
Fenstergrösse nicht im zulässigen Bereich
Polygon-Modus wurde nicht angegeben
Polygon-Modus nicht im zulässigen Bereich
Shader-Quellcodedateien wurden nicht angegeben
Vertex-Shader-Quellcodedatei wurde nicht angegeben
Fragment-Shader-Quellcodedatei wurde nicht angegeben
31
Einführung in die Shader Programmierung unter OpenGL 2.0
Anlagen
C.6 Quellcode: „OpenGL 2.0 Shader Demo“-Programm
32
Einführung in die Shader Programmierung unter OpenGL 2.0
Anlagen
C.7 Quellcode: Basis-Programm
33
Einführung in die Shader Programmierung unter OpenGL 2.0
Anlagen
C.8 Folien: Präsentation
34