Aus Linux-Magazin 10/2006

Ob Bühnenbild oder 3D-Modell, erst Anstrich und Licht sorgen für die perfekte Illusion

© photocase.com

Ein überzeugendes Bühnenbild sorgt für die passende Atmosphäre im Theater. Auch am Computer machen Anstrich und Beleuchtung die Illusion von 3D-Modellen perfekt. Selbst einfache Skripte zaubern dank OpenGL mit Hilfe von Bitmaps und Beleuchtung Überraschendes auf den Schirm.

Wie ein geometrisches 3D-Modell mit ein paar Farben auf den Schirm kommt, hat kürzlich ein Artikel [1] zu Tcl3D [2] beschrieben. Doch OpenGL kann bedeutend mehr. Um bei Flugzeugen oder Menschen alle Details wie Augen, Bekleidung oder Beschriftung nachzubilden, wären Millionen von Dreiecken notwendig. Viel einfacher ist es, auf eine grobe Form ansprechende Bitmaps wie ein Abziehbild zu kleben. Bei 3D-Modellen heißt dieses Verfahren Textur. Aktuelle Grafikkarten unterstützen es durch riesige Speicher für Texturen.

Fürs letzte Finish des virtuellen Bühnenbilds sorgt die Beleuchtung. Das Standardlicht aus OpenGL hat den abstoßenden Charme von Neonlicht – doch es gibt angenehmere Lichtquellen, deren Verhalten der Bühnenbauer bis ins Feinste beschreiben darf.

Die hier gezeigten Beispiele setzen auf denen im ersten Artikel auf [1], daher sind die Geometrien und Ansichten bereits definiert. Die gedruckten Listings enthalten den jeweils relevanten Ausschnitt; der komplette Code steht wie immer auf dem FTP-Server des Linux-Magazins [3]. Die Skripte sind wieder für Paul Obermeiers Tcl-Erweiterung Tcl3D [2] geschrieben. Die Beispiele lassen sich aber auch gut auf OpenGL unter C oder Java anwenden, da die Befehle überall den gleichen Namen tragen.

Abziehbild

3D-Modelle bestehen meist aus Dreiecken, die sind simpel und schnell zu erzeugen. Selbst einfache Modelle mit wenigen Dreiecken können realistisch aussehen, wenn sie eine passende Textur erhalten (Abbildungen 1a bis 1c). Damit OpenGL die Bitmaps passend auf die Geometrie montiert, benötigt es jedoch genaue Anweisungen, wohin welche Stelle des Abziehbildes gehört.

Abbildung 1a: Am Anfang steht ein Netz aus Dreiecken, die ein kugelförmiges Modell bilden.

Abbildung 1a: Am Anfang steht ein Netz aus Dreiecken, die ein kugelförmiges Modell bilden.

Abbildung 1b: Eine Hülle lässt Objekte wie eine Kugel erscheinen und verdeckt die unsichtbaren Kanten.

Abbildung 1b: Eine Hülle lässt Objekte wie eine Kugel erscheinen und verdeckt die unsichtbaren Kanten.

Abbildung 1c: Eine passende Textur gibt dem Oberflächennetz das Aussehen eines Steins.

Abbildung 1c: Eine passende Textur gibt dem Oberflächennetz das Aussehen eines Steins.

Dabei treffen zwei Welten aufeinander: das dreidimensionale X-Y-Z-Koordinatensystem des Dreiecks und das zweidimensionale S-T-Koordinatensystem der Textur. Der Befehl »glTexCoord2f« sagt OpenGL, welche Stelle der Textur (S, T) auf den nächsten definierten Geometriepunkt (X, Y, Z) kommt. Abbildung 2 zeigt das Verfahren mit drei Dreiecken und einer kleinen Bitmap.

Abbildung 2: Die OpenGL-Funktion »glTexCoord2f« bildet die Bitmap auf die Geometrie ab. Dabei legt der Programmierer fest, welcher Punkt des Bildes wo auf der Oberfläche landet.

Abbildung 2: Die OpenGL-Funktion »glTexCoord2f« bildet die Bitmap auf die Geometrie ab. Dabei legt der Programmierer fest, welcher Punkt des Bildes wo auf der Oberfläche landet.

