<?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=End</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=End"/>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php/Spezial:Beitr%C3%A4ge/End"/>
		<updated>2026-05-09T10:39:25Z</updated>
		<subtitle>Benutzerbeiträge</subtitle>
		<generator>MediaWiki 1.27.4</generator>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=glDrawElements&amp;diff=26389</id>
		<title>glDrawElements</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=glDrawElements&amp;diff=26389"/>
				<updated>2017-11-08T11:46:19Z</updated>
		
		<summary type="html">&lt;p&gt;End: /* Parameter */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= glDrawElements =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Name ==&lt;br /&gt;
'''glDrawElements''' - Rendert Primitiven aus einem Datenarray heraus.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Delphi-Spezifikation ==&lt;br /&gt;
 procedure '''glDrawElements'''(''mode'' : glEnum; ''count'' : glSizei; ''_type'' : glEnum;&lt;br /&gt;
                          '''const''' ''indices'' : PGLvoid); &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
! ''mode''&lt;br /&gt;
| Gibt an welcher [[Primitiv]]en-Type gerendert werden soll. Hier sind die symbolische Konstanten '''GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_TRIANGLES, GL_QUAD_STRIP, GL_QUADS''' und '''GL_POLYGON''' erlaubt.&lt;br /&gt;
|-&lt;br /&gt;
! ''count''&lt;br /&gt;
| Anzahl der zu rendernden Elemente.&lt;br /&gt;
|-&lt;br /&gt;
! ''type''&lt;br /&gt;
| Gibt den Typ der Werte in ''indices'' an. Muss entweder '''GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT''' oder '''GL_UNSIGNED_INT''' sein.&lt;br /&gt;
|-&lt;br /&gt;
! ''indices''&lt;br /&gt;
| Zeiger hinter dem die Indizes hinterlegt sind. Wird ein Buffer Object verwendet, gibt dieser Parameter das Offset im Buffer in Bytes an.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Beschreibung == &lt;br /&gt;
'''glDrawElements''' beschreibt mehrere geometrische Primitiven mit nur sehr wenigen Unteraufrufen. Anstatt also für einzelne [[Eckpunkt]]e, [[Normalen]], [[Texturkoordinate]]n, Kantenflags oder Farbwerte einen eigenen GL-Befehl aufzurufen, kann man hier für Eckpunkte, Normalen, usw. eigene Arrays angeben und nutzen, um mit '''glDrawElements''' eine Sequenz von Primitiven mit nur einem Befehl zu rendern.&lt;br /&gt;
&lt;br /&gt;
Wenn '''glDrawElements''' aufgerufen wird, nimmt es ''count'' Elemente aus den aktivierten Arrays, deren Positionen in ''indices'' gespeichert sind, um eine Abfolge geometrischer [[Primitive]]n zu erstellen. ''mode'' gibt dabei an, welche Art von [[Primitive]] konstruiert werden soll und wie diese Arrayelemente [[Primitive]]n darstellen. Wenn mehr als ein Array aktiviert wurde, werden diese auch genutzt (Vertexarray, Normalenarray, Farbarray, Texturkoordinatenarray, etc.) Wenn '''GL_VERTEX_ARRAY''' nicht aktiviert ist, werden allerdings keine geometrischen [[Primitive]]n erstellt.&lt;br /&gt;
&lt;br /&gt;
Vertexattribute, die durch '''glDrawElements''' verändert werden, haben nach dem Rücksprung von '''glDrawElements''' undefinierte Werte. Wenn z.B. '''GL_COLOR_ARRAY''' aktiviert wurde, ist der aktuell gesetze Farbwert nach der Ausführung von '''glDrawElements''' undefiniert. Unveränderte Attribute behalten allerdings ihren angegebenen Status.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Effekt von '''glDrawElements''' ist derselbe wie&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt; glBegin(''mode'');&lt;br /&gt;
     for i := 0 to ''count'' - 1 do begin&lt;br /&gt;
         glArrayElement(''indices''[i]);&lt;br /&gt;
     end;&lt;br /&gt;
 glEnd();&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
=== Beispiele ===&lt;br /&gt;
'''Beispiel 1'''&lt;br /&gt;
 oneIndices : ARRAY[0..6] OF GLubyte = (0,  1,  2,  3,  4,  5,  6);&lt;br /&gt;
 twoIndices : ARRAY[0..5] OF GLubyte = (7,  1,  8,  9, 10, 11);&lt;br /&gt;
 ...&lt;br /&gt;
 glDrawElements(GL_LINE_STRIP, 7, GL_UNSIGNED_BYTE, @oneIndices);&lt;br /&gt;
 glDrawElements(GL_LINE_STRIP, 6, GL_UNSIGNED_BYTE, @twoIndices);&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
'''Beispiel 2'''&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Array mit Farbwerten und ein Array mit Vertices werden eingebunden, aktiviert und mit einem 16-Bit (entspricht Word) Indexarray über '''glDrawElements''' gezeichnet:&lt;br /&gt;
 glEnableClientState(GL_COLOR_ARRAY);&lt;br /&gt;
 glEnableClientState(GL_VERTEX_ARRAY);&lt;br /&gt;
 &lt;br /&gt;
 glColorPointer(4,GL_UNSIGNED_BYTE,0,@Colors[0]); &lt;br /&gt;
 glVertexPointer(3,GL_FLOAT,0,@Positions[0]);&lt;br /&gt;
 &lt;br /&gt;
 glDrawElements(GL_LINE_STRIP, Count, GL_UNSIGNED_SHORT, @Indices[0]);&lt;br /&gt;
 &lt;br /&gt;
 glDisableClientState(GL_COLOR_ARRAY);&lt;br /&gt;
 glDisableClientState(GL_VERTEX_ARRAY); &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hinweise ==&lt;br /&gt;
