38
E E i i n n f f ü ü h h r r u u n n g g in die S S h h a a d d e e r r P P r r o o g g r r a a m m m m i i e e r r u u n n g g unter O O p p e e n n G G L L 2 2 . . 0 0

Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

  • Upload
    ledan

  • View
    215

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

EEiinnffüühhrruunngg iinn ddiiee

SShhaaddeerr PPrrooggrraammmmiieerruunngg uunntteerr

OOppeennGGLL 22..00

Page 2: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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

Page 3: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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 leicht-verstä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

Page 4: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

Einführung in die Shader Programmierung unter OpenGL 2.0 Inhaltsverzeichnis

Inhaltsverzeichnis 1. Einleitung 1 1.1 Projektbeschreibung 1 1.2 Zielsetzung 1 2. Theorie 2 2.1 Geschichtliche Entwicklung von OpenGL 2 2.2 Was sind Shader ? 3 2.3 Welche Möglichkeiten bieten Shader ? 3 2.4 Wo werden Shader in der OpenGL-Pipeline eingesetzt ? 5 2.5 Was ist GLSL ? 6 2.6 GLSL oder HLSL ? 7 2.7 Grundoperationen zur Verwendung von Shader 8 2.8 Vor- und Nachteile von Shader 10 3. Praxis 12 3.1 Aufbau von Shader 12 3.2 Variablentypen und Qualifiers 13 3.3 Kommunikation Anwendung zu Shader 15 3.4 Shader IDE's 16 3.5 Umgebungseinrichtung unter Windows mit DEV-C++ 5 IDE 17 3.6 Umgebungseinrichtung unter Solaris und Linux 18 3.7 Basis Programm in C 19 3.8 Beispiel: „Toon“-Shader 21 A Glossar 23 B Quellen 24 C Anlagen 25 C.1 Übersicht: Dateisystem Projektdatenträger 25 C.2 Bedienungsanleitung: „Shader Demo“-Programm 26 C.3 Programmstrukturdiagramm: „OpenGL 2.0 Shader Demo“ Programm 28 C.4 Arbeitsumgebungen: „OpenGL 2.0 Shader Demo“-Programm 30 C.5 Fehler-Codes: „OpenGL 2.0 Shader Demo“-Programm 31 C.6 Quellcode: „OpenGL 2.0 Shader Demo“-Programm 32 C.7 Quellcode: Basis-Programm 33 C.8 Folien: Präsentation 34

IV

Page 5: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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 Shader-Programme 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

Page 6: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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 3D-Computergrafiken 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 OpenGL-Standards 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

Page 7: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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 Hardware-Lö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 3D-Raum 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 Vertex- und 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

Page 8: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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 Vertex-Transformationen 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 „Bump-Mapping“ 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

Page 9: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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.

Abb. 2.4-1 – Ausschnitt der OpenGL-Pipeline (abstrakt, in Anlehnung an Quelle 1)

Vertices (1.0, 2.5, 3.4, 1.0)

Vertex-Connectivity (GL LINE, GL POLYGON, …)

Vertex-Transformation

Primitive Assembly / Rasterization

Fragments Pixel Positions

Fragment Texturing / Coloring

Raster Operations

Colored Fragments

Pixel Updates

Transformed Vertices

Vertex-Shader

Fragment-Shader

Sind die Raumpunkte transformiert, werden sie mit den „Vertex-Zusammengehö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

Page 10: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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 Shader-Programmen 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

Page 11: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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

Page 12: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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.

Abb. 2.7-1 – Notwendige Grundoperationen, 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

Schritt Operation OpenGL 2.0

8

Page 13: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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 Shader-Programms 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

Page 14: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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 Implementierungs-mö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 Shader-Programmierbarkeit ihrer Hardware gewährleisten, wenn sie einen OpenGL 2.0-kompatiblen 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 Shader-IDE'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 Shader-Entwicklungsumgebungen 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

Page 15: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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 Entwicklung

OpenGL: „Alpha-Blending“ im Fragment-Shader nur mit schlechter Performance

Realitätsnahe Effekte, wenn genügend Hardwareleistung

Direct3D: API ist nur unter Windows 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

Page 16: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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 Fragment-Shader 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

Page 17: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

Einführung in die Shader Programmierung unter OpenGL 2.0 Praxis