Das abgedruckte Listing 1 zeigt die wesentlichen Ausschnitte des kompletten Quelltextes [3]. Das Hauptprogramm setzt die Funktion »tclCreateFunc« als »-createproc« ins OpenGL-Widget ein. Damit ruft die Library diese Funktion auf, um den Inhalt des Widget zu erzeugen. Die Funktion lädt die Texturen und erzeugt die Geometrie.

Listing 1: Texturen

01 # Wird ein Mal aufgerufen
02 proc tclCreateFunc {toglwin} {
03   # ein paar Einstellungen
04   glEnable GL_TEXTURE_2D
05   glEnable GL_DEPTH_TEST
06   glPolygonMode GL_FRONT_AND_BACK GL_FILL
07 
08   # Bild in Tcl laden
09   if [catch {image create photo -file "worked_stone_8180226.JPG"} phImg] {
10     error "Fehler beim Laden: $phImg"
11   }
12 
13   # OpenGL-Vektor mit Bitmap aus Tcl-Image erzeugen
14   set w [image width     $phImg]
15   set h [image height    $phImg]
16   set n [tcl3dPhotoChans $phImg]
17   set pTextureImage [tcl3dVector GLubyte [expr {$w * $h * $n}]]
18   tcl3dPhoto2Vector $phImg $pTextureImage
19   image delete $phImg ;# Bild aus Tcl löschen
20 
21   # Interpolation angeben
22   glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MIN_FILTER $::GL_LINEAR
23   glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MAG_FILTER $::GL_LINEAR
24 
25   # Textur aus OpenGL-Vektor mit Bitmap erzeugen
26   set ::g_textureID [tcl3dVector GLuint 1]
27   glGenTextures 1 $::g_textureID
28   glBindTexture GL_TEXTURE_2D [$::g_textureID get 0]
29 
30   if {$n == 3} {set type $::GL_RGB
31   } else {      set type $::GL_RGBA}
32   glTexImage2D GL_TEXTURE_2D 0 $n $w $h 0 $type GL_UNSIGNED_BYTE $pTextureImage
33 
34   # OpenGL-Vektor mit Bitmap löschen
35   $pTextureImage delete
36 
37   # Display-Liste erzeugen...
38   set ::g_sphereDList [glGenLists 1]
39   glNewList $::g_sphereDList GL_COMPILE
40   # ...und mit Geometrie und Textur füllen
41   renderSphere 0.0 0.0 0.0 1.5 $::aufloesung
42   glEndList
43 }
44 
45 # Kugel aus Dreiecken mit Textur erzeugen
46 proc renderSphere {r p} {
47   [...]
48   # Normalenvektor berechnen
49   set normalX [expr {cos($theta2) * cos($theta3)}]
50   set normalY [expr {sin($theta2)}]
51   set normalZ [expr {cos($theta2) * sin($theta3)}]
52   glNormal3f $normalX $normalY $normalZ
53 
54   # Einfache Zylinderprojektion der Textur
55   glTexCoord2f [expr {-1.0 * ($j/double($p))}] 
56                [expr { 2.0 * ($i+1)/double($p)}]
57 
58   # Position der Knotenpunkte berechnen
59   set posX [expr {$r * $normalX}]
60   set posY [expr {$r * $normalY}]
61   set posZ [expr {$r * $normalZ}]
62   glVertex3f $posX $posY $posZ
63   [...]
64 }

Bitmaps für Texturen liegen üblicherweise auf der Festplatte, insbesondere für realistische Darstellungen sind es meist Fotos der gewünschten Oberflächen. Solche Texturen finden sich zum Beispiel bei Mayang [4] oder speziell für Holz bei [5]. Als Textur eignet sich eine beliebige Bitmap, allerdings sollte die Kantenlänge eine Potenz von 2 sein, zum Beispiel 256 mal 512. Damit es an den Kanten zu keinen sichtbaren Stößen kommt, kann ein Gimp-Filter die Bilder in nahtlose Muster verwandeln (»Filter | Abbilden | Nahtlos machen«).

Auf Umwegen

Es gibt leider keine Funktion, die Bitmaps direkt von der Festplatte in OpenGL lädt. Daher sind drei Schritte nötig. Zuerst holt das Skript, wie bei Tk üblich, die Bitmaps mit »image create photo -file Dateiname«. Gewöhnlich laden Tk-Programme damit Bitmaps für Buttons. Die If-catch-Konstruktion in den Zeilen 9 bis 11 sorgt für eine Fehlermeldung, falls das Skript die Datei nicht laden kann.