'''glDrawElements''' ist erst ab GL Version 1.1 oder höher nutzbar.&lt;br /&gt;
&lt;br /&gt;
'''glDrawElements''' wird in [[Displaylisten]] eingebunden, wenn die Funktion also in eine Displayliste kompiliert wird, werden die benötigten Arrayzeiger (welche das sind, wird durch die Arrayzeiger und aktivierten States beschrieben) in die Displayliste kompiliert. Dies geschieht, da die Arrayzeiger und aktivierten States clientseitige States sind, und die Displayliste daher nur bei ihrer Erstellung beeinflussen, nicht jedoch bei ihrer Ausführung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Fehlermeldungen ==&lt;br /&gt;
'''GL_INVALID_ENUM''' wird generiert, wenn ''mode'' keinen gültigen Wert enthält.&lt;br /&gt;
&lt;br /&gt;
'''GL_INVALID_VALUE''' wird, generiert wenn ''count'' negativ ist.&lt;br /&gt;
&lt;br /&gt;
'''GL_INVALID_OPERATION''' wird generiert, wenn '''glDrawElements''' in einem [[glBegin]]-[[glEnd]] Block aufgerufen wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
[[glArrayElement]], [[glEnableClientState]], [[glDisableClientState]], [[glBegin|glBegin / glEnd]], [[glColorPointer]], [[glDrawArrays]], [[glDrawRangeElements]], [[glEdgeFlagPointer]], [[glFogCoordPointer]], [[glGetPointerv]], [[glGetString]], [[glIndexPointer]], [[glInterleavedArrays]], [[glMultiDrawArrays]], [[glMultiDrawElements]], [[glNormalPointer]], [[glSecondaryColorPointer]], [[glTexCoordPointer]], [[glVertexPointer]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:GL|DrawElements]]&lt;br /&gt;
[[Kategorie:GL1.1|DrawElements]]&lt;br /&gt;
[[Kategorie:GL3|DrawElements]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=DGL_Treffen/2017/Organisation&amp;diff=26368</id>
		<title>DGL Treffen/2017/Organisation</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=DGL_Treffen/2017/Organisation&amp;diff=26368"/>
				<updated>2017-05-22T23:29:35Z</updated>
		
		<summary type="html">&lt;p&gt;End: pfannkuchen&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Wie bereits im Forum angedroht, planen wir momentan ein DGL-Treffen in Schweden im Juli 2017. Hierfür geht es an einen See in Ryd.&lt;br /&gt;
&lt;br /&gt;
;Thema: &amp;quot;Going Wild&amp;quot; ;-)&lt;br /&gt;
&lt;br /&gt;
Weitere Infos und detaillierte Besprechungen finden in [https://delphigl.com/forum/viewtopic.php?f=4&amp;amp;t=11569 diesem Forenthread] statt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Wo?==&lt;br /&gt;
S25105&lt;br /&gt;
Södra Rimshult 2,&lt;br /&gt;
Ryd&lt;br /&gt;
&lt;br /&gt;
[http://www.novasol.de/p/S25105?PE=8&amp;amp;K=0&amp;amp;SD=01-07-2017&amp;amp;DUR=14&amp;amp;ED=15-07-2017&amp;amp;wt.si_n=NormalSearchBookingFlow#overview-tab Novasol Link]&lt;br /&gt;
&lt;br /&gt;
Latitude:56.41619, Longitude:14.7563549.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Wann?==&lt;br /&gt;
*Anreise: Sa. 01.07.2017&lt;br /&gt;
*Abreise: Sa. 15.07.2017&lt;br /&gt;
&lt;br /&gt;
==Was kostet das?==&lt;br /&gt;
Ein Preis von 500€-700€ wird angestrebt. Letztendlich hängt der Preis davon ab, wieviel verzerrt und unternommen wird. Anreise erfolgt gemeinsam über Gruppen. Die Anreise bis zu einem gemeinsamen Treffpunkt muss selbstständig organisiert werden.&lt;br /&gt;
Die Verpflegung erfolgt üblicherweise über eine Umlage und wir holen uns gemeinsam etwas.&lt;br /&gt;
&lt;br /&gt;
Die Abrechnung erfolgt einige Wochen nach Ende. Wer einen längeren Zahlungshorizont braucht, sollte dies bitte vorher bei Phobeus melden.&lt;br /&gt;
 Sollte jemand aus Kostengründen nicht teilnehmen können, kann er sich per Mail an Phobeus wenden.&lt;br /&gt;
&lt;br /&gt;
==Wer kommt mit?==&lt;br /&gt;
Zumindest nicht mehr, wer sich nicht bisher angemeldet hat. Es sind 8 Betten im Haus und diese sind bereits alle belegt. Bitte beim nächsten Mal rechtzeitig melden und alle mit Bedarf können mitkommen ;)&lt;br /&gt;
&lt;br /&gt;
ARG = Anreisegruppe ;)&lt;br /&gt;
&lt;br /&gt;
[[Datei:DGL_Treffen_2017_Feldkarte.jpg|200px|thumb|right|Feldkarte für die Anfahrt]]&lt;br /&gt;
&lt;br /&gt;
{|{{Prettytable_B1}}&lt;br /&gt;
!Teilnehmer&lt;br /&gt;
!Tage&lt;br /&gt;
(14=max)&lt;br /&gt;
!Anreise&lt;br /&gt;
!Kommentar&lt;br /&gt;
|-&lt;br /&gt;
|Phobeus&lt;br /&gt;
|14&lt;br /&gt;
|PKW &lt;br /&gt;
|(ARG Nord: 1 Plätze im PKW frei ab Hamburg.)&lt;br /&gt;
|-&lt;br /&gt;
|i0n0s&lt;br /&gt;
|14&lt;br /&gt;
|PKW &lt;br /&gt;
|(ARG SÜD: 1 Platz im PKW frei ab Gießen.)&lt;br /&gt;
|-&lt;br /&gt;
|Pixelschubser&lt;br /&gt;
|14&lt;br /&gt;
| -&lt;br /&gt;
|(Anreise über ARG Nord)&lt;br /&gt;
|-&lt;br /&gt;
|Flash&lt;br /&gt;
|14&lt;br /&gt;
|PKW&lt;br /&gt;
| ARG Ost: 2-3 Plätze im Wagen (?) frei ab Chemnitz&lt;br /&gt;
|-&lt;br /&gt;
|TAK2004&lt;br /&gt;
|14&lt;br /&gt;
| -&lt;br /&gt;
| Anreise über ARG Ost?&lt;br /&gt;
|-&lt;br /&gt;
|Frase&lt;br /&gt;
|14&lt;br /&gt;
| -&lt;br /&gt;
| Anreise über ARG Ost&lt;br /&gt;
|-&lt;br /&gt;
|End&lt;br /&gt;
|14&lt;br /&gt;
| -&lt;br /&gt;
| Anreise über ARG Süd oder ARG Nord&lt;br /&gt;
|-&lt;br /&gt;
| ''offen''&lt;br /&gt;
| &lt;br /&gt;
| -&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ''offen''&lt;br /&gt;
| &lt;br /&gt;
| -&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ''offen''&lt;br /&gt;
| &lt;br /&gt;
| -&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Wie kommt man hin?==&lt;br /&gt;
Die Anreisedetails stehen noch nicht fest. Mögliche Anreise einen Tag vorher und Übernachtung in Hamburg bei Phobeus ist möglich. Von dort aus geht es Richtung Rostock, wo der nächste Treffpunkt für die Überfahrt mit der Fähre ist. Von da aus geht es dann mit dem Auto bis zum Ziel&lt;br /&gt;
&lt;br /&gt;
==Was muss man persönlich mitbringen?==&lt;br /&gt;
* ggf. Reisekasse für eigene Einkäufe (Schweden hat keinen Euro!)&lt;br /&gt;
* Bettwäsche und Handtücher&lt;br /&gt;
* Wechsel-Kleidung&lt;br /&gt;
* Reisedokumente (Führerschein, Personalausweis, Versicherungs- und Geldkarten)&lt;br /&gt;
* Reiseapotheke&lt;br /&gt;
* Hygieneartikel &lt;br /&gt;
* Badesachen (inkl. Sonnencreme, Mückencreme)&lt;br /&gt;
* Sonstiges (was zu lesen, Schreibzeug etc.)&lt;br /&gt;
&lt;br /&gt;
==Was müssen wir gemeinsammitbringen?==&lt;br /&gt;
* Klopapier&lt;br /&gt;
* Netzwerkkabel (!!!!)&lt;br /&gt;
* Steckdosenleisten (!!!!!)&lt;br /&gt;
* Küchenequipement (Gewürze, Dosenöffner/Korkenzieher/Flaschenöffner, Kaffeefilter, Geschirrtücher, Wischtücher, Küchenrolle, Spülmittel)&lt;br /&gt;
* Elektronik (1 Router, Laptop, Netzwerkkabel, Fotoapparat)&lt;br /&gt;
&lt;br /&gt;
==Was gibts zu erleben?==&lt;br /&gt;
*DGLer in echt ;)&lt;br /&gt;
*Spiel und Spannung&lt;br /&gt;
*Eine große weiße Leinwand zum bewundern (?)&lt;br /&gt;
*Ausgebildete Barkeeper&lt;br /&gt;
*Baden und Grillen&lt;br /&gt;
*Mini-LAN&lt;br /&gt;
*Virtuelle Realitäten (?)&lt;br /&gt;
*Live Projektvorstellung&lt;br /&gt;
*Wildnis pur! (To be discussed, ob draußen oder drinnen)&lt;br /&gt;
&lt;br /&gt;
==Was gibts zu essen?==&lt;br /&gt;
&lt;br /&gt;
Wir kochen und essen gemeinschaftlich. So kommt jeder an die Reihe und sollte entsprechend etwas parat haben. Jeder Koch verfügt über eine beliebige Anzahl an Hilfssklaven. Urbanen Legenden zufolge sollen schlechte Köche früher häufiger mal über Bord gegangen sein. Zudem verhindern satte Beuche Aufstände bereits im Keim!&lt;br /&gt;
&lt;br /&gt;
Hauptmahlzeiten&lt;br /&gt;
{|{{Prettytable_B1}}&lt;br /&gt;
!Koch&lt;br /&gt;
!Speise&lt;br /&gt;
!Benötigte Zutaten&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Zwischenmahlzeiten / Snacks&lt;br /&gt;
{|{{Prettytable_B1}}&lt;br /&gt;
!Koch&lt;br /&gt;
!Speise&lt;br /&gt;
!Benötigte Zutaten&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Einkaufsliste==&lt;br /&gt;
&lt;br /&gt;
Alt aus Dänemark und nur als Orientierung drin:&lt;br /&gt;
----Frühstück-----&lt;br /&gt;
*100 Eier&lt;br /&gt;
*3kg Bacon&lt;br /&gt;
*14kg Müsli&lt;br /&gt;
*40l H-Milch&lt;br /&gt;
*100 Aufback-Brötchen (ohne Kühlung!)&lt;br /&gt;
*8 Aufback-Baguettes (ohne Kühlung!)&lt;br /&gt;
*8kg Käse &amp;amp; Wurst&lt;br /&gt;
*8 Marmeladen&lt;br /&gt;
*4 Butter&lt;br /&gt;
*60l Orangensaft&lt;br /&gt;
*20 Packungen Quark&lt;br /&gt;
*300gr Speck&lt;br /&gt;
----Obst------&lt;br /&gt;
*10kg Äpfel&lt;br /&gt;
*2kg Birnen&lt;br /&gt;
*2kg Pfirsiche,&lt;br /&gt;
*2 große Wassermelonen&lt;br /&gt;
*4 Honigmelonen (Zergeneier ^^)&lt;br /&gt;
*2kg Kiwis&lt;br /&gt;
*5kg Tomaten&lt;br /&gt;
*2kg Paprika&lt;br /&gt;
*4 Gurken&lt;br /&gt;
*2kg Zwiebeln&lt;br /&gt;
*2-3 Salate (Haltbarkeit :()&lt;br /&gt;
*6kg Kartoffeln&lt;br /&gt;
----Abgepacktes----&lt;br /&gt;
*4 Dosen Mais&lt;br /&gt;
*2 Dosen Thunfisch&lt;br /&gt;
*1kg TK-Spinat&lt;br /&gt;
*8 Pack Schafskäse&lt;br /&gt;
*4kg Pizzakäse&lt;br /&gt;
*2kg Gouda&lt;br /&gt;
*5 Dosen Tomaten&lt;br /&gt;
*5 Dosen Bohnen&lt;br /&gt;
*3kg Mehl (550)&lt;br /&gt;
*3 Pack Frischhefe&lt;br /&gt;
*Rinderbrühe&lt;br /&gt;
*3 Packungen Sauerkraut&lt;br /&gt;
*1 Glas eingelegte Gurken&lt;br /&gt;
----Knapperkram---&lt;br /&gt;
*30 diverse Chipstüten&lt;br /&gt;
*6kg Nussmischungen&lt;br /&gt;
----Cocktails-----&lt;br /&gt;
*1 Flasche Havana Club&lt;br /&gt;
*2 Flaschen Wodka&lt;br /&gt;
*4l Ananassaft&lt;br /&gt;
*4l Grapefruitsaft&lt;br /&gt;
*8l Marakuja Saft&lt;br /&gt;
*Zuckersirup&lt;br /&gt;
----Sonstiges----&lt;br /&gt;
*Toilettenpapier (1 Großpack)&lt;br /&gt;
*Küchenpapier&lt;br /&gt;
*Müllbeutel &amp;gt;30l&lt;br /&gt;
*Waschmittel&lt;br /&gt;
*Backpapier&lt;br /&gt;
*1 Pack Zucker&lt;br /&gt;
*Salz&lt;br /&gt;
*Körniges Salz&lt;br /&gt;
*Pfeffer&lt;br /&gt;
*2l Olivenöl&lt;br /&gt;
*1l Essig&lt;br /&gt;
*Grillkohle&lt;br /&gt;
*Grillanzünder &amp;amp; Feuerzeug&lt;br /&gt;
*Alufolie&lt;br /&gt;
----Fleisch------&lt;br /&gt;
*2kg Fleisch zum Grillen&lt;br /&gt;
*2kg Kassler&lt;br /&gt;
*1kg geräucherte Mettenden&lt;br /&gt;
*2kg Hähnchenbrust&lt;br /&gt;
*48 Hotdogwürstchen&lt;br /&gt;
*24 Hotdogbrötchen&lt;br /&gt;
*Remouladensoße&lt;br /&gt;
*Diverse Grillsoßen&lt;br /&gt;
*Geröstete Zwiebeln&lt;br /&gt;
*Ketchup&lt;br /&gt;
*Senf&lt;br /&gt;
-----Onigiri----&lt;br /&gt;
*Sushireis&lt;br /&gt;
*Sushi-Essig&lt;br /&gt;
*Nori&lt;br /&gt;
----Ends patentierte Pfannkuchen----&lt;br /&gt;
1x Pfannkuchen fuer alle =&lt;br /&gt;
*10 Eier&lt;br /&gt;
*1kg Mehl&lt;br /&gt;
*1 Liter Milch&lt;br /&gt;
*1 Mixer&lt;br /&gt;
*1 bis 2kg Zucker&lt;br /&gt;
*eine Prise Salz&lt;br /&gt;
&lt;br /&gt;
Wahlweise kann Mehl durch Zucker jeder Sorte oder Muesli substituiert werden&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=glGetShaderInfoLog&amp;diff=25967</id>
		<title>glGetShaderInfoLog</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=glGetShaderInfoLog&amp;diff=25967"/>
				<updated>2013-12-04T18:22:33Z</updated>
		
		<summary type="html">&lt;p&gt;End: var hinzugefügt.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= glGetShaderInfoLog =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Name ==&lt;br /&gt;
'''glGetShaderInfoLog''' - Gibt das Information-Log eines Shaderobjekts aus&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Delphi-Spezifikation ==&lt;br /&gt;
&lt;br /&gt;
 procedure '''glGetShaderInfoLog'''(''shader'' : GLuint; ''maxLength'' : GLsizei; var ''length'' : GLInt; ''infoLog'' : PGLchar) &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
! ''shader'' &lt;br /&gt;
| Gibt das Shaderobjekt an, dessen Information-Log abgefragt werden soll.&lt;br /&gt;
|-&lt;br /&gt;
! ''maxLength'' &lt;br /&gt;
| Gibt die Größe des Zeichen-Puffers für das Speichern des erhaltenen Information-Logs an.&lt;br /&gt;
|-&lt;br /&gt;
! ''length''&lt;br /&gt;
| Gibt die Länge des Strings (ohne die Null-Terminierung) an, der nach ''infoLog'' ausgegeben wird.&lt;br /&gt;
|-&lt;br /&gt;
! ''infoLog''&lt;br /&gt;
| Gibt ein Zeichen-Array an, das verwendet wird, um das Information-Log auszugeben.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beschreibung == &lt;br /&gt;
'''glGetShaderInfoLog''' gibt das Information-Log für das spezifizierte Shaderobjekt aus. Das Information-Log eines Shaderobjekts wird verändert, wenn das Shaderobjekt gelinkt oder validiert wird. Der ausgegebene String ist null-terminiert.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''glGetShaderInfoLog''' legt in ''infoLog'' maximal so viele Zeichen des Information-Log ab, wie durch ''maxLength'' angegeben wurde. Die Anzahl der ausgegebenen Zeichen - ausschließlich der Null-Terminierung - wird durch ''length'' angegeben. Wenn die Länge des ausgegenen Strings nicht von Interesse ist, kann '''nil''' als ''length''-Argument verwendet werden. Die Größe des Puffers, der zum Speichern des zurückgelieferten Information-Log verwendet wird, kann durch einen Aufruf von [[glGetShader]] mit dem Argument '''GL_INFO_LOG_LENGTH''', herausgefunden werden.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Das Information-Log für ein Shaderobjekt ist entweder ein leerer String oder ein String, der Informationen über die letzte Link- oder Validierungs-Operation enthält. Das Log kann Diagnose-Nachrichten, Warnungen und andere Informationen enthalten. Wenn ein Shaderobjekt erzeugt wird, ist sein Informations-Log nicht unbedingt ein String mit der Länge 0, beispielsweise können gewisse OpenGL-Implementationen die Ausgabe &amp;quot;no errors.&amp;quot; mit length 11 ausgeben. Deshalb sollte man vor einem Aufruf von '''glGetShaderInfoLog''' [[glGetShader]] mit dem Argument '''GL_COMPILE_STATUS''' abfragen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hinweise ==&lt;br /&gt;
'''glGetShaderInfoLog''' ist nur in OpenGL-Versionen ab mindestens 2.0 verfügbar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das Information-Log für ein Shaderobjekt ist der wichtigste Weg der OpenGL-Implementation, Informationen über das Linken und Validieren mitzuteilen. Das Information-Log kann während dem Entwicklungsprozess hilfreich für Programmierer sein, auch wenn diese Operationen erfolgreich verlaufen. Man sollte aber nicht erwarten, dass verschiedene OpenGL-Implementationen (vor allem von verschiedenen Herstellern) identische Information-Logs liefern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Fehlermeldungen ==&lt;br /&gt;
'''GL_INVALID_VALUE''' wird generiert, wenn ''shader'' kein von OpenGL erzeugter Wert ist.&lt;br /&gt;
&lt;br /&gt;
'''GL_INVALID_OPERATION''' wird generiert, wenn ''shader'' kein Shaderobjekt ist.&lt;br /&gt;
&lt;br /&gt;
'''GL_INVALID_VALUE''' wird generiert, wenn ''maxLength'' kleiner 0 ist.&lt;br /&gt;
&lt;br /&gt;
'''GL_INVALID_OPERATION''' wird generiert, wenn '''glGetShaderInfoLog''' innerhalb eines [[glBegin]]-[[glEnd]] Blocks aufgerufen wird. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Zugehörige Wertrückgaben ==&lt;br /&gt;
[[glGetShader]] mit Token [[glGetShader#GL_INFO_LOG_LENGTH|GL_INFO_LOG_LENGTH]]&lt;br /&gt;
&lt;br /&gt;
[[glIsShader]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
[[glCompileShader]], [[glGetShaderInfoLog]], [[glLinkProgram]], [[glValidateProgram]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:GL|GetProgram]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=SDL_DisplayFormatAlpha&amp;diff=25838</id>
		<title>SDL DisplayFormatAlpha</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=SDL_DisplayFormatAlpha&amp;diff=25838"/>
				<updated>2013-09-07T10:03:01Z</updated>
		
		<summary type="html">&lt;p&gt;End: Versionskennzeichnung.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= SDL_DisplayFormat =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Name ==&lt;br /&gt;
'''SDL_DisplayFormat''' - Konvertiert eine Surface ins Anzeigeformat. Ab Version 1.0.&lt;br /&gt;
&lt;br /&gt;
== Delphi-Spezifikation ==&lt;br /&gt;
 function '''SDL_DisplayFormat'''(''surface'' : PSDL_Surface)  : PSDL_Surface&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
! ''surface'' &lt;br /&gt;
| Die Surface die kopiert und konvertiert werden soll&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beschreibung == &lt;br /&gt;
Die übergebene Surface wird in eine neue Surface kopiert, die das aktuell verwendete Pixelformat des Videopuffers verwendet.&lt;br /&gt;
&lt;br /&gt;
An dieser Stelle können auch die Vorteile von Hardware Colorkey und Alpha-Blit-Beschleunigung genutzt werden.&lt;br /&gt;
&lt;br /&gt;
Diese Funktion kann auch dazu benutzt werden, um eine Farbe in einen Alphakanal umzuwandeln, wenn der SDL_SRCCOLORKEY-Flag in der Surface gesetzt ist. Dann wird auf der generierten Surface an der stelle, wo die Farbe zutrifft Alpha=0 sein (transparent), ansonsten Alpha=1 (voll sichtbar).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  Rückgabewert ==&lt;br /&gt;
Wenn die Konvertierung erfolgreich ist, wird der Pointer auf die neue Surface zurückgeliefert, sonst (wenn z.B. der Speicher überläuft), wird '''nil''' zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
[[SDL_ConvertSurface]], [[SDL_DisplayFormat]], [[SDL_SetAlpha]], [[SDL_SetColorKey]], [[SDL_Surface]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:SDL|DisplayFormat]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=SDL_DisplayFormat&amp;diff=25837</id>
		<title>SDL DisplayFormat</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=SDL_DisplayFormat&amp;diff=25837"/>
				<updated>2013-09-07T10:02:47Z</updated>
		
		<summary type="html">&lt;p&gt;End: Versionskennzeichnung.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= SDL_DisplayFormat =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Name ==&lt;br /&gt;
'''SDL_DisplayFormat''' - Konvertiert eine Surface ins Anzeigeformat. Ab Version 1.0.&lt;br /&gt;
&lt;br /&gt;
== Delphi-Spezifikation ==&lt;br /&gt;
 function '''SDL_DisplayFormat'''(''surface'' : PSDL_Surface)  : PSDL_Surface&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
! ''surface'' &lt;br /&gt;
| Die Surface die kopiert und konvertiert werden soll&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beschreibung == &lt;br /&gt;
Die übergebene Surface wird in eine neue Surface kopiert, die das aktuell verwendete Pixelformat des Videopuffers verwendet.&lt;br /&gt;
&lt;br /&gt;
An dieser Stelle können auch die Vorteile von Hardware Colorkey und Alpha-Blit-Beschleunigung genutzt werden.&lt;br /&gt;
&lt;br /&gt;
Wenn der Alphakanal verwendet werden soll, muss die Funktion [[SDL_DisplayFormatAlpha]] verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  Rückgabewert ==&lt;br /&gt;
Wenn die Konvertierung erfolgreich ist, wird der Pointer auf die neue Surface zurückgeliefert, sonst (wenn z.B. der Speicher überläuft), wird {{INLINE_CODE|nil}} zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
[[SDL_ConvertSurface]], [[SDL_DisplayFormatAlpha]], [[SDL_SetAlpha]], [[SDL_SetColorKey]], [[SDL_Surface]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:SDL|DisplayFormat]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=SDL_CreateRGBSurfaceFrom&amp;diff=25836</id>
		<title>SDL CreateRGBSurfaceFrom</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=SDL_CreateRGBSurfaceFrom&amp;diff=25836"/>
				<updated>2013-09-07T10:01:02Z</updated>
		
		<summary type="html">&lt;p&gt;End: Versionskennzeichnung.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= SDL_CreateRGBSurfaceFrom =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Name ==&lt;br /&gt;
'''SDL_CreateRGBSurfaceFrom''' - Erstellt eine neue [[SDL_Surface]] aus den gegebenen Pixeldaten. Ab Version 1.0.&lt;br /&gt;
&lt;br /&gt;
== Delphi-Spezifikation ==&lt;br /&gt;
 function '''SDL_CreateRGBSurfaceFrom'''(''pixels'': Pointer; ''width'', ''heigth'', ''depth'': Integer;&lt;br /&gt;
                                     ''RMask'', ''GMask'', ''BMask'', ''AMask'': Uint32): PSDL_Surface&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
! ''pixels'' &lt;br /&gt;
| Vorhandene Pixeldaten&lt;br /&gt;
|-&lt;br /&gt;
! ''width, heigth'' &lt;br /&gt;
| Grösse der Surface&lt;br /&gt;
|-&lt;br /&gt;
! ''depth''&lt;br /&gt;
| Anzahl der Bits pro Pixel (siehe [[SDL_Surface]])&lt;br /&gt;
|-&lt;br /&gt;
! ''RMask'', ''GMask'', ''BMask'', ''AMask''&lt;br /&gt;
| Benötigt für 24 und 32 Bit Surfaces.&lt;br /&gt;
| Beschreibt im welchen 'Teil' des Pixels sich z.b. Rot befindet.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beschreibung == &lt;br /&gt;
Erstellt eine [[SDL_Surface]] im Speicher aus dem im ''pixels'' übergebenen Pixeldaten&lt;br /&gt;
(darf erst nach  [[SDL_SetVideoMode]] aufgerufen werden).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hinweise ==&lt;br /&gt;
Die Pixeldaten müssen den übergebenen Parametern entsprechen.&lt;br /&gt;
Sie werden '''nicht''' in die [[SDL_Surface]]-Struktur kopiert, weshalb das Freigeben dieser Daten erst nach [[SDL_FreeSurface]] erfolgen darf.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Rückgabewert ==&lt;br /&gt;
'''SDL_CreateRGBSurfaceFrom''' gibt '''nil''' zurück, wenn ein Fehler aufgetreten ist. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
[[SDL_CreateRGBSurface]], [[SDL_FreeSurface]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:SDL|CreateRGBSurfaceFrom]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=SDL_CreateRGBSurface&amp;diff=25835</id>
		<title>SDL CreateRGBSurface</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=SDL_CreateRGBSurface&amp;diff=25835"/>
				<updated>2013-09-07T10:00:48Z</updated>
		
		<summary type="html">&lt;p&gt;End: Versionskennzeichnung.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= SDL_CreateRGBSurface =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Name ==&lt;br /&gt;
'''SDL_CreateRGBSurface''' - Erstellt eine leere [[SDL_Surface]]. Ab Version 1.0.&lt;br /&gt;
&lt;br /&gt;
== Delphi-Spezifikation ==&lt;br /&gt;
 function '''SDL_CreateRGBSurface'''(''flags'' : Uint32; ''width'', ''heigth'', ''depth'': Integer;&lt;br /&gt;
                                     ''RMask'', ''GMask'', ''BMask'', ''AMask'': Uint32): PSDL_Surface&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
! ''flags'' &lt;br /&gt;
| Zu setzende Flags&lt;br /&gt;
|-&lt;br /&gt;
! ''width, heigth'' &lt;br /&gt;
| Grösse der Surface&lt;br /&gt;
|-&lt;br /&gt;
! ''depth''&lt;br /&gt;
| Anzahl der Bits pro Pixel (siehe [[SDL_Surface]])&lt;br /&gt;
|-&lt;br /&gt;
! ''RMask'', ''GMask'', ''BMask'', ''AMask''&lt;br /&gt;
| Benötigt für 24 und 32 Bit Surfaces.&lt;br /&gt;
| Beschreibt im welchen 'Teil' des Pixels sich z.b. Rot befindet.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beschreibung == &lt;br /&gt;
Erstellt eine leere [[SDL_Surface]] im Speicher (darf erst nach  [[SDL_SetVideoMode]] aufgerufen werden).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hinweise ==&lt;br /&gt;
Wenn bitsPerPixel 8 ist, wird eine leere (Farb)Palette in [[SDL_PixelFormat]] benutzt, ansonsten wird ein 'packed-pixel' [[SDL_PixelFormat]] erstellt, da die [RGBA]Masken benutzt.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Wenn ein Alphakanal angeben ist (wenn Amask ungleich 0 ist), wird die '''SDL_SRCALPHA''' flag automatisch gesetzt.&lt;br /&gt;
Man kann sie mit Hilfe eines Aufrufes von [[SDL_SetAlpha]] nach der Surface-Erstellung entfernen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Manchmal kann das Setzten der Alpha Maske komische Ergebnisse verursachen. Dies kann man umgehen indem man den Amask Parameter auf 0 setzt, aber die '''SDL_SRCALPHA''' flag setzt und danach [[SDL_SetAlpha]] mit dem '''SDL_SRCALPHA''' flag benutzt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Rückgabewert ==&lt;br /&gt;
'''SDL_CreateRGBSurface''' gibt '''nil''' zurück, wenn ein Fehler aufgetreten ist. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beispiel ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;//Erstellen einer 32-Bit surface wie OpenGL sie für Texturen erwartet   &lt;br /&gt;
var&lt;br /&gt;
  surface: PSDL_Surface;&lt;br /&gt;
  rmask, gmask, bmask, amask: Uint32;&lt;br /&gt;
&lt;br /&gt;
  //SDL interpretiert jeden Pixel als 32-Bit Wert.&lt;br /&gt;
  //deshalb muss unsere Maske auf der Byte Ordnung des Computers basieren&lt;br /&gt;
  if SDL_BYTEORDER = SDL_BIG_ENDIAN then&lt;br /&gt;
  begin&lt;br /&gt;
    rmask:=$ff000000;&lt;br /&gt;
    gmask:=$00ff0000;&lt;br /&gt;
    bmask:=$0000ff00;&lt;br /&gt;
    amask:=$000000ff;&lt;br /&gt;
  end&lt;br /&gt;
  else&lt;br /&gt;
  begin&lt;br /&gt;
    rmask:=$000000ff;&lt;br /&gt;
    gmask:=$0000ff00;&lt;br /&gt;
    bmask:=$00ff0000;&lt;br /&gt;
    amask:=$ff000000;&lt;br /&gt;
  end;&lt;br /&gt;
&lt;br /&gt;
  surface:=SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32,rmask, gmask, bmask, amask);&lt;br /&gt;
  if (surface=nil) then&lt;br /&gt;
  begin &lt;br /&gt;
    writeln('CreateRGBSurface fehlgeschlagen');&lt;br /&gt;
    exit;&lt;br /&gt;
  end&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
[[SDL_CreateRGBSurfaceFrom]], [[SDL_FreeSurface]], [[SDL_SetVideoMode]], [[SDL_LockSurface]], [[SDL_PixelFormat]], [[SDL_Surface]], [[SDL_SetAlpha]], [[SDL_SetColorKey]] &lt;br /&gt;
&lt;br /&gt;
[[Kategorie:SDL|CreateRGBSurface]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=SDL_Surface&amp;diff=25834</id>
		<title>SDL Surface</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=SDL_Surface&amp;diff=25834"/>
				<updated>2013-09-07T10:00:21Z</updated>
		
		<summary type="html">&lt;p&gt;End: Hinweis auf deprecation.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= SDL_Surface =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Name ==&lt;br /&gt;
'''SDL_Surface''' - Struktur der graphischen Oberfläche&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Delphi-Spezifikation ==&lt;br /&gt;
 type&lt;br /&gt;
  '''TSDL_Surface'''=record&lt;br /&gt;
    ''flags''     : Uint32;           //nur Lesezugriff&lt;br /&gt;
    ''format''    : PSDL_Pixelformat; //nur Lesezugriff&lt;br /&gt;
    ''w'', ''h''      : Integer;          //nur Lesezugriff&lt;br /&gt;
    ''pitch''     : Uint16;           //nur Lesezugriff&lt;br /&gt;
    ''pixels''    : Pointer;          //Lese- und Schreibzugriff&lt;br /&gt;
    ''clip_rect'' : SDL_Rect;         //nur Lesezugriff&lt;br /&gt;
    ''refcount''  : Integer;          //meistens nur Lesezugriff&lt;br /&gt;
  end;&lt;br /&gt;
&lt;br /&gt;
  //es existieren weitere private Felder die nicht aufgeführt sind&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
! ''flags'' &lt;br /&gt;
| Gesetzte Flags&lt;br /&gt;
|-&lt;br /&gt;
! ''format'' &lt;br /&gt;
| Pixelformat (siehe [[SDL_PixelFormat]])&lt;br /&gt;
|-&lt;br /&gt;
! ''w'', ''h'' &lt;br /&gt;
| Breite und Höhe der Surface&lt;br /&gt;
|-&lt;br /&gt;
! ''pitch'' &lt;br /&gt;
| Länge einer Surface-Scanline in Bytes&lt;br /&gt;
|-&lt;br /&gt;
! ''clip_rect'' &lt;br /&gt;
| Surface Clipping Rechteck&lt;br /&gt;
|-&lt;br /&gt;
! ''refcount'' &lt;br /&gt;
| Referenzzähler - wird beim Freigeben der Surface verwendet&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beschreibung == &lt;br /&gt;
Eine '''SDL_Surface''' repräsentiert bis SDL-Version 2.0 eine Gebiet des 'graphischen' Speichers, Speicher in dem gezeichnet werden kann.&lt;br /&gt;
&lt;br /&gt;
Ab Version 2.0 werden hierfür TSDL_Window und TSDL_Texture benutzt.&lt;br /&gt;
&lt;br /&gt;
Der Video Framebuffer wird als '''SDL_Surface''' von [[SDL_SetVideoMode]] und [[SDL_GetVideoSurface]] zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
Die Felder ''w'' und ''h'' sind Werte die die Breite und Höhe der Surface in Pixeln wiedergeben.&lt;br /&gt;
&lt;br /&gt;
Das Feld ''pixels'' ist ein Pointer auf die aktuelle Pixeldaten.&lt;br /&gt;
Siehe [[SDL_PixelFormat#Beispiel|SDL_PixelFormat]].&lt;br /&gt;
&lt;br /&gt;
Das Feld ''clip_rect'' ist das clipping rectangle wie es in [[SDL_SetClipRect]] gesetzt wurde.&lt;br /&gt;
&lt;br /&gt;
Das Feld ''flags'' unterstütz die folgenden per '''or''' verknüpften Werte:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
!SDL_SWSURFACE 	&lt;br /&gt;
|Das Surface wird im Systemspeicher gespeichert&lt;br /&gt;
|-&lt;br /&gt;
!SDL_HWSURFACE 	&lt;br /&gt;
|Das Surface wird im Grafikspeicher gespeichert&lt;br /&gt;
|-&lt;br /&gt;
!SDL_ASYNCBLIT 	&lt;br /&gt;
|Das Surface benutzt asynchrone [[blit]]s, wenn möglich&lt;br /&gt;
|-&lt;br /&gt;
!SDL_ANYFORMAT 	&lt;br /&gt;
|Erlaub jegliche Pixelformate (Display Surface)&lt;br /&gt;
|-&lt;br /&gt;
!SDL_HWPALETTE 	&lt;br /&gt;
|Das Surface hat eine exklusive Palette&lt;br /&gt;
|-&lt;br /&gt;
!SDL_DOUBLEBUF 	&lt;br /&gt;
|Das Surface ist doublebuffered (Display Surface)&lt;br /&gt;
|-&lt;br /&gt;
!SDL_FULLSCREEN 	&lt;br /&gt;
|Das Surface nutzt eine Vollbildanzeige (Display Surface)&lt;br /&gt;
|-&lt;br /&gt;
!SDL_NOFRAME&lt;br /&gt;
|Das Fenster hat deine Titelleiste oder Framedekoration. Bei '''SDL_FULLSCREEN''' ist es automatisch gesetzt.&lt;br /&gt;
|-&lt;br /&gt;
!SDL_OPENGL 	&lt;br /&gt;
|Das Surface hat einen OpenGL-Kontext (Display Surface)&lt;br /&gt;
|-&lt;br /&gt;
!SDL_OPENGLBLIT 	&lt;br /&gt;
|Das Surface unterstützt OpenGL blitting (Display Surface). HINWEIS: Dieses Flag wird aus Kompatibilitätsgründen weitergeführt und wird nicht für neuen Quelltext empfohlen.&lt;br /&gt;
|-&lt;br /&gt;
!SDL_RESIZABLE 	&lt;br /&gt;
|Das Surface kann in seiner Größe verändert werden (Display Surface)&lt;br /&gt;
|-&lt;br /&gt;
!SDL_HWACCEL 	&lt;br /&gt;
|Das Surface blit benutzt Hardwarebeschleunigung&lt;br /&gt;
|-&lt;br /&gt;
!SDL_SRCCOLORKEY&lt;br /&gt;
|Surface benutzt colorkey blitting&lt;br /&gt;
|-&lt;br /&gt;
!SDL_RLEACCEL 	&lt;br /&gt;
|Colorkey blitting wird durch RLE beschleunigt&lt;br /&gt;
|-&lt;br /&gt;
!SDL_SRCALPHA 	&lt;br /&gt;
|Surface blit benutzt Alpha-Blending&lt;br /&gt;
|-&lt;br /&gt;
!SDL_PREALLOC 	&lt;br /&gt;
|Das Surface benutzt bereitgestellten Speicher&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Hinweise ==&lt;br /&gt;
Um auf die Pixeldaten zuzugreifen kann es nötig sein die Surface zu sperren (siehe [[SDL_LockSurface]]).&lt;br /&gt;
&lt;br /&gt;
''refcount'' gibt an wieviele Zeiger auf die Surface gesetzt wurden.&lt;br /&gt;
Wenn dieser Wert 1 ist, wird die Surface mit [[SDL_FreeSurface]] freigegeben, andernfalls nur der Wert erniedrigt. &lt;br /&gt;
&lt;br /&gt;
'''SDL_RESIZABLE''': Unter Windows führt das Grössenverändern zum Verlust des OpenGL-Kontext.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
[[SDL_PixelFormat]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:SDL|Surface]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=SDL_CreateCursor&amp;diff=25833</id>
		<title>SDL CreateCursor</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=SDL_CreateCursor&amp;diff=25833"/>
				<updated>2013-09-07T09:58:10Z</updated>
		
		<summary type="html">&lt;p&gt;End: Versionskennzeichnung.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= SDL_CreateCursor =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Name ==&lt;br /&gt;
'''SDL_CreateCursor''' - Erstellt einen Pointer auf einen Cursor, der später verwendet werden kann. Ab Version 1.0.&lt;br /&gt;
&lt;br /&gt;
== Delphi-Spezifikation ==&lt;br /&gt;
 procedure '''SDL_CreateCursor'''(''data'', ''mask'' : PUInt8; ''w'', ''h'', ''hot_x'', ''hot_y'' : integer) : PSDL_Cursor&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
! ''data'' &lt;br /&gt;
| Ein Pointer auf ein im Speicher befindliches Byte-Array, wo die Cursor-Daten gespeichert sind (siehe unten)&lt;br /&gt;
|-&lt;br /&gt;
! ''mask'' &lt;br /&gt;
| Ein Pointer auf ein im Speicher befindliches Byte-Array, wo die Cursor-Daten gespeichert sind (siehe unten)&lt;br /&gt;
|-&lt;br /&gt;
! ''w''&lt;br /&gt;
| Die Breite des Cursors&lt;br /&gt;
|-&lt;br /&gt;
! ''h''&lt;br /&gt;
| Die Höhe des Cursors&lt;br /&gt;
|-&lt;br /&gt;
! ''hot_x'', ''hot_y''&lt;br /&gt;
| Der Klickpunkt des Cursors von oben-links (0,0)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beschreibung == &lt;br /&gt;
Der Befehl gibt einen Pointer auf einen Cursor zurück, der aus den Byte-Arrays erstellt wird.&lt;br /&gt;
&lt;br /&gt;
Die Byte-Arrays werden bitweise interpretiert:&lt;br /&gt;
{| {{Prettytable_B1}} 	&lt;br /&gt;
! Databit&lt;br /&gt;
! Maskbit&lt;br /&gt;
! Pixelfarbe&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 1&lt;br /&gt;
| Schwarz&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| 1&lt;br /&gt;
| Weiss&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| 0&lt;br /&gt;
| Transparent&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 0&lt;br /&gt;
| Wenn möglich invertiert, ansonsten Schwarz&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hinweise ==&lt;br /&gt;
Der Cursor muss ein Vielfaches von 8 breit sein.&lt;br /&gt;
&lt;br /&gt;
Ein Cursor, der mit dieser Methode erstellt wurde, muss mit [[SDL_FreeCursor]] wieder freigegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  Rückgabewert ==&lt;br /&gt;
Der Pointer auf den Cursor oder {{INLINE_CODE|nil}} wenn ein Fehler aufgetreten ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
[[SDL_FreeCursor]], [[SDL_SetCursor]], [[SDL_ShowCursor]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:SDL|CreateCursor]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=SDL_ConvertSurface&amp;diff=25832</id>
		<title>SDL ConvertSurface</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=SDL_ConvertSurface&amp;diff=25832"/>
				<updated>2013-09-07T09:57:48Z</updated>
		
		<summary type="html">&lt;p&gt;End: Versionskennzeichnung.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= SDL ConvertSurface =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Name ==&lt;br /&gt;
'''SDL_ConvertSurface''' - Konvertiert eine Surface zum Format einer anderen [[SDL_Surface|Surface]]. Ab Version 1.0.&lt;br /&gt;
&lt;br /&gt;
== Delphi-Spezifikation ==&lt;br /&gt;
 function '''SDL_ConvertSurface'''(''src'': PSDL_Surface; ''fmt'': PSDL_PixelFormat; ''flags'': UInt32): PSDL_Surface;&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
! ''src'' &lt;br /&gt;
| Die Quell-Surface von der kopiert wird&lt;br /&gt;
|-&lt;br /&gt;
! ''fmt'' &lt;br /&gt;
| Das Pixel-Format, in welches konvertiert werden soll&lt;br /&gt;
|-&lt;br /&gt;
! ''flags'' &lt;br /&gt;
| Das flags-Parameter wird an [[SDL_CreateRGBSurface]] übergeben und hat auch die entsprechende Syntax&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beschreibung == &lt;br /&gt;
Erzeugt eine neue Surface mit dem angegebenen Format (fmt) und kopiert und konvertiert die übergebene Surface (src) zu der neu erstellten. Schlägt die Funktion fehl, wird nil zurückgeliefert. Diese Funktion ist außerdem nützlich, um eine Surface zu kopieren.&lt;br /&gt;
&lt;br /&gt;
Diese Funktion wird intern von [[SDL_DisplayFormat]] genutzt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hinweise ==&lt;br /&gt;
Die Funktion kann nur nach [[SDL_Init]] aufgerufen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  Rückgabewert ==&lt;br /&gt;
Zurückgeliefert wird eine neue Surface mit dem angegebenen Pixelformat (fmt), die den Inhalt der Quell-Surface enthält (src).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
[[SDL_CreateRGBSurface]], [[SDL_DisplayFormat]], [[SDL_PixelFormat]], [[SDL_Surface]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:SDL|ConvertSurface]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=SDL_BlitSurface&amp;diff=25831</id>
		<title>SDL BlitSurface</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=SDL_BlitSurface&amp;diff=25831"/>
				<updated>2013-09-07T09:57:25Z</updated>
		
		<summary type="html">&lt;p&gt;End: Versionskennzeichnung.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= SDL_BlitSurface =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Name ==&lt;br /&gt;
'''SDL_BlitSurface''' - Führt einen schnellen Kopiervorgang zwischen Surfaces durch. Ab Version 1.&lt;br /&gt;
&lt;br /&gt;
== Delphi-Spezifikation ==&lt;br /&gt;
 function '''SDL_BlitSurface'''(''src'' : PSDL_Surface; ''srcrect'' : PSDL_Rect; &lt;br /&gt;
                          ''dst'' : PSDL_Surface; ''dstrect'' : PSDL_Rect) : integer&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
! ''src'' &lt;br /&gt;
| Quellsurface, von der kopiert wird&lt;br /&gt;
|-&lt;br /&gt;
! ''srcrect'' &lt;br /&gt;
| siehe unten&lt;br /&gt;
|-&lt;br /&gt;
! ''dst'' &lt;br /&gt;
| Zielsurface, auf die kopiert wird&lt;br /&gt;
|-&lt;br /&gt;
! ''dstrect'' &lt;br /&gt;
| siehe unten&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beschreibung == &lt;br /&gt;
SDL_BlitSurface führt einen schnellen Kopiervorgang von der Quellsurface auf die Zielsurface. Dabei wird w und h von ''srcrect'' für die Höhe und Breite und x und y von ''dstrect'' für die obere rechte Ecke des Kopierbereichs verwendet.&lt;br /&gt;
&lt;br /&gt;
Wenn ''srcrect'' gleich {{INLINE_CODE|nil}} ist, dann wird die komplette Quellsurface kopiert. Wenn ''dstrect'' gleich {{INLINE_CODE|nil}} ist, dann sind die Koordinaten (0,0), also die obere linke Ecke der Zielsurface.&lt;br /&gt;
&lt;br /&gt;
Der endgültige Kopierbereich wird, nachdem jegliches Clipping durchgeführt wurde, in ''dstrect'' gespeichert. (''srcrect'' wird nicht verändert)&lt;br /&gt;
&lt;br /&gt;
Das Ergebnis der Blit-Funktion variiert nach der SDL_SRCALPHA Option (Siehe [[SDL_SetAlpha]] für eine Erklärung der Beeinflussung)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hinweise ==&lt;br /&gt;
Bitte beachten, dass diese Funktion keine Streckung oder Stauchung durchführen kann.&lt;br /&gt;
Außerdem sollte sie (wie die meisten SDL-Surfacefunktionen) '''nicht''' zusammen mit OpenGL verwendet werden!&lt;br /&gt;
&lt;br /&gt;
SDL_BlitSurface sollte nicht mit einem gelocktem Surface durchgeführt werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  Rückgabewert ==&lt;br /&gt;
Die Funktion gibt 0 zurück, wenn kein Fehler aufgetreten ist, ansonsten -1.&lt;br /&gt;
&lt;br /&gt;
Wenn die Surface im Videospeicher liegt und die Funktion -2 zurückgibt, dann ist der Zugriff auf den Videospeicher verloren gegangen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
[[SDL_FillRect]], [[SDL_Rect]], [[SDL_SetAlpha]], [[SDL_SetColorKey]], [[SDL_Surface]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:SDL|BlitSurface]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=SDL_GetError&amp;diff=25828</id>
		<title>SDL GetError</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=SDL_GetError&amp;diff=25828"/>
				<updated>2013-08-29T18:44:01Z</updated>
		
		<summary type="html">&lt;p&gt;End: Kategorie hinzugefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= SDL_GetError =&lt;br /&gt;
&lt;br /&gt;
== Name ==&lt;br /&gt;
'''SDL_GetError''' - Liefert einen String zurück der den letzten aufgetretenen Fehler näher beschreibt. Ab Version 1.0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Delphi-Spezifikation ==&lt;br /&gt;
 function '''SDL_GetError''': PChar;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beschreibung ==&lt;br /&gt;
'''SDL_GetError''' liefert einen String zurück der den letzten aufgetretenen Fehler näher beschreibt. Besonders bei der Initalisierung sollte überprüft werden, ob angeforderte Ressourcen auch zur Verfügung stehen. Wird statt eines Ergebnisses ein NIL-Wert zurückgegeben, empfiehlt es sich mit '''SDL_GetError''' den aufgetretenen Fehler auszugeben. Dies erleichtert in der Praxis sehr häufig die Diagnose eines Problems.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beispiel ==&lt;br /&gt;
Wir versuchen künstlich einen Fehler hervorzurufen indem wir als gewünschte Bildschirmauflösung negative Werte angeben. Die daraus resultierende Ausgabe lautet: ''Invalid width or height''&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;[...]&lt;br /&gt;
surface := SDL_SetVideoMode(-800, -600, -32, videoflags);&lt;br /&gt;
if not assigned(surface) then&lt;br /&gt;
begin&lt;br /&gt;
  WriteLn(SDL_GetError);&lt;br /&gt;
  Quit_App;&lt;br /&gt;
end;&lt;br /&gt;
[...]&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
[[glGetError]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:SDL|SDL2|GetError]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_glsl&amp;diff=25827</id>
		<title>Tutorial glsl</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_glsl&amp;diff=25827"/>
				<updated>2013-08-29T13:53:22Z</updated>
		
		<summary type="html">&lt;p&gt;End: Ein paar Rechtschreibfehler korrigiert ;)&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 einfache Shader zu schreiben und auch in ihren Programmen zu nutzen. Außerdem 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 Geometryshader 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 permanent 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 Originalspezifikation])&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 Originalspezifikation])&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 Originalspezifikation])&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 Originalspezifikation])&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 also 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;
Außerdem 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(pShader, 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;
 glUseProgram(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. Außerdem 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 vorzeichenbehafteter Integerwert&lt;br /&gt;
|-&lt;br /&gt;
|uint 	&lt;br /&gt;
|Vorzeichenbehafteter vorzeichenloser 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 vorzeichenbehafteter Integervektor&lt;br /&gt;
|-&lt;br /&gt;
|ivec3 	&lt;br /&gt;
|3-Komponenten vorzeichenbehafteter Integervektor&lt;br /&gt;
|-&lt;br /&gt;
|ivec4 	&lt;br /&gt;
|4-Komponenten vorzeichenbehafteter Integervektor&lt;br /&gt;
|-&lt;br /&gt;
|uvec2 	&lt;br /&gt;
|2-Komponenten vorzeichenloser Integervektor&lt;br /&gt;
|-&lt;br /&gt;
|uvec3 	&lt;br /&gt;
|3-Komponenten vorzeichenloser Integervektor&lt;br /&gt;
|-&lt;br /&gt;
|uvec4 	&lt;br /&gt;
|4-Komponenten vorzeichenloser 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;
|matMxN 	&lt;br /&gt;
|Matrix mit M Spalten und N Zeilen&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[i].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 außen 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, außerdem entfällt dann logischerweise das {{INLINE_CODE|return}}. Falls die Funktion eines ihrere Argumente nach außen ü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 außen.&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 x)&lt;br /&gt;
: Gibt den Sinus von x zurück, wobei x in Radien angegeben wird.&lt;br /&gt;
* genType cos (genType x)&lt;br /&gt;
: Gibt den Kosinus von x zurück, wobei x in Radien angegeben wird.&lt;br /&gt;
* genType tan (genType x)&lt;br /&gt;
: Gibt den Tangens von x zurück, wobei x 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 Arckosinus 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;
==Hyperbolisch==&lt;br /&gt;
* genType sinh (genType x)&lt;br /&gt;
: Gibt den Sinus Hyperbolicus von x zurück. (return = (exp(x) - exp(-x)) * 0.5; )&lt;br /&gt;
* genType cosh (genType x)&lt;br /&gt;
: Gibt den Kosinus Hyperbolicus von x zurück. (return = (exp(x) + exp(-x)) * 0.5; )&lt;br /&gt;
* genType tanh (genType x)&lt;br /&gt;
: Gibt den Tangens Hyperbolicus von x zurück. (return = (exp(x) - exp(-x)) / (exp(x) + exp(-x)); )&lt;br /&gt;
* genType asinh (genType angle)&lt;br /&gt;
: Gibt den Areasinus Hyperbolicus von x zurück. (return = log(x + sqrt(x * x + 1.0)); )&lt;br /&gt;
* genType acosh (genType angle)&lt;br /&gt;
: Gibt den Areakosinus Hyperbolicus von x zurück. (return = log(x + sqrt(x * x - 1.0)); )&lt;br /&gt;
* genType atanh (genType x)&lt;br /&gt;
: Gibt den Areatangens Hyperbolicus von x zurück. (return = log((1.0 + x) / (1.0 - x)) * 0.5; )&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 exp (genType x)&lt;br /&gt;
: Gibt e(Eulerischezahl ≈ 2.7182) hoch x zurück.&lt;br /&gt;
* genType log (genType x)&lt;br /&gt;
: Gibt den Logarithmus zur Basis e(Eulerischezahl ≈ 2.7182) von x 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;
==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 roundeven(genType x)&lt;br /&gt;
: Rundet auf den nächsten Integerwert und gibt diesen zuück. Bei &amp;quot;.5&amp;quot; Werten wird zur nächsten geraden Zahl gerundet.&lt;br /&gt;
* genType round(genType x)&lt;br /&gt;
: Rundet auf den nächsten Integerwert und gibt diesen zuück. &amp;quot;.5&amp;quot; Werte werden je nach Implementation anders behandelt.&lt;br /&gt;
* genType trunc(genType x)&lt;br /&gt;
: Rundet auf den nächsten Integerwert dessen Absoluterwert nicht größer ist als der Absolutewert von x&lt;br /&gt;
* genType floor (genType x)&lt;br /&gt;
: Gibt denn größten Integerwert zurück, der kleiner oder gleich x ist.&lt;br /&gt;
* genType ceil (genType x)&lt;br /&gt;
: Gibt den kleinsten 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. (result = 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 .  (return = min(minVal, max(maxVal, x)))&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. (result = 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;= edge0 und 1.0 wenn x &amp;gt;= edge1. Dazwischen wird eine weiche Hermite Interpolation durchgeführt.&lt;br /&gt;
::float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);&lt;br /&gt;
::result = t * t * (3.0 - 2.0 * t)&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 l, genType N)&lt;br /&gt;
: Gibt den an der Flächenausrichtung N reflektierten Vektor I zurück. (result = l - 2.0 * dot(N,I) * N; )&lt;br /&gt;
* genType refract (genType l, genType N, float eta)&lt;br /&gt;
: Gibt den an der Flächenausrichtung N mit dem Brechungsindex eta gebrochenen Vektor l zurück. &lt;br /&gt;
::gentype k = 1.0 - eta * eta * (1.0 - dot(N, l) * dot(N, l))&lt;br /&gt;
::if (k &amp;lt; 0.0)&lt;br /&gt;
:::result = 0.0&lt;br /&gt;
::else &lt;br /&gt;
:::result = eta * l - (eta * dot(N, l) * sqrt(k)) * N&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;
* mat transpose (mat m)&lt;br /&gt;
: Gibt die transponierte Matrix von m zurück.&lt;br /&gt;
* mat invert (mat m)&lt;br /&gt;
: Gibt die invertierte Matrix von m zurück. Also die Matrix, die mit m multipliziert die Normalmatrix ergeben würde.&lt;br /&gt;
* mat outerProduct(vec c, vec r)&lt;br /&gt;
: Gibt eine eine Matrix als Ergebnis der linearen (return[m, n] = c[m] * r[n])-Operation zurück.&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;
: '''Texturegröße :'''&lt;br /&gt;
Mit den textureSize-Befehlen kann die Größe einer Textur bestimmt werden, wobei lod das Mipmaplevel angibt:&lt;br /&gt;
*int textureSize(sampler1D sampler, int lod)&lt;br /&gt;
*ivec2 textureSize(sampler2D sampler, int lod)&lt;br /&gt;
*ivec3 textureSize(sampler3D sampler, int lod)&lt;br /&gt;
*ivec2 textureSize(samplerCube sampler, int lod)&lt;br /&gt;
*int textureSize(sampler1DShadow sampler, int lod)&lt;br /&gt;
*ivec2 textureSize(sampler2DShadow sampler, int lod)&lt;br /&gt;
&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;
{{Vorlage:Hinweis|Der Uniform-Integer für den Sampler referenziert '''nicht''' den Namen (die ID) des Texturobjektes, sondern die Nummer der Texturunit.}}&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 nur die 3DLabs 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;
Außerdem 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-Shader 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 gilt inzwischen auch offizielle die Shadersprache für 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>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=SDL_WasInit&amp;diff=25825</id>
		<title>SDL WasInit</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=SDL_WasInit&amp;diff=25825"/>
				<updated>2013-08-24T12:36:02Z</updated>
		
		<summary type="html">&lt;p&gt;End: Versionsangaben hinzugefügt.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= SDL_WasInit =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Name ==&lt;br /&gt;
'''SDL_WasInit''' - Überprüft ob Teilsysteme von SDL initialisiert wurden. Ab Version 1.0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Delphi-Spezifikation ==&lt;br /&gt;
&lt;br /&gt;
 function '''SDL_WasInit'''(''flags'' : Uint32): Uint32&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
! ''flags'' &lt;br /&gt;
| Enthält die zu initialisierenden Teile von SDL&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Wobei dies die Teilsysteme von SDL sind:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
!SDL_INIT_TIMER 	&lt;br /&gt;
|Initialisiert das Zeit Managment.&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_AUDIO 	&lt;br /&gt;
|Initialisiert das Audio Subsystem.&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_VIDEO 	&lt;br /&gt;
|Initialisiert das Fenster Managment.&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_CDROM 	&lt;br /&gt;
|Initialisiert das CD-ROM Subsystem.&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_JOYSTICK 	&lt;br /&gt;
|Initialisiert das Joystick Subsystem.&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_EVERYTHING 	&lt;br /&gt;
|Initialisiert alle Subsysteme.&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_NOPARACHUTE 	&lt;br /&gt;
|Verhindert das SDL fatale Signale fängt.&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_EVENTTHREAD 	&lt;br /&gt;
|Startet den Event Manager in einem speraten Thread.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beschreibung ==&lt;br /&gt;
'''SDL_WasInit''' dient zur Überprüfung ob Teilsysteme von [[SDL]] schon initalisiert wurden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hinweise ==&lt;br /&gt;
Die ''flags'' sollten [[bitweise Kombination|bitweise]] mit '''or''' verknüpft werden.&lt;br /&gt;
Bsp: '''SDL_INIT_VIDEO or SDL_INIT_AUDIO'''&lt;br /&gt;
&lt;br /&gt;
== Rückgabewert ==&lt;br /&gt;
'''SDL_WasInit''' gibt die initialisierten Teilsysteme bitweise per '''or''' verknüpft zurück.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beispiel ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
var subsystem_init: Uint32;&lt;br /&gt;
begin&lt;br /&gt;
  subsystem_init:=SDL_WasInit(SDL_INIT_EVERYTHING);&lt;br /&gt;
  if (subsystem_init and SDL_INIT_VIDEO)&amp;lt;&amp;gt;0 then&lt;br /&gt;
    writeln('Video is initialized.')&lt;br /&gt;
  else&lt;br /&gt;
    writeln('Video is not initialized.');&lt;br /&gt;
end;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;  //Überprüfung auf ein spezifisches Teilsystem&lt;br /&gt;
begin&lt;br /&gt;
  if SDL_WasInit(SDL_INIT_VIDEO)&amp;lt;&amp;gt;0 then&lt;br /&gt;
    writeln('Video is initialized.')&lt;br /&gt;
  else&lt;br /&gt;
    writeln('Video is not initialized.');&lt;br /&gt;
end;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;  //Überprüfung auf zwei Teilsystemen&lt;br /&gt;
var subsytem_mask: Uint32;&lt;br /&gt;
begin&lt;br /&gt;
  subsystem_mask:=SDL_INIT_VIDEO or SDL_INIT_AUDIO;&lt;br /&gt;
&lt;br /&gt;
  if (SDL_WasInit(subsystem_mask)=subsystem_mask) then&lt;br /&gt;
    writeln('Video and Audio initialized.')&lt;br /&gt;
  else&lt;br /&gt;
    writeln('Video and Audio not initialized.');&lt;br /&gt;
end;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
[[SDL_Init]], [[SDL_InitSubSystem]] &lt;br /&gt;
&lt;br /&gt;
[[Kategorie:SDL|WasInit]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=SDL_QuitSubSystem&amp;diff=25824</id>
		<title>SDL QuitSubSystem</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=SDL_QuitSubSystem&amp;diff=25824"/>
				<updated>2013-08-24T12:34:20Z</updated>
		
		<summary type="html">&lt;p&gt;End: Versionsangaben hinzugefügt.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= SDL_QuitSubSystem =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Name ==&lt;br /&gt;
'''SDL_QuitSubSystem''' - Beendet ein Subsystem. Ab Version 1.0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Delphi-Spezifikation ==&lt;br /&gt;
 procedure '''SDL_QuitSubSystem'''(''flags'' : Uint32)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
! ''flags'' &lt;br /&gt;
| Enthält die Teilsysteme, siehe [[SDL_Init]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beschreibung == &lt;br /&gt;
'''SDL_QuitSubSystem''' beendet einzelne Teilsysteme von SDL, die bereits initialisiert wurden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
[[SDL_Quit]], [[SDL_Init]], [[SDL_InitSubSystem]] &lt;br /&gt;
&lt;br /&gt;
[[Kategorie:SDL|QuitSubSystem]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=SDL_Quit&amp;diff=25823</id>
		<title>SDL Quit</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=SDL_Quit&amp;diff=25823"/>
				<updated>2013-08-24T12:32:50Z</updated>
		
		<summary type="html">&lt;p&gt;End: Versionsangaben hinzugefügt.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= SDL_Quit =&lt;br /&gt;
&lt;br /&gt;
== Name ==&lt;br /&gt;
'''SDL_Quit''' - Beendet die Nutzung von SDL. Ab Version 1.0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Delphi-Spezifikation ==&lt;br /&gt;
 procedure '''SDL_Quit''';&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beschreibung ==&lt;br /&gt;
'''SDL_Quit''' fährt alle SDL-Subsysteme herunter und gibt die verwendeten Ressourcen wieder frei. Es sollte immer dann aufgerufen &lt;br /&gt;
werden, wenn die Anwendung beendet. Bitte beachtet, dass '''SDL_Quit''' nur die SDL-Subsysteme beendet und nicht die Anwendung selbst.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
[[SDL_Init]], [[SDL_QuitSubSystem]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:SDL|Quit]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=SDL_LoadObject&amp;diff=25822</id>
		<title>SDL LoadObject</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=SDL_LoadObject&amp;diff=25822"/>
				<updated>2013-08-24T12:32:19Z</updated>
		
		<summary type="html">&lt;p&gt;End: Versionsangaben hinzugefügt.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= SDL_LoadObject =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Name ==&lt;br /&gt;
'''SDL_LoadObject''' - Liefert einen Pointer zu einer Bibliothek zurück. Unter Windows sind dies DLLs, unter Linux werden damit Shared Libraries angesprochen. Ab Version 1.0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Delphi-Spezifikation ==&lt;br /&gt;
&lt;br /&gt;
 function ''SDL_LoadObject''('''const''' ''sofile'' : PChar): Pointer&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
! ''sofile'' &lt;br /&gt;
| Nullterminierter String, der den Namen des Shared Objekts enthält.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beschreibung ==&lt;br /&gt;
'''SDL_LoadObject''' ermittelt einen Pointer zu einer Bibliothek. Dieser Pointer, auch als Handle bezeichnet, wird in den Funktionen [[SDL_LoadFunction]] und [[SDL_UnloadObject]] verwendet. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hinweis ==&lt;br /&gt;
Unter Linux ist die Groß-/Kleinschreibung des Namens der Shared Library zu beachten. &lt;br /&gt;
&lt;br /&gt;
Beim Entladen des Shared Objects werden alle abgefragten Funktionspointer ungültig.&lt;br /&gt;
&lt;br /&gt;
Wenn die Art und Anzahl der Parameter der Funktion beim Aufruf nicht übereinstimmen, wird die Anwendung mysteriös crashen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Rückgabewert ==&lt;br /&gt;
Ein Zeiger auf die geladene Library. Falls ein Fehler aufgetreten ist, ist der Rückgabewert 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch == &lt;br /&gt;
[[SDL_LoadFunction]], [[SDL_UnloadObject]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:SDL|Allgemein]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=SDL_InitSubSystem&amp;diff=25821</id>
		<title>SDL InitSubSystem</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=SDL_InitSubSystem&amp;diff=25821"/>
				<updated>2013-08-24T12:26:48Z</updated>
		
		<summary type="html">&lt;p&gt;End: Versionsangaben hinzugefügt.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= SDL_InitSubSystem =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Name ==&lt;br /&gt;
'''SDL_InitSubSystem''' - Initialisiert weitere Teilsysteme von SDL. Ab Version 1.0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Delphi-Spezifikation ==&lt;br /&gt;
&lt;br /&gt;
 function '''SDL_INITSUBSYSTEM'''(''flags'' : Uint32): Integer&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
! ''flags'' &lt;br /&gt;
| Enthält die zu initialisierenden Teile von SDL&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Wobei dies die Teilsysteme von SDL sind:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
!SDL_INIT_TIMER 	&lt;br /&gt;
|Initialisiert das Zeit Managment.&lt;br /&gt;
|1.2 / 1.3 / 2.0&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_AUDIO 	&lt;br /&gt;
|Initialisiert das Audio Subsystem.&lt;br /&gt;
|1.2 / 1.3 / 2.0&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_VIDEO 	&lt;br /&gt;
|Initialisiert das Fenster Managment.&lt;br /&gt;
|1.2 / 1.3 / 2.0&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_CDROM 	&lt;br /&gt;
|Initialisiert das CD-ROM Subsystem.&lt;br /&gt;
|1.2 / 1.3&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_JOYSTICK 	&lt;br /&gt;
|Initialisiert das Joystick Subsystem.&lt;br /&gt;
|1.2 / 1.3 / 2.0&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_EVERYTHING 	&lt;br /&gt;
|Initialisiert alle Subsysteme.&lt;br /&gt;
|1.2 / 1.3 / 2.0&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_NOPARACHUTE 	&lt;br /&gt;
|Verhindert das SDL fatale Signale fängt.&lt;br /&gt;
|1.2 / 1.3 / 2.0&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_EVENTTHREAD 	&lt;br /&gt;
|Startet den Event Manager in einem speraten Thread.&lt;br /&gt;
|1.2 / 1.3 / 2.0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beschreibung == &lt;br /&gt;
Mit '''SDL_InitSubSystem''' kann man noch nicht initialisierte Teilsysteme von SDL initialisieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hinweise ==&lt;br /&gt;
Die ''flags'' sollten [[bitweise Kombination|bitweise]] mit '''or''' verknüpft werden.&lt;br /&gt;
Bsp: '''SDL_INIT_VIDEO or SDL_INIT_AUDIO'''&lt;br /&gt;
&lt;br /&gt;
==  Rückgabewert ==&lt;br /&gt;
'''SDL_InitSubSystem''' gibt 0 bei Erfolg zurück, -1 bei einem Fehler.&lt;br /&gt;
Eine Fehlermeldung bekommt man über [[SDL_GetError]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
[[SDL_Init]], [[SDL_WasInit]], [[SDL_QuitSubSystem]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:SDL|InitSubSystem]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=SDL_GetError&amp;diff=25820</id>
		<title>SDL GetError</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=SDL_GetError&amp;diff=25820"/>
				<updated>2013-08-24T12:22:46Z</updated>
		
		<summary type="html">&lt;p&gt;End: Versionsangaben hinzugefügt.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= SDL_GetError =&lt;br /&gt;
&lt;br /&gt;
== Name ==&lt;br /&gt;
'''SDL_GetError''' - Liefert einen String zurück der den letzten aufgetretenen Fehler näher beschreibt. Ab Version 1.0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Delphi-Spezifikation ==&lt;br /&gt;
 function '''SDL_GetError''': PChar;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beschreibung ==&lt;br /&gt;
'''SDL_GetError''' liefert einen String zurück der den letzten aufgetretenen Fehler näher beschreibt. Besonders bei der Initalisierung sollte überprüft werden, ob angeforderte Ressourcen auch zur Verfügung stehen. Wird statt eines Ergebnisses ein NIL-Wert zurückgegeben, empfiehlt es sich mit '''SDL_GetError''' den aufgetretenen Fehler auszugeben. Dies erleichtert in der Praxis sehr häufig die Diagnose eines Problems.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beispiel ==&lt;br /&gt;
Wir versuchen künstlich einen Fehler hervorzurufen indem wir als gewünschte Bildschirmauflösung negative Werte angeben. Die daraus resultierende Ausgabe lautet: ''Invalid width or height''&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;[...]&lt;br /&gt;
surface := SDL_SetVideoMode(-800, -600, -32, videoflags);&lt;br /&gt;
if not assigned(surface) then&lt;br /&gt;
begin&lt;br /&gt;
  WriteLn(SDL_GetError);&lt;br /&gt;
  Quit_App;&lt;br /&gt;
end;&lt;br /&gt;
[...]&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
[[glGetError]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:SDL|GetError]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=SDL_Init&amp;diff=25819</id>
		<title>SDL Init</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=SDL_Init&amp;diff=25819"/>
				<updated>2013-08-24T12:21:42Z</updated>
		
		<summary type="html">&lt;p&gt;End: Eine weitere Versionsangabe.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= SDL_Init =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Name ==&lt;br /&gt;
'''SDL_Init''' - Initialisiert SDL&lt;br /&gt;
&lt;br /&gt;
Ab Version 1.0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Delphi-Spezifikation ==&lt;br /&gt;
&lt;br /&gt;
 function '''SDL_INIT'''(''flags'' : Uint32): Integer&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
! ''flags'' &lt;br /&gt;
| Enthält die zu initialisierenden Teile von SDL&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Wobei dies die Teilsysteme von SDL sind:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
!SDL_INIT_TIMER &lt;br /&gt;
|Initialisiert das Zeit Managment.&lt;br /&gt;
|1.2 / 1.3 / 2.0&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_AUDIO 	&lt;br /&gt;
|Initialisiert das Audio Subsystem.&lt;br /&gt;
|1.2 / 1.3 / 2.0&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_VIDEO 	&lt;br /&gt;
|Initialisiert das Fenster Managment.&lt;br /&gt;
|1.2 / 1.3 / 2.0&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_CDROM 	&lt;br /&gt;
|Initialisiert das CD-ROM Subsystem.&lt;br /&gt;
|1.2 / 1.3&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_JOYSTICK 	&lt;br /&gt;
|Initialisiert das Joystick Subsystem.&lt;br /&gt;
|1.2 / 1.3 / 2.0&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_EVERYTHING 	&lt;br /&gt;
|Initialisiert alle Subsysteme.&lt;br /&gt;
|1.2 / 1.3 / 2.0&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_NOPARACHUTE 	&lt;br /&gt;
|Verhindert das SDL fatale Signale fängt.&lt;br /&gt;
|1.2 / 1.3 / 2.0&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_EVENTTHREAD 	&lt;br /&gt;
|Startet den Event Manager in einem speraten Thread.&lt;br /&gt;
|1.2 / 1.3 / 2.0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beschreibung == &lt;br /&gt;
'''SDL_Init''' initialisiert die gewünschten Teilsysteme von SDL und muss vor allen anderen SDL-Funktionen aufgerufen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hinweise ==&lt;br /&gt;
Die ''flags'' sollten [[bitweise Kombination|bitweise]] mit '''or''' verknüpft werden.&lt;br /&gt;
Bsp: '''SDL_INIT_VIDEO or SDL_INIT_AUDIO'''&lt;br /&gt;
&lt;br /&gt;
== Rückgabewert ==&lt;br /&gt;
'''SDL_Init''' gibt 0 bei Erfolg zurück, -1 bei einem Fehler.&lt;br /&gt;
Eine Fehlermeldung bekommt man über [[SDL_GetError]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beispiel ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;[...]&lt;br /&gt;
if (SDL_Init(SDL_INIT_VIDEO or SDL_INIT_TIMER) &amp;lt; 0 ) then&lt;br /&gt;
begin&lt;br /&gt;
  WriteLn('Error during SDL init:'+SDL_GetError);&lt;br /&gt;
  Quit_App;&lt;br /&gt;
end;&lt;br /&gt;
[...]&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Siehe auch ==&lt;br /&gt;
[[SDL_Quit]], [[SDL_InitSubSystem]], [[SDL_GetError]] &lt;br /&gt;
&lt;br /&gt;
[[Kategorie:SDL|Init]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=SDL_Init&amp;diff=25818</id>
		<title>SDL Init</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=SDL_Init&amp;diff=25818"/>
				<updated>2013-08-24T12:20:06Z</updated>
		
		<summary type="html">&lt;p&gt;End: Versionsangaben hinzugefügt.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= SDL_Init =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Name ==&lt;br /&gt;
'''SDL_Init''' - Initialisiert SDL&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Delphi-Spezifikation ==&lt;br /&gt;
&lt;br /&gt;
 function '''SDL_INIT'''(''flags'' : Uint32): Integer&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
! ''flags'' &lt;br /&gt;
| Enthält die zu initialisierenden Teile von SDL&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Wobei dies die Teilsysteme von SDL sind:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
!SDL_INIT_TIMER &lt;br /&gt;
|Initialisiert das Zeit Managment.&lt;br /&gt;
|1.2 / 1.3 / 2.0&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_AUDIO 	&lt;br /&gt;
|Initialisiert das Audio Subsystem.&lt;br /&gt;
|1.2 / 1.3 / 2.0&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_VIDEO 	&lt;br /&gt;
|Initialisiert das Fenster Managment.&lt;br /&gt;
|1.2 / 1.3 / 2.0&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_CDROM 	&lt;br /&gt;
|Initialisiert das CD-ROM Subsystem.&lt;br /&gt;
|1.2 / 1.3&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_JOYSTICK 	&lt;br /&gt;
|Initialisiert das Joystick Subsystem.&lt;br /&gt;
|1.2 / 1.3 / 2.0&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_EVERYTHING 	&lt;br /&gt;
|Initialisiert alle Subsysteme.&lt;br /&gt;
|1.2 / 1.3 / 2.0&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_NOPARACHUTE 	&lt;br /&gt;
|Verhindert das SDL fatale Signale fängt.&lt;br /&gt;
|1.2 / 1.3 / 2.0&lt;br /&gt;
|-&lt;br /&gt;
!SDL_INIT_EVENTTHREAD 	&lt;br /&gt;
|Startet den Event Manager in einem speraten Thread.&lt;br /&gt;
|1.2 / 1.3 / 2.0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beschreibung == &lt;br /&gt;
'''SDL_Init''' initialisiert die gewünschten Teilsysteme von SDL und muss vor allen anderen SDL-Funktionen aufgerufen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hinweise ==&lt;br /&gt;
Die ''flags'' sollten [[bitweise Kombination|bitweise]] mit '''or''' verknüpft werden.&lt;br /&gt;
Bsp: '''SDL_INIT_VIDEO or SDL_INIT_AUDIO'''&lt;br /&gt;
&lt;br /&gt;
== Rückgabewert ==&lt;br /&gt;
'''SDL_Init''' gibt 0 bei Erfolg zurück, -1 bei einem Fehler.&lt;br /&gt;
Eine Fehlermeldung bekommt man über [[SDL_GetError]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beispiel ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;[...]&lt;br /&gt;
if (SDL_Init(SDL_INIT_VIDEO or SDL_INIT_TIMER) &amp;lt; 0 ) then&lt;br /&gt;
begin&lt;br /&gt;
  WriteLn('Error during SDL init:'+SDL_GetError);&lt;br /&gt;
  Quit_App;&lt;br /&gt;
end;&lt;br /&gt;
[...]&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Siehe auch ==&lt;br /&gt;
[[SDL_Quit]], [[SDL_InitSubSystem]], [[SDL_GetError]] &lt;br /&gt;
&lt;br /&gt;
[[Kategorie:SDL|Init]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_ColorPicking_Shader&amp;diff=25745</id>
		<title>Tutorial ColorPicking Shader</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_ColorPicking_Shader&amp;diff=25745"/>
				<updated>2013-03-02T09:34:56Z</updated>
		
		<summary type="html">&lt;p&gt;End: Das Pixel-Array des Mauszeigers ist jetzt WIRKLICH 9 Pixel groß und es werden WIRKLICH nur 9 Pixel eingelesen.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Objektselektion mit Color Picking=&lt;br /&gt;
&lt;br /&gt;
==Einleitung==&lt;br /&gt;
&lt;br /&gt;
Jaja, schon das dritte Selektionstutorial auf DelphiGL. Aber glaubt mir wenn&lt;br /&gt;
ich euch sage, dass es dafür auch gute Gründe gibt. DGL bot bisher leider&lt;br /&gt;
nur Tutorials, die das Picking auf Basis von OpenGLs Namestack behandeln. Diese&lt;br /&gt;
Methode ist aber gerade für Einsteiger ungeeignet, nicht etwa, weil sie&lt;br /&gt;
unnötig kompliziert wäre, aber weil sie hoffnungslos veraltet, tendenziell&lt;br /&gt;
inkompatibel zu nVidias Treibern (Softwaremodus!) und enorm unflexibel ist.&lt;br /&gt;
Jedenfalls war es kein Anflug aus purer Bosheit, der die Khronos-Group dazu&lt;br /&gt;
bewogen hat, diese Methode in OpenGL3 zu entfernen.&lt;br /&gt;
&lt;br /&gt;
Ein Wort zur angestrebten Zielgruppe:&lt;br /&gt;
Bedenkt bitte, dass das Tutorial eher darauf ausgelegt ist, euch eine&lt;br /&gt;
performante, für große Projekte taugliche und vor allem zukunftssichere Methode&lt;br /&gt;
zu präsentieren. Für Einsteiger mit weniger großen Ambitionen empfiehlt sich aber vorerst eher die [[Tutorial ColorPicking|shaderlose Variante]] ([http://s200005540.online.de/verschiedenes/colorpicking.pdf Vorabversion als PDF]), welche mit einfacheren Mitteln auskommt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In diesem Tutorial soll es um Color Picking, also Selektion mithilfe von Farben,&lt;br /&gt;
gehen. Damit ihr euch ein Bild davon machen könnt wo ihr steht, wenn ihr die&lt;br /&gt;
Technik beherrscht, hier ein kurzer Überblick über die Vor- und Nachteile:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;center&amp;quot;&amp;gt;&amp;lt;b&amp;gt;Vorteile&amp;lt;/b&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;center&amp;quot;&amp;gt;&amp;lt;b&amp;gt;Nachteile&amp;lt;/b&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
* Geschwindigkeit&lt;br /&gt;
:Ein Selektionsvorgang mit dieser Methode dauert niemals länger als ein ganz normales Rendering der Szene - i.d.R. ist es sogar schneller, da das Verfahren darauf aufbaut, viel &amp;quot;unter den Tisch fallen zu lassen&amp;quot;.&lt;br /&gt;
      &lt;br /&gt;
* Speichereffizienz&lt;br /&gt;
:Im Gegensatz zu strahlbasierten Verfahren, die im Härtefall eine eigene Kollisionsgeometrie benötigen, funktioniert Color Picking  mit Shadern &amp;quot;in place&amp;quot; und benötigt keinen zusätzlichen Speicher (oder nur vernachlässigbar wenig). Wird es ohne Shader implementiert, fallen mit jedem selektierbarem Objekt 3-4 Byte pro Vertex an (d.h. etwa 12 Bytes für ein Quad).&lt;br /&gt;
      &lt;br /&gt;
* Flexibilität&lt;br /&gt;
:Color Picking funktioniert mit jeder Grafik-Schnittstelle und jeder Art von Geometrie - das schließt 2D, 3D, animiert, dynamisch und alphamaskiert mit ein. Objekte müssen nicht, wie in diesem Beispiel, durch einen festen Index identifiziert werden, sondern können auch problemlos mit eigenen Werten oder sogar Funktionen versehen werden. Und das Beste:&lt;br /&gt;
      &lt;br /&gt;
* Simplizität&lt;br /&gt;
:Das Alles gibt es zum Preis eines kleinen Fragmentshaders. Mehr Aufwand ist kaum nötig, um so gut wie alle Sonderfälle abzudecken. Man kann als Fausregel festhalten: Alles was der Benutzer sieht, kann selektiert werden. Ohne Kompromisse! Pixelgenau. Ohne aufwändige Mathematik dahinter. Und alles _voll_ Hardwarebeschleunigt. Bei der shaderlosen Variante müssen sich allerdings ein paar Gedanken über die zugrundeliegende Geometrie gemacht werden (auch vom Performanceaspekt her betrachtet).&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
* Reproduzierbarkeit&lt;br /&gt;
:Leider ist man bei einem hardwarebasierten Verfahren (trifft auf Color Picking mit OpenGL sowie Direct3D zu) auf Gedeih und Verderb dem Treiber ausgeliefert. Und damit hängt der Erfolg der Selektion theoretisch auch davon ab, wie gut sich der Treiberhersteller an Standards halten kann. Insbesondere Dinge wie Antialiasing können die Selektion verfälschen - in diesem Tutorial wird aber auch ein sehr effektiver Workaround dagegen angeboten. In der Praxis ist dieser Nachteil auch eher unbedeutend, weil man ein gewisses Maß an Standards durchaus vorraussetzen kann.&lt;br /&gt;
      &lt;br /&gt;
* Redundanz zum Physikcode&lt;br /&gt;
:Wenn alle mathematischen Grundlagen für eine Selektion via Raycasting geschaffen sind, wäre eine zusätzliche Implementierung von Color Picking nur Ballast. &amp;quot;Grundlagen für Raycasting&amp;quot; hört sich vielleicht abgehoben an, diese sind aber z.B. schon in einem einfachen Ego Shooter geschaffen, wenn man herauskriegen will, wo das Einschussloch gezeichnet werden soll oder welche Hitbox des Gegners getroffen wurde.&lt;br /&gt;
      &lt;br /&gt;
* Hardwareanforderungen&lt;br /&gt;
:Je mehr Features man nutzt (wie z.B. Shader), desto neuer muss die Grafikhardware sein. Die Methode, die hier im Tut vorgestellt wird, basiert auf GLSL und ist damit ab OpenGL 2.0 Core zu haben.&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Theorie==&lt;br /&gt;
&lt;br /&gt;
Die Theorie hinter dem Color Picking ist ganz schnell erklärt. Man zeichnet&lt;br /&gt;
jedes selektierbare Objekt in einer einmaligen Farbe und merkt sich, welches&lt;br /&gt;
Objekt in welcher Farbe gezeichnet wurde.&lt;br /&gt;
Dann wird ein Pixel unter dem Mauszeiger ausgelesen - anhand der ausgelesenen&lt;br /&gt;
Farbe lässt sich auf das Objekt unter dem Mauszeiger zurückschließen. Das ist&lt;br /&gt;
vielleicht momentan noch ein bisschen sehr abstrakt, sollte aber schon klarer&lt;br /&gt;
werden, wenn ihr den Beispielcode verfolgt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Implementierung==&lt;br /&gt;
&lt;br /&gt;
===Organisation===&lt;br /&gt;
&lt;br /&gt;
Vorweg muss gesagt sein: Wirklich alles was ich in dem Beispielcode mache, ist&lt;br /&gt;
nur eine Lösung von vielen. Wie euch durch die kurze Theorie schon dämmern&lt;br /&gt;
sollte gibt es etliche Möglichkeiten Color Picking zu implementieren. In diesem&lt;br /&gt;
Beispiel sieht das Ganze so aus:&lt;br /&gt;
Die Daten der selektierbaren Objekte (Displayliste, Position und ein String)&lt;br /&gt;
sind in einem Record zusammengefasst. Alle diese Records sind in einem Array&lt;br /&gt;
angeordnet und werden auch per Schleife gezeichnet... exakt dieser Array-Index&lt;br /&gt;
ist es nun, was jedem individuellen Objekt seine Identifizierbarkeit spendiert.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Der Shader===&lt;br /&gt;
&lt;br /&gt;
Jeder der bei Shader an böhmische Dörfer denkt, sollte sich vielleicht vorher&lt;br /&gt;
kurz das [[Tutorial glsl|GLSL-Tutorial]] auf DGL zu Gemüte führen. Prinzipiell handelt es sich&lt;br /&gt;
um kleine Programme, die Teile der festen OpenGL-Pipeline (dazu gehört z.B.&lt;br /&gt;
die Positionierung von Vertices und das Zeichnen oder Verwerfen von Pixeln)&lt;br /&gt;
ersetzen. Shader können entweder in Assembler oder einer Sprache namens GLSL&lt;br /&gt;
in einer C-artigen Syntax geschrieben werden - in diesem Beispiel wird letztere&lt;br /&gt;
Methode verwendet, da die Assemblervariante kaum noch weiterentwickelt wird und&lt;br /&gt;
schlechter zu lesen ist.&lt;br /&gt;
&lt;br /&gt;
Sehen wir uns nun die Shader an, der vor einem Selektionsvorgang gebunden und&lt;br /&gt;
anschließend wieder ausgeschaltet werden:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
// Vertexshader&lt;br /&gt;
&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
  gl_Position = ftransform();&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;
&lt;br /&gt;
Der Vertexshader macht offensichtlich nichts (oder besser: nur) weltbewegendes.&lt;br /&gt;
Jedes Vertex an seine Stelle setzen und Texturkoordinaten durchschleifen... aber&lt;br /&gt;
da fehlt doch was? Der Vertexshader übergibt gar keine Farbdaten - d.h. wir&lt;br /&gt;
können schonmal festhalten, dass die aktuelle Farbe in der Statemachine komplett&lt;br /&gt;
&amp;lt;b&amp;gt;ignoriert&amp;lt;/b&amp;gt; wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
// Fragmentshader&lt;br /&gt;
&lt;br /&gt;
uniform vec4 color;&lt;br /&gt;
uniform float use_alpha_tex;&lt;br /&gt;
uniform sampler2D sampler;&lt;br /&gt;
&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
  if (use_alpha_tex == 1.0)&lt;br /&gt;
    if (texture2D(sampler, vec2(gl_TexCoord[0])).a &amp;lt; 0.2)&lt;br /&gt;
      discard;&lt;br /&gt;
      &lt;br /&gt;
  gl_FragColor = color;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hier sieht es schon gleich viel interessanter aus. Der Fragmentshader bekommt&lt;br /&gt;
zwei im Programm gesetzte uniform Variablen: color und use_alpha_tex. Wie man in&lt;br /&gt;
der letzten Zeile sieht, ist der Wert dieser ominösen color-Variable genau das,&lt;br /&gt;
was auch im Framebuffer erscheinen wird.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;use_alpha_tex&amp;quot; wird im Programm auf 1.0 gesetzt, wenn Texturen mit Alphakanal &lt;br /&gt;
verwendet werden.&lt;br /&gt;
Sollen solche Texturen verwendet werden, liest der Shader den aktuellen&lt;br /&gt;
Alphawert und verwirft das Fragment, wenn Alpha unter dem Schwellenwert 0.2&lt;br /&gt;
liegt. Es handelt sich also nur um einen handgemachten Alphatest.&lt;br /&gt;
&lt;br /&gt;
Dabei sei angemerkt, dass dies kein sonderlich stilvolles Vorgehen ist: Man&lt;br /&gt;
versucht möglichst, einen Shader nur auf eine ganz eng umrissene Aufgabe hin&lt;br /&gt;
zu gestalten - da haben solche Abfragen nichts zu suchen. Es dient in diesem&lt;br /&gt;
Tutorial aber der Übersichtlichkeit, also werden wir mal beide Augen zudrücken.&lt;br /&gt;
&lt;br /&gt;
Zusammenfassend kann man also sagen, dass wenn der Shader aktiviert ist, jedes&lt;br /&gt;
einzelne gezeichnete Pixel eine von uns im Hauptprogramm festgelegte Farbe&lt;br /&gt;
bekommt. Zusätzlich hat der Shader die Fähigkeit, bei Texturen mit Alphakanal&lt;br /&gt;
&amp;quot;unsichtbare&amp;quot; Pixel zu ignorieren und damit den Hintergrund durchscheinen zu&lt;br /&gt;
lassen.&lt;br /&gt;
&lt;br /&gt;
Tipp: Objekte mit Textur ohne Alphakanal zählen bei der Selektion wie Objekte&lt;br /&gt;
ganz ohne Textur, da es sich letztendlich nur um ein Quad handelt, das in einer&lt;br /&gt;
Einheitsfarbe eingefärbt werden soll.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Die Renderschleife===&lt;br /&gt;
&lt;br /&gt;
Sehen wir uns jetzt einmal den Code an, bei dem wirklich etwas gezeichnet wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
procedure Render;&lt;br /&gt;
const&lt;br /&gt;
  fac: single = 1/255;&lt;br /&gt;
var&lt;br /&gt;
  i: longword;&lt;br /&gt;
  iv: array [0..3] of byte absolute i; // iv und i überschneiden sich&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Kopf der Prozedur sieht man schon erste Vorbereitungen auf das, was gleich&lt;br /&gt;
während der Schleife passieren wird. Durch das absolute-Schlüsselwort überlappen&lt;br /&gt;
i und iv im Speicher. Rein praktisch bedeutet das, dass man über iv auf die&lt;br /&gt;
einzelnen Bytes der for-Variable i zugreifen kann, als wäre sie ein Byte-Array.&lt;br /&gt;
&lt;br /&gt;
Durch Multiplikation mit der Konstante fac wird ein Byte-Wert (0..255) in einen&lt;br /&gt;
Float im Bereich (0..1) umgerechnet. Dies ist notwendig, da die Grafikkarte&lt;br /&gt;
intern mit Floats arbeitet und man daher nur Floats übergeben kann (auf SM 4.0&lt;br /&gt;
Karten funktioniert auch Integer, ist aber sehr unperformant).&lt;br /&gt;
Das nächste Häppchen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
begin&lt;br /&gt;
  glClear(GL_COLOR_BUFFER_BIT);&lt;br /&gt;
&lt;br /&gt;
  // Das Erste Model soll texturiert werden&lt;br /&gt;
  glEnable(GL_TEXTURE_2D);&lt;br /&gt;
  glUniform1f(SelShader.use_alpha_tex, 1.0);&lt;br /&gt;
&lt;br /&gt;
  for i := 1 to high(Objekte) do&lt;br /&gt;
  begin&lt;br /&gt;
    if i = 2 then begin // Ab dem zweiten nicht mehr&lt;br /&gt;
      glDisable(GL_TEXTURE_2D);&lt;br /&gt;
      glUniform1f(SelShader.use_alpha_tex, 0.0);&lt;br /&gt;
    end;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Offensichtlich sind unsere Objekte im Array so angeordnet, dass zuerst&lt;br /&gt;
texturierte Objekte (wir setzen use_alpha_tex auf 1.0 und aktivieren TEXTURE_2D)&lt;br /&gt;
gezeichnet werden sollen. Diese Art von Sortierung macht Sinn, da Statechanges&lt;br /&gt;
auf jeden Fall zu vermeiden sind, wenn sie vermeidbar sind. Gemeint ist mit&lt;br /&gt;
Sortierung nicht, dass Alphatexturen zuerst kommen müssen, das ist manchmal auch&lt;br /&gt;
gar nicht möglich, sondern das nicht mitten in der Schleife zwischen texturiert&lt;br /&gt;
und nicht texturiert gewechselt werden muss. Bei dem zweiten Durchlauf wird die&lt;br /&gt;
Texturierung deaktiviert und es geht ohne weiter (ergo: Es gibt nur ein&lt;br /&gt;
texturiertes Objekt). Der interessante Teil der Renderfunktion folgt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
    // Den Index in eine Farbe umrechnen und im Shader setzen&lt;br /&gt;
    {$ifdef ENDIAN_BIG}&lt;br /&gt;
    glUniform4f(SelShader.color, iv[1]*fac, iv[2]*fac, iv[3]*fac, 1.0);&lt;br /&gt;
    {$else}&lt;br /&gt;
    glUniform4f(SelShader.color, iv[0]*fac, iv[1]*fac, iv[2]*fac, 1.0);&lt;br /&gt;
    {$endif}&lt;br /&gt;
&lt;br /&gt;
    // Zeichnen&lt;br /&gt;
    glLoadIdentity;&lt;br /&gt;
    glTranslatef(Objekte[i].posx, Objekte[i].posy, 0);&lt;br /&gt;
    glCallList(Objekte[i].displayliste);&lt;br /&gt;
  end;&lt;br /&gt;
end;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wie versprochen werden die 3 untersten (ich sage bewusst nicht &amp;quot;ersten&amp;quot;) Bytes&lt;br /&gt;
einzeln in Floats umgerechnet und landen in color.r, color.g und color.b des&lt;br /&gt;
Shaders. color.a wird nicht verwendet und auf 1.0 gesetzt (1.0 ist der übliche&lt;br /&gt;
Standardwert für Alpha). Mit dem so präparierten Shader würde nun gezeichnet&lt;br /&gt;
werden, wäre er aktiviert.&lt;br /&gt;
&lt;br /&gt;
Die berechtigte Frage ist jetzt: Warum gibt es bei der Index-Umrechnung zwei&lt;br /&gt;
verschiedene Varianten? Der Grund ist die sogenannte Endianess oder Byte Order.&lt;br /&gt;
Bei Little-Endian-Systemen (z.B. x86) werden die Bytes mit höherer Adresse&lt;br /&gt;
signifikanter, bei Big Endian (z.B. PowerPC, Playstation 3) ist es genau&lt;br /&gt;
umgekehrt.&lt;br /&gt;
&lt;br /&gt;
Da wir nur 24 Bit (= 3 Byte) des Farbpuffers benutzen, interessiert uns das&lt;br /&gt;
signifikanteste Byte des DWords nicht. Da dieses auf Big-Endian-Systemen&lt;br /&gt;
gerade iv[0] ist, müssen die Offsets verschoben werden. Die folgende Grafik&lt;br /&gt;
verdeutlicht dies:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Endian.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Natürlich wird bei so einer einfachen Methode die Reihenfolge der&lt;br /&gt;
Farbkomponenten verändert. Aus RGB auf Little Endian wird BGR auf Big Endian. Da&lt;br /&gt;
wir die gefärbten Bilder allerdings sowieso nicht zu Gesicht bekommen, ist es&lt;br /&gt;
egal.&lt;br /&gt;
Ja, wir werden tatsächlich nie sehen können, was während der Selektion passiert.&lt;br /&gt;
Oder hat jemand bis jetzt ein SwapBuffers ausmachen können? Nein? Gut, das muss&lt;br /&gt;
so :3&lt;br /&gt;
&lt;br /&gt;
Wenn ihr den {{ArchivLink|file=tut_colorpicking_src|text=restlichen Code}} analysiert werdet ihr feststellen, dass SwapBuffers&lt;br /&gt;
nur in der Eventschleife von SDL aufgerufen wird. Wenn Render in der Select-Prozedur aufgerufen wird, werden die Buffer nicht getauscht (und damit das&lt;br /&gt;
Bild nicht angezeigt).&lt;br /&gt;
&lt;br /&gt;
Erratum: Wie ihr seht wurde die Grafik von mir korrigiert. Ich habe mich&lt;br /&gt;
entschlossen den Fehler nur durchzustreichen, damit ihr davon lernen könnt&lt;br /&gt;
und ihn nicht wiederholt:&lt;br /&gt;
Es handelt sich bei dieser Vorgehensweise NICHT um eine BITweise Verschiebung&lt;br /&gt;
nach links (SHL 8), sondern um eine BYTEweise. Was macht das schon aus?&lt;br /&gt;
Sehr viel! Wie &amp;quot;The Winner&amp;quot; mir freundlicherweise mitteilte, interpretiert die&lt;br /&gt;
CPU bei bitweisen Operationen das LongWord &amp;quot;am Stück&amp;quot;, also vom höchstwertigen&lt;br /&gt;
zum untersten Bit von Links nach Rechts. Damit bedeutet ein SHL unabhängig von&lt;br /&gt;
der Plattform immer eine Multiplikation mit 2 (= Verschiebung um ein Bit in&lt;br /&gt;
Richtung des am meisten signifikanten Bits).&lt;br /&gt;
&lt;br /&gt;
===Der Selektionscode===&lt;br /&gt;
&lt;br /&gt;
Ich hoffe ihr wurdet von dem Bit- und Bytegeschubse noch nicht gänzlich&lt;br /&gt;
frustiert und überlegt, den Rest des Tutorials erstmal beiseite zu legen. Im&lt;br /&gt;
Selektionscode (folgt) kommt noch ein bisschen mehr davon ^_^&lt;br /&gt;
Bevor ich euch allerdings den Code gebe, solltet ihr erstmal wissen, was bei der&lt;br /&gt;
Selektion genau gemacht wird.&lt;br /&gt;
Anders als im kurzen Theorieteil besprochen lesen wir nicht nur einen Pixel,&lt;br /&gt;
sondern eine 3x3-Box (9 Pixel) um den Mauszeiger herum aus. Das tun wir, um die&lt;br /&gt;
Umgebung des Pixels zu untersuchen und damit Fehler durch Antialiasing sehr&lt;br /&gt;
effektiv zu erkennen. Das Problem mit AA ist, dass es Mischfarben erzeugt: Das&lt;br /&gt;
bedeutet wann man auf den Randbereich eines Objektes klickt, kann es sein, dass&lt;br /&gt;
man nicht die Farbe des Objektes erwischt, sondern _irgend eine_ Mischfarbe.&lt;br /&gt;
&lt;br /&gt;
Wird diese kritiklos wieder als Index interpretiert landen wir irgendwo im&lt;br /&gt;
Array und im besten Fall stürzt das Programm ab (im schlimmsten Fall passiert&lt;br /&gt;
&amp;lt;i&amp;gt;nichts&amp;lt;/i&amp;gt; und der Fehler bleibt uns bis zur Veröffentlichung erhalten).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
function Select(x, y: integer): longword;&lt;br /&gt;
var&lt;br /&gt;
  PixelData: array [0..8] of longword;&lt;br /&gt;
  count, i: longword;&lt;br /&gt;
begin&lt;br /&gt;
  // Koordinaten umrechnen (SDL-Fenster in OpenGL / 3x3-Box zentrieren)&lt;br /&gt;
  y := WINDOW_Y-y;&lt;br /&gt;
  if x &amp;gt; 0 then if x &amp;lt; WINDOW_X then dec(x) else dec(x,2);&lt;br /&gt;
  if y &amp;gt; 0 then if y &amp;lt; WINDOW_Y then dec(y) else dec(y,2);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst wird der &amp;quot;Mauszeiger&amp;quot; (eigentlich nur die Koordinaten, die wir bekommen&lt;br /&gt;
haben) von Fensterpixeln (Ursprung oben) in OpenGL-Pixel (Ursprung unten)&lt;br /&gt;
umgerechnet und wenn möglich nach unten links verschoben. Das verschieben sorgt&lt;br /&gt;
dafür, dass die angeklickte Stelle genau in der Mitte der gleich ausgelesenen&lt;br /&gt;
3x3-Box ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
  glUseProgram(SelShader.prog);&lt;br /&gt;
  glClearColor(0.0, 0.0, 0.0, 0.0);&lt;br /&gt;
  glEnable(GL_SCISSOR_TEST);&lt;br /&gt;
  glScissor(x, y, 3, 3); // Die wenigsten Pixel müssen in den Buffer&lt;br /&gt;
&lt;br /&gt;
  Render;&lt;br /&gt;
  // Kein SwapBuffers. Das codierte Bild sieht eh nicht hübsch aus.&lt;br /&gt;
  &lt;br /&gt;
  glUseProgram(0);&lt;br /&gt;
  glClearColor(0.1, 0.1, 0.1, 1.0);&lt;br /&gt;
  glDisable(GL_SCISSOR_TEST);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das Zeichnen sollte eigentlich selbsterklärend sein. Der Shader wird aktiviert,&lt;br /&gt;
die Hintergrundfarbe auf (0 0 0 0) gesetzt (entspricht dem Index 0!) und der&lt;br /&gt;
Scissor Test aktiviert. Der Test macht bei Selektion sehr viel Sinn, da wir uns&lt;br /&gt;
ja eigentlich nur für 9 Pixel interessieren - warum dann alle im meinem Fall&lt;br /&gt;
786.432 Pixel in den Framebuffer schreiben?&lt;br /&gt;
In Anbetracht dessen, dass Scissor so gut wie kostenlos ist, wäre das eine&lt;br /&gt;
unverzeiliche Sünde. Was der Test allerdings nicht verhindert ist, dass für&lt;br /&gt;
jedes Pixel der Fragmentshader abgearbeitet werden muss - seht es also nicht als&lt;br /&gt;
Freibrief für den Uber-Shader aus if-Abfragen.&lt;br /&gt;
&lt;br /&gt;
Aufgerufen wird die normale Render-Prozedur, die wir so angepasst haben, dass&lt;br /&gt;
sie dem Shader, wenn er gebunden ist, die relevanten Daten zukommen&lt;br /&gt;
lässt. Nehmt das als Anreiz euer Rendering bei großen Szenen gut zu optimieren&lt;br /&gt;
(z.B. mit Octrees/BSP und Frustrum Culling) - eure Selektion profitiert genauso&lt;br /&gt;
davon. Nach dem Rendering wird Alles zurückgesetzt und erhält damit wieder&lt;br /&gt;
seine vorherige Ordnung.&lt;br /&gt;
&lt;br /&gt;
Jetzt kommt endlich der &amp;lt;b&amp;gt;wirklich&amp;lt;/b&amp;gt; interessante Teil.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
  glReadPixels(x, y, 3, 3, GL_RGBA, GL_UNSIGNED_BYTE, @PixelData[0]);&lt;br /&gt;
&lt;br /&gt;
  count := 0;&lt;br /&gt;
&lt;br /&gt;
  for i := 0 to 8 do&lt;br /&gt;
  begin&lt;br /&gt;
    if PixelData[4] = PixelData[i] then inc(count);&lt;br /&gt;
    &lt;br /&gt;
    if count &amp;gt; 3 then&lt;br /&gt;
    begin&lt;br /&gt;
      {$ifdef ENDIAN_BIG}&lt;br /&gt;
      result := (PixelData[4] shr 8)&lt;br /&gt;
      {$else}&lt;br /&gt;
      result := PixelData[4] and $FFFFFF;&lt;br /&gt;
      {$endif}&lt;br /&gt;
      exit;&lt;br /&gt;
    end;&lt;br /&gt;
  end;&lt;br /&gt;
&lt;br /&gt;
  // Wenn diese Stelle erreicht wird, hat die Schleife nicht mehr als 3&lt;br /&gt;
  // gleichfarbige Pixel zusammenbekommen. Selektion ungültig.&lt;br /&gt;
  result := 0;&lt;br /&gt;
end;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Interessant, aber es bleibt weiterhin einfach (ich hoffe es war einfach, bis&lt;br /&gt;
jetzt ^^). Aus Vogelperspektive: Es werden 9 RGBA-Werte aus dem Framebuffer&lt;br /&gt;
geholt - Alpha wird immer 255, da wird nur 24 Bit benutzen (Standardwert von&lt;br /&gt;
OpenGL) - und in 9 DWords geschrieben.&lt;br /&gt;
Schließlich wird gezählt, wie viele Pixel mit PixelData[4] (das ist die Mitte,&lt;br /&gt;
der Mauszeigerpixel) identisch sind. Wenn es mindestens 4 Pixel sind, wird&lt;br /&gt;
die Selektion für gültig erklärt - d.h. der Mauszeigerpixel wird in result&lt;br /&gt;
geschrieben und die Funktion kehrt zurück.&lt;br /&gt;
Wenn die Funktion in der Schleife noch nicht verlassen wurde, wird result auf 0&lt;br /&gt;
gesetzt.&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel in dem gezeigt wird, wie uns diesen Vorgehen hilft, Fehler zu&lt;br /&gt;
Erkennen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:AAc-Beispiel.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der von mir festgesetzte Schwellenwert &amp;quot;4&amp;quot; (bedenkt dabei, dass implementations bedingt&lt;br /&gt;
der Pixel unter dem Mauszeiger mitgezählt wird) ist genaugenommen&lt;br /&gt;
variabel. Theoretisch würde vermutlich auch 3 reichen, aber ich gehe da gerne&lt;br /&gt;
auf Nummer sicher. Der Nachteil der Sicherheit ist, das man z.B. keine Linien&lt;br /&gt;
mit 1px Breite selektieren kann - das kleinste selektierbare Objekt hat die&lt;br /&gt;
gezeichnete Größe von 2x2 Pixeln.&lt;br /&gt;
&lt;br /&gt;
Wie ihr seht, muss das LongWord vor der Rückgabe noch bearbeitet werden: Bei LE&lt;br /&gt;
reicht es, den Alpha-Wert per Bitmaske abzuschneiden. Bei Big Endian landet der&lt;br /&gt;
Alpha-Wert (glaube ich!) im untersten Byte. Daher muss in Richtung &amp;quot;unten&amp;quot;&lt;br /&gt;
verschoben werden, damit der Alpha-Wert entfernt und unser Pixel-Index im&lt;br /&gt;
unteren Bereich landet - schaut euch ruhig nochmal die Endian-Grafik an, wenn&lt;br /&gt;
ihr jetzt nur Bahnhof versteht.&lt;br /&gt;
Ich kann den Big Endian-Code leider mangels Maschine nicht testen. Sollte er&lt;br /&gt;
also auf die Art nicht funktionieren, sofort in den IRC kommen oder mir eine PM&lt;br /&gt;
schreiben (so kommt man auch an sein wohlverdientes Feedback).&lt;br /&gt;
&lt;br /&gt;
Und damit sind wir mit dem Thema durch. Was jetzt noch kommt ist lediglich für&lt;br /&gt;
den Spezialfall interessant, wenn man mit 32-Bit selektieren will... kann ja&lt;br /&gt;
sein, dass man die Bitschubserei satt hat oder 16.777.215 codierbare Objekte&lt;br /&gt;
neben dem Hintergrund nicht genug sind :-)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Ergänzung: 32/16 Bit Farbtiefe===&lt;br /&gt;
&lt;br /&gt;
32 Bit sind eigentlich leichter handzuhaben, als 24 Bit. Das kommt daher, dass&lt;br /&gt;
ein echter 32-Bit-Wert aus dem Framebuffer genau unserem (und eurem, gemeint&lt;br /&gt;
sind die BEler) nativen LongWord entspricht und damit die ganze Bitschubserei&lt;br /&gt;
inklusive Unterscheidung zwischen BE und LE überflüssig macht:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
    glUniform4f(SelShader.color, iv[0]*fac, iv[1]*fac, iv[2]*fac, iv[3]*fac);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
    if count &amp;gt; 3 then&lt;br /&gt;
    begin&lt;br /&gt;
      result := PixelData[4];&lt;br /&gt;
      exit;&lt;br /&gt;
    end;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dazu kommt noch, dass wir auf einmal Raum für 4.294.967.295 Objekte haben, was&lt;br /&gt;
definitiv mehr ist, als man jemals ausschöpfen könnte - an unsere&lt;br /&gt;
mitzeitreisdenden Leser: Das Tutorial stammt von 2009, das war damals so ;-)&lt;br /&gt;
&lt;br /&gt;
Der Nachteil an 32 Bit zur Selektion (ja, jetzt wird es nochmal kurz ernst) ist,&lt;br /&gt;
dass wir uns erstmal nicht darauf verlassen können, auch wirklich einen 32 Bit&lt;br /&gt;
Buffer vom Treiber zu bekommen, wenn wir einen anfordern. Ohne Überprüfungen&lt;br /&gt;
und Ausweichmöglichkeit auf 24 Bit läuft es also nicht.&lt;br /&gt;
Daraus folgt? Genau - wir brauchen sowieso den 24 Bit-Code für solche Härtefälle.&lt;br /&gt;
In Folge dessen ist der &amp;quot;Einfachheitsvorteil&amp;quot; von 32 Bit ad absurdum geführt&lt;br /&gt;
und wir können getrost auf 24 Bit setzen.&lt;br /&gt;
&lt;br /&gt;
Ein noch gravierenderer Nachteil ist, dass wir nun auch auf OpenGL-Funktionen&lt;br /&gt;
aufpassen müssen, die den Alphawert verwenden. Wenn beispielsweise Alphatest&lt;br /&gt;
während der Selektion aktiviert ist, werden selbst mit einer kulanten&lt;br /&gt;
Einstellung wie (GL_GREATER, 0.0) alle Selektionen von Objekten mit Alpha=0&lt;br /&gt;
verworfen. Das sind auf Little Endian die ersten 16.777.215 und bei Big Endian&lt;br /&gt;
jedes 256ste.&lt;br /&gt;
&lt;br /&gt;
Erlaubt der Treiber die Verwendung von lediglich 16 Bit, so wären noch 65535&lt;br /&gt;
Objekte selektierbar. Das ist zwar in der Regel ebenfalls mehr als genug, aber&lt;br /&gt;
leider erfordert 16 Bit aufgrund unterschiedlicher Bitlängen der Farbkomponenten&lt;br /&gt;
(R: 5, G: 6, B: 5) einen enormen Aufwand bei der Zerlegung/Zusammensetzung des&lt;br /&gt;
Index in/aus Farben, der nicht ohne massive Verwendung von Bitmasken und -shifts&lt;br /&gt;
auskommt.&lt;br /&gt;
Aus diesem Grund habe ich mich dazu entschlossen, das Thema &amp;quot;16 Bit&amp;quot; im Tutorial&lt;br /&gt;
nicht weiter zu behandeln.&lt;br /&gt;
&lt;br /&gt;
==Shaderlose Variante (Anregung)==&lt;br /&gt;
&lt;br /&gt;
===Einleitung===&lt;br /&gt;
&lt;br /&gt;
In den letzten Kapiteln wurde die Implementierung mit Shadern besprochen. Diese&lt;br /&gt;
bieten, wie schon am Anfang kurz in den Vorteilen angerissen, ein Maximum an&lt;br /&gt;
Flexilibität und Speichereffizienz (da komplett unabhängig von der Geometrie)&lt;br /&gt;
bei unbeeinträchtigter Performance. Im Prinzip eine Win-Win-Situation, könnte&lt;br /&gt;
man meinen... leider gibt es aber auch noch Hardware, auf der keine Shader&lt;br /&gt;
laufen.&lt;br /&gt;
In diesem Kapitel soll es also darum gehen, euch eine Übersicht darüber zu&lt;br /&gt;
geben, was in einer solchen Situation machbar ist - inklusive Bewertung im&lt;br /&gt;
Kontext der angestrebten Zielgruppe (siehe &amp;quot;Einleitung&amp;quot;). Implementieren müsst&lt;br /&gt;
ihr es dann aber selbst. Wenn euch die Shaderlose Variante nicht weiter&lt;br /&gt;
interessiert, könnt ihr auch problemlos zum Schluss übergehen - ihr verpasst&lt;br /&gt;
nichts mehr.&lt;br /&gt;
&lt;br /&gt;
Wesentlich schwieriger sind ohne Shader allerdings Spezialeffekte wie&lt;br /&gt;
transparente Texturen. Eine Lösung sieht so aus, dass ihr zunächst das&lt;br /&gt;
texturierte Objekt mit aktiviertem Alphatest in eine Stencil-Maske zeichnet.&lt;br /&gt;
Danach wird in einem zweiten Pass ein Quad mit der Indexfarbe gezeichnet -&lt;br /&gt;
durch die Maske werden nur solche Pixel geschrieben, die vorher den Alphatest&lt;br /&gt;
bestanden und damit die Stencilmaske geformt haben.&lt;br /&gt;
Nun aber zum grundlegenden Thema:&lt;br /&gt;
&lt;br /&gt;
Prinzipiell stehen euch ohne Shader zwei Möglichkeiten offen: 1) Einstreuen von&lt;br /&gt;
Immediate Mode in eure Renderschleife oder 2) Anpassung der Geometrie.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Immediate Mode===&lt;br /&gt;
&lt;br /&gt;
Möglichkeit 1 sieht in Pseudocode folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
  procedure Render(mode)&lt;br /&gt;
  &lt;br /&gt;
    if mode = rendermode&lt;br /&gt;
      Texturen aktivieren&lt;br /&gt;
      Lighting aktivieren&lt;br /&gt;
      usw.&lt;br /&gt;
    if mode = selection&lt;br /&gt;
      Texturen deaktiveren&lt;br /&gt;
      Lighting deaktivieren&lt;br /&gt;
      usw.&lt;br /&gt;
&lt;br /&gt;
    foreach i in models&lt;br /&gt;
      if mode = rendermode&lt;br /&gt;
        Normale Farbe[i] setzen oder Textur binden&lt;br /&gt;
      if mode = selection&lt;br /&gt;
        glColor3ubv(@i) // nur Little Endian...&lt;br /&gt;
      &lt;br /&gt;
      Farblose(!) Geometrie[i] zeichnen&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Vorteil wird schnell ersichtlich: Die Methode bleibt flexibel und einfach&lt;br /&gt;
handzuhaben - bei gleichzeitig guter Speichereffizienz. Was auf diese Art aber&lt;br /&gt;
leider niemals erreicht wird ist maximale Performance.&lt;br /&gt;
Durch die Verwendung von Immediate Mode wird dem Treiber jede Möglichkeit&lt;br /&gt;
geraubt, den Rendervorgang zu optimieren. Gleichzeitig kann der Treiber auch&lt;br /&gt;
keine Daten cachen (und ggf. wiederverwenden) sondern muss im Gegenteil noch&lt;br /&gt;
Leistung dafür verbrauchen, jederzeit auf jeden Fehltritt von euch vorbereitet&lt;br /&gt;
zu sein. Die Methode stößt also schnell an ihre Grenzen, wenn große Mengen&lt;br /&gt;
von Daten verarbeitet werden sollen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Vertex Array / VBO===&lt;br /&gt;
&lt;br /&gt;
Betrachtet man Möglichkeit 2 genauer, stellt man fest, dass es auch hier wieder&lt;br /&gt;
mehrere Optionen gibt.&lt;br /&gt;
Die Displaylisten, die im Shaderteil verwendet werden, sind&lt;br /&gt;
&amp;lt;i&amp;gt;state complete&amp;lt;/i&amp;gt;. Das bedeutet, sie enthalten alle Informationen, die der&lt;br /&gt;
Treiber zum zeichnen braucht und sind nicht auf externe Aufrufe wie glColor&lt;br /&gt;
angewiesen - der Treiber kann sie also in ein internes Format umwandeln, welches&lt;br /&gt;
das volle Spektrum an Optimierungen und Cachetricks unterstüzt. Der Treiber&lt;br /&gt;
erhält alle Daten &amp;quot;am Stück&amp;quot; und kann sich 100%ig auf das Rendern&lt;br /&gt;
&amp;quot;konzentrieren&amp;quot;, weil der Benutzer gar nicht die Möglichkeit erhält, irgendetwas&lt;br /&gt;
absurdes zu tun.&lt;br /&gt;
&lt;br /&gt;
Will man diese Art von Displaylisten ohne Shader für die Selektion fit machen,&lt;br /&gt;
benötigt man auf der einen Seite Listen mit den &amp;quot;normalen Farben&amp;quot; (welche auch&lt;br /&gt;
schlichtweg &amp;quot;keine Farben&amp;quot; sein können, wenn nur Texturen verwendet werden) und&lt;br /&gt;
Listen mit eingebauten Selektionsfarben.&lt;br /&gt;
Bei dieser Methode wird die benötigte Geometrie &amp;lt;i&amp;gt;verdoppelt&amp;lt;/i&amp;gt; - mit anderen&lt;br /&gt;
Worten: Sie kommt aus Speichersicht überhaupt nicht in Frage.&lt;br /&gt;
Es bringt auch nichts, die Displaylisten &amp;quot;unverbindlicher&amp;quot; zu halten und die&lt;br /&gt;
Spezifika wie Farbe in der Renderschleife festzulegen - damit würdet ihr nämlich&lt;br /&gt;
wieder beim Immediate Mode landen und hättet &amp;lt;i&amp;gt;trotz&amp;lt;/i&amp;gt; Listen, die durch die&lt;br /&gt;
Mischung mit Immediate Mode nicht mehr optimierbar und damit nutzlos geworden sind,&lt;br /&gt;
nichts gewonnen.&lt;br /&gt;
&lt;br /&gt;
Es muss also ein Weg gefunden werden, der folgende Kriterien erfüllt:&lt;br /&gt;
&lt;br /&gt;
# Der Treiber muss seine Daten &amp;quot;am Stück&amp;quot; erhalten können.&lt;br /&gt;
# Selektion und normales Rendering sollen die gleiche Geometrie nutzen.&lt;br /&gt;
# Trotzdem müssen die Farben austauschbar sein.&lt;br /&gt;
&lt;br /&gt;
Die Lösung sieht so aus, dass wir selbst ein Vertex Array (Hauptspeicherbasiert)&lt;br /&gt;
oder ein Vertex Buffer Object (VRAM-Basiert) erstellen. Der Einfachheit halber&lt;br /&gt;
stelle ich hier nur die Variante mit den VAs vor - es sollte sich aber ziemlich&lt;br /&gt;
gut auf VBOs übertragen lassen.&lt;br /&gt;
&lt;br /&gt;
Es werden drei Arrays erstellt:&lt;br /&gt;
* Vertices&lt;br /&gt;
* Farbdaten oder Texturkoordinaten&lt;br /&gt;
* Selektionsfarben&lt;br /&gt;
&lt;br /&gt;
In OpenGL ist es nun möglich, mittels der gl*Pointer-Funktionen die Datenquellen&lt;br /&gt;
für einen Aufruf von glDrawArrays zu bestimmten. glVertexPointer zeigt stets auf&lt;br /&gt;
unsere Vertices.&lt;br /&gt;
&lt;br /&gt;
glColorPointer wird je nach dem, ob es sich um eine Selektion oder ein normales&lt;br /&gt;
Rendering handelt, auf die Farbdaten oder die Selektionsfarben gesetzt. Werden&lt;br /&gt;
nur Texturen verwendet, bleibt glTexCoordPointer immer auf diese gesetzt,&lt;br /&gt;
der Farbpointer immer auf die Selektionsfarben - und je nach Fall werden dann&lt;br /&gt;
GL_COLOR_ARRAY oder GL_TEXTURE_2D deaktiviert oder aktiviert.&lt;br /&gt;
&lt;br /&gt;
Bedenkt auch, dass ihr mehrmals verwendete Vertices nicht mehrfach speichern&lt;br /&gt;
müsst. Benutzt stattdessen indizierte Arrays um den Speicherverbrauch zu senken&lt;br /&gt;
und ganz nebenbei die caching performance des Treibers zu erhöhen. &lt;br /&gt;
&lt;br /&gt;
==Schlusswort==&lt;br /&gt;
&lt;br /&gt;
Das war jetzt Color Picking. Ich sage es aber gerne nochmal: Bevor ihr euch&lt;br /&gt;
meine Implementation auf's Auge drücken lasst denkt daran, dass es nur eine&lt;br /&gt;
Lösung von vielen ist.&lt;br /&gt;
Wann immer in eurer Situation etwas anderes angebracht sein sollte, macht es&lt;br /&gt;
anders!&lt;br /&gt;
Es kann auch nicht schaden, wenn ihr euch den kompletten Beispielcode zum&lt;br /&gt;
Tutorial (siehe unten) mal anseht. Neben dglOpenGL und&lt;br /&gt;
Jedi-SDL verwende ich noch drei Units, die von mir sind. Ich erhebe keinen&lt;br /&gt;
Urheberrechtsanspruch auf diese Units, d.h. ihr könnt sie nach belieben&lt;br /&gt;
ausschlachten, verändern und selbst verwenden (meinetwegen auch kommerziell).&lt;br /&gt;
&lt;br /&gt;
Wenn ihr eine Frage oder Feedback zum Tutorial oder zum Verfahren habt, findet&lt;br /&gt;
ihr mich öfters im IRC-Channel von DGL oder erreicht mich bei Fragen von&lt;br /&gt;
öffentlichem Interesse auch im [http://delphigl.com/forum/index.php Forum].&lt;br /&gt;
&lt;br /&gt;
Gruß Waran&lt;br /&gt;
&lt;br /&gt;
== Dateien ==&lt;br /&gt;
* {{ArchivLink|file=tut_colorpicking_src|text=Quellcode des Beispieles}}&lt;br /&gt;
* {{ArchivLink|file=tut_colorpicking_exe|text=Vorkompilierte Version des Beispieles (Windows)}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{TUTORIAL_NAVIGATION|[[Tutorial Objektselektion]]|[[Tutorial TexFilter]]}}&lt;br /&gt;
[[Kategorie:Tutorial|ColorPicking]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=SDL_CreateCond&amp;diff=25738</id>
		<title>SDL CreateCond</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=SDL_CreateCond&amp;diff=25738"/>
				<updated>2013-01-20T08:06:41Z</updated>
		
		<summary type="html">&lt;p&gt;End: Die Seite wurde neu angelegt: „ = SDL_CreateCond =   ==Name== '''SDL_CreateCond''' - Erstellt eine Thread-Bedingung.  ==Delphi-Syntax==   function SDL_CreateCond: PSDL_Cond;  ==Beschreibung=…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt; = SDL_CreateCond = &lt;br /&gt;
&lt;br /&gt;
==Name==&lt;br /&gt;
'''SDL_CreateCond''' - Erstellt eine Thread-Bedingung.&lt;br /&gt;
&lt;br /&gt;
==Delphi-Syntax==&lt;br /&gt;
  function SDL_CreateCond: PSDL_Cond;&lt;br /&gt;
&lt;br /&gt;
==Beschreibung==&lt;br /&gt;
&lt;br /&gt;
Erstellt eine neue Thread-Bedingung.&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=SDL_KillThread&amp;diff=25737</id>
		<title>SDL KillThread</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=SDL_KillThread&amp;diff=25737"/>
				<updated>2013-01-20T08:02:31Z</updated>
		
		<summary type="html">&lt;p&gt;End: kleiner Link zu SDL_WaitThread im Hinweis&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= SDL_KillThread =&lt;br /&gt;
&lt;br /&gt;
==Name==&lt;br /&gt;
&lt;br /&gt;
'''SDL_KillThread''' - löscht einen Thread sofort. &lt;br /&gt;
&lt;br /&gt;
==Delphi-Spezifikation==&lt;br /&gt;
  procedure SDL_KillThread( thread : PSDL_Thread );&lt;br /&gt;
&lt;br /&gt;
==Parameter==&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
! ''thread'' &lt;br /&gt;
| Der Thread der gelöscht werden soll.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Beschreibung==&lt;br /&gt;
&lt;br /&gt;
SDL_KillThread löscht den Thread sofort, ohne auf dessen Beendigung zu warten.&lt;br /&gt;
&lt;br /&gt;
Sollte nicht verwendet werden, wenn der Thread Dateioperationen durchführt, da diese sonst sofort abgebrochen werden und Dateifragmente entstehen. Bei einer try-finally Konstruktion wird finally nicht aufgerufen!&lt;br /&gt;
&lt;br /&gt;
==Hinweis==&lt;br /&gt;
&lt;br /&gt;
Durch einen Bug in SDL 1.2 wird der vom Thread reservierte Speicher nicht gelöscht! Die einzige Möglichkeit einen Thread zu löschen und den Speicher zu löschen ist '''SDL_WaitThread'''[[http://wiki.delphigl.com/index.php/SDL_WaitThread]].&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=SDL_KillThread&amp;diff=25736</id>
		<title>SDL KillThread</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=SDL_KillThread&amp;diff=25736"/>
				<updated>2013-01-20T08:00:24Z</updated>
		
		<summary type="html">&lt;p&gt;End: Die Seite wurde neu angelegt: „= SDL_KillThread =  ==Name==  '''SDL_KillThread''' - löscht einen Thread sofort.   ==Delphi-Spezifikation==   procedure SDL_KillThread( thread : PSDL_Thread )…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= SDL_KillThread =&lt;br /&gt;
&lt;br /&gt;
==Name==&lt;br /&gt;
&lt;br /&gt;
'''SDL_KillThread''' - löscht einen Thread sofort. &lt;br /&gt;
&lt;br /&gt;
==Delphi-Spezifikation==&lt;br /&gt;
  procedure SDL_KillThread( thread : PSDL_Thread );&lt;br /&gt;
&lt;br /&gt;
==Parameter==&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
! ''thread'' &lt;br /&gt;
| Der Thread der gelöscht werden soll.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Beschreibung==&lt;br /&gt;
&lt;br /&gt;
SDL_KillThread löscht den Thread sofort, ohne auf dessen Beendigung zu warten.&lt;br /&gt;
&lt;br /&gt;
Sollte nicht verwendet werden, wenn der Thread Dateioperationen durchführt, da diese sonst sofort abgebrochen werden und Dateifragmente entstehen. Bei einer try-finally Konstruktion wird finally nicht aufgerufen!&lt;br /&gt;
&lt;br /&gt;
==Hinweis==&lt;br /&gt;
&lt;br /&gt;
Durch einen Bug in SDL 1.2 wird der vom Thread reservierte Speicher nicht gelöscht! Die einzige Möglichkeit einen Thread zu löschen und den Speicher zu löschen ist '''SDL_WaitThread'''.&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Deferred_Shading&amp;diff=25734</id>
		<title>Deferred Shading</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Deferred_Shading&amp;diff=25734"/>
				<updated>2013-01-13T09:39:34Z</updated>
		
		<summary type="html">&lt;p&gt;End: MRT ab OpenGL 2.0 =&amp;gt; http://en.wikipedia.org/wiki/Multiple_Render_Targets&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Deferred Shading =&lt;br /&gt;
&lt;br /&gt;
Der Begriff ''Deferred Shading'' (zu dt. &amp;quot;verzögertes Schattieren&amp;quot;) oder auch ''Deferred Lighting'' (&amp;quot;verzögerte Beleuchtung&amp;quot;) beschreibt eine Technik, mit deren Hilfe die Geometrieverarbeitung von der Lichtberechnung getrennt werden kann. Dies erlaubt hunderte Lichtquellen in einer hoch-komplexen Szene.&lt;br /&gt;
&lt;br /&gt;
== Idee ==&lt;br /&gt;
Um eine Szene mit einem traditionellen Forward-Renderer zu beleuchten, wird normalerweise jedes Objekt der Szene mit den entsprechenden Beleuchtungsparametern der Lichtquelle gezeichnet. Die verschiedenen Ergebnisse werden durch additives Blenden akkumuliert. Für jede Lichtquelle muss also jedes Objekt gezeichnet werden. Angenommen wir haben ''nL'' Lichtquellen und ''nO'' Objekte, dann liegt die Anzahl der Rendercalls bei ''O(nO * nL)''. Natürlich ist es möglich mehrere Lichtquellen in einem Pass (z.B. 8 auf einmal) zu berechnen, aber wir gehen von hunderten Lichtquellen aus, es sind also mehrere Passes notwendig und die Geometrie müsste entsprechend mehrfach verarbeitet werden.&lt;br /&gt;
&lt;br /&gt;
''Deferred Shading'' verfolgt einen anderen Ansatz: Anstatt jedes Objekt der Szene für jeden Licht-Pass neu zu renderen, werden zunächst für jeden Pixel alle beleuchtungsrelevanten Daten (z.B. 3D-Position, Normale, Textur-Farbe, etc.) in ein oder mehrere Rendertargets (oftmals auch G-Buffer genannt) geschrieben. Die eigentliche Lichtberechnung kann nun durchgeführt werden indem ein bildschirmfüllendes Quad bzw. die Lichtgeometrie (Kugel für ein Punktlicht, Kegel für ein Spotlight) gerendert wird. Für jeden Pixel werden die Daten aus dem G-Buffer ausgelesen und die Beleuchtung entsprechend dieser Daten berechnet. Die Zahl der Rendercalls liegt bei diesem Ansatz nur noch bei ''O(nO + nL)''. Mit dieser Methode sind hunderte Lichter gleichzeitig in einer hoch-komplexen Szene möglich.&lt;br /&gt;
&lt;br /&gt;
Das Verfahren ist nur dann sinnvoll, wenn man es mit einer sehr komplexen Geometrie und sehr vielen Lichtquellen zu tun hat. Hat man zum Beispiel zwar viele Lichtquellen, aber eine einfache Geometrie, kann bereits ein einfacher Depth-Only-Pass zum initialisieren des Z-Buffers verhindern, dass für unsichtbare Pixel unnötige Lichtberechnungen durchgeführt werden.&lt;br /&gt;
&lt;br /&gt;
== Vor-/Nachteile ==&lt;br /&gt;
&lt;br /&gt;
'''Vorteile:'''&lt;br /&gt;
* Viele Lichtquellen bei komplexer Geometrie möglich&lt;br /&gt;
* Postprocessing Effekte (Bloom, Tonemapping, Depth of Field, etc.) können einfach angeschlossen werden, da bereits alle benötigten Informationen aufbereitet vorliegen.&lt;br /&gt;
* Lichtberechnung mit reduzierter Auflösung möglich (sinnvoll z.B. bei FSAA, siehe [[Inferred Lighting]])&lt;br /&gt;
&lt;br /&gt;
'''Nachteile:'''&lt;br /&gt;
* Kein Hardware Anti-Aliasing möglich&lt;br /&gt;
* Transparente Objekte müssen getrennt behandelt werden (Abhilfe schafft [[Inferred Lighting]])&lt;br /&gt;
* Nur auf neueren Grafikkarten mit MRT (Mutliple Render Target) und Floating Point-Textur Support möglich (ab DirectX 9 kompatiblem Grafikchip; OpenGL Version 2.0)&lt;br /&gt;
&lt;br /&gt;
== Screenshots des G-Buffer ==&lt;br /&gt;
Um sich den Inhalt des G-Buffers besser vorstellen zu können, sind hier vier einzelnen Texturen eines G-Buffers.&lt;br /&gt;
&amp;lt;gallery widths=&amp;quot;150&amp;quot; heights=&amp;quot;80&amp;quot;&amp;gt;&lt;br /&gt;
  Datei:DeferredShading-Position.png|Positionstextur&lt;br /&gt;
  Datei:DeferredShading-Albedo.png|Albedo bzw. Farbpuffer&lt;br /&gt;
  Datei:DeferredShading-Normal.png|Normal-Puffer&lt;br /&gt;
  Datei:DeferredShading-Specular.png|Specular-Puffer&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
[[Datei:DeferredShading-Final.png|200px|thumb|center|Finales Bild]]&lt;br /&gt;
&lt;br /&gt;
== Implementierung ==&lt;br /&gt;
Zunächst müssen die Geometriedaten in den (G-Buffer) geschrieben werden. Hierzu benötigen wir drei 16-Bit Float Rendertarget Texturen. Niedrigere Bittiefen sind für Positionsbeschreibung und Normalenvektor zu wenig. Alle Rendertarget-Texturen müssen die gleiche Bittiefe haben. Sind mehrere Rendertargets aktiviert, so wird Hardware-Anti-Aliasing automatisch abgeschaltet. Die folgenden Beispiele sind mit Andorra 2D entwickelt und sollten recht einfach verständlich und nach OpenGL/DirectX umzusetzen sein.&lt;br /&gt;
&lt;br /&gt;
'''Schritt 1: Erstellen der Rendertargets'''&lt;br /&gt;
&amp;lt;source lang=&amp;quot;delphi&amp;quot;&amp;gt;&lt;br /&gt;
FRT_1_Albedo := TAdRenderTargetTexture.Create(FDraw);&lt;br /&gt;
FRT_1_Albedo.BitDepth := adF64Bit;&lt;br /&gt;
FRT_1_Albedo.SetSize(surfacew, surfaceh);&lt;br /&gt;
FRT_1_Albedo.Filter := atPoint;&lt;br /&gt;
&lt;br /&gt;
FRT_2_Position := TAdRenderTargetTexture.Create(FDraw);&lt;br /&gt;
[...]&lt;br /&gt;
&lt;br /&gt;
FRT_3_Normal := TAdRenderTargetTexture.Create(FDraw);&lt;br /&gt;
[...]&lt;br /&gt;
&lt;br /&gt;
FRT_4_Composite := TAdRenderTargetTexture.Create(FDraw);&lt;br /&gt;
[...]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Schritt 2: Der G-Buffer-Fill Shader (HLSL/Cg)'''&amp;lt;br&amp;gt;&lt;br /&gt;
Der hier gezeigte Shader ist nur ein einfaches Beispiel. Unter anderem kann durch das geschickte Weglassen von Daten (Berechnen von X, Y aus den Z und den Screen-Coordinaten im Lighting-Shader) Bandbreite eingespart werden.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//Fragment Shader&lt;br /&gt;
&lt;br /&gt;
struct fs_res {&lt;br /&gt;
  float4 position: COLOR1;&lt;br /&gt;
  float4 normal: COLOR2;&lt;br /&gt;
  float4 albedo: COLOR0;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
fs_res fs_std_geometry(&lt;br /&gt;
  float3 viewpos: TEXCOORD0,&lt;br /&gt;
  float3 normal: TEXCOORD1&lt;br /&gt;
)&lt;br /&gt;
{&lt;br /&gt;
  fs_res OUT;  &lt;br /&gt;
   &lt;br /&gt;
  OUT.position = float4(viewpos, 1.0f); &lt;br /&gt;
  OUT.normal = float4(normal, 1.0f);&lt;br /&gt;
  OUT.albedo = float4(1.0f, 1.0f, 1.0f , 1.0f);&lt;br /&gt;
  &lt;br /&gt;
  return OUT;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Vertex Shader&lt;br /&gt;
&lt;br /&gt;
struct vs_res {&lt;br /&gt;
  float4 pos: POSITION;&lt;br /&gt;
  float3 viewpos : TEXCOORD0;  &lt;br /&gt;
  float3 normal: TEXCOORD1;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vs_res vs_std_geometry(&lt;br /&gt;
  float3 position : POSITION,&lt;br /&gt;
  float3 normal: NORMAL,&lt;br /&gt;
  uniform float4x4 modelview,&lt;br /&gt;
  uniform float4x4 modelviewproj&lt;br /&gt;
)&lt;br /&gt;
{&lt;br /&gt;
  vs_res OUT; &lt;br /&gt;
  &lt;br /&gt;
  OUT.pos = mul(float4(position, 1.0f), modelviewproj);&lt;br /&gt;
  OUT.viewpos = mul(float4(position, 1.0f), modelview);&lt;br /&gt;
  OUT.normal = normalize(mul(float4(normal, 0.0f), modelview));&lt;br /&gt;
&lt;br /&gt;
  return OUT;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Schritt 3: Daten in G-Buffer Rendern'''&lt;br /&gt;
&amp;lt;source lang=&amp;quot;delphi&amp;quot;&amp;gt;&lt;br /&gt;
  //Activate the G-Buffers&lt;br /&gt;
  FDraw.AdAppl.SetRenderTarget(0, FRT_1_Albedo.Texture);&lt;br /&gt;
  FDraw.AdAppl.SetRenderTarget(1, FRT_2_Position.Texture);&lt;br /&gt;
  FDraw.AdAppl.SetRenderTarget(2, FRT_3_Normal.Texture);&lt;br /&gt;
&lt;br /&gt;
  FDraw.AdAppl.Viewport := AdRect(0, 0, surfacew, surfaceh);&lt;br /&gt;
  FDraw.AdAppl.ClearSurface(AdRect(0, 0, surfacew, surfaceh), [alColorBuffer, alZBuffer,&lt;br /&gt;
    alStencilBuffer], Ad_ARGB(0, 0, 0, 0), 1, 1);&lt;br /&gt;
&lt;br /&gt;
  //Activate the shaders&lt;br /&gt;
  FTransformShader.FragmentShader.BindEffect;&lt;br /&gt;
  FTransformShader.VertexShader.BindEffect;&lt;br /&gt;
&lt;br /&gt;
  FScene.Draw(FCamera, nil, 0);&lt;br /&gt;
&lt;br /&gt;
  //Deactivate the shaders&lt;br /&gt;
  FTransformShader.VertexShader.UnbindEffect;&lt;br /&gt;
  FTransformShader.FragmentShader.UnbindEffect;&lt;br /&gt;
&lt;br /&gt;
  FDraw.AdAppl.SetRenderTarget(2, nil);&lt;br /&gt;
  FDraw.AdAppl.SetRenderTarget(1, nil);&lt;br /&gt;
  FDraw.AdAppl.SetRenderTarget(0, nil);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Schritt 4: Einfacher Direktionaler Licht-Shader'''&amp;lt;br&amp;gt;&lt;br /&gt;
Das zur Beleuchtung verwendete Quad liegt in diesem (einfachen) Fall bereits projeziert in normierten Koordinaten vor.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
struct ps_light_res {&lt;br /&gt;
  float4 color: COLOR0;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
ps_light_res ps_light_geometry(&lt;br /&gt;
  float3 screenpos: TEXCOORD0,&lt;br /&gt;
  float3 viewpos: TEXCOORD1,&lt;br /&gt;
  float3 lightdir: TEXCOORD2,&lt;br /&gt;
  &lt;br /&gt;
  uniform sampler sPosition,&lt;br /&gt;
  uniform sampler sNormal,&lt;br /&gt;
  uniform sampler sAlbedo,&lt;br /&gt;
  uniform float4 lightcolor&lt;br /&gt;
)&lt;br /&gt;
{&lt;br /&gt;
  ps_light_res OUT;&lt;br /&gt;
  &lt;br /&gt;
  float4 col = tex2D(sAlbedo, float2(screenpos.x, -screenpos.y));&lt;br /&gt;
  float4 normal = tex2D(sNormal, float2(screenpos.x, -screenpos.y));&lt;br /&gt;
  &lt;br /&gt;
  OUT.color = float4((lightcolor * col * clamp(dot(normal.xyz, lightdir), 0.0f, 1.0f)).rgb, 1.0f);&lt;br /&gt;
  &lt;br /&gt;
  return OUT;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
struct vs_light_res {&lt;br /&gt;
  float4 pos: POSITION;&lt;br /&gt;
  float3 screenpos: TEXCOORD0;&lt;br /&gt;
  float3 viewpos: TEXCOORD1;&lt;br /&gt;
  float3 lightdir: TEXCOORD2;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vs_light_res vs_light_geometry(&lt;br /&gt;
  float3 position : POSITION,&lt;br /&gt;
  uniform float4x4 modelview,&lt;br /&gt;
  uniform float4x4 modelviewproj,&lt;br /&gt;
  uniform float3 lightdir&lt;br /&gt;
)&lt;br /&gt;
{&lt;br /&gt;
  vs_light_res OUT;&lt;br /&gt;
  &lt;br /&gt;
  OUT.pos = float4(position, 1.0f);&lt;br /&gt;
  OUT.screenpos = position * float3(0.5f, 0.5f, 0.0f) + float3(0.5f, 0.5f, 0.0f);//mul(pos, modelviewproj);&lt;br /&gt;
  OUT.viewpos = mul(position, modelview);&lt;br /&gt;
  OUT.lightdir = normalize(mul(float4(lightdir, 0.0f), modelview));&lt;br /&gt;
  &lt;br /&gt;
  return OUT;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Schritt 5: Lichtquellen in das Composite RT rendern'''&lt;br /&gt;
&amp;lt;source lang=&amp;quot;delphi&amp;quot;&amp;gt;&lt;br /&gt;
  //Render a directional light using a quad&lt;br /&gt;
  FDraw.AdAppl.SetRenderTarget(0, FRT_4_Composite.Texture);&lt;br /&gt;
  FDraw.AdAppl.Viewport := AdRect(0, 0, surfacew, surfaceh);&lt;br /&gt;
  FDraw.AdAppl.ClearSurface(AdRect(0, 0, surfacew, surfaceh), [alColorBuffer, alZBuffer,&lt;br /&gt;
    alStencilBuffer], Ad_ARGB(255, 0, 0, 0), 1, 1);  &lt;br /&gt;
&lt;br /&gt;
  FLightShader.FragmentShader.SetParameter('sAlbedo', FRT_1_Albedo.Texture);&lt;br /&gt;
  FLightShader.FragmentShader.SetParameter('sPosition', FRT_2_Position.Texture);&lt;br /&gt;
  FLightShader.FragmentShader.SetParameter('sNormal', FRT_3_Normal.Texture);&lt;br /&gt;
&lt;br /&gt;
  FLightShader.FragmentShader.BindEffect;&lt;br /&gt;
  FLightShader.VertexShader.BindEffect;&lt;br /&gt;
&lt;br /&gt;
  //Render a blue light&lt;br /&gt;
  FLightShader.FragmentShader.SetParameter('lightcolor', Ad_ARGB(255, 50, 50, 100));&lt;br /&gt;
  FLightShader.VertexShader.SetParameter('lightdir', AcVector_Normalize(AcVector3(2.0, 2.0, -1.0)));&lt;br /&gt;
  FQuad.BlendMode = bmAdd;&lt;br /&gt;
  FQuad.Draw(nil);&lt;br /&gt;
&lt;br /&gt;
  FLightShader.FragmentShader.UnbindEffect;&lt;br /&gt;
  FLightShader.VertexShader.UnbindEffect;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Schritt 6: Das Ergebnis Zeichnen'''&amp;lt;br&amp;gt;&lt;br /&gt;
Nun muss nur noch das Ergebnis im &amp;quot;Composite&amp;quot;-RT gezeichnet werden - oder weitere Post-Processing Maßnahmen durchgeführt werden.&lt;br /&gt;
&lt;br /&gt;
==Weblinks==&lt;br /&gt;
* http://www.gamedev.net/reference/programming/features/defRender/&lt;br /&gt;
&lt;br /&gt;
==Siehe auch==&lt;br /&gt;
* [[Shader]]&lt;br /&gt;
* [[FBO]]&lt;br /&gt;
* [[Inferred Lighting]]&lt;br /&gt;
* [[Hintergrundwissen#Render-Pipeline|Render-Pipeline]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=glEnable&amp;diff=25733</id>
		<title>glEnable</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=glEnable&amp;diff=25733"/>
				<updated>2013-01-12T14:42:45Z</updated>
		
		<summary type="html">&lt;p&gt;End: GL_FALSE = GL_TRUE? in Wahrheit GL_MULTISAMPLE (siehe OpenGL.org), fehlt aber noch ein Eintrag unten.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= glEnable, glDisable =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Name ==&lt;br /&gt;
'''gEnable, glDisable''' - Aktiviert bzw. deaktiviert eine server-seitige Fähigkeit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Delphi-Spezifikation ==&lt;br /&gt;
 procedure '''glEnable'''(''cap'': TGLEnum);&lt;br /&gt;
 procedure '''glDisable'''(''cap'': TGLEnum);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
&amp;lt;table border=1 rules=all&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt; &lt;br /&gt;
 &amp;lt;td&amp;gt;''cap''&amp;lt;/td&amp;gt;&lt;br /&gt;
 &amp;lt;td&amp;gt;Symbolische Konstante der zu (de)aktivierenden GL-Fähigkeit.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Beschreibung == &lt;br /&gt;
'''glEnable''' und '''glDisable''' aktivieren bzw. deaktivieren verschiedene Fähigkeiten, deren momentane Einstellung entweder mit [[glIsEnabled]] oder [[glGet]] ermittelt werden kann. Die Vorgabe für alle Einstellungen (Ausgenommen '''GL_DITHER''' und '''GL_MULTISAMPLE''', die beide '''GL_TRUE''' sind) ist '''GL_FALSE'''.&lt;br /&gt;
&lt;br /&gt;
Beide Befehle bekommen als Argument die symbolische Konstante der OpenGL-Fähigkeit übergeben, die umgeschaltet werden soll. Gültig sind dabei folgende Werte :&lt;br /&gt;
&lt;br /&gt;
=== GL_ALPHA_TEST ===&lt;br /&gt;
Wenn aktiviert, wird der Alphatest ausgeführt. Siehe [[glAlphaFunc]].&lt;br /&gt;
&lt;br /&gt;
=== GL_AUTO_NORMAL ===&lt;br /&gt;
Wenn aktiviert, werden automatisch Normalen generiert, wenn '''GL_MAP2_VERTEX_3''' oder '''GL_MAP2_VERTEX_4''' zur Erstellung von Vertices genutzt werden. Siehe [[glMap2]].&lt;br /&gt;
&lt;br /&gt;
=== GL_BLEND ===&lt;br /&gt;
Wenn aktiviert werden ankommenden RGBA-Farben mit den Werten die sich im Farbpuffer befinden vermischt. Siehe [[glBlendFunc]].&lt;br /&gt;
&lt;br /&gt;
=== GL_CLIP_PLANEi ===&lt;br /&gt;
Wenn aktiviert, wird die Geometrie gegen die nutzerdefinierte Schnittfläche ''i'' geschnitten. Siehe [[glClipPlane]].&lt;br /&gt;
&lt;br /&gt;
=== GL_COLOR_LOGIC_OP ===&lt;br /&gt;
Wenn aktiviert, werden die momentan gewählten logischen Operationen auf ankommenden RGBA-Farben und Farbpuffer-Werte angewendet. Siehe [[glLogicOp]].&lt;br /&gt;
&lt;br /&gt;
=== GL_COLOR_MATERIAL ===&lt;br /&gt;
Wenn aktiviert, benutzen einer oder mehrere Materialparameter die aktuelle Farbeinstellung. Siehe [[glColorMaterial]].&lt;br /&gt;
&lt;br /&gt;
=== GL_COLOR_TABLE_EXT ===&lt;br /&gt;
Wenn aktiviert, werden Farbbild-Komponenenten auf eine Farbtabelle verteilt, die vor einer Windung stattfindet. Siehe [[glColorTable]].&lt;br /&gt;
&lt;br /&gt;
=== GL_CONVOLUTION_1D_EXT ===&lt;br /&gt;
Wenn aktiviert, wird die ein-dimensionale Windung während des Pixeltransfers durchgeführt. Siehe [[glConvolutionFilter1DEXT]].&lt;br /&gt;
&lt;br /&gt;
=== GL_CONVOLUTION_2D_EXT ===&lt;br /&gt;
Wenn aktiviert, wird die zwei-dimensionale Windung während des Pixeltransfers durchgeführt. Siehe [[glConvolutionFilter2DEXT]].&lt;br /&gt;
&lt;br /&gt;
=== GL_CULL_FACE ===&lt;br /&gt;
Wenn aktiviert, werden Polygone entsprechend ihrer Zeichnungsrichtung (Wicklung wäre der korrekt Ausdruck --[[Benutzer:Sascha Willems|Sascha Willems]] 13:05, 9. Jul 2004 (CEST)) (in Fensterkoordinaten) ausgeschlossen. Siehe [[glCullFace]].&lt;br /&gt;
&lt;br /&gt;
=== GL_DEPTH_TEST ===&lt;br /&gt;
Wenn aktiviert werden Tiefenvergleiche getätigt und der Tiefenpuffer aktualisiert. Man beachte, dass selbst dann, wenn ein Tiefenpuffer existiert und die Tiefenmaske ungleich null ist, der Tiefenpuffer nicht aktiviert wird, wenn der [[Tiefentest]] inaktiv ist. Siehe [[glDepthFunc]] und [[glDepthRange]].&lt;br /&gt;
&lt;br /&gt;
=== GL_DITHER ===&lt;br /&gt;
Wenn aktiviert, werden Farbkomponenten oder -indizes gedithert (siehe [[Dithering]]).&lt;br /&gt;
&lt;br /&gt;
=== GL_FOG ===&lt;br /&gt;
Wenn aktiviert, wird die Nebelfarbe in den Farbwert nach der Texturierung gemischt. Siehe [[glFog]].&lt;br /&gt;
&lt;br /&gt;
=== GL_FOG_OFFSET_EXT ===&lt;br /&gt;
Wenn aktiviert wird ein Versatz zum Z-Wert, der zur Berechnung des Nebels genutzt wird, addiert. Siehe [[glFog]].&lt;br /&gt;
&lt;br /&gt;
=== GL_INDEX_LOGIC_OP === &lt;br /&gt;
Wenn aktiviert, werden die momentan gewählten logischen Operationen auf einkommende Index- und Farbpufferindizes angewandt. Siehe [[glLogicOp]].&lt;br /&gt;
&lt;br /&gt;
=== GL_INTERLACE_EXT ===&lt;br /&gt;
Wenn aktiviert, wird ein Bild als interlaced (zu Deutsch : verschachtelt) angesehen. Jede Reihe ''m'' des Bildes wird behandelt als wäre sie Reihe 2 * ''m''. Wenn das Quellbild also eine Höhe von ''h'' Reihen hat, erweitert dies die Höhe des Bildes effektiv auf 2 * ''h'' - 1. Wo Fehler durch die Angabe ungültiger Bilddimensionen entstehen (z.B. [[glTexImage2D]], wird die resultierende Dimension geprüft, nicht die Dimension des Quellbildes. Dieses Token hat keinen Effekt auf Bild-Leseoperationen (Siehe [[glEnable#GL_INTERLACE_READ_I3D|GL_INTERLACE_READ_I3D]].&lt;br /&gt;
&lt;br /&gt;
=== GL_INTERLACE_READ_I3D ===&lt;br /&gt;
Wenn aktiviert, werden Bilder im Framepuffer als interlaced angesehen. Jede Reihe ''m'' des Bildes wird behandelt als wäre sie Reihe 2 * ''m''. Wenn das Bild im Framepuffer eine Höhe von ''h'' Reiehen hat, wird dieses effektiv auf eine Höhe von 2 * ''h'' - 1 vergrößert. Dieses Token betrifft nur [[glReadPixels]] und [[glCopyPixels]].&lt;br /&gt;
&lt;br /&gt;
=== GL_LIGHTi ===&lt;br /&gt;
Wenn aktiviert, wird die Lichtquelle ''i'' in die Berechnung der Beleuchtungsgleichung mit einbezogen. Siehe [[glLightModel]] und [[glLight]].&lt;br /&gt;
&lt;br /&gt;
=== GL_LIGHTING ===&lt;br /&gt;
Wenn aktiviert, werden die aktuellen Beleuchtungsparameter genutzt um die Vertex- oder Indexfarbe zu berechnen. Ansonsten wird einfach die aktuelle Farbe zw. der aktuelle Index zugewiesen. Siehe [[glMaterial]], [[glLightModel]] und [[glLight]].&lt;br /&gt;
&lt;br /&gt;
=== GL_LINE_SMOOTH ===&lt;br /&gt;
Wenn aktiviert, werden Linien mit dem korrekten rechtwinkligen &amp;quot;Eecken&amp;quot; gerendert. Dieser Effekt ist nur bei [[glLineWidth|breiten Linen]] von Bedeutung. Siehe [[OpenGL_Smooth]]&lt;br /&gt;
{|&lt;br /&gt;
! Aktiviert&lt;br /&gt;
! Deaktiviert&lt;br /&gt;
|-&lt;br /&gt;
|[[Bild:GL LINE SMOOTH_aktiviert.png]]&lt;br /&gt;
|[[Bild:GL LINE SMOOTH deaktiviert.png]]&lt;br /&gt;
|}&lt;br /&gt;
''In vierfacher Vergrößerung''&lt;br /&gt;
&lt;br /&gt;
=== GL_LINE_STIPPLE ===&lt;br /&gt;
Wenn aktiviert, wird das aktuelle Punktierungsmuster für das Zeichnen von Linien verwendet. Siehe [[glLineStipple]].&lt;br /&gt;
&lt;br /&gt;
=== GL_MAP1_COLOR_4 ===&lt;br /&gt;
Wenn aktiviert, generieren Aufrufe an [[glEvalCoord1]], [[glEvalMesh1]] und [[glEvalPoint1]] RGBA-Werte. Siehe [[glMap1]].&lt;br /&gt;
&lt;br /&gt;
=== GL_MAP1_INDEX ===&lt;br /&gt;
Wenn aktiviert, generieren Aufrufe an [[glEvalCoord1]], [[glEvalMesh1]] und [[glEvalPoint1]] Farb-Indizes. Siehe [[glMap1]].&lt;br /&gt;
&lt;br /&gt;
=== GL_MAP1_NORMAL ===&lt;br /&gt;
Wenn aktiviert, generieren Aufrufe an [[glEvalCoord1]], [[glEvalMesh1]] und [[glEvalPoint1]] Normalen. Siehe [[glMap1]].&lt;br /&gt;
&lt;br /&gt;
=== GL_MAP1_TEXTURE_COORD_1 ===&lt;br /&gt;
Wenn aktiviert, generieren Aufrufe an [[glEvalCoord1]], [[glEvalMesh1]] und [[glEvalPoint1]] s-Texturkoordinaten. Siehe [[glMap1]].&lt;br /&gt;
&lt;br /&gt;
=== GL_MAP1_TEXTURE_COORD_2 ===&lt;br /&gt;
Wenn aktiviert, generieren Aufrufe an [[glEvalCoord1]], [[glEvalMesh1]] und [[glEvalPoint1]] s- und t-Texturkoordinaten. Siehe [[glMap1]].&lt;br /&gt;
=== GL_MAP1_TEXTURE_COORD_3 ===&lt;br /&gt;
Wenn aktiviert, generieren Aufrufe an [[glEvalCoord1]], [[glEvalMesh1]] und [[glEvalPoint1]] s-, t- und r-Texturkoordinaten. Siehe [[glMap1]].&lt;br /&gt;
&lt;br /&gt;
=== GL_MAP1_TEXTURE_COORD_4 ===&lt;br /&gt;
Wenn aktiviert, generieren Aufrufe an [[glEvalCoord1]], [[glEvalMesh1]] und [[glEvalPoint1]] s-, t-, r- und q-Texturkoordianten. Siehe [[glMap1]].&lt;br /&gt;
&lt;br /&gt;
=== GL_MAP1_VERTEX_3 ===&lt;br /&gt;
Wenn aktiviert, generieren Aufrufe an [[glEvalCoord1]], [[glEvalMesh1]] und [[glEvalPoint1]] x-, y- und z-Vertexkoordinaten. Siehe [[glMap1]].&lt;br /&gt;
&lt;br /&gt;
=== GL_MAP1_VERTEX_4 ===&lt;br /&gt;
Wenn aktiviert, generieren Aufrufe an [[glEvalCoord1]], [[glEvalMesh1]] und [[glEvalPoint1]] x-, y-, z- und w-Vertexkoordinaten. Siehe [[glMap1]].&lt;br /&gt;
&lt;br /&gt;
=== GL_MAP2_COLOR_4 ===&lt;br /&gt;
Wenn aktiviert, generieren Aufrufe an [[glEvalCoord2]], [[glEvalMesh2]] und [[glEvalPoint2]] RGBA-Werte. Siehe [[glMap2]].&lt;br /&gt;
&lt;br /&gt;
=== GL_MAP2_INDEX ===&lt;br /&gt;
Wenn aktiviert, generieren Aufrufe an [[glEvalCoord2]], [[glEvalMesh2]] und [[glEvalPoint2]] Farb-Indizes. Siehe [[glMap2]].&lt;br /&gt;
&lt;br /&gt;
=== GL_MAP2_NORMAL ===&lt;br /&gt;
Wenn aktiviert, generieren Aufrufe an [[glEvalCoord2]], [[glEvalMesh2]] und [[glEvalPoint2]] Normale. Siehe [[glMap2]].&lt;br /&gt;
&lt;br /&gt;
=== GL_MAP2_TEXTURE_COORD_1 ===&lt;br /&gt;
Wenn aktiviert, generieren Aufrufe an [[glEvalCoord2]], [[glEvalMesh2]] und [[glEvalPoint2]] s-Texturkoordinaten. Siehe [[glMap2]].&lt;br /&gt;
&lt;br /&gt;
=== GL_MAP2_TEXTURE_COORD_2 ===&lt;br /&gt;
Wenn aktiviert, generieren Aufrufe an [[glEvalCoord2]], [[glEvalMesh2]] und [[glEvalPoint2]] s- und t-Texturkoordinaten. Siehe [[glMap2]].&lt;br /&gt;
&lt;br /&gt;
=== GL_MAP2_TEXTURE_COORD_3 ===&lt;br /&gt;
Wenn aktiviert, generieren Aufrufe an [[glEvalCoord2]], [[glEvalMesh2]] und [[glEvalPoint2]] s-, t- und r-Texturkoordinaten. Siehe [[glMap2]].&lt;br /&gt;
&lt;br /&gt;
=== GL_MAP2_TEXTURE_COORD_4 ===&lt;br /&gt;
Wenn aktiviert, generieren Aufrufe an [[glEvalCoord2]], [[glEvalMesh2]] und [[glEvalPoint2]] s-, t-, r- und q-Texturkoordinaten. Siehe [[glMap2]].&lt;br /&gt;
&lt;br /&gt;
=== GL_MAP2_VERTEX_3 ===&lt;br /&gt;
Wenn aktiviert, generieren Aufrufe an [[glEvalCoord2]], [[glEvalMesh2]] und [[glEvalPoint2]] x, y und z-Vertexkoordinaten. Siehe [[glMap2]].&lt;br /&gt;
&lt;br /&gt;
=== GL_MAP2_VERTEX_4 ===&lt;br /&gt;
Wenn aktiviert, generieren Aufrufe an [[glEvalCoord2]], [[glEvalMesh2]] und [[glEvalPoint2]] x, y, z- und w-Vertexkoordinaten. Siehe [[glMap2]].&lt;br /&gt;
&lt;br /&gt;
=== GL_MULTISAMPLE_EXT ===&lt;br /&gt;
Wenn aktiviert, bekommt jeder Pixel im Framepuffer GL_SAMPLES_EXT-Samplepunkte zugewiesen. with it.&lt;br /&gt;
&lt;br /&gt;
=== GL_NORMALIZE ===&lt;br /&gt;
Wenn aktiviert, werden via [[glNormal]] angegebene Normalen nach ihrer Transformation auf Einheitslänge skaliert. Siehe [[glNormal]].&lt;br /&gt;
&lt;br /&gt;
=== GL_OCCLUSION_TEST_EXT ===&lt;br /&gt;
Wenn aktiviert, wird der Ausschluß-Status (Occlusion, Deutsche Übersetzung ist leider nicht gebräuchlich --[[Benutzer:Sascha Willems|Sascha Willems]] 13:05, 9. Jul 2004 (CEST)) je nach Tiefentest aktualisiert (siehe [[glDepthFunc]]). Der Ausschluß-Status kann mit [[glGetBooleanv]] ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
=== GL_PIXEL_TEX_GEN_EXT ===&lt;br /&gt;
Wenn aktiviert, werden die RGBA-Farben des Bildes genutzt um Texturkoordinaten für das Fragment zu generieren. Siehe [[glPixelTexGenEXT]].&lt;br /&gt;
&lt;br /&gt;
=== GL_POINT_SMOOTH ===&lt;br /&gt;
Wenn aktiviert, werden Punkte gefiltert gezeichnet. Ansonsten werden ungefilterte Punkte gerendert. Siehe [[glPointSize]], [[OpenGL_Smooth]].&lt;br /&gt;
&lt;br /&gt;
=== GL_POLYGON_OFFSET_FILL ===&lt;br /&gt;
Wenn aktiviert und das Polygon im GL_FILL-Modus gerendert wird, wird ein Versatz zum Tiefenwert der Fragmente des Polygons addiert, bevor der Tiefentest stattfindet. Siehe [[glPolygonOffset]].&lt;br /&gt;
&lt;br /&gt;
=== GL_POLYGON_OFFSET_LINE ===&lt;br /&gt;
Wenn aktiviert und das Polygon im GL_LINE-Modus gerendert wird, wird ein Versatz zum Tiefenwert der Fragmente des Polygons addiert, bevor der Tiefentest stattfindet. Siehe [[glPolygonOffset]].&lt;br /&gt;
&lt;br /&gt;
=== GL_POLYGON_OFFSET_POINT ===&lt;br /&gt;
Wenn aktiviert, wird ein Versatz zu den Tiefenwerten der Fragmente eines Polygons addiert, bevor der Tiefentest stattfindet, wenn es im GL_POINT-Modus gerendert wird. Siehe [[glPolygonOffset]].&lt;br /&gt;
&lt;br /&gt;
=== GL_POLYGON_SMOOTH ===&lt;br /&gt;
Wenn aktiviert, werden Polygone mit korrekter Filterung gezeichnet, indem der Alphawert eines [[Fragment]]es entsprechend der Deckung gesetzt wird. [[Blenden|Blending]] muss ebenfalls aktiviert sein um korrekte Resultate zu erhalten. Siehe [[OpenGL_Smooth]]&lt;br /&gt;
{{Hinweis|Funktion ist meist nicht in Hardware verfügbar, es wird häufig auf Softwaremodus umgeschalten und auch dort nicht immer korrekt gezeichnet.}}&lt;br /&gt;
&lt;br /&gt;
=== GL_POLYGON_STIPPLE ===&lt;br /&gt;
Wenn aktiviert, wird das aktuelle Polygon-Punktierungs-Muster zum Rendern der Polygone genutzt. Siehe [[glPolygonStipple]].&lt;br /&gt;
&lt;br /&gt;
=== GL_POST_COLOR_MATRIX_COLOR_TABLE_EXT ===&lt;br /&gt;
Wenn aktiviert, werden Farbbild-Komponentne in die Farbtabelle gelegt die nach der Farbmatrix kommt. Siehe [[glColorTable]].&lt;br /&gt;
&lt;br /&gt;
=== GL_POST_CONVOLUTION_COLOR_TABLE_EXT ===&lt;br /&gt;
Wenn aktiviert, werden Farbbild-Komponenten in eine Farbtabelle gelegt die nach der Windung, aber vor der Farbmatrix kommt. Siehe [[glColorTable]].&lt;br /&gt;
&lt;br /&gt;
=== GL_RESCALE_NORMAL_EXT ===&lt;br /&gt;
Wenn aktiviert, werden Normalen mit einem Reskalierungsfaktor multipliziert, nachdem sie in den Augenraum transformiert wurden und bevor sie normalisiert werden. Dieser Faktor wird aus der obersten Reihe der inversen umgestellten Modelansichtsmatrix berechnet.&lt;br /&gt;
&lt;br /&gt;
=== GL_SAMPLE_ALPHA_TO_MASK_EXT ===&lt;br /&gt;
Wenn aktiviert, wird der Alphawert eines Fragmentes genutzt, um einen temporären Maskenwert zu erstellen, welcher mit dem Maskenwert des Fragmentes verUNDet wird.&lt;br /&gt;
&lt;br /&gt;
=== GL_SAMPLE_ALPHA_TO_ONE_EXT ===&lt;br /&gt;
Wenn aktiviert, wird der Alphawert der Fragmente durch den maximal verfügbaren Alphawert ersetzt.&lt;br /&gt;
&lt;br /&gt;
=== GL_SAMPLE_MASK_EXT ===&lt;br /&gt;
Wenn aktiviert, wird der Wert von '''GL_SAMPLE_MASK_VALUE_EXT''' genutzt, um temporäre Maskenwerte zu erstellen, die dann mit den Maskenwerten der Fragmente geUNDet werden. (AND-Verknüpft werden)&lt;br /&gt;
&lt;br /&gt;
=== GL_SCISSOR_TEST ===&lt;br /&gt;
Wenn aktiviert, werden Fragmente verworfen die ausserhalb des Scissor-Rechtecks liegen. Siehe [[glScissor]].&lt;br /&gt;
&lt;br /&gt;
=== GL_SEPARABLE_2D_EXT ===&lt;br /&gt;
Wenn aktiviert und GL_CONVOLUTION_2D_EXT deaktiviert ist, wird zweidimensionale Wicklung mit separierbarem Filter während des Pixeltransfers durchgeführt. Siehe [[glSeparableFilter2D]].&lt;br /&gt;
&lt;br /&gt;
=== GL_STENCIL_TEST ===&lt;br /&gt;
Wenn aktiviert, werden Stempeltests durchgeführt und der Stencilpuffer aktualisiert. Siehe [[glStencilFunc]] und [[glStencilOp]].&lt;br /&gt;
&lt;br /&gt;
=== GL_TEXTURE_1D ===&lt;br /&gt;
Wenn aktiviert, wird eindimensionale Texturierung angewandt (es sei denn zweidimensionale Texturierung wurde auch aktiviert). Siehe [[glTexImage1D]].&lt;br /&gt;
&lt;br /&gt;
=== GL_TEXTURE_2D ===&lt;br /&gt;
Wenn aktiviert, wird zweidimensionale Texturierung angewandt (es sei denn dreidimensionale Texturierung wurde auch aktiviert). Siehe [[glTexImage2D]].&lt;br /&gt;
&lt;br /&gt;
=== GL_TEXTURE_3D(''_EXT'') ===&lt;br /&gt;
Wenn aktiviert, wird dreidimensionale Texturierung angewandt. Siehe [[glTexImage3D]].&lt;br /&gt;
&lt;br /&gt;
=== GL_TEXTURE_COLOR_TABLE_EXT ===&lt;br /&gt;
Wenn aktiviert, wird die gefilterte Texturenfarbe an die Farbtabelle für Texturen angepasst, bevor die Umgebung mit der Fragmentfarbe vermischt wird. Siehe [[glColorTable]].&lt;br /&gt;
&lt;br /&gt;
=== GL_TEXTURE_GEN_Q ===&lt;br /&gt;
Wenn aktiviert, wird die q-Texturkoordinate anhand der via [[glTexGen]] definierten Funktion zur Texturgenerierung berechnet. Ansonsten wird die aktuell angegebene q-Texturkoordinate genutzt. Siehe [[glTexGen]].&lt;br /&gt;
&lt;br /&gt;
=== GL_TEXTURE_GEN_R ===&lt;br /&gt;
Wenn aktiviert, wird die r-Texturkoordinate anhand der via [[glTexGen]] definierten Funktion zur Texturgenerierung berechnet. Ansonsten wird die aktuell angegebene r-Texturkoordinate genutzt. Siehe [[glTexGen]].&lt;br /&gt;
&lt;br /&gt;
=== GL_TEXTURE_GEN_S ===&lt;br /&gt;
Wenn aktiviert, wird die s-Texturkoordinate anhand der via [[glTexGen]] definierten Funktion zur Texturgenerierung berechnet. Ansonsten wird die aktuell angegebene s-Texturkoordinate genutzt. Siehe [[glTexGen]].&lt;br /&gt;
&lt;br /&gt;
=== GL_TEXTURE_GEN_T ===&lt;br /&gt;
Wenn aktiviert, wird die t-Texturkoordinate anhand der via [[glTexGen]] definierten Funktion zur Texturgenerierung berechnet. Ansonsten wird die aktuell angegebene t-Texturkoordinate genutzt. Siehe [[glTexGen]].&lt;br /&gt;
&lt;br /&gt;
== Erweiterungen ==&lt;br /&gt;
Einige Routinen und Konstanten für diese Funktion sind Teil einer Erweiterung, also nicht Teil des GL-Kerns. Die folgenden Erweiterungen müssen in der durch [[glGetString]] mit dem Argument '''GL_EXTENSIONS''' gelieferten Zeichenkette enthalten sein, damit diese genutzt werden können.&lt;br /&gt;
&lt;br /&gt;
=== GL_EXT_color_table ===&lt;br /&gt;
'''GL_COLOR_TABLE_EXT''', '''GL_POST_CONVOLUTION_COLOR_TABLE_EXT''' und '''GL_POST_COLOR_MATRIX_COLOR_TABLE_EXT''' sind Teil der Erweiterung [[GL_EXT_color_table]].&lt;br /&gt;
&lt;br /&gt;
=== GL_EXT_convolution ===&lt;br /&gt;
'''GL_CONVOLUTION_1D_EXT''', '''GL_CONVOLUTION_2D_EXT''' und '''GL_SEPARABLE_2D_EXT''' sind Teil der Erweiterung [[GL_EXT_convolution]].&lt;br /&gt;
&lt;br /&gt;
=== GL_EXT_fog_offset ===&lt;br /&gt;
'''GL_FOG_OFFSET_EXT''' ist Teil der Erweiterung [[GL_EXT_fog_offset]].&lt;br /&gt;
&lt;br /&gt;
=== EXT_interlace ===&lt;br /&gt;
'''GL_INTERLACE_EXT''' ist Teil der Erweiterung [[GL_EXT_interlace]].&lt;br /&gt;
 &lt;br /&gt;
=== EXT_interlace_read ===&lt;br /&gt;
'''GL_INTERLACE_READ_I3D''' ist Teil der Erweiterung [[GL_EXT_interlace_read]].&lt;br /&gt;
&lt;br /&gt;
=== GL_EXT_multisample ===&lt;br /&gt;
'''GL_MULTISAMPLE_EXT''', '''GL_SAMPLE_ALPHA_TO_MASK_EXT''', '''GL_SAMPLE_ALPHA_TO_ONE_EXT''' und '''GL_SAMPLE_MASK_EXT''' sind Teil der Erweiterung  [[GL_EXT_multisample]].&lt;br /&gt;
&lt;br /&gt;
=== GL_EXT_occlusion_test ===&lt;br /&gt;
'''GL_OCCLUSION_TEST_EXT''' ist Teil der Erweiterung [[GL_EXT_occlusion_test]].&lt;br /&gt;
&lt;br /&gt;
=== GL_EXT_pixel_texture ===&lt;br /&gt;
'''GL_PIXEL_TEX_GEN_EXT''' ist Teil der Erweiterung [[GL_EXT_pixel_texture]].&lt;br /&gt;
&lt;br /&gt;
=== GL_EXT_rescale_normal ===&lt;br /&gt;
'''GL_RESCALE_NORMAL_EXT''' ist Teil der Erweiterung [[GL_EXT_rescale_normal]].&lt;br /&gt;
&lt;br /&gt;
=== GL_EXT_texture3D ===&lt;br /&gt;
'''GL_TEXTURE_3D_EXT''' ist Teil der Erweiterung [[GL_EXT_texture3D]].&lt;br /&gt;
&lt;br /&gt;
=== GL_EXT_texture_color_table ===&lt;br /&gt;
'''GL_TEXTURE_COLOR_TABLE_EXT''' ist Teil der Erweiterung [[GL_EXT_texture_color_table]]. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Fehlermeldungen ==&lt;br /&gt;
'''GL_INVALID_ENUM''' wird generiert, wenn ''cap'' kein gültiges Token ist.&lt;br /&gt;
&lt;br /&gt;
'''GL_INVALID_OPERATION''' wird generiert, wenn [[glPixelTransfer]] zwischen [[glBegin]] und dem passenden [[glEnd]] aufgerufen wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  Zugehörige Wertrückgaben ==&lt;br /&gt;
[[glGet]]&lt;br /&gt;
&lt;br /&gt;
[[glIsEnabled]]&lt;br /&gt;
&lt;br /&gt;
(Die zu übergebenden Argumente können in der Beschreibung zu den beiden Funktionen nachgelesen werden.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
[[glAlphaFunc]], [[glBitmap]], [[glBlendFunc]], [[glClipPlane]], [[glColorMaterial]], [[glColorTable]], [[glCopyColorTable]], [[glCopyPixels]], [[glCopyTexImage1D]], [[glCopyTexImage2D]], [[glCopyTexSubImage1D]], [[glCopyTexSubImage2D]], [[glCopyTexSubImage3D]], [[glCullFace]], [[glDepthFunc]], [[glDepthRange]], [[glDrawPixels]], [[glEnableClientState]], [[glFog]], [[glGet]], [[glGetString]], [[glIsEnabled]], [[glLight]], [[glLightModel]], [[glLineWidth]], [[glLineStipple]], [[glLogicOp]], [[glMap1]], [[glMap2]], [[glMaterial]], [[glNormal]], [[glPointSize]], [[glPolygonMode]], [[glPolygonOffset]], [[glPolygonStipple]], [[glSampleMaskEXT]], [[glScissor]], [[glStencilFunc]], [[glStencilOp]], [[glTexGen]], [[glTexImage1D]], [[glTexImage2D]], [[glTexImage3D]], [[glTexSubImage1D]], [[glTexSubImage2D]], [[glTexSubImage3D]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:GL|Enable]]&lt;br /&gt;
[[Kategorie:GL1.0|Enable]]&lt;br /&gt;
[[Kategorie:GL3|Enable]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_glsl&amp;diff=25729</id>
		<title>Tutorial glsl</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_glsl&amp;diff=25729"/>
				<updated>2012-12-16T10:41:16Z</updated>
		
		<summary type="html">&lt;p&gt;End: nur zwei kleine Fehler ^^&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 einfache Shader zu schreiben und auch in ihren Programmen zu nutzen. Außerdem 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 Originalspezifikation])&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 Originalspezifikation])&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 Originalspezifikation])&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 Originalspezifikation])&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 also 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;
Außerdem 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(pShader, 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;
 glUseProgram(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. Außerdem 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 vorzeichenbehafteter Integerwert&lt;br /&gt;
|-&lt;br /&gt;
|uint 	&lt;br /&gt;
|Vorzeichenbehafteter vorzeichenloser 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 vorzeichenbehafteter Integervektor&lt;br /&gt;
|-&lt;br /&gt;
|ivec3 	&lt;br /&gt;
|3-Komponenten vorzeichenbehafteter Integervektor&lt;br /&gt;
|-&lt;br /&gt;
|ivec4 	&lt;br /&gt;
|4-Komponenten vorzeichenbehafteter Integervektor&lt;br /&gt;
|-&lt;br /&gt;
|uvec2 	&lt;br /&gt;
|2-Komponenten vorzeichenloser Integervektor&lt;br /&gt;
|-&lt;br /&gt;
|uvec3 	&lt;br /&gt;
|3-Komponenten vorzeichenloser Integervektor&lt;br /&gt;
|-&lt;br /&gt;
|uvec4 	&lt;br /&gt;
|4-Komponenten vorzeichenloser 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;
|matMxN 	&lt;br /&gt;
|Matrix mit M Spalten und N Zeilen&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[i].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 außen 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, außerdem entfällt dann logischerweise das {{INLINE_CODE|return}}. Falls die Funktion eines ihrere Argumente nach außen ü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 außen.&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 x)&lt;br /&gt;
: Gibt den Sinus von x zurück, wobei x in Radien angegeben wird.&lt;br /&gt;
* genType cos (genType x)&lt;br /&gt;
: Gibt den Kosinus von x zurück, wobei x in Radien angegeben wird.&lt;br /&gt;
* genType tan (genType x)&lt;br /&gt;
: Gibt den Tangens von x zurück, wobei x 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 Arckosinus 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;
==Hyperbolisch==&lt;br /&gt;
* genType sinh (genType x)&lt;br /&gt;
: Gibt den Sinus Hyperbolicus von x zurück. (return = (exp(x) - exp(-x)) * 0.5; )&lt;br /&gt;
* genType cosh (genType x)&lt;br /&gt;
: Gibt den Kosinus Hyperbolicus von x zurück. (return = (exp(x) + exp(-x)) * 0.5; )&lt;br /&gt;
* genType tanh (genType x)&lt;br /&gt;
: Gibt den Tangens Hyperbolicus von x zurück. (return = (exp(x) - exp(-x)) / (exp(x) + exp(-x)); )&lt;br /&gt;
* genType asinh (genType angle)&lt;br /&gt;
: Gibt den Areasinus Hyperbolicus von x zurück. (return = log(x + sqrt(x * x + 1.0)); )&lt;br /&gt;
* genType acosh (genType angle)&lt;br /&gt;
: Gibt den Areakosinus Hyperbolicus von x zurück. (return = log(x + sqrt(x * x - 1.0)); )&lt;br /&gt;
* genType atanh (genType x)&lt;br /&gt;
: Gibt den Areatangens Hyperbolicus von x zurück. (return = log((1.0 + x) / (1.0 - x)) * 0.5; )&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 exp (genType x)&lt;br /&gt;
: Gibt e(Eulerischezahl ≈ 2.7182) hoch x zurück.&lt;br /&gt;
* genType log (genType x)&lt;br /&gt;
: Gibt den Logarithmus zur Basis e(Eulerischezahl ≈ 2.7182) von x 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;
==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 roundeven(genType x)&lt;br /&gt;
: Rundet auf den nächsten Integerwert und gibt diesen zuück. Bei &amp;quot;.5&amp;quot; Werten wird zur nächsten geraden Zahl gerundet.&lt;br /&gt;
* genType round(genType x)&lt;br /&gt;
: Rundet auf den nächsten Integerwert und gibt diesen zuück. &amp;quot;.5&amp;quot; Werte werden je nach Implementation anders behandelt.&lt;br /&gt;
* genType trunc(genType x)&lt;br /&gt;
: Rundet auf den nächsten Integerwert dessen Absoluterwert nicht größer ist als der Absolutewert von x&lt;br /&gt;
* genType floor (genType x)&lt;br /&gt;
: Gibt denn größten Integerwert zurück, der kleiner oder gleich x ist.&lt;br /&gt;
* genType ceil (genType x)&lt;br /&gt;
: Gibt den kleinsten 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. (result = 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 .  (return = min(minVal, max(maxVal, x)))&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. (result = 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;= edge0 und 1.0 wenn x &amp;gt;= edge1. Dazwischen wird eine weiche Hermite Interpolation durchgeführt.&lt;br /&gt;
::float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);&lt;br /&gt;
::result = t * t * (3.0 - 2.0 * t)&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 l, genType N)&lt;br /&gt;
: Gibt den an der Flächenausrichtung N reflektierten Vektor I zurück. (result = l - 2.0 * dot(N,I) * N; )&lt;br /&gt;
* genType refract (genType l, genType N, float eta)&lt;br /&gt;
: Gibt den an der Flächenausrichtung N mit dem Brechungsindex eta gebrochenen Vektor l zurück. &lt;br /&gt;
::gentype k = 1.0 - eta * eta * (1.0 - dot(N, l) * dot(N, l))&lt;br /&gt;
::if (k &amp;lt; 0.0)&lt;br /&gt;
:::result = 0.0&lt;br /&gt;
::else &lt;br /&gt;
:::result = eta * l - (eta * dot(N, l) * sqrt(k)) * N&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;
* mat transpose (mat m)&lt;br /&gt;
: Gibt die transponierte Matrix von m zurück.&lt;br /&gt;
* mat invert (mat m)&lt;br /&gt;
: Gibt die invertierte Matrix von m zurück. Also die Matrix, die mit m multipliziert die Normalmatrix ergeben würde.&lt;br /&gt;
* mat outerProduct(vec c, vec r)&lt;br /&gt;
: Gibt eine eine Matrix als Ergebnis der linearen (return[m, n] = c[m] * r[n])-Operation zurück.&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;
: '''Texturegröße :'''&lt;br /&gt;
Mit den textureSize-Befehlen kann die Größe einer Textur bestimmt werden, wobei lod das Mipmaplevel angibt:&lt;br /&gt;
*int textureSize(sampler1D sampler, int lod)&lt;br /&gt;
*ivec2 textureSize(sampler2D sampler, int lod)&lt;br /&gt;
*ivec3 textureSize(sampler3D sampler, int lod)&lt;br /&gt;
*ivec2 textureSize(samplerCube sampler, int lod)&lt;br /&gt;
*int textureSize(sampler1DShadow sampler, int lod)&lt;br /&gt;
*ivec2 textureSize(sampler2DShadow sampler, int lod)&lt;br /&gt;
&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;
{{Vorlage:Hinweis|Der Uniform-Integer für den Sampler referenziert '''nicht''' den Namen (die ID) des Texturobjektes, sondern die Nummer der Texturunit.}}&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 nur die 3DLabs 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;
Außerdem 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-Shader 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 gilt inzwischen auch offizielle die Shadersprache für 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>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_SDL_Einstieg&amp;diff=25728</id>
		<title>Tutorial SDL Einstieg</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_SDL_Einstieg&amp;diff=25728"/>
				<updated>2012-12-16T10:30:21Z</updated>
		
		<summary type="html">&lt;p&gt;End: siehe Forumsbeitrag http://www.delphigl.com/forum/viewtopic.php?f=8&amp;amp;p=92541#p92541&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=SDL - Simple Directmedia Layer=&lt;br /&gt;
==Vorwort==&lt;br /&gt;
&lt;br /&gt;
Ich weiß, dass ich mich damit unbeliebt machen werde,aber... Was haben GLUT und DirectX gemeinsam? Na, Na! Wer weiß es? Richtig, sie haben beide keine Zukunft mehr. ;) Na gut, war nicht wirklich der Reißer, aber zumindest war es der Gedanke, den ich hatte als ich mich das erste Mal mit dem Simple DirectMedia Layer befaßt habe (kurz SDL). Das Ganze hat nichts mit einem Breitbandanschluß oder einer neuen Designer-Droge zu tun, sondern es handelt sich dabei um eine plattformübergreifende API.&lt;br /&gt;
&lt;br /&gt;
Die Idee die dahinter steckt ist genauso simpel wie genial! DirectX ist eine wirklich hervorragende API, allerdings hat das ganze ein Nachteil! Es kommt von Microsoft und ist nur für Windows verfügbar. Die OpenSource-Gemeinde müsste vor Scham im Boden versinken, wenn man dazu nicht passend ein Projekt ins Leben rufen würde, dass diesem Defizit ein Ende bereitet. Bei SDL handelt es sich um einen abstrakten Layer der auf jeder Plattform gleich ist und dann im Hintergrund die Befehle entsprechend dem darunter befindlichen OS umwandelt. Der Vorteil für den Programmierer ist klar: Wer seine Anwendung mit SDL schreibt, kann diese auch sehr schnell auf andere Systeme portieren. Eine reine SDL Anwendung in Delphi geschrieben, sollte sich also ohne Probleme auch unter Kylix kompilieren lassen und das ganz ohne den ganzen Source-Code umzubauen. Das Ganze ist zwar nicht so komplex wie DirectX von Microsoft, hat aber mindestens genauso viel Potenzial! Wer sich nun fragt, wozu das Ganze für ihn interessant sein soll, hat nicht mitgedacht! SDL für Fensterverwaltung und Benutzerinteraktion und dazu die geilste und portabelste Grafik-API, die es auf der Welt gibt : OpenGL! ;)&lt;br /&gt;
&lt;br /&gt;
Ich hoffe sehr, dass ich mit diesem Artikel einige von euch für die Kombination SDL und OpenGL begeistern kann, denn gerade wir Delpher haben auch im Linux-Sektor eine Menge Potenzial, dass leider nicht genutzt wird! In diesem Sinne viel Erfolg! ;)&lt;br /&gt;
&lt;br /&gt;
==Initialisierung von SDL==&lt;br /&gt;
===SDL! Bitte kommen!===&lt;br /&gt;
&lt;br /&gt;
Wer sich bereits einmal mit der Programmierung der Windows-API beschäftigt hat, wird hier sicherlich nichts stark Befremdliches vorfinden. Sicherlich, alles heißt irgendwie anders, aber dafür ist das Ganze auch um einiges leichter zu handhaben als die Fenstererzeugung mit der WinAPI. Direkt im Hauptprogramm fangen wir erst einmal damit an SDL zu initialisieren:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt; SDL_Init ( SDL_INIT_VIDEO );&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf diese Weise teilen wir unserem Programm mit welche Teile von SDL initialisiert werden sollen. In unserem Beispiel die Bildschirmausgabe. Wir können als Parameter auch weitere Subsysteme übergeben z. B:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt; SDL_Init ( SDL_INIT_VIDEO or SDL_INIT_TIMER );&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dazu aber später mehr! Wie immer ist es wichtig, dass man nicht nur Code an den Computer schickt, sondern auch darauf vorbereitet ist dass eventuell ein Fehler aufgetreten ist. Dieser soll dann natürlich auch vom Programm abgefangen werden!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;// Initalisieren vom Simple DirectMedia Layer&lt;br /&gt;
  if ( SDL_Init( SDL_INIT_VIDEO ) &amp;lt; 0 ) then&lt;br /&gt;
  begin&lt;br /&gt;
    Log.LogError('Initalisierung von SDL schlug fehl: '+SDL_GetError,'SDL_Init');&lt;br /&gt;
    Quit_App;&lt;br /&gt;
  end;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sollte ein negativer Wert als Rückgabe erfolgen, so ist ein Fehler aufgetreten. Wir machen uns in diesem Fall die Fehlerbehandlung sehr einfach. Wir nutzen das im SDL integrierte Log-File und geben dort eine Fehlermeldung aus. Um die Orientierung zu erleichtern geben wir noch das Modul an in dem der Fehler auftrat. In diesem Fall eben bei der Initialisierung von SDL. Zu {{INLINE_CODE|Quit_App}} kommen wir später. Es handelt sich dabei um eine selbst geschriebene Funktion zum Freigeben der Ressourcen.&lt;br /&gt;
&lt;br /&gt;
===Grafikkarten sind gar nicht so anders===&lt;br /&gt;
&lt;br /&gt;
Sicherlich ist es nicht jedem Leser hier bewusst, dass man für eine grafische Ausgabe auch eine Grafikkarte braucht. Deswegen werde ich hier noch einmal explizit darauf eingehen! :) Da SDL uns zur Verfügung steht können wir es auch verwenden um uns Informationen über die eingebaute Grafikkarte einzuholen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;// Information über Grafikkarte einholen&lt;br /&gt;
  videoInfo := SDL_GetVideoInfo;&lt;br /&gt;
  if ( videoInfo = nil ) then&lt;br /&gt;
  begin&lt;br /&gt;
    Log.LogError('Grafikkarte ließ sich nicht abfragen: '+SDL_GetError,'SDL_Init' );&lt;br /&gt;
    Quit_App;&lt;br /&gt;
  end;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei VideoInfo handelt es sich um eine {{INLINE_CODE|PSDL_VideoInfo}}-Struktur. Konnten die Informationen erfolgreich abgefragt werden, so sind alle interessanten Informationen in dieser Struktur enthalten, z.B. wie viel MB Speicher diese hat! Ist die Rückgabe undefiniert, greift natürlich unsere Fehlerbehandlung.&lt;br /&gt;
&lt;br /&gt;
===Die Suche nach dem wahren Pixelformat===&lt;br /&gt;
&lt;br /&gt;
Unser nächstes Ziel ist nun die Erzeugung der eigentlichen Zeichenfläche. Diese ist zu vergleichen mit dem Canvas eines Windows-Fensters. Natürlich müssen wir auch hier erst einige Einstellungen vornehmen!Immerhin wollen wir ja auch nicht ein paar 2D-Bilder á la DirectDraw rendern, sondern hardwarebeschleunigtes OpenGL!Also beginnen wir die Flags für die eigentliche Initalisierung zu sammeln:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;// Flags für den SDL-Grafikmodus setzen&lt;br /&gt;
  videoFlags := SDL_OPENGL or                  // OpenGL-Unterstützung aktivieren&lt;br /&gt;
                SDL_HWPALETTE;                 // Palette in Hardware speichern&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vermutlich wird sich niemand finden, der die Sinnhaftigkeit dieser Flags wirklich anzweifeln wird!Als nächstes ermitteln wir ob die Möglichkeit besteht den Speicher und die eigentliche Hardwarebeschleunigung auch zu nutzen. Ich denke nicht, dass jemand heutzutage noch darauf verzichtet wenn er es nicht muss ;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;// Kann das Surface in den Speicher?&lt;br /&gt;
  if ( videoInfo.hw_available &amp;lt;&amp;gt; 0 ) then&lt;br /&gt;
    videoFlags := videoFlags or SDL_HWSURFACE&lt;br /&gt;
  else&lt;br /&gt;
    videoFlags := videoFlags or SDL_SWSURFACE;&lt;br /&gt;
&lt;br /&gt;
  // Wird hardware blitting unterstützt?&lt;br /&gt;
  if ( videoInfo.blit_hw &amp;lt;&amp;gt; 0 ) then videoFlags := videoFlags or SDL_HWACCEL;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nun erfolgt die die Definition des PixelFormats dass für die Initialisierung von OpenGL unentbehrlich ist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;// Setzen der OpenGL-Attribute&lt;br /&gt;
  SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );&lt;br /&gt;
  SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );&lt;br /&gt;
  SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );&lt;br /&gt;
  SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );&lt;br /&gt;
  SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Farbwerte sollten so belassen werden. Der Tiefenbuffer wird auf 16 Bit festgelegt und ein BackBuffer soll auch erzeugt werden. Jeder der sich bereits einmal mit der Initialisierung beschäftigt hat, wird hier Gemeinsamkeiten finden und sich auch denken können wie man z.B. den Stencil-Buffer unter SDL setzt:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE,  8 );&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nun würden wir einen 8 Bit-Stencil-Buffer initialisieren. Gleiches gilt natürlich auch für den Akkumulations-Buffer!Damit haben wir alle Informationen gesammelt die wir brauchen um ein OpenGL-Fenster mit SDL zu erzeugen. Wenn man sich den Source Code ansieht, wird man merken, dass dieser um einiges schlanker ist als die Initalisierung der WinAPI und wir zudem auch noch plattformunabhängig sind!Einige kleinere Einstellungen nehmen wir allerdings noch vor. Nur kleine kosmetische Änderungen wie der Fenstertitel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;// Fenstertitel festlegen&lt;br /&gt;
  SDL_WM_SetCaption( WINDOWS_CAPTION , nil);&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Als einfacher String wird der Titelname übergeben, der zweite Paramter kann dazu verwendet werden ein Icon für die Leiste zu definieren. Auch können wir an dieser Stelle entscheiden ob der Benutzer in der Lage sein soll das Fenster in seiner Größe zu verändern. Standardgemäß ist dieses Feature deaktiviert, so dass die Fenstergröße immer gleich bleibt. Wollen wir ein Skalieren jedoch zulassen, übergeben wir einfach ein weiteres Video-Flag:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;videoflags := videoFlags or SDL_RESIZABLE;    // Enable window resizing&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nun haben wir alles beisammen und erzeugen unser Surface!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;videoflags := // Initalisierung der Surface&lt;br /&gt;
  surface := SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,videoflags );&lt;br /&gt;
  if ( surface = nil ) then&lt;br /&gt;
  begin&lt;br /&gt;
    Log.LogError('Erzeugen einer OpenGL-Zeichenfläche schlug fehl: '+SDL_GetError,'SDL_Init' );&lt;br /&gt;
    Quit_App;&lt;br /&gt;
  end;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ich denke nicht, dass es einer genaueren Erklärung bedarf was an dieser Stelle geschieht. Die Fenstergröße und Farbtiefe, sowie die Wunschliste unserer Video-Flags wird übergeben und wenn alles angeforderte auch möglich ist, erhalten wir von SDL ein {{INLINE_CODE|PSDL_Surface}} zurück mit der wir dann weiterarbeiten können (und auch werden) ;)&lt;br /&gt;