Die oben gezeigte Shaderstruktur stellt den grundlegenden Aufbau eines Shader-Programms 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-Shader-Programmen 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

Page 18: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

Einführung in die Shader Programmierung unter OpenGL 2.0 Praxis

varying Variablen mit diesem Schlüsselwort sind für die Kommunikation zwischen Vertex- und Fragment-Shader nötig. Die Deklaration muss in beiden Shader-Programmen vorgenommen werden. Der Zugriff ist je Shader-Typ unterschiedlich. Im Vertex-Shader 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 selbst-definierten Variablen sind ebenso wie bei „uniform“-Variablen auch „Build-In“-„attribute“-Variablen im Shader lesbar.

Abb. 3.2-1 – Schaubild „Qualifier“-Verfügbarkeit

Vertex-Shader

Fragment-Shader

Anwendung

„uniform“-Variable

„attribute“-Variable

„Build-In“-„attribute“-Variable

„Build-In“-„uniform“-Variable

„varying“-Variable

„Build-In“-„varying“-Variable

14

Page 19: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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 Shader-Programm 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.

Abb. 3.3-1 – Operationen zum Setzen von Shader-Variablen, OpenGL 2.0

9 Variable an Handler binden glGetUniformLocation

10 Variable setzen glUniform*

Schritt Operation OpenGL 2.0

glGetAttribLocation

glVertexAttrib*

15

Page 20: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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 Shader-Code 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

Page 21: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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-Update-Service 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

Page 22: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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 Shader-programmierbare 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

Page 23: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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

Page 24: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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 Shader-Paar Daten aus der Applikation, so muss die Verbindung wie in Kapitel 3.3 behandelt aufgebaut werden.

20

Page 25: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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

Page 26: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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

Page 27: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

Einführung in die Shader Programmierung unter OpenGL 2.0 Glossar

A Glossar Begriff Erklärung API Application Programming Interface, eine Software Schnittstelle. Bump-Mapping Ein Verfahren zum Vortäuschen von Tiefeneindruck auf texturierten Flächen. Direct3D Ein Modul des DirectX-API, das für die 3D- Grafikberechnung zuständig ist. Displacement-Mapping auch Vertex-Texturing, Im Gegensatz zum Bump-Mapping wird hier auch die Geometrie in Abhängigkeit zur Textur verändert. Dynamic Bump-Mapping Wie „Bump-Mapping“ jedoch mit verschieben der Höhentextur(en). Fragment In der Computer-Grafik ein „potentielles Pixel“. GLSL auch GLslang, „C“-ähnliche Hochsprache zur Shader-Programmierung unter OpenGL 2.0. Highmap Eine spezielle Textur die Höheninformationen für Bump-Mapping enthält. HLSL Steht für „High Level Shading Language“. Ist die Hochsprache für Direct3D-Shader. IDE „Integrated Development Environment“. Eine Oberfläche für die Programmentwicklung. IRIS GL Eine von der Firma Silicon Graphics Inc. entwickelte Grafik-API. Vorläufer des OpenGL. OpenGL Eine hardwarehersteller-unabhänge Programmierschnittstelle für Grafikanwendungen konstruiert als Zustandsautomat. Verfügbar unter vielen Betriebssystemumgebungen. OpenGL-Pipeline auch „OpenGL-Rendering-Pipeline“ genannt. Der Weg den eine mathematische Vektorgrafik im OpenGL- System durchläuft bis sie am Bildschirm ausgegeben wird. Shader Ein mathematischer Algorithmus zur Manipulation von Grafikberechnungen. Vertex Ein Raumpunkt mit drei Koordinaten und optional einem Tiefenwert.

23

Page 28: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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

Page 29: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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 Eine Auswahl an Shader-Paaren aus dem Internet. Auch teilweise modifiziert. quellen Die Quellen Nr. 2 und 3 als PDF-Dokumente.

25

