<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
		<id>https://wiki.delphigl.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Phlegmatiker</id>
		<title>DGL Wiki - Benutzerbeiträge [de]</title>
		<link rel="self" type="application/atom+xml" href="https://wiki.delphigl.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Phlegmatiker"/>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php/Spezial:Beitr%C3%A4ge/Phlegmatiker"/>
		<updated>2026-04-19T20:07:49Z</updated>
		<subtitle>Benutzerbeiträge</subtitle>
		<generator>MediaWiki 1.27.4</generator>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_Matrix2&amp;diff=25436</id>
		<title>Tutorial Matrix2</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_Matrix2&amp;diff=25436"/>
				<updated>2011-12-18T10:08:40Z</updated>
		
		<summary type="html">&lt;p&gt;Phlegmatiker: /* GL_MODELVIEW */ www.seitseid.de :) Kommasetzung, Richtige Fälle...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Matrizen und Matrixmanipulationen= &lt;br /&gt;
&lt;br /&gt;
== Vorwort == &lt;br /&gt;
Willkommen bei meinem zweiten Tutorial.&amp;lt;br&amp;gt; &lt;br /&gt;
In letzter Zeit traten im Forum verstärkt fragen wie ''&amp;quot;Wie positioniere ich Objekte richtig?&amp;quot;'' und ''&amp;quot;Ich komm mit den Matrizen net klar. Könnt ihr helfen?&amp;quot;'' auf. Dies war Anlass für mich ein weiteres Tutorial zum Thema Matrizen zu schreiben. Ich werde versuchen viel mit Bildern und Gleichnissen zu arbeiten. Wer aber das ganze Angebot zum Thema &amp;quot;Matrix&amp;quot; nutzen will sollte ruhig auch einen Blick auf Phobeus Matrixtutorial ([[Tutorial_lektion3]]) und auf den Wikiartikel zum Thema [[Matrix]] werfen.&lt;br /&gt;
&lt;br /&gt;
== Matrizen in OpenGL == &lt;br /&gt;
&lt;br /&gt;
OpenGL kennt drei Matrizen. Wer OpenGL programmieren will sollte diese auch kennen: &lt;br /&gt;
* '''GL_MODELVIEW''' - Die Modelviewmatrix &lt;br /&gt;
: Die Modelviewmatrix sollte immer dann aktiviert sein, wenn ihr an die Grafikkarte [[Vertex]]daten senden wollt. Diese Matrix wird auf die Position der Vertices, die mit [[glVertex]] gesendet werden angewandt. Ebenso beeinflusst sie die Ausrichtung der [[Normalen]], die mit Hilfe von [[glNormal]] gesetzt werden. Kurz, alles was mit den Objekten eurer Welt zu tun hat, erfordert die Aktivierung dieser Matrix.&lt;br /&gt;
* '''GL_PROJECTION''' - Die Projektionsmatrix &lt;br /&gt;
: Diese Matrix wird selten gebraucht. Sie bestimmt, wie am Ende alles angezeigt wird. Sie bestimmt quasi die Eigenschaften der &amp;quot;Kamera&amp;quot;. &lt;br /&gt;
* '''GL_TEXTURE''' - Die Texturmatrix &lt;br /&gt;
: Diese Matrix wird auf die Texturkoordinaten angewandt, mit der Folge, dass sich die Texturen auf den Oberflächen bewegen.&lt;br /&gt;
&lt;br /&gt;
Diese Matrizen können per [[glMatrixMode]] aktiviert werden. Dabei kann immer nur eine Matrix aktiv sein. Wenn ihr z.B. {{INLINE_CODE|glMatrixMode(GL_MODELVIEW)}} aufgerufen habt, dann sagt man &amp;quot;Die Modelviewmatrix ist die '''''aktuelle Matrix'''''&amp;quot;. Alle Matrixmanipulationen (wir kommen gleich dazu was das ist) wirken sich ''nur'' auf die ''aktuelle Matrix'' aus.&lt;br /&gt;
&lt;br /&gt;
== Kurze Matrixtheorie == &lt;br /&gt;
''Was sind Matrizen?'' &amp;lt;br&amp;gt; &lt;br /&gt;
Matrizen sind aufgebaut wie Tabellen. Das tolle daran ist - man kann damit rechnen. &amp;lt;br&amp;gt; &lt;br /&gt;
''&amp;quot;Gaaaaanz toll! Jetzt rechnen die schon mit Tabellen...&amp;quot;''&amp;lt;br&amp;gt; &lt;br /&gt;
So schlimm ist das gar nicht. Denn das Rechnen übernimmt OpenGL für uns. Ihr müsst nur wissen, dass wann immer ihr einen Befehl wie [[glTranslate]], [[glRotate]] oder [[glScale]] verwendet, ihr eine Matrix mit der ''aktuellen Matrix'' multipliziert. &lt;br /&gt;
{{Hinweis|Wenn ihr wissen wollt, wie man Matrizen miteinander multipliziert, dann lest euch einmal den Artikel &amp;quot;[[Matrix]]&amp;quot; durch und auch das dort verlinkte PDF &amp;quot;CompGeoScript&amp;quot;.}} &lt;br /&gt;
&lt;br /&gt;
== Wie sehen Matrizen aus? == &lt;br /&gt;
In &amp;quot;echt&amp;quot; sehen Matrizen wie Tabellen voller Zahlen aus. &amp;lt;br&amp;gt; &lt;br /&gt;
Will man sich eine Matrix grafisch vorstellen, sollte man sich ein 3 dimensionales Gitter vorstellen. Dieses Gitter ist das Koordinatensystem der Matrix. Wenn ihr mit [[glTranslate]], [[glRotate]] oder [[glScale]] die Matrix manipuliert, dann verändert ihr die Position des Koordinatenursprungs (glTranslate), die Ausrichtung der Achsen (glRotate) oder die Maße (glScale). Im dritten Teil des Tutorials gehe ich auf die Auswirkungen dieser Befehle noch einmal genauer ein. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Die drei OpenGL Matrizen = &lt;br /&gt;
&lt;br /&gt;
== GL_PROJECTION == &lt;br /&gt;
Ich möchte zuerst einmal die Projektionsmatrix vorstellen. Diese Matrix wird meist nur am Rande erwähnt, macht aber einen verdammt wichtigen Job: Sie projeziert den Inhalt der Welt auf den Bildschirm. &lt;br /&gt;
&lt;br /&gt;
Wenn ihr der Projektionsmatrix per [[glLoadMatrix]] eine Matrix zuweist, die nur Nullen enthält, werdet ihr feststellen, dass ihr nichts seht. Ihr habt damit nämlich die Projektionsmatrix ausgeschaltet und da wir ja was sehen wollen, unterlassen wir das in Zukunft lieber ;). &lt;br /&gt;
&lt;br /&gt;
''Aber was kann man dann mit der Projektionsmatrix machen (,außer sie nicht auszuschalten ;-) )?'' &amp;lt;br&amp;gt; &lt;br /&gt;
Bei der Vorstellung der einzelnen Matrizen erwähnte ich bereits die &amp;quot;Kamera&amp;quot;. Um gleich mal eins festzustellen: Ein Objekt &amp;quot;Kamera&amp;quot; existiert nicht. Das einzige, was man von der &amp;quot;Kamera&amp;quot; mitbekommt, ist die Ausgabe. Und wie wir gerade gelernt haben ist welcher Teil für die Ausgabe zuständig? Richtig! Die Projektionsmatrix. Sie ist unsere &amp;quot;Kamera&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Kommt jetzt aber bitte nicht auf die Idee, eure Projektionsmatrix per '''glTranslate''' und '''glRotate''' irgendwohin zu bewegen... Das ist nämlich gar nicht die Aufgabe der Projektionsmatrix. Ihre Aufgabe ist &amp;quot;das Abbild für die Ausgabe zu manipulieren&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Im Ausgangszustand ([[glLoadIdentity]] wurde für die Projektionsmatrix aufgerufen), gibt die Projektionsmatrix das Bild der Welt unverändert aus. Wenn man '''glTranslate''' auf die Projektionsmatrix anwendet, dann verschiebt man nicht die Welt, sondern sagt der  Projektionsmatrix, dass sie das gesehene Bild verschieben soll. &lt;br /&gt;
&lt;br /&gt;
Befehle wie [[gluPerspective]] und [[glOrtho]] sind typische Befehle zum einstellen der Projektionsmatrix. Diese Befehle bestimmen nämlich in welcher Form die Ausgabe gemacht wird. Entweder perspektivisch verzerrt (gluPerspective) oder durch Parallelprojektion (glOrtho).&lt;br /&gt;
&lt;br /&gt;
Wenn man die Projektionsmatrix manipuliert, ist das vergleichbar mit dem Austauschen des Objektivs bei einer Kamera. Man könnt sogar über die Projektionsmatrix einen &amp;quot;Fischauge&amp;quot; Effekt erzeugen... (Aber fragt mich bitte nicht, wie die Matrix dazu aussieht... ;-) Falls ihrs wisst, einfach im Forum posten. Ich wäre interessiert.)&lt;br /&gt;
&lt;br /&gt;
== GL_MODELVIEW == &lt;br /&gt;
Wie bereits erwähnt ist die Modelviewmatrix die wichtigste Matrix in der OpenGL Welt, denn sie wirkt sich auf Ausrichtung und Position aller Primitive und damit Objekte in der OpenGL Welt aus. Ohne Daten in der Modelviewmatrix, kann die Projektionsmatrix auch nichts ausgeben. &lt;br /&gt;
&lt;br /&gt;
Wenn ihr [[Vertex]]daten  an die Grafikkarte übermittelt solltet ihr die Modelviewmatrix aktiviert haben. Positionsangaben wie z.B. {{INLINE_CODE|glVertex3f(1,0,1);}} beziehen sich auf das aktuelle Koordinatensystem. Das Koordinatensystem ist quasi der Teil der Matrix mit dem ihr arbeitet, und den ihr euch vorstellen könnt (/müßt.).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie ihr bereits wisst kann man mit den Befehlen [[glTranslate]], [[glRotate]] und [[glScale]] das Koordinatensystem manipulieren. Dadurch seid ihr in der Lage beim &amp;quot;Bauen&amp;quot; von Objekten mit &amp;quot;lokalen Koordinaten&amp;quot; zu arbeiten. &lt;br /&gt;
&lt;br /&gt;
=== lokale und globale Koordinaten === &lt;br /&gt;
''Worin unterscheiden sich lokale und globale Koordinaten?'' &amp;lt;br&amp;gt; &lt;br /&gt;
Um diese Frage zu klären bedarf es eines kleinen Beispiels: &lt;br /&gt;
&lt;br /&gt;
Stellt euch vor, ihr wollt zwei Würfel zeichnen. Der eine soll um den Punkt (3,4,5)  mit einer Kantenlänge von 1 erstellt werden, der andere soll um den Punkt (1,2,3) mit Kantenlänge 2 und dazu 30° um die Y-Achse gedreht werden. &lt;br /&gt;
&lt;br /&gt;
Wenn man mit '''globalen''' Koordinaten arbeitet lässt man die Matrix so wie sie ist (verzichtet also auf die 3 genannten Befehle) und schreibt die Koordinaten der Eckpunkte per Hand hin: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;glBegin(GL_QUADS); &lt;br /&gt;
  //Vorderseite erster Würfel &lt;br /&gt;
  glVertex3f(2,5,6); &lt;br /&gt;
  glVertex3f(2,3,6); &lt;br /&gt;
  glVertex3f(4,3,6); &lt;br /&gt;
  glVertex3f(4,5,6); &lt;br /&gt;
  //Nächste Seite &lt;br /&gt;
  [...] &lt;br /&gt;
&lt;br /&gt;
  //Vorderseite zweiter Würfel &lt;br /&gt;
  glVertex3f(0,3,4); &lt;br /&gt;
  glVertex3f(0,1,4); &lt;br /&gt;
  glVertex3f(2,1,4); &lt;br /&gt;
  glVertex3f(2,3,4); &lt;br /&gt;
  [...] &lt;br /&gt;
&lt;br /&gt;
glEnd; &lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Bei '''lokalen''' Koordinaten bewegt man zuerst den Koordinatenursprung an die Stelle an die der Würfel entstehen soll, richtet dann wenn nötig die Achsen entsprechend aus, und kann dann '''lokale''' Koordinaten übergeben. Lokal bedeutet hier relativ zum aktuellen Koordinatensystem. &lt;br /&gt;
&lt;br /&gt;
''Aber was soll das für einen Vorteil haben?'' &amp;lt;br&amp;gt; &lt;br /&gt;
Dem einen oder anderen ist vielleicht aufgefallen, dass wir zweimal das selbe Objekt zeichnen sollen. Der einzige Unterschied besteht in der Position, Ausrichtung und Größe/Skalierung. Um Arbeit zu sparen, erstellt man deshalb ein Unterprogramm welches einen Einheitswürfel (Kantenlänge 1) rendert und ruft vor dem Zeichnen einfach die passende Kombination aus glTranslate, glRotate und glScale auf: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;procedure ZeichneWuerfel; &lt;br /&gt;
begin &lt;br /&gt;
  glBegin(GL_QUADS); &lt;br /&gt;
    glVertex3f(-0.5, 0.5, 0.5); &lt;br /&gt;
    glVertex3f(-0.5,-0.5, 0.5); &lt;br /&gt;
    glVertex3f( 0.5,-0.5, 0.5); &lt;br /&gt;
    glVertex3f( 0.5, 0.5, 0.5); &lt;br /&gt;
    [...] &lt;br /&gt;
  glEnd; &lt;br /&gt;
end; &lt;br /&gt;
&lt;br /&gt;
begin &lt;br /&gt;
  glPushMatrix; &lt;br /&gt;
    glTranslatef(3,4,5); &lt;br /&gt;
    ZeichneWuerfel; &lt;br /&gt;
  glPopMatrix; &lt;br /&gt;
  glPushMatrix; &lt;br /&gt;
    glTranslatef(1,2,3); &lt;br /&gt;
    glRotatef(30,0,1,0); &lt;br /&gt;
    glScalef(2,2,2); &lt;br /&gt;
    ZeichneWuerfel; &lt;br /&gt;
  glPopMatrix; &lt;br /&gt;
end; &lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Wie ihr seht, haben lokale Koordinaten den Vorteil, dass man wiederverwendbaren Code schreiben kann. Bei globalen Koordinaten muss für jedes Objekt eigener Code geschrieben werden (und wenn sich das Objekt bewegt dann wieder...).&lt;br /&gt;
&lt;br /&gt;
Dreimal dürft ihr raten, welche Methode häufiger verwendet wird. ;-) &lt;br /&gt;
{{Hinweis|Modeller wie 3D Studio Max benutzen globale Koordinaten beim exportieren der Modelle. Dies hat den Vorteil, dass beim importieren einer ganzen 3DS Szene, die Objekte gleich an der richtigen Position stehen, und nicht erst ausgerichtet werden müssen.}}&lt;br /&gt;
&lt;br /&gt;
== GL_TEXTURE == &lt;br /&gt;
Dieser Matrix sollte endlich mehr Aufmerksamkeit geschenkt werden. Sie kann nämlich mit den Texturen in der Szene einiges anfangen... &lt;br /&gt;
&lt;br /&gt;
Aber der Reihe nach: &lt;br /&gt;
&lt;br /&gt;
Wie ihr vielleicht schon im [[Tutorial_lektion4|Einsteigertutorial 4 - Texturen]] gelesen habt, sind Texturkoordinaten immer so, dass {{INLINE_CODE|[[glTexCoord2f]](0,0)}} die obere linke Ecke und {{INLINE_CODE|glTexCoord2f(1,1)}} die untere Rechte Ecke der Textur betrifft. Wie die Textur außerhalb dieses Bereichs aussieht bestimmt ihr mittels [[glTexParameter]] und dem Parametern '''GL_TEXTURE_WRAP_S''' und '''GL_TEXTURE_WRAP_T'''. &lt;br /&gt;
&lt;br /&gt;
Nun stellt euch einmal vor, ihr habt 2 Quads die beide die selbe Textur bekommen sollen. Einziger Unterschied ist, dass bei dem einen Quad der Inhalt der Textur um 20° in Uhrzeigerrichtung gedreht ist. Blöd, oder? Das heißt ja jetzt, dass ihr in eurem Zeichenprogramm eine weitere Textur erstellen müßt, um das zweite Quad zu texturieren oder die Texturkoordinaten per Hand ändern müsst. &amp;lt;br&amp;gt; &lt;br /&gt;
'''STOP!''' Ihr hab es sicherlich schon mitbekommen: Dieses Szenario kann leicht mit der Texturmatrix gelößt werden. Und zwar so... &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;procedure drawTexturedQuad; &lt;br /&gt;
begin &lt;br /&gt;
  glBegin(GL_QUADS); &lt;br /&gt;
    glTexCoord(0,0); glVertex3f(-1, 1,0); &lt;br /&gt;
    glTexCoord(0,1); glVertex3f(-1,-1,0); &lt;br /&gt;
    glTexCoord(1,1); glVertex3f( 1,-1,0); &lt;br /&gt;
    glTexCoord(1,0); glVertex3f( 1, 1,0); &lt;br /&gt;
  glEnd; &lt;br /&gt;
end; &lt;br /&gt;
&lt;br /&gt;
begin &lt;br /&gt;
  glMatrixMode(GL_MODELVIEW); &lt;br /&gt;
  glBindTexture(GL_TEXTURE_2D, texID); &lt;br /&gt;
  glTranslatef(-2,0,0); &lt;br /&gt;
  drawTexturedQuad; &lt;br /&gt;
&lt;br /&gt;
  glMatrixMode(GL_TEXTURE); &lt;br /&gt;
  glRotatef(20,0,0,1); &lt;br /&gt;
&lt;br /&gt;
  glMatrixMode(GL_MODELVIEW); &lt;br /&gt;
  glTranslatef(4,0,0); &lt;br /&gt;
  drawTexturedQuad; &lt;br /&gt;
end;&amp;lt;/source&amp;gt; &lt;br /&gt;
''Was ist hier geschehn? ''&amp;lt;br&amp;gt;&lt;br /&gt;
Durch die vorherige Aktivierung der Texturmatrix wirkt sich das nachfolgende glRotate nicht auf die Modelle der Szene sondern auf die Texturkoordinaten aus. Auf gut deutsch: OpenGL dreht vor dem rendern des zweiten Quads die Textur um 20°. &lt;br /&gt;
&lt;br /&gt;
Wenn ihr beim rotieren der Texturmatrix, bei jedem Renderdurchlauf den Winkel um ein Stück erhöht passiert was?... Richtig! Eure Textur dreht sich auf eurem Quad... Das is dann quasi eure erste Animation... Und das ohne ein Objekt zu bewegen... Cool, oder?&lt;br /&gt;
&lt;br /&gt;
= Auswirkungen von Matrixmanipulationen - oder &amp;quot;Wie positioniere ich meine Objekte richtig?&amp;quot;= &lt;br /&gt;
In diesem Teil des Tutorials möchte ich euch zeigen wie die 3 Befehle '''glTranslate, glRotate''' und '''glScale''' eure aktuelle Matrix verändern. Ich bleibe hierbei im 2 dimensionalen Raum, da sonst die Skizzen zu unübersichtlich werden. (Die Befehle sind dabei natürlich die selben wie für 3D Manipulationen. Ich ignoriere nur einfach immer die Y-Angaben.) &lt;br /&gt;
&lt;br /&gt;
Zuersteinmal zum warm werden: &amp;lt;br&amp;gt; &lt;br /&gt;
[[Bild:Tutorial Matrix2 Ausgangsbild.png|framed|center|So stelle ich mir eine 2D-Matrix vor.]] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==glTranslate== &lt;br /&gt;
{{INLINE_CODE|[[glTranslate]](a,b,c)}} verschiebt den Koordinatenursprung des aktuellen Koordinatensystems um ''a'' Einheiten in die Richtung der X-Achse, um ''b'' Einheiten in die Richtung der Y-Achse und um ''c'' Einheiten in die Richtung der Z-Achse. &lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutorial Matrix2 Translate.png|framed|center|Das passiert bei einer Translation um 3.5 Einheiten in X und -3 Einheiten in Z-Richtung.]] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==glRotate== &lt;br /&gt;
{{INLINE_CODE|[[glRotate]](w,x,y,z)}} rotiert das Koordinatensystem um ''w'' Grad um die Rotationsachse welche durch (0,0,0) und (''x,y,z'') verläuft. '''glRotate richtet also die Achsen neu aus.''' (Die Richtung der Achsen ist z.B. wichtig für glTranslate) &lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutorial Matrix2 Rotate.png|framed|center|Das passiert bei einer Rotation um 45° mit der Y-Achse als Rotationsachse.]]&lt;br /&gt;
&lt;br /&gt;
==glScale== &lt;br /&gt;
{{INLINE_CODE|[[glScale]](x,y,z)}} skaliert die Maße der Koordinatenachsen (Bestimmt also wie lange &amp;quot;eine Einheit&amp;quot; wirklich ist). Wenn ''x,y'' oder ''z'' größer als 1 ist, werden die Maßeinheiten der entsprechenden Achse gestreckt, wenn die Werte kleiner 1 sind gestaucht. (Wenn die Werte gleich 0 sind verschwindet die Szene auf nimmer wieder sehn(, da hilft dann nur noch glLoadIdentity um die Matrix wieder nutzbar zu machen), sind die Werte gleich 1 verändert sich nichts.) &lt;br /&gt;
&lt;br /&gt;
''x,y'' und ''z'' muss man sich als Prozentangaben vorstellen. Will man die Szene in X-Richtung um das doppelte (also 200%) vergrößern/strecken muss ''x'' gleich 2 sein. Will man die Y-Richtung auf ein Zehntel (also 10%) verkürzen/stauchen muss ''y'' gleich 0.1 sein. &lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutorial Matrix2 Scale.png|framed|center|Das passiert bei einer Skalierung. Wie ihr seht, sind die Seiten unterschiedlich skaliert worden (X-Achse: 80%, Z-Achse: 60%).]] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Kombination - Translate vor Rotate== &lt;br /&gt;
Wird Translate vor Rotate aufgerufen, bewegt sich der Koordinatenursprung zuerst an den Zielpunkt (über glTranslate angegeben). Anschließend werden die Achsen neu ausgerichtet (durch glRotate). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|Folgender Code wird demonstriert: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt; &lt;br /&gt;
  glTranslatef(3.5,0,-3); &lt;br /&gt;
  glRotatef(45, 0, 1, 0); &lt;br /&gt;
  ZeichneKoordinatensystem; &lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Ausgangsbild.png|framed|center|Bevor glTranslate aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Translate.png|framed|center|Nachdem glTranslate aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 TranslateRot.png|framed|center|Nachdem glRotate aufgerufen wurde. Man sieht, dass die jeweils vorhergehende Veränderung bestehend bleibt, und die Basis für die nachfolgende Änderung bildet.]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wird der Winkel von glRotate bei jedem Renderdurchlauf erhöht, dreht sich ein anschließend gezeichnetes Objekt um die durch glTranslate angegeben Position. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Kombination - Rotate vor Translate== &lt;br /&gt;
Wird Rotate vor Translate aufgerufen, werden zuerst die Achsen neu ausgerichtet und dann der Koordinatenursprung bezüglich dieser neuen Achsen verschoben. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|Folgender Code wird demonstriert: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt; &lt;br /&gt;
  glRotatef(45, 0, 1, 0); &lt;br /&gt;
  glTranslatef(3.5,0,-3);   &lt;br /&gt;
  ZeichneKoordinatensystem; &lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Ausgangsbild.png|framed|center|Bevor glRotate aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Rotate.png|framed|center|Nachdem glRotate aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 RotateTrans.png|framed|center|Nachdem glTranslate aufgerufen wurde. Man sieht, dass die vorhergehende Rotation die Verschieberichtung beeinflusst.]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Wird der Winkel von glRotate bei jedem Renderdurchlauf erhöht, bewegt sich ein nach glTranslate gezeichnetes Objekt auf einer Kreisbahn um den Koordinatenursprung wie er beim Aufruf von glRotate aktuell war. Der Radius der Kreisbahn wird durch glTranslate bestimmt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wenn man die beiden Ergebnisse direkt vergleicht sieht man, dass die Reihenfolge von Bedeutung für das Ergebniss ist. Das die Unterschiede so &amp;quot;klein&amp;quot; ausfallen liegt nur daran, dass bei rotate nicht mit größeren Winkeln rotiert wurde. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|width=&amp;quot;50%&amp;quot; | [[Bild:Tutorial Matrix2 RotateTrans.png|framed|center|Erst Rotiert]] &lt;br /&gt;
|- &lt;br /&gt;
|width=&amp;quot;50%&amp;quot; | [[Bild:Tutorial Matrix2 TranslateRot.png|framed|center|Erst Verschoben]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kombination - Scale vor Rotate== &lt;br /&gt;
Die Rotation wird nur von der Richung, nicht aber der Länge der Achsen beeinflusst. Der Winkel um den gedreht wird, bleibt von der Skalierung unberührt (45° bleiben 45°. Die Achsen zeigen anschließend jeweils in die gleiche Richtung) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|Folgender Code wird demonstriert: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt; &lt;br /&gt;
  glScalef(0.8, 1, 0.6); &lt;br /&gt;
  glRotatef(45, 0, 1, 0); &lt;br /&gt;
  ZeichneKoordinatensystem; &lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Ausgangsbild.png|framed|center|Bevor glScale aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Scale.png|framed|center|Nachdem glScale aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 ScaleRot.png|framed|center|Nachdem glRotate aufgerufen wurde. Man sieht, dass die Skalierung den Winkel nicht beeinflusst. Das Koordinatensystem wurde korrekt um 45° gedreht.]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Der direkte Vergleich zeigt, dass die Skalierung keinen Effekt auf den Winkel hatte. Beide Koordinatensysteme sind gleich ausgerichtet: &lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|width=&amp;quot;50%&amp;quot; | [[Bild:Tutorial Matrix2 Rotate.png|framed|center|Unskaliert]] &lt;br /&gt;
|- &lt;br /&gt;
|width=&amp;quot;50%&amp;quot; | [[Bild:Tutorial Matrix2 ScaleRot.png|framed|center|Skaliert]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Kombination - Scale vor Translate== &lt;br /&gt;
Die Verschiebung ist Abhängig von der Ausrichtung der Achsen (glRotate) und der Maße der Achsen (glScale). Aus diesem Grunde beeinflusst glScale die nachfolgenden Translationen. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|Folgender Code wird demonstriert: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt; &lt;br /&gt;
  glScalef(0.8, 1, 0.6); &lt;br /&gt;
  glTranslatef(3.5,0,-3); &lt;br /&gt;
  ZeichneKoordinatensystem; &lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Ausgangsbild.png|framed|center|Bevor glScale aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Scale.png|framed|center|Nachdem glScale aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 ScaleTrans.png|framed|center|Nachdem glTranslate aufgerufen wurde.]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Der direkte Vergleich zeigt, dass sich die Skalierung auf die Verschiebung auswirkt. Denn obwohl der Verschiebung in die gleiche Richtung und um den selben Wert erfolgt, sind die Resultate nicht identisch. Dies liegt daran, dass glScale die Maße verändert hat. Die Verschiebung in X-Richtung erreicht dadurch nur 80% und in Z-Richtung sogar nur 60% der unskalierten Transformation: &lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|width=&amp;quot;50%&amp;quot; | [[Bild:Tutorial Matrix2 Translate.png|framed|center|Unskaliert]] &lt;br /&gt;
|- &lt;br /&gt;
|width=&amp;quot;50%&amp;quot; | [[Bild:Tutorial Matrix2 ScaleTrans.png|framed|center|Skaliert]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Nachwort= &lt;br /&gt;
7 Stunden sind vorbei und das Tutorial ist auf eine ordentliche Länge angewachsen. Ich hoffe ich konnte euch die OpenGL Matrizen etwas näher bringen. &lt;br /&gt;
&lt;br /&gt;
Wer jetzt denkt ''&amp;quot;Bilder sind mir zu statisch!&amp;quot;'', dem möchte ich noch diese Programme ans Herz legen: &lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|{{Prettytable}}&lt;br /&gt;
!Name&lt;br /&gt;
!Hersteller&lt;br /&gt;
!Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.delphigl.com/forum/viewtopic.php?p=37378#37378 '''Matrix2 - Skizzenrenderer''']&lt;br /&gt;
|Flash&lt;br /&gt;
|Dieses Programm habe ich geschrieben um die Skizzen für dieses Tutorial zu erstellen. Es wurde so modifiziert, dass man beliebige Kombinationen von glTranslate, glRotate und glScale anzeigen kann. &lt;br /&gt;
|-&lt;br /&gt;
|[http://www.phobeus.de/hosting/shared/pixelpracht/main.php?s=opengl&amp;amp;t=1&amp;amp;p=2 '''Matrix Control''']&lt;br /&gt;
|Lithander&lt;br /&gt;
|Das Programm erlaubt euch zu beobachten, wie die Matrizen sich bei den einzelnen Befehlen verändern und wie die Ausgabe aussieht. Besonderheit an diesem Programm ist, dass ihr die Matrizen auch per Hand manipulieren könnt.&lt;br /&gt;
|}&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sollten immer noch Unklarheiten bestehen bleibt das Forum natürlich auch weiterhin die Anlaufstelle Nummer1. Dies betrifft auch euer Feedback zum Tutorial. &lt;br /&gt;
&lt;br /&gt;
MfG &lt;br /&gt;
: Flash ('''Kevin Fleischer''') &lt;br /&gt;
&lt;br /&gt;
{{TUTORIAL_NAVIGATION|[[Tutorial_2D]]|-}} &lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Tutorial|Matrix2]]&lt;/div&gt;</summary>
		<author><name>Phlegmatiker</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_Matrix2&amp;diff=25435</id>
		<title>Tutorial Matrix2</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_Matrix2&amp;diff=25435"/>
				<updated>2011-12-18T10:02:49Z</updated>
		
		<summary type="html">&lt;p&gt;Phlegmatiker: /* GL_PROJECTION */ einzigste -&amp;gt; einzige, wißt -&amp;gt; wisst, Kommasetzung&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Matrizen und Matrixmanipulationen= &lt;br /&gt;
&lt;br /&gt;
== Vorwort == &lt;br /&gt;
Willkommen bei meinem zweiten Tutorial.&amp;lt;br&amp;gt; &lt;br /&gt;
In letzter Zeit traten im Forum verstärkt fragen wie ''&amp;quot;Wie positioniere ich Objekte richtig?&amp;quot;'' und ''&amp;quot;Ich komm mit den Matrizen net klar. Könnt ihr helfen?&amp;quot;'' auf. Dies war Anlass für mich ein weiteres Tutorial zum Thema Matrizen zu schreiben. Ich werde versuchen viel mit Bildern und Gleichnissen zu arbeiten. Wer aber das ganze Angebot zum Thema &amp;quot;Matrix&amp;quot; nutzen will sollte ruhig auch einen Blick auf Phobeus Matrixtutorial ([[Tutorial_lektion3]]) und auf den Wikiartikel zum Thema [[Matrix]] werfen.&lt;br /&gt;
&lt;br /&gt;
== Matrizen in OpenGL == &lt;br /&gt;
&lt;br /&gt;
OpenGL kennt drei Matrizen. Wer OpenGL programmieren will sollte diese auch kennen: &lt;br /&gt;
* '''GL_MODELVIEW''' - Die Modelviewmatrix &lt;br /&gt;
: Die Modelviewmatrix sollte immer dann aktiviert sein, wenn ihr an die Grafikkarte [[Vertex]]daten senden wollt. Diese Matrix wird auf die Position der Vertices, die mit [[glVertex]] gesendet werden angewandt. Ebenso beeinflusst sie die Ausrichtung der [[Normalen]], die mit Hilfe von [[glNormal]] gesetzt werden. Kurz, alles was mit den Objekten eurer Welt zu tun hat, erfordert die Aktivierung dieser Matrix.&lt;br /&gt;
* '''GL_PROJECTION''' - Die Projektionsmatrix &lt;br /&gt;
: Diese Matrix wird selten gebraucht. Sie bestimmt, wie am Ende alles angezeigt wird. Sie bestimmt quasi die Eigenschaften der &amp;quot;Kamera&amp;quot;. &lt;br /&gt;
* '''GL_TEXTURE''' - Die Texturmatrix &lt;br /&gt;
: Diese Matrix wird auf die Texturkoordinaten angewandt, mit der Folge, dass sich die Texturen auf den Oberflächen bewegen.&lt;br /&gt;
&lt;br /&gt;
Diese Matrizen können per [[glMatrixMode]] aktiviert werden. Dabei kann immer nur eine Matrix aktiv sein. Wenn ihr z.B. {{INLINE_CODE|glMatrixMode(GL_MODELVIEW)}} aufgerufen habt, dann sagt man &amp;quot;Die Modelviewmatrix ist die '''''aktuelle Matrix'''''&amp;quot;. Alle Matrixmanipulationen (wir kommen gleich dazu was das ist) wirken sich ''nur'' auf die ''aktuelle Matrix'' aus.&lt;br /&gt;
&lt;br /&gt;
== Kurze Matrixtheorie == &lt;br /&gt;
''Was sind Matrizen?'' &amp;lt;br&amp;gt; &lt;br /&gt;
Matrizen sind aufgebaut wie Tabellen. Das tolle daran ist - man kann damit rechnen. &amp;lt;br&amp;gt; &lt;br /&gt;
''&amp;quot;Gaaaaanz toll! Jetzt rechnen die schon mit Tabellen...&amp;quot;''&amp;lt;br&amp;gt; &lt;br /&gt;
So schlimm ist das gar nicht. Denn das Rechnen übernimmt OpenGL für uns. Ihr müsst nur wissen, dass wann immer ihr einen Befehl wie [[glTranslate]], [[glRotate]] oder [[glScale]] verwendet, ihr eine Matrix mit der ''aktuellen Matrix'' multipliziert. &lt;br /&gt;
{{Hinweis|Wenn ihr wissen wollt, wie man Matrizen miteinander multipliziert, dann lest euch einmal den Artikel &amp;quot;[[Matrix]]&amp;quot; durch und auch das dort verlinkte PDF &amp;quot;CompGeoScript&amp;quot;.}} &lt;br /&gt;
&lt;br /&gt;
== Wie sehen Matrizen aus? == &lt;br /&gt;
In &amp;quot;echt&amp;quot; sehen Matrizen wie Tabellen voller Zahlen aus. &amp;lt;br&amp;gt; &lt;br /&gt;
Will man sich eine Matrix grafisch vorstellen, sollte man sich ein 3 dimensionales Gitter vorstellen. Dieses Gitter ist das Koordinatensystem der Matrix. Wenn ihr mit [[glTranslate]], [[glRotate]] oder [[glScale]] die Matrix manipuliert, dann verändert ihr die Position des Koordinatenursprungs (glTranslate), die Ausrichtung der Achsen (glRotate) oder die Maße (glScale). Im dritten Teil des Tutorials gehe ich auf die Auswirkungen dieser Befehle noch einmal genauer ein. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Die drei OpenGL Matrizen = &lt;br /&gt;
&lt;br /&gt;
== GL_PROJECTION == &lt;br /&gt;
Ich möchte zuerst einmal die Projektionsmatrix vorstellen. Diese Matrix wird meist nur am Rande erwähnt, macht aber einen verdammt wichtigen Job: Sie projeziert den Inhalt der Welt auf den Bildschirm. &lt;br /&gt;
&lt;br /&gt;
Wenn ihr der Projektionsmatrix per [[glLoadMatrix]] eine Matrix zuweist, die nur Nullen enthält, werdet ihr feststellen, dass ihr nichts seht. Ihr habt damit nämlich die Projektionsmatrix ausgeschaltet und da wir ja was sehen wollen, unterlassen wir das in Zukunft lieber ;). &lt;br /&gt;
&lt;br /&gt;
''Aber was kann man dann mit der Projektionsmatrix machen (,außer sie nicht auszuschalten ;-) )?'' &amp;lt;br&amp;gt; &lt;br /&gt;
Bei der Vorstellung der einzelnen Matrizen erwähnte ich bereits die &amp;quot;Kamera&amp;quot;. Um gleich mal eins festzustellen: Ein Objekt &amp;quot;Kamera&amp;quot; existiert nicht. Das einzige, was man von der &amp;quot;Kamera&amp;quot; mitbekommt, ist die Ausgabe. Und wie wir gerade gelernt haben ist welcher Teil für die Ausgabe zuständig? Richtig! Die Projektionsmatrix. Sie ist unsere &amp;quot;Kamera&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Kommt jetzt aber bitte nicht auf die Idee, eure Projektionsmatrix per '''glTranslate''' und '''glRotate''' irgendwohin zu bewegen... Das ist nämlich gar nicht die Aufgabe der Projektionsmatrix. Ihre Aufgabe ist &amp;quot;das Abbild für die Ausgabe zu manipulieren&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Im Ausgangszustand ([[glLoadIdentity]] wurde für die Projektionsmatrix aufgerufen), gibt die Projektionsmatrix das Bild der Welt unverändert aus. Wenn man '''glTranslate''' auf die Projektionsmatrix anwendet, dann verschiebt man nicht die Welt, sondern sagt der  Projektionsmatrix, dass sie das gesehene Bild verschieben soll. &lt;br /&gt;
&lt;br /&gt;
Befehle wie [[gluPerspective]] und [[glOrtho]] sind typische Befehle zum einstellen der Projektionsmatrix. Diese Befehle bestimmen nämlich in welcher Form die Ausgabe gemacht wird. Entweder perspektivisch verzerrt (gluPerspective) oder durch Parallelprojektion (glOrtho).&lt;br /&gt;
&lt;br /&gt;
Wenn man die Projektionsmatrix manipuliert, ist das vergleichbar mit dem Austauschen des Objektivs bei einer Kamera. Man könnt sogar über die Projektionsmatrix einen &amp;quot;Fischauge&amp;quot; Effekt erzeugen... (Aber fragt mich bitte nicht, wie die Matrix dazu aussieht... ;-) Falls ihrs wisst, einfach im Forum posten. Ich wäre interessiert.)&lt;br /&gt;
&lt;br /&gt;
== GL_MODELVIEW == &lt;br /&gt;
Wie bereits erwähnt ist die Modelviewmatrix die wichtigste Matrix in der OpenGL Welt, denn sie wirkt sich auf Ausrichtung und Position aller Primitive und damit Objekte in der OpenGL Welt aus. Ohne Daten in der Modelviewmatrix, kann die Projektionsmatrix auch nichts ausgeben. &lt;br /&gt;
&lt;br /&gt;
Wenn ihr [[Vertex]]daten  an die Grafikkarte übermittelt solltet ihr die Modelviewmatrix aktiviert haben. Positionsangaben wie z.B. {{INLINE_CODE|glVertex3f(1,0,1);}} beziehen sich auf das aktuelle Koordinatensystem. Das Koordinatensystem ist quasi der Teil der Matrix mit dem ihr arbeitet, und den ihr euch vorstellen könnt (/müßt.).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie ihr bereits wisst kann man mit den Befehlen [[glTranslate]], [[glRotate]] und [[glScale]] das Koordinatensystem manipulieren. Dadurch seit ihr in der Lage beim &amp;quot;bauen&amp;quot; von Objekten mit &amp;quot;lokalen Koordinaten&amp;quot; zu arbeiten. &lt;br /&gt;
&lt;br /&gt;
=== lokale und globale Koordinaten === &lt;br /&gt;
''Worin unterscheiden sich lokale und globale Koordinaten?'' &amp;lt;br&amp;gt; &lt;br /&gt;
Um diese Frage zu klären bedarf es eines kleinen Beispiels: &lt;br /&gt;
&lt;br /&gt;
Stellt euch vor, ihr wollt zwei Würfel zeichnen. Der eine soll um den Punkt (3,4,5)  mit einer Kantenlänge von 1 erstellt werden, der andere soll um den Punkt (1,2,3) mit Kantenlänge 2 und dazu 30° um die Y-Achse gedreht werden. &lt;br /&gt;
&lt;br /&gt;
Wenn man mit '''globalen''' Koordinaten arbeitet lässt man die Matrix so wie sie ist (verzichtet also auf die 3 genannten Befehle) und schreibt die Koordinaten der Eckpunkte per Hand hin: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;glBegin(GL_QUADS); &lt;br /&gt;
  //Vorderseite erster Würfel &lt;br /&gt;
  glVertex3f(2,5,6); &lt;br /&gt;
  glVertex3f(2,3,6); &lt;br /&gt;
  glVertex3f(4,3,6); &lt;br /&gt;
  glVertex3f(4,5,6); &lt;br /&gt;
  //Nächste Seite &lt;br /&gt;
  [...] &lt;br /&gt;
&lt;br /&gt;
  //Vorderseite zweiter Würfel &lt;br /&gt;
  glVertex3f(0,3,4); &lt;br /&gt;
  glVertex3f(0,1,4); &lt;br /&gt;
  glVertex3f(2,1,4); &lt;br /&gt;
  glVertex3f(2,3,4); &lt;br /&gt;
  [...] &lt;br /&gt;
&lt;br /&gt;
glEnd; &lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Bei '''lokalen''' Koordinaten bewegt man zuerst den Koordinatenursprung an die Stelle an die der Würfel entstehen soll, richtet dann wenn nötig die Achsen entsprechend aus, und kann dann '''lokale''' Koordinaten übergeben. Lokal bedeutet hier relativ zum aktuellen Koordinatensystem. &lt;br /&gt;
&lt;br /&gt;
''Aber was soll das für einen Vorteil haben?'' &amp;lt;br&amp;gt; &lt;br /&gt;
Dem ein oder anderen ist vielleicht aufgefallen, dass wir 2x das selbe Objekt zeichnen sollen. Der einzigste Unterschied besteht in der Position, Ausrichtung und Größe/Scalierung. Um Arbeit zu sparen erstellt man deshalb ein Unterprogramm welches einen Einheitswürfel (Kantenlänge 1) rendert, und ruft vor dem zeichnen einfach die passende Kombination aus glTranslate, glRotate und glScale auf: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;procedure zeichneWuerfel; &lt;br /&gt;
begin &lt;br /&gt;
  glBegin(GL_QUADS); &lt;br /&gt;
    glVertex3f(-0.5, 0.5, 0.5); &lt;br /&gt;
    glVertex3f(-0.5,-0.5, 0.5); &lt;br /&gt;
    glVertex3f( 0.5,-0.5, 0.5); &lt;br /&gt;
    glVertex3f( 0.5, 0.5, 0.5); &lt;br /&gt;
    [...] &lt;br /&gt;
  glEnd; &lt;br /&gt;
end; &lt;br /&gt;
&lt;br /&gt;
begin &lt;br /&gt;
  glPushMatrix; &lt;br /&gt;
    glTranslatef(3,4,5); &lt;br /&gt;
    zeichneWuerfel; &lt;br /&gt;
  glPopMatrix; &lt;br /&gt;
  glPushMatrix; &lt;br /&gt;
    glTranslatef(1,2,3); &lt;br /&gt;
    glRotatef(30,0,1,0); &lt;br /&gt;
    glScalef(2,2,2); &lt;br /&gt;
    zeichneWuerfel; &lt;br /&gt;
  glPopMatrix; &lt;br /&gt;
end; &lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Wie ihr seht, haben lokale Koordinaten den Vorteil, dass man wiederverwendbaren Code schreiben kann. Bei globalen Koordinaten muss für jedes Objekt eigener Code geschrieben werden (und wenn sich das Objekt bewegt dann wieder...).&lt;br /&gt;
&lt;br /&gt;
Dreimal dürft ihr raten, welche Methode häufiger verwendet wird. ;-) &lt;br /&gt;
{{Hinweis|Modeller wie 3D Studio Max benutzen globale Koordinaten beim exportieren der Modelle. Dies hat den Vorteil, dass beim importieren einer ganzen 3DS Szene, die Objekte gleich an der richtigen Position stehen, und nicht erst ausgerichtet werden müssen.}} &lt;br /&gt;
&lt;br /&gt;
== GL_TEXTURE == &lt;br /&gt;
Dieser Matrix sollte endlich mehr Aufmerksamkeit geschenkt werden. Sie kann nämlich mit den Texturen in der Szene einiges anfangen... &lt;br /&gt;
&lt;br /&gt;
Aber der Reihe nach: &lt;br /&gt;
&lt;br /&gt;
Wie ihr vielleicht schon im [[Tutorial_lektion4|Einsteigertutorial 4 - Texturen]] gelesen habt, sind Texturkoordinaten immer so, dass {{INLINE_CODE|[[glTexCoord2f]](0,0)}} die obere linke Ecke und {{INLINE_CODE|glTexCoord2f(1,1)}} die untere Rechte Ecke der Textur betrifft. Wie die Textur außerhalb dieses Bereichs aussieht bestimmt ihr mittels [[glTexParameter]] und dem Parametern '''GL_TEXTURE_WRAP_S''' und '''GL_TEXTURE_WRAP_T'''. &lt;br /&gt;
&lt;br /&gt;
Nun stellt euch einmal vor, ihr habt 2 Quads die beide die selbe Textur bekommen sollen. Einziger Unterschied ist, dass bei dem einen Quad der Inhalt der Textur um 20° in Uhrzeigerrichtung gedreht ist. Blöd, oder? Das heißt ja jetzt, dass ihr in eurem Zeichenprogramm eine weitere Textur erstellen müßt, um das zweite Quad zu texturieren oder die Texturkoordinaten per Hand ändern müsst. &amp;lt;br&amp;gt; &lt;br /&gt;
'''STOP!''' Ihr hab es sicherlich schon mitbekommen: Dieses Szenario kann leicht mit der Texturmatrix gelößt werden. Und zwar so... &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;procedure drawTexturedQuad; &lt;br /&gt;
begin &lt;br /&gt;
  glBegin(GL_QUADS); &lt;br /&gt;
    glTexCoord(0,0); glVertex3f(-1, 1,0); &lt;br /&gt;
    glTexCoord(0,1); glVertex3f(-1,-1,0); &lt;br /&gt;
    glTexCoord(1,1); glVertex3f( 1,-1,0); &lt;br /&gt;
    glTexCoord(1,0); glVertex3f( 1, 1,0); &lt;br /&gt;
  glEnd; &lt;br /&gt;
end; &lt;br /&gt;
&lt;br /&gt;
begin &lt;br /&gt;
  glMatrixMode(GL_MODELVIEW); &lt;br /&gt;
  glBindTexture(GL_TEXTURE_2D, texID); &lt;br /&gt;
  glTranslatef(-2,0,0); &lt;br /&gt;
  drawTexturedQuad; &lt;br /&gt;
&lt;br /&gt;
  glMatrixMode(GL_TEXTURE); &lt;br /&gt;
  glRotatef(20,0,0,1); &lt;br /&gt;
&lt;br /&gt;
  glMatrixMode(GL_MODELVIEW); &lt;br /&gt;
  glTranslatef(4,0,0); &lt;br /&gt;
  drawTexturedQuad; &lt;br /&gt;
end;&amp;lt;/source&amp;gt; &lt;br /&gt;
''Was ist hier geschehn? ''&amp;lt;br&amp;gt;&lt;br /&gt;
Durch die vorherige Aktivierung der Texturmatrix wirkt sich das nachfolgende glRotate nicht auf die Modelle der Szene sondern auf die Texturkoordinaten aus. Auf gut deutsch: OpenGL dreht vor dem rendern des zweiten Quads die Textur um 20°. &lt;br /&gt;
&lt;br /&gt;
Wenn ihr beim rotieren der Texturmatrix, bei jedem Renderdurchlauf den Winkel um ein Stück erhöht passiert was?... Richtig! Eure Textur dreht sich auf eurem Quad... Das is dann quasi eure erste Animation... Und das ohne ein Objekt zu bewegen... Cool, oder?&lt;br /&gt;
&lt;br /&gt;
= Auswirkungen von Matrixmanipulationen - oder &amp;quot;Wie positioniere ich meine Objekte richtig?&amp;quot;= &lt;br /&gt;
In diesem Teil des Tutorials möchte ich euch zeigen wie die 3 Befehle '''glTranslate, glRotate''' und '''glScale''' eure aktuelle Matrix verändern. Ich bleibe hierbei im 2 dimensionalen Raum, da sonst die Skizzen zu unübersichtlich werden. (Die Befehle sind dabei natürlich die selben wie für 3D Manipulationen. Ich ignoriere nur einfach immer die Y-Angaben.) &lt;br /&gt;
&lt;br /&gt;
Zuersteinmal zum warm werden: &amp;lt;br&amp;gt; &lt;br /&gt;
[[Bild:Tutorial Matrix2 Ausgangsbild.png|framed|center|So stelle ich mir eine 2D-Matrix vor.]] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==glTranslate== &lt;br /&gt;
{{INLINE_CODE|[[glTranslate]](a,b,c)}} verschiebt den Koordinatenursprung des aktuellen Koordinatensystems um ''a'' Einheiten in die Richtung der X-Achse, um ''b'' Einheiten in die Richtung der Y-Achse und um ''c'' Einheiten in die Richtung der Z-Achse. &lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutorial Matrix2 Translate.png|framed|center|Das passiert bei einer Translation um 3.5 Einheiten in X und -3 Einheiten in Z-Richtung.]] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==glRotate== &lt;br /&gt;
{{INLINE_CODE|[[glRotate]](w,x,y,z)}} rotiert das Koordinatensystem um ''w'' Grad um die Rotationsachse welche durch (0,0,0) und (''x,y,z'') verläuft. '''glRotate richtet also die Achsen neu aus.''' (Die Richtung der Achsen ist z.B. wichtig für glTranslate) &lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutorial Matrix2 Rotate.png|framed|center|Das passiert bei einer Rotation um 45° mit der Y-Achse als Rotationsachse.]]&lt;br /&gt;
&lt;br /&gt;
==glScale== &lt;br /&gt;
{{INLINE_CODE|[[glScale]](x,y,z)}} skaliert die Maße der Koordinatenachsen (Bestimmt also wie lange &amp;quot;eine Einheit&amp;quot; wirklich ist). Wenn ''x,y'' oder ''z'' größer als 1 ist, werden die Maßeinheiten der entsprechenden Achse gestreckt, wenn die Werte kleiner 1 sind gestaucht. (Wenn die Werte gleich 0 sind verschwindet die Szene auf nimmer wieder sehn(, da hilft dann nur noch glLoadIdentity um die Matrix wieder nutzbar zu machen), sind die Werte gleich 1 verändert sich nichts.) &lt;br /&gt;
&lt;br /&gt;
''x,y'' und ''z'' muss man sich als Prozentangaben vorstellen. Will man die Szene in X-Richtung um das doppelte (also 200%) vergrößern/strecken muss ''x'' gleich 2 sein. Will man die Y-Richtung auf ein Zehntel (also 10%) verkürzen/stauchen muss ''y'' gleich 0.1 sein. &lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutorial Matrix2 Scale.png|framed|center|Das passiert bei einer Skalierung. Wie ihr seht, sind die Seiten unterschiedlich skaliert worden (X-Achse: 80%, Z-Achse: 60%).]] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Kombination - Translate vor Rotate== &lt;br /&gt;
Wird Translate vor Rotate aufgerufen, bewegt sich der Koordinatenursprung zuerst an den Zielpunkt (über glTranslate angegeben). Anschließend werden die Achsen neu ausgerichtet (durch glRotate). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|Folgender Code wird demonstriert: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt; &lt;br /&gt;
  glTranslatef(3.5,0,-3); &lt;br /&gt;
  glRotatef(45, 0, 1, 0); &lt;br /&gt;
  ZeichneKoordinatensystem; &lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Ausgangsbild.png|framed|center|Bevor glTranslate aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Translate.png|framed|center|Nachdem glTranslate aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 TranslateRot.png|framed|center|Nachdem glRotate aufgerufen wurde. Man sieht, dass die jeweils vorhergehende Veränderung bestehend bleibt, und die Basis für die nachfolgende Änderung bildet.]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wird der Winkel von glRotate bei jedem Renderdurchlauf erhöht, dreht sich ein anschließend gezeichnetes Objekt um die durch glTranslate angegeben Position. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Kombination - Rotate vor Translate== &lt;br /&gt;
Wird Rotate vor Translate aufgerufen, werden zuerst die Achsen neu ausgerichtet und dann der Koordinatenursprung bezüglich dieser neuen Achsen verschoben. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|Folgender Code wird demonstriert: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt; &lt;br /&gt;
  glRotatef(45, 0, 1, 0); &lt;br /&gt;
  glTranslatef(3.5,0,-3);   &lt;br /&gt;
  ZeichneKoordinatensystem; &lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Ausgangsbild.png|framed|center|Bevor glRotate aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Rotate.png|framed|center|Nachdem glRotate aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 RotateTrans.png|framed|center|Nachdem glTranslate aufgerufen wurde. Man sieht, dass die vorhergehende Rotation die Verschieberichtung beeinflusst.]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Wird der Winkel von glRotate bei jedem Renderdurchlauf erhöht, bewegt sich ein nach glTranslate gezeichnetes Objekt auf einer Kreisbahn um den Koordinatenursprung wie er beim Aufruf von glRotate aktuell war. Der Radius der Kreisbahn wird durch glTranslate bestimmt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wenn man die beiden Ergebnisse direkt vergleicht sieht man, dass die Reihenfolge von Bedeutung für das Ergebniss ist. Das die Unterschiede so &amp;quot;klein&amp;quot; ausfallen liegt nur daran, dass bei rotate nicht mit größeren Winkeln rotiert wurde. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|width=&amp;quot;50%&amp;quot; | [[Bild:Tutorial Matrix2 RotateTrans.png|framed|center|Erst Rotiert]] &lt;br /&gt;
|- &lt;br /&gt;
|width=&amp;quot;50%&amp;quot; | [[Bild:Tutorial Matrix2 TranslateRot.png|framed|center|Erst Verschoben]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kombination - Scale vor Rotate== &lt;br /&gt;
Die Rotation wird nur von der Richung, nicht aber der Länge der Achsen beeinflusst. Der Winkel um den gedreht wird, bleibt von der Skalierung unberührt (45° bleiben 45°. Die Achsen zeigen anschließend jeweils in die gleiche Richtung) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|Folgender Code wird demonstriert: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt; &lt;br /&gt;
  glScalef(0.8, 1, 0.6); &lt;br /&gt;
  glRotatef(45, 0, 1, 0); &lt;br /&gt;
  ZeichneKoordinatensystem; &lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Ausgangsbild.png|framed|center|Bevor glScale aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Scale.png|framed|center|Nachdem glScale aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 ScaleRot.png|framed|center|Nachdem glRotate aufgerufen wurde. Man sieht, dass die Skalierung den Winkel nicht beeinflusst. Das Koordinatensystem wurde korrekt um 45° gedreht.]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Der direkte Vergleich zeigt, dass die Skalierung keinen Effekt auf den Winkel hatte. Beide Koordinatensysteme sind gleich ausgerichtet: &lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|width=&amp;quot;50%&amp;quot; | [[Bild:Tutorial Matrix2 Rotate.png|framed|center|Unskaliert]] &lt;br /&gt;
|- &lt;br /&gt;
|width=&amp;quot;50%&amp;quot; | [[Bild:Tutorial Matrix2 ScaleRot.png|framed|center|Skaliert]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Kombination - Scale vor Translate== &lt;br /&gt;
Die Verschiebung ist Abhängig von der Ausrichtung der Achsen (glRotate) und der Maße der Achsen (glScale). Aus diesem Grunde beeinflusst glScale die nachfolgenden Translationen. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|Folgender Code wird demonstriert: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt; &lt;br /&gt;
  glScalef(0.8, 1, 0.6); &lt;br /&gt;
  glTranslatef(3.5,0,-3); &lt;br /&gt;
  ZeichneKoordinatensystem; &lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Ausgangsbild.png|framed|center|Bevor glScale aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Scale.png|framed|center|Nachdem glScale aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 ScaleTrans.png|framed|center|Nachdem glTranslate aufgerufen wurde.]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Der direkte Vergleich zeigt, dass sich die Skalierung auf die Verschiebung auswirkt. Denn obwohl der Verschiebung in die gleiche Richtung und um den selben Wert erfolgt, sind die Resultate nicht identisch. Dies liegt daran, dass glScale die Maße verändert hat. Die Verschiebung in X-Richtung erreicht dadurch nur 80% und in Z-Richtung sogar nur 60% der unskalierten Transformation: &lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|width=&amp;quot;50%&amp;quot; | [[Bild:Tutorial Matrix2 Translate.png|framed|center|Unskaliert]] &lt;br /&gt;
|- &lt;br /&gt;
|width=&amp;quot;50%&amp;quot; | [[Bild:Tutorial Matrix2 ScaleTrans.png|framed|center|Skaliert]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Nachwort= &lt;br /&gt;
7 Stunden sind vorbei und das Tutorial ist auf eine ordentliche Länge angewachsen. Ich hoffe ich konnte euch die OpenGL Matrizen etwas näher bringen. &lt;br /&gt;
&lt;br /&gt;
Wer jetzt denkt ''&amp;quot;Bilder sind mir zu statisch!&amp;quot;'', dem möchte ich noch diese Programme ans Herz legen: &lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|{{Prettytable}}&lt;br /&gt;
!Name&lt;br /&gt;
!Hersteller&lt;br /&gt;
!Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.delphigl.com/forum/viewtopic.php?p=37378#37378 '''Matrix2 - Skizzenrenderer''']&lt;br /&gt;
|Flash&lt;br /&gt;
|Dieses Programm habe ich geschrieben um die Skizzen für dieses Tutorial zu erstellen. Es wurde so modifiziert, dass man beliebige Kombinationen von glTranslate, glRotate und glScale anzeigen kann. &lt;br /&gt;
|-&lt;br /&gt;
|[http://www.phobeus.de/hosting/shared/pixelpracht/main.php?s=opengl&amp;amp;t=1&amp;amp;p=2 '''Matrix Control''']&lt;br /&gt;
|Lithander&lt;br /&gt;
|Das Programm erlaubt euch zu beobachten, wie die Matrizen sich bei den einzelnen Befehlen verändern und wie die Ausgabe aussieht. Besonderheit an diesem Programm ist, dass ihr die Matrizen auch per Hand manipulieren könnt.&lt;br /&gt;
|}&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sollten immer noch Unklarheiten bestehen bleibt das Forum natürlich auch weiterhin die Anlaufstelle Nummer1. Dies betrifft auch euer Feedback zum Tutorial. &lt;br /&gt;
&lt;br /&gt;
MfG &lt;br /&gt;
: Flash ('''Kevin Fleischer''') &lt;br /&gt;
&lt;br /&gt;
{{TUTORIAL_NAVIGATION|[[Tutorial_2D]]|-}} &lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Tutorial|Matrix2]]&lt;/div&gt;</summary>
		<author><name>Phlegmatiker</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_Matrix2&amp;diff=25434</id>
		<title>Tutorial Matrix2</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_Matrix2&amp;diff=25434"/>
				<updated>2011-12-18T10:00:25Z</updated>
		
		<summary type="html">&lt;p&gt;Phlegmatiker: /* Matrizen in OpenGL */ Zahlen bis 12 schreibt man aus.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Matrizen und Matrixmanipulationen= &lt;br /&gt;
&lt;br /&gt;
== Vorwort == &lt;br /&gt;
Willkommen bei meinem zweiten Tutorial.&amp;lt;br&amp;gt; &lt;br /&gt;
In letzter Zeit traten im Forum verstärkt fragen wie ''&amp;quot;Wie positioniere ich Objekte richtig?&amp;quot;'' und ''&amp;quot;Ich komm mit den Matrizen net klar. Könnt ihr helfen?&amp;quot;'' auf. Dies war Anlass für mich ein weiteres Tutorial zum Thema Matrizen zu schreiben. Ich werde versuchen viel mit Bildern und Gleichnissen zu arbeiten. Wer aber das ganze Angebot zum Thema &amp;quot;Matrix&amp;quot; nutzen will sollte ruhig auch einen Blick auf Phobeus Matrixtutorial ([[Tutorial_lektion3]]) und auf den Wikiartikel zum Thema [[Matrix]] werfen.&lt;br /&gt;
&lt;br /&gt;
== Matrizen in OpenGL == &lt;br /&gt;
&lt;br /&gt;
OpenGL kennt drei Matrizen. Wer OpenGL programmieren will sollte diese auch kennen: &lt;br /&gt;
* '''GL_MODELVIEW''' - Die Modelviewmatrix &lt;br /&gt;
: Die Modelviewmatrix sollte immer dann aktiviert sein, wenn ihr an die Grafikkarte [[Vertex]]daten senden wollt. Diese Matrix wird auf die Position der Vertices, die mit [[glVertex]] gesendet werden angewandt. Ebenso beeinflusst sie die Ausrichtung der [[Normalen]], die mit Hilfe von [[glNormal]] gesetzt werden. Kurz, alles was mit den Objekten eurer Welt zu tun hat, erfordert die Aktivierung dieser Matrix.&lt;br /&gt;
* '''GL_PROJECTION''' - Die Projektionsmatrix &lt;br /&gt;
: Diese Matrix wird selten gebraucht. Sie bestimmt, wie am Ende alles angezeigt wird. Sie bestimmt quasi die Eigenschaften der &amp;quot;Kamera&amp;quot;. &lt;br /&gt;
* '''GL_TEXTURE''' - Die Texturmatrix &lt;br /&gt;
: Diese Matrix wird auf die Texturkoordinaten angewandt, mit der Folge, dass sich die Texturen auf den Oberflächen bewegen.&lt;br /&gt;
&lt;br /&gt;
Diese Matrizen können per [[glMatrixMode]] aktiviert werden. Dabei kann immer nur eine Matrix aktiv sein. Wenn ihr z.B. {{INLINE_CODE|glMatrixMode(GL_MODELVIEW)}} aufgerufen habt, dann sagt man &amp;quot;Die Modelviewmatrix ist die '''''aktuelle Matrix'''''&amp;quot;. Alle Matrixmanipulationen (wir kommen gleich dazu was das ist) wirken sich ''nur'' auf die ''aktuelle Matrix'' aus.&lt;br /&gt;
&lt;br /&gt;
== Kurze Matrixtheorie == &lt;br /&gt;
''Was sind Matrizen?'' &amp;lt;br&amp;gt; &lt;br /&gt;
Matrizen sind aufgebaut wie Tabellen. Das tolle daran ist - man kann damit rechnen. &amp;lt;br&amp;gt; &lt;br /&gt;
''&amp;quot;Gaaaaanz toll! Jetzt rechnen die schon mit Tabellen...&amp;quot;''&amp;lt;br&amp;gt; &lt;br /&gt;
So schlimm ist das gar nicht. Denn das Rechnen übernimmt OpenGL für uns. Ihr müsst nur wissen, dass wann immer ihr einen Befehl wie [[glTranslate]], [[glRotate]] oder [[glScale]] verwendet, ihr eine Matrix mit der ''aktuellen Matrix'' multipliziert. &lt;br /&gt;
{{Hinweis|Wenn ihr wissen wollt, wie man Matrizen miteinander multipliziert, dann lest euch einmal den Artikel &amp;quot;[[Matrix]]&amp;quot; durch und auch das dort verlinkte PDF &amp;quot;CompGeoScript&amp;quot;.}} &lt;br /&gt;
&lt;br /&gt;
== Wie sehen Matrizen aus? == &lt;br /&gt;
In &amp;quot;echt&amp;quot; sehen Matrizen wie Tabellen voller Zahlen aus. &amp;lt;br&amp;gt; &lt;br /&gt;
Will man sich eine Matrix grafisch vorstellen, sollte man sich ein 3 dimensionales Gitter vorstellen. Dieses Gitter ist das Koordinatensystem der Matrix. Wenn ihr mit [[glTranslate]], [[glRotate]] oder [[glScale]] die Matrix manipuliert, dann verändert ihr die Position des Koordinatenursprungs (glTranslate), die Ausrichtung der Achsen (glRotate) oder die Maße (glScale). Im dritten Teil des Tutorials gehe ich auf die Auswirkungen dieser Befehle noch einmal genauer ein. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Die drei OpenGL Matrizen = &lt;br /&gt;
&lt;br /&gt;
== GL_PROJECTION == &lt;br /&gt;
Ich möchte zuerst einmal die Projektionsmatrix vorstellen. Diese Matrix wird meist nur am Rande erwähnt, macht aber einen verdammt wichtigen Job: Sie projeziert den Inhalt der Welt auf den Bildschirm. &lt;br /&gt;
&lt;br /&gt;
Wenn ihr der Projektionsmatrix per [[glLoadMatrix]] eine Matrix zuweist, die nur Nullen enthält, werdet ihr feststellen, dass ihr nichts seht. Ihr habt damit nämlich die Projektionsmatrix ausgeschaltet und da wir ja was sehen wollen, unterlassen wir das in Zukunft lieber ;). &lt;br /&gt;
&lt;br /&gt;
''Aber was kann man dann mit der Projektionsmatrix machen (,außer sie nicht auszuschalten ;-) )?'' &amp;lt;br&amp;gt; &lt;br /&gt;
Bei der Vorstellung der einzelnen Matrizen erwähnte ich bereits die &amp;quot;Kamera&amp;quot;. Um gleich mal eins festzustellen: Ein Objekt &amp;quot;Kamera&amp;quot; existiert nicht. Das einzigste was man von der &amp;quot;Kamera&amp;quot; mitbekommt ist die Ausgabe. Und wie wir gerade gelernt haben ist welcher Teil für die Ausgabe zuständig? Richtig! Die Projektionsmatrix. Sie ist unsere &amp;quot;Kamera&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Kommt jetzt aber bitte nicht auf die Idee, eure Projektionsmatrix per '''glTranslate''' und '''glRotate''' irgendwohin zu bewegen... Das ist nämlich gar nicht die Aufgabe der Projektionsmatrix. Ihre Aufgabe ist &amp;quot;das Abbild für die Ausgabe zu manipulieren&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Im Ausgangszustand ([[glLoadIdentity]] wurde für die Projektionsmatrix aufgerufen), gibt die Projektionsmatrix das Bild der Welt unverändert aus. Wenn man '''glTranslate''' auf die Projektionsmatrix anwendet, dann verschiebt man nicht die Welt, sondern sagt der  Projektionsmatrix, dass sie das gesehene Bild verschieben soll. &lt;br /&gt;
&lt;br /&gt;
Befehle wie [[gluPerspective]] und [[glOrtho]] sind typische Befehle zum einstellen der Projektionsmatrix. Diese Befehle bestimmen nämlich in welcher Form die Ausgabe gemacht wird. Entweder perspektivisch verzerrt (gluPerspective) oder durch Parallelprojektion (glOrtho).&lt;br /&gt;
&lt;br /&gt;
Wenn man die Projektionsmatrix manipuliert, ist das vergleichbar mit dem Austauschen des Objektivs bei einer Kamera. Man könnt sogar über die Projektionsmatrix einen &amp;quot;Fischauge&amp;quot; Effekt erzeugen... (Aber fragt mich bitte nicht, wie die Matrix dazu aussieht... ;-) Falls ihrs wißt, einfach im Forum posten. Ich wäre interessiert.)&lt;br /&gt;
&lt;br /&gt;
== GL_MODELVIEW == &lt;br /&gt;
Wie bereits erwähnt ist die Modelviewmatrix die wichtigste Matrix in der OpenGL Welt, denn sie wirkt sich auf Ausrichtung und Position aller Primitive und damit Objekte in der OpenGL Welt aus. Ohne Daten in der Modelviewmatrix, kann die Projektionsmatrix auch nichts ausgeben. &lt;br /&gt;
&lt;br /&gt;
Wenn ihr [[Vertex]]daten  an die Grafikkarte übermittelt solltet ihr die Modelviewmatrix aktiviert haben. Positionsangaben wie z.B. {{INLINE_CODE|glVertex3f(1,0,1);}} beziehen sich auf das aktuelle Koordinatensystem. Das Koordinatensystem ist quasi der Teil der Matrix mit dem ihr arbeitet, und den ihr euch vorstellen könnt (/müßt.).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie ihr bereits wisst kann man mit den Befehlen [[glTranslate]], [[glRotate]] und [[glScale]] das Koordinatensystem manipulieren. Dadurch seit ihr in der Lage beim &amp;quot;bauen&amp;quot; von Objekten mit &amp;quot;lokalen Koordinaten&amp;quot; zu arbeiten. &lt;br /&gt;
&lt;br /&gt;
=== lokale und globale Koordinaten === &lt;br /&gt;
''Worin unterscheiden sich lokale und globale Koordinaten?'' &amp;lt;br&amp;gt; &lt;br /&gt;
Um diese Frage zu klären bedarf es eines kleinen Beispiels: &lt;br /&gt;
&lt;br /&gt;
Stellt euch vor, ihr wollt zwei Würfel zeichnen. Der eine soll um den Punkt (3,4,5)  mit einer Kantenlänge von 1 erstellt werden, der andere soll um den Punkt (1,2,3) mit Kantenlänge 2 und dazu 30° um die Y-Achse gedreht werden. &lt;br /&gt;
&lt;br /&gt;
Wenn man mit '''globalen''' Koordinaten arbeitet lässt man die Matrix so wie sie ist (verzichtet also auf die 3 genannten Befehle) und schreibt die Koordinaten der Eckpunkte per Hand hin: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;glBegin(GL_QUADS); &lt;br /&gt;
  //Vorderseite erster Würfel &lt;br /&gt;
  glVertex3f(2,5,6); &lt;br /&gt;
  glVertex3f(2,3,6); &lt;br /&gt;
  glVertex3f(4,3,6); &lt;br /&gt;
  glVertex3f(4,5,6); &lt;br /&gt;
  //Nächste Seite &lt;br /&gt;
  [...] &lt;br /&gt;
&lt;br /&gt;
  //Vorderseite zweiter Würfel &lt;br /&gt;
  glVertex3f(0,3,4); &lt;br /&gt;
  glVertex3f(0,1,4); &lt;br /&gt;
  glVertex3f(2,1,4); &lt;br /&gt;
  glVertex3f(2,3,4); &lt;br /&gt;
  [...] &lt;br /&gt;
&lt;br /&gt;
glEnd; &lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Bei '''lokalen''' Koordinaten bewegt man zuerst den Koordinatenursprung an die Stelle an die der Würfel entstehen soll, richtet dann wenn nötig die Achsen entsprechend aus, und kann dann '''lokale''' Koordinaten übergeben. Lokal bedeutet hier relativ zum aktuellen Koordinatensystem. &lt;br /&gt;
&lt;br /&gt;
''Aber was soll das für einen Vorteil haben?'' &amp;lt;br&amp;gt; &lt;br /&gt;
Dem ein oder anderen ist vielleicht aufgefallen, dass wir 2x das selbe Objekt zeichnen sollen. Der einzigste Unterschied besteht in der Position, Ausrichtung und Größe/Scalierung. Um Arbeit zu sparen erstellt man deshalb ein Unterprogramm welches einen Einheitswürfel (Kantenlänge 1) rendert, und ruft vor dem zeichnen einfach die passende Kombination aus glTranslate, glRotate und glScale auf: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;procedure zeichneWuerfel; &lt;br /&gt;
begin &lt;br /&gt;
  glBegin(GL_QUADS); &lt;br /&gt;
    glVertex3f(-0.5, 0.5, 0.5); &lt;br /&gt;
    glVertex3f(-0.5,-0.5, 0.5); &lt;br /&gt;
    glVertex3f( 0.5,-0.5, 0.5); &lt;br /&gt;
    glVertex3f( 0.5, 0.5, 0.5); &lt;br /&gt;
    [...] &lt;br /&gt;
  glEnd; &lt;br /&gt;
end; &lt;br /&gt;
&lt;br /&gt;
begin &lt;br /&gt;
  glPushMatrix; &lt;br /&gt;
    glTranslatef(3,4,5); &lt;br /&gt;
    zeichneWuerfel; &lt;br /&gt;
  glPopMatrix; &lt;br /&gt;
  glPushMatrix; &lt;br /&gt;
    glTranslatef(1,2,3); &lt;br /&gt;
    glRotatef(30,0,1,0); &lt;br /&gt;
    glScalef(2,2,2); &lt;br /&gt;
    zeichneWuerfel; &lt;br /&gt;
  glPopMatrix; &lt;br /&gt;
end; &lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Wie ihr seht, haben lokale Koordinaten den Vorteil, dass man wiederverwendbaren Code schreiben kann. Bei globalen Koordinaten muss für jedes Objekt eigener Code geschrieben werden (und wenn sich das Objekt bewegt dann wieder...).&lt;br /&gt;
&lt;br /&gt;
Dreimal dürft ihr raten, welche Methode häufiger verwendet wird. ;-) &lt;br /&gt;
{{Hinweis|Modeller wie 3D Studio Max benutzen globale Koordinaten beim exportieren der Modelle. Dies hat den Vorteil, dass beim importieren einer ganzen 3DS Szene, die Objekte gleich an der richtigen Position stehen, und nicht erst ausgerichtet werden müssen.}} &lt;br /&gt;
&lt;br /&gt;
== GL_TEXTURE == &lt;br /&gt;
Dieser Matrix sollte endlich mehr Aufmerksamkeit geschenkt werden. Sie kann nämlich mit den Texturen in der Szene einiges anfangen... &lt;br /&gt;
&lt;br /&gt;
Aber der Reihe nach: &lt;br /&gt;
&lt;br /&gt;
Wie ihr vielleicht schon im [[Tutorial_lektion4|Einsteigertutorial 4 - Texturen]] gelesen habt, sind Texturkoordinaten immer so, dass {{INLINE_CODE|[[glTexCoord2f]](0,0)}} die obere linke Ecke und {{INLINE_CODE|glTexCoord2f(1,1)}} die untere Rechte Ecke der Textur betrifft. Wie die Textur außerhalb dieses Bereichs aussieht bestimmt ihr mittels [[glTexParameter]] und dem Parametern '''GL_TEXTURE_WRAP_S''' und '''GL_TEXTURE_WRAP_T'''. &lt;br /&gt;
&lt;br /&gt;
Nun stellt euch einmal vor, ihr habt 2 Quads die beide die selbe Textur bekommen sollen. Einziger Unterschied ist, dass bei dem einen Quad der Inhalt der Textur um 20° in Uhrzeigerrichtung gedreht ist. Blöd, oder? Das heißt ja jetzt, dass ihr in eurem Zeichenprogramm eine weitere Textur erstellen müßt, um das zweite Quad zu texturieren oder die Texturkoordinaten per Hand ändern müsst. &amp;lt;br&amp;gt; &lt;br /&gt;
'''STOP!''' Ihr hab es sicherlich schon mitbekommen: Dieses Szenario kann leicht mit der Texturmatrix gelößt werden. Und zwar so... &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;procedure drawTexturedQuad; &lt;br /&gt;
begin &lt;br /&gt;
  glBegin(GL_QUADS); &lt;br /&gt;
    glTexCoord(0,0); glVertex3f(-1, 1,0); &lt;br /&gt;
    glTexCoord(0,1); glVertex3f(-1,-1,0); &lt;br /&gt;
    glTexCoord(1,1); glVertex3f( 1,-1,0); &lt;br /&gt;
    glTexCoord(1,0); glVertex3f( 1, 1,0); &lt;br /&gt;
  glEnd; &lt;br /&gt;
end; &lt;br /&gt;
&lt;br /&gt;
begin &lt;br /&gt;
  glMatrixMode(GL_MODELVIEW); &lt;br /&gt;
  glBindTexture(GL_TEXTURE_2D, texID); &lt;br /&gt;
  glTranslatef(-2,0,0); &lt;br /&gt;
  drawTexturedQuad; &lt;br /&gt;
&lt;br /&gt;
  glMatrixMode(GL_TEXTURE); &lt;br /&gt;
  glRotatef(20,0,0,1); &lt;br /&gt;
&lt;br /&gt;
  glMatrixMode(GL_MODELVIEW); &lt;br /&gt;
  glTranslatef(4,0,0); &lt;br /&gt;
  drawTexturedQuad; &lt;br /&gt;
end;&amp;lt;/source&amp;gt; &lt;br /&gt;
''Was ist hier geschehn? ''&amp;lt;br&amp;gt;&lt;br /&gt;
Durch die vorherige Aktivierung der Texturmatrix wirkt sich das nachfolgende glRotate nicht auf die Modelle der Szene sondern auf die Texturkoordinaten aus. Auf gut deutsch: OpenGL dreht vor dem rendern des zweiten Quads die Textur um 20°. &lt;br /&gt;
&lt;br /&gt;
Wenn ihr beim rotieren der Texturmatrix, bei jedem Renderdurchlauf den Winkel um ein Stück erhöht passiert was?... Richtig! Eure Textur dreht sich auf eurem Quad... Das is dann quasi eure erste Animation... Und das ohne ein Objekt zu bewegen... Cool, oder?&lt;br /&gt;
&lt;br /&gt;
= Auswirkungen von Matrixmanipulationen - oder &amp;quot;Wie positioniere ich meine Objekte richtig?&amp;quot;= &lt;br /&gt;
In diesem Teil des Tutorials möchte ich euch zeigen wie die 3 Befehle '''glTranslate, glRotate''' und '''glScale''' eure aktuelle Matrix verändern. Ich bleibe hierbei im 2 dimensionalen Raum, da sonst die Skizzen zu unübersichtlich werden. (Die Befehle sind dabei natürlich die selben wie für 3D Manipulationen. Ich ignoriere nur einfach immer die Y-Angaben.) &lt;br /&gt;
&lt;br /&gt;
Zuersteinmal zum warm werden: &amp;lt;br&amp;gt; &lt;br /&gt;
[[Bild:Tutorial Matrix2 Ausgangsbild.png|framed|center|So stelle ich mir eine 2D-Matrix vor.]] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==glTranslate== &lt;br /&gt;
{{INLINE_CODE|[[glTranslate]](a,b,c)}} verschiebt den Koordinatenursprung des aktuellen Koordinatensystems um ''a'' Einheiten in die Richtung der X-Achse, um ''b'' Einheiten in die Richtung der Y-Achse und um ''c'' Einheiten in die Richtung der Z-Achse. &lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutorial Matrix2 Translate.png|framed|center|Das passiert bei einer Translation um 3.5 Einheiten in X und -3 Einheiten in Z-Richtung.]] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==glRotate== &lt;br /&gt;
{{INLINE_CODE|[[glRotate]](w,x,y,z)}} rotiert das Koordinatensystem um ''w'' Grad um die Rotationsachse welche durch (0,0,0) und (''x,y,z'') verläuft. '''glRotate richtet also die Achsen neu aus.''' (Die Richtung der Achsen ist z.B. wichtig für glTranslate) &lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutorial Matrix2 Rotate.png|framed|center|Das passiert bei einer Rotation um 45° mit der Y-Achse als Rotationsachse.]]&lt;br /&gt;
&lt;br /&gt;
==glScale== &lt;br /&gt;
{{INLINE_CODE|[[glScale]](x,y,z)}} skaliert die Maße der Koordinatenachsen (Bestimmt also wie lange &amp;quot;eine Einheit&amp;quot; wirklich ist). Wenn ''x,y'' oder ''z'' größer als 1 ist, werden die Maßeinheiten der entsprechenden Achse gestreckt, wenn die Werte kleiner 1 sind gestaucht. (Wenn die Werte gleich 0 sind verschwindet die Szene auf nimmer wieder sehn(, da hilft dann nur noch glLoadIdentity um die Matrix wieder nutzbar zu machen), sind die Werte gleich 1 verändert sich nichts.) &lt;br /&gt;
&lt;br /&gt;
''x,y'' und ''z'' muss man sich als Prozentangaben vorstellen. Will man die Szene in X-Richtung um das doppelte (also 200%) vergrößern/strecken muss ''x'' gleich 2 sein. Will man die Y-Richtung auf ein Zehntel (also 10%) verkürzen/stauchen muss ''y'' gleich 0.1 sein. &lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutorial Matrix2 Scale.png|framed|center|Das passiert bei einer Skalierung. Wie ihr seht, sind die Seiten unterschiedlich skaliert worden (X-Achse: 80%, Z-Achse: 60%).]] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Kombination - Translate vor Rotate== &lt;br /&gt;
Wird Translate vor Rotate aufgerufen, bewegt sich der Koordinatenursprung zuerst an den Zielpunkt (über glTranslate angegeben). Anschließend werden die Achsen neu ausgerichtet (durch glRotate). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|Folgender Code wird demonstriert: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt; &lt;br /&gt;
  glTranslatef(3.5,0,-3); &lt;br /&gt;
  glRotatef(45, 0, 1, 0); &lt;br /&gt;
  ZeichneKoordinatensystem; &lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Ausgangsbild.png|framed|center|Bevor glTranslate aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Translate.png|framed|center|Nachdem glTranslate aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 TranslateRot.png|framed|center|Nachdem glRotate aufgerufen wurde. Man sieht, dass die jeweils vorhergehende Veränderung bestehend bleibt, und die Basis für die nachfolgende Änderung bildet.]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wird der Winkel von glRotate bei jedem Renderdurchlauf erhöht, dreht sich ein anschließend gezeichnetes Objekt um die durch glTranslate angegeben Position. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Kombination - Rotate vor Translate== &lt;br /&gt;
Wird Rotate vor Translate aufgerufen, werden zuerst die Achsen neu ausgerichtet und dann der Koordinatenursprung bezüglich dieser neuen Achsen verschoben. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|Folgender Code wird demonstriert: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt; &lt;br /&gt;
  glRotatef(45, 0, 1, 0); &lt;br /&gt;
  glTranslatef(3.5,0,-3);   &lt;br /&gt;
  ZeichneKoordinatensystem; &lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Ausgangsbild.png|framed|center|Bevor glRotate aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Rotate.png|framed|center|Nachdem glRotate aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 RotateTrans.png|framed|center|Nachdem glTranslate aufgerufen wurde. Man sieht, dass die vorhergehende Rotation die Verschieberichtung beeinflusst.]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Wird der Winkel von glRotate bei jedem Renderdurchlauf erhöht, bewegt sich ein nach glTranslate gezeichnetes Objekt auf einer Kreisbahn um den Koordinatenursprung wie er beim Aufruf von glRotate aktuell war. Der Radius der Kreisbahn wird durch glTranslate bestimmt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wenn man die beiden Ergebnisse direkt vergleicht sieht man, dass die Reihenfolge von Bedeutung für das Ergebniss ist. Das die Unterschiede so &amp;quot;klein&amp;quot; ausfallen liegt nur daran, dass bei rotate nicht mit größeren Winkeln rotiert wurde. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|width=&amp;quot;50%&amp;quot; | [[Bild:Tutorial Matrix2 RotateTrans.png|framed|center|Erst Rotiert]] &lt;br /&gt;
|- &lt;br /&gt;
|width=&amp;quot;50%&amp;quot; | [[Bild:Tutorial Matrix2 TranslateRot.png|framed|center|Erst Verschoben]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kombination - Scale vor Rotate== &lt;br /&gt;
Die Rotation wird nur von der Richung, nicht aber der Länge der Achsen beeinflusst. Der Winkel um den gedreht wird, bleibt von der Skalierung unberührt (45° bleiben 45°. Die Achsen zeigen anschließend jeweils in die gleiche Richtung) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|Folgender Code wird demonstriert: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt; &lt;br /&gt;
  glScalef(0.8, 1, 0.6); &lt;br /&gt;
  glRotatef(45, 0, 1, 0); &lt;br /&gt;
  ZeichneKoordinatensystem; &lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Ausgangsbild.png|framed|center|Bevor glScale aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Scale.png|framed|center|Nachdem glScale aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 ScaleRot.png|framed|center|Nachdem glRotate aufgerufen wurde. Man sieht, dass die Skalierung den Winkel nicht beeinflusst. Das Koordinatensystem wurde korrekt um 45° gedreht.]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Der direkte Vergleich zeigt, dass die Skalierung keinen Effekt auf den Winkel hatte. Beide Koordinatensysteme sind gleich ausgerichtet: &lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|width=&amp;quot;50%&amp;quot; | [[Bild:Tutorial Matrix2 Rotate.png|framed|center|Unskaliert]] &lt;br /&gt;
|- &lt;br /&gt;
|width=&amp;quot;50%&amp;quot; | [[Bild:Tutorial Matrix2 ScaleRot.png|framed|center|Skaliert]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Kombination - Scale vor Translate== &lt;br /&gt;
Die Verschiebung ist Abhängig von der Ausrichtung der Achsen (glRotate) und der Maße der Achsen (glScale). Aus diesem Grunde beeinflusst glScale die nachfolgenden Translationen. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|Folgender Code wird demonstriert: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt; &lt;br /&gt;
  glScalef(0.8, 1, 0.6); &lt;br /&gt;
  glTranslatef(3.5,0,-3); &lt;br /&gt;
  ZeichneKoordinatensystem; &lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Ausgangsbild.png|framed|center|Bevor glScale aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Scale.png|framed|center|Nachdem glScale aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 ScaleTrans.png|framed|center|Nachdem glTranslate aufgerufen wurde.]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Der direkte Vergleich zeigt, dass sich die Skalierung auf die Verschiebung auswirkt. Denn obwohl der Verschiebung in die gleiche Richtung und um den selben Wert erfolgt, sind die Resultate nicht identisch. Dies liegt daran, dass glScale die Maße verändert hat. Die Verschiebung in X-Richtung erreicht dadurch nur 80% und in Z-Richtung sogar nur 60% der unskalierten Transformation: &lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|width=&amp;quot;50%&amp;quot; | [[Bild:Tutorial Matrix2 Translate.png|framed|center|Unskaliert]] &lt;br /&gt;
|- &lt;br /&gt;
|width=&amp;quot;50%&amp;quot; | [[Bild:Tutorial Matrix2 ScaleTrans.png|framed|center|Skaliert]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Nachwort= &lt;br /&gt;
7 Stunden sind vorbei und das Tutorial ist auf eine ordentliche Länge angewachsen. Ich hoffe ich konnte euch die OpenGL Matrizen etwas näher bringen. &lt;br /&gt;
&lt;br /&gt;
Wer jetzt denkt ''&amp;quot;Bilder sind mir zu statisch!&amp;quot;'', dem möchte ich noch diese Programme ans Herz legen: &lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|{{Prettytable}}&lt;br /&gt;
!Name&lt;br /&gt;
!Hersteller&lt;br /&gt;
!Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.delphigl.com/forum/viewtopic.php?p=37378#37378 '''Matrix2 - Skizzenrenderer''']&lt;br /&gt;
|Flash&lt;br /&gt;
|Dieses Programm habe ich geschrieben um die Skizzen für dieses Tutorial zu erstellen. Es wurde so modifiziert, dass man beliebige Kombinationen von glTranslate, glRotate und glScale anzeigen kann. &lt;br /&gt;
|-&lt;br /&gt;
|[http://www.phobeus.de/hosting/shared/pixelpracht/main.php?s=opengl&amp;amp;t=1&amp;amp;p=2 '''Matrix Control''']&lt;br /&gt;
|Lithander&lt;br /&gt;
|Das Programm erlaubt euch zu beobachten, wie die Matrizen sich bei den einzelnen Befehlen verändern und wie die Ausgabe aussieht. Besonderheit an diesem Programm ist, dass ihr die Matrizen auch per Hand manipulieren könnt.&lt;br /&gt;
|}&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sollten immer noch Unklarheiten bestehen bleibt das Forum natürlich auch weiterhin die Anlaufstelle Nummer1. Dies betrifft auch euer Feedback zum Tutorial. &lt;br /&gt;
&lt;br /&gt;
MfG &lt;br /&gt;
: Flash ('''Kevin Fleischer''') &lt;br /&gt;
&lt;br /&gt;
{{TUTORIAL_NAVIGATION|[[Tutorial_2D]]|-}} &lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Tutorial|Matrix2]]&lt;/div&gt;</summary>
		<author><name>Phlegmatiker</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_Matrix2&amp;diff=25433</id>
		<title>Tutorial Matrix2</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_Matrix2&amp;diff=25433"/>
				<updated>2011-12-18T09:59:17Z</updated>
		
		<summary type="html">&lt;p&gt;Phlegmatiker: /* Vorwort */  Zahlen bis 12 schreibt man aus.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Matrizen und Matrixmanipulationen= &lt;br /&gt;
&lt;br /&gt;
== Vorwort == &lt;br /&gt;
Willkommen bei meinem zweiten Tutorial.&amp;lt;br&amp;gt; &lt;br /&gt;
In letzter Zeit traten im Forum verstärkt fragen wie ''&amp;quot;Wie positioniere ich Objekte richtig?&amp;quot;'' und ''&amp;quot;Ich komm mit den Matrizen net klar. Könnt ihr helfen?&amp;quot;'' auf. Dies war Anlass für mich ein weiteres Tutorial zum Thema Matrizen zu schreiben. Ich werde versuchen viel mit Bildern und Gleichnissen zu arbeiten. Wer aber das ganze Angebot zum Thema &amp;quot;Matrix&amp;quot; nutzen will sollte ruhig auch einen Blick auf Phobeus Matrixtutorial ([[Tutorial_lektion3]]) und auf den Wikiartikel zum Thema [[Matrix]] werfen.&lt;br /&gt;
&lt;br /&gt;
== Matrizen in OpenGL == &lt;br /&gt;
&lt;br /&gt;
OpenGL kennt 3 Matrizen. Wer OpenGL programmieren will sollte diese auch kennen: &lt;br /&gt;
* '''GL_MODELVIEW''' - Die Modelviewmatrix &lt;br /&gt;
: Die Modelviewmatrix sollte immer dann aktiviert sein, wenn ihr an die Grafikkarte [[Vertex]]daten senden wollt. Diese Matrix wird auf die Position der Vertices, die mit [[glVertex]] gesendet werden angewandt. Ebenso beeinflusst sie die Ausrichtung der [[Normalen]], die mit Hilfe von [[glNormal]] gesetzt werden. Kurz, alles was mit den Objekten eurer Welt zu tun hat, erfordert die Aktivierung dieser Matrix.&lt;br /&gt;
* '''GL_PROJECTION''' - Die Projektionsmatrix &lt;br /&gt;
: Diese Matrix wird selten gebraucht. Sie bestimmt, wie am Ende alles angezeigt wird. Sie bestimmt quasi die Eigenschaften der &amp;quot;Kamera&amp;quot;. &lt;br /&gt;
* '''GL_TEXTURE''' - Die Texturmatrix &lt;br /&gt;
: Diese Matrix wird auf die Texturkoordinaten angewandt, mit der Folge, dass sich die Texturen auf den Oberflächen bewegen.&lt;br /&gt;
&lt;br /&gt;
Diese 3 Matrizen können per [[glMatrixMode]] aktiviert werden. Dabei kann immer nur eine Matrix aktiv sein. Wenn ihr z.B. {{INLINE_CODE|glMatrixMode(GL_MODELVIEW)}} aufgerufen habt, dann sagt man &amp;quot;Die Modelviewmatrix ist die '''''aktuelle Matrix'''''&amp;quot;. Alle Matrixmanipulationen (wir kommen gleich dazu was das ist) wirken sich ''nur'' auf die ''aktuelle Matrix'' aus.&lt;br /&gt;
&lt;br /&gt;
== Kurze Matrixtheorie == &lt;br /&gt;
''Was sind Matrizen?'' &amp;lt;br&amp;gt; &lt;br /&gt;
Matrizen sind aufgebaut wie Tabellen. Das tolle daran ist - man kann damit rechnen. &amp;lt;br&amp;gt; &lt;br /&gt;
''&amp;quot;Gaaaaanz toll! Jetzt rechnen die schon mit Tabellen...&amp;quot;''&amp;lt;br&amp;gt; &lt;br /&gt;
So schlimm ist das gar nicht. Denn das Rechnen übernimmt OpenGL für uns. Ihr müsst nur wissen, dass wann immer ihr einen Befehl wie [[glTranslate]], [[glRotate]] oder [[glScale]] verwendet, ihr eine Matrix mit der ''aktuellen Matrix'' multipliziert. &lt;br /&gt;
{{Hinweis|Wenn ihr wissen wollt, wie man Matrizen miteinander multipliziert, dann lest euch einmal den Artikel &amp;quot;[[Matrix]]&amp;quot; durch und auch das dort verlinkte PDF &amp;quot;CompGeoScript&amp;quot;.}} &lt;br /&gt;
&lt;br /&gt;
== Wie sehen Matrizen aus? == &lt;br /&gt;
In &amp;quot;echt&amp;quot; sehen Matrizen wie Tabellen voller Zahlen aus. &amp;lt;br&amp;gt; &lt;br /&gt;
Will man sich eine Matrix grafisch vorstellen, sollte man sich ein 3 dimensionales Gitter vorstellen. Dieses Gitter ist das Koordinatensystem der Matrix. Wenn ihr mit [[glTranslate]], [[glRotate]] oder [[glScale]] die Matrix manipuliert, dann verändert ihr die Position des Koordinatenursprungs (glTranslate), die Ausrichtung der Achsen (glRotate) oder die Maße (glScale). Im dritten Teil des Tutorials gehe ich auf die Auswirkungen dieser Befehle noch einmal genauer ein. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Die drei OpenGL Matrizen = &lt;br /&gt;
&lt;br /&gt;
== GL_PROJECTION == &lt;br /&gt;
Ich möchte zuerst einmal die Projektionsmatrix vorstellen. Diese Matrix wird meist nur am Rande erwähnt, macht aber einen verdammt wichtigen Job: Sie projeziert den Inhalt der Welt auf den Bildschirm. &lt;br /&gt;
&lt;br /&gt;
Wenn ihr der Projektionsmatrix per [[glLoadMatrix]] eine Matrix zuweist, die nur Nullen enthält, werdet ihr feststellen, dass ihr nichts seht. Ihr habt damit nämlich die Projektionsmatrix ausgeschaltet und da wir ja was sehen wollen, unterlassen wir das in Zukunft lieber ;). &lt;br /&gt;
&lt;br /&gt;
''Aber was kann man dann mit der Projektionsmatrix machen (,außer sie nicht auszuschalten ;-) )?'' &amp;lt;br&amp;gt; &lt;br /&gt;
Bei der Vorstellung der einzelnen Matrizen erwähnte ich bereits die &amp;quot;Kamera&amp;quot;. Um gleich mal eins festzustellen: Ein Objekt &amp;quot;Kamera&amp;quot; existiert nicht. Das einzigste was man von der &amp;quot;Kamera&amp;quot; mitbekommt ist die Ausgabe. Und wie wir gerade gelernt haben ist welcher Teil für die Ausgabe zuständig? Richtig! Die Projektionsmatrix. Sie ist unsere &amp;quot;Kamera&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Kommt jetzt aber bitte nicht auf die Idee, eure Projektionsmatrix per '''glTranslate''' und '''glRotate''' irgendwohin zu bewegen... Das ist nämlich gar nicht die Aufgabe der Projektionsmatrix. Ihre Aufgabe ist &amp;quot;das Abbild für die Ausgabe zu manipulieren&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Im Ausgangszustand ([[glLoadIdentity]] wurde für die Projektionsmatrix aufgerufen), gibt die Projektionsmatrix das Bild der Welt unverändert aus. Wenn man '''glTranslate''' auf die Projektionsmatrix anwendet, dann verschiebt man nicht die Welt, sondern sagt der  Projektionsmatrix, dass sie das gesehene Bild verschieben soll. &lt;br /&gt;
&lt;br /&gt;
Befehle wie [[gluPerspective]] und [[glOrtho]] sind typische Befehle zum einstellen der Projektionsmatrix. Diese Befehle bestimmen nämlich in welcher Form die Ausgabe gemacht wird. Entweder perspektivisch verzerrt (gluPerspective) oder durch Parallelprojektion (glOrtho).&lt;br /&gt;
&lt;br /&gt;
Wenn man die Projektionsmatrix manipuliert, ist das vergleichbar mit dem Austauschen des Objektivs bei einer Kamera. Man könnt sogar über die Projektionsmatrix einen &amp;quot;Fischauge&amp;quot; Effekt erzeugen... (Aber fragt mich bitte nicht, wie die Matrix dazu aussieht... ;-) Falls ihrs wißt, einfach im Forum posten. Ich wäre interessiert.)&lt;br /&gt;
&lt;br /&gt;
== GL_MODELVIEW == &lt;br /&gt;
Wie bereits erwähnt ist die Modelviewmatrix die wichtigste Matrix in der OpenGL Welt, denn sie wirkt sich auf Ausrichtung und Position aller Primitive und damit Objekte in der OpenGL Welt aus. Ohne Daten in der Modelviewmatrix, kann die Projektionsmatrix auch nichts ausgeben. &lt;br /&gt;
&lt;br /&gt;
Wenn ihr [[Vertex]]daten  an die Grafikkarte übermittelt solltet ihr die Modelviewmatrix aktiviert haben. Positionsangaben wie z.B. {{INLINE_CODE|glVertex3f(1,0,1);}} beziehen sich auf das aktuelle Koordinatensystem. Das Koordinatensystem ist quasi der Teil der Matrix mit dem ihr arbeitet, und den ihr euch vorstellen könnt (/müßt.).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie ihr bereits wisst kann man mit den Befehlen [[glTranslate]], [[glRotate]] und [[glScale]] das Koordinatensystem manipulieren. Dadurch seit ihr in der Lage beim &amp;quot;bauen&amp;quot; von Objekten mit &amp;quot;lokalen Koordinaten&amp;quot; zu arbeiten. &lt;br /&gt;
&lt;br /&gt;
=== lokale und globale Koordinaten === &lt;br /&gt;
''Worin unterscheiden sich lokale und globale Koordinaten?'' &amp;lt;br&amp;gt; &lt;br /&gt;
Um diese Frage zu klären bedarf es eines kleinen Beispiels: &lt;br /&gt;
&lt;br /&gt;
Stellt euch vor, ihr wollt zwei Würfel zeichnen. Der eine soll um den Punkt (3,4,5)  mit einer Kantenlänge von 1 erstellt werden, der andere soll um den Punkt (1,2,3) mit Kantenlänge 2 und dazu 30° um die Y-Achse gedreht werden. &lt;br /&gt;
&lt;br /&gt;
Wenn man mit '''globalen''' Koordinaten arbeitet lässt man die Matrix so wie sie ist (verzichtet also auf die 3 genannten Befehle) und schreibt die Koordinaten der Eckpunkte per Hand hin: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;glBegin(GL_QUADS); &lt;br /&gt;
  //Vorderseite erster Würfel &lt;br /&gt;
  glVertex3f(2,5,6); &lt;br /&gt;
  glVertex3f(2,3,6); &lt;br /&gt;
  glVertex3f(4,3,6); &lt;br /&gt;
  glVertex3f(4,5,6); &lt;br /&gt;
  //Nächste Seite &lt;br /&gt;
  [...] &lt;br /&gt;
&lt;br /&gt;
  //Vorderseite zweiter Würfel &lt;br /&gt;
  glVertex3f(0,3,4); &lt;br /&gt;
  glVertex3f(0,1,4); &lt;br /&gt;
  glVertex3f(2,1,4); &lt;br /&gt;
  glVertex3f(2,3,4); &lt;br /&gt;
  [...] &lt;br /&gt;
&lt;br /&gt;
glEnd; &lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Bei '''lokalen''' Koordinaten bewegt man zuerst den Koordinatenursprung an die Stelle an die der Würfel entstehen soll, richtet dann wenn nötig die Achsen entsprechend aus, und kann dann '''lokale''' Koordinaten übergeben. Lokal bedeutet hier relativ zum aktuellen Koordinatensystem. &lt;br /&gt;
&lt;br /&gt;
''Aber was soll das für einen Vorteil haben?'' &amp;lt;br&amp;gt; &lt;br /&gt;
Dem ein oder anderen ist vielleicht aufgefallen, dass wir 2x das selbe Objekt zeichnen sollen. Der einzigste Unterschied besteht in der Position, Ausrichtung und Größe/Scalierung. Um Arbeit zu sparen erstellt man deshalb ein Unterprogramm welches einen Einheitswürfel (Kantenlänge 1) rendert, und ruft vor dem zeichnen einfach die passende Kombination aus glTranslate, glRotate und glScale auf: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;procedure zeichneWuerfel; &lt;br /&gt;
begin &lt;br /&gt;
  glBegin(GL_QUADS); &lt;br /&gt;
    glVertex3f(-0.5, 0.5, 0.5); &lt;br /&gt;
    glVertex3f(-0.5,-0.5, 0.5); &lt;br /&gt;
    glVertex3f( 0.5,-0.5, 0.5); &lt;br /&gt;
    glVertex3f( 0.5, 0.5, 0.5); &lt;br /&gt;
    [...] &lt;br /&gt;
  glEnd; &lt;br /&gt;
end; &lt;br /&gt;
&lt;br /&gt;
begin &lt;br /&gt;
  glPushMatrix; &lt;br /&gt;
    glTranslatef(3,4,5); &lt;br /&gt;
    zeichneWuerfel; &lt;br /&gt;
  glPopMatrix; &lt;br /&gt;
  glPushMatrix; &lt;br /&gt;
    glTranslatef(1,2,3); &lt;br /&gt;
    glRotatef(30,0,1,0); &lt;br /&gt;
    glScalef(2,2,2); &lt;br /&gt;
    zeichneWuerfel; &lt;br /&gt;
  glPopMatrix; &lt;br /&gt;
end; &lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Wie ihr seht, haben lokale Koordinaten den Vorteil, dass man wiederverwendbaren Code schreiben kann. Bei globalen Koordinaten muss für jedes Objekt eigener Code geschrieben werden (und wenn sich das Objekt bewegt dann wieder...).&lt;br /&gt;
&lt;br /&gt;
Dreimal dürft ihr raten, welche Methode häufiger verwendet wird. ;-) &lt;br /&gt;
{{Hinweis|Modeller wie 3D Studio Max benutzen globale Koordinaten beim exportieren der Modelle. Dies hat den Vorteil, dass beim importieren einer ganzen 3DS Szene, die Objekte gleich an der richtigen Position stehen, und nicht erst ausgerichtet werden müssen.}} &lt;br /&gt;
&lt;br /&gt;
== GL_TEXTURE == &lt;br /&gt;
Dieser Matrix sollte endlich mehr Aufmerksamkeit geschenkt werden. Sie kann nämlich mit den Texturen in der Szene einiges anfangen... &lt;br /&gt;
&lt;br /&gt;
Aber der Reihe nach: &lt;br /&gt;
&lt;br /&gt;
Wie ihr vielleicht schon im [[Tutorial_lektion4|Einsteigertutorial 4 - Texturen]] gelesen habt, sind Texturkoordinaten immer so, dass {{INLINE_CODE|[[glTexCoord2f]](0,0)}} die obere linke Ecke und {{INLINE_CODE|glTexCoord2f(1,1)}} die untere Rechte Ecke der Textur betrifft. Wie die Textur außerhalb dieses Bereichs aussieht bestimmt ihr mittels [[glTexParameter]] und dem Parametern '''GL_TEXTURE_WRAP_S''' und '''GL_TEXTURE_WRAP_T'''. &lt;br /&gt;
&lt;br /&gt;
Nun stellt euch einmal vor, ihr habt 2 Quads die beide die selbe Textur bekommen sollen. Einziger Unterschied ist, dass bei dem einen Quad der Inhalt der Textur um 20° in Uhrzeigerrichtung gedreht ist. Blöd, oder? Das heißt ja jetzt, dass ihr in eurem Zeichenprogramm eine weitere Textur erstellen müßt, um das zweite Quad zu texturieren oder die Texturkoordinaten per Hand ändern müsst. &amp;lt;br&amp;gt; &lt;br /&gt;
'''STOP!''' Ihr hab es sicherlich schon mitbekommen: Dieses Szenario kann leicht mit der Texturmatrix gelößt werden. Und zwar so... &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;procedure drawTexturedQuad; &lt;br /&gt;
begin &lt;br /&gt;
  glBegin(GL_QUADS); &lt;br /&gt;
    glTexCoord(0,0); glVertex3f(-1, 1,0); &lt;br /&gt;
    glTexCoord(0,1); glVertex3f(-1,-1,0); &lt;br /&gt;
    glTexCoord(1,1); glVertex3f( 1,-1,0); &lt;br /&gt;
    glTexCoord(1,0); glVertex3f( 1, 1,0); &lt;br /&gt;
  glEnd; &lt;br /&gt;
end; &lt;br /&gt;
&lt;br /&gt;
begin &lt;br /&gt;
  glMatrixMode(GL_MODELVIEW); &lt;br /&gt;
  glBindTexture(GL_TEXTURE_2D, texID); &lt;br /&gt;
  glTranslatef(-2,0,0); &lt;br /&gt;
  drawTexturedQuad; &lt;br /&gt;
&lt;br /&gt;
  glMatrixMode(GL_TEXTURE); &lt;br /&gt;
  glRotatef(20,0,0,1); &lt;br /&gt;
&lt;br /&gt;
  glMatrixMode(GL_MODELVIEW); &lt;br /&gt;
  glTranslatef(4,0,0); &lt;br /&gt;
  drawTexturedQuad; &lt;br /&gt;
end;&amp;lt;/source&amp;gt; &lt;br /&gt;
''Was ist hier geschehn? ''&amp;lt;br&amp;gt;&lt;br /&gt;
Durch die vorherige Aktivierung der Texturmatrix wirkt sich das nachfolgende glRotate nicht auf die Modelle der Szene sondern auf die Texturkoordinaten aus. Auf gut deutsch: OpenGL dreht vor dem rendern des zweiten Quads die Textur um 20°. &lt;br /&gt;
&lt;br /&gt;
Wenn ihr beim rotieren der Texturmatrix, bei jedem Renderdurchlauf den Winkel um ein Stück erhöht passiert was?... Richtig! Eure Textur dreht sich auf eurem Quad... Das is dann quasi eure erste Animation... Und das ohne ein Objekt zu bewegen... Cool, oder?&lt;br /&gt;
&lt;br /&gt;
= Auswirkungen von Matrixmanipulationen - oder &amp;quot;Wie positioniere ich meine Objekte richtig?&amp;quot;= &lt;br /&gt;
In diesem Teil des Tutorials möchte ich euch zeigen wie die 3 Befehle '''glTranslate, glRotate''' und '''glScale''' eure aktuelle Matrix verändern. Ich bleibe hierbei im 2 dimensionalen Raum, da sonst die Skizzen zu unübersichtlich werden. (Die Befehle sind dabei natürlich die selben wie für 3D Manipulationen. Ich ignoriere nur einfach immer die Y-Angaben.) &lt;br /&gt;
&lt;br /&gt;
Zuersteinmal zum warm werden: &amp;lt;br&amp;gt; &lt;br /&gt;
[[Bild:Tutorial Matrix2 Ausgangsbild.png|framed|center|So stelle ich mir eine 2D-Matrix vor.]] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==glTranslate== &lt;br /&gt;
{{INLINE_CODE|[[glTranslate]](a,b,c)}} verschiebt den Koordinatenursprung des aktuellen Koordinatensystems um ''a'' Einheiten in die Richtung der X-Achse, um ''b'' Einheiten in die Richtung der Y-Achse und um ''c'' Einheiten in die Richtung der Z-Achse. &lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutorial Matrix2 Translate.png|framed|center|Das passiert bei einer Translation um 3.5 Einheiten in X und -3 Einheiten in Z-Richtung.]] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==glRotate== &lt;br /&gt;
{{INLINE_CODE|[[glRotate]](w,x,y,z)}} rotiert das Koordinatensystem um ''w'' Grad um die Rotationsachse welche durch (0,0,0) und (''x,y,z'') verläuft. '''glRotate richtet also die Achsen neu aus.''' (Die Richtung der Achsen ist z.B. wichtig für glTranslate) &lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutorial Matrix2 Rotate.png|framed|center|Das passiert bei einer Rotation um 45° mit der Y-Achse als Rotationsachse.]]&lt;br /&gt;
&lt;br /&gt;
==glScale== &lt;br /&gt;
{{INLINE_CODE|[[glScale]](x,y,z)}} skaliert die Maße der Koordinatenachsen (Bestimmt also wie lange &amp;quot;eine Einheit&amp;quot; wirklich ist). Wenn ''x,y'' oder ''z'' größer als 1 ist, werden die Maßeinheiten der entsprechenden Achse gestreckt, wenn die Werte kleiner 1 sind gestaucht. (Wenn die Werte gleich 0 sind verschwindet die Szene auf nimmer wieder sehn(, da hilft dann nur noch glLoadIdentity um die Matrix wieder nutzbar zu machen), sind die Werte gleich 1 verändert sich nichts.) &lt;br /&gt;
&lt;br /&gt;
''x,y'' und ''z'' muss man sich als Prozentangaben vorstellen. Will man die Szene in X-Richtung um das doppelte (also 200%) vergrößern/strecken muss ''x'' gleich 2 sein. Will man die Y-Richtung auf ein Zehntel (also 10%) verkürzen/stauchen muss ''y'' gleich 0.1 sein. &lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutorial Matrix2 Scale.png|framed|center|Das passiert bei einer Skalierung. Wie ihr seht, sind die Seiten unterschiedlich skaliert worden (X-Achse: 80%, Z-Achse: 60%).]] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Kombination - Translate vor Rotate== &lt;br /&gt;
Wird Translate vor Rotate aufgerufen, bewegt sich der Koordinatenursprung zuerst an den Zielpunkt (über glTranslate angegeben). Anschließend werden die Achsen neu ausgerichtet (durch glRotate). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|Folgender Code wird demonstriert: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt; &lt;br /&gt;
  glTranslatef(3.5,0,-3); &lt;br /&gt;
  glRotatef(45, 0, 1, 0); &lt;br /&gt;
  ZeichneKoordinatensystem; &lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Ausgangsbild.png|framed|center|Bevor glTranslate aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Translate.png|framed|center|Nachdem glTranslate aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 TranslateRot.png|framed|center|Nachdem glRotate aufgerufen wurde. Man sieht, dass die jeweils vorhergehende Veränderung bestehend bleibt, und die Basis für die nachfolgende Änderung bildet.]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wird der Winkel von glRotate bei jedem Renderdurchlauf erhöht, dreht sich ein anschließend gezeichnetes Objekt um die durch glTranslate angegeben Position. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Kombination - Rotate vor Translate== &lt;br /&gt;
Wird Rotate vor Translate aufgerufen, werden zuerst die Achsen neu ausgerichtet und dann der Koordinatenursprung bezüglich dieser neuen Achsen verschoben. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|Folgender Code wird demonstriert: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt; &lt;br /&gt;
  glRotatef(45, 0, 1, 0); &lt;br /&gt;
  glTranslatef(3.5,0,-3);   &lt;br /&gt;
  ZeichneKoordinatensystem; &lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Ausgangsbild.png|framed|center|Bevor glRotate aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Rotate.png|framed|center|Nachdem glRotate aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 RotateTrans.png|framed|center|Nachdem glTranslate aufgerufen wurde. Man sieht, dass die vorhergehende Rotation die Verschieberichtung beeinflusst.]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Wird der Winkel von glRotate bei jedem Renderdurchlauf erhöht, bewegt sich ein nach glTranslate gezeichnetes Objekt auf einer Kreisbahn um den Koordinatenursprung wie er beim Aufruf von glRotate aktuell war. Der Radius der Kreisbahn wird durch glTranslate bestimmt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wenn man die beiden Ergebnisse direkt vergleicht sieht man, dass die Reihenfolge von Bedeutung für das Ergebniss ist. Das die Unterschiede so &amp;quot;klein&amp;quot; ausfallen liegt nur daran, dass bei rotate nicht mit größeren Winkeln rotiert wurde. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|width=&amp;quot;50%&amp;quot; | [[Bild:Tutorial Matrix2 RotateTrans.png|framed|center|Erst Rotiert]] &lt;br /&gt;
|- &lt;br /&gt;
|width=&amp;quot;50%&amp;quot; | [[Bild:Tutorial Matrix2 TranslateRot.png|framed|center|Erst Verschoben]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kombination - Scale vor Rotate== &lt;br /&gt;
Die Rotation wird nur von der Richung, nicht aber der Länge der Achsen beeinflusst. Der Winkel um den gedreht wird, bleibt von der Skalierung unberührt (45° bleiben 45°. Die Achsen zeigen anschließend jeweils in die gleiche Richtung) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|Folgender Code wird demonstriert: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt; &lt;br /&gt;
  glScalef(0.8, 1, 0.6); &lt;br /&gt;
  glRotatef(45, 0, 1, 0); &lt;br /&gt;
  ZeichneKoordinatensystem; &lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Ausgangsbild.png|framed|center|Bevor glScale aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Scale.png|framed|center|Nachdem glScale aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 ScaleRot.png|framed|center|Nachdem glRotate aufgerufen wurde. Man sieht, dass die Skalierung den Winkel nicht beeinflusst. Das Koordinatensystem wurde korrekt um 45° gedreht.]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Der direkte Vergleich zeigt, dass die Skalierung keinen Effekt auf den Winkel hatte. Beide Koordinatensysteme sind gleich ausgerichtet: &lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|width=&amp;quot;50%&amp;quot; | [[Bild:Tutorial Matrix2 Rotate.png|framed|center|Unskaliert]] &lt;br /&gt;
|- &lt;br /&gt;
|width=&amp;quot;50%&amp;quot; | [[Bild:Tutorial Matrix2 ScaleRot.png|framed|center|Skaliert]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Kombination - Scale vor Translate== &lt;br /&gt;
Die Verschiebung ist Abhängig von der Ausrichtung der Achsen (glRotate) und der Maße der Achsen (glScale). Aus diesem Grunde beeinflusst glScale die nachfolgenden Translationen. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|Folgender Code wird demonstriert: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt; &lt;br /&gt;
  glScalef(0.8, 1, 0.6); &lt;br /&gt;
  glTranslatef(3.5,0,-3); &lt;br /&gt;
  ZeichneKoordinatensystem; &lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Ausgangsbild.png|framed|center|Bevor glScale aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 Scale.png|framed|center|Nachdem glScale aufgerufen wurde.]] &lt;br /&gt;
|- &lt;br /&gt;
|[[Bild:Tutorial Matrix2 ScaleTrans.png|framed|center|Nachdem glTranslate aufgerufen wurde.]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Der direkte Vergleich zeigt, dass sich die Skalierung auf die Verschiebung auswirkt. Denn obwohl der Verschiebung in die gleiche Richtung und um den selben Wert erfolgt, sind die Resultate nicht identisch. Dies liegt daran, dass glScale die Maße verändert hat. Die Verschiebung in X-Richtung erreicht dadurch nur 80% und in Z-Richtung sogar nur 60% der unskalierten Transformation: &lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; &lt;br /&gt;
{|{{Prettytable}} &lt;br /&gt;
|width=&amp;quot;50%&amp;quot; | [[Bild:Tutorial Matrix2 Translate.png|framed|center|Unskaliert]] &lt;br /&gt;
|- &lt;br /&gt;
|width=&amp;quot;50%&amp;quot; | [[Bild:Tutorial Matrix2 ScaleTrans.png|framed|center|Skaliert]] &lt;br /&gt;
|}&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Nachwort= &lt;br /&gt;
7 Stunden sind vorbei und das Tutorial ist auf eine ordentliche Länge angewachsen. Ich hoffe ich konnte euch die OpenGL Matrizen etwas näher bringen. &lt;br /&gt;
&lt;br /&gt;
Wer jetzt denkt ''&amp;quot;Bilder sind mir zu statisch!&amp;quot;'', dem möchte ich noch diese Programme ans Herz legen: &lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|{{Prettytable}}&lt;br /&gt;
!Name&lt;br /&gt;
!Hersteller&lt;br /&gt;
!Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.delphigl.com/forum/viewtopic.php?p=37378#37378 '''Matrix2 - Skizzenrenderer''']&lt;br /&gt;
|Flash&lt;br /&gt;
|Dieses Programm habe ich geschrieben um die Skizzen für dieses Tutorial zu erstellen. Es wurde so modifiziert, dass man beliebige Kombinationen von glTranslate, glRotate und glScale anzeigen kann. &lt;br /&gt;
|-&lt;br /&gt;
|[http://www.phobeus.de/hosting/shared/pixelpracht/main.php?s=opengl&amp;amp;t=1&amp;amp;p=2 '''Matrix Control''']&lt;br /&gt;
|Lithander&lt;br /&gt;
|Das Programm erlaubt euch zu beobachten, wie die Matrizen sich bei den einzelnen Befehlen verändern und wie die Ausgabe aussieht. Besonderheit an diesem Programm ist, dass ihr die Matrizen auch per Hand manipulieren könnt.&lt;br /&gt;
|}&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sollten immer noch Unklarheiten bestehen bleibt das Forum natürlich auch weiterhin die Anlaufstelle Nummer1. Dies betrifft auch euer Feedback zum Tutorial. &lt;br /&gt;
&lt;br /&gt;
MfG &lt;br /&gt;
: Flash ('''Kevin Fleischer''') &lt;br /&gt;
&lt;br /&gt;
{{TUTORIAL_NAVIGATION|[[Tutorial_2D]]|-}} &lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Tutorial|Matrix2]]&lt;/div&gt;</summary>
		<author><name>Phlegmatiker</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tool&amp;diff=25381</id>
		<title>Tool</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tool&amp;diff=25381"/>
				<updated>2011-08-16T16:43:24Z</updated>
		
		<summary type="html">&lt;p&gt;Phlegmatiker: totel Links entfernt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Kostenlose Tools ==&lt;br /&gt;
&lt;br /&gt;
Kostenlose für OpenGL/3D-Spieleprogrammierung/3D-Grafik relevante Tools und Programme.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== OpenGL ===&lt;br /&gt;
{| {{Prettytable_B1}}&lt;br /&gt;
!width=&amp;quot;25%&amp;quot;| Name, Link&lt;br /&gt;
!width=&amp;quot;75%&amp;quot;| Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
![http://www.realtech-vr.com/glview/ GLView]&lt;br /&gt;
|Tool welches Informationen über die auf einem Rechner vorhandene GL Implementation extrahiert und anzeigt. Unter anderem von welchem Hersteller die Implementation stammt und welche Extensions/GL-Version unterstützt wird.&lt;br /&gt;
|-&lt;br /&gt;
![http://delphi3d.net/hardware/index.php GLinfo]&lt;br /&gt;
|Tool welches Informationen über die auf einem Rechner vorhandene GL Implementation extrahiert und anzeigt. Es werden auch technische Informationen wie maximal zulässige Texturgröße angezeigt. Das Tool generiert ein Logfile was, wenn gewünscht, auch in die '''OpenGL Hardware Registry''' eingetragen werden kann.&lt;br /&gt;
|-&lt;br /&gt;
![http://www.gremedy.com/ gDEBugger]&lt;br /&gt;
| Mächtiger OpenGL/OpenCL Debugger, Profiler und Memory Analyzer.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Mathematik/Physik ===&lt;br /&gt;
{| {{Prettytable_B1}}&lt;br /&gt;
!width=&amp;quot;25%&amp;quot;| Name, Link&lt;br /&gt;
!width=&amp;quot;75%&amp;quot;| Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
![http://www.amd.com/acml/ ACML]&lt;br /&gt;
| Bibliothek mit hochoptimierten Befehlen für Mathematische Berechnungen (C++, gut dokumentiert, AMD-optimiert)&lt;br /&gt;
|-&lt;br /&gt;
! [http://math-atlas.sourceforge.net/ ATLAS]&lt;br /&gt;
| Bibliothek basierend auf BLAS und LAPACK (C++/Fortran)&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.netlib.org/blas/ BLAS]&lt;br /&gt;
| Bibliothek mit optimierten Befehlen für lineare Algebra (Fortran 77)&lt;br /&gt;
|- &lt;br /&gt;
! [http://www.partow.net/projects/fastgeo/index.html FastGeo]&lt;br /&gt;
| Bibiothek mit optimierten mathematischen Funktionen die direkt für Delphi/FreePascal entwickelt wurde. Prozedural aufgebaut (nicht OOP)&lt;br /&gt;
|- &lt;br /&gt;
! [http://www.fftw.org/ FFTW]&lt;br /&gt;
| Bibliothek mit optimierten Befehlen für FFTs (als DLL mit C++/Pascal-Header erhältlich)&lt;br /&gt;
|- &lt;br /&gt;
! [http://www.netlib.org/lapack/ LAPACK]&lt;br /&gt;
| Bibliothek mit optimierten Befehlen für lineare Algebra (Fortran 77)&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.nvidia.de/object/nvidia_physx_de.html PhysX Engine]&lt;br /&gt;
| Eine der größten Physik-Engines&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== 2D/Texturen-Tools ===&lt;br /&gt;
&lt;br /&gt;
{| {{Prettytable_B1}}&lt;br /&gt;
!width=&amp;quot;25%&amp;quot;| Name, Link&lt;br /&gt;
!width=&amp;quot;75%&amp;quot;| Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.lmnopc.com/bitmapfontbuilder/ Bitmap Font Builder] &lt;br /&gt;
| Erstellt 2D-Fonttexturen, mit diversen Einstellungsmöglichkeiten. Exportiert zudem auch noch die Dimensionen der Buchstaben.&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.saschawillems.de/?page_id=253 Explosion Texture Generator]&lt;br /&gt;
| Erstellt eine 2D-Textur mit einer animierten Explosion. Ideal für animierte Billboard-Explosionen.&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.planetside.co.uk/terragen/ Terragen]&lt;br /&gt;
| Ein besseres Tool zum Erstellen realistischer Skybox-Texturen gibt es nicht.&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.planetside.co.uk/terragen/tg2/tech_preview.shtml Terragen 2 Technology Preview]&lt;br /&gt;
| Obwohl noch die Technology Preview schon gut geeignet um sowohl Skyboxes als auch Terrain-Texturen mit Normalmaps zu rendern.&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.saschawillems.de/?page_id=92 TerrTexGen]&lt;br /&gt;
| Tool zur Erstellung von Terraintexturen. Oft und gerne genutzt.&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.bundysoft.com/L3DT/ L3DT]&lt;br /&gt;
| Der 'Large 3D Terrain Generator' (L3DT) erzeugt hochwertige 16bit Graustufen [[Heightmap|Heightmaps]] sowie Alphamaps und darf auch in der kostenlosen Version kommerziell genutzt werden.&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.texturesynthesis.com/texture.htm MRFsynthesis]&lt;br /&gt;
| Automatische Generierung von hochwertigen, kachelbaren Texturen mit beliebiger Auflösung aus Fotos oder anderen Quelltexturen. Ausführliche Beschreibung im [[Texturesynthesis|Texturesynthesis-Artikel]].&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.logarithmic.net/pfh/resynthesizer Resynthesizer]&lt;br /&gt;
| Ein Plugin für '''GIMP''' mit ähnlichen Funktionen wie '''MRFsynthesis''', jedoch mehr Features und höherer Geschwindigkeit. Ausführliche Beschreibung im [[Texturesynthesis|Texturesynthesis-Artikel]].&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.gimp.org/ GIMP]&lt;br /&gt;
| GNU Image Manipulation Tool. Gutes kostenloses Bildbearbeitungsprogramm das sich nicht unbedingt vor Photoshop &amp;amp; Co. (mal abgesehen von der UI) verstecken muss.&lt;br /&gt;
|-&lt;br /&gt;
! [http://web.bethere.co.uk/terabit/ Tattoo]&lt;br /&gt;
| Ein sog. 3D-Paint Tool, mit dem man direkt auf ein Modell zeichnen kann und so Texturen erstellen kann. Besonders für Leute die Probleme haben 2D-Texturen für komplexe Modelle zu erstellen ein tolles Programm. Das Tool unterstützt viele Modell- und Texturformate und ist für die nicht-kommerzielle Nutzung umsonst.&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.lysator.liu.se/~kand/caustics/ Caustics Generator]&lt;br /&gt;
| Ein sehr schönes Programm, dass Relief-Texturen aller Colleur erzeugen kann. Das Programm eignet sich auch zum automatischen Berechnen animierter Sequenzen, wie zum Beispiel einer Wasserbewegung in 30 Frames. Sowohl die Ränder als auch die Übergänge zeitlich werden so erstellt, dass alle Übergänge fließend wirken.&lt;br /&gt;
|-&lt;br /&gt;
! [http://neotextureedit.sourceforge.net/index.html NeoTextureEdit]&lt;br /&gt;
| NeoTextureEdit ist ein einfach zu benutzender, graphenbasierter OpenSource-Textureditor/-generator. Auf Basis von kontinuierlichen Funktionen und Filtern kann man Texturen beliebiger Größe und Auflösung erzeugen.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== 3D-Tools ===&lt;br /&gt;
&lt;br /&gt;
{| {{Prettytable_B1}}&lt;br /&gt;
!width=&amp;quot;25%&amp;quot;| Name, Link&lt;br /&gt;
!width=&amp;quot;75%&amp;quot;| Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.delgine.com/ DeleD]&lt;br /&gt;
| Mit Delphi entwickelter 3D-Editor, der speziell auf Spieleentwickler ausgerichtet ist. Zwar noch in Entwicklung, aber bereits mehr als brauchbar.&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.anim8or.com/ Anim8or]&lt;br /&gt;
| Kostenloser 3D-Modeller, allerdings fehlen (noch) einige nützliche Features wie z.B. UVW-Mapping.&lt;br /&gt;
|-&lt;br /&gt;
! [http://sourceforge.net/projects/wings/ Wings 3D]&lt;br /&gt;
| Freeware Polygon Modeller. Obwohl ihm noch einige Features fehlen, ist er einen Blick wert.&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.blender3d.org/ Blender3D]&lt;br /&gt;
| Sehr ausgereiftes und komplexes 3D Tool mit frei gestaltbarer Oberfläche. &lt;br /&gt;
* [http://blendpolis.serverpool.org/f/article.php blend.polis]- Deutsche Blender Seite mit Tutorials&lt;br /&gt;
* umfangreiches [http://www.trcoding.de/informatik/blender/index.html Einsteiger Tutorial]&lt;br /&gt;
* '''sehr gute''' [http://blenderunderground.com/category/video-tutorials/ Video-Tutorials] (englisch)&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.fluidstudios.com/ FSRad]&lt;br /&gt;
|Auf Lightmaps spezialisierter Radiosity Prozessor. &lt;br /&gt;
|-&lt;br /&gt;
! [http://www.delphigl.com/forum/viewtopic.php?t=2421 gl3ds]&lt;br /&gt;
| '''3ds''' Model-Loader (DGL-Projekt)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Shaderentwicklung  ===&lt;br /&gt;
&lt;br /&gt;
{| {{Prettytable_B1}}&lt;br /&gt;
!width=&amp;quot;25%&amp;quot;| Name, Link&lt;br /&gt;
!width=&amp;quot;75%&amp;quot;| Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.ati.com/developer/rendermonkey/index.html RenderMonkey 1.5]&lt;br /&gt;
| ATI's HLSL-Shader IDE. Jetzt auch endlich mit Support für glSlang.&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.opengl.org/sdk/tools/ShaderDesigner/ OpenGL Shader Designer]&lt;br /&gt;
| Gute Shader IDE für glSlang.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Sound ===&lt;br /&gt;
&lt;br /&gt;
{| {{Prettytable_B1}}&lt;br /&gt;
!width=&amp;quot;25%&amp;quot;| Name, Link&lt;br /&gt;
!width=&amp;quot;75%&amp;quot;| Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.buzzmachines.com/ BUZZ]&lt;br /&gt;
| Komplettes Soundstudio für E-Sounds. Es existieren unmengen Plugins welche das verhalten von allen denkbaren Soundeffekten und Soundgeneratoren imitieren können.&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.bluemoon.ee/history/scwin/index.html Sound Club]&lt;br /&gt;
| Eine Art &amp;quot;Tracker&amp;quot; mit recht vielen Features, der dass Erstellen von Musik einfach macht. War mal Shareware, ist inzwischen aber als Freeware erhältlich.&lt;br /&gt;
|-&lt;br /&gt;
! [http://www-personal.monash.edu.au/~myless/catnap/pamela/index.html PAMELA]&lt;br /&gt;
| Vergleicht in Waveform abgespeicherte Sprache mit einem eingegebenem Text und ermittelt an welchem Zeitpunkt welche Laute vorkommen, und erstellt daraus eine Liste. Mit Hilfe dieser Liste kann man seine Figuren lippensynchron animieren.&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.madtracker.org/ MadTracker]&lt;br /&gt;
| Sehr ausgereifter, professioneller Tracker. Kann auch FastTracker-Module (*.xm) bearbeiten. Wer modulbasierte Musik in seinen Programmen nutzen will, sollte sich MadTracker auf jeden Fall ansehen.&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.modplug.com/ ModPlugTracker]&lt;br /&gt;
| Sehr ausgereifter und vielseitiger Tracker. Kann alle gängigen Module (*.mod, *.nst, *.s3m, *.stm, *.xm, *.it, *.mtm, *.okt, *.mdl, *.669, *.far) bearbeiten, sowie Midis und Waves importieren und exportieren. Auch einen Download wert: ModPlugPlayer, der kleine Bruder vom Tracker, der die oben genannten Module abspielen kann und das mit einer Vielzahl von Funktionen. So kann z.B. der Resampling-Mode eingestellt werden, oder die Geschwindigkeit des abgespielten Mods, sowie die Tonhöhe über Schieberegler verändern. Die beiden Programme können auch komprimierte Mods (*.mdz, *.s3z, *.xmz, *.itz), sowie die Unreal-Module (*.utx) bearbeiten.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Programmierung/IDE/Allgemein ===&lt;br /&gt;
&lt;br /&gt;
{| {{Prettytable_B1}}&lt;br /&gt;
!width=&amp;quot;25%&amp;quot;| Name, Link&lt;br /&gt;
!width=&amp;quot;75%&amp;quot;| Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.prestosoft.com/ps.asp?page=edp_examdiff ExamDiff]&lt;br /&gt;
| Beschreibung: Visuelles Vergleichsprogramm für Text/Quellcode Dateien um Veränderungen an solchen Dateien zu suchen. (Freeware nur Pro Version kostenpflichtig)&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.gexperts.org/ GExperts]&lt;br /&gt;
| Geniale IDE-Erweiterung (inkl. diverser Tools) um die Produktivität bzw. Funktionalität von Delphi zu verbessern/erweitern. &lt;br /&gt;
|-&lt;br /&gt;
! [http://www.automatedqa.com/downloads/memproof.asp MemProof]&lt;br /&gt;
| Ein Tool für diverse Borland Entwicklungsumgebungen, welches nach Speicherlecks sucht.&lt;br /&gt;
|-&lt;br /&gt;
! [http://www.winmerge.org/ WinMerge]&lt;br /&gt;
| Externes Datei-Vergleichen zum visuellen Zusammenführen von Konflikten.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Phlegmatiker</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_GLScene&amp;diff=25327</id>
		<title>Tutorial GLScene</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_GLScene&amp;diff=25327"/>
				<updated>2011-07-30T11:07:32Z</updated>
		
		<summary type="html">&lt;p&gt;Phlegmatiker: /* Installation(das Grauen...) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=GlScene Tutorial=&lt;br /&gt;
==Vorwort==&lt;br /&gt;
&lt;br /&gt;
GLScene ist eine wirklich geniale Komponentensammlung, um schnell z.B. einen Editor für die eigene Engine zu proggen. Aber schon die Installation ist so komplex, dass einige daran scheitern. Ich habe auch eine Weile (ca. 3 Stunden nur für die Installation) gebraucht. Darum liefere ich hier eine kleine Einführung in GLScene (exklusiv für DelphiGL.com ;-)). Habe ein bisschen dafür gebraucht, weil wieder mal ein paar Lehrer eine „Schreibt-mal-schnell-eine-zweiseitige-Abhandlung-Phase“ hatten. Aber schließlich bin ich doch noch fertig geworden. Diese Anleitung ist für totale Einsteiger - Fortgeschrittene und Profis werden nix Neues erfahren. Da ich kein Freund großer Worte bin, fange ich einfach mal an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Installation (so wie bei jedem andern Package auch)==&lt;br /&gt;
&lt;br /&gt;
* im $(BDS)\Lib oder $(DELPHI)\Lib Ordner einen GLScene Ordner anlegen und entweder GLScene da hinein auschecken oder die Archive die man von sf.net beziehen kann dort hin entpacken. Dann sollten Strukturen wie diese hier entstehen: ..\Lib\GLScene\Source, ..\Lib\GLScene\Source\Base, ..\Lib\GLScene\Demos, ... und so weiter&lt;br /&gt;
&lt;br /&gt;
* Delphi starten&lt;br /&gt;
&lt;br /&gt;
* Dann entscheidet man sich, möchte man GLScene generell immer verfügbar haben oder doch nur für bestimmte Projekte. Falls man es generell verfügbar haben möchte, schließt man alle offenen Projekte und geht in die Optionen, Verzeichnisse &amp;amp; Bedingungen (Directories &amp;amp; Conditionals) und fügt bei den Suchpfaden sämtliche Ordner und Unterordner des Source Verzeichnisses von GLScene hinzu.&lt;br /&gt;
&lt;br /&gt;
* Man durchsucht das GLScene Verzeichnis nach dlls, es sollten ansich 4 Stück sein. FMod, Bass, ODE und öhm noch irgendeine andere :) - Diese kopiert man entweder in den %SYSTEMROOT%\System32 (aufnem 32Bit Windows) oder ins %SYSTEMROOT%\SysWOW64 (aufnem 64bit Windows), damit Delphi auch die Einstiegspunkte für externe Funktionen finden kann. Später reichts die dlls mit in das Verzeichnis zu packen wo die fertige .exe deines Programms liegt. &lt;br /&gt;
&lt;br /&gt;
* Je nach Delphiversion öffnet man dann aus dem GLScene\ Verzeichnis das passende Package. Im Fall von Delphi 14 (D2010) zuerst das GLScene_RunTime.dproj, dann das jeweilige DesignTime Package zum installieren der eigentlich Komponenten.&lt;br /&gt;
&lt;br /&gt;
* Das gleiche kann man dann auch mit den zusätzlichen Packages durchführen. Für die Cg Shader Komponenten ist das Nvidia Cg SDK von nöten, da dlls benötigt werden die diesem SDK beiliegen.&lt;br /&gt;
&lt;br /&gt;
==Erste Schritte==&lt;br /&gt;
&lt;br /&gt;
Als erstes fügen wir eine Komponente mit dem schönen Namen GLScene ([[Bild:Tutorial GLScene html m2fc1a926.png]]) ein. Das ist das wichtigste aller Objekte und wird in allen euren GLScene-Programmen vorkommen. Mit einem Doppelklick darauf seht ihr den Grundaufbau eurer Szene:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutorial GLScene html 74dd1768.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle Bestandteile eurer Szene werden in GLScene nach Cameras und Scene objects eingeordnet. Um euch einen Überblick über die von GLScene bereitgestellten Objekte zu verschaffen, macht ihr einen Rechtsklick auf Scene objects und geht dann auf Add object. Die meisten von den Einträgen hier erklären sich von selbst und wenn sie es nicht gleich tun, dann nach einigem Ausprobieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anschließend setzen wir noch einen GLSceneViewer ([[Bild:Tutorial GLScene html m27e37d40.png]]) ins Formular. Standardmäßig ist er nur 100x100 groß, also stellen wir in den Eigenschaften des GLSceneViewers Align auf alClient. Wie der Name schon sagt, ist der GLSceneviewer das Objekt, das die Szene (aus dem Objekt GLScene) auf den Bildschirm bringt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nun können wir das Programm einfach mal starten:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutorial GLScene html cffa458.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Juhu! Es lässt sich [hoffentlich] compilieren (bei einem OpenGL-Init ohne GLScene käme das, bei mir jedenfalls, fast einem Wunder gleich ;-)). Aber was sehen unsere entzündeten Augen da? Das Formular ist ja ganz leer! Nun, anscheinend ist die Initialisierung doch nicht so einfach. Es fehlt noch eine Kamera, die, mit dem GLSceneviewer verknüpft, unsere Szene anzeigt. Wer gut aufgepasst hat, sieht wahrscheinlich gleich, was zu tun ist (Den anderen gibt`s was auf die Finger!). Mit einem Doppelklick auf [[Bild:Tutorial GLScene html m2fc1a926.png]] öffnen wir das „Inhaltsverzeichnis“ unserer Szene. Es folgt ein Rechtsklick auf Cameras und dann auf Add Camera. Schon ist die Kamera in unserer Szene implementiert. Jetzt muss unserem GLSceneviewer nur noch gesagt werden, über welche Kamera er die Szene darstellen soll, denn bei größeren Programmen gibt es oft mehrere Kameras. Dazu klicken wir auf den GlSceneviewer und stellen in den Eigenschaften Camera auf GLCamera1 ein. Nach einem weiteren Compilieren stellen wir fest, dass sich immer noch nichts tut. Das liegt daran, dass sich ja noch nichts in der Szene befindet, was darzustellen wäre. Deshalb fügen wir jetzt einfach per Scene objects -&amp;gt; Add object -&amp;gt; Basic geometry &amp;gt; Sphere im GlScene – Dialog eine Kugel ein. Dann fehlt nur noch, dass wir die Camera ein wenig verschieben, da sie sich standardmäßig mitten in der Kugel an dem Punkt 0|0|0 befindet. Also stellen wir die Eigenschaft Position von der Camera ein wenig anders ein. Zu guter letzt definieren wir unsere Kugel als Zielobjekt (TargetObject), auf das die Kamera gerichtet sein soll. Das Ergebnis:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutorial GLScene html m151172de.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Demotivierend, nicht? Naja, wenigstens ist was Rundes da. Das kommt daher, dass wir noch keine Lichtquelle definiert haben. Inzwischen dürfte der Weg aber klar sein: GLScene1 -&amp;gt; Scene objects -&amp;gt; Rechtsklick -&amp;gt; Add object -&amp;gt; LightSource. Dann verschieben wir noch schnell die Lichtquelle, wie immer mit einer kleinen Veränderung der Positionseigenschaft. Und schon haben wir unsere erste Szene fertig:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutorial GLScene html 17961123.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Immer noch sehr schlicht, aber man muss natürlich den Arbeitsaufwand mit dem eines normalen Inits vergleichen, um jetzt darüber zu urteilen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wer durch unsere bisherigen (optischen) Ergebnisse etwas demotiviert wurde, dem verordne ich dringend mal einen Besuch im GLScene - Ordner Demos/bench/... !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Zusätzliches==&lt;br /&gt;
&lt;br /&gt;
Natürlich gibt es noch weitere Features, von denen ich hier mal ein paar aufzählen möchte:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alles, was die Szene indirekt kosmetisch beeinflusst, ist bei der Eigenschaft Buffer des GLSceneViewers zu finden:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutorial GLScene html m549c3f82.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die meisten dürften sich selbst erklären. Da dies aber ein Tutorial für Anfänger sein soll, mal eine kleine Aufzählung:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:AntiAliasing: Wird verwendet, um pixelige Stufen zu vermeiden. Man hat hier mehrere Stufen zur Auswahl, die jeweilige Unterstützung hängt von der Grafikkarte und ihren Treibern ab.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutorial GLScene html m3d75de8.png|center]]&lt;br /&gt;
&lt;br /&gt;
::Das umrahmte Bild zeigt eine „antialiasierte“ (grausam, dieses Wort, nicht?) Kugel. AntiAliasing hat aber den Nachteil, dass es den PC zum Teil enorm verlangsamen kann, sofern man nicht eine Grafikkarte von ATI ab einer Radeon 9500 Pro besitzt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:BackgroundColor: Legt, wie könnte es anders sein, die Hintergrundfarbe des GLSceneViewers fest.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:ColorDepth: Hier kann man, wie bei den Desktop-Eigenschaften die Farbtiefe der Darstellung anpassen. Standard sind, glaube ich, 32 Bit (cddefault)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:ContextOptions: Hier können Veränderungen am Rendering-Kontext vorgenommen werden, wie z.B. der StencilBuffer aktiviert werden etc...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:DepthPrecision: Hat mehr oder weniger die gleiche Funktion wie ColorDepth.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:FaceCulling: Zeichnet nur die Vorderseiten von Objekten und bringt so mehr Frames. (Dazu gibt’s ein DGL – Tutorial)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:FogEnable: Aktiviert Nebel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:FogEnvironment: Die Optionen des Nebels:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:FogColor: Hmm.. *scharf nachdenk* ach ja, Farbe des Nebels ;-)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:FogDistance: Legt fest, ob sich der Nebel kreis- oder würfelförmig um den Betrachter ausbreiten soll.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:FogEnd: Bestimmt die Entfernung zum Betrachter, ab der nichts mehr zu sehen ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:FogLinear: Dazu gibt’s schon ein Tutorial (von Lithander).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:FogStart: Gegenpart zu FogEnd und legt den Abstand zum Betrachter fest, ab dem der Nebel beginnt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:Lighting: Aktiviert/Deaktiviert alle Lichtquellen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:ShadeModel: Wie schön rund sollen z.B. Kugeln werden?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als nächstes möchte ich mit euch noch einige Optionen der Objekte selbst durchgehen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:Bottom (bei Kugeln): Hier kann man bestimmen, ob und wie die Kugel „beschnitten“ werden soll (mir ist hier nix Besseres eingefallen), am besten einfach mal Werte wie -20 eingeben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:Material: Mit einem Klick auf ... öffnet man den Material Editor:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutorial GLScene html m7dc9f971.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::Das hier ist mal das Texturfenster. Hier kann man ein Bild als Textur laden. Anschließend hat man einige Optionen zur Verfügung, am besten probiert ihr einfach mal ein bisschen rum, um die verschiedenen Effekte zu genießen. Wichtig ist nur, dass das Häkchen bei Disabled entfernt ist, da sonst keine Textur dargestellt wird (wird immer wieder gern vergessen). Ansonsten gibt’s halt noch die Register Front und Back, deren Optionen sich auch selbst erklären dürften. Um einfach die Farbe des Objekts zu verändern, geht man meist auf Front -&amp;gt; Diffuse.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:PitchAngle, RollAngle, TurnAngle: die Drehung des Objekts in um die Z-(PitchAngle), die X-(RollAngle) und die Y-Achse (TurnAngle)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:Slices und Stacks (bei Kugeln): Gibt an, aus wie vielen Teilen die Kugeln gemacht werden soll, sprich die „Rundheit“ (wo wird uns dieses Deutsch noch hinführen?)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:Stop (auch bei Kugeln): Eigentlich wie Bottom, nur wird die Kugel durch eine Senkrechte Ebene „beschnitten“ (ich geb`s auf)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:ShowAxes: Zeigt die Achsen an (ist eine meiner Lieblingsoptionen!)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:Visible: Ist wohl selbsterklärend ;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Der „Cadencer“==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutorial GLScene html m1130af53.png]]&lt;br /&gt;
&lt;br /&gt;
Wenn man mit GLScene arbeitet, wird man zwangsläufig irgendwann mal mit dem Cadencer zu tun haben. Er ist nämlich das Wichtigste für Animationen und entspricht dem OnIdle aus der VCL. Im einzigen Ereignis des Cadencers, OnProgress, kann man dann z.B. Bewegungen nach dem Prinzip&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
Objekt.Position = Objekt.Position + Objekt.Geschwindigkeit&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
durchführen.&lt;br /&gt;
&lt;br /&gt;
Der Cadencer ermöglicht es aber auch, frameunabhägige Bewegungen durchzuführen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
Objekt.Position = Objekt.Position + Objekt.Geschwindigkeit * Deltatime&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Objekte erzeugen, während das Programm läuft==&lt;br /&gt;
&lt;br /&gt;
Wenn man z.B. einen Editor programmiert, wird man Objekte während des Renderns komplett neu erzeugen müssen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle Objekte der Szene sind sogenannte GLCustomSceneObjects. Also definieren wir in einer Variablen-Sektion eine Variable nach dem Schema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
Objekt: TGLCustomSceneObject;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um dann also ein Objekt zu erzeugen, müssen wir entscheiden, ob es ein sogenanntes Rootobject oder Childobject werden soll. Rootobjekte befinden sich in der Objekthierarchie ganz oben, Childobjekte sind immer einem Rootobjekt untergeordnet. Das zeige ich am besten mal mit folgendem Bild:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutorial GLScene html m325f1590.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der praktische Unterschied der beiden Arten ist, dass Rootobjekte automatisch an die Position 0|0|0 gesetzt werden. Childobjekte werden im Gegensatz dazu zwar auch an der Position 0|0|0 erstellt, jedoch relativ zu ihrem Rootobjekt. Das heißt, wenn man z.B. ein Rootobjekt an die Position 1|2|4 stellt, dann wird ein Childobjekt, das dann erstellt wird, auch an die Position 1|2|4 gebracht. Das ist ein bisschen kompliziert, am besten probiert ihr das einfach mal aus.&lt;br /&gt;
&lt;br /&gt;
Nun aber zum praktischen Teil:&lt;br /&gt;
&lt;br /&gt;
*Ein Rootobjekt erstellen&lt;br /&gt;
      RootObjekt := GLScene.Objects.AddNewChild(TGLCube);&lt;br /&gt;
          |                                       |&lt;br /&gt;
      TGLCustomSceneObject             Typ des neuen Objekts&lt;br /&gt;
&lt;br /&gt;
*Ein Childobjekt erstellen&lt;br /&gt;
&lt;br /&gt;
      ChildObjekt :=         RootObjekt.AddNewChild(TGLFrustrum);&lt;br /&gt;
         |                       |                           |&lt;br /&gt;
      TGLCustomSceneObject Das Rootobjekt des Childobjekts   Typ des neuen Objekts&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Nachwort==&lt;br /&gt;
&lt;br /&gt;
Das war’s erstmal. Ich hoffe, dass ich euch einen kleinen Überblick über die Materie habe geben können. Wie immer könnt ihr eure Fragen, eventuelle Fehler oder Ideen für ein weiterführendes Tutorial im Forum posten. Über Feedback würde ich mich natürlich auch sehr freuen!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Euer&lt;br /&gt;
&lt;br /&gt;
'''La_Boda'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{TUTORIAL_NAVIGATION|-|[[Tutorial_WebGL]]}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Tutorial|GLScene]]&lt;/div&gt;</summary>
		<author><name>Phlegmatiker</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Checkliste_Allgemein&amp;diff=25268</id>
		<title>Checkliste Allgemein</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Checkliste_Allgemein&amp;diff=25268"/>
				<updated>2011-07-15T20:44:33Z</updated>
		
		<summary type="html">&lt;p&gt;Phlegmatiker: /* Grundlagen */ Schreibfehler, Grammatik&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Hier gibt es eine allgemeine Checkliste, wenn ihr nichts oder nicht das seht, was ihr sehen wollt.&lt;br /&gt;
&lt;br /&gt;
==Grundlagen==&lt;br /&gt;
*'''Benutzen Sie eine funktionierende Programmgrundlage (Template)?'''&lt;br /&gt;
:Wurde ein [[Template]] von DelphiGL.com benutzt, oder wurde das Template bereits erfolgreich getestet, dann kann von einer funktionierenden Programmgrundlage ausgegangen werden.&lt;br /&gt;
&lt;br /&gt;
*'''Läuft das Programm ohne OpenGL-Fehler zu produzieren?'''&lt;br /&gt;
:Mittels eines Error-Handlers, wie er im &amp;quot;[[Tutorial_quickstart]]&amp;quot; beschrieben ist, wird dies überprüft.&lt;br /&gt;
&lt;br /&gt;
==Was machen wenn...?==&lt;br /&gt;
* '''&amp;quot;Ich sehe nur die Fensterfarbe/garnichts&amp;quot;'''&lt;br /&gt;
** [[SwapBuffers]] fehlt?&lt;br /&gt;
&lt;br /&gt;
* '''&amp;quot;Ich sehe nur schwarz&amp;quot;'''&lt;br /&gt;
** Hintergrundfarbe mal auf etwas anderes als schwarz stellen um zu schauen, ob das Objekt eventuell schwarz gezeichnet wird. Wenn ja:&lt;br /&gt;
*** Ist versehentlich eine Textur gesetzt? → glDisable(GL_TEXTURE_2D)&lt;br /&gt;
*** Versehentlich die falsche Farbe eingestellt? → glColor4f(1.0, 1.0, 1.0, 1.0)&lt;br /&gt;
** Folgende Tests testweise deaktivieren:&lt;br /&gt;
*** Tiefentest (GL_DEPTH_TEST)&lt;br /&gt;
*** Backfaceculling (GL_CULL_FACE)&lt;br /&gt;
*** Alphatest (GL_ALPHA_TEST)&lt;br /&gt;
&lt;br /&gt;
* '''&amp;quot;Ich sehe nur die Hintergrundfarbe&amp;quot;'''&lt;br /&gt;
** Wenn diese schwarz ist, bitte oben nachschauen&lt;br /&gt;
** Ist die Projektionsmatrix richtig gesetzt ([[glOrtho]], [[gluPerspective]])?&lt;br /&gt;
** Ist der Viewport richtig gesetzt ([[glViewport]])?&lt;br /&gt;
** Ist das Objekt zwischen Near- und Far-Cull-Plane (gesetzt in der Projektion)? → ggf. mit [[glTranslate|glTranslatef]](0, 0, -z) experimentieren.&lt;br /&gt;
** Ist Culling aktiviert? Werden die Vertices in der richtigen Reihenfolge übergeben? ([[Tutorial_Lektion_5]])&lt;/div&gt;</summary>
		<author><name>Phlegmatiker</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_glsl&amp;diff=25267</id>
		<title>Tutorial glsl</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_glsl&amp;diff=25267"/>
				<updated>2011-07-15T20:40:59Z</updated>
		
		<summary type="html">&lt;p&gt;Phlegmatiker: /* Die Shadersprache */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Einleitung=&lt;br /&gt;
Hallo und willkommen bei meiner &amp;quot;Einführung&amp;quot; in GLSL (kurz für &amp;quot;Open'''GL''' '''S'''hading '''L'''anguage&amp;quot;), der offiziellen Hochlevel-Shadersprache von OpenGL. In diesem umfangreichen Dokument werde ich versuchen, sowohl auf die Nutzung (sprich das Laden und Anhängen von Shadern im Quellcode), als auch auf die Programmierung von Shadern selbst einzugehen, inklusive aller Sprachelemente der OpenGL Shadersprache. Es wird also auch recht viele Informationen zu der C-ähnlichen Programmstruktur und den von GLSL angebotenen Variablen und Attributen gehen. Am Ende dieser Einführung sollten alle die, die sich für das Thema interessieren, in der Lage sein, zumindest einfach Shader zu schreiben und auch in ihren Programmen zu nutzen. Ausserdem soll dieses Dokument gleichzeitig als ein deutsches &amp;quot;Pendant&amp;quot; zu den von Khronoes veröffentlichten Shaderspezifikationen, und damit als alltägliches Nachschlagewerk, dienen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Vorkenntnisse==&lt;br /&gt;
Wie auch schon mein ARB_VP-Tutorial richtet sich auch diese Einführung aufgrund ihrer Thematik eher an die fortgeschritteneren GL-Programmierer und neben sehr guten GL-Kenntnissen sollten sich alle, die sich daran versuchen wollen, mit den technischen Hintergründen der GL, wie z.B. dem Aufbau der Renderpipeline auskennen. Weiterhin sind C-Kenntnisse absolut erforderlich, da die Shader ja in einer an ANSI-C angelehnten Syntax geschrieben werden. Auch Begriffsdefinitionen zu Vertex oder Fragment werden zum Verständis dieser Einführung benötigt. Wer also noch am Anfang seiner GL-Karriere steht, dem wird dieses Dokument nicht viel nützen. Ganz nebenbei solltet ihr auch noch eine gehörige Portion Zeit (am besten nen kompletten Nachmittag) mitbringen, denn die folgende Kost ist nicht nur umfangreich, sondern auch manchmal recht schwer verdaulich.&lt;br /&gt;
&lt;br /&gt;
=Was ist GLSL?=&lt;br /&gt;
Wie Eingangs kurz angesprochen handelt es sich bei GLSL um eine Shadersprache, also um eine Hochsprache, in der man die programmierbaren Teile aktueller Grafikbeschleuniger nach eigenem Belieben programmieren kann. Sie stellt quasi den Nachfolger zu den in Assembler geschriebenen Vertex- und Fragmentprogrammen ([[GL_ARB_Vertex_Program]]/[[GL_ARB_Fragment_Program]]) dar und basiert auf ANSI C, erweitert um Vektor- und Matrixtypen sowie einige C++-Mechanismen.&lt;br /&gt;
&lt;br /&gt;
Die in GLSL geschriebenen Programme nennen sich, angepasst an die Terminologie von RenderMan und DirectX, [[Shader]] (im Gegensatz zu &amp;quot;Programme&amp;quot; bei ARB_VP/FP) und werden entweder auf Eckpunkte (VertexShader), Fragmente (FragmentShader) angewendet, oder (neuerdings, ab Shadermodell 4.0) auch genutzt um Geometrie zu erstellen (Geometryshader). Andere Teile der Renderpipeline (z.B. die Rasterisierung) können momentan noch nicht durch Shader beeinflusst werden, was allerdings in Zukunft noch kommen kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Voraussetzungen==&lt;br /&gt;
&lt;br /&gt;
GLSL wurde 2005 mit OpenGL 1.5 eingeführt. Während es in Sachen Treiber- und Hardwareunterstützung anfänglich noch dürftig aussah, wird man inzwischen keine Grafikkarte mehr kaufen können die nicht zumindest Vertex- und Fragmentshader beherscht. Geometrieshader hingegen sind relativ neu und wurden erst mit Shadermodell 4.0 eingeführt, hier ist es also unter Umständen noch möglich dass selbst aktuelle Treiber/Karten keine Geometrieshader beherrschen.&lt;br /&gt;
&lt;br /&gt;
Natürlich benötigt man auch einen passenden OpenGL-Header der die für GLSL nötigen Funktionen exportiert. Ich verweise dazu auf unseren eigenen OpenGL-Header [[DGLOpenGL.pas]], der peermanent auf dem aktuellsten Stand gehalten wird und auch Support für Geometrieshader mitbringt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Extensions==&lt;br /&gt;
&lt;br /&gt;
Die GL-Shadersprache &amp;quot;besteht&amp;quot; in ihrer aktuellen Version aus folgenden Extensions, fürs Verständnis wäre es nicht schlecht, wenn ihr euch zumindest die Einleitungen dazu durchlest :&lt;br /&gt;
* [[GL_ARB_Shader_Objects]] ([http://oss.sgi.com/projects/ogl-sample/registry/ARB/shader_objects.txt Orginal Spezifikation])&lt;br /&gt;
: Definiert die API-Aufrufe die zum Erstellen, Kompilieren, Linken, Anhängen und Aktivieren von Shader- und Programmobjekten nötig sind. &lt;br /&gt;
* [[GL_ARB_Vertex_Shader]] ([http://oss.sgi.com/projects/ogl-sample/registry/ARB/vertex_shader.txt Orginal Spezifikation])&lt;br /&gt;
: Fügt der OpenGL Programmierbarkeit auf Vertexebene hinzu. &lt;br /&gt;
* [[GL_ARB_Fragment_Shader]] ([http://oss.sgi.com/projects/ogl-sample/registry/ARB/fragment_shader.txt Orginal Spezifikation])&lt;br /&gt;
: Fügt der OpenGL Programmierbarkeit auf Fragmentebene hinzu. &lt;br /&gt;
* [[GL_ARB_Shading_Language_100]] ([http://oss.sgi.com/projects/ogl-sample/registry/ARB/shading_language_100.txt Orginal Spezifikation])&lt;br /&gt;
: Gibt die unterstützte Version von glSlang an, momentan 1.00.&lt;br /&gt;
&lt;br /&gt;
'''Hinweis''' : Seit OpenGL 2.0 ist GLSL Teil des Kerns. Wenn die Karte als OpenGL 2.0 unterstützt, dann unterstützt sie auch (zumindest in Software) Vertex- und Fragmentshader.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Sprachversionen==&lt;br /&gt;
&lt;br /&gt;
Neben der OpenGL-Version und dem vorhandenen Shadermodell (das eher an DirectX ausgerichtet ist), bietet auch GLSL verschiedene Versionen, die entsprechend erweiterte Funktionalität bieten.&lt;br /&gt;
&lt;br /&gt;
Auslesen kann man die verfürgbare GLSL-Version wie folgt :&lt;br /&gt;
&lt;br /&gt;
 glGetString(GL_SHADING_LANGUAGE_VERSION)&lt;br /&gt;
&lt;br /&gt;
Erst ab Version 1.4. kann man davon ausgehen dass GLSL alle Features des Shadermodells 4.0 liefert, ab 1.3 grob gesagt Shadermodell 3.0 (bei GLSL lässt sich das leider nicht so leicht unterteilen).&lt;br /&gt;
&lt;br /&gt;
Ausserdem kann man seinem Shader eine Versionsnummer verpassen. Sollte der Shadercompiler (also Treiber bzw. Hardware) diese Version nicht unterstützen, gibt dieser eine Fehlermeldung heraus :&lt;br /&gt;
&lt;br /&gt;
 #version 1.50 &lt;br /&gt;
&lt;br /&gt;
''(Hinweis : Muss am Anfang des Shaders stehen)''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Objekte==&lt;br /&gt;
&lt;br /&gt;
Im Zuge der Vereinheitlichung der GL wird immer häufiger in Objekte gekapselt, deren API dann auch aneinander angelehnt ist. Ziel ist, dabei die Programmierung der GL uniform zu machen, so dass z.B. zwischen dem Erstellen und Verwalten eines Vertex-Buffer-Objektes oder eines Shader-Objektes kaum ein Unterschied besteht (demnächst kommen dann auch Pixel-Buffer-Objekte dazu). Mit glSlang wurden dann im Zuge dieser Aktion zwei neue Objekte eingeführt, deren Definition ihr euch unbedingt einprägen solltet :&lt;br /&gt;
&lt;br /&gt;
* '''Programmobjekt'''&lt;br /&gt;
:Ein Objekt, an das die Shader später angebunden werden. Bietet Funktionalität zum Linken der Shader und prüft dabei die Kompatibilität zwischen Vertex- und Fragmentshader.&lt;br /&gt;
&lt;br /&gt;
* '''Shaderobjekt'''&lt;br /&gt;
:Dieses Objekt verwaltet den Quellcodestring eines Shaders und ist entweder vom Typ '''GL_VERTEX_SHADER''', '''GL_FRAGMENT_SHADER_ARB''' oder '''GL_GEOMETRY_SHADER'''.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Ressourcen==&lt;br /&gt;
&lt;br /&gt;
Die Shadersprache ist keinesfalls final und es wurden bereits diverse Ausdrücke für zukünftige Verwendung reserviert, denn ein Ziel bei ihrer Entwicklung war es, sie so zukunftsorientiert zu gestalten, dass auch Grafikkarten der nächsten und übernächsten Generation voll ausgenutzt werden können. Damit einher geht die Tatsache, dass sich die Spezifikationen in Zukunft ändern/erweitern werden, weshalb man da immer einen Blick hineinwerfen sollte. Die Anlaufstelle dafür ist die [http://www.opengl.org/documentation/specs/ Spezifikationenliste auf OpenGL.org].&lt;br /&gt;
&lt;br /&gt;
=GLSL im Programm=&lt;br /&gt;
Bevor wir uns mit der Syntax von glSlang beschäftigen, zeige ich euch erstmal, wie ihr Shader in euer Programm einbindet und nutzt. Warum das zuerst? Ganz einfach deshalb, weil ihr dann das, was ihr im glSlang-Syntaxteil lernt, direkt in eurer Testanwendung verwenden könnt. Hoffe diese Entscheidung klingt logisch und findet Anklang.&lt;br /&gt;
&lt;br /&gt;
Zuerst benötigen wir natürlich unsere Objekte. Zum einen ein ''Programmobjekt'', an das unsere Shader gebunden werden, und zwei ''Shaderobjekte'', die den Quellcode unseres Vertex bzw. Fragment Shaders aufnehmen. Dazu wurde eigens der neue &amp;quot;Datentyp&amp;quot; {{INLINE_CODE|glHandle}} eingeführt, der ein Objekthandle repräsentiert. Wir deklarieren also wie folgt :&lt;br /&gt;
&lt;br /&gt;
 ProgramObject        : GLhandle;&lt;br /&gt;
 VertexShaderObject   : GLhandle;&lt;br /&gt;
 FragmentShaderObject : GLhandle;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nach dieser Deklaration können wir dann damit beginnen unsere Objekte zu erstellen. Den Anfang macht das Programmobjekt :&lt;br /&gt;
&lt;br /&gt;
 ProgramObject        := glCreateProgram;&lt;br /&gt;
&lt;br /&gt;
Die Funktion [[glCreateProgram]] erstellt uns oben ein leeres Programmobjekt und gibt ein gültiges Handle darauf zurück.&lt;br /&gt;
&lt;br /&gt;
Weiter gehts mit der Erstellung unseres Vertex bzw. Fragment Shaders :&lt;br /&gt;
&lt;br /&gt;
 VertexShaderObject   := glCreateShader(GL_VERTEX_SHADER);&lt;br /&gt;
 FragmentShaderObject := glCreateShader(GL_FRAGMENT_SHADER);&lt;br /&gt;
&lt;br /&gt;
[[glCreateShader]] dient zur Generierung eines leeren Shaderobjektes. Momentan unterstützt diese Funktion VertexShader und FragmentShader.&lt;br /&gt;
&lt;br /&gt;
Nachdem wir nun also zwei gültige Shaderobjekte haben, wollen wir diese auch mit entsprechendem Quellcode versorgen :&lt;br /&gt;
&lt;br /&gt;
 glShaderSource(VertexShaderObject, 1, @ShaderText, @ShaderLength);&lt;br /&gt;
 glShaderSource(FragmentShaderObject, 1, @ShaderText, @ShaderLength);&lt;br /&gt;
&lt;br /&gt;
Via [[glShaderSource]] setzen wir den Quellcode eines Shaderobjektes ''komplett'' neu. Zum Laden des Quellcodes bietet sich unter Delphi übrigens eine TStringList geradezu an. Es sollte beachtet werden, dass der Quellcode zu diesem Zeitpunkt ''nicht geparst'' wird, also keine Fehleruntersuchung stattfindet.&lt;br /&gt;
&lt;br /&gt;
Der Quellcode wurde jetzt also an unsere Shaderobjekte gebunden und sollte dann natürlich auch noch kompiliert werden :&lt;br /&gt;
&lt;br /&gt;
 glCompileShader(VertexShaderObject);&lt;br /&gt;
 glCompileShader(FragmentShaderObject);&lt;br /&gt;
&lt;br /&gt;
Der glSlang-Compiler des Treibers wird bei einem Aufruf von [[glCompileShader]] versuchen, unsere Shader zu kompilieren. Sofern diese keine Fehler aufweisen, sollte dies auch erfolgreich sein. Wenn nicht, dann spuckt uns der Shadercompiler (je nach Treiber) recht detaillierte Infos aus. Wie man an diese Infos kommt könnt ihr gleich nachlesen.&lt;br /&gt;
&lt;br /&gt;
Wenn unsere Shader dann kompiliert werden konnten, ist es Zeit, diese an unser anfangs erstelltes Programmobjekt anzuhängen :&lt;br /&gt;
&lt;br /&gt;
 glAttachShader(ProgramObject, VertexShaderObject);&lt;br /&gt;
 glAttachShader(ProgramObject, FragmentShaderObject);&lt;br /&gt;
&lt;br /&gt;
Nachdem die Shaderobjekte nun an das Programmobjekt angehängt wurden, werden diese nicht mehr benötigt und ihre Resourcen können freigegeben werden :&lt;br /&gt;
&lt;br /&gt;
 glDeleteShader(VertexShaderObject);&lt;br /&gt;
 glDeleteShader(FragmentShaderObject);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Am Schluß müssen wir dann noch unsere ans Programmobjekt gebundenen Shader linken :&lt;br /&gt;
&lt;br /&gt;
 glLinkProgram(ProgramObject);&lt;br /&gt;
&lt;br /&gt;
Während [[glCompileShader]] unsere Shader auf syntaktische Fehler innerhalb ihres lokalen Raums geprüft hat, werden beim Linken durch [[glLinkProgram]] die angehangenen Shader zu einem ausführbaren Shader gelinkt. Folgende Bedingungen führen zu einem '''Linkerfehler''':&lt;br /&gt;
&lt;br /&gt;
* Die Zahl der von der Implementation unterstützten Attributvariablen wurde überschritten&lt;br /&gt;
* Der Speicherplatz für Uniformvariablen wurde überschritten&lt;br /&gt;
* Die Zahl der von der Implementation angebotenen Sampler wurde überschritten&lt;br /&gt;
* Die main-Funktion fehlt&lt;br /&gt;
* Die Liste der Varying-Variablen des Vertexshaders stimmt nicht mit der des Fragmentshaders überein&lt;br /&gt;
* Funktions- oder Variablenname nicht gefunden&lt;br /&gt;
* Eine gemeinsame Globale ist mit unterschiedlichen Werten oder Typen initialisiert worden&lt;br /&gt;
* Zwei Sampler unterschiedlichen Typs zeigen auf die selbe Textureneinheit&lt;br /&gt;
* Ein oder mehrere angehangene(r) Shader wurden nicht erfolgreich kompiliert&lt;br /&gt;
&lt;br /&gt;
Die Nutzung von glSlang im eigenen Programm ist wie oben erkennbar also nicht wirklich schwer und innerhalb kurzer Zeit realisiert. Natürlich ist es auch möglich z.B. nur einen VertexShader oder nur einen FragmentShader an ein Programmobjekt zu binden.&lt;br /&gt;
&lt;br /&gt;
Noch eine kleine Notiz zum Löschen der Shader mittel [[glDeleteShader]] : Da Shader(objekte) einen Referenzzähler besitzen und erst gelöscht werden wenn diese nirgendwo mehr benötigt werden, ist es nicht falsch diese vor dem Linkvorgang zu löschen. Allerdings spielt es letztendlich keine Rolle ob die Löschanweisung vorher der nachher ausgeführt wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Fehlererkennung==&lt;br /&gt;
Natürlich wird es ohne Fehlerausgabe recht schwer, etwaige Probleme in einem Vertex- oder Fragmentshader zu finden. Doch auch in diesem Bereich wurde glSlang recht gut durchdacht und es wurden zwei Funktionen eingeführt, welche im Zusammenspiel die Fehlersuche recht einfach machen, nämlich [[glGetShaderInfoLog]] und [[glGetShader]] mit dem Argument {{INLINE_CODE|GL_OBJECT_INFO_LOG_LENGTH}}. Erstere Funktion liefert uns einen Logstring, während uns letztere Funktion dessen Länge angibt. Der Logstring wird verändert, sobald ein Shader kompiliert oder ein Programm gelinkt wird.&lt;br /&gt;
&lt;br /&gt;
Um die Ausgabe dieses Logs so einfach wie möglich zu machen, bietet es sich an beide in einer einfach Funktion unterzubringen :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;function glSlang_GetInfoLog(pShader: GLHandleARB): String;&lt;br /&gt;
var&lt;br /&gt;
  blen, slen: GLInt;&lt;br /&gt;
  InfoLog: PGLCharARB;&lt;br /&gt;
&lt;br /&gt;
begin&lt;br /&gt;
  glGetShaderiv(glObject, GL_INFO_LOG_LENGTH , @blen);&lt;br /&gt;
  if blen &amp;gt; 1 then&lt;br /&gt;
  begin&lt;br /&gt;
    GetMem(InfoLog, blen * SizeOf(GLCharARB));&lt;br /&gt;
    glGetShaderInfoLog(pShader, blen, slen, InfoLog);&lt;br /&gt;
    Result := PChar(InfoLog);&lt;br /&gt;
    Dispose(InfoLog);&lt;br /&gt;
  end;&lt;br /&gt;
end;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Funktion ist recht leicht erklärt : Zuerst lassen wir uns über {{INLINE_CODE|glGetShaderiv}} mitteilen wie lang der aktuelle Infolog ist. Sollte dort tatsächlich etwas drinstehen (blen &amp;gt; 1), dann lassen wir uns dessen Inhalt via {{INLINE_CODE|glGetShaderInfoLog}} in {{INLINE_CODE|InfoLog}} ausgeben und liefern diesen als Ergebnis zurück.&lt;br /&gt;
&lt;br /&gt;
Wie bereits gesagt wird nur nach dem Kompilieren eines Shaders bzw. dem Linken eines Programmobjektes ein Infolog erstellt. Es bietet sich dadurch an, direkt danach einen solchen Aufruf zu machen :&lt;br /&gt;
&lt;br /&gt;
 glCompileShader(VertexShaderObject);&lt;br /&gt;
 ShowMessage(glSlang_GetInfoLog(VertexShaderObject));&lt;br /&gt;
&lt;br /&gt;
Wenn unser Vertex Shader komplett fehlerfrei kompiliert werden konnte, dann sehen wir als Ergebnis nur einen leeren Dialog. Ist dies nicht der Fall, so werden wir vom Treiber mit recht detaillierten Fehlerinformationen &amp;quot;belohnt&amp;quot;, z.B. so :&lt;br /&gt;
&lt;br /&gt;
[[Bild:GLSL_error_vshader.jpg]]&lt;br /&gt;
&lt;br /&gt;
Auch das Infolog nach dem Linken des Programmobjektes dürfte, selbst wenn keine Fehler vorkommen, recht interessant sein, das sieht dann nämlich so aus :&lt;br /&gt;
&lt;br /&gt;
[[Bild:GLSL info programobject.jpg]]&lt;br /&gt;
&lt;br /&gt;
Wie zu sehen, wird uns nach dem erfolgreichen Linken auch gesagt, ob und welcher Shader in Hardware bzw. Software läuft. Für Debuggingzwecke sicherlich eine mehr als brauchbare Information.&lt;br /&gt;
&lt;br /&gt;
==Shader benutzen==&lt;br /&gt;
Um den Shader auch für die nächsten Polygone zu benutzen oder Uniformparameter übergeben zu können, ruft man die Funktion&lt;br /&gt;
 glUseProgramt(ProgramObject);&lt;br /&gt;
um alle Shader zu deaktivieren, ruft man dieselbe Funktion mit dem Parameter 0.&lt;br /&gt;
&lt;br /&gt;
==Parameterübergabe==&lt;br /&gt;
Uniformparameter (mehr dazu später) stellen die Schnittstelle zwischen eurem Programm und dem Shader dar, werden also genutzt um Daten aus dem Programm heraus an einen Shader zu übergeben. Zur Übergabe dieser Parameter bietet OpenGL diverse Funktionen, die alle Abkömmlinge von [[glUniform]] sind. Während mit {{INLINE_CODE|glUniform4f}} z.B. ein Vier-Komponentenvektor an das Programmobjekt übergeben wird, kann man mittels {{INLINE_CODE|glUniformMatrix4fv}} ganze Matrizen schnell und einfach übergeben. Ausserdem gibt es nun die Möglichkeit Uniformparameter direkt über ihren Namen, statt wie unter ARB_FP/VP über einen festen Index zu adressieren. Die Funktion [[glGetUniformLocationARB]] gibt anhand des übergebenen Parameternamens dessen Position zurück. Man kann also ganz einfach über den Namen drauf zugreifen :&lt;br /&gt;
&lt;br /&gt;
 glUniform3f(glGetUniformLocation(ProgramObject, PGLCharARB('LightPosition')), LPos[0], LPos[1], LPos[2]);&lt;br /&gt;
 glUniform1i(glGetUniformLocation(ProgramObject, PGLCharARB('texSamplerTMU3')), 3);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wichtig ist hier, das man je nach Parametertyp auch die passende Anzahl von Argumenten übergibt. Also für einen 4-Komponenten Floatvektor {{INLINE_CODE|glUniform4fARB}} und für einen einfachen Integerwert (z.B. Textureinheit für einen Sampler) glUnifrom1iARB. Auch nicht vergessen dürft ihr, das die Namen der Parameter genauso wie im Shader geschrieben werden müssen, also Groß- und Kleinschreibung beachtet werden muß.&lt;br /&gt;
&lt;br /&gt;
=Die Shadersprache=&lt;br /&gt;
&lt;br /&gt;
Nachdem wir uns mit der Einbindung der glSlang-Shader in unser Programm beschäftigt haben, wollen wir uns in den folgenden Kapiteln um die Sprachelemente von glSlang kümmern. Wie schon gesagt basiert glSlang auf ANSI-C, wurde allerdings um speziell auf den Zielbereich angepasste Vektor- und Matrixtypen und einige C++-Features wie das freie deklarieren von Variablen an jeder Stelle und das Funktionsüberladen auf Basis des Argumenttyps erweitert. Wer sich ein wenig mit C/C++ auskennt sollte also in der nun folgenden Materie keine Probleme bekommen.&lt;br /&gt;
&lt;br /&gt;
'''Obligatorische Hinweise für verwöhnte Delphi-Nutzer : '''&lt;br /&gt;
*Wie von C/C++ her gewohnt, spielt auch in glSlang die Groß- und Kleinschreibung eine wichtige Rolle, also bitte achtet darauf. gl_Position ist eine komplett andere Variable als z.B. gl_position.&lt;br /&gt;
*Es findet keine automatische Typenkonvertierung statt. Das bedeutet also das float MyFloat = 1 ungültig ist und es in dem Falle float MyFloat = 1.0 heissen muss. Typecasts müssen also immer manuell stattfinden, z.B. MyFloat = float(MyInt).&lt;br /&gt;
&lt;br /&gt;
'''Kleine Programmstrukturkunde für C-Unkundige :'''&amp;lt;br&amp;gt;&lt;br /&gt;
Da sicherlich einige Delpher nie richtig was mit C gemacht haben, zeige ich mal anhand eines kleinen Beispieles (das auf keinen Fall nen brauchbaren Shader darstellt) den grundlegenden Aufbau eines glSlang-Shaders, der natürlich dem Aufbau eines C-Programmes stark ähnelt :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
uniform vec4 VariableA;&lt;br /&gt;
float VariableB;&lt;br /&gt;
vec3  VariableC;&lt;br /&gt;
const float KonstanteA = 256.0;&lt;br /&gt;
&lt;br /&gt;
float MyFunction(vec4 ArgumentA)&lt;br /&gt;
{&lt;br /&gt;
    float FunktionsVariableA = float(5.0);&lt;br /&gt;
&lt;br /&gt;
    return float(ArgumentA * (FunktionsVariableA + KonstanteA));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Ich bin ein Kommentar&lt;br /&gt;
/* Und ich auch */&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;&lt;br /&gt;
    gl_TexCoord[0] = gl_MultiTexCoord0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sieht doch recht bekannt aus, unser Programmaufbau. Delphi und C haben ja so einige Grundlagen gleich, darunter auch der ungefähre Programmaufbau. Ausserhalb jeglicher Funktionen legen wir am Programmanfang unsere Variablen, Konstanten und Attribute fest, die dann ''global'' nutzbar sind, also in jeder Funktion.&lt;br /&gt;
&lt;br /&gt;
Darunter deklarieren wir dann eine kleine Funktion. Wie auch bei den Variablendeklarationen wird hier der Rückgabetyp nicht wie bei Pascal nach dem Funktionsnamen untergebracht, sondern davor. Innerhalb der Funktion können dann wieder Variablen deklariert werden, die dann allerdings ''lokal'', also nur in dieser Funktion nutzbar sind. Vorteil dieser Deklaration ist die Tatsache, dass je nach Grafikkarte nur bestimmt viele globale Variablen deklariert werden können. Wenn möglich sollte man also mit lokalen Vorlieb nehmen. Unsere Funktion gibt dann natürlich noch via return einen Wert zurück, ''was gemacht werden muss'', sofern man diese nicht als void deklariert hat (entspräche dann einer Prozedur in Pascal). Wird dies nicht getan, so spuckt der Compiler einen Fehler aus.&lt;br /&gt;
&lt;br /&gt;
Auch wichtig sind natürlich Kommentare. Erste Variante (Doppelslash) ist auch in der Pascalwelt verfügbar und kommentiert eine einzelne Zeile aus. Die Variante darunter kann man für Kommentarblöcke nutzen (/* .. */) und entspricht den Kommentaren in geschweiften Klammern in Delphi.&lt;br /&gt;
&lt;br /&gt;
Danach kommt dann die '''wichtigste Funktion''' des Shaders, nämlich '''main''', die in keinem Shader fehlen darf. Sie stellt quasi den Programmkörper dar und ist oft auch die einzige Funktion in einem Shader. Sie erhält weder ein Argument, noch gibt sie einen Wert zurück.&lt;br /&gt;
&lt;br /&gt;
Soviel also zum grundlegenden Aufbau eines Shader. Hoffe das jetzt alle die in C nicht so bewandert sind damit klar kommen, und dann bald ihre ersten glSlang-Shader schreiben können.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Datentypen==&lt;br /&gt;
&lt;br /&gt;
Obwohl einige Datentypen aus C übernommen wurden, sieht man der Typenliste an, das diese speziell auf den 3D-Bereich zugeschnitten wurde. Variablen müssen vor ihrer Nutzung eindeutig deklariert sein, Typecasting erfolgt über Konstruktoren (dazu später mehr). Folgende Datentypen stehen sowohl im Vertex- als auch Fragmentshader zur Verfügung :&lt;br /&gt;
&lt;br /&gt;
{|{{Prettytable_B1}}&lt;br /&gt;
!Datentyp  	&lt;br /&gt;
!Erklärung&lt;br /&gt;
|-&lt;br /&gt;
|void 	&lt;br /&gt;
|Für Funktionen die keinen Wert zurückgeben&lt;br /&gt;
|-&lt;br /&gt;
|bool 	&lt;br /&gt;
|Konditionaler Typ, entweder true (wahr) oder false (falsch)&lt;br /&gt;
|-&lt;br /&gt;
|int 	&lt;br /&gt;
|Vorzeichenbehafteter Integerwert&lt;br /&gt;
|-&lt;br /&gt;
|float 	&lt;br /&gt;
|Fließkommaskalar mit Singlegenauigkeit (32 Bit)&lt;br /&gt;
|-&lt;br /&gt;
|vec2 	&lt;br /&gt;
|2-Komponenten Fließkommavektor&lt;br /&gt;
|-&lt;br /&gt;
|vec3 	&lt;br /&gt;
|3-Komponenten Fließkommavektor&lt;br /&gt;
|-&lt;br /&gt;
|vec4 	&lt;br /&gt;
|4-Komponenten Fließkommavektor&lt;br /&gt;
|-&lt;br /&gt;
|bvec2 	&lt;br /&gt;
|2-Komponenten Booleanvektor&lt;br /&gt;
|-&lt;br /&gt;
|bvec3 	&lt;br /&gt;
|3-Komponenten Booleanvektor&lt;br /&gt;
|-&lt;br /&gt;
|bvec4 	&lt;br /&gt;
|4-Komponenten Booleanvektor&lt;br /&gt;
|-&lt;br /&gt;
|ivec2 	&lt;br /&gt;
|2-Komponenten Integervektor&lt;br /&gt;
|-&lt;br /&gt;
|ivec3 	&lt;br /&gt;
|3-Komponenten Integervektor&lt;br /&gt;
|-&lt;br /&gt;
|ivec4 	&lt;br /&gt;
|4-Komponenten Integervektor&lt;br /&gt;
|-&lt;br /&gt;
|mat2 	&lt;br /&gt;
|2x2 Fließkommamatrix&lt;br /&gt;
|-&lt;br /&gt;
|mat3 	&lt;br /&gt;
|3x3 Fließkommamatrix&lt;br /&gt;
|-&lt;br /&gt;
|mat4 	&lt;br /&gt;
|4x4 Fließkommamatrix&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die sampler-Typen stellen eine besondere Klasse zum Zugriff auf Texturen dar, und werden im Kapitel 6.7 genauer erklärt, inklusive einiger Anwendungsbeispiele.&lt;br /&gt;
&lt;br /&gt;
{|{{Prettytable_B1}}&lt;br /&gt;
!Datentyp  	&lt;br /&gt;
!Erklärung&lt;br /&gt;
|-&lt;br /&gt;
|sampler1D 	&lt;br /&gt;
|Zugriff auf 1D-Textur&lt;br /&gt;
|-&lt;br /&gt;
|sampler2D 	&lt;br /&gt;
|Zugriff auf 2D-Textur&lt;br /&gt;
|-&lt;br /&gt;
|sampler3D 	&lt;br /&gt;
|Zugriff auf 3D-Textur&lt;br /&gt;
|-&lt;br /&gt;
|samplerCube 	&lt;br /&gt;
|Zugriff auf Cubemap&lt;br /&gt;
|-&lt;br /&gt;
|sampler2DRect 	&lt;br /&gt;
|Zugriff auf Texturen die nicht 2^n * 2^n entsprechen (&amp;quot;non power-of-two&amp;quot;, NPOT)&lt;br /&gt;
|-&lt;br /&gt;
|sampler1DShadow 	&lt;br /&gt;
|Zugriff auf 1D-Tiefentextur mit Vergleichsoperation&lt;br /&gt;
|-&lt;br /&gt;
|sampler2DShadow 	&lt;br /&gt;
|Zugriff auf 2D-Tiefentextur mit Vergleichsoperation&lt;br /&gt;
|-&lt;br /&gt;
|samplerCubeShadow&lt;br /&gt;
|Zugriff auf Tiefentextur in einer Cubemap (z.b. für omni-diretionale Lichtquellen)&lt;br /&gt;
|-&lt;br /&gt;
|sampler2DRectShadow&lt;br /&gt;
|Zugriff auf 2D-NPOT-Tiefentextur &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|sampler1DArray&lt;br /&gt;
|Zugriff auf ein array aus 1D-Texturen &lt;br /&gt;
|-&lt;br /&gt;
|sampler2DArray&lt;br /&gt;
|Zugriff auf ein array aus 2D-Texturen &lt;br /&gt;
|-&lt;br /&gt;
|sampler1DArrayShadow&lt;br /&gt;
|Zugriff auf ein array aus 1D-Tiefentexturen &lt;br /&gt;
|-&lt;br /&gt;
|sampler2DArrayShadow&lt;br /&gt;
|Zugriff auf ein array aus 2D-Tiefentexturen &lt;br /&gt;
|-&lt;br /&gt;
|samplerBuffer&lt;br /&gt;
|Zugriff auf eine Puffertextur (1D-Texutr zum Speichern von Pufferobjekten)&lt;br /&gt;
|-&lt;br /&gt;
|sampler2DMS&lt;br /&gt;
|Zugriff auf eine 2D-Textur mit mehreren Samplepunkten (z.b. für Multisampling)&lt;br /&gt;
|-&lt;br /&gt;
|sampler2DMSArray&lt;br /&gt;
|Zugriff auf einarray aus 2D-Textur mit mehreren Samplepunkten (z.b. für Multisampling)&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Arrays===&lt;br /&gt;
&lt;br /&gt;
Natürlich unterstützt glSlang auch Arrays, die wie in C deklariert werden und deren Index bei 0 beginnt. Folgendes Array im Shader :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
float temp[3];&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
beginnt also bei Index 0 und endet bei Index 2. Im Gegensatz zu C lassen sich Arrays in glSlang allerdings ''nicht bei der Initialisierung vorbelegen''. Wenn ein Array als Parameter einer Funktion deklariert wird, so darf dieses keine Dimensionierung erhalten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Strukturen===&lt;br /&gt;
&lt;br /&gt;
Neu ggü. ARB_FP/VP ist nun auch die Möglichkeit, Strukturen in einem Shader zu deklarieren. Vor allem die Übersicht komplexerer Shader kann dadurch stark verbessert werden. Strukturen werden wie gewohnt mit dem Schlüsselwort {{INLINE_CODE|struct}} eingeleitet und können dann zur Typisierung von Variablen genutzt werden. Folgendes Beispiel dürfte die Nutzung verdeutlichen :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct light&lt;br /&gt;
{&lt;br /&gt;
    bool active;&lt;br /&gt;
    float intensity;&lt;br /&gt;
    vec3 position;&lt;br /&gt;
    vec3 color;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Im Shader können dann neue Variablen von diesem Typ ganz einfach deklariert werden :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
 light LightSource[3];&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Der Zugriff auf die Elemente der Struktur erfolgt dann wie gewohnt über den Punkt :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
LightSource[3].position = vec3(1.0, 1.0, 5.0);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Typenqualifzierer==&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zur Typendeklaration kann eine Variable noch einen Typenqualifizerer vorangestellt bekommen, der an den Anfang der Deklaration gehört.&lt;br /&gt;
&lt;br /&gt;
* '''const'''&lt;br /&gt;
: Festgelegte (nur lesen) Konstante bzw. nur lesbarer Funktionsparameter.&lt;br /&gt;
&lt;br /&gt;
* '''uniform'''&lt;br /&gt;
: Ein den ganzen Shader über gleichbleibender Wert, der eine Schnittstelle zwischen dem Shader und der OpenGL-Anwendung darstellt. Ein Uniformwert wird in der Hauptanwendung an den entsprechenden Shader übergeben und kann dort dann genutzt werden.&lt;br /&gt;
&lt;br /&gt;
* '''attribute'''&lt;br /&gt;
: Nur lesbare Werte die eine Verbindung zwischen dem Shader und der OpenGL-VertexAPI darstellen (z.B. VertexParameter eines VertexArrays). Natürlich nur in einem Vertex Shader nutzbar.&lt;br /&gt;
&lt;br /&gt;
* '''varying'''&lt;br /&gt;
: Stellt die Verbindung zwischen einem Vertex- und einem FragmentShader dar. Werden im VertexShader geschrieben und dann perspektivisch korrekt über die Primitive interpoliert, um dann im Fragment Shader gelesen werden zu können. Nutzbar sind hier nur die Typen float, vec2, vec3, vec4, mat2, mat3 und mat4, Strukturen und andere Datentypen können nicht varying sein. Die Namen einer varying-Variable müssen sowohl im VertexShader als auch im FragmentShader gleich sein.&lt;br /&gt;
&lt;br /&gt;
* '''in'''&lt;br /&gt;
: Für Variablen die an eine Funktion übergeben und dort ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
* '''out'''&lt;br /&gt;
: Für Variablen die von einer Funktion nach aussen zurückgegeben werden.&lt;br /&gt;
&lt;br /&gt;
* '''inout'''&lt;br /&gt;
: Für Variablen die sowohl an eine Funktion übergeben als auch von dieser zurückgegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um obige Auflistung nicht leer im Raum stehen zu lassen zeige ich ein paar Beispiele die hoffentlich zum Verständnis beitragen :&lt;br /&gt;
&lt;br /&gt;
===Beispiel A=== &lt;br /&gt;
Vertexnormale soll an einen FragmenShader (interpoliert) übergeben werden :&lt;br /&gt;
&lt;br /&gt;
:Im VertexShader :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
varying vec3 VertexNormal;&lt;br /&gt;
...&lt;br /&gt;
VertexNormal = normalize(MV_IT * gl_Normal);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
:Im FragmentShader :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
varying vec3 VertexNormal;&lt;br /&gt;
...&lt;br /&gt;
TempVector = VertexNormal*...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Beispiel B=== &lt;br /&gt;
Uniformparameter zur nachträglichen Farbänderung der Szene wird im Programm übergeben :&lt;br /&gt;
&lt;br /&gt;
:Im VertexShader :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
uniform vec4 GlobalColor;&lt;br /&gt;
...&lt;br /&gt;
gl_FrontColor = GlobalColor * gl_Color;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
:Im Programm :&lt;br /&gt;
&lt;br /&gt;
 glUniform4fARB(glSlang_GetUniLoc(ProgramObject, 'GlobalColor'), Col[0], Col[1], Col[2], Col[3]);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Beispiel C=== &lt;br /&gt;
Konstante zur festen Farbänderung :&lt;br /&gt;
&lt;br /&gt;
:Im VertexShader :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
const vec4 ColorBias = vec4(0.2, 0.3, 0.0, 0.0);&lt;br /&gt;
...&lt;br /&gt;
gl_FrontColor = ColorBias * gl_Color;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
==Konstruktoren==&lt;br /&gt;
&lt;br /&gt;
Um in einem Shader ''Vektoren'' oder ''Matrizen'' mit Werten zu belegen, gibt es sogenannte Konstruktoren (nicht zu verwechseln mit z.B. Klassenkonstruktoren unter Delphi), die im Endeffekt nichts anderes als Funktionen zur Vorbelegung von Vektoren oder Matrizen darstellen. Dabei trägt der Konstruktor den selben Namen wie die Typendeklaration, also lässt sich eine Variable vom Typ {{INLINE_CODE|vec4}} mit dem Konstruktor {{INLINE_CODE|vec4(float, float, float, float)}} initialisieren.&lt;br /&gt;
&lt;br /&gt;
Allerdings hat man sich recht viel Mühe bei dieser Konstruktorgeschichte gemacht, so dass man einen vec4 nicht unbedingt mit einem {{INLINE_CODE|vec4}}-Konstruktor vorbelegen muss, sondern es vielseitige Möglichkeiten gibt. Um dies zu verdeutlichen gibts ein paar Beispiele :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
vec4 Color = vec4(1.0, 0.0, 0.0, 0.0);&lt;br /&gt;
vec4 Color = vec4(MyVec3, 1.0);&lt;br /&gt;
vec4 Color = vec4(MyVec2_A, MyVec2_B);&lt;br /&gt;
&lt;br /&gt;
vec3 LVec  = vec3(MyVec4);&lt;br /&gt;
vec2 Tmp   = vec2(MyVec3);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Trotz der recht wenigen Beispiele sollte schnell erkennbar sein, das man hier wirklich sehr viele Kombinationsmöglichkeiten hat, die dann gültig sind ''wenn man mindestens auf die benötigte Anzahl der Argumente kommt''. Im vorletzten Beispiel wird z.B. ein 3-Komponentenvektor aus einem 4-Komponentenvektor initialisiert. Das erzeugt keinen Fehler, sondern führt dazu das {{INLINE_CODE|vec3.x, vec3.y, vec3.z}} aus MyVec4 übernommen werden und MyVec4.w einfach ignoriert wird.&lt;br /&gt;
&lt;br /&gt;
Das Umkehrbeispiel, also&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
vec4 Color = vec4(MyVec3)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
funktioniert allerdings nicht, da hier die Zahl der benötigten Argumente nicht erreicht wird. In diesem Falle müsste es dann&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt; &lt;br /&gt;
vec4 Color = vec4(MyVec3, 0.0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
heissen.&lt;br /&gt;
&lt;br /&gt;
Obiges gilt natürlich auch für ''Matrixkonstruktoren'', hier sind z.B. folgende Konstuktoren denkbar, obwohl eigentlich alle Möglichkeiten nutzbar sind, ''solange die benötigte Zahl an Argumenten erreicht wird'' :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
mat4 MyMatrix = mat4(MyVec4, MyVec4, MyVec4, MyVec4);&lt;br /&gt;
mat2 MyMatrix = mat4(1.0, 0.0, 0.0, 0.0,&lt;br /&gt;
                     0.0, 1.0, 0.0, 0.0,&lt;br /&gt;
                     0.0, 0.0, 1.0, 0.0,&lt;br /&gt;
                     0.0, 0.0, 0.0, 1.0);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vektor- und Matrixkomponenten==&lt;br /&gt;
&lt;br /&gt;
Was natürlich in keiner Shadersprache fehlen darf, ist der leichte Zugriff auf die einzelnen Komponenten eines Vektors. glSlang bietet, je nach Anwendungsgebiet gleich drei Namensets für den Zugriff auf die Komponenten eines solchen Vektors, welches Set man nutzen will bleibt natürlich frei und ist unabhängig von der Deklaration eines Vektors. Man sollte nur darauf achten, beim gleichzeitigen Zugriff auf mehrere Komponenten im gleichen Namenset zu verbleiben :&lt;br /&gt;
&lt;br /&gt;
* {x, y, z, w}&lt;br /&gt;
:Für den Zugriff auf Vektoren die Punkte, Normale oder sonstige Vertexdaten repräsentieren.&lt;br /&gt;
&lt;br /&gt;
* {r, g, b, a}&lt;br /&gt;
:Für den Zugriff auf Vektoren die Farbwerte repräsentieren.&lt;br /&gt;
&lt;br /&gt;
* {s, t, p, q}&lt;br /&gt;
:Für den Zugriff auf Vektoren die Texturkoordinaten repräsentieren.&lt;br /&gt;
&lt;br /&gt;
Ein paar Beispiele zur Unterstreichung des oben gesagten :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
v4.rgba = vec4(1.0, 0.0, 0.0, 0.0);  // gültig&lt;br /&gt;
v4.rgzw = vec4(1.0, 1.0, 1.0, 2.0);  // Ungültig, da verschiedenen Namensets&lt;br /&gt;
v2.rgb  = vec3(1.0, 2.0, 1.0);       // Ungültig, da vec2 nur r+g besitzt&lt;br /&gt;
v2.xx   = vec2(5.0, 3.0);            // Ungültig, da 2 mal gleiche Komponente&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auch der Zugriff auf die Komponenten einer Matrix geht leicht von der Hand. Namensets wie bei den Vektoren gibt es hier natürlich keine, aber folgende Beispiele sollen den Zugriff aufzeigen :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
MyMat4[2]    = vec4(1.0); // Setzt die 3.Zeile der Matrix komplett auf 1.0&lt;br /&gt;
MyMat4[3][3] = 3.5;       // Setzt das Element unren rechts auf 3.5&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ein Zugriff auf Matrixelemente ausserhalb ihrer Dimension (also z.B. MyMat4[4][4]) liefert unvorhersehabre Ergebnise, also sollte man auf diese Fälle prüfen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Vektor- und Matrixoperationen==&lt;br /&gt;
&lt;br /&gt;
Wie von C gewohnt sind in glSlang so ziemlich alle Operatoren die man auf Matrizen oder Vektoren anwenden kann überladen, so das man nicht umständlich über selbstgeschriebene Funktionen kombinieren muss. Darüber hinaus ist es in den meisten Fällen auch möglich ohne Konvertierung Fließkommawerte mit kompletten Matrizen oder Vektoren zu kombinieren. Folgende Beispiele zeigen einige der vielfältigen Kombinationsmöglichkeiten auf :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
vec3  dest;&lt;br /&gt;
vec3  source;&lt;br /&gt;
float factor;&lt;br /&gt;
&lt;br /&gt;
vec3 dest = source + factor; &lt;br /&gt;
&lt;br /&gt;
// Ist gleich&lt;br /&gt;
dest.x = source.x + factor;&lt;br /&gt;
dest.y = source.y + factor;&lt;br /&gt;
dest.z = source.z + factor;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Matrix * Vektor ist auch ohne manuelle Konvertierung möglich :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
vec3  dest;&lt;br /&gt;
vec3  source;&lt;br /&gt;
mat3  MyMat;&lt;br /&gt;
 &lt;br /&gt;
dest = source * MyMat; &lt;br /&gt;
 &lt;br /&gt;
// Ist gleich&lt;br /&gt;
dest.x = dot(source, MyMat[0]);&lt;br /&gt;
dest.y = dot(source, MyMat[1]);&lt;br /&gt;
dest.z = dot(source, MyMat[2]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auch hier sind die Möglichkeiten fast unbeschränkt und zeigen wieder wie flexibel glSlang ausgelegt ist. &lt;br /&gt;
&lt;br /&gt;
==Operatoren==&lt;br /&gt;
&lt;br /&gt;
glSlang bietet (momentan) folgende Operatoren, die Liste ist nach ihrer Gewichtung sortiert (Anfang = höchste). Alle ''reservierten'' Operatoren werden erst in kommender Hardware/glSlang-Versionen nutzbar sein :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div  align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|{{Prettytable_B1}}&lt;br /&gt;
!Operatorklasse  	&lt;br /&gt;
!Operatoren  	&lt;br /&gt;
!Assoziation&lt;br /&gt;
|-&lt;br /&gt;
|Gruppering 	&lt;br /&gt;
|() 	&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
|Arrayindizierung&amp;lt;br&amp;gt;Funktionsaufrufe und Konstruktoren&amp;lt;br&amp;gt;Strukturfeldwahl und Swizzle&amp;lt;br&amp;gt;Postinkrement und -dekrement&amp;lt;br&amp;gt; 	&lt;br /&gt;
|[]&amp;lt;br&amp;gt;()&amp;lt;br&amp;gt;.&amp;lt;br&amp;gt;++ -- 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Prefixinkrement- und dekrement&amp;lt;br&amp;gt;Einheitlich (~ reserviert) 	&lt;br /&gt;
| ++ --&amp;lt;br&amp;gt; + - ~ ! 	&lt;br /&gt;
|Rechts n. Links&lt;br /&gt;
|-&lt;br /&gt;
|Mulitplikation (% reserviert) 	&lt;br /&gt;
|* / % 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Additiv 	&lt;br /&gt;
| + - 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Bitweises Verschieben (reserviert) 	&lt;br /&gt;
|&amp;lt;&amp;lt;  &amp;gt;&amp;gt; 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Relation 	&lt;br /&gt;
|&amp;lt;  &amp;gt;  &amp;lt;=  &amp;gt;= 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Vergleich 	&lt;br /&gt;
|==  != 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Bitweises AND (reserviert) 	&lt;br /&gt;
|&amp;amp; 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Bitweises XOR (reserviert) 	&lt;br /&gt;
|^ 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Bitweises OR (reserviert) 	&lt;br /&gt;
| &amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt; 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Logisches AND 	&lt;br /&gt;
|&amp;amp;&amp;amp; 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Logisches XOR 	&lt;br /&gt;
|^^ 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Logisches OR 	&lt;br /&gt;
| &amp;lt;nowiki&amp;gt;||&amp;lt;/nowiki&amp;gt; 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Auswahl 	&lt;br /&gt;
|?: 	&lt;br /&gt;
|Rechts n. Links&lt;br /&gt;
|-&lt;br /&gt;
|Zuweisung&amp;lt;br&amp;gt;Arithmetrische Zuweisung&amp;lt;br&amp;gt;(Modulis, Shift und bitweise Op. reserviert) 	&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt;&amp;lt;br&amp;gt; &amp;lt;nowiki&amp;gt;+= -=  *=  /=  %=&amp;lt;/nowiki&amp;gt; &amp;lt;br&amp;gt; &amp;lt;nowiki&amp;gt;&amp;lt;&amp;lt;=  &amp;gt;&amp;gt;= &amp;amp;=  ^=  |=&amp;lt;/nowiki&amp;gt; 	&lt;br /&gt;
|Rechts n. Links&lt;br /&gt;
|-&lt;br /&gt;
|Aufzählung 	&lt;br /&gt;
|, 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Funktionen==&lt;br /&gt;
&lt;br /&gt;
Ein großer Vorteil von Hochsprachen ist u.A. die Möglichkeit oft genutzte Codeteile in Funktionen (bzw. auch Prozeduren unter Pascal) zu verpacken um so Flexibilität als auch Übersichtlichkeit zu steigern. Wer schonmal was in C geschrieben hat, der wird sich jetzt sicherlich kein Kopfzerbrechen machen müssen. Funktionen werden in glSlang genauso nach folgendem Prinzip deklariert :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
RückgabeTyp FunktionsName(Typ0 Argument0, Typ1, Argument1, ... , TypN, ArgumentN)&lt;br /&gt;
 {&lt;br /&gt;
 return RückgabeWert;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Funktionen die ''nichts zurückgeben'' müssen mit dem RückgabeTyp {{INLINE_CODE|void}} deklariert werden, ausserdem entfällt dann logischerweise das {{INLINE_CODE|return}}. Falls die Funktion eines ihrere Argumente nach aussen übergeben soll, muss dieses Argument mit dem Typenqualifizierer out (Siehe Kapitel 4.2) versehen werden. ''Arrays'' können nur als Eingabeargumente übergeben werden und dürfen nich dimensioniert als Argument verwendet werden, sondern müssen mit leeren Klammern argumentiert werden.&lt;br /&gt;
Ein paar Beispiele :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
void MeineFunktion(float EingabeWert; out float AusgabeWert)&lt;br /&gt;
 {&lt;br /&gt;
 AusgabeWert = EingabeWert*MyConstValue;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Funktion gibt ''nichts'' zurück, aber gibt EingabeWert*MyConstValue im Ausgabeargument AusgabeWert nach aussen.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
float MeineFunktion(float EingabeWert)&lt;br /&gt;
 {&lt;br /&gt;
 return EingabeWert*MyConstValue;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bietet genau die selbe Funktionalität wie das Beispiel darüber. Allerdings wird hier der berechnete Wert als Ergebnis der Funktion zurückgeliefert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
float VektorSumme(float v[])&lt;br /&gt;
 {&lt;br /&gt;
 return v[0]+v[1]+v[2]+v[3];&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wie bereits gesagt darf ein Array als Argument keine Dimensionierung enthalten. Wenn man der Funktion also ein Array übergibt, sollte man vorher drauf achten das es entsprechend der in der Funktion genutzten Indizes dimensioniert wurde.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==if-Anweisung==&lt;br /&gt;
&lt;br /&gt;
Selektion über eine if-Anweisung darf auch in keiner Hochsprache fehlen. Genauso wie in C oder Delphi erwartet auch hier die If-Anweisung einen boolschen Ausdruck (Wahr oder Falsch) und wird dann ausgeführt (wahr) bzw. verzweigt auf ein (wenn vorhanden) else (falsch). Verschachtelung ist wie erwartet auch möglich.&lt;br /&gt;
&lt;br /&gt;
'''Hinweis : ''' &lt;br /&gt;
Grafikkarten auf dem Stand des Shadermodells 2.0 (Radeon 9x00, Radeon X8x0, GeForceFX 5x00) unterstüzten im Fragmentshader kein Early-Out, was zur Folge hat das bei einer If-Anweisung immer alle Zweige ausgeführt werden. Am Ende wird dann aber nur ein Ergebnis geschrieben, die anderen verworfen. Auf solchen Karten bringen If-Anweisungen also im Normalfall keine Geschwindigkeitssteigerung, sondern oft eher das Gegenteil.&lt;br /&gt;
Neuere SM3.0-Karten (Radeon X1x00, GeForce6x00 und höher) ist dass nicht mehr der Fall, da hier dynamische Verzweigungen und auch Early-Out von der Hardware implementiert werden.&lt;br /&gt;
&lt;br /&gt;
==Schleifen==&lt;br /&gt;
&lt;br /&gt;
Auch Schleifen, ein wichtiges Konzept jeder Hochsprache haben ihren Weg in glSlang gefunden. Unterstützt werden folgende Schleifentypen :&lt;br /&gt;
&lt;br /&gt;
* '''for'''-Schleife&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
for (Startausdruck; Durchlaufbedingung; Wiederholungsausdruck)&lt;br /&gt;
  {&lt;br /&gt;
   statement&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''while'''-Schleife&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
while (Durchlaufbedingung)&lt;br /&gt;
 {&lt;br /&gt;
  statement&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''do'''-while-Schleife&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
do&lt;br /&gt;
 {&lt;br /&gt;
  statement&lt;br /&gt;
 }&lt;br /&gt;
 while (Durchlaufbedingung)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Hinweis :''' Grafikkarten auf dem Stand des Shadermodells 2.0 (Radeon 9x00, Radeon X8x0, GeForceFX 5x00) unterstüzten Schleifen nicht in Hardware. Schleifen werden dann beim Kompilieren vom Treiber entrollt, wodurch natürlich Shader mit weitaus mehr Instruktionen als erwartet generiert werden. Von daher sollte man auf solchen Karten möglichst auf Schleifen verzichten, oder diese nur recht kurz halten. Bei SM3.0-Karten (Radeon X1x00, GeForce6x00 und höher) ist dass nicht mehr der Fall.&lt;br /&gt;
&lt;br /&gt;
=Eingebaute Variablen, Attribute und Konstanten=&lt;br /&gt;
Nachdem wir uns nun lange genug mit den minderinterssanten Elementen der glSlang-Syntax beschäftigt haben, gehts jetzt endlich an die wirklich interessanten Dinge. Wie schon ARB_VP/ARB_FP bringt auch glSlang jede Menge eingabauter Variablen, Attribute und Konstanten mit, deren Aliase sie recht leicht identifizierbar machen (ganz im Gegensatz zum Indexgewusel bei den DX-Shadern).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Variablen im Vertex Shader==&lt;br /&gt;
Exklusiv im Vertex Shader stehen die folgenden Variablen zur Verfügung :&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_Position    muss geschrieben werden&lt;br /&gt;
:Dieser Variable '''muss''' im Vertexshader ein Wert zugewiesen werden, wird dies nicht getan ist das Ergebnis (sprich die Position des Vertex) undefiniert. Vorgesehen ist diese Variable für die ''homogene Position des Vertex'' und wird u.a. zum Clipping und Culling verwendet. Sie darf natürlich auch (mehrfach) geschrieben und ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
* float gl_PointSize    kann geschrieben werden&lt;br /&gt;
:Diese Variable wurde dazu vorgesehen um dort im VertexShader die Punktgröße in Pixeln hineinzuschreiben.&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_ClipVertex    kann geschrieben werden&lt;br /&gt;
:Falls genutzt, sollten hier die Vertexkoordinaten die im Zusammenhang mit benutzerdefinierten Clippingplanes genutzt werden abgelegt werden. Wichtig ist, das gl_ClipVertex im selben Koordinatenraum wie die Clippingplane definiert ist.&lt;br /&gt;
&lt;br /&gt;
==Attribute im Vertex Shader==&lt;br /&gt;
&lt;br /&gt;
Folgende Attribute stehen nur im Vertex Shader zur Verfügung und '''können nur gelesen werden''' :&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_Color&lt;br /&gt;
: Farbwert des Vertex.&lt;br /&gt;
* vec4 gl_SecondaryColor&lt;br /&gt;
:Sekundärer Farbwert des Vertex.&lt;br /&gt;
* vec4 gl_Normal&lt;br /&gt;
:Normale des Vertex.&lt;br /&gt;
* vec4 gl_Vertex&lt;br /&gt;
:Koordinaten des Vertex;&lt;br /&gt;
* vec4 gl_MultiTexCoord0..7&lt;br /&gt;
:Texturkoordinaten auf Textureinheit 0..7.&lt;br /&gt;
* float gl_FogCoord&lt;br /&gt;
:Nebelkoordinate des Vertex. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Variablen im Fragment Shader==&lt;br /&gt;
&lt;br /&gt;
Im Fragment Shader sind folgende Variablen exklusiv nutzbar :&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_FragColor&lt;br /&gt;
: Speichert den Farbwert des Fragmentes, der von folgenden Funktionen der festen Pipeline genutzt wird. Wird dieser Variable nichts zugewiesen, so ist ihr Inhalt undefiniert und darauf aufbauende Ergebnisse ebenfalls.&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_FragData[0..15]&lt;br /&gt;
: Ersetzt gl_FragColor bei der Verwendung von multiplen Rendertargets. &lt;br /&gt;
&lt;br /&gt;
* float gl_FragDepth&lt;br /&gt;
: Durch schreiben dieser Variable kann man den von der festen Funktionspipeline ermittelten Tiefenwert überspringen, der mit {{INLINE_CODE|gl_FragCoord.z}} ausgelesen werden kann. Wird dieser Wert nicht geschrieben, nutzen folgende Funktionen der Pipeline den vorher fest berechneten Wert.&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_FragCoord    nur lesen&lt;br /&gt;
: In dieser Variable ist die Position des Fragmentes relativ zur Fensterposition im Format x,y,z,1/w abgelegt, wobei z den von der festen Funktionspipeline berechneten Tiefenwert enthält.&lt;br /&gt;
&lt;br /&gt;
* bool gl_FrontFacing    nur lesen&lt;br /&gt;
: Gibt an ob das Fragment zu einer nach vorne zeigenden Primitive gehört (=true). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Bezug auf {{INLINE_CODE|gl_FragColor}} und {{INLINE_CODE|gl_FragDepth}} sei noch anzumerken das diese ''nicht'' in den Wertebereich 0..1 gebracht werden müssen, da dies später durch die feste Funktionspipeline automatisch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
==Eingebaute Varyings==&lt;br /&gt;
&lt;br /&gt;
Wie bereits in Kapitel 4.2 erwähnt, stellen Varyings eine Schnittstelle zwischen dem Vertex und dem Fragment Shader dar. Sie werden im Vertex Shader geschrieben und können dann im Fragment Shader ausgelesen werden, ohne das die folgenden Varyings dafür explizit deklariert werden müssen :&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_FrontColor&lt;br /&gt;
: Farbe der Vorderseite des Vertex.&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_BackColor&lt;br /&gt;
: Farbe der Rückseite des Vertex.&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_FrontSecondaryColor&lt;br /&gt;
: Sekundäre Farbe der Vorderseite des Vertex.&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_BackSecondaryColor&lt;br /&gt;
: Sekundäre Farbe der Rückseite des Vertex.&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_TexCoord[x]&lt;br /&gt;
: Texturkoordinaten des Vertex auf Textureinheit x, wobei x die von der Hardware zur Verfügung gestellte Zahl der Textureinheiten-1 nicht überschreiten darf.&lt;br /&gt;
&lt;br /&gt;
* float gl_FogFragCoord&lt;br /&gt;
: Nebelkoordinate des Fragmentes. &lt;br /&gt;
&lt;br /&gt;
Die Varyings {{INLINE_CODE|gl_FrontColor, gl_FrontSecondaryColor, gl_BackColor}} und {{INLINE_CODE|gl_BackSecondaryColor}} können im FragmentShader nur unter den Aliases gl_Color bzw. gl_SecondaryColor gelesen werden. Welcher Wert des Vertex Shaders im Fragment Shader dort eingesetzt wird ist abhängig davon ob das Fragment zu einer nach vorne oder nach hinten zeigenden Primitive gehört.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Eingebaute Konstanten==&lt;br /&gt;
Auch diverse Konstanten wurden definiert um darauf schnell im Shader zugreifen zu können. In den Klammern stehen die von einer GL-Implementation als Mindestanforderung anzubietenden Werte. Alle Konstanten sind sowohl im Vertex als auch im Fragment Shader abrufbar :&lt;br /&gt;
&lt;br /&gt;
: OpenGL 1.0/1.2 :&lt;br /&gt;
* int gl_MaxLights (8)&lt;br /&gt;
* int gl_MaxClipPlanes (6)&lt;br /&gt;
* int gl_MaxTextureUnits (2)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
: ARB_Fragment_Program :&lt;br /&gt;
* int gl_MaxTextureCoordsARB (2)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
: Vertex_Shader :&lt;br /&gt;
* int gl_MaxVertexAttributesGL2 (16)&lt;br /&gt;
* int gl_MaxVertexUniformFloatsGL2 (512)&lt;br /&gt;
* int gl_MaxVaryingFloatsGL2 (32)&lt;br /&gt;
* int gl_MaxVertexTextureUnitsGL2 (1)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
: Fragment_Shader :&lt;br /&gt;
* int gl_MaxFragmentTextureUnitsGL2 (2)&lt;br /&gt;
* int gl_MaxFragmentUniformFloatsGL2 (64)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Eingebaute Uniformvariablen==&lt;br /&gt;
&lt;br /&gt;
Um den Zugriff auf OpenGL-Staten zu vereinfachen wurden in glSlang diverse Uniformvariablen zur direkten Verwendung im Shader eingebaut. Wie gewohnt wurden auch hier sinnvolle Namen verwendet, so dass eine tiefere Erklärung unnötig sein dürfte :&lt;br /&gt;
&lt;br /&gt;
* mat4 gl_ModelViewMatrix&lt;br /&gt;
* mat4 gl_ProjectionMatrix&lt;br /&gt;
* mat4 gl_ModelViewProjectionMatrix&lt;br /&gt;
* mat3 gl_NormalMatrix&lt;br /&gt;
:{{INLINE_CODE|gl_NormalMatrix}} repräsentiert die invertierten und anschließend transponierten oberen 3x3 Werte der {{INLINE_CODE|gl_ModelViewMatrix}}.&lt;br /&gt;
* mat4 gl_TextureMatrix[gl_MaxTextureCoordsARB]&lt;br /&gt;
&lt;br /&gt;
* float gl_NormalScale&lt;br /&gt;
: Gibt den unter OpenGL festgelegten Faktor zur Skalierung der Normalen zurück.&lt;br /&gt;
&lt;br /&gt;
* struct gl_DepthRangeParameters&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct gl_DepthRangeParameters&lt;br /&gt;
{&lt;br /&gt;
 float near;&lt;br /&gt;
 float far;&lt;br /&gt;
 float diff;&lt;br /&gt;
};&lt;br /&gt;
gl_DepthRangeParameters gl_DepthRange;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
: Clippingplanes : &lt;br /&gt;
* vec4 gl_ClipPlane[gl_MaxClipPlanes]&lt;br /&gt;
  &lt;br /&gt;
*struct gl_PointParameters&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct gl_PointParameters&lt;br /&gt;
{&lt;br /&gt;
 float size;&lt;br /&gt;
 float sizeMin;&lt;br /&gt;
 float sizeMax;&lt;br /&gt;
 float fadeThresholdSize;&lt;br /&gt;
 float distanceConstantAttenuation;&lt;br /&gt;
 float distanceLinearAttenuation;&lt;br /&gt;
 float distanceQuadraticAttenuation;&lt;br /&gt;
};&lt;br /&gt;
gl_PointParameters gl_Point;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*struct gl_MaterialParameters&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct gl_MaterialParameters&lt;br /&gt;
{&lt;br /&gt;
 vec4 emission;&lt;br /&gt;
 vec4 ambient;&lt;br /&gt;
 vec4 diffuse;&lt;br /&gt;
 vec4 specular;&lt;br /&gt;
 float shininess;&lt;br /&gt;
};&lt;br /&gt;
gl_MaterialParameters gl_FrontMaterial;&lt;br /&gt;
gl_MaterialParameters gl_BackMaterial;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*struct gl_LightSourceParameters&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct gl_LightSourceParameters&lt;br /&gt;
{&lt;br /&gt;
 vec4 ambient;&lt;br /&gt;
 vec4 diffuse;&lt;br /&gt;
 vec4 specular;&lt;br /&gt;
 vec4 position;&lt;br /&gt;
 vec4 halfVector;&lt;br /&gt;
 vec3 spotDirection;&lt;br /&gt;
 float spotExponent;&lt;br /&gt;
 float spotCutoff;&lt;br /&gt;
 float spotCosCutoff;&lt;br /&gt;
 float constantAttenuation;&lt;br /&gt;
 float linearAttenuation;&lt;br /&gt;
 float quadraticAttenuation;&lt;br /&gt;
};&lt;br /&gt;
gl_LightSourceParameters gl_LightSource[gl_MaxLights];&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*struct gl_LightModelParameters&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct gl_LightModelParameters&lt;br /&gt;
{&lt;br /&gt;
 vec4 ambient;&lt;br /&gt;
};&lt;br /&gt;
gl_LightModelParameters gl_LightModel;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*struct gl_LightModelProducts&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct gl_LightModelProducts&lt;br /&gt;
{&lt;br /&gt;
 vec4 sceneColor;&lt;br /&gt;
};&lt;br /&gt;
gl_LightModelProducts gl_FrontLightModelProduct;&lt;br /&gt;
gl_LightModelProducts gl_BackLightModelProduct;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*struct gl_LightProducts&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct gl_LightProducts&lt;br /&gt;
{&lt;br /&gt;
 vec4 ambient;&lt;br /&gt;
 vec4 diffuse;&lt;br /&gt;
 vec4 specular;&lt;br /&gt;
};&lt;br /&gt;
gl_LightProducts gl_FrontLightProduct[gl_MaxLights];&lt;br /&gt;
gl_LightProducts gl_BackLightProduct[gl_MaxLights];&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* vec4 gl_TextureEnvColor[gl_MaxFragmentTextureUnitsGL2]&lt;br /&gt;
* vec4 gl_EyePlaneS[gl_MaxTextureCoordsARB]&lt;br /&gt;
* vec4 gl_EyePlaneT[gl_MaxTextureCoordsARB]&lt;br /&gt;
* vec4 gl_EyePlaneR[gl_MaxTextureCoordsARB]&lt;br /&gt;
* vec4 gl_EyePlaneQ[gl_MaxTextureCoordsARB]&lt;br /&gt;
* vec4 gl_ObjectPlaneS[gl_MaxTextureCoordsARB]&lt;br /&gt;
* vec4 gl_ObjectPlaneT[gl_MaxTextureCoordsARB]&lt;br /&gt;
* vec4 gl_ObjectPlaneR[gl_MaxTextureCoordsARB]&lt;br /&gt;
* vec4 gl_ObjectPlaneQ[gl_MaxTextureCoordsARB]&lt;br /&gt;
&lt;br /&gt;
*struct gl_FogParameters&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct gl_FogParameters&lt;br /&gt;
{&lt;br /&gt;
 vec4 color;&lt;br /&gt;
 float density;&lt;br /&gt;
 float start;&lt;br /&gt;
 float end;&lt;br /&gt;
 float scale;&lt;br /&gt;
};&lt;br /&gt;
gl_FogParameters gl_Fog;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Diese recht umfangreiche GL-Stateliste sollte eigentlich jeden Bedarf decken und momentan gibts kaum einen OpenGL-Status den man so nicht in einem Shader abfragen bzw. nutzen kann.&lt;br /&gt;
&lt;br /&gt;
=Eingebaute Funktionen=&lt;br /&gt;
glSlang ist mit diversen Skalar- und Vektorfunktionen ausgestattet, die teilweise (idealerweise) sogar direkt in der Hardware ausgeführt werden, weshalb einer fertigen Funktion ggü. gleichwertigen eigenen Berechnungen immer der Vorzug zu geben ist.&lt;br /&gt;
{{Hinweis| ''genType'' kann vom Type float, vec2, vec3 oder vec4 sein, ''mat'' vom Typ mat2, mat3 oder mat4.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Trigonometrie und Winkel==&lt;br /&gt;
Alle übergebenen Winkel sollten, soweit nicht anders vermerkt, in Radien angegeben werden.&lt;br /&gt;
&lt;br /&gt;
* genType radians (genType degrees)&lt;br /&gt;
: Wandelt von Grad nach Radien. &lt;br /&gt;
* genType degrees (genType radians)&lt;br /&gt;
: Wandelt von Radien nach Grad.&lt;br /&gt;
* genType sin (genType angle)&lt;br /&gt;
: Gibt den Sinus von Angle zurück, wobei Angle in Radien angegeben wird.&lt;br /&gt;
* genType cos (genType angle)&lt;br /&gt;
: Gibt den Cosinus von Angle zurück, wobei Angle in Radien angegeben wird.&lt;br /&gt;
* genType tan (genType angle)&lt;br /&gt;
: Gibt den Tangens von Angle zurück, wobei Angle in Radien angegeben wird.&lt;br /&gt;
* genType asin (genType x)&lt;br /&gt;
: Liefert den Arcsinus von x zurück, also den Winkel dessen Sinus x ergeben würde.&lt;br /&gt;
* genType acos (genType x)&lt;br /&gt;
: Liefert den Arccosinus von x zurück, also den Winkel dessen Cosinus x ergeben würde.&lt;br /&gt;
* genType atan (genType y, genType x)&lt;br /&gt;
: Liefert den Winkel zurück, dessen Tangens x/y ergeben würde.&lt;br /&gt;
* genType atan (genType y_over_x)&lt;br /&gt;
: Liefert den Winkel zurück, dessen Tangens x über y ergeben würde.&lt;br /&gt;
&lt;br /&gt;
==Exponentiell==&lt;br /&gt;
* genType pow (genType x, genType y)&lt;br /&gt;
: Gibt x hoch y zurück.&lt;br /&gt;
* genType exp2 (genType x)&lt;br /&gt;
: Gibt 2 hoch x zurück.&lt;br /&gt;
* genType log2 (genType x)&lt;br /&gt;
: Gibt den Logarithmus zur Basis 2 von x zurück.&lt;br /&gt;
* genType sqrt (genType x)&lt;br /&gt;
: Gibt die Wurzel von x zurück.&lt;br /&gt;
* genType inversesqrt (genType x)&lt;br /&gt;
: Gibt die umgekehrte Wurzel von x zurück. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Standardfunktionen==&lt;br /&gt;
* genType abs (genType x)&lt;br /&gt;
: Liefert den absoluten Wert von x zurück.&lt;br /&gt;
* genType sign (genType x)&lt;br /&gt;
: Gibt -1.0 zurück, wenn x &amp;lt; 0.0, 0.0 wenn x = 0.0 und 1.0 wenn x &amp;gt; 0.0.&lt;br /&gt;
* genType floor (genType x)&lt;br /&gt;
: Gibt denn nächsten Integerwert zurück, der kleiner oder gleich x ist.&lt;br /&gt;
* genType ceil (genType x)&lt;br /&gt;
: Gibt den nächsten Integerwert zurück, der größer oder gleich x ist.&lt;br /&gt;
* genType fract (genType x)&lt;br /&gt;
: Gibt den Nachkommateil von x zurück.&lt;br /&gt;
* genType mod (genType x, float y) &lt;br /&gt;
* genType mod (genType x, genType y)&lt;br /&gt;
: Gibt den Modulus zurück. (=x-y * floor(x/y)) &lt;br /&gt;
* genType min (genType x, genType y) &lt;br /&gt;
* genType min (genType x, float y)&lt;br /&gt;
: Liefert y zurück wenn y &amp;lt; x, ansonsten x. &lt;br /&gt;
* genType max (genType x, genType y) &lt;br /&gt;
* genType max (genType x, float y)&lt;br /&gt;
: Liefert y zurück wenn x &amp;lt; y, ansonsten x. &lt;br /&gt;
* genType clamp (genType x, genType minVal, genType maxVal) &lt;br /&gt;
* genType clamp (genType x, float minVal, float maxVal)&lt;br /&gt;
: Zwängt x in den Bereich minVal..maxVal. &lt;br /&gt;
* genType mix (genType x, genType y, genType a)&lt;br /&gt;
* genType mix (genType x, genType y, float a)&lt;br /&gt;
: Liefert den linearen Blend zwischen x und y zurück. (= x * (1-a) + y * a) &lt;br /&gt;
* genType step (genType edge, genType x)&lt;br /&gt;
* genType step (float edge, genType x)&lt;br /&gt;
: Liefert 0.0 zurück, wenn x &amp;lt;= edge, ansonsten 1.0. &lt;br /&gt;
* genType smoothstep (genType edge0, genType edge1, genType x)&lt;br /&gt;
* genType smoothstep (float edge0, float edge1, genType x)&lt;br /&gt;
: Liefert 0.0 zurück, wenn x &amp;lt;= edge und 1.0 wenn x &amp;gt;= edge. Dabei wird eine weiche Hermite Interpolation zwischen 0 und 1 durchgeführt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Geometrie==&lt;br /&gt;
* float length (genType x)&lt;br /&gt;
: Gibt die Länge des Vektors x (= sqrt(x[0]² + x[1]² + ... + x[n]²) zurück. &lt;br /&gt;
* float distance (genType p0, genType p1)&lt;br /&gt;
: Gibt die Distanz zwischen den zwei Vektoren p0 un p1 (= length(p0-p1)) zurück. &lt;br /&gt;
* float dot (genType x, genType y)&lt;br /&gt;
: Gibt das Punktprodukt von x und y zurück (=x[0]*y[0] + x[1]*y[1] + ... + x[n]*y[n]). &lt;br /&gt;
* vec3 cross (vec3 x, vec3 y)&lt;br /&gt;
: Gibt das Kreuzprodukt von x und y zurück. &lt;br /&gt;
* genType normalize (genType x)&lt;br /&gt;
: Normalisiert den Vektor x auf die Länge 1. &lt;br /&gt;
* vec4 ftransform()&lt;br /&gt;
: Nur im Vertex Shader. Die Funktion stellt sicher, das das eingehende Vertex haargenau so transformiert wird wie in der festen Funktionspipeline. gl_Position = ftransform() wird dann also gebraucht, wenn in mehreren Durchgängen sowohl im Shader als auch in der festen Pipeline gerendert wird, um sicherzustellen das in beiden Fällen die gleiche Vertexposition herauskommt. &lt;br /&gt;
* genType faceforward (genType N, genType I, genType Nref)&lt;br /&gt;
: Gibt einen nach vorne zeigenden Vektor N zurück. (If dot(NRef, I) &amp;lt; 0 return N else return -N) &lt;br /&gt;
* genType reflect (genType I, genType N)&lt;br /&gt;
: Gibt den an der Flächenausrichtung N reflektierten Vektor I zurück. (=I-2 * dot(N,I) * N) &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Matrixfunktionen==&lt;br /&gt;
* mat matrixCompMult (mat x, mat y)&lt;br /&gt;
: Multipliziert Matrix X mit Matrix Y komponentenweise. Um eine normale lineare Matrixmultiplikation durchzuführen, sollte der &amp;quot;*&amp;quot;-Operator genutzt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Vektorvergleiche==&lt;br /&gt;
Die meisten Vektorvergleichsfunktionen liefern als Ergebnis einen boolvektor zurück, da die Vergleiche per Komponente stattfinden. Wenn man also x = vec4(1.0, 3.0, 0.0, 0.0) mit y = vec4(2.0, 1.5, 1.5, 0.0) via lessThan(x, y) vergleicht, erhält man als Ergebnis bvec(true, false, true, false).&lt;br /&gt;
&lt;br /&gt;
* bvec lessThan (vec x, vec y)&lt;br /&gt;
* bvec lessThan (ivec x, ivec y)&lt;br /&gt;
: Gibt den komponentenweisen Vergleich x &amp;lt; y zurück. &lt;br /&gt;
* bvec lessThanEqual (vec x, vec y)&lt;br /&gt;
* bvec lessThanEqual (ivec x, ivec y)&lt;br /&gt;
: Gibt den komponentenweisen Vergleich x &amp;lt;= y zurück. &lt;br /&gt;
* bvec greaterThan (vec x, vec y)&lt;br /&gt;
* bvec greaterThan (ivec x, ivec y)&lt;br /&gt;
: Gibt den komponentenweisen Vergleich x &amp;gt; y zurück. &lt;br /&gt;
* bvec greaterThanEqual (vec x, vec y)&lt;br /&gt;
* bvec greaterThanEqual (ivec x, ivec y)&lt;br /&gt;
: Gibt den komponentenweisen Vergleich x &amp;gt;= y zurück. &lt;br /&gt;
* bvec equal (vec x, vec y)&lt;br /&gt;
* bvec equal (ivec x, ivec y)&lt;br /&gt;
* bvec equal (bvec x, bvec y)&lt;br /&gt;
: Gibt den komponentenweisen Vergleich x == y zurück. &lt;br /&gt;
* bvec notEqual (vec x, vec y)&lt;br /&gt;
* bvec notEqual (ivec x, ivec y)&lt;br /&gt;
* bvec notEqual (bvec x, bvec y)&lt;br /&gt;
: Gibt den komponentenweisen Vergleich x != y zurück. &lt;br /&gt;
* bool any (bvec x)&lt;br /&gt;
: Liefert true zurück, wenn mindestens eine der Komponenten von x true ist.&lt;br /&gt;
* bool all (bvec x)&lt;br /&gt;
: Liefert true zurück, wenn alle Komponenten von x true sind. &lt;br /&gt;
* bvec not (bvec x)&lt;br /&gt;
: Liefert die logische Negation von x zurück. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Texturenzugriffe==&lt;br /&gt;
&lt;br /&gt;
Diese wichtige Funktionskategorie dient dazu, Werte aus einer an eine Textureinheit gebundenen Textur zu ermitteln. Die Texturenzugriffe können sowohl im Vertex (!) als auch im Fragment Shader ausgeführt werden, wobei der optionale Parameter bias im Vertex Shader ignoriert wird. Allerdings gibt es zusätzlich Funktionen die auf &amp;quot;Lod&amp;quot; enden und nur im Vertex Shader genutzt werden dürfen um eben dieses Manko zu umgehen. Funktionen mit dem Suffix &amp;quot;Proj&amp;quot; geben einen projizierten Texturenwert zurück.&lt;br /&gt;
&lt;br /&gt;
: '''1D-Texturen :'''&lt;br /&gt;
* vec4 texture1D (sampler1D sampler, float coord [, float bias])&lt;br /&gt;
* vec4 texture1DProj (sampler1D sampler, vec2 coord [, float bias])&lt;br /&gt;
* vec4 texture1DProj (sampler1D sampler, vec4 coord [, float bias])&lt;br /&gt;
: Nur im Vertex Shader :&lt;br /&gt;
* vec4 texture1DLod (sampler1D sampler, float coord, float lod)&lt;br /&gt;
* vec4 texture1DProjLod (sampler1D sampler, vec2 coord, float lod)&lt;br /&gt;
* vec4 texture1DProjLod (sampler1D sampler, vec4 coord, float lod)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
: '''2D-Texturen :'''&lt;br /&gt;
* vec4 texture2D (sampler2D sampler, vec2 coord [, float bias])&lt;br /&gt;
* vec4 texture2DProj (sampler2D sampler, vec3 coord [, float bias])&lt;br /&gt;
* vec4 texture2DProj (sampler2D sampler, vec4 coord [, float bias])&lt;br /&gt;
: Nur im Vertex Shader : &lt;br /&gt;
* vec4 texture2DLod (sampler2D sampler, vec2 coord, float lod)&lt;br /&gt;
* vec4 texture2DProjLod (sampler2D sampler, vec3 coord, float lod)&lt;br /&gt;
* vec4 texture2DProjLod (sampler2D sampler, vec4 coord, float lod)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
: '''3D-Texturen :'''&lt;br /&gt;
* vec4 texture3D (sampler3D sampler, vec3 coord [, float bias])&lt;br /&gt;
* vec4 texture3DProj (sampler3D sampler, vec4 coord [, float bias])&lt;br /&gt;
: Nur im Vertex Shader : &lt;br /&gt;
* vec4 texture3DLod (sampler3D sampler, vec3 coord, float lod)&lt;br /&gt;
* vec4 texture3DProjLod (sampler3D sampler, vec4 coord, float lod)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
: '''Cubemap :'''&lt;br /&gt;
* vec4 textureCube (samplerCube sampler, vec3 coord [, float bias])&lt;br /&gt;
: Nur im Vertex Shader : &lt;br /&gt;
*vec4 textureCubeLod (samplerCube sampler, vec3 coord, float lod)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
: '''Tiefentextur (Shadowmap) :'''&lt;br /&gt;
* vec4 shadow1D (sampler1DShadow sampler, vec3 coord [, float bias])&lt;br /&gt;
* vec4 shadow2D (sampler2DShadow sampler, vec3 coord [, float bias])&lt;br /&gt;
* vec4 shadow1DProj (sampler1DShadow sampler, vec4 coord [, float bias])&lt;br /&gt;
* vec4 shadow2DProj (sampler2DShadow sampler, vec4 coord [, float bias])&lt;br /&gt;
: Nur im Vertex Shader :&lt;br /&gt;
* vec4 shadow1DLod (sampler1DShadow sampler, vec3 coord, float lod)&lt;br /&gt;
* vec4 shadow2DLod (sampler2DShadow sampler, vec3 coord, float lod)&lt;br /&gt;
* vec4 shadow1DProjLod (sampler1DShadow sampler, vec4 coord, float lod)&lt;br /&gt;
* vec4 shadow2DProjLod (sampler2DShadow sampler, vec4 coord, float lod)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wie bereits eingangs gesagt ist dieses Kapitel ein sehr wichtiges, denn eine 3D-Szene ohne Texturen ist heute kaum denkbar. Darüber hinaus lassen sich durch Texturenzugriffe recht viele interessante Sachen machen, z.B. ein einfacher Blurfilter oder das freie überblenden bestimmter Texturenteile. Deshalb führe ich hier kurz ein paar Beispiele an, welche die Nutzung dieser Funktionen verdeutlichen sollen :&lt;br /&gt;
&lt;br /&gt;
===Beispiel A=== &lt;br /&gt;
Eine Textur gebunden die einfach ausgegeben werden soll&lt;br /&gt;
&lt;br /&gt;
''Im Vertex Shader'' :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
 gl_Position     = gl_ModelViewProjectionMatrix * gl_Vertex;&lt;br /&gt;
 gl_TexCoord[0]  = gl_MultiTexCoord0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
Der Vertex Shader ist recht minimal. Neben der homogenen Vertexposition leiten wir hier nur die im OpenGL-Programm angegebenen Texturkoordinaten weiter. ''Dies ist aber unbedingt nötig!'' Ohne die letzte Zeile hätten wir im Fragment Shader keine gültigen Texturkoordinaten auf TMU0, was in einer Fehldarstellung enden würde.&lt;br /&gt;
&lt;br /&gt;
''im Fragment Shader'' :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
uniform sampler2D texSampler;&lt;br /&gt;
&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
 gl_FragColor = texture2D(texSampler, vec2(gl_TexCoord[0]));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Zuerst deklarieren wir hier einen 2D-Texturensampler, wichtig : '''Texturensampler müssen IMMER als uniform deklariert werden!''' In der Hauptfunktion weisen wir dann einfach den über die Funktion texture2D aus unserer gebundenen Textur ausgelesenen Farbwert, anhand der vom Vertex Shader übergebenen Texturkoordinaten, zu.&lt;br /&gt;
&lt;br /&gt;
===Beispiel B=== &lt;br /&gt;
Zwei Texturen, jeweils auf TMU0 und TMU1. Fragmentfarbe soll eine Multiplikation der beiden Texturen darstellen.&lt;br /&gt;
&lt;br /&gt;
In diesem Beispielfall (der recht häufig vorkommt) müssen wir im Programm festlegen, ''welcher Sampler welche Textureinheit adressiert'', genau deshalb müssen die Texturensampler auch als uniform deklariert werden. Die Standardtextureneinheit eines Samplers ist TMU0, was in unserem Falle natürlich nicht brauchbar ist. Also müssen wir unserem zweiten Textursampler im Programm mitteilen das er seine Daten aus TMU1 beziehen soll :&lt;br /&gt;
&lt;br /&gt;
 glUniform1iARB(glSlang_GetUniLoc(ProgramObject, 'texSamplerTMU1'), 1);&lt;br /&gt;
&lt;br /&gt;
Dies ist also unbedingt zu machen, sobald ein Texturensampler eine Textureinheit &amp;gt; GL_TEXTURE_0 adressieren will. Die Textureneinheit des Samplers lässt sich also nicht im Shader selbst festlegen. Der Fragment Shader ist nun allerdings schnell hergeleitet (Vertex Shader verändert sich nicht, da TMU1 die Texturkoordinaten auch von TMU0 bezieht) :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
im Fragment Shader :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
uniform sampler2D texSamplerTMU0;&lt;br /&gt;
uniform sampler2D texSamplerTMU1;&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
    gl_FragColor = texture2D(texSamplerTMU0, vec2(gl_TexCoord[0])) *&lt;br /&gt;
                   texture2D(texSamplerTMU1, vec2(gl_TexCoord[0]));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Noisefunktionen==&lt;br /&gt;
Sowohl im Vertex als auch im Fragment Shader lassen sich [[GLSL noise|Noisefunktionen]] nutzen, mit deren Hilfe sich eine gewisse &amp;quot;Zufälligkeit&amp;quot; simulieren lässt (wirklich zufällige Werte sind es natürlich nicht). Ein zurückgegebener Wert liegt dabei immer im Bereich [-1..1] und ist immer bei gleichem Eigabewert auch immer gleich. Die Verwendung empfiehlt sich derzeit allerdings eher nicht, da nicht alle aktuellen Treiber die Funktionen unterstützen und eine Noisetextur wahrscheinlich performanter ist.&lt;br /&gt;
&lt;br /&gt;
* float noise1 (genType x)&lt;br /&gt;
* vec2 noise2 (genType x)&lt;br /&gt;
* vec3 noise3 (genType x)&lt;br /&gt;
* vec4 noise4 (genType x)&lt;br /&gt;
&lt;br /&gt;
==Discard==&lt;br /&gt;
Eigentlich keine Funktion, sondern eine Abbruchbedingung '''nur im Fragment Shader'''. Das Schlüsselwort {{INLINE_CODE|discard}} verwirft das aktuell bearbeitete Fragment und beendet gleichzeitig den Shader. Es kann z.B. genutzt werden um Alphamasking manuell durchzuführen.&lt;br /&gt;
Man sollte dabei jedoch beachten dass ein Großteil der aktuellen Hardware kein &amp;quot;early-out&amp;quot; (frühes Beenden) im Fragmentshader unterstützt. Wenn dort also ein {{INLINE_CODE|discard}} auftaucht, wird trotzdem auch der Code danach ausgeführt und einfach verworfen. Einen Geschwindigkeitsvorteil durch diesen Befehl wird man also erst auf neueren Karten feststellen, die dieses Faeature auch so unterstützen wie es angedacht war. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Beispielshader=&lt;br /&gt;
Wen bis hierhin nicht der Mut verlassen hat, und wer aufmerksam gelesen hat, dürfte jetzt also zumindest in der Lage sein kleinere Shader in glSlang zu schreiben und diese auch im Programm zu nutzen. Ich habe im Themenbereich &amp;quot;glSlang&amp;quot; versucht alle Bereiche der Shadersprache selbst anzusprechen und hoffe das auch brauchbar rübergebracht zu haben. Um oben erlerntes (hoffe ich doch mal) nochmal zu vertiefen werde ich jetzt (wie ich das bereits bei meinem ARB_VP-Tutorial getan habe) einen simplen Beispielshader (Vertex und Fragment Shader) auseinanderpflücken um so u.a. auch die Programmstruktur für alle die in C nicht so bewandert sind zu erörtern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Der Vertex Shader==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
uniform vec4 GlobalColor;&lt;br /&gt;
&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
 gl_Position     = gl_ModelViewProjectionMatrix * gl_Vertex;&lt;br /&gt;
 gl_FrontColor   = gl_Color * GlobalColor;&lt;br /&gt;
 gl_TexCoord[0]  = gl_MultiTexCoord0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wie gesagt recht simpel. Angefangen wird mit der Deklaration einer globalen Uniformvariable namens {{INLINE_CODE|GlobalColor}}. Wie wir uns erinnern gibt der Typenqualifizierer uniform an, das wir den Wert dieser Variable (ein 4-Komponentenvektor, da Farbwerte aus R,G,B und A bestehen) in unserem Programm an den Shader übermitteln.&lt;br /&gt;
&lt;br /&gt;
Danach gehts ohne Umwege direkt in unsere Hauptfunktion, da wir im Vertex Shader keine anderen Funktionen benötigen. Dort berechnen wir zuerst die homogene Position unseres Vertex, die sich aus der eingehenden Vertexposition multipliziert mit der Modelansichtsmatrix ergibt. Wie schonmal gesagt '''muss diesem Wert etwas zugewiesen werden''', da sonst alle darauf aufbauenden Funktionen unvorhersehbare Ergebnisse liefern.&lt;br /&gt;
Ausserdem wollen wir die Frontfarbe unseres Vertex jedesmal mit der im Programm übergebenen GlobalColor multiplizieren, so dass wir den Farbwert der gesamten Szene aus unserem Programm heraus manipulieren können. Zu guterletzt geben wir dann noch unsere aus der festen Funktionspipeline erhaltenen Texturkoordinaten auf Textureinheit 0 weiter. Wenn im Fragmentshader Texturkoordinaten verwendet werden, '''muss das getan werden'''. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Der Fragment Shader==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
uniform sampler2D Texture0;&lt;br /&gt;
uniform sampler2D Texture1;&lt;br /&gt;
uniform sampler2D Texture2;&lt;br /&gt;
uniform sampler2D Texture3;&lt;br /&gt;
&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
 vec2 TexCoord = vec2( gl_TexCoord[0] );&lt;br /&gt;
 vec4 RGB      = texture2D( Texture0, TexCoord );&lt;br /&gt;
&lt;br /&gt;
 gl_FragColor  = texture2D(Texture1, TexCoord) * RGB.r +&lt;br /&gt;
                 texture2D(Texture2, TexCoord) * RGB.g +&lt;br /&gt;
                 texture2D(Texture3, TexCoord) * RGB.b;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auch hier passiert nicht wirklich viel Großartiges. Wir deklarieren beim Shaderanfang zuerst vier Texturensampler, da wir insgesamt vier verschiedene Texturen im Shader auslesen wollen, eine Verlaufstextur und drei Oberflächentexturen. Auch hier sei wieder gesagt das man Sampler '''immer als uniform deklarieren muss'''. In der Hauptfunktion deklarieren wir dann einen Farbvektor, der auch direkt einen Farbwert aus Textureinheit 0 zugewiesen bekommt. Auf Textureinheit 0 haben wir ihm Hauptprogramm eine Verlaufstextur gebunden, die angibt wie die drei folgenden Texturen ineinander geblendet werden.&lt;br /&gt;
Danach schreiben wir dann den Farbwert des Fragmentes, der '''im Fragment Shader ausgegeben werden muss'''. Der besteht wie einfach zu erkennen aus Farbwert von Textureinheit 1 * Rotwert von Textureinheit 0 + Farbwert von Textureinheit 2 * Grünwert von Textureinheit 0 + Farbwert von Textureinheit 3 * Blauwert von Textureinheit 0. So ist z.B. an Stellen an denen in der Verlaufstextur reines blau liegt nur die dritte Textur sichtbar.&lt;br /&gt;
&lt;br /&gt;
So viel also zu unserem kleinen Beispielshader. Er ist weder besonders toll noch besonders sinnvoll, sollte aber auch eher dazu dienen euch glSlang ein wenig zu veranschaulichen, was mir hoffentlich gelungen ist.&lt;br /&gt;
&lt;br /&gt;
Wenn ihr in den vorangegangenen Kapiteln zumindest ein wenig aufgepasst habt, dann könnt ihr euch vor eurem inneren Auge hoffentlich vortstellen was der Shader macht : Er blendet drei Texturen weich anhand der Verlaufstextur ineinander über. Sowas kann man z.B. für ein Terrain nutzen, um dieses anhand einer Farbtextur zu texturieren. Für alle, die damit Probleme haben hier zwei Bilder die den Shader veranschaulichen. Links die Verlaufstextur, die angibt wo welche Textur wie stark gewichtet wird und rechts dann das Ergebnis :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; [[BILD:GLSL_sample_shader_a.jpg]] [[BILD:GLSL_sample_shader_b.jpg]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Post Mortem=&lt;br /&gt;
Das wars also, meine &amp;quot;Einführung&amp;quot; in die OpenGL Shader Sprache. Ich hoffe es hat euch nicht gelangweilt und auch die von mir zur Verfügung gestellten Informationen haben euch hoffentlich ausgereicht. Mit der Veröffentlichung dieser Einführung geht übrigens auch die Eröffnung eines Shaderforums hier auf der DGL einher, in der ihr dann also fleissig Fragen zum Thema stellen oder eure Shader präsentieren könnt. In diesem Post Mortem gehe ich jetzt noch kurz auf die Zukunft von glSlang ein und zeige ein paar Screenshots (damit die Augen entspannen können), bevor ihr euch dann selbst in die Shaderwelt stürzen könnt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Beispiele=&lt;br /&gt;
&lt;br /&gt;
Anbei ein paar exemplarische Screenshots. Da man mit GLSL aber alle möglichen Effekte berechnen kann (u.a. auch 1:1 die feste Funktionspipeline) ist es hier unmöglich einen Überblick aller möglichen Techniken zu geben.&lt;br /&gt;
&lt;br /&gt;
[[Datei:tut_glsl_eigenershader_01.png]] [[Datei:tut_glsl_eigenershader_02.png]] [[Datei:tut_glsl_eigenershader_03.png]]&lt;br /&gt;
&lt;br /&gt;
Wie im ersten (und dritten) Screenshot zu sehen ist es natürlich auch möglich mehrere Techniken innerhalb einer Szene zu nutzen. Hier sind letztendlich bis auf Hardwarelimitationen keine Grenzen gesetzt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Die Zukunft=&lt;br /&gt;
Als dieses Tutorial geschrieben wurde, war noch nicht ganz abzusehen dass bzw. ob sich GLSL auch durchsetzen würde. ARB-Shadr und NVidias cG waren damals die Platzhirsche, aber inzwischen werden ARB-Shader nicht mehr genutzt (und auch schon länger nicht mehr weiterentwickelt) und auch NVidia setzt primär auf GLSL. GLSL wird permanent weiterenwtickelt und Hersteller können dank des flexiblen Extensionsystems auch in GLSL eigene Extensions offenlegen um die aktuellsten Features (wie z.b. den Tesselator auf aktuellen ATI-Karten) nutzen zu können. GLSL it als inzwischen auch offizielle die Shadersprache frü OpenGL und wird permanent an die neusten technischen Entwicklungen im Grafikkartenbereich angepasst.&lt;br /&gt;
&lt;br /&gt;
Wer also unter OpenGL etwas mit Shadern machen möchte, kommt an GLSL nicht vorbei!&lt;br /&gt;
&lt;br /&gt;
Also viel Spaß beim Experimentieren und Shaderschreiben! Und nicht vergessen : Wir wollen sehen was ihr so treibt,&lt;br /&gt;
&lt;br /&gt;
Euer&lt;br /&gt;
:Sascha Willems&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{TUTORIAL_NAVIGATION|-|[[Tutorial_glsl2]]}}&lt;br /&gt;
[[Kategorie:Tutorial|GLSL]]&lt;/div&gt;</summary>
		<author><name>Phlegmatiker</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_glsl&amp;diff=25266</id>
		<title>Tutorial glsl</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_glsl&amp;diff=25266"/>
				<updated>2011-07-15T20:39:12Z</updated>
		
		<summary type="html">&lt;p&gt;Phlegmatiker: /* Fehlererkennung */ Code gescheit eingerückt, auch wenn die Namenskonvention zu wünschen übrig lässt.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Einleitung=&lt;br /&gt;
Hallo und willkommen bei meiner &amp;quot;Einführung&amp;quot; in GLSL (kurz für &amp;quot;Open'''GL''' '''S'''hading '''L'''anguage&amp;quot;), der offiziellen Hochlevel-Shadersprache von OpenGL. In diesem umfangreichen Dokument werde ich versuchen, sowohl auf die Nutzung (sprich das Laden und Anhängen von Shadern im Quellcode), als auch auf die Programmierung von Shadern selbst einzugehen, inklusive aller Sprachelemente der OpenGL Shadersprache. Es wird also auch recht viele Informationen zu der C-ähnlichen Programmstruktur und den von GLSL angebotenen Variablen und Attributen gehen. Am Ende dieser Einführung sollten alle die, die sich für das Thema interessieren, in der Lage sein, zumindest einfach Shader zu schreiben und auch in ihren Programmen zu nutzen. Ausserdem soll dieses Dokument gleichzeitig als ein deutsches &amp;quot;Pendant&amp;quot; zu den von Khronoes veröffentlichten Shaderspezifikationen, und damit als alltägliches Nachschlagewerk, dienen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Vorkenntnisse==&lt;br /&gt;
Wie auch schon mein ARB_VP-Tutorial richtet sich auch diese Einführung aufgrund ihrer Thematik eher an die fortgeschritteneren GL-Programmierer und neben sehr guten GL-Kenntnissen sollten sich alle, die sich daran versuchen wollen, mit den technischen Hintergründen der GL, wie z.B. dem Aufbau der Renderpipeline auskennen. Weiterhin sind C-Kenntnisse absolut erforderlich, da die Shader ja in einer an ANSI-C angelehnten Syntax geschrieben werden. Auch Begriffsdefinitionen zu Vertex oder Fragment werden zum Verständis dieser Einführung benötigt. Wer also noch am Anfang seiner GL-Karriere steht, dem wird dieses Dokument nicht viel nützen. Ganz nebenbei solltet ihr auch noch eine gehörige Portion Zeit (am besten nen kompletten Nachmittag) mitbringen, denn die folgende Kost ist nicht nur umfangreich, sondern auch manchmal recht schwer verdaulich.&lt;br /&gt;
&lt;br /&gt;
=Was ist GLSL?=&lt;br /&gt;
Wie Eingangs kurz angesprochen handelt es sich bei GLSL um eine Shadersprache, also um eine Hochsprache, in der man die programmierbaren Teile aktueller Grafikbeschleuniger nach eigenem Belieben programmieren kann. Sie stellt quasi den Nachfolger zu den in Assembler geschriebenen Vertex- und Fragmentprogrammen ([[GL_ARB_Vertex_Program]]/[[GL_ARB_Fragment_Program]]) dar und basiert auf ANSI C, erweitert um Vektor- und Matrixtypen sowie einige C++-Mechanismen.&lt;br /&gt;
&lt;br /&gt;
Die in GLSL geschriebenen Programme nennen sich, angepasst an die Terminologie von RenderMan und DirectX, [[Shader]] (im Gegensatz zu &amp;quot;Programme&amp;quot; bei ARB_VP/FP) und werden entweder auf Eckpunkte (VertexShader), Fragmente (FragmentShader) angewendet, oder (neuerdings, ab Shadermodell 4.0) auch genutzt um Geometrie zu erstellen (Geometryshader). Andere Teile der Renderpipeline (z.B. die Rasterisierung) können momentan noch nicht durch Shader beeinflusst werden, was allerdings in Zukunft noch kommen kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Voraussetzungen==&lt;br /&gt;
&lt;br /&gt;
GLSL wurde 2005 mit OpenGL 1.5 eingeführt. Während es in Sachen Treiber- und Hardwareunterstützung anfänglich noch dürftig aussah, wird man inzwischen keine Grafikkarte mehr kaufen können die nicht zumindest Vertex- und Fragmentshader beherscht. Geometrieshader hingegen sind relativ neu und wurden erst mit Shadermodell 4.0 eingeführt, hier ist es also unter Umständen noch möglich dass selbst aktuelle Treiber/Karten keine Geometrieshader beherrschen.&lt;br /&gt;
&lt;br /&gt;
Natürlich benötigt man auch einen passenden OpenGL-Header der die für GLSL nötigen Funktionen exportiert. Ich verweise dazu auf unseren eigenen OpenGL-Header [[DGLOpenGL.pas]], der peermanent auf dem aktuellsten Stand gehalten wird und auch Support für Geometrieshader mitbringt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Extensions==&lt;br /&gt;
&lt;br /&gt;
Die GL-Shadersprache &amp;quot;besteht&amp;quot; in ihrer aktuellen Version aus folgenden Extensions, fürs Verständnis wäre es nicht schlecht, wenn ihr euch zumindest die Einleitungen dazu durchlest :&lt;br /&gt;
* [[GL_ARB_Shader_Objects]] ([http://oss.sgi.com/projects/ogl-sample/registry/ARB/shader_objects.txt Orginal Spezifikation])&lt;br /&gt;
: Definiert die API-Aufrufe die zum Erstellen, Kompilieren, Linken, Anhängen und Aktivieren von Shader- und Programmobjekten nötig sind. &lt;br /&gt;
* [[GL_ARB_Vertex_Shader]] ([http://oss.sgi.com/projects/ogl-sample/registry/ARB/vertex_shader.txt Orginal Spezifikation])&lt;br /&gt;
: Fügt der OpenGL Programmierbarkeit auf Vertexebene hinzu. &lt;br /&gt;
* [[GL_ARB_Fragment_Shader]] ([http://oss.sgi.com/projects/ogl-sample/registry/ARB/fragment_shader.txt Orginal Spezifikation])&lt;br /&gt;
: Fügt der OpenGL Programmierbarkeit auf Fragmentebene hinzu. &lt;br /&gt;
* [[GL_ARB_Shading_Language_100]] ([http://oss.sgi.com/projects/ogl-sample/registry/ARB/shading_language_100.txt Orginal Spezifikation])&lt;br /&gt;
: Gibt die unterstützte Version von glSlang an, momentan 1.00.&lt;br /&gt;
&lt;br /&gt;
'''Hinweis''' : Seit OpenGL 2.0 ist GLSL Teil des Kerns. Wenn die Karte als OpenGL 2.0 unterstützt, dann unterstützt sie auch (zumindest in Software) Vertex- und Fragmentshader.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Sprachversionen==&lt;br /&gt;
&lt;br /&gt;
Neben der OpenGL-Version und dem vorhandenen Shadermodell (das eher an DirectX ausgerichtet ist), bietet auch GLSL verschiedene Versionen, die entsprechend erweiterte Funktionalität bieten.&lt;br /&gt;
&lt;br /&gt;
Auslesen kann man die verfürgbare GLSL-Version wie folgt :&lt;br /&gt;
&lt;br /&gt;
 glGetString(GL_SHADING_LANGUAGE_VERSION)&lt;br /&gt;
&lt;br /&gt;
Erst ab Version 1.4. kann man davon ausgehen dass GLSL alle Features des Shadermodells 4.0 liefert, ab 1.3 grob gesagt Shadermodell 3.0 (bei GLSL lässt sich das leider nicht so leicht unterteilen).&lt;br /&gt;
&lt;br /&gt;
Ausserdem kann man seinem Shader eine Versionsnummer verpassen. Sollte der Shadercompiler (also Treiber bzw. Hardware) diese Version nicht unterstützen, gibt dieser eine Fehlermeldung heraus :&lt;br /&gt;
&lt;br /&gt;
 #version 1.50 &lt;br /&gt;
&lt;br /&gt;
''(Hinweis : Muss am Anfang des Shaders stehen)''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Objekte==&lt;br /&gt;
&lt;br /&gt;
Im Zuge der Vereinheitlichung der GL wird immer häufiger in Objekte gekapselt, deren API dann auch aneinander angelehnt ist. Ziel ist, dabei die Programmierung der GL uniform zu machen, so dass z.B. zwischen dem Erstellen und Verwalten eines Vertex-Buffer-Objektes oder eines Shader-Objektes kaum ein Unterschied besteht (demnächst kommen dann auch Pixel-Buffer-Objekte dazu). Mit glSlang wurden dann im Zuge dieser Aktion zwei neue Objekte eingeführt, deren Definition ihr euch unbedingt einprägen solltet :&lt;br /&gt;
&lt;br /&gt;
* '''Programmobjekt'''&lt;br /&gt;
:Ein Objekt, an das die Shader später angebunden werden. Bietet Funktionalität zum Linken der Shader und prüft dabei die Kompatibilität zwischen Vertex- und Fragmentshader.&lt;br /&gt;
&lt;br /&gt;
* '''Shaderobjekt'''&lt;br /&gt;
:Dieses Objekt verwaltet den Quellcodestring eines Shaders und ist entweder vom Typ '''GL_VERTEX_SHADER''', '''GL_FRAGMENT_SHADER_ARB''' oder '''GL_GEOMETRY_SHADER'''.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Ressourcen==&lt;br /&gt;
&lt;br /&gt;
Die Shadersprache ist keinesfalls final und es wurden bereits diverse Ausdrücke für zukünftige Verwendung reserviert, denn ein Ziel bei ihrer Entwicklung war es, sie so zukunftsorientiert zu gestalten, dass auch Grafikkarten der nächsten und übernächsten Generation voll ausgenutzt werden können. Damit einher geht die Tatsache, dass sich die Spezifikationen in Zukunft ändern/erweitern werden, weshalb man da immer einen Blick hineinwerfen sollte. Die Anlaufstelle dafür ist die [http://www.opengl.org/documentation/specs/ Spezifikationenliste auf OpenGL.org].&lt;br /&gt;
&lt;br /&gt;
=GLSL im Programm=&lt;br /&gt;
Bevor wir uns mit der Syntax von glSlang beschäftigen, zeige ich euch erstmal, wie ihr Shader in euer Programm einbindet und nutzt. Warum das zuerst? Ganz einfach deshalb, weil ihr dann das, was ihr im glSlang-Syntaxteil lernt, direkt in eurer Testanwendung verwenden könnt. Hoffe diese Entscheidung klingt logisch und findet Anklang.&lt;br /&gt;
&lt;br /&gt;
Zuerst benötigen wir natürlich unsere Objekte. Zum einen ein ''Programmobjekt'', an das unsere Shader gebunden werden, und zwei ''Shaderobjekte'', die den Quellcode unseres Vertex bzw. Fragment Shaders aufnehmen. Dazu wurde eigens der neue &amp;quot;Datentyp&amp;quot; {{INLINE_CODE|glHandle}} eingeführt, der ein Objekthandle repräsentiert. Wir deklarieren also wie folgt :&lt;br /&gt;
&lt;br /&gt;
 ProgramObject        : GLhandle;&lt;br /&gt;
 VertexShaderObject   : GLhandle;&lt;br /&gt;
 FragmentShaderObject : GLhandle;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nach dieser Deklaration können wir dann damit beginnen unsere Objekte zu erstellen. Den Anfang macht das Programmobjekt :&lt;br /&gt;
&lt;br /&gt;
 ProgramObject        := glCreateProgram;&lt;br /&gt;
&lt;br /&gt;
Die Funktion [[glCreateProgram]] erstellt uns oben ein leeres Programmobjekt und gibt ein gültiges Handle darauf zurück.&lt;br /&gt;
&lt;br /&gt;
Weiter gehts mit der Erstellung unseres Vertex bzw. Fragment Shaders :&lt;br /&gt;
&lt;br /&gt;
 VertexShaderObject   := glCreateShader(GL_VERTEX_SHADER);&lt;br /&gt;
 FragmentShaderObject := glCreateShader(GL_FRAGMENT_SHADER);&lt;br /&gt;
&lt;br /&gt;
[[glCreateShader]] dient zur Generierung eines leeren Shaderobjektes. Momentan unterstützt diese Funktion VertexShader und FragmentShader.&lt;br /&gt;
&lt;br /&gt;
Nachdem wir nun also zwei gültige Shaderobjekte haben, wollen wir diese auch mit entsprechendem Quellcode versorgen :&lt;br /&gt;
&lt;br /&gt;
 glShaderSource(VertexShaderObject, 1, @ShaderText, @ShaderLength);&lt;br /&gt;
 glShaderSource(FragmentShaderObject, 1, @ShaderText, @ShaderLength);&lt;br /&gt;
&lt;br /&gt;
Via [[glShaderSource]] setzen wir den Quellcode eines Shaderobjektes ''komplett'' neu. Zum Laden des Quellcodes bietet sich unter Delphi übrigens eine TStringList geradezu an. Es sollte beachtet werden, dass der Quellcode zu diesem Zeitpunkt ''nicht geparst'' wird, also keine Fehleruntersuchung stattfindet.&lt;br /&gt;
&lt;br /&gt;
Der Quellcode wurde jetzt also an unsere Shaderobjekte gebunden und sollte dann natürlich auch noch kompiliert werden :&lt;br /&gt;
&lt;br /&gt;
 glCompileShader(VertexShaderObject);&lt;br /&gt;
 glCompileShader(FragmentShaderObject);&lt;br /&gt;
&lt;br /&gt;
Der glSlang-Compiler des Treibers wird bei einem Aufruf von [[glCompileShader]] versuchen, unsere Shader zu kompilieren. Sofern diese keine Fehler aufweisen, sollte dies auch erfolgreich sein. Wenn nicht, dann spuckt uns der Shadercompiler (je nach Treiber) recht detaillierte Infos aus. Wie man an diese Infos kommt könnt ihr gleich nachlesen.&lt;br /&gt;
&lt;br /&gt;
Wenn unsere Shader dann kompiliert werden konnten, ist es Zeit, diese an unser anfangs erstelltes Programmobjekt anzuhängen :&lt;br /&gt;
&lt;br /&gt;
 glAttachShader(ProgramObject, VertexShaderObject);&lt;br /&gt;
 glAttachShader(ProgramObject, FragmentShaderObject);&lt;br /&gt;
&lt;br /&gt;
Nachdem die Shaderobjekte nun an das Programmobjekt angehängt wurden, werden diese nicht mehr benötigt und ihre Resourcen können freigegeben werden :&lt;br /&gt;
&lt;br /&gt;
 glDeleteShader(VertexShaderObject);&lt;br /&gt;
 glDeleteShader(FragmentShaderObject);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Am Schluß müssen wir dann noch unsere ans Programmobjekt gebundenen Shader linken :&lt;br /&gt;
&lt;br /&gt;
 glLinkProgram(ProgramObject);&lt;br /&gt;
&lt;br /&gt;
Während [[glCompileShader]] unsere Shader auf syntaktische Fehler innerhalb ihres lokalen Raums geprüft hat, werden beim Linken durch [[glLinkProgram]] die angehangenen Shader zu einem ausführbaren Shader gelinkt. Folgende Bedingungen führen zu einem '''Linkerfehler''':&lt;br /&gt;
&lt;br /&gt;
* Die Zahl der von der Implementation unterstützten Attributvariablen wurde überschritten&lt;br /&gt;
* Der Speicherplatz für Uniformvariablen wurde überschritten&lt;br /&gt;
* Die Zahl der von der Implementation angebotenen Sampler wurde überschritten&lt;br /&gt;
* Die main-Funktion fehlt&lt;br /&gt;
* Die Liste der Varying-Variablen des Vertexshaders stimmt nicht mit der des Fragmentshaders überein&lt;br /&gt;
* Funktions- oder Variablenname nicht gefunden&lt;br /&gt;
* Eine gemeinsame Globale ist mit unterschiedlichen Werten oder Typen initialisiert worden&lt;br /&gt;
* Zwei Sampler unterschiedlichen Typs zeigen auf die selbe Textureneinheit&lt;br /&gt;
* Ein oder mehrere angehangene(r) Shader wurden nicht erfolgreich kompiliert&lt;br /&gt;
&lt;br /&gt;
Die Nutzung von glSlang im eigenen Programm ist wie oben erkennbar also nicht wirklich schwer und innerhalb kurzer Zeit realisiert. Natürlich ist es auch möglich z.B. nur einen VertexShader oder nur einen FragmentShader an ein Programmobjekt zu binden.&lt;br /&gt;
&lt;br /&gt;
Noch eine kleine Notiz zum Löschen der Shader mittel [[glDeleteShader]] : Da Shader(objekte) einen Referenzzähler besitzen und erst gelöscht werden wenn diese nirgendwo mehr benötigt werden, ist es nicht falsch diese vor dem Linkvorgang zu löschen. Allerdings spielt es letztendlich keine Rolle ob die Löschanweisung vorher der nachher ausgeführt wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Fehlererkennung==&lt;br /&gt;
Natürlich wird es ohne Fehlerausgabe recht schwer, etwaige Probleme in einem Vertex- oder Fragmentshader zu finden. Doch auch in diesem Bereich wurde glSlang recht gut durchdacht und es wurden zwei Funktionen eingeführt, welche im Zusammenspiel die Fehlersuche recht einfach machen, nämlich [[glGetShaderInfoLog]] und [[glGetShader]] mit dem Argument {{INLINE_CODE|GL_OBJECT_INFO_LOG_LENGTH}}. Erstere Funktion liefert uns einen Logstring, während uns letztere Funktion dessen Länge angibt. Der Logstring wird verändert, sobald ein Shader kompiliert oder ein Programm gelinkt wird.&lt;br /&gt;
&lt;br /&gt;
Um die Ausgabe dieses Logs so einfach wie möglich zu machen, bietet es sich an beide in einer einfach Funktion unterzubringen :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;function glSlang_GetInfoLog(pShader: GLHandleARB): String;&lt;br /&gt;
var&lt;br /&gt;
  blen, slen: GLInt;&lt;br /&gt;
  InfoLog: PGLCharARB;&lt;br /&gt;
&lt;br /&gt;
begin&lt;br /&gt;
  glGetShaderiv(glObject, GL_INFO_LOG_LENGTH , @blen);&lt;br /&gt;
  if blen &amp;gt; 1 then&lt;br /&gt;
  begin&lt;br /&gt;
    GetMem(InfoLog, blen * SizeOf(GLCharARB));&lt;br /&gt;
    glGetShaderInfoLog(pShader, blen, slen, InfoLog);&lt;br /&gt;
    Result := PChar(InfoLog);&lt;br /&gt;
    Dispose(InfoLog);&lt;br /&gt;
  end;&lt;br /&gt;
end;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Funktion ist recht leicht erklärt : Zuerst lassen wir uns über {{INLINE_CODE|glGetShaderiv}} mitteilen wie lang der aktuelle Infolog ist. Sollte dort tatsächlich etwas drinstehen (blen &amp;gt; 1), dann lassen wir uns dessen Inhalt via {{INLINE_CODE|glGetShaderInfoLog}} in {{INLINE_CODE|InfoLog}} ausgeben und liefern diesen als Ergebnis zurück.&lt;br /&gt;
&lt;br /&gt;
Wie bereits gesagt wird nur nach dem Kompilieren eines Shaders bzw. dem Linken eines Programmobjektes ein Infolog erstellt. Es bietet sich dadurch an, direkt danach einen solchen Aufruf zu machen :&lt;br /&gt;
&lt;br /&gt;
 glCompileShader(VertexShaderObject);&lt;br /&gt;
 ShowMessage(glSlang_GetInfoLog(VertexShaderObject));&lt;br /&gt;
&lt;br /&gt;
Wenn unser Vertex Shader komplett fehlerfrei kompiliert werden konnte, dann sehen wir als Ergebnis nur einen leeren Dialog. Ist dies nicht der Fall, so werden wir vom Treiber mit recht detaillierten Fehlerinformationen &amp;quot;belohnt&amp;quot;, z.B. so :&lt;br /&gt;
&lt;br /&gt;
[[Bild:GLSL_error_vshader.jpg]]&lt;br /&gt;
&lt;br /&gt;
Auch das Infolog nach dem Linken des Programmobjektes dürfte, selbst wenn keine Fehler vorkommen, recht interessant sein, das sieht dann nämlich so aus :&lt;br /&gt;
&lt;br /&gt;
[[Bild:GLSL info programobject.jpg]]&lt;br /&gt;
&lt;br /&gt;
Wie zu sehen, wird uns nach dem erfolgreichen Linken auch gesagt, ob und welcher Shader in Hardware bzw. Software läuft. Für Debuggingzwecke sicherlich eine mehr als brauchbare Information.&lt;br /&gt;
&lt;br /&gt;
==Shader benutzen==&lt;br /&gt;
Um den Shader auch für die nächsten Polygone zu benutzen oder Uniformparameter übergeben zu können, ruft man die Funktion&lt;br /&gt;
 glUseProgramt(ProgramObject);&lt;br /&gt;
um alle Shader zu deaktivieren, ruft man dieselbe Funktion mit dem Parameter 0.&lt;br /&gt;
&lt;br /&gt;
==Parameterübergabe==&lt;br /&gt;
Uniformparameter (mehr dazu später) stellen die Schnittstelle zwischen eurem Programm und dem Shader dar, werden also genutzt um Daten aus dem Programm heraus an einen Shader zu übergeben. Zur Übergabe dieser Parameter bietet OpenGL diverse Funktionen, die alle Abkömmlinge von [[glUniform]] sind. Während mit {{INLINE_CODE|glUniform4f}} z.B. ein Vier-Komponentenvektor an das Programmobjekt übergeben wird, kann man mittels {{INLINE_CODE|glUniformMatrix4fv}} ganze Matrizen schnell und einfach übergeben. Ausserdem gibt es nun die Möglichkeit Uniformparameter direkt über ihren Namen, statt wie unter ARB_FP/VP über einen festen Index zu adressieren. Die Funktion [[glGetUniformLocationARB]] gibt anhand des übergebenen Parameternamens dessen Position zurück. Man kann also ganz einfach über den Namen drauf zugreifen :&lt;br /&gt;
&lt;br /&gt;
 glUniform3f(glGetUniformLocation(ProgramObject, PGLCharARB('LightPosition')), LPos[0], LPos[1], LPos[2]);&lt;br /&gt;
 glUniform1i(glGetUniformLocation(ProgramObject, PGLCharARB('texSamplerTMU3')), 3);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wichtig ist hier, das man je nach Parametertyp auch die passende Anzahl von Argumenten übergibt. Also für einen 4-Komponenten Floatvektor {{INLINE_CODE|glUniform4fARB}} und für einen einfachen Integerwert (z.B. Textureinheit für einen Sampler) glUnifrom1iARB. Auch nicht vergessen dürft ihr, das die Namen der Parameter genauso wie im Shader geschrieben werden müssen, also Groß- und Kleinschreibung beachtet werden muß.&lt;br /&gt;
&lt;br /&gt;
=Die Shadersprache=&lt;br /&gt;
&lt;br /&gt;
Nachdem wir uns mit der Einbindung der glSlang-Shader in unser Programm beschäftigt haben, wollen wir uns in den folgenden Kapiteln um die Sprachelemente von glSlang kümmern. Wie schon gesagt basiert glSlang auf ANSI-C, wurde allerdings um speziell auf den Zielbereich angepasste Vektor- und Matrixtypen und einige C++-Features wie das freie deklarieren von Variablen an jeder Stelle und das Funktionsüberladen auf Basis des Argumenttyps erweitert. Wer sich ein wenig mit C/C++ auskennt sollte also in der nun folgenden Materie keine Probleme bekommen.&lt;br /&gt;
&lt;br /&gt;
'''Obligatorische Hinweise für verwöhnte Delphi-Nutzer : '''&lt;br /&gt;
*Wie von C/C++ her gewohnt, spielt auch in glSlang die Groß- und Kleinschreibung eine wichtige Rolle, also bitte achtet darauf. gl_Position ist eine komplett andere Variable als z.B. gl_position.&lt;br /&gt;
*Es findet keine automatische Typenkonvertierung statt. Das bedeutet also das float MyFloat = 1 ungültig ist und es in dem Falle float MyFloat = 1.0 heissen muss. Typecasts müssen also immer manuell stattfinden, z.B. MyFloat = float(MyInt).&lt;br /&gt;
&lt;br /&gt;
'''Kleine Programmstrukturkunde für C-Unkundige :'''&amp;lt;br&amp;gt;&lt;br /&gt;
Da sicherlich einige Delpher nie richtig was mit C gemacht haben, zeige ich mal anhand eines kleinen Beispieles (das auf keinen Fall nen brauchbaren Shader darstellt) den grundlegenden Aufbau eines glSlang-Shaders, der natürlich dem Aufbau eines C-Programmes stark ähnelt :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
uniform vec4 VariableA;&lt;br /&gt;
float VariableB;&lt;br /&gt;
vec3  VariableC;&lt;br /&gt;
const float KonstanteA = 256.0;&lt;br /&gt;
&lt;br /&gt;
float MyFunction(vec4 ArgumentA)&lt;br /&gt;
 {&lt;br /&gt;
 float FunktionsVariableA = float(5.0);&lt;br /&gt;
&lt;br /&gt;
 return float(ArgumentA * (FunktionsVariableA + KonstanteA));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
// Ich bin ein Kommentar&lt;br /&gt;
/* Und ich auch */&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
 gl_Position     = gl_ModelViewProjectionMatrix * gl_Vertex;&lt;br /&gt;
 gl_TexCoord[0]  = gl_MultiTexCoord0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sieht doch recht bekannt aus, unser Programmaufbau. Delphi und C haben ja so einige Grundlagen gleich, darunter auch der ungefähre Programmaufbau. Ausserhalb jeglicher Funktionen legen wir am Programmanfang unsere Variablen, Konstanten und Attribute fest, die dann ''global'' nutzbar sind, also in jeder Funktion.&lt;br /&gt;
&lt;br /&gt;
Darunter deklarieren wir dann eine kleine Funktion. Wie auch bei den Variablendeklarationen wird hier der Rückgabetyp nicht wie bei Pascal nach dem Funktionsnamen untergebracht, sondern davor. Innerhalb der Funktion können dann wieder Variablen deklariert werden, die dann allerdings ''lokal'', also nur in dieser Funktion nutzbar sind. Vorteil dieser Deklaration ist die Tatsache, dass je nach Grafikkarte nur bestimmt viele globale Variablen deklariert werden können. Wenn möglich sollte man also mit lokalen Vorlieb nehmen. Unsere Funktion gibt dann natürlich noch via return einen Wert zurück, ''was gemacht werden muss'', sofern man diese nicht als void deklariert hat (entspräche dann einer Prozedur in Pascal). Wird dies nicht getan, so spuckt der Compiler einen Fehler aus.&lt;br /&gt;
&lt;br /&gt;
Auch wichtig sind natürlich Kommentare. Erste Variante (Doppelslash) ist auch in der Pascalwelt verfügbar und kommentiert eine einzelne Zeile aus. Die Variante darunter kann man für Kommentarblöcke nutzen (/* .. */) und entspricht den Kommentaren in geschweiften Klammern in Delphi.&lt;br /&gt;
&lt;br /&gt;
Danach kommt dann die '''wichtigste Funktion''' des Shaders, nämlich '''main''', die in keinem Shader fehlen darf. Sie stellt quasi den Programmkörper dar und ist oft auch die einzige Funktion in einem Shader. Sie erhält weder ein Argument, noch gibt sie einen Wert zurück.&lt;br /&gt;
&lt;br /&gt;
Soviel also zum grundlegenden Aufbau eines Shader. Hoffe das jetzt alle die in C nicht so bewandert sind damit klar kommen, und dann bald ihre ersten glSlang-Shader schreiben können.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Datentypen==&lt;br /&gt;
&lt;br /&gt;
Obwohl einige Datentypen aus C übernommen wurden, sieht man der Typenliste an, das diese speziell auf den 3D-Bereich zugeschnitten wurde. Variablen müssen vor ihrer Nutzung eindeutig deklariert sein, Typecasting erfolgt über Konstruktoren (dazu später mehr). Folgende Datentypen stehen sowohl im Vertex- als auch Fragmentshader zur Verfügung :&lt;br /&gt;
&lt;br /&gt;
{|{{Prettytable_B1}}&lt;br /&gt;
!Datentyp  	&lt;br /&gt;
!Erklärung&lt;br /&gt;
|-&lt;br /&gt;
|void 	&lt;br /&gt;
|Für Funktionen die keinen Wert zurückgeben&lt;br /&gt;
|-&lt;br /&gt;
|bool 	&lt;br /&gt;
|Konditionaler Typ, entweder true (wahr) oder false (falsch)&lt;br /&gt;
|-&lt;br /&gt;
|int 	&lt;br /&gt;
|Vorzeichenbehafteter Integerwert&lt;br /&gt;
|-&lt;br /&gt;
|float 	&lt;br /&gt;
|Fließkommaskalar mit Singlegenauigkeit (32 Bit)&lt;br /&gt;
|-&lt;br /&gt;
|vec2 	&lt;br /&gt;
|2-Komponenten Fließkommavektor&lt;br /&gt;
|-&lt;br /&gt;
|vec3 	&lt;br /&gt;
|3-Komponenten Fließkommavektor&lt;br /&gt;
|-&lt;br /&gt;
|vec4 	&lt;br /&gt;
|4-Komponenten Fließkommavektor&lt;br /&gt;
|-&lt;br /&gt;
|bvec2 	&lt;br /&gt;
|2-Komponenten Booleanvektor&lt;br /&gt;
|-&lt;br /&gt;
|bvec3 	&lt;br /&gt;
|3-Komponenten Booleanvektor&lt;br /&gt;
|-&lt;br /&gt;
|bvec4 	&lt;br /&gt;
|4-Komponenten Booleanvektor&lt;br /&gt;
|-&lt;br /&gt;
|ivec2 	&lt;br /&gt;
|2-Komponenten Integervektor&lt;br /&gt;
|-&lt;br /&gt;
|ivec3 	&lt;br /&gt;
|3-Komponenten Integervektor&lt;br /&gt;
|-&lt;br /&gt;
|ivec4 	&lt;br /&gt;
|4-Komponenten Integervektor&lt;br /&gt;
|-&lt;br /&gt;
|mat2 	&lt;br /&gt;
|2x2 Fließkommamatrix&lt;br /&gt;
|-&lt;br /&gt;
|mat3 	&lt;br /&gt;
|3x3 Fließkommamatrix&lt;br /&gt;
|-&lt;br /&gt;
|mat4 	&lt;br /&gt;
|4x4 Fließkommamatrix&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die sampler-Typen stellen eine besondere Klasse zum Zugriff auf Texturen dar, und werden im Kapitel 6.7 genauer erklärt, inklusive einiger Anwendungsbeispiele.&lt;br /&gt;
&lt;br /&gt;
{|{{Prettytable_B1}}&lt;br /&gt;
!Datentyp  	&lt;br /&gt;
!Erklärung&lt;br /&gt;
|-&lt;br /&gt;
|sampler1D 	&lt;br /&gt;
|Zugriff auf 1D-Textur&lt;br /&gt;
|-&lt;br /&gt;
|sampler2D 	&lt;br /&gt;
|Zugriff auf 2D-Textur&lt;br /&gt;
|-&lt;br /&gt;
|sampler3D 	&lt;br /&gt;
|Zugriff auf 3D-Textur&lt;br /&gt;
|-&lt;br /&gt;
|samplerCube 	&lt;br /&gt;
|Zugriff auf Cubemap&lt;br /&gt;
|-&lt;br /&gt;
|sampler2DRect 	&lt;br /&gt;
|Zugriff auf Texturen die nicht 2^n * 2^n entsprechen (&amp;quot;non power-of-two&amp;quot;, NPOT)&lt;br /&gt;
|-&lt;br /&gt;
|sampler1DShadow 	&lt;br /&gt;
|Zugriff auf 1D-Tiefentextur mit Vergleichsoperation&lt;br /&gt;
|-&lt;br /&gt;
|sampler2DShadow 	&lt;br /&gt;
|Zugriff auf 2D-Tiefentextur mit Vergleichsoperation&lt;br /&gt;
|-&lt;br /&gt;
|samplerCubeShadow&lt;br /&gt;
|Zugriff auf Tiefentextur in einer Cubemap (z.b. für omni-diretionale Lichtquellen)&lt;br /&gt;
|-&lt;br /&gt;
|sampler2DRectShadow&lt;br /&gt;
|Zugriff auf 2D-NPOT-Tiefentextur &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|sampler1DArray&lt;br /&gt;
|Zugriff auf ein array aus 1D-Texturen &lt;br /&gt;
|-&lt;br /&gt;
|sampler2DArray&lt;br /&gt;
|Zugriff auf ein array aus 2D-Texturen &lt;br /&gt;
|-&lt;br /&gt;
|sampler1DArrayShadow&lt;br /&gt;
|Zugriff auf ein array aus 1D-Tiefentexturen &lt;br /&gt;
|-&lt;br /&gt;
|sampler2DArrayShadow&lt;br /&gt;
|Zugriff auf ein array aus 2D-Tiefentexturen &lt;br /&gt;
|-&lt;br /&gt;
|samplerBuffer&lt;br /&gt;
|Zugriff auf eine Puffertextur (1D-Texutr zum Speichern von Pufferobjekten)&lt;br /&gt;
|-&lt;br /&gt;
|sampler2DMS&lt;br /&gt;
|Zugriff auf eine 2D-Textur mit mehreren Samplepunkten (z.b. für Multisampling)&lt;br /&gt;
|-&lt;br /&gt;
|sampler2DMSArray&lt;br /&gt;
|Zugriff auf einarray aus 2D-Textur mit mehreren Samplepunkten (z.b. für Multisampling)&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Arrays===&lt;br /&gt;
&lt;br /&gt;
Natürlich unterstützt glSlang auch Arrays, die wie in C deklariert werden und deren Index bei 0 beginnt. Folgendes Array im Shader :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
float temp[3];&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
beginnt also bei Index 0 und endet bei Index 2. Im Gegensatz zu C lassen sich Arrays in glSlang allerdings ''nicht bei der Initialisierung vorbelegen''. Wenn ein Array als Parameter einer Funktion deklariert wird, so darf dieses keine Dimensionierung erhalten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Strukturen===&lt;br /&gt;
&lt;br /&gt;
Neu ggü. ARB_FP/VP ist nun auch die Möglichkeit, Strukturen in einem Shader zu deklarieren. Vor allem die Übersicht komplexerer Shader kann dadurch stark verbessert werden. Strukturen werden wie gewohnt mit dem Schlüsselwort {{INLINE_CODE|struct}} eingeleitet und können dann zur Typisierung von Variablen genutzt werden. Folgendes Beispiel dürfte die Nutzung verdeutlichen :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct light&lt;br /&gt;
 {&lt;br /&gt;
 bool active;&lt;br /&gt;
 float intensity;&lt;br /&gt;
 vec3 position;&lt;br /&gt;
 vec3 color;&lt;br /&gt;
 };&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Im Shader können dann neue Variablen von diesem Typ ganz einfach deklariert werden :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
 light LightSource[3];&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Der Zugriff auf die Elemente der Struktur erfolgt dann wie gewohnt über den Punkt :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
LightSource[3].position = vec3(1.0, 1.0, 5.0);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Typenqualifzierer==&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zur Typendeklaration kann eine Variable noch einen Typenqualifizerer vorangestellt bekommen, der an den Anfang der Deklaration gehört.&lt;br /&gt;
&lt;br /&gt;
* '''const'''&lt;br /&gt;
: Festgelegte (nur lesen) Konstante bzw. nur lesbarer Funktionsparameter.&lt;br /&gt;
&lt;br /&gt;
* '''uniform'''&lt;br /&gt;
: Ein den ganzen Shader über gleichbleibender Wert, der eine Schnittstelle zwischen dem Shader und der OpenGL-Anwendung darstellt. Ein Uniformwert wird in der Hauptanwendung an den entsprechenden Shader übergeben und kann dort dann genutzt werden.&lt;br /&gt;
&lt;br /&gt;
* '''attribute'''&lt;br /&gt;
: Nur lesbare Werte die eine Verbindung zwischen dem Shader und der OpenGL-VertexAPI darstellen (z.B. VertexParameter eines VertexArrays). Natürlich nur in einem Vertex Shader nutzbar.&lt;br /&gt;
&lt;br /&gt;
* '''varying'''&lt;br /&gt;
: Stellt die Verbindung zwischen einem Vertex- und einem FragmentShader dar. Werden im VertexShader geschrieben und dann perspektivisch korrekt über die Primitive interpoliert, um dann im Fragment Shader gelesen werden zu können. Nutzbar sind hier nur die Typen float, vec2, vec3, vec4, mat2, mat3 und mat4, Strukturen und andere Datentypen können nicht varying sein. Die Namen einer varying-Variable müssen sowohl im VertexShader als auch im FragmentShader gleich sein.&lt;br /&gt;
&lt;br /&gt;
* '''in'''&lt;br /&gt;
: Für Variablen die an eine Funktion übergeben und dort ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
* '''out'''&lt;br /&gt;
: Für Variablen die von einer Funktion nach aussen zurückgegeben werden.&lt;br /&gt;
&lt;br /&gt;
* '''inout'''&lt;br /&gt;
: Für Variablen die sowohl an eine Funktion übergeben als auch von dieser zurückgegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um obige Auflistung nicht leer im Raum stehen zu lassen zeige ich ein paar Beispiele die hoffentlich zum Verständnis beitragen :&lt;br /&gt;
&lt;br /&gt;
===Beispiel A=== &lt;br /&gt;
Vertexnormale soll an einen FragmenShader (interpoliert) übergeben werden :&lt;br /&gt;
&lt;br /&gt;
:Im VertexShader :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
varying vec3 VertexNormal;&lt;br /&gt;
...&lt;br /&gt;
VertexNormal = normalize(MV_IT * gl_Normal);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
:Im FragmentShader :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
varying vec3 VertexNormal;&lt;br /&gt;
...&lt;br /&gt;
TempVector = VertexNormal*...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Beispiel B=== &lt;br /&gt;
Uniformparameter zur nachträglichen Farbänderung der Szene wird im Programm übergeben :&lt;br /&gt;
&lt;br /&gt;
:Im VertexShader :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
uniform vec4 GlobalColor;&lt;br /&gt;
...&lt;br /&gt;
gl_FrontColor = GlobalColor * gl_Color;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
:Im Programm :&lt;br /&gt;
&lt;br /&gt;
 glUniform4fARB(glSlang_GetUniLoc(ProgramObject, 'GlobalColor'), Col[0], Col[1], Col[2], Col[3]);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Beispiel C=== &lt;br /&gt;
Konstante zur festen Farbänderung :&lt;br /&gt;
&lt;br /&gt;
:Im VertexShader :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
const vec4 ColorBias = vec4(0.2, 0.3, 0.0, 0.0);&lt;br /&gt;
...&lt;br /&gt;
gl_FrontColor = ColorBias * gl_Color;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
==Konstruktoren==&lt;br /&gt;
&lt;br /&gt;
Um in einem Shader ''Vektoren'' oder ''Matrizen'' mit Werten zu belegen, gibt es sogenannte Konstruktoren (nicht zu verwechseln mit z.B. Klassenkonstruktoren unter Delphi), die im Endeffekt nichts anderes als Funktionen zur Vorbelegung von Vektoren oder Matrizen darstellen. Dabei trägt der Konstruktor den selben Namen wie die Typendeklaration, also lässt sich eine Variable vom Typ {{INLINE_CODE|vec4}} mit dem Konstruktor {{INLINE_CODE|vec4(float, float, float, float)}} initialisieren.&lt;br /&gt;
&lt;br /&gt;
Allerdings hat man sich recht viel Mühe bei dieser Konstruktorgeschichte gemacht, so dass man einen vec4 nicht unbedingt mit einem {{INLINE_CODE|vec4}}-Konstruktor vorbelegen muss, sondern es vielseitige Möglichkeiten gibt. Um dies zu verdeutlichen gibts ein paar Beispiele :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
vec4 Color = vec4(1.0, 0.0, 0.0, 0.0);&lt;br /&gt;
vec4 Color = vec4(MyVec3, 1.0);&lt;br /&gt;
vec4 Color = vec4(MyVec2_A, MyVec2_B);&lt;br /&gt;
&lt;br /&gt;
vec3 LVec  = vec3(MyVec4);&lt;br /&gt;
vec2 Tmp   = vec2(MyVec3);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Trotz der recht wenigen Beispiele sollte schnell erkennbar sein, das man hier wirklich sehr viele Kombinationsmöglichkeiten hat, die dann gültig sind ''wenn man mindestens auf die benötigte Anzahl der Argumente kommt''. Im vorletzten Beispiel wird z.B. ein 3-Komponentenvektor aus einem 4-Komponentenvektor initialisiert. Das erzeugt keinen Fehler, sondern führt dazu das {{INLINE_CODE|vec3.x, vec3.y, vec3.z}} aus MyVec4 übernommen werden und MyVec4.w einfach ignoriert wird.&lt;br /&gt;
&lt;br /&gt;
Das Umkehrbeispiel, also&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
vec4 Color = vec4(MyVec3)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
funktioniert allerdings nicht, da hier die Zahl der benötigten Argumente nicht erreicht wird. In diesem Falle müsste es dann&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt; &lt;br /&gt;
vec4 Color = vec4(MyVec3, 0.0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
heissen.&lt;br /&gt;
&lt;br /&gt;
Obiges gilt natürlich auch für ''Matrixkonstruktoren'', hier sind z.B. folgende Konstuktoren denkbar, obwohl eigentlich alle Möglichkeiten nutzbar sind, ''solange die benötigte Zahl an Argumenten erreicht wird'' :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
mat4 MyMatrix = mat4(MyVec4, MyVec4, MyVec4, MyVec4);&lt;br /&gt;
mat2 MyMatrix = mat4(1.0, 0.0, 0.0, 0.0,&lt;br /&gt;
                     0.0, 1.0, 0.0, 0.0,&lt;br /&gt;
                     0.0, 0.0, 1.0, 0.0,&lt;br /&gt;
                     0.0, 0.0, 0.0, 1.0);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vektor- und Matrixkomponenten==&lt;br /&gt;
&lt;br /&gt;
Was natürlich in keiner Shadersprache fehlen darf, ist der leichte Zugriff auf die einzelnen Komponenten eines Vektors. glSlang bietet, je nach Anwendungsgebiet gleich drei Namensets für den Zugriff auf die Komponenten eines solchen Vektors, welches Set man nutzen will bleibt natürlich frei und ist unabhängig von der Deklaration eines Vektors. Man sollte nur darauf achten, beim gleichzeitigen Zugriff auf mehrere Komponenten im gleichen Namenset zu verbleiben :&lt;br /&gt;
&lt;br /&gt;
* {x, y, z, w}&lt;br /&gt;
:Für den Zugriff auf Vektoren die Punkte, Normale oder sonstige Vertexdaten repräsentieren.&lt;br /&gt;
&lt;br /&gt;
* {r, g, b, a}&lt;br /&gt;
:Für den Zugriff auf Vektoren die Farbwerte repräsentieren.&lt;br /&gt;
&lt;br /&gt;
* {s, t, p, q}&lt;br /&gt;
:Für den Zugriff auf Vektoren die Texturkoordinaten repräsentieren.&lt;br /&gt;
&lt;br /&gt;
Ein paar Beispiele zur Unterstreichung des oben gesagten :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
v4.rgba = vec4(1.0, 0.0, 0.0, 0.0);  // gültig&lt;br /&gt;
v4.rgzw = vec4(1.0, 1.0, 1.0, 2.0);  // Ungültig, da verschiedenen Namensets&lt;br /&gt;
v2.rgb  = vec3(1.0, 2.0, 1.0);       // Ungültig, da vec2 nur r+g besitzt&lt;br /&gt;
v2.xx   = vec2(5.0, 3.0);            // Ungültig, da 2 mal gleiche Komponente&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auch der Zugriff auf die Komponenten einer Matrix geht leicht von der Hand. Namensets wie bei den Vektoren gibt es hier natürlich keine, aber folgende Beispiele sollen den Zugriff aufzeigen :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
MyMat4[2]    = vec4(1.0); // Setzt die 3.Zeile der Matrix komplett auf 1.0&lt;br /&gt;
MyMat4[3][3] = 3.5;       // Setzt das Element unren rechts auf 3.5&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ein Zugriff auf Matrixelemente ausserhalb ihrer Dimension (also z.B. MyMat4[4][4]) liefert unvorhersehabre Ergebnise, also sollte man auf diese Fälle prüfen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Vektor- und Matrixoperationen==&lt;br /&gt;
&lt;br /&gt;
Wie von C gewohnt sind in glSlang so ziemlich alle Operatoren die man auf Matrizen oder Vektoren anwenden kann überladen, so das man nicht umständlich über selbstgeschriebene Funktionen kombinieren muss. Darüber hinaus ist es in den meisten Fällen auch möglich ohne Konvertierung Fließkommawerte mit kompletten Matrizen oder Vektoren zu kombinieren. Folgende Beispiele zeigen einige der vielfältigen Kombinationsmöglichkeiten auf :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
vec3  dest;&lt;br /&gt;
vec3  source;&lt;br /&gt;
float factor;&lt;br /&gt;
&lt;br /&gt;
vec3 dest = source + factor; &lt;br /&gt;
&lt;br /&gt;
// Ist gleich&lt;br /&gt;
dest.x = source.x + factor;&lt;br /&gt;
dest.y = source.y + factor;&lt;br /&gt;
dest.z = source.z + factor;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Matrix * Vektor ist auch ohne manuelle Konvertierung möglich :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
vec3  dest;&lt;br /&gt;
vec3  source;&lt;br /&gt;
mat3  MyMat;&lt;br /&gt;
 &lt;br /&gt;
dest = source * MyMat; &lt;br /&gt;
 &lt;br /&gt;
// Ist gleich&lt;br /&gt;
dest.x = dot(source, MyMat[0]);&lt;br /&gt;
dest.y = dot(source, MyMat[1]);&lt;br /&gt;
dest.z = dot(source, MyMat[2]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auch hier sind die Möglichkeiten fast unbeschränkt und zeigen wieder wie flexibel glSlang ausgelegt ist. &lt;br /&gt;
&lt;br /&gt;
==Operatoren==&lt;br /&gt;
&lt;br /&gt;
glSlang bietet (momentan) folgende Operatoren, die Liste ist nach ihrer Gewichtung sortiert (Anfang = höchste). Alle ''reservierten'' Operatoren werden erst in kommender Hardware/glSlang-Versionen nutzbar sein :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div  align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|{{Prettytable_B1}}&lt;br /&gt;
!Operatorklasse  	&lt;br /&gt;
!Operatoren  	&lt;br /&gt;
!Assoziation&lt;br /&gt;
|-&lt;br /&gt;
|Gruppering 	&lt;br /&gt;
|() 	&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
|Arrayindizierung&amp;lt;br&amp;gt;Funktionsaufrufe und Konstruktoren&amp;lt;br&amp;gt;Strukturfeldwahl und Swizzle&amp;lt;br&amp;gt;Postinkrement und -dekrement&amp;lt;br&amp;gt; 	&lt;br /&gt;
|[]&amp;lt;br&amp;gt;()&amp;lt;br&amp;gt;.&amp;lt;br&amp;gt;++ -- 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Prefixinkrement- und dekrement&amp;lt;br&amp;gt;Einheitlich (~ reserviert) 	&lt;br /&gt;
| ++ --&amp;lt;br&amp;gt; + - ~ ! 	&lt;br /&gt;
|Rechts n. Links&lt;br /&gt;
|-&lt;br /&gt;
|Mulitplikation (% reserviert) 	&lt;br /&gt;
|* / % 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Additiv 	&lt;br /&gt;
| + - 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Bitweises Verschieben (reserviert) 	&lt;br /&gt;
|&amp;lt;&amp;lt;  &amp;gt;&amp;gt; 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Relation 	&lt;br /&gt;
|&amp;lt;  &amp;gt;  &amp;lt;=  &amp;gt;= 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Vergleich 	&lt;br /&gt;
|==  != 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Bitweises AND (reserviert) 	&lt;br /&gt;
|&amp;amp; 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Bitweises XOR (reserviert) 	&lt;br /&gt;
|^ 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Bitweises OR (reserviert) 	&lt;br /&gt;
| &amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt; 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Logisches AND 	&lt;br /&gt;
|&amp;amp;&amp;amp; 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Logisches XOR 	&lt;br /&gt;
|^^ 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Logisches OR 	&lt;br /&gt;
| &amp;lt;nowiki&amp;gt;||&amp;lt;/nowiki&amp;gt; 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Auswahl 	&lt;br /&gt;
|?: 	&lt;br /&gt;
|Rechts n. Links&lt;br /&gt;
|-&lt;br /&gt;
|Zuweisung&amp;lt;br&amp;gt;Arithmetrische Zuweisung&amp;lt;br&amp;gt;(Modulis, Shift und bitweise Op. reserviert) 	&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt;&amp;lt;br&amp;gt; &amp;lt;nowiki&amp;gt;+= -=  *=  /=  %=&amp;lt;/nowiki&amp;gt; &amp;lt;br&amp;gt; &amp;lt;nowiki&amp;gt;&amp;lt;&amp;lt;=  &amp;gt;&amp;gt;= &amp;amp;=  ^=  |=&amp;lt;/nowiki&amp;gt; 	&lt;br /&gt;
|Rechts n. Links&lt;br /&gt;
|-&lt;br /&gt;
|Aufzählung 	&lt;br /&gt;
|, 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Funktionen==&lt;br /&gt;
&lt;br /&gt;
Ein großer Vorteil von Hochsprachen ist u.A. die Möglichkeit oft genutzte Codeteile in Funktionen (bzw. auch Prozeduren unter Pascal) zu verpacken um so Flexibilität als auch Übersichtlichkeit zu steigern. Wer schonmal was in C geschrieben hat, der wird sich jetzt sicherlich kein Kopfzerbrechen machen müssen. Funktionen werden in glSlang genauso nach folgendem Prinzip deklariert :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
RückgabeTyp FunktionsName(Typ0 Argument0, Typ1, Argument1, ... , TypN, ArgumentN)&lt;br /&gt;
 {&lt;br /&gt;
 return RückgabeWert;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Funktionen die ''nichts zurückgeben'' müssen mit dem RückgabeTyp {{INLINE_CODE|void}} deklariert werden, ausserdem entfällt dann logischerweise das {{INLINE_CODE|return}}. Falls die Funktion eines ihrere Argumente nach aussen übergeben soll, muss dieses Argument mit dem Typenqualifizierer out (Siehe Kapitel 4.2) versehen werden. ''Arrays'' können nur als Eingabeargumente übergeben werden und dürfen nich dimensioniert als Argument verwendet werden, sondern müssen mit leeren Klammern argumentiert werden.&lt;br /&gt;
Ein paar Beispiele :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
void MeineFunktion(float EingabeWert; out float AusgabeWert)&lt;br /&gt;
 {&lt;br /&gt;
 AusgabeWert = EingabeWert*MyConstValue;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Funktion gibt ''nichts'' zurück, aber gibt EingabeWert*MyConstValue im Ausgabeargument AusgabeWert nach aussen.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
float MeineFunktion(float EingabeWert)&lt;br /&gt;
 {&lt;br /&gt;
 return EingabeWert*MyConstValue;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bietet genau die selbe Funktionalität wie das Beispiel darüber. Allerdings wird hier der berechnete Wert als Ergebnis der Funktion zurückgeliefert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
float VektorSumme(float v[])&lt;br /&gt;
 {&lt;br /&gt;
 return v[0]+v[1]+v[2]+v[3];&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wie bereits gesagt darf ein Array als Argument keine Dimensionierung enthalten. Wenn man der Funktion also ein Array übergibt, sollte man vorher drauf achten das es entsprechend der in der Funktion genutzten Indizes dimensioniert wurde.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==if-Anweisung==&lt;br /&gt;
&lt;br /&gt;
Selektion über eine if-Anweisung darf auch in keiner Hochsprache fehlen. Genauso wie in C oder Delphi erwartet auch hier die If-Anweisung einen boolschen Ausdruck (Wahr oder Falsch) und wird dann ausgeführt (wahr) bzw. verzweigt auf ein (wenn vorhanden) else (falsch). Verschachtelung ist wie erwartet auch möglich.&lt;br /&gt;
&lt;br /&gt;
'''Hinweis : ''' &lt;br /&gt;
Grafikkarten auf dem Stand des Shadermodells 2.0 (Radeon 9x00, Radeon X8x0, GeForceFX 5x00) unterstüzten im Fragmentshader kein Early-Out, was zur Folge hat das bei einer If-Anweisung immer alle Zweige ausgeführt werden. Am Ende wird dann aber nur ein Ergebnis geschrieben, die anderen verworfen. Auf solchen Karten bringen If-Anweisungen also im Normalfall keine Geschwindigkeitssteigerung, sondern oft eher das Gegenteil.&lt;br /&gt;
Neuere SM3.0-Karten (Radeon X1x00, GeForce6x00 und höher) ist dass nicht mehr der Fall, da hier dynamische Verzweigungen und auch Early-Out von der Hardware implementiert werden.&lt;br /&gt;
&lt;br /&gt;
==Schleifen==&lt;br /&gt;
&lt;br /&gt;
Auch Schleifen, ein wichtiges Konzept jeder Hochsprache haben ihren Weg in glSlang gefunden. Unterstützt werden folgende Schleifentypen :&lt;br /&gt;
&lt;br /&gt;
* '''for'''-Schleife&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
for (Startausdruck; Durchlaufbedingung; Wiederholungsausdruck)&lt;br /&gt;
  {&lt;br /&gt;
   statement&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''while'''-Schleife&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
while (Durchlaufbedingung)&lt;br /&gt;
 {&lt;br /&gt;
  statement&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''do'''-while-Schleife&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
do&lt;br /&gt;
 {&lt;br /&gt;
  statement&lt;br /&gt;
 }&lt;br /&gt;
 while (Durchlaufbedingung)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Hinweis :''' Grafikkarten auf dem Stand des Shadermodells 2.0 (Radeon 9x00, Radeon X8x0, GeForceFX 5x00) unterstüzten Schleifen nicht in Hardware. Schleifen werden dann beim Kompilieren vom Treiber entrollt, wodurch natürlich Shader mit weitaus mehr Instruktionen als erwartet generiert werden. Von daher sollte man auf solchen Karten möglichst auf Schleifen verzichten, oder diese nur recht kurz halten. Bei SM3.0-Karten (Radeon X1x00, GeForce6x00 und höher) ist dass nicht mehr der Fall.&lt;br /&gt;
&lt;br /&gt;
=Eingebaute Variablen, Attribute und Konstanten=&lt;br /&gt;
Nachdem wir uns nun lange genug mit den minderinterssanten Elementen der glSlang-Syntax beschäftigt haben, gehts jetzt endlich an die wirklich interessanten Dinge. Wie schon ARB_VP/ARB_FP bringt auch glSlang jede Menge eingabauter Variablen, Attribute und Konstanten mit, deren Aliase sie recht leicht identifizierbar machen (ganz im Gegensatz zum Indexgewusel bei den DX-Shadern).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Variablen im Vertex Shader==&lt;br /&gt;
Exklusiv im Vertex Shader stehen die folgenden Variablen zur Verfügung :&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_Position    muss geschrieben werden&lt;br /&gt;
:Dieser Variable '''muss''' im Vertexshader ein Wert zugewiesen werden, wird dies nicht getan ist das Ergebnis (sprich die Position des Vertex) undefiniert. Vorgesehen ist diese Variable für die ''homogene Position des Vertex'' und wird u.a. zum Clipping und Culling verwendet. Sie darf natürlich auch (mehrfach) geschrieben und ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
* float gl_PointSize    kann geschrieben werden&lt;br /&gt;
:Diese Variable wurde dazu vorgesehen um dort im VertexShader die Punktgröße in Pixeln hineinzuschreiben.&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_ClipVertex    kann geschrieben werden&lt;br /&gt;
:Falls genutzt, sollten hier die Vertexkoordinaten die im Zusammenhang mit benutzerdefinierten Clippingplanes genutzt werden abgelegt werden. Wichtig ist, das gl_ClipVertex im selben Koordinatenraum wie die Clippingplane definiert ist.&lt;br /&gt;
&lt;br /&gt;
==Attribute im Vertex Shader==&lt;br /&gt;
&lt;br /&gt;
Folgende Attribute stehen nur im Vertex Shader zur Verfügung und '''können nur gelesen werden''' :&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_Color&lt;br /&gt;
: Farbwert des Vertex.&lt;br /&gt;
* vec4 gl_SecondaryColor&lt;br /&gt;
:Sekundärer Farbwert des Vertex.&lt;br /&gt;
* vec4 gl_Normal&lt;br /&gt;
:Normale des Vertex.&lt;br /&gt;
* vec4 gl_Vertex&lt;br /&gt;
:Koordinaten des Vertex;&lt;br /&gt;
* vec4 gl_MultiTexCoord0..7&lt;br /&gt;
:Texturkoordinaten auf Textureinheit 0..7.&lt;br /&gt;
* float gl_FogCoord&lt;br /&gt;
:Nebelkoordinate des Vertex. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Variablen im Fragment Shader==&lt;br /&gt;
&lt;br /&gt;
Im Fragment Shader sind folgende Variablen exklusiv nutzbar :&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_FragColor&lt;br /&gt;
: Speichert den Farbwert des Fragmentes, der von folgenden Funktionen der festen Pipeline genutzt wird. Wird dieser Variable nichts zugewiesen, so ist ihr Inhalt undefiniert und darauf aufbauende Ergebnisse ebenfalls.&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_FragData[0..15]&lt;br /&gt;
: Ersetzt gl_FragColor bei der Verwendung von multiplen Rendertargets. &lt;br /&gt;
&lt;br /&gt;
* float gl_FragDepth&lt;br /&gt;
: Durch schreiben dieser Variable kann man den von der festen Funktionspipeline ermittelten Tiefenwert überspringen, der mit {{INLINE_CODE|gl_FragCoord.z}} ausgelesen werden kann. Wird dieser Wert nicht geschrieben, nutzen folgende Funktionen der Pipeline den vorher fest berechneten Wert.&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_FragCoord    nur lesen&lt;br /&gt;
: In dieser Variable ist die Position des Fragmentes relativ zur Fensterposition im Format x,y,z,1/w abgelegt, wobei z den von der festen Funktionspipeline berechneten Tiefenwert enthält.&lt;br /&gt;
&lt;br /&gt;
* bool gl_FrontFacing    nur lesen&lt;br /&gt;
: Gibt an ob das Fragment zu einer nach vorne zeigenden Primitive gehört (=true). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Bezug auf {{INLINE_CODE|gl_FragColor}} und {{INLINE_CODE|gl_FragDepth}} sei noch anzumerken das diese ''nicht'' in den Wertebereich 0..1 gebracht werden müssen, da dies später durch die feste Funktionspipeline automatisch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
==Eingebaute Varyings==&lt;br /&gt;
&lt;br /&gt;
Wie bereits in Kapitel 4.2 erwähnt, stellen Varyings eine Schnittstelle zwischen dem Vertex und dem Fragment Shader dar. Sie werden im Vertex Shader geschrieben und können dann im Fragment Shader ausgelesen werden, ohne das die folgenden Varyings dafür explizit deklariert werden müssen :&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_FrontColor&lt;br /&gt;
: Farbe der Vorderseite des Vertex.&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_BackColor&lt;br /&gt;
: Farbe der Rückseite des Vertex.&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_FrontSecondaryColor&lt;br /&gt;
: Sekundäre Farbe der Vorderseite des Vertex.&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_BackSecondaryColor&lt;br /&gt;
: Sekundäre Farbe der Rückseite des Vertex.&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_TexCoord[x]&lt;br /&gt;
: Texturkoordinaten des Vertex auf Textureinheit x, wobei x die von der Hardware zur Verfügung gestellte Zahl der Textureinheiten-1 nicht überschreiten darf.&lt;br /&gt;
&lt;br /&gt;
* float gl_FogFragCoord&lt;br /&gt;
: Nebelkoordinate des Fragmentes. &lt;br /&gt;
&lt;br /&gt;
Die Varyings {{INLINE_CODE|gl_FrontColor, gl_FrontSecondaryColor, gl_BackColor}} und {{INLINE_CODE|gl_BackSecondaryColor}} können im FragmentShader nur unter den Aliases gl_Color bzw. gl_SecondaryColor gelesen werden. Welcher Wert des Vertex Shaders im Fragment Shader dort eingesetzt wird ist abhängig davon ob das Fragment zu einer nach vorne oder nach hinten zeigenden Primitive gehört.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Eingebaute Konstanten==&lt;br /&gt;
Auch diverse Konstanten wurden definiert um darauf schnell im Shader zugreifen zu können. In den Klammern stehen die von einer GL-Implementation als Mindestanforderung anzubietenden Werte. Alle Konstanten sind sowohl im Vertex als auch im Fragment Shader abrufbar :&lt;br /&gt;
&lt;br /&gt;
: OpenGL 1.0/1.2 :&lt;br /&gt;
* int gl_MaxLights (8)&lt;br /&gt;
* int gl_MaxClipPlanes (6)&lt;br /&gt;
* int gl_MaxTextureUnits (2)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
: ARB_Fragment_Program :&lt;br /&gt;
* int gl_MaxTextureCoordsARB (2)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
: Vertex_Shader :&lt;br /&gt;
* int gl_MaxVertexAttributesGL2 (16)&lt;br /&gt;
* int gl_MaxVertexUniformFloatsGL2 (512)&lt;br /&gt;
* int gl_MaxVaryingFloatsGL2 (32)&lt;br /&gt;
* int gl_MaxVertexTextureUnitsGL2 (1)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
: Fragment_Shader :&lt;br /&gt;
* int gl_MaxFragmentTextureUnitsGL2 (2)&lt;br /&gt;
* int gl_MaxFragmentUniformFloatsGL2 (64)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Eingebaute Uniformvariablen==&lt;br /&gt;
&lt;br /&gt;
Um den Zugriff auf OpenGL-Staten zu vereinfachen wurden in glSlang diverse Uniformvariablen zur direkten Verwendung im Shader eingebaut. Wie gewohnt wurden auch hier sinnvolle Namen verwendet, so dass eine tiefere Erklärung unnötig sein dürfte :&lt;br /&gt;
&lt;br /&gt;
* mat4 gl_ModelViewMatrix&lt;br /&gt;
* mat4 gl_ProjectionMatrix&lt;br /&gt;
* mat4 gl_ModelViewProjectionMatrix&lt;br /&gt;
* mat3 gl_NormalMatrix&lt;br /&gt;
:{{INLINE_CODE|gl_NormalMatrix}} repräsentiert die invertierten und anschließend transponierten oberen 3x3 Werte der {{INLINE_CODE|gl_ModelViewMatrix}}.&lt;br /&gt;
* mat4 gl_TextureMatrix[gl_MaxTextureCoordsARB]&lt;br /&gt;
&lt;br /&gt;
* float gl_NormalScale&lt;br /&gt;
: Gibt den unter OpenGL festgelegten Faktor zur Skalierung der Normalen zurück.&lt;br /&gt;
&lt;br /&gt;
* struct gl_DepthRangeParameters&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct gl_DepthRangeParameters&lt;br /&gt;
{&lt;br /&gt;
 float near;&lt;br /&gt;
 float far;&lt;br /&gt;
 float diff;&lt;br /&gt;
};&lt;br /&gt;
gl_DepthRangeParameters gl_DepthRange;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
: Clippingplanes : &lt;br /&gt;
* vec4 gl_ClipPlane[gl_MaxClipPlanes]&lt;br /&gt;
  &lt;br /&gt;
*struct gl_PointParameters&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct gl_PointParameters&lt;br /&gt;
{&lt;br /&gt;
 float size;&lt;br /&gt;
 float sizeMin;&lt;br /&gt;
 float sizeMax;&lt;br /&gt;
 float fadeThresholdSize;&lt;br /&gt;
 float distanceConstantAttenuation;&lt;br /&gt;
 float distanceLinearAttenuation;&lt;br /&gt;
 float distanceQuadraticAttenuation;&lt;br /&gt;
};&lt;br /&gt;
gl_PointParameters gl_Point;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*struct gl_MaterialParameters&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct gl_MaterialParameters&lt;br /&gt;
{&lt;br /&gt;
 vec4 emission;&lt;br /&gt;
 vec4 ambient;&lt;br /&gt;
 vec4 diffuse;&lt;br /&gt;
 vec4 specular;&lt;br /&gt;
 float shininess;&lt;br /&gt;
};&lt;br /&gt;
gl_MaterialParameters gl_FrontMaterial;&lt;br /&gt;
gl_MaterialParameters gl_BackMaterial;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*struct gl_LightSourceParameters&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct gl_LightSourceParameters&lt;br /&gt;
{&lt;br /&gt;
 vec4 ambient;&lt;br /&gt;
 vec4 diffuse;&lt;br /&gt;
 vec4 specular;&lt;br /&gt;
 vec4 position;&lt;br /&gt;
 vec4 halfVector;&lt;br /&gt;
 vec3 spotDirection;&lt;br /&gt;
 float spotExponent;&lt;br /&gt;
 float spotCutoff;&lt;br /&gt;
 float spotCosCutoff;&lt;br /&gt;
 float constantAttenuation;&lt;br /&gt;
 float linearAttenuation;&lt;br /&gt;
 float quadraticAttenuation;&lt;br /&gt;
};&lt;br /&gt;
gl_LightSourceParameters gl_LightSource[gl_MaxLights];&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*struct gl_LightModelParameters&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct gl_LightModelParameters&lt;br /&gt;
{&lt;br /&gt;
 vec4 ambient;&lt;br /&gt;
};&lt;br /&gt;
gl_LightModelParameters gl_LightModel;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*struct gl_LightModelProducts&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct gl_LightModelProducts&lt;br /&gt;
{&lt;br /&gt;
 vec4 sceneColor;&lt;br /&gt;
};&lt;br /&gt;
gl_LightModelProducts gl_FrontLightModelProduct;&lt;br /&gt;
gl_LightModelProducts gl_BackLightModelProduct;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*struct gl_LightProducts&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct gl_LightProducts&lt;br /&gt;
{&lt;br /&gt;
 vec4 ambient;&lt;br /&gt;
 vec4 diffuse;&lt;br /&gt;
 vec4 specular;&lt;br /&gt;
};&lt;br /&gt;
gl_LightProducts gl_FrontLightProduct[gl_MaxLights];&lt;br /&gt;
gl_LightProducts gl_BackLightProduct[gl_MaxLights];&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* vec4 gl_TextureEnvColor[gl_MaxFragmentTextureUnitsGL2]&lt;br /&gt;
* vec4 gl_EyePlaneS[gl_MaxTextureCoordsARB]&lt;br /&gt;
* vec4 gl_EyePlaneT[gl_MaxTextureCoordsARB]&lt;br /&gt;
* vec4 gl_EyePlaneR[gl_MaxTextureCoordsARB]&lt;br /&gt;
* vec4 gl_EyePlaneQ[gl_MaxTextureCoordsARB]&lt;br /&gt;
* vec4 gl_ObjectPlaneS[gl_MaxTextureCoordsARB]&lt;br /&gt;
* vec4 gl_ObjectPlaneT[gl_MaxTextureCoordsARB]&lt;br /&gt;
* vec4 gl_ObjectPlaneR[gl_MaxTextureCoordsARB]&lt;br /&gt;
* vec4 gl_ObjectPlaneQ[gl_MaxTextureCoordsARB]&lt;br /&gt;
&lt;br /&gt;
*struct gl_FogParameters&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct gl_FogParameters&lt;br /&gt;
{&lt;br /&gt;
 vec4 color;&lt;br /&gt;
 float density;&lt;br /&gt;
 float start;&lt;br /&gt;
 float end;&lt;br /&gt;
 float scale;&lt;br /&gt;
};&lt;br /&gt;
gl_FogParameters gl_Fog;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Diese recht umfangreiche GL-Stateliste sollte eigentlich jeden Bedarf decken und momentan gibts kaum einen OpenGL-Status den man so nicht in einem Shader abfragen bzw. nutzen kann.&lt;br /&gt;
&lt;br /&gt;
=Eingebaute Funktionen=&lt;br /&gt;
glSlang ist mit diversen Skalar- und Vektorfunktionen ausgestattet, die teilweise (idealerweise) sogar direkt in der Hardware ausgeführt werden, weshalb einer fertigen Funktion ggü. gleichwertigen eigenen Berechnungen immer der Vorzug zu geben ist.&lt;br /&gt;
{{Hinweis| ''genType'' kann vom Type float, vec2, vec3 oder vec4 sein, ''mat'' vom Typ mat2, mat3 oder mat4.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Trigonometrie und Winkel==&lt;br /&gt;
Alle übergebenen Winkel sollten, soweit nicht anders vermerkt, in Radien angegeben werden.&lt;br /&gt;
&lt;br /&gt;
* genType radians (genType degrees)&lt;br /&gt;
: Wandelt von Grad nach Radien. &lt;br /&gt;
* genType degrees (genType radians)&lt;br /&gt;
: Wandelt von Radien nach Grad.&lt;br /&gt;
* genType sin (genType angle)&lt;br /&gt;
: Gibt den Sinus von Angle zurück, wobei Angle in Radien angegeben wird.&lt;br /&gt;
* genType cos (genType angle)&lt;br /&gt;
: Gibt den Cosinus von Angle zurück, wobei Angle in Radien angegeben wird.&lt;br /&gt;
* genType tan (genType angle)&lt;br /&gt;
: Gibt den Tangens von Angle zurück, wobei Angle in Radien angegeben wird.&lt;br /&gt;
* genType asin (genType x)&lt;br /&gt;
: Liefert den Arcsinus von x zurück, also den Winkel dessen Sinus x ergeben würde.&lt;br /&gt;
* genType acos (genType x)&lt;br /&gt;
: Liefert den Arccosinus von x zurück, also den Winkel dessen Cosinus x ergeben würde.&lt;br /&gt;
* genType atan (genType y, genType x)&lt;br /&gt;
: Liefert den Winkel zurück, dessen Tangens x/y ergeben würde.&lt;br /&gt;
* genType atan (genType y_over_x)&lt;br /&gt;
: Liefert den Winkel zurück, dessen Tangens x über y ergeben würde.&lt;br /&gt;
&lt;br /&gt;
==Exponentiell==&lt;br /&gt;
* genType pow (genType x, genType y)&lt;br /&gt;
: Gibt x hoch y zurück.&lt;br /&gt;
* genType exp2 (genType x)&lt;br /&gt;
: Gibt 2 hoch x zurück.&lt;br /&gt;
* genType log2 (genType x)&lt;br /&gt;
: Gibt den Logarithmus zur Basis 2 von x zurück.&lt;br /&gt;
* genType sqrt (genType x)&lt;br /&gt;
: Gibt die Wurzel von x zurück.&lt;br /&gt;
* genType inversesqrt (genType x)&lt;br /&gt;
: Gibt die umgekehrte Wurzel von x zurück. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Standardfunktionen==&lt;br /&gt;
* genType abs (genType x)&lt;br /&gt;
: Liefert den absoluten Wert von x zurück.&lt;br /&gt;
* genType sign (genType x)&lt;br /&gt;
: Gibt -1.0 zurück, wenn x &amp;lt; 0.0, 0.0 wenn x = 0.0 und 1.0 wenn x &amp;gt; 0.0.&lt;br /&gt;
* genType floor (genType x)&lt;br /&gt;
: Gibt denn nächsten Integerwert zurück, der kleiner oder gleich x ist.&lt;br /&gt;
* genType ceil (genType x)&lt;br /&gt;
: Gibt den nächsten Integerwert zurück, der größer oder gleich x ist.&lt;br /&gt;
* genType fract (genType x)&lt;br /&gt;
: Gibt den Nachkommateil von x zurück.&lt;br /&gt;
* genType mod (genType x, float y) &lt;br /&gt;
* genType mod (genType x, genType y)&lt;br /&gt;
: Gibt den Modulus zurück. (=x-y * floor(x/y)) &lt;br /&gt;
* genType min (genType x, genType y) &lt;br /&gt;
* genType min (genType x, float y)&lt;br /&gt;
: Liefert y zurück wenn y &amp;lt; x, ansonsten x. &lt;br /&gt;
* genType max (genType x, genType y) &lt;br /&gt;
* genType max (genType x, float y)&lt;br /&gt;
: Liefert y zurück wenn x &amp;lt; y, ansonsten x. &lt;br /&gt;
* genType clamp (genType x, genType minVal, genType maxVal) &lt;br /&gt;
* genType clamp (genType x, float minVal, float maxVal)&lt;br /&gt;
: Zwängt x in den Bereich minVal..maxVal. &lt;br /&gt;
* genType mix (genType x, genType y, genType a)&lt;br /&gt;
* genType mix (genType x, genType y, float a)&lt;br /&gt;
: Liefert den linearen Blend zwischen x und y zurück. (= x * (1-a) + y * a) &lt;br /&gt;
* genType step (genType edge, genType x)&lt;br /&gt;
* genType step (float edge, genType x)&lt;br /&gt;
: Liefert 0.0 zurück, wenn x &amp;lt;= edge, ansonsten 1.0. &lt;br /&gt;
* genType smoothstep (genType edge0, genType edge1, genType x)&lt;br /&gt;
* genType smoothstep (float edge0, float edge1, genType x)&lt;br /&gt;
: Liefert 0.0 zurück, wenn x &amp;lt;= edge und 1.0 wenn x &amp;gt;= edge. Dabei wird eine weiche Hermite Interpolation zwischen 0 und 1 durchgeführt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Geometrie==&lt;br /&gt;
* float length (genType x)&lt;br /&gt;
: Gibt die Länge des Vektors x (= sqrt(x[0]² + x[1]² + ... + x[n]²) zurück. &lt;br /&gt;
* float distance (genType p0, genType p1)&lt;br /&gt;
: Gibt die Distanz zwischen den zwei Vektoren p0 un p1 (= length(p0-p1)) zurück. &lt;br /&gt;
* float dot (genType x, genType y)&lt;br /&gt;
: Gibt das Punktprodukt von x und y zurück (=x[0]*y[0] + x[1]*y[1] + ... + x[n]*y[n]). &lt;br /&gt;
* vec3 cross (vec3 x, vec3 y)&lt;br /&gt;
: Gibt das Kreuzprodukt von x und y zurück. &lt;br /&gt;
* genType normalize (genType x)&lt;br /&gt;
: Normalisiert den Vektor x auf die Länge 1. &lt;br /&gt;
* vec4 ftransform()&lt;br /&gt;
: Nur im Vertex Shader. Die Funktion stellt sicher, das das eingehende Vertex haargenau so transformiert wird wie in der festen Funktionspipeline. gl_Position = ftransform() wird dann also gebraucht, wenn in mehreren Durchgängen sowohl im Shader als auch in der festen Pipeline gerendert wird, um sicherzustellen das in beiden Fällen die gleiche Vertexposition herauskommt. &lt;br /&gt;
* genType faceforward (genType N, genType I, genType Nref)&lt;br /&gt;
: Gibt einen nach vorne zeigenden Vektor N zurück. (If dot(NRef, I) &amp;lt; 0 return N else return -N) &lt;br /&gt;
* genType reflect (genType I, genType N)&lt;br /&gt;
: Gibt den an der Flächenausrichtung N reflektierten Vektor I zurück. (=I-2 * dot(N,I) * N) &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Matrixfunktionen==&lt;br /&gt;
* mat matrixCompMult (mat x, mat y)&lt;br /&gt;
: Multipliziert Matrix X mit Matrix Y komponentenweise. Um eine normale lineare Matrixmultiplikation durchzuführen, sollte der &amp;quot;*&amp;quot;-Operator genutzt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Vektorvergleiche==&lt;br /&gt;
Die meisten Vektorvergleichsfunktionen liefern als Ergebnis einen boolvektor zurück, da die Vergleiche per Komponente stattfinden. Wenn man also x = vec4(1.0, 3.0, 0.0, 0.0) mit y = vec4(2.0, 1.5, 1.5, 0.0) via lessThan(x, y) vergleicht, erhält man als Ergebnis bvec(true, false, true, false).&lt;br /&gt;
&lt;br /&gt;
* bvec lessThan (vec x, vec y)&lt;br /&gt;
* bvec lessThan (ivec x, ivec y)&lt;br /&gt;
: Gibt den komponentenweisen Vergleich x &amp;lt; y zurück. &lt;br /&gt;
* bvec lessThanEqual (vec x, vec y)&lt;br /&gt;
* bvec lessThanEqual (ivec x, ivec y)&lt;br /&gt;
: Gibt den komponentenweisen Vergleich x &amp;lt;= y zurück. &lt;br /&gt;
* bvec greaterThan (vec x, vec y)&lt;br /&gt;
* bvec greaterThan (ivec x, ivec y)&lt;br /&gt;
: Gibt den komponentenweisen Vergleich x &amp;gt; y zurück. &lt;br /&gt;
* bvec greaterThanEqual (vec x, vec y)&lt;br /&gt;
* bvec greaterThanEqual (ivec x, ivec y)&lt;br /&gt;
: Gibt den komponentenweisen Vergleich x &amp;gt;= y zurück. &lt;br /&gt;
* bvec equal (vec x, vec y)&lt;br /&gt;
* bvec equal (ivec x, ivec y)&lt;br /&gt;
* bvec equal (bvec x, bvec y)&lt;br /&gt;
: Gibt den komponentenweisen Vergleich x == y zurück. &lt;br /&gt;
* bvec notEqual (vec x, vec y)&lt;br /&gt;
* bvec notEqual (ivec x, ivec y)&lt;br /&gt;
* bvec notEqual (bvec x, bvec y)&lt;br /&gt;
: Gibt den komponentenweisen Vergleich x != y zurück. &lt;br /&gt;
* bool any (bvec x)&lt;br /&gt;
: Liefert true zurück, wenn mindestens eine der Komponenten von x true ist.&lt;br /&gt;
* bool all (bvec x)&lt;br /&gt;
: Liefert true zurück, wenn alle Komponenten von x true sind. &lt;br /&gt;
* bvec not (bvec x)&lt;br /&gt;
: Liefert die logische Negation von x zurück. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Texturenzugriffe==&lt;br /&gt;
&lt;br /&gt;
Diese wichtige Funktionskategorie dient dazu, Werte aus einer an eine Textureinheit gebundenen Textur zu ermitteln. Die Texturenzugriffe können sowohl im Vertex (!) als auch im Fragment Shader ausgeführt werden, wobei der optionale Parameter bias im Vertex Shader ignoriert wird. Allerdings gibt es zusätzlich Funktionen die auf &amp;quot;Lod&amp;quot; enden und nur im Vertex Shader genutzt werden dürfen um eben dieses Manko zu umgehen. Funktionen mit dem Suffix &amp;quot;Proj&amp;quot; geben einen projizierten Texturenwert zurück.&lt;br /&gt;
&lt;br /&gt;
: '''1D-Texturen :'''&lt;br /&gt;
* vec4 texture1D (sampler1D sampler, float coord [, float bias])&lt;br /&gt;
* vec4 texture1DProj (sampler1D sampler, vec2 coord [, float bias])&lt;br /&gt;
* vec4 texture1DProj (sampler1D sampler, vec4 coord [, float bias])&lt;br /&gt;
: Nur im Vertex Shader :&lt;br /&gt;
* vec4 texture1DLod (sampler1D sampler, float coord, float lod)&lt;br /&gt;
* vec4 texture1DProjLod (sampler1D sampler, vec2 coord, float lod)&lt;br /&gt;
* vec4 texture1DProjLod (sampler1D sampler, vec4 coord, float lod)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
: '''2D-Texturen :'''&lt;br /&gt;
* vec4 texture2D (sampler2D sampler, vec2 coord [, float bias])&lt;br /&gt;
* vec4 texture2DProj (sampler2D sampler, vec3 coord [, float bias])&lt;br /&gt;
* vec4 texture2DProj (sampler2D sampler, vec4 coord [, float bias])&lt;br /&gt;
: Nur im Vertex Shader : &lt;br /&gt;
* vec4 texture2DLod (sampler2D sampler, vec2 coord, float lod)&lt;br /&gt;
* vec4 texture2DProjLod (sampler2D sampler, vec3 coord, float lod)&lt;br /&gt;
* vec4 texture2DProjLod (sampler2D sampler, vec4 coord, float lod)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
: '''3D-Texturen :'''&lt;br /&gt;
* vec4 texture3D (sampler3D sampler, vec3 coord [, float bias])&lt;br /&gt;
* vec4 texture3DProj (sampler3D sampler, vec4 coord [, float bias])&lt;br /&gt;
: Nur im Vertex Shader : &lt;br /&gt;
* vec4 texture3DLod (sampler3D sampler, vec3 coord, float lod)&lt;br /&gt;
* vec4 texture3DProjLod (sampler3D sampler, vec4 coord, float lod)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
: '''Cubemap :'''&lt;br /&gt;
* vec4 textureCube (samplerCube sampler, vec3 coord [, float bias])&lt;br /&gt;
: Nur im Vertex Shader : &lt;br /&gt;
*vec4 textureCubeLod (samplerCube sampler, vec3 coord, float lod)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
: '''Tiefentextur (Shadowmap) :'''&lt;br /&gt;
* vec4 shadow1D (sampler1DShadow sampler, vec3 coord [, float bias])&lt;br /&gt;
* vec4 shadow2D (sampler2DShadow sampler, vec3 coord [, float bias])&lt;br /&gt;
* vec4 shadow1DProj (sampler1DShadow sampler, vec4 coord [, float bias])&lt;br /&gt;
* vec4 shadow2DProj (sampler2DShadow sampler, vec4 coord [, float bias])&lt;br /&gt;
: Nur im Vertex Shader :&lt;br /&gt;
* vec4 shadow1DLod (sampler1DShadow sampler, vec3 coord, float lod)&lt;br /&gt;
* vec4 shadow2DLod (sampler2DShadow sampler, vec3 coord, float lod)&lt;br /&gt;
* vec4 shadow1DProjLod (sampler1DShadow sampler, vec4 coord, float lod)&lt;br /&gt;
* vec4 shadow2DProjLod (sampler2DShadow sampler, vec4 coord, float lod)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wie bereits eingangs gesagt ist dieses Kapitel ein sehr wichtiges, denn eine 3D-Szene ohne Texturen ist heute kaum denkbar. Darüber hinaus lassen sich durch Texturenzugriffe recht viele interessante Sachen machen, z.B. ein einfacher Blurfilter oder das freie überblenden bestimmter Texturenteile. Deshalb führe ich hier kurz ein paar Beispiele an, welche die Nutzung dieser Funktionen verdeutlichen sollen :&lt;br /&gt;
&lt;br /&gt;
===Beispiel A=== &lt;br /&gt;
Eine Textur gebunden die einfach ausgegeben werden soll&lt;br /&gt;
&lt;br /&gt;
''Im Vertex Shader'' :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
 gl_Position     = gl_ModelViewProjectionMatrix * gl_Vertex;&lt;br /&gt;
 gl_TexCoord[0]  = gl_MultiTexCoord0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
Der Vertex Shader ist recht minimal. Neben der homogenen Vertexposition leiten wir hier nur die im OpenGL-Programm angegebenen Texturkoordinaten weiter. ''Dies ist aber unbedingt nötig!'' Ohne die letzte Zeile hätten wir im Fragment Shader keine gültigen Texturkoordinaten auf TMU0, was in einer Fehldarstellung enden würde.&lt;br /&gt;
&lt;br /&gt;
''im Fragment Shader'' :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
uniform sampler2D texSampler;&lt;br /&gt;
&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
 gl_FragColor = texture2D(texSampler, vec2(gl_TexCoord[0]));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Zuerst deklarieren wir hier einen 2D-Texturensampler, wichtig : '''Texturensampler müssen IMMER als uniform deklariert werden!''' In der Hauptfunktion weisen wir dann einfach den über die Funktion texture2D aus unserer gebundenen Textur ausgelesenen Farbwert, anhand der vom Vertex Shader übergebenen Texturkoordinaten, zu.&lt;br /&gt;
&lt;br /&gt;
===Beispiel B=== &lt;br /&gt;
Zwei Texturen, jeweils auf TMU0 und TMU1. Fragmentfarbe soll eine Multiplikation der beiden Texturen darstellen.&lt;br /&gt;
&lt;br /&gt;
In diesem Beispielfall (der recht häufig vorkommt) müssen wir im Programm festlegen, ''welcher Sampler welche Textureinheit adressiert'', genau deshalb müssen die Texturensampler auch als uniform deklariert werden. Die Standardtextureneinheit eines Samplers ist TMU0, was in unserem Falle natürlich nicht brauchbar ist. Also müssen wir unserem zweiten Textursampler im Programm mitteilen das er seine Daten aus TMU1 beziehen soll :&lt;br /&gt;
&lt;br /&gt;
 glUniform1iARB(glSlang_GetUniLoc(ProgramObject, 'texSamplerTMU1'), 1);&lt;br /&gt;
&lt;br /&gt;
Dies ist also unbedingt zu machen, sobald ein Texturensampler eine Textureinheit &amp;gt; GL_TEXTURE_0 adressieren will. Die Textureneinheit des Samplers lässt sich also nicht im Shader selbst festlegen. Der Fragment Shader ist nun allerdings schnell hergeleitet (Vertex Shader verändert sich nicht, da TMU1 die Texturkoordinaten auch von TMU0 bezieht) :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
im Fragment Shader :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
uniform sampler2D texSamplerTMU0;&lt;br /&gt;
uniform sampler2D texSamplerTMU1;&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
    gl_FragColor = texture2D(texSamplerTMU0, vec2(gl_TexCoord[0])) *&lt;br /&gt;
                   texture2D(texSamplerTMU1, vec2(gl_TexCoord[0]));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Noisefunktionen==&lt;br /&gt;
Sowohl im Vertex als auch im Fragment Shader lassen sich [[GLSL noise|Noisefunktionen]] nutzen, mit deren Hilfe sich eine gewisse &amp;quot;Zufälligkeit&amp;quot; simulieren lässt (wirklich zufällige Werte sind es natürlich nicht). Ein zurückgegebener Wert liegt dabei immer im Bereich [-1..1] und ist immer bei gleichem Eigabewert auch immer gleich. Die Verwendung empfiehlt sich derzeit allerdings eher nicht, da nicht alle aktuellen Treiber die Funktionen unterstützen und eine Noisetextur wahrscheinlich performanter ist.&lt;br /&gt;
&lt;br /&gt;
* float noise1 (genType x)&lt;br /&gt;
* vec2 noise2 (genType x)&lt;br /&gt;
* vec3 noise3 (genType x)&lt;br /&gt;
* vec4 noise4 (genType x)&lt;br /&gt;
&lt;br /&gt;
==Discard==&lt;br /&gt;
Eigentlich keine Funktion, sondern eine Abbruchbedingung '''nur im Fragment Shader'''. Das Schlüsselwort {{INLINE_CODE|discard}} verwirft das aktuell bearbeitete Fragment und beendet gleichzeitig den Shader. Es kann z.B. genutzt werden um Alphamasking manuell durchzuführen.&lt;br /&gt;
Man sollte dabei jedoch beachten dass ein Großteil der aktuellen Hardware kein &amp;quot;early-out&amp;quot; (frühes Beenden) im Fragmentshader unterstützt. Wenn dort also ein {{INLINE_CODE|discard}} auftaucht, wird trotzdem auch der Code danach ausgeführt und einfach verworfen. Einen Geschwindigkeitsvorteil durch diesen Befehl wird man also erst auf neueren Karten feststellen, die dieses Faeature auch so unterstützen wie es angedacht war. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Beispielshader=&lt;br /&gt;
Wen bis hierhin nicht der Mut verlassen hat, und wer aufmerksam gelesen hat, dürfte jetzt also zumindest in der Lage sein kleinere Shader in glSlang zu schreiben und diese auch im Programm zu nutzen. Ich habe im Themenbereich &amp;quot;glSlang&amp;quot; versucht alle Bereiche der Shadersprache selbst anzusprechen und hoffe das auch brauchbar rübergebracht zu haben. Um oben erlerntes (hoffe ich doch mal) nochmal zu vertiefen werde ich jetzt (wie ich das bereits bei meinem ARB_VP-Tutorial getan habe) einen simplen Beispielshader (Vertex und Fragment Shader) auseinanderpflücken um so u.a. auch die Programmstruktur für alle die in C nicht so bewandert sind zu erörtern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Der Vertex Shader==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
uniform vec4 GlobalColor;&lt;br /&gt;
&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
 gl_Position     = gl_ModelViewProjectionMatrix * gl_Vertex;&lt;br /&gt;
 gl_FrontColor   = gl_Color * GlobalColor;&lt;br /&gt;
 gl_TexCoord[0]  = gl_MultiTexCoord0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wie gesagt recht simpel. Angefangen wird mit der Deklaration einer globalen Uniformvariable namens {{INLINE_CODE|GlobalColor}}. Wie wir uns erinnern gibt der Typenqualifizierer uniform an, das wir den Wert dieser Variable (ein 4-Komponentenvektor, da Farbwerte aus R,G,B und A bestehen) in unserem Programm an den Shader übermitteln.&lt;br /&gt;
&lt;br /&gt;
Danach gehts ohne Umwege direkt in unsere Hauptfunktion, da wir im Vertex Shader keine anderen Funktionen benötigen. Dort berechnen wir zuerst die homogene Position unseres Vertex, die sich aus der eingehenden Vertexposition multipliziert mit der Modelansichtsmatrix ergibt. Wie schonmal gesagt '''muss diesem Wert etwas zugewiesen werden''', da sonst alle darauf aufbauenden Funktionen unvorhersehbare Ergebnisse liefern.&lt;br /&gt;
Ausserdem wollen wir die Frontfarbe unseres Vertex jedesmal mit der im Programm übergebenen GlobalColor multiplizieren, so dass wir den Farbwert der gesamten Szene aus unserem Programm heraus manipulieren können. Zu guterletzt geben wir dann noch unsere aus der festen Funktionspipeline erhaltenen Texturkoordinaten auf Textureinheit 0 weiter. Wenn im Fragmentshader Texturkoordinaten verwendet werden, '''muss das getan werden'''. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Der Fragment Shader==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
uniform sampler2D Texture0;&lt;br /&gt;
uniform sampler2D Texture1;&lt;br /&gt;
uniform sampler2D Texture2;&lt;br /&gt;
uniform sampler2D Texture3;&lt;br /&gt;
&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
 vec2 TexCoord = vec2( gl_TexCoord[0] );&lt;br /&gt;
 vec4 RGB      = texture2D( Texture0, TexCoord );&lt;br /&gt;
&lt;br /&gt;
 gl_FragColor  = texture2D(Texture1, TexCoord) * RGB.r +&lt;br /&gt;
                 texture2D(Texture2, TexCoord) * RGB.g +&lt;br /&gt;
                 texture2D(Texture3, TexCoord) * RGB.b;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auch hier passiert nicht wirklich viel Großartiges. Wir deklarieren beim Shaderanfang zuerst vier Texturensampler, da wir insgesamt vier verschiedene Texturen im Shader auslesen wollen, eine Verlaufstextur und drei Oberflächentexturen. Auch hier sei wieder gesagt das man Sampler '''immer als uniform deklarieren muss'''. In der Hauptfunktion deklarieren wir dann einen Farbvektor, der auch direkt einen Farbwert aus Textureinheit 0 zugewiesen bekommt. Auf Textureinheit 0 haben wir ihm Hauptprogramm eine Verlaufstextur gebunden, die angibt wie die drei folgenden Texturen ineinander geblendet werden.&lt;br /&gt;
Danach schreiben wir dann den Farbwert des Fragmentes, der '''im Fragment Shader ausgegeben werden muss'''. Der besteht wie einfach zu erkennen aus Farbwert von Textureinheit 1 * Rotwert von Textureinheit 0 + Farbwert von Textureinheit 2 * Grünwert von Textureinheit 0 + Farbwert von Textureinheit 3 * Blauwert von Textureinheit 0. So ist z.B. an Stellen an denen in der Verlaufstextur reines blau liegt nur die dritte Textur sichtbar.&lt;br /&gt;
&lt;br /&gt;
So viel also zu unserem kleinen Beispielshader. Er ist weder besonders toll noch besonders sinnvoll, sollte aber auch eher dazu dienen euch glSlang ein wenig zu veranschaulichen, was mir hoffentlich gelungen ist.&lt;br /&gt;
&lt;br /&gt;
Wenn ihr in den vorangegangenen Kapiteln zumindest ein wenig aufgepasst habt, dann könnt ihr euch vor eurem inneren Auge hoffentlich vortstellen was der Shader macht : Er blendet drei Texturen weich anhand der Verlaufstextur ineinander über. Sowas kann man z.B. für ein Terrain nutzen, um dieses anhand einer Farbtextur zu texturieren. Für alle, die damit Probleme haben hier zwei Bilder die den Shader veranschaulichen. Links die Verlaufstextur, die angibt wo welche Textur wie stark gewichtet wird und rechts dann das Ergebnis :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; [[BILD:GLSL_sample_shader_a.jpg]] [[BILD:GLSL_sample_shader_b.jpg]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Post Mortem=&lt;br /&gt;
Das wars also, meine &amp;quot;Einführung&amp;quot; in die OpenGL Shader Sprache. Ich hoffe es hat euch nicht gelangweilt und auch die von mir zur Verfügung gestellten Informationen haben euch hoffentlich ausgereicht. Mit der Veröffentlichung dieser Einführung geht übrigens auch die Eröffnung eines Shaderforums hier auf der DGL einher, in der ihr dann also fleissig Fragen zum Thema stellen oder eure Shader präsentieren könnt. In diesem Post Mortem gehe ich jetzt noch kurz auf die Zukunft von glSlang ein und zeige ein paar Screenshots (damit die Augen entspannen können), bevor ihr euch dann selbst in die Shaderwelt stürzen könnt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Beispiele=&lt;br /&gt;
&lt;br /&gt;
Anbei ein paar exemplarische Screenshots. Da man mit GLSL aber alle möglichen Effekte berechnen kann (u.a. auch 1:1 die feste Funktionspipeline) ist es hier unmöglich einen Überblick aller möglichen Techniken zu geben.&lt;br /&gt;
&lt;br /&gt;
[[Datei:tut_glsl_eigenershader_01.png]] [[Datei:tut_glsl_eigenershader_02.png]] [[Datei:tut_glsl_eigenershader_03.png]]&lt;br /&gt;
&lt;br /&gt;
Wie im ersten (und dritten) Screenshot zu sehen ist es natürlich auch möglich mehrere Techniken innerhalb einer Szene zu nutzen. Hier sind letztendlich bis auf Hardwarelimitationen keine Grenzen gesetzt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Die Zukunft=&lt;br /&gt;
Als dieses Tutorial geschrieben wurde, war noch nicht ganz abzusehen dass bzw. ob sich GLSL auch durchsetzen würde. ARB-Shadr und NVidias cG waren damals die Platzhirsche, aber inzwischen werden ARB-Shader nicht mehr genutzt (und auch schon länger nicht mehr weiterentwickelt) und auch NVidia setzt primär auf GLSL. GLSL wird permanent weiterenwtickelt und Hersteller können dank des flexiblen Extensionsystems auch in GLSL eigene Extensions offenlegen um die aktuellsten Features (wie z.b. den Tesselator auf aktuellen ATI-Karten) nutzen zu können. GLSL it als inzwischen auch offizielle die Shadersprache frü OpenGL und wird permanent an die neusten technischen Entwicklungen im Grafikkartenbereich angepasst.&lt;br /&gt;
&lt;br /&gt;
Wer also unter OpenGL etwas mit Shadern machen möchte, kommt an GLSL nicht vorbei!&lt;br /&gt;
&lt;br /&gt;
Also viel Spaß beim Experimentieren und Shaderschreiben! Und nicht vergessen : Wir wollen sehen was ihr so treibt,&lt;br /&gt;
&lt;br /&gt;
Euer&lt;br /&gt;
:Sascha Willems&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{TUTORIAL_NAVIGATION|-|[[Tutorial_glsl2]]}}&lt;br /&gt;
[[Kategorie:Tutorial|GLSL]]&lt;/div&gt;</summary>
		<author><name>Phlegmatiker</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_glsl&amp;diff=25265</id>
		<title>Tutorial glsl</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_glsl&amp;diff=25265"/>
				<updated>2011-07-15T20:36:17Z</updated>
		
		<summary type="html">&lt;p&gt;Phlegmatiker: /* Ressourcen */ OpenGL.org richtig geschrieben :)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Einleitung=&lt;br /&gt;
Hallo und willkommen bei meiner &amp;quot;Einführung&amp;quot; in GLSL (kurz für &amp;quot;Open'''GL''' '''S'''hading '''L'''anguage&amp;quot;), der offiziellen Hochlevel-Shadersprache von OpenGL. In diesem umfangreichen Dokument werde ich versuchen, sowohl auf die Nutzung (sprich das Laden und Anhängen von Shadern im Quellcode), als auch auf die Programmierung von Shadern selbst einzugehen, inklusive aller Sprachelemente der OpenGL Shadersprache. Es wird also auch recht viele Informationen zu der C-ähnlichen Programmstruktur und den von GLSL angebotenen Variablen und Attributen gehen. Am Ende dieser Einführung sollten alle die, die sich für das Thema interessieren, in der Lage sein, zumindest einfach Shader zu schreiben und auch in ihren Programmen zu nutzen. Ausserdem soll dieses Dokument gleichzeitig als ein deutsches &amp;quot;Pendant&amp;quot; zu den von Khronoes veröffentlichten Shaderspezifikationen, und damit als alltägliches Nachschlagewerk, dienen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Vorkenntnisse==&lt;br /&gt;
Wie auch schon mein ARB_VP-Tutorial richtet sich auch diese Einführung aufgrund ihrer Thematik eher an die fortgeschritteneren GL-Programmierer und neben sehr guten GL-Kenntnissen sollten sich alle, die sich daran versuchen wollen, mit den technischen Hintergründen der GL, wie z.B. dem Aufbau der Renderpipeline auskennen. Weiterhin sind C-Kenntnisse absolut erforderlich, da die Shader ja in einer an ANSI-C angelehnten Syntax geschrieben werden. Auch Begriffsdefinitionen zu Vertex oder Fragment werden zum Verständis dieser Einführung benötigt. Wer also noch am Anfang seiner GL-Karriere steht, dem wird dieses Dokument nicht viel nützen. Ganz nebenbei solltet ihr auch noch eine gehörige Portion Zeit (am besten nen kompletten Nachmittag) mitbringen, denn die folgende Kost ist nicht nur umfangreich, sondern auch manchmal recht schwer verdaulich.&lt;br /&gt;
&lt;br /&gt;
=Was ist GLSL?=&lt;br /&gt;
Wie Eingangs kurz angesprochen handelt es sich bei GLSL um eine Shadersprache, also um eine Hochsprache, in der man die programmierbaren Teile aktueller Grafikbeschleuniger nach eigenem Belieben programmieren kann. Sie stellt quasi den Nachfolger zu den in Assembler geschriebenen Vertex- und Fragmentprogrammen ([[GL_ARB_Vertex_Program]]/[[GL_ARB_Fragment_Program]]) dar und basiert auf ANSI C, erweitert um Vektor- und Matrixtypen sowie einige C++-Mechanismen.&lt;br /&gt;
&lt;br /&gt;
Die in GLSL geschriebenen Programme nennen sich, angepasst an die Terminologie von RenderMan und DirectX, [[Shader]] (im Gegensatz zu &amp;quot;Programme&amp;quot; bei ARB_VP/FP) und werden entweder auf Eckpunkte (VertexShader), Fragmente (FragmentShader) angewendet, oder (neuerdings, ab Shadermodell 4.0) auch genutzt um Geometrie zu erstellen (Geometryshader). Andere Teile der Renderpipeline (z.B. die Rasterisierung) können momentan noch nicht durch Shader beeinflusst werden, was allerdings in Zukunft noch kommen kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Voraussetzungen==&lt;br /&gt;
&lt;br /&gt;
GLSL wurde 2005 mit OpenGL 1.5 eingeführt. Während es in Sachen Treiber- und Hardwareunterstützung anfänglich noch dürftig aussah, wird man inzwischen keine Grafikkarte mehr kaufen können die nicht zumindest Vertex- und Fragmentshader beherscht. Geometrieshader hingegen sind relativ neu und wurden erst mit Shadermodell 4.0 eingeführt, hier ist es also unter Umständen noch möglich dass selbst aktuelle Treiber/Karten keine Geometrieshader beherrschen.&lt;br /&gt;
&lt;br /&gt;
Natürlich benötigt man auch einen passenden OpenGL-Header der die für GLSL nötigen Funktionen exportiert. Ich verweise dazu auf unseren eigenen OpenGL-Header [[DGLOpenGL.pas]], der peermanent auf dem aktuellsten Stand gehalten wird und auch Support für Geometrieshader mitbringt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Extensions==&lt;br /&gt;
&lt;br /&gt;
Die GL-Shadersprache &amp;quot;besteht&amp;quot; in ihrer aktuellen Version aus folgenden Extensions, fürs Verständnis wäre es nicht schlecht, wenn ihr euch zumindest die Einleitungen dazu durchlest :&lt;br /&gt;
* [[GL_ARB_Shader_Objects]] ([http://oss.sgi.com/projects/ogl-sample/registry/ARB/shader_objects.txt Orginal Spezifikation])&lt;br /&gt;
: Definiert die API-Aufrufe die zum Erstellen, Kompilieren, Linken, Anhängen und Aktivieren von Shader- und Programmobjekten nötig sind. &lt;br /&gt;
* [[GL_ARB_Vertex_Shader]] ([http://oss.sgi.com/projects/ogl-sample/registry/ARB/vertex_shader.txt Orginal Spezifikation])&lt;br /&gt;
: Fügt der OpenGL Programmierbarkeit auf Vertexebene hinzu. &lt;br /&gt;
* [[GL_ARB_Fragment_Shader]] ([http://oss.sgi.com/projects/ogl-sample/registry/ARB/fragment_shader.txt Orginal Spezifikation])&lt;br /&gt;
: Fügt der OpenGL Programmierbarkeit auf Fragmentebene hinzu. &lt;br /&gt;
* [[GL_ARB_Shading_Language_100]] ([http://oss.sgi.com/projects/ogl-sample/registry/ARB/shading_language_100.txt Orginal Spezifikation])&lt;br /&gt;
: Gibt die unterstützte Version von glSlang an, momentan 1.00.&lt;br /&gt;
&lt;br /&gt;
'''Hinweis''' : Seit OpenGL 2.0 ist GLSL Teil des Kerns. Wenn die Karte als OpenGL 2.0 unterstützt, dann unterstützt sie auch (zumindest in Software) Vertex- und Fragmentshader.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Sprachversionen==&lt;br /&gt;
&lt;br /&gt;
Neben der OpenGL-Version und dem vorhandenen Shadermodell (das eher an DirectX ausgerichtet ist), bietet auch GLSL verschiedene Versionen, die entsprechend erweiterte Funktionalität bieten.&lt;br /&gt;
&lt;br /&gt;
Auslesen kann man die verfürgbare GLSL-Version wie folgt :&lt;br /&gt;
&lt;br /&gt;
 glGetString(GL_SHADING_LANGUAGE_VERSION)&lt;br /&gt;
&lt;br /&gt;
Erst ab Version 1.4. kann man davon ausgehen dass GLSL alle Features des Shadermodells 4.0 liefert, ab 1.3 grob gesagt Shadermodell 3.0 (bei GLSL lässt sich das leider nicht so leicht unterteilen).&lt;br /&gt;
&lt;br /&gt;
Ausserdem kann man seinem Shader eine Versionsnummer verpassen. Sollte der Shadercompiler (also Treiber bzw. Hardware) diese Version nicht unterstützen, gibt dieser eine Fehlermeldung heraus :&lt;br /&gt;
&lt;br /&gt;
 #version 1.50 &lt;br /&gt;
&lt;br /&gt;
''(Hinweis : Muss am Anfang des Shaders stehen)''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Objekte==&lt;br /&gt;
&lt;br /&gt;
Im Zuge der Vereinheitlichung der GL wird immer häufiger in Objekte gekapselt, deren API dann auch aneinander angelehnt ist. Ziel ist, dabei die Programmierung der GL uniform zu machen, so dass z.B. zwischen dem Erstellen und Verwalten eines Vertex-Buffer-Objektes oder eines Shader-Objektes kaum ein Unterschied besteht (demnächst kommen dann auch Pixel-Buffer-Objekte dazu). Mit glSlang wurden dann im Zuge dieser Aktion zwei neue Objekte eingeführt, deren Definition ihr euch unbedingt einprägen solltet :&lt;br /&gt;
&lt;br /&gt;
* '''Programmobjekt'''&lt;br /&gt;
:Ein Objekt, an das die Shader später angebunden werden. Bietet Funktionalität zum Linken der Shader und prüft dabei die Kompatibilität zwischen Vertex- und Fragmentshader.&lt;br /&gt;
&lt;br /&gt;
* '''Shaderobjekt'''&lt;br /&gt;
:Dieses Objekt verwaltet den Quellcodestring eines Shaders und ist entweder vom Typ '''GL_VERTEX_SHADER''', '''GL_FRAGMENT_SHADER_ARB''' oder '''GL_GEOMETRY_SHADER'''.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Ressourcen==&lt;br /&gt;
&lt;br /&gt;
Die Shadersprache ist keinesfalls final und es wurden bereits diverse Ausdrücke für zukünftige Verwendung reserviert, denn ein Ziel bei ihrer Entwicklung war es, sie so zukunftsorientiert zu gestalten, dass auch Grafikkarten der nächsten und übernächsten Generation voll ausgenutzt werden können. Damit einher geht die Tatsache, dass sich die Spezifikationen in Zukunft ändern/erweitern werden, weshalb man da immer einen Blick hineinwerfen sollte. Die Anlaufstelle dafür ist die [http://www.opengl.org/documentation/specs/ Spezifikationenliste auf OpenGL.org].&lt;br /&gt;
&lt;br /&gt;
=GLSL im Programm=&lt;br /&gt;
Bevor wir uns mit der Syntax von glSlang beschäftigen, zeige ich euch erstmal, wie ihr Shader in euer Programm einbindet und nutzt. Warum das zuerst? Ganz einfach deshalb, weil ihr dann das, was ihr im glSlang-Syntaxteil lernt, direkt in eurer Testanwendung verwenden könnt. Hoffe diese Entscheidung klingt logisch und findet Anklang.&lt;br /&gt;
&lt;br /&gt;
Zuerst benötigen wir natürlich unsere Objekte. Zum einen ein ''Programmobjekt'', an das unsere Shader gebunden werden, und zwei ''Shaderobjekte'', die den Quellcode unseres Vertex bzw. Fragment Shaders aufnehmen. Dazu wurde eigens der neue &amp;quot;Datentyp&amp;quot; {{INLINE_CODE|glHandle}} eingeführt, der ein Objekthandle repräsentiert. Wir deklarieren also wie folgt :&lt;br /&gt;
&lt;br /&gt;
 ProgramObject        : GLhandle;&lt;br /&gt;
 VertexShaderObject   : GLhandle;&lt;br /&gt;
 FragmentShaderObject : GLhandle;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nach dieser Deklaration können wir dann damit beginnen unsere Objekte zu erstellen. Den Anfang macht das Programmobjekt :&lt;br /&gt;
&lt;br /&gt;
 ProgramObject        := glCreateProgram;&lt;br /&gt;
&lt;br /&gt;
Die Funktion [[glCreateProgram]] erstellt uns oben ein leeres Programmobjekt und gibt ein gültiges Handle darauf zurück.&lt;br /&gt;
&lt;br /&gt;
Weiter gehts mit der Erstellung unseres Vertex bzw. Fragment Shaders :&lt;br /&gt;
&lt;br /&gt;
 VertexShaderObject   := glCreateShader(GL_VERTEX_SHADER);&lt;br /&gt;
 FragmentShaderObject := glCreateShader(GL_FRAGMENT_SHADER);&lt;br /&gt;
&lt;br /&gt;
[[glCreateShader]] dient zur Generierung eines leeren Shaderobjektes. Momentan unterstützt diese Funktion VertexShader und FragmentShader.&lt;br /&gt;
&lt;br /&gt;
Nachdem wir nun also zwei gültige Shaderobjekte haben, wollen wir diese auch mit entsprechendem Quellcode versorgen :&lt;br /&gt;
&lt;br /&gt;
 glShaderSource(VertexShaderObject, 1, @ShaderText, @ShaderLength);&lt;br /&gt;
 glShaderSource(FragmentShaderObject, 1, @ShaderText, @ShaderLength);&lt;br /&gt;
&lt;br /&gt;
Via [[glShaderSource]] setzen wir den Quellcode eines Shaderobjektes ''komplett'' neu. Zum Laden des Quellcodes bietet sich unter Delphi übrigens eine TStringList geradezu an. Es sollte beachtet werden, dass der Quellcode zu diesem Zeitpunkt ''nicht geparst'' wird, also keine Fehleruntersuchung stattfindet.&lt;br /&gt;
&lt;br /&gt;
Der Quellcode wurde jetzt also an unsere Shaderobjekte gebunden und sollte dann natürlich auch noch kompiliert werden :&lt;br /&gt;
&lt;br /&gt;
 glCompileShader(VertexShaderObject);&lt;br /&gt;
 glCompileShader(FragmentShaderObject);&lt;br /&gt;
&lt;br /&gt;
Der glSlang-Compiler des Treibers wird bei einem Aufruf von [[glCompileShader]] versuchen, unsere Shader zu kompilieren. Sofern diese keine Fehler aufweisen, sollte dies auch erfolgreich sein. Wenn nicht, dann spuckt uns der Shadercompiler (je nach Treiber) recht detaillierte Infos aus. Wie man an diese Infos kommt könnt ihr gleich nachlesen.&lt;br /&gt;
&lt;br /&gt;
Wenn unsere Shader dann kompiliert werden konnten, ist es Zeit, diese an unser anfangs erstelltes Programmobjekt anzuhängen :&lt;br /&gt;
&lt;br /&gt;
 glAttachShader(ProgramObject, VertexShaderObject);&lt;br /&gt;
 glAttachShader(ProgramObject, FragmentShaderObject);&lt;br /&gt;
&lt;br /&gt;
Nachdem die Shaderobjekte nun an das Programmobjekt angehängt wurden, werden diese nicht mehr benötigt und ihre Resourcen können freigegeben werden :&lt;br /&gt;
&lt;br /&gt;
 glDeleteShader(VertexShaderObject);&lt;br /&gt;
 glDeleteShader(FragmentShaderObject);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Am Schluß müssen wir dann noch unsere ans Programmobjekt gebundenen Shader linken :&lt;br /&gt;
&lt;br /&gt;
 glLinkProgram(ProgramObject);&lt;br /&gt;
&lt;br /&gt;
Während [[glCompileShader]] unsere Shader auf syntaktische Fehler innerhalb ihres lokalen Raums geprüft hat, werden beim Linken durch [[glLinkProgram]] die angehangenen Shader zu einem ausführbaren Shader gelinkt. Folgende Bedingungen führen zu einem '''Linkerfehler''':&lt;br /&gt;
&lt;br /&gt;
* Die Zahl der von der Implementation unterstützten Attributvariablen wurde überschritten&lt;br /&gt;
* Der Speicherplatz für Uniformvariablen wurde überschritten&lt;br /&gt;
* Die Zahl der von der Implementation angebotenen Sampler wurde überschritten&lt;br /&gt;
* Die main-Funktion fehlt&lt;br /&gt;
* Die Liste der Varying-Variablen des Vertexshaders stimmt nicht mit der des Fragmentshaders überein&lt;br /&gt;
* Funktions- oder Variablenname nicht gefunden&lt;br /&gt;
* Eine gemeinsame Globale ist mit unterschiedlichen Werten oder Typen initialisiert worden&lt;br /&gt;
* Zwei Sampler unterschiedlichen Typs zeigen auf die selbe Textureneinheit&lt;br /&gt;
* Ein oder mehrere angehangene(r) Shader wurden nicht erfolgreich kompiliert&lt;br /&gt;
&lt;br /&gt;
Die Nutzung von glSlang im eigenen Programm ist wie oben erkennbar also nicht wirklich schwer und innerhalb kurzer Zeit realisiert. Natürlich ist es auch möglich z.B. nur einen VertexShader oder nur einen FragmentShader an ein Programmobjekt zu binden.&lt;br /&gt;
&lt;br /&gt;
Noch eine kleine Notiz zum Löschen der Shader mittel [[glDeleteShader]] : Da Shader(objekte) einen Referenzzähler besitzen und erst gelöscht werden wenn diese nirgendwo mehr benötigt werden, ist es nicht falsch diese vor dem Linkvorgang zu löschen. Allerdings spielt es letztendlich keine Rolle ob die Löschanweisung vorher der nachher ausgeführt wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Fehlererkennung==&lt;br /&gt;
Natürlich wird es ohne Fehlerausgabe recht schwer, etwaige Probleme in einem Vertex- oder Fragmentshader zu finden. Doch auch in diesem Bereich wurde glSlang recht gut durchdacht und es wurden zwei Funktionen eingeführt, welche im Zusammenspiel die Fehlersuche recht einfach machen, nämlich [[glGetShaderInfoLog]] und [[glGetShader]] mit dem Argument {{INLINE_CODE|GL_OBJECT_INFO_LOG_LENGTH}}. Erstere Funktion liefert uns einen Logstring, während uns letztere Funktion dessen Länge angibt. Der Logstring wird verändert, sobald ein Shader kompiliert oder ein Programm gelinkt wird.&lt;br /&gt;
&lt;br /&gt;
Um die Ausgabe dieses Logs so einfach wie möglich zu machen, bietet es sich an beide in einer einfach Funktion unterzubringen :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;function glSlang_GetInfoLog(pShader : GLHandleARB) : String;&lt;br /&gt;
var&lt;br /&gt;
 blen,slen : GLInt;&lt;br /&gt;
 InfoLog   : PGLCharARB;&lt;br /&gt;
begin&lt;br /&gt;
glGetShaderiv(glObject, GL_INFO_LOG_LENGTH , @blen);&lt;br /&gt;
if blen &amp;gt; 1 then&lt;br /&gt;
 begin&lt;br /&gt;
 GetMem(InfoLog, blen*SizeOf(GLCharARB));&lt;br /&gt;
 glGetShaderInfoLog(pShader, blen, slen, InfoLog);&lt;br /&gt;
 Result := PChar(InfoLog);&lt;br /&gt;
 Dispose(InfoLog);&lt;br /&gt;
 end;&lt;br /&gt;
end;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Funktion ist recht leicht erklärt : Zuerst lassen wir uns über {{INLINE_CODE|glGetShaderiv}} mitteilen wie lang der aktuelle Infolog ist. Sollte dort tatsächlich etwas drinstehen (blen &amp;gt; 1), dann lassen wir uns dessen Inhalt via {{INLINE_CODE|glGetShaderInfoLog}} in {{INLINE_CODE|InfoLog}} ausgeben und liefern diesen als Ergebnis zurück.&lt;br /&gt;
&lt;br /&gt;
Wie bereits gesagt wird nur nach dem Kompilieren eines Shaders bzw. dem Linken eines Programmobjektes ein Infolog erstellt. Es bietet sich dadurch an, direkt danach einen solchen Aufruf zu machen :&lt;br /&gt;
&lt;br /&gt;
 glCompileShader(VertexShaderObject);&lt;br /&gt;
 ShowMessage(glSlang_GetInfoLog(VertexShaderObject));&lt;br /&gt;
&lt;br /&gt;
Wenn unser Vertex Shader komplett fehlerfrei kompiliert werden konnte, dann sehen wir als Ergebnis nur einen leeren Dialog. Ist dies nicht der Fall, so werden wir vom Treiber mit recht detaillierten Fehlerinformationen &amp;quot;belohnt&amp;quot;, z.B. so :&lt;br /&gt;
&lt;br /&gt;
[[Bild:GLSL_error_vshader.jpg]]&lt;br /&gt;
&lt;br /&gt;
Auch das Infolog nach dem Linken des Programmobjektes dürfte, selbst wenn keine Fehler vorkommen, recht interessant sein, das sieht dann nämlich so aus :&lt;br /&gt;
&lt;br /&gt;
[[Bild:GLSL info programobject.jpg]]&lt;br /&gt;
&lt;br /&gt;
Wie zu sehen, wird uns nach dem erfolgreichen Linken auch gesagt, ob und welcher Shader in Hardware bzw. Software läuft. Für Debuggingzwecke sicherlich eine mehr als brauchbare Information.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Shader benutzen==&lt;br /&gt;
Um den Shader auch für die nächsten Polygone zu benutzen oder Uniformparameter übergeben zu können, ruft man die Funktion&lt;br /&gt;
 glUseProgramt(ProgramObject);&lt;br /&gt;
um alle Shader zu deaktivieren, ruft man dieselbe Funktion mit dem Parameter 0.&lt;br /&gt;
&lt;br /&gt;
==Parameterübergabe==&lt;br /&gt;
Uniformparameter (mehr dazu später) stellen die Schnittstelle zwischen eurem Programm und dem Shader dar, werden also genutzt um Daten aus dem Programm heraus an einen Shader zu übergeben. Zur Übergabe dieser Parameter bietet OpenGL diverse Funktionen, die alle Abkömmlinge von [[glUniform]] sind. Während mit {{INLINE_CODE|glUniform4f}} z.B. ein Vier-Komponentenvektor an das Programmobjekt übergeben wird, kann man mittels {{INLINE_CODE|glUniformMatrix4fv}} ganze Matrizen schnell und einfach übergeben. Ausserdem gibt es nun die Möglichkeit Uniformparameter direkt über ihren Namen, statt wie unter ARB_FP/VP über einen festen Index zu adressieren. Die Funktion [[glGetUniformLocationARB]] gibt anhand des übergebenen Parameternamens dessen Position zurück. Man kann also ganz einfach über den Namen drauf zugreifen :&lt;br /&gt;
&lt;br /&gt;
 glUniform3f(glGetUniformLocation(ProgramObject, PGLCharARB('LightPosition')), LPos[0], LPos[1], LPos[2]);&lt;br /&gt;
 glUniform1i(glGetUniformLocation(ProgramObject, PGLCharARB('texSamplerTMU3')), 3);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wichtig ist hier, das man je nach Parametertyp auch die passende Anzahl von Argumenten übergibt. Also für einen 4-Komponenten Floatvektor {{INLINE_CODE|glUniform4fARB}} und für einen einfachen Integerwert (z.B. Textureinheit für einen Sampler) glUnifrom1iARB. Auch nicht vergessen dürft ihr, das die Namen der Parameter genauso wie im Shader geschrieben werden müssen, also Groß- und Kleinschreibung beachtet werden muß.&lt;br /&gt;
&lt;br /&gt;
=Die Shadersprache=&lt;br /&gt;
&lt;br /&gt;
Nachdem wir uns mit der Einbindung der glSlang-Shader in unser Programm beschäftigt haben, wollen wir uns in den folgenden Kapiteln um die Sprachelemente von glSlang kümmern. Wie schon gesagt basiert glSlang auf ANSI-C, wurde allerdings um speziell auf den Zielbereich angepasste Vektor- und Matrixtypen und einige C++-Features wie das freie deklarieren von Variablen an jeder Stelle und das Funktionsüberladen auf Basis des Argumenttyps erweitert. Wer sich ein wenig mit C/C++ auskennt sollte also in der nun folgenden Materie keine Probleme bekommen.&lt;br /&gt;
&lt;br /&gt;
'''Obligatorische Hinweise für verwöhnte Delphi-Nutzer : '''&lt;br /&gt;
*Wie von C/C++ her gewohnt, spielt auch in glSlang die Groß- und Kleinschreibung eine wichtige Rolle, also bitte achtet darauf. gl_Position ist eine komplett andere Variable als z.B. gl_position.&lt;br /&gt;
*Es findet keine automatische Typenkonvertierung statt. Das bedeutet also das float MyFloat = 1 ungültig ist und es in dem Falle float MyFloat = 1.0 heissen muss. Typecasts müssen also immer manuell stattfinden, z.B. MyFloat = float(MyInt).&lt;br /&gt;
&lt;br /&gt;
'''Kleine Programmstrukturkunde für C-Unkundige :'''&amp;lt;br&amp;gt;&lt;br /&gt;
Da sicherlich einige Delpher nie richtig was mit C gemacht haben, zeige ich mal anhand eines kleinen Beispieles (das auf keinen Fall nen brauchbaren Shader darstellt) den grundlegenden Aufbau eines glSlang-Shaders, der natürlich dem Aufbau eines C-Programmes stark ähnelt :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
uniform vec4 VariableA;&lt;br /&gt;
float VariableB;&lt;br /&gt;
vec3  VariableC;&lt;br /&gt;
const float KonstanteA = 256.0;&lt;br /&gt;
&lt;br /&gt;
float MyFunction(vec4 ArgumentA)&lt;br /&gt;
 {&lt;br /&gt;
 float FunktionsVariableA = float(5.0);&lt;br /&gt;
&lt;br /&gt;
 return float(ArgumentA * (FunktionsVariableA + KonstanteA));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
// Ich bin ein Kommentar&lt;br /&gt;
/* Und ich auch */&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
 gl_Position     = gl_ModelViewProjectionMatrix * gl_Vertex;&lt;br /&gt;
 gl_TexCoord[0]  = gl_MultiTexCoord0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sieht doch recht bekannt aus, unser Programmaufbau. Delphi und C haben ja so einige Grundlagen gleich, darunter auch der ungefähre Programmaufbau. Ausserhalb jeglicher Funktionen legen wir am Programmanfang unsere Variablen, Konstanten und Attribute fest, die dann ''global'' nutzbar sind, also in jeder Funktion.&lt;br /&gt;
&lt;br /&gt;
Darunter deklarieren wir dann eine kleine Funktion. Wie auch bei den Variablendeklarationen wird hier der Rückgabetyp nicht wie bei Pascal nach dem Funktionsnamen untergebracht, sondern davor. Innerhalb der Funktion können dann wieder Variablen deklariert werden, die dann allerdings ''lokal'', also nur in dieser Funktion nutzbar sind. Vorteil dieser Deklaration ist die Tatsache, dass je nach Grafikkarte nur bestimmt viele globale Variablen deklariert werden können. Wenn möglich sollte man also mit lokalen Vorlieb nehmen. Unsere Funktion gibt dann natürlich noch via return einen Wert zurück, ''was gemacht werden muss'', sofern man diese nicht als void deklariert hat (entspräche dann einer Prozedur in Pascal). Wird dies nicht getan, so spuckt der Compiler einen Fehler aus.&lt;br /&gt;
&lt;br /&gt;
Auch wichtig sind natürlich Kommentare. Erste Variante (Doppelslash) ist auch in der Pascalwelt verfügbar und kommentiert eine einzelne Zeile aus. Die Variante darunter kann man für Kommentarblöcke nutzen (/* .. */) und entspricht den Kommentaren in geschweiften Klammern in Delphi.&lt;br /&gt;
&lt;br /&gt;
Danach kommt dann die '''wichtigste Funktion''' des Shaders, nämlich '''main''', die in keinem Shader fehlen darf. Sie stellt quasi den Programmkörper dar und ist oft auch die einzige Funktion in einem Shader. Sie erhält weder ein Argument, noch gibt sie einen Wert zurück.&lt;br /&gt;
&lt;br /&gt;
Soviel also zum grundlegenden Aufbau eines Shader. Hoffe das jetzt alle die in C nicht so bewandert sind damit klar kommen, und dann bald ihre ersten glSlang-Shader schreiben können.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Datentypen==&lt;br /&gt;
&lt;br /&gt;
Obwohl einige Datentypen aus C übernommen wurden, sieht man der Typenliste an, das diese speziell auf den 3D-Bereich zugeschnitten wurde. Variablen müssen vor ihrer Nutzung eindeutig deklariert sein, Typecasting erfolgt über Konstruktoren (dazu später mehr). Folgende Datentypen stehen sowohl im Vertex- als auch Fragmentshader zur Verfügung :&lt;br /&gt;
&lt;br /&gt;
{|{{Prettytable_B1}}&lt;br /&gt;
!Datentyp  	&lt;br /&gt;
!Erklärung&lt;br /&gt;
|-&lt;br /&gt;
|void 	&lt;br /&gt;
|Für Funktionen die keinen Wert zurückgeben&lt;br /&gt;
|-&lt;br /&gt;
|bool 	&lt;br /&gt;
|Konditionaler Typ, entweder true (wahr) oder false (falsch)&lt;br /&gt;
|-&lt;br /&gt;
|int 	&lt;br /&gt;
|Vorzeichenbehafteter Integerwert&lt;br /&gt;
|-&lt;br /&gt;
|float 	&lt;br /&gt;
|Fließkommaskalar mit Singlegenauigkeit (32 Bit)&lt;br /&gt;
|-&lt;br /&gt;
|vec2 	&lt;br /&gt;
|2-Komponenten Fließkommavektor&lt;br /&gt;
|-&lt;br /&gt;
|vec3 	&lt;br /&gt;
|3-Komponenten Fließkommavektor&lt;br /&gt;
|-&lt;br /&gt;
|vec4 	&lt;br /&gt;
|4-Komponenten Fließkommavektor&lt;br /&gt;
|-&lt;br /&gt;
|bvec2 	&lt;br /&gt;
|2-Komponenten Booleanvektor&lt;br /&gt;
|-&lt;br /&gt;
|bvec3 	&lt;br /&gt;
|3-Komponenten Booleanvektor&lt;br /&gt;
|-&lt;br /&gt;
|bvec4 	&lt;br /&gt;
|4-Komponenten Booleanvektor&lt;br /&gt;
|-&lt;br /&gt;
|ivec2 	&lt;br /&gt;
|2-Komponenten Integervektor&lt;br /&gt;
|-&lt;br /&gt;
|ivec3 	&lt;br /&gt;
|3-Komponenten Integervektor&lt;br /&gt;
|-&lt;br /&gt;
|ivec4 	&lt;br /&gt;
|4-Komponenten Integervektor&lt;br /&gt;
|-&lt;br /&gt;
|mat2 	&lt;br /&gt;
|2x2 Fließkommamatrix&lt;br /&gt;
|-&lt;br /&gt;
|mat3 	&lt;br /&gt;
|3x3 Fließkommamatrix&lt;br /&gt;
|-&lt;br /&gt;
|mat4 	&lt;br /&gt;
|4x4 Fließkommamatrix&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die sampler-Typen stellen eine besondere Klasse zum Zugriff auf Texturen dar, und werden im Kapitel 6.7 genauer erklärt, inklusive einiger Anwendungsbeispiele.&lt;br /&gt;
&lt;br /&gt;
{|{{Prettytable_B1}}&lt;br /&gt;
!Datentyp  	&lt;br /&gt;
!Erklärung&lt;br /&gt;
|-&lt;br /&gt;
|sampler1D 	&lt;br /&gt;
|Zugriff auf 1D-Textur&lt;br /&gt;
|-&lt;br /&gt;
|sampler2D 	&lt;br /&gt;
|Zugriff auf 2D-Textur&lt;br /&gt;
|-&lt;br /&gt;
|sampler3D 	&lt;br /&gt;
|Zugriff auf 3D-Textur&lt;br /&gt;
|-&lt;br /&gt;
|samplerCube 	&lt;br /&gt;
|Zugriff auf Cubemap&lt;br /&gt;
|-&lt;br /&gt;
|sampler2DRect 	&lt;br /&gt;
|Zugriff auf Texturen die nicht 2^n * 2^n entsprechen (&amp;quot;non power-of-two&amp;quot;, NPOT)&lt;br /&gt;
|-&lt;br /&gt;
|sampler1DShadow 	&lt;br /&gt;
|Zugriff auf 1D-Tiefentextur mit Vergleichsoperation&lt;br /&gt;
|-&lt;br /&gt;
|sampler2DShadow 	&lt;br /&gt;
|Zugriff auf 2D-Tiefentextur mit Vergleichsoperation&lt;br /&gt;
|-&lt;br /&gt;
|samplerCubeShadow&lt;br /&gt;
|Zugriff auf Tiefentextur in einer Cubemap (z.b. für omni-diretionale Lichtquellen)&lt;br /&gt;
|-&lt;br /&gt;
|sampler2DRectShadow&lt;br /&gt;
|Zugriff auf 2D-NPOT-Tiefentextur &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|sampler1DArray&lt;br /&gt;
|Zugriff auf ein array aus 1D-Texturen &lt;br /&gt;
|-&lt;br /&gt;
|sampler2DArray&lt;br /&gt;
|Zugriff auf ein array aus 2D-Texturen &lt;br /&gt;
|-&lt;br /&gt;
|sampler1DArrayShadow&lt;br /&gt;
|Zugriff auf ein array aus 1D-Tiefentexturen &lt;br /&gt;
|-&lt;br /&gt;
|sampler2DArrayShadow&lt;br /&gt;
|Zugriff auf ein array aus 2D-Tiefentexturen &lt;br /&gt;
|-&lt;br /&gt;
|samplerBuffer&lt;br /&gt;
|Zugriff auf eine Puffertextur (1D-Texutr zum Speichern von Pufferobjekten)&lt;br /&gt;
|-&lt;br /&gt;
|sampler2DMS&lt;br /&gt;
|Zugriff auf eine 2D-Textur mit mehreren Samplepunkten (z.b. für Multisampling)&lt;br /&gt;
|-&lt;br /&gt;
|sampler2DMSArray&lt;br /&gt;
|Zugriff auf einarray aus 2D-Textur mit mehreren Samplepunkten (z.b. für Multisampling)&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Arrays===&lt;br /&gt;
&lt;br /&gt;
Natürlich unterstützt glSlang auch Arrays, die wie in C deklariert werden und deren Index bei 0 beginnt. Folgendes Array im Shader :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
float temp[3];&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
beginnt also bei Index 0 und endet bei Index 2. Im Gegensatz zu C lassen sich Arrays in glSlang allerdings ''nicht bei der Initialisierung vorbelegen''. Wenn ein Array als Parameter einer Funktion deklariert wird, so darf dieses keine Dimensionierung erhalten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Strukturen===&lt;br /&gt;
&lt;br /&gt;
Neu ggü. ARB_FP/VP ist nun auch die Möglichkeit, Strukturen in einem Shader zu deklarieren. Vor allem die Übersicht komplexerer Shader kann dadurch stark verbessert werden. Strukturen werden wie gewohnt mit dem Schlüsselwort {{INLINE_CODE|struct}} eingeleitet und können dann zur Typisierung von Variablen genutzt werden. Folgendes Beispiel dürfte die Nutzung verdeutlichen :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct light&lt;br /&gt;
 {&lt;br /&gt;
 bool active;&lt;br /&gt;
 float intensity;&lt;br /&gt;
 vec3 position;&lt;br /&gt;
 vec3 color;&lt;br /&gt;
 };&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Im Shader können dann neue Variablen von diesem Typ ganz einfach deklariert werden :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
 light LightSource[3];&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Der Zugriff auf die Elemente der Struktur erfolgt dann wie gewohnt über den Punkt :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
LightSource[3].position = vec3(1.0, 1.0, 5.0);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Typenqualifzierer==&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zur Typendeklaration kann eine Variable noch einen Typenqualifizerer vorangestellt bekommen, der an den Anfang der Deklaration gehört.&lt;br /&gt;
&lt;br /&gt;
* '''const'''&lt;br /&gt;
: Festgelegte (nur lesen) Konstante bzw. nur lesbarer Funktionsparameter.&lt;br /&gt;
&lt;br /&gt;
* '''uniform'''&lt;br /&gt;
: Ein den ganzen Shader über gleichbleibender Wert, der eine Schnittstelle zwischen dem Shader und der OpenGL-Anwendung darstellt. Ein Uniformwert wird in der Hauptanwendung an den entsprechenden Shader übergeben und kann dort dann genutzt werden.&lt;br /&gt;
&lt;br /&gt;
* '''attribute'''&lt;br /&gt;
: Nur lesbare Werte die eine Verbindung zwischen dem Shader und der OpenGL-VertexAPI darstellen (z.B. VertexParameter eines VertexArrays). Natürlich nur in einem Vertex Shader nutzbar.&lt;br /&gt;
&lt;br /&gt;
* '''varying'''&lt;br /&gt;
: Stellt die Verbindung zwischen einem Vertex- und einem FragmentShader dar. Werden im VertexShader geschrieben und dann perspektivisch korrekt über die Primitive interpoliert, um dann im Fragment Shader gelesen werden zu können. Nutzbar sind hier nur die Typen float, vec2, vec3, vec4, mat2, mat3 und mat4, Strukturen und andere Datentypen können nicht varying sein. Die Namen einer varying-Variable müssen sowohl im VertexShader als auch im FragmentShader gleich sein.&lt;br /&gt;
&lt;br /&gt;
* '''in'''&lt;br /&gt;
: Für Variablen die an eine Funktion übergeben und dort ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
* '''out'''&lt;br /&gt;
: Für Variablen die von einer Funktion nach aussen zurückgegeben werden.&lt;br /&gt;
&lt;br /&gt;
* '''inout'''&lt;br /&gt;
: Für Variablen die sowohl an eine Funktion übergeben als auch von dieser zurückgegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um obige Auflistung nicht leer im Raum stehen zu lassen zeige ich ein paar Beispiele die hoffentlich zum Verständnis beitragen :&lt;br /&gt;
&lt;br /&gt;
===Beispiel A=== &lt;br /&gt;
Vertexnormale soll an einen FragmenShader (interpoliert) übergeben werden :&lt;br /&gt;
&lt;br /&gt;
:Im VertexShader :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
varying vec3 VertexNormal;&lt;br /&gt;
...&lt;br /&gt;
VertexNormal = normalize(MV_IT * gl_Normal);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
:Im FragmentShader :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
varying vec3 VertexNormal;&lt;br /&gt;
...&lt;br /&gt;
TempVector = VertexNormal*...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Beispiel B=== &lt;br /&gt;
Uniformparameter zur nachträglichen Farbänderung der Szene wird im Programm übergeben :&lt;br /&gt;
&lt;br /&gt;
:Im VertexShader :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
uniform vec4 GlobalColor;&lt;br /&gt;
...&lt;br /&gt;
gl_FrontColor = GlobalColor * gl_Color;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
:Im Programm :&lt;br /&gt;
&lt;br /&gt;
 glUniform4fARB(glSlang_GetUniLoc(ProgramObject, 'GlobalColor'), Col[0], Col[1], Col[2], Col[3]);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Beispiel C=== &lt;br /&gt;
Konstante zur festen Farbänderung :&lt;br /&gt;
&lt;br /&gt;
:Im VertexShader :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
const vec4 ColorBias = vec4(0.2, 0.3, 0.0, 0.0);&lt;br /&gt;
...&lt;br /&gt;
gl_FrontColor = ColorBias * gl_Color;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
==Konstruktoren==&lt;br /&gt;
&lt;br /&gt;
Um in einem Shader ''Vektoren'' oder ''Matrizen'' mit Werten zu belegen, gibt es sogenannte Konstruktoren (nicht zu verwechseln mit z.B. Klassenkonstruktoren unter Delphi), die im Endeffekt nichts anderes als Funktionen zur Vorbelegung von Vektoren oder Matrizen darstellen. Dabei trägt der Konstruktor den selben Namen wie die Typendeklaration, also lässt sich eine Variable vom Typ {{INLINE_CODE|vec4}} mit dem Konstruktor {{INLINE_CODE|vec4(float, float, float, float)}} initialisieren.&lt;br /&gt;
&lt;br /&gt;
Allerdings hat man sich recht viel Mühe bei dieser Konstruktorgeschichte gemacht, so dass man einen vec4 nicht unbedingt mit einem {{INLINE_CODE|vec4}}-Konstruktor vorbelegen muss, sondern es vielseitige Möglichkeiten gibt. Um dies zu verdeutlichen gibts ein paar Beispiele :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
vec4 Color = vec4(1.0, 0.0, 0.0, 0.0);&lt;br /&gt;
vec4 Color = vec4(MyVec3, 1.0);&lt;br /&gt;
vec4 Color = vec4(MyVec2_A, MyVec2_B);&lt;br /&gt;
&lt;br /&gt;
vec3 LVec  = vec3(MyVec4);&lt;br /&gt;
vec2 Tmp   = vec2(MyVec3);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Trotz der recht wenigen Beispiele sollte schnell erkennbar sein, das man hier wirklich sehr viele Kombinationsmöglichkeiten hat, die dann gültig sind ''wenn man mindestens auf die benötigte Anzahl der Argumente kommt''. Im vorletzten Beispiel wird z.B. ein 3-Komponentenvektor aus einem 4-Komponentenvektor initialisiert. Das erzeugt keinen Fehler, sondern führt dazu das {{INLINE_CODE|vec3.x, vec3.y, vec3.z}} aus MyVec4 übernommen werden und MyVec4.w einfach ignoriert wird.&lt;br /&gt;
&lt;br /&gt;
Das Umkehrbeispiel, also&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
vec4 Color = vec4(MyVec3)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
funktioniert allerdings nicht, da hier die Zahl der benötigten Argumente nicht erreicht wird. In diesem Falle müsste es dann&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt; &lt;br /&gt;
vec4 Color = vec4(MyVec3, 0.0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
heissen.&lt;br /&gt;
&lt;br /&gt;
Obiges gilt natürlich auch für ''Matrixkonstruktoren'', hier sind z.B. folgende Konstuktoren denkbar, obwohl eigentlich alle Möglichkeiten nutzbar sind, ''solange die benötigte Zahl an Argumenten erreicht wird'' :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
mat4 MyMatrix = mat4(MyVec4, MyVec4, MyVec4, MyVec4);&lt;br /&gt;
mat2 MyMatrix = mat4(1.0, 0.0, 0.0, 0.0,&lt;br /&gt;
                     0.0, 1.0, 0.0, 0.0,&lt;br /&gt;
                     0.0, 0.0, 1.0, 0.0,&lt;br /&gt;
                     0.0, 0.0, 0.0, 1.0);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Vektor- und Matrixkomponenten==&lt;br /&gt;
&lt;br /&gt;
Was natürlich in keiner Shadersprache fehlen darf, ist der leichte Zugriff auf die einzelnen Komponenten eines Vektors. glSlang bietet, je nach Anwendungsgebiet gleich drei Namensets für den Zugriff auf die Komponenten eines solchen Vektors, welches Set man nutzen will bleibt natürlich frei und ist unabhängig von der Deklaration eines Vektors. Man sollte nur darauf achten, beim gleichzeitigen Zugriff auf mehrere Komponenten im gleichen Namenset zu verbleiben :&lt;br /&gt;
&lt;br /&gt;
* {x, y, z, w}&lt;br /&gt;
:Für den Zugriff auf Vektoren die Punkte, Normale oder sonstige Vertexdaten repräsentieren.&lt;br /&gt;
&lt;br /&gt;
* {r, g, b, a}&lt;br /&gt;
:Für den Zugriff auf Vektoren die Farbwerte repräsentieren.&lt;br /&gt;
&lt;br /&gt;
* {s, t, p, q}&lt;br /&gt;
:Für den Zugriff auf Vektoren die Texturkoordinaten repräsentieren.&lt;br /&gt;
&lt;br /&gt;
Ein paar Beispiele zur Unterstreichung des oben gesagten :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
v4.rgba = vec4(1.0, 0.0, 0.0, 0.0);  // gültig&lt;br /&gt;
v4.rgzw = vec4(1.0, 1.0, 1.0, 2.0);  // Ungültig, da verschiedenen Namensets&lt;br /&gt;
v2.rgb  = vec3(1.0, 2.0, 1.0);       // Ungültig, da vec2 nur r+g besitzt&lt;br /&gt;
v2.xx   = vec2(5.0, 3.0);            // Ungültig, da 2 mal gleiche Komponente&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auch der Zugriff auf die Komponenten einer Matrix geht leicht von der Hand. Namensets wie bei den Vektoren gibt es hier natürlich keine, aber folgende Beispiele sollen den Zugriff aufzeigen :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
MyMat4[2]    = vec4(1.0); // Setzt die 3.Zeile der Matrix komplett auf 1.0&lt;br /&gt;
MyMat4[3][3] = 3.5;       // Setzt das Element unren rechts auf 3.5&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ein Zugriff auf Matrixelemente ausserhalb ihrer Dimension (also z.B. MyMat4[4][4]) liefert unvorhersehabre Ergebnise, also sollte man auf diese Fälle prüfen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Vektor- und Matrixoperationen==&lt;br /&gt;
&lt;br /&gt;
Wie von C gewohnt sind in glSlang so ziemlich alle Operatoren die man auf Matrizen oder Vektoren anwenden kann überladen, so das man nicht umständlich über selbstgeschriebene Funktionen kombinieren muss. Darüber hinaus ist es in den meisten Fällen auch möglich ohne Konvertierung Fließkommawerte mit kompletten Matrizen oder Vektoren zu kombinieren. Folgende Beispiele zeigen einige der vielfältigen Kombinationsmöglichkeiten auf :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
vec3  dest;&lt;br /&gt;
vec3  source;&lt;br /&gt;
float factor;&lt;br /&gt;
&lt;br /&gt;
vec3 dest = source + factor; &lt;br /&gt;
&lt;br /&gt;
// Ist gleich&lt;br /&gt;
dest.x = source.x + factor;&lt;br /&gt;
dest.y = source.y + factor;&lt;br /&gt;
dest.z = source.z + factor;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Matrix * Vektor ist auch ohne manuelle Konvertierung möglich :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
vec3  dest;&lt;br /&gt;
vec3  source;&lt;br /&gt;
mat3  MyMat;&lt;br /&gt;
 &lt;br /&gt;
dest = source * MyMat; &lt;br /&gt;
 &lt;br /&gt;
// Ist gleich&lt;br /&gt;
dest.x = dot(source, MyMat[0]);&lt;br /&gt;
dest.y = dot(source, MyMat[1]);&lt;br /&gt;
dest.z = dot(source, MyMat[2]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auch hier sind die Möglichkeiten fast unbeschränkt und zeigen wieder wie flexibel glSlang ausgelegt ist. &lt;br /&gt;
&lt;br /&gt;
==Operatoren==&lt;br /&gt;
&lt;br /&gt;
glSlang bietet (momentan) folgende Operatoren, die Liste ist nach ihrer Gewichtung sortiert (Anfang = höchste). Alle ''reservierten'' Operatoren werden erst in kommender Hardware/glSlang-Versionen nutzbar sein :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div  align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|{{Prettytable_B1}}&lt;br /&gt;
!Operatorklasse  	&lt;br /&gt;
!Operatoren  	&lt;br /&gt;
!Assoziation&lt;br /&gt;
|-&lt;br /&gt;
|Gruppering 	&lt;br /&gt;
|() 	&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
|Arrayindizierung&amp;lt;br&amp;gt;Funktionsaufrufe und Konstruktoren&amp;lt;br&amp;gt;Strukturfeldwahl und Swizzle&amp;lt;br&amp;gt;Postinkrement und -dekrement&amp;lt;br&amp;gt; 	&lt;br /&gt;
|[]&amp;lt;br&amp;gt;()&amp;lt;br&amp;gt;.&amp;lt;br&amp;gt;++ -- 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Prefixinkrement- und dekrement&amp;lt;br&amp;gt;Einheitlich (~ reserviert) 	&lt;br /&gt;
| ++ --&amp;lt;br&amp;gt; + - ~ ! 	&lt;br /&gt;
|Rechts n. Links&lt;br /&gt;
|-&lt;br /&gt;
|Mulitplikation (% reserviert) 	&lt;br /&gt;
|* / % 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Additiv 	&lt;br /&gt;
| + - 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Bitweises Verschieben (reserviert) 	&lt;br /&gt;
|&amp;lt;&amp;lt;  &amp;gt;&amp;gt; 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Relation 	&lt;br /&gt;
|&amp;lt;  &amp;gt;  &amp;lt;=  &amp;gt;= 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Vergleich 	&lt;br /&gt;
|==  != 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Bitweises AND (reserviert) 	&lt;br /&gt;
|&amp;amp; 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Bitweises XOR (reserviert) 	&lt;br /&gt;
|^ 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Bitweises OR (reserviert) 	&lt;br /&gt;
| &amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt; 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Logisches AND 	&lt;br /&gt;
|&amp;amp;&amp;amp; 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Logisches XOR 	&lt;br /&gt;
|^^ 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Logisches OR 	&lt;br /&gt;
| &amp;lt;nowiki&amp;gt;||&amp;lt;/nowiki&amp;gt; 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|Auswahl 	&lt;br /&gt;
|?: 	&lt;br /&gt;
|Rechts n. Links&lt;br /&gt;
|-&lt;br /&gt;
|Zuweisung&amp;lt;br&amp;gt;Arithmetrische Zuweisung&amp;lt;br&amp;gt;(Modulis, Shift und bitweise Op. reserviert) 	&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt;&amp;lt;br&amp;gt; &amp;lt;nowiki&amp;gt;+= -=  *=  /=  %=&amp;lt;/nowiki&amp;gt; &amp;lt;br&amp;gt; &amp;lt;nowiki&amp;gt;&amp;lt;&amp;lt;=  &amp;gt;&amp;gt;= &amp;amp;=  ^=  |=&amp;lt;/nowiki&amp;gt; 	&lt;br /&gt;
|Rechts n. Links&lt;br /&gt;
|-&lt;br /&gt;
|Aufzählung 	&lt;br /&gt;
|, 	&lt;br /&gt;
|Links n. Rechts&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Funktionen==&lt;br /&gt;
&lt;br /&gt;
Ein großer Vorteil von Hochsprachen ist u.A. die Möglichkeit oft genutzte Codeteile in Funktionen (bzw. auch Prozeduren unter Pascal) zu verpacken um so Flexibilität als auch Übersichtlichkeit zu steigern. Wer schonmal was in C geschrieben hat, der wird sich jetzt sicherlich kein Kopfzerbrechen machen müssen. Funktionen werden in glSlang genauso nach folgendem Prinzip deklariert :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
RückgabeTyp FunktionsName(Typ0 Argument0, Typ1, Argument1, ... , TypN, ArgumentN)&lt;br /&gt;
 {&lt;br /&gt;
 return RückgabeWert;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Funktionen die ''nichts zurückgeben'' müssen mit dem RückgabeTyp {{INLINE_CODE|void}} deklariert werden, ausserdem entfällt dann logischerweise das {{INLINE_CODE|return}}. Falls die Funktion eines ihrere Argumente nach aussen übergeben soll, muss dieses Argument mit dem Typenqualifizierer out (Siehe Kapitel 4.2) versehen werden. ''Arrays'' können nur als Eingabeargumente übergeben werden und dürfen nich dimensioniert als Argument verwendet werden, sondern müssen mit leeren Klammern argumentiert werden.&lt;br /&gt;
Ein paar Beispiele :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
void MeineFunktion(float EingabeWert; out float AusgabeWert)&lt;br /&gt;
 {&lt;br /&gt;
 AusgabeWert = EingabeWert*MyConstValue;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Funktion gibt ''nichts'' zurück, aber gibt EingabeWert*MyConstValue im Ausgabeargument AusgabeWert nach aussen.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
float MeineFunktion(float EingabeWert)&lt;br /&gt;
 {&lt;br /&gt;
 return EingabeWert*MyConstValue;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bietet genau die selbe Funktionalität wie das Beispiel darüber. Allerdings wird hier der berechnete Wert als Ergebnis der Funktion zurückgeliefert.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
float VektorSumme(float v[])&lt;br /&gt;
 {&lt;br /&gt;
 return v[0]+v[1]+v[2]+v[3];&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wie bereits gesagt darf ein Array als Argument keine Dimensionierung enthalten. Wenn man der Funktion also ein Array übergibt, sollte man vorher drauf achten das es entsprechend der in der Funktion genutzten Indizes dimensioniert wurde.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==if-Anweisung==&lt;br /&gt;
&lt;br /&gt;
Selektion über eine if-Anweisung darf auch in keiner Hochsprache fehlen. Genauso wie in C oder Delphi erwartet auch hier die If-Anweisung einen boolschen Ausdruck (Wahr oder Falsch) und wird dann ausgeführt (wahr) bzw. verzweigt auf ein (wenn vorhanden) else (falsch). Verschachtelung ist wie erwartet auch möglich.&lt;br /&gt;
&lt;br /&gt;
'''Hinweis : ''' &lt;br /&gt;
Grafikkarten auf dem Stand des Shadermodells 2.0 (Radeon 9x00, Radeon X8x0, GeForceFX 5x00) unterstüzten im Fragmentshader kein Early-Out, was zur Folge hat das bei einer If-Anweisung immer alle Zweige ausgeführt werden. Am Ende wird dann aber nur ein Ergebnis geschrieben, die anderen verworfen. Auf solchen Karten bringen If-Anweisungen also im Normalfall keine Geschwindigkeitssteigerung, sondern oft eher das Gegenteil.&lt;br /&gt;
Neuere SM3.0-Karten (Radeon X1x00, GeForce6x00 und höher) ist dass nicht mehr der Fall, da hier dynamische Verzweigungen und auch Early-Out von der Hardware implementiert werden.&lt;br /&gt;
&lt;br /&gt;
==Schleifen==&lt;br /&gt;
&lt;br /&gt;
Auch Schleifen, ein wichtiges Konzept jeder Hochsprache haben ihren Weg in glSlang gefunden. Unterstützt werden folgende Schleifentypen :&lt;br /&gt;
&lt;br /&gt;
* '''for'''-Schleife&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
for (Startausdruck; Durchlaufbedingung; Wiederholungsausdruck)&lt;br /&gt;
  {&lt;br /&gt;
   statement&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''while'''-Schleife&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
while (Durchlaufbedingung)&lt;br /&gt;
 {&lt;br /&gt;
  statement&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''do'''-while-Schleife&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
do&lt;br /&gt;
 {&lt;br /&gt;
  statement&lt;br /&gt;
 }&lt;br /&gt;
 while (Durchlaufbedingung)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Hinweis :''' Grafikkarten auf dem Stand des Shadermodells 2.0 (Radeon 9x00, Radeon X8x0, GeForceFX 5x00) unterstüzten Schleifen nicht in Hardware. Schleifen werden dann beim Kompilieren vom Treiber entrollt, wodurch natürlich Shader mit weitaus mehr Instruktionen als erwartet generiert werden. Von daher sollte man auf solchen Karten möglichst auf Schleifen verzichten, oder diese nur recht kurz halten. Bei SM3.0-Karten (Radeon X1x00, GeForce6x00 und höher) ist dass nicht mehr der Fall.&lt;br /&gt;
&lt;br /&gt;
=Eingebaute Variablen, Attribute und Konstanten=&lt;br /&gt;
Nachdem wir uns nun lange genug mit den minderinterssanten Elementen der glSlang-Syntax beschäftigt haben, gehts jetzt endlich an die wirklich interessanten Dinge. Wie schon ARB_VP/ARB_FP bringt auch glSlang jede Menge eingabauter Variablen, Attribute und Konstanten mit, deren Aliase sie recht leicht identifizierbar machen (ganz im Gegensatz zum Indexgewusel bei den DX-Shadern).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Variablen im Vertex Shader==&lt;br /&gt;
Exklusiv im Vertex Shader stehen die folgenden Variablen zur Verfügung :&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_Position    muss geschrieben werden&lt;br /&gt;
:Dieser Variable '''muss''' im Vertexshader ein Wert zugewiesen werden, wird dies nicht getan ist das Ergebnis (sprich die Position des Vertex) undefiniert. Vorgesehen ist diese Variable für die ''homogene Position des Vertex'' und wird u.a. zum Clipping und Culling verwendet. Sie darf natürlich auch (mehrfach) geschrieben und ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
* float gl_PointSize    kann geschrieben werden&lt;br /&gt;
:Diese Variable wurde dazu vorgesehen um dort im VertexShader die Punktgröße in Pixeln hineinzuschreiben.&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_ClipVertex    kann geschrieben werden&lt;br /&gt;
:Falls genutzt, sollten hier die Vertexkoordinaten die im Zusammenhang mit benutzerdefinierten Clippingplanes genutzt werden abgelegt werden. Wichtig ist, das gl_ClipVertex im selben Koordinatenraum wie die Clippingplane definiert ist.&lt;br /&gt;
&lt;br /&gt;
==Attribute im Vertex Shader==&lt;br /&gt;
&lt;br /&gt;
Folgende Attribute stehen nur im Vertex Shader zur Verfügung und '''können nur gelesen werden''' :&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_Color&lt;br /&gt;
: Farbwert des Vertex.&lt;br /&gt;
* vec4 gl_SecondaryColor&lt;br /&gt;
:Sekundärer Farbwert des Vertex.&lt;br /&gt;
* vec4 gl_Normal&lt;br /&gt;
:Normale des Vertex.&lt;br /&gt;
* vec4 gl_Vertex&lt;br /&gt;
:Koordinaten des Vertex;&lt;br /&gt;
* vec4 gl_MultiTexCoord0..7&lt;br /&gt;
:Texturkoordinaten auf Textureinheit 0..7.&lt;br /&gt;
* float gl_FogCoord&lt;br /&gt;
:Nebelkoordinate des Vertex. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Variablen im Fragment Shader==&lt;br /&gt;
&lt;br /&gt;
Im Fragment Shader sind folgende Variablen exklusiv nutzbar :&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_FragColor&lt;br /&gt;
: Speichert den Farbwert des Fragmentes, der von folgenden Funktionen der festen Pipeline genutzt wird. Wird dieser Variable nichts zugewiesen, so ist ihr Inhalt undefiniert und darauf aufbauende Ergebnisse ebenfalls.&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_FragData[0..15]&lt;br /&gt;
: Ersetzt gl_FragColor bei der Verwendung von multiplen Rendertargets. &lt;br /&gt;
&lt;br /&gt;
* float gl_FragDepth&lt;br /&gt;
: Durch schreiben dieser Variable kann man den von der festen Funktionspipeline ermittelten Tiefenwert überspringen, der mit {{INLINE_CODE|gl_FragCoord.z}} ausgelesen werden kann. Wird dieser Wert nicht geschrieben, nutzen folgende Funktionen der Pipeline den vorher fest berechneten Wert.&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_FragCoord    nur lesen&lt;br /&gt;
: In dieser Variable ist die Position des Fragmentes relativ zur Fensterposition im Format x,y,z,1/w abgelegt, wobei z den von der festen Funktionspipeline berechneten Tiefenwert enthält.&lt;br /&gt;
&lt;br /&gt;
* bool gl_FrontFacing    nur lesen&lt;br /&gt;
: Gibt an ob das Fragment zu einer nach vorne zeigenden Primitive gehört (=true). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Bezug auf {{INLINE_CODE|gl_FragColor}} und {{INLINE_CODE|gl_FragDepth}} sei noch anzumerken das diese ''nicht'' in den Wertebereich 0..1 gebracht werden müssen, da dies später durch die feste Funktionspipeline automatisch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
==Eingebaute Varyings==&lt;br /&gt;
&lt;br /&gt;
Wie bereits in Kapitel 4.2 erwähnt, stellen Varyings eine Schnittstelle zwischen dem Vertex und dem Fragment Shader dar. Sie werden im Vertex Shader geschrieben und können dann im Fragment Shader ausgelesen werden, ohne das die folgenden Varyings dafür explizit deklariert werden müssen :&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_FrontColor&lt;br /&gt;
: Farbe der Vorderseite des Vertex.&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_BackColor&lt;br /&gt;
: Farbe der Rückseite des Vertex.&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_FrontSecondaryColor&lt;br /&gt;
: Sekundäre Farbe der Vorderseite des Vertex.&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_BackSecondaryColor&lt;br /&gt;
: Sekundäre Farbe der Rückseite des Vertex.&lt;br /&gt;
&lt;br /&gt;
* vec4 gl_TexCoord[x]&lt;br /&gt;
: Texturkoordinaten des Vertex auf Textureinheit x, wobei x die von der Hardware zur Verfügung gestellte Zahl der Textureinheiten-1 nicht überschreiten darf.&lt;br /&gt;
&lt;br /&gt;
* float gl_FogFragCoord&lt;br /&gt;
: Nebelkoordinate des Fragmentes. &lt;br /&gt;
&lt;br /&gt;
Die Varyings {{INLINE_CODE|gl_FrontColor, gl_FrontSecondaryColor, gl_BackColor}} und {{INLINE_CODE|gl_BackSecondaryColor}} können im FragmentShader nur unter den Aliases gl_Color bzw. gl_SecondaryColor gelesen werden. Welcher Wert des Vertex Shaders im Fragment Shader dort eingesetzt wird ist abhängig davon ob das Fragment zu einer nach vorne oder nach hinten zeigenden Primitive gehört.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Eingebaute Konstanten==&lt;br /&gt;
Auch diverse Konstanten wurden definiert um darauf schnell im Shader zugreifen zu können. In den Klammern stehen die von einer GL-Implementation als Mindestanforderung anzubietenden Werte. Alle Konstanten sind sowohl im Vertex als auch im Fragment Shader abrufbar :&lt;br /&gt;
&lt;br /&gt;
: OpenGL 1.0/1.2 :&lt;br /&gt;
* int gl_MaxLights (8)&lt;br /&gt;
* int gl_MaxClipPlanes (6)&lt;br /&gt;
* int gl_MaxTextureUnits (2)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
: ARB_Fragment_Program :&lt;br /&gt;
* int gl_MaxTextureCoordsARB (2)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
: Vertex_Shader :&lt;br /&gt;
* int gl_MaxVertexAttributesGL2 (16)&lt;br /&gt;
* int gl_MaxVertexUniformFloatsGL2 (512)&lt;br /&gt;
* int gl_MaxVaryingFloatsGL2 (32)&lt;br /&gt;
* int gl_MaxVertexTextureUnitsGL2 (1)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
: Fragment_Shader :&lt;br /&gt;
* int gl_MaxFragmentTextureUnitsGL2 (2)&lt;br /&gt;
* int gl_MaxFragmentUniformFloatsGL2 (64)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Eingebaute Uniformvariablen==&lt;br /&gt;
&lt;br /&gt;
Um den Zugriff auf OpenGL-Staten zu vereinfachen wurden in glSlang diverse Uniformvariablen zur direkten Verwendung im Shader eingebaut. Wie gewohnt wurden auch hier sinnvolle Namen verwendet, so dass eine tiefere Erklärung unnötig sein dürfte :&lt;br /&gt;
&lt;br /&gt;
* mat4 gl_ModelViewMatrix&lt;br /&gt;
* mat4 gl_ProjectionMatrix&lt;br /&gt;
* mat4 gl_ModelViewProjectionMatrix&lt;br /&gt;
* mat3 gl_NormalMatrix&lt;br /&gt;
:{{INLINE_CODE|gl_NormalMatrix}} repräsentiert die invertierten und anschließend transponierten oberen 3x3 Werte der {{INLINE_CODE|gl_ModelViewMatrix}}.&lt;br /&gt;
* mat4 gl_TextureMatrix[gl_MaxTextureCoordsARB]&lt;br /&gt;
&lt;br /&gt;
* float gl_NormalScale&lt;br /&gt;
: Gibt den unter OpenGL festgelegten Faktor zur Skalierung der Normalen zurück.&lt;br /&gt;
&lt;br /&gt;
* struct gl_DepthRangeParameters&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct gl_DepthRangeParameters&lt;br /&gt;
{&lt;br /&gt;
 float near;&lt;br /&gt;
 float far;&lt;br /&gt;
 float diff;&lt;br /&gt;
};&lt;br /&gt;
gl_DepthRangeParameters gl_DepthRange;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
: Clippingplanes : &lt;br /&gt;
* vec4 gl_ClipPlane[gl_MaxClipPlanes]&lt;br /&gt;
  &lt;br /&gt;
*struct gl_PointParameters&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct gl_PointParameters&lt;br /&gt;
{&lt;br /&gt;
 float size;&lt;br /&gt;
 float sizeMin;&lt;br /&gt;
 float sizeMax;&lt;br /&gt;
 float fadeThresholdSize;&lt;br /&gt;
 float distanceConstantAttenuation;&lt;br /&gt;
 float distanceLinearAttenuation;&lt;br /&gt;
 float distanceQuadraticAttenuation;&lt;br /&gt;
};&lt;br /&gt;
gl_PointParameters gl_Point;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*struct gl_MaterialParameters&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct gl_MaterialParameters&lt;br /&gt;
{&lt;br /&gt;
 vec4 emission;&lt;br /&gt;
 vec4 ambient;&lt;br /&gt;
 vec4 diffuse;&lt;br /&gt;
 vec4 specular;&lt;br /&gt;
 float shininess;&lt;br /&gt;
};&lt;br /&gt;
gl_MaterialParameters gl_FrontMaterial;&lt;br /&gt;
gl_MaterialParameters gl_BackMaterial;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*struct gl_LightSourceParameters&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct gl_LightSourceParameters&lt;br /&gt;
{&lt;br /&gt;
 vec4 ambient;&lt;br /&gt;
 vec4 diffuse;&lt;br /&gt;
 vec4 specular;&lt;br /&gt;
 vec4 position;&lt;br /&gt;
 vec4 halfVector;&lt;br /&gt;
 vec3 spotDirection;&lt;br /&gt;
 float spotExponent;&lt;br /&gt;
 float spotCutoff;&lt;br /&gt;
 float spotCosCutoff;&lt;br /&gt;
 float constantAttenuation;&lt;br /&gt;
 float linearAttenuation;&lt;br /&gt;
 float quadraticAttenuation;&lt;br /&gt;
};&lt;br /&gt;
gl_LightSourceParameters gl_LightSource[gl_MaxLights];&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*struct gl_LightModelParameters&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct gl_LightModelParameters&lt;br /&gt;
{&lt;br /&gt;
 vec4 ambient;&lt;br /&gt;
};&lt;br /&gt;
gl_LightModelParameters gl_LightModel;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*struct gl_LightModelProducts&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct gl_LightModelProducts&lt;br /&gt;
{&lt;br /&gt;
 vec4 sceneColor;&lt;br /&gt;
};&lt;br /&gt;
gl_LightModelProducts gl_FrontLightModelProduct;&lt;br /&gt;
gl_LightModelProducts gl_BackLightModelProduct;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*struct gl_LightProducts&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct gl_LightProducts&lt;br /&gt;
{&lt;br /&gt;
 vec4 ambient;&lt;br /&gt;
 vec4 diffuse;&lt;br /&gt;
 vec4 specular;&lt;br /&gt;
};&lt;br /&gt;
gl_LightProducts gl_FrontLightProduct[gl_MaxLights];&lt;br /&gt;
gl_LightProducts gl_BackLightProduct[gl_MaxLights];&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* vec4 gl_TextureEnvColor[gl_MaxFragmentTextureUnitsGL2]&lt;br /&gt;
* vec4 gl_EyePlaneS[gl_MaxTextureCoordsARB]&lt;br /&gt;
* vec4 gl_EyePlaneT[gl_MaxTextureCoordsARB]&lt;br /&gt;
* vec4 gl_EyePlaneR[gl_MaxTextureCoordsARB]&lt;br /&gt;
* vec4 gl_EyePlaneQ[gl_MaxTextureCoordsARB]&lt;br /&gt;
* vec4 gl_ObjectPlaneS[gl_MaxTextureCoordsARB]&lt;br /&gt;
* vec4 gl_ObjectPlaneT[gl_MaxTextureCoordsARB]&lt;br /&gt;
* vec4 gl_ObjectPlaneR[gl_MaxTextureCoordsARB]&lt;br /&gt;
* vec4 gl_ObjectPlaneQ[gl_MaxTextureCoordsARB]&lt;br /&gt;
&lt;br /&gt;
*struct gl_FogParameters&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
struct gl_FogParameters&lt;br /&gt;
{&lt;br /&gt;
 vec4 color;&lt;br /&gt;
 float density;&lt;br /&gt;
 float start;&lt;br /&gt;
 float end;&lt;br /&gt;
 float scale;&lt;br /&gt;
};&lt;br /&gt;
gl_FogParameters gl_Fog;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Diese recht umfangreiche GL-Stateliste sollte eigentlich jeden Bedarf decken und momentan gibts kaum einen OpenGL-Status den man so nicht in einem Shader abfragen bzw. nutzen kann.&lt;br /&gt;
&lt;br /&gt;
=Eingebaute Funktionen=&lt;br /&gt;
glSlang ist mit diversen Skalar- und Vektorfunktionen ausgestattet, die teilweise (idealerweise) sogar direkt in der Hardware ausgeführt werden, weshalb einer fertigen Funktion ggü. gleichwertigen eigenen Berechnungen immer der Vorzug zu geben ist.&lt;br /&gt;
{{Hinweis| ''genType'' kann vom Type float, vec2, vec3 oder vec4 sein, ''mat'' vom Typ mat2, mat3 oder mat4.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Trigonometrie und Winkel==&lt;br /&gt;
Alle übergebenen Winkel sollten, soweit nicht anders vermerkt, in Radien angegeben werden.&lt;br /&gt;
&lt;br /&gt;
* genType radians (genType degrees)&lt;br /&gt;
: Wandelt von Grad nach Radien. &lt;br /&gt;
* genType degrees (genType radians)&lt;br /&gt;
: Wandelt von Radien nach Grad.&lt;br /&gt;
* genType sin (genType angle)&lt;br /&gt;
: Gibt den Sinus von Angle zurück, wobei Angle in Radien angegeben wird.&lt;br /&gt;
* genType cos (genType angle)&lt;br /&gt;
: Gibt den Cosinus von Angle zurück, wobei Angle in Radien angegeben wird.&lt;br /&gt;
* genType tan (genType angle)&lt;br /&gt;
: Gibt den Tangens von Angle zurück, wobei Angle in Radien angegeben wird.&lt;br /&gt;
* genType asin (genType x)&lt;br /&gt;
: Liefert den Arcsinus von x zurück, also den Winkel dessen Sinus x ergeben würde.&lt;br /&gt;
* genType acos (genType x)&lt;br /&gt;
: Liefert den Arccosinus von x zurück, also den Winkel dessen Cosinus x ergeben würde.&lt;br /&gt;
* genType atan (genType y, genType x)&lt;br /&gt;
: Liefert den Winkel zurück, dessen Tangens x/y ergeben würde.&lt;br /&gt;
* genType atan (genType y_over_x)&lt;br /&gt;
: Liefert den Winkel zurück, dessen Tangens x über y ergeben würde.&lt;br /&gt;
&lt;br /&gt;
==Exponentiell==&lt;br /&gt;
* genType pow (genType x, genType y)&lt;br /&gt;
: Gibt x hoch y zurück.&lt;br /&gt;
* genType exp2 (genType x)&lt;br /&gt;
: Gibt 2 hoch x zurück.&lt;br /&gt;
* genType log2 (genType x)&lt;br /&gt;
: Gibt den Logarithmus zur Basis 2 von x zurück.&lt;br /&gt;
* genType sqrt (genType x)&lt;br /&gt;
: Gibt die Wurzel von x zurück.&lt;br /&gt;
* genType inversesqrt (genType x)&lt;br /&gt;
: Gibt die umgekehrte Wurzel von x zurück. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Standardfunktionen==&lt;br /&gt;
* genType abs (genType x)&lt;br /&gt;
: Liefert den absoluten Wert von x zurück.&lt;br /&gt;
* genType sign (genType x)&lt;br /&gt;
: Gibt -1.0 zurück, wenn x &amp;lt; 0.0, 0.0 wenn x = 0.0 und 1.0 wenn x &amp;gt; 0.0.&lt;br /&gt;
* genType floor (genType x)&lt;br /&gt;
: Gibt denn nächsten Integerwert zurück, der kleiner oder gleich x ist.&lt;br /&gt;
* genType ceil (genType x)&lt;br /&gt;
: Gibt den nächsten Integerwert zurück, der größer oder gleich x ist.&lt;br /&gt;
* genType fract (genType x)&lt;br /&gt;
: Gibt den Nachkommateil von x zurück.&lt;br /&gt;
* genType mod (genType x, float y) &lt;br /&gt;
* genType mod (genType x, genType y)&lt;br /&gt;
: Gibt den Modulus zurück. (=x-y * floor(x/y)) &lt;br /&gt;
* genType min (genType x, genType y) &lt;br /&gt;
* genType min (genType x, float y)&lt;br /&gt;
: Liefert y zurück wenn y &amp;lt; x, ansonsten x. &lt;br /&gt;
* genType max (genType x, genType y) &lt;br /&gt;
* genType max (genType x, float y)&lt;br /&gt;
: Liefert y zurück wenn x &amp;lt; y, ansonsten x. &lt;br /&gt;
* genType clamp (genType x, genType minVal, genType maxVal) &lt;br /&gt;
* genType clamp (genType x, float minVal, float maxVal)&lt;br /&gt;
: Zwängt x in den Bereich minVal..maxVal. &lt;br /&gt;
* genType mix (genType x, genType y, genType a)&lt;br /&gt;
* genType mix (genType x, genType y, float a)&lt;br /&gt;
: Liefert den linearen Blend zwischen x und y zurück. (= x * (1-a) + y * a) &lt;br /&gt;
* genType step (genType edge, genType x)&lt;br /&gt;
* genType step (float edge, genType x)&lt;br /&gt;
: Liefert 0.0 zurück, wenn x &amp;lt;= edge, ansonsten 1.0. &lt;br /&gt;
* genType smoothstep (genType edge0, genType edge1, genType x)&lt;br /&gt;
* genType smoothstep (float edge0, float edge1, genType x)&lt;br /&gt;
: Liefert 0.0 zurück, wenn x &amp;lt;= edge und 1.0 wenn x &amp;gt;= edge. Dabei wird eine weiche Hermite Interpolation zwischen 0 und 1 durchgeführt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Geometrie==&lt;br /&gt;
* float length (genType x)&lt;br /&gt;
: Gibt die Länge des Vektors x (= sqrt(x[0]² + x[1]² + ... + x[n]²) zurück. &lt;br /&gt;
* float distance (genType p0, genType p1)&lt;br /&gt;
: Gibt die Distanz zwischen den zwei Vektoren p0 un p1 (= length(p0-p1)) zurück. &lt;br /&gt;
* float dot (genType x, genType y)&lt;br /&gt;
: Gibt das Punktprodukt von x und y zurück (=x[0]*y[0] + x[1]*y[1] + ... + x[n]*y[n]). &lt;br /&gt;
* vec3 cross (vec3 x, vec3 y)&lt;br /&gt;
: Gibt das Kreuzprodukt von x und y zurück. &lt;br /&gt;
* genType normalize (genType x)&lt;br /&gt;
: Normalisiert den Vektor x auf die Länge 1. &lt;br /&gt;
* vec4 ftransform()&lt;br /&gt;
: Nur im Vertex Shader. Die Funktion stellt sicher, das das eingehende Vertex haargenau so transformiert wird wie in der festen Funktionspipeline. gl_Position = ftransform() wird dann also gebraucht, wenn in mehreren Durchgängen sowohl im Shader als auch in der festen Pipeline gerendert wird, um sicherzustellen das in beiden Fällen die gleiche Vertexposition herauskommt. &lt;br /&gt;
* genType faceforward (genType N, genType I, genType Nref)&lt;br /&gt;
: Gibt einen nach vorne zeigenden Vektor N zurück. (If dot(NRef, I) &amp;lt; 0 return N else return -N) &lt;br /&gt;
* genType reflect (genType I, genType N)&lt;br /&gt;
: Gibt den an der Flächenausrichtung N reflektierten Vektor I zurück. (=I-2 * dot(N,I) * N) &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Matrixfunktionen==&lt;br /&gt;
* mat matrixCompMult (mat x, mat y)&lt;br /&gt;
: Multipliziert Matrix X mit Matrix Y komponentenweise. Um eine normale lineare Matrixmultiplikation durchzuführen, sollte der &amp;quot;*&amp;quot;-Operator genutzt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Vektorvergleiche==&lt;br /&gt;
Die meisten Vektorvergleichsfunktionen liefern als Ergebnis einen boolvektor zurück, da die Vergleiche per Komponente stattfinden. Wenn man also x = vec4(1.0, 3.0, 0.0, 0.0) mit y = vec4(2.0, 1.5, 1.5, 0.0) via lessThan(x, y) vergleicht, erhält man als Ergebnis bvec(true, false, true, false).&lt;br /&gt;
&lt;br /&gt;
* bvec lessThan (vec x, vec y)&lt;br /&gt;
* bvec lessThan (ivec x, ivec y)&lt;br /&gt;
: Gibt den komponentenweisen Vergleich x &amp;lt; y zurück. &lt;br /&gt;
* bvec lessThanEqual (vec x, vec y)&lt;br /&gt;
* bvec lessThanEqual (ivec x, ivec y)&lt;br /&gt;
: Gibt den komponentenweisen Vergleich x &amp;lt;= y zurück. &lt;br /&gt;
* bvec greaterThan (vec x, vec y)&lt;br /&gt;
* bvec greaterThan (ivec x, ivec y)&lt;br /&gt;
: Gibt den komponentenweisen Vergleich x &amp;gt; y zurück. &lt;br /&gt;
* bvec greaterThanEqual (vec x, vec y)&lt;br /&gt;
* bvec greaterThanEqual (ivec x, ivec y)&lt;br /&gt;
: Gibt den komponentenweisen Vergleich x &amp;gt;= y zurück. &lt;br /&gt;
* bvec equal (vec x, vec y)&lt;br /&gt;
* bvec equal (ivec x, ivec y)&lt;br /&gt;
* bvec equal (bvec x, bvec y)&lt;br /&gt;
: Gibt den komponentenweisen Vergleich x == y zurück. &lt;br /&gt;
* bvec notEqual (vec x, vec y)&lt;br /&gt;
* bvec notEqual (ivec x, ivec y)&lt;br /&gt;
* bvec notEqual (bvec x, bvec y)&lt;br /&gt;
: Gibt den komponentenweisen Vergleich x != y zurück. &lt;br /&gt;
* bool any (bvec x)&lt;br /&gt;
: Liefert true zurück, wenn mindestens eine der Komponenten von x true ist.&lt;br /&gt;
* bool all (bvec x)&lt;br /&gt;
: Liefert true zurück, wenn alle Komponenten von x true sind. &lt;br /&gt;
* bvec not (bvec x)&lt;br /&gt;
: Liefert die logische Negation von x zurück. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Texturenzugriffe==&lt;br /&gt;
&lt;br /&gt;
Diese wichtige Funktionskategorie dient dazu, Werte aus einer an eine Textureinheit gebundenen Textur zu ermitteln. Die Texturenzugriffe können sowohl im Vertex (!) als auch im Fragment Shader ausgeführt werden, wobei der optionale Parameter bias im Vertex Shader ignoriert wird. Allerdings gibt es zusätzlich Funktionen die auf &amp;quot;Lod&amp;quot; enden und nur im Vertex Shader genutzt werden dürfen um eben dieses Manko zu umgehen. Funktionen mit dem Suffix &amp;quot;Proj&amp;quot; geben einen projizierten Texturenwert zurück.&lt;br /&gt;
&lt;br /&gt;
: '''1D-Texturen :'''&lt;br /&gt;
* vec4 texture1D (sampler1D sampler, float coord [, float bias])&lt;br /&gt;
* vec4 texture1DProj (sampler1D sampler, vec2 coord [, float bias])&lt;br /&gt;
* vec4 texture1DProj (sampler1D sampler, vec4 coord [, float bias])&lt;br /&gt;
: Nur im Vertex Shader :&lt;br /&gt;
* vec4 texture1DLod (sampler1D sampler, float coord, float lod)&lt;br /&gt;
* vec4 texture1DProjLod (sampler1D sampler, vec2 coord, float lod)&lt;br /&gt;
* vec4 texture1DProjLod (sampler1D sampler, vec4 coord, float lod)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
: '''2D-Texturen :'''&lt;br /&gt;
* vec4 texture2D (sampler2D sampler, vec2 coord [, float bias])&lt;br /&gt;
* vec4 texture2DProj (sampler2D sampler, vec3 coord [, float bias])&lt;br /&gt;
* vec4 texture2DProj (sampler2D sampler, vec4 coord [, float bias])&lt;br /&gt;
: Nur im Vertex Shader : &lt;br /&gt;
* vec4 texture2DLod (sampler2D sampler, vec2 coord, float lod)&lt;br /&gt;
* vec4 texture2DProjLod (sampler2D sampler, vec3 coord, float lod)&lt;br /&gt;
* vec4 texture2DProjLod (sampler2D sampler, vec4 coord, float lod)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
: '''3D-Texturen :'''&lt;br /&gt;
* vec4 texture3D (sampler3D sampler, vec3 coord [, float bias])&lt;br /&gt;
* vec4 texture3DProj (sampler3D sampler, vec4 coord [, float bias])&lt;br /&gt;
: Nur im Vertex Shader : &lt;br /&gt;
* vec4 texture3DLod (sampler3D sampler, vec3 coord, float lod)&lt;br /&gt;
* vec4 texture3DProjLod (sampler3D sampler, vec4 coord, float lod)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
: '''Cubemap :'''&lt;br /&gt;
* vec4 textureCube (samplerCube sampler, vec3 coord [, float bias])&lt;br /&gt;
: Nur im Vertex Shader : &lt;br /&gt;
*vec4 textureCubeLod (samplerCube sampler, vec3 coord, float lod)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
: '''Tiefentextur (Shadowmap) :'''&lt;br /&gt;
* vec4 shadow1D (sampler1DShadow sampler, vec3 coord [, float bias])&lt;br /&gt;
* vec4 shadow2D (sampler2DShadow sampler, vec3 coord [, float bias])&lt;br /&gt;
* vec4 shadow1DProj (sampler1DShadow sampler, vec4 coord [, float bias])&lt;br /&gt;
* vec4 shadow2DProj (sampler2DShadow sampler, vec4 coord [, float bias])&lt;br /&gt;
: Nur im Vertex Shader :&lt;br /&gt;
* vec4 shadow1DLod (sampler1DShadow sampler, vec3 coord, float lod)&lt;br /&gt;
* vec4 shadow2DLod (sampler2DShadow sampler, vec3 coord, float lod)&lt;br /&gt;
* vec4 shadow1DProjLod (sampler1DShadow sampler, vec4 coord, float lod)&lt;br /&gt;
* vec4 shadow2DProjLod (sampler2DShadow sampler, vec4 coord, float lod)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wie bereits eingangs gesagt ist dieses Kapitel ein sehr wichtiges, denn eine 3D-Szene ohne Texturen ist heute kaum denkbar. Darüber hinaus lassen sich durch Texturenzugriffe recht viele interessante Sachen machen, z.B. ein einfacher Blurfilter oder das freie überblenden bestimmter Texturenteile. Deshalb führe ich hier kurz ein paar Beispiele an, welche die Nutzung dieser Funktionen verdeutlichen sollen :&lt;br /&gt;
&lt;br /&gt;
===Beispiel A=== &lt;br /&gt;
Eine Textur gebunden die einfach ausgegeben werden soll&lt;br /&gt;
&lt;br /&gt;
''Im Vertex Shader'' :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
 gl_Position     = gl_ModelViewProjectionMatrix * gl_Vertex;&lt;br /&gt;
 gl_TexCoord[0]  = gl_MultiTexCoord0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
Der Vertex Shader ist recht minimal. Neben der homogenen Vertexposition leiten wir hier nur die im OpenGL-Programm angegebenen Texturkoordinaten weiter. ''Dies ist aber unbedingt nötig!'' Ohne die letzte Zeile hätten wir im Fragment Shader keine gültigen Texturkoordinaten auf TMU0, was in einer Fehldarstellung enden würde.&lt;br /&gt;
&lt;br /&gt;
''im Fragment Shader'' :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
uniform sampler2D texSampler;&lt;br /&gt;
&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
 gl_FragColor = texture2D(texSampler, vec2(gl_TexCoord[0]));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Zuerst deklarieren wir hier einen 2D-Texturensampler, wichtig : '''Texturensampler müssen IMMER als uniform deklariert werden!''' In der Hauptfunktion weisen wir dann einfach den über die Funktion texture2D aus unserer gebundenen Textur ausgelesenen Farbwert, anhand der vom Vertex Shader übergebenen Texturkoordinaten, zu.&lt;br /&gt;
&lt;br /&gt;
===Beispiel B=== &lt;br /&gt;
Zwei Texturen, jeweils auf TMU0 und TMU1. Fragmentfarbe soll eine Multiplikation der beiden Texturen darstellen.&lt;br /&gt;
&lt;br /&gt;
In diesem Beispielfall (der recht häufig vorkommt) müssen wir im Programm festlegen, ''welcher Sampler welche Textureinheit adressiert'', genau deshalb müssen die Texturensampler auch als uniform deklariert werden. Die Standardtextureneinheit eines Samplers ist TMU0, was in unserem Falle natürlich nicht brauchbar ist. Also müssen wir unserem zweiten Textursampler im Programm mitteilen das er seine Daten aus TMU1 beziehen soll :&lt;br /&gt;
&lt;br /&gt;
 glUniform1iARB(glSlang_GetUniLoc(ProgramObject, 'texSamplerTMU1'), 1);&lt;br /&gt;
&lt;br /&gt;
Dies ist also unbedingt zu machen, sobald ein Texturensampler eine Textureinheit &amp;gt; GL_TEXTURE_0 adressieren will. Die Textureneinheit des Samplers lässt sich also nicht im Shader selbst festlegen. Der Fragment Shader ist nun allerdings schnell hergeleitet (Vertex Shader verändert sich nicht, da TMU1 die Texturkoordinaten auch von TMU0 bezieht) :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
im Fragment Shader :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
uniform sampler2D texSamplerTMU0;&lt;br /&gt;
uniform sampler2D texSamplerTMU1;&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
    gl_FragColor = texture2D(texSamplerTMU0, vec2(gl_TexCoord[0])) *&lt;br /&gt;
                   texture2D(texSamplerTMU1, vec2(gl_TexCoord[0]));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Noisefunktionen==&lt;br /&gt;
Sowohl im Vertex als auch im Fragment Shader lassen sich [[GLSL noise|Noisefunktionen]] nutzen, mit deren Hilfe sich eine gewisse &amp;quot;Zufälligkeit&amp;quot; simulieren lässt (wirklich zufällige Werte sind es natürlich nicht). Ein zurückgegebener Wert liegt dabei immer im Bereich [-1..1] und ist immer bei gleichem Eigabewert auch immer gleich. Die Verwendung empfiehlt sich derzeit allerdings eher nicht, da nicht alle aktuellen Treiber die Funktionen unterstützen und eine Noisetextur wahrscheinlich performanter ist.&lt;br /&gt;
&lt;br /&gt;
* float noise1 (genType x)&lt;br /&gt;
* vec2 noise2 (genType x)&lt;br /&gt;
* vec3 noise3 (genType x)&lt;br /&gt;
* vec4 noise4 (genType x)&lt;br /&gt;
&lt;br /&gt;
==Discard==&lt;br /&gt;
Eigentlich keine Funktion, sondern eine Abbruchbedingung '''nur im Fragment Shader'''. Das Schlüsselwort {{INLINE_CODE|discard}} verwirft das aktuell bearbeitete Fragment und beendet gleichzeitig den Shader. Es kann z.B. genutzt werden um Alphamasking manuell durchzuführen.&lt;br /&gt;
Man sollte dabei jedoch beachten dass ein Großteil der aktuellen Hardware kein &amp;quot;early-out&amp;quot; (frühes Beenden) im Fragmentshader unterstützt. Wenn dort also ein {{INLINE_CODE|discard}} auftaucht, wird trotzdem auch der Code danach ausgeführt und einfach verworfen. Einen Geschwindigkeitsvorteil durch diesen Befehl wird man also erst auf neueren Karten feststellen, die dieses Faeature auch so unterstützen wie es angedacht war. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Beispielshader=&lt;br /&gt;
Wen bis hierhin nicht der Mut verlassen hat, und wer aufmerksam gelesen hat, dürfte jetzt also zumindest in der Lage sein kleinere Shader in glSlang zu schreiben und diese auch im Programm zu nutzen. Ich habe im Themenbereich &amp;quot;glSlang&amp;quot; versucht alle Bereiche der Shadersprache selbst anzusprechen und hoffe das auch brauchbar rübergebracht zu haben. Um oben erlerntes (hoffe ich doch mal) nochmal zu vertiefen werde ich jetzt (wie ich das bereits bei meinem ARB_VP-Tutorial getan habe) einen simplen Beispielshader (Vertex und Fragment Shader) auseinanderpflücken um so u.a. auch die Programmstruktur für alle die in C nicht so bewandert sind zu erörtern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Der Vertex Shader==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
uniform vec4 GlobalColor;&lt;br /&gt;
&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
 gl_Position     = gl_ModelViewProjectionMatrix * gl_Vertex;&lt;br /&gt;
 gl_FrontColor   = gl_Color * GlobalColor;&lt;br /&gt;
 gl_TexCoord[0]  = gl_MultiTexCoord0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wie gesagt recht simpel. Angefangen wird mit der Deklaration einer globalen Uniformvariable namens {{INLINE_CODE|GlobalColor}}. Wie wir uns erinnern gibt der Typenqualifizierer uniform an, das wir den Wert dieser Variable (ein 4-Komponentenvektor, da Farbwerte aus R,G,B und A bestehen) in unserem Programm an den Shader übermitteln.&lt;br /&gt;
&lt;br /&gt;
Danach gehts ohne Umwege direkt in unsere Hauptfunktion, da wir im Vertex Shader keine anderen Funktionen benötigen. Dort berechnen wir zuerst die homogene Position unseres Vertex, die sich aus der eingehenden Vertexposition multipliziert mit der Modelansichtsmatrix ergibt. Wie schonmal gesagt '''muss diesem Wert etwas zugewiesen werden''', da sonst alle darauf aufbauenden Funktionen unvorhersehbare Ergebnisse liefern.&lt;br /&gt;
Ausserdem wollen wir die Frontfarbe unseres Vertex jedesmal mit der im Programm übergebenen GlobalColor multiplizieren, so dass wir den Farbwert der gesamten Szene aus unserem Programm heraus manipulieren können. Zu guterletzt geben wir dann noch unsere aus der festen Funktionspipeline erhaltenen Texturkoordinaten auf Textureinheit 0 weiter. Wenn im Fragmentshader Texturkoordinaten verwendet werden, '''muss das getan werden'''. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Der Fragment Shader==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
uniform sampler2D Texture0;&lt;br /&gt;
uniform sampler2D Texture1;&lt;br /&gt;
uniform sampler2D Texture2;&lt;br /&gt;
uniform sampler2D Texture3;&lt;br /&gt;
&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
 vec2 TexCoord = vec2( gl_TexCoord[0] );&lt;br /&gt;
 vec4 RGB      = texture2D( Texture0, TexCoord );&lt;br /&gt;
&lt;br /&gt;
 gl_FragColor  = texture2D(Texture1, TexCoord) * RGB.r +&lt;br /&gt;
                 texture2D(Texture2, TexCoord) * RGB.g +&lt;br /&gt;
                 texture2D(Texture3, TexCoord) * RGB.b;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auch hier passiert nicht wirklich viel Großartiges. Wir deklarieren beim Shaderanfang zuerst vier Texturensampler, da wir insgesamt vier verschiedene Texturen im Shader auslesen wollen, eine Verlaufstextur und drei Oberflächentexturen. Auch hier sei wieder gesagt das man Sampler '''immer als uniform deklarieren muss'''. In der Hauptfunktion deklarieren wir dann einen Farbvektor, der auch direkt einen Farbwert aus Textureinheit 0 zugewiesen bekommt. Auf Textureinheit 0 haben wir ihm Hauptprogramm eine Verlaufstextur gebunden, die angibt wie die drei folgenden Texturen ineinander geblendet werden.&lt;br /&gt;
Danach schreiben wir dann den Farbwert des Fragmentes, der '''im Fragment Shader ausgegeben werden muss'''. Der besteht wie einfach zu erkennen aus Farbwert von Textureinheit 1 * Rotwert von Textureinheit 0 + Farbwert von Textureinheit 2 * Grünwert von Textureinheit 0 + Farbwert von Textureinheit 3 * Blauwert von Textureinheit 0. So ist z.B. an Stellen an denen in der Verlaufstextur reines blau liegt nur die dritte Textur sichtbar.&lt;br /&gt;
&lt;br /&gt;
So viel also zu unserem kleinen Beispielshader. Er ist weder besonders toll noch besonders sinnvoll, sollte aber auch eher dazu dienen euch glSlang ein wenig zu veranschaulichen, was mir hoffentlich gelungen ist.&lt;br /&gt;
&lt;br /&gt;
Wenn ihr in den vorangegangenen Kapiteln zumindest ein wenig aufgepasst habt, dann könnt ihr euch vor eurem inneren Auge hoffentlich vortstellen was der Shader macht : Er blendet drei Texturen weich anhand der Verlaufstextur ineinander über. Sowas kann man z.B. für ein Terrain nutzen, um dieses anhand einer Farbtextur zu texturieren. Für alle, die damit Probleme haben hier zwei Bilder die den Shader veranschaulichen. Links die Verlaufstextur, die angibt wo welche Textur wie stark gewichtet wird und rechts dann das Ergebnis :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt; [[BILD:GLSL_sample_shader_a.jpg]] [[BILD:GLSL_sample_shader_b.jpg]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Post Mortem=&lt;br /&gt;
Das wars also, meine &amp;quot;Einführung&amp;quot; in die OpenGL Shader Sprache. Ich hoffe es hat euch nicht gelangweilt und auch die von mir zur Verfügung gestellten Informationen haben euch hoffentlich ausgereicht. Mit der Veröffentlichung dieser Einführung geht übrigens auch die Eröffnung eines Shaderforums hier auf der DGL einher, in der ihr dann also fleissig Fragen zum Thema stellen oder eure Shader präsentieren könnt. In diesem Post Mortem gehe ich jetzt noch kurz auf die Zukunft von glSlang ein und zeige ein paar Screenshots (damit die Augen entspannen können), bevor ihr euch dann selbst in die Shaderwelt stürzen könnt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Beispiele=&lt;br /&gt;
&lt;br /&gt;
Anbei ein paar exemplarische Screenshots. Da man mit GLSL aber alle möglichen Effekte berechnen kann (u.a. auch 1:1 die feste Funktionspipeline) ist es hier unmöglich einen Überblick aller möglichen Techniken zu geben.&lt;br /&gt;
&lt;br /&gt;
[[Datei:tut_glsl_eigenershader_01.png]] [[Datei:tut_glsl_eigenershader_02.png]] [[Datei:tut_glsl_eigenershader_03.png]]&lt;br /&gt;
&lt;br /&gt;
Wie im ersten (und dritten) Screenshot zu sehen ist es natürlich auch möglich mehrere Techniken innerhalb einer Szene zu nutzen. Hier sind letztendlich bis auf Hardwarelimitationen keine Grenzen gesetzt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Die Zukunft=&lt;br /&gt;
Als dieses Tutorial geschrieben wurde, war noch nicht ganz abzusehen dass bzw. ob sich GLSL auch durchsetzen würde. ARB-Shadr und NVidias cG waren damals die Platzhirsche, aber inzwischen werden ARB-Shader nicht mehr genutzt (und auch schon länger nicht mehr weiterentwickelt) und auch NVidia setzt primär auf GLSL. GLSL wird permanent weiterenwtickelt und Hersteller können dank des flexiblen Extensionsystems auch in GLSL eigene Extensions offenlegen um die aktuellsten Features (wie z.b. den Tesselator auf aktuellen ATI-Karten) nutzen zu können. GLSL it als inzwischen auch offizielle die Shadersprache frü OpenGL und wird permanent an die neusten technischen Entwicklungen im Grafikkartenbereich angepasst.&lt;br /&gt;
&lt;br /&gt;
Wer also unter OpenGL etwas mit Shadern machen möchte, kommt an GLSL nicht vorbei!&lt;br /&gt;
&lt;br /&gt;
Also viel Spaß beim Experimentieren und Shaderschreiben! Und nicht vergessen : Wir wollen sehen was ihr so treibt,&lt;br /&gt;
&lt;br /&gt;
Euer&lt;br /&gt;
:Sascha Willems&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{TUTORIAL_NAVIGATION|-|[[Tutorial_glsl2]]}}&lt;br /&gt;
[[Kategorie:Tutorial|GLSL]]&lt;/div&gt;</summary>
		<author><name>Phlegmatiker</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Feste_Funktionspipeline&amp;diff=25264</id>
		<title>Feste Funktionspipeline</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Feste_Funktionspipeline&amp;diff=25264"/>
				<updated>2011-07-15T20:31:53Z</updated>
		
		<summary type="html">&lt;p&gt;Phlegmatiker: Rechtschreibfehler korrigiert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Unvollständig|Es Fehlt Matrix Kontrolle, Feedback, Eingabe Konvertierung, Lighting und Texture Koordinaten generierung. }}&lt;br /&gt;
&lt;br /&gt;
Fixe Funktionspipeline für OpenGL 1.1&lt;br /&gt;
&lt;br /&gt;
= Vertex Pipeline =&lt;br /&gt;
[[Bild:VertexPipeline.GIF|framed|right|Die Vertexpipeline]]&lt;br /&gt;
&lt;br /&gt;
== Eingabe Konvertierung ==&lt;br /&gt;
Hier erhält die [[Vertex]] Pipeline durch entsprechende Konvertierung(en) eine standardisierte Form eines [[Vertex|Vertices]].&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch: [[glVertex]], [[glVertexPointer]], [[glArrayElement]]&lt;br /&gt;
&lt;br /&gt;
== [[Modelview]] Muliplikation ==&lt;br /&gt;
Der [[Vertex]] wird mit der im [[Modelview]] [[Matrix]] [[Stack]] oben aufliegenden Matrix multipliziert.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch: [[glMatrixMode]], [[glPushMatrix]], [[glPopMatrix]], [[glTranslate]], [[glScale]], [[glRotate]], [[glMultMatrix]], [[glLoadMatrix]], [[glLoadIdentity]]&lt;br /&gt;
&lt;br /&gt;
== [[Primitive]] erstellen ==&lt;br /&gt;
Hier werden die Eingabedaten über die Art des [[Primitiv|Primitives]] gegebenenfalls konvertiert und weiter gereicht.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch: [[glBegin]], [[glEnd]], [[glDrawElements]], [[glDrawArrays]]&lt;br /&gt;
&lt;br /&gt;
== [[Flat Shading]] ==&lt;br /&gt;
Gegebenenfalls wird der bereits berechnete Farbwert für das Flat Shading für alle Punkte des [[Primitiv|Primitives]] gleich gesetzt.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch: [[glShadeModel]]&lt;br /&gt;
&lt;br /&gt;
== Benutzerdefinierte [[Clipping Plane|Clipping Planes]] ==&lt;br /&gt;
Hier werden gegebenenfalls die [[Primitiv|Primitive]] an benutzerdefinierten Ebenen abgeschnitten, weiter gereicht oder komplett verworfen.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch: [[glClipPlane]]&lt;br /&gt;
&lt;br /&gt;
== Projection Multiplikation ==&lt;br /&gt;
Hier werden die [[Vertex|Vertices]] mit der am [[Projection]] [[Matrix]] Stack oben aufliegenden [[Matrix]] multipliziert.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch [[glOrtho]], [[glFrustum]], [[gluPerspective]], [[glMatrixMode]]&lt;br /&gt;
&lt;br /&gt;
== [[Kamera]] Clipping ==&lt;br /&gt;
Das clippen am [[Kamera]] Sichtkörper&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch: [[Clipping Plane]]&lt;br /&gt;
&lt;br /&gt;
== Division durch w ==&lt;br /&gt;
Hier werden x, y und z Koordinaten des [[Vertex|Vertices]] durch die w Koordinate dividiert. In diesem Schritt erfolgt bei der perspektivischen Projektion die eigentliche Projektion auf den Bildschirm (oder andere Ausgabemedien).&lt;br /&gt;
&lt;br /&gt;
== Viewport Multiplikation ==&lt;br /&gt;
Hier wird der x und y Teil des [[Vertex]] mit der [[Viewport]] [[Matrix]] multipliziert. Das Ergebnis sind die Pixelcoordinaten des [[Vertex]].&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch: [[glViewport]]&lt;br /&gt;
&lt;br /&gt;
== Z Anpassung ==&lt;br /&gt;
Hier wird der zuerst im Bereich [-1|1] liegende z Teil des [[Vertex]] auf den für den [[Tiefenpuffer|Z Buffer]] benötigten Bereich [0|1] gescaled.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch: [[glDepthRange]]&lt;br /&gt;
&lt;br /&gt;
== [[Polygon]] [[Backface Culling|Culling]] ==&lt;br /&gt;
Das [[Backface Culling|Front- bzw. Backface Culling]] findet hier statt.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch [[glFrontFace]], [[glCullFace]]&lt;br /&gt;
&lt;br /&gt;
== [[Polygon]] mode ==&lt;br /&gt;
Gegebenenfalls wird hier 1 3eck in 3 Linien oder 3 Punkte zerlegt. Das typische Wireframe kommt häufig hier zustande.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch: [[glPolygonMode]]&lt;br /&gt;
&lt;br /&gt;
== Rasterizer ==&lt;br /&gt;
Hier werden aus dem Primitiv die Fragmente berechnet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Fragment Pipeline =&lt;br /&gt;
[[Bild:FragmentPipeline.png|framed|right|Die Fragmentpipeline]]&lt;br /&gt;
&lt;br /&gt;
== Rasterizer ==&lt;br /&gt;
Die Aufgabe des Rasterizers ist es, aus 2 dimensionalen Primitiven die durch 1, 2 oder 3 [[Vertex|Vertices]] gegeben sind die Pixel zu berechnen die gezeichnet werden sollen. Jedes Pixel das gezeichnet werden soll wird weiter durch die Fragment Pipeline geschickt wo es noch ein Reihe von Tests durchlaufen muss bis es endgültig in den Frame Buffer gelangt. Für jedes Fragment werden folgende Werte berechnet und weiter gereicht:&lt;br /&gt;
*Koordinaten innerhalb des Frame Buffers&lt;br /&gt;
*Interpolierte Tiefe (Z-Wert)&lt;br /&gt;
*Interpolierte [[Texturkoordinaten]] (gegebenenfalls auch mehrere [[Texturkoordinaten]])&lt;br /&gt;
*Interpolierter Farbwert (gegebenenfalls auch 2 Farbwerte)&lt;br /&gt;
*gegebenenfalls Deckung für [[Antialiasing]]&lt;br /&gt;
Auf moderneren Grafikkarten werden hier die erzeugten Fragmente auf mehrere Fragment Prozessoren aufgeteilt und parallel berechnet um eine höhere Füllrate zu erzielen.&lt;br /&gt;
&lt;br /&gt;
=== Punkte ===&lt;br /&gt;
Größe des Punkte wird kontrolliert durch [[glPointSize]]. Wenn Punkt antialiased (siehe auch [[glEnable]]( GL_POINT_SMOOTH ), [[Aliasing]] und [[Antialiasing]]) gezeichnet werden sollen, so wird die prozentuelle Deckung des Pixels für später berechnet und gespeichert gespeichert. Ein Antialiased Punkt ist ein Kreis, nicht antialiased Punkte werden als Quadrat dar gestellt.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch: [[glEnable]], [[glDisable]] und [[glPointSize]]&lt;br /&gt;
&lt;br /&gt;
=== Linien ===&lt;br /&gt;
Breite der Linie wird kontrolliert durch [[glLineWidth]]. [[Antialiasing]] von Linien wird durch [[glEnable]]( GL_LINE_SMOOTH ) erreicht. Ist GL_LINE_STIPPLE aktiviert, so werden hier die nicht entsprechenden Fragmente verworfen bzw. nicht erzeugt.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch: [[glEnable]], [[glDisable]], [[glLineWidth]] und glLineStipple]]&lt;br /&gt;
&lt;br /&gt;
=== 3ecke ===&lt;br /&gt;
Mit GL_POLYGON_SMOOTH kann hier das Antialiasing erreicht werden.&lt;br /&gt;
&lt;br /&gt;
{{Warnung|GL_POLYGON_SMOOTH schaltet sehr häufig in Softwaremodus um, da nicht in Hardware verfügbar. Und auch im Softwaremodus werden häufig die Edge Flags bei geclippten 3ecken nicht richtig gesetzt (siehe [[glEdgeFlag]] und [[Clipping Plane]]).}}&lt;br /&gt;
&lt;br /&gt;
Mit [[glPolygonStipple]] kann man auch hier das erzeugen von Fragmenten verhindern werden. Gegebenenfalls wird die Tiefe (Z-Wert) noch mit [[glPolygonOffset]] modifiziert.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch: [[glEnable]], [[glDisable]], [[glPolygonOffset]] und [[glPolygonStipple]]&lt;br /&gt;
&lt;br /&gt;
== [[Texel]] Generierung ==&lt;br /&gt;
Berechnung der Farbwerte der Texel. Hier werden für eine [[Trilineare Filterung]] zuerst die beiden [[Mipmap|Mipmaps]] welche verwendet werden sollen berechnet, danach werden die 8 umliegenden Texel (4 in jedem Mipmap) entsprechend interpoliert.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch: [[glGenTextures]], [[glDeleteTextures]], [[glTexImage1D]], [[glTexImage2D]], [[glTexImage3D]], [[glTexSubImage1D]], [[glTexSubImage2D]], [[glTexSubImage3D]], [[gluBuild1DMipmaps]], [[gluBuild2DMipmaps]], [[glTexParameter]], [[glEnable]], [[glDisable]] und [[glBindTexture]]&lt;br /&gt;
&lt;br /&gt;
== Texel Anwendung (Berechnung) ==&lt;br /&gt;
Ausgehend von Farbe ([[glColor]]), Texelfarbe(n) und Texturfarb konstante ([[glTexEnv]]) wird hier ein neuer Farbwert für das Fragment berechnet.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch: [[glTexEnv]], [[glColor]] und [[GL_ARB_texture_env_combine]]&lt;br /&gt;
&lt;br /&gt;
== Nebel Berechnung ==&lt;br /&gt;
Wenn GL_FOG aktiviert ist, so werden hier die Distanz basierten Nebelberechnungen so wie durch [[glFog]] definiert mit Hilfe des Z-Wertes des Fragmentes durchgeführt.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch: [[glEnable]], [[glDisable]] und [[glFog]]&lt;br /&gt;
&lt;br /&gt;
== Deckungsberechnung Antialiasing ==&lt;br /&gt;
Hier wird im RGBA Modus der Alpha Wert eines Fragmentes anhand der Deckung die durch den Rasterizer berechnet wurde modifiziert.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch: [[glEnable]]( GL_POLYGON_SMOOTH ), [[glEnable]]( GL_LINE_SMOOTH ), [[glEnable]]( GL_POINT_SMOOTH ) und [[glDisable]]&lt;br /&gt;
&lt;br /&gt;
== Pixel Besitzer Test ==&lt;br /&gt;
Prüft ob der aktuelle OpenGL Context (siehe [[wglMakeCurrent]]) im Besitz des Pixels, welches gezeichnet werden soll, ist. Ist dies nicht der Fall (Beispielsweise durch ein darüber liegendes Fenster welches das Pixel verdeckt), so wird beim Fenstersystem angefragt was zu tun ist. Eine Mögliche Reaktion ist beispielsweise das Verwerfen des Fragmentes.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch: [[wglCreateContext]], [[wglDeleteContext]], [[wglMakeCurrent]] und [[wglGetCurrentContext]]&lt;br /&gt;
&lt;br /&gt;
== Scissor Test ==&lt;br /&gt;
Wenn GL_SCISSOR_TEST aktiviert ist, so wird hier geprüft ob das Fragment innerhalb des Rechtecks liegt welches mit [[glScissor]] definiert wurde. Ist dies nicht der Fall, so wird das Fragment verworfen.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch: [[glEnable]], [[glDisable]] und [[glScissor]]&lt;br /&gt;
&lt;br /&gt;
== Alpha Test ==&lt;br /&gt;
Wenn GL_ALPHA_TEST aktiviert ist, so wird geprüft ob der Alpha Wert des Fragmentes die mit [[glAlphaFunc]] definierte Bedienung erfüllt. Wird die Bedienung nicht erfüllt, so wird das Fragment verworfen.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch: [[glEnable]], [[glDisable]] und [[glAlphaFunc]]&lt;br /&gt;
&lt;br /&gt;
== Stencil Test ==&lt;br /&gt;
Wenn GL_STENCIL_TEST aktiviert ist, so wird geprüft ob der Stencil Teil des aktuellen [[Framebuffer]] an der Fragmentposition die Bedienung, welche mit [[glStencilFunc]] angegeben wurde, erfüllt. Ist dies nicht der Fall, so wird das Fragment verworfen.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch: [[glEnable]], [[glDisable]] und [[glStencilFunc]]&lt;br /&gt;
&lt;br /&gt;
== Tiefen Test ==&lt;br /&gt;
Wenn GL_DEPTH_TEST aktiviert ist, so wird geprüft ob der Tiefen Teil des aktuellen [[Framebuffer]] an der Fragmentposition die Bedienung, welche mit [[glDepthFunc]] angegeben wurde, erfüllt. Ist dies nicht der Fall, so wird das Fragment verworfen.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch: [[glEnable]], [[glDisable]] und [[glDepthFunc]]&lt;br /&gt;
&lt;br /&gt;
== Blending ==&lt;br /&gt;
Wenn GL_BLEND aktiviert ist, so wird die Farbe des Fragmentes und die Farbe aus dem aktuellen [[Framebuffer]] an der Fragmentposition anhand der oder des Alphawertes und der mit [[glBlendFunc]] angegebenen Funktion interpoliert.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch [[glEnable]], [[glDisable]], [[glBlendFunc]] und [[GL_ARB_imaging]]&lt;br /&gt;
&lt;br /&gt;
== [[Dithering]] ==&lt;br /&gt;
For allem im Farbindex-Modus wird hier die Illusion von mehreren unterschiedlichen Farben und weiche Übergänge erzeugt. Die Bedienung für diesen Algorithmus ist allerdings, das er nur am aktuelle Fragment basiert (Beispielsweise Fensterposition und Farbwert), was die Berechnungsmöglichkeiten etwas einschränkt.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch: [[glEnable]]( GL_DITHER ), [[glDisable]], [[Antialiasing]] und [[Dithering]]&lt;br /&gt;
&lt;br /&gt;
== Logische Operationen ==&lt;br /&gt;
Hier können auf Bit-Ebene logische Operationen durchgeführt werden. Wenn im RGBA Modus GL_COLOR_LOGIC_OP aktiviert ist, so wird dafür Blending ausgeschalten.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch: [[glEnable]], [[glDisable]] und [[glLogicOp]]&lt;br /&gt;
&lt;br /&gt;
== Farb Maskierung ==&lt;br /&gt;
Hier kann mittels [[glIndexMask]], [[glColorMask]], [[glDepthMask]] und [[glStencilMask]] gesteuert werden, welche Werte in den [[Framebuffer]] geschrieben werden sollen und welche nicht. Was genau rein geschrieben wird, kann für den Stencil Buffer entweder hier oder auch schon beim Stencil Test durch [[glStencilOp]] festgelegt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe auch: [[glIndexMask]], [[glColorMask]], [[glDepthMask]], [[glStencilMask]] und [[glStencilOp]]&lt;br /&gt;
&lt;br /&gt;
== Frame Buffer Kontrolle ==&lt;br /&gt;
Dieser Teil übernimmt die Kontrolle über alle vorhandenen [[Framebuffer]]. Beispielsweise durch [[glDrawBuffer]] kann der aktuelle Frame Buffer gewechselt werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
[[SwapBuffers]] und [[glDrawBuffer]]&lt;br /&gt;
&lt;br /&gt;
[[ShaderModel]] für die Änderung an der Pipeline mit Einführung von [[Shader]]n.&lt;br /&gt;
&lt;br /&gt;
== Ressourcen ==&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[http://www.opengl.org/documentation/specs/version1.1/state.pdf OpenGL 1.1 State Machine (PDF)]&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[http://www.opengl.org/documentation/specs/version1.2/opengl1.2.1.pdf OpenGL 1.2.1 Specification (PDF)]&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;/div&gt;</summary>
		<author><name>Phlegmatiker</name></author>	</entry>

	</feed>