&lt;br /&gt;
==OpenGL Initalisierung==&lt;br /&gt;
&lt;br /&gt;
Die meisten Leute gehen von einem ziemlich komplexen, aufwendigen und vor allem schweren Vorfang aus, wenn sie hören dass jemand OpenGL initalisiert. Dabei ist OpenGL gar nicht schwer zu initalisieren. Das eigentliche Problem ist vielmehr an ein Fenster vom Betriebsystem zu kommen dass auch OpenGL unterstützt. Dies haben wir allerdings bereits erfolgreich im letzten Kapitel geschafft, so dass wir nun nur noch dafür sorgen müssen, dass wir Zugriff auf die OpenGL-Runtimes erhalten. Dies ist jedoch ziemlich leicht:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt; // Laden und Initalisieren von OpenGL&lt;br /&gt;
    InitOpenGL;&lt;br /&gt;
    ReadExtensions;&lt;br /&gt;
    ReadImplementationProperties;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fertig! Schon steht nichts mehr zwischen uns und dem OpenGL-Render-Spass ;) Allerdings empfiehlt es sich immer noch einige grundlegende Dinge einzustellen, einfach weil es hübscher gerendert wird ;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;    glClearColor(0.0, 0.0, 0.0, 1.0);         // Bildschirm löschen (schwarz)&lt;br /&gt;
    glClearDepth(1.0);                                    // Depth Buffer Setup&lt;br /&gt;
    glEnable(GL_DEPTH_TEST);                        // Aktiviert Depth Testing&lt;br /&gt;
    glDepthFunc(GL_LEQUAL);                          // Bestimmt den Typ des Depth Testing&lt;br /&gt;
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);// Qualitativ bessere Koordinaten&lt;br /&gt;
                                                       // Interpolation&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das wir OpenGL initalisiert haben ist sicher ein guter Anfang, allerdings wollen wir natürlich auch etwas sehen. Dafür ist es notwendig, dass wir unseren Viewport setzen und die Projektions-Matrix auf die entsprechende Größe transformieren. Aus taktischen Gründen schreiben wir uns dafür eine Funtion, die wir auch später beim Event-Handlung wiederverwenden können:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;function glResizeWindow( width : integer; height : integer ) : Boolean;&lt;br /&gt;