Danach wandert die Bitmap aus Tk zu OpenGL. Hierfür hat Tcl3D bequemerweise eine Funktion, die Tk-Images in einen OpenGL-Vektor lädt. Zuerst erzeugt in Zeile 17 »tcl3dVector« einen Vektor, seine Größe bestimmt sich aus Länge und Breite des Image multipliziert mit der Anzahl der Kanäle. Normale Bilder haben je einen Kanal für Rot, Grün und Blau, einige noch einen weiteren für die Transparenz. Die Funktion »tcl3dPhoto2Vector« kopiert in Zeile 18 den Bildinhalt in den Vektor. Nun liegt das Bild doppelt vor, als OpenGL-Vektor und als Tk-Bild. Letzteres löscht Zeile 19, um Speicher zu sparen.

Klar ist, dass OpenGL die Bitmap in den meisten Fällen verzerrt, um sie auf die Geometrie zu legen. Dazu interpoliert es die Zwischenpunkte, der Befehl »glTexParameteri« sorgt in den Zeilen 22 und 23 für eine einfache lineare Interpolation. Als Nächstes erzeugt »glBindTexture« aus dem vorhandenen Vektor ein Texturobjekt (Zeile 28).

Textur mit Zusatz

Neben der darzustellenden Bitmap enthalten Texturobjekte weitere Informationen wie Höhe, Breite und Typ. In Zeile 32 verbindet »glTexImage2D« diese Daten mit dem Bild aus dem vorher erzeugten OpenGL-Vektor. Texturobjekte liegen üblicherweise im Speicher der Grafikkarte, folglich kann die Karte sie ohne Zugriff auf den Hauptspeicher verwenden und auf der Geometrie anbringen. Der Code in Zeile 35 löscht daher den OpenGL-Vektor, der das Bild enthält.

Anders als zum Beispiel Objekte in Java mit dessen Garbage Collection, verschwinden bei OpenGL einmal angelegte Variablen nicht von selbst. Es empfiehlt sich daher, für Zwischenschritte angelegte Variablen wie den vorliegenden Vektor explizit zu löschen. Andernfalls müllen sie den Haupt- oder (schlimmer) den Grafikkartenspeicher voll und bremsen die Anzeige.

Als Nächstes erzeugt das Programm die Geometrie und dekoriert sie mit der Textur (Zeilen 38 bis 42). Für eine saubere Fläche mit Textur benötigt OpenGL die Knotenpunkte der Dreiecke, den Normalenvektor an den Knotenpunkten und die Position in der Bitmap. Der Normalenvektor ist ein Vektor der Länge 1. Er steht senkrecht zur Oberfläche und definiert damit deren Lage. OpenGL braucht ihn, um die Beleuchtung und Spiegelung zu berechnen.

Im Beispiel baut die Funktion »renderSphere« ab Zeile 46 eine Kugel aus mehreren Dreiecksstreifen auf (Abbildung 1a), die Anzahl der Streifen bleibt dabei beliebig wählbar. Die vollständige Version findet sich auf dem FTP-Server [3], in Listing 1 ist nur der Ausschnitt für die Texturbehandlung zu sehen.

Der Winkel »theta2« entspricht dem Höhengrad, »theta3« dem Längengrad (Zeilen 49 bis 51). Zuerst berechnet das Skript den Normalenvektor. Bei einer Kugel ist das denkbar einfach. Danach definiert »glTexCoord2f« (Zeile 55), welcher Punkt aus der Textur auf welche Stelle der Geometrie kommt. Die Kugel erfordert eine Projektion, um die ebene Textur auf die gebogene Oberfläche zu legen. Das Beispiel setzt auf eine einfache Zylinderprojektion.

Steiniges Muster

Das Ergebnis ist in Abbildung 1c zu bewundern. Das rechteckige Gitter aus der Bitmap (Abbildung 1d) ist an den Polen zu Dreiecken verzerrt. Zum Schluss gibt »glVertex3f« die Koordinate eines Gitterpunkts auf der Kugel an, damit ist die Definition eines Punktes komplett.

Abbildung 1d: Die Oberflächenstruktur eines Steins ist unabhängig von dessen Form. Ein zweidimensionales Foto der Oberfläche genügt daher als Textur.