Page 30: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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-Shader- Quellcodedatei -fs <Dateiname> „Dateiname“ ist die zu verwendende Fragment-Shader- Quellcodedatei 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 FPS- Berechnungen (‚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ändig- ausgefüllt dargestellt (standard). 2: „Wireframe“: Nur die Kanten werden als Drahtgitter- modell gezeigt. 3: „Vertex“: Zeigt nur die Vertices an. -win <Breite> <Höhe> Legt die Grösse des Grafikfensters beim Programm- start fest. Es existiert ein zulässiger Bereich. Für exakte Werte das Programm mit Parameter „-help“ aufrufen.

26

Page 31: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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 Grafik- systems. 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

Page 32: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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.

Abb. C.3-1 – Dateimodulstruktur

sdtypdef.h sdmacro.h sdglobal.h

shaddemo.c sdshader.c

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 Zusammen- hang 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

Page 33: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

Einführung in die Shader Programmierung unter OpenGL 2.0 Anlagen

Programm-Ablauf-Plan (PAP)

Ja

Nein

Fehler

Ja

Nein

Fehler

Ja

Nein

Fehler

Programm initialisieren

Aufrufargumente parsen

GLut-System initialisieren

GLew-System initialisieren

Shader-Programm erstellen (laden, übersetzen, binden)

GL-System initialisieren

System starten / Funktionen aktivieren

System beenden

Fehlerbehandlung

Aufrufende Shell

Ja

Nein

Taste gedrückt

GLut-Hauptschleife

Aufrufende Shell

Ja

Nein

Fehler

Ja

Nein

Endetaste gedrückt

Funktion aktivieren / deaktivieren

Abb. C.3-2 – Programm-Ablauf-Plan „Shader Demo“-Programm

29

Page 34: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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.0-Inkompatibilität)

30

Page 35: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

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 -1 bis -99 IO-Fehler (Ein-/Ausgabefehler) -101 bis -199 GL-Fehler (Grafik / Shader) -201 bis -299 Parser-Fehler (Aufruffehler) -301 bis -399 Code Beschreibung Rückgabewert Interne Fehler SHDE-001 Unbekannter Fehler -1 SHDE-011 Variable für Dateiname hat keinen Wert (‚NULL’) -11 SHDE-021 Unbekannter FPS-Modus -21 SHDE-022 Unbekannter Anzeige-Modus -22 SHDE-023 Unbekannter Polygon-Modus -23 SHDE-031 Keine Shader-InfoLog-Nachricht vorhanden -31 SHDE-032 Keine Shader-Programm-InfoLog-Nachricht vorhanden -32 IO-Fehler(Ein-/Ausgabefehler) SHDE-101 Datei kann nicht geöffnet werden -101 SHDE-102 Datei ist leer -102 GL-Fehler (Grafik-/Shader-Fehler) SHDE-201 OpenGL 2.0 'extension wrangler' nicht verfügbar -201 SHDE-211 Vertex-Shader-Quellcode kann nicht übersetzt werden -211 SHDE-212 Fragment-Shader-Quellcode kann nicht übersetzt werden -212 SHDE-213 Shader-Programm kann nicht gebunden werden -213 Parser-Fehler SHDE-301 Unbekannter Parameter -301 SHDE-302 Debug-Stufe wurde nicht angegeben -302 SHDE-303 Debug-Stufe nicht im zulässigen Bereich -303 SHDE-304 Fenstergrösse wurde nicht angegeben -304 SHDE-305 Fenstergrösse nicht im zulässigen Bereich -305 SHDE-306 Polygon-Modus wurde nicht angegeben -306 SHDE-307 Polygon-Modus nicht im zulässigen Bereich -307 SHDE-311 Shader-Quellcodedateien wurden nicht angegeben -311 SHDE-312 Vertex-Shader-Quellcodedatei wurde nicht angegeben -312 SHDE-313 Fragment-Shader-Quellcodedatei wurde nicht angegeben -313

31

Page 36: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

Einführung in die Shader Programmierung unter OpenGL 2.0 Anlagen

C.6 Quellcode: „OpenGL 2.0 Shader Demo“-Programm

32

Page 37: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

Einführung in die Shader Programmierung unter OpenGL 2.0 Anlagen

C.7 Quellcode: Basis-Programm

33

Page 38: Einführung - hs-fulda. · PDF filehat OpenGL im Bereich der 3D-Computerspiele viel Marktanteil verloren. Nicht zuletzt ist dies auf die frühere Einführung von programmierbaren Shader

Einführung in die Shader Programmierung unter OpenGL 2.0 Anlagen

C.8 Folien: Präsentation

34