begin&lt;br /&gt;
// Verhindern von &amp;quot;Division by Zero&amp;quot;&lt;br /&gt;
  if ( height = 0 ) then height := 1;&lt;br /&gt;
&lt;br /&gt;
  // Viewport und Projektions-Matrix aktualisieren&lt;br /&gt;
  glViewport( 0, 0, width, height );&lt;br /&gt;
&lt;br /&gt;
  glMatrixMode( GL_PROJECTION );&lt;br /&gt;
    glLoadIdentity;&lt;br /&gt;
    gluPerspective( 45.0, width / height, 0.1, 100.0 );&lt;br /&gt;
  glMatrixMode( GL_MODELVIEW );&lt;br /&gt;
&lt;br /&gt;
  // Rücksetzen der World-Matrix&lt;br /&gt;
  glLoadIdentity;&lt;br /&gt;
&lt;br /&gt;
  // Vorgang erfolgreich&lt;br /&gt;
  result := true;&lt;br /&gt;
end;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All diese Vorgänge sollten für einen OpenGL-Programmierer nichts erschreckend neues sein. Damit der Viewport auch wirklich richtig gesetzt wird, rufen wir diese Funktion einfach einmal auf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;// Anpassen der Fenstergröße&lt;br /&gt;
  glResizeWindow( SCREEN_WIDTH, SCREEN_HEIGHT );&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Tag, Post!==&lt;br /&gt;