Abbildung 1d: Die Oberflächenstruktur eines Steins ist unabhängig von dessen Form. Ein zweidimensionales Foto der Oberfläche genügt daher als Textur.

Der weitere Quelltext definiert mit diesen Punkten Dreiecke und stellt damit die Kugeloberfläche zusammen. In Abbildung 1a sind als Demonstration nur die Kanten dargestellt. Die Textur (Abbildung 1d) gibt der sehr einfachen Geometrie ein recht realistisches Aussehen (Abbildung 1c).

Licht aus, Spot an

Bisher kam die Standardbeleuchtung zum Einsatz, mit der kalten Stimmung von Neonlicht. Wie alles in OpenGL lässt sich die Beleuchtung aber bis in die letzte Kleinigkeit definieren. Umgebungs- oder Spotlichter mit ihren Farben und Positionen sowie das Material einer Oberfläche bestimmen letztlich die Farbe eines Objekts. Beim Material ist sowohl die normale Körperfarbe definierbar als auch die Farbe der Reflexe.

Ein Beispiel ist in Abbildung 3 zu sehen, Ausschnitte aus dem Quelltext finden sich in Listing 2. Der Anwender wählt hier die Farbe der Kugel, der Beleuchtung und der Reflexe. Das Skript hat den gewohnten Aufbau mit den Prozeduren »tclCreateFunc« (Zeile 13), »tclReshapeFunc« (gekürzt) und »tclDisplayFunc« (Zeile 37). Die »tclCreateFunc« schaltet in Zeile 22 mit »glEnable« zuerst die benutzerdefinierte Beleuchtung ein und positioniert danach das erste Licht »GL_LIGHT0« (Zeilen 23 bis 25). Dann schaltet »glEnable« auch noch das Material ein (Zeilen 28 bis 29).

Abbildung 3: OpenGL-Programme können die Farbe der Beleuchtung und des Materials bis ins feinste Detail definieren. Ein kleines Skript gibt dem Benutzer Zugriff auf die wichtigsten Parameter.

Abbildung 3: OpenGL-Programme können die Farbe der Beleuchtung und des Materials bis ins feinste Detail definieren. Ein kleines Skript gibt dem Benutzer Zugriff auf die wichtigsten Parameter.

Listing 2: Licht und
Farbe

01 #!/usr/bin/wish
02 package require tcl3d
03 
04 # Startfarben
05 set ambient  #00d0d0
06 set specular #ffff00
07 set material #eeeeee
08 set emission #000000
09 set shinines 25.0
10 
11 # Position des Lichts setzen
12 # Ein Mal bei der Initialisierung aufgerufen
13 proc tclCreateFunc {toglwin} {
14   # Hintergrundfarbe
15   glClearColor 0.0 0.0 0.0 0.0
16 
17   #glPolygonMode GL_FRONT_AND_BACK GL_LINE
18   glShadeModel GL_SMOOTH
19   glEnable GL_DEPTH_TEST
20 
21   # Eigenes Licht definieren
22   glEnable GL_LIGHTING
23   glEnable GL_LIGHT0
24   set light_position {1.0 1.0 1.0 0.0}
25   glLightfv GL_LIGHT0 GL_POSITION $light_position
26 
27   # Materialspezifisches Licht anschalten
28   glColorMaterial GL_FRONT GL_DIFFUSE
29   glEnable GL_COLOR_MATERIAL
30 
31   # Farben initialisieren
32   farbe
33 }
34 
35 # Neue Kugel zeichnen.
36 # Wird für jedes Anzeigen aufgerufen.
37 proc tclDisplayFunc {toglwin} {
38   # Bisherige Geometrie löschen
39   glClear [expr {$::GL_COLOR_BUFFER_BIT | $::GL_DEPTH_BUFFER_BIT}]
40   # Kugel erzeugen
41   glutSolidSphere 1.0 32 32
42   glFlush
43 }
44 
45 # Materialfarbe setzen
46 # Bei jeder Änderung der Farben aufgerufen,
47 proc farbe {args} {
48   # Lichtfarbe
49   glLightfv GL_LIGHT0 GL_AMBIENT  [farbe2liste $::ambient]
50 
51   # Materialfarbe für Reflexe
52   glMaterialf GL_FRONT GL_SHININESS $::shinines
53   glMaterialfv GL_FRONT GL_SPECULAR [farbe2liste $::specular]
54 
55   # Farbe als Lichtquelle
56   glMaterialfv GL_FRONT GL_EMISSION [farbe2liste $::emission]
57 
58   # Oberflächenfarbe
59   glColor4fv [farbe2liste $::material]
60 
61   .fr.toglwin postredisplay
62 }
63 
64 # Wandel HEX-Farbe in RGB-Liste
65 proc farbe2liste {farbe} {
66   set retval {}
67   set liste [winfo rgb . $farbe]
68   foreach c $liste {
69     lappend retval [expr {$c / 65535.0}]
70   }
71   return $retval
72 }