===Die Idee===&lt;br /&gt;
&lt;br /&gt;
Würden wir nun unser Programm in diesem Zustand starten, würden wir für den Bruchteil einer Sekunde ein Fenster angezeigt bekommen (das immerhin OpenGL-kompatibel ist! *g) und danach sofort wieder verschwindet. Überlegt man sich einmal ganz genau, was passiert, wird einem der Grund dafür schnell klar:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;begin&lt;br /&gt;
  // Initalisierung&lt;br /&gt;
  Init_SDL;&lt;br /&gt;
  Init_OpenGL;&lt;br /&gt;
&lt;br /&gt;
  // Anpassen der Fenstergröße&lt;br /&gt;
  glResizeWindow( SCREEN_WIDTH, SCREEN_HEIGHT );&lt;br /&gt;
end.&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unser Hauptprogramm initalisiert SDL, danach OpenGL, passt das Ganze an der Fenstergröße an und beendet danach die Aufgabenliste. Für Windows bedeutet dies, dass das Programm seine Verarbeitung abgeschlossen hat und somit nicht mehr gebraucht wird und schon findet sich unsere SDL-Anwendung auf dem Müllhaufen. (Um Mißverständnisse zu vermeiden: Nicht der Papierkorb und nicht aufm Desktop *g*). Wir brauchen also eine Schleife die sich immer wieder im Programm wiederholt und dafür sorgt, dass diese nur unter einer ganz bestimmten Bedingung verlassen wird und somit das Programm auch beendet wird. Man spricht von dem Main-Loop oder auch Game-Loop:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;begin&lt;br /&gt;
  // Initalisierung&lt;br /&gt;
  Init_SDL;&lt;br /&gt;
  Init_OpenGL;&lt;br /&gt;
&lt;br /&gt;
  // Anpassen der Fenstergröße&lt;br /&gt;
  glResizeWindow( SCREEN_WIDTH, SCREEN_HEIGHT );&lt;br /&gt;
&lt;br /&gt;
  // Eintritt in Main-Loop&lt;br /&gt;
  while ( Done &amp;lt;&amp;gt; -1 ) do&lt;br /&gt;
  begin&lt;br /&gt;
    glHandleEvents;&lt;br /&gt;
    glDrawScene;&lt;br /&gt;
  end;&lt;br /&gt;
end.&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Done ist in unserem Fall ein einfacher Integer-Wert. Sobald dieser im eigentlichen Programm auf -1 gesetzt wird, wird die Schleife nicht ein weiteres Mal durchlaufen. Wir sehen auch, dass in der Schleife zwei Funktionen aufgerufen werden. Dies bietet sich an um die Übersicht zu wahren!Natürlich können wir auch noch weitere Aufgaben in der Schleife verarbeiten!&lt;br /&gt;
GlDrawSzene ist die Funktion die die OpenGL-Befehle beinhaltet und sich um die grafische Ausgabe kümmert. Dieser Teil ist identisch mit der entsprechenden Funktion unter der WinAPI oder der VCL. Würden wir allerdings die Schleife immer nur mit dieser Funktion durchlaufen, so würde der Benutzer keine Interaktion mit dem Programm durchführen können, da immer nur die Schleife durchlaufen wird. Die Anwendung würde hängen. Es ist daher notwendig, dass diese auf Ereignisse des Betriebsystems oder des Anwenders reagiert.&lt;br /&gt;
&lt;br /&gt;
===Event-Handling===&lt;br /&gt;
&lt;br /&gt;
Um zu begreifen wie genau eine solche Ereignis-Reaktion aussieht, schauen wir uns die Funktion {{INLINE_CODE|glHandleEvents}} etwas genauer an:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;procedure glHandleEvents;&lt;br /&gt;
var event       : TSDL_Event;&lt;br /&gt;
begin;&lt;br /&gt;
    // Verarbeiten der Events&lt;br /&gt;
    while ( SDL_PollEvent( @event ) = 1 ) do&lt;br /&gt;
    begin&lt;br /&gt;
      case event.type_ of&lt;br /&gt;