Die Definition von Licht und Farbe geschieht in der Prozedur »farbe« (Zeile 47). Initial ruft über »tclCreateFunc« die Farbfunktion auf, künftig benutzt das GUI diese Funktion bei jeder Änderung der Farben. Die Prozedur »farbe« setzt die Farbe der Lichtquelle »GL_LIGHT0« durch das Kommando »glLightfv« (Zeile 49). Die Hilfsfunktion »farbe2liste« (ab Zeile 65) verwandelt die Farbe aus der Hex-Darstellung »#fe0000« in die RGB-Liste »1.0, 0.0, 0.0«.

Neben der Beleuchtung spielt auch die Farbe des Körpers eine Rolle, dafür sind Funktionen aus der »glMaterial«-Familie zuständig. Für die Beispielkugel stellen »GL_SHININESS« und »GL_SPECULAR« die Farbe und Intensität der Spitzenlichter ein (Zeilen 52 bis 53). Die Spitzenlichter sind jener Teil des Lichts, den der Körper direkt von einer Lichtquelle zum Betrachter reflektiert. Größe und Helligkeit hängen vor allem von der Oberfläche ab, eine polierte Billardkugel hat kleinere und hellere Spitzenlichter als eine raue Holzkugel.

Die meisten Körper strahlen nicht selbst, aber auch Glühbirnen und Neonröhren lassen sich mit OpenGL darstellen. Hierfür dient die Farbe »GL_EMISSION« (Zeile 65), sie gibt das vom Körper abgestrahlte Licht an. Zuletzt definiert »glColor4fv« (Zeile 59) eine Farbe, die wie die »glMaterial«-Kommandos für die nächste definierte Geometrie gilt.

Damit dieses Beispiel nicht zu kompliziert gerät, erzeugt »tclDisplayFunc« bei jedem Aufruf eine neue Kugel. Hierzu nutzt sie eine Funktion aus der Glut-Bibliothek (GL Utilities): »glutSolidSphere« (Zeile 41) erzeugt eine Kugel aus Dreiecken mit dem gewünschten Radius und der gewünschten Auflösung. Da dies immer auf die »farbe«-Prozedur folgt, gelten das dort definierte Material und die dort festgelegte Oberflächenfarbe. Der restliche Fensteraufbau ist normales Tk mit Buttons zum Ändern der Farbe.

Fremde Federn

Mit den bisher vorgestellten Methoden erzeugt ein Skript eigene Geometrien, bewegt und beleuchtet sie und umwickelt sie mit Texturen. Allerdings kann es ganz schön aufwändig sein, ein ganzes Auto, Haus oder Flugzeug mit puren OpenGL-Befehlen zu programmieren. Mit Werkzeugen wie Ayam [6] oder Blender [7] klappt das erheblich einfacher. Sie bieten ein CAD-System speziell für Oberflächenmodelle und unterstützen selbst das Anpassen und Zuschneiden der Texturen.

Abbildung 4: Dieses Doppeldecker-Modell stammt aus einer CAD-Software. Ein Tcl3D-Skript importiert die Objektdatei und verwendet sie in OpenGL.

Abbildung 4: Dieses Doppeldecker-Modell stammt aus einer CAD-Software. Ein Tcl3D-Skript importiert die Objektdatei und verwendet sie in OpenGL.

Listing 3: Wavefront-Modell
lesen