&lt;br /&gt;
        // Beenden der Applikation&lt;br /&gt;
        SDL_QUITEV :&lt;br /&gt;
        begin&lt;br /&gt;
          Done := -1;&lt;br /&gt;
        end;&lt;br /&gt;
&lt;br /&gt;
        // Taste wurde gedrückt&lt;br /&gt;
        SDL_KEYDOWN :&lt;br /&gt;
        begin&lt;br /&gt;
          glHandleKeyPress( @event.key.keysym );&lt;br /&gt;
        end;&lt;br /&gt;
&lt;br /&gt;
        // Fenster-Größe hat sich verändert&lt;br /&gt;
        SDL_VIDEORESIZE :&lt;br /&gt;
        begin&lt;br /&gt;
          glResizeWindow( event.resize.w, event.resize.h );&lt;br /&gt;
        end;&lt;br /&gt;
      end;//case&lt;br /&gt;
    end;//while&lt;br /&gt;
end;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit {{INLINE_CODE|SDL_PollEvent}} fragen wir bei SDL an, ob Nachrichten für unsere Anwendung vorliegen. Ist dies der Fall, so durchlaufen wir alle diese Nachrichten nacheinander. Um die Art der Nachricht zu ermitteln übergeben wir eine Struktur vom Typ {{INLINE_CODE|TSDL_EVENT}} und nutzen {{INLINE_CODE|.type_}} um zu ermitteln, um was für eine Nachricht es sich handelt. In unserem Fall reagieren wir auf 3 Ereignisse.&lt;br /&gt;
&lt;br /&gt;
===Sein oder nicht sein...===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;  // Beenden der Applikation&lt;br /&gt;
        SDL_QUITEV :&lt;br /&gt;
        begin&lt;br /&gt;
          Done := -1;&lt;br /&gt;
        end;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Liegt ein Ereignis vom Typ {{INLINE_CODE|SDL_QUITEV}} vor, so hat die Anwendung die Meldung erhalten dass sie beendet werden soll. Der wahrscheinlichste Grund dafür wird sein, dass der Anwender auf das X im Fenstertitel geklickt hat. Es liegt nun an uns dafür zu sorgen, dass diesem Wunsch auch nachgekommen wird. Wie wir uns erinnern wird das Programm verlassen, sobald {{INLINE_CODE|done := -1;}} gesetzt ist. Also machen wir dies auch. Nachdem alle Nachrichten abgearbeitet sind und der Main-Loop betreten wird, ist die Bedingung für einen Programmabbruch erfüllt. &lt;br /&gt;
&lt;br /&gt;
===Tastatur-Handling===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;   // Taste wurde gedrückt&lt;br /&gt;
        SDL_KEYDOWN :&lt;br /&gt;
        begin&lt;br /&gt;
          glHandleKeyPress( @event.key.keysym );&lt;br /&gt;
        end;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieses Event wird dann ausgelöst, wenn eine Taste gedrückt wurde. Wir übergeben in diesem Fall das Ereignis weiter an eine Funktion, die sich dann mit der Auswertung beschäftigt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;procedure glHandleKeyPress( keysym : PSDL_keysym );&lt;br /&gt;
begin;&lt;br /&gt;
  case keysym.sym of&lt;br /&gt;
    SDLK_ESCAPE : done := -1;&lt;br /&gt;
  end;&lt;br /&gt;
end;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hierzu überprüfen wir, welche Taste gedrückt wurde. In diesem Fall handelt es sich um die Escape-Taste und sie soll beim Betätigen das Programm beenden. Würden wir abfragen wollen, ob die F1-Taste gedrückt wurde, so könnten wir dies mit {{INLINE_CODE|SDLK_F1}} machen. Weitesgehend entsprechen die SDLK-Konsten den VK-Konstanten der WINAPI. Wer über eine neuere Delphi-Version verfügt, kann ja auch mal STRG drücken und dann mit der linken Maustaste auf {{INLINE_CODE|SDLK_ESCAPE}} klicken. Delphi wird dann an die Stelle springen, wo die Konstanten definiert sind. Dort werdet ihr sicherlich auch recht schnell die anderen Tasten finden, die ihr sucht.  &lt;br /&gt;
&lt;br /&gt;
===Eine Frage der wahren Größe===&lt;br /&gt;
&lt;br /&gt;
{{INLINE_CODE|SDL_VIDEORESIZE}} wird dann ausgelöst, wenn sich die Zeichenfläche in Ihrer Größe verändert hat. Zum Beispiel, weil der Anwender gerade das Fenster größer gezogen hat.&lt;br /&gt;
&lt;br /&gt;
Durch diese Veränderung der Zeichenfläche werden unsere Projektions-Matrix und der Viewport ungültig. Wir müssen diese also neu anpassen. Wer sich gut erinnern kann, wird nun verstehen warum ich anfangs gesagt habe, dass wir uns die {{INLINE_CODE|glResizeWindow}}-Funktion so schreiben, dass wir sie in einem Event wieder verwenden können.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;glResizeWindow( event.resize.w, event.resize.h );&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir übergeben einfach die vom Event übergebene neue Größe unseres Fensters und passen die Projektions-Matrix neu an. Schon kann der Anwender nach belieben die Größe des Render-Fensters verändern. So einfach ist das...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==OpenGL? Überall gleich!==&lt;br /&gt;
&lt;br /&gt;
Wie ich bereits erwähnt habe, ist in der Funktion glDrawScene nichts wirklich Neues anzufinden, was nicht in einer API oder VCL-Lösung anzutreffen wäre. Schließlich ist OpenGL eben dafür geschaffen worden so portabel wie möglich zu sein:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;procedure glDrawScene;&lt;br /&gt;
begin&lt;br /&gt;
  // Screen- und Tiefenbuffer bereinigen&lt;br /&gt;
  glClear( GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT );&lt;br /&gt;
&lt;br /&gt;
  glLoadIdentity;&lt;br /&gt;
  glTranslatef( -1.5, 0.0, -6.0 );&lt;br /&gt;
&lt;br /&gt;
  // Zeichne Dreieck&lt;br /&gt;
  glBegin( GL_TRIANGLES );&lt;br /&gt;
    glVertex3f( 0.0, 1.0, 0.0 );&lt;br /&gt;
    glVertex3f( 1.0, -1.0, 0.0 );&lt;br /&gt;
    glVertex3f( -1.0, -1.0, 0.0 );&lt;br /&gt;
  glEnd;&lt;br /&gt;
&lt;br /&gt;
  glTranslatef( 3.0, 0.0, 0.0 );&lt;br /&gt;
&lt;br /&gt;
  // Zeichne ein Quadrat&lt;br /&gt;
  glBegin( GL_QUADS );&lt;br /&gt;
    glVertex3f( -1.0, 1.0, 0.0 );&lt;br /&gt;
    glVertex3f( 1.0, 1.0, 0.0 );&lt;br /&gt;
    glVertex3f( 1.0, -1.0, 0.0 );&lt;br /&gt;
    glVertex3f( -1.0, -1.0, 0.0 );&lt;br /&gt;
  glEnd;&lt;br /&gt;
&lt;br /&gt;
  // Buffer-Wechseln ==&amp;gt; Anzeigen&lt;br /&gt;
  SDL_GL_SwapBuffers;&lt;br /&gt;
end;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Einzig und alleine die letzte Zeile ist anders. Hat unter der WINAPI an dieser Stelle noch eine WGL-Funktion ihren Dienst verrichtet, so macht dies hier eine SDL-Funktion. WGL steht unter Linux nicht zur Verfügung und man würde sich ansonsten auf Windows-Systeme festlegen. Technisch geschieht hier aber nichts anders als auch bei der WGL-Funktion nämlich das der hintere Framebuffer nach &amp;quot;vorne&amp;quot; geholt wird, sprich auf dem Bildschirm angezeigt wird. Ohne diesen Aufruf würde OpenGL zwar brav im Hintergrund rendern, aber niemals etwas anzeigen. Das kann auch nicht in unserem Interesse sein, oder? ;) &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Time to say goodbye!==&lt;br /&gt;
&lt;br /&gt;
Ich weiß ja wirklich nicht wie es Euch geht,  aber ich bin immer wenn ich etwas wegschmeiße ziemlich sensibel drauf. Und wenn ich mich hier im Zimmer umsehe, habe ich auch das Gefühl dass ich mich nie wirklich von einem meiner Computer getrennt habe O_o (habe sie halt immer noch alle ziemlich lieb *schnief). Aber es gibt eben Momente bei denen man sich von etwas was man gerne hat auch wieder trennt und wenn es sich nicht mehr vermeiden läßt, sollte man den Moment wenigstens in Ehre halten. &lt;br /&gt;
&lt;br /&gt;
Nein, wer nun erwartet dass ich für euch große unsinkbare Schiffe versenke, wird enttäuscht sein ;) Wir schreiben einfach eine kleine Prozedur die unsere Anwendung umweltfreundlich entsorgt. Diese Prozedur können wir auch dann einsetzen wenn ein Fehler augetreten ist. Sicher könnte man den ganzen Kram auch einfach seinem Schicksal (Windows) überlassen, aber zu einem sauberen Code gehört es sich eben, dass freizugeben was man auch angefordert hat. Ich denke nicht dass der Code wirklich einer näheren Erklärung bedarf!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;//----------------------------------------------------------------------------&lt;br /&gt;
// Terminieren der SDL-Anwendung&lt;br /&gt;
//----------------------------------------------------------------------------&lt;br /&gt;
procedure Quit_App;&lt;br /&gt;
begin;&lt;br /&gt;
  // Freigeben der Ressourcen&lt;br /&gt;
  SDL_QUIT;&lt;br /&gt;
  Halt(0);&lt;br /&gt;
end;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Nachwort==&lt;br /&gt;
&lt;br /&gt;
Das war also bereits unser kleiner Crash-Kurs in die Welt des SDL. Ich hoffe sehrmdass dieses Tutorial verständlich genug war um SDL auch künftig einzusetzen. Es ist meiner Meinung nach wichtig ein Gegengewicht zu Microsoft in der Welt zu haben und der Programmierer soll ja ökonomisch denken. Was spricht also dagegen seine Anwendung so zu gestalten, dass man sie ohne Probleme auch nach Linux übersetzen könnte?Gerade in Verbindung mit OpenGL entfaltet sich ein richtges Dream-Team. Der eine für die Fensterverwaltung, der andere für die grafische Ausgabe. Jeder der bereits (oder immer noch?!) mit GLUT arbeitet, sollte schleunigst davon weg kommen und auf SDL umsteigen. Weil es einfach besser ist ;)&lt;br /&gt;
&lt;br /&gt;
Sicherlich werden nun nicht unbedingt SDL-Anwendungen aus dem Boden schießen, aber der eine oder andere hat ja vielleicht schon ein wenig Blut geleckt und möchte etwas weiter damit herum spielen? Habe ich bereits erwähnt, dass SDL auch etwas für Joysticks, Mäuse und Sound zur Verfügung stellt? Auch ein abstraktes System für mehre Threads ist mit von der Partie, sowie einige Funktionen zum Benutzen von Audio-CDs. Wer Lust auf mehr SDL hat, sollte unbedingt einmal einen Blick in die SDL-Hilfe werfen. Das Projekt ist jung, aber motiviert und hat eine Menge Potenzial!Die Delphi-Portierung wird von den JEDIs selbst unter der Projekt-Führung von Dominique Louis durchgeführt. Wer bereits seit DelphiX-Zeiten in der Szene unterwegs ist wird wissen, was es bedeutet! Gute Arbeit und Sicherheit für die Zukunft ;)&lt;br /&gt;
In diesem Sinne ... viel Spaß ;)&lt;br /&gt;
&lt;br /&gt;
Euer&lt;br /&gt;
:'''Phobeus'''&lt;br /&gt;
&lt;br /&gt;
{{TUTORIAL_NAVIGATION|-|[[Tutorial_SDL_RWops]]}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Tutorial|SDL_Einstieg]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Control_Shader&amp;diff=25696</id>
		<title>Control Shader</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Control_Shader&amp;diff=25696"/>
				<updated>2012-08-10T09:50:00Z</updated>
		
		<summary type="html">&lt;p&gt;End: Die Seite wurde neu angelegt: „Der Tessellation Control Shader (DirectX: Hull Shader) berechnet für eine detailarme Oberfläche (ein grobes Dreiecksnetz) eine Reihe von Kontrollpunkten, mit…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Der Tessellation Control Shader (DirectX: Hull Shader) berechnet für eine detailarme Oberfläche (ein grobes Dreiecksnetz) eine Reihe von Kontrollpunkten, mit deren Hilfe der Tessellator im Anschluss daran die Oberfläche in ein feingliedrigeres Dreiecksnetz unterteilt (Subdivision).&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Evaluation_Shader&amp;diff=25695</id>
		<title>Evaluation Shader</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Evaluation_Shader&amp;diff=25695"/>
				<updated>2012-08-10T09:49:25Z</updated>
		
		<summary type="html">&lt;p&gt;End: Die Seite wurde neu angelegt: „Der Tessellation Evaluation Shader (DirectX: Domain Shader) kommt nach dem Tessellator zum Einsatz und berechnet die Positionen der durch die Tessellation neu …“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Der Tessellation Evaluation Shader (DirectX: Domain Shader) kommt nach dem Tessellator zum Einsatz und berechnet die Positionen der durch die Tessellation neu erzeugten Vertices. Auf diese Weise lassen sich einem 3D-Modell neue Oberflächendetails hinzufügen.&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:Pipeline.png&amp;diff=25694</id>
		<title>Datei:Pipeline.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:Pipeline.png&amp;diff=25694"/>
				<updated>2012-08-10T09:44:55Z</updated>
		
		<summary type="html">&lt;p&gt;End: lud eine neue Version von „Datei:Pipeline.png“ hoch: rote kästen...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Die OpenGL Renderingpipeline.&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:Pipeline.png&amp;diff=25693</id>
		<title>Datei:Pipeline.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:Pipeline.png&amp;diff=25693"/>
				<updated>2012-08-10T09:42:28Z</updated>
		
		<summary type="html">&lt;p&gt;End: lud eine neue Version von „Datei:Pipeline.png“ hoch: Andere Grafik inklusive der Neuerungen von der neuen 4.3 Spezifikation (Compute-Shader, etc.)

aus dem Dokument:

http://www.g-truc.net/doc/OpenGL4.3review.pdf&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Die OpenGL Renderingpipeline.&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Framecounter&amp;diff=25690</id>
		<title>Framecounter</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Framecounter&amp;diff=25690"/>
				<updated>2012-07-18T08:44:40Z</updated>
		
		<summary type="html">&lt;p&gt;End: /* Methode 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Problemstellung==&lt;br /&gt;
Die Bildwiederholrate in Frames per Seconds ist ein in Computerspielen oftmals verwendeter Wert, der eine Aussage über die Leistungsfähigkeit des Computersystems geben kann.&amp;lt;br&amp;gt;&lt;br /&gt;
Wenn man in seinem Programm die [[Frames|Frame]] pro Sekunde (FPS) anzeigen lassen möchte, so gibt es verschiedene Lösungswege.&lt;br /&gt;
&lt;br /&gt;
==Ansätze==&lt;br /&gt;
===Methode 1===&lt;br /&gt;
&lt;br /&gt;
Am Anfang der Renderschleife &amp;quot;misst&amp;quot; man die Zeit und speichert sie in einer Variable.&lt;br /&gt;
Dafür kann man die von Windows bereitgestellten Methoden [http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/gettickcount.asp &amp;quot;Gettickcount&amp;quot;] (gibt in Millisekunden an, wie lange Windows läuft) oder [http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/Windowing/Timers/TimerReference/TimerFunctions/QueryPerformanceCounter.asp &amp;quot;QueryPerformanceCounter&amp;quot;] und unter SDL SDL_GetTicks verwenden.&lt;br /&gt;
Für unsere Zwecke reichen diese Funktionen vollkommen aus.&lt;br /&gt;
&lt;br /&gt;
Als zweiten Schritt rendert man seine Szene, verarbeitet Tastatureingaben usw. &lt;br /&gt;
Also alles, was in der Renderschleife passiert.&lt;br /&gt;
&lt;br /&gt;
Am Ende der Renderschleife stoppt man dann ein zweites Mal die Zeit und erhält nun eine Zeitdifferenz.&lt;br /&gt;
&lt;br /&gt;
Die FPS erhält man nun durch folgende Berechnung:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;FPS = 1000 / Zeitdifferenz;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wobei Zeitdifferenz bei dieser Formel auch in Millisekunden angegeben sein muss.&lt;br /&gt;
&lt;br /&gt;
===Methode 2===&lt;br /&gt;
&lt;br /&gt;
Diese Methode unterscheidet sich kaum von Methode 1. &lt;br /&gt;
Wieder wird:&lt;br /&gt;
#Startzeit bestimmt&lt;br /&gt;
#gerendert&lt;br /&gt;
#Endzeit bestimmt&lt;br /&gt;
#Zeitdifferenz berechnet&lt;br /&gt;
&lt;br /&gt;
Anschließend wird die Zeitdifferenz auf eine Variable TimeCount addiert. Außerdem wird eine Zählvariable für die Frames erhöht.&lt;br /&gt;
&lt;br /&gt;
Wenn die Variable Timecount größer-gleich 1000 wird (es ist mindestens 1 sec vergangen) wird die Frameanzahl berechnet und ausgegeben.&lt;br /&gt;
&lt;br /&gt;
Die Methode 2 hat gegenüber Methode 1 den Vorteil, dass die Frameanzahl nicht nach jedem Frame sondern maximal nur einmal pro Sekunde berechnet wird.&lt;br /&gt;
&lt;br /&gt;
==Implementierung==&lt;br /&gt;
&lt;br /&gt;
Der folgende Code (passend zu Methode 2) wird im OnIdle-Event des OpenGL Formulars ausgeführt. Die Anzahl der Frames wird in der Beschriftung (Caption) des Fensters ausgegeben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt; procedure TForm1.IdleHandler(Sender: TObject; var Done: Boolean);&lt;br /&gt;
 begin&lt;br /&gt;
 //&lt;br /&gt;
   StartTime:= GetTickCount;&lt;br /&gt;
 &lt;br /&gt;
   Render;&lt;br /&gt;
 &lt;br /&gt;
   DrawTime:= GetTickCount - StartTime;&lt;br /&gt;
 &lt;br /&gt;
   inc(TimeCount, DrawTime);&lt;br /&gt;
   inc(FrameCount);&lt;br /&gt;
 &lt;br /&gt;
   if TimeCount &amp;gt;= 1000 then begin&lt;br /&gt;
     Frames:= FrameCount;&lt;br /&gt;
     Dec(TimeCount, 1000);&lt;br /&gt;
     FrameCount:= 0;&lt;br /&gt;
 &lt;br /&gt;
     Caption:= InttoStr(Frames) + 'FPS';&lt;br /&gt;
   end;&lt;br /&gt;
 &lt;br /&gt;
   Done:= false;&lt;br /&gt;
 end;&amp;lt;/source&amp;gt;&lt;br /&gt;
==Siehe auch==&lt;br /&gt;
[[Frameratenbegrenzung]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Anleitung]] [[Kategorie:Technik_oder_Algorithmus]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Framecounter&amp;diff=25689</id>
		<title>Framecounter</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Framecounter&amp;diff=25689"/>
				<updated>2012-07-18T08:44:21Z</updated>
		
		<summary type="html">&lt;p&gt;End: /* Methode 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Problemstellung==&lt;br /&gt;
Die Bildwiederholrate in Frames per Seconds ist ein in Computerspielen oftmals verwendeter Wert, der eine Aussage über die Leistungsfähigkeit des Computersystems geben kann.&amp;lt;br&amp;gt;&lt;br /&gt;
Wenn man in seinem Programm die [[Frames|Frame]] pro Sekunde (FPS) anzeigen lassen möchte, so gibt es verschiedene Lösungswege.&lt;br /&gt;
&lt;br /&gt;
==Ansätze==&lt;br /&gt;
===Methode 1===&lt;br /&gt;
&lt;br /&gt;
Am Anfang der Renderschleife &amp;quot;misst&amp;quot; man die Zeit und speichert sie in einer Variable.&lt;br /&gt;
Dafür kann man die von Windows bereitgestellten Methoden [http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/gettickcount.asp &amp;quot;Gettickcount&amp;quot;] (gibt in Millisekunden an, wie lange Windows läuft) oder [http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/Windowing/Timers/TimerReference/TimerFunctions/QueryPerformanceCounter.asp &amp;quot;QueryPerformanceCounter&amp;quot;] und unter SDL SDL_GetTicks verwenden.&lt;br /&gt;
Für unsere Zwecke reichen diese beiden Funktionen vollkommen aus.&lt;br /&gt;
&lt;br /&gt;
Als zweiten Schritt rendert man seine Szene, verarbeitet Tastatureingaben usw. &lt;br /&gt;
Also alles, was in der Renderschleife passiert.&lt;br /&gt;
&lt;br /&gt;
Am Ende der Renderschleife stoppt man dann ein zweites Mal die Zeit und erhält nun eine Zeitdifferenz.&lt;br /&gt;
&lt;br /&gt;
Die FPS erhält man nun durch folgende Berechnung:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;FPS = 1000 / Zeitdifferenz;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wobei Zeitdifferenz bei dieser Formel auch in Millisekunden angegeben sein muss.&lt;br /&gt;
&lt;br /&gt;
===Methode 2===&lt;br /&gt;
&lt;br /&gt;
Diese Methode unterscheidet sich kaum von Methode 1. &lt;br /&gt;
Wieder wird:&lt;br /&gt;
#Startzeit bestimmt&lt;br /&gt;
#gerendert&lt;br /&gt;
#Endzeit bestimmt&lt;br /&gt;
#Zeitdifferenz berechnet&lt;br /&gt;
&lt;br /&gt;
Anschließend wird die Zeitdifferenz auf eine Variable TimeCount addiert. Außerdem wird eine Zählvariable für die Frames erhöht.&lt;br /&gt;
&lt;br /&gt;
Wenn die Variable Timecount größer-gleich 1000 wird (es ist mindestens 1 sec vergangen) wird die Frameanzahl berechnet und ausgegeben.&lt;br /&gt;
&lt;br /&gt;
Die Methode 2 hat gegenüber Methode 1 den Vorteil, dass die Frameanzahl nicht nach jedem Frame sondern maximal nur einmal pro Sekunde berechnet wird.&lt;br /&gt;
&lt;br /&gt;
==Implementierung==&lt;br /&gt;
&lt;br /&gt;
Der folgende Code (passend zu Methode 2) wird im OnIdle-Event des OpenGL Formulars ausgeführt. Die Anzahl der Frames wird in der Beschriftung (Caption) des Fensters ausgegeben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt; procedure TForm1.IdleHandler(Sender: TObject; var Done: Boolean);&lt;br /&gt;
 begin&lt;br /&gt;
 //&lt;br /&gt;
   StartTime:= GetTickCount;&lt;br /&gt;
 &lt;br /&gt;
   Render;&lt;br /&gt;
 &lt;br /&gt;
   DrawTime:= GetTickCount - StartTime;&lt;br /&gt;
 &lt;br /&gt;
   inc(TimeCount, DrawTime);&lt;br /&gt;
   inc(FrameCount);&lt;br /&gt;
 &lt;br /&gt;
   if TimeCount &amp;gt;= 1000 then begin&lt;br /&gt;
     Frames:= FrameCount;&lt;br /&gt;
     Dec(TimeCount, 1000);&lt;br /&gt;
     FrameCount:= 0;&lt;br /&gt;
 &lt;br /&gt;
     Caption:= InttoStr(Frames) + 'FPS';&lt;br /&gt;
   end;&lt;br /&gt;
 &lt;br /&gt;
   Done:= false;&lt;br /&gt;
 end;&amp;lt;/source&amp;gt;&lt;br /&gt;
==Siehe auch==&lt;br /&gt;
[[Frameratenbegrenzung]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Anleitung]] [[Kategorie:Technik_oder_Algorithmus]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Frameratenbegrenzung&amp;diff=25688</id>
		<title>Frameratenbegrenzung</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Frameratenbegrenzung&amp;diff=25688"/>
				<updated>2012-07-18T08:42:56Z</updated>
		
		<summary type="html">&lt;p&gt;End: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Problemstellung==&lt;br /&gt;
Bei vielen 3D-Anwendungen erfolgt die Bildausgabe so schnell hintereinander, wie die Hardware dies ermöglicht. Das bedeutet aber auch, dass die Auslastung des Computersystems auf 100% ansteigt. Das wiederum benötigt jede Menge Strom.&amp;lt;br&amp;gt;Unser Auge wiederum nimmt eine Bewegung ab ca. 20 Bildern pro Sekunde als flüssig wahr - es bringt also nicht sehr viel, wenn unsere Anwendung mit mehr als 1000FPS läuft - wir bekommen davon sowieso nichts mit, außer niedriger Akkulaufzeit und hoher Stromrechnung. Die Lösung für dieses Problem ist eine Frameratenbegrenzung, die die Bildwiederholrate auf einen gewissen Wert limitiert und unsere Anwendung in der Zeit, in der nichts getan werden muss schlafen legt.&lt;br /&gt;
&lt;br /&gt;
==Ansatz==&lt;br /&gt;
&lt;br /&gt;
===Die naive Lösung===&lt;br /&gt;
Die einfachste Realisierung der Frameratenbegrenzung ist ein einfaches Hinzufügen der &amp;quot;Sleep&amp;quot; Anweisung in die Hauptschleife. Gehen wir von Sleep(5) aus, so haben wir eine Maximale Framerate von 200FPS. Diese Lösung ist jedoch etwas suboptimal. Gehen wir davon aus, dass das Zeichnen der Inhalte an sich schon 5 Millisekunden dauert, so haben wir nur noch eine Framerate von 100FPS. Auf einem älterem Rechner könnte diese Berechnung auch länger dauern und die erreichte Framerate sich daher noch mehr von unserem anvisierten Wert entfernen.&lt;br /&gt;
&lt;br /&gt;
===Die intelligente Lösung===&lt;br /&gt;
Schlauer ist es, von der Zeit, die unser Programm pausiert, die Dauer des Rendervorgangs abzuziehen. Dazu ist es nötig, die Zeit, die zwischen zwei Frames vergeht zu messen. Um die Schlafenszeit nicht in dieser Messung zu haben, müssen wir uns diese natürlich merken und vorher abziehen. Mit diesem Ansatz passt sich die CPU-Auslastung an die Leistung des Systems an: Auf einem High-End PC wird sie automatisch niedriger als auf einem Rechner aus dem letztem Jahrhundert - so gehört es sich schließlich auch.&lt;br /&gt;
&lt;br /&gt;
==Implementierung==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
var&lt;br /&gt;
  FMaximumFrameRate: double;&lt;br /&gt;
  FLastSleep: double = 0;&lt;br /&gt;
&lt;br /&gt;
procedure LimitFrameRate(atd: double); //&amp;quot;atd&amp;quot; ist die Zeitdifferenz zwischen zwei Frames - inklusive der &amp;quot;Sleeptime&amp;quot;&lt;br /&gt;
var&lt;br /&gt;
  sleeptime: Double;&lt;br /&gt;
begin&lt;br /&gt;
  sleeptime := 1000 / FMaximumFrameRate - (atd - FLastSleep);&lt;br /&gt;
  if sleeptime &amp;gt; 0 then&lt;br /&gt;
  begin&lt;br /&gt;
    //statt sleep kann unter SDL auch SDL_Delay verwendet werden &lt;br /&gt;
    Sleep(trunc(sleeptime));&lt;br /&gt;
    FLastSleep := sleeptime;&lt;br /&gt;
  end else&lt;br /&gt;
    FLastSleep := 0;&lt;br /&gt;
end;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Siehe auch==&lt;br /&gt;
[[Framecounter]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Anleitung]] [[Kategorie:Technik_oder_Algorithmus]]&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Kuchenst%C3%BCck&amp;diff=25248</id>
		<title>Kuchenstück</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Kuchenst%C3%BCck&amp;diff=25248"/>
				<updated>2011-07-11T09:27:32Z</updated>
		
		<summary type="html">&lt;p&gt;End: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Kuchenstück ==&lt;br /&gt;
&lt;br /&gt;
Ein Kuchen- oder Käsestück ist generell ein Stück eines flachen, breiten Zylinders. D. h. man weiß, wenn man in Mathe (9. Klasse) in Geometrie aufgepasst hat, dass der Kuchen/der Käse durch folgende Variablen beschrieben  ist:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
! r&lt;br /&gt;
| der Radius der beiden Kreise, welche die Grund- und Deckflächen des Kuchens bilden.&lt;br /&gt;
|-&lt;br /&gt;
! h&lt;br /&gt;
| die Höhe des Kuchens.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nun brauchen wir aber Vertices, um den Kreis in [[OpenGL]] darstellen zu können. Wir brauchen also zwei Kreise. Die Vertices eines Kreises lassen sich einfach berechnen:&lt;br /&gt;
&lt;br /&gt;
:X = r * cos α&lt;br /&gt;
&lt;br /&gt;
:Y = r * sin α&lt;br /&gt;
&lt;br /&gt;
Nun einmal in einer for-Schleife den ganzen Kreis in einer beliebigen Auflösung durchgehen (zum Beispiel bis 360° durchlaufen lassen) und in ein dynamisches Array of TPoint abspeichern. Beim Kuchenstück lässt man die Schleife nur bis α durchlaufen. Um den Wert für α auszurechen, kann man folgende Formeln nutzen:&lt;br /&gt;
&lt;br /&gt;
:α = U&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt; / U * 360°&lt;br /&gt;
&lt;br /&gt;
:U = 2 * &amp;amp;pi; * r&lt;br /&gt;
&lt;br /&gt;
(U&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt; ist der Umfang des Kreissektors des Kuchenstückes.)&lt;br /&gt;
&lt;br /&gt;
Damit hättet ihr jetzt das nötige Wissen für ein Kuchenstück. Beim Käse kommen zwar normalerweise noch Löcher rein, aber das ist Stoff für etwas anderes. Bis dahin nutzt ihr am besten einfach Texturen mit Löchern darauf.&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Kuchenst%C3%BCck&amp;diff=25243</id>
		<title>Kuchenstück</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Kuchenst%C3%BCck&amp;diff=25243"/>
				<updated>2011-07-11T08:44:37Z</updated>
		
		<summary type="html">&lt;p&gt;End: Die Seite wurde neu angelegt: „== Kuchenstück ==  Ein Kuchen- oder Käsestück ist generell ein Stück eines flachen, breiten Zylinders. D. h. weiß man, wenn man in Mathe (9. Klasse) in Geome…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Kuchenstück ==&lt;br /&gt;
&lt;br /&gt;
Ein Kuchen- oder Käsestück ist generell ein Stück eines flachen, breiten Zylinders. D. h. weiß man, wenn man in Mathe (9. Klasse) in Geometrie aufgepasst hat, dass der Kuchen/der Käse durch folgende Variablen beschrieben  ist:&lt;br /&gt;
&lt;br /&gt;
r der Radius der beiden Kreise, die die Grundfläche des Kuchens bilden.&lt;br /&gt;
&lt;br /&gt;
h die Höhe des Kuchens.&lt;br /&gt;
&lt;br /&gt;
Nun brauchen wir aber Vertices, um den Kreis in OpenGL darstellen zu können. Wir brauchen also zwei Kreise. Die Vertices eines Kreises lassen sich einfach berechnen:&lt;br /&gt;
&lt;br /&gt;
Y = sin α * r&lt;br /&gt;
&lt;br /&gt;
X = cos α * r&lt;br /&gt;
&lt;br /&gt;
Nun einmal in einer for-Schleife den ganzen Kreis in einer beliebigen Auflösung durchgehen (zum Beispiel bis 360° durchlaufen lassen) und in ein dynamisches Array of TPoint abspeichern. Und beim Kuchenstück halt nur bis α durchlaufen lassen. Um α rauszukriegen gibt es übrigens diese Formeln:&lt;br /&gt;
&lt;br /&gt;
α = Ui / U * 360°&lt;br /&gt;
&lt;br /&gt;
U = 2 * pi * r&lt;br /&gt;
&lt;br /&gt;
Ui ist der Umfang des Kreis-Sektors des Kuchenstückes.&lt;br /&gt;
Damit hättet ihr jetzt das nötige Wissen für ein Kuchenstück. Beim Käse kommen zwar normalerweise noch Löcher rein, aber das ist Stoff für was anderes...bis dahin nutzt ihr am besten einfach Texturen mit Löchern drauf. ^^&lt;/div&gt;</summary>
		<author><name>End</name></author>	</entry>

	</feed>