01 # Startwerte setzen und Displayliste erzeugen.
02 # Wird beim Erzeugen des Fensters aufgerufen.
03 proc tclCreateFunc {toglwin} {
04     # Schwarzer Hintergrund
05     glClearColor 0.1 0.7 1 0.5
06 
07     # Etwas Tuning
08     glClearDepth 1.0
09     glEnable GL_DEPTH_TEST
10     glShadeModel GL_SMOOTH
11     glDepthFunc GL_LEQUAL
12     glHint GL_PERSPECTIVE_CORRECTION_HINT GL_NICEST
13 
14     glEnable GL_DEPTH_TEST
15     glEnable GL_LIGHTING
16     glEnable GL_LIGHT0
17 
18     # Datei lesen
19     set filename "untitled.obj"
20     set ::objId [glmReadOBJ $fileName]
21     glmFacetNormals $::objId
22     glmVertexNormals $::objId 90.0
23 }
24 
25 # 3D-Modell anzeigen
26 proc tclDisplayFunc { toglwin } {
27     # Screen and Depth Buffer Löschen
28     glClear [expr $::GL_COLOR_BUFFER_BIT | $::GL_DEPTH_BUFFER_BIT]
29 
30     # Anfangsposition setzen
31     glLoadIdentity
32     glTranslatef $::Posx $::Posy $::Posz
33     glRotatef $::Rotx 1.0 0.0 0.0
34     glRotatef $::Roty 0.0 1.0 0.0
35     glRotatef $::Rotz 0.0 0.0 1.0
36 
37     glmDraw $::objId [expr $::GLM_SMOOTH | $::GLM_MATERIAL]
38     $toglwin swapbuffers
39 }

Dank Nate Robins GLM-Bibliothek können OpenGL-Skripte fertige Modelle importieren, wenn sie in einer Datei im Object-Wavefront-Format vorliegen (».obj«). Diese Bibliothek ist Teil des Tcl3D-Pakets, steht aber auch für andere Programmiersprachen zur Verfügung. Die legendäre Kitty Hawk der Gebrüder Wright dient als Beispiel in Abbildung 4. Das VRML-Modell aus [8] lässt sich mit Blender [7] in eine ».obj«-Datei verwandeln (steht in [3] zum Download). Listing 3 liest diese Datei und bringt das Modell auf den Schirm.

Beim Initialisieren lädt »tclCreateFunc« (ab Zeile 3) das Modell mit Hilfe der Funktion »glmReadObj« (Zeile 20). Die für OpenGL notwendigen Normalenvektoren berechnen »glmFacetNormals« und »glmVertexNormals« (Zeilen 21 bis 22). Das Modell ist damit zur Anzeige bereit, die »tclDisplayFunc« (ab Zeile 26) ruft es mit »glmDraw« auf (Zeile 37). Dabei verwendet sie die Flags »SMOOTH« und »MATERIAL« – fertig. Statt viele tausend Dreiecke einzeln zu definieren, hat das Skript in wenigen Schritten ein komplettes Modell geladen.

Tutorials gefragt

Dieser Artikel und sein erster Teil [1] beschreiben die ersten Schritte in OpenGL. Skriptsprachen erweisen sich dabei als besonders praktisch. Es gibt viel zu entdecken in der künstlichen 3D-Welt, auch im Bereich der Shader ([9], [10]). Dazu empfiehlt es sich, die umfangreichen Beispiele aus Tcl3D [2] auszuprobieren, sie zeigen viele interessante Aspekte. Die weitere Neugier befriedigt Google mit über zwei Millionen Treffern zu »+OpenGL +Tutorial«. (fjl)

Infos

[1] Carsten Zerbst, “Virtueller Bühnenbildner”: Linux-Magazin 07/06, S. 118

[2] Tcl3D: [http://www.tcl3d.org]

[3] Downloads zum Artikel: [ftp://ftp.linux-magazin.de/pub/listings/magazin/2006/10/3D-Skripting]

[4] Freie Texturen bei Mayang: [http://www.mayang.com/textures/]

[5] Woodworker\’s: [http://www.woodworking.org/WC/woodsampler.html]

[6] Ayam: [http://ayam.sourceforge.net]

[7] Blender: [http://www.blender.org]

[8] 3D-Modell der Kitty Hawk: [http://www.ocnus.com/models/Vehicles/]

[9] Stephan Siemen, “Glänzende Effekte – 3D-Grafiken verbessern durch Shader”: Linux-Magazin 02/04, S. 98

[10] Axel Jäger, “Schattenspiele – Shader mit der OpenGL Shading Language programmieren”: Linux-Magazin 11/05, S. 52

[11] Matthias Hopf, “Nicht nur fürs Auge – OpenGL-beschleunigter Desktop mit XGL und Compiz “: Linux-Magazin 05/06, S. 42

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 4